From ab45d4358d36683ed9a939e596226949a56bb4dd Mon Sep 17 00:00:00 2001 From: regneq Date: Fri, 4 Jul 2025 09:53:45 -0700 Subject: [PATCH 001/194] [Bug Fix] Add a missing Froglok starting area for Titanium Startzone. (#4962) * Add a missing Froglok starting area for Titanium Startzone. * fix formatting. * add a missing break. --- common/eq_constants.h | 3 ++- world/worlddb.cpp | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/common/eq_constants.h b/common/eq_constants.h index f67618bac3..b577b9fb34 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -988,7 +988,8 @@ enum StartZoneIndex { Felwithe, Akanon, Cabilis, - SharVahl + SharVahl, + RatheMtn }; enum FVNoDropFlagRule diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 9ca580c40d..9501670fd0 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -732,6 +732,12 @@ void WorldDatabase::SetTitaniumDefaultStartZone(PlayerProfile_Struct* in_pp, Cha in_pp->binds[0].zone_id = Zones::SHARVAHL; // sharvahl break; } + case StartZoneIndex::RatheMtn: + { + in_pp->zone_id = Zones::RATHEMTN; // rathemtn + in_pp->binds[0].zone_id = Zones::RATHEMTN; // rathemtn + break; + } } } } From 323a0c0b27ce19586305347d4bf37a3f2d2ae990 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Thu, 10 Jul 2025 15:08:08 -0400 Subject: [PATCH 002/194] [Feature] Zone Scripting (#4908) * [Feature] Add Zone Scripting Capabilities * Push * Update zone.cpp * Fix crashes * Lua * Add other events, finish Lua * Add EVENT_ENTER_ZONE * Final * Push * Push * [Feature] Add Zone Scripting Capabilities * Push * Update zone.cpp * Fix crashes * Add EVENT_ENTER_ZONE * Remove duplicates * Update embparser.cpp --- zone/attack.cpp | 19 ++ zone/client_packet.cpp | 21 ++ zone/corpse.cpp | 15 + zone/embparser.cpp | 551 ++++++++++++++++++------------- zone/embparser.h | 91 ++--- zone/entity.cpp | 5 + zone/lua_parser.cpp | 263 ++++++++++++++- zone/lua_parser.h | 45 ++- zone/lua_parser_events.cpp | 289 ++++++++++++++++ zone/lua_parser_events.h | 137 ++++++++ zone/lua_zone.cpp | 77 +++++ zone/lua_zone.h | 11 + zone/npc.cpp | 5 + zone/object.cpp | 24 ++ zone/perl_zone.cpp | 66 ++++ zone/quest_interface.h | 45 +++ zone/quest_parser_collection.cpp | 225 +++++++++++++ zone/quest_parser_collection.h | 39 +++ zone/questmgr.cpp | 114 ++++--- zone/questmgr.h | 25 +- zone/zone.cpp | 258 +++++++++++++++ zone/zone.h | 30 ++ 22 files changed, 2012 insertions(+), 343 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index e28eac7cc1..9c6581a324 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3039,6 +3039,25 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy DispatchZoneControllerEvent(EVENT_DEATH_ZONE, owner_or_self, export_string, 0, &args); } + if (parse->ZoneHasQuestSub(EVENT_DEATH_ZONE)) { + const auto& export_string = fmt::format( + "{} {} {} {} {} {} {} {} {}", + killer_mob ? killer_mob->GetID() : 0, + damage, + spell, + static_cast(attack_skill), + entity_id, + m_combat_record.GetStartTime(), + m_combat_record.GetEndTime(), + m_combat_record.GetDamageReceived(), + m_combat_record.GetHealingReceived() + ); + + std::vector args = { corpse, this, owner_or_self }; + + parse->EventZone(EVENT_DEATH_ZONE, zone, export_string, 0, &args); + } + return true; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a69a6b96eb..a62131b71c 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -795,6 +795,11 @@ void Client::CompleteConnect() parse->EventPlayer(EVENT_ENTER_ZONE, this, "", 0); } + if (parse->ZoneHasQuestSub(EVENT_ENTER_ZONE)) { + std::vector args = { this }; + parse->EventZone(EVENT_ENTER_ZONE, zone, "", 0, &args); + } + DeleteEntityVariable(SEE_BUFFS_FLAG); // the way that the client deals with positions during the initial spawn struct @@ -4709,6 +4714,12 @@ void Client::Handle_OP_ClickDoor(const EQApplicationPacket *app) quest_return = parse->EventPlayer(EVENT_CLICK_DOOR, this, std::to_string(cd->doorid), 0, &args); } + if (parse->ZoneHasQuestSub(EVENT_CLICK_DOOR)) { + std::vector args = { currentdoor, this }; + + quest_return = parse->EventZone(EVENT_CLICK_DOOR, zone, std::to_string(cd->doorid), 0, &args); + } + if (quest_return == 0) { currentdoor->HandleClick(this, 0); } @@ -4741,6 +4752,11 @@ void Client::Handle_OP_ClickObject(const EQApplicationPacket *app) parse->EventPlayer(EVENT_CLICK_OBJECT, this, std::to_string(click_object->drop_id), GetID(), &args); } + if (parse->ZoneHasQuestSub(EVENT_CLICK_OBJECT)) { + std::vector args = { object, this }; + parse->EventZone(EVENT_CLICK_OBJECT, zone, std::to_string(click_object->drop_id), GetID(), &args); + } + if (IsDevToolsEnabled()) { SetObjectToolEntityId(entity->GetID()); ObjectManipulation::CommandHeader(this); @@ -12042,6 +12058,11 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app) parse->EventPlayer(EVENT_POPUP_RESPONSE, this, std::to_string(popup_response->popupid), 0); } + if (parse->ZoneHasQuestSub(EVENT_POPUP_RESPONSE)) { + std::vector args = { this }; + parse->EventZone(EVENT_POPUP_RESPONSE, zone, std::to_string(popup_response->popupid), 0, &args); + } + auto t = GetTarget(); if (t) { parse->EventBotMercNPC(EVENT_POPUP_RESPONSE, t, this, [&]() { return std::to_string(popup_response->popupid); }); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index f0b04a8f54..9bd13d63b8 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1586,6 +1586,21 @@ void Corpse::LootCorpseItem(Client *c, const EQApplicationPacket *app) } } + if (parse->ZoneHasQuestSub(EVENT_LOOT_ZONE)) { + const auto &export_string = fmt::format( + "{} {} {} {}", + inst->GetItem()->ID, + inst->GetCharges(), + EntityList::RemoveNumbers(corpse_name), + GetID() + ); + + std::vector args = {inst, this, c}; + if (parse->EventZone(EVENT_LOOT_ZONE, zone, export_string, 0, &args) != 0) { + prevent_loot = true; + } + } + if (inst && PlayerEventLogs::Instance()->IsEventEnabled(PlayerEvent::LOOT_ITEM) && !IsPlayerCorpse()) { auto e = PlayerEvent::LootItemEvent{ .item_id = inst->GetItem()->ID, diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 16a662482c..903a4821f0 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -222,6 +222,8 @@ PerlembParser::PerlembParser() : perl(nullptr) global_bot_quest_status_ = questUnloaded; merc_quest_status_ = questUnloaded; global_merc_quest_status_ = questUnloaded; + zone_quest_status_ = questUnloaded; + global_zone_quest_status_ = questUnloaded; } PerlembParser::~PerlembParser() @@ -265,6 +267,8 @@ void PerlembParser::ReloadQuests() global_bot_quest_status_ = questUnloaded; merc_quest_status_ = questUnloaded; global_merc_quest_status_ = questUnloaded; + zone_quest_status_ = questUnloaded; + global_zone_quest_status_ = questUnloaded; item_quest_status_.clear(); spell_quest_status_.clear(); @@ -278,6 +282,7 @@ int PerlembParser::EventCommon( EQ::ItemInstance* inst, const SPDat_Spell_Struct* spell, Mob* mob, + Zone* zone, uint32 extra_data, bool is_global, std::vector* extra_pointers @@ -287,52 +292,22 @@ int PerlembParser::EventCommon( return 0; } - bool is_player_quest = false; - bool is_global_player_quest = false; - bool is_global_npc_quest = false; - bool is_bot_quest = false; - bool is_global_bot_quest = false; - bool is_merc_quest = false; - bool is_global_merc_quest = false; - bool is_item_quest = false; - bool is_spell_quest = false; - - std::string package_name; - - GetQuestTypes( - is_player_quest, - is_global_player_quest, - is_bot_quest, - is_global_bot_quest, - is_merc_quest, - is_global_merc_quest, - is_global_npc_quest, - is_item_quest, - is_spell_quest, + QuestType quest_type = GetQuestTypes( event_id, npc_mob, inst, mob, + zone, is_global ); - GetQuestPackageName( - is_player_quest, - is_global_player_quest, - is_bot_quest, - is_global_bot_quest, - is_merc_quest, - is_global_merc_quest, - is_global_npc_quest, - is_item_quest, - is_spell_quest, - package_name, + std::string package_name = GetQuestPackageName( + quest_type, event_id, object_id, data, npc_mob, - inst, - is_global + inst ); const std::string& sub_name = QuestEventSubroutines[event_id]; @@ -348,15 +323,7 @@ int PerlembParser::EventCommon( /* Check for QGlobal export event enable */ if (parse->perl_event_export_settings[event_id].qglobals) { ExportQGlobals( - is_player_quest, - is_global_player_quest, - is_bot_quest, - is_global_bot_quest, - is_merc_quest, - is_global_merc_quest, - is_global_npc_quest, - is_item_quest, - is_spell_quest, + quest_type, package_name, npc_mob, mob, @@ -367,15 +334,7 @@ int PerlembParser::EventCommon( /* Check for Mob export event enable */ if (parse->perl_event_export_settings[event_id].mob) { ExportMobVariables( - is_player_quest, - is_global_player_quest, - is_bot_quest, - is_global_bot_quest, - is_merc_quest, - is_global_merc_quest, - is_global_npc_quest, - is_item_quest, - is_spell_quest, + quest_type, package_name, mob, npc_mob @@ -397,19 +356,24 @@ int PerlembParser::EventCommon( ExportEventVariables(package_name, event_id, object_id, data, npc_mob, inst, mob, extra_data, extra_pointers); } - if (is_player_quest || is_global_player_quest) { - return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, mob, mob, nullptr, nullptr); - } else if (is_bot_quest || is_global_bot_quest || is_merc_quest || is_global_merc_quest) { - return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, npc_mob, mob, nullptr, nullptr); - } else if (is_item_quest) { - return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, mob, mob, inst, nullptr); - } else if (is_spell_quest) { + if (quest_type == QuestType::Player || quest_type == QuestType::PlayerGlobal) { + return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, mob, mob, nullptr, nullptr, nullptr); + } else if ( + quest_type == QuestType::Bot || + quest_type == QuestType::BotGlobal || + quest_type == QuestType::Merc || + quest_type == QuestType::MercGlobal + ) { + return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, npc_mob, mob, nullptr, nullptr, nullptr); + } else if (quest_type == QuestType::Item || quest_type == QuestType::ItemGlobal) { + return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, mob, mob, inst, nullptr, nullptr); + } else if (quest_type == QuestType::Spell || quest_type == QuestType::SpellGlobal) { if (mob) { - return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, mob, mob, nullptr, spell); + return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, mob, mob, nullptr, spell, nullptr); } else { - return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, npc_mob, mob, nullptr, spell); + return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, npc_mob, mob, nullptr, spell, nullptr); } - } else { + } else if (quest_type == QuestType::NPC || quest_type == QuestType::NPCGlobal) { return SendCommands( package_name.c_str(), QuestEventSubroutines[event_id], @@ -417,8 +381,20 @@ int PerlembParser::EventCommon( npc_mob, mob, nullptr, + nullptr, nullptr ); + } else if (quest_type == QuestType::Zone || quest_type == QuestType::ZoneGlobal) { + return SendCommands( + package_name.c_str(), + QuestEventSubroutines[event_id], + 0, + nullptr, + nullptr, + nullptr, + nullptr, + zone + ); } } @@ -439,6 +415,7 @@ int PerlembParser::EventNPC( nullptr, nullptr, mob, + nullptr, extra_data, false, extra_pointers @@ -462,6 +439,7 @@ int PerlembParser::EventGlobalNPC( nullptr, nullptr, mob, + nullptr, extra_data, true, extra_pointers @@ -484,6 +462,7 @@ int PerlembParser::EventPlayer( nullptr, nullptr, client, + nullptr, extra_data, false, extra_pointers @@ -506,6 +485,7 @@ int PerlembParser::EventGlobalPlayer( nullptr, nullptr, client, + nullptr, extra_data, true, extra_pointers @@ -534,6 +514,7 @@ int PerlembParser::EventItem( inst, nullptr, client, + nullptr, extra_data, false, extra_pointers @@ -558,6 +539,7 @@ int PerlembParser::EventSpell( nullptr, &spells[spell_id], client, + nullptr, extra_data, false, extra_pointers @@ -1006,7 +988,8 @@ int PerlembParser::SendCommands( Mob* other, Mob* mob, EQ::ItemInstance* inst, - const SPDat_Spell_Struct* spell + const SPDat_Spell_Struct* spell, + Zone* zone ) { if (!perl) { @@ -1014,12 +997,20 @@ int PerlembParser::SendCommands( } int ret_value = 0; + RunningQuest q; if (mob && mob->IsClient()) { - quest_manager.StartQuest(other, mob->CastToClient(), inst, spell); - } else { - quest_manager.StartQuest(other); + q.owner = other; + q.initiator = mob->CastToClient(); + q.questitem = inst; + q.questspell = spell; + } + + if (zone) { + q.zone = zone; } + quest_manager.StartQuest(q); + try { perl->eval(fmt::format("package {};", prefix).c_str()); @@ -1033,7 +1024,8 @@ int PerlembParser::SendCommands( "merc", "npc", "questitem", - "spell" + "spell", + "zone" }; for (const auto& suffix : suffixes) { @@ -1058,21 +1050,23 @@ int PerlembParser::SendCommands( sv_setsv(client, _empty_sv); } - if (other->IsBot()) { - Bot* b = quest_manager.GetBot(); - buf = fmt::format("{}::bot", prefix); - SV* bot = get_sv(buf.c_str(), true); - sv_setref_pv(bot, "Bot", b); - } else if (other->IsMerc()) { - Merc* m = quest_manager.GetMerc(); - buf = fmt::format("{}::merc", prefix); - SV* merc = get_sv(buf.c_str(), true); - sv_setref_pv(merc, "Merc", m); - } else if (other->IsNPC()) { - NPC* n = quest_manager.GetNPC(); - buf = fmt::format("{}::npc", prefix); - SV* npc = get_sv(buf.c_str(), true); - sv_setref_pv(npc, "NPC", n); + if (other) { + if (other->IsBot()) { + Bot* b = quest_manager.GetBot(); + buf = fmt::format("{}::bot", prefix); + SV* bot = get_sv(buf.c_str(), true); + sv_setref_pv(bot, "Bot", b); + } else if (other->IsMerc()) { + Merc* m = quest_manager.GetMerc(); + buf = fmt::format("{}::merc", prefix); + SV* merc = get_sv(buf.c_str(), true); + sv_setref_pv(merc, "Merc", m); + } else if (other->IsNPC()) { + NPC* n = quest_manager.GetNPC(); + buf = fmt::format("{}::npc", prefix); + SV* npc = get_sv(buf.c_str(), true); + sv_setref_pv(npc, "NPC", n); + } } //only export QuestItem if it's an inst quest @@ -1110,7 +1104,8 @@ int PerlembParser::SendCommands( "merc", "npc", "questitem", - "spell" + "spell", + "zone" }; for (const auto& suffix : suffixes) { @@ -1192,20 +1187,12 @@ void PerlembParser::MapFunctions() #endif // EMBPERL_XS_CLASSES } -void PerlembParser::GetQuestTypes( - bool& is_player_quest, - bool& is_global_player_quest, - bool& is_bot_quest, - bool& is_global_bot_quest, - bool& is_merc_quest, - bool& is_global_merc_quest, - bool& is_global_npc_quest, - bool& is_item_quest, - bool& is_spell_quest, +QuestType PerlembParser::GetQuestTypes( QuestEventID event_id, Mob* npc_mob, EQ::ItemInstance* inst, Mob* mob, + Zone* zone, bool is_global ) { @@ -1219,100 +1206,74 @@ void PerlembParser::GetQuestTypes( event_id == EVENT_SPELL_FADE || event_id == EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE ) { - is_spell_quest = true; + return is_global ? QuestType::SpellGlobal : QuestType::Spell; } else { if (npc_mob) { if (!inst) { - if (is_global) { - if (npc_mob->IsBot()) { - is_global_bot_quest = true; - } else if (npc_mob->IsMerc()) { - is_global_merc_quest = true; - } - } else { - if (npc_mob->IsBot()) { - is_bot_quest = true; - } else if (npc_mob->IsMerc()) { - is_merc_quest = true; - } + if (npc_mob->IsBot()) { + return is_global ? QuestType::BotGlobal : QuestType::Bot; + } else if (npc_mob->IsMerc()) { + return is_global ? QuestType::MercGlobal : QuestType::Merc; + } else if (npc_mob->IsNPC()) { + return is_global ? QuestType::NPCGlobal : QuestType::NPC; } } else { - is_item_quest = true; + return is_global ? QuestType::ItemGlobal : QuestType::Item; } } else if (!npc_mob && mob) { if (!inst) { - if (is_global) { - if (mob->IsClient()) { - is_global_player_quest = true; - } - } else { - if (mob->IsClient()) { - is_player_quest = true; - } + if (mob->IsClient()) { + return is_global ? QuestType::PlayerGlobal : QuestType::Player; } } else { - is_item_quest = true; + return is_global ? QuestType::ItemGlobal : QuestType::Item; } + } else if (zone) { + return is_global ? QuestType::ZoneGlobal : QuestType::Zone; } } } -void PerlembParser::GetQuestPackageName( - bool& is_player_quest, - bool& is_global_player_quest, - bool& is_bot_quest, - bool& is_global_bot_quest, - bool& is_merc_quest, - bool& is_global_merc_quest, - bool& is_global_npc_quest, - bool& is_item_quest, - bool& is_spell_quest, - std::string& package_name, +std::string PerlembParser::GetQuestPackageName( + QuestType quest_type, QuestEventID event_id, uint32 object_id, const char* data, Mob* npc_mob, - EQ::ItemInstance* inst, - bool is_global + EQ::ItemInstance* inst ) { - if ( - !is_player_quest && - !is_global_player_quest && - !is_bot_quest && - !is_global_bot_quest && - !is_merc_quest && - !is_global_merc_quest && - !is_item_quest && - !is_spell_quest - ) { - if (is_global) { - is_global_npc_quest = true; - package_name = "qst_global_npc"; - } else { - package_name = fmt::format("qst_npc_{}", npc_mob->GetNPCTypeID()); - } - } else if (is_item_quest) { + if (quest_type == QuestType::NPC) { + return fmt::format("qst_npc_{}", npc_mob->GetNPCTypeID()); + } else if (quest_type == QuestType::NPCGlobal) { + return "qst_global_npc"; + } else if (quest_type == QuestType::Item || quest_type == QuestType::ItemGlobal) { if (!inst) { - return; - } - - package_name = fmt::format("qst_item_{}", inst->GetID()); - } else if (is_player_quest) { - package_name = "qst_player"; - } else if (is_global_player_quest) { - package_name = "qst_global_player"; - } else if (is_bot_quest) { - package_name = "qst_bot"; - } else if (is_global_bot_quest) { - package_name = "qst_global_bot"; - } else if (is_merc_quest) { - package_name = "qst_merc"; - } else if (is_global_merc_quest) { - package_name = "qst_global_merc"; - } else { - package_name = fmt::format("qst_spell_{}", object_id); - } + return ""; + } + + return fmt::format("qst_item_{}", inst->GetID()); + } else if (quest_type == QuestType::Player) { + return "qst_player"; + } else if (quest_type == QuestType::PlayerGlobal) { + return "qst_global_player"; + } else if (quest_type == QuestType::Bot) { + return "qst_bot"; + } else if (quest_type == QuestType::BotGlobal) { + return "qst_global_bot"; + } else if (quest_type == QuestType::Merc) { + return "qst_merc"; + } else if (quest_type == QuestType::MercGlobal) { + return "qst_global_merc"; + } else if (quest_type == QuestType::Spell || quest_type == QuestType::SpellGlobal) { + return fmt::format("qst_spell_{}", object_id); + } else if (quest_type == QuestType::Zone) { + return "qst_zone"; + } else if (quest_type == QuestType::ZoneGlobal) { + return "qst_global_zone"; + } + + return ""; } void PerlembParser::ExportCharID(const std::string& package_name, int& char_id, Mob* npc_mob, Mob* mob) @@ -1331,15 +1292,7 @@ void PerlembParser::ExportCharID(const std::string& package_name, int& char_id, } void PerlembParser::ExportQGlobals( - bool is_player_quest, - bool is_global_player_quest, - bool is_bot_quest, - bool is_global_bot_quest, - bool is_merc_quest, - bool is_global_merc_quest, - bool is_global_npc_quest, - bool is_item_quest, - bool is_spell_quest, + QuestType quest_type, std::string& package_name, Mob* npc_mob, Mob* mob, @@ -1347,16 +1300,7 @@ void PerlembParser::ExportQGlobals( ) { //NPC quest - if ( - !is_player_quest && - !is_global_player_quest && - !is_bot_quest && - !is_global_bot_quest && - !is_merc_quest && - !is_global_merc_quest && - !is_item_quest && - !is_spell_quest - ) { + if (quest_type == QuestType::NPC || quest_type == QuestType::NPCGlobal) { //only export for npcs that are global enabled. if (npc_mob && npc_mob->GetQglobal()) { std::map globhash; @@ -1485,15 +1429,7 @@ void PerlembParser::ExportQGlobals( } void PerlembParser::ExportMobVariables( - bool is_player_quest, - bool is_global_player_quest, - bool is_bot_quest, - bool is_global_bot_quest, - bool is_merc_quest, - bool is_global_merc_quest, - bool is_global_npc_quest, - bool is_item_quest, - bool is_spell_quest, + QuestType quest_type, std::string& package_name, Mob* mob, Mob* npc_mob @@ -1511,15 +1447,7 @@ void PerlembParser::ExportMobVariables( ExportVar(package_name.c_str(), "bot_owner_char_id", mob->CastToBot()->GetBotOwnerCharacterID()); } - if ( - !is_player_quest && - !is_global_player_quest && - !is_bot_quest && - !is_global_bot_quest && - !is_merc_quest && - !is_global_merc_quest && - !is_item_quest - ) { + if (quest_type == QuestType::NPC || quest_type == QuestType::NPCGlobal) { if (mob && mob->IsClient() && npc_mob && npc_mob->IsNPC()) { Client* c = mob->CastToClient(); @@ -1543,16 +1471,7 @@ void PerlembParser::ExportMobVariables( ExportVar(package_name.c_str(), "userid", mob->GetID()); } - if ( - !is_player_quest && - !is_global_player_quest && - !is_bot_quest && - !is_global_bot_quest && - !is_merc_quest && - !is_global_merc_quest && - !is_item_quest && - !is_spell_quest - ) { + if (quest_type == QuestType::NPC || quest_type == QuestType::NPCGlobal) { if (npc_mob->IsNPC()) { ExportVar(package_name.c_str(), "mname", npc_mob->GetName()); ExportVar(package_name.c_str(), "mobid", npc_mob->GetID()); @@ -1758,10 +1677,14 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "doorid", data); ExportVar(package_name.c_str(), "version", zone->GetInstanceVersion()); - if (extra_pointers && extra_pointers->size() == 1) { + if (extra_pointers && extra_pointers->size() >= 1) { ExportVar(package_name.c_str(), "door", "Doors", std::any_cast(extra_pointers->at(0))); } + if (extra_pointers && extra_pointers->size() == 2) { + ExportVar(package_name.c_str(), "player", "Client", std::any_cast(extra_pointers->at(1))); + } + break; } @@ -1782,10 +1705,14 @@ void PerlembParser::ExportEventVariables( ); } - if (extra_pointers && extra_pointers->size() == 2) { + if (extra_pointers && extra_pointers->size() >= 2) { ExportVar(package_name.c_str(), "corpse", "Corpse", std::any_cast(extra_pointers->at(1))); } + if (extra_pointers && extra_pointers->size() == 3) { + ExportVar(package_name.c_str(), "player", "Client", std::any_cast(extra_pointers->at(2))); + } + break; } @@ -1852,7 +1779,7 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "picked_up_id", data); ExportVar(package_name.c_str(), "picked_up_entity_id", extra_data); - if (extra_pointers && extra_pointers->size() == 1) { + if (extra_pointers && extra_pointers->size() >= 1) { ExportVar( package_name.c_str(), "item", @@ -1861,6 +1788,10 @@ void PerlembParser::ExportEventVariables( ); } + if (extra_pointers && extra_pointers->size() == 2) { + ExportVar(package_name.c_str(), "player", "Client", std::any_cast(extra_pointers->at(1))); + } + break; } @@ -1873,6 +1804,11 @@ void PerlembParser::ExportEventVariables( case EVENT_POPUP_RESPONSE: { ExportVar(package_name.c_str(), "popupid", data); + + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "player", "Client", std::any_cast(extra_pointers->at(0))); + } + break; } @@ -2036,10 +1972,14 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "objectid", data); ExportVar(package_name.c_str(), "clicker_id", extra_data); - if (extra_pointers && extra_pointers->size() == 1) { + if (extra_pointers && extra_pointers->size() >= 1) { ExportVar(package_name.c_str(), "object", "Object", std::any_cast(extra_pointers->at(0))); } + if (extra_pointers && extra_pointers->size() == 2) { + ExportVar(package_name.c_str(), "player", "Client", std::any_cast(extra_pointers->at(1))); + } + break; } @@ -2115,6 +2055,13 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "killed_npc_id", !killed->IsMerc() && killed->IsNPC() ? killed->GetNPCTypeID() : 0); } } + + if (extra_pointers && extra_pointers->size() == 3) { + Mob* killer = std::any_cast(extra_pointers->at(2)); + if (killer) { + ExportVar(package_name.c_str(), "killer", "Mob", killer); + } + } break; } @@ -2142,10 +2089,21 @@ void PerlembParser::ExportEventVariables( } case EVENT_SPAWN_ZONE: { - ExportVar(package_name.c_str(), "spawned_entity_id", mob->GetID()); - ExportVar(package_name.c_str(), "spawned_bot_id", mob->IsBot() ? mob->CastToBot()->GetBotID() : 0); - ExportVar(package_name.c_str(), "spawned_npc_id", mob->IsNPC() ? mob->GetNPCTypeID() : 0); - ExportVar(package_name.c_str(), "spawned", "Mob", mob); + if (mob) { + ExportVar(package_name.c_str(), "spawned", "Mob", mob); + ExportVar(package_name.c_str(), "spawned_bot_id", mob->IsBot() ? mob->CastToBot()->GetBotID() : 0); + ExportVar(package_name.c_str(), "spawned_entity_id", mob->GetID()); + ExportVar(package_name.c_str(), "spawned_npc_id", mob->IsNPC() ? mob->GetNPCTypeID() : 0); + } + + if (extra_pointers && extra_pointers->size() == 1) { + NPC* spawn_npc = std::any_cast(extra_pointers->at(0)); + ExportVar(package_name.c_str(), "spawned", "NPC", spawn_npc); + ExportVar(package_name.c_str(), "spawned_bot_id", spawn_npc->IsBot() ? spawn_npc->CastToBot()->GetBotID() : 0); + ExportVar(package_name.c_str(), "spawned_entity_id", spawn_npc->GetID()); + ExportVar(package_name.c_str(), "spawned_npc_id", spawn_npc->IsNPC() ? spawn_npc->GetNPCTypeID() : 0); + } + break; } @@ -2386,6 +2344,7 @@ void PerlembParser::ExportEventVariables( } case EVENT_DESPAWN: { + ExportVar(package_name.c_str(), "despawned", "Mob", npc_mob); ExportVar(package_name.c_str(), "despawned_entity_id", npc_mob->GetID()); ExportVar(package_name.c_str(), "despawned_bot_id", npc_mob->IsBot() ? npc_mob->CastToBot()->GetBotID() : 0); ExportVar(package_name.c_str(), "despawned_merc_id", npc_mob->IsMerc() ? npc_mob->CastToMerc()->GetMercenaryID() : 0); @@ -2394,9 +2353,21 @@ void PerlembParser::ExportEventVariables( } case EVENT_DESPAWN_ZONE: { - ExportVar(package_name.c_str(), "despawned_entity_id", mob->GetID()); - ExportVar(package_name.c_str(), "despawned_bot_id", mob->IsBot() ? mob->CastToBot()->GetBotID() : 0); - ExportVar(package_name.c_str(), "despawned_npc_id", mob->IsNPC() ? mob->GetNPCTypeID() : 0); + if (mob) { + ExportVar(package_name.c_str(), "despawned", "Mob", mob); + ExportVar(package_name.c_str(), "despawned_bot_id", mob->IsBot() ? mob->CastToBot()->GetBotID() : 0); + ExportVar(package_name.c_str(), "despawned_entity_id", mob->GetID()); + ExportVar(package_name.c_str(), "despawned_npc_id", mob->IsNPC() ? mob->GetNPCTypeID() : 0); + } + + if (extra_pointers && extra_pointers->size() == 1) { + NPC* spawn_npc = std::any_cast(extra_pointers->at(0)); + ExportVar(package_name.c_str(), "despawned", "NPC", spawn_npc); + ExportVar(package_name.c_str(), "despawned_bot_id", spawn_npc->IsBot() ? spawn_npc->CastToBot()->GetBotID() : 0); + ExportVar(package_name.c_str(), "despawned_entity_id", spawn_npc->GetID()); + ExportVar(package_name.c_str(), "despawned_npc_id", spawn_npc->IsNPC() ? spawn_npc->GetNPCTypeID() : 0); + } + break; } @@ -2551,6 +2522,14 @@ void PerlembParser::ExportEventVariables( break; } + case EVENT_ENTER_ZONE: { + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "player", "Client", std::any_cast(extra_pointers->at(0))); + } + + break; + } + default: { break; } @@ -2648,6 +2627,7 @@ int PerlembParser::EventBot( nullptr, nullptr, mob, + nullptr, extra_data, false, extra_pointers @@ -2671,6 +2651,7 @@ int PerlembParser::EventGlobalBot( nullptr, nullptr, mob, + nullptr, extra_data, true, extra_pointers @@ -2768,6 +2749,7 @@ int PerlembParser::EventMerc( nullptr, nullptr, mob, + nullptr, extra_data, false, extra_pointers @@ -2791,6 +2773,127 @@ int PerlembParser::EventGlobalMerc( nullptr, nullptr, mob, + nullptr, + extra_data, + true, + extra_pointers + ); +} + +void PerlembParser::LoadZoneScript(std::string filename) +{ + if (!perl || zone_quest_status_ != questUnloaded) { + return; + } + + try { + perl->eval_file("qst_zone", filename.c_str()); + } catch (std::string e) { + AddError( + fmt::format( + "Error Compiling Zone Quest File [{}] Error [{}]", + filename, + e + ) + ); + + zone_quest_status_ = questFailedToLoad; + return; + } + + zone_quest_status_ = questLoaded; +} + +void PerlembParser::LoadGlobalZoneScript(std::string filename) +{ + if (!perl || global_zone_quest_status_ != questUnloaded) { + return; + } + + try { + perl->eval_file("qst_global_zone", filename.c_str()); + } catch (std::string e) { + AddError( + fmt::format( + "Error Compiling Global Zone Quest File [{}] Error [{}]", + filename, + e + ) + ); + + global_zone_quest_status_ = questFailedToLoad; + return; + } + + global_zone_quest_status_ = questLoaded; +} + +bool PerlembParser::ZoneHasQuestSub(QuestEventID event_id) +{ + if ( + !perl || + zone_quest_status_ != questLoaded || + event_id >= _LargestEventID + ) { + return false; + } + + return perl->SubExists("qst_zone", QuestEventSubroutines[event_id]); +} + +bool PerlembParser::GlobalZoneHasQuestSub(QuestEventID event_id) +{ + if ( + !perl || + global_zone_quest_status_ != questLoaded || + event_id >= _LargestEventID + ) { + return false; + } + + return perl->SubExists("qst_global_zone", QuestEventSubroutines[event_id]); +} + +int PerlembParser::EventZone( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers +) +{ + return EventCommon( + event_id, + 0, + data.c_str(), + nullptr, + nullptr, + nullptr, + nullptr, + zone, + extra_data, + false, + extra_pointers + ); +} + +int PerlembParser::EventGlobalZone( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers +) +{ + return EventCommon( + event_id, + 0, + data.c_str(), + nullptr, + nullptr, + nullptr, + nullptr, + zone, extra_data, true, extra_pointers diff --git a/zone/embparser.h b/zone/embparser.h index dd4ffe8d89..5817ce15b5 100644 --- a/zone/embparser.h +++ b/zone/embparser.h @@ -41,6 +41,23 @@ typedef enum { questFailedToLoad } PerlQuestStatus; +enum class QuestType { + Bot, + BotGlobal, + Item, + ItemGlobal, + Merc, + MercGlobal, + NPC, + NPCGlobal, + Player, + PlayerGlobal, + Spell, + SpellGlobal, + Zone, + ZoneGlobal +}; + class PerlembParser : public QuestInterface { public: PerlembParser(); @@ -136,6 +153,22 @@ class PerlembParser : public QuestInterface { std::vector* extra_pointers ); + virtual int EventZone( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers + ); + + virtual int EventGlobalZone( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers + ); + virtual bool HasQuestSub(uint32 npc_id, QuestEventID event_id); virtual bool HasGlobalQuestSub(QuestEventID event_id); virtual bool PlayerHasQuestSub(QuestEventID event_id); @@ -146,6 +179,8 @@ class PerlembParser : public QuestInterface { virtual bool GlobalBotHasQuestSub(QuestEventID event_id); virtual bool MercHasQuestSub(QuestEventID event_id); virtual bool GlobalMercHasQuestSub(QuestEventID event_id); + virtual bool ZoneHasQuestSub(QuestEventID event_id); + virtual bool GlobalZoneHasQuestSub(QuestEventID event_id); virtual void LoadNPCScript(std::string filename, int npc_id); virtual void LoadGlobalNPCScript(std::string filename); @@ -157,6 +192,8 @@ class PerlembParser : public QuestInterface { virtual void LoadGlobalBotScript(std::string filename); virtual void LoadMercScript(std::string filename); virtual void LoadGlobalMercScript(std::string filename); + virtual void LoadZoneScript(std::string filename); + virtual void LoadGlobalZoneScript(std::string filename); virtual void AddVar(std::string name, std::string val); virtual std::string GetVar(std::string name); @@ -182,6 +219,7 @@ class PerlembParser : public QuestInterface { EQ::ItemInstance* inst, const SPDat_Spell_Struct* spell, Mob* mob, + Zone* zone, uint32 extra_data, bool is_global, std::vector* extra_pointers @@ -194,59 +232,34 @@ class PerlembParser : public QuestInterface { Mob* other, Mob* mob, EQ::ItemInstance* inst, - const SPDat_Spell_Struct* spell + const SPDat_Spell_Struct* spell, + Zone* zone ); void MapFunctions(); - void GetQuestTypes( - bool& is_player_quest, - bool& is_global_player_quest, - bool& is_bot_quest, - bool& is_global_bot_quest, - bool& is_merc_quest, - bool& is_global_merc_quest, - bool& is_global_npc_quest, - bool& is_item_quest, - bool& is_spell_quest, + QuestType GetQuestTypes( QuestEventID event, Mob* npc_mob, EQ::ItemInstance* inst, Mob* mob, + Zone* zone, bool is_global ); - void GetQuestPackageName( - bool& is_player_quest, - bool& is_global_player_quest, - bool& is_bot_quest, - bool& is_global_bot_quest, - bool& is_merc_quest, - bool& is_global_merc_quest, - bool& is_global_npc_quest, - bool& is_item_quest, - bool& is_spell_quest, - std::string& package_name, + std::string GetQuestPackageName( + QuestType quest_type, QuestEventID event, uint32 object_id, const char* data, Mob* npc_mob, - EQ::ItemInstance* inst, - bool is_global + EQ::ItemInstance* inst ); void ExportCharID(const std::string& package_name, int& char_id, Mob* npc_mob, Mob* mob); void ExportQGlobals( - bool is_player_quest, - bool is_global_player_quest, - bool is_bot_quest, - bool is_global_bot_quest, - bool is_merc_quest, - bool is_global_merc_quest, - bool is_global_npc_quest, - bool is_item_quest, - bool is_spell_quest, + QuestType quest_type, std::string& package_name, Mob* npc_mob, Mob* mob, @@ -254,15 +267,7 @@ class PerlembParser : public QuestInterface { ); void ExportMobVariables( - bool is_player_quest, - bool is_global_player_quest, - bool is_bot_quest, - bool is_global_bot_quest, - bool is_merc_quest, - bool is_global_merc_quest, - bool is_global_npc_quest, - bool is_item_quest, - bool is_spell_quest, + QuestType quest_type, std::string& package_name, Mob* mob, Mob* npc_mob @@ -295,6 +300,8 @@ class PerlembParser : public QuestInterface { PerlQuestStatus global_bot_quest_status_; PerlQuestStatus merc_quest_status_; PerlQuestStatus global_merc_quest_status_; + PerlQuestStatus zone_quest_status_; + PerlQuestStatus global_zone_quest_status_; SV* _empty_sv; diff --git a/zone/entity.cpp b/zone/entity.cpp index b878950017..0b94fc7ace 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -743,6 +743,11 @@ void EntityList::AddNPC(NPC *npc, bool send_spawn_packet, bool dont_queue) npc->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, npc, "", 0, nullptr); } + if (parse->ZoneHasQuestSub(EVENT_SPAWN_ZONE)) { + std::vector args = { npc }; + parse->EventZone(EVENT_SPAWN_ZONE, zone, "", 0, &args); + } + if (zone->HasMap() && zone->HasWaterMap()) { npc->SetSpawnedInWater(false); if (zone->watermap->InLiquid(npc->GetPosition())) { diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index d44fb2bfaa..0f8dded50e 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -219,6 +219,7 @@ LuaParser::LuaParser() { SpellArgumentDispatch[i] = handle_spell_null; EncounterArgumentDispatch[i] = handle_encounter_null; BotArgumentDispatch[i] = handle_bot_null; + ZoneArgumentDispatch[i] = handle_zone_null; } NPCArgumentDispatch[EVENT_SAY] = handle_npc_event_say; @@ -409,6 +410,23 @@ LuaParser::LuaParser() { BotArgumentDispatch[EVENT_ENTITY_VARIABLE_SET] = handle_bot_entity_variable; BotArgumentDispatch[EVENT_ENTITY_VARIABLE_UPDATE] = handle_bot_entity_variable; BotArgumentDispatch[EVENT_SPELL_BLOCKED] = handle_bot_spell_blocked; + + ZoneArgumentDispatch[EVENT_CLICK_DOOR] = handle_zone_click_door; + ZoneArgumentDispatch[EVENT_CLICK_OBJECT] = handle_zone_click_object; + ZoneArgumentDispatch[EVENT_DEATH_ZONE] = handle_zone_death; + ZoneArgumentDispatch[EVENT_DESPAWN_ZONE] = handle_zone_despawn; + ZoneArgumentDispatch[EVENT_ENTER_ZONE] = handle_zone_enter; + ZoneArgumentDispatch[EVENT_LOOT_ZONE] = handle_zone_loot; + ZoneArgumentDispatch[EVENT_PAYLOAD] = handle_zone_payload; + ZoneArgumentDispatch[EVENT_PLAYER_PICKUP] = handle_zone_pickup; + ZoneArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_zone_popup; + ZoneArgumentDispatch[EVENT_SIGNAL] = handle_zone_signal; + ZoneArgumentDispatch[EVENT_SPAWN_ZONE] = handle_zone_spawn; + ZoneArgumentDispatch[EVENT_TIMER] = handle_zone_timer; + ZoneArgumentDispatch[EVENT_TIMER_PAUSE] = handle_zone_timer_pause_resume_start; + ZoneArgumentDispatch[EVENT_TIMER_RESUME] = handle_zone_timer_pause_resume_start; + ZoneArgumentDispatch[EVENT_TIMER_START] = handle_zone_timer_pause_resume_start; + ZoneArgumentDispatch[EVENT_TIMER_STOP] = handle_zone_timer_stop; #endif L = nullptr; @@ -489,7 +507,13 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M arg_function(this, L, npc, init, data, extra_data, extra_pointers); Client *c = (init && init->IsClient()) ? init->CastToClient() : nullptr; - quest_manager.StartQuest(npc, c); + RunningQuest q; + + q.owner = npc; + q.initiator = c; + + quest_manager.StartQuest(q); + if(lua_pcall(L, 1, 1, start + 1)) { std::string error = lua_tostring(L, -1); AddError(error); @@ -582,7 +606,13 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client * auto arg_function = PlayerArgumentDispatch[evt]; arg_function(this, L, client, data, extra_data, extra_pointers); - quest_manager.StartQuest(client, client); + RunningQuest q; + + q.owner = client; + q.initiator = client; + + quest_manager.StartQuest(q); + if(lua_pcall(L, 1, 1, start + 1)) { std::string error = lua_tostring(L, -1); AddError(error); @@ -666,7 +696,14 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl auto arg_function = ItemArgumentDispatch[evt]; arg_function(this, L, client, item, mob, data, extra_data, extra_pointers); - quest_manager.StartQuest(client, client, item); + RunningQuest q; + + q.owner = client; + q.initiator = client; + q.questitem = item; + + quest_manager.StartQuest(q); + if(lua_pcall(L, 1, 1, start + 1)) { std::string error = lua_tostring(L, -1); AddError(error); @@ -748,7 +785,14 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, Mob* mob, auto arg_function = SpellArgumentDispatch[evt]; arg_function(this, L, mob, client, spell_id, data, extra_data, extra_pointers); - quest_manager.StartQuest(mob, client, nullptr, const_cast(&spells[spell_id])); + RunningQuest q; + + q.owner = client; + q.initiator = client; + q.questspell = const_cast(&spells[spell_id]); + + quest_manager.StartQuest(q); + if(lua_pcall(L, 1, 1, start + 1)) { std::string error = lua_tostring(L, -1); AddError(error); @@ -814,7 +858,13 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std:: auto arg_function = EncounterArgumentDispatch[evt]; arg_function(this, L, enc, data, extra_data, extra_pointers); - quest_manager.StartQuest(enc, nullptr, nullptr, nullptr, encounter_name); + RunningQuest q; + + q.owner = enc; + q.encounter = encounter_name; + + quest_manager.StartQuest(q); + if(lua_pcall(L, 1, 1, start + 1)) { std::string error = lua_tostring(L, -1); AddError(error); @@ -1757,7 +1807,13 @@ int LuaParser::_EventBot( arg_function(this, L, bot, init, data, extra_data, extra_pointers); auto* c = (init && init->IsClient()) ? init->CastToClient() : nullptr; - quest_manager.StartQuest(bot, c); + RunningQuest q; + + q.owner = bot; + q.initiator = c; + + quest_manager.StartQuest(q); + if(lua_pcall(L, 1, 1, start + 1)) { std::string error = lua_tostring(L, -1); AddError(error); @@ -1936,7 +1992,13 @@ int LuaParser::_EventMerc( arg_function(this, L, merc, init, data, extra_data, extra_pointers); auto* c = (init && init->IsClient()) ? init->CastToClient() : nullptr; - quest_manager.StartQuest(merc, c); + RunningQuest q; + + q.owner = merc; + q.initiator = c; + + quest_manager.StartQuest(q); + if(lua_pcall(L, 1, 1, start + 1)) { std::string error = lua_tostring(L, -1); AddError(error); @@ -2039,3 +2101,190 @@ void LuaParser::LoadMercScript(std::string filename) { void LuaParser::LoadGlobalMercScript(std::string filename) { LoadScript(filename, "global_merc"); } + +int LuaParser::EventZone( + QuestEventID evt, + Zone *zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + evt = ConvertLuaEvent(evt); + if (evt >= _LargestEventID) { + return 0; + } + + if (!zone) { + return 0; + } + + if (!ZoneHasQuestSub(evt)) { + return 0; + } + + return _EventZone("zone", evt, zone, data, extra_data, extra_pointers); +} + +int LuaParser::EventGlobalZone( + QuestEventID evt, + Zone *zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + evt = ConvertLuaEvent(evt); + if (evt >= _LargestEventID) { + return 0; + } + + if (!zone) { + return 0; + } + + if (!GlobalZoneHasQuestSub(evt)) { + return 0; + } + + return _EventZone("global_zone", evt, zone, data, extra_data, extra_pointers); +} + +int LuaParser::_EventZone( + std::string package_name, + QuestEventID evt, + Zone *zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers, + luabind::adl::object *l_func +) { + const char *sub_name = LuaEvents[evt]; + int start = lua_gettop(L); + + try { + int npop = 2; + PushErrorHandler(L); + if(l_func != nullptr) { + l_func->push(L); + } else { + lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str()); + lua_getfield(L, -1, sub_name); + npop = 3; + } + + lua_createtable(L, 0, 0); + //push self + Lua_Zone l_zone(zone); + luabind::adl::object l_zone_o = luabind::adl::object(L, l_zone); + l_zone_o.push(L); + lua_setfield(L, -2, "self"); + + auto arg_function = ZoneArgumentDispatch[evt]; + arg_function(this, L, zone, data, extra_data, extra_pointers); + + RunningQuest q; + + q.zone = zone; + + quest_manager.StartQuest(q); + + if(lua_pcall(L, 1, 1, start + 1)) { + std::string error = lua_tostring(L, -1); + AddError(error); + quest_manager.EndQuest(); + lua_pop(L, npop); + return 0; + } + quest_manager.EndQuest(); + + if(lua_isnumber(L, -1)) { + int ret = static_cast(lua_tointeger(L, -1)); + lua_pop(L, npop); + return ret; + } + + lua_pop(L, npop); + } catch(std::exception &ex) { + AddError( + fmt::format( + "Lua Exception | [{}] for Zone [{}] in [{}]: {}", + sub_name, + zone->GetShortName(), + package_name, + ex.what() + ) + ); + + //Restore our stack to the best of our ability + int end = lua_gettop(L); + int n = end - start; + if(n > 0) { + lua_pop(L, n); + } + } + + return 0; +} + +int LuaParser::DispatchEventZone( + QuestEventID evt, + Zone *zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + evt = ConvertLuaEvent(evt); + if (evt >= _LargestEventID) { + return 0; + } + + std::string package_name = "zone"; + + auto iter = lua_encounter_events_registered.find(package_name); + if (iter == lua_encounter_events_registered.end()) { + return 0; + } + + int ret = 0; + auto riter = iter->second.begin(); + while (riter != iter->second.end()) { + if (riter->event_id == evt) { + package_name = fmt::format("encounter_{}", riter->encounter_name); + int i = _EventZone(package_name, evt, zone, data, extra_data, extra_pointers, &riter->lua_reference); + if (i != 0) { + ret = i; + } + } + + ++riter; + } + + return ret; +} + +bool LuaParser::ZoneHasQuestSub(QuestEventID evt) { + evt = ConvertLuaEvent(evt); + if (evt >= _LargestEventID) { + return false; + } + + const char *subname = LuaEvents[evt]; + return HasFunction(subname, "zone"); +} + +bool LuaParser::GlobalZoneHasQuestSub(QuestEventID evt) { + evt = ConvertLuaEvent(evt); + if (evt >= _LargestEventID) { + return false; + } + + const char *subname = LuaEvents[evt]; + return HasFunction(subname, "global_zone"); +} + +void LuaParser::LoadZoneScript(std::string filename) { + LoadScript(filename, "zone"); +} + +void LuaParser::LoadGlobalZoneScript(std::string filename) { + LoadScript(filename, "global_zone"); +} diff --git a/zone/lua_parser.h b/zone/lua_parser.h index fbd50a9845..c1bad7088d 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -125,6 +125,20 @@ class LuaParser : public QuestInterface { uint32 extra_data, std::vector* extra_pointers ); + virtual int EventZone( + QuestEventID evt, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers + ); + virtual int EventGlobalZone( + QuestEventID evt, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers + ); virtual bool HasQuestSub(uint32 npc_id, QuestEventID evt); virtual bool HasGlobalQuestSub(QuestEventID evt); @@ -138,6 +152,8 @@ class LuaParser : public QuestInterface { virtual bool GlobalBotHasQuestSub(QuestEventID evt); virtual bool MercHasQuestSub(QuestEventID evt); virtual bool GlobalMercHasQuestSub(QuestEventID evt); + virtual bool ZoneHasQuestSub(QuestEventID evt); + virtual bool GlobalZoneHasQuestSub(QuestEventID evt); virtual void LoadNPCScript(std::string filename, int npc_id); virtual void LoadGlobalNPCScript(std::string filename); @@ -150,6 +166,8 @@ class LuaParser : public QuestInterface { virtual void LoadGlobalBotScript(std::string filename); virtual void LoadMercScript(std::string filename); virtual void LoadGlobalMercScript(std::string filename); + virtual void LoadZoneScript(std::string filename); + virtual void LoadGlobalZoneScript(std::string filename); virtual void AddVar(std::string name, std::string val); virtual std::string GetVar(std::string name); @@ -207,6 +225,13 @@ class LuaParser : public QuestInterface { uint32 extra_data, std::vector* extra_pointers ); + virtual int DispatchEventZone( + QuestEventID evt, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers + ); static LuaParser* Instance() { static LuaParser inst; @@ -307,6 +332,15 @@ class LuaParser : public QuestInterface { std::vector* extra_pointers, luabind::adl::object* l_func = nullptr ); + int _EventZone( + std::string package_name, + QuestEventID evt, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers, + luabind::adl::object* l_func = nullptr + ); void LoadScript(std::string filename, std::string package_name); void MapFunctions(lua_State *L); @@ -317,12 +351,13 @@ class LuaParser : public QuestInterface { std::vector mods_; lua_State *L; - NPCArgumentHandler NPCArgumentDispatch[_LargestEventID]; - PlayerArgumentHandler PlayerArgumentDispatch[_LargestEventID]; - ItemArgumentHandler ItemArgumentDispatch[_LargestEventID]; - SpellArgumentHandler SpellArgumentDispatch[_LargestEventID]; + NPCArgumentHandler NPCArgumentDispatch[_LargestEventID]; + PlayerArgumentHandler PlayerArgumentDispatch[_LargestEventID]; + ItemArgumentHandler ItemArgumentDispatch[_LargestEventID]; + SpellArgumentHandler SpellArgumentDispatch[_LargestEventID]; EncounterArgumentHandler EncounterArgumentDispatch[_LargestEventID]; - BotArgumentHandler BotArgumentDispatch[_LargestEventID]; + BotArgumentHandler BotArgumentDispatch[_LargestEventID]; + ZoneArgumentHandler ZoneArgumentDispatch[_LargestEventID]; }; #endif diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index 8d2517fe38..153775e785 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -2873,4 +2873,293 @@ void handle_bot_spell_blocked( lua_setfield(L, -2, "cast_spell"); } +// Zone + +void handle_zone_null( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { +} + +void handle_zone_click_door( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Door l_door(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_door_o = luabind::adl::object(L, l_door); + l_door_o.push(L); + lua_setfield(L, -2, "door"); + + Lua_Client l_client(std::any_cast(extra_pointers->at(1))); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_zone_click_object( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Object l_object(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_object_o = luabind::adl::object(L, l_object); + l_object_o.push(L); + lua_setfield(L, -2, "object"); + + Lua_Client l_client(std::any_cast(extra_pointers->at(1))); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_zone_death( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + Lua_Mob l_mob(std::any_cast(extra_pointers->at(2))); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); + + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); + lua_setfield(L, -2, "killer_id"); + + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); + lua_setfield(L, -2, "damage"); + + const uint32 spell_id = Strings::ToUnsignedInt(sep.arg[2]); + if (IsValidSpell(spell_id)) { + Lua_Spell l_spell(&spells[spell_id]); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); + l_spell_o.push(L); + lua_setfield(L, -2, "spell"); + } else { + Lua_Spell l_spell(nullptr); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); + l_spell_o.push(L); + lua_setfield(L, -2, "spell"); + } + + lua_pushinteger(L, Strings::ToInt(sep.arg[3])); + lua_setfield(L, -2, "skill_id"); + + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[4])); + lua_setfield(L, -2, "killed_entity_id"); + + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[5])); + lua_setfield(L, -2, "combat_start_time"); + + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[6])); + lua_setfield(L, -2, "combat_end_time"); + + lua_pushinteger(L, Strings::ToBigInt(sep.arg[7])); + lua_setfield(L, -2, "damage_received"); + + lua_pushinteger(L, Strings::ToBigInt(sep.arg[8])); + lua_setfield(L, -2, "healing_received"); + + if (extra_pointers && extra_pointers->size() >= 1) { + Lua_Corpse l_corpse(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); + l_corpse_o.push(L); + lua_setfield(L, -2, "corpse"); + } + + if (extra_pointers && extra_pointers->size() >= 2) { + Lua_NPC l_npc(std::any_cast(extra_pointers->at(1))); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); + l_npc_o.push(L); + lua_setfield(L, -2, "killed"); + } +} + +void handle_zone_despawn( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_NPC l_npc(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); + l_npc_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_zone_enter( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Client l_client(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_zone_loot( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Client l_client(std::any_cast(extra_pointers->at(2))); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); + + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); + l_item_o.push(L); + lua_setfield(L, -2, "item"); + + Lua_Corpse l_corpse(std::any_cast(extra_pointers->at(1))); + luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); + l_corpse_o.push(L); + lua_setfield(L, -2, "corpse"); +} + +void handle_zone_payload( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); + lua_setfield(L, -2, "payload_id"); + + lua_pushstring(L, sep.argplus[1]); + lua_setfield(L, -2, "payload_value"); +} + +void handle_zone_pickup( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); + l_item_o.push(L); + lua_setfield(L, -2, "item"); + + Lua_Client l_client(std::any_cast(extra_pointers->at(1))); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_zone_popup( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushinteger(L, Strings::ToInt(data)); + lua_setfield(L, -2, "popup_id"); + + Lua_Client l_client(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_zone_signal( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushinteger(L, Strings::ToInt(data)); + lua_setfield(L, -2, "signal"); +} + +void handle_zone_spawn( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_NPC l_npc(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); + l_npc_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_zone_timer( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushstring(L, data.c_str()); + lua_setfield(L, -2, "timer"); +} + +void handle_zone_timer_pause_resume_start( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + lua_pushstring(L, sep.arg[0]); + lua_setfield(L, -2, "timer"); + + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[1])); + lua_setfield(L, -2, "duration"); +} + +void handle_zone_timer_stop( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushstring(L, data.c_str()); + lua_setfield(L, -2, "timer"); +} + #endif diff --git a/zone/lua_parser_events.h b/zone/lua_parser_events.h index 3cb428c58e..0adb7ba997 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -9,6 +9,7 @@ typedef void(*SpellArgumentHandler)(QuestInterface*, lua_State*, Mob*, Client*, typedef void(*EncounterArgumentHandler)(QuestInterface*, lua_State*, Encounter* encounter, std::string, uint32, std::vector*); typedef void(*BotArgumentHandler)(QuestInterface*, lua_State*, Bot*, Mob*, std::string, uint32, std::vector*); typedef void(*MercArgumentHandler)(QuestInterface*, lua_State*, Merc*, Mob*, std::string, uint32, std::vector*); +typedef void(*ZoneArgumentHandler)(QuestInterface*, lua_State*, Zone*, std::string, uint32, std::vector*); // NPC void handle_npc_event_say( @@ -1278,5 +1279,141 @@ void handle_bot_spell_blocked( std::vector *extra_pointers ); +// Zone +void handle_zone_null( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_click_door( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_click_object( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_death( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_despawn( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_enter( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_loot( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_payload( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_pickup( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_popup( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_signal( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_spawn( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_timer( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_timer_pause_resume_start( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_timer_stop( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + #endif #endif diff --git a/zone/lua_zone.cpp b/zone/lua_zone.cpp index 8250296ff2..3907a3ed96 100644 --- a/zone/lua_zone.cpp +++ b/zone/lua_zone.cpp @@ -772,6 +772,72 @@ bool Lua_Zone::VariableExists(const std::string& variable_name) return self->VariableExists(variable_name); } +uint32 Lua_Zone::GetTimerDuration(std::string name) +{ + Lua_Safe_Call_Int(); + return self->GetTimerDuration(name); +} + +uint32 Lua_Zone::GetTimerRemainingTime(std::string name) +{ + Lua_Safe_Call_Int(); + return self->GetTimerRemainingTime(name); +} + +bool Lua_Zone::HasTimer(std::string name) +{ + Lua_Safe_Call_Bool(); + return self->HasTimer(name); +} + +bool Lua_Zone::IsPausedTimer(std::string name) +{ + Lua_Safe_Call_Bool(); + return self->IsPausedTimer(name); +} + +void Lua_Zone::PauseTimer(std::string name) +{ + Lua_Safe_Call_Void(); + self->PauseTimer(name); +} + +void Lua_Zone::ResumeTimer(std::string name) +{ + Lua_Safe_Call_Void(); + self->ResumeTimer(name); +} + +void Lua_Zone::SetTimer(std::string name, uint32 duration) +{ + Lua_Safe_Call_Void(); + self->SetTimer(name, duration); +} + +void Lua_Zone::StopTimer(std::string name) +{ + Lua_Safe_Call_Void(); + self->StopTimer(name); +} + +void Lua_Zone::StopAllTimers() +{ + Lua_Safe_Call_Void(); + self->StopAllTimers(); +} + +void Lua_Zone::SendPayload(int payload_id, std::string payload_value) +{ + Lua_Safe_Call_Void(); + self->SendPayload(payload_id, payload_value); +} + +void Lua_Zone::Signal(int signal_id) +{ + Lua_Safe_Call_Void(); + self->Signal(signal_id); +} + luabind::scope lua_register_zone() { return luabind::class_("Zones") .def(luabind::constructor<>()) @@ -861,6 +927,8 @@ luabind::scope lua_register_zone() { .def("GetSnowDuration", (int(Lua_Zone::*)(uint8))&Lua_Zone::GetSnowDuration) .def("GetTimeType", &Lua_Zone::GetTimeType) .def("GetTimeZone", &Lua_Zone::GetTimeZone) + .def("GetTimerDuration", &Lua_Zone::GetTimerDuration) + .def("GetTimerRemainingTime", &Lua_Zone::GetTimerRemainingTime) .def("GetZoneDescription", &Lua_Zone::GetZoneDescription) .def("GetZoneID", &Lua_Zone::GetZoneID) .def("GetZoneType", &Lua_Zone::GetZoneType) @@ -875,10 +943,12 @@ luabind::scope lua_register_zone() { .def("HasMap", &Lua_Zone::HasMap) .def("HasWaterMap", &Lua_Zone::HasWaterMap) .def("HasWeather", &Lua_Zone::HasWeather) + .def("HasTimer", &Lua_Zone::HasTimer) .def("IsCity", &Lua_Zone::IsCity) .def("IsHotzone", &Lua_Zone::IsHotzone) .def("IsInstancePersistent", &Lua_Zone::IsInstancePersistent) .def("IsIdleWhenEmpty", &Lua_Zone::IsIdleWhenEmpty) + .def("IsPausedTimer", &Lua_Zone::IsPausedTimer) .def("IsPVPZone", &Lua_Zone::IsPVPZone) .def("IsRaining", &Lua_Zone::IsRaining) .def("IsSnowing", &Lua_Zone::IsSnowing) @@ -887,8 +957,11 @@ luabind::scope lua_register_zone() { .def("IsStaticZone", &Lua_Zone::IsStaticZone) .def("IsUCSServerAvailable", &Lua_Zone::IsUCSServerAvailable) .def("IsWaterZone", &Lua_Zone::IsWaterZone) + .def("PauseTimer", &Lua_Zone::PauseTimer) .def("Repop", (void(Lua_Zone::*)(void))&Lua_Zone::Repop) .def("Repop", (void(Lua_Zone::*)(bool))&Lua_Zone::Repop) + .def("ResumeTimer", &Lua_Zone::ResumeTimer) + .def("SendPayload", &Lua_Zone::SendPayload) .def("SetAAEXPModifier", &Lua_Zone::SetAAEXPModifier) .def("SetAAEXPModifierByCharacterID", &Lua_Zone::SetAAEXPModifierByCharacterID) .def("SetBucket", (void(Lua_Zone::*)(const std::string&,const std::string&))&Lua_Zone::SetBucket) @@ -898,8 +971,12 @@ luabind::scope lua_register_zone() { .def("SetInstanceTimer", &Lua_Zone::SetInstanceTimer) .def("SetInstanceTimeRemaining", &Lua_Zone::SetInstanceTimeRemaining) .def("SetIsHotzone", &Lua_Zone::SetIsHotzone) + .def("SetTimer", &Lua_Zone::SetTimer) .def("SetVariable", &Lua_Zone::SetVariable) .def("ShowZoneGlobalLoot", &Lua_Zone::ShowZoneGlobalLoot) + .def("Signal", &Lua_Zone::Signal) + .def("StopTimer", &Lua_Zone::StopTimer) + .def("StopAllTimers", &Lua_Zone::StopAllTimers) .def("VariableExists", &Lua_Zone::VariableExists); } diff --git a/zone/lua_zone.h b/zone/lua_zone.h index 48d297bb60..b1a5390c2a 100644 --- a/zone/lua_zone.h +++ b/zone/lua_zone.h @@ -147,6 +147,17 @@ class Lua_Zone : public Lua_Ptr luabind::object GetVariables(lua_State* L); void SetVariable(const std::string& variable_name, const std::string& variable_value); bool VariableExists(const std::string& variable_name); + uint32 GetTimerDuration(std::string name); + uint32 GetTimerRemainingTime(std::string name); + bool HasTimer(std::string name); + bool IsPausedTimer(std::string name); + void PauseTimer(std::string name); + void ResumeTimer(std::string name); + void SetTimer(std::string name, uint32 duration); + void StopTimer(std::string name); + void StopAllTimers(); + void Signal(int signal_id); + void SendPayload(int payload_id, std::string payload_value); // data buckets void SetBucket(const std::string& bucket_name, const std::string& bucket_value); diff --git a/zone/npc.cpp b/zone/npc.cpp index ade7c8e934..1c70da2c40 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -864,6 +864,11 @@ void NPC::Depop(bool start_spawn_timer) { DispatchZoneControllerEvent(EVENT_DESPAWN_ZONE, this, "", 0, nullptr); } + if (parse->ZoneHasQuestSub(EVENT_DESPAWN_ZONE)) { + std::vector args = { this }; + parse->EventZone(EVENT_DESPAWN_ZONE, zone, "", 0, &args); + } + p_depop = true; if (respawn2) { if (start_spawn_timer) { diff --git a/zone/object.cpp b/zone/object.cpp index eb6daad49e..6da171b23d 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -657,6 +657,30 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) } } + if (parse->ZoneHasQuestSub(EVENT_PLAYER_PICKUP)) { + std::vector args = { m_inst, sender }; + + if (parse->EventZone(EVENT_PLAYER_PICKUP, zone, std::to_string(item->ID), GetID(), &args)) { + auto outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct)); + + memcpy(outapp->pBuffer, click_object, sizeof(ClickObject_Struct)); + + auto co = (ClickObject_Struct*) outapp->pBuffer; + + co->drop_id = 0; + + entity_list.QueueClients(nullptr, outapp, false); + + safe_delete(outapp); + + sender->SetTradeskillObject(nullptr); + + user = nullptr; + + return true; + } + } + // Transfer item to client sender->PutItemInInventory(EQ::invslot::slotCursor, *m_inst, false); sender->SendItemPacket(EQ::invslot::slotCursor, m_inst, ItemPacketTrade); diff --git a/zone/perl_zone.cpp b/zone/perl_zone.cpp index 6cb49f557a..7783c6020b 100644 --- a/zone/perl_zone.cpp +++ b/zone/perl_zone.cpp @@ -598,6 +598,61 @@ bool Perl_Zone_VariableExists(Zone* self, const std::string variable_name) return self->VariableExists(variable_name); } +uint32 Perl_Zone_GetTimerDuration(Zone* self, std::string name) +{ + return self->GetTimerDuration(name); +} + +uint32 Perl_Zone_GetTimerRemainingTime(Zone* self, std::string name) +{ + return self->GetTimerRemainingTime(name); +} + +bool Perl_Zone_HasTimer(Zone* self, std::string name) +{ + return self->HasTimer(name); +} + +bool Perl_Zone_IsPausedTimer(Zone* self, std::string name) +{ + return self->IsPausedTimer(name); +} + +void Perl_Zone_PauseTimer(Zone* self, std::string name) +{ + self->PauseTimer(name); +} + +void Perl_Zone_ResumeTimer(Zone* self, std::string name) +{ + self->ResumeTimer(name); +} + +void Perl_Zone_SetTimer(Zone* self, std::string name, uint32 duration) +{ + self->SetTimer(name, duration); +} + +void Perl_Zone_StopTimer(Zone* self, std::string name) +{ + self->StopTimer(name); +} + +void Perl_Zone_StopAllTimers(Zone* self) +{ + self->StopAllTimers(); +} + +void Perl_Zone_SendPayload(Zone* self, int payload_id, std::string payload_value) +{ + self->SendPayload(payload_id, payload_value); +} + +void Perl_Zone_Signal(Zone* self, int signal_id) +{ + self->Signal(signal_id); +} + void perl_register_zone() { perl::interpreter perl(PERL_GET_THX); @@ -689,6 +744,8 @@ void perl_register_zone() package.add("GetSnowDuration", (int(*)(Zone*, uint8))&Perl_Zone_GetSnowDuration); package.add("GetTimeType", &Perl_Zone_GetTimeType); package.add("GetTimeZone", &Perl_Zone_GetTimeZone); + package.add("GetTimerDuration", &Perl_Zone_GetTimerDuration); + package.add("GetTimerRemainingTime", &Perl_Zone_GetTimerRemainingTime); package.add("GetZoneDescription", &Perl_Zone_GetZoneDescription); package.add("GetZoneID", &Perl_Zone_GetZoneID); package.add("GetZoneType", &Perl_Zone_GetZoneType); @@ -701,12 +758,14 @@ void perl_register_zone() package.add("GetZoneTotalBlockedSpells", &Perl_Zone_GetZoneTotalBlockedSpells); package.add("HasGraveyard", &Perl_Zone_HasGraveyard); package.add("HasMap", &Perl_Zone_HasMap); + package.add("HasTimer", &Perl_Zone_HasTimer); package.add("HasWaterMap", &Perl_Zone_HasWaterMap); package.add("HasWeather", &Perl_Zone_HasWeather); package.add("IsCity", &Perl_Zone_IsCity); package.add("IsHotzone", &Perl_Zone_IsHotzone); package.add("IsInstancePersistent", &Perl_Zone_IsInstancePersistent); package.add("IsIdleWhenEmpty", &Perl_Zone_IsIdleWhenEmpty); + package.add("IsPausedTimer", &Perl_Zone_IsPausedTimer); package.add("IsPVPZone", &Perl_Zone_IsPVPZone); package.add("IsRaining", &Perl_Zone_IsRaining); package.add("IsSnowing", &Perl_Zone_IsSnowing); @@ -715,8 +774,11 @@ void perl_register_zone() package.add("IsStaticZone", &Perl_Zone_IsStaticZone); package.add("IsUCSServerAvailable", &Perl_Zone_IsUCSServerAvailable); package.add("IsWaterZone", &Perl_Zone_IsWaterZone); + package.add("PauseTimer", &Perl_Zone_PauseTimer); package.add("Repop", (void(*)(Zone*))&Perl_Zone_Repop); package.add("Repop", (void(*)(Zone*, bool))&Perl_Zone_Repop); + package.add("ResumeTimer", &Perl_Zone_ResumeTimer); + package.add("SendPayload", &Perl_Zone_SendPayload); package.add("SetAAEXPModifier", &Perl_Zone_SetAAEXPModifier); package.add("SetAAEXPModifierByCharacterID", &Perl_Zone_SetAAEXPModifierByCharacterID); package.add("SetBucket", (void(*)(Zone*, const std::string, const std::string))&Perl_Zone_SetBucket); @@ -726,7 +788,11 @@ void perl_register_zone() package.add("SetInstanceTimer", &Perl_Zone_SetInstanceTimer); package.add("SetInstanceTimeRemaining", &Perl_Zone_SetInstanceTimeRemaining); package.add("SetIsHotzone", &Perl_Zone_SetIsHotzone); + package.add("SetTimer", &Perl_Zone_SetTimer); package.add("SetVariable", &Perl_Zone_SetVariable); + package.add("Signal", &Perl_Zone_Signal); + package.add("StopTimer", &Perl_Zone_StopTimer); + package.add("StopAllTimers", &Perl_Zone_StopAllTimers); package.add("ShowZoneGlobalLoot", &Perl_Zone_ShowZoneGlobalLoot); package.add("VariableExists", &Perl_Zone_VariableExists); } diff --git a/zone/quest_interface.h b/zone/quest_interface.h index 687a90f587..f18e1dbece 100644 --- a/zone/quest_interface.h +++ b/zone/quest_interface.h @@ -163,6 +163,28 @@ class QuestInterface { return 0; } + virtual int EventZone( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers + ) + { + return 0; + } + + virtual int EventGlobalZone( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers + ) + { + return 0; + } + virtual bool HasQuestSub(uint32 npc_id, QuestEventID event_id) { return false; @@ -223,6 +245,16 @@ class QuestInterface { return false; } + virtual bool ZoneHasQuestSub(QuestEventID event_id) + { + return false; + } + + virtual bool GlobalZoneHasQuestSub(QuestEventID event_id) + { + return false; + } + virtual void LoadNPCScript(std::string filename, int npc_id) { } virtual void LoadGlobalNPCScript(std::string filename) { } virtual void LoadPlayerScript(std::string filename) { } @@ -234,6 +266,8 @@ class QuestInterface { virtual void LoadGlobalBotScript(std::string filename) { } virtual void LoadMercScript(std::string filename) { } virtual void LoadGlobalMercScript(std::string filename) { } + virtual void LoadZoneScript(std::string filename) { } + virtual void LoadGlobalZoneScript(std::string filename) { } virtual int DispatchEventNPC( QuestEventID event_id, @@ -308,6 +342,17 @@ class QuestInterface { return 0; } + virtual int DispatchEventZone( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers + ) + { + return 0; + } + virtual void AddVar(std::string name, std::string val) { } virtual std::string GetVar(std::string name) { diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index 2ab537c649..9535cb89ab 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -49,6 +49,8 @@ QuestParserCollection::QuestParserCollection() _global_bot_quest_status = QuestUnloaded; _merc_quest_status = QuestUnloaded; _global_merc_quest_status = QuestUnloaded; + _zone_quest_status = QuestUnloaded; + _global_zone_quest_status = QuestUnloaded; } QuestParserCollection::~QuestParserCollection() { } @@ -85,6 +87,7 @@ void QuestParserCollection::ReloadQuests(bool reset_timers) { if (reset_timers) { quest_manager.ClearAllTimers(); + zone->StopAllTimers(); } MapOpcodes(); @@ -98,6 +101,8 @@ void QuestParserCollection::ReloadQuests(bool reset_timers) _global_bot_quest_status = QuestUnloaded; _merc_quest_status = QuestUnloaded; _global_merc_quest_status = QuestUnloaded; + _zone_quest_status = QuestUnloaded; + _global_zone_quest_status = QuestUnloaded; _spell_quest_status.clear(); _item_quest_status.clear(); @@ -426,6 +431,49 @@ bool QuestParserCollection::MercHasQuestSub(QuestEventID event_id) return MercHasQuestSubLocal(event_id) || MercHasQuestSubGlobal(event_id); } +bool QuestParserCollection::ZoneHasQuestSubLocal(QuestEventID event_id) +{ + if (_zone_quest_status == QuestUnloaded) { + std::string filename; + auto qi = GetQIByZoneQuest(filename); + + if (qi) { + _zone_quest_status = qi->GetIdentifier(); + qi->LoadZoneScript(filename); + return qi->ZoneHasQuestSub(event_id); + } + } else if (_zone_quest_status != QuestFailedToLoad) { + auto iter = _interfaces.find(_zone_quest_status); + return iter->second->ZoneHasQuestSub(event_id); + } + + return false; +} + +bool QuestParserCollection::ZoneHasQuestSubGlobal(QuestEventID event_id) +{ + if (_global_zone_quest_status == QuestUnloaded) { + std::string filename; + auto qi = GetQIByGlobalZoneQuest(filename); + + if (qi) { + _global_zone_quest_status = qi->GetIdentifier(); + qi->LoadGlobalZoneScript(filename); + return qi->GlobalZoneHasQuestSub(event_id); + } + } else if (_global_zone_quest_status != QuestFailedToLoad) { + auto iter = _interfaces.find(_global_zone_quest_status); + return iter->second->GlobalZoneHasQuestSub(event_id); + } + + return false; +} + +bool QuestParserCollection::ZoneHasQuestSub(QuestEventID event_id) +{ + return ZoneHasQuestSubLocal(event_id) || ZoneHasQuestSubGlobal(event_id); +} + int QuestParserCollection::EventNPC( QuestEventID event_id, NPC* npc, @@ -924,6 +972,83 @@ int QuestParserCollection::EventMercGlobal( return 0; } +int QuestParserCollection::EventZone( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers +) +{ + const int local_return = EventZoneLocal(event_id, zone, data, extra_data, extra_pointers); + const int global_return = EventZoneGlobal(event_id, zone, data, extra_data, extra_pointers); + const int default_return = DispatchEventZone(event_id, zone, data, extra_data, extra_pointers); + + if (local_return != 0) { + return local_return; + } else if (global_return != 0) { + return global_return; + } else if (default_return != 0) { + return default_return; + } + + return 0; +} + +int QuestParserCollection::EventZoneLocal( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers +) +{ + if (_zone_quest_status == QuestUnloaded) { + std::string filename; + auto qi = GetQIByZoneQuest(filename); + + if (qi) { + _zone_quest_status = qi->GetIdentifier(); + qi->LoadZoneScript(filename); + return qi->EventZone(event_id, zone, data, extra_data, extra_pointers); + } + } else { + if (_zone_quest_status != QuestFailedToLoad) { + auto iter = _interfaces.find(_zone_quest_status); + return iter->second->EventZone(event_id, zone, data, extra_data, extra_pointers); + } + } + + return 0; +} + +int QuestParserCollection::EventZoneGlobal( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers +) +{ + if (_global_zone_quest_status == QuestUnloaded) { + std::string filename; + auto qi = GetQIByGlobalZoneQuest(filename); + + if (qi) { + _global_zone_quest_status = qi->GetIdentifier(); + qi->LoadGlobalZoneScript(filename); + return qi->EventGlobalZone(event_id, zone, data, extra_data, extra_pointers); + } + } else { + if (_global_zone_quest_status != QuestFailedToLoad) { + auto iter = _interfaces.find(_global_zone_quest_status); + return iter->second->EventGlobalZone(event_id, zone, data, extra_data, extra_pointers); + } + } + + return 0; +} + QuestInterface* QuestParserCollection::GetQIByNPCQuest(uint32 npc_id, std::string& filename) { if (!zone) { @@ -1425,6 +1550,86 @@ QuestInterface* QuestParserCollection::GetQIByGlobalMercQuest(std::string& filen return nullptr; } +QuestInterface* QuestParserCollection::GetQIByZoneQuest(std::string& filename) +{ + if (!zone || !zone->IsLoaded()) { + return nullptr; + } + + std::string file_name; + for (auto& dir: PathManager::Instance()->GetQuestPaths()) { + const std::string& global_path = fmt::format( + "{}/{}", + dir, + QUEST_GLOBAL_DIRECTORY + ); + + const std::string& zone_path = fmt::format( + "{}/{}", + dir, + zone->GetShortName() + ); + + const std::string& zone_versioned_path = fmt::format( + "{}/{}/v{}", + dir, + zone->GetShortName(), + zone->GetInstanceVersion() + ); + + std::vector file_names = { + fmt::format("{}/zone", zone_versioned_path), // Local versioned by Instance Version ./quests/zone/v0/zone.ext + fmt::format("{}/zone_v{}", zone_path, zone->GetInstanceVersion()), // Local by Instance Version + fmt::format("{}/zone", zone_path), // Local + fmt::format("{}/zone", global_path) // Global + }; + + for (auto& file: file_names) { + for (auto* e: _load_precedence) { + file_name = fmt::format( + "{}.{}", + file, + _extensions.find(e->GetIdentifier())->second + ); + + if (File::Exists(file_name)) { + filename = file_name; + return e; + } + } + } + } + + return nullptr; +} + +QuestInterface* QuestParserCollection::GetQIByGlobalZoneQuest(std::string& filename) +{ + if (!zone) { + return nullptr; + } + + std::string file_name; + + for (auto& dir: PathManager::Instance()->GetQuestPaths()) { + for (auto* e: _load_precedence) { + file_name = fmt::format( + "{}/{}/global_zone.{}", + dir, + QUEST_GLOBAL_DIRECTORY, + _extensions.find(e->GetIdentifier())->second + ); + + if (File::Exists(file_name)) { + filename = file_name; + return e; + } + } + } + + return nullptr; +} + void QuestParserCollection::GetErrors(std::list& quest_errors) { quest_errors.clear(); @@ -1561,6 +1766,26 @@ int QuestParserCollection::DispatchEventMerc( return ret; } +int QuestParserCollection::DispatchEventZone( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers +) +{ + int ret = 0; + + for (const auto& e: _load_precedence) { + int i = e->DispatchEventZone(event_id, zone, data, extra_data, extra_pointers); + if (i != 0) { + ret = i; + } + } + + return ret; +} + void QuestParserCollection::LoadPerlEventExportSettings(PerlEventExportSettings* s) { for (int i = 0; i < _LargestEventID; i++) { diff --git a/zone/quest_parser_collection.h b/zone/quest_parser_collection.h index cb0a5e8d11..5d7d1d3c08 100644 --- a/zone/quest_parser_collection.h +++ b/zone/quest_parser_collection.h @@ -72,6 +72,7 @@ class QuestParserCollection { bool ItemHasQuestSub(EQ::ItemInstance* inst, QuestEventID event_id); bool BotHasQuestSub(QuestEventID event_id); bool MercHasQuestSub(QuestEventID event_id); + bool ZoneHasQuestSub(QuestEventID event_id); int EventNPC( QuestEventID event_id, @@ -172,6 +173,14 @@ class QuestParserCollection { std::vector* extra_pointers = nullptr ); + int EventZone( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data = 0, + std::vector* extra_pointers = nullptr + ); + void GetErrors(std::list &quest_errors); /* @@ -209,6 +218,8 @@ class QuestParserCollection { bool BotHasQuestSubGlobal(QuestEventID event_id); bool MercHasQuestSubLocal(QuestEventID event_id); bool MercHasQuestSubGlobal(QuestEventID event_id); + bool ZoneHasQuestSubLocal(QuestEventID event_id); + bool ZoneHasQuestSubGlobal(QuestEventID event_id); int EventNPCLocal( QuestEventID event_id, @@ -280,6 +291,22 @@ class QuestParserCollection { std::vector* extra_pointers ); + int EventZoneLocal( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers + ); + + int EventZoneGlobal( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers + ); + QuestInterface* GetQIByNPCQuest(uint32 npc_id, std::string& filename); QuestInterface* GetQIByGlobalNPCQuest(std::string& filename); QuestInterface* GetQIByPlayerQuest(std::string& filename); @@ -291,6 +318,8 @@ class QuestParserCollection { QuestInterface* GetQIByGlobalBotQuest(std::string& filename); QuestInterface* GetQIByMercQuest(std::string& filename); QuestInterface* GetQIByGlobalMercQuest(std::string& filename); + QuestInterface* GetQIByZoneQuest(std::string& filename); + QuestInterface* GetQIByGlobalZoneQuest(std::string& filename); int DispatchEventNPC( QuestEventID event_id, @@ -347,6 +376,14 @@ class QuestParserCollection { std::vector* extra_pointers ); + int DispatchEventZone( + QuestEventID event_id, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector* extra_pointers + ); + std::map _interfaces; std::map _extensions; std::list _load_precedence; @@ -359,6 +396,8 @@ class QuestParserCollection { uint32 _global_bot_quest_status; uint32 _merc_quest_status; uint32 _global_merc_quest_status; + uint32 _zone_quest_status; + uint32 _global_zone_quest_status; std::map _spell_quest_status; std::map _item_quest_status; std::map _encounter_quest_status; diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index ac17e68d35..288b87ab8a 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -64,10 +64,10 @@ QuestManager quest_manager; EQ::ItemInstance* questitem = nullptr; \ const SPDat_Spell_Struct* questspell = nullptr; \ bool depop_npc = false; \ - std::string encounter; \ + std::string encounter = ""; \ do { \ - if(!quests_running_.empty()) { \ - running_quest e = quests_running_.top(); \ + if(!m_running_quests.empty()) { \ + RunningQuest e = m_running_quests.top(); \ owner = e.owner; \ initiator = e.initiator; \ questitem = e.questitem; \ @@ -124,33 +124,30 @@ void QuestManager::Process() { } } -void QuestManager::StartQuest(Mob *_owner, Client *_initiator, EQ::ItemInstance* _questitem, const SPDat_Spell_Struct* _questspell, std::string encounter) { - running_quest run; - run.owner = _owner; - run.initiator = _initiator; - run.questitem = _questitem; - run.questspell = _questspell; - run.depop_npc = false; - run.encounter = encounter; - quests_running_.push(run); +void QuestManager::StartQuest(const RunningQuest& q) +{ + m_running_quests.push(q); } void QuestManager::EndQuest() { - running_quest run = quests_running_.top(); - if(run.depop_npc && run.owner->IsNPC()) { + RunningQuest run = m_running_quests.top(); + + if (run.depop_npc && run.owner->IsNPC()) { //clear out any timers for them... std::list::iterator cur = QTimerList.begin(), end; end = QTimerList.end(); while (cur != end) { - if (cur->mob == run.owner) + if (cur->mob == run.owner) { cur = QTimerList.erase(cur); - else + } else { ++cur; + } } run.owner->Depop(); } - quests_running_.pop(); + + m_running_quests.pop(); } void QuestManager::ClearAllTimers() { @@ -1098,18 +1095,18 @@ void QuestManager::depop(int npc_type) { tmp->CastToNPC()->Depop(); } else { - running_quest e = quests_running_.top(); + RunningQuest e = m_running_quests.top(); e.depop_npc = true; - quests_running_.pop(); - quests_running_.push(e); + m_running_quests.pop(); + m_running_quests.push(e); } } } else { //depop self - running_quest e = quests_running_.top(); + RunningQuest e = m_running_quests.top(); e.depop_npc = true; - quests_running_.pop(); - quests_running_.push(e); + m_running_quests.pop(); + m_running_quests.push(e); } } } @@ -1606,7 +1603,7 @@ void QuestManager::save() { void QuestManager::faction(int faction_id, int faction_value, int temp) { QuestManagerCurrentQuestVars(); - running_quest run = quests_running_.top(); + RunningQuest run = m_running_quests.top(); if(run.owner->IsCharmed() == false && initiator) { if(faction_id != 0 && faction_value != 0) { initiator->SetFactionLevel2( @@ -2077,10 +2074,10 @@ void QuestManager::respawn(int npcTypeID, int grid) { if (!owner || !owner->IsNPC()) return; - running_quest e = quests_running_.top(); + RunningQuest e = m_running_quests.top(); e.depop_npc = true; - quests_running_.pop(); - quests_running_.push(e); + m_running_quests.pop(); + m_running_quests.push(e); const NPCType* npcType = nullptr; if ((npcType = content_db.LoadNPCTypesData(npcTypeID))) @@ -3980,81 +3977,90 @@ void QuestManager::ReloadZoneStaticData() } } -Client *QuestManager::GetInitiator() const { - if(!quests_running_.empty()) { - running_quest e = quests_running_.top(); +Client* QuestManager::GetInitiator() const +{ + if (!m_running_quests.empty()) { + RunningQuest e = m_running_quests.top(); return e.initiator; } return nullptr; } -NPC *QuestManager::GetNPC() const { - if(!quests_running_.empty()) { - running_quest e = quests_running_.top(); +NPC* QuestManager::GetNPC() const +{ + if (!m_running_quests.empty()) { + RunningQuest e = m_running_quests.top(); return (e.owner && e.owner->IsNPC()) ? e.owner->CastToNPC() : nullptr; } return nullptr; } -Bot *QuestManager::GetBot() const { - if (!quests_running_.empty()) { - running_quest e = quests_running_.top(); +Bot* QuestManager::GetBot() const +{ + if (!m_running_quests.empty()) { + RunningQuest e = m_running_quests.top(); return (e.owner && e.owner->IsBot()) ? e.owner->CastToBot() : nullptr; } return nullptr; } -Merc *QuestManager::GetMerc() const { - if (!quests_running_.empty()) { - running_quest e = quests_running_.top(); +Merc* QuestManager::GetMerc() const +{ + if (!m_running_quests.empty()) { + RunningQuest e = m_running_quests.top(); return (e.owner && e.owner->IsMerc()) ? e.owner->CastToMerc() : nullptr; } return nullptr; } -Mob *QuestManager::GetOwner() const { - if(!quests_running_.empty()) { - running_quest e = quests_running_.top(); +Mob* QuestManager::GetOwner() const +{ + if (!m_running_quests.empty()) { + RunningQuest e = m_running_quests.top(); return e.owner; } return nullptr; } -EQ::InventoryProfile *QuestManager::GetInventory() const { - if(!quests_running_.empty()) { - running_quest e = quests_running_.top(); +EQ::InventoryProfile* QuestManager::GetInventory() const +{ + if (!m_running_quests.empty()) { + RunningQuest e = m_running_quests.top(); return &e.initiator->GetInv(); } return nullptr; } -EQ::ItemInstance *QuestManager::GetQuestItem() const { - if(!quests_running_.empty()) { - running_quest e = quests_running_.top(); +EQ::ItemInstance* QuestManager::GetQuestItem() const +{ + if (!m_running_quests.empty()) { + RunningQuest e = m_running_quests.top(); return e.questitem; } return nullptr; } -const SPDat_Spell_Struct *QuestManager::GetQuestSpell() { - if(!quests_running_.empty()) { - running_quest e = quests_running_.top(); +const SPDat_Spell_Struct* QuestManager::GetQuestSpell() +{ + if (!m_running_quests.empty()) { + RunningQuest e = m_running_quests.top(); return e.questspell; } return nullptr; } -std::string QuestManager::GetEncounter() const { - if(!quests_running_.empty()) { - running_quest e = quests_running_.top(); +std::string QuestManager::GetEncounter() const +{ + if (!m_running_quests.empty()) { + RunningQuest e = m_running_quests.top(); return e.encounter; } diff --git a/zone/questmgr.h b/zone/questmgr.h index 0e3cd4a4f3..b85e6e330f 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -33,15 +33,17 @@ namespace EQ class ItemInstance; } +struct RunningQuest { + Mob* owner = nullptr; + Client* initiator = nullptr; + EQ::ItemInstance* questitem = nullptr; + const SPDat_Spell_Struct* questspell = nullptr; + bool depop_npc = false; + std::string encounter = ""; + Zone* zone = nullptr; +}; + class QuestManager { - struct running_quest { - Mob *owner; - Client *initiator; - EQ::ItemInstance* questitem; - const SPDat_Spell_Struct* questspell; - bool depop_npc; - std::string encounter; - }; struct PausedTimer { Mob* owner; @@ -49,12 +51,13 @@ class QuestManager { uint32 time; }; public: + QuestManager(); virtual ~QuestManager(); - void StartQuest(Mob *_owner, Client *_initiator = nullptr, EQ::ItemInstance* _questitem = nullptr, const SPDat_Spell_Struct* _questspell = nullptr, std::string encounter = ""); + void StartQuest(const RunningQuest& q); void EndQuest(); - bool QuestsRunning() { return !quests_running_.empty(); } + bool QuestsRunning() { return !m_running_quests.empty(); } void Process(); @@ -381,7 +384,7 @@ class QuestManager { bool handin(std::map required); private: - std::stack quests_running_; + std::stack m_running_quests; bool HaveProximitySays; diff --git a/zone/zone.cpp b/zone/zone.cpp index 37216b0468..29ee85867f 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1693,6 +1693,25 @@ bool Zone::Process() { } } + const bool has_timer_event = parse->ZoneHasQuestSub(EVENT_TIMER); + + for (auto e : zone_timers) { + if (e.timer_.Enabled() && e.timer_.Check()) { + if (has_timer_event) { + parse->EventZone(EVENT_TIMER, this, e.name); + } + } + } + + if (!m_zone_signals.empty()) { + int signal_id = m_zone_signals.front(); + m_zone_signals.pop_front(); + + if (parse->ZoneHasQuestSub(EVENT_SIGNAL)) { + parse->EventZone(EVENT_SIGNAL, this, std::to_string(signal_id), 0); + } + } + mMovementManager->Process(); return true; @@ -1935,6 +1954,8 @@ void Zone::Repop(bool is_forced) quest_manager.ClearAllTimers(); + StopAllTimers(); + LogInfo("Loading spawn groups"); if (!content_db.LoadSpawnGroups(short_name, GetInstanceVersion(), &spawn_group_list)) { LogError("Loading spawn groups failed"); @@ -3301,4 +3322,241 @@ void Zone::ReloadMaps() pathing = IPathfinder::Load(map_name); } +uint32 Zone::GetTimerDuration(std::string name) +{ + if (!IsLoaded() || zone_timers.empty()) { + return 0; + } + + const auto& e = std::find_if( + zone_timers.begin(), + zone_timers.end(), + [&name](ZoneTimer e) { + return e.name == name; + } + ); + + return e != zone_timers.end() ? e->timer_.GetDuration() : 0; +} + +uint32 Zone::GetTimerRemainingTime(std::string name) +{ + if (!IsLoaded() || zone_timers.empty()) { + return 0; + } + + const auto& e = std::find_if( + zone_timers.begin(), + zone_timers.end(), + [&name](ZoneTimer e) { + return e.name == name; + } + ); + + return e != zone_timers.end() ? e->timer_.GetRemainingTime() : 0; +} + +bool Zone::HasTimer(std::string name) +{ + if (!IsLoaded() || zone_timers.empty()) { + return false; + } + + const auto& e = std::find_if( + zone_timers.begin(), + zone_timers.end(), + [&name](ZoneTimer e) { + return e.name == name; + } + ); + + return e != zone_timers.end(); +} + +bool Zone::IsPausedTimer(std::string name) +{ + if (!IsLoaded() || paused_zone_timers.empty()) { + return false; + } + + const auto& e = std::find_if( + paused_zone_timers.begin(), + paused_zone_timers.end(), + [&name](PausedZoneTimer e) { + return e.name == name; + } + ); + + return e != paused_zone_timers.end(); +} + +void Zone::PauseTimer(std::string name) +{ + if ( + !IsLoaded() || + zone_timers.empty() || + !HasTimer(name) || + IsPausedTimer(name) + ) { + return; + } + + uint32 remaining_time = 0; + + const bool has_pause_event = parse->ZoneHasQuestSub(EVENT_TIMER_PAUSE); + + if (!zone_timers.empty()) { + for (auto e = zone_timers.begin(); e != zone_timers.end(); e++) { + if (e->name == name) { + remaining_time = e->timer_.GetRemainingTime(); + + zone_timers.erase(e); + + const std::string& export_string = fmt::format( + "{} {}", + name, + remaining_time + ); + + LogQuests( + "Pausing timer [{}] with [{}] ms remaining", + name, + remaining_time + ); + + paused_zone_timers.emplace_back( + PausedZoneTimer{ + .name = name, + .remaining_time = remaining_time + } + ); + + if (has_pause_event) { + parse->EventZone(EVENT_TIMER_PAUSE, this, export_string); + } + + break; + } + } + } +} + +void Zone::ResumeTimer(std::string name) +{ + if ( + !IsLoaded() || + paused_zone_timers.empty() || + !IsPausedTimer(name) + ) { + return; + } + + uint32 remaining_time = 0; + + if (!paused_zone_timers.empty()) { + for (auto e = paused_zone_timers.begin(); e != paused_zone_timers.end(); e++) { + if (e->name == name) { + remaining_time = e->remaining_time; + + paused_zone_timers.erase(e); + + if (!remaining_time) { + LogQuests("Paused timer [{}] not found or has expired.", name); + return; + } + + const std::string& export_string = fmt::format( + "{} {}", + name, + remaining_time + ); + + LogQuests( + "Creating a new timer and resuming [{}] with [{}] ms remaining", + name, + remaining_time + ); + + zone_timers.emplace_back(ZoneTimer(name, remaining_time)); + + if (parse->ZoneHasQuestSub(EVENT_TIMER_RESUME)) { + parse->EventZone(EVENT_TIMER_RESUME, this, export_string); + } + + break; + } + } + } +} + +void Zone::SetTimer(std::string name, uint32 duration) +{ + if (!IsLoaded() || HasTimer(name)) { + return; + } + + zone_timers.emplace_back(ZoneTimer(name, duration)); + + if (parse->ZoneHasQuestSub(EVENT_TIMER_START)) { + const std::string& export_string = fmt::format("{} {}", name, duration); + parse->EventZone(EVENT_TIMER_START, this, export_string); + } +} + +void Zone::StopTimer(std::string name) +{ + if ( + !IsLoaded() || + zone_timers.empty() || + !HasTimer(name) || + IsPausedTimer(name) + ) { + return; + } + + const bool has_stop_event = parse->ZoneHasQuestSub(EVENT_TIMER_STOP); + + for (auto e = zone_timers.begin(); e != zone_timers.end(); e++) { + if (e->name == name) { + if (has_stop_event) { + parse->EventZone(EVENT_TIMER_STOP, this, name); + } + + zone_timers.erase(e); + break; + } + } +} + +void Zone::StopAllTimers() +{ + if (!IsLoaded() || zone_timers.empty()) { + return; + } + + const bool has_stop_event = parse->ZoneHasQuestSub(EVENT_TIMER_STOP); + + for (auto e = zone_timers.begin(); e != zone_timers.end();) { + if (has_stop_event) { + parse->EventZone(EVENT_TIMER_STOP, this, e->name); + } + + e = zone_timers.erase(e); + } +} + +void Zone::Signal(int signal_id) +{ + m_zone_signals.push_back(signal_id); +} + +void Zone::SendPayload(int payload_id, std::string payload_value) +{ + if (parse->ZoneHasQuestSub(EVENT_PAYLOAD)) { + const auto& export_string = fmt::format("{} {}", payload_id, payload_value); + + parse->EventZone(EVENT_PAYLOAD, this, export_string, 0); + } +} + #include "zone_loot.cpp" diff --git a/zone/zone.h b/zone/zone.h index 237c7fdb02..60c291abf1 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -486,6 +486,24 @@ class Zone { static void ClearZoneState(uint32 zone_id, uint32 instance_id); void ReloadMaps(); + void Signal(int signal_id); + void SendPayload(int payload_id, std::string payload_value); + + struct PausedZoneTimer { + std::string name; + uint32 remaining_time; + }; + + uint32 GetTimerDuration(std::string name); + uint32 GetTimerRemainingTime(std::string name); + bool HasTimer(std::string name); + bool IsPausedTimer(std::string name); + void PauseTimer(std::string name); + void ResumeTimer(std::string name); + void SetTimer(std::string name, uint32 duration); + void StopTimer(std::string name); + void StopAllTimers(); + private: bool allow_mercs; bool can_bind; @@ -552,6 +570,18 @@ class Zone { std::vector m_base_data = { }; uint32_t m_zone_server_id = 0; + + class ZoneTimer { + public: + inline ZoneTimer(std::string _name, uint32 duration) + : name(_name), timer_(duration) { timer_.Start(duration, false); } + std::string name; + Timer timer_; + }; + + std::vector zone_timers; + std::vector paused_zone_timers; + std::deque m_zone_signals; }; #endif From b8884d65722703d123ba4fbcba1a9e5ba28eb0a6 Mon Sep 17 00:00:00 2001 From: Bemvaras <169070864+Barathos@users.noreply.github.com> Date: Thu, 10 Jul 2025 13:09:04 -0600 Subject: [PATCH 003/194] [Quest API] Add GetMemberRole() to Perl/Lua (#4963) * Add group member role retrieval * Expose group member role to Lua * Cleanup * Cleanup --------- Co-authored-by: Kinglykrab --- zone/groups.cpp | 54 ++++++++++++++++++++++++++++++++++++++++---- zone/groups.h | 9 +++++++- zone/lua_group.cpp | 12 ++++++++++ zone/lua_group.h | 2 ++ zone/perl_groups.cpp | 12 ++++++++++ 5 files changed, 83 insertions(+), 6 deletions(-) diff --git a/zone/groups.cpp b/zone/groups.cpp index 821546e7eb..b70f44f18e 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -2472,19 +2472,63 @@ bool Group::AmIPuller(const char *mob_name) return !((bool)PullerName.compare(mob_name)); } -bool Group::HasRole(Mob *m, uint8 Role) +bool Group::HasRole(Mob* m, uint8 Role) { - if(!m) + if (!m) { return false; + } - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if((m == members[i]) && (MemberRoles[i] & Role)) + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { + if (m == members[i] && MemberRoles[i] & Role) { return true; + } } + return false; } +uint8 Group::GetMemberRole(Mob* m) +{ + if (!m) { + return 0; + } + + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { + if (m == members[i]) { + uint8 role = MemberRoles[i]; + + if (m == leader) { + role |= RoleLeader; + } + + return role; + } + } + + return 0; +} + +uint8 Group::GetMemberRole(const char* name) +{ + if (!name) { + return 0; + } + + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { + if (!strcasecmp(membername[i], name)) { + uint8 role = MemberRoles[i]; + + if (leader && !strcasecmp(leader->GetName(), name)) { + role |= RoleLeader; + } + + return role; + } + } + + return 0; +} + void Group::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_required /*= true*/, bool ignore_sender /*= true*/, float distance /*= 0*/) { if (sender && sender->IsClient()) { for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { diff --git a/zone/groups.h b/zone/groups.h index a07ecc61c8..8c312f6efd 100644 --- a/zone/groups.h +++ b/zone/groups.h @@ -30,7 +30,12 @@ class Mob; #define MAX_MARKED_NPCS 3 -enum { RoleAssist = 1, RoleTank = 2, RolePuller = 4 }; +enum { + RoleAssist = 1, + RoleTank = 2, + RolePuller = 4, + RoleLeader = 8 +}; class GroupIDConsumer { public: @@ -119,6 +124,8 @@ class Group : public GroupIDConsumer { void SetGroupTankTarget(Mob *m); void SetGroupPullerTarget(Mob *m); bool HasRole(Mob *m, uint8 Role); + uint8 GetMemberRole(Mob* m); + uint8 GetMemberRole(const char* name); void NotifyAssistTarget(Client *c); void NotifyTankTarget(Client *c); void NotifyPullerTarget(Client *c); diff --git a/zone/lua_group.cpp b/zone/lua_group.cpp index a427ef3d38..4bb1f4c4fd 100644 --- a/zone/lua_group.cpp +++ b/zone/lua_group.cpp @@ -122,6 +122,16 @@ Lua_Mob Lua_Group::GetMember(int member_index) { return self->members[member_index]; } +uint8 Lua_Group::GetMemberRole(Lua_Mob member) { + Lua_Safe_Call_Int(); + return self->GetMemberRole(member); +} + +uint8 Lua_Group::GetMemberRole(const char* name) { + Lua_Safe_Call_Int(); + return self->GetMemberRole(name); +} + bool Lua_Group::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name) { Lua_Safe_Call_Bool(); @@ -155,6 +165,8 @@ luabind::scope lua_register_group() { .def("GetLeaderName", (const char*(Lua_Group::*)(void))&Lua_Group::GetLeaderName) .def("GetLowestLevel", (uint32(Lua_Group::*)(void))&Lua_Group::GetLowestLevel) .def("GetMember", (Lua_Mob(Lua_Group::*)(int))&Lua_Group::GetMember) + .def("GetMemberRole", (uint8(Lua_Group::*)(Lua_Mob))&Lua_Group::GetMemberRole) + .def("GetMemberRole", (uint8(Lua_Group::*)(const char*))&Lua_Group::GetMemberRole) .def("GetTotalGroupDamage", (uint32(Lua_Group::*)(Lua_Mob))&Lua_Group::GetTotalGroupDamage) .def("GroupCount", (int(Lua_Group::*)(void))&Lua_Group::GroupCount) .def("GroupMessage", (void(Lua_Group::*)(Lua_Mob,const char*))&Lua_Group::GroupMessage) diff --git a/zone/lua_group.h b/zone/lua_group.h index 949740d66c..ee4e353bc5 100644 --- a/zone/lua_group.h +++ b/zone/lua_group.h @@ -49,6 +49,8 @@ class Lua_Group : public Lua_Ptr void TeleportGroup(Lua_Mob sender, uint32 zone_id, uint32 instance_id, float x, float y, float z, float h); int GetID(); Lua_Mob GetMember(int member_index); + uint8 GetMemberRole(Lua_Mob member); + uint8 GetMemberRole(const char* name); bool DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name); bool DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name, int max_check_count); }; diff --git a/zone/perl_groups.cpp b/zone/perl_groups.cpp index f93e31db87..a97716a28d 100644 --- a/zone/perl_groups.cpp +++ b/zone/perl_groups.cpp @@ -127,6 +127,16 @@ Client* Perl_Group_GetMember(Group* self, int member_index) // @categories Accou return member ? member->CastToClient() : nullptr; } +uint8_t Perl_Group_GetMemberRole(Group* self, Mob* member) // @categories Account and Character, Script Utility, Group +{ + return self->GetMemberRole(member); +} + +uint8_t Perl_Group_GetMemberRole(Group* self, const char* name) // @categories Account and Character, Script Utility, Group +{ + return self->GetMemberRole(name); +} + bool Perl_Group_DoesAnyMemberHaveExpeditionLockout(Group* self, std::string expedition_name, std::string event_name) { return self->AnyMemberHasDzLockout(expedition_name, event_name); @@ -163,6 +173,8 @@ void perl_register_group() package.add("GetLeaderName", &Perl_Group_GetLeaderName); package.add("GetLowestLevel", &Perl_Group_GetLowestLevel); package.add("GetMember", &Perl_Group_GetMember); + package.add("GetMemberRole", (uint8_t(*)(Group*, Mob*))&Perl_Group_GetMemberRole); + package.add("GetMemberRole", (uint8_t(*)(Group*, const char*))&Perl_Group_GetMemberRole); package.add("GetTotalGroupDamage", &Perl_Group_GetTotalGroupDamage); package.add("GroupCount", &Perl_Group_GroupCount); package.add("GroupMessage", (void(*)(Group*, Mob*, const char*))&Perl_Group_GroupMessage); From f3232cdc3a37f6a8efd2411c01184b8b6c0d29d8 Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Wed, 30 Jul 2025 08:37:23 -0500 Subject: [PATCH 004/194] [Database] Add Indexes to NPC's Spawns Loot (#4972) --- common/database/database_update_manifest.cpp | 25 ++++++++++++++++++++ common/version.h | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 05984036e2..58d8026a4d 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -7136,6 +7136,31 @@ ADD COLUMN `entity_variables` TEXT DEFAULT NULL AFTER `rezzable`; )", .content_schema_update = false }, + ManifestEntry{ + .version = 9326, + .description = "2025_07_27_add_indexes_npc_spawns_loot.sql", + .check = "SHOW INDEX FROM npc_types", + .condition = "missing", + .match = "idx_npc_types_loottable_id", + .sql = R"( +ALTER TABLE npc_types + ADD INDEX idx_npc_types_loottable_id (loottable_id); + +ALTER TABLE spawnentry + ADD INDEX idx_spawnentry_spawngroup_id (spawngroupID), + ADD INDEX idx_spawnentry_npc_id (npcID); + +ALTER TABLE lootdrop_entries + ADD INDEX idx_lootdrop_entries_lootdrop_id (lootdrop_id), + ADD INDEX idx_lootdrop_entries_item_id (item_id); + +ALTER TABLE loottable_entries + ADD INDEX idx_loottable_entries_lootdrop_id (lootdrop_id), + ADD INDEX idx_loottable_entries_loottable_id (loottable_id); +)", + .content_schema_update = true + }, + // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ // .version = 9228, diff --git a/common/version.h b/common/version.h index 82382af863..0fb38f1af1 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9325 +#define CURRENT_BINARY_DATABASE_VERSION 9326 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054 #define CUSTOM_BINARY_DATABASE_VERSION 0 From 9544e100c3c403c6ae88da3cab96a78ad21e85ea Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Wed, 30 Jul 2025 19:39:29 -0400 Subject: [PATCH 005/194] [Bug Fix] Fix Hero's Forge Ingame and Character Select (#4966) --- world/worlddb.cpp | 10 +++++++--- zone/mob_appearance.cpp | 6 +++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 9501670fd0..f47cdb608d 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -901,9 +901,13 @@ bool WorldDatabase::GetCharSelInventory( inst->SetCustomDataString(e.custom_data); } - inst->SetOrnamentIcon(e.ornament_icon); - inst->SetOrnamentationIDFile(e.ornament_idfile); - inst->SetOrnamentHeroModel(e.ornament_hero_model); + if (e.ornament_icon != 0 || e.ornament_idfile != 0 || e.ornament_hero_model != 0) { + inst->SetOrnamentIcon(e.ornament_icon); + inst->SetOrnamentationIDFile(e.ornament_idfile); + inst->SetOrnamentHeroModel(e.ornament_hero_model); + } else if (item->HerosForgeModel > 0) { + inst->SetOrnamentHeroModel(item->HerosForgeModel); + } inv->PutItem(e.slot_id, *inst); diff --git a/zone/mob_appearance.cpp b/zone/mob_appearance.cpp index 4302474434..2556a41b1e 100644 --- a/zone/mob_appearance.cpp +++ b/zone/mob_appearance.cpp @@ -286,8 +286,8 @@ uint32 Mob::GetHerosForgeModel(uint8 material_slot) const if (augment) { item = augment->GetItem(); heros_forge_model = item->HerosForgeModel; - } else if (inst->GetOrnamentHeroModel()) { - heros_forge_model = inst->GetOrnamentHeroModel(); + } else if (inst->GetOrnamentHeroModel(material_slot)) { + heros_forge_model = inst->GetOrnamentHeroModel(material_slot); } } } @@ -421,7 +421,7 @@ void Mob::SendWearChange(uint8 material_slot, Client *one_client) return key; }; - + auto dedupe_key = build_key(*w); auto send_if_changed = [&](Client* client) { auto& last_key = m_last_seen_wearchange[client->GetID()][material_slot]; From 73a5f11e17507ae97f0e1686cccf49ac78a1f5db Mon Sep 17 00:00:00 2001 From: regneq Date: Wed, 30 Jul 2025 16:39:55 -0700 Subject: [PATCH 006/194] [Bug Fix] [Bug Fix] Show player count on the server list status. (#4971) --- loginserver/options.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loginserver/options.h b/loginserver/options.h index 31976f142e..73d6f62169 100644 --- a/loginserver/options.h +++ b/loginserver/options.h @@ -31,7 +31,7 @@ class Options { inline void DefaultLoginServerName(const std::string &v) { m_default_loginserver_name = v; } inline std::string GetDefaultLoginServerName() const { return m_default_loginserver_name; } inline bool IsShowPlayerCountEnabled() const { return m_show_player_count; } - inline void SetShowPlayerCount(bool show_player_count) { show_player_count = show_player_count; } + inline void SetShowPlayerCount(bool show_player_count) { m_show_player_count = show_player_count; } inline bool IsWorldDevTestServersListBottom() const { return m_world_dev_list_bottom; } inline void SetWorldDevTestServersListBottom(bool list_bottom) { m_world_dev_list_bottom = list_bottom; } inline bool IsWorldSpecialCharacterStartListBottom() const { return m_special_char_list_bottom; } From 909de47acdd63cd559b5a841700a3f4a341b235c Mon Sep 17 00:00:00 2001 From: solar Date: Sat, 2 Aug 2025 07:32:30 -0700 Subject: [PATCH 007/194] fix player movement deltas (jumping, turning) (#4975) Co-authored-by: solar --- zone/client_packet.cpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a62131b71c..3bbfc7cb5a 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4983,9 +4983,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { m_Proximity = glm::vec3(cx, cy, cz); } - /* Update internal state */ - m_Delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading)); - if (RuleB(Skills, TrackingAutoRefreshSkillUps) && IsTracking() && ((m_Position.x != cx) || (m_Position.y != cy))) { if (zone->random.Real(0, 100) < 70)//should be good CheckIncreaseSkill(EQ::skills::SkillTracking, nullptr, -20); @@ -5019,6 +5016,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { rewind_timer.Start(30000, true); } + glm::vec4 prevDelta = m_Delta; // SetMoving clears m_Delta SetMoving(!(cy == m_Position.y && cx == m_Position.x)); if (RuleB(Character, EnableAutoAFK)) { @@ -5033,12 +5031,13 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { CheckSendBulkNpcPositions(); - int32 new_animation = ppu->animation; - /* Update internal server position from what the client has sent */ - m_Position.x = cx; - m_Position.y = cy; - m_Position.z = cz; + glm::vec4 prevPosition = m_Position; + m_Position = glm::vec4(cx, cy, cz, new_heading); + m_Delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading)); + int32 prevAnimation = ppu->animation; + animation = ppu->animation; + bool positionUpdated = m_Position != prevPosition || m_Delta != prevDelta || m_Delta != glm::vec4(0.0f) || prevAnimation != animation; /* Visual Debugging */ if (RuleB(Character, OPClientUpdateVisualDebug)) { @@ -5048,11 +5047,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { } /* Only feed real time updates when client is moving */ - if (IsMoving() || new_heading != m_Position.w || new_animation != animation) { - - animation = ppu->animation; - m_Position.w = new_heading; - + if (positionUpdated) { /* Broadcast update to other clients */ static EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct *position_update = (PlayerPositionUpdateServer_Struct *) outapp.pBuffer; @@ -5065,7 +5060,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { entity_list.QueueCloseClients(this, &outapp, true, RuleI(Range, ClientPositionUpdates), nullptr, true); } - /* Always send position updates to group - send when beyond normal ClientPositionUpdate range */ Group *group = GetGroup(); Raid *raid = GetRaid(); @@ -5091,7 +5085,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { } CheckVirtualZoneLines(); - } void Client::Handle_OP_CombatAbility(const EQApplicationPacket *app) From ffa813b92cdaff6a038d9cc072cce431576b0064 Mon Sep 17 00:00:00 2001 From: solar Date: Sat, 2 Aug 2025 17:15:11 -0700 Subject: [PATCH 008/194] [Build] Fix Linking with GCC (#4969) Co-authored-by: solar --- zone/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index e497b5ed51..ffea99f781 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -502,7 +502,7 @@ if (EQEMU_BUILD_STATIC AND PERL_LIBRARY) endif() # link zone against common libraries -target_link_libraries(zone PRIVATE ${ZONE_LIBS} lua_zone perl_zone gm_commands_zone) +target_link_libraries(zone PRIVATE lua_zone perl_zone gm_commands_zone ${ZONE_LIBS}) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) From e9be2d76c3609a77570587950d680e475738bbbf Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 2 Aug 2025 20:15:44 -0400 Subject: [PATCH 009/194] [Commands] Add #show keyring Subcommand (#4973) --- .../command_subsettings_repository.h | 1 + zone/client.cpp | 18 +++++++++++++++--- zone/client.h | 2 +- zone/client_packet.cpp | 2 +- zone/gm_commands/show.cpp | 2 ++ zone/gm_commands/show/keyring.cpp | 12 ++++++++++++ zone/lua_client.cpp | 9 ++++++++- zone/lua_client.h | 1 + zone/perl_client.cpp | 10 ++++++++-- 9 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 zone/gm_commands/show/keyring.cpp diff --git a/common/repositories/command_subsettings_repository.h b/common/repositories/command_subsettings_repository.h index 7faaf76b1e..963bcee91e 100644 --- a/common/repositories/command_subsettings_repository.h +++ b/common/repositories/command_subsettings_repository.h @@ -142,6 +142,7 @@ class CommandSubsettingsRepository: public BaseCommandSubsettingsRepository { {.parent_command = "show", .sub_command = "hatelist", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "hatelist"}, {.parent_command = "show", .sub_command = "inventory", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "peekinv"}, {.parent_command = "show", .sub_command = "ip_lookup", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "iplookup"}, + {.parent_command = "show", .sub_command = "keyring", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showkeyring"}, {.parent_command = "show", .sub_command = "line_of_sight", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "checklos"}, {.parent_command = "show", .sub_command = "network", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "network"}, {.parent_command = "show", .sub_command = "network_stats", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "netstats"}, diff --git a/zone/client.cpp b/zone/client.cpp index f296f27298..17eb2bac50 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -4780,9 +4780,21 @@ bool Client::KeyRingClear() ); } -void Client::KeyRingList() +void Client::KeyRingList(Client* c) { - Message(Chat::LightBlue, "Keys on Keyring:"); + if (!c) { + return; + } + + std::string message = "Keys on Keyring:"; + if (c != this) { + message = fmt::format( + "Keys on Keyring for {}:", + GetCleanName() + ); + } + + c->Message(Chat::LightBlue, message.c_str()); const EQ::ItemData *item = nullptr; @@ -4795,7 +4807,7 @@ void Client::KeyRingList() item->Name ); - Message(Chat::LightBlue, item_string.c_str()); + c->Message(Chat::LightBlue, item_string.c_str()); } } } diff --git a/zone/client.h b/zone/client.h index b75fb56f0a..8bf808b1d7 100644 --- a/zone/client.h +++ b/zone/client.h @@ -331,7 +331,7 @@ class Client : public Mob bool KeyRingCheck(uint32 item_id); bool KeyRingClear(); bool KeyRingRemove(uint32 item_id); - void KeyRingList(); + void KeyRingList(Client* c = nullptr); bool IsNameChangeAllowed(); void InvokeChangeNameWindow(bool immediate = true); bool ClearNameChange(); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 3bbfc7cb5a..5ee5fb7098 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9782,7 +9782,7 @@ void Client::Handle_OP_Jump(const EQApplicationPacket *app) void Client::Handle_OP_KeyRing(const EQApplicationPacket *app) { - KeyRingList(); + KeyRingList(this); } void Client::Handle_OP_KickPlayers(const EQApplicationPacket *app) diff --git a/zone/gm_commands/show.cpp b/zone/gm_commands/show.cpp index 8f45ee869d..5a5de45606 100755 --- a/zone/gm_commands/show.cpp +++ b/zone/gm_commands/show.cpp @@ -15,6 +15,7 @@ #include "show/group_info.cpp" #include "show/hatelist.cpp" #include "show/inventory.cpp" +#include "show/keyring.cpp" #include "show/ip_lookup.cpp" #include "show/line_of_sight.cpp" #include "show/network.cpp" @@ -78,6 +79,7 @@ void command_show(Client *c, const Seperator *sep) Cmd{.cmd = "hatelist", .u = "hatelist", .fn = ShowHateList, .a = {"#hatelist"}}, Cmd{.cmd = "inventory", .u = "inventory", .fn = ShowInventory, .a = {"#peekinv"}}, Cmd{.cmd = "ip_lookup", .u = "ip_lookup", .fn = ShowIPLookup, .a = {"#iplookup"}}, + Cmd{.cmd = "keyring", .u = "keyring", .fn = ShowKeyring, .a = {"#showkeyring"}}, Cmd{.cmd = "line_of_sight", .u = "line_of_sight", .fn = ShowLineOfSight, .a = {"#checklos"}}, Cmd{.cmd = "network", .u = "network", .fn = ShowNetwork, .a = {"#network"}}, Cmd{.cmd = "network_stats", .u = "network_stats", .fn = ShowNetworkStats, .a = {"#netstats"}}, diff --git a/zone/gm_commands/show/keyring.cpp b/zone/gm_commands/show/keyring.cpp new file mode 100644 index 0000000000..39552f8ccb --- /dev/null +++ b/zone/gm_commands/show/keyring.cpp @@ -0,0 +1,12 @@ +#include "../../client.h" +#include "../../dialogue_window.h" + +void ShowKeyring(Client *c, const Seperator *sep) +{ + Client* t = c; + if (c->GetTarget() && c->GetTarget()->IsClient()) { + t = c->GetTarget()->CastToClient(); + } + + t->KeyRingList(c); +} diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index b99636f191..a295f5c6d0 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -3575,7 +3575,13 @@ bool Lua_Client::KeyRingClear() void Lua_Client::KeyRingList() { Lua_Safe_Call_Void(); - self->KeyRingList(); + self->KeyRingList(self); +} + +void Lua_Client::KeyRingList(Lua_Client c) +{ + Lua_Safe_Call_Void(); + self->KeyRingList(self); } bool Lua_Client::KeyRingRemove(uint32 item_id) @@ -3932,6 +3938,7 @@ luabind::scope lua_register_client() { .def("KeyRingCheck", (bool(Lua_Client::*)(uint32))&Lua_Client::KeyRingCheck) .def("KeyRingClear", (bool(Lua_Client::*)(void))&Lua_Client::KeyRingClear) .def("KeyRingList", (void(Lua_Client::*)(void))&Lua_Client::KeyRingList) + .def("KeyRingList", (void(Lua_Client::*)(Lua_Client))&Lua_Client::KeyRingList) .def("KeyRingRemove", (bool(Lua_Client::*)(uint32))&Lua_Client::KeyRingRemove) .def("Kick", (void(Lua_Client::*)(void))&Lua_Client::Kick) .def("LearnDisciplines", (uint16(Lua_Client::*)(uint8,uint8))&Lua_Client::LearnDisciplines) diff --git a/zone/lua_client.h b/zone/lua_client.h index 04b9da273d..5835899103 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -521,6 +521,7 @@ class Lua_Client : public Lua_Mob bool KeyRingCheck(uint32 item_id); bool KeyRingClear(); void KeyRingList(); + void KeyRingList(Lua_Client c); bool KeyRingRemove(uint32 item_id); bool CompleteTask(int task_id); bool UncompleteTask(int task_id); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 2f853c9cb9..d4a73c8518 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -3328,7 +3328,12 @@ bool Perl_Client_KeyRingClear(Client* self) void Perl_Client_KeyRingList(Client* self) { - self->KeyRingList(); + self->KeyRingList(self); +} + +void Perl_Client_KeyRingList(Client* self, Client* c) +{ + self->KeyRingList(c); } bool Perl_Client_KeyRingRemove(Client* self, uint32 item_id) @@ -3675,7 +3680,8 @@ void perl_register_client() package.add("KeyRingAdd", &Perl_Client_KeyRingAdd); package.add("KeyRingCheck", &Perl_Client_KeyRingCheck); package.add("KeyRingClear", &Perl_Client_KeyRingClear); - package.add("KeyRingList", &Perl_Client_KeyRingList); + package.add("KeyRingList", (void(*)(Client*))&Perl_Client_KeyRingList); + package.add("KeyRingList", (void(*)(Client*, Client*))&Perl_Client_KeyRingList); package.add("KeyRingRemove", &Perl_Client_KeyRingRemove); package.add("Kick", &Perl_Client_Kick); package.add("LearnDisciplines", &Perl_Client_LearnDisciplines); From 0afef19d265baed5a49cdcf6613f9d9657b5213a Mon Sep 17 00:00:00 2001 From: solar Date: Sat, 2 Aug 2025 17:16:35 -0700 Subject: [PATCH 010/194] [Loginserver] Fix Legacy World When Using Local DB (#4970) Co-authored-by: solar --- loginserver/world_server.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/loginserver/world_server.cpp b/loginserver/world_server.cpp index 1ff7b1492a..44e6049d1f 100644 --- a/loginserver/world_server.cpp +++ b/loginserver/world_server.cpp @@ -155,7 +155,11 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne auto *res = (UsertoWorldResponseLegacy *) packet.Data(); LogDebug("Trying to find client with user id of [{}]", res->lsaccountid); - Client *c = server.client_manager->GetClient(res->lsaccountid, "eqemu"); + std::string db_loginserver = "local"; + if (std::getenv("LSPX")) { + db_loginserver = "eqemu"; + } + Client *c = server.client_manager->GetClient(res->lsaccountid, db_loginserver); if (c) { LogDebug( "Found client with user id of [{}] and account name of [{}]", From 41f3d7ff312358e4bb88efeff66d1cadda449238 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Aug 2025 19:16:57 -0500 Subject: [PATCH 011/194] Bump golang.org/x/oauth2 in /utils/scripts/build/should-release (#4967) Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.0.0-20180821212333-d2e6202438be to 0.27.0. - [Commits](https://github.com/golang/oauth2/commits/v0.27.0) --- updated-dependencies: - dependency-name: golang.org/x/oauth2 dependency-version: 0.27.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- utils/scripts/build/should-release/go.mod | 5 +---- utils/scripts/build/should-release/go.sum | 10 ++++------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/utils/scripts/build/should-release/go.mod b/utils/scripts/build/should-release/go.mod index eaa7981342..df899a9e13 100644 --- a/utils/scripts/build/should-release/go.mod +++ b/utils/scripts/build/should-release/go.mod @@ -6,13 +6,10 @@ toolchain go1.23.5 require ( github.com/google/go-github/v41 v41.0.0 - golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be + golang.org/x/oauth2 v0.27.0 ) require ( - github.com/golang/protobuf v1.3.2 // indirect github.com/google/go-querystring v1.1.0 // indirect golang.org/x/crypto v0.36.0 // indirect - golang.org/x/net v0.38.0 // indirect - google.golang.org/appengine v1.6.7 // indirect ) diff --git a/utils/scripts/build/should-release/go.sum b/utils/scripts/build/should-release/go.sum index 88fd4be027..d821c4071c 100644 --- a/utils/scripts/build/should-release/go.sum +++ b/utils/scripts/build/should-release/go.sum @@ -1,9 +1,9 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v41 v41.0.0 h1:HseJrM2JFf2vfiZJ8anY2hqBjdfY1Vlj/K27ueww4gg= github.com/google/go-github/v41 v41.0.0/go.mod h1:XgmCA5H323A9rtgExdTcnDkcqp6S30AVACCBDOonIxg= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= @@ -14,10 +14,9 @@ golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= +golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -27,5 +26,4 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= From 0a1df5bbb655fd99d9dfb74a9c66b4b2bceee835 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 2 Aug 2025 20:17:56 -0400 Subject: [PATCH 012/194] [Quest API] Add GetTimers() and GetPausedTimers() to Perl/Lua (#4965) * [Quest API] Add GetTimers() and GetPausedTimers() to Perl/Lua * Push --- zone/embparser_api.cpp | 36 ++++++++++++++++++++++++++++++++++++ zone/lua_general.cpp | 28 ++++++++++++++++++++++++++++ zone/lua_mob.cpp | 34 +++++++++++++++++++++++++++++++++- zone/lua_mob.h | 4 +++- zone/lua_zone.cpp | 32 ++++++++++++++++++++++++++++++++ zone/lua_zone.h | 2 ++ zone/perl_mob.cpp | 26 ++++++++++++++++++++++++++ zone/perl_zone.cpp | 36 ++++++++++++++++++++++++++++++++++++ zone/questmgr.cpp | 30 ++++++++++++++++++++++++++++++ zone/questmgr.h | 2 ++ zone/zone.cpp | 26 ++++++++++++++++++++++++++ zone/zone.h | 2 ++ 12 files changed, 256 insertions(+), 2 deletions(-) diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 8bd0bfa94e..c305532f72 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -6005,6 +6005,40 @@ bool Perl__handin(perl::reference handin_ref) return quest_manager.handin(handin_map); } +perl::array Perl__get_paused_timers(Mob* m) +{ + perl::array a; + + const auto& l = quest_manager.GetPausedTimers(m); + + if (!l.empty()) { + a.reserve(l.size()); + + for (const auto& v : l) { + a.push_back(v); + } + } + + return a; +} + +perl::array Perl__get_timers(Mob* m) +{ + perl::array a; + + const auto& l = quest_manager.GetTimers(m); + + if (!l.empty()) { + a.reserve(l.size()); + + for (const auto& v: l) { + a.push_back(v); + } + } + + return a; +} + void perl_register_quest() { perl::interpreter perl(PERL_GET_THX); @@ -6694,6 +6728,7 @@ void perl_register_quest() package.add("getguildidbycharid", &Perl__getguildidbycharid); package.add("getgroupidbycharid", &Perl__getgroupidbycharid); package.add("getinventoryslotname", &Perl__getinventoryslotname); + package.add("get_paused_timers", &Perl__get_paused_timers); package.add("getraididbycharid", &Perl__getraididbycharid); package.add("get_race_bitmask", &Perl__get_race_bitmask); package.add("get_recipe_component_item_ids", &Perl__GetRecipeComponentItemIDs); @@ -6713,6 +6748,7 @@ void perl_register_quest() package.add("getspellstat", (int(*)(uint32, std::string))&Perl__getspellstat); package.add("getspellstat", (int(*)(uint32, std::string, uint8))&Perl__getspellstat); package.add("getskillname", &Perl__getskillname); + package.add("get_timers", &Perl__get_timers); package.add("getlevel", &Perl__getlevel); package.add("getplayerburiedcorpsecount", &Perl__getplayerburiedcorpsecount); package.add("getplayercorpsecount", &Perl__getplayercorpsecount); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index b7e1964d9d..ae3242885b 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -5675,6 +5675,32 @@ bool lua_handin(luabind::adl::object handin_table) return quest_manager.handin(handin_map); } +luabind::object lua_get_paused_timers(lua_State* L, Mob* m) { + auto t = luabind::newtable(L); + auto v = quest_manager.GetPausedTimers(m); + int i = 1; + + for (const auto& e : v) { + t[i] = e; + i++; + } + + return t; +} + +luabind::object lua_get_timers(lua_State* L, Mob* m) { + auto t = luabind::newtable(L); + auto v = quest_manager.GetTimers(m); + int i = 1; + + for (const auto& e : v) { + t[i] = e; + i++; + } + + return t; +} + #define LuaCreateNPCParse(name, c_type, default_value) do { \ cur = table[#name]; \ if(luabind::type(cur) != LUA_TNIL) { \ @@ -6486,6 +6512,8 @@ luabind::scope lua_register_general() { luabind::def("spawn_grid", &lua_spawn_grid), luabind::def("get_zone", &lua_get_zone), luabind::def("handin", &lua_handin), + luabind::def("get_paused_timers", &lua_get_paused_timers), + luabind::def("get_timers", &lua_get_timers), /* Cross Zone */ diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 27ab7bbd86..23890987ee 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -3482,6 +3482,36 @@ void Lua_Mob::BuffFadeSongs() self->BuffFadeSongs(); } +luabind::object Lua_Mob::GetPausedTimers(lua_State* L) { + auto t = luabind::newtable(L); + if (d_) { + auto self = reinterpret_cast(d_); + auto l = quest_manager.GetPausedTimers(self); + int i = 1; + for (const auto& v : l) { + t[i] = v; + i++; + } + } + + return t; +} + +luabind::object Lua_Mob::GetTimers(lua_State* L) { + auto t = luabind::newtable(L); + if (d_) { + auto self = reinterpret_cast(d_); + auto l = quest_manager.GetTimers(self); + int i = 1; + for (const auto& v : l) { + t[i] = v; + i++; + } + } + + return t; +} + luabind::scope lua_register_mob() { return luabind::class_("Mob") .def(luabind::constructor<>()) @@ -3822,6 +3852,7 @@ luabind::scope lua_register_mob() { .def("GetOwner", &Lua_Mob::GetOwner) .def("GetOwnerID", &Lua_Mob::GetOwnerID) .def("GetPR", &Lua_Mob::GetPR) + .def("GetPausedTimers", &Lua_Mob::GetPausedTimers) .def("GetPet", &Lua_Mob::GetPet) .def("GetPetOrder", (int(Lua_Mob::*)(void))&Lua_Mob::GetPetOrder) .def("GetPhR", &Lua_Mob::GetPhR) @@ -3847,6 +3878,7 @@ luabind::scope lua_register_mob() { .def("GetTarget", &Lua_Mob::GetTarget) .def("GetTexture", &Lua_Mob::GetTexture) .def("GetTimerDurationMS", &Lua_Mob::GetTimerDurationMS) + .def("GetTimers", &Lua_Mob::GetTimers) .def("GetUltimateOwner", &Lua_Mob::GetUltimateOwner) .def("GetWIS", &Lua_Mob::GetWIS) .def("GetWalkspeed", &Lua_Mob::GetWalkspeed) @@ -3908,7 +3940,7 @@ luabind::scope lua_register_mob() { .def("IsPausedTimer", &Lua_Mob::IsPausedTimer) .def("IsPet", (bool(Lua_Mob::*)(void))&Lua_Mob::IsPet) .def("IsPetOwnerBot", &Lua_Mob::IsPetOwnerBot) - .def("IsPetOwnerClient", &Lua_Mob::IsPetOwnerClient) + .def("IsPetOwnerClient", &Lua_Mob::IsPetOwnerClient) .def("IsPetOwnerNPC", &Lua_Mob::IsPetOwnerNPC) .def("IsPetOwnerOfClientBot", &Lua_Mob::IsPetOwnerOfClientBot) .def("IsPureMeleeClass", &Lua_Mob::IsPureMeleeClass) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 0f3d4f6c4e..f95794a10c 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -574,7 +574,7 @@ class Lua_Mob : public Lua_Entity bool IsFamiliar(); bool IsTargetLockPet(); bool IsPetOwnerBot(); - bool IsPetOwnerClient(); + bool IsPetOwnerClient(); bool IsPetOwnerNPC(); bool IsPetOwnerOfClientBot(); bool IsDestructibleObject(); @@ -612,6 +612,8 @@ class Lua_Mob : public Lua_Entity void BuffFadeDetrimentalByCaster(Lua_Mob caster); void BuffFadeNonPersistDeath(); void BuffFadeSongs(); + luabind::object GetPausedTimers(lua_State* L); + luabind::object GetTimers(lua_State* L); }; #endif diff --git a/zone/lua_zone.cpp b/zone/lua_zone.cpp index 3907a3ed96..0375716205 100644 --- a/zone/lua_zone.cpp +++ b/zone/lua_zone.cpp @@ -838,6 +838,36 @@ void Lua_Zone::Signal(int signal_id) self->Signal(signal_id); } +luabind::object Lua_Zone::GetPausedTimers(lua_State* L) { + auto t = luabind::newtable(L); + if (d_) { + auto self = reinterpret_cast(d_); + auto l = self->GetPausedTimers(); + int i = 1; + for (const auto& v : l) { + t[i] = v; + i++; + } + } + + return t; +} + +luabind::object Lua_Zone::GetTimers(lua_State* L) { + auto t = luabind::newtable(L); + if (d_) { + auto self = reinterpret_cast(d_); + auto l = self->GetTimers(); + int i = 1; + for (const auto& v : l) { + t[i] = v; + i++; + } + } + + return t; +} + luabind::scope lua_register_zone() { return luabind::class_("Zones") .def(luabind::constructor<>()) @@ -906,6 +936,7 @@ luabind::scope lua_register_zone() { .def("GetMinimumStatus", &Lua_Zone::GetMinimumStatus) .def("GetNote", &Lua_Zone::GetNote) .def("GetNPCMaximumAggroDistance", &Lua_Zone::GetNPCMaximumAggroDistance) + .def("GetPausedTimers", &Lua_Zone::GetPausedTimers) .def("GetPEQZone", &Lua_Zone::GetPEQZone) .def("GetRainChance", (int(Lua_Zone::*)(void))&Lua_Zone::GetRainChance) .def("GetRainChance", (int(Lua_Zone::*)(uint8))&Lua_Zone::GetRainChance) @@ -929,6 +960,7 @@ luabind::scope lua_register_zone() { .def("GetTimeZone", &Lua_Zone::GetTimeZone) .def("GetTimerDuration", &Lua_Zone::GetTimerDuration) .def("GetTimerRemainingTime", &Lua_Zone::GetTimerRemainingTime) + .def("GetTimers", &Lua_Zone::GetTimers) .def("GetZoneDescription", &Lua_Zone::GetZoneDescription) .def("GetZoneID", &Lua_Zone::GetZoneID) .def("GetZoneType", &Lua_Zone::GetZoneType) diff --git a/zone/lua_zone.h b/zone/lua_zone.h index b1a5390c2a..42a1d88418 100644 --- a/zone/lua_zone.h +++ b/zone/lua_zone.h @@ -158,6 +158,8 @@ class Lua_Zone : public Lua_Ptr void StopAllTimers(); void Signal(int signal_id); void SendPayload(int payload_id, std::string payload_value); + luabind::object GetPausedTimers(lua_State* L); + luabind::object GetTimers(lua_State* L); // data buckets void SetBucket(const std::string& bucket_name, const std::string& bucket_value); diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index af564d3b7b..3261140309 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -3573,6 +3573,30 @@ void Perl_Mob_BuffFadeSongs(Mob* self) self->BuffFadeSongs(); } +perl::array Perl_Mob_GetPausedTimers(Mob* self) +{ + perl::array a; + + const auto& l = quest_manager.GetPausedTimers(self); + for (const auto& v : l) { + a.push_back(v); + } + + return a; +} + +perl::array Perl_Mob_GetTimers(Mob* self) +{ + perl::array a; + + const auto& l = quest_manager.GetTimers(self); + for (const auto& v : l) { + a.push_back(v); + } + + return a; +} + void perl_register_mob() { perl::interpreter perl(PERL_GET_THX); @@ -3897,6 +3921,7 @@ void perl_register_mob() package.add("GetOwner", &Perl_Mob_GetOwner); package.add("GetOwnerID", &Perl_Mob_GetOwnerID); package.add("GetPR", &Perl_Mob_GetPR); + package.add("GetPausedTimers", &Perl_Mob_GetPausedTimers); package.add("GetPet", &Perl_Mob_GetPet); package.add("GetPetID", &Perl_Mob_GetPetID); package.add("GetPetOrder", &Perl_Mob_GetPetOrder); @@ -3927,6 +3952,7 @@ void perl_register_mob() package.add("GetTarget", &Perl_Mob_GetTarget); package.add("GetTexture", &Perl_Mob_GetTexture); package.add("GetTimerDurationMS", &Perl_Mob_GetTimerDurationMS); + package.add("GetTimers", &Perl_Mob_GetTimers); package.add("GetUltimateOwner", &Perl_Mob_GetUltimateOwner); package.add("GetWIS", &Perl_Mob_GetWIS); package.add("GetWalkspeed", &Perl_Mob_GetWalkspeed); diff --git a/zone/perl_zone.cpp b/zone/perl_zone.cpp index 7783c6020b..b81bfe344d 100644 --- a/zone/perl_zone.cpp +++ b/zone/perl_zone.cpp @@ -653,6 +653,40 @@ void Perl_Zone_Signal(Zone* self, int signal_id) self->Signal(signal_id); } +perl::array Perl_Zone_GetPausedTimers(Zone* self) +{ + perl::array a; + + const auto& l = self->GetPausedTimers(); + + if (!l.empty()) { + a.reserve(l.size()); + + for (const auto& v : l) { + a.push_back(v); + } + } + + return a; +} + +perl::array Perl_Zone_GetTimers(Zone* self) +{ + perl::array a; + + const auto& l = self->GetTimers(); + + if (!l.empty()) { + a.reserve(l.size()); + + for (const auto& v : l) { + a.push_back(v); + } + } + + return a; +} + void perl_register_zone() { perl::interpreter perl(PERL_GET_THX); @@ -723,6 +757,7 @@ void perl_register_zone() package.add("GetMinimumStatus", &Perl_Zone_GetMinimumStatus); package.add("GetNote", &Perl_Zone_GetNote); package.add("GetNPCMaximumAggroDistance", &Perl_Zone_GetNPCMaximumAggroDistance); + package.add("GetPausedTimers", &Perl_Zone_GetPausedTimers); package.add("GetPEQZone", &Perl_Zone_GetPEQZone); package.add("GetRainChance", (int(*)(Zone*))&Perl_Zone_GetRainChance); package.add("GetRainChance", (int(*)(Zone*, uint8))&Perl_Zone_GetRainChance); @@ -746,6 +781,7 @@ void perl_register_zone() package.add("GetTimeZone", &Perl_Zone_GetTimeZone); package.add("GetTimerDuration", &Perl_Zone_GetTimerDuration); package.add("GetTimerRemainingTime", &Perl_Zone_GetTimerRemainingTime); + package.add("GetTimers", &Perl_Zone_GetTimers); package.add("GetZoneDescription", &Perl_Zone_GetZoneDescription); package.add("GetZoneID", &Perl_Zone_GetZoneID); package.add("GetZoneType", &Perl_Zone_GetZoneType); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 288b87ab8a..342955fffc 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -4667,3 +4667,33 @@ bool QuestManager::handin(std::map required) { return owner->CastToNPC()->CheckHandin(initiator, {}, required, {}); } + +std::vector QuestManager::GetPausedTimers(Mob* m) +{ + std::vector v; + + if (m && !PTimerList.empty()) { + for (auto e = PTimerList.begin(); e != PTimerList.end(); e++) { + if (e->owner == m) { + v.emplace_back(e->name); + } + } + } + + return v; +} + +std::vector QuestManager::GetTimers(Mob* m) +{ + std::vector v; + + if (m && !QTimerList.empty()) { + for (auto e = QTimerList.begin(); e != QTimerList.end(); e++) { + if (e->mob == m) { + v.emplace_back(e->name); + } + } + } + + return v; +} diff --git a/zone/questmgr.h b/zone/questmgr.h index b85e6e330f..f58bb283a2 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -364,6 +364,8 @@ class QuestManager { bool SetAutoLoginCharacterNameByAccountID(uint32 account_id, const std::string& character_name); void SpawnCircle(uint32 npc_id, glm::vec4 position, float radius, uint32 points); void SpawnGrid(uint32 npc_id, glm::vec4 position, float spacing, uint32 spawn_count); + std::vector GetPausedTimers(Mob* m); + std::vector GetTimers(Mob* m); Bot *GetBot() const; Client *GetInitiator() const; diff --git a/zone/zone.cpp b/zone/zone.cpp index 29ee85867f..eea9d8a97a 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -3559,4 +3559,30 @@ void Zone::SendPayload(int payload_id, std::string payload_value) } } +std::vector Zone::GetPausedTimers() +{ + std::vector v; + + if (!paused_zone_timers.empty()) { + for (auto e = paused_zone_timers.begin(); e != paused_zone_timers.end(); e++) { + v.emplace_back(e->name); + } + } + + return v; +} + +std::vector Zone::GetTimers() +{ + std::vector v; + + if (!zone_timers.empty()) { + for (auto e = zone_timers.begin(); e != zone_timers.end(); e++) { + v.emplace_back(e->name); + } + } + + return v; +} + #include "zone_loot.cpp" diff --git a/zone/zone.h b/zone/zone.h index 60c291abf1..fe9d396505 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -503,6 +503,8 @@ class Zone { void SetTimer(std::string name, uint32 duration); void StopTimer(std::string name); void StopAllTimers(); + std::vector GetPausedTimers(); + std::vector GetTimers(); private: bool allow_mercs; From d9f4d49ef4ac6c6f555b135e5311d7cd6b32ad13 Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Sat, 2 Aug 2025 20:11:29 -0500 Subject: [PATCH 013/194] [Release] 23.9.0 (#4976) --- CHANGELOG.md | 43 +++++++++++++++++++++++++++++++++++++++++++ common/version.h | 2 +- package.json | 2 +- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 627baca5e6..e903559e7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,46 @@ +## [23.9.0] 8/2/2025 + +### Bots + +* Fix FinishBuffing rule ([#4961](https://github.com/EQEmu/Server/pull/4961)) @nytmyr 2025-07-01 +* Fix ^cast resurrects ([#4958](https://github.com/EQEmu/Server/pull/4958)) @nytmyr 2025-06-29 + +### Build + +* Fix Linking with GCC ([#4969](https://github.com/EQEmu/Server/pull/4969)) @solar984 2025-08-03 +* More Build Speed Improvements ([#4959](https://github.com/EQEmu/Server/pull/4959)) @Akkadius 2025-06-30 + +### Commands + +* Add #show keyring Subcommand ([#4973](https://github.com/EQEmu/Server/pull/4973)) @Kinglykrab 2025-08-03 + +### Database + +* Add Indexes to NPC's Spawns Loot ([#4972](https://github.com/EQEmu/Server/pull/4972)) @Akkadius 2025-07-30 + +### Feature + +* Zone Scripting ([#4908](https://github.com/EQEmu/Server/pull/4908)) @Kinglykrab 2025-07-10 + +### Fixes + +* Add a missing Froglok starting area for Titanium Startzone. ([#4962](https://github.com/EQEmu/Server/pull/4962)) @regneq 2025-07-04 +* Fix Hero's Forge Ingame and Character Select ([#4966](https://github.com/EQEmu/Server/pull/4966)) @Kinglykrab 2025-07-30 +* Show player count on the server list status. ([#4971](https://github.com/EQEmu/Server/pull/4971)) @regneq 2025-07-30 + +### Loginserver + +* Fix Legacy World When Using Local DB ([#4970](https://github.com/EQEmu/Server/pull/4970)) @solar984 2025-08-03 + +### Performance + +* Clear Wearchange Deduplication Cache ([#4960](https://github.com/EQEmu/Server/pull/4960)) @Akkadius 2025-06-30 + +### Quest API + +* Add GetMemberRole() to Perl/Lua ([#4963](https://github.com/EQEmu/Server/pull/4963)) @Barathos 2025-07-10 +* Add GetTimers() and GetPausedTimers() to Perl/Lua ([#4965](https://github.com/EQEmu/Server/pull/4965)) @Kinglykrab 2025-08-03 + ## [23.8.1] 6/28/2025 ### Crash Fix diff --git a/common/version.h b/common/version.h index 0fb38f1af1..eb68f66cca 100644 --- a/common/version.h +++ b/common/version.h @@ -25,7 +25,7 @@ // Build variables // these get injected during the build pipeline -#define CURRENT_VERSION "23.8.1-dev" // always append -dev to the current version for custom-builds +#define CURRENT_VERSION "23.9.0-dev" // always append -dev to the current version for custom-builds #define LOGIN_VERSION "0.8.0" #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ diff --git a/package.json b/package.json index 05a5664fad..b21f09c162 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eqemu-server", - "version": "23.8.1", + "version": "23.9.0", "repository": { "type": "git", "url": "https://github.com/EQEmu/Server.git" From d142e1ca8178d394b81b8ec870343465bd8e1c73 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 2 Aug 2025 23:09:30 -0400 Subject: [PATCH 014/194] [Hotfix] Fix Quest Ownership Edge Case (#4977) * [Hotfix] Fix Quest Ownership Edge Case * Push --- CHANGELOG.md | 6 ++++++ common/version.h | 2 +- package.json | 2 +- zone/embparser.cpp | 8 +++++--- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e903559e7b..7d87da2db5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [23.9.1] 8/2/2025 + +### Hotfix + +* Fix Quest Ownership Edge Case ([#4977](https://github.com/EQEmu/Server/pull/4977)) @Kinglykrab 2025-08-02 + ## [23.9.0] 8/2/2025 ### Bots diff --git a/common/version.h b/common/version.h index eb68f66cca..2bcb00f99d 100644 --- a/common/version.h +++ b/common/version.h @@ -25,7 +25,7 @@ // Build variables // these get injected during the build pipeline -#define CURRENT_VERSION "23.9.0-dev" // always append -dev to the current version for custom-builds +#define CURRENT_VERSION "23.9.1-dev" // always append -dev to the current version for custom-builds #define LOGIN_VERSION "0.8.0" #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ diff --git a/package.json b/package.json index b21f09c162..d148cc68bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eqemu-server", - "version": "23.9.0", + "version": "23.9.1", "repository": { "type": "git", "url": "https://github.com/EQEmu/Server.git" diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 903a4821f0..bd4eabc0d9 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -998,11 +998,13 @@ int PerlembParser::SendCommands( int ret_value = 0; RunningQuest q; + + q.owner = other; + q.questitem = inst; + q.questspell = spell; + if (mob && mob->IsClient()) { - q.owner = other; q.initiator = mob->CastToClient(); - q.questitem = inst; - q.questspell = spell; } if (zone) { From d876c6df2ae79075a76c01b088e86c04a85dfe1c Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Mon, 11 Aug 2025 14:06:13 -0400 Subject: [PATCH 015/194] [Bug Fix] Fix #show recipe uint16 Cap (#4978) --- zone/gm_commands/show/recipe.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/gm_commands/show/recipe.cpp b/zone/gm_commands/show/recipe.cpp index e4bd45ad1c..e9f8db6660 100644 --- a/zone/gm_commands/show/recipe.cpp +++ b/zone/gm_commands/show/recipe.cpp @@ -10,7 +10,7 @@ void ShowRecipe(Client *c, const Seperator *sep) return; } - const uint16 recipe_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); + const uint32 recipe_id = Strings::ToUnsignedInt(sep->arg[2]); const auto& re = TradeskillRecipeEntriesRepository::GetWhere( content_db, From c4f408bffc754979d72dfb2501c9325dd31f5526 Mon Sep 17 00:00:00 2001 From: regneq Date: Mon, 11 Aug 2025 13:49:59 -0700 Subject: [PATCH 016/194] [Bug Fix] Fix Race 474 for Titanium (#4979) --- common/patches/titanium.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 19d93addb2..c93b925814 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1059,7 +1059,7 @@ namespace Titanium OUT(spawnid); OUT_str(charname); - if (emu->race > 473) + if (emu->race > 474) eq->race = 1; else OUT(race); @@ -1840,7 +1840,7 @@ namespace Titanium emu_cse = (CharacterSelectEntry_Struct *)emu_ptr; eq->Race[char_index] = emu_cse->Race; - if (eq->Race[char_index] > 473) + if (eq->Race[char_index] > 474) eq->Race[char_index] = 1; for (int index = 0; index < EQ::textures::materialCount; ++index) { @@ -2421,7 +2421,7 @@ namespace Titanium strcpy(eq->title, emu->title); // eq->unknown0274 = emu->unknown0274; eq->helm = emu->helm; - if (emu->race > 473) + if (emu->race > 474) eq->race = 1; else eq->race = emu->race; From 4d12dd5c43f497b4d8827217b5b2ba32968fe3ba Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 15 Aug 2025 21:36:35 -0700 Subject: [PATCH 017/194] [Code] Remove Attributions (#4988) --- common/CMakeLists.txt | 16 +- common/eq_stream_intf.h | 12 +- common/net/eqstream.cpp | 22 +- common/net/eqstream.h | 16 +- ...ion.cpp => reliable_stream_connection.cpp} | 204 +++++++++--------- ...nection.h => reliable_stream_connection.h} | 92 ++++---- ...ak_pooling.h => reliable_stream_pooling.h} | 0 ...ak_structs.h => reliable_stream_structs.h} | 20 +- common/spdat.h | 2 +- hc/eq.cpp | 20 +- hc/eq.h | 26 +-- hc/login.cpp | 10 +- hc/login.h | 14 +- hc/world.cpp | 10 +- hc/world.h | 14 +- loginserver/account_management.cpp | 20 +- loginserver/client.h | 6 +- ucs/clientlist.cpp | 10 +- world/main.cpp | 10 +- zone/api_service.cpp | 2 +- zone/attack.cpp | 8 +- zone/gm_commands/show/network.cpp | 42 ++-- zone/gm_commands/show/network_stats.cpp | 10 +- zone/main.cpp | 10 +- 24 files changed, 298 insertions(+), 298 deletions(-) rename common/net/{daybreak_connection.cpp => reliable_stream_connection.cpp} (82%) rename common/net/{daybreak_connection.h => reliable_stream_connection.h} (72%) rename common/net/{daybreak_pooling.h => reliable_stream_pooling.h} (100%) rename common/net/{daybreak_structs.h => reliable_stream_structs.h} (86%) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 0921cec5f0..2a3c3ad723 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -104,9 +104,9 @@ SET(common_sources net/console_server.cpp net/console_server_connection.cpp net/crc32.cpp - net/daybreak_connection.cpp net/eqstream.cpp net/packet.cpp + net/reliable_stream_connection.cpp net/servertalk_client_connection.cpp net/servertalk_legacy_client_connection.cpp net/servertalk_server.cpp @@ -671,13 +671,13 @@ SET(common_headers net/console_server.h net/console_server_connection.h net/crc32.h - net/daybreak_connection.h - net/daybreak_pooling.h - net/daybreak_structs.h net/dns.h net/endian.h net/eqstream.h net/packet.h + net/reliable_stream_connection.h + net/reliable_stream_pooling.h + net/reliable_stream_structs.h net/servertalk_client_connection.h net/servertalk_legacy_client_connection.h net/servertalk_common.h @@ -743,10 +743,6 @@ SOURCE_GROUP(Net FILES net/console_server_connection.h net/crc32.cpp net/crc32.h - net/daybreak_connection.cpp - net/daybreak_connection.h - net/daybreak_pooling.h - net/daybreak_structs.h net/dns.h net/endian.h net/eqmq.cpp @@ -755,6 +751,10 @@ SOURCE_GROUP(Net FILES net/eqstream.h net/packet.cpp net/packet.h + net/reliable_stream_connection.cpp + net/reliable_stream_connection.h + net/reliable_stream_pooling.h + net/reliable_stream_structs.h net/servertalk_client_connection.cpp net/servertalk_client_connection.h net/servertalk_legacy_client_connection.cpp diff --git a/common/eq_stream_intf.h b/common/eq_stream_intf.h index e2b7b21c7d..5b2d24c825 100644 --- a/common/eq_stream_intf.h +++ b/common/eq_stream_intf.h @@ -6,7 +6,7 @@ #include #include "emu_versions.h" #include "eq_packet.h" -#include "net/daybreak_connection.h" +#include "net/reliable_stream_connection.h" typedef enum { ESTABLISHED, @@ -33,18 +33,18 @@ struct EQStreamManagerInterfaceOptions //Login I had trouble getting to recognize compression at all //but that might be because it was still a bit buggy when i was testing that. if (compressed) { - daybreak_options.encode_passes[0] = EQ::Net::EncodeCompression; + reliable_stream_options.encode_passes[0] = EQ::Net::EncodeCompression; } else if (encoded) { - daybreak_options.encode_passes[0] = EQ::Net::EncodeXOR; + reliable_stream_options.encode_passes[0] = EQ::Net::EncodeXOR; } - daybreak_options.port = port; + reliable_stream_options.port = port; } int opcode_size; bool track_opcode_stats; - EQ::Net::DaybreakConnectionManagerOptions daybreak_options; + EQ::Net::ReliableStreamConnectionManagerOptions reliable_stream_options; }; class EQStreamManagerInterface @@ -80,7 +80,7 @@ class EQStreamInterface { struct Stats { - EQ::Net::DaybreakConnectionStats DaybreakStats; + EQ::Net::ReliableStreamConnectionStats ReliableStreamStats; int RecvCount[_maxEmuOpcode]; int SentCount[_maxEmuOpcode]; }; diff --git a/common/net/eqstream.cpp b/common/net/eqstream.cpp index 0e3c671d72..633dea4c9a 100644 --- a/common/net/eqstream.cpp +++ b/common/net/eqstream.cpp @@ -1,11 +1,11 @@ #include "eqstream.h" #include "../eqemu_logsys.h" -EQ::Net::EQStreamManager::EQStreamManager(const EQStreamManagerInterfaceOptions &options) : EQStreamManagerInterface(options), m_daybreak(options.daybreak_options) +EQ::Net::EQStreamManager::EQStreamManager(const EQStreamManagerInterfaceOptions &options) : EQStreamManagerInterface(options), m_reliable_stream(options.reliable_stream_options) { - m_daybreak.OnNewConnection(std::bind(&EQStreamManager::DaybreakNewConnection, this, std::placeholders::_1)); - m_daybreak.OnConnectionStateChange(std::bind(&EQStreamManager::DaybreakConnectionStateChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - m_daybreak.OnPacketRecv(std::bind(&EQStreamManager::DaybreakPacketRecv, this, std::placeholders::_1, std::placeholders::_2)); + m_reliable_stream.OnNewConnection(std::bind(&EQStreamManager::ReliableStreamNewConnection, this, std::placeholders::_1)); + m_reliable_stream.OnConnectionStateChange(std::bind(&EQStreamManager::ReliableStreamConnectionStateChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + m_reliable_stream.OnPacketRecv(std::bind(&EQStreamManager::ReliableStreamPacketRecv, this, std::placeholders::_1, std::placeholders::_2)); } EQ::Net::EQStreamManager::~EQStreamManager() @@ -15,11 +15,11 @@ EQ::Net::EQStreamManager::~EQStreamManager() void EQ::Net::EQStreamManager::SetOptions(const EQStreamManagerInterfaceOptions &options) { m_options = options; - auto &opts = m_daybreak.GetOptions(); - opts = options.daybreak_options; + auto &opts = m_reliable_stream.GetOptions(); + opts = options.reliable_stream_options; } -void EQ::Net::EQStreamManager::DaybreakNewConnection(std::shared_ptr connection) +void EQ::Net::EQStreamManager::ReliableStreamNewConnection(std::shared_ptr connection) { std::shared_ptr stream(new EQStream(this, connection)); m_streams.emplace(std::make_pair(connection, stream)); @@ -28,7 +28,7 @@ void EQ::Net::EQStreamManager::DaybreakNewConnection(std::shared_ptr connection, DbProtocolStatus from, DbProtocolStatus to) +void EQ::Net::EQStreamManager::ReliableStreamConnectionStateChange(std::shared_ptr connection, DbProtocolStatus from, DbProtocolStatus to) { auto iter = m_streams.find(connection); if (iter != m_streams.end()) { @@ -42,7 +42,7 @@ void EQ::Net::EQStreamManager::DaybreakConnectionStateChange(std::shared_ptr connection, const Packet &p) +void EQ::Net::EQStreamManager::ReliableStreamPacketRecv(std::shared_ptr connection, const Packet &p) { auto iter = m_streams.find(connection); if (iter != m_streams.end()) { @@ -53,7 +53,7 @@ void EQ::Net::EQStreamManager::DaybreakPacketRecv(std::shared_ptr connection) +EQ::Net::EQStream::EQStream(EQStreamManagerInterface *owner, std::shared_ptr connection) { m_owner = owner; m_connection = connection; @@ -235,7 +235,7 @@ EQStreamState EQ::Net::EQStream::GetState() { EQ::Net::EQStream::Stats EQ::Net::EQStream::GetStats() const { Stats ret; - ret.DaybreakStats = m_connection->GetStats(); + ret.ReliableStreamStats = m_connection->GetStats(); for (int i = 0; i < _maxEmuOpcode; ++i) { ret.RecvCount[i] = 0; diff --git a/common/net/eqstream.h b/common/net/eqstream.h index a87c6ec0b1..4a8e6ddd98 100644 --- a/common/net/eqstream.h +++ b/common/net/eqstream.h @@ -3,7 +3,7 @@ #include "../eq_packet.h" #include "../eq_stream_intf.h" #include "../opcodemgr.h" -#include "daybreak_connection.h" +#include "reliable_stream_connection.h" #include #include #include @@ -23,21 +23,21 @@ namespace EQ void OnNewConnection(std::function)> func) { m_on_new_connection = func; } void OnConnectionStateChange(std::function, DbProtocolStatus, DbProtocolStatus)> func) { m_on_connection_state_change = func; } private: - DaybreakConnectionManager m_daybreak; + ReliableStreamConnectionManager m_reliable_stream; std::function)> m_on_new_connection; std::function, DbProtocolStatus, DbProtocolStatus)> m_on_connection_state_change; - std::map, std::shared_ptr> m_streams; + std::map, std::shared_ptr> m_streams; - void DaybreakNewConnection(std::shared_ptr connection); - void DaybreakConnectionStateChange(std::shared_ptr connection, DbProtocolStatus from, DbProtocolStatus to); - void DaybreakPacketRecv(std::shared_ptr connection, const Packet &p); + void ReliableStreamNewConnection(std::shared_ptr connection); + void ReliableStreamConnectionStateChange(std::shared_ptr connection, DbProtocolStatus from, DbProtocolStatus to); + void ReliableStreamPacketRecv(std::shared_ptr connection, const Packet &p); friend class EQStream; }; class EQStream : public EQStreamInterface { public: - EQStream(EQStreamManagerInterface *parent, std::shared_ptr connection); + EQStream(EQStreamManagerInterface *parent, std::shared_ptr connection); ~EQStream(); virtual void QueuePacket(const EQApplicationPacket *p, bool ack_req = true); @@ -67,7 +67,7 @@ namespace EQ virtual EQStreamManagerInterface* GetManager() const; private: EQStreamManagerInterface *m_owner; - std::shared_ptr m_connection; + std::shared_ptr m_connection; OpcodeManager **m_opcode_manager; std::deque> m_packet_queue; std::unordered_map m_packet_recv_count; diff --git a/common/net/daybreak_connection.cpp b/common/net/reliable_stream_connection.cpp similarity index 82% rename from common/net/daybreak_connection.cpp rename to common/net/reliable_stream_connection.cpp index 9d40eadb89..e1101f452e 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/reliable_stream_connection.cpp @@ -1,4 +1,4 @@ -#include "daybreak_connection.h" +#include "reliable_stream_connection.h" #include "../event/event_loop.h" #include "../data_verification.h" #include "crc32.h" @@ -12,7 +12,7 @@ constexpr size_t MAX_CLIENT_RECV_BYTES_PER_WINDOW = 140 * 1024; // buffer pools SendBufferPool send_buffer_pool; -EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager() +EQ::Net::ReliableStreamConnectionManager::ReliableStreamConnectionManager() { m_attached = nullptr; memset(&m_timer, 0, sizeof(uv_timer_t)); @@ -21,7 +21,7 @@ EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager() Attach(EQ::EventLoop::Get().Handle()); } -EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager(const DaybreakConnectionManagerOptions &opts) +EQ::Net::ReliableStreamConnectionManager::ReliableStreamConnectionManager(const ReliableStreamConnectionManagerOptions &opts) { m_attached = nullptr; m_options = opts; @@ -31,12 +31,12 @@ EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager(const DaybreakConn Attach(EQ::EventLoop::Get().Handle()); } -EQ::Net::DaybreakConnectionManager::~DaybreakConnectionManager() +EQ::Net::ReliableStreamConnectionManager::~ReliableStreamConnectionManager() { Detach(); } -void EQ::Net::DaybreakConnectionManager::Attach(uv_loop_t *loop) +void EQ::Net::ReliableStreamConnectionManager::Attach(uv_loop_t *loop) { if (!m_attached) { uv_timer_init(loop, &m_timer); @@ -45,7 +45,7 @@ void EQ::Net::DaybreakConnectionManager::Attach(uv_loop_t *loop) auto update_rate = (uint64_t)(1000.0 / m_options.tic_rate_hertz); uv_timer_start(&m_timer, [](uv_timer_t *handle) { - DaybreakConnectionManager *c = (DaybreakConnectionManager*)handle->data; + ReliableStreamConnectionManager *c = (ReliableStreamConnectionManager*)handle->data; c->UpdateDataBudget(); c->Process(); c->ProcessResend(); @@ -71,7 +71,7 @@ void EQ::Net::DaybreakConnectionManager::Attach(uv_loop_t *loop) buf->len = 65536; }, [](uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) { - DaybreakConnectionManager *c = (DaybreakConnectionManager*)handle->data; + ReliableStreamConnectionManager *c = (ReliableStreamConnectionManager*)handle->data; if (nread < 0 || addr == nullptr) { return; } @@ -90,7 +90,7 @@ void EQ::Net::DaybreakConnectionManager::Attach(uv_loop_t *loop) } } -void EQ::Net::DaybreakConnectionManager::Detach() +void EQ::Net::ReliableStreamConnectionManager::Detach() { if (m_attached) { uv_udp_recv_stop(&m_socket); @@ -99,11 +99,11 @@ void EQ::Net::DaybreakConnectionManager::Detach() } } -void EQ::Net::DaybreakConnectionManager::Connect(const std::string &addr, int port) +void EQ::Net::ReliableStreamConnectionManager::Connect(const std::string &addr, int port) { //todo dns resolution - auto connection = std::shared_ptr(new DaybreakConnection(this, addr, port)); + auto connection = std::shared_ptr(new ReliableStreamConnection(this, addr, port)); connection->m_self = connection; if (m_on_new_connection) { @@ -113,7 +113,7 @@ void EQ::Net::DaybreakConnectionManager::Connect(const std::string &addr, int po m_connections.emplace(std::make_pair(std::make_pair(addr, port), connection)); } -void EQ::Net::DaybreakConnectionManager::Process() +void EQ::Net::ReliableStreamConnectionManager::Process() { auto now = Clock::now(); auto iter = m_connections.begin(); @@ -177,7 +177,7 @@ void EQ::Net::DaybreakConnectionManager::Process() } } -void EQ::Net::DaybreakConnectionManager::UpdateDataBudget() +void EQ::Net::ReliableStreamConnectionManager::UpdateDataBudget() { auto outgoing_data_rate = m_options.outgoing_data_rate; if (outgoing_data_rate <= 0.0) { @@ -196,7 +196,7 @@ void EQ::Net::DaybreakConnectionManager::UpdateDataBudget() } } -void EQ::Net::DaybreakConnectionManager::ProcessResend() +void EQ::Net::ReliableStreamConnectionManager::ProcessResend() { auto iter = m_connections.begin(); while (iter != m_connections.end()) { @@ -217,15 +217,15 @@ void EQ::Net::DaybreakConnectionManager::ProcessResend() } } -void EQ::Net::DaybreakConnectionManager::ProcessPacket(const std::string &endpoint, int port, const char *data, size_t size) +void EQ::Net::ReliableStreamConnectionManager::ProcessPacket(const std::string &endpoint, int port, const char *data, size_t size) { if (m_options.simulated_in_packet_loss && m_options.simulated_in_packet_loss >= m_rand.Int(0, 100)) { return; } - if (size < DaybreakHeader::size()) { + if (size < ReliableStreamHeader::size()) { if (m_on_error_message) { - m_on_error_message(fmt::format("Packet of size {0} which is less than {1}", size, DaybreakHeader::size())); + m_on_error_message(fmt::format("Packet of size {0} which is less than {1}", size, ReliableStreamHeader::size())); } return; } @@ -239,9 +239,9 @@ void EQ::Net::DaybreakConnectionManager::ProcessPacket(const std::string &endpoi else { if (data[0] == 0 && data[1] == OP_SessionRequest) { StaticPacket p((void*)data, size); - auto request = p.GetSerialize(0); + auto request = p.GetSerialize(0); - connection = std::shared_ptr(new DaybreakConnection(this, request, endpoint, port)); + connection = std::shared_ptr(new ReliableStreamConnection(this, request, endpoint, port)); connection->m_self = connection; if (m_on_new_connection) { @@ -262,7 +262,7 @@ void EQ::Net::DaybreakConnectionManager::ProcessPacket(const std::string &endpoi } } -std::shared_ptr EQ::Net::DaybreakConnectionManager::FindConnectionByEndpoint(std::string addr, int port) +std::shared_ptr EQ::Net::ReliableStreamConnectionManager::FindConnectionByEndpoint(std::string addr, int port) { auto p = std::make_pair(addr, port); auto iter = m_connections.find(p); @@ -273,9 +273,9 @@ std::shared_ptr EQ::Net::DaybreakConnectionManager: return nullptr; } -void EQ::Net::DaybreakConnectionManager::SendDisconnect(const std::string &addr, int port) +void EQ::Net::ReliableStreamConnectionManager::SendDisconnect(const std::string &addr, int port) { - DaybreakDisconnect header; + ReliableStreamDisconnect header; header.zero = 0; header.opcode = OP_OutOfSession; header.connect_code = 0; @@ -300,7 +300,7 @@ void EQ::Net::DaybreakConnectionManager::SendDisconnect(const std::string &addr, } //new connection made as server -EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner, const DaybreakConnect &connect, const std::string &endpoint, int port) +EQ::Net::ReliableStreamConnection::ReliableStreamConnection(ReliableStreamConnectionManager *owner, const ReliableStreamConnect &connect, const std::string &endpoint, int port) { m_owner = owner; m_last_send = Clock::now(); @@ -327,7 +327,7 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner } //new connection made as client -EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner, const std::string &endpoint, int port) +EQ::Net::ReliableStreamConnection::ReliableStreamConnection(ReliableStreamConnectionManager *owner, const std::string &endpoint, int port) { m_owner = owner; m_last_send = Clock::now(); @@ -349,11 +349,11 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_outgoing_budget = owner->m_options.outgoing_data_rate; } -EQ::Net::DaybreakConnection::~DaybreakConnection() +EQ::Net::ReliableStreamConnection::~ReliableStreamConnection() { } -void EQ::Net::DaybreakConnection::Close() +void EQ::Net::ReliableStreamConnection::Close() { if (m_status != StatusDisconnected && m_status != StatusDisconnecting) { FlushBuffer(); @@ -367,17 +367,17 @@ void EQ::Net::DaybreakConnection::Close() ChangeStatus(StatusDisconnecting); } -void EQ::Net::DaybreakConnection::QueuePacket(Packet &p) +void EQ::Net::ReliableStreamConnection::QueuePacket(Packet &p) { QueuePacket(p, 0, true); } -void EQ::Net::DaybreakConnection::QueuePacket(Packet &p, int stream) +void EQ::Net::ReliableStreamConnection::QueuePacket(Packet &p, int stream) { QueuePacket(p, stream, true); } -void EQ::Net::DaybreakConnection::QueuePacket(Packet &p, int stream, bool reliable) +void EQ::Net::ReliableStreamConnection::QueuePacket(Packet &p, int stream, bool reliable) { if (*(char*)p.Data() == 0) { DynamicPacket packet; @@ -390,21 +390,21 @@ void EQ::Net::DaybreakConnection::QueuePacket(Packet &p, int stream, bool reliab InternalQueuePacket(p, stream, reliable); } -EQ::Net::DaybreakConnectionStats EQ::Net::DaybreakConnection::GetStats() +EQ::Net::ReliableStreamConnectionStats EQ::Net::ReliableStreamConnection::GetStats() { - EQ::Net::DaybreakConnectionStats ret = m_stats; + EQ::Net::ReliableStreamConnectionStats ret = m_stats; ret.datarate_remaining = m_outgoing_budget; ret.avg_ping = m_rolling_ping; return ret; } -void EQ::Net::DaybreakConnection::ResetStats() +void EQ::Net::ReliableStreamConnection::ResetStats() { m_stats.Reset(); } -void EQ::Net::DaybreakConnection::Process() +void EQ::Net::ReliableStreamConnection::Process() { try { auto now = Clock::now(); @@ -422,7 +422,7 @@ void EQ::Net::DaybreakConnection::Process() } } -void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) +void EQ::Net::ReliableStreamConnection::ProcessPacket(Packet &p) { m_last_recv = Clock::now(); m_stats.recv_packets++; @@ -458,13 +458,13 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) switch (m_encode_passes[i]) { case EncodeCompression: if(temp.GetInt8(0) == 0) - Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + Decompress(temp, ReliableStreamHeader::size(), temp.Length() - ReliableStreamHeader::size()); else Decompress(temp, 1, temp.Length() - 1); break; case EncodeXOR: if (temp.GetInt8(0) == 0) - Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + Decode(temp, ReliableStreamHeader::size(), temp.Length() - ReliableStreamHeader::size()); else Decode(temp, 1, temp.Length() - 1); break; @@ -483,7 +483,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) switch (m_encode_passes[i]) { case EncodeXOR: if (temp.GetInt8(0) == 0) - Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + Decode(temp, ReliableStreamHeader::size(), temp.Length() - ReliableStreamHeader::size()); else Decode(temp, 1, temp.Length() - 1); break; @@ -502,7 +502,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) } } -void EQ::Net::DaybreakConnection::ProcessQueue() +void EQ::Net::ReliableStreamConnection::ProcessQueue() { for (int i = 0; i < 4; ++i) { auto stream = &m_streams[i]; @@ -521,7 +521,7 @@ void EQ::Net::DaybreakConnection::ProcessQueue() } } -void EQ::Net::DaybreakConnection::RemoveFromQueue(int stream, uint16_t seq) +void EQ::Net::ReliableStreamConnection::RemoveFromQueue(int stream, uint16_t seq) { auto s = &m_streams[stream]; auto iter = s->packet_queue.find(seq); @@ -532,7 +532,7 @@ void EQ::Net::DaybreakConnection::RemoveFromQueue(int stream, uint16_t seq) } } -void EQ::Net::DaybreakConnection::AddToQueue(int stream, uint16_t seq, const Packet &p) +void EQ::Net::ReliableStreamConnection::AddToQueue(int stream, uint16_t seq, const Packet &p) { auto s = &m_streams[stream]; auto iter = s->packet_queue.find(seq); @@ -544,7 +544,7 @@ void EQ::Net::DaybreakConnection::AddToQueue(int stream, uint16_t seq, const Pac } } -void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) +void EQ::Net::ReliableStreamConnection::ProcessDecodedPacket(const Packet &p) { if (p.GetInt8(0) == 0) { if (p.Length() < 2) { @@ -628,13 +628,13 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) case OP_SessionRequest: { if (m_status == StatusConnected) { - auto request = p.GetSerialize(0); + auto request = p.GetSerialize(0); if (NetworkToHost(request.connect_code) != m_connect_code) { return; } - DaybreakConnectReply reply; + ReliableStreamConnectReply reply; reply.zero = 0; reply.opcode = OP_SessionResponse; reply.connect_code = HostToNetwork(m_connect_code); @@ -656,13 +656,13 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) case OP_SessionResponse: { if (m_status == StatusConnecting) { - auto reply = p.GetSerialize(0); + auto reply = p.GetSerialize(0); if (m_connect_code == reply.connect_code) { m_encode_key = reply.encode_key; m_crc_bytes = reply.crc_bytes; - m_encode_passes[0] = (DaybreakEncodeType)reply.encode_pass1; - m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2; + m_encode_passes[0] = (ReliableStreamEncodeType)reply.encode_pass1; + m_encode_passes[1] = (ReliableStreamEncodeType)reply.encode_pass2; m_max_packet_size = reply.max_packet_size; ChangeStatus(StatusConnected); @@ -686,7 +686,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) return; } - auto header = p.GetSerialize(0); + auto header = p.GetSerialize(0); auto sequence = NetworkToHost(header.sequence); auto stream_id = header.opcode - OP_Packet; auto stream = &m_streams[stream_id]; @@ -703,7 +703,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) RemoveFromQueue(stream_id, sequence); SendAck(stream_id, stream->sequence_in); stream->sequence_in++; - StaticPacket next((char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size()); + StaticPacket next((char*)p.Data() + ReliableStreamReliableHeader::size(), p.Length() - ReliableStreamReliableHeader::size()); ProcessDecodedPacket(next); } @@ -715,7 +715,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) case OP_Fragment3: case OP_Fragment4: { - auto header = p.GetSerialize(0); + auto header = p.GetSerialize(0); auto sequence = NetworkToHost(header.sequence); auto stream_id = header.opcode - OP_Fragment; auto stream = &m_streams[stream_id]; @@ -735,22 +735,22 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) stream->sequence_in++; if (stream->fragment_total_bytes == 0) { - auto fragheader = p.GetSerialize(0); + auto fragheader = p.GetSerialize(0); stream->fragment_total_bytes = NetworkToHost(fragheader.total_size); stream->fragment_current_bytes = 0; stream->fragment_packet.Reserve(stream->fragment_total_bytes); stream->fragment_packet.PutData( stream->fragment_current_bytes, - (char*)p.Data() + DaybreakReliableFragmentHeader::size(), p.Length() - DaybreakReliableFragmentHeader::size()); + (char*)p.Data() + ReliableStreamReliableFragmentHeader::size(), p.Length() - ReliableStreamReliableFragmentHeader::size()); - stream->fragment_current_bytes += (uint32_t)(p.Length() - DaybreakReliableFragmentHeader::size()); + stream->fragment_current_bytes += (uint32_t)(p.Length() - ReliableStreamReliableFragmentHeader::size()); } else { stream->fragment_packet.PutData( stream->fragment_current_bytes, - (char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size()); + (char*)p.Data() + ReliableStreamReliableHeader::size(), p.Length() - ReliableStreamReliableHeader::size()); - stream->fragment_current_bytes += (uint32_t)(p.Length() - DaybreakReliableHeader::size()); + stream->fragment_current_bytes += (uint32_t)(p.Length() - ReliableStreamReliableHeader::size()); if (stream->fragment_current_bytes >= stream->fragment_total_bytes) { ProcessDecodedPacket(stream->fragment_packet); @@ -769,7 +769,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) case OP_Ack3: case OP_Ack4: { - auto header = p.GetSerialize(0); + auto header = p.GetSerialize(0); auto sequence = NetworkToHost(header.sequence); auto stream_id = header.opcode - OP_Ack; Ack(stream_id, sequence); @@ -781,7 +781,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) case OP_OutOfOrderAck3: case OP_OutOfOrderAck4: { - auto header = p.GetSerialize(0); + auto header = p.GetSerialize(0); auto sequence = NetworkToHost(header.sequence); auto stream_id = header.opcode - OP_OutOfOrderAck; OutOfOrderAck(stream_id, sequence); @@ -815,13 +815,13 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) } case OP_SessionStatRequest: { - auto request = p.GetSerialize(0); + auto request = p.GetSerialize(0); m_stats.sync_remote_sent_packets = EQ::Net::NetworkToHost(request.packets_sent); m_stats.sync_remote_recv_packets = EQ::Net::NetworkToHost(request.packets_recv); m_stats.sync_sent_packets = m_stats.sent_packets; m_stats.sync_recv_packets = m_stats.recv_packets; - DaybreakSessionStatResponse response; + ReliableStreamSessionStatResponse response; response.zero = 0; response.opcode = OP_SessionStatResponse; response.timestamp = request.timestamp; @@ -836,7 +836,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) break; } case OP_SessionStatResponse: { - auto response = p.GetSerialize(0); + auto response = p.GetSerialize(0); m_stats.sync_remote_sent_packets = EQ::Net::NetworkToHost(response.server_sent); m_stats.sync_remote_recv_packets = EQ::Net::NetworkToHost(response.server_recv); m_stats.sync_sent_packets = m_stats.sent_packets; @@ -858,7 +858,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) } } -bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p) +bool EQ::Net::ReliableStreamConnection::ValidateCRC(Packet &p) { if (m_crc_bytes == 0U) { return true; @@ -892,7 +892,7 @@ bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p) return false; } -void EQ::Net::DaybreakConnection::AppendCRC(Packet &p) +void EQ::Net::ReliableStreamConnection::AppendCRC(Packet &p) { if (m_crc_bytes == 0U) { return; @@ -911,7 +911,7 @@ void EQ::Net::DaybreakConnection::AppendCRC(Packet &p) } } -void EQ::Net::DaybreakConnection::ChangeStatus(DbProtocolStatus new_status) +void EQ::Net::ReliableStreamConnection::ChangeStatus(DbProtocolStatus new_status) { if (m_owner->m_on_connection_state_change) { if (auto self = m_self.lock()) { @@ -922,7 +922,7 @@ void EQ::Net::DaybreakConnection::ChangeStatus(DbProtocolStatus new_status) m_status = new_status; } -bool EQ::Net::DaybreakConnection::PacketCanBeEncoded(Packet &p) const +bool EQ::Net::ReliableStreamConnection::PacketCanBeEncoded(Packet &p) const { if (p.Length() < 2) { return false; @@ -941,7 +941,7 @@ bool EQ::Net::DaybreakConnection::PacketCanBeEncoded(Packet &p) const return true; } -void EQ::Net::DaybreakConnection::Decode(Packet &p, size_t offset, size_t length) +void EQ::Net::ReliableStreamConnection::Decode(Packet &p, size_t offset, size_t length) { int key = m_encode_key; char *buffer = (char*)p.Data() + offset; @@ -961,7 +961,7 @@ void EQ::Net::DaybreakConnection::Decode(Packet &p, size_t offset, size_t length } } -void EQ::Net::DaybreakConnection::Encode(Packet &p, size_t offset, size_t length) +void EQ::Net::ReliableStreamConnection::Encode(Packet &p, size_t offset, size_t length) { int key = m_encode_key; char *buffer = (char*)p.Data() + offset; @@ -1050,7 +1050,7 @@ uint32_t Deflate(const uint8_t* in, uint32_t in_len, uint8_t* out, uint32_t out_ } } -void EQ::Net::DaybreakConnection::Decompress(Packet &p, size_t offset, size_t length) +void EQ::Net::ReliableStreamConnection::Decompress(Packet &p, size_t offset, size_t length) { if (length < 2) { return; @@ -1075,7 +1075,7 @@ void EQ::Net::DaybreakConnection::Decompress(Packet &p, size_t offset, size_t le p.PutData(offset, new_buffer, new_length); } -void EQ::Net::DaybreakConnection::Compress(Packet &p, size_t offset, size_t length) +void EQ::Net::ReliableStreamConnection::Compress(Packet &p, size_t offset, size_t length) { static thread_local uint8_t new_buffer[2048] = { 0 }; uint8_t *buffer = (uint8_t*)p.Data() + offset; @@ -1097,14 +1097,14 @@ void EQ::Net::DaybreakConnection::Compress(Packet &p, size_t offset, size_t leng p.PutData(offset, new_buffer, new_length); } -void EQ::Net::DaybreakConnection::ProcessResend() +void EQ::Net::ReliableStreamConnection::ProcessResend() { for (int i = 0; i < 4; ++i) { ProcessResend(i); } } -void EQ::Net::DaybreakConnection::ProcessResend(int stream) +void EQ::Net::ReliableStreamConnection::ProcessResend(int stream) { if (m_status == DbProtocolStatus::StatusDisconnected) { return; @@ -1201,7 +1201,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) auto &sp = e.second; auto &p = sp.packet; - if (p.Length() >= DaybreakHeader::size()) { + if (p.Length() >= ReliableStreamHeader::size()) { if (p.GetInt8(0) == 0 && p.GetInt8(1) >= OP_Fragment && p.GetInt8(1) <= OP_Fragment4) { m_stats.resent_fragments++; } @@ -1232,7 +1232,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) m_last_ack = now; } -void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) +void EQ::Net::ReliableStreamConnection::Ack(int stream, uint16_t seq) { auto now = Clock::now(); auto s = &m_streams[stream]; @@ -1259,7 +1259,7 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) m_last_ack = now; } -void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) +void EQ::Net::ReliableStreamConnection::OutOfOrderAck(int stream, uint16_t seq) { auto now = Clock::now(); auto s = &m_streams[stream]; @@ -1279,15 +1279,15 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) m_last_ack = now; } -void EQ::Net::DaybreakConnection::UpdateDataBudget(double budget_add) +void EQ::Net::ReliableStreamConnection::UpdateDataBudget(double budget_add) { auto outgoing_data_rate = m_owner->m_options.outgoing_data_rate; m_outgoing_budget = EQ::ClampUpper(m_outgoing_budget + budget_add, outgoing_data_rate); } -void EQ::Net::DaybreakConnection::SendAck(int stream_id, uint16_t seq) +void EQ::Net::ReliableStreamConnection::SendAck(int stream_id, uint16_t seq) { - DaybreakReliableHeader ack; + ReliableStreamReliableHeader ack; ack.zero = 0; ack.opcode = OP_Ack + stream_id; ack.sequence = HostToNetwork(seq); @@ -1298,9 +1298,9 @@ void EQ::Net::DaybreakConnection::SendAck(int stream_id, uint16_t seq) InternalBufferedSend(p); } -void EQ::Net::DaybreakConnection::SendOutOfOrderAck(int stream_id, uint16_t seq) +void EQ::Net::ReliableStreamConnection::SendOutOfOrderAck(int stream_id, uint16_t seq) { - DaybreakReliableHeader ack; + ReliableStreamReliableHeader ack; ack.zero = 0; ack.opcode = OP_OutOfOrderAck + stream_id; ack.sequence = HostToNetwork(seq); @@ -1311,9 +1311,9 @@ void EQ::Net::DaybreakConnection::SendOutOfOrderAck(int stream_id, uint16_t seq) InternalBufferedSend(p); } -void EQ::Net::DaybreakConnection::SendDisconnect() +void EQ::Net::ReliableStreamConnection::SendDisconnect() { - DaybreakDisconnect disconnect; + ReliableStreamDisconnect disconnect; disconnect.zero = 0; disconnect.opcode = OP_SessionDisconnect; disconnect.connect_code = HostToNetwork(m_connect_code); @@ -1322,7 +1322,7 @@ void EQ::Net::DaybreakConnection::SendDisconnect() InternalSend(out); } -void EQ::Net::DaybreakConnection::InternalBufferedSend(Packet &p) +void EQ::Net::ReliableStreamConnection::InternalBufferedSend(Packet &p) { if (p.Length() > 0xFFU) { FlushBuffer(); @@ -1331,7 +1331,7 @@ void EQ::Net::DaybreakConnection::InternalBufferedSend(Packet &p) } //we could add this packet to a combined - size_t raw_size = DaybreakHeader::size() + (size_t)m_crc_bytes + m_buffered_packets_length + m_buffered_packets.size() + 1 + p.Length(); + size_t raw_size = ReliableStreamHeader::size() + (size_t)m_crc_bytes + m_buffered_packets_length + m_buffered_packets.size() + 1 + p.Length(); if (raw_size > m_max_packet_size) { FlushBuffer(); } @@ -1346,9 +1346,9 @@ void EQ::Net::DaybreakConnection::InternalBufferedSend(Packet &p) } } -void EQ::Net::DaybreakConnection::SendConnect() +void EQ::Net::ReliableStreamConnection::SendConnect() { - DaybreakConnect connect; + ReliableStreamConnect connect; connect.zero = 0; connect.opcode = OP_SessionRequest; connect.protocol_version = HostToNetwork(3U); @@ -1361,9 +1361,9 @@ void EQ::Net::DaybreakConnection::SendConnect() InternalSend(p); } -void EQ::Net::DaybreakConnection::SendKeepAlive() +void EQ::Net::ReliableStreamConnection::SendKeepAlive() { - DaybreakHeader keep_alive; + ReliableStreamHeader keep_alive; keep_alive.zero = 0; keep_alive.opcode = OP_KeepAlive; @@ -1373,7 +1373,7 @@ void EQ::Net::DaybreakConnection::SendKeepAlive() InternalSend(p); } -void EQ::Net::DaybreakConnection::InternalSend(Packet &p) { +void EQ::Net::ReliableStreamConnection::InternalSend(Packet &p) { if (m_owner->m_options.outgoing_data_rate > 0.0) { auto new_budget = m_outgoing_budget - (p.Length() / 1024.0); if (new_budget <= 0.0) { @@ -1409,14 +1409,14 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p) { switch (m_encode_passe) { case EncodeCompression: if (out.GetInt8(0) == 0) { - Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); + Compress(out, ReliableStreamHeader::size(), out.Length() - ReliableStreamHeader::size()); } else { Compress(out, 1, out.Length() - 1); } break; case EncodeXOR: if (out.GetInt8(0) == 0) { - Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); + Encode(out, ReliableStreamHeader::size(), out.Length() - ReliableStreamHeader::size()); } else { Encode(out, 1, out.Length() - 1); } @@ -1466,7 +1466,7 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p) { } } -void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, bool reliable) +void EQ::Net::ReliableStreamConnection::InternalQueuePacket(Packet &p, int stream_id, bool reliable) { if (!reliable) { auto max_raw_size = 0xFFU - m_crc_bytes; @@ -1480,23 +1480,23 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, } auto stream = &m_streams[stream_id]; - auto max_raw_size = m_max_packet_size - m_crc_bytes - DaybreakReliableHeader::size() - 1; // -1 for compress flag + auto max_raw_size = m_max_packet_size - m_crc_bytes - ReliableStreamReliableHeader::size() - 1; // -1 for compress flag size_t length = p.Length(); if (length > max_raw_size) { - DaybreakReliableFragmentHeader first_header; + ReliableStreamReliableFragmentHeader first_header; first_header.reliable.zero = 0; first_header.reliable.opcode = OP_Fragment + stream_id; first_header.reliable.sequence = HostToNetwork(stream->sequence_out); first_header.total_size = (uint32_t)HostToNetwork((uint32_t)length); size_t used = 0; - size_t sublen = m_max_packet_size - m_crc_bytes - DaybreakReliableFragmentHeader::size() - 1; // -1 for compress flag + size_t sublen = m_max_packet_size - m_crc_bytes - ReliableStreamReliableFragmentHeader::size() - 1; // -1 for compress flag DynamicPacket first_packet; first_packet.PutSerialize(0, first_header); - first_packet.PutData(DaybreakReliableFragmentHeader::size(), (char*)p.Data() + used, sublen); + first_packet.PutData(ReliableStreamReliableFragmentHeader::size(), (char*)p.Data() + used, sublen); used += sublen; - DaybreakSentPacket sent; + ReliableStreamSentPacket sent; sent.packet.PutPacket(0, first_packet); sent.last_sent = Clock::now(); sent.first_sent = Clock::now(); @@ -1513,22 +1513,22 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, while (used < length) { auto left = length - used; DynamicPacket packet; - DaybreakReliableHeader header; + ReliableStreamReliableHeader header; header.zero = 0; header.opcode = OP_Fragment + stream_id; header.sequence = HostToNetwork(stream->sequence_out); packet.PutSerialize(0, header); if (left > max_raw_size) { - packet.PutData(DaybreakReliableHeader::size(), (char*)p.Data() + used, max_raw_size); + packet.PutData(ReliableStreamReliableHeader::size(), (char*)p.Data() + used, max_raw_size); used += max_raw_size; } else { - packet.PutData(DaybreakReliableHeader::size(), (char*)p.Data() + used, left); + packet.PutData(ReliableStreamReliableHeader::size(), (char*)p.Data() + used, left); used += left; } - DaybreakSentPacket sent; + ReliableStreamSentPacket sent; sent.packet.PutPacket(0, packet); sent.last_sent = Clock::now(); sent.first_sent = Clock::now(); @@ -1545,14 +1545,14 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, } else { DynamicPacket packet; - DaybreakReliableHeader header; + ReliableStreamReliableHeader header; header.zero = 0; header.opcode = OP_Packet + stream_id; header.sequence = HostToNetwork(stream->sequence_out); packet.PutSerialize(0, header); - packet.PutPacket(DaybreakReliableHeader::size(), p); + packet.PutPacket(ReliableStreamReliableHeader::size(), p); - DaybreakSentPacket sent; + ReliableStreamSentPacket sent; sent.packet.PutPacket(0, packet); sent.last_sent = Clock::now(); sent.first_sent = Clock::now(); @@ -1568,7 +1568,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, } } -void EQ::Net::DaybreakConnection::FlushBuffer() +void EQ::Net::ReliableStreamConnection::FlushBuffer() { if (m_buffered_packets.empty()) { return; @@ -1595,7 +1595,7 @@ void EQ::Net::DaybreakConnection::FlushBuffer() m_buffered_packets_length = 0; } -EQ::Net::SequenceOrder EQ::Net::DaybreakConnection::CompareSequence(uint16_t expected, uint16_t actual) const +EQ::Net::SequenceOrder EQ::Net::ReliableStreamConnection::CompareSequence(uint16_t expected, uint16_t actual) const { int diff = (int)actual - (int)expected; diff --git a/common/net/daybreak_connection.h b/common/net/reliable_stream_connection.h similarity index 72% rename from common/net/daybreak_connection.h rename to common/net/reliable_stream_connection.h index 1fddc09c98..97e1982c72 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/reliable_stream_connection.h @@ -2,8 +2,8 @@ #include "../random.h" #include "packet.h" -#include "daybreak_structs.h" -#include "daybreak_pooling.h" +#include "reliable_stream_structs.h" +#include "reliable_stream_pooling.h" #include #include #include @@ -16,7 +16,7 @@ namespace EQ { namespace Net { - enum DaybreakProtocolOpcode + enum ReliableStreamProtocolOpcode { OP_Padding = 0x00, OP_SessionRequest = 0x01, @@ -55,7 +55,7 @@ namespace EQ StatusDisconnected }; - enum DaybreakEncodeType + enum ReliableStreamEncodeType { EncodeNone = 0, EncodeCompression = 1, @@ -72,9 +72,9 @@ namespace EQ typedef std::chrono::steady_clock::time_point Timestamp; typedef std::chrono::steady_clock Clock; - struct DaybreakConnectionStats + struct ReliableStreamConnectionStats { - DaybreakConnectionStats() { + ReliableStreamConnectionStats() { recv_bytes = 0; sent_bytes = 0; recv_packets = 0; @@ -134,14 +134,14 @@ namespace EQ uint64_t bytes_before_encode; }; - class DaybreakConnectionManager; - class DaybreakConnection; - class DaybreakConnection + class ReliableStreamConnectionManager; + class ReliableStreamConnection; + class ReliableStreamConnection { public: - DaybreakConnection(DaybreakConnectionManager *owner, const DaybreakConnect &connect, const std::string &endpoint, int port); - DaybreakConnection(DaybreakConnectionManager *owner, const std::string &endpoint, int port); - ~DaybreakConnection(); + ReliableStreamConnection(ReliableStreamConnectionManager *owner, const ReliableStreamConnect &connect, const std::string &endpoint, int port); + ReliableStreamConnection(ReliableStreamConnectionManager *owner, const std::string &endpoint, int port); + ~ReliableStreamConnection(); const std::string& RemoteEndpoint() const { return m_endpoint; } int RemotePort() const { return m_port; } @@ -151,23 +151,23 @@ namespace EQ void QueuePacket(Packet &p, int stream); void QueuePacket(Packet &p, int stream, bool reliable); - DaybreakConnectionStats GetStats(); + ReliableStreamConnectionStats GetStats(); void ResetStats(); size_t GetRollingPing() const { return m_rolling_ping; } DbProtocolStatus GetStatus() const { return m_status; } - const DaybreakEncodeType* GetEncodePasses() const { return m_encode_passes; } - const DaybreakConnectionManager* GetManager() const { return m_owner; } - DaybreakConnectionManager* GetManager() { return m_owner; } + const ReliableStreamEncodeType* GetEncodePasses() const { return m_encode_passes; } + const ReliableStreamConnectionManager* GetManager() const { return m_owner; } + ReliableStreamConnectionManager* GetManager() { return m_owner; } private: - DaybreakConnectionManager *m_owner; + ReliableStreamConnectionManager *m_owner; std::string m_endpoint; int m_port; uint32_t m_connect_code; uint32_t m_encode_key; uint32_t m_max_packet_size; uint32_t m_crc_bytes; - DaybreakEncodeType m_encode_passes[2]; + ReliableStreamEncodeType m_encode_passes[2]; Timestamp m_last_send; Timestamp m_last_recv; @@ -176,7 +176,7 @@ namespace EQ std::list m_buffered_packets; size_t m_buffered_packets_length; std::unique_ptr m_combined; - DaybreakConnectionStats m_stats; + ReliableStreamConnectionStats m_stats; Timestamp m_last_session_stats; size_t m_rolling_ping; Timestamp m_close_time; @@ -188,7 +188,7 @@ namespace EQ bool m_acked_since_last_resend = false; Timestamp m_last_ack; - struct DaybreakSentPacket + struct ReliableStreamSentPacket { DynamicPacket packet; Timestamp last_sent; @@ -197,9 +197,9 @@ namespace EQ size_t resend_delay; }; - struct DaybreakStream + struct ReliableStream { - DaybreakStream() { + ReliableStream() { sequence_in = 0; sequence_out = 0; fragment_current_bytes = 0; @@ -214,11 +214,11 @@ namespace EQ uint32_t fragment_current_bytes; uint32_t fragment_total_bytes; - std::map sent_packets; + std::map sent_packets; }; - DaybreakStream m_streams[4]; - std::weak_ptr m_self; + ReliableStream m_streams[4]; + std::weak_ptr m_self; void Process(); void ProcessPacket(Packet &p); @@ -251,12 +251,12 @@ namespace EQ void FlushBuffer(); SequenceOrder CompareSequence(uint16_t expected, uint16_t actual) const; - friend class DaybreakConnectionManager; + friend class ReliableStreamConnectionManager; }; - struct DaybreakConnectionManagerOptions + struct ReliableStreamConnectionManagerOptions { - DaybreakConnectionManagerOptions() { + ReliableStreamConnectionManagerOptions() { max_connection_count = 0; keepalive_delay_ms = 9000; resend_delay_ms = 30; @@ -268,8 +268,8 @@ namespace EQ connect_stale_ms = 5000; crc_length = 2; max_packet_size = 512; - encode_passes[0] = DaybreakEncodeType::EncodeNone; - encode_passes[1] = DaybreakEncodeType::EncodeNone; + encode_passes[0] = ReliableStreamEncodeType::EncodeNone; + encode_passes[1] = ReliableStreamEncodeType::EncodeNone; port = 0; hold_size = 512; hold_length_ms = 50; @@ -299,28 +299,28 @@ namespace EQ double tic_rate_hertz; size_t resend_timeout; size_t connection_close_time; - DaybreakEncodeType encode_passes[2]; + ReliableStreamEncodeType encode_passes[2]; int port; double outgoing_data_rate; }; - class DaybreakConnectionManager + class ReliableStreamConnectionManager { public: - DaybreakConnectionManager(); - DaybreakConnectionManager(const DaybreakConnectionManagerOptions &opts); - ~DaybreakConnectionManager(); + ReliableStreamConnectionManager(); + ReliableStreamConnectionManager(const ReliableStreamConnectionManagerOptions &opts); + ~ReliableStreamConnectionManager(); void Connect(const std::string &addr, int port); void Process(); void UpdateDataBudget(); void ProcessResend(); - void OnNewConnection(std::function)> func) { m_on_new_connection = func; } - void OnConnectionStateChange(std::function, DbProtocolStatus, DbProtocolStatus)> func) { m_on_connection_state_change = func; } - void OnPacketRecv(std::function, const Packet &)> func) { m_on_packet_recv = func; } + void OnNewConnection(std::function)> func) { m_on_new_connection = func; } + void OnConnectionStateChange(std::function, DbProtocolStatus, DbProtocolStatus)> func) { m_on_connection_state_change = func; } + void OnPacketRecv(std::function, const Packet &)> func) { m_on_packet_recv = func; } void OnErrorMessage(std::function func) { m_on_error_message = func; } - DaybreakConnectionManagerOptions& GetOptions() { return m_options; } + ReliableStreamConnectionManagerOptions& GetOptions() { return m_options; } private: void Attach(uv_loop_t *loop); void Detach(); @@ -329,18 +329,18 @@ namespace EQ uv_timer_t m_timer; uv_udp_t m_socket; uv_loop_t *m_attached; - DaybreakConnectionManagerOptions m_options; - std::function)> m_on_new_connection; - std::function, DbProtocolStatus, DbProtocolStatus)> m_on_connection_state_change; - std::function, const Packet&)> m_on_packet_recv; + ReliableStreamConnectionManagerOptions m_options; + std::function)> m_on_new_connection; + std::function, DbProtocolStatus, DbProtocolStatus)> m_on_connection_state_change; + std::function, const Packet&)> m_on_packet_recv; std::function m_on_error_message; - std::map, std::shared_ptr> m_connections; + std::map, std::shared_ptr> m_connections; void ProcessPacket(const std::string &endpoint, int port, const char *data, size_t size); - std::shared_ptr FindConnectionByEndpoint(std::string addr, int port); + std::shared_ptr FindConnectionByEndpoint(std::string addr, int port); void SendDisconnect(const std::string &addr, int port); - friend class DaybreakConnection; + friend class ReliableStreamConnection; }; } } diff --git a/common/net/daybreak_pooling.h b/common/net/reliable_stream_pooling.h similarity index 100% rename from common/net/daybreak_pooling.h rename to common/net/reliable_stream_pooling.h diff --git a/common/net/daybreak_structs.h b/common/net/reliable_stream_structs.h similarity index 86% rename from common/net/daybreak_structs.h rename to common/net/reliable_stream_structs.h index 3047897b2c..f48e1f9c35 100644 --- a/common/net/daybreak_structs.h +++ b/common/net/reliable_stream_structs.h @@ -8,7 +8,7 @@ namespace EQ { namespace Net { - struct DaybreakHeader + struct ReliableStreamHeader { static size_t size() { return 2; } uint8_t zero; @@ -22,7 +22,7 @@ namespace EQ } }; - struct DaybreakConnect + struct ReliableStreamConnect { static size_t size() { return 14; } uint8_t zero; @@ -42,7 +42,7 @@ namespace EQ } }; - struct DaybreakConnectReply + struct ReliableStreamConnectReply { static size_t size() { return 17; } uint8_t zero; @@ -68,7 +68,7 @@ namespace EQ } }; - struct DaybreakDisconnect + struct ReliableStreamDisconnect { static size_t size() { return 8; } uint8_t zero; @@ -84,7 +84,7 @@ namespace EQ } }; - struct DaybreakReliableHeader + struct ReliableStreamReliableHeader { static size_t size() { return 4; } uint8_t zero; @@ -100,10 +100,10 @@ namespace EQ } }; - struct DaybreakReliableFragmentHeader + struct ReliableStreamReliableFragmentHeader { - static size_t size() { return 4 + DaybreakReliableHeader::size(); } - DaybreakReliableHeader reliable; + static size_t size() { return 4 + ReliableStreamReliableHeader::size(); } + ReliableStreamReliableHeader reliable; uint32_t total_size; template @@ -114,7 +114,7 @@ namespace EQ } }; - struct DaybreakSessionStatRequest + struct ReliableStreamSessionStatRequest { static size_t size() { return 40; } uint8_t zero; @@ -144,7 +144,7 @@ namespace EQ } }; - struct DaybreakSessionStatResponse + struct ReliableStreamSessionStatResponse { static size_t size() { return 40; } uint8_t zero; diff --git a/common/spdat.h b/common/spdat.h index afc00f4ddb..4cea6e0980 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -1057,7 +1057,7 @@ typedef enum { } DmgShieldType; //Spell Effect IDs -// https://forums.daybreakgames.com/eq/index.php?threads/enumerated-spa-list.206288/ +// https://web.archive.org/web/20250816011656/https://forums.everquest.com/index.php?threads/enumerated-spa-list.206288/ // mirror: http://pastebin.com/MYeQqGwe #define SE_CurrentHP 0 // implemented - Heals and nukes, repeates every tic if in a buff #define SE_ArmorClass 1 // implemented diff --git a/hc/eq.cpp b/hc/eq.cpp index aab481e82d..d8f2877d85 100644 --- a/hc/eq.cpp +++ b/hc/eq.cpp @@ -33,7 +33,7 @@ EverQuest::EverQuest(const std::string &host, int port, const std::string &user, } else { m_host = addr; - m_login_connection_manager.reset(new EQ::Net::DaybreakConnectionManager()); + m_login_connection_manager.reset(new EQ::Net::ReliableStreamConnectionManager()); m_login_connection_manager->OnNewConnection(std::bind(&EverQuest::LoginOnNewConnection, this, std::placeholders::_1)); m_login_connection_manager->OnConnectionStateChange(std::bind(&EverQuest::LoginOnStatusChangeReconnectEnabled, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); @@ -48,13 +48,13 @@ EverQuest::~EverQuest() { } -void EverQuest::LoginOnNewConnection(std::shared_ptr connection) +void EverQuest::LoginOnNewConnection(std::shared_ptr connection) { m_login_connection = connection; Log.OutF(Logs::General, Logs::Headless_Client, "Connecting..."); } -void EverQuest::LoginOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) +void EverQuest::LoginOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) { if (to == EQ::Net::StatusConnected) { Log.OutF(Logs::General, Logs::Headless_Client, "Login connected."); @@ -70,14 +70,14 @@ void EverQuest::LoginOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) +void EverQuest::LoginOnStatusChangeReconnectDisabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) { if (to == EQ::Net::StatusDisconnected) { m_login_connection.reset(); } } -void EverQuest::LoginOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet & p) +void EverQuest::LoginOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet & p) { auto opcode = p.GetUInt16(0); switch (opcode) { @@ -251,20 +251,20 @@ void EverQuest::LoginDisableReconnect() void EverQuest::ConnectToWorld() { - m_world_connection_manager.reset(new EQ::Net::DaybreakConnectionManager()); + m_world_connection_manager.reset(new EQ::Net::ReliableStreamConnectionManager()); m_world_connection_manager->OnNewConnection(std::bind(&EverQuest::WorldOnNewConnection, this, std::placeholders::_1)); m_world_connection_manager->OnConnectionStateChange(std::bind(&EverQuest::WorldOnStatusChangeReconnectEnabled, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); m_world_connection_manager->OnPacketRecv(std::bind(&EverQuest::WorldOnPacketRecv, this, std::placeholders::_1, std::placeholders::_2)); m_world_connection_manager->Connect(m_host, 9000); } -void EverQuest::WorldOnNewConnection(std::shared_ptr connection) +void EverQuest::WorldOnNewConnection(std::shared_ptr connection) { m_world_connection = connection; Log.OutF(Logs::General, Logs::Headless_Client, "Connecting to world..."); } -void EverQuest::WorldOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) +void EverQuest::WorldOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) { if (to == EQ::Net::StatusConnected) { Log.OutF(Logs::General, Logs::Headless_Client, "World connected."); @@ -278,14 +278,14 @@ void EverQuest::WorldOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) +void EverQuest::WorldOnStatusChangeReconnectDisabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) { if (to == EQ::Net::StatusDisconnected) { m_world_connection.reset(); } } -void EverQuest::WorldOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet & p) +void EverQuest::WorldOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet & p) { auto opcode = p.GetUInt16(0); switch (opcode) { diff --git a/hc/eq.h b/hc/eq.h index 7cdbfe1cd6..63467b3185 100644 --- a/hc/eq.h +++ b/hc/eq.h @@ -1,7 +1,7 @@ #pragma once #include "../common/eqemu_logsys.h" -#include "../common/net/daybreak_connection.h" +#include "../common/net/reliable_stream_connection.h" #include "../common/event/timer.h" #include #include @@ -26,10 +26,10 @@ class EverQuest private: //Login - void LoginOnNewConnection(std::shared_ptr connection); - void LoginOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void LoginOnStatusChangeReconnectDisabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void LoginOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p); + void LoginOnNewConnection(std::shared_ptr connection); + void LoginOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); + void LoginOnStatusChangeReconnectDisabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); + void LoginOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p); void LoginSendSessionReady(); void LoginSendLogin(); @@ -41,25 +41,25 @@ class EverQuest void LoginDisableReconnect(); - std::unique_ptr m_login_connection_manager; - std::shared_ptr m_login_connection; + std::unique_ptr m_login_connection_manager; + std::shared_ptr m_login_connection; std::map m_world_servers; //World void ConnectToWorld(); - void WorldOnNewConnection(std::shared_ptr connection); - void WorldOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void WorldOnStatusChangeReconnectDisabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void WorldOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p); + void WorldOnNewConnection(std::shared_ptr connection); + void WorldOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); + void WorldOnStatusChangeReconnectDisabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); + void WorldOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p); void WorldSendClientAuth(); void WorldSendEnterWorld(const std::string &character); void WorldProcessCharacterSelect(const EQ::Net::Packet &p); - std::unique_ptr m_world_connection_manager; - std::shared_ptr m_world_connection; + std::unique_ptr m_world_connection_manager; + std::shared_ptr m_world_connection; //Variables std::string m_host; diff --git a/hc/login.cpp b/hc/login.cpp index 170a32bf71..f6dca7c780 100644 --- a/hc/login.cpp +++ b/hc/login.cpp @@ -26,7 +26,7 @@ LoginConnection::LoginConnection(const std::string &username, const std::string m_host_port = host_port; m_server = server; - m_connection_manager.reset(new EQ::Net::DaybreakConnectionManager()); + m_connection_manager.reset(new EQ::Net::ReliableStreamConnectionManager()); m_connection_manager->OnNewConnection(std::bind(&LoginConnection::OnNewConnection, this, std::placeholders::_1)); m_connection_manager->OnConnectionStateChange(std::bind(&LoginConnection::OnStatusChangeActive, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); @@ -39,13 +39,13 @@ LoginConnection::~LoginConnection() { } -void LoginConnection::OnNewConnection(std::shared_ptr connection) +void LoginConnection::OnNewConnection(std::shared_ptr connection) { m_connection = connection; Log.OutF(Logs::General, Logs::Headless_Client, "Connecting..."); } -void LoginConnection::OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) +void LoginConnection::OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) { if (to == EQ::Net::StatusConnected) { Log.OutF(Logs::General, Logs::Headless_Client, "Login connected."); @@ -61,7 +61,7 @@ void LoginConnection::OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) +void LoginConnection::OnStatusChangeInactive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) { if (to == EQ::Net::StatusDisconnected) { m_key.clear(); @@ -70,7 +70,7 @@ void LoginConnection::OnStatusChangeInactive(std::shared_ptr conn, const EQ::Net::Packet &p) +void LoginConnection::OnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p) { auto opcode = p.GetUInt16(0); switch (opcode) { diff --git a/hc/login.h b/hc/login.h index 31a448b70c..bec7c3cdd9 100644 --- a/hc/login.h +++ b/hc/login.h @@ -1,6 +1,6 @@ #pragma once -#include "../common/net/daybreak_connection.h" +#include "../common/net/reliable_stream_connection.h" #include "../common/event/timer.h" #include @@ -23,10 +23,10 @@ class LoginConnection ~LoginConnection(); private: - void OnNewConnection(std::shared_ptr connection); - void OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void OnStatusChangeInactive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void OnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p); + void OnNewConnection(std::shared_ptr connection); + void OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); + void OnStatusChangeInactive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); + void OnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p); void Kill(); void Start(); @@ -38,8 +38,8 @@ class LoginConnection void ProcessServerPacketList(const EQ::Net::Packet &p); void ProcessServerPlayResponse(const EQ::Net::Packet &p); - std::unique_ptr m_connection_manager; - std::shared_ptr m_connection; + std::unique_ptr m_connection_manager; + std::shared_ptr m_connection; bool m_connecting; std::unique_ptr m_connect_timer; diff --git a/hc/world.cpp b/hc/world.cpp index 7be7cecb4d..c9d690f62b 100644 --- a/hc/world.cpp +++ b/hc/world.cpp @@ -8,7 +8,7 @@ WorldConnection::WorldConnection(const std::string &key, uint32_t dbid, const st m_key = key; m_dbid = dbid; - m_connection_manager.reset(new EQ::Net::DaybreakConnectionManager()); + m_connection_manager.reset(new EQ::Net::ReliableStreamConnectionManager()); m_connection_manager->OnNewConnection(std::bind(&WorldConnection::OnNewConnection, this, std::placeholders::_1)); m_connection_manager->OnConnectionStateChange(std::bind(&WorldConnection::OnStatusChangeActive, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); m_connection_manager->OnPacketRecv(std::bind(&WorldConnection::OnPacketRecv, this, std::placeholders::_1, std::placeholders::_2)); @@ -18,13 +18,13 @@ WorldConnection::WorldConnection(const std::string &key, uint32_t dbid, const st WorldConnection::~WorldConnection() { } -void WorldConnection::OnNewConnection(std::shared_ptr connection) +void WorldConnection::OnNewConnection(std::shared_ptr connection) { m_connection = connection; Log.OutF(Logs::General, Logs::Headless_Client, "Connecting to world..."); } -void WorldConnection::OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) +void WorldConnection::OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) { if (to == EQ::Net::StatusConnected) { Log.OutF(Logs::General, Logs::Headless_Client, "World connected."); @@ -38,14 +38,14 @@ void WorldConnection::OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) +void WorldConnection::OnStatusChangeInactive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) { if (to == EQ::Net::StatusDisconnected) { m_connection.reset(); } } -void WorldConnection::OnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p) +void WorldConnection::OnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p) { auto opcode = p.GetUInt16(0); Log.OutF(Logs::General, Logs::Headless_Client, "Packet in:\n{0}", p.ToString()); diff --git a/hc/world.h b/hc/world.h index 7ca0e96d7e..b1df83894f 100644 --- a/hc/world.h +++ b/hc/world.h @@ -1,6 +1,6 @@ #pragma once -#include "../common/net/daybreak_connection.h" +#include "../common/net/reliable_stream_connection.h" #include "../common/event/timer.h" #include @@ -10,17 +10,17 @@ class WorldConnection WorldConnection(const std::string &key, uint32_t dbid, const std::string &host); ~WorldConnection(); private: - void OnNewConnection(std::shared_ptr connection); - void OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void OnStatusChangeInactive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void OnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p); + void OnNewConnection(std::shared_ptr connection); + void OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); + void OnStatusChangeInactive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); + void OnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p); void Kill(); void Start(); void SendClientAuth(); - std::unique_ptr m_connection_manager; - std::shared_ptr m_connection; + std::unique_ptr m_connection_manager; + std::shared_ptr m_connection; bool m_connecting; std::unique_ptr m_connect_timer; diff --git a/loginserver/account_management.cpp b/loginserver/account_management.cpp index a76ae894b3..f7c0ed5353 100644 --- a/loginserver/account_management.cpp +++ b/loginserver/account_management.cpp @@ -124,18 +124,18 @@ uint64 AccountManagement::CheckExternalLoginserverUserCredentials(LoginAccountCo bool running = true; uint32 ret = 0; - EQ::Net::DaybreakConnectionManager mgr; - std::shared_ptr conn; + EQ::Net::ReliableStreamConnectionManager mgr; + std::shared_ptr conn; mgr.OnNewConnection( - [&](std::shared_ptr connection) { + [&](std::shared_ptr connection) { conn = connection; } ); mgr.OnConnectionStateChange( [&]( - std::shared_ptr conn, + std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to ) { @@ -152,7 +152,7 @@ uint64 AccountManagement::CheckExternalLoginserverUserCredentials(LoginAccountCo ); mgr.OnPacketRecv( - [&](std::shared_ptr conn, const EQ::Net::Packet &p) { + [&](std::shared_ptr conn, const EQ::Net::Packet &p) { auto opcode = p.GetUInt16(0); switch (opcode) { case 0x0017: //OP_ChatMessage @@ -250,18 +250,18 @@ uint64 AccountManagement::HealthCheckUserLogin() bool running = true; uint64 ret = 0; - EQ::Net::DaybreakConnectionManager mgr; - std::shared_ptr c; + EQ::Net::ReliableStreamConnectionManager mgr; + std::shared_ptr c; mgr.OnNewConnection( - [&](std::shared_ptr connection) { + [&](std::shared_ptr connection) { c = connection; } ); mgr.OnConnectionStateChange( [&]( - std::shared_ptr conn, + std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to ) { @@ -278,7 +278,7 @@ uint64 AccountManagement::HealthCheckUserLogin() ); mgr.OnPacketRecv( - [&](std::shared_ptr conn, const EQ::Net::Packet &p) { + [&](std::shared_ptr conn, const EQ::Net::Packet &p) { auto opcode = p.GetUInt16(0); switch (opcode) { case 0x0017: //OP_ChatMessage diff --git a/loginserver/client.h b/loginserver/client.h index 5c62f2c835..0dc71d00c7 100644 --- a/loginserver/client.h +++ b/loginserver/client.h @@ -6,7 +6,7 @@ #include "../common/random.h" #include "../common/eq_stream_intf.h" #include "../common/net/dns.h" -#include "../common/net/daybreak_connection.h" +#include "../common/net/reliable_stream_connection.h" #include "login_types.h" #include "../common/repositories/login_accounts_repository.h" #include @@ -54,8 +54,8 @@ class Client { unsigned int m_selected_play_server_id; unsigned int m_play_sequence_id; std::string m_key; - std::unique_ptr m_login_connection_manager; - std::shared_ptr m_login_connection; + std::unique_ptr m_login_connection_manager; + std::shared_ptr m_login_connection; LoginBaseMessage m_login_base_message; std::string m_stored_username; std::string m_stored_password; diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index 251fd8f05d..749b9276f4 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -469,11 +469,11 @@ static void ProcessCommandIgnore(Client *c, std::string Ignoree) { Clientlist::Clientlist(int ChatPort) { EQStreamManagerInterfaceOptions chat_opts(ChatPort, false, false); chat_opts.opcode_size = 1; - chat_opts.daybreak_options.stale_connection_ms = 600000; - chat_opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS); - chat_opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor); - chat_opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS); - chat_opts.daybreak_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS); + chat_opts.reliable_stream_options.stale_connection_ms = 600000; + chat_opts.reliable_stream_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS); + chat_opts.reliable_stream_options.resend_delay_factor = RuleR(Network, ResendDelayFactor); + chat_opts.reliable_stream_options.resend_delay_min = RuleI(Network, ResendDelayMinMS); + chat_opts.reliable_stream_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS); chatsf = new EQ::Net::EQStreamManager(chat_opts); diff --git a/world/main.cpp b/world/main.cpp index 9ea0f26cb6..c9386128e1 100644 --- a/world/main.cpp +++ b/world/main.cpp @@ -333,11 +333,11 @@ int main(int argc, char **argv) WorldBoot::CheckForPossibleConfigurationIssues(); EQStreamManagerInterfaceOptions opts(9000, false, false); - opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS); - opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor); - opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS); - opts.daybreak_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS); - opts.daybreak_options.outgoing_data_rate = RuleR(Network, ClientDataRate); + opts.reliable_stream_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS); + opts.reliable_stream_options.resend_delay_factor = RuleR(Network, ResendDelayFactor); + opts.reliable_stream_options.resend_delay_min = RuleI(Network, ResendDelayMinMS); + opts.reliable_stream_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS); + opts.reliable_stream_options.outgoing_data_rate = RuleR(Network, ClientDataRate); EQ::Net::EQStreamManager eqsm(opts); diff --git a/zone/api_service.cpp b/zone/api_service.cpp index 6f1c16d9d9..607ab64c6c 100644 --- a/zone/api_service.cpp +++ b/zone/api_service.cpp @@ -82,7 +82,7 @@ Json::Value ApiGetPacketStatistics(EQ::Net::WebsocketServerConnection *connectio auto connection = client->Connection(); auto opts = connection->GetManager()->GetOptions(); auto eqs_stats = connection->GetStats(); - auto &stats = eqs_stats.DaybreakStats; + auto &stats = eqs_stats.ReliableStreamStats; auto now = EQ::Net::Clock::now(); auto sec_since_stats_reset = std::chrono::duration_cast>( now - stats.created diff --git a/zone/attack.cpp b/zone/attack.cpp index 9c6581a324..f541c3e92c 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -401,8 +401,8 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit) */ /* Order according to current (SoF+?) dev quotes: - * https://forums.daybreakgames.com/eq/index.php?threads/test-update-06-10-15.223510/page-2#post-3261772 - * https://forums.daybreakgames.com/eq/index.php?threads/test-update-06-10-15.223510/page-2#post-3268227 + * https://web.archive.org/web/20250816014133/https://forums.everquest.com/index.php?threads/test-update-06-10-15.223510/page-2#post-3261772 + * https://web.archive.org/web/20250816014133/https://forums.everquest.com/index.php?threads/test-update-06-10-15.223510/page-2#post-3268227 * Riposte 50, hDEX, must have weapon/fists, doesn't work on archery/throwing * Block 25, hDEX, works on archery/throwing, behind block done here if back to attacker base1 is chance * Parry 45, hDEX, doesn't work on throwing/archery, must be facing target @@ -461,7 +461,7 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit) } /* Heroic Strikethrough Implementation per Dev Quotes (2018): - * https://forums.daybreakgames.com/eq/index.php?threads/illusions-benefit-neza-10-dodge.246757/#post-3622670 + * https://web.archive.org/web/20250816014810/https://forums.everquest.com/index.php?threads/illusions-benefit-neza-10-dodge.246757/#post-3622670 * Step1 = HeroicStrikethrough(NPC) * Step2 = HeroicAgility / 25 * Step3 = MIN( Step1, Step2 ) @@ -3414,7 +3414,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) { uint8 Mob::GetWeaponDamageBonus(const EQ::ItemData *weapon, bool offhand) { // dev quote with old and new formulas - // https://forums.daybreakgames.com/eq/index.php?threads/test-update-09-17-15.226618/page-5#post-3326194 + // https://web.archive.org/web/20250816013618/https://forums.everquest.com/index.php?threads/test-update-09-17-15.226618/page-5#post-3326194 // // We assume that the level check is done before calling this function and sinister strikes is checked before // calling for offhand DB diff --git a/zone/gm_commands/show/network.cpp b/zone/gm_commands/show/network.cpp index d9eff2c165..46d32a69cb 100644 --- a/zone/gm_commands/show/network.cpp +++ b/zone/gm_commands/show/network.cpp @@ -16,17 +16,17 @@ void ShowNetwork(Client *c, const Seperator *sep) popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Max Packet Size") + - DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.max_packet_size)) + DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.max_packet_size)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Max Connection Count") + - DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.max_connection_count)) + DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.max_connection_count)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Keep Alive Delay") + - DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.keepalive_delay_ms)) + DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.keepalive_delay_ms)) ); popup_table += DialogueWindow::TableRow( @@ -34,64 +34,64 @@ void ShowNetwork(Client *c, const Seperator *sep) DialogueWindow::TableCell( fmt::format( "{:.2f}", - opts.daybreak_options.resend_delay_factor + opts.reliable_stream_options.resend_delay_factor ) ) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Resend Delay") + - DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.resend_delay_ms)) + DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.resend_delay_ms)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Resend Delay Minimum") + - DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.resend_delay_min)) + DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.resend_delay_min)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Resend Delay Maximum") + - DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.resend_delay_max)) + DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.resend_delay_max)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Connect Delay") + - DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.connect_delay_ms)) + DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.connect_delay_ms)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Connect Stale") + - DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.connect_stale_ms)) + DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.connect_stale_ms)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Stale Connection") + - DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.stale_connection_ms)) + DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.stale_connection_ms)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("CRC Length") + - DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.crc_length)) + DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.crc_length)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Hold Size") + - DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.hold_size)) + DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.hold_size)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Hold Length") + - DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.hold_length_ms)) + DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.hold_length_ms)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Simulated In Packet Loss") + - DialogueWindow::TableCell(std::to_string(opts.daybreak_options.simulated_in_packet_loss)) + DialogueWindow::TableCell(std::to_string(opts.reliable_stream_options.simulated_in_packet_loss)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Simulated Out Packet Loss") + - DialogueWindow::TableCell(std::to_string(opts.daybreak_options.simulated_out_packet_loss)) + DialogueWindow::TableCell(std::to_string(opts.reliable_stream_options.simulated_out_packet_loss)) ); popup_table += DialogueWindow::TableRow( @@ -99,34 +99,34 @@ void ShowNetwork(Client *c, const Seperator *sep) DialogueWindow::TableCell( fmt::format( "{:.2f}", - opts.daybreak_options.tic_rate_hertz + opts.reliable_stream_options.tic_rate_hertz ) ) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Resend Timeout") + - DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.resend_timeout)) + DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.resend_timeout)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Connection Close Time") + - DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.daybreak_options.connection_close_time)) + DialogueWindow::TableCell(Strings::MillisecondsToTime(opts.reliable_stream_options.connection_close_time)) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Encode Passes (1)") + - DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.encode_passes[0])) + DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.encode_passes[0])) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Encode Passes (2)") + - DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.encode_passes[1])) + DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.encode_passes[1])) ); popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Port") + - DialogueWindow::TableCell(Strings::Commify(opts.daybreak_options.port)) + DialogueWindow::TableCell(Strings::Commify(opts.reliable_stream_options.port)) ); popup_table = DialogueWindow::Table(popup_table); diff --git a/zone/gm_commands/show/network_stats.cpp b/zone/gm_commands/show/network_stats.cpp index 8d51e8f692..75bf2b25f3 100644 --- a/zone/gm_commands/show/network_stats.cpp +++ b/zone/gm_commands/show/network_stats.cpp @@ -7,7 +7,7 @@ void ShowNetworkStats(Client *c, const Seperator *sep) const auto opts = connection->GetManager()->GetOptions(); const auto eqs_stats = connection->GetStats(); - const auto& stats = eqs_stats.DaybreakStats; + const auto& stats = eqs_stats.ReliableStreamStats; const auto sec_since_stats_reset = std::chrono::duration_cast>( EQ::Net::Clock::now() - stats.created @@ -217,7 +217,7 @@ void ShowNetworkStats(Client *c, const Seperator *sep) ) ); - if (opts.daybreak_options.outgoing_data_rate > 0.0) { + if (opts.reliable_stream_options.outgoing_data_rate > 0.0) { popup_table += DialogueWindow::TableRow( DialogueWindow::TableCell("Outgoing Link Saturation") + DialogueWindow::TableCell( @@ -229,14 +229,14 @@ void ShowNetworkStats(Client *c, const Seperator *sep) 1.0 - ( ( - opts.daybreak_options.outgoing_data_rate - + opts.reliable_stream_options.outgoing_data_rate - stats.datarate_remaining ) / - opts.daybreak_options.outgoing_data_rate + opts.reliable_stream_options.outgoing_data_rate ) ) ), - opts.daybreak_options.outgoing_data_rate + opts.reliable_stream_options.outgoing_data_rate ) ) ); diff --git a/zone/main.cpp b/zone/main.cpp index 6177ce5626..4f5916078e 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -555,11 +555,11 @@ int main(int argc, char **argv) LogInfo("Starting EQ Network server on port [{}]", Config->ZonePort); EQStreamManagerInterfaceOptions opts(Config->ZonePort, false, RuleB(Network, CompressZoneStream)); - opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS); - opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor); - opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS); - opts.daybreak_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS); - opts.daybreak_options.outgoing_data_rate = RuleR(Network, ClientDataRate); + opts.reliable_stream_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS); + opts.reliable_stream_options.resend_delay_factor = RuleR(Network, ResendDelayFactor); + opts.reliable_stream_options.resend_delay_min = RuleI(Network, ResendDelayMinMS); + opts.reliable_stream_options.resend_delay_max = RuleI(Network, ResendDelayMaxMS); + opts.reliable_stream_options.outgoing_data_rate = RuleR(Network, ClientDataRate); eqsm = std::make_unique(opts); eqsf_open = true; From 00b66ce4324f2bb780da709c7645509a6e044081 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 16 Aug 2025 21:34:16 -0400 Subject: [PATCH 018/194] [Commands] Add #find account Subcommand (#4981) Credit goes to https://github.com/The-Heroes-Journey-EQEMU/Server/pull/281 --- .../command_subsettings_repository.h | 1 + zone/gm_commands/find.cpp | 4 +- zone/gm_commands/find/account.cpp | 50 +++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 zone/gm_commands/find/account.cpp diff --git a/common/repositories/command_subsettings_repository.h b/common/repositories/command_subsettings_repository.h index 963bcee91e..aa99d164a2 100644 --- a/common/repositories/command_subsettings_repository.h +++ b/common/repositories/command_subsettings_repository.h @@ -49,6 +49,7 @@ class CommandSubsettingsRepository: public BaseCommandSubsettingsRepository { // these are the base definitions for command_subsettings and can be over-ridden by the database std::vector static_records = { {.parent_command = "find", .sub_command = "aa", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findaa"}, + {.parent_command = "find", .sub_command = "account", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findaccount"}, {.parent_command = "find", .sub_command = "body_type", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findbodytype"}, {.parent_command = "find", .sub_command = "bug_category", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findbugcategory"}, {.parent_command = "find", .sub_command = "character", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "findcharacter"}, diff --git a/zone/gm_commands/find.cpp b/zone/gm_commands/find.cpp index 0bdbcbe709..6ee5815cb4 100644 --- a/zone/gm_commands/find.cpp +++ b/zone/gm_commands/find.cpp @@ -1,5 +1,6 @@ #include "../client.h" #include "find/aa.cpp" +#include "find/account.cpp" #include "find/body_type.cpp" #include "find/bot.cpp" #include "find/bug_category.cpp" @@ -38,6 +39,7 @@ void command_find(Client *c, const Seperator *sep) std::vector commands = { Cmd{.cmd = "aa", .u = "aa [Search Criteria]", .fn = FindAA, .a = {"#findaa"}}, + Cmd{.cmd = "account", .u = "account [Search Criteria]", .fn = FindAccount, .a = {"#findaccount"}}, Cmd{.cmd = "body_type", .u = "body_type [Search Criteria]", .fn = FindBodyType, .a = {"#findbodytype"}}, Cmd{.cmd = "bug_category", .u = "bug_category [Search Criteria]", .fn = FindBugCategory, .a = {"#findbugcategory"}}, Cmd{.cmd = "character", .u = "character [Search Criteria]", .fn = FindCharacter, .a = {"#findcharacter"}}, @@ -72,7 +74,7 @@ void command_find(Client *c, const Seperator *sep) commands.emplace_back( Cmd{.cmd = "bot", .u = "bot [Search Criteria]", .fn = FindBot, .a = {"#findbot"}} ); - + std::sort(commands.begin(), commands.end(), [](const Cmd& a, const Cmd& b) { return a.cmd < b.cmd; }); diff --git a/zone/gm_commands/find/account.cpp b/zone/gm_commands/find/account.cpp new file mode 100644 index 0000000000..1265c8431f --- /dev/null +++ b/zone/gm_commands/find/account.cpp @@ -0,0 +1,50 @@ +#include "../../client.h" +#include "../../common/repositories/account_repository.h" + +void FindAccount(Client *c, const Seperator *sep) +{ + const uint16 arguments = sep->argnum; + if (arguments < 2) { + c->Message(Chat::White, "Usage: #find account [Character Name]"); + c->Message(Chat::White, "Note: Used to print the account ID and name of the account a character belongs to."); + return; + } + + const std::string& character_name = sep->arg[2]; + + const auto& e = CharacterDataRepository::FindByName(database, character_name); + + if (!e.id) { + c->Message( + Chat::White, + fmt::format( + "Character '{}' does not exist.", + character_name + ).c_str() + ); + return; + } + + auto a = AccountRepository::FindOne(database, e.account_id); + + if (!a.id) { + c->Message( + Chat::White, + fmt::format( + "Character '{}' is not attached to an account.", + character_name + ).c_str() + ); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Account {} ({}) owns the character {}.", + a.name, + a.id, + character_name + ).c_str() + ); +} From d475428157ed29435a2f1bf9f8c7a7e04b5ff42d Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 16 Aug 2025 21:34:28 -0400 Subject: [PATCH 019/194] [Quest API] Add GetKeyRing() to Perl/Lua (#4980) --- zone/client.h | 1 + zone/lua_client.cpp | 17 +++++++++++++++++ zone/lua_client.h | 1 + zone/perl_client.cpp | 13 +++++++++++++ 4 files changed, 32 insertions(+) diff --git a/zone/client.h b/zone/client.h index 8bf808b1d7..87a9c1d961 100644 --- a/zone/client.h +++ b/zone/client.h @@ -326,6 +326,7 @@ class Client : public Mob void TraderStartTrader(const EQApplicationPacket *app); // void TraderPriceUpdate(const EQApplicationPacket *app); uint8 WithCustomer(uint16 NewCustomer); + std::vector GetKeyRing() { return keyring; } void KeyRingLoad(); bool KeyRingAdd(uint32 item_id); bool KeyRingCheck(uint32 item_id); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index a295f5c6d0..15ec526b64 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -3608,6 +3608,22 @@ void Lua_Client::EnableTitleSet(uint32 title_set) { self->EnableTitle(title_set); } +luabind::object Lua_Client::GetKeyRing(lua_State* L) +{ + auto lua_table = luabind::newtable(L); + + if (d_) { + auto self = reinterpret_cast(d_); + int index = 1; + for (const uint32& item_id: self->GetKeyRing()) { + lua_table[index] = item_id; + index++; + } + } + + return lua_table; +} + luabind::scope lua_register_client() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -3838,6 +3854,7 @@ luabind::scope lua_register_client() { .def("GetInvulnerableEnvironmentDamage", (bool(Lua_Client::*)(void))&Lua_Client::GetInvulnerableEnvironmentDamage) .def("GetItemIDAt", (int(Lua_Client::*)(int))&Lua_Client::GetItemIDAt) .def("GetItemCooldown", (uint32(Lua_Client::*)(uint32))&Lua_Client::GetItemCooldown) + .def("GetKeyRing", (luabind::object(Lua_Client::*)(lua_State* L))&Lua_Client::GetKeyRing) .def("GetLDoNLosses", (int(Lua_Client::*)(void))&Lua_Client::GetLDoNLosses) .def("GetLDoNLossesTheme", (int(Lua_Client::*)(int))&Lua_Client::GetLDoNLossesTheme) .def("GetLDoNPointsTheme", (int(Lua_Client::*)(int))&Lua_Client::GetLDoNPointsTheme) diff --git a/zone/lua_client.h b/zone/lua_client.h index 5835899103..c85c061b67 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -525,6 +525,7 @@ class Lua_Client : public Lua_Mob bool KeyRingRemove(uint32 item_id); bool CompleteTask(int task_id); bool UncompleteTask(int task_id); + luabind::object GetKeyRing(lua_State* L); // account data buckets void SetAccountBucket(std::string bucket_name, std::string bucket_value); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index d4a73c8518..49a2d9d02f 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -3351,6 +3351,18 @@ bool Perl_Client_UncompleteTask(Client* self, int task_id) return self->UncompleteTask(task_id); } +perl::array Perl_Client_GetKeyRing(Client* self) +{ + perl::array result; + const auto& v = self->GetKeyRing(); + + for (int i = 0; i < v.size(); ++i) { + result.push_back(v[i]); + } + + return result; +} + void perl_register_client() { perl::interpreter perl(PERL_GET_THX); @@ -3582,6 +3594,7 @@ void perl_register_client() package.add("GetItemCooldown", &Perl_Client_GetItemCooldown); package.add("GetItemIDAt", &Perl_Client_GetItemIDAt); package.add("GetItemInInventory", &Perl_Client_GetItemInInventory); + package.add("GetKeyRing", &Perl_Client_GetKeyRing); package.add("GetLDoNLosses", &Perl_Client_GetLDoNLosses); package.add("GetLDoNLossesTheme", &Perl_Client_GetLDoNLossesTheme); package.add("GetLDoNPointsTheme", &Perl_Client_GetLDoNPointsTheme); From e13b133ac837860a147e6be98fe3c08e8e56ab05 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 16 Aug 2025 21:34:39 -0400 Subject: [PATCH 020/194] [Quest API] Add GetNPCTintIndex() to Perl/Lua (#4983) --- zone/lua_npc.cpp | 11 +++++++++-- zone/lua_npc.h | 1 + zone/npc.cpp | 13 +++++++++++++ zone/npc.h | 3 +++ zone/perl_npc.cpp | 10 ++++++++-- 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index 67f26155de..b0cd59c49a 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -945,10 +945,16 @@ bool Lua_NPC::IsResumedFromZoneSuspend() return self->IsResumedFromZoneSuspend(); } -void Lua_NPC::SetNPCTintIndex(uint32 id) +void Lua_NPC::SetNPCTintIndex(uint32 index) { Lua_Safe_Call_Void(); - self->SendAppearancePacket(AppearanceType::NPCTintIndex, id); + self->SetNPCTintIndex(index); +} + +uint32 Lua_NPC::GetNPCTintIndex() +{ + Lua_Safe_Call_Int(); + return self->GetNPCTintIndex(); } luabind::scope lua_register_npc() { @@ -1018,6 +1024,7 @@ luabind::scope lua_register_npc() { .def("GetNPCSpellsEffectsID", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsEffectsID) .def("GetNPCSpellsID", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsID) .def("GetNPCStat", (float(Lua_NPC::*)(std::string))&Lua_NPC::GetNPCStat) + .def("GetNPCTintIndex", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetNPCTintIndex) .def("GetPetSpellID", (int(Lua_NPC::*)(void))&Lua_NPC::GetPetSpellID) .def("GetPlatinum", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetPlatinum) .def("GetPrimSkill", (int(Lua_NPC::*)(void))&Lua_NPC::GetPrimSkill) diff --git a/zone/lua_npc.h b/zone/lua_npc.h index 90d6e21428..d166ccdffa 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -200,6 +200,7 @@ class Lua_NPC : public Lua_Mob Lua_Spawn GetSpawn(lua_State* L); bool IsResumedFromZoneSuspend(); void SetNPCTintIndex(uint32 id); + uint32 GetNPCTintIndex(); }; diff --git a/zone/npc.cpp b/zone/npc.cpp index 1c70da2c40..c0b2954fdd 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -4940,3 +4940,16 @@ void NPC::ResetMultiQuest() { m_hand_in = {}; } + +void NPC::SetNPCTintIndex(uint32 index) +{ + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + auto* s = (SpawnAppearance_Struct*) outapp->pBuffer; + + s->spawn_id = GetID(); + s->type = AppearanceType::NPCTintIndex; + s->parameter = index; + + entity_list.QueueClients(this, outapp); + safe_delete(outapp); +} diff --git a/zone/npc.h b/zone/npc.h index 31a4e09f99..4c4d3cb1bb 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -552,6 +552,9 @@ class NPC : public Mob void ScaleNPC(uint8 npc_level, bool always_scale = false, bool override_special_abilities = false); + uint32 GetNPCTintIndex() { return m_npc_tint_id; } + void SetNPCTintIndex(uint32 index); + void RecalculateSkills(); void ReloadSpells(); diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index df8b5a924c..6eaf0ac475 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -885,9 +885,14 @@ Spawn2* Perl_NPC_GetSpawn(NPC* self) return self->GetSpawn(); } -void Perl_NPC_SetNPCTintIndex(NPC* self, uint32 id) +void Perl_NPC_SetNPCTintIndex(NPC* self, uint32 index) { - return self->SendAppearancePacket(AppearanceType::NPCTintIndex, id); + self->SetNPCTintIndex(index); +} + +uint32 Perl_NPC_GetNPCTintIndex(NPC* self) +{ + return self->GetNPCTintIndex(); } void perl_register_npc() @@ -959,6 +964,7 @@ void perl_register_npc() package.add("GetNPCSpellsEffectsID", &Perl_NPC_GetNPCSpellsEffectsID); package.add("GetNPCSpellsID", &Perl_NPC_GetNPCSpellsID); package.add("GetNPCStat", &Perl_NPC_GetNPCStat); + package.add("GetNPCTintIndex", &Perl_NPC_GetNPCTintIndex); package.add("GetPetSpellID", &Perl_NPC_GetPetSpellID); package.add("GetPlatinum", &Perl_NPC_GetPlatinum); package.add("GetPrimSkill", &Perl_NPC_GetPrimSkill); From adb3196ca589913978ac2870a497567f43fc5201 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 16 Aug 2025 21:34:55 -0400 Subject: [PATCH 021/194] [Cleanup] Add #npcedit npc_tint_id Help Message (#4982) * [Cleanup] Add #npcedit npc_tint_id Help Message * Update npcedit.cpp * Update npcedit.cpp --- zone/gm_commands/npcedit.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/gm_commands/npcedit.cpp b/zone/gm_commands/npcedit.cpp index 4f372b1e04..ff0080e67d 100755 --- a/zone/gm_commands/npcedit.cpp +++ b/zone/gm_commands/npcedit.cpp @@ -110,6 +110,7 @@ void SendNPCEditSubCommands(Client *c) c->Message(Chat::White, "Usage: #npcedit setanimation [Animation ID] - Sets an NPC's Animation on Spawn (Stored in spawn2 table)"); c->Message(Chat::White, "Usage: #npcedit respawntime [Respawn Time] - Sets an NPC's Respawn Timer in Seconds (Stored in spawn2 table)"); c->Message(Chat::White, "Usage: #npcedit set_grid [Grid ID] - Sets an NPC's Grid ID"); + c->Message(Chat::White, "Usage: #npcedit npc_tint_id [NPC Tint ID] - Sets an NPC's Tint ID (0 to 78 for RoF2)"); } void command_npcedit(Client *c, const Seperator *sep) @@ -1836,4 +1837,4 @@ void command_npcedit(Client *c, const Seperator *sep) } c->Message(Chat::White, d.c_str()); -} \ No newline at end of file +} From ed3f6c2a40724b97741ea7fc945344fcbee1333e Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 16 Aug 2025 21:35:13 -0400 Subject: [PATCH 022/194] [Cleanup] Fix Issues with Strings::Commify and Mob::SendStatsWindow (#4984) --- common/strings.cpp | 6 ++++++ zone/mob.cpp | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/common/strings.cpp b/common/strings.cpp index 52990aa85d..eb56ab2f52 100644 --- a/common/strings.cpp +++ b/common/strings.cpp @@ -313,6 +313,12 @@ std::string Strings::Commify(const std::string &number) auto string_length = static_cast(number.length()); + if (string_length == 3) { + return number; + } else if (string_length == 4 && number.starts_with("-")) { + return number; + } + int i = 0; for (i = string_length - 3; i >= 0; i -= 3) { if (i > 0) { diff --git a/zone/mob.cpp b/zone/mob.cpp index 16774bfbcb..7d6f3229eb 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1317,7 +1317,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.IsMercenary = IsMerc() ? 1 : 0; ns->spawn.targetable_with_hotkey = no_target_hotkey ? 0 : 1; // opposite logic! ns->spawn.untargetable = IsTargetable(); - + ns->spawn.petOwnerId = ownerid; ns->spawn.haircolor = haircolor; @@ -2361,7 +2361,7 @@ void Mob::SendStatsWindow(Client* c, bool use_window) // Attack 2 final_string += fmt::format( - "Offense: {}{} | {}{}", + "Offense: {}{}{}{}", Strings::Commify(offense(skill)), ( itembonuses.ATK ? @@ -8792,4 +8792,4 @@ bool Mob::LoadDataBucketsCache() } return true; -} \ No newline at end of file +} From 1fe5d9fa4f0ab378e6b82ba86f53e7460c9b336d Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 16 Aug 2025 21:35:38 -0400 Subject: [PATCH 023/194] [Commands] Add #task complete Saylink to #task show (#4985) --- zone/task_client_state.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp index 8690e05ef2..af9525a604 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -1414,11 +1414,19 @@ void ClientTaskState::ShowClientTaskInfoMessage(ClientTaskInformation *task, Cli c->Message( Chat::White, fmt::format( - "Task {} | Title: {} ID: {} Type: {}", + "Task {} | Title: {} ID: {} Type: {} | {}", task->slot, task_data->title, task->task_id, - Tasks::GetTaskTypeDescription(task_data->type) + Tasks::GetTaskTypeDescription(task_data->type), + Saylink::Create( + fmt::format( + "#task complete {}", + task->task_id + ), + false, + "Complete" + ) ).c_str() ); c->Message(Chat::White, "------------------------------------------------"); From 207ee2daa0762f90df4ec5546196ebfc1f1f201d Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 16 Aug 2025 21:35:55 -0400 Subject: [PATCH 024/194] [Database] Add `heal_amount` to `character_stats_record` (#4986) * [Database] Add heal_amount to character_stats_record * Update version.h --- common/database/database_update_manifest.cpp | 11 + .../base_character_stats_record_repository.h | 196 ++++++++++-------- common/version.h | 2 +- zone/client_packet.cpp | 1 + 4 files changed, 117 insertions(+), 93 deletions(-) diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 58d8026a4d..f6eddc69b5 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -7160,6 +7160,17 @@ ALTER TABLE loottable_entries )", .content_schema_update = true }, + ManifestEntry{ + .version = 9327, + .description = "2025_08_13_character_stats_record_heal_amount.sql", + .check = "SHOW COLUMNS FROM `character_stats_record` LIKE 'heal_amount'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `character_stats_record` +ADD COLUMN `heal_amount` int(11) NULL DEFAULT 0 AFTER `spell_damage`; +)" + }, // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ diff --git a/common/repositories/base/base_character_stats_record_repository.h b/common/repositories/base/base_character_stats_record_repository.h index d4bd8d041f..aac41280a4 100644 --- a/common/repositories/base/base_character_stats_record_repository.h +++ b/common/repositories/base/base_character_stats_record_repository.h @@ -70,6 +70,7 @@ class BaseCharacterStatsRecordRepository { int32_t endurance_regen; int32_t shielding; int32_t spell_damage; + int32_t heal_amount; int32_t spell_shielding; int32_t strikethrough; int32_t stun_resist; @@ -154,6 +155,7 @@ class BaseCharacterStatsRecordRepository { "endurance_regen", "shielding", "spell_damage", + "heal_amount", "spell_shielding", "strikethrough", "stun_resist", @@ -234,6 +236,7 @@ class BaseCharacterStatsRecordRepository { "endurance_regen", "shielding", "spell_damage", + "heal_amount", "spell_shielding", "strikethrough", "stun_resist", @@ -348,6 +351,7 @@ class BaseCharacterStatsRecordRepository { e.endurance_regen = 0; e.shielding = 0; e.spell_damage = 0; + e.heal_amount = 0; e.spell_shielding = 0; e.strikethrough = 0; e.stun_resist = 0; @@ -458,29 +462,30 @@ class BaseCharacterStatsRecordRepository { e.endurance_regen = row[48] ? static_cast(atoi(row[48])) : 0; e.shielding = row[49] ? static_cast(atoi(row[49])) : 0; e.spell_damage = row[50] ? static_cast(atoi(row[50])) : 0; - e.spell_shielding = row[51] ? static_cast(atoi(row[51])) : 0; - e.strikethrough = row[52] ? static_cast(atoi(row[52])) : 0; - e.stun_resist = row[53] ? static_cast(atoi(row[53])) : 0; - e.backstab = row[54] ? static_cast(atoi(row[54])) : 0; - e.wind = row[55] ? static_cast(atoi(row[55])) : 0; - e.brass = row[56] ? static_cast(atoi(row[56])) : 0; - e.string = row[57] ? static_cast(atoi(row[57])) : 0; - e.percussion = row[58] ? static_cast(atoi(row[58])) : 0; - e.singing = row[59] ? static_cast(atoi(row[59])) : 0; - e.baking = row[60] ? static_cast(atoi(row[60])) : 0; - e.alchemy = row[61] ? static_cast(atoi(row[61])) : 0; - e.tailoring = row[62] ? static_cast(atoi(row[62])) : 0; - e.blacksmithing = row[63] ? static_cast(atoi(row[63])) : 0; - e.fletching = row[64] ? static_cast(atoi(row[64])) : 0; - e.brewing = row[65] ? static_cast(atoi(row[65])) : 0; - e.jewelry = row[66] ? static_cast(atoi(row[66])) : 0; - e.pottery = row[67] ? static_cast(atoi(row[67])) : 0; - e.research = row[68] ? static_cast(atoi(row[68])) : 0; - e.alcohol = row[69] ? static_cast(atoi(row[69])) : 0; - e.fishing = row[70] ? static_cast(atoi(row[70])) : 0; - e.tinkering = row[71] ? static_cast(atoi(row[71])) : 0; - e.created_at = strtoll(row[72] ? row[72] : "-1", nullptr, 10); - e.updated_at = strtoll(row[73] ? row[73] : "-1", nullptr, 10); + e.heal_amount = row[51] ? static_cast(atoi(row[51])) : 0; + e.spell_shielding = row[52] ? static_cast(atoi(row[52])) : 0; + e.strikethrough = row[53] ? static_cast(atoi(row[53])) : 0; + e.stun_resist = row[54] ? static_cast(atoi(row[54])) : 0; + e.backstab = row[55] ? static_cast(atoi(row[55])) : 0; + e.wind = row[56] ? static_cast(atoi(row[56])) : 0; + e.brass = row[57] ? static_cast(atoi(row[57])) : 0; + e.string = row[58] ? static_cast(atoi(row[58])) : 0; + e.percussion = row[59] ? static_cast(atoi(row[59])) : 0; + e.singing = row[60] ? static_cast(atoi(row[60])) : 0; + e.baking = row[61] ? static_cast(atoi(row[61])) : 0; + e.alchemy = row[62] ? static_cast(atoi(row[62])) : 0; + e.tailoring = row[63] ? static_cast(atoi(row[63])) : 0; + e.blacksmithing = row[64] ? static_cast(atoi(row[64])) : 0; + e.fletching = row[65] ? static_cast(atoi(row[65])) : 0; + e.brewing = row[66] ? static_cast(atoi(row[66])) : 0; + e.jewelry = row[67] ? static_cast(atoi(row[67])) : 0; + e.pottery = row[68] ? static_cast(atoi(row[68])) : 0; + e.research = row[69] ? static_cast(atoi(row[69])) : 0; + e.alcohol = row[70] ? static_cast(atoi(row[70])) : 0; + e.fishing = row[71] ? static_cast(atoi(row[71])) : 0; + e.tinkering = row[72] ? static_cast(atoi(row[72])) : 0; + e.created_at = strtoll(row[73] ? row[73] : "-1", nullptr, 10); + e.updated_at = strtoll(row[74] ? row[74] : "-1", nullptr, 10); return e; } @@ -565,29 +570,30 @@ class BaseCharacterStatsRecordRepository { v.push_back(columns[48] + " = " + std::to_string(e.endurance_regen)); v.push_back(columns[49] + " = " + std::to_string(e.shielding)); v.push_back(columns[50] + " = " + std::to_string(e.spell_damage)); - v.push_back(columns[51] + " = " + std::to_string(e.spell_shielding)); - v.push_back(columns[52] + " = " + std::to_string(e.strikethrough)); - v.push_back(columns[53] + " = " + std::to_string(e.stun_resist)); - v.push_back(columns[54] + " = " + std::to_string(e.backstab)); - v.push_back(columns[55] + " = " + std::to_string(e.wind)); - v.push_back(columns[56] + " = " + std::to_string(e.brass)); - v.push_back(columns[57] + " = " + std::to_string(e.string)); - v.push_back(columns[58] + " = " + std::to_string(e.percussion)); - v.push_back(columns[59] + " = " + std::to_string(e.singing)); - v.push_back(columns[60] + " = " + std::to_string(e.baking)); - v.push_back(columns[61] + " = " + std::to_string(e.alchemy)); - v.push_back(columns[62] + " = " + std::to_string(e.tailoring)); - v.push_back(columns[63] + " = " + std::to_string(e.blacksmithing)); - v.push_back(columns[64] + " = " + std::to_string(e.fletching)); - v.push_back(columns[65] + " = " + std::to_string(e.brewing)); - v.push_back(columns[66] + " = " + std::to_string(e.jewelry)); - v.push_back(columns[67] + " = " + std::to_string(e.pottery)); - v.push_back(columns[68] + " = " + std::to_string(e.research)); - v.push_back(columns[69] + " = " + std::to_string(e.alcohol)); - v.push_back(columns[70] + " = " + std::to_string(e.fishing)); - v.push_back(columns[71] + " = " + std::to_string(e.tinkering)); - v.push_back(columns[72] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); - v.push_back(columns[73] + " = FROM_UNIXTIME(" + (e.updated_at > 0 ? std::to_string(e.updated_at) : "null") + ")"); + v.push_back(columns[51] + " = " + std::to_string(e.heal_amount)); + v.push_back(columns[52] + " = " + std::to_string(e.spell_shielding)); + v.push_back(columns[53] + " = " + std::to_string(e.strikethrough)); + v.push_back(columns[54] + " = " + std::to_string(e.stun_resist)); + v.push_back(columns[55] + " = " + std::to_string(e.backstab)); + v.push_back(columns[56] + " = " + std::to_string(e.wind)); + v.push_back(columns[57] + " = " + std::to_string(e.brass)); + v.push_back(columns[58] + " = " + std::to_string(e.string)); + v.push_back(columns[59] + " = " + std::to_string(e.percussion)); + v.push_back(columns[60] + " = " + std::to_string(e.singing)); + v.push_back(columns[61] + " = " + std::to_string(e.baking)); + v.push_back(columns[62] + " = " + std::to_string(e.alchemy)); + v.push_back(columns[63] + " = " + std::to_string(e.tailoring)); + v.push_back(columns[64] + " = " + std::to_string(e.blacksmithing)); + v.push_back(columns[65] + " = " + std::to_string(e.fletching)); + v.push_back(columns[66] + " = " + std::to_string(e.brewing)); + v.push_back(columns[67] + " = " + std::to_string(e.jewelry)); + v.push_back(columns[68] + " = " + std::to_string(e.pottery)); + v.push_back(columns[69] + " = " + std::to_string(e.research)); + v.push_back(columns[70] + " = " + std::to_string(e.alcohol)); + v.push_back(columns[71] + " = " + std::to_string(e.fishing)); + v.push_back(columns[72] + " = " + std::to_string(e.tinkering)); + v.push_back(columns[73] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")"); + v.push_back(columns[74] + " = FROM_UNIXTIME(" + (e.updated_at > 0 ? std::to_string(e.updated_at) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -660,6 +666,7 @@ class BaseCharacterStatsRecordRepository { v.push_back(std::to_string(e.endurance_regen)); v.push_back(std::to_string(e.shielding)); v.push_back(std::to_string(e.spell_damage)); + v.push_back(std::to_string(e.heal_amount)); v.push_back(std::to_string(e.spell_shielding)); v.push_back(std::to_string(e.strikethrough)); v.push_back(std::to_string(e.stun_resist)); @@ -763,6 +770,7 @@ class BaseCharacterStatsRecordRepository { v.push_back(std::to_string(e.endurance_regen)); v.push_back(std::to_string(e.shielding)); v.push_back(std::to_string(e.spell_damage)); + v.push_back(std::to_string(e.heal_amount)); v.push_back(std::to_string(e.spell_shielding)); v.push_back(std::to_string(e.strikethrough)); v.push_back(std::to_string(e.stun_resist)); @@ -870,29 +878,30 @@ class BaseCharacterStatsRecordRepository { e.endurance_regen = row[48] ? static_cast(atoi(row[48])) : 0; e.shielding = row[49] ? static_cast(atoi(row[49])) : 0; e.spell_damage = row[50] ? static_cast(atoi(row[50])) : 0; - e.spell_shielding = row[51] ? static_cast(atoi(row[51])) : 0; - e.strikethrough = row[52] ? static_cast(atoi(row[52])) : 0; - e.stun_resist = row[53] ? static_cast(atoi(row[53])) : 0; - e.backstab = row[54] ? static_cast(atoi(row[54])) : 0; - e.wind = row[55] ? static_cast(atoi(row[55])) : 0; - e.brass = row[56] ? static_cast(atoi(row[56])) : 0; - e.string = row[57] ? static_cast(atoi(row[57])) : 0; - e.percussion = row[58] ? static_cast(atoi(row[58])) : 0; - e.singing = row[59] ? static_cast(atoi(row[59])) : 0; - e.baking = row[60] ? static_cast(atoi(row[60])) : 0; - e.alchemy = row[61] ? static_cast(atoi(row[61])) : 0; - e.tailoring = row[62] ? static_cast(atoi(row[62])) : 0; - e.blacksmithing = row[63] ? static_cast(atoi(row[63])) : 0; - e.fletching = row[64] ? static_cast(atoi(row[64])) : 0; - e.brewing = row[65] ? static_cast(atoi(row[65])) : 0; - e.jewelry = row[66] ? static_cast(atoi(row[66])) : 0; - e.pottery = row[67] ? static_cast(atoi(row[67])) : 0; - e.research = row[68] ? static_cast(atoi(row[68])) : 0; - e.alcohol = row[69] ? static_cast(atoi(row[69])) : 0; - e.fishing = row[70] ? static_cast(atoi(row[70])) : 0; - e.tinkering = row[71] ? static_cast(atoi(row[71])) : 0; - e.created_at = strtoll(row[72] ? row[72] : "-1", nullptr, 10); - e.updated_at = strtoll(row[73] ? row[73] : "-1", nullptr, 10); + e.heal_amount = row[51] ? static_cast(atoi(row[51])) : 0; + e.spell_shielding = row[52] ? static_cast(atoi(row[52])) : 0; + e.strikethrough = row[53] ? static_cast(atoi(row[53])) : 0; + e.stun_resist = row[54] ? static_cast(atoi(row[54])) : 0; + e.backstab = row[55] ? static_cast(atoi(row[55])) : 0; + e.wind = row[56] ? static_cast(atoi(row[56])) : 0; + e.brass = row[57] ? static_cast(atoi(row[57])) : 0; + e.string = row[58] ? static_cast(atoi(row[58])) : 0; + e.percussion = row[59] ? static_cast(atoi(row[59])) : 0; + e.singing = row[60] ? static_cast(atoi(row[60])) : 0; + e.baking = row[61] ? static_cast(atoi(row[61])) : 0; + e.alchemy = row[62] ? static_cast(atoi(row[62])) : 0; + e.tailoring = row[63] ? static_cast(atoi(row[63])) : 0; + e.blacksmithing = row[64] ? static_cast(atoi(row[64])) : 0; + e.fletching = row[65] ? static_cast(atoi(row[65])) : 0; + e.brewing = row[66] ? static_cast(atoi(row[66])) : 0; + e.jewelry = row[67] ? static_cast(atoi(row[67])) : 0; + e.pottery = row[68] ? static_cast(atoi(row[68])) : 0; + e.research = row[69] ? static_cast(atoi(row[69])) : 0; + e.alcohol = row[70] ? static_cast(atoi(row[70])) : 0; + e.fishing = row[71] ? static_cast(atoi(row[71])) : 0; + e.tinkering = row[72] ? static_cast(atoi(row[72])) : 0; + e.created_at = strtoll(row[73] ? row[73] : "-1", nullptr, 10); + e.updated_at = strtoll(row[74] ? row[74] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -968,29 +977,30 @@ class BaseCharacterStatsRecordRepository { e.endurance_regen = row[48] ? static_cast(atoi(row[48])) : 0; e.shielding = row[49] ? static_cast(atoi(row[49])) : 0; e.spell_damage = row[50] ? static_cast(atoi(row[50])) : 0; - e.spell_shielding = row[51] ? static_cast(atoi(row[51])) : 0; - e.strikethrough = row[52] ? static_cast(atoi(row[52])) : 0; - e.stun_resist = row[53] ? static_cast(atoi(row[53])) : 0; - e.backstab = row[54] ? static_cast(atoi(row[54])) : 0; - e.wind = row[55] ? static_cast(atoi(row[55])) : 0; - e.brass = row[56] ? static_cast(atoi(row[56])) : 0; - e.string = row[57] ? static_cast(atoi(row[57])) : 0; - e.percussion = row[58] ? static_cast(atoi(row[58])) : 0; - e.singing = row[59] ? static_cast(atoi(row[59])) : 0; - e.baking = row[60] ? static_cast(atoi(row[60])) : 0; - e.alchemy = row[61] ? static_cast(atoi(row[61])) : 0; - e.tailoring = row[62] ? static_cast(atoi(row[62])) : 0; - e.blacksmithing = row[63] ? static_cast(atoi(row[63])) : 0; - e.fletching = row[64] ? static_cast(atoi(row[64])) : 0; - e.brewing = row[65] ? static_cast(atoi(row[65])) : 0; - e.jewelry = row[66] ? static_cast(atoi(row[66])) : 0; - e.pottery = row[67] ? static_cast(atoi(row[67])) : 0; - e.research = row[68] ? static_cast(atoi(row[68])) : 0; - e.alcohol = row[69] ? static_cast(atoi(row[69])) : 0; - e.fishing = row[70] ? static_cast(atoi(row[70])) : 0; - e.tinkering = row[71] ? static_cast(atoi(row[71])) : 0; - e.created_at = strtoll(row[72] ? row[72] : "-1", nullptr, 10); - e.updated_at = strtoll(row[73] ? row[73] : "-1", nullptr, 10); + e.heal_amount = row[51] ? static_cast(atoi(row[51])) : 0; + e.spell_shielding = row[52] ? static_cast(atoi(row[52])) : 0; + e.strikethrough = row[53] ? static_cast(atoi(row[53])) : 0; + e.stun_resist = row[54] ? static_cast(atoi(row[54])) : 0; + e.backstab = row[55] ? static_cast(atoi(row[55])) : 0; + e.wind = row[56] ? static_cast(atoi(row[56])) : 0; + e.brass = row[57] ? static_cast(atoi(row[57])) : 0; + e.string = row[58] ? static_cast(atoi(row[58])) : 0; + e.percussion = row[59] ? static_cast(atoi(row[59])) : 0; + e.singing = row[60] ? static_cast(atoi(row[60])) : 0; + e.baking = row[61] ? static_cast(atoi(row[61])) : 0; + e.alchemy = row[62] ? static_cast(atoi(row[62])) : 0; + e.tailoring = row[63] ? static_cast(atoi(row[63])) : 0; + e.blacksmithing = row[64] ? static_cast(atoi(row[64])) : 0; + e.fletching = row[65] ? static_cast(atoi(row[65])) : 0; + e.brewing = row[66] ? static_cast(atoi(row[66])) : 0; + e.jewelry = row[67] ? static_cast(atoi(row[67])) : 0; + e.pottery = row[68] ? static_cast(atoi(row[68])) : 0; + e.research = row[69] ? static_cast(atoi(row[69])) : 0; + e.alcohol = row[70] ? static_cast(atoi(row[70])) : 0; + e.fishing = row[71] ? static_cast(atoi(row[71])) : 0; + e.tinkering = row[72] ? static_cast(atoi(row[72])) : 0; + e.created_at = strtoll(row[73] ? row[73] : "-1", nullptr, 10); + e.updated_at = strtoll(row[74] ? row[74] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -1116,6 +1126,7 @@ class BaseCharacterStatsRecordRepository { v.push_back(std::to_string(e.endurance_regen)); v.push_back(std::to_string(e.shielding)); v.push_back(std::to_string(e.spell_damage)); + v.push_back(std::to_string(e.heal_amount)); v.push_back(std::to_string(e.spell_shielding)); v.push_back(std::to_string(e.strikethrough)); v.push_back(std::to_string(e.stun_resist)); @@ -1212,6 +1223,7 @@ class BaseCharacterStatsRecordRepository { v.push_back(std::to_string(e.endurance_regen)); v.push_back(std::to_string(e.shielding)); v.push_back(std::to_string(e.spell_damage)); + v.push_back(std::to_string(e.heal_amount)); v.push_back(std::to_string(e.spell_shielding)); v.push_back(std::to_string(e.strikethrough)); v.push_back(std::to_string(e.stun_resist)); diff --git a/common/version.h b/common/version.h index 2bcb00f99d..bf8c83fbad 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9326 +#define CURRENT_BINARY_DATABASE_VERSION 9327 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054 #define CUSTOM_BINARY_DATABASE_VERSION 0 diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 5ee5fb7098..bdcbbc13a5 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -16818,6 +16818,7 @@ void Client::RecordStats() r.endurance_regen = GetEnduranceRegen() - GetSpellBonuses().EnduranceRegen; r.shielding = GetShielding() - GetSpellBonuses().MeleeMitigation; r.spell_damage = GetSpellDmg() - GetSpellBonuses().SpellDmg; + r.heal_amount = GetHealAmt() - GetSpellBonuses().HealAmt; r.spell_shielding = GetSpellShield() - GetSpellBonuses().SpellShield; r.strikethrough = GetStrikeThrough() - GetSpellBonuses().StrikeThrough; r.stun_resist = GetStunResist() - GetSpellBonuses().StunResist; From a4e47d9180c508fb98defdb3fa9eb84ee6286ddc Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sun, 17 Aug 2025 01:00:31 -0400 Subject: [PATCH 025/194] [Pets] Add Pet Constants and Methods (#4987) * [Pets] Add Pet Constants and Methods * Remove GetID * GetPetTypeName() * Cleanup --- common/emu_constants.cpp | 20 + common/emu_constants.h | 127 ++++ zone/attack.cpp | 8 +- zone/bonuses.cpp | 4 +- zone/bot.cpp | 24 +- zone/client.cpp | 33 +- zone/client.h | 2 +- zone/client_packet.cpp | 1278 +++++++++++++++++++++--------------- zone/common.h | 62 +- zone/embparser.cpp | 7 + zone/embparser_api.cpp | 12 + zone/event_codes.h | 1 + zone/lua_general.cpp | 15 +- zone/lua_mob.cpp | 31 +- zone/lua_mob.h | 7 +- zone/lua_parser.cpp | 5 +- zone/lua_parser_events.cpp | 33 + zone/lua_parser_events.h | 19 + zone/mob.cpp | 22 +- zone/mob.h | 27 +- zone/mob_ai.cpp | 10 +- zone/npc.cpp | 2 +- zone/perl_mob.cpp | 20 +- zone/pets.cpp | 16 +- zone/pets.h | 2 +- zone/special_attacks.cpp | 2 +- zone/spell_effects.cpp | 34 +- zone/zoning.cpp | 2 +- 28 files changed, 1146 insertions(+), 679 deletions(-) diff --git a/common/emu_constants.cpp b/common/emu_constants.cpp index 670aeb9813..ecb1e4c580 100644 --- a/common/emu_constants.cpp +++ b/common/emu_constants.cpp @@ -451,3 +451,23 @@ bool LDoNTheme::IsValid(uint32 theme_id) { return ldon_theme_names.find(theme_id) != ldon_theme_names.end(); } + +std::string PetCommand::GetName(uint8 pet_command) +{ + return IsValid(pet_command) ? pet_commands[pet_command] : "UNKNOWN PET COMMAND"; +} + +bool PetCommand::IsValid(uint8 pet_command) +{ + return pet_commands.find(pet_command) != pet_commands.end(); +} + +std::string PetType::GetName(uint8 pet_type) +{ + return IsValid(pet_type) ? pet_types[pet_type] : "UNKNOWN PET TYPE"; +} + +bool PetType::IsValid(uint8 pet_type) +{ + return pet_types.find(pet_type) != pet_types.end(); +} diff --git a/common/emu_constants.h b/common/emu_constants.h index 085fcd8288..0c762ffb8c 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -792,4 +792,131 @@ namespace BookType { constexpr uint8 ItemInfo = 2; } +namespace PetButton { + constexpr uint8 Sit = 0; + constexpr uint8 Stop = 1; + constexpr uint8 Regroup = 2; + constexpr uint8 Follow = 3; + constexpr uint8 Guard = 4; + constexpr uint8 Taunt = 5; + constexpr uint8 Hold = 6; + constexpr uint8 GreaterHold = 7; + constexpr uint8 Focus = 8; + constexpr uint8 SpellHold = 9; +} + +namespace PetButtonState { + constexpr uint8 Off = 0; + constexpr uint8 On = 1; +} + +namespace PetCommand { + constexpr uint8 HealthReport = 0; // /pet health or Pet Window + constexpr uint8 Leader = 1; // /pet leader or Pet Window + constexpr uint8 Attack = 2; // /pet attack or Pet Window + constexpr uint8 QAttack = 3; // /pet qattack or Pet Window + constexpr uint8 FollowMe = 4; // /pet follow or Pet Window + constexpr uint8 GuardHere = 5; // /pet guard or Pet Window + constexpr uint8 Sit = 6; // /pet sit or Pet Window + constexpr uint8 SitDown = 7; // /pet sit on + constexpr uint8 StandUp = 8; // /pet sit off + constexpr uint8 Stop = 9; // /pet stop or Pet Window - Not implemented + constexpr uint8 StopOn = 10; // /pet stop on - Not implemented + constexpr uint8 StopOff = 11; // /pet stop off - Not implemented + constexpr uint8 Taunt = 12; // /pet taunt or Pet Window + constexpr uint8 TauntOn = 13; // /pet taunt on + constexpr uint8 TauntOff = 14; // /pet taunt off + constexpr uint8 Hold = 15; // /pet hold or Pet Window, won't add to hate list unless attacking + constexpr uint8 HoldOn = 16; // /pet hold on + constexpr uint8 HoldOff = 17; // /pet hold off + constexpr uint8 GreaterHold = 18; // /pet ghold, will never add to hate list unless told to + constexpr uint8 GreaterHoldOn = 19; // /pet ghold on + constexpr uint8 GreaterHoldOff = 20; // /pet ghold off + constexpr uint8 SpellHold = 21; // /pet no cast or /pet spellhold or Pet Window + constexpr uint8 SpellHoldOn = 22; // /pet spellhold on + constexpr uint8 SpellHoldOff = 23; // /pet spellhold off + constexpr uint8 Focus = 24; // /pet focus or Pet Window + constexpr uint8 FocusOn = 25; // /pet focus on + constexpr uint8 FocusOff = 26; // /pet focus off + constexpr uint8 Feign = 27; // /pet feign + constexpr uint8 BackOff = 28; // /pet back off + constexpr uint8 GetLost = 29; // /pet get lost + constexpr uint8 GuardMe = 30; // Same as /pet follow, but different message in older clients + constexpr uint8 Regroup = 31; // /pet regroup, acts like classic hold + constexpr uint8 RegroupOn = 32; // /pet regroup on + constexpr uint8 RegroupOff = 33; // /pet regroup off + constexpr uint8 Max = 34; + + static std::map pet_commands = { + { PetCommand::HealthReport, "Health Report" }, + { PetCommand::Leader, "Leader" }, + { PetCommand::Attack, "Attack" }, + { PetCommand::QAttack, "QAttack" }, + { PetCommand::FollowMe, "Follow Me" }, + { PetCommand::GuardHere, "Guard Here" }, + { PetCommand::Sit, "Sit" }, + { PetCommand::SitDown, "Sit Down" }, + { PetCommand::StandUp, "Stand Up" }, + { PetCommand::Stop, "Stop" }, + { PetCommand::StopOn, "Stop On" }, + { PetCommand::StopOff, "Stop Off" }, + { PetCommand::Taunt, "Taunt" }, + { PetCommand::TauntOn, "Taunt On" }, + { PetCommand::TauntOff, "Taunt Off" }, + { PetCommand::Hold, "Hold" }, + { PetCommand::HoldOn, "Hold On" }, + { PetCommand::HoldOff, "Hold Off" }, + { PetCommand::GreaterHold, "Greater Hold" }, + { PetCommand::GreaterHoldOn, "Greater Hold On" }, + { PetCommand::GreaterHoldOff, "Greater Hold Off" }, + { PetCommand::SpellHold, "Spell Hold" }, + { PetCommand::SpellHoldOn, "Spell Hold On" }, + { PetCommand::SpellHoldOff, "Spell Hold Off" }, + { PetCommand::Focus, "Focus" }, + { PetCommand::FocusOn, "Focus On" }, + { PetCommand::FocusOff, "Focus Off" }, + { PetCommand::Feign, "Feign" }, + { PetCommand::BackOff, "Back Off" }, + { PetCommand::GetLost, "Get Lost" }, + { PetCommand::GuardMe, "Guard Me" }, + { PetCommand::Regroup, "Regroup" }, + { PetCommand::RegroupOn, "Regroup On" }, + { PetCommand::RegroupOff, "Regroup Off" }, + { PetCommand::Max, "Max" } + }; + + std::string GetName(uint8 pet_command); + bool IsValid(uint8 pet_command); +} + +namespace PetOrder { + constexpr uint8 Follow = 0; + constexpr uint8 Sit = 1; + constexpr uint8 Guard = 2; + constexpr uint8 Feign = 3; +} + +namespace PetType { + constexpr uint8 Familiar = 0; + constexpr uint8 Animation = 1; + constexpr uint8 Normal = 2; + constexpr uint8 Charmed = 3; + constexpr uint8 Follow = 4; + constexpr uint8 TargetLock = 5; + constexpr uint8 None = 255; + + static std::map pet_types = { + { PetType::Familiar, "Familiar" }, + { PetType::Animation, "Animation" }, + { PetType::Normal, "Normal" }, + { PetType::Charmed, "Charmed" }, + { PetType::Follow, "Follow" }, + { PetType::TargetLock, "Target Lock" }, + { PetType::None, "None" } + }; + + std::string GetName(uint8 pet_type); + bool IsValid(uint8 pet_type); +} + #endif /*COMMON_EMU_CONSTANTS_H*/ diff --git a/zone/attack.cpp b/zone/attack.cpp index f541c3e92c..5a26a9b8f0 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4113,11 +4113,11 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons if (IsPet()) { Mob *owner = GetOwner(); if (owner && owner->IsClient()) { - if (GetPetOrder() == SPO_Sit) { + if (GetPetOrder() == PetOrder::Sit) { SetPetOrder(GetPreviousPetOrder()); } // fix GUI sit button to be unpressed and stop sitting regen - owner->CastToClient()->SetPetCommandState(PET_BUTTON_SIT, 0); + owner->CastToClient()->SetPetCommandState(PetButton::Sit, PetButtonState::Off); SetAppearance(eaStanding); } } @@ -4147,12 +4147,12 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons if (IsClient() && !pet->IsPetStop()) { // if pet was sitting his new mode is previous setting of // follow or guard after the battle (live verified) - if (pet->GetPetOrder() == SPO_Sit) { + if (pet->GetPetOrder() == PetOrder::Sit) { pet->SetPetOrder(pet->GetPreviousPetOrder()); } // fix GUI sit button to be unpressed and stop sitting regen - CastToClient()->SetPetCommandState(PET_BUTTON_SIT, 0); + CastToClient()->SetPetCommandState(PetButton::Sit, PetButtonState::Off); pet->SetAppearance(eaStanding); } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index d81c3ddf8e..640e9ddd19 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1549,7 +1549,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; case SE_AddPetCommand: - if (base_value && limit_value < PET_MAXCOMMANDS) + if (base_value && limit_value < PetCommand::Max) newbon->PetCommands[limit_value] = true; break; @@ -1557,7 +1557,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) if (newbon->FeignedMinionChance < base_value) { newbon->FeignedMinionChance = base_value; } - newbon->PetCommands[PET_FEIGN] = true; + newbon->PetCommands[PetCommand::Feign] = true; break; case SE_AdditionalAura: diff --git a/zone/bot.cpp b/zone/bot.cpp index 7f1be16886..2716c88c64 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -99,7 +99,7 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm SetPullingFlag(false); SetReturningFlag(false); SetIsUsingItemClick(false); - m_previous_pet_order = SPO_Guard; + m_previous_pet_order = PetOrder::Guard; rest_timer.Disable(); m_ping_timer.Disable(); @@ -232,7 +232,7 @@ Bot::Bot( SetPullingFlag(false); SetReturningFlag(false); SetIsUsingItemClick(false); - m_previous_pet_order = SPO_Guard; + m_previous_pet_order = PetOrder::Guard; rest_timer.Disable(); m_ping_timer.Disable(); @@ -2313,7 +2313,7 @@ void Bot::AI_Process() bot_owner->SetBotPulling(false); if (GetPet()) { - GetPet()->SetPetOrder(SPO_Follow); + GetPet()->SetPetOrder(PetOrder::Follow); GetPet()->CastToNPC()->SaveGuardSpot(true); } @@ -2569,7 +2569,7 @@ void Bot::DoOutOfCombatChecks(Client* bot_owner, Mob* follow_mob, float leash_di bot_owner->SetBotPulling(false); if (GetPet()) { - GetPet()->SetPetOrder(SPO_Follow); + GetPet()->SetPetOrder(PetOrder::Follow); GetPet()->CastToNPC()->SaveGuardSpot(true); } } @@ -3198,7 +3198,7 @@ bool Bot::IsValidTarget( bot_owner->SetBotPulling(false); if (GetPet()) { - GetPet()->SetPetOrder(SPO_Follow); + GetPet()->SetPetOrder(PetOrder::Follow); GetPet()->CastToNPC()->SaveGuardSpot(true); } } @@ -3233,7 +3233,7 @@ Mob* Bot::GetBotTarget(Client* bot_owner) bot_owner->SetBotPulling(false); if (GetPet()) { - GetPet()->SetPetOrder(SPO_Follow); + GetPet()->SetPetOrder(PetOrder::Follow); GetPet()->CastToNPC()->SaveGuardSpot(true); } } @@ -3269,7 +3269,7 @@ bool Bot::ReturningFlagChecks(Client* bot_owner, Mob* leash_owner, float fm_dist bot_owner->SetBotPulling(false); if (GetPet()) { - GetPet()->SetPetOrder(SPO_Follow); + GetPet()->SetPetOrder(PetOrder::Follow); GetPet()->CastToNPC()->SaveGuardSpot(true); if (HasControllablePet(BotAnimEmpathy::BackOff)) { @@ -3313,7 +3313,7 @@ bool Bot::PullingFlagChecks(Client* bot_owner) { bot_owner->SetBotPulling(false); if (GetPet()) { - GetPet()->SetPetOrder(SPO_Follow); + GetPet()->SetPetOrder(PetOrder::Follow); GetPet()->CastToNPC()->SaveGuardSpot(true); } @@ -3494,7 +3494,7 @@ Client* Bot::SetLeashOwner(Client* bot_owner, Group* bot_group, Raid* raid, uint void Bot::SetOwnerTarget(Client* bot_owner) { if (GetPet() && (PULLING_BOT || RETURNING_BOT)) { - GetPet()->SetPetOrder(SPO_Follow); + GetPet()->SetPetOrder(PetOrder::Follow); } SetAttackFlag(false); @@ -3533,7 +3533,7 @@ void Bot::BotPullerProcess(Client* bot_owner, Raid* raid) { bot_owner->SetBotPulling(false); if (GetPet()) { - GetPet()->SetPetOrder(SPO_Follow); + GetPet()->SetPetOrder(PetOrder::Follow); GetPet()->CastToNPC()->SaveGuardSpot(true); } @@ -3562,7 +3562,7 @@ void Bot::BotPullerProcess(Client* bot_owner, Raid* raid) { if (HasControllablePet(BotAnimEmpathy::Guard)) { m_previous_pet_order = GetPet()->GetPetOrder(); GetPet()->CastToNPC()->SaveGuardSpot(GetPosition()); - GetPet()->SetPetOrder(SPO_Guard); + GetPet()->SetPetOrder(PetOrder::Guard); } } } @@ -13456,6 +13456,6 @@ bool Bot::HasControllablePet(uint8 ranks_required) { } return GetClass() != Class::Enchanter || - GetPet()->GetPetType() != petAnimation || + GetPet()->GetPetType() != PetType::Animation || GetAA(aaAnimationEmpathy) >= ranks_required; } diff --git a/zone/client.cpp b/zone/client.cpp index 17eb2bac50..2fa767d094 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -6415,17 +6415,17 @@ void Client::SuspendMinion(int value) // TODO: These pet command states need to be synced ... // Will just fix them for now if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { - SetPetCommandState(PET_BUTTON_SIT, 0); - SetPetCommandState(PET_BUTTON_STOP, 0); - SetPetCommandState(PET_BUTTON_REGROUP, 0); - SetPetCommandState(PET_BUTTON_FOLLOW, 1); - SetPetCommandState(PET_BUTTON_GUARD, 0); + SetPetCommandState(PetButton::Sit, PetButtonState::Off); + SetPetCommandState(PetButton::Stop, PetButtonState::Off); + SetPetCommandState(PetButton::Regroup, PetButtonState::Off); + SetPetCommandState(PetButton::Follow, PetButtonState::On); + SetPetCommandState(PetButton::Guard, PetButtonState::Off); // Taunt saved on client side for logging on with pet // In our db for when we zone. - SetPetCommandState(PET_BUTTON_HOLD, 0); - SetPetCommandState(PET_BUTTON_GHOLD, 0); - SetPetCommandState(PET_BUTTON_FOCUS, 0); - SetPetCommandState(PET_BUTTON_SPELLHOLD, 0); + SetPetCommandState(PetButton::Hold, PetButtonState::Off); + SetPetCommandState(PetButton::GreaterHold, PetButtonState::Off); + SetPetCommandState(PetButton::Focus, PetButtonState::Off); + SetPetCommandState(PetButton::SpellHold, PetButtonState::Off); } } else @@ -6906,9 +6906,9 @@ void Client::CheckLDoNHail(NPC* n) auto pet = GetPet(); if (pet) { - if (pet->GetPetType() == petCharmed) { + if (pet->GetPetType() == PetType::Charmed) { pet->BuffFadeByEffect(SE_Charm); - } else if (pet->GetPetType() == petNPCFollow) { + } else if (pet->GetPetType() == PetType::Follow) { pet->SetOwnerID(0); } else { pet->Depop(); @@ -9450,12 +9450,15 @@ void Client::ProcessAggroMeter() } } -void Client::SetPetCommandState(int button, int state) +void Client::SetPetCommandState(uint8 button, uint8 state) { auto app = new EQApplicationPacket(OP_PetCommandState, sizeof(PetCommandState_Struct)); - auto pcs = (PetCommandState_Struct *)app->pBuffer; - pcs->button_id = button; - pcs->state = state; + + auto s = (PetCommandState_Struct*) app->pBuffer; + + s->button_id = button; + s->state = state; + FastQueuePacket(&app); } diff --git a/zone/client.h b/zone/client.h index 87a9c1d961..d5e8f3ef4c 100644 --- a/zone/client.h +++ b/zone/client.h @@ -524,7 +524,7 @@ class Client : public Mob inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; } void ReloadExpansionProfileSetting(); - void SetPetCommandState(int button, int state); + void SetPetCommandState(uint8 button, uint8 state); bool AutoAttackEnabled() const { return auto_attack; } bool AutoFireEnabled() const { return auto_fire; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index bdcbbc13a5..1f273a191e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -955,17 +955,17 @@ void Client::CompleteConnect() // TODO: load these states // We at least will set them to the correct state for now if (m_ClientVersionBit & EQ::versions::maskUFAndLater && GetPet()) { - SetPetCommandState(PET_BUTTON_SIT, 0); - SetPetCommandState(PET_BUTTON_STOP, 0); - SetPetCommandState(PET_BUTTON_REGROUP, 0); - SetPetCommandState(PET_BUTTON_FOLLOW, 1); - SetPetCommandState(PET_BUTTON_GUARD, 0); + SetPetCommandState(PetButton::Sit, PetButtonState::Off); + SetPetCommandState(PetButton::Stop, PetButtonState::Off); + SetPetCommandState(PetButton::Regroup, PetButtonState::Off); + SetPetCommandState(PetButton::Follow, PetButtonState::On); + SetPetCommandState(PetButton::Guard, PetButtonState::Off); // Taunt saved on client side for logging on with pet // In our db for when we zone. - SetPetCommandState(PET_BUTTON_HOLD, 0); - SetPetCommandState(PET_BUTTON_GHOLD, 0); - SetPetCommandState(PET_BUTTON_FOCUS, 0); - SetPetCommandState(PET_BUTTON_SPELLHOLD, 0); + SetPetCommandState(PetButton::Hold, PetButtonState::Off); + SetPetCommandState(PetButton::GreaterHold, PetButtonState::Off); + SetPetCommandState(PetButton::Focus, PetButtonState::Off); + SetPetCommandState(PetButton::SpellHold, PetButtonState::Off); } database.LoadAuras(this); // this ends up spawning them so probably safer to load this later (here) @@ -11073,661 +11073,913 @@ void Client::Handle_OP_PDeletePetition(const EQApplicationPacket *app) return; } + void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) { if (app->size != sizeof(PetCommand_Struct)) { LogError("Wrong size: OP_PetCommands, size=[{}], expected [{}]", app->size, sizeof(PetCommand_Struct)); return; } + + auto* s = (PetCommand_Struct*) app->pBuffer; + char val1[20] = { 0 }; - PetCommand_Struct* pet = (PetCommand_Struct*)app->pBuffer; - Mob* mypet = GetPet(); - Mob *target = entity_list.GetMob(pet->target); - if (!mypet || pet->command == PET_LEADER) { - if (pet->command == PET_LEADER) { + Mob* pet = GetPet(); + Mob* t = entity_list.GetMob(s->target); + + if (!pet || s->command == PetCommand::Leader) { + if (s->command == PetCommand::Leader) { // we either send the ID of an NPC we're interested in or no ID for our own pet - if (target) { - auto owner = target->GetOwner(); - if (owner) - target->SayString(PET_LEADERIS, owner->GetCleanName()); - else - target->SayString(I_FOLLOW_NOONE); - } else if (mypet) { - mypet->SayString(PET_LEADERIS, GetName()); + if (t) { + Mob* owner = t->GetOwner(); + if (owner) { + t->SayString(PET_LEADERIS, owner->GetCleanName()); + } else { + t->SayString(I_FOLLOW_NOONE); + } + } else if (pet) { + pet->SayString(PET_LEADERIS, GetName()); } } return; } - if (mypet->GetPetType() == petTargetLock && (pet->command != PET_HEALTHREPORT && pet->command != PET_GETLOST)) + if (!pet->IsNPC()) { return; + } + + if ( + pet->GetPetType() == PetType::TargetLock && + s->command != PetCommand::HealthReport && + s->command != PetCommand::GetLost + ) { + return; + } // just let the command "/pet get lost" work for familiars - if (mypet->GetPetType() == petFamiliar && pet->command != PET_GETLOST) + if (pet->GetPetType() == PetType::Familiar && s->command != PetCommand::GetLost) { return; + } - uint32 PetCommand = pet->command; + const bool can_use_command = ( + (pet->GetPetType() == PetType::Animation && aabonuses.PetCommands[s->command]) || + pet->GetPetType() != PetType::Animation + ); - // Handle Sit/Stand toggle in UF and later. - /* - if (GetClientVersion() >= EQClientUnderfoot) - { - if (PetCommand == PET_SITDOWN) - if (mypet->GetPetOrder() == SPO_Sit) - PetCommand = PET_STANDUP; - } - */ + switch (s->command) { + case PetCommand::Attack: { + if ( + !t || + pet->IsFeared() || + !can_use_command || + t == this || + !( + DistanceSquaredNoZ(pet->GetPosition(), GetTarget()->GetPosition()) <= + (RuleR(Pets, AttackCommandRange) * RuleR(Pets, AttackCommandRange)) + ) || + DistanceSquared(pet->GetPosition(), t->GetPosition()) >= RuleR(Aggro, PetAttackRange) + ) { + break; + } - switch (PetCommand) - { - case PET_ATTACK: { - if (!target) - break; + if (RuleB(Pets, PetsRequireLoS) && !DoLosChecks(t)) { + pet->SayString(this, NOT_LEGAL_TARGET); + break; + } - if (RuleB(Pets, PetsRequireLoS) && !DoLosChecks(target)) { - mypet->SayString(this, NOT_LEGAL_TARGET); - break; - } + if (t->IsMezzed()) { + MessageString(Chat::NPCQuestSay, CANNOT_WAKE, pet->GetCleanName(), t->GetCleanName()); + break; + } - if (target->IsMezzed()) { - MessageString(Chat::NPCQuestSay, CANNOT_WAKE, mypet->GetCleanName(), target->GetCleanName()); - break; - } + if (!pet->IsAttackAllowed(t)) { + pet->SayString(this, NOT_LEGAL_TARGET); + break; + } - if (mypet->IsFeared()) - break; //prevent pet from attacking stuff while feared + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; - if (!mypet->IsAttackAllowed(target)) { - mypet->SayString(this, NOT_LEGAL_TARGET); - break; - } + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - // default range is 200, takes Z into account - // really they do something weird where they're added to the aggro list then remove them - // and will attack if they come in range -- too lazy, lets remove exploits for now - if (DistanceSquared(mypet->GetPosition(), target->GetPosition()) >= RuleR(Aggro, PetAttackRange)) { - // they say they're attacking then remove on live ... so they don't really say anything in this case ... - break; - } + pet->SetFeigned(false); - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - if (target != this && DistanceSquared(mypet->GetPosition(), target->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { - mypet->SetFeigned(false); - if (mypet->IsPetStop()) { - mypet->SetPetStop(false); - SetPetCommandState(PET_BUTTON_STOP, 0); - } - if (mypet->IsPetRegroup()) { - mypet->SetPetRegroup(false); - SetPetCommandState(PET_BUTTON_REGROUP, 0); - } + if (pet->IsPetStop()) { + pet->SetPetStop(false); + SetPetCommandState(PetButton::Stop, PetButtonState::Off); + } - // fix GUI sit button to be unpressed and stop sitting regen - SetPetCommandState(PET_BUTTON_SIT, 0); - if (mypet->GetPetOrder() == SPO_Sit || mypet->GetPetOrder() == SPO_FeignDeath) { - mypet->SetPetOrder(mypet->GetPreviousPetOrder()); - mypet->SetAppearance(eaStanding); - } + if (pet->IsPetRegroup()) { + pet->SetPetRegroup(false); + SetPetCommandState(PetButton::Regroup, PetButtonState::Off); + } - zone->AddAggroMob(); - // classic acts like qattack - int hate = 1; - if (mypet->IsEngaged()) { - auto top = mypet->GetHateMost(); - if (top && top != target) - hate += mypet->GetHateAmount(top) - mypet->GetHateAmount(target) + 100; // should be enough to cause target change + SetPetCommandState(PetButton::Sit, PetButtonState::Off); + + if (pet->GetPetOrder() == PetOrder::Sit || pet->GetPetOrder() == PetOrder::Feign) { + pet->SetPetOrder(pet->GetPreviousPetOrder()); + pet->SetAppearance(eaStanding); + } + + zone->AddAggroMob(); + + int hate = 1; // classic acts like qattack + if (pet->IsEngaged()) { + Mob* top = pet->GetHateMost(); + if (top && top != t) { + hate += pet->GetHateAmount(top) - pet->GetHateAmount(t) + 100; } - mypet->AddToHateList(target, hate, 0, true, false, false, SPELL_UNKNOWN, true); - MessageString(Chat::PetResponse, PET_ATTACKING, mypet->GetCleanName(), target->GetCleanName()); - SetTarget(target); } - } - break; - } - case PET_QATTACK: { - if (mypet->IsFeared()) - break; //prevent pet from attacking stuff while feared - if (!GetTarget()) { + pet->AddToHateList(t, hate, 0, true, false, false, SPELL_UNKNOWN, true); + MessageString(Chat::PetResponse, PET_ATTACKING, pet->GetCleanName(), t->GetCleanName()); + SetTarget(t); break; } + case PetCommand::QAttack: { + if ( + pet->IsFeared() || + !GetTarget() || + GetTarget() == this || + !can_use_command || + !( + DistanceSquaredNoZ(pet->GetPosition(), GetTarget()->GetPosition()) <= + (RuleR(Pets, AttackCommandRange) * RuleR(Pets, AttackCommandRange)) + ) + ) { + break; + } + + if (RuleB(Pets, PetsRequireLoS) && !DoLosChecks(GetTarget())) { + pet->SayString(this, NOT_LEGAL_TARGET); + break; + } + + if (GetTarget()->IsMezzed()) { + MessageString(Chat::NPCQuestSay, CANNOT_WAKE, pet->GetCleanName(), GetTarget()->GetCleanName()); + break; + } + + if (!pet->IsAttackAllowed(GetTarget())) { + pet->SayString(this, NOT_LEGAL_TARGET); + break; + } - if (RuleB(Pets, PetsRequireLoS) && !DoLosChecks(GetTarget())) { - mypet->SayString(this, NOT_LEGAL_TARGET); + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + pet->SetFeigned(false); + + if (pet->IsPetStop()) { + pet->SetPetStop(false); + SetPetCommandState(PetButton::Stop, PetButtonState::Off); + } + + if (pet->IsPetRegroup()) { + pet->SetPetRegroup(false); + SetPetCommandState(PetButton::Regroup, PetButtonState::Off); + } + + SetPetCommandState(PetButton::Sit, PetButtonState::Off); + + if (pet->GetPetOrder() == PetOrder::Sit || pet->GetPetOrder() == PetOrder::Feign) { + pet->SetPetOrder(pet->GetPreviousPetOrder()); + pet->SetAppearance(eaStanding); + } + + zone->AddAggroMob(); + pet->AddToHateList(GetTarget(), 1, 0, true, false, false, SPELL_UNKNOWN, true); + MessageString(Chat::PetResponse, PET_ATTACKING, pet->GetCleanName(), GetTarget()->GetCleanName()); break; } + case PetCommand::BackOff: { + if (pet->IsFeared() || !can_use_command) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + pet->SayString(this, Chat::PetResponse, PET_CALMING); + pet->WipeHateList(); + pet->SetTarget(nullptr); + + if (pet->IsPetStop()) { + pet->SetPetStop(false); + SetPetCommandState(PetButton::Stop, PetButtonState::Off); + } - if (GetTarget()->IsMezzed()) { - MessageString(Chat::NPCQuestSay, CANNOT_WAKE, mypet->GetCleanName(), GetTarget()->GetCleanName()); break; } + case PetCommand::HealthReport: { + if (!can_use_command) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - if (!mypet->IsAttackAllowed(GetTarget())) { - mypet->SayString(this, NOT_LEGAL_TARGET); + MessageString(Chat::PetResponse, PET_REPORT_HP, ConvertArrayF(pet->GetHPRatio(), val1)); + pet->ShowBuffs(this); break; } + case PetCommand::GetLost: { + if (pet->Charmed()) { + break; + } - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - if (GetTarget() != this && DistanceSquaredNoZ(mypet->GetPosition(), GetTarget()->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { - mypet->SetFeigned(false); - if (mypet->IsPetStop()) { - mypet->SetPetStop(false); - SetPetCommandState(PET_BUTTON_STOP, 0); - } - if (mypet->IsPetRegroup()) { - mypet->SetPetRegroup(false); - SetPetCommandState(PET_BUTTON_REGROUP, 0); - } + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; - // fix GUI sit button to be unpressed and stop sitting regen - SetPetCommandState(PET_BUTTON_SIT, 0); - if (mypet->GetPetOrder() == SPO_Sit || mypet->GetPetOrder() == SPO_FeignDeath) { - mypet->SetPetOrder(mypet->GetPreviousPetOrder()); - mypet->SetAppearance(eaStanding); - } + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - zone->AddAggroMob(); - mypet->AddToHateList(GetTarget(), 1, 0, true, false, false, SPELL_UNKNOWN, true); - MessageString(Chat::PetResponse, PET_ATTACKING, mypet->GetCleanName(), GetTarget()->GetCleanName()); + if (pet->GetPetType() == PetType::Charmed) { + pet->BuffFadeByEffect(SE_Charm); + break; + } else { + SetPet(nullptr); } - } - break; - } - case PET_BACKOFF: { - if (mypet->IsFeared()) break; //keeps pet running while feared - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - mypet->SayString(this, Chat::PetResponse, PET_CALMING); - mypet->WipeHateList(); - mypet->SetTarget(nullptr); - if (mypet->IsPetStop()) { - mypet->SetPetStop(false); - SetPetCommandState(PET_BUTTON_STOP, 0); - } - } - break; - } - case PET_HEALTHREPORT: { - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - MessageString(Chat::PetResponse, PET_REPORT_HP, ConvertArrayF(mypet->GetHPRatio(), val1)); - mypet->ShowBuffs(this); - } - break; - } - case PET_GETLOST: { - if (mypet->Charmed()) - break; - if (mypet->GetPetType() == petCharmed || !mypet->IsNPC()) { - // eqlive ignores this command - // we could just remove the charm - // and continue - mypet->BuffFadeByEffect(SE_Charm); + pet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); + pet->CastToNPC()->Depop(); break; } - else { - SetPet(nullptr); - } + case PetCommand::GuardHere: { + if (pet->IsFeared() || !can_use_command) { + break; + } - mypet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); - mypet->CastToNPC()->Depop(); + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; - //Oddly, the client (Titanium) will still allow "/pet get lost" command despite me adding the code below. If someone can figure that out, you can uncomment this code and use it. - /* - if((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) { - mypet->SayString(PET_GETLOST_STRING); - mypet->CastToNPC()->Depop(); - } - */ + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - break; - } - case PET_GUARDHERE: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - if (mypet->IsNPC()) { - - // Set Sit button to unpressed - send stand anim/end hpregen - mypet->SetFeigned(false); - SetPetCommandState(PET_BUTTON_SIT, 0); - mypet->SetAppearance(eaStanding); - - mypet->SayString(this, Chat::PetResponse, PET_GUARDINGLIFE); - mypet->SetPetOrder(SPO_Guard); - mypet->CastToNPC()->SaveGuardSpot(mypet->GetPosition()); - if (!mypet->GetTarget()) // want them to not twitch if they're chasing something down - mypet->StopNavigation(); - if (mypet->IsPetStop()) { - mypet->SetPetStop(false); - SetPetCommandState(PET_BUTTON_STOP, 0); - } + pet->SetFeigned(false); + SetPetCommandState(PetButton::Sit, PetButtonState::Off); + pet->SetAppearance(eaStanding); + pet->SayString(this, Chat::PetResponse, PET_GUARDINGLIFE); + pet->SetPetOrder(PetOrder::Guard); + pet->CastToNPC()->SaveGuardSpot(pet->GetPosition()); + + if (!pet->GetTarget()) { + pet->StopNavigation(); } + + if (pet->IsPetStop()) { + pet->SetPetStop(false); + SetPetCommandState(PetButton::Stop, PetButtonState::Off); + } + + break; } - break; - } - case PET_FOLLOWME: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + case PetCommand::FollowMe: { + if (pet->IsFeared() || !can_use_command) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - mypet->SetFeigned(false); - mypet->SayString(this, Chat::PetResponse, PET_FOLLOWING); - mypet->SetPetOrder(SPO_Follow); + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - // fix GUI sit button to be unpressed - send stand anim/end hpregen - SetPetCommandState(PET_BUTTON_SIT, 0); - mypet->SetAppearance(eaStanding); + pet->SetFeigned(false); + pet->SayString(this, Chat::PetResponse, PET_FOLLOWING); + pet->SetPetOrder(PetOrder::Follow); + SetPetCommandState(PetButton::Sit, PetButtonState::Off); + pet->SetAppearance(eaStanding); - if (mypet->IsPetStop()) { - mypet->SetPetStop(false); - SetPetCommandState(PET_BUTTON_STOP, 0); + if (pet->IsPetStop()) { + pet->SetPetStop(false); + SetPetCommandState(PetButton::Stop, PetButtonState::Off); } + + break; } - break; - } - case PET_TAUNT: { - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - if (mypet->CastToNPC()->IsTaunting()) - { - MessageString(Chat::PetResponse, PET_NO_TAUNT); - mypet->CastToNPC()->SetTaunting(false); - } - else - { - MessageString(Chat::PetResponse, PET_DO_TAUNT); - mypet->CastToNPC()->SetTaunting(true); + case PetCommand::Taunt: { + if (!can_use_command) { + break; } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + MessageString(Chat::PetResponse, pet->CastToNPC()->IsTaunting() ? PET_NO_TAUNT : PET_DO_TAUNT); + pet->CastToNPC()->SetTaunting(!pet->CastToNPC()->IsTaunting()); + break; } - break; - } - case PET_TAUNT_ON: { - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + case PetCommand::TauntOn: { + if (!can_use_command) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + MessageString(Chat::PetResponse, PET_DO_TAUNT); - mypet->CastToNPC()->SetTaunting(true); + pet->CastToNPC()->SetTaunting(true); + break; } - break; - } - case PET_TAUNT_OFF: { - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + case PetCommand::TauntOff: { + if (!can_use_command) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + MessageString(Chat::PetResponse, PET_NO_TAUNT); - mypet->CastToNPC()->SetTaunting(false); + pet->CastToNPC()->SetTaunting(false); + break; } - break; - } - case PET_GUARDME: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + case PetCommand::GuardMe: { + if (pet->IsFeared() || can_use_command) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - mypet->SetFeigned(false); - mypet->SayString(this, Chat::PetResponse, PET_GUARDME_STRING); - mypet->SetPetOrder(SPO_Follow); + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - // Set Sit button to unpressed - send stand anim/end hpregen - SetPetCommandState(PET_BUTTON_SIT, 0); - mypet->SetAppearance(eaStanding); + pet->SetFeigned(false); + pet->SayString(this, Chat::PetResponse, PET_GUARDME_STRING); + pet->SetPetOrder(PetOrder::Follow); + SetPetCommandState(PetButton::Sit, PetButtonState::Off); + pet->SetAppearance(eaStanding); - if (mypet->IsPetStop()) { - mypet->SetPetStop(false); - SetPetCommandState(PET_BUTTON_STOP, 0); + if (pet->IsPetStop()) { + pet->SetPetStop(false); + SetPetCommandState(PetButton::Stop, PetButtonState::Off); } - } - break; - } - case PET_SIT: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - if (mypet->GetPetOrder() == SPO_Sit) - { - mypet->SetFeigned(false); - mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING); - mypet->SetPetOrder(mypet->GetPreviousPetOrder()); - mypet->SetAppearance(eaStanding); + break; + } + case PetCommand::Sit: { + if (pet->IsFeared() || !can_use_command) { + break; } - else - { - mypet->SetFeigned(false); - mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING); - mypet->SetPetOrder(SPO_Sit); - mypet->SetRunAnimSpeed(0); - if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet - mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting - mypet->SetAppearance(eaSitting); + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + pet->SetFeigned(false); + pet->SayString(this, Chat::PetResponse, PET_SIT_STRING); + pet->SetPetOrder(pet->GetPetOrder() == PetOrder::Sit ? pet->GetPreviousPetOrder() : PetOrder::Sit); + pet->SetAppearance(pet->GetPetOrder() == PetOrder::Sit ? eaStanding : eaSitting); + + if (pet->GetPetOrder() != PetOrder::Sit) { + pet->SetRunAnimSpeed(0); + + if (!pet->UseBardSpellLogic()) { + pet->InterruptSpell(); + } } + + break; } - break; - } - case PET_STANDUP: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + case PetCommand::StandUp: { + if (pet->IsFeared() || !can_use_command) { + break; + } - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - mypet->SetFeigned(false); - mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING); - SetPetCommandState(PET_BUTTON_SIT, 0); - mypet->SetPetOrder(mypet->GetPreviousPetOrder()); - mypet->SetAppearance(eaStanding); + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + pet->SetFeigned(false); + pet->SayString(this, Chat::PetResponse, PET_SIT_STRING); + SetPetCommandState(PetButton::Sit, PetButtonState::Off); + pet->SetPetOrder(pet->GetPreviousPetOrder()); + pet->SetAppearance(eaStanding); + break; } - break; - } - case PET_SITDOWN: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + case PetCommand::SitDown: { + if (pet->IsFeared() || !can_use_command) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - mypet->SetFeigned(false); - mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING); - SetPetCommandState(PET_BUTTON_SIT, 1); - mypet->SetPetOrder(SPO_Sit); - mypet->SetRunAnimSpeed(0); - if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet - mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting - mypet->SetAppearance(eaSitting); + pet->SetFeigned(false); + pet->SayString(this, Chat::PetResponse, PET_SIT_STRING); + SetPetCommandState(PetButton::Sit, PetButtonState::On); + pet->SetPetOrder(PetOrder::Sit); + pet->SetRunAnimSpeed(0); + + if (!pet->UseBardSpellLogic()){ + pet->InterruptSpell(); + } + + pet->SetAppearance(eaSitting); + break; } - break; - } - case PET_HOLD: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { - if (mypet->IsHeld()) - { - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) - MessageString(Chat::PetResponse, PET_HOLD_SET_OFF); - mypet->SetHeld(false); + case PetCommand::Hold: { + if (!aabonuses.PetCommands[s->command]) { + break; } - else - { - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + if (pet->IsHeld()) { + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { + MessageString(Chat::PetResponse, PET_HOLD_SET_OFF); + } + + pet->SetHeld(false); + } else { + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { MessageString(Chat::PetResponse, PET_HOLD_SET_ON); + } - if (m_ClientVersionBit & EQ::versions::maskUFAndLater) - mypet->SayString(this, Chat::PetResponse, PET_NOW_HOLDING); - else - mypet->SayString(this, Chat::PetResponse, PET_ON_HOLD); + if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { + pet->SayString(this, Chat::PetResponse, PET_NOW_HOLDING); + } else { + pet->SayString(this, Chat::PetResponse, PET_ON_HOLD); + } - mypet->SetHeld(true); + pet->SetHeld(true); } - mypet->SetGHeld(false); - SetPetCommandState(PET_BUTTON_GHOLD, 0); + + pet->SetGHeld(false); + SetPetCommandState(PetButton::GreaterHold, PetButtonState::Off); + break; } - break; - } - case PET_HOLD_ON: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && !mypet->IsHeld()) { - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) + case PetCommand::HoldOn: { + if (!pet->IsHeld() || !aabonuses.PetCommands[s->command]) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { MessageString(Chat::PetResponse, PET_HOLD_SET_ON); + } - if (m_ClientVersionBit & EQ::versions::maskUFAndLater) - mypet->SayString(this, Chat::PetResponse, PET_NOW_HOLDING); - else - mypet->SayString(this, Chat::PetResponse, PET_ON_HOLD); - mypet->SetHeld(true); - mypet->SetGHeld(false); - SetPetCommandState(PET_BUTTON_GHOLD, 0); + if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { + pet->SayString(this, Chat::PetResponse, PET_NOW_HOLDING); + } else { + pet->SayString(this, Chat::PetResponse, PET_ON_HOLD); + } + + pet->SetHeld(true); + pet->SetGHeld(false); + SetPetCommandState(PetButton::GreaterHold, PetButtonState::Off); + break; } - break; - } - case PET_HOLD_OFF: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsHeld()) { - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) + case PetCommand::HoldOff: { + if (!pet->IsHeld() || !aabonuses.PetCommands[s->command]) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { MessageString(Chat::PetResponse, PET_HOLD_SET_OFF); - mypet->SetHeld(false); + } + + pet->SetHeld(false); + break; } - break; - } - case PET_GHOLD: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { - if (mypet->IsGHeld()) - { - if (m_ClientVersionBit & EQ::versions::maskUFAndLater) - MessageString(Chat::PetResponse, PET_OFF_GHOLD); - mypet->SetGHeld(false); + case PetCommand::GreaterHold: { + if (!aabonuses.PetCommands[s->command]) { + break; } - else - { + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + if (pet->IsGHeld()) { + if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { + MessageString(Chat::PetResponse, PET_OFF_GHOLD); + } + + pet->SetGHeld(false); + } else { if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { MessageString(Chat::PetResponse, PET_ON_GHOLD); - mypet->SayString(this, Chat::PetResponse, PET_GHOLD_ON_MSG); + pet->SayString(this, Chat::PetResponse, PET_GHOLD_ON_MSG); } else { - mypet->SayString(this, Chat::PetResponse, PET_ON_HOLD); + pet->SayString(this, Chat::PetResponse, PET_ON_HOLD); } - mypet->SetGHeld(true); + + pet->SetGHeld(true); } - mypet->SetHeld(false); - SetPetCommandState(PET_BUTTON_HOLD, 0); + + pet->SetHeld(false); + SetPetCommandState(PetButton::Hold, PetButtonState::Off); + break; } - break; - } - case PET_GHOLD_ON: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { + case PetCommand::GreaterHoldOn: { + if (!aabonuses.PetCommands[s->command]) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { MessageString(Chat::PetResponse, PET_ON_GHOLD); - mypet->SayString(this, Chat::PetResponse, PET_GHOLD_ON_MSG); + pet->SayString(this, Chat::PetResponse, PET_GHOLD_ON_MSG); } else { - mypet->SayString(this, Chat::PetResponse, PET_ON_HOLD); + pet->SayString(this, Chat::PetResponse, PET_ON_HOLD); } - mypet->SetGHeld(true); - mypet->SetHeld(false); - SetPetCommandState(PET_BUTTON_HOLD, 0); + + pet->SetGHeld(true); + pet->SetHeld(false); + SetPetCommandState(PetButton::Hold, PetButtonState::Off); + break; } - break; - } - case PET_GHOLD_OFF: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsGHeld()) { - if (m_ClientVersionBit & EQ::versions::maskUFAndLater) + case PetCommand::GreaterHoldOff: { + if (!pet->IsGHeld() || !aabonuses.PetCommands[s->command]) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { MessageString(Chat::PetResponse, PET_OFF_GHOLD); - mypet->SetGHeld(false); + } + + pet->SetGHeld(false); + break; } - break; - } - case PET_SPELLHOLD: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { - if (mypet->IsFeared()) + case PetCommand::SpellHold: { + if (pet->IsFeared() || !aabonuses.PetCommands[s->command]) { break; - if (mypet->IsNoCast()) { - MessageString(Chat::PetResponse, PET_CASTING); - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) - MessageString(Chat::PetResponse, PET_SPELLHOLD_SET_OFF); - mypet->SetNoCast(false); } - else { - MessageString(Chat::PetResponse, PET_NOT_CASTING); - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) - MessageString(Chat::PetResponse, PET_SPELLHOLD_SET_ON); - mypet->SetNoCast(true); + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + MessageString(Chat::PetResponse, pet->IsNoCast() ? PET_CASTING : PET_NOT_CASTING); + + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { + MessageString(Chat::PetResponse, pet->IsNoCast() ? PET_SPELLHOLD_SET_OFF : PET_SPELLHOLD_SET_ON); } + + pet->SetNoCast(!pet->IsNoCast()); + break; } - break; - } - case PET_SPELLHOLD_ON: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { - if (mypet->IsFeared()) + case PetCommand::SpellHoldOn: { + if (pet->IsFeared() || pet->IsNoCast() || !aabonuses.PetCommands[s->command]) { break; - if (!mypet->IsNoCast()) { - MessageString(Chat::PetResponse, PET_NOT_CASTING); - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) - MessageString(Chat::PetResponse, PET_SPELLHOLD_SET_ON); - mypet->SetNoCast(true); } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + MessageString(Chat::PetResponse, PET_NOT_CASTING); + + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { + MessageString(Chat::PetResponse, PET_SPELLHOLD_SET_ON); + } + + pet->SetNoCast(true); + break; } - break; - } - case PET_SPELLHOLD_OFF: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { - if (mypet->IsFeared()) + case PetCommand::SpellHoldOff: { + if (pet->IsFeared() || !pet->IsNoCast() || !aabonuses.PetCommands[s->command]) { break; - if (mypet->IsNoCast()) { - MessageString(Chat::PetResponse, PET_CASTING); - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) - MessageString(Chat::PetResponse, PET_SPELLHOLD_SET_OFF); - mypet->SetNoCast(false); } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + MessageString(Chat::PetResponse, PET_CASTING); + + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { + MessageString(Chat::PetResponse, PET_SPELLHOLD_SET_OFF); + } + + pet->SetNoCast(false); + break; } - break; - } - case PET_FOCUS: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { - if (mypet->IsFeared()) + case PetCommand::Focus: { + if (pet->IsFeared() || !aabonuses.PetCommands[s->command]) { break; - if (mypet->IsFocused()) { - MessageString(Chat::PetResponse, PET_NOT_FOCUSING); - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) - MessageString(Chat::PetResponse, PET_FOCUS_SET_OFF); - mypet->SetFocused(false); } - else { - MessageString(Chat::PetResponse, PET_NOW_FOCUSING); - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) - MessageString(Chat::PetResponse, PET_FOCUS_SET_ON); - mypet->SetFocused(true); + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + MessageString(Chat::PetResponse, pet->IsFocused() ? PET_NOT_FOCUSING : PET_NOW_FOCUSING); + + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { + MessageString(Chat::PetResponse, pet->IsFocused() ? PET_FOCUS_SET_OFF : PET_FOCUS_SET_ON); } + + pet->SetFocused(!pet->IsFocused()); + break; } - break; - } - case PET_FOCUS_ON: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { - if (mypet->IsFeared()) + case PetCommand::FocusOn: { + if (pet->IsFeared() || pet->IsFocused() || !aabonuses.PetCommands[s->command]) { break; - if (!mypet->IsFocused()) { - MessageString(Chat::PetResponse, PET_NOW_FOCUSING); - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) - MessageString(Chat::PetResponse, PET_FOCUS_SET_ON); - mypet->SetFocused(true); } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + MessageString(Chat::PetResponse, PET_NOW_FOCUSING); + + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { + MessageString(Chat::PetResponse, PET_FOCUS_SET_ON); + } + + pet->SetFocused(true); + break; } - break; - } - case PET_FOCUS_OFF: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { - if (mypet->IsFeared()) + case PetCommand::FocusOff: { + if (pet->IsFeared() || !pet->IsFocused() || !aabonuses.PetCommands[s->command]) { break; - if (mypet->IsFocused()) { - MessageString(Chat::PetResponse, PET_NOT_FOCUSING); - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) - MessageString(Chat::PetResponse, PET_FOCUS_SET_OFF); - mypet->SetFocused(false); } - } - break; - } - case PET_FEIGN: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { - if (mypet->IsFeared()) - break; + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + MessageString(Chat::PetResponse, PET_NOT_FOCUSING); - int pet_fd_chance = aabonuses.FeignedMinionChance; - if (zone->random.Int(0, 99) > pet_fd_chance) { - mypet->SetFeigned(false); - entity_list.MessageCloseString(this, false, 200, 10, STRING_FEIGNFAILED, mypet->GetCleanName()); + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { + MessageString(Chat::PetResponse, PET_FOCUS_SET_OFF); } - else { - bool has_aggro_immunity = GetSpecialAbility(SpecialAbility::AggroImmunity); - mypet->SetSpecialAbility(SpecialAbility::AggroImmunity, 1); - mypet->WipeHateList(); - mypet->SetPetOrder(SPO_FeignDeath); - mypet->SetRunAnimSpeed(0); - mypet->StopNavigation(); - mypet->SetAppearance(eaDead); - mypet->SetFeigned(true); - mypet->SetTarget(nullptr); - if (!mypet->UseBardSpellLogic()) { - mypet->InterruptSpell(); + + pet->SetFocused(false); + break; + } + case PetCommand::Feign: { + if (pet->IsFeared() || !aabonuses.PetCommands[s->command]) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + if (zone->random.Int(0, 99) > aabonuses.FeignedMinionChance) { + pet->SetFeigned(false); + entity_list.MessageCloseString(this, false, 200, 10, STRING_FEIGNFAILED, pet->GetCleanName()); + } else { + pet->SetSpecialAbility(SpecialAbility::AggroImmunity, 1); + pet->WipeHateList(); + pet->SetPetOrder(PetOrder::Feign); + pet->SetRunAnimSpeed(0); + pet->StopNavigation(); + pet->SetAppearance(eaDead); + pet->SetFeigned(true); + pet->SetTarget(nullptr); + + if (!pet->UseBardSpellLogic()) { + pet->InterruptSpell(); } - if (!has_aggro_immunity) { - mypet->SetSpecialAbility(SpecialAbility::AggroImmunity, 0); + if (!GetSpecialAbility(SpecialAbility::AggroImmunity)) { + pet->SetSpecialAbility(SpecialAbility::AggroImmunity, 0); } } + + break; } - break; - } - case PET_STOP: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + case PetCommand::Stop: { + if (pet->IsFeared() || !can_use_command) { + break; + } - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - if (mypet->IsPetStop()) { - mypet->SetPetStop(false); + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + if (pet->IsPetStop()) { + pet->SetPetStop(false); } else { - mypet->SetPetStop(true); - mypet->StopNavigation(); - mypet->SetTarget(nullptr); - if (mypet->IsPetRegroup()) { - mypet->SetPetRegroup(false); - SetPetCommandState(PET_BUTTON_REGROUP, 0); + pet->SetPetStop(true); + pet->StopNavigation(); + pet->SetTarget(nullptr); + + if (pet->IsPetRegroup()) { + pet->SetPetRegroup(false); + SetPetCommandState(PetButton::Regroup, PetButtonState::Off); } } - mypet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); + + pet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); + break; } - break; - } - case PET_STOP_ON: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + case PetCommand::StopOn: { + if (pet->IsFeared() || pet->IsPetStop() || !can_use_command) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - mypet->SetPetStop(true); - mypet->StopNavigation(); - mypet->SetTarget(nullptr); - mypet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); - if (mypet->IsPetRegroup()) { - mypet->SetPetRegroup(false); - SetPetCommandState(PET_BUTTON_REGROUP, 0); + pet->SetPetStop(true); + pet->StopNavigation(); + pet->SetTarget(nullptr); + pet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); + + if (pet->IsPetRegroup()) { + pet->SetPetRegroup(false); + SetPetCommandState(PetButton::Regroup, PetButtonState::Off); } + + break; } - break; - } - case PET_STOP_OFF: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + case PetCommand::StopOff: { + if (pet->IsFeared() || !pet->IsPetStop() || !can_use_command) { + break; + } - if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - mypet->SetPetStop(false); - mypet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; + + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + pet->SetPetStop(false); + pet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); + break; } - break; - } - case PET_REGROUP: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + case PetCommand::Regroup: { + if (pet->IsFeared() || !aabonuses.PetCommands[s->command]) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; - if (aabonuses.PetCommands[PetCommand]) { - if (mypet->IsPetRegroup()) { - mypet->SetPetRegroup(false); - mypet->SayString(this, Chat::PetResponse, PET_OFF_REGROUPING); + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + if (pet->IsPetRegroup()) { + pet->SetPetRegroup(false); + pet->SayString(this, Chat::PetResponse, PET_OFF_REGROUPING); } else { - mypet->SetPetRegroup(true); - mypet->SetTarget(nullptr); - mypet->SayString(this, Chat::PetResponse, PET_ON_REGROUPING); - if (mypet->IsPetStop()) { - mypet->SetPetStop(false); - SetPetCommandState(PET_BUTTON_STOP, 0); + pet->SetPetRegroup(true); + pet->SetTarget(nullptr); + pet->SayString(this, Chat::PetResponse, PET_ON_REGROUPING); + + if (pet->IsPetStop()) { + pet->SetPetStop(false); + SetPetCommandState(PetButton::Stop, PetButtonState::Off); } } + + break; } - break; - } - case PET_REGROUP_ON: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + case PetCommand::RegroupOn: { + if (pet->IsFeared() || pet->IsPetRegroup() || !aabonuses.PetCommands[s->command]) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; - if (aabonuses.PetCommands[PetCommand]) { - mypet->SetPetRegroup(true); - mypet->SetTarget(nullptr); - mypet->SayString(this, Chat::PetResponse, PET_ON_REGROUPING); - if (mypet->IsPetStop()) { - mypet->SetPetStop(false); - SetPetCommandState(PET_BUTTON_STOP, 0); + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + pet->SetPetRegroup(true); + pet->SetTarget(nullptr); + pet->SayString(this, Chat::PetResponse, PET_ON_REGROUPING); + + if (pet->IsPetStop()) { + pet->SetPetStop(false); + SetPetCommandState(PetButton::Stop, PetButtonState::Off); } + + break; } - break; - } - case PET_REGROUP_OFF: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + case PetCommand::RegroupOff: { + if (pet->IsFeared() || !pet->IsPetRegroup() || !aabonuses.PetCommands[s->command]) { + break; + } + + std::function f = [&s]() { + return PetCommand::GetName(s->command); + }; - if (aabonuses.PetCommands[PetCommand]) { - mypet->SetPetRegroup(false); - mypet->SayString(this, Chat::PetResponse, PET_OFF_REGROUPING); + parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); + parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + + pet->SetPetRegroup(false); + pet->SayString(this, Chat::PetResponse, PET_OFF_REGROUPING); + break; + } + default: { + LogError("[{}] attempted to use an unknown pet command: [{}]", GetCleanName(), s->command); + break; } - break; - } - default: - printf("Client attempted to use a unknown pet command:\n"); - break; } } diff --git a/zone/common.h b/zone/common.h index 10c17b7a6e..5c5e12f796 100644 --- a/zone/common.h +++ b/zone/common.h @@ -3,6 +3,7 @@ #include "../common/types.h" #include "../common/spdat.h" +#include "../common/emu_constants.h" #include @@ -45,55 +46,6 @@ namespace Archetype { //Maximum distance from a zone point if zone was specified #define ZONEPOINT_ZONE_RANGE 40000.0f -// Defines based on the RoF2 Client -#define PET_HEALTHREPORT 0 // 0x00 - /pet health or Pet Window -#define PET_LEADER 1 // 0x01 - /pet leader or Pet Window -#define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window -#define PET_QATTACK 3 // 0x03 - /pet qattack or Pet Window -#define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window -#define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window -#define PET_SIT 6 // 0x06 - /pet sit or Pet Window -#define PET_SITDOWN 7 // 0x07 - /pet sit on -#define PET_STANDUP 8 // 0x08 - /pet sit off -#define PET_STOP 9 // 0x09 - /pet stop or Pet Window - Not implemented -#define PET_STOP_ON 10 // 0x0a - /pet stop on - Not implemented -#define PET_STOP_OFF 11 // 0x0b - /pet stop off - Not implemented -#define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window -#define PET_TAUNT_ON 13 // 0x0d - /pet taunt on -#define PET_TAUNT_OFF 14 // 0x0e - /pet taunt off -#define PET_HOLD 15 // 0x0f - /pet hold or Pet Window, won't add to hate list unless attacking -#define PET_HOLD_ON 16 // 0x10 - /pet hold on -#define PET_HOLD_OFF 17 // 0x11 - /pet hold off -#define PET_GHOLD 18 // 0x12 - /pet ghold, will never add to hate list unless told to -#define PET_GHOLD_ON 19 // 0x13 - /pet ghold on -#define PET_GHOLD_OFF 20 // 0x14 - /pet ghold off -#define PET_SPELLHOLD 21 // 0x15 - /pet no cast or /pet spellhold or Pet Window -#define PET_SPELLHOLD_ON 22 // 0x16 - /pet spellhold on -#define PET_SPELLHOLD_OFF 23 // 0x17 - /pet spellhold off -#define PET_FOCUS 24 // 0x18 - /pet focus or Pet Window -#define PET_FOCUS_ON 25 // 0x19 - /pet focus on -#define PET_FOCUS_OFF 26 // 0x1a - /pet focus off -#define PET_FEIGN 27 // 0x1b - /pet feign -#define PET_BACKOFF 28 // 0x1c - /pet back off -#define PET_GETLOST 29 // 0x1d - /pet get lost -#define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client /pet target in modern clients but doesn't send packet -#define PET_REGROUP 31 // 0x1f - /pet regroup, acts like classic hold. Stops attack and moves back to guard/you but doesn't clear hate list -#define PET_REGROUP_ON 32 // 0x20 - /pet regroup on, turns on regroup -#define PET_REGROUP_OFF 33 // 0x21 - /pet regroup off, turns off regroup -#define PET_MAXCOMMANDS PET_REGROUP_OFF + 1 - -// can change the state of these buttons with a packet -#define PET_BUTTON_SIT 0 -#define PET_BUTTON_STOP 1 -#define PET_BUTTON_REGROUP 2 -#define PET_BUTTON_FOLLOW 3 -#define PET_BUTTON_GUARD 4 -#define PET_BUTTON_TAUNT 5 -#define PET_BUTTON_HOLD 6 -#define PET_BUTTON_GHOLD 7 -#define PET_BUTTON_FOCUS 8 -#define PET_BUTTON_SPELLHOLD 9 - #define AURA_HARDCAP 2 #define WEAPON_STANCE_TYPE_MAX 2 @@ -617,7 +569,7 @@ struct StatBonuses { uint8 TradeSkillMastery; // Allow number of tradeskills to exceed 200 skill. int16 NoBreakAESneak; // Percent value int16 FeignedCastOnChance; // Percent Value - bool PetCommands[PET_MAXCOMMANDS]; // SPA 267 + bool PetCommands[PetCommand::Max]; // SPA 267 int FeignedMinionChance; // SPA 281 base1 = chance, just like normal FD int GrantForage; // affects max skill of forage as well as granting non-forage classes forage int aura_slots; @@ -781,16 +733,6 @@ enum { GridRandomPath }; -typedef enum { - petFamiliar, //only listens to /pet get lost - petAnimation, //does not listen to any commands - petOther, - petCharmed, - petNPCFollow, - petTargetLock, //remain active as long something is on the hatelist. Don't listen to any commands - petNone = 0xFF // not a pet -} PetType; - typedef enum { SingleTarget, // causes effect to spell_target AETarget, // causes effect in aerange of target + target diff --git a/zone/embparser.cpp b/zone/embparser.cpp index bd4eabc0d9..6d220b8d81 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -207,6 +207,7 @@ const char* QuestEventSubroutines[_LargestEventID] = { "EVENT_AA_LOSS", "EVENT_SPELL_BLOCKED", "EVENT_READ_ITEM", + "EVENT_PET_COMMAND", // Add new events before these or Lua crashes "EVENT_SPELL_EFFECT_BOT", @@ -2532,6 +2533,12 @@ void PerlembParser::ExportEventVariables( break; } + case EVENT_PET_COMMAND: { + ExportVar(package_name.c_str(), "pet_command", extra_data); + ExportVar(package_name.c_str(), "pet_command_name", data); + break; + } + default: { break; } diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index c305532f72..feedab7fd4 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -6039,6 +6039,16 @@ perl::array Perl__get_timers(Mob* m) return a; } +std::string Perl__get_pet_command_name(uint8 pet_command) +{ + return PetCommand::GetName(pet_command); +} + +std::string Perl__get_pet_type_name(uint8 pet_type) +{ + return PetType::GetName(pet_type); +} + void perl_register_quest() { perl::interpreter perl(PERL_GET_THX); @@ -6729,6 +6739,8 @@ void perl_register_quest() package.add("getgroupidbycharid", &Perl__getgroupidbycharid); package.add("getinventoryslotname", &Perl__getinventoryslotname); package.add("get_paused_timers", &Perl__get_paused_timers); + package.add("get_pet_command_name", &Perl__get_pet_command_name); + package.add("get_pet_type_name", &Perl__get_pet_type_name); package.add("getraididbycharid", &Perl__getraididbycharid); package.add("get_race_bitmask", &Perl__get_race_bitmask); package.add("get_recipe_component_item_ids", &Perl__GetRecipeComponentItemIDs); diff --git a/zone/event_codes.h b/zone/event_codes.h index aeee133934..0d14f565d2 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -145,6 +145,7 @@ typedef enum { EVENT_AA_LOSS, EVENT_SPELL_BLOCKED, EVENT_READ_ITEM, + EVENT_PET_COMMAND, // Add new events before these or Lua crashes EVENT_SPELL_EFFECT_BOT, diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index ae3242885b..ae8c4b2af0 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -5701,6 +5701,16 @@ luabind::object lua_get_timers(lua_State* L, Mob* m) { return t; } +std::string lua_get_pet_command_name(uint8 pet_command) +{ + return PetCommand::GetName(pet_command); +} + +std::string lua_get_pet_type_name(uint8 pet_type) +{ + return PetType::GetName(pet_type); +} + #define LuaCreateNPCParse(name, c_type, default_value) do { \ cur = table[#name]; \ if(luabind::type(cur) != LUA_TNIL) { \ @@ -6514,6 +6524,8 @@ luabind::scope lua_register_general() { luabind::def("handin", &lua_handin), luabind::def("get_paused_timers", &lua_get_paused_timers), luabind::def("get_timers", &lua_get_timers), + luabind::def("get_pet_command_name", &lua_get_pet_command_name), + luabind::def("get_pet_type_name", &lua_get_pet_type_name), /* Cross Zone */ @@ -6979,7 +6991,8 @@ luabind::scope lua_register_events() { luabind::value("entity_variable_set", static_cast(EVENT_ENTITY_VARIABLE_SET)), luabind::value("entity_variable_update", static_cast(EVENT_ENTITY_VARIABLE_UPDATE)), luabind::value("aa_loss", static_cast(EVENT_AA_LOSS)), - luabind::value("read", static_cast(EVENT_READ_ITEM)) + luabind::value("read", static_cast(EVENT_READ_ITEM)), + luabind::value("pet_command", static_cast(EVENT_PET_COMMAND)) )]; } diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 23890987ee..e23eb2d034 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1241,12 +1241,12 @@ float Lua_Mob::GetAssistRange() { return self->GetAssistRange(); } -void Lua_Mob::SetPetOrder(int order) { +void Lua_Mob::SetPetOrder(uint8 pet_order) { Lua_Safe_Call_Void(); - self->SetPetOrder(static_cast(order)); + self->SetPetOrder(pet_order); } -int Lua_Mob::GetPetOrder() { +uint8 Lua_Mob::GetPetOrder() { Lua_Safe_Call_Int(); return self->GetPetOrder(); } @@ -3512,6 +3512,24 @@ luabind::object Lua_Mob::GetTimers(lua_State* L) { return t; } +uint8 Lua_Mob::GetPetType() +{ + Lua_Safe_Call_Int(); + return self->GetPetType(); +} + +std::string Lua_Mob::GetPetTypeName() +{ + Lua_Safe_Call_String(); + return PetType::GetName(self->GetPetType()); +} + +void Lua_Mob::SetPetType(uint8 pet_type) +{ + Lua_Safe_Call_Void(); + self->SetPetType(pet_type); +} + luabind::scope lua_register_mob() { return luabind::class_("Mob") .def(luabind::constructor<>()) @@ -3854,7 +3872,9 @@ luabind::scope lua_register_mob() { .def("GetPR", &Lua_Mob::GetPR) .def("GetPausedTimers", &Lua_Mob::GetPausedTimers) .def("GetPet", &Lua_Mob::GetPet) - .def("GetPetOrder", (int(Lua_Mob::*)(void))&Lua_Mob::GetPetOrder) + .def("GetPetOrder", (uint8(Lua_Mob::*)(void))&Lua_Mob::GetPetOrder) + .def("GetPetType", &Lua_Mob::GetPetType) + .def("GetPetTypeName", &Lua_Mob::GetPetTypeName) .def("GetPhR", &Lua_Mob::GetPhR) .def("GetRace", &Lua_Mob::GetRace) .def("GetRaceName", &Lua_Mob::GetRaceName) @@ -4049,7 +4069,8 @@ luabind::scope lua_register_mob() { .def("SetMana", &Lua_Mob::SetMana) .def("SetOOCRegen", (void(Lua_Mob::*)(int64))&Lua_Mob::SetOOCRegen) .def("SetPet", &Lua_Mob::SetPet) - .def("SetPetOrder", (void(Lua_Mob::*)(int))&Lua_Mob::SetPetOrder) + .def("SetPetOrder", (void(Lua_Mob::*)(uint8))&Lua_Mob::SetPetOrder) + .def("SetPetType", &Lua_Mob::SetPetType) .def("SetPseudoRoot", (void(Lua_Mob::*)(bool))&Lua_Mob::SetPseudoRoot) .def("SetRace", (void(Lua_Mob::*)(uint16))&Lua_Mob::SetRace) .def("SetRunning", (void(Lua_Mob::*)(bool))&Lua_Mob::SetRunning) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index f95794a10c..b5019aa5f6 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -280,8 +280,8 @@ class Lua_Mob : public Lua_Entity bool IsAIControlled(); float GetAggroRange(); float GetAssistRange(); - void SetPetOrder(int order); - int GetPetOrder(); + void SetPetOrder(uint8 pet_order); + uint8 GetPetOrder(); bool IsRoamer(); bool IsRooted(); bool IsEngaged(); @@ -614,6 +614,9 @@ class Lua_Mob : public Lua_Entity void BuffFadeSongs(); luabind::object GetPausedTimers(lua_State* L); luabind::object GetTimers(lua_State* L); + uint8 GetPetType(); + std::string GetPetTypeName(); + void SetPetType(uint8 pet_type); }; #endif diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 0f8dded50e..c3f37aec57 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -188,7 +188,8 @@ const char *LuaEvents[_LargestEventID] = { "event_entity_variable_update", "event_aa_loss", "event_spell_blocked", - "event_read_item" + "event_read_item", + "event_pet_command" }; extern Zone *zone; @@ -264,6 +265,7 @@ LuaParser::LuaParser() { NPCArgumentDispatch[EVENT_ENTITY_VARIABLE_SET] = handle_npc_entity_variable; NPCArgumentDispatch[EVENT_ENTITY_VARIABLE_UPDATE] = handle_npc_entity_variable; NPCArgumentDispatch[EVENT_SPELL_BLOCKED] = handle_npc_spell_blocked; + NPCArgumentDispatch[EVENT_PET_COMMAND] = handle_npc_pet_command; PlayerArgumentDispatch[EVENT_SAY] = handle_player_say; PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage; @@ -355,6 +357,7 @@ LuaParser::LuaParser() { PlayerArgumentDispatch[EVENT_SPELL_BLOCKED] = handle_player_spell_blocked; PlayerArgumentDispatch[EVENT_READ_ITEM] = handle_player_read_item; PlayerArgumentDispatch[EVENT_CONNECT] = handle_player_connect; + PlayerArgumentDispatch[EVENT_PET_COMMAND] = handle_player_pet_command; ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click; ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click; diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index 153775e785..68dd7ca2ab 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -668,6 +668,23 @@ void handle_npc_spell_blocked( lua_setfield(L, -2, "cast_spell"); } +void handle_npc_pet_command( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) +{ + lua_pushinteger(L, extra_data); + lua_setfield(L, -2, "pet_command"); + + lua_pushstring(L, data.c_str()); + lua_setfield(L, -2, "pet_command_name"); +} + // Player void handle_player_say( QuestInterface *parse, @@ -1829,6 +1846,22 @@ void handle_player_connect( lua_setfield(L, -2, "is_first_login"); } +void handle_player_pet_command( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) +{ + lua_pushinteger(L, extra_data); + lua_setfield(L, -2, "pet_command"); + + lua_pushstring(L, data.c_str()); + lua_setfield(L, -2, "pet_command_name"); +} + // Item void handle_item_click( QuestInterface *parse, diff --git a/zone/lua_parser_events.h b/zone/lua_parser_events.h index 0adb7ba997..79135bd6e6 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -262,6 +262,16 @@ void handle_npc_spell_blocked( std::vector *extra_pointers ); +void handle_npc_pet_command( + QuestInterface *parse, + lua_State* L, + NPC* npc, + Mob *init, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + // Player void handle_player_say( QuestInterface *parse, @@ -875,6 +885,15 @@ void handle_player_connect( std::vector *extra_pointers ); +void handle_player_pet_command( + QuestInterface *parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + // Item void handle_item_click( QuestInterface *parse, diff --git a/zone/mob.cpp b/zone/mob.cpp index 7d6f3229eb..0a167201d5 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -392,7 +392,7 @@ Mob::Mob( spellbonuses.AssistRange = -1; SetPetID(0); SetOwnerID(0); - SetPetType(petNone); // default to not a pet + SetPetType(PetType::None); // default to not a pet SetPetPower(0); held = false; gheld = false; @@ -454,8 +454,8 @@ Mob::Mob( weaponstance.itembonus_buff_spell_id = 0; weaponstance.aabonus_buff_spell_id = 0; - pStandingPetOrder = SPO_Follow; - m_previous_pet_order = SPO_Follow; + m_pet_order = PetOrder::Follow; + m_previous_pet_order = PetOrder::Follow; pseudo_rooted = false; nobuff_invisible = 0; @@ -623,7 +623,7 @@ bool Mob::HasAnInvisibilityEffect() { void Mob::BreakCharmPetIfConditionsMet() { auto pet = GetPet(); - if (pet && pet->GetPetType() == petCharmed && HasAnInvisibilityEffect()) { + if (pet && pet->GetPetType() == PetType::Charmed && HasAnInvisibilityEffect()) { if (RuleB(Pets, LivelikeBreakCharmOnInvis) || IsInvisible(pet)) { pet->BuffFadeByEffect(SE_Charm); } @@ -655,14 +655,14 @@ void Mob::CalcInvisibleLevel() BreakCharmPetIfConditionsMet(); } -void Mob::SetPetOrder(eStandingPetOrder i) { - if (i == SPO_Sit || i == SPO_FeignDeath) { - if (pStandingPetOrder == SPO_Follow || pStandingPetOrder == SPO_Guard) { - m_previous_pet_order = pStandingPetOrder; +void Mob::SetPetOrder(uint8 pet_order) { + if (pet_order == PetOrder::Sit || pet_order == PetOrder::Feign) { + if (m_pet_order == PetOrder::Follow || m_pet_order == PetOrder::Guard) { + m_previous_pet_order = m_pet_order; } } - pStandingPetOrder = i; + m_pet_order = pet_order; } void Mob::SetInvisible(uint8 state, bool set_on_bonus_calc) { @@ -4567,8 +4567,8 @@ void Mob::SetOwnerID(uint16 new_owner_id) { if ( !ownerid && IsNPC() && - GetPetType() != petCharmed && - GetPetType() != petNone + GetPetType() != PetType::Charmed && + GetPetType() != PetType::None ) { Depop(); } diff --git a/zone/mob.h b/zone/mob.h index 193d8aae28..ca0abe2682 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -98,7 +98,6 @@ class Mob : public Entity { public: enum CLIENT_CONN_STATUS { CLIENT_CONNECTING, CLIENT_CONNECTED, CLIENT_LINKDEAD, CLIENT_KICKED, DISCONNECTED, CLIENT_ERROR, CLIENT_CONNECTINGALL }; - enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard, SPO_FeignDeath }; struct MobSpecialAbility { MobSpecialAbility() { @@ -601,7 +600,7 @@ class Mob : public Entity { inline const char* GetName() const { return name; } inline const char* GetOrigName() const { return orig_name; } inline const char* GetLastName() const { return lastname; } - inline const eStandingPetOrder GetPreviousPetOrder() const { return m_previous_pet_order; } + inline const uint8 GetPreviousPetOrder() const { return m_previous_pet_order; } const char *GetCleanName(); virtual void SetName(const char *new_name = nullptr) { new_name ? strn0cpy(name, new_name, 64) : strn0cpy(name, GetName(), 64); return; }; @@ -1083,14 +1082,14 @@ class Mob : public Entity { Mob* GetUltimateOwner(); void SetPetID(uint16 NewPetID); inline uint16 GetPetID() const { return petid; } - inline PetType GetPetType() const { return type_of_pet; } - void SetPetType(PetType p) { type_of_pet = p; } + inline uint8 GetPetType() const { return type_of_pet; } + void SetPetType(uint8 pet_type) { type_of_pet = pet_type; } inline int16 GetPetPower() const { return (petpower < 0) ? 0 : petpower; } void SetPetPower(int16 p) { if (p < 0) petpower = 0; else petpower = p; } - bool IsFamiliar() const { return type_of_pet == petFamiliar; } - bool IsAnimation() const { return type_of_pet == petAnimation; } - bool IsCharmed() const { return type_of_pet == petCharmed; } - bool IsTargetLockPet() const { return type_of_pet == petTargetLock; } + bool IsFamiliar() const { return type_of_pet == PetType::Familiar; } + bool IsAnimation() const { return type_of_pet == PetType::Animation; } + bool IsCharmed() const { return type_of_pet == PetType::Charmed; } + bool IsTargetLockPet() const { return type_of_pet == PetType::TargetLock; } inline uint32 GetPetTargetLockID() { return pet_targetlock_id; }; inline void SetPetTargetLockID(uint32 value) { pet_targetlock_id = value; }; void SetOwnerID(uint16 new_owner_id); @@ -1212,8 +1211,8 @@ class Mob : public Entity { inline const float GetAssistRange() const { return (spellbonuses.AssistRange == -1) ? pAssistRange : spellbonuses.AssistRange; } - void SetPetOrder(eStandingPetOrder i); - inline const eStandingPetOrder GetPetOrder() const { return pStandingPetOrder; } + void SetPetOrder(uint8 pet_order); + inline const uint8 GetPetOrder() const { return m_pet_order; } inline void SetHeld(bool nState) { held = nState; } inline const bool IsHeld() const { return held; } inline void SetGHeld(bool nState) { gheld = nState; } @@ -1300,7 +1299,7 @@ class Mob : public Entity { bool IsPetAggroExempt(Mob *pet_owner); void InstillDoubt(Mob *who); - bool Charmed() const { return type_of_pet == petCharmed; } + bool Charmed() const { return type_of_pet == PetType::Charmed; } static uint32 GetLevelHP(uint8 tlevel); uint32 GetZoneID() const; //for perl uint16 GetInstanceVersion() const; //for perl @@ -1596,7 +1595,7 @@ class Mob : public Entity { StatBonuses aabonuses; uint16 petid; uint16 ownerid; - PetType type_of_pet; + uint8 type_of_pet; int16 petpower; uint32 follow_id; uint32 follow_dist; @@ -1825,8 +1824,8 @@ class Mob : public Entity { Timer viral_timer; // MobAI stuff - eStandingPetOrder pStandingPetOrder; - eStandingPetOrder m_previous_pet_order; + uint8 m_pet_order; + uint8 m_previous_pet_order; uint32 minLastFightingDelayMoving; uint32 maxLastFightingDelayMoving; float pAggroRange = 0; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index f39797c108..173fae7a5f 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1397,8 +1397,8 @@ void Mob::AI_Process() { else if (AI_movement_timer->Check() && !IsRooted()) { if (IsPet()) { // we're a pet, do as we're told - switch (pStandingPetOrder) { - case SPO_Follow: { + switch (m_pet_order) { + case PetOrder::Follow: { Mob *owner = GetOwner(); if (owner == nullptr) { @@ -1447,18 +1447,18 @@ void Mob::AI_Process() { break; } - case SPO_Sit: { + case PetOrder::Sit: { SetAppearance(eaSitting, false); break; } - case SPO_Guard: { + case PetOrder::Guard: { //only NPCs can guard stuff. (forced by where the guard movement code is in the AI) if (IsNPC()) { CastToNPC()->NextGuardPosition(); } break; } - case SPO_FeignDeath: { + case PetOrder::Feign: { SetAppearance(eaDead, false); break; } diff --git a/zone/npc.cpp b/zone/npc.cpp index c0b2954fdd..de97d0fb5e 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -4014,7 +4014,7 @@ void NPC::SetTaunting(bool is_taunting) { taunting = is_taunting; if (IsPet() && IsPetOwnerClient()) { - GetOwner()->CastToClient()->SetPetCommandState(PET_BUTTON_TAUNT, is_taunting); + GetOwner()->CastToClient()->SetPetCommandState(PetButton::Taunt, is_taunting); } } diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 3261140309..dd06db33b8 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -1114,11 +1114,16 @@ uint16 Perl_Mob_GetOwnerID(Mob* self) // @categories Script Utility, Pet return self->GetOwnerID(); } -int Perl_Mob_GetPetType(Mob* self) // @categories Script Utility, Pet +uint8 Perl_Mob_GetPetType(Mob* self) // @categories Script Utility, Pet { return self->GetPetType(); } +std::string Perl_Mob_GetPetTypeName(Mob* self) // @categories Script Utility, Pet +{ + return PetType::GetName(self->GetPetType()); +} + int Perl_Mob_GetBodyType(Mob* self) // @categories Stats and Attributes { return self->GetBodyType(); @@ -1254,12 +1259,12 @@ float Perl_Mob_GetAssistRange(Mob* self) // @categories Stats and Attributes, Ha return self->GetAssistRange(); } -void Perl_Mob_SetPetOrder(Mob* self, int order) // @categories Pet +void Perl_Mob_SetPetOrder(Mob* self, uint8 pet_order) // @categories Pet { - self->SetPetOrder(static_cast(order)); + self->SetPetOrder(pet_order); } -int Perl_Mob_GetPetOrder(Mob* self) // @categories Script Utility, Pet +uint8 Perl_Mob_GetPetOrder(Mob* self) // @categories Script Utility, Pet { return self->GetPetOrder(); } @@ -3597,6 +3602,11 @@ perl::array Perl_Mob_GetTimers(Mob* self) return a; } +void Perl_Mob_SetPetType(Mob* self, uint8 pet_type) +{ + self->SetPetType(pet_type); +} + void perl_register_mob() { perl::interpreter perl(PERL_GET_THX); @@ -3926,6 +3936,7 @@ void perl_register_mob() package.add("GetPetID", &Perl_Mob_GetPetID); package.add("GetPetOrder", &Perl_Mob_GetPetOrder); package.add("GetPetType", &Perl_Mob_GetPetType); + package.add("GetPetTypeName", &Perl_Mob_GetPetTypeName); package.add("GetPhR", &Perl_Mob_GetPhR); package.add("GetRace", &Perl_Mob_GetRace); package.add("GetRaceName", &Perl_Mob_GetRaceName); @@ -4187,6 +4198,7 @@ void perl_register_mob() package.add("SetPet", &Perl_Mob_SetPet); package.add("SetPetID", &Perl_Mob_SetPetID); package.add("SetPetOrder", &Perl_Mob_SetPetOrder); + package.add("SetPetType", &Perl_Mob_SetPetType); package.add("SetRace", &Perl_Mob_SetRace); package.add("SetRunAnimSpeed", &Perl_Mob_SetRunAnimSpeed); package.add("SetRunning", &Perl_Mob_SetRunning); diff --git a/zone/pets.cpp b/zone/pets.cpp index 37028e60a2..2c8db2d317 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -267,7 +267,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, } //this takes ownership of the npc_type data - auto npc = new Pet(npc_type, this, (PetType)record.petcontrol, spell_id, record.petpower); + auto npc = new Pet(npc_type, this, record.petcontrol, spell_id, record.petpower); // Now that we have an actual object to interact with, load // the base items for the pet. These are always loaded @@ -295,7 +295,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, SetPetID(npc->GetID()); // We need to handle PetType 5 (petHatelist), add the current target to the hatelist of the pet - if (record.petcontrol == petTargetLock) + if (record.petcontrol == PetType::TargetLock) { Mob* m_target = GetTarget(); @@ -341,7 +341,7 @@ void NPC::TryDepopTargetLockedPets(Mob* current_target) { return; } //Use when pets are given petype 5 - if (IsPet() && GetPetType() == petTargetLock && GetPetTargetLockID()) { + if (IsPet() && GetPetType() == PetType::TargetLock && GetPetTargetLockID()) { CastSpell(SPELL_UNSUMMON_SELF, GetID()); //Live like behavior, damages self for 20K if (!HasDied()) { Kill(); //Ensure pet dies if over 20k HP. @@ -356,11 +356,11 @@ void NPC::TryDepopTargetLockedPets(Mob* current_target) { /* This is why the pets ghost - pets were being spawned too far away from its npc owner and some into walls or objects (+10), this sometimes creates the "ghost" effect. I changed to +2 (as close as I could get while it still looked good). I also noticed this can happen if an NPC is spawned on the same spot of another or in a related bad spot.*/ -Pet::Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 power) +Pet::Pet(NPCType *type_data, Mob *owner, uint8 pet_type, uint16 spell_id, int16 power) : NPC(type_data, 0, owner->GetPosition() + glm::vec4(2.0f, 2.0f, 0.0f, 0.0f), GravityBehavior::Water) { GiveNPCTypeData(type_data); - SetPetType(type); + SetPetType(pet_type); SetPetPower(power); SetOwnerID(owner ? owner->GetID() : 0); SetPetSpellID(spell_id); @@ -374,8 +374,8 @@ Pet::Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 po if (owner && owner->IsClient()) { if (!(owner->CastToClient()->ClientVersionBit() & EQ::versions::maskUFAndLater)) { if ( - (GetPetType() != petFamiliar && GetPetType() != petAnimation) || - aabonuses.PetCommands[PET_TAUNT] + (GetPetType() != PetType::Familiar && GetPetType() != PetType::Animation) || + aabonuses.PetCommands[PetCommand::Taunt] ) { SetTaunting(true); } @@ -587,7 +587,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) && _CLIENTPET(this) && GetPetType() <= petOther); + bool petCanHaveNoDrop = (RuleB(Pets, CanTakeNoDrop) && _CLIENTPET(this) && GetPetType() <= PetType::Normal); if (!noDrop || petCanHaveNoDrop) { AddLootDrop(item2, LootdropEntriesRepository::NewNpcEntity(), true); diff --git a/zone/pets.h b/zone/pets.h index f8ab50ecac..dc656fb085 100644 --- a/zone/pets.h +++ b/zone/pets.h @@ -6,7 +6,7 @@ struct NPCType; class Pet : public NPC { public: - Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 power); + Pet(NPCType *type_data, Mob *owner, uint8 pet_type, uint16 spell_id, int16 power); virtual bool CheckSpellLevelRestriction(Mob *caster, uint16 spell_id); }; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 4ce6bd1503..b1101e9c6b 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -1907,7 +1907,7 @@ void NPC::DoClassAttacks(Mob *target) { target->GetBodyType() != BodyType::Undead && taunt_time && type_of_pet && - type_of_pet != petTargetLock && + type_of_pet != PetType::TargetLock && DistanceSquared(GetPosition(), target->GetPosition()) <= (RuleI(Pets, PetTauntRange) * RuleI(Pets, PetTauntRange)) ) { GetOwner()->MessageString(Chat::PetResponse, PET_TAUNTING); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index e990287379..71b3b20245 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -803,19 +803,19 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove caster->SetPet(this); SetOwnerID(caster->GetID()); - SetPetOrder(SPO_Follow); + SetPetOrder(PetOrder::Follow); SetAppearance(eaStanding); // Client has saved previous pet sit/stand - make all new pets // stand and follow on charm. if (caster->IsClient()) { Client *cpet = caster->CastToClient(); - cpet->SetPetCommandState(PET_BUTTON_SIT,0); - cpet->SetPetCommandState(PET_BUTTON_FOLLOW, 1); - cpet->SetPetCommandState(PET_BUTTON_GUARD, 0); - cpet->SetPetCommandState(PET_BUTTON_STOP, 0); + cpet->SetPetCommandState(PetButton::Sit, PetButtonState::Off); + cpet->SetPetCommandState(PetButton::Follow, PetButtonState::On); + cpet->SetPetCommandState(PetButton::Guard, PetButtonState::Off); + cpet->SetPetCommandState(PetButton::Stop, PetButtonState::Off); } - SetPetType(petCharmed); + SetPetType(PetType::Charmed); // This was done in AddBuff, but we were not a pet yet, so // the target windows didn't get updated. @@ -1308,18 +1308,18 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (IsClient() && pet) { auto c = CastToClient(); if (c->ClientVersionBit() & EQ::versions::maskUFAndLater) { - c->SetPetCommandState(PET_BUTTON_SIT, 0); - c->SetPetCommandState(PET_BUTTON_STOP, 0); - c->SetPetCommandState(PET_BUTTON_REGROUP, 0); - c->SetPetCommandState(PET_BUTTON_FOLLOW, 1); - c->SetPetCommandState(PET_BUTTON_GUARD, 0); + c->SetPetCommandState(PetButton::Sit, PetButtonState::Off); + c->SetPetCommandState(PetButton::Stop, PetButtonState::Off); + c->SetPetCommandState(PetButton::Regroup, PetButtonState::Off); + c->SetPetCommandState(PetButton::Follow, PetButtonState::On); + c->SetPetCommandState(PetButton::Guard, PetButtonState::Off); // Creating pet from spell - taunt always false // If suspended pet - that will be restore there // If logging in, client will send toggle - c->SetPetCommandState(PET_BUTTON_HOLD, 0); - c->SetPetCommandState(PET_BUTTON_GHOLD, 0); - c->SetPetCommandState(PET_BUTTON_FOCUS, 0); - c->SetPetCommandState(PET_BUTTON_SPELLHOLD, 0); + c->SetPetCommandState(PetButton::Hold, PetButtonState::Off); + c->SetPetCommandState(PetButton::GreaterHold, PetButtonState::Off); + c->SetPetCommandState(PetButton::Focus, PetButtonState::Off); + c->SetPetCommandState(PetButton::SpellHold, PetButtonState::Off); } } } @@ -1618,7 +1618,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove GetOwnerID() && // I'm a pet caster && // there's a caster caster->GetID() == GetOwnerID() && // and it's my master - GetPetType() != petCharmed + GetPetType() != PetType::Charmed ) { uint16 pet_spellid = CastToNPC()->GetPetSpellID(); @@ -4427,7 +4427,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) SendAppearancePacket(AppearanceType::Pet, 0, true, true); Mob* owner = GetOwner(); SetOwnerID(0); - SetPetType(petNone); + SetPetType(PetType::None); SetHeld(false); SetGHeld(false); SetNoCast(false); diff --git a/zone/zoning.cpp b/zone/zoning.cpp index f857a6e204..96ad15dbc6 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -709,7 +709,7 @@ void Client::ProcessMovePC(uint32 zoneID, uint32 instance_id, float x, float y, //if they have a pet and they are staying in zone, move with them Mob *p = GetPet(); if(p != nullptr){ - p->SetPetOrder(SPO_Follow); + p->SetPetOrder(PetOrder::Follow); p->GMMove(x+15, y, z); //so it dosent have to run across the map. } } From 145111f11ecbb2c17b6c9bef7a3ee750a8246bf3 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Fri, 29 Aug 2025 06:52:51 -0400 Subject: [PATCH 026/194] [Bug Fix] Fix Task Reloading (#5002) --- zone/task_manager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp index 3e6ec9992b..d6df2ebb92 100644 --- a/zone/task_manager.cpp +++ b/zone/task_manager.cpp @@ -43,6 +43,8 @@ bool TaskManager::LoadTaskSets() bool TaskManager::LoadTasks(int single_task) { + m_task_data.clear(); + std::string task_query_filter = fmt::format("id = {}", single_task); if (single_task == 0) { if (!LoadTaskSets()) { From 02f66de67955c24c7b18224e256fa21d436aa683 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Fri, 29 Aug 2025 12:02:11 -0400 Subject: [PATCH 027/194] [Cleanup] Remove Unused errorname Variable (#5001) --- zone/entity.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index 0b94fc7ace..80623674e0 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -56,8 +56,6 @@ extern volatile bool is_zone_loaded; extern WorldServer worldserver; extern uint32 numclients; -extern char errorname[32]; - Entity::Entity() { id = 0; From 0c65a4febe402d4d395e50435ee1047cb6acc25a Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Fri, 29 Aug 2025 20:08:03 -0400 Subject: [PATCH 028/194] [Cleanup] Fix #set race 0 Message (#5004) --- zone/gm_commands/set/race.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/zone/gm_commands/set/race.cpp b/zone/gm_commands/set/race.cpp index 48bb11f0c1..4a5f86c31c 100755 --- a/zone/gm_commands/set/race.cpp +++ b/zone/gm_commands/set/race.cpp @@ -44,6 +44,19 @@ void SetRace(Client *c, const Seperator *sep) } ); + if (race_id == Race::Doug) { + c->Message( + Chat::White, + fmt::format( + "{} {} been returned to {} base race.", + c->GetTargetDescription(t, TargetDescriptionType::UCYou), + c == t ? "have" : "has", + c == t ? "your" : "their" + ).c_str() + ); + return; + } + c->Message( Chat::White, fmt::format( From 822a5dcac487e0ac5ac5597b11b312fcd8e0f7a7 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 30 Aug 2025 13:05:18 -0400 Subject: [PATCH 029/194] [Cleanup] Cleanup #show ip_lookup Message (#5005) * [Cleanup] Cleanup #show ip_lookup Message * Test * Update clientlist.cpp --- world/clientlist.cpp | 109 ++++++++++++++++++++-------- world/clientlist.h | 2 +- zone/gm_commands/show/ip_lookup.cpp | 2 +- 3 files changed, 79 insertions(+), 34 deletions(-) diff --git a/world/clientlist.cpp b/world/clientlist.cpp index 31eeb6d670..1671ca2adf 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -281,62 +281,107 @@ ClientListEntry* ClientList::FindCLEByCharacterID(uint32 iCharID) { return nullptr; } -void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* iName) { +void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* search_criteria) +{ LinkedListIterator iterator(clientlist); - int x = 0, y = 0; - int namestrlen = iName == 0 ? 0 : strlen(iName); - bool addnewline = false; - char newline[3]; - if (connection->IsConsole()) - strcpy(newline, "\r\n"); - else - strcpy(newline, "^"); - auto out = fmt::memory_buffer(); + int found_count = 0; + int total_count = 0; + int name_length = search_criteria ? strlen(search_criteria) : 0; + + const char* new_line = connection->IsConsole() ? "\r\n" : "^"; + bool add_new_line = false; + + std::string message; + iterator.Reset(); - while(iterator.MoreElements()) { + + while (iterator.MoreElements()) { ClientListEntry* cle = iterator.GetData(); - if (admin >= cle->Admin() && (iName == 0 || namestrlen == 0 || strncasecmp(cle->name(), iName, namestrlen) == 0 || strncasecmp(cle->AccountName(), iName, namestrlen) == 0 || strncasecmp(cle->LSName(), iName, namestrlen) == 0)) { - struct in_addr in; - in.s_addr = cle->GetIP(); - if (addnewline) { - fmt::format_to(std::back_inserter(out), fmt::runtime(newline)); + + struct in_addr in; + in.s_addr = cle->GetIP(); + + if ( + admin >= cle->Admin() && + ( + !search_criteria || + Strings::Contains(std::string(inet_ntoa(in)), search_criteria) || + Strings::Contains(cle->name(), search_criteria) == 0 || + Strings::Contains(cle->AccountName(), search_criteria) == 0 || + Strings::Contains(cle->LSName(), search_criteria) == 0 + ) + ) { + if (add_new_line) { + message += new_line; } - fmt::format_to(std::back_inserter(out), "ID: {} Acc# {} AccName: {} IP: {}", cle->GetID(), cle->AccountID(), cle->AccountName(), inet_ntoa(in)); - fmt::format_to(std::back_inserter(out), "{} Stale: {} Online: {} Admin: {}", newline, cle->GetStaleCounter(), static_cast(cle->Online()), cle->Admin()); - if (cle->LSID()) - fmt::format_to(std::back_inserter(out), "{} LSID: {} LSName: {} WorldAdmin: {}", newline, cle->LSID(), cle->LSName(), cle->WorldAdmin()); - if (cle->CharID()) - fmt::format_to(std::back_inserter(out), "{} CharID: {} CharName: {} Zone: {} ({})", newline, cle->CharID(), cle->name(), ZoneName(cle->zone()), cle->zone()); - if (out.size() >= 3072) { + + message += fmt::format( + "Account: {} ({}) | IP: {} | Admin: {}", + cle->AccountName(), + cle->AccountID(), + inet_ntoa(in), + cle->Admin() + ); + + if (cle->CharID()) { + message += fmt::format( + "{}Character: {} ({}) | Zone: {} ({})", + new_line, + cle->name(), + cle->CharID(), + ZoneLongName(cle->zone()), + cle->zone() + ); + } + + if (message.size() >= 3072) { connection->SendEmoteMessageRaw( to, 0, AccountStatus::Player, Chat::NPCQuestSay, - out.data() + message.c_str() ); - addnewline = false; - out.clear(); + message.clear(); + add_new_line = false; } else { - addnewline = true; + add_new_line = true; } - y++; + + found_count++; } + iterator.Advance(); - x++; + total_count++; } - fmt::format_to(std::back_inserter(out), "{}{} CLEs in memory. {} CLEs listed. numplayers = {}.", newline, x, y, numplayers); + + message += fmt::format( + "{}{}Player Count: {}", + new_line, + ( + found_count != total_count ? + fmt::format( + "Total: {} CLE{} | Found: {} CLE{} | ", + total_count, + (total_count != 1 ? "s" : ""), + found_count, + (found_count != 1 ? "s" : "") + ) : + "" + ), + numplayers + ); + connection->SendEmoteMessageRaw( to, 0, AccountStatus::Player, Chat::NPCQuestSay, - out.data() + message.c_str() ); } - void ClientList::CLEAdd( uint32 login_server_id, const char *login_server_name, diff --git a/world/clientlist.h b/world/clientlist.h index 64501f2650..b158ad28db 100644 --- a/world/clientlist.h +++ b/world/clientlist.h @@ -45,7 +45,7 @@ class ClientList { void SendClientVersionSummary(const char *Name); void SendLFGMatches(ServerLFGMatchesRequest_Struct *LFGMatchesRequest); void ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct* whom, WorldTCPConnection* connection); - void SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* iName = 0); + void SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* search_criteria = 0); bool SendPacket(const char* to, ServerPacket* pack); diff --git a/zone/gm_commands/show/ip_lookup.cpp b/zone/gm_commands/show/ip_lookup.cpp index b020541b47..aefcaeaf3c 100644 --- a/zone/gm_commands/show/ip_lookup.cpp +++ b/zone/gm_commands/show/ip_lookup.cpp @@ -9,7 +9,7 @@ void ShowIPLookup(Client *c, const Seperator *sep) auto pack = new ServerPacket( ServerOP_IPLookup, - sizeof(ServerGenericWorldQuery_Struct) + ip_length + 1 + sizeof(ServerGenericWorldQuery_Struct) + ip_length ); auto s = (ServerGenericWorldQuery_Struct *) pack->pBuffer; From 9668074d940617d1b357b6ed21d571bbcfa4df01 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 30 Aug 2025 13:56:14 -0400 Subject: [PATCH 030/194] [Bug Fix] Fix Recipe Inspect Bug (#4994) --- zone/client_packet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 1f273a191e..143a44d4e2 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -16001,7 +16001,7 @@ void Client::Handle_OP_TradeSkillRecipeInspect(const EQApplicationPacket* app) const auto& v = TradeskillRecipeEntriesRepository::GetWhere( content_db, fmt::format( - "`recipe_id` = {} AND `componentcount` = 0 AND `successcount` > 0 LIMIT 1", + "`recipe_id` = {} AND `componentcount` = 0 AND `successcount` > 0 ORDER BY `id` ASC LIMIT 1", s->recipe_id ) ); From 33df8ea6656771c1f2ad61a20bb8390c3890606d Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 30 Aug 2025 14:42:40 -0400 Subject: [PATCH 031/194] [Repositories] Convert Character Inspect Messages to Repositories (#4997) --- common/shareddb.cpp | 30 +++++++++++++++++++++--------- common/shareddb.h | 4 ++-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 0880e1f2ea..09a1909024 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -51,6 +51,7 @@ #include "repositories/inventory_repository.h" #include "repositories/books_repository.h" #include "repositories/sharedbank_repository.h" +#include "repositories/character_inspect_messages_repository.h" namespace ItemField { @@ -1906,18 +1907,29 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { LoadDamageShieldTypes(sp, max_spells); } -void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message) { - const std::string query = StringFormat("SELECT `inspect_message` FROM `character_inspect_messages` WHERE `id` = %u LIMIT 1", character_id); - auto results = QueryDatabase(query); - memset(message, '\0', sizeof(InspectMessage_Struct)); - for (auto& row = results.begin(); row != results.end(); ++row) { - memcpy(message, row[0], sizeof(InspectMessage_Struct)); +void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* s) +{ + const auto& e = CharacterInspectMessagesRepository::FindOne(*this, character_id); + + memset(s, '\0', sizeof(InspectMessage_Struct)); + + if (!e.id) { + return; } + + memcpy(s, e.inspect_message.c_str(), sizeof(InspectMessage_Struct)); } -void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message) { - const std::string query = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message) VALUES (%u, '%s')", character_id, Strings::Escape(message->text).c_str()); - auto results = QueryDatabase(query); +void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* s) +{ + auto e = CharacterInspectMessagesRepository::NewEntity(); + + e.id = character_id; + e.inspect_message = s->text; + + if (!CharacterInspectMessagesRepository::ReplaceOne(*this, e)) { + LogError("Failed to save character inspect message of [{}] for character_id [{}]", s->text, character_id); + } } uint32 SharedDatabase::GetSpellsCount() diff --git a/common/shareddb.h b/common/shareddb.h index d36132fd31..032865cbd4 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -76,8 +76,8 @@ class SharedDatabase : public Database { uint8 GetGMSpeed(uint32 account_id); bool SetHideMe(uint32 account_id, uint8 hideme); int DeleteStalePlayerCorpses(); - void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct *message); - void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct *message); + void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* s); + void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* s); bool GetCommandSettings(std::map>> &command_settings); bool UpdateInjectedCommandSettings(const std::vector> &injected); bool UpdateOrphanedCommandSettings(const std::vector &orphaned); From 92c8b0e5850c69cc590aa1c9224f2098011c5f40 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 30 Aug 2025 15:33:11 -0400 Subject: [PATCH 032/194] [Constants] Change Race Changes to Race Namespace (#5000) --- common/faction.cpp | 58 +- common/races.cpp | 3697 +++++++++++++-------------- common/races.h | 202 +- world/client.cpp | 40 +- world/clientlist.cpp | 2 +- zone/aa.cpp | 2 +- zone/attack.cpp | 8 +- zone/bot.cpp | 82 +- zone/bot_commands/appearance.cpp | 34 +- zone/bot_commands/bot.cpp | 52 +- zone/client.cpp | 2 +- zone/client_mods.cpp | 160 +- zone/client_packet.cpp | 18 +- zone/client_process.cpp | 2 +- zone/entity.cpp | 4 +- zone/exp.cpp | 14 +- zone/gm_commands/feature.cpp | 6 +- zone/gm_commands/randomfeatures.cpp | 2 +- zone/mob.cpp | 38 +- zone/npc.cpp | 6 +- zone/special_attacks.cpp | 6 +- zone/tradeskills.cpp | 4 +- zone/worldserver.cpp | 2 +- 23 files changed, 2086 insertions(+), 2355 deletions(-) diff --git a/common/faction.cpp b/common/faction.cpp index 29cf45e58c..793991593c 100644 --- a/common/faction.cpp +++ b/common/faction.cpp @@ -95,12 +95,12 @@ bool IsOfEqualRace(int r1, int r2) } // TODO: add more values switch (r1) { - case DARK_ELF: + case Race::DarkElf: if (r2 == Race::NeriakCitizen) { return true; } break; - case BARBARIAN: + case Race::Barbarian: if (r2 == Race::HalasCitizen) { return true; } @@ -116,49 +116,49 @@ bool IsOfIndiffRace(int r1, int r2) } // TODO: add more values switch (r1) { - case DARK_ELF: - case OGRE: - case TROLL: - if (r2 == OGRE || r2 == TROLL || r2 == DARK_ELF) { + case Race::DarkElf: + case Race::Ogre: + case Race::Troll: + if (r2 == Race::Ogre || r2 == Race::Troll || r2 == Race::DarkElf) { return true; } break; - case HUMAN: - case BARBARIAN: - case HALF_ELF: - case GNOME: - case HALFLING: - case WOOD_ELF: - if (r2 == HUMAN || - r2 == BARBARIAN || - r2 == ERUDITE || - r2 == HALF_ELF || - r2 == GNOME || - r2 == HALFLING || - r2 == DWARF || - r2 == HIGH_ELF || - r2 == WOOD_ELF) { + case Race::Human: + case Race::Barbarian: + case Race::HalfElf: + case Race::Gnome: + case Race::Halfling: + case Race::WoodElf: + if (r2 == Race::Human || + r2 == Race::Barbarian || + r2 == Race::Erudite || + r2 == Race::HalfElf || + r2 == Race::Gnome || + r2 == Race::Halfling || + r2 == Race::Dwarf || + r2 == Race::HighElf || + r2 == Race::WoodElf) { return true; } break; - case ERUDITE: - if (r2 == HUMAN || r2 == HALF_ELF) { + case Race::Erudite: + if (r2 == Race::Human || r2 == Race::HalfElf) { return true; } break; - case DWARF: - if (r2 == HALFLING || r2 == GNOME) { + case Race::Dwarf: + if (r2 == Race::Halfling || r2 == Race::Gnome) { return true; } break; - case HIGH_ELF: - if (r2 == WOOD_ELF) { + case Race::HighElf: + if (r2 == Race::WoodElf) { return true; } break; - case VAHSHIR: + case Race::VahShir: return true; - case IKSAR: + case Race::Iksar: return false; } return false; diff --git a/common/races.cpp b/common/races.cpp index 033d188bf3..a01597640e 100644 --- a/common/races.cpp +++ b/common/races.cpp @@ -22,1467 +22,1376 @@ const char* GetRaceIDName(uint16 race_id) { switch (race_id) { - // Old Race Labels - //case HUMAN: - // return "Human"; - //case BARBARIAN: - // return "Barbarian"; - //case ERUDITE: - // return "Erudite"; - //case WOOD_ELF: - // return "Wood Elf"; - //case HIGH_ELF: - // return "High Elf"; - //case DARK_ELF: - // return "Dark Elf"; - //case HALF_ELF: - // return "Half Elf"; - //case DWARF: - // return "Dwarf"; - //case TROLL: - // return "Troll"; - //case OGRE: - // return "Ogre"; - //case HALFLING: - // return "Halfling"; - //case GNOME: - // return "Gnome"; - //case IKSAR: - // return "Iksar"; - //case WEREWOLF: - // return "Werewolf"; - //case SKELETON: - // return "Skeleton"; - //case ELEMENTAL: - // return "Elemental"; - //case EYE_OF_ZOMM: - // return "Eye of Zomm"; - //case WOLF_ELEMENTAL: - // return "Wolf Elemental"; - //case IKSAR_SKELETON: - // return "Iksar Skeleton"; - //case VAHSHIR: - // return "Vah Shir"; - //case FROGLOK: - //case FROGLOK2: // "Piranha"? (low-byte issue..) - // return "Froglok"; - //case DRAKKIN: - // return "Drakkin"; - - // RoF2 Race Labels - case Race::Abhorrent: - return "Abhorrent"; - case Race::AirElemental: - case Race::AirElemental2: - return "Air Elemental"; - case Race::AirMephit: - return "Air Mephit"; - case Race::Akhevan: - case Race::Akheva: - return "Akheva"; - case Race::Alaran: - return "Alaran"; - case Race::AlaranGhost: - return "Alaran Ghost"; - case Race::AlaranSentryStone: - return "Alaran Sentry Stone"; - case Race::Alligator: - case Race::Alligator2: - return "Alligator"; - case Race::Denizen: - case Race::Amygdalan: - return "Amygdalan"; - case Race::Aneuk: - return "Aneuk"; - case Race::AnimatedArmor: - return "Animated Armor"; - case Race::AnimatedHand: - return "Animated Hand"; - case Race::AnimatedStatue: - case Race::AnimatedStatue2: - return "Animated Statue"; - case Race::Apexus: - return "Apexus"; - case Race::Arachnid: - return "Arachnid"; - case Race::ArcanistOfHate: - return "Arcanist of Hate"; - case Race::Armadillo: - return "Armadillo"; - case Race::ArmorRack: - return "Armor Rack"; - case Race::Aviak: - case Race::Aviak2: - return "Aviak"; - case Race::AviakPullAlong: - return "Aviak Pull Along"; - case Race::AyonaeRo: - return "Ayonae Ro"; - case Race::Banner: - case Race::Banner2: - case Race::Banner3: - case Race::Banner4: - case Race::Banner5: - case Race::Banner6: - case Race::Banner7: - return "Banner"; - case Race::TenthAnniversaryBanner: - return "10th Anniversary Banner"; - case Race::Banshee: - case Race::Banshee2: - case Race::Banshee3: - return "Banshee"; - case Race::Barbarian: - case Race::HalasCitizen: - return "Barbarian"; - case Race::Barrel: - return "Barrel"; - case Race::UndeadBoat: - return "Barrel Barge Ship"; - case Race::Basilisk: - return "Basilisk"; - case Race::GiantBat: - case Race::Bat: - case Race::Bat2: - return "Bat"; - case Race::Bazu: - return "Bazu"; - case Race::Bear: - case Race::Bear2: - case Race::Bear3: - return "Bear"; - case Race::BearMount: - return "Bear Mount"; - case Race::BearTrap: - return "Bear Trap"; - case Race::Beetle: - case Race::Beetle2: - case Race::Beetle3: - return "Beetle"; - case Race::HumanBeggar: - return "Beggar"; - case Race::Bellikos: - return "Bellikos"; - case Race::Bertoxxulous: - case Race::BertoxxulousNew: - return "Bertoxxulous"; - case Race::Bixie: - case Race::Bixie2: - return "Bixie"; - case Race::BlimpShip: - return "Blimp Ship"; - case Race::BlindDreamer: - return "Blind Dreamer"; - case Race::BloodRaven: - return "Blood Raven"; - case Race::Boat: - case Race::Boat2: - return "Boat"; - case Race::Bolvirk: - return "Bolvirk"; - case Race::BoneGolem: - case Race::BoneGolem2: - return "Bone Golem"; - case Race::Bones: - return "Bones"; - case Race::BookDervish: - return "Book Dervish"; - case Race::Portal: - return "BoT Portal"; - case Race::Boulder: - return "Boulder"; - case Race::Box: - return "Box"; - case Race::Braxi: - return "Braxi"; - case Race::BraxiMount: - return "Braxi Mount"; - case Race::Brell: - return "Brell"; - case Race::BrellsFirstCreation: - return "Brell's First Creation"; - case Race::Bristlebane: - return "Bristlebane"; - case Race::BrokenClockwork: - return "Broken Clockwork"; - case Race::Brontotherium: - return "Brontotherium"; - case Race::Brownie: - case Race::Brownie2: - return "Brownie"; - case Race::Bubonian: - return "Bubonian"; - case Race::BubonianUnderling: - return "Bubonian Underling"; - case Race::Burynai: - case Race::Burynai2: - return "Burynai"; - case Race::TenthAnniversaryCake: - return "10th Anniversary Cake"; - case Race::Campfire: - return "Campfire"; - case Race::CarrierHand: - return "Carrier Hand"; - case Race::Cat: - return "Cat"; - case Race::CazicThule: - case Race::CazicThule2: - return "Cazic Thule"; - case Race::Centaur: - case Race::Centaur2: - return "Centaur"; - case Race::Chest: - case Race::Chest2: - case Race::Chest3: - return "Chest"; - case Race::Chimera: - case Race::Chimera2: - return "Chimera"; - case Race::Chokidai: - return "Chokidai"; - case Race::Clam: - return "Clam"; - case Race::CliknarMount: - return "Cliknar Mount"; - case Race::CliknarQueen: - return "Cliknar Queen"; - case Race::CliknarSoldier: - return "Cliknar Soldier"; - case Race::CliknarWorker: - return "Cliknar Worker"; - case Race::ClockworkBeetle: - return "Clockwork Beetle"; - case Race::ClockworkBoar: - return "Clockwork Boar"; - case Race::ClockworkBomb: - return "Clockwork Bomb"; - case Race::ClockworkBrain: - return "Clockwork Brain"; - case Race::ClockworkGnome: - return "Clockwork Gnome"; - case Race::ClockworkGolem: - return "Clockwork Golem"; - case Race::ClockworkGuardian: - return "Clockwork Guardian"; - case Race::Cockatrice: - return "Cockatrice"; - case Race::Coffin: - case Race::Coffin2: - return "Coffin"; - case Race::CoinPurse: - return "Coin Purse"; - case Race::Coldain: - case Race::Coldain2: - case Race::Coldain3: - return "Coldain"; - case Race::Coral: - return "Coral"; - case Race::Corathus: - return "Corathus"; - case Race::Crab: - return "Crab"; - case Race::Cragbeast: - return "Cragbeast"; - case Race::Cragslither: - return "Cragslither"; - case Race::Crocodile: - return "Crocodile"; - case Race::Crystal: - return "Crystal"; - case Race::CrystalShard: - return "Crystal Shard"; - case Race::CrystalSphere: - return "Crystal Sphere"; - case Race::CrystalSpider: - return "Crystal Spider"; - case Race::CrystalskinAmbuloid: - return "Crystalskin Ambuloid"; - case Race::CrystalskinSessiloid: - return "Crystalskin Sessiloid"; - case Race::DaisyMan: - return "Daisy Man"; - case Race::DarkElf: - case Race::NeriakCitizen: - return "Dark Elf"; - case Race::DarkLord: - return "Dark Lord"; - case Race::DemiLich: - return "Demi Lich"; - case Race::DemonVulture: - return "Demon Vulture"; - case Race::Dervish: - case Race::Dervish2: - case Race::Dervish3: - case Race::Dervish4: - return "Dervish"; - case Race::Dervish5: - return "Dervish(Ver. 5)"; - case Race::Dervish6: - return "Dervish(Ver. 6)"; - case Race::Devourer: - return "Devourer"; - case Race::DireWolf: - return "Dire Wolf"; - case Race::DiscordShip: - return "Discord Ship"; - case Race::Discordling: - return "Discordling"; - case Race::DiseasedFiend: - return "Diseased Fiend"; - case Race::Djinn: - return "Djinn"; - case Race::Drachnid: - case Race::Drachnid2: - return "Drachnid"; - case Race::DrachnidCocoon: - return "Drachnid Cocoon"; - case Race::Dracolich: - return "Dracolich"; - case Race::Draglock: - return "Draglock"; - case Race::LavaDragon: - case Race::DragonSkeleton: - case Race::WaterDragon: - case Race::VeliousDragon: - case Race::ClockworkDragon: - case Race::BlackAndWhiteDragon: - case Race::GhostDragon: - case Race::PrismaticDragon: - case Race::Quarm: - case Race::Dragon: - case Race::Dragon2: - case Race::Dragon3: - case Race::Dragon4: - case Race::Dragon5: - case Race::Dragon6: - case Race::Dragon7: - return "Dragon"; - case Race::DragonBones: - return "Dragon Bones"; - case Race::DragonEgg: - return "Dragon Egg"; - case Race::DragonStatue: - return "Dragon Statue"; - case Race::Dragorn: - return "Dragorn"; - case Race::DragornBox: - return "Dragorn Box"; - case Race::Drake: - case Race::Drake2: - case Race::Drake3: - return "Drake"; - case Race::Drakkin: - return "Drakkin"; - case Race::Drixie: - return "Drixie"; - case Race::Drogmor: - return "Drogmore"; - case Race::Drolvarg: - return "Drolvarg"; - case Race::Dryad: - return "Dryad"; - case Race::Dwarf: - case Race::KaladimCitizen: - return "Dwarf"; - case Race::DynamiteKeg: - return "Dynamite Keg"; - case Race::Dynleth: - return "Dyn'Leth"; - case Race::EarthElemental: - case Race::EarthElemental2: - return "Earth Elemental"; - case Race::EarthMephit: - return "Earth Mephit"; - case Race::GiantEel: - return "Eel"; - case Race::Efreeti: - case Race::Efreeti2: - return "Efreeti"; - case Race::Elddar: - return "Elddar"; - case Race::Elemental: - return "Elemental"; - case Race::ElkHead: - return "Elk Head"; - case Race::ElvenBoat: - return "Elven Boat"; - case Race::ElvenGhost: - return "Elven Ghost"; - case Race::EnchantedArmor: - return "Enchanted Armor"; - case Race::Erollisi: - return "Erollisi"; - case Race::Erudite: - case Race::EruditeCitizen: - case Race::Erudite2: - return "Erudite"; - case Race::EvanTest: - return "Evan Test"; - case Race::EvilEye: - case Race::EvilEye2: - case Race::EvilEye3: - return "Evil Eye"; - case Race::Exoskeleton: - return "Exoskeleton"; - case Race::ExplosiveCart: - return "Explosive Cart"; - case Race::EyeOfZomm: - return "Eye"; - case Race::Fairy: - case Race::Fairy2: - return "Fairy"; - case Race::FallenKnight: - return "Fallen Knight"; - case Race::Faun: - return "Faun"; - case Race::FayDrake: - return "Fay Drake"; - case Race::FenninRo: - return "Fennin Ro"; - case Race::Feran: - return "Feran"; - case Race::FeranMount: - return "Feran Mount"; - case Race::Fiend: - return "Fiend"; - case Race::FireElemental: - case Race::FireElemental2: - return "Fire Elemental"; - case Race::FireMephit: - return "Fire Mephit"; - case Race::Fish: - case Race::KunarkFish: - return "Fish"; - case Race::Flag: - return "Flag"; - case Race::FloatingIsland: - return "Floating Island"; - case Race::FloatingSkull: - return "Floating Skull"; - case Race::FloatingTower: - return "Floating Tower"; - case Race::Fly: - return "Fly"; - case Race::FlyingCarpet: - return "Flying Carpet"; - case Race::ForestGiant2: - return "Forest Giant"; - case Race::Frog: - case Race::Frog2: - return "Frog"; - case Race::Froglok: - case Race::FroglokGhoul: - case Race::Froglok2: - return "Froglok"; - case Race::FroglokGhost: - return "Froglok Ghost"; - case Race::FroglokSkeleton: - return "Froglok Skeleton"; - case Race::FungalFiend: - return "Fungal Fiend"; - case Race::FungusPatch: - return "Fungus Patch"; - case Race::Fungusman: - return "Fungusman"; - case Race::Galorian: - return "Galorian"; - case Race::Gargoyle: - case Race::Gargoyle2: - return "Gargoyle"; - case Race::Gasbag: - return "Gasbag"; - case Race::GelatinousCube: - case Race::GelatinousCube2: - return "Gelatinous Cube"; - case Race::Gelidran: - return "Gelidran"; - case Race::Genari: - return "Genari"; - case Race::Geonid: - return "Geonid"; - case Race::Ghost: - case Race::DwarfGhost: - case Race::EruditeGhost: - case Race::PirateGhost: - return "Ghost"; - case Race::GhostShip: - case Race::GhostShip2: - return "Ghost Ship"; - case Race::Ghoul: - case Race::Ghoul2: - return "Ghoul"; - case Race::Giant: - case Race::ForestGiant: - case Race::FrostGiant: - case Race::StormGiant: - case Race::EarthGolem: - case Race::IronGolem: - case Race::StormGolem: - case Race::AirGolem: - case Race::WoodGolem: - case Race::FireGolem: - case Race::WaterGolem: - case Race::Giant2: - case Race::Giant3: - return "Giant"; - case Race::GiantClockwork: - return "Giant Clockwork"; - case Race::Giant4: - return "Giant(Rallosian mats)"; - case Race::GiantShade: - return "Giant Shade"; - case Race::Gigyn: - return "Gigyn"; - case Race::GingerbreadMan: - return "Gingerbread Man"; - case Race::Girplan: - return "Girplan"; - case Race::Gnoll: - case Race::Gnoll2: - case Race::Gnoll3: - return "Gnoll"; - case Race::Gnome: - return "Gnome"; - case Race::Gnomework: - return "Gnomework"; - case Race::GnomishBalloon: - return "Gnomish Balloon"; - case Race::GnomishBoat: - return "Gnomish Boat"; - case Race::GnomishHoveringTransport: - return "Gnomish Hovering Transport"; - case Race::GnomishRocketPack: - return "Gnomish Rocket Pack"; - case Race::Goblin: - case Race::Bloodgill: - case Race::KunarkGoblin: - case Race::NewGoblin: - case Race::Goblin2: - return "Goblin"; - case Race::Luclin2: - return "God - Luclin(Ver. 2)"; - case Race::Luclin3: - return "God - Luclin(Ver. 3)"; - case Race::Luclin4: - return "God - Luclin(Ver. 4)"; - case Race::GodOfDiscord: - return "God of Discord"; - case Race::Golem: - case Race::Golem2: - return "Golem"; - case Race::Goo: - case Race::Goo2: - case Race::Goo3: - case Race::Goo4: - return "Goo"; - case Race::Goral: - return "Goral"; - case Race::GoralMount: - return "Goral Mount"; - case Race::Gorgon: - return "Gorgon"; - case Race::Gorilla: - case Race::Gorilla2: - return "Gorilla"; - case Race::GrandfatherClock: - return "Grandfather Clock"; - case Race::GrekenYoung: - return "Greken - Young"; - case Race::GrekenYoungAdult: - return "Greken - Young Adult"; - case Race::Grendlaen: - return "Grendlaen"; - case Race::GriegVeneficus: - return "Grieg Veneficus"; - case Race::Griffin: - case Race::Griffin2: - return "Griffin"; - case Race::Grimling: - return "Grimling"; - case Race::GroundShaker: - return "Ground Shaker"; - case Race::FreeportGuard: - case Race::Felguard: - case Race::Fayguard: - case Race::VahShirGuard: - return "Guard"; - case Race::GuardOfJustice: - return "Guard of Justice"; - case Race::GuardianCpu: - return "Guardian CPU"; - case Race::Hadal: - return "Hadal"; - case Race::Hag: - return "Hag"; - case Race::HalfElf: - return "Half Elf"; - case Race::Halfling: - case Race::RivervaleCitizen: - return "Halfling"; - case Race::Harpy: - case Race::Harpy2: - return "Harpy"; - case Race::HighElf: - return "High Elf"; - case Race::Hippogriff: - return "Hippogriff"; - case Race::Holgresh: - case Race::Holgresh2: - return "Holgresh"; - case Race::HoneyPot: - return "Honey Pot"; - case Race::Horse: - case Race::Horse2: - case Race::Horse3: - return "Horse"; - case Race::HoveringPlatform: - return "Hovering Platform"; - case Race::Hraquis: - return "Hraquis"; - case Race::Human: - case Race::HighpassCitizen: - case Race::QeynosCitizen: - case Race::Human2: - return "Human"; - case Race::HumanGhost: - return "Human Ghost"; - case Race::Huvul: - return "Huvul"; - case Race::HydraCrystal: - return "Hydra Crystal"; - case Race::HydraMount: - return "Hydra Mount"; - case Race::Hydra: - return "Hydra NPC"; - case Race::Hynid: - return "Hynid"; - case Race::IceSpectre: - return "Ice Spectre"; - case Race::Ikaav: - return "Ikaav"; - case Race::Iksar: - case Race::IksarCitizen: - return "Iksar"; - case Race::IksarGhost: - return "Iksar Ghost"; - case Race::IksarGolem: - return "Iksar Golem"; - case Race::IksarSkeleton: - return "Iksar Skeleton"; - case Race::IksarSpirit: - return "Iksar Spirit"; - case Race::Imp: - return "Imp"; - case Race::Innoruuk: - return "Innoruuk"; - case Race::Insect: - return "Insect"; - case Race::InteractiveObject: - return "Interactive Object"; - case Race::InvisibleMan: - case Race::InvisibleMan2: - case Race::InvisibleMan3: - return "Invisible Man"; - case Race::InvisibleManOfZomm: - return "Invisible Man of Zomm"; - case Race::Ixt: - return "Ixt"; - case Race::Jokester: - return "Jokester"; - case Race::JumJumBucket: - return "Jum Jum Bucket"; - case Race::JunkBeast: - return "Junk Beast"; - case Race::Kangon: - return "Kangon"; - case Race::KangonMount: - return "Kangon Mount"; - case Race::Karana: - return "Karana"; - case Race::PhinigelAutropos: - case Race::Kedge: - return "Kedge"; - case Race::Kerran: - case Race::Kerran2: - return "Kerran"; - case Race::Kirin: - case Race::Kirin2: - return "Kirin"; - case Race::KnightOfHate: - return "Knight of Hate"; - case Race::KnightOfPestilence: - return "Knight of Pestilence"; - case Race::Kobold: - case Race::Kobold2: - return "Kobold"; - case Race::Kraken: - return "Kraken"; - case Race::Kyv: - return "Kyv"; - case Race::Launch: - return "Launch"; - case Race::LavaRock: - return "Lava Rock"; - case Race::LavaSpider: - return "Lava Spider"; - case Race::LavaSpiderQueen: - return "Lava Spider Queen"; - case Race::Leech: - return "Leech"; - case Race::Lepertoloth: - return "Lepertoloth"; - case Race::Lightcrawler: - return "Lightcrawler"; - case Race::LightingWarrior: - return "Lightning Warrior"; - case Race::Lion: - return "Lion"; - case Race::LizardMan: - return "Lizard Man"; - case Race::Luclin: - return "Luclin"; - case Race::Luggald: - case Race::Luggald2: - return "Luggald"; - case Race::Luggald3: - return "Luggalds"; - case Race::Malarian: - return "Malarian"; - case Race::Mammoth: - case Race::Mammoth2: - return "Mammoth"; - case Race::ManEatingPlant: - return "Man - Eating Plant"; - case Race::Mansion: - return "Mansion"; - case Race::Manticore: - return "Manticore"; - case Race::Unknown5: - return "Mantrap"; - case Race::Marionette: - return "Marionette"; - case Race::Mastruq: - return "Mastruq"; - case Race::MataMuram: - return "Mata Muram"; - case Race::Toolbox: - return "Medium Plant"; - case Race::Mephit: - return "Mephit"; - case Race::MerchantShip: - return "Merchant Ship"; - case Race::Mermaid: - return "Mermaid"; - case Race::Mimic: - return "Mimic"; - case Race::MiniPom: - return "Mini POM"; - case Race::Minotaur: - case Race::Minotaur2: - case Race::Minotaur3: - case Race::Minotaur4: - return "Minotaur"; - case Race::MithanielMarr: - return "Mithaniel Marr"; - case Race::MorellThule: - return "Morell Thule"; - case Race::Mosquito: - return "Mosquito"; - case Race::MouthOfInsanity: - return "Mouth of Insanity"; - case Race::Muddite: - return "Muddite"; - case Race::Mummy: - return "Mummy"; - case Race::MuramiteArmorPile: - return "Muramite Armor Pile"; - case Race::Murkglider: - return "Murkglider"; - case Race::MurkgliderEggSack: - return "Murkglider Egg Sac"; - case Race::Mutna: - return "Mutna"; - case Race::Nekhon: - return "Nekhon"; - case Race::Netherbian: - return "Netherbian"; - case Race::Nightmare: - return "Nightmare"; - case Race::NightmareGargoyle: - return "Nightmare Gargoyle"; - case Race::NightmareGoblin: - return "Nightmare Goblin"; - case Race::NightmareMephit: - return "Nightmare Mephit"; - case Race::Unicorn2: - case Race::Unicorn3: - return "Nightmare / Unicorn"; - case Race::NightmareWraith: - return "Nightmare Wraith"; - case Race::Nihil: - return "Nihil"; - case Race::Nilborien: - return "Nilborien"; - case Race::Noc: - return "Noc"; - case Race::Nymph: - return "Nymph"; - case Race::Ogre: - case Race::OggokCitizen: - return "Ogre"; - case Race::Ogre2: - return "Ogre NPC - Male"; - case Race::Orb: - return "Orb"; - case Race::Orc: - case Race::Orc2: - return "Orc"; - case Race::Othmir: - return "Othmir"; - case Race::Owlbear: - return "Owlbear"; - case Race::ParasiticScavenger: - return "Parasitic Scavenger"; - case Race::Pegasus: - case Race::Pegasus2: - case Race::Pegasus3: - return "Pegasus"; - case Race::Phoenix: - return "Phoenix"; - case Race::Piranha: - return "Piranha"; - case Race::OneArmedPirate: - case Race::SpiritmasterNadox: - case Race::BrokenSkullTaskmaster: - case Race::GnomePirate: - case Race::DarkElfPirate: - case Race::OgrePirate: - case Race::HumanPirate: - case Race::EruditePirate: - return "Pirate"; - case Race::PirateShip: - return "Pirate Ship"; - case Race::Pixie: - return "Pixie"; - case Race::PoisonFrog: - return "Poison Frog"; - case Race::Portal2: - return "Portal"; - case Race::PowderKeg: - return "Powder Keg"; - case Race::PressurePlate: - return "Pressure Plate"; - case Race::PufferSpore: - return "Puffer Spore"; - case Race::Puma: - case Race::Puma2: - case Race::Puma3: - return "Puma"; - case Race::Pusling: - return "Pusling"; - case Race::Pyrilen: - return "Pyrilen"; - case Race::Ratuk: - return "Ra`tuk"; - case Race::Rabbit: - return "Rabbit"; - case Race::StatueOfRallosZek: - case Race::NewRallosZek: - return "Rallos Zek"; - case Race::RallosOgre: - return "Rallos Zek Minion"; - case Race::Raptor: - case Race::Raptor2: - return "Raptor"; - case Race::RaptorMount: - return "Raptor Mount"; - case Race::GiantRat: - case Race::Rat: - return "Rat"; - case Race::RatMount: - return "Rat Mount"; - case Race::Ratman: - case Race::Ratman2: - return "Ratman"; - case Race::ReanimatedHand: - return "Reanimated Hand"; - case Race::Recuso: - return "Recuso"; - case Race::RegenerationPool: - return "Regeneration Pool"; - case Race::RelicCase: - return "Relic case "; - case Race::RhinoBeetle: - return "Rhino Beetle"; - case Race::Rhinoceros: - return "Rhinoceros"; - case Race::RobocopterOfZomm: - return "Robocopter of Zomm"; - case Race::RockPile: - return "Rock Pile"; - case Race::Rockhopper: - return "Rockhopper"; - case Race::RonnieTest: - return "Ronnie Test"; - case Race::RootTentacle: - return "Root Tentacle"; - case Race::RotDogMount: - return "Rot Dog Mount"; - case Race::RotDog: - return "Rotdog"; - case Race::Rotocopter: - return "Rotocopter"; - case Race::Rowboat: - return "Rowboat"; - case Race::RoyalGuard: - return "Royal Guard"; - case Race::RujarkianOrc: - case Race::MasterOrc: - return "Rujarkian Orc"; - case Race::RunedOrb: - return "Runed Orb"; - case Race::RunicSymbol: - return "Runic Symbol"; - case Race::Sabertooth: - return "Saber - toothed Cat"; - case Race::SaltpetterBomb: - return "Saltpetter Bomb"; - case Race::SandElf: - return "Sand Elf"; - case Race::Sandman: - return "Sandman"; - case Race::Sarnak: - case Race::Sarnak2: - return "Sarnak"; - case Race::SarnakGolem: - return "Sarnak Golem"; - case Race::SarnakSpirit: - return "Sarnak Spirit"; - case Race::Saryrn: - return "Saryrn"; - case Race::Satyr: - return "Satyr"; - case Race::ScaledWolf: - return "Scaled Wolf"; - case Race::Scarecrow: - case Race::Scarecrow2: - return "Scarecrow"; - case Race::ScarletCheetah: - return "Scarlet Cheetah"; - case Race::ScleraMount: - return "Sclera Mount"; - case Race::Scorpion: - case Race::IksarScorpion: - case Race::Scorpion2: - return "Scorpion"; - case Race::Scrykin: - return "Scrykin"; - case Race::SeaTurtle: - return "Sea Turtle"; - case Race::SeaHorse: - return "Seahorse"; - case Race::Selyrah: - return "Selyrah"; - case Race::SelyrahMount: - return "Selyrah Mount"; - case Race::LordInquisitorSeru: - return "Seru"; - case Race::ServantOfShadow: - return "Servant of Shadow"; - case Race::SessiloidMount: - return "Sessiloid Mount"; - case Race::Shade: - case Race::Shade2: - case Race::Shade3: - return "Shade"; - case Race::KhatiSha: - return "Shadel"; - case Race::ShamblingMound: - return "Shambling Mound"; - case Race::Shark: - return "Shark"; - case Race::Shiknar: - return "Shik'Nar"; - case Race::Shiliskin: - return "Shiliskin"; - case Race::Ship: - return "Ship"; - case Race::ShipInABottle: - return "Ship in a Bottle"; - case Race::Shissar: - case Race::Shissar2: - return "Shissar"; - case Race::Shrieker: - return "Shrieker"; - case Race::Siren: - case Race::Siren2: - return "Siren"; - case Race::SkeletalHorse: - return "Skeletal Horse"; - case Race::Skeleton: - case Race::Skeleton2: - case Race::Skeleton3: - return "Skeleton"; - case Race::Skunk: - return "Skunk"; - case Race::Skystrider: - return "Skystrider"; - case Race::Plant2: - return "Small Plant"; - case Race::GiantSnake: - case Race::Snake: - return "Snake"; - case Race::SnakeElemental: - return "Snake Elemental"; - case Race::SnowDervish: - return "Snow Dervish"; - case Race::SnowRabbit: - return "Snow Rabbit"; - case Race::Sokokar: - return "Sokokar"; - case Race::SokokarMount: - return "Sokokar Mount"; - case Race::SokokarMount2: - return "Sokokar(w saddle)"; - case Race::SolusekRo: - case Race::SolusekRo2: - return "Solusek Ro"; - case Race::SolusekRoGuard: - return "Solusek Ro Guard"; - case Race::SonicWolf: - return "Sonic Wolf"; - case Race::SoulDevourer: - return "Soul Devourer"; - case Race::Spectre: - case Race::Spectre2: - return "Spectre"; - case Race::SpellParticle: - return "Spell Particle 1"; - case Race::Sphinx: - case Race::Sphinx2: - return "Sphinx"; - case Race::GiantSpider: - case Race::Spider: - return "Spider"; - case Race::SpiderEggSack: - return "Spider Egg Sack"; - case Race::SpiderMount: - return "Spider Mount"; - case Race::SpiderQueen: - return "Spider Queen"; - case Race::SpikeTrap: - return "Spike Trap"; - case Race::SpiritWolf: - return "Spirit Wolf"; - case Race::Sporali: - return "Sporali"; - case Race::StoneJug: - return "Stone Jug"; - case Race::StonePylon: - return "Stone Pylon"; - case Race::StoneRing: - return "Stone Ring"; - case Race::StoneWorker: - case Race::StoneWorker2: - return "Stone Worker"; - case Race::Stonegrabber: - return "Stonegrabber"; - case Race::Stonemite: - return "Stonemite"; - case Race::Stormrider: - return "Stormrider"; - case Race::Succubus: - return "Succubus"; - case Race::Succulent: - return "Succulent"; - case Race::SullonZek: - return "Sullon Zek"; - case Race::Shadel: - return "Sun Revenant"; - case Race::Sunflower: - return "Sunflower"; - case Race::Swinetor: - return "Swinetor"; - case Race::Swordfish: - return "Swordfish"; - case Race::Synarcana: - return "Synarcana"; - case Race::Table: - return "Table"; - case Race::FroglokTadpole: - return "Tadpole"; - case Race::Taelosian: - return "Taelosian"; - case Race::WineCask: - return "Tall Plant"; - case Race::TallonZek: - return "Tallon Zek"; - case Race::Taneth: - return "Taneth"; - case Race::TarewMarr: - return "Tarew Marr"; - case Race::Tegi: - return "Tegi"; - case Race::TeleportMan: - return "Teleport Man"; - case Race::TeleportationStand: - return "Teleportation Stand"; - case Race::Telmira: - return "Telmira"; - case Race::TentacleTerror: - case Race::TentacleTerror2: - return "Tentacle Terror"; - case Race::TerrisThule: - return "Terris Thule"; - case Race::TestObject: - return "Test Object"; - case Race::Rathe: - return "The Rathe"; - case Race::TribunalNew: - return "The Tribunal"; - case Race::ThoughtHorror: - return "Thought Horror"; - case Race::Tiger: - return "Tiger"; - case Race::TinSoldier: - return "Tin Soldier"; - case Race::Plant: - return "Toolbox"; - case Race::TopiaryLion: - return "Topiary Lion"; - case Race::TopiaryLionMount: - return "Topiary Lion Mount"; - case Race::Tormentor: - return "Tormentor"; - case Race::Totem: - case Race::Totem2: - return "Totem"; - case Race::Trakanon: - return "Trakanon"; - case Race::Tranquilion: - return "Tranquilion"; - case Race::Treant: - case Race::Treant2: - case Race::Treant3: - return "Treant"; - case Race::Tribunal: - return "Tribunal"; - case Race::Triumvirate: - return "Triumvirate"; - case Race::Troll: - case Race::GrobbCitizen: - case Race::TrollCrewMember: - case Race::PirateDeckhand: - case Race::BrokenSkullPirate: - return "Troll"; - case Race::TrollZombie: - return "Troll Zombie"; - case Race::Trusik: - return "Trusik"; - case Race::Tsetsian: - return "Tsetsian"; - case Race::Tumbleweed: - return "Tumbleweed"; - case Race::Tunare: - return "Tunare"; - case Race::Turepta: - return "Turepta"; - case Race::Ukun: - return "Ukun"; - case Race::Ulthork: - return "Ulthork"; - case Race::UndeadChokidai: - return "Undead Chokidai"; - case Race::UndeadFootman: - return "Undead Footman"; - case Race::UndeadFroglok: - return "Undead Froglok"; - case Race::UndeadIksar: - return "Undead Iksar"; - case Race::UndeadKnight: - return "Undead Knight"; - case Race::UndeadSarnak: - return "Undead Sarnak"; - case Race::UndeadVeksar: - return "Undead Veksar"; - case Race::Underbulk: - return "Underbulk"; - case Race::Unicorn: - return "Unicorn"; - case Race::Doug: - case Race::MinorIllusion: - case Race::Tree: - case Race::Unknown: - case Race::Unknown2: - case Race::Unknown3: - case Race::Unknown4: - return "UNKNOWN RACE"; - case Race::VahShir: - case Race::VahShirKing: - return "Vah Shir"; - case Race::VahShirSkeleton: - return "Vah Shir Skeleton"; - case Race::VallonZek: - return "Vallon Zek"; - case Race::Valorian: - case Race::Valorian2: - return "Valorian"; - case Race::Vampire: - case Race::ElfVampire: - case Race::Vampire2: - case Race::VampireVolatalis: - case Race::UndeadVampire: - case Race::Vampire3: - case Race::MasterVampire: - case Race::Vampire4: - return "Vampire"; - case Race::Vase: - return "Vase"; - case Race::Vegerog: - return "Vegerog"; - case Race::Veksar: - case Race::Veksar2: - case Race::Veksar3: - return "Veksar"; - case Race::VenrilSathir: - return "Venril Sathir"; - case Race::VineMaw: - return "Vine Maw"; - case Race::Wagon: - return "Wagon"; - case Race::Walrus: - return "Walrus"; - case Race::WarBoar: - case Race::WarBoar2: - return "War Boar"; - case Race::WarWraith: - return "War Wraith"; - case Race::Wasp: - return "Wasp"; - case Race::WaterElemental: - case Race::WaterElemental2: - return "Water Elemental"; - case Race::WaterMephit: - return "Water Mephit"; - case Race::WaterSpout: - return "Water Spout"; - case Race::WeaponRack: - case Race::WeaponRack2: - return "Weapon Rack"; - case Race::Web: - return "Web"; - case Race::WeddingAltar: - return "Wedding Altar"; - case Race::WeddingArbor: - return "Wedding Arbor"; - case Race::WeddingFlowers: - return "Wedding Flowers"; - case Race::Wereorc: - return "Wereorc"; - case Race::Werewolf: - case Race::Werewolf2: - case Race::Werewolf3: - return "Werewolf"; - case Race::WetfangMinnow: - return "Wetfang Minnow"; - case Race::Whirligig: - return "Whirligig"; - case Race::WickerBasket: - return "Wicker Basket"; - case Race::Wisp: - return "Will - O - Wisp"; - case Race::StoneJug2: - case Race::WineCask2: - return "Wine Cask"; - case Race::Witheran: - case Race::Witheran2: - return "Witheran"; - case Race::Wolf: - case Race::WolfElemental: - case Race::Wolf2: - return "Wolf"; - case Race::WoodElf: - return "Wood Elf"; - case Race::Worg: - case Race::Worg2: - return "Worg"; - case Race::Worm: - return "Worm"; - case Race::Wretch: - return "Wretch"; - case Race::Wrulon: - case Race::Wrulon2: - return "Wrulon"; - case Race::Wurm: - case Race::Wurm2: - return "Wurm"; - case Race::WurmMount: - return "Wurm Mount"; - case Race::Wyvern: - case Race::Wyvern2: - return "Wyvern"; - case Race::Xalgoz: - return "Xalgoz"; - case Race::Xaric: - return "Xaric the Unspoken"; - case Race::Xegony: - return "Xegony"; - case Race::Yakkar: - return "Yakkar"; - case Race::Yeti: - return "Yeti"; - case Race::Zebuxoruk: - return "Zebuxoruk"; - case Race::ZebuxoruksCage: - return "Zebuxoruk's Cage"; - case Race::Zelniak: - return "Zelniak"; - case Race::Zombie: - case Race::Zombie2: - return "Zombie"; - default: - return "UNKNOWN RACE"; + case Race::Abhorrent: + return "Abhorrent"; + case Race::AirElemental: + case Race::AirElemental2: + return "Air Elemental"; + case Race::AirMephit: + return "Air Mephit"; + case Race::Akhevan: + case Race::Akheva: + return "Akheva"; + case Race::Alaran: + return "Alaran"; + case Race::AlaranGhost: + return "Alaran Ghost"; + case Race::AlaranSentryStone: + return "Alaran Sentry Stone"; + case Race::Alligator: + case Race::Alligator2: + return "Alligator"; + case Race::Denizen: + case Race::Amygdalan: + return "Amygdalan"; + case Race::Aneuk: + return "Aneuk"; + case Race::AnimatedArmor: + return "Animated Armor"; + case Race::AnimatedHand: + return "Animated Hand"; + case Race::AnimatedStatue: + case Race::AnimatedStatue2: + return "Animated Statue"; + case Race::Apexus: + return "Apexus"; + case Race::Arachnid: + return "Arachnid"; + case Race::ArcanistOfHate: + return "Arcanist of Hate"; + case Race::Armadillo: + return "Armadillo"; + case Race::ArmorRack: + return "Armor Rack"; + case Race::Aviak: + case Race::Aviak2: + return "Aviak"; + case Race::AviakPullAlong: + return "Aviak Pull Along"; + case Race::AyonaeRo: + return "Ayonae Ro"; + case Race::Banner: + case Race::Banner2: + case Race::Banner3: + case Race::Banner4: + case Race::Banner5: + case Race::Banner6: + case Race::Banner7: + return "Banner"; + case Race::TenthAnniversaryBanner: + return "10th Anniversary Banner"; + case Race::Banshee: + case Race::Banshee2: + case Race::Banshee3: + return "Banshee"; + case Race::Barbarian: + case Race::HalasCitizen: + return "Barbarian"; + case Race::Barrel: + return "Barrel"; + case Race::UndeadBoat: + return "Barrel Barge Ship"; + case Race::Basilisk: + return "Basilisk"; + case Race::GiantBat: + case Race::Bat: + case Race::Bat2: + return "Bat"; + case Race::Bazu: + return "Bazu"; + case Race::Bear: + case Race::Bear2: + case Race::Bear3: + return "Bear"; + case Race::BearMount: + return "Bear Mount"; + case Race::BearTrap: + return "Bear Trap"; + case Race::Beetle: + case Race::Beetle2: + case Race::Beetle3: + return "Beetle"; + case Race::HumanBeggar: + return "Beggar"; + case Race::Bellikos: + return "Bellikos"; + case Race::Bertoxxulous: + case Race::BertoxxulousNew: + return "Bertoxxulous"; + case Race::Bixie: + case Race::Bixie2: + return "Bixie"; + case Race::BlimpShip: + return "Blimp Ship"; + case Race::BlindDreamer: + return "Blind Dreamer"; + case Race::BloodRaven: + return "Blood Raven"; + case Race::Boat: + case Race::Boat2: + return "Boat"; + case Race::Bolvirk: + return "Bolvirk"; + case Race::BoneGolem: + case Race::BoneGolem2: + return "Bone Golem"; + case Race::Bones: + return "Bones"; + case Race::BookDervish: + return "Book Dervish"; + case Race::Portal: + return "BoT Portal"; + case Race::Boulder: + return "Boulder"; + case Race::Box: + return "Box"; + case Race::Braxi: + return "Braxi"; + case Race::BraxiMount: + return "Braxi Mount"; + case Race::Brell: + return "Brell"; + case Race::BrellsFirstCreation: + return "Brell's First Creation"; + case Race::Bristlebane: + return "Bristlebane"; + case Race::BrokenClockwork: + return "Broken Clockwork"; + case Race::Brontotherium: + return "Brontotherium"; + case Race::Brownie: + case Race::Brownie2: + return "Brownie"; + case Race::Bubonian: + return "Bubonian"; + case Race::BubonianUnderling: + return "Bubonian Underling"; + case Race::Burynai: + case Race::Burynai2: + return "Burynai"; + case Race::TenthAnniversaryCake: + return "10th Anniversary Cake"; + case Race::Campfire: + return "Campfire"; + case Race::CarrierHand: + return "Carrier Hand"; + case Race::Cat: + return "Cat"; + case Race::CazicThule: + case Race::CazicThule2: + return "Cazic Thule"; + case Race::Centaur: + case Race::Centaur2: + return "Centaur"; + case Race::Chest: + case Race::Chest2: + case Race::Chest3: + return "Chest"; + case Race::Chimera: + case Race::Chimera2: + return "Chimera"; + case Race::Chokidai: + return "Chokidai"; + case Race::Clam: + return "Clam"; + case Race::CliknarMount: + return "Cliknar Mount"; + case Race::CliknarQueen: + return "Cliknar Queen"; + case Race::CliknarSoldier: + return "Cliknar Soldier"; + case Race::CliknarWorker: + return "Cliknar Worker"; + case Race::ClockworkBeetle: + return "Clockwork Beetle"; + case Race::ClockworkBoar: + return "Clockwork Boar"; + case Race::ClockworkBomb: + return "Clockwork Bomb"; + case Race::ClockworkBrain: + return "Clockwork Brain"; + case Race::ClockworkGnome: + return "Clockwork Gnome"; + case Race::ClockworkGolem: + return "Clockwork Golem"; + case Race::ClockworkGuardian: + return "Clockwork Guardian"; + case Race::Cockatrice: + return "Cockatrice"; + case Race::Coffin: + case Race::Coffin2: + return "Coffin"; + case Race::CoinPurse: + return "Coin Purse"; + case Race::Coldain: + case Race::Coldain2: + case Race::Coldain3: + return "Coldain"; + case Race::Coral: + return "Coral"; + case Race::Corathus: + return "Corathus"; + case Race::Crab: + return "Crab"; + case Race::Cragbeast: + return "Cragbeast"; + case Race::Cragslither: + return "Cragslither"; + case Race::Crocodile: + return "Crocodile"; + case Race::Crystal: + return "Crystal"; + case Race::CrystalShard: + return "Crystal Shard"; + case Race::CrystalSphere: + return "Crystal Sphere"; + case Race::CrystalSpider: + return "Crystal Spider"; + case Race::CrystalskinAmbuloid: + return "Crystalskin Ambuloid"; + case Race::CrystalskinSessiloid: + return "Crystalskin Sessiloid"; + case Race::DaisyMan: + return "Daisy Man"; + case Race::DarkElf: + case Race::NeriakCitizen: + return "Dark Elf"; + case Race::DarkLord: + return "Dark Lord"; + case Race::DemiLich: + return "Demi Lich"; + case Race::DemonVulture: + return "Demon Vulture"; + case Race::Dervish: + case Race::Dervish2: + case Race::Dervish3: + case Race::Dervish4: + return "Dervish"; + case Race::Dervish5: + return "Dervish(Ver. 5)"; + case Race::Dervish6: + return "Dervish(Ver. 6)"; + case Race::Devourer: + return "Devourer"; + case Race::DireWolf: + return "Dire Wolf"; + case Race::DiscordShip: + return "Discord Ship"; + case Race::Discordling: + return "Discordling"; + case Race::DiseasedFiend: + return "Diseased Fiend"; + case Race::Djinn: + return "Djinn"; + case Race::Drachnid: + case Race::Drachnid2: + return "Drachnid"; + case Race::DrachnidCocoon: + return "Drachnid Cocoon"; + case Race::Dracolich: + return "Dracolich"; + case Race::Draglock: + return "Draglock"; + case Race::LavaDragon: + case Race::DragonSkeleton: + case Race::WaterDragon: + case Race::VeliousDragon: + case Race::ClockworkDragon: + case Race::BlackAndWhiteDragon: + case Race::GhostDragon: + case Race::PrismaticDragon: + case Race::Quarm: + case Race::Dragon: + case Race::Dragon2: + case Race::Dragon3: + case Race::Dragon4: + case Race::Dragon5: + case Race::Dragon6: + case Race::Dragon7: + return "Dragon"; + case Race::DragonBones: + return "Dragon Bones"; + case Race::DragonEgg: + return "Dragon Egg"; + case Race::DragonStatue: + return "Dragon Statue"; + case Race::Dragorn: + return "Dragorn"; + case Race::DragornBox: + return "Dragorn Box"; + case Race::Drake: + case Race::Drake2: + case Race::Drake3: + return "Drake"; + case Race::Drakkin: + return "Drakkin"; + case Race::Drixie: + return "Drixie"; + case Race::Drogmor: + return "Drogmore"; + case Race::Drolvarg: + return "Drolvarg"; + case Race::Dryad: + return "Dryad"; + case Race::Dwarf: + case Race::KaladimCitizen: + return "Dwarf"; + case Race::DynamiteKeg: + return "Dynamite Keg"; + case Race::Dynleth: + return "Dyn'Leth"; + case Race::EarthElemental: + case Race::EarthElemental2: + return "Earth Elemental"; + case Race::EarthMephit: + return "Earth Mephit"; + case Race::GiantEel: + return "Eel"; + case Race::Efreeti: + case Race::Efreeti2: + return "Efreeti"; + case Race::Elddar: + return "Elddar"; + case Race::Elemental: + return "Elemental"; + case Race::ElkHead: + return "Elk Head"; + case Race::ElvenBoat: + return "Elven Boat"; + case Race::ElvenGhost: + return "Elven Ghost"; + case Race::EnchantedArmor: + return "Enchanted Armor"; + case Race::Erollisi: + return "Erollisi"; + case Race::Erudite: + case Race::EruditeCitizen: + case Race::Erudite2: + return "Erudite"; + case Race::EvanTest: + return "Evan Test"; + case Race::EvilEye: + case Race::EvilEye2: + case Race::EvilEye3: + return "Evil Eye"; + case Race::Exoskeleton: + return "Exoskeleton"; + case Race::ExplosiveCart: + return "Explosive Cart"; + case Race::EyeOfZomm: + return "Eye"; + case Race::Fairy: + case Race::Fairy2: + return "Fairy"; + case Race::FallenKnight: + return "Fallen Knight"; + case Race::Faun: + return "Faun"; + case Race::FayDrake: + return "Fay Drake"; + case Race::FenninRo: + return "Fennin Ro"; + case Race::Feran: + return "Feran"; + case Race::FeranMount: + return "Feran Mount"; + case Race::Fiend: + return "Fiend"; + case Race::FireElemental: + case Race::FireElemental2: + return "Fire Elemental"; + case Race::FireMephit: + return "Fire Mephit"; + case Race::Fish: + case Race::KunarkFish: + return "Fish"; + case Race::Flag: + return "Flag"; + case Race::FloatingIsland: + return "Floating Island"; + case Race::FloatingSkull: + return "Floating Skull"; + case Race::FloatingTower: + return "Floating Tower"; + case Race::Fly: + return "Fly"; + case Race::FlyingCarpet: + return "Flying Carpet"; + case Race::ForestGiant2: + return "Forest Giant"; + case Race::Frog: + case Race::Frog2: + return "Frog"; + case Race::Froglok: + case Race::FroglokGhoul: + case Race::Froglok2: + return "Froglok"; + case Race::FroglokGhost: + return "Froglok Ghost"; + case Race::FroglokSkeleton: + return "Froglok Skeleton"; + case Race::FungalFiend: + return "Fungal Fiend"; + case Race::FungusPatch: + return "Fungus Patch"; + case Race::Fungusman: + return "Fungusman"; + case Race::Galorian: + return "Galorian"; + case Race::Gargoyle: + case Race::Gargoyle2: + return "Gargoyle"; + case Race::Gasbag: + return "Gasbag"; + case Race::GelatinousCube: + case Race::GelatinousCube2: + return "Gelatinous Cube"; + case Race::Gelidran: + return "Gelidran"; + case Race::Genari: + return "Genari"; + case Race::Geonid: + return "Geonid"; + case Race::Ghost: + case Race::DwarfGhost: + case Race::EruditeGhost: + case Race::PirateGhost: + return "Ghost"; + case Race::GhostShip: + case Race::GhostShip2: + return "Ghost Ship"; + case Race::Ghoul: + case Race::Ghoul2: + return "Ghoul"; + case Race::Giant: + case Race::ForestGiant: + case Race::FrostGiant: + case Race::StormGiant: + case Race::EarthGolem: + case Race::IronGolem: + case Race::StormGolem: + case Race::AirGolem: + case Race::WoodGolem: + case Race::FireGolem: + case Race::WaterGolem: + case Race::Giant2: + case Race::Giant3: + return "Giant"; + case Race::GiantClockwork: + return "Giant Clockwork"; + case Race::Giant4: + return "Giant(Rallosian mats)"; + case Race::GiantShade: + return "Giant Shade"; + case Race::Gigyn: + return "Gigyn"; + case Race::GingerbreadMan: + return "Gingerbread Man"; + case Race::Girplan: + return "Girplan"; + case Race::Gnoll: + case Race::Gnoll2: + case Race::Gnoll3: + return "Gnoll"; + case Race::Gnome: + return "Gnome"; + case Race::Gnomework: + return "Gnomework"; + case Race::GnomishBalloon: + return "Gnomish Balloon"; + case Race::GnomishBoat: + return "Gnomish Boat"; + case Race::GnomishHoveringTransport: + return "Gnomish Hovering Transport"; + case Race::GnomishRocketPack: + return "Gnomish Rocket Pack"; + case Race::Goblin: + case Race::Bloodgill: + case Race::KunarkGoblin: + case Race::NewGoblin: + case Race::Goblin2: + return "Goblin"; + case Race::Luclin2: + return "God - Luclin(Ver. 2)"; + case Race::Luclin3: + return "God - Luclin(Ver. 3)"; + case Race::Luclin4: + return "God - Luclin(Ver. 4)"; + case Race::GodOfDiscord: + return "God of Discord"; + case Race::Golem: + case Race::Golem2: + return "Golem"; + case Race::Goo: + case Race::Goo2: + case Race::Goo3: + case Race::Goo4: + return "Goo"; + case Race::Goral: + return "Goral"; + case Race::GoralMount: + return "Goral Mount"; + case Race::Gorgon: + return "Gorgon"; + case Race::Gorilla: + case Race::Gorilla2: + return "Gorilla"; + case Race::GrandfatherClock: + return "Grandfather Clock"; + case Race::GrekenYoung: + return "Greken - Young"; + case Race::GrekenYoungAdult: + return "Greken - Young Adult"; + case Race::Grendlaen: + return "Grendlaen"; + case Race::GriegVeneficus: + return "Grieg Veneficus"; + case Race::Griffin: + case Race::Griffin2: + return "Griffin"; + case Race::Grimling: + return "Grimling"; + case Race::GroundShaker: + return "Ground Shaker"; + case Race::FreeportGuard: + case Race::Felguard: + case Race::Fayguard: + case Race::VahShirGuard: + return "Guard"; + case Race::GuardOfJustice: + return "Guard of Justice"; + case Race::GuardianCpu: + return "Guardian CPU"; + case Race::Hadal: + return "Hadal"; + case Race::Hag: + return "Hag"; + case Race::HalfElf: + return "Half Elf"; + case Race::Halfling: + case Race::RivervaleCitizen: + return "Halfling"; + case Race::Harpy: + case Race::Harpy2: + return "Harpy"; + case Race::HighElf: + return "High Elf"; + case Race::Hippogriff: + return "Hippogriff"; + case Race::Holgresh: + case Race::Holgresh2: + return "Holgresh"; + case Race::HoneyPot: + return "Honey Pot"; + case Race::Horse: + case Race::Horse2: + case Race::Horse3: + return "Horse"; + case Race::HoveringPlatform: + return "Hovering Platform"; + case Race::Hraquis: + return "Hraquis"; + case Race::Human: + case Race::HighpassCitizen: + case Race::QeynosCitizen: + case Race::Human2: + return "Human"; + case Race::HumanGhost: + return "Human Ghost"; + case Race::Huvul: + return "Huvul"; + case Race::HydraCrystal: + return "Hydra Crystal"; + case Race::HydraMount: + return "Hydra Mount"; + case Race::Hydra: + return "Hydra NPC"; + case Race::Hynid: + return "Hynid"; + case Race::IceSpectre: + return "Ice Spectre"; + case Race::Ikaav: + return "Ikaav"; + case Race::Iksar: + case Race::IksarCitizen: + return "Iksar"; + case Race::IksarGhost: + return "Iksar Ghost"; + case Race::IksarGolem: + return "Iksar Golem"; + case Race::IksarSkeleton: + return "Iksar Skeleton"; + case Race::IksarSpirit: + return "Iksar Spirit"; + case Race::Imp: + return "Imp"; + case Race::Innoruuk: + return "Innoruuk"; + case Race::Insect: + return "Insect"; + case Race::InteractiveObject: + return "Interactive Object"; + case Race::InvisibleMan: + case Race::InvisibleMan2: + case Race::InvisibleMan3: + return "Invisible Man"; + case Race::InvisibleManOfZomm: + return "Invisible Man of Zomm"; + case Race::Ixt: + return "Ixt"; + case Race::Jokester: + return "Jokester"; + case Race::JumJumBucket: + return "Jum Jum Bucket"; + case Race::JunkBeast: + return "Junk Beast"; + case Race::Kangon: + return "Kangon"; + case Race::KangonMount: + return "Kangon Mount"; + case Race::Karana: + return "Karana"; + case Race::PhinigelAutropos: + case Race::Kedge: + return "Kedge"; + case Race::Kerran: + case Race::Kerran2: + return "Kerran"; + case Race::Kirin: + case Race::Kirin2: + return "Kirin"; + case Race::KnightOfHate: + return "Knight of Hate"; + case Race::KnightOfPestilence: + return "Knight of Pestilence"; + case Race::Kobold: + case Race::Kobold2: + return "Kobold"; + case Race::Kraken: + return "Kraken"; + case Race::Kyv: + return "Kyv"; + case Race::Launch: + return "Launch"; + case Race::LavaRock: + return "Lava Rock"; + case Race::LavaSpider: + return "Lava Spider"; + case Race::LavaSpiderQueen: + return "Lava Spider Queen"; + case Race::Leech: + return "Leech"; + case Race::Lepertoloth: + return "Lepertoloth"; + case Race::Lightcrawler: + return "Lightcrawler"; + case Race::LightingWarrior: + return "Lightning Warrior"; + case Race::Lion: + return "Lion"; + case Race::LizardMan: + return "Lizard Man"; + case Race::Luclin: + return "Luclin"; + case Race::Luggald: + case Race::Luggald2: + return "Luggald"; + case Race::Luggald3: + return "Luggalds"; + case Race::Malarian: + return "Malarian"; + case Race::Mammoth: + case Race::Mammoth2: + return "Mammoth"; + case Race::ManEatingPlant: + return "Man - Eating Plant"; + case Race::Mansion: + return "Mansion"; + case Race::Manticore: + return "Manticore"; + case Race::Unknown5: + return "Mantrap"; + case Race::Marionette: + return "Marionette"; + case Race::Mastruq: + return "Mastruq"; + case Race::MataMuram: + return "Mata Muram"; + case Race::Toolbox: + return "Medium Plant"; + case Race::Mephit: + return "Mephit"; + case Race::MerchantShip: + return "Merchant Ship"; + case Race::Mermaid: + return "Mermaid"; + case Race::Mimic: + return "Mimic"; + case Race::MiniPom: + return "Mini POM"; + case Race::Minotaur: + case Race::Minotaur2: + case Race::Minotaur3: + case Race::Minotaur4: + return "Minotaur"; + case Race::MithanielMarr: + return "Mithaniel Marr"; + case Race::MorellThule: + return "Morell Thule"; + case Race::Mosquito: + return "Mosquito"; + case Race::MouthOfInsanity: + return "Mouth of Insanity"; + case Race::Muddite: + return "Muddite"; + case Race::Mummy: + return "Mummy"; + case Race::MuramiteArmorPile: + return "Muramite Armor Pile"; + case Race::Murkglider: + return "Murkglider"; + case Race::MurkgliderEggSack: + return "Murkglider Egg Sac"; + case Race::Mutna: + return "Mutna"; + case Race::Nekhon: + return "Nekhon"; + case Race::Netherbian: + return "Netherbian"; + case Race::Nightmare: + return "Nightmare"; + case Race::NightmareGargoyle: + return "Nightmare Gargoyle"; + case Race::NightmareGoblin: + return "Nightmare Goblin"; + case Race::NightmareMephit: + return "Nightmare Mephit"; + case Race::Unicorn2: + case Race::Unicorn3: + return "Nightmare / Unicorn"; + case Race::NightmareWraith: + return "Nightmare Wraith"; + case Race::Nihil: + return "Nihil"; + case Race::Nilborien: + return "Nilborien"; + case Race::Noc: + return "Noc"; + case Race::Nymph: + return "Nymph"; + case Race::Ogre: + case Race::OggokCitizen: + return "Ogre"; + case Race::Ogre2: + return "Ogre NPC - Male"; + case Race::Orb: + return "Orb"; + case Race::Orc: + case Race::Orc2: + return "Orc"; + case Race::Othmir: + return "Othmir"; + case Race::Owlbear: + return "Owlbear"; + case Race::ParasiticScavenger: + return "Parasitic Scavenger"; + case Race::Pegasus: + case Race::Pegasus2: + case Race::Pegasus3: + return "Pegasus"; + case Race::Phoenix: + return "Phoenix"; + case Race::Piranha: + return "Piranha"; + case Race::OneArmedPirate: + case Race::SpiritmasterNadox: + case Race::BrokenSkullTaskmaster: + case Race::GnomePirate: + case Race::DarkElfPirate: + case Race::OgrePirate: + case Race::HumanPirate: + case Race::EruditePirate: + return "Pirate"; + case Race::PirateShip: + return "Pirate Ship"; + case Race::Pixie: + return "Pixie"; + case Race::PoisonFrog: + return "Poison Frog"; + case Race::Portal2: + return "Portal"; + case Race::PowderKeg: + return "Powder Keg"; + case Race::PressurePlate: + return "Pressure Plate"; + case Race::PufferSpore: + return "Puffer Spore"; + case Race::Puma: + case Race::Puma2: + case Race::Puma3: + return "Puma"; + case Race::Pusling: + return "Pusling"; + case Race::Pyrilen: + return "Pyrilen"; + case Race::Ratuk: + return "Ra`tuk"; + case Race::Rabbit: + return "Rabbit"; + case Race::StatueOfRallosZek: + case Race::NewRallosZek: + return "Rallos Zek"; + case Race::RallosOgre: + return "Rallos Zek Minion"; + case Race::Raptor: + case Race::Raptor2: + return "Raptor"; + case Race::RaptorMount: + return "Raptor Mount"; + case Race::GiantRat: + case Race::Rat: + return "Rat"; + case Race::RatMount: + return "Rat Mount"; + case Race::Ratman: + case Race::Ratman2: + return "Ratman"; + case Race::ReanimatedHand: + return "Reanimated Hand"; + case Race::Recuso: + return "Recuso"; + case Race::RegenerationPool: + return "Regeneration Pool"; + case Race::RelicCase: + return "Relic case "; + case Race::RhinoBeetle: + return "Rhino Beetle"; + case Race::Rhinoceros: + return "Rhinoceros"; + case Race::RobocopterOfZomm: + return "Robocopter of Zomm"; + case Race::RockPile: + return "Rock Pile"; + case Race::Rockhopper: + return "Rockhopper"; + case Race::RonnieTest: + return "Ronnie Test"; + case Race::RootTentacle: + return "Root Tentacle"; + case Race::RotDogMount: + return "Rot Dog Mount"; + case Race::RotDog: + return "Rotdog"; + case Race::Rotocopter: + return "Rotocopter"; + case Race::Rowboat: + return "Rowboat"; + case Race::RoyalGuard: + return "Royal Guard"; + case Race::RujarkianOrc: + case Race::MasterOrc: + return "Rujarkian Orc"; + case Race::RunedOrb: + return "Runed Orb"; + case Race::RunicSymbol: + return "Runic Symbol"; + case Race::Sabertooth: + return "Saber - toothed Cat"; + case Race::SaltpetterBomb: + return "Saltpetter Bomb"; + case Race::SandElf: + return "Sand Elf"; + case Race::Sandman: + return "Sandman"; + case Race::Sarnak: + case Race::Sarnak2: + return "Sarnak"; + case Race::SarnakGolem: + return "Sarnak Golem"; + case Race::SarnakSpirit: + return "Sarnak Spirit"; + case Race::Saryrn: + return "Saryrn"; + case Race::Satyr: + return "Satyr"; + case Race::ScaledWolf: + return "Scaled Wolf"; + case Race::Scarecrow: + case Race::Scarecrow2: + return "Scarecrow"; + case Race::ScarletCheetah: + return "Scarlet Cheetah"; + case Race::ScleraMount: + return "Sclera Mount"; + case Race::Scorpion: + case Race::IksarScorpion: + case Race::Scorpion2: + return "Scorpion"; + case Race::Scrykin: + return "Scrykin"; + case Race::SeaTurtle: + return "Sea Turtle"; + case Race::SeaHorse: + return "Seahorse"; + case Race::Selyrah: + return "Selyrah"; + case Race::SelyrahMount: + return "Selyrah Mount"; + case Race::LordInquisitorSeru: + return "Seru"; + case Race::ServantOfShadow: + return "Servant of Shadow"; + case Race::SessiloidMount: + return "Sessiloid Mount"; + case Race::Shade: + case Race::Shade2: + case Race::Shade3: + return "Shade"; + case Race::KhatiSha: + return "Shadel"; + case Race::ShamblingMound: + return "Shambling Mound"; + case Race::Shark: + return "Shark"; + case Race::Shiknar: + return "Shik'Nar"; + case Race::Shiliskin: + return "Shiliskin"; + case Race::Ship: + return "Ship"; + case Race::ShipInABottle: + return "Ship in a Bottle"; + case Race::Shissar: + case Race::Shissar2: + return "Shissar"; + case Race::Shrieker: + return "Shrieker"; + case Race::Siren: + case Race::Siren2: + return "Siren"; + case Race::SkeletalHorse: + return "Skeletal Horse"; + case Race::Skeleton: + case Race::Skeleton2: + case Race::Skeleton3: + return "Skeleton"; + case Race::Skunk: + return "Skunk"; + case Race::Skystrider: + return "Skystrider"; + case Race::Plant2: + return "Small Plant"; + case Race::GiantSnake: + case Race::Snake: + return "Snake"; + case Race::SnakeElemental: + return "Snake Elemental"; + case Race::SnowDervish: + return "Snow Dervish"; + case Race::SnowRabbit: + return "Snow Rabbit"; + case Race::Sokokar: + return "Sokokar"; + case Race::SokokarMount: + return "Sokokar Mount"; + case Race::SokokarMount2: + return "Sokokar(w saddle)"; + case Race::SolusekRo: + case Race::SolusekRo2: + return "Solusek Ro"; + case Race::SolusekRoGuard: + return "Solusek Ro Guard"; + case Race::SonicWolf: + return "Sonic Wolf"; + case Race::SoulDevourer: + return "Soul Devourer"; + case Race::Spectre: + case Race::Spectre2: + return "Spectre"; + case Race::SpellParticle: + return "Spell Particle 1"; + case Race::Sphinx: + case Race::Sphinx2: + return "Sphinx"; + case Race::GiantSpider: + case Race::Spider: + return "Spider"; + case Race::SpiderEggSack: + return "Spider Egg Sack"; + case Race::SpiderMount: + return "Spider Mount"; + case Race::SpiderQueen: + return "Spider Queen"; + case Race::SpikeTrap: + return "Spike Trap"; + case Race::SpiritWolf: + return "Spirit Wolf"; + case Race::Sporali: + return "Sporali"; + case Race::StoneJug: + return "Stone Jug"; + case Race::StonePylon: + return "Stone Pylon"; + case Race::StoneRing: + return "Stone Ring"; + case Race::StoneWorker: + case Race::StoneWorker2: + return "Stone Worker"; + case Race::Stonegrabber: + return "Stonegrabber"; + case Race::Stonemite: + return "Stonemite"; + case Race::Stormrider: + return "Stormrider"; + case Race::Succubus: + return "Succubus"; + case Race::Succulent: + return "Succulent"; + case Race::SullonZek: + return "Sullon Zek"; + case Race::Shadel: + return "Sun Revenant"; + case Race::Sunflower: + return "Sunflower"; + case Race::Swinetor: + return "Swinetor"; + case Race::Swordfish: + return "Swordfish"; + case Race::Synarcana: + return "Synarcana"; + case Race::Table: + return "Table"; + case Race::FroglokTadpole: + return "Tadpole"; + case Race::Taelosian: + return "Taelosian"; + case Race::WineCask: + return "Tall Plant"; + case Race::TallonZek: + return "Tallon Zek"; + case Race::Taneth: + return "Taneth"; + case Race::TarewMarr: + return "Tarew Marr"; + case Race::Tegi: + return "Tegi"; + case Race::TeleportMan: + return "Teleport Man"; + case Race::TeleportationStand: + return "Teleportation Stand"; + case Race::Telmira: + return "Telmira"; + case Race::TentacleTerror: + case Race::TentacleTerror2: + return "Tentacle Terror"; + case Race::TerrisThule: + return "Terris Thule"; + case Race::TestObject: + return "Test Object"; + case Race::Rathe: + return "The Rathe"; + case Race::TribunalNew: + return "The Tribunal"; + case Race::ThoughtHorror: + return "Thought Horror"; + case Race::Tiger: + return "Tiger"; + case Race::TinSoldier: + return "Tin Soldier"; + case Race::Plant: + return "Toolbox"; + case Race::TopiaryLion: + return "Topiary Lion"; + case Race::TopiaryLionMount: + return "Topiary Lion Mount"; + case Race::Tormentor: + return "Tormentor"; + case Race::Totem: + case Race::Totem2: + return "Totem"; + case Race::Trakanon: + return "Trakanon"; + case Race::Tranquilion: + return "Tranquilion"; + case Race::Treant: + case Race::Treant2: + case Race::Treant3: + return "Treant"; + case Race::Tribunal: + return "Tribunal"; + case Race::Triumvirate: + return "Triumvirate"; + case Race::Troll: + case Race::GrobbCitizen: + case Race::TrollCrewMember: + case Race::PirateDeckhand: + case Race::BrokenSkullPirate: + return "Troll"; + case Race::TrollZombie: + return "Troll Zombie"; + case Race::Trusik: + return "Trusik"; + case Race::Tsetsian: + return "Tsetsian"; + case Race::Tumbleweed: + return "Tumbleweed"; + case Race::Tunare: + return "Tunare"; + case Race::Turepta: + return "Turepta"; + case Race::Ukun: + return "Ukun"; + case Race::Ulthork: + return "Ulthork"; + case Race::UndeadChokidai: + return "Undead Chokidai"; + case Race::UndeadFootman: + return "Undead Footman"; + case Race::UndeadFroglok: + return "Undead Froglok"; + case Race::UndeadIksar: + return "Undead Iksar"; + case Race::UndeadKnight: + return "Undead Knight"; + case Race::UndeadSarnak: + return "Undead Sarnak"; + case Race::UndeadVeksar: + return "Undead Veksar"; + case Race::Underbulk: + return "Underbulk"; + case Race::Unicorn: + return "Unicorn"; + case Race::Doug: + case Race::MinorIllusion: + case Race::Tree: + case Race::Unknown: + case Race::Unknown2: + case Race::Unknown3: + case Race::Unknown4: + return "UNKNOWN RACE"; + case Race::VahShir: + case Race::VahShirKing: + return "Vah Shir"; + case Race::VahShirSkeleton: + return "Vah Shir Skeleton"; + case Race::VallonZek: + return "Vallon Zek"; + case Race::Valorian: + case Race::Valorian2: + return "Valorian"; + case Race::Vampire: + case Race::ElfVampire: + case Race::Vampire2: + case Race::VampireVolatalis: + case Race::UndeadVampire: + case Race::Vampire3: + case Race::MasterVampire: + case Race::Vampire4: + return "Vampire"; + case Race::Vase: + return "Vase"; + case Race::Vegerog: + return "Vegerog"; + case Race::Veksar: + case Race::Veksar2: + case Race::Veksar3: + return "Veksar"; + case Race::VenrilSathir: + return "Venril Sathir"; + case Race::VineMaw: + return "Vine Maw"; + case Race::Wagon: + return "Wagon"; + case Race::Walrus: + return "Walrus"; + case Race::WarBoar: + case Race::WarBoar2: + return "War Boar"; + case Race::WarWraith: + return "War Wraith"; + case Race::Wasp: + return "Wasp"; + case Race::WaterElemental: + case Race::WaterElemental2: + return "Water Elemental"; + case Race::WaterMephit: + return "Water Mephit"; + case Race::WaterSpout: + return "Water Spout"; + case Race::WeaponRack: + case Race::WeaponRack2: + return "Weapon Rack"; + case Race::Web: + return "Web"; + case Race::WeddingAltar: + return "Wedding Altar"; + case Race::WeddingArbor: + return "Wedding Arbor"; + case Race::WeddingFlowers: + return "Wedding Flowers"; + case Race::Wereorc: + return "Wereorc"; + case Race::Werewolf: + case Race::Werewolf2: + case Race::Werewolf3: + return "Werewolf"; + case Race::WetfangMinnow: + return "Wetfang Minnow"; + case Race::Whirligig: + return "Whirligig"; + case Race::WickerBasket: + return "Wicker Basket"; + case Race::Wisp: + return "Will - O - Wisp"; + case Race::StoneJug2: + case Race::WineCask2: + return "Wine Cask"; + case Race::Witheran: + case Race::Witheran2: + return "Witheran"; + case Race::Wolf: + case Race::WolfElemental: + case Race::Wolf2: + return "Wolf"; + case Race::WoodElf: + return "Wood Elf"; + case Race::Worg: + case Race::Worg2: + return "Worg"; + case Race::Worm: + return "Worm"; + case Race::Wretch: + return "Wretch"; + case Race::Wrulon: + case Race::Wrulon2: + return "Wrulon"; + case Race::Wurm: + case Race::Wurm2: + return "Wurm"; + case Race::WurmMount: + return "Wurm Mount"; + case Race::Wyvern: + case Race::Wyvern2: + return "Wyvern"; + case Race::Xalgoz: + return "Xalgoz"; + case Race::Xaric: + return "Xaric the Unspoken"; + case Race::Xegony: + return "Xegony"; + case Race::Yakkar: + return "Yakkar"; + case Race::Yeti: + return "Yeti"; + case Race::Zebuxoruk: + return "Zebuxoruk"; + case Race::ZebuxoruksCage: + return "Zebuxoruk's Cage"; + case Race::Zelniak: + return "Zelniak"; + case Race::Zombie: + case Race::Zombie2: + return "Zombie"; + default: + return "UNKNOWN RACE"; } } -const char* GetPlayerRaceName(uint32 player_race_value) +uint32 GetPlayerRaceValue(uint16 race_id) { - return GetRaceIDName(GetRaceIDFromPlayerRaceValue(player_race_value)); -} - -uint32 GetPlayerRaceValue(uint16 race_id) { switch (race_id) { - case HUMAN: - case BARBARIAN: - case ERUDITE: - case WOOD_ELF: - case HIGH_ELF: - case DARK_ELF: - case HALF_ELF: - case DWARF: - case TROLL: - case OGRE: - case HALFLING: - case GNOME: + case Race::Human: + case Race::Barbarian: + case Race::Erudite: + case Race::WoodElf: + case Race::HighElf: + case Race::DarkElf: + case Race::HalfElf: + case Race::Dwarf: + case Race::Troll: + case Race::Ogre: + case Race::Halfling: + case Race::Gnome: return race_id; - case IKSAR: - return PLAYER_RACE_IKSAR; - case VAHSHIR: - return PLAYER_RACE_VAHSHIR; - case FROGLOK: - case FROGLOK2: - return PLAYER_RACE_FROGLOK; - case DRAKKIN: - return PLAYER_RACE_DRAKKIN; + case Race::Iksar: + return RaceIndex::Iksar; + case Race::VahShir: + return RaceIndex::VahShir; + case Race::Froglok2: + return RaceIndex::Froglok; + case Race::Drakkin: + return RaceIndex::Drakkin; default: - return PLAYER_RACE_UNKNOWN; // watch + return Race::Doug; } } -uint16 GetPlayerRaceBit(uint16 race_id) { +uint16 GetPlayerRaceBit(uint16 race_id) +{ switch (race_id) { - case HUMAN: - return PLAYER_RACE_HUMAN_BIT; - case BARBARIAN: - return PLAYER_RACE_BARBARIAN_BIT; - case ERUDITE: - return PLAYER_RACE_ERUDITE_BIT; - case WOOD_ELF: - return PLAYER_RACE_WOOD_ELF_BIT; - case HIGH_ELF: - return PLAYER_RACE_HIGH_ELF_BIT; - case DARK_ELF: - return PLAYER_RACE_DARK_ELF_BIT; - case HALF_ELF: - return PLAYER_RACE_HALF_ELF_BIT; - case DWARF: - return PLAYER_RACE_DWARF_BIT; - case TROLL: - return PLAYER_RACE_TROLL_BIT; - case OGRE: - return PLAYER_RACE_OGRE_BIT; - case HALFLING: - return PLAYER_RACE_HALFLING_BIT; - case GNOME: - return PLAYER_RACE_GNOME_BIT; - case IKSAR: - return PLAYER_RACE_IKSAR_BIT; - case VAHSHIR: - return PLAYER_RACE_VAHSHIR_BIT; - case FROGLOK: - return PLAYER_RACE_FROGLOK_BIT; - case DRAKKIN: - return PLAYER_RACE_DRAKKIN_BIT; + case Race::Human: + return RaceBitmask::Human; + case Race::Barbarian: + return RaceBitmask::Barbarian; + case Race::Erudite: + return RaceBitmask::Erudite; + case Race::WoodElf: + return RaceBitmask::WoodElf; + case Race::HighElf: + return RaceBitmask::HighElf; + case Race::DarkElf: + return RaceBitmask::DarkElf; + case Race::HalfElf: + return RaceBitmask::HalfElf; + case Race::Dwarf: + return RaceBitmask::Dwarf; + case Race::Troll: + return RaceBitmask::Troll; + case Race::Ogre: + return RaceBitmask::Ogre; + case Race::Halfling: + return RaceBitmask::Halfling; + case Race::Gnome: + return RaceBitmask::Gnome; + case Race::Iksar: + return RaceBitmask::Iksar; + case Race::VahShir: + return RaceBitmask::VahShir; + case Race::Froglok2: + return RaceBitmask::Froglok; + case Race::Drakkin: + return RaceBitmask::Drakkin; default: - return PLAYER_RACE_UNKNOWN_BIT; + return RaceBitmask::Unknown; } } -uint16 GetRaceIDFromPlayerRaceValue(uint32 player_race_value) { +uint16 GetRaceIDFromPlayerRaceValue(uint32 player_race_value) +{ switch (player_race_value) { - case PLAYER_RACE_HUMAN: - case PLAYER_RACE_BARBARIAN: - case PLAYER_RACE_ERUDITE: - case PLAYER_RACE_WOOD_ELF: - case PLAYER_RACE_HIGH_ELF: - case PLAYER_RACE_DARK_ELF: - case PLAYER_RACE_HALF_ELF: - case PLAYER_RACE_DWARF: - case PLAYER_RACE_TROLL: - case PLAYER_RACE_OGRE: - case PLAYER_RACE_HALFLING: - case PLAYER_RACE_GNOME: + case RaceIndex::Human: + case RaceIndex::Barbarian: + case RaceIndex::Erudite: + case RaceIndex::WoodElf: + case RaceIndex::HighElf: + case RaceIndex::DarkElf: + case RaceIndex::HalfElf: + case RaceIndex::Dwarf: + case RaceIndex::Troll: + case RaceIndex::Ogre: + case RaceIndex::Halfling: + case RaceIndex::Gnome: return player_race_value; - case PLAYER_RACE_IKSAR: - return IKSAR; - case PLAYER_RACE_VAHSHIR: - return VAHSHIR; - case PLAYER_RACE_FROGLOK: - return FROGLOK; - case PLAYER_RACE_DRAKKIN: - return DRAKKIN; + case RaceIndex::Iksar: + return Race::Iksar; + case RaceIndex::VahShir: + return Race::VahShir; + case RaceIndex::Froglok: + return Race::Froglok2; + case RaceIndex::Drakkin: + return Race::Drakkin; default: - return PLAYER_RACE_UNKNOWN; // watch - } -} - -uint16 GetRaceIDFromPlayerRaceBit(uint32 player_race_bit) -{ - switch (player_race_bit) { - case PLAYER_RACE_HUMAN_BIT: - return HUMAN; - case PLAYER_RACE_BARBARIAN_BIT: - return BARBARIAN; - case PLAYER_RACE_ERUDITE_BIT: - return ERUDITE; - case PLAYER_RACE_WOOD_ELF_BIT: - return WOOD_ELF; - case PLAYER_RACE_HIGH_ELF_BIT: - return HIGH_ELF; - case PLAYER_RACE_DARK_ELF_BIT: - return DARK_ELF; - case PLAYER_RACE_HALF_ELF_BIT: - return HALF_ELF; - case PLAYER_RACE_DWARF_BIT: - return DWARF; - case PLAYER_RACE_TROLL_BIT: - return TROLL; - case PLAYER_RACE_OGRE_BIT: - return OGRE; - case PLAYER_RACE_HALFLING_BIT: - return HALFLING; - case PLAYER_RACE_GNOME_BIT: - return GNOME; - case PLAYER_RACE_IKSAR_BIT: - return IKSAR; - case PLAYER_RACE_VAHSHIR_BIT: - return VAHSHIR; - case PLAYER_RACE_FROGLOK_BIT: - return FROGLOK; - case PLAYER_RACE_DRAKKIN_BIT: - return DRAKKIN; - default: - return PLAYER_RACE_UNKNOWN; // watch + return Race::Doug; } } @@ -1605,634 +1514,480 @@ float GetRaceGenderDefaultHeight(int race, int gender) return male_height[race]; } -// PlayerAppearance prep -#define HUMAN_MALE ((HUMAN << 8) | Gender::Male) -#define HUMAN_FEMALE ((HUMAN << 8) | Gender::Female) -#define BARBARIAN_MALE ((BARBARIAN << 8) | Gender::Male) -#define BARBARIAN_FEMALE ((BARBARIAN << 8) | Gender::Female) -#define ERUDITE_MALE ((ERUDITE << 8) | Gender::Male) -#define ERUDITE_FEMALE ((ERUDITE << 8) | Gender::Female) -#define WOOD_ELF_MALE ((WOOD_ELF << 8) | Gender::Male) -#define WOOD_ELF_FEMALE ((WOOD_ELF << 8) | Gender::Female) -#define HIGH_ELF_MALE ((HIGH_ELF << 8) | Gender::Male) -#define HIGH_ELF_FEMALE ((HIGH_ELF << 8) | Gender::Female) -#define DARK_ELF_MALE ((DARK_ELF << 8) | Gender::Male) -#define DARK_ELF_FEMALE ((DARK_ELF << 8) | Gender::Female) -#define HALF_ELF_MALE ((HALF_ELF << 8) | Gender::Male) -#define HALF_ELF_FEMALE ((HALF_ELF << 8) | Gender::Female) -#define DWARF_MALE ((DWARF << 8) | Gender::Male) -#define DWARF_FEMALE ((DWARF << 8) | Gender::Female) -#define TROLL_MALE ((TROLL << 8) | Gender::Male) -#define TROLL_FEMALE ((TROLL << 8) | Gender::Female) -#define OGRE_MALE ((OGRE << 8) | Gender::Male) -#define OGRE_FEMALE ((OGRE << 8) | Gender::Female) -#define HALFLING_MALE ((HALFLING << 8) | Gender::Male) -#define HALFLING_FEMALE ((HALFLING << 8) | Gender::Female) -#define GNOME_MALE ((GNOME << 8) | Gender::Male) -#define GNOME_FEMALE ((GNOME << 8) | Gender::Female) -#define IKSAR_MALE ((IKSAR << 8) | Gender::Male) -#define IKSAR_FEMALE ((IKSAR << 8) | Gender::Female) -#define VAHSHIR_MALE ((VAHSHIR << 8) | Gender::Male) -#define VAHSHIR_FEMALE ((VAHSHIR << 8) | Gender::Female) -#define FROGLOK_MALE ((FROGLOK << 8) | Gender::Male) -#define FROGLOK_FEMALE ((FROGLOK << 8) | Gender::Female) -#define DRAKKIN_MALE ((DRAKKIN << 8) | Gender::Male) -#define DRAKKIN_FEMALE ((DRAKKIN << 8) | Gender::Female) - -#define BINDRG(r, g) (((int)r << 8) | g) - - -bool PlayerAppearance::IsValidBeard(uint16 race_id, uint8 gender_id, uint8 beard_value, bool use_luclin) +#define GetRaceGenderMask(race_id, gender_id) (((int)race_id << 8) | gender_id) + +bool RaceAppearance::IsValidBeard(uint16 race_id, uint8 gender_id, uint8 beard_value, bool use_luclin) { - if (beard_value == 0xFF) + if (beard_value == std::numeric_limits::max()) { return true; + } if (use_luclin) { - switch (BINDRG(race_id, gender_id)) { - case DWARF_FEMALE: - if (beard_value <= 1) - return true; - break; - case HIGH_ELF_MALE: - case DARK_ELF_MALE: - case HALF_ELF_MALE: - case DRAKKIN_FEMALE: - if (beard_value <= 3) + switch (GetRaceGenderMask(race_id, gender_id)) { + case RaceAppearance::DwarfFemale: + if (beard_value <= 1) { + return true; + } + + break; + case RaceAppearance::HighElfMale: + case RaceAppearance::DarkElfMale: + case RaceAppearance::HalfElfMale: + case RaceAppearance::DrakkinFemale: + if (beard_value <= 3) { + return true; + } + + break; + case RaceAppearance::HumanMale: + case RaceAppearance::BarbarianMale: + case RaceAppearance::EruditeMale: + case RaceAppearance::DwarfMale: + case RaceAppearance::HalflingMale: + case RaceAppearance::GnomeMale: + if (beard_value <= 5) { + return true; + } + + break; + case RaceAppearance::DrakkinMale: + if (beard_value <= 11) { + return true; + } + + break; + default: + break; + } + + return false; + } else { + switch (GetRaceGenderMask(race_id, gender_id)) { + case RaceAppearance::DrakkinFemale: + if (beard_value <= 3) { + return true; + } + + break; + case RaceAppearance::DrakkinMale: + if (beard_value <= 11) { + return true; + } + + break; + default: + break; + } + + return false; + } +} + +bool RaceAppearance::IsValidBeardColor(uint16 race_id, uint8 gender_id, uint8 beard_color_value, bool use_luclin) +{ + if (beard_color_value == std::numeric_limits::max()) { + return true; + } + + switch (GetRaceGenderMask(race_id, gender_id)) { + case RaceAppearance::GnomeMale: + if (beard_color_value <= 24) { return true; + } + break; - case HUMAN_MALE: - case BARBARIAN_MALE: - case ERUDITE_MALE: - case DWARF_MALE: - case HALFLING_MALE: - case GNOME_MALE: - if (beard_value <= 5) + case RaceAppearance::HumanMale: + case RaceAppearance::BarbarianMale: + case RaceAppearance::EruditeMale: + case RaceAppearance::HalfElfMale: + case RaceAppearance::DwarfMale: + case RaceAppearance::DwarfFemale: + case RaceAppearance::HalflingMale: + if (beard_color_value <= 19) { return true; + } + break; - case DRAKKIN_MALE: - if (beard_value <= 11) + case RaceAppearance::DarkElfMale: + if (EQ::ValueWithin(beard_color_value, 13, 18)) { return true; + } + break; - default: - break; - } - return false; - } - else { - switch (BINDRG(race_id, gender_id)) { - case DRAKKIN_FEMALE: - if (beard_value <= 3) + case RaceAppearance::HighElfMale: + if (beard_color_value <= 14) { return true; + } + break; - case DRAKKIN_MALE: - if (beard_value <= 11) + case RaceAppearance::FroglokMale: + case RaceAppearance::FroglokFemale: + case RaceAppearance::DrakkinMale: + case RaceAppearance::DrakkinFemale: + if (beard_color_value <= 3) { return true; + } + break; default: break; - } - return false; } -} -bool PlayerAppearance::IsValidBeardColor(uint16 race_id, uint8 gender_id, uint8 beard_color_value, bool use_luclin) -{ - if (beard_color_value == 0xFF) - return true; - - switch (BINDRG(race_id, gender_id)) { - case GNOME_MALE: - if (beard_color_value <= 24) - return true; - break; - case HUMAN_MALE: - case BARBARIAN_MALE: - case ERUDITE_MALE: - case HALF_ELF_MALE: - case DWARF_MALE: - case DWARF_FEMALE: - case HALFLING_MALE: - if (beard_color_value <= 19) - return true; - break; - case DARK_ELF_MALE: - if (beard_color_value >= 13 && beard_color_value <= 18) - return true; - break; - case HIGH_ELF_MALE: - if (beard_color_value <= 14) - return true; - break; - case FROGLOK_MALE: - case FROGLOK_FEMALE: - case DRAKKIN_MALE: - case DRAKKIN_FEMALE: - if (beard_color_value <= 3) - return true; - break; - default: - break; - } return false; } -bool PlayerAppearance::IsValidDetail(uint16 race_id, uint8 gender_id, uint32 detail_value, bool use_luclin) +bool RaceAppearance::IsValidDetail(uint16 race_id, uint8 gender_id, uint32 detail_value, bool use_luclin) { - if (detail_value == 0xFFFFFFFF) + if (detail_value == std::numeric_limits::max()) { return true; - - switch (BINDRG(race_id, gender_id)) { - case DRAKKIN_MALE: - case DRAKKIN_FEMALE: - if (detail_value <= 7) - return true; - break; - default: - break; } - return false; -} -bool PlayerAppearance::IsValidEyeColor(uint16 race_id, uint8 gender_id, uint8 eye_color_value, bool use_luclin) -{ - return true; // need valid criteria - - switch (BINDRG(race_id, gender_id)) { - case HUMAN_MALE: - case HUMAN_FEMALE: - case BARBARIAN_MALE: - case BARBARIAN_FEMALE: - case ERUDITE_MALE: - case ERUDITE_FEMALE: - case WOOD_ELF_MALE: - case WOOD_ELF_FEMALE: - case HIGH_ELF_MALE: - case HIGH_ELF_FEMALE: - case DARK_ELF_MALE: - case DARK_ELF_FEMALE: - case HALF_ELF_MALE: - case HALF_ELF_FEMALE: - case DWARF_MALE: - case DWARF_FEMALE: - case OGRE_MALE: - case OGRE_FEMALE: - case HALFLING_MALE: - case HALFLING_FEMALE: - case GNOME_MALE: - case GNOME_FEMALE: - case IKSAR_MALE: - case IKSAR_FEMALE: - case VAHSHIR_MALE: - case VAHSHIR_FEMALE: - if (eye_color_value <= 9) - return true; - break; - case TROLL_MALE: - case TROLL_FEMALE: - if (eye_color_value <= 10) - return true; - break; - case FROGLOK_MALE: - case FROGLOK_FEMALE: - case DRAKKIN_MALE: - case DRAKKIN_FEMALE: - if (eye_color_value <= 11) - return true; - break; - default: - break; - } - return false; -} - -bool PlayerAppearance::IsValidFace(uint16 race_id, uint8 gender_id, uint8 face_value, bool use_luclin) -{ - if (face_value == 0xFF) - return true; + switch (GetRaceGenderMask(race_id, gender_id)) { + case RaceAppearance::DrakkinMale: + case RaceAppearance::DrakkinFemale: + if (detail_value <= 7) { + return true; + } - switch (BINDRG(race_id, gender_id)) { - case DRAKKIN_MALE: - case DRAKKIN_FEMALE: - if (face_value <= 6) - return true; - break; - case HUMAN_MALE: - case HUMAN_FEMALE: - case BARBARIAN_MALE: - case BARBARIAN_FEMALE: - case ERUDITE_MALE: - case ERUDITE_FEMALE: - case WOOD_ELF_MALE: - case WOOD_ELF_FEMALE: - case HIGH_ELF_MALE: - case HIGH_ELF_FEMALE: - case DARK_ELF_MALE: - case DARK_ELF_FEMALE: - case HALF_ELF_MALE: - case HALF_ELF_FEMALE: - case DWARF_MALE: - case DWARF_FEMALE: - case TROLL_MALE: - case TROLL_FEMALE: - case OGRE_MALE: - case OGRE_FEMALE: - case HALFLING_MALE: - case HALFLING_FEMALE: - case GNOME_MALE: - case GNOME_FEMALE: - case IKSAR_MALE: - case IKSAR_FEMALE: - case VAHSHIR_MALE: - case VAHSHIR_FEMALE: - if (face_value <= 7) - return true; - break; - case FROGLOK_MALE: - case FROGLOK_FEMALE: - if (face_value <= 9) - return true; - break; - default: - break; + break; + default: + break; } + return false; } -bool PlayerAppearance::IsValidHair(uint16 race_id, uint8 gender_id, uint8 hair_value, bool use_luclin) +bool RaceAppearance::IsValidEyeColor(uint16 race_id, uint8 gender_id, uint8 eye_color_value, bool use_luclin) { - if (hair_value == 0xFF) + if (eye_color_value == std::numeric_limits::max()) { return true; + } - if (use_luclin) { - switch (BINDRG(race_id, gender_id)) { - case HUMAN_MALE: - case HUMAN_FEMALE: - case BARBARIAN_MALE: - case BARBARIAN_FEMALE: - case WOOD_ELF_MALE: - case WOOD_ELF_FEMALE: - case HIGH_ELF_MALE: - case HIGH_ELF_FEMALE: - case DARK_ELF_MALE: - case DARK_ELF_FEMALE: - case HALF_ELF_MALE: - case HALF_ELF_FEMALE: - case DWARF_MALE: - case DWARF_FEMALE: - case TROLL_FEMALE: - case OGRE_FEMALE: - case HALFLING_MALE: - case HALFLING_FEMALE: - case GNOME_MALE: - case GNOME_FEMALE: - if (hair_value <= 3) - return true; - break; - case ERUDITE_MALE: - if (hair_value <= 5) - return true; - break; - case DRAKKIN_FEMALE: - if (hair_value <= 7) + switch (GetRaceGenderMask(race_id, gender_id)) { + case RaceAppearance::HumanMale: + case RaceAppearance::HumanFemale: + case RaceAppearance::BarbarianMale: + case RaceAppearance::BarbarianFemale: + case RaceAppearance::EruditeMale: + case RaceAppearance::EruditeFemale: + case RaceAppearance::WoodElfMale: + case RaceAppearance::WoodElfFemale: + case RaceAppearance::HighElfMale: + case RaceAppearance::HighElfFemale: + case RaceAppearance::DarkElfMale: + case RaceAppearance::DarkElfFemale: + case RaceAppearance::HalfElfMale: + case RaceAppearance::HalfElfFemale: + case RaceAppearance::DwarfMale: + case RaceAppearance::DwarfFemale: + case RaceAppearance::OgreMale: + case RaceAppearance::OgreFemale: + case RaceAppearance::HalflingMale: + case RaceAppearance::HalflingFemale: + case RaceAppearance::GnomeMale: + case RaceAppearance::GnomeFemale: + case RaceAppearance::IksarMale: + case RaceAppearance::IksarFemale: + case RaceAppearance::VahShirMale: + case RaceAppearance::VahShirFemale: + if (eye_color_value <= 9) { return true; + } + break; - case ERUDITE_FEMALE: - case DRAKKIN_MALE: - if (hair_value <= 8) - return true; - break; - default: - break; - } - return false; - } - else { - switch (BINDRG(race_id, gender_id)) { - case DRAKKIN_FEMALE: - if (hair_value <= 7) + case RaceAppearance::TrollMale: + case RaceAppearance::TrollFemale: + if (eye_color_value <= 10) { return true; + } + break; - case DRAKKIN_MALE: - if (hair_value <= 8) + case RaceAppearance::FroglokMale: + case RaceAppearance::FroglokFemale: + case RaceAppearance::DrakkinMale: + case RaceAppearance::DrakkinFemale: + if (eye_color_value <= 11) { return true; + } + break; default: break; - } - return false; } -} - -bool PlayerAppearance::IsValidHairColor(uint16 race_id, uint8 gender_id, uint8 hair_color_value, bool use_luclin) -{ - if (hair_color_value == 0xFF) - return true; - switch (BINDRG(race_id, gender_id)) { - case GNOME_MALE: - case GNOME_FEMALE: - if (hair_color_value <= 24) - return true; - break; - case TROLL_FEMALE: - case OGRE_FEMALE: - if (hair_color_value <= 23) - return true; - break; - case HUMAN_MALE: - case HUMAN_FEMALE: - case BARBARIAN_MALE: - case BARBARIAN_FEMALE: - case WOOD_ELF_MALE: - case WOOD_ELF_FEMALE: - case HALF_ELF_MALE: - case HALF_ELF_FEMALE: - case DWARF_MALE: - case DWARF_FEMALE: - case HALFLING_MALE: - case HALFLING_FEMALE: - if (hair_color_value <= 19) - return true; - break; - case DARK_ELF_MALE: - case DARK_ELF_FEMALE: - if (hair_color_value >= 13 && hair_color_value <= 18) - return true; - break; - case HIGH_ELF_MALE: - case HIGH_ELF_FEMALE: - if (hair_color_value <= 14) - return true; - break; - case FROGLOK_MALE: - case FROGLOK_FEMALE: - case DRAKKIN_MALE: - case DRAKKIN_FEMALE: - if (hair_color_value <= 3) - return true; - break; - default: - break; - } return false; } -bool PlayerAppearance::IsValidHead(uint16 race_id, uint8 gender_id, uint8 head_value, bool use_luclin) +bool RaceAppearance::IsValidFace(uint16 race_id, uint8 gender_id, uint8 face_value, bool use_luclin) { - if (head_value == 0xFF) + if (face_value == std::numeric_limits::max()) { return true; + } - if (use_luclin) { - switch (BINDRG(race_id, gender_id)) { - case HUMAN_MALE: - case HUMAN_FEMALE: - case BARBARIAN_MALE: - case BARBARIAN_FEMALE: - case WOOD_ELF_MALE: - case WOOD_ELF_FEMALE: - case HIGH_ELF_MALE: - case HIGH_ELF_FEMALE: - case DARK_ELF_MALE: - case DARK_ELF_FEMALE: - case HALF_ELF_MALE: - case HALF_ELF_FEMALE: - case DWARF_MALE: - case DWARF_FEMALE: - case TROLL_MALE: - case TROLL_FEMALE: - case OGRE_MALE: - case OGRE_FEMALE: - case HALFLING_MALE: - case HALFLING_FEMALE: - case GNOME_MALE: - case GNOME_FEMALE: - case IKSAR_MALE: - case IKSAR_FEMALE: - case VAHSHIR_MALE: - case VAHSHIR_FEMALE: - case FROGLOK_MALE: - case FROGLOK_FEMALE: - case DRAKKIN_MALE: - case DRAKKIN_FEMALE: - if (head_value <= 3) + switch (GetRaceGenderMask(race_id, gender_id)) { + case RaceAppearance::DrakkinMale: + case RaceAppearance::DrakkinFemale: + if (face_value <= 6) { return true; + } + break; - case ERUDITE_MALE: - case ERUDITE_FEMALE: - if (head_value <= 4) - return true; - break; - default: - break; - } - return false; - } - else { - switch (BINDRG(race_id, gender_id)) { - case HUMAN_MALE: - case HUMAN_FEMALE: - case BARBARIAN_MALE: - case BARBARIAN_FEMALE: - case ERUDITE_MALE: - case ERUDITE_FEMALE: - case WOOD_ELF_MALE: - case WOOD_ELF_FEMALE: - case HIGH_ELF_MALE: - case HIGH_ELF_FEMALE: - case DARK_ELF_MALE: - case DARK_ELF_FEMALE: - case HALF_ELF_MALE: - case HALF_ELF_FEMALE: - case DWARF_MALE: - case DWARF_FEMALE: - case TROLL_MALE: - case TROLL_FEMALE: - case OGRE_MALE: - case OGRE_FEMALE: - case HALFLING_MALE: - case HALFLING_FEMALE: - case IKSAR_MALE: - case IKSAR_FEMALE: - case VAHSHIR_MALE: - case VAHSHIR_FEMALE: - case FROGLOK_MALE: - case FROGLOK_FEMALE: - case DRAKKIN_MALE: - case DRAKKIN_FEMALE: - if (head_value <= 3) + case RaceAppearance::HumanMale: + case RaceAppearance::HumanFemale: + case RaceAppearance::BarbarianMale: + case RaceAppearance::BarbarianFemale: + case RaceAppearance::EruditeMale: + case RaceAppearance::EruditeFemale: + case RaceAppearance::WoodElfMale: + case RaceAppearance::WoodElfFemale: + case RaceAppearance::HighElfMale: + case RaceAppearance::HighElfFemale: + case RaceAppearance::DarkElfMale: + case RaceAppearance::DarkElfFemale: + case RaceAppearance::HalfElfMale: + case RaceAppearance::HalfElfFemale: + case RaceAppearance::DwarfMale: + case RaceAppearance::DwarfFemale: + case RaceAppearance::TrollMale: + case RaceAppearance::TrollFemale: + case RaceAppearance::OgreMale: + case RaceAppearance::OgreFemale: + case RaceAppearance::HalflingMale: + case RaceAppearance::HalflingFemale: + case RaceAppearance::GnomeMale: + case RaceAppearance::GnomeFemale: + case RaceAppearance::IksarMale: + case RaceAppearance::IksarFemale: + case RaceAppearance::VahShirMale: + case RaceAppearance::VahShirFemale: + if (face_value <= 7) { return true; + } + break; - case GNOME_MALE: - case GNOME_FEMALE: - if (head_value <= 4) + case RaceAppearance::FroglokMale: + case RaceAppearance::FroglokFemale: + if (face_value <= 9) { return true; + } + break; default: break; - } - return false; } -} -bool PlayerAppearance::IsValidHeritage(uint16 race_id, uint8 gender_id, uint32 heritage_value, bool use_luclin) -{ - if (heritage_value == 0xFFFFFFFF) - return true; - - switch (BINDRG(race_id, gender_id)) { - case DRAKKIN_MALE: - case DRAKKIN_FEMALE: - if (heritage_value <= 7) // > 5 seems to jumble other features..else, some heritages have 'specialized' features - return true; - break; - default: - break; - } return false; } -bool PlayerAppearance::IsValidTattoo(uint16 race_id, uint8 gender_id, uint32 tattoo_value, bool use_luclin) +bool RaceAppearance::IsValidHair(uint16 race_id, uint8 gender_id, uint8 hair_value, bool use_luclin) { - if (tattoo_value == 0xFFFFFFFF) + if (hair_value == std::numeric_limits::max()) { return true; + } - switch (BINDRG(race_id, gender_id)) { - case DRAKKIN_MALE: - case DRAKKIN_FEMALE: - if (tattoo_value <= 7) - return true; - break; - default: - break; + if (use_luclin) { + switch (GetRaceGenderMask(race_id, gender_id)) { + case RaceAppearance::HumanMale: + case RaceAppearance::HumanFemale: + case RaceAppearance::BarbarianMale: + case RaceAppearance::BarbarianFemale: + case RaceAppearance::WoodElfMale: + case RaceAppearance::WoodElfFemale: + case RaceAppearance::HighElfMale: + case RaceAppearance::HighElfFemale: + case RaceAppearance::DarkElfMale: + case RaceAppearance::DarkElfFemale: + case RaceAppearance::HalfElfMale: + case RaceAppearance::HalfElfFemale: + case RaceAppearance::DwarfMale: + case RaceAppearance::DwarfFemale: + case RaceAppearance::TrollFemale: + case RaceAppearance::OgreFemale: + case RaceAppearance::HalflingMale: + case RaceAppearance::HalflingFemale: + case RaceAppearance::GnomeMale: + case RaceAppearance::GnomeFemale: + if (hair_value <= 3) { + return true; + } + + break; + case RaceAppearance::EruditeMale: + if (hair_value <= 5) { + return true; + } + + break; + case RaceAppearance::DrakkinFemale: + if (hair_value <= 7) { + return true; + } + + break; + case RaceAppearance::EruditeFemale: + case RaceAppearance::DrakkinMale: + if (hair_value <= 8) { + return true; + } + + break; + default: + break; + } + + return false; + } else { + switch (GetRaceGenderMask(race_id, gender_id)) { + case RaceAppearance::DrakkinFemale: + if (hair_value <= 7) { + return true; + } + + break; + case RaceAppearance::DrakkinMale: + if (hair_value <= 8) { + return true; + } + + break; + default: + break; + } + + return false; } - return false; } -bool PlayerAppearance::IsValidTexture(uint16 race_id, uint8 gender_id, uint8 texture_value, bool use_luclin) +bool RaceAppearance::IsValidHairColor(uint16 race_id, uint8 gender_id, uint8 hair_color_value, bool use_luclin) { - if (texture_value == 0xFF) + if (hair_color_value == std::numeric_limits::max()) { return true; + } - if (use_luclin) { - switch (BINDRG(race_id, gender_id)) { - case HUMAN_MALE: - case HUMAN_FEMALE: - case IKSAR_MALE: - case IKSAR_FEMALE: - case DRAKKIN_MALE: - case DRAKKIN_FEMALE: - if ((texture_value >= 10 && texture_value <= 16) || texture_value <= 4) + switch (GetRaceGenderMask(race_id, gender_id)) { + case RaceAppearance::GnomeMale: + case RaceAppearance::GnomeFemale: + if (hair_color_value <= 24) { return true; + } + break; - case ERUDITE_MALE: - case ERUDITE_FEMALE: - case HIGH_ELF_MALE: - case HIGH_ELF_FEMALE: - case DARK_ELF_MALE: - case DARK_ELF_FEMALE: - case GNOME_MALE: - case GNOME_FEMALE: - case FROGLOK_MALE: - case FROGLOK_FEMALE: - if ((texture_value >= 10 && texture_value <= 16) || texture_value <= 3) + case RaceAppearance::TrollFemale: + case RaceAppearance::OgreFemale: + if (hair_color_value <= 23) { return true; + } + break; - case BARBARIAN_MALE: - case BARBARIAN_FEMALE: - case WOOD_ELF_MALE: - case WOOD_ELF_FEMALE: - case HALF_ELF_MALE: - case HALF_ELF_FEMALE: - case DWARF_MALE: - case DWARF_FEMALE: - case TROLL_MALE: - case TROLL_FEMALE: - case OGRE_MALE: - case OGRE_FEMALE: - case HALFLING_MALE: - case HALFLING_FEMALE: - case VAHSHIR_MALE: - case VAHSHIR_FEMALE: - if (texture_value <= 3) + case RaceAppearance::HumanMale: + case RaceAppearance::HumanFemale: + case RaceAppearance::BarbarianMale: + case RaceAppearance::BarbarianFemale: + case RaceAppearance::WoodElfMale: + case RaceAppearance::WoodElfFemale: + case RaceAppearance::HalfElfMale: + case RaceAppearance::HalfElfFemale: + case RaceAppearance::DwarfMale: + case RaceAppearance::DwarfFemale: + case RaceAppearance::HalflingMale: + case RaceAppearance::HalflingFemale: + if (hair_color_value <= 19) { return true; + } + break; - default: - break; - } - return false; - } - else { - switch (BINDRG(race_id, gender_id)) { - case HUMAN_MALE: - case HUMAN_FEMALE: - case ERUDITE_MALE: - case ERUDITE_FEMALE: - case DRAKKIN_MALE: - case DRAKKIN_FEMALE: - if ((texture_value >= 10 && texture_value <= 16) || texture_value <= 4) + case RaceAppearance::DarkElfMale: + case RaceAppearance::DarkElfFemale: + if (EQ::ValueWithin(hair_color_value, 13, 18)) { return true; + } + break; - case HIGH_ELF_MALE: - case HIGH_ELF_FEMALE: - case DARK_ELF_MALE: - case DARK_ELF_FEMALE: - case GNOME_MALE: - case GNOME_FEMALE: - case FROGLOK_MALE: - case FROGLOK_FEMALE: - if ((texture_value >= 10 && texture_value <= 16) || texture_value <= 3) + case RaceAppearance::HighElfMale: + case RaceAppearance::HighElfFemale: + if (hair_color_value <= 14) { return true; + } + break; - case VAHSHIR_MALE: - case VAHSHIR_FEMALE: - if (texture_value == 50 || texture_value <= 3) + case RaceAppearance::FroglokMale: + case RaceAppearance::FroglokFemale: + case RaceAppearance::DrakkinMale: + case RaceAppearance::DrakkinFemale: + if (hair_color_value <= 3) { return true; + } + break; - case IKSAR_MALE: - case IKSAR_FEMALE: - if (texture_value == 10 || texture_value <= 4) - return true; + default: break; - case BARBARIAN_MALE: - case BARBARIAN_FEMALE: - case WOOD_ELF_MALE: - case WOOD_ELF_FEMALE: - case HALF_ELF_MALE: - case HALF_ELF_FEMALE: - case DWARF_MALE: - case DWARF_FEMALE: - case TROLL_MALE: - case TROLL_FEMALE: - case OGRE_MALE: - case OGRE_FEMALE: - case HALFLING_MALE: - case HALFLING_FEMALE: - if (texture_value <= 3) + } + + return false; +} + +bool RaceAppearance::IsValidHeritage(uint16 race_id, uint8 gender_id, uint32 heritage_value, bool use_luclin) +{ + if (heritage_value == std::numeric_limits::max()) { + return true; + } + + switch (GetRaceGenderMask(race_id, gender_id)) { + case RaceAppearance::DrakkinMale: + case RaceAppearance::DrakkinFemale: + if (heritage_value <= 7) { return true; + } + break; default: break; - } - return false; } + + return false; } -bool PlayerAppearance::IsValidWoad(uint16 race_id, uint8 gender_id, uint8 woad_value, bool use_luclin) +bool RaceAppearance::IsValidTattoo(uint16 race_id, uint8 gender_id, uint32 tattoo_value, bool use_luclin) { - if (woad_value == 0xFF) + if (tattoo_value == std::numeric_limits::max()) { return true; + } - if (use_luclin) { - switch (BINDRG(race_id, gender_id)) { - case BARBARIAN_MALE: - case BARBARIAN_FEMALE: - if (woad_value <= 8) + switch (GetRaceGenderMask(race_id, gender_id)) { + case RaceAppearance::DrakkinMale: + case RaceAppearance::DrakkinFemale: + if (tattoo_value <= 7) { return true; + } + break; default: break; + } + + return false; +} + +bool RaceAppearance::IsValidWoad(uint16 race_id, uint8 gender_id, uint8 woad_value, bool use_luclin) +{ + if (woad_value == std::numeric_limits::max()) { + return true; + } + + if (use_luclin) { + switch (GetRaceGenderMask(race_id, gender_id)) { + case RaceAppearance::BarbarianMale: + case RaceAppearance::BarbarianFemale: + if (woad_value <= 8) { + return true; + } + + break; + default: + break; } } + return false; } diff --git a/common/races.h b/common/races.h index b3f6988c5f..3d9d9f8d34 100644 --- a/common/races.h +++ b/common/races.h @@ -21,103 +21,7 @@ #include "../common/types.h" #include -namespace Gender { - constexpr uint8 Male = 0; - constexpr uint8 Female = 1; - constexpr uint8 Neuter = 2; -} - -//theres a big list straight from the client below. - -#define HUMAN 1 -#define BARBARIAN 2 -#define ERUDITE 3 -#define WOOD_ELF 4 -#define HIGH_ELF 5 -#define DARK_ELF 6 -#define HALF_ELF 7 -#define DWARF 8 -#define TROLL 9 -#define OGRE 10 -#define HALFLING 11 -#define GNOME 12 -#define WEREWOLF 14 -#define WOLF 42 -#define BEAR 43 -#define SKELETON 60 -#define TIGER 63 -#define ELEMENTAL 75 -#define ALLIGATOR 91 -#define OGGOK_CITIZEN 93 -#define EYE_OF_ZOMM 108 -#define WOLF_ELEMENTAL 120 -#define INVISIBLE_MAN 127 -#define IKSAR 128 -#define VAHSHIR 130 -#define CONTROLLED_BOAT 141 -#define MINOR_ILL_OBJ 142 -#define TREE 143 -#define IKSAR_SKELETON 161 -#define FROGLOK 330 -// TODO: check all clients for (BYTE) usage of '/who all' class and remove FROGLOK2, if possible (330 - 74 = 256 .. WORD->BYTE conversion loss...) -#define FROGLOK2 74 // Not sure why /who all reports race as 74 for frogloks -#define FAIRY 473 -#define DRAKKIN 522 // 32768 -#define EMU_RACE_NPC 131069 // was 65533 -#define EMU_RACE_PET 131070 // was 65534 -#define EMU_RACE_UNKNOWN 131071 // was 65535 - - -// player race values -#define PLAYER_RACE_UNKNOWN 0 -#define PLAYER_RACE_HUMAN 1 -#define PLAYER_RACE_BARBARIAN 2 -#define PLAYER_RACE_ERUDITE 3 -#define PLAYER_RACE_WOOD_ELF 4 -#define PLAYER_RACE_HIGH_ELF 5 -#define PLAYER_RACE_DARK_ELF 6 -#define PLAYER_RACE_HALF_ELF 7 -#define PLAYER_RACE_DWARF 8 -#define PLAYER_RACE_TROLL 9 -#define PLAYER_RACE_OGRE 10 -#define PLAYER_RACE_HALFLING 11 -#define PLAYER_RACE_GNOME 12 -#define PLAYER_RACE_IKSAR 13 -#define PLAYER_RACE_VAHSHIR 14 -#define PLAYER_RACE_FROGLOK 15 -#define PLAYER_RACE_DRAKKIN 16 - -#define PLAYER_RACE_COUNT 16 - - -#define PLAYER_RACE_EMU_NPC 17 -#define PLAYER_RACE_EMU_PET 18 -#define PLAYER_RACE_EMU_COUNT 19 - - -// player race bits -#define PLAYER_RACE_UNKNOWN_BIT 0 -#define PLAYER_RACE_HUMAN_BIT 1 -#define PLAYER_RACE_BARBARIAN_BIT 2 -#define PLAYER_RACE_ERUDITE_BIT 4 -#define PLAYER_RACE_WOOD_ELF_BIT 8 -#define PLAYER_RACE_HIGH_ELF_BIT 16 -#define PLAYER_RACE_DARK_ELF_BIT 32 -#define PLAYER_RACE_HALF_ELF_BIT 64 -#define PLAYER_RACE_DWARF_BIT 128 -#define PLAYER_RACE_TROLL_BIT 256 -#define PLAYER_RACE_OGRE_BIT 512 -#define PLAYER_RACE_HALFLING_BIT 1024 -#define PLAYER_RACE_GNOME_BIT 2048 -#define PLAYER_RACE_IKSAR_BIT 4096 -#define PLAYER_RACE_VAHSHIR_BIT 8192 -#define PLAYER_RACE_FROGLOK_BIT 16384 -#define PLAYER_RACE_DRAKKIN_BIT 32768 - -#define PLAYER_RACE_ALL_MASK 65535 - const char* GetRaceIDName(uint16 race_id); -const char* GetPlayerRaceName(uint32 player_race_value); const char* GetGenderName(uint32 gender_id); bool IsPlayerRace(uint16 race_id); @@ -127,25 +31,13 @@ uint32 GetPlayerRaceValue(uint16 race_id); uint16 GetPlayerRaceBit(uint16 race_id); uint16 GetRaceIDFromPlayerRaceValue(uint32 player_race_value); -uint16 GetRaceIDFromPlayerRaceBit(uint32 player_race_bit); float GetRaceGenderDefaultHeight(int race, int gender); -// player race-/gender-based model feature validators -namespace PlayerAppearance -{ - bool IsValidBeard(uint16 race_id, uint8 gender_id, uint8 beard_value, bool use_luclin = true); - bool IsValidBeardColor(uint16 race_id, uint8 gender_id, uint8 beard_color_value, bool use_luclin = true); - bool IsValidDetail(uint16 race_id, uint8 gender_id, uint32 detail_value, bool use_luclin = true); - bool IsValidEyeColor(uint16 race_id, uint8 gender_id, uint8 eye_color_value, bool use_luclin = true); - bool IsValidFace(uint16 race_id, uint8 gender_id, uint8 face_value, bool use_luclin = true); - bool IsValidHair(uint16 race_id, uint8 gender_id, uint8 hair_value, bool use_luclin = true); - bool IsValidHairColor(uint16 race_id, uint8 gender_id, uint8 hair_color_value, bool use_luclin = true); - bool IsValidHead(uint16 race_id, uint8 gender_id, uint8 head_value, bool use_luclin = true); - bool IsValidHeritage(uint16 race_id, uint8 gender_id, uint32 heritage_value, bool use_luclin = true); - bool IsValidTattoo(uint16 race_id, uint8 gender_id, uint32 tattoo_value, bool use_luclin = true); - bool IsValidTexture(uint16 race_id, uint8 gender_id, uint8 texture_value, bool use_luclin = true); - bool IsValidWoad(uint16 race_id, uint8 gender_id, uint8 woad_value, bool use_luclin = true); +namespace Gender { + constexpr uint8 Male = 0; + constexpr uint8 Female = 1; + constexpr uint8 Neuter = 2; } namespace Race { @@ -884,8 +776,92 @@ namespace Race { constexpr uint16 Pegasus3 = 732; constexpr uint16 InteractiveObject = 2250; constexpr uint16 Node = 2254; +} + +namespace RaceBitmask { + constexpr uint16 Unknown = 0; + constexpr uint16 Human = 1; + constexpr uint16 Barbarian = 2; + constexpr uint16 Erudite = 4; + constexpr uint16 WoodElf = 8; + constexpr uint16 HighElf = 16; + constexpr uint16 DarkElf = 32; + constexpr uint16 HalfElf = 64; + constexpr uint16 Dwarf = 128; + constexpr uint16 Troll = 256; + constexpr uint16 Ogre = 512; + constexpr uint16 Halfling = 1024; + constexpr uint16 Gnome = 2048; + constexpr uint16 Iksar = 4096; + constexpr uint16 VahShir = 8192; + constexpr uint16 Froglok = 16384; + constexpr uint16 Drakkin = 32768; + constexpr uint16 All = 65535; +} + +namespace RaceIndex { + constexpr uint16 Human = 1; + constexpr uint16 Barbarian = 2; + constexpr uint16 Erudite = 3; + constexpr uint16 WoodElf = 4; + constexpr uint16 HighElf = 5; + constexpr uint16 DarkElf = 6; + constexpr uint16 HalfElf = 7; + constexpr uint16 Dwarf = 8; + constexpr uint16 Troll = 9; + constexpr uint16 Ogre = 10; + constexpr uint16 Halfling = 11; + constexpr uint16 Gnome = 12; + constexpr uint16 Iksar = 13; + constexpr uint16 VahShir = 14; + constexpr uint16 Froglok = 15; + constexpr uint16 Drakkin = 16; +} + +namespace RaceAppearance { + bool IsValidBeard(uint16 race_id, uint8 gender_id, uint8 beard_value, bool use_luclin = true); + bool IsValidBeardColor(uint16 race_id, uint8 gender_id, uint8 beard_color_value, bool use_luclin = true); + bool IsValidDetail(uint16 race_id, uint8 gender_id, uint32 detail_value, bool use_luclin = true); + bool IsValidEyeColor(uint16 race_id, uint8 gender_id, uint8 eye_color_value, bool use_luclin = true); + bool IsValidFace(uint16 race_id, uint8 gender_id, uint8 face_value, bool use_luclin = true); + bool IsValidHair(uint16 race_id, uint8 gender_id, uint8 hair_value, bool use_luclin = true); + bool IsValidHairColor(uint16 race_id, uint8 gender_id, uint8 hair_color_value, bool use_luclin = true); + bool IsValidHeritage(uint16 race_id, uint8 gender_id, uint32 heritage_value, bool use_luclin = true); + bool IsValidTattoo(uint16 race_id, uint8 gender_id, uint32 tattoo_value, bool use_luclin = true); + bool IsValidWoad(uint16 race_id, uint8 gender_id, uint8 woad_value, bool use_luclin = true); - constexpr uint16 ALL_RACES_BITMASK = 65535; + constexpr int HumanMale = (Race::Human << 8) | Gender::Male; + constexpr int HumanFemale = (Race::Human << 8) | Gender::Female; + constexpr int BarbarianMale = (Race::Barbarian << 8) | Gender::Male; + constexpr int BarbarianFemale = (Race::Barbarian << 8) | Gender::Female; + constexpr int EruditeMale = (Race::Erudite << 8) | Gender::Male; + constexpr int EruditeFemale = (Race::Erudite << 8) | Gender::Female; + constexpr int WoodElfMale = (Race::WoodElf << 8) | Gender::Male; + constexpr int WoodElfFemale = (Race::WoodElf << 8) | Gender::Female; + constexpr int HighElfMale = (Race::HighElf << 8) | Gender::Male; + constexpr int HighElfFemale = (Race::HighElf << 8) | Gender::Female; + constexpr int DarkElfMale = (Race::DarkElf << 8) | Gender::Male; + constexpr int DarkElfFemale = (Race::DarkElf << 8) | Gender::Female; + constexpr int HalfElfMale = (Race::HalfElf << 8) | Gender::Male; + constexpr int HalfElfFemale = (Race::HalfElf << 8) | Gender::Female; + constexpr int DwarfMale = (Race::Dwarf << 8) | Gender::Male; + constexpr int DwarfFemale = (Race::Dwarf << 8) | Gender::Female; + constexpr int TrollMale = (Race::Troll << 8) | Gender::Male; + constexpr int TrollFemale = (Race::Troll << 8) | Gender::Female; + constexpr int OgreMale = (Race::Ogre << 8) | Gender::Male; + constexpr int OgreFemale = (Race::Ogre << 8) | Gender::Female; + constexpr int HalflingMale = (Race::Halfling << 8) | Gender::Male; + constexpr int HalflingFemale = (Race::Halfling << 8) | Gender::Female; + constexpr int GnomeMale = (Race::Gnome << 8) | Gender::Male; + constexpr int GnomeFemale = (Race::Gnome << 8) | Gender::Female; + constexpr int IksarMale = (Race::Iksar << 8) | Gender::Male; + constexpr int IksarFemale = (Race::Iksar << 8) | Gender::Female; + constexpr int VahShirMale = (Race::VahShir << 8) | Gender::Male; + constexpr int VahShirFemale = (Race::VahShir << 8) | Gender::Female; + constexpr int FroglokMale = (Race::Froglok2 << 8) | Gender::Male; + constexpr int FroglokFemale = (Race::Froglok2 << 8) | Gender::Female; + constexpr int DrakkinMale = (Race::Drakkin << 8) | Gender::Male; + constexpr int DrakkinFemale = (Race::Drakkin << 8) | Gender::Female; } #endif diff --git a/world/client.cpp b/world/client.cpp index a6ffd75717..52244e5316 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -2076,10 +2076,10 @@ bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc) classtemp = cc->class_ - 1; racetemp = cc->race - 1; // these have non sequential race numbers so they need to be mapped - if (cc->race == FROGLOK) racetemp = 14; - if (cc->race == VAHSHIR) racetemp = 13; - if (cc->race == IKSAR) racetemp = 12; - if (cc->race == DRAKKIN) racetemp = 15; + if (cc->race == Race::Froglok2) racetemp = 14; + if (cc->race == Race::VahShir) racetemp = 13; + if (cc->race == Race::Iksar) racetemp = 12; + if (cc->race == Race::Drakkin) racetemp = 15; // if out of range looking it up in the table would crash stuff // so we return from these @@ -2186,43 +2186,43 @@ void Client::SetRaceStartingSkills( PlayerProfile_Struct *pp ) { switch( pp->race ) { - case BARBARIAN: - case DWARF: - case ERUDITE: - case HALF_ELF: - case HIGH_ELF: - case HUMAN: - case OGRE: - case TROLL: - case DRAKKIN: //Drakkin are supposed to get a starting AA Skill + case Race::Barbarian: + case Race::Dwarf: + case Race::Erudite: + case Race::HalfElf: + case Race::HighElf: + case Race::Human: + case Race::Ogre: + case Race::Troll: + case Race::Drakkin: //Drakkin are supposed to get a starting AA Skill { // No Race Specific Skills break; } - case DARK_ELF: + case Race::DarkElf: { pp->skills[EQ::skills::SkillHide] = 50; break; } - case FROGLOK: + case Race::Froglok2: { if (RuleI(Skills, SwimmingStartValue) < 125) { pp->skills[EQ::skills::SkillSwimming] = 125; } break; } - case GNOME: + case Race::Gnome: { pp->skills[EQ::skills::SkillTinkering] = 50; break; } - case HALFLING: + case Race::Halfling: { pp->skills[EQ::skills::SkillHide] = 50; pp->skills[EQ::skills::SkillSneak] = 50; break; } - case IKSAR: + case Race::Iksar: { pp->skills[EQ::skills::SkillForage] = 50; if (RuleI(Skills, SwimmingStartValue) < 100) { @@ -2230,13 +2230,13 @@ void Client::SetRaceStartingSkills( PlayerProfile_Struct *pp ) } break; } - case WOOD_ELF: + case Race::WoodElf: { pp->skills[EQ::skills::SkillForage] = 50; pp->skills[EQ::skills::SkillHide] = 50; break; } - case VAHSHIR: + case Race::VahShir: { pp->skills[EQ::skills::SkillSafeFall] = 50; pp->skills[EQ::skills::SkillSneak] = 50; diff --git a/world/clientlist.cpp b/world/clientlist.cpp index 1671ca2adf..d8f1d9fbc5 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -643,7 +643,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S whomlen = strlen(whom->whom); if (whom->wrace == 0x001A) { // 0x001A is the old Froglok race number and is sent by the client for /who all froglok - whom->wrace = FROGLOK; // This is what EQEmu uses for the Froglok Race number. + whom->wrace = Race::Froglok2; // This is what EQEmu uses for the Froglok Race number. } } diff --git a/zone/aa.cpp b/zone/aa.cpp index 6005f4282a..9e25cf8604 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1619,7 +1619,7 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) auto race = GetPlayerRaceValue(GetBaseRace()); - race = race > PLAYER_RACE_COUNT ? Race::Human : race; + race = race > RaceIndex::Drakkin ? Race::Human : race; if (!(a->races & (1 << (race - 1)))) { return false; diff --git a/zone/attack.cpp b/zone/attack.cpp index 5a26a9b8f0..aee861749c 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -896,7 +896,7 @@ int Mob::GetClassRaceACBonus() ac_bonus = 16; } - if (GetRace() == IKSAR) + if (GetRace() == Race::Iksar) ac_bonus += EQ::Clamp(static_cast(level), 10, 35); return ac_bonus; @@ -3545,7 +3545,7 @@ int Mob::GetHandToHandDelay(void) int iksar = 0; if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652 && GetLevel() > 46) epic = 280; - else if (GetRace() == IKSAR) + else if (GetRace() == Race::Iksar) iksar = 1; // the delay bonus from the monk epic scales up to a skill of 280 if (epic >= skill) @@ -3586,8 +3586,8 @@ int Mob::GetHandToHandDelay(void) return 16; int level = GetLevel(); if (level > 62) - return GetRace() == IKSAR ? 21 : 20; - return GetRace() == IKSAR ? mnk_iks_delay[level] : mnk_hum_delay[level]; + return GetRace() == Race::Iksar ? 21 : 20; + return GetRace() == Race::Iksar ? mnk_iks_delay[level] : mnk_hum_delay[level]; } else if (GetClass() == Class::Beastlord) { int level = GetLevel(); diff --git a/zone/bot.cpp b/zone/bot.cpp index 2716c88c64..bd008955df 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -317,7 +317,7 @@ Bot::Bot( ); } else if (spell.base_value[x1] == -2) // WTF IS THIS { - if (GetRace() == IKSAR || GetRace() == VAHSHIR || GetRace() <= GNOME) { + if (GetRace() == Race::Iksar || GetRace() == Race::VahShir || GetRace() <= Race::Gnome) { SendIllusionPacket( AppearanceStruct{ .gender_id = GetGender(), @@ -346,27 +346,27 @@ Bot::Bot( } switch (spell.base_value[x1]) { - case OGRE: + case Race::Ogre: SendAppearancePacket(AppearanceType::Size, 9); break; - case TROLL: + case Race::Troll: SendAppearancePacket(AppearanceType::Size, 8); break; - case VAHSHIR: - case BARBARIAN: + case Race::VahShir: + case Race::Barbarian: SendAppearancePacket(AppearanceType::Size, 7); break; - case HALF_ELF: - case WOOD_ELF: - case DARK_ELF: - case FROGLOK: + case Race::HalfElf: + case Race::WoodElf: + case Race::DarkElf: + case Race::Froglok2: SendAppearancePacket(AppearanceType::Size, 5); break; - case DWARF: + case Race::Dwarf: SendAppearancePacket(AppearanceType::Size, 4); break; - case HALFLING: - case GNOME: + case Race::Halfling: + case Race::Gnome: SendAppearancePacket(AppearanceType::Size, 3); break; default: @@ -457,10 +457,10 @@ Bot::Bot( int resurrection_sickness_spell_id = ( RuleB(Bots, OldRaceRezEffects) && ( - GetRace() == BARBARIAN || - GetRace() == DWARF || - GetRace() == TROLL || - GetRace() == OGRE + GetRace() == Race::Barbarian || + GetRace() == Race::Dwarf || + GetRace() == Race::Troll || + GetRace() == Race::Ogre ) ? RuleI(Bots, OldResurrectionSicknessSpell) : RuleI(Bots, ResurrectionSicknessSpell) @@ -955,9 +955,9 @@ void Bot::GenerateBaseStats() float BotSize = GetSize(); switch(GetRace()) { - case HUMAN: // Humans have no race bonus + case Race::Human: // Humans have no race bonus break; - case BARBARIAN: + case Race::Barbarian: Strength += 28; Stamina += 20; Agility += 7; @@ -968,7 +968,7 @@ void Bot::GenerateBaseStats() BotSize = 7.0; ColdResist += 10; break; - case ERUDITE: + case Race::Erudite: Strength -= 15; Stamina -= 5; Agility -= 5; @@ -979,7 +979,7 @@ void Bot::GenerateBaseStats() MagicResist += 5; DiseaseResist -= 5; break; - case WOOD_ELF: + case Race::WoodElf: Strength -= 10; Stamina -= 10; Agility += 20; @@ -987,7 +987,7 @@ void Bot::GenerateBaseStats() Wisdom += 5; BotSize = 5.0; break; - case HIGH_ELF: + case Race::HighElf: Strength -= 20; Stamina -= 10; Agility += 10; @@ -996,7 +996,7 @@ void Bot::GenerateBaseStats() Intelligence += 12; Charisma += 5; break; - case DARK_ELF: + case Race::DarkElf: Strength -= 15; Stamina -= 10; Agility += 15; @@ -1005,7 +1005,7 @@ void Bot::GenerateBaseStats() Charisma -= 15; BotSize = 5.0; break; - case HALF_ELF: + case Race::HalfElf: Strength -= 5; Stamina -= 5; Agility += 15; @@ -1013,7 +1013,7 @@ void Bot::GenerateBaseStats() Wisdom -= 15; BotSize = 5.5; break; - case DWARF: + case Race::Dwarf: Strength += 15; Stamina += 15; Agility -= 5; @@ -1025,7 +1025,7 @@ void Bot::GenerateBaseStats() MagicResist -= 5; PoisonResist += 5; break; - case TROLL: + case Race::Troll: Strength += 33; Stamina += 34; Agility += 8; @@ -1035,7 +1035,7 @@ void Bot::GenerateBaseStats() BotSize = 8.0; FireResist -= 20; break; - case OGRE: + case Race::Ogre: Strength += 55; Stamina += 77; Agility -= 5; @@ -1045,7 +1045,7 @@ void Bot::GenerateBaseStats() Charisma -= 38; BotSize = 9.0; break; - case HALFLING: + case Race::Halfling: Strength -= 5; Agility += 20; Dexterity += 15; @@ -1056,7 +1056,7 @@ void Bot::GenerateBaseStats() PoisonResist += 5; DiseaseResist += 5; break; - case GNOME: + case Race::Gnome: Strength -= 15; Stamina -= 5; Agility += 10; @@ -1066,7 +1066,7 @@ void Bot::GenerateBaseStats() Charisma -= 15; BotSize = 3.0; break; - case IKSAR: + case Race::Iksar: Strength -= 5; Stamina -= 5; Agility += 15; @@ -1076,7 +1076,7 @@ void Bot::GenerateBaseStats() MagicResist -= 5; FireResist -= 5; break; - case VAHSHIR: + case Race::VahShir: Strength += 15; Agility += 15; Dexterity -= 5; @@ -1087,7 +1087,7 @@ void Bot::GenerateBaseStats() MagicResist -= 5; FireResist -= 5; break; - case FROGLOK: + case Race::Froglok2: Strength -= 5; Stamina += 5; Agility += 25; @@ -1097,7 +1097,7 @@ void Bot::GenerateBaseStats() MagicResist -= 5; FireResist -= 5; break; - case DRAKKIN: + case Race::Drakkin: Strength -= 5; Stamina += 5; Agility += 10; @@ -1140,7 +1140,7 @@ void Bot::GenerateBaseStats() void Bot::GenerateAppearance() { // Randomize facial appearance int iFace = 0; - if (GetRace() == BARBARIAN) // Barbarian w/Tatoo + if (GetRace() == Race::Barbarian) // Barbarian w/Tatoo { iFace = zone->random.Int(0, 79); } @@ -1152,13 +1152,13 @@ void Bot::GenerateAppearance() { int iHair = 0; int iBeard = 0; int iBeardColor = 1; - if (GetRace() == DRAKKIN) { + if (GetRace() == Race::Drakkin) { iHair = zone->random.Int(0, 8); iBeard = zone->random.Int(0, 11); iBeardColor = zone->random.Int(0, 3); } else if (GetGender()) { iHair = zone->random.Int(0, 2); - if (GetRace() == DWARF && zone->random.Int(1, 100) < 50) { + if (GetRace() == Race::Dwarf && zone->random.Int(1, 100) < 50) { iFace += 10; } } else { @@ -1168,7 +1168,7 @@ void Bot::GenerateAppearance() { } int iHairColor = 0; - if (GetRace() == DRAKKIN) { + if (GetRace() == Race::Drakkin) { iHairColor = zone->random.Int(0, 3); } else { iHairColor = zone->random.Int(0, 19); @@ -1176,7 +1176,7 @@ void Bot::GenerateAppearance() { auto iEyeColor1 = (uint8)zone->random.Int(0, 9); uint8 iEyeColor2 = 0; - if (GetRace() == DRAKKIN) { + if (GetRace() == Race::Drakkin) { iEyeColor1 = iEyeColor2 = (uint8)zone->random.Int(0, 11); } else if (zone->random.Int(1, 100) > 96) { iEyeColor2 = zone->random.Int(0, 9); @@ -1187,7 +1187,7 @@ void Bot::GenerateAppearance() { int iHeritage = 0; int iTattoo = 0; int iDetails = 0; - if (GetRace() == DRAKKIN) { + if (GetRace() == Race::Drakkin) { iHeritage = zone->random.Int(0, 6); iTattoo = zone->random.Int(0, 7); iDetails = zone->random.Int(0, 7); @@ -5404,9 +5404,9 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { case Class::Paladin: { bool is_large_race = ( - GetBaseRace() == OGRE || - GetBaseRace() == TROLL || - GetBaseRace() == BARBARIAN + GetBaseRace() == Race::Ogre || + GetBaseRace() == Race::Troll || + GetBaseRace() == Race::Barbarian ); bool has_bash_skill = GetSkill(EQ::skills::SkillBash) > 0; bool has_shield_in_secondary = diff --git a/zone/bot_commands/appearance.cpp b/zone/bot_commands/appearance.cpp index 5758846c9e..6707baea21 100644 --- a/zone/bot_commands/appearance.cpp +++ b/zone/bot_commands/appearance.cpp @@ -46,9 +46,9 @@ void bot_command_beard_color(Client *c, const Seperator *sep) uint8 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = AFT_None; - if (my_bot->GetGender() != Gender::Male && my_bot->GetRace() != DWARF) + if (my_bot->GetGender() != Gender::Male && my_bot->GetRace() != Race::Dwarf) fail_type = AFT_GenderRace; - else if (!PlayerAppearance::IsValidBeardColor(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + else if (!RaceAppearance::IsValidBeardColor(my_bot->GetRace(), my_bot->GetGender(), uvalue)) fail_type = AFT_Value; else my_bot->SetBeardColor(uvalue); @@ -83,9 +83,9 @@ void bot_command_beard_style(Client *c, const Seperator *sep) uint8 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = AFT_None; - if (my_bot->GetGender() != Gender::Male && my_bot->GetRace() != DWARF) + if (my_bot->GetGender() != Gender::Male && my_bot->GetRace() != Race::Dwarf) fail_type = AFT_GenderRace; - else if (!PlayerAppearance::IsValidBeard(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + else if (!RaceAppearance::IsValidBeard(my_bot->GetRace(), my_bot->GetGender(), uvalue)) fail_type = AFT_Value; else my_bot->SetBeard(uvalue); @@ -122,9 +122,9 @@ void bot_command_details(Client *c, const Seperator *sep) uint32 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = AFT_None; - if (my_bot->GetRace() != DRAKKIN) + if (my_bot->GetRace() != Race::Drakkin) fail_type = AFT_Race; - else if (!PlayerAppearance::IsValidDetail(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + else if (!RaceAppearance::IsValidDetail(my_bot->GetRace(), my_bot->GetGender(), uvalue)) fail_type = AFT_Value; else my_bot->SetDrakkinDetails(uvalue); @@ -281,7 +281,7 @@ void bot_command_eyes(Client *c, const Seperator *sep) // eye_bias = 2; auto fail_type = AFT_None; - if (!PlayerAppearance::IsValidEyeColor(my_bot->GetRace(), my_bot->GetGender(), uvalue)) { + if (!RaceAppearance::IsValidEyeColor(my_bot->GetRace(), my_bot->GetGender(), uvalue)) { fail_type = AFT_Value; } else { @@ -328,12 +328,12 @@ void bot_command_face(Client *c, const Seperator *sep) uint8 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = AFT_None; - if (!PlayerAppearance::IsValidFace(my_bot->GetRace(), my_bot->GetGender(), uvalue)) { + if (!RaceAppearance::IsValidFace(my_bot->GetRace(), my_bot->GetGender(), uvalue)) { fail_type = AFT_Value; } else { uint8 old_woad = 0; - if (my_bot->GetRace() == BARBARIAN) + if (my_bot->GetRace() == Race::Barbarian) old_woad = ((my_bot->GetLuclinFace() / 10) * 10); my_bot->SetLuclinFace((old_woad + uvalue)); } @@ -368,7 +368,7 @@ void bot_command_hair_color(Client *c, const Seperator *sep) uint8 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = AFT_None; - if (!PlayerAppearance::IsValidHairColor(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + if (!RaceAppearance::IsValidHairColor(my_bot->GetRace(), my_bot->GetGender(), uvalue)) fail_type = AFT_Value; else my_bot->SetHairColor(uvalue); @@ -403,7 +403,7 @@ void bot_command_hairstyle(Client *c, const Seperator *sep) uint8 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = AFT_None; - if (!PlayerAppearance::IsValidHair(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + if (!RaceAppearance::IsValidHair(my_bot->GetRace(), my_bot->GetGender(), uvalue)) fail_type = AFT_Value; else my_bot->SetHairStyle(uvalue); @@ -440,9 +440,9 @@ void bot_command_heritage(Client *c, const Seperator *sep) uint32 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = AFT_None; - if (my_bot->GetRace() != DRAKKIN) + if (my_bot->GetRace() != Race::Drakkin) fail_type = AFT_Race; - else if (!PlayerAppearance::IsValidHeritage(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + else if (!RaceAppearance::IsValidHeritage(my_bot->GetRace(), my_bot->GetGender(), uvalue)) fail_type = AFT_Value; else my_bot->SetDrakkinHeritage(uvalue); @@ -479,9 +479,9 @@ void bot_command_tattoo(Client *c, const Seperator *sep) uint32 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = AFT_None; - if (my_bot->GetRace() != DRAKKIN) + if (my_bot->GetRace() != Race::Drakkin) fail_type = AFT_Race; - else if (!PlayerAppearance::IsValidTattoo(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + else if (!RaceAppearance::IsValidTattoo(my_bot->GetRace(), my_bot->GetGender(), uvalue)) fail_type = AFT_Value; else my_bot->SetDrakkinTattoo(uvalue); @@ -516,10 +516,10 @@ void bot_command_woad(Client *c, const Seperator *sep) uint8 uvalue = Strings::ToInt(sep->arg[1]); auto fail_type = AFT_None; - if (my_bot->GetRace() != BARBARIAN) { + if (my_bot->GetRace() != Race::Barbarian) { fail_type = AFT_Race; } - else if (!PlayerAppearance::IsValidWoad(my_bot->GetRace(), my_bot->GetGender(), uvalue)) { + else if (!RaceAppearance::IsValidWoad(my_bot->GetRace(), my_bot->GetGender(), uvalue)) { fail_type = AFT_Value; } else { diff --git a/zone/bot_commands/bot.cpp b/zone/bot_commands/bot.cpp index 647e8d75b9..2d37c503a4 100644 --- a/zone/bot_commands/bot.cpp +++ b/zone/bot_commands/bot.cpp @@ -455,13 +455,13 @@ void bot_command_follow_distance(Client *c, const Seperator *sep) fmt::format("- You must use a value between 1 and {}.", RuleI(Bots, MaxFollowDistance)) }; p.example_format = { fmt::format("{} [reset]/[set [value]] [actionable]", sep->arg[0]) }; - p.examples_one = { - "To set all bots to follow at a distance of 25:", - fmt::format("{} set 25 spawned", sep->arg[0]) + p.examples_one = { + "To set all bots to follow at a distance of 25:", + fmt::format("{} set 25 spawned", sep->arg[0]) }; - p.examples_two = { - "To check the curret following distance of all bots:", - fmt::format("{} current spawned", sep->arg[0]) + p.examples_two = { + "To check the curret following distance of all bots:", + fmt::format("{} current spawned", sep->arg[0]) }; p.examples_three = { @@ -470,10 +470,10 @@ void bot_command_follow_distance(Client *c, const Seperator *sep) "{} reset byclass {}", sep->arg[0], Class::Wizard - ) + ) }; p.actionables = { "target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned" }; - + std::string popup_text = c->SendBotCommandHelpWindow(p); popup_text = DialogueWindow::Table(popup_text); @@ -483,7 +483,7 @@ void bot_command_follow_distance(Client *c, const Seperator *sep) } const int ab_mask = ActionableBots::ABM_Type2; - + uint32 bfd = RuleI(Bots, DefaultFollowDistance); bool set_flag = false; bool current_check = false; @@ -862,7 +862,7 @@ void bot_command_report(Client *c, const Seperator *sep) c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationmembers | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]); return; } - + const int ab_mask = ActionableBots::ABM_Type1; std::string arg1 = sep->arg[1]; @@ -1057,7 +1057,7 @@ void bot_command_stance(Client *c, const Seperator *sep) BotCommandHelpParams p; p.description = { "Change a bot's stance to control the way it behaves." }; - p.notes = + p.notes = { "- Changing a stance will reset all settings to match that stance type.", "- Any changes made will only save to that stance for future use.", @@ -1122,29 +1122,29 @@ void bot_command_stance(Client *c, const Seperator *sep) Stance::AEBurn ) }; - p.example_format = + p.example_format = { fmt::format( "{} [current | value]", sep->arg[0]) }; - p.examples_one = - { - "To set all bots to BurnAE:", + p.examples_one = + { + "To set all bots to BurnAE:", fmt::format("{} {} spawned {}", sep->arg[0], Stance::Aggressive, Class::ShadowKnight ) }; - p.examples_two = - { - "To set all Shadowknights to Aggressive:", + p.examples_two = + { + "To set all Shadowknights to Aggressive:", fmt::format("{} {} byclass {}", sep->arg[0], Stance::Aggressive, Class::ShadowKnight ) }; - p.examples_three = { - "To check the current stances of all bots:", - fmt::format("{} current spawned", sep->arg[0]) + p.examples_three = { + "To check the current stances of all bots:", + fmt::format("{} current spawned", sep->arg[0]) }; p.actionables = { "target, byname, ownergroup, ownerraid, targetgroup, namesgroup, healrotationtargets, mmr, byclass, byrace, spawned" }; @@ -1239,7 +1239,7 @@ void bot_command_stance(Client *c, const Seperator *sep) database.botdb.LoadBotSettings(bot_iter); if ( - (bot_iter->GetClass() == Class::Warrior || bot_iter->GetClass() == Class::Paladin || bot_iter->GetClass() == Class::ShadowKnight) && + (bot_iter->GetClass() == Class::Warrior || bot_iter->GetClass() == Class::Paladin || bot_iter->GetClass() == Class::ShadowKnight) && (bot_iter->GetBotStance() == Stance::Aggressive) ) { bot_iter->SetTaunting(true); @@ -1255,7 +1255,7 @@ void bot_command_stance(Client *c, const Seperator *sep) bot_iter->GetPet()->CastToNPC()->SetTaunting(false); } } - + bot_iter->Save(); ++success_count; } @@ -1431,7 +1431,7 @@ void bot_command_summon(Client *c, const Seperator *sep) c->Message(Chat::White, "usage: %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | healrotationtargets | mmr | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]); return; } - + const int ab_mask = ActionableBots::ABM_Type1; std::string arg1 = sep->arg[1]; @@ -1550,7 +1550,7 @@ void bot_command_toggle_ranged(Client *c, const Seperator *sep) return; } - + std::string arg1 = sep->arg[1]; int ab_arg = 1; @@ -1712,7 +1712,7 @@ void bot_command_toggle_helm(Client *c, const Seperator *sep) return; } - + std::string arg1 = sep->arg[1]; int ab_arg = 1; diff --git a/zone/client.cpp b/zone/client.cpp index 2fa767d094..50c42f69bf 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8445,7 +8445,7 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction) merchant->SayString(zone->random.Int(WONT_SELL_DEEDS1, WONT_SELL_DEEDS6)); } else if (lowestvalue == fmod.race_mod) { // race biggest // Non-standard race (ex. illusioned to wolf) - if (GetRace() > PLAYER_RACE_COUNT) { + if (!IsPlayerRace(GetRace())) { messageid = zone->random.Int(1, 3); // these aren't sequential StringIDs :( switch (messageid) { case 1: diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 23ef134541..85149ef065 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1011,52 +1011,52 @@ int32 Client::CalcMR() { //racial bases switch (GetBaseRace()) { - case HUMAN: + case Race::Human: MR = 25; break; - case BARBARIAN: + case Race::Barbarian: MR = 25; break; - case ERUDITE: + case Race::Erudite: MR = 30; break; - case WOOD_ELF: + case Race::WoodElf: MR = 25; break; - case HIGH_ELF: + case Race::HighElf: MR = 25; break; - case DARK_ELF: + case Race::DarkElf: MR = 25; break; - case HALF_ELF: + case Race::HalfElf: MR = 25; break; - case DWARF: + case Race::Dwarf: MR = 30; break; - case TROLL: + case Race::Troll: MR = 25; break; - case OGRE: + case Race::Ogre: MR = 25; break; - case HALFLING: + case Race::Halfling: MR = 25; break; - case GNOME: + case Race::Gnome: MR = 25; break; - case IKSAR: + case Race::Iksar: MR = 25; break; - case VAHSHIR: + case Race::VahShir: MR = 25; break; - case FROGLOK: + case Race::Froglok2: MR = 30; break; - case DRAKKIN: + case Race::Drakkin: { MR = 25; if (GetDrakkinHeritage() == 2) @@ -1085,52 +1085,52 @@ int32 Client::CalcFR() { //racial bases switch (GetBaseRace()) { - case HUMAN: + case Race::Human: FR = 25; break; - case BARBARIAN: + case Race::Barbarian: FR = 25; break; - case ERUDITE: + case Race::Erudite: FR = 25; break; - case WOOD_ELF: + case Race::WoodElf: FR = 25; break; - case HIGH_ELF: + case Race::HighElf: FR = 25; break; - case DARK_ELF: + case Race::DarkElf: FR = 25; break; - case HALF_ELF: + case Race::HalfElf: FR = 25; break; - case DWARF: + case Race::Dwarf: FR = 25; break; - case TROLL: + case Race::Troll: FR = 5; break; - case OGRE: + case Race::Ogre: FR = 25; break; - case HALFLING: + case Race::Halfling: FR = 25; break; - case GNOME: + case Race::Gnome: FR = 25; break; - case IKSAR: + case Race::Iksar: FR = 30; break; - case VAHSHIR: + case Race::VahShir: FR = 25; break; - case FROGLOK: + case Race::Froglok2: FR = 25; break; - case DRAKKIN: + case Race::Drakkin: { FR = 25; if (GetDrakkinHeritage() == 0) @@ -1171,52 +1171,52 @@ int32 Client::CalcDR() { //racial bases switch (GetBaseRace()) { - case HUMAN: + case Race::Human: DR = 15; break; - case BARBARIAN: + case Race::Barbarian: DR = 15; break; - case ERUDITE: + case Race::Erudite: DR = 10; break; - case WOOD_ELF: + case Race::WoodElf: DR = 15; break; - case HIGH_ELF: + case Race::HighElf: DR = 15; break; - case DARK_ELF: + case Race::DarkElf: DR = 15; break; - case HALF_ELF: + case Race::HalfElf: DR = 15; break; - case DWARF: + case Race::Dwarf: DR = 15; break; - case TROLL: + case Race::Troll: DR = 15; break; - case OGRE: + case Race::Ogre: DR = 15; break; - case HALFLING: + case Race::Halfling: DR = 20; break; - case GNOME: + case Race::Gnome: DR = 15; break; - case IKSAR: + case Race::Iksar: DR = 15; break; - case VAHSHIR: + case Race::VahShir: DR = 15; break; - case FROGLOK: + case Race::Froglok2: DR = 15; break; - case DRAKKIN: + case Race::Drakkin: { DR = 15; if (GetDrakkinHeritage() == 1) @@ -1263,52 +1263,52 @@ int32 Client::CalcPR() { //racial bases switch (GetBaseRace()) { - case HUMAN: + case Race::Human: PR = 15; break; - case BARBARIAN: + case Race::Barbarian: PR = 15; break; - case ERUDITE: + case Race::Erudite: PR = 15; break; - case WOOD_ELF: + case Race::WoodElf: PR = 15; break; - case HIGH_ELF: + case Race::HighElf: PR = 15; break; - case DARK_ELF: + case Race::DarkElf: PR = 15; break; - case HALF_ELF: + case Race::HalfElf: PR = 15; break; - case DWARF: + case Race::Dwarf: PR = 20; break; - case TROLL: + case Race::Troll: PR = 15; break; - case OGRE: + case Race::Ogre: PR = 15; break; - case HALFLING: + case Race::Halfling: PR = 20; break; - case GNOME: + case Race::Gnome: PR = 15; break; - case IKSAR: + case Race::Iksar: PR = 15; break; - case VAHSHIR: + case Race::VahShir: PR = 15; break; - case FROGLOK: + case Race::Froglok2: PR = 30; break; - case DRAKKIN: + case Race::Drakkin: { PR = 15; if (GetDrakkinHeritage() == 3) @@ -1355,52 +1355,52 @@ int32 Client::CalcCR() { //racial bases switch (GetBaseRace()) { - case HUMAN: + case Race::Human: CR = 25; break; - case BARBARIAN: + case Race::Barbarian: CR = 35; break; - case ERUDITE: + case Race::Erudite: CR = 25; break; - case WOOD_ELF: + case Race::WoodElf: CR = 25; break; - case HIGH_ELF: + case Race::HighElf: CR = 25; break; - case DARK_ELF: + case Race::DarkElf: CR = 25; break; - case HALF_ELF: + case Race::HalfElf: CR = 25; break; - case DWARF: + case Race::Dwarf: CR = 25; break; - case TROLL: + case Race::Troll: CR = 25; break; - case OGRE: + case Race::Ogre: CR = 25; break; - case HALFLING: + case Race::Halfling: CR = 25; break; - case GNOME: + case Race::Gnome: CR = 25; break; - case IKSAR: + case Race::Iksar: CR = 15; break; - case VAHSHIR: + case Race::VahShir: CR = 25; break; - case FROGLOK: + case Race::Froglok2: CR = 25; break; - case DRAKKIN: + case Race::Drakkin: { CR = 25; if (GetDrakkinHeritage() == 4) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 143a44d4e2..2100cbb19f 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1515,23 +1515,23 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) switch (race) { - case OGRE: + case Race::Ogre: size = 9; break; - case TROLL: + case Race::Troll: size = 8; break; - case VAHSHIR: case BARBARIAN: + case Race::VahShir: case Race::Barbarian: size = 7; break; - case HUMAN: case HIGH_ELF: case ERUDITE: case IKSAR: case DRAKKIN: + case Race::Human: case Race::HighElf: case Race::Erudite: case Race::Iksar: case Race::Drakkin: size = 6; break; - case HALF_ELF: + case Race::HalfElf: size = 5.5; break; - case WOOD_ELF: case DARK_ELF: case FROGLOK: + case Race::WoodElf: case Race::DarkElf: case Race::Froglok2: size = 5; break; - case DWARF: + case Race::Dwarf: size = 4; break; - case HALFLING: + case Race::Halfling: size = 3.5; break; - case GNOME: + case Race::Gnome: size = 3; break; default: size = 0; diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 99f6a48f59..71144db89f 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1648,7 +1648,7 @@ void Client::OPGMTraining(const EQApplicationPacket *app) //#pragma GCC push_options //#pragma GCC optimize ("O0") for (int sk = EQ::skills::Skill1HBlunt; sk <= EQ::skills::HIGHEST_SKILL; ++sk) { - if (sk == EQ::skills::SkillTinkering && GetRace() != GNOME) { + if (sk == EQ::skills::SkillTinkering && GetRace() != Race::Gnome) { gmtrain->skills[sk] = 0; //Non gnomes can't tinker! } else { gmtrain->skills[sk] = GetMaxSkillAfterSpecializationRules((EQ::skills::SkillType)sk, MaxSkill((EQ::skills::SkillType)sk, GetClass(), RuleI(Character, MaxLevel))); diff --git a/zone/entity.cpp b/zone/entity.cpp index 80623674e0..37fa9b4adb 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1389,7 +1389,7 @@ void EntityList::SendZoneSpawnsBulk(Client *client) bool is_delayed_packet = ( DistanceSquared(client_position, spawn_position) > distance_max || - (spawn->IsClient() && (spawn->GetRace() == MINOR_ILL_OBJ || spawn->GetRace() == TREE)) + (spawn->IsClient() && (spawn->GetRace() == Race::MinorIllusion || spawn->GetRace() == Race::Tree)) ); if (is_delayed_packet) { @@ -1413,7 +1413,7 @@ void EntityList::SendZoneSpawnsBulk(Client *client) * * Illusion races on PCs don't work as a mass spawn * But they will work as an add_spawn AFTER CLIENT_CONNECTED. - * if (spawn->IsClient() && (race == MINOR_ILL_OBJ || race == TREE)) { + * if (spawn->IsClient() && (race == Race::MinorIllusion || race == Race::Tree)) { * app = new EQApplicationPacket; * spawn->CreateSpawnPacket(app); * client->QueuePacket(app, true, Client::CLIENT_CONNECTED); diff --git a/zone/exp.cpp b/zone/exp.cpp index a924f24d49..e3016f8b25 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -130,7 +130,7 @@ uint64 Client::CalcEXP(uint8 consider_level, bool ignore_modifiers) { if ( GetClass() == Class::Warrior || GetClass() == Class::Rogue || - GetBaseRace() == HALFLING + GetBaseRace() == Race::Halfling ) { total_modifier *= 1.05; } @@ -291,7 +291,7 @@ void Client::CalculateStandardAAExp(uint64 &add_aaxp, uint8 conlevel, bool resex // Shouldn't race not affect AA XP? if (RuleB(Character, UseRaceClassExpBonuses)) { - if (GetBaseRace() == HALFLING) { + if (GetBaseRace() == Race::Halfling) { aatotalmod *= 1.05; } @@ -439,7 +439,7 @@ void Client::CalculateExp(uint64 in_add_exp, uint64 &add_exp, uint64 &add_aaxp, if (RuleB(Character, UseRaceClassExpBonuses)) { - if (GetBaseRace() == HALFLING) { + if (GetBaseRace() == Race::Halfling) { totalmod *= 1.05; } @@ -1057,13 +1057,13 @@ uint32 Client::GetEXPForLevel(uint16 check_level) if(RuleB(Character,UseOldRaceExpPenalties)) { float racemod = 1.0; - if(GetBaseRace() == TROLL || GetBaseRace() == IKSAR) { + if(GetBaseRace() == Race::Troll || GetBaseRace() == Race::Iksar) { racemod = 1.2; - } else if(GetBaseRace() == OGRE) { + } else if(GetBaseRace() == Race::Ogre) { racemod = 1.15; - } else if(GetBaseRace() == BARBARIAN) { + } else if(GetBaseRace() == Race::Barbarian) { racemod = 1.05; - } else if(GetBaseRace() == HALFLING) { + } else if(GetBaseRace() == Race::Halfling) { racemod = 0.95; } diff --git a/zone/gm_commands/feature.cpp b/zone/gm_commands/feature.cpp index 41999fe2c6..f43f279fa2 100644 --- a/zone/gm_commands/feature.cpp +++ b/zone/gm_commands/feature.cpp @@ -83,7 +83,7 @@ void command_feature(Client *c, const Seperator *sep) feature_changed = "Beard Color"; value_changed = f.beardcolor; } else if (is_details) { - if (t->GetRace() != DRAKKIN) { + if (t->GetRace() != Race::Drakkin) { c->Message(Chat::White, "You must target a Drakkin to use this command."); return; } @@ -116,7 +116,7 @@ void command_feature(Client *c, const Seperator *sep) feature_changed = "Helmet Texture"; value_changed = helm_texture; } else if (is_heritage) { - if (t->GetRace() != DRAKKIN) { + if (t->GetRace() != Race::Drakkin) { c->Message(Chat::White, "You must target a Drakkin to use this command."); return; } @@ -148,7 +148,7 @@ void command_feature(Client *c, const Seperator *sep) feature_changed = "Size"; value_changed = size; } else if (is_tattoo) { - if (t->GetRace() != DRAKKIN) { + if (t->GetRace() != Race::Drakkin) { c->Message(Chat::White, "You must target a Drakkin to use this command."); return; } diff --git a/zone/gm_commands/randomfeatures.cpp b/zone/gm_commands/randomfeatures.cpp index 64a8bcda3f..4a771ba13c 100755 --- a/zone/gm_commands/randomfeatures.cpp +++ b/zone/gm_commands/randomfeatures.cpp @@ -8,7 +8,7 @@ void command_randomfeatures(Client *c, const Seperator *sep) } auto target = c->GetTarget(); - + if (target->RandomizeFeatures()) { c->Message( Chat::White, diff --git a/zone/mob.cpp b/zone/mob.cpp index 0a167201d5..7968cdacaa 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3819,7 +3819,7 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) // Adjust all settings based on the min and max for each feature of each race and gender switch (GetRace()) { - case HUMAN: + case Race::Human: new_hair_color = zone->random.Int(0, 19); if (current_gender == Gender::Male) { @@ -3831,7 +3831,7 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) } break; - case BARBARIAN: + case Race::Barbarian: new_hair_color = zone->random.Int(0, 19); new_luclin_face = zone->random.Int(0, 87); @@ -3844,7 +3844,7 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) } break; - case ERUDITE: + case Race::Erudite: if (current_gender == Gender::Male) { new_beard_color = zone->random.Int(0, 19); new_beard = zone->random.Int(0, 5); @@ -3854,7 +3854,7 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) } break; - case WOOD_ELF: + case Race::WoodElf: new_hair_color = zone->random.Int(0, 19); if (current_gender == Gender::Male) { @@ -3864,7 +3864,7 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) } break; - case HIGH_ELF: + case Race::HighElf: new_hair_color = zone->random.Int(0, 14); if (current_gender == Gender::Male) { @@ -3876,7 +3876,7 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) } break; - case DARK_ELF: + case Race::DarkElf: new_hair_color = zone->random.Int(13, 18); if (current_gender == Gender::Male) { @@ -3888,7 +3888,7 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) } break; - case HALF_ELF: + case Race::HalfElf: new_hair_color = zone->random.Int(0, 19); if (current_gender == Gender::Male) { @@ -3900,7 +3900,7 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) } break; - case DWARF: + case Race::Dwarf: new_hair_color = zone->random.Int(0, 19); new_beard_color = new_hair_color; @@ -3913,7 +3913,7 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) } break; - case TROLL: + case Race::Troll: new_eye_color_one = zone->random.Int(0, 10); new_eye_color_two = zone->random.Int(0, 10); @@ -3923,14 +3923,14 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) } break; - case OGRE: + case Race::Ogre: if (current_gender == Gender::Female) { new_hair_style = zone->random.Int(0, 3); new_hair_color = zone->random.Int(0, 23); } break; - case HALFLING: + case Race::Halfling: new_hair_color = zone->random.Int(0, 19); if (current_gender == Gender::Male) { @@ -3942,7 +3942,7 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) } break; - case GNOME: + case Race::Gnome: new_hair_color = zone->random.Int(0, 24); if (current_gender == Gender::Male) { @@ -3954,14 +3954,14 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) } break; - case IKSAR: - case VAHSHIR: + case Race::Iksar: + case Race::VahShir: new_luclin_face = zone->random.Int(0, 7); break; - case FROGLOK: + case Race::Froglok2: new_luclin_face = zone->random.Int(0, 9); break; - case DRAKKIN: + case Race::Drakkin: new_hair_color = zone->random.Int(0, 3); new_beard_color = new_hair_color; new_eye_color_one = zone->random.Int(0, 11); @@ -4023,8 +4023,8 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) uint16 Mob::GetFactionRace() { uint16 current_race = GetRace(); - if (IsPlayerRace(current_race) || current_race == TREE || - current_race == MINOR_ILL_OBJ) { + if (IsPlayerRace(current_race) || current_race == Race::Tree || + current_race == Race::MinorIllusion) { return current_race; } else { @@ -7704,7 +7704,7 @@ bool Mob::CanRaceEquipItem(uint32 item_id) } auto item_races = itm->Races; - if(item_races == PLAYER_RACE_ALL_MASK) { + if(item_races == RaceBitmask::All) { return true; } diff --git a/zone/npc.cpp b/zone/npc.cpp index de97d0fb5e..8f12645b78 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -2901,7 +2901,7 @@ void NPC::DoNPCEmote(uint8 event_, uint32 emote_id, Mob* t) // Mob Variables Strings::FindReplace(processed, "$mname", GetCleanName()); Strings::FindReplace(processed, "$mracep", GetRacePlural()); - Strings::FindReplace(processed, "$mrace", GetPlayerRaceName(GetRace())); + Strings::FindReplace(processed, "$mrace", GetRaceIDName(GetRace())); Strings::FindReplace(processed, "$mclass", GetClassIDName(GetClass())); Strings::FindReplace(processed, "$mclassp", GetClassPlural()); @@ -2909,7 +2909,7 @@ void NPC::DoNPCEmote(uint8 event_, uint32 emote_id, Mob* t) Strings::FindReplace(processed, "$name", t ? t->GetCleanName() : "foe"); Strings::FindReplace(processed, "$class", t ? GetClassIDName(t->GetClass()) : "class"); Strings::FindReplace(processed, "$classp", t ? t->GetClassPlural() : "classes"); - Strings::FindReplace(processed, "$race", t ? GetPlayerRaceName(t->GetRace()) : "race"); + Strings::FindReplace(processed, "$race", t ? GetRaceIDName(t->GetRace()) : "race"); Strings::FindReplace(processed, "$racep", t ? t->GetRacePlural() : "races"); if (emoteid == e->emoteid) { @@ -3792,7 +3792,7 @@ bool NPC::IsGuard() case Race::HalasCitizen: case Race::NeriakCitizen: case Race::GrobbCitizen: - case OGGOK_CITIZEN: + case Race::OggokCitizen: case Race::KaladimCitizen: return true; default: diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index b1101e9c6b..57feb3f2e1 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -352,9 +352,9 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) if (ca_atk->m_skill == EQ::skills::SkillBash) { // SLAM - Bash without a shield equipped switch (GetRace()) { - case OGRE: - case TROLL: - case BARBARIAN: + case Race::Ogre: + case Race::Troll: + case Race::Barbarian: bypass_skill_check = true; default: break; diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 6e16783949..d307ca418a 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -466,7 +466,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob } } else if (spec.tradeskill == EQ::skills::SkillTinkering) { - if (user_pp.race != GNOME) { + if (user_pp.race != Race::Gnome) { user->Message(Chat::Red, "Only gnomes can tinker."); auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); @@ -643,7 +643,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac } } else if (spec.tradeskill == EQ::skills::SkillTinkering) { - if (user->GetRace() != GNOME) { + if (user->GetRace() != Race::Gnome) { user->Message(Chat::Red, "Only gnomes can tinker."); auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index f0fe6a8703..7643e0e278 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -4276,7 +4276,7 @@ bool WorldServer::SendVoiceMacro(Client* From, uint32 Type, char* Target, uint32 uint16 player_race = GetPlayerRaceValue(From->GetRace()); - if (player_race == PLAYER_RACE_UNKNOWN) { + if (player_race == Race::Doug) { player_race = From->GetBaseRace(); } From 060f6e377dbae0ccc8f595d2d897060de9ecdb23 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 30 Aug 2025 15:33:19 -0400 Subject: [PATCH 033/194] [Constants] Convert SE Defines to SpellEffect Namespace (#4999) --- common/item_data.h | 2 +- common/ruletypes.h | 2 +- common/spdat.cpp | 830 ++++++++++----------- common/spdat.h | 1061 ++++++++++++++------------- zone/aa.cpp | 20 +- zone/aggro.cpp | 134 ++-- zone/attack.cpp | 54 +- zone/bonuses.cpp | 1430 ++++++++++++++++++------------------ zone/bot.cpp | 180 ++--- zone/bot_commands/pet.cpp | 8 +- zone/botspellsai.cpp | 116 +-- zone/client.cpp | 18 +- zone/client_mods.cpp | 20 +- zone/client_packet.cpp | 36 +- zone/common.h | 88 +-- zone/effects.cpp | 12 +- zone/fearpath.cpp | 2 +- zone/merc.cpp | 66 +- zone/mob.cpp | 44 +- zone/mob_ai.cpp | 4 +- zone/pets.cpp | 16 +- zone/spell_effects.cpp | 1458 ++++++++++++++++++------------------- zone/spells.cpp | 106 +-- zone/tune.cpp | 18 +- zone/worldserver.cpp | 2 +- zone/zonedb.cpp | 4 +- 26 files changed, 2865 insertions(+), 2866 deletions(-) diff --git a/common/item_data.h b/common/item_data.h index e4cad0e7a3..6967c218c1 100644 --- a/common/item_data.h +++ b/common/item_data.h @@ -438,7 +438,7 @@ namespace EQ //uint32 Unk054 {}; int16 MaxCharges {}; // Maximum charges items can hold: -1 if not a chargeable item uint8 ItemType {}; // Item Type/Skill (itemClass* from above) - int32 SubType {}; // Some items have sub types that can be used for other things (unbreakable fishing poles, SE_FFItemClass) + int32 SubType {}; // Some items have sub types that can be used for other things (unbreakable fishing poles, SpellEffect::FFItemClass) uint8 Material {}; // Item material type uint32 HerosForgeModel {};// Hero's Forge Armor Model Type (2-13?) float SellRate {}; // Sell rate diff --git a/common/ruletypes.h b/common/ruletypes.h index 730b971fc8..1e08a9cbdf 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -619,7 +619,7 @@ RULE_INT(Combat, SneakPullAssistRange, 400, "Modified range of assist for sneak RULE_BOOL(Combat, Classic2HBAnimation, false, "2HB will use the 2 hand piercing animation instead of the overhead slashing animation") RULE_BOOL(Combat, ArcheryConsumesAmmo, true, "Set to false to disable Archery Ammo Consumption") RULE_BOOL(Combat, ThrowingConsumesAmmo, true, "Set to false to disable Throwing Ammo Consumption") -RULE_BOOL(Combat, UseLiveRiposteMechanics, false, "Set to true to disable SPA 173 SE_RiposteChance from making those with the effect on them immune to enrage, can longer riposte from a riposte.") +RULE_BOOL(Combat, UseLiveRiposteMechanics, false, "Set to true to disable SPA 173 SpellEffect::RiposteChance from making those with the effect on them immune to enrage, can longer riposte from a riposte.") RULE_INT(Combat, FrontalStunImmunityClasses, 0, "Bitmask for Classes than have frontal stun immunity, No Races (0) by default.") RULE_BOOL(Combat, NPCsUseFrontalStunImmunityClasses, false, "Enable or disable NPCs using frontal stun immunity Classes from Combat:FrontalStunImmunityClasses, false by default.") RULE_INT(Combat, FrontalStunImmunityRaces, 512, "Bitmask for Races than have frontal stun immunity, Ogre (512) only by default.") diff --git a/common/spdat.cpp b/common/spdat.cpp index 7631d2b98b..f4d3df2558 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -105,7 +105,7 @@ bool IsTargetableAESpell(uint16 spell_id) bool IsSacrificeSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_Sacrifice); + return IsEffectInSpell(spell_id, SpellEffect::Sacrifice); } bool IsLifetapSpell(uint16 spell_id) @@ -129,7 +129,7 @@ bool IsLifetapSpell(uint16 spell_id) bool IsMesmerizeSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_Mez); + return IsEffectInSpell(spell_id, SpellEffect::Mez); } bool SpellBreaksMez(uint16 spell_id) @@ -139,7 +139,7 @@ bool SpellBreaksMez(uint16 spell_id) bool IsStunSpell(uint16 spell_id) { - return (IsValidSpell(spell_id) && IsEffectInSpell(spell_id, SE_Stun) || IsEffectInSpell(spell_id, SE_SpinTarget)); + return (IsValidSpell(spell_id) && IsEffectInSpell(spell_id, SpellEffect::Stun) || IsEffectInSpell(spell_id, SpellEffect::SpinTarget)); } bool IsSummonSpell(uint16 spell_id) @@ -153,9 +153,9 @@ bool IsSummonSpell(uint16 spell_id) for (int i = 0; i < EFFECT_COUNT; i++) { const auto effect_id = spell.effect_id[i]; if ( - effect_id == SE_SummonPet || - effect_id == SE_SummonItem || - effect_id == SE_SummonPC + effect_id == SpellEffect::SummonPet || + effect_id == SpellEffect::SummonItem || + effect_id == SpellEffect::SummonPC ) { return true; } @@ -180,7 +180,7 @@ bool IsDamageSpell(uint16 spell_id) const auto effect_id = spell.effect_id[i]; if ( spell.base_value[i] < 0 && - (effect_id == SE_CurrentHPOnce || effect_id == SE_CurrentHP) + (effect_id == SpellEffect::CurrentHPOnce || effect_id == SpellEffect::CurrentHP) ) { return true; } @@ -207,9 +207,9 @@ bool IsAnyDamageSpell(uint16 spell_id) if ( spell.base_value[i] < 0 && ( - effect_id == SE_CurrentHPOnce || + effect_id == SpellEffect::CurrentHPOnce || ( - effect_id == SE_CurrentHP && + effect_id == SpellEffect::CurrentHP && spell.buff_duration < 1 ) ) @@ -241,7 +241,7 @@ bool IsDamageOverTimeSpell(uint16 spell_id) const auto effect_id = spell.effect_id[i]; if ( spell.base_value[i] < 0 && - effect_id == SE_CurrentHP && + effect_id == SpellEffect::CurrentHP && spell.buff_duration > 1 ) { return true; @@ -253,7 +253,7 @@ bool IsDamageOverTimeSpell(uint16 spell_id) bool IsFearSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_Fear); + return IsEffectInSpell(spell_id, SpellEffect::Fear); } bool IsCureSpell(uint16 spell_id) @@ -268,10 +268,10 @@ bool IsCureSpell(uint16 spell_id) for (int i = 0; i < EFFECT_COUNT; i++) { if ( - spell.effect_id[i] == SE_DiseaseCounter || - spell.effect_id[i] == SE_PoisonCounter || - spell.effect_id[i] == SE_CurseCounter || - spell.effect_id[i] == SE_CorruptionCounter + spell.effect_id[i] == SpellEffect::DiseaseCounter || + spell.effect_id[i] == SpellEffect::PoisonCounter || + spell.effect_id[i] == SpellEffect::CurseCounter || + spell.effect_id[i] == SpellEffect::CorruptionCounter ) { has_cure_effect = true; } @@ -298,9 +298,9 @@ bool IsSlowSpell(uint16 spell_id) for (int i = 0; i < EFFECT_COUNT; i++) { const auto effect_id = spell.effect_id[i]; if ( - effect_id == SE_AttackSpeed4 || + effect_id == SpellEffect::AttackSpeed4 || ( - effect_id == SE_AttackSpeed && + effect_id == SpellEffect::AttackSpeed && spell.base_value[i] < 100 ) ) { @@ -320,7 +320,7 @@ bool IsHasteSpell(uint16 spell_id) const auto& spell = spells[spell_id]; for (int i = 0; i < EFFECT_COUNT; i++) { - if (spell.effect_id[i] == SE_AttackSpeed) { + if (spell.effect_id[i] == SpellEffect::AttackSpeed) { return (spell.base_value[i] < 100); } } @@ -331,15 +331,15 @@ bool IsHasteSpell(uint16 spell_id) bool IsHarmonySpell(uint16 spell_id) { return ( - IsEffectInSpell(spell_id, SE_ChangeFrenzyRad) || - IsEffectInSpell(spell_id, SE_Harmony) || - IsEffectInSpell(spell_id, SE_Lull) + IsEffectInSpell(spell_id, SpellEffect::ChangeFrenzyRad) || + IsEffectInSpell(spell_id, SpellEffect::Harmony) || + IsEffectInSpell(spell_id, SpellEffect::Lull) ); } bool IsPercentalHealSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_PercentalHeal); + return IsEffectInSpell(spell_id, SpellEffect::PercentalHeal); } bool IsGroupOnlySpell(uint16 spell_id) @@ -359,13 +359,13 @@ bool IsBeneficialSpell(uint16 spell_id) // You'd think just checking goodEffect flag would be enough? if (spells[spell_id].good_effect == BENEFICIAL_EFFECT) { - // If the target type is ST_Self or ST_Pet and is a SE_CancleMagic spell + // If the target type is ST_Self or ST_Pet and is a SpellEffect::CancleMagic spell // it is not Beneficial const auto target_type = spells[spell_id].target_type; if ( target_type != ST_Self && target_type != ST_Pet && - IsEffectInSpell(spell_id, SE_CancelMagic) + IsEffectInSpell(spell_id, SpellEffect::CancelMagic) ) { return false; } @@ -387,7 +387,7 @@ bool IsBeneficialSpell(uint16 spell_id) // checking these SAI cause issues with the rng defensive proc line // So I guess instead of fixing it for real, just a quick hack :P if ( - spells[spell_id].effect_id[0] != SE_DefensiveProc && + spells[spell_id].effect_id[0] != SpellEffect::DefensiveProc && ( spell_affect_index == SAI_Calm || spell_affect_index == SAI_Dispell_Sight || @@ -403,16 +403,16 @@ bool IsBeneficialSpell(uint16 spell_id) if ( ( spell_affect_index == SAI_Calm && - IsEffectInSpell(spell_id, SE_Harmony) + IsEffectInSpell(spell_id, SpellEffect::Harmony) ) || ( spell_affect_index == SAI_Calm_Song && - IsEffectInSpell(spell_id, SE_BindSight) + IsEffectInSpell(spell_id, SpellEffect::BindSight) ) || ( spell_affect_index == SAI_Dispell_Sight && spells[spell_id].skill == EQ::skills::SkillDivination && - !IsEffectInSpell(spell_id, SE_VoiceGraft) + !IsEffectInSpell(spell_id, SpellEffect::VoiceGraft) ) ) { return false; @@ -436,52 +436,52 @@ bool IsDetrimentalSpell(uint16 spell_id) bool IsInvisibleSpell(uint16 spell_id) { return ( - IsEffectInSpell(spell_id, SE_Invisibility) || - IsEffectInSpell(spell_id, SE_Invisibility2) || - IsEffectInSpell(spell_id, SE_InvisVsUndead) || - IsEffectInSpell(spell_id, SE_InvisVsUndead2) || - IsEffectInSpell(spell_id, SE_InvisVsAnimals) || - IsEffectInSpell(spell_id, SE_ImprovedInvisAnimals) + IsEffectInSpell(spell_id, SpellEffect::Invisibility) || + IsEffectInSpell(spell_id, SpellEffect::Invisibility2) || + IsEffectInSpell(spell_id, SpellEffect::InvisVsUndead) || + IsEffectInSpell(spell_id, SpellEffect::InvisVsUndead2) || + IsEffectInSpell(spell_id, SpellEffect::InvisVsAnimals) || + IsEffectInSpell(spell_id, SpellEffect::ImprovedInvisAnimals) ); } bool IsInvulnerabilitySpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_DivineAura); + return IsEffectInSpell(spell_id, SpellEffect::DivineAura); } bool IsCompleteHealDurationSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_CompleteHeal); + return IsEffectInSpell(spell_id, SpellEffect::CompleteHeal); } bool IsPoisonCounterSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_PoisonCounter); + return IsEffectInSpell(spell_id, SpellEffect::PoisonCounter); } bool IsDiseaseCounterSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_DiseaseCounter); + return IsEffectInSpell(spell_id, SpellEffect::DiseaseCounter); } bool IsSummonItemSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_SummonItem); + return IsEffectInSpell(spell_id, SpellEffect::SummonItem); } bool IsSummonSkeletonSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_NecPet); + return IsEffectInSpell(spell_id, SpellEffect::NecPet); } bool IsSummonPetSpell(uint16 spell_id) { return ( - IsEffectInSpell(spell_id, SE_SummonPet) || - IsEffectInSpell(spell_id, SE_SummonBSTPet) || - IsEffectInSpell(spell_id, SE_Familiar) || - IsEffectInSpell(spell_id, SE_NecPet) + IsEffectInSpell(spell_id, SpellEffect::SummonPet) || + IsEffectInSpell(spell_id, SpellEffect::SummonBSTPet) || + IsEffectInSpell(spell_id, SpellEffect::Familiar) || + IsEffectInSpell(spell_id, SpellEffect::NecPet) ); } @@ -495,12 +495,12 @@ bool IsPetSpell(uint16 spell_id) bool IsSummonPCSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_SummonPC); + return IsEffectInSpell(spell_id, SpellEffect::SummonPC); } bool IsCharmSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_Charm); + return IsEffectInSpell(spell_id, SpellEffect::Charm); } bool IsResurrectionSicknessSpell(uint16 spell_id) { @@ -515,42 +515,42 @@ bool IsResurrectionSicknessSpell(uint16 spell_id) { bool IsBlindSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_Blind); + return IsEffectInSpell(spell_id, SpellEffect::Blind); } bool IsHealthSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_CurrentHP); + return IsEffectInSpell(spell_id, SpellEffect::CurrentHP); } bool IsCastTimeReductionSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_IncreaseSpellHaste); + return IsEffectInSpell(spell_id, SpellEffect::IncreaseSpellHaste); } bool IsIncreaseDurationSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_IncreaseSpellDuration); + return IsEffectInSpell(spell_id, SpellEffect::IncreaseSpellDuration); } bool IsManaCostReductionSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_ReduceManaCost); + return IsEffectInSpell(spell_id, SpellEffect::ReduceManaCost); } bool IsIncreaseRangeSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_IncreaseRange); + return IsEffectInSpell(spell_id, SpellEffect::IncreaseRange); } bool IsImprovedHealingSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_ImprovedHeal); + return IsEffectInSpell(spell_id, SpellEffect::ImprovedHeal); } bool IsImprovedDamageSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_ImprovedDamage); + return IsEffectInSpell(spell_id, SpellEffect::ImprovedDamage); } bool IsAEDurationSpell(uint16 spell_id) @@ -596,7 +596,7 @@ bool IsPureNukeSpell(uint16 spell_id) if ( effect_count == 1 && - IsEffectInSpell(spell_id, SE_CurrentHP) && + IsEffectInSpell(spell_id, SpellEffect::CurrentHP) && spells[spell_id].buff_duration == 0 && IsDamageSpell(spell_id) ) { @@ -799,8 +799,8 @@ bool IsPartialResistableSpell(uint16 spell_id) if ( spell.base_value[o] < 0 && ( - effect_id == SE_CurrentHPOnce || - effect_id == SE_CurrentHP + effect_id == SpellEffect::CurrentHPOnce || + effect_id == SpellEffect::CurrentHP ) ) { return true; @@ -846,7 +846,7 @@ bool IsTGBCompatibleSpell(uint16 spell_id) !IsDetrimentalSpell(spell_id) && spells[spell_id].buff_duration != 0 && !IsBardSong(spell_id) && - !IsEffectInSpell(spell_id, SE_Illusion) + !IsEffectInSpell(spell_id, SpellEffect::Illusion) ) { return true; } @@ -899,10 +899,10 @@ uint16 GetSpellTriggerSpellID(uint16 spell_id, int effect_id) for (int i = 0; i < EFFECT_COUNT; i++) { if ( - spell.effect_id[i] == SE_TriggerOnCast || - spell.effect_id[i] == SE_SpellTrigger || - spell.effect_id[i] == SE_ApplyEffect || - spell.effect_id[i] == SE_Trigger_Spell_Non_Item + spell.effect_id[i] == SpellEffect::TriggerOnCast || + spell.effect_id[i] == SpellEffect::SpellTrigger || + spell.effect_id[i] == SpellEffect::ApplyEffect || + spell.effect_id[i] == SpellEffect::Trigger_Spell_Non_Item ) { const auto trigger_spell_id = spell.limit_value[i]; if ( @@ -932,17 +932,17 @@ bool IsBlankSpellEffect(uint16 spell_id, int effect_index) const auto base_value = spell.base_value[effect_index]; const auto formula = spell.formula[effect_index]; - // SE_CHA is "spacer" - // SE_Stacking* are also considered blank where this is used + // SpellEffect::CHA is "spacer" + // SpellEffect::Stacking* are also considered blank where this is used if ( - effect == SE_Blank || + effect == SpellEffect::Blank || ( - effect == SE_CHA && + effect == SpellEffect::CHA && base_value == 0 && formula == 100 ) || - effect == SE_StackingCommand_Block || - effect == SE_StackingCommand_Overwrite + effect == SpellEffect::StackingCommand_Block || + effect == SpellEffect::StackingCommand_Overwrite ) { return true; } @@ -1041,7 +1041,7 @@ int CalculatePoisonCounters(uint16 spell_id) for (int i = 0; i < EFFECT_COUNT; i++) { if ( - spell.effect_id[i] == SE_PoisonCounter && + spell.effect_id[i] == SpellEffect::PoisonCounter && spell.base_value[i] > 0 ) { counters += spell.base_value[i]; @@ -1063,7 +1063,7 @@ int CalculateDiseaseCounters(uint16 spell_id) for (int i = 0; i < EFFECT_COUNT; i++) { if ( - spell.effect_id[i] == SE_DiseaseCounter && + spell.effect_id[i] == SpellEffect::DiseaseCounter && spell.base_value[i] > 0 ) { counters += spell.base_value[i]; @@ -1085,7 +1085,7 @@ int CalculateCurseCounters(uint16 spell_id) for (int i = 0; i < EFFECT_COUNT; i++) { if ( - spell.effect_id[i] == SE_CurseCounter && + spell.effect_id[i] == SpellEffect::CurseCounter && spell.base_value[i] > 0 ) { counters += spell.base_value[i]; @@ -1107,7 +1107,7 @@ int CalculateCorruptionCounters(uint16 spell_id) for (int i = 0; i < EFFECT_COUNT; i++) { if ( - spell.effect_id[i] == SE_CorruptionCounter && + spell.effect_id[i] == SpellEffect::CorruptionCounter && spell.base_value[i] > 0) { counters += spell.base_value[i]; @@ -1254,30 +1254,30 @@ int8 GetSpellResurrectionSicknessCheck(uint16 spell_id_one, uint16 spell_id_two) bool IsRuneSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_Rune); + return IsEffectInSpell(spell_id, SpellEffect::Rune); } bool IsMagicRuneSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_AbsorbMagicAtt); + return IsEffectInSpell(spell_id, SpellEffect::AbsorbMagicAtt); } bool IsManaTapSpell(uint16 spell_id) { return ( - IsEffectInSpell(spell_id, SE_CurrentMana) && + IsEffectInSpell(spell_id, SpellEffect::CurrentMana) && spells[spell_id].target_type == ST_Tap ); } bool IsAllianceSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_AddFaction); + return IsEffectInSpell(spell_id, SpellEffect::AddFaction); } bool IsDeathSaveSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_DeathSave); + return IsEffectInSpell(spell_id, SpellEffect::DeathSave); } // Deathsave spells with base of 1 are partial @@ -1291,7 +1291,7 @@ bool IsPartialDeathSaveSpell(uint16 spell_id) for (int i = 0; i < EFFECT_COUNT; i++) { if ( - spell.effect_id[i] == SE_DeathSave && + spell.effect_id[i] == SpellEffect::DeathSave && spell.base_value[i] == PARTIAL_DEATH_SAVE ) { return true; @@ -1312,7 +1312,7 @@ bool IsFullDeathSaveSpell(uint16 spell_id) for (int i = 0; i < EFFECT_COUNT; i++) { if ( - spell.effect_id[i] == SE_DeathSave && + spell.effect_id[i] == SpellEffect::DeathSave && spell.base_value[i] == FULL_DEATH_SAVE ) { return true; @@ -1324,33 +1324,33 @@ bool IsFullDeathSaveSpell(uint16 spell_id) bool IsShadowStepSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_ShadowStep); + return IsEffectInSpell(spell_id, SpellEffect::ShadowStep); } bool IsSuccorSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_Succor); + return IsEffectInSpell(spell_id, SpellEffect::Succor); } bool IsTeleportSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_Teleport); + return IsEffectInSpell(spell_id, SpellEffect::Teleport); } bool IsTranslocateSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_Translocate); + return IsEffectInSpell(spell_id, SpellEffect::Translocate); } bool IsGateSpell(uint16 spell_id) { - return IsEffectInSpell(spell_id, SE_Gate); + return IsEffectInSpell(spell_id, SpellEffect::Gate); } bool IsIllusionSpell(uint16 spell_id) { return ( - IsEffectInSpell(spell_id, SE_Illusion) && + IsEffectInSpell(spell_id, SpellEffect::Illusion) && spells[spell_id].target_type == ST_Self ); } @@ -1406,9 +1406,9 @@ DmgShieldType GetDamageShieldType(uint16 spell_id, int damage_shield_type) bool IsLDoNObjectSpell(uint16 spell_id) { return ( - IsEffectInSpell(spell_id, SE_AppraiseLDonChest) || - IsEffectInSpell(spell_id, SE_DisarmLDoNTrap) || - IsEffectInSpell(spell_id, SE_UnlockLDoNChest) + IsEffectInSpell(spell_id, SpellEffect::AppraiseLDonChest) || + IsEffectInSpell(spell_id, SpellEffect::DisarmLDoNTrap) || + IsEffectInSpell(spell_id, SpellEffect::UnlockLDoNChest) ); } @@ -1426,8 +1426,8 @@ bool IsHealOverTimeSpell(uint16 spell_id) { if ( ( - IsEffectInSpell(spell_id, SE_HealOverTime) || - GetSpellTriggerSpellID(spell_id, SE_HealOverTime) + IsEffectInSpell(spell_id, SpellEffect::HealOverTime) || + GetSpellTriggerSpellID(spell_id, SpellEffect::HealOverTime) ) && !IsGroupSpell(spell_id) ) { @@ -1442,9 +1442,9 @@ bool IsCompleteHealSpell(uint16 spell_id) if ( ( spell_id == SPELL_COMPLETE_HEAL || - IsEffectInSpell(spell_id, SE_CompleteHeal) || + IsEffectInSpell(spell_id, SpellEffect::CompleteHeal) || IsPercentalHealSpell(spell_id) || - GetSpellTriggerSpellID(spell_id, SE_CompleteHeal) + GetSpellTriggerSpellID(spell_id, SpellEffect::CompleteHeal) ) && !IsGroupSpell(spell_id) ) { @@ -1457,16 +1457,16 @@ bool IsCompleteHealSpell(uint16 spell_id) bool IsFastHealSpell(uint16 spell_id) { spell_id = ( - IsEffectInSpell(spell_id, SE_CurrentHP) ? + IsEffectInSpell(spell_id, SpellEffect::CurrentHP) ? spell_id : - GetSpellTriggerSpellID(spell_id, SE_CurrentHP) + GetSpellTriggerSpellID(spell_id, SpellEffect::CurrentHP) ); if (!spell_id) { spell_id = ( - IsEffectInSpell(spell_id, SE_CurrentHPOnce) ? + IsEffectInSpell(spell_id, SpellEffect::CurrentHPOnce) ? spell_id : - GetSpellTriggerSpellID(spell_id, SE_CurrentHPOnce) + GetSpellTriggerSpellID(spell_id, SpellEffect::CurrentHPOnce) ); } @@ -1481,8 +1481,8 @@ bool IsFastHealSpell(uint16 spell_id) { if ( spells[spell_id].base_value[i] > 0 && ( - spells[spell_id].effect_id[i] == SE_CurrentHP || - spells[spell_id].effect_id[i] == SE_CurrentHPOnce + spells[spell_id].effect_id[i] == SpellEffect::CurrentHP || + spells[spell_id].effect_id[i] == SpellEffect::CurrentHPOnce ) ) { return true; @@ -1497,16 +1497,16 @@ bool IsFastHealSpell(uint16 spell_id) { bool IsVeryFastHealSpell(uint16 spell_id) { spell_id = ( - IsEffectInSpell(spell_id, SE_CurrentHP) ? + IsEffectInSpell(spell_id, SpellEffect::CurrentHP) ? spell_id : - GetSpellTriggerSpellID(spell_id, SE_CurrentHP) + GetSpellTriggerSpellID(spell_id, SpellEffect::CurrentHP) ); if (!spell_id) { spell_id = ( - IsEffectInSpell(spell_id, SE_CurrentHPOnce) ? + IsEffectInSpell(spell_id, SpellEffect::CurrentHPOnce) ? spell_id : - GetSpellTriggerSpellID(spell_id, SE_CurrentHPOnce) + GetSpellTriggerSpellID(spell_id, SpellEffect::CurrentHPOnce) ); } @@ -1521,8 +1521,8 @@ bool IsVeryFastHealSpell(uint16 spell_id) if ( spells[spell_id].base_value[i] > 0 && ( - spells[spell_id].effect_id[i] == SE_CurrentHP || - spells[spell_id].effect_id[i] == SE_CurrentHPOnce + spells[spell_id].effect_id[i] == SpellEffect::CurrentHP || + spells[spell_id].effect_id[i] == SpellEffect::CurrentHPOnce ) ) { return true; @@ -1537,16 +1537,16 @@ bool IsVeryFastHealSpell(uint16 spell_id) bool IsRegularSingleTargetHealSpell(uint16 spell_id) { spell_id = ( - IsEffectInSpell(spell_id, SE_CurrentHP) ? + IsEffectInSpell(spell_id, SpellEffect::CurrentHP) ? spell_id : - GetSpellTriggerSpellID(spell_id, SE_CurrentHP) + GetSpellTriggerSpellID(spell_id, SpellEffect::CurrentHP) ); if (!spell_id) { spell_id = ( - IsEffectInSpell(spell_id, SE_CurrentHPOnce) ? + IsEffectInSpell(spell_id, SpellEffect::CurrentHPOnce) ? spell_id : - GetSpellTriggerSpellID(spell_id, SE_CurrentHPOnce) + GetSpellTriggerSpellID(spell_id, SpellEffect::CurrentHPOnce) ); } @@ -1567,8 +1567,8 @@ bool IsRegularSingleTargetHealSpell(uint16 spell_id) spells[spell_id].base_value[i] > 0 && spells[spell_id].buff_duration == 0 && ( - spells[spell_id].effect_id[i] == SE_CurrentHP || - spells[spell_id].effect_id[i] == SE_CurrentHPOnce + spells[spell_id].effect_id[i] == SpellEffect::CurrentHP || + spells[spell_id].effect_id[i] == SpellEffect::CurrentHPOnce ) ) { return true; @@ -1583,16 +1583,16 @@ bool IsRegularSingleTargetHealSpell(uint16 spell_id) bool IsRegularPetHealSpell(uint16 spell_id) { spell_id = ( - IsEffectInSpell(spell_id, SE_CurrentHP) ? + IsEffectInSpell(spell_id, SpellEffect::CurrentHP) ? spell_id : - GetSpellTriggerSpellID(spell_id, SE_CurrentHP) + GetSpellTriggerSpellID(spell_id, SpellEffect::CurrentHP) ); if (!spell_id) { spell_id = ( - IsEffectInSpell(spell_id, SE_CurrentHPOnce) ? + IsEffectInSpell(spell_id, SpellEffect::CurrentHPOnce) ? spell_id : - GetSpellTriggerSpellID(spell_id, SE_CurrentHPOnce) + GetSpellTriggerSpellID(spell_id, SpellEffect::CurrentHPOnce) ); } @@ -1613,8 +1613,8 @@ bool IsRegularPetHealSpell(uint16 spell_id) spells[spell_id].base_value[i] > 0 && spells[spell_id].buff_duration == 0 && ( - spells[spell_id].effect_id[i] == SE_CurrentHP || - spells[spell_id].effect_id[i] == SE_CurrentHPOnce + spells[spell_id].effect_id[i] == SpellEffect::CurrentHP || + spells[spell_id].effect_id[i] == SpellEffect::CurrentHPOnce ) ) { return true; @@ -1629,16 +1629,16 @@ bool IsRegularPetHealSpell(uint16 spell_id) bool IsRegularGroupHealSpell(uint16 spell_id) { spell_id = ( - IsEffectInSpell(spell_id, SE_CurrentHP) ? + IsEffectInSpell(spell_id, SpellEffect::CurrentHP) ? spell_id : - GetSpellTriggerSpellID(spell_id, SE_CurrentHP) + GetSpellTriggerSpellID(spell_id, SpellEffect::CurrentHP) ); if (!spell_id) { spell_id = ( - IsEffectInSpell(spell_id, SE_CurrentHPOnce) ? + IsEffectInSpell(spell_id, SpellEffect::CurrentHPOnce) ? spell_id : - GetSpellTriggerSpellID(spell_id, SE_CurrentHPOnce) + GetSpellTriggerSpellID(spell_id, SpellEffect::CurrentHPOnce) ); } @@ -1653,8 +1653,8 @@ bool IsRegularGroupHealSpell(uint16 spell_id) spells[spell_id].base_value[i] > 0 && spells[spell_id].buff_duration == 0 && ( - spells[spell_id].effect_id[i] == SE_CurrentHP || - spells[spell_id].effect_id[i] == SE_CurrentHPOnce + spells[spell_id].effect_id[i] == SpellEffect::CurrentHP || + spells[spell_id].effect_id[i] == SpellEffect::CurrentHPOnce ) ) { return true; @@ -1671,9 +1671,9 @@ bool IsGroupCompleteHealSpell(uint16 spell_id) { IsValidSpell(spell_id) && ( spell_id == SPELL_COMPLETE_HEAL || - IsEffectInSpell(spell_id, SE_CompleteHeal) || + IsEffectInSpell(spell_id, SpellEffect::CompleteHeal) || IsPercentalHealSpell(spell_id) || - GetSpellTriggerSpellID(spell_id, SE_CompleteHeal) + GetSpellTriggerSpellID(spell_id, SpellEffect::CompleteHeal) ) && IsGroupSpell(spell_id) ) { @@ -1687,8 +1687,8 @@ bool IsGroupHealOverTimeSpell(uint16 spell_id) { if ( IsValidSpell(spell_id) && ( - IsEffectInSpell(spell_id, SE_HealOverTime) || - GetSpellTriggerSpellID(spell_id, SE_HealOverTime) + IsEffectInSpell(spell_id, SpellEffect::HealOverTime) || + GetSpellTriggerSpellID(spell_id, SpellEffect::HealOverTime) ) && IsGroupSpell(spell_id) ) { @@ -1738,7 +1738,7 @@ bool IsAnyBuffSpell(uint16 spell_id) { IsBeneficialSpell(spell_id) && !IsBardSong(spell_id) && !IsEscapeSpell(spell_id) && - (!IsSummonPetSpell(spell_id) && !IsEffectInSpell(spell_id, SE_TemporaryPets)) + (!IsSummonPetSpell(spell_id) && !IsEffectInSpell(spell_id, SpellEffect::TemporaryPets)) ) { return true; } @@ -1751,9 +1751,9 @@ bool IsDispelSpell(uint16 spell_id) { } if ( - IsEffectInSpell(spell_id, SE_CancelMagic) || - IsEffectInSpell(spell_id, SE_DispelBeneficial) || - IsEffectInSpell(spell_id, SE_DispelBeneficial) + IsEffectInSpell(spell_id, SpellEffect::CancelMagic) || + IsEffectInSpell(spell_id, SpellEffect::DispelBeneficial) || + IsEffectInSpell(spell_id, SpellEffect::DispelBeneficial) ) { return true; } @@ -1768,12 +1768,12 @@ bool IsEscapeSpell(uint16 spell_id) { return ( IsInvulnerabilitySpell(spell_id) || - IsEffectInSpell(spell_id, SE_FeignDeath) || - IsEffectInSpell(spell_id, SE_DeathSave) || - IsEffectInSpell(spell_id, SE_Destroy) || + IsEffectInSpell(spell_id, SpellEffect::FeignDeath) || + IsEffectInSpell(spell_id, SpellEffect::DeathSave) || + IsEffectInSpell(spell_id, SpellEffect::Destroy) || ( - IsEffectInSpell(spell_id, SE_WipeHateList) && - spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_WipeHateList)] > 0 + IsEffectInSpell(spell_id, SpellEffect::WipeHateList) && + spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SpellEffect::WipeHateList)] > 0 ) ); } @@ -1791,12 +1791,12 @@ bool IsDebuffSpell(uint16 spell_id) IsMesmerizeSpell(spell_id) || IsCharmSpell(spell_id) || IsSlowSpell(spell_id) || - IsEffectInSpell(spell_id, SE_Root) || - IsEffectInSpell(spell_id, SE_CancelMagic) || - IsEffectInSpell(spell_id, SE_MovementSpeed) || + IsEffectInSpell(spell_id, SpellEffect::Root) || + IsEffectInSpell(spell_id, SpellEffect::CancelMagic) || + IsEffectInSpell(spell_id, SpellEffect::MovementSpeed) || IsFearSpell(spell_id) || - IsEffectInSpell(spell_id, SE_InstantHate) || - IsEffectInSpell(spell_id, SE_TossUp) + IsEffectInSpell(spell_id, SpellEffect::InstantHate) || + IsEffectInSpell(spell_id, SpellEffect::TossUp) ); } @@ -1807,16 +1807,16 @@ bool IsHateReduxSpell(uint16 spell_id) { return ( ( - IsEffectInSpell(spell_id, SE_InstantHate) && - spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_InstantHate)] < 0 + IsEffectInSpell(spell_id, SpellEffect::InstantHate) && + spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SpellEffect::InstantHate)] < 0 ) || ( - IsEffectInSpell(spell_id, SE_Hate) && - spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_Hate)] < 0 + IsEffectInSpell(spell_id, SpellEffect::Hate) && + spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SpellEffect::Hate)] < 0 ) || ( - IsEffectInSpell(spell_id, SE_ReduceHate) && - spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_ReduceHate)] < 0 + IsEffectInSpell(spell_id, SpellEffect::ReduceHate) && + spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SpellEffect::ReduceHate)] < 0 ) ); } @@ -1830,13 +1830,13 @@ bool IsResistDebuffSpell(uint16 spell_id) return ( !IsBeneficialSpell(spell_id) && ( - IsEffectInSpell(spell_id, SE_ResistFire) || - IsEffectInSpell(spell_id, SE_ResistCold) || - IsEffectInSpell(spell_id, SE_ResistPoison) || - IsEffectInSpell(spell_id, SE_ResistDisease) || - IsEffectInSpell(spell_id, SE_ResistMagic) || - IsEffectInSpell(spell_id, SE_ResistAll) || - IsEffectInSpell(spell_id, SE_ResistCorruption) + IsEffectInSpell(spell_id, SpellEffect::ResistFire) || + IsEffectInSpell(spell_id, SpellEffect::ResistCold) || + IsEffectInSpell(spell_id, SpellEffect::ResistPoison) || + IsEffectInSpell(spell_id, SpellEffect::ResistDisease) || + IsEffectInSpell(spell_id, SpellEffect::ResistMagic) || + IsEffectInSpell(spell_id, SpellEffect::ResistAll) || + IsEffectInSpell(spell_id, SpellEffect::ResistCorruption) ) ); } @@ -1849,10 +1849,10 @@ bool IsSelfConversionSpell(uint16 spell_id) return ( GetSpellTargetType(spell_id) == ST_Self && - IsEffectInSpell(spell_id, SE_CurrentMana) && - IsEffectInSpell(spell_id, SE_CurrentHP) && - spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_CurrentMana)] > 0 && - spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_CurrentHP)] < 0 + IsEffectInSpell(spell_id, SpellEffect::CurrentMana) && + IsEffectInSpell(spell_id, SpellEffect::CurrentHP) && + spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SpellEffect::CurrentMana)] > 0 && + spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SpellEffect::CurrentHP)] < 0 ); } @@ -1896,9 +1896,9 @@ bool IsCastOnFadeDurationSpell(uint16 spell_id) { for (int i = 0; i < EFFECT_COUNT; ++i) { if ( - spells[spell_id].effect_id[i] == SE_CastOnFadeEffect || - spells[spell_id].effect_id[i] == SE_CastOnFadeEffectNPC || - spells[spell_id].effect_id[i] == SE_CastOnFadeEffectAlways + spells[spell_id].effect_id[i] == SpellEffect::CastOnFadeEffect || + spells[spell_id].effect_id[i] == SpellEffect::CastOnFadeEffectNPC || + spells[spell_id].effect_id[i] == SpellEffect::CastOnFadeEffectAlways ) { return true; } @@ -1926,7 +1926,7 @@ bool IsDistanceModifierSpell(uint16 spell_id) int GetSpellPartialMeleeRuneReduction(uint16 spell_id) { for (int i = 0; i < EFFECT_COUNT; ++i) { - if (spells[spell_id].effect_id[i] == SE_MitigateMeleeDamage) { + if (spells[spell_id].effect_id[i] == SpellEffect::MitigateMeleeDamage) { return spells[spell_id].base_value[i]; } } @@ -1937,7 +1937,7 @@ int GetSpellPartialMeleeRuneReduction(uint16 spell_id) int GetSpellPartialMagicRuneReduction(uint16 spell_id) { for (int i = 0; i < EFFECT_COUNT; ++i) { - if (spells[spell_id].effect_id[i] == SE_MitigateSpellDamage) { + if (spells[spell_id].effect_id[i] == SpellEffect::MitigateSpellDamage) { return spells[spell_id].base_value[i]; } } @@ -1948,7 +1948,7 @@ int GetSpellPartialMagicRuneReduction(uint16 spell_id) int GetSpellPartialMeleeRuneAmount(uint16 spell_id) { for (int i = 0; i < EFFECT_COUNT; ++i) { - if (spells[spell_id].effect_id[i] == SE_MitigateMeleeDamage) { + if (spells[spell_id].effect_id[i] == SpellEffect::MitigateMeleeDamage) { return spells[spell_id].max_value[i]; } } @@ -1959,7 +1959,7 @@ int GetSpellPartialMeleeRuneAmount(uint16 spell_id) int GetSpellPartialMagicRuneAmount(uint16 spell_id) { for (int i = 0; i < EFFECT_COUNT; ++i) { - if (spells[spell_id].effect_id[i] == SE_MitigateSpellDamage) { + if (spells[spell_id].effect_id[i] == SpellEffect::MitigateSpellDamage) { return spells[spell_id].max_value[i]; } } @@ -2002,15 +2002,15 @@ bool IsStackableDOT(uint16 spell_id) } return ( - IsEffectInSpell(spell_id, SE_CurrentHP) || - IsEffectInSpell(spell_id, SE_GravityEffect) + IsEffectInSpell(spell_id, SpellEffect::CurrentHP) || + IsEffectInSpell(spell_id, SpellEffect::GravityEffect) ); } bool IsBardOnlyStackEffect(int effect_id) { switch (effect_id) { - case SE_BardAEDot: + case SpellEffect::BardAEDot: return true; default: return false; @@ -2039,91 +2039,91 @@ bool IsEffectIgnoredInStacking(int effect_id) { // this should match RoF2 switch (effect_id) { - case SE_SeeInvis: - case SE_DiseaseCounter: - case SE_PoisonCounter: - case SE_Levitate: - case SE_InfraVision: - case SE_UltraVision: - case SE_CurrentHPOnce: - case SE_CurseCounter: - case SE_ImprovedDamage: - case SE_ImprovedHeal: - case SE_SpellResistReduction: - case SE_IncreaseSpellHaste: - case SE_IncreaseSpellDuration: - case SE_IncreaseRange: - case SE_SpellHateMod: - case SE_ReduceReagentCost: - case SE_ReduceManaCost: - case SE_FcStunTimeMod: - case SE_LimitMaxLevel: - case SE_LimitResist: - case SE_LimitTarget: - case SE_LimitEffect: - case SE_LimitSpellType: - case SE_LimitSpell: - case SE_LimitMinDur: - case SE_LimitInstant: - case SE_LimitMinLevel: - case SE_LimitCastTimeMin: - case SE_LimitCastTimeMax: - case SE_StackingCommand_Block: - case SE_StackingCommand_Overwrite: - case SE_PetPowerIncrease: - case SE_SkillDamageAmount: - case SE_ChannelChanceSpells: - case SE_Blank: - case SE_FcDamageAmt: - case SE_SpellDurationIncByTic: - case SE_FcSpellVulnerability: - case SE_FcDamageAmtIncoming: - case SE_FcDamagePctCrit: - case SE_FcDamageAmtCrit: - case SE_ReduceReuseTimer: - case SE_LimitCombatSkills: - case SE_BlockNextSpellFocus: - case SE_SpellTrigger: - case SE_LimitManaMin: - case SE_CorruptionCounter: - case SE_ApplyEffect: - case SE_NegateSpellEffect: - case SE_LimitSpellGroup: - case SE_LimitManaMax: - case SE_FcHealAmt: - case SE_FcHealPctIncoming: - case SE_FcHealAmtIncoming: - case SE_FcHealPctCritIncoming: - case SE_FcHealAmtCrit: - case SE_LimitClass: - case SE_LimitRace: - case SE_FcBaseEffects: - case SE_FFItemClass: - case SE_SkillDamageAmount2: - case SE_FcLimitUse: - case SE_FcIncreaseNumHits: - case SE_LimitUseMin: - case SE_LimitUseType: - case SE_GravityEffect: - case SE_Display: + case SpellEffect::SeeInvis: + case SpellEffect::DiseaseCounter: + case SpellEffect::PoisonCounter: + case SpellEffect::Levitate: + case SpellEffect::InfraVision: + case SpellEffect::UltraVision: + case SpellEffect::CurrentHPOnce: + case SpellEffect::CurseCounter: + case SpellEffect::ImprovedDamage: + case SpellEffect::ImprovedHeal: + case SpellEffect::SpellResistReduction: + case SpellEffect::IncreaseSpellHaste: + case SpellEffect::IncreaseSpellDuration: + case SpellEffect::IncreaseRange: + case SpellEffect::SpellHateMod: + case SpellEffect::ReduceReagentCost: + case SpellEffect::ReduceManaCost: + case SpellEffect::FcStunTimeMod: + case SpellEffect::LimitMaxLevel: + case SpellEffect::LimitResist: + case SpellEffect::LimitTarget: + case SpellEffect::LimitEffect: + case SpellEffect::LimitSpellType: + case SpellEffect::LimitSpell: + case SpellEffect::LimitMinDur: + case SpellEffect::LimitInstant: + case SpellEffect::LimitMinLevel: + case SpellEffect::LimitCastTimeMin: + case SpellEffect::LimitCastTimeMax: + case SpellEffect::StackingCommand_Block: + case SpellEffect::StackingCommand_Overwrite: + case SpellEffect::PetPowerIncrease: + case SpellEffect::SkillDamageAmount: + case SpellEffect::ChannelChanceSpells: + case SpellEffect::Blank: + case SpellEffect::FcDamageAmt: + case SpellEffect::SpellDurationIncByTic: + case SpellEffect::FcSpellVulnerability: + case SpellEffect::FcDamageAmtIncoming: + case SpellEffect::FcDamagePctCrit: + case SpellEffect::FcDamageAmtCrit: + case SpellEffect::ReduceReuseTimer: + case SpellEffect::LimitCombatSkills: + case SpellEffect::BlockNextSpellFocus: + case SpellEffect::SpellTrigger: + case SpellEffect::LimitManaMin: + case SpellEffect::CorruptionCounter: + case SpellEffect::ApplyEffect: + case SpellEffect::NegateSpellEffect: + case SpellEffect::LimitSpellGroup: + case SpellEffect::LimitManaMax: + case SpellEffect::FcHealAmt: + case SpellEffect::FcHealPctIncoming: + case SpellEffect::FcHealAmtIncoming: + case SpellEffect::FcHealPctCritIncoming: + case SpellEffect::FcHealAmtCrit: + case SpellEffect::LimitClass: + case SpellEffect::LimitRace: + case SpellEffect::FcBaseEffects: + case SpellEffect::FFItemClass: + case SpellEffect::SkillDamageAmount2: + case SpellEffect::FcLimitUse: + case SpellEffect::FcIncreaseNumHits: + case SpellEffect::LimitUseMin: + case SpellEffect::LimitUseType: + case SpellEffect::GravityEffect: + case SpellEffect::Display: //Spell effects implemented after ROF2, following same pattern, lets assume these should go here. - case SE_Fc_Spell_Damage_Pct_IncomingPC: - case SE_Fc_Spell_Damage_Amt_IncomingPC: - case SE_Ff_CasterClass: - case SE_Ff_Same_Caster: - case SE_Proc_Timer_Modifier: - case SE_Weapon_Stance: - case SE_TwinCastBlocker: - case SE_Fc_CastTimeAmt: - case SE_Fc_CastTimeMod2: - case SE_Ff_DurationMax: - case SE_Ff_Endurance_Max: - case SE_Ff_Endurance_Min: - case SE_Ff_ReuseTimeMin: - case SE_Ff_ReuseTimeMax: - case SE_Ff_Value_Min: - case SE_Ff_Value_Max: - case SE_Ff_FocusTimerMin: + case SpellEffect::Fc_Spell_Damage_Pct_IncomingPC: + case SpellEffect::Fc_Spell_Damage_Amt_IncomingPC: + case SpellEffect::Ff_CasterClass: + case SpellEffect::Ff_Same_Caster: + case SpellEffect::Proc_Timer_Modifier: + case SpellEffect::Weapon_Stance: + case SpellEffect::TwinCastBlocker: + case SpellEffect::Fc_CastTimeAmt: + case SpellEffect::Fc_CastTimeMod2: + case SpellEffect::Ff_DurationMax: + case SpellEffect::Ff_Endurance_Max: + case SpellEffect::Ff_Endurance_Min: + case SpellEffect::Ff_ReuseTimeMin: + case SpellEffect::Ff_ReuseTimeMax: + case SpellEffect::Ff_Value_Min: + case SpellEffect::Ff_Value_Max: + case SpellEffect::Ff_FocusTimerMin: return true; default: return false; @@ -2133,40 +2133,40 @@ bool IsEffectIgnoredInStacking(int effect_id) bool IsFocusLimit(int effect_id) { switch (effect_id) { - case SE_LimitMaxLevel: - case SE_LimitResist: - case SE_LimitTarget: - case SE_LimitEffect: - case SE_LimitSpellType: - case SE_LimitSpell: - case SE_LimitMinDur: - case SE_LimitInstant: - case SE_LimitMinLevel: - case SE_LimitCastTimeMin: - case SE_LimitCastTimeMax: - case SE_LimitCombatSkills: - case SE_LimitManaMin: - case SE_LimitSpellGroup: - case SE_LimitManaMax: - case SE_LimitSpellClass: - case SE_LimitSpellSubclass: - case SE_LimitClass: - case SE_LimitRace: - case SE_LimitCastingSkill: - case SE_LimitUseMin: - case SE_LimitUseType: - case SE_Ff_Override_NotFocusable: - case SE_Ff_CasterClass: - case SE_Ff_Same_Caster: - case SE_Ff_DurationMax: - case SE_Ff_Endurance_Max: - case SE_Ff_Endurance_Min: - case SE_Ff_ReuseTimeMin: - case SE_Ff_ReuseTimeMax: - case SE_Ff_Value_Min: - case SE_Ff_Value_Max: - case SE_Ff_FocusTimerMin: - case SE_FFItemClass: + case SpellEffect::LimitMaxLevel: + case SpellEffect::LimitResist: + case SpellEffect::LimitTarget: + case SpellEffect::LimitEffect: + case SpellEffect::LimitSpellType: + case SpellEffect::LimitSpell: + case SpellEffect::LimitMinDur: + case SpellEffect::LimitInstant: + case SpellEffect::LimitMinLevel: + case SpellEffect::LimitCastTimeMin: + case SpellEffect::LimitCastTimeMax: + case SpellEffect::LimitCombatSkills: + case SpellEffect::LimitManaMin: + case SpellEffect::LimitSpellGroup: + case SpellEffect::LimitManaMax: + case SpellEffect::LimitSpellClass: + case SpellEffect::LimitSpellSubclass: + case SpellEffect::LimitClass: + case SpellEffect::LimitRace: + case SpellEffect::LimitCastingSkill: + case SpellEffect::LimitUseMin: + case SpellEffect::LimitUseType: + case SpellEffect::Ff_Override_NotFocusable: + case SpellEffect::Ff_CasterClass: + case SpellEffect::Ff_Same_Caster: + case SpellEffect::Ff_DurationMax: + case SpellEffect::Ff_Endurance_Max: + case SpellEffect::Ff_Endurance_Min: + case SpellEffect::Ff_ReuseTimeMin: + case SpellEffect::Ff_ReuseTimeMax: + case SpellEffect::Ff_Value_Min: + case SpellEffect::Ff_Value_Max: + case SpellEffect::Ff_FocusTimerMin: + case SpellEffect::FFItemClass: return true; default: return false; @@ -2192,10 +2192,10 @@ int GetSpellFuriousBash(uint16 spell_id) auto mod = 0; for (int i = 0; i < EFFECT_COUNT; ++i) { - if (spells[spell_id].effect_id[i] == SE_SpellHateMod) { + if (spells[spell_id].effect_id[i] == SpellEffect::SpellHateMod) { mod = spells[spell_id].base_value[i]; } else if ( - spells[spell_id].effect_id[i] == SE_LimitEffect && + spells[spell_id].effect_id[i] == SpellEffect::LimitEffect && spells[spell_id].base_value[i] == 999 ) { found_effect_limit = true; @@ -2275,47 +2275,47 @@ bool IsInstrumentModifierAppliedToSpellEffect(uint16 spell_id, int effect_id) //Effects that are verified modifiable by bard instrument/singing mods, or highly likely due to similiar type of effect. switch (effect_id) { //Only modify instant endurance or mana effects (Ie. Mana drain, Crescendo line) - case SE_CurrentEndurance: - case SE_CurrentMana: { + case SpellEffect::CurrentEndurance: + case SpellEffect::CurrentMana: { return spells[spell_id].buff_duration == 0; } - case SE_CurrentHP: - case SE_ArmorClass: - case SE_ACv2: - case SE_MovementSpeed: - case SE_ATK: - case SE_STR: - case SE_DEX: - case SE_AGI: - case SE_STA: - case SE_INT: - case SE_WIS: - case SE_CHA: - case SE_AllStats: - case SE_ResistFire: - case SE_ResistCold: - case SE_ResistPoison: - case SE_ResistDisease: - case SE_ResistMagic: - case SE_ResistAll: - case SE_ResistCorruption: - case SE_Rune: - case SE_AbsorbMagicAtt: - case SE_DamageShield: - case SE_MitigateDamageShield: - case SE_Amplification: //On live Amplification is modified by singing mods, including itself. - case SE_TripleAttackChance: - case SE_Flurry: - case SE_DamageModifier: - case SE_DamageModifier2: - case SE_MinDamageModifier: - case SE_ProcChance: - case SE_PetFlurry: // ? Need verified - case SE_DiseaseCounter: - case SE_PoisonCounter: - case SE_CurseCounter: - case SE_CorruptionCounter: + case SpellEffect::CurrentHP: + case SpellEffect::ArmorClass: + case SpellEffect::ACv2: + case SpellEffect::MovementSpeed: + case SpellEffect::ATK: + case SpellEffect::STR: + case SpellEffect::DEX: + case SpellEffect::AGI: + case SpellEffect::STA: + case SpellEffect::INT: + case SpellEffect::WIS: + case SpellEffect::CHA: + case SpellEffect::AllStats: + case SpellEffect::ResistFire: + case SpellEffect::ResistCold: + case SpellEffect::ResistPoison: + case SpellEffect::ResistDisease: + case SpellEffect::ResistMagic: + case SpellEffect::ResistAll: + case SpellEffect::ResistCorruption: + case SpellEffect::Rune: + case SpellEffect::AbsorbMagicAtt: + case SpellEffect::DamageShield: + case SpellEffect::MitigateDamageShield: + case SpellEffect::Amplification: //On live Amplification is modified by singing mods, including itself. + case SpellEffect::TripleAttackChance: + case SpellEffect::Flurry: + case SpellEffect::DamageModifier: + case SpellEffect::DamageModifier2: + case SpellEffect::MinDamageModifier: + case SpellEffect::ProcChance: + case SpellEffect::PetFlurry: // ? Need verified + case SpellEffect::DiseaseCounter: + case SpellEffect::PoisonCounter: + case SpellEffect::CurseCounter: + case SpellEffect::CorruptionCounter: return true; /* @@ -2323,45 +2323,45 @@ bool IsInstrumentModifierAppliedToSpellEffect(uint16 spell_id, int effect_id) Focus Effects, Proc Effects, Spell Triggers are not modified but handled elsewhere, not neccessary to checked here. */ - case SE_AttackSpeed: //(Haste AND Slow not modifiable) - case SE_AttackSpeed2: - case SE_AttackSpeed3: - case SE_Lull: - case SE_ChangeFrenzyRad: - case SE_Harmony: - case SE_AddFaction: - //case SE_CurrentMana: // duration only - case SE_ManaRegen_v2: - //case SE_CurrentEndurance: // duration only - case SE_PersistentEffect: - case SE_ReduceReuseTimer: - case SE_Stun: - case SE_Mez: - case SE_WipeHateList: //? - case SE_CancelMagic: - case SE_ManaAbsorbPercentDamage: - case SE_ResistSpellChance: - case SE_Reflect: - case SE_MitigateSpellDamage: - case SE_MitigateMeleeDamage: - case SE_AllInstrumentMod: - case SE_AddSingingMod: - case SE_SongModCap: - case SE_BardSongRange: - case SE_TemporaryPets: - case SE_SpellOnDeath: - case SE_Invisibility: - case SE_Invisibility2: - case SE_InvisVsUndead: - case SE_InvisVsUndead2: - case SE_InvisVsAnimals: - case SE_ImprovedInvisAnimals: - case SE_SeeInvis: - case SE_Levitate: - case SE_WaterBreathing: - case SE_ModelSize: - case SE_ChangeHeight: - case SE_MakeDrunk: + case SpellEffect::AttackSpeed: //(Haste AND Slow not modifiable) + case SpellEffect::AttackSpeed2: + case SpellEffect::AttackSpeed3: + case SpellEffect::Lull: + case SpellEffect::ChangeFrenzyRad: + case SpellEffect::Harmony: + case SpellEffect::AddFaction: + //case SpellEffect::CurrentMana: // duration only + case SpellEffect::ManaRegen_v2: + //case SpellEffect::CurrentEndurance: // duration only + case SpellEffect::PersistentEffect: + case SpellEffect::ReduceReuseTimer: + case SpellEffect::Stun: + case SpellEffect::Mez: + case SpellEffect::WipeHateList: //? + case SpellEffect::CancelMagic: + case SpellEffect::ManaAbsorbPercentDamage: + case SpellEffect::ResistSpellChance: + case SpellEffect::Reflect: + case SpellEffect::MitigateSpellDamage: + case SpellEffect::MitigateMeleeDamage: + case SpellEffect::AllInstrumentMod: + case SpellEffect::AddSingingMod: + case SpellEffect::SongModCap: + case SpellEffect::BardSongRange: + case SpellEffect::TemporaryPets: + case SpellEffect::SpellOnDeath: + case SpellEffect::Invisibility: + case SpellEffect::Invisibility2: + case SpellEffect::InvisVsUndead: + case SpellEffect::InvisVsUndead2: + case SpellEffect::InvisVsAnimals: + case SpellEffect::ImprovedInvisAnimals: + case SpellEffect::SeeInvis: + case SpellEffect::Levitate: + case SpellEffect::WaterBreathing: + case SpellEffect::ModelSize: + case SpellEffect::ChangeHeight: + case SpellEffect::MakeDrunk: return false; default: return true; @@ -2379,8 +2379,8 @@ bool IsPulsingBardSong(uint16 spell_id) spells[spell_id].buff_duration == 0xFFFF || spells[spell_id].recast_time > 0 || spells[spell_id].mana > 0 || - IsEffectInSpell(spell_id, SE_TemporaryPets) || - IsEffectInSpell(spell_id, SE_Familiar) + IsEffectInSpell(spell_id, SpellEffect::TemporaryPets) || + IsEffectInSpell(spell_id, SpellEffect::Familiar) ) { return false; } @@ -2555,28 +2555,28 @@ int GetSpellProcLimitTimer(uint16 spell_id, int proc_type) if (proc_type == ProcType::MELEE_PROC) { if ( - spells[spell_id].effect_id[i] == SE_WeaponProc || - spells[spell_id].effect_id[i] == SE_AddMeleeProc + spells[spell_id].effect_id[i] == SpellEffect::WeaponProc || + spells[spell_id].effect_id[i] == SpellEffect::AddMeleeProc ) { use_next_timer = true; } } if (proc_type == ProcType::RANGED_PROC) { - if (spells[spell_id].effect_id[i] == SE_RangedProc) { + if (spells[spell_id].effect_id[i] == SpellEffect::RangedProc) { use_next_timer = true; } } if (proc_type == ProcType::DEFENSIVE_PROC) { - if (spells[spell_id].effect_id[i] == SE_DefensiveProc) { + if (spells[spell_id].effect_id[i] == SpellEffect::DefensiveProc) { use_next_timer = true; } } if ( use_next_timer && - spells[spell_id].effect_id[i] == SE_Proc_Timer_Modifier + spells[spell_id].effect_id[i] == SpellEffect::Proc_Timer_Modifier ) { return spells[spell_id].limit_value[i]; } @@ -2683,23 +2683,23 @@ bool IsAegolismSpell(uint16 spell_id) { for (int i = 0; i < EFFECT_COUNT; ++i) { - if (i == 0 && spells[spell_id].effect_id[i] != SE_StackingCommand_Block) { + if (i == 0 && spells[spell_id].effect_id[i] != SpellEffect::StackingCommand_Block) { return 0; } - if (i == 1 && spells[spell_id].effect_id[i] == SE_TotalHP) { + if (i == 1 && spells[spell_id].effect_id[i] == SpellEffect::TotalHP) { has_max_hp = true; } - if (i == 2 && spells[spell_id].effect_id[i] == SE_CurrentHPOnce) { + if (i == 2 && spells[spell_id].effect_id[i] == SpellEffect::CurrentHPOnce) { has_current_hp = true; } - if (i == 3 && spells[spell_id].effect_id[i] == SE_ArmorClass) { + if (i == 3 && spells[spell_id].effect_id[i] == SpellEffect::ArmorClass) { has_ac = true; } - if (i == 4 && spells[spell_id].effect_id[i] != SE_StackingCommand_Overwrite) { + if (i == 4 && spells[spell_id].effect_id[i] != SpellEffect::StackingCommand_Overwrite) { return 0; } } @@ -2726,16 +2726,16 @@ bool AegolismStackingIsSymbolSpell(uint16 spell_id) { for (int i = 0; i < EFFECT_COUNT; ++i) { - if ((i < 2 && spells[spell_id].effect_id[i] != SE_CHA) || - i > 3 && spells[spell_id].effect_id[i] != SE_Blank) { + if ((i < 2 && spells[spell_id].effect_id[i] != SpellEffect::CHA) || + i > 3 && spells[spell_id].effect_id[i] != SpellEffect::Blank) { return 0; } - if (i == 2 && spells[spell_id].effect_id[i] == SE_TotalHP) { + if (i == 2 && spells[spell_id].effect_id[i] == SpellEffect::TotalHP) { has_max_hp = true; } - if (i == 3 && spells[spell_id].effect_id[i] == SE_CurrentHPOnce) { + if (i == 3 && spells[spell_id].effect_id[i] == SpellEffect::CurrentHPOnce) { has_current_hp = true; } } @@ -2759,12 +2759,12 @@ bool AegolismStackingIsArmorClassSpell(uint16 spell_id) { for (int i = 0; i < EFFECT_COUNT; ++i) { - if ((i < 3 && spells[spell_id].effect_id[i] != SE_CHA) || - i > 3 && spells[spell_id].effect_id[i] != SE_Blank) { + if ((i < 3 && spells[spell_id].effect_id[i] != SpellEffect::CHA) || + i > 3 && spells[spell_id].effect_id[i] != SpellEffect::Blank) { return 0; } - if (i == 3 && spells[spell_id].effect_id[i] == SE_ArmorClass) { + if (i == 3 && spells[spell_id].effect_id[i] == SpellEffect::ArmorClass) { has_ac = true; } } @@ -2800,10 +2800,10 @@ bool IsLichSpell(uint16 spell_id) return ( GetSpellTargetType(spell_id) == ST_Self && - IsEffectInSpell(spell_id, SE_CurrentMana) && - IsEffectInSpell(spell_id, SE_CurrentHP) && - spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_CurrentMana)] > 0 && - spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_CurrentHP)] < 0 && + IsEffectInSpell(spell_id, SpellEffect::CurrentMana) && + IsEffectInSpell(spell_id, SpellEffect::CurrentHP) && + spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SpellEffect::CurrentMana)] > 0 && + spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SpellEffect::CurrentHP)] < 0 && spells[spell_id].buff_duration > 0 ); } @@ -2828,7 +2828,7 @@ bool IsResurrectSpell(uint16 spell_id) return false; } - return IsEffectInSpell(spell_id, SE_Revive); + return IsEffectInSpell(spell_id, SpellEffect::Revive); } bool IsResistanceBuffSpell(uint16 spell_id) { @@ -2844,13 +2844,13 @@ bool IsResistanceBuffSpell(uint16 spell_id) { } if ( - spell.effect_id[i] == SE_ResistFire || - spell.effect_id[i] == SE_ResistCold || - spell.effect_id[i] == SE_ResistPoison || - spell.effect_id[i] == SE_ResistDisease || - spell.effect_id[i] == SE_ResistMagic || - spell.effect_id[i] == SE_ResistCorruption || - spell.effect_id[i] == SE_ResistAll + spell.effect_id[i] == SpellEffect::ResistFire || + spell.effect_id[i] == SpellEffect::ResistCold || + spell.effect_id[i] == SpellEffect::ResistPoison || + spell.effect_id[i] == SpellEffect::ResistDisease || + spell.effect_id[i] == SpellEffect::ResistMagic || + spell.effect_id[i] == SpellEffect::ResistCorruption || + spell.effect_id[i] == SpellEffect::ResistAll ) { return true; } @@ -2872,13 +2872,13 @@ bool IsResistanceOnlySpell(uint16 spell_id) { } if ( - spell.effect_id[i] == SE_ResistFire || - spell.effect_id[i] == SE_ResistCold || - spell.effect_id[i] == SE_ResistPoison || - spell.effect_id[i] == SE_ResistDisease || - spell.effect_id[i] == SE_ResistMagic || - spell.effect_id[i] == SE_ResistCorruption || - spell.effect_id[i] == SE_ResistAll + spell.effect_id[i] == SpellEffect::ResistFire || + spell.effect_id[i] == SpellEffect::ResistCold || + spell.effect_id[i] == SpellEffect::ResistPoison || + spell.effect_id[i] == SpellEffect::ResistDisease || + spell.effect_id[i] == SpellEffect::ResistMagic || + spell.effect_id[i] == SpellEffect::ResistCorruption || + spell.effect_id[i] == SpellEffect::ResistAll ) { continue; } @@ -2902,7 +2902,7 @@ bool IsDamageShieldOnlySpell(uint16 spell_id) { } if ( - spell.effect_id[i] != SE_DamageShield + spell.effect_id[i] != SpellEffect::DamageShield ) { return false; } @@ -2924,14 +2924,14 @@ bool IsDamageShieldAndResistSpell(uint16 spell_id) { } if ( - spell.effect_id[i] != SE_DamageShield && - spell.effect_id[i] != SE_ResistFire && - spell.effect_id[i] != SE_ResistCold && - spell.effect_id[i] != SE_ResistPoison && - spell.effect_id[i] != SE_ResistDisease && - spell.effect_id[i] != SE_ResistMagic && - spell.effect_id[i] != SE_ResistCorruption && - spell.effect_id[i] != SE_ResistAll + spell.effect_id[i] != SpellEffect::DamageShield && + spell.effect_id[i] != SpellEffect::ResistFire && + spell.effect_id[i] != SpellEffect::ResistCold && + spell.effect_id[i] != SpellEffect::ResistPoison && + spell.effect_id[i] != SpellEffect::ResistDisease && + spell.effect_id[i] != SpellEffect::ResistMagic && + spell.effect_id[i] != SpellEffect::ResistCorruption && + spell.effect_id[i] != SpellEffect::ResistAll ) { return false; } @@ -2947,12 +2947,12 @@ bool IsHateSpell(uint16 spell_id) { return ( ( - IsEffectInSpell(spell_id, SE_Hate) && - spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_Hate)] > 0 + IsEffectInSpell(spell_id, SpellEffect::Hate) && + spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SpellEffect::Hate)] > 0 ) || ( - IsEffectInSpell(spell_id, SE_InstantHate) && - spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SE_InstantHate)] > 0 + IsEffectInSpell(spell_id, SpellEffect::InstantHate) && + spells[spell_id].base_value[GetSpellEffectIndex(spell_id, SpellEffect::InstantHate)] > 0 ) ); } diff --git a/common/spdat.h b/common/spdat.h index 4cea6e0980..11130d6a4e 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -1059,537 +1059,536 @@ typedef enum { //Spell Effect IDs // https://web.archive.org/web/20250816011656/https://forums.everquest.com/index.php?threads/enumerated-spa-list.206288/ // mirror: http://pastebin.com/MYeQqGwe -#define SE_CurrentHP 0 // implemented - Heals and nukes, repeates every tic if in a buff -#define SE_ArmorClass 1 // implemented -#define SE_ATK 2 // implemented -#define SE_MovementSpeed 3 // implemented - SoW, SoC, etc -#define SE_STR 4 // implemented -#define SE_DEX 5 // implemented -#define SE_AGI 6 // implemented -#define SE_STA 7 // implemented -#define SE_INT 8 // implemented -#define SE_WIS 9 // implemented -#define SE_CHA 10 // implemented - used as a spacer -#define SE_AttackSpeed 11 // implemented -#define SE_Invisibility 12 // implemented - TO DO: Implemented Invisiblity Levels -#define SE_SeeInvis 13 // implemented - TO DO: Implemented See Invisiblity Levels -#define SE_WaterBreathing 14 // implemented -#define SE_CurrentMana 15 // implemented -//#define SE_NPCFrenzy 16 // not used -//#define SE_NPCAwareness 17 // not used -#define SE_Lull 18 // implemented - Reaction Radius -#define SE_AddFaction 19 // implemented - Alliance line -#define SE_Blind 20 // implemented -#define SE_Stun 21 // implemented -#define SE_Charm 22 // implemented -#define SE_Fear 23 // implemented -#define SE_Stamina 24 // implemented - Invigor and such -#define SE_BindAffinity 25 // implemented - TO DO: Implement 2nd and 3rd Recall (value 2,3 ect). Sets additional bind points. -#define SE_Gate 26 // implemented - Gate to bind point -#define SE_CancelMagic 27 // implemented -#define SE_InvisVsUndead 28 // implemented -#define SE_InvisVsAnimals 29 // implemented -#define SE_ChangeFrenzyRad 30 // implemented - Pacify -#define SE_Mez 31 // implemented -#define SE_SummonItem 32 // implemented -#define SE_SummonPet 33 // implemented -//#define SE_Confuse 34 // not used (Nimbus of Temporal Rifting) ? -#define SE_DiseaseCounter 35 // implemented -#define SE_PoisonCounter 36 // implemented -//#define SE_DetectHostile 37 // not used -//#define SE_DetectMagic 38 // not used -#define SE_TwinCastBlocker 39 // implemented - If present in spell, then the spell can not be twincast. -#define SE_DivineAura 40 // implemented -#define SE_Destroy 41 // implemented - Disintegrate, Banishment of Shadows -#define SE_ShadowStep 42 // implemented -#define SE_Berserk 43 // implemented (*not used in any known live spell) Makes client 'Berserk' giving crip blow chance. -#define SE_Lycanthropy 44 // implemented -#define SE_Vampirism 45 // implemented (*not used in any known live spell) Stackable lifetap from melee. -#define SE_ResistFire 46 // implemented -#define SE_ResistCold 47 // implemented -#define SE_ResistPoison 48 // implemented -#define SE_ResistDisease 49 // implemented -#define SE_ResistMagic 50 // implemented -//#define SE_DetectTraps 51 // not used -#define SE_SenseDead 52 // implemented -#define SE_SenseSummoned 53 // implemented -#define SE_SenseAnimals 54 // implemented -#define SE_Rune 55 // implemented -#define SE_TrueNorth 56 // implemented -#define SE_Levitate 57 // implemented -#define SE_Illusion 58 // implemented -#define SE_DamageShield 59 // implemented -//#define SE_TransferItem 60 // not used -#define SE_Identify 61 // implemented -//#define SE_ItemID 62 // not used -#define SE_WipeHateList 63 // implemented, @Memblur, chance to wipe hate list of target, base: pct chance, limit: none, max: ? (not implemented), Note: caster level and CHA add to pct chance -#define SE_SpinTarget 64 // implemented - TO DO: Not sure stun portion is working correctly -#define SE_InfraVision 65 // implemented -#define SE_UltraVision 66 // implemented -#define SE_EyeOfZomm 67 // implemented -#define SE_ReclaimPet 68 // implemented -#define SE_TotalHP 69 // implemented -//#define SE_CorpseBomb 70 // not used -#define SE_NecPet 71 // implemented -//#define SE_PreserveCorpse 72 // not used -#define SE_BindSight 73 // implemented, @Vision, see through the eyes of your target, click off buff to end effect, base: 1, limit: none, max: none -#define SE_FeignDeath 74 // implemented -#define SE_VoiceGraft 75 // implemented -#define SE_Sentinel 76 // *not implemented?(just seems to send a message) -#define SE_LocateCorpse 77 // implemented -#define SE_AbsorbMagicAtt 78 // implemented - Rune for spells -#define SE_CurrentHPOnce 79 // implemented - Heals and nukes, non-repeating if in a buff -//#define SE_EnchantLight 80 // not used -#define SE_Revive 81 // implemented - Resurrect -#define SE_SummonPC 82 // implemented -#define SE_Teleport 83 // implemented -#define SE_TossUp 84 // implemented - Gravity Flux -#define SE_WeaponProc 85 // implemented - i.e. Call of Fire -#define SE_Harmony 86 // implemented -#define SE_MagnifyVision 87 // implemented - Telescope -#define SE_Succor 88 // implemented - Evacuate/Succor lines -#define SE_ModelSize 89 // implemented - Shrink, Growth -//#define SE_Cloak 90 // *not implemented - Used in only 2 spells -#define SE_SummonCorpse 91 // implemented -#define SE_InstantHate 92 // implemented - add hate -#define SE_StopRain 93 // implemented - Wake of Karana -#define SE_NegateIfCombat 94 // implemented -#define SE_Sacrifice 95 // implemented -#define SE_Silence 96 // implemented -#define SE_ManaPool 97 // implemented -#define SE_AttackSpeed2 98 // implemented - Melody of Ervaj -#define SE_Root 99 // implemented -#define SE_HealOverTime 100 // implemented -#define SE_CompleteHeal 101 // implemented -#define SE_Fearless 102 // implemented - Valiant Companion -#define SE_CallPet 103 // implemented - Summon Companion -#define SE_Translocate 104 // implemented -#define SE_AntiGate 105 // implemented - Translocational Anchor -#define SE_SummonBSTPet 106 // implemented -#define SE_AlterNPCLevel 107 // implemented - not used on live -#define SE_Familiar 108 // implemented -#define SE_SummonItemIntoBag 109 // implemented - summons stuff into container -#define SE_IncreaseArchery 110 // implemented -#define SE_ResistAll 111 // implemented - Note: Physical Resists are not modified by this effect. -#define SE_CastingLevel 112 // implemented -#define SE_SummonHorse 113 // implemented -#define SE_ChangeAggro 114 // implemented - Hate modifing buffs(ie horrifying visage) -#define SE_Hunger 115 // implemented - Song of Sustenance -#define SE_CurseCounter 116 // implemented -#define SE_MagicWeapon 117 // implemented - makes weapon magical -#define SE_Amplification 118 // implemented, @Song, stackable singing mod, base: mod%, limit: none, max: none, Note: Can focus itself. -#define SE_AttackSpeed3 119 // implemented -#define SE_HealRate 120 // implemented - reduces healing by a % -#define SE_ReverseDS 121 // implemented -#define SE_ReduceSkill 122 // implemented - base: skill id, limit: none, max: none, formula: % skill is reduced (positive) -#define SE_Screech 123 // implemented Spell Blocker(If have buff with value +1 will block any effect with -1) -#define SE_ImprovedDamage 124 // implemented -#define SE_ImprovedHeal 125 // implemented -#define SE_SpellResistReduction 126 // implemented -#define SE_IncreaseSpellHaste 127 // implemented, @Fc, On Caster, cast time mod pct, base: pct -#define SE_IncreaseSpellDuration 128 // implemented, @Fc, On Caster, spell duration mod pct, base: pct -#define SE_IncreaseRange 129 // implemented, @Fc, On Caster, spell range mod pct, base: pct -#define SE_SpellHateMod 130 // implemented, @Fc, On Caster, spell hate mod pct, base: min pct, limit: max pct -#define SE_ReduceReagentCost 131 // implemented, @Fc, On Caster, do not consume reagent pct chance, base: min pct, limit: max pct -#define SE_ReduceManaCost 132 // implemented, @Fc, On Caster, reduce mana cost by pct, base: min pct, limt: max pct -#define SE_FcStunTimeMod 133 // implemented, @Fc, On Caster, spell range mod pct, base: pct -#define SE_LimitMaxLevel 134 // implemented, @Ff, Max level of spell that can be focused, if base2 then decrease effectiviness by base2 % per level over max, base: lv, base2: effectiveness pct -#define SE_LimitResist 135 // implemented, @Ff, Resist Type(s) that a spell focus can require or exclude, base1: resist type, Include: Positive Exclude: Negative -#define SE_LimitTarget 136 // implemented, @Ff, Target Type(s) that a spell focus can require or exclude, base1: target type, Include: Positive Exclude: Negative -#define SE_LimitEffect 137 // implemented, @Ff, Spell effect(s) that a spell focus can require or exclude, base1: SPA id, Include: Positive Exclude: Negative -#define SE_LimitSpellType 138 // implemented, @Ff, Only allow focus spells that are Beneficial or Detrimental, base1: 0=det 1=bene -#define SE_LimitSpell 139 // implemented, @Ff, Specific spell id(s) that a spell focus can require or exclude, base1: SPA id, Include: Positive Exclude: Negative -#define SE_LimitMinDur 140 // implemented, @Ff, Mininum duration of spell that can be focused, base1: tics -#define SE_LimitInstant 141 // implemented, @Ff, Include or exclude if an isntant cast spell can be focused, base1: 0=Exclude if Instant 1=Allow only if Instant -#define SE_LimitMinLevel 142 // implemented, @Ff, Mininum level of spell that can be focused, base1: lv -#define SE_LimitCastTimeMin 143 // implemented, @Ff, Mininum cast time of spell that can be focused, base1: milliseconds -#define SE_LimitCastTimeMax 144 // implemented, @Ff, Max cast time of spell that can be focused, base1: milliseconds -#define SE_Teleport2 145 // implemented - Banishment of the Pantheon -//#define SE_ElectricityResist 146 // *not implemented TODO: Now used on live, xyz for teleport spells? also in temp pets? -#define SE_PercentalHeal 147 // implemented -#define SE_StackingCommand_Block 148 // implemented? -#define SE_StackingCommand_Overwrite 149 // implemented? -#define SE_DeathSave 150 // implemented -#define SE_SuspendPet 151 // implemented, @Pet, allow caster to have an extra suspended pet, base: 0=no buffs/items 1=buffs+items, limit: none, max: none -#define SE_TemporaryPets 152 // implemented -#define SE_BalanceHP 153 // implemented -#define SE_DispelDetrimental 154 // implemented, @Dispel, removes only detrimental effects on a target, base: pct chance (950=95%), limit: none, max: none -#define SE_SpellCritDmgIncrease 155 // implemented - no known live spells use this currently -#define SE_IllusionCopy 156 // implemented - Deception -#define SE_SpellDamageShield 157 // implemented, @DS, causes non-melee damage on caster of a spell, base: Amt DS (negative), limit: none, max: unknown (same as base but +) -#define SE_Reflect 158 // implemented, @SpellMisc, reflect casted detrimental spell back at caster, base: chance pct, limit: resist modifier (positive value reduces resists), max: pct of base dmg mod (50=50pct of base) -#define SE_AllStats 159 // implemented -#define SE_MakeDrunk 160 // *not implemented - Effect works entirely client side (Should check against tolerance) -#define SE_MitigateSpellDamage 161 // implemented, @Runes, mitigate incoming spell damage by percentage until rune fades, base: percent mitigation, limit: max dmg absorbed per hit, max: rune amt, Note: If placed on item or AA, will provide stackable percent mitigation. -#define SE_MitigateMeleeDamage 162 // implemented - rune with max value -#define SE_NegateAttacks 163 // implemented -#define SE_AppraiseLDonChest 164 // implemented -#define SE_DisarmLDoNTrap 165 // implemented -#define SE_UnlockLDoNChest 166 // implemented -#define SE_PetPowerIncrease 167 // implemented, @Fc, On Caster, pet power mod, base: value -#define SE_MeleeMitigation 168 // implemented -#define SE_CriticalHitChance 169 // implemented -#define SE_SpellCritChance 170 // implemented -#define SE_CrippBlowChance 171 // implemented -#define SE_AvoidMeleeChance 172 // implemented -#define SE_RiposteChance 173 // implemented -#define SE_DodgeChance 174 // implemented -#define SE_ParryChance 175 // implemented -#define SE_DualWieldChance 176 // implemented -#define SE_DoubleAttackChance 177 // implemented -#define SE_MeleeLifetap 178 // implemented -#define SE_AllInstrumentMod 179 // implemented, @Song, set mod for ALL instrument/singing skills that will be used if higher then item mods, base: mod%, limit: none, max: none -#define SE_ResistSpellChance 180 // implemented -#define SE_ResistFearChance 181 // implemented -#define SE_HundredHands 182 // implemented -#define SE_MeleeSkillCheck 183 // implemented -#define SE_HitChance 184 // implemented -#define SE_DamageModifier 185 // implemented -#define SE_MinDamageModifier 186 // implemented -#define SE_BalanceMana 187 // implemented - Balances party mana -#define SE_IncreaseBlockChance 188 // implemented -#define SE_CurrentEndurance 189 // implemented -#define SE_EndurancePool 190 // implemented -#define SE_Amnesia 191 // implemented - Silence vs Melee Effect -#define SE_Hate 192 // implemented - Instant and hate over time. -#define SE_SkillAttack 193 // implemented, -#define SE_FadingMemories 194 // implemented, @Aggro, Remove from hate lists and make invisible. Can set max level of NPCs that can be affected. base: success chance, limit: max level (ROF2), max: max level (modern client), Note: Support for max level requires Rule (Spells, UseFadingMemoriesMaxLevel) to be true. If used from limit field, then it set as the level, ie. max level of 75 would use limit value of 75. If set from max field, max level 75 would use max value of 1075, if you want to set it so it checks a level range above the spell target then for it to only work on mobs 5 levels or below you set max value to 5. -#define SE_StunResist 195 // implemented -#define SE_StrikeThrough 196 // implemented -#define SE_SkillDamageTaken 197 // implemented -#define SE_CurrentEnduranceOnce 198 // implemented -#define SE_Taunt 199 // implemented - % chance to taunt the target -#define SE_ProcChance 200 // implemented -#define SE_RangedProc 201 // implemented -#define SE_IllusionOther 202 // implemented - Project Illusion -#define SE_MassGroupBuff 203 // implemented -#define SE_GroupFearImmunity 204 // implemented - (Does not use bonus) -#define SE_Rampage 205 // implemented, @Combat Instant, Perform a primary slot combat rounds on all creatures within a 40 foot radius, base: number of attack rounds, limit: max entities hit per round, max: none, Note: AE range is 40 by default. Custom: Set field 'aoe_range' to override default. Adding additional attacks and hit count limit. -#define SE_AETaunt 206 // implemented -#define SE_FleshToBone 207 // implemented -//#define SE_PurgePoison 208 // not used -#define SE_DispelBeneficial 209 // implemented, @Dispel, removes only beneficial effects on a target, base: pct chance (950=95%), limit: none, max: none -#define SE_PetShield 210 // implmented, @ShieldAbility, allows pet to 'shield' owner for 50 pct of damage taken for a duration, base: Time multiplier 1=12 seconds, 2=24 ect, limit: mitigation on pet owner override (not on live), max: mitigation on pet overide (not on live) -#define SE_AEMelee 211 // implemented TO DO: Implement to allow NPC use (client only atm). -#define SE_FrenziedDevastation 212 // implemented - increase spell criticals + all DD spells cast 2x mana. -#define SE_PetMaxHP 213 // implemented[AA] - increases the maximum hit points of your pet -#define SE_MaxHPChange 214 // implemented -#define SE_PetAvoidance 215 // implemented[AA] - increases pet ability to avoid melee damage -#define SE_Accuracy 216 // implemented -#define SE_HeadShot 217 // implemented - ability to head shot (base2 = damage) -#define SE_PetCriticalHit 218 // implemented[AA] - gives pets a baseline critical hit chance -#define SE_SlayUndead 219 // implemented - Allow extra damage against undead (base1 = rate, base2 = damage mod). -#define SE_SkillDamageAmount 220 // implemented -#define SE_Packrat 221 // implemented as bonus -#define SE_BlockBehind 222 // implemented - Chance to block from behind (with our without Shield) -#define SE_DoubleRiposte 223 // implemented - Chance to double riposte [not used on live] -#define SE_GiveDoubleRiposte 224 // implemented[AA] -#define SE_GiveDoubleAttack 225 // implemented[AA] - Allow any class to double attack with set chance. -#define SE_TwoHandBash 226 // *not implemented as bonus -#define SE_ReduceSkillTimer 227 // implemented -#define SE_ReduceFallDamage 228 // implented - reduce the damage that you take from falling -#define SE_PersistantCasting 229 // implemented -#define SE_ExtendedShielding 230 // implemented, @ShieldAbility, extends the range of your /shield ability by an amount of distance, base: distance units, limit: none, max: none -#define SE_StunBashChance 231 // implemented - increase chance to stun from bash. -#define SE_DivineSave 232 // implemented (base1 == % chance on death to insta-res) (base2 == spell cast on save) -#define SE_Metabolism 233 // implemented - Modifies food/drink consumption rates. -#define SE_ReduceApplyPoisonTime 234 // not implemented as bonus - reduces the time to apply poison -#define SE_ChannelChanceSpells 235 // implemented[AA] - chance to channel from SPELLS *No longer used on live. -//#define SE_FreePet 236 // not used -#define SE_GivePetGroupTarget 237 // implemented[AA] - (Pet Affinity) -#define SE_IllusionPersistence 238 // implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed. -#define SE_FeignedCastOnChance 239 // implemented - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you. -//#define SE_StringUnbreakable 240 // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.] -#define SE_ImprovedReclaimEnergy 241 // implemented - increase the amount of mana returned to you when reclaiming your pet. -#define SE_IncreaseChanceMemwipe 242 // implemented - @Memblur, increases the chance to wipe hate with memory blurr, base: chance pct, limit: none, max: none, Note: Mods final blur chance after other bonuses added. -#define SE_CharmBreakChance 243 // implemented - Total Domination -#define SE_RootBreakChance 244 // implemented[AA] reduce the chance that your root will break. -#define SE_TrapCircumvention 245 // implemented, @Traps, decreases the chance that you will set off a trap when opening a chest or other similar container by percentage, base: chance modifer, limit: none, max: none -#define SE_SetBreathLevel 246 // *not implemented as bonus -#define SE_RaiseSkillCap 247 // implemented[AA] - adds skill over the skill cap. -#define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100) -#define SE_SecondaryDmgInc 249 // implemented[AA] Allows off hand weapon to recieve a damage bonus (Sinister Strikes) -#define SE_SpellProcChance 250 // implemented - Increase chance to proc from melee proc spells (ie Spirit of Panther) -#define SE_ConsumeProjectile 251 // implemented[AA] - chance to not consume an arrow (ConsumeProjectile = 100) -#define SE_FrontalBackstabChance 252 // implemented[AA] - chance to perform a full damage backstab from front. -#define SE_FrontalBackstabMinDmg 253 // implemented[AA] - allow a frontal backstab for mininum damage. -#define SE_Blank 254 // implemented -#define SE_ShieldDuration 255 // implemented, , @ShieldAbility, extends the duration of your /shield ability, base: seconds, limit: none, max: none -#define SE_ShroudofStealth 256 // implemented -#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold - official name is GivePetHold -#define SE_TripleBackstab 258 // implemented[AA] - chance to perform a triple backstab -#define SE_CombatStability 259 // implemented[AA] - damage mitigation -#define SE_AddSingingMod 260 // implemented, @Song, set mod for specific instrument/singing skills that will be used if higher then item mods, base: mod%, limit: ItemType ID, max: none -#define SE_SongModCap 261 // implemented, @Song, raise max song modifier cap, base: amt, limit: none, max: none, Note: No longer used on live -#define SE_RaiseStatCap 262 // implemented -#define SE_TradeSkillMastery 263 // implemented - lets you raise more than one tradeskill above master. -#define SE_HastenedAASkill 264 // implemented -#define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled -#define SE_ExtraAttackChance 266 // implemented, @OffBonus, gives your double attacks a percent chance to perform an extra attack with 2-handed primary weapon, base: chance, limit: amt attacks, max: none -#define SE_AddPetCommand 267 // implemented - sets command base2 to base1 -#define SE_ReduceTradeskillFail 268 // implemented - reduces chance to fail with given tradeskill by a percent chance -#define SE_MaxBindWound 269 // implemented[AA] - Increase max HP you can bind wound. -#define SE_BardSongRange 270 // implemented, @Song, increase range of beneficial bard songs, base: mod%, limit: none, max: none , Note: example Sionachie's Crescendo -#define SE_BaseMovementSpeed 271 // implemented[AA] - mods basemove speed, doesn't stack with other move mods -#define SE_CastingLevel2 272 // implemented -#define SE_CriticalDoTChance 273 // implemented -#define SE_CriticalHealChance 274 // implemented -#define SE_CriticalMend 275 // implemented[AA] - chance to critical monk mend -#define SE_Ambidexterity 276 // implemented[AA] - increase chance to duel weild by adding bonus 'skill' -#define SE_UnfailingDivinity 277 // implemented[AA] - ability grants your Death Pact-type spells a second chance to successfully heal their target, also can cause said spells to do a portion of their healing value even on a complete failure. -#define SE_FinishingBlow 278 // implemented[AA] - chance to do massive damage under 10% HP (base1 = chance, base2 = damage) -#define SE_Flurry 279 // implemented -#define SE_PetFlurry 280 // implemented[AA] -#define SE_FeignedMinion 281 // implemented, ability allows you to instruct your pet to feign death via the '/pet feign' command, base: succeed chance, limit: none, max: none, Note: Only implemented as an AA. -#define SE_ImprovedBindWound 282 // implemented[AA] - increase bind wound amount by percent. -#define SE_DoubleSpecialAttack 283 // implemented[AA] - Chance to perform second special attack as monk -//#define SE_LoHSetHeal 284 // not used -#define SE_NimbleEvasion 285 // *not implemented - base1 = 100 for max -#define SE_FcDamageAmt 286 // implemented, @Fc, On Caster, spell damage mod flat amt, base: amt -#define SE_SpellDurationIncByTic 287 // implemented, @Fc, SPA: 287, SE_SpellDurationIncByTic, On Caster, spell buff duration mod, base: tics -#define SE_SkillAttackProc 288 // implemented, @Procs, chance to cast a spell when using a skill, base: chance, limit: skill, max: spellid, note: if used in AA the spell id is set in aa_ranks spell field, chance is calculated as 100% = value 1000. -#define SE_CastOnFadeEffect 289 // implemented - Triggers only if fades after natural duration. -#define SE_IncreaseRunSpeedCap 290 // implemented[AA] - increases run speed over the hard cap -#define SE_Purify 291 // implemented, @Dispel, remove up specified amount of detiremental spells, base: amt removed, limit: none, max: none, Note: excluding charm, fear, resurrection, and revival sickness -#define SE_StrikeThrough2 292 // implemented[AA] - increasing chance of bypassing an opponent's special defenses, such as dodge, block, parry, and riposte. -#define SE_FrontalStunResist 293 // implemented[AA] - Reduce chance to be stunned from front. -- live descriptions sounds like this isn't limited to frontal anymore -#define SE_CriticalSpellChance 294 // implemented - increase chance to critical hit and critical damage modifier. -//#define SE_ReduceTimerSpecial 295 // not used -#define SE_FcSpellVulnerability 296 // implemented, @Fc, On Target, spell damage taken mod pct, base: min pct, limit: max pct -#define SE_FcDamageAmtIncoming 297 // implemetned, @Fc, On Target, damage taken flat amt, base: amt -#define SE_ChangeHeight 298 // implemented -#define SE_WakeTheDead 299 // implemented, @Pets, summon one temporary pet from nearby corpses that last a set duration, base: none, limit: none, max: duration (seconds). Note: max range of corpse is 250. -#define SE_Doppelganger 300 // implemented -#define SE_ArcheryDamageModifier 301 // implemented[AA] - increase archery damage by percent -#define SE_FcDamagePctCrit 302 // implemented, @Fc, On Caster, spell damage mod pct, base: min pct, limit: max pct, Note: applied after critical hits has been calculated. -#define SE_FcDamageAmtCrit 303 // implemented, @Fc, On Caster, spell damage mod flat amt, base: amt -#define SE_OffhandRiposteFail 304 // implemented as bonus - enemy cannot riposte offhand attacks -#define SE_MitigateDamageShield 305 // implemented - off hand attacks only (Shielding Resistance) -#define SE_ArmyOfTheDead 306 // implemented, @Pets, summon multiple temporary pets from nearby corpses that last a set duration, base: amount of corpses that a pet can summon from, limit: none, max: duration (seconds). Note: max range of corpse is 250. -//#define SE_Appraisal 307 // *not implemented Rogue AA - This ability allows you to estimate the selling price of an item you are holding on your cursor. -#define SE_ZoneSuspendMinion 308 // implemented, @Pet, allow suspended pets to be resummoned upon zoning, base: 1, limit: none, max: none, Calc: Bool -#define SE_GateCastersBindpoint 309 // implemented - Gate to casters bind point -#define SE_ReduceReuseTimer 310 // implemented, @Fc, On Caster, spell and disc reuse time mod by amount, base: milliseconds -#define SE_LimitCombatSkills 311 // implemented, @Ff, Include or exclude combat skills or procs from being focused, base1: 0=Exclude if proc 1=Allow only if proc. -#define SE_Sanctuary 312 // implemented - Places caster at bottom hate list, effect fades if cast cast spell on targets other than self. -#define SE_ForageAdditionalItems 313 // implemented[AA] - chance to forage additional items -#define SE_Invisibility2 314 // implemented - fixed duration invisible -#define SE_InvisVsUndead2 315 // implemented - fixed duration ITU -#define SE_ImprovedInvisAnimals 316 // implemented -#define SE_ItemHPRegenCapIncrease 317 // implemented[AA] - increases amount of health regen gained via items -#define SE_ItemManaRegenCapIncrease 318 // implemented - increases amount of mana regen you can gain via items -#define SE_CriticalHealOverTime 319 // implemented -#define SE_ShieldBlock 320 // implemented - Block attacks with shield -#define SE_ReduceHate 321 // implemented -#define SE_GateToHomeCity 322 // implemented -#define SE_DefensiveProc 323 // implemented -#define SE_HPToMana 324 // implemented -#define SE_NoBreakAESneak 325 // implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell. -#define SE_SpellSlotIncrease 326 // *not implemented as bonus - increases your spell slot availability -#define SE_MysticalAttune 327 // implemented - increases amount of buffs that a player can have -#define SE_DelayDeath 328 // implemented - increases how far you can fall below 0 hp before you die -#define SE_ManaAbsorbPercentDamage 329 // implemented -#define SE_CriticalDamageMob 330 // implemented -#define SE_Salvage 331 // implemented - chance to recover items that would be destroyed in failed tradeskill combine -#define SE_SummonToCorpse 332 // *not implemented AA - Call of the Wild (Druid/Shaman Res spell with no exp) TOOD: implement this. -#define SE_CastOnRuneFadeEffect 333 // implemented -#define SE_BardAEDot 334 // implemented -#define SE_BlockNextSpellFocus 335 // implemented, @Fc, On Caster, chance to block next spell, base: chance -//#define SE_IllusionaryTarget 336 // not used -#define SE_PercentXPIncrease 337 // implemented -#define SE_SummonAndResAllCorpses 338 // implemented -#define SE_TriggerOnCast 339 // implemented, @Fc, On Caster, cast on spell use, base: chance pct limit: spellid -#define SE_SpellTrigger 340 // implemented - chance to trigger spell [Share rolls with 469] All base2 spells share roll chance, only 1 cast. -#define SE_ItemAttackCapIncrease 341 // implemented[AA] - increases the maximum amount of attack you can gain from items. -#define SE_ImmuneFleeing 342 // implemented - stop mob from fleeing -#define SE_InterruptCasting 343 // implemented - % chance to interrupt spells being cast every tic. Cacophony (8272) -#define SE_ChannelChanceItems 344 // implemented[AA] - chance to not have ITEM effects interrupted when you take damage. -#define SE_AssassinateLevel 345 // implemented as bonus - AA Assisination max level to kill -#define SE_HeadShotLevel 346 // implemented[AA] - HeadShot max level to kill -#define SE_DoubleRangedAttack 347 // implemented - chance at an additional archery attack (consumes arrow) -#define SE_LimitManaMin 348 // implemented, @Ff, Mininum mana of spell that can be focused, base1: mana amt -#define SE_ShieldEquipDmgMod 349 // implemented[AA] Increase melee base damage (indirectly increasing hate) when wearing a shield. -#define SE_ManaBurn 350 // implemented - Drains mana for damage/heal at a defined ratio up to a defined maximum amount of mana. -#define SE_PersistentEffect 351 // *not implemented. creates a trap/totem that casts a spell (spell id + base1?) when anything comes near it. can probably make a beacon for this -#define SE_IncreaseTrapCount 352 // *not implemented - looks to be some type of invulnerability? Test ITC (8755) -#define SE_AdditionalAura 353 // *not implemented - allows use of more than 1 aura, aa effect -//#define SE_DeactivateAllTraps 354 // *not implemented - looks to be some type of invulnerability? Test DAT (8757) -//#define SE_LearnTrap 355 // *not implemented - looks to be some type of invulnerability? Test LT (8758) -//#define SE_ChangeTriggerType 356 // not used -#define SE_FcMute 357 // implemented, @Fc, On Caster, prevents spell casting, base: chance pct -#define SE_CurrentManaOnce 358 // implemented -//#define SE_PassiveSenseTrap 359 // *not implemented - Invulnerability (Brell's Blessing) -#define SE_ProcOnKillShot 360 // implemented - a buff that has a base1 % to cast spell base2 when you kill a "challenging foe" base3 min level -#define SE_SpellOnDeath 361 // implemented - casts spell on death of buffed -#define SE_PotionBeltSlots 362 // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank. -#define SE_BandolierSlots 363 // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank. -#define SE_TripleAttackChance 364 // implemented -#define SE_ProcOnSpellKillShot 365 // implemented - chance to trigger a spell on kill when the kill is caused by a specific spell with this effect in it (10470 Venin) -//#define SE_GroupShielding 366 // *not implemented[AA] This gives you /shieldgroup -#define SE_SetBodyType 367 // implemented - set body type of base1 so it can be affected by spells that are limited to that type (Plant, Animal, Undead, etc) -//#define SE_FactionMod 368 // *not implemented - increases faction with base1 (faction id, live won't match up w/ ours) by base2 -#define SE_CorruptionCounter 369 // implemented -#define SE_ResistCorruption 370 // implemented -#define SE_AttackSpeed4 371 // implemented - stackable slow effect 'Inhibit Melee' -#define SE_ForageSkill 372 // implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not. -#define SE_CastOnFadeEffectAlways 373 // implemented - Triggers if fades after natural duration OR from rune/numhits fades. -#define SE_ApplyEffect 374 // implemented -#define SE_DotCritDmgIncrease 375 // implemented - Increase damage of DoT critical amount -//#define SE_Fling 376 // *not implemented - used in 2 test spells (12945 | Movement Test Spell 1) -#define SE_CastOnFadeEffectNPC 377 // implemented - Triggers only if fades after natural duration (On live these are usually players spells that effect an NPC). -#define SE_SpellEffectResistChance 378 // implemented - Increase chance to resist specific spell effect (base1=value, base2=spell effect id) -#define SE_ShadowStepDirectional 379 // implemented - handled by client -#define SE_Knockdown 380 // implemented - small knock back(handled by client) -//#define SE_KnockTowardCaster 381 // *not implemented (Call of Hither) knocks you back to caster (value) distance units infront -#define SE_NegateSpellEffect 382 // implemented, @Debuff, negates specific spell effect benefits for the duration of the debuff and prevent non-duration spell effect from working, base: see NegateSpellEffecttype Enum, limit: SPA id, max: none -#define SE_SympatheticProc 383 // implemented, @Fc, On Caster, cast on spell use, base: variable proc chance on cast time, limit: spellid -#define SE_Leap 384 // implemented - Leap effect, ie stomping leap -#define SE_LimitSpellGroup 385 // implemented, @Ff, Spell group(s) that a spell focus can require or exclude, base1: spellgroup id, Include: Positive Exclude: Negative -#define SE_CastOnCurer 386 // implemented - Casts a spell on the person curing -#define SE_CastOnCure 387 // implemented - Casts a spell on the cured person -#define SE_SummonCorpseZone 388 // implemented - summons a corpse from any zone(nec AA) -#define SE_FcTimerRefresh 389 // implemented, @Fc, On Caster, reset all recast timers, base: 1, Note: Applied from casted spells only -#define SE_FcTimerLockout 390 // implemented, @Fc, On Caster, set a spell to be on recast timer, base: recast duration milliseconds, Note: Applied from casted spells only -#define SE_LimitManaMax 391 // implemented, @Ff, Mininum mana of spell that can be focused, base1: mana amt -#define SE_FcHealAmt 392 // implemented, @Fc, On Caster, spell healing mod flat amt, base: amt -#define SE_FcHealPctIncoming 393 // implemented, @Fc, On Target, heal received mod pct, base: pct, limit: random max pct -#define SE_FcHealAmtIncoming 394 // implemented, @Fc, On Target, heal received mod flat amt, base: amt -#define SE_FcHealPctCritIncoming 395 // implemented, @Fc, On Target, heal received mod pct, base: pct, limit: random max pct -#define SE_FcHealAmtCrit 396 // implemented, @Fc, On Caster, spell healing mod flat amt, base: amt -#define SE_PetMeleeMitigation 397 // implemented[AA] - additional mitigation to your pets. Adds AC -#define SE_SwarmPetDuration 398 // implemented - Affects the duration of swarm pets -#define SE_FcTwincast 399 // implemented - cast 2 spells for every 1 -#define SE_HealGroupFromMana 400 // implemented - Drains mana and heals for each point of mana drained -#define SE_ManaDrainWithDmg 401 // implemented - Deals damage based on the amount of mana drained -#define SE_EndDrainWithDmg 402 // implemented - Deals damage for the amount of endurance drained -#define SE_LimitSpellClass 403 // implemented, @Ff, 'Spell Category' using table field 'spell_class' that a spell focus can require or exclude, base1: category type, Include: Positive Exclude: Negative -#define SE_LimitSpellSubclass 404 // implemented, @Ff, 'Spell Category Subclass' using table field 'spell_subclass' that a spell focus can require or exclude, base1: category type, Include: Positive Exclude: Negative -#define SE_TwoHandBluntBlock 405 // implemented - chance to block attacks when using two hand blunt weapons (similiar to shield block) -#define SE_CastonNumHitFade 406 // implemented - casts a spell when a buff fades due to its numhits being depleted -#define SE_CastonFocusEffect 407 // implemented - casts a spell if focus limits are met (ie triggers when a focus effects is applied) -#define SE_LimitHPPercent 408 // implemented - limited to a certain percent of your hp(ie heals up to 50%) -#define SE_LimitManaPercent 409 // implemented - limited to a certain percent of your mana -#define SE_LimitEndPercent 410 // implemented - limited to a certain percent of your end -#define SE_LimitClass 411 // implemented, @Ff, Class(es) that can use the spell focus, base1: class(es), Note: The class value in dbase is +1 in relation to item class value, set as you would item for multiple classes -#define SE_LimitRace 412 // implemented, @Ff, Race that can use the spell focus, base1: race, Note: not used in any known live spells. Use only single race at a time. -#define SE_FcBaseEffects 413 // implemented, @Fc, On Caster, base spell effectiveness mod pct, base: pct -#define SE_LimitCastingSkill 414 // implemented, @Ff, Spell and singing skills(s) that a spell focus can require or exclude, base1: skill id, Include: Positive Exclude: Negative -#define SE_FFItemClass 415 // implemented, @Ff, Limits focuses to be applied only from item click. base1: item ItemType (-1 to include for all ItemTypes,-1000 to exclude clicks from getting the focus, or exclude specific SubTypes or Slots if set), limit: item SubType (-1 for all SubTypes), max: item Slots (bitmask of valid slots, -1 ALL slots), Note: not used on live. See comments in Mob::CalcFocusEffect for more details. -#define SE_ACv2 416 // implemented - New AC spell effect -#define SE_ManaRegen_v2 417 // implemented - New mana regen effect -#define SE_SkillDamageAmount2 418 // implemented - adds skill damage directly to certain attacks -#define SE_AddMeleeProc 419 // implemented - Adds a proc -#define SE_FcLimitUse 420 // implemented, @Fc, On Caster, numhits mod pct, base: pct, Note: not used in any known live spells -#define SE_FcIncreaseNumHits 421 // implemented, @Fc, On Caster, numhits mod flat amt, base: amt -#define SE_LimitUseMin 422 // implemented, @Ff Minium amount of numhits for a spell to be focused, base: numhit amt -#define SE_LimitUseType 423 // implemented, @Ff Focus will only affect if has this numhits type, base: numhit type -#define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace -#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626) -#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window -#define SE_SkillProcAttempt 427 // implemented - chance to proc when using a skill(ie taunt) -#define SE_LimitToSkill 428 // implemented, @Procs, limits what combat skills will effect a skill proc, base: skill value, limit: none, max: none -#define SE_SkillProcSuccess 429 // implemented - chance to proc when tje skill in use successfully fires. -//#define SE_PostEffect 430 // *not implemented - Fear of the Dark(27641) - Alters vision -//#define SE_PostEffectData 431 // *not implemented - Fear of the Dark(27641) - Alters vision -//#define SE_ExpandMaxActiveTrophyBen 432 // not used -#define SE_CriticalDotDecay 433 // implemented - increase critical dot chance, effect decays based on level of spell it effects. (12266) -#define SE_CriticalHealDecay 434 // implemented - increase critical heal chance, effect decays based on level of spell it effects. -#define SE_CriticalRegenDecay 435 // implemented - increase critical heal over time chance, effect decays based on level of spell it effects. -//#define SE_BeneficialCountDownHold 436 // not used ( 23491 | ABTest Buff Hold) -//#define SE_TeleporttoAnchor 437 // *not implemented - Teleport Guild Hall Anchor(33099) -//#define SE_TranslocatetoAnchor 438 // *not implemented - Translocate Primary Anchor (27750) -#define SE_Assassinate 439 // implemented[AA] - Assassinate damage -#define SE_FinishingBlowLvl 440 // implemented[AA] - Sets the level Finishing blow can be triggered on an NPC -#define SE_DistanceRemoval 441 // implemented - Buff is removed from target when target moves X amount of distance away from where initially hit. -#define SE_TriggerOnReqTarget 442 // implemented, @SpellTrigger, triggers a spell when Target Requirement conditions are met (see enum SpellRestriction for IDs), base: spellid, limit: SpellRestriction ID, max: none, Note: Usually cast on a target -#define SE_TriggerOnReqCaster 443 // implemented, @SpellTrigger, triggers a spell when Caster Requirement conditions are met (see enum SpellRestriction for IDs), base: spellid, limit: SpellRestriction ID, max: none, Note: Usually self only -#define SE_ImprovedTaunt 444 // implemented - Locks Aggro On Caster and Decrease other Players Aggro by X% on NPC targets below level Y -//#define SE_AddMercSlot 445 // *not implemented[AA] - [Hero's Barracks] Allows you to conscript additional mercs. -#define SE_AStacker 446 // implementet - bufff stacking blocker (26219 | Qirik's Watch) -#define SE_BStacker 447 // implemented -#define SE_CStacker 448 // implemented -#define SE_DStacker 449 // implemented -#define SE_MitigateDotDamage 450 // implemented, @Runes, mitigate incoming dot damage by percentage until rune fades, base: percent mitigation, limit: max dmg absorbed per hit, max: rune amt, Note: If placed on item or AA, will provide stackable percent mitigation. -#define SE_MeleeThresholdGuard 451 // implemented Partial Melee Rune that only is lowered if melee hits are over X amount of damage -#define SE_SpellThresholdGuard 452 // implemented Partial Spell Rune that only is lowered if spell hits are over X amount of damage -#define SE_TriggerMeleeThreshold 453 // implemented Trigger effect on X amount of melee damage taken in a single hit -#define SE_TriggerSpellThreshold 454 // implemented Trigger effect on X amount of spell damage taken in a single hit -#define SE_AddHatePct 455 // implemented Modify total hate by % -#define SE_AddHateOverTimePct 456 // implemented Modify total hate by % over time. -#define SE_ResourceTap 457 // implemented Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end. -#define SE_FactionModPct 458 // implemented Modifies faction gains and losses by percent. -#define SE_DamageModifier2 459 // implemented - Modifies melee damage by skill type -#define SE_Ff_Override_NotFocusable 460 // implemented, @Fc, Allow spell to be focused event if flagged with 'not_focusable' in spell table, base: 1 -#define SE_ImprovedDamage2 461 // implemented, @Fc, On Caster, spell damage mod pct, base: min pct, limit: max pct -#define SE_FcDamageAmt2 462 // implemented, @Fc, On Caster, spell damage mod flat amt, base: amt -#define SE_Shield_Target 463 // implemented, Base1 % damage shielded on target -#define SE_PC_Pet_Rampage 464 // implemented - Base1 % chance to do rampage for base2 % of damage each melee round -#define SE_PC_Pet_AE_Rampage 465 // implemented - Base1 % chance to do AE rampage for base2 % of damage each melee round -#define SE_PC_Pet_Flurry_Chance 466 // implemented - Base1 % chance to do flurry from double attack hit. -#define SE_DS_Mitigation_Amount 467 // implemented - Modify incoming damage shield damage by a flat amount -#define SE_DS_Mitigation_Percentage 468 // implemented - Modify incoming damage shield damage by percentage -#define SE_Chance_Best_in_Spell_Grp 469 // implemented - Chance to cast highest scribed spell within a spell group. All base2 spells share roll chance, only 1 cast. -#define SE_Trigger_Best_in_Spell_Grp 470 // implemented - Chance to cast highest scribed spell within a spell group. Each spell has own chance. -#define SE_Double_Melee_Round 471 // implemented, @OffBonus, percent chance to repeat primary weapon round with a percent damage modifier, base: pct chance repeat, limit: pct dmg mod, max: none -#define SE_Buy_AA_Rank 472 // implemented, @Special, Used in AA abilities that have Enable/Disable toggle. Spell on Disabled Rank has this effect in it, base: 1, limit: none, max: none, Note: This will not just buy an AA -#define SE_Double_Backstab_Front 473 // implemented - Chance to double backstab from front -#define SE_Pet_Crit_Melee_Damage_Pct_Owner 474 // implemenetd - Critical damage mod applied to pets from owner -#define SE_Trigger_Spell_Non_Item 475 // implemented - Trigger spell on cast only if not from item click. -#define SE_Weapon_Stance 476 // implemented, @Misc, Apply a specific spell buffs automatically depending 2Hander, Shield or Dual Wield is equipped, base: spellid, base: 0=2H 1=Shield 2=DW, max: none -#define SE_Hatelist_To_Top_Index 477 // Implemented - Chance to be set to top of rampage list -#define SE_Hatelist_To_Tail_Index 478 // Implemented - Chance to be set to bottom of rampage list -#define SE_Ff_Value_Min 479 // implemented, @Ff, Minimum base value of a spell that can be focused, base: spells to be focused base1 value -#define SE_Ff_Value_Max 480 // implemented, @Ff, Max base value of a spell that can be focused, base: spells to be focused base1 value -#define SE_Fc_Cast_Spell_On_Land 481 // implemented, @Fc, On Target, cast spell if hit by spell, base: chance pct, limit: spellid -#define SE_Skill_Base_Damage_Mod 482 // implemented, @OffBonus, modify base melee damage by percent, base: pct, limit: skill(-1=ALL), max: none -#define SE_Fc_Spell_Damage_Pct_IncomingPC 483 // implemented, @Fc, On Target, spell damage taken mod pct, base: min pct, limit: max pct -#define SE_Fc_Spell_Damage_Amt_IncomingPC 484 // implemented, @Fc, On Target, damage taken flat amt, base: amt -#define SE_Ff_CasterClass 485 // implemented, @Ff, Caster of spell on target with a focus effect that is checked by incoming spells must be specified class(es). base1: class(es), Note: Set multiple classes same as would for items -#define SE_Ff_Same_Caster 486 // implemented, @Ff, Caster of spell on target with a focus effect that is checked by incoming spells, base1: 0=Must be different caster 1=Must be same caster -//#define SE_Extend_Tradeskill_Cap 487 // -//#define SE_Defender_Melee_Force_Pct_PC 488 // -#define SE_Worn_Endurance_Regen_Cap 489 // implemented, modify worn regen cap, base: amt, limit: none, max: none -#define SE_Ff_ReuseTimeMin 490 // implemented, @Ff, Minimum recast time of a spell that can be focused, base: recast time -#define SE_Ff_ReuseTimeMax 491 // implemented, @Ff, Max recast time of a spell that can be focused, base: recast time -#define SE_Ff_Endurance_Min 492 // implemented, @Ff, Minimum endurance cost of a spell that can be focused, base: endurance cost -#define SE_Ff_Endurance_Max 493 // implemented, @Ff, Max endurance cost of a spell that can be focused, base: endurance cost -#define SE_Pet_Add_Atk 494 // implemented - Bonus on pet owner which gives their pet increased attack stat -#define SE_Ff_DurationMax 495 // implemented, @Ff, Max duration of spell that can be focused, base: tics -#define SE_Critical_Melee_Damage_Mod_Max 496 // implemented - increase or decrease by percent critical damage (not stackable) -//#define SE_Ff_FocusCastProcNoBypass 497 // -#define SE_AddExtraAttackPct_1h_Primary 498 // implemented, @OffBonus, gives your double attacks a percent chance to perform an extra attack with 1-handed primary weapon, base: chance, limit: amt attacks, max: none -#define SE_AddExtraAttackPct_1h_Secondary 499 //implemented, @OffBonus, gives your double attacks a percent chance to perform an extra attack with 1-handed secondary weapon, base: chance, limit: amt attacks, max: none -#define SE_Fc_CastTimeMod2 500 // implemented, @Fc, On Caster, cast time mod pct, base: pct, Note: Can reduce to instant cast -#define SE_Fc_CastTimeAmt 501 // implemented, @Fc, On Caster, cast time mod flat amt, base: milliseconds, Note: Can reduce to instant cast -#define SE_Fearstun 502 // implemented - Stun with a max level limit. Normal stun restrictions don't apply. -#define SE_Melee_Damage_Position_Mod 503 // implemented, @OffBonus, modify melee damage by percent if done from Front or Behind opponent, base: pct, limit: 0=back 1=front, max: none -#define SE_Melee_Damage_Position_Amt 504 // implemented, @OffBonus, modify melee damage by flat amount if done from Front or Behind opponent, base: amt, limit: 0=back 1=front, max: none -#define SE_Damage_Taken_Position_Mod 505 // implemented, @DefBonus, modify melee damage by percent if dmg taken from Front or Behind, base: pct, limit: 0=back 1=front, max: none -#define SE_Damage_Taken_Position_Amt 506 // implemented -@DefBonus, modify melee damage by flat amount if dmg taken from your Front or Behind, base: amt, limit: 0=back 1=front, max: none -#define SE_Fc_Amplify_Mod 507 // implemented, @Fc, On Caster, damage-heal-dot mod pct, base: pct -#define SE_Fc_Amplify_Amt 508 // implemented, @Fc, On Caster, damage-heal-dot mod flat amt, base: amt -#define SE_Health_Transfer 509 // implemented - exchange health for damage or healing on a target. ie Lifeburn/Act of Valor -#define SE_Fc_ResistIncoming 510 // implemented, @Fc, On Target, resist modifier, base: amt -#define SE_Ff_FocusTimerMin 511 // implemented, @Ff, sets a recast time until focus can be used again, base: 1, limit: time ms, Note: ie. limit to 1 trigger every 1.5 seconds -#define SE_Proc_Timer_Modifier 512 // implemented - limits procs per amount of a time based on timer value, base: 1, limit: time ms, Note:, ie limit to 1 proc every 55 seconds) -//#define SE_Mana_Max_Percent 513 // -//#define SE_Endurance_Max_Percent 514 // -#define SE_AC_Avoidance_Max_Percent 515 // implemented - stackable avoidance modifier -#define SE_AC_Mitigation_Max_Percent 516 // implemented - stackable defense modifier -//#define SE_Attack_Offense_Max_Percent 517 // -#define SE_Attack_Accuracy_Max_Percent 518 // implemented - stackable accurary modifer -//#define SE_Luck_Amount 519 // -//#define SE_Luck_Percent 520 // -#define SE_Endurance_Absorb_Pct_Damage 521 // implemented - Reduces % of Damage using Endurance, drains endurance at a ratio (ie. 0.05 Endurance per Hit Point) -#define SE_Instant_Mana_Pct 522 // implemented - Increase/Decrease mana by percent of max mana -#define SE_Instant_Endurance_Pct 523 // implemented - Increase/Decrease mana by percent of max endurance -#define SE_Duration_HP_Pct 524 // implemented - Decrease Current Hit Points by % of Total Hit Points per Tick, up to a MAX per tick -#define SE_Duration_Mana_Pct 525 // implemented - Decrease Current Mana by % of Total Mana per Tick, up to a MAX per tick -#define SE_Duration_Endurance_Pct 526 // implemented - Decrease Current Endurance by % of Total Hit Points per Tick, up to a MAX per tick - - -// LAST +namespace SpellEffect { + constexpr int CurrentHP = 0; // implemented - Heals and nukes, repeates every tic if in a buff + constexpr int ArmorClass = 1; // implemented + constexpr int ATK = 2; // implemented + constexpr int MovementSpeed = 3; // implemented - SoW, SoC, etc + constexpr int STR = 4; // implemented + constexpr int DEX = 5; // implemented + constexpr int AGI = 6; // implemented + constexpr int STA = 7; // implemented + constexpr int INT = 8; // implemented + constexpr int WIS = 9; // implemented + constexpr int CHA = 10; // implemented - used as a spacer + constexpr int AttackSpeed = 11; // implemented + constexpr int Invisibility = 12; // implemented - TO DO: Implemented Invisiblity Levels + constexpr int SeeInvis = 13; // implemented - TO DO: Implemented See Invisiblity Levels + constexpr int WaterBreathing = 14; // implemented + constexpr int CurrentMana = 15; // implemented + constexpr int NPCFrenzy = 16; // not used + constexpr int NPCAwareness = 17; // not used + constexpr int Lull = 18; // implemented - Reaction Radius + constexpr int AddFaction = 19; // implemented - Alliance line + constexpr int Blind = 20; // implemented + constexpr int Stun = 21; // implemented + constexpr int Charm = 22; // implemented + constexpr int Fear = 23; // implemented + constexpr int Stamina = 24; // implemented - Invigor and such + constexpr int BindAffinity = 25; // implemented - TO DO: Implement 2nd and 3rd Recall (value 2,3 ect). Sets additional bind points. + constexpr int Gate = 26; // implemented - Gate to bind point + constexpr int CancelMagic = 27; // implemented + constexpr int InvisVsUndead = 28; // implemented + constexpr int InvisVsAnimals = 29; // implemented + constexpr int ChangeFrenzyRad = 30; // implemented - Pacify + constexpr int Mez = 31; // implemented + constexpr int SummonItem = 32; // implemented + constexpr int SummonPet = 33; // implemented + constexpr int Confuse = 34; // not used (Nimbus of Temporal Rifting) ? + constexpr int DiseaseCounter = 35; // implemented + constexpr int PoisonCounter = 36; // implemented + constexpr int DetectHostile = 37; // not used + constexpr int DetectMagic = 38; // not used + constexpr int TwinCastBlocker = 39; // implemented - If present in spell, then the spell can not be twincast. + constexpr int DivineAura = 40; // implemented + constexpr int Destroy = 41; // implemented - Disintegrate, Banishment of Shadows + constexpr int ShadowStep = 42; // implemented + constexpr int Berserk = 43; // implemented (*not used in any known live spell) Makes client 'Berserk' giving crip blow chance. + constexpr int Lycanthropy = 44; // implemented + constexpr int Vampirism = 45; // implemented (*not used in any known live spell) Stackable lifetap from melee. + constexpr int ResistFire = 46; // implemented + constexpr int ResistCold = 47; // implemented + constexpr int ResistPoison = 48; // implemented + constexpr int ResistDisease = 49; // implemented + constexpr int ResistMagic = 50; // implemented + constexpr int DetectTraps = 51; // not used + constexpr int SenseDead = 52; // implemented + constexpr int SenseSummoned = 53; // implemented + constexpr int SenseAnimals = 54; // implemented + constexpr int Rune = 55; // implemented + constexpr int TrueNorth = 56; // implemented + constexpr int Levitate = 57; // implemented + constexpr int Illusion = 58; // implemented + constexpr int DamageShield = 59; // implemented + constexpr int TransferItem = 60; // not used + constexpr int Identify = 61; // implemented + constexpr int ItemID = 62; // not used + constexpr int WipeHateList = 63; // implemented, @Memblur, chance to wipe hate list of target, base: pct chance, limit: none, max: ? (not implemented), Note: caster level and CHA add to pct chance + constexpr int SpinTarget = 64; // implemented - TO DO: Not sure stun portion is working correctly + constexpr int InfraVision = 65; // implemented + constexpr int UltraVision = 66; // implemented + constexpr int EyeOfZomm = 67; // implemented + constexpr int ReclaimPet = 68; // implemented + constexpr int TotalHP = 69; // implemented + constexpr int CorpseBomb = 70; // not used + constexpr int NecPet = 71; // implemented + constexpr int PreserveCorpse = 72; // not used + constexpr int BindSight = 73; // implemented, @Vision, see through the eyes of your target, click off buff to end effect, base: 1, limit: none, max: none + constexpr int FeignDeath = 74; // implemented + constexpr int VoiceGraft = 75; // implemented + constexpr int Sentinel = 76; // *not implemented?(just seems to send a message) + constexpr int LocateCorpse = 77; // implemented + constexpr int AbsorbMagicAtt = 78; // implemented - Rune for spells + constexpr int CurrentHPOnce = 79; // implemented - Heals and nukes, non-repeating if in a buff + constexpr int EnchantLight = 80; // not used + constexpr int Revive = 81; // implemented - Resurrect + constexpr int SummonPC = 82; // implemented + constexpr int Teleport = 83; // implemented + constexpr int TossUp = 84; // implemented - Gravity Flux + constexpr int WeaponProc = 85; // implemented - i.e. Call of Fire + constexpr int Harmony = 86; // implemented + constexpr int MagnifyVision = 87; // implemented - Telescope + constexpr int Succor = 88; // implemented - Evacuate/Succor lines + constexpr int ModelSize = 89; // implemented - Shrink, Growth + constexpr int Cloak = 90; // *not implemented - Used in only 2 spells + constexpr int SummonCorpse = 91; // implemented + constexpr int InstantHate = 92; // implemented - add hate + constexpr int StopRain = 93; // implemented - Wake of Karana + constexpr int NegateIfCombat = 94; // implemented + constexpr int Sacrifice = 95; // implemented + constexpr int Silence = 96; // implemented + constexpr int ManaPool = 97; // implemented + constexpr int AttackSpeed2 = 98; // implemented - Melody of Ervaj + constexpr int Root = 99; // implemented + constexpr int HealOverTime = 100; // implemented + constexpr int CompleteHeal = 101; // implemented + constexpr int Fearless = 102; // implemented - Valiant Companion + constexpr int CallPet = 103; // implemented - Summon Companion + constexpr int Translocate = 104; // implemented + constexpr int AntiGate = 105; // implemented - Translocational Anchor + constexpr int SummonBSTPet = 106; // implemented + constexpr int AlterNPCLevel = 107; // implemented - not used on live + constexpr int Familiar = 108; // implemented + constexpr int SummonItemIntoBag = 109; // implemented - summons stuff into container + constexpr int IncreaseArchery = 110; // implemented + constexpr int ResistAll = 111; // implemented - Note: Physical Resists are not modified by this effect. + constexpr int CastingLevel = 112; // implemented + constexpr int SummonHorse = 113; // implemented + constexpr int ChangeAggro = 114; // implemented - Hate modifing buffs(ie horrifying visage) + constexpr int Hunger = 115; // implemented - Song of Sustenance + constexpr int CurseCounter = 116; // implemented + constexpr int MagicWeapon = 117; // implemented - makes weapon magical + constexpr int Amplification = 118; // implemented, @Song, stackable singing mod, base: mod%, limit: none, max: none, Note: Can focus itself. + constexpr int AttackSpeed3 = 119; // implemented + constexpr int HealRate = 120; // implemented - reduces healing by a % + constexpr int ReverseDS = 121; // implemented + constexpr int ReduceSkill = 122; // implemented - base: skill id, limit: none, max: none, formula: % skill is reduced (positive) + constexpr int Screech = 123; // implemented Spell Blocker(If have buff with value +1 will block any effect with -1) + constexpr int ImprovedDamage = 124; // implemented + constexpr int ImprovedHeal = 125; // implemented + constexpr int SpellResistReduction = 126; // implemented + constexpr int IncreaseSpellHaste = 127; // implemented, @Fc, On Caster, cast time mod pct, base: pct + constexpr int IncreaseSpellDuration = 128; // implemented, @Fc, On Caster, spell duration mod pct, base: pct + constexpr int IncreaseRange = 129; // implemented, @Fc, On Caster, spell range mod pct, base: pct + constexpr int SpellHateMod = 130; // implemented, @Fc, On Caster, spell hate mod pct, base: min pct, limit: max pct + constexpr int ReduceReagentCost = 131; // implemented, @Fc, On Caster, do not consume reagent pct chance, base: min pct, limit: max pct + constexpr int ReduceManaCost = 132; // implemented, @Fc, On Caster, reduce mana cost by pct, base: min pct, limt: max pct + constexpr int FcStunTimeMod = 133; // implemented, @Fc, On Caster, spell range mod pct, base: pct + constexpr int LimitMaxLevel = 134; // implemented, @Ff, Max level of spell that can be focused, if base2 then decrease effectiviness by base2 % per level over max, base: lv, base2: effectiveness pct + constexpr int LimitResist = 135; // implemented, @Ff, Resist Type(s) that a spell focus can require or exclude, base1: resist type, Include: Positive Exclude: Negative + constexpr int LimitTarget = 136; // implemented, @Ff, Target Type(s) that a spell focus can require or exclude, base1: target type, Include: Positive Exclude: Negative + constexpr int LimitEffect = 137; // implemented, @Ff, Spell effect(s) that a spell focus can require or exclude, base1: SPA id, Include: Positive Exclude: Negative + constexpr int LimitSpellType = 138; // implemented, @Ff, Only allow focus spells that are Beneficial or Detrimental, base1: 0=det 1=bene + constexpr int LimitSpell = 139; // implemented, @Ff, Specific spell id(s) that a spell focus can require or exclude, base1: SPA id, Include: Positive Exclude: Negative + constexpr int LimitMinDur = 140; // implemented, @Ff, Mininum duration of spell that can be focused, base1: tics + constexpr int LimitInstant = 141; // implemented, @Ff, Include or exclude if an isntant cast spell can be focused, base1: 0=Exclude if Instant 1=Allow only if Instant + constexpr int LimitMinLevel = 142; // implemented, @Ff, Mininum level of spell that can be focused, base1: lv + constexpr int LimitCastTimeMin = 143; // implemented, @Ff, Mininum cast time of spell that can be focused, base1: milliseconds + constexpr int LimitCastTimeMax = 144; // implemented, @Ff, Max cast time of spell that can be focused, base1: milliseconds + constexpr int Teleport2 = 145; // implemented - Banishment of the Pantheon + constexpr int ElectricityResist = 146; // *not implemented TODO: Now used on live, xyz for teleport spells? also in temp pets? + constexpr int PercentalHeal = 147; // implemented + constexpr int StackingCommand_Block = 148; // implemented? + constexpr int StackingCommand_Overwrite = 149; // implemented? + constexpr int DeathSave = 150; // implemented + constexpr int SuspendPet = 151; // implemented, @Pet, allow caster to have an extra suspended pet, base: 0=no buffs/items 1=buffs+items, limit: none, max: none + constexpr int TemporaryPets = 152; // implemented + constexpr int BalanceHP = 153; // implemented + constexpr int DispelDetrimental = 154; // implemented, @Dispel, removes only detrimental effects on a target, base: pct chance (950=95%), limit: none, max: none + constexpr int SpellCritDmgIncrease = 155; // implemented - no known live spells use this currently + constexpr int IllusionCopy = 156; // implemented - Deception + constexpr int SpellDamageShield = 157; // implemented, @DS, causes non-melee damage on caster of a spell, base: Amt DS (negative), limit: none, max: unknown (same as base but +) + constexpr int Reflect = 158; // implemented, @SpellMisc, reflect casted detrimental spell back at caster, base: chance pct, limit: resist modifier (positive value reduces resists), max: pct of base dmg mod (50=50pct of base) + constexpr int AllStats = 159; // implemented + constexpr int MakeDrunk = 160; // *not implemented - Effect works entirely client side (Should check against tolerance) + constexpr int MitigateSpellDamage = 161; // implemented, @Runes, mitigate incoming spell damage by percentage until rune fades, base: percent mitigation, limit: max dmg absorbed per hit, max: rune amt, Note: If placed on item or AA, will provide stackable percent mitigation. + constexpr int MitigateMeleeDamage = 162; // implemented - rune with max value + constexpr int NegateAttacks = 163; // implemented + constexpr int AppraiseLDonChest = 164; // implemented + constexpr int DisarmLDoNTrap = 165; // implemented + constexpr int UnlockLDoNChest = 166; // implemented + constexpr int PetPowerIncrease = 167; // implemented, @Fc, On Caster, pet power mod, base: value + constexpr int MeleeMitigation = 168; // implemented + constexpr int CriticalHitChance = 169; // implemented + constexpr int SpellCritChance = 170; // implemented + constexpr int CrippBlowChance = 171; // implemented + constexpr int AvoidMeleeChance = 172; // implemented + constexpr int RiposteChance = 173; // implemented + constexpr int DodgeChance = 174; // implemented + constexpr int ParryChance = 175; // implemented + constexpr int DualWieldChance = 176; // implemented + constexpr int DoubleAttackChance = 177; // implemented + constexpr int MeleeLifetap = 178; // implemented + constexpr int AllInstrumentMod = 179; // implemented, @Song, set mod for ALL instrument/singing skills that will be used if higher then item mods, base: mod%, limit: none, max: none + constexpr int ResistSpellChance = 180; // implemented + constexpr int ResistFearChance = 181; // implemented + constexpr int HundredHands = 182; // implemented + constexpr int MeleeSkillCheck = 183; // implemented + constexpr int HitChance = 184; // implemented + constexpr int DamageModifier = 185; // implemented + constexpr int MinDamageModifier = 186; // implemented + constexpr int BalanceMana = 187; // implemented - Balances party mana + constexpr int IncreaseBlockChance = 188; // implemented + constexpr int CurrentEndurance = 189; // implemented + constexpr int EndurancePool = 190; // implemented + constexpr int Amnesia = 191; // implemented - Silence vs Melee Effect + constexpr int Hate = 192; // implemented - Instant and hate over time. + constexpr int SkillAttack = 193; // implemented, + constexpr int FadingMemories = 194; // implemented, @Aggro, Remove from hate lists and make invisible. Can set max level of NPCs that can be affected. base: success chance, limit: max level (ROF2), max: max level (modern client), Note: Support for max level requires Rule (Spells, UseFadingMemoriesMaxLevel) to be true. If used from limit field, then it set as the level, ie. max level of 75 would use limit value of 75. If set from max field, max level 75 would use max value of 1075, if you want to set it so it checks a level range above the spell target then for it to only work on mobs 5 levels or below you set max value to 5. + constexpr int StunResist = 195; // implemented + constexpr int StrikeThrough = 196; // implemented + constexpr int SkillDamageTaken = 197; // implemented + constexpr int CurrentEnduranceOnce = 198; // implemented + constexpr int Taunt = 199; // implemented - % chance to taunt the target + constexpr int ProcChance = 200; // implemented + constexpr int RangedProc = 201; // implemented + constexpr int IllusionOther = 202; // implemented - Project Illusion + constexpr int MassGroupBuff = 203; // implemented + constexpr int GroupFearImmunity = 204; // implemented - (Does not use bonus) + constexpr int Rampage = 205; // implemented, @Combat Instant, Perform a primary slot combat rounds on all creatures within a 40 foot radius, base: number of attack rounds, limit: max entities hit per round, max: none, Note: AE range is 40 by default. Custom: Set field 'aoe_range' to override default. Adding additional attacks and hit count limit. + constexpr int AETaunt = 206; // implemented + constexpr int FleshToBone = 207; // implemented + constexpr int PurgePoison = 208; // not used + constexpr int DispelBeneficial = 209; // implemented, @Dispel, removes only beneficial effects on a target, base: pct chance (950=95%), limit: none, max: none + constexpr int PetShield = 210; // implmented, @ShieldAbility, allows pet to 'shield' owner for 50 pct of damage taken for a duration, base: Time multiplier 1=12 seconds, 2=24 ect, limit: mitigation on pet owner override (not on live), max: mitigation on pet overide (not on live) + constexpr int AEMelee = 211; // implemented TO DO: Implement to allow NPC use (client only atm). + constexpr int FrenziedDevastation = 212; // implemented - increase spell criticals + all DD spells cast 2x mana. + constexpr int PetMaxHP = 213; // implemented[AA] - increases the maximum hit points of your pet + constexpr int MaxHPChange = 214; // implemented + constexpr int PetAvoidance = 215; // implemented[AA] - increases pet ability to avoid melee damage + constexpr int Accuracy = 216; // implemented + constexpr int HeadShot = 217; // implemented - ability to head shot (base2 = damage) + constexpr int PetCriticalHit = 218; // implemented[AA] - gives pets a baseline critical hit chance + constexpr int SlayUndead = 219; // implemented - Allow extra damage against undead (base1 = rate, base2 = damage mod). + constexpr int SkillDamageAmount = 220; // implemented + constexpr int Packrat = 221; // implemented as bonus + constexpr int BlockBehind = 222; // implemented - Chance to block from behind (with our without Shield) + constexpr int DoubleRiposte = 223; // implemented - Chance to double riposte [not used on live] + constexpr int GiveDoubleRiposte = 224; // implemented[AA] + constexpr int GiveDoubleAttack = 225; // implemented[AA] - Allow any class to double attack with set chance. + constexpr int TwoHandBash = 226; // *not implemented as bonus + constexpr int ReduceSkillTimer = 227; // implemented + constexpr int ReduceFallDamage = 228; // implented - reduce the damage that you take from falling + constexpr int PersistantCasting = 229; // implemented + constexpr int ExtendedShielding = 230; // implemented, @ShieldAbility, extends the range of your /shield ability by an amount of distance, base: distance units, limit: none, max: none + constexpr int StunBashChance = 231; // implemented - increase chance to stun from bash. + constexpr int DivineSave = 232; // implemented (base1 == % chance on death to insta-res) (base2 == spell cast on save) + constexpr int Metabolism = 233; // implemented - Modifies food/drink consumption rates. + constexpr int ReduceApplyPoisonTime = 234; // not implemented as bonus - reduces the time to apply poison + constexpr int ChannelChanceSpells = 235; // implemented[AA] - chance to channel from SPELLS *No longer used on live. + constexpr int FreePet = 236; // not used + constexpr int GivePetGroupTarget = 237; // implemented[AA] - (Pet Affinity) + constexpr int IllusionPersistence = 238; // implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed. + constexpr int FeignedCastOnChance = 239; // implemented - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you. + constexpr int StringUnbreakable = 240; // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.] + constexpr int ImprovedReclaimEnergy = 241; // implemented - increase the amount of mana returned to you when reclaiming your pet. + constexpr int IncreaseChanceMemwipe = 242; // implemented - @Memblur, increases the chance to wipe hate with memory blurr, base: chance pct, limit: none, max: none, Note: Mods final blur chance after other bonuses added. + constexpr int CharmBreakChance = 243; // implemented - Total Domination + constexpr int RootBreakChance = 244; // implemented[AA] reduce the chance that your root will break. + constexpr int TrapCircumvention = 245; // implemented, @Traps, decreases the chance that you will set off a trap when opening a chest or other similar container by percentage, base: chance modifer, limit: none, max: none + constexpr int SetBreathLevel = 246; // *not implemented as bonus + constexpr int RaiseSkillCap = 247; // implemented[AA] - adds skill over the skill cap. + constexpr int SecondaryForte = 248; // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100) + constexpr int SecondaryDmgInc = 249; // implemented[AA] Allows off hand weapon to recieve a damage bonus (Sinister Strikes) + constexpr int SpellProcChance = 250; // implemented - Increase chance to proc from melee proc spells (ie Spirit of Panther) + constexpr int ConsumeProjectile = 251; // implemented[AA] - chance to not consume an arrow (ConsumeProjectile = 100) + constexpr int FrontalBackstabChance = 252; // implemented[AA] - chance to perform a full damage backstab from front. + constexpr int FrontalBackstabMinDmg = 253; // implemented[AA] - allow a frontal backstab for mininum damage. + constexpr int Blank = 254; // implemented + constexpr int ShieldDuration = 255; // implemented, , @ShieldAbility, extends the duration of your /shield ability, base: seconds, limit: none, max: none + constexpr int ShroudofStealth = 256; // implemented + constexpr int PetDiscipline = 257; // not implemented as bonus - /pet hold - official name is GivePetHold + constexpr int TripleBackstab = 258; // implemented[AA] - chance to perform a triple backstab + constexpr int CombatStability = 259; // implemented[AA] - damage mitigation + constexpr int AddSingingMod = 260; // implemented, @Song, set mod for specific instrument/singing skills that will be used if higher then item mods, base: mod%, limit: ItemType ID, max: none + constexpr int SongModCap = 261; // implemented, @Song, raise max song modifier cap, base: amt, limit: none, max: none, Note: No longer used on live + constexpr int RaiseStatCap = 262; // implemented + constexpr int TradeSkillMastery = 263; // implemented - lets you raise more than one tradeskill above master. + constexpr int HastenedAASkill = 264; // implemented + constexpr int MasteryofPast = 265; // implemented[AA] - Spells less than effect values level can not be fizzled + constexpr int ExtraAttackChance = 266; // implemented, @OffBonus, gives your double attacks a percent chance to perform an extra attack with 2-handed primary weapon, base: chance, limit: amt attacks, max: none + constexpr int AddPetCommand = 267; // implemented - sets command base2 to base1 + constexpr int ReduceTradeskillFail = 268; // implemented - reduces chance to fail with given tradeskill by a percent chance + constexpr int MaxBindWound = 269; // implemented[AA] - Increase max HP you can bind wound. + constexpr int BardSongRange = 270; // implemented, @Song, increase range of beneficial bard songs, base: mod%, limit: none, max: none , Note: example Sionachie's Crescendo + constexpr int BaseMovementSpeed = 271; // implemented[AA] - mods basemove speed, doesn't stack with other move mods + constexpr int CastingLevel2 = 272; // implemented + constexpr int CriticalDoTChance = 273; // implemented + constexpr int CriticalHealChance = 274; // implemented + constexpr int CriticalMend = 275; // implemented[AA] - chance to critical monk mend + constexpr int Ambidexterity = 276; // implemented[AA] - increase chance to duel weild by adding bonus 'skill' + constexpr int UnfailingDivinity = 277; // implemented[AA] - ability grants your Death Pact-type spells a second chance to successfully heal their target, also can cause said spells to do a portion of their healing value even on a complete failure. + constexpr int FinishingBlow = 278; // implemented[AA] - chance to do massive damage under 10% HP (base1 = chance, base2 = damage) + constexpr int Flurry = 279; // implemented + constexpr int PetFlurry = 280; // implemented[AA] + constexpr int FeignedMinion = 281; // implemented, ability allows you to instruct your pet to feign death via the '/pet feign' command, base: succeed chance, limit: none, max: none, Note: Only implemented as an AA. + constexpr int ImprovedBindWound = 282; // implemented[AA] - increase bind wound amount by percent. + constexpr int DoubleSpecialAttack = 283; // implemented[AA] - Chance to perform second special attack as monk + constexpr int LoHSetHeal = 284; // not used + constexpr int NimbleEvasion = 285; // *not implemented - base1 = 100 for max + constexpr int FcDamageAmt = 286; // implemented, @Fc, On Caster, spell damage mod flat amt, base: amt + constexpr int SpellDurationIncByTic = 287; // implemented, @Fc, SPA: 287, SpellEffect::SpellDurationIncByTic, = On Caster, spell buff duration mod, base: tics + constexpr int SkillAttackProc = 288; // implemented, @Procs, chance to cast a spell when using a skill, base: chance, limit: skill, max: spellid, note: if used in AA the spell id is set in aa_ranks spell field, chance is calculated as 100% = value 1000. + constexpr int CastOnFadeEffect = 289; // implemented - Triggers only if fades after natural duration. + constexpr int IncreaseRunSpeedCap = 290; // implemented[AA] - increases run speed over the hard cap + constexpr int Purify = 291; // implemented, @Dispel, remove up specified amount of detiremental spells, base: amt removed, limit: none, max: none, Note: excluding charm, fear, resurrection, and revival sickness + constexpr int StrikeThrough2 = 292; // implemented[AA] - increasing chance of bypassing an opponent's special defenses, such as dodge, block, parry, and riposte. + constexpr int FrontalStunResist = 293; // implemented[AA] - Reduce chance to be stunned from front. -- live descriptions sounds like this isn't limited to frontal anymore + constexpr int CriticalSpellChance = 294; // implemented - increase chance to critical hit and critical damage modifier. + constexpr int ReduceTimerSpecial = 295; // not used + constexpr int FcSpellVulnerability = 296; // implemented, @Fc, On Target, spell damage taken mod pct, base: min pct, limit: max pct + constexpr int FcDamageAmtIncoming = 297; // implemetned, @Fc, On Target, damage taken flat amt, base: amt + constexpr int ChangeHeight = 298; // implemented + constexpr int WakeTheDead = 299; // implemented, @Pets, summon one temporary pet from nearby corpses that last a set duration, base: none, limit: none, max: duration (seconds). Note: max range of corpse is 250. + constexpr int Doppelganger = 300; // implemented + constexpr int ArcheryDamageModifier = 301; // implemented[AA] - increase archery damage by percent + constexpr int FcDamagePctCrit = 302; // implemented, @Fc, On Caster, spell damage mod pct, base: min pct, limit: max pct, Note: applied after critical hits has been calculated. + constexpr int FcDamageAmtCrit = 303; // implemented, @Fc, On Caster, spell damage mod flat amt, base: amt + constexpr int OffhandRiposteFail = 304; // implemented as bonus - enemy cannot riposte offhand attacks + constexpr int MitigateDamageShield = 305; // implemented - off hand attacks only (Shielding Resistance) + constexpr int ArmyOfTheDead = 306; // implemented, @Pets, summon multiple temporary pets from nearby corpses that last a set duration, base: amount of corpses that a pet can summon from, limit: none, max: duration (seconds). Note: max range of corpse is 250. + constexpr int Appraisal = 307; // *not implemented Rogue AA - This ability allows you to estimate the selling price of an item you are holding on your cursor. + constexpr int ZoneSuspendMinion = 308; // implemented, @Pet, allow suspended pets to be resummoned upon zoning, base: 1, limit: none, max: none, Calc: Bool + constexpr int GateCastersBindpoint = 309; // implemented - Gate to casters bind point + constexpr int ReduceReuseTimer = 310; // implemented, @Fc, On Caster, spell and disc reuse time mod by amount, base: milliseconds + constexpr int LimitCombatSkills = 311; // implemented, @Ff, Include or exclude combat skills or procs from being focused, base1: 0=Exclude if proc 1=Allow only if proc. + constexpr int Sanctuary = 312; // implemented - Places caster at bottom hate list, effect fades if cast cast spell on targets other than self. + constexpr int ForageAdditionalItems = 313; // implemented[AA] - chance to forage additional items + constexpr int Invisibility2 = 314; // implemented - fixed duration invisible + constexpr int InvisVsUndead2 = 315; // implemented - fixed duration ITU + constexpr int ImprovedInvisAnimals = 316; // implemented + constexpr int ItemHPRegenCapIncrease = 317; // implemented[AA] - increases amount of health regen gained via items + constexpr int ItemManaRegenCapIncrease = 318; // implemented - increases amount of mana regen you can gain via items + constexpr int CriticalHealOverTime = 319; // implemented + constexpr int ShieldBlock = 320; // implemented - Block attacks with shield + constexpr int ReduceHate = 321; // implemented + constexpr int GateToHomeCity = 322; // implemented + constexpr int DefensiveProc = 323; // implemented + constexpr int HPToMana = 324; // implemented + constexpr int NoBreakAESneak = 325; // implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell. + constexpr int SpellSlotIncrease = 326; // *not implemented as bonus - increases your spell slot availability + constexpr int MysticalAttune = 327; // implemented - increases amount of buffs that a player can have + constexpr int DelayDeath = 328; // implemented - increases how far you can fall below 0 hp before you die + constexpr int ManaAbsorbPercentDamage = 329; // implemented + constexpr int CriticalDamageMob = 330; // implemented + constexpr int Salvage = 331; // implemented - chance to recover items that would be destroyed in failed tradeskill combine + constexpr int SummonToCorpse = 332; // *not implemented AA - Call of the Wild (Druid/Shaman Res spell with no exp) TOOD: implement this. + constexpr int CastOnRuneFadeEffect = 333; // implemented + constexpr int BardAEDot = 334; // implemented + constexpr int BlockNextSpellFocus = 335; // implemented, @Fc, On Caster, chance to block next spell, base: chance + constexpr int IllusionaryTarget = 336; // not used + constexpr int PercentXPIncrease = 337; // implemented + constexpr int SummonAndResAllCorpses = 338; // implemented + constexpr int TriggerOnCast = 339; // implemented, @Fc, On Caster, cast on spell use, base: chance pct limit: spellid + constexpr int SpellTrigger = 340; // implemented - chance to trigger spell [Share rolls with 469] All base2 spells share roll chance, only 1 cast. + constexpr int ItemAttackCapIncrease = 341; // implemented[AA] - increases the maximum amount of attack you can gain from items. + constexpr int ImmuneFleeing = 342; // implemented - stop mob from fleeing + constexpr int InterruptCasting = 343; // implemented - % chance to interrupt spells being cast every tic. Cacophony (8272) + constexpr int ChannelChanceItems = 344; // implemented[AA] - chance to not have ITEM effects interrupted when you take damage. + constexpr int AssassinateLevel = 345; // implemented as bonus - AA Assisination max level to kill + constexpr int HeadShotLevel = 346; // implemented[AA] - HeadShot max level to kill + constexpr int DoubleRangedAttack = 347; // implemented - chance at an additional archery attack (consumes arrow) + constexpr int LimitManaMin = 348; // implemented, @Ff, Mininum mana of spell that can be focused, base1: mana amt + constexpr int ShieldEquipDmgMod = 349; // implemented[AA] Increase melee base damage (indirectly increasing hate) when wearing a shield. + constexpr int ManaBurn = 350; // implemented - Drains mana for damage/heal at a defined ratio up to a defined maximum amount of mana. + constexpr int PersistentEffect = 351; // *not implemented. creates a trap/totem that casts a spell (spell id + base1?) when anything comes near it. can probably make a beacon for this + constexpr int IncreaseTrapCount = 352; // *not implemented - looks to be some type of invulnerability? Test ITC (8755) + constexpr int AdditionalAura = 353; // *not implemented - allows use of more than 1 aura, aa effect + constexpr int DeactivateAllTraps = 354; // *not implemented - looks to be some type of invulnerability? Test DAT (8757) + constexpr int LearnTrap = 355; // *not implemented - looks to be some type of invulnerability? Test LT (8758) + constexpr int ChangeTriggerType = 356; // not used + constexpr int FcMute = 357; // implemented, @Fc, On Caster, prevents spell casting, base: chance pct + constexpr int CurrentManaOnce = 358; // implemented + constexpr int PassiveSenseTrap = 359; // *not implemented - Invulnerability (Brell's Blessing) + constexpr int ProcOnKillShot = 360; // implemented - a buff that has a base1 % to cast spell base2 when you kill a "challenging foe" base3 min level + constexpr int SpellOnDeath = 361; // implemented - casts spell on death of buffed + constexpr int PotionBeltSlots = 362; // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank. + constexpr int BandolierSlots = 363; // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank. + constexpr int TripleAttackChance = 364; // implemented + constexpr int ProcOnSpellKillShot = 365; // implemented - chance to trigger a spell on kill when the kill is caused by a specific spell with this effect in it (10470 Venin) + constexpr int GroupShielding = 366; // *not implemented[AA] This gives you /shieldgroup + constexpr int SetBodyType = 367; // implemented - set body type of base1 so it can be affected by spells that are limited to that type (Plant, Animal, Undead, etc) + constexpr int FactionMod = 368; // *not implemented - increases faction with base1 (faction id, live won't match up w/ ours) by base2 + constexpr int CorruptionCounter = 369; // implemented + constexpr int ResistCorruption = 370; // implemented + constexpr int AttackSpeed4 = 371; // implemented - stackable slow effect 'Inhibit Melee' + constexpr int ForageSkill = 372; // implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not. + constexpr int CastOnFadeEffectAlways = 373; // implemented - Triggers if fades after natural duration OR from rune/numhits fades. + constexpr int ApplyEffect = 374; // implemented + constexpr int DotCritDmgIncrease = 375; // implemented - Increase damage of DoT critical amount + constexpr int Fling = 376; // *not implemented - used in 2 test spells (12945 | Movement Test Spell 1) + constexpr int CastOnFadeEffectNPC = 377; // implemented - Triggers only if fades after natural duration (On live these are usually players spells that effect an NPC). + constexpr int SpellEffectResistChance = 378; // implemented - Increase chance to resist specific spell effect (base1=value, base2=spell effect id) + constexpr int ShadowStepDirectional = 379; // implemented - handled by client + constexpr int Knockdown = 380; // implemented - small knock back(handled by client) + constexpr int KnockTowardCaster = 381; // *not implemented (Call of Hither) knocks you back to caster (value) distance units infront + constexpr int NegateSpellEffect = 382; // implemented, @Debuff, negates specific spell effect benefits for the duration of the debuff and prevent non-duration spell effect from working, base: see NegateSpellEffecttype Enum, limit: SPA id, max: none + constexpr int SympatheticProc = 383; // implemented, @Fc, On Caster, cast on spell use, base: variable proc chance on cast time, limit: spellid + constexpr int Leap = 384; // implemented - Leap effect, ie stomping leap + constexpr int LimitSpellGroup = 385; // implemented, @Ff, Spell group(s) that a spell focus can require or exclude, base1: spellgroup id, Include: Positive Exclude: Negative + constexpr int CastOnCurer = 386; // implemented - Casts a spell on the person curing + constexpr int CastOnCure = 387; // implemented - Casts a spell on the cured person + constexpr int SummonCorpseZone = 388; // implemented - summons a corpse from any zone(nec AA) + constexpr int FcTimerRefresh = 389; // implemented, @Fc, On Caster, reset all recast timers, base: 1, Note: Applied from casted spells only + constexpr int FcTimerLockout = 390; // implemented, @Fc, On Caster, set a spell to be on recast timer, base: recast duration milliseconds, Note: Applied from casted spells only + constexpr int LimitManaMax = 391; // implemented, @Ff, Mininum mana of spell that can be focused, base1: mana amt + constexpr int FcHealAmt = 392; // implemented, @Fc, On Caster, spell healing mod flat amt, base: amt + constexpr int FcHealPctIncoming = 393; // implemented, @Fc, On Target, heal received mod pct, base: pct, limit: random max pct + constexpr int FcHealAmtIncoming = 394; // implemented, @Fc, On Target, heal received mod flat amt, base: amt + constexpr int FcHealPctCritIncoming = 395; // implemented, @Fc, On Target, heal received mod pct, base: pct, limit: random max pct + constexpr int FcHealAmtCrit = 396; // implemented, @Fc, On Caster, spell healing mod flat amt, base: amt + constexpr int PetMeleeMitigation = 397; // implemented[AA] - additional mitigation to your pets. Adds AC + constexpr int SwarmPetDuration = 398; // implemented - Affects the duration of swarm pets + constexpr int FcTwincast = 399; // implemented - cast 2 spells for every 1 + constexpr int HealGroupFromMana = 400; // implemented - Drains mana and heals for each point of mana drained + constexpr int ManaDrainWithDmg = 401; // implemented - Deals damage based on the amount of mana drained + constexpr int EndDrainWithDmg = 402; // implemented - Deals damage for the amount of endurance drained + constexpr int LimitSpellClass = 403; // implemented, @Ff, 'Spell Category' using table field 'spell_class' that a spell focus can require or exclude, base1: category type, Include: Positive Exclude: Negative + constexpr int LimitSpellSubclass = 404; // implemented, @Ff, 'Spell Category Subclass' using table field 'spell_subclass' that a spell focus can require or exclude, base1: category type, Include: Positive Exclude: Negative + constexpr int TwoHandBluntBlock = 405; // implemented - chance to block attacks when using two hand blunt weapons (similiar to shield block) + constexpr int CastonNumHitFade = 406; // implemented - casts a spell when a buff fades due to its numhits being depleted + constexpr int CastonFocusEffect = 407; // implemented - casts a spell if focus limits are met (ie triggers when a focus effects is applied) + constexpr int LimitHPPercent = 408; // implemented - limited to a certain percent of your hp(ie heals up to 50%) + constexpr int LimitManaPercent = 409; // implemented - limited to a certain percent of your mana + constexpr int LimitEndPercent = 410; // implemented - limited to a certain percent of your end + constexpr int LimitClass = 411; // implemented, @Ff, Class(es) that can use the spell focus, base1: class(es), Note: The class value in dbase is +1 in relation to item class value, set as you would item for multiple classes + constexpr int LimitRace = 412; // implemented, @Ff, Race that can use the spell focus, base1: race, Note: not used in any known live spells. Use only single race at a time. + constexpr int FcBaseEffects = 413; // implemented, @Fc, On Caster, base spell effectiveness mod pct, base: pct + constexpr int LimitCastingSkill = 414; // implemented, @Ff, Spell and singing skills(s) that a spell focus can require or exclude, base1: skill id, Include: Positive Exclude: Negative + constexpr int FFItemClass = 415; // implemented, @Ff, Limits focuses to be applied only from item click. base1: item ItemType (-1 to include for all ItemTypes,-1000 to exclude clicks from getting the focus, or exclude specific SubTypes or Slots if set), limit: item SubType (-1 for all SubTypes), max: item Slots (bitmask of valid slots, -1 ALL slots), Note: not used on live. See comments in Mob::CalcFocusEffect for more details. + constexpr int ACv2 = 416; // implemented - New AC spell effect + constexpr int ManaRegen_v2 = 417; // implemented - New mana regen effect + constexpr int SkillDamageAmount2 = 418; // implemented - adds skill damage directly to certain attacks + constexpr int AddMeleeProc = 419; // implemented - Adds a proc + constexpr int FcLimitUse = 420; // implemented, @Fc, On Caster, numhits mod pct, base: pct, Note: not used in any known live spells + constexpr int FcIncreaseNumHits = 421; // implemented, @Fc, On Caster, numhits mod flat amt, base: amt + constexpr int LimitUseMin = 422; // implemented, @Ff Minium amount of numhits for a spell to be focused, base: numhit amt + constexpr int LimitUseType = 423; // implemented, = @Ff Focus will only affect if has this numhits type, base: numhit type + constexpr int GravityEffect = 424; // implemented - Pulls/pushes you toward/away the mob at a set pace + constexpr int Display = 425; // *not implemented - Illusion: Flying Dragon(21626) + constexpr int IncreaseExtTargetWindow = 426; // *not implmented[AA] - increases the capacity of your extended target window + constexpr int SkillProcAttempt = 427; // implemented - chance to proc when using a skill(ie taunt) + constexpr int LimitToSkill = 428; // implemented, @Procs, limits what combat skills will effect a skill proc, base: skill value, limit: none, max: none + constexpr int SkillProcSuccess = 429; // implemented - chance to proc when tje skill in use successfully fires. + constexpr int PostEffect = 430; // *not implemented - Fear of the Dark(27641) - Alters vision + constexpr int PostEffectData = 431; // *not implemented - Fear of the Dark(27641) - Alters vision + constexpr int ExpandMaxActiveTrophyBen = 432; // not used + constexpr int CriticalDotDecay = 433; // implemented - increase critical dot chance, effect decays based on level of spell it effects. (12266) + constexpr int CriticalHealDecay = 434; // implemented - increase critical heal chance, effect decays based on level of spell it effects. + constexpr int CriticalRegenDecay = 435; // implemented - increase critical heal over time chance, effect decays based on level of spell it effects. + constexpr int BeneficialCountDownHold = 436; // not used ( 23491 | ABTest Buff Hold) + constexpr int TeleporttoAnchor = 437; // *not implemented - Teleport Guild Hall Anchor(33099) + constexpr int TranslocatetoAnchor = 438; // *not implemented - Translocate Primary Anchor (27750) + constexpr int Assassinate = 439; // implemented[AA] - Assassinate damage + constexpr int FinishingBlowLvl = 440; // implemented[AA] - Sets the level Finishing blow can be triggered on an NPC + constexpr int DistanceRemoval = 441; // implemented - Buff is removed from target when target moves X amount of distance away from where initially hit. + constexpr int TriggerOnReqTarget = 442; // implemented, @SpellTrigger, triggers a spell when Target Requirement conditions are met (see enum SpellRestriction for IDs), base: spellid, limit: SpellRestriction ID, max: none, Note: Usually cast on a target + constexpr int TriggerOnReqCaster = 443; // implemented, @SpellTrigger, triggers a spell when Caster Requirement conditions are met (see enum SpellRestriction for IDs), base: spellid, limit: SpellRestriction ID, max: none, Note: Usually self only + constexpr int ImprovedTaunt = 444; // implemented - Locks Aggro On Caster and Decrease other Players Aggro by X% on NPC targets below level Y + constexpr int AddMercSlot = 445; // *not implemented[AA] - [Hero's Barracks] Allows you to conscript additional mercs. + constexpr int AStacker = 446; // implementet - bufff stacking blocker (26219 | Qirik's Watch) + constexpr int BStacker = 447; // implemented + constexpr int CStacker = 448; // implemented + constexpr int DStacker = 449; // implemented + constexpr int MitigateDotDamage = 450; // implemented, @Runes, mitigate incoming dot damage by percentage until rune fades, base: percent mitigation, limit: max dmg absorbed per hit, max: rune amt, Note: If placed on item or AA, will provide stackable percent mitigation. + constexpr int MeleeThresholdGuard = 451; // implemented Partial Melee Rune that only is lowered if melee hits are over X amount of damage + constexpr int SpellThresholdGuard = 452; // implemented Partial Spell Rune that only is lowered if spell hits are over X amount of damage + constexpr int TriggerMeleeThreshold = 453; // implemented Trigger effect on X amount of melee damage taken in a single hit + constexpr int TriggerSpellThreshold = 454; // implemented Trigger effect on X amount of spell damage taken in a single hit + constexpr int AddHatePct = 455; // implemented Modify total hate by % + constexpr int AddHateOverTimePct = 456; // implemented Modify total hate by % over time. + constexpr int ResourceTap = 457; // implemented Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end. + constexpr int FactionModPct = 458; // implemented Modifies faction gains and losses by percent. + constexpr int DamageModifier2 = 459; // implemented - Modifies melee damage by skill type + constexpr int Ff_Override_NotFocusable = 460; // implemented, @Fc, Allow spell to be focused event if flagged with 'not_focusable' in spell table, base: 1 + constexpr int ImprovedDamage2 = 461; // implemented, @Fc, On Caster, spell damage mod pct, base: min pct, limit: max pct + constexpr int FcDamageAmt2 = 462; // implemented, @Fc, On Caster, spell damage mod flat amt, base: amt + constexpr int Shield_Target = 463; // implemented, Base1 % damage shielded on target + constexpr int PC_Pet_Rampage = 464; // implemented - Base1 % chance to do rampage for base2 % of damage each melee round + constexpr int PC_Pet_AE_Rampage = 465; // implemented - Base1 % chance to do AE rampage for base2 % of damage each melee round + constexpr int PC_Pet_Flurry_Chance = 466; // implemented - Base1 % chance to do flurry from double attack hit. + constexpr int DS_Mitigation_Amount = 467; // implemented - Modify incoming damage shield damage by a flat amount + constexpr int DS_Mitigation_Percentage = 468; // implemented - Modify incoming damage shield damage by percentage + constexpr int Chance_Best_in_Spell_Grp = 469; // implemented - Chance to cast highest scribed spell within a spell group. All base2 spells share roll chance, only 1 cast. + constexpr int Trigger_Best_in_Spell_Grp = 470; // implemented - Chance to cast highest scribed spell within a spell group. Each spell has own chance. + constexpr int Double_Melee_Round = 471; // implemented, @OffBonus, percent chance to repeat primary weapon round with a percent damage modifier, base: pct chance repeat, limit: pct dmg mod, max: none + constexpr int Buy_AA_Rank = 472; // implemented, @Special, Used in AA abilities that have Enable/Disable toggle. Spell on Disabled Rank has this effect in it, base: 1, limit: none, max: none, Note: This will not just buy an AA + constexpr int Double_Backstab_Front = 473; // implemented - Chance to double backstab from front + constexpr int Pet_Crit_Melee_Damage_Pct_Owner = 474; // implemenetd - Critical damage mod applied to pets from owner + constexpr int Trigger_Spell_Non_Item = 475; // implemented - Trigger spell on cast only if not from item click. + constexpr int Weapon_Stance = 476; // implemented, @Misc, Apply a specific spell buffs automatically depending 2Hander, Shield or Dual Wield is equipped, base: spellid, base: 0=2H 1=Shield 2=DW, max: none + constexpr int Hatelist_To_Top_Index = 477; // Implemented - Chance to be set to top of rampage list + constexpr int Hatelist_To_Tail_Index = 478; // Implemented - Chance to be set to bottom of rampage list + constexpr int Ff_Value_Min = 479; // implemented, @Ff, Minimum base value of a spell that can be focused, base: spells to be focused base1 value + constexpr int Ff_Value_Max = 480; // implemented, @Ff, Max base value of a spell that can be focused, base: spells to be focused base1 value + constexpr int Fc_Cast_Spell_On_Land = 481; // implemented, @Fc, On Target, cast spell if hit by spell, base: chance pct, limit: spellid + constexpr int Skill_Base_Damage_Mod = 482; // implemented, @OffBonus, modify base melee damage by percent, base: pct, limit: skill(-1=ALL), max: none + constexpr int Fc_Spell_Damage_Pct_IncomingPC = 483; // implemented, @Fc, On Target, spell damage taken mod pct, base: min pct, limit: max pct + constexpr int Fc_Spell_Damage_Amt_IncomingPC = 484; // implemented, @Fc, On Target, damage taken flat amt, base: amt + constexpr int Ff_CasterClass = 485; // implemented, @Ff, Caster of spell on target with a focus effect that is checked by incoming spells must be specified class(es). base1: class(es), Note: Set multiple classes same as would for items + constexpr int Ff_Same_Caster = 486; // implemented, @Ff, Caster of spell on target with a focus effect that is checked by incoming spells, base1: 0=Must be different caster 1=Must be same caster + constexpr int Extend_Tradeskill_Cap = 487; // + constexpr int Defender_Melee_Force_Pct_PC = 488; // + constexpr int Worn_Endurance_Regen_Cap = 489; // implemented, modify worn regen cap, base: amt, limit: none, max: none + constexpr int Ff_ReuseTimeMin = 490; // implemented, @Ff, Minimum recast time of a spell that can be focused, base: recast time + constexpr int Ff_ReuseTimeMax = 491; // implemented, @Ff, Max recast time of a spell that can be focused, base: recast time + constexpr int Ff_Endurance_Min = 492; // implemented, @Ff, Minimum endurance cost of a spell that can be focused, base: endurance cost + constexpr int Ff_Endurance_Max = 493; // implemented, @Ff, Max endurance cost of a spell that can be focused, base: endurance cost + constexpr int Pet_Add_Atk = 494; // implemented - Bonus on pet owner which gives their pet increased attack stat + constexpr int Ff_DurationMax = 495; // implemented, @Ff, Max duration of spell that can be focused, base: tics + constexpr int Critical_Melee_Damage_Mod_Max = 496; // implemented - increase or decrease by percent critical damage (not stackable) + constexpr int Ff_FocusCastProcNoBypass = 497; // + constexpr int AddExtraAttackPct_1h_Primary = 498; // implemented, @OffBonus, gives your double attacks a percent chance to perform an extra attack with 1-handed primary weapon, base: chance, limit: amt attacks, max: none + constexpr int AddExtraAttackPct_1h_Secondary = 499; //implemented, @OffBonus, gives your double attacks a percent chance to perform an extra attack with 1-handed secondary weapon, base: chance, limit: amt attacks, max: none + constexpr int Fc_CastTimeMod2 = 500; // implemented, @Fc, On Caster, cast time mod pct, base: pct, Note: Can reduce to instant cast + constexpr int Fc_CastTimeAmt = 501; // implemented, @Fc, On Caster, cast time mod flat amt, base: milliseconds, Note: Can reduce to instant cast + constexpr int Fearstun = 502; // implemented - Stun with a max level limit. Normal stun restrictions don't apply. + constexpr int Melee_Damage_Position_Mod = 503; // implemented, @OffBonus, modify melee damage by percent if done from Front or Behind opponent, base: pct, limit: 0=back 1=front, max: none + constexpr int Melee_Damage_Position_Amt = 504; // implemented, @OffBonus, modify melee damage by flat amount if done from Front or Behind opponent, base: amt, limit: 0=back 1=front, max: none + constexpr int Damage_Taken_Position_Mod = 505; // implemented, @DefBonus, modify melee damage by percent if dmg taken from Front or Behind, base: pct, limit: 0=back 1=front, max: none + constexpr int Damage_Taken_Position_Amt = 506; // implemented -@DefBonus, modify melee damage by flat amount if dmg taken from your Front or Behind, base: amt, limit: 0=back 1=front, max: none + constexpr int Fc_Amplify_Mod = 507; // implemented, @Fc, On Caster, damage-heal-dot mod pct, base: pct + constexpr int Fc_Amplify_Amt = 508; // implemented, @Fc, On Caster, damage-heal-dot mod flat amt, base: amt + constexpr int Health_Transfer = 509; // implemented - exchange health for damage or healing on a target. ie Lifeburn/Act of Valor + constexpr int Fc_ResistIncoming = 510; // implemented, @Fc, On Target, resist modifier, base: amt + constexpr int Ff_FocusTimerMin = 511; // implemented, @Ff, sets a recast time until focus can be used again, base: 1, limit: time ms, Note: ie. limit to 1 trigger every 1.5 seconds + constexpr int Proc_Timer_Modifier = 512; // implemented - limits procs per amount of a time based on timer value, base: 1, limit: time ms, Note:, ie limit to 1 proc every 55 seconds) + constexpr int Mana_Max_Percent = 513; // + constexpr int Endurance_Max_Percent = 514; // + constexpr int AC_Avoidance_Max_Percent = 515; // implemented - stackable avoidance modifier + constexpr int AC_Mitigation_Max_Percent = 516; // implemented - stackable defense modifier + constexpr int Attack_Offense_Max_Percent = 517; // + constexpr int Attack_Accuracy_Max_Percent = 518; // implemented - stackable accurary modifer + constexpr int Luck_Amount = 519; // + constexpr int Luck_Percent = 520; // + constexpr int Endurance_Absorb_Pct_Damage = 521; // implemented - Reduces % of Damage using Endurance, drains endurance at a ratio (ie. 0.05 Endurance per Hit Point) + constexpr int Instant_Mana_Pct = 522; // implemented - Increase/Decrease mana by percent of max mana + constexpr int Instant_Endurance_Pct = 523; // implemented - Increase/Decrease mana by percent of max endurance + constexpr int Duration_HP_Pct = 524; // implemented - Decrease Current Hit Points by % of Total Hit Points per Tick, up to a MAX per tick + constexpr int Duration_Mana_Pct = 525; // implemented - Decrease Current Mana by % of Total Mana per Tick, up to a MAX per tick + constexpr int Duration_Endurance_Pct = 526; // implemented - Decrease Current Endurance by % of Total Hit Points per Tick, up to a MAX per tick +} #define DF_Permanent 50 #define DF_Aura 51 @@ -1698,7 +1697,7 @@ struct SPDat_Spell_Struct /* 181 */ int pvp_duration; // buffdurationformula for PvP -- PVP_DURATION /* 182 */ int pvp_duration_cap; // buffduration for PvP -- PVP_DURATION_CAP /* 183 */ int pcnpc_only_flag; // valid values are 0, 1 = PCs (and mercs), and 2 = NPCs (and not mercs) -- PCNPC_ONLY_FLAG -/* 184 */ bool cast_not_standing; // this is checked in the client's EQ_Spell::IsCastWhileInvisSpell, this also blocks SE_InterruptCasting from affecting this spell -- CAST_NOT_STANDING (Allows casting if DA, stun, mezed, charm? fear?, damage to invul targets) +/* 184 */ bool cast_not_standing; // this is checked in the client's EQ_Spell::IsCastWhileInvisSpell, this also blocks SpellEffect::InterruptCasting from affecting this spell -- CAST_NOT_STANDING (Allows casting if DA, stun, mezed, charm? fear?, damage to invul targets) /* 185 */ bool can_mgb; // 0=no, -1 or 1 = yes -- CAN_MGB /* 186 */ int dispel_flag; // -- NO_DISPELL /* 187 */ //int npc_category; // -- NPC_MEM_CATEGORY diff --git a/zone/aa.cpp b/zone/aa.cpp index 9e25cf8604..edefa361db 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -82,7 +82,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u for (int x = 0; x < MAX_SWARM_PETS; x++) { - if (spells[spell_id].effect_id[x] == SE_TemporaryPets) + if (spells[spell_id].effect_id[x] == SpellEffect::TemporaryPets) { pet.count = spells[spell_id].base_value[x]; pet.duration = spells[spell_id].max_value[x]; @@ -1376,7 +1376,7 @@ int Mob::GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in) { } for(auto &effect : rank->effects) { - if(effect.effect_id == SE_HastenedAASkill && effect.limit_value == ability_in->id) { + if(effect.effect_id == SpellEffect::HastenedAASkill && effect.limit_value == ability_in->id) { total_reduction += effect.base_value; } } @@ -1949,7 +1949,7 @@ void Client::TogglePassiveAlternativeAdvancement(const AA::Rank &rank, uint32 ab Instructions for how to make the AA - assuming a basic level of knowledge of how AA's work. - aa_abilities table : Create new ability with a hotkey, type 3, zero charges - - aa_ranks table : [Disabled rank] First rank, should have a cost > 0 (this is what you buy), Set hotkeys, MUST SET A SPELL CONTAINING EFFECT SE_Buy_AA_Rank(SPA 472), set a short recast timer. + - aa_ranks table : [Disabled rank] First rank, should have a cost > 0 (this is what you buy), Set hotkeys, MUST SET A SPELL CONTAINING EFFECT SpellEffect::Buy_AA_Rank(SPA 472), set a short recast timer. [Enabled rank] Second rank, should have a cost = 0, Set hotkeys, Set any valid spell ID you want (it has to exist but does nothing), set a short recast timer. *Recommend if doing custom, just make the hotkey titled 'Toggle ' and use for both. @@ -1969,7 +1969,7 @@ void Client::TogglePassiveAlternativeAdvancement(const AA::Rank &rank, uint32 ab */ - bool enable_next_rank = IsEffectInSpell(rank.spell, SE_Buy_AA_Rank); + bool enable_next_rank = IsEffectInSpell(rank.spell, SpellEffect::Buy_AA_Rank); if (enable_next_rank) { @@ -1980,7 +1980,7 @@ void Client::TogglePassiveAlternativeAdvancement(const AA::Rank &rank, uint32 ab AA::Rank *rank_next = zone->GetAlternateAdvancementRank(rank.next_id); //Add checks for any special cases for toggle. - if (rank_next && IsEffectinAlternateAdvancementRankEffects(*rank_next, SE_Weapon_Stance)) { + if (rank_next && IsEffectinAlternateAdvancementRankEffects(*rank_next, SpellEffect::Weapon_Stance)) { weaponstance.aabonus_enabled = true; ApplyWeaponsStance(); } @@ -1994,7 +1994,7 @@ void Client::TogglePassiveAlternativeAdvancement(const AA::Rank &rank, uint32 ab Message(Chat::Spells, "You disable an ability."); //Message live gives you. Should come from spell. //Add checks for any special cases for toggle. - if (IsEffectinAlternateAdvancementRankEffects(rank, SE_Weapon_Stance)) { + if (IsEffectinAlternateAdvancementRankEffects(rank, SpellEffect::Weapon_Stance)) { weaponstance.aabonus_enabled = false; BuffFadeBySpellID(weaponstance.aabonus_buff_spell_id); } @@ -2005,8 +2005,8 @@ void Client::TogglePassiveAlternativeAdvancement(const AA::Rank &rank, uint32 ab bool Client::UseTogglePassiveHotkey(const AA::Rank &rank) { /* - Disabled rank needs a rank spell containing the SE_Buy_AA_Rank effect to return true. - Enabled rank checks to see if the prior rank contains a rank spell with SE_Buy_AA_Rank, if so true. + Disabled rank needs a rank spell containing the SpellEffect::Buy_AA_Rank effect to return true. + Enabled rank checks to see if the prior rank contains a rank spell with SpellEffect::Buy_AA_Rank, if so true. Note: On live the enabled rank is Expendable with Charge 1. @@ -2014,13 +2014,13 @@ bool Client::UseTogglePassiveHotkey(const AA::Rank &rank) { */ - if (IsEffectInSpell(rank.spell, SE_Buy_AA_Rank)) {//Checked when is Disabled. + if (IsEffectInSpell(rank.spell, SpellEffect::Buy_AA_Rank)) {//Checked when is Disabled. return true; } else if (rank.prev_id != -1) {//Check when effect is Enabled. AA::Rank *rank_prev = zone->GetAlternateAdvancementRank(rank.prev_id); - if (rank_prev && IsEffectInSpell(rank_prev->spell, SE_Buy_AA_Rank)) { + if (rank_prev && IsEffectInSpell(rank_prev->spell, SpellEffect::Buy_AA_Rank)) { return true; } } diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 3447787df0..136a09ded5 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -1377,132 +1377,132 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool is_proc) for (int o = 0; o < EFFECT_COUNT; o++) { switch (spells[spell_id].effect_id[o]) { - case SE_CurrentHPOnce: - case SE_CurrentHP: { + case SpellEffect::CurrentHPOnce: + case SpellEffect::CurrentHP: { int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id); if(val < 0) { aggro_amount -= val; } break; } - case SE_MovementSpeed: { + case SpellEffect::MovementSpeed: { int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id); if (val < 0) { aggro_amount += default_aggro; } break; } - case SE_AttackSpeed: - case SE_AttackSpeed2: - case SE_AttackSpeed3: { + case SpellEffect::AttackSpeed: + case SpellEffect::AttackSpeed2: + case SpellEffect::AttackSpeed3: { int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id); if (val < 100) { aggro_amount += default_aggro; } break; } - case SE_Stun: - case SE_Blind: - case SE_Mez: - case SE_Charm: - case SE_Fear: - case SE_Fearstun: + case SpellEffect::Stun: + case SpellEffect::Blind: + case SpellEffect::Mez: + case SpellEffect::Charm: + case SpellEffect::Fear: + case SpellEffect::Fearstun: aggro_amount += default_aggro; break; - case SE_Root: + case SpellEffect::Root: aggro_amount += 10; break; - case SE_ACv2: - case SE_ArmorClass: { + case SpellEffect::ACv2: + case SpellEffect::ArmorClass: { int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id); if (val < 0) { aggro_amount += default_aggro; } break; } - case SE_ATK: - case SE_ResistMagic: - case SE_ResistFire: - case SE_ResistCold: - case SE_ResistPoison: - case SE_ResistDisease: - case SE_STR: - case SE_STA: - case SE_DEX: - case SE_AGI: - case SE_INT: - case SE_WIS: - case SE_CHA: { + case SpellEffect::ATK: + case SpellEffect::ResistMagic: + case SpellEffect::ResistFire: + case SpellEffect::ResistCold: + case SpellEffect::ResistPoison: + case SpellEffect::ResistDisease: + case SpellEffect::STR: + case SpellEffect::STA: + case SpellEffect::DEX: + case SpellEffect::AGI: + case SpellEffect::INT: + case SpellEffect::WIS: + case SpellEffect::CHA: { int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id); if (val < 0) { aggro_amount += 10; } break; } - case SE_ResistAll: { + case SpellEffect::ResistAll: { int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id); if (val < 0) { aggro_amount += 50; } break; } - case SE_AllStats: { + case SpellEffect::AllStats: { int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id); if (val < 0) { aggro_amount += 70; } break; } - case SE_BardAEDot: + case SpellEffect::BardAEDot: aggro_amount += 10; break; - case SE_SpinTarget: - case SE_Amnesia: - case SE_Silence: - case SE_Destroy: + case SpellEffect::SpinTarget: + case SpellEffect::Amnesia: + case SpellEffect::Silence: + case SpellEffect::Destroy: aggro_amount += default_aggro; break; // unsure -- leave them this for now - case SE_Harmony: - case SE_CastingLevel: - case SE_MeleeMitigation: - case SE_CriticalHitChance: - case SE_AvoidMeleeChance: - case SE_RiposteChance: - case SE_DodgeChance: - case SE_ParryChance: - case SE_DualWieldChance: - case SE_DoubleAttackChance: - case SE_MeleeSkillCheck: - case SE_HitChance: - case SE_DamageModifier: - case SE_MinDamageModifier: - case SE_IncreaseBlockChance: - case SE_Accuracy: - case SE_DamageShield: - case SE_SpellDamageShield: - case SE_ReverseDS: { + case SpellEffect::Harmony: + case SpellEffect::CastingLevel: + case SpellEffect::MeleeMitigation: + case SpellEffect::CriticalHitChance: + case SpellEffect::AvoidMeleeChance: + case SpellEffect::RiposteChance: + case SpellEffect::DodgeChance: + case SpellEffect::ParryChance: + case SpellEffect::DualWieldChance: + case SpellEffect::DoubleAttackChance: + case SpellEffect::MeleeSkillCheck: + case SpellEffect::HitChance: + case SpellEffect::DamageModifier: + case SpellEffect::MinDamageModifier: + case SpellEffect::IncreaseBlockChance: + case SpellEffect::Accuracy: + case SpellEffect::DamageShield: + case SpellEffect::SpellDamageShield: + case SpellEffect::ReverseDS: { aggro_amount += mob_level * 2; break; } // unsure -- leave them this for now - case SE_CurrentMana: - case SE_ManaRegen_v2: - case SE_ManaPool: - case SE_CurrentEndurance: { + case SpellEffect::CurrentMana: + case SpellEffect::ManaRegen_v2: + case SpellEffect::ManaPool: + case SpellEffect::CurrentEndurance: { int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id); if (val < 0) { aggro_amount -= val * 2; } break; } - case SE_CancelMagic: - case SE_DispelDetrimental: - case SE_DispelBeneficial: + case SpellEffect::CancelMagic: + case SpellEffect::DispelDetrimental: + case SpellEffect::DispelBeneficial: dispel = true; break; - case SE_ReduceHate: - case SE_InstantHate: + case SpellEffect::ReduceHate: + case SpellEffect::InstantHate: non_modified_aggro = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id); break; } @@ -1549,8 +1549,8 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib for (int o = 0; o < EFFECT_COUNT; o++) { switch (spells[spell_id].effect_id[o]) { - case SE_CurrentHP: - case SE_PercentalHeal: + case SpellEffect::CurrentHP: + case SpellEffect::PercentalHeal: { if (heal_possible == 0) { AggroAmount += 1; @@ -1572,12 +1572,12 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possib AggroAmount += std::max(val, (int64)1); break; } - case SE_Rune: + case SpellEffect::Rune: AggroAmount += CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], GetLevel(), spell_id) * 2; ignore_default_buff = true; break; - case SE_HealOverTime: + case SpellEffect::HealOverTime: AggroAmount += 10; ignore_default_buff = true; break; diff --git a/zone/attack.cpp b/zone/attack.cpp index aee861749c..f5552c47cb 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -179,7 +179,7 @@ int Mob::compute_tohit(EQ::skills::SkillType skillinuse) //SYNC WITH: tune.cpp, mob.h TuneGetTotalToHit int Mob::GetTotalToHit(EQ::skills::SkillType skill, int chance_mod) { - if (chance_mod >= 10000) // override for stuff like SE_SkillAttack + if (chance_mod >= 10000) // override for stuff like SpellEffect::SkillAttack return -1; // calculate attacker's accuracy @@ -209,7 +209,7 @@ int Mob::GetTotalToHit(EQ::skills::SkillType skill, int chance_mod) if (atkhit_bonus) accuracy += round(static_cast(accuracy) * static_cast(atkhit_bonus) * 0.0001); - // 216 Melee Accuracy Amt aka SE_Accuracy -- flat bonus + // 216 Melee Accuracy Amt aka SpellEffect::Accuracy -- flat bonus accuracy += itembonuses.Accuracy[EQ::skills::HIGHEST_SKILL + 1] + aabonuses.Accuracy[EQ::skills::HIGHEST_SKILL + 1] + spellbonuses.Accuracy[EQ::skills::HIGHEST_SKILL + 1] + @@ -224,7 +224,7 @@ int Mob::GetTotalToHit(EQ::skills::SkillType skill, int chance_mod) if (spellbonuses.HitChanceEffect[EQ::skills::HIGHEST_SKILL + 1] >= 10000) return -1; - // 184 Accuracy % aka SE_HitChance -- percentage increase + // 184 Accuracy % aka SpellEffect::HitChance -- percentage increase auto hit_bonus = itembonuses.HitChanceEffect[EQ::skills::HIGHEST_SKILL + 1] + aabonuses.HitChanceEffect[EQ::skills::HIGHEST_SKILL + 1] + spellbonuses.HitChanceEffect[EQ::skills::HIGHEST_SKILL + 1] + @@ -285,7 +285,7 @@ int Mob::compute_defense() } - //516 SE_AC_Mitigation_Max_Percent + //516 SpellEffect::AC_Mitigation_Max_Percent auto ac_bonus = itembonuses.AC_Mitigation_Max_Percent + aabonuses.AC_Mitigation_Max_Percent + spellbonuses.AC_Mitigation_Max_Percent; if (ac_bonus) { defense += round(static_cast(defense) * static_cast(ac_bonus) * 0.0001); @@ -315,15 +315,15 @@ int Mob::GetTotalDefense() if (evasion_bonus >= 10000) return -1; - // 515 SE_AC_Avoidance_Max_Percent + // 515 SpellEffect::AC_Avoidance_Max_Percent auto ac_aviodance_bonus = itembonuses.AC_Avoidance_Max_Percent + aabonuses.AC_Avoidance_Max_Percent + spellbonuses.AC_Avoidance_Max_Percent; if (ac_aviodance_bonus) avoidance += round(static_cast(avoidance) * static_cast(ac_aviodance_bonus) * 0.0001); - // 172 Evasion aka SE_AvoidMeleeChance + // 172 Evasion aka SpellEffect::AvoidMeleeChance evasion_bonus += itembonuses.AvoidMeleeChanceEffect + aabonuses.AvoidMeleeChanceEffect; // item bonus here isn't mod2 avoidance - // 215 Pet Avoidance % aka SE_PetAvoidance + // 215 Pet Avoidance % aka SpellEffect::PetAvoidance evasion_bonus += GetPetAvoidanceBonusFromOwner(); // Evasion is a percentage bonus according to AA descriptions @@ -1917,7 +1917,7 @@ bool Client::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::Skil dead = true; if (m_pet && m_pet->IsCharmed()) { - m_pet->BuffFadeByEffect(SE_Charm); + m_pet->BuffFadeByEffect(SpellEffect::Charm); } if (GetMerc()) { @@ -3678,7 +3678,7 @@ int64 Mob::ReduceDamage(int64 damage) return DMG_RUNE; if (spellbonuses.MeleeRune[SBIndex::RUNE_AMOUNT] && spellbonuses.MeleeRune[SBIndex::RUNE_BUFFSLOT] >= 0) - damage = RuneAbsorb(damage, SE_Rune); + damage = RuneAbsorb(damage, SpellEffect::Rune); if (damage < 1) return DMG_RUNE; @@ -3805,10 +3805,10 @@ int64 Mob::AffectMagicalDamage(int64 damage, uint16 spell_id, const bool iBuffTi //Regular runes absorb spell damage (except dots) - Confirmed on live. if (spellbonuses.MeleeRune[SBIndex::RUNE_AMOUNT] && spellbonuses.MeleeRune[SBIndex::RUNE_BUFFSLOT] >= 0) - damage = RuneAbsorb(damage, SE_Rune); + damage = RuneAbsorb(damage, SpellEffect::Rune); if (spellbonuses.AbsorbMagicAtt[SBIndex::RUNE_AMOUNT] && spellbonuses.AbsorbMagicAtt[SBIndex::RUNE_BUFFSLOT] >= 0) - damage = RuneAbsorb(damage, SE_AbsorbMagicAtt); + damage = RuneAbsorb(damage, SpellEffect::AbsorbMagicAtt); if (damage < 1) return 0; @@ -4174,7 +4174,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons damage = ReduceDamage(damage); LogCombat("Melee Damage reduced to [{}]", damage); damage = ReduceAllDamage(damage); - TryTriggerThreshHold(damage, SE_TriggerMeleeThreshold, attacker); + TryTriggerThreshHold(damage, SpellEffect::TriggerMeleeThreshold, attacker); CheckNumHitsRemaining(NumHit::IncomingHitSuccess); } @@ -4199,7 +4199,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons Message(263, "%s tries to cast on YOU, but YOUR magical skin absorbs the spell.", attacker->GetCleanName()); } damage = ReduceAllDamage(damage); - TryTriggerThreshHold(damage, SE_TriggerSpellThreshold, attacker); + TryTriggerThreshHold(damage, SpellEffect::TriggerSpellThreshold, attacker); } if (IsClient() && CastToClient()->sneaking) { @@ -4314,7 +4314,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons GetCleanName(), /* Message1 */ attacker->GetCleanName() /* Message2 */ ); - BuffFadeByEffect(SE_Mez); + BuffFadeByEffect(SpellEffect::Mez); } // broken up for readability @@ -4399,12 +4399,12 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons int bashsave_roll = zone->random.Int(0, 100); if (bashsave_roll > 98 || bashsave_roll > (55 - stunbash_chance)) { // did stun -- roll other resists - // SE_FrontalStunResist description says any angle now a days + // SpellEffect::FrontalStunResist description says any angle now a days int stun_resist2 = spellbonuses.FrontalStunResist + itembonuses.FrontalStunResist + aabonuses.FrontalStunResist; if (zone->random.Int(1, 100) > stun_resist2) { // stun resist 2 failed - // time to check SE_StunResist and mod2 stun resist + // time to check SpellEffect::StunResist and mod2 stun resist int stun_resist = spellbonuses.StunResist + itembonuses.StunResist + aabonuses.StunResist; if (zone->random.Int(0, 100) >= stun_resist) { @@ -5668,7 +5668,7 @@ void Mob::DoRiposte(Mob *defender) defender->itembonuses.DoubleRiposte; if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) { - LogCombat("Preforming a double riposted from SE_DoubleRiposte ([{}] percent chance)", DoubleRipChance); + LogCombat("Preforming a double riposted from SpellEffect::DoubleRiposte ([{}] percent chance)", DoubleRipChance); defender->Attack(this, EQ::invslot::slotPrimary, true); if (HasDied()) return; @@ -5679,7 +5679,7 @@ void Mob::DoRiposte(Mob *defender) // Live AA - Double Riposte if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) { - LogCombat("Preforming a double riposted from SE_GiveDoubleRiposte base1 == 0 ([{}] percent chance)", DoubleRipChance); + LogCombat("Preforming a double riposted from SpellEffect::GiveDoubleRiposte base1 == 0 ([{}] percent chance)", DoubleRipChance); defender->Attack(this, EQ::invslot::slotPrimary, true); if (HasDied()) return; @@ -6027,12 +6027,12 @@ void Mob::TrySkillProc(Mob *on, EQ::skills::SkillType skill, uint16 ReuseTime, b for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[base_spell_id].effect_id[i] == SE_SkillProcAttempt || spells[base_spell_id].effect_id[i] == SE_SkillProcSuccess) { + if (spells[base_spell_id].effect_id[i] == SpellEffect::SkillProcAttempt || spells[base_spell_id].effect_id[i] == SpellEffect::SkillProcSuccess) { proc_spell_id = spells[base_spell_id].base_value[i]; ProcMod = static_cast(spells[base_spell_id].limit_value[i]); } - else if (spells[base_spell_id].effect_id[i] == SE_LimitToSkill && spells[base_spell_id].base_value[i] <= EQ::skills::HIGHEST_SKILL) { + else if (spells[base_spell_id].effect_id[i] == SpellEffect::LimitToSkill && spells[base_spell_id].base_value[i] <= EQ::skills::HIGHEST_SKILL) { if (CanProc && spells[base_spell_id].base_value[i] == skill && IsValidSpell(proc_spell_id)) { float final_chance = chance * (ProcMod / 100.0f); if (zone->random.Roll(final_chance)) { @@ -6071,12 +6071,12 @@ void Mob::TrySkillProc(Mob *on, EQ::skills::SkillType skill, uint16 ReuseTime, b ProcMod = 0; for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[base_spell_id].effect_id[i] == SE_SkillProcAttempt || spells[base_spell_id].effect_id[i] == SE_SkillProcSuccess) { + if (spells[base_spell_id].effect_id[i] == SpellEffect::SkillProcAttempt || spells[base_spell_id].effect_id[i] == SpellEffect::SkillProcSuccess) { proc_spell_id = spells[base_spell_id].base_value[i]; ProcMod = static_cast(spells[base_spell_id].limit_value[i]); } - else if (spells[base_spell_id].effect_id[i] == SE_LimitToSkill && spells[base_spell_id].base_value[i] <= EQ::skills::HIGHEST_SKILL) { + else if (spells[base_spell_id].effect_id[i] == SpellEffect::LimitToSkill && spells[base_spell_id].base_value[i] <= EQ::skills::HIGHEST_SKILL) { if (CanProc && spells[base_spell_id].base_value[i] == skill && IsValidSpell(proc_spell_id)) { float final_chance = chance * (ProcMod / 100.0f); @@ -6133,11 +6133,11 @@ void Mob::TrySkillProc(Mob *on, EQ::skills::SkillType skill, uint16 ReuseTime, b limit_value = effect.limit_value; slot = effect.slot; - if (effect_id == SE_SkillProcAttempt || effect_id == SE_SkillProcSuccess) { + if (effect_id == SpellEffect::SkillProcAttempt || effect_id == SpellEffect::SkillProcSuccess) { proc_spell_id = base_value; ProcMod = static_cast(limit_value); } - else if (effect_id == SE_LimitToSkill && base_value <= EQ::skills::HIGHEST_SKILL) { + else if (effect_id == SpellEffect::LimitToSkill && base_value <= EQ::skills::HIGHEST_SKILL) { if (CanProc && base_value == skill && IsValidSpell(proc_spell_id)) { float final_chance = chance * (ProcMod / 100.0f); @@ -6300,7 +6300,7 @@ bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) { int32 Mob::RuneAbsorb(int64 damage, uint16 type) { uint32 buff_max = GetMaxTotalSlots(); - if (type == SE_Rune) { + if (type == SpellEffect::Rune) { for (uint32 slot = 0; slot < buff_max; slot++) { if (slot == spellbonuses.MeleeRune[SBIndex::RUNE_BUFFSLOT] && spellbonuses.MeleeRune[SBIndex::RUNE_AMOUNT] && buffs[slot].melee_rune && IsValidSpell(buffs[slot].spellid)) { int melee_rune_left = buffs[slot].melee_rune; @@ -6544,7 +6544,7 @@ void Mob::DoShieldDamageOnShielderSpellEffect(Mob* shield_target, int64 hit_dama return; } /* - SPA 463 SE_SHIELD_TARGET + SPA 463 SpellEffect::SHIELD_TARGET Live description: "Shields your target, taking a percentage of their damage". Only example spell on live is an NPC who uses it during a raid event "Laurion's Song" expansion. SPA 54492 'Guardian Stance' Described as 100% Melee Shielding @@ -6596,7 +6596,7 @@ void Mob::CommonBreakInvisibleFromCombat() CancelSneakHide(); if (spellbonuses.NegateIfCombat) { - BuffFadeByEffect(SE_NegateIfCombat); + BuffFadeByEffect(SpellEffect::NegateIfCombat); } hidden = false; diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 640e9ddd19..0cc44cac33 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -52,7 +52,7 @@ void Mob::CalcBonuses() We set this here because NPC's can cast spells to change walkspeed/runspeed */ float get_walk_speed = static_cast(0.025f * GetWalkspeed()); - rooted = FindType(SE_Root); + rooted = FindType(SpellEffect::Root); } void NPC::CalcBonuses() @@ -108,7 +108,7 @@ void Client::CalcBonuses() SetAttackTimer(); - rooted = FindType(SE_Root); + rooted = FindType(SpellEffect::Root); XPRate = 100 + spellbonuses.XPRateMod; @@ -625,7 +625,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) uint32 effect = 0; int32 base_value = 0; - int32 limit_value = 0; // only really used for SE_RaiseStatCap & SE_ReduceSkillTimer in aa_effects table + int32 limit_value = 0; // only really used for SpellEffect::RaiseStatCap & SpellEffect::ReduceSkillTimer in aa_effects table uint32 slot = 0; for (const auto &e : rank.effects) { @@ -634,13 +634,13 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) limit_value = e.limit_value; slot = e.slot; - // we default to 0 (SE_CurrentHP) for the effect, so if there aren't any base1/2 values, we'll just skip it + // we default to 0 (SpellEffect::CurrentHP) for the effect, so if there aren't any base1/2 values, we'll just skip it if (effect == 0 && base_value == 0 && limit_value == 0) continue; // IsBlankSpellEffect() - if (effect == SE_Blank || (effect == SE_CHA && base_value == 0) || effect == SE_StackingCommand_Block || - effect == SE_StackingCommand_Overwrite) + if (effect == SpellEffect::Blank || (effect == SpellEffect::CHA && base_value == 0) || effect == SpellEffect::StackingCommand_Block || + effect == SpellEffect::StackingCommand_Overwrite) continue; LogAA("Applying Effect [{}] from AA [{}] in slot [{}] (base1: [{}], base2: [{}]) on [{}]", @@ -653,12 +653,12 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } switch (effect) { - case SE_ACv2: - case SE_ArmorClass: + case SpellEffect::ACv2: + case SpellEffect::ArmorClass: newbon->AC += base_value; break; // Note: AA effects that use accuracy are skill limited, while spell effect is not. - case SE_Accuracy: + case SpellEffect::Accuracy: // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) break; @@ -667,83 +667,83 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) else if (newbon->Accuracy[limit_value] < base_value) newbon->Accuracy[limit_value] += base_value; break; - case SE_CurrentHP: // regens + case SpellEffect::CurrentHP: // regens newbon->HPRegen += base_value; break; - case SE_CurrentEndurance: + case SpellEffect::CurrentEndurance: newbon->EnduranceRegen += base_value; break; - case SE_MovementSpeed: + case SpellEffect::MovementSpeed: newbon->movementspeed += base_value; // should we let these stack? /*if (base1 > newbon->movementspeed) //or should we use a total value? newbon->movementspeed = base1;*/ break; - case SE_STR: + case SpellEffect::STR: newbon->STR += base_value; break; - case SE_DEX: + case SpellEffect::DEX: newbon->DEX += base_value; break; - case SE_AGI: + case SpellEffect::AGI: newbon->AGI += base_value; break; - case SE_STA: + case SpellEffect::STA: newbon->STA += base_value; break; - case SE_INT: + case SpellEffect::INT: newbon->INT += base_value; break; - case SE_WIS: + case SpellEffect::WIS: newbon->WIS += base_value; break; - case SE_CHA: + case SpellEffect::CHA: newbon->CHA += base_value; break; - case SE_WaterBreathing: + case SpellEffect::WaterBreathing: // handled by client break; - case SE_CurrentMana: + case SpellEffect::CurrentMana: newbon->ManaRegen += base_value; break; - case SE_ManaPool: + case SpellEffect::ManaPool: newbon->Mana += base_value; break; - case SE_ItemManaRegenCapIncrease: + case SpellEffect::ItemManaRegenCapIncrease: newbon->ItemManaRegenCap += base_value; break; - case SE_ResistFire: + case SpellEffect::ResistFire: newbon->FR += base_value; break; - case SE_ResistCold: + case SpellEffect::ResistCold: newbon->CR += base_value; break; - case SE_ResistPoison: + case SpellEffect::ResistPoison: newbon->PR += base_value; break; - case SE_ResistDisease: + case SpellEffect::ResistDisease: newbon->DR += base_value; break; - case SE_ResistMagic: + case SpellEffect::ResistMagic: newbon->MR += base_value; break; - case SE_ResistCorruption: + case SpellEffect::ResistCorruption: newbon->Corrup += base_value; break; - case SE_IncreaseSpellHaste: + case SpellEffect::IncreaseSpellHaste: break; - case SE_IncreaseRange: + case SpellEffect::IncreaseRange: break; - case SE_MaxHPChange: + case SpellEffect::MaxHPChange: newbon->PercentMaxHPChange += base_value; break; - case SE_Packrat: + case SpellEffect::Packrat: newbon->Packrat += base_value; break; - case SE_TwoHandBash: + case SpellEffect::TwoHandBash: break; - case SE_SetBreathLevel: + case SpellEffect::SetBreathLevel: break; - case SE_RaiseStatCap: + case SpellEffect::RaiseStatCap: switch (limit_value) { // are these #define'd somewhere? case 0: // str @@ -787,117 +787,117 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } break; - case SE_SpellSlotIncrease: + case SpellEffect::SpellSlotIncrease: break; - case SE_MysticalAttune: + case SpellEffect::MysticalAttune: newbon->BuffSlotIncrease += base_value; break; - case SE_TotalHP: + case SpellEffect::TotalHP: newbon->FlatMaxHPChange += base_value; break; - case SE_StunResist: + case SpellEffect::StunResist: newbon->StunResist += base_value; break; - case SE_SpellCritChance: + case SpellEffect::SpellCritChance: newbon->CriticalSpellChance += base_value; break; - case SE_SpellCritDmgIncrease: + case SpellEffect::SpellCritDmgIncrease: newbon->SpellCritDmgIncrease += base_value; break; - case SE_DotCritDmgIncrease: + case SpellEffect::DotCritDmgIncrease: newbon->DotCritDmgIncrease += base_value; break; - case SE_ResistSpellChance: + case SpellEffect::ResistSpellChance: newbon->ResistSpellChance += base_value; break; - case SE_CriticalHealChance: + case SpellEffect::CriticalHealChance: newbon->CriticalHealChance += base_value; break; - case SE_CriticalHealOverTime: + case SpellEffect::CriticalHealOverTime: newbon->CriticalHealOverTime += base_value; break; - case SE_CriticalDoTChance: + case SpellEffect::CriticalDoTChance: newbon->CriticalDoTChance += base_value; break; - case SE_ReduceSkillTimer: + case SpellEffect::ReduceSkillTimer: newbon->SkillReuseTime[limit_value] += base_value; break; - case SE_Fearless: + case SpellEffect::Fearless: newbon->Fearless = true; break; - case SE_PersistantCasting: + case SpellEffect::PersistantCasting: newbon->PersistantCasting += base_value; break; - case SE_DelayDeath: + case SpellEffect::DelayDeath: newbon->DelayDeath += base_value; break; - case SE_FrontalStunResist: + case SpellEffect::FrontalStunResist: newbon->FrontalStunResist += base_value; break; - case SE_ImprovedBindWound: + case SpellEffect::ImprovedBindWound: newbon->BindWound += base_value; break; - case SE_MaxBindWound: + case SpellEffect::MaxBindWound: newbon->MaxBindWound += base_value; break; - case SE_SeeInvis: + case SpellEffect::SeeInvis: base_value = std::min({ base_value, MAX_INVISIBILTY_LEVEL }); if (newbon->SeeInvis < base_value) { newbon->SeeInvis = base_value; } break; - case SE_BaseMovementSpeed: + case SpellEffect::BaseMovementSpeed: newbon->BaseMovementSpeed += base_value; break; - case SE_IncreaseRunSpeedCap: + case SpellEffect::IncreaseRunSpeedCap: newbon->IncreaseRunSpeedCap += base_value; break; - case SE_ConsumeProjectile: + case SpellEffect::ConsumeProjectile: newbon->ConsumeProjectile += base_value; break; - case SE_ForageAdditionalItems: + case SpellEffect::ForageAdditionalItems: newbon->ForageAdditionalItems += base_value; break; - case SE_Salvage: + case SpellEffect::Salvage: newbon->SalvageChance += base_value; break; - case SE_ArcheryDamageModifier: + case SpellEffect::ArcheryDamageModifier: newbon->ArcheryDamageModifier += base_value; break; - case SE_DoubleRangedAttack: + case SpellEffect::DoubleRangedAttack: newbon->DoubleRangedAttack += base_value; break; - case SE_DamageShield: + case SpellEffect::DamageShield: newbon->DamageShield += base_value; break; - case SE_CharmBreakChance: + case SpellEffect::CharmBreakChance: newbon->CharmBreakChance += base_value; break; - case SE_OffhandRiposteFail: + case SpellEffect::OffhandRiposteFail: newbon->OffhandRiposteFail += base_value; break; - case SE_ItemAttackCapIncrease: + case SpellEffect::ItemAttackCapIncrease: newbon->ItemATKCap += base_value; break; - case SE_GivePetGroupTarget: + case SpellEffect::GivePetGroupTarget: newbon->GivePetGroupTarget = true; break; - case SE_ItemHPRegenCapIncrease: + case SpellEffect::ItemHPRegenCapIncrease: newbon->ItemHPRegenCap += base_value; break; - case SE_Ambidexterity: + case SpellEffect::Ambidexterity: newbon->Ambidexterity += base_value; break; - case SE_PetMaxHP: + case SpellEffect::PetMaxHP: newbon->PetMaxHP += base_value; break; - case SE_AvoidMeleeChance: + case SpellEffect::AvoidMeleeChance: newbon->AvoidMeleeChanceEffect += base_value; break; - case SE_CombatStability: + case SpellEffect::CombatStability: newbon->CombatStability += base_value; break; - case SE_AddSingingMod: + case SpellEffect::AddSingingMod: switch (limit_value) { case EQ::item::ItemTypeWindInstrument: newbon->windMod += base_value; @@ -916,99 +916,99 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } break; - case SE_SongModCap: + case SpellEffect::SongModCap: newbon->songModCap += base_value; break; - case SE_PetCriticalHit: + case SpellEffect::PetCriticalHit: newbon->PetCriticalHit += base_value; break; - case SE_PetAvoidance: + case SpellEffect::PetAvoidance: newbon->PetAvoidance += base_value; break; - case SE_ShieldBlock: + case SpellEffect::ShieldBlock: newbon->ShieldBlock += base_value; break; - case SE_ShieldEquipDmgMod: + case SpellEffect::ShieldEquipDmgMod: newbon->ShieldEquipDmgMod += base_value; break; - case SE_SecondaryDmgInc: + case SpellEffect::SecondaryDmgInc: newbon->SecondaryDmgInc = true; break; - case SE_ChangeAggro: + case SpellEffect::ChangeAggro: newbon->hatemod += base_value; break; - case SE_EndurancePool: + case SpellEffect::EndurancePool: newbon->Endurance += base_value; break; - case SE_ChannelChanceItems: + case SpellEffect::ChannelChanceItems: newbon->ChannelChanceItems += base_value; break; - case SE_ChannelChanceSpells: + case SpellEffect::ChannelChanceSpells: newbon->ChannelChanceSpells += base_value; break; - case SE_DoubleSpecialAttack: + case SpellEffect::DoubleSpecialAttack: newbon->DoubleSpecialAttack += base_value; break; - case SE_TripleBackstab: + case SpellEffect::TripleBackstab: newbon->TripleBackstab += base_value; break; - case SE_FrontalBackstabMinDmg: + case SpellEffect::FrontalBackstabMinDmg: newbon->FrontalBackstabMinDmg = true; break; - case SE_FrontalBackstabChance: + case SpellEffect::FrontalBackstabChance: newbon->FrontalBackstabChance += base_value; break; - case SE_Double_Backstab_Front: + case SpellEffect::Double_Backstab_Front: newbon->Double_Backstab_Front += base_value; break; - case SE_BlockBehind: + case SpellEffect::BlockBehind: newbon->BlockBehind += base_value; break; - case SE_StrikeThrough: - case SE_StrikeThrough2: + case SpellEffect::StrikeThrough: + case SpellEffect::StrikeThrough2: newbon->StrikeThrough += base_value; break; - case SE_DoubleAttackChance: + case SpellEffect::DoubleAttackChance: newbon->DoubleAttackChance += base_value; break; - case SE_GiveDoubleAttack: + case SpellEffect::GiveDoubleAttack: newbon->GiveDoubleAttack += base_value; break; - case SE_ProcChance: + case SpellEffect::ProcChance: newbon->ProcChanceSPA += base_value; break; - case SE_RiposteChance: + case SpellEffect::RiposteChance: newbon->RiposteChance += base_value; break; - case SE_DodgeChance: + case SpellEffect::DodgeChance: newbon->DodgeChance += base_value; break; - case SE_ParryChance: + case SpellEffect::ParryChance: newbon->ParryChance += base_value; break; - case SE_IncreaseBlockChance: + case SpellEffect::IncreaseBlockChance: newbon->IncreaseBlockChance += base_value; break; - case SE_Flurry: + case SpellEffect::Flurry: newbon->FlurryChance += base_value; break; - case SE_PetFlurry: + case SpellEffect::PetFlurry: newbon->PetFlurry += base_value; break; - case SE_BardSongRange: + case SpellEffect::BardSongRange: newbon->SongRange += base_value; break; - case SE_RootBreakChance: + case SpellEffect::RootBreakChance: newbon->RootBreakChance += base_value; break; - case SE_UnfailingDivinity: + case SpellEffect::UnfailingDivinity: newbon->UnfailingDivinity += base_value; break; - case SE_CrippBlowChance: + case SpellEffect::CrippBlowChance: newbon->CrippBlowChance += base_value; break; - case SE_HitChance: { + case SpellEffect::HitChance: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) break; @@ -1019,7 +1019,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_ProcOnKillShot: + case SpellEffect::ProcOnKillShot: for (int i = 0; i < MAX_SPELL_TRIGGER * 3; i += 3) { if (!newbon->SpellOnKill[i] || ((newbon->SpellOnKill[i] == limit_value) && (newbon->SpellOnKill[i + 1] < base_value))) { @@ -1038,7 +1038,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } break; - case SE_SpellOnDeath: + case SpellEffect::SpellOnDeath: for (int i = 0; i < MAX_SPELL_TRIGGER * 2; i += 2) { if (!newbon->SpellOnDeath[i]) { // base1 = SpellID to be triggered, base2 = chance to fire @@ -1049,8 +1049,8 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } break; - case SE_WeaponProc: - case SE_AddMeleeProc: + case SpellEffect::WeaponProc: + case SpellEffect::AddMeleeProc: for (int i = 0; i < MAX_AA_PROCS; i += 4) { if (!newbon->SpellProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID]) { newbon->SpellProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] = rank.id; //aa rank id @@ -1062,7 +1062,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } break; - case SE_RangedProc: + case SpellEffect::RangedProc: for (int i = 0; i < MAX_AA_PROCS; i += 4) { if (!newbon->RangedProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID]) { newbon->RangedProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] = rank.id; //aa rank id @@ -1074,7 +1074,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } break; - case SE_DefensiveProc: + case SpellEffect::DefensiveProc: for (int i = 0; i < MAX_AA_PROCS; i += 4) { if (!newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID]) { newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] = rank.id; //aa rank id @@ -1086,7 +1086,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } break; - case SE_Proc_Timer_Modifier: { + case SpellEffect::Proc_Timer_Modifier: { /* AA can multiples of this in a single effect, proc should use the timer that comes after the respective proc spell effect, thus rank.id will be already set @@ -1120,7 +1120,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_CriticalHitChance: { + case SpellEffect::CriticalHitChance: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) break; @@ -1130,7 +1130,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->CriticalHitChance[limit_value] += base_value; } break; - case SE_CriticalDamageMob: { + case SpellEffect::CriticalDamageMob: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) break; @@ -1142,7 +1142,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_Critical_Melee_Damage_Mod_Max: + case SpellEffect::Critical_Melee_Damage_Mod_Max: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) @@ -1155,7 +1155,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_CriticalSpellChance: { + case SpellEffect::CriticalSpellChance: { newbon->CriticalSpellChance += base_value; if (limit_value > newbon->SpellCritDmgIncNoStack) @@ -1164,12 +1164,12 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_ResistFearChance: { + case SpellEffect::ResistFearChance: { newbon->ResistFearChance += base_value; // these should stack break; } - case SE_SkillDamageAmount: { + case SpellEffect::SkillDamageAmount: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) break; @@ -1180,7 +1180,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_SkillAttackProc: { + case SpellEffect::SkillAttackProc: { for (int i = 0; i < MAX_CAST_ON_SKILL_USE; i += 3) { if (!newbon->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]) { // spell id newbon->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID] = rank.spell; // spell to proc @@ -1196,7 +1196,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_DamageModifier: { + case SpellEffect::DamageModifier: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) break; @@ -1207,7 +1207,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_DamageModifier2: { + case SpellEffect::DamageModifier2: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) break; @@ -1218,7 +1218,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_Skill_Base_Damage_Mod: { + case SpellEffect::Skill_Base_Damage_Mod: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) break; @@ -1229,7 +1229,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_SlayUndead: { + case SpellEffect::SlayUndead: { if (newbon->SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] < base_value) { newbon->SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] = base_value; // Rate newbon->SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] = limit_value; // Damage Modifier @@ -1237,12 +1237,12 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_DoubleRiposte: { + case SpellEffect::DoubleRiposte: { newbon->DoubleRiposte += base_value; break; } - case SE_GiveDoubleRiposte: { + case SpellEffect::GiveDoubleRiposte: { // 0=Regular Riposte 1=Skill Attack Riposte 2=Skill if (limit_value == 0) { if (newbon->GiveDoubleRiposte[SBIndex::DOUBLE_RIPOSTE_CHANCE] < base_value) @@ -1258,7 +1258,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } // Physically raises skill cap ie if 55/55 it will raise to 55/60 - case SE_RaiseSkillCap: { + case SpellEffect::RaiseSkillCap: { if (limit_value > EQ::skills::HIGHEST_SKILL) break; @@ -1268,23 +1268,23 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_MasteryofPast: { + case SpellEffect::MasteryofPast: { if (newbon->MasteryofPast < base_value) newbon->MasteryofPast = base_value; break; } - case SE_CastingLevel: { + case SpellEffect::CastingLevel: { newbon->adjusted_casting_skill += base_value; break; } - case SE_CastingLevel2: { + case SpellEffect::CastingLevel2: { newbon->effective_casting_level += base_value; break; } - case SE_DivineSave: { + case SpellEffect::DivineSave: { if (newbon->DivineSaveChance[SBIndex::DIVINE_SAVE_CHANCE] < base_value) { newbon->DivineSaveChance[SBIndex::DIVINE_SAVE_CHANCE] = base_value; newbon->DivineSaveChance[SBIndex::DIVINE_SAVE_SPELL_TRIGGER_ID] = limit_value; @@ -1292,7 +1292,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_SpellEffectResistChance: { + case SpellEffect::SpellEffectResistChance: { for (int e = 0; e < MAX_RESISTABLE_EFFECTS * 2; e += 2) { if ( !newbon->SEResist[e + 1] || @@ -1310,7 +1310,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_MitigateDamageShield: { + case SpellEffect::MitigateDamageShield: { //AA that increase mitigation are set to negative. if (base_value < 0) { @@ -1321,7 +1321,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_FinishingBlow: { + case SpellEffect::FinishingBlow: { // base1 = chance, base2 = damage if (newbon->FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] < limit_value) { newbon->FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = base_value; @@ -1330,7 +1330,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_FinishingBlowLvl: { + case SpellEffect::FinishingBlowLvl: { // base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) if (newbon->FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] < base_value) { newbon->FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = base_value; @@ -1339,23 +1339,23 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_StunBashChance: + case SpellEffect::StunBashChance: newbon->StunBashChance += base_value; break; - case SE_IncreaseChanceMemwipe: + case SpellEffect::IncreaseChanceMemwipe: newbon->IncreaseChanceMemwipe += base_value; break; - case SE_CriticalMend: + case SpellEffect::CriticalMend: newbon->CriticalMend += base_value; break; - case SE_HealRate: + case SpellEffect::HealRate: newbon->HealRate += base_value; break; - case SE_MeleeLifetap: { + case SpellEffect::MeleeLifetap: { if ((base_value < 0) && (newbon->MeleeLifetap > base_value)) newbon->MeleeLifetap = base_value; @@ -1365,27 +1365,27 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_Vampirism: + case SpellEffect::Vampirism: newbon->Vampirism += base_value; break; - case SE_FrenziedDevastation: + case SpellEffect::FrenziedDevastation: newbon->FrenziedDevastation += limit_value; break; - case SE_SpellProcChance: + case SpellEffect::SpellProcChance: newbon->SpellProcChance += base_value; break; - case SE_Berserk: + case SpellEffect::Berserk: newbon->BerserkSPA = true; break; - case SE_Metabolism: + case SpellEffect::Metabolism: newbon->Metabolism += base_value; break; - case SE_ImprovedReclaimEnergy: { + case SpellEffect::ImprovedReclaimEnergy: { if ((base_value < 0) && (newbon->ImprovedReclaimEnergy > base_value)) newbon->ImprovedReclaimEnergy = base_value; @@ -1394,7 +1394,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_HeadShot: { + case SpellEffect::HeadShot: { if (newbon->HeadShot[SBIndex::FINISHING_EFFECT_DMG] < limit_value) { newbon->HeadShot[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = base_value; newbon->HeadShot[SBIndex::FINISHING_EFFECT_DMG] = limit_value; @@ -1402,7 +1402,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_HeadShotLevel: { + case SpellEffect::HeadShotLevel: { if (newbon->HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] < base_value) { newbon->HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = base_value; newbon->HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = limit_value; @@ -1410,7 +1410,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_Assassinate: { + case SpellEffect::Assassinate: { if (newbon->Assassinate[SBIndex::FINISHING_EFFECT_DMG] < limit_value) { newbon->Assassinate[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = base_value; newbon->Assassinate[SBIndex::FINISHING_EFFECT_DMG] = limit_value; @@ -1418,7 +1418,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_AssassinateLevel: { + case SpellEffect::AssassinateLevel: { if (newbon->AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] < base_value) { newbon->AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = base_value; newbon->AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = limit_value; @@ -1426,11 +1426,11 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_PetMeleeMitigation: + case SpellEffect::PetMeleeMitigation: newbon->PetMeleeMitigation += base_value; break; - case SE_FactionModPct: { + case SpellEffect::FactionModPct: { if ((base_value < 0) && (newbon->FactionModPct > base_value)) newbon->FactionModPct = base_value; @@ -1439,15 +1439,15 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_Illusion: + case SpellEffect::Illusion: newbon->Illusion = rank.spell; break; - case SE_IllusionPersistence: + case SpellEffect::IllusionPersistence: newbon->IllusionPersistence = base_value; break; - case SE_LimitToSkill: { + case SpellEffect::LimitToSkill: { // Bad data or unsupported new skill if (base_value > EQ::skills::HIGHEST_SKILL) { @@ -1460,7 +1460,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_SkillProcAttempt: { + case SpellEffect::SkillProcAttempt: { for (int e = 0; e < MAX_SKILL_PROCS; e++) { if (newbon->SkillProc[e] && newbon->SkillProc[e] == rank.id) break; // Do not use the same aa id more than once. @@ -1473,7 +1473,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_SkillProcSuccess: { + case SpellEffect::SkillProcSuccess: { for (int e = 0; e < MAX_SKILL_PROCS; e++) { if (newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == rank.id) @@ -1487,44 +1487,44 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_MeleeMitigation: + case SpellEffect::MeleeMitigation: newbon->MeleeMitigationEffect += base_value; break; - case SE_ATK: + case SpellEffect::ATK: newbon->ATK += base_value; break; - case SE_IncreaseExtTargetWindow: + case SpellEffect::IncreaseExtTargetWindow: newbon->extra_xtargets += base_value; break; - case SE_PC_Pet_Rampage: { + case SpellEffect::PC_Pet_Rampage: { newbon->PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE] += base_value; //Chance to rampage if (newbon->PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] < limit_value) newbon->PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = limit_value; //Damage modifer - take highest break; } - case SE_PC_Pet_AE_Rampage: { + case SpellEffect::PC_Pet_AE_Rampage: { newbon->PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_CHANCE] += base_value; //Chance to rampage if (newbon->PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] < limit_value) newbon->PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = limit_value; //Damage modifer - take highest break; } - case SE_PC_Pet_Flurry_Chance: + case SpellEffect::PC_Pet_Flurry_Chance: newbon->PC_Pet_Flurry += base_value; //Chance to Flurry break; - case SE_ShroudofStealth: + case SpellEffect::ShroudofStealth: newbon->ShroudofStealth = true; break; - case SE_ReduceFallDamage: + case SpellEffect::ReduceFallDamage: newbon->ReduceFallDamage += base_value; break; - case SE_ReduceTradeskillFail:{ + case SpellEffect::ReduceTradeskillFail:{ if (limit_value > EQ::skills::HIGHEST_SKILL) break; @@ -1533,42 +1533,42 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_TradeSkillMastery: + case SpellEffect::TradeSkillMastery: if (newbon->TradeSkillMastery < base_value) newbon->TradeSkillMastery = base_value; break; - case SE_NoBreakAESneak: + case SpellEffect::NoBreakAESneak: if (newbon->NoBreakAESneak < base_value) newbon->NoBreakAESneak = base_value; break; - case SE_FeignedCastOnChance: + case SpellEffect::FeignedCastOnChance: if (newbon->FeignedCastOnChance < base_value) newbon->FeignedCastOnChance = base_value; break; - case SE_AddPetCommand: + case SpellEffect::AddPetCommand: if (base_value && limit_value < PetCommand::Max) newbon->PetCommands[limit_value] = true; break; - case SE_FeignedMinion: + case SpellEffect::FeignedMinion: if (newbon->FeignedMinionChance < base_value) { newbon->FeignedMinionChance = base_value; } newbon->PetCommands[PetCommand::Feign] = true; break; - case SE_AdditionalAura: + case SpellEffect::AdditionalAura: newbon->aura_slots += base_value; break; - case SE_IncreaseTrapCount: + case SpellEffect::IncreaseTrapCount: newbon->trap_slots += base_value; break; - case SE_ForageSkill: + case SpellEffect::ForageSkill: newbon->GrantForage += base_value; // we need to grant a skill point here // I'd rather not do this here, but whatever, probably fine @@ -1579,19 +1579,19 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } break; - case SE_Attack_Accuracy_Max_Percent: + case SpellEffect::Attack_Accuracy_Max_Percent: newbon->Attack_Accuracy_Max_Percent += base_value; break; - case SE_AC_Mitigation_Max_Percent: + case SpellEffect::AC_Mitigation_Max_Percent: newbon->AC_Mitigation_Max_Percent += base_value; break; - case SE_AC_Avoidance_Max_Percent: + case SpellEffect::AC_Avoidance_Max_Percent: newbon->AC_Avoidance_Max_Percent += base_value; break; - case SE_Damage_Taken_Position_Mod: + case SpellEffect::Damage_Taken_Position_Mod: { //Mitigate if damage taken from behind base2 = 0, from front base2 = 1 if (limit_value < 0 || limit_value >= 2) { @@ -1604,7 +1604,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_Melee_Damage_Position_Mod: + case SpellEffect::Melee_Damage_Position_Mod: { if (limit_value < 0 || limit_value >= 2) { break; @@ -1616,7 +1616,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_Damage_Taken_Position_Amt: + case SpellEffect::Damage_Taken_Position_Amt: { //Mitigate if damage taken from behind base2 = 0, from front base2 = 1 if (limit_value < 0 || limit_value >= 2) { @@ -1626,7 +1626,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_Melee_Damage_Position_Amt: + case SpellEffect::Melee_Damage_Position_Amt: { //Mitigate if damage taken from behind base2 = 0, from front base2 = 1 if (limit_value < 0 || limit_value >= 2) { @@ -1637,23 +1637,23 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_DS_Mitigation_Amount: + case SpellEffect::DS_Mitigation_Amount: newbon->DS_Mitigation_Amount += base_value; break; - case SE_DS_Mitigation_Percentage: + case SpellEffect::DS_Mitigation_Percentage: newbon->DS_Mitigation_Percentage += base_value; break; - case SE_Pet_Crit_Melee_Damage_Pct_Owner: + case SpellEffect::Pet_Crit_Melee_Damage_Pct_Owner: newbon->Pet_Crit_Melee_Damage_Pct_Owner += base_value; break; - case SE_Pet_Add_Atk: + case SpellEffect::Pet_Add_Atk: newbon->Pet_Add_Atk += base_value; break; - case SE_Weapon_Stance: + case SpellEffect::Weapon_Stance: { if (IsValidSpell(base_value)) { //base1 is the spell_id of buff if (limit_value <= WEAPON_STANCE_TYPE_MAX) { //0=2H, 1=Shield, 2=DW @@ -1672,7 +1672,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_ExtraAttackChance: + case SpellEffect::ExtraAttackChance: { if (newbon->ExtraAttackChance[SBIndex::EXTRA_ATTACK_CHANCE] < base_value) { newbon->ExtraAttackChance[SBIndex::EXTRA_ATTACK_CHANCE] = base_value; @@ -1681,7 +1681,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_AddExtraAttackPct_1h_Primary: + case SpellEffect::AddExtraAttackPct_1h_Primary: { if (newbon->ExtraAttackChancePrimary[SBIndex::EXTRA_ATTACK_CHANCE] < base_value) { newbon->ExtraAttackChancePrimary[SBIndex::EXTRA_ATTACK_CHANCE] = base_value; @@ -1690,7 +1690,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_AddExtraAttackPct_1h_Secondary: + case SpellEffect::AddExtraAttackPct_1h_Secondary: { if (newbon->ExtraAttackChanceSecondary[SBIndex::EXTRA_ATTACK_CHANCE] < base_value) { @@ -1700,7 +1700,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_Double_Melee_Round: + case SpellEffect::Double_Melee_Round: { if (newbon->DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] < base_value) { newbon->DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] = base_value; @@ -1710,7 +1710,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_ExtendedShielding: + case SpellEffect::ExtendedShielding: { if (newbon->ExtendedShielding < base_value) { newbon->ExtendedShielding = base_value; @@ -1718,7 +1718,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_ShieldDuration: + case SpellEffect::ShieldDuration: { if (newbon->ShieldDuration < base_value) { newbon->ShieldDuration = base_value; @@ -1726,23 +1726,23 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; } - case SE_Worn_Endurance_Regen_Cap: + case SpellEffect::Worn_Endurance_Regen_Cap: newbon->ItemEnduranceRegenCap += base_value; break; - case SE_SecondaryForte: + case SpellEffect::SecondaryForte: if (newbon->SecondaryForte < base_value) { newbon->SecondaryForte = base_value; } break; - case SE_ZoneSuspendMinion: + case SpellEffect::ZoneSuspendMinion: newbon->ZoneSuspendMinion = base_value; break; - case SE_Reflect: + case SpellEffect::Reflect: if (newbon->reflect[SBIndex::REFLECT_CHANCE] < base_value) { newbon->reflect[SBIndex::REFLECT_CHANCE] = base_value; @@ -1752,69 +1752,69 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } break; - case SE_SpellDamageShield: + case SpellEffect::SpellDamageShield: newbon->SpellDamageShield += base_value; break; - case SE_Amplification: + case SpellEffect::Amplification: newbon->Amplification += base_value; break; - case SE_MitigateSpellDamage: + case SpellEffect::MitigateSpellDamage: { newbon->MitigateSpellRune[SBIndex::MITIGATION_RUNE_PERCENT] += base_value; break; } - case SE_MitigateDotDamage: + case SpellEffect::MitigateDotDamage: { newbon->MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT] += base_value; break; } - case SE_TrapCircumvention: + case SpellEffect::TrapCircumvention: newbon->TrapCircumvention += base_value; break; // to do - case SE_PetDiscipline: + case SpellEffect::PetDiscipline: break; - case SE_PotionBeltSlots: + case SpellEffect::PotionBeltSlots: break; - case SE_BandolierSlots: + case SpellEffect::BandolierSlots: break; - case SE_ReduceApplyPoisonTime: + case SpellEffect::ReduceApplyPoisonTime: break; - case SE_NimbleEvasion: + case SpellEffect::NimbleEvasion: break; // not handled here - case SE_HastenedAASkill: + case SpellEffect::HastenedAASkill: // not handled here but don't want to clutter debug log -- these may need to be verified to ignore - case SE_LimitMaxLevel: - case SE_LimitResist: - case SE_LimitTarget: - case SE_LimitEffect: - case SE_LimitSpellType: - case SE_LimitMinDur: - case SE_LimitInstant: - case SE_LimitMinLevel: - case SE_LimitCastTimeMin: - case SE_LimitCastTimeMax: - case SE_LimitSpell: - case SE_LimitCombatSkills: - case SE_LimitManaMin: - case SE_LimitSpellGroup: - case SE_LimitSpellClass: - case SE_LimitSpellSubclass: - case SE_LimitHPPercent: - case SE_LimitManaPercent: - case SE_LimitEndPercent: - case SE_LimitClass: - case SE_LimitRace: - case SE_LimitCastingSkill: - case SE_LimitUseMin: - case SE_LimitUseType: + case SpellEffect::LimitMaxLevel: + case SpellEffect::LimitResist: + case SpellEffect::LimitTarget: + case SpellEffect::LimitEffect: + case SpellEffect::LimitSpellType: + case SpellEffect::LimitMinDur: + case SpellEffect::LimitInstant: + case SpellEffect::LimitMinLevel: + case SpellEffect::LimitCastTimeMin: + case SpellEffect::LimitCastTimeMax: + case SpellEffect::LimitSpell: + case SpellEffect::LimitCombatSkills: + case SpellEffect::LimitManaMin: + case SpellEffect::LimitSpellGroup: + case SpellEffect::LimitSpellClass: + case SpellEffect::LimitSpellSubclass: + case SpellEffect::LimitHPPercent: + case SpellEffect::LimitManaPercent: + case SpellEffect::LimitEndPercent: + case SpellEffect::LimitClass: + case SpellEffect::LimitRace: + case SpellEffect::LimitCastingSkill: + case SpellEffect::LimitUseMin: + case SpellEffect::LimitUseType: break; default: @@ -1851,7 +1851,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) //Disables a specific spell effect bonus completely, can also be limited to negate only item, AA or spell bonuses. if (spellbonuses.NegateEffects){ for(i = 0; i < buff_count; i++) { - if(IsValidSpell(buffs[i].spellid) && (IsEffectInSpell(buffs[i].spellid, SE_NegateSpellEffect)) ) + if(IsValidSpell(buffs[i].spellid) && (IsEffectInSpell(buffs[i].spellid, SpellEffect::NegateSpellEffect)) ) NegateSpellEffectBonuses(buffs[i].spellid); } } @@ -1913,7 +1913,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table //Non-Focused Effect to modify incoming spell damage by resist type. - if (spell_effect_id == SE_FcSpellVulnerability) { + if (spell_effect_id == SpellEffect::FcSpellVulnerability) { ModVulnerability(limit_value, effect_value); } @@ -1922,17 +1922,17 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne switch (spell_effect_id) { - case SE_CurrentHP: //regens + case SpellEffect::CurrentHP: //regens if(effect_value > 0) { new_bonus->HPRegen += effect_value; } break; - case SE_CurrentEndurance: + case SpellEffect::CurrentEndurance: new_bonus->EnduranceRegen += effect_value; break; - case SE_ChangeFrenzyRad: + case SpellEffect::ChangeFrenzyRad: { if (max_value != 0 && GetLevel() > max_value) break; @@ -1944,7 +1944,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Harmony: + case SpellEffect::Harmony: { if (max_value != 0 && GetLevel() > max_value) break; @@ -1958,7 +1958,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_AttackSpeed: + case SpellEffect::AttackSpeed: { if ((effect_value - 100) > 0) { // Haste if (new_bonus->haste < 0) break; // Slowed - Don't apply haste @@ -1975,7 +1975,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_AttackSpeed2: + case SpellEffect::AttackSpeed2: { if ((effect_value - 100) > 0) { // Haste V2 - Stacks with V1 but does not Overcap if (new_bonus->hastetype2 < 0) break; //Slowed - Don't apply haste2 @@ -1992,7 +1992,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_AttackSpeed3: + case SpellEffect::AttackSpeed3: { if (effect_value < 0){ //Slow effect_value -= (effect_value * GetSlowMitigation()/100); @@ -2008,7 +2008,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_AttackSpeed4: + case SpellEffect::AttackSpeed4: { // These don't generate the IMMUNE_ATKSPEED message and the icon shows up // but have no effect on the mobs attack speed @@ -2027,87 +2027,87 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_IncreaseArchery: + case SpellEffect::IncreaseArchery: { new_bonus->increase_archery += effect_value; break; } - case SE_TotalHP: + case SpellEffect::TotalHP: { new_bonus->FlatMaxHPChange += effect_value; break; } - case SE_ManaRegen_v2: - case SE_CurrentMana: + case SpellEffect::ManaRegen_v2: + case SpellEffect::CurrentMana: { new_bonus->ManaRegen += effect_value; break; } - case SE_ManaPool: + case SpellEffect::ManaPool: { new_bonus->Mana += effect_value; break; } - case SE_Stamina: + case SpellEffect::Stamina: { new_bonus->EnduranceReduction += effect_value; break; } - case SE_ACv2: - case SE_ArmorClass: + case SpellEffect::ACv2: + case SpellEffect::ArmorClass: { new_bonus->AC += effect_value; break; } - case SE_ATK: + case SpellEffect::ATK: { new_bonus->ATK += effect_value; break; } - case SE_STR: + case SpellEffect::STR: { new_bonus->STR += effect_value; break; } - case SE_DEX: + case SpellEffect::DEX: { new_bonus->DEX += effect_value; break; } - case SE_AGI: + case SpellEffect::AGI: { new_bonus->AGI += effect_value; break; } - case SE_STA: + case SpellEffect::STA: { new_bonus->STA += effect_value; break; } - case SE_INT: + case SpellEffect::INT: { new_bonus->INT += effect_value; break; } - case SE_WIS: + case SpellEffect::WIS: { new_bonus->WIS += effect_value; break; } - case SE_CHA: + case SpellEffect::CHA: { if (spells[spell_id].base_value[i] != 0) { new_bonus->CHA += effect_value; @@ -2115,7 +2115,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_AllStats: + case SpellEffect::AllStats: { new_bonus->STR += effect_value; new_bonus->DEX += effect_value; @@ -2127,37 +2127,37 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_ResistFire: + case SpellEffect::ResistFire: { new_bonus->FR += effect_value; break; } - case SE_ResistCold: + case SpellEffect::ResistCold: { new_bonus->CR += effect_value; break; } - case SE_ResistPoison: + case SpellEffect::ResistPoison: { new_bonus->PR += effect_value; break; } - case SE_ResistDisease: + case SpellEffect::ResistDisease: { new_bonus->DR += effect_value; break; } - case SE_ResistMagic: + case SpellEffect::ResistMagic: { new_bonus->MR += effect_value; break; } - case SE_ResistAll: + case SpellEffect::ResistAll: { new_bonus->MR += effect_value; new_bonus->DR += effect_value; @@ -2167,13 +2167,13 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_ResistCorruption: + case SpellEffect::ResistCorruption: { new_bonus->Corrup += effect_value; break; } - case SE_RaiseStatCap: + case SpellEffect::RaiseStatCap: { switch(spells[spell_id].limit_value[i]) { @@ -2221,13 +2221,13 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_CastingLevel: // Brilliance of Ro + case SpellEffect::CastingLevel: // Brilliance of Ro { new_bonus->adjusted_casting_skill += effect_value; break; } - case SE_CastingLevel2: + case SpellEffect::CastingLevel2: { new_bonus->effective_casting_level += effect_value; @@ -2237,15 +2237,15 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_MovementSpeed: + case SpellEffect::MovementSpeed: new_bonus->movementspeed += effect_value; break; - case SE_SpellDamageShield: + case SpellEffect::SpellDamageShield: new_bonus->SpellDamageShield += effect_value; break; - case SE_DamageShield: + case SpellEffect::DamageShield: { new_bonus->DamageShield += effect_value; new_bonus->DamageShieldSpellID = spell_id; @@ -2258,7 +2258,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_ReverseDS: + case SpellEffect::ReverseDS: { new_bonus->ReverseDamageShield += effect_value; new_bonus->ReverseDamageShieldSpellID = spell_id; @@ -2270,7 +2270,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Reflect: + case SpellEffect::Reflect: if (AdditiveWornBonus) { new_bonus->reflect[SBIndex::REFLECT_CHANCE] += effect_value; @@ -2283,20 +2283,20 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne } break; - case SE_Amplification: + case SpellEffect::Amplification: new_bonus->Amplification += effect_value; break; - case SE_ChangeAggro: + case SpellEffect::ChangeAggro: new_bonus->hatemod += effect_value; break; - case SE_MeleeMitigation: + case SpellEffect::MeleeMitigation: // This value is negative because it counteracts another SPA :P new_bonus->MeleeMitigationEffect += effect_value; break; - case SE_CriticalHitChance: + case SpellEffect::CriticalHitChance: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) @@ -2325,7 +2325,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_CrippBlowChance: + case SpellEffect::CrippBlowChance: { if (AdditiveWornBonus) new_bonus->CrippBlowChance += effect_value; @@ -2339,7 +2339,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_AvoidMeleeChance: + case SpellEffect::AvoidMeleeChance: { if (AdditiveWornBonus) new_bonus->AvoidMeleeChanceEffect += effect_value; @@ -2352,7 +2352,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_RiposteChance: + case SpellEffect::RiposteChance: { if (AdditiveWornBonus) new_bonus->RiposteChance += effect_value; @@ -2365,7 +2365,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_DodgeChance: + case SpellEffect::DodgeChance: { if (AdditiveWornBonus) new_bonus->DodgeChance += effect_value; @@ -2378,7 +2378,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_ParryChance: + case SpellEffect::ParryChance: { if (AdditiveWornBonus) new_bonus->ParryChance += effect_value; @@ -2391,7 +2391,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_DualWieldChance: + case SpellEffect::DualWieldChance: { if (AdditiveWornBonus) new_bonus->DualWieldChance += effect_value; @@ -2404,7 +2404,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_DoubleAttackChance: + case SpellEffect::DoubleAttackChance: { if (AdditiveWornBonus) @@ -2418,7 +2418,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_TripleAttackChance: + case SpellEffect::TripleAttackChance: { if (AdditiveWornBonus) @@ -2432,7 +2432,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_MeleeLifetap: + case SpellEffect::MeleeLifetap: { if (AdditiveWornBonus) new_bonus->MeleeLifetap += spells[spell_id].base_value[i]; @@ -2445,11 +2445,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Vampirism: + case SpellEffect::Vampirism: new_bonus->Vampirism += effect_value; break; - case SE_AllInstrumentMod: + case SpellEffect::AllInstrumentMod: { if(effect_value > new_bonus->singingMod) new_bonus->singingMod = effect_value; @@ -2464,21 +2464,21 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_ResistSpellChance: + case SpellEffect::ResistSpellChance: new_bonus->ResistSpellChance += effect_value; break; - case SE_ResistFearChance: + case SpellEffect::ResistFearChance: { new_bonus->ResistFearChance += effect_value; // these should stack break; } - case SE_Fearless: + case SpellEffect::Fearless: new_bonus->Fearless = true; break; - case SE_HundredHands: + case SpellEffect::HundredHands: { if (AdditiveWornBonus) new_bonus->HundredHands += effect_value; @@ -2490,7 +2490,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_MeleeSkillCheck: + case SpellEffect::MeleeSkillCheck: { if(new_bonus->MeleeSkillCheck < effect_value) { new_bonus->MeleeSkillCheck = effect_value; @@ -2499,7 +2499,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_HitChance: + case SpellEffect::HitChance: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) @@ -2536,7 +2536,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne } - case SE_DamageModifier: + case SpellEffect::DamageModifier: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) @@ -2549,7 +2549,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_DamageModifier2: + case SpellEffect::DamageModifier2: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) @@ -2562,7 +2562,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Skill_Base_Damage_Mod: + case SpellEffect::Skill_Base_Damage_Mod: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) @@ -2575,7 +2575,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_MinDamageModifier: + case SpellEffect::MinDamageModifier: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) @@ -2588,7 +2588,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_ReduceSkill: { + case SpellEffect::ReduceSkill: { // Bad data or unsupported new skill if (spells[spell_id].base_value[i] > EQ::skills::HIGHEST_SKILL) { break; @@ -2607,14 +2607,14 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_StunResist: + case SpellEffect::StunResist: { if(new_bonus->StunResist < effect_value) new_bonus->StunResist = effect_value; break; } - case SE_ProcChance: + case SpellEffect::ProcChance: { if (AdditiveWornBonus) new_bonus->ProcChanceSPA += effect_value; @@ -2628,7 +2628,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_ExtraAttackChance: + case SpellEffect::ExtraAttackChance: { if (AdditiveWornBonus) { new_bonus->ExtraAttackChance[SBIndex::EXTRA_ATTACK_CHANCE] += effect_value; @@ -2641,7 +2641,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_AddExtraAttackPct_1h_Primary: + case SpellEffect::AddExtraAttackPct_1h_Primary: { if (AdditiveWornBonus) { new_bonus->ExtraAttackChancePrimary[SBIndex::EXTRA_ATTACK_CHANCE] += effect_value; @@ -2655,7 +2655,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_AddExtraAttackPct_1h_Secondary: + case SpellEffect::AddExtraAttackPct_1h_Secondary: { if (AdditiveWornBonus) { new_bonus->ExtraAttackChanceSecondary[SBIndex::EXTRA_ATTACK_CHANCE] += effect_value; @@ -2669,7 +2669,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Double_Melee_Round: + case SpellEffect::Double_Melee_Round: { if (AdditiveWornBonus) { new_bonus->DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] += effect_value; @@ -2683,14 +2683,14 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_PercentXPIncrease: + case SpellEffect::PercentXPIncrease: { if(new_bonus->XPRateMod < effect_value) new_bonus->XPRateMod = effect_value; break; } - case SE_DeathSave: + case SpellEffect::DeathSave: { if(new_bonus->DeathSave[SBIndex::DEATH_SAVE_TYPE] < effect_value) { @@ -2703,7 +2703,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_DivineSave: + case SpellEffect::DivineSave: { if (AdditiveWornBonus) { new_bonus->DivineSaveChance[SBIndex::DIVINE_SAVE_CHANCE] += effect_value; @@ -2718,11 +2718,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Flurry: + case SpellEffect::Flurry: new_bonus->FlurryChance += effect_value; break; - case SE_Accuracy: + case SpellEffect::Accuracy: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) @@ -2736,19 +2736,19 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_MaxHPChange: + case SpellEffect::MaxHPChange: new_bonus->PercentMaxHPChange += effect_value; break; - case SE_EndurancePool: + case SpellEffect::EndurancePool: new_bonus->Endurance += effect_value; break; - case SE_HealRate: + case SpellEffect::HealRate: new_bonus->HealRate += effect_value; break; - case SE_SkillDamageTaken: + case SpellEffect::SkillDamageTaken: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) @@ -2771,11 +2771,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_SpellCritChance: + case SpellEffect::SpellCritChance: new_bonus->CriticalSpellChance += effect_value; break; - case SE_CriticalSpellChance: + case SpellEffect::CriticalSpellChance: { new_bonus->CriticalSpellChance += effect_value; @@ -2784,35 +2784,35 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_SpellCritDmgIncrease: + case SpellEffect::SpellCritDmgIncrease: new_bonus->SpellCritDmgIncrease += effect_value; break; - case SE_DotCritDmgIncrease: + case SpellEffect::DotCritDmgIncrease: new_bonus->DotCritDmgIncrease += effect_value; break; - case SE_CriticalHealChance: + case SpellEffect::CriticalHealChance: new_bonus->CriticalHealChance += effect_value; break; - case SE_CriticalHealOverTime: + case SpellEffect::CriticalHealOverTime: new_bonus->CriticalHealOverTime += effect_value; break; - case SE_CriticalHealDecay: + case SpellEffect::CriticalHealDecay: new_bonus->CriticalHealDecay = true; break; - case SE_CriticalRegenDecay: + case SpellEffect::CriticalRegenDecay: new_bonus->CriticalRegenDecay = true; break; - case SE_CriticalDotDecay: + case SpellEffect::CriticalDotDecay: new_bonus->CriticalDotDecay = true; break; - case SE_MitigateDamageShield: + case SpellEffect::MitigateDamageShield: { /* Bard songs have identical negative base value and positive max @@ -2828,11 +2828,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_CriticalDoTChance: + case SpellEffect::CriticalDoTChance: new_bonus->CriticalDoTChance += effect_value; break; - case SE_ProcOnKillShot: + case SpellEffect::ProcOnKillShot: { for(int e = 0; e < MAX_SPELL_TRIGGER*3; e+=3) { @@ -2848,7 +2848,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_SpellOnDeath: + case SpellEffect::SpellOnDeath: { for(int e = 0; e < MAX_SPELL_TRIGGER; e+=2) { @@ -2863,7 +2863,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_CriticalDamageMob: + case SpellEffect::CriticalDamageMob: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) @@ -2875,7 +2875,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Critical_Melee_Damage_Mod_Max: + case SpellEffect::Critical_Melee_Damage_Mod_Max: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) @@ -2889,14 +2889,14 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_ReduceSkillTimer: + case SpellEffect::ReduceSkillTimer: { if(new_bonus->SkillReuseTime[limit_value] < effect_value) new_bonus->SkillReuseTime[limit_value] = effect_value; break; } - case SE_SkillDamageAmount: + case SpellEffect::SkillDamageAmount: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) @@ -2908,23 +2908,23 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_GravityEffect: + case SpellEffect::GravityEffect: new_bonus->GravityEffect = 1; break; - case SE_AntiGate: + case SpellEffect::AntiGate: new_bonus->AntiGate = true; break; - case SE_MagicWeapon: + case SpellEffect::MagicWeapon: new_bonus->MagicWeapon = true; break; - case SE_Hunger: + case SpellEffect::Hunger: new_bonus->hunger = true; break; - case SE_IncreaseBlockChance: + case SpellEffect::IncreaseBlockChance: if (AdditiveWornBonus) new_bonus->IncreaseBlockChance += effect_value; else if (effect_value < 0 && new_bonus->IncreaseBlockChance > effect_value) @@ -2933,11 +2933,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne new_bonus->IncreaseBlockChance = effect_value; break; - case SE_PersistantCasting: + case SpellEffect::PersistantCasting: new_bonus->PersistantCasting += effect_value; break; - case SE_LimitHPPercent: + case SpellEffect::LimitHPPercent: { if(new_bonus->HPPercCap[SBIndex::RESOURCE_PERCENT_CAP] != 0 && new_bonus->HPPercCap[SBIndex::RESOURCE_PERCENT_CAP] > effect_value){ new_bonus->HPPercCap[SBIndex::RESOURCE_PERCENT_CAP] = effect_value; @@ -2949,7 +2949,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne } break; } - case SE_LimitManaPercent: + case SpellEffect::LimitManaPercent: { if(new_bonus->ManaPercCap[SBIndex::RESOURCE_PERCENT_CAP] != 0 && new_bonus->ManaPercCap[SBIndex::RESOURCE_PERCENT_CAP] > effect_value){ new_bonus->ManaPercCap[SBIndex::RESOURCE_PERCENT_CAP] = effect_value; @@ -2962,7 +2962,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_LimitEndPercent: + case SpellEffect::LimitEndPercent: { if(new_bonus->EndPercCap[SBIndex::RESOURCE_PERCENT_CAP] != 0 && new_bonus->EndPercCap[SBIndex::RESOURCE_PERCENT_CAP] > effect_value) { new_bonus->EndPercCap[SBIndex::RESOURCE_PERCENT_CAP] = effect_value; @@ -2977,33 +2977,33 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_NegateSpellEffect: + case SpellEffect::NegateSpellEffect: new_bonus->NegateEffects = true; break; - case SE_ImmuneFleeing: + case SpellEffect::ImmuneFleeing: new_bonus->ImmuneToFlee = true; if (currently_fleeing) // lets update shit now instead of next tick ProcessFlee(); break; - case SE_DelayDeath: + case SpellEffect::DelayDeath: new_bonus->DelayDeath += effect_value; break; - case SE_SpellProcChance: + case SpellEffect::SpellProcChance: new_bonus->SpellProcChance += effect_value; break; - case SE_CharmBreakChance: + case SpellEffect::CharmBreakChance: new_bonus->CharmBreakChance += effect_value; break; - case SE_BardSongRange: + case SpellEffect::BardSongRange: new_bonus->SongRange += effect_value; break; - case SE_HPToMana: + case SpellEffect::HPToMana: { //Lower the ratio the more favorable if ((!new_bonus->HPToManaConvert) || (new_bonus->HPToManaConvert >= effect_value)) { @@ -3012,7 +3012,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_SkillDamageAmount2: + case SpellEffect::SkillDamageAmount2: { // Bad data or unsupported new skill if (limit_value > EQ::skills::HIGHEST_SKILL) @@ -3024,7 +3024,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_NegateAttacks: + case SpellEffect::NegateAttacks: { if ( !new_bonus->NegateAttacks[SBIndex::NEGATE_ATK_EXISTS] || @@ -3040,7 +3040,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_MitigateMeleeDamage: + case SpellEffect::MitigateMeleeDamage: { if (new_bonus->MitigateMeleeRune[SBIndex::MITIGATION_RUNE_PERCENT] < effect_value){ new_bonus->MitigateMeleeRune[SBIndex::MITIGATION_RUNE_PERCENT] = effect_value; @@ -3052,7 +3052,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne } - case SE_MeleeThresholdGuard: + case SpellEffect::MeleeThresholdGuard: { if (new_bonus->MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT] < effect_value){ new_bonus->MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT] = effect_value; @@ -3062,7 +3062,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_SpellThresholdGuard: + case SpellEffect::SpellThresholdGuard: { if (new_bonus->SpellThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT] < effect_value){ new_bonus->SpellThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT] = effect_value; @@ -3072,7 +3072,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_MitigateSpellDamage: + case SpellEffect::MitigateSpellDamage: { if (WornType) { new_bonus->MitigateSpellRune[SBIndex::MITIGATION_RUNE_PERCENT] += effect_value; @@ -3087,7 +3087,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_MitigateDotDamage: + case SpellEffect::MitigateDotDamage: { if (WornType) { new_bonus->MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT] += effect_value; @@ -3102,7 +3102,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_ManaAbsorbPercentDamage: + case SpellEffect::ManaAbsorbPercentDamage: { if (new_bonus->ManaAbsorbPercentDamage < effect_value){ new_bonus->ManaAbsorbPercentDamage = effect_value; @@ -3110,7 +3110,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Endurance_Absorb_Pct_Damage: + case SpellEffect::Endurance_Absorb_Pct_Damage: { if (new_bonus->EnduranceAbsorbPercentDamage[SBIndex::ENDURANCE_ABSORD_MITIGIATION] < effect_value) { new_bonus->EnduranceAbsorbPercentDamage[SBIndex::ENDURANCE_ABSORD_MITIGIATION] = effect_value; @@ -3119,7 +3119,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Shield_Target: + case SpellEffect::Shield_Target: { if (new_bonus->ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT] < effect_value) { new_bonus->ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT] = effect_value; @@ -3128,27 +3128,27 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_TriggerMeleeThreshold: + case SpellEffect::TriggerMeleeThreshold: new_bonus->TriggerMeleeThreshold = true; break; - case SE_TriggerSpellThreshold: + case SpellEffect::TriggerSpellThreshold: new_bonus->TriggerSpellThreshold = true; break; - case SE_ShieldBlock: + case SpellEffect::ShieldBlock: new_bonus->ShieldBlock += effect_value; break; - case SE_ShieldEquipDmgMod: + case SpellEffect::ShieldEquipDmgMod: new_bonus->ShieldEquipDmgMod += effect_value; break; - case SE_BlockBehind: + case SpellEffect::BlockBehind: new_bonus->BlockBehind += effect_value; break; - case SE_Blind: + case SpellEffect::Blind: if (!RuleB(Combat, AllowRaidTargetBlind) && IsRaidTarget()) { // do not blind raid targets break; } @@ -3156,93 +3156,93 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne new_bonus->IsBlind = true; break; - case SE_Fear: + case SpellEffect::Fear: new_bonus->IsFeared = true; break; //AA bonuses - implemented broadly into spell/item effects - case SE_FrontalStunResist: + case SpellEffect::FrontalStunResist: new_bonus->FrontalStunResist += effect_value; break; - case SE_ImprovedBindWound: + case SpellEffect::ImprovedBindWound: new_bonus->BindWound += effect_value; break; - case SE_MaxBindWound: + case SpellEffect::MaxBindWound: new_bonus->MaxBindWound += effect_value; break; - case SE_BaseMovementSpeed: + case SpellEffect::BaseMovementSpeed: new_bonus->BaseMovementSpeed += effect_value; break; - case SE_IncreaseRunSpeedCap: + case SpellEffect::IncreaseRunSpeedCap: new_bonus->IncreaseRunSpeedCap += effect_value; break; - case SE_DoubleSpecialAttack: + case SpellEffect::DoubleSpecialAttack: new_bonus->DoubleSpecialAttack += effect_value; break; - case SE_TripleBackstab: + case SpellEffect::TripleBackstab: new_bonus->TripleBackstab += effect_value; break; - case SE_FrontalBackstabMinDmg: + case SpellEffect::FrontalBackstabMinDmg: new_bonus->FrontalBackstabMinDmg = true; break; - case SE_FrontalBackstabChance: + case SpellEffect::FrontalBackstabChance: new_bonus->FrontalBackstabChance += effect_value; break; - case SE_Double_Backstab_Front: + case SpellEffect::Double_Backstab_Front: new_bonus->Double_Backstab_Front += effect_value; break; - case SE_ConsumeProjectile: + case SpellEffect::ConsumeProjectile: new_bonus->ConsumeProjectile += effect_value; break; - case SE_ForageAdditionalItems: + case SpellEffect::ForageAdditionalItems: new_bonus->ForageAdditionalItems += effect_value; break; - case SE_Salvage: + case SpellEffect::Salvage: new_bonus->SalvageChance += effect_value; break; - case SE_ArcheryDamageModifier: + case SpellEffect::ArcheryDamageModifier: new_bonus->ArcheryDamageModifier += effect_value; break; - case SE_DoubleRangedAttack: + case SpellEffect::DoubleRangedAttack: new_bonus->DoubleRangedAttack += effect_value; break; - case SE_SecondaryDmgInc: + case SpellEffect::SecondaryDmgInc: new_bonus->SecondaryDmgInc = true; break; - case SE_StrikeThrough: - case SE_StrikeThrough2: + case SpellEffect::StrikeThrough: + case SpellEffect::StrikeThrough2: new_bonus->StrikeThrough += effect_value; break; - case SE_GiveDoubleAttack: + case SpellEffect::GiveDoubleAttack: new_bonus->GiveDoubleAttack += effect_value; break; - case SE_PetCriticalHit: + case SpellEffect::PetCriticalHit: new_bonus->PetCriticalHit += effect_value; break; - case SE_CombatStability: + case SpellEffect::CombatStability: new_bonus->CombatStability += effect_value; break; - case SE_AddSingingMod: + case SpellEffect::AddSingingMod: switch (limit_value) { case EQ::item::ItemTypeWindInstrument: new_bonus->windMod += effect_value; @@ -3264,76 +3264,76 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne } break; - case SE_SongModCap: + case SpellEffect::SongModCap: new_bonus->songModCap += effect_value; break; - case SE_PetAvoidance: + case SpellEffect::PetAvoidance: new_bonus->PetAvoidance += effect_value; break; - case SE_Ambidexterity: + case SpellEffect::Ambidexterity: new_bonus->Ambidexterity += effect_value; break; - case SE_PetMaxHP: + case SpellEffect::PetMaxHP: new_bonus->PetMaxHP += effect_value; break; - case SE_PetFlurry: + case SpellEffect::PetFlurry: new_bonus->PetFlurry += effect_value; break; - case SE_GivePetGroupTarget: + case SpellEffect::GivePetGroupTarget: new_bonus->GivePetGroupTarget = true; break; - case SE_RootBreakChance: + case SpellEffect::RootBreakChance: new_bonus->RootBreakChance += effect_value; break; - case SE_ChannelChanceItems: + case SpellEffect::ChannelChanceItems: new_bonus->ChannelChanceItems += effect_value; break; - case SE_ChannelChanceSpells: + case SpellEffect::ChannelChanceSpells: new_bonus->ChannelChanceSpells += effect_value; break; - case SE_UnfailingDivinity: + case SpellEffect::UnfailingDivinity: new_bonus->UnfailingDivinity += effect_value; break; - case SE_ItemHPRegenCapIncrease: + case SpellEffect::ItemHPRegenCapIncrease: new_bonus->ItemHPRegenCap += effect_value; break; - case SE_OffhandRiposteFail: + case SpellEffect::OffhandRiposteFail: new_bonus->OffhandRiposteFail += effect_value; break; - case SE_ItemAttackCapIncrease: + case SpellEffect::ItemAttackCapIncrease: new_bonus->ItemATKCap += effect_value; break; - case SE_TwoHandBluntBlock: + case SpellEffect::TwoHandBluntBlock: new_bonus->TwoHandBluntBlock += effect_value; break; - case SE_StunBashChance: + case SpellEffect::StunBashChance: new_bonus->StunBashChance += effect_value; break; - case SE_IncreaseChanceMemwipe: + case SpellEffect::IncreaseChanceMemwipe: new_bonus->IncreaseChanceMemwipe += effect_value; break; - case SE_CriticalMend: + case SpellEffect::CriticalMend: new_bonus->CriticalMend += effect_value; break; - case SE_SpellEffectResistChance: + case SpellEffect::SpellEffectResistChance: { for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) { @@ -3353,20 +3353,20 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_MasteryofPast: + case SpellEffect::MasteryofPast: { if(new_bonus->MasteryofPast < effect_value) new_bonus->MasteryofPast = effect_value; break; } - case SE_DoubleRiposte: + case SpellEffect::DoubleRiposte: { new_bonus->DoubleRiposte += effect_value; break; } - case SE_GiveDoubleRiposte: + case SpellEffect::GiveDoubleRiposte: { //Only allow for regular double riposte chance. if(new_bonus->GiveDoubleRiposte[limit_value] == 0){ @@ -3376,7 +3376,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_SlayUndead: { + case SpellEffect::SlayUndead: { if (new_bonus->SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] < effect_value) { new_bonus->SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] = limit_value; // Rate new_bonus->SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] = effect_value; // Damage Modifier @@ -3384,16 +3384,16 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_TriggerOnReqTarget: - case SE_TriggerOnReqCaster: + case SpellEffect::TriggerOnReqTarget: + case SpellEffect::TriggerOnReqCaster: new_bonus->TriggerOnCastRequirement = true; break; - case SE_DivineAura: + case SpellEffect::DivineAura: new_bonus->DivineAura = true; break; - case SE_ImprovedTaunt: + case SpellEffect::ImprovedTaunt: if (new_bonus->ImprovedTaunt[SBIndex::IMPROVED_TAUNT_MAX_LVL] < effect_value) { new_bonus->ImprovedTaunt[SBIndex::IMPROVED_TAUNT_MAX_LVL] = effect_value; new_bonus->ImprovedTaunt[SBIndex::IMPROVED_TAUNT_AGGRO_MOD] = limit_value; @@ -3402,15 +3402,15 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; - case SE_DistanceRemoval: + case SpellEffect::DistanceRemoval: new_bonus->DistanceRemoval = true; break; - case SE_FrenziedDevastation: + case SpellEffect::FrenziedDevastation: new_bonus->FrenziedDevastation += limit_value; break; - case SE_Root: + case SpellEffect::Root: if (new_bonus->Root[SBIndex::ROOT_EXISTS] && (new_bonus->Root[SBIndex::ROOT_BUFFSLOT] > buffslot)){ new_bonus->Root[SBIndex::ROOT_EXISTS] = 1; new_bonus->Root[SBIndex::ROOT_BUFFSLOT] = buffslot; @@ -3421,7 +3421,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne } break; - case SE_Rune: + case SpellEffect::Rune: if (new_bonus->MeleeRune[SBIndex::RUNE_AMOUNT] && (new_bonus->MeleeRune[SBIndex::RUNE_BUFFSLOT] > buffslot)){ @@ -3435,7 +3435,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; - case SE_AbsorbMagicAtt: + case SpellEffect::AbsorbMagicAtt: if (new_bonus->AbsorbMagicAtt[SBIndex::RUNE_AMOUNT] && (new_bonus->AbsorbMagicAtt[SBIndex::RUNE_BUFFSLOT] > buffslot)){ new_bonus->AbsorbMagicAtt[SBIndex::RUNE_AMOUNT] = effect_value; new_bonus->AbsorbMagicAtt[SBIndex::RUNE_BUFFSLOT] = buffslot; @@ -3446,15 +3446,15 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne } break; - case SE_NegateIfCombat: + case SpellEffect::NegateIfCombat: new_bonus->NegateIfCombat = true; break; - case SE_Screech: + case SpellEffect::Screech: new_bonus->Screech = effect_value; break; - case SE_AlterNPCLevel: + case SpellEffect::AlterNPCLevel: if (IsNPC()){ if (!new_bonus->AlterNPCLevel @@ -3474,36 +3474,36 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne } break; - case SE_AStacker: + case SpellEffect::AStacker: new_bonus->AStacker[SBIndex::BUFFSTACKER_EXISTS] = 1; new_bonus->AStacker[SBIndex::BUFFSTACKER_VALUE] = effect_value; break; - case SE_BStacker: + case SpellEffect::BStacker: new_bonus->BStacker[SBIndex::BUFFSTACKER_EXISTS] = 1; new_bonus->BStacker[SBIndex::BUFFSTACKER_VALUE] = effect_value; break; - case SE_CStacker: + case SpellEffect::CStacker: new_bonus->CStacker[SBIndex::BUFFSTACKER_EXISTS] = 1; new_bonus->CStacker[SBIndex::BUFFSTACKER_VALUE] = effect_value; break; - case SE_DStacker: + case SpellEffect::DStacker: new_bonus->DStacker[SBIndex::BUFFSTACKER_EXISTS] = 1; new_bonus->DStacker[SBIndex::BUFFSTACKER_VALUE] = effect_value; break; - case SE_Berserk: + case SpellEffect::Berserk: new_bonus->BerserkSPA = true; break; - case SE_Metabolism: + case SpellEffect::Metabolism: new_bonus->Metabolism += effect_value; break; - case SE_ImprovedReclaimEnergy: + case SpellEffect::ImprovedReclaimEnergy: { if((effect_value < 0) && (new_bonus->ImprovedReclaimEnergy > effect_value)) new_bonus->ImprovedReclaimEnergy = effect_value; @@ -3513,7 +3513,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_HeadShot: + case SpellEffect::HeadShot: { if(new_bonus->HeadShot[SBIndex::FINISHING_EFFECT_DMG] < limit_value){ new_bonus->HeadShot[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; @@ -3522,7 +3522,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_HeadShotLevel: { + case SpellEffect::HeadShotLevel: { if (new_bonus->HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] < effect_value) { new_bonus->HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; new_bonus->HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = limit_value; @@ -3530,7 +3530,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Assassinate: + case SpellEffect::Assassinate: { if(new_bonus->Assassinate[SBIndex::FINISHING_EFFECT_DMG] < limit_value){ new_bonus->Assassinate[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; @@ -3539,7 +3539,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_AssassinateLevel: + case SpellEffect::AssassinateLevel: { if(new_bonus->AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] < effect_value) { new_bonus->AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; @@ -3548,7 +3548,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_FinishingBlow: + case SpellEffect::FinishingBlow: { //base1 = chance, base2 = damage if (new_bonus->FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] < limit_value){ @@ -3558,7 +3558,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_FinishingBlowLvl: + case SpellEffect::FinishingBlowLvl: { if (new_bonus->FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] < effect_value){ new_bonus->FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; @@ -3567,15 +3567,15 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_PetMeleeMitigation: + case SpellEffect::PetMeleeMitigation: new_bonus->PetMeleeMitigation += effect_value; break; - case SE_Sanctuary: + case SpellEffect::Sanctuary: new_bonus->Sanctuary = true; break; - case SE_FactionModPct: + case SpellEffect::FactionModPct: { if((effect_value < 0) && (new_bonus->FactionModPct > effect_value)) new_bonus->FactionModPct = effect_value; @@ -3585,15 +3585,15 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Illusion: + case SpellEffect::Illusion: new_bonus->Illusion = spell_id; break; - case SE_IllusionPersistence: + case SpellEffect::IllusionPersistence: new_bonus->IllusionPersistence = effect_value; break; - case SE_LimitToSkill: { + case SpellEffect::LimitToSkill: { // Bad data or unsupported new skill if (effect_value > EQ::skills::HIGHEST_SKILL) { break; @@ -3605,7 +3605,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_SkillProcAttempt:{ + case SpellEffect::SkillProcAttempt:{ for(int e = 0; e < MAX_SKILL_PROCS; e++) { @@ -3621,7 +3621,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_SkillProcSuccess:{ + case SpellEffect::SkillProcSuccess:{ for(int e = 0; e < MAX_SKILL_PROCS; e++) { @@ -3636,7 +3636,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_SkillAttackProc: { + case SpellEffect::SkillAttackProc: { for (int i = 0; i < MAX_CAST_ON_SKILL_USE; i += 3) { if (!new_bonus->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID]) { // spell id new_bonus->SkillAttackProc[i + SBIndex::SKILLATK_PROC_SPELL_ID] = max_value; // spell to proc @@ -3652,33 +3652,33 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_PC_Pet_Rampage: { + case SpellEffect::PC_Pet_Rampage: { new_bonus->PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE] += effect_value; //Chance to rampage if (new_bonus->PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] < limit_value) new_bonus->PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = limit_value; //Damage modifer - take highest break; } - case SE_PC_Pet_AE_Rampage: { + case SpellEffect::PC_Pet_AE_Rampage: { new_bonus->PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_CHANCE] += effect_value; //Chance to rampage if (new_bonus->PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] < limit_value) new_bonus->PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = limit_value; //Damage modifer - take highest break; } - case SE_PC_Pet_Flurry_Chance: + case SpellEffect::PC_Pet_Flurry_Chance: new_bonus->PC_Pet_Flurry += effect_value; //Chance to Flurry break; - case SE_ShroudofStealth: + case SpellEffect::ShroudofStealth: new_bonus->ShroudofStealth = true; break; - case SE_ReduceFallDamage: + case SpellEffect::ReduceFallDamage: new_bonus->ReduceFallDamage += effect_value; break; - case SE_ReduceTradeskillFail:{ + case SpellEffect::ReduceTradeskillFail:{ if (limit_value > EQ::skills::HIGHEST_SKILL) break; @@ -3687,12 +3687,12 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_TradeSkillMastery: + case SpellEffect::TradeSkillMastery: if (new_bonus->TradeSkillMastery < effect_value) new_bonus->TradeSkillMastery = effect_value; break; - case SE_RaiseSkillCap: { + case SpellEffect::RaiseSkillCap: { if (limit_value > EQ::skills::HIGHEST_SKILL) break; @@ -3701,40 +3701,40 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_NoBreakAESneak: + case SpellEffect::NoBreakAESneak: if (new_bonus->NoBreakAESneak < effect_value) new_bonus->NoBreakAESneak = effect_value; break; - case SE_FeignedCastOnChance: + case SpellEffect::FeignedCastOnChance: if (new_bonus->FeignedCastOnChance < effect_value) new_bonus->FeignedCastOnChance = effect_value; break; - case SE_AdditionalAura: + case SpellEffect::AdditionalAura: if (new_bonus->aura_slots < effect_value) new_bonus->aura_slots = effect_value; break; - case SE_IncreaseTrapCount: + case SpellEffect::IncreaseTrapCount: if (new_bonus->trap_slots < effect_value) new_bonus->trap_slots = effect_value; break; - case SE_Attack_Accuracy_Max_Percent: + case SpellEffect::Attack_Accuracy_Max_Percent: new_bonus->Attack_Accuracy_Max_Percent += effect_value; break; - case SE_AC_Mitigation_Max_Percent: + case SpellEffect::AC_Mitigation_Max_Percent: new_bonus->AC_Mitigation_Max_Percent += effect_value; break; - case SE_AC_Avoidance_Max_Percent: + case SpellEffect::AC_Avoidance_Max_Percent: new_bonus->AC_Avoidance_Max_Percent += effect_value; break; - case SE_Damage_Taken_Position_Mod: + case SpellEffect::Damage_Taken_Position_Mod: { //Mitigate if damage taken from behind base2 = 0, from front base2 = 1 if (limit_value < 0 || limit_value >= 2) { @@ -3749,7 +3749,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Melee_Damage_Position_Mod: + case SpellEffect::Melee_Damage_Position_Mod: { //Increase damage by percent from behind base2 = 0, from front base2 = 1 if (limit_value < 0 || limit_value >= 2) { @@ -3764,7 +3764,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Damage_Taken_Position_Amt: + case SpellEffect::Damage_Taken_Position_Amt: { //Mitigate if damage taken from behind base2 = 0, from front base2 = 1 if (limit_value < 0 || limit_value >= 2) { @@ -3775,7 +3775,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Melee_Damage_Position_Amt: + case SpellEffect::Melee_Damage_Position_Amt: { //Mitigate if damage taken from behind base2 = 0, from front base2 = 1 if (limit_value < 0 || limit_value >= 2) { @@ -3786,23 +3786,23 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_DS_Mitigation_Amount: + case SpellEffect::DS_Mitigation_Amount: new_bonus->DS_Mitigation_Amount += effect_value; break; - case SE_DS_Mitigation_Percentage: + case SpellEffect::DS_Mitigation_Percentage: new_bonus->DS_Mitigation_Percentage += effect_value; break; - case SE_Pet_Crit_Melee_Damage_Pct_Owner: + case SpellEffect::Pet_Crit_Melee_Damage_Pct_Owner: new_bonus->Pet_Crit_Melee_Damage_Pct_Owner += effect_value; break; - case SE_Pet_Add_Atk: + case SpellEffect::Pet_Add_Atk: new_bonus->Pet_Add_Atk += effect_value; break; - case SE_ExtendedShielding: + case SpellEffect::ExtendedShielding: { if (AdditiveWornBonus) { new_bonus->ExtendedShielding += effect_value; @@ -3816,7 +3816,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_ShieldDuration: + case SpellEffect::ShieldDuration: { if (AdditiveWornBonus) { new_bonus->ShieldDuration += effect_value; @@ -3830,15 +3830,15 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Worn_Endurance_Regen_Cap: + case SpellEffect::Worn_Endurance_Regen_Cap: new_bonus->ItemEnduranceRegenCap += effect_value; break; - case SE_ItemManaRegenCapIncrease: + case SpellEffect::ItemManaRegenCapIncrease: new_bonus->ItemManaRegenCap += effect_value; break; - case SE_Weapon_Stance: { + case SpellEffect::Weapon_Stance: { if (IsValidSpell(effect_value)) { //base1 is the spell_id of buff if (limit_value <= WEAPON_STANCE_TYPE_MAX) { //0=2H, 1=Shield, 2=DW if (IsValidSpell(new_bonus->WeaponStance[limit_value])) { //Check if we already a spell_id saved for this effect @@ -3870,42 +3870,42 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; } - case SE_Invisibility: - case SE_Invisibility2: + case SpellEffect::Invisibility: + case SpellEffect::Invisibility2: effect_value = std::min({ effect_value, MAX_INVISIBILTY_LEVEL }); if (new_bonus->invisibility < effect_value) new_bonus->invisibility = effect_value; break; - case SE_InvisVsUndead: - case SE_InvisVsUndead2: + case SpellEffect::InvisVsUndead: + case SpellEffect::InvisVsUndead2: if (new_bonus->invisibility_verse_undead < effect_value) new_bonus->invisibility_verse_undead = effect_value; break; - case SE_InvisVsAnimals: - case SE_ImprovedInvisAnimals: + case SpellEffect::InvisVsAnimals: + case SpellEffect::ImprovedInvisAnimals: effect_value = std::min({ effect_value, MAX_INVISIBILTY_LEVEL }); if (new_bonus->invisibility_verse_animal < effect_value) new_bonus->invisibility_verse_animal = effect_value; break; - case SE_SeeInvis: + case SpellEffect::SeeInvis: effect_value = std::min({ effect_value, MAX_INVISIBILTY_LEVEL }); if (new_bonus->SeeInvis < effect_value) { new_bonus->SeeInvis = effect_value; } break; - case SE_ZoneSuspendMinion: + case SpellEffect::ZoneSuspendMinion: new_bonus->ZoneSuspendMinion = effect_value; break; - case SE_CompleteHeal: + case SpellEffect::CompleteHeal: new_bonus->CompleteHealBuffBlocker = true; break; - case SE_TrapCircumvention: + case SpellEffect::TrapCircumvention: new_bonus->TrapCircumvention += effect_value; break; } @@ -4128,93 +4128,93 @@ uint8 Mob::IsFocusEffect(uint16 spell_id,int effect_index, bool AA,uint32 aa_eff switch (effect) { - case SE_ImprovedDamage: + case SpellEffect::ImprovedDamage: return focusImprovedDamage; - case SE_ImprovedDamage2: + case SpellEffect::ImprovedDamage2: return focusImprovedDamage2; - case SE_ImprovedHeal: + case SpellEffect::ImprovedHeal: return focusImprovedHeal; - case SE_ReduceManaCost: + case SpellEffect::ReduceManaCost: return focusManaCost; - case SE_IncreaseSpellHaste: + case SpellEffect::IncreaseSpellHaste: return focusSpellHaste; - case SE_IncreaseSpellDuration: + case SpellEffect::IncreaseSpellDuration: return focusSpellDuration; - case SE_SpellDurationIncByTic: + case SpellEffect::SpellDurationIncByTic: return focusSpellDurByTic; - case SE_SwarmPetDuration: + case SpellEffect::SwarmPetDuration: return focusSwarmPetDuration; - case SE_IncreaseRange: + case SpellEffect::IncreaseRange: return focusRange; - case SE_ReduceReagentCost: + case SpellEffect::ReduceReagentCost: return focusReagentCost; - case SE_PetPowerIncrease: + case SpellEffect::PetPowerIncrease: return focusPetPower; - case SE_SpellResistReduction: + case SpellEffect::SpellResistReduction: return focusResistRate; - case SE_Fc_ResistIncoming: + case SpellEffect::Fc_ResistIncoming: return focusFcResistIncoming; - case SE_Fc_Amplify_Mod: + case SpellEffect::Fc_Amplify_Mod: return focusFcAmplifyMod; - case SE_Fc_Amplify_Amt: + case SpellEffect::Fc_Amplify_Amt: return focusFcAmplifyAmt; - case SE_SpellHateMod: + case SpellEffect::SpellHateMod: return focusSpellHateMod; - case SE_ReduceReuseTimer: + case SpellEffect::ReduceReuseTimer: return focusReduceRecastTime; - case SE_TriggerOnCast: + case SpellEffect::TriggerOnCast: return focusTriggerOnCast; - case SE_FcSpellVulnerability: + case SpellEffect::FcSpellVulnerability: return focusSpellVulnerability; - case SE_Fc_Spell_Damage_Pct_IncomingPC: + case SpellEffect::Fc_Spell_Damage_Pct_IncomingPC: return focusFcSpellDamagePctIncomingPC; - case SE_BlockNextSpellFocus: + case SpellEffect::BlockNextSpellFocus: return focusBlockNextSpell; - case SE_FcTwincast: + case SpellEffect::FcTwincast: return focusTwincast; - case SE_SympatheticProc: + case SpellEffect::SympatheticProc: return focusSympatheticProc; - case SE_FcDamageAmt: + case SpellEffect::FcDamageAmt: return focusFcDamageAmt; - case SE_FcDamageAmt2: + case SpellEffect::FcDamageAmt2: return focusFcDamageAmt2; - case SE_FcDamageAmtCrit: + case SpellEffect::FcDamageAmtCrit: return focusFcDamageAmtCrit; - case SE_FcDamagePctCrit: + case SpellEffect::FcDamagePctCrit: return focusFcDamagePctCrit; - case SE_FcDamageAmtIncoming: + case SpellEffect::FcDamageAmtIncoming: return focusFcDamageAmtIncoming; - case SE_Fc_Spell_Damage_Amt_IncomingPC: + case SpellEffect::Fc_Spell_Damage_Amt_IncomingPC: return focusFcSpellDamageAmtIncomingPC; - case SE_FcHealAmtIncoming: + case SpellEffect::FcHealAmtIncoming: return focusFcHealAmtIncoming; - case SE_FcHealPctIncoming: + case SpellEffect::FcHealPctIncoming: return focusFcHealPctIncoming; - case SE_FcBaseEffects: + case SpellEffect::FcBaseEffects: return focusFcBaseEffects; - case SE_FcIncreaseNumHits: + case SpellEffect::FcIncreaseNumHits: return focusIncreaseNumHits; - case SE_FcLimitUse: + case SpellEffect::FcLimitUse: return focusFcLimitUse; - case SE_FcMute: + case SpellEffect::FcMute: return focusFcMute; - case SE_FcTimerRefresh: + case SpellEffect::FcTimerRefresh: return focusFcTimerRefresh; - case SE_FcTimerLockout: + case SpellEffect::FcTimerLockout: return focusFcTimerLockout; - case SE_Fc_Cast_Spell_On_Land: + case SpellEffect::Fc_Cast_Spell_On_Land: return focusFcCastSpellOnLand; - case SE_FcStunTimeMod: + case SpellEffect::FcStunTimeMod: return focusFcStunTimeMod; - case SE_Fc_CastTimeMod2: + case SpellEffect::Fc_CastTimeMod2: return focusFcCastTimeMod2; - case SE_Fc_CastTimeAmt: + case SpellEffect::Fc_CastTimeAmt: return focusFcCastTimeAmt; - case SE_FcHealPctCritIncoming: + case SpellEffect::FcHealPctCritIncoming: return focusFcHealPctCritIncoming; - case SE_FcHealAmt: + case SpellEffect::FcHealAmt: return focusFcHealAmt; - case SE_FcHealAmtCrit: + case SpellEffect::FcHealAmtCrit: return focusFcHealAmtCrit; } @@ -4234,7 +4234,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) bool negate_aabonus = false; bool negate_itembonus = false; - if (spells[spell_id].effect_id[i] == SE_NegateSpellEffect) { + if (spells[spell_id].effect_id[i] == SpellEffect::NegateSpellEffect) { //Set negate types switch (spells[spell_id].base_value[i]) @@ -4286,43 +4286,43 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) //Negate bonuses switch (spells[spell_id].limit_value[i]) { - case SE_CurrentHP: + case SpellEffect::CurrentHP: if (negate_spellbonus) { spellbonuses.HPRegen = effect_value; } if (negate_aabonus) { aabonuses.HPRegen = effect_value; } if (negate_itembonus) { itembonuses.HPRegen = effect_value; } break; - case SE_CurrentEndurance: + case SpellEffect::CurrentEndurance: if (negate_spellbonus) { spellbonuses.EnduranceRegen = effect_value; } if (negate_aabonus) { aabonuses.EnduranceRegen = effect_value; } if (negate_itembonus) { itembonuses.EnduranceRegen = effect_value; } break; - case SE_ChangeFrenzyRad: + case SpellEffect::ChangeFrenzyRad: if (negate_spellbonus) { spellbonuses.AggroRange = static_cast(effect_value); } if (negate_aabonus) { aabonuses.AggroRange = static_cast(effect_value); } if (negate_itembonus) { itembonuses.AggroRange = static_cast(effect_value); } break; - case SE_Harmony: + case SpellEffect::Harmony: if (negate_spellbonus) { spellbonuses.AssistRange = static_cast(effect_value); } if (negate_aabonus) { aabonuses.AssistRange = static_cast(effect_value); } if (negate_itembonus) { itembonuses.AssistRange = static_cast(effect_value); } break; - case SE_AttackSpeed: + case SpellEffect::AttackSpeed: if (negate_spellbonus) { spellbonuses.haste = effect_value; } if (negate_aabonus) { aabonuses.haste = effect_value; } if (negate_itembonus) { itembonuses.haste = effect_value; } break; - case SE_AttackSpeed2: + case SpellEffect::AttackSpeed2: if (negate_spellbonus) { spellbonuses.hastetype2 = effect_value; } if (negate_aabonus) { aabonuses.hastetype2 = effect_value; } if (negate_itembonus) { itembonuses.hastetype2 = effect_value; } break; - case SE_AttackSpeed3: + case SpellEffect::AttackSpeed3: { if (negate_spellbonus) { spellbonuses.hastetype3 = effect_value; } if (negate_aabonus) { aabonuses.hastetype3 = effect_value; } @@ -4330,99 +4330,99 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_AttackSpeed4: + case SpellEffect::AttackSpeed4: if (negate_spellbonus) { spellbonuses.inhibitmelee = effect_value; } if (negate_aabonus) { aabonuses.inhibitmelee = effect_value; } if (negate_itembonus) { itembonuses.inhibitmelee = effect_value; } break; - case SE_IncreaseArchery: + case SpellEffect::IncreaseArchery: if (negate_spellbonus) { spellbonuses.increase_archery = effect_value; } if (negate_aabonus) { aabonuses.increase_archery = effect_value; } if (negate_itembonus) { itembonuses.increase_archery = effect_value; } break; - case SE_TotalHP: + case SpellEffect::TotalHP: if (negate_spellbonus) { spellbonuses.FlatMaxHPChange = effect_value; } if (negate_aabonus) { aabonuses.FlatMaxHPChange = effect_value; } if (negate_itembonus) { itembonuses.FlatMaxHPChange = effect_value; } break; - case SE_ManaRegen_v2: - case SE_CurrentMana: + case SpellEffect::ManaRegen_v2: + case SpellEffect::CurrentMana: if (negate_spellbonus) { spellbonuses.ManaRegen = effect_value; } if (negate_aabonus) { aabonuses.ManaRegen = effect_value; } if (negate_itembonus) { itembonuses.ManaRegen = effect_value; } break; - case SE_ManaPool: + case SpellEffect::ManaPool: if (negate_spellbonus) { spellbonuses.Mana = effect_value; } if (negate_itembonus) { itembonuses.Mana = effect_value; } if (negate_aabonus) { aabonuses.Mana = effect_value; } break; - case SE_Stamina: + case SpellEffect::Stamina: if (negate_spellbonus) { spellbonuses.EnduranceReduction = effect_value; } if (negate_itembonus) { itembonuses.EnduranceReduction = effect_value; } if (negate_aabonus) { aabonuses.EnduranceReduction = effect_value; } break; - case SE_ACv2: - case SE_ArmorClass: + case SpellEffect::ACv2: + case SpellEffect::ArmorClass: if (negate_spellbonus) { spellbonuses.AC = effect_value; } if (negate_aabonus) { aabonuses.AC = effect_value; } if (negate_itembonus) { itembonuses.AC = effect_value; } break; - case SE_ATK: + case SpellEffect::ATK: if (negate_spellbonus) { spellbonuses.ATK = effect_value; } if (negate_aabonus) { aabonuses.ATK = effect_value; } if (negate_itembonus) { itembonuses.ATK = effect_value; } break; - case SE_STR: + case SpellEffect::STR: if (negate_spellbonus) { spellbonuses.STR = effect_value; } if (negate_itembonus) { itembonuses.STR = effect_value; } if (negate_aabonus) { aabonuses.STR = effect_value; } break; - case SE_DEX: + case SpellEffect::DEX: if (negate_spellbonus) { spellbonuses.DEX = effect_value; } if (negate_aabonus) { aabonuses.DEX = effect_value; } if (negate_itembonus) { itembonuses.DEX = effect_value; } break; - case SE_AGI: + case SpellEffect::AGI: if (negate_itembonus) { itembonuses.AGI = effect_value; } if (negate_aabonus) { aabonuses.AGI = effect_value; } if (negate_spellbonus) { spellbonuses.AGI = effect_value; } break; - case SE_STA: + case SpellEffect::STA: if (negate_spellbonus) { spellbonuses.STA = effect_value; } if (negate_itembonus) { itembonuses.STA = effect_value; } if (negate_aabonus) { aabonuses.STA = effect_value; } break; - case SE_INT: + case SpellEffect::INT: if (negate_spellbonus) { spellbonuses.INT = effect_value; } if (negate_aabonus) { aabonuses.INT = effect_value; } if (negate_itembonus) { itembonuses.INT = effect_value; } break; - case SE_WIS: + case SpellEffect::WIS: if (negate_spellbonus) { spellbonuses.WIS = effect_value; } if (negate_aabonus) { aabonuses.WIS = effect_value; } if (negate_itembonus) { itembonuses.WIS = effect_value; } break; - case SE_CHA: + case SpellEffect::CHA: if (negate_itembonus) { itembonuses.CHA = effect_value; } if (negate_spellbonus) { spellbonuses.CHA = effect_value; } if (negate_aabonus) { aabonuses.CHA = effect_value; } break; - case SE_AllStats: + case SpellEffect::AllStats: { if (negate_spellbonus) { spellbonuses.STR = effect_value; @@ -4457,37 +4457,37 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_ResistFire: + case SpellEffect::ResistFire: if (negate_spellbonus) { spellbonuses.FR = effect_value; } if (negate_itembonus) { itembonuses.FR = effect_value; } if (negate_aabonus) { aabonuses.FR = effect_value; } break; - case SE_ResistCold: + case SpellEffect::ResistCold: if (negate_spellbonus) { spellbonuses.CR = effect_value; } if (negate_aabonus) { aabonuses.CR = effect_value; } if (negate_itembonus) { itembonuses.CR = effect_value; } break; - case SE_ResistPoison: + case SpellEffect::ResistPoison: if (negate_spellbonus) { spellbonuses.PR = effect_value; } if (negate_aabonus) { aabonuses.PR = effect_value; } if (negate_itembonus) { itembonuses.PR = effect_value; } break; - case SE_ResistDisease: + case SpellEffect::ResistDisease: if (negate_spellbonus) { spellbonuses.DR = effect_value; } if (negate_itembonus) { itembonuses.DR = effect_value; } if (negate_aabonus) { aabonuses.DR = effect_value; } break; - case SE_ResistMagic: + case SpellEffect::ResistMagic: if (negate_spellbonus) { spellbonuses.MR = effect_value; } if (negate_aabonus) { aabonuses.MR = effect_value; } if (negate_itembonus) { itembonuses.MR = effect_value; } break; - case SE_ResistAll: + case SpellEffect::ResistAll: { if (negate_spellbonus) { spellbonuses.MR = effect_value; @@ -4516,74 +4516,74 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_ResistCorruption: + case SpellEffect::ResistCorruption: if (negate_spellbonus) { spellbonuses.Corrup = effect_value; } if (negate_itembonus) { itembonuses.Corrup = effect_value; } if (negate_aabonus) { aabonuses.Corrup = effect_value; } break; - case SE_CastingLevel: // Brilliance of Ro + case SpellEffect::CastingLevel: // Brilliance of Ro if (negate_spellbonus) { spellbonuses.adjusted_casting_skill = effect_value; } if (negate_aabonus) { aabonuses.adjusted_casting_skill = effect_value; } if (negate_itembonus) { itembonuses.adjusted_casting_skill = effect_value; } break; - case SE_CastingLevel2: + case SpellEffect::CastingLevel2: if (negate_spellbonus) { spellbonuses.effective_casting_level = effect_value; } if (negate_aabonus) { aabonuses.effective_casting_level = effect_value; } if (negate_itembonus) { itembonuses.effective_casting_level = effect_value; } break; - case SE_MovementSpeed: + case SpellEffect::MovementSpeed: if (negate_spellbonus) { spellbonuses.movementspeed = effect_value; } if (negate_aabonus) { aabonuses.movementspeed = effect_value; } if (negate_itembonus) { itembonuses.movementspeed = effect_value; } break; - case SE_SpellDamageShield: + case SpellEffect::SpellDamageShield: if (negate_spellbonus) { spellbonuses.SpellDamageShield = effect_value; } if (negate_aabonus) { aabonuses.SpellDamageShield = effect_value; } if (negate_itembonus) { itembonuses.SpellDamageShield = effect_value; } break; - case SE_DamageShield: + case SpellEffect::DamageShield: if (negate_spellbonus) { spellbonuses.DamageShield = effect_value; } if (negate_aabonus) { aabonuses.DamageShield = effect_value; } if (negate_itembonus) { itembonuses.DamageShield = effect_value; } break; - case SE_ReverseDS: + case SpellEffect::ReverseDS: if (negate_spellbonus) { spellbonuses.ReverseDamageShield = effect_value; } if (negate_aabonus) { aabonuses.ReverseDamageShield = effect_value; } if (negate_itembonus) { itembonuses.ReverseDamageShield = effect_value; } break; - case SE_Reflect: + case SpellEffect::Reflect: if (negate_spellbonus) { spellbonuses.reflect[SBIndex::REFLECT_CHANCE] = effect_value; } if (negate_aabonus) { aabonuses.reflect[SBIndex::REFLECT_CHANCE] = effect_value; } if (negate_itembonus) { itembonuses.reflect[SBIndex::REFLECT_CHANCE] = effect_value; } break; - case SE_Amplification: + case SpellEffect::Amplification: if (negate_spellbonus) { spellbonuses.Amplification = effect_value; } if (negate_itembonus) { itembonuses.Amplification = effect_value; } if (negate_aabonus) { aabonuses.Amplification = effect_value; } break; - case SE_ChangeAggro: + case SpellEffect::ChangeAggro: if (negate_spellbonus) { spellbonuses.hatemod = effect_value; } if (negate_itembonus) { itembonuses.hatemod = effect_value; } if (negate_aabonus) { aabonuses.hatemod = effect_value; } break; - case SE_MeleeMitigation: + case SpellEffect::MeleeMitigation: if (negate_spellbonus) { spellbonuses.MeleeMitigationEffect = effect_value; } if (negate_itembonus) { itembonuses.MeleeMitigationEffect = effect_value; } if (negate_aabonus) { aabonuses.MeleeMitigationEffect = effect_value; } break; - case SE_CriticalHitChance: + case SpellEffect::CriticalHitChance: { for (int e = 0; e < EQ::skills::HIGHEST_SKILL + 1; e++) { @@ -4593,61 +4593,61 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) } } - case SE_CrippBlowChance: + case SpellEffect::CrippBlowChance: if (negate_spellbonus) { spellbonuses.CrippBlowChance = effect_value; } if (negate_aabonus) { aabonuses.CrippBlowChance = effect_value; } if (negate_itembonus) { itembonuses.CrippBlowChance = effect_value; } break; - case SE_AvoidMeleeChance: + case SpellEffect::AvoidMeleeChance: if (negate_spellbonus) { spellbonuses.AvoidMeleeChanceEffect = effect_value; } if (negate_aabonus) { aabonuses.AvoidMeleeChanceEffect = effect_value; } if (negate_itembonus) { itembonuses.AvoidMeleeChanceEffect = effect_value; } break; - case SE_RiposteChance: + case SpellEffect::RiposteChance: if (negate_spellbonus) { spellbonuses.RiposteChance = effect_value; } if (negate_aabonus) { aabonuses.RiposteChance = effect_value; } if (negate_itembonus) { itembonuses.RiposteChance = effect_value; } break; - case SE_DodgeChance: + case SpellEffect::DodgeChance: if (negate_spellbonus) { spellbonuses.DodgeChance = effect_value; } if (negate_aabonus) { aabonuses.DodgeChance = effect_value; } if (negate_itembonus) { itembonuses.DodgeChance = effect_value; } break; - case SE_ParryChance: + case SpellEffect::ParryChance: if (negate_spellbonus) { spellbonuses.ParryChance = effect_value; } if (negate_aabonus) { aabonuses.ParryChance = effect_value; } if (negate_itembonus) { itembonuses.ParryChance = effect_value; } break; - case SE_DualWieldChance: + case SpellEffect::DualWieldChance: if (negate_spellbonus) { spellbonuses.DualWieldChance = effect_value; } if (negate_aabonus) { aabonuses.DualWieldChance = effect_value; } if (negate_itembonus) { itembonuses.DualWieldChance = effect_value; } break; - case SE_DoubleAttackChance: + case SpellEffect::DoubleAttackChance: if (negate_spellbonus) { spellbonuses.DoubleAttackChance = effect_value; } if (negate_aabonus) { aabonuses.DoubleAttackChance = effect_value; } if (negate_itembonus) { itembonuses.DoubleAttackChance = effect_value; } break; - case SE_TripleAttackChance: + case SpellEffect::TripleAttackChance: if (negate_spellbonus) { spellbonuses.TripleAttackChance = effect_value; } if (negate_aabonus) { aabonuses.TripleAttackChance = effect_value; } if (negate_itembonus) { itembonuses.TripleAttackChance = effect_value; } break; - case SE_MeleeLifetap: + case SpellEffect::MeleeLifetap: if (negate_spellbonus) { spellbonuses.MeleeLifetap = effect_value; } if (negate_aabonus) { aabonuses.MeleeLifetap = effect_value; } if (negate_itembonus) { itembonuses.MeleeLifetap = effect_value; } break; - case SE_AllInstrumentMod: + case SpellEffect::AllInstrumentMod: { if (negate_spellbonus) { spellbonuses.singingMod = effect_value; @@ -4675,38 +4675,38 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_ResistSpellChance: + case SpellEffect::ResistSpellChance: if (negate_spellbonus) { spellbonuses.ResistSpellChance = effect_value; } if (negate_aabonus) { aabonuses.ResistSpellChance = effect_value; } if (negate_itembonus) { itembonuses.ResistSpellChance = effect_value; } break; - case SE_ResistFearChance: + case SpellEffect::ResistFearChance: if (negate_spellbonus) {spellbonuses.ResistFearChance = effect_value; } if (negate_aabonus) { aabonuses.ResistFearChance = effect_value; } if (negate_itembonus) { itembonuses.ResistFearChance = effect_value; } break; - case SE_Fearless: + case SpellEffect::Fearless: if (negate_spellbonus) { spellbonuses.Fearless = false; } if (negate_aabonus) { aabonuses.Fearless = false; } if (negate_itembonus) { itembonuses.Fearless = false; } break; - case SE_HundredHands: + case SpellEffect::HundredHands: if (negate_spellbonus) { spellbonuses.HundredHands = effect_value; } if (negate_aabonus) { aabonuses.HundredHands = effect_value; } if (negate_itembonus) { itembonuses.HundredHands = effect_value; } break; - case SE_MeleeSkillCheck: + case SpellEffect::MeleeSkillCheck: { if (negate_spellbonus) { spellbonuses.MeleeSkillCheck = effect_value; } if (negate_spellbonus) { spellbonuses.MeleeSkillCheckSkill = effect_value; } break; } - case SE_HitChance: + case SpellEffect::HitChance: { for (int e = 0; e < EQ::skills::HIGHEST_SKILL + 1; e++) { @@ -4717,7 +4717,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_DamageModifier: + case SpellEffect::DamageModifier: { for (int e = 0; e < EQ::skills::HIGHEST_SKILL + 1; e++) { @@ -4728,7 +4728,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_DamageModifier2: + case SpellEffect::DamageModifier2: { for (int e = 0; e < EQ::skills::HIGHEST_SKILL + 1; e++) { @@ -4739,7 +4739,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_Skill_Base_Damage_Mod: + case SpellEffect::Skill_Base_Damage_Mod: { for (int e = 0; e < EQ::skills::HIGHEST_SKILL + 1; e++) { @@ -4751,7 +4751,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) } - case SE_MinDamageModifier: + case SpellEffect::MinDamageModifier: { for (int e = 0; e < EQ::skills::HIGHEST_SKILL + 1; e++) { @@ -4762,55 +4762,55 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_StunResist: + case SpellEffect::StunResist: if (negate_spellbonus) { spellbonuses.StunResist = effect_value; } if (negate_aabonus) { aabonuses.StunResist = effect_value; } if (negate_itembonus) { itembonuses.StunResist = effect_value; } break; - case SE_ProcChance: + case SpellEffect::ProcChance: if (negate_spellbonus) { spellbonuses.ProcChanceSPA = effect_value; } if (negate_aabonus) { aabonuses.ProcChanceSPA = effect_value; } if (negate_itembonus) { itembonuses.ProcChanceSPA = effect_value; } break; - case SE_ExtraAttackChance: + case SpellEffect::ExtraAttackChance: if (negate_spellbonus) { spellbonuses.ExtraAttackChance[SBIndex::EXTRA_ATTACK_CHANCE] = effect_value; } if (negate_aabonus) { aabonuses.ExtraAttackChance[SBIndex::EXTRA_ATTACK_CHANCE] = effect_value; } if (negate_itembonus) { itembonuses.ExtraAttackChance[SBIndex::EXTRA_ATTACK_CHANCE] = effect_value; } break; - case SE_AddExtraAttackPct_1h_Primary: + case SpellEffect::AddExtraAttackPct_1h_Primary: if (negate_spellbonus) { spellbonuses.ExtraAttackChancePrimary[SBIndex::EXTRA_ATTACK_CHANCE] = effect_value; } if (negate_aabonus) { aabonuses.ExtraAttackChancePrimary[SBIndex::EXTRA_ATTACK_CHANCE] = effect_value; } if (negate_itembonus) { itembonuses.ExtraAttackChancePrimary[SBIndex::EXTRA_ATTACK_CHANCE] = effect_value; } break; - case SE_AddExtraAttackPct_1h_Secondary: + case SpellEffect::AddExtraAttackPct_1h_Secondary: if (negate_spellbonus) { spellbonuses.ExtraAttackChanceSecondary[SBIndex::EXTRA_ATTACK_CHANCE] = effect_value; } if (negate_aabonus) { aabonuses.ExtraAttackChanceSecondary[SBIndex::EXTRA_ATTACK_CHANCE] = effect_value; } if (negate_itembonus) { itembonuses.ExtraAttackChanceSecondary[SBIndex::EXTRA_ATTACK_CHANCE] = effect_value; } break; - case SE_Double_Melee_Round: + case SpellEffect::Double_Melee_Round: if (negate_spellbonus) { spellbonuses.DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] = effect_value; } if (negate_aabonus) { aabonuses.DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] = effect_value; } if (negate_itembonus) { itembonuses.DoubleMeleeRound[SBIndex::DOUBLE_MELEE_ROUND_CHANCE] = effect_value; } break; - case SE_PercentXPIncrease: + case SpellEffect::PercentXPIncrease: if (negate_spellbonus) { spellbonuses.XPRateMod = effect_value; } if (negate_aabonus) { aabonuses.XPRateMod = effect_value; } if (negate_itembonus) { itembonuses.XPRateMod = effect_value; } break; - case SE_Flurry: + case SpellEffect::Flurry: if (negate_spellbonus) { spellbonuses.FlurryChance = effect_value; } if (negate_aabonus) { aabonuses.FlurryChance = effect_value; } if (negate_itembonus) { itembonuses.FlurryChance = effect_value; } break; - case SE_Accuracy: + case SpellEffect::Accuracy: { if (negate_spellbonus) { spellbonuses.Accuracy[EQ::skills::HIGHEST_SKILL + 1] = effect_value; } if (negate_itembonus) { itembonuses.Accuracy[EQ::skills::HIGHEST_SKILL + 1] = effect_value; } @@ -4822,25 +4822,25 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_MaxHPChange: + case SpellEffect::MaxHPChange: if (negate_spellbonus) { spellbonuses.PercentMaxHPChange = effect_value; } if (negate_aabonus) { aabonuses.PercentMaxHPChange = effect_value; } if (negate_itembonus) { itembonuses.PercentMaxHPChange = effect_value; } break; - case SE_EndurancePool: + case SpellEffect::EndurancePool: if (negate_spellbonus) { spellbonuses.Endurance = effect_value; } if (negate_aabonus) { aabonuses.Endurance = effect_value; } if (negate_itembonus) { itembonuses.Endurance = effect_value; } break; - case SE_HealRate: + case SpellEffect::HealRate: if (negate_spellbonus) { spellbonuses.HealRate = effect_value; } if (negate_aabonus) { aabonuses.HealRate = effect_value; } if (negate_itembonus) { itembonuses.HealRate = effect_value; } break; - case SE_SkillDamageTaken: + case SpellEffect::SkillDamageTaken: { for (int e = 0; e < EQ::skills::HIGHEST_SKILL + 1; e++) { @@ -4852,13 +4852,13 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_SpellCritChance: + case SpellEffect::SpellCritChance: if (negate_spellbonus) { spellbonuses.CriticalSpellChance = effect_value; } if (negate_aabonus) { aabonuses.CriticalSpellChance = effect_value; } if (negate_itembonus) { itembonuses.CriticalSpellChance = effect_value; } break; - case SE_CriticalSpellChance: + case SpellEffect::CriticalSpellChance: if (negate_spellbonus) { spellbonuses.CriticalSpellChance = effect_value; spellbonuses.SpellCritDmgIncrease = effect_value; @@ -4876,43 +4876,43 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_SpellCritDmgIncrease: + case SpellEffect::SpellCritDmgIncrease: if (negate_spellbonus) { spellbonuses.SpellCritDmgIncrease = effect_value; } if (negate_aabonus) { aabonuses.SpellCritDmgIncrease = effect_value; } if (negate_itembonus) { itembonuses.SpellCritDmgIncrease = effect_value; } break; - case SE_DotCritDmgIncrease: + case SpellEffect::DotCritDmgIncrease: if (negate_spellbonus) { spellbonuses.DotCritDmgIncrease = effect_value; } if (negate_aabonus) { aabonuses.DotCritDmgIncrease = effect_value; } if (negate_itembonus) { itembonuses.DotCritDmgIncrease = effect_value; } break; - case SE_CriticalHealChance: + case SpellEffect::CriticalHealChance: if (negate_spellbonus) { spellbonuses.CriticalHealChance = effect_value; } if (negate_aabonus) { aabonuses.CriticalHealChance = effect_value; } if (negate_itembonus) { itembonuses.CriticalHealChance = effect_value; } break; - case SE_CriticalHealOverTime: + case SpellEffect::CriticalHealOverTime: if (negate_spellbonus) { spellbonuses.CriticalHealOverTime = effect_value; } if (negate_aabonus) { aabonuses.CriticalHealOverTime = effect_value; } if (negate_itembonus) { itembonuses.CriticalHealOverTime = effect_value; } break; - case SE_MitigateDamageShield: + case SpellEffect::MitigateDamageShield: if (negate_spellbonus) { spellbonuses.DSMitigationOffHand = effect_value; } if (negate_itembonus) { itembonuses.DSMitigationOffHand = effect_value; } if (negate_aabonus) { aabonuses.DSMitigationOffHand = effect_value; } break; - case SE_CriticalDoTChance: + case SpellEffect::CriticalDoTChance: if (negate_spellbonus) { spellbonuses.CriticalDoTChance = effect_value; } if (negate_aabonus) { aabonuses.CriticalDoTChance = effect_value; } if (negate_itembonus) { itembonuses.CriticalDoTChance = effect_value; } break; - case SE_ProcOnKillShot: + case SpellEffect::ProcOnKillShot: { for (int e = 0; e < MAX_SPELL_TRIGGER * 3; e += 3) { @@ -4939,7 +4939,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) } /* - case SE_SpellOnDeath: + case SpellEffect::SpellOnDeath: { for(int e = 0; e < MAX_SPELL_TRIGGER; e=2) { @@ -4950,7 +4950,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) } */ - case SE_CriticalDamageMob: + case SpellEffect::CriticalDamageMob: { for (int e = 0; e < EQ::skills::HIGHEST_SKILL + 1; e++) { @@ -4961,7 +4961,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_Critical_Melee_Damage_Mod_Max: + case SpellEffect::Critical_Melee_Damage_Mod_Max: { for (int e = 0; e < EQ::skills::HIGHEST_SKILL + 1; e++) { @@ -4972,7 +4972,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_SkillDamageAmount: + case SpellEffect::SkillDamageAmount: { for (int e = 0; e < EQ::skills::HIGHEST_SKILL + 1; e++) { @@ -4983,47 +4983,47 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_IncreaseBlockChance: + case SpellEffect::IncreaseBlockChance: if (negate_spellbonus) { spellbonuses.IncreaseBlockChance = effect_value; } if (negate_aabonus) { aabonuses.IncreaseBlockChance = effect_value; } if (negate_itembonus) { itembonuses.IncreaseBlockChance = effect_value; } break; - case SE_PersistantCasting: + case SpellEffect::PersistantCasting: if (negate_spellbonus) { spellbonuses.PersistantCasting = effect_value; } if (negate_itembonus) { itembonuses.PersistantCasting = effect_value; } if (negate_aabonus) { aabonuses.PersistantCasting = effect_value; } break; - case SE_ImmuneFleeing: + case SpellEffect::ImmuneFleeing: if (negate_spellbonus) { spellbonuses.ImmuneToFlee = false; } break; - case SE_DelayDeath: + case SpellEffect::DelayDeath: if (negate_spellbonus) { spellbonuses.DelayDeath = effect_value; } if (negate_aabonus) { aabonuses.DelayDeath = effect_value; } if (negate_itembonus) { itembonuses.DelayDeath = effect_value; } break; - case SE_SpellProcChance: + case SpellEffect::SpellProcChance: if (negate_spellbonus) { spellbonuses.SpellProcChance = effect_value; } if (negate_itembonus) { itembonuses.SpellProcChance = effect_value; } if (negate_aabonus) { aabonuses.SpellProcChance = effect_value; } break; - case SE_CharmBreakChance: + case SpellEffect::CharmBreakChance: if (negate_spellbonus) { spellbonuses.CharmBreakChance = effect_value; } if (negate_aabonus) { aabonuses.CharmBreakChance = effect_value; } if (negate_itembonus) { itembonuses.CharmBreakChance = effect_value; } break; - case SE_BardSongRange: + case SpellEffect::BardSongRange: if (negate_spellbonus) { spellbonuses.SongRange = effect_value; } if (negate_aabonus) { aabonuses.SongRange = effect_value; } if (negate_itembonus) { itembonuses.SongRange = effect_value; } break; - case SE_SkillDamageAmount2: + case SpellEffect::SkillDamageAmount2: { for (int e = 0; e < EQ::skills::HIGHEST_SKILL + 1; e++) { @@ -5034,7 +5034,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_NegateAttacks: + case SpellEffect::NegateAttacks: if (negate_spellbonus) { spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_EXISTS] = effect_value; spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_BUFFSLOT] = effect_value; @@ -5042,7 +5042,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_MitigateMeleeDamage: + case SpellEffect::MitigateMeleeDamage: if (negate_spellbonus) { spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_PERCENT] = effect_value; spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_BUFFSLOT] = -1; @@ -5050,7 +5050,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_MeleeThresholdGuard: + case SpellEffect::MeleeThresholdGuard: if (negate_spellbonus) { spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT] = effect_value; spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_BUFFSLOT] = -1; @@ -5059,7 +5059,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_SpellThresholdGuard: + case SpellEffect::SpellThresholdGuard: if (negate_spellbonus) { spellbonuses.SpellThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT] = effect_value; spellbonuses.SpellThresholdGuard[SBIndex::THRESHOLDGUARD_BUFFSLOT] = -1; @@ -5068,7 +5068,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_MitigateSpellDamage: + case SpellEffect::MitigateSpellDamage: if (negate_spellbonus) { spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_PERCENT] = effect_value; spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_BUFFSLOT] = -1; @@ -5076,7 +5076,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_MitigateDotDamage: + case SpellEffect::MitigateDotDamage: if (negate_spellbonus) { spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT] = effect_value; spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_BUFFSLOT] = -1; @@ -5084,11 +5084,11 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_ManaAbsorbPercentDamage: + case SpellEffect::ManaAbsorbPercentDamage: if (negate_spellbonus) { spellbonuses.ManaAbsorbPercentDamage = effect_value; } break; - case SE_Endurance_Absorb_Pct_Damage: + case SpellEffect::Endurance_Absorb_Pct_Damage: if (negate_spellbonus) { spellbonuses.EnduranceAbsorbPercentDamage[SBIndex::ENDURANCE_ABSORD_MITIGIATION] = effect_value; spellbonuses.EnduranceAbsorbPercentDamage[SBIndex::ENDURANCE_ABSORD_DRAIN_PER_HP] = effect_value; @@ -5096,223 +5096,223 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_ShieldBlock: + case SpellEffect::ShieldBlock: if (negate_spellbonus) { spellbonuses.ShieldBlock = effect_value; } if (negate_aabonus) { aabonuses.ShieldBlock = effect_value; } if (negate_itembonus) { itembonuses.ShieldBlock = effect_value; } - case SE_BlockBehind: + case SpellEffect::BlockBehind: if (negate_spellbonus) { spellbonuses.BlockBehind = effect_value; } if (negate_aabonus) { aabonuses.BlockBehind = effect_value; } if (negate_itembonus) { itembonuses.BlockBehind = effect_value; } break; - case SE_Blind: + case SpellEffect::Blind: if (negate_spellbonus) { spellbonuses.IsBlind = false; } break; - case SE_Fear: + case SpellEffect::Fear: if (negate_spellbonus) { spellbonuses.IsFeared = false; } break; - case SE_FrontalStunResist: + case SpellEffect::FrontalStunResist: if (negate_spellbonus) { spellbonuses.FrontalStunResist = effect_value; } if (negate_aabonus) { aabonuses.FrontalStunResist = effect_value; } if (negate_itembonus) { itembonuses.FrontalStunResist = effect_value; } break; - case SE_ImprovedBindWound: + case SpellEffect::ImprovedBindWound: if (negate_aabonus) { aabonuses.BindWound = effect_value; } if (negate_itembonus) { itembonuses.BindWound = effect_value; } if (negate_spellbonus) { spellbonuses.BindWound = effect_value; } break; - case SE_MaxBindWound: + case SpellEffect::MaxBindWound: if (negate_spellbonus) { spellbonuses.MaxBindWound = effect_value; } if (negate_aabonus) { aabonuses.MaxBindWound = effect_value; } if (negate_itembonus) { itembonuses.MaxBindWound = effect_value; } break; - case SE_BaseMovementSpeed: + case SpellEffect::BaseMovementSpeed: if (negate_spellbonus) { spellbonuses.BaseMovementSpeed = effect_value; } if (negate_aabonus) { aabonuses.BaseMovementSpeed = effect_value; } if (negate_itembonus) { itembonuses.BaseMovementSpeed = effect_value; } break; - case SE_IncreaseRunSpeedCap: + case SpellEffect::IncreaseRunSpeedCap: if (negate_itembonus) { itembonuses.IncreaseRunSpeedCap = effect_value; } if (negate_aabonus) { aabonuses.IncreaseRunSpeedCap = effect_value; } if (negate_spellbonus) { spellbonuses.IncreaseRunSpeedCap = effect_value; } break; - case SE_DoubleSpecialAttack: + case SpellEffect::DoubleSpecialAttack: if (negate_spellbonus) { spellbonuses.DoubleSpecialAttack = effect_value; } if (negate_aabonus) { aabonuses.DoubleSpecialAttack = effect_value; } if (negate_itembonus) { itembonuses.DoubleSpecialAttack = effect_value; } break; - case SE_TripleBackstab: + case SpellEffect::TripleBackstab: if (negate_spellbonus) { spellbonuses.TripleBackstab = effect_value; } if (negate_aabonus) { aabonuses.TripleBackstab = effect_value; } if (negate_itembonus) { itembonuses.TripleBackstab = effect_value; } break; - case SE_FrontalBackstabMinDmg: + case SpellEffect::FrontalBackstabMinDmg: if (negate_spellbonus) { spellbonuses.FrontalBackstabMinDmg = false; } break; - case SE_FrontalBackstabChance: + case SpellEffect::FrontalBackstabChance: if (negate_spellbonus) { spellbonuses.FrontalBackstabChance = effect_value; } if (negate_aabonus) { aabonuses.FrontalBackstabChance = effect_value; } if (negate_itembonus) { itembonuses.FrontalBackstabChance = effect_value; } break; - case SE_Double_Backstab_Front: + case SpellEffect::Double_Backstab_Front: if (negate_spellbonus) { spellbonuses.Double_Backstab_Front = effect_value; } if (negate_aabonus) { aabonuses.Double_Backstab_Front = effect_value; } if (negate_itembonus) { itembonuses.Double_Backstab_Front = effect_value; } break; - case SE_ConsumeProjectile: + case SpellEffect::ConsumeProjectile: if (negate_spellbonus) { spellbonuses.ConsumeProjectile = effect_value; } if (negate_aabonus) { aabonuses.ConsumeProjectile = effect_value; } if (negate_itembonus) { itembonuses.ConsumeProjectile = effect_value; } break; - case SE_ForageAdditionalItems: + case SpellEffect::ForageAdditionalItems: if (negate_spellbonus) { spellbonuses.ForageAdditionalItems = effect_value; } if (negate_aabonus) { aabonuses.ForageAdditionalItems = effect_value; } if (negate_itembonus) { itembonuses.ForageAdditionalItems = effect_value; } break; - case SE_Salvage: + case SpellEffect::Salvage: if (negate_spellbonus) { spellbonuses.SalvageChance = effect_value; } if (negate_aabonus) { aabonuses.SalvageChance = effect_value; } if (negate_itembonus) { itembonuses.SalvageChance = effect_value; } break; - case SE_ArcheryDamageModifier: + case SpellEffect::ArcheryDamageModifier: if (negate_spellbonus) { spellbonuses.ArcheryDamageModifier = effect_value; } if (negate_aabonus) { aabonuses.ArcheryDamageModifier = effect_value; } if (negate_itembonus) { itembonuses.ArcheryDamageModifier = effect_value; } break; - case SE_SecondaryDmgInc: + case SpellEffect::SecondaryDmgInc: if (negate_spellbonus) { spellbonuses.SecondaryDmgInc = false; } if (negate_aabonus) { aabonuses.SecondaryDmgInc = false; } if (negate_itembonus) { itembonuses.SecondaryDmgInc = false; } break; - case SE_StrikeThrough: - case SE_StrikeThrough2: + case SpellEffect::StrikeThrough: + case SpellEffect::StrikeThrough2: if (negate_spellbonus) { spellbonuses.StrikeThrough = effect_value; } if (negate_aabonus) { aabonuses.StrikeThrough = effect_value; } if (negate_itembonus) { itembonuses.StrikeThrough = effect_value; } break; - case SE_GiveDoubleAttack: + case SpellEffect::GiveDoubleAttack: if (negate_spellbonus) { spellbonuses.GiveDoubleAttack = effect_value; } if (negate_aabonus) { aabonuses.GiveDoubleAttack = effect_value; } if (negate_itembonus) { itembonuses.GiveDoubleAttack = effect_value; } break; - case SE_PetCriticalHit: + case SpellEffect::PetCriticalHit: if (negate_spellbonus) { spellbonuses.PetCriticalHit = effect_value; } if (negate_aabonus) { aabonuses.PetCriticalHit = effect_value; } if (negate_itembonus) { itembonuses.PetCriticalHit = effect_value; } break; - case SE_CombatStability: + case SpellEffect::CombatStability: if (negate_spellbonus) { spellbonuses.CombatStability = effect_value; } if (negate_aabonus) { aabonuses.CombatStability = effect_value; } if (negate_itembonus) { itembonuses.CombatStability = effect_value; } break; - case SE_PetAvoidance: + case SpellEffect::PetAvoidance: if (negate_spellbonus) { spellbonuses.PetAvoidance = effect_value; } if (negate_aabonus) { aabonuses.PetAvoidance = effect_value; } if (negate_itembonus) { itembonuses.PetAvoidance = effect_value; } break; - case SE_Ambidexterity: + case SpellEffect::Ambidexterity: if (negate_spellbonus) { spellbonuses.Ambidexterity = effect_value; } if (negate_aabonus) { aabonuses.Ambidexterity = effect_value; } if (negate_itembonus) { itembonuses.Ambidexterity = effect_value; } break; - case SE_PetMaxHP: + case SpellEffect::PetMaxHP: if (negate_spellbonus) { spellbonuses.PetMaxHP = effect_value; } if (negate_aabonus) { aabonuses.PetMaxHP = effect_value; } if (negate_itembonus) { itembonuses.PetMaxHP = effect_value; } break; - case SE_PetFlurry: + case SpellEffect::PetFlurry: if (negate_spellbonus) { spellbonuses.PetFlurry = effect_value; } if (negate_aabonus) { aabonuses.PetFlurry = effect_value; } if (negate_itembonus) { itembonuses.PetFlurry = effect_value; } break; - case SE_GivePetGroupTarget: + case SpellEffect::GivePetGroupTarget: if (negate_spellbonus) { spellbonuses.GivePetGroupTarget = false; } if (negate_aabonus) { aabonuses.GivePetGroupTarget = false; } if (negate_itembonus) { itembonuses.GivePetGroupTarget = false; } break; - case SE_PetMeleeMitigation: + case SpellEffect::PetMeleeMitigation: if (negate_spellbonus) { spellbonuses.PetMeleeMitigation = effect_value; } if (negate_itembonus) { itembonuses.PetMeleeMitigation = effect_value; } if (negate_aabonus) { aabonuses.PetMeleeMitigation = effect_value; } break; - case SE_RootBreakChance: + case SpellEffect::RootBreakChance: if (negate_spellbonus) { spellbonuses.RootBreakChance = effect_value; } if (negate_aabonus) { aabonuses.RootBreakChance = effect_value; } if (negate_itembonus) { itembonuses.RootBreakChance = effect_value; } break; - case SE_ChannelChanceItems: + case SpellEffect::ChannelChanceItems: if (negate_spellbonus) { spellbonuses.ChannelChanceItems = effect_value; } if (negate_aabonus) { aabonuses.ChannelChanceItems = effect_value; } if (negate_itembonus) { itembonuses.ChannelChanceItems = effect_value; } break; - case SE_ChannelChanceSpells: + case SpellEffect::ChannelChanceSpells: if (negate_spellbonus) { spellbonuses.ChannelChanceSpells = effect_value; } if (negate_aabonus) { aabonuses.ChannelChanceSpells = effect_value; } if (negate_itembonus) { itembonuses.ChannelChanceSpells = effect_value; } break; - case SE_UnfailingDivinity: + case SpellEffect::UnfailingDivinity: if (negate_spellbonus) { spellbonuses.UnfailingDivinity = effect_value; } if (negate_aabonus) { aabonuses.UnfailingDivinity = effect_value; } if (negate_itembonus) { itembonuses.UnfailingDivinity = effect_value; } break; - case SE_ItemHPRegenCapIncrease: + case SpellEffect::ItemHPRegenCapIncrease: if (negate_spellbonus) { spellbonuses.ItemHPRegenCap = effect_value; } if (negate_aabonus) { aabonuses.ItemHPRegenCap = effect_value; } if (negate_itembonus) { itembonuses.ItemHPRegenCap = effect_value; } break; - case SE_Worn_Endurance_Regen_Cap: + case SpellEffect::Worn_Endurance_Regen_Cap: if (negate_spellbonus) { spellbonuses.ItemEnduranceRegenCap = effect_value; } if (negate_aabonus) { aabonuses.ItemEnduranceRegenCap = effect_value; } if (negate_itembonus) { itembonuses.ItemEnduranceRegenCap = effect_value; } break; - case SE_OffhandRiposteFail: + case SpellEffect::OffhandRiposteFail: if (negate_spellbonus) { spellbonuses.OffhandRiposteFail = effect_value; } if (negate_aabonus) { aabonuses.OffhandRiposteFail = effect_value; } if (negate_itembonus) { itembonuses.OffhandRiposteFail = effect_value; } break; - case SE_ItemAttackCapIncrease: + case SpellEffect::ItemAttackCapIncrease: if (negate_aabonus) { aabonuses.ItemATKCap = effect_value; } if (negate_itembonus) { itembonuses.ItemATKCap = effect_value; } if (negate_spellbonus) { spellbonuses.ItemATKCap = effect_value; } break; - case SE_SpellEffectResistChance: + case SpellEffect::SpellEffectResistChance: { for (int e = 0; e < MAX_RESISTABLE_EFFECTS * 2; e += 2) { @@ -5332,25 +5332,25 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_MasteryofPast: + case SpellEffect::MasteryofPast: if (negate_spellbonus) { spellbonuses.MasteryofPast = effect_value; } if (negate_aabonus) { aabonuses.MasteryofPast = effect_value; } if (negate_itembonus) { itembonuses.MasteryofPast = effect_value; } break; - case SE_DoubleRiposte: + case SpellEffect::DoubleRiposte: if (negate_spellbonus) { spellbonuses.DoubleRiposte = effect_value; } if (negate_itembonus) { itembonuses.DoubleRiposte = effect_value; } if (negate_aabonus) { aabonuses.DoubleRiposte = effect_value; } break; - case SE_GiveDoubleRiposte: + case SpellEffect::GiveDoubleRiposte: if (negate_spellbonus) { spellbonuses.GiveDoubleRiposte[SBIndex::DOUBLE_RIPOSTE_CHANCE] = effect_value; } if (negate_itembonus) { itembonuses.GiveDoubleRiposte[SBIndex::DOUBLE_RIPOSTE_CHANCE] = effect_value; } if (negate_aabonus) { aabonuses.GiveDoubleRiposte[SBIndex::DOUBLE_RIPOSTE_CHANCE] = effect_value; } break; - case SE_SlayUndead: + case SpellEffect::SlayUndead: if (negate_spellbonus) { spellbonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] = effect_value; spellbonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] = effect_value; @@ -5368,53 +5368,53 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_DoubleRangedAttack: + case SpellEffect::DoubleRangedAttack: if (negate_spellbonus) { spellbonuses.DoubleRangedAttack = effect_value; } if (negate_aabonus) { aabonuses.DoubleRangedAttack = effect_value; } if (negate_itembonus) { itembonuses.DoubleRangedAttack = effect_value; } break; - case SE_ShieldEquipDmgMod: + case SpellEffect::ShieldEquipDmgMod: if (negate_spellbonus) { spellbonuses.ShieldEquipDmgMod = effect_value; } if (negate_aabonus) { aabonuses.ShieldEquipDmgMod = effect_value; } if (negate_itembonus) { itembonuses.ShieldEquipDmgMod = effect_value; } break; - case SE_TriggerMeleeThreshold: + case SpellEffect::TriggerMeleeThreshold: if (negate_spellbonus) { spellbonuses.TriggerMeleeThreshold = false; } break; - case SE_TriggerSpellThreshold: + case SpellEffect::TriggerSpellThreshold: if (negate_spellbonus) { spellbonuses.TriggerSpellThreshold = false; } break; - case SE_DivineAura: + case SpellEffect::DivineAura: if (negate_spellbonus) { spellbonuses.DivineAura = false; } break; - case SE_StunBashChance: + case SpellEffect::StunBashChance: if (negate_spellbonus) { spellbonuses.StunBashChance = effect_value; } if (negate_itembonus) { itembonuses.StunBashChance = effect_value; } if (negate_aabonus) { aabonuses.StunBashChance = effect_value; } break; - case SE_IncreaseChanceMemwipe: + case SpellEffect::IncreaseChanceMemwipe: if (negate_spellbonus) { spellbonuses.IncreaseChanceMemwipe = effect_value; } if (negate_itembonus) { itembonuses.IncreaseChanceMemwipe = effect_value; } if (negate_aabonus) { aabonuses.IncreaseChanceMemwipe = effect_value; } break; - case SE_CriticalMend: + case SpellEffect::CriticalMend: if (negate_spellbonus) { spellbonuses.CriticalMend = effect_value; } if (negate_itembonus) { itembonuses.CriticalMend = effect_value; } if (negate_aabonus) { aabonuses.CriticalMend = effect_value; } break; - case SE_DistanceRemoval: + case SpellEffect::DistanceRemoval: if (negate_spellbonus) { spellbonuses.DistanceRemoval = false; } break; - case SE_ImprovedTaunt: + case SpellEffect::ImprovedTaunt: if (negate_spellbonus) { spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_MAX_LVL] = effect_value; spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_AGGRO_MOD] = effect_value; @@ -5423,13 +5423,13 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_FrenziedDevastation: + case SpellEffect::FrenziedDevastation: if (negate_spellbonus) { spellbonuses.FrenziedDevastation = effect_value; } if (negate_aabonus) { aabonuses.FrenziedDevastation = effect_value; } if (negate_itembonus) { itembonuses.FrenziedDevastation = effect_value; } break; - case SE_Root: + case SpellEffect::Root: if (negate_spellbonus) { spellbonuses.Root[SBIndex::ROOT_EXISTS] = effect_value; spellbonuses.Root[SBIndex::ROOT_BUFFSLOT] = -1; @@ -5437,7 +5437,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_Rune: + case SpellEffect::Rune: if (negate_spellbonus) { spellbonuses.MeleeRune[SBIndex::RUNE_AMOUNT] = effect_value; spellbonuses.MeleeRune[SBIndex::RUNE_BUFFSLOT] = -1; @@ -5445,7 +5445,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_AbsorbMagicAtt: + case SpellEffect::AbsorbMagicAtt: if (negate_spellbonus) { spellbonuses.AbsorbMagicAtt[SBIndex::RUNE_AMOUNT] = effect_value; spellbonuses.AbsorbMagicAtt[SBIndex::RUNE_BUFFSLOT] = -1; @@ -5453,31 +5453,31 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_Berserk: + case SpellEffect::Berserk: if (negate_spellbonus) { spellbonuses.BerserkSPA = false; } if (negate_aabonus) { aabonuses.BerserkSPA = false; } if (negate_itembonus) { itembonuses.BerserkSPA = false; } break; - case SE_Vampirism: + case SpellEffect::Vampirism: if (negate_spellbonus) { spellbonuses.Vampirism = effect_value; } if (negate_aabonus) { aabonuses.Vampirism = effect_value; } if (negate_itembonus) { itembonuses.Vampirism = effect_value; } break; - case SE_Metabolism: + case SpellEffect::Metabolism: if (negate_spellbonus) { spellbonuses.Metabolism = effect_value; } if (negate_aabonus) { aabonuses.Metabolism = effect_value; } if (negate_itembonus) { itembonuses.Metabolism = effect_value; } break; - case SE_ImprovedReclaimEnergy: + case SpellEffect::ImprovedReclaimEnergy: if (negate_spellbonus) { spellbonuses.ImprovedReclaimEnergy = effect_value; } if (negate_aabonus) { aabonuses.ImprovedReclaimEnergy = effect_value; } if (negate_itembonus) { itembonuses.ImprovedReclaimEnergy = effect_value; } break; - case SE_HeadShot: + case SpellEffect::HeadShot: if (negate_spellbonus) { spellbonuses.HeadShot[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; spellbonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] = effect_value; @@ -5495,7 +5495,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_HeadShotLevel: + case SpellEffect::HeadShotLevel: if (negate_spellbonus) { spellbonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; spellbonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value; @@ -5513,7 +5513,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_Assassinate: + case SpellEffect::Assassinate: if (negate_spellbonus) { spellbonuses.Assassinate[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; spellbonuses.Assassinate[SBIndex::FINISHING_EFFECT_DMG] = effect_value; @@ -5531,7 +5531,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_AssassinateLevel: + case SpellEffect::AssassinateLevel: if (negate_spellbonus) { spellbonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; spellbonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS] = effect_value; @@ -5549,7 +5549,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_FinishingBlow: + case SpellEffect::FinishingBlow: if (negate_spellbonus) { spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] = effect_value; spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] = effect_value; @@ -5567,7 +5567,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_FinishingBlowLvl: + case SpellEffect::FinishingBlowLvl: if (negate_spellbonus) { spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX] = effect_value; spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_BLOW_LEVEL_HP_RATIO] = effect_value; @@ -5585,42 +5585,42 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_Sanctuary: + case SpellEffect::Sanctuary: if (negate_spellbonus) { spellbonuses.Sanctuary = false; } break; - case SE_FactionModPct: + case SpellEffect::FactionModPct: if (negate_spellbonus) { spellbonuses.FactionModPct = effect_value; } if (negate_itembonus) { itembonuses.FactionModPct = effect_value; } if (negate_aabonus) { aabonuses.FactionModPct = effect_value; } break; - case SE_IllusionPersistence: + case SpellEffect::IllusionPersistence: if (negate_spellbonus) { spellbonuses.IllusionPersistence = effect_value; } if (negate_itembonus) { itembonuses.IllusionPersistence = effect_value; } if (negate_aabonus) { aabonuses.IllusionPersistence = effect_value; } break; - case SE_Attack_Accuracy_Max_Percent: + case SpellEffect::Attack_Accuracy_Max_Percent: if (negate_spellbonus) { spellbonuses.Attack_Accuracy_Max_Percent = effect_value; } if (negate_itembonus) { itembonuses.Attack_Accuracy_Max_Percent = effect_value; } if (negate_aabonus) { aabonuses.Attack_Accuracy_Max_Percent = effect_value; } break; - case SE_AC_Mitigation_Max_Percent: + case SpellEffect::AC_Mitigation_Max_Percent: if (negate_spellbonus) { spellbonuses.AC_Mitigation_Max_Percent = effect_value; } if (negate_itembonus) { itembonuses.AC_Mitigation_Max_Percent = effect_value; } if (negate_aabonus) { aabonuses.AC_Mitigation_Max_Percent = effect_value; } break; - case SE_AC_Avoidance_Max_Percent: + case SpellEffect::AC_Avoidance_Max_Percent: if (negate_spellbonus) { spellbonuses.AC_Avoidance_Max_Percent = effect_value; } if (negate_itembonus) { itembonuses.AC_Avoidance_Max_Percent = effect_value; } if (negate_aabonus) { aabonuses.AC_Avoidance_Max_Percent = effect_value; } break; - case SE_Melee_Damage_Position_Mod: + case SpellEffect::Melee_Damage_Position_Mod: if (negate_spellbonus) { spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_BACK] = effect_value; spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; @@ -5638,7 +5638,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_Damage_Taken_Position_Mod: + case SpellEffect::Damage_Taken_Position_Mod: if (negate_spellbonus) { spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_BACK] = effect_value; spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITION_FRONT] = effect_value; @@ -5656,7 +5656,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_Melee_Damage_Position_Amt: + case SpellEffect::Melee_Damage_Position_Amt: if (negate_spellbonus) { spellbonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_BACK] = effect_value; spellbonuses.Melee_Damage_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; @@ -5674,7 +5674,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_Damage_Taken_Position_Amt: + case SpellEffect::Damage_Taken_Position_Amt: if (negate_spellbonus) { spellbonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_BACK] = effect_value; spellbonuses.Damage_Taken_Position_Amt[SBIndex::POSITION_FRONT] = effect_value; @@ -5692,31 +5692,31 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_DS_Mitigation_Amount: + case SpellEffect::DS_Mitigation_Amount: if (negate_spellbonus) { spellbonuses.DS_Mitigation_Amount = effect_value; } if (negate_itembonus) { itembonuses.DS_Mitigation_Amount = effect_value; } if (negate_aabonus) { aabonuses.DS_Mitigation_Amount = effect_value; } break; - case SE_DS_Mitigation_Percentage: + case SpellEffect::DS_Mitigation_Percentage: if (negate_spellbonus) { spellbonuses.DS_Mitigation_Percentage = effect_value; } if (negate_itembonus) { itembonuses.DS_Mitigation_Percentage = effect_value; } if (negate_aabonus) { aabonuses.DS_Mitigation_Percentage = effect_value; } break; - case SE_Pet_Crit_Melee_Damage_Pct_Owner: + case SpellEffect::Pet_Crit_Melee_Damage_Pct_Owner: if (negate_spellbonus) { spellbonuses.Pet_Crit_Melee_Damage_Pct_Owner = effect_value; } if (negate_itembonus) { itembonuses.Pet_Crit_Melee_Damage_Pct_Owner = effect_value; } if (negate_aabonus) { aabonuses.Pet_Crit_Melee_Damage_Pct_Owner = effect_value; } break; - case SE_Pet_Add_Atk: + case SpellEffect::Pet_Add_Atk: if (negate_spellbonus) { spellbonuses.Pet_Add_Atk = effect_value; } if (negate_itembonus) { itembonuses.Pet_Add_Atk = effect_value; } if (negate_aabonus) { aabonuses.Pet_Add_Atk = effect_value; } break; - case SE_PC_Pet_Rampage: + case SpellEffect::PC_Pet_Rampage: if (negate_spellbonus) { spellbonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value; spellbonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value; @@ -5734,7 +5734,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_PC_Pet_AE_Rampage: + case SpellEffect::PC_Pet_AE_Rampage: if (negate_spellbonus) { spellbonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_CHANCE] = effect_value; spellbonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] = effect_value; @@ -5753,7 +5753,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; - case SE_SkillProcSuccess: { + case SpellEffect::SkillProcSuccess: { for (int e = 0; e < MAX_SKILL_PROCS; e++) { if (negate_spellbonus) { spellbonuses.SkillProcSuccess[e] = effect_value; } @@ -5763,7 +5763,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_SkillProcAttempt: { + case SpellEffect::SkillProcAttempt: { for (int e = 0; e < MAX_SKILL_PROCS; e++) { if (negate_spellbonus) { spellbonuses.SkillProc[e] = effect_value; } @@ -5773,7 +5773,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) break; } - case SE_Shield_Target: { + case SpellEffect::Shield_Target: { if (negate_spellbonus) { spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_MITIGATION_PERCENT] = effect_value; spellbonuses.ShieldTargetSpa[SBIndex::SHIELD_TARGET_BUFFSLOT] = effect_value; diff --git a/zone/bot.cpp b/zone/bot.cpp index bd008955df..1aeb0c09ac 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -296,8 +296,8 @@ Bot::Bot( for (int x1 = 0; x1 < EFFECT_COUNT; x1++) { switch (spell.effect_id[x1]) { - case SE_IllusionCopy: - case SE_Illusion: { + case SpellEffect::IllusionCopy: + case SpellEffect::Illusion: { if (GetIllusionBlock()) { break; } @@ -375,63 +375,63 @@ Bot::Bot( } break; } - case SE_Silence: + case SpellEffect::Silence: { Silence(true); break; } - case SE_Amnesia: + case SpellEffect::Amnesia: { Amnesia(true); break; } - case SE_DivineAura: + case SpellEffect::DivineAura: { invulnerable = true; break; } - case SE_Invisibility2: - case SE_Invisibility: + case SpellEffect::Invisibility2: + case SpellEffect::Invisibility: { invisible = true; SendAppearancePacket(AppearanceType::Invisibility, 1); break; } - case SE_Levitate: + case SpellEffect::Levitate: { if (!zone->CanLevitate()) { SendAppearancePacket(AppearanceType::FlyMode, 0); - BuffFadeByEffect(SE_Levitate); + BuffFadeByEffect(SpellEffect::Levitate); } else { SendAppearancePacket(AppearanceType::FlyMode, 2); } break; } - case SE_InvisVsUndead2: - case SE_InvisVsUndead: + case SpellEffect::InvisVsUndead2: + case SpellEffect::InvisVsUndead: { invisible_undead = true; break; } - case SE_InvisVsAnimals: + case SpellEffect::InvisVsAnimals: { invisible_animals = true; break; } - case SE_AddMeleeProc: - case SE_WeaponProc: + case SpellEffect::AddMeleeProc: + case SpellEffect::WeaponProc: { AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel); break; } - case SE_DefensiveProc: + case SpellEffect::DefensiveProc: { AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid); break; } - case SE_RangedProc: + case SpellEffect::RangedProc: { AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid); break; @@ -1527,7 +1527,7 @@ bool Bot::LoadPet() auto my_buffs = GetBuffs(); if (buffs_max && my_buffs) { for (int index = 0; index < buffs_max; ++index) { - if (IsEffectInSpell(my_buffs[index].spellid, SE_Familiar)) { + if (IsEffectInSpell(my_buffs[index].spellid, SpellEffect::Familiar)) { MakePet(my_buffs[index].spellid, spells[my_buffs[index].spellid].teleport_zone); return true; } @@ -3578,7 +3578,7 @@ void Bot::Depop() { if (bot_pet) { if (bot_pet->Charmed()) { - bot_pet->BuffFadeByEffect(SE_Charm); + bot_pet->BuffFadeByEffect(SpellEffect::Charm); } else { bot_pet->Depop(); @@ -5974,7 +5974,7 @@ bool Bot::SpellOnTarget( if (spelltar->IsPet()) { for (int i = 0; i < EFFECT_COUNT; ++i) { - if (spells[spell_id].effect_id[i] == SE_Illusion) { + if (spells[spell_id].effect_id[i] == SpellEffect::Illusion) { return false; } } @@ -6214,7 +6214,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spe if (!noGroupSpell) { for (Mob* m : GetBuffTargets(spellTarget)) { - if (IsEffectInSpell(thespell, SE_AbsorbMagicAtt) || IsEffectInSpell(thespell, SE_Rune)) { + if (IsEffectInSpell(thespell, SpellEffect::AbsorbMagicAtt) || IsEffectInSpell(thespell, SpellEffect::Rune)) { for (int i = 0; i < m->GetMaxTotalSlots(); i++) { uint32 buff_count = m->GetMaxTotalSlots(); @@ -7831,7 +7831,7 @@ bool Bot::GetNeedsCured(Mob *tar) { bool need_cured = false; if (tar) { - if (tar->FindType(SE_PoisonCounter) || tar->FindType(SE_DiseaseCounter) || tar->FindType(SE_CurseCounter) || tar->FindType(SE_CorruptionCounter)) { + if (tar->FindType(SpellEffect::PoisonCounter) || tar->FindType(SpellEffect::DiseaseCounter) || tar->FindType(SpellEffect::CurseCounter) || tar->FindType(SpellEffect::CorruptionCounter)) { uint32 buff_count = tar->GetMaxTotalSlots(); for (unsigned int j = 0; j < buff_count; j++) { @@ -8616,7 +8616,7 @@ void Bot::Escape() } void Bot::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls, bool calculate_speed) { - BuffFadeByEffect(SE_Levitate); + BuffFadeByEffect(SpellEffect::Levitate); if (CheckLosFN(target_x, target_y, target_z, 6.0f) || ignore_los) { auto p = new EQApplicationPacket(OP_Fling, sizeof(fling_struct)); auto* f = (fling_struct*) p->pBuffer; @@ -9553,9 +9553,9 @@ bool Bot::CastChecks(uint16 spell_id, Mob* tar, uint16 spell_type, bool precheck if (spells[spell_id].target_type == ST_Self && tar != this) { if ( - !IsEffectInSpell(spell_id, SE_SummonCorpse) || + !IsEffectInSpell(spell_id, SpellEffect::SummonCorpse) || ( - IsEffectInSpell(spell_id, SE_SummonCorpse) && + IsEffectInSpell(spell_id, SpellEffect::SummonCorpse) && !RuleB(Bots, AllowCommandedSummonCorpse) ) ) { @@ -9667,7 +9667,7 @@ bool Bot::CastChecks(uint16 spell_id, Mob* tar, uint16 spell_type, bool precheck if ( !zone->CanLevitate() && - IsEffectInSpell(spell_id, SE_Levitate) + IsEffectInSpell(spell_id, SpellEffect::Levitate) ) { LogBotSpellChecksDetail("{} says, 'Cancelling cast of {} due to !CanLevitate.'", GetCleanName(), GetSpellName(spell_id)); return false; @@ -9907,8 +9907,8 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) { spell_type != BotSpellTypes::Succor ) && ( - IsEffectInSpell(spell_id, SE_Teleport) || - IsEffectInSpell(spell_id, SE_Succor) + IsEffectInSpell(spell_id, SpellEffect::Teleport) || + IsEffectInSpell(spell_id, SpellEffect::Succor) ) ) { LogBotSpellChecksDetail("{} says, 'Cancelling cast of {} on {} due to Teleport.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); @@ -9918,7 +9918,7 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) { if ( tar->IsPet() && !RuleB(Bots, CanCastIllusionsOnPets) && - IsEffectInSpell(spell_id, SE_Illusion) + IsEffectInSpell(spell_id, SpellEffect::Illusion) ) { LogBotSpellChecksDetail("{} says, 'Cancelling cast of {} on {} due to PetSE_Illusion.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); return false; @@ -9962,13 +9962,13 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) { tar->IsBot() && (tar->GetLevel() >= tar->CastToBot()->GetStopMeleeLevel()) && ( - IsEffectInSpell(spell_id, SE_AttackSpeed) || - IsEffectInSpell(spell_id, SE_ReverseDS) + IsEffectInSpell(spell_id, SpellEffect::AttackSpeed) || + IsEffectInSpell(spell_id, SpellEffect::ReverseDS) ) || ( SpellEffectsCount(spell_id) == 1 && ( - IsEffectInSpell(spell_id, SE_ATK) || IsEffectInSpell(spell_id, SE_STR) + IsEffectInSpell(spell_id, SpellEffect::ATK) || IsEffectInSpell(spell_id, SpellEffect::STR) ) ) ) { @@ -9978,11 +9978,11 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) { break; case Archetype::Melee: if ( - IsEffectInSpell(spell_id, SE_IncreaseSpellHaste) || - IsEffectInSpell(spell_id, SE_ManaPool) || - IsEffectInSpell(spell_id, SE_CastingLevel) || - IsEffectInSpell(spell_id, SE_ManaRegen_v2) || - IsEffectInSpell(spell_id, SE_CurrentMana) + IsEffectInSpell(spell_id, SpellEffect::IncreaseSpellHaste) || + IsEffectInSpell(spell_id, SpellEffect::ManaPool) || + IsEffectInSpell(spell_id, SpellEffect::CastingLevel) || + IsEffectInSpell(spell_id, SpellEffect::ManaRegen_v2) || + IsEffectInSpell(spell_id, SpellEffect::CurrentMana) ) { LogBotSpellChecksDetail("{} says, 'Cancelling cast of {} on {} due to Archetype::Melee.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); return false; @@ -9997,8 +9997,8 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) { // Differences for each type if (spell_type != BotSpellTypes::InCombatBuff) { if ( - IsEffectInSpell(spell_id, SE_AbsorbMagicAtt) || - IsEffectInSpell(spell_id, SE_Rune) + IsEffectInSpell(spell_id, SpellEffect::AbsorbMagicAtt) || + IsEffectInSpell(spell_id, SpellEffect::Rune) ) { for (int i = 0; i < tar->GetMaxTotalSlots(); i++) { uint32 buff_count = tar->GetMaxTotalSlots(); @@ -10026,14 +10026,14 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) { tar->IsBot() && (tar->GetLevel() >= tar->CastToBot()->GetStopMeleeLevel()) && ( - IsEffectInSpell(spell_id, SE_AttackSpeed) || - IsEffectInSpell(spell_id, SE_ReverseDS) + IsEffectInSpell(spell_id, SpellEffect::AttackSpeed) || + IsEffectInSpell(spell_id, SpellEffect::ReverseDS) ) || ( SpellEffectsCount(spell_id) == 1 && ( - IsEffectInSpell(spell_id, SE_ATK) || - IsEffectInSpell(spell_id, SE_STR) + IsEffectInSpell(spell_id, SpellEffect::ATK) || + IsEffectInSpell(spell_id, SpellEffect::STR) ) ) ) { @@ -10043,11 +10043,11 @@ bool Bot::CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar) { break; case Archetype::Melee: if ( - IsEffectInSpell(spell_id, SE_IncreaseSpellHaste) || - IsEffectInSpell(spell_id, SE_ManaPool) || - IsEffectInSpell(spell_id, SE_CastingLevel) || - IsEffectInSpell(spell_id, SE_ManaRegen_v2) || - IsEffectInSpell(spell_id, SE_CurrentMana) + IsEffectInSpell(spell_id, SpellEffect::IncreaseSpellHaste) || + IsEffectInSpell(spell_id, SpellEffect::ManaPool) || + IsEffectInSpell(spell_id, SpellEffect::CastingLevel) || + IsEffectInSpell(spell_id, SpellEffect::ManaRegen_v2) || + IsEffectInSpell(spell_id, SpellEffect::CurrentMana) ) { LogBotSpellChecksDetail("{} says, 'Cancelling cast of {} on {} due to Archetype::Melee.'", GetCleanName(), GetSpellName(spell_id), tar->GetCleanName()); return false; @@ -10329,7 +10329,7 @@ bool Bot::IsValidMezTarget(Mob* owner, Mob* npc, uint16 spell_id) { auto npc_buffs = npc->GetBuffs(); for (int i = 0; i < buff_count; i++) { - if (IsDetrimentalSpell(npc_buffs[i].spellid) && IsEffectInSpell(npc_buffs[i].spellid, SE_CurrentHP)) { + if (IsDetrimentalSpell(npc_buffs[i].spellid) && IsEffectInSpell(npc_buffs[i].spellid, SpellEffect::CurrentHP)) { return false; } } @@ -11684,7 +11684,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) { return false; case BotSpellTypes::Root: case BotSpellTypes::AERoot: - if (IsDetrimentalSpell(spell_id) && IsEffectInSpell(spell_id, SE_Root)) { + if (IsDetrimentalSpell(spell_id) && IsEffectInSpell(spell_id, SpellEffect::Root)) { return true; } @@ -11718,7 +11718,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) { return false; case BotSpellTypes::Pet: - if (IsSummonPetSpell(spell_id) || IsEffectInSpell(spell_id, SE_TemporaryPets)) { + if (IsSummonPetSpell(spell_id) || IsEffectInSpell(spell_id, SpellEffect::TemporaryPets)) { return true; } @@ -11732,7 +11732,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) { return false; case BotSpellTypes::Snare: case BotSpellTypes::AESnare: - if (IsDetrimentalSpell(spell_id) && IsEffectInSpell(spell_id, SE_MovementSpeed)) { + if (IsDetrimentalSpell(spell_id) && IsEffectInSpell(spell_id, SpellEffect::MovementSpeed)) { return true; } @@ -11806,7 +11806,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) { return false; case BotSpellTypes::Resurrect: - if (IsEffectInSpell(spell_id, SE_Revive)) { + if (IsEffectInSpell(spell_id, SpellEffect::Revive)) { return true; } @@ -11911,14 +11911,14 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) { return false; case BotSpellTypes::ResistBuffs: case BotSpellTypes::PetResistBuffs: - if (IsResistanceBuffSpell(spell_id) && !IsEffectInSpell(spell_id, SE_DamageShield)) { + if (IsResistanceBuffSpell(spell_id) && !IsEffectInSpell(spell_id, SpellEffect::DamageShield)) { return true; } return false; case BotSpellTypes::DamageShields: case BotSpellTypes::PetDamageShields: - if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_DamageShield)) { + if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SpellEffect::DamageShield)) { return true; } @@ -11926,7 +11926,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) { case BotSpellTypes::Teleport: if ( IsBeneficialSpell(spell_id) && - (IsEffectInSpell(spell_id, SE_Teleport) || IsEffectInSpell(spell_id, SE_Translocate)) + (IsEffectInSpell(spell_id, SpellEffect::Teleport) || IsEffectInSpell(spell_id, SpellEffect::Translocate)) ) { return true; } @@ -11942,40 +11942,40 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) { case BotSpellTypes::Succor: if ( IsBeneficialSpell(spell_id) && - IsEffectInSpell(spell_id, SE_Succor) + IsEffectInSpell(spell_id, SpellEffect::Succor) ) { return true; } return false; case BotSpellTypes::BindAffinity: - if (IsEffectInSpell(spell_id, SE_BindAffinity)) { + if (IsEffectInSpell(spell_id, SpellEffect::BindAffinity)) { return true; } return false; case BotSpellTypes::Identify: - if (IsEffectInSpell(spell_id, SE_Identify)) { + if (IsEffectInSpell(spell_id, SpellEffect::Identify)) { return true; } return false; case BotSpellTypes::Levitate: - if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_Levitate)) { + if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SpellEffect::Levitate)) { return true; } return false; case BotSpellTypes::Rune: if (IsBeneficialSpell(spell_id) && - (IsEffectInSpell(spell_id, SE_AbsorbMagicAtt) || IsEffectInSpell(spell_id, SE_Rune)) + (IsEffectInSpell(spell_id, SpellEffect::AbsorbMagicAtt) || IsEffectInSpell(spell_id, SpellEffect::Rune)) ) { return true; } return false; case BotSpellTypes::WaterBreathing: - if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_WaterBreathing)) { + if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SpellEffect::WaterBreathing)) { return true; } @@ -11983,7 +11983,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) { case BotSpellTypes::Size: if ( IsBeneficialSpell(spell_id) && - (IsEffectInSpell(spell_id, SE_ModelSize) || IsEffectInSpell(spell_id, SE_ChangeHeight)) + (IsEffectInSpell(spell_id, SpellEffect::ModelSize) || IsEffectInSpell(spell_id, SpellEffect::ChangeHeight)) ) { return true; } @@ -11991,14 +11991,14 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) { return false; case BotSpellTypes::Invisibility: if (IsBeneficialSpell(spell_id) && - (IsEffectInSpell(spell_id, SE_SeeInvis) ||IsInvisibleSpell(spell_id)) + (IsEffectInSpell(spell_id, SpellEffect::SeeInvis) ||IsInvisibleSpell(spell_id)) ) { return true; } return false; case BotSpellTypes::MovementSpeed: - if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SE_MovementSpeed)) { + if (IsBeneficialSpell(spell_id) && IsEffectInSpell(spell_id, SpellEffect::MovementSpeed)) { return true; } @@ -12007,10 +12007,10 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) { if ( IsBeneficialSpell(spell_id) && ( - IsEffectInSpell(spell_id, SE_GateToHomeCity) || + IsEffectInSpell(spell_id, SpellEffect::GateToHomeCity) || ( teleport_zone.compare("") && - (IsEffectInSpell(spell_id, SE_Teleport) || IsEffectInSpell(spell_id, SE_Translocate)) + (IsEffectInSpell(spell_id, SpellEffect::Teleport) || IsEffectInSpell(spell_id, SpellEffect::Translocate)) ) ) ) { @@ -12019,7 +12019,7 @@ bool Bot::IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id) { return false; case BotSpellTypes::SummonCorpse: - if (IsEffectInSpell(spell_id, SE_SummonCorpse)) { + if (IsEffectInSpell(spell_id, SpellEffect::SummonCorpse)) { return true; } @@ -12510,15 +12510,15 @@ bool Bot::IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spe break; case CommandedSubTypes::SeeInvis: - if (IsEffectInSpell(spell_id, SE_SeeInvis)) { + if (IsEffectInSpell(spell_id, SpellEffect::SeeInvis)) { return true; } break; case CommandedSubTypes::Invis: if ( - IsEffectInSpell(spell_id, SE_Invisibility) || - IsEffectInSpell(spell_id, SE_Invisibility2) + IsEffectInSpell(spell_id, SpellEffect::Invisibility) || + IsEffectInSpell(spell_id, SpellEffect::Invisibility2) ) { return true; } @@ -12526,8 +12526,8 @@ bool Bot::IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spe break; case CommandedSubTypes::InvisUndead: if ( - IsEffectInSpell(spell_id, SE_InvisVsUndead) || - IsEffectInSpell(spell_id, SE_InvisVsUndead2) + IsEffectInSpell(spell_id, SpellEffect::InvisVsUndead) || + IsEffectInSpell(spell_id, SpellEffect::InvisVsUndead2) ) { return true; } @@ -12535,8 +12535,8 @@ bool Bot::IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spe break; case CommandedSubTypes::InvisAnimals: if ( - IsEffectInSpell(spell_id, SE_InvisVsAnimals) || - IsEffectInSpell(spell_id, SE_ImprovedInvisAnimals) + IsEffectInSpell(spell_id, SpellEffect::InvisVsAnimals) || + IsEffectInSpell(spell_id, SpellEffect::ImprovedInvisAnimals) ) { return true; } @@ -12545,13 +12545,13 @@ bool Bot::IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spe case CommandedSubTypes::Shrink: if ( ( - IsEffectInSpell(spell_id, SE_ModelSize) && - CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SE_ModelSize), GetLevel()) < 100 + IsEffectInSpell(spell_id, SpellEffect::ModelSize) && + CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SpellEffect::ModelSize), GetLevel()) < 100 ) || ( - IsEffectInSpell(spell_id, SE_ChangeHeight) && - CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SE_ChangeHeight), GetLevel()) < 100 + IsEffectInSpell(spell_id, SpellEffect::ChangeHeight) && + CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SpellEffect::ChangeHeight), GetLevel()) < 100 ) ) { return true; @@ -12561,13 +12561,13 @@ bool Bot::IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spe case CommandedSubTypes::Grow: if ( ( - IsEffectInSpell(spell_id, SE_ModelSize) && - CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SE_ModelSize), GetLevel()) > 100 + IsEffectInSpell(spell_id, SpellEffect::ModelSize) && + CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SpellEffect::ModelSize), GetLevel()) > 100 ) || ( - IsEffectInSpell(spell_id, SE_ChangeHeight) && - CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SE_ChangeHeight), GetLevel()) > 100 + IsEffectInSpell(spell_id, SpellEffect::ChangeHeight) && + CalcSpellEffectValue(spell_id, GetSpellEffectIndex(spell_id, SpellEffect::ChangeHeight), GetLevel()) > 100 ) ) { return true; @@ -12577,7 +12577,7 @@ bool Bot::IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spe case CommandedSubTypes::Selo: if ( IsBeneficialSpell(spell_id) && - IsEffectInSpell(spell_id, SE_MovementSpeed) && + IsEffectInSpell(spell_id, SpellEffect::MovementSpeed) && IsBardSong(spell_id) ) { return true; @@ -13347,7 +13347,7 @@ bool Bot::IsImmuneToBotSpell(uint16 spell_id, Mob* caster) { if (!GetSpecialAbility(SpecialAbility::MesmerizeImmunity) && IsMesmerizeSpell(spell_id)) { // check max level for spell - effect_index = GetSpellEffectIndex(spell_id, SE_Mez); + effect_index = GetSpellEffectIndex(spell_id, SpellEffect::Mez); assert(effect_index >= 0); // NPCs get to ignore the max level if ( @@ -13359,13 +13359,13 @@ bool Bot::IsImmuneToBotSpell(uint16 spell_id, Mob* caster) { } // slow and haste spells - if (GetSpecialAbility(SpecialAbility::SlowImmunity) && IsEffectInSpell(spell_id, SE_AttackSpeed)) { + if (GetSpecialAbility(SpecialAbility::SlowImmunity) && IsEffectInSpell(spell_id, SpellEffect::AttackSpeed)) { return true; } // client vs client fear - if (!GetSpecialAbility(SpecialAbility::FearImmunity) && IsEffectInSpell(spell_id, SE_Fear)) { - effect_index = GetSpellEffectIndex(spell_id, SE_Fear); + if (!GetSpecialAbility(SpecialAbility::FearImmunity) && IsEffectInSpell(spell_id, SpellEffect::Fear)) { + effect_index = GetSpellEffectIndex(spell_id, SpellEffect::Fear); if (IsClient() && caster->IsClient() && (caster->CastToClient()->GetGM() == false)) { LogSpells("Clients cannot fear eachother!"); @@ -13389,7 +13389,7 @@ bool Bot::IsImmuneToBotSpell(uint16 spell_id, Mob* caster) { //let npcs cast whatever charm on anyone if (!caster->IsNPC()) { // check level limit of charm spell - effect_index = GetSpellEffectIndex(spell_id, SE_Charm); + effect_index = GetSpellEffectIndex(spell_id, SpellEffect::Charm); assert(effect_index >= 0); if (GetLevel() > spells[spell_id].max_value[effect_index] && spells[spell_id].max_value[effect_index] != 0) { return true; @@ -13400,8 +13400,8 @@ bool Bot::IsImmuneToBotSpell(uint16 spell_id, Mob* caster) { if ( GetSpecialAbility(SpecialAbility::SnareImmunity) && ( - IsEffectInSpell(spell_id, SE_Root) || - IsEffectInSpell(spell_id, SE_MovementSpeed) + IsEffectInSpell(spell_id, SpellEffect::Root) || + IsEffectInSpell(spell_id, SpellEffect::MovementSpeed) ) ) { return true; diff --git a/zone/bot_commands/pet.cpp b/zone/bot_commands/pet.cpp index 7163f0f5c3..d47726e5c0 100644 --- a/zone/bot_commands/pet.cpp +++ b/zone/bot_commands/pet.cpp @@ -245,7 +245,7 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep) if (pet_type == 6 && RuleI(Bots, RequiredMagicianEpicPetItemID) > 0) { bool has_item = bot_iter->HasBotItem(RuleI(Bots, RequiredMagicianEpicPetItemID)) != INVALID_INDEX; - + if (!has_item) { c->Message( Chat::Say, @@ -257,7 +257,7 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep) ); continue; - } + } } if (current_check) { @@ -313,7 +313,7 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep) continue; } - if (!IsEffectInSpell(s.SpellId, SE_SummonPet)) { + if (!IsEffectInSpell(s.SpellId, SpellEffect::SummonPet)) { continue; } @@ -401,7 +401,7 @@ void bot_command_pet_set_type(Client *c, const Seperator *sep) return; } - + if (success_count == 1 && first_found) { c->Message( Chat::Green, diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index d9e19a1eb0..b6ad79214b 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -40,7 +40,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 chance, uint16 spell_type, uint16 sub_targ ) { return false; } - + if ( !IsCommandedSpell() && zone->random.Int(0, 100) > chance @@ -240,7 +240,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 chance, uint16 spell_type, uint16 sub_targ tar->GetCleanName() ).c_str() ); - + InterruptSpell(); } @@ -297,7 +297,7 @@ bool Bot::BotCastMez(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spel if (AIDoSpellCast(s.SpellIndex, tar, s.ManaCost)) { if (BotSpellTypeUsesTargetSettings(spell_type)) { SetCastedSpellType(UINT16_MAX); - + if (!IsCommandedSpell()) { SetBotSpellRecastTimer(spell_type, tar, true); } @@ -384,7 +384,7 @@ bool Bot::BotCastPet(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spel int familiar_buff_slot = -1; if (buffs_max && my_buffs) { for (int index = 0; index < buffs_max; ++index) { - if (IsEffectInSpell(my_buffs[index].spellid, SE_Familiar)) { + if (IsEffectInSpell(my_buffs[index].spellid, SpellEffect::Familiar)) { MakePet(my_buffs[index].spellid, spells[my_buffs[index].spellid].teleport_zone); familiar_buff_slot = index; break; @@ -445,11 +445,11 @@ bool Bot::BotCastNuke(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spe } if ( - !tar->GetSpecialAbility(SpecialAbility::StunImmunity) && + !tar->GetSpecialAbility(SpecialAbility::StunImmunity) && ( - IsCommandedSpell() || + IsCommandedSpell() || (!tar->IsStunned() && (zone->random.Int(1, 100) <= stun_chance)) - ) + ) ) { bot_spell = GetBestBotSpellForStunByTargetType(this, ST_TargetOptional, spell_type, IsAEBotSpellType(spell_type), tar); } @@ -1173,7 +1173,7 @@ BotSpell Bot::GetBestBotSpellForVeryFastHeal(Bot* caster, Mob* tar, uint16 spell result.ManaCost = 0; if (caster) { - std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CurrentHP); + std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::CurrentHP); for (auto bot_spell_list_itr : bot_spell_list) { if ( @@ -1198,7 +1198,7 @@ BotSpell Bot::GetBestBotSpellForFastHeal(Bot* caster, Mob* tar, uint16 spell_typ result.ManaCost = 0; if (caster) { - std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CurrentHP); + std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::CurrentHP); for (auto bot_spell_list_itr : bot_spell_list) { if (IsFastHealSpell(bot_spell_list_itr.SpellId) && caster->CastChecks(bot_spell_list_itr.SpellId, tar, spell_type)) { @@ -1222,7 +1222,7 @@ BotSpell Bot::GetBestBotSpellForHealOverTime(Bot* caster, Mob* tar, uint16 spell result.ManaCost = 0; if (caster) { - std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_HealOverTime); + std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::HealOverTime); for (auto bot_spell_list_itr : bot_spell_list) { if (IsHealOverTimeSpell(bot_spell_list_itr.SpellId) && caster->CastChecks(bot_spell_list_itr.SpellId, tar, spell_type)) { @@ -1278,7 +1278,7 @@ BotSpell Bot::GetBestBotSpellForRegularSingleTargetHeal(Bot* caster, Mob* tar, u result.ManaCost = 0; if (caster) { - std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CurrentHP); + std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::CurrentHP); for (std::list::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) { if (IsRegularSingleTargetHealSpell(bot_spell_list_itr->SpellId) && caster->CastChecks(bot_spell_list_itr->SpellId, tar, spell_type)) { @@ -1302,7 +1302,7 @@ BotSpell Bot::GetFirstBotSpellForSingleTargetHeal(Bot* caster, Mob* tar, uint16 result.ManaCost = 0; if (caster) { - std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CurrentHP); + std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::CurrentHP); for (std::list::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) { if (IsRegularSingleTargetHealSpell(bot_spell_list_itr->SpellId) && caster->CastChecks(bot_spell_list_itr->SpellId, tar, spell_type)) { @@ -1329,7 +1329,7 @@ BotSpell Bot::GetBestBotSpellForGroupHeal(Bot* caster, Mob* tar, uint16 spell_ty return result; } - std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CurrentHP); + std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::CurrentHP); int target_count = 0; int required_count = caster->GetSpellTypeAEOrGroupTargetCount(spell_type); @@ -1367,7 +1367,7 @@ BotSpell Bot::GetBestBotSpellForGroupHealOverTime(Bot* caster, Mob* tar, uint16 return result; } - std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_HealOverTime); + std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::HealOverTime); int target_count = 0; int required_count = caster->GetSpellTypeAEOrGroupTargetCount(spell_type); @@ -1405,7 +1405,7 @@ BotSpell Bot::GetBestBotSpellForGroupCompleteHeal(Bot* caster, Mob* tar, uint16 return result; } - std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_CompleteHeal); + std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::CompleteHeal); int target_count = 0; int required_count = caster->GetSpellTypeAEOrGroupTargetCount(spell_type); @@ -1440,7 +1440,7 @@ BotSpell Bot::GetBestBotSpellForMez(Bot* caster, uint16 spell_type) { result.ManaCost = 0; if (caster) { - std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_Mez); + std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::Mez); for (std::list::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) { if ( @@ -1548,7 +1548,7 @@ BotSpell Bot::GetBestBotMagicianPetSpell(Bot* caster, uint16 spell_type) { result.ManaCost = 0; if (caster) { - std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_SummonPet); + std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::SummonPet); std::string pet_type = GetBotMagicianPetType(caster); for(std::list::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) { @@ -1638,7 +1638,7 @@ std::string Bot::GetBotMagicianPetType(Bot* caster) { continue; } - if (!IsEffectInSpell(s.SpellId, SE_SummonPet)) { + if (!IsEffectInSpell(s.SpellId, SpellEffect::SummonPet)) { continue; } @@ -1683,7 +1683,7 @@ std::string Bot::GetBotMagicianPetType(Bot* caster) { if (bot_level >= water_min_level) { result = std::string("SumWater"); } - + found = true; break; case SumFire: @@ -1730,7 +1730,7 @@ BotSpell Bot::GetBestBotSpellForNukeByTargetType(Bot* caster, SpellTargetType ta } if (caster) { - std::list bot_spell_list = GetBotSpellsForSpellEffectAndTargetType(caster, spell_type, SE_CurrentHP, target_type); + std::list bot_spell_list = GetBotSpellsForSpellEffectAndTargetType(caster, spell_type, SpellEffect::CurrentHP, target_type); for(std::list::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) { if (IsPureNukeSpell(bot_spell_list_itr->SpellId) || IsDamageSpell(bot_spell_list_itr->SpellId)) { @@ -1777,7 +1777,7 @@ BotSpell Bot::GetBestBotSpellForStunByTargetType(Bot* caster, SpellTargetType ta if (caster) { - std::list bot_spell_list = GetBotSpellsForSpellEffectAndTargetType(caster, spell_type, SE_Stun, target_type); + std::list bot_spell_list = GetBotSpellsForSpellEffectAndTargetType(caster, spell_type, SpellEffect::Stun, target_type); for(std::list::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) { @@ -1835,7 +1835,7 @@ BotSpell Bot::GetBestBotWizardNukeSpellByTargetResists(Bot* caster, Mob* target, } - std::list bot_spell_list = GetBotSpellsForSpellEffectAndTargetType(caster, spell_type, SE_CurrentHP, ST_Target); + std::list bot_spell_list = GetBotSpellsForSpellEffectAndTargetType(caster, spell_type, SpellEffect::CurrentHP, ST_Target); BotSpell first_wizard_magic_nuke_spell_found; first_wizard_magic_nuke_spell_found.SpellId = 0; @@ -1855,32 +1855,32 @@ BotSpell Bot::GetBestBotWizardNukeSpellByTargetResists(Bot* caster, Mob* target, } else if (!select_lure_nuke && IsPureNukeSpell(bot_spell_list_itr->SpellId)) { if ( - ((target->GetMR() < target->GetCR()) || (target->GetMR() < target->GetFR())) && - (GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_MAGIC) && + ((target->GetMR() < target->GetCR()) || (target->GetMR() < target->GetFR())) && + (GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_MAGIC) && (spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) && caster->CastChecks(bot_spell_list_itr->SpellId, target, spell_type) ) { spell_selected = true; } else if ( - ((target->GetCR() < target->GetMR()) || (target->GetCR() < target->GetFR())) && - (GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_COLD) && - (spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) && + ((target->GetCR() < target->GetMR()) || (target->GetCR() < target->GetFR())) && + (GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_COLD) && + (spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) && caster->CastChecks(bot_spell_list_itr->SpellId, target, spell_type) ) { spell_selected = true; } else if ( - ((target->GetFR() < target->GetCR()) || (target->GetFR() < target->GetMR())) && - (GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_FIRE) && - (spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) && + ((target->GetFR() < target->GetCR()) || (target->GetFR() < target->GetMR())) && + (GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_FIRE) && + (spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) && caster->CastChecks(bot_spell_list_itr->SpellId, target, spell_type) ) { spell_selected = true; } else if ( - (GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_MAGIC) && - (spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) && + (GetSpellResistType(bot_spell_list_itr->SpellId) == RESIST_MAGIC) && + (spells[bot_spell_list_itr->SpellId].resist_difficulty > lure_resis_value) && caster->CastChecks(bot_spell_list_itr->SpellId, target, spell_type) ) { first_wizard_magic_nuke_spell_found.SpellId = bot_spell_list_itr->SpellId; @@ -1998,11 +1998,11 @@ BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* caster, Mob *tar, uint16 spell if ( (bot_spell_list[i].type == BotSpellTypes::Debuff || IsResistDebuffSpell(bot_spell_list[i].spellid)) && ( - (needs_magic_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistMagic) || IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistAll))) || - (needs_cold_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistCold) || IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistAll))) || - (needs_fire_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistFire) || IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistAll))) || - (needs_poison_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistPoison) || IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistAll))) || - (needs_disease_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistDisease) || IsEffectInSpell(bot_spell_list[i].spellid, SE_ResistAll))) + (needs_magic_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistMagic) || IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistAll))) || + (needs_cold_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistCold) || IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistAll))) || + (needs_fire_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistFire) || IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistAll))) || + (needs_poison_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistPoison) || IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistAll))) || + (needs_disease_resist_debuff && (IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistDisease) || IsEffectInSpell(bot_spell_list[i].spellid, SpellEffect::ResistAll))) ) && !tar->IsImmuneToSpell(bot_spell_list[i].spellid, caster) && tar->CanBuffStack(bot_spell_list[i].spellid, caster->GetLevel(), true) >= 0 && @@ -2033,7 +2033,7 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* caster, Mob* tar, uint16 spell_type) { if (caster) { std::vector bot_spell_list_itr = GetPrioritizedBotSpellsBySpellType(caster, spell_type, tar); - + if (IsGroupBotSpellType(spell_type)) { int count_needs_cured = 0; uint16 count_poisoned = 0; @@ -2049,16 +2049,16 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* caster, Mob* tar, uint16 spell_type) { for (Mob* m : (IsGroupBotSpellType(spell_type) ? caster->GetSpellTargetList() : caster->GetSpellTargetList(true))) { if (caster->GetNeedsCured(m)) { if (caster->CastChecks(itr->SpellId, m, spell_type, true, IsGroupBotSpellType(spell_type))) { - if (m->FindType(SE_PoisonCounter)) { + if (m->FindType(SpellEffect::PoisonCounter)) { ++count_poisoned; } - if (m->FindType(SE_DiseaseCounter)) { + if (m->FindType(SpellEffect::DiseaseCounter)) { ++count_diseased; } - if (m->FindType(SE_CurseCounter)) { + if (m->FindType(SpellEffect::CurseCounter)) { ++count_cursed; } - if (m->FindType(SE_CorruptionCounter)) { + if (m->FindType(SpellEffect::CorruptionCounter)) { ++count_corrupted; } } @@ -2066,10 +2066,10 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* caster, Mob* tar, uint16 spell_type) { } if ( - (count_poisoned >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SE_PoisonCounter)) || - (count_diseased >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SE_DiseaseCounter)) || - (count_cursed >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SE_CurseCounter)) || - (count_corrupted >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SE_CorruptionCounter)) + (count_poisoned >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SpellEffect::PoisonCounter)) || + (count_diseased >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SpellEffect::DiseaseCounter)) || + (count_cursed >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SpellEffect::CurseCounter)) || + (count_corrupted >= caster->GetSpellTypeAEOrGroupTargetCount(spell_type) && IsEffectInSpell(itr->SpellId, SpellEffect::CorruptionCounter)) ) { result.SpellId = itr->SpellId; result.SpellIndex = itr->SpellIndex; @@ -2086,10 +2086,10 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* caster, Mob* tar, uint16 spell_type) { } if ( - tar->FindType(SE_PoisonCounter) && IsEffectInSpell(itr->SpellId, SE_PoisonCounter) || - tar->FindType(SE_DiseaseCounter) && IsEffectInSpell(itr->SpellId, SE_DiseaseCounter) || - tar->FindType(SE_CurseCounter) && IsEffectInSpell(itr->SpellId, SE_CurseCounter) || - tar->FindType(SE_CorruptionCounter) && IsEffectInSpell(itr->SpellId, SE_CorruptionCounter) + tar->FindType(SpellEffect::PoisonCounter) && IsEffectInSpell(itr->SpellId, SpellEffect::PoisonCounter) || + tar->FindType(SpellEffect::DiseaseCounter) && IsEffectInSpell(itr->SpellId, SpellEffect::DiseaseCounter) || + tar->FindType(SpellEffect::CurseCounter) && IsEffectInSpell(itr->SpellId, SpellEffect::CurseCounter) || + tar->FindType(SpellEffect::CorruptionCounter) && IsEffectInSpell(itr->SpellId, SpellEffect::CorruptionCounter) ) { result.SpellId = itr->SpellId; result.SpellIndex = itr->SpellIndex; @@ -2146,13 +2146,13 @@ uint8 Bot::GetChanceToCastBySpellType(uint16 spell_type) case BotSpellTypes::Dispel: return RuleI(Bots, PercentChanceToCastDispel); case BotSpellTypes::InCombatBuff: - return RuleI(Bots, PercentChanceToCastInCombatBuff); + return RuleI(Bots, PercentChanceToCastInCombatBuff); case BotSpellTypes::HateLine: return RuleI(Bots, PercentChanceToCastHateLine); case BotSpellTypes::Mez: - return RuleI(Bots, PercentChanceToCastMez); + return RuleI(Bots, PercentChanceToCastMez); case BotSpellTypes::Slow: - return RuleI(Bots, PercentChanceToCastSlow); + return RuleI(Bots, PercentChanceToCastSlow); case BotSpellTypes::Debuff: return RuleI(Bots, PercentChanceToCastDebuff); case BotSpellTypes::Cure: @@ -2161,7 +2161,7 @@ uint8 Bot::GetChanceToCastBySpellType(uint16 spell_type) case BotSpellTypes::GroupCures: return RuleI(Bots, PercentChanceToCastGroupCure); case BotSpellTypes::HateRedux: - return RuleI(Bots, PercentChanceToCastHateRedux); + return RuleI(Bots, PercentChanceToCastHateRedux); case BotSpellTypes::Fear: return RuleI(Bots, PercentChanceToCastFear); case BotSpellTypes::RegularHeal: @@ -2758,8 +2758,8 @@ bool Bot::IsValidSpellRange(uint16 spell_id, Mob* tar) { ) { range = GetAOERange(spell_id); } - - if (RuleB(Bots, EnableBotTGB) && IsTGBCompatibleSpell(spell_id) && IsGroupSpell(spell_id)) { + + if (RuleB(Bots, EnableBotTGB) && IsTGBCompatibleSpell(spell_id) && IsGroupSpell(spell_id)) { range = spells[spell_id].aoe_range; } @@ -2838,7 +2838,7 @@ BotSpell Bot::GetBestBotSpellForRez(Bot* caster, Mob* target, uint16 spell_type) result.ManaCost = 0; if (caster) { - std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_Revive); + std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::Revive); for (std::list::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) { if ( @@ -2865,7 +2865,7 @@ BotSpell Bot::GetBestBotSpellForCharm(Bot* caster, Mob* target, uint16 spell_typ result.ManaCost = 0; if (caster) { - std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SE_Charm); + std::list bot_spell_list = GetBotSpellsForSpellEffect(caster, spell_type, SpellEffect::Charm); for (std::list::iterator bot_spell_list_itr = bot_spell_list.begin(); bot_spell_list_itr != bot_spell_list.end(); ++bot_spell_list_itr) { if ( diff --git a/zone/client.cpp b/zone/client.cpp index 50c42f69bf..5ed9eddec1 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1391,7 +1391,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s } case ChatChannel_Shout: { /* Shout */ Mob *sender = this; - if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SpellEffect::VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); @@ -1429,7 +1429,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s else if(!RuleB(Chat, ServerWideAuction)) { Mob *sender = this; - if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SpellEffect::VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); @@ -1476,7 +1476,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s { Mob *sender = this; - if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SpellEffect::VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); @@ -1606,7 +1606,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s } Mob* sender = this; - if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft)) { + if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SpellEffect::VoiceGraft)) { sender = GetPet(); } @@ -6907,7 +6907,7 @@ void Client::CheckLDoNHail(NPC* n) auto pet = GetPet(); if (pet) { if (pet->GetPetType() == PetType::Charmed) { - pet->BuffFadeByEffect(SE_Charm); + pet->BuffFadeByEffect(SpellEffect::Charm); } else if (pet->GetPetType() == PetType::Follow) { pet->SetOwnerID(0); } else { @@ -10658,7 +10658,7 @@ void Client::MovePCDynamicZone(const std::string& zone_name, int zone_version, b } void Client::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls, bool calculate_speed) { - BuffFadeByEffect(SE_Levitate); + BuffFadeByEffect(SpellEffect::Levitate); if (CheckLosFN(target_x, target_y, target_z, 6.0f) || ignore_los) { auto p = new EQApplicationPacket(OP_Fling, sizeof(fling_struct)); auto* f = (fling_struct*) p->pBuffer; @@ -10723,7 +10723,7 @@ std::vector Client::GetLearnableDisciplines(uint8 min_level, uint8 max_leve continue; } - if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == SE_CHA) { + if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == SpellEffect::CHA) { continue; } @@ -10794,7 +10794,7 @@ std::vector Client::GetScribeableSpells(uint8 min_level, uint8 max_level) { continue; } - if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == SE_CHA) { + if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == SpellEffect::CHA) { continue; } @@ -11436,7 +11436,7 @@ void Client::SummonBaggedItems(uint32 bag_item_id, const std::vector& return; } - // todo: maybe some common functions for SE_SummonItem and SE_SummonItemIntoBag + // todo: maybe some common functions for SpellEffect::SummonItem and SpellEffect::SummonItemIntoBag const EQ::ItemData* bag_item = database.GetItem(bag_item_id); if (!bag_item) diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 85149ef065..6c7026185c 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -693,7 +693,7 @@ int64 Client::CalcManaRegen(bool bCombat) } regen += aabonuses.ManaRegen; - // add in + 1 bonus for SE_CompleteHeal, but we don't do anything for it yet? + // add in + 1 bonus for SpellEffect::CompleteHeal, but we don't do anything for it yet? int item_bonus = itembonuses.ManaRegen; // this is capped already item_bonus += itembonuses.heroic_mana_regen; @@ -1482,24 +1482,24 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) Bard Spell Effects Mod uses the highest bonus from either of these for each instrument - SPA 179 SE_AllInstrumentMod is used for instrument spellbonus.______Mod. This applies to ALL instrument mods (Puretones Discipline) - SPA 260 SE_AddSingingMod is used for instrument spellbonus.______Mod. This applies to indiviual instrument mods. (Instrument mastery AA) + SPA 179 SpellEffect::AllInstrumentMod is used for instrument spellbonus.______Mod. This applies to ALL instrument mods (Puretones Discipline) + SPA 260 SpellEffect::AddSingingMod is used for instrument spellbonus.______Mod. This applies to indiviual instrument mods. (Instrument mastery AA) -Example usage: From AA a value of 4 = 40% - SPA 118 SE_Amplification is a stackable singing mod, on live it exists as both spell and AA bonus (stackable) + SPA 118 SpellEffect::Amplification is a stackable singing mod, on live it exists as both spell and AA bonus (stackable) - Live Behavior: Amplifcation can be modified by singing mods and amplification itself, thus on the second cast of Amplification you will recieve the mod from the first cast, this continues until you reach the song mod cap. - SPA 261 SE_SongModCap raises song focus cap (No longer used on live) - SPA 270 SE_BardSongRange increase range of beneficial bard songs (Sionachie's Crescendo) + SPA 261 SpellEffect::SongModCap raises song focus cap (No longer used on live) + SPA 270 SpellEffect::BardSongRange increase range of beneficial bard songs (Sionachie's Crescendo) - SPA 413 SE_FcBaseEffects focus effect that replaced item instrument mods + SPA 413 SpellEffect::FcBaseEffects focus effect that replaced item instrument mods Issues 10-15-21: Bonuses are not applied, unless song is stopped and restarted due to pulse keeping it continues. -> Need to recode songs to recast when duration ends. Formula Live Bards: - mod = (10 + (aabonus.____Mod [SPA 260 AA Instrument Mastery]) + (SE_FcBaseEffect[SPA 413])/10 + (spellbonus.______Mod [SPA 179 Puretone Disc]) + (Amplication [SPA 118])/10 + mod = (10 + (aabonus.____Mod [SPA 260 AA Instrument Mastery]) + (SpellEffect::FcBaseEffect[SPA 413])/10 + (spellbonus.______Mod [SPA 179 Puretone Disc]) + (Amplication [SPA 118])/10 TODO: Spell Table Fields that need to be implemented Field 225 //float base_effects_focus_slope; // -- BASE_EFFECTS_FOCUS_SLOPE @@ -1567,7 +1567,7 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) else effectmod = spellbonuses.singingMod; if (IsBardSong(spell_id)) - effectmod += aabonuses.singingMod + (spellbonuses.Amplification + itembonuses.Amplification + aabonuses.Amplification); //SPA 118 SE_Amplification + effectmod += aabonuses.singingMod + (spellbonuses.Amplification + itembonuses.Amplification + aabonuses.Amplification); //SPA 118 SpellEffect::Amplification break; default: effectmod = 10; @@ -1584,7 +1584,7 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) if (effectmodcap) { - effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap; //SPA 261 SE_SongModCap (not used on live) + effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap; //SPA 261 SpellEffect::SongModCap (not used on live) //Incase a negative modifier is used. if (effectmodcap <= 0) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2100cbb19f..42f0b8bbed 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -671,7 +671,7 @@ void Client::CompleteConnect() for (int x1 = 0; x1 < EFFECT_COUNT; x1++) { switch (spell.effect_id[x1]) { - case SE_Illusion: { + case SpellEffect::Illusion: { if (GetIllusionBlock()) { break; } @@ -682,41 +682,41 @@ void Client::CompleteConnect() } break; } - case SE_SummonHorse: { + case SpellEffect::SummonHorse: { if (RuleB(Character, PreventMountsFromZoning) || !zone->CanCastOutdoor()) { - BuffFadeByEffect(SE_SummonHorse); + BuffFadeByEffect(SpellEffect::SummonHorse); } else { SummonHorse(buffs[j1].spellid); } break; } - case SE_Silence: + case SpellEffect::Silence: { Silence(true); break; } - case SE_Amnesia: + case SpellEffect::Amnesia: { Amnesia(true); break; } - case SE_DivineAura: + case SpellEffect::DivineAura: { invulnerable = true; break; } - case SE_Invisibility2: - case SE_Invisibility: + case SpellEffect::Invisibility2: + case SpellEffect::Invisibility: { SendAppearancePacket(AppearanceType::Invisibility, Invisibility::Invisible); break; } - case SE_Levitate: + case SpellEffect::Levitate: { if (!zone->CanLevitate()) { if (!GetGM()) { SendAppearancePacket(AppearanceType::FlyMode, 0); - BuffFadeByEffect(SE_Levitate); + BuffFadeByEffect(SpellEffect::Levitate); Message(Chat::Red, "You can't levitate in this zone."); break; } @@ -737,18 +737,18 @@ void Client::CompleteConnect() break; } - case SE_AddMeleeProc: - case SE_WeaponProc: + case SpellEffect::AddMeleeProc: + case SpellEffect::WeaponProc: { AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC)); break; } - case SE_DefensiveProc: + case SpellEffect::DefensiveProc: { AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC)); break; } - case SE_RangedProc: + case SpellEffect::RangedProc: { AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC)); break; @@ -4259,7 +4259,7 @@ void Client::Handle_OP_BuffRemoveRequest(const EQApplicationPacket *app) uint16 SpellID = m->GetSpellIDFromSlot(brrs->SlotID); - if (SpellID && (GetGM() || ((IsBeneficialSpell(SpellID) || IsEffectInSpell(SpellID, SE_BindSight)) && !spells[SpellID].no_remove))) { + if (SpellID && (GetGM() || ((IsBeneficialSpell(SpellID) || IsEffectInSpell(SpellID, SpellEffect::BindSight)) && !spells[SpellID].no_remove))) { m->BuffFadeBySlot(brrs->SlotID, true); } } @@ -5078,7 +5078,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { // Dismount horses when entering water if (GetHorseId() && RuleB(Character, DismountWater)) { SetHorseId(0); - BuffFadeByEffect(SE_SummonHorse); + BuffFadeByEffect(SpellEffect::SummonHorse); } } CheckRegionTypeChanges(); @@ -11312,7 +11312,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); if (pet->GetPetType() == PetType::Charmed) { - pet->BuffFadeByEffect(SE_Charm); + pet->BuffFadeByEffect(SpellEffect::Charm); break; } else { SetPet(nullptr); @@ -14239,7 +14239,7 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app) Recast is 3 minutes. For custom use cases, Mob::ShieldAbility can be used in quests with all parameters being altered. This functional - is also used for SPA 201 SE_PetShield, which functions in a simalar manner with pet shielding owner. + is also used for SPA 201 SpellEffect::PetShield, which functions in a simalar manner with pet shielding owner. Note: If either the shielder or the shield target die all variables are reset on both. diff --git a/zone/common.h b/zone/common.h index 5c5e12f796..4c187566d5 100644 --- a/zone/common.h +++ b/zone/common.h @@ -53,50 +53,50 @@ namespace Archetype { #define SHIELD_ABILITY_RECAST_TIME 180 typedef enum { //focus types - focusSpellHaste = 1, //@Fc, SPA: 127, SE_IncreaseSpellHaste, On Caster, cast time mod pct, base: pct - focusSpellDuration, //@Fc, SPA: 128, SE_IncreaseSpellDuration, On Caster, spell duration mod pct, base: pct - focusRange, //@Fc, SPA: 129, SE_IncreaseRange, On Caster, spell range mod pct, base: pct - focusReagentCost, //@Fc, SPA: 131, SE_ReduceReagentCost, On Caster, do not consume reagent pct chance, base: min pct, limit: max pct - focusManaCost, //@Fc, SPA: 132, SE_ReduceManaCost, On Caster, reduce mana cost by pct, base: min pct, limt: max pct - focusImprovedHeal, //@Fc, SPA: 125, SE_ImprovedHeal, On Caster, spell healing mod pct, base: min pct, limit: max pct - focusImprovedDamage, //@Fc, SPA: 124, SE_ImprovedDamage, On Caster, spell damage mod pct, base: min pct, limit: max pct - focusImprovedDamage2, //@Fc, SPA: 461, SE_ImprovedDamage2, On Caster, spell damage mod pct, base: min pct, limit: max pct - focusFcDamagePctCrit, //@Fc, SPA: 302, SE_FcDamagePctCrit, On Caster, spell damage mod pct, base: min pct, limit: max pct - focusPetPower, //@Fc, SPA: 167, SE_PetPowerIncrease, On Caster, pet power mod, base: value - focusResistRate, //@Fc, SPA: 126, SE_SpellResistReduction, On Caster, casted spell resist mod pct, base: min pct, limit: max pct - focusSpellHateMod, //@Fc, SPA: 130, SE_SpellHateMod, On Caster, spell hate mod pct, base: min pct, limit: max pct - focusTriggerOnCast, //@Fc, SPA: 339, SE_TriggerOnCast, On Caster, cast on spell use, base: chance pct limit: spellid - focusSpellVulnerability, //@Fc, SPA: 296, SE_FcSpellVulnerability, On Target, spell damage taken mod pct, base: min pct, limit: max pct - focusFcSpellDamagePctIncomingPC, //@Fc, SPA: 483, SE_Fc_Spell_Damage_Pct_IncomingPC, On Target, spell damage taken mod pct, base: min pct, limit: max pct - focusTwincast, //@Fc, SPA: 399, SE_FcTwincast, On Caster, chance cast spell twice, base: chance pct - focusSympatheticProc, //@Fc, SPA: 383, SE_SympatheticProc, On Caster, cast on spell use, base: variable proc chance on cast time, limit: spellid - focusFcDamageAmt, //@Fc, SPA: 286, SE_FcDamageAmt, On Caster, spell damage mod flat amt, base: amt - focusFcDamageAmt2, //@Fc, SPA: 462, SE_FcDamageAmt2, On Caster, spell damage mod flat amt, base: amt - focusFcDamageAmtCrit, //@Fc, SPA: 303, SE_FFcDamageAmtCrit, On Caster, spell damage mod flat amt, base: amt - focusSpellDurByTic, //@Fc, SPA: 287, SE_SpellDurationIncByTic, On Caster, spell buff duration mod, base: tics - focusSwarmPetDuration, //@Fc, SPA: 398, SE_SwarmPetDuration, On Caster, swarm pet duration mod, base: milliseconds - focusReduceRecastTime, //@Fc, SPA: 310, SE_ReduceReuseTimer, On Caster, disc reuse time mod, base: milliseconds - focusBlockNextSpell, //@Fc, SPA: 335, SE_BlockNextSpellFocus, On Caster, chance to block next spell, base: chance - focusFcHealPctIncoming, //@Fc, SPA: 393, SE_FcHealPctIncoming, On Target, heal received mod pct, base: pct - focusFcDamageAmtIncoming, //@Fc, SPA: 297, SE_FcDamageAmtIncoming, On Target, damage taken flat amt, base: amt - focusFcSpellDamageAmtIncomingPC, //@Fc, SPA: 484, SE_Fc_Spell_Damage_Amt_IncomingPC, On Target, damage taken flat amt, base: amt - focusFcCastSpellOnLand, //@Fc, SPA: 481, SE_Fc_Cast_Spell_On_Land, On Target, cast spell if hit by spell, base: chance pct, limit: spellid - focusFcHealAmtIncoming, //@Fc, SPA: 394, SE_FcHealAmtIncoming, On Target, heal received mod flat amt, base: amt - focusFcBaseEffects, //@Fc, SPA: 413, SE_FcBaseEffects, On Caster, base spell effectiveness mod pct, base: pct - focusIncreaseNumHits, //@Fc, SPA: 421, SE_FcIncreaseNumHits, On Caster, numhits mod flat amt, base: amt - focusFcLimitUse, //@Fc, SPA: 420, SE_FcLimitUse, On Caster, numhits mod pct, base: pct - focusFcMute, //@Fc, SPA: 357, SE_FcMute, On Caster, prevents spell casting, base: chance pct - focusFcTimerRefresh, //@Fc, SPA: 389, SE_FcTimerRefresh, On Caster, reset spell recast timer, base: 1 - focusFcTimerLockout, //@Fc, SPA: 390, SE_FcTimerLockout, On Caster, set a spell to be on recast timer, base: recast duration milliseconds - focusFcStunTimeMod, //@Fc, SPA: 133, SE_FcStunTimeMod, On Caster, stun time mod pct, base: chance pct - focusFcResistIncoming, //@Fc, SPA: 510, SE_Fc_Resist_Incoming, On Target, resist modifier, base: amt - focusFcAmplifyMod, //@Fc, SPA: 507, SE_Fc_Amplify_Mod, On Caster, damage-heal-dot mod pct, base: pct - focusFcAmplifyAmt, //@Fc, SPA: 508, SE_Fc_Amplify_Amt, On Caster, damage-heal-dot mod flat amt, base: amt - focusFcCastTimeMod2, //@Fc, SPA: 500, SE_Fc_CastTimeMod2, On Caster, cast time mod pct, base: pct - focusFcCastTimeAmt, //@Fc, SPA: 501, SE_Fc_CastTimeAmt, On Caster, cast time mod flat amt, base: milliseconds - focusFcHealPctCritIncoming, //@Fc, SPA: 395, SE_FcHealPctCritIncoming, On Target, spell healing mod pct, base: pct - focusFcHealAmt, //@Fc, SPA: 392, SE_FcHealAmt, On Caster, spell healing mod flat amt, base: amt - focusFcHealAmtCrit, //@Fc, SPA: 396, SE_FcHealAmtCrit, On Caster, spell healing mod flat amt, base: amt + focusSpellHaste = 1, //@Fc, SPA: 127, SpellEffect::IncreaseSpellHaste, On Caster, cast time mod pct, base: pct + focusSpellDuration, //@Fc, SPA: 128, SpellEffect::IncreaseSpellDuration, On Caster, spell duration mod pct, base: pct + focusRange, //@Fc, SPA: 129, SpellEffect::IncreaseRange, On Caster, spell range mod pct, base: pct + focusReagentCost, //@Fc, SPA: 131, SpellEffect::ReduceReagentCost, On Caster, do not consume reagent pct chance, base: min pct, limit: max pct + focusManaCost, //@Fc, SPA: 132, SpellEffect::ReduceManaCost, On Caster, reduce mana cost by pct, base: min pct, limt: max pct + focusImprovedHeal, //@Fc, SPA: 125, SpellEffect::ImprovedHeal, On Caster, spell healing mod pct, base: min pct, limit: max pct + focusImprovedDamage, //@Fc, SPA: 124, SpellEffect::ImprovedDamage, On Caster, spell damage mod pct, base: min pct, limit: max pct + focusImprovedDamage2, //@Fc, SPA: 461, SpellEffect::ImprovedDamage2, On Caster, spell damage mod pct, base: min pct, limit: max pct + focusFcDamagePctCrit, //@Fc, SPA: 302, SpellEffect::FcDamagePctCrit, On Caster, spell damage mod pct, base: min pct, limit: max pct + focusPetPower, //@Fc, SPA: 167, SpellEffect::PetPowerIncrease, On Caster, pet power mod, base: value + focusResistRate, //@Fc, SPA: 126, SpellEffect::SpellResistReduction, On Caster, casted spell resist mod pct, base: min pct, limit: max pct + focusSpellHateMod, //@Fc, SPA: 130, SpellEffect::SpellHateMod, On Caster, spell hate mod pct, base: min pct, limit: max pct + focusTriggerOnCast, //@Fc, SPA: 339, SpellEffect::TriggerOnCast, On Caster, cast on spell use, base: chance pct limit: spellid + focusSpellVulnerability, //@Fc, SPA: 296, SpellEffect::FcSpellVulnerability, On Target, spell damage taken mod pct, base: min pct, limit: max pct + focusFcSpellDamagePctIncomingPC, //@Fc, SPA: 483, SpellEffect::Fc_Spell_Damage_Pct_IncomingPC, On Target, spell damage taken mod pct, base: min pct, limit: max pct + focusTwincast, //@Fc, SPA: 399, SpellEffect::FcTwincast, On Caster, chance cast spell twice, base: chance pct + focusSympatheticProc, //@Fc, SPA: 383, SpellEffect::SympatheticProc, On Caster, cast on spell use, base: variable proc chance on cast time, limit: spellid + focusFcDamageAmt, //@Fc, SPA: 286, SpellEffect::FcDamageAmt, On Caster, spell damage mod flat amt, base: amt + focusFcDamageAmt2, //@Fc, SPA: 462, SpellEffect::FcDamageAmt2, On Caster, spell damage mod flat amt, base: amt + focusFcDamageAmtCrit, //@Fc, SPA: 303, SpellEffect::FFcDamageAmtCrit, On Caster, spell damage mod flat amt, base: amt + focusSpellDurByTic, //@Fc, SPA: 287, SpellEffect::SpellDurationIncByTic, On Caster, spell buff duration mod, base: tics + focusSwarmPetDuration, //@Fc, SPA: 398, SpellEffect::SwarmPetDuration, On Caster, swarm pet duration mod, base: milliseconds + focusReduceRecastTime, //@Fc, SPA: 310, SpellEffect::ReduceReuseTimer, On Caster, disc reuse time mod, base: milliseconds + focusBlockNextSpell, //@Fc, SPA: 335, SpellEffect::BlockNextSpellFocus, On Caster, chance to block next spell, base: chance + focusFcHealPctIncoming, //@Fc, SPA: 393, SpellEffect::FcHealPctIncoming, On Target, heal received mod pct, base: pct + focusFcDamageAmtIncoming, //@Fc, SPA: 297, SpellEffect::FcDamageAmtIncoming, On Target, damage taken flat amt, base: amt + focusFcSpellDamageAmtIncomingPC, //@Fc, SPA: 484, SpellEffect::Fc_Spell_Damage_Amt_IncomingPC, On Target, damage taken flat amt, base: amt + focusFcCastSpellOnLand, //@Fc, SPA: 481, SpellEffect::Fc_Cast_Spell_On_Land, On Target, cast spell if hit by spell, base: chance pct, limit: spellid + focusFcHealAmtIncoming, //@Fc, SPA: 394, SpellEffect::FcHealAmtIncoming, On Target, heal received mod flat amt, base: amt + focusFcBaseEffects, //@Fc, SPA: 413, SpellEffect::FcBaseEffects, On Caster, base spell effectiveness mod pct, base: pct + focusIncreaseNumHits, //@Fc, SPA: 421, SpellEffect::FcIncreaseNumHits, On Caster, numhits mod flat amt, base: amt + focusFcLimitUse, //@Fc, SPA: 420, SpellEffect::FcLimitUse, On Caster, numhits mod pct, base: pct + focusFcMute, //@Fc, SPA: 357, SpellEffect::FcMute, On Caster, prevents spell casting, base: chance pct + focusFcTimerRefresh, //@Fc, SPA: 389, SpellEffect::FcTimerRefresh, On Caster, reset spell recast timer, base: 1 + focusFcTimerLockout, //@Fc, SPA: 390, SpellEffect::FcTimerLockout, On Caster, set a spell to be on recast timer, base: recast duration milliseconds + focusFcStunTimeMod, //@Fc, SPA: 133, SpellEffect::FcStunTimeMod, On Caster, stun time mod pct, base: chance pct + focusFcResistIncoming, //@Fc, SPA: 510, SpellEffect::Fc_Resist_Incoming, On Target, resist modifier, base: amt + focusFcAmplifyMod, //@Fc, SPA: 507, SpellEffect::Fc_Amplify_Mod, On Caster, damage-heal-dot mod pct, base: pct + focusFcAmplifyAmt, //@Fc, SPA: 508, SpellEffect::Fc_Amplify_Amt, On Caster, damage-heal-dot mod flat amt, base: amt + focusFcCastTimeMod2, //@Fc, SPA: 500, SpellEffect::Fc_CastTimeMod2, On Caster, cast time mod pct, base: pct + focusFcCastTimeAmt, //@Fc, SPA: 501, SpellEffect::Fc_CastTimeAmt, On Caster, cast time mod flat amt, base: milliseconds + focusFcHealPctCritIncoming, //@Fc, SPA: 395, SpellEffect::FcHealPctCritIncoming, On Target, spell healing mod pct, base: pct + focusFcHealAmt, //@Fc, SPA: 392, SpellEffect::FcHealAmt, On Caster, spell healing mod flat amt, base: amt + focusFcHealAmtCrit, //@Fc, SPA: 396, SpellEffect::FcHealAmtCrit, On Caster, spell healing mod flat amt, base: amt } focusType; //Any new FocusType needs to be added to the Mob::IsFocus function #define HIGHEST_FOCUS focusFcHealAmtCrit //Should always be last focusType in enum diff --git a/zone/effects.cpp b/zone/effects.cpp index 8d8ccb9c9d..3efda3d5e0 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -263,7 +263,7 @@ int64 Mob::GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_ chance += itembonuses.CriticalDoTChance + spellbonuses.CriticalDoTChance + aabonuses.CriticalDoTChance; if (spellbonuses.CriticalDotDecay) - chance += GetDecayEffectValue(spell_id, SE_CriticalDotDecay); + chance += GetDecayEffectValue(spell_id, SpellEffect::CriticalDotDecay); if (spells[spell_id].override_crit_chance > 0 && chance > spells[spell_id].override_crit_chance) chance = spells[spell_id].override_crit_chance; @@ -429,14 +429,14 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr critical_chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance; if (spellbonuses.CriticalHealDecay) { - critical_chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay); + critical_chance += GetDecayEffectValue(spell_id, SpellEffect::CriticalHealDecay); } } else { critical_chance = itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime; if (spellbonuses.CriticalRegenDecay) { - critical_chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay); + critical_chance += GetDecayEffectValue(spell_id, SpellEffect::CriticalRegenDecay); } } @@ -596,7 +596,7 @@ int32 Mob::GetActSpellCost(uint16 spell_id, int32 cost) if (buffs[buffSlot].spellid == 0 || buffs[buffSlot].spellid >= SPDAT_RECORDS) continue; - if(IsEffectInSpell(buffs[buffSlot].spellid, SE_ReduceManaCost)) { + if(IsEffectInSpell(buffs[buffSlot].spellid, SpellEffect::ReduceManaCost)) { if(CalcFocusEffect(focusManaCost, buffs[buffSlot].spellid, spell_id) == 100) cost = 1; } @@ -1105,8 +1105,8 @@ void EntityList::AESpell( IsTargetableAESpell(spell_id) && is_detrimental_spell && !is_npc && - !IsEffectInSpell(spell_id, SE_Lull) && - !IsEffectInSpell(spell_id, SE_Mez) + !IsEffectInSpell(spell_id, SpellEffect::Lull) && + !IsEffectInSpell(spell_id, SpellEffect::Mez) ) { max_targets_allowed = RuleI(Spells, TargetedAOEMaxTargets); } else if ( diff --git a/zone/fearpath.cpp b/zone/fearpath.cpp index e7fcd458bb..e944b057da 100644 --- a/zone/fearpath.cpp +++ b/zone/fearpath.cpp @@ -365,7 +365,7 @@ void Mob::CalculateNewFearpoint() // fallback logic if pathing system can't be used bool inliquid = zone->HasWaterMap() && zone->watermap->InLiquid(glm::vec3(GetPosition())) || zone->IsWaterZone(GetZ()); bool stay_inliquid = (inliquid && IsNPC() && CastToNPC()->IsUnderwaterOnly()); - bool levitating = IsClient() && (FindType(SE_Levitate) || flymode != GravityBehavior::Ground); + bool levitating = IsClient() && (FindType(SpellEffect::Levitate) || flymode != GravityBehavior::Ground); bool open_outdoor_zone = !zone->CanCastOutdoor() && !zone->IsCity(); int loop = 0; diff --git a/zone/merc.cpp b/zone/merc.cpp index f19287e86d..c29faff18a 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -118,7 +118,7 @@ void Merc::CalcBonuses() CalcMaxMana(); CalcMaxEndurance(); - rooted = FindType(SE_Root); + rooted = FindType(SpellEffect::Root); } float Merc::GetDefaultSize() { @@ -1730,7 +1730,7 @@ bool Merc::AICastSpell(int8 iChance, uint32 iSpellTypes) { } else { //check for heal over time. if not present, try it first - if (!tar->FindType(SE_HealOverTime)) { + if (!tar->FindType(SpellEffect::HealOverTime)) { selectedMercSpell = GetBestMercSpellForHealOverTime(this); //get regular heal @@ -1779,7 +1779,7 @@ bool Merc::AICastSpell(int8 iChance, uint32 iSpellTypes) { if( !IsImmuneToSpell(selectedMercSpell.spellid, this) && (CanBuffStack(selectedMercSpell.spellid, mercLevel, true) >= 0)) { - if( GetArchetype() == Archetype::Melee && IsEffectInSpell(selectedMercSpell.spellid, SE_IncreaseSpellHaste)) { + if( GetArchetype() == Archetype::Melee && IsEffectInSpell(selectedMercSpell.spellid, SpellEffect::IncreaseSpellHaste)) { continue; } @@ -1806,7 +1806,7 @@ bool Merc::AICastSpell(int8 iChance, uint32 iSpellTypes) { if( !tar->IsImmuneToSpell(selectedMercSpell.spellid, this) && (tar->CanBuffStack(selectedMercSpell.spellid, mercLevel, true) >= 0)) { - if( tar->GetArchetype() == Archetype::Melee && IsEffectInSpell(selectedMercSpell.spellid, SE_IncreaseSpellHaste)) { + if( tar->GetArchetype() == Archetype::Melee && IsEffectInSpell(selectedMercSpell.spellid, SpellEffect::IncreaseSpellHaste)) { continue; } @@ -2292,7 +2292,7 @@ int64 Merc::GetFocusEffect(focusType type, uint16 spell_id, bool from_buff_tic) if(type == focusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact)) return 100; - if(type == focusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id))) + if(type == focusReagentCost && (IsEffectInSpell(spell_id, SpellEffect::SummonItem) || IsSacrificeSpell(spell_id))) return 0; //Summon Spells that require reagents are typically imbue type spells, enchant metal, sacrifice and shouldn't be affected //by reagent conservation for obvious reasons. @@ -2620,7 +2620,7 @@ MercSpell Merc::GetBestMercSpellForVeryFastHeal(Merc* caster) { result.time_cancast = 0; if(caster) { - std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CurrentHP); + std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SpellEffect::CurrentHP); for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { @@ -2653,7 +2653,7 @@ MercSpell Merc::GetBestMercSpellForFastHeal(Merc* caster) { result.time_cancast = 0; if(caster) { - std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CurrentHP); + std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SpellEffect::CurrentHP); for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { @@ -2686,7 +2686,7 @@ MercSpell Merc::GetBestMercSpellForHealOverTime(Merc* caster) { result.time_cancast = 0; if(caster) { - std::list mercHoTSpellList = GetMercSpellsForSpellEffect(caster, SE_HealOverTime); + std::list mercHoTSpellList = GetMercSpellsForSpellEffect(caster, SpellEffect::HealOverTime); for (auto mercSpellListItr = mercHoTSpellList.begin(); mercSpellListItr != mercHoTSpellList.end(); ++mercSpellListItr) { @@ -2727,7 +2727,7 @@ MercSpell Merc::GetBestMercSpellForPercentageHeal(Merc* caster) { result.time_cancast = 0; if(caster && caster->AI_HasSpells()) { - std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CurrentHP); + std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SpellEffect::CurrentHP); for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { @@ -2760,7 +2760,7 @@ MercSpell Merc::GetBestMercSpellForRegularSingleTargetHeal(Merc* caster) { result.time_cancast = 0; if(caster) { - std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CurrentHP); + std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SpellEffect::CurrentHP); for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { @@ -2793,7 +2793,7 @@ MercSpell Merc::GetFirstMercSpellForSingleTargetHeal(Merc* caster) { result.time_cancast = 0; if(caster) { - std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CurrentHP); + std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SpellEffect::CurrentHP); for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { @@ -2827,7 +2827,7 @@ MercSpell Merc::GetBestMercSpellForGroupHeal(Merc* caster) { result.time_cancast = 0; if(caster) { - std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CurrentHP); + std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SpellEffect::CurrentHP); for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { @@ -2860,7 +2860,7 @@ MercSpell Merc::GetBestMercSpellForGroupHealOverTime(Merc* caster) { result.time_cancast = 0; if(caster) { - std::list mercHoTSpellList = GetMercSpellsForSpellEffect(caster, SE_HealOverTime); + std::list mercHoTSpellList = GetMercSpellsForSpellEffect(caster, SpellEffect::HealOverTime); for (auto mercSpellListItr = mercHoTSpellList.begin(); mercSpellListItr != mercHoTSpellList.end(); ++mercSpellListItr) { @@ -2901,7 +2901,7 @@ MercSpell Merc::GetBestMercSpellForGroupCompleteHeal(Merc* caster) { result.time_cancast = 0; if(caster) { - std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CompleteHeal); + std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SpellEffect::CompleteHeal); for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { @@ -2934,7 +2934,7 @@ MercSpell Merc::GetBestMercSpellForAETaunt(Merc* caster) { result.time_cancast = 0; if(caster) { - std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_Taunt); + std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SpellEffect::Taunt); for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { @@ -2969,7 +2969,7 @@ MercSpell Merc::GetBestMercSpellForTaunt(Merc* caster) { result.time_cancast = 0; if(caster) { - std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_Taunt); + std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SpellEffect::Taunt); for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { @@ -3002,7 +3002,7 @@ MercSpell Merc::GetBestMercSpellForHate(Merc* caster) { result.time_cancast = 0; if(caster) { - std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_InstantHate); + std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SpellEffect::InstantHate); for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { @@ -3038,10 +3038,10 @@ MercSpell Merc::GetBestMercSpellForCure(Merc* caster, Mob *tar) { return result; int countNeedsCured = 0; - bool isPoisoned = tar->FindType(SE_PoisonCounter); - bool isDiseased = tar->FindType(SE_DiseaseCounter); - bool isCursed = tar->FindType(SE_CurseCounter); - bool isCorrupted = tar->FindType(SE_CorruptionCounter); + bool isPoisoned = tar->FindType(SpellEffect::PoisonCounter); + bool isDiseased = tar->FindType(SpellEffect::DiseaseCounter); + bool isCursed = tar->FindType(SpellEffect::CurseCounter); + bool isCorrupted = tar->FindType(SpellEffect::CorruptionCounter); if(caster && caster->AI_HasSpells()) { std::list cureList = GetMercSpellsBySpellType(caster, SpellType_Cure); @@ -3068,19 +3068,19 @@ MercSpell Merc::GetBestMercSpellForCure(Merc* caster, Mob *tar) { if(selectedMercSpell.spellid == 0) continue; - if(isPoisoned && IsEffectInSpell(itr->spellid, SE_PoisonCounter)) { + if(isPoisoned && IsEffectInSpell(itr->spellid, SpellEffect::PoisonCounter)) { spellSelected = true; } - else if(isDiseased && IsEffectInSpell(itr->spellid, SE_DiseaseCounter)) { + else if(isDiseased && IsEffectInSpell(itr->spellid, SpellEffect::DiseaseCounter)) { spellSelected = true; } - else if(isCursed && IsEffectInSpell(itr->spellid, SE_CurseCounter)) { + else if(isCursed && IsEffectInSpell(itr->spellid, SpellEffect::CurseCounter)) { spellSelected = true; } - else if(isCorrupted && IsEffectInSpell(itr->spellid, SE_CorruptionCounter)) { + else if(isCorrupted && IsEffectInSpell(itr->spellid, SpellEffect::CorruptionCounter)) { spellSelected = true; } - else if(IsEffectInSpell(itr->spellid, SE_DispelDetrimental)) { + else if(IsEffectInSpell(itr->spellid, SpellEffect::DispelDetrimental)) { spellSelected = true; } @@ -3108,19 +3108,19 @@ MercSpell Merc::GetBestMercSpellForCure(Merc* caster, Mob *tar) { if(selectedMercSpell.spellid == 0) continue; - if(isPoisoned && IsEffectInSpell(itr->spellid, SE_PoisonCounter)) { + if(isPoisoned && IsEffectInSpell(itr->spellid, SpellEffect::PoisonCounter)) { spellSelected = true; } - else if(isDiseased && IsEffectInSpell(itr->spellid, SE_DiseaseCounter)) { + else if(isDiseased && IsEffectInSpell(itr->spellid, SpellEffect::DiseaseCounter)) { spellSelected = true; } - else if(isCursed && IsEffectInSpell(itr->spellid, SE_CurseCounter)) { + else if(isCursed && IsEffectInSpell(itr->spellid, SpellEffect::CurseCounter)) { spellSelected = true; } - else if(isCorrupted && IsEffectInSpell(itr->spellid, SE_CorruptionCounter)) { + else if(isCorrupted && IsEffectInSpell(itr->spellid, SpellEffect::CorruptionCounter)) { spellSelected = true; } - else if(IsEffectInSpell(itr->spellid, SE_DispelDetrimental)) { + else if(IsEffectInSpell(itr->spellid, SpellEffect::DispelDetrimental)) { spellSelected = true; } @@ -3155,7 +3155,7 @@ MercSpell Merc::GetBestMercSpellForStun(Merc* caster) { result.time_cancast = 0; if(caster) { - std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_Stun); + std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SpellEffect::Stun); for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { @@ -3492,7 +3492,7 @@ bool Merc::GetNeedsCured(Mob *tar) { bool needCured = false; if(tar) { - if(tar->FindType(SE_PoisonCounter) || tar->FindType(SE_DiseaseCounter) || tar->FindType(SE_CurseCounter) || tar->FindType(SE_CorruptionCounter)) { + if(tar->FindType(SpellEffect::PoisonCounter) || tar->FindType(SpellEffect::DiseaseCounter) || tar->FindType(SpellEffect::CurseCounter) || tar->FindType(SpellEffect::CorruptionCounter)) { uint32 buff_count = tar->GetMaxTotalSlots(); int buffsWithCounters = 0; needCured = true; diff --git a/zone/mob.cpp b/zone/mob.cpp index 7968cdacaa..1302246b25 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -547,7 +547,7 @@ Mob::~Mob() AI_Stop(); if (GetPet()) { if (GetPet()->Charmed()) { - GetPet()->BuffFadeByEffect(SE_Charm); + GetPet()->BuffFadeByEffect(SpellEffect::Charm); } else { SetPet(0); @@ -625,7 +625,7 @@ void Mob::BreakCharmPetIfConditionsMet() { auto pet = GetPet(); if (pet && pet->GetPetType() == PetType::Charmed && HasAnInvisibilityEffect()) { if (RuleB(Pets, LivelikeBreakCharmOnInvis) || IsInvisible(pet)) { - pet->BuffFadeByEffect(SE_Charm); + pet->BuffFadeByEffect(SpellEffect::Charm); } LogRules( "Pets:LivelikeBreakCharmOnInvis for [{}] invisible [{}] hidden [{}] improved_hidden (shroud of stealth) [{}] invisible_animals [{}] invisible_undead [{}]", @@ -1352,7 +1352,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) // 3 - Mobs in water do not sink. A value of 3 in this field appears to be the default setting for all mobs // (in water or not) according to 6.2 era packet collects. if(IsClient()) - ns->spawn.flymode = FindType(SE_Levitate) ? 2 : 0; + ns->spawn.flymode = FindType(SpellEffect::Levitate) ? 2 : 0; else ns->spawn.flymode = flymode; @@ -5629,7 +5629,7 @@ int Mob::GetSnaredAmount() for(int j = 0; j < EFFECT_COUNT; j++) { - if (spells[buffs[i].spellid].effect_id[j] == SE_MovementSpeed) + if (spells[buffs[i].spellid].effect_id[j] == SpellEffect::MovementSpeed) { int64 val = CalcSpellEffectValue_formula(spells[buffs[i].spellid].formula[j], spells[buffs[i].spellid].base_value[j], spells[buffs[i].spellid].max_value[j], buffs[i].casterlevel, buffs[i].spellid); //int effect = CalcSpellEffectValue(buffs[i].spellid, spells[buffs[i].spellid].effectid[j], buffs[i].casterlevel); @@ -5827,7 +5827,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) if (!target || !IsValidSpell(spell_id)) return false; - /*The effects SE_SpellTrigger (SPA 340) and SE_Chance_Best_in_Spell_Grp (SPA 469) work as follows, you typically will have 2-3 different spells each with their own + /*The effects SpellEffect::SpellTrigger (SPA 340) and SpellEffect::Chance_Best_in_Spell_Grp (SPA 469) work as follows, you typically will have 2-3 different spells each with their own chance to be triggered with all chances equaling up to 100 pct, with only 1 spell out of the group being ultimately cast. (ie Effect1 trigger spellA with 30% chance, Effect2 triggers spellB with 20% chance, Effect3 triggers spellC with 50% chance). The following function ensures a statistically accurate chance for each spell to be cast based on their chance values. These effects are also used in spells where there @@ -5842,7 +5842,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[spell_id].effect_id[i] == SE_SpellTrigger || spells[spell_id].effect_id[i] == SE_Chance_Best_in_Spell_Grp) + if (spells[spell_id].effect_id[i] == SpellEffect::SpellTrigger || spells[spell_id].effect_id[i] == SpellEffect::Chance_Best_in_Spell_Grp) total_chance += spells[spell_id].base_value[i]; } @@ -5852,7 +5852,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) for (int i = 0; i < EFFECT_COUNT; i++){ //Find spells with SPA 340 and add the cumulative percent chances to the roll array - if ((spells[spell_id].effect_id[i] == SE_SpellTrigger) || (spells[spell_id].effect_id[i] == SE_Chance_Best_in_Spell_Grp)){ + if ((spells[spell_id].effect_id[i] == SpellEffect::SpellTrigger) || (spells[spell_id].effect_id[i] == SpellEffect::Chance_Best_in_Spell_Grp)){ const int cumulative_chance = current_chance + spells[spell_id].base_value[i]; chance_array[i] = cumulative_chance; current_chance = cumulative_chance; @@ -5875,11 +5875,11 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) } if (CastSpell) { - if (spells[spell_id].effect_id[effect_slot] == SE_SpellTrigger && IsValidSpell(spells[spell_id].limit_value[effect_slot])) { + if (spells[spell_id].effect_id[effect_slot] == SpellEffect::SpellTrigger && IsValidSpell(spells[spell_id].limit_value[effect_slot])) { SpellFinished(spells[spell_id].limit_value[effect_slot], target, EQ::spells::CastingSlot::Item, 0, -1, spells[spells[spell_id].limit_value[effect_slot]].resist_difficulty); return true; } - else if (IsClient() && spells[spell_id].effect_id[effect_slot] == SE_Chance_Best_in_Spell_Grp) { + else if (IsClient() && spells[spell_id].effect_id[effect_slot] == SpellEffect::Chance_Best_in_Spell_Grp) { uint32 best_spell_id = CastToClient()->GetHighestScribedSpellinSpellGroup(spells[spell_id].limit_value[effect_slot]); if (IsValidSpell(best_spell_id)) { SpellFinished(best_spell_id, target, EQ::spells::CastingSlot::Item, 0, -1, spells[best_spell_id].resist_difficulty); @@ -5899,7 +5899,7 @@ void Mob::TryTriggerOnCastRequirement() int spell_id = buffs[e].spellid; if (IsValidSpell(spell_id)) { for (int i = 0; i < EFFECT_COUNT; i++) { - if ((spells[spell_id].effect_id[i] == SE_TriggerOnReqTarget) || (spells[spell_id].effect_id[i] == SE_TriggerOnReqCaster)) { + if ((spells[spell_id].effect_id[i] == SpellEffect::TriggerOnReqTarget) || (spells[spell_id].effect_id[i] == SpellEffect::TriggerOnReqCaster)) { if (PassCastRestriction(spells[spell_id].limit_value[i])) { SpellFinished(spells[spell_id].base_value[i], this, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].resist_difficulty); if (!TryFadeEffect(e)) { @@ -5942,7 +5942,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id) int buff_count = GetMaxTotalSlots(); for(int i = 0; i < buff_count; i++) { - if(IsEffectInSpell(buffs[i].spellid, SE_FcTwincast)) + if(IsEffectInSpell(buffs[i].spellid, SpellEffect::FcTwincast)) { int32 focus = CalcFocusEffect(focusTwincast, buffs[i].spellid, spell_id); if(focus > 0) @@ -5968,10 +5968,10 @@ void Mob::ApplyHealthTransferDamage(Mob *caster, Mob *target, uint16 spell_id) This allows for the AE spells to function without repeatedly killing caster Damage or heal portion can be found as regular single use spell effect */ - if (IsEffectInSpell(spell_id, SE_Health_Transfer)){ + if (IsEffectInSpell(spell_id, SpellEffect::Health_Transfer)){ for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[spell_id].effect_id[i] == SE_Health_Transfer) { + if (spells[spell_id].effect_id[i] == SpellEffect::Health_Transfer) { int64 new_hp = GetMaxHP(); new_hp -= GetMaxHP() * spells[spell_id].base_value[i] / 1000; @@ -6175,8 +6175,8 @@ bool Mob::TryFadeEffect(int slot) if (!spells[buffs[slot].spellid].effect_id[i]) continue; - if (spells[buffs[slot].spellid].effect_id[i] == SE_CastOnFadeEffectAlways || - spells[buffs[slot].spellid].effect_id[i] == SE_CastOnRuneFadeEffect) + if (spells[buffs[slot].spellid].effect_id[i] == SpellEffect::CastOnFadeEffectAlways || + spells[buffs[slot].spellid].effect_id[i] == SpellEffect::CastOnRuneFadeEffect) { uint16 spell_id = spells[buffs[slot].spellid].base_value[i]; BuffFadeBySlot(slot); @@ -6560,9 +6560,9 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id) { if (IsValidSpell(spell_id)) { - if(IsEffectInSpell(spell_id, SE_ProcOnSpellKillShot)) { + if(IsEffectInSpell(spell_id, SpellEffect::ProcOnSpellKillShot)) { for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[spell_id].effect_id[i] == SE_ProcOnSpellKillShot) + if (spells[spell_id].effect_id[i] == SpellEffect::ProcOnSpellKillShot) { if (IsValidSpell(spells[spell_id].limit_value[i]) && spells[spell_id].max_value[i] <= level) { @@ -6897,11 +6897,11 @@ void Mob::DoGravityEffect() int buff_count = GetMaxTotalSlots(); for (int slot = 0; slot < buff_count; slot++) { - if (IsValidSpell(buffs[slot].spellid) && IsEffectInSpell(buffs[slot].spellid, SE_GravityEffect)) + if (IsValidSpell(buffs[slot].spellid) && IsEffectInSpell(buffs[slot].spellid, SpellEffect::GravityEffect)) { for (int i = 0; i < EFFECT_COUNT; i++) { - if(spells[buffs[slot].spellid].effect_id[i] == SE_GravityEffect) { + if(spells[buffs[slot].spellid].effect_id[i] == SpellEffect::GravityEffect) { int casterId = buffs[slot].casterid; if(casterId) @@ -7108,7 +7108,7 @@ void Mob::CastOnCurer(uint32 spell_id) { for(int i = 0; i < EFFECT_COUNT; i++) { - if (spells[spell_id].effect_id[i] == SE_CastOnCurer) + if (spells[spell_id].effect_id[i] == SpellEffect::CastOnCurer) { if(IsValidSpell(spells[spell_id].base_value[i])) { @@ -7122,7 +7122,7 @@ void Mob::CastOnCure(uint32 spell_id) { for(int i = 0; i < EFFECT_COUNT; i++) { - if (spells[spell_id].effect_id[i] == SE_CastOnCure) + if (spells[spell_id].effect_id[i] == SpellEffect::CastOnCure) { if(IsValidSpell(spells[spell_id].base_value[i])) { @@ -7139,7 +7139,7 @@ void Mob::CastOnNumHitFade(uint32 spell_id) for(int i = 0; i < EFFECT_COUNT; i++) { - if (spells[spell_id].effect_id[i] == SE_CastonNumHitFade) + if (spells[spell_id].effect_id[i] == SpellEffect::CastonNumHitFade) { if(IsValidSpell(spells[spell_id].base_value[i])) { diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 173fae7a5f..516df6384e 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -615,7 +615,7 @@ void Client::AI_SpellCast() continue; } - if(IsEffectInSpell(current_spell, SE_Charm)) + if(IsEffectInSpell(current_spell, SpellEffect::Charm)) { continue; } @@ -724,7 +724,7 @@ void Client::AI_Process() { if(!IsFeared() && !IsLD()) { - BuffFadeByEffect(SE_Charm); + BuffFadeByEffect(SpellEffect::Charm); return; } } diff --git a/zone/pets.cpp b/zone/pets.cpp index 2c8db2d317..fea4c7f7ba 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -547,22 +547,22 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { if (buffs[j1].spellid <= (uint32)SPDAT_RECORDS) { for (int x1=0; x1 < EFFECT_COUNT; x1++) { switch (spells[buffs[j1].spellid].effect_id[x1]) { - case SE_AddMeleeProc: - case SE_WeaponProc: + case SpellEffect::AddMeleeProc: + case SpellEffect::WeaponProc: // We need to reapply buff based procs // We need to do this here so suspended pets also regain their procs. AddProcToWeapon(GetProcID(buffs[j1].spellid,x1), false, 100+spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC)); break; - case SE_DefensiveProc: + case SpellEffect::DefensiveProc: AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC)); break; - case SE_RangedProc: + case SpellEffect::RangedProc: AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC)); break; - case SE_Charm: - case SE_Rune: - case SE_NegateAttacks: - case SE_Illusion: + case SpellEffect::Charm: + case SpellEffect::Rune: + case SpellEffect::NegateAttacks: + case SpellEffect::Illusion: buffs[j1].spellid = SPELL_UNKNOWN; pet_buffs[j1].spellid = SPELLBOOK_UNKNOWN; pet_buffs[j1].effect_type = 0; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 71b3b20245..145c4f67a7 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -109,7 +109,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove else { if(IsBuffSpell(spell_id)){ - if(IsEffectInSpell(spell_id, SE_BindSight)) + if(IsEffectInSpell(spell_id, SpellEffect::BindSight)) { if(caster) { @@ -219,7 +219,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (!IsDistanceModifierSpell(spell_id)) SetSpellPowerDistanceMod(0); - bool spell_trigger_cast_complete = false; //Used with SE_Spell_Trigger and SE_Chance_Best_in_Spell_Grp, true when spell has been triggered. + bool spell_trigger_cast_complete = false; //Used with SpellEffect::Spell_Trigger and SpellEffect::Chance_Best_in_Spell_Grp, true when spell has been triggered. // if buff slot, use instrument mod there, otherwise calc it uint32 instrument_mod = buffslot > -1 ? buffs[buffslot].instrument_mod : caster ? caster->GetInstrumentMod(spell_id) : 10; @@ -241,7 +241,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove //Prevents effect from being applied if (spellbonuses.NegateEffects) { - if (effect != SE_NegateSpellEffect && NegateSpellEffect(spell_id, effect)) { + if (effect != SpellEffect::NegateSpellEffect && NegateSpellEffect(spell_id, effect)) { if (caster) { caster->Message(Chat::Red, "Part or all of this spell has lost its effectiveness."); //Placeholder msg, until live one is obtained. } @@ -254,12 +254,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #endif switch(effect) { - case SE_CurrentHP: // nukes, heals; also regen/dot if a buff + case SpellEffect::CurrentHP: // nukes, heals; also regen/dot if a buff { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Current Hitpoints: %+i", effect_value); #endif - // SE_CurrentHP is calculated at first tick if its a dot/buff + // SpellEffect::CurrentHP is calculated at first tick if its a dot/buff if (buffslot >= 0) { //This is here so dots with hit counters tic down on initial cast. if (caster && effect_value < 0) { @@ -315,7 +315,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_CurrentHPOnce: // used in buffs usually, see Courage + case SpellEffect::CurrentHPOnce: // used in buffs usually, see Courage { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Current Hitpoints Once: %+i", effect_value); @@ -390,7 +390,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } else if (dmg > 0) { //do not apply focus/critical to buff spells - if (caster && !IsEffectInSpell(spell_id, SE_TotalHP)) { + if (caster && !IsEffectInSpell(spell_id, SpellEffect::TotalHP)) { dmg = caster->GetActSpellHealing(spell_id, dmg, this); } HealDamage(dmg, caster); @@ -399,7 +399,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_PercentalHeal: + case SpellEffect::PercentalHeal: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Percental Heal: %+i (%d%% max)", spell.max_value[i], effect_value); @@ -434,7 +434,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_CompleteHeal: + case SpellEffect::CompleteHeal: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Complete Heal"); @@ -450,7 +450,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_CurrentMana: + case SpellEffect::CurrentMana: { // Bards don't get mana from effects, good or bad. if(GetClass() == Class::Bard) @@ -487,7 +487,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_CurrentManaOnce: + case SpellEffect::CurrentManaOnce: { // Bards don't get mana from effects, good or bad. if(GetClass() == Class::Bard) @@ -499,7 +499,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Translocate: + case SpellEffect::Translocate: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Translocate: %s %d %d %d heading %d", @@ -517,7 +517,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Succor: + case SpellEffect::Succor: { float x, y, z, heading; @@ -575,7 +575,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (IsClient()) { if (HasPet()) { if (RuleB(Spells, EvacClearCharmPet) && GetPet()->IsCharmed()) { - GetPet()->BuffFadeByEffect(SE_Charm); + GetPet()->BuffFadeByEffect(SpellEffect::Charm); } } @@ -598,9 +598,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_GateCastersBindpoint: // Used on Teleport Bind. - case SE_Teleport: // gates, rings, circles, etc - case SE_Teleport2: + case SpellEffect::GateCastersBindpoint: // Used on Teleport Bind. + case SpellEffect::Teleport: // gates, rings, circles, etc + case SpellEffect::Teleport2: { float x, y, z, heading; const char *target_zone = nullptr; @@ -630,7 +630,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } } - if (effect == SE_GateCastersBindpoint && caster && caster->IsClient()) + if (effect == SpellEffect::GateCastersBindpoint && caster && caster->IsClient()) { // Teleport Bind uses caster's bind point int index = spells[spell_id].base_value[i] - 1; if (index < 0 || index > 4) @@ -646,11 +646,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM const char *efstr = "Teleport"; - if(effect == SE_Teleport) + if(effect == SpellEffect::Teleport) efstr = "Teleport v1"; - else if(effect == SE_Teleport2) + else if(effect == SpellEffect::Teleport2) efstr = "Teleport v2"; - else if(effect == SE_Succor) + else if(effect == SpellEffect::Succor) efstr = "Succor"; snprintf(effect_desc, _EDLEN, @@ -672,7 +672,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_FleshToBone: + case SpellEffect::FleshToBone: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Flesh To Bone"); @@ -701,7 +701,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_GroupFearImmunity:{ + case SpellEffect::GroupFearImmunity:{ #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Group Fear Immunity"); #endif @@ -726,7 +726,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_AddFaction: + case SpellEffect::AddFaction: { if (caster && !IsPet() && GetPrimaryFaction() > 0) { caster->AddFactionBonus(GetPrimaryFaction(),effect_value); @@ -734,7 +734,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Stun: + case SpellEffect::Stun: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Stun: %d msec", effect_value); @@ -777,7 +777,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Charm: + case SpellEffect::Charm: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Charm: %+i (up to lvl %d)", effect_value, spell.max_value[i]); @@ -867,9 +867,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } - case SE_SenseDead: - case SE_SenseSummoned: - case SE_SenseAnimals: + case SpellEffect::SenseDead: + case SpellEffect::SenseSummoned: + case SpellEffect::SenseAnimals: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Sense Target: %+i", effect_value); @@ -882,12 +882,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove int MessageID = SENSE_UNDEAD; - if(effect == SE_SenseSummoned) + if(effect == SpellEffect::SenseSummoned) { bt = BodyType::Summoned; MessageID = SENSE_SUMMONED; } - else if(effect == SE_SenseAnimals) + else if(effect == SpellEffect::SenseAnimals) { bt = BodyType::Animal; MessageID = SENSE_ANIMAL; @@ -910,7 +910,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Fear: + case SpellEffect::Fear: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Fear: %+i", effect_value); @@ -939,7 +939,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_BindAffinity: //TO DO: Add support for secondary and tertiary gate abilities + case SpellEffect::BindAffinity: //TO DO: Add support for secondary and tertiary gate abilities { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Bind Affinity"); @@ -1080,7 +1080,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Gate: + case SpellEffect::Gate: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Gate"); @@ -1095,7 +1095,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_CancelMagic: + case SpellEffect::CancelMagic: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Cancel Magic: %d", effect_value); @@ -1111,7 +1111,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_DispelDetrimental: + case SpellEffect::DispelDetrimental: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Dispel Detrimental: %d", effect_value); @@ -1142,7 +1142,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_DispelBeneficial: + case SpellEffect::DispelBeneficial: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Dispel Beneficial: %d", effect_value); @@ -1169,7 +1169,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Purify: + case SpellEffect::Purify: { //Attempt to remove up to base amount of detrimental effects (excluding charm, fear, resurrection, and revival sickness). int purify_count = spells[spell_id].base_value[i]; @@ -1180,8 +1180,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove for(int slot = 0; slot < purify_count; slot++) { if (IsValidSpell(buffs[slot].spellid) && IsDetrimentalSpell(buffs[slot].spellid)){ - if (!IsEffectInSpell(buffs[slot].spellid, SE_Charm) && - !IsEffectInSpell(buffs[slot].spellid, SE_Fear) && + if (!IsEffectInSpell(buffs[slot].spellid, SpellEffect::Charm) && + !IsEffectInSpell(buffs[slot].spellid, SpellEffect::Fear) && buffs[slot].spellid != SPELL_RESURRECTION_SICKNESS && buffs[slot].spellid != SPELL_RESURRECTION_SICKNESS2 && buffs[slot].spellid != SPELL_RESURRECTION_SICKNESS3 && @@ -1195,7 +1195,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Mez: + case SpellEffect::Mez: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Mesmerize"); @@ -1204,7 +1204,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SummonItem: + case SpellEffect::SummonItem: { const EQ::ItemData *item = database.GetItem(spell.base_value[i]); #ifdef SPELL_EFFECT_SPAM @@ -1240,7 +1240,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SummonItemIntoBag: + case SpellEffect::SummonItemIntoBag: { const EQ::ItemData *item = database.GetItem(spell.base_value[i]); if (!item) { @@ -1287,10 +1287,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SummonBSTPet: - case SE_NecPet: - case SE_SummonPet: - case SE_Familiar: + case SpellEffect::SummonBSTPet: + case SpellEffect::NecPet: + case SpellEffect::SummonPet: + case SpellEffect::Familiar: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Summon %s: %s", (effect==SE_Familiar)?"Familiar":"Pet", spell.teleport_zone); @@ -1326,7 +1326,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_DivineAura: + case SpellEffect::DivineAura: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Invulnerability"); @@ -1339,7 +1339,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_ShadowStep: + case SpellEffect::ShadowStep: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Shadow Step: %d", effect_value); @@ -1352,7 +1352,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Blind: + case SpellEffect::Blind: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Blind: %+i", effect_value); @@ -1361,7 +1361,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (IsBeneficialSpell(spell_id) && spells[spell_id].buff_duration == 0) { int buff_count = GetMaxBuffSlots(); for (int slot = 0; slot < buff_count; slot++) { - if (IsValidSpell(buffs[slot].spellid) && IsEffectInSpell(buffs[slot].spellid, SE_Blind)) { + if (IsValidSpell(buffs[slot].spellid) && IsEffectInSpell(buffs[slot].spellid, SpellEffect::Blind)) { if (caster && TryDispel(caster->GetCasterLevel(spell_id), buffs[slot].casterlevel, 1)) { BuffFadeBySlot(slot); slot = buff_count; @@ -1375,7 +1375,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Rune: + case SpellEffect::Rune: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Melee Absorb Rune: %+i", effect_value); @@ -1386,7 +1386,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_AbsorbMagicAtt: + case SpellEffect::AbsorbMagicAtt: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Spell Absorb Rune: %+i", effect_value); @@ -1398,7 +1398,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_MitigateMeleeDamage: + case SpellEffect::MitigateMeleeDamage: { if (buffslot > -1) { buffs[buffslot].melee_rune = spells[spell_id].max_value[i]; @@ -1406,7 +1406,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_MeleeThresholdGuard: + case SpellEffect::MeleeThresholdGuard: { if (buffslot > -1) { buffs[buffslot].melee_rune = spells[spell_id].max_value[i]; @@ -1414,7 +1414,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SpellThresholdGuard: + case SpellEffect::SpellThresholdGuard: { if (buffslot > -1) { buffs[buffslot].magic_rune = spells[spell_id].max_value[i]; @@ -1422,7 +1422,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_MitigateSpellDamage: + case SpellEffect::MitigateSpellDamage: { if (buffslot > -1) { buffs[buffslot].magic_rune = spells[spell_id].max_value[i]; @@ -1430,7 +1430,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_MitigateDotDamage: + case SpellEffect::MitigateDotDamage: { if (buffslot > -1) { buffs[buffslot].dot_rune = spells[spell_id].max_value[i]; @@ -1438,7 +1438,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_DistanceRemoval: + case SpellEffect::DistanceRemoval: { if (buffslot > -1) { buffs[buffslot].caston_x = int(GetX()); @@ -1448,7 +1448,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Levitate: + case SpellEffect::Levitate: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Levitate"); @@ -1464,7 +1464,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_DeathSave: { + case SpellEffect::DeathSave: { int16 mod = 0; @@ -1480,7 +1480,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Illusion: + case SpellEffect::Illusion: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Illusion: race %d", effect_value); @@ -1497,7 +1497,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_IllusionCopy: + case SpellEffect::IllusionCopy: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Illusion Copy"); @@ -1527,13 +1527,13 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_WipeHateList: + case SpellEffect::WipeHateList: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Memory Blur: %d", effect_value); #endif //Memory blur component of Mez spells is not checked again if Mez is recast on a target that is already mezed - if (!CanMemoryBlurFromMez && IsEffectInSpell(spell_id, SE_Mez)) { + if (!CanMemoryBlurFromMez && IsEffectInSpell(spell_id, SpellEffect::Mez)) { break; } @@ -1558,7 +1558,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SpinTarget: + case SpellEffect::SpinTarget: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Spin: %d", effect_value); @@ -1589,7 +1589,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_EyeOfZomm: + case SpellEffect::EyeOfZomm: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Eye of Zomm"); @@ -1607,7 +1607,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_ReclaimPet: + case SpellEffect::ReclaimPet: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Reclaim Pet"); @@ -1642,7 +1642,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_BindSight: + case SpellEffect::BindSight: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Bind Sight"); @@ -1654,7 +1654,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_FeignDeath: + case SpellEffect::FeignDeath: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Feign Death"); @@ -1675,7 +1675,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Sentinel: + case SpellEffect::Sentinel: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Sentinel"); @@ -1696,7 +1696,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_LocateCorpse: + case SpellEffect::LocateCorpse: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Locate Corpse"); @@ -1709,8 +1709,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SummonToCorpse: - case SE_Revive: + case SpellEffect::SummonToCorpse: + case SpellEffect::Revive: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Revive"); // heh the corpse won't see this @@ -1726,8 +1726,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_ModelSize: - case SE_ChangeHeight: + case SpellEffect::ModelSize: + case SpellEffect::ChangeHeight: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Model Size: %d%%", effect_value); @@ -1745,14 +1745,14 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } } //Only applies to SPA 89, max value also likely does something, but unknown. - else if (effect == SE_ModelSize && spells[spell_id].limit_value[i]) { + else if (effect == SpellEffect::ModelSize && spells[spell_id].limit_value[i]) { ChangeSize(spells[spell_id].limit_value[i]); } break; } - case SE_Root: + case SpellEffect::Root: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Root: %+i", effect_value); @@ -1768,7 +1768,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SummonHorse: + case SpellEffect::SummonHorse: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Summon Mount: %s", spell.teleport_zone); @@ -1787,7 +1787,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SummonCorpse: + case SpellEffect::SummonCorpse: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Summon Corpse: %d", effect_value); @@ -1857,13 +1857,13 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } else { MessageString(Chat::LightBlue, TARGET_NOT_FOUND); - LogError("[{}] attempted to cast spell id [{}] with spell effect SE_SummonCorpse, but could not cast target into a Client object", GetCleanName(), spell_id); + LogError("[{}] attempted to cast spell id [{}] with spell effect SpellEffect::SummonCorpse, but could not cast target into a Client object", GetCleanName(), spell_id); } } break; } - case SE_SummonCorpseZone: + case SpellEffect::SummonCorpseZone: { if (IsClient()) { Client* client_target = CastToClient(); @@ -1910,13 +1910,13 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } } else { MessageString(Chat::Spells, TARGET_NOT_FOUND); - LogError("[{}] attempted to cast spell id [{}] with spell effect SE_SummonCorpseZone, but could not cast target into a Client object", GetCleanName(), spell_id); + LogError("[{}] attempted to cast spell id [{}] with spell effect SpellEffect::SummonCorpseZone, but could not cast target into a Client object", GetCleanName(), spell_id); } } break; } - case SE_AddMeleeProc: - case SE_WeaponProc: + case SpellEffect::AddMeleeProc: + case SpellEffect::WeaponProc: { uint16 proc_id = GetProcID(spell_id, i); #ifdef SPELL_EFFECT_SPAM @@ -1931,7 +1931,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_RangedProc: + case SpellEffect::RangedProc: { uint16 procid = GetProcID(spell_id, i); #ifdef SPELL_EFFECT_SPAM @@ -1941,7 +1941,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_DefensiveProc: + case SpellEffect::DefensiveProc: { uint16 procid = GetProcID(spell_id, i); #ifdef SPELL_EFFECT_SPAM @@ -1951,7 +1951,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_NegateAttacks: + case SpellEffect::NegateAttacks: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Melee Negate Attack Rune: %+i", effect_value); @@ -1960,7 +1960,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove buffs[buffslot].hit_number = effect_value; break; } - case SE_AppraiseLDonChest: + case SpellEffect::AppraiseLDonChest: { if(IsNPC()) { @@ -1984,7 +1984,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_DisarmLDoNTrap: + case SpellEffect::DisarmLDoNTrap: { if(IsNPC()) { @@ -2008,7 +2008,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_UnlockLDoNChest: + case SpellEffect::UnlockLDoNChest: { if(IsNPC()) { @@ -2032,7 +2032,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Lull: + case SpellEffect::Lull: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Lull"); @@ -2041,7 +2041,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_PoisonCounter: + case SpellEffect::PoisonCounter: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Poison Counter: %+i", effect_value); @@ -2074,7 +2074,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_DiseaseCounter: + case SpellEffect::DiseaseCounter: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Disease Counter: %+i", effect_value); @@ -2110,7 +2110,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_CurseCounter: + case SpellEffect::CurseCounter: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Curse Counter: %+i", effect_value); @@ -2146,7 +2146,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_CorruptionCounter: + case SpellEffect::CorruptionCounter: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Corruption Counter: %+i", effect_value); @@ -2179,7 +2179,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Destroy: + case SpellEffect::Destroy: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Destroy"); @@ -2193,7 +2193,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_TossUp: + case SpellEffect::TossUp: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Toss Up: %d", effect_value); @@ -2204,7 +2204,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_StopRain: + case SpellEffect::StopRain: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Stop Rain"); @@ -2215,7 +2215,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Sacrifice: + case SpellEffect::Sacrifice: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Sacrifice"); @@ -2227,7 +2227,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SummonPC: + case SpellEffect::SummonPC: { if (!caster) { break; @@ -2262,7 +2262,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Silence: + case SpellEffect::Silence: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Silence"); @@ -2271,7 +2271,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Amnesia: + case SpellEffect::Amnesia: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Amnesia"); @@ -2280,7 +2280,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_CallPet: + case SpellEffect::CallPet: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Call Pet"); @@ -2296,15 +2296,15 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_StackingCommand_Block: - case SE_StackingCommand_Overwrite: + case SpellEffect::StackingCommand_Block: + case SpellEffect::StackingCommand_Overwrite: { // these are special effects used by the buff stuff break; } - case SE_TemporaryPets: //Dook- swarms and wards: + case SpellEffect::TemporaryPets: //Dook- swarms and wards: { if (!caster) break; @@ -2320,7 +2320,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_FadingMemories: //Dook- escape etc + case SpellEffect::FadingMemories: //Dook- escape etc { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Fading Memories"); @@ -2373,7 +2373,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Rampage: + case SpellEffect::Rampage: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Rampage"); @@ -2391,7 +2391,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_AEMelee: + case SpellEffect::AEMelee: { //old aa @@ -2402,7 +2402,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_AETaunt: + case SpellEffect::AETaunt: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "AE Taunt"); @@ -2418,7 +2418,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SkillAttack: + case SpellEffect::SkillAttack: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Skill Attack"); @@ -2450,7 +2450,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_WakeTheDead: + case SpellEffect::WakeTheDead: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Wake The Dead"); @@ -2470,7 +2470,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_ArmyOfTheDead: + case SpellEffect::ArmyOfTheDead: { if (caster && caster->IsClient()) { int dur = spells[spell_id].max_value[i]; @@ -2491,7 +2491,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Doppelganger: + case SpellEffect::Doppelganger: { if(caster && caster->IsClient()) { char pet_name[64]; @@ -2503,12 +2503,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_BardAEDot: + case SpellEffect::BardAEDot: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Bard AE Dot: %+i", effect_value); #endif - // SE_CurrentHP is calculated at first tick if its a dot/buff + // SpellEffect::CurrentHP is calculated at first tick if its a dot/buff if (buffslot >= 0) break; //This effect does no damage if target is moving. @@ -2541,7 +2541,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_CurrentEndurance: { + case SpellEffect::CurrentEndurance: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Current Endurance: %+i", effect_value); #endif @@ -2554,7 +2554,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_CurrentEnduranceOnce: + case SpellEffect::CurrentEnduranceOnce: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Current Endurance Once: %+i", effect_value); @@ -2569,7 +2569,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_BalanceHP: { + case SpellEffect::BalanceHP: { if(!caster) break; @@ -2597,7 +2597,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_BalanceMana: { + case SpellEffect::BalanceMana: { if(!caster) break; @@ -2625,7 +2625,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SummonAndResAllCorpses: + case SpellEffect::SummonAndResAllCorpses: { if(IsClient()) CastToClient()->SummonAndRezzAllCorpses(); @@ -2633,14 +2633,14 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_GateToHomeCity: + case SpellEffect::GateToHomeCity: { if(IsClient()) CastToClient()->GoToBind(4); break; } - case SE_SuspendPet: + case SpellEffect::SuspendPet: { if(IsClient()) CastToClient()->SuspendMinion(spell.base_value[i]); @@ -2648,7 +2648,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_FcTimerRefresh: + case SpellEffect::FcTimerRefresh: { if(IsClient()) { for (unsigned int i = 0; i < EQ::spells::SPELL_GEM_COUNT; ++i) { @@ -2667,7 +2667,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_FcTimerLockout: { + case SpellEffect::FcTimerLockout: { if (IsClient()) { for (unsigned int mem_spell : CastToClient()->m_pp.mem_spells) { if (IsValidSpell(mem_spell)) { @@ -2696,7 +2696,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_HealGroupFromMana: { + case SpellEffect::HealGroupFromMana: { if(!caster) break; @@ -2740,7 +2740,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_ManaDrainWithDmg: + case SpellEffect::ManaDrainWithDmg: { int mana_damage = 0; int32 mana_to_use = GetMana() - spell.base_value[i]; @@ -2759,7 +2759,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_EndDrainWithDmg: + case SpellEffect::EndDrainWithDmg: { if(IsClient()) { int end_damage = 0; @@ -2780,16 +2780,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SetBodyType: + case SpellEffect::SetBodyType: { SetBodyType(spell.base_value[i], false); break; } - case SE_Leap: + case SpellEffect::Leap: { // These effects remove lev and only work a certain distance away. - BuffFadeByEffect(SE_Levitate); + BuffFadeByEffect(SpellEffect::Levitate); if (caster && caster->GetTarget()) { float my_x = caster->GetX(); float my_y = caster->GetY(); @@ -2825,7 +2825,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } break; } - case SE_VoiceGraft: + case SpellEffect::VoiceGraft: { if(caster && caster->GetPet()) caster->spellbonuses.VoiceGraft = caster->GetPetID(); @@ -2833,7 +2833,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_ManaBurn: + case SpellEffect::ManaBurn: { int32 max_mana = spell.base_value[i]; int ratio = spell.limit_value[i]; @@ -2862,7 +2862,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Taunt: + case SpellEffect::Taunt: { if (caster && IsNPC()){ caster->Taunt(CastToNPC(), false, spell.base_value[i], true, spell.limit_value[i]); @@ -2870,26 +2870,26 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_AttackSpeed: + case SpellEffect::AttackSpeed: if (spell.base_value[i] < 100) SlowMitigation(caster); break; - case SE_AttackSpeed2: + case SpellEffect::AttackSpeed2: if (spell.base_value[i] < 100) SlowMitigation(caster); break; - case SE_AttackSpeed3: + case SpellEffect::AttackSpeed3: if (spell.base_value[i] < 0) SlowMitigation(caster); break; - case SE_AttackSpeed4: + case SpellEffect::AttackSpeed4: SlowMitigation(caster); break; - case SE_AddHatePct: + case SpellEffect::AddHatePct: { if (IsNPC()){ int64 new_hate = CastToNPC()->GetHateAmount(caster) * (100 + spell.base_value[i]) / 100; @@ -2901,7 +2901,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Hate:{ + case SpellEffect::Hate:{ if (buffslot >= 0) break; @@ -2925,7 +2925,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_InterruptCasting:{ + case SpellEffect::InterruptCasting:{ if (buffslot >= 0) break; @@ -2935,20 +2935,20 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_MassGroupBuff:{ + case SpellEffect::MassGroupBuff:{ SetMGB(true); MessageString(Chat::Disciplines, MGB_STRING); break; } - case SE_IllusionOther: { + case SpellEffect::IllusionOther: { SetProjectIllusion(true); Message(Chat::NPCQuestSay, "The power of your next illusion spell will flow to your grouped target in your place."); break; } - case SE_ApplyEffect: { + case SpellEffect::ApplyEffect: { if (caster && IsValidSpell(spells[spell_id].limit_value[i])){ if(zone->random.Roll(spells[spell_id].base_value[i])) @@ -2957,7 +2957,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_SpellTrigger: { + case SpellEffect::SpellTrigger: { if (!spell_trigger_cast_complete) { if (caster && caster->TrySpellTrigger(this, spell_id, i)) @@ -2967,7 +2967,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } - case SE_Instant_Mana_Pct: { + case SpellEffect::Instant_Mana_Pct: { effect_value = spells[spell_id].base_value[i]; int64 amt = std::abs(GetMaxMana() * effect_value / 10000); if (spells[spell_id].max_value[i] && amt > spells[spell_id].max_value[i]) @@ -2982,7 +2982,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Instant_Endurance_Pct: { + case SpellEffect::Instant_Endurance_Pct: { effect_value = spells[spell_id].base_value[i]; if (IsClient()) { int32 amt = std::abs(CastToClient()->GetMaxEndurance() * effect_value / 10000); @@ -3002,7 +3002,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove Calc for base1 is found in ApplyHealthTransferDamage() due to needing to account for AOE functionality since effect can potentially kill caster. */ - case SE_Health_Transfer: { + case SpellEffect::Health_Transfer: { if (caster) { effect_value = spells[spell_id].limit_value[i]; int64 amt = std::abs(caster->GetMaxHP() * effect_value / 1000); @@ -3017,7 +3017,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Chance_Best_in_Spell_Grp: { + case SpellEffect::Chance_Best_in_Spell_Grp: { if (!spell_trigger_cast_complete) { if (caster && caster->TrySpellTrigger(this, spell_id, i)) spell_trigger_cast_complete = true; @@ -3025,7 +3025,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Trigger_Best_in_Spell_Grp: { + case SpellEffect::Trigger_Best_in_Spell_Grp: { if (caster && !caster->IsClient()) break; @@ -3039,7 +3039,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Trigger_Spell_Non_Item: { + case SpellEffect::Trigger_Spell_Non_Item: { //Only trigger if not from item if (caster && caster->IsClient() && GetCastedSpellInvSlot() > 0) break; @@ -3050,19 +3050,19 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Hatelist_To_Tail_Index: { + case SpellEffect::Hatelist_To_Tail_Index: { if (caster && zone->random.Roll(spells[spell_id].base_value[i])) caster->SetBottomRampageList(); break; } - case SE_Hatelist_To_Top_Index: { + case SpellEffect::Hatelist_To_Top_Index: { if (caster && zone->random.Roll(spells[spell_id].base_value[i])) caster->SetTopRampageList(); break; } - case SE_Fearstun: { + case SpellEffect::Fearstun: { //Normal 'stun' restrictions do not apply. base1=duration, base2=PC duration, max =lv restrict if (!caster) break; @@ -3095,7 +3095,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_PetShield: { + case SpellEffect::PetShield: { if (IsPet()) { Mob* petowner = GetOwner(); if (petowner) { @@ -3108,316 +3108,316 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Weapon_Stance: { + case SpellEffect::Weapon_Stance: { if (IsClient()) { CastToClient()->ApplyWeaponsStance(); } break; } - case SE_HealOverTime: { + case SpellEffect::HealOverTime: { //This is here so buffs with hit counters tic down on initial cast. caster->GetActSpellHealing(spell_id, effect_value, nullptr, false); break; } - case SE_PersistentEffect: + case SpellEffect::PersistentEffect: MakeAura(spell_id); break; // Handled Elsewhere - case SE_ImmuneFleeing: - case SE_NegateSpellEffect: - case SE_Knockdown: // handled by client - case SE_ShadowStepDirectional: // handled by client - case SE_SpellOnDeath: - case SE_BlockNextSpellFocus: - case SE_ReduceReuseTimer: - case SE_SwarmPetDuration: - case SE_LimitHPPercent: - case SE_LimitManaPercent: - case SE_LimitEndPercent: - case SE_ExtraAttackChance: - case SE_ProcChance: - case SE_StunResist: - case SE_MinDamageModifier: - case SE_DamageModifier: - case SE_DamageModifier2: - case SE_HitChance: - case SE_MeleeSkillCheck: - case SE_HundredHands: - case SE_ResistFearChance: - case SE_ResistSpellChance: - case SE_AllInstrumentMod: - case SE_MeleeLifetap: - case SE_DoubleAttackChance: - case SE_TripleAttackChance: - case SE_DualWieldChance: - case SE_ParryChance: - case SE_DodgeChance: - case SE_RiposteChance: - case SE_AvoidMeleeChance: - case SE_CrippBlowChance: - case SE_CriticalHitChance: - case SE_MeleeMitigation: - case SE_Reflect: - case SE_Screech: - case SE_Amplification: - case SE_MagicWeapon: - case SE_Hunger: - case SE_MagnifyVision: - case SE_Lycanthropy: - case SE_NegateIfCombat: - case SE_CastingLevel: - case SE_CastingLevel2: - case SE_RaiseStatCap: - case SE_ResistAll: - case SE_ResistMagic: - case SE_ResistDisease: - case SE_ResistPoison: - case SE_ResistCold: - case SE_ResistFire: - case SE_AllStats: - case SE_MakeDrunk: - case SE_CHA: - case SE_WIS: - case SE_INT: - case SE_STA: - case SE_AGI: - case SE_DEX: - case SE_STR: - case SE_ATK: - case SE_ArmorClass: - case SE_EndurancePool: - case SE_Stamina: - case SE_UltraVision: - case SE_InfraVision: - case SE_ManaPool: - case SE_TotalHP: - case SE_ChangeFrenzyRad: - case SE_Harmony: - case SE_ChangeAggro: - case SE_Identify: - case SE_InstantHate: - case SE_ReduceHate: - case SE_SpellDamageShield: - case SE_ReverseDS: - case SE_DamageShield: - case SE_TrueNorth: - case SE_WaterBreathing: - case SE_MovementSpeed: - case SE_PercentXPIncrease: - case SE_DivineSave: - case SE_Accuracy: - case SE_Flurry: - case SE_ImprovedDamage: - case SE_ImprovedDamage2: - case SE_ImprovedHeal: - case SE_IncreaseSpellHaste: - case SE_IncreaseSpellDuration: - case SE_IncreaseRange: - case SE_SpellHateMod: - case SE_ReduceReagentCost: - case SE_ReduceManaCost: - case SE_LimitMaxLevel: - case SE_LimitResist: - case SE_LimitTarget: - case SE_LimitEffect: - case SE_LimitSpellType: - case SE_LimitSpell: - case SE_LimitMinDur: - case SE_LimitInstant: - case SE_LimitMinLevel: - case SE_LimitCastTimeMin: - case SE_LimitManaMin: - case SE_LimitCombatSkills: - case SE_SpellDurationIncByTic: - case SE_TriggerOnCast: - case SE_HealRate: - case SE_SkillDamageTaken: - case SE_FcSpellVulnerability: - case SE_Fc_Spell_Damage_Pct_IncomingPC: - case SE_Fc_Spell_Damage_Amt_IncomingPC: - case SE_FcTwincast: - case SE_DelayDeath: - case SE_CastOnFadeEffect: - case SE_CastOnFadeEffectNPC: - case SE_CastOnFadeEffectAlways: - case SE_CastOnRuneFadeEffect: - case SE_MaxHPChange: - case SE_SympatheticProc: - case SE_FcDamageAmt: - case SE_FcDamageAmt2: - case SE_CriticalSpellChance: - case SE_SpellCritChance: - case SE_SpellCritDmgIncrease: - case SE_DotCritDmgIncrease: - case SE_CriticalHealChance: - case SE_CriticalHealOverTime: - case SE_CriticalDoTChance: - case SE_ProcOnKillShot: - case SE_ProcOnSpellKillShot: - case SE_CriticalDamageMob: - case SE_LimitSpellGroup: - case SE_ResistCorruption: - case SE_ReduceSkillTimer: - case SE_HPToMana: - case SE_ManaAbsorbPercentDamage: - case SE_SkillDamageAmount: - case SE_SkillDamageAmount2: - case SE_GravityEffect: - case SE_IncreaseBlockChance: - case SE_AntiGate: - case SE_Fearless: - case SE_FcDamageAmtCrit: - case SE_FcHealAmtCrit: - case SE_CastOnCurer: - case SE_CastOnCure: - case SE_CastonNumHitFade: - case SE_LimitToSkill: - case SE_SpellProcChance: - case SE_CharmBreakChance: - case SE_BardSongRange: - case SE_ACv2: - case SE_ManaRegen_v2: - case SE_FcDamagePctCrit: - case SE_FcHealAmt: - case SE_FcHealPctIncoming: - case SE_CriticalHealDecay: - case SE_CriticalRegenDecay: - case SE_FcDamageAmtIncoming: - case SE_LimitCastingSkill: - case SE_MitigateDamageShield: - case SE_FcBaseEffects: - case SE_LimitClass: - case SE_BlockBehind: - case SE_ShieldBlock: - case SE_PetCriticalHit: - case SE_SlayUndead: - case SE_GiveDoubleAttack: - case SE_StrikeThrough: - case SE_StrikeThrough2: - case SE_SecondaryDmgInc: - case SE_ArcheryDamageModifier: - case SE_ConsumeProjectile: - case SE_ForageAdditionalItems: - case SE_Salvage: - case SE_FrontalBackstabChance: - case SE_FrontalBackstabMinDmg: - case SE_TripleBackstab: - case SE_DoubleSpecialAttack: - case SE_IncreaseRunSpeedCap: - case SE_BaseMovementSpeed: - case SE_FrontalStunResist: - case SE_ImprovedBindWound: - case SE_MaxBindWound: - case SE_CombatStability: - case SE_AddSingingMod: - case SE_SongModCap: - case SE_HeadShot: - case SE_HeadShotLevel: - case SE_PetAvoidance: - case SE_GiveDoubleRiposte: - case SE_Ambidexterity: - case SE_PetMaxHP: - case SE_PetFlurry: - case SE_MasteryofPast: - case SE_GivePetGroupTarget: - case SE_RootBreakChance: - case SE_UnfailingDivinity: - case SE_ChannelChanceSpells: - case SE_ChannelChanceItems: - case SE_FcHealPctCritIncoming: - case SE_FcIncreaseNumHits: - case SE_CastonFocusEffect: - case SE_FcHealAmtIncoming: - case SE_LimitManaMax: - case SE_DoubleRangedAttack: - case SE_ShieldEquipDmgMod: - case SE_TriggerOnReqTarget: - case SE_LimitRace: - case SE_FcLimitUse: - case SE_FcMute: - case SE_LimitUseType: - case SE_FcStunTimeMod: - case SE_StunBashChance: - case SE_IncreaseChanceMemwipe: - case SE_CriticalMend: - case SE_LimitCastTimeMax: - case SE_TriggerOnReqCaster: - case SE_FrenziedDevastation: - case SE_AStacker: - case SE_BStacker: - case SE_CStacker: - case SE_DStacker: - case SE_DoubleRiposte: - case SE_Berserk: - case SE_Vampirism: - case SE_Metabolism: - case SE_FinishingBlow: - case SE_FinishingBlowLvl: - case SE_Assassinate: - case SE_AssassinateLevel: - case SE_FactionModPct: - case SE_LimitSpellClass: - case SE_Sanctuary: - case SE_PetMeleeMitigation: - case SE_SkillProcAttempt: - case SE_SkillProcSuccess: - case SE_SpellResistReduction: - case SE_IncreaseArchery: - case SE_Duration_HP_Pct: - case SE_Duration_Mana_Pct: - case SE_Duration_Endurance_Pct: - case SE_Endurance_Absorb_Pct_Damage: - case SE_AC_Mitigation_Max_Percent: - case SE_AC_Avoidance_Max_Percent: - case SE_Attack_Accuracy_Max_Percent: - case SE_Critical_Melee_Damage_Mod_Max: - case SE_Melee_Damage_Position_Mod: - case SE_Damage_Taken_Position_Mod: - case SE_Melee_Damage_Position_Amt: - case SE_Damage_Taken_Position_Amt: - case SE_DS_Mitigation_Amount: - case SE_DS_Mitigation_Percentage: - case SE_Double_Backstab_Front: - case SE_Pet_Crit_Melee_Damage_Pct_Owner: - case SE_Pet_Add_Atk: - case SE_TwinCastBlocker: - case SE_Fc_Cast_Spell_On_Land: - case SE_Ff_CasterClass: - case SE_Ff_Same_Caster: - case SE_Fc_ResistIncoming: - case SE_Fc_Amplify_Amt: - case SE_Fc_Amplify_Mod: - case SE_Fc_CastTimeAmt: - case SE_Fc_CastTimeMod2: - case SE_Ff_DurationMax: - case SE_Ff_Endurance_Max: - case SE_Ff_Endurance_Min: - case SE_Ff_ReuseTimeMin: - case SE_Ff_ReuseTimeMax: - case SE_Ff_Value_Min: - case SE_Ff_Value_Max: - case SE_AddExtraAttackPct_1h_Primary: - case SE_AddExtraAttackPct_1h_Secondary: - case SE_Double_Melee_Round: - case SE_Skill_Base_Damage_Mod: - case SE_Worn_Endurance_Regen_Cap: - case SE_Buy_AA_Rank: - case SE_Ff_FocusTimerMin: - case SE_Proc_Timer_Modifier: - case SE_FFItemClass: - case SE_SpellEffectResistChance: - case SE_SeeInvis: - case SE_Invisibility: - case SE_Invisibility2: - case SE_InvisVsAnimals: - case SE_ImprovedInvisAnimals: - case SE_InvisVsUndead: - case SE_InvisVsUndead2: - case SE_Shield_Target: - case SE_ReduceSkill: + case SpellEffect::ImmuneFleeing: + case SpellEffect::NegateSpellEffect: + case SpellEffect::Knockdown: // handled by client + case SpellEffect::ShadowStepDirectional: // handled by client + case SpellEffect::SpellOnDeath: + case SpellEffect::BlockNextSpellFocus: + case SpellEffect::ReduceReuseTimer: + case SpellEffect::SwarmPetDuration: + case SpellEffect::LimitHPPercent: + case SpellEffect::LimitManaPercent: + case SpellEffect::LimitEndPercent: + case SpellEffect::ExtraAttackChance: + case SpellEffect::ProcChance: + case SpellEffect::StunResist: + case SpellEffect::MinDamageModifier: + case SpellEffect::DamageModifier: + case SpellEffect::DamageModifier2: + case SpellEffect::HitChance: + case SpellEffect::MeleeSkillCheck: + case SpellEffect::HundredHands: + case SpellEffect::ResistFearChance: + case SpellEffect::ResistSpellChance: + case SpellEffect::AllInstrumentMod: + case SpellEffect::MeleeLifetap: + case SpellEffect::DoubleAttackChance: + case SpellEffect::TripleAttackChance: + case SpellEffect::DualWieldChance: + case SpellEffect::ParryChance: + case SpellEffect::DodgeChance: + case SpellEffect::RiposteChance: + case SpellEffect::AvoidMeleeChance: + case SpellEffect::CrippBlowChance: + case SpellEffect::CriticalHitChance: + case SpellEffect::MeleeMitigation: + case SpellEffect::Reflect: + case SpellEffect::Screech: + case SpellEffect::Amplification: + case SpellEffect::MagicWeapon: + case SpellEffect::Hunger: + case SpellEffect::MagnifyVision: + case SpellEffect::Lycanthropy: + case SpellEffect::NegateIfCombat: + case SpellEffect::CastingLevel: + case SpellEffect::CastingLevel2: + case SpellEffect::RaiseStatCap: + case SpellEffect::ResistAll: + case SpellEffect::ResistMagic: + case SpellEffect::ResistDisease: + case SpellEffect::ResistPoison: + case SpellEffect::ResistCold: + case SpellEffect::ResistFire: + case SpellEffect::AllStats: + case SpellEffect::MakeDrunk: + case SpellEffect::CHA: + case SpellEffect::WIS: + case SpellEffect::INT: + case SpellEffect::STA: + case SpellEffect::AGI: + case SpellEffect::DEX: + case SpellEffect::STR: + case SpellEffect::ATK: + case SpellEffect::ArmorClass: + case SpellEffect::EndurancePool: + case SpellEffect::Stamina: + case SpellEffect::UltraVision: + case SpellEffect::InfraVision: + case SpellEffect::ManaPool: + case SpellEffect::TotalHP: + case SpellEffect::ChangeFrenzyRad: + case SpellEffect::Harmony: + case SpellEffect::ChangeAggro: + case SpellEffect::Identify: + case SpellEffect::InstantHate: + case SpellEffect::ReduceHate: + case SpellEffect::SpellDamageShield: + case SpellEffect::ReverseDS: + case SpellEffect::DamageShield: + case SpellEffect::TrueNorth: + case SpellEffect::WaterBreathing: + case SpellEffect::MovementSpeed: + case SpellEffect::PercentXPIncrease: + case SpellEffect::DivineSave: + case SpellEffect::Accuracy: + case SpellEffect::Flurry: + case SpellEffect::ImprovedDamage: + case SpellEffect::ImprovedDamage2: + case SpellEffect::ImprovedHeal: + case SpellEffect::IncreaseSpellHaste: + case SpellEffect::IncreaseSpellDuration: + case SpellEffect::IncreaseRange: + case SpellEffect::SpellHateMod: + case SpellEffect::ReduceReagentCost: + case SpellEffect::ReduceManaCost: + case SpellEffect::LimitMaxLevel: + case SpellEffect::LimitResist: + case SpellEffect::LimitTarget: + case SpellEffect::LimitEffect: + case SpellEffect::LimitSpellType: + case SpellEffect::LimitSpell: + case SpellEffect::LimitMinDur: + case SpellEffect::LimitInstant: + case SpellEffect::LimitMinLevel: + case SpellEffect::LimitCastTimeMin: + case SpellEffect::LimitManaMin: + case SpellEffect::LimitCombatSkills: + case SpellEffect::SpellDurationIncByTic: + case SpellEffect::TriggerOnCast: + case SpellEffect::HealRate: + case SpellEffect::SkillDamageTaken: + case SpellEffect::FcSpellVulnerability: + case SpellEffect::Fc_Spell_Damage_Pct_IncomingPC: + case SpellEffect::Fc_Spell_Damage_Amt_IncomingPC: + case SpellEffect::FcTwincast: + case SpellEffect::DelayDeath: + case SpellEffect::CastOnFadeEffect: + case SpellEffect::CastOnFadeEffectNPC: + case SpellEffect::CastOnFadeEffectAlways: + case SpellEffect::CastOnRuneFadeEffect: + case SpellEffect::MaxHPChange: + case SpellEffect::SympatheticProc: + case SpellEffect::FcDamageAmt: + case SpellEffect::FcDamageAmt2: + case SpellEffect::CriticalSpellChance: + case SpellEffect::SpellCritChance: + case SpellEffect::SpellCritDmgIncrease: + case SpellEffect::DotCritDmgIncrease: + case SpellEffect::CriticalHealChance: + case SpellEffect::CriticalHealOverTime: + case SpellEffect::CriticalDoTChance: + case SpellEffect::ProcOnKillShot: + case SpellEffect::ProcOnSpellKillShot: + case SpellEffect::CriticalDamageMob: + case SpellEffect::LimitSpellGroup: + case SpellEffect::ResistCorruption: + case SpellEffect::ReduceSkillTimer: + case SpellEffect::HPToMana: + case SpellEffect::ManaAbsorbPercentDamage: + case SpellEffect::SkillDamageAmount: + case SpellEffect::SkillDamageAmount2: + case SpellEffect::GravityEffect: + case SpellEffect::IncreaseBlockChance: + case SpellEffect::AntiGate: + case SpellEffect::Fearless: + case SpellEffect::FcDamageAmtCrit: + case SpellEffect::FcHealAmtCrit: + case SpellEffect::CastOnCurer: + case SpellEffect::CastOnCure: + case SpellEffect::CastonNumHitFade: + case SpellEffect::LimitToSkill: + case SpellEffect::SpellProcChance: + case SpellEffect::CharmBreakChance: + case SpellEffect::BardSongRange: + case SpellEffect::ACv2: + case SpellEffect::ManaRegen_v2: + case SpellEffect::FcDamagePctCrit: + case SpellEffect::FcHealAmt: + case SpellEffect::FcHealPctIncoming: + case SpellEffect::CriticalHealDecay: + case SpellEffect::CriticalRegenDecay: + case SpellEffect::FcDamageAmtIncoming: + case SpellEffect::LimitCastingSkill: + case SpellEffect::MitigateDamageShield: + case SpellEffect::FcBaseEffects: + case SpellEffect::LimitClass: + case SpellEffect::BlockBehind: + case SpellEffect::ShieldBlock: + case SpellEffect::PetCriticalHit: + case SpellEffect::SlayUndead: + case SpellEffect::GiveDoubleAttack: + case SpellEffect::StrikeThrough: + case SpellEffect::StrikeThrough2: + case SpellEffect::SecondaryDmgInc: + case SpellEffect::ArcheryDamageModifier: + case SpellEffect::ConsumeProjectile: + case SpellEffect::ForageAdditionalItems: + case SpellEffect::Salvage: + case SpellEffect::FrontalBackstabChance: + case SpellEffect::FrontalBackstabMinDmg: + case SpellEffect::TripleBackstab: + case SpellEffect::DoubleSpecialAttack: + case SpellEffect::IncreaseRunSpeedCap: + case SpellEffect::BaseMovementSpeed: + case SpellEffect::FrontalStunResist: + case SpellEffect::ImprovedBindWound: + case SpellEffect::MaxBindWound: + case SpellEffect::CombatStability: + case SpellEffect::AddSingingMod: + case SpellEffect::SongModCap: + case SpellEffect::HeadShot: + case SpellEffect::HeadShotLevel: + case SpellEffect::PetAvoidance: + case SpellEffect::GiveDoubleRiposte: + case SpellEffect::Ambidexterity: + case SpellEffect::PetMaxHP: + case SpellEffect::PetFlurry: + case SpellEffect::MasteryofPast: + case SpellEffect::GivePetGroupTarget: + case SpellEffect::RootBreakChance: + case SpellEffect::UnfailingDivinity: + case SpellEffect::ChannelChanceSpells: + case SpellEffect::ChannelChanceItems: + case SpellEffect::FcHealPctCritIncoming: + case SpellEffect::FcIncreaseNumHits: + case SpellEffect::CastonFocusEffect: + case SpellEffect::FcHealAmtIncoming: + case SpellEffect::LimitManaMax: + case SpellEffect::DoubleRangedAttack: + case SpellEffect::ShieldEquipDmgMod: + case SpellEffect::TriggerOnReqTarget: + case SpellEffect::LimitRace: + case SpellEffect::FcLimitUse: + case SpellEffect::FcMute: + case SpellEffect::LimitUseType: + case SpellEffect::FcStunTimeMod: + case SpellEffect::StunBashChance: + case SpellEffect::IncreaseChanceMemwipe: + case SpellEffect::CriticalMend: + case SpellEffect::LimitCastTimeMax: + case SpellEffect::TriggerOnReqCaster: + case SpellEffect::FrenziedDevastation: + case SpellEffect::AStacker: + case SpellEffect::BStacker: + case SpellEffect::CStacker: + case SpellEffect::DStacker: + case SpellEffect::DoubleRiposte: + case SpellEffect::Berserk: + case SpellEffect::Vampirism: + case SpellEffect::Metabolism: + case SpellEffect::FinishingBlow: + case SpellEffect::FinishingBlowLvl: + case SpellEffect::Assassinate: + case SpellEffect::AssassinateLevel: + case SpellEffect::FactionModPct: + case SpellEffect::LimitSpellClass: + case SpellEffect::Sanctuary: + case SpellEffect::PetMeleeMitigation: + case SpellEffect::SkillProcAttempt: + case SpellEffect::SkillProcSuccess: + case SpellEffect::SpellResistReduction: + case SpellEffect::IncreaseArchery: + case SpellEffect::Duration_HP_Pct: + case SpellEffect::Duration_Mana_Pct: + case SpellEffect::Duration_Endurance_Pct: + case SpellEffect::Endurance_Absorb_Pct_Damage: + case SpellEffect::AC_Mitigation_Max_Percent: + case SpellEffect::AC_Avoidance_Max_Percent: + case SpellEffect::Attack_Accuracy_Max_Percent: + case SpellEffect::Critical_Melee_Damage_Mod_Max: + case SpellEffect::Melee_Damage_Position_Mod: + case SpellEffect::Damage_Taken_Position_Mod: + case SpellEffect::Melee_Damage_Position_Amt: + case SpellEffect::Damage_Taken_Position_Amt: + case SpellEffect::DS_Mitigation_Amount: + case SpellEffect::DS_Mitigation_Percentage: + case SpellEffect::Double_Backstab_Front: + case SpellEffect::Pet_Crit_Melee_Damage_Pct_Owner: + case SpellEffect::Pet_Add_Atk: + case SpellEffect::TwinCastBlocker: + case SpellEffect::Fc_Cast_Spell_On_Land: + case SpellEffect::Ff_CasterClass: + case SpellEffect::Ff_Same_Caster: + case SpellEffect::Fc_ResistIncoming: + case SpellEffect::Fc_Amplify_Amt: + case SpellEffect::Fc_Amplify_Mod: + case SpellEffect::Fc_CastTimeAmt: + case SpellEffect::Fc_CastTimeMod2: + case SpellEffect::Ff_DurationMax: + case SpellEffect::Ff_Endurance_Max: + case SpellEffect::Ff_Endurance_Min: + case SpellEffect::Ff_ReuseTimeMin: + case SpellEffect::Ff_ReuseTimeMax: + case SpellEffect::Ff_Value_Min: + case SpellEffect::Ff_Value_Max: + case SpellEffect::AddExtraAttackPct_1h_Primary: + case SpellEffect::AddExtraAttackPct_1h_Secondary: + case SpellEffect::Double_Melee_Round: + case SpellEffect::Skill_Base_Damage_Mod: + case SpellEffect::Worn_Endurance_Regen_Cap: + case SpellEffect::Buy_AA_Rank: + case SpellEffect::Ff_FocusTimerMin: + case SpellEffect::Proc_Timer_Modifier: + case SpellEffect::FFItemClass: + case SpellEffect::SpellEffectResistChance: + case SpellEffect::SeeInvis: + case SpellEffect::Invisibility: + case SpellEffect::Invisibility2: + case SpellEffect::InvisVsAnimals: + case SpellEffect::ImprovedInvisAnimals: + case SpellEffect::InvisVsUndead: + case SpellEffect::InvisVsUndead2: + case SpellEffect::Shield_Target: + case SpellEffect::ReduceSkill: { break; } @@ -3474,7 +3474,7 @@ int64 Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level oval, instrument_mod, effect_value); } /* - SPA 413 SE_FcBaseEffects, modifies base value of a spell effect after formula calcultion, but before other focuses. + SPA 413 SpellEffect::FcBaseEffects, modifies base value of a spell effect after formula calcultion, but before other focuses. This is applied to non-Bards in Mob::GetInstrumentMod Like bard modifiers, this is sent in the action_struct using action->instrument_mod (which is a base effect modifier) @@ -3936,7 +3936,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) // doing it every time up here, since most buff effects dont need it switch (effect) { - case SE_CurrentHP: { + case SpellEffect::CurrentHP: { if (spells[buff.spellid].limit_value[i] && !PassCastRestriction(spells[buff.spellid].limit_value[i])) { break; } @@ -3967,7 +3967,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) } break; } - case SE_HealOverTime: { + case SpellEffect::HealOverTime: { effect_value = CalcSpellEffectValue(buff.spellid, i, buff.casterlevel, buff.instrument_mod); if (caster) { effect_value = caster->GetActSpellHealing(buff.spellid, effect_value, nullptr, true); @@ -3978,12 +3978,12 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) break; } - case SE_CurrentEndurance: { + case SpellEffect::CurrentEndurance: { // Handled with bonuses break; } - case SE_BardAEDot: { + case SpellEffect::BardAEDot: { effect_value = CalcSpellEffectValue(buff.spellid, i, buff.casterlevel, buff.instrument_mod, caster); @@ -4008,7 +4008,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) break; } - case SE_Hate: { + case SpellEffect::Hate: { effect_value = CalcSpellEffectValue(buff.spellid, i, buff.casterlevel, buff.instrument_mod); if (caster) { if (effect_value > 0) { @@ -4030,7 +4030,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) break; } - case SE_WipeHateList: { + case SpellEffect::WipeHateList: { if (IsMesmerizeSpell(buff.spellid)) { break; } @@ -4051,9 +4051,9 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) break; } - case SE_Charm: { + case SpellEffect::Charm: { if (!caster || !PassCharismaCheck(caster, buff.spellid)) { - BuffFadeByEffect(SE_Charm); + BuffFadeByEffect(SpellEffect::Charm); // Remove from hate list of any NPC's hate list and remove all NPCs this hate list if (IsNPC()) { @@ -4065,7 +4065,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) break; } - case SE_Root: { + case SpellEffect::Root: { /* Root formula derived from extensive personal live parses - Kayen ROOT has a 70% chance to do a resist check to break. */ @@ -4083,7 +4083,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) break; } - case SE_Fear: { + case SpellEffect::Fear: { if (zone->random.Roll(RuleI(Spells, FearBreakCheckChance))) { float resist_check = ResistSpell(spells[buff.spellid].resist_type, buff.spellid, caster,0,0,true); @@ -4096,9 +4096,9 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) break; } - case SE_Invisibility: - case SE_InvisVsAnimals: - case SE_InvisVsUndead: { + case SpellEffect::Invisibility: + case SpellEffect::InvisVsAnimals: + case SpellEffect::InvisVsUndead: { if (buff.ticsremaining > 3) { if (!IsBardSong(buff.spellid)) { double break_chance = 2.0; @@ -4119,9 +4119,9 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) } } } - case SE_ImprovedInvisAnimals: - case SE_Invisibility2: - case SE_InvisVsUndead2: { + case SpellEffect::ImprovedInvisAnimals: + case SpellEffect::Invisibility2: + case SpellEffect::InvisVsUndead2: { if (!IsBardSong(buff.spellid)) { if (buff.ticsremaining <= 3 && buff.ticsremaining > 1) { MessageString(Chat::Spells, INVIS_BEGIN_BREAK); @@ -4129,7 +4129,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) } break; } - case SE_InterruptCasting: { + case SpellEffect::InterruptCasting: { if (IsCasting()) { const auto &spell = spells[casting_spell_id]; if (!IsCastNotStandingSpell(spell.id) && zone->random.Roll(spells[buff.spellid].base_value[i])) { @@ -4140,22 +4140,22 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) } // These effects always trigger when they fade. // Should we have this triggered from else where? - case SE_CastOnFadeEffect: - case SE_CastOnFadeEffectNPC: - case SE_CastOnFadeEffectAlways: { + case SpellEffect::CastOnFadeEffect: + case SpellEffect::CastOnFadeEffectNPC: + case SpellEffect::CastOnFadeEffectAlways: { if (buff.ticsremaining == 0) { SpellFinished(spells[buff.spellid].base_value[i], this, EQ::spells::CastingSlot::Item, 0, -1, spells[spells[buff.spellid].base_value[i]].resist_difficulty); } break; } - case SE_LocateCorpse: { + case SpellEffect::LocateCorpse: { // This is handled by the client prior to SoD. if (IsClient() && (CastToClient()->ClientVersionBit() & EQ::versions::maskSoDAndLater)) CastToClient()->LocateCorpse(); } - case SE_DistanceRemoval: { + case SpellEffect::DistanceRemoval: { if (spellbonuses.DistanceRemoval) { int distance = @@ -4172,7 +4172,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) } } - case SE_AddHateOverTimePct: { + case SpellEffect::AddHateOverTimePct: { if (IsNPC()) { int64 new_hate = CastToNPC()->GetHateAmount(caster) * (100 + spell.base_value[i]) / 100; if (new_hate <= 0) @@ -4183,7 +4183,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) break; } - case SE_Duration_HP_Pct: { + case SpellEffect::Duration_HP_Pct: { effect_value = spells[buff.spellid].base_value[i]; int64 amt = std::abs(GetMaxHP() * effect_value / 100); if (spells[buff.spellid].max_value[i] && amt > spells[buff.spellid].max_value[i]) @@ -4198,7 +4198,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) break; } - case SE_Duration_Mana_Pct: { + case SpellEffect::Duration_Mana_Pct: { effect_value = spells[buff.spellid].base_value[i]; int32 amt = std::abs(GetMaxMana() * effect_value / 100); if (spells[buff.spellid].max_value[i] && amt > spells[buff.spellid].max_value[i]) @@ -4214,7 +4214,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) break; } - case SE_Duration_Endurance_Pct: { + case SpellEffect::Duration_Endurance_Pct: { effect_value = spells[buff.spellid].base_value[i]; if (IsClient()) { @@ -4302,8 +4302,8 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) switch (spells[buffs[slot].spellid].effect_id[i]) { - case SE_AddMeleeProc: - case SE_WeaponProc: + case SpellEffect::AddMeleeProc: + case SpellEffect::WeaponProc: { uint16 proc_id = GetProcID(buffs[slot].spellid, i); @@ -4316,21 +4316,21 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) break; } - case SE_DefensiveProc: + case SpellEffect::DefensiveProc: { uint16 procid = GetProcID(buffs[slot].spellid, i); RemoveDefensiveProc(procid); break; } - case SE_RangedProc: + case SpellEffect::RangedProc: { uint16 procid = GetProcID(buffs[slot].spellid, i); RemoveRangedProc(procid); break; } - case SE_SummonHorse: + case SpellEffect::SummonHorse: { if(IsClient()) { @@ -4342,8 +4342,8 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) break; } - case SE_IllusionCopy: - case SE_Illusion: + case SpellEffect::IllusionCopy: + case SpellEffect::Illusion: { SendIllusionPacket( AppearanceStruct{ @@ -4361,44 +4361,44 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) break; } - case SE_Levitate: + case SpellEffect::Levitate: { - if (!AffectedBySpellExcludingSlot(slot, SE_Levitate)) + if (!AffectedBySpellExcludingSlot(slot, SpellEffect::Levitate)) SendAppearancePacket(AppearanceType::FlyMode, 0); break; } - case SE_Silence: + case SpellEffect::Silence: { Silence(false); break; } - case SE_Amnesia: + case SpellEffect::Amnesia: { Amnesia(false); break; } - case SE_DivineAura: + case SpellEffect::DivineAura: { SetInvul(false); break; } - case SE_Rune: + case SpellEffect::Rune: { buffs[slot].melee_rune = 0; break; } - case SE_AbsorbMagicAtt: + case SpellEffect::AbsorbMagicAtt: { buffs[slot].magic_rune = 0; break; } - case SE_Familiar: + case SpellEffect::Familiar: { Mob *mypet = GetPet(); if (mypet){ @@ -4409,14 +4409,14 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) break; } - case SE_Mez: + case SpellEffect::Mez: { SendAppearancePacket(AppearanceType::Animation, Animation::Standing); // unfreeze mezzed = false; break; } - case SE_Charm: + case SpellEffect::Charm: { if(IsNPC()) { @@ -4461,7 +4461,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) for (unsigned int j = 0; j < buff_count; j++) { if (IsValidSpell(tar->GetBuffs()[j].spellid)) { auto spell = spells[tar->GetBuffs()[j].spellid]; - if (spell.good_effect == DETRIMENTAL_EFFECT && IsEffectInSpell(spell.id, SE_CurrentHP) && tar->GetBuffs()[j].casterid == GetID()) { + if (spell.good_effect == DETRIMENTAL_EFFECT && IsEffectInSpell(spell.id, SpellEffect::CurrentHP) && tar->GetBuffs()[j].casterid == GetID()) { tar->BuffFadeBySpellID(spell.id); } } @@ -4475,7 +4475,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) for (unsigned int j = 0; j < buff_count; j++) { if (IsValidSpell(GetBuffs()[j].spellid )) { auto spell = spells[GetBuffs()[j].spellid]; - if (spell.good_effect == DETRIMENTAL_EFFECT && IsEffectInSpell(spell.id, SE_CurrentHP)) { + if (spell.good_effect == DETRIMENTAL_EFFECT && IsEffectInSpell(spell.id, SpellEffect::CurrentHP)) { BuffFadeBySpellID(spell.id); } } @@ -4530,7 +4530,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) CastToClient()->AI_Start(CLIENT_LD_TIMEOUT); else { - bool feared = FindType(SE_Fear); + bool feared = FindType(SpellEffect::Fear); if(!feared) CastToClient()->AI_Stop(); } @@ -4538,24 +4538,24 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) break; } - case SE_Root: + case SpellEffect::Root: { buffs[slot].RootBreakChance = 0; rooted = false; break; } - case SE_Blind: - if (currently_fleeing && !FindType(SE_Fear)) + case SpellEffect::Blind: + if (currently_fleeing && !FindType(SpellEffect::Fear)) currently_fleeing = false; break; - case SE_Fear: + case SpellEffect::Fear: { if(RuleB(Combat, EnableFearPathing)){ if(IsClient()) { - bool charmed = FindType(SE_Charm); + bool charmed = FindType(SpellEffect::Charm); if(!charmed) CastToClient()->AI_Stop(); } @@ -4572,7 +4572,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) break; } - case SE_ImmuneFleeing: { + case SpellEffect::ImmuneFleeing: { if (RuleB(Combat, EnableFearPathing)) { if (flee_mode) { currently_fleeing = true; @@ -4582,7 +4582,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) break; } - case SE_BindSight: + case SpellEffect::BindSight: { if(IsClient()) { @@ -4591,20 +4591,20 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) break; } - case SE_SetBodyType: + case SpellEffect::SetBodyType: { SetBodyType(GetOrigBodyType(), false); break; } - case SE_AlterNPCLevel: + case SpellEffect::AlterNPCLevel: { if (IsNPC()) SetLevel(GetOrigLevel()); break; } - case SE_EyeOfZomm: + case SpellEffect::EyeOfZomm: { if (IsClient()) { @@ -4621,7 +4621,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) break; } - case SE_Weapon_Stance: + case SpellEffect::Weapon_Stance: { /* If we click off the spell buff (or fades naturally) giving us @@ -4735,15 +4735,15 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) bool LimitInclude[MaxLimitInclude] = {false}; /* Certain limits require only one of several Include conditions to be true. Ie. Add damage to fire OR ice spells. - 0/1 SE_LimitResist - 2/3 SE_LimitSpell - 4/5 SE_LimitEffect - 6/7 SE_LimitTarget - 8/9 SE_LimitSpellGroup: - 10/11 SE_LimitCastingSkill: - 12/13 SE_LimitSpellClass: - 14/15 SE_LimitSpellSubClass: - 16/17 SE_FFItemCLass: + 0/1 SpellEffect::_LimitResist + 2/3 SpellEffect::_LimitSpell + 4/5 SpellEffect::_LimitEffect + 6/7 SpellEffect::_LimitTarget + 8/9 SpellEffect::_LimitSpellGroup: + 10/11 SpellEffect::LimitCastingSkill: + 12/13 SpellEffect::LimitSpellClass: + 14/15 SpellEffect::LimitSpellSubClass: + 16/17 SpellEffect::FFItemCLass: Remember: Update MaxLimitInclude in spdat.h if adding new limits that require Includes */ @@ -4789,11 +4789,11 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } switch (effect) { - case SE_Blank: + case SpellEffect::Blank: break; // Handle Focus Limits - case SE_LimitResist: + case SpellEffect::LimitResist: if (base_value < 0) { if (spell.resist_type == -base_value) { // Exclude LimitFailure = true; @@ -4807,7 +4807,7 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_LimitInstant: + case SpellEffect::LimitInstant: if (base_value == 1 && spell.buff_duration) { // Fail if not instant LimitFailure = true; } @@ -4817,7 +4817,7 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) break; - case SE_LimitMaxLevel: + case SpellEffect::LimitMaxLevel: spell_level = spell.classes[(GetClass() % 17) - 1]; lvldiff = spell_level - base_value; // every level over cap reduces the effect by base2 percent unless from a clicky when @@ -4835,25 +4835,25 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_LimitMinLevel: + case SpellEffect::LimitMinLevel: if ((spell.classes[(GetClass() % 17) - 1]) < base_value) { LimitFailure = true; } break; - case SE_LimitCastTimeMin: + case SpellEffect::LimitCastTimeMin: if (static_cast(spell.cast_time) < base_value) { LimitFailure = true; } break; - case SE_LimitCastTimeMax: + case SpellEffect::LimitCastTimeMax: if (static_cast(spell.cast_time) > base_value) { LimitFailure = true; } break; - case SE_LimitSpell: + case SpellEffect::LimitSpell: if (base_value < 0) { // Exclude if (spell_id == -base_value) { LimitFailure = true; @@ -4867,13 +4867,13 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_LimitMinDur: + case SpellEffect::LimitMinDur: if (base_value > CalcBuffDuration_formula(GetLevel(), spell.buff_duration_formula, spell.buff_duration)) { LimitFailure = true; } break; - case SE_LimitEffect: + case SpellEffect::LimitEffect: if (base_value < 0) { if (IsEffectInSpell(spell_id, -base_value)) { // Exclude LimitFailure = true; @@ -4882,7 +4882,7 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) else { LimitInclude[IncludeExistsSELimitEffect] = true; // they use 33 here for all classes ... unsure if the type check is really needed - if (base_value == SE_SummonPet && type == focusReagentCost) { + if (base_value == SpellEffect::SummonPet && type == focusReagentCost) { if (IsPetSpell(spell_id)) { LimitInclude[IncludeFoundSELimitEffect] = true; } @@ -4895,7 +4895,7 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_LimitSpellType: + case SpellEffect::LimitSpellType: switch (base_value) { case 0: if (!IsDetrimentalSpell(spell_id)) { @@ -4910,19 +4910,19 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_LimitManaMin: + case SpellEffect::LimitManaMin: if (spell.mana < base_value) { LimitFailure = true; } break; - case SE_LimitManaMax: + case SpellEffect::LimitManaMax: if (spell.mana > base_value) { LimitFailure = true; } break; - case SE_LimitTarget: + case SpellEffect::LimitTarget: if (base_value < 0) { if (-base_value == spell.target_type) { // Exclude LimitFailure = true; @@ -4936,7 +4936,7 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_LimitCombatSkills: + case SpellEffect::LimitCombatSkills: if (base_value == 0 && (IsCombatSkill(spell_id) || IsCombatProc(spell_id))) { // Exclude Discs / Procs LimitFailure = true; } @@ -4946,7 +4946,7 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) break; - case SE_LimitSpellGroup: + case SpellEffect::LimitSpellGroup: if (base_value < 0) { if (-base_value == spell.spell_group) { // Exclude LimitFailure = true; @@ -4960,7 +4960,7 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_LimitCastingSkill: + case SpellEffect::LimitCastingSkill: if (base_value < 0) { if (-base_value == spell.skill) { LimitFailure = true; @@ -4974,7 +4974,7 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_LimitSpellClass: + case SpellEffect::LimitSpellClass: if (base_value < 0) { // Exclude if (-base_value == spell.spell_class) { LimitFailure = true; @@ -4988,7 +4988,7 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_LimitSpellSubclass: + case SpellEffect::LimitSpellSubclass: if (base_value < 0) { // Exclude if (-base_value == spell.spell_subclass) { LimitFailure = true; @@ -5002,7 +5002,7 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_LimitClass: + case SpellEffect::LimitClass: // Do not use this limit more then once per spell. If multiple class, treat value like items // would. if (!PassLimitClass(base_value, GetClass())) { @@ -5010,75 +5010,75 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_LimitRace: + case SpellEffect::LimitRace: if (base_value != GetRace()) { LimitFailure = true; } break; - case SE_LimitUseMin: + case SpellEffect::LimitUseMin: if (base_value > spell.hit_number) { LimitFailure = true; } break; - case SE_LimitUseType: + case SpellEffect::LimitUseType: if (base_value != spell.hit_number_type) { LimitFailure = true; } break; - case SE_Ff_DurationMax: + case SpellEffect::Ff_DurationMax: if (base_value > spell.buff_duration) { LimitFailure = true; } break; - case SE_Ff_Endurance_Min: + case SpellEffect::Ff_Endurance_Min: if (spell.endurance_cost < base_value) { LimitFailure = true; } break; - case SE_Ff_Endurance_Max: + case SpellEffect::Ff_Endurance_Max: if (spell.endurance_cost > base_value) { LimitFailure = true; } break; - case SE_Ff_ReuseTimeMin: + case SpellEffect::Ff_ReuseTimeMin: if (spell.recast_time < base_value) { LimitFailure = true; } break; - case SE_Ff_ReuseTimeMax: + case SpellEffect::Ff_ReuseTimeMax: if (spell.recast_time > base_value) { LimitFailure = true; } break; - case SE_Ff_Value_Min: + case SpellEffect::Ff_Value_Min: index_id = GetSpellEffectIndex(spell_id, limit_value); if (index_id >= 0 && spell.base_value[index_id] < base_value) { LimitFailure = true; } break; - case SE_Ff_Value_Max: + case SpellEffect::Ff_Value_Max: index_id = GetSpellEffectIndex(spell_id, limit_value); if (index_id >= 0 && spell.base_value[index_id] > base_value) { LimitFailure = true; } break; - case SE_Ff_Override_NotFocusable: + case SpellEffect::Ff_Override_NotFocusable: if (base_value == 1) { not_focusable = false; } break; - case SE_Ff_FocusTimerMin: + case SpellEffect::Ff_FocusTimerMin: if (IsFocusProcLimitTimerActive(-rank.id)) { LimitFailure = true; } @@ -5087,7 +5087,7 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_FFItemClass: + case SpellEffect::FFItemClass: has_item_limit_check = true; if (casting_spell_inventory_slot && casting_spell_inventory_slot != -1) { if (IsClient() && casting_spell_slot == EQ::spells::CastingSlot::Item && casting_spell_inventory_slot != 0xFFFFFFFF) { @@ -5143,111 +5143,111 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) break; /* These are not applicable to AA's because there is never a 'caster' of the 'buff' with the focus effect. - case SE_Ff_Same_Caster: - case SE_Ff_CasterClass: + case SpellEffect::Ff_Same_Caster: + case SpellEffect::Ff_CasterClass: */ // Handle Focus Effects - case SE_ImprovedDamage: + case SpellEffect::ImprovedDamage: if (type == focusImprovedDamage && base_value > value) { value = base_value; } break; - case SE_ImprovedDamage2: + case SpellEffect::ImprovedDamage2: if (type == focusImprovedDamage2 && base_value > value) { value = base_value; } break; - case SE_Fc_Amplify_Mod: + case SpellEffect::Fc_Amplify_Mod: if (type == focusFcAmplifyMod && base_value > value) { value = base_value; } break; - case SE_ImprovedHeal: + case SpellEffect::ImprovedHeal: if (type == focusImprovedHeal && base_value > value) { value = base_value; } break; - case SE_ReduceManaCost: + case SpellEffect::ReduceManaCost: if (type == focusManaCost) { value = base_value; } break; - case SE_IncreaseSpellHaste: + case SpellEffect::IncreaseSpellHaste: if (type == focusSpellHaste && base_value > value) { value = base_value; try_apply_to_item_click = is_from_item_click ? true : false; } break; - case SE_Fc_CastTimeMod2: + case SpellEffect::Fc_CastTimeMod2: if (type == focusFcCastTimeMod2 && base_value > value) { value = base_value; try_apply_to_item_click = is_from_item_click ? true : false; } break; - case SE_Fc_CastTimeAmt: + case SpellEffect::Fc_CastTimeAmt: if (type == focusFcCastTimeAmt && base_value > value) { value = base_value; try_apply_to_item_click = is_from_item_click ? true : false; } break; - case SE_IncreaseSpellDuration: + case SpellEffect::IncreaseSpellDuration: if (type == focusSpellDuration && base_value > value) { value = base_value; } break; - case SE_SpellDurationIncByTic: + case SpellEffect::SpellDurationIncByTic: if (type == focusSpellDurByTic && base_value > value) { value = base_value; } break; - case SE_SwarmPetDuration: + case SpellEffect::SwarmPetDuration: if (type == focusSwarmPetDuration && base_value > value) { value = base_value; } break; - case SE_IncreaseRange: + case SpellEffect::IncreaseRange: if (type == focusRange && base_value > value) { value = base_value; } break; - case SE_ReduceReagentCost: + case SpellEffect::ReduceReagentCost: if (type == focusReagentCost && base_value > value) { value = base_value; } break; - case SE_PetPowerIncrease: + case SpellEffect::PetPowerIncrease: if (type == focusPetPower && base_value > value) { value = base_value; } break; - case SE_SpellResistReduction: + case SpellEffect::SpellResistReduction: if (type == focusResistRate && base_value > value) { value = base_value; } break; - case SE_Fc_ResistIncoming: + case SpellEffect::Fc_ResistIncoming: if (type == focusFcResistIncoming && base_value > value) { value = base_value; } break; - case SE_SpellHateMod: + case SpellEffect::SpellHateMod: if (type == focusSpellHateMod) { if (value != 0) { if (value > 0) { @@ -5267,14 +5267,14 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_ReduceReuseTimer: + case SpellEffect::ReduceReuseTimer: if (type == focusReduceRecastTime) { value = base_value / 1000; try_apply_to_item_click = is_from_item_click ? true : false; } break; - case SE_TriggerOnCast: + case SpellEffect::TriggerOnCast: if (type == focusTriggerOnCast) { if (zone->random.Roll(base_value)) { value = limit_value; @@ -5286,19 +5286,19 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_FcSpellVulnerability: + case SpellEffect::FcSpellVulnerability: if (type == focusSpellVulnerability) { value = base_value; } break; - case SE_Fc_Spell_Damage_Pct_IncomingPC: + case SpellEffect::Fc_Spell_Damage_Pct_IncomingPC: if (type == focusFcSpellDamagePctIncomingPC) { value = base_value; } break; - case SE_BlockNextSpellFocus: + case SpellEffect::BlockNextSpellFocus: if (type == focusBlockNextSpell) { if (zone->random.Roll(base_value)) { value = 1; @@ -5306,122 +5306,122 @@ int64 Mob::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) } break; - case SE_FcTwincast: - if (type == focusTwincast && !IsEffectInSpell(spell_id, SE_TwinCastBlocker)) { + case SpellEffect::FcTwincast: + if (type == focusTwincast && !IsEffectInSpell(spell_id, SpellEffect::TwinCastBlocker)) { value = base_value; } break; // Note if using these as AA, make sure this is first focus used. - case SE_SympatheticProc: + case SpellEffect::SympatheticProc: if (type == focusSympatheticProc) { value = limit_value; } break; - case SE_FcDamageAmt: + case SpellEffect::FcDamageAmt: if (type == focusFcDamageAmt) { value = base_value; } break; - case SE_FcDamageAmt2: + case SpellEffect::FcDamageAmt2: if (type == focusFcDamageAmt2) { value = base_value; } break; - case SE_Fc_Amplify_Amt: + case SpellEffect::Fc_Amplify_Amt: if (type == focusFcAmplifyAmt) { value = base_value; } break; - case SE_FcDamageAmtCrit: + case SpellEffect::FcDamageAmtCrit: if (type == focusFcDamageAmtCrit) { value = base_value; } break; - case SE_FcDamageAmtIncoming: + case SpellEffect::FcDamageAmtIncoming: if (type == focusFcDamageAmtIncoming) { value = base_value; } break; - case SE_Fc_Spell_Damage_Amt_IncomingPC: + case SpellEffect::Fc_Spell_Damage_Amt_IncomingPC: if (type == focusFcSpellDamageAmtIncomingPC) { value = base_value; } break; - case SE_FcHealAmtIncoming: + case SpellEffect::FcHealAmtIncoming: if (type == focusFcHealAmtIncoming) { value = base_value; } break; - case SE_FcHealPctCritIncoming: + case SpellEffect::FcHealPctCritIncoming: if (type == focusFcHealPctCritIncoming) { value = base_value; } break; - case SE_FcHealAmtCrit: + case SpellEffect::FcHealAmtCrit: if (type == focusFcHealAmtCrit) { value = base_value; } break; - case SE_FcHealAmt: + case SpellEffect::FcHealAmt: if (type == focusFcHealAmt) { value = base_value; } break; - case SE_FcHealPctIncoming: + case SpellEffect::FcHealPctIncoming: if (type == focusFcHealPctIncoming) { value = base_value; } break; - case SE_FcBaseEffects: + case SpellEffect::FcBaseEffects: if (type == focusFcBaseEffects) { value = base_value; } break; - case SE_FcDamagePctCrit: + case SpellEffect::FcDamagePctCrit: if (type == focusFcDamagePctCrit) { value = base_value; } break; - case SE_FcIncreaseNumHits: + case SpellEffect::FcIncreaseNumHits: if (type == focusIncreaseNumHits) { value = base_value; } break; - case SE_FcLimitUse: + case SpellEffect::FcLimitUse: if (type == focusFcLimitUse) { value = base_value; } break; - case SE_FcMute: + case SpellEffect::FcMute: if (type == focusFcMute) { value = base_value; } break; - case SE_FcStunTimeMod: + case SpellEffect::FcStunTimeMod: if (type == focusFcStunTimeMod) { value = base_value; } break; - case SE_Fc_Cast_Spell_On_Land: + case SpellEffect::Fc_Cast_Spell_On_Land: if (type == focusFcCastSpellOnLand) { if (zone->random.Roll(base_value)) { value = limit_value; @@ -5469,7 +5469,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } // No further checks if spell_id no_focusable, unless spell focus_id contains an override limiter. - if (spells[spell_id].not_focusable && !IsEffectInSpell(focus_id, SE_Ff_Override_NotFocusable)) { + if (spells[spell_id].not_focusable && !IsEffectInSpell(focus_id, SpellEffect::Ff_Override_NotFocusable)) { return 0; } @@ -5497,15 +5497,15 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo /* Certain limits require only one of several Include conditions to be true. Determined by limits being negative or positive Ie. Add damage to fire OR ice spells. If positive we 'Include', by checking each limit of same type to look for match until found. Opposed to just 'Excluding', where if set to negative, if we find that match then focus fails, ie Add damage to all spells BUT Fire. - 0/1 SE_LimitResist - 2/3 SE_LimitSpell - 4/5 SE_LimitEffect - 6/7 SE_LimitTarget - 8/9 SE_LimitSpellGroup: - 10/11 SE_LimitCastingSkill: - 12/13 SE_LimitSpellClass: - 14/15 SE_LimitSpellSubClass: - 16/17 SE_FFItemCLass: + 0/1 SpellEffect::_LimitResist + 2/3 SpellEffect::_LimitSpell + 4/5 SpellEffect::_LimitEffect + 6/7 SpellEffect::_LimitTarget + 8/9 SpellEffect::_LimitSpellGroup: + 10/11 SpellEffect::LimitCastingSkill: + 12/13 SpellEffect::LimitSpellClass: + 14/15 SpellEffect::LimitSpellSubClass: + 16/17 SpellEffect::FFItemCLass: Remember: Update MaxLimitInclude in spdat.h if adding new limits that require Includes */ @@ -5513,10 +5513,10 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo switch (focus_spell.effect_id[i]) { - case SE_Blank: + case SpellEffect::Blank: break; - case SE_LimitResist: + case SpellEffect::LimitResist: if (focus_spell.base_value[i] < 0) { if (spell.resist_type == -focus_spell.base_value[i]) { // Exclude return 0; @@ -5530,7 +5530,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_LimitInstant: + case SpellEffect::LimitInstant: if (focus_spell.base_value[i] == 1 && spell.buff_duration) { // Fail if not instant return 0; } @@ -5540,7 +5540,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; - case SE_LimitMaxLevel: + case SpellEffect::LimitMaxLevel: if (IsNPC()) { break; } @@ -5562,7 +5562,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_LimitMinLevel: + case SpellEffect::LimitMinLevel: if (IsNPC()) { break; } @@ -5571,19 +5571,19 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_LimitCastTimeMin: + case SpellEffect::LimitCastTimeMin: if (spells[spell_id].cast_time < (uint16) focus_spell.base_value[i]) { return (0); } break; - case SE_LimitCastTimeMax: + case SpellEffect::LimitCastTimeMax: if (spells[spell_id].cast_time > (uint16) focus_spell.base_value[i]) { return (0); } break; - case SE_LimitSpell: + case SpellEffect::LimitSpell: if (focus_spell.base_value[i] < 0) { // Exclude if (spell_id == -focus_spell.base_value[i]) { return (0); @@ -5597,14 +5597,14 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_LimitMinDur: + case SpellEffect::LimitMinDur: if (focus_spell.base_value[i] > CalcBuffDuration_formula(GetLevel(), spell.buff_duration_formula, spell.buff_duration)) { return (0); } break; - case SE_LimitEffect: + case SpellEffect::LimitEffect: if (focus_spell.base_value[i] < 0) { if (IsEffectInSpell(spell_id, -focus_spell.base_value[i])) { // Exclude return 0; @@ -5618,7 +5618,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_LimitSpellType: + case SpellEffect::LimitSpellType: switch (focus_spell.base_value[i]) { case 0: if (!IsDetrimentalSpell(spell_id)) { @@ -5636,19 +5636,19 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_LimitManaMin: + case SpellEffect::LimitManaMin: if (spell.mana < focus_spell.base_value[i]) { return 0; } break; - case SE_LimitManaMax: + case SpellEffect::LimitManaMax: if (spell.mana > focus_spell.base_value[i]) { return 0; } break; - case SE_LimitTarget: + case SpellEffect::LimitTarget: if (focus_spell.base_value[i] < 0) { if (-focus_spell.base_value[i] == spell.target_type) { // Exclude return 0; @@ -5662,7 +5662,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_LimitCombatSkills: + case SpellEffect::LimitCombatSkills: if (focus_spell.base_value[i] == 0 && (IsCombatSkill(spell_id) || IsCombatProc(spell_id))) { // Exclude Discs / Procs return 0; @@ -5673,7 +5673,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; - case SE_LimitSpellGroup: + case SpellEffect::LimitSpellGroup: if (focus_spell.base_value[i] < 0) { if (-focus_spell.base_value[i] == spell.spell_group) { // Exclude return 0; @@ -5687,7 +5687,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_LimitCastingSkill: + case SpellEffect::LimitCastingSkill: if (focus_spell.base_value[i] < 0) { if (-focus_spell.base_value[i] == spell.skill) { return 0; @@ -5701,7 +5701,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_LimitClass: + case SpellEffect::LimitClass: // Do not use this limit more then once per spell. If multiple class, treat value like items // would. if (!PassLimitClass(focus_spell.base_value[i], GetClass())) { @@ -5709,31 +5709,31 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_LimitRace: + case SpellEffect::LimitRace: if (focus_spell.base_value[i] != GetRace()) { return 0; } break; - case SE_LimitUseMin: + case SpellEffect::LimitUseMin: if (focus_spell.base_value[i] > spell.hit_number) { return 0; } break; - case SE_LimitUseType: + case SpellEffect::LimitUseType: if (focus_spell.base_value[i] != spell.hit_number_type) { return 0; } break; - case SE_CastonFocusEffect: + case SpellEffect::CastonFocusEffect: if (focus_spell.base_value[i] > 0) { Caston_spell_id = focus_spell.base_value[i]; } break; - case SE_LimitSpellClass: + case SpellEffect::LimitSpellClass: if (focus_spell.base_value[i] < 0) { // Exclude if (-focus_spell.base_value[i] == spell.spell_class) { return 0; @@ -5747,7 +5747,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_LimitSpellSubclass: + case SpellEffect::LimitSpellSubclass: if (focus_spell.base_value[i] < 0) { // Exclude if (-focus_spell.base_value[i] == spell.spell_subclass) { return 0; @@ -5761,7 +5761,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_Ff_Same_Caster://hmm do i need to pass casterid from buff slot here + case SpellEffect::Ff_Same_Caster://hmm do i need to pass casterid from buff slot here if (focus_spell.base_value[i] == 0) { if (caster && casterid == caster->GetID()) { return 0; @@ -5774,7 +5774,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_Ff_CasterClass: { + case SpellEffect::Ff_CasterClass: { // Do not use this limit more then once per spell. If multiple class, treat value like items would. if (caster && !PassLimitClass(focus_spell.base_value[i], caster->GetClass())) { @@ -5783,51 +5783,51 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; } - case SE_Ff_DurationMax: + case SpellEffect::Ff_DurationMax: if (focus_spell.base_value[i] > spell.buff_duration) { return 0; } break; - case SE_Ff_Endurance_Min: + case SpellEffect::Ff_Endurance_Min: if (spell.endurance_cost < focus_spell.base_value[i]) { return 0; } break; - case SE_Ff_Endurance_Max: + case SpellEffect::Ff_Endurance_Max: if (spell.endurance_cost > focus_spell.base_value[i]) { return 0; } break; - case SE_Ff_ReuseTimeMin: + case SpellEffect::Ff_ReuseTimeMin: if (spell.recast_time < focus_spell.base_value[i]) { return 0; } break; - case SE_Ff_ReuseTimeMax: + case SpellEffect::Ff_ReuseTimeMax: if (spell.recast_time > focus_spell.base_value[i]) { return 0; } break; - case SE_Ff_Value_Min: + case SpellEffect::Ff_Value_Min: index_id = GetSpellEffectIndex(spell_id, focus_spell.limit_value[i]); if (index_id >= 0 && spell.base_value[index_id] < focus_spell.base_value[i]) { return 0; } break; - case SE_Ff_Value_Max: + case SpellEffect::Ff_Value_Max: index_id = GetSpellEffectIndex(spell_id, focus_spell.limit_value[i]); if (index_id >= 0 && spell.base_value[index_id] > focus_spell.base_value[i]) { return 0; } break; - case SE_Ff_FocusTimerMin: + case SpellEffect::Ff_FocusTimerMin: if (IsFocusProcLimitTimerActive(focus_spell.id)) { return 0; } @@ -5836,7 +5836,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_FFItemClass: + case SpellEffect::FFItemClass: /* Limits focuses to check if cast from item clicks. Can be used to INCLUDE or EXCLUDE items by ItemType and/or SubType and/or Slots @@ -5927,8 +5927,8 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; // handle effects - case SE_ImprovedDamage: - case SE_ImprovedDamage2: + case SpellEffect::ImprovedDamage: + case SpellEffect::ImprovedDamage2: if (!RuleB(Spells, UseClassicSpellFocus)) { if (type == focusImprovedDamage || type == focusImprovedDamage2) { value = GetFocusRandomEffectivenessValue(focus_spell.base_value[i], focus_spell.limit_value[i], best_focus); @@ -5942,14 +5942,14 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } } - case SE_Fc_Amplify_Mod: + case SpellEffect::Fc_Amplify_Mod: if (type == focusFcAmplifyMod && focus_spell.base_value[i] > value) { value = focus_spell.base_value[i]; } break; - case SE_ImprovedHeal: - case SE_ReduceManaCost: + case SpellEffect::ImprovedHeal: + case SpellEffect::ReduceManaCost: if (!RuleB(Spells, UseClassicSpellFocus)) { if (type == focusImprovedHeal || type == focusManaCost) { value = GetFocusRandomEffectivenessValue(focus_spell.base_value[i], focus_spell.limit_value[i], best_focus); @@ -5964,52 +5964,52 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_IncreaseSpellHaste: + case SpellEffect::IncreaseSpellHaste: if (type == focusSpellHaste && focus_spell.base_value[i] > value) { value = focus_spell.base_value[i]; try_apply_to_item_click = is_from_item_click ? true : false; } break; - case SE_Fc_CastTimeMod2: + case SpellEffect::Fc_CastTimeMod2: if (type == focusFcCastTimeMod2 && focus_spell.base_value[i] > value) { value = focus_spell.base_value[i]; try_apply_to_item_click = is_from_item_click ? true : false; } break; - case SE_Fc_CastTimeAmt: + case SpellEffect::Fc_CastTimeAmt: if (type == focusFcCastTimeAmt && focus_spell.base_value[i] > value) { value = focus_spell.base_value[i]; try_apply_to_item_click = is_from_item_click ? true : false; } break; - case SE_IncreaseSpellDuration: + case SpellEffect::IncreaseSpellDuration: if (type == focusSpellDuration && focus_spell.base_value[i] > value) { value = focus_spell.base_value[i]; } break; - case SE_SpellDurationIncByTic: + case SpellEffect::SpellDurationIncByTic: if (type == focusSpellDurByTic && focus_spell.base_value[i] > value) { value = focus_spell.base_value[i]; } break; - case SE_SwarmPetDuration: + case SpellEffect::SwarmPetDuration: if (type == focusSwarmPetDuration && focus_spell.base_value[i] > value) { value = focus_spell.base_value[i]; } break; - case SE_IncreaseRange: + case SpellEffect::IncreaseRange: if (type == focusRange && focus_spell.base_value[i] > value) { value = focus_spell.base_value[i]; } break; - case SE_ReduceReagentCost: + case SpellEffect::ReduceReagentCost: if (!RuleB(Spells, UseClassicSpellFocus)) { if (type == focusReagentCost) { value = GetFocusRandomEffectivenessValue(focus_spell.base_value[i], focus_spell.limit_value[i], best_focus); @@ -6022,25 +6022,25 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_PetPowerIncrease: + case SpellEffect::PetPowerIncrease: if (type == focusPetPower && focus_spell.base_value[i] > value) { value = focus_spell.base_value[i]; } break; - case SE_SpellResistReduction: + case SpellEffect::SpellResistReduction: if (type == focusResistRate) { value = GetFocusRandomEffectivenessValue(focus_spell.base_value[i], focus_spell.limit_value[i], best_focus); } break; - case SE_Fc_ResistIncoming: + case SpellEffect::Fc_ResistIncoming: if (type == focusFcResistIncoming && focus_spell.base_value[i] > value) { value = focus_spell.base_value[i]; } break; - case SE_SpellHateMod: + case SpellEffect::SpellHateMod: if (!RuleB(Spells, UseClassicSpellFocus)) { if (type == focusSpellHateMod) { value = GetFocusRandomEffectivenessValue(focus_spell.base_value[i], focus_spell.limit_value[i], best_focus); @@ -6057,14 +6057,14 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_ReduceReuseTimer: + case SpellEffect::ReduceReuseTimer: if (type == focusReduceRecastTime) { value = focus_spell.base_value[i] / 1000; try_apply_to_item_click = is_from_item_click ? true : false; } break; - case SE_TriggerOnCast: + case SpellEffect::TriggerOnCast: if (type == focusTriggerOnCast) { if (zone->random.Roll(focus_spell.base_value[i])) { value = focus_spell.limit_value[i]; @@ -6075,7 +6075,7 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_BlockNextSpellFocus: + case SpellEffect::BlockNextSpellFocus: if (type == focusBlockNextSpell) { if (zone->random.Roll(focus_spell.base_value[i])) { value = 1; @@ -6083,145 +6083,145 @@ int64 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo } break; - case SE_SympatheticProc: + case SpellEffect::SympatheticProc: if (type == focusSympatheticProc) { value = focus_id; } break; - case SE_FcSpellVulnerability: + case SpellEffect::FcSpellVulnerability: if (type == focusSpellVulnerability) { value = GetFocusRandomEffectivenessValue(focus_spell.base_value[i], focus_spell.limit_value[i], best_focus); } break; - case SE_Fc_Spell_Damage_Pct_IncomingPC: + case SpellEffect::Fc_Spell_Damage_Pct_IncomingPC: if (type == focusFcSpellDamagePctIncomingPC) { value = GetFocusRandomEffectivenessValue(focus_spell.base_value[i], focus_spell.limit_value[i], best_focus); } break; - case SE_FcTwincast: - if (type == focusTwincast && !IsEffectInSpell(spell_id, SE_TwinCastBlocker)) { + case SpellEffect::FcTwincast: + if (type == focusTwincast && !IsEffectInSpell(spell_id, SpellEffect::TwinCastBlocker)) { value = focus_spell.base_value[i]; } break; - case SE_FcDamageAmt: + case SpellEffect::FcDamageAmt: if (type == focusFcDamageAmt) { value = focus_spell.base_value[i]; } break; - case SE_FcDamageAmt2: + case SpellEffect::FcDamageAmt2: if (type == focusFcDamageAmt2) { value = focus_spell.base_value[i]; } break; - case SE_Fc_Amplify_Amt: + case SpellEffect::Fc_Amplify_Amt: if (type == focusFcAmplifyAmt) { value = focus_spell.base_value[i]; } break; - case SE_FcDamageAmtCrit: + case SpellEffect::FcDamageAmtCrit: if (type == focusFcDamageAmtCrit) { value = focus_spell.base_value[i]; } break; - case SE_FcDamageAmtIncoming: + case SpellEffect::FcDamageAmtIncoming: if (type == focusFcDamageAmtIncoming) { value = focus_spell.base_value[i]; } break; - case SE_Fc_Spell_Damage_Amt_IncomingPC: + case SpellEffect::Fc_Spell_Damage_Amt_IncomingPC: if (type == focusFcSpellDamageAmtIncomingPC) { value = focus_spell.base_value[i]; } break; - case SE_FcHealAmtIncoming: + case SpellEffect::FcHealAmtIncoming: if (type == focusFcHealAmtIncoming) { value = focus_spell.base_value[i]; } break; - case SE_FcDamagePctCrit: + case SpellEffect::FcDamagePctCrit: if (type == focusFcDamagePctCrit) { value = focus_spell.base_value[i]; } break; - case SE_FcHealPctCritIncoming: + case SpellEffect::FcHealPctCritIncoming: if (type == focusFcHealPctCritIncoming) { value = GetFocusRandomEffectivenessValue(focus_spell.base_value[i], focus_spell.limit_value[i], best_focus); } break; - case SE_FcHealAmtCrit: + case SpellEffect::FcHealAmtCrit: if (type == focusFcHealAmtCrit) { value = focus_spell.base_value[i]; } break; - case SE_FcHealAmt: + case SpellEffect::FcHealAmt: if (type == focusFcHealAmt) { value = focus_spell.base_value[i]; } break; - case SE_FcHealPctIncoming: + case SpellEffect::FcHealPctIncoming: if (type == focusFcHealPctIncoming) { value = GetFocusRandomEffectivenessValue(focus_spell.base_value[i], focus_spell.limit_value[i], best_focus); } break; - case SE_FcBaseEffects: + case SpellEffect::FcBaseEffects: if (type == focusFcBaseEffects) { value = focus_spell.base_value[i]; } break; - case SE_FcIncreaseNumHits: + case SpellEffect::FcIncreaseNumHits: if (type == focusIncreaseNumHits) { value = focus_spell.base_value[i]; } break; - case SE_FcLimitUse: + case SpellEffect::FcLimitUse: if (type == focusFcLimitUse) { value = focus_spell.base_value[i]; } break; - case SE_FcMute: + case SpellEffect::FcMute: if (type == focusFcMute) { value = focus_spell.base_value[i]; } break; - case SE_FcStunTimeMod: + case SpellEffect::FcStunTimeMod: if (type == focusFcStunTimeMod) { value = focus_spell.base_value[i]; } break; - case SE_FcTimerRefresh: + case SpellEffect::FcTimerRefresh: if (type == focusFcTimerRefresh) { value = focus_spell.base_value[i]; } break; - case SE_FcTimerLockout: + case SpellEffect::FcTimerLockout: if (type == focusFcTimerLockout) { value = focus_spell.base_value[i]; } break; - case SE_Fc_Cast_Spell_On_Land: + case SpellEffect::Fc_Cast_Spell_On_Land: if (type == focusFcCastSpellOnLand) { if (zone->random.Roll(focus_spell.base_value[i])) { value = focus_spell.limit_value[i]; @@ -6300,7 +6300,7 @@ void Mob::TryTriggerOnCastFocusEffect(focusType type, uint16 spell_id) temp_item = ins->GetItem(); if (temp_item && temp_item->Focus.Effect > 0 && IsValidSpell(temp_item->Focus.Effect)) { focus_spell_id = temp_item->Focus.Effect; - if (!IsEffectInSpell(focus_spell_id, SE_TriggerOnCast)) { + if (!IsEffectInSpell(focus_spell_id, SpellEffect::TriggerOnCast)) { continue; } @@ -6317,7 +6317,7 @@ void Mob::TryTriggerOnCastFocusEffect(focusType type, uint16 spell_id) if (temp_item_aug && temp_item_aug->Focus.Effect > 0 && IsValidSpell(temp_item_aug->Focus.Effect)) { focus_spell_id = temp_item_aug->Focus.Effect; - if (!IsEffectInSpell(focus_spell_id, SE_TriggerOnCast)) { + if (!IsEffectInSpell(focus_spell_id, SpellEffect::TriggerOnCast)) { continue; } @@ -6340,7 +6340,7 @@ void Mob::TryTriggerOnCastFocusEffect(focusType type, uint16 spell_id) continue; } - if (!IsEffectInSpell(focus_spell_id, SE_TriggerOnCast)) { + if (!IsEffectInSpell(focus_spell_id, SpellEffect::TriggerOnCast)) { continue; } @@ -6831,7 +6831,7 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro } } - if (type == focusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id))) { + if (type == focusReagentCost && (IsEffectInSpell(spell_id, SpellEffect::SummonItem) || IsSacrificeSpell(spell_id))) { return 0; } //Summon Spells that require reagents are typically imbue type spells, enchant metal, sacrifice and shouldn't be affected @@ -7022,7 +7022,7 @@ void Mob::CheckNumHitsRemaining(NumHit type, int32 buff_slot, uint16 spell_id) 3: [Incoming Spells] (180=SE_ResistSpellChance, 296=SE_FcSpellVulnerability) //Note: Determinetal spells only unless proven otherwise 4: [Outgoing Spells] 5: [Outgoing Hit Successes] (220=SE_SkillDamageAmount, 178=SE_MeleeLifetap, 121=SE_ReverseDS, ?373=SE_CastOnFadeEffectAlways) - 6: [Incoming Hit Successes] (59=SE_DamageShield, 197=SE_SkillDamageTaken, 162=define SE_MitigateMeleeDamage) + 6: [Incoming Hit Successes] (59=SE_DamageShield, 197=SE_SkillDamageTaken, 162=define SpellEffect::MitigateMeleeDamage) 7: [Matching Spells] *When focus is triggered (focus effects) 8: [Incoming Hits or Spells] (329=SE_ManaAbsorbPercentDamage) 9: [Reflected Spells] If successful @@ -7164,8 +7164,8 @@ bool Mob::TryDivineSave() spellbonuses.DivineSaveChance[SBIndex::DIVINE_SAVE_SPELL_TRIGGER_ID] }; //Fade the divine save effect here after saving the old effects off. - //That way, if desired, the effect could apply SE_DivineSave again. - BuffFadeByEffect(SE_DivineSave); + //That way, if desired, the effect could apply SpellEffect::DivineSave again. + BuffFadeByEffect(SpellEffect::DivineSave); for(size_t i = 0; i < ( sizeof(EffectsToTry) / sizeof(EffectsToTry[0]) ); ++i) { if( EffectsToTry[i] ) @@ -7193,7 +7193,7 @@ bool Mob::TryDeathSave() { the a value of a heal modifier of the base effects heal. Ie. Divine Intervention is 8000 HP Max UD1=20, therefore heal is 8000*20/100 -No evidence of chance rate increasing between UD1-3, numbers indicate it uses same CHA rate as first DI. - -In later expansions this SE_DeathSave was given a level limit and a heal value in its effect data. + -In later expansions this SpellEffect::DeathSave was given a level limit and a heal value in its effect data. */ if (spellbonuses.DeathSave[SBIndex::DEATH_SAVE_TYPE]){ @@ -7337,7 +7337,7 @@ float Mob::GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 I int16 Mob::GetSympatheticSpellProcRate(uint16 spell_id) { for (int i = 0; i < EFFECT_COUNT; i++){ - if (spells[spell_id].effect_id[i] == SE_SympatheticProc) + if (spells[spell_id].effect_id[i] == SpellEffect::SympatheticProc) return spells[spell_id].base_value[i]; } @@ -7347,7 +7347,7 @@ int16 Mob::GetSympatheticSpellProcRate(uint16 spell_id) uint16 Mob::GetSympatheticSpellProcID(uint16 spell_id) { for (int i = 0; i < EFFECT_COUNT; i++){ - if (spells[spell_id].effect_id[i] == SE_SympatheticProc) + if (spells[spell_id].effect_id[i] == SpellEffect::SympatheticProc) return spells[spell_id].limit_value[i]; } @@ -7372,8 +7372,8 @@ int64 Mob::GetFcDamageAmtIncoming(Mob *caster, int32 spell_id, bool from_buff_ti { //THIS is target of spell cast int64 dmg = 0; - dmg += GetFocusEffect(focusFcDamageAmtIncoming, spell_id, caster, from_buff_tic); //SPA 297 SE_FcDamageAmtIncoming - dmg += GetFocusEffect(focusFcSpellDamageAmtIncomingPC, spell_id, caster, from_buff_tic); //SPA 484 SE_Fc_Spell_Damage_Amt_IncomingPC + dmg += GetFocusEffect(focusFcDamageAmtIncoming, spell_id, caster, from_buff_tic); //SPA 297 SpellEffect::FcDamageAmtIncoming + dmg += GetFocusEffect(focusFcSpellDamageAmtIncomingPC, spell_id, caster, from_buff_tic); //SPA 484 SpellEffect::Fc_Spell_Damage_Amt_IncomingPC return dmg; } @@ -7433,8 +7433,8 @@ int64 Mob::GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spel bool Mob::PassLimitClass(uint32 Classes_, uint16 Class_) { - //The class value for SE_LimitClass is +1 to its equivelent value in item dbase - //Example Bard on items is '128' while Bard on SE_LimitClass is '256', keep this in mind if making custom spells. + //The class value for SpellEffect::LimitClass is +1 to its equivelent value in item dbase + //Example Bard on items is '128' while Bard on SpellEffect::LimitClass is '256', keep this in mind if making custom spells. if (Class_ > 16) return false; @@ -7486,7 +7486,7 @@ bool Mob::TrySpellEffectResist(uint16 spell_id) for(int i = 0; i < EFFECT_COUNT; ++i) { - if (spells[spell_id].effect_id[i] == SE_Blank) { + if (spells[spell_id].effect_id[i] == SpellEffect::Blank) { continue; } @@ -8286,7 +8286,7 @@ bool Mob::PassCastRestriction(int value) case HAS_NO_MANA_BURN_BUFF: { bool has_effect = false; for (int i = 0; i < GetMaxTotalSlots(); i++) { - if (IsValidSpell(buffs[i].spellid) && IsEffectInSpell(buffs[i].spellid, SE_ManaBurn)) { + if (IsValidSpell(buffs[i].spellid) && IsEffectInSpell(buffs[i].spellid, SpellEffect::ManaBurn)) { has_effect = true; } } @@ -9737,7 +9737,7 @@ void Mob::ResourceTap(int64 damage, uint16 spellid) return; for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[spellid].effect_id[i] == SE_ResourceTap) { + if (spells[spellid].effect_id[i] == SpellEffect::ResourceTap) { damage = (damage * spells[spellid].base_value[i]) / 1000; if (damage) { @@ -9767,9 +9767,9 @@ void Mob::TryTriggerThreshHold(int64 damage, int effect_id, Mob* attacker){ if (damage <= 0) return; - if ((SE_TriggerMeleeThreshold == effect_id) && !spellbonuses.TriggerMeleeThreshold ) + if ((SpellEffect::TriggerMeleeThreshold == effect_id) && !spellbonuses.TriggerMeleeThreshold ) return; - else if ((SE_TriggerSpellThreshold == effect_id) && !spellbonuses.TriggerSpellThreshold) + else if ((SpellEffect::TriggerSpellThreshold == effect_id) && !spellbonuses.TriggerSpellThreshold) return; int buff_count = GetMaxTotalSlots(); @@ -9806,10 +9806,10 @@ void Mob::TryTriggerThreshHold(int64 damage, int effect_id, Mob* attacker){ void Mob::CastSpellOnLand(Mob* caster, int32 spell_id) { /* - This function checks for incoming spells on a mob, if they meet the criteria for focus SE_Fc_Cast_Spell_on_Land then + This function checks for incoming spells on a mob, if they meet the criteria for focus SpellEffect::Fc_Cast_Spell_on_Land then a new spell will be cast by THIS mob as specified by the focus effect. Note: Chance to cast the spell is determined in the CalcFocusEffect function if not 100pct. - ApplyFocusProcLimiter() function checks for SE_Proc_Timer_Modifier which allows for limiting how often a spell from effect can be triggered + ApplyFocusProcLimiter() function checks for SpellEffect::Proc_Timer_Modifier which allows for limiting how often a spell from effect can be triggered for example, if set to base=1 and base2= 1500, then for everyone 1 successful trigger, you will be unable to trigger again for 1.5 seconds. Live only has this focus in buffs/debuffs that can be placed on a target. TODO: Will consider adding support for it as AA and Item. @@ -9825,7 +9825,7 @@ void Mob::CastSpellOnLand(Mob* caster, int32 spell_id) int buff_count = GetMaxTotalSlots(); for (int i = 0; i < buff_count; i++) { - if ((IsValidSpell(buffs[i].spellid) && (buffs[i].spellid != spell_id) && IsEffectInSpell(buffs[i].spellid, SE_Fc_Cast_Spell_On_Land))) { + if ((IsValidSpell(buffs[i].spellid) && (buffs[i].spellid != spell_id) && IsEffectInSpell(buffs[i].spellid, SpellEffect::Fc_Cast_Spell_On_Land))) { //Step 2: Check if we pass all focus limiters and focus chance roll trigger_spell_id = CalcFocusEffect(focusFcCastSpellOnLand, buffs[i].spellid, spell_id, false, buffs[i].casterid, caster); @@ -9877,18 +9877,18 @@ void Mob::BreakInvisibleSpells() { if(invisible) { nobuff_invisible = 0; - BuffFadeByEffect(SE_Invisibility); - BuffFadeByEffect(SE_Invisibility2); + BuffFadeByEffect(SpellEffect::Invisibility); + BuffFadeByEffect(SpellEffect::Invisibility2); } if(invisible_undead) { ZeroInvisibleVars(InvisType::T_INVISIBLE_VERSE_UNDEAD); - BuffFadeByEffect(SE_InvisVsUndead); - BuffFadeByEffect(SE_InvisVsUndead2); + BuffFadeByEffect(SpellEffect::InvisVsUndead); + BuffFadeByEffect(SpellEffect::InvisVsUndead2); } if(invisible_animals){ ZeroInvisibleVars(InvisType::T_INVISIBLE_VERSE_ANIMAL); - BuffFadeByEffect(SE_ImprovedInvisAnimals); - BuffFadeByEffect(SE_InvisVsAnimals); + BuffFadeByEffect(SpellEffect::ImprovedInvisAnimals); + BuffFadeByEffect(SpellEffect::InvisVsAnimals); } } @@ -9944,8 +9944,8 @@ bool Mob::HarmonySpellLevelCheck(int32 spell_id, Mob *target) } for (int i = 0; i < EFFECT_COUNT; i++) { - // not important to check limit on SE_Lull as it doesnt have one and if the other components won't land, then SE_Lull wont either - if (spells[spell_id].effect_id[i] == SE_ChangeFrenzyRad || spells[spell_id].effect_id[i] == SE_Harmony) { + // not important to check limit on SpellEffect::Lull as it doesnt have one and if the other components won't land, then SpellEffect::Lull wont either + if (spells[spell_id].effect_id[i] == SpellEffect::ChangeFrenzyRad || spells[spell_id].effect_id[i] == SpellEffect::Harmony) { if ((spells[spell_id].max_value[i] != 0 && target->GetLevel() > spells[spell_id].max_value[i]) || target->GetSpecialAbility(SpecialAbility::PacifyImmunity)) { return false; } @@ -9986,14 +9986,14 @@ bool Mob::PassCharmTargetRestriction(Mob *target) { bool Mob::PassLimitToSkill(EQ::skills::SkillType skill, int32 spell_id, int proc_type, int aa_id) { /* - Check if SE_AddMeleProc or SE_RangedProc have a skill limiter. Passes automatically if no skill limiters present. + Check if SpellEffect::AddMeleProc or SpellEffect::RangedProc have a skill limiter. Passes automatically if no skill limiters present. */ int32 proc_type_spaid = 0; if (proc_type == ProcType::MELEE_PROC) { - proc_type_spaid = SE_AddMeleeProc; + proc_type_spaid = SpellEffect::AddMeleeProc; } if (proc_type == ProcType::RANGED_PROC) { - proc_type_spaid = SE_RangedProc; + proc_type_spaid = SpellEffect::RangedProc; } bool match_proc_type = false; @@ -10009,7 +10009,7 @@ bool Mob::PassLimitToSkill(EQ::skills::SkillType skill, int32 spell_id, int proc if (spells[spell_id].effect_id[i] == proc_type_spaid) { match_proc_type = true; } - if (match_proc_type && spells[spell_id].effect_id[i] == SE_LimitToSkill && spells[spell_id].base_value[i] <= EQ::skills::HIGHEST_SKILL) { + if (match_proc_type && spells[spell_id].effect_id[i] == SpellEffect::LimitToSkill && spells[spell_id].base_value[i] <= EQ::skills::HIGHEST_SKILL) { has_limit_check = true; if (spells[spell_id].base_value[i] == skill) { @@ -10046,7 +10046,7 @@ bool Mob::PassLimitToSkill(EQ::skills::SkillType skill, int32 spell_id, int proc match_proc_type = true; } - if (match_proc_type && effect.effect_id == SE_LimitToSkill && effect.base_value <= EQ::skills::HIGHEST_SKILL) { + if (match_proc_type && effect.effect_id == SpellEffect::LimitToSkill && effect.base_value <= EQ::skills::HIGHEST_SKILL) { has_limit_check = true; if (effect.base_value == skill) { return true; @@ -10114,11 +10114,11 @@ bool Mob::NegateSpellEffect(uint16 spell_id, int effect_id) for (int i = 0; i < GetMaxTotalSlots(); i++) { //Check for any buffs containing NegateEffect - if (IsValidSpell(buffs[i].spellid) && IsEffectInSpell(buffs[i].spellid, SE_NegateSpellEffect) && spell_id != buffs[i].spellid) { + if (IsValidSpell(buffs[i].spellid) && IsEffectInSpell(buffs[i].spellid, SpellEffect::NegateSpellEffect) && spell_id != buffs[i].spellid) { //Match each of the negate effects with the current spell effect, if found, that effect will not be applied. for (int j = 0; j < EFFECT_COUNT; j++) { - if (spells[buffs[i].spellid].effect_id[j] == SE_NegateSpellEffect && + if (spells[buffs[i].spellid].effect_id[j] == SpellEffect::NegateSpellEffect && spells[buffs[i].spellid].limit_value[j] == effect_id && (spells[buffs[i].spellid].base_value[j] == NEGATE_SPA_ALL_BONUSES || spells[buffs[i].spellid].base_value[j] == NEGATE_SPA_SPELLBONUS || @@ -10144,7 +10144,7 @@ int Mob::GetMemoryBlurChance(int base_chance) Memory blur is applied to mez on initial cast using same formula. However, recasting on a target that is already mezed will not give a chance to memory blur. The blur is not checked on buff ticks. - SPA 242 SE_IncreaseChanceMemwipe modifies the final chance after all bonuses are applied. + SPA 242 SpellEffect::IncreaseChanceMemwipe modifies the final chance after all bonuses are applied. This is also applied to memory blur from mez spells. this = caster @@ -10251,7 +10251,7 @@ void Mob::SpreadVirusEffect(int32 spell_id, uint32 caster_id, int32 buff_tics_re bool Mob::IsFocusProcLimitTimerActive(int32 focus_spell_id) { /* - Used with SPA 511 SE_Ff_FocusTimerMin to limit how often a focus effect can be applied. + Used with SPA 511 SpellEffect::Ff_FocusTimerMin to limit how often a focus effect can be applied. Ie. Can only have a spell trigger once every 15 seconds, or to be more creative can only have the fire spells received a very high special focused once every 30 seconds. Note, this stores timers for both spell, item and AA related focuses For AA the focus_spell_id @@ -10293,7 +10293,7 @@ void Mob::SetFocusProcLimitTimer(int32 focus_spell_id, uint32 focus_reuse_time) bool Mob::IsProcLimitTimerActive(int32 base_spell_id, uint32 proc_reuse_time, int proc_type) { /* - Used with SPA 512 SE_Proc_Timer_Modifier to limit how often a proc can be cast. + Used with SPA 512 SpellEffect::Proc_Timer_Modifier to limit how often a proc can be cast. If this effect exists it will prevent the next proc from firing until the timer defined in SPA 512 is finished. Ie. 1 proc every 55 seconds. Spell, Ranged, and Defensive procs all have their own timer array, therefore @@ -10428,7 +10428,7 @@ void Mob::ApplyIllusionToCorpse(int32 spell_id, Corpse* new_corpse) { } for (int i = 0; i < EFFECT_COUNT; i++){ - if (spells[spell_id].effect_id[i] == SE_Illusion) { + if (spells[spell_id].effect_id[i] == SpellEffect::Illusion) { new_corpse->ApplySpellEffectIllusion(spell_id, nullptr, -1, spells[spell_id].base_value[i], spells[spell_id].limit_value[i], spells[spell_id].max_value[i]); return; } @@ -10594,7 +10594,7 @@ bool Mob::HasPersistDeathIllusion(int32 spell_id) { if ( spell_id != SPELL_MINOR_ILLUSION && spell_id != SPELL_ILLUSION_TREE && - IsEffectInSpell(spell_id, SE_Illusion) && + IsEffectInSpell(spell_id, SpellEffect::Illusion) && IsBeneficialSpell(spell_id) ) { return true; diff --git a/zone/spells.cpp b/zone/spells.cpp index f34914b558..c37fa4467d 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -218,11 +218,11 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, //It appears that the Sanctuary effect is removed by a check on the client side (keep this however for redundancy) if (spellbonuses.Sanctuary && (spells[spell_id].target_type != ST_Self && GetTarget() != this) || IsDetrimentalSpell(spell_id)) { - BuffFadeByEffect(SE_Sanctuary); + BuffFadeByEffect(SpellEffect::Sanctuary); } if (spellbonuses.NegateIfCombat) { - BuffFadeByEffect(SE_NegateIfCombat); + BuffFadeByEffect(SpellEffect::NegateIfCombat); } if(GetTarget() && IsManaTapSpell(spell_id)) { @@ -696,7 +696,7 @@ bool Mob::DoCastingChecksZoneRestrictions(bool check_on_casting, int32 spell_id) }, // Levitation restriction { - [&]() { return !bypass_casting_restrictions && !zone->CanLevitate() && IsEffectInSpell(spell_id, SE_Levitate); }, + [&]() { return !bypass_casting_restrictions && !zone->CanLevitate() && IsEffectInSpell(spell_id, SpellEffect::Levitate); }, [&]() { if (gm_bypass_message("zone levitation restrictions")) { return true; } Message(Chat::Red, "You have entered an area where levitation effects do not function."); @@ -858,7 +858,7 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp /* Cannot cast shield target on self */ - if (this == spell_target && IsEffectInSpell(spell_id, SE_Shield_Target)) { + if (this == spell_target && IsEffectInSpell(spell_id, SpellEffect::Shield_Target)) { LogSpells("You cannot shield yourself"); Message(Chat::SpellFailure, "You cannot shield yourself."); return false; @@ -890,7 +890,7 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp /* Various charm related target restrictions */ - if (IsEffectInSpell(spell_id, SE_Charm) && !PassCharmTargetRestriction(spell_target)) { + if (IsEffectInSpell(spell_id, SpellEffect::Charm) && !PassCharmTargetRestriction(spell_target)) { LogSpells("Spell casting canceled [{}] : can not use charm on this target.", spell_id); return false; } @@ -1669,7 +1669,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo // handle the components for traditional casters else { - if (!RuleB(Character, PetsUseReagents) && (IsEffectInSpell(spell_id, SE_SummonPet) || IsEffectInSpell(spell_id, SE_NecPet)) || + if (!RuleB(Character, PetsUseReagents) && (IsEffectInSpell(spell_id, SpellEffect::SummonPet) || IsEffectInSpell(spell_id, SpellEffect::NecPet)) || (IsBardSong(spell_id) && (slot == CastingSlot::Item|| slot == CastingSlot::PotionBelt))) { //bypass reagent cost } @@ -1706,7 +1706,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo return; } } - else if (!RuleB(Character, PetsUseReagents) && (IsEffectInSpell(spell_id, SE_SummonPet) || IsEffectInSpell(spell_id, SE_NecPet))) { + else if (!RuleB(Character, PetsUseReagents) && (IsEffectInSpell(spell_id, SpellEffect::SummonPet) || IsEffectInSpell(spell_id, SpellEffect::NecPet))) { //bypass reagent cost } else if (!bard_song_mode) @@ -1922,7 +1922,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce case ST_Self: { bool bot_can_summon_corpse = IsBot() && - IsEffectInSpell(spell_id, SE_SummonCorpse) && + IsEffectInSpell(spell_id, SpellEffect::SummonCorpse) && RuleB(Bots, AllowCommandedSummonCorpse); if (!bot_can_summon_corpse) { @@ -2878,7 +2878,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in ApplyHealthTransferDamage(this, target, spell_id); //This needs to be here for bind sight to update correctly on client. - if (IsClient() && IsEffectInSpell(spell_id, SE_BindSight)) { + if (IsClient() && IsEffectInSpell(spell_id, SpellEffect::BindSight)) { for (int i = 0; i < GetMaxTotalSlots(); i++) { if (buffs[i].spellid == spell_id) { CastToClient()->SendBuffNumHitPacket(buffs[i], i);//its hack, it works. @@ -2911,7 +2911,7 @@ bool Mob::ApplyBardPulse(int32 spell_id, Mob *spell_target, CastingSlot slot) { Bard song charm that have no mana will continue to try and pulse on target, but will only reapply when charm fades. Live does not spam client with do not take hold messages. Checking here avoids that from happening. Only try to reapply if charm fades. */ - if (spell_target->IsCharmed() && spells[spell_id].mana == 0 && spell_target->GetOwner() == this && IsEffectInSpell(spell_id, SE_Charm)) { + if (spell_target->IsCharmed() && spells[spell_id].mana == 0 && spell_target->GetOwner() == this && IsEffectInSpell(spell_id, SpellEffect::Charm)) { if (IsClient()) { CastToClient()->CheckSongSkillIncrease(spell_id); } @@ -2992,7 +2992,7 @@ int Mob::CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caste ) && spell_id != SPELL_MINOR_ILLUSION && spell_id != SPELL_ILLUSION_TREE && - IsEffectInSpell(spell_id, SE_Illusion) + IsEffectInSpell(spell_id, SpellEffect::Illusion) ) { res = 10000; // ~16h override } @@ -3104,7 +3104,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, return 0; } - if (spellbonuses.CompleteHealBuffBlocker && IsEffectInSpell(spellid2, SE_CompleteHeal)) { + if (spellbonuses.CompleteHealBuffBlocker && IsEffectInSpell(spellid2, SpellEffect::CompleteHeal)) { Message(0, "You must wait before you can be affected by this spell again."); return -1; } @@ -3116,9 +3116,9 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, return -1; } - if (!IsStackableDOT(spellid1) && !IsEffectInSpell(spellid1, SE_ManaBurn)) { // mana burn spells we need to use the stacking command blocks live actually checks those first, we should probably rework to that too + if (!IsStackableDOT(spellid1) && !IsEffectInSpell(spellid1, SpellEffect::ManaBurn)) { // mana burn spells we need to use the stacking command blocks live actually checks those first, we should probably rework to that too if (caster_level1 > caster_level2) { // cur buff higher level than new - if (IsEffectInSpell(spellid1, SE_ImprovedTaunt)) { + if (IsEffectInSpell(spellid1, SpellEffect::ImprovedTaunt)) { LogSpells("SE_ImprovedTaunt level exception, overwriting"); return 1; } else { @@ -3162,12 +3162,12 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, if (spellid1 != spellid2) { for (i = 0; i < EFFECT_COUNT; i++) { // we don't want this optimization for mana burns - if (sp1.effect_id[i] != sp2.effect_id[i] || sp1.effect_id[i] == SE_ManaBurn) { + if (sp1.effect_id[i] != sp2.effect_id[i] || sp1.effect_id[i] == SpellEffect::ManaBurn) { effect_match = false; break; } } - } else if (IsEffectInSpell(spellid1, SE_ManaBurn)) { + } else if (IsEffectInSpell(spellid1, SpellEffect::ManaBurn)) { LogSpells("We have a Mana Burn spell that is the same, they won't stack"); return -1; } @@ -3181,7 +3181,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, effect2 = sp2.effect_id[i]; if (spellbonuses.Screech == 1) { - if (effect2 == SE_Screech && sp2.base_value[i] == -1) { + if (effect2 == SpellEffect::Screech && sp2.base_value[i] == -1) { MessageString(Chat::SpellFailure, SCREECH_BUFF_BLOCK, sp2.name); return -1; } @@ -3194,32 +3194,32 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, is not fully removed at the time of the trigger */ if (spellbonuses.AStacker[SBIndex::BUFFSTACKER_EXISTS]) { - if ((effect2 == SE_AStacker) && (sp2.effect_id[i] <= spellbonuses.AStacker[SBIndex::BUFFSTACKER_VALUE])) + if ((effect2 == SpellEffect::AStacker) && (sp2.effect_id[i] <= spellbonuses.AStacker[SBIndex::BUFFSTACKER_VALUE])) return -1; } if (spellbonuses.BStacker[SBIndex::BUFFSTACKER_EXISTS]) { - if ((effect2 == SE_BStacker) && (sp2.effect_id[i] <= spellbonuses.BStacker[SBIndex::BUFFSTACKER_VALUE])) + if ((effect2 == SpellEffect::BStacker) && (sp2.effect_id[i] <= spellbonuses.BStacker[SBIndex::BUFFSTACKER_VALUE])) return -1; - if ((effect2 == SE_AStacker) && (!IsCastOnFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_BStacker))) + if ((effect2 == SpellEffect::AStacker) && (!IsCastOnFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SpellEffect::BStacker))) return -1; } if (spellbonuses.CStacker[SBIndex::BUFFSTACKER_EXISTS]) { - if ((effect2 == SE_CStacker) && (sp2.effect_id[i] <= spellbonuses.CStacker[SBIndex::BUFFSTACKER_VALUE])) + if ((effect2 == SpellEffect::CStacker) && (sp2.effect_id[i] <= spellbonuses.CStacker[SBIndex::BUFFSTACKER_VALUE])) return -1; - if ((effect2 == SE_BStacker) && (!IsCastOnFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_CStacker))) + if ((effect2 == SpellEffect::BStacker) && (!IsCastOnFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SpellEffect::CStacker))) return -1; } if (spellbonuses.DStacker[SBIndex::BUFFSTACKER_EXISTS]) { - if ((effect2 == SE_DStacker) && (sp2.effect_id[i] <= spellbonuses.DStacker[SBIndex::BUFFSTACKER_VALUE])) + if ((effect2 == SpellEffect::DStacker) && (sp2.effect_id[i] <= spellbonuses.DStacker[SBIndex::BUFFSTACKER_VALUE])) return -1; - if ((effect2 == SE_CStacker) && (!IsCastOnFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_DStacker))) + if ((effect2 == SpellEffect::CStacker) && (!IsCastOnFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SpellEffect::DStacker))) return -1; } - if(effect2 == SE_StackingCommand_Overwrite) + if(effect2 == SpellEffect::StackingCommand_Overwrite) { overwrite_effect = sp2.base_value[i]; overwrite_slot = sp2.formula[i] - 201; //they use base 1 for slots, we use base 0 @@ -3247,7 +3247,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, sp2.name, spellid2, overwrite_effect, overwrite_slot, overwrite_below_value); } - } else if (effect1 == SE_StackingCommand_Block) + } else if (effect1 == SpellEffect::StackingCommand_Block) { blocked_effect = sp1.base_value[i]; blocked_slot = sp1.formula[i] - 201; @@ -3324,7 +3324,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, // negative AC affects are skipped. Ex. Sun's Corona and Glacier Breath should stack // There may be more SPAs we need to add here .... // The client does just check base rather than calculating the affect change value. - if ((effect1 == SE_ArmorClass || effect1 == SE_ACv2) && sp2.base_value[i] < 0) + if ((effect1 == SpellEffect::ArmorClass || effect1 == SpellEffect::ACv2) && sp2.base_value[i] < 0) continue; /* @@ -3332,13 +3332,13 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, If Caster1 isn't the same as Caster2 and the effect is a DoT then ignore it. */ if(IsNPC() && caster1 && caster2 && caster1 != caster2) { - if(effect1 == SE_CurrentHP && sp1_detrimental && sp2_detrimental) { + if(effect1 == SpellEffect::CurrentHP && sp1_detrimental && sp2_detrimental) { LogSpells("Both casters exist and are not the same, the effect is a detrimental dot, moving on"); continue; } } - if(effect1 == SE_CompleteHeal){ //SE_CompleteHeal never stacks or overwrites ever, always block. + if(effect1 == SpellEffect::CompleteHeal){ //SE_CompleteHeal never stacks or overwrites ever, always block. LogSpells("Blocking spell because complete heal never stacks or overwries"); return (-1); } @@ -3347,7 +3347,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, If the spells aren't the same and the effect is a dot we can go ahead and stack it */ - if(effect1 == SE_CurrentHP && spellid1 != spellid2 && sp1_detrimental && sp2_detrimental) { + if(effect1 == SpellEffect::CurrentHP && spellid1 != spellid2 && sp1_detrimental && sp2_detrimental) { LogSpells("The spells are not the same and it is a detrimental dot, passing"); continue; } @@ -3356,7 +3356,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, sp2_value = CalcSpellEffectValue(spellid2, i, caster_level2); // Spells like SoW won't stack if a snare effect is already in place. - if (effect2 == SE_MovementSpeed && effect1 == SE_MovementSpeed) { + if (effect2 == SpellEffect::MovementSpeed && effect1 == SpellEffect::MovementSpeed) { if (sp1_value < 0 && sp2_value > 0) { return -1; } else if (sp2_value < 0 && sp1_value > 0) { @@ -3366,7 +3366,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, // DoTs won't overwrite regeneration but will block regeneration spells. if (spells[spellid1].buff_duration > 0 && spells[spellid2].buff_duration > 0 && - effect1 == SE_CurrentHP && effect2 == SE_CurrentHP) { + effect1 == SpellEffect::CurrentHP && effect2 == SpellEffect::CurrentHP) { if (!sp1_detrimental && sp2_detrimental) { continue; } else if (sp1_detrimental && !sp2_detrimental) { @@ -3378,8 +3378,8 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, // have a value that's a percentage for instance if ( - effect1 == SE_AttackSpeed || - effect1 == SE_AttackSpeed2 + effect1 == SpellEffect::AttackSpeed || + effect1 == SpellEffect::AttackSpeed2 ) { sp1_value -= 100; @@ -3929,7 +3929,7 @@ bool Mob::SpellOnTarget( IsDetrimentalSpell(spell_id) && !IsAttackAllowed(spelltar, true) && !IsResurrectionEffects(spell_id) && - !IsEffectInSpell(spell_id, SE_BindSight) + !IsEffectInSpell(spell_id, SpellEffect::BindSight) ) { if (!IsClient() || !CastToClient()->GetGM()) { MessageString(Chat::SpellFailure, SPELL_NO_HOLD); @@ -3997,7 +3997,7 @@ bool Mob::SpellOnTarget( // select target uint16 target_id = 0; - if (IsEffectInSpell(spell_id, SE_BindSight)) { + if (IsEffectInSpell(spell_id, SpellEffect::BindSight)) { action->target = GetID(); target_id = GetID(); } else { @@ -4151,7 +4151,7 @@ bool Mob::SpellOnTarget( // Not sure if all 3 should be stacking //This is not live like behavior (~Kayen confirmed 2/2/22) if (!RuleB(Spells, AllowDoubleInvis) && !IsActiveBardSong(spell_id)) { - if (IsEffectInSpell(spell_id, SE_Invisibility)) { + if (IsEffectInSpell(spell_id, SpellEffect::Invisibility)) { if (spelltar->invisible) { spelltar->MessageString(Chat::SpellFailure, ALREADY_INVIS, GetCleanName()); safe_delete(action_packet); @@ -4159,7 +4159,7 @@ bool Mob::SpellOnTarget( } } - if (IsEffectInSpell(spell_id, SE_InvisVsUndead)) { + if (IsEffectInSpell(spell_id, SpellEffect::InvisVsUndead)) { if (spelltar->invisible_undead) { spelltar->MessageString(Chat::SpellFailure, ALREADY_INVIS, GetCleanName()); safe_delete(action_packet); @@ -4167,7 +4167,7 @@ bool Mob::SpellOnTarget( } } - if (IsEffectInSpell(spell_id, SE_InvisVsAnimals)) { + if (IsEffectInSpell(spell_id, SpellEffect::InvisVsAnimals)) { if (spelltar->invisible_animals) { spelltar->MessageString(Chat::SpellFailure, ALREADY_INVIS, GetCleanName()); safe_delete(action_packet); @@ -4276,7 +4276,7 @@ bool Mob::SpellOnTarget( } else if ( !IsAttackAllowed(spelltar, true) && !IsResurrectionEffects(spell_id) && - !IsEffectInSpell(spell_id, SE_BindSight) + !IsEffectInSpell(spell_id, SpellEffect::BindSight) ) { // Detrimental spells - PVP check LogSpells( "Detrimental spell [{}] can't take hold [{}] -> [{}]", @@ -4334,7 +4334,7 @@ bool Mob::SpellOnTarget( int buff_count = GetMaxTotalSlots(); int focus = 0; for (int b = 0; b < buff_count; b++) { - if (IsEffectInSpell(buffs[b].spellid, SE_BlockNextSpellFocus)) { + if (IsEffectInSpell(buffs[b].spellid, SpellEffect::BlockNextSpellFocus)) { focus = CalcFocusEffect(focusBlockNextSpell, buffs[b].spellid, spell_id); if (focus) { CheckNumHitsRemaining(NumHit::MatchingSpells, b); @@ -4629,7 +4629,7 @@ bool Mob::SpellOnTarget( return false; } - //Check SE_Fc_Cast_Spell_On_Land SPA 481 on target, if hit by this spell and Conditions are Met then target will cast the specified spell. + //Check SpellEffect::Fc_Cast_Spell_On_Land SPA 481 on target, if hit by this spell and Conditions are Met then target will cast the specified spell. if (spelltar) { spelltar->CastSpellOnLand(this, spell_id); } @@ -4677,11 +4677,11 @@ bool Mob::SpellOnTarget( } } - if (spelltar->IsClient() && IsEffectInSpell(spell_id, SE_ShadowStep)) { + if (spelltar->IsClient() && IsEffectInSpell(spell_id, SpellEffect::ShadowStep)) { spelltar->CastToClient()->cheat_manager.SetExemptStatus(ShadowStep, true); } - if (!IsEffectInSpell(spell_id, SE_BindAffinity)) { + if (!IsEffectInSpell(spell_id, SpellEffect::BindAffinity)) { if (spelltar != this && spelltar->IsClient()) {// send to target spelltar->CastToClient()->QueuePacket(action_packet); } @@ -4704,7 +4704,7 @@ bool Mob::SpellOnTarget( if ( !IsLifetapSpell(spell_id) && - !IsEffectInSpell(spell_id, SE_BindAffinity) && + !IsEffectInSpell(spell_id, SpellEffect::BindAffinity) && !IsAENukeSpell(spell_id) && !IsDamageSpell(spell_id) ) { @@ -4727,7 +4727,7 @@ bool Mob::SpellOnTarget( However due to server thinking your healed, you are unable to correct it by healing. Solution: You need to resend the HP update after buff completed and action packet resent. */ - if ((IsEffectInSpell(spell_id, SE_TotalHP) || IsEffectInSpell(spell_id, SE_MaxHPChange)) && (IsEffectInSpell(spell_id, SE_CurrentHPOnce) || IsEffectInSpell(spell_id, SE_CurrentHP))) { + if ((IsEffectInSpell(spell_id, SpellEffect::TotalHP) || IsEffectInSpell(spell_id, SpellEffect::MaxHPChange)) && (IsEffectInSpell(spell_id, SpellEffect::CurrentHPOnce) || IsEffectInSpell(spell_id, SpellEffect::CurrentHP))) { SendHPUpdate(true); } @@ -5096,7 +5096,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) } // check max level for spell - effect_index = GetSpellEffectIndex(spell_id, SE_Mez); + effect_index = GetSpellEffectIndex(spell_id, SpellEffect::Mez); assert(effect_index >= 0); // NPCs get to ignore the max level if((GetLevel() > spells[spell_id].max_value[effect_index]) && @@ -5110,7 +5110,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) } // slow and haste spells - if(GetSpecialAbility(SpecialAbility::SlowImmunity) && IsEffectInSpell(spell_id, SE_AttackSpeed)) + if(GetSpecialAbility(SpecialAbility::SlowImmunity) && IsEffectInSpell(spell_id, SpellEffect::AttackSpeed)) { LogSpells("We are immune to Slow spells"); caster->MessageString(Chat::Red, IMMUNE_ATKSPEED); @@ -5124,9 +5124,9 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) } // client vs client fear - if(IsEffectInSpell(spell_id, SE_Fear)) + if(IsEffectInSpell(spell_id, SpellEffect::Fear)) { - effect_index = GetSpellEffectIndex(spell_id, SE_Fear); + effect_index = GetSpellEffectIndex(spell_id, SpellEffect::Fear); if(GetSpecialAbility(SpecialAbility::FearImmunity)) { LogSpells("We are immune to Fear spells"); caster->MessageString(Chat::Red, IMMUNE_FEAR); // need to verify message type, not in MQ2Cast for easy look up @@ -5190,7 +5190,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) if(!caster->IsNPC()) { // check level limit of charm spell - effect_index = GetSpellEffectIndex(spell_id, SE_Charm); + effect_index = GetSpellEffectIndex(spell_id, SpellEffect::Charm); assert(effect_index >= 0); if(GetLevel() > spells[spell_id].max_value[effect_index] && spells[spell_id].max_value[effect_index] != 0) { @@ -5211,8 +5211,8 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) if ( - IsEffectInSpell(spell_id, SE_Root) || - IsEffectInSpell(spell_id, SE_MovementSpeed) + IsEffectInSpell(spell_id, SpellEffect::Root) || + IsEffectInSpell(spell_id, SpellEffect::MovementSpeed) ) { if(GetSpecialAbility(SpecialAbility::SnareImmunity)) { diff --git a/zone/tune.cpp b/zone/tune.cpp index 39d6e9bdb2..6f94d7bbdb 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -466,12 +466,12 @@ void Mob::TuneGetAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ch if (loop_add_avoid >= 0) { Message(0, "[#Tune] OPTION1: MODIFY Client Heroic AGI or Avoidance Mod2 stat by [+ %i ]", loop_add_avoid); - Message(0, "[#Tune] OPTION2: Give CLIENT an evasion bonus using SPA 172 Evasion SE_AvoidMeleeChance from (spells/items/aa) of [+ %i pct ]", evasion_bonus); + Message(0, "[#Tune] OPTION2: Give CLIENT an evasion bonus using SPA 172 Evasion SpellEffect::AvoidMeleeChance from (spells/items/aa) of [+ %i pct ]", evasion_bonus); } else { Message(0, "[#Tune] OPTION1: MODIFY Client Heroic AGI or Avoidance Mod2 stat by [ %i ]", loop_add_avoid); - Message(0, "[#Tune] OPTION2: Give CLIENT an evasion bonus using SPA 172 Evasion SE_AvoidMeleeChance from (spells/items/aa) of [ %i pct ]", evasion_bonus); + Message(0, "[#Tune] OPTION2: Give CLIENT an evasion bonus using SPA 172 Evasion SpellEffect::AvoidMeleeChance from (spells/items/aa) of [ %i pct ]", evasion_bonus); } Message(0, "###################COMPLETE###################"); @@ -1283,7 +1283,7 @@ int64 Mob::Tunecompute_tohit(EQ::skills::SkillType skillinuse, int accuracy_over // return -1 in cases that always hit int64 Mob::TuneGetTotalToHit(EQ::skills::SkillType skill, int chance_mod, int accuracy_override, int add_accuracy) { - if (chance_mod >= 10000) // override for stuff like SE_SkillAttack + if (chance_mod >= 10000) // override for stuff like SpellEffect::SkillAttack return -1; // calculate attacker's accuracy @@ -1313,7 +1313,7 @@ int64 Mob::TuneGetTotalToHit(EQ::skills::SkillType skill, int chance_mod, int ac if (atkhit_bonus) accuracy += round(static_cast(accuracy) * static_cast(atkhit_bonus) * 0.0001); - // 216 Melee Accuracy Amt aka SE_Accuracy -- flat bonus + // 216 Melee Accuracy Amt aka SpellEffect::Accuracy -- flat bonus accuracy += itembonuses.Accuracy[EQ::skills::HIGHEST_SKILL + 1] + aabonuses.Accuracy[EQ::skills::HIGHEST_SKILL + 1] + spellbonuses.Accuracy[EQ::skills::HIGHEST_SKILL + 1] + @@ -1335,7 +1335,7 @@ int64 Mob::TuneGetTotalToHit(EQ::skills::SkillType skill, int chance_mod, int ac if (spellbonuses.HitChanceEffect[EQ::skills::HIGHEST_SKILL + 1] >= 10000) return -1; - // 184 Accuracy % aka SE_HitChance -- percentage increase + // 184 Accuracy % aka SpellEffect::HitChance -- percentage increase auto hit_bonus = itembonuses.HitChanceEffect[EQ::skills::HIGHEST_SKILL + 1] + aabonuses.HitChanceEffect[EQ::skills::HIGHEST_SKILL + 1] + spellbonuses.HitChanceEffect[EQ::skills::HIGHEST_SKILL + 1] + @@ -1360,15 +1360,15 @@ int64 Mob::TuneGetTotalDefense(int avoidance_override, int add_avoidance) if (evasion_bonus >= 10000) return -1; - // 515 SE_AC_Avoidance_Max_Percent + // 515 SpellEffect::AC_Avoidance_Max_Percent auto ac_aviodance_bonus = itembonuses.AC_Avoidance_Max_Percent + aabonuses.AC_Avoidance_Max_Percent + spellbonuses.AC_Avoidance_Max_Percent; if (ac_aviodance_bonus) avoidance += round(static_cast(avoidance) * static_cast(ac_aviodance_bonus) * 0.0001); - // 172 Evasion aka SE_AvoidMeleeChance + // 172 Evasion aka SpellEffect::AvoidMeleeChance evasion_bonus += itembonuses.AvoidMeleeChanceEffect + aabonuses.AvoidMeleeChanceEffect; // item bonus here isn't mod2 avoidance - // 215 Pet Avoidance % aka SE_PetAvoidance + // 215 Pet Avoidance % aka SpellEffect::PetAvoidance evasion_bonus += GetPetAvoidanceBonusFromOwner(); // Evasion is a percentage bonus according to AA descriptions @@ -1410,7 +1410,7 @@ int64 Mob::Tunecompute_defense(int avoidance_override, int add_avoidance) } - //516 SE_AC_Mitigation_Max_Percent + //516 SpellEffect::AC_Mitigation_Max_Percent auto ac_bonus = itembonuses.AC_Mitigation_Max_Percent + aabonuses.AC_Mitigation_Max_Percent + spellbonuses.AC_Mitigation_Max_Percent; if (ac_bonus) { defense += round(static_cast(defense) * static_cast(ac_bonus) * 0.0001); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 7643e0e278..747302e24e 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -957,7 +957,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) LogSpells("[WorldServer::HandleMessage] Found corpse. Marking corpse as rezzed if needed"); // I don't know why Rezzed is not set to true in CompleteRezz(). - if (!IsEffectInSpell(srs->rez.spellid, SE_SummonToCorpse)) { + if (!IsEffectInSpell(srs->rez.spellid, SpellEffect::SummonToCorpse)) { corpse->IsRezzed(true); corpse->CompleteResurrection(); } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 7cd66a8363..0dc1436750 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3009,12 +3009,12 @@ void ZoneDatabase::LoadBuffs(Client *client) continue; } - if (IsEffectInSpell(buffs[slot_id].spellid, SE_Charm)) { + if (IsEffectInSpell(buffs[slot_id].spellid, SpellEffect::Charm)) { buffs[slot_id].spellid = SPELL_UNKNOWN; break; } - if (IsEffectInSpell(buffs[slot_id].spellid, SE_Illusion)) { + if (IsEffectInSpell(buffs[slot_id].spellid, SpellEffect::Illusion)) { if (buffs[slot_id].persistant_buff) { break; } From ba78394ce94d85b598c951f3cf681f9086e815a2 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 30 Aug 2025 15:42:04 -0400 Subject: [PATCH 034/194] [Repositories] Convert Spell Loading to Repositories (#4996) --- common/database/database_update_manifest.cpp | 19 + .../base/base_spells_new_repository.h | 2040 ++++++++--------- common/shareddb.cpp | 421 ++-- common/spdat.h | 1 - common/version.h | 2 +- 5 files changed, 1279 insertions(+), 1204 deletions(-) diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index f6eddc69b5..2236b4ab94 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -7171,6 +7171,25 @@ ALTER TABLE `character_stats_record` ADD COLUMN `heal_amount` int(11) NULL DEFAULT 0 AFTER `spell_damage`; )" }, + ManifestEntry{ + .version = 9328, + .description = "2025_08_27_spells_new_column_names.sql", + .check = "SHOW COLUMNS FROM `spells_new` LIKE 'feedbackable'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `spells_new` +CHANGE COLUMN `field160` `feedbackable` int(11) NOT NULL DEFAULT 0 AFTER `npc_no_los`, +CHANGE COLUMN `field198` `no_detrimental_spell_aggro` int(11) NOT NULL DEFAULT 0 AFTER `not_extendable`, +CHANGE COLUMN `field209` `no_resist` int(11) NULL DEFAULT 0 AFTER `rank`, +CHANGE COLUMN `field217` `override_crit_chance` int(11) NULL DEFAULT 0 AFTER `field216`, +CHANGE COLUMN `field220` `no_heal_damage_item_mod` int(11) NULL DEFAULT 0 AFTER `maxtargets`, +CHANGE COLUMN `field221` `caster_requirement_id` int(11) NULL DEFAULT 0 AFTER `no_heal_damage_item_mod`, +CHANGE COLUMN `field222` `spell_class` int(11) NULL DEFAULT 0 AFTER `caster_requirement_id`, +CHANGE COLUMN `field223` `spell_subclass` int(11) NULL DEFAULT 0 AFTER `spell_class`, +CHANGE COLUMN `field232` `no_remove` int(11) NOT NULL DEFAULT 0 AFTER `min_range`; +)" + } // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ diff --git a/common/repositories/base/base_spells_new_repository.h b/common/repositories/base/base_spells_new_repository.h index 019e8eaea0..60a19fb577 100644 --- a/common/repositories/base/base_spells_new_repository.h +++ b/common/repositories/base/base_spells_new_repository.h @@ -179,7 +179,7 @@ class BaseSpellsNewRepository { int32_t effectdescnum; int32_t effectdescnum2; int32_t npc_no_los; - int32_t field160; + int32_t feedbackable; int32_t reflectable; int32_t bonushate; int32_t field163; @@ -217,7 +217,7 @@ class BaseSpellsNewRepository { int32_t ConeStopAngle; int32_t sneaking; int32_t not_extendable; - int32_t field198; + int32_t no_detrimental_spell_aggro; int32_t field199; int32_t suspendable; int32_t viral_range; @@ -228,7 +228,7 @@ class BaseSpellsNewRepository { int32_t field206; int32_t spellgroup; int32_t rank_; - int32_t field209; + int32_t no_resist; int32_t field210; int32_t CastRestriction; int32_t allowrest; @@ -236,13 +236,13 @@ class BaseSpellsNewRepository { int32_t OutofCombat; int32_t field215; int32_t field216; - int32_t field217; + int32_t override_crit_chance; int32_t aemaxtargets; int32_t maxtargets; - int32_t field220; - int32_t field221; - int32_t field222; - int32_t field223; + int32_t no_heal_damage_item_mod; + int32_t caster_requirement_id; + int32_t spell_class; + int32_t spell_subclass; int32_t persistdeath; int32_t field225; int32_t field226; @@ -251,7 +251,7 @@ class BaseSpellsNewRepository { float max_dist; float max_dist_mod; int32_t min_range; - int32_t field232; + int32_t no_remove; int32_t field233; int32_t field234; int32_t field235; @@ -426,7 +426,7 @@ class BaseSpellsNewRepository { "effectdescnum", "effectdescnum2", "npc_no_los", - "field160", + "feedbackable", "reflectable", "bonushate", "field163", @@ -464,7 +464,7 @@ class BaseSpellsNewRepository { "ConeStopAngle", "sneaking", "not_extendable", - "field198", + "no_detrimental_spell_aggro", "field199", "suspendable", "viral_range", @@ -475,7 +475,7 @@ class BaseSpellsNewRepository { "field206", "spellgroup", "`rank`", - "field209", + "no_resist", "field210", "CastRestriction", "allowrest", @@ -483,13 +483,13 @@ class BaseSpellsNewRepository { "OutofCombat", "field215", "field216", - "field217", + "override_crit_chance", "aemaxtargets", "maxtargets", - "field220", - "field221", - "field222", - "field223", + "no_heal_damage_item_mod", + "caster_requirement_id", + "spell_class", + "spell_subclass", "persistdeath", "field225", "field226", @@ -498,7 +498,7 @@ class BaseSpellsNewRepository { "max_dist", "max_dist_mod", "min_range", - "field232", + "no_remove", "field233", "field234", "field235", @@ -669,7 +669,7 @@ class BaseSpellsNewRepository { "effectdescnum", "effectdescnum2", "npc_no_los", - "field160", + "feedbackable", "reflectable", "bonushate", "field163", @@ -707,7 +707,7 @@ class BaseSpellsNewRepository { "ConeStopAngle", "sneaking", "not_extendable", - "field198", + "no_detrimental_spell_aggro", "field199", "suspendable", "viral_range", @@ -718,7 +718,7 @@ class BaseSpellsNewRepository { "field206", "spellgroup", "`rank`", - "field209", + "no_resist", "field210", "CastRestriction", "allowrest", @@ -726,13 +726,13 @@ class BaseSpellsNewRepository { "OutofCombat", "field215", "field216", - "field217", + "override_crit_chance", "aemaxtargets", "maxtargets", - "field220", - "field221", - "field222", - "field223", + "no_heal_damage_item_mod", + "caster_requirement_id", + "spell_class", + "spell_subclass", "persistdeath", "field225", "field226", @@ -741,7 +741,7 @@ class BaseSpellsNewRepository { "max_dist", "max_dist_mod", "min_range", - "field232", + "no_remove", "field233", "field234", "field235", @@ -786,243 +786,243 @@ class BaseSpellsNewRepository { { SpellsNew e{}; - e.id = 0; - e.name = ""; - e.player_1 = "BLUE_TRAIL"; - e.teleport_zone = ""; - e.you_cast = ""; - e.other_casts = ""; - e.cast_on_you = ""; - e.cast_on_other = ""; - e.spell_fades = ""; - e.range_ = 100; - e.aoerange = 0; - e.pushback = 0; - e.pushup = 0; - e.cast_time = 0; - e.recovery_time = 0; - e.recast_time = 0; - e.buffdurationformula = 7; - e.buffduration = 65; - e.AEDuration = 0; - e.mana = 0; - e.effect_base_value1 = 100; - e.effect_base_value2 = 0; - e.effect_base_value3 = 0; - e.effect_base_value4 = 0; - e.effect_base_value5 = 0; - e.effect_base_value6 = 0; - e.effect_base_value7 = 0; - e.effect_base_value8 = 0; - e.effect_base_value9 = 0; - e.effect_base_value10 = 0; - e.effect_base_value11 = 0; - e.effect_base_value12 = 0; - e.effect_limit_value1 = 0; - e.effect_limit_value2 = 0; - e.effect_limit_value3 = 0; - e.effect_limit_value4 = 0; - e.effect_limit_value5 = 0; - e.effect_limit_value6 = 0; - e.effect_limit_value7 = 0; - e.effect_limit_value8 = 0; - e.effect_limit_value9 = 0; - e.effect_limit_value10 = 0; - e.effect_limit_value11 = 0; - e.effect_limit_value12 = 0; - e.max1 = 0; - e.max2 = 0; - e.max3 = 0; - e.max4 = 0; - e.max5 = 0; - e.max6 = 0; - e.max7 = 0; - e.max8 = 0; - e.max9 = 0; - e.max10 = 0; - e.max11 = 0; - e.max12 = 0; - e.icon = 0; - e.memicon = 0; - e.components1 = -1; - e.components2 = -1; - e.components3 = -1; - e.components4 = -1; - e.component_counts1 = 1; - e.component_counts2 = 1; - e.component_counts3 = 1; - e.component_counts4 = 1; - e.NoexpendReagent1 = -1; - e.NoexpendReagent2 = -1; - e.NoexpendReagent3 = -1; - e.NoexpendReagent4 = -1; - e.formula1 = 100; - e.formula2 = 100; - e.formula3 = 100; - e.formula4 = 100; - e.formula5 = 100; - e.formula6 = 100; - e.formula7 = 100; - e.formula8 = 100; - e.formula9 = 100; - e.formula10 = 100; - e.formula11 = 100; - e.formula12 = 100; - e.LightType = 0; - e.goodEffect = 0; - e.Activated = 0; - e.resisttype = 0; - e.effectid1 = 254; - e.effectid2 = 254; - e.effectid3 = 254; - e.effectid4 = 254; - e.effectid5 = 254; - e.effectid6 = 254; - e.effectid7 = 254; - e.effectid8 = 254; - e.effectid9 = 254; - e.effectid10 = 254; - e.effectid11 = 254; - e.effectid12 = 254; - e.targettype = 2; - e.basediff = 0; - e.skill = 98; - e.zonetype = -1; - e.EnvironmentType = 0; - e.TimeOfDay = 0; - e.classes1 = 255; - e.classes2 = 255; - e.classes3 = 255; - e.classes4 = 255; - e.classes5 = 255; - e.classes6 = 255; - e.classes7 = 255; - e.classes8 = 255; - e.classes9 = 255; - e.classes10 = 255; - e.classes11 = 255; - e.classes12 = 255; - e.classes13 = 255; - e.classes14 = 255; - e.classes15 = 255; - e.classes16 = 255; - e.CastingAnim = 44; - e.TargetAnim = 13; - e.TravelType = 0; - e.SpellAffectIndex = -1; - e.disallow_sit = 0; - e.deities0 = 0; - e.deities1 = 0; - e.deities2 = 0; - e.deities3 = 0; - e.deities4 = 0; - e.deities5 = 0; - e.deities6 = 0; - e.deities7 = 0; - e.deities8 = 0; - e.deities9 = 0; - e.deities10 = 0; - e.deities11 = 0; - e.deities12 = 0; - e.deities13 = 0; - e.deities14 = 0; - e.deities15 = 0; - e.deities16 = 0; - e.field142 = 100; - e.field143 = 0; - e.new_icon = 161; - e.spellanim = 0; - e.uninterruptable = 0; - e.ResistDiff = -150; - e.dot_stacking_exempt = 0; - e.deleteable = 0; - e.RecourseLink = 0; - e.no_partial_resist = 0; - e.field152 = 0; - e.field153 = 0; - e.short_buff_box = -1; - e.descnum = 0; - e.typedescnum = 0; - e.effectdescnum = 0; - e.effectdescnum2 = 0; - e.npc_no_los = 0; - e.field160 = 0; - e.reflectable = 0; - e.bonushate = 0; - e.field163 = 100; - e.field164 = -150; - e.ldon_trap = 0; - e.EndurCost = 0; - e.EndurTimerIndex = 0; - e.IsDiscipline = 0; - e.field169 = 0; - e.field170 = 0; - e.field171 = 0; - e.field172 = 0; - e.HateAdded = 0; - e.EndurUpkeep = 0; - e.numhitstype = 0; - e.numhits = 0; - e.pvpresistbase = -150; - e.pvpresistcalc = 100; - e.pvpresistcap = -150; - e.spell_category = -99; - e.pvp_duration = 0; - e.pvp_duration_cap = 0; - e.pcnpc_only_flag = 0; - e.cast_not_standing = 0; - e.can_mgb = 0; - e.nodispell = -1; - e.npc_category = 0; - e.npc_usefulness = 0; - e.MinResist = 0; - e.MaxResist = 0; - e.viral_targets = 0; - e.viral_timer = 0; - e.nimbuseffect = 0; - e.ConeStartAngle = 0; - e.ConeStopAngle = 0; - e.sneaking = 0; - e.not_extendable = 0; - e.field198 = 0; - e.field199 = 1; - e.suspendable = 0; - e.viral_range = 0; - e.songcap = 0; - e.field203 = 0; - e.field204 = 0; - e.no_block = 0; - e.field206 = -1; - e.spellgroup = 0; - e.rank_ = 0; - e.field209 = 0; - e.field210 = 1; - e.CastRestriction = 0; - e.allowrest = 0; - e.InCombat = 0; - e.OutofCombat = 0; - e.field215 = 0; - e.field216 = 0; - e.field217 = 0; - e.aemaxtargets = 0; - e.maxtargets = 0; - e.field220 = 0; - e.field221 = 0; - e.field222 = 0; - e.field223 = 0; - e.persistdeath = 0; - e.field225 = 0; - e.field226 = 0; - e.min_dist = 0; - e.min_dist_mod = 0; - e.max_dist = 0; - e.max_dist_mod = 0; - e.min_range = 0; - e.field232 = 0; - e.field233 = 0; - e.field234 = 0; - e.field235 = 0; - e.field236 = 0; + e.id = 0; + e.name = ""; + e.player_1 = "BLUE_TRAIL"; + e.teleport_zone = ""; + e.you_cast = ""; + e.other_casts = ""; + e.cast_on_you = ""; + e.cast_on_other = ""; + e.spell_fades = ""; + e.range_ = 100; + e.aoerange = 0; + e.pushback = 0; + e.pushup = 0; + e.cast_time = 0; + e.recovery_time = 0; + e.recast_time = 0; + e.buffdurationformula = 7; + e.buffduration = 65; + e.AEDuration = 0; + e.mana = 0; + e.effect_base_value1 = 100; + e.effect_base_value2 = 0; + e.effect_base_value3 = 0; + e.effect_base_value4 = 0; + e.effect_base_value5 = 0; + e.effect_base_value6 = 0; + e.effect_base_value7 = 0; + e.effect_base_value8 = 0; + e.effect_base_value9 = 0; + e.effect_base_value10 = 0; + e.effect_base_value11 = 0; + e.effect_base_value12 = 0; + e.effect_limit_value1 = 0; + e.effect_limit_value2 = 0; + e.effect_limit_value3 = 0; + e.effect_limit_value4 = 0; + e.effect_limit_value5 = 0; + e.effect_limit_value6 = 0; + e.effect_limit_value7 = 0; + e.effect_limit_value8 = 0; + e.effect_limit_value9 = 0; + e.effect_limit_value10 = 0; + e.effect_limit_value11 = 0; + e.effect_limit_value12 = 0; + e.max1 = 0; + e.max2 = 0; + e.max3 = 0; + e.max4 = 0; + e.max5 = 0; + e.max6 = 0; + e.max7 = 0; + e.max8 = 0; + e.max9 = 0; + e.max10 = 0; + e.max11 = 0; + e.max12 = 0; + e.icon = 0; + e.memicon = 0; + e.components1 = -1; + e.components2 = -1; + e.components3 = -1; + e.components4 = -1; + e.component_counts1 = 1; + e.component_counts2 = 1; + e.component_counts3 = 1; + e.component_counts4 = 1; + e.NoexpendReagent1 = -1; + e.NoexpendReagent2 = -1; + e.NoexpendReagent3 = -1; + e.NoexpendReagent4 = -1; + e.formula1 = 100; + e.formula2 = 100; + e.formula3 = 100; + e.formula4 = 100; + e.formula5 = 100; + e.formula6 = 100; + e.formula7 = 100; + e.formula8 = 100; + e.formula9 = 100; + e.formula10 = 100; + e.formula11 = 100; + e.formula12 = 100; + e.LightType = 0; + e.goodEffect = 0; + e.Activated = 0; + e.resisttype = 0; + e.effectid1 = 254; + e.effectid2 = 254; + e.effectid3 = 254; + e.effectid4 = 254; + e.effectid5 = 254; + e.effectid6 = 254; + e.effectid7 = 254; + e.effectid8 = 254; + e.effectid9 = 254; + e.effectid10 = 254; + e.effectid11 = 254; + e.effectid12 = 254; + e.targettype = 2; + e.basediff = 0; + e.skill = 98; + e.zonetype = -1; + e.EnvironmentType = 0; + e.TimeOfDay = 0; + e.classes1 = 255; + e.classes2 = 255; + e.classes3 = 255; + e.classes4 = 255; + e.classes5 = 255; + e.classes6 = 255; + e.classes7 = 255; + e.classes8 = 255; + e.classes9 = 255; + e.classes10 = 255; + e.classes11 = 255; + e.classes12 = 255; + e.classes13 = 255; + e.classes14 = 255; + e.classes15 = 255; + e.classes16 = 255; + e.CastingAnim = 44; + e.TargetAnim = 13; + e.TravelType = 0; + e.SpellAffectIndex = -1; + e.disallow_sit = 0; + e.deities0 = 0; + e.deities1 = 0; + e.deities2 = 0; + e.deities3 = 0; + e.deities4 = 0; + e.deities5 = 0; + e.deities6 = 0; + e.deities7 = 0; + e.deities8 = 0; + e.deities9 = 0; + e.deities10 = 0; + e.deities11 = 0; + e.deities12 = 0; + e.deities13 = 0; + e.deities14 = 0; + e.deities15 = 0; + e.deities16 = 0; + e.field142 = 100; + e.field143 = 0; + e.new_icon = 161; + e.spellanim = 0; + e.uninterruptable = 0; + e.ResistDiff = -150; + e.dot_stacking_exempt = 0; + e.deleteable = 0; + e.RecourseLink = 0; + e.no_partial_resist = 0; + e.field152 = 0; + e.field153 = 0; + e.short_buff_box = -1; + e.descnum = 0; + e.typedescnum = 0; + e.effectdescnum = 0; + e.effectdescnum2 = 0; + e.npc_no_los = 0; + e.feedbackable = 0; + e.reflectable = 0; + e.bonushate = 0; + e.field163 = 100; + e.field164 = -150; + e.ldon_trap = 0; + e.EndurCost = 0; + e.EndurTimerIndex = 0; + e.IsDiscipline = 0; + e.field169 = 0; + e.field170 = 0; + e.field171 = 0; + e.field172 = 0; + e.HateAdded = 0; + e.EndurUpkeep = 0; + e.numhitstype = 0; + e.numhits = 0; + e.pvpresistbase = -150; + e.pvpresistcalc = 100; + e.pvpresistcap = -150; + e.spell_category = -99; + e.pvp_duration = 0; + e.pvp_duration_cap = 0; + e.pcnpc_only_flag = 0; + e.cast_not_standing = 0; + e.can_mgb = 0; + e.nodispell = -1; + e.npc_category = 0; + e.npc_usefulness = 0; + e.MinResist = 0; + e.MaxResist = 0; + e.viral_targets = 0; + e.viral_timer = 0; + e.nimbuseffect = 0; + e.ConeStartAngle = 0; + e.ConeStopAngle = 0; + e.sneaking = 0; + e.not_extendable = 0; + e.no_detrimental_spell_aggro = 0; + e.field199 = 1; + e.suspendable = 0; + e.viral_range = 0; + e.songcap = 0; + e.field203 = 0; + e.field204 = 0; + e.no_block = 0; + e.field206 = -1; + e.spellgroup = 0; + e.rank_ = 0; + e.no_resist = 0; + e.field210 = 1; + e.CastRestriction = 0; + e.allowrest = 0; + e.InCombat = 0; + e.OutofCombat = 0; + e.field215 = 0; + e.field216 = 0; + e.override_crit_chance = 0; + e.aemaxtargets = 0; + e.maxtargets = 0; + e.no_heal_damage_item_mod = 0; + e.caster_requirement_id = 0; + e.spell_class = 0; + e.spell_subclass = 0; + e.persistdeath = 0; + e.field225 = 0; + e.field226 = 0; + e.min_dist = 0; + e.min_dist_mod = 0; + e.max_dist = 0; + e.max_dist_mod = 0; + e.min_range = 0; + e.no_remove = 0; + e.field233 = 0; + e.field234 = 0; + e.field235 = 0; + e.field236 = 0; return e; } @@ -1059,243 +1059,243 @@ class BaseSpellsNewRepository { if (results.RowCount() == 1) { SpellsNew e{}; - e.id = row[0] ? static_cast(atoi(row[0])) : 0; - e.name = row[1] ? row[1] : ""; - e.player_1 = row[2] ? row[2] : "BLUE_TRAIL"; - e.teleport_zone = row[3] ? row[3] : ""; - e.you_cast = row[4] ? row[4] : ""; - e.other_casts = row[5] ? row[5] : ""; - e.cast_on_you = row[6] ? row[6] : ""; - e.cast_on_other = row[7] ? row[7] : ""; - e.spell_fades = row[8] ? row[8] : ""; - e.range_ = row[9] ? static_cast(atoi(row[9])) : 100; - e.aoerange = row[10] ? static_cast(atoi(row[10])) : 0; - e.pushback = row[11] ? static_cast(atoi(row[11])) : 0; - e.pushup = row[12] ? static_cast(atoi(row[12])) : 0; - e.cast_time = row[13] ? static_cast(atoi(row[13])) : 0; - e.recovery_time = row[14] ? static_cast(atoi(row[14])) : 0; - e.recast_time = row[15] ? static_cast(atoi(row[15])) : 0; - e.buffdurationformula = row[16] ? static_cast(atoi(row[16])) : 7; - e.buffduration = row[17] ? static_cast(atoi(row[17])) : 65; - e.AEDuration = row[18] ? static_cast(atoi(row[18])) : 0; - e.mana = row[19] ? static_cast(atoi(row[19])) : 0; - e.effect_base_value1 = row[20] ? static_cast(atoi(row[20])) : 100; - e.effect_base_value2 = row[21] ? static_cast(atoi(row[21])) : 0; - e.effect_base_value3 = row[22] ? static_cast(atoi(row[22])) : 0; - e.effect_base_value4 = row[23] ? static_cast(atoi(row[23])) : 0; - e.effect_base_value5 = row[24] ? static_cast(atoi(row[24])) : 0; - e.effect_base_value6 = row[25] ? static_cast(atoi(row[25])) : 0; - e.effect_base_value7 = row[26] ? static_cast(atoi(row[26])) : 0; - e.effect_base_value8 = row[27] ? static_cast(atoi(row[27])) : 0; - e.effect_base_value9 = row[28] ? static_cast(atoi(row[28])) : 0; - e.effect_base_value10 = row[29] ? static_cast(atoi(row[29])) : 0; - e.effect_base_value11 = row[30] ? static_cast(atoi(row[30])) : 0; - e.effect_base_value12 = row[31] ? static_cast(atoi(row[31])) : 0; - e.effect_limit_value1 = row[32] ? static_cast(atoi(row[32])) : 0; - e.effect_limit_value2 = row[33] ? static_cast(atoi(row[33])) : 0; - e.effect_limit_value3 = row[34] ? static_cast(atoi(row[34])) : 0; - e.effect_limit_value4 = row[35] ? static_cast(atoi(row[35])) : 0; - e.effect_limit_value5 = row[36] ? static_cast(atoi(row[36])) : 0; - e.effect_limit_value6 = row[37] ? static_cast(atoi(row[37])) : 0; - e.effect_limit_value7 = row[38] ? static_cast(atoi(row[38])) : 0; - e.effect_limit_value8 = row[39] ? static_cast(atoi(row[39])) : 0; - e.effect_limit_value9 = row[40] ? static_cast(atoi(row[40])) : 0; - e.effect_limit_value10 = row[41] ? static_cast(atoi(row[41])) : 0; - e.effect_limit_value11 = row[42] ? static_cast(atoi(row[42])) : 0; - e.effect_limit_value12 = row[43] ? static_cast(atoi(row[43])) : 0; - e.max1 = row[44] ? static_cast(atoi(row[44])) : 0; - e.max2 = row[45] ? static_cast(atoi(row[45])) : 0; - e.max3 = row[46] ? static_cast(atoi(row[46])) : 0; - e.max4 = row[47] ? static_cast(atoi(row[47])) : 0; - e.max5 = row[48] ? static_cast(atoi(row[48])) : 0; - e.max6 = row[49] ? static_cast(atoi(row[49])) : 0; - e.max7 = row[50] ? static_cast(atoi(row[50])) : 0; - e.max8 = row[51] ? static_cast(atoi(row[51])) : 0; - e.max9 = row[52] ? static_cast(atoi(row[52])) : 0; - e.max10 = row[53] ? static_cast(atoi(row[53])) : 0; - e.max11 = row[54] ? static_cast(atoi(row[54])) : 0; - e.max12 = row[55] ? static_cast(atoi(row[55])) : 0; - e.icon = row[56] ? static_cast(atoi(row[56])) : 0; - e.memicon = row[57] ? static_cast(atoi(row[57])) : 0; - e.components1 = row[58] ? static_cast(atoi(row[58])) : -1; - e.components2 = row[59] ? static_cast(atoi(row[59])) : -1; - e.components3 = row[60] ? static_cast(atoi(row[60])) : -1; - e.components4 = row[61] ? static_cast(atoi(row[61])) : -1; - e.component_counts1 = row[62] ? static_cast(atoi(row[62])) : 1; - e.component_counts2 = row[63] ? static_cast(atoi(row[63])) : 1; - e.component_counts3 = row[64] ? static_cast(atoi(row[64])) : 1; - e.component_counts4 = row[65] ? static_cast(atoi(row[65])) : 1; - e.NoexpendReagent1 = row[66] ? static_cast(atoi(row[66])) : -1; - e.NoexpendReagent2 = row[67] ? static_cast(atoi(row[67])) : -1; - e.NoexpendReagent3 = row[68] ? static_cast(atoi(row[68])) : -1; - e.NoexpendReagent4 = row[69] ? static_cast(atoi(row[69])) : -1; - e.formula1 = row[70] ? static_cast(atoi(row[70])) : 100; - e.formula2 = row[71] ? static_cast(atoi(row[71])) : 100; - e.formula3 = row[72] ? static_cast(atoi(row[72])) : 100; - e.formula4 = row[73] ? static_cast(atoi(row[73])) : 100; - e.formula5 = row[74] ? static_cast(atoi(row[74])) : 100; - e.formula6 = row[75] ? static_cast(atoi(row[75])) : 100; - e.formula7 = row[76] ? static_cast(atoi(row[76])) : 100; - e.formula8 = row[77] ? static_cast(atoi(row[77])) : 100; - e.formula9 = row[78] ? static_cast(atoi(row[78])) : 100; - e.formula10 = row[79] ? static_cast(atoi(row[79])) : 100; - e.formula11 = row[80] ? static_cast(atoi(row[80])) : 100; - e.formula12 = row[81] ? static_cast(atoi(row[81])) : 100; - e.LightType = row[82] ? static_cast(atoi(row[82])) : 0; - e.goodEffect = row[83] ? static_cast(atoi(row[83])) : 0; - e.Activated = row[84] ? static_cast(atoi(row[84])) : 0; - e.resisttype = row[85] ? static_cast(atoi(row[85])) : 0; - e.effectid1 = row[86] ? static_cast(atoi(row[86])) : 254; - e.effectid2 = row[87] ? static_cast(atoi(row[87])) : 254; - e.effectid3 = row[88] ? static_cast(atoi(row[88])) : 254; - e.effectid4 = row[89] ? static_cast(atoi(row[89])) : 254; - e.effectid5 = row[90] ? static_cast(atoi(row[90])) : 254; - e.effectid6 = row[91] ? static_cast(atoi(row[91])) : 254; - e.effectid7 = row[92] ? static_cast(atoi(row[92])) : 254; - e.effectid8 = row[93] ? static_cast(atoi(row[93])) : 254; - e.effectid9 = row[94] ? static_cast(atoi(row[94])) : 254; - e.effectid10 = row[95] ? static_cast(atoi(row[95])) : 254; - e.effectid11 = row[96] ? static_cast(atoi(row[96])) : 254; - e.effectid12 = row[97] ? static_cast(atoi(row[97])) : 254; - e.targettype = row[98] ? static_cast(atoi(row[98])) : 2; - e.basediff = row[99] ? static_cast(atoi(row[99])) : 0; - e.skill = row[100] ? static_cast(atoi(row[100])) : 98; - e.zonetype = row[101] ? static_cast(atoi(row[101])) : -1; - e.EnvironmentType = row[102] ? static_cast(atoi(row[102])) : 0; - e.TimeOfDay = row[103] ? static_cast(atoi(row[103])) : 0; - e.classes1 = row[104] ? static_cast(atoi(row[104])) : 255; - e.classes2 = row[105] ? static_cast(atoi(row[105])) : 255; - e.classes3 = row[106] ? static_cast(atoi(row[106])) : 255; - e.classes4 = row[107] ? static_cast(atoi(row[107])) : 255; - e.classes5 = row[108] ? static_cast(atoi(row[108])) : 255; - e.classes6 = row[109] ? static_cast(atoi(row[109])) : 255; - e.classes7 = row[110] ? static_cast(atoi(row[110])) : 255; - e.classes8 = row[111] ? static_cast(atoi(row[111])) : 255; - e.classes9 = row[112] ? static_cast(atoi(row[112])) : 255; - e.classes10 = row[113] ? static_cast(atoi(row[113])) : 255; - e.classes11 = row[114] ? static_cast(atoi(row[114])) : 255; - e.classes12 = row[115] ? static_cast(atoi(row[115])) : 255; - e.classes13 = row[116] ? static_cast(atoi(row[116])) : 255; - e.classes14 = row[117] ? static_cast(atoi(row[117])) : 255; - e.classes15 = row[118] ? static_cast(atoi(row[118])) : 255; - e.classes16 = row[119] ? static_cast(atoi(row[119])) : 255; - e.CastingAnim = row[120] ? static_cast(atoi(row[120])) : 44; - e.TargetAnim = row[121] ? static_cast(atoi(row[121])) : 13; - e.TravelType = row[122] ? static_cast(atoi(row[122])) : 0; - e.SpellAffectIndex = row[123] ? static_cast(atoi(row[123])) : -1; - e.disallow_sit = row[124] ? static_cast(atoi(row[124])) : 0; - e.deities0 = row[125] ? static_cast(atoi(row[125])) : 0; - e.deities1 = row[126] ? static_cast(atoi(row[126])) : 0; - e.deities2 = row[127] ? static_cast(atoi(row[127])) : 0; - e.deities3 = row[128] ? static_cast(atoi(row[128])) : 0; - e.deities4 = row[129] ? static_cast(atoi(row[129])) : 0; - e.deities5 = row[130] ? static_cast(atoi(row[130])) : 0; - e.deities6 = row[131] ? static_cast(atoi(row[131])) : 0; - e.deities7 = row[132] ? static_cast(atoi(row[132])) : 0; - e.deities8 = row[133] ? static_cast(atoi(row[133])) : 0; - e.deities9 = row[134] ? static_cast(atoi(row[134])) : 0; - e.deities10 = row[135] ? static_cast(atoi(row[135])) : 0; - e.deities11 = row[136] ? static_cast(atoi(row[136])) : 0; - e.deities12 = row[137] ? static_cast(atoi(row[137])) : 0; - e.deities13 = row[138] ? static_cast(atoi(row[138])) : 0; - e.deities14 = row[139] ? static_cast(atoi(row[139])) : 0; - e.deities15 = row[140] ? static_cast(atoi(row[140])) : 0; - e.deities16 = row[141] ? static_cast(atoi(row[141])) : 0; - e.field142 = row[142] ? static_cast(atoi(row[142])) : 100; - e.field143 = row[143] ? static_cast(atoi(row[143])) : 0; - e.new_icon = row[144] ? static_cast(atoi(row[144])) : 161; - e.spellanim = row[145] ? static_cast(atoi(row[145])) : 0; - e.uninterruptable = row[146] ? static_cast(atoi(row[146])) : 0; - e.ResistDiff = row[147] ? static_cast(atoi(row[147])) : -150; - e.dot_stacking_exempt = row[148] ? static_cast(atoi(row[148])) : 0; - e.deleteable = row[149] ? static_cast(atoi(row[149])) : 0; - e.RecourseLink = row[150] ? static_cast(atoi(row[150])) : 0; - e.no_partial_resist = row[151] ? static_cast(atoi(row[151])) : 0; - e.field152 = row[152] ? static_cast(atoi(row[152])) : 0; - e.field153 = row[153] ? static_cast(atoi(row[153])) : 0; - e.short_buff_box = row[154] ? static_cast(atoi(row[154])) : -1; - e.descnum = row[155] ? static_cast(atoi(row[155])) : 0; - e.typedescnum = row[156] ? static_cast(atoi(row[156])) : 0; - e.effectdescnum = row[157] ? static_cast(atoi(row[157])) : 0; - e.effectdescnum2 = row[158] ? static_cast(atoi(row[158])) : 0; - e.npc_no_los = row[159] ? static_cast(atoi(row[159])) : 0; - e.field160 = row[160] ? static_cast(atoi(row[160])) : 0; - e.reflectable = row[161] ? static_cast(atoi(row[161])) : 0; - e.bonushate = row[162] ? static_cast(atoi(row[162])) : 0; - e.field163 = row[163] ? static_cast(atoi(row[163])) : 100; - e.field164 = row[164] ? static_cast(atoi(row[164])) : -150; - e.ldon_trap = row[165] ? static_cast(atoi(row[165])) : 0; - e.EndurCost = row[166] ? static_cast(atoi(row[166])) : 0; - e.EndurTimerIndex = row[167] ? static_cast(atoi(row[167])) : 0; - e.IsDiscipline = row[168] ? static_cast(atoi(row[168])) : 0; - e.field169 = row[169] ? static_cast(atoi(row[169])) : 0; - e.field170 = row[170] ? static_cast(atoi(row[170])) : 0; - e.field171 = row[171] ? static_cast(atoi(row[171])) : 0; - e.field172 = row[172] ? static_cast(atoi(row[172])) : 0; - e.HateAdded = row[173] ? static_cast(atoi(row[173])) : 0; - e.EndurUpkeep = row[174] ? static_cast(atoi(row[174])) : 0; - e.numhitstype = row[175] ? static_cast(atoi(row[175])) : 0; - e.numhits = row[176] ? static_cast(atoi(row[176])) : 0; - e.pvpresistbase = row[177] ? static_cast(atoi(row[177])) : -150; - e.pvpresistcalc = row[178] ? static_cast(atoi(row[178])) : 100; - e.pvpresistcap = row[179] ? static_cast(atoi(row[179])) : -150; - e.spell_category = row[180] ? static_cast(atoi(row[180])) : -99; - e.pvp_duration = row[181] ? static_cast(atoi(row[181])) : 0; - e.pvp_duration_cap = row[182] ? static_cast(atoi(row[182])) : 0; - e.pcnpc_only_flag = row[183] ? static_cast(atoi(row[183])) : 0; - e.cast_not_standing = row[184] ? static_cast(atoi(row[184])) : 0; - e.can_mgb = row[185] ? static_cast(atoi(row[185])) : 0; - e.nodispell = row[186] ? static_cast(atoi(row[186])) : -1; - e.npc_category = row[187] ? static_cast(atoi(row[187])) : 0; - e.npc_usefulness = row[188] ? static_cast(atoi(row[188])) : 0; - e.MinResist = row[189] ? static_cast(atoi(row[189])) : 0; - e.MaxResist = row[190] ? static_cast(atoi(row[190])) : 0; - e.viral_targets = row[191] ? static_cast(atoi(row[191])) : 0; - e.viral_timer = row[192] ? static_cast(atoi(row[192])) : 0; - e.nimbuseffect = row[193] ? static_cast(atoi(row[193])) : 0; - e.ConeStartAngle = row[194] ? static_cast(atoi(row[194])) : 0; - e.ConeStopAngle = row[195] ? static_cast(atoi(row[195])) : 0; - e.sneaking = row[196] ? static_cast(atoi(row[196])) : 0; - e.not_extendable = row[197] ? static_cast(atoi(row[197])) : 0; - e.field198 = row[198] ? static_cast(atoi(row[198])) : 0; - e.field199 = row[199] ? static_cast(atoi(row[199])) : 1; - e.suspendable = row[200] ? static_cast(atoi(row[200])) : 0; - e.viral_range = row[201] ? static_cast(atoi(row[201])) : 0; - e.songcap = row[202] ? static_cast(atoi(row[202])) : 0; - e.field203 = row[203] ? static_cast(atoi(row[203])) : 0; - e.field204 = row[204] ? static_cast(atoi(row[204])) : 0; - e.no_block = row[205] ? static_cast(atoi(row[205])) : 0; - e.field206 = row[206] ? static_cast(atoi(row[206])) : -1; - e.spellgroup = row[207] ? static_cast(atoi(row[207])) : 0; - e.rank_ = row[208] ? static_cast(atoi(row[208])) : 0; - e.field209 = row[209] ? static_cast(atoi(row[209])) : 0; - e.field210 = row[210] ? static_cast(atoi(row[210])) : 1; - e.CastRestriction = row[211] ? static_cast(atoi(row[211])) : 0; - e.allowrest = row[212] ? static_cast(atoi(row[212])) : 0; - e.InCombat = row[213] ? static_cast(atoi(row[213])) : 0; - e.OutofCombat = row[214] ? static_cast(atoi(row[214])) : 0; - e.field215 = row[215] ? static_cast(atoi(row[215])) : 0; - e.field216 = row[216] ? static_cast(atoi(row[216])) : 0; - e.field217 = row[217] ? static_cast(atoi(row[217])) : 0; - e.aemaxtargets = row[218] ? static_cast(atoi(row[218])) : 0; - e.maxtargets = row[219] ? static_cast(atoi(row[219])) : 0; - e.field220 = row[220] ? static_cast(atoi(row[220])) : 0; - e.field221 = row[221] ? static_cast(atoi(row[221])) : 0; - e.field222 = row[222] ? static_cast(atoi(row[222])) : 0; - e.field223 = row[223] ? static_cast(atoi(row[223])) : 0; - e.persistdeath = row[224] ? static_cast(atoi(row[224])) : 0; - e.field225 = row[225] ? static_cast(atoi(row[225])) : 0; - e.field226 = row[226] ? static_cast(atoi(row[226])) : 0; - e.min_dist = row[227] ? strtof(row[227], nullptr) : 0; - e.min_dist_mod = row[228] ? strtof(row[228], nullptr) : 0; - e.max_dist = row[229] ? strtof(row[229], nullptr) : 0; - e.max_dist_mod = row[230] ? strtof(row[230], nullptr) : 0; - e.min_range = row[231] ? static_cast(atoi(row[231])) : 0; - e.field232 = row[232] ? static_cast(atoi(row[232])) : 0; - e.field233 = row[233] ? static_cast(atoi(row[233])) : 0; - e.field234 = row[234] ? static_cast(atoi(row[234])) : 0; - e.field235 = row[235] ? static_cast(atoi(row[235])) : 0; - e.field236 = row[236] ? static_cast(atoi(row[236])) : 0; + e.id = row[0] ? static_cast(atoi(row[0])) : 0; + e.name = row[1] ? row[1] : ""; + e.player_1 = row[2] ? row[2] : "BLUE_TRAIL"; + e.teleport_zone = row[3] ? row[3] : ""; + e.you_cast = row[4] ? row[4] : ""; + e.other_casts = row[5] ? row[5] : ""; + e.cast_on_you = row[6] ? row[6] : ""; + e.cast_on_other = row[7] ? row[7] : ""; + e.spell_fades = row[8] ? row[8] : ""; + e.range_ = row[9] ? static_cast(atoi(row[9])) : 100; + e.aoerange = row[10] ? static_cast(atoi(row[10])) : 0; + e.pushback = row[11] ? static_cast(atoi(row[11])) : 0; + e.pushup = row[12] ? static_cast(atoi(row[12])) : 0; + e.cast_time = row[13] ? static_cast(atoi(row[13])) : 0; + e.recovery_time = row[14] ? static_cast(atoi(row[14])) : 0; + e.recast_time = row[15] ? static_cast(atoi(row[15])) : 0; + e.buffdurationformula = row[16] ? static_cast(atoi(row[16])) : 7; + e.buffduration = row[17] ? static_cast(atoi(row[17])) : 65; + e.AEDuration = row[18] ? static_cast(atoi(row[18])) : 0; + e.mana = row[19] ? static_cast(atoi(row[19])) : 0; + e.effect_base_value1 = row[20] ? static_cast(atoi(row[20])) : 100; + e.effect_base_value2 = row[21] ? static_cast(atoi(row[21])) : 0; + e.effect_base_value3 = row[22] ? static_cast(atoi(row[22])) : 0; + e.effect_base_value4 = row[23] ? static_cast(atoi(row[23])) : 0; + e.effect_base_value5 = row[24] ? static_cast(atoi(row[24])) : 0; + e.effect_base_value6 = row[25] ? static_cast(atoi(row[25])) : 0; + e.effect_base_value7 = row[26] ? static_cast(atoi(row[26])) : 0; + e.effect_base_value8 = row[27] ? static_cast(atoi(row[27])) : 0; + e.effect_base_value9 = row[28] ? static_cast(atoi(row[28])) : 0; + e.effect_base_value10 = row[29] ? static_cast(atoi(row[29])) : 0; + e.effect_base_value11 = row[30] ? static_cast(atoi(row[30])) : 0; + e.effect_base_value12 = row[31] ? static_cast(atoi(row[31])) : 0; + e.effect_limit_value1 = row[32] ? static_cast(atoi(row[32])) : 0; + e.effect_limit_value2 = row[33] ? static_cast(atoi(row[33])) : 0; + e.effect_limit_value3 = row[34] ? static_cast(atoi(row[34])) : 0; + e.effect_limit_value4 = row[35] ? static_cast(atoi(row[35])) : 0; + e.effect_limit_value5 = row[36] ? static_cast(atoi(row[36])) : 0; + e.effect_limit_value6 = row[37] ? static_cast(atoi(row[37])) : 0; + e.effect_limit_value7 = row[38] ? static_cast(atoi(row[38])) : 0; + e.effect_limit_value8 = row[39] ? static_cast(atoi(row[39])) : 0; + e.effect_limit_value9 = row[40] ? static_cast(atoi(row[40])) : 0; + e.effect_limit_value10 = row[41] ? static_cast(atoi(row[41])) : 0; + e.effect_limit_value11 = row[42] ? static_cast(atoi(row[42])) : 0; + e.effect_limit_value12 = row[43] ? static_cast(atoi(row[43])) : 0; + e.max1 = row[44] ? static_cast(atoi(row[44])) : 0; + e.max2 = row[45] ? static_cast(atoi(row[45])) : 0; + e.max3 = row[46] ? static_cast(atoi(row[46])) : 0; + e.max4 = row[47] ? static_cast(atoi(row[47])) : 0; + e.max5 = row[48] ? static_cast(atoi(row[48])) : 0; + e.max6 = row[49] ? static_cast(atoi(row[49])) : 0; + e.max7 = row[50] ? static_cast(atoi(row[50])) : 0; + e.max8 = row[51] ? static_cast(atoi(row[51])) : 0; + e.max9 = row[52] ? static_cast(atoi(row[52])) : 0; + e.max10 = row[53] ? static_cast(atoi(row[53])) : 0; + e.max11 = row[54] ? static_cast(atoi(row[54])) : 0; + e.max12 = row[55] ? static_cast(atoi(row[55])) : 0; + e.icon = row[56] ? static_cast(atoi(row[56])) : 0; + e.memicon = row[57] ? static_cast(atoi(row[57])) : 0; + e.components1 = row[58] ? static_cast(atoi(row[58])) : -1; + e.components2 = row[59] ? static_cast(atoi(row[59])) : -1; + e.components3 = row[60] ? static_cast(atoi(row[60])) : -1; + e.components4 = row[61] ? static_cast(atoi(row[61])) : -1; + e.component_counts1 = row[62] ? static_cast(atoi(row[62])) : 1; + e.component_counts2 = row[63] ? static_cast(atoi(row[63])) : 1; + e.component_counts3 = row[64] ? static_cast(atoi(row[64])) : 1; + e.component_counts4 = row[65] ? static_cast(atoi(row[65])) : 1; + e.NoexpendReagent1 = row[66] ? static_cast(atoi(row[66])) : -1; + e.NoexpendReagent2 = row[67] ? static_cast(atoi(row[67])) : -1; + e.NoexpendReagent3 = row[68] ? static_cast(atoi(row[68])) : -1; + e.NoexpendReagent4 = row[69] ? static_cast(atoi(row[69])) : -1; + e.formula1 = row[70] ? static_cast(atoi(row[70])) : 100; + e.formula2 = row[71] ? static_cast(atoi(row[71])) : 100; + e.formula3 = row[72] ? static_cast(atoi(row[72])) : 100; + e.formula4 = row[73] ? static_cast(atoi(row[73])) : 100; + e.formula5 = row[74] ? static_cast(atoi(row[74])) : 100; + e.formula6 = row[75] ? static_cast(atoi(row[75])) : 100; + e.formula7 = row[76] ? static_cast(atoi(row[76])) : 100; + e.formula8 = row[77] ? static_cast(atoi(row[77])) : 100; + e.formula9 = row[78] ? static_cast(atoi(row[78])) : 100; + e.formula10 = row[79] ? static_cast(atoi(row[79])) : 100; + e.formula11 = row[80] ? static_cast(atoi(row[80])) : 100; + e.formula12 = row[81] ? static_cast(atoi(row[81])) : 100; + e.LightType = row[82] ? static_cast(atoi(row[82])) : 0; + e.goodEffect = row[83] ? static_cast(atoi(row[83])) : 0; + e.Activated = row[84] ? static_cast(atoi(row[84])) : 0; + e.resisttype = row[85] ? static_cast(atoi(row[85])) : 0; + e.effectid1 = row[86] ? static_cast(atoi(row[86])) : 254; + e.effectid2 = row[87] ? static_cast(atoi(row[87])) : 254; + e.effectid3 = row[88] ? static_cast(atoi(row[88])) : 254; + e.effectid4 = row[89] ? static_cast(atoi(row[89])) : 254; + e.effectid5 = row[90] ? static_cast(atoi(row[90])) : 254; + e.effectid6 = row[91] ? static_cast(atoi(row[91])) : 254; + e.effectid7 = row[92] ? static_cast(atoi(row[92])) : 254; + e.effectid8 = row[93] ? static_cast(atoi(row[93])) : 254; + e.effectid9 = row[94] ? static_cast(atoi(row[94])) : 254; + e.effectid10 = row[95] ? static_cast(atoi(row[95])) : 254; + e.effectid11 = row[96] ? static_cast(atoi(row[96])) : 254; + e.effectid12 = row[97] ? static_cast(atoi(row[97])) : 254; + e.targettype = row[98] ? static_cast(atoi(row[98])) : 2; + e.basediff = row[99] ? static_cast(atoi(row[99])) : 0; + e.skill = row[100] ? static_cast(atoi(row[100])) : 98; + e.zonetype = row[101] ? static_cast(atoi(row[101])) : -1; + e.EnvironmentType = row[102] ? static_cast(atoi(row[102])) : 0; + e.TimeOfDay = row[103] ? static_cast(atoi(row[103])) : 0; + e.classes1 = row[104] ? static_cast(atoi(row[104])) : 255; + e.classes2 = row[105] ? static_cast(atoi(row[105])) : 255; + e.classes3 = row[106] ? static_cast(atoi(row[106])) : 255; + e.classes4 = row[107] ? static_cast(atoi(row[107])) : 255; + e.classes5 = row[108] ? static_cast(atoi(row[108])) : 255; + e.classes6 = row[109] ? static_cast(atoi(row[109])) : 255; + e.classes7 = row[110] ? static_cast(atoi(row[110])) : 255; + e.classes8 = row[111] ? static_cast(atoi(row[111])) : 255; + e.classes9 = row[112] ? static_cast(atoi(row[112])) : 255; + e.classes10 = row[113] ? static_cast(atoi(row[113])) : 255; + e.classes11 = row[114] ? static_cast(atoi(row[114])) : 255; + e.classes12 = row[115] ? static_cast(atoi(row[115])) : 255; + e.classes13 = row[116] ? static_cast(atoi(row[116])) : 255; + e.classes14 = row[117] ? static_cast(atoi(row[117])) : 255; + e.classes15 = row[118] ? static_cast(atoi(row[118])) : 255; + e.classes16 = row[119] ? static_cast(atoi(row[119])) : 255; + e.CastingAnim = row[120] ? static_cast(atoi(row[120])) : 44; + e.TargetAnim = row[121] ? static_cast(atoi(row[121])) : 13; + e.TravelType = row[122] ? static_cast(atoi(row[122])) : 0; + e.SpellAffectIndex = row[123] ? static_cast(atoi(row[123])) : -1; + e.disallow_sit = row[124] ? static_cast(atoi(row[124])) : 0; + e.deities0 = row[125] ? static_cast(atoi(row[125])) : 0; + e.deities1 = row[126] ? static_cast(atoi(row[126])) : 0; + e.deities2 = row[127] ? static_cast(atoi(row[127])) : 0; + e.deities3 = row[128] ? static_cast(atoi(row[128])) : 0; + e.deities4 = row[129] ? static_cast(atoi(row[129])) : 0; + e.deities5 = row[130] ? static_cast(atoi(row[130])) : 0; + e.deities6 = row[131] ? static_cast(atoi(row[131])) : 0; + e.deities7 = row[132] ? static_cast(atoi(row[132])) : 0; + e.deities8 = row[133] ? static_cast(atoi(row[133])) : 0; + e.deities9 = row[134] ? static_cast(atoi(row[134])) : 0; + e.deities10 = row[135] ? static_cast(atoi(row[135])) : 0; + e.deities11 = row[136] ? static_cast(atoi(row[136])) : 0; + e.deities12 = row[137] ? static_cast(atoi(row[137])) : 0; + e.deities13 = row[138] ? static_cast(atoi(row[138])) : 0; + e.deities14 = row[139] ? static_cast(atoi(row[139])) : 0; + e.deities15 = row[140] ? static_cast(atoi(row[140])) : 0; + e.deities16 = row[141] ? static_cast(atoi(row[141])) : 0; + e.field142 = row[142] ? static_cast(atoi(row[142])) : 100; + e.field143 = row[143] ? static_cast(atoi(row[143])) : 0; + e.new_icon = row[144] ? static_cast(atoi(row[144])) : 161; + e.spellanim = row[145] ? static_cast(atoi(row[145])) : 0; + e.uninterruptable = row[146] ? static_cast(atoi(row[146])) : 0; + e.ResistDiff = row[147] ? static_cast(atoi(row[147])) : -150; + e.dot_stacking_exempt = row[148] ? static_cast(atoi(row[148])) : 0; + e.deleteable = row[149] ? static_cast(atoi(row[149])) : 0; + e.RecourseLink = row[150] ? static_cast(atoi(row[150])) : 0; + e.no_partial_resist = row[151] ? static_cast(atoi(row[151])) : 0; + e.field152 = row[152] ? static_cast(atoi(row[152])) : 0; + e.field153 = row[153] ? static_cast(atoi(row[153])) : 0; + e.short_buff_box = row[154] ? static_cast(atoi(row[154])) : -1; + e.descnum = row[155] ? static_cast(atoi(row[155])) : 0; + e.typedescnum = row[156] ? static_cast(atoi(row[156])) : 0; + e.effectdescnum = row[157] ? static_cast(atoi(row[157])) : 0; + e.effectdescnum2 = row[158] ? static_cast(atoi(row[158])) : 0; + e.npc_no_los = row[159] ? static_cast(atoi(row[159])) : 0; + e.feedbackable = row[160] ? static_cast(atoi(row[160])) : 0; + e.reflectable = row[161] ? static_cast(atoi(row[161])) : 0; + e.bonushate = row[162] ? static_cast(atoi(row[162])) : 0; + e.field163 = row[163] ? static_cast(atoi(row[163])) : 100; + e.field164 = row[164] ? static_cast(atoi(row[164])) : -150; + e.ldon_trap = row[165] ? static_cast(atoi(row[165])) : 0; + e.EndurCost = row[166] ? static_cast(atoi(row[166])) : 0; + e.EndurTimerIndex = row[167] ? static_cast(atoi(row[167])) : 0; + e.IsDiscipline = row[168] ? static_cast(atoi(row[168])) : 0; + e.field169 = row[169] ? static_cast(atoi(row[169])) : 0; + e.field170 = row[170] ? static_cast(atoi(row[170])) : 0; + e.field171 = row[171] ? static_cast(atoi(row[171])) : 0; + e.field172 = row[172] ? static_cast(atoi(row[172])) : 0; + e.HateAdded = row[173] ? static_cast(atoi(row[173])) : 0; + e.EndurUpkeep = row[174] ? static_cast(atoi(row[174])) : 0; + e.numhitstype = row[175] ? static_cast(atoi(row[175])) : 0; + e.numhits = row[176] ? static_cast(atoi(row[176])) : 0; + e.pvpresistbase = row[177] ? static_cast(atoi(row[177])) : -150; + e.pvpresistcalc = row[178] ? static_cast(atoi(row[178])) : 100; + e.pvpresistcap = row[179] ? static_cast(atoi(row[179])) : -150; + e.spell_category = row[180] ? static_cast(atoi(row[180])) : -99; + e.pvp_duration = row[181] ? static_cast(atoi(row[181])) : 0; + e.pvp_duration_cap = row[182] ? static_cast(atoi(row[182])) : 0; + e.pcnpc_only_flag = row[183] ? static_cast(atoi(row[183])) : 0; + e.cast_not_standing = row[184] ? static_cast(atoi(row[184])) : 0; + e.can_mgb = row[185] ? static_cast(atoi(row[185])) : 0; + e.nodispell = row[186] ? static_cast(atoi(row[186])) : -1; + e.npc_category = row[187] ? static_cast(atoi(row[187])) : 0; + e.npc_usefulness = row[188] ? static_cast(atoi(row[188])) : 0; + e.MinResist = row[189] ? static_cast(atoi(row[189])) : 0; + e.MaxResist = row[190] ? static_cast(atoi(row[190])) : 0; + e.viral_targets = row[191] ? static_cast(atoi(row[191])) : 0; + e.viral_timer = row[192] ? static_cast(atoi(row[192])) : 0; + e.nimbuseffect = row[193] ? static_cast(atoi(row[193])) : 0; + e.ConeStartAngle = row[194] ? static_cast(atoi(row[194])) : 0; + e.ConeStopAngle = row[195] ? static_cast(atoi(row[195])) : 0; + e.sneaking = row[196] ? static_cast(atoi(row[196])) : 0; + e.not_extendable = row[197] ? static_cast(atoi(row[197])) : 0; + e.no_detrimental_spell_aggro = row[198] ? static_cast(atoi(row[198])) : 0; + e.field199 = row[199] ? static_cast(atoi(row[199])) : 1; + e.suspendable = row[200] ? static_cast(atoi(row[200])) : 0; + e.viral_range = row[201] ? static_cast(atoi(row[201])) : 0; + e.songcap = row[202] ? static_cast(atoi(row[202])) : 0; + e.field203 = row[203] ? static_cast(atoi(row[203])) : 0; + e.field204 = row[204] ? static_cast(atoi(row[204])) : 0; + e.no_block = row[205] ? static_cast(atoi(row[205])) : 0; + e.field206 = row[206] ? static_cast(atoi(row[206])) : -1; + e.spellgroup = row[207] ? static_cast(atoi(row[207])) : 0; + e.rank_ = row[208] ? static_cast(atoi(row[208])) : 0; + e.no_resist = row[209] ? static_cast(atoi(row[209])) : 0; + e.field210 = row[210] ? static_cast(atoi(row[210])) : 1; + e.CastRestriction = row[211] ? static_cast(atoi(row[211])) : 0; + e.allowrest = row[212] ? static_cast(atoi(row[212])) : 0; + e.InCombat = row[213] ? static_cast(atoi(row[213])) : 0; + e.OutofCombat = row[214] ? static_cast(atoi(row[214])) : 0; + e.field215 = row[215] ? static_cast(atoi(row[215])) : 0; + e.field216 = row[216] ? static_cast(atoi(row[216])) : 0; + e.override_crit_chance = row[217] ? static_cast(atoi(row[217])) : 0; + e.aemaxtargets = row[218] ? static_cast(atoi(row[218])) : 0; + e.maxtargets = row[219] ? static_cast(atoi(row[219])) : 0; + e.no_heal_damage_item_mod = row[220] ? static_cast(atoi(row[220])) : 0; + e.caster_requirement_id = row[221] ? static_cast(atoi(row[221])) : 0; + e.spell_class = row[222] ? static_cast(atoi(row[222])) : 0; + e.spell_subclass = row[223] ? static_cast(atoi(row[223])) : 0; + e.persistdeath = row[224] ? static_cast(atoi(row[224])) : 0; + e.field225 = row[225] ? static_cast(atoi(row[225])) : 0; + e.field226 = row[226] ? static_cast(atoi(row[226])) : 0; + e.min_dist = row[227] ? strtof(row[227], nullptr) : 0; + e.min_dist_mod = row[228] ? strtof(row[228], nullptr) : 0; + e.max_dist = row[229] ? strtof(row[229], nullptr) : 0; + e.max_dist_mod = row[230] ? strtof(row[230], nullptr) : 0; + e.min_range = row[231] ? static_cast(atoi(row[231])) : 0; + e.no_remove = row[232] ? static_cast(atoi(row[232])) : 0; + e.field233 = row[233] ? static_cast(atoi(row[233])) : 0; + e.field234 = row[234] ? static_cast(atoi(row[234])) : 0; + e.field235 = row[235] ? static_cast(atoi(row[235])) : 0; + e.field236 = row[236] ? static_cast(atoi(row[236])) : 0; return e; } @@ -1489,7 +1489,7 @@ class BaseSpellsNewRepository { v.push_back(columns[157] + " = " + std::to_string(e.effectdescnum)); v.push_back(columns[158] + " = " + std::to_string(e.effectdescnum2)); v.push_back(columns[159] + " = " + std::to_string(e.npc_no_los)); - v.push_back(columns[160] + " = " + std::to_string(e.field160)); + v.push_back(columns[160] + " = " + std::to_string(e.feedbackable)); v.push_back(columns[161] + " = " + std::to_string(e.reflectable)); v.push_back(columns[162] + " = " + std::to_string(e.bonushate)); v.push_back(columns[163] + " = " + std::to_string(e.field163)); @@ -1527,7 +1527,7 @@ class BaseSpellsNewRepository { v.push_back(columns[195] + " = " + std::to_string(e.ConeStopAngle)); v.push_back(columns[196] + " = " + std::to_string(e.sneaking)); v.push_back(columns[197] + " = " + std::to_string(e.not_extendable)); - v.push_back(columns[198] + " = " + std::to_string(e.field198)); + v.push_back(columns[198] + " = " + std::to_string(e.no_detrimental_spell_aggro)); v.push_back(columns[199] + " = " + std::to_string(e.field199)); v.push_back(columns[200] + " = " + std::to_string(e.suspendable)); v.push_back(columns[201] + " = " + std::to_string(e.viral_range)); @@ -1538,7 +1538,7 @@ class BaseSpellsNewRepository { v.push_back(columns[206] + " = " + std::to_string(e.field206)); v.push_back(columns[207] + " = " + std::to_string(e.spellgroup)); v.push_back(columns[208] + " = " + std::to_string(e.rank_)); - v.push_back(columns[209] + " = " + std::to_string(e.field209)); + v.push_back(columns[209] + " = " + std::to_string(e.no_resist)); v.push_back(columns[210] + " = " + std::to_string(e.field210)); v.push_back(columns[211] + " = " + std::to_string(e.CastRestriction)); v.push_back(columns[212] + " = " + std::to_string(e.allowrest)); @@ -1546,13 +1546,13 @@ class BaseSpellsNewRepository { v.push_back(columns[214] + " = " + std::to_string(e.OutofCombat)); v.push_back(columns[215] + " = " + std::to_string(e.field215)); v.push_back(columns[216] + " = " + std::to_string(e.field216)); - v.push_back(columns[217] + " = " + std::to_string(e.field217)); + v.push_back(columns[217] + " = " + std::to_string(e.override_crit_chance)); v.push_back(columns[218] + " = " + std::to_string(e.aemaxtargets)); v.push_back(columns[219] + " = " + std::to_string(e.maxtargets)); - v.push_back(columns[220] + " = " + std::to_string(e.field220)); - v.push_back(columns[221] + " = " + std::to_string(e.field221)); - v.push_back(columns[222] + " = " + std::to_string(e.field222)); - v.push_back(columns[223] + " = " + std::to_string(e.field223)); + v.push_back(columns[220] + " = " + std::to_string(e.no_heal_damage_item_mod)); + v.push_back(columns[221] + " = " + std::to_string(e.caster_requirement_id)); + v.push_back(columns[222] + " = " + std::to_string(e.spell_class)); + v.push_back(columns[223] + " = " + std::to_string(e.spell_subclass)); v.push_back(columns[224] + " = " + std::to_string(e.persistdeath)); v.push_back(columns[225] + " = " + std::to_string(e.field225)); v.push_back(columns[226] + " = " + std::to_string(e.field226)); @@ -1561,7 +1561,7 @@ class BaseSpellsNewRepository { v.push_back(columns[229] + " = " + std::to_string(e.max_dist)); v.push_back(columns[230] + " = " + std::to_string(e.max_dist_mod)); v.push_back(columns[231] + " = " + std::to_string(e.min_range)); - v.push_back(columns[232] + " = " + std::to_string(e.field232)); + v.push_back(columns[232] + " = " + std::to_string(e.no_remove)); v.push_back(columns[233] + " = " + std::to_string(e.field233)); v.push_back(columns[234] + " = " + std::to_string(e.field234)); v.push_back(columns[235] + " = " + std::to_string(e.field235)); @@ -1747,7 +1747,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.effectdescnum)); v.push_back(std::to_string(e.effectdescnum2)); v.push_back(std::to_string(e.npc_no_los)); - v.push_back(std::to_string(e.field160)); + v.push_back(std::to_string(e.feedbackable)); v.push_back(std::to_string(e.reflectable)); v.push_back(std::to_string(e.bonushate)); v.push_back(std::to_string(e.field163)); @@ -1785,7 +1785,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.ConeStopAngle)); v.push_back(std::to_string(e.sneaking)); v.push_back(std::to_string(e.not_extendable)); - v.push_back(std::to_string(e.field198)); + v.push_back(std::to_string(e.no_detrimental_spell_aggro)); v.push_back(std::to_string(e.field199)); v.push_back(std::to_string(e.suspendable)); v.push_back(std::to_string(e.viral_range)); @@ -1796,7 +1796,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.field206)); v.push_back(std::to_string(e.spellgroup)); v.push_back(std::to_string(e.rank_)); - v.push_back(std::to_string(e.field209)); + v.push_back(std::to_string(e.no_resist)); v.push_back(std::to_string(e.field210)); v.push_back(std::to_string(e.CastRestriction)); v.push_back(std::to_string(e.allowrest)); @@ -1804,13 +1804,13 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.OutofCombat)); v.push_back(std::to_string(e.field215)); v.push_back(std::to_string(e.field216)); - v.push_back(std::to_string(e.field217)); + v.push_back(std::to_string(e.override_crit_chance)); v.push_back(std::to_string(e.aemaxtargets)); v.push_back(std::to_string(e.maxtargets)); - v.push_back(std::to_string(e.field220)); - v.push_back(std::to_string(e.field221)); - v.push_back(std::to_string(e.field222)); - v.push_back(std::to_string(e.field223)); + v.push_back(std::to_string(e.no_heal_damage_item_mod)); + v.push_back(std::to_string(e.caster_requirement_id)); + v.push_back(std::to_string(e.spell_class)); + v.push_back(std::to_string(e.spell_subclass)); v.push_back(std::to_string(e.persistdeath)); v.push_back(std::to_string(e.field225)); v.push_back(std::to_string(e.field226)); @@ -1819,7 +1819,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.max_dist)); v.push_back(std::to_string(e.max_dist_mod)); v.push_back(std::to_string(e.min_range)); - v.push_back(std::to_string(e.field232)); + v.push_back(std::to_string(e.no_remove)); v.push_back(std::to_string(e.field233)); v.push_back(std::to_string(e.field234)); v.push_back(std::to_string(e.field235)); @@ -2013,7 +2013,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.effectdescnum)); v.push_back(std::to_string(e.effectdescnum2)); v.push_back(std::to_string(e.npc_no_los)); - v.push_back(std::to_string(e.field160)); + v.push_back(std::to_string(e.feedbackable)); v.push_back(std::to_string(e.reflectable)); v.push_back(std::to_string(e.bonushate)); v.push_back(std::to_string(e.field163)); @@ -2051,7 +2051,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.ConeStopAngle)); v.push_back(std::to_string(e.sneaking)); v.push_back(std::to_string(e.not_extendable)); - v.push_back(std::to_string(e.field198)); + v.push_back(std::to_string(e.no_detrimental_spell_aggro)); v.push_back(std::to_string(e.field199)); v.push_back(std::to_string(e.suspendable)); v.push_back(std::to_string(e.viral_range)); @@ -2062,7 +2062,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.field206)); v.push_back(std::to_string(e.spellgroup)); v.push_back(std::to_string(e.rank_)); - v.push_back(std::to_string(e.field209)); + v.push_back(std::to_string(e.no_resist)); v.push_back(std::to_string(e.field210)); v.push_back(std::to_string(e.CastRestriction)); v.push_back(std::to_string(e.allowrest)); @@ -2070,13 +2070,13 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.OutofCombat)); v.push_back(std::to_string(e.field215)); v.push_back(std::to_string(e.field216)); - v.push_back(std::to_string(e.field217)); + v.push_back(std::to_string(e.override_crit_chance)); v.push_back(std::to_string(e.aemaxtargets)); v.push_back(std::to_string(e.maxtargets)); - v.push_back(std::to_string(e.field220)); - v.push_back(std::to_string(e.field221)); - v.push_back(std::to_string(e.field222)); - v.push_back(std::to_string(e.field223)); + v.push_back(std::to_string(e.no_heal_damage_item_mod)); + v.push_back(std::to_string(e.caster_requirement_id)); + v.push_back(std::to_string(e.spell_class)); + v.push_back(std::to_string(e.spell_subclass)); v.push_back(std::to_string(e.persistdeath)); v.push_back(std::to_string(e.field225)); v.push_back(std::to_string(e.field226)); @@ -2085,7 +2085,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.max_dist)); v.push_back(std::to_string(e.max_dist_mod)); v.push_back(std::to_string(e.min_range)); - v.push_back(std::to_string(e.field232)); + v.push_back(std::to_string(e.no_remove)); v.push_back(std::to_string(e.field233)); v.push_back(std::to_string(e.field234)); v.push_back(std::to_string(e.field235)); @@ -2123,243 +2123,243 @@ class BaseSpellsNewRepository { for (auto row = results.begin(); row != results.end(); ++row) { SpellsNew e{}; - e.id = row[0] ? static_cast(atoi(row[0])) : 0; - e.name = row[1] ? row[1] : ""; - e.player_1 = row[2] ? row[2] : "BLUE_TRAIL"; - e.teleport_zone = row[3] ? row[3] : ""; - e.you_cast = row[4] ? row[4] : ""; - e.other_casts = row[5] ? row[5] : ""; - e.cast_on_you = row[6] ? row[6] : ""; - e.cast_on_other = row[7] ? row[7] : ""; - e.spell_fades = row[8] ? row[8] : ""; - e.range_ = row[9] ? static_cast(atoi(row[9])) : 100; - e.aoerange = row[10] ? static_cast(atoi(row[10])) : 0; - e.pushback = row[11] ? static_cast(atoi(row[11])) : 0; - e.pushup = row[12] ? static_cast(atoi(row[12])) : 0; - e.cast_time = row[13] ? static_cast(atoi(row[13])) : 0; - e.recovery_time = row[14] ? static_cast(atoi(row[14])) : 0; - e.recast_time = row[15] ? static_cast(atoi(row[15])) : 0; - e.buffdurationformula = row[16] ? static_cast(atoi(row[16])) : 7; - e.buffduration = row[17] ? static_cast(atoi(row[17])) : 65; - e.AEDuration = row[18] ? static_cast(atoi(row[18])) : 0; - e.mana = row[19] ? static_cast(atoi(row[19])) : 0; - e.effect_base_value1 = row[20] ? static_cast(atoi(row[20])) : 100; - e.effect_base_value2 = row[21] ? static_cast(atoi(row[21])) : 0; - e.effect_base_value3 = row[22] ? static_cast(atoi(row[22])) : 0; - e.effect_base_value4 = row[23] ? static_cast(atoi(row[23])) : 0; - e.effect_base_value5 = row[24] ? static_cast(atoi(row[24])) : 0; - e.effect_base_value6 = row[25] ? static_cast(atoi(row[25])) : 0; - e.effect_base_value7 = row[26] ? static_cast(atoi(row[26])) : 0; - e.effect_base_value8 = row[27] ? static_cast(atoi(row[27])) : 0; - e.effect_base_value9 = row[28] ? static_cast(atoi(row[28])) : 0; - e.effect_base_value10 = row[29] ? static_cast(atoi(row[29])) : 0; - e.effect_base_value11 = row[30] ? static_cast(atoi(row[30])) : 0; - e.effect_base_value12 = row[31] ? static_cast(atoi(row[31])) : 0; - e.effect_limit_value1 = row[32] ? static_cast(atoi(row[32])) : 0; - e.effect_limit_value2 = row[33] ? static_cast(atoi(row[33])) : 0; - e.effect_limit_value3 = row[34] ? static_cast(atoi(row[34])) : 0; - e.effect_limit_value4 = row[35] ? static_cast(atoi(row[35])) : 0; - e.effect_limit_value5 = row[36] ? static_cast(atoi(row[36])) : 0; - e.effect_limit_value6 = row[37] ? static_cast(atoi(row[37])) : 0; - e.effect_limit_value7 = row[38] ? static_cast(atoi(row[38])) : 0; - e.effect_limit_value8 = row[39] ? static_cast(atoi(row[39])) : 0; - e.effect_limit_value9 = row[40] ? static_cast(atoi(row[40])) : 0; - e.effect_limit_value10 = row[41] ? static_cast(atoi(row[41])) : 0; - e.effect_limit_value11 = row[42] ? static_cast(atoi(row[42])) : 0; - e.effect_limit_value12 = row[43] ? static_cast(atoi(row[43])) : 0; - e.max1 = row[44] ? static_cast(atoi(row[44])) : 0; - e.max2 = row[45] ? static_cast(atoi(row[45])) : 0; - e.max3 = row[46] ? static_cast(atoi(row[46])) : 0; - e.max4 = row[47] ? static_cast(atoi(row[47])) : 0; - e.max5 = row[48] ? static_cast(atoi(row[48])) : 0; - e.max6 = row[49] ? static_cast(atoi(row[49])) : 0; - e.max7 = row[50] ? static_cast(atoi(row[50])) : 0; - e.max8 = row[51] ? static_cast(atoi(row[51])) : 0; - e.max9 = row[52] ? static_cast(atoi(row[52])) : 0; - e.max10 = row[53] ? static_cast(atoi(row[53])) : 0; - e.max11 = row[54] ? static_cast(atoi(row[54])) : 0; - e.max12 = row[55] ? static_cast(atoi(row[55])) : 0; - e.icon = row[56] ? static_cast(atoi(row[56])) : 0; - e.memicon = row[57] ? static_cast(atoi(row[57])) : 0; - e.components1 = row[58] ? static_cast(atoi(row[58])) : -1; - e.components2 = row[59] ? static_cast(atoi(row[59])) : -1; - e.components3 = row[60] ? static_cast(atoi(row[60])) : -1; - e.components4 = row[61] ? static_cast(atoi(row[61])) : -1; - e.component_counts1 = row[62] ? static_cast(atoi(row[62])) : 1; - e.component_counts2 = row[63] ? static_cast(atoi(row[63])) : 1; - e.component_counts3 = row[64] ? static_cast(atoi(row[64])) : 1; - e.component_counts4 = row[65] ? static_cast(atoi(row[65])) : 1; - e.NoexpendReagent1 = row[66] ? static_cast(atoi(row[66])) : -1; - e.NoexpendReagent2 = row[67] ? static_cast(atoi(row[67])) : -1; - e.NoexpendReagent3 = row[68] ? static_cast(atoi(row[68])) : -1; - e.NoexpendReagent4 = row[69] ? static_cast(atoi(row[69])) : -1; - e.formula1 = row[70] ? static_cast(atoi(row[70])) : 100; - e.formula2 = row[71] ? static_cast(atoi(row[71])) : 100; - e.formula3 = row[72] ? static_cast(atoi(row[72])) : 100; - e.formula4 = row[73] ? static_cast(atoi(row[73])) : 100; - e.formula5 = row[74] ? static_cast(atoi(row[74])) : 100; - e.formula6 = row[75] ? static_cast(atoi(row[75])) : 100; - e.formula7 = row[76] ? static_cast(atoi(row[76])) : 100; - e.formula8 = row[77] ? static_cast(atoi(row[77])) : 100; - e.formula9 = row[78] ? static_cast(atoi(row[78])) : 100; - e.formula10 = row[79] ? static_cast(atoi(row[79])) : 100; - e.formula11 = row[80] ? static_cast(atoi(row[80])) : 100; - e.formula12 = row[81] ? static_cast(atoi(row[81])) : 100; - e.LightType = row[82] ? static_cast(atoi(row[82])) : 0; - e.goodEffect = row[83] ? static_cast(atoi(row[83])) : 0; - e.Activated = row[84] ? static_cast(atoi(row[84])) : 0; - e.resisttype = row[85] ? static_cast(atoi(row[85])) : 0; - e.effectid1 = row[86] ? static_cast(atoi(row[86])) : 254; - e.effectid2 = row[87] ? static_cast(atoi(row[87])) : 254; - e.effectid3 = row[88] ? static_cast(atoi(row[88])) : 254; - e.effectid4 = row[89] ? static_cast(atoi(row[89])) : 254; - e.effectid5 = row[90] ? static_cast(atoi(row[90])) : 254; - e.effectid6 = row[91] ? static_cast(atoi(row[91])) : 254; - e.effectid7 = row[92] ? static_cast(atoi(row[92])) : 254; - e.effectid8 = row[93] ? static_cast(atoi(row[93])) : 254; - e.effectid9 = row[94] ? static_cast(atoi(row[94])) : 254; - e.effectid10 = row[95] ? static_cast(atoi(row[95])) : 254; - e.effectid11 = row[96] ? static_cast(atoi(row[96])) : 254; - e.effectid12 = row[97] ? static_cast(atoi(row[97])) : 254; - e.targettype = row[98] ? static_cast(atoi(row[98])) : 2; - e.basediff = row[99] ? static_cast(atoi(row[99])) : 0; - e.skill = row[100] ? static_cast(atoi(row[100])) : 98; - e.zonetype = row[101] ? static_cast(atoi(row[101])) : -1; - e.EnvironmentType = row[102] ? static_cast(atoi(row[102])) : 0; - e.TimeOfDay = row[103] ? static_cast(atoi(row[103])) : 0; - e.classes1 = row[104] ? static_cast(atoi(row[104])) : 255; - e.classes2 = row[105] ? static_cast(atoi(row[105])) : 255; - e.classes3 = row[106] ? static_cast(atoi(row[106])) : 255; - e.classes4 = row[107] ? static_cast(atoi(row[107])) : 255; - e.classes5 = row[108] ? static_cast(atoi(row[108])) : 255; - e.classes6 = row[109] ? static_cast(atoi(row[109])) : 255; - e.classes7 = row[110] ? static_cast(atoi(row[110])) : 255; - e.classes8 = row[111] ? static_cast(atoi(row[111])) : 255; - e.classes9 = row[112] ? static_cast(atoi(row[112])) : 255; - e.classes10 = row[113] ? static_cast(atoi(row[113])) : 255; - e.classes11 = row[114] ? static_cast(atoi(row[114])) : 255; - e.classes12 = row[115] ? static_cast(atoi(row[115])) : 255; - e.classes13 = row[116] ? static_cast(atoi(row[116])) : 255; - e.classes14 = row[117] ? static_cast(atoi(row[117])) : 255; - e.classes15 = row[118] ? static_cast(atoi(row[118])) : 255; - e.classes16 = row[119] ? static_cast(atoi(row[119])) : 255; - e.CastingAnim = row[120] ? static_cast(atoi(row[120])) : 44; - e.TargetAnim = row[121] ? static_cast(atoi(row[121])) : 13; - e.TravelType = row[122] ? static_cast(atoi(row[122])) : 0; - e.SpellAffectIndex = row[123] ? static_cast(atoi(row[123])) : -1; - e.disallow_sit = row[124] ? static_cast(atoi(row[124])) : 0; - e.deities0 = row[125] ? static_cast(atoi(row[125])) : 0; - e.deities1 = row[126] ? static_cast(atoi(row[126])) : 0; - e.deities2 = row[127] ? static_cast(atoi(row[127])) : 0; - e.deities3 = row[128] ? static_cast(atoi(row[128])) : 0; - e.deities4 = row[129] ? static_cast(atoi(row[129])) : 0; - e.deities5 = row[130] ? static_cast(atoi(row[130])) : 0; - e.deities6 = row[131] ? static_cast(atoi(row[131])) : 0; - e.deities7 = row[132] ? static_cast(atoi(row[132])) : 0; - e.deities8 = row[133] ? static_cast(atoi(row[133])) : 0; - e.deities9 = row[134] ? static_cast(atoi(row[134])) : 0; - e.deities10 = row[135] ? static_cast(atoi(row[135])) : 0; - e.deities11 = row[136] ? static_cast(atoi(row[136])) : 0; - e.deities12 = row[137] ? static_cast(atoi(row[137])) : 0; - e.deities13 = row[138] ? static_cast(atoi(row[138])) : 0; - e.deities14 = row[139] ? static_cast(atoi(row[139])) : 0; - e.deities15 = row[140] ? static_cast(atoi(row[140])) : 0; - e.deities16 = row[141] ? static_cast(atoi(row[141])) : 0; - e.field142 = row[142] ? static_cast(atoi(row[142])) : 100; - e.field143 = row[143] ? static_cast(atoi(row[143])) : 0; - e.new_icon = row[144] ? static_cast(atoi(row[144])) : 161; - e.spellanim = row[145] ? static_cast(atoi(row[145])) : 0; - e.uninterruptable = row[146] ? static_cast(atoi(row[146])) : 0; - e.ResistDiff = row[147] ? static_cast(atoi(row[147])) : -150; - e.dot_stacking_exempt = row[148] ? static_cast(atoi(row[148])) : 0; - e.deleteable = row[149] ? static_cast(atoi(row[149])) : 0; - e.RecourseLink = row[150] ? static_cast(atoi(row[150])) : 0; - e.no_partial_resist = row[151] ? static_cast(atoi(row[151])) : 0; - e.field152 = row[152] ? static_cast(atoi(row[152])) : 0; - e.field153 = row[153] ? static_cast(atoi(row[153])) : 0; - e.short_buff_box = row[154] ? static_cast(atoi(row[154])) : -1; - e.descnum = row[155] ? static_cast(atoi(row[155])) : 0; - e.typedescnum = row[156] ? static_cast(atoi(row[156])) : 0; - e.effectdescnum = row[157] ? static_cast(atoi(row[157])) : 0; - e.effectdescnum2 = row[158] ? static_cast(atoi(row[158])) : 0; - e.npc_no_los = row[159] ? static_cast(atoi(row[159])) : 0; - e.field160 = row[160] ? static_cast(atoi(row[160])) : 0; - e.reflectable = row[161] ? static_cast(atoi(row[161])) : 0; - e.bonushate = row[162] ? static_cast(atoi(row[162])) : 0; - e.field163 = row[163] ? static_cast(atoi(row[163])) : 100; - e.field164 = row[164] ? static_cast(atoi(row[164])) : -150; - e.ldon_trap = row[165] ? static_cast(atoi(row[165])) : 0; - e.EndurCost = row[166] ? static_cast(atoi(row[166])) : 0; - e.EndurTimerIndex = row[167] ? static_cast(atoi(row[167])) : 0; - e.IsDiscipline = row[168] ? static_cast(atoi(row[168])) : 0; - e.field169 = row[169] ? static_cast(atoi(row[169])) : 0; - e.field170 = row[170] ? static_cast(atoi(row[170])) : 0; - e.field171 = row[171] ? static_cast(atoi(row[171])) : 0; - e.field172 = row[172] ? static_cast(atoi(row[172])) : 0; - e.HateAdded = row[173] ? static_cast(atoi(row[173])) : 0; - e.EndurUpkeep = row[174] ? static_cast(atoi(row[174])) : 0; - e.numhitstype = row[175] ? static_cast(atoi(row[175])) : 0; - e.numhits = row[176] ? static_cast(atoi(row[176])) : 0; - e.pvpresistbase = row[177] ? static_cast(atoi(row[177])) : -150; - e.pvpresistcalc = row[178] ? static_cast(atoi(row[178])) : 100; - e.pvpresistcap = row[179] ? static_cast(atoi(row[179])) : -150; - e.spell_category = row[180] ? static_cast(atoi(row[180])) : -99; - e.pvp_duration = row[181] ? static_cast(atoi(row[181])) : 0; - e.pvp_duration_cap = row[182] ? static_cast(atoi(row[182])) : 0; - e.pcnpc_only_flag = row[183] ? static_cast(atoi(row[183])) : 0; - e.cast_not_standing = row[184] ? static_cast(atoi(row[184])) : 0; - e.can_mgb = row[185] ? static_cast(atoi(row[185])) : 0; - e.nodispell = row[186] ? static_cast(atoi(row[186])) : -1; - e.npc_category = row[187] ? static_cast(atoi(row[187])) : 0; - e.npc_usefulness = row[188] ? static_cast(atoi(row[188])) : 0; - e.MinResist = row[189] ? static_cast(atoi(row[189])) : 0; - e.MaxResist = row[190] ? static_cast(atoi(row[190])) : 0; - e.viral_targets = row[191] ? static_cast(atoi(row[191])) : 0; - e.viral_timer = row[192] ? static_cast(atoi(row[192])) : 0; - e.nimbuseffect = row[193] ? static_cast(atoi(row[193])) : 0; - e.ConeStartAngle = row[194] ? static_cast(atoi(row[194])) : 0; - e.ConeStopAngle = row[195] ? static_cast(atoi(row[195])) : 0; - e.sneaking = row[196] ? static_cast(atoi(row[196])) : 0; - e.not_extendable = row[197] ? static_cast(atoi(row[197])) : 0; - e.field198 = row[198] ? static_cast(atoi(row[198])) : 0; - e.field199 = row[199] ? static_cast(atoi(row[199])) : 1; - e.suspendable = row[200] ? static_cast(atoi(row[200])) : 0; - e.viral_range = row[201] ? static_cast(atoi(row[201])) : 0; - e.songcap = row[202] ? static_cast(atoi(row[202])) : 0; - e.field203 = row[203] ? static_cast(atoi(row[203])) : 0; - e.field204 = row[204] ? static_cast(atoi(row[204])) : 0; - e.no_block = row[205] ? static_cast(atoi(row[205])) : 0; - e.field206 = row[206] ? static_cast(atoi(row[206])) : -1; - e.spellgroup = row[207] ? static_cast(atoi(row[207])) : 0; - e.rank_ = row[208] ? static_cast(atoi(row[208])) : 0; - e.field209 = row[209] ? static_cast(atoi(row[209])) : 0; - e.field210 = row[210] ? static_cast(atoi(row[210])) : 1; - e.CastRestriction = row[211] ? static_cast(atoi(row[211])) : 0; - e.allowrest = row[212] ? static_cast(atoi(row[212])) : 0; - e.InCombat = row[213] ? static_cast(atoi(row[213])) : 0; - e.OutofCombat = row[214] ? static_cast(atoi(row[214])) : 0; - e.field215 = row[215] ? static_cast(atoi(row[215])) : 0; - e.field216 = row[216] ? static_cast(atoi(row[216])) : 0; - e.field217 = row[217] ? static_cast(atoi(row[217])) : 0; - e.aemaxtargets = row[218] ? static_cast(atoi(row[218])) : 0; - e.maxtargets = row[219] ? static_cast(atoi(row[219])) : 0; - e.field220 = row[220] ? static_cast(atoi(row[220])) : 0; - e.field221 = row[221] ? static_cast(atoi(row[221])) : 0; - e.field222 = row[222] ? static_cast(atoi(row[222])) : 0; - e.field223 = row[223] ? static_cast(atoi(row[223])) : 0; - e.persistdeath = row[224] ? static_cast(atoi(row[224])) : 0; - e.field225 = row[225] ? static_cast(atoi(row[225])) : 0; - e.field226 = row[226] ? static_cast(atoi(row[226])) : 0; - e.min_dist = row[227] ? strtof(row[227], nullptr) : 0; - e.min_dist_mod = row[228] ? strtof(row[228], nullptr) : 0; - e.max_dist = row[229] ? strtof(row[229], nullptr) : 0; - e.max_dist_mod = row[230] ? strtof(row[230], nullptr) : 0; - e.min_range = row[231] ? static_cast(atoi(row[231])) : 0; - e.field232 = row[232] ? static_cast(atoi(row[232])) : 0; - e.field233 = row[233] ? static_cast(atoi(row[233])) : 0; - e.field234 = row[234] ? static_cast(atoi(row[234])) : 0; - e.field235 = row[235] ? static_cast(atoi(row[235])) : 0; - e.field236 = row[236] ? static_cast(atoi(row[236])) : 0; + e.id = row[0] ? static_cast(atoi(row[0])) : 0; + e.name = row[1] ? row[1] : ""; + e.player_1 = row[2] ? row[2] : "BLUE_TRAIL"; + e.teleport_zone = row[3] ? row[3] : ""; + e.you_cast = row[4] ? row[4] : ""; + e.other_casts = row[5] ? row[5] : ""; + e.cast_on_you = row[6] ? row[6] : ""; + e.cast_on_other = row[7] ? row[7] : ""; + e.spell_fades = row[8] ? row[8] : ""; + e.range_ = row[9] ? static_cast(atoi(row[9])) : 100; + e.aoerange = row[10] ? static_cast(atoi(row[10])) : 0; + e.pushback = row[11] ? static_cast(atoi(row[11])) : 0; + e.pushup = row[12] ? static_cast(atoi(row[12])) : 0; + e.cast_time = row[13] ? static_cast(atoi(row[13])) : 0; + e.recovery_time = row[14] ? static_cast(atoi(row[14])) : 0; + e.recast_time = row[15] ? static_cast(atoi(row[15])) : 0; + e.buffdurationformula = row[16] ? static_cast(atoi(row[16])) : 7; + e.buffduration = row[17] ? static_cast(atoi(row[17])) : 65; + e.AEDuration = row[18] ? static_cast(atoi(row[18])) : 0; + e.mana = row[19] ? static_cast(atoi(row[19])) : 0; + e.effect_base_value1 = row[20] ? static_cast(atoi(row[20])) : 100; + e.effect_base_value2 = row[21] ? static_cast(atoi(row[21])) : 0; + e.effect_base_value3 = row[22] ? static_cast(atoi(row[22])) : 0; + e.effect_base_value4 = row[23] ? static_cast(atoi(row[23])) : 0; + e.effect_base_value5 = row[24] ? static_cast(atoi(row[24])) : 0; + e.effect_base_value6 = row[25] ? static_cast(atoi(row[25])) : 0; + e.effect_base_value7 = row[26] ? static_cast(atoi(row[26])) : 0; + e.effect_base_value8 = row[27] ? static_cast(atoi(row[27])) : 0; + e.effect_base_value9 = row[28] ? static_cast(atoi(row[28])) : 0; + e.effect_base_value10 = row[29] ? static_cast(atoi(row[29])) : 0; + e.effect_base_value11 = row[30] ? static_cast(atoi(row[30])) : 0; + e.effect_base_value12 = row[31] ? static_cast(atoi(row[31])) : 0; + e.effect_limit_value1 = row[32] ? static_cast(atoi(row[32])) : 0; + e.effect_limit_value2 = row[33] ? static_cast(atoi(row[33])) : 0; + e.effect_limit_value3 = row[34] ? static_cast(atoi(row[34])) : 0; + e.effect_limit_value4 = row[35] ? static_cast(atoi(row[35])) : 0; + e.effect_limit_value5 = row[36] ? static_cast(atoi(row[36])) : 0; + e.effect_limit_value6 = row[37] ? static_cast(atoi(row[37])) : 0; + e.effect_limit_value7 = row[38] ? static_cast(atoi(row[38])) : 0; + e.effect_limit_value8 = row[39] ? static_cast(atoi(row[39])) : 0; + e.effect_limit_value9 = row[40] ? static_cast(atoi(row[40])) : 0; + e.effect_limit_value10 = row[41] ? static_cast(atoi(row[41])) : 0; + e.effect_limit_value11 = row[42] ? static_cast(atoi(row[42])) : 0; + e.effect_limit_value12 = row[43] ? static_cast(atoi(row[43])) : 0; + e.max1 = row[44] ? static_cast(atoi(row[44])) : 0; + e.max2 = row[45] ? static_cast(atoi(row[45])) : 0; + e.max3 = row[46] ? static_cast(atoi(row[46])) : 0; + e.max4 = row[47] ? static_cast(atoi(row[47])) : 0; + e.max5 = row[48] ? static_cast(atoi(row[48])) : 0; + e.max6 = row[49] ? static_cast(atoi(row[49])) : 0; + e.max7 = row[50] ? static_cast(atoi(row[50])) : 0; + e.max8 = row[51] ? static_cast(atoi(row[51])) : 0; + e.max9 = row[52] ? static_cast(atoi(row[52])) : 0; + e.max10 = row[53] ? static_cast(atoi(row[53])) : 0; + e.max11 = row[54] ? static_cast(atoi(row[54])) : 0; + e.max12 = row[55] ? static_cast(atoi(row[55])) : 0; + e.icon = row[56] ? static_cast(atoi(row[56])) : 0; + e.memicon = row[57] ? static_cast(atoi(row[57])) : 0; + e.components1 = row[58] ? static_cast(atoi(row[58])) : -1; + e.components2 = row[59] ? static_cast(atoi(row[59])) : -1; + e.components3 = row[60] ? static_cast(atoi(row[60])) : -1; + e.components4 = row[61] ? static_cast(atoi(row[61])) : -1; + e.component_counts1 = row[62] ? static_cast(atoi(row[62])) : 1; + e.component_counts2 = row[63] ? static_cast(atoi(row[63])) : 1; + e.component_counts3 = row[64] ? static_cast(atoi(row[64])) : 1; + e.component_counts4 = row[65] ? static_cast(atoi(row[65])) : 1; + e.NoexpendReagent1 = row[66] ? static_cast(atoi(row[66])) : -1; + e.NoexpendReagent2 = row[67] ? static_cast(atoi(row[67])) : -1; + e.NoexpendReagent3 = row[68] ? static_cast(atoi(row[68])) : -1; + e.NoexpendReagent4 = row[69] ? static_cast(atoi(row[69])) : -1; + e.formula1 = row[70] ? static_cast(atoi(row[70])) : 100; + e.formula2 = row[71] ? static_cast(atoi(row[71])) : 100; + e.formula3 = row[72] ? static_cast(atoi(row[72])) : 100; + e.formula4 = row[73] ? static_cast(atoi(row[73])) : 100; + e.formula5 = row[74] ? static_cast(atoi(row[74])) : 100; + e.formula6 = row[75] ? static_cast(atoi(row[75])) : 100; + e.formula7 = row[76] ? static_cast(atoi(row[76])) : 100; + e.formula8 = row[77] ? static_cast(atoi(row[77])) : 100; + e.formula9 = row[78] ? static_cast(atoi(row[78])) : 100; + e.formula10 = row[79] ? static_cast(atoi(row[79])) : 100; + e.formula11 = row[80] ? static_cast(atoi(row[80])) : 100; + e.formula12 = row[81] ? static_cast(atoi(row[81])) : 100; + e.LightType = row[82] ? static_cast(atoi(row[82])) : 0; + e.goodEffect = row[83] ? static_cast(atoi(row[83])) : 0; + e.Activated = row[84] ? static_cast(atoi(row[84])) : 0; + e.resisttype = row[85] ? static_cast(atoi(row[85])) : 0; + e.effectid1 = row[86] ? static_cast(atoi(row[86])) : 254; + e.effectid2 = row[87] ? static_cast(atoi(row[87])) : 254; + e.effectid3 = row[88] ? static_cast(atoi(row[88])) : 254; + e.effectid4 = row[89] ? static_cast(atoi(row[89])) : 254; + e.effectid5 = row[90] ? static_cast(atoi(row[90])) : 254; + e.effectid6 = row[91] ? static_cast(atoi(row[91])) : 254; + e.effectid7 = row[92] ? static_cast(atoi(row[92])) : 254; + e.effectid8 = row[93] ? static_cast(atoi(row[93])) : 254; + e.effectid9 = row[94] ? static_cast(atoi(row[94])) : 254; + e.effectid10 = row[95] ? static_cast(atoi(row[95])) : 254; + e.effectid11 = row[96] ? static_cast(atoi(row[96])) : 254; + e.effectid12 = row[97] ? static_cast(atoi(row[97])) : 254; + e.targettype = row[98] ? static_cast(atoi(row[98])) : 2; + e.basediff = row[99] ? static_cast(atoi(row[99])) : 0; + e.skill = row[100] ? static_cast(atoi(row[100])) : 98; + e.zonetype = row[101] ? static_cast(atoi(row[101])) : -1; + e.EnvironmentType = row[102] ? static_cast(atoi(row[102])) : 0; + e.TimeOfDay = row[103] ? static_cast(atoi(row[103])) : 0; + e.classes1 = row[104] ? static_cast(atoi(row[104])) : 255; + e.classes2 = row[105] ? static_cast(atoi(row[105])) : 255; + e.classes3 = row[106] ? static_cast(atoi(row[106])) : 255; + e.classes4 = row[107] ? static_cast(atoi(row[107])) : 255; + e.classes5 = row[108] ? static_cast(atoi(row[108])) : 255; + e.classes6 = row[109] ? static_cast(atoi(row[109])) : 255; + e.classes7 = row[110] ? static_cast(atoi(row[110])) : 255; + e.classes8 = row[111] ? static_cast(atoi(row[111])) : 255; + e.classes9 = row[112] ? static_cast(atoi(row[112])) : 255; + e.classes10 = row[113] ? static_cast(atoi(row[113])) : 255; + e.classes11 = row[114] ? static_cast(atoi(row[114])) : 255; + e.classes12 = row[115] ? static_cast(atoi(row[115])) : 255; + e.classes13 = row[116] ? static_cast(atoi(row[116])) : 255; + e.classes14 = row[117] ? static_cast(atoi(row[117])) : 255; + e.classes15 = row[118] ? static_cast(atoi(row[118])) : 255; + e.classes16 = row[119] ? static_cast(atoi(row[119])) : 255; + e.CastingAnim = row[120] ? static_cast(atoi(row[120])) : 44; + e.TargetAnim = row[121] ? static_cast(atoi(row[121])) : 13; + e.TravelType = row[122] ? static_cast(atoi(row[122])) : 0; + e.SpellAffectIndex = row[123] ? static_cast(atoi(row[123])) : -1; + e.disallow_sit = row[124] ? static_cast(atoi(row[124])) : 0; + e.deities0 = row[125] ? static_cast(atoi(row[125])) : 0; + e.deities1 = row[126] ? static_cast(atoi(row[126])) : 0; + e.deities2 = row[127] ? static_cast(atoi(row[127])) : 0; + e.deities3 = row[128] ? static_cast(atoi(row[128])) : 0; + e.deities4 = row[129] ? static_cast(atoi(row[129])) : 0; + e.deities5 = row[130] ? static_cast(atoi(row[130])) : 0; + e.deities6 = row[131] ? static_cast(atoi(row[131])) : 0; + e.deities7 = row[132] ? static_cast(atoi(row[132])) : 0; + e.deities8 = row[133] ? static_cast(atoi(row[133])) : 0; + e.deities9 = row[134] ? static_cast(atoi(row[134])) : 0; + e.deities10 = row[135] ? static_cast(atoi(row[135])) : 0; + e.deities11 = row[136] ? static_cast(atoi(row[136])) : 0; + e.deities12 = row[137] ? static_cast(atoi(row[137])) : 0; + e.deities13 = row[138] ? static_cast(atoi(row[138])) : 0; + e.deities14 = row[139] ? static_cast(atoi(row[139])) : 0; + e.deities15 = row[140] ? static_cast(atoi(row[140])) : 0; + e.deities16 = row[141] ? static_cast(atoi(row[141])) : 0; + e.field142 = row[142] ? static_cast(atoi(row[142])) : 100; + e.field143 = row[143] ? static_cast(atoi(row[143])) : 0; + e.new_icon = row[144] ? static_cast(atoi(row[144])) : 161; + e.spellanim = row[145] ? static_cast(atoi(row[145])) : 0; + e.uninterruptable = row[146] ? static_cast(atoi(row[146])) : 0; + e.ResistDiff = row[147] ? static_cast(atoi(row[147])) : -150; + e.dot_stacking_exempt = row[148] ? static_cast(atoi(row[148])) : 0; + e.deleteable = row[149] ? static_cast(atoi(row[149])) : 0; + e.RecourseLink = row[150] ? static_cast(atoi(row[150])) : 0; + e.no_partial_resist = row[151] ? static_cast(atoi(row[151])) : 0; + e.field152 = row[152] ? static_cast(atoi(row[152])) : 0; + e.field153 = row[153] ? static_cast(atoi(row[153])) : 0; + e.short_buff_box = row[154] ? static_cast(atoi(row[154])) : -1; + e.descnum = row[155] ? static_cast(atoi(row[155])) : 0; + e.typedescnum = row[156] ? static_cast(atoi(row[156])) : 0; + e.effectdescnum = row[157] ? static_cast(atoi(row[157])) : 0; + e.effectdescnum2 = row[158] ? static_cast(atoi(row[158])) : 0; + e.npc_no_los = row[159] ? static_cast(atoi(row[159])) : 0; + e.feedbackable = row[160] ? static_cast(atoi(row[160])) : 0; + e.reflectable = row[161] ? static_cast(atoi(row[161])) : 0; + e.bonushate = row[162] ? static_cast(atoi(row[162])) : 0; + e.field163 = row[163] ? static_cast(atoi(row[163])) : 100; + e.field164 = row[164] ? static_cast(atoi(row[164])) : -150; + e.ldon_trap = row[165] ? static_cast(atoi(row[165])) : 0; + e.EndurCost = row[166] ? static_cast(atoi(row[166])) : 0; + e.EndurTimerIndex = row[167] ? static_cast(atoi(row[167])) : 0; + e.IsDiscipline = row[168] ? static_cast(atoi(row[168])) : 0; + e.field169 = row[169] ? static_cast(atoi(row[169])) : 0; + e.field170 = row[170] ? static_cast(atoi(row[170])) : 0; + e.field171 = row[171] ? static_cast(atoi(row[171])) : 0; + e.field172 = row[172] ? static_cast(atoi(row[172])) : 0; + e.HateAdded = row[173] ? static_cast(atoi(row[173])) : 0; + e.EndurUpkeep = row[174] ? static_cast(atoi(row[174])) : 0; + e.numhitstype = row[175] ? static_cast(atoi(row[175])) : 0; + e.numhits = row[176] ? static_cast(atoi(row[176])) : 0; + e.pvpresistbase = row[177] ? static_cast(atoi(row[177])) : -150; + e.pvpresistcalc = row[178] ? static_cast(atoi(row[178])) : 100; + e.pvpresistcap = row[179] ? static_cast(atoi(row[179])) : -150; + e.spell_category = row[180] ? static_cast(atoi(row[180])) : -99; + e.pvp_duration = row[181] ? static_cast(atoi(row[181])) : 0; + e.pvp_duration_cap = row[182] ? static_cast(atoi(row[182])) : 0; + e.pcnpc_only_flag = row[183] ? static_cast(atoi(row[183])) : 0; + e.cast_not_standing = row[184] ? static_cast(atoi(row[184])) : 0; + e.can_mgb = row[185] ? static_cast(atoi(row[185])) : 0; + e.nodispell = row[186] ? static_cast(atoi(row[186])) : -1; + e.npc_category = row[187] ? static_cast(atoi(row[187])) : 0; + e.npc_usefulness = row[188] ? static_cast(atoi(row[188])) : 0; + e.MinResist = row[189] ? static_cast(atoi(row[189])) : 0; + e.MaxResist = row[190] ? static_cast(atoi(row[190])) : 0; + e.viral_targets = row[191] ? static_cast(atoi(row[191])) : 0; + e.viral_timer = row[192] ? static_cast(atoi(row[192])) : 0; + e.nimbuseffect = row[193] ? static_cast(atoi(row[193])) : 0; + e.ConeStartAngle = row[194] ? static_cast(atoi(row[194])) : 0; + e.ConeStopAngle = row[195] ? static_cast(atoi(row[195])) : 0; + e.sneaking = row[196] ? static_cast(atoi(row[196])) : 0; + e.not_extendable = row[197] ? static_cast(atoi(row[197])) : 0; + e.no_detrimental_spell_aggro = row[198] ? static_cast(atoi(row[198])) : 0; + e.field199 = row[199] ? static_cast(atoi(row[199])) : 1; + e.suspendable = row[200] ? static_cast(atoi(row[200])) : 0; + e.viral_range = row[201] ? static_cast(atoi(row[201])) : 0; + e.songcap = row[202] ? static_cast(atoi(row[202])) : 0; + e.field203 = row[203] ? static_cast(atoi(row[203])) : 0; + e.field204 = row[204] ? static_cast(atoi(row[204])) : 0; + e.no_block = row[205] ? static_cast(atoi(row[205])) : 0; + e.field206 = row[206] ? static_cast(atoi(row[206])) : -1; + e.spellgroup = row[207] ? static_cast(atoi(row[207])) : 0; + e.rank_ = row[208] ? static_cast(atoi(row[208])) : 0; + e.no_resist = row[209] ? static_cast(atoi(row[209])) : 0; + e.field210 = row[210] ? static_cast(atoi(row[210])) : 1; + e.CastRestriction = row[211] ? static_cast(atoi(row[211])) : 0; + e.allowrest = row[212] ? static_cast(atoi(row[212])) : 0; + e.InCombat = row[213] ? static_cast(atoi(row[213])) : 0; + e.OutofCombat = row[214] ? static_cast(atoi(row[214])) : 0; + e.field215 = row[215] ? static_cast(atoi(row[215])) : 0; + e.field216 = row[216] ? static_cast(atoi(row[216])) : 0; + e.override_crit_chance = row[217] ? static_cast(atoi(row[217])) : 0; + e.aemaxtargets = row[218] ? static_cast(atoi(row[218])) : 0; + e.maxtargets = row[219] ? static_cast(atoi(row[219])) : 0; + e.no_heal_damage_item_mod = row[220] ? static_cast(atoi(row[220])) : 0; + e.caster_requirement_id = row[221] ? static_cast(atoi(row[221])) : 0; + e.spell_class = row[222] ? static_cast(atoi(row[222])) : 0; + e.spell_subclass = row[223] ? static_cast(atoi(row[223])) : 0; + e.persistdeath = row[224] ? static_cast(atoi(row[224])) : 0; + e.field225 = row[225] ? static_cast(atoi(row[225])) : 0; + e.field226 = row[226] ? static_cast(atoi(row[226])) : 0; + e.min_dist = row[227] ? strtof(row[227], nullptr) : 0; + e.min_dist_mod = row[228] ? strtof(row[228], nullptr) : 0; + e.max_dist = row[229] ? strtof(row[229], nullptr) : 0; + e.max_dist_mod = row[230] ? strtof(row[230], nullptr) : 0; + e.min_range = row[231] ? static_cast(atoi(row[231])) : 0; + e.no_remove = row[232] ? static_cast(atoi(row[232])) : 0; + e.field233 = row[233] ? static_cast(atoi(row[233])) : 0; + e.field234 = row[234] ? static_cast(atoi(row[234])) : 0; + e.field235 = row[235] ? static_cast(atoi(row[235])) : 0; + e.field236 = row[236] ? static_cast(atoi(row[236])) : 0; all_entries.push_back(e); } @@ -2384,243 +2384,243 @@ class BaseSpellsNewRepository { for (auto row = results.begin(); row != results.end(); ++row) { SpellsNew e{}; - e.id = row[0] ? static_cast(atoi(row[0])) : 0; - e.name = row[1] ? row[1] : ""; - e.player_1 = row[2] ? row[2] : "BLUE_TRAIL"; - e.teleport_zone = row[3] ? row[3] : ""; - e.you_cast = row[4] ? row[4] : ""; - e.other_casts = row[5] ? row[5] : ""; - e.cast_on_you = row[6] ? row[6] : ""; - e.cast_on_other = row[7] ? row[7] : ""; - e.spell_fades = row[8] ? row[8] : ""; - e.range_ = row[9] ? static_cast(atoi(row[9])) : 100; - e.aoerange = row[10] ? static_cast(atoi(row[10])) : 0; - e.pushback = row[11] ? static_cast(atoi(row[11])) : 0; - e.pushup = row[12] ? static_cast(atoi(row[12])) : 0; - e.cast_time = row[13] ? static_cast(atoi(row[13])) : 0; - e.recovery_time = row[14] ? static_cast(atoi(row[14])) : 0; - e.recast_time = row[15] ? static_cast(atoi(row[15])) : 0; - e.buffdurationformula = row[16] ? static_cast(atoi(row[16])) : 7; - e.buffduration = row[17] ? static_cast(atoi(row[17])) : 65; - e.AEDuration = row[18] ? static_cast(atoi(row[18])) : 0; - e.mana = row[19] ? static_cast(atoi(row[19])) : 0; - e.effect_base_value1 = row[20] ? static_cast(atoi(row[20])) : 100; - e.effect_base_value2 = row[21] ? static_cast(atoi(row[21])) : 0; - e.effect_base_value3 = row[22] ? static_cast(atoi(row[22])) : 0; - e.effect_base_value4 = row[23] ? static_cast(atoi(row[23])) : 0; - e.effect_base_value5 = row[24] ? static_cast(atoi(row[24])) : 0; - e.effect_base_value6 = row[25] ? static_cast(atoi(row[25])) : 0; - e.effect_base_value7 = row[26] ? static_cast(atoi(row[26])) : 0; - e.effect_base_value8 = row[27] ? static_cast(atoi(row[27])) : 0; - e.effect_base_value9 = row[28] ? static_cast(atoi(row[28])) : 0; - e.effect_base_value10 = row[29] ? static_cast(atoi(row[29])) : 0; - e.effect_base_value11 = row[30] ? static_cast(atoi(row[30])) : 0; - e.effect_base_value12 = row[31] ? static_cast(atoi(row[31])) : 0; - e.effect_limit_value1 = row[32] ? static_cast(atoi(row[32])) : 0; - e.effect_limit_value2 = row[33] ? static_cast(atoi(row[33])) : 0; - e.effect_limit_value3 = row[34] ? static_cast(atoi(row[34])) : 0; - e.effect_limit_value4 = row[35] ? static_cast(atoi(row[35])) : 0; - e.effect_limit_value5 = row[36] ? static_cast(atoi(row[36])) : 0; - e.effect_limit_value6 = row[37] ? static_cast(atoi(row[37])) : 0; - e.effect_limit_value7 = row[38] ? static_cast(atoi(row[38])) : 0; - e.effect_limit_value8 = row[39] ? static_cast(atoi(row[39])) : 0; - e.effect_limit_value9 = row[40] ? static_cast(atoi(row[40])) : 0; - e.effect_limit_value10 = row[41] ? static_cast(atoi(row[41])) : 0; - e.effect_limit_value11 = row[42] ? static_cast(atoi(row[42])) : 0; - e.effect_limit_value12 = row[43] ? static_cast(atoi(row[43])) : 0; - e.max1 = row[44] ? static_cast(atoi(row[44])) : 0; - e.max2 = row[45] ? static_cast(atoi(row[45])) : 0; - e.max3 = row[46] ? static_cast(atoi(row[46])) : 0; - e.max4 = row[47] ? static_cast(atoi(row[47])) : 0; - e.max5 = row[48] ? static_cast(atoi(row[48])) : 0; - e.max6 = row[49] ? static_cast(atoi(row[49])) : 0; - e.max7 = row[50] ? static_cast(atoi(row[50])) : 0; - e.max8 = row[51] ? static_cast(atoi(row[51])) : 0; - e.max9 = row[52] ? static_cast(atoi(row[52])) : 0; - e.max10 = row[53] ? static_cast(atoi(row[53])) : 0; - e.max11 = row[54] ? static_cast(atoi(row[54])) : 0; - e.max12 = row[55] ? static_cast(atoi(row[55])) : 0; - e.icon = row[56] ? static_cast(atoi(row[56])) : 0; - e.memicon = row[57] ? static_cast(atoi(row[57])) : 0; - e.components1 = row[58] ? static_cast(atoi(row[58])) : -1; - e.components2 = row[59] ? static_cast(atoi(row[59])) : -1; - e.components3 = row[60] ? static_cast(atoi(row[60])) : -1; - e.components4 = row[61] ? static_cast(atoi(row[61])) : -1; - e.component_counts1 = row[62] ? static_cast(atoi(row[62])) : 1; - e.component_counts2 = row[63] ? static_cast(atoi(row[63])) : 1; - e.component_counts3 = row[64] ? static_cast(atoi(row[64])) : 1; - e.component_counts4 = row[65] ? static_cast(atoi(row[65])) : 1; - e.NoexpendReagent1 = row[66] ? static_cast(atoi(row[66])) : -1; - e.NoexpendReagent2 = row[67] ? static_cast(atoi(row[67])) : -1; - e.NoexpendReagent3 = row[68] ? static_cast(atoi(row[68])) : -1; - e.NoexpendReagent4 = row[69] ? static_cast(atoi(row[69])) : -1; - e.formula1 = row[70] ? static_cast(atoi(row[70])) : 100; - e.formula2 = row[71] ? static_cast(atoi(row[71])) : 100; - e.formula3 = row[72] ? static_cast(atoi(row[72])) : 100; - e.formula4 = row[73] ? static_cast(atoi(row[73])) : 100; - e.formula5 = row[74] ? static_cast(atoi(row[74])) : 100; - e.formula6 = row[75] ? static_cast(atoi(row[75])) : 100; - e.formula7 = row[76] ? static_cast(atoi(row[76])) : 100; - e.formula8 = row[77] ? static_cast(atoi(row[77])) : 100; - e.formula9 = row[78] ? static_cast(atoi(row[78])) : 100; - e.formula10 = row[79] ? static_cast(atoi(row[79])) : 100; - e.formula11 = row[80] ? static_cast(atoi(row[80])) : 100; - e.formula12 = row[81] ? static_cast(atoi(row[81])) : 100; - e.LightType = row[82] ? static_cast(atoi(row[82])) : 0; - e.goodEffect = row[83] ? static_cast(atoi(row[83])) : 0; - e.Activated = row[84] ? static_cast(atoi(row[84])) : 0; - e.resisttype = row[85] ? static_cast(atoi(row[85])) : 0; - e.effectid1 = row[86] ? static_cast(atoi(row[86])) : 254; - e.effectid2 = row[87] ? static_cast(atoi(row[87])) : 254; - e.effectid3 = row[88] ? static_cast(atoi(row[88])) : 254; - e.effectid4 = row[89] ? static_cast(atoi(row[89])) : 254; - e.effectid5 = row[90] ? static_cast(atoi(row[90])) : 254; - e.effectid6 = row[91] ? static_cast(atoi(row[91])) : 254; - e.effectid7 = row[92] ? static_cast(atoi(row[92])) : 254; - e.effectid8 = row[93] ? static_cast(atoi(row[93])) : 254; - e.effectid9 = row[94] ? static_cast(atoi(row[94])) : 254; - e.effectid10 = row[95] ? static_cast(atoi(row[95])) : 254; - e.effectid11 = row[96] ? static_cast(atoi(row[96])) : 254; - e.effectid12 = row[97] ? static_cast(atoi(row[97])) : 254; - e.targettype = row[98] ? static_cast(atoi(row[98])) : 2; - e.basediff = row[99] ? static_cast(atoi(row[99])) : 0; - e.skill = row[100] ? static_cast(atoi(row[100])) : 98; - e.zonetype = row[101] ? static_cast(atoi(row[101])) : -1; - e.EnvironmentType = row[102] ? static_cast(atoi(row[102])) : 0; - e.TimeOfDay = row[103] ? static_cast(atoi(row[103])) : 0; - e.classes1 = row[104] ? static_cast(atoi(row[104])) : 255; - e.classes2 = row[105] ? static_cast(atoi(row[105])) : 255; - e.classes3 = row[106] ? static_cast(atoi(row[106])) : 255; - e.classes4 = row[107] ? static_cast(atoi(row[107])) : 255; - e.classes5 = row[108] ? static_cast(atoi(row[108])) : 255; - e.classes6 = row[109] ? static_cast(atoi(row[109])) : 255; - e.classes7 = row[110] ? static_cast(atoi(row[110])) : 255; - e.classes8 = row[111] ? static_cast(atoi(row[111])) : 255; - e.classes9 = row[112] ? static_cast(atoi(row[112])) : 255; - e.classes10 = row[113] ? static_cast(atoi(row[113])) : 255; - e.classes11 = row[114] ? static_cast(atoi(row[114])) : 255; - e.classes12 = row[115] ? static_cast(atoi(row[115])) : 255; - e.classes13 = row[116] ? static_cast(atoi(row[116])) : 255; - e.classes14 = row[117] ? static_cast(atoi(row[117])) : 255; - e.classes15 = row[118] ? static_cast(atoi(row[118])) : 255; - e.classes16 = row[119] ? static_cast(atoi(row[119])) : 255; - e.CastingAnim = row[120] ? static_cast(atoi(row[120])) : 44; - e.TargetAnim = row[121] ? static_cast(atoi(row[121])) : 13; - e.TravelType = row[122] ? static_cast(atoi(row[122])) : 0; - e.SpellAffectIndex = row[123] ? static_cast(atoi(row[123])) : -1; - e.disallow_sit = row[124] ? static_cast(atoi(row[124])) : 0; - e.deities0 = row[125] ? static_cast(atoi(row[125])) : 0; - e.deities1 = row[126] ? static_cast(atoi(row[126])) : 0; - e.deities2 = row[127] ? static_cast(atoi(row[127])) : 0; - e.deities3 = row[128] ? static_cast(atoi(row[128])) : 0; - e.deities4 = row[129] ? static_cast(atoi(row[129])) : 0; - e.deities5 = row[130] ? static_cast(atoi(row[130])) : 0; - e.deities6 = row[131] ? static_cast(atoi(row[131])) : 0; - e.deities7 = row[132] ? static_cast(atoi(row[132])) : 0; - e.deities8 = row[133] ? static_cast(atoi(row[133])) : 0; - e.deities9 = row[134] ? static_cast(atoi(row[134])) : 0; - e.deities10 = row[135] ? static_cast(atoi(row[135])) : 0; - e.deities11 = row[136] ? static_cast(atoi(row[136])) : 0; - e.deities12 = row[137] ? static_cast(atoi(row[137])) : 0; - e.deities13 = row[138] ? static_cast(atoi(row[138])) : 0; - e.deities14 = row[139] ? static_cast(atoi(row[139])) : 0; - e.deities15 = row[140] ? static_cast(atoi(row[140])) : 0; - e.deities16 = row[141] ? static_cast(atoi(row[141])) : 0; - e.field142 = row[142] ? static_cast(atoi(row[142])) : 100; - e.field143 = row[143] ? static_cast(atoi(row[143])) : 0; - e.new_icon = row[144] ? static_cast(atoi(row[144])) : 161; - e.spellanim = row[145] ? static_cast(atoi(row[145])) : 0; - e.uninterruptable = row[146] ? static_cast(atoi(row[146])) : 0; - e.ResistDiff = row[147] ? static_cast(atoi(row[147])) : -150; - e.dot_stacking_exempt = row[148] ? static_cast(atoi(row[148])) : 0; - e.deleteable = row[149] ? static_cast(atoi(row[149])) : 0; - e.RecourseLink = row[150] ? static_cast(atoi(row[150])) : 0; - e.no_partial_resist = row[151] ? static_cast(atoi(row[151])) : 0; - e.field152 = row[152] ? static_cast(atoi(row[152])) : 0; - e.field153 = row[153] ? static_cast(atoi(row[153])) : 0; - e.short_buff_box = row[154] ? static_cast(atoi(row[154])) : -1; - e.descnum = row[155] ? static_cast(atoi(row[155])) : 0; - e.typedescnum = row[156] ? static_cast(atoi(row[156])) : 0; - e.effectdescnum = row[157] ? static_cast(atoi(row[157])) : 0; - e.effectdescnum2 = row[158] ? static_cast(atoi(row[158])) : 0; - e.npc_no_los = row[159] ? static_cast(atoi(row[159])) : 0; - e.field160 = row[160] ? static_cast(atoi(row[160])) : 0; - e.reflectable = row[161] ? static_cast(atoi(row[161])) : 0; - e.bonushate = row[162] ? static_cast(atoi(row[162])) : 0; - e.field163 = row[163] ? static_cast(atoi(row[163])) : 100; - e.field164 = row[164] ? static_cast(atoi(row[164])) : -150; - e.ldon_trap = row[165] ? static_cast(atoi(row[165])) : 0; - e.EndurCost = row[166] ? static_cast(atoi(row[166])) : 0; - e.EndurTimerIndex = row[167] ? static_cast(atoi(row[167])) : 0; - e.IsDiscipline = row[168] ? static_cast(atoi(row[168])) : 0; - e.field169 = row[169] ? static_cast(atoi(row[169])) : 0; - e.field170 = row[170] ? static_cast(atoi(row[170])) : 0; - e.field171 = row[171] ? static_cast(atoi(row[171])) : 0; - e.field172 = row[172] ? static_cast(atoi(row[172])) : 0; - e.HateAdded = row[173] ? static_cast(atoi(row[173])) : 0; - e.EndurUpkeep = row[174] ? static_cast(atoi(row[174])) : 0; - e.numhitstype = row[175] ? static_cast(atoi(row[175])) : 0; - e.numhits = row[176] ? static_cast(atoi(row[176])) : 0; - e.pvpresistbase = row[177] ? static_cast(atoi(row[177])) : -150; - e.pvpresistcalc = row[178] ? static_cast(atoi(row[178])) : 100; - e.pvpresistcap = row[179] ? static_cast(atoi(row[179])) : -150; - e.spell_category = row[180] ? static_cast(atoi(row[180])) : -99; - e.pvp_duration = row[181] ? static_cast(atoi(row[181])) : 0; - e.pvp_duration_cap = row[182] ? static_cast(atoi(row[182])) : 0; - e.pcnpc_only_flag = row[183] ? static_cast(atoi(row[183])) : 0; - e.cast_not_standing = row[184] ? static_cast(atoi(row[184])) : 0; - e.can_mgb = row[185] ? static_cast(atoi(row[185])) : 0; - e.nodispell = row[186] ? static_cast(atoi(row[186])) : -1; - e.npc_category = row[187] ? static_cast(atoi(row[187])) : 0; - e.npc_usefulness = row[188] ? static_cast(atoi(row[188])) : 0; - e.MinResist = row[189] ? static_cast(atoi(row[189])) : 0; - e.MaxResist = row[190] ? static_cast(atoi(row[190])) : 0; - e.viral_targets = row[191] ? static_cast(atoi(row[191])) : 0; - e.viral_timer = row[192] ? static_cast(atoi(row[192])) : 0; - e.nimbuseffect = row[193] ? static_cast(atoi(row[193])) : 0; - e.ConeStartAngle = row[194] ? static_cast(atoi(row[194])) : 0; - e.ConeStopAngle = row[195] ? static_cast(atoi(row[195])) : 0; - e.sneaking = row[196] ? static_cast(atoi(row[196])) : 0; - e.not_extendable = row[197] ? static_cast(atoi(row[197])) : 0; - e.field198 = row[198] ? static_cast(atoi(row[198])) : 0; - e.field199 = row[199] ? static_cast(atoi(row[199])) : 1; - e.suspendable = row[200] ? static_cast(atoi(row[200])) : 0; - e.viral_range = row[201] ? static_cast(atoi(row[201])) : 0; - e.songcap = row[202] ? static_cast(atoi(row[202])) : 0; - e.field203 = row[203] ? static_cast(atoi(row[203])) : 0; - e.field204 = row[204] ? static_cast(atoi(row[204])) : 0; - e.no_block = row[205] ? static_cast(atoi(row[205])) : 0; - e.field206 = row[206] ? static_cast(atoi(row[206])) : -1; - e.spellgroup = row[207] ? static_cast(atoi(row[207])) : 0; - e.rank_ = row[208] ? static_cast(atoi(row[208])) : 0; - e.field209 = row[209] ? static_cast(atoi(row[209])) : 0; - e.field210 = row[210] ? static_cast(atoi(row[210])) : 1; - e.CastRestriction = row[211] ? static_cast(atoi(row[211])) : 0; - e.allowrest = row[212] ? static_cast(atoi(row[212])) : 0; - e.InCombat = row[213] ? static_cast(atoi(row[213])) : 0; - e.OutofCombat = row[214] ? static_cast(atoi(row[214])) : 0; - e.field215 = row[215] ? static_cast(atoi(row[215])) : 0; - e.field216 = row[216] ? static_cast(atoi(row[216])) : 0; - e.field217 = row[217] ? static_cast(atoi(row[217])) : 0; - e.aemaxtargets = row[218] ? static_cast(atoi(row[218])) : 0; - e.maxtargets = row[219] ? static_cast(atoi(row[219])) : 0; - e.field220 = row[220] ? static_cast(atoi(row[220])) : 0; - e.field221 = row[221] ? static_cast(atoi(row[221])) : 0; - e.field222 = row[222] ? static_cast(atoi(row[222])) : 0; - e.field223 = row[223] ? static_cast(atoi(row[223])) : 0; - e.persistdeath = row[224] ? static_cast(atoi(row[224])) : 0; - e.field225 = row[225] ? static_cast(atoi(row[225])) : 0; - e.field226 = row[226] ? static_cast(atoi(row[226])) : 0; - e.min_dist = row[227] ? strtof(row[227], nullptr) : 0; - e.min_dist_mod = row[228] ? strtof(row[228], nullptr) : 0; - e.max_dist = row[229] ? strtof(row[229], nullptr) : 0; - e.max_dist_mod = row[230] ? strtof(row[230], nullptr) : 0; - e.min_range = row[231] ? static_cast(atoi(row[231])) : 0; - e.field232 = row[232] ? static_cast(atoi(row[232])) : 0; - e.field233 = row[233] ? static_cast(atoi(row[233])) : 0; - e.field234 = row[234] ? static_cast(atoi(row[234])) : 0; - e.field235 = row[235] ? static_cast(atoi(row[235])) : 0; - e.field236 = row[236] ? static_cast(atoi(row[236])) : 0; + e.id = row[0] ? static_cast(atoi(row[0])) : 0; + e.name = row[1] ? row[1] : ""; + e.player_1 = row[2] ? row[2] : "BLUE_TRAIL"; + e.teleport_zone = row[3] ? row[3] : ""; + e.you_cast = row[4] ? row[4] : ""; + e.other_casts = row[5] ? row[5] : ""; + e.cast_on_you = row[6] ? row[6] : ""; + e.cast_on_other = row[7] ? row[7] : ""; + e.spell_fades = row[8] ? row[8] : ""; + e.range_ = row[9] ? static_cast(atoi(row[9])) : 100; + e.aoerange = row[10] ? static_cast(atoi(row[10])) : 0; + e.pushback = row[11] ? static_cast(atoi(row[11])) : 0; + e.pushup = row[12] ? static_cast(atoi(row[12])) : 0; + e.cast_time = row[13] ? static_cast(atoi(row[13])) : 0; + e.recovery_time = row[14] ? static_cast(atoi(row[14])) : 0; + e.recast_time = row[15] ? static_cast(atoi(row[15])) : 0; + e.buffdurationformula = row[16] ? static_cast(atoi(row[16])) : 7; + e.buffduration = row[17] ? static_cast(atoi(row[17])) : 65; + e.AEDuration = row[18] ? static_cast(atoi(row[18])) : 0; + e.mana = row[19] ? static_cast(atoi(row[19])) : 0; + e.effect_base_value1 = row[20] ? static_cast(atoi(row[20])) : 100; + e.effect_base_value2 = row[21] ? static_cast(atoi(row[21])) : 0; + e.effect_base_value3 = row[22] ? static_cast(atoi(row[22])) : 0; + e.effect_base_value4 = row[23] ? static_cast(atoi(row[23])) : 0; + e.effect_base_value5 = row[24] ? static_cast(atoi(row[24])) : 0; + e.effect_base_value6 = row[25] ? static_cast(atoi(row[25])) : 0; + e.effect_base_value7 = row[26] ? static_cast(atoi(row[26])) : 0; + e.effect_base_value8 = row[27] ? static_cast(atoi(row[27])) : 0; + e.effect_base_value9 = row[28] ? static_cast(atoi(row[28])) : 0; + e.effect_base_value10 = row[29] ? static_cast(atoi(row[29])) : 0; + e.effect_base_value11 = row[30] ? static_cast(atoi(row[30])) : 0; + e.effect_base_value12 = row[31] ? static_cast(atoi(row[31])) : 0; + e.effect_limit_value1 = row[32] ? static_cast(atoi(row[32])) : 0; + e.effect_limit_value2 = row[33] ? static_cast(atoi(row[33])) : 0; + e.effect_limit_value3 = row[34] ? static_cast(atoi(row[34])) : 0; + e.effect_limit_value4 = row[35] ? static_cast(atoi(row[35])) : 0; + e.effect_limit_value5 = row[36] ? static_cast(atoi(row[36])) : 0; + e.effect_limit_value6 = row[37] ? static_cast(atoi(row[37])) : 0; + e.effect_limit_value7 = row[38] ? static_cast(atoi(row[38])) : 0; + e.effect_limit_value8 = row[39] ? static_cast(atoi(row[39])) : 0; + e.effect_limit_value9 = row[40] ? static_cast(atoi(row[40])) : 0; + e.effect_limit_value10 = row[41] ? static_cast(atoi(row[41])) : 0; + e.effect_limit_value11 = row[42] ? static_cast(atoi(row[42])) : 0; + e.effect_limit_value12 = row[43] ? static_cast(atoi(row[43])) : 0; + e.max1 = row[44] ? static_cast(atoi(row[44])) : 0; + e.max2 = row[45] ? static_cast(atoi(row[45])) : 0; + e.max3 = row[46] ? static_cast(atoi(row[46])) : 0; + e.max4 = row[47] ? static_cast(atoi(row[47])) : 0; + e.max5 = row[48] ? static_cast(atoi(row[48])) : 0; + e.max6 = row[49] ? static_cast(atoi(row[49])) : 0; + e.max7 = row[50] ? static_cast(atoi(row[50])) : 0; + e.max8 = row[51] ? static_cast(atoi(row[51])) : 0; + e.max9 = row[52] ? static_cast(atoi(row[52])) : 0; + e.max10 = row[53] ? static_cast(atoi(row[53])) : 0; + e.max11 = row[54] ? static_cast(atoi(row[54])) : 0; + e.max12 = row[55] ? static_cast(atoi(row[55])) : 0; + e.icon = row[56] ? static_cast(atoi(row[56])) : 0; + e.memicon = row[57] ? static_cast(atoi(row[57])) : 0; + e.components1 = row[58] ? static_cast(atoi(row[58])) : -1; + e.components2 = row[59] ? static_cast(atoi(row[59])) : -1; + e.components3 = row[60] ? static_cast(atoi(row[60])) : -1; + e.components4 = row[61] ? static_cast(atoi(row[61])) : -1; + e.component_counts1 = row[62] ? static_cast(atoi(row[62])) : 1; + e.component_counts2 = row[63] ? static_cast(atoi(row[63])) : 1; + e.component_counts3 = row[64] ? static_cast(atoi(row[64])) : 1; + e.component_counts4 = row[65] ? static_cast(atoi(row[65])) : 1; + e.NoexpendReagent1 = row[66] ? static_cast(atoi(row[66])) : -1; + e.NoexpendReagent2 = row[67] ? static_cast(atoi(row[67])) : -1; + e.NoexpendReagent3 = row[68] ? static_cast(atoi(row[68])) : -1; + e.NoexpendReagent4 = row[69] ? static_cast(atoi(row[69])) : -1; + e.formula1 = row[70] ? static_cast(atoi(row[70])) : 100; + e.formula2 = row[71] ? static_cast(atoi(row[71])) : 100; + e.formula3 = row[72] ? static_cast(atoi(row[72])) : 100; + e.formula4 = row[73] ? static_cast(atoi(row[73])) : 100; + e.formula5 = row[74] ? static_cast(atoi(row[74])) : 100; + e.formula6 = row[75] ? static_cast(atoi(row[75])) : 100; + e.formula7 = row[76] ? static_cast(atoi(row[76])) : 100; + e.formula8 = row[77] ? static_cast(atoi(row[77])) : 100; + e.formula9 = row[78] ? static_cast(atoi(row[78])) : 100; + e.formula10 = row[79] ? static_cast(atoi(row[79])) : 100; + e.formula11 = row[80] ? static_cast(atoi(row[80])) : 100; + e.formula12 = row[81] ? static_cast(atoi(row[81])) : 100; + e.LightType = row[82] ? static_cast(atoi(row[82])) : 0; + e.goodEffect = row[83] ? static_cast(atoi(row[83])) : 0; + e.Activated = row[84] ? static_cast(atoi(row[84])) : 0; + e.resisttype = row[85] ? static_cast(atoi(row[85])) : 0; + e.effectid1 = row[86] ? static_cast(atoi(row[86])) : 254; + e.effectid2 = row[87] ? static_cast(atoi(row[87])) : 254; + e.effectid3 = row[88] ? static_cast(atoi(row[88])) : 254; + e.effectid4 = row[89] ? static_cast(atoi(row[89])) : 254; + e.effectid5 = row[90] ? static_cast(atoi(row[90])) : 254; + e.effectid6 = row[91] ? static_cast(atoi(row[91])) : 254; + e.effectid7 = row[92] ? static_cast(atoi(row[92])) : 254; + e.effectid8 = row[93] ? static_cast(atoi(row[93])) : 254; + e.effectid9 = row[94] ? static_cast(atoi(row[94])) : 254; + e.effectid10 = row[95] ? static_cast(atoi(row[95])) : 254; + e.effectid11 = row[96] ? static_cast(atoi(row[96])) : 254; + e.effectid12 = row[97] ? static_cast(atoi(row[97])) : 254; + e.targettype = row[98] ? static_cast(atoi(row[98])) : 2; + e.basediff = row[99] ? static_cast(atoi(row[99])) : 0; + e.skill = row[100] ? static_cast(atoi(row[100])) : 98; + e.zonetype = row[101] ? static_cast(atoi(row[101])) : -1; + e.EnvironmentType = row[102] ? static_cast(atoi(row[102])) : 0; + e.TimeOfDay = row[103] ? static_cast(atoi(row[103])) : 0; + e.classes1 = row[104] ? static_cast(atoi(row[104])) : 255; + e.classes2 = row[105] ? static_cast(atoi(row[105])) : 255; + e.classes3 = row[106] ? static_cast(atoi(row[106])) : 255; + e.classes4 = row[107] ? static_cast(atoi(row[107])) : 255; + e.classes5 = row[108] ? static_cast(atoi(row[108])) : 255; + e.classes6 = row[109] ? static_cast(atoi(row[109])) : 255; + e.classes7 = row[110] ? static_cast(atoi(row[110])) : 255; + e.classes8 = row[111] ? static_cast(atoi(row[111])) : 255; + e.classes9 = row[112] ? static_cast(atoi(row[112])) : 255; + e.classes10 = row[113] ? static_cast(atoi(row[113])) : 255; + e.classes11 = row[114] ? static_cast(atoi(row[114])) : 255; + e.classes12 = row[115] ? static_cast(atoi(row[115])) : 255; + e.classes13 = row[116] ? static_cast(atoi(row[116])) : 255; + e.classes14 = row[117] ? static_cast(atoi(row[117])) : 255; + e.classes15 = row[118] ? static_cast(atoi(row[118])) : 255; + e.classes16 = row[119] ? static_cast(atoi(row[119])) : 255; + e.CastingAnim = row[120] ? static_cast(atoi(row[120])) : 44; + e.TargetAnim = row[121] ? static_cast(atoi(row[121])) : 13; + e.TravelType = row[122] ? static_cast(atoi(row[122])) : 0; + e.SpellAffectIndex = row[123] ? static_cast(atoi(row[123])) : -1; + e.disallow_sit = row[124] ? static_cast(atoi(row[124])) : 0; + e.deities0 = row[125] ? static_cast(atoi(row[125])) : 0; + e.deities1 = row[126] ? static_cast(atoi(row[126])) : 0; + e.deities2 = row[127] ? static_cast(atoi(row[127])) : 0; + e.deities3 = row[128] ? static_cast(atoi(row[128])) : 0; + e.deities4 = row[129] ? static_cast(atoi(row[129])) : 0; + e.deities5 = row[130] ? static_cast(atoi(row[130])) : 0; + e.deities6 = row[131] ? static_cast(atoi(row[131])) : 0; + e.deities7 = row[132] ? static_cast(atoi(row[132])) : 0; + e.deities8 = row[133] ? static_cast(atoi(row[133])) : 0; + e.deities9 = row[134] ? static_cast(atoi(row[134])) : 0; + e.deities10 = row[135] ? static_cast(atoi(row[135])) : 0; + e.deities11 = row[136] ? static_cast(atoi(row[136])) : 0; + e.deities12 = row[137] ? static_cast(atoi(row[137])) : 0; + e.deities13 = row[138] ? static_cast(atoi(row[138])) : 0; + e.deities14 = row[139] ? static_cast(atoi(row[139])) : 0; + e.deities15 = row[140] ? static_cast(atoi(row[140])) : 0; + e.deities16 = row[141] ? static_cast(atoi(row[141])) : 0; + e.field142 = row[142] ? static_cast(atoi(row[142])) : 100; + e.field143 = row[143] ? static_cast(atoi(row[143])) : 0; + e.new_icon = row[144] ? static_cast(atoi(row[144])) : 161; + e.spellanim = row[145] ? static_cast(atoi(row[145])) : 0; + e.uninterruptable = row[146] ? static_cast(atoi(row[146])) : 0; + e.ResistDiff = row[147] ? static_cast(atoi(row[147])) : -150; + e.dot_stacking_exempt = row[148] ? static_cast(atoi(row[148])) : 0; + e.deleteable = row[149] ? static_cast(atoi(row[149])) : 0; + e.RecourseLink = row[150] ? static_cast(atoi(row[150])) : 0; + e.no_partial_resist = row[151] ? static_cast(atoi(row[151])) : 0; + e.field152 = row[152] ? static_cast(atoi(row[152])) : 0; + e.field153 = row[153] ? static_cast(atoi(row[153])) : 0; + e.short_buff_box = row[154] ? static_cast(atoi(row[154])) : -1; + e.descnum = row[155] ? static_cast(atoi(row[155])) : 0; + e.typedescnum = row[156] ? static_cast(atoi(row[156])) : 0; + e.effectdescnum = row[157] ? static_cast(atoi(row[157])) : 0; + e.effectdescnum2 = row[158] ? static_cast(atoi(row[158])) : 0; + e.npc_no_los = row[159] ? static_cast(atoi(row[159])) : 0; + e.feedbackable = row[160] ? static_cast(atoi(row[160])) : 0; + e.reflectable = row[161] ? static_cast(atoi(row[161])) : 0; + e.bonushate = row[162] ? static_cast(atoi(row[162])) : 0; + e.field163 = row[163] ? static_cast(atoi(row[163])) : 100; + e.field164 = row[164] ? static_cast(atoi(row[164])) : -150; + e.ldon_trap = row[165] ? static_cast(atoi(row[165])) : 0; + e.EndurCost = row[166] ? static_cast(atoi(row[166])) : 0; + e.EndurTimerIndex = row[167] ? static_cast(atoi(row[167])) : 0; + e.IsDiscipline = row[168] ? static_cast(atoi(row[168])) : 0; + e.field169 = row[169] ? static_cast(atoi(row[169])) : 0; + e.field170 = row[170] ? static_cast(atoi(row[170])) : 0; + e.field171 = row[171] ? static_cast(atoi(row[171])) : 0; + e.field172 = row[172] ? static_cast(atoi(row[172])) : 0; + e.HateAdded = row[173] ? static_cast(atoi(row[173])) : 0; + e.EndurUpkeep = row[174] ? static_cast(atoi(row[174])) : 0; + e.numhitstype = row[175] ? static_cast(atoi(row[175])) : 0; + e.numhits = row[176] ? static_cast(atoi(row[176])) : 0; + e.pvpresistbase = row[177] ? static_cast(atoi(row[177])) : -150; + e.pvpresistcalc = row[178] ? static_cast(atoi(row[178])) : 100; + e.pvpresistcap = row[179] ? static_cast(atoi(row[179])) : -150; + e.spell_category = row[180] ? static_cast(atoi(row[180])) : -99; + e.pvp_duration = row[181] ? static_cast(atoi(row[181])) : 0; + e.pvp_duration_cap = row[182] ? static_cast(atoi(row[182])) : 0; + e.pcnpc_only_flag = row[183] ? static_cast(atoi(row[183])) : 0; + e.cast_not_standing = row[184] ? static_cast(atoi(row[184])) : 0; + e.can_mgb = row[185] ? static_cast(atoi(row[185])) : 0; + e.nodispell = row[186] ? static_cast(atoi(row[186])) : -1; + e.npc_category = row[187] ? static_cast(atoi(row[187])) : 0; + e.npc_usefulness = row[188] ? static_cast(atoi(row[188])) : 0; + e.MinResist = row[189] ? static_cast(atoi(row[189])) : 0; + e.MaxResist = row[190] ? static_cast(atoi(row[190])) : 0; + e.viral_targets = row[191] ? static_cast(atoi(row[191])) : 0; + e.viral_timer = row[192] ? static_cast(atoi(row[192])) : 0; + e.nimbuseffect = row[193] ? static_cast(atoi(row[193])) : 0; + e.ConeStartAngle = row[194] ? static_cast(atoi(row[194])) : 0; + e.ConeStopAngle = row[195] ? static_cast(atoi(row[195])) : 0; + e.sneaking = row[196] ? static_cast(atoi(row[196])) : 0; + e.not_extendable = row[197] ? static_cast(atoi(row[197])) : 0; + e.no_detrimental_spell_aggro = row[198] ? static_cast(atoi(row[198])) : 0; + e.field199 = row[199] ? static_cast(atoi(row[199])) : 1; + e.suspendable = row[200] ? static_cast(atoi(row[200])) : 0; + e.viral_range = row[201] ? static_cast(atoi(row[201])) : 0; + e.songcap = row[202] ? static_cast(atoi(row[202])) : 0; + e.field203 = row[203] ? static_cast(atoi(row[203])) : 0; + e.field204 = row[204] ? static_cast(atoi(row[204])) : 0; + e.no_block = row[205] ? static_cast(atoi(row[205])) : 0; + e.field206 = row[206] ? static_cast(atoi(row[206])) : -1; + e.spellgroup = row[207] ? static_cast(atoi(row[207])) : 0; + e.rank_ = row[208] ? static_cast(atoi(row[208])) : 0; + e.no_resist = row[209] ? static_cast(atoi(row[209])) : 0; + e.field210 = row[210] ? static_cast(atoi(row[210])) : 1; + e.CastRestriction = row[211] ? static_cast(atoi(row[211])) : 0; + e.allowrest = row[212] ? static_cast(atoi(row[212])) : 0; + e.InCombat = row[213] ? static_cast(atoi(row[213])) : 0; + e.OutofCombat = row[214] ? static_cast(atoi(row[214])) : 0; + e.field215 = row[215] ? static_cast(atoi(row[215])) : 0; + e.field216 = row[216] ? static_cast(atoi(row[216])) : 0; + e.override_crit_chance = row[217] ? static_cast(atoi(row[217])) : 0; + e.aemaxtargets = row[218] ? static_cast(atoi(row[218])) : 0; + e.maxtargets = row[219] ? static_cast(atoi(row[219])) : 0; + e.no_heal_damage_item_mod = row[220] ? static_cast(atoi(row[220])) : 0; + e.caster_requirement_id = row[221] ? static_cast(atoi(row[221])) : 0; + e.spell_class = row[222] ? static_cast(atoi(row[222])) : 0; + e.spell_subclass = row[223] ? static_cast(atoi(row[223])) : 0; + e.persistdeath = row[224] ? static_cast(atoi(row[224])) : 0; + e.field225 = row[225] ? static_cast(atoi(row[225])) : 0; + e.field226 = row[226] ? static_cast(atoi(row[226])) : 0; + e.min_dist = row[227] ? strtof(row[227], nullptr) : 0; + e.min_dist_mod = row[228] ? strtof(row[228], nullptr) : 0; + e.max_dist = row[229] ? strtof(row[229], nullptr) : 0; + e.max_dist_mod = row[230] ? strtof(row[230], nullptr) : 0; + e.min_range = row[231] ? static_cast(atoi(row[231])) : 0; + e.no_remove = row[232] ? static_cast(atoi(row[232])) : 0; + e.field233 = row[233] ? static_cast(atoi(row[233])) : 0; + e.field234 = row[234] ? static_cast(atoi(row[234])) : 0; + e.field235 = row[235] ? static_cast(atoi(row[235])) : 0; + e.field236 = row[236] ? static_cast(atoi(row[236])) : 0; all_entries.push_back(e); } @@ -2855,7 +2855,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.effectdescnum)); v.push_back(std::to_string(e.effectdescnum2)); v.push_back(std::to_string(e.npc_no_los)); - v.push_back(std::to_string(e.field160)); + v.push_back(std::to_string(e.feedbackable)); v.push_back(std::to_string(e.reflectable)); v.push_back(std::to_string(e.bonushate)); v.push_back(std::to_string(e.field163)); @@ -2893,7 +2893,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.ConeStopAngle)); v.push_back(std::to_string(e.sneaking)); v.push_back(std::to_string(e.not_extendable)); - v.push_back(std::to_string(e.field198)); + v.push_back(std::to_string(e.no_detrimental_spell_aggro)); v.push_back(std::to_string(e.field199)); v.push_back(std::to_string(e.suspendable)); v.push_back(std::to_string(e.viral_range)); @@ -2904,7 +2904,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.field206)); v.push_back(std::to_string(e.spellgroup)); v.push_back(std::to_string(e.rank_)); - v.push_back(std::to_string(e.field209)); + v.push_back(std::to_string(e.no_resist)); v.push_back(std::to_string(e.field210)); v.push_back(std::to_string(e.CastRestriction)); v.push_back(std::to_string(e.allowrest)); @@ -2912,13 +2912,13 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.OutofCombat)); v.push_back(std::to_string(e.field215)); v.push_back(std::to_string(e.field216)); - v.push_back(std::to_string(e.field217)); + v.push_back(std::to_string(e.override_crit_chance)); v.push_back(std::to_string(e.aemaxtargets)); v.push_back(std::to_string(e.maxtargets)); - v.push_back(std::to_string(e.field220)); - v.push_back(std::to_string(e.field221)); - v.push_back(std::to_string(e.field222)); - v.push_back(std::to_string(e.field223)); + v.push_back(std::to_string(e.no_heal_damage_item_mod)); + v.push_back(std::to_string(e.caster_requirement_id)); + v.push_back(std::to_string(e.spell_class)); + v.push_back(std::to_string(e.spell_subclass)); v.push_back(std::to_string(e.persistdeath)); v.push_back(std::to_string(e.field225)); v.push_back(std::to_string(e.field226)); @@ -2927,7 +2927,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.max_dist)); v.push_back(std::to_string(e.max_dist_mod)); v.push_back(std::to_string(e.min_range)); - v.push_back(std::to_string(e.field232)); + v.push_back(std::to_string(e.no_remove)); v.push_back(std::to_string(e.field233)); v.push_back(std::to_string(e.field234)); v.push_back(std::to_string(e.field235)); @@ -3114,7 +3114,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.effectdescnum)); v.push_back(std::to_string(e.effectdescnum2)); v.push_back(std::to_string(e.npc_no_los)); - v.push_back(std::to_string(e.field160)); + v.push_back(std::to_string(e.feedbackable)); v.push_back(std::to_string(e.reflectable)); v.push_back(std::to_string(e.bonushate)); v.push_back(std::to_string(e.field163)); @@ -3152,7 +3152,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.ConeStopAngle)); v.push_back(std::to_string(e.sneaking)); v.push_back(std::to_string(e.not_extendable)); - v.push_back(std::to_string(e.field198)); + v.push_back(std::to_string(e.no_detrimental_spell_aggro)); v.push_back(std::to_string(e.field199)); v.push_back(std::to_string(e.suspendable)); v.push_back(std::to_string(e.viral_range)); @@ -3163,7 +3163,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.field206)); v.push_back(std::to_string(e.spellgroup)); v.push_back(std::to_string(e.rank_)); - v.push_back(std::to_string(e.field209)); + v.push_back(std::to_string(e.no_resist)); v.push_back(std::to_string(e.field210)); v.push_back(std::to_string(e.CastRestriction)); v.push_back(std::to_string(e.allowrest)); @@ -3171,13 +3171,13 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.OutofCombat)); v.push_back(std::to_string(e.field215)); v.push_back(std::to_string(e.field216)); - v.push_back(std::to_string(e.field217)); + v.push_back(std::to_string(e.override_crit_chance)); v.push_back(std::to_string(e.aemaxtargets)); v.push_back(std::to_string(e.maxtargets)); - v.push_back(std::to_string(e.field220)); - v.push_back(std::to_string(e.field221)); - v.push_back(std::to_string(e.field222)); - v.push_back(std::to_string(e.field223)); + v.push_back(std::to_string(e.no_heal_damage_item_mod)); + v.push_back(std::to_string(e.caster_requirement_id)); + v.push_back(std::to_string(e.spell_class)); + v.push_back(std::to_string(e.spell_subclass)); v.push_back(std::to_string(e.persistdeath)); v.push_back(std::to_string(e.field225)); v.push_back(std::to_string(e.field226)); @@ -3186,7 +3186,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.max_dist)); v.push_back(std::to_string(e.max_dist_mod)); v.push_back(std::to_string(e.min_range)); - v.push_back(std::to_string(e.field232)); + v.push_back(std::to_string(e.no_remove)); v.push_back(std::to_string(e.field233)); v.push_back(std::to_string(e.field234)); v.push_back(std::to_string(e.field235)); diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 09a1909024..4e6f289041 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -52,6 +52,7 @@ #include "repositories/books_repository.h" #include "repositories/sharedbank_repository.h" #include "repositories/character_inspect_messages_repository.h" +#include "repositories/spells_new_repository.h" namespace ItemField { @@ -1694,16 +1695,9 @@ const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) { return nullptr; // nothing here for now... database and/or sharemem pulls later } -int SharedDatabase::GetMaxSpellID() { - const std::string query = "SELECT MAX(id) FROM spells_new"; - auto results = QueryDatabase(query); - if (!results.Success()) { - return -1; - } - - auto& row = results.begin(); - - return Strings::ToInt(row[0]); +int SharedDatabase::GetMaxSpellID() +{ + return SpellsNewRepository::GetMaxId(*this); } bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp) { @@ -1735,173 +1729,247 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { *static_cast(data) = max_spells; SPDat_Spell_Struct *sp = reinterpret_cast(static_cast(data) + sizeof(uint32)); - const std::string query = "SELECT * FROM spells_new ORDER BY id ASC"; - auto results = QueryDatabase(query); - if (!results.Success()) { - return; - } + const auto& l = SpellsNewRepository::All(*this); - if(results.ColumnCount() <= SPELL_LOAD_FIELD_COUNT) { - LogSpells("Fatal error loading spells: Spell field count < SPELL_LOAD_FIELD_COUNT([{}])", SPELL_LOAD_FIELD_COUNT); + if (l.empty()) { return; - } - - int counter = 0; + } - for (auto& row = results.begin(); row != results.end(); ++row) { - const int tempid = Strings::ToInt(row[0]); - if(tempid >= max_spells) { + for (const auto& e : l) { + if (e.id >= max_spells) { LogSpells("Non fatal error: spell.id >= max_spells, ignoring"); continue; } - ++counter; - sp[tempid].id = tempid; - strn0cpy(sp[tempid].name, row[1], sizeof(sp[tempid].name)); - strn0cpy(sp[tempid].player_1, row[2], sizeof(sp[tempid].player_1)); - strn0cpy(sp[tempid].teleport_zone, row[3], sizeof(sp[tempid].teleport_zone)); - strn0cpy(sp[tempid].you_cast, row[4], sizeof(sp[tempid].you_cast)); - strn0cpy(sp[tempid].other_casts, row[5], sizeof(sp[tempid].other_casts)); - strn0cpy(sp[tempid].cast_on_you, row[6], sizeof(sp[tempid].cast_on_you)); - strn0cpy(sp[tempid].cast_on_other, row[7], sizeof(sp[tempid].cast_on_other)); - strn0cpy(sp[tempid].spell_fades, row[8], sizeof(sp[tempid].spell_fades)); - - sp[tempid].range = Strings::ToFloat(row[9]); - sp[tempid].aoe_range = Strings::ToFloat(row[10]); - sp[tempid].push_back = Strings::ToFloat(row[11]); - sp[tempid].push_up = Strings::ToFloat(row[12]); - sp[tempid].cast_time=Strings::ToUnsignedInt(row[13]); - sp[tempid].recovery_time=Strings::ToUnsignedInt(row[14]); - sp[tempid].recast_time=Strings::ToUnsignedInt(row[15]); - sp[tempid].buff_duration_formula=Strings::ToUnsignedInt(row[16]); - sp[tempid].buff_duration=Strings::ToUnsignedInt(row[17]); - sp[tempid].aoe_duration=Strings::ToUnsignedInt(row[18]); - sp[tempid].mana=Strings::ToInt(row[19]); - - int y=0; - for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].base_value[y]=Strings::ToInt(row[20+y]); // effect_base_value - - for(y=0; y < EFFECT_COUNT; y++) - sp[tempid].limit_value[y]=Strings::ToInt(row[32+y]); // effect_limit_value - - for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].max_value[y]=Strings::ToInt(row[44+y]); - - for(y=0; y< 4;y++) - sp[tempid].component[y]=Strings::ToInt(row[58+y]); - - for(y=0; y< 4;y++) - sp[tempid].component_count[y]=Strings::ToInt(row[62+y]); - - for(y=0; y< 4;y++) - sp[tempid].no_expend_reagent[y]=Strings::ToInt(row[66+y]); - - for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].formula[y]=Strings::ToUnsignedInt(row[70+y]); - - sp[tempid].good_effect=Strings::ToInt(row[83]); - sp[tempid].activated=Strings::ToInt(row[84]); - sp[tempid].resist_type=Strings::ToInt(row[85]); - - for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].effect_id[y]=Strings::ToInt(row[86+y]); - - sp[tempid].target_type = static_cast(Strings::ToInt(row[98])); - sp[tempid].base_difficulty=Strings::ToInt(row[99]); - - int tmp_skill = Strings::ToInt(row[100]); - - if (tmp_skill < 0 || tmp_skill > EQ::skills::HIGHEST_SKILL) - sp[tempid].skill = EQ::skills::SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated - else - sp[tempid].skill = static_cast(tmp_skill); - - sp[tempid].zone_type=Strings::ToInt(row[101]); - sp[tempid].environment_type=Strings::ToInt(row[102]); - sp[tempid].time_of_day=Strings::ToInt(row[103]); - - for(y=0; y < Class::PLAYER_CLASS_COUNT;y++) - sp[tempid].classes[y]=Strings::ToInt(row[104+y]); - - sp[tempid].casting_animation=Strings::ToInt(row[120]); - sp[tempid].spell_affect_index=Strings::ToInt(row[123]); - sp[tempid].disallow_sit=Strings::ToInt(row[124]); - sp[tempid].deity_agnostic=Strings::ToInt(row[125]); - - for (y = 0; y < 16; y++) - sp[tempid].deities[y]=Strings::ToInt(row[126+y]); - - sp[tempid].new_icon=Strings::ToInt(row[144]); - sp[tempid].uninterruptable=Strings::ToBool(row[146]); - sp[tempid].resist_difficulty=Strings::ToInt(row[147]); - sp[tempid].unstackable_dot = Strings::ToBool(row[148]); - sp[tempid].recourse_link = Strings::ToUnsignedInt(row[150]); - sp[tempid].no_partial_resist = Strings::ToBool(row[151]); - - sp[tempid].short_buff_box = Strings::ToInt(row[154]); - sp[tempid].description_id = Strings::ToInt(row[155]); - sp[tempid].type_description_id = Strings::ToInt(row[156]); - sp[tempid].effect_description_id = Strings::ToInt(row[157]); - - sp[tempid].npc_no_los = Strings::ToBool(row[159]); - sp[tempid].feedbackable = Strings::ToBool(row[160]); - sp[tempid].reflectable = Strings::ToBool(row[161]); - sp[tempid].bonus_hate=Strings::ToInt(row[162]); - - sp[tempid].ldon_trap = Strings::ToBool(row[165]); - sp[tempid].endurance_cost= Strings::ToInt(row[166]); - sp[tempid].timer_id= Strings::ToInt(row[167]); - sp[tempid].is_discipline = Strings::ToBool(row[168]); - sp[tempid].hate_added= Strings::ToInt(row[173]); - sp[tempid].endurance_upkeep=Strings::ToInt(row[174]); - sp[tempid].hit_number_type = Strings::ToInt(row[175]); - sp[tempid].hit_number = Strings::ToInt(row[176]); - sp[tempid].pvp_resist_base= Strings::ToInt(row[177]); - sp[tempid].pvp_resist_per_level= Strings::ToInt(row[178]); - sp[tempid].pvp_resist_cap= Strings::ToInt(row[179]); - sp[tempid].spell_category= Strings::ToInt(row[180]); - sp[tempid].pvp_duration = Strings::ToInt(row[181]); - sp[tempid].pvp_duration_cap = Strings::ToInt(row[182]); - sp[tempid].pcnpc_only_flag= Strings::ToInt(row[183]); - sp[tempid].cast_not_standing = Strings::ToInt(row[184]) != 0; - sp[tempid].can_mgb= Strings::ToBool(row[185]); - sp[tempid].dispel_flag = Strings::ToInt(row[186]); - sp[tempid].min_resist = Strings::ToInt(row[189]); - sp[tempid].max_resist = Strings::ToInt(row[190]); - sp[tempid].viral_targets = Strings::ToInt(row[191]); - sp[tempid].viral_timer = Strings::ToInt(row[192]); - sp[tempid].nimbus_effect = Strings::ToInt(row[193]); - sp[tempid].directional_start = Strings::ToFloat(row[194]); - sp[tempid].directional_end = Strings::ToFloat(row[195]); - sp[tempid].sneak = Strings::ToBool(row[196]); - sp[tempid].not_focusable = Strings::ToBool(row[197]); - sp[tempid].no_detrimental_spell_aggro = Strings::ToBool(row[198]); - sp[tempid].suspendable = Strings::ToBool(row[200]); - sp[tempid].viral_range = Strings::ToInt(row[201]); - sp[tempid].song_cap = Strings::ToInt(row[202]); - sp[tempid].no_block = Strings::ToInt(row[205]); - sp[tempid].spell_group=Strings::ToInt(row[207]); - sp[tempid].rank = Strings::ToInt(row[208]); - sp[tempid].no_resist=Strings::ToInt(row[209]); - sp[tempid].cast_restriction = Strings::ToInt(row[211]); - sp[tempid].allow_rest = Strings::ToBool(row[212]); - sp[tempid].can_cast_in_combat = Strings::ToBool(row[213]); - sp[tempid].can_cast_out_of_combat = Strings::ToBool(row[214]); - sp[tempid].override_crit_chance = Strings::ToInt(row[217]); - sp[tempid].aoe_max_targets = Strings::ToInt(row[218]); - sp[tempid].no_heal_damage_item_mod = Strings::ToInt(row[219]); - sp[tempid].caster_requirement_id = Strings::ToInt(row[220]); - sp[tempid].spell_class = Strings::ToInt(row[221]); - sp[tempid].spell_subclass = Strings::ToInt(row[222]); - sp[tempid].persist_death = Strings::ToBool(row[224]); - sp[tempid].min_distance = Strings::ToFloat(row[227]); - sp[tempid].min_distance_mod = Strings::ToFloat(row[228]); - sp[tempid].max_distance = Strings::ToFloat(row[229]); - sp[tempid].max_distance_mod = Strings::ToFloat(row[230]); - sp[tempid].min_range = Strings::ToFloat(row[231]); - sp[tempid].no_remove = Strings::ToBool(row[232]); - sp[tempid].damage_shield_type = 0; + sp[e.id].id = e.id; + + strn0cpy(sp[e.id].name, e.name.c_str(), sizeof(sp[e.id].name)); + strn0cpy(sp[e.id].player_1, e.player_1.c_str(), sizeof(sp[e.id].player_1)); + strn0cpy(sp[e.id].teleport_zone, e.teleport_zone.c_str(), sizeof(sp[e.id].teleport_zone)); + strn0cpy(sp[e.id].you_cast, e.you_cast.c_str(), sizeof(sp[e.id].you_cast)); + strn0cpy(sp[e.id].other_casts, e.other_casts.c_str(), sizeof(sp[e.id].other_casts)); + strn0cpy(sp[e.id].cast_on_you, e.cast_on_you.c_str(), sizeof(sp[e.id].cast_on_you)); + strn0cpy(sp[e.id].cast_on_other, e.cast_on_other.c_str(), sizeof(sp[e.id].cast_on_other)); + strn0cpy(sp[e.id].spell_fades, e.spell_fades.c_str(), sizeof(sp[e.id].spell_fades)); + + sp[e.id].range = e.range_; + sp[e.id].aoe_range = e.aoerange; + sp[e.id].push_back = e.pushback; + sp[e.id].push_up = e.pushup; + sp[e.id].cast_time = e.cast_time; + sp[e.id].recovery_time = e.recovery_time; + sp[e.id].recast_time = e.recast_time; + sp[e.id].buff_duration_formula = e.buffdurationformula; + sp[e.id].buff_duration = e.buffduration; + sp[e.id].aoe_duration = e.AEDuration; + sp[e.id].mana = e.mana; + + sp[e.id].base_value[0] = e.effect_base_value1; + sp[e.id].base_value[1] = e.effect_base_value2; + sp[e.id].base_value[2] = e.effect_base_value3; + sp[e.id].base_value[3] = e.effect_base_value4; + sp[e.id].base_value[4] = e.effect_base_value5; + sp[e.id].base_value[5] = e.effect_base_value6; + sp[e.id].base_value[6] = e.effect_base_value7; + sp[e.id].base_value[7] = e.effect_base_value8; + sp[e.id].base_value[8] = e.effect_base_value9; + sp[e.id].base_value[9] = e.effect_base_value10; + sp[e.id].base_value[10] = e.effect_base_value11; + sp[e.id].base_value[11] = e.effect_base_value12; + + sp[e.id].limit_value[0] = e.effect_limit_value1; + sp[e.id].limit_value[1] = e.effect_limit_value2; + sp[e.id].limit_value[2] = e.effect_limit_value3; + sp[e.id].limit_value[3] = e.effect_limit_value4; + sp[e.id].limit_value[4] = e.effect_limit_value5; + sp[e.id].limit_value[5] = e.effect_limit_value6; + sp[e.id].limit_value[6] = e.effect_limit_value7; + sp[e.id].limit_value[7] = e.effect_limit_value8; + sp[e.id].limit_value[8] = e.effect_limit_value9; + sp[e.id].limit_value[9] = e.effect_limit_value10; + sp[e.id].limit_value[10] = e.effect_limit_value11; + sp[e.id].limit_value[11] = e.effect_limit_value12; + + sp[e.id].max_value[0] = e.max1; + sp[e.id].max_value[1] = e.max2; + sp[e.id].max_value[2] = e.max3; + sp[e.id].max_value[3] = e.max4; + sp[e.id].max_value[4] = e.max5; + sp[e.id].max_value[5] = e.max6; + sp[e.id].max_value[6] = e.max7; + sp[e.id].max_value[7] = e.max8; + sp[e.id].max_value[8] = e.max9; + sp[e.id].max_value[9] = e.max10; + sp[e.id].max_value[10] = e.max11; + sp[e.id].max_value[11] = e.max12; + + sp[e.id].component[0] = e.components1; + sp[e.id].component[1] = e.components2; + sp[e.id].component[2] = e.components3; + sp[e.id].component[3] = e.components4; + + sp[e.id].component_count[0] = e.component_counts1; + sp[e.id].component_count[1] = e.component_counts2; + sp[e.id].component_count[2] = e.component_counts3; + sp[e.id].component_count[3] = e.component_counts4; + + sp[e.id].no_expend_reagent[0] = e.NoexpendReagent1; + sp[e.id].no_expend_reagent[1] = e.NoexpendReagent2; + sp[e.id].no_expend_reagent[2] = e.NoexpendReagent3; + sp[e.id].no_expend_reagent[3] = e.NoexpendReagent4; + + sp[e.id].formula[0] = e.formula1; + sp[e.id].formula[1] = e.formula2; + sp[e.id].formula[2] = e.formula3; + sp[e.id].formula[3] = e.formula4; + sp[e.id].formula[4] = e.formula5; + sp[e.id].formula[5] = e.formula6; + sp[e.id].formula[6] = e.formula7; + sp[e.id].formula[7] = e.formula8; + sp[e.id].formula[8] = e.formula9; + sp[e.id].formula[9] = e.formula10; + sp[e.id].formula[10] = e.formula11; + sp[e.id].formula[11] = e.formula12; + + sp[e.id].good_effect = e.goodEffect; + sp[e.id].activated = e.Activated; + sp[e.id].resist_type = e.resisttype; + + sp[e.id].effect_id[0] = e.effectid1; + sp[e.id].effect_id[1] = e.effectid2; + sp[e.id].effect_id[2] = e.effectid3; + sp[e.id].effect_id[3] = e.effectid4; + sp[e.id].effect_id[4] = e.effectid5; + sp[e.id].effect_id[5] = e.effectid6; + sp[e.id].effect_id[6] = e.effectid7; + sp[e.id].effect_id[7] = e.effectid8; + sp[e.id].effect_id[8] = e.effectid9; + sp[e.id].effect_id[9] = e.effectid10; + sp[e.id].effect_id[10] = e.effectid11; + sp[e.id].effect_id[11] = e.effectid12; + + sp[e.id].target_type = static_cast(e.targettype); + + sp[e.id].base_difficulty = e.basediff; + + sp[e.id].skill = ( + EQ::ValueWithin(e.skill, 0, EQ::skills::HIGHEST_SKILL) ? + static_cast(e.skill) : + EQ::skills::SkillBegging + ); + + sp[e.id].zone_type = e.zonetype; + sp[e.id].environment_type = e.EnvironmentType; + sp[e.id].time_of_day = e.TimeOfDay; + + sp[e.id].classes[0] = e.classes1; + sp[e.id].classes[1] = e.classes2; + sp[e.id].classes[2] = e.classes3; + sp[e.id].classes[3] = e.classes4; + sp[e.id].classes[4] = e.classes5; + sp[e.id].classes[5] = e.classes6; + sp[e.id].classes[6] = e.classes7; + sp[e.id].classes[7] = e.classes8; + sp[e.id].classes[8] = e.classes9; + sp[e.id].classes[9] = e.classes10; + sp[e.id].classes[10] = e.classes11; + sp[e.id].classes[11] = e.classes12; + sp[e.id].classes[12] = e.classes13; + sp[e.id].classes[13] = e.classes14; + sp[e.id].classes[14] = e.classes15; + sp[e.id].classes[15] = e.classes16; + + sp[e.id].casting_animation = e.CastingAnim; + sp[e.id].spell_affect_index = e.SpellAffectIndex; + sp[e.id].disallow_sit = e.disallow_sit; + + sp[e.id].deity_agnostic = e.deities0; // Agnostic + sp[e.id].deities[0] = e.deities1; // Bertoxxulous + sp[e.id].deities[1] = e.deities2; // Brell Serilis + sp[e.id].deities[2] = e.deities3; // Cazic Thule + sp[e.id].deities[3] = e.deities4; // Erollsi Marr + sp[e.id].deities[4] = e.deities5; // Bristlebane + sp[e.id].deities[5] = e.deities6; // Innoruuk + sp[e.id].deities[6] = e.deities7; // Karana + sp[e.id].deities[7] = e.deities8; // Mithaniel Marr + sp[e.id].deities[8] = e.deities9; // Prexius + sp[e.id].deities[9] = e.deities10; // Quellious + sp[e.id].deities[10] = e.deities11; // Rallos Zek + sp[e.id].deities[11] = e.deities12; // Rodcet Nife + sp[e.id].deities[12] = e.deities13; // Solusek Ro + sp[e.id].deities[13] = e.deities14; // The Tribunal + sp[e.id].deities[14] = e.deities15; // Tunare + sp[e.id].deities[15] = e.deities16; // Veeshan + + sp[e.id].new_icon = e.new_icon; + sp[e.id].uninterruptable = e.uninterruptable; + sp[e.id].resist_difficulty = e.ResistDiff; + sp[e.id].unstackable_dot = e.dot_stacking_exempt; + sp[e.id].recourse_link = e.RecourseLink; + sp[e.id].no_partial_resist = e.no_partial_resist; + sp[e.id].short_buff_box = e.short_buff_box; + sp[e.id].description_id = e.descnum; + sp[e.id].type_description_id = e.typedescnum; + sp[e.id].effect_description_id = e.effectdescnum; + sp[e.id].npc_no_los = e.npc_no_los; + sp[e.id].feedbackable = e.feedbackable; + sp[e.id].reflectable = e.reflectable; + sp[e.id].bonus_hate = e.bonushate; + sp[e.id].ldon_trap = e.ldon_trap; + sp[e.id].endurance_cost = e.EndurCost; + sp[e.id].timer_id = e.EndurTimerIndex; + sp[e.id].is_discipline = e.IsDiscipline; + sp[e.id].hate_added = e.HateAdded; + sp[e.id].endurance_upkeep = e.EndurUpkeep; + sp[e.id].hit_number_type = e.numhits; + sp[e.id].hit_number = e.numhitstype; + sp[e.id].pvp_resist_base = e.pvpresistbase; + sp[e.id].pvp_resist_per_level = e.pvpresistcalc; + sp[e.id].pvp_resist_cap = e.pvpresistcap; + sp[e.id].spell_category = e.spell_category; + sp[e.id].pvp_duration = e.pvp_duration; + sp[e.id].pvp_duration_cap = e.pvp_duration_cap; + sp[e.id].pcnpc_only_flag = e.pcnpc_only_flag; + sp[e.id].cast_not_standing = e.cast_not_standing; + sp[e.id].can_mgb = e.can_mgb; + sp[e.id].dispel_flag = e.nodispell; + sp[e.id].min_resist = e.MinResist; + sp[e.id].max_resist = e.MaxResist; + sp[e.id].viral_targets = e.viral_targets; + sp[e.id].viral_timer = e.viral_timer; + sp[e.id].nimbus_effect = e.nimbuseffect; + sp[e.id].directional_start = e.ConeStartAngle; + sp[e.id].directional_end = e.ConeStopAngle; + sp[e.id].sneak = e.sneaking; + sp[e.id].not_focusable = e.not_extendable; + + sp[e.id].no_detrimental_spell_aggro = e.no_detrimental_spell_aggro; + + sp[e.id].suspendable = e.suspendable; + sp[e.id].viral_range = e.viral_range; + sp[e.id].song_cap = e.songcap; + sp[e.id].no_block = e.no_block; + sp[e.id].spell_group = e.spellgroup; + sp[e.id].rank = e.rank_; + sp[e.id].no_resist = e.no_resist; + sp[e.id].cast_restriction = e.CastRestriction; + sp[e.id].allow_rest = e.allowrest; + sp[e.id].can_cast_in_combat = e.InCombat; + sp[e.id].can_cast_out_of_combat = e.OutofCombat; + sp[e.id].override_crit_chance = e.override_crit_chance; + sp[e.id].aoe_max_targets = e.aemaxtargets; + sp[e.id].no_heal_damage_item_mod = e.no_heal_damage_item_mod; + sp[e.id].caster_requirement_id = e.caster_requirement_id; + sp[e.id].spell_class = e.spell_class; + sp[e.id].spell_subclass = e.spell_subclass; + sp[e.id].persist_death = e.persistdeath; + sp[e.id].min_distance = e.min_dist; + sp[e.id].min_distance_mod = e.min_dist_mod; + sp[e.id].max_distance = e.max_dist; + sp[e.id].max_distance_mod = e.max_dist_mod; + sp[e.id].min_range = e.min_range; + sp[e.id].no_remove = e.no_remove; + sp[e.id].damage_shield_type = 0; } LoadDamageShieldTypes(sp, max_spells); @@ -1934,18 +2002,7 @@ void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const Insp uint32 SharedDatabase::GetSpellsCount() { - auto results = QueryDatabase("SELECT count(*) FROM spells_new"); - if (!results.Success() || !results.RowCount()) { - return 0; - } - - auto& row = results.begin(); - - if (row[0]) { - return Strings::ToUnsignedInt(row[0]); - } - - return 0; + return SpellsNewRepository::Count(*this); } uint32 SharedDatabase::GetItemsCount() diff --git a/common/spdat.h b/common/spdat.h index 11130d6a4e..9df894d350 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -1600,7 +1600,6 @@ namespace SpellEffect { // number. note that the id field is counted as 0, this way the numbers // here match the numbers given to sep in the loading function net.cpp // -#define SPELL_LOAD_FIELD_COUNT 236 struct SPDat_Spell_Struct { diff --git a/common/version.h b/common/version.h index bf8c83fbad..af74568c6b 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9327 +#define CURRENT_BINARY_DATABASE_VERSION 9328 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054 #define CUSTOM_BINARY_DATABASE_VERSION 0 From e015d0d67e0db2b6c6af302137773ad32014cbb3 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 30 Aug 2025 16:23:33 -0400 Subject: [PATCH 035/194] [Repositories] Convert Damage Shield Types to Repositories (#4995) * [Repositories] Convert Damage Shield Types to Repositories * Remove max spell ID --- common/shareddb.cpp | 24 +++++++++++------------- common/shareddb.h | 2 +- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 4e6f289041..ecee4ca177 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -53,6 +53,7 @@ #include "repositories/sharedbank_repository.h" #include "repositories/character_inspect_messages_repository.h" #include "repositories/spells_new_repository.h" +#include "repositories/damageshieldtypes_repository.h" namespace ItemField { @@ -1675,20 +1676,17 @@ bool SharedDatabase::GetCommandSubSettings(std::vector 0 " - "AND `spellid` <= %i", iMaxSpellID); - auto results = QueryDatabase(query); - if (!results.Success()) { - return; - } +void SharedDatabase::LoadDamageShieldTypes(SPDat_Spell_Struct* s) +{ + const auto& l = DamageshieldtypesRepository::All(*this); - for(auto& row = results.begin(); row != results.end(); ++row) { - const int spellID = Strings::ToInt(row[0]); - if((spellID > 0) && (spellID <= iMaxSpellID)) - sp[spellID].damage_shield_type = Strings::ToUnsignedInt(row[1]); - } + if (l.empty()) { + return; + } + for (const auto& e : l) { + s[e.spellid].damage_shield_type = e.type; + } } const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) { @@ -1972,7 +1970,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[e.id].damage_shield_type = 0; } - LoadDamageShieldTypes(sp, max_spells); + LoadDamageShieldTypes(sp); } void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* s) diff --git a/common/shareddb.h b/common/shareddb.h index 032865cbd4..8002b62b42 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -173,7 +173,7 @@ class SharedDatabase : public Database { int GetMaxSpellID(); bool LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp); void LoadSpells(void *data, int max_spells); - void LoadDamageShieldTypes(SPDat_Spell_Struct *sp, int32 iMaxSpellID); + void LoadDamageShieldTypes(SPDat_Spell_Struct* s); uint32 GetSharedSpellsCount() { return m_shared_spells_count; } uint32 GetSpellsCount(); From 1eb89edbbd506c7f3ab45fa4dac266ce642f41e3 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 30 Aug 2025 16:39:23 -0400 Subject: [PATCH 036/194] [Repositories] Convert Item Loading to Repositories (#4998) --- common/CMakeLists.txt | 1 - common/item_fieldlist.h | 206 ------------------ common/shareddb.cpp | 466 ++++++++++++++++++---------------------- common/shareddb.h | 2 +- 4 files changed, 213 insertions(+), 462 deletions(-) delete mode 100644 common/item_fieldlist.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 2a3c3ad723..1a9028eb7a 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -603,7 +603,6 @@ SET(common_headers ipc_mutex.h ip_util.h item_data.h - item_fieldlist.h item_instance.h json_config.h light_source.h diff --git a/common/item_fieldlist.h b/common/item_fieldlist.h deleted file mode 100644 index 3c00f1e440..0000000000 --- a/common/item_fieldlist.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - - -These fields must be in the order of how they are serialized! - - - -*/ - -F(itemclass) -F(name) -F(lore) -F(idfile) -F(id) -F(weight) -F(norent) -F(nodrop) -F(size) -F(slots) -F(price) -F(icon) -F(UNK012) -F(UNK013) -F(benefitflag) -F(tradeskills) -F(cr) -F(dr) -F(pr) -F(mr) -F(fr) -F(astr) -F(asta) -F(aagi) -F(adex) -F(acha) -F(aint) -F(awis) -F(hp) -F(mana) -F(ac) -F(deity) -F(skillmodvalue) -F(UNK033) -F(skillmodmax) -F(skillmodtype) -F(banedmgrace) -F(banedmgamt) -F(banedmgbody) -F(magic) -F(casttime_) -F(reqlevel) -F(bardtype) -F(bardvalue) -F(light) -F(delay) -F(reclevel) -F(recskill) -F(elemdmgtype) -F(elemdmgamt) -F(range) -F(damage) -F(color) -F(classes) -F(races) -F(UNK054) -F(maxcharges) -F(itemtype) -F(material) -F(herosforgemodel) -F(sellrate) -F(UNK059) -F(casttime) -F(elitematerial) -F(procrate) -F(combateffects) -F(shielding) -F(stunresist) -F(strikethrough) -F(extradmgskill) -F(extradmgamt) -F(spellshield) -F(avoidance) -F(accuracy) -F(charmfileid) -F(factionmod1) -F(factionmod2) -F(factionmod3) -F(factionmod4) -F(factionamt1) -F(factionamt2) -F(factionamt3) -F(factionamt4) -F(charmfile) -F(augtype) -F(augslot1type) -F(augslot1visible) -F(augslot2type) -F(augslot2visible) -F(augslot3type) -F(augslot3visible) -F(augslot4type) -F(augslot4visible) -F(augslot5type) -F(augslot5visible) -F(augslot6type) -F(augslot6visible) -F(ldontheme) -F(ldonprice) -F(ldonsold) -F(bagtype) -F(bagslots) -F(bagsize) -F(bagwr) -F(book) -F(booktype) -F(filename) -F(banedmgraceamt) -F(augrestrict) -F(loregroup) -F(pendingloreflag) -F(artifactflag) -F(summonedflag) -F(favor) -F(fvnodrop) -F(endur) -F(dotshielding) -F(attack) -F(regen) -F(manaregen) -F(enduranceregen) -F(haste) -F(damageshield) -F(recastdelay) -F(recasttype) -F(guildfavor) -F(augdistiller) -F(UNK123) -F(UNK124) -F(attuneable) -F(nopet) -F(UNK127) -F(pointtype) -F(potionbelt) -F(potionbeltslots) -F(stacksize) -F(notransfer) -F(stackable) -F(UNK134) -F(clickeffect) -F(clicktype) -F(clicklevel) -F(clicklevel2) -F(proceffect) -F(proctype) -F(proclevel) -F(proclevel2) -F(worneffect) -F(worntype) -F(wornlevel) -F(wornlevel2) -F(focuseffect) -F(focustype) -F(focuslevel) -F(focuslevel2) -F(scrolleffect) -F(scrolltype) -F(scrolllevel) -F(scrolllevel2) -F(bardeffect) -F(bardeffecttype) -F(bardlevel2) -F(bardlevel) -F(questitemflag) -F(svcorruption) -F(purity) -F(evoitem) -F(evoid) -F(evolvinglevel) -F(evomax) -F(backstabdmg) -F(dsmitigation) -F(heroic_str) -F(heroic_int) -F(heroic_wis) -F(heroic_agi) -F(heroic_dex) -F(heroic_sta) -F(heroic_cha) -F(heroic_mr) -F(heroic_fr) -F(heroic_cr) -F(heroic_dr) -F(heroic_pr) -F(heroic_svcorrup) -F(healamt) -F(spelldmg) -F(ldonsellbackrate) -F(scriptfileid) -F(expendablearrow) -F(clairvoyance) -F(clickname) -F(procname) -F(wornname) -F(focusname) -F(scrollname) -F(subtype) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index ecee4ca177..89c48daa1d 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -54,19 +54,7 @@ #include "repositories/character_inspect_messages_repository.h" #include "repositories/spells_new_repository.h" #include "repositories/damageshieldtypes_repository.h" - -namespace ItemField -{ - enum { - source = 0, -#define F(x) x, -#include "item_fieldlist.h" -#undef F - updated, - minstatus, - comment, - }; -} +#include "repositories/items_repository.h" SharedDatabase::SharedDatabase() : Database() @@ -947,27 +935,10 @@ void SharedDatabase::ClearOldRecastTimestamps(uint32 char_id) ); } -void SharedDatabase::GetItemsCount(int32 &item_count, uint32 &max_id) +void SharedDatabase::GetItemsCount(int32& item_count, uint32& max_id) { - item_count = -1; - max_id = 0; - - const std::string query = "SELECT MAX(id), count(*) FROM items"; - auto results = QueryDatabase(query); - if (!results.Success()) { - return; - } - - if (results.RowCount() == 0) - return; - - auto& row = results.begin(); - - if (row[0]) - max_id = Strings::ToUnsignedInt(row[0]); - - if (row[1]) - item_count = Strings::ToUnsignedInt(row[1]); + max_id = ItemsRepository::GetMaxId(*this); + item_count = ItemsRepository::Count(*this); } bool SharedDatabase::LoadItems(const std::string &prefix) { @@ -997,14 +968,14 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ std::string variable_buffer; - bool disable_attuneable = RuleB(Items, DisableAttuneable); - bool disable_bard_focus_effects = RuleB(Items, DisableBardFocusEffects); - bool disable_lore = RuleB(Items, DisableLore); - bool disable_no_drop = RuleB(Items, DisableNoDrop); - bool disable_no_pet = RuleB(Items, DisableNoPet); - bool disable_no_rent = RuleB(Items, DisableNoRent); - bool disable_no_transfer = RuleB(Items, DisableNoTransfer); - bool disable_potion_belt = RuleB(Items, DisablePotionBelt); + bool disable_attuneable = RuleB(Items, DisableAttuneable); + bool disable_bard_focus_effects = RuleB(Items, DisableBardFocusEffects); + bool disable_lore = RuleB(Items, DisableLore); + bool disable_no_drop = RuleB(Items, DisableNoDrop); + bool disable_no_pet = RuleB(Items, DisableNoPet); + bool disable_no_rent = RuleB(Items, DisableNoRent); + bool disable_no_transfer = RuleB(Items, DisableNoTransfer); + bool disable_potion_belt = RuleB(Items, DisablePotionBelt); bool disable_spell_focus_effects = RuleB(Items, DisableSpellFocusEffects); // Old Variable Code @@ -1035,206 +1006,204 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ EQ::ItemData item; - const std::string query = "SELECT source," -#define F(x) "`"#x"`," -#include "item_fieldlist.h" -#undef F - "updated, minstatus, comment FROM items ORDER BY id"; - auto results = QueryDatabase(query); - if (!results.Success()) { + const auto& l = ItemsRepository::All(*this); + + if (l.empty()) { return; } - for (auto& row = results.begin(); row != results.end(); ++row) { + for (const auto& e : l) { memset(&item, 0, sizeof(EQ::ItemData)); // Unique Identifier - item.ID = Strings::ToUnsignedInt(row[ItemField::id]); + item.ID = e.id; // Minimum Status - item.MinStatus = static_cast(Strings::ToUnsignedInt(row[ItemField::minstatus])); + item.MinStatus = static_cast(e.minstatus); // Name, Lore, and Comment - strn0cpy(item.Name, row[ItemField::name], sizeof(item.Name)); - strn0cpy(item.Lore, row[ItemField::lore], sizeof(item.Lore)); - strn0cpy(item.Comment, row[ItemField::comment], sizeof(item.Comment)); + strn0cpy(item.Name, e.Name.c_str(), sizeof(item.Name)); + strn0cpy(item.Lore, e.lore.c_str(), sizeof(item.Lore)); + strn0cpy(item.Comment, e.comment.c_str(), sizeof(item.Comment)); // Flags - item.ArtifactFlag = Strings::ToBool(row[ItemField::artifactflag]); - item.Attuneable = !disable_attuneable && Strings::ToBool(row[ItemField::attuneable]); - item.BenefitFlag = Strings::ToBool(row[ItemField::benefitflag]); - item.FVNoDrop = Strings::ToBool(row[ItemField::fvnodrop]); - item.Magic = Strings::ToBool(row[ItemField::magic]); - item.NoDrop = disable_no_drop ? static_cast(255) : static_cast(Strings::ToUnsignedInt(row[ItemField::nodrop])); - item.NoPet = !disable_no_pet && Strings::ToBool(row[ItemField::nopet]); - item.NoRent = disable_no_rent ? static_cast(255) : static_cast(Strings::ToUnsignedInt(row[ItemField::norent])); - item.NoTransfer = !disable_no_transfer && Strings::ToBool(row[ItemField::notransfer]); - item.PendingLoreFlag = Strings::ToBool(row[ItemField::pendingloreflag]); - item.QuestItemFlag = Strings::ToBool(row[ItemField::questitemflag]); - item.Stackable = Strings::ToBool(row[ItemField::stackable]); - item.Tradeskills = Strings::ToBool(row[ItemField::tradeskills]); - item.SummonedFlag = Strings::ToBool(row[ItemField::summonedflag]); + item.ArtifactFlag = e.artifactflag; + item.Attuneable = !disable_attuneable && e.attuneable; + item.BenefitFlag = e.benefitflag; + item.FVNoDrop = e.fvnodrop; + item.Magic = e.magic; + item.NoDrop = disable_no_drop ? std::numeric_limits::max() : e.nodrop; + item.NoPet = !disable_no_pet && e.nopet; + item.NoRent = disable_no_rent ? std::numeric_limits::max() : e.norent; + item.NoTransfer = !disable_no_transfer && e.notransfer; + item.PendingLoreFlag = e.pendingloreflag; + item.QuestItemFlag = e.questitemflag; + item.Stackable = e.stackable; + item.Tradeskills = e.tradeskills; + item.SummonedFlag = e.summonedflag; // Lore - item.LoreGroup = disable_lore ? 0 : Strings::ToInt(row[ItemField::loregroup]); - item.LoreFlag = !disable_lore && item.LoreGroup != 0; + item.LoreGroup = disable_lore ? 0 : e.loregroup; + item.LoreFlag = !disable_lore && item.LoreGroup != 0; // Type - item.AugType = Strings::ToUnsignedInt(row[ItemField::augtype]); - item.ItemType = static_cast(Strings::ToUnsignedInt(row[ItemField::itemtype])); - item.SubType = Strings::ToInt(row[ItemField::subtype]); + item.AugType = e.augtype; + item.ItemType = static_cast(e.itemtype); + item.SubType = e.subtype; // Miscellaneous - item.ExpendableArrow = static_cast(Strings::ToUnsignedInt(row[ItemField::expendablearrow])); - item.Light = static_cast(Strings::ToInt(row[ItemField::light])); - item.MaxCharges = static_cast(Strings::ToInt(row[ItemField::maxcharges])); - item.Size = static_cast(Strings::ToUnsignedInt(row[ItemField::size])); - item.StackSize = static_cast(Strings::ToInt(row[ItemField::stacksize])); - item.Weight = Strings::ToInt(row[ItemField::weight]); + item.ExpendableArrow = e.expendablearrow; + item.Light = EQ::Clamp(e.light, -128, 127); + item.MaxCharges = e.maxcharges; + item.Size = static_cast(e.size); + item.StackSize = e.stacksize; + item.Weight = e.weight; // Potion Belt - item.PotionBelt = !disable_potion_belt && Strings::ToBool(row[ItemField::potionbelt]); - item.PotionBeltSlots = disable_potion_belt ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::potionbeltslots])); + item.PotionBelt = !disable_potion_belt && e.potionbelt; + item.PotionBeltSlots = disable_potion_belt ? 0 : static_cast(e.potionbeltslots); // Merchant - item.Favor = Strings::ToUnsignedInt(row[ItemField::favor]); - item.GuildFavor = Strings::ToUnsignedInt(row[ItemField::guildfavor]); - item.Price = Strings::ToUnsignedInt(row[ItemField::price]); - item.SellRate = Strings::ToFloat(row[ItemField::sellrate]); + item.Favor = e.favor; + item.GuildFavor = e.guildfavor; + item.Price = e.price; + item.SellRate = e.sellrate; // Display - item.Color = Strings::ToUnsignedInt(row[ItemField::color]); - item.EliteMaterial = Strings::ToUnsignedInt(row[ItemField::elitematerial]); - item.HerosForgeModel = Strings::ToUnsignedInt(row[ItemField::herosforgemodel]); - item.Icon = Strings::ToUnsignedInt(row[ItemField::icon]); - strn0cpy(item.IDFile, row[ItemField::idfile], sizeof(item.IDFile)); - item.Material = static_cast(Strings::ToUnsignedInt(row[ItemField::material])); + item.Color = e.color; + item.EliteMaterial = e.elitematerial; + item.HerosForgeModel = e.herosforgemodel; + item.Icon = e.icon; + strn0cpy(item.IDFile, e.idfile.c_str(), sizeof(item.IDFile)); + item.Material = e.material; // Resists - item.CR = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::cr]), -128, 127)); - item.DR = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::dr]), -128, 127)); - item.FR = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::fr]), -128, 127)); - item.MR = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::mr]), -128, 127)); - item.PR = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::pr]), -128, 127)); - item.SVCorruption = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::svcorruption]), -128, 127)); + item.CR = EQ::Clamp(e.cr, -128, 127); + item.DR = EQ::Clamp(e.dr, -128, 127); + item.FR = EQ::Clamp(e.fr, -128, 127); + item.MR = EQ::Clamp(e.mr, -128, 127); + item.PR = EQ::Clamp(e.pr, -128, 127); + item.SVCorruption = EQ::Clamp(e.svcorruption, -128, 127); // Heroic Resists - item.HeroicCR = Strings::ToInt(row[ItemField::heroic_cr]); - item.HeroicDR = Strings::ToInt(row[ItemField::heroic_dr]); - item.HeroicFR = Strings::ToInt(row[ItemField::heroic_fr]); - item.HeroicMR = Strings::ToInt(row[ItemField::heroic_mr]); - item.HeroicPR = Strings::ToInt(row[ItemField::heroic_pr]); - item.HeroicSVCorrup = Strings::ToInt(row[ItemField::heroic_svcorrup]); + item.HeroicCR = e.heroic_cr; + item.HeroicDR = e.heroic_dr; + item.HeroicFR = e.heroic_fr; + item.HeroicMR = e.heroic_mr; + item.HeroicPR = e.heroic_pr; + item.HeroicSVCorrup = e.heroic_svcorrup; // Stats - item.AAgi = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::aagi]), -128, 127)); - item.ACha = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::acha]), -128, 127)); - item.ADex = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::adex]), -128, 127)); - item.AInt = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::aint]), -128, 127)); - item.ASta = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::asta]), -128, 127)); - item.AStr = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::astr]), -128, 127)); - item.AWis = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::awis]), -128, 127)); + item.AAgi = EQ::Clamp(e.aagi, -128, 127); + item.ACha = EQ::Clamp(e.acha, -128, 127); + item.ADex = EQ::Clamp(e.adex, -128, 127); + item.AInt = EQ::Clamp(e.aint, -128, 127); + item.ASta = EQ::Clamp(e.asta, -128, 127); + item.AStr = EQ::Clamp(e.astr, -128, 127); + item.AWis = EQ::Clamp(e.awis, -128, 127); // Heroic Stats - item.HeroicAgi = Strings::ToInt(row[ItemField::heroic_agi]); - item.HeroicCha = Strings::ToInt(row[ItemField::heroic_cha]); - item.HeroicDex = Strings::ToInt(row[ItemField::heroic_dex]); - item.HeroicInt = Strings::ToInt(row[ItemField::heroic_int]); - item.HeroicSta = Strings::ToInt(row[ItemField::heroic_sta]); - item.HeroicStr = Strings::ToInt(row[ItemField::heroic_str]); - item.HeroicWis = Strings::ToInt(row[ItemField::heroic_wis]); + item.HeroicAgi = e.heroic_agi; + item.HeroicCha = e.heroic_cha; + item.HeroicDex = e.heroic_dex; + item.HeroicInt = e.heroic_int; + item.HeroicSta = e.heroic_sta; + item.HeroicStr = e.heroic_str; + item.HeroicWis = e.heroic_wis; // Health, Mana, and Endurance - item.HP = Strings::ToInt(row[ItemField::hp]); - item.Regen = Strings::ToInt(row[ItemField::regen]); - item.Mana = Strings::ToInt(row[ItemField::mana]); - item.ManaRegen = Strings::ToInt(row[ItemField::manaregen]); - item.Endur = Strings::ToInt(row[ItemField::endur]); - item.EnduranceRegen = Strings::ToInt(row[ItemField::enduranceregen]); + item.HP = e.hp; + item.Regen = e.regen; + item.Mana = e.mana; + item.ManaRegen = e.manaregen; + item.Endur = e.endur; + item.EnduranceRegen = e.enduranceregen; // Bane Damage - item.BaneDmgAmt = Strings::ToInt(row[ItemField::banedmgamt]); - item.BaneDmgBody = Strings::ToUnsignedInt(row[ItemField::banedmgbody]); - item.BaneDmgRace = Strings::ToUnsignedInt(row[ItemField::banedmgrace]); - item.BaneDmgRaceAmt = Strings::ToUnsignedInt(row[ItemField::banedmgraceamt]); + item.BaneDmgAmt = e.banedmgamt; + item.BaneDmgBody = e.banedmgbody; + item.BaneDmgRace = e.banedmgrace; + item.BaneDmgRaceAmt = e.banedmgraceamt; // Elemental Damage - item.ElemDmgType = static_cast(Strings::ToUnsignedInt(row[ItemField::elemdmgtype])); - item.ElemDmgAmt = static_cast(Strings::ToUnsignedInt(row[ItemField::elemdmgamt])); + item.ElemDmgType = static_cast(e.elemdmgtype); + item.ElemDmgAmt = static_cast(e.elemdmgamt); // Combat - item.BackstabDmg = Strings::ToUnsignedInt(row[ItemField::backstabdmg]); - item.Damage = Strings::ToUnsignedInt(row[ItemField::damage]); - item.Delay = static_cast(Strings::ToUnsignedInt(row[ItemField::delay])); - item.Range = static_cast(Strings::ToUnsignedInt(row[ItemField::range])); + item.BackstabDmg = e.backstabdmg; + item.Damage = e.damage; + item.Delay = static_cast(e.delay); + item.Range = static_cast(e.range_); // Combat Stats - item.AC = Strings::ToInt(row[ItemField::ac]); - item.Accuracy = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::accuracy]), -128, 127)); - item.Attack = Strings::ToInt(row[ItemField::attack]); - item.Avoidance = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::avoidance]), -128, 127)); - item.Clairvoyance = Strings::ToUnsignedInt(row[ItemField::clairvoyance]); - item.CombatEffects = Strings::IsNumber(row[ItemField::combateffects]) ? static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::combateffects]), -128, 127)) : 0; - item.DamageShield = Strings::ToInt(row[ItemField::damageshield]); - item.DotShielding = Strings::ToInt(row[ItemField::dotshielding]); - item.DSMitigation = Strings::ToUnsignedInt(row[ItemField::dsmitigation]); - item.Haste = Strings::ToInt(row[ItemField::haste]); - item.HealAmt = Strings::ToInt(row[ItemField::healamt]); - item.Purity = Strings::ToUnsignedInt(row[ItemField::purity]); - item.Shielding = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::shielding]), -128, 127)); - item.SpellDmg = Strings::ToInt(row[ItemField::spelldmg]); - item.SpellShield = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::spellshield]), -128, 127)); - item.StrikeThrough = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::strikethrough]), -128, 127)); - item.StunResist = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::stunresist]), -128, 127)); + item.AC = e.ac; + item.Accuracy = EQ::Clamp(e.accuracy, -128, 127); + item.Attack = e.attack; + item.Avoidance = EQ::Clamp(e.avoidance, -128, 127); + item.Clairvoyance = e.clairvoyance; + item.CombatEffects = Strings::IsNumber(e.combateffects) ? static_cast(EQ::Clamp(Strings::ToInt(e.combateffects), -128, 127)) : 0; + item.DamageShield = e.damageshield; + item.DotShielding = e.dotshielding; + item.DSMitigation = e.dsmitigation; + item.Haste = e.haste; + item.HealAmt = e.healamt; + item.Purity = e.purity; + item.Shielding = EQ::Clamp(e.shielding, -128, 127); + item.SpellDmg = e.spelldmg; + item.SpellShield = EQ::Clamp(e.spellshield, -128, 127); + item.StrikeThrough = EQ::Clamp(e.strikethrough, -128, 127); + item.StunResist = EQ::Clamp(e.stunresist, -128, 127); // Restrictions - item.AugRestrict = Strings::ToUnsignedInt(row[ItemField::augrestrict]); - item.Classes = Strings::ToUnsignedInt(row[ItemField::classes]); - item.Deity = Strings::ToUnsignedInt(row[ItemField::deity]); - item.ItemClass = static_cast(Strings::ToUnsignedInt(row[ItemField::itemclass])); - item.Races = Strings::ToUnsignedInt(row[ItemField::races]); - item.RecLevel = static_cast(Strings::ToUnsignedInt(row[ItemField::reclevel])); - item.RecSkill = static_cast(Strings::ToUnsignedInt(row[ItemField::recskill])); - item.ReqLevel = static_cast(Strings::ToUnsignedInt(row[ItemField::reqlevel])); - item.Slots = Strings::ToUnsignedInt(row[ItemField::slots]); + item.AugRestrict = e.augrestrict; + item.Classes = e.classes; + item.Deity = e.deity; + item.ItemClass = static_cast(e.itemclass); + item.Races = e.races; + item.RecLevel = static_cast(e.reclevel); + item.RecSkill = static_cast(e.recskill); + item.ReqLevel = static_cast(e.reqlevel); + item.Slots = e.slots; // Skill Modifier - item.SkillModValue = Strings::ToInt(row[ItemField::skillmodvalue]); - item.SkillModMax = Strings::ToInt(row[ItemField::skillmodmax]); - item.SkillModType = Strings::ToUnsignedInt(row[ItemField::skillmodtype]); + item.SkillModValue = e.skillmodvalue; + item.SkillModMax = e.skillmodmax; + item.SkillModType = e.skillmodtype; // Extra Damage Skill - item.ExtraDmgSkill = Strings::ToInt(row[ItemField::extradmgskill]); - item.ExtraDmgAmt = Strings::ToInt(row[ItemField::extradmgamt]); + item.ExtraDmgSkill = e.extradmgskill; + item.ExtraDmgAmt = e.extradmgamt; // Bard - item.BardType = Strings::ToUnsignedInt(row[ItemField::bardtype]); - item.BardValue = Strings::ToInt(row[ItemField::bardvalue]); + item.BardType = e.bardtype; + item.BardValue = e.bardvalue; // Faction - item.FactionAmt1 = Strings::ToInt(row[ItemField::factionamt1]); - item.FactionMod1 = Strings::ToInt(row[ItemField::factionmod1]); - item.FactionAmt2 = Strings::ToInt(row[ItemField::factionamt2]); - item.FactionMod2 = Strings::ToInt(row[ItemField::factionmod2]); - item.FactionAmt3 = Strings::ToInt(row[ItemField::factionamt3]); - item.FactionMod3 = Strings::ToInt(row[ItemField::factionmod3]); - item.FactionAmt4 = Strings::ToInt(row[ItemField::factionamt4]); - item.FactionMod4 = Strings::ToInt(row[ItemField::factionmod4]); - - // Augment - item.AugDistiller = Strings::ToUnsignedInt(row[ItemField::augdistiller]); - item.AugSlotType[0] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot1type])); - item.AugSlotVisible[0] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot1visible])); - item.AugSlotType[1] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot2type])); - item.AugSlotVisible[1] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot2visible])); - item.AugSlotType[2] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot3type])); - item.AugSlotVisible[2] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot3visible])); - item.AugSlotType[3] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot4type])); - item.AugSlotVisible[3] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot4visible])); - item.AugSlotType[4] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot5type])); - item.AugSlotVisible[4] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot5visible])); - item.AugSlotType[5] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot6type])); - item.AugSlotVisible[5] = static_cast(Strings::ToUnsignedInt(row[ItemField::augslot6visible])); + item.FactionAmt1 = e.factionamt1; + item.FactionMod1 = e.factionmod1; + item.FactionAmt2 = e.factionamt2; + item.FactionMod2 = e.factionmod2; + item.FactionAmt3 = e.factionamt3; + item.FactionMod3 = e.factionmod3; + item.FactionAmt4 = e.factionamt4; + item.FactionMod4 = e.factionmod4; + + // Augment Distiller + item.AugDistiller = e.augdistiller; + + // Augment Slots + item.AugSlotType[0] = static_cast(e.augslot1type); + item.AugSlotVisible[0] = static_cast(e.augslot1visible); + item.AugSlotType[1] = static_cast(e.augslot2type); + item.AugSlotVisible[1] = static_cast(e.augslot2visible); + item.AugSlotType[2] = static_cast(e.augslot3type); + item.AugSlotVisible[2] = static_cast(e.augslot3visible); + item.AugSlotType[3] = static_cast(e.augslot4type); + item.AugSlotVisible[3] = static_cast(e.augslot4visible); + item.AugSlotType[4] = static_cast(e.augslot5type); + item.AugSlotVisible[4] = static_cast(e.augslot5visible); + item.AugSlotType[5] = static_cast(e.augslot6type); + item.AugSlotVisible[5] = static_cast(e.augslot6visible); // Augment Unknowns for (uint8 i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { @@ -1242,79 +1211,79 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } // LDoN - item.LDoNTheme = Strings::ToUnsignedInt(row[ItemField::ldontheme]); - item.LDoNPrice = Strings::ToUnsignedInt(row[ItemField::ldonprice]); - item.LDoNSellBackRate = Strings::ToUnsignedInt(row[ItemField::ldonsellbackrate]); - item.LDoNSold = Strings::ToUnsignedInt(row[ItemField::ldonsold]); - item.PointType = Strings::ToUnsignedInt(row[ItemField::pointtype]); + item.LDoNTheme = e.ldontheme; + item.LDoNPrice = e.ldonprice; + item.LDoNSellBackRate = e.ldonsellbackrate; + item.LDoNSold = e.ldonsold; + item.PointType = e.pointtype; // Bag - item.BagSize = static_cast(Strings::ToUnsignedInt(row[ItemField::bagsize])); - item.BagSlots = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::bagslots]), 0, static_cast(EQ::invbag::SLOT_COUNT))); - item.BagType = static_cast(Strings::ToUnsignedInt(row[ItemField::bagtype])); - item.BagWR = static_cast(EQ::Clamp(Strings::ToInt(row[ItemField::bagwr]), 0, 100)); + item.BagSize = static_cast(e.bagsize); + item.BagSlots = EQ::Clamp(e.bagslots, 0, static_cast(EQ::invbag::SLOT_COUNT)); + item.BagType = static_cast(e.bagtype); + item.BagWR = EQ::Clamp(e.bagwr, 0, 100); // Bard Effect - item.Bard.Effect = disable_bard_focus_effects ? 0 : Strings::ToInt(row[ItemField::bardeffect]); - item.Bard.Type = disable_bard_focus_effects ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::bardtype])); - item.Bard.Level = disable_bard_focus_effects ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::bardlevel])); - item.Bard.Level2 = disable_bard_focus_effects ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::bardlevel2])); + item.Bard.Effect = disable_bard_focus_effects ? 0 : e.bardeffect; + item.Bard.Type = disable_bard_focus_effects ? 0 : static_cast(e.bardtype); + item.Bard.Level = disable_bard_focus_effects ? 0 : static_cast(e.bardlevel); + item.Bard.Level2 = disable_bard_focus_effects ? 0 : static_cast(e.bardlevel2); // Book - item.Book = static_cast(Strings::ToUnsignedInt(row[ItemField::book])); - item.BookType = Strings::ToUnsignedInt(row[ItemField::booktype]); + item.Book = static_cast(e.book); + item.BookType = e.booktype; // Click Effect - item.CastTime = Strings::ToUnsignedInt(row[ItemField::casttime]); - item.CastTime_ = Strings::ToInt(row[ItemField::casttime_]); - item.Click.Effect = Strings::ToInt(row[ItemField::clickeffect]); - item.Click.Type = static_cast(Strings::ToUnsignedInt(row[ItemField::clicktype])); - item.Click.Level = static_cast(Strings::ToUnsignedInt(row[ItemField::clicklevel])); - item.Click.Level2 = static_cast(Strings::ToUnsignedInt(row[ItemField::clicklevel2])); - strn0cpy(item.ClickName, row[ItemField::clickname], sizeof(item.ClickName)); - item.RecastDelay = Strings::ToUnsignedInt(row[ItemField::recastdelay]); - item.RecastType = Strings::ToInt(row[ItemField::recasttype]); + item.CastTime = e.casttime; + item.CastTime_ = e.casttime_; + item.Click.Effect = e.clickeffect; + item.Click.Type = static_cast(e.clicktype); + item.Click.Level = static_cast(e.clicklevel); + item.Click.Level2 = static_cast(e.clicklevel2); + strn0cpy(item.ClickName, e.clickname.c_str(), sizeof(item.ClickName)); + item.RecastDelay = e.recastdelay; + item.RecastType = e.recasttype; // Focus Effect - item.Focus.Effect = disable_spell_focus_effects ? 0 : Strings::ToInt(row[ItemField::focuseffect]); - item.Focus.Type = disable_spell_focus_effects ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::focustype])); - item.Focus.Level = disable_spell_focus_effects ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::focuslevel])); - item.Focus.Level2 = disable_spell_focus_effects ? 0 : static_cast(Strings::ToUnsignedInt(row[ItemField::focuslevel2])); - strn0cpy(item.FocusName, disable_spell_focus_effects ? "" : row[ItemField::focusname], sizeof(item.FocusName)); + item.Focus.Effect = disable_spell_focus_effects ? 0 : e.focuseffect; + item.Focus.Type = disable_spell_focus_effects ? 0 : static_cast(e.focustype); + item.Focus.Level = disable_spell_focus_effects ? 0 : static_cast(e.focuslevel); + item.Focus.Level2 = disable_spell_focus_effects ? 0 : static_cast(e.focuslevel2); + strn0cpy(item.FocusName, disable_spell_focus_effects ? "" : e.focusname.c_str(), sizeof(item.FocusName)); // Proc Effect - item.Proc.Effect = Strings::ToInt(row[ItemField::proceffect]); - item.Proc.Type = static_cast(Strings::ToUnsignedInt(row[ItemField::proctype])); - item.Proc.Level = static_cast(Strings::ToUnsignedInt(row[ItemField::proclevel])); - item.Proc.Level2 = static_cast(Strings::ToUnsignedInt(row[ItemField::proclevel2])); - strn0cpy(item.ProcName, row[ItemField::procname], sizeof(item.ProcName)); - item.ProcRate = Strings::ToInt(row[ItemField::procrate]); + item.Proc.Effect = e.proceffect; + item.Proc.Type = static_cast(e.proctype); + item.Proc.Level = static_cast(e.proclevel); + item.Proc.Level2 = static_cast(e.proclevel2); + strn0cpy(item.ProcName, e.procname.c_str(), sizeof(item.ProcName)); + item.ProcRate = e.procrate; // Scroll Effect - item.Scroll.Effect = Strings::ToInt(row[ItemField::scrolleffect]); - item.Scroll.Type = static_cast(Strings::ToUnsignedInt(row[ItemField::scrolltype])); - item.Scroll.Level = static_cast(Strings::ToUnsignedInt(row[ItemField::scrolllevel])); - item.Scroll.Level2 = static_cast(Strings::ToUnsignedInt(row[ItemField::scrolllevel2])); - strn0cpy(item.ScrollName, row[ItemField::scrollname], sizeof(item.ScrollName)); + item.Scroll.Effect = e.scrolleffect; + item.Scroll.Type = static_cast(e.scrolltype); + item.Scroll.Level = static_cast(e.scrolllevel); + item.Scroll.Level2 = static_cast(e.scrolllevel2); + strn0cpy(item.ScrollName, e.scrollname.c_str(), sizeof(item.ScrollName)); // Worn Effect - item.Worn.Effect = Strings::ToInt(row[ItemField::worneffect]); - item.Worn.Type = static_cast(Strings::ToUnsignedInt(row[ItemField::worntype])); - item.Worn.Level = static_cast(Strings::ToUnsignedInt(row[ItemField::wornlevel])); - item.Worn.Level2 = static_cast(Strings::ToUnsignedInt(row[ItemField::wornlevel2])); - strn0cpy(item.WornName, row[ItemField::wornname], sizeof(item.WornName)); + item.Worn.Effect = e.worneffect; + item.Worn.Type = static_cast(e.worntype); + item.Worn.Level = static_cast(e.wornlevel); + item.Worn.Level2 = static_cast(e.wornlevel2); + strn0cpy(item.WornName, e.wornname.c_str(), sizeof(item.WornName)); // Evolving Item - item.EvolvingID = Strings::ToUnsignedInt(row[ItemField::evoid]); - item.EvolvingItem = static_cast(Strings::ToUnsignedInt(row[ItemField::evoitem])); - item.EvolvingLevel = static_cast(Strings::ToUnsignedInt(row[ItemField::evolvinglevel])); - item.EvolvingMax = static_cast(Strings::ToUnsignedInt(row[ItemField::evomax])); + item.EvolvingID = e.evoid; + item.EvolvingItem = static_cast(e.evoitem); + item.EvolvingLevel = static_cast(e.evolvinglevel); + item.EvolvingMax = static_cast(e.evomax); // Scripting - item.CharmFileID = Strings::IsNumber(row[ItemField::charmfileid]) ? Strings::ToUnsignedInt(row[ItemField::charmfileid]) : 0; - strn0cpy(item.CharmFile, row[ItemField::charmfile], sizeof(item.CharmFile)); - strn0cpy(item.Filename, row[ItemField::filename], sizeof(item.Filename)); - item.ScriptFileID = Strings::ToUnsignedInt(row[ItemField::scriptfileid]); + item.CharmFileID = Strings::IsNumber(e.charmfileid) ? Strings::ToUnsignedInt(e.charmfileid) : 0; + strn0cpy(item.CharmFile, e.charmfile.c_str(), sizeof(item.CharmFile)); + strn0cpy(item.Filename, e.filename.c_str(), sizeof(item.Filename)); + item.ScriptFileID = e.scriptfileid; try { hash.insert(item.ID, item); @@ -2005,18 +1974,7 @@ uint32 SharedDatabase::GetSpellsCount() uint32 SharedDatabase::GetItemsCount() { - auto results = QueryDatabase("SELECT count(*) FROM items"); - if (!results.Success() || !results.RowCount()) { - return 0; - } - - auto& row = results.begin(); - - if (row[0]) { - return Strings::ToUnsignedInt(row[0]); - } - - return 0; + return ItemsRepository::Count(*this); } void SharedDatabase::SetSharedItemsCount(uint32 shared_items_count) diff --git a/common/shareddb.h b/common/shareddb.h index 8002b62b42..873b8e1a0a 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -158,7 +158,7 @@ class SharedDatabase : public Database { ); EQ::ItemInstance *CreateBaseItem(const EQ::ItemData *item, int16 charges = 0); - void GetItemsCount(int32 &item_count, uint32 &max_id); + void GetItemsCount(int32& item_count, uint32& max_id); void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id); bool LoadItems(const std::string &prefix); const EQ::ItemData *IterateItems(uint32 *id) const; From dee58f9a91a9773f56fd4c9fd9c11c2ccc7fe340 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Mon, 1 Sep 2025 21:39:24 -0400 Subject: [PATCH 037/194] [Repositories] Convert Shared Bank Platinum to Repositories (#5006) --- common/shareddb.cpp | 25 +++++++++---------------- common/shareddb.h | 2 +- zone/client_process.cpp | 2 +- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 89c48daa1d..4039551fd7 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -448,27 +448,20 @@ bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) ); } - int32 SharedDatabase::GetSharedPlatinum(uint32 account_id) { - const auto query = fmt::format("SELECT sharedplat FROM account WHERE id = {}", account_id); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { - return 0; - } - - auto row = results.begin(); - return Strings::ToInt(row[0]); + const auto& e = AccountRepository::FindOne(*this, account_id); + + return e.sharedplat; } -bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) { - const std::string query = StringFormat("UPDATE account SET sharedplat = sharedplat + %i WHERE id = %i", amount_to_add, account_id); - const auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } +bool SharedDatabase::AddSharedPlatinum(uint32 account_id, int amount) +{ + auto e = AccountRepository::FindOne(*this, account_id); - return true; + e.sharedplat += amount; + + return AccountRepository::UpdateOne(*this, e); } bool SharedDatabase::SetStartingItems( diff --git a/common/shareddb.h b/common/shareddb.h index 873b8e1a0a..fa86f859eb 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -104,7 +104,7 @@ class SharedDatabase : public Database { bool VerifyInventory(uint32 account_id, int16 slot_id, const EQ::ItemInstance *inst); bool GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is_charid); int32 GetSharedPlatinum(uint32 account_id); - bool SetSharedPlatinum(uint32 account_id, int32 amount_to_add); + bool AddSharedPlatinum(uint32 account_id, int amount); bool GetInventory(Client* c); bool GetInventory(uint32 account_id, char *name, EQ::InventoryProfile *inv); // deprecated std::map GetItemRecastTimestamps(uint32 char_id); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 71144db89f..e14985763d 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1571,7 +1571,7 @@ void Client::OPMoveCoin(const EQApplicationPacket* app) if (from_bucket == &m_pp.platinum_shared) amount_to_add = 0 - amount_to_take; - database.SetSharedPlatinum(AccountID(),amount_to_add); + database.AddSharedPlatinum(AccountID(),amount_to_add); } } else{ From 231bf8b4ec560a55137366c066cb7a438660bc76 Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 7 Sep 2025 20:13:00 -0300 Subject: [PATCH 038/194] Update database_update_manifest.cpp (#5011) --- common/database/database_update_manifest.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 2236b4ab94..bd030f98a9 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -7188,7 +7188,8 @@ CHANGE COLUMN `field221` `caster_requirement_id` int(11) NULL DEFAULT 0 AFTER `n CHANGE COLUMN `field222` `spell_class` int(11) NULL DEFAULT 0 AFTER `caster_requirement_id`, CHANGE COLUMN `field223` `spell_subclass` int(11) NULL DEFAULT 0 AFTER `spell_class`, CHANGE COLUMN `field232` `no_remove` int(11) NOT NULL DEFAULT 0 AFTER `min_range`; -)" +)", + .content_schema_update = true } // -- template; copy/paste this when you need to create a new entry From 9b143132be28d47f650ee54302d3ee82ab3c69cb Mon Sep 17 00:00:00 2001 From: Mitch Freeman <65987027+neckkola@users.noreply.github.com> Date: Sun, 7 Sep 2025 23:51:39 -0300 Subject: [PATCH 039/194] [Bug Fix] Fix Several Evolving Item Bugs (#4992) * Add sending evolving items via parcels Send, retrieve and inspect tested ok * Sell evolving items to a merchant and purchase tested ok. * Fix a problem with potions and quantity --- common/database/database_update_manifest.cpp | 16 ++- common/evolving_items.cpp | 4 + common/patches/rof2.cpp | 3 +- ..._character_parcels_containers_repository.h | 100 ++++++++------ .../base/base_character_parcels_repository.h | 130 ++++++++++-------- common/version.h | 2 +- zone/parcels.cpp | 34 +++-- 7 files changed, 170 insertions(+), 119 deletions(-) diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index bd030f98a9..d5abb2a0ed 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -7190,8 +7190,22 @@ CHANGE COLUMN `field223` `spell_subclass` int(11) NULL DEFAULT 0 AFTER `spell_cl CHANGE COLUMN `field232` `no_remove` int(11) NOT NULL DEFAULT 0 AFTER `min_range`; )", .content_schema_update = true - } + }, + ManifestEntry{ + .version = 9329, + .description = "2025_08_22_character_parcel_updates.sql", + .check = "SHOW COLUMNS FROM `character_parcels` LIKE 'evolve_amount'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `character_parcels` + ADD COLUMN `evolve_amount` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `quantity`; +ALTER TABLE `character_parcels_containers` + ADD COLUMN `evolve_amount` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `quantity`; +)", + .content_schema_update = false + }, // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ // .version = 9228, diff --git a/common/evolving_items.cpp b/common/evolving_items.cpp index f7f99b7a68..f14a733f3f 100644 --- a/common/evolving_items.cpp +++ b/common/evolving_items.cpp @@ -74,6 +74,10 @@ void EvolvingItemsManager::DoLootChecks(const uint32 char_id, const uint16 slot_ e.item_id = inst.GetID(); e.equipped = inst.GetEvolveEquipped(); e.final_item_id = EvolvingItemsManager::Instance()->GetFinalItemID(inst); + if (inst.GetEvolveCurrentAmount() > 0) { + e.current_amount = inst.GetEvolveCurrentAmount(); + inst.CalculateEvolveProgression(); + } auto r = CharacterEvolvingItemsRepository::InsertOne(*m_db, e); e.id = r.id; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 0d4043d307..b250a5de61 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -6481,7 +6481,7 @@ namespace RoF2 hdr.scaled_value = (inst->IsScaling() ? (inst->GetExp() / 100) : 0); hdr.instance_id = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : inst->GetSerialNumber()); hdr.parcel_item_id = packet_type == ItemPacketParcel ? inst->GetID() : 0; - if (item->EvolvingItem) { + if (item->EvolvingItem && packet_type != ItemPacketParcel && packet_type != ItemPacketMerchant) { hdr.instance_id = inst->GetEvolveUniqueID() & 0xFFFFFFFF; //lower dword hdr.parcel_item_id = inst->GetEvolveUniqueID() >> 32; //upper dword } @@ -6500,6 +6500,7 @@ namespace RoF2 if (item->EvolvingItem > 0) { RoF2::structs::EvolvingItem_Struct evotop; + inst->CalculateEvolveProgression(); evotop.final_item_id = inst->GetEvolveFinalItemID(); evotop.evolve_level = item->EvolvingLevel; diff --git a/common/repositories/base/base_character_parcels_containers_repository.h b/common/repositories/base/base_character_parcels_containers_repository.h index 9c98cc068a..12ca611b75 100644 --- a/common/repositories/base/base_character_parcels_containers_repository.h +++ b/common/repositories/base/base_character_parcels_containers_repository.h @@ -30,6 +30,7 @@ class BaseCharacterParcelsContainersRepository { uint32_t aug_slot_5; uint32_t aug_slot_6; uint32_t quantity; + uint32_t evolve_amount; }; static std::string PrimaryKey() @@ -51,6 +52,7 @@ class BaseCharacterParcelsContainersRepository { "aug_slot_5", "aug_slot_6", "quantity", + "evolve_amount", }; } @@ -68,6 +70,7 @@ class BaseCharacterParcelsContainersRepository { "aug_slot_5", "aug_slot_6", "quantity", + "evolve_amount", }; } @@ -108,17 +111,18 @@ class BaseCharacterParcelsContainersRepository { { CharacterParcelsContainers e{}; - e.id = 0; - e.parcels_id = 0; - e.slot_id = 0; - e.item_id = 0; - e.aug_slot_1 = 0; - e.aug_slot_2 = 0; - e.aug_slot_3 = 0; - e.aug_slot_4 = 0; - e.aug_slot_5 = 0; - e.aug_slot_6 = 0; - e.quantity = 0; + e.id = 0; + e.parcels_id = 0; + e.slot_id = 0; + e.item_id = 0; + e.aug_slot_1 = 0; + e.aug_slot_2 = 0; + e.aug_slot_3 = 0; + e.aug_slot_4 = 0; + e.aug_slot_5 = 0; + e.aug_slot_6 = 0; + e.quantity = 0; + e.evolve_amount = 0; return e; } @@ -155,17 +159,18 @@ class BaseCharacterParcelsContainersRepository { if (results.RowCount() == 1) { CharacterParcelsContainers e{}; - e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; - e.parcels_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.slot_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.item_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.aug_slot_1 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.aug_slot_2 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - e.aug_slot_3 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; - e.aug_slot_4 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; - e.aug_slot_5 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.aug_slot_6 = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; - e.quantity = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.parcels_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.slot_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.item_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.aug_slot_1 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.aug_slot_2 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.aug_slot_3 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.aug_slot_4 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.aug_slot_5 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.aug_slot_6 = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.quantity = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.evolve_amount = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; return e; } @@ -209,6 +214,7 @@ class BaseCharacterParcelsContainersRepository { v.push_back(columns[8] + " = " + std::to_string(e.aug_slot_5)); v.push_back(columns[9] + " = " + std::to_string(e.aug_slot_6)); v.push_back(columns[10] + " = " + std::to_string(e.quantity)); + v.push_back(columns[11] + " = " + std::to_string(e.evolve_amount)); auto results = db.QueryDatabase( fmt::format( @@ -241,6 +247,7 @@ class BaseCharacterParcelsContainersRepository { v.push_back(std::to_string(e.aug_slot_5)); v.push_back(std::to_string(e.aug_slot_6)); v.push_back(std::to_string(e.quantity)); + v.push_back(std::to_string(e.evolve_amount)); auto results = db.QueryDatabase( fmt::format( @@ -281,6 +288,7 @@ class BaseCharacterParcelsContainersRepository { v.push_back(std::to_string(e.aug_slot_5)); v.push_back(std::to_string(e.aug_slot_6)); v.push_back(std::to_string(e.quantity)); + v.push_back(std::to_string(e.evolve_amount)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -314,17 +322,18 @@ class BaseCharacterParcelsContainersRepository { for (auto row = results.begin(); row != results.end(); ++row) { CharacterParcelsContainers e{}; - e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; - e.parcels_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.slot_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.item_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.aug_slot_1 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.aug_slot_2 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - e.aug_slot_3 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; - e.aug_slot_4 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; - e.aug_slot_5 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.aug_slot_6 = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; - e.quantity = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.parcels_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.slot_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.item_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.aug_slot_1 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.aug_slot_2 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.aug_slot_3 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.aug_slot_4 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.aug_slot_5 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.aug_slot_6 = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.quantity = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.evolve_amount = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -349,17 +358,18 @@ class BaseCharacterParcelsContainersRepository { for (auto row = results.begin(); row != results.end(); ++row) { CharacterParcelsContainers e{}; - e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; - e.parcels_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.slot_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.item_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.aug_slot_1 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.aug_slot_2 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - e.aug_slot_3 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; - e.aug_slot_4 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; - e.aug_slot_5 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.aug_slot_6 = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; - e.quantity = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.parcels_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.slot_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.item_id = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.aug_slot_1 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.aug_slot_2 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.aug_slot_3 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.aug_slot_4 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.aug_slot_5 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.aug_slot_6 = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.quantity = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.evolve_amount = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -445,6 +455,7 @@ class BaseCharacterParcelsContainersRepository { v.push_back(std::to_string(e.aug_slot_5)); v.push_back(std::to_string(e.aug_slot_6)); v.push_back(std::to_string(e.quantity)); + v.push_back(std::to_string(e.evolve_amount)); auto results = db.QueryDatabase( fmt::format( @@ -478,6 +489,7 @@ class BaseCharacterParcelsContainersRepository { v.push_back(std::to_string(e.aug_slot_5)); v.push_back(std::to_string(e.aug_slot_6)); v.push_back(std::to_string(e.quantity)); + v.push_back(std::to_string(e.evolve_amount)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/repositories/base/base_character_parcels_repository.h b/common/repositories/base/base_character_parcels_repository.h index 9263f307bb..df7242aedd 100644 --- a/common/repositories/base/base_character_parcels_repository.h +++ b/common/repositories/base/base_character_parcels_repository.h @@ -30,6 +30,7 @@ class BaseCharacterParcelsRepository { uint32_t aug_slot_6; uint32_t slot_id; uint32_t quantity; + uint32_t evolve_amount; std::string from_name; std::string note; time_t sent_date; @@ -54,6 +55,7 @@ class BaseCharacterParcelsRepository { "aug_slot_6", "slot_id", "quantity", + "evolve_amount", "from_name", "note", "sent_date", @@ -74,6 +76,7 @@ class BaseCharacterParcelsRepository { "aug_slot_6", "slot_id", "quantity", + "evolve_amount", "from_name", "note", "UNIX_TIMESTAMP(sent_date)", @@ -117,20 +120,21 @@ class BaseCharacterParcelsRepository { { CharacterParcels e{}; - e.id = 0; - e.char_id = 0; - e.item_id = 0; - e.aug_slot_1 = 0; - e.aug_slot_2 = 0; - e.aug_slot_3 = 0; - e.aug_slot_4 = 0; - e.aug_slot_5 = 0; - e.aug_slot_6 = 0; - e.slot_id = 0; - e.quantity = 0; - e.from_name = ""; - e.note = ""; - e.sent_date = 0; + e.id = 0; + e.char_id = 0; + e.item_id = 0; + e.aug_slot_1 = 0; + e.aug_slot_2 = 0; + e.aug_slot_3 = 0; + e.aug_slot_4 = 0; + e.aug_slot_5 = 0; + e.aug_slot_6 = 0; + e.slot_id = 0; + e.quantity = 0; + e.evolve_amount = 0; + e.from_name = ""; + e.note = ""; + e.sent_date = 0; return e; } @@ -167,20 +171,21 @@ class BaseCharacterParcelsRepository { if (results.RowCount() == 1) { CharacterParcels e{}; - e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; - e.char_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.aug_slot_1 = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.aug_slot_2 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.aug_slot_3 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - e.aug_slot_4 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; - e.aug_slot_5 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; - e.aug_slot_6 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.slot_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; - e.quantity = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; - e.from_name = row[11] ? row[11] : ""; - e.note = row[12] ? row[12] : ""; - e.sent_date = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.char_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.aug_slot_1 = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.aug_slot_2 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.aug_slot_3 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.aug_slot_4 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.aug_slot_5 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.aug_slot_6 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.slot_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.quantity = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.evolve_amount = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.from_name = row[12] ? row[12] : ""; + e.note = row[13] ? row[13] : ""; + e.sent_date = strtoll(row[14] ? row[14] : "-1", nullptr, 10); return e; } @@ -224,9 +229,10 @@ class BaseCharacterParcelsRepository { v.push_back(columns[8] + " = " + std::to_string(e.aug_slot_6)); v.push_back(columns[9] + " = " + std::to_string(e.slot_id)); v.push_back(columns[10] + " = " + std::to_string(e.quantity)); - v.push_back(columns[11] + " = '" + Strings::Escape(e.from_name) + "'"); - v.push_back(columns[12] + " = '" + Strings::Escape(e.note) + "'"); - v.push_back(columns[13] + " = FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")"); + v.push_back(columns[11] + " = " + std::to_string(e.evolve_amount)); + v.push_back(columns[12] + " = '" + Strings::Escape(e.from_name) + "'"); + v.push_back(columns[13] + " = '" + Strings::Escape(e.note) + "'"); + v.push_back(columns[14] + " = FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")"); auto results = db.QueryDatabase( fmt::format( @@ -259,6 +265,7 @@ class BaseCharacterParcelsRepository { v.push_back(std::to_string(e.aug_slot_6)); v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.quantity)); + v.push_back(std::to_string(e.evolve_amount)); v.push_back("'" + Strings::Escape(e.from_name) + "'"); v.push_back("'" + Strings::Escape(e.note) + "'"); v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")"); @@ -302,6 +309,7 @@ class BaseCharacterParcelsRepository { v.push_back(std::to_string(e.aug_slot_6)); v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.quantity)); + v.push_back(std::to_string(e.evolve_amount)); v.push_back("'" + Strings::Escape(e.from_name) + "'"); v.push_back("'" + Strings::Escape(e.note) + "'"); v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")"); @@ -338,20 +346,21 @@ class BaseCharacterParcelsRepository { for (auto row = results.begin(); row != results.end(); ++row) { CharacterParcels e{}; - e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; - e.char_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.aug_slot_1 = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.aug_slot_2 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.aug_slot_3 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - e.aug_slot_4 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; - e.aug_slot_5 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; - e.aug_slot_6 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.slot_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; - e.quantity = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; - e.from_name = row[11] ? row[11] : ""; - e.note = row[12] ? row[12] : ""; - e.sent_date = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.char_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.aug_slot_1 = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.aug_slot_2 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.aug_slot_3 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.aug_slot_4 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.aug_slot_5 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.aug_slot_6 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.slot_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.quantity = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.evolve_amount = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.from_name = row[12] ? row[12] : ""; + e.note = row[13] ? row[13] : ""; + e.sent_date = strtoll(row[14] ? row[14] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -376,20 +385,21 @@ class BaseCharacterParcelsRepository { for (auto row = results.begin(); row != results.end(); ++row) { CharacterParcels e{}; - e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; - e.char_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.aug_slot_1 = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.aug_slot_2 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; - e.aug_slot_3 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; - e.aug_slot_4 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; - e.aug_slot_5 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; - e.aug_slot_6 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.slot_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; - e.quantity = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; - e.from_name = row[11] ? row[11] : ""; - e.note = row[12] ? row[12] : ""; - e.sent_date = strtoll(row[13] ? row[13] : "-1", nullptr, 10); + e.id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.char_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.item_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.aug_slot_1 = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; + e.aug_slot_2 = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.aug_slot_3 = row[5] ? static_cast(strtoul(row[5], nullptr, 10)) : 0; + e.aug_slot_4 = row[6] ? static_cast(strtoul(row[6], nullptr, 10)) : 0; + e.aug_slot_5 = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; + e.aug_slot_6 = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.slot_id = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.quantity = row[10] ? static_cast(strtoul(row[10], nullptr, 10)) : 0; + e.evolve_amount = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.from_name = row[12] ? row[12] : ""; + e.note = row[13] ? row[13] : ""; + e.sent_date = strtoll(row[14] ? row[14] : "-1", nullptr, 10); all_entries.push_back(e); } @@ -475,6 +485,7 @@ class BaseCharacterParcelsRepository { v.push_back(std::to_string(e.aug_slot_6)); v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.quantity)); + v.push_back(std::to_string(e.evolve_amount)); v.push_back("'" + Strings::Escape(e.from_name) + "'"); v.push_back("'" + Strings::Escape(e.note) + "'"); v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")"); @@ -511,6 +522,7 @@ class BaseCharacterParcelsRepository { v.push_back(std::to_string(e.aug_slot_6)); v.push_back(std::to_string(e.slot_id)); v.push_back(std::to_string(e.quantity)); + v.push_back(std::to_string(e.evolve_amount)); v.push_back("'" + Strings::Escape(e.from_name) + "'"); v.push_back("'" + Strings::Escape(e.note) + "'"); v.push_back("FROM_UNIXTIME(" + (e.sent_date > 0 ? std::to_string(e.sent_date) : "null") + ")"); diff --git a/common/version.h b/common/version.h index af74568c6b..9b9ddb4a63 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9328 +#define CURRENT_BINARY_DATABASE_VERSION 9329 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054 #define CUSTOM_BINARY_DATABASE_VERSION 0 diff --git a/zone/parcels.cpp b/zone/parcels.cpp index 4ef3b1a2b5..f1dc874c1f 100644 --- a/zone/parcels.cpp +++ b/zone/parcels.cpp @@ -61,6 +61,7 @@ void Client::SendBulkParcels() inst->SetCharges(p.second.quantity); inst->SetMerchantCount(1); inst->SetMerchantSlot(p.second.slot_id); + inst->SetEvolveCurrentAmount(p.second.evolve_amount); if (inst->IsStackable()) { inst->SetCharges(p.second.quantity); } @@ -164,6 +165,7 @@ void Client::SendParcel(Parcel_Struct &parcel_in) inst->SetCharges(p.quantity); inst->SetMerchantCount(1); inst->SetMerchantSlot(p.slot_id); + inst->SetEvolveCurrentAmount(p.evolve_amount); if (inst->IsStackable()) { inst->SetCharges(p.quantity); } @@ -381,23 +383,23 @@ void Client::DoParcelSend(const Parcel_Struct *parcel_in) return; } - uint32 quantity{}; + uint32 quantity = 1; if (inst->IsStackable()) { quantity = parcel_in->quantity; - } - else { - quantity = inst->GetCharges() >= 0 ? inst->GetCharges() : parcel_in->quantity; + } else if (inst->GetItem()->MaxCharges > 0) { + quantity = inst->GetCharges(); } CharacterParcelsRepository::CharacterParcels parcel_out{}; - parcel_out.from_name = GetName(); - parcel_out.note = parcel_in->note; - parcel_out.sent_date = time(nullptr); - parcel_out.quantity = quantity; - parcel_out.item_id = inst->GetID(); - parcel_out.char_id = send_to_client.at(0).char_id; - parcel_out.slot_id = next_slot; - parcel_out.id = 0; + parcel_out.from_name = GetName(); + parcel_out.note = parcel_in->note; + parcel_out.sent_date = time(nullptr); + parcel_out.quantity = quantity; + parcel_out.item_id = inst->GetID(); + parcel_out.char_id = send_to_client.at(0).char_id; + parcel_out.slot_id = next_slot; + parcel_out.evolve_amount = inst->GetEvolveCurrentAmount(); + parcel_out.id = 0; if (inst->IsAugmented()) { auto augs = inst->GetAugmentIDs(); @@ -445,7 +447,9 @@ void Client::DoParcelSend(const Parcel_Struct *parcel_in) cpc.aug_slot_5 = augs.at(4); cpc.aug_slot_6 = augs.at(5); } - cpc.quantity = kv.second->GetCharges() >= 0 ? kv.second->GetCharges() : 1; + + cpc.quantity = kv.second->GetCharges() >= 0 ? kv.second->GetCharges() : 1; + cpc.evolve_amount = kv.second->GetEvolveCurrentAmount(); all_entries.push_back(cpc); } CharacterParcelsContainersRepository::InsertMany(database, all_entries); @@ -679,6 +683,8 @@ void Client::DoParcelRetrieve(const ParcelRetrieve_Struct &parcel_in) return; } + inst->SetEvolveCurrentAmount(p->second.evolve_amount); + if (inst->IsStackable()) { inst->SetCharges(item_quantity > 0 ? item_quantity : 1); } @@ -715,6 +721,8 @@ void Client::DoParcelRetrieve(const ParcelRetrieve_Struct &parcel_in) return; } + item->SetEvolveCurrentAmount(i.evolve_amount); + if (CheckLoreConflict(item->GetItem())) { if (RuleB(Parcel, DeleteOnDuplicate)) { MessageString(Chat::Yellow, PARCEL_DUPLICATE_DELETE, inst->GetItem()->Name); From dcaa0ecdaa02577964ebacf3cfc61caa8c74a94d Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Mon, 15 Sep 2025 09:14:29 -0400 Subject: [PATCH 040/194] [Quest API] Add Identifiers to Get/Modify NPC Stat Methods (#5012) --- zone/npc.cpp | 396 +++++++++++++++++++-------------------------------- 1 file changed, 147 insertions(+), 249 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index 8f12645b78..9f8631f4fa 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -2274,9 +2274,9 @@ void NPC::SetLevel(uint8 in_level, bool command) void NPC::ModifyNPCStat(const std::string& stat, const std::string& value) { - auto stat_lower = Strings::ToLower(stat); + const std::string& stat_lower = Strings::ToLower(stat); - auto variable_key = fmt::format( + const std::string& variable_key = fmt::format( "modify_stat_{}", stat_lower ); @@ -2288,40 +2288,24 @@ void NPC::ModifyNPCStat(const std::string& stat, const std::string& value) if (stat_lower == "ac") { AC = Strings::ToInt(value); CalcAC(); - return; - } - else if (stat_lower == "str") { + } else if (stat_lower == "str") { STR = Strings::ToInt(value); - return; - } - else if (stat_lower == "sta") { + } else if (stat_lower == "sta") { STA = Strings::ToInt(value); - return; - } - else if (stat_lower == "agi") { + } else if (stat_lower == "agi") { AGI = Strings::ToInt(value); CalcAC(); - return; - } - else if (stat_lower == "dex") { + } else if (stat_lower == "dex") { DEX = Strings::ToInt(value); - return; - } - else if (stat_lower == "wis") { + } else if (stat_lower == "wis") { WIS = Strings::ToInt(value); CalcMaxMana(); - return; - } - else if (stat_lower == "int" || stat_lower == "_int") { + } else if (stat_lower == "int" || stat_lower == "_int") { INT = Strings::ToInt(value); CalcMaxMana(); - return; - } - else if (stat_lower == "cha") { + } else if (stat_lower == "cha") { CHA = Strings::ToInt(value); - return; - } - else if (stat_lower == "max_hp") { + } else if (stat_lower == "max_hp") { base_hp = Strings::ToBigInt(value); CalcMaxHP(); @@ -2329,45 +2313,27 @@ void NPC::ModifyNPCStat(const std::string& stat, const std::string& value) current_hp = max_hp; } - return; - } - else if (stat_lower == "max_mana") { + } else if (stat_lower == "max_mana") { npc_mana = Strings::ToUnsignedBigInt(value); CalcMaxMana(); if (current_mana > max_mana) { current_mana = max_mana; } - return; - } - else if (stat_lower == "mr") { + } else if (stat_lower == "mr") { MR = Strings::ToInt(value); - return; - } - else if (stat_lower == "fr") { + } else if (stat_lower == "fr") { FR = Strings::ToInt(value); - return; - } - else if (stat_lower == "cr") { + } else if (stat_lower == "cr") { CR = Strings::ToInt(value); - return; - } - else if (stat_lower == "cor") { + } else if (stat_lower == "cor") { Corrup = Strings::ToInt(value); - return; - } - else if (stat_lower == "pr") { + } else if (stat_lower == "pr") { PR = Strings::ToInt(value); - return; - } - else if (stat_lower == "dr") { + } else if (stat_lower == "dr") { DR = Strings::ToInt(value); - return; - } - else if (stat_lower == "phr") { + } else if (stat_lower == "phr") { PhR = Strings::ToInt(value); - return; - } - else if (stat_lower == "runspeed") { + } else if (stat_lower == "runspeed") { runspeed = Strings::ToFloat(value); base_runspeed = (int) (runspeed * 40.0f); base_walkspeed = base_runspeed * 100 / 265; @@ -2375,297 +2341,229 @@ void NPC::ModifyNPCStat(const std::string& stat, const std::string& value) base_fearspeed = base_runspeed * 100 / 127; fearspeed = ((float) base_fearspeed) * 0.025f; CalcBonuses(); - return; - } - else if (stat_lower == "special_attacks") { + } else if (stat_lower == "special_attacks") { NPCSpecialAttacks(value.c_str(), 0, true); - return; - } - else if (stat_lower == "special_abilities") { + } else if (stat_lower == "special_abilities") { ProcessSpecialAbilities(value); - return; - } - else if (stat_lower == "attack_speed") { + } else if (stat_lower == "attack_speed") { attack_speed = Strings::ToFloat(value); CalcBonuses(); - return; - } - else if (stat_lower == "attack_delay") { + } else if (stat_lower == "attack_delay") { /* TODO: fix DB */ attack_delay = Strings::ToInt(value) * 100; CalcBonuses(); - return; - } - else if (stat_lower == "atk") { + } else if (stat_lower == "atk") { ATK = Strings::ToInt(value); - return; - } - else if (stat_lower == "accuracy") { + } else if (stat_lower == "accuracy") { accuracy_rating = Strings::ToInt(value); - return; - } - else if (stat_lower == "avoidance") { + } else if (stat_lower == "avoidance") { avoidance_rating = Strings::ToInt(value); - return; - } - else if (stat_lower == "trackable") { + } else if (stat_lower == "trackable") { trackable = Strings::ToInt(value); - return; - } - else if (stat_lower == "min_hit") { - min_dmg = Strings::ToInt(value); + } else if (stat_lower == "min_hit") { + min_dmg = Strings::ToInt(value); // Clamp max_dmg to be >= min_dmg - max_dmg = std::max(min_dmg, max_dmg); + max_dmg = std::max(min_dmg, max_dmg); base_damage = round((max_dmg - min_dmg) / 1.9); min_damage = min_dmg - round(base_damage / 10.0); - return; - } - else if (stat_lower == "max_hit") { - max_dmg = Strings::ToInt(value); + } else if (stat_lower == "max_hit") { + max_dmg = Strings::ToInt(value); // Clamp min_dmg to be <= max_dmg - min_dmg = std::min(min_dmg, max_dmg); + min_dmg = std::min(min_dmg, max_dmg); base_damage = round((max_dmg - min_dmg) / 1.9); min_damage = min_dmg - round(base_damage / 10.0); - return; - } - else if (stat_lower == "attack_count") { + } else if (stat_lower == "attack_count") { attack_count = Strings::ToInt(value); - return; - } - else if (stat_lower == "see_invis") { + } else if (stat_lower == "see_invis") { see_invis = Strings::ToInt(value); - return; - } - else if (stat_lower == "see_invis_undead") { + } else if (stat_lower == "see_invis_undead") { see_invis_undead = Strings::ToInt(value); - return; - } - else if (stat_lower == "see_hide") { + } else if (stat_lower == "see_hide") { see_hide = Strings::ToInt(value); - return; - } - else if (stat_lower == "see_improved_hide") { + } else if (stat_lower == "see_improved_hide") { see_improved_hide = Strings::ToInt(value); - return; - } - else if (stat_lower == "hp_regen") { + } else if (stat_lower == "hp_regen") { hp_regen = Strings::ToBigInt(value); - return; - } - else if (stat_lower == "hp_regen_per_second") { + } else if (stat_lower == "hp_regen_per_second") { hp_regen_per_second = Strings::ToBigInt(value); - return; - } - else if (stat_lower == "mana_regen") { + } else if (stat_lower == "mana_regen") { mana_regen = Strings::ToBigInt(value); - return; - } - else if (stat_lower == "level") { + } else if (stat_lower == "level") { SetLevel(Strings::ToInt(value)); - return; - } - else if (stat_lower == "aggro") { + } else if (stat_lower == "aggro") { pAggroRange = Strings::ToFloat(value); - return; - } - else if (stat_lower == "assist") { + } else if (stat_lower == "assist") { pAssistRange = Strings::ToFloat(value); - return; - } - else if (stat_lower == "slow_mitigation") { + } else if (stat_lower == "slow_mitigation") { slow_mitigation = Strings::ToInt(value); - return; - } - else if (stat_lower == "loottable_id") { + } else if (stat_lower == "loottable_id") { m_loottable_id = Strings::ToFloat(value); - return; - } - else if (stat_lower == "healscale") { + } else if (stat_lower == "healscale") { healscale = Strings::ToFloat(value); - return; - } - else if (stat_lower == "spellscale") { + } else if (stat_lower == "spellscale") { spellscale = Strings::ToFloat(value); - return; - } - else if (stat_lower == "npc_spells_id") { + } else if (stat_lower == "npc_spells_id") { AI_AddNPCSpells(Strings::ToInt(value)); - return; - } - else if (stat_lower == "npc_spells_effects_id") { + } else if (stat_lower == "npc_spells_effects_id") { AI_AddNPCSpellsEffects(Strings::ToInt(value)); CalcBonuses(); - return; - } - else if (stat_lower == "heroic_strikethrough") { + } else if (stat_lower == "heroic_strikethrough") { heroic_strikethrough = Strings::ToInt(value); - return; - } - else if (stat_lower == "keeps_sold_items") { + } else if (stat_lower == "keeps_sold_items") { SetKeepsSoldItems(Strings::ToBool(value)); - return; + } else if (stat_lower == "charm_ac") { + charm_ac = Strings::ToInt(value); + } else if (stat_lower == "charm_min_dmg") { + charm_min_dmg = Strings::ToInt(value); + } else if (stat_lower == "charm_max_dmg") { + charm_max_dmg = Strings::ToInt(value); + } else if (stat_lower == "charm_attack_delay") { + charm_attack_delay = Strings::ToInt(value); + } else if (stat_lower == "charm_accuracy_rating") { + charm_accuracy_rating = Strings::ToInt(value); + } else if (stat_lower == "charm_avoidance_rating") { + charm_avoidance_rating = Strings::ToInt(value); + } else if (stat_lower == "charm_atk") { + charm_atk = Strings::ToInt(value); + } else if (stat_lower == "default_ac") { + default_ac = Strings::ToInt(value); + } else if (stat_lower == "default_min_dmg") { + default_min_dmg = Strings::ToInt(value); + } else if (stat_lower == "default_max_dmg") { + default_max_dmg = Strings::ToInt(value); + } else if (stat_lower == "default_attack_delay") { + default_attack_delay = Strings::ToInt(value); + } else if (stat_lower == "default_accuracy_rating") { + default_accuracy_rating = Strings::ToInt(value); + } else if (stat_lower == "default_avoidance_rating") { + default_avoidance_rating = Strings::ToInt(value); + } else if (stat_lower == "default_atk") { + default_atk = Strings::ToInt(value); } } float NPC::GetNPCStat(const std::string& stat) { + const std::string& stat_lower = Strings::ToLower(stat); - if (auto stat_lower = Strings::ToLower(stat); stat_lower == "ac") { + if (stat_lower == "ac") { return AC; - } - else if (stat_lower == "str") { + } else if (stat_lower == "str") { return STR; - } - else if (stat_lower == "sta") { + } else if (stat_lower == "sta") { return STA; - } - else if (stat_lower == "agi") { + } else if (stat_lower == "agi") { return AGI; - } - else if (stat_lower == "dex") { + } else if (stat_lower == "dex") { return DEX; - } - else if (stat_lower == "wis") { + } else if (stat_lower == "wis") { return WIS; - } - else if (stat_lower == "int" || stat_lower == "_int") { + } else if (stat_lower == "int" || stat_lower == "_int") { return INT; - } - else if (stat_lower == "cha") { + } else if (stat_lower == "cha") { return CHA; - } - else if (stat_lower == "max_hp") { + } else if (stat_lower == "max_hp") { return base_hp; - } - else if (stat_lower == "max_mana") { + } else if (stat_lower == "max_mana") { return npc_mana; - } - else if (stat_lower == "mr") { + } else if (stat_lower == "mr") { return MR; - } - else if (stat_lower == "fr") { + } else if (stat_lower == "fr") { return FR; - } - else if (stat_lower == "cr") { + } else if (stat_lower == "cr") { return CR; - } - else if (stat_lower == "cor") { + } else if (stat_lower == "cor") { return Corrup; - } - else if (stat_lower == "phr") { + } else if (stat_lower == "phr") { return PhR; - } - else if (stat_lower == "pr") { + } else if (stat_lower == "pr") { return PR; - } - else if (stat_lower == "dr") { + } else if (stat_lower == "dr") { return DR; - } - else if (stat_lower == "runspeed") { + } else if (stat_lower == "runspeed") { return runspeed; - } - else if (stat_lower == "attack_speed") { + } else if (stat_lower == "attack_speed") { return attack_speed; - } - else if (stat_lower == "attack_delay") { + } else if (stat_lower == "attack_delay") { return attack_delay; - } - else if (stat_lower == "atk") { + } else if (stat_lower == "atk") { return ATK; - } - else if (stat_lower == "accuracy") { + } else if (stat_lower == "accuracy") { return accuracy_rating; - } - else if (stat_lower == "avoidance") { + } else if (stat_lower == "avoidance") { return avoidance_rating; - } - else if (stat_lower == "trackable") { + } else if (stat_lower == "trackable") { return trackable; - } - else if (stat_lower == "min_hit") { + } else if (stat_lower == "min_hit") { return min_dmg; - } - else if (stat_lower == "max_hit") { + } else if (stat_lower == "max_hit") { return max_dmg; - } - else if (stat_lower == "attack_count") { + } else if (stat_lower == "attack_count") { return attack_count; - } - else if (stat_lower == "see_invis") { + } else if (stat_lower == "see_invis") { return see_invis; - } - else if (stat_lower == "see_invis_undead") { + } else if (stat_lower == "see_invis_undead") { return see_invis_undead; - } - else if (stat_lower == "see_hide") { + } else if (stat_lower == "see_hide") { return see_hide; - } - else if (stat_lower == "see_improved_hide") { + } else if (stat_lower == "see_improved_hide") { return see_improved_hide; - } - else if (stat_lower == "hp_regen") { + } else if (stat_lower == "hp_regen") { return hp_regen; - } - else if (stat_lower == "hp_regen_per_second") { + } else if (stat_lower == "hp_regen_per_second") { return hp_regen_per_second; - } - else if (stat_lower == "mana_regen") { + } else if (stat_lower == "mana_regen") { return mana_regen; - } - else if (stat_lower == "level") { + } else if (stat_lower == "level") { return GetOrigLevel(); - } - else if (stat_lower == "aggro") { + } else if (stat_lower == "aggro") { return pAggroRange; - } - else if (stat_lower == "assist") { + } else if (stat_lower == "assist") { return pAssistRange; - } - else if (stat_lower == "slow_mitigation") { + } else if (stat_lower == "slow_mitigation") { return slow_mitigation; - } - else if (stat_lower == "loottable_id") { + } else if (stat_lower == "loottable_id") { return m_loottable_id; - } - else if (stat_lower == "healscale") { + } else if (stat_lower == "healscale") { return healscale; - } - else if (stat_lower == "spellscale") { + } else if (stat_lower == "spellscale") { return spellscale; - } - else if (stat_lower == "npc_spells_id") { + } else if (stat_lower == "npc_spells_id") { return npc_spells_id; - } - else if (stat_lower == "npc_spells_effects_id") { + } else if (stat_lower == "npc_spells_effects_id") { return npc_spells_effects_id; - } - else if (stat_lower == "heroic_strikethrough") { + } else if (stat_lower == "heroic_strikethrough") { return heroic_strikethrough; - } - else if (stat_lower == "keeps_sold_items") { + } else if (stat_lower == "keeps_sold_items") { return keeps_sold_items; - } - //default values - else if (stat_lower == "default_ac") { + } else if (stat_lower == "default_ac") { return default_ac; - } - else if (stat_lower == "default_min_hit") { + } else if (stat_lower == "default_min_hit") { return default_min_dmg; - } - else if (stat_lower == "default_max_hit") { + } else if (stat_lower == "default_max_hit") { return default_max_dmg; - } - else if (stat_lower == "default_attack_delay") { + } else if (stat_lower == "default_attack_delay") { return default_attack_delay; - } - else if (stat_lower == "default_accuracy") { + } else if (stat_lower == "default_accuracy") { return default_accuracy_rating; - } - else if (stat_lower == "default_avoidance") { + } else if (stat_lower == "default_avoidance") { return default_avoidance_rating; - } - else if (stat_lower == "default_atk") { + } else if (stat_lower == "default_atk") { return default_atk; + } else if (stat_lower == "charm_ac") { + return charm_ac; + } else if (stat_lower == "charm_min_hit") { + return charm_min_dmg; + } else if (stat_lower == "charm_max_hit") { + return charm_max_dmg; + } else if (stat_lower == "charm_attack_delay") { + return charm_attack_delay; + } else if (stat_lower == "charm_accuracy") { + return charm_accuracy_rating; + } else if (stat_lower == "charm_avoidance") { + return charm_avoidance_rating; + } else if (stat_lower == "charm_atk") { + return charm_atk; } return 0.0f; From 6506ad5b512e2d05e673afbdddc5cf57208fac60 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Mon, 15 Sep 2025 09:14:46 -0400 Subject: [PATCH 041/194] [Quest API] Add EVENT_CHARM_START and EVENT_CHARM_END (#5013) --- zone/embparser.cpp | 2 ++ zone/event_codes.h | 2 ++ zone/lua_general.cpp | 4 ++- zone/lua_parser.cpp | 6 +++- zone/npc.cpp | 79 +++++++++++++++++++----------------------- zone/npc.h | 2 +- zone/spell_effects.cpp | 14 ++++---- 7 files changed, 55 insertions(+), 54 deletions(-) diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 6d220b8d81..ad9708d527 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -208,6 +208,8 @@ const char* QuestEventSubroutines[_LargestEventID] = { "EVENT_SPELL_BLOCKED", "EVENT_READ_ITEM", "EVENT_PET_COMMAND", + "EVENT_CHARM_START", + "EVENT_CHARM_END", // Add new events before these or Lua crashes "EVENT_SPELL_EFFECT_BOT", diff --git a/zone/event_codes.h b/zone/event_codes.h index 0d14f565d2..ff345abff5 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -146,6 +146,8 @@ typedef enum { EVENT_SPELL_BLOCKED, EVENT_READ_ITEM, EVENT_PET_COMMAND, + EVENT_CHARM_START, + EVENT_CHARM_END, // Add new events before these or Lua crashes EVENT_SPELL_EFFECT_BOT, diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index ae8c4b2af0..1873aec0b6 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -6992,7 +6992,9 @@ luabind::scope lua_register_events() { luabind::value("entity_variable_update", static_cast(EVENT_ENTITY_VARIABLE_UPDATE)), luabind::value("aa_loss", static_cast(EVENT_AA_LOSS)), luabind::value("read", static_cast(EVENT_READ_ITEM)), - luabind::value("pet_command", static_cast(EVENT_PET_COMMAND)) + luabind::value("pet_command", static_cast(EVENT_PET_COMMAND)), + luabind::value("charm_start", static_cast(EVENT_CHARM_START)), + luabind::value("charm_end", static_cast(EVENT_CHARM_END)) )]; } diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index c3f37aec57..3e3a5257fa 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -189,7 +189,9 @@ const char *LuaEvents[_LargestEventID] = { "event_aa_loss", "event_spell_blocked", "event_read_item", - "event_pet_command" + "event_pet_command", + "event_charm_start", + "event_charm_end" }; extern Zone *zone; @@ -266,6 +268,8 @@ LuaParser::LuaParser() { NPCArgumentDispatch[EVENT_ENTITY_VARIABLE_UPDATE] = handle_npc_entity_variable; NPCArgumentDispatch[EVENT_SPELL_BLOCKED] = handle_npc_spell_blocked; NPCArgumentDispatch[EVENT_PET_COMMAND] = handle_npc_pet_command; + NPCArgumentDispatch[EVENT_CHARM_START] = handle_npc_single_mob; + NPCArgumentDispatch[EVENT_CHARM_END] = handle_npc_single_mob; PlayerArgumentDispatch[EVENT_SAY] = handle_player_say; PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage; diff --git a/zone/npc.cpp b/zone/npc.cpp index 9f8631f4fa..0a91d8e52c 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -3285,62 +3285,55 @@ void NPC::DepopSwarmPets() } } -void NPC::ModifyStatsOnCharm(bool is_charm_removed) +void NPC::ModifyStatsOnCharm(bool remove_charm, Mob* charmer) { - if (is_charm_removed) { - if (charm_ac) { - AC = default_ac; - } - if (charm_attack_delay) { - attack_delay = default_attack_delay; - } - if (charm_accuracy_rating) { - accuracy_rating = default_accuracy_rating; - } - if (charm_avoidance_rating) { - avoidance_rating = default_avoidance_rating; - } - if (charm_atk) { - ATK = default_atk; - } - if (charm_min_dmg || charm_max_dmg) { - base_damage = round((default_max_dmg - default_min_dmg) / 1.9); - min_damage = default_min_dmg - round(base_damage / 10.0); - } - if (RuleB(Spells, CharmDisablesSpecialAbilities)) { - ProcessSpecialAbilities(default_special_abilities); - } + if (!remove_charm && parse->HasQuestSub(GetNPCTypeID(), EVENT_CHARM_START)) { + parse->EventNPC(EVENT_CHARM_START, this, charmer, "", 0); + } else if (remove_charm && parse->HasQuestSub(GetNPCTypeID(), EVENT_CHARM_END)) { + parse->EventNPC(EVENT_CHARM_END, this, charmer, "", 0); + } - SetAttackTimer(); - CalcAC(); + const int new_ac = remove_charm ? default_ac : charm_ac; + const int new_attack_delay = remove_charm ? default_attack_delay : charm_attack_delay; + const int new_accuracy_rating = remove_charm ? default_accuracy_rating : charm_accuracy_rating; + const int new_avoidance_rating = remove_charm ? default_avoidance_rating : charm_avoidance_rating; + const int new_atk = remove_charm ? default_atk : charm_atk; + const int new_min_dmg = remove_charm ? default_min_dmg : charm_min_dmg; + const int new_max_dmg = remove_charm ? default_max_dmg : charm_max_dmg; - return; + if (new_ac) { + AC = new_ac; } - if (charm_ac) { - AC = charm_ac; - } - if (charm_attack_delay) { - attack_delay = charm_attack_delay; + if (new_attack_delay) { + attack_delay = new_attack_delay; } - if (charm_accuracy_rating) { - accuracy_rating = charm_accuracy_rating; + + if (new_accuracy_rating) { + accuracy_rating = new_accuracy_rating; } - if (charm_avoidance_rating) { - avoidance_rating = charm_avoidance_rating; + + if (new_avoidance_rating) { + avoidance_rating = new_avoidance_rating; } - if (charm_atk) { - ATK = charm_atk; + + if (new_atk) { + ATK = new_atk; } - if (charm_min_dmg || charm_max_dmg) { - base_damage = round((charm_max_dmg - charm_min_dmg) / 1.9); - min_damage = charm_min_dmg - round(base_damage / 10.0); + + if (new_min_dmg || new_max_dmg) { + base_damage = std::round((new_max_dmg - new_min_dmg) / 1.9); + min_damage = new_min_dmg - std::round(base_damage / 10.0); } + if (RuleB(Spells, CharmDisablesSpecialAbilities)) { - ClearSpecialAbilities(); + if (remove_charm) { + ProcessSpecialAbilities(default_special_abilities); + } else { + ClearSpecialAbilities(); + } } - // the rest of the stats aren't cached, so lets just do these two instead of full CalcBonuses() SetAttackTimer(); CalcAC(); } diff --git a/zone/npc.h b/zone/npc.h index 4c4d3cb1bb..90569d12b2 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -346,7 +346,7 @@ class NPC : public Mob int64 GetNPCHPRegen() const { return hp_regen + itembonuses.HPRegen + spellbonuses.HPRegen; } inline const char* GetAmmoIDfile() const { return ammo_idfile; } - void ModifyStatsOnCharm(bool is_charm_removed); + void ModifyStatsOnCharm(bool remove_charm, Mob* charmer); //waypoint crap int GetMaxWp() const { return max_wp; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 145c4f67a7..42078e3222 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -835,12 +835,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove SendAppearancePacket(AppearanceType::Pet, caster->GetID(), true, true); } - if (IsClient()) - { + if (IsClient()) { CastToClient()->AI_Start(); - } else if(IsNPC()) { - CastToNPC()->SetPetSpellID(0); //not a pet spell. - CastToNPC()->ModifyStatsOnCharm(false); + } else if (IsNPC()) { + CastToNPC()->SetPetSpellID(0); //not a pet spell. + CastToNPC()->ModifyStatsOnCharm(false, caster); } bool bBreak = false; @@ -4418,10 +4417,9 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) case SpellEffect::Charm: { - if(IsNPC()) - { + if (IsNPC()) { CastToNPC()->RestoreGuardSpotCharm(); - CastToNPC()->ModifyStatsOnCharm(true); + CastToNPC()->ModifyStatsOnCharm(true, GetOwner()); } SendAppearancePacket(AppearanceType::Pet, 0, true, true); From 0bbb5b90e72c3db41d2a9d73548879fbbe9d81cd Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Mon, 15 Sep 2025 09:14:59 -0400 Subject: [PATCH 042/194] [Repositories] Convert Total Time Played to Repositories (#5008) --- common/repositories/character_data_repository.h | 16 ++++++++++++++++ common/shareddb.cpp | 10 ---------- common/shareddb.h | 1 - zone/client_packet.cpp | 4 ++-- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/common/repositories/character_data_repository.h b/common/repositories/character_data_repository.h index d95ac2fda3..68390fc35e 100644 --- a/common/repositories/character_data_repository.h +++ b/common/repositories/character_data_repository.h @@ -191,6 +191,22 @@ class CharacterDataRepository: public BaseCharacterDataRepository { return character_ids; } + + static uint32_t GetTotalTimePlayed(Database& db, uint32_t account_id) + { + auto query = fmt::format( + "SELECT SUM(time_played) FROM `character_data` WHERE `account_id` = {}", + account_id + ); + + auto results = db.QueryDatabase(query); + if (!results.Success()) { + return 0; + } + + auto row = results.begin(); + return Strings::ToUnsignedInt(row[0]); + } }; #endif //EQEMU_CHARACTER_DATA_REPOSITORY_H diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 4039551fd7..5570a1d361 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -122,16 +122,6 @@ bool SharedDatabase::SetGMFlymode(uint32 account_id, uint8 flymode) return a.id > 0; } -uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) { - uint32 EntitledTime = 0; - const std::string query = StringFormat("SELECT `time_played` FROM `character_data` WHERE `account_id` = %u", AccountID); - auto results = QueryDatabase(query); - for (auto& row = results.begin(); row != results.end(); ++row) { - EntitledTime += Strings::ToUnsignedInt(row[0]); - } - return EntitledTime; -} - void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey) { char mail_key[17]; diff --git a/common/shareddb.h b/common/shareddb.h index fa86f859eb..bad19eb8e8 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -82,7 +82,6 @@ class SharedDatabase : public Database { bool UpdateInjectedCommandSettings(const std::vector> &injected); bool UpdateOrphanedCommandSettings(const std::vector &orphaned); bool GetCommandSubSettings(std::vector &command_subsettings); - uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID); bool SetGMInvul(uint32 account_id, bool gminvul); bool SetGMFlymode(uint32 account_id, uint8 flymode); void SetMailKey(int CharID, int IPAddress, int MailKey); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 42f0b8bbed..441b4a5383 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1713,7 +1713,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (zone->IsPVPZone()) m_pp.pvp = 1; /* Time entitled on Account: Move to account */ - m_pp.timeentitledonaccount = database.GetTotalTimeEntitledOnAccount(AccountID()) / 1440; + m_pp.timeentitledonaccount = CharacterDataRepository::GetTotalTimePlayed(database, AccountID()) / 1440; /* Reset rest timer if the durations have been lowered in the database */ if ((m_pp.RestTimer > RuleI(Character, RestRegenTimeToActivate)) && (m_pp.RestTimer > RuleI(Character, RestRegenRaidTimeToActivate))) m_pp.RestTimer = 0; @@ -7988,7 +7988,7 @@ void Client::Handle_OP_GuildCreate(const EQApplicationPacket *app) if ((Admin() < RuleI(Guild, PlayerCreationRequiredStatus)) || (GetLevel() < RuleI(Guild, PlayerCreationRequiredLevel)) || - (database.GetTotalTimeEntitledOnAccount(AccountID()) < (unsigned int)RuleI(Guild, PlayerCreationRequiredTime))) + (CharacterDataRepository::GetTotalTimePlayed(database, AccountID()) < (unsigned int)RuleI(Guild, PlayerCreationRequiredTime))) { Message(Chat::Red, "Your status, level or time playing on this account are insufficient to use this feature."); return; From 044b9c142061972f7245546f445dd664a3b656ca Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Mon, 15 Sep 2025 14:23:48 -0400 Subject: [PATCH 043/194] [Repositories] Convert Mail Key to Repositories (#5007) * [Repositories] Convert Mail Key to Repositories * Update shareddb.cpp --------- Co-authored-by: JJ <3617814+joligario@users.noreply.github.com> --- common/shareddb.cpp | 57 +++++++++++++++------------------------------ common/shareddb.h | 4 ++-- 2 files changed, 21 insertions(+), 40 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 5570a1d361..4527bfc5c2 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -122,56 +122,37 @@ bool SharedDatabase::SetGMFlymode(uint32 account_id, uint8 flymode) return a.id > 0; } -void SharedDatabase::SetMailKey(int CharID, int IPAddress, int MailKey) +void SharedDatabase::SetMailKey(uint32 character_id, int ip_address, int mail_key) { - char mail_key[17]; + std::string full_mail_key; - if (RuleB(Chat, EnableMailKeyIPVerification) == true) { - sprintf(mail_key, "%08X%08X", IPAddress, MailKey); - } - else { - sprintf(mail_key, "%08X", MailKey); + if (RuleB(Chat, EnableMailKeyIPVerification)) { + full_mail_key = fmt::format("{:08X}{:08X}", ip_address, mail_key); + } else { + full_mail_key = fmt::format("{:08X}", mail_key); } - const std::string query = StringFormat( - "UPDATE character_data SET mailkey = '%s' WHERE id = '%i'", - mail_key, CharID - ); + auto e = CharacterDataRepository::FindOne(*this, character_id); + + e.mailkey = full_mail_key; - const auto results = QueryDatabase(query); - if (!results.Success()) { - LogError("SharedDatabase::SetMailKey({}, {}) : {}", CharID, mail_key, results.ErrorMessage().c_str()); + if (!CharacterDataRepository::UpdateOne(*this, e)) { + LogError("Failed to set mailkey to [{}] for character_id [{}]", full_mail_key, character_id); } } -SharedDatabase::MailKeys SharedDatabase::GetMailKey(int character_id) +SharedDatabase::MailKeys SharedDatabase::GetMailKey(uint32 character_id) { - const std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `id`='%i' LIMIT 1", character_id); - auto results = QueryDatabase(query); - if (!results.Success()) { - return MailKeys{}; - } - - if (!results.RowCount()) { - Log(Logs::General, - Logs::ClientLogin, - "Error: Mailkey for character id [%i] does not exist or could not be found", - character_id - ); - return MailKeys{}; - } - - auto &row = results.begin(); - if (row != results.end()) { - std::string mail_key = row[0]; + auto e = CharacterDataRepository::FindOne(*this, character_id); - return MailKeys{ - .mail_key = mail_key.substr(8), - .mail_key_full = mail_key - }; + if (!e.id) { + return MailKeys{ }; } - return MailKeys{}; + return MailKeys{ + .mail_key = e.mailkey.substr(8), + .mail_key_full = e.mailkey + }; } bool SharedDatabase::SaveCursor( diff --git a/common/shareddb.h b/common/shareddb.h index bad19eb8e8..463aaac96e 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -84,12 +84,12 @@ class SharedDatabase : public Database { bool GetCommandSubSettings(std::vector &command_subsettings); bool SetGMInvul(uint32 account_id, bool gminvul); bool SetGMFlymode(uint32 account_id, uint8 flymode); - void SetMailKey(int CharID, int IPAddress, int MailKey); + void SetMailKey(uint32 character_id, int ip_address, int mail_key); struct MailKeys { std::string mail_key; std::string mail_key_full; }; - MailKeys GetMailKey(int character_id); + MailKeys GetMailKey(uint32 character_id); bool SaveCursor( uint32 char_id, std::list::const_iterator &start, From 4b69df646ca1206e49c1ca5d1029404b7274abe5 Mon Sep 17 00:00:00 2001 From: JJ <3617814+joligario@users.noreply.github.com> Date: Tue, 16 Sep 2025 11:35:03 -0400 Subject: [PATCH 044/194] [Release] 23.10.0 (#5014) * Update CHANGELOG.md * Update version.h * Update package.json --- CHANGELOG.md | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ common/version.h | 2 +- package.json | 2 +- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d87da2db5..010228cacc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,67 @@ +## [23.10.0] 9/15/2025 + +### Build + +* Fix Linking with GCC ([#4969](https://github.com/EQEmu/Server/pull/4969)) @solar984 2025-08-03 + +### Code + +* Add #npcedit npc_tint_id Help Message ([#4982](https://github.com/EQEmu/Server/pull/4982)) @Kinglykrab 2025-08-17 +* Cleanup #show ip_lookup Message ([#5005](https://github.com/EQEmu/Server/pull/5005)) @Kinglykrab 2025-08-30 +* Fix #set race 0 Message ([#5004](https://github.com/EQEmu/Server/pull/5004)) @Kinglykrab 2025-08-30 +* Fix Issues with Strings::Commify and Mob::SendStatsWindow ([#4984](https://github.com/EQEmu/Server/pull/4984)) @Kinglykrab 2025-08-17 +* Remove Attributions ([#4988](https://github.com/EQEmu/Server/pull/4988)) @KimLS 2025-08-16 +* Remove Unused errorname Variable ([#5001](https://github.com/EQEmu/Server/pull/5001)) @Kinglykrab 2025-08-29 + +### Commands + +* Add #find account Subcommand ([#4981](https://github.com/EQEmu/Server/pull/4981)) @Kinglykrab 2025-08-17 +* Add #show keyring Subcommand ([#4973](https://github.com/EQEmu/Server/pull/4973)) @Kinglykrab 2025-08-03 +* Add #task complete Saylink to #task show ([#4985](https://github.com/EQEmu/Server/pull/4985)) @Kinglykrab 2025-08-17 + +### Constants + +* Change Race Changes to Race Namespace ([#5000](https://github.com/EQEmu/Server/pull/5000)) @Kinglykrab 2025-08-30 +* Convert SE Defines to SpellEffect Namespace ([#4999](https://github.com/EQEmu/Server/pull/4999)) @Kinglykrab 2025-08-30 + +### Database + +* Add `heal_amount` to `character_stats_record` ([#4986](https://github.com/EQEmu/Server/pull/4986)) @Kinglykrab 2025-08-17 + +### Fixes + +* Fix #show recipe uint16 Cap ([#4978](https://github.com/EQEmu/Server/pull/4978)) @Kinglykrab 2025-08-11 +* Fix Race 474 for Titanium ([#4979](https://github.com/EQEmu/Server/pull/4979)) @regneq 2025-08-11 +* Fix Recipe Inspect Bug ([#4994](https://github.com/EQEmu/Server/pull/4994)) @Kinglykrab 2025-08-30 +* Fix Several Evolving Item Bugs ([#4992](https://github.com/EQEmu/Server/pull/4992)) @neckkola 2025-09-08 +* Fix Task Reloading ([#5002](https://github.com/EQEmu/Server/pull/5002)) @Kinglykrab 2025-08-29 + +### Loginserver + +* Fix Legacy World When Using Local DB ([#4970](https://github.com/EQEmu/Server/pull/4970)) @solar984 2025-08-03 + +### Pets + +* Add Pet Constants and Methods ([#4987](https://github.com/EQEmu/Server/pull/4987)) @Kinglykrab 2025-08-17 + +### Quest API + +* Add EVENT_CHARM_START and EVENT_CHARM_END ([#5013](https://github.com/EQEmu/Server/pull/5013)) @Kinglykrab 2025-09-15 +* Add GetKeyRing() to Perl/Lua ([#4980](https://github.com/EQEmu/Server/pull/4980)) @Kinglykrab 2025-08-17 +* Add GetNPCTintIndex() to Perl/Lua ([#4983](https://github.com/EQEmu/Server/pull/4983)) @Kinglykrab 2025-08-17 +* Add GetTimers() and GetPausedTimers() to Perl/Lua ([#4965](https://github.com/EQEmu/Server/pull/4965)) @Kinglykrab 2025-08-03 +* Add Identifiers to Get/Modify NPC Stat Methods ([#5012](https://github.com/EQEmu/Server/pull/5012)) @Kinglykrab 2025-09-15 + +### Repositories + +* Convert Character Inspect Messages to Repositories ([#4997](https://github.com/EQEmu/Server/pull/4997)) @Kinglykrab 2025-08-30 +* Convert Damage Shield Types to Repositories ([#4995](https://github.com/EQEmu/Server/pull/4995)) @Kinglykrab 2025-08-30 +* Convert Item Loading to Repositories ([#4998](https://github.com/EQEmu/Server/pull/4998)) @Kinglykrab 2025-08-30 +* Convert Mail Key to Repositories ([#5007](https://github.com/EQEmu/Server/pull/5007)) @Kinglykrab 2025-09-15 +* Convert Shared Bank Platinum to Repositories ([#5006](https://github.com/EQEmu/Server/pull/5006)) @Kinglykrab 2025-09-02 +* Convert Spell Loading to Repositories ([#4996](https://github.com/EQEmu/Server/pull/4996)) @Kinglykrab 2025-08-30 +* Convert Total Time Played to Repositories ([#5008](https://github.com/EQEmu/Server/pull/5008)) @Kinglykrab 2025-09-15 + ## [23.9.1] 8/2/2025 ### Hotfix diff --git a/common/version.h b/common/version.h index 9b9ddb4a63..0b9b4e0e6b 100644 --- a/common/version.h +++ b/common/version.h @@ -25,7 +25,7 @@ // Build variables // these get injected during the build pipeline -#define CURRENT_VERSION "23.9.1-dev" // always append -dev to the current version for custom-builds +#define CURRENT_VERSION "23.10.0-dev" // always append -dev to the current version for custom-builds #define LOGIN_VERSION "0.8.0" #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ diff --git a/package.json b/package.json index d148cc68bb..2ad9967a4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eqemu-server", - "version": "23.9.1", + "version": "23.10.0", "repository": { "type": "git", "url": "https://github.com/EQEmu/Server.git" From 1575a2af403f51b3919118e7405be4634a35d943 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Tue, 16 Sep 2025 22:52:57 -0400 Subject: [PATCH 045/194] [Hotfix] Fixed Mail Key Bug (#5015) * [Hotfix] Fixed Mail Key Bug * Release --- CHANGELOG.md | 5 +++++ common/shareddb.cpp | 8 ++++++-- common/shareddb.h | 2 +- common/version.h | 2 +- package.json | 2 +- world/client.cpp | 2 +- 6 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 010228cacc..b774412133 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [23.10.1] 9/16/2025 + +### Hotfix +* Fixed Mail Key Bug ([#5015](https://github.com/EQEmu/Server/pull/5015)) @Kinglykrab 2025-09-16 + ## [23.10.0] 9/15/2025 ### Build diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 4527bfc5c2..0a9dab91f1 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -122,7 +122,7 @@ bool SharedDatabase::SetGMFlymode(uint32 account_id, uint8 flymode) return a.id > 0; } -void SharedDatabase::SetMailKey(uint32 character_id, int ip_address, int mail_key) +void SharedDatabase::SetMailKey(uint32 character_id, uint32 ip_address, uint32 mail_key) { std::string full_mail_key; @@ -133,6 +133,10 @@ void SharedDatabase::SetMailKey(uint32 character_id, int ip_address, int mail_ke } auto e = CharacterDataRepository::FindOne(*this, character_id); + if (!e.id) { + LogError("Failed to find character_id [{}] when setting mailkey", character_id); + return; + } e.mailkey = full_mail_key; @@ -422,7 +426,7 @@ bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) int32 SharedDatabase::GetSharedPlatinum(uint32 account_id) { const auto& e = AccountRepository::FindOne(*this, account_id); - + return e.sharedplat; } diff --git a/common/shareddb.h b/common/shareddb.h index 463aaac96e..2a78be670d 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -84,7 +84,7 @@ class SharedDatabase : public Database { bool GetCommandSubSettings(std::vector &command_subsettings); bool SetGMInvul(uint32 account_id, bool gminvul); bool SetGMFlymode(uint32 account_id, uint8 flymode); - void SetMailKey(uint32 character_id, int ip_address, int mail_key); + void SetMailKey(uint32 character_id, uint32 ip_address, uint32 mail_key); struct MailKeys { std::string mail_key; std::string mail_key_full; diff --git a/common/version.h b/common/version.h index 0b9b4e0e6b..25688ca0dc 100644 --- a/common/version.h +++ b/common/version.h @@ -25,7 +25,7 @@ // Build variables // these get injected during the build pipeline -#define CURRENT_VERSION "23.10.0-dev" // always append -dev to the current version for custom-builds +#define CURRENT_VERSION "23.10.1-dev" // always append -dev to the current version for custom-builds #define LOGIN_VERSION "0.8.0" #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ diff --git a/package.json b/package.json index 2ad9967a4c..f8782b8f09 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eqemu-server", - "version": "23.10.0", + "version": "23.10.1", "repository": { "type": "git", "url": "https://github.com/EQEmu/Server.git" diff --git a/world/client.cpp b/world/client.cpp index 52244e5316..a2d35a4852 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -985,7 +985,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { safe_delete(outapp); // set mailkey - used for duration of character session - int mail_key = EQ::Random::Instance()->Int(1, INT_MAX); + uint32 mail_key = EQ::Random::Instance()->Int(1, INT_MAX); database.SetMailKey(charid, GetIP(), mail_key); if (UCSServerAvailable_) { From e71ce001ff410b25f9f4726a36b5444eec0c8fdc Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Wed, 17 Sep 2025 00:47:42 -0500 Subject: [PATCH 046/194] Hotfix: revert #4996 --- common/database/database_update_manifest.cpp | 20 - .../base/base_spells_new_repository.h | 2040 ++++++++--------- common/shareddb.cpp | 433 ++-- common/spdat.h | 1 + common/version.h | 2 +- 5 files changed, 1217 insertions(+), 1279 deletions(-) diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index d5abb2a0ed..15dc4a27f5 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -7173,26 +7173,6 @@ ADD COLUMN `heal_amount` int(11) NULL DEFAULT 0 AFTER `spell_damage`; }, ManifestEntry{ .version = 9328, - .description = "2025_08_27_spells_new_column_names.sql", - .check = "SHOW COLUMNS FROM `spells_new` LIKE 'feedbackable'", - .condition = "empty", - .match = "", - .sql = R"( -ALTER TABLE `spells_new` -CHANGE COLUMN `field160` `feedbackable` int(11) NOT NULL DEFAULT 0 AFTER `npc_no_los`, -CHANGE COLUMN `field198` `no_detrimental_spell_aggro` int(11) NOT NULL DEFAULT 0 AFTER `not_extendable`, -CHANGE COLUMN `field209` `no_resist` int(11) NULL DEFAULT 0 AFTER `rank`, -CHANGE COLUMN `field217` `override_crit_chance` int(11) NULL DEFAULT 0 AFTER `field216`, -CHANGE COLUMN `field220` `no_heal_damage_item_mod` int(11) NULL DEFAULT 0 AFTER `maxtargets`, -CHANGE COLUMN `field221` `caster_requirement_id` int(11) NULL DEFAULT 0 AFTER `no_heal_damage_item_mod`, -CHANGE COLUMN `field222` `spell_class` int(11) NULL DEFAULT 0 AFTER `caster_requirement_id`, -CHANGE COLUMN `field223` `spell_subclass` int(11) NULL DEFAULT 0 AFTER `spell_class`, -CHANGE COLUMN `field232` `no_remove` int(11) NOT NULL DEFAULT 0 AFTER `min_range`; -)", - .content_schema_update = true - }, - ManifestEntry{ - .version = 9329, .description = "2025_08_22_character_parcel_updates.sql", .check = "SHOW COLUMNS FROM `character_parcels` LIKE 'evolve_amount'", .condition = "empty", diff --git a/common/repositories/base/base_spells_new_repository.h b/common/repositories/base/base_spells_new_repository.h index 60a19fb577..019e8eaea0 100644 --- a/common/repositories/base/base_spells_new_repository.h +++ b/common/repositories/base/base_spells_new_repository.h @@ -179,7 +179,7 @@ class BaseSpellsNewRepository { int32_t effectdescnum; int32_t effectdescnum2; int32_t npc_no_los; - int32_t feedbackable; + int32_t field160; int32_t reflectable; int32_t bonushate; int32_t field163; @@ -217,7 +217,7 @@ class BaseSpellsNewRepository { int32_t ConeStopAngle; int32_t sneaking; int32_t not_extendable; - int32_t no_detrimental_spell_aggro; + int32_t field198; int32_t field199; int32_t suspendable; int32_t viral_range; @@ -228,7 +228,7 @@ class BaseSpellsNewRepository { int32_t field206; int32_t spellgroup; int32_t rank_; - int32_t no_resist; + int32_t field209; int32_t field210; int32_t CastRestriction; int32_t allowrest; @@ -236,13 +236,13 @@ class BaseSpellsNewRepository { int32_t OutofCombat; int32_t field215; int32_t field216; - int32_t override_crit_chance; + int32_t field217; int32_t aemaxtargets; int32_t maxtargets; - int32_t no_heal_damage_item_mod; - int32_t caster_requirement_id; - int32_t spell_class; - int32_t spell_subclass; + int32_t field220; + int32_t field221; + int32_t field222; + int32_t field223; int32_t persistdeath; int32_t field225; int32_t field226; @@ -251,7 +251,7 @@ class BaseSpellsNewRepository { float max_dist; float max_dist_mod; int32_t min_range; - int32_t no_remove; + int32_t field232; int32_t field233; int32_t field234; int32_t field235; @@ -426,7 +426,7 @@ class BaseSpellsNewRepository { "effectdescnum", "effectdescnum2", "npc_no_los", - "feedbackable", + "field160", "reflectable", "bonushate", "field163", @@ -464,7 +464,7 @@ class BaseSpellsNewRepository { "ConeStopAngle", "sneaking", "not_extendable", - "no_detrimental_spell_aggro", + "field198", "field199", "suspendable", "viral_range", @@ -475,7 +475,7 @@ class BaseSpellsNewRepository { "field206", "spellgroup", "`rank`", - "no_resist", + "field209", "field210", "CastRestriction", "allowrest", @@ -483,13 +483,13 @@ class BaseSpellsNewRepository { "OutofCombat", "field215", "field216", - "override_crit_chance", + "field217", "aemaxtargets", "maxtargets", - "no_heal_damage_item_mod", - "caster_requirement_id", - "spell_class", - "spell_subclass", + "field220", + "field221", + "field222", + "field223", "persistdeath", "field225", "field226", @@ -498,7 +498,7 @@ class BaseSpellsNewRepository { "max_dist", "max_dist_mod", "min_range", - "no_remove", + "field232", "field233", "field234", "field235", @@ -669,7 +669,7 @@ class BaseSpellsNewRepository { "effectdescnum", "effectdescnum2", "npc_no_los", - "feedbackable", + "field160", "reflectable", "bonushate", "field163", @@ -707,7 +707,7 @@ class BaseSpellsNewRepository { "ConeStopAngle", "sneaking", "not_extendable", - "no_detrimental_spell_aggro", + "field198", "field199", "suspendable", "viral_range", @@ -718,7 +718,7 @@ class BaseSpellsNewRepository { "field206", "spellgroup", "`rank`", - "no_resist", + "field209", "field210", "CastRestriction", "allowrest", @@ -726,13 +726,13 @@ class BaseSpellsNewRepository { "OutofCombat", "field215", "field216", - "override_crit_chance", + "field217", "aemaxtargets", "maxtargets", - "no_heal_damage_item_mod", - "caster_requirement_id", - "spell_class", - "spell_subclass", + "field220", + "field221", + "field222", + "field223", "persistdeath", "field225", "field226", @@ -741,7 +741,7 @@ class BaseSpellsNewRepository { "max_dist", "max_dist_mod", "min_range", - "no_remove", + "field232", "field233", "field234", "field235", @@ -786,243 +786,243 @@ class BaseSpellsNewRepository { { SpellsNew e{}; - e.id = 0; - e.name = ""; - e.player_1 = "BLUE_TRAIL"; - e.teleport_zone = ""; - e.you_cast = ""; - e.other_casts = ""; - e.cast_on_you = ""; - e.cast_on_other = ""; - e.spell_fades = ""; - e.range_ = 100; - e.aoerange = 0; - e.pushback = 0; - e.pushup = 0; - e.cast_time = 0; - e.recovery_time = 0; - e.recast_time = 0; - e.buffdurationformula = 7; - e.buffduration = 65; - e.AEDuration = 0; - e.mana = 0; - e.effect_base_value1 = 100; - e.effect_base_value2 = 0; - e.effect_base_value3 = 0; - e.effect_base_value4 = 0; - e.effect_base_value5 = 0; - e.effect_base_value6 = 0; - e.effect_base_value7 = 0; - e.effect_base_value8 = 0; - e.effect_base_value9 = 0; - e.effect_base_value10 = 0; - e.effect_base_value11 = 0; - e.effect_base_value12 = 0; - e.effect_limit_value1 = 0; - e.effect_limit_value2 = 0; - e.effect_limit_value3 = 0; - e.effect_limit_value4 = 0; - e.effect_limit_value5 = 0; - e.effect_limit_value6 = 0; - e.effect_limit_value7 = 0; - e.effect_limit_value8 = 0; - e.effect_limit_value9 = 0; - e.effect_limit_value10 = 0; - e.effect_limit_value11 = 0; - e.effect_limit_value12 = 0; - e.max1 = 0; - e.max2 = 0; - e.max3 = 0; - e.max4 = 0; - e.max5 = 0; - e.max6 = 0; - e.max7 = 0; - e.max8 = 0; - e.max9 = 0; - e.max10 = 0; - e.max11 = 0; - e.max12 = 0; - e.icon = 0; - e.memicon = 0; - e.components1 = -1; - e.components2 = -1; - e.components3 = -1; - e.components4 = -1; - e.component_counts1 = 1; - e.component_counts2 = 1; - e.component_counts3 = 1; - e.component_counts4 = 1; - e.NoexpendReagent1 = -1; - e.NoexpendReagent2 = -1; - e.NoexpendReagent3 = -1; - e.NoexpendReagent4 = -1; - e.formula1 = 100; - e.formula2 = 100; - e.formula3 = 100; - e.formula4 = 100; - e.formula5 = 100; - e.formula6 = 100; - e.formula7 = 100; - e.formula8 = 100; - e.formula9 = 100; - e.formula10 = 100; - e.formula11 = 100; - e.formula12 = 100; - e.LightType = 0; - e.goodEffect = 0; - e.Activated = 0; - e.resisttype = 0; - e.effectid1 = 254; - e.effectid2 = 254; - e.effectid3 = 254; - e.effectid4 = 254; - e.effectid5 = 254; - e.effectid6 = 254; - e.effectid7 = 254; - e.effectid8 = 254; - e.effectid9 = 254; - e.effectid10 = 254; - e.effectid11 = 254; - e.effectid12 = 254; - e.targettype = 2; - e.basediff = 0; - e.skill = 98; - e.zonetype = -1; - e.EnvironmentType = 0; - e.TimeOfDay = 0; - e.classes1 = 255; - e.classes2 = 255; - e.classes3 = 255; - e.classes4 = 255; - e.classes5 = 255; - e.classes6 = 255; - e.classes7 = 255; - e.classes8 = 255; - e.classes9 = 255; - e.classes10 = 255; - e.classes11 = 255; - e.classes12 = 255; - e.classes13 = 255; - e.classes14 = 255; - e.classes15 = 255; - e.classes16 = 255; - e.CastingAnim = 44; - e.TargetAnim = 13; - e.TravelType = 0; - e.SpellAffectIndex = -1; - e.disallow_sit = 0; - e.deities0 = 0; - e.deities1 = 0; - e.deities2 = 0; - e.deities3 = 0; - e.deities4 = 0; - e.deities5 = 0; - e.deities6 = 0; - e.deities7 = 0; - e.deities8 = 0; - e.deities9 = 0; - e.deities10 = 0; - e.deities11 = 0; - e.deities12 = 0; - e.deities13 = 0; - e.deities14 = 0; - e.deities15 = 0; - e.deities16 = 0; - e.field142 = 100; - e.field143 = 0; - e.new_icon = 161; - e.spellanim = 0; - e.uninterruptable = 0; - e.ResistDiff = -150; - e.dot_stacking_exempt = 0; - e.deleteable = 0; - e.RecourseLink = 0; - e.no_partial_resist = 0; - e.field152 = 0; - e.field153 = 0; - e.short_buff_box = -1; - e.descnum = 0; - e.typedescnum = 0; - e.effectdescnum = 0; - e.effectdescnum2 = 0; - e.npc_no_los = 0; - e.feedbackable = 0; - e.reflectable = 0; - e.bonushate = 0; - e.field163 = 100; - e.field164 = -150; - e.ldon_trap = 0; - e.EndurCost = 0; - e.EndurTimerIndex = 0; - e.IsDiscipline = 0; - e.field169 = 0; - e.field170 = 0; - e.field171 = 0; - e.field172 = 0; - e.HateAdded = 0; - e.EndurUpkeep = 0; - e.numhitstype = 0; - e.numhits = 0; - e.pvpresistbase = -150; - e.pvpresistcalc = 100; - e.pvpresistcap = -150; - e.spell_category = -99; - e.pvp_duration = 0; - e.pvp_duration_cap = 0; - e.pcnpc_only_flag = 0; - e.cast_not_standing = 0; - e.can_mgb = 0; - e.nodispell = -1; - e.npc_category = 0; - e.npc_usefulness = 0; - e.MinResist = 0; - e.MaxResist = 0; - e.viral_targets = 0; - e.viral_timer = 0; - e.nimbuseffect = 0; - e.ConeStartAngle = 0; - e.ConeStopAngle = 0; - e.sneaking = 0; - e.not_extendable = 0; - e.no_detrimental_spell_aggro = 0; - e.field199 = 1; - e.suspendable = 0; - e.viral_range = 0; - e.songcap = 0; - e.field203 = 0; - e.field204 = 0; - e.no_block = 0; - e.field206 = -1; - e.spellgroup = 0; - e.rank_ = 0; - e.no_resist = 0; - e.field210 = 1; - e.CastRestriction = 0; - e.allowrest = 0; - e.InCombat = 0; - e.OutofCombat = 0; - e.field215 = 0; - e.field216 = 0; - e.override_crit_chance = 0; - e.aemaxtargets = 0; - e.maxtargets = 0; - e.no_heal_damage_item_mod = 0; - e.caster_requirement_id = 0; - e.spell_class = 0; - e.spell_subclass = 0; - e.persistdeath = 0; - e.field225 = 0; - e.field226 = 0; - e.min_dist = 0; - e.min_dist_mod = 0; - e.max_dist = 0; - e.max_dist_mod = 0; - e.min_range = 0; - e.no_remove = 0; - e.field233 = 0; - e.field234 = 0; - e.field235 = 0; - e.field236 = 0; + e.id = 0; + e.name = ""; + e.player_1 = "BLUE_TRAIL"; + e.teleport_zone = ""; + e.you_cast = ""; + e.other_casts = ""; + e.cast_on_you = ""; + e.cast_on_other = ""; + e.spell_fades = ""; + e.range_ = 100; + e.aoerange = 0; + e.pushback = 0; + e.pushup = 0; + e.cast_time = 0; + e.recovery_time = 0; + e.recast_time = 0; + e.buffdurationformula = 7; + e.buffduration = 65; + e.AEDuration = 0; + e.mana = 0; + e.effect_base_value1 = 100; + e.effect_base_value2 = 0; + e.effect_base_value3 = 0; + e.effect_base_value4 = 0; + e.effect_base_value5 = 0; + e.effect_base_value6 = 0; + e.effect_base_value7 = 0; + e.effect_base_value8 = 0; + e.effect_base_value9 = 0; + e.effect_base_value10 = 0; + e.effect_base_value11 = 0; + e.effect_base_value12 = 0; + e.effect_limit_value1 = 0; + e.effect_limit_value2 = 0; + e.effect_limit_value3 = 0; + e.effect_limit_value4 = 0; + e.effect_limit_value5 = 0; + e.effect_limit_value6 = 0; + e.effect_limit_value7 = 0; + e.effect_limit_value8 = 0; + e.effect_limit_value9 = 0; + e.effect_limit_value10 = 0; + e.effect_limit_value11 = 0; + e.effect_limit_value12 = 0; + e.max1 = 0; + e.max2 = 0; + e.max3 = 0; + e.max4 = 0; + e.max5 = 0; + e.max6 = 0; + e.max7 = 0; + e.max8 = 0; + e.max9 = 0; + e.max10 = 0; + e.max11 = 0; + e.max12 = 0; + e.icon = 0; + e.memicon = 0; + e.components1 = -1; + e.components2 = -1; + e.components3 = -1; + e.components4 = -1; + e.component_counts1 = 1; + e.component_counts2 = 1; + e.component_counts3 = 1; + e.component_counts4 = 1; + e.NoexpendReagent1 = -1; + e.NoexpendReagent2 = -1; + e.NoexpendReagent3 = -1; + e.NoexpendReagent4 = -1; + e.formula1 = 100; + e.formula2 = 100; + e.formula3 = 100; + e.formula4 = 100; + e.formula5 = 100; + e.formula6 = 100; + e.formula7 = 100; + e.formula8 = 100; + e.formula9 = 100; + e.formula10 = 100; + e.formula11 = 100; + e.formula12 = 100; + e.LightType = 0; + e.goodEffect = 0; + e.Activated = 0; + e.resisttype = 0; + e.effectid1 = 254; + e.effectid2 = 254; + e.effectid3 = 254; + e.effectid4 = 254; + e.effectid5 = 254; + e.effectid6 = 254; + e.effectid7 = 254; + e.effectid8 = 254; + e.effectid9 = 254; + e.effectid10 = 254; + e.effectid11 = 254; + e.effectid12 = 254; + e.targettype = 2; + e.basediff = 0; + e.skill = 98; + e.zonetype = -1; + e.EnvironmentType = 0; + e.TimeOfDay = 0; + e.classes1 = 255; + e.classes2 = 255; + e.classes3 = 255; + e.classes4 = 255; + e.classes5 = 255; + e.classes6 = 255; + e.classes7 = 255; + e.classes8 = 255; + e.classes9 = 255; + e.classes10 = 255; + e.classes11 = 255; + e.classes12 = 255; + e.classes13 = 255; + e.classes14 = 255; + e.classes15 = 255; + e.classes16 = 255; + e.CastingAnim = 44; + e.TargetAnim = 13; + e.TravelType = 0; + e.SpellAffectIndex = -1; + e.disallow_sit = 0; + e.deities0 = 0; + e.deities1 = 0; + e.deities2 = 0; + e.deities3 = 0; + e.deities4 = 0; + e.deities5 = 0; + e.deities6 = 0; + e.deities7 = 0; + e.deities8 = 0; + e.deities9 = 0; + e.deities10 = 0; + e.deities11 = 0; + e.deities12 = 0; + e.deities13 = 0; + e.deities14 = 0; + e.deities15 = 0; + e.deities16 = 0; + e.field142 = 100; + e.field143 = 0; + e.new_icon = 161; + e.spellanim = 0; + e.uninterruptable = 0; + e.ResistDiff = -150; + e.dot_stacking_exempt = 0; + e.deleteable = 0; + e.RecourseLink = 0; + e.no_partial_resist = 0; + e.field152 = 0; + e.field153 = 0; + e.short_buff_box = -1; + e.descnum = 0; + e.typedescnum = 0; + e.effectdescnum = 0; + e.effectdescnum2 = 0; + e.npc_no_los = 0; + e.field160 = 0; + e.reflectable = 0; + e.bonushate = 0; + e.field163 = 100; + e.field164 = -150; + e.ldon_trap = 0; + e.EndurCost = 0; + e.EndurTimerIndex = 0; + e.IsDiscipline = 0; + e.field169 = 0; + e.field170 = 0; + e.field171 = 0; + e.field172 = 0; + e.HateAdded = 0; + e.EndurUpkeep = 0; + e.numhitstype = 0; + e.numhits = 0; + e.pvpresistbase = -150; + e.pvpresistcalc = 100; + e.pvpresistcap = -150; + e.spell_category = -99; + e.pvp_duration = 0; + e.pvp_duration_cap = 0; + e.pcnpc_only_flag = 0; + e.cast_not_standing = 0; + e.can_mgb = 0; + e.nodispell = -1; + e.npc_category = 0; + e.npc_usefulness = 0; + e.MinResist = 0; + e.MaxResist = 0; + e.viral_targets = 0; + e.viral_timer = 0; + e.nimbuseffect = 0; + e.ConeStartAngle = 0; + e.ConeStopAngle = 0; + e.sneaking = 0; + e.not_extendable = 0; + e.field198 = 0; + e.field199 = 1; + e.suspendable = 0; + e.viral_range = 0; + e.songcap = 0; + e.field203 = 0; + e.field204 = 0; + e.no_block = 0; + e.field206 = -1; + e.spellgroup = 0; + e.rank_ = 0; + e.field209 = 0; + e.field210 = 1; + e.CastRestriction = 0; + e.allowrest = 0; + e.InCombat = 0; + e.OutofCombat = 0; + e.field215 = 0; + e.field216 = 0; + e.field217 = 0; + e.aemaxtargets = 0; + e.maxtargets = 0; + e.field220 = 0; + e.field221 = 0; + e.field222 = 0; + e.field223 = 0; + e.persistdeath = 0; + e.field225 = 0; + e.field226 = 0; + e.min_dist = 0; + e.min_dist_mod = 0; + e.max_dist = 0; + e.max_dist_mod = 0; + e.min_range = 0; + e.field232 = 0; + e.field233 = 0; + e.field234 = 0; + e.field235 = 0; + e.field236 = 0; return e; } @@ -1059,243 +1059,243 @@ class BaseSpellsNewRepository { if (results.RowCount() == 1) { SpellsNew e{}; - e.id = row[0] ? static_cast(atoi(row[0])) : 0; - e.name = row[1] ? row[1] : ""; - e.player_1 = row[2] ? row[2] : "BLUE_TRAIL"; - e.teleport_zone = row[3] ? row[3] : ""; - e.you_cast = row[4] ? row[4] : ""; - e.other_casts = row[5] ? row[5] : ""; - e.cast_on_you = row[6] ? row[6] : ""; - e.cast_on_other = row[7] ? row[7] : ""; - e.spell_fades = row[8] ? row[8] : ""; - e.range_ = row[9] ? static_cast(atoi(row[9])) : 100; - e.aoerange = row[10] ? static_cast(atoi(row[10])) : 0; - e.pushback = row[11] ? static_cast(atoi(row[11])) : 0; - e.pushup = row[12] ? static_cast(atoi(row[12])) : 0; - e.cast_time = row[13] ? static_cast(atoi(row[13])) : 0; - e.recovery_time = row[14] ? static_cast(atoi(row[14])) : 0; - e.recast_time = row[15] ? static_cast(atoi(row[15])) : 0; - e.buffdurationformula = row[16] ? static_cast(atoi(row[16])) : 7; - e.buffduration = row[17] ? static_cast(atoi(row[17])) : 65; - e.AEDuration = row[18] ? static_cast(atoi(row[18])) : 0; - e.mana = row[19] ? static_cast(atoi(row[19])) : 0; - e.effect_base_value1 = row[20] ? static_cast(atoi(row[20])) : 100; - e.effect_base_value2 = row[21] ? static_cast(atoi(row[21])) : 0; - e.effect_base_value3 = row[22] ? static_cast(atoi(row[22])) : 0; - e.effect_base_value4 = row[23] ? static_cast(atoi(row[23])) : 0; - e.effect_base_value5 = row[24] ? static_cast(atoi(row[24])) : 0; - e.effect_base_value6 = row[25] ? static_cast(atoi(row[25])) : 0; - e.effect_base_value7 = row[26] ? static_cast(atoi(row[26])) : 0; - e.effect_base_value8 = row[27] ? static_cast(atoi(row[27])) : 0; - e.effect_base_value9 = row[28] ? static_cast(atoi(row[28])) : 0; - e.effect_base_value10 = row[29] ? static_cast(atoi(row[29])) : 0; - e.effect_base_value11 = row[30] ? static_cast(atoi(row[30])) : 0; - e.effect_base_value12 = row[31] ? static_cast(atoi(row[31])) : 0; - e.effect_limit_value1 = row[32] ? static_cast(atoi(row[32])) : 0; - e.effect_limit_value2 = row[33] ? static_cast(atoi(row[33])) : 0; - e.effect_limit_value3 = row[34] ? static_cast(atoi(row[34])) : 0; - e.effect_limit_value4 = row[35] ? static_cast(atoi(row[35])) : 0; - e.effect_limit_value5 = row[36] ? static_cast(atoi(row[36])) : 0; - e.effect_limit_value6 = row[37] ? static_cast(atoi(row[37])) : 0; - e.effect_limit_value7 = row[38] ? static_cast(atoi(row[38])) : 0; - e.effect_limit_value8 = row[39] ? static_cast(atoi(row[39])) : 0; - e.effect_limit_value9 = row[40] ? static_cast(atoi(row[40])) : 0; - e.effect_limit_value10 = row[41] ? static_cast(atoi(row[41])) : 0; - e.effect_limit_value11 = row[42] ? static_cast(atoi(row[42])) : 0; - e.effect_limit_value12 = row[43] ? static_cast(atoi(row[43])) : 0; - e.max1 = row[44] ? static_cast(atoi(row[44])) : 0; - e.max2 = row[45] ? static_cast(atoi(row[45])) : 0; - e.max3 = row[46] ? static_cast(atoi(row[46])) : 0; - e.max4 = row[47] ? static_cast(atoi(row[47])) : 0; - e.max5 = row[48] ? static_cast(atoi(row[48])) : 0; - e.max6 = row[49] ? static_cast(atoi(row[49])) : 0; - e.max7 = row[50] ? static_cast(atoi(row[50])) : 0; - e.max8 = row[51] ? static_cast(atoi(row[51])) : 0; - e.max9 = row[52] ? static_cast(atoi(row[52])) : 0; - e.max10 = row[53] ? static_cast(atoi(row[53])) : 0; - e.max11 = row[54] ? static_cast(atoi(row[54])) : 0; - e.max12 = row[55] ? static_cast(atoi(row[55])) : 0; - e.icon = row[56] ? static_cast(atoi(row[56])) : 0; - e.memicon = row[57] ? static_cast(atoi(row[57])) : 0; - e.components1 = row[58] ? static_cast(atoi(row[58])) : -1; - e.components2 = row[59] ? static_cast(atoi(row[59])) : -1; - e.components3 = row[60] ? static_cast(atoi(row[60])) : -1; - e.components4 = row[61] ? static_cast(atoi(row[61])) : -1; - e.component_counts1 = row[62] ? static_cast(atoi(row[62])) : 1; - e.component_counts2 = row[63] ? static_cast(atoi(row[63])) : 1; - e.component_counts3 = row[64] ? static_cast(atoi(row[64])) : 1; - e.component_counts4 = row[65] ? static_cast(atoi(row[65])) : 1; - e.NoexpendReagent1 = row[66] ? static_cast(atoi(row[66])) : -1; - e.NoexpendReagent2 = row[67] ? static_cast(atoi(row[67])) : -1; - e.NoexpendReagent3 = row[68] ? static_cast(atoi(row[68])) : -1; - e.NoexpendReagent4 = row[69] ? static_cast(atoi(row[69])) : -1; - e.formula1 = row[70] ? static_cast(atoi(row[70])) : 100; - e.formula2 = row[71] ? static_cast(atoi(row[71])) : 100; - e.formula3 = row[72] ? static_cast(atoi(row[72])) : 100; - e.formula4 = row[73] ? static_cast(atoi(row[73])) : 100; - e.formula5 = row[74] ? static_cast(atoi(row[74])) : 100; - e.formula6 = row[75] ? static_cast(atoi(row[75])) : 100; - e.formula7 = row[76] ? static_cast(atoi(row[76])) : 100; - e.formula8 = row[77] ? static_cast(atoi(row[77])) : 100; - e.formula9 = row[78] ? static_cast(atoi(row[78])) : 100; - e.formula10 = row[79] ? static_cast(atoi(row[79])) : 100; - e.formula11 = row[80] ? static_cast(atoi(row[80])) : 100; - e.formula12 = row[81] ? static_cast(atoi(row[81])) : 100; - e.LightType = row[82] ? static_cast(atoi(row[82])) : 0; - e.goodEffect = row[83] ? static_cast(atoi(row[83])) : 0; - e.Activated = row[84] ? static_cast(atoi(row[84])) : 0; - e.resisttype = row[85] ? static_cast(atoi(row[85])) : 0; - e.effectid1 = row[86] ? static_cast(atoi(row[86])) : 254; - e.effectid2 = row[87] ? static_cast(atoi(row[87])) : 254; - e.effectid3 = row[88] ? static_cast(atoi(row[88])) : 254; - e.effectid4 = row[89] ? static_cast(atoi(row[89])) : 254; - e.effectid5 = row[90] ? static_cast(atoi(row[90])) : 254; - e.effectid6 = row[91] ? static_cast(atoi(row[91])) : 254; - e.effectid7 = row[92] ? static_cast(atoi(row[92])) : 254; - e.effectid8 = row[93] ? static_cast(atoi(row[93])) : 254; - e.effectid9 = row[94] ? static_cast(atoi(row[94])) : 254; - e.effectid10 = row[95] ? static_cast(atoi(row[95])) : 254; - e.effectid11 = row[96] ? static_cast(atoi(row[96])) : 254; - e.effectid12 = row[97] ? static_cast(atoi(row[97])) : 254; - e.targettype = row[98] ? static_cast(atoi(row[98])) : 2; - e.basediff = row[99] ? static_cast(atoi(row[99])) : 0; - e.skill = row[100] ? static_cast(atoi(row[100])) : 98; - e.zonetype = row[101] ? static_cast(atoi(row[101])) : -1; - e.EnvironmentType = row[102] ? static_cast(atoi(row[102])) : 0; - e.TimeOfDay = row[103] ? static_cast(atoi(row[103])) : 0; - e.classes1 = row[104] ? static_cast(atoi(row[104])) : 255; - e.classes2 = row[105] ? static_cast(atoi(row[105])) : 255; - e.classes3 = row[106] ? static_cast(atoi(row[106])) : 255; - e.classes4 = row[107] ? static_cast(atoi(row[107])) : 255; - e.classes5 = row[108] ? static_cast(atoi(row[108])) : 255; - e.classes6 = row[109] ? static_cast(atoi(row[109])) : 255; - e.classes7 = row[110] ? static_cast(atoi(row[110])) : 255; - e.classes8 = row[111] ? static_cast(atoi(row[111])) : 255; - e.classes9 = row[112] ? static_cast(atoi(row[112])) : 255; - e.classes10 = row[113] ? static_cast(atoi(row[113])) : 255; - e.classes11 = row[114] ? static_cast(atoi(row[114])) : 255; - e.classes12 = row[115] ? static_cast(atoi(row[115])) : 255; - e.classes13 = row[116] ? static_cast(atoi(row[116])) : 255; - e.classes14 = row[117] ? static_cast(atoi(row[117])) : 255; - e.classes15 = row[118] ? static_cast(atoi(row[118])) : 255; - e.classes16 = row[119] ? static_cast(atoi(row[119])) : 255; - e.CastingAnim = row[120] ? static_cast(atoi(row[120])) : 44; - e.TargetAnim = row[121] ? static_cast(atoi(row[121])) : 13; - e.TravelType = row[122] ? static_cast(atoi(row[122])) : 0; - e.SpellAffectIndex = row[123] ? static_cast(atoi(row[123])) : -1; - e.disallow_sit = row[124] ? static_cast(atoi(row[124])) : 0; - e.deities0 = row[125] ? static_cast(atoi(row[125])) : 0; - e.deities1 = row[126] ? static_cast(atoi(row[126])) : 0; - e.deities2 = row[127] ? static_cast(atoi(row[127])) : 0; - e.deities3 = row[128] ? static_cast(atoi(row[128])) : 0; - e.deities4 = row[129] ? static_cast(atoi(row[129])) : 0; - e.deities5 = row[130] ? static_cast(atoi(row[130])) : 0; - e.deities6 = row[131] ? static_cast(atoi(row[131])) : 0; - e.deities7 = row[132] ? static_cast(atoi(row[132])) : 0; - e.deities8 = row[133] ? static_cast(atoi(row[133])) : 0; - e.deities9 = row[134] ? static_cast(atoi(row[134])) : 0; - e.deities10 = row[135] ? static_cast(atoi(row[135])) : 0; - e.deities11 = row[136] ? static_cast(atoi(row[136])) : 0; - e.deities12 = row[137] ? static_cast(atoi(row[137])) : 0; - e.deities13 = row[138] ? static_cast(atoi(row[138])) : 0; - e.deities14 = row[139] ? static_cast(atoi(row[139])) : 0; - e.deities15 = row[140] ? static_cast(atoi(row[140])) : 0; - e.deities16 = row[141] ? static_cast(atoi(row[141])) : 0; - e.field142 = row[142] ? static_cast(atoi(row[142])) : 100; - e.field143 = row[143] ? static_cast(atoi(row[143])) : 0; - e.new_icon = row[144] ? static_cast(atoi(row[144])) : 161; - e.spellanim = row[145] ? static_cast(atoi(row[145])) : 0; - e.uninterruptable = row[146] ? static_cast(atoi(row[146])) : 0; - e.ResistDiff = row[147] ? static_cast(atoi(row[147])) : -150; - e.dot_stacking_exempt = row[148] ? static_cast(atoi(row[148])) : 0; - e.deleteable = row[149] ? static_cast(atoi(row[149])) : 0; - e.RecourseLink = row[150] ? static_cast(atoi(row[150])) : 0; - e.no_partial_resist = row[151] ? static_cast(atoi(row[151])) : 0; - e.field152 = row[152] ? static_cast(atoi(row[152])) : 0; - e.field153 = row[153] ? static_cast(atoi(row[153])) : 0; - e.short_buff_box = row[154] ? static_cast(atoi(row[154])) : -1; - e.descnum = row[155] ? static_cast(atoi(row[155])) : 0; - e.typedescnum = row[156] ? static_cast(atoi(row[156])) : 0; - e.effectdescnum = row[157] ? static_cast(atoi(row[157])) : 0; - e.effectdescnum2 = row[158] ? static_cast(atoi(row[158])) : 0; - e.npc_no_los = row[159] ? static_cast(atoi(row[159])) : 0; - e.feedbackable = row[160] ? static_cast(atoi(row[160])) : 0; - e.reflectable = row[161] ? static_cast(atoi(row[161])) : 0; - e.bonushate = row[162] ? static_cast(atoi(row[162])) : 0; - e.field163 = row[163] ? static_cast(atoi(row[163])) : 100; - e.field164 = row[164] ? static_cast(atoi(row[164])) : -150; - e.ldon_trap = row[165] ? static_cast(atoi(row[165])) : 0; - e.EndurCost = row[166] ? static_cast(atoi(row[166])) : 0; - e.EndurTimerIndex = row[167] ? static_cast(atoi(row[167])) : 0; - e.IsDiscipline = row[168] ? static_cast(atoi(row[168])) : 0; - e.field169 = row[169] ? static_cast(atoi(row[169])) : 0; - e.field170 = row[170] ? static_cast(atoi(row[170])) : 0; - e.field171 = row[171] ? static_cast(atoi(row[171])) : 0; - e.field172 = row[172] ? static_cast(atoi(row[172])) : 0; - e.HateAdded = row[173] ? static_cast(atoi(row[173])) : 0; - e.EndurUpkeep = row[174] ? static_cast(atoi(row[174])) : 0; - e.numhitstype = row[175] ? static_cast(atoi(row[175])) : 0; - e.numhits = row[176] ? static_cast(atoi(row[176])) : 0; - e.pvpresistbase = row[177] ? static_cast(atoi(row[177])) : -150; - e.pvpresistcalc = row[178] ? static_cast(atoi(row[178])) : 100; - e.pvpresistcap = row[179] ? static_cast(atoi(row[179])) : -150; - e.spell_category = row[180] ? static_cast(atoi(row[180])) : -99; - e.pvp_duration = row[181] ? static_cast(atoi(row[181])) : 0; - e.pvp_duration_cap = row[182] ? static_cast(atoi(row[182])) : 0; - e.pcnpc_only_flag = row[183] ? static_cast(atoi(row[183])) : 0; - e.cast_not_standing = row[184] ? static_cast(atoi(row[184])) : 0; - e.can_mgb = row[185] ? static_cast(atoi(row[185])) : 0; - e.nodispell = row[186] ? static_cast(atoi(row[186])) : -1; - e.npc_category = row[187] ? static_cast(atoi(row[187])) : 0; - e.npc_usefulness = row[188] ? static_cast(atoi(row[188])) : 0; - e.MinResist = row[189] ? static_cast(atoi(row[189])) : 0; - e.MaxResist = row[190] ? static_cast(atoi(row[190])) : 0; - e.viral_targets = row[191] ? static_cast(atoi(row[191])) : 0; - e.viral_timer = row[192] ? static_cast(atoi(row[192])) : 0; - e.nimbuseffect = row[193] ? static_cast(atoi(row[193])) : 0; - e.ConeStartAngle = row[194] ? static_cast(atoi(row[194])) : 0; - e.ConeStopAngle = row[195] ? static_cast(atoi(row[195])) : 0; - e.sneaking = row[196] ? static_cast(atoi(row[196])) : 0; - e.not_extendable = row[197] ? static_cast(atoi(row[197])) : 0; - e.no_detrimental_spell_aggro = row[198] ? static_cast(atoi(row[198])) : 0; - e.field199 = row[199] ? static_cast(atoi(row[199])) : 1; - e.suspendable = row[200] ? static_cast(atoi(row[200])) : 0; - e.viral_range = row[201] ? static_cast(atoi(row[201])) : 0; - e.songcap = row[202] ? static_cast(atoi(row[202])) : 0; - e.field203 = row[203] ? static_cast(atoi(row[203])) : 0; - e.field204 = row[204] ? static_cast(atoi(row[204])) : 0; - e.no_block = row[205] ? static_cast(atoi(row[205])) : 0; - e.field206 = row[206] ? static_cast(atoi(row[206])) : -1; - e.spellgroup = row[207] ? static_cast(atoi(row[207])) : 0; - e.rank_ = row[208] ? static_cast(atoi(row[208])) : 0; - e.no_resist = row[209] ? static_cast(atoi(row[209])) : 0; - e.field210 = row[210] ? static_cast(atoi(row[210])) : 1; - e.CastRestriction = row[211] ? static_cast(atoi(row[211])) : 0; - e.allowrest = row[212] ? static_cast(atoi(row[212])) : 0; - e.InCombat = row[213] ? static_cast(atoi(row[213])) : 0; - e.OutofCombat = row[214] ? static_cast(atoi(row[214])) : 0; - e.field215 = row[215] ? static_cast(atoi(row[215])) : 0; - e.field216 = row[216] ? static_cast(atoi(row[216])) : 0; - e.override_crit_chance = row[217] ? static_cast(atoi(row[217])) : 0; - e.aemaxtargets = row[218] ? static_cast(atoi(row[218])) : 0; - e.maxtargets = row[219] ? static_cast(atoi(row[219])) : 0; - e.no_heal_damage_item_mod = row[220] ? static_cast(atoi(row[220])) : 0; - e.caster_requirement_id = row[221] ? static_cast(atoi(row[221])) : 0; - e.spell_class = row[222] ? static_cast(atoi(row[222])) : 0; - e.spell_subclass = row[223] ? static_cast(atoi(row[223])) : 0; - e.persistdeath = row[224] ? static_cast(atoi(row[224])) : 0; - e.field225 = row[225] ? static_cast(atoi(row[225])) : 0; - e.field226 = row[226] ? static_cast(atoi(row[226])) : 0; - e.min_dist = row[227] ? strtof(row[227], nullptr) : 0; - e.min_dist_mod = row[228] ? strtof(row[228], nullptr) : 0; - e.max_dist = row[229] ? strtof(row[229], nullptr) : 0; - e.max_dist_mod = row[230] ? strtof(row[230], nullptr) : 0; - e.min_range = row[231] ? static_cast(atoi(row[231])) : 0; - e.no_remove = row[232] ? static_cast(atoi(row[232])) : 0; - e.field233 = row[233] ? static_cast(atoi(row[233])) : 0; - e.field234 = row[234] ? static_cast(atoi(row[234])) : 0; - e.field235 = row[235] ? static_cast(atoi(row[235])) : 0; - e.field236 = row[236] ? static_cast(atoi(row[236])) : 0; + e.id = row[0] ? static_cast(atoi(row[0])) : 0; + e.name = row[1] ? row[1] : ""; + e.player_1 = row[2] ? row[2] : "BLUE_TRAIL"; + e.teleport_zone = row[3] ? row[3] : ""; + e.you_cast = row[4] ? row[4] : ""; + e.other_casts = row[5] ? row[5] : ""; + e.cast_on_you = row[6] ? row[6] : ""; + e.cast_on_other = row[7] ? row[7] : ""; + e.spell_fades = row[8] ? row[8] : ""; + e.range_ = row[9] ? static_cast(atoi(row[9])) : 100; + e.aoerange = row[10] ? static_cast(atoi(row[10])) : 0; + e.pushback = row[11] ? static_cast(atoi(row[11])) : 0; + e.pushup = row[12] ? static_cast(atoi(row[12])) : 0; + e.cast_time = row[13] ? static_cast(atoi(row[13])) : 0; + e.recovery_time = row[14] ? static_cast(atoi(row[14])) : 0; + e.recast_time = row[15] ? static_cast(atoi(row[15])) : 0; + e.buffdurationformula = row[16] ? static_cast(atoi(row[16])) : 7; + e.buffduration = row[17] ? static_cast(atoi(row[17])) : 65; + e.AEDuration = row[18] ? static_cast(atoi(row[18])) : 0; + e.mana = row[19] ? static_cast(atoi(row[19])) : 0; + e.effect_base_value1 = row[20] ? static_cast(atoi(row[20])) : 100; + e.effect_base_value2 = row[21] ? static_cast(atoi(row[21])) : 0; + e.effect_base_value3 = row[22] ? static_cast(atoi(row[22])) : 0; + e.effect_base_value4 = row[23] ? static_cast(atoi(row[23])) : 0; + e.effect_base_value5 = row[24] ? static_cast(atoi(row[24])) : 0; + e.effect_base_value6 = row[25] ? static_cast(atoi(row[25])) : 0; + e.effect_base_value7 = row[26] ? static_cast(atoi(row[26])) : 0; + e.effect_base_value8 = row[27] ? static_cast(atoi(row[27])) : 0; + e.effect_base_value9 = row[28] ? static_cast(atoi(row[28])) : 0; + e.effect_base_value10 = row[29] ? static_cast(atoi(row[29])) : 0; + e.effect_base_value11 = row[30] ? static_cast(atoi(row[30])) : 0; + e.effect_base_value12 = row[31] ? static_cast(atoi(row[31])) : 0; + e.effect_limit_value1 = row[32] ? static_cast(atoi(row[32])) : 0; + e.effect_limit_value2 = row[33] ? static_cast(atoi(row[33])) : 0; + e.effect_limit_value3 = row[34] ? static_cast(atoi(row[34])) : 0; + e.effect_limit_value4 = row[35] ? static_cast(atoi(row[35])) : 0; + e.effect_limit_value5 = row[36] ? static_cast(atoi(row[36])) : 0; + e.effect_limit_value6 = row[37] ? static_cast(atoi(row[37])) : 0; + e.effect_limit_value7 = row[38] ? static_cast(atoi(row[38])) : 0; + e.effect_limit_value8 = row[39] ? static_cast(atoi(row[39])) : 0; + e.effect_limit_value9 = row[40] ? static_cast(atoi(row[40])) : 0; + e.effect_limit_value10 = row[41] ? static_cast(atoi(row[41])) : 0; + e.effect_limit_value11 = row[42] ? static_cast(atoi(row[42])) : 0; + e.effect_limit_value12 = row[43] ? static_cast(atoi(row[43])) : 0; + e.max1 = row[44] ? static_cast(atoi(row[44])) : 0; + e.max2 = row[45] ? static_cast(atoi(row[45])) : 0; + e.max3 = row[46] ? static_cast(atoi(row[46])) : 0; + e.max4 = row[47] ? static_cast(atoi(row[47])) : 0; + e.max5 = row[48] ? static_cast(atoi(row[48])) : 0; + e.max6 = row[49] ? static_cast(atoi(row[49])) : 0; + e.max7 = row[50] ? static_cast(atoi(row[50])) : 0; + e.max8 = row[51] ? static_cast(atoi(row[51])) : 0; + e.max9 = row[52] ? static_cast(atoi(row[52])) : 0; + e.max10 = row[53] ? static_cast(atoi(row[53])) : 0; + e.max11 = row[54] ? static_cast(atoi(row[54])) : 0; + e.max12 = row[55] ? static_cast(atoi(row[55])) : 0; + e.icon = row[56] ? static_cast(atoi(row[56])) : 0; + e.memicon = row[57] ? static_cast(atoi(row[57])) : 0; + e.components1 = row[58] ? static_cast(atoi(row[58])) : -1; + e.components2 = row[59] ? static_cast(atoi(row[59])) : -1; + e.components3 = row[60] ? static_cast(atoi(row[60])) : -1; + e.components4 = row[61] ? static_cast(atoi(row[61])) : -1; + e.component_counts1 = row[62] ? static_cast(atoi(row[62])) : 1; + e.component_counts2 = row[63] ? static_cast(atoi(row[63])) : 1; + e.component_counts3 = row[64] ? static_cast(atoi(row[64])) : 1; + e.component_counts4 = row[65] ? static_cast(atoi(row[65])) : 1; + e.NoexpendReagent1 = row[66] ? static_cast(atoi(row[66])) : -1; + e.NoexpendReagent2 = row[67] ? static_cast(atoi(row[67])) : -1; + e.NoexpendReagent3 = row[68] ? static_cast(atoi(row[68])) : -1; + e.NoexpendReagent4 = row[69] ? static_cast(atoi(row[69])) : -1; + e.formula1 = row[70] ? static_cast(atoi(row[70])) : 100; + e.formula2 = row[71] ? static_cast(atoi(row[71])) : 100; + e.formula3 = row[72] ? static_cast(atoi(row[72])) : 100; + e.formula4 = row[73] ? static_cast(atoi(row[73])) : 100; + e.formula5 = row[74] ? static_cast(atoi(row[74])) : 100; + e.formula6 = row[75] ? static_cast(atoi(row[75])) : 100; + e.formula7 = row[76] ? static_cast(atoi(row[76])) : 100; + e.formula8 = row[77] ? static_cast(atoi(row[77])) : 100; + e.formula9 = row[78] ? static_cast(atoi(row[78])) : 100; + e.formula10 = row[79] ? static_cast(atoi(row[79])) : 100; + e.formula11 = row[80] ? static_cast(atoi(row[80])) : 100; + e.formula12 = row[81] ? static_cast(atoi(row[81])) : 100; + e.LightType = row[82] ? static_cast(atoi(row[82])) : 0; + e.goodEffect = row[83] ? static_cast(atoi(row[83])) : 0; + e.Activated = row[84] ? static_cast(atoi(row[84])) : 0; + e.resisttype = row[85] ? static_cast(atoi(row[85])) : 0; + e.effectid1 = row[86] ? static_cast(atoi(row[86])) : 254; + e.effectid2 = row[87] ? static_cast(atoi(row[87])) : 254; + e.effectid3 = row[88] ? static_cast(atoi(row[88])) : 254; + e.effectid4 = row[89] ? static_cast(atoi(row[89])) : 254; + e.effectid5 = row[90] ? static_cast(atoi(row[90])) : 254; + e.effectid6 = row[91] ? static_cast(atoi(row[91])) : 254; + e.effectid7 = row[92] ? static_cast(atoi(row[92])) : 254; + e.effectid8 = row[93] ? static_cast(atoi(row[93])) : 254; + e.effectid9 = row[94] ? static_cast(atoi(row[94])) : 254; + e.effectid10 = row[95] ? static_cast(atoi(row[95])) : 254; + e.effectid11 = row[96] ? static_cast(atoi(row[96])) : 254; + e.effectid12 = row[97] ? static_cast(atoi(row[97])) : 254; + e.targettype = row[98] ? static_cast(atoi(row[98])) : 2; + e.basediff = row[99] ? static_cast(atoi(row[99])) : 0; + e.skill = row[100] ? static_cast(atoi(row[100])) : 98; + e.zonetype = row[101] ? static_cast(atoi(row[101])) : -1; + e.EnvironmentType = row[102] ? static_cast(atoi(row[102])) : 0; + e.TimeOfDay = row[103] ? static_cast(atoi(row[103])) : 0; + e.classes1 = row[104] ? static_cast(atoi(row[104])) : 255; + e.classes2 = row[105] ? static_cast(atoi(row[105])) : 255; + e.classes3 = row[106] ? static_cast(atoi(row[106])) : 255; + e.classes4 = row[107] ? static_cast(atoi(row[107])) : 255; + e.classes5 = row[108] ? static_cast(atoi(row[108])) : 255; + e.classes6 = row[109] ? static_cast(atoi(row[109])) : 255; + e.classes7 = row[110] ? static_cast(atoi(row[110])) : 255; + e.classes8 = row[111] ? static_cast(atoi(row[111])) : 255; + e.classes9 = row[112] ? static_cast(atoi(row[112])) : 255; + e.classes10 = row[113] ? static_cast(atoi(row[113])) : 255; + e.classes11 = row[114] ? static_cast(atoi(row[114])) : 255; + e.classes12 = row[115] ? static_cast(atoi(row[115])) : 255; + e.classes13 = row[116] ? static_cast(atoi(row[116])) : 255; + e.classes14 = row[117] ? static_cast(atoi(row[117])) : 255; + e.classes15 = row[118] ? static_cast(atoi(row[118])) : 255; + e.classes16 = row[119] ? static_cast(atoi(row[119])) : 255; + e.CastingAnim = row[120] ? static_cast(atoi(row[120])) : 44; + e.TargetAnim = row[121] ? static_cast(atoi(row[121])) : 13; + e.TravelType = row[122] ? static_cast(atoi(row[122])) : 0; + e.SpellAffectIndex = row[123] ? static_cast(atoi(row[123])) : -1; + e.disallow_sit = row[124] ? static_cast(atoi(row[124])) : 0; + e.deities0 = row[125] ? static_cast(atoi(row[125])) : 0; + e.deities1 = row[126] ? static_cast(atoi(row[126])) : 0; + e.deities2 = row[127] ? static_cast(atoi(row[127])) : 0; + e.deities3 = row[128] ? static_cast(atoi(row[128])) : 0; + e.deities4 = row[129] ? static_cast(atoi(row[129])) : 0; + e.deities5 = row[130] ? static_cast(atoi(row[130])) : 0; + e.deities6 = row[131] ? static_cast(atoi(row[131])) : 0; + e.deities7 = row[132] ? static_cast(atoi(row[132])) : 0; + e.deities8 = row[133] ? static_cast(atoi(row[133])) : 0; + e.deities9 = row[134] ? static_cast(atoi(row[134])) : 0; + e.deities10 = row[135] ? static_cast(atoi(row[135])) : 0; + e.deities11 = row[136] ? static_cast(atoi(row[136])) : 0; + e.deities12 = row[137] ? static_cast(atoi(row[137])) : 0; + e.deities13 = row[138] ? static_cast(atoi(row[138])) : 0; + e.deities14 = row[139] ? static_cast(atoi(row[139])) : 0; + e.deities15 = row[140] ? static_cast(atoi(row[140])) : 0; + e.deities16 = row[141] ? static_cast(atoi(row[141])) : 0; + e.field142 = row[142] ? static_cast(atoi(row[142])) : 100; + e.field143 = row[143] ? static_cast(atoi(row[143])) : 0; + e.new_icon = row[144] ? static_cast(atoi(row[144])) : 161; + e.spellanim = row[145] ? static_cast(atoi(row[145])) : 0; + e.uninterruptable = row[146] ? static_cast(atoi(row[146])) : 0; + e.ResistDiff = row[147] ? static_cast(atoi(row[147])) : -150; + e.dot_stacking_exempt = row[148] ? static_cast(atoi(row[148])) : 0; + e.deleteable = row[149] ? static_cast(atoi(row[149])) : 0; + e.RecourseLink = row[150] ? static_cast(atoi(row[150])) : 0; + e.no_partial_resist = row[151] ? static_cast(atoi(row[151])) : 0; + e.field152 = row[152] ? static_cast(atoi(row[152])) : 0; + e.field153 = row[153] ? static_cast(atoi(row[153])) : 0; + e.short_buff_box = row[154] ? static_cast(atoi(row[154])) : -1; + e.descnum = row[155] ? static_cast(atoi(row[155])) : 0; + e.typedescnum = row[156] ? static_cast(atoi(row[156])) : 0; + e.effectdescnum = row[157] ? static_cast(atoi(row[157])) : 0; + e.effectdescnum2 = row[158] ? static_cast(atoi(row[158])) : 0; + e.npc_no_los = row[159] ? static_cast(atoi(row[159])) : 0; + e.field160 = row[160] ? static_cast(atoi(row[160])) : 0; + e.reflectable = row[161] ? static_cast(atoi(row[161])) : 0; + e.bonushate = row[162] ? static_cast(atoi(row[162])) : 0; + e.field163 = row[163] ? static_cast(atoi(row[163])) : 100; + e.field164 = row[164] ? static_cast(atoi(row[164])) : -150; + e.ldon_trap = row[165] ? static_cast(atoi(row[165])) : 0; + e.EndurCost = row[166] ? static_cast(atoi(row[166])) : 0; + e.EndurTimerIndex = row[167] ? static_cast(atoi(row[167])) : 0; + e.IsDiscipline = row[168] ? static_cast(atoi(row[168])) : 0; + e.field169 = row[169] ? static_cast(atoi(row[169])) : 0; + e.field170 = row[170] ? static_cast(atoi(row[170])) : 0; + e.field171 = row[171] ? static_cast(atoi(row[171])) : 0; + e.field172 = row[172] ? static_cast(atoi(row[172])) : 0; + e.HateAdded = row[173] ? static_cast(atoi(row[173])) : 0; + e.EndurUpkeep = row[174] ? static_cast(atoi(row[174])) : 0; + e.numhitstype = row[175] ? static_cast(atoi(row[175])) : 0; + e.numhits = row[176] ? static_cast(atoi(row[176])) : 0; + e.pvpresistbase = row[177] ? static_cast(atoi(row[177])) : -150; + e.pvpresistcalc = row[178] ? static_cast(atoi(row[178])) : 100; + e.pvpresistcap = row[179] ? static_cast(atoi(row[179])) : -150; + e.spell_category = row[180] ? static_cast(atoi(row[180])) : -99; + e.pvp_duration = row[181] ? static_cast(atoi(row[181])) : 0; + e.pvp_duration_cap = row[182] ? static_cast(atoi(row[182])) : 0; + e.pcnpc_only_flag = row[183] ? static_cast(atoi(row[183])) : 0; + e.cast_not_standing = row[184] ? static_cast(atoi(row[184])) : 0; + e.can_mgb = row[185] ? static_cast(atoi(row[185])) : 0; + e.nodispell = row[186] ? static_cast(atoi(row[186])) : -1; + e.npc_category = row[187] ? static_cast(atoi(row[187])) : 0; + e.npc_usefulness = row[188] ? static_cast(atoi(row[188])) : 0; + e.MinResist = row[189] ? static_cast(atoi(row[189])) : 0; + e.MaxResist = row[190] ? static_cast(atoi(row[190])) : 0; + e.viral_targets = row[191] ? static_cast(atoi(row[191])) : 0; + e.viral_timer = row[192] ? static_cast(atoi(row[192])) : 0; + e.nimbuseffect = row[193] ? static_cast(atoi(row[193])) : 0; + e.ConeStartAngle = row[194] ? static_cast(atoi(row[194])) : 0; + e.ConeStopAngle = row[195] ? static_cast(atoi(row[195])) : 0; + e.sneaking = row[196] ? static_cast(atoi(row[196])) : 0; + e.not_extendable = row[197] ? static_cast(atoi(row[197])) : 0; + e.field198 = row[198] ? static_cast(atoi(row[198])) : 0; + e.field199 = row[199] ? static_cast(atoi(row[199])) : 1; + e.suspendable = row[200] ? static_cast(atoi(row[200])) : 0; + e.viral_range = row[201] ? static_cast(atoi(row[201])) : 0; + e.songcap = row[202] ? static_cast(atoi(row[202])) : 0; + e.field203 = row[203] ? static_cast(atoi(row[203])) : 0; + e.field204 = row[204] ? static_cast(atoi(row[204])) : 0; + e.no_block = row[205] ? static_cast(atoi(row[205])) : 0; + e.field206 = row[206] ? static_cast(atoi(row[206])) : -1; + e.spellgroup = row[207] ? static_cast(atoi(row[207])) : 0; + e.rank_ = row[208] ? static_cast(atoi(row[208])) : 0; + e.field209 = row[209] ? static_cast(atoi(row[209])) : 0; + e.field210 = row[210] ? static_cast(atoi(row[210])) : 1; + e.CastRestriction = row[211] ? static_cast(atoi(row[211])) : 0; + e.allowrest = row[212] ? static_cast(atoi(row[212])) : 0; + e.InCombat = row[213] ? static_cast(atoi(row[213])) : 0; + e.OutofCombat = row[214] ? static_cast(atoi(row[214])) : 0; + e.field215 = row[215] ? static_cast(atoi(row[215])) : 0; + e.field216 = row[216] ? static_cast(atoi(row[216])) : 0; + e.field217 = row[217] ? static_cast(atoi(row[217])) : 0; + e.aemaxtargets = row[218] ? static_cast(atoi(row[218])) : 0; + e.maxtargets = row[219] ? static_cast(atoi(row[219])) : 0; + e.field220 = row[220] ? static_cast(atoi(row[220])) : 0; + e.field221 = row[221] ? static_cast(atoi(row[221])) : 0; + e.field222 = row[222] ? static_cast(atoi(row[222])) : 0; + e.field223 = row[223] ? static_cast(atoi(row[223])) : 0; + e.persistdeath = row[224] ? static_cast(atoi(row[224])) : 0; + e.field225 = row[225] ? static_cast(atoi(row[225])) : 0; + e.field226 = row[226] ? static_cast(atoi(row[226])) : 0; + e.min_dist = row[227] ? strtof(row[227], nullptr) : 0; + e.min_dist_mod = row[228] ? strtof(row[228], nullptr) : 0; + e.max_dist = row[229] ? strtof(row[229], nullptr) : 0; + e.max_dist_mod = row[230] ? strtof(row[230], nullptr) : 0; + e.min_range = row[231] ? static_cast(atoi(row[231])) : 0; + e.field232 = row[232] ? static_cast(atoi(row[232])) : 0; + e.field233 = row[233] ? static_cast(atoi(row[233])) : 0; + e.field234 = row[234] ? static_cast(atoi(row[234])) : 0; + e.field235 = row[235] ? static_cast(atoi(row[235])) : 0; + e.field236 = row[236] ? static_cast(atoi(row[236])) : 0; return e; } @@ -1489,7 +1489,7 @@ class BaseSpellsNewRepository { v.push_back(columns[157] + " = " + std::to_string(e.effectdescnum)); v.push_back(columns[158] + " = " + std::to_string(e.effectdescnum2)); v.push_back(columns[159] + " = " + std::to_string(e.npc_no_los)); - v.push_back(columns[160] + " = " + std::to_string(e.feedbackable)); + v.push_back(columns[160] + " = " + std::to_string(e.field160)); v.push_back(columns[161] + " = " + std::to_string(e.reflectable)); v.push_back(columns[162] + " = " + std::to_string(e.bonushate)); v.push_back(columns[163] + " = " + std::to_string(e.field163)); @@ -1527,7 +1527,7 @@ class BaseSpellsNewRepository { v.push_back(columns[195] + " = " + std::to_string(e.ConeStopAngle)); v.push_back(columns[196] + " = " + std::to_string(e.sneaking)); v.push_back(columns[197] + " = " + std::to_string(e.not_extendable)); - v.push_back(columns[198] + " = " + std::to_string(e.no_detrimental_spell_aggro)); + v.push_back(columns[198] + " = " + std::to_string(e.field198)); v.push_back(columns[199] + " = " + std::to_string(e.field199)); v.push_back(columns[200] + " = " + std::to_string(e.suspendable)); v.push_back(columns[201] + " = " + std::to_string(e.viral_range)); @@ -1538,7 +1538,7 @@ class BaseSpellsNewRepository { v.push_back(columns[206] + " = " + std::to_string(e.field206)); v.push_back(columns[207] + " = " + std::to_string(e.spellgroup)); v.push_back(columns[208] + " = " + std::to_string(e.rank_)); - v.push_back(columns[209] + " = " + std::to_string(e.no_resist)); + v.push_back(columns[209] + " = " + std::to_string(e.field209)); v.push_back(columns[210] + " = " + std::to_string(e.field210)); v.push_back(columns[211] + " = " + std::to_string(e.CastRestriction)); v.push_back(columns[212] + " = " + std::to_string(e.allowrest)); @@ -1546,13 +1546,13 @@ class BaseSpellsNewRepository { v.push_back(columns[214] + " = " + std::to_string(e.OutofCombat)); v.push_back(columns[215] + " = " + std::to_string(e.field215)); v.push_back(columns[216] + " = " + std::to_string(e.field216)); - v.push_back(columns[217] + " = " + std::to_string(e.override_crit_chance)); + v.push_back(columns[217] + " = " + std::to_string(e.field217)); v.push_back(columns[218] + " = " + std::to_string(e.aemaxtargets)); v.push_back(columns[219] + " = " + std::to_string(e.maxtargets)); - v.push_back(columns[220] + " = " + std::to_string(e.no_heal_damage_item_mod)); - v.push_back(columns[221] + " = " + std::to_string(e.caster_requirement_id)); - v.push_back(columns[222] + " = " + std::to_string(e.spell_class)); - v.push_back(columns[223] + " = " + std::to_string(e.spell_subclass)); + v.push_back(columns[220] + " = " + std::to_string(e.field220)); + v.push_back(columns[221] + " = " + std::to_string(e.field221)); + v.push_back(columns[222] + " = " + std::to_string(e.field222)); + v.push_back(columns[223] + " = " + std::to_string(e.field223)); v.push_back(columns[224] + " = " + std::to_string(e.persistdeath)); v.push_back(columns[225] + " = " + std::to_string(e.field225)); v.push_back(columns[226] + " = " + std::to_string(e.field226)); @@ -1561,7 +1561,7 @@ class BaseSpellsNewRepository { v.push_back(columns[229] + " = " + std::to_string(e.max_dist)); v.push_back(columns[230] + " = " + std::to_string(e.max_dist_mod)); v.push_back(columns[231] + " = " + std::to_string(e.min_range)); - v.push_back(columns[232] + " = " + std::to_string(e.no_remove)); + v.push_back(columns[232] + " = " + std::to_string(e.field232)); v.push_back(columns[233] + " = " + std::to_string(e.field233)); v.push_back(columns[234] + " = " + std::to_string(e.field234)); v.push_back(columns[235] + " = " + std::to_string(e.field235)); @@ -1747,7 +1747,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.effectdescnum)); v.push_back(std::to_string(e.effectdescnum2)); v.push_back(std::to_string(e.npc_no_los)); - v.push_back(std::to_string(e.feedbackable)); + v.push_back(std::to_string(e.field160)); v.push_back(std::to_string(e.reflectable)); v.push_back(std::to_string(e.bonushate)); v.push_back(std::to_string(e.field163)); @@ -1785,7 +1785,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.ConeStopAngle)); v.push_back(std::to_string(e.sneaking)); v.push_back(std::to_string(e.not_extendable)); - v.push_back(std::to_string(e.no_detrimental_spell_aggro)); + v.push_back(std::to_string(e.field198)); v.push_back(std::to_string(e.field199)); v.push_back(std::to_string(e.suspendable)); v.push_back(std::to_string(e.viral_range)); @@ -1796,7 +1796,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.field206)); v.push_back(std::to_string(e.spellgroup)); v.push_back(std::to_string(e.rank_)); - v.push_back(std::to_string(e.no_resist)); + v.push_back(std::to_string(e.field209)); v.push_back(std::to_string(e.field210)); v.push_back(std::to_string(e.CastRestriction)); v.push_back(std::to_string(e.allowrest)); @@ -1804,13 +1804,13 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.OutofCombat)); v.push_back(std::to_string(e.field215)); v.push_back(std::to_string(e.field216)); - v.push_back(std::to_string(e.override_crit_chance)); + v.push_back(std::to_string(e.field217)); v.push_back(std::to_string(e.aemaxtargets)); v.push_back(std::to_string(e.maxtargets)); - v.push_back(std::to_string(e.no_heal_damage_item_mod)); - v.push_back(std::to_string(e.caster_requirement_id)); - v.push_back(std::to_string(e.spell_class)); - v.push_back(std::to_string(e.spell_subclass)); + v.push_back(std::to_string(e.field220)); + v.push_back(std::to_string(e.field221)); + v.push_back(std::to_string(e.field222)); + v.push_back(std::to_string(e.field223)); v.push_back(std::to_string(e.persistdeath)); v.push_back(std::to_string(e.field225)); v.push_back(std::to_string(e.field226)); @@ -1819,7 +1819,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.max_dist)); v.push_back(std::to_string(e.max_dist_mod)); v.push_back(std::to_string(e.min_range)); - v.push_back(std::to_string(e.no_remove)); + v.push_back(std::to_string(e.field232)); v.push_back(std::to_string(e.field233)); v.push_back(std::to_string(e.field234)); v.push_back(std::to_string(e.field235)); @@ -2013,7 +2013,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.effectdescnum)); v.push_back(std::to_string(e.effectdescnum2)); v.push_back(std::to_string(e.npc_no_los)); - v.push_back(std::to_string(e.feedbackable)); + v.push_back(std::to_string(e.field160)); v.push_back(std::to_string(e.reflectable)); v.push_back(std::to_string(e.bonushate)); v.push_back(std::to_string(e.field163)); @@ -2051,7 +2051,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.ConeStopAngle)); v.push_back(std::to_string(e.sneaking)); v.push_back(std::to_string(e.not_extendable)); - v.push_back(std::to_string(e.no_detrimental_spell_aggro)); + v.push_back(std::to_string(e.field198)); v.push_back(std::to_string(e.field199)); v.push_back(std::to_string(e.suspendable)); v.push_back(std::to_string(e.viral_range)); @@ -2062,7 +2062,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.field206)); v.push_back(std::to_string(e.spellgroup)); v.push_back(std::to_string(e.rank_)); - v.push_back(std::to_string(e.no_resist)); + v.push_back(std::to_string(e.field209)); v.push_back(std::to_string(e.field210)); v.push_back(std::to_string(e.CastRestriction)); v.push_back(std::to_string(e.allowrest)); @@ -2070,13 +2070,13 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.OutofCombat)); v.push_back(std::to_string(e.field215)); v.push_back(std::to_string(e.field216)); - v.push_back(std::to_string(e.override_crit_chance)); + v.push_back(std::to_string(e.field217)); v.push_back(std::to_string(e.aemaxtargets)); v.push_back(std::to_string(e.maxtargets)); - v.push_back(std::to_string(e.no_heal_damage_item_mod)); - v.push_back(std::to_string(e.caster_requirement_id)); - v.push_back(std::to_string(e.spell_class)); - v.push_back(std::to_string(e.spell_subclass)); + v.push_back(std::to_string(e.field220)); + v.push_back(std::to_string(e.field221)); + v.push_back(std::to_string(e.field222)); + v.push_back(std::to_string(e.field223)); v.push_back(std::to_string(e.persistdeath)); v.push_back(std::to_string(e.field225)); v.push_back(std::to_string(e.field226)); @@ -2085,7 +2085,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.max_dist)); v.push_back(std::to_string(e.max_dist_mod)); v.push_back(std::to_string(e.min_range)); - v.push_back(std::to_string(e.no_remove)); + v.push_back(std::to_string(e.field232)); v.push_back(std::to_string(e.field233)); v.push_back(std::to_string(e.field234)); v.push_back(std::to_string(e.field235)); @@ -2123,243 +2123,243 @@ class BaseSpellsNewRepository { for (auto row = results.begin(); row != results.end(); ++row) { SpellsNew e{}; - e.id = row[0] ? static_cast(atoi(row[0])) : 0; - e.name = row[1] ? row[1] : ""; - e.player_1 = row[2] ? row[2] : "BLUE_TRAIL"; - e.teleport_zone = row[3] ? row[3] : ""; - e.you_cast = row[4] ? row[4] : ""; - e.other_casts = row[5] ? row[5] : ""; - e.cast_on_you = row[6] ? row[6] : ""; - e.cast_on_other = row[7] ? row[7] : ""; - e.spell_fades = row[8] ? row[8] : ""; - e.range_ = row[9] ? static_cast(atoi(row[9])) : 100; - e.aoerange = row[10] ? static_cast(atoi(row[10])) : 0; - e.pushback = row[11] ? static_cast(atoi(row[11])) : 0; - e.pushup = row[12] ? static_cast(atoi(row[12])) : 0; - e.cast_time = row[13] ? static_cast(atoi(row[13])) : 0; - e.recovery_time = row[14] ? static_cast(atoi(row[14])) : 0; - e.recast_time = row[15] ? static_cast(atoi(row[15])) : 0; - e.buffdurationformula = row[16] ? static_cast(atoi(row[16])) : 7; - e.buffduration = row[17] ? static_cast(atoi(row[17])) : 65; - e.AEDuration = row[18] ? static_cast(atoi(row[18])) : 0; - e.mana = row[19] ? static_cast(atoi(row[19])) : 0; - e.effect_base_value1 = row[20] ? static_cast(atoi(row[20])) : 100; - e.effect_base_value2 = row[21] ? static_cast(atoi(row[21])) : 0; - e.effect_base_value3 = row[22] ? static_cast(atoi(row[22])) : 0; - e.effect_base_value4 = row[23] ? static_cast(atoi(row[23])) : 0; - e.effect_base_value5 = row[24] ? static_cast(atoi(row[24])) : 0; - e.effect_base_value6 = row[25] ? static_cast(atoi(row[25])) : 0; - e.effect_base_value7 = row[26] ? static_cast(atoi(row[26])) : 0; - e.effect_base_value8 = row[27] ? static_cast(atoi(row[27])) : 0; - e.effect_base_value9 = row[28] ? static_cast(atoi(row[28])) : 0; - e.effect_base_value10 = row[29] ? static_cast(atoi(row[29])) : 0; - e.effect_base_value11 = row[30] ? static_cast(atoi(row[30])) : 0; - e.effect_base_value12 = row[31] ? static_cast(atoi(row[31])) : 0; - e.effect_limit_value1 = row[32] ? static_cast(atoi(row[32])) : 0; - e.effect_limit_value2 = row[33] ? static_cast(atoi(row[33])) : 0; - e.effect_limit_value3 = row[34] ? static_cast(atoi(row[34])) : 0; - e.effect_limit_value4 = row[35] ? static_cast(atoi(row[35])) : 0; - e.effect_limit_value5 = row[36] ? static_cast(atoi(row[36])) : 0; - e.effect_limit_value6 = row[37] ? static_cast(atoi(row[37])) : 0; - e.effect_limit_value7 = row[38] ? static_cast(atoi(row[38])) : 0; - e.effect_limit_value8 = row[39] ? static_cast(atoi(row[39])) : 0; - e.effect_limit_value9 = row[40] ? static_cast(atoi(row[40])) : 0; - e.effect_limit_value10 = row[41] ? static_cast(atoi(row[41])) : 0; - e.effect_limit_value11 = row[42] ? static_cast(atoi(row[42])) : 0; - e.effect_limit_value12 = row[43] ? static_cast(atoi(row[43])) : 0; - e.max1 = row[44] ? static_cast(atoi(row[44])) : 0; - e.max2 = row[45] ? static_cast(atoi(row[45])) : 0; - e.max3 = row[46] ? static_cast(atoi(row[46])) : 0; - e.max4 = row[47] ? static_cast(atoi(row[47])) : 0; - e.max5 = row[48] ? static_cast(atoi(row[48])) : 0; - e.max6 = row[49] ? static_cast(atoi(row[49])) : 0; - e.max7 = row[50] ? static_cast(atoi(row[50])) : 0; - e.max8 = row[51] ? static_cast(atoi(row[51])) : 0; - e.max9 = row[52] ? static_cast(atoi(row[52])) : 0; - e.max10 = row[53] ? static_cast(atoi(row[53])) : 0; - e.max11 = row[54] ? static_cast(atoi(row[54])) : 0; - e.max12 = row[55] ? static_cast(atoi(row[55])) : 0; - e.icon = row[56] ? static_cast(atoi(row[56])) : 0; - e.memicon = row[57] ? static_cast(atoi(row[57])) : 0; - e.components1 = row[58] ? static_cast(atoi(row[58])) : -1; - e.components2 = row[59] ? static_cast(atoi(row[59])) : -1; - e.components3 = row[60] ? static_cast(atoi(row[60])) : -1; - e.components4 = row[61] ? static_cast(atoi(row[61])) : -1; - e.component_counts1 = row[62] ? static_cast(atoi(row[62])) : 1; - e.component_counts2 = row[63] ? static_cast(atoi(row[63])) : 1; - e.component_counts3 = row[64] ? static_cast(atoi(row[64])) : 1; - e.component_counts4 = row[65] ? static_cast(atoi(row[65])) : 1; - e.NoexpendReagent1 = row[66] ? static_cast(atoi(row[66])) : -1; - e.NoexpendReagent2 = row[67] ? static_cast(atoi(row[67])) : -1; - e.NoexpendReagent3 = row[68] ? static_cast(atoi(row[68])) : -1; - e.NoexpendReagent4 = row[69] ? static_cast(atoi(row[69])) : -1; - e.formula1 = row[70] ? static_cast(atoi(row[70])) : 100; - e.formula2 = row[71] ? static_cast(atoi(row[71])) : 100; - e.formula3 = row[72] ? static_cast(atoi(row[72])) : 100; - e.formula4 = row[73] ? static_cast(atoi(row[73])) : 100; - e.formula5 = row[74] ? static_cast(atoi(row[74])) : 100; - e.formula6 = row[75] ? static_cast(atoi(row[75])) : 100; - e.formula7 = row[76] ? static_cast(atoi(row[76])) : 100; - e.formula8 = row[77] ? static_cast(atoi(row[77])) : 100; - e.formula9 = row[78] ? static_cast(atoi(row[78])) : 100; - e.formula10 = row[79] ? static_cast(atoi(row[79])) : 100; - e.formula11 = row[80] ? static_cast(atoi(row[80])) : 100; - e.formula12 = row[81] ? static_cast(atoi(row[81])) : 100; - e.LightType = row[82] ? static_cast(atoi(row[82])) : 0; - e.goodEffect = row[83] ? static_cast(atoi(row[83])) : 0; - e.Activated = row[84] ? static_cast(atoi(row[84])) : 0; - e.resisttype = row[85] ? static_cast(atoi(row[85])) : 0; - e.effectid1 = row[86] ? static_cast(atoi(row[86])) : 254; - e.effectid2 = row[87] ? static_cast(atoi(row[87])) : 254; - e.effectid3 = row[88] ? static_cast(atoi(row[88])) : 254; - e.effectid4 = row[89] ? static_cast(atoi(row[89])) : 254; - e.effectid5 = row[90] ? static_cast(atoi(row[90])) : 254; - e.effectid6 = row[91] ? static_cast(atoi(row[91])) : 254; - e.effectid7 = row[92] ? static_cast(atoi(row[92])) : 254; - e.effectid8 = row[93] ? static_cast(atoi(row[93])) : 254; - e.effectid9 = row[94] ? static_cast(atoi(row[94])) : 254; - e.effectid10 = row[95] ? static_cast(atoi(row[95])) : 254; - e.effectid11 = row[96] ? static_cast(atoi(row[96])) : 254; - e.effectid12 = row[97] ? static_cast(atoi(row[97])) : 254; - e.targettype = row[98] ? static_cast(atoi(row[98])) : 2; - e.basediff = row[99] ? static_cast(atoi(row[99])) : 0; - e.skill = row[100] ? static_cast(atoi(row[100])) : 98; - e.zonetype = row[101] ? static_cast(atoi(row[101])) : -1; - e.EnvironmentType = row[102] ? static_cast(atoi(row[102])) : 0; - e.TimeOfDay = row[103] ? static_cast(atoi(row[103])) : 0; - e.classes1 = row[104] ? static_cast(atoi(row[104])) : 255; - e.classes2 = row[105] ? static_cast(atoi(row[105])) : 255; - e.classes3 = row[106] ? static_cast(atoi(row[106])) : 255; - e.classes4 = row[107] ? static_cast(atoi(row[107])) : 255; - e.classes5 = row[108] ? static_cast(atoi(row[108])) : 255; - e.classes6 = row[109] ? static_cast(atoi(row[109])) : 255; - e.classes7 = row[110] ? static_cast(atoi(row[110])) : 255; - e.classes8 = row[111] ? static_cast(atoi(row[111])) : 255; - e.classes9 = row[112] ? static_cast(atoi(row[112])) : 255; - e.classes10 = row[113] ? static_cast(atoi(row[113])) : 255; - e.classes11 = row[114] ? static_cast(atoi(row[114])) : 255; - e.classes12 = row[115] ? static_cast(atoi(row[115])) : 255; - e.classes13 = row[116] ? static_cast(atoi(row[116])) : 255; - e.classes14 = row[117] ? static_cast(atoi(row[117])) : 255; - e.classes15 = row[118] ? static_cast(atoi(row[118])) : 255; - e.classes16 = row[119] ? static_cast(atoi(row[119])) : 255; - e.CastingAnim = row[120] ? static_cast(atoi(row[120])) : 44; - e.TargetAnim = row[121] ? static_cast(atoi(row[121])) : 13; - e.TravelType = row[122] ? static_cast(atoi(row[122])) : 0; - e.SpellAffectIndex = row[123] ? static_cast(atoi(row[123])) : -1; - e.disallow_sit = row[124] ? static_cast(atoi(row[124])) : 0; - e.deities0 = row[125] ? static_cast(atoi(row[125])) : 0; - e.deities1 = row[126] ? static_cast(atoi(row[126])) : 0; - e.deities2 = row[127] ? static_cast(atoi(row[127])) : 0; - e.deities3 = row[128] ? static_cast(atoi(row[128])) : 0; - e.deities4 = row[129] ? static_cast(atoi(row[129])) : 0; - e.deities5 = row[130] ? static_cast(atoi(row[130])) : 0; - e.deities6 = row[131] ? static_cast(atoi(row[131])) : 0; - e.deities7 = row[132] ? static_cast(atoi(row[132])) : 0; - e.deities8 = row[133] ? static_cast(atoi(row[133])) : 0; - e.deities9 = row[134] ? static_cast(atoi(row[134])) : 0; - e.deities10 = row[135] ? static_cast(atoi(row[135])) : 0; - e.deities11 = row[136] ? static_cast(atoi(row[136])) : 0; - e.deities12 = row[137] ? static_cast(atoi(row[137])) : 0; - e.deities13 = row[138] ? static_cast(atoi(row[138])) : 0; - e.deities14 = row[139] ? static_cast(atoi(row[139])) : 0; - e.deities15 = row[140] ? static_cast(atoi(row[140])) : 0; - e.deities16 = row[141] ? static_cast(atoi(row[141])) : 0; - e.field142 = row[142] ? static_cast(atoi(row[142])) : 100; - e.field143 = row[143] ? static_cast(atoi(row[143])) : 0; - e.new_icon = row[144] ? static_cast(atoi(row[144])) : 161; - e.spellanim = row[145] ? static_cast(atoi(row[145])) : 0; - e.uninterruptable = row[146] ? static_cast(atoi(row[146])) : 0; - e.ResistDiff = row[147] ? static_cast(atoi(row[147])) : -150; - e.dot_stacking_exempt = row[148] ? static_cast(atoi(row[148])) : 0; - e.deleteable = row[149] ? static_cast(atoi(row[149])) : 0; - e.RecourseLink = row[150] ? static_cast(atoi(row[150])) : 0; - e.no_partial_resist = row[151] ? static_cast(atoi(row[151])) : 0; - e.field152 = row[152] ? static_cast(atoi(row[152])) : 0; - e.field153 = row[153] ? static_cast(atoi(row[153])) : 0; - e.short_buff_box = row[154] ? static_cast(atoi(row[154])) : -1; - e.descnum = row[155] ? static_cast(atoi(row[155])) : 0; - e.typedescnum = row[156] ? static_cast(atoi(row[156])) : 0; - e.effectdescnum = row[157] ? static_cast(atoi(row[157])) : 0; - e.effectdescnum2 = row[158] ? static_cast(atoi(row[158])) : 0; - e.npc_no_los = row[159] ? static_cast(atoi(row[159])) : 0; - e.feedbackable = row[160] ? static_cast(atoi(row[160])) : 0; - e.reflectable = row[161] ? static_cast(atoi(row[161])) : 0; - e.bonushate = row[162] ? static_cast(atoi(row[162])) : 0; - e.field163 = row[163] ? static_cast(atoi(row[163])) : 100; - e.field164 = row[164] ? static_cast(atoi(row[164])) : -150; - e.ldon_trap = row[165] ? static_cast(atoi(row[165])) : 0; - e.EndurCost = row[166] ? static_cast(atoi(row[166])) : 0; - e.EndurTimerIndex = row[167] ? static_cast(atoi(row[167])) : 0; - e.IsDiscipline = row[168] ? static_cast(atoi(row[168])) : 0; - e.field169 = row[169] ? static_cast(atoi(row[169])) : 0; - e.field170 = row[170] ? static_cast(atoi(row[170])) : 0; - e.field171 = row[171] ? static_cast(atoi(row[171])) : 0; - e.field172 = row[172] ? static_cast(atoi(row[172])) : 0; - e.HateAdded = row[173] ? static_cast(atoi(row[173])) : 0; - e.EndurUpkeep = row[174] ? static_cast(atoi(row[174])) : 0; - e.numhitstype = row[175] ? static_cast(atoi(row[175])) : 0; - e.numhits = row[176] ? static_cast(atoi(row[176])) : 0; - e.pvpresistbase = row[177] ? static_cast(atoi(row[177])) : -150; - e.pvpresistcalc = row[178] ? static_cast(atoi(row[178])) : 100; - e.pvpresistcap = row[179] ? static_cast(atoi(row[179])) : -150; - e.spell_category = row[180] ? static_cast(atoi(row[180])) : -99; - e.pvp_duration = row[181] ? static_cast(atoi(row[181])) : 0; - e.pvp_duration_cap = row[182] ? static_cast(atoi(row[182])) : 0; - e.pcnpc_only_flag = row[183] ? static_cast(atoi(row[183])) : 0; - e.cast_not_standing = row[184] ? static_cast(atoi(row[184])) : 0; - e.can_mgb = row[185] ? static_cast(atoi(row[185])) : 0; - e.nodispell = row[186] ? static_cast(atoi(row[186])) : -1; - e.npc_category = row[187] ? static_cast(atoi(row[187])) : 0; - e.npc_usefulness = row[188] ? static_cast(atoi(row[188])) : 0; - e.MinResist = row[189] ? static_cast(atoi(row[189])) : 0; - e.MaxResist = row[190] ? static_cast(atoi(row[190])) : 0; - e.viral_targets = row[191] ? static_cast(atoi(row[191])) : 0; - e.viral_timer = row[192] ? static_cast(atoi(row[192])) : 0; - e.nimbuseffect = row[193] ? static_cast(atoi(row[193])) : 0; - e.ConeStartAngle = row[194] ? static_cast(atoi(row[194])) : 0; - e.ConeStopAngle = row[195] ? static_cast(atoi(row[195])) : 0; - e.sneaking = row[196] ? static_cast(atoi(row[196])) : 0; - e.not_extendable = row[197] ? static_cast(atoi(row[197])) : 0; - e.no_detrimental_spell_aggro = row[198] ? static_cast(atoi(row[198])) : 0; - e.field199 = row[199] ? static_cast(atoi(row[199])) : 1; - e.suspendable = row[200] ? static_cast(atoi(row[200])) : 0; - e.viral_range = row[201] ? static_cast(atoi(row[201])) : 0; - e.songcap = row[202] ? static_cast(atoi(row[202])) : 0; - e.field203 = row[203] ? static_cast(atoi(row[203])) : 0; - e.field204 = row[204] ? static_cast(atoi(row[204])) : 0; - e.no_block = row[205] ? static_cast(atoi(row[205])) : 0; - e.field206 = row[206] ? static_cast(atoi(row[206])) : -1; - e.spellgroup = row[207] ? static_cast(atoi(row[207])) : 0; - e.rank_ = row[208] ? static_cast(atoi(row[208])) : 0; - e.no_resist = row[209] ? static_cast(atoi(row[209])) : 0; - e.field210 = row[210] ? static_cast(atoi(row[210])) : 1; - e.CastRestriction = row[211] ? static_cast(atoi(row[211])) : 0; - e.allowrest = row[212] ? static_cast(atoi(row[212])) : 0; - e.InCombat = row[213] ? static_cast(atoi(row[213])) : 0; - e.OutofCombat = row[214] ? static_cast(atoi(row[214])) : 0; - e.field215 = row[215] ? static_cast(atoi(row[215])) : 0; - e.field216 = row[216] ? static_cast(atoi(row[216])) : 0; - e.override_crit_chance = row[217] ? static_cast(atoi(row[217])) : 0; - e.aemaxtargets = row[218] ? static_cast(atoi(row[218])) : 0; - e.maxtargets = row[219] ? static_cast(atoi(row[219])) : 0; - e.no_heal_damage_item_mod = row[220] ? static_cast(atoi(row[220])) : 0; - e.caster_requirement_id = row[221] ? static_cast(atoi(row[221])) : 0; - e.spell_class = row[222] ? static_cast(atoi(row[222])) : 0; - e.spell_subclass = row[223] ? static_cast(atoi(row[223])) : 0; - e.persistdeath = row[224] ? static_cast(atoi(row[224])) : 0; - e.field225 = row[225] ? static_cast(atoi(row[225])) : 0; - e.field226 = row[226] ? static_cast(atoi(row[226])) : 0; - e.min_dist = row[227] ? strtof(row[227], nullptr) : 0; - e.min_dist_mod = row[228] ? strtof(row[228], nullptr) : 0; - e.max_dist = row[229] ? strtof(row[229], nullptr) : 0; - e.max_dist_mod = row[230] ? strtof(row[230], nullptr) : 0; - e.min_range = row[231] ? static_cast(atoi(row[231])) : 0; - e.no_remove = row[232] ? static_cast(atoi(row[232])) : 0; - e.field233 = row[233] ? static_cast(atoi(row[233])) : 0; - e.field234 = row[234] ? static_cast(atoi(row[234])) : 0; - e.field235 = row[235] ? static_cast(atoi(row[235])) : 0; - e.field236 = row[236] ? static_cast(atoi(row[236])) : 0; + e.id = row[0] ? static_cast(atoi(row[0])) : 0; + e.name = row[1] ? row[1] : ""; + e.player_1 = row[2] ? row[2] : "BLUE_TRAIL"; + e.teleport_zone = row[3] ? row[3] : ""; + e.you_cast = row[4] ? row[4] : ""; + e.other_casts = row[5] ? row[5] : ""; + e.cast_on_you = row[6] ? row[6] : ""; + e.cast_on_other = row[7] ? row[7] : ""; + e.spell_fades = row[8] ? row[8] : ""; + e.range_ = row[9] ? static_cast(atoi(row[9])) : 100; + e.aoerange = row[10] ? static_cast(atoi(row[10])) : 0; + e.pushback = row[11] ? static_cast(atoi(row[11])) : 0; + e.pushup = row[12] ? static_cast(atoi(row[12])) : 0; + e.cast_time = row[13] ? static_cast(atoi(row[13])) : 0; + e.recovery_time = row[14] ? static_cast(atoi(row[14])) : 0; + e.recast_time = row[15] ? static_cast(atoi(row[15])) : 0; + e.buffdurationformula = row[16] ? static_cast(atoi(row[16])) : 7; + e.buffduration = row[17] ? static_cast(atoi(row[17])) : 65; + e.AEDuration = row[18] ? static_cast(atoi(row[18])) : 0; + e.mana = row[19] ? static_cast(atoi(row[19])) : 0; + e.effect_base_value1 = row[20] ? static_cast(atoi(row[20])) : 100; + e.effect_base_value2 = row[21] ? static_cast(atoi(row[21])) : 0; + e.effect_base_value3 = row[22] ? static_cast(atoi(row[22])) : 0; + e.effect_base_value4 = row[23] ? static_cast(atoi(row[23])) : 0; + e.effect_base_value5 = row[24] ? static_cast(atoi(row[24])) : 0; + e.effect_base_value6 = row[25] ? static_cast(atoi(row[25])) : 0; + e.effect_base_value7 = row[26] ? static_cast(atoi(row[26])) : 0; + e.effect_base_value8 = row[27] ? static_cast(atoi(row[27])) : 0; + e.effect_base_value9 = row[28] ? static_cast(atoi(row[28])) : 0; + e.effect_base_value10 = row[29] ? static_cast(atoi(row[29])) : 0; + e.effect_base_value11 = row[30] ? static_cast(atoi(row[30])) : 0; + e.effect_base_value12 = row[31] ? static_cast(atoi(row[31])) : 0; + e.effect_limit_value1 = row[32] ? static_cast(atoi(row[32])) : 0; + e.effect_limit_value2 = row[33] ? static_cast(atoi(row[33])) : 0; + e.effect_limit_value3 = row[34] ? static_cast(atoi(row[34])) : 0; + e.effect_limit_value4 = row[35] ? static_cast(atoi(row[35])) : 0; + e.effect_limit_value5 = row[36] ? static_cast(atoi(row[36])) : 0; + e.effect_limit_value6 = row[37] ? static_cast(atoi(row[37])) : 0; + e.effect_limit_value7 = row[38] ? static_cast(atoi(row[38])) : 0; + e.effect_limit_value8 = row[39] ? static_cast(atoi(row[39])) : 0; + e.effect_limit_value9 = row[40] ? static_cast(atoi(row[40])) : 0; + e.effect_limit_value10 = row[41] ? static_cast(atoi(row[41])) : 0; + e.effect_limit_value11 = row[42] ? static_cast(atoi(row[42])) : 0; + e.effect_limit_value12 = row[43] ? static_cast(atoi(row[43])) : 0; + e.max1 = row[44] ? static_cast(atoi(row[44])) : 0; + e.max2 = row[45] ? static_cast(atoi(row[45])) : 0; + e.max3 = row[46] ? static_cast(atoi(row[46])) : 0; + e.max4 = row[47] ? static_cast(atoi(row[47])) : 0; + e.max5 = row[48] ? static_cast(atoi(row[48])) : 0; + e.max6 = row[49] ? static_cast(atoi(row[49])) : 0; + e.max7 = row[50] ? static_cast(atoi(row[50])) : 0; + e.max8 = row[51] ? static_cast(atoi(row[51])) : 0; + e.max9 = row[52] ? static_cast(atoi(row[52])) : 0; + e.max10 = row[53] ? static_cast(atoi(row[53])) : 0; + e.max11 = row[54] ? static_cast(atoi(row[54])) : 0; + e.max12 = row[55] ? static_cast(atoi(row[55])) : 0; + e.icon = row[56] ? static_cast(atoi(row[56])) : 0; + e.memicon = row[57] ? static_cast(atoi(row[57])) : 0; + e.components1 = row[58] ? static_cast(atoi(row[58])) : -1; + e.components2 = row[59] ? static_cast(atoi(row[59])) : -1; + e.components3 = row[60] ? static_cast(atoi(row[60])) : -1; + e.components4 = row[61] ? static_cast(atoi(row[61])) : -1; + e.component_counts1 = row[62] ? static_cast(atoi(row[62])) : 1; + e.component_counts2 = row[63] ? static_cast(atoi(row[63])) : 1; + e.component_counts3 = row[64] ? static_cast(atoi(row[64])) : 1; + e.component_counts4 = row[65] ? static_cast(atoi(row[65])) : 1; + e.NoexpendReagent1 = row[66] ? static_cast(atoi(row[66])) : -1; + e.NoexpendReagent2 = row[67] ? static_cast(atoi(row[67])) : -1; + e.NoexpendReagent3 = row[68] ? static_cast(atoi(row[68])) : -1; + e.NoexpendReagent4 = row[69] ? static_cast(atoi(row[69])) : -1; + e.formula1 = row[70] ? static_cast(atoi(row[70])) : 100; + e.formula2 = row[71] ? static_cast(atoi(row[71])) : 100; + e.formula3 = row[72] ? static_cast(atoi(row[72])) : 100; + e.formula4 = row[73] ? static_cast(atoi(row[73])) : 100; + e.formula5 = row[74] ? static_cast(atoi(row[74])) : 100; + e.formula6 = row[75] ? static_cast(atoi(row[75])) : 100; + e.formula7 = row[76] ? static_cast(atoi(row[76])) : 100; + e.formula8 = row[77] ? static_cast(atoi(row[77])) : 100; + e.formula9 = row[78] ? static_cast(atoi(row[78])) : 100; + e.formula10 = row[79] ? static_cast(atoi(row[79])) : 100; + e.formula11 = row[80] ? static_cast(atoi(row[80])) : 100; + e.formula12 = row[81] ? static_cast(atoi(row[81])) : 100; + e.LightType = row[82] ? static_cast(atoi(row[82])) : 0; + e.goodEffect = row[83] ? static_cast(atoi(row[83])) : 0; + e.Activated = row[84] ? static_cast(atoi(row[84])) : 0; + e.resisttype = row[85] ? static_cast(atoi(row[85])) : 0; + e.effectid1 = row[86] ? static_cast(atoi(row[86])) : 254; + e.effectid2 = row[87] ? static_cast(atoi(row[87])) : 254; + e.effectid3 = row[88] ? static_cast(atoi(row[88])) : 254; + e.effectid4 = row[89] ? static_cast(atoi(row[89])) : 254; + e.effectid5 = row[90] ? static_cast(atoi(row[90])) : 254; + e.effectid6 = row[91] ? static_cast(atoi(row[91])) : 254; + e.effectid7 = row[92] ? static_cast(atoi(row[92])) : 254; + e.effectid8 = row[93] ? static_cast(atoi(row[93])) : 254; + e.effectid9 = row[94] ? static_cast(atoi(row[94])) : 254; + e.effectid10 = row[95] ? static_cast(atoi(row[95])) : 254; + e.effectid11 = row[96] ? static_cast(atoi(row[96])) : 254; + e.effectid12 = row[97] ? static_cast(atoi(row[97])) : 254; + e.targettype = row[98] ? static_cast(atoi(row[98])) : 2; + e.basediff = row[99] ? static_cast(atoi(row[99])) : 0; + e.skill = row[100] ? static_cast(atoi(row[100])) : 98; + e.zonetype = row[101] ? static_cast(atoi(row[101])) : -1; + e.EnvironmentType = row[102] ? static_cast(atoi(row[102])) : 0; + e.TimeOfDay = row[103] ? static_cast(atoi(row[103])) : 0; + e.classes1 = row[104] ? static_cast(atoi(row[104])) : 255; + e.classes2 = row[105] ? static_cast(atoi(row[105])) : 255; + e.classes3 = row[106] ? static_cast(atoi(row[106])) : 255; + e.classes4 = row[107] ? static_cast(atoi(row[107])) : 255; + e.classes5 = row[108] ? static_cast(atoi(row[108])) : 255; + e.classes6 = row[109] ? static_cast(atoi(row[109])) : 255; + e.classes7 = row[110] ? static_cast(atoi(row[110])) : 255; + e.classes8 = row[111] ? static_cast(atoi(row[111])) : 255; + e.classes9 = row[112] ? static_cast(atoi(row[112])) : 255; + e.classes10 = row[113] ? static_cast(atoi(row[113])) : 255; + e.classes11 = row[114] ? static_cast(atoi(row[114])) : 255; + e.classes12 = row[115] ? static_cast(atoi(row[115])) : 255; + e.classes13 = row[116] ? static_cast(atoi(row[116])) : 255; + e.classes14 = row[117] ? static_cast(atoi(row[117])) : 255; + e.classes15 = row[118] ? static_cast(atoi(row[118])) : 255; + e.classes16 = row[119] ? static_cast(atoi(row[119])) : 255; + e.CastingAnim = row[120] ? static_cast(atoi(row[120])) : 44; + e.TargetAnim = row[121] ? static_cast(atoi(row[121])) : 13; + e.TravelType = row[122] ? static_cast(atoi(row[122])) : 0; + e.SpellAffectIndex = row[123] ? static_cast(atoi(row[123])) : -1; + e.disallow_sit = row[124] ? static_cast(atoi(row[124])) : 0; + e.deities0 = row[125] ? static_cast(atoi(row[125])) : 0; + e.deities1 = row[126] ? static_cast(atoi(row[126])) : 0; + e.deities2 = row[127] ? static_cast(atoi(row[127])) : 0; + e.deities3 = row[128] ? static_cast(atoi(row[128])) : 0; + e.deities4 = row[129] ? static_cast(atoi(row[129])) : 0; + e.deities5 = row[130] ? static_cast(atoi(row[130])) : 0; + e.deities6 = row[131] ? static_cast(atoi(row[131])) : 0; + e.deities7 = row[132] ? static_cast(atoi(row[132])) : 0; + e.deities8 = row[133] ? static_cast(atoi(row[133])) : 0; + e.deities9 = row[134] ? static_cast(atoi(row[134])) : 0; + e.deities10 = row[135] ? static_cast(atoi(row[135])) : 0; + e.deities11 = row[136] ? static_cast(atoi(row[136])) : 0; + e.deities12 = row[137] ? static_cast(atoi(row[137])) : 0; + e.deities13 = row[138] ? static_cast(atoi(row[138])) : 0; + e.deities14 = row[139] ? static_cast(atoi(row[139])) : 0; + e.deities15 = row[140] ? static_cast(atoi(row[140])) : 0; + e.deities16 = row[141] ? static_cast(atoi(row[141])) : 0; + e.field142 = row[142] ? static_cast(atoi(row[142])) : 100; + e.field143 = row[143] ? static_cast(atoi(row[143])) : 0; + e.new_icon = row[144] ? static_cast(atoi(row[144])) : 161; + e.spellanim = row[145] ? static_cast(atoi(row[145])) : 0; + e.uninterruptable = row[146] ? static_cast(atoi(row[146])) : 0; + e.ResistDiff = row[147] ? static_cast(atoi(row[147])) : -150; + e.dot_stacking_exempt = row[148] ? static_cast(atoi(row[148])) : 0; + e.deleteable = row[149] ? static_cast(atoi(row[149])) : 0; + e.RecourseLink = row[150] ? static_cast(atoi(row[150])) : 0; + e.no_partial_resist = row[151] ? static_cast(atoi(row[151])) : 0; + e.field152 = row[152] ? static_cast(atoi(row[152])) : 0; + e.field153 = row[153] ? static_cast(atoi(row[153])) : 0; + e.short_buff_box = row[154] ? static_cast(atoi(row[154])) : -1; + e.descnum = row[155] ? static_cast(atoi(row[155])) : 0; + e.typedescnum = row[156] ? static_cast(atoi(row[156])) : 0; + e.effectdescnum = row[157] ? static_cast(atoi(row[157])) : 0; + e.effectdescnum2 = row[158] ? static_cast(atoi(row[158])) : 0; + e.npc_no_los = row[159] ? static_cast(atoi(row[159])) : 0; + e.field160 = row[160] ? static_cast(atoi(row[160])) : 0; + e.reflectable = row[161] ? static_cast(atoi(row[161])) : 0; + e.bonushate = row[162] ? static_cast(atoi(row[162])) : 0; + e.field163 = row[163] ? static_cast(atoi(row[163])) : 100; + e.field164 = row[164] ? static_cast(atoi(row[164])) : -150; + e.ldon_trap = row[165] ? static_cast(atoi(row[165])) : 0; + e.EndurCost = row[166] ? static_cast(atoi(row[166])) : 0; + e.EndurTimerIndex = row[167] ? static_cast(atoi(row[167])) : 0; + e.IsDiscipline = row[168] ? static_cast(atoi(row[168])) : 0; + e.field169 = row[169] ? static_cast(atoi(row[169])) : 0; + e.field170 = row[170] ? static_cast(atoi(row[170])) : 0; + e.field171 = row[171] ? static_cast(atoi(row[171])) : 0; + e.field172 = row[172] ? static_cast(atoi(row[172])) : 0; + e.HateAdded = row[173] ? static_cast(atoi(row[173])) : 0; + e.EndurUpkeep = row[174] ? static_cast(atoi(row[174])) : 0; + e.numhitstype = row[175] ? static_cast(atoi(row[175])) : 0; + e.numhits = row[176] ? static_cast(atoi(row[176])) : 0; + e.pvpresistbase = row[177] ? static_cast(atoi(row[177])) : -150; + e.pvpresistcalc = row[178] ? static_cast(atoi(row[178])) : 100; + e.pvpresistcap = row[179] ? static_cast(atoi(row[179])) : -150; + e.spell_category = row[180] ? static_cast(atoi(row[180])) : -99; + e.pvp_duration = row[181] ? static_cast(atoi(row[181])) : 0; + e.pvp_duration_cap = row[182] ? static_cast(atoi(row[182])) : 0; + e.pcnpc_only_flag = row[183] ? static_cast(atoi(row[183])) : 0; + e.cast_not_standing = row[184] ? static_cast(atoi(row[184])) : 0; + e.can_mgb = row[185] ? static_cast(atoi(row[185])) : 0; + e.nodispell = row[186] ? static_cast(atoi(row[186])) : -1; + e.npc_category = row[187] ? static_cast(atoi(row[187])) : 0; + e.npc_usefulness = row[188] ? static_cast(atoi(row[188])) : 0; + e.MinResist = row[189] ? static_cast(atoi(row[189])) : 0; + e.MaxResist = row[190] ? static_cast(atoi(row[190])) : 0; + e.viral_targets = row[191] ? static_cast(atoi(row[191])) : 0; + e.viral_timer = row[192] ? static_cast(atoi(row[192])) : 0; + e.nimbuseffect = row[193] ? static_cast(atoi(row[193])) : 0; + e.ConeStartAngle = row[194] ? static_cast(atoi(row[194])) : 0; + e.ConeStopAngle = row[195] ? static_cast(atoi(row[195])) : 0; + e.sneaking = row[196] ? static_cast(atoi(row[196])) : 0; + e.not_extendable = row[197] ? static_cast(atoi(row[197])) : 0; + e.field198 = row[198] ? static_cast(atoi(row[198])) : 0; + e.field199 = row[199] ? static_cast(atoi(row[199])) : 1; + e.suspendable = row[200] ? static_cast(atoi(row[200])) : 0; + e.viral_range = row[201] ? static_cast(atoi(row[201])) : 0; + e.songcap = row[202] ? static_cast(atoi(row[202])) : 0; + e.field203 = row[203] ? static_cast(atoi(row[203])) : 0; + e.field204 = row[204] ? static_cast(atoi(row[204])) : 0; + e.no_block = row[205] ? static_cast(atoi(row[205])) : 0; + e.field206 = row[206] ? static_cast(atoi(row[206])) : -1; + e.spellgroup = row[207] ? static_cast(atoi(row[207])) : 0; + e.rank_ = row[208] ? static_cast(atoi(row[208])) : 0; + e.field209 = row[209] ? static_cast(atoi(row[209])) : 0; + e.field210 = row[210] ? static_cast(atoi(row[210])) : 1; + e.CastRestriction = row[211] ? static_cast(atoi(row[211])) : 0; + e.allowrest = row[212] ? static_cast(atoi(row[212])) : 0; + e.InCombat = row[213] ? static_cast(atoi(row[213])) : 0; + e.OutofCombat = row[214] ? static_cast(atoi(row[214])) : 0; + e.field215 = row[215] ? static_cast(atoi(row[215])) : 0; + e.field216 = row[216] ? static_cast(atoi(row[216])) : 0; + e.field217 = row[217] ? static_cast(atoi(row[217])) : 0; + e.aemaxtargets = row[218] ? static_cast(atoi(row[218])) : 0; + e.maxtargets = row[219] ? static_cast(atoi(row[219])) : 0; + e.field220 = row[220] ? static_cast(atoi(row[220])) : 0; + e.field221 = row[221] ? static_cast(atoi(row[221])) : 0; + e.field222 = row[222] ? static_cast(atoi(row[222])) : 0; + e.field223 = row[223] ? static_cast(atoi(row[223])) : 0; + e.persistdeath = row[224] ? static_cast(atoi(row[224])) : 0; + e.field225 = row[225] ? static_cast(atoi(row[225])) : 0; + e.field226 = row[226] ? static_cast(atoi(row[226])) : 0; + e.min_dist = row[227] ? strtof(row[227], nullptr) : 0; + e.min_dist_mod = row[228] ? strtof(row[228], nullptr) : 0; + e.max_dist = row[229] ? strtof(row[229], nullptr) : 0; + e.max_dist_mod = row[230] ? strtof(row[230], nullptr) : 0; + e.min_range = row[231] ? static_cast(atoi(row[231])) : 0; + e.field232 = row[232] ? static_cast(atoi(row[232])) : 0; + e.field233 = row[233] ? static_cast(atoi(row[233])) : 0; + e.field234 = row[234] ? static_cast(atoi(row[234])) : 0; + e.field235 = row[235] ? static_cast(atoi(row[235])) : 0; + e.field236 = row[236] ? static_cast(atoi(row[236])) : 0; all_entries.push_back(e); } @@ -2384,243 +2384,243 @@ class BaseSpellsNewRepository { for (auto row = results.begin(); row != results.end(); ++row) { SpellsNew e{}; - e.id = row[0] ? static_cast(atoi(row[0])) : 0; - e.name = row[1] ? row[1] : ""; - e.player_1 = row[2] ? row[2] : "BLUE_TRAIL"; - e.teleport_zone = row[3] ? row[3] : ""; - e.you_cast = row[4] ? row[4] : ""; - e.other_casts = row[5] ? row[5] : ""; - e.cast_on_you = row[6] ? row[6] : ""; - e.cast_on_other = row[7] ? row[7] : ""; - e.spell_fades = row[8] ? row[8] : ""; - e.range_ = row[9] ? static_cast(atoi(row[9])) : 100; - e.aoerange = row[10] ? static_cast(atoi(row[10])) : 0; - e.pushback = row[11] ? static_cast(atoi(row[11])) : 0; - e.pushup = row[12] ? static_cast(atoi(row[12])) : 0; - e.cast_time = row[13] ? static_cast(atoi(row[13])) : 0; - e.recovery_time = row[14] ? static_cast(atoi(row[14])) : 0; - e.recast_time = row[15] ? static_cast(atoi(row[15])) : 0; - e.buffdurationformula = row[16] ? static_cast(atoi(row[16])) : 7; - e.buffduration = row[17] ? static_cast(atoi(row[17])) : 65; - e.AEDuration = row[18] ? static_cast(atoi(row[18])) : 0; - e.mana = row[19] ? static_cast(atoi(row[19])) : 0; - e.effect_base_value1 = row[20] ? static_cast(atoi(row[20])) : 100; - e.effect_base_value2 = row[21] ? static_cast(atoi(row[21])) : 0; - e.effect_base_value3 = row[22] ? static_cast(atoi(row[22])) : 0; - e.effect_base_value4 = row[23] ? static_cast(atoi(row[23])) : 0; - e.effect_base_value5 = row[24] ? static_cast(atoi(row[24])) : 0; - e.effect_base_value6 = row[25] ? static_cast(atoi(row[25])) : 0; - e.effect_base_value7 = row[26] ? static_cast(atoi(row[26])) : 0; - e.effect_base_value8 = row[27] ? static_cast(atoi(row[27])) : 0; - e.effect_base_value9 = row[28] ? static_cast(atoi(row[28])) : 0; - e.effect_base_value10 = row[29] ? static_cast(atoi(row[29])) : 0; - e.effect_base_value11 = row[30] ? static_cast(atoi(row[30])) : 0; - e.effect_base_value12 = row[31] ? static_cast(atoi(row[31])) : 0; - e.effect_limit_value1 = row[32] ? static_cast(atoi(row[32])) : 0; - e.effect_limit_value2 = row[33] ? static_cast(atoi(row[33])) : 0; - e.effect_limit_value3 = row[34] ? static_cast(atoi(row[34])) : 0; - e.effect_limit_value4 = row[35] ? static_cast(atoi(row[35])) : 0; - e.effect_limit_value5 = row[36] ? static_cast(atoi(row[36])) : 0; - e.effect_limit_value6 = row[37] ? static_cast(atoi(row[37])) : 0; - e.effect_limit_value7 = row[38] ? static_cast(atoi(row[38])) : 0; - e.effect_limit_value8 = row[39] ? static_cast(atoi(row[39])) : 0; - e.effect_limit_value9 = row[40] ? static_cast(atoi(row[40])) : 0; - e.effect_limit_value10 = row[41] ? static_cast(atoi(row[41])) : 0; - e.effect_limit_value11 = row[42] ? static_cast(atoi(row[42])) : 0; - e.effect_limit_value12 = row[43] ? static_cast(atoi(row[43])) : 0; - e.max1 = row[44] ? static_cast(atoi(row[44])) : 0; - e.max2 = row[45] ? static_cast(atoi(row[45])) : 0; - e.max3 = row[46] ? static_cast(atoi(row[46])) : 0; - e.max4 = row[47] ? static_cast(atoi(row[47])) : 0; - e.max5 = row[48] ? static_cast(atoi(row[48])) : 0; - e.max6 = row[49] ? static_cast(atoi(row[49])) : 0; - e.max7 = row[50] ? static_cast(atoi(row[50])) : 0; - e.max8 = row[51] ? static_cast(atoi(row[51])) : 0; - e.max9 = row[52] ? static_cast(atoi(row[52])) : 0; - e.max10 = row[53] ? static_cast(atoi(row[53])) : 0; - e.max11 = row[54] ? static_cast(atoi(row[54])) : 0; - e.max12 = row[55] ? static_cast(atoi(row[55])) : 0; - e.icon = row[56] ? static_cast(atoi(row[56])) : 0; - e.memicon = row[57] ? static_cast(atoi(row[57])) : 0; - e.components1 = row[58] ? static_cast(atoi(row[58])) : -1; - e.components2 = row[59] ? static_cast(atoi(row[59])) : -1; - e.components3 = row[60] ? static_cast(atoi(row[60])) : -1; - e.components4 = row[61] ? static_cast(atoi(row[61])) : -1; - e.component_counts1 = row[62] ? static_cast(atoi(row[62])) : 1; - e.component_counts2 = row[63] ? static_cast(atoi(row[63])) : 1; - e.component_counts3 = row[64] ? static_cast(atoi(row[64])) : 1; - e.component_counts4 = row[65] ? static_cast(atoi(row[65])) : 1; - e.NoexpendReagent1 = row[66] ? static_cast(atoi(row[66])) : -1; - e.NoexpendReagent2 = row[67] ? static_cast(atoi(row[67])) : -1; - e.NoexpendReagent3 = row[68] ? static_cast(atoi(row[68])) : -1; - e.NoexpendReagent4 = row[69] ? static_cast(atoi(row[69])) : -1; - e.formula1 = row[70] ? static_cast(atoi(row[70])) : 100; - e.formula2 = row[71] ? static_cast(atoi(row[71])) : 100; - e.formula3 = row[72] ? static_cast(atoi(row[72])) : 100; - e.formula4 = row[73] ? static_cast(atoi(row[73])) : 100; - e.formula5 = row[74] ? static_cast(atoi(row[74])) : 100; - e.formula6 = row[75] ? static_cast(atoi(row[75])) : 100; - e.formula7 = row[76] ? static_cast(atoi(row[76])) : 100; - e.formula8 = row[77] ? static_cast(atoi(row[77])) : 100; - e.formula9 = row[78] ? static_cast(atoi(row[78])) : 100; - e.formula10 = row[79] ? static_cast(atoi(row[79])) : 100; - e.formula11 = row[80] ? static_cast(atoi(row[80])) : 100; - e.formula12 = row[81] ? static_cast(atoi(row[81])) : 100; - e.LightType = row[82] ? static_cast(atoi(row[82])) : 0; - e.goodEffect = row[83] ? static_cast(atoi(row[83])) : 0; - e.Activated = row[84] ? static_cast(atoi(row[84])) : 0; - e.resisttype = row[85] ? static_cast(atoi(row[85])) : 0; - e.effectid1 = row[86] ? static_cast(atoi(row[86])) : 254; - e.effectid2 = row[87] ? static_cast(atoi(row[87])) : 254; - e.effectid3 = row[88] ? static_cast(atoi(row[88])) : 254; - e.effectid4 = row[89] ? static_cast(atoi(row[89])) : 254; - e.effectid5 = row[90] ? static_cast(atoi(row[90])) : 254; - e.effectid6 = row[91] ? static_cast(atoi(row[91])) : 254; - e.effectid7 = row[92] ? static_cast(atoi(row[92])) : 254; - e.effectid8 = row[93] ? static_cast(atoi(row[93])) : 254; - e.effectid9 = row[94] ? static_cast(atoi(row[94])) : 254; - e.effectid10 = row[95] ? static_cast(atoi(row[95])) : 254; - e.effectid11 = row[96] ? static_cast(atoi(row[96])) : 254; - e.effectid12 = row[97] ? static_cast(atoi(row[97])) : 254; - e.targettype = row[98] ? static_cast(atoi(row[98])) : 2; - e.basediff = row[99] ? static_cast(atoi(row[99])) : 0; - e.skill = row[100] ? static_cast(atoi(row[100])) : 98; - e.zonetype = row[101] ? static_cast(atoi(row[101])) : -1; - e.EnvironmentType = row[102] ? static_cast(atoi(row[102])) : 0; - e.TimeOfDay = row[103] ? static_cast(atoi(row[103])) : 0; - e.classes1 = row[104] ? static_cast(atoi(row[104])) : 255; - e.classes2 = row[105] ? static_cast(atoi(row[105])) : 255; - e.classes3 = row[106] ? static_cast(atoi(row[106])) : 255; - e.classes4 = row[107] ? static_cast(atoi(row[107])) : 255; - e.classes5 = row[108] ? static_cast(atoi(row[108])) : 255; - e.classes6 = row[109] ? static_cast(atoi(row[109])) : 255; - e.classes7 = row[110] ? static_cast(atoi(row[110])) : 255; - e.classes8 = row[111] ? static_cast(atoi(row[111])) : 255; - e.classes9 = row[112] ? static_cast(atoi(row[112])) : 255; - e.classes10 = row[113] ? static_cast(atoi(row[113])) : 255; - e.classes11 = row[114] ? static_cast(atoi(row[114])) : 255; - e.classes12 = row[115] ? static_cast(atoi(row[115])) : 255; - e.classes13 = row[116] ? static_cast(atoi(row[116])) : 255; - e.classes14 = row[117] ? static_cast(atoi(row[117])) : 255; - e.classes15 = row[118] ? static_cast(atoi(row[118])) : 255; - e.classes16 = row[119] ? static_cast(atoi(row[119])) : 255; - e.CastingAnim = row[120] ? static_cast(atoi(row[120])) : 44; - e.TargetAnim = row[121] ? static_cast(atoi(row[121])) : 13; - e.TravelType = row[122] ? static_cast(atoi(row[122])) : 0; - e.SpellAffectIndex = row[123] ? static_cast(atoi(row[123])) : -1; - e.disallow_sit = row[124] ? static_cast(atoi(row[124])) : 0; - e.deities0 = row[125] ? static_cast(atoi(row[125])) : 0; - e.deities1 = row[126] ? static_cast(atoi(row[126])) : 0; - e.deities2 = row[127] ? static_cast(atoi(row[127])) : 0; - e.deities3 = row[128] ? static_cast(atoi(row[128])) : 0; - e.deities4 = row[129] ? static_cast(atoi(row[129])) : 0; - e.deities5 = row[130] ? static_cast(atoi(row[130])) : 0; - e.deities6 = row[131] ? static_cast(atoi(row[131])) : 0; - e.deities7 = row[132] ? static_cast(atoi(row[132])) : 0; - e.deities8 = row[133] ? static_cast(atoi(row[133])) : 0; - e.deities9 = row[134] ? static_cast(atoi(row[134])) : 0; - e.deities10 = row[135] ? static_cast(atoi(row[135])) : 0; - e.deities11 = row[136] ? static_cast(atoi(row[136])) : 0; - e.deities12 = row[137] ? static_cast(atoi(row[137])) : 0; - e.deities13 = row[138] ? static_cast(atoi(row[138])) : 0; - e.deities14 = row[139] ? static_cast(atoi(row[139])) : 0; - e.deities15 = row[140] ? static_cast(atoi(row[140])) : 0; - e.deities16 = row[141] ? static_cast(atoi(row[141])) : 0; - e.field142 = row[142] ? static_cast(atoi(row[142])) : 100; - e.field143 = row[143] ? static_cast(atoi(row[143])) : 0; - e.new_icon = row[144] ? static_cast(atoi(row[144])) : 161; - e.spellanim = row[145] ? static_cast(atoi(row[145])) : 0; - e.uninterruptable = row[146] ? static_cast(atoi(row[146])) : 0; - e.ResistDiff = row[147] ? static_cast(atoi(row[147])) : -150; - e.dot_stacking_exempt = row[148] ? static_cast(atoi(row[148])) : 0; - e.deleteable = row[149] ? static_cast(atoi(row[149])) : 0; - e.RecourseLink = row[150] ? static_cast(atoi(row[150])) : 0; - e.no_partial_resist = row[151] ? static_cast(atoi(row[151])) : 0; - e.field152 = row[152] ? static_cast(atoi(row[152])) : 0; - e.field153 = row[153] ? static_cast(atoi(row[153])) : 0; - e.short_buff_box = row[154] ? static_cast(atoi(row[154])) : -1; - e.descnum = row[155] ? static_cast(atoi(row[155])) : 0; - e.typedescnum = row[156] ? static_cast(atoi(row[156])) : 0; - e.effectdescnum = row[157] ? static_cast(atoi(row[157])) : 0; - e.effectdescnum2 = row[158] ? static_cast(atoi(row[158])) : 0; - e.npc_no_los = row[159] ? static_cast(atoi(row[159])) : 0; - e.feedbackable = row[160] ? static_cast(atoi(row[160])) : 0; - e.reflectable = row[161] ? static_cast(atoi(row[161])) : 0; - e.bonushate = row[162] ? static_cast(atoi(row[162])) : 0; - e.field163 = row[163] ? static_cast(atoi(row[163])) : 100; - e.field164 = row[164] ? static_cast(atoi(row[164])) : -150; - e.ldon_trap = row[165] ? static_cast(atoi(row[165])) : 0; - e.EndurCost = row[166] ? static_cast(atoi(row[166])) : 0; - e.EndurTimerIndex = row[167] ? static_cast(atoi(row[167])) : 0; - e.IsDiscipline = row[168] ? static_cast(atoi(row[168])) : 0; - e.field169 = row[169] ? static_cast(atoi(row[169])) : 0; - e.field170 = row[170] ? static_cast(atoi(row[170])) : 0; - e.field171 = row[171] ? static_cast(atoi(row[171])) : 0; - e.field172 = row[172] ? static_cast(atoi(row[172])) : 0; - e.HateAdded = row[173] ? static_cast(atoi(row[173])) : 0; - e.EndurUpkeep = row[174] ? static_cast(atoi(row[174])) : 0; - e.numhitstype = row[175] ? static_cast(atoi(row[175])) : 0; - e.numhits = row[176] ? static_cast(atoi(row[176])) : 0; - e.pvpresistbase = row[177] ? static_cast(atoi(row[177])) : -150; - e.pvpresistcalc = row[178] ? static_cast(atoi(row[178])) : 100; - e.pvpresistcap = row[179] ? static_cast(atoi(row[179])) : -150; - e.spell_category = row[180] ? static_cast(atoi(row[180])) : -99; - e.pvp_duration = row[181] ? static_cast(atoi(row[181])) : 0; - e.pvp_duration_cap = row[182] ? static_cast(atoi(row[182])) : 0; - e.pcnpc_only_flag = row[183] ? static_cast(atoi(row[183])) : 0; - e.cast_not_standing = row[184] ? static_cast(atoi(row[184])) : 0; - e.can_mgb = row[185] ? static_cast(atoi(row[185])) : 0; - e.nodispell = row[186] ? static_cast(atoi(row[186])) : -1; - e.npc_category = row[187] ? static_cast(atoi(row[187])) : 0; - e.npc_usefulness = row[188] ? static_cast(atoi(row[188])) : 0; - e.MinResist = row[189] ? static_cast(atoi(row[189])) : 0; - e.MaxResist = row[190] ? static_cast(atoi(row[190])) : 0; - e.viral_targets = row[191] ? static_cast(atoi(row[191])) : 0; - e.viral_timer = row[192] ? static_cast(atoi(row[192])) : 0; - e.nimbuseffect = row[193] ? static_cast(atoi(row[193])) : 0; - e.ConeStartAngle = row[194] ? static_cast(atoi(row[194])) : 0; - e.ConeStopAngle = row[195] ? static_cast(atoi(row[195])) : 0; - e.sneaking = row[196] ? static_cast(atoi(row[196])) : 0; - e.not_extendable = row[197] ? static_cast(atoi(row[197])) : 0; - e.no_detrimental_spell_aggro = row[198] ? static_cast(atoi(row[198])) : 0; - e.field199 = row[199] ? static_cast(atoi(row[199])) : 1; - e.suspendable = row[200] ? static_cast(atoi(row[200])) : 0; - e.viral_range = row[201] ? static_cast(atoi(row[201])) : 0; - e.songcap = row[202] ? static_cast(atoi(row[202])) : 0; - e.field203 = row[203] ? static_cast(atoi(row[203])) : 0; - e.field204 = row[204] ? static_cast(atoi(row[204])) : 0; - e.no_block = row[205] ? static_cast(atoi(row[205])) : 0; - e.field206 = row[206] ? static_cast(atoi(row[206])) : -1; - e.spellgroup = row[207] ? static_cast(atoi(row[207])) : 0; - e.rank_ = row[208] ? static_cast(atoi(row[208])) : 0; - e.no_resist = row[209] ? static_cast(atoi(row[209])) : 0; - e.field210 = row[210] ? static_cast(atoi(row[210])) : 1; - e.CastRestriction = row[211] ? static_cast(atoi(row[211])) : 0; - e.allowrest = row[212] ? static_cast(atoi(row[212])) : 0; - e.InCombat = row[213] ? static_cast(atoi(row[213])) : 0; - e.OutofCombat = row[214] ? static_cast(atoi(row[214])) : 0; - e.field215 = row[215] ? static_cast(atoi(row[215])) : 0; - e.field216 = row[216] ? static_cast(atoi(row[216])) : 0; - e.override_crit_chance = row[217] ? static_cast(atoi(row[217])) : 0; - e.aemaxtargets = row[218] ? static_cast(atoi(row[218])) : 0; - e.maxtargets = row[219] ? static_cast(atoi(row[219])) : 0; - e.no_heal_damage_item_mod = row[220] ? static_cast(atoi(row[220])) : 0; - e.caster_requirement_id = row[221] ? static_cast(atoi(row[221])) : 0; - e.spell_class = row[222] ? static_cast(atoi(row[222])) : 0; - e.spell_subclass = row[223] ? static_cast(atoi(row[223])) : 0; - e.persistdeath = row[224] ? static_cast(atoi(row[224])) : 0; - e.field225 = row[225] ? static_cast(atoi(row[225])) : 0; - e.field226 = row[226] ? static_cast(atoi(row[226])) : 0; - e.min_dist = row[227] ? strtof(row[227], nullptr) : 0; - e.min_dist_mod = row[228] ? strtof(row[228], nullptr) : 0; - e.max_dist = row[229] ? strtof(row[229], nullptr) : 0; - e.max_dist_mod = row[230] ? strtof(row[230], nullptr) : 0; - e.min_range = row[231] ? static_cast(atoi(row[231])) : 0; - e.no_remove = row[232] ? static_cast(atoi(row[232])) : 0; - e.field233 = row[233] ? static_cast(atoi(row[233])) : 0; - e.field234 = row[234] ? static_cast(atoi(row[234])) : 0; - e.field235 = row[235] ? static_cast(atoi(row[235])) : 0; - e.field236 = row[236] ? static_cast(atoi(row[236])) : 0; + e.id = row[0] ? static_cast(atoi(row[0])) : 0; + e.name = row[1] ? row[1] : ""; + e.player_1 = row[2] ? row[2] : "BLUE_TRAIL"; + e.teleport_zone = row[3] ? row[3] : ""; + e.you_cast = row[4] ? row[4] : ""; + e.other_casts = row[5] ? row[5] : ""; + e.cast_on_you = row[6] ? row[6] : ""; + e.cast_on_other = row[7] ? row[7] : ""; + e.spell_fades = row[8] ? row[8] : ""; + e.range_ = row[9] ? static_cast(atoi(row[9])) : 100; + e.aoerange = row[10] ? static_cast(atoi(row[10])) : 0; + e.pushback = row[11] ? static_cast(atoi(row[11])) : 0; + e.pushup = row[12] ? static_cast(atoi(row[12])) : 0; + e.cast_time = row[13] ? static_cast(atoi(row[13])) : 0; + e.recovery_time = row[14] ? static_cast(atoi(row[14])) : 0; + e.recast_time = row[15] ? static_cast(atoi(row[15])) : 0; + e.buffdurationformula = row[16] ? static_cast(atoi(row[16])) : 7; + e.buffduration = row[17] ? static_cast(atoi(row[17])) : 65; + e.AEDuration = row[18] ? static_cast(atoi(row[18])) : 0; + e.mana = row[19] ? static_cast(atoi(row[19])) : 0; + e.effect_base_value1 = row[20] ? static_cast(atoi(row[20])) : 100; + e.effect_base_value2 = row[21] ? static_cast(atoi(row[21])) : 0; + e.effect_base_value3 = row[22] ? static_cast(atoi(row[22])) : 0; + e.effect_base_value4 = row[23] ? static_cast(atoi(row[23])) : 0; + e.effect_base_value5 = row[24] ? static_cast(atoi(row[24])) : 0; + e.effect_base_value6 = row[25] ? static_cast(atoi(row[25])) : 0; + e.effect_base_value7 = row[26] ? static_cast(atoi(row[26])) : 0; + e.effect_base_value8 = row[27] ? static_cast(atoi(row[27])) : 0; + e.effect_base_value9 = row[28] ? static_cast(atoi(row[28])) : 0; + e.effect_base_value10 = row[29] ? static_cast(atoi(row[29])) : 0; + e.effect_base_value11 = row[30] ? static_cast(atoi(row[30])) : 0; + e.effect_base_value12 = row[31] ? static_cast(atoi(row[31])) : 0; + e.effect_limit_value1 = row[32] ? static_cast(atoi(row[32])) : 0; + e.effect_limit_value2 = row[33] ? static_cast(atoi(row[33])) : 0; + e.effect_limit_value3 = row[34] ? static_cast(atoi(row[34])) : 0; + e.effect_limit_value4 = row[35] ? static_cast(atoi(row[35])) : 0; + e.effect_limit_value5 = row[36] ? static_cast(atoi(row[36])) : 0; + e.effect_limit_value6 = row[37] ? static_cast(atoi(row[37])) : 0; + e.effect_limit_value7 = row[38] ? static_cast(atoi(row[38])) : 0; + e.effect_limit_value8 = row[39] ? static_cast(atoi(row[39])) : 0; + e.effect_limit_value9 = row[40] ? static_cast(atoi(row[40])) : 0; + e.effect_limit_value10 = row[41] ? static_cast(atoi(row[41])) : 0; + e.effect_limit_value11 = row[42] ? static_cast(atoi(row[42])) : 0; + e.effect_limit_value12 = row[43] ? static_cast(atoi(row[43])) : 0; + e.max1 = row[44] ? static_cast(atoi(row[44])) : 0; + e.max2 = row[45] ? static_cast(atoi(row[45])) : 0; + e.max3 = row[46] ? static_cast(atoi(row[46])) : 0; + e.max4 = row[47] ? static_cast(atoi(row[47])) : 0; + e.max5 = row[48] ? static_cast(atoi(row[48])) : 0; + e.max6 = row[49] ? static_cast(atoi(row[49])) : 0; + e.max7 = row[50] ? static_cast(atoi(row[50])) : 0; + e.max8 = row[51] ? static_cast(atoi(row[51])) : 0; + e.max9 = row[52] ? static_cast(atoi(row[52])) : 0; + e.max10 = row[53] ? static_cast(atoi(row[53])) : 0; + e.max11 = row[54] ? static_cast(atoi(row[54])) : 0; + e.max12 = row[55] ? static_cast(atoi(row[55])) : 0; + e.icon = row[56] ? static_cast(atoi(row[56])) : 0; + e.memicon = row[57] ? static_cast(atoi(row[57])) : 0; + e.components1 = row[58] ? static_cast(atoi(row[58])) : -1; + e.components2 = row[59] ? static_cast(atoi(row[59])) : -1; + e.components3 = row[60] ? static_cast(atoi(row[60])) : -1; + e.components4 = row[61] ? static_cast(atoi(row[61])) : -1; + e.component_counts1 = row[62] ? static_cast(atoi(row[62])) : 1; + e.component_counts2 = row[63] ? static_cast(atoi(row[63])) : 1; + e.component_counts3 = row[64] ? static_cast(atoi(row[64])) : 1; + e.component_counts4 = row[65] ? static_cast(atoi(row[65])) : 1; + e.NoexpendReagent1 = row[66] ? static_cast(atoi(row[66])) : -1; + e.NoexpendReagent2 = row[67] ? static_cast(atoi(row[67])) : -1; + e.NoexpendReagent3 = row[68] ? static_cast(atoi(row[68])) : -1; + e.NoexpendReagent4 = row[69] ? static_cast(atoi(row[69])) : -1; + e.formula1 = row[70] ? static_cast(atoi(row[70])) : 100; + e.formula2 = row[71] ? static_cast(atoi(row[71])) : 100; + e.formula3 = row[72] ? static_cast(atoi(row[72])) : 100; + e.formula4 = row[73] ? static_cast(atoi(row[73])) : 100; + e.formula5 = row[74] ? static_cast(atoi(row[74])) : 100; + e.formula6 = row[75] ? static_cast(atoi(row[75])) : 100; + e.formula7 = row[76] ? static_cast(atoi(row[76])) : 100; + e.formula8 = row[77] ? static_cast(atoi(row[77])) : 100; + e.formula9 = row[78] ? static_cast(atoi(row[78])) : 100; + e.formula10 = row[79] ? static_cast(atoi(row[79])) : 100; + e.formula11 = row[80] ? static_cast(atoi(row[80])) : 100; + e.formula12 = row[81] ? static_cast(atoi(row[81])) : 100; + e.LightType = row[82] ? static_cast(atoi(row[82])) : 0; + e.goodEffect = row[83] ? static_cast(atoi(row[83])) : 0; + e.Activated = row[84] ? static_cast(atoi(row[84])) : 0; + e.resisttype = row[85] ? static_cast(atoi(row[85])) : 0; + e.effectid1 = row[86] ? static_cast(atoi(row[86])) : 254; + e.effectid2 = row[87] ? static_cast(atoi(row[87])) : 254; + e.effectid3 = row[88] ? static_cast(atoi(row[88])) : 254; + e.effectid4 = row[89] ? static_cast(atoi(row[89])) : 254; + e.effectid5 = row[90] ? static_cast(atoi(row[90])) : 254; + e.effectid6 = row[91] ? static_cast(atoi(row[91])) : 254; + e.effectid7 = row[92] ? static_cast(atoi(row[92])) : 254; + e.effectid8 = row[93] ? static_cast(atoi(row[93])) : 254; + e.effectid9 = row[94] ? static_cast(atoi(row[94])) : 254; + e.effectid10 = row[95] ? static_cast(atoi(row[95])) : 254; + e.effectid11 = row[96] ? static_cast(atoi(row[96])) : 254; + e.effectid12 = row[97] ? static_cast(atoi(row[97])) : 254; + e.targettype = row[98] ? static_cast(atoi(row[98])) : 2; + e.basediff = row[99] ? static_cast(atoi(row[99])) : 0; + e.skill = row[100] ? static_cast(atoi(row[100])) : 98; + e.zonetype = row[101] ? static_cast(atoi(row[101])) : -1; + e.EnvironmentType = row[102] ? static_cast(atoi(row[102])) : 0; + e.TimeOfDay = row[103] ? static_cast(atoi(row[103])) : 0; + e.classes1 = row[104] ? static_cast(atoi(row[104])) : 255; + e.classes2 = row[105] ? static_cast(atoi(row[105])) : 255; + e.classes3 = row[106] ? static_cast(atoi(row[106])) : 255; + e.classes4 = row[107] ? static_cast(atoi(row[107])) : 255; + e.classes5 = row[108] ? static_cast(atoi(row[108])) : 255; + e.classes6 = row[109] ? static_cast(atoi(row[109])) : 255; + e.classes7 = row[110] ? static_cast(atoi(row[110])) : 255; + e.classes8 = row[111] ? static_cast(atoi(row[111])) : 255; + e.classes9 = row[112] ? static_cast(atoi(row[112])) : 255; + e.classes10 = row[113] ? static_cast(atoi(row[113])) : 255; + e.classes11 = row[114] ? static_cast(atoi(row[114])) : 255; + e.classes12 = row[115] ? static_cast(atoi(row[115])) : 255; + e.classes13 = row[116] ? static_cast(atoi(row[116])) : 255; + e.classes14 = row[117] ? static_cast(atoi(row[117])) : 255; + e.classes15 = row[118] ? static_cast(atoi(row[118])) : 255; + e.classes16 = row[119] ? static_cast(atoi(row[119])) : 255; + e.CastingAnim = row[120] ? static_cast(atoi(row[120])) : 44; + e.TargetAnim = row[121] ? static_cast(atoi(row[121])) : 13; + e.TravelType = row[122] ? static_cast(atoi(row[122])) : 0; + e.SpellAffectIndex = row[123] ? static_cast(atoi(row[123])) : -1; + e.disallow_sit = row[124] ? static_cast(atoi(row[124])) : 0; + e.deities0 = row[125] ? static_cast(atoi(row[125])) : 0; + e.deities1 = row[126] ? static_cast(atoi(row[126])) : 0; + e.deities2 = row[127] ? static_cast(atoi(row[127])) : 0; + e.deities3 = row[128] ? static_cast(atoi(row[128])) : 0; + e.deities4 = row[129] ? static_cast(atoi(row[129])) : 0; + e.deities5 = row[130] ? static_cast(atoi(row[130])) : 0; + e.deities6 = row[131] ? static_cast(atoi(row[131])) : 0; + e.deities7 = row[132] ? static_cast(atoi(row[132])) : 0; + e.deities8 = row[133] ? static_cast(atoi(row[133])) : 0; + e.deities9 = row[134] ? static_cast(atoi(row[134])) : 0; + e.deities10 = row[135] ? static_cast(atoi(row[135])) : 0; + e.deities11 = row[136] ? static_cast(atoi(row[136])) : 0; + e.deities12 = row[137] ? static_cast(atoi(row[137])) : 0; + e.deities13 = row[138] ? static_cast(atoi(row[138])) : 0; + e.deities14 = row[139] ? static_cast(atoi(row[139])) : 0; + e.deities15 = row[140] ? static_cast(atoi(row[140])) : 0; + e.deities16 = row[141] ? static_cast(atoi(row[141])) : 0; + e.field142 = row[142] ? static_cast(atoi(row[142])) : 100; + e.field143 = row[143] ? static_cast(atoi(row[143])) : 0; + e.new_icon = row[144] ? static_cast(atoi(row[144])) : 161; + e.spellanim = row[145] ? static_cast(atoi(row[145])) : 0; + e.uninterruptable = row[146] ? static_cast(atoi(row[146])) : 0; + e.ResistDiff = row[147] ? static_cast(atoi(row[147])) : -150; + e.dot_stacking_exempt = row[148] ? static_cast(atoi(row[148])) : 0; + e.deleteable = row[149] ? static_cast(atoi(row[149])) : 0; + e.RecourseLink = row[150] ? static_cast(atoi(row[150])) : 0; + e.no_partial_resist = row[151] ? static_cast(atoi(row[151])) : 0; + e.field152 = row[152] ? static_cast(atoi(row[152])) : 0; + e.field153 = row[153] ? static_cast(atoi(row[153])) : 0; + e.short_buff_box = row[154] ? static_cast(atoi(row[154])) : -1; + e.descnum = row[155] ? static_cast(atoi(row[155])) : 0; + e.typedescnum = row[156] ? static_cast(atoi(row[156])) : 0; + e.effectdescnum = row[157] ? static_cast(atoi(row[157])) : 0; + e.effectdescnum2 = row[158] ? static_cast(atoi(row[158])) : 0; + e.npc_no_los = row[159] ? static_cast(atoi(row[159])) : 0; + e.field160 = row[160] ? static_cast(atoi(row[160])) : 0; + e.reflectable = row[161] ? static_cast(atoi(row[161])) : 0; + e.bonushate = row[162] ? static_cast(atoi(row[162])) : 0; + e.field163 = row[163] ? static_cast(atoi(row[163])) : 100; + e.field164 = row[164] ? static_cast(atoi(row[164])) : -150; + e.ldon_trap = row[165] ? static_cast(atoi(row[165])) : 0; + e.EndurCost = row[166] ? static_cast(atoi(row[166])) : 0; + e.EndurTimerIndex = row[167] ? static_cast(atoi(row[167])) : 0; + e.IsDiscipline = row[168] ? static_cast(atoi(row[168])) : 0; + e.field169 = row[169] ? static_cast(atoi(row[169])) : 0; + e.field170 = row[170] ? static_cast(atoi(row[170])) : 0; + e.field171 = row[171] ? static_cast(atoi(row[171])) : 0; + e.field172 = row[172] ? static_cast(atoi(row[172])) : 0; + e.HateAdded = row[173] ? static_cast(atoi(row[173])) : 0; + e.EndurUpkeep = row[174] ? static_cast(atoi(row[174])) : 0; + e.numhitstype = row[175] ? static_cast(atoi(row[175])) : 0; + e.numhits = row[176] ? static_cast(atoi(row[176])) : 0; + e.pvpresistbase = row[177] ? static_cast(atoi(row[177])) : -150; + e.pvpresistcalc = row[178] ? static_cast(atoi(row[178])) : 100; + e.pvpresistcap = row[179] ? static_cast(atoi(row[179])) : -150; + e.spell_category = row[180] ? static_cast(atoi(row[180])) : -99; + e.pvp_duration = row[181] ? static_cast(atoi(row[181])) : 0; + e.pvp_duration_cap = row[182] ? static_cast(atoi(row[182])) : 0; + e.pcnpc_only_flag = row[183] ? static_cast(atoi(row[183])) : 0; + e.cast_not_standing = row[184] ? static_cast(atoi(row[184])) : 0; + e.can_mgb = row[185] ? static_cast(atoi(row[185])) : 0; + e.nodispell = row[186] ? static_cast(atoi(row[186])) : -1; + e.npc_category = row[187] ? static_cast(atoi(row[187])) : 0; + e.npc_usefulness = row[188] ? static_cast(atoi(row[188])) : 0; + e.MinResist = row[189] ? static_cast(atoi(row[189])) : 0; + e.MaxResist = row[190] ? static_cast(atoi(row[190])) : 0; + e.viral_targets = row[191] ? static_cast(atoi(row[191])) : 0; + e.viral_timer = row[192] ? static_cast(atoi(row[192])) : 0; + e.nimbuseffect = row[193] ? static_cast(atoi(row[193])) : 0; + e.ConeStartAngle = row[194] ? static_cast(atoi(row[194])) : 0; + e.ConeStopAngle = row[195] ? static_cast(atoi(row[195])) : 0; + e.sneaking = row[196] ? static_cast(atoi(row[196])) : 0; + e.not_extendable = row[197] ? static_cast(atoi(row[197])) : 0; + e.field198 = row[198] ? static_cast(atoi(row[198])) : 0; + e.field199 = row[199] ? static_cast(atoi(row[199])) : 1; + e.suspendable = row[200] ? static_cast(atoi(row[200])) : 0; + e.viral_range = row[201] ? static_cast(atoi(row[201])) : 0; + e.songcap = row[202] ? static_cast(atoi(row[202])) : 0; + e.field203 = row[203] ? static_cast(atoi(row[203])) : 0; + e.field204 = row[204] ? static_cast(atoi(row[204])) : 0; + e.no_block = row[205] ? static_cast(atoi(row[205])) : 0; + e.field206 = row[206] ? static_cast(atoi(row[206])) : -1; + e.spellgroup = row[207] ? static_cast(atoi(row[207])) : 0; + e.rank_ = row[208] ? static_cast(atoi(row[208])) : 0; + e.field209 = row[209] ? static_cast(atoi(row[209])) : 0; + e.field210 = row[210] ? static_cast(atoi(row[210])) : 1; + e.CastRestriction = row[211] ? static_cast(atoi(row[211])) : 0; + e.allowrest = row[212] ? static_cast(atoi(row[212])) : 0; + e.InCombat = row[213] ? static_cast(atoi(row[213])) : 0; + e.OutofCombat = row[214] ? static_cast(atoi(row[214])) : 0; + e.field215 = row[215] ? static_cast(atoi(row[215])) : 0; + e.field216 = row[216] ? static_cast(atoi(row[216])) : 0; + e.field217 = row[217] ? static_cast(atoi(row[217])) : 0; + e.aemaxtargets = row[218] ? static_cast(atoi(row[218])) : 0; + e.maxtargets = row[219] ? static_cast(atoi(row[219])) : 0; + e.field220 = row[220] ? static_cast(atoi(row[220])) : 0; + e.field221 = row[221] ? static_cast(atoi(row[221])) : 0; + e.field222 = row[222] ? static_cast(atoi(row[222])) : 0; + e.field223 = row[223] ? static_cast(atoi(row[223])) : 0; + e.persistdeath = row[224] ? static_cast(atoi(row[224])) : 0; + e.field225 = row[225] ? static_cast(atoi(row[225])) : 0; + e.field226 = row[226] ? static_cast(atoi(row[226])) : 0; + e.min_dist = row[227] ? strtof(row[227], nullptr) : 0; + e.min_dist_mod = row[228] ? strtof(row[228], nullptr) : 0; + e.max_dist = row[229] ? strtof(row[229], nullptr) : 0; + e.max_dist_mod = row[230] ? strtof(row[230], nullptr) : 0; + e.min_range = row[231] ? static_cast(atoi(row[231])) : 0; + e.field232 = row[232] ? static_cast(atoi(row[232])) : 0; + e.field233 = row[233] ? static_cast(atoi(row[233])) : 0; + e.field234 = row[234] ? static_cast(atoi(row[234])) : 0; + e.field235 = row[235] ? static_cast(atoi(row[235])) : 0; + e.field236 = row[236] ? static_cast(atoi(row[236])) : 0; all_entries.push_back(e); } @@ -2855,7 +2855,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.effectdescnum)); v.push_back(std::to_string(e.effectdescnum2)); v.push_back(std::to_string(e.npc_no_los)); - v.push_back(std::to_string(e.feedbackable)); + v.push_back(std::to_string(e.field160)); v.push_back(std::to_string(e.reflectable)); v.push_back(std::to_string(e.bonushate)); v.push_back(std::to_string(e.field163)); @@ -2893,7 +2893,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.ConeStopAngle)); v.push_back(std::to_string(e.sneaking)); v.push_back(std::to_string(e.not_extendable)); - v.push_back(std::to_string(e.no_detrimental_spell_aggro)); + v.push_back(std::to_string(e.field198)); v.push_back(std::to_string(e.field199)); v.push_back(std::to_string(e.suspendable)); v.push_back(std::to_string(e.viral_range)); @@ -2904,7 +2904,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.field206)); v.push_back(std::to_string(e.spellgroup)); v.push_back(std::to_string(e.rank_)); - v.push_back(std::to_string(e.no_resist)); + v.push_back(std::to_string(e.field209)); v.push_back(std::to_string(e.field210)); v.push_back(std::to_string(e.CastRestriction)); v.push_back(std::to_string(e.allowrest)); @@ -2912,13 +2912,13 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.OutofCombat)); v.push_back(std::to_string(e.field215)); v.push_back(std::to_string(e.field216)); - v.push_back(std::to_string(e.override_crit_chance)); + v.push_back(std::to_string(e.field217)); v.push_back(std::to_string(e.aemaxtargets)); v.push_back(std::to_string(e.maxtargets)); - v.push_back(std::to_string(e.no_heal_damage_item_mod)); - v.push_back(std::to_string(e.caster_requirement_id)); - v.push_back(std::to_string(e.spell_class)); - v.push_back(std::to_string(e.spell_subclass)); + v.push_back(std::to_string(e.field220)); + v.push_back(std::to_string(e.field221)); + v.push_back(std::to_string(e.field222)); + v.push_back(std::to_string(e.field223)); v.push_back(std::to_string(e.persistdeath)); v.push_back(std::to_string(e.field225)); v.push_back(std::to_string(e.field226)); @@ -2927,7 +2927,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.max_dist)); v.push_back(std::to_string(e.max_dist_mod)); v.push_back(std::to_string(e.min_range)); - v.push_back(std::to_string(e.no_remove)); + v.push_back(std::to_string(e.field232)); v.push_back(std::to_string(e.field233)); v.push_back(std::to_string(e.field234)); v.push_back(std::to_string(e.field235)); @@ -3114,7 +3114,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.effectdescnum)); v.push_back(std::to_string(e.effectdescnum2)); v.push_back(std::to_string(e.npc_no_los)); - v.push_back(std::to_string(e.feedbackable)); + v.push_back(std::to_string(e.field160)); v.push_back(std::to_string(e.reflectable)); v.push_back(std::to_string(e.bonushate)); v.push_back(std::to_string(e.field163)); @@ -3152,7 +3152,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.ConeStopAngle)); v.push_back(std::to_string(e.sneaking)); v.push_back(std::to_string(e.not_extendable)); - v.push_back(std::to_string(e.no_detrimental_spell_aggro)); + v.push_back(std::to_string(e.field198)); v.push_back(std::to_string(e.field199)); v.push_back(std::to_string(e.suspendable)); v.push_back(std::to_string(e.viral_range)); @@ -3163,7 +3163,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.field206)); v.push_back(std::to_string(e.spellgroup)); v.push_back(std::to_string(e.rank_)); - v.push_back(std::to_string(e.no_resist)); + v.push_back(std::to_string(e.field209)); v.push_back(std::to_string(e.field210)); v.push_back(std::to_string(e.CastRestriction)); v.push_back(std::to_string(e.allowrest)); @@ -3171,13 +3171,13 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.OutofCombat)); v.push_back(std::to_string(e.field215)); v.push_back(std::to_string(e.field216)); - v.push_back(std::to_string(e.override_crit_chance)); + v.push_back(std::to_string(e.field217)); v.push_back(std::to_string(e.aemaxtargets)); v.push_back(std::to_string(e.maxtargets)); - v.push_back(std::to_string(e.no_heal_damage_item_mod)); - v.push_back(std::to_string(e.caster_requirement_id)); - v.push_back(std::to_string(e.spell_class)); - v.push_back(std::to_string(e.spell_subclass)); + v.push_back(std::to_string(e.field220)); + v.push_back(std::to_string(e.field221)); + v.push_back(std::to_string(e.field222)); + v.push_back(std::to_string(e.field223)); v.push_back(std::to_string(e.persistdeath)); v.push_back(std::to_string(e.field225)); v.push_back(std::to_string(e.field226)); @@ -3186,7 +3186,7 @@ class BaseSpellsNewRepository { v.push_back(std::to_string(e.max_dist)); v.push_back(std::to_string(e.max_dist_mod)); v.push_back(std::to_string(e.min_range)); - v.push_back(std::to_string(e.no_remove)); + v.push_back(std::to_string(e.field232)); v.push_back(std::to_string(e.field233)); v.push_back(std::to_string(e.field234)); v.push_back(std::to_string(e.field235)); diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 0a9dab91f1..d680df1de0 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -56,6 +56,19 @@ #include "repositories/damageshieldtypes_repository.h" #include "repositories/items_repository.h" +namespace ItemField +{ + enum { + source = 0, +#define F(x) x, +#include "item_fieldlist.h" +#undef F + updated, + minstatus, + comment, + }; +} + SharedDatabase::SharedDatabase() : Database() { @@ -1630,9 +1643,16 @@ const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) { return nullptr; // nothing here for now... database and/or sharemem pulls later } -int SharedDatabase::GetMaxSpellID() -{ - return SpellsNewRepository::GetMaxId(*this); +int SharedDatabase::GetMaxSpellID() { + const std::string query = "SELECT MAX(id) FROM spells_new"; + auto results = QueryDatabase(query); + if (!results.Success()) { + return -1; + } + + auto& row = results.begin(); + + return Strings::ToInt(row[0]); } bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp) { @@ -1664,247 +1684,173 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { *static_cast(data) = max_spells; SPDat_Spell_Struct *sp = reinterpret_cast(static_cast(data) + sizeof(uint32)); - const auto& l = SpellsNewRepository::All(*this); + const std::string query = "SELECT * FROM spells_new ORDER BY id ASC"; + auto results = QueryDatabase(query); + if (!results.Success()) { + return; + } - if (l.empty()) { + if(results.ColumnCount() <= SPELL_LOAD_FIELD_COUNT) { + LogSpells("Fatal error loading spells: Spell field count < SPELL_LOAD_FIELD_COUNT([{}])", SPELL_LOAD_FIELD_COUNT); return; - } + } - for (const auto& e : l) { - if (e.id >= max_spells) { + int counter = 0; + + for (auto& row = results.begin(); row != results.end(); ++row) { + const int tempid = Strings::ToInt(row[0]); + if(tempid >= max_spells) { LogSpells("Non fatal error: spell.id >= max_spells, ignoring"); continue; } - sp[e.id].id = e.id; - - strn0cpy(sp[e.id].name, e.name.c_str(), sizeof(sp[e.id].name)); - strn0cpy(sp[e.id].player_1, e.player_1.c_str(), sizeof(sp[e.id].player_1)); - strn0cpy(sp[e.id].teleport_zone, e.teleport_zone.c_str(), sizeof(sp[e.id].teleport_zone)); - strn0cpy(sp[e.id].you_cast, e.you_cast.c_str(), sizeof(sp[e.id].you_cast)); - strn0cpy(sp[e.id].other_casts, e.other_casts.c_str(), sizeof(sp[e.id].other_casts)); - strn0cpy(sp[e.id].cast_on_you, e.cast_on_you.c_str(), sizeof(sp[e.id].cast_on_you)); - strn0cpy(sp[e.id].cast_on_other, e.cast_on_other.c_str(), sizeof(sp[e.id].cast_on_other)); - strn0cpy(sp[e.id].spell_fades, e.spell_fades.c_str(), sizeof(sp[e.id].spell_fades)); - - sp[e.id].range = e.range_; - sp[e.id].aoe_range = e.aoerange; - sp[e.id].push_back = e.pushback; - sp[e.id].push_up = e.pushup; - sp[e.id].cast_time = e.cast_time; - sp[e.id].recovery_time = e.recovery_time; - sp[e.id].recast_time = e.recast_time; - sp[e.id].buff_duration_formula = e.buffdurationformula; - sp[e.id].buff_duration = e.buffduration; - sp[e.id].aoe_duration = e.AEDuration; - sp[e.id].mana = e.mana; - - sp[e.id].base_value[0] = e.effect_base_value1; - sp[e.id].base_value[1] = e.effect_base_value2; - sp[e.id].base_value[2] = e.effect_base_value3; - sp[e.id].base_value[3] = e.effect_base_value4; - sp[e.id].base_value[4] = e.effect_base_value5; - sp[e.id].base_value[5] = e.effect_base_value6; - sp[e.id].base_value[6] = e.effect_base_value7; - sp[e.id].base_value[7] = e.effect_base_value8; - sp[e.id].base_value[8] = e.effect_base_value9; - sp[e.id].base_value[9] = e.effect_base_value10; - sp[e.id].base_value[10] = e.effect_base_value11; - sp[e.id].base_value[11] = e.effect_base_value12; - - sp[e.id].limit_value[0] = e.effect_limit_value1; - sp[e.id].limit_value[1] = e.effect_limit_value2; - sp[e.id].limit_value[2] = e.effect_limit_value3; - sp[e.id].limit_value[3] = e.effect_limit_value4; - sp[e.id].limit_value[4] = e.effect_limit_value5; - sp[e.id].limit_value[5] = e.effect_limit_value6; - sp[e.id].limit_value[6] = e.effect_limit_value7; - sp[e.id].limit_value[7] = e.effect_limit_value8; - sp[e.id].limit_value[8] = e.effect_limit_value9; - sp[e.id].limit_value[9] = e.effect_limit_value10; - sp[e.id].limit_value[10] = e.effect_limit_value11; - sp[e.id].limit_value[11] = e.effect_limit_value12; - - sp[e.id].max_value[0] = e.max1; - sp[e.id].max_value[1] = e.max2; - sp[e.id].max_value[2] = e.max3; - sp[e.id].max_value[3] = e.max4; - sp[e.id].max_value[4] = e.max5; - sp[e.id].max_value[5] = e.max6; - sp[e.id].max_value[6] = e.max7; - sp[e.id].max_value[7] = e.max8; - sp[e.id].max_value[8] = e.max9; - sp[e.id].max_value[9] = e.max10; - sp[e.id].max_value[10] = e.max11; - sp[e.id].max_value[11] = e.max12; - - sp[e.id].component[0] = e.components1; - sp[e.id].component[1] = e.components2; - sp[e.id].component[2] = e.components3; - sp[e.id].component[3] = e.components4; - - sp[e.id].component_count[0] = e.component_counts1; - sp[e.id].component_count[1] = e.component_counts2; - sp[e.id].component_count[2] = e.component_counts3; - sp[e.id].component_count[3] = e.component_counts4; - - sp[e.id].no_expend_reagent[0] = e.NoexpendReagent1; - sp[e.id].no_expend_reagent[1] = e.NoexpendReagent2; - sp[e.id].no_expend_reagent[2] = e.NoexpendReagent3; - sp[e.id].no_expend_reagent[3] = e.NoexpendReagent4; - - sp[e.id].formula[0] = e.formula1; - sp[e.id].formula[1] = e.formula2; - sp[e.id].formula[2] = e.formula3; - sp[e.id].formula[3] = e.formula4; - sp[e.id].formula[4] = e.formula5; - sp[e.id].formula[5] = e.formula6; - sp[e.id].formula[6] = e.formula7; - sp[e.id].formula[7] = e.formula8; - sp[e.id].formula[8] = e.formula9; - sp[e.id].formula[9] = e.formula10; - sp[e.id].formula[10] = e.formula11; - sp[e.id].formula[11] = e.formula12; - - sp[e.id].good_effect = e.goodEffect; - sp[e.id].activated = e.Activated; - sp[e.id].resist_type = e.resisttype; - - sp[e.id].effect_id[0] = e.effectid1; - sp[e.id].effect_id[1] = e.effectid2; - sp[e.id].effect_id[2] = e.effectid3; - sp[e.id].effect_id[3] = e.effectid4; - sp[e.id].effect_id[4] = e.effectid5; - sp[e.id].effect_id[5] = e.effectid6; - sp[e.id].effect_id[6] = e.effectid7; - sp[e.id].effect_id[7] = e.effectid8; - sp[e.id].effect_id[8] = e.effectid9; - sp[e.id].effect_id[9] = e.effectid10; - sp[e.id].effect_id[10] = e.effectid11; - sp[e.id].effect_id[11] = e.effectid12; - - sp[e.id].target_type = static_cast(e.targettype); - - sp[e.id].base_difficulty = e.basediff; - - sp[e.id].skill = ( - EQ::ValueWithin(e.skill, 0, EQ::skills::HIGHEST_SKILL) ? - static_cast(e.skill) : - EQ::skills::SkillBegging - ); - - sp[e.id].zone_type = e.zonetype; - sp[e.id].environment_type = e.EnvironmentType; - sp[e.id].time_of_day = e.TimeOfDay; - - sp[e.id].classes[0] = e.classes1; - sp[e.id].classes[1] = e.classes2; - sp[e.id].classes[2] = e.classes3; - sp[e.id].classes[3] = e.classes4; - sp[e.id].classes[4] = e.classes5; - sp[e.id].classes[5] = e.classes6; - sp[e.id].classes[6] = e.classes7; - sp[e.id].classes[7] = e.classes8; - sp[e.id].classes[8] = e.classes9; - sp[e.id].classes[9] = e.classes10; - sp[e.id].classes[10] = e.classes11; - sp[e.id].classes[11] = e.classes12; - sp[e.id].classes[12] = e.classes13; - sp[e.id].classes[13] = e.classes14; - sp[e.id].classes[14] = e.classes15; - sp[e.id].classes[15] = e.classes16; - - sp[e.id].casting_animation = e.CastingAnim; - sp[e.id].spell_affect_index = e.SpellAffectIndex; - sp[e.id].disallow_sit = e.disallow_sit; - - sp[e.id].deity_agnostic = e.deities0; // Agnostic - sp[e.id].deities[0] = e.deities1; // Bertoxxulous - sp[e.id].deities[1] = e.deities2; // Brell Serilis - sp[e.id].deities[2] = e.deities3; // Cazic Thule - sp[e.id].deities[3] = e.deities4; // Erollsi Marr - sp[e.id].deities[4] = e.deities5; // Bristlebane - sp[e.id].deities[5] = e.deities6; // Innoruuk - sp[e.id].deities[6] = e.deities7; // Karana - sp[e.id].deities[7] = e.deities8; // Mithaniel Marr - sp[e.id].deities[8] = e.deities9; // Prexius - sp[e.id].deities[9] = e.deities10; // Quellious - sp[e.id].deities[10] = e.deities11; // Rallos Zek - sp[e.id].deities[11] = e.deities12; // Rodcet Nife - sp[e.id].deities[12] = e.deities13; // Solusek Ro - sp[e.id].deities[13] = e.deities14; // The Tribunal - sp[e.id].deities[14] = e.deities15; // Tunare - sp[e.id].deities[15] = e.deities16; // Veeshan - - sp[e.id].new_icon = e.new_icon; - sp[e.id].uninterruptable = e.uninterruptable; - sp[e.id].resist_difficulty = e.ResistDiff; - sp[e.id].unstackable_dot = e.dot_stacking_exempt; - sp[e.id].recourse_link = e.RecourseLink; - sp[e.id].no_partial_resist = e.no_partial_resist; - sp[e.id].short_buff_box = e.short_buff_box; - sp[e.id].description_id = e.descnum; - sp[e.id].type_description_id = e.typedescnum; - sp[e.id].effect_description_id = e.effectdescnum; - sp[e.id].npc_no_los = e.npc_no_los; - sp[e.id].feedbackable = e.feedbackable; - sp[e.id].reflectable = e.reflectable; - sp[e.id].bonus_hate = e.bonushate; - sp[e.id].ldon_trap = e.ldon_trap; - sp[e.id].endurance_cost = e.EndurCost; - sp[e.id].timer_id = e.EndurTimerIndex; - sp[e.id].is_discipline = e.IsDiscipline; - sp[e.id].hate_added = e.HateAdded; - sp[e.id].endurance_upkeep = e.EndurUpkeep; - sp[e.id].hit_number_type = e.numhits; - sp[e.id].hit_number = e.numhitstype; - sp[e.id].pvp_resist_base = e.pvpresistbase; - sp[e.id].pvp_resist_per_level = e.pvpresistcalc; - sp[e.id].pvp_resist_cap = e.pvpresistcap; - sp[e.id].spell_category = e.spell_category; - sp[e.id].pvp_duration = e.pvp_duration; - sp[e.id].pvp_duration_cap = e.pvp_duration_cap; - sp[e.id].pcnpc_only_flag = e.pcnpc_only_flag; - sp[e.id].cast_not_standing = e.cast_not_standing; - sp[e.id].can_mgb = e.can_mgb; - sp[e.id].dispel_flag = e.nodispell; - sp[e.id].min_resist = e.MinResist; - sp[e.id].max_resist = e.MaxResist; - sp[e.id].viral_targets = e.viral_targets; - sp[e.id].viral_timer = e.viral_timer; - sp[e.id].nimbus_effect = e.nimbuseffect; - sp[e.id].directional_start = e.ConeStartAngle; - sp[e.id].directional_end = e.ConeStopAngle; - sp[e.id].sneak = e.sneaking; - sp[e.id].not_focusable = e.not_extendable; - - sp[e.id].no_detrimental_spell_aggro = e.no_detrimental_spell_aggro; - - sp[e.id].suspendable = e.suspendable; - sp[e.id].viral_range = e.viral_range; - sp[e.id].song_cap = e.songcap; - sp[e.id].no_block = e.no_block; - sp[e.id].spell_group = e.spellgroup; - sp[e.id].rank = e.rank_; - sp[e.id].no_resist = e.no_resist; - sp[e.id].cast_restriction = e.CastRestriction; - sp[e.id].allow_rest = e.allowrest; - sp[e.id].can_cast_in_combat = e.InCombat; - sp[e.id].can_cast_out_of_combat = e.OutofCombat; - sp[e.id].override_crit_chance = e.override_crit_chance; - sp[e.id].aoe_max_targets = e.aemaxtargets; - sp[e.id].no_heal_damage_item_mod = e.no_heal_damage_item_mod; - sp[e.id].caster_requirement_id = e.caster_requirement_id; - sp[e.id].spell_class = e.spell_class; - sp[e.id].spell_subclass = e.spell_subclass; - sp[e.id].persist_death = e.persistdeath; - sp[e.id].min_distance = e.min_dist; - sp[e.id].min_distance_mod = e.min_dist_mod; - sp[e.id].max_distance = e.max_dist; - sp[e.id].max_distance_mod = e.max_dist_mod; - sp[e.id].min_range = e.min_range; - sp[e.id].no_remove = e.no_remove; - sp[e.id].damage_shield_type = 0; + ++counter; + sp[tempid].id = tempid; + strn0cpy(sp[tempid].name, row[1], sizeof(sp[tempid].name)); + strn0cpy(sp[tempid].player_1, row[2], sizeof(sp[tempid].player_1)); + strn0cpy(sp[tempid].teleport_zone, row[3], sizeof(sp[tempid].teleport_zone)); + strn0cpy(sp[tempid].you_cast, row[4], sizeof(sp[tempid].you_cast)); + strn0cpy(sp[tempid].other_casts, row[5], sizeof(sp[tempid].other_casts)); + strn0cpy(sp[tempid].cast_on_you, row[6], sizeof(sp[tempid].cast_on_you)); + strn0cpy(sp[tempid].cast_on_other, row[7], sizeof(sp[tempid].cast_on_other)); + strn0cpy(sp[tempid].spell_fades, row[8], sizeof(sp[tempid].spell_fades)); + + sp[tempid].range = Strings::ToFloat(row[9]); + sp[tempid].aoe_range = Strings::ToFloat(row[10]); + sp[tempid].push_back = Strings::ToFloat(row[11]); + sp[tempid].push_up = Strings::ToFloat(row[12]); + sp[tempid].cast_time=Strings::ToUnsignedInt(row[13]); + sp[tempid].recovery_time=Strings::ToUnsignedInt(row[14]); + sp[tempid].recast_time=Strings::ToUnsignedInt(row[15]); + sp[tempid].buff_duration_formula=Strings::ToUnsignedInt(row[16]); + sp[tempid].buff_duration=Strings::ToUnsignedInt(row[17]); + sp[tempid].aoe_duration=Strings::ToUnsignedInt(row[18]); + sp[tempid].mana=Strings::ToInt(row[19]); + + int y=0; + for(y=0; y< EFFECT_COUNT;y++) + sp[tempid].base_value[y]=Strings::ToInt(row[20+y]); // effect_base_value + + for(y=0; y < EFFECT_COUNT; y++) + sp[tempid].limit_value[y]=Strings::ToInt(row[32+y]); // effect_limit_value + + for(y=0; y< EFFECT_COUNT;y++) + sp[tempid].max_value[y]=Strings::ToInt(row[44+y]); + + for(y=0; y< 4;y++) + sp[tempid].component[y]=Strings::ToInt(row[58+y]); + + for(y=0; y< 4;y++) + sp[tempid].component_count[y]=Strings::ToInt(row[62+y]); + + for(y=0; y< 4;y++) + sp[tempid].no_expend_reagent[y]=Strings::ToInt(row[66+y]); + + for(y=0; y< EFFECT_COUNT;y++) + sp[tempid].formula[y]=Strings::ToUnsignedInt(row[70+y]); + + sp[tempid].good_effect=Strings::ToInt(row[83]); + sp[tempid].activated=Strings::ToInt(row[84]); + sp[tempid].resist_type=Strings::ToInt(row[85]); + + for(y=0; y< EFFECT_COUNT;y++) + sp[tempid].effect_id[y]=Strings::ToInt(row[86+y]); + + sp[tempid].target_type = static_cast(Strings::ToInt(row[98])); + sp[tempid].base_difficulty=Strings::ToInt(row[99]); + + int tmp_skill = Strings::ToInt(row[100]); + + if (tmp_skill < 0 || tmp_skill > EQ::skills::HIGHEST_SKILL) + sp[tempid].skill = EQ::skills::SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated + else + sp[tempid].skill = static_cast(tmp_skill); + + sp[tempid].zone_type=Strings::ToInt(row[101]); + sp[tempid].environment_type=Strings::ToInt(row[102]); + sp[tempid].time_of_day=Strings::ToInt(row[103]); + + for(y=0; y < Class::PLAYER_CLASS_COUNT;y++) + sp[tempid].classes[y]=Strings::ToInt(row[104+y]); + + sp[tempid].casting_animation=Strings::ToInt(row[120]); + sp[tempid].spell_affect_index=Strings::ToInt(row[123]); + sp[tempid].disallow_sit=Strings::ToInt(row[124]); + sp[tempid].deity_agnostic=Strings::ToInt(row[125]); + + for (y = 0; y < 16; y++) + sp[tempid].deities[y]=Strings::ToInt(row[126+y]); + + sp[tempid].new_icon=Strings::ToInt(row[144]); + sp[tempid].uninterruptable=Strings::ToBool(row[146]); + sp[tempid].resist_difficulty=Strings::ToInt(row[147]); + sp[tempid].unstackable_dot = Strings::ToBool(row[148]); + sp[tempid].recourse_link = Strings::ToUnsignedInt(row[150]); + sp[tempid].no_partial_resist = Strings::ToBool(row[151]); + + sp[tempid].short_buff_box = Strings::ToInt(row[154]); + sp[tempid].description_id = Strings::ToInt(row[155]); + sp[tempid].type_description_id = Strings::ToInt(row[156]); + sp[tempid].effect_description_id = Strings::ToInt(row[157]); + + sp[tempid].npc_no_los = Strings::ToBool(row[159]); + sp[tempid].feedbackable = Strings::ToBool(row[160]); + sp[tempid].reflectable = Strings::ToBool(row[161]); + sp[tempid].bonus_hate=Strings::ToInt(row[162]); + + sp[tempid].ldon_trap = Strings::ToBool(row[165]); + sp[tempid].endurance_cost= Strings::ToInt(row[166]); + sp[tempid].timer_id= Strings::ToInt(row[167]); + sp[tempid].is_discipline = Strings::ToBool(row[168]); + sp[tempid].hate_added= Strings::ToInt(row[173]); + sp[tempid].endurance_upkeep=Strings::ToInt(row[174]); + sp[tempid].hit_number_type = Strings::ToInt(row[175]); + sp[tempid].hit_number = Strings::ToInt(row[176]); + sp[tempid].pvp_resist_base= Strings::ToInt(row[177]); + sp[tempid].pvp_resist_per_level= Strings::ToInt(row[178]); + sp[tempid].pvp_resist_cap= Strings::ToInt(row[179]); + sp[tempid].spell_category= Strings::ToInt(row[180]); + sp[tempid].pvp_duration = Strings::ToInt(row[181]); + sp[tempid].pvp_duration_cap = Strings::ToInt(row[182]); + sp[tempid].pcnpc_only_flag= Strings::ToInt(row[183]); + sp[tempid].cast_not_standing = Strings::ToInt(row[184]) != 0; + sp[tempid].can_mgb= Strings::ToBool(row[185]); + sp[tempid].dispel_flag = Strings::ToInt(row[186]); + sp[tempid].min_resist = Strings::ToInt(row[189]); + sp[tempid].max_resist = Strings::ToInt(row[190]); + sp[tempid].viral_targets = Strings::ToInt(row[191]); + sp[tempid].viral_timer = Strings::ToInt(row[192]); + sp[tempid].nimbus_effect = Strings::ToInt(row[193]); + sp[tempid].directional_start = Strings::ToFloat(row[194]); + sp[tempid].directional_end = Strings::ToFloat(row[195]); + sp[tempid].sneak = Strings::ToBool(row[196]); + sp[tempid].not_focusable = Strings::ToBool(row[197]); + sp[tempid].no_detrimental_spell_aggro = Strings::ToBool(row[198]); + sp[tempid].suspendable = Strings::ToBool(row[200]); + sp[tempid].viral_range = Strings::ToInt(row[201]); + sp[tempid].song_cap = Strings::ToInt(row[202]); + sp[tempid].no_block = Strings::ToInt(row[205]); + sp[tempid].spell_group=Strings::ToInt(row[207]); + sp[tempid].rank = Strings::ToInt(row[208]); + sp[tempid].no_resist=Strings::ToInt(row[209]); + sp[tempid].cast_restriction = Strings::ToInt(row[211]); + sp[tempid].allow_rest = Strings::ToBool(row[212]); + sp[tempid].can_cast_in_combat = Strings::ToBool(row[213]); + sp[tempid].can_cast_out_of_combat = Strings::ToBool(row[214]); + sp[tempid].override_crit_chance = Strings::ToInt(row[217]); + sp[tempid].aoe_max_targets = Strings::ToInt(row[218]); + sp[tempid].no_heal_damage_item_mod = Strings::ToInt(row[219]); + sp[tempid].caster_requirement_id = Strings::ToInt(row[220]); + sp[tempid].spell_class = Strings::ToInt(row[221]); + sp[tempid].spell_subclass = Strings::ToInt(row[222]); + sp[tempid].persist_death = Strings::ToBool(row[224]); + sp[tempid].min_distance = Strings::ToFloat(row[227]); + sp[tempid].min_distance_mod = Strings::ToFloat(row[228]); + sp[tempid].max_distance = Strings::ToFloat(row[229]); + sp[tempid].max_distance_mod = Strings::ToFloat(row[230]); + sp[tempid].min_range = Strings::ToFloat(row[231]); + sp[tempid].no_remove = Strings::ToBool(row[232]); + sp[tempid].damage_shield_type = 0; } LoadDamageShieldTypes(sp); @@ -1937,7 +1883,18 @@ void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const Insp uint32 SharedDatabase::GetSpellsCount() { - return SpellsNewRepository::Count(*this); + auto results = QueryDatabase("SELECT count(*) FROM spells_new"); + if (!results.Success() || !results.RowCount()) { + return 0; + } + + auto& row = results.begin(); + + if (row[0]) { + return Strings::ToUnsignedInt(row[0]); + } + + return 0; } uint32 SharedDatabase::GetItemsCount() diff --git a/common/spdat.h b/common/spdat.h index 9df894d350..11130d6a4e 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -1600,6 +1600,7 @@ namespace SpellEffect { // number. note that the id field is counted as 0, this way the numbers // here match the numbers given to sep in the loading function net.cpp // +#define SPELL_LOAD_FIELD_COUNT 236 struct SPDat_Spell_Struct { diff --git a/common/version.h b/common/version.h index 25688ca0dc..b9c5436918 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9329 +#define CURRENT_BINARY_DATABASE_VERSION 9328 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054 #define CUSTOM_BINARY_DATABASE_VERSION 0 From 0447618f7e177be4ec76483273a92a5023e37050 Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Wed, 17 Sep 2025 00:50:03 -0500 Subject: [PATCH 047/194] hotfix: merge fix --- common/shareddb.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index d680df1de0..0ef0cbe4e0 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -56,19 +56,6 @@ #include "repositories/damageshieldtypes_repository.h" #include "repositories/items_repository.h" -namespace ItemField -{ - enum { - source = 0, -#define F(x) x, -#include "item_fieldlist.h" -#undef F - updated, - minstatus, - comment, - }; -} - SharedDatabase::SharedDatabase() : Database() { From e8f4ffd62846cc97e4f6d9f19b4efaa61764e39a Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Wed, 17 Sep 2025 00:52:31 -0500 Subject: [PATCH 048/194] [Release] 23.10.2 --- CHANGELOG.md | 6 ++++++ common/version.h | 2 +- package.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b774412133..9da523f41d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [23.10.2] 9/16/2025 + +### Hotfix + +* Revert #4996 as it was causing critical issues with spells that needs to be further investigated. @Akkadius 2025-09-17 + ## [23.10.1] 9/16/2025 ### Hotfix diff --git a/common/version.h b/common/version.h index b9c5436918..285e169688 100644 --- a/common/version.h +++ b/common/version.h @@ -25,7 +25,7 @@ // Build variables // these get injected during the build pipeline -#define CURRENT_VERSION "23.10.1-dev" // always append -dev to the current version for custom-builds +#define CURRENT_VERSION "23.10.2-dev" // always append -dev to the current version for custom-builds #define LOGIN_VERSION "0.8.0" #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ diff --git a/package.json b/package.json index f8782b8f09..b1dd4a343e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eqemu-server", - "version": "23.10.1", + "version": "23.10.2", "repository": { "type": "git", "url": "https://github.com/EQEmu/Server.git" From 8175ae61874cbf20d7b05102821f6f8a4f4d1c39 Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Wed, 17 Sep 2025 01:31:48 -0500 Subject: [PATCH 049/194] [Release] 23.10.3 --- CHANGELOG.md | 6 + common/version.h | 2 +- package.json | 2 +- zone/client_packet.cpp | 1260 ++++++++++++++++------------------------ zone/common.h | 60 ++ 5 files changed, 572 insertions(+), 758 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9da523f41d..7f735023c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [23.10.3] 9/16/2025 + +### Hotfix + +* Hotfix crashes occurring in #4987. @Akkadius 2025-09-17 + ## [23.10.2] 9/16/2025 ### Hotfix diff --git a/common/version.h b/common/version.h index 285e169688..c119346d45 100644 --- a/common/version.h +++ b/common/version.h @@ -25,7 +25,7 @@ // Build variables // these get injected during the build pipeline -#define CURRENT_VERSION "23.10.2-dev" // always append -dev to the current version for custom-builds +#define CURRENT_VERSION "23.10.3-dev" // always append -dev to the current version for custom-builds #define LOGIN_VERSION "0.8.0" #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ diff --git a/package.json b/package.json index b1dd4a343e..985a21c386 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eqemu-server", - "version": "23.10.2", + "version": "23.10.3", "repository": { "type": "git", "url": "https://github.com/EQEmu/Server.git" diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 441b4a5383..a059bef659 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -11080,909 +11080,657 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) LogError("Wrong size: OP_PetCommands, size=[{}], expected [{}]", app->size, sizeof(PetCommand_Struct)); return; } - - auto* s = (PetCommand_Struct*) app->pBuffer; - char val1[20] = { 0 }; + PetCommand_Struct* pet = (PetCommand_Struct*)app->pBuffer; + Mob* mypet = GetPet(); + Mob *target = entity_list.GetMob(pet->target); - Mob* pet = GetPet(); - Mob* t = entity_list.GetMob(s->target); - - if (!pet || s->command == PetCommand::Leader) { - if (s->command == PetCommand::Leader) { + if (!mypet || pet->command == PET_LEADER) { + if (pet->command == PET_LEADER) { // we either send the ID of an NPC we're interested in or no ID for our own pet - if (t) { - Mob* owner = t->GetOwner(); - if (owner) { - t->SayString(PET_LEADERIS, owner->GetCleanName()); - } else { - t->SayString(I_FOLLOW_NOONE); - } - } else if (pet) { - pet->SayString(PET_LEADERIS, GetName()); + if (target) { + auto owner = target->GetOwner(); + if (owner) + target->SayString(PET_LEADERIS, owner->GetCleanName()); + else + target->SayString(I_FOLLOW_NOONE); + } else if (mypet) { + mypet->SayString(PET_LEADERIS, GetName()); } } return; } - if (!pet->IsNPC()) { + if (mypet->GetPetType() == petTargetLock && (pet->command != PET_HEALTHREPORT && pet->command != PET_GETLOST)) return; - } - - if ( - pet->GetPetType() == PetType::TargetLock && - s->command != PetCommand::HealthReport && - s->command != PetCommand::GetLost - ) { - return; - } // just let the command "/pet get lost" work for familiars - if (pet->GetPetType() == PetType::Familiar && s->command != PetCommand::GetLost) { + if (mypet->GetPetType() == petFamiliar && pet->command != PET_GETLOST) return; - } - - const bool can_use_command = ( - (pet->GetPetType() == PetType::Animation && aabonuses.PetCommands[s->command]) || - pet->GetPetType() != PetType::Animation - ); - - switch (s->command) { - case PetCommand::Attack: { - if ( - !t || - pet->IsFeared() || - !can_use_command || - t == this || - !( - DistanceSquaredNoZ(pet->GetPosition(), GetTarget()->GetPosition()) <= - (RuleR(Pets, AttackCommandRange) * RuleR(Pets, AttackCommandRange)) - ) || - DistanceSquared(pet->GetPosition(), t->GetPosition()) >= RuleR(Aggro, PetAttackRange) - ) { - break; - } - - if (RuleB(Pets, PetsRequireLoS) && !DoLosChecks(t)) { - pet->SayString(this, NOT_LEGAL_TARGET); - break; - } - - if (t->IsMezzed()) { - MessageString(Chat::NPCQuestSay, CANNOT_WAKE, pet->GetCleanName(), t->GetCleanName()); - break; - } - if (!pet->IsAttackAllowed(t)) { - pet->SayString(this, NOT_LEGAL_TARGET); - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - pet->SetFeigned(false); - - if (pet->IsPetStop()) { - pet->SetPetStop(false); - SetPetCommandState(PetButton::Stop, PetButtonState::Off); - } - - if (pet->IsPetRegroup()) { - pet->SetPetRegroup(false); - SetPetCommandState(PetButton::Regroup, PetButtonState::Off); - } - - SetPetCommandState(PetButton::Sit, PetButtonState::Off); - - if (pet->GetPetOrder() == PetOrder::Sit || pet->GetPetOrder() == PetOrder::Feign) { - pet->SetPetOrder(pet->GetPreviousPetOrder()); - pet->SetAppearance(eaStanding); - } - - zone->AddAggroMob(); + uint32 PetCommand = pet->command; - int hate = 1; // classic acts like qattack - if (pet->IsEngaged()) { - Mob* top = pet->GetHateMost(); - if (top && top != t) { - hate += pet->GetHateAmount(top) - pet->GetHateAmount(t) + 100; - } - } + // Handle Sit/Stand toggle in UF and later. + /* + if (GetClientVersion() >= EQClientUnderfoot) + { + if (PetCommand == PET_SITDOWN) + if (mypet->GetPetOrder() == SPO_Sit) + PetCommand = PET_STANDUP; + } + */ - pet->AddToHateList(t, hate, 0, true, false, false, SPELL_UNKNOWN, true); - MessageString(Chat::PetResponse, PET_ATTACKING, pet->GetCleanName(), t->GetCleanName()); - SetTarget(t); + switch (PetCommand) + { + case PET_ATTACK: { + if (!target) break; - } - case PetCommand::QAttack: { - if ( - pet->IsFeared() || - !GetTarget() || - GetTarget() == this || - !can_use_command || - !( - DistanceSquaredNoZ(pet->GetPosition(), GetTarget()->GetPosition()) <= - (RuleR(Pets, AttackCommandRange) * RuleR(Pets, AttackCommandRange)) - ) - ) { - break; - } - if (RuleB(Pets, PetsRequireLoS) && !DoLosChecks(GetTarget())) { - pet->SayString(this, NOT_LEGAL_TARGET); - break; - } - - if (GetTarget()->IsMezzed()) { - MessageString(Chat::NPCQuestSay, CANNOT_WAKE, pet->GetCleanName(), GetTarget()->GetCleanName()); - break; - } - - if (!pet->IsAttackAllowed(GetTarget())) { - pet->SayString(this, NOT_LEGAL_TARGET); - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - pet->SetFeigned(false); - - if (pet->IsPetStop()) { - pet->SetPetStop(false); - SetPetCommandState(PetButton::Stop, PetButtonState::Off); - } - - if (pet->IsPetRegroup()) { - pet->SetPetRegroup(false); - SetPetCommandState(PetButton::Regroup, PetButtonState::Off); - } - - SetPetCommandState(PetButton::Sit, PetButtonState::Off); - - if (pet->GetPetOrder() == PetOrder::Sit || pet->GetPetOrder() == PetOrder::Feign) { - pet->SetPetOrder(pet->GetPreviousPetOrder()); - pet->SetAppearance(eaStanding); - } - - zone->AddAggroMob(); - pet->AddToHateList(GetTarget(), 1, 0, true, false, false, SPELL_UNKNOWN, true); - MessageString(Chat::PetResponse, PET_ATTACKING, pet->GetCleanName(), GetTarget()->GetCleanName()); + if (RuleB(Pets, PetsRequireLoS) && !DoLosChecks(target)) { + mypet->SayString(this, NOT_LEGAL_TARGET); break; } - case PetCommand::BackOff: { - if (pet->IsFeared() || !can_use_command) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - pet->SayString(this, Chat::PetResponse, PET_CALMING); - pet->WipeHateList(); - pet->SetTarget(nullptr); - - if (pet->IsPetStop()) { - pet->SetPetStop(false); - SetPetCommandState(PetButton::Stop, PetButtonState::Off); - } + if (target->IsMezzed()) { + MessageString(Chat::NPCQuestSay, CANNOT_WAKE, mypet->GetCleanName(), target->GetCleanName()); break; } - case PetCommand::HealthReport: { - if (!can_use_command) { - break; - } - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; + if (mypet->IsFeared()) + break; //prevent pet from attacking stuff while feared - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - MessageString(Chat::PetResponse, PET_REPORT_HP, ConvertArrayF(pet->GetHPRatio(), val1)); - pet->ShowBuffs(this); + if (!mypet->IsAttackAllowed(target)) { + mypet->SayString(this, NOT_LEGAL_TARGET); break; } - case PetCommand::GetLost: { - if (pet->Charmed()) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - if (pet->GetPetType() == PetType::Charmed) { - pet->BuffFadeByEffect(SpellEffect::Charm); - break; - } else { - SetPet(nullptr); - } - pet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); - pet->CastToNPC()->Depop(); + // default range is 200, takes Z into account + // really they do something weird where they're added to the aggro list then remove them + // and will attack if they come in range -- too lazy, lets remove exploits for now + if (DistanceSquared(mypet->GetPosition(), target->GetPosition()) >= RuleR(Aggro, PetAttackRange)) { + // they say they're attacking then remove on live ... so they don't really say anything in this case ... break; } - case PetCommand::GuardHere: { - if (pet->IsFeared() || !can_use_command) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - pet->SetFeigned(false); - SetPetCommandState(PetButton::Sit, PetButtonState::Off); - pet->SetAppearance(eaStanding); - pet->SayString(this, Chat::PetResponse, PET_GUARDINGLIFE); - pet->SetPetOrder(PetOrder::Guard); - pet->CastToNPC()->SaveGuardSpot(pet->GetPosition()); + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + if (target != this && DistanceSquared(mypet->GetPosition(), target->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { + mypet->SetFeigned(false); + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); + } + if (mypet->IsPetRegroup()) { + mypet->SetPetRegroup(false); + SetPetCommandState(PET_BUTTON_REGROUP, 0); + } - if (!pet->GetTarget()) { - pet->StopNavigation(); - } + // fix GUI sit button to be unpressed and stop sitting regen + SetPetCommandState(PET_BUTTON_SIT, 0); + if (mypet->GetPetOrder() == SPO_Sit || mypet->GetPetOrder() == SPO_FeignDeath) { + mypet->SetPetOrder(mypet->GetPreviousPetOrder()); + mypet->SetAppearance(eaStanding); + } - if (pet->IsPetStop()) { - pet->SetPetStop(false); - SetPetCommandState(PetButton::Stop, PetButtonState::Off); + zone->AddAggroMob(); + // classic acts like qattack + int hate = 1; + if (mypet->IsEngaged()) { + auto top = mypet->GetHateMost(); + if (top && top != target) + hate += mypet->GetHateAmount(top) - mypet->GetHateAmount(target) + 100; // should be enough to cause target change + } + mypet->AddToHateList(target, hate, 0, true, false, false, SPELL_UNKNOWN, true); + MessageString(Chat::PetResponse, PET_ATTACKING, mypet->GetCleanName(), target->GetCleanName()); + SetTarget(target); } - - break; } - case PetCommand::FollowMe: { - if (pet->IsFeared() || !can_use_command) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - pet->SetFeigned(false); - pet->SayString(this, Chat::PetResponse, PET_FOLLOWING); - pet->SetPetOrder(PetOrder::Follow); - SetPetCommandState(PetButton::Sit, PetButtonState::Off); - pet->SetAppearance(eaStanding); - - if (pet->IsPetStop()) { - pet->SetPetStop(false); - SetPetCommandState(PetButton::Stop, PetButtonState::Off); - } + break; + } + case PET_QATTACK: { + if (mypet->IsFeared()) + break; //prevent pet from attacking stuff while feared + if (!GetTarget()) { break; } - case PetCommand::Taunt: { - if (!can_use_command) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - MessageString(Chat::PetResponse, pet->CastToNPC()->IsTaunting() ? PET_NO_TAUNT : PET_DO_TAUNT); - pet->CastToNPC()->SetTaunting(!pet->CastToNPC()->IsTaunting()); + if (RuleB(Pets, PetsRequireLoS) && !DoLosChecks(GetTarget())) { + mypet->SayString(this, NOT_LEGAL_TARGET); break; } - case PetCommand::TauntOn: { - if (!can_use_command) { - break; - } - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - MessageString(Chat::PetResponse, PET_DO_TAUNT); - pet->CastToNPC()->SetTaunting(true); + if (GetTarget()->IsMezzed()) { + MessageString(Chat::NPCQuestSay, CANNOT_WAKE, mypet->GetCleanName(), GetTarget()->GetCleanName()); break; } - case PetCommand::TauntOff: { - if (!can_use_command) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - MessageString(Chat::PetResponse, PET_NO_TAUNT); - pet->CastToNPC()->SetTaunting(false); + if (!mypet->IsAttackAllowed(GetTarget())) { + mypet->SayString(this, NOT_LEGAL_TARGET); break; } - case PetCommand::GuardMe: { - if (pet->IsFeared() || can_use_command) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + if (GetTarget() != this && DistanceSquaredNoZ(mypet->GetPosition(), GetTarget()->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { + mypet->SetFeigned(false); + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); + } + if (mypet->IsPetRegroup()) { + mypet->SetPetRegroup(false); + SetPetCommandState(PET_BUTTON_REGROUP, 0); + } - pet->SetFeigned(false); - pet->SayString(this, Chat::PetResponse, PET_GUARDME_STRING); - pet->SetPetOrder(PetOrder::Follow); - SetPetCommandState(PetButton::Sit, PetButtonState::Off); - pet->SetAppearance(eaStanding); + // fix GUI sit button to be unpressed and stop sitting regen + SetPetCommandState(PET_BUTTON_SIT, 0); + if (mypet->GetPetOrder() == SPO_Sit || mypet->GetPetOrder() == SPO_FeignDeath) { + mypet->SetPetOrder(mypet->GetPreviousPetOrder()); + mypet->SetAppearance(eaStanding); + } - if (pet->IsPetStop()) { - pet->SetPetStop(false); - SetPetCommandState(PetButton::Stop, PetButtonState::Off); + zone->AddAggroMob(); + mypet->AddToHateList(GetTarget(), 1, 0, true, false, false, SPELL_UNKNOWN, true); + MessageString(Chat::PetResponse, PET_ATTACKING, mypet->GetCleanName(), GetTarget()->GetCleanName()); } + } + break; + } + case PET_BACKOFF: { + if (mypet->IsFeared()) break; //keeps pet running while feared + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + mypet->SayString(this, Chat::PetResponse, PET_CALMING); + mypet->WipeHateList(); + mypet->SetTarget(nullptr); + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); + } + } + break; + } + case PET_HEALTHREPORT: { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + MessageString(Chat::PetResponse, PET_REPORT_HP, ConvertArrayF(mypet->GetHPRatio(), val1)); + mypet->ShowBuffs(this); + } + break; + } + case PET_GETLOST: { + if (mypet->Charmed()) + break; + if (mypet->GetPetType() == petCharmed || !mypet->IsNPC()) { + // eqlive ignores this command + // we could just remove the charm + // and continue + mypet->BuffFadeByEffect(SpellEffect::Charm); break; } - case PetCommand::Sit: { - if (pet->IsFeared() || !can_use_command) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + else { + SetPet(nullptr); + } - pet->SetFeigned(false); - pet->SayString(this, Chat::PetResponse, PET_SIT_STRING); - pet->SetPetOrder(pet->GetPetOrder() == PetOrder::Sit ? pet->GetPreviousPetOrder() : PetOrder::Sit); - pet->SetAppearance(pet->GetPetOrder() == PetOrder::Sit ? eaStanding : eaSitting); + mypet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); + mypet->CastToNPC()->Depop(); - if (pet->GetPetOrder() != PetOrder::Sit) { - pet->SetRunAnimSpeed(0); + //Oddly, the client (Titanium) will still allow "/pet get lost" command despite me adding the code below. If someone can figure that out, you can uncomment this code and use it. + /* + if((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) { + mypet->SayString(PET_GETLOST_STRING); + mypet->CastToNPC()->Depop(); + } + */ - if (!pet->UseBardSpellLogic()) { - pet->InterruptSpell(); + break; + } + case PET_GUARDHERE: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + if (mypet->IsNPC()) { + + // Set Sit button to unpressed - send stand anim/end hpregen + mypet->SetFeigned(false); + SetPetCommandState(PET_BUTTON_SIT, 0); + mypet->SetAppearance(eaStanding); + + mypet->SayString(this, Chat::PetResponse, PET_GUARDINGLIFE); + mypet->SetPetOrder(SPO_Guard); + mypet->CastToNPC()->SaveGuardSpot(mypet->GetPosition()); + if (!mypet->GetTarget()) // want them to not twitch if they're chasing something down + mypet->StopNavigation(); + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); } } - - break; } - case PetCommand::StandUp: { - if (pet->IsFeared() || !can_use_command) { - break; - } + break; + } + case PET_FOLLOWME: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + mypet->SetFeigned(false); + mypet->SayString(this, Chat::PetResponse, PET_FOLLOWING); + mypet->SetPetOrder(SPO_Follow); - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + // fix GUI sit button to be unpressed - send stand anim/end hpregen + SetPetCommandState(PET_BUTTON_SIT, 0); + mypet->SetAppearance(eaStanding); - pet->SetFeigned(false); - pet->SayString(this, Chat::PetResponse, PET_SIT_STRING); - SetPetCommandState(PetButton::Sit, PetButtonState::Off); - pet->SetPetOrder(pet->GetPreviousPetOrder()); - pet->SetAppearance(eaStanding); - break; + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); + } } - case PetCommand::SitDown: { - if (pet->IsFeared() || !can_use_command) { - break; + break; + } + case PET_TAUNT: { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + if (mypet->CastToNPC()->IsTaunting()) + { + MessageString(Chat::PetResponse, PET_NO_TAUNT); + mypet->CastToNPC()->SetTaunting(false); } + else + { + MessageString(Chat::PetResponse, PET_DO_TAUNT); + mypet->CastToNPC()->SetTaunting(true); + } + } + break; + } + case PET_TAUNT_ON: { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + MessageString(Chat::PetResponse, PET_DO_TAUNT); + mypet->CastToNPC()->SetTaunting(true); + } + break; + } + case PET_TAUNT_OFF: { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + MessageString(Chat::PetResponse, PET_NO_TAUNT); + mypet->CastToNPC()->SetTaunting(false); + } + break; + } + case PET_GUARDME: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + mypet->SetFeigned(false); + mypet->SayString(this, Chat::PetResponse, PET_GUARDME_STRING); + mypet->SetPetOrder(SPO_Follow); - pet->SetFeigned(false); - pet->SayString(this, Chat::PetResponse, PET_SIT_STRING); - SetPetCommandState(PetButton::Sit, PetButtonState::On); - pet->SetPetOrder(PetOrder::Sit); - pet->SetRunAnimSpeed(0); + // Set Sit button to unpressed - send stand anim/end hpregen + SetPetCommandState(PET_BUTTON_SIT, 0); + mypet->SetAppearance(eaStanding); - if (!pet->UseBardSpellLogic()){ - pet->InterruptSpell(); + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); } - - pet->SetAppearance(eaSitting); - break; } - case PetCommand::Hold: { - if (!aabonuses.PetCommands[s->command]) { - break; - } + break; + } + case PET_SIT: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + if (mypet->GetPetOrder() == SPO_Sit) + { + mypet->SetFeigned(false); + mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING); + mypet->SetPetOrder(mypet->GetPreviousPetOrder()); + mypet->SetAppearance(eaStanding); + } + else + { + mypet->SetFeigned(false); + mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING); + mypet->SetPetOrder(SPO_Sit); + mypet->SetRunAnimSpeed(0); + if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet + mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting + mypet->SetAppearance(eaSitting); + } + } + break; + } + case PET_STANDUP: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + mypet->SetFeigned(false); + mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING); + SetPetCommandState(PET_BUTTON_SIT, 0); + mypet->SetPetOrder(mypet->GetPreviousPetOrder()); + mypet->SetAppearance(eaStanding); + } + break; + } + case PET_SITDOWN: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if (pet->IsHeld()) { - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + mypet->SetFeigned(false); + mypet->SayString(this, Chat::PetResponse, PET_SIT_STRING); + SetPetCommandState(PET_BUTTON_SIT, 1); + mypet->SetPetOrder(SPO_Sit); + mypet->SetRunAnimSpeed(0); + if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet + mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting + mypet->SetAppearance(eaSitting); + } + break; + } + case PET_HOLD: { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { + if (mypet->IsHeld()) + { + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) MessageString(Chat::PetResponse, PET_HOLD_SET_OFF); - } - - pet->SetHeld(false); - } else { - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { + mypet->SetHeld(false); + } + else + { + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) MessageString(Chat::PetResponse, PET_HOLD_SET_ON); - } - if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { - pet->SayString(this, Chat::PetResponse, PET_NOW_HOLDING); - } else { - pet->SayString(this, Chat::PetResponse, PET_ON_HOLD); - } + if (m_ClientVersionBit & EQ::versions::maskUFAndLater) + mypet->SayString(this, Chat::PetResponse, PET_NOW_HOLDING); + else + mypet->SayString(this, Chat::PetResponse, PET_ON_HOLD); - pet->SetHeld(true); + mypet->SetHeld(true); } - - pet->SetGHeld(false); - SetPetCommandState(PetButton::GreaterHold, PetButtonState::Off); - break; + mypet->SetGHeld(false); + SetPetCommandState(PET_BUTTON_GHOLD, 0); } - case PetCommand::HoldOn: { - if (!pet->IsHeld() || !aabonuses.PetCommands[s->command]) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { + break; + } + case PET_HOLD_ON: { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && !mypet->IsHeld()) { + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) MessageString(Chat::PetResponse, PET_HOLD_SET_ON); - } - if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { - pet->SayString(this, Chat::PetResponse, PET_NOW_HOLDING); - } else { - pet->SayString(this, Chat::PetResponse, PET_ON_HOLD); - } - - pet->SetHeld(true); - pet->SetGHeld(false); - SetPetCommandState(PetButton::GreaterHold, PetButtonState::Off); - break; + if (m_ClientVersionBit & EQ::versions::maskUFAndLater) + mypet->SayString(this, Chat::PetResponse, PET_NOW_HOLDING); + else + mypet->SayString(this, Chat::PetResponse, PET_ON_HOLD); + mypet->SetHeld(true); + mypet->SetGHeld(false); + SetPetCommandState(PET_BUTTON_GHOLD, 0); } - case PetCommand::HoldOff: { - if (!pet->IsHeld() || !aabonuses.PetCommands[s->command]) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { + break; + } + case PET_HOLD_OFF: { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsHeld()) { + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) MessageString(Chat::PetResponse, PET_HOLD_SET_OFF); - } - - pet->SetHeld(false); - break; + mypet->SetHeld(false); } - case PetCommand::GreaterHold: { - if (!aabonuses.PetCommands[s->command]) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - if (pet->IsGHeld()) { - if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { + break; + } + case PET_GHOLD: { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { + if (mypet->IsGHeld()) + { + if (m_ClientVersionBit & EQ::versions::maskUFAndLater) MessageString(Chat::PetResponse, PET_OFF_GHOLD); - } - - pet->SetGHeld(false); - } else { + mypet->SetGHeld(false); + } + else + { if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { MessageString(Chat::PetResponse, PET_ON_GHOLD); - pet->SayString(this, Chat::PetResponse, PET_GHOLD_ON_MSG); + mypet->SayString(this, Chat::PetResponse, PET_GHOLD_ON_MSG); } else { - pet->SayString(this, Chat::PetResponse, PET_ON_HOLD); + mypet->SayString(this, Chat::PetResponse, PET_ON_HOLD); } - - pet->SetGHeld(true); + mypet->SetGHeld(true); } - - pet->SetHeld(false); - SetPetCommandState(PetButton::Hold, PetButtonState::Off); - break; + mypet->SetHeld(false); + SetPetCommandState(PET_BUTTON_HOLD, 0); } - case PetCommand::GreaterHoldOn: { - if (!aabonuses.PetCommands[s->command]) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - + break; + } + case PET_GHOLD_ON: { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { MessageString(Chat::PetResponse, PET_ON_GHOLD); - pet->SayString(this, Chat::PetResponse, PET_GHOLD_ON_MSG); + mypet->SayString(this, Chat::PetResponse, PET_GHOLD_ON_MSG); } else { - pet->SayString(this, Chat::PetResponse, PET_ON_HOLD); + mypet->SayString(this, Chat::PetResponse, PET_ON_HOLD); } - - pet->SetGHeld(true); - pet->SetHeld(false); - SetPetCommandState(PetButton::Hold, PetButtonState::Off); - break; + mypet->SetGHeld(true); + mypet->SetHeld(false); + SetPetCommandState(PET_BUTTON_HOLD, 0); } - case PetCommand::GreaterHoldOff: { - if (!pet->IsGHeld() || !aabonuses.PetCommands[s->command]) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - if (m_ClientVersionBit & EQ::versions::maskUFAndLater) { + break; + } + case PET_GHOLD_OFF: { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsGHeld()) { + if (m_ClientVersionBit & EQ::versions::maskUFAndLater) MessageString(Chat::PetResponse, PET_OFF_GHOLD); - } - - pet->SetGHeld(false); - break; + mypet->SetGHeld(false); } - case PetCommand::SpellHold: { - if (pet->IsFeared() || !aabonuses.PetCommands[s->command]) { + break; + } + case PET_SPELLHOLD: { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { + if (mypet->IsFeared()) break; + if (mypet->IsNoCast()) { + MessageString(Chat::PetResponse, PET_CASTING); + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) + MessageString(Chat::PetResponse, PET_SPELLHOLD_SET_OFF); + mypet->SetNoCast(false); } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - MessageString(Chat::PetResponse, pet->IsNoCast() ? PET_CASTING : PET_NOT_CASTING); - - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { - MessageString(Chat::PetResponse, pet->IsNoCast() ? PET_SPELLHOLD_SET_OFF : PET_SPELLHOLD_SET_ON); + else { + MessageString(Chat::PetResponse, PET_NOT_CASTING); + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) + MessageString(Chat::PetResponse, PET_SPELLHOLD_SET_ON); + mypet->SetNoCast(true); } - - pet->SetNoCast(!pet->IsNoCast()); - break; } - case PetCommand::SpellHoldOn: { - if (pet->IsFeared() || pet->IsNoCast() || !aabonuses.PetCommands[s->command]) { + break; + } + case PET_SPELLHOLD_ON: { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { + if (mypet->IsFeared()) break; + if (!mypet->IsNoCast()) { + MessageString(Chat::PetResponse, PET_NOT_CASTING); + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) + MessageString(Chat::PetResponse, PET_SPELLHOLD_SET_ON); + mypet->SetNoCast(true); } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - MessageString(Chat::PetResponse, PET_NOT_CASTING); - - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { - MessageString(Chat::PetResponse, PET_SPELLHOLD_SET_ON); - } - - pet->SetNoCast(true); - break; } - case PetCommand::SpellHoldOff: { - if (pet->IsFeared() || !pet->IsNoCast() || !aabonuses.PetCommands[s->command]) { + break; + } + case PET_SPELLHOLD_OFF: { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { + if (mypet->IsFeared()) break; + if (mypet->IsNoCast()) { + MessageString(Chat::PetResponse, PET_CASTING); + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) + MessageString(Chat::PetResponse, PET_SPELLHOLD_SET_OFF); + mypet->SetNoCast(false); } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - MessageString(Chat::PetResponse, PET_CASTING); - - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { - MessageString(Chat::PetResponse, PET_SPELLHOLD_SET_OFF); - } - - pet->SetNoCast(false); - break; } - case PetCommand::Focus: { - if (pet->IsFeared() || !aabonuses.PetCommands[s->command]) { + break; + } + case PET_FOCUS: { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { + if (mypet->IsFeared()) break; + if (mypet->IsFocused()) { + MessageString(Chat::PetResponse, PET_NOT_FOCUSING); + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) + MessageString(Chat::PetResponse, PET_FOCUS_SET_OFF); + mypet->SetFocused(false); } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - MessageString(Chat::PetResponse, pet->IsFocused() ? PET_NOT_FOCUSING : PET_NOW_FOCUSING); - - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { - MessageString(Chat::PetResponse, pet->IsFocused() ? PET_FOCUS_SET_OFF : PET_FOCUS_SET_ON); + else { + MessageString(Chat::PetResponse, PET_NOW_FOCUSING); + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) + MessageString(Chat::PetResponse, PET_FOCUS_SET_ON); + mypet->SetFocused(true); } - - pet->SetFocused(!pet->IsFocused()); - break; } - case PetCommand::FocusOn: { - if (pet->IsFeared() || pet->IsFocused() || !aabonuses.PetCommands[s->command]) { + break; + } + case PET_FOCUS_ON: { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { + if (mypet->IsFeared()) break; + if (!mypet->IsFocused()) { + MessageString(Chat::PetResponse, PET_NOW_FOCUSING); + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) + MessageString(Chat::PetResponse, PET_FOCUS_SET_ON); + mypet->SetFocused(true); } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - MessageString(Chat::PetResponse, PET_NOW_FOCUSING); - - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { - MessageString(Chat::PetResponse, PET_FOCUS_SET_ON); - } - - pet->SetFocused(true); - break; } - case PetCommand::FocusOff: { - if (pet->IsFeared() || !pet->IsFocused() || !aabonuses.PetCommands[s->command]) { + break; + } + case PET_FOCUS_OFF: { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { + if (mypet->IsFeared()) break; + if (mypet->IsFocused()) { + MessageString(Chat::PetResponse, PET_NOT_FOCUSING); + if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) + MessageString(Chat::PetResponse, PET_FOCUS_SET_OFF); + mypet->SetFocused(false); } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - MessageString(Chat::PetResponse, PET_NOT_FOCUSING); - - if (m_ClientVersionBit & EQ::versions::maskSoDAndLater) { - MessageString(Chat::PetResponse, PET_FOCUS_SET_OFF); - } - - pet->SetFocused(false); - break; } - case PetCommand::Feign: { - if (pet->IsFeared() || !aabonuses.PetCommands[s->command]) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; + break; + } - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + case PET_FEIGN: { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { + if (mypet->IsFeared()) + break; - if (zone->random.Int(0, 99) > aabonuses.FeignedMinionChance) { - pet->SetFeigned(false); - entity_list.MessageCloseString(this, false, 200, 10, STRING_FEIGNFAILED, pet->GetCleanName()); - } else { - pet->SetSpecialAbility(SpecialAbility::AggroImmunity, 1); - pet->WipeHateList(); - pet->SetPetOrder(PetOrder::Feign); - pet->SetRunAnimSpeed(0); - pet->StopNavigation(); - pet->SetAppearance(eaDead); - pet->SetFeigned(true); - pet->SetTarget(nullptr); - - if (!pet->UseBardSpellLogic()) { - pet->InterruptSpell(); + int pet_fd_chance = aabonuses.FeignedMinionChance; + if (zone->random.Int(0, 99) > pet_fd_chance) { + mypet->SetFeigned(false); + entity_list.MessageCloseString(this, false, 200, 10, STRING_FEIGNFAILED, mypet->GetCleanName()); + } + else { + bool has_aggro_immunity = GetSpecialAbility(SpecialAbility::AggroImmunity); + mypet->SetSpecialAbility(SpecialAbility::AggroImmunity, 1); + mypet->WipeHateList(); + mypet->SetPetOrder(SPO_FeignDeath); + mypet->SetRunAnimSpeed(0); + mypet->StopNavigation(); + mypet->SetAppearance(eaDead); + mypet->SetFeigned(true); + mypet->SetTarget(nullptr); + if (!mypet->UseBardSpellLogic()) { + mypet->InterruptSpell(); } - if (!GetSpecialAbility(SpecialAbility::AggroImmunity)) { - pet->SetSpecialAbility(SpecialAbility::AggroImmunity, 0); + if (!has_aggro_immunity) { + mypet->SetSpecialAbility(SpecialAbility::AggroImmunity, 0); } } - - break; } - case PetCommand::Stop: { - if (pet->IsFeared() || !can_use_command) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + break; + } + case PET_STOP: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if (pet->IsPetStop()) { - pet->SetPetStop(false); + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); } else { - pet->SetPetStop(true); - pet->StopNavigation(); - pet->SetTarget(nullptr); - - if (pet->IsPetRegroup()) { - pet->SetPetRegroup(false); - SetPetCommandState(PetButton::Regroup, PetButtonState::Off); + mypet->SetPetStop(true); + mypet->StopNavigation(); + mypet->SetTarget(nullptr); + if (mypet->IsPetRegroup()) { + mypet->SetPetRegroup(false); + SetPetCommandState(PET_BUTTON_REGROUP, 0); } } - - pet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); - break; + mypet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); } - case PetCommand::StopOn: { - if (pet->IsFeared() || pet->IsPetStop() || !can_use_command) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - pet->SetPetStop(true); - pet->StopNavigation(); - pet->SetTarget(nullptr); - pet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); + break; + } + case PET_STOP_ON: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if (pet->IsPetRegroup()) { - pet->SetPetRegroup(false); - SetPetCommandState(PetButton::Regroup, PetButtonState::Off); + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + mypet->SetPetStop(true); + mypet->StopNavigation(); + mypet->SetTarget(nullptr); + mypet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); + if (mypet->IsPetRegroup()) { + mypet->SetPetRegroup(false); + SetPetCommandState(PET_BUTTON_REGROUP, 0); } - - break; } - case PetCommand::StopOff: { - if (pet->IsFeared() || !pet->IsPetStop() || !can_use_command) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + break; + } + case PET_STOP_OFF: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - pet->SetPetStop(false); - pet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); - break; + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + mypet->SetPetStop(false); + mypet->SayString(this, Chat::PetResponse, PET_GETLOST_STRING); } - case PetCommand::Regroup: { - if (pet->IsFeared() || !aabonuses.PetCommands[s->command]) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + break; + } + case PET_REGROUP: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if (pet->IsPetRegroup()) { - pet->SetPetRegroup(false); - pet->SayString(this, Chat::PetResponse, PET_OFF_REGROUPING); + if (aabonuses.PetCommands[PetCommand]) { + if (mypet->IsPetRegroup()) { + mypet->SetPetRegroup(false); + mypet->SayString(this, Chat::PetResponse, PET_OFF_REGROUPING); } else { - pet->SetPetRegroup(true); - pet->SetTarget(nullptr); - pet->SayString(this, Chat::PetResponse, PET_ON_REGROUPING); - - if (pet->IsPetStop()) { - pet->SetPetStop(false); - SetPetCommandState(PetButton::Stop, PetButtonState::Off); + mypet->SetPetRegroup(true); + mypet->SetTarget(nullptr); + mypet->SayString(this, Chat::PetResponse, PET_ON_REGROUPING); + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); } } - - break; } - case PetCommand::RegroupOn: { - if (pet->IsFeared() || pet->IsPetRegroup() || !aabonuses.PetCommands[s->command]) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); - - pet->SetPetRegroup(true); - pet->SetTarget(nullptr); - pet->SayString(this, Chat::PetResponse, PET_ON_REGROUPING); + break; + } + case PET_REGROUP_ON: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if (pet->IsPetStop()) { - pet->SetPetStop(false); - SetPetCommandState(PetButton::Stop, PetButtonState::Off); + if (aabonuses.PetCommands[PetCommand]) { + mypet->SetPetRegroup(true); + mypet->SetTarget(nullptr); + mypet->SayString(this, Chat::PetResponse, PET_ON_REGROUPING); + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); } - - break; } - case PetCommand::RegroupOff: { - if (pet->IsFeared() || !pet->IsPetRegroup() || !aabonuses.PetCommands[s->command]) { - break; - } - - std::function f = [&s]() { - return PetCommand::GetName(s->command); - }; - - parse->EventMob(EVENT_PET_COMMAND, pet, CastToMob(), f, s->command); - parse->EventMob(EVENT_PET_COMMAND, CastToMob(), pet, f, s->command); + break; + } + case PET_REGROUP_OFF: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - pet->SetPetRegroup(false); - pet->SayString(this, Chat::PetResponse, PET_OFF_REGROUPING); - break; - } - default: { - LogError("[{}] attempted to use an unknown pet command: [{}]", GetCleanName(), s->command); - break; + if (aabonuses.PetCommands[PetCommand]) { + mypet->SetPetRegroup(false); + mypet->SayString(this, Chat::PetResponse, PET_OFF_REGROUPING); } + break; + } + default: + printf("Client attempted to use a unknown pet command:\n"); + break; } } - void Client::Handle_OP_Petition(const EQApplicationPacket *app) { if (app->size <= 1) diff --git a/zone/common.h b/zone/common.h index 4c187566d5..6a11f7255f 100644 --- a/zone/common.h +++ b/zone/common.h @@ -854,6 +854,66 @@ struct DataBucketCache uint32_t bucket_expires; }; +// Defines based on the RoF2 Client +#define PET_HEALTHREPORT 0 // 0x00 - /pet health or Pet Window +#define PET_LEADER 1 // 0x01 - /pet leader or Pet Window +#define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window +#define PET_QATTACK 3 // 0x03 - /pet qattack or Pet Window +#define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window +#define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window +#define PET_SIT 6 // 0x06 - /pet sit or Pet Window +#define PET_SITDOWN 7 // 0x07 - /pet sit on +#define PET_STANDUP 8 // 0x08 - /pet sit off +#define PET_STOP 9 // 0x09 - /pet stop or Pet Window - Not implemented +#define PET_STOP_ON 10 // 0x0a - /pet stop on - Not implemented +#define PET_STOP_OFF 11 // 0x0b - /pet stop off - Not implemented +#define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window +#define PET_TAUNT_ON 13 // 0x0d - /pet taunt on +#define PET_TAUNT_OFF 14 // 0x0e - /pet taunt off +#define PET_HOLD 15 // 0x0f - /pet hold or Pet Window, won't add to hate list unless attacking +#define PET_HOLD_ON 16 // 0x10 - /pet hold on +#define PET_HOLD_OFF 17 // 0x11 - /pet hold off +#define PET_GHOLD 18 // 0x12 - /pet ghold, will never add to hate list unless told to +#define PET_GHOLD_ON 19 // 0x13 - /pet ghold on +#define PET_GHOLD_OFF 20 // 0x14 - /pet ghold off +#define PET_SPELLHOLD 21 // 0x15 - /pet no cast or /pet spellhold or Pet Window +#define PET_SPELLHOLD_ON 22 // 0x16 - /pet spellhold on +#define PET_SPELLHOLD_OFF 23 // 0x17 - /pet spellhold off +#define PET_FOCUS 24 // 0x18 - /pet focus or Pet Window +#define PET_FOCUS_ON 25 // 0x19 - /pet focus on +#define PET_FOCUS_OFF 26 // 0x1a - /pet focus off +#define PET_FEIGN 27 // 0x1b - /pet feign +#define PET_BACKOFF 28 // 0x1c - /pet back off +#define PET_GETLOST 29 // 0x1d - /pet get lost +#define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client /pet target in modern clients but doesn't send packet +#define PET_REGROUP 31 // 0x1f - /pet regroup, acts like classic hold. Stops attack and moves back to guard/you but doesn't clear hate list +#define PET_REGROUP_ON 32 // 0x20 - /pet regroup on, turns on regroup +#define PET_REGROUP_OFF 33 // 0x21 - /pet regroup off, turns off regroup +#define PET_MAXCOMMANDS PET_REGROUP_OFF + 1 + +// can change the state of these buttons with a packet +#define PET_BUTTON_SIT 0 +#define PET_BUTTON_STOP 1 +#define PET_BUTTON_REGROUP 2 +#define PET_BUTTON_FOLLOW 3 +#define PET_BUTTON_GUARD 4 +#define PET_BUTTON_TAUNT 5 +#define PET_BUTTON_HOLD 6 +#define PET_BUTTON_GHOLD 7 +#define PET_BUTTON_FOCUS 8 +#define PET_BUTTON_SPELLHOLD 9 + +enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard, SPO_FeignDeath }; + +typedef enum { + petFamiliar, //only listens to /pet get lost + petAnimation, //does not listen to any commands + petOther, + petCharmed, + petNPCFollow, + petTargetLock, //remain active as long something is on the hatelist. Don't listen to any commands + petNone = 0xFF // not a pet +} PetTypeOld; #endif From ecc0d4b5c0b36a47a585aaabd40c2ebce946e038 Mon Sep 17 00:00:00 2001 From: Exonintrendo Date: Thu, 16 Oct 2025 13:22:49 -0400 Subject: [PATCH 050/194] updated crash report url to new hosted spire location (#5024) --- common/crash.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/crash.cpp b/common/crash.cpp index 968a7c5ff3..b7dcac7a47 100644 --- a/common/crash.cpp +++ b/common/crash.cpp @@ -23,7 +23,7 @@ void SendCrashReport(const std::string &crash_report) { // can configure multiple endpoints if need be std::vector endpoints = { - "https://spire.akkadius.com/api/v1/analytics/server-crash-report", + "https://spire.eqemu.dev/api/v1/analytics/server-crash-report", // "http://localhost:3010/api/v1/analytics/server-crash-report", // development }; From eb4e7d694c8c89ebcf1f8b0489e0f311206546e8 Mon Sep 17 00:00:00 2001 From: Jordan Conner <321j.con@gmail.com> Date: Thu, 23 Oct 2025 01:37:37 -0400 Subject: [PATCH 051/194] Update client.cpp HandleEnterWorldPacket for UCS Local Address (#5020) world/client.cpp's EnterWorld will correctly serve a LAN client the eqemu_config.json.world.localaddress based off IsLocalClient. It will then serve a non-LAN client the world.address value. This concept needs to be applied to UCS as that system also receives direct client connections. Inside world/client.cpp HandleEnterWorldPacket is where world sends the client info about UCS connection. This fix specifically handles the issue when you have a server on LAN and want to connect to it via another LAN computer + you have external clients. --- world/client.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/world/client.cpp b/world/client.cpp index a2d35a4852..674d096399 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1019,8 +1019,16 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { break; } + std::string ucs_addr = config->GetUCSHost(); + if (cle && cle->IsLocalClient()) { + const char* local_addr = config->LocalAddress.c_str(); + if (local_addr[0]) { + ucs_addr = local_addr; + } + } + buffer = fmt::format("{},{},{}.{},{}{:08X}", - config->GetUCSHost(), + ucs_addr, config->GetUCSPort(), config->ShortName, GetCharName(), @@ -1046,7 +1054,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { } buffer = fmt::format("{},{},{}.{},{}{:08X}", - config->GetUCSHost(), + ucs_addr, config->GetUCSPort(), config->ShortName, GetCharName(), From f74efcaa5f5f6662eaee46844b117e21f08cc5fa Mon Sep 17 00:00:00 2001 From: Vayle <76063792+Valorith@users.noreply.github.com> Date: Thu, 23 Oct 2025 01:50:00 -0400 Subject: [PATCH 052/194] [Bug Fix] Enhance SummonItemIntoInventory() to support stacking of items (#5022) * Initial plan * Initial plan * Enhance SummonItemIntoInventory to support stacking Co-authored-by: Valorith <76063792+Valorith@users.noreply.github.com> * Update .gitignore * Revert "Update .gitignore" This reverts commit 16159398d8a69c53a719a1d54d068bbe0fa5284c. * Disable PCH for patch sources compiled with -O0 Disables precompiled headers for specific patch source files that are compiled with -O0 on UNIX. This avoids Clang errors caused by __OPTIMIZE__ macro state mismatches between the PCH and translation units. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- common/CMakeLists.txt | 5 +++++ zone/inventory.cpp | 44 ++++++++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 1a9028eb7a..45af7b94dc 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -842,6 +842,11 @@ ENDIF (UNIX) IF (EQEMU_BUILD_PCH) TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/std-pch.h) + # Avoid PCH/__OPTIMIZE__ mismatch when compiling certain patch sources with -O0 + # These files are compiled with -O0 on UNIX (see COMPILE_FLAGS above), which + # disables the __OPTIMIZE__ predefined macro. Disabling PCH for them prevents + # Clang from erroring due to macro state differences between the PCH and TU. + SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES SKIP_PRECOMPILE_HEADERS ON) ENDIF () SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 1c2b62c4f8..847368d1b8 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -4607,26 +4607,32 @@ void Client::SummonItemIntoInventory( return; } - const bool is_arrow = inst->GetItem()->ItemType == EQ::item::ItemTypeArrow; - const int16 slot_id = m_inv.FindFreeSlot( - inst->IsClassBag(), - true, - inst->GetItem()->Size, - is_arrow - ); + // Try stacking first if the item is stackable, then fall back to finding a free slot + if (!PutItemInInventoryWithStacking(inst)) { + // PutItemInInventoryWithStacking failed, fall back to original behavior + const bool is_arrow = inst->GetItem()->ItemType == EQ::item::ItemTypeArrow; + const int16 slot_id = m_inv.FindFreeSlot( + inst->IsClassBag(), + true, + inst->GetItem()->Size, + is_arrow + ); - SummonItem( - item_id, - charges, - aug1, - aug2, - aug3, - aug4, - aug5, - aug6, - is_attuned, - slot_id - ); + SummonItem( + item_id, + charges, + aug1, + aug2, + aug3, + aug4, + aug5, + aug6, + is_attuned, + slot_id + ); + } + + safe_delete(inst); } bool Client::HasItemOnCorpse(uint32 item_id) From c611a25385bfe5df90878e8eea143fe170ee5c84 Mon Sep 17 00:00:00 2001 From: m0th <43860202+m0th-omens@users.noreply.github.com> Date: Thu, 30 Oct 2025 01:22:23 -0400 Subject: [PATCH 053/194] Dev Container Overhaul (#5023) * Cleanup & Reorganize Makefile for Dev Containers * Fix Makefile & misc fixes --------- Co-authored-by: m0th <43860202+m0th@users.noreply.github.com> --- .devcontainer/.gitignore | 11 +- .devcontainer/Makefile | 318 +++++++++++++------------------- .devcontainer/devcontainer.json | 35 +++- .vscode/settings.json | 25 --- CMakePresets.json | 49 +++++ tests/cppunit/CMakeLists.txt | 2 +- 6 files changed, 219 insertions(+), 221 deletions(-) create mode 100644 CMakePresets.json diff --git a/.devcontainer/.gitignore b/.devcontainer/.gitignore index a58f289c30..cdb408d2d7 100644 --- a/.devcontainer/.gitignore +++ b/.devcontainer/.gitignore @@ -1,6 +1,5 @@ -!Makefile -base/*.sql -base/*.zip -base/db/ -base/maps/ -!base/expansion/Makefile +base/ +!base/*.json +override/ +repo/ +cache/ diff --git a/.devcontainer/Makefile b/.devcontainer/Makefile index 53f06232c9..65bda74af0 100644 --- a/.devcontainer/Makefile +++ b/.devcontainer/Makefile @@ -1,196 +1,127 @@ +# Build binaries: make cmake, make build +# One time initial setup (or to reset db): make prep, make inject-mariadb, make maps +# Update custom db edits: make inject-custom +# Start up server: make shared, make login, make world, make zone +# in game, stop combat spam #logs set gmsay 79 0 +# in game, stop loot spam #logs set gmsay 69 0 NAME := eqemu-server -.ONESHELL: -DOCKER_ARGS := --rm --name ${NAME} -v $$PWD:/src -w /src ${NAME} -DOCKER_ARM64_ARGS := --rm --platform linux/arm64 --name ${NAME}-arm64 -v $$PWD:/src -w /src ${NAME}-arm64 - -.PHONY: build -build: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile build --no-print-directory - exit -endif - cd build$$BUILD_SUFFIX && cmake --build . --config Release --target all -- - -.PHONY: cmake -cmake: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile cmake --no-print-directory - exit -endif - @echo "working directory: $$PWD" - mkdir -p build$$BUILD_SUFFIX - @cd build$$BUILD_SUFFIX && cmake -DEQEMU_BUILD_LOGIN=ON \ - -DEQEMU_BUILD_TESTS=ON \ - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -G Ninja .. - -clean: -ifneq (,$(findstring .devcontainer,$$PWD)) - @make -C ../ -f .devcontainer/Makefile clean --no-print-directory -endif - rm -rf build - -docker-cmake: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile docker-cmake --no-print-directory - exit -endif - @echo "working directory: $$PWD" - git submodule update --init --recursive - docker run ${DOCKER_ARGS} make cmake - -docker-build: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile docker-build --no-print-directory - exit -endif - docker run ${DOCKER_ARGS} make build - -# Build image if it doesn't exist -docker-image-build: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile docker-image-build --no-print-directory - exit -endif -ifeq ($(shell docker images -q ${NAME} 2> /dev/null),) - @echo "Docker image not found. Building..." - docker build -f Dockerfile.debian.dev -t ${NAME} . -endif - -docker-arm-cmake: docker-arm-image-build -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile docker-arm-cmake --no-print-directory - exit -endif - git submodule update --init --recursive - docker run ${DOCKER_ARM64_ARGS} make cmake BUILD_SUFFIX=arm64 +.PHONY: prep +prep: is-vscode + @echo "Preparing build/bin for usage..." -docker-arm-build: docker-arm-image-build -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile docker-arm-build --no-print-directory - exit -endif - docker run ${DOCKER_ARM64_ARGS} make build BUILD_SUFFIX=arm64 + @echo "Prepping folders..." + @mkdir -p .devcontainer/override + @mkdir -p .devcontainer/repo + @mkdir -p .devcontainer/cache + @mkdir -p build/bin/logs + @mkdir -p build/bin/shared + @mkdir -p build/bin/assets + + @echo "Applying overrides..." + @if [ ! -f .devcontainer/override/eqemu_config.json ]; then cp .devcontainer/base/eqemu_config.json .devcontainer/override/eqemu_config.json; fi + @if [ -f build/bin/eqemu_config.json ]; then unlink build/bin/eqemu_config.json; fi + cd build/bin && ln -s ../../.devcontainer/override/eqemu_config.json eqemu_config.json + @if [ ! -f .devcontainer/override/login.json ]; then cp .devcontainer/base/login.json .devcontainer/override/login.json; fi + @if [ -f build/bin/login.json ]; then unlink build/bin/login.json; fi + cd build/bin && ln -s ../../.devcontainer/override/login.json login.json + + @echo "Cloning repositories..." + cd .devcontainer/repo && if [ ! -d "quests" ]; then cd ../../.devcontainer/repo/ && git clone https://github.com/ProjectEQ/projecteqquests.git quests; fi + cd .devcontainer/repo && if [ ! -d "eqemu-definitions" ]; then cd ../../.devcontainer/repo/ && git clone https://github.com/xackery/eqemu-definitions.git eqemu-definitions; fi + cd .devcontainer/repo && if [ ! -d "maps" ]; then cd ../../ && make maps; fi + @if [ -d build/bin/quests ]; then unlink build/bin/quests; fi + cd build/bin && ln -s ../../.devcontainer/repo/quests quests + @if [ -d build/bin/maps ]; then unlink build/bin/maps; fi + cd build/bin && ln -s ../../.devcontainer/repo/maps maps + @if [ -d build/bin/eqemu-definitions ]; then unlink build/bin/eqemu-definitions; fi + cd build/bin && ln -s ../../.devcontainer/repo/eqemu-definitions eqemu-definitions + @mkdir -p build/bin/quests/mods + + @echo "Applying base links..." + cp -R -u -p utils/patches .devcontainer/base/ + @if [ -d build/bin/assets/patches ]; then unlink build/bin/assets/patches; fi + cd build/bin/assets && ln -s ../../../.devcontainer/base/patches patches + @if [ -d build/bin/lua_modules ]; then unlink build/bin/lua_modules; fi + cd build/bin && ln -s ../../.devcontainer/repo/quests/lua_modules lua_modules + @if [ -d build/bin/mods ]; then unlink build/bin/mods; fi + cd build/bin && ln -s ../../.devcontainer/repo/quests/mods mods + @if [ -d build/bin/plugins ]; then unlink build/bin/plugins; fi + cd build/bin && ln -s ../../.devcontainer/repo/quests/plugins plugins -docker-arm-image-build: -ifeq ($(shell docker images -q ${NAME}-arm64 2> /dev/null),) - @echo "Docker image not found. Building..." - docker build -f Dockerfile.debian.arm.dev -t ${NAME}-arm64 . -endif + @echo "Eqemu is prepared. Edit build/bin/eqemu_config.json to configure." -docker-clean: clean +is-vscode: + @if [ -z "$$REMOTE_CONTAINERS" ]; then \ + echo "Not running in VS Code devcontainer"; \ + exit 1; \ + fi -.PHONY: prep -prep: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile prep --no-print-directory - exit -endif - @echo "Preparing build/bin for usage..." - mkdir -p build/bin/assets/patches - cp -R -u -p .devcontainer/base/eqemu_config.json build/bin/eqemu_config.json - cp -R -u -p .devcontainer/base/login.json build/bin/login.json - cp -R -u -p loginserver/login_util/* build/bin/assets/patches/ - mkdir -p build/bin/assets - cp -R -u -p utils/patches build/bin/assets/ - -unlink build/bin/lua_modules - cd build/bin && ln -s quests/lua_modules lua_modules - -unlink build/bin/mods - cd build/bin && ln -s quests/mods mods - -unlink build/bin/maps - cd build/bin && ln -s ../../base/maps maps - mkdir -p build/bin/logs - mkdir -p build/bin/shared - @echo "Eqemu is prepared. Edit build/bin/eqemu_config.json to configure." +clean: is-vscode + rm -rf build -maps: +.PHONY: maps +maps: is-vscode @echo "Downloading maps..." - @mkdir -p base/maps - @cd base/maps && wget -nc https://github.com/Akkadius/eqemu-maps/archive/refs/heads/master.zip - @cd base/maps && unzip -o master.zip - @cd base/maps && mv eqemu-maps-master/* . - @cd base/maps && rm -rf eqemu-maps-master + @mkdir -p .devcontainer/repo/maps + @cd .devcontainer/repo/maps && wget -nc https://github.com/EQEmu/maps/archive/refs/heads/master.zip + @cd .devcontainer/repo/maps && unzip -o master.zip + @cd .devcontainer/repo/maps && mv maps-master/* . + @cd .devcontainer/repo/maps && rm -rf maps-master @echo "Maps downloaded." -quests: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile quests --no-print-directory - exit -endif - @cd build/bin && git clone https://github.com/ProjectEQ/projecteqquests.git quests - # Runs tests .PHONY: test -test: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile test --no-print-directory - exit -endif +test: is-vscode cd build/bin && ./tests # Runs login binary .PHONY: login -login: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile login --no-print-directory - exit -endif +login: is-vscode check-mariadb cd build/bin && ./loginserver +.PHONY: hotfix +hotfix: shared + # Runs shared_memory binary .PHONY: shared -shared: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile shared --no-print-directory - exit -endif +shared: is-vscode check-mariadb cd build/bin && ./shared_memory # Runs zone binary .PHONY: zone -zone: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile zone --no-print-directory - exit -endif - @-rm build/bin/logs/zone/zone*.log +zone: is-vscode check-mariadb + @find build/bin/logs/zone/ -type f -name 'zone*.log' -exec rm -f {} + cd build/bin && ./zone +check-mariadb: is-vscode + @if ! sudo service mariadb status | grep -q 'active (running)'; then \ + sudo service mariadb start; \ + fi + # Runs world binary .PHONY: world -world: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile world --no-print-directory - exit -endif - @-rm build/bin/logs/world*.log +world: is-vscode check-mariadb + @find build/bin/logs/ -type f -name 'world*.log' -exec rm -f {} + cd build/bin && ./world # Runs ucs binary .PHONY: ucs -ucs: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile ucs --no-print-directory - exit -endif - @-rm build/bin/logs/ucs*.log +ucs: is-vscode check-mariadb + @find build/bin/logs/ -type f -name 'ucs*.log' -exec rm -f {} + cd build/bin && ./ucs # Runs queryserv binary .PHONY: queryserv -queryserv: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile queryserv --no-print-directory - exit -endif - @-rm build/bin/logs/query_server*.log +queryserv: is-vscode check-mariadb + @find build/bin/logs/ -type f -name 'query_server*.log' -exec rm -f {} + cd build/bin && ./queryserv -valgrind-%: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile valgrind --no-print-directory - exit -endif +reset-content: + @echo "Resetting content tables in database peq..." + cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_content.sql" + +valgrind-%: is-vscode cd build/bin && valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=logs/$*.valgrind.log ./$* # Start mariaDB standalone @@ -201,30 +132,33 @@ mariadb: .PHONY: inject-mariadb inject-mariadb: -sudo service mariadb start - -mkdir -p base/db/ + -mkdir -p .devcontainer/cache/db/ -sudo mariadb -e 'DROP DATABASE IF EXISTS peq;' -sudo mariadb -e 'CREATE DATABASE peq;' - -sudo mariadb -e "CREATE USER 'peq'@'127.0.0.1' IDENTIFIED BY 'peqpass';" + -sudo mariadb -e "CREATE USER IF NOT EXISTS 'peq'@'127.0.0.1' IDENTIFIED BY 'peqpass';" -sudo mariadb -e "GRANT ALL PRIVILEGES ON *.* TO 'peq'@'127.0.0.1';" -ifeq (,$(wildcard base/db/db.sql.zip)) - @echo "base/db.sql.zip not found. Downloading latest from https://db.projecteq.net/" - wget -nc https://db.projecteq.net/latest -O base/db/db.sql.zip - -cd base/db && unzip db.sql.zip +ifeq (,$(wildcard .devcontainer/cache/db/db.sql.zip)) + @echo ".devcontainer/cache/db.sql.zip not found. Downloading database from https://db.eqemu.dev/latest" + wget -nc https://db.eqemu.dev/latest -O .devcontainer/cache/db/db.sql.zip + -cd .devcontainer/cache/db && unzip db.sql.zip endif @echo "Sourcing db may take a while, please wait..." - @cd base/db/peq-dump && sudo mariadb --database peq -e "source create_all_tables.sql" + + @cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_content.sql" + @cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_login.sql" + @cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_player.sql" + @# deprecated cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_queryserv.sql" + @cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_state.sql" + @cd .devcontainer/cache/db/peq-dump && sudo mariadb --database peq -e "source create_tables_system.sql" + @echo "MariaDB is now injected." .PHONY: gm-% -gm-%: +gm-%: is-vscode sudo mariadb --database peq -e "UPDATE account SET status=255 WHERE name = '$*';" @echo "Account $* is now a GM. /camp to have it go into effect." -depends: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile depends --no-print-directory - exit -endif +depends: is-vscode sudo apt install graphviz pip time pip3 install graphviz mkdir -p build/depends @@ -241,44 +175,54 @@ endif @echo "Common..." time python3 build/depends/dependency_graph.py -f png common build/depends/common.dot -backup: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile backup --no-print-directory - exit -endif +backup: is-vscode @mkdir -p build/bin/backup cd build/bin && ./world database:dump --compress --player-tables --state-tables --system-tables --query-serv-tables -cpu-zone: +restore-%: is-vscode + @if [ -z "$*" ]; then \ + echo "Please provide a backup file to restore from. Example: make restore-backup.sql"; \ + exit 1; \ + fi + @echo "Restoring from backup $*" + @sudo mariadb --database peq -e "$*" + + +cpu-zone: is-vscode ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile cpu-zone --no-print-directory + @echo "This makefile is not intended to be run from the .devcontainer directory." exit endif @cd build/bin && mkdir -p tmp cd build/bin && CPUPROFILE=prof.out ./zone -pprof-zone: +pprof-zone: is-vscode ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile pprof-zone --no-print-directory + @echo "This makefile is not intended to be run from the .devcontainer directory." exit endif cd build/bin && google-pprof --pdf zone prof.out > prof.pdf -pprof-web-zone: -ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile pprof-web-zone --no-print-directory - exit -endif - cd build/bin && google-pprof --web zone prof.out -pprof-gv-zone: + +pprof-gv-zone: is-vscode ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile pprof-gv-zone --no-print-directory + @echo "This makefile is not intended to be run from the .devcontainer directory." exit endif cd build/bin && google-pprof --gv zone prof.out > prof.gv -heap-zone: + +heap-zone: is-vscode ifeq ($(findstring .devcontainer,$(CURDIR)),.devcontainer) - @make -C ../ -f .devcontainer/Makefile heap-zone --no-print-directory + @echo "This makefile is not intended to be run from the .devcontainer directory." exit endif @cd build/bin && mkdir -p tmp cd build/bin && HEAPPROFILE=prof.out ./zone + + +.PHONY: pull +pull: + git pull + @if [ ! -d "quests" ]; then git clone https://github.com/rebuildeq/quests.git quests; fi + cd quests && git pull + @if [ ! -d "eqemu-definitions" ]; then git clone https://github.com/xackery/eqemu-definitions.git eqemu-definitions; fi + cd eqemu-definitions && git pull \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index d6ccc72654..90ec8234c7 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -40,10 +40,41 @@ "GitHub.copilot", "xackery.make-magic", "Gruntfuggly.todo-tree", - "ms-vscode.cmake-tools" - ] + "ms-vscode.cmake-tools", + "sumneko.lua" + ], + "settings": { + "Lua.runtime.version": "Lua 5.1", + "Lua.workspace.library": [ + "/src/repo/eqemu-definitions" + ], + "Lua.diagnostics.disable": [ + "lowercase-global" + ], + "cmake.statusbar.advanced": { + "kit": { + "visibility": "hidden" + }, + "debug": { + "visibility": "hidden" + }, + "buildTarget": { + "visibility": "compact" + }, + "launch": { + "visibility": "hidden" + }, + "ctest": { + "visibility": "icon" + } + } + } } }, + "mounts": [ + "source=${localWorkspaceFolder}/.devcontainer/Makefile,target=/src/Makefile,type=bind,consistency=cached" + ], + "workspaceFolder": "/src", "workspaceMount": "source=${localWorkspaceFolder},target=/src,type=bind,consistency=cached" } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index bf5c79fae3..8bdf6f6fae 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -21,14 +21,6 @@ "${workspaceFolder}/dependencies/zlibng" ], "telemetry.enableTelemetry": false, - "cmake.buildDirectory": "${workspaceFolder}/build", - "cmake.configureArgs": [ - "-DEQEMU_BUILD_LOGIN=ON", - "-DEQEMU_BUILD_TESTS=ON", - "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache", - "-DEQEMU_ADD_PROFILER=ON", - "Ninja" - ], "cmake.skipConfigureIfCachePresent": true, "cmake.configureOnOpen": false, "files.associations": { @@ -115,22 +107,5 @@ "format": "cpp", "ranges": "cpp", "span": "cpp" - }, - "cmake.statusbar.advanced": { - "kit": { - "visibility": "hidden", - }, - "debug": { - "visibility": "hidden", - }, - "buildTarget": { - "visibility": "hidden", - }, - "launch": { - "visibility": "hidden", - }, - "ctest": { - "visibility": "icon", - } } } \ No newline at end of file diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000000..aa1a294534 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,49 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 19, + "patch": 0 + }, + "configurePresets": [ + { + "name": "linux-debug", + "displayName": "Linux Debug", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "CMAKE_C_COMPILER_LAUNCHER": "ccache", + "CMAKE_CXX_COMPILER_LAUNCHER": "ccache", + "EQEMU_BUILD_LOGIN": "ON", + "EQEMU_BUILD_TESTS": "ON", + "EQEMU_ADD_PROFILER": "ON" + } + }, + { + "name": "linux-release", + "displayName": "Linux Release", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/release", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_C_COMPILER_LAUNCHER": "ccache", + "CMAKE_CXX_COMPILER_LAUNCHER": "ccache", + "EQEMU_BUILD_LOGIN": "ON" + } + }, + { + "name": "win-msvc", + "displayName": "Windows MSVC (VS 2022)", + "generator": "Visual Studio 17 2022", + "binaryDir": "${sourceDir}/build/{presetName}", + "architecture": { "value": "x64" }, + "cacheVariables": { + "CMAKE_CONFIGURATION_TYPES": "Debug;Release", + "EQEMU_BUILD_LOGIN": "ON", + "EQEMU_BUILD_TESTS": "ON" + } + } + ] +} \ No newline at end of file diff --git a/tests/cppunit/CMakeLists.txt b/tests/cppunit/CMakeLists.txt index 16747f7850..7b7e4c7490 100644 --- a/tests/cppunit/CMakeLists.txt +++ b/tests/cppunit/CMakeLists.txt @@ -35,4 +35,4 @@ IF(UNIX) ADD_DEFINITIONS(-fPIC) ENDIF(UNIX) -SET(LIBRARY_OUTPUT_PATH ../../Bin) +SET(LIBRARY_OUTPUT_PATH ../../bin) From e42dc2e1d28f63266d5eecb85def1bc2f92ef6be Mon Sep 17 00:00:00 2001 From: brainiac Date: Mon, 17 Nov 2025 10:21:05 -0800 Subject: [PATCH 054/194] Add Github Actions support (#5031) Basic support for building linux and windows in pull requests and also the master branch. Removes search for local perl on windows. Just always use the packaged perl until we can switch to a package manager. Removes drone config file, since that isn't doing anything useful anymore. --- .drone.yml | 98 -------------------------------- .github/workflows/build.yaml | 81 ++++++++++++++++++++++++++ cmake/DependencyHelperMSVC.cmake | 67 ++++++++++------------ 3 files changed, 112 insertions(+), 134 deletions(-) delete mode 100644 .drone.yml create mode 100644 .github/workflows/build.yaml diff --git a/.drone.yml b/.drone.yml deleted file mode 100644 index 7a5443d4c4..0000000000 --- a/.drone.yml +++ /dev/null @@ -1,98 +0,0 @@ ---- - -kind: pipeline -type: docker -name: Build Linux - -# Limits how many of these builds can run on the drone runner at a time, this isn't about cores -concurrency: - limit: 1 - -volumes: - - name: cache - host: - path: /var/lib/cache-release - -steps: - - name: Build Linux X64 - image: akkadius/eqemu-server:v14 - environment: - GITHUB_TOKEN: - from_secret: GH_RELEASE_GITHUB_API_TOKEN - RCLONE_CONFIG_REMOTE_TYPE: ftp - RCLONE_FTP_HOST: drone.akkadius.com - RCLONE_FTP_USER: artifacts - RCLONE_FTP_PASS: - from_secret: RCLONE_FTP_PASS - commands: - - ./utils/scripts/build/linux-build.sh - volumes: - - name: cache - path: /home/eqemu/.ccache/ - ---- - -kind: pipeline -type: exec -name: Build Windows - -# Limits how many of these builds can run on the drone runner at a time, this isn't about cores -concurrency: - limit: 1 - -platform: - os: windows - arch: amd64 - -steps: - - name: Build Windows X64 - environment: - RCLONE_CONFIG_REMOTE_TYPE: ftp - RCLONE_FTP_HOST: drone.akkadius.com - RCLONE_FTP_USER: artifacts - RCLONE_FTP_PASS: - from_secret: RCLONE_FTP_PASS - GITHUB_TOKEN: - from_secret: GH_RELEASE_GITHUB_API_TOKEN - commands: - - .\utils\scripts\build\windows-build.ps1 - ---- - -kind: pipeline -type: docker -name: Publish Artifacts to Github - -steps: - - name: Upload Artifacts - image: akkadius/eqemu-build-releaser:v3 - environment: - RCLONE_CONFIG_REMOTE_TYPE: ftp - RCLONE_FTP_HOST: drone.akkadius.com - RCLONE_FTP_USER: artifacts - RCLONE_FTP_PASS: - from_secret: RCLONE_FTP_PASS - GH_RELEASE_GITHUB_API_TOKEN: - from_secret: GH_RELEASE_GITHUB_API_TOKEN - GITHUB_TOKEN: - from_secret: GH_RELEASE_GITHUB_API_TOKEN - commands: - - ./utils/scripts/build/should-release/should-release - - rclone config create remote ftp env_auth true > /dev/null - - | - rclone copy remote: --include "eqemu-server*.zip" . - - gh-release --assets=eqemu-server-linux-x64.zip,eqemu-server-windows-x64.zip -y - - | - rclone delete remote: --include "eqemu-server*.zip" - -trigger: - branch: - - master - event: - - push - -depends_on: - - Build Windows - - Build Linux - - diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000000..c9650cf56d --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,81 @@ +name: Build +on: + push: + branches: + - master + pull_request: + +jobs: + linux: + name: Linux + runs-on: ubuntu-latest + steps: + - name: Checkout source + uses: actions/checkout@v5 + with: + submodules: recursive + + - name: Setup ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ runner.os }}-ccache + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential ninja-build ccache libmariadb-dev libmariadb-dev-compat libboost-all-dev libperl-dev liblua5.1-0-dev libluajit-5.1-dev zlib1g-dev uuid-dev libssl-dev libsodium-dev libmbedtls-dev + + - name: Configure + run: | + cmake -S . -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DEQEMU_BUILD_TESTS=ON \ + -DEQEMU_BUILD_LOGIN=ON \ + -DEQEMU_BUILD_LUA=ON \ + -DEQEMU_BUILD_PERL=ON \ + -DEQEMU_BUILD_CLIENT_FILES=ON + + - name: Build + run: cmake --build build --parallel + + - name: Test + working-directory: build + run: ./bin/tests + + windows: + name: Windows + runs-on: windows-latest + steps: + - name: Checkout source + uses: actions/checkout@v5 + with: + submodules: recursive + + - name: Enable long paths + run: git config --global core.longpaths true + + - name: Setup MSVC environment + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + + - name: Configure + shell: pwsh + run: | + cmake -S . -B build -G "Visual Studio 17 2022" -A x64 ` + -DCMAKE_BUILD_TYPE=RelWithDebInfo ` + -DEQEMU_BUILD_TESTS=ON ` + -DEQEMU_BUILD_LOGIN=ON ` + -DEQEMU_BUILD_LUA=ON ` + -DEQEMU_BUILD_ZLIB=ON ` + -DEQEMU_BUILD_CLIENT_FILES=ON + + - name: Build + shell: pwsh + run: cmake --build build --config RelWithDebInfo --target ALL_BUILD -- /m + + - name: Test + working-directory: build + run: ./bin/RelWithDebInfo/tests.exe diff --git a/cmake/DependencyHelperMSVC.cmake b/cmake/DependencyHelperMSVC.cmake index 33f92e41b5..1f4554e6ce 100644 --- a/cmake/DependencyHelperMSVC.cmake +++ b/cmake/DependencyHelperMSVC.cmake @@ -35,60 +35,55 @@ ENDIF() IF(EQEMU_FETCH_MSVC_DEPENDENCIES_VCPKG) MESSAGE(STATUS "Resolving vcpkg dependencies...") - + IF(NOT EXISTS ${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_ZIP}) EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/vcpkg) - + MESSAGE(STATUS "Downloading existing vcpkg dependencies from releases...") - FILE(DOWNLOAD ${EQEMU_VCPKG_URL} ${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_ZIP} + FILE(DOWNLOAD ${EQEMU_VCPKG_URL} ${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_ZIP} SHOW_PROGRESS STATUS DOWNLOAD_STATUS) - + LIST(GET DOWNLOAD_STATUS 0 STATUS_CODE) IF(NOT STATUS_CODE EQUAL 0) MESSAGE(FATAL_ERROR "Was unable to download dependencies from ${EQEMU_VCPKG_URL}") ENDIF() - + MESSAGE(STATUS "Extracting files...") EXECUTE_PROCESS( COMMAND ${CMAKE_COMMAND} -E tar xzf ${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_ZIP} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/vcpkg ) ENDIF() - + INCLUDE(${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake) ENDIF() IF(EQEMU_FETCH_MSVC_DEPENDENCIES_PERL) - #Try to find perl first, (so you can use your active install first) - FIND_PACKAGE(PerlLibs) - - IF(NOT PerlLibs_FOUND) - MESSAGE(STATUS "Resolving perl dependencies...") - - IF(NOT EXISTS ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP}) - EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/perl) - EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}) - - MESSAGE(STATUS "Downloading portable perl...") - FILE(DOWNLOAD ${EQEMU_PERL_URL} ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP} - SHOW_PROGRESS - STATUS DOWNLOAD_STATUS) - - LIST(GET DOWNLOAD_STATUS 0 STATUS_CODE) - IF(NOT STATUS_CODE EQUAL 0) - MESSAGE(FATAL_ERROR "Was unable to download dependencies from ${EQEMU_PERL_URL}") - ENDIF() - - MESSAGE(STATUS "Extracting files...") - EXECUTE_PROCESS( - COMMAND ${CMAKE_COMMAND} -E tar xzf ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP} - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR} - ) + MESSAGE(STATUS "Resolving perl dependencies...") + + IF(NOT EXISTS ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP}) + EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/perl) + EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}) + + MESSAGE(STATUS "Downloading portable perl...") + FILE(DOWNLOAD ${EQEMU_PERL_URL} ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP} + SHOW_PROGRESS + STATUS DOWNLOAD_STATUS) + + LIST(GET DOWNLOAD_STATUS 0 STATUS_CODE) + IF(NOT STATUS_CODE EQUAL 0) + MESSAGE(FATAL_ERROR "Was unable to download dependencies from ${EQEMU_PERL_URL}") ENDIF() - - SET(PERL_EXECUTABLE ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/bin/perl.exe CACHE FILEPATH "Path to perl program" FORCE) - SET(PERL_INCLUDE_PATH ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/lib/CORE CACHE PATH "Path to perl include files" FORCE) - SET(PERL_LIBRARY ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/lib/CORE/libperl524.a CACHE FILEPATH "Path to perl library" FORCE) + + MESSAGE(STATUS "Extracting files...") + EXECUTE_PROCESS( + COMMAND ${CMAKE_COMMAND} -E tar xzf ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR} + ) ENDIF() -ENDIF() \ No newline at end of file + + SET(PERL_EXECUTABLE ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/bin/perl.exe CACHE FILEPATH "Path to perl program" FORCE) + SET(PERL_INCLUDE_PATH ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/lib/CORE CACHE PATH "Path to perl include files" FORCE) + SET(PERL_LIBRARY ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/lib/CORE/libperl524.a CACHE FILEPATH "Path to perl library" FORCE) +ENDIF() From 9b3f9f356db1ed29ca8a098cad3682d041b0c5fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Nov 2025 19:44:17 +0100 Subject: [PATCH 055/194] Bump golang.org/x/crypto in /utils/scripts/build/should-release (#5032) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.36.0 to 0.45.0. - [Commits](https://github.com/golang/crypto/compare/v0.36.0...v0.45.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-version: 0.45.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- utils/scripts/build/should-release/go.mod | 6 ++---- utils/scripts/build/should-release/go.sum | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/utils/scripts/build/should-release/go.mod b/utils/scripts/build/should-release/go.mod index df899a9e13..0866b19935 100644 --- a/utils/scripts/build/should-release/go.mod +++ b/utils/scripts/build/should-release/go.mod @@ -1,8 +1,6 @@ module should-release -go 1.23.0 - -toolchain go1.23.5 +go 1.24.0 require ( github.com/google/go-github/v41 v41.0.0 @@ -11,5 +9,5 @@ require ( require ( github.com/google/go-querystring v1.1.0 // indirect - golang.org/x/crypto v0.36.0 // indirect + golang.org/x/crypto v0.45.0 // indirect ) diff --git a/utils/scripts/build/should-release/go.sum b/utils/scripts/build/should-release/go.sum index d821c4071c..7f3392bcc4 100644 --- a/utils/scripts/build/should-release/go.sum +++ b/utils/scripts/build/should-release/go.sum @@ -10,8 +10,8 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= From c84df0d5ba4294cf4088064556d251c1a70819c9 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 13 Dec 2025 19:56:37 -0800 Subject: [PATCH 056/194] Build Improvements (#5033) * Start rewrite, add vcpkg * Simple vcpkg manifest, will almost certainly need tweaking * Remove cmake ext we wont be using anymore * Update vcpkg to no longer be from 2022, update cmake lists (wip) * Add finds to the toplevel cmakelists * WIP, luabind and perlbind build. Common only partially builds. * Fix common build. * shared_memory compiles * client files compile * Tests and more cmake version updates * World, had to swap out zlib-ng for now because it wasn't playing nicely along side the zlib install. May revisit. * UCS compiles now too! * queryserv and eqlaunch * loginserver works * Zone works but is messy, tomorrow futher cleanup! * Cleanup main file * remove old zlibng, remove perlwrap, remove hc * More cleanup * vcpkg baseline set for CI * Remove pkg-config, it's the suggested way to use luajit with vcpkg but it causes issues with CI and might be a pain point for windows users * Actually add file * Set perlbind include dir * Perl link got lost * PERL_SET_INTERP causes an issue on newer versions of perl on windows because a symbol is not properly exported in their API, change the lines so it's basically what it used to be * Remove static unix linking, we dont do automated released anymore and this was tightly coupled to that. Can explore this again if we decide to change that. * Remove unused submodules, set cmake policy for boost * Fix some cereal includes * Improve some boilerplate, I'd still like to do better about getting linker stuff set. * Going through and cleaning up the build. * Fix world, separate out data_buckets. * add fixes for other servers * fix zone * Fix client files, loginserver and tests * Newer versions of libmariadb default to tls forced on, return to the default of not forcing that. auto_login were breaking on linux builds loginserver wasn't setting proper openssl compile flag * Move set out of a giant cpp file include. * Convert show * convert find * Add uuid to unix builds * Remove some cpp includes. * Restructure to remove more things. * change db update manifest to header change build yml * Move world CLI include cpps to cmake. * Move zone cli out of source and into cmake * Sidecar stuff wont directly include cpp files now too. * Fix uuid-dev missing on linux runner * Reorg common cmake file * Some cleanup * Fix libsodium support (oops). Fix perl support (more oops) * Change doc --------- Co-authored-by: KimLS --- .github/workflows/build.yaml | 2 +- .gitmodules | 18 +- BUILD.md | 21 +- CMakeLists.txt | 658 +- client_files/CMakeLists.txt | 2 +- client_files/export/CMakeLists.txt | 14 +- client_files/import/CMakeLists.txt | 14 +- cmake/DependencyHelperMSVC.cmake | 89 - cmake/FindLua51.cmake | 91 - cmake/FindLuaJit.cmake | 1 - cmake/FindMariaDB.cmake | 87 - cmake/FindMySQL.cmake | 87 - cmake/FindSodium.cmake | 30 - cmake/FindmbedTLS.cmake | 93 - common/CMakeLists.txt | 650 +- common/classes.cpp | 1 + common/cli/eqemu_command_handler.cpp | 1 + common/data_bucket.cpp | 74 +- common/data_bucket.h | 25 +- common/database/database_update.cpp | 7 +- ...anifest.cpp => database_update_manifest.h} | 2 +- ...ts.cpp => database_update_manifest_bots.h} | 2 +- ....cpp => database_update_manifest_custom.h} | 2 +- common/dbcore.cpp | 8 + common/dynamic_zone_lockout.cpp | 1 + common/eq_packet_structs.h | 6 +- common/eqemu_config.h | 1 + common/eqemu_logsys.h | 1 + .../events/player_event_discord_formatter.cpp | 1 + common/file.cpp | 1 + common/ip_util.cpp | 1 + common/net/console_server.cpp | 1 + common/net/console_server_connection.cpp | 1 + common/net/packet.cpp | 1 + common/net/reliable_stream_connection.cpp | 1 + common/net/websocket_server.cpp | 1 + common/net/websocket_server_connection.cpp | 1 + common/patches/uf.cpp | 2 +- common/process/process.cpp | 1 + common/profanity_manager.h | 2 +- common/repositories/trader_repository.h | 4 +- common/rulesys.cpp | 1 + common/shareddb.cpp | 1 + common/strings.cpp | 6 +- common/util/uuid.cpp | 1 + eqlaunch/CMakeLists.txt | 14 +- hc/CMakeLists.txt | 22 - hc/eq.cpp | 350 - hc/eq.h | 74 - hc/login.cpp | 255 - hc/login.h | 56 - hc/main.cpp | 51 - hc/world.cpp | 78 - hc/world.h | 31 - hc/zone.cpp | 0 hc/zone.h | 0 libs/CMakeLists.txt | 12 +- libs/luabind/CMakeLists.txt | 23 +- libs/perlbind/CMakeLists.txt | 6 +- libs/zlibng/.gitattributes | 4 - libs/zlibng/.github/workflows/analyze.yml | 39 - libs/zlibng/.github/workflows/cmake.yml | 381 - libs/zlibng/.github/workflows/configure.yml | 185 - libs/zlibng/.github/workflows/fuzz.yml | 23 - libs/zlibng/.github/workflows/libpng.yml | 46 - libs/zlibng/.github/workflows/nmake.yml | 48 - libs/zlibng/.github/workflows/pkgcheck.yml | 121 - libs/zlibng/.github/workflows/release.yml | 73 - libs/zlibng/.gitignore | 86 - libs/zlibng/.shellcheckrc | 1 - libs/zlibng/CMakeLists.txt | 1285 --- libs/zlibng/FAQ.zlib | 374 - libs/zlibng/INDEX.md | 37 - libs/zlibng/LICENSE.md | 19 - libs/zlibng/Makefile.in | 441 - libs/zlibng/README.md | 206 - libs/zlibng/adler32.c | 139 - libs/zlibng/adler32_p.h | 53 - libs/zlibng/arch/.gitignore | 2 - libs/zlibng/arch/arm/Makefile.in | 68 - libs/zlibng/arch/arm/adler32_neon.c | 126 - libs/zlibng/arch/arm/arm.h | 13 - libs/zlibng/arch/arm/armfeature.c | 69 - libs/zlibng/arch/arm/chunkset_neon.c | 54 - libs/zlibng/arch/arm/crc32_acle.c | 110 - libs/zlibng/arch/arm/ctzl.h | 12 - libs/zlibng/arch/arm/insert_string_acle.c | 22 - libs/zlibng/arch/arm/slide_neon.c | 52 - libs/zlibng/arch/generic/Makefile.in | 21 - libs/zlibng/arch/power/Makefile.in | 49 - libs/zlibng/arch/power/adler32_power8.c | 154 - libs/zlibng/arch/power/power.c | 19 - libs/zlibng/arch/power/power.h | 13 - libs/zlibng/arch/power/slide_hash_power8.c | 60 - libs/zlibng/arch/s390/Makefile.in | 40 - libs/zlibng/arch/s390/README.md | 216 - libs/zlibng/arch/s390/dfltcc_common.c | 89 - libs/zlibng/arch/s390/dfltcc_common.h | 29 - libs/zlibng/arch/s390/dfltcc_deflate.c | 406 - libs/zlibng/arch/s390/dfltcc_deflate.h | 56 - libs/zlibng/arch/s390/dfltcc_detail.h | 199 - libs/zlibng/arch/s390/dfltcc_inflate.c | 137 - libs/zlibng/arch/s390/dfltcc_inflate.h | 49 - libs/zlibng/arch/x86/INDEX.md | 8 - libs/zlibng/arch/x86/Makefile.in | 107 - libs/zlibng/arch/x86/adler32_avx.c | 117 - libs/zlibng/arch/x86/adler32_ssse3.c | 118 - libs/zlibng/arch/x86/chunkset_avx.c | 50 - libs/zlibng/arch/x86/chunkset_sse.c | 51 - libs/zlibng/arch/x86/compare258_avx.c | 67 - libs/zlibng/arch/x86/compare258_sse.c | 74 - libs/zlibng/arch/x86/crc_folding.c | 457 - libs/zlibng/arch/x86/crc_folding.h | 19 - libs/zlibng/arch/x86/insert_string_sse.c | 46 - libs/zlibng/arch/x86/slide_avx.c | 47 - libs/zlibng/arch/x86/slide_sse.c | 46 - libs/zlibng/arch/x86/x86.c | 80 - libs/zlibng/arch/x86/x86.h | 18 - libs/zlibng/chunkset.c | 81 - libs/zlibng/chunkset_tpl.h | 172 - libs/zlibng/cmake/detect-arch.c | 99 - libs/zlibng/cmake/detect-arch.cmake | 93 - libs/zlibng/cmake/detect-sanitizer.cmake | 123 - libs/zlibng/cmake/run-and-compare.cmake | 48 - libs/zlibng/cmake/run-and-redirect.cmake | 38 - libs/zlibng/cmake/test-compress.cmake | 188 - libs/zlibng/cmake/toolchain-aarch64.cmake | 26 - libs/zlibng/cmake/toolchain-arm.cmake | 24 - libs/zlibng/cmake/toolchain-mingw-i686.cmake | 16 - .../zlibng/cmake/toolchain-mingw-x86_64.cmake | 16 - libs/zlibng/cmake/toolchain-powerpc.cmake | 25 - libs/zlibng/cmake/toolchain-powerpc64.cmake | 25 - libs/zlibng/cmake/toolchain-powerpc64le.cmake | 25 - libs/zlibng/cmake/toolchain-s390x.cmake | 25 - libs/zlibng/cmake/toolchain-sparc64.cmake | 25 - libs/zlibng/compare258.c | 186 - libs/zlibng/compress.c | 83 - libs/zlibng/configure | 1725 ---- libs/zlibng/crc32.c | 202 - libs/zlibng/crc32_comb.c | 108 - libs/zlibng/crc32_comb_tbl.h | 300 - libs/zlibng/crc32_p.h | 19 - libs/zlibng/crc32_tbl.h | 444 - libs/zlibng/deflate.c | 1782 ---- libs/zlibng/deflate.h | 411 - libs/zlibng/deflate_fast.c | 106 - libs/zlibng/deflate_medium.c | 293 - libs/zlibng/deflate_p.h | 82 - libs/zlibng/deflate_quick.c | 121 - libs/zlibng/deflate_slow.c | 137 - libs/zlibng/doc/algorithm.txt | 209 - libs/zlibng/doc/rfc1950.txt | 619 -- libs/zlibng/doc/rfc1951.txt | 955 --- libs/zlibng/doc/rfc1952.txt | 675 -- libs/zlibng/doc/txtvsbin.txt | 107 - libs/zlibng/fallback_builtins.h | 44 - libs/zlibng/functable.c | 466 - libs/zlibng/functable.h | 29 - libs/zlibng/gzguts.h | 154 - libs/zlibng/gzlib.c | 543 -- libs/zlibng/gzread.c | 602 -- libs/zlibng/gzwrite.c | 526 -- libs/zlibng/infback.c | 510 -- libs/zlibng/inffast.c | 325 - libs/zlibng/inffast.h | 18 - libs/zlibng/inffixed_tbl.h | 94 - libs/zlibng/inflate.c | 1329 --- libs/zlibng/inflate.h | 134 - libs/zlibng/inflate_p.h | 101 - libs/zlibng/inftrees.c | 297 - libs/zlibng/inftrees.h | 66 - libs/zlibng/insert_string.c | 25 - libs/zlibng/insert_string_tpl.h | 89 - libs/zlibng/match_tpl.h | 180 - libs/zlibng/test/.gitignore | 5 - libs/zlibng/test/CVE-2002-0059/test.gz | Bin 4610 -> 0 bytes libs/zlibng/test/CVE-2003-0107.c | 22 - libs/zlibng/test/CVE-2004-0797/test.gz | Bin 52 -> 0 bytes libs/zlibng/test/CVE-2005-1849/test.gz | Bin 52 -> 0 bytes libs/zlibng/test/CVE-2005-2096/test.gz | Bin 52 -> 0 bytes libs/zlibng/test/GH-361/test.txt | 4 - libs/zlibng/test/GH-364/test.bin | Bin 8 -> 0 bytes libs/zlibng/test/GH-382/defneg3.dat | 1 - libs/zlibng/test/GH-751/test.txt | 1 - libs/zlibng/test/Makefile.in | 116 - libs/zlibng/test/README.md | 36 - libs/zlibng/test/abi/ignore | 12 - .../abi/zlib-v1.2.11-arm-linux-gnueabihf.abi | 119 - .../abi/zlib-v1.2.11-x86_64-linux-gnu.abi | 1037 --- libs/zlibng/test/abicheck.md | 59 - libs/zlibng/test/abicheck.sh | 164 - libs/zlibng/test/adler32_test.c | 365 - libs/zlibng/test/data/fireworks.jpg | Bin 123093 -> 0 bytes libs/zlibng/test/data/lcet10.txt | 7519 ----------------- libs/zlibng/test/data/paper-100k.pdf | Bin 102400 -> 0 bytes libs/zlibng/test/example.c | 1067 --- libs/zlibng/test/fuzz/checksum_fuzzer.c | 86 - libs/zlibng/test/fuzz/compress_fuzzer.c | 87 - libs/zlibng/test/fuzz/example_dict_fuzzer.c | 169 - libs/zlibng/test/fuzz/example_flush_fuzzer.c | 124 - libs/zlibng/test/fuzz/example_large_fuzzer.c | 141 - libs/zlibng/test/fuzz/example_small_fuzzer.c | 123 - libs/zlibng/test/fuzz/minigzip_fuzzer.c | 321 - .../test/fuzz/standalone_fuzz_target_runner.c | 36 - libs/zlibng/test/infcover.c | 682 -- libs/zlibng/test/minideflate.c | 307 - libs/zlibng/test/minigzip.c | 376 - libs/zlibng/test/pkgcheck.sh | 176 - libs/zlibng/test/switchlevels.c | 169 - libs/zlibng/test/testCVEinputs.sh | 30 - libs/zlibng/tools/codecov-upload.sh | 9 - libs/zlibng/tools/config.sub | 17 - libs/zlibng/tools/makecrct.c | 177 - libs/zlibng/tools/makefixed.c | 89 - libs/zlibng/tools/maketrees.c | 147 - libs/zlibng/trees.c | 822 -- libs/zlibng/trees.h | 40 - libs/zlibng/trees_emit.h | 228 - libs/zlibng/trees_tbl.h | 132 - libs/zlibng/uncompr.c | 85 - libs/zlibng/win32/DLL_FAQ.txt | 397 - libs/zlibng/win32/Makefile.a64 | 208 - libs/zlibng/win32/Makefile.arm | 220 - libs/zlibng/win32/Makefile.msc | 215 - libs/zlibng/win32/README-WIN32.txt | 103 - libs/zlibng/win32/zlib-ng.def | 60 - libs/zlibng/win32/zlib-ng1.rc | 40 - libs/zlibng/win32/zlib.def | 61 - libs/zlibng/win32/zlib1.rc | 40 - libs/zlibng/win32/zlibcompat.def | 94 - libs/zlibng/zbuild.h | 29 - libs/zlibng/zconf-ng.h.in | 177 - libs/zlibng/zconf.h.in | 185 - libs/zlibng/zendian.h | 60 - libs/zlibng/zlib-ng.h | 1888 ----- libs/zlibng/zlib-ng.map | 107 - libs/zlibng/zlib.3 | 149 - libs/zlibng/zlib.h | 1831 ---- libs/zlibng/zlib.map | 100 - libs/zlibng/zlib.pc.cmakein | 13 - libs/zlibng/zlib.pc.in | 13 - libs/zlibng/zutil.c | 111 - libs/zlibng/zutil.h | 254 - libs/zlibng/zutil_p.h | 34 - loginserver/CMakeLists.txt | 16 +- queryserv/CMakeLists.txt | 16 +- shared_memory/CMakeLists.txt | 14 +- submodules/cereal | 1 - submodules/fmt | 1 - submodules/glm | 1 - submodules/libuv | 1 - submodules/recastnavigation | 1 - submodules/vcpkg | 1 + tests/CMakeLists.txt | 50 +- tests/cppunit/CMakeLists.txt | 16 +- ucs/CMakeLists.txt | 17 +- vcpkg.json | 20 + world/CMakeLists.txt | 63 +- ...{bots_disable.cpp => cli_bots_disable.cpp} | 1 + .../{bots_enable.cpp => cli_bots_enable.cpp} | 1 + ...y_character.cpp => cli_copy_character.cpp} | 2 + ...rency.cpp => cli_database_concurrency.cpp} | 1 + ...atabase_dump.cpp => cli_database_dump.cpp} | 1 + ...schema.cpp => cli_database_get_schema.cpp} | 1 + ...pp => cli_database_set_account_status.cpp} | 1 + ...e_updates.cpp => cli_database_updates.cpp} | 2 + ...e_version.cpp => cli_database_version.cpp} | 1 + ..._settings.cpp => cli_etl_get_settings.cpp} | 2 + ...ercs_disable.cpp => cli_mercs_disable.cpp} | 1 + ...{mercs_enable.cpp => cli_mercs_enable.cpp} | 1 + world/cli/{test.cpp => cli_test.cpp} | 1 + .../{test_colors.cpp => cli_test_colors.cpp} | 1 + ...t_expansion.cpp => cli_test_expansion.cpp} | 1 + ...repository.cpp => cli_test_repository.cpp} | 1 + ...sitory_2.cpp => cli_test_repository_2.cpp} | 2 + ...mark.cpp => cli_test_string_benchmark.cpp} | 1 + world/cli/{version.cpp => cli_version.cpp} | 1 + world/client.cpp | 4 +- world/world_server_cli.cpp | 19 - zone/CMakeLists.txt | 336 +- zone/bonuses.cpp | 2 +- zone/bot.cpp | 4 +- zone/bot_command.cpp | 62 - .../{actionable.cpp => bot_actionable.cpp} | 0 .../{appearance.cpp => bot_appearance.cpp} | 0 ...{apply_poison.cpp => bot_apply_poison.cpp} | 0 ...{apply_potion.cpp => bot_apply_potion.cpp} | 0 .../{attack.cpp => bot_attack.cpp} | 0 .../{behind_mob.cpp => bot_behind_mob.cpp} | 0 ...locked_buffs.cpp => bot_blocked_buffs.cpp} | 0 zone/bot_commands/{bot.cpp => bot_bot.cpp} | 0 ...{bot_settings.cpp => bot_bot_settings.cpp} | 0 zone/bot_commands/{cast.cpp => bot_cast.cpp} | 0 ..._race_list.cpp => bot_class_race_list.cpp} | 0 .../{click_item.cpp => bot_click_item.cpp} | 0 ...opy_settings.cpp => bot_copy_settings.cpp} | 0 ..._settings.cpp => bot_default_settings.cpp} | 0 .../{depart.cpp => bot_depart.cpp} | 0 .../{discipline.cpp => bot_discipline.cpp} | 0 ...nce_ranged.cpp => bot_distance_ranged.cpp} | 0 ...{find_aliases.cpp => bot_find_aliases.cpp} | 0 .../{follow.cpp => bot_follow.cpp} | 0 .../bot_commands/{guard.cpp => bot_guard.cpp} | 0 ...eal_rotation.cpp => bot_heal_rotation.cpp} | 0 zone/bot_commands/{help.cpp => bot_help.cpp} | 0 zone/bot_commands/{hold.cpp => bot_hold.cpp} | 0 ...usion_block.cpp => bot_illusion_block.cpp} | 0 .../{inventory.cpp => bot_inventory.cpp} | 0 .../{item_use.cpp => bot_item_use.cpp} | 0 ...elee_range.cpp => bot_max_melee_range.cpp} | 0 zone/bot_commands/{name.cpp => bot_name.cpp} | 0 ...{owner_option.cpp => bot_owner_option.cpp} | 0 zone/bot_commands/{pet.cpp => bot_pet.cpp} | 0 .../{pick_lock.cpp => bot_pick_lock.cpp} | 1 + .../{pickpocket.cpp => bot_pickpocket.cpp} | 0 .../{precombat.cpp => bot_precombat.cpp} | 0 zone/bot_commands/{pull.cpp => bot_pull.cpp} | 0 .../{release.cpp => bot_release.cpp} | 0 ...{set_assistee.cpp => bot_set_assistee.cpp} | 0 ..._hp_percent.cpp => bot_sit_hp_percent.cpp} | 0 ...it_in_combat.cpp => bot_sit_in_combat.cpp} | 0 ...a_percent.cpp => bot_sit_mana_percent.cpp} | 0 .../bot_commands/{spell.cpp => bot_spell.cpp} | 0 ..._checks.cpp => bot_spell_aggro_checks.cpp} | 0 ...e_cast.cpp => bot_spell_announce_cast.cpp} | 0 ...{spell_delays.cpp => bot_spell_delays.cpp} | 0 ...ity.cpp => bot_spell_engaged_priority.cpp} | 0 .../{spell_holds.cpp => bot_spell_holds.cpp} | 0 ...iority.cpp => bot_spell_idle_priority.cpp} | 0 ...ax_hp_pct.cpp => bot_spell_max_hp_pct.cpp} | 0 ...ana_pct.cpp => bot_spell_max_mana_pct.cpp} | 0 ...holds.cpp => bot_spell_max_thresholds.cpp} | 0 ...in_hp_pct.cpp => bot_spell_min_hp_pct.cpp} | 0 ...ana_pct.cpp => bot_spell_min_mana_pct.cpp} | 0 ...holds.cpp => bot_spell_min_thresholds.cpp} | 0 ...rity.cpp => bot_spell_pursue_priority.cpp} | 0 ...limits.cpp => bot_spell_resist_limits.cpp} | 0 ...t_count.cpp => bot_spell_target_count.cpp} | 0 .../{spelltypes.cpp => bot_spelltypes.cpp} | 0 .../{summon.cpp => bot_summon.cpp} | 0 .../{suspend.cpp => bot_suspend.cpp} | 0 .../bot_commands/{taunt.cpp => bot_taunt.cpp} | 0 .../bot_commands/{timer.cpp => bot_timer.cpp} | 0 .../bot_commands/{track.cpp => bot_track.cpp} | 0 .../{view_combos.cpp => bot_view_combos.cpp} | 0 ...kets.cpp => cli_benchmark_databuckets.cpp} | 14 +- ...ve_http.cpp => cli_sidecar_serve_http.cpp} | 2 + .../{databuckets.cpp => cli_databuckets.cpp} | 6 + .../{npc_handins.cpp => cli_npc_handins.cpp} | 6 + ...est.cpp => cli_npc_handins_multiquest.cpp} | 6 + .../{_test_util.cpp => cli_test_util.cpp} | 8 +- .../{zone_state.cpp => cli_zone_state.cpp} | 11 +- zone/client.cpp | 33 +- zone/client_packet.cpp | 2 +- zone/client_process.cpp | 2 +- zone/embparser_api.cpp | 12 +- zone/embperl.cpp | 10 +- zone/exp.cpp | 2 +- zone/gm_commands/CMakeLists.txt | 169 + zone/gm_commands/databuckets.cpp | 6 +- zone/gm_commands/find.cpp | 51 +- zone/gm_commands/find/{aa.cpp => find_aa.cpp} | 0 .../find/{account.cpp => find_account.cpp} | 2 +- .../{body_type.cpp => find_body_type.cpp} | 0 .../find/{bot.cpp => find_bot.cpp} | 2 +- ...bug_category.cpp => find_bug_category.cpp} | 0 .../{character.cpp => find_character.cpp} | 2 +- .../find/{class.cpp => find_class.cpp} | 0 ...ison_type.cpp => find_comparison_type.cpp} | 0 .../find/{currency.cpp => find_currency.cpp} | 0 .../find/{deity.cpp => find_deity.cpp} | 0 .../find/{emote.cpp => find_emote.cpp} | 0 .../find/{faction.cpp => find_faction.cpp} | 0 .../find/{item.cpp => find_item.cpp} | 2 +- .../find/{language.cpp => find_language.cpp} | 0 .../{ldon_theme.cpp => find_ldon_theme.cpp} | 0 .../find/{npctype.cpp => find_npctype.cpp} | 0 .../{object_type.cpp => find_object_type.cpp} | 0 .../find/{race.cpp => find_race.cpp} | 0 .../find/{recipe.cpp => find_recipe.cpp} | 2 +- .../find/{skill.cpp => find_skill.cpp} | 0 ...l_ability.cpp => find_special_ability.cpp} | 0 .../find/{spell.cpp => find_spell.cpp} | 2 + .../find/{stance.cpp => find_stance.cpp} | 0 .../find/{task.cpp => find_task.cpp} | 2 + .../find/{zone.cpp => find_zone.cpp} | 2 +- zone/gm_commands/fixmob.cpp | 31 +- zone/gm_commands/gmzone.cpp | 3 +- zone/gm_commands/set.cpp | 113 +- .../set/{aa_exp.cpp => set_aa_exp.cpp} | 0 .../set/{aa_points.cpp => set_aa_points.cpp} | 0 ...re_points.cpp => set_adventure_points.cpp} | 0 ...urrency.cpp => set_alternate_currency.cpp} | 0 .../set/{animation.cpp => set_animation.cpp} | 0 .../set/{anon.cpp => set_anon.cpp} | 0 .../{auto_login.cpp => set_auto_login.cpp} | 2 +- .../{bind_point.cpp => set_bind_point.cpp} | 0 .../set/{checksum.cpp => set_checksum.cpp} | 0 ..._permanent.cpp => set_class_permanent.cpp} | 0 .../set/{crystals.cpp => set_crystals.cpp} | 0 .../set/{date.cpp => set_date.cpp} | 0 .../set/{endurance.cpp => set_endurance.cpp} | 0 ...urance_full.cpp => set_endurance_full.cpp} | 0 zone/gm_commands/set/{exp.cpp => set_exp.cpp} | 0 .../set/{flymode.cpp => set_flymode.cpp} | 0 .../set/{frozen.cpp => set_frozen.cpp} | 0 .../set/{gender.cpp => set_gender.cpp} | 0 ...permanent.cpp => set_gender_permanent.cpp} | 0 zone/gm_commands/set/{gm.cpp => set_gm.cpp} | 0 .../set/{gm_speed.cpp => set_gm_speed.cpp} | 0 .../set/{gm_status.cpp => set_gm_status.cpp} | 0 .../set/{god_mode.cpp => set_god_mode.cpp} | 0 .../set/{haste.cpp => set_haste.cpp} | 0 .../{hero_model.cpp => set_hero_model.cpp} | 0 .../set/{hide_me.cpp => set_hide_me.cpp} | 0 zone/gm_commands/set/{hp.cpp => set_hp.cpp} | 0 .../set/{hp_full.cpp => set_hp_full.cpp} | 0 ...{invulnerable.cpp => set_invulnerable.cpp} | 0 .../set/{language.cpp => set_language.cpp} | 0 .../set/{last_name.cpp => set_last_name.cpp} | 0 .../set/{level.cpp => set_level.cpp} | 0 ...rver_info.cpp => set_loginserver_info.cpp} | 0 .../set/{mana.cpp => set_mana.cpp} | 0 .../set/{mana_full.cpp => set_mana_full.cpp} | 0 .../set/{motd.cpp => set_motd.cpp} | 0 .../set/{name.cpp => set_name.cpp} | 0 .../set/{ooc_mute.cpp => set_ooc_mute.cpp} | 0 .../set/{password.cpp => set_password.cpp} | 0 zone/gm_commands/set/{pvp.cpp => set_pvp.cpp} | 0 .../{pvp_points.cpp => set_pvp_points.cpp} | 0 .../set/{race.cpp => set_race.cpp} | 0 ...e_permanent.cpp => set_race_permanent.cpp} | 0 ...erver_locked.cpp => set_server_locked.cpp} | 0 .../set/{skill.cpp => set_skill.cpp} | 0 .../set/{skill_all.cpp => set_skill_all.cpp} | 0 ...kill_all_max.cpp => set_skill_all_max.cpp} | 0 .../{start_zone.cpp => set_start_zone.cpp} | 0 ...porary_name.cpp => set_temporary_name.cpp} | 0 .../set/{texture.cpp => set_texture.cpp} | 0 .../set/{time.cpp => set_time.cpp} | 0 .../set/{time_zone.cpp => set_time_zone.cpp} | 0 .../set/{title.cpp => set_title.cpp} | 0 ...{title_suffix.cpp => set_title_suffix.cpp} | 0 .../set/{weather.cpp => set_weather.cpp} | 0 .../set/{zone.cpp => set_zone.cpp} | 3 + zone/gm_commands/show.cpp | 105 +- .../{aa_points.cpp => show_aa_points.cpp} | 0 .../show/{aas.cpp => show_aas.cpp} | 0 .../show/{aggro.cpp => show_aggro.cpp} | 0 .../{auto_login.cpp => show_auto_login.cpp} | 2 +- .../show/{buffs.cpp => show_buffs.cpp} | 0 ...count.cpp => show_buried_corpse_count.cpp} | 0 ...ry.cpp => show_client_version_summary.cpp} | 0 ...ntent_flags.cpp => show_content_flags.cpp} | 0 .../{currencies.cpp => show_currencies.cpp} | 0 .../show/{distance.cpp => show_distance.cpp} | 0 .../show/{emotes.cpp => show_emotes.cpp} | 0 ...eld_of_view.cpp => show_field_of_view.cpp} | 0 .../show/{flags.cpp => show_flags.cpp} | 0 .../{group_info.cpp => show_group_info.cpp} | 0 .../show/{hatelist.cpp => show_hatelist.cpp} | 0 .../{inventory.cpp => show_inventory.cpp} | 0 .../{ip_lookup.cpp => show_ip_lookup.cpp} | 0 .../show/{keyring.cpp => show_keyring.cpp} | 0 ...ne_of_sight.cpp => show_line_of_sight.cpp} | 0 .../show/{network.cpp => show_network.cpp} | 0 ...twork_stats.cpp => show_network_stats.cpp} | 0 ...obal_loot.cpp => show_npc_global_loot.cpp} | 0 .../{npc_stats.cpp => show_npc_stats.cpp} | 0 .../show/{npc_type.cpp => show_npc_type.cpp} | 0 ...qzone_flags.cpp => show_peqzone_flags.cpp} | 0 .../show/{petition.cpp => show_petition.cpp} | 2 +- ...tition_info.cpp => show_petition_info.cpp} | 2 +- .../{proximity.cpp => show_proximity.cpp} | 0 ...quest_errors.cpp => show_quest_errors.cpp} | 0 ...est_globals.cpp => show_quest_globals.cpp} | 0 .../show/{recipe.cpp => show_recipe.cpp} | 4 +- .../{server_info.cpp => show_server_info.cpp} | 2 +- .../show/{skills.cpp => show_skills.cpp} | 0 ...spawn_status.cpp => show_spawn_status.cpp} | 0 ...ilities.cpp => show_special_abilities.cpp} | 0 .../show/{spells.cpp => show_spells.cpp} | 0 .../{spells_list.cpp => show_spells_list.cpp} | 0 .../show/{stats.cpp => show_stats.cpp} | 0 .../show/{timers.cpp => show_timers.cpp} | 0 .../show/{traps.cpp => show_traps.cpp} | 0 .../show/{uptime.cpp => show_uptime.cpp} | 0 .../show/{variable.cpp => show_variable.cpp} | 0 .../show/{version.cpp => show_version.cpp} | 0 .../{waypoints.cpp => show_waypoints.cpp} | 0 .../show/{who.cpp => show_who.cpp} | 0 .../show/{xtargets.cpp => show_xtargets.cpp} | 2 +- .../{zone_data.cpp => show_zone_data.cpp} | 0 ...bal_loot.cpp => show_zone_global_loot.cpp} | 0 .../{zone_loot.cpp => show_zone_loot.cpp} | 0 .../{zone_points.cpp => show_zone_points.cpp} | 0 .../{zone_status.cpp => show_zone_status.cpp} | 0 ..._variables.cpp => show_zone_variables.cpp} | 0 zone/lua_general.cpp | 12 +- zone/lua_parser.cpp | 3 +- zone/mob.cpp | 16 +- zone/pathfinder_nav_mesh.cpp | 4 +- zone/pathfinder_nav_mesh.h | 2 +- zone/sidecar_api/log_handler.cpp | 18 - zone/sidecar_api/map_best_z_controller.cpp | 4 - zone/sidecar_api/sidecar_api.cpp | 36 +- zone/sidecar_api/test_controller.cpp | 10 - zone/spells.cpp | 2 +- zone/zone.cpp | 14 +- zone/zone_cli.cpp | 10 - 510 files changed, 1518 insertions(+), 46461 deletions(-) delete mode 100644 cmake/DependencyHelperMSVC.cmake delete mode 100644 cmake/FindLua51.cmake delete mode 100644 cmake/FindMariaDB.cmake delete mode 100644 cmake/FindMySQL.cmake delete mode 100644 cmake/FindSodium.cmake delete mode 100644 cmake/FindmbedTLS.cmake rename common/database/{database_update_manifest.cpp => database_update_manifest.h} (99%) rename common/database/{database_update_manifest_bots.cpp => database_update_manifest_bots.h} (99%) rename common/database/{database_update_manifest_custom.cpp => database_update_manifest_custom.h} (98%) delete mode 100644 hc/CMakeLists.txt delete mode 100644 hc/eq.cpp delete mode 100644 hc/eq.h delete mode 100644 hc/login.cpp delete mode 100644 hc/login.h delete mode 100644 hc/main.cpp delete mode 100644 hc/world.cpp delete mode 100644 hc/world.h delete mode 100644 hc/zone.cpp delete mode 100644 hc/zone.h delete mode 100644 libs/zlibng/.gitattributes delete mode 100644 libs/zlibng/.github/workflows/analyze.yml delete mode 100644 libs/zlibng/.github/workflows/cmake.yml delete mode 100644 libs/zlibng/.github/workflows/configure.yml delete mode 100644 libs/zlibng/.github/workflows/fuzz.yml delete mode 100644 libs/zlibng/.github/workflows/libpng.yml delete mode 100644 libs/zlibng/.github/workflows/nmake.yml delete mode 100644 libs/zlibng/.github/workflows/pkgcheck.yml delete mode 100644 libs/zlibng/.github/workflows/release.yml delete mode 100644 libs/zlibng/.gitignore delete mode 100644 libs/zlibng/.shellcheckrc delete mode 100644 libs/zlibng/CMakeLists.txt delete mode 100644 libs/zlibng/FAQ.zlib delete mode 100644 libs/zlibng/INDEX.md delete mode 100644 libs/zlibng/LICENSE.md delete mode 100644 libs/zlibng/Makefile.in delete mode 100644 libs/zlibng/README.md delete mode 100644 libs/zlibng/adler32.c delete mode 100644 libs/zlibng/adler32_p.h delete mode 100644 libs/zlibng/arch/.gitignore delete mode 100644 libs/zlibng/arch/arm/Makefile.in delete mode 100644 libs/zlibng/arch/arm/adler32_neon.c delete mode 100644 libs/zlibng/arch/arm/arm.h delete mode 100644 libs/zlibng/arch/arm/armfeature.c delete mode 100644 libs/zlibng/arch/arm/chunkset_neon.c delete mode 100644 libs/zlibng/arch/arm/crc32_acle.c delete mode 100644 libs/zlibng/arch/arm/ctzl.h delete mode 100644 libs/zlibng/arch/arm/insert_string_acle.c delete mode 100644 libs/zlibng/arch/arm/slide_neon.c delete mode 100644 libs/zlibng/arch/generic/Makefile.in delete mode 100644 libs/zlibng/arch/power/Makefile.in delete mode 100644 libs/zlibng/arch/power/adler32_power8.c delete mode 100644 libs/zlibng/arch/power/power.c delete mode 100644 libs/zlibng/arch/power/power.h delete mode 100644 libs/zlibng/arch/power/slide_hash_power8.c delete mode 100644 libs/zlibng/arch/s390/Makefile.in delete mode 100644 libs/zlibng/arch/s390/README.md delete mode 100644 libs/zlibng/arch/s390/dfltcc_common.c delete mode 100644 libs/zlibng/arch/s390/dfltcc_common.h delete mode 100644 libs/zlibng/arch/s390/dfltcc_deflate.c delete mode 100644 libs/zlibng/arch/s390/dfltcc_deflate.h delete mode 100644 libs/zlibng/arch/s390/dfltcc_detail.h delete mode 100644 libs/zlibng/arch/s390/dfltcc_inflate.c delete mode 100644 libs/zlibng/arch/s390/dfltcc_inflate.h delete mode 100644 libs/zlibng/arch/x86/INDEX.md delete mode 100644 libs/zlibng/arch/x86/Makefile.in delete mode 100644 libs/zlibng/arch/x86/adler32_avx.c delete mode 100644 libs/zlibng/arch/x86/adler32_ssse3.c delete mode 100644 libs/zlibng/arch/x86/chunkset_avx.c delete mode 100644 libs/zlibng/arch/x86/chunkset_sse.c delete mode 100644 libs/zlibng/arch/x86/compare258_avx.c delete mode 100644 libs/zlibng/arch/x86/compare258_sse.c delete mode 100644 libs/zlibng/arch/x86/crc_folding.c delete mode 100644 libs/zlibng/arch/x86/crc_folding.h delete mode 100644 libs/zlibng/arch/x86/insert_string_sse.c delete mode 100644 libs/zlibng/arch/x86/slide_avx.c delete mode 100644 libs/zlibng/arch/x86/slide_sse.c delete mode 100644 libs/zlibng/arch/x86/x86.c delete mode 100644 libs/zlibng/arch/x86/x86.h delete mode 100644 libs/zlibng/chunkset.c delete mode 100644 libs/zlibng/chunkset_tpl.h delete mode 100644 libs/zlibng/cmake/detect-arch.c delete mode 100644 libs/zlibng/cmake/detect-arch.cmake delete mode 100644 libs/zlibng/cmake/detect-sanitizer.cmake delete mode 100644 libs/zlibng/cmake/run-and-compare.cmake delete mode 100644 libs/zlibng/cmake/run-and-redirect.cmake delete mode 100644 libs/zlibng/cmake/test-compress.cmake delete mode 100644 libs/zlibng/cmake/toolchain-aarch64.cmake delete mode 100644 libs/zlibng/cmake/toolchain-arm.cmake delete mode 100644 libs/zlibng/cmake/toolchain-mingw-i686.cmake delete mode 100644 libs/zlibng/cmake/toolchain-mingw-x86_64.cmake delete mode 100644 libs/zlibng/cmake/toolchain-powerpc.cmake delete mode 100644 libs/zlibng/cmake/toolchain-powerpc64.cmake delete mode 100644 libs/zlibng/cmake/toolchain-powerpc64le.cmake delete mode 100644 libs/zlibng/cmake/toolchain-s390x.cmake delete mode 100644 libs/zlibng/cmake/toolchain-sparc64.cmake delete mode 100644 libs/zlibng/compare258.c delete mode 100644 libs/zlibng/compress.c delete mode 100644 libs/zlibng/configure delete mode 100644 libs/zlibng/crc32.c delete mode 100644 libs/zlibng/crc32_comb.c delete mode 100644 libs/zlibng/crc32_comb_tbl.h delete mode 100644 libs/zlibng/crc32_p.h delete mode 100644 libs/zlibng/crc32_tbl.h delete mode 100644 libs/zlibng/deflate.c delete mode 100644 libs/zlibng/deflate.h delete mode 100644 libs/zlibng/deflate_fast.c delete mode 100644 libs/zlibng/deflate_medium.c delete mode 100644 libs/zlibng/deflate_p.h delete mode 100644 libs/zlibng/deflate_quick.c delete mode 100644 libs/zlibng/deflate_slow.c delete mode 100644 libs/zlibng/doc/algorithm.txt delete mode 100644 libs/zlibng/doc/rfc1950.txt delete mode 100644 libs/zlibng/doc/rfc1951.txt delete mode 100644 libs/zlibng/doc/rfc1952.txt delete mode 100644 libs/zlibng/doc/txtvsbin.txt delete mode 100644 libs/zlibng/fallback_builtins.h delete mode 100644 libs/zlibng/functable.c delete mode 100644 libs/zlibng/functable.h delete mode 100644 libs/zlibng/gzguts.h delete mode 100644 libs/zlibng/gzlib.c delete mode 100644 libs/zlibng/gzread.c delete mode 100644 libs/zlibng/gzwrite.c delete mode 100644 libs/zlibng/infback.c delete mode 100644 libs/zlibng/inffast.c delete mode 100644 libs/zlibng/inffast.h delete mode 100644 libs/zlibng/inffixed_tbl.h delete mode 100644 libs/zlibng/inflate.c delete mode 100644 libs/zlibng/inflate.h delete mode 100644 libs/zlibng/inflate_p.h delete mode 100644 libs/zlibng/inftrees.c delete mode 100644 libs/zlibng/inftrees.h delete mode 100644 libs/zlibng/insert_string.c delete mode 100644 libs/zlibng/insert_string_tpl.h delete mode 100644 libs/zlibng/match_tpl.h delete mode 100644 libs/zlibng/test/.gitignore delete mode 100644 libs/zlibng/test/CVE-2002-0059/test.gz delete mode 100644 libs/zlibng/test/CVE-2003-0107.c delete mode 100644 libs/zlibng/test/CVE-2004-0797/test.gz delete mode 100644 libs/zlibng/test/CVE-2005-1849/test.gz delete mode 100644 libs/zlibng/test/CVE-2005-2096/test.gz delete mode 100644 libs/zlibng/test/GH-361/test.txt delete mode 100644 libs/zlibng/test/GH-364/test.bin delete mode 100644 libs/zlibng/test/GH-382/defneg3.dat delete mode 100644 libs/zlibng/test/GH-751/test.txt delete mode 100644 libs/zlibng/test/Makefile.in delete mode 100644 libs/zlibng/test/README.md delete mode 100644 libs/zlibng/test/abi/ignore delete mode 100644 libs/zlibng/test/abi/zlib-v1.2.11-arm-linux-gnueabihf.abi delete mode 100644 libs/zlibng/test/abi/zlib-v1.2.11-x86_64-linux-gnu.abi delete mode 100644 libs/zlibng/test/abicheck.md delete mode 100644 libs/zlibng/test/abicheck.sh delete mode 100644 libs/zlibng/test/adler32_test.c delete mode 100644 libs/zlibng/test/data/fireworks.jpg delete mode 100644 libs/zlibng/test/data/lcet10.txt delete mode 100644 libs/zlibng/test/data/paper-100k.pdf delete mode 100644 libs/zlibng/test/example.c delete mode 100644 libs/zlibng/test/fuzz/checksum_fuzzer.c delete mode 100644 libs/zlibng/test/fuzz/compress_fuzzer.c delete mode 100644 libs/zlibng/test/fuzz/example_dict_fuzzer.c delete mode 100644 libs/zlibng/test/fuzz/example_flush_fuzzer.c delete mode 100644 libs/zlibng/test/fuzz/example_large_fuzzer.c delete mode 100644 libs/zlibng/test/fuzz/example_small_fuzzer.c delete mode 100644 libs/zlibng/test/fuzz/minigzip_fuzzer.c delete mode 100644 libs/zlibng/test/fuzz/standalone_fuzz_target_runner.c delete mode 100644 libs/zlibng/test/infcover.c delete mode 100644 libs/zlibng/test/minideflate.c delete mode 100644 libs/zlibng/test/minigzip.c delete mode 100644 libs/zlibng/test/pkgcheck.sh delete mode 100644 libs/zlibng/test/switchlevels.c delete mode 100644 libs/zlibng/test/testCVEinputs.sh delete mode 100644 libs/zlibng/tools/codecov-upload.sh delete mode 100644 libs/zlibng/tools/config.sub delete mode 100644 libs/zlibng/tools/makecrct.c delete mode 100644 libs/zlibng/tools/makefixed.c delete mode 100644 libs/zlibng/tools/maketrees.c delete mode 100644 libs/zlibng/trees.c delete mode 100644 libs/zlibng/trees.h delete mode 100644 libs/zlibng/trees_emit.h delete mode 100644 libs/zlibng/trees_tbl.h delete mode 100644 libs/zlibng/uncompr.c delete mode 100644 libs/zlibng/win32/DLL_FAQ.txt delete mode 100644 libs/zlibng/win32/Makefile.a64 delete mode 100644 libs/zlibng/win32/Makefile.arm delete mode 100644 libs/zlibng/win32/Makefile.msc delete mode 100644 libs/zlibng/win32/README-WIN32.txt delete mode 100644 libs/zlibng/win32/zlib-ng.def delete mode 100644 libs/zlibng/win32/zlib-ng1.rc delete mode 100644 libs/zlibng/win32/zlib.def delete mode 100644 libs/zlibng/win32/zlib1.rc delete mode 100644 libs/zlibng/win32/zlibcompat.def delete mode 100644 libs/zlibng/zbuild.h delete mode 100644 libs/zlibng/zconf-ng.h.in delete mode 100644 libs/zlibng/zconf.h.in delete mode 100644 libs/zlibng/zendian.h delete mode 100644 libs/zlibng/zlib-ng.h delete mode 100644 libs/zlibng/zlib-ng.map delete mode 100644 libs/zlibng/zlib.3 delete mode 100644 libs/zlibng/zlib.h delete mode 100644 libs/zlibng/zlib.map delete mode 100644 libs/zlibng/zlib.pc.cmakein delete mode 100644 libs/zlibng/zlib.pc.in delete mode 100644 libs/zlibng/zutil.c delete mode 100644 libs/zlibng/zutil.h delete mode 100644 libs/zlibng/zutil_p.h delete mode 160000 submodules/cereal delete mode 160000 submodules/fmt delete mode 160000 submodules/glm delete mode 160000 submodules/libuv delete mode 160000 submodules/recastnavigation create mode 160000 submodules/vcpkg create mode 100644 vcpkg.json rename world/cli/{bots_disable.cpp => cli_bots_disable.cpp} (96%) rename world/cli/{bots_enable.cpp => cli_bots_enable.cpp} (95%) rename world/cli/{copy_character.cpp => cli_copy_character.cpp} (93%) rename world/cli/{database_concurrency.cpp => cli_database_concurrency.cpp} (97%) rename world/cli/{database_dump.cpp => cli_database_dump.cpp} (98%) rename world/cli/{database_get_schema.cpp => cli_database_get_schema.cpp} (98%) rename world/cli/{database_set_account_status.cpp => cli_database_set_account_status.cpp} (93%) rename world/cli/{database_updates.cpp => cli_database_updates.cpp} (89%) rename world/cli/{database_version.cpp => cli_database_version.cpp} (95%) rename world/cli/{etl_get_settings.cpp => cli_etl_get_settings.cpp} (96%) rename world/cli/{mercs_disable.cpp => cli_mercs_disable.cpp} (96%) rename world/cli/{mercs_enable.cpp => cli_mercs_enable.cpp} (97%) rename world/cli/{test.cpp => cli_test.cpp} (96%) rename world/cli/{test_colors.cpp => cli_test_colors.cpp} (99%) rename world/cli/{test_expansion.cpp => cli_test_expansion.cpp} (97%) rename world/cli/{test_repository.cpp => cli_test_repository.cpp} (98%) rename world/cli/{test_repository_2.cpp => cli_test_repository_2.cpp} (88%) rename world/cli/{test_string_benchmark.cpp => cli_test_string_benchmark.cpp} (98%) rename world/cli/{version.cpp => cli_version.cpp} (95%) rename zone/bot_commands/{actionable.cpp => bot_actionable.cpp} (100%) rename zone/bot_commands/{appearance.cpp => bot_appearance.cpp} (100%) rename zone/bot_commands/{apply_poison.cpp => bot_apply_poison.cpp} (100%) rename zone/bot_commands/{apply_potion.cpp => bot_apply_potion.cpp} (100%) rename zone/bot_commands/{attack.cpp => bot_attack.cpp} (100%) rename zone/bot_commands/{behind_mob.cpp => bot_behind_mob.cpp} (100%) rename zone/bot_commands/{blocked_buffs.cpp => bot_blocked_buffs.cpp} (100%) rename zone/bot_commands/{bot.cpp => bot_bot.cpp} (100%) rename zone/bot_commands/{bot_settings.cpp => bot_bot_settings.cpp} (100%) rename zone/bot_commands/{cast.cpp => bot_cast.cpp} (100%) rename zone/bot_commands/{class_race_list.cpp => bot_class_race_list.cpp} (100%) rename zone/bot_commands/{click_item.cpp => bot_click_item.cpp} (100%) rename zone/bot_commands/{copy_settings.cpp => bot_copy_settings.cpp} (100%) rename zone/bot_commands/{default_settings.cpp => bot_default_settings.cpp} (100%) rename zone/bot_commands/{depart.cpp => bot_depart.cpp} (100%) rename zone/bot_commands/{discipline.cpp => bot_discipline.cpp} (100%) rename zone/bot_commands/{distance_ranged.cpp => bot_distance_ranged.cpp} (100%) rename zone/bot_commands/{find_aliases.cpp => bot_find_aliases.cpp} (100%) rename zone/bot_commands/{follow.cpp => bot_follow.cpp} (100%) rename zone/bot_commands/{guard.cpp => bot_guard.cpp} (100%) rename zone/bot_commands/{heal_rotation.cpp => bot_heal_rotation.cpp} (100%) rename zone/bot_commands/{help.cpp => bot_help.cpp} (100%) rename zone/bot_commands/{hold.cpp => bot_hold.cpp} (100%) rename zone/bot_commands/{illusion_block.cpp => bot_illusion_block.cpp} (100%) rename zone/bot_commands/{inventory.cpp => bot_inventory.cpp} (100%) rename zone/bot_commands/{item_use.cpp => bot_item_use.cpp} (100%) rename zone/bot_commands/{max_melee_range.cpp => bot_max_melee_range.cpp} (100%) rename zone/bot_commands/{name.cpp => bot_name.cpp} (100%) rename zone/bot_commands/{owner_option.cpp => bot_owner_option.cpp} (100%) rename zone/bot_commands/{pet.cpp => bot_pet.cpp} (100%) rename zone/bot_commands/{pick_lock.cpp => bot_pick_lock.cpp} (98%) rename zone/bot_commands/{pickpocket.cpp => bot_pickpocket.cpp} (100%) rename zone/bot_commands/{precombat.cpp => bot_precombat.cpp} (100%) rename zone/bot_commands/{pull.cpp => bot_pull.cpp} (100%) rename zone/bot_commands/{release.cpp => bot_release.cpp} (100%) rename zone/bot_commands/{set_assistee.cpp => bot_set_assistee.cpp} (100%) rename zone/bot_commands/{sit_hp_percent.cpp => bot_sit_hp_percent.cpp} (100%) rename zone/bot_commands/{sit_in_combat.cpp => bot_sit_in_combat.cpp} (100%) rename zone/bot_commands/{sit_mana_percent.cpp => bot_sit_mana_percent.cpp} (100%) rename zone/bot_commands/{spell.cpp => bot_spell.cpp} (100%) rename zone/bot_commands/{spell_aggro_checks.cpp => bot_spell_aggro_checks.cpp} (100%) rename zone/bot_commands/{spell_announce_cast.cpp => bot_spell_announce_cast.cpp} (100%) rename zone/bot_commands/{spell_delays.cpp => bot_spell_delays.cpp} (100%) rename zone/bot_commands/{spell_engaged_priority.cpp => bot_spell_engaged_priority.cpp} (100%) rename zone/bot_commands/{spell_holds.cpp => bot_spell_holds.cpp} (100%) rename zone/bot_commands/{spell_idle_priority.cpp => bot_spell_idle_priority.cpp} (100%) rename zone/bot_commands/{spell_max_hp_pct.cpp => bot_spell_max_hp_pct.cpp} (100%) rename zone/bot_commands/{spell_max_mana_pct.cpp => bot_spell_max_mana_pct.cpp} (100%) rename zone/bot_commands/{spell_max_thresholds.cpp => bot_spell_max_thresholds.cpp} (100%) rename zone/bot_commands/{spell_min_hp_pct.cpp => bot_spell_min_hp_pct.cpp} (100%) rename zone/bot_commands/{spell_min_mana_pct.cpp => bot_spell_min_mana_pct.cpp} (100%) rename zone/bot_commands/{spell_min_thresholds.cpp => bot_spell_min_thresholds.cpp} (100%) rename zone/bot_commands/{spell_pursue_priority.cpp => bot_spell_pursue_priority.cpp} (100%) rename zone/bot_commands/{spell_resist_limits.cpp => bot_spell_resist_limits.cpp} (100%) rename zone/bot_commands/{spell_target_count.cpp => bot_spell_target_count.cpp} (100%) rename zone/bot_commands/{spelltypes.cpp => bot_spelltypes.cpp} (100%) rename zone/bot_commands/{summon.cpp => bot_summon.cpp} (100%) rename zone/bot_commands/{suspend.cpp => bot_suspend.cpp} (100%) rename zone/bot_commands/{taunt.cpp => bot_taunt.cpp} (100%) rename zone/bot_commands/{timer.cpp => bot_timer.cpp} (100%) rename zone/bot_commands/{track.cpp => bot_track.cpp} (100%) rename zone/bot_commands/{view_combos.cpp => bot_view_combos.cpp} (100%) rename zone/cli/{benchmark_databuckets.cpp => cli_benchmark_databuckets.cpp} (96%) rename zone/cli/{sidecar_serve_http.cpp => cli_sidecar_serve_http.cpp} (88%) rename zone/cli/tests/{databuckets.cpp => cli_databuckets.cpp} (97%) rename zone/cli/tests/{npc_handins.cpp => cli_npc_handins.cpp} (97%) rename zone/cli/tests/{npc_handins_multiquest.cpp => cli_npc_handins_multiquest.cpp} (93%) rename zone/cli/tests/{_test_util.cpp => cli_test_util.cpp} (81%) rename zone/cli/tests/{zone_state.cpp => cli_zone_state.cpp} (98%) create mode 100644 zone/gm_commands/CMakeLists.txt rename zone/gm_commands/find/{aa.cpp => find_aa.cpp} (100%) rename zone/gm_commands/find/{account.cpp => find_account.cpp} (94%) rename zone/gm_commands/find/{body_type.cpp => find_body_type.cpp} (100%) rename zone/gm_commands/find/{bot.cpp => find_bot.cpp} (96%) rename zone/gm_commands/find/{bug_category.cpp => find_bug_category.cpp} (100%) rename zone/gm_commands/find/{character.cpp => find_character.cpp} (95%) rename zone/gm_commands/find/{class.cpp => find_class.cpp} (100%) rename zone/gm_commands/find/{comparison_type.cpp => find_comparison_type.cpp} (100%) rename zone/gm_commands/find/{currency.cpp => find_currency.cpp} (100%) rename zone/gm_commands/find/{deity.cpp => find_deity.cpp} (100%) rename zone/gm_commands/find/{emote.cpp => find_emote.cpp} (100%) rename zone/gm_commands/find/{faction.cpp => find_faction.cpp} (100%) rename zone/gm_commands/find/{item.cpp => find_item.cpp} (97%) rename zone/gm_commands/find/{language.cpp => find_language.cpp} (100%) rename zone/gm_commands/find/{ldon_theme.cpp => find_ldon_theme.cpp} (100%) rename zone/gm_commands/find/{npctype.cpp => find_npctype.cpp} (100%) rename zone/gm_commands/find/{object_type.cpp => find_object_type.cpp} (100%) rename zone/gm_commands/find/{race.cpp => find_race.cpp} (100%) rename zone/gm_commands/find/{recipe.cpp => find_recipe.cpp} (96%) rename zone/gm_commands/find/{skill.cpp => find_skill.cpp} (100%) rename zone/gm_commands/find/{special_ability.cpp => find_special_ability.cpp} (100%) rename zone/gm_commands/find/{spell.cpp => find_spell.cpp} (97%) rename zone/gm_commands/find/{stance.cpp => find_stance.cpp} (100%) rename zone/gm_commands/find/{task.cpp => find_task.cpp} (97%) rename zone/gm_commands/find/{zone.cpp => find_zone.cpp} (98%) rename zone/gm_commands/set/{aa_exp.cpp => set_aa_exp.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{aa_points.cpp => set_aa_points.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{adventure_points.cpp => set_adventure_points.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{alternate_currency.cpp => set_alternate_currency.cpp} (100%) rename zone/gm_commands/set/{animation.cpp => set_animation.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{anon.cpp => set_anon.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{auto_login.cpp => set_auto_login.cpp} (95%) mode change 100755 => 100644 rename zone/gm_commands/set/{bind_point.cpp => set_bind_point.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{checksum.cpp => set_checksum.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{class_permanent.cpp => set_class_permanent.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{crystals.cpp => set_crystals.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{date.cpp => set_date.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{endurance.cpp => set_endurance.cpp} (100%) rename zone/gm_commands/set/{endurance_full.cpp => set_endurance_full.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{exp.cpp => set_exp.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{flymode.cpp => set_flymode.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{frozen.cpp => set_frozen.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{gender.cpp => set_gender.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{gender_permanent.cpp => set_gender_permanent.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{gm.cpp => set_gm.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{gm_speed.cpp => set_gm_speed.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{gm_status.cpp => set_gm_status.cpp} (100%) rename zone/gm_commands/set/{god_mode.cpp => set_god_mode.cpp} (100%) rename zone/gm_commands/set/{haste.cpp => set_haste.cpp} (100%) rename zone/gm_commands/set/{hero_model.cpp => set_hero_model.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{hide_me.cpp => set_hide_me.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{hp.cpp => set_hp.cpp} (100%) rename zone/gm_commands/set/{hp_full.cpp => set_hp_full.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{invulnerable.cpp => set_invulnerable.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{language.cpp => set_language.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{last_name.cpp => set_last_name.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{level.cpp => set_level.cpp} (100%) rename zone/gm_commands/set/{loginserver_info.cpp => set_loginserver_info.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{mana.cpp => set_mana.cpp} (100%) rename zone/gm_commands/set/{mana_full.cpp => set_mana_full.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{motd.cpp => set_motd.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{name.cpp => set_name.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{ooc_mute.cpp => set_ooc_mute.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{password.cpp => set_password.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{pvp.cpp => set_pvp.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{pvp_points.cpp => set_pvp_points.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{race.cpp => set_race.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{race_permanent.cpp => set_race_permanent.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{server_locked.cpp => set_server_locked.cpp} (100%) rename zone/gm_commands/set/{skill.cpp => set_skill.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{skill_all.cpp => set_skill_all.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{skill_all_max.cpp => set_skill_all_max.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{start_zone.cpp => set_start_zone.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{temporary_name.cpp => set_temporary_name.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{texture.cpp => set_texture.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{time.cpp => set_time.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{time_zone.cpp => set_time_zone.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{title.cpp => set_title.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{title_suffix.cpp => set_title_suffix.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{weather.cpp => set_weather.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/set/{zone.cpp => set_zone.cpp} (99%) mode change 100755 => 100644 rename zone/gm_commands/show/{aa_points.cpp => show_aa_points.cpp} (100%) rename zone/gm_commands/show/{aas.cpp => show_aas.cpp} (100%) rename zone/gm_commands/show/{aggro.cpp => show_aggro.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/show/{auto_login.cpp => show_auto_login.cpp} (92%) rename zone/gm_commands/show/{buffs.cpp => show_buffs.cpp} (100%) rename zone/gm_commands/show/{buried_corpse_count.cpp => show_buried_corpse_count.cpp} (100%) rename zone/gm_commands/show/{client_version_summary.cpp => show_client_version_summary.cpp} (100%) rename zone/gm_commands/show/{content_flags.cpp => show_content_flags.cpp} (100%) rename zone/gm_commands/show/{currencies.cpp => show_currencies.cpp} (100%) rename zone/gm_commands/show/{distance.cpp => show_distance.cpp} (100%) rename zone/gm_commands/show/{emotes.cpp => show_emotes.cpp} (100%) rename zone/gm_commands/show/{field_of_view.cpp => show_field_of_view.cpp} (100%) rename zone/gm_commands/show/{flags.cpp => show_flags.cpp} (100%) rename zone/gm_commands/show/{group_info.cpp => show_group_info.cpp} (100%) rename zone/gm_commands/show/{hatelist.cpp => show_hatelist.cpp} (100%) rename zone/gm_commands/show/{inventory.cpp => show_inventory.cpp} (100%) rename zone/gm_commands/show/{ip_lookup.cpp => show_ip_lookup.cpp} (100%) rename zone/gm_commands/show/{keyring.cpp => show_keyring.cpp} (100%) rename zone/gm_commands/show/{line_of_sight.cpp => show_line_of_sight.cpp} (100%) rename zone/gm_commands/show/{network.cpp => show_network.cpp} (100%) rename zone/gm_commands/show/{network_stats.cpp => show_network_stats.cpp} (100%) rename zone/gm_commands/show/{npc_global_loot.cpp => show_npc_global_loot.cpp} (100%) rename zone/gm_commands/show/{npc_stats.cpp => show_npc_stats.cpp} (100%) rename zone/gm_commands/show/{npc_type.cpp => show_npc_type.cpp} (100%) rename zone/gm_commands/show/{peqzone_flags.cpp => show_peqzone_flags.cpp} (100%) rename zone/gm_commands/show/{petition.cpp => show_petition.cpp} (94%) rename zone/gm_commands/show/{petition_info.cpp => show_petition_info.cpp} (96%) rename zone/gm_commands/show/{proximity.cpp => show_proximity.cpp} (100%) rename zone/gm_commands/show/{quest_errors.cpp => show_quest_errors.cpp} (100%) rename zone/gm_commands/show/{quest_globals.cpp => show_quest_globals.cpp} (100%) rename zone/gm_commands/show/{recipe.cpp => show_recipe.cpp} (93%) rename zone/gm_commands/show/{server_info.cpp => show_server_info.cpp} (98%) rename zone/gm_commands/show/{skills.cpp => show_skills.cpp} (100%) rename zone/gm_commands/show/{spawn_status.cpp => show_spawn_status.cpp} (100%) rename zone/gm_commands/show/{special_abilities.cpp => show_special_abilities.cpp} (100%) rename zone/gm_commands/show/{spells.cpp => show_spells.cpp} (100%) rename zone/gm_commands/show/{spells_list.cpp => show_spells_list.cpp} (100%) rename zone/gm_commands/show/{stats.cpp => show_stats.cpp} (100%) rename zone/gm_commands/show/{timers.cpp => show_timers.cpp} (100%) rename zone/gm_commands/show/{traps.cpp => show_traps.cpp} (100%) rename zone/gm_commands/show/{uptime.cpp => show_uptime.cpp} (100%) rename zone/gm_commands/show/{variable.cpp => show_variable.cpp} (100%) rename zone/gm_commands/show/{version.cpp => show_version.cpp} (100%) rename zone/gm_commands/show/{waypoints.cpp => show_waypoints.cpp} (100%) rename zone/gm_commands/show/{who.cpp => show_who.cpp} (100%) mode change 100755 => 100644 rename zone/gm_commands/show/{xtargets.cpp => show_xtargets.cpp} (94%) rename zone/gm_commands/show/{zone_data.cpp => show_zone_data.cpp} (100%) rename zone/gm_commands/show/{zone_global_loot.cpp => show_zone_global_loot.cpp} (100%) rename zone/gm_commands/show/{zone_loot.cpp => show_zone_loot.cpp} (100%) rename zone/gm_commands/show/{zone_points.cpp => show_zone_points.cpp} (100%) rename zone/gm_commands/show/{zone_status.cpp => show_zone_status.cpp} (100%) rename zone/gm_commands/show/{zone_variables.cpp => show_zone_variables.cpp} (100%) delete mode 100644 zone/sidecar_api/log_handler.cpp delete mode 100644 zone/sidecar_api/map_best_z_controller.cpp delete mode 100644 zone/sidecar_api/test_controller.cpp diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c9650cf56d..adcdf726a3 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -23,7 +23,7 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get install -y build-essential ninja-build ccache libmariadb-dev libmariadb-dev-compat libboost-all-dev libperl-dev liblua5.1-0-dev libluajit-5.1-dev zlib1g-dev uuid-dev libssl-dev libsodium-dev libmbedtls-dev + sudo apt-get install -y build-essential ninja-build ccache uuid-dev - name: Configure run: | diff --git a/.gitmodules b/.gitmodules index c9c3988cb6..b7f3564e59 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,18 +1,6 @@ -[submodule "submodules/glm"] - path = submodules/glm - url = https://github.com/g-truc/glm.git -[submodule "submodules/fmt"] - path = submodules/fmt - url = https://github.com/fmtlib/fmt.git -[submodule "submodules/libuv"] - path = submodules/libuv - url = https://github.com/libuv/libuv.git -[submodule "submodules/cereal"] - path = submodules/cereal - url = https://github.com/USCiLab/cereal.git [submodule "submodules/websocketpp"] path = submodules/websocketpp url = https://github.com/zaphoyd/websocketpp.git -[submodule "submodules/recastnavigation"] - path = submodules/recastnavigation - url = https://github.com/EQEmu/recastnavigation.git +[submodule "submodules/vcpkg"] + path = submodules/vcpkg + url = https://github.com/microsoft/vcpkg.git diff --git a/BUILD.md b/BUILD.md index c1051f2b63..a49192a967 100644 --- a/BUILD.md +++ b/BUILD.md @@ -4,46 +4,35 @@ This guide is far from exhaustive, you should expect to have some experience wit ### CMake -EQEmu uses CMake as the build system on all platforms. You will need CMake 3.2 or higher to build from source. +EQEmu uses CMake as the build system on all platforms. You will need CMake 3.20 or higher to build from source. ### Dependencies The following libraries are required to build from source: -- [boost](https://www.boost.org/ "boost") -- [zlib](https://www.zlib.net/ "zlib") (If not included the source will build [zlib-ng](https://github.com/zlib-ng/zlib-ng "zlib-ng") instead) -- [libmysql](https://dev.mysql.com/downloads/connector/c/ "libmysql") or [libmariadb](https://github.com/MariaDB/mariadb-connector-c "libmariadb") +- uuid (unix) The following libraries are not strictly required but in many cased recommended. -- [OpenSSL](https://www.openssl.org/ "OpenSSL") or [mbedTLS](https://tls.mbed.org/ "mbedTLS") (Required for the loginserver and headless client) -- [libsodium](https://github.com/jedisct1/libsodium "libsodium") (Required for strong password hashing on the loginserver) -- [Lua 5.1](https://www.lua.org/ "Lua 5.1") or [LuaJit](http://luajit.org/ "LuaJit") (Required for Lua Quest Scripting) - [Perl](https://www.perl.org/ "Perl") (Required for Perl Quest Scripting) ##### Windows -For windows it is suggested you make use of [vcpkg](https://github.com/microsoft/vcpkg "vcpkg") if you wish to build your own dependencies. - If you wish to use Perl then you should use whichever version of Perl you have installed on the target system. -You can also download a vcpkg export from our releases section for Visual Studio [x86](https://github.com/EQEmu/Server/releases/download/v1.2/vcpkg-export-x86.zip "x86") or [x64](https://github.com/EQEmu/Server/releases/download/v1.2/vcpkg-export-x64.zip "x64") that includes a toolchain file you can pass to CMake. - ##### Linux For Linux you simply can install the dependencies from your package manager, below is an example of doing it on Ubuntu using apt-get. - sudo apt-get install libmysqlclient-dev libperl-dev libboost-dev liblua5.1-0-dev zlib1g-dev uuid-dev libssl-dev + sudo apt-get install libperl-dev uuid-dev ### Running CMake ##### Windows The following is a modified command our automated build server uses to run CMake via the release vcpkg export and its toolchain file. -Assuming it is starting in c:/projects/eqemu and the x64 dependencies were extracted to c:/projects/eqemu/vcpkg. - mkdir build cd build - cmake -G "Visual Studio 15 2017 Win64" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_ZLIB=ON -DCMAKE_TOOLCHAIN_FILE="c:/projects/eqemu/vcpkg/vcpkg-export-20180828-145455/scripts/buildsystems/vcpkg.cmake" .. + cmake -G "Visual Studio 15 2022 Win64" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON .. ##### Linux -Similarly to Windows running CMake on Linux is simple it just omits the toolchain file and uses a different generator. +Similarly to Windows running CMake on Linux is simple it just uses a different generator. mkdir build cd build diff --git a/CMakeLists.txt b/CMakeLists.txt index 59279caa8c..8470bbbf47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,490 +1,180 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.12) - -SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH}) - -IF(POLICY CMP0074) - CMAKE_POLICY(SET CMP0074 NEW) -ENDIF() - -PROJECT(EQEmu) - -IF(NOT CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) -ENDIF(NOT CMAKE_BUILD_TYPE) - -SET(CMAKE_CXX_STANDARD 20) -SET(CMAKE_CXX_STANDARD_REQUIRED ON) -SET(CMAKE_CXX_EXTENSIONS OFF) - -OPTION(EQEMU_BUILD_STATIC "Build with static linking" OFF) -OPTION(EQEMU_BUILD_PCH "Build with precompiled headers (Windows)" ON) - -IF (EQEMU_BUILD_STATIC) - SET(BUILD_SHARED_LIBS OFF) - SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a") - MESSAGE(STATUS "Building with static linking") - SET(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++") - IF (UNIX) - SET(PERL_LIBRARY "/opt/eqemu-perl/lib/5.32.1/x86_64-linux-thread-multi/CORE/libperl.so") - SET(PERL_INCLUDE_PATH "/opt/eqemu-perl/lib/5.32.1/x86_64-linux-thread-multi/CORE/") - SET(PERL_EXECUTABLE "/opt/eqemu-perl/bin/perl") - ENDIF () -ENDIF (EQEMU_BUILD_STATIC) - - -# Requires libgoogle-perftools-dev google-perftools packages for linux (debian) -IF(EQEMU_ADD_PROFILER) - SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--no-as-needed,-lprofiler,--as-needed") -ENDIF(EQEMU_ADD_PROFILER) - -IF(USE_MAP_MMFS) - ADD_DEFINITIONS(-DUSE_MAP_MMFS) -ENDIF (USE_MAP_MMFS) - -IF(MSVC) +cmake_minimum_required(VERSION 3.20.0) + +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH}) + +if(NOT CMAKE_TOOLCHAIN_FILE) + if(DEFINED ENV{VCPKG_ROOT}) + message(STATUS "Using vcpkg from VCPKG_ROOT") + set(CMAKE_TOOLCHAIN_FILE + "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + CACHE FILEPATH "Vcpkg toolchain file" + ) + else() + message(STATUS "Using vcpkg submodule") + set(CMAKE_TOOLCHAIN_FILE + "${CMAKE_CURRENT_SOURCE_DIR}/submodules/vcpkg/scripts/buildsystems/vcpkg.cmake" + CACHE FILEPATH "Vcpkg toolchain file" + ) + endif() +endif() + +project(EQEmu + VERSION 24.10.3 + LANGUAGES CXX +) + +#explicitly set CMP0167 for Find Boost +if(POLICY CMP0167) + cmake_policy(SET CMP0167 NEW) +endif() + +if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Build type") +endif() + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +option(EQEMU_BUILD_PCH "Build with precompiled headers (Windows)" ON) + +if(MSVC) add_compile_options(/bigobj) - ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) - ADD_DEFINITIONS(-DNOMINMAX) - ADD_DEFINITIONS(-DCRASH_LOGGING) - ADD_DEFINITIONS(-D_HAS_AUTO_PTR_ETC) # for Luabind on C++17 + add_compile_definitions(_CRT_SECURE_NO_WARNINGS NOMINMAX CRASH_LOGGING _HAS_AUTO_PTR_ETC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") - - OPTION(EQEMU_DISABLE_MSVC_WARNINGS "Disable MSVC compile warnings." ON) - IF(EQEMU_DISABLE_MSVC_WARNINGS) - ADD_DEFINITIONS( "/W0 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo /Os") - ENDIF(EQEMU_DISABLE_MSVC_WARNINGS) -ELSE(MSVC) - ADD_DEFINITIONS(-DHAS_UNION_SEMUN) -ENDIF(MSVC) + option(EQEMU_DISABLE_MSVC_WARNINGS "Disable MSVC compile warnings." ON) + if(EQEMU_DISABLE_MSVC_WARNINGS) + add_compile_options(/W0 /wd4005 /wd4996 /nologo /Os) + endif() +else() + add_compile_definitions(HAS_UNION_SEMUN) +endif() #FreeBSD support -IF(UNIX) - IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - ADD_DEFINITIONS(-DFREEBSD) - ADD_DEFINITIONS(-D_GLIBCXX_USE_C99) - SET(FREEBSD TRUE) - ENDIF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - IF(CMAKE_SYSTEM_NAME MATCHES "Darwin") - ADD_DEFINITIONS(-DDARWIN) - SET(DARWIN TRUE) - ENDIF(CMAKE_SYSTEM_NAME MATCHES "Darwin") -ENDIF(UNIX) - -ADD_DEFINITIONS(-DGLM_FORCE_RADIANS) -ADD_DEFINITIONS(-DGLM_FORCE_CTOR_INIT) -ADD_DEFINITIONS(-DGLM_ENABLE_EXPERIMENTAL) - -#MSVC can fetch dependencies automatically. -IF(MSVC) - INCLUDE("${CMAKE_SOURCE_DIR}/cmake/DependencyHelperMSVC.cmake") -ENDIF() - -#Find everything we need -FIND_PACKAGE(Boost REQUIRED) -FIND_PACKAGE(MySQL) -FIND_PACKAGE(MariaDB) -FIND_PACKAGE(ZLIB) -FIND_PACKAGE(OpenSSL) -FIND_PACKAGE(Lua51) -FIND_PACKAGE(LuaJit) -FIND_PACKAGE(PerlLibs) -FIND_PACKAGE(Sodium) -FIND_PACKAGE(mbedTLS) - -MESSAGE(STATUS "**************************************************") -MESSAGE(STATUS "* Library Detection *") -MESSAGE(STATUS "**************************************************") - -IF(MYSQL_FOUND) - MESSAGE(STATUS "* MySQL: FOUND *") -ELSE() - MESSAGE(STATUS "* MySQL: MISSING *") -ENDIF() - -IF(MARIADB_FOUND) - MESSAGE(STATUS "* MariaDB: FOUND *") -ELSE() - MESSAGE(STATUS "* MariaDB: MISSING *") -ENDIF() - -IF(ZLIB_FOUND) - MESSAGE(STATUS "* ZLIB: FOUND *") -ELSE() - MESSAGE(STATUS "* ZLIB: MISSING *") -ENDIF() - -IF(Lua51_FOUND) - MESSAGE(STATUS "* Lua: FOUND *") -ELSE() - MESSAGE(STATUS "* Lua: MISSING *") -ENDIF() - -IF(LuaJit_FOUND) - MESSAGE(STATUS "* LuaJIT: FOUND *") -ELSE() - MESSAGE(STATUS "* LuaJIT: MISSING *") -ENDIF() - -IF(PerlLibs_FOUND) - MESSAGE(STATUS "* Perl: FOUND *") -ELSE() - MESSAGE(STATUS "* Perl: MISSING *") -ENDIF() - -IF(SODIUM_FOUND) - MESSAGE(STATUS "* libsodium: FOUND *") -ELSE() - MESSAGE(STATUS "* libsodium: MISSING *") -ENDIF() - -IF(OpenSSL_FOUND) - MESSAGE(STATUS "* OpenSSL: FOUND *") -ELSE() - MESSAGE(STATUS "* OpenSSL: MISSING *") -ENDIF() - -IF(MBEDTLS_FOUND) - MESSAGE(STATUS "* mbedTLS: FOUND *") -ELSE() - MESSAGE(STATUS "* mbedTLS: MISSING *") -ENDIF() - -MESSAGE(STATUS "PERL_INCLUDE_PATH: ${PERL_INCLUDE_PATH}") -MESSAGE(STATUS "PERL_LIBRARY: ${PERL_LIBRARY}") -MESSAGE(STATUS "PERL_INCLUDE_DIR: ${PERL_INCLUDE_DIR}") -MESSAGE(STATUS "PERL_INCLUDE_DIRS: ${PERL_INCLUDE_DIRS}") -MESSAGE(STATUS "PERL_LIBRARIES: ${PERL_LIBRARIES}") -MESSAGE(STATUS "PERL_VERSION: ${PERL_VERSION}") - -MESSAGE(STATUS "**************************************************") +if(UNIX) + if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + add_compile_definitions(FREEBSD) + add_compile_definitions(_GLIBCXX_USE_C99) + set(FREEBSD TRUE) + endif() + if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + add_compile_definitions(DARWIN) + set(DARWIN TRUE) + endif() +endif() + +find_package(Boost REQUIRED COMPONENTS dynamic_bitset foreach tuple) +find_package(cereal CONFIG REQUIRED) +find_package(fmt CONFIG REQUIRED) +find_package(glm CONFIG REQUIRED) +find_package(unofficial-libmariadb CONFIG REQUIRED) +find_package(libuv CONFIG REQUIRED) +find_package(OpenSSL REQUIRED) +find_package(recastnavigation CONFIG REQUIRED) +find_package(ZLIB REQUIRED) +find_package(LuaJit REQUIRED) +find_package(unofficial-sodium CONFIG REQUIRED) +find_package(PerlLibs) + +message(STATUS "**************************************************") +message(STATUS "* Library Detection *") +message(STATUS "**************************************************") + +if(MARIADB_FOUND) + message(STATUS "* MariaDB: FOUND *") +else() + message(STATUS "* MariaDB: MISSING *") +endif() + +if(ZLIB_FOUND) + message(STATUS "* ZLIB: FOUND *") +else() + message(STATUS "* ZLIB: MISSING *") +endif() + +if(LuaJit_FOUND) + message(STATUS "* LuaJIT: FOUND *") +else() + message(STATUS "* LuaJIT: MISSING *") +endif() + +if(PerlLibs_FOUND) + message(STATUS "* Perl: FOUND *") +else() + message(STATUS "* Perl: MISSING *") +endif() + +if(OpenSSL_FOUND) + message(STATUS "* OpenSSL: FOUND *") +else() + message(STATUS "* OpenSSL: MISSING *") +endif() + +message(STATUS "PERL_INCLUDE_PATH: ${PERL_INCLUDE_PATH}") +message(STATUS "PERL_LIBRARY: ${PERL_LIBRARY}") +message(STATUS "PERL_INCLUDE_DIR: ${PERL_INCLUDE_DIR}") +message(STATUS "PERL_INCLUDE_DIRS: ${PERL_INCLUDE_DIRS}") +message(STATUS "PERL_LIBRARIES: ${PERL_LIBRARIES}") +message(STATUS "PERL_VERSION: ${PERL_VERSION}") +message(STATUS "**************************************************") #options -OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON) -OPTION(EQEMU_BUILD_SERVER "Build the game server." ON) -OPTION(EQEMU_BUILD_LOGIN "Build the login server." ON) -OPTION(EQEMU_BUILD_HC "Build the headless client." OFF) -OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF) -OPTION(EQEMU_BUILD_CLIENT_FILES "Build Client Import/Export Data Programs." ON) -OPTION(EQEMU_PREFER_LUA "Build with normal Lua even if LuaJIT is found." OFF) - -#PRNG options -OPTION(EQEMU_ADDITIVE_LFIB_PRNG "Use Additive LFib for PRNG." OFF) -MARK_AS_ADVANCED(EQEMU_ADDITIVE_LFIB_PRNG) -OPTION(EQEMU_BIASED_INT_DIST "Use biased int dist instead of uniform." OFF) -MARK_AS_ADVANCED(EQEMU_BIASED_INT_DIST) -SET(EQEMU_CUSTOM_PRNG_ENGINE "" CACHE STRING "Custom random engine. (ex. std::default_random_engine)") -MARK_AS_ADVANCED(EQEMU_CUSTOM_PRNG_ENGINE) - -IF(CMAKE_COMPILER_IS_GNUCXX) - OPTION(EQEMU_SFMT19937 "Use GCC's extention for SIMD Fast MT19937." OFF) - MARK_AS_ADVANCED(EQEMU_SFMT19937) -ENDIF() - -IF(EQEMU_ADDITIVE_LFIB_PRNG) - ADD_DEFINITIONS(-DUSE_ADDITIVE_LFIB_PRNG) - IF(EQEMU_SFMT19937) - MESSAGE(STATUS "SFMT19937 and ADDITITVE_LFIB_PRNG both set, SFMT19937 ignored.") - SET(EQEMU_SFMT19937 OFF) - ENDIF() - IF(NOT EQEMU_CUSTOM_PRNG_ENGINE STREQUAL "") - MESSAGE(STATUS "CUSTOM_PRNG_ENGINE and ADDITITVE_LFIB_PRNG both set, CUSTOM_PRNG_ENGINE ignored.") - SET(EQEMU_CUSTOM_PRNG_ENGINE "") - ENDIF() -ENDIF() - -IF(EQEMU_SFMT19937) - ADD_DEFINITIONS(-DUSE_SFMT19937) - IF(NOT EQEMU_CUSTOM_PRNG_ENGINE STREQUAL "") - MESSAGE(STATUS "CUSTOM_PRNG_ENGINE and SFMT19937 both set, CUSTOM_PRNG_ENGINE ignored.") - SET(EQEMU_CUSTOM_PRNG_ENGINE "") - ENDIF() -ENDIF() - -IF(NOT EQEMU_CUSTOM_PRNG_ENGINE STREQUAL "") - ADD_DEFINITIONS(-DUSE_CUSTOM_PRNG_ENGINE=${EQEMU_CUSTOM_PRNG_ENGINE}) -ENDIF() - -IF(EQEMU_BIASED_INT_DIST) - ADD_DEFINITIONS(-DBIASED_INT_DIST) -ENDIF() - -IF(EQEMU_COMMANDS_LOGGING) - ADD_DEFINITIONS(-DCOMMANDS_LOGGING) -ENDIF(EQEMU_COMMANDS_LOGGING) - -#database -IF(MySQL_FOUND AND MariaDB_FOUND) - SET(DATABASE_LIBRARY_SELECTION MariaDB CACHE STRING "Database library to use: - MySQL - MariaDB" - ) - - IF(DATABASE_LIBRARY_SELECTION STREQUAL "MySQL") - SET(DATABASE_LIBRARY_TYPE " MySQL") - SET(DATABASE_LIBRARY_LIBS ${MySQL_LIBRARIES}) - SET(DATABASE_LIBRARY_INCLUDE ${MySQL_INCLUDE_DIR}) - ELSEIF(DATABASE_LIBRARY_SELECTION STREQUAL "MariaDB") - SET(DATABASE_LIBRARY_TYPE "MariaDB") - SET(DATABASE_LIBRARY_LIBS ${MariaDB_LIBRARIES}) - SET(DATABASE_LIBRARY_INCLUDE ${MariaDB_INCLUDE_DIR}) - ELSE() - MESSAGE(FATAL_ERROR "Unknown database library set, should be one of: MySQL, MariaDB") - ENDIF() -ELSEIF(MariaDB_FOUND) - SET(DATABASE_LIBRARY_TYPE "MariaDB") - SET(DATABASE_LIBRARY_LIBS ${MariaDB_LIBRARIES}) - SET(DATABASE_LIBRARY_INCLUDE ${MariaDB_INCLUDE_DIR}) -ELSEIF(MySQL_FOUND) - SET(DATABASE_LIBRARY_TYPE " MySQL") - SET(DATABASE_LIBRARY_LIBS ${MySQL_LIBRARIES}) - SET(DATABASE_LIBRARY_INCLUDE ${MySQL_INCLUDE_DIR}) -ELSE() - MESSAGE(FATAL_ERROR "One of MySQL or MariaDB is a required dependency.") -ENDIF() - -#security -#prefer openssl to mbedtls (arbitrary) -IF(OpenSSL_FOUND AND MBEDTLS_FOUND) - SET(TLS_LIBRARY_SELECTION OpenSSL CACHE STRING "TLS library to use: - OpenSSL - mbedTLS" - ) - - IF(TLS_LIBRARY_SELECTION STREQUAL "OpenSSL") - SET(TLS_LIBRARY_TYPE " OpenSSL") - SET(TLS_LIBRARY_ENABLED ON) - SET(TLS_LIBRARY_LIBS ${OPENSSL_LIBRARIES}) - SET(TLS_LIBRARY_INCLUDE ${OPENSSL_INCLUDE_DIR}) - ADD_DEFINITIONS(-DEQEMU_USE_OPENSSL) - IF(${OPENSSL_VERSION} VERSION_GREATER_EQUAL "1.1.1") - ADD_DEFINITIONS(-DCPPHTTPLIB_OPENSSL_SUPPORT) - ENDIF() - ELSEIF(TLS_LIBRARY_SELECTION STREQUAL "mbedTLS") - SET(TLS_LIBRARY_TYPE " mbedTLS") - SET(TLS_LIBRARY_ENABLED ON) - SET(TLS_LIBRARY_LIBS ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) - SET(TLS_LIBRARY_INCLUDE ${MBEDTLS_INCLUDE_DIR}) - ADD_DEFINITIONS(-DEQEMU_USE_MBEDTLS) - ELSE() - MESSAGE(FATAL_ERROR "Unknown TLS library set, should be one of: OpenSSL, mbedTLS") - ENDIF() -ELSEIF(OpenSSL_FOUND) - SET(TLS_LIBRARY_TYPE " OpenSSL") - SET(TLS_LIBRARY_ENABLED ON) - SET(TLS_LIBRARY_LIBS ${OPENSSL_LIBRARIES}) - SET(TLS_LIBRARY_INCLUDE ${OPENSSL_INCLUDE_DIR}) - ADD_DEFINITIONS(-DEQEMU_USE_OPENSSL) - IF(${OPENSSL_VERSION} VERSION_GREATER_EQUAL "1.1.1") - ADD_DEFINITIONS(-DCPPHTTPLIB_OPENSSL_SUPPORT) - ENDIF() -ELSEIF(MBEDTLS_FOUND) - SET(TLS_LIBRARY_TYPE " mbedTLS") - SET(TLS_LIBRARY_ENABLED ON) - SET(TLS_LIBRARY_LIBS ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) - SET(TLS_LIBRARY_INCLUDE ${MBEDTLS_INCLUDE_DIR}) - ADD_DEFINITIONS(-DEQEMU_USE_MBEDTLS) -ELSE() - SET(TLS_LIBRARY_TYPE "Disabled") - SET(TLS_LIBRARY_ENABLED OFF) -ENDIF() - -IF(SODIUM_FOUND) - SET(SODIUM_LIBRARY_TYPE "Libsodium") - SET(SODIUM_LIBRARY_ENABLED ON) - SET(SODIUM_LIBRARY_LIBS ${SODIUM_LIBRARIES}) - SET(SODIUM_LIBRARY_INCLUDE ${SODIUM_INCLUDE_DIRS}) - ADD_DEFINITIONS(-DENABLE_SECURITY) -ELSE() - SET(SODIUM_LIBRARY_TYPE " Disabled") - SET(SODIUM_LIBRARY_ENABLED OFF) -ENDIF() - -IF(LUAJIT_FOUND AND NOT (EQEMU_PREFER_LUA AND Lua51_FOUND)) - SET(LUA_LIBRARY_TYPE " LuaJIT") - SET(LUA_LIBRARY_ENABLED ON) - SET(LUA_LIBRARY_LIBS ${LUAJIT_LIBRARY} luabind) - SET(LUA_LIBRARY_INCLUDE ${LUAJIT_INCLUDE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/libs/luabind") -ELSEIF(Lua51_FOUND ) - SET(LUA_LIBRARY_TYPE " Lua 5.1") - SET(LUA_LIBRARY_ENABLED ON) - SET(LUA_LIBRARY_LIBS ${LUA_LIBRARY} luabind) - SET(LUA_LIBRARY_INCLUDE ${LUA_INCLUDE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/libs/luabind") -ELSE() - SET(LUA_LIBRARY_TYPE "Disabled") - SET(LUA_LIBRARY_ENABLED OFF) -ENDIF() - -IF(PerlLibs_FOUND) - SET(PERL_LIBRARY_TYPE " Perl") - SET(PERL_LIBRARY_ENABLED ON) - SET(PERL_LIBRARY_LIBS ${PERL_LIBRARY}) - SET(PERL_LIBRARY_INCLUDE ${PERL_INCLUDE_PATH}) -ELSE() - SET(PERL_LIBRARY_TYPE "Disabled") - SET(PERL_LIBRARY_ENABLED OFF) -ENDIF() - -#use zlib if exists -IF(ZLIB_FOUND) - OPTION(EQEMU_BUILD_ZLIB "Build internal version of zlib." ON) - IF(EQEMU_BUILD_ZLIB) - SET(ZLIB_LIBRARY_TYPE "zlib-ng") - SET(ZLIB_LIBRARY_LIBS "zlibstatic") - SET(ZLIB_LIBRARY_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng") - INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng") - ELSE() - SET(ZLIB_LIBRARY_TYPE " zlib") - SET(ZLIB_LIBRARY_LIBS ${ZLIB_LIBRARY}) - SET(ZLIB_LIBRARY_INCLUDE ${ZLIB_INCLUDE_DIRS}) - ENDIF() -ELSE() - SET(ZLIB_LIBRARY_TYPE "zlib-ng") - SET(ZLIB_LIBRARY_LIBS "zlibstatic") - SET(ZLIB_LIBRARY_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng") -ENDIF() - -IF (EQEMU_BUILD_STATIC) - SET(ZLIB_LIBRARY_LIBS libz.a) -ENDIF(EQEMU_BUILD_STATIC) - -MESSAGE(STATUS "") -MESSAGE(STATUS "**************************************************") -MESSAGE(STATUS "* Library Usage *") -MESSAGE(STATUS "**************************************************") -MESSAGE(STATUS "* Database: ${DATABASE_LIBRARY_TYPE} *") -MESSAGE(STATUS "* TLS: ${TLS_LIBRARY_TYPE} *") -MESSAGE(STATUS "* Sodium: ${SODIUM_LIBRARY_TYPE} *") -MESSAGE(STATUS "* Lua: ${LUA_LIBRARY_TYPE} *") -MESSAGE(STATUS "* Perl: ${PERL_LIBRARY_TYPE} *") -MESSAGE(STATUS "* zlib: ${ZLIB_LIBRARY_TYPE} *") -MESSAGE(STATUS "**************************************************") - -#setup server libs and headers -SET(SERVER_LIBS common ${DATABASE_LIBRARY_LIBS} ${ZLIB_LIBRARY_LIBS} ${Boost_LIBRARIES} uv_a fmt RecastNavigation::Detour) - -set(FMT_HEADER_ONLY OFF) - -INCLUDE_DIRECTORIES(SYSTEM "${DATABASE_LIBRARY_INCLUDE}") -INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_LIBRARY_INCLUDE}") -INCLUDE_DIRECTORIES(SYSTEM "${Boost_INCLUDE_DIRS}") -INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/glm") -INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/cereal/include") -INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/fmt/include") -INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/libuv/include" ) -INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DebugUtils/Include") -INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Detour/Include") -INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourCrowd/Include") -INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourTileCache/Include") -INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include") -INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp") - -# silence obnoxious deprecation message -ADD_DEFINITIONS(-DBOOST_BIND_GLOBAL_PLACEHOLDERS) - -IF(TLS_LIBRARY_ENABLED) - SET(SERVER_LIBS ${SERVER_LIBS} ${TLS_LIBRARY_LIBS}) - INCLUDE_DIRECTORIES(SYSTEM "${TLS_LIBRARY_INCLUDE}") -ENDIF() - -IF(SODIUM_LIBRARY_ENABLED) - SET(SERVER_LIBS ${SERVER_LIBS} ${SODIUM_LIBRARY_LIBS}) - INCLUDE_DIRECTORIES(SYSTEM "${SODIUM_LIBRARY_INCLUDE}") -ENDIF() - -IF(LUA_LIBRARY_ENABLED) - OPTION(EQEMU_BUILD_LUA "Build Lua parser." ON) - - IF(EQEMU_BUILD_LUA) - ADD_DEFINITIONS(-DLUA_EQEMU) - SET(ZONE_LIBS ${LUA_LIBRARY_LIBS}) - INCLUDE_DIRECTORIES(SYSTEM "${LUA_LIBRARY_INCLUDE}") - - OPTION(EQEMU_SANITIZE_LUA_LIBS "Sanitize Lua Libraries (Remove OS and IO standard libraries from being able to run)." ON) - IF(EQEMU_SANITIZE_LUA_LIBS) - ADD_DEFINITIONS(-DSANITIZE_LUA_LIBS) - ENDIF() - ENDIF() -ENDIF() - -IF(PERL_LIBRARY_ENABLED) - OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON) - IF(EQEMU_BUILD_PERL) - SET(SERVER_LIBS ${SERVER_LIBS} ${PERL_LIBRARY_LIBS} perlbind) - INCLUDE_DIRECTORIES(SYSTEM "${PERL_LIBRARY_INCLUDE}") - ADD_DEFINITIONS(-DEMBPERL) - ADD_DEFINITIONS(-DEMBPERL_PLUGIN) - ADD_DEFINITIONS(-DPERLBIND_NO_STRICT_SCALAR_TYPES) - IF (UNIX AND EQEMU_BUILD_STATIC) - SET(SERVER_LIBS ${SERVER_LIBS} libcrypt.a) - ENDIF () - ENDIF() -ENDIF() - -IF(WIN32) - SET(SERVER_LIBS ${SERVER_LIBS} "ws2_32" "psapi" "iphlpapi" "userenv") -ENDIF() - -IF(UNIX) - SET(SERVER_LIBS ${SERVER_LIBS} ${CMAKE_DL_LIBS} "z" "m" "pthread") - IF(NOT DARWIN) - SET(SERVER_LIBS ${SERVER_LIBS} "rt") - ENDIF() - # Freebsd provides uuids in the C library - IF(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") - SET(SERVER_LIBS ${SERVER_LIBS} "uuid") - ENDIF() -ENDIF() - -SET(ZONE_LIBS ${ZONE_LIBS} ${SERVER_LIBS}) - -IF(EQEMU_BUILD_LOGIN AND NOT TLS_LIBRARY_ENABLED) - MESSAGE(FATAL_ERROR "Login server requires a TLS Library to build.") -ENDIF() - -IF(EQEMU_BUILD_HC AND NOT TLS_LIBRARY_ENABLED) - MESSAGE(FATAL_ERROR "Headless client requires a TLS Library to build.") -ENDIF() - -IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC) - ADD_SUBDIRECTORY(common) - ADD_SUBDIRECTORY(libs) - ADD_SUBDIRECTORY(submodules/fmt) - ADD_SUBDIRECTORY(submodules/libuv) - - IF(EQEMU_BUILD_ZLIB) - SET(ZLIB_COMPAT ON CACHE BOOL "Compile with zlib compatible API") - SET(ZLIB_ENABLE_TESTS OFF CACHE BOOL "Build test binaries") - ADD_SUBDIRECTORY(libs/zlibng) - ENDIF() - - SET(RECASTNAVIGATION_DEMO OFF CACHE BOOL "Build demo") - SET(RECASTNAVIGATION_TESTS OFF CACHE BOOL "Build tests") - SET(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "Build examples") - ADD_SUBDIRECTORY(submodules/recastnavigation) -ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC) - -IF(EQEMU_BUILD_SERVER) - ADD_SUBDIRECTORY(shared_memory) - ADD_SUBDIRECTORY(world) - ADD_SUBDIRECTORY(zone) - ADD_SUBDIRECTORY(ucs) - ADD_SUBDIRECTORY(queryserv) - ADD_SUBDIRECTORY(eqlaunch) -ENDIF(EQEMU_BUILD_SERVER) - -IF(EQEMU_BUILD_LOGIN) - ADD_SUBDIRECTORY(loginserver) -ENDIF(EQEMU_BUILD_LOGIN) - -IF(EQEMU_BUILD_HC) - ADD_SUBDIRECTORY(hc) -ENDIF(EQEMU_BUILD_HC) - -IF(EQEMU_BUILD_TESTS) - ADD_SUBDIRECTORY(tests) -ENDIF(EQEMU_BUILD_TESTS) - -IF(EQEMU_BUILD_CLIENT_FILES) - ADD_SUBDIRECTORY(client_files) -ENDIF(EQEMU_BUILD_CLIENT_FILES) +option(EQEMU_BUILD_SERVER "Build the game server." ON) +option(EQEMU_BUILD_LOGIN "Build the login server." ON) +option(EQEMU_BUILD_TESTS "Build utility tests." OFF) +option(EQEMU_BUILD_CLIENT_FILES "Build Client Import/Export Data Programs." ON) + +if(PerlLibs_FOUND) + option(EQEMU_BUILD_PERL "Build Perl parser." ON) + + if(EQEMU_BUILD_PERL) + set(PERL_LIBRARY_TYPE " Perl") + else() + set(PERL_LIBRARY_TYPE " Missing") + endif() +else() + set(PERL_LIBRARY_TYPE "Disabled") +endif() + +message(STATUS "") +message(STATUS "**************************************************") +message(STATUS "* Library Usage *") +message(STATUS "**************************************************") +message(STATUS "* Database: MariaDB *") +message(STATUS "* TLS: OpenSSL *") +message(STATUS "* Lua: LuaJIT *") +message(STATUS "* Perl: ${PERL_LIBRARY_TYPE} *") +message(STATUS "* zlib: ZLIB *") +message(STATUS "**************************************************") + + +option(EQEMU_BUILD_LUA "Build Lua parser." ON) + +if(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_CLIENT_FILES) + add_subdirectory(common) + add_subdirectory(libs) +else() + message(FATAL_ERROR "No targets were selected to build, we must build at least one target.") +endif() + +if(EQEMU_BUILD_SERVER) + add_subdirectory(shared_memory) + add_subdirectory(world) + add_subdirectory(zone) + add_subdirectory(ucs) + add_subdirectory(queryserv) + add_subdirectory(eqlaunch) +endif() + +if(EQEMU_BUILD_LOGIN) + add_subdirectory(loginserver) +endif() + +if(EQEMU_BUILD_TESTS) + add_subdirectory(tests) +endif() + +if(EQEMU_BUILD_CLIENT_FILES) + add_subdirectory(client_files) +endif() diff --git a/client_files/CMakeLists.txt b/client_files/CMakeLists.txt index d4b5962e3d..2fec654cfc 100644 --- a/client_files/CMakeLists.txt +++ b/client_files/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.5) +cmake_minimum_required(VERSION 3.20) add_subdirectory(import) add_subdirectory(export) diff --git a/client_files/export/CMakeLists.txt b/client_files/export/CMakeLists.txt index b7f15dddbd..c35a22efea 100644 --- a/client_files/export/CMakeLists.txt +++ b/client_files/export/CMakeLists.txt @@ -1,16 +1,16 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.12) +cmake_minimum_required(VERSION 3.20.0) -SET(export_sources +set(export_sources main.cpp ) -SET(export_headers +set(export_headers ) -ADD_EXECUTABLE(export_client_files ${export_sources} ${export_headers}) +add_executable(export_client_files ${export_sources} ${export_headers}) -INSTALL(TARGETS export_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS export_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -TARGET_LINK_LIBRARIES(export_client_files ${SERVER_LIBS}) +target_link_libraries(export_client_files common) -SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/client_files/import/CMakeLists.txt b/client_files/import/CMakeLists.txt index da08cda6e3..af7f4da0ce 100644 --- a/client_files/import/CMakeLists.txt +++ b/client_files/import/CMakeLists.txt @@ -1,16 +1,16 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.12) +cmake_minimum_required(VERSION 3.20.0) -SET(import_sources +set(import_sources main.cpp ) -SET(import_headers +set(import_headers ) -ADD_EXECUTABLE(import_client_files ${import_sources} ${import_headers}) +add_executable(import_client_files ${import_sources} ${import_headers}) -INSTALL(TARGETS import_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS import_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -TARGET_LINK_LIBRARIES(import_client_files ${SERVER_LIBS}) +target_link_libraries(import_client_files common) -SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/cmake/DependencyHelperMSVC.cmake b/cmake/DependencyHelperMSVC.cmake deleted file mode 100644 index 1f4554e6ce..0000000000 --- a/cmake/DependencyHelperMSVC.cmake +++ /dev/null @@ -1,89 +0,0 @@ -OPTION(EQEMU_FETCH_MSVC_DEPENDENCIES_VCPKG "Automatically fetch vcpkg dependencies for MSCV" ON) -OPTION(EQEMU_FETCH_MSVC_DEPENDENCIES_PERL "Automatically fetch perl dependencies for MSCV" ON) - -MARK_AS_ADVANCED(EQEMU_FETCH_MSVC_DEPENDENCIES_VCPKG) -MARK_AS_ADVANCED(EQEMU_FETCH_MSVC_DEPENDENCIES_PERL) - -SET(EQEMU_MSVC_DEPENDENCIES_VCPKG_X86 "https://github.com/EQEmu/Server/releases/download/v1.2/vcpkg-export-x86.zip") -SET(EQEMU_MSVC_DEPENDENCIES_VCPKG_X64 "https://github.com/EQEmu/Server/releases/download/v1.2/vcpkg-export-x64.zip") -SET(EQEMU_MSVC_DEPENDENCIES_PERL_X86 "http://strawberryperl.com/download/5.24.4.1/strawberry-perl-5.24.4.1-32bit-portable.zip") -SET(EQEMU_MSVC_DEPENDENCIES_PERL_X64 "http://strawberryperl.com/download/5.24.4.1/strawberry-perl-5.24.4.1-64bit-portable.zip") -SET(EQEMU_MSVC_DEPENDENCIES_VCPKG_X86_ZIP "vcpkg-export-x86.zip") -SET(EQEMU_MSVC_DEPENDENCIES_VCPKG_X64_ZIP "vcpkg-export-x64.zip") -SET(EQEMU_MSVC_DEPENDENCIES_VCPKG_X86_DIR "vcpkg-export-x86") -SET(EQEMU_MSVC_DEPENDENCIES_VCPKG_X64_DIR "vcpkg-export-x64") -SET(EQEMU_MSVC_DEPENDENCIES_PERL_X86_ZIP "strawberry-perl-5.24.4.1-32bit-portable.zip") -SET(EQEMU_MSVC_DEPENDENCIES_PERL_X64_ZIP "strawberry-perl-5.24.4.1-64bit-portable.zip") -SET(EQEMU_MSVC_DEPENDENCIES_PERL_X86_DIR "x86") -SET(EQEMU_MSVC_DEPENDENCIES_PERL_X64_DIR "x64") - -IF(CMAKE_SIZEOF_VOID_P EQUAL 8) - SET(EQEMU_VCPKG_URL ${EQEMU_MSVC_DEPENDENCIES_VCPKG_X64}) - SET(EQEMU_PERL_URL ${EQEMU_MSVC_DEPENDENCIES_PERL_X64}) - SET(EQEMU_VCPKG_ZIP ${EQEMU_MSVC_DEPENDENCIES_VCPKG_X64_ZIP}) - SET(EQEMU_VCPKG_DIR ${EQEMU_MSVC_DEPENDENCIES_VCPKG_X64_DIR}) - SET(EQEMU_PERL_ZIP ${EQEMU_MSVC_DEPENDENCIES_PERL_X64_ZIP}) - SET(EQEMU_PERL_DIR ${EQEMU_MSVC_DEPENDENCIES_PERL_X64_DIR}) -ELSE() - SET(EQEMU_VCPKG_URL ${EQEMU_MSVC_DEPENDENCIES_VCPKG_X86}) - SET(EQEMU_PERL_URL ${EQEMU_MSVC_DEPENDENCIES_PERL_X86}) - SET(EQEMU_VCPKG_ZIP ${EQEMU_MSVC_DEPENDENCIES_VCPKG_X86_ZIP}) - SET(EQEMU_VCPKG_DIR ${EQEMU_MSVC_DEPENDENCIES_VCPKG_X86_DIR}) - SET(EQEMU_PERL_ZIP ${EQEMU_MSVC_DEPENDENCIES_PERL_X86_ZIP}) - SET(EQEMU_PERL_DIR ${EQEMU_MSVC_DEPENDENCIES_PERL_X86_DIR}) -ENDIF() - -IF(EQEMU_FETCH_MSVC_DEPENDENCIES_VCPKG) - MESSAGE(STATUS "Resolving vcpkg dependencies...") - - IF(NOT EXISTS ${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_ZIP}) - EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/vcpkg) - - MESSAGE(STATUS "Downloading existing vcpkg dependencies from releases...") - FILE(DOWNLOAD ${EQEMU_VCPKG_URL} ${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_ZIP} - SHOW_PROGRESS - STATUS DOWNLOAD_STATUS) - - LIST(GET DOWNLOAD_STATUS 0 STATUS_CODE) - IF(NOT STATUS_CODE EQUAL 0) - MESSAGE(FATAL_ERROR "Was unable to download dependencies from ${EQEMU_VCPKG_URL}") - ENDIF() - - MESSAGE(STATUS "Extracting files...") - EXECUTE_PROCESS( - COMMAND ${CMAKE_COMMAND} -E tar xzf ${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_ZIP} - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/vcpkg - ) - ENDIF() - - INCLUDE(${PROJECT_SOURCE_DIR}/vcpkg/${EQEMU_VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake) -ENDIF() - -IF(EQEMU_FETCH_MSVC_DEPENDENCIES_PERL) - MESSAGE(STATUS "Resolving perl dependencies...") - - IF(NOT EXISTS ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP}) - EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/perl) - EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}) - - MESSAGE(STATUS "Downloading portable perl...") - FILE(DOWNLOAD ${EQEMU_PERL_URL} ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP} - SHOW_PROGRESS - STATUS DOWNLOAD_STATUS) - - LIST(GET DOWNLOAD_STATUS 0 STATUS_CODE) - IF(NOT STATUS_CODE EQUAL 0) - MESSAGE(FATAL_ERROR "Was unable to download dependencies from ${EQEMU_PERL_URL}") - ENDIF() - - MESSAGE(STATUS "Extracting files...") - EXECUTE_PROCESS( - COMMAND ${CMAKE_COMMAND} -E tar xzf ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_ZIP} - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR} - ) - ENDIF() - - SET(PERL_EXECUTABLE ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/bin/perl.exe CACHE FILEPATH "Path to perl program" FORCE) - SET(PERL_INCLUDE_PATH ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/lib/CORE CACHE PATH "Path to perl include files" FORCE) - SET(PERL_LIBRARY ${PROJECT_SOURCE_DIR}/perl/${EQEMU_PERL_DIR}/perl/lib/CORE/libperl524.a CACHE FILEPATH "Path to perl library" FORCE) -ENDIF() diff --git a/cmake/FindLua51.cmake b/cmake/FindLua51.cmake deleted file mode 100644 index 0aab2bb82d..0000000000 --- a/cmake/FindLua51.cmake +++ /dev/null @@ -1,91 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. -# Modified from the FindLua51 that comes with CMake - -#[=======================================================================[.rst: -FindLua51 ---------- - - - -Locate Lua51 library This module defines - -:: - - LUA51_FOUND, if false, do not try to link to Lua - LUA_LIBRARIES - LUA_INCLUDE_DIR, where to find lua.h - LUA_VERSION_STRING, the version of Lua found (since CMake 2.8.8) - - - -Note that the expected include convention is - -:: - - #include "lua.h" - -and not - -:: - - #include - -This is because, the lua location is not standardized and may exist in -locations other than lua/ -#]=======================================================================] - -find_path(LUA_INCLUDE_DIR lua.h - HINTS - ENV LUA_DIR - PATH_SUFFIXES include/lua51 include/lua5.1 include/lua-5.1 include/lua include - PATHS - ~/Library/Frameworks - /Library/Frameworks - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt -) - -find_library(LUA_LIBRARY - NAMES lua51 lua5.1 lua-5.1 lua - HINTS - ENV LUA_DIR - PATH_SUFFIXES lib - PATHS - ~/Library/Frameworks - /Library/Frameworks - /sw - /opt/local - /opt/csw - /opt -) - -if(LUA_LIBRARY) - # include the math library for Unix - if(UNIX AND NOT APPLE AND NOT BEOS AND NOT HAIKU) - find_library(LUA_MATH_LIBRARY m) - set( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries") - # For Windows and Mac, don't need to explicitly include the math library - else() - set( LUA_LIBRARIES "${LUA_LIBRARY}" CACHE STRING "Lua Libraries") - endif() -endif() - -if(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h") - file(STRINGS "${LUA_INCLUDE_DIR}/lua.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua .+\"") - - string(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([^\"]+)\".*" "\\1" LUA_VERSION_STRING "${lua_version_str}") - unset(lua_version_str) -endif() - -include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake) -# handle the QUIETLY and REQUIRED arguments and set LUA51_FOUND to TRUE if -# all listed variables are TRUE -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua51 - REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR - VERSION_VAR LUA_VERSION_STRING) - -mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY) - diff --git a/cmake/FindLuaJit.cmake b/cmake/FindLuaJit.cmake index a7376dee19..1880743394 100644 --- a/cmake/FindLuaJit.cmake +++ b/cmake/FindLuaJit.cmake @@ -88,4 +88,3 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJit VERSION_VAR LUAJIT_VERSION_STRING) mark_as_advanced(LUAJIT_INCLUDE_DIR LUAJIT_LIBRARIES LUAJIT_LIBRARY LUAJIT_MATH_LIBRARY) - diff --git a/cmake/FindMariaDB.cmake b/cmake/FindMariaDB.cmake deleted file mode 100644 index 14f54734df..0000000000 --- a/cmake/FindMariaDB.cmake +++ /dev/null @@ -1,87 +0,0 @@ -# - Find mariadbclient -# -# -*- cmake -*- -# -# Find the native MariaDB includes and library -# -# MariaDB_INCLUDE_DIR - where to find mysql.h, etc. -# MariaDB_LIBRARIES - List of libraries when using MariaDB. -# MariaDB_FOUND - True if MariaDB found. -# The following can be used as a hint as to where to search: -# MARIADB_ROOT - -IF (MariaDB_INCLUDE_DIR AND MariaDB_LIBRARIES) - # Already in cache, be silent - SET(MariaDB_FIND_QUIETLY TRUE) -ENDIF (MariaDB_INCLUDE_DIR AND MariaDB_LIBRARIES) - -# Include dir -IF(MARIADB_ROOT) - FIND_PATH(MariaDB_INCLUDE_DIR - NAMES mariadb_version.h - PATHS ${MARIADB_ROOT}/include - PATH_SUFFIXES mysql mariadb - NO_DEFAULT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - ) - FIND_PATH(MariaDB_INCLUDE_DIR - NAMES mariadb_version.h - PATH_SUFFIXES mysql mariadb - ) -ELSE(MARIADB_ROOT) - FIND_PATH(MariaDB_INCLUDE_DIR - NAMES mariadb_version.h - PATH_SUFFIXES mysql mariadb - ) -ENDIF(MARIADB_ROOT) - -# Library -SET(MariaDB_NAMES libmariadb) -IF(MARIADB_ROOT) - FIND_LIBRARY(MariaDB_LIBRARY - NAMES ${MariaDB_NAMES} - PATHS ${MARIADB_ROOT}/lib - PATH_SUFFIXES mysql mariadb - NO_DEFAULT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - ) - - FIND_LIBRARY(MariaDB_LIBRARY - NAMES ${MariaDB_NAMES} - PATH_SUFFIXES mysql mariadb - ) -ELSE(MARIADB_ROOT) - FIND_LIBRARY(MariaDB_LIBRARY - NAMES ${MariaDB_NAMES} mariadbclient_r mariadbclient - PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 - PATH_SUFFIXES mysql mariadb - ) -ENDIF(MARIADB_ROOT) - -IF (MariaDB_INCLUDE_DIR AND MariaDB_LIBRARY) - SET(MariaDB_FOUND TRUE) - SET(MariaDB_LIBRARIES ${MariaDB_LIBRARY}) -ELSE (MariaDB_INCLUDE_DIR AND MariaDB_LIBRARY) - SET(MariaDB_FOUND FALSE) - SET(MariaDB_LIBRARIES) -ENDIF (MariaDB_INCLUDE_DIR AND MariaDB_LIBRARY) - - -# handle the QUIETLY and REQUIRED arguments and set MariaDB_FOUND to TRUE if -# all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(MariaDB DEFAULT_MSG MariaDB_LIBRARY MariaDB_INCLUDE_DIR) - -IF(MariaDB_FOUND) - SET( MariaDB_LIBRARY_RELEASE ${MariaDB_LIBRARY} ) - SET( MariaDB_LIBRARY_DEBUG ${MariaDB_LIBRARY} ) - SET( MariaDB_LIBRARIES ${MariaDB_LIBRARY_RELEASE} ${MariaDB_LIBRARY_DEBUG} ) -ELSE(MariaDB_FOUND) - SET( MariaDB_LIBRARIES ) -ENDIF(MariaDB_FOUND) - -MARK_AS_ADVANCED( - MariaDB_LIBRARY_DEBUG - MariaDB_LIBRARY_RELEASE - MariaDB_INCLUDE_DIR - ) diff --git a/cmake/FindMySQL.cmake b/cmake/FindMySQL.cmake deleted file mode 100644 index 5a79275529..0000000000 --- a/cmake/FindMySQL.cmake +++ /dev/null @@ -1,87 +0,0 @@ -# - Find mysqlclient -# -# -*- cmake -*- -# -# Find the native MySQL includes and library -# -# MySQL_INCLUDE_DIR - where to find mysql.h, etc. -# MySQL_LIBRARIES - List of libraries when using MySQL. -# MySQL_FOUND - True if MySQL found. -# The following can be used as a hint as to where to search: -# MYSQL_ROOT - -IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARIES) - # Already in cache, be silent - SET(MySQL_FIND_QUIETLY TRUE) -ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARIES) - -# Include dir -IF(MYSQL_ROOT) - FIND_PATH(MySQL_INCLUDE_DIR - NAMES mysql.h - PATHS ${MYSQL_ROOT}/include - PATH_SUFFIXES mysql - NO_DEFAULT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - ) - FIND_PATH(MySQL_INCLUDE_DIR - NAMES mysql.h - PATH_SUFFIXES mysql - ) -ELSE(MYSQL_ROOT) - FIND_PATH(MySQL_INCLUDE_DIR - NAMES mysql.h - PATH_SUFFIXES mysql - ) -ENDIF(MYSQL_ROOT) - -# Library -SET(MySQL_NAMES libmysql) -IF(MYSQL_ROOT) - FIND_LIBRARY(MySQL_LIBRARY - NAMES ${MySQL_NAMES} - PATHS ${MYSQL_ROOT}/lib - PATH_SUFFIXES mysql - NO_DEFAULT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - ) - - FIND_LIBRARY(MySQL_LIBRARY - NAMES ${MySQL_NAMES} - PATH_SUFFIXES mysql - ) -ELSE(MYSQL_ROOT) - FIND_LIBRARY(MySQL_LIBRARY - NAMES ${MySQL_NAMES} mysqlclient_r mysqlclient - PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64 - PATH_SUFFIXES mysql - ) -ENDIF(MYSQL_ROOT) - -IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY) - SET(MySQL_FOUND TRUE) - SET( MySQL_LIBRARIES ${MySQL_LIBRARY} ) -ELSE (MySQL_INCLUDE_DIR AND MySQL_LIBRARY) - SET(MySQL_FOUND FALSE) - SET( MySQL_LIBRARIES ) -ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY) - - -# handle the QUIETLY and REQUIRED arguments and set MySQL_FOUND to TRUE if -# all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(MySQL DEFAULT_MSG MySQL_LIBRARY MySQL_INCLUDE_DIR) - -IF(MySQL_FOUND) - SET( MySQL_LIBRARY_RELEASE ${MySQL_LIBRARY} ) - SET( MySQL_LIBRARY_DEBUG ${MySQL_LIBRARY} ) - SET( MySQL_LIBRARIES ${MySQL_LIBRARY_RELEASE} ${MySQL_LIBRARY_DEBUG} ) -ELSE(MySQL_FOUND) - SET( MySQL_LIBRARIES ) -ENDIF(MySQL_FOUND) - -MARK_AS_ADVANCED( - MySQL_LIBRARY_DEBUG - MySQL_LIBRARY_RELEASE - MySQL_INCLUDE_DIR - ) diff --git a/cmake/FindSodium.cmake b/cmake/FindSodium.cmake deleted file mode 100644 index 3c5ae34670..0000000000 --- a/cmake/FindSodium.cmake +++ /dev/null @@ -1,30 +0,0 @@ -if (NOT MSVC) -include(FindPkgConfig) -pkg_check_modules(PC_SODIUM "libsodium") -if (NOT PC_SODIUM_FOUND) - pkg_check_modules(PC_SODIUM "sodium") -endif (NOT PC_SODIUM_FOUND) -if (PC_SODIUM_FOUND) - set(SODIUM_INCLUDE_HINTS ${PC_SODIUM_INCLUDE_DIRS} ${PC_SODIUM_INCLUDE_DIRS}/*) - set(SODIUM_LIBRARY_HINTS ${PC_SODIUM_LIBRARY_DIRS} ${PC_SODIUM_LIBRARY_DIRS}/*) -endif() -endif (NOT MSVC) - -# some libraries install the headers is a subdirectory of the include dir -# returned by pkg-config, so use a wildcard match to improve chances of finding -# headers and libraries. -find_path( - SODIUM_INCLUDE_DIRS - NAMES sodium.h - HINTS ${SODIUM_INCLUDE_HINTS} -) - -find_library( - SODIUM_LIBRARIES - NAMES libsodium sodium - HINTS ${SODIUM_LIBRARY_HINTS} -) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(SODIUM DEFAULT_MSG SODIUM_LIBRARIES SODIUM_INCLUDE_DIRS) -mark_as_advanced(SODIUM_FOUND SODIUM_LIBRARIES SODIUM_INCLUDE_DIRS) diff --git a/cmake/FindmbedTLS.cmake b/cmake/FindmbedTLS.cmake deleted file mode 100644 index d2a3ce3b99..0000000000 --- a/cmake/FindmbedTLS.cmake +++ /dev/null @@ -1,93 +0,0 @@ -# - Try to find mbedTLS -# Once done this will define -# -# Read-Only variables -# MBEDTLS_FOUND - system has mbedTLS -# MBEDTLS_INCLUDE_DIR - the mbedTLS include directory -# MBEDTLS_LIBRARY_DIR - the mbedTLS library directory -# MBEDTLS_LIBRARIES - Link these to use mbedTLS -# MBEDTLS_LIBRARY - path to mbedTLS library -# MBEDX509_LIBRARY - path to mbedTLS X.509 library -# MBEDCRYPTO_LIBRARY - path to mbedTLS Crypto library -# -# Hint -# MBEDTLS_ROOT_DIR can be pointed to a local mbedTLS installation. - -SET(_MBEDTLS_ROOT_HINTS - ${MBEDTLS_ROOT_DIR} - ENV MBEDTLS_ROOT_DIR -) - -SET(_MBEDTLS_ROOT_HINTS_AND_PATHS - HINTS ${_MBEDTLS_ROOT_HINTS} - PATHS ${_MBEDTLS_ROOT_PATHS} -) - -FIND_PATH(MBEDTLS_INCLUDE_DIR - NAMES mbedtls/version.h - ${_MBEDTLS_ROOT_HINTS_AND_PATHS} - PATH_SUFFIXES include -) - -IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARIES) - # Already in cache, be silent - SET(MBEDTLS_FIND_QUIETLY TRUE) -ENDIF() - -FIND_LIBRARY(MBEDTLS_LIBRARY - NAMES mbedtls libmbedtls - ${_MBEDTLS_ROOT_HINTS_AND_PATHS} - PATH_SUFFIXES library -) -FIND_LIBRARY(MBEDX509_LIBRARY - NAMES mbedx509 libmbedx509 - ${_MBEDTLS_ROOT_HINTS_AND_PATHS} - PATH_SUFFIXES library -) -FIND_LIBRARY(MBEDCRYPTO_LIBRARY - NAMES mbedcrypto libmbedcrypto - ${_MBEDTLS_ROOT_HINTS_AND_PATHS} - PATH_SUFFIXES library -) - -IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY) - SET(MBEDTLS_FOUND TRUE) -ENDIF() - -IF(MBEDTLS_FOUND) - # split mbedTLS into -L and -l linker options, so we can set them for pkg-config - GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_DIR ${MBEDTLS_LIBRARY} PATH) - GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY} NAME_WE) - GET_FILENAME_COMPONENT(MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY} NAME_WE) - GET_FILENAME_COMPONENT(MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY} NAME_WE) - STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE}) - STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE}) - STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE}) - SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}") - - IF(NOT MBEDTLS_FIND_QUIETLY) - MESSAGE(STATUS "Found mbedTLS:") - FILE(READ ${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h MBEDTLSCONTENT) - STRING(REGEX MATCH "MBEDTLS_VERSION_STRING +\"[0-9|.]+\"" MBEDTLSMATCH ${MBEDTLSCONTENT}) - IF (MBEDTLSMATCH) - STRING(REGEX REPLACE "MBEDTLS_VERSION_STRING +\"([0-9|.]+)\"" "\\1" MBEDTLS_VERSION ${MBEDTLSMATCH}) - MESSAGE(STATUS " version ${MBEDTLS_VERSION}") - ENDIF(MBEDTLSMATCH) - MESSAGE(STATUS " TLS: ${MBEDTLS_LIBRARY}") - MESSAGE(STATUS " X509: ${MBEDX509_LIBRARY}") - MESSAGE(STATUS " Crypto: ${MBEDCRYPTO_LIBRARY}") - ENDIF(NOT MBEDTLS_FIND_QUIETLY) -ELSE(MBEDTLS_FOUND) - IF(MBEDTLS_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find mbedTLS") - ENDIF(MBEDTLS_FIND_REQUIRED) -ENDIF(MBEDTLS_FOUND) - -MARK_AS_ADVANCED( - MBEDTLS_INCLUDE_DIR - MBEDTLS_LIBRARY_DIR - MBEDTLS_LIBRARIES - MBEDTLS_LIBRARY - MBEDX509_LIBRARY - MBEDCRYPTO_LIBRARY -) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 45af7b94dc..8c65626142 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -1,6 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.12) +cmake_minimum_required(VERSION 3.20.0) -SET(common_sources +set(common_sources base_packet.cpp bazaar.cpp bodytypes.cpp @@ -9,54 +9,55 @@ SET(common_sources compression.cpp condition.cpp content/world_content_service.cpp - discord/discord.cpp crash.cpp crc16.cpp crc32.cpp - database/database_dump_service.cpp + data_bucket.cpp database.cpp - database_instances.cpp - database/database_update_manifest.cpp - database/database_update_manifest_custom.cpp - database/database_update_manifest_bots.cpp + database/database_dump_service.cpp database/database_update.cpp + database_instances.cpp dbcore.cpp deity.cpp + discord/discord.cpp + discord/discord_manager.cpp dynamic_zone_base.cpp dynamic_zone_lockout.cpp emu_constants.cpp emu_limits.cpp emu_opcodes.cpp emu_versions.cpp - eqdb.cpp - eqdb_res.cpp - eqemu_exception.cpp - eqemu_config.cpp - eqemu_logsys.cpp eq_limits.cpp eq_packet.cpp eq_stream_ident.cpp eq_stream_proxy.cpp + eqdb.cpp + eqdb_res.cpp + eqemu_config.cpp + eqemu_exception.cpp + eqemu_logsys.cpp eqtime.cpp event_sub.cpp - events/player_event_logs.cpp events/player_event_discord_formatter.cpp + events/player_event_logs.cpp evolving_items.cpp extprofile.cpp - discord/discord_manager.cpp faction.cpp file.cpp guild_base.cpp guilds.cpp inventory_profile.cpp inventory_slot.cpp - ipc_mutex.cpp ip_util.cpp + ipc_mutex.cpp item_data.cpp item_instance.cpp + json/json.hpp + json/jsoncpp.cpp json_config.cpp light_source.cpp md5.cpp + memory/ksm.hpp memory_buffer.cpp memory_mapped_file.cpp misc.cpp @@ -65,17 +66,45 @@ SET(common_sources mysql_request_result.cpp mysql_request_row.cpp mysql_stmt.cpp + net/console_server.cpp + net/console_server_connection.cpp + net/crc32.cpp + net/eqstream.cpp + net/packet.cpp + net/reliable_stream_connection.cpp + net/servertalk_client_connection.cpp + net/servertalk_legacy_client_connection.cpp + net/servertalk_server.cpp + net/servertalk_server_connection.cpp + net/tcp_connection.cpp + net/tcp_server.cpp + net/websocket_server.cpp + net/websocket_server_connection.cpp opcode_map.cpp opcodemgr.cpp packet_dump.cpp packet_dump_file.cpp packet_functions.cpp + patches/patches.cpp + patches/rof.cpp + patches/rof2.cpp + patches/rof2_limits.cpp + patches/rof_limits.cpp + patches/sod.cpp + patches/sod_limits.cpp + patches/sof.cpp + patches/sof_limits.cpp + patches/titanium.cpp + patches/titanium_limits.cpp + patches/uf.cpp + patches/uf_limits.cpp path_manager.cpp perl_eqdb.cpp perl_eqdb_res.cpp - process/process.cpp - process.cpp + platform.cpp proc_launcher.cpp + process.cpp + process/process.cpp profanity_manager.cpp ptimer.cpp races.cpp @@ -87,98 +116,69 @@ SET(common_sources serverinfo.cpp shared_tasks.cpp shareddb.cpp - skills.cpp skill_caps.cpp + skills.cpp spdat.cpp spdat_bot.cpp + StackWalker/StackWalker.cpp strings.cpp + strings_legacy.cpp + strings_misc.cpp struct_strategy.cpp textures.cpp timer.cpp unix.cpp - platform.cpp - json/json.hpp - json/jsoncpp.cpp - zone_store.cpp - memory/ksm.hpp - net/console_server.cpp - net/console_server_connection.cpp - net/crc32.cpp - net/eqstream.cpp - net/packet.cpp - net/reliable_stream_connection.cpp - net/servertalk_client_connection.cpp - net/servertalk_legacy_client_connection.cpp - net/servertalk_server.cpp - net/servertalk_server_connection.cpp - net/tcp_connection.cpp - net/tcp_server.cpp - net/websocket_server.cpp - net/websocket_server_connection.cpp - patches/patches.cpp - patches/sod.cpp - patches/sod_limits.cpp - patches/sof.cpp - patches/sof_limits.cpp - patches/rof.cpp - patches/rof_limits.cpp - patches/rof2.cpp - patches/rof2_limits.cpp - patches/titanium.cpp - patches/titanium_limits.cpp - patches/uf.cpp - patches/uf_limits.cpp - StackWalker/StackWalker.cpp util/directory.cpp - util/uuid.cpp) - -SET(repositories + util/uuid.cpp + zone_store.cpp +) +set(repositories # Criteria repositories/criteria/content_filter_criteria.h - repositories/base/base_grid_repository.h - repositories/base/base_grid_entries_repository.h - # Base Repositories repositories/base/base_aa_ability_repository.h - repositories/base/base_aa_ranks_repository.h repositories/base/base_aa_rank_effects_repository.h repositories/base/base_aa_rank_prereqs_repository.h - repositories/base/base_account_repository.h + repositories/base/base_aa_ranks_repository.h repositories/base/base_account_flags_repository.h repositories/base/base_account_ip_repository.h + repositories/base/base_account_repository.h repositories/base/base_account_rewards_repository.h repositories/base/base_adventure_details_repository.h repositories/base/base_adventure_members_repository.h repositories/base/base_adventure_stats_repository.h - repositories/base/base_adventure_template_repository.h - repositories/base/base_adventure_template_entry_repository.h repositories/base/base_adventure_template_entry_flavor_repository.h + repositories/base/base_adventure_template_entry_repository.h + repositories/base/base_adventure_template_repository.h repositories/base/base_alternate_currency_repository.h repositories/base/base_auras_repository.h repositories/base/base_base_data_repository.h repositories/base/base_blocked_spells_repository.h repositories/base/base_books_repository.h - repositories/base/base_bugs_repository.h repositories/base/base_bug_reports_repository.h + repositories/base/base_bugs_repository.h repositories/base/base_buyer_repository.h repositories/base/base_buyer_trade_items_repository.h + repositories/base/base_char_create_combinations_repository.h + repositories/base/base_char_create_point_allocations_repository.h + repositories/base/base_char_recipe_list_repository.h repositories/base/base_character_activities_repository.h - repositories/base/base_character_alternate_abilities_repository.h repositories/base/base_character_alt_currency_repository.h + repositories/base/base_character_alternate_abilities_repository.h repositories/base/base_character_auras_repository.h repositories/base/base_character_bandolier_repository.h repositories/base/base_character_bind_repository.h repositories/base/base_character_buffs_repository.h - repositories/base/base_character_corpses_repository.h repositories/base/base_character_corpse_items_repository.h + repositories/base/base_character_corpses_repository.h repositories/base/base_character_currency_repository.h repositories/base/base_character_data_repository.h repositories/base/base_character_disciplines_repository.h repositories/base/base_character_evolving_items_repository.h - repositories/base/base_character_expedition_lockouts_repository.h repositories/base/base_character_exp_modifiers_repository.h + repositories/base/base_character_expedition_lockouts_repository.h repositories/base/base_character_inspect_messages_repository.h repositories/base/base_character_instance_safereturns_repository.h repositories/base/base_character_item_recast_repository.h @@ -186,8 +186,8 @@ SET(repositories repositories/base/base_character_leadership_abilities_repository.h repositories/base/base_character_material_repository.h repositories/base/base_character_memmed_spells_repository.h - repositories/base/base_character_parcels_repository.h repositories/base/base_character_parcels_containers_repository.h + repositories/base/base_character_parcels_repository.h repositories/base/base_character_peqzone_flags_repository.h repositories/base/base_character_pet_buffs_repository.h repositories/base/base_character_pet_info_repository.h @@ -195,16 +195,13 @@ SET(repositories repositories/base/base_character_potionbelt_repository.h repositories/base/base_character_skills_repository.h repositories/base/base_character_spells_repository.h - repositories/base/base_character_tasks_repository.h repositories/base/base_character_task_timers_repository.h - repositories/base/base_char_create_combinations_repository.h - repositories/base/base_char_create_point_allocations_repository.h - repositories/base/base_char_recipe_list_repository.h - repositories/base/base_chatchannels_repository.h + repositories/base/base_character_tasks_repository.h repositories/base/base_chatchannel_reserved_names_repository.h - repositories/base/base_completed_shared_tasks_repository.h + repositories/base/base_chatchannels_repository.h repositories/base/base_completed_shared_task_activity_state_repository.h repositories/base/base_completed_shared_task_members_repository.h + repositories/base/base_completed_shared_tasks_repository.h repositories/base/base_completed_tasks_repository.h repositories/base/base_content_flags_repository.h repositories/base/base_damageshieldtypes_repository.h @@ -213,14 +210,14 @@ SET(repositories repositories/base/base_discord_webhooks_repository.h repositories/base/base_discovered_items_repository.h repositories/base/base_doors_repository.h - repositories/base/base_dynamic_zones_repository.h repositories/base/base_dynamic_zone_lockouts_repository.h repositories/base/base_dynamic_zone_members_repository.h repositories/base/base_dynamic_zone_templates_repository.h + repositories/base/base_dynamic_zones_repository.h repositories/base/base_faction_association_repository.h repositories/base/base_faction_base_data_repository.h - repositories/base/base_faction_list_repository.h repositories/base/base_faction_list_mod_repository.h + repositories/base/base_faction_list_repository.h repositories/base/base_faction_values_repository.h repositories/base/base_fishing_repository.h repositories/base/base_forage_repository.h @@ -228,23 +225,25 @@ SET(repositories repositories/base/base_global_loot_repository.h repositories/base/base_gm_ips_repository.h repositories/base/base_graveyard_repository.h + repositories/base/base_grid_entries_repository.h + repositories/base/base_grid_repository.h repositories/base/base_ground_spawns_repository.h repositories/base/base_group_id_repository.h repositories/base/base_group_leaders_repository.h - repositories/base/base_guilds_repository.h - repositories/base/base_guild_ranks_repository.h - repositories/base/base_guild_permissions_repository.h - repositories/base/base_guild_members_repository.h repositories/base/base_guild_bank_repository.h + repositories/base/base_guild_members_repository.h + repositories/base/base_guild_permissions_repository.h + repositories/base/base_guild_ranks_repository.h repositories/base/base_guild_relations_repository.h + repositories/base/base_guilds_repository.h repositories/base/base_horses_repository.h - repositories/base/base_instance_list_repository.h repositories/base/base_instance_list_player_repository.h + repositories/base/base_instance_list_repository.h repositories/base/base_inventory_repository.h repositories/base/base_inventory_snapshots_repository.h repositories/base/base_ip_exemptions_repository.h - repositories/base/base_items_repository.h repositories/base/base_items_evolving_details_repository.h + repositories/base/base_items_repository.h repositories/base/base_ldon_trap_entries_repository.h repositories/base/base_ldon_trap_templates_repository.h repositories/base/base_level_exp_mods_repository.h @@ -255,47 +254,47 @@ SET(repositories repositories/base/base_login_server_list_types_repository.h repositories/base/base_login_world_servers_repository.h repositories/base/base_logsys_categories_repository.h - repositories/base/base_lootdrop_repository.h repositories/base/base_lootdrop_entries_repository.h - repositories/base/base_loottable_repository.h + repositories/base/base_lootdrop_repository.h repositories/base/base_loottable_entries_repository.h + repositories/base/base_loottable_repository.h repositories/base/base_mail_repository.h repositories/base/base_merchantlist_repository.h repositories/base/base_merchantlist_temp_repository.h repositories/base/base_name_filter_repository.h repositories/base/base_npc_emotes_repository.h - repositories/base/base_npc_faction_repository.h repositories/base/base_npc_faction_entries_repository.h + repositories/base/base_npc_faction_repository.h repositories/base/base_npc_scale_global_base_repository.h - repositories/base/base_npc_spells_repository.h - repositories/base/base_npc_spells_effects_repository.h repositories/base/base_npc_spells_effects_entries_repository.h + repositories/base/base_npc_spells_effects_repository.h repositories/base/base_npc_spells_entries_repository.h + repositories/base/base_npc_spells_repository.h repositories/base/base_npc_types_repository.h repositories/base/base_npc_types_tint_repository.h - repositories/base/base_object_repository.h repositories/base/base_object_contents_repository.h + repositories/base/base_object_repository.h repositories/base/base_perl_event_export_settings_repository.h repositories/base/base_petitions_repository.h - repositories/base/base_pets_repository.h repositories/base/base_pets_beastlord_data_repository.h - repositories/base/base_pets_equipmentset_repository.h repositories/base/base_pets_equipmentset_entries_repository.h - repositories/base/base_player_titlesets_repository.h + repositories/base/base_pets_equipmentset_repository.h + repositories/base/base_pets_repository.h repositories/base/base_player_event_aa_purchase_repository.h - repositories/base/base_player_event_killed_npc_repository.h repositories/base/base_player_event_killed_named_npc_repository.h + repositories/base/base_player_event_killed_npc_repository.h repositories/base/base_player_event_killed_raid_npc_repository.h repositories/base/base_player_event_log_settings_repository.h repositories/base/base_player_event_logs_repository.h repositories/base/base_player_event_loot_items_repository.h repositories/base/base_player_event_merchant_purchase_repository.h repositories/base/base_player_event_merchant_sell_repository.h - repositories/base/base_player_event_npc_handin_repository.h repositories/base/base_player_event_npc_handin_entries_repository.h + repositories/base/base_player_event_npc_handin_repository.h repositories/base/base_player_event_speech_repository.h - repositories/base/base_player_event_trade_repository.h repositories/base/base_player_event_trade_entries_repository.h + repositories/base/base_player_event_trade_repository.h + repositories/base/base_player_titlesets_repository.h repositories/base/base_quest_globals_repository.h repositories/base/base_raid_details_repository.h repositories/base/base_raid_members_repository.h @@ -305,76 +304,79 @@ SET(repositories repositories/base/base_rule_values_repository.h repositories/base/base_saylink_repository.h repositories/base/base_server_scheduled_events_repository.h - repositories/base/base_shared_tasks_repository.h repositories/base/base_shared_task_activity_state_repository.h repositories/base/base_shared_task_dynamic_zones_repository.h repositories/base/base_shared_task_members_repository.h + repositories/base/base_shared_tasks_repository.h repositories/base/base_skill_caps_repository.h repositories/base/base_spawn2_repository.h - repositories/base/base_spawnentry_repository.h - repositories/base/base_spawngroup_repository.h - repositories/base/base_spawn_conditions_repository.h repositories/base/base_spawn_condition_values_repository.h + repositories/base/base_spawn_conditions_repository.h repositories/base/base_spawn_events_repository.h - repositories/base/base_spells_new_repository.h + repositories/base/base_spawnentry_repository.h + repositories/base/base_spawngroup_repository.h repositories/base/base_spell_buckets_repository.h repositories/base/base_spell_globals_repository.h - repositories/base/base_starting_items_repository.h + repositories/base/base_spells_new_repository.h repositories/base/base_start_zones_repository.h + repositories/base/base_starting_items_repository.h + repositories/base/base_task_activities_repository.h repositories/base/base_tasks_repository.h repositories/base/base_tasksets_repository.h - repositories/base/base_task_activities_repository.h repositories/base/base_timers_repository.h repositories/base/base_titles_repository.h repositories/base/base_trader_repository.h - repositories/base/base_tradeskill_recipe_repository.h repositories/base/base_tradeskill_recipe_entries_repository.h + repositories/base/base_tradeskill_recipe_repository.h repositories/base/base_traps_repository.h - repositories/base/base_tributes_repository.h repositories/base/base_tribute_levels_repository.h + repositories/base/base_tributes_repository.h repositories/base/base_veteran_reward_templates_repository.h - repositories/base/base_zone_repository.h repositories/base/base_zone_points_repository.h + repositories/base/base_zone_repository.h # Extended Repositories repositories/aa_ability_repository.h - repositories/aa_ranks_repository.h repositories/aa_rank_effects_repository.h repositories/aa_rank_prereqs_repository.h - repositories/account_repository.h + repositories/aa_ranks_repository.h repositories/account_flags_repository.h repositories/account_ip_repository.h + repositories/account_repository.h repositories/account_rewards_repository.h repositories/adventure_details_repository.h repositories/adventure_members_repository.h repositories/adventure_stats_repository.h - repositories/adventure_template_repository.h - repositories/adventure_template_entry_repository.h repositories/adventure_template_entry_flavor_repository.h + repositories/adventure_template_entry_repository.h + repositories/adventure_template_repository.h repositories/alternate_currency_repository.h repositories/auras_repository.h repositories/base_data_repository.h repositories/blocked_spells_repository.h repositories/books_repository.h - repositories/bugs_repository.h repositories/bug_reports_repository.h + repositories/bugs_repository.h repositories/buyer_buy_lines_repository.h repositories/buyer_trade_items_repository.h + repositories/char_create_combinations_repository.h + repositories/char_create_point_allocations_repository.h + repositories/char_recipe_list_repository.h repositories/character_activities_repository.h - repositories/character_alternate_abilities_repository.h repositories/character_alt_currency_repository.h + repositories/character_alternate_abilities_repository.h repositories/character_auras_repository.h repositories/character_bandolier_repository.h repositories/character_bind_repository.h repositories/character_buffs_repository.h - repositories/character_corpses_repository.h repositories/character_corpse_items_repository.h + repositories/character_corpses_repository.h repositories/character_currency_repository.h repositories/character_data_repository.h repositories/character_disciplines_repository.h repositories/character_evolving_items_repository.h - repositories/character_expedition_lockouts_repository.h repositories/character_exp_modifiers_repository.h + repositories/character_expedition_lockouts_repository.h repositories/character_inspect_messages_repository.h repositories/character_instance_safereturns_repository.h repositories/character_item_recast_repository.h @@ -382,8 +384,8 @@ SET(repositories repositories/character_leadership_abilities_repository.h repositories/character_material_repository.h repositories/character_memmed_spells_repository.h - repositories/character_parcels_repository.h repositories/character_parcels_containers_repository.h + repositories/character_parcels_repository.h repositories/character_peqzone_flags_repository.h repositories/character_pet_buffs_repository.h repositories/character_pet_info_repository.h @@ -391,16 +393,13 @@ SET(repositories repositories/character_potionbelt_repository.h repositories/character_skills_repository.h repositories/character_spells_repository.h - repositories/character_tasks_repository.h repositories/character_task_timers_repository.h - repositories/char_create_combinations_repository.h - repositories/char_create_point_allocations_repository.h - repositories/char_recipe_list_repository.h - repositories/chatchannels_repository.h + repositories/character_tasks_repository.h repositories/chatchannel_reserved_names_repository.h - repositories/completed_shared_tasks_repository.h + repositories/chatchannels_repository.h repositories/completed_shared_task_activity_state_repository.h repositories/completed_shared_task_members_repository.h + repositories/completed_shared_tasks_repository.h repositories/completed_tasks_repository.h repositories/content_flags_repository.h repositories/damageshieldtypes_repository.h @@ -409,14 +408,14 @@ SET(repositories repositories/discord_webhooks_repository.h repositories/discovered_items_repository.h repositories/doors_repository.h - repositories/dynamic_zones_repository.h repositories/dynamic_zone_lockouts_repository.h repositories/dynamic_zone_members_repository.h repositories/dynamic_zone_templates_repository.h + repositories/dynamic_zones_repository.h repositories/faction_association_repository.h repositories/faction_base_data_repository.h - repositories/faction_list_repository.h repositories/faction_list_mod_repository.h + repositories/faction_list_repository.h repositories/faction_values_repository.h repositories/fishing_repository.h repositories/forage_repository.h @@ -427,20 +426,20 @@ SET(repositories repositories/ground_spawns_repository.h repositories/group_id_repository.h repositories/group_leaders_repository.h - repositories/guilds_repository.h - repositories/guild_ranks_repository.h - repositories/guild_permissions_repository.h - repositories/guild_members_repository.h repositories/guild_bank_repository.h + repositories/guild_members_repository.h + repositories/guild_permissions_repository.h + repositories/guild_ranks_repository.h repositories/guild_relations_repository.h + repositories/guilds_repository.h repositories/horses_repository.h - repositories/instance_list_repository.h repositories/instance_list_player_repository.h + repositories/instance_list_repository.h repositories/inventory_repository.h repositories/inventory_snapshots_repository.h repositories/ip_exemptions_repository.h - repositories/items_repository.h repositories/items_evolving_details_repository.h + repositories/items_repository.h repositories/ldon_trap_entries_repository.h repositories/ldon_trap_templates_repository.h repositories/level_exp_mods_repository.h @@ -451,47 +450,47 @@ SET(repositories repositories/login_server_list_types_repository.h repositories/login_world_servers_repository.h repositories/logsys_categories_repository.h - repositories/lootdrop_repository.h repositories/lootdrop_entries_repository.h - repositories/loottable_repository.h + repositories/lootdrop_repository.h repositories/loottable_entries_repository.h + repositories/loottable_repository.h repositories/mail_repository.h repositories/merchantlist_repository.h repositories/merchantlist_temp_repository.h repositories/name_filter_repository.h repositories/npc_emotes_repository.h - repositories/npc_faction_repository.h repositories/npc_faction_entries_repository.h + repositories/npc_faction_repository.h repositories/npc_scale_global_base_repository.h - repositories/npc_spells_repository.h - repositories/npc_spells_effects_repository.h repositories/npc_spells_effects_entries_repository.h + repositories/npc_spells_effects_repository.h repositories/npc_spells_entries_repository.h + repositories/npc_spells_repository.h repositories/npc_types_repository.h repositories/npc_types_tint_repository.h - repositories/object_repository.h repositories/object_contents_repository.h + repositories/object_repository.h repositories/perl_event_export_settings_repository.h repositories/petitions_repository.h - repositories/pets_repository.h repositories/pets_beastlord_data_repository.h - repositories/pets_equipmentset_repository.h repositories/pets_equipmentset_entries_repository.h - repositories/player_titlesets_repository.h + repositories/pets_equipmentset_repository.h + repositories/pets_repository.h repositories/player_event_aa_purchase_repository.h - repositories/player_event_killed_npc_repository.h repositories/player_event_killed_named_npc_repository.h + repositories/player_event_killed_npc_repository.h repositories/player_event_killed_raid_npc_repository.h repositories/player_event_log_settings_repository.h repositories/player_event_logs_repository.h repositories/player_event_loot_items_repository.h repositories/player_event_merchant_purchase_repository.h repositories/player_event_merchant_sell_repository.h - repositories/player_event_npc_handin_repository.h repositories/player_event_npc_handin_entries_repository.h + repositories/player_event_npc_handin_repository.h repositories/player_event_speech_repository.h - repositories/player_event_trade_repository.h repositories/player_event_trade_entries_repository.h + repositories/player_event_trade_repository.h + repositories/player_titlesets_repository.h repositories/quest_globals_repository.h repositories/raid_details_repository.h repositories/raid_members_repository.h @@ -501,44 +500,47 @@ SET(repositories repositories/rule_values_repository.h repositories/saylink_repository.h repositories/server_scheduled_events_repository.h - repositories/shared_tasks_repository.h repositories/shared_task_activity_state_repository.h repositories/shared_task_dynamic_zones_repository.h repositories/shared_task_members_repository.h + repositories/shared_tasks_repository.h repositories/skill_caps_repository.h repositories/spawn2_repository.h - repositories/spawnentry_repository.h - repositories/spawngroup_repository.h - repositories/spawn_conditions_repository.h repositories/spawn_condition_values_repository.h + repositories/spawn_conditions_repository.h repositories/spawn_events_repository.h - repositories/spells_new_repository.h + repositories/spawnentry_repository.h + repositories/spawngroup_repository.h repositories/spell_buckets_repository.h repositories/spell_globals_repository.h - repositories/starting_items_repository.h + repositories/spells_new_repository.h repositories/start_zones_repository.h + repositories/starting_items_repository.h + repositories/task_activities_repository.h repositories/tasks_repository.h repositories/tasksets_repository.h - repositories/task_activities_repository.h repositories/timers_repository.h repositories/titles_repository.h repositories/trader_repository.h - repositories/tradeskill_recipe_repository.h repositories/tradeskill_recipe_entries_repository.h + repositories/tradeskill_recipe_repository.h repositories/traps_repository.h - repositories/tributes_repository.h repositories/tribute_levels_repository.h + repositories/tributes_repository.h repositories/veteran_reward_templates_repository.h - repositories/zone_repository.h repositories/zone_points_repository.h - + repositories/zone_repository.h ) -SET(common_headers +set(common_headers + StackWalker/StackWalker.h additive_lagged_fibonacci_engine.h - bazaar.h base_packet.h + bazaar.h bodytypes.h + cli/argh.h + cli/eqemu_command_handler.h + cli/terminal_color.hpp classes.h compression.h condition.h @@ -546,15 +548,16 @@ SET(common_headers crash.h crc16.h crc32.h - cli/argh.h - cli/eqemu_command_handler.h - cli/terminal_color.hpp cron/croncpp.h - database/database_dump_service.h + data_bucket.cpp data_verification.h database.h - database_schema.h + database/database_dump_service.h database/database_update.h + database/database_update_manifest.h + database/database_update_manifest_bots.h + database/database_update_manifest_custom.h + database_schema.h dbcore.h deity.h discord/discord.h @@ -567,30 +570,33 @@ SET(common_headers emu_oplist.h emu_versions.h eq_constants.h + eq_limits.h + eq_packet.h eq_packet_structs.h + eq_stream_ident.h + eq_stream_intf.h + eq_stream_locator.h + eq_stream_proxy.h eqdb.h eqdb_res.h - eqemu_exception.h eqemu_config.h eqemu_config_elements.h + eqemu_exception.h eqemu_logsys.h eqemu_logsys_log_aliases.h - eq_limits.h - eq_packet.h - eq_stream_ident.h - eq_stream_intf.h - eq_stream_locator.h - eq_stream_proxy.h eqtime.h - events/player_event_logs.h + event/event_loop.h + event/task.h + event/timer.h + event_sub.h events/player_event_discord_formatter.h + events/player_event_logs.h events/player_events.h - event_sub.h evolving_items.h extprofile.h faction.h - file.h features.h + file.h fixed_memory_hash_set.h fixed_memory_variable_hash_set.h global_define.h @@ -600,10 +606,13 @@ SET(common_headers http/uri.h inventory_profile.h inventory_slot.h - ipc_mutex.h ip_util.h + ipc_mutex.h item_data.h item_instance.h + json/json-forwards.h + json/json.h + json/json_archive_single_line.h json_config.h light_source.h linked_list.h @@ -618,55 +627,6 @@ SET(common_headers mysql_request_result.h mysql_request_row.h mysql_stmt.h - op_codes.h - opcode_dispatch.h - opcodemgr.h - packet_dump.h - packet_dump_file.h - packet_functions.h - path_manager.cpp - platform.h - process/process.h - process.h - proc_launcher.h - profanity_manager.h - profiler.h - ptimer.h - queue.h - races.h - raid.h - random.h - rdtsc.h - rulesys.h - ruletypes.h - say_link.h - seperator.h - serialize_buffer.h - server_event_scheduler.h - serverinfo.h - servertalk.h - server_reload_types.h - shared_tasks.h - shareddb.h - skills.h - skill_caps.h - spdat.h - strings.h - struct_strategy.h - tasks.h - textures.h - timer.h - types.h - unix.h - useperl.h - version.h - zone_store.h - event/event_loop.h - event/task.h - event/timer.h - json/json_archive_single_line.h - json/json.h - json/json-forwards.h net/console_server.h net/console_server_connection.h net/crc32.h @@ -678,8 +638,8 @@ SET(common_headers net/reliable_stream_pooling.h net/reliable_stream_structs.h net/servertalk_client_connection.h - net/servertalk_legacy_client_connection.h net/servertalk_common.h + net/servertalk_legacy_client_connection.h net/servertalk_server.h net/servertalk_server_connection.h net/tcp_connection.h @@ -687,7 +647,21 @@ SET(common_headers net/tcp_server.h net/websocket_server.h net/websocket_server_connection.h + op_codes.h + opcode_dispatch.h + opcodemgr.h + packet_dump.h + packet_dump_file.h + packet_functions.h patches/patches.h + patches/rof.h + patches/rof2.h + patches/rof2_limits.h + patches/rof2_ops.h + patches/rof2_structs.h + patches/rof_limits.h + patches/rof_ops.h + patches/rof_structs.h patches/sod.h patches/sod_limits.h patches/sod_ops.h @@ -699,14 +673,6 @@ SET(common_headers patches/ss_declare.h patches/ss_define.h patches/ss_register.h - patches/rof.h - patches/rof_limits.h - patches/rof_ops.h - patches/rof_structs.h - patches/rof2.h - patches/rof2_limits.h - patches/rof2_ops.h - patches/rof2_structs.h patches/titanium.h patches/titanium_limits.h patches/titanium_ops.h @@ -715,138 +681,142 @@ SET(common_headers patches/uf_limits.h patches/uf_ops.h patches/uf_structs.h - termcolor/rang.hpp + path_manager.cpp + platform.h + proc_launcher.h + process.h + process/process.h + profanity_manager.h + profiler.h + ptimer.h + queue.h + races.h + raid.h + random.h + rdtsc.h + rulesys.h + ruletypes.h + say_link.h + seperator.h + serialize_buffer.h + server_event_scheduler.h + server_reload_types.h + serverinfo.h + servertalk.h + shared_tasks.h + shareddb.h + skill_caps.h + skills.h + spdat.h stacktrace/backward.hpp - StackWalker/StackWalker.h - util/memory_stream.h + strings.h + struct_strategy.h + tasks.h + termcolor/rang.hpp + textures.h + timer.h + types.h + unix.h + useperl.h util/directory.h + util/memory_stream.h util/uuid.h + version.h + zone_store.h ) -SOURCE_GROUP(Event FILES - event/event_loop.h - event/timer.h - event/task.h -) +# Source Groups (Regex based for automatic subdirectory handling) +source_group("CLI" REGULAR_EXPRESSION "^cli/") +source_group("Content" REGULAR_EXPRESSION "^content/") +source_group("Cron" REGULAR_EXPRESSION "^cron/") +source_group("Database" REGULAR_EXPRESSION "^database/") +source_group("Discord" REGULAR_EXPRESSION "^discord/") +source_group("Event" REGULAR_EXPRESSION "^event/") +source_group("Events" REGULAR_EXPRESSION "^events/") +source_group("Http" REGULAR_EXPRESSION "^http/") +source_group("Json" REGULAR_EXPRESSION "^json/") +source_group("Memory" REGULAR_EXPRESSION "^memory/") +source_group("Net" REGULAR_EXPRESSION "^net/") +source_group("Patches" REGULAR_EXPRESSION "^patches/") +source_group("Process" REGULAR_EXPRESSION "^process/") +source_group("Repositories" REGULAR_EXPRESSION "^repositories/") +source_group("StackWalker" REGULAR_EXPRESSION "^StackWalker/") +source_group("Stacktrace" REGULAR_EXPRESSION "^stacktrace/") +source_group("Termcolor" REGULAR_EXPRESSION "^termcolor/") +source_group("Util" REGULAR_EXPRESSION "^util/") -SOURCE_GROUP(Json FILES - json/json.h - json/jsoncpp.cpp - json/json-forwards.h -) +option(EQEMU_ADD_PROFILER "Link with Google perftools profiler" OFF) +#PRNG options +option(EQEMU_ADDITIVE_LFIB_PRNG "Use Additive LFib for PRNG." OFF) +mark_as_advanced(EQEMU_ADDITIVE_LFIB_PRNG) +option(EQEMU_BIASED_INT_DIST "Use biased int dist instead of uniform." OFF) +mark_as_advanced(EQEMU_BIASED_INT_DIST) +set(EQEMU_CUSTOM_PRNG_ENGINE "" CACHE STRING "Custom random engine. (ex. std::default_random_engine)") +mark_as_advanced(EQEMU_CUSTOM_PRNG_ENGINE) -SOURCE_GROUP(Net FILES - net/console_server.cpp - net/console_server.h - net/console_server_connection.cpp - net/console_server_connection.h - net/crc32.cpp - net/crc32.h - net/dns.h - net/endian.h - net/eqmq.cpp - net/eqmq.h - net/eqstream.cpp - net/eqstream.h - net/packet.cpp - net/packet.h - net/reliable_stream_connection.cpp - net/reliable_stream_connection.h - net/reliable_stream_pooling.h - net/reliable_stream_structs.h - net/servertalk_client_connection.cpp - net/servertalk_client_connection.h - net/servertalk_legacy_client_connection.cpp - net/servertalk_legacy_client_connection.h - net/servertalk_common.h - net/servertalk_server.cpp - net/servertalk_server.h - net/servertalk_server_connection.cpp - net/servertalk_server_connection.h - net/tcp_connection.cpp - net/tcp_connection.h - net/tcp_connection_pooling.h - net/tcp_server.cpp - net/tcp_server.h - net/websocket_server.cpp - net/websocket_server.h - net/websocket_server_connection.cpp - net/websocket_server_connection.h -) +if(CMAKE_COMPILER_IS_GNUCXX) + option(EQEMU_SFMT19937 "Use GCC's extention for SIMD Fast MT19937." OFF) + mark_as_advanced(EQEMU_SFMT19937) +endif() -SOURCE_GROUP(Patches FILES - patches/patches.h - patches/sod.h - patches/sod_limits.h - patches/sod_ops.h - patches/sod_structs.h - patches/sof.h - patches/sof_limits.h - patches/sof_ops.h - patches/sof_structs.h - patches/ss_declare.h - patches/ss_define.h - patches/ss_register.h - patches/rof.h - patches/rof_limits.h - patches/rof_ops.h - patches/rof_structs.h - patches/rof2.h - patches/rof2_limits.h - patches/rof2_ops.h - patches/rof2_structs.h - patches/titanium.h - patches/titanium_limits.h - patches/titanium_ops.h - patches/titanium_structs.h - patches/uf.h - patches/uf_limits.h - patches/uf_ops.h - patches/uf_structs.h - patches/patches.cpp - patches/sod.cpp - patches/sod_limits.cpp - patches/sof.cpp - patches/sof_limits.cpp - patches/rof.cpp - patches/rof_limits.cpp - patches/rof2.cpp - patches/rof2_limits.cpp - patches/titanium.cpp - patches/titanium_limits.cpp - patches/uf.cpp - patches/uf_limits.cpp -) +include_directories(Patches SocketLib StackWalker) -SOURCE_GROUP(StackWalker FILES - StackWalker/StackWalker.h - StackWalker/StackWalker.cpp -) +add_library(common ${common_sources} ${common_headers} ${repositories}) -SOURCE_GROUP(Util FILES - util/memory_stream.h - util/directory.cpp - util/directory.h - util/uuid.cpp - util/uuid.h -) +target_compile_definitions(common PUBLIC BOOST_BIND_GLOBAL_PLACEHOLDERS GLM_FORCE_RADIANS GLM_FORCE_CTOR_INIT GLM_ENABLE_EXPERIMENTAL ENABLE_SECURITY) +target_include_directories(common PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../submodules/websocketpp") +target_link_libraries(common PUBLIC cereal::cereal fmt::fmt unofficial::libmariadb $,libuv::uv_a,libuv::uv> OpenSSL::SSL OpenSSL::Crypto ZLIB::ZLIB unofficial-sodium::sodium) + +# Requires libgoogle-perftools-dev google-perftools packages for linux (debian) +if(EQEMU_ADD_PROFILER) + set(CMAKE_EXE_LINKER_FLAGS "-Wl,--no-as-needed,-lprofiler,--as-needed") +endif() + +if(EQEMU_ADDITIVE_LFIB_PRNG) + target_compile_definitions(common PUBLIC USE_ADDITIVE_LFIB_PRNG) + if(EQEMU_SFMT19937) + message(STATUS "SFMT19937 and ADDITITVE_LFIB_PRNG both set, SFMT19937 ignored.") + set(EQEMU_SFMT19937 OFF) + endif() + if(NOT EQEMU_CUSTOM_PRNG_ENGINE STREQUAL "") + message(STATUS "CUSTOM_PRNG_ENGINE and ADDITITVE_LFIB_PRNG both set, CUSTOM_PRNG_ENGINE ignored.") + set(EQEMU_CUSTOM_PRNG_ENGINE "") + endif() +endif() + +if(EQEMU_SFMT19937) + target_compile_definitions(common PUBLIC USE_SFMT19937) + if(NOT EQEMU_CUSTOM_PRNG_ENGINE STREQUAL "") + message(STATUS "CUSTOM_PRNG_ENGINE and SFMT19937 both set, CUSTOM_PRNG_ENGINE ignored.") + set(EQEMU_CUSTOM_PRNG_ENGINE "") + endif() +endif() + +if(NOT EQEMU_CUSTOM_PRNG_ENGINE STREQUAL "") + target_compile_definitions(common PUBLIC USE_CUSTOM_PRNG_ENGINE=${EQEMU_CUSTOM_PRNG_ENGINE}) +endif() -INCLUDE_DIRECTORIES(Patches SocketLib StackWalker) +if(EQEMU_BIASED_INT_DIST) + target_compile_definitions(common PUBLIC BIASED_INT_DIST) +endif() -ADD_LIBRARY(common ${common_sources} ${common_headers} ${repositories}) +if(${OPENSSL_VERSION} VERSION_GREATER_EQUAL "1.1.1") + target_compile_definitions(common PUBLIC CPPHTTPLIB_OPENSSL_SUPPORT) +endif() -IF (UNIX) - SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) - SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0) -ENDIF (UNIX) +if(UNIX) + target_link_libraries(common PUBLIC uuid) + set_source_files_properties("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) + set_source_files_properties("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0) +endif() -IF (EQEMU_BUILD_PCH) +if(EQEMU_BUILD_PCH) TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/std-pch.h) # Avoid PCH/__OPTIMIZE__ mismatch when compiling certain patch sources with -O0 # These files are compiled with -O0 on UNIX (see COMPILE_FLAGS above), which # disables the __OPTIMIZE__ predefined macro. Disabling PCH for them prevents # Clang from erroring due to macro state differences between the PCH and TU. - SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES SKIP_PRECOMPILE_HEADERS ON) -ENDIF () + set_source_files_properties("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES SKIP_PRECOMPILE_HEADERS ON) +endif() -SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) \ No newline at end of file diff --git a/common/classes.cpp b/common/classes.cpp index f849a5bfd3..df13500043 100644 --- a/common/classes.cpp +++ b/common/classes.cpp @@ -16,6 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include "../common/global_define.h" #include "../common/classes.h" #include "data_verification.h" diff --git a/common/cli/eqemu_command_handler.cpp b/common/cli/eqemu_command_handler.cpp index 9017adbb3d..bf796b42b1 100644 --- a/common/cli/eqemu_command_handler.cpp +++ b/common/cli/eqemu_command_handler.cpp @@ -19,6 +19,7 @@ */ #include +#include #include "eqemu_command_handler.h" #include "terminal_color.hpp" #include "../platform.h" diff --git a/common/data_bucket.cpp b/common/data_bucket.cpp index bef06a1245..0378c379f3 100644 --- a/common/data_bucket.cpp +++ b/common/data_bucket.cpp @@ -9,17 +9,7 @@ using json = nlohmann::json; const std::string NESTED_KEY_DELIMITER = "."; std::vector g_data_bucket_cache = {}; -#if defined(ZONE) -#include "../zone/zonedb.h" -extern ZoneDatabase database; -#elif defined(WORLD) -#include "../world/worlddb.h" -extern WorldDatabase database; -#else -#error "You must define either ZONE or WORLD" -#endif - -void DataBucket::SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time) +void DataBucket::SetData(SharedDatabase* database, const std::string &bucket_key, const std::string &bucket_value, std::string expires_time) { auto k = DataBucketKey{ .key = bucket_key, @@ -27,10 +17,10 @@ void DataBucket::SetData(const std::string &bucket_key, const std::string &bucke .expires = expires_time, }; - DataBucket::SetData(k); + DataBucket::SetData(database, k); } -void DataBucket::SetData(const DataBucketKey &k_) +void DataBucket::SetData(SharedDatabase *database, const DataBucketKey &k_) { DataBucketKey k = k_; // copy the key so we can modify it bool is_nested = k.key.find(NESTED_KEY_DELIMITER) != std::string::npos; @@ -39,7 +29,7 @@ void DataBucket::SetData(const DataBucketKey &k_) } auto b = DataBucketsRepository::NewEntity(); - auto r = GetData(k, true); + auto r = GetData(database, k, true); // if we have an entry, use it if (r.id > 0) { b = r; @@ -149,10 +139,10 @@ void DataBucket::SetData(const DataBucketKey &k_) } } - DataBucketsRepository::UpdateOne(database, b); + DataBucketsRepository::UpdateOne(*database, b); } else { - b = DataBucketsRepository::InsertOne(database, b); + b = DataBucketsRepository::InsertOne(*database, b); // add to cache if it doesn't exist if (CanCache(k) && !ExistsInCache(b)) { @@ -162,9 +152,9 @@ void DataBucket::SetData(const DataBucketKey &k_) } } -std::string DataBucket::GetData(const std::string &bucket_key) +std::string DataBucket::GetData(SharedDatabase* database, const std::string &bucket_key) { - return GetData(DataBucketKey{.key = bucket_key}).value; + return GetData(database, DataBucketKey{.key = bucket_key}).value; } DataBucketsRepository::DataBuckets DataBucket::ExtractNestedValue( @@ -214,7 +204,7 @@ DataBucketsRepository::DataBuckets DataBucket::ExtractNestedValue( // if the bucket doesn't exist, it will be added to the cache as a miss // if ignore_misses_cache is true, the bucket will not be added to the cache as a miss // the only place we should be ignoring the misses cache is on the initial read during SetData -DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k_, bool ignore_misses_cache) +DataBucketsRepository::DataBuckets DataBucket::GetData(SharedDatabase* database, const DataBucketKey &k_, bool ignore_misses_cache) { DataBucketKey k = k_; // Copy the key so we can modify it @@ -244,7 +234,7 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k_, if (CheckBucketMatch(e, k)) { if (e.expires > 0 && e.expires < std::time(nullptr)) { LogDataBuckets("Attempted to read expired key [{}] removing from cache", e.key_); - DeleteData(k); + DeleteData(database, k); return DataBucketsRepository::NewEntity(); } @@ -261,7 +251,7 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k_, // Fetch the value from the database auto r = DataBucketsRepository::GetWhere( - database, + *database, fmt::format( " {} `key` = '{}' LIMIT 1", DataBucket::GetScopedDbFilters(k), @@ -310,7 +300,7 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k_, // If the entry has expired, delete it if (bucket.expires > 0 && bucket.expires < static_cast(std::time(nullptr))) { - DeleteData(k); + DeleteData(database, k); return DataBucketsRepository::NewEntity(); } @@ -337,22 +327,22 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k_, return bucket; } -std::string DataBucket::GetDataExpires(const std::string &bucket_key) +std::string DataBucket::GetDataExpires(SharedDatabase* database, const std::string &bucket_key) { - return GetDataExpires(DataBucketKey{.key = bucket_key}); + return GetDataExpires(database, DataBucketKey{.key = bucket_key}); } -std::string DataBucket::GetDataRemaining(const std::string &bucket_key) +std::string DataBucket::GetDataRemaining(SharedDatabase* database, const std::string &bucket_key) { - return GetDataRemaining(DataBucketKey{.key = bucket_key}); + return GetDataRemaining(database, DataBucketKey{.key = bucket_key}); } -bool DataBucket::DeleteData(const std::string &bucket_key) +bool DataBucket::DeleteData(SharedDatabase* database, const std::string &bucket_key) { - return DeleteData(DataBucketKey{.key = bucket_key}); + return DeleteData(database, DataBucketKey{.key = bucket_key}); } -bool DataBucket::DeleteData(const DataBucketKey &k) +bool DataBucket::DeleteData(SharedDatabase* database, const DataBucketKey &k) { bool is_nested_key = k.key.find(NESTED_KEY_DELIMITER) != std::string::npos; @@ -374,7 +364,7 @@ bool DataBucket::DeleteData(const DataBucketKey &k) // Regular key deletion, no nesting involved return DataBucketsRepository::DeleteWhere( - database, + *database, fmt::format("{} `key` = '{}'", DataBucket::GetScopedDbFilters(k), k.key) ); } @@ -384,7 +374,7 @@ bool DataBucket::DeleteData(const DataBucketKey &k) DataBucketKey top_level_k = k; top_level_k.key = top_level_key; - auto r = GetData(top_level_k); + auto r = GetData(database, top_level_k); if (r.id == 0 || r.value.empty() || !Strings::IsValidJson(r.value)) { LogDataBuckets("Attempted to delete nested key [{}] but parent key [{}] does not exist or is invalid JSON", k.key, top_level_key); return false; @@ -444,14 +434,14 @@ bool DataBucket::DeleteData(const DataBucketKey &k) } return DataBucketsRepository::DeleteWhere( - database, + *database, fmt::format("{} `key` = '{}'", DataBucket::GetScopedDbFilters(k), top_level_key) ); } // Otherwise, update the existing JSON without the deleted key r.value = json_value.dump(); - DataBucketsRepository::UpdateOne(database, r); + DataBucketsRepository::UpdateOne(*database, r); // Update cache if (CanCache(k)) { @@ -466,7 +456,7 @@ bool DataBucket::DeleteData(const DataBucketKey &k) return true; } -std::string DataBucket::GetDataExpires(const DataBucketKey &k) +std::string DataBucket::GetDataExpires(SharedDatabase* database, const DataBucketKey &k) { LogDataBuckets( "Getting bucket expiration key [{}] bot_id [{}] account_id [{}] character_id [{}] npc_id [{}]", @@ -477,7 +467,7 @@ std::string DataBucket::GetDataExpires(const DataBucketKey &k) k.npc_id ); - auto r = GetData(k); + auto r = GetData(database, k); if (r.id == 0) { return {}; } @@ -485,7 +475,7 @@ std::string DataBucket::GetDataExpires(const DataBucketKey &k) return std::to_string(r.expires); } -std::string DataBucket::GetDataRemaining(const DataBucketKey &k) +std::string DataBucket::GetDataRemaining(SharedDatabase* database, const DataBucketKey &k) { LogDataBuckets( "Getting bucket remaining key [{}] bot_id [{}] account_id [{}] character_id [{}] npc_id [{}] bot_id [{}] zone_id [{}] instance_id [{}]", @@ -499,7 +489,7 @@ std::string DataBucket::GetDataRemaining(const DataBucketKey &k) k.instance_id ); - auto r = GetData(k); + auto r = GetData(database, k); if (r.id == 0) { return "0"; } @@ -565,10 +555,10 @@ bool DataBucket::CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe, ); } -void DataBucket::LoadZoneCache(uint16 zone_id, uint16 instance_id) +void DataBucket::LoadZoneCache(SharedDatabase* database, uint16 zone_id, uint16 instance_id) { const auto &l = DataBucketsRepository::GetWhere( - database, + *database, fmt::format( "zone_id = {} AND instance_id = {} AND (`expires` > {} OR `expires` = 0)", zone_id, @@ -608,7 +598,7 @@ void DataBucket::LoadZoneCache(uint16 zone_id, uint16 instance_id) ); } -void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector ids) +void DataBucket::BulkLoadEntitiesToCache(SharedDatabase* database, DataBucketLoadType::Type t, std::vector ids) { if (ids.empty()) { return; @@ -653,7 +643,7 @@ void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector } const auto &l = DataBucketsRepository::GetWhere( - database, + *database, fmt::format( "{} IN ({}) AND (`expires` > {} OR `expires` = 0)", column, @@ -843,4 +833,4 @@ bool DataBucket::CanCache(const DataBucketKey &key) } return false; -} \ No newline at end of file +} diff --git a/common/data_bucket.h b/common/data_bucket.h index 6f5c1bcc62..c93d98b2c3 100644 --- a/common/data_bucket.h +++ b/common/data_bucket.h @@ -5,6 +5,7 @@ #include "types.h" #include "repositories/data_buckets_repository.h" #include "json/json_archive_single_line.h" +#include "shareddb.h" struct DataBucketKey { std::string key; @@ -38,26 +39,26 @@ namespace DataBucketLoadType { class DataBucket { public: // non-scoped bucket methods (for global buckets) - static void SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time = ""); - static bool DeleteData(const std::string &bucket_key); - static std::string GetData(const std::string &bucket_key); - static std::string GetDataExpires(const std::string &bucket_key); - static std::string GetDataRemaining(const std::string &bucket_key); + static void SetData(SharedDatabase *database, const std::string &bucket_key, const std::string &bucket_value, std::string expires_time = ""); + static bool DeleteData(SharedDatabase *database, const std::string &bucket_key); + static std::string GetData(SharedDatabase *database, const std::string &bucket_key); + static std::string GetDataExpires(SharedDatabase *database, const std::string &bucket_key); + static std::string GetDataRemaining(SharedDatabase *database, const std::string &bucket_key); // scoped bucket methods - static void SetData(const DataBucketKey &k_); - static bool DeleteData(const DataBucketKey &k); - static DataBucketsRepository::DataBuckets GetData(const DataBucketKey &k_, bool ignore_misses_cache = false); - static std::string GetDataExpires(const DataBucketKey &k); - static std::string GetDataRemaining(const DataBucketKey &k); + static void SetData(SharedDatabase *database, const DataBucketKey &k_); + static bool DeleteData(SharedDatabase *database, const DataBucketKey &k); + static DataBucketsRepository::DataBuckets GetData(SharedDatabase *database, const DataBucketKey &k_, bool ignore_misses_cache = false); + static std::string GetDataExpires(SharedDatabase *database, const DataBucketKey &k); + static std::string GetDataRemaining(SharedDatabase *database, const DataBucketKey &k); static std::string GetScopedDbFilters(const DataBucketKey &k); // bucket repository versus key matching static bool CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe, const DataBucketKey &k); static bool ExistsInCache(const DataBucketsRepository::DataBuckets &entry); - static void LoadZoneCache(uint16 zone_id, uint16 instance_id); - static void BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector ids); + static void LoadZoneCache(SharedDatabase* database, uint16 zone_id, uint16 instance_id); + static void BulkLoadEntitiesToCache(SharedDatabase* database, DataBucketLoadType::Type t, std::vector ids); static void DeleteCachedBuckets(DataBucketLoadType::Type type, uint32 id, uint32 secondary_id = 0); static void DeleteFromMissesCache(DataBucketsRepository::DataBuckets e); diff --git a/common/database/database_update.cpp b/common/database/database_update.cpp index d296aa92bd..d1837b448b 100644 --- a/common/database/database_update.cpp +++ b/common/database/database_update.cpp @@ -5,11 +5,10 @@ #include "../strings.h" #include "../rulesys.h" #include "../http/httplib.h" - -#include "database_update_manifest.cpp" -#include "database_update_manifest_custom.cpp" -#include "database_update_manifest_bots.cpp" #include "database_dump_service.h" +#include "database_update_manifest.h" +#include "database_update_manifest_custom.h" +#include "database_update_manifest_bots.h" constexpr int BREAK_LENGTH = 70; diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.h similarity index 99% rename from common/database/database_update_manifest.cpp rename to common/database/database_update_manifest.h index 15dc4a27f5..6e88d04819 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.h @@ -1,4 +1,4 @@ -#include "database_update.h" +#pragma once std::vector manifest_entries = { ManifestEntry{ diff --git a/common/database/database_update_manifest_bots.cpp b/common/database/database_update_manifest_bots.h similarity index 99% rename from common/database/database_update_manifest_bots.cpp rename to common/database/database_update_manifest_bots.h index c2da0fd708..4f492bda7b 100644 --- a/common/database/database_update_manifest_bots.cpp +++ b/common/database/database_update_manifest_bots.h @@ -1,4 +1,4 @@ -#include "database_update.h" +#pragma once std::vector bot_manifest_entries = { ManifestEntry{ diff --git a/common/database/database_update_manifest_custom.cpp b/common/database/database_update_manifest_custom.h similarity index 98% rename from common/database/database_update_manifest_custom.cpp rename to common/database/database_update_manifest_custom.h index e441d600c1..61bc102961 100644 --- a/common/database/database_update_manifest_custom.cpp +++ b/common/database/database_update_manifest_custom.h @@ -1,4 +1,4 @@ -#include "database_update.h" +#pragma once std::vector manifest_entries_custom = { ManifestEntry{ diff --git a/common/dbcore.cpp b/common/dbcore.cpp index ff0afac3ab..bb233536c2 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -258,9 +258,17 @@ bool DBcore::Open(uint32 *errnum, char *errbuf) if (pCompress) { flags |= CLIENT_COMPRESS; } + + //todo: we need to revisit this ssl handling later + //the whole connect code is ancient and tls is starting to come as a default requirement for many db setups if (pSSL) { flags |= CLIENT_SSL; } + else { + int off = 0; + mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &off); + mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &off); + } if (mysql_real_connect(mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) { pStatus = Connected; diff --git a/common/dynamic_zone_lockout.cpp b/common/dynamic_zone_lockout.cpp index a47a9e205f..a714dc1015 100644 --- a/common/dynamic_zone_lockout.cpp +++ b/common/dynamic_zone_lockout.cpp @@ -3,6 +3,7 @@ #include "rulesys.h" #include "util/uuid.h" #include +#include #include DzLockout::DzLockout(std::string uuid, std::string expedition, std::string event, uint64_t expire_time, uint32_t duration) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 0a13492540..cb0cc7732b 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -23,9 +23,9 @@ #include #include #include -#include "../cereal/include/cereal/archives/binary.hpp" -#include "../cereal/include/cereal/types/string.hpp" -#include "../cereal/include/cereal/types/vector.hpp" +#include +#include +#include #include "../common/version.h" #include "emu_constants.h" #include "textures.h" diff --git a/common/eqemu_config.h b/common/eqemu_config.h index 57a0543c84..94b0fea521 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -23,6 +23,7 @@ #include "path_manager.h" #include #include +#include struct LoginConfig { std::string LoginHost; diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index 0757b3e98c..210d784f8e 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -34,6 +34,7 @@ #endif #include +#include #include "types.h" namespace Logs { diff --git a/common/events/player_event_discord_formatter.cpp b/common/events/player_event_discord_formatter.cpp index 5b068f5070..b25680902d 100644 --- a/common/events/player_event_discord_formatter.cpp +++ b/common/events/player_event_discord_formatter.cpp @@ -3,6 +3,7 @@ #include "../json/json_archive_single_line.h" #include #include +#include #include #include diff --git a/common/file.cpp b/common/file.cpp index 97eec90514..df15255afc 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -36,6 +36,7 @@ #endif #include +#include #include #include #include diff --git a/common/ip_util.cpp b/common/ip_util.cpp index df4abcfc0f..c0316ea109 100644 --- a/common/ip_util.cpp +++ b/common/ip_util.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include "ip_util.h" diff --git a/common/net/console_server.cpp b/common/net/console_server.cpp index a5276f4cf1..4cc2b21269 100644 --- a/common/net/console_server.cpp +++ b/common/net/console_server.cpp @@ -1,6 +1,7 @@ #include "console_server.h" #include "../strings.h" #include +#include EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port) { diff --git a/common/net/console_server_connection.cpp b/common/net/console_server_connection.cpp index e53058f67d..47e321b805 100644 --- a/common/net/console_server_connection.cpp +++ b/common/net/console_server_connection.cpp @@ -5,6 +5,7 @@ #include "../servertalk.h" #include "../rulesys.h" #include +#include EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr connection) { diff --git a/common/net/packet.cpp b/common/net/packet.cpp index 1ae959e621..a4ec4b4982 100644 --- a/common/net/packet.cpp +++ b/common/net/packet.cpp @@ -2,6 +2,7 @@ #include "endian.h" #include #include +#include void EQ::Net::Packet::PutInt8(size_t offset, int8_t value) { diff --git a/common/net/reliable_stream_connection.cpp b/common/net/reliable_stream_connection.cpp index e1101f452e..c75bfe77ab 100644 --- a/common/net/reliable_stream_connection.cpp +++ b/common/net/reliable_stream_connection.cpp @@ -4,6 +4,7 @@ #include "crc32.h" #include #include +#include // observed client receive window is 300 packets, 140KB constexpr size_t MAX_CLIENT_RECV_PACKETS_PER_WINDOW = 300; diff --git a/common/net/websocket_server.cpp b/common/net/websocket_server.cpp index f74f437bac..1e8b80b64e 100644 --- a/common/net/websocket_server.cpp +++ b/common/net/websocket_server.cpp @@ -2,6 +2,7 @@ #include "../event/event_loop.h" #include "../event/timer.h" #include +#include #include #include #include diff --git a/common/net/websocket_server_connection.cpp b/common/net/websocket_server_connection.cpp index 3c12715185..36e85eb743 100644 --- a/common/net/websocket_server_connection.cpp +++ b/common/net/websocket_server_connection.cpp @@ -4,6 +4,7 @@ #include "../util/uuid.h" #include #include +#include struct EQ::Net::WebsocketServerConnection::Impl { WebsocketServer *parent; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 6433621f5c..c414b3353b 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -38,7 +38,7 @@ #include "../raid.h" #include "../guilds.h" //#include "../repositories/trader_repository.h" -#include "../cereal/include/cereal/types/vector.hpp" +#include #include #include diff --git a/common/process/process.cpp b/common/process/process.cpp index 56bbeff2b4..92bf757f48 100644 --- a/common/process/process.cpp +++ b/common/process/process.cpp @@ -2,6 +2,7 @@ #include #include "process.h" #include +#include std::string Process::execute(const std::string &cmd) { diff --git a/common/profanity_manager.h b/common/profanity_manager.h index 311ca19e00..165b6516e0 100644 --- a/common/profanity_manager.h +++ b/common/profanity_manager.h @@ -23,7 +23,7 @@ #include #include #include - +#include class DBcore; diff --git a/common/repositories/trader_repository.h b/common/repositories/trader_repository.h index 0354d64371..3c5fbdafc9 100644 --- a/common/repositories/trader_repository.h +++ b/common/repositories/trader_repository.h @@ -7,8 +7,8 @@ #include "items_repository.h" #include "../../common/item_data.h" #include "../../common/races.h" -#include "../cereal/include/cereal/archives/binary.hpp" -#include "../cereal/include/cereal/types/string.hpp" +#include +#include class TraderRepository : public BaseTraderRepository { public: diff --git a/common/rulesys.cpp b/common/rulesys.cpp index f73112b1b4..3e6f833a8f 100644 --- a/common/rulesys.cpp +++ b/common/rulesys.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "../common/repositories/rule_sets_repository.h" #include "../common/repositories/rule_values_repository.h" diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 0ef0cbe4e0..89da73410f 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #if defined(_MSC_VER) && _MSC_VER >= 1800 #include diff --git a/common/strings.cpp b/common/strings.cpp index eb56ab2f52..62aec29759 100644 --- a/common/strings.cpp +++ b/common/strings.cpp @@ -36,6 +36,7 @@ #include "strings.h" #include #include +#include #include #include @@ -47,14 +48,9 @@ #include #include -//Const char based -#include "strings_legacy.cpp" // legacy c functions -#include "strings_misc.cpp" // anything non "Strings" scoped - #ifdef _WINDOWS #include #include -#include #endif std::string Strings::Random(size_t length) diff --git a/common/util/uuid.cpp b/common/util/uuid.cpp index 7acd1517fd..1e221b5b9c 100644 --- a/common/util/uuid.cpp +++ b/common/util/uuid.cpp @@ -2,6 +2,7 @@ #include #include +#include #ifdef _WIN32 #include diff --git a/eqlaunch/CMakeLists.txt b/eqlaunch/CMakeLists.txt index 4fde2c2220..beafeb7f02 100644 --- a/eqlaunch/CMakeLists.txt +++ b/eqlaunch/CMakeLists.txt @@ -1,20 +1,20 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.12) +cmake_minimum_required(VERSION 3.20) -SET(eqlaunch_sources +set(eqlaunch_sources eqlaunch.cpp worldserver.cpp zone_launch.cpp ) -SET(eqlaunch_headers +set(eqlaunch_headers worldserver.h zone_launch.h ) -ADD_EXECUTABLE(eqlaunch ${eqlaunch_sources} ${eqlaunch_headers}) +add_executable(eqlaunch ${eqlaunch_sources} ${eqlaunch_headers}) -INSTALL(TARGETS eqlaunch RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS eqlaunch RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -TARGET_LINK_LIBRARIES(eqlaunch ${SERVER_LIBS}) +target_link_libraries(eqlaunch common) -SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/hc/CMakeLists.txt b/hc/CMakeLists.txt deleted file mode 100644 index 9f2c78298b..0000000000 --- a/hc/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) - -SET(hc_sources - eq.cpp - main.cpp - login.cpp - world.cpp -) - -SET(hc_headers - eq.h - login.h - world.h -) - -ADD_EXECUTABLE(hc ${hc_sources} ${hc_headers}) - -INSTALL(TARGETS hc RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) - -TARGET_LINK_LIBRARIES(hc ${SERVER_LIBS}) - -SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/hc/eq.cpp b/hc/eq.cpp deleted file mode 100644 index d8f2877d85..0000000000 --- a/hc/eq.cpp +++ /dev/null @@ -1,350 +0,0 @@ -#include "eq.h" -#include "../common/net/dns.h" - -const char* eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char* buffer_out, bool enc) { - DES_key_schedule k; - DES_cblock v; - - memset(&k, 0, sizeof(DES_key_schedule)); - memset(&v, 0, sizeof(DES_cblock)); - - if (!enc && buffer_in_sz && buffer_in_sz % 8 != 0) { - return nullptr; - } - - DES_ncbc_encrypt((const unsigned char*)buffer_in, (unsigned char*)buffer_out, (long)buffer_in_sz, &k, &v, enc); - return buffer_out; -} - -EverQuest::EverQuest(const std::string &host, int port, const std::string &user, const std::string &pass, const std::string &server, const std::string &character) -{ - m_host = host; - m_port = port; - m_user = user; - m_pass = pass; - m_server = server; - m_character = character; - m_dbid = 0; - - EQ::Net::DNSLookup(m_host, port, false, [&](const std::string &addr) { - if (addr.empty()) { - Log.OutF(Logs::General, Logs::Headless_Client, "Could not resolve address: {0}", m_host); - return; - } - else { - m_host = addr; - m_login_connection_manager.reset(new EQ::Net::ReliableStreamConnectionManager()); - - m_login_connection_manager->OnNewConnection(std::bind(&EverQuest::LoginOnNewConnection, this, std::placeholders::_1)); - m_login_connection_manager->OnConnectionStateChange(std::bind(&EverQuest::LoginOnStatusChangeReconnectEnabled, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - m_login_connection_manager->OnPacketRecv(std::bind(&EverQuest::LoginOnPacketRecv, this, std::placeholders::_1, std::placeholders::_2)); - - m_login_connection_manager->Connect(m_host, m_port); - } - }); -} - -EverQuest::~EverQuest() -{ -} - -void EverQuest::LoginOnNewConnection(std::shared_ptr connection) -{ - m_login_connection = connection; - Log.OutF(Logs::General, Logs::Headless_Client, "Connecting..."); -} - -void EverQuest::LoginOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) -{ - if (to == EQ::Net::StatusConnected) { - Log.OutF(Logs::General, Logs::Headless_Client, "Login connected."); - LoginSendSessionReady(); - } - - if (to == EQ::Net::StatusDisconnected) { - Log.OutF(Logs::General, Logs::Headless_Client, "Login connection lost before we got to world, reconnecting."); - m_key.clear(); - m_dbid = 0; - m_login_connection.reset(); - m_login_connection_manager->Connect(m_host, m_port); - } -} - -void EverQuest::LoginOnStatusChangeReconnectDisabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) -{ - if (to == EQ::Net::StatusDisconnected) { - m_login_connection.reset(); - } -} - -void EverQuest::LoginOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet & p) -{ - auto opcode = p.GetUInt16(0); - switch (opcode) { - case 0x0017: //OP_ChatMessage - LoginSendLogin(); - break; - case 0x0018: - LoginProcessLoginResponse(p); - break; - case 0x0019: - LoginProcessServerPacketList(p); - break; - case 0x0022: - LoginProcessServerPlayResponse(p); - break; - } -} - -void EverQuest::LoginSendSessionReady() -{ - EQ::Net::DynamicPacket p; - p.PutUInt16(0, 1); //OP_SessionReady - p.PutUInt32(2, 2); - - m_login_connection->QueuePacket(p); -} - -void EverQuest::LoginSendLogin() -{ - size_t buffer_len = m_user.length() + m_pass.length() + 2; - std::unique_ptr buffer(new char[buffer_len]); - - strcpy(&buffer[0], m_user.c_str()); - strcpy(&buffer[m_user.length() + 1], m_pass.c_str()); - - size_t encrypted_len = buffer_len; - - if (encrypted_len % 8 > 0) { - encrypted_len = ((encrypted_len / 8) + 1) * 8; - } - - EQ::Net::DynamicPacket p; - p.Resize(12 + encrypted_len); - p.PutUInt16(0, 2); //OP_Login - p.PutUInt32(2, 3); - - eqcrypt_block(&buffer[0], buffer_len, (char*)p.Data() + 12, true); - - m_login_connection->QueuePacket(p); -} - -void EverQuest::LoginSendServerRequest() -{ - EQ::Net::DynamicPacket p; - p.PutUInt16(0, 4); //OP_ServerListRequest - p.PutUInt32(2, 4); - - m_login_connection->QueuePacket(p); -} - -void EverQuest::LoginSendPlayRequest(uint32_t id) -{ - EQ::Net::DynamicPacket p; - p.PutUInt16(0, 0x000d); - p.PutUInt16(2, 5); - p.PutUInt32(4, 0); - p.PutUInt32(8, 0); - p.PutUInt32(12, id); - - m_login_connection->QueuePacket(p); -} - -void EverQuest::LoginProcessLoginResponse(const EQ::Net::Packet & p) -{ - auto encrypt_size = p.Length() - 12; - if (encrypt_size % 8 > 0) { - encrypt_size = (encrypt_size / 8) * 8; - } - - std::unique_ptr decrypted(new char[encrypt_size]); - - eqcrypt_block((char*)p.Data() + 12, encrypt_size, &decrypted[0], false); - - EQ::Net::StaticPacket sp(&decrypted[0], encrypt_size); - auto response_error = sp.GetUInt16(1); - - if (response_error > 101) { - Log.OutF(Logs::General, Logs::Headless_Client, "Error logging in response code: {0}", response_error); - LoginDisableReconnect(); - } - else { - m_key = sp.GetCString(12); - m_dbid = sp.GetUInt32(8); - - Log.OutF(Logs::General, Logs::Headless_Client, "Logged in successfully with dbid {0} and key {1}", m_dbid, m_key); - LoginSendServerRequest(); - } -} - -void EverQuest::LoginProcessServerPacketList(const EQ::Net::Packet & p) -{ - m_world_servers.clear(); - auto number_of_servers = p.GetUInt32(18); - size_t idx = 22; - - for (auto i = 0U; i < number_of_servers; ++i) { - WorldServer ws; - ws.address = p.GetCString(idx); - idx += (ws.address.length() + 1); - - ws.type = p.GetInt32(idx); - idx += 4; - - auto id = p.GetUInt32(idx); - idx += 4; - - ws.long_name = p.GetCString(idx); - idx += (ws.long_name.length() + 1); - - ws.lang = p.GetCString(idx); - idx += (ws.lang.length() + 1); - - ws.region = p.GetCString(idx); - idx += (ws.region.length() + 1); - - ws.status = p.GetInt32(idx); - idx += 4; - - ws.players = p.GetInt32(idx); - idx += 4; - - m_world_servers[id] = ws; - } - - for (auto server : m_world_servers) { - if (server.second.long_name.compare(m_server) == 0) { - Log.OutF(Logs::General, Logs::Headless_Client, "Found world server {0}, attempting to login.", m_server); - LoginSendPlayRequest(server.first); - return; - } - } - - Log.OutF(Logs::General, Logs::Headless_Client, "Got response from login server but could not find world server {0} disconnecting.", m_server); - LoginDisableReconnect(); -} - -void EverQuest::LoginProcessServerPlayResponse(const EQ::Net::Packet &p) -{ - auto allowed = p.GetUInt8(12); - - if (allowed) { - auto server = p.GetUInt32(18); - auto ws = m_world_servers.find(server); - if (ws != m_world_servers.end()) { - ConnectToWorld(); - LoginDisableReconnect(); - } - } - else { - auto message = p.GetUInt16(13); - Log.OutF(Logs::General, Logs::Headless_Client, "Failed to login to server with message {0}"); - LoginDisableReconnect(); - } -} - -void EverQuest::LoginDisableReconnect() -{ - m_login_connection_manager->OnConnectionStateChange(std::bind(&EverQuest::LoginOnStatusChangeReconnectDisabled, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - m_login_connection->Close(); -} - -void EverQuest::ConnectToWorld() -{ - m_world_connection_manager.reset(new EQ::Net::ReliableStreamConnectionManager()); - m_world_connection_manager->OnNewConnection(std::bind(&EverQuest::WorldOnNewConnection, this, std::placeholders::_1)); - m_world_connection_manager->OnConnectionStateChange(std::bind(&EverQuest::WorldOnStatusChangeReconnectEnabled, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - m_world_connection_manager->OnPacketRecv(std::bind(&EverQuest::WorldOnPacketRecv, this, std::placeholders::_1, std::placeholders::_2)); - m_world_connection_manager->Connect(m_host, 9000); -} - -void EverQuest::WorldOnNewConnection(std::shared_ptr connection) -{ - m_world_connection = connection; - Log.OutF(Logs::General, Logs::Headless_Client, "Connecting to world..."); -} - -void EverQuest::WorldOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) -{ - if (to == EQ::Net::StatusConnected) { - Log.OutF(Logs::General, Logs::Headless_Client, "World connected."); - WorldSendClientAuth(); - } - - if (to == EQ::Net::StatusDisconnected) { - Log.OutF(Logs::General, Logs::Headless_Client, "World connection lost, reconnecting."); - m_world_connection.reset(); - m_world_connection_manager->Connect(m_host, 9000); - } -} - -void EverQuest::WorldOnStatusChangeReconnectDisabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) -{ - if (to == EQ::Net::StatusDisconnected) { - m_world_connection.reset(); - } -} - -void EverQuest::WorldOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet & p) -{ - auto opcode = p.GetUInt16(0); - switch (opcode) { - case 0x00d2: - WorldProcessCharacterSelect(p); - break; - default: - Log.OutF(Logs::General, Logs::Headless_Client, "Unhandled opcode: {0:#x}", opcode); - break; - } -} - -void EverQuest::WorldSendClientAuth() -{ - EQ::Net::DynamicPacket p; - p.Resize(2 + 464); - - p.PutUInt16(0, 0x7a09U); - std::string dbid_str = std::to_string(m_dbid); - - p.PutCString(2, dbid_str.c_str()); - p.PutCString(2 + dbid_str.length() + 1, m_key.c_str()); - - m_world_connection->QueuePacket(p); -} - -void EverQuest::WorldSendEnterWorld(const std::string &character) -{ - EQ::Net::DynamicPacket p; - p.PutUInt16(0, 0x578f); - p.PutString(2, character); - p.PutUInt32(66, 0); - p.PutUInt32(70, 0); - - m_world_connection->QueuePacket(p); -} - -void EverQuest::WorldProcessCharacterSelect(const EQ::Net::Packet &p) -{ - auto char_count = p.GetUInt32(2); - size_t idx = 6; - - //Log.OutF(Logs::General, Logs::Headless_Client, "{0} characters", char_count); - for (uint32_t i = 0; i < char_count; ++i) { - auto name = p.GetCString(idx); - idx += name.length() + 1; - - auto pclass = p.GetUInt8(idx); - auto prace = p.GetUInt32(idx + 1); - auto plevel = p.GetUInt8(idx + 5); - - idx += 274; - if (m_character.compare(name) == 0) { - Log.OutF(Logs::General, Logs::Headless_Client, "Found {0}, would attempt to login here.", m_character); - WorldSendEnterWorld(m_character); - return; - } - } - - Log.OutF(Logs::General, Logs::Headless_Client, "Could not find {0}, cannot continue to login.", m_character); -} - \ No newline at end of file diff --git a/hc/eq.h b/hc/eq.h deleted file mode 100644 index 63467b3185..0000000000 --- a/hc/eq.h +++ /dev/null @@ -1,74 +0,0 @@ -#pragma once - -#include "../common/eqemu_logsys.h" -#include "../common/net/reliable_stream_connection.h" -#include "../common/event/timer.h" -#include -#include -#include - -struct WorldServer -{ - std::string long_name; - std::string address; - int type; - std::string lang; - std::string region; - int status; - int players; -}; - -class EverQuest -{ -public: - EverQuest(const std::string &host, int port, const std::string &user, const std::string &pass, const std::string &server, const std::string &character); - ~EverQuest(); - -private: - //Login - void LoginOnNewConnection(std::shared_ptr connection); - void LoginOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void LoginOnStatusChangeReconnectDisabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void LoginOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p); - - void LoginSendSessionReady(); - void LoginSendLogin(); - void LoginSendServerRequest(); - void LoginSendPlayRequest(uint32_t id); - void LoginProcessLoginResponse(const EQ::Net::Packet &p); - void LoginProcessServerPacketList(const EQ::Net::Packet &p); - void LoginProcessServerPlayResponse(const EQ::Net::Packet &p); - - void LoginDisableReconnect(); - - std::unique_ptr m_login_connection_manager; - std::shared_ptr m_login_connection; - std::map m_world_servers; - - //World - void ConnectToWorld(); - - void WorldOnNewConnection(std::shared_ptr connection); - void WorldOnStatusChangeReconnectEnabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void WorldOnStatusChangeReconnectDisabled(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void WorldOnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p); - - void WorldSendClientAuth(); - void WorldSendEnterWorld(const std::string &character); - - void WorldProcessCharacterSelect(const EQ::Net::Packet &p); - - std::unique_ptr m_world_connection_manager; - std::shared_ptr m_world_connection; - - //Variables - std::string m_host; - int m_port; - std::string m_user; - std::string m_pass; - std::string m_server; - std::string m_character; - - std::string m_key; - uint32_t m_dbid; -}; \ No newline at end of file diff --git a/hc/login.cpp b/hc/login.cpp deleted file mode 100644 index f6dca7c780..0000000000 --- a/hc/login.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/*#include "login.h" -#include "../common/eqemu_logsys.h" -#include - -const char* eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char* buffer_out, bool enc) { - DES_key_schedule k; - DES_cblock v; - - memset(&k, 0, sizeof(DES_key_schedule)); - memset(&v, 0, sizeof(DES_cblock)); - - if (!enc && buffer_in_sz && buffer_in_sz % 8 != 0) { - return nullptr; - } - - DES_ncbc_encrypt((const unsigned char*)buffer_in, (unsigned char*)buffer_out, (long)buffer_in_sz, &k, &v, enc); - return buffer_out; -} - -LoginConnection::LoginConnection(const std::string &username, const std::string &password, const std::string &host, int host_port, const std::string &server) -{ - m_connecting = false; - m_username = username; - m_password = password; - m_host = host; - m_host_port = host_port; - m_server = server; - - m_connection_manager.reset(new EQ::Net::ReliableStreamConnectionManager()); - - m_connection_manager->OnNewConnection(std::bind(&LoginConnection::OnNewConnection, this, std::placeholders::_1)); - m_connection_manager->OnConnectionStateChange(std::bind(&LoginConnection::OnStatusChangeActive, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - m_connection_manager->OnPacketRecv(std::bind(&LoginConnection::OnPacketRecv, this, std::placeholders::_1, std::placeholders::_2)); - - m_connection_manager->Connect(host, host_port); -} - -LoginConnection::~LoginConnection() -{ -} - -void LoginConnection::OnNewConnection(std::shared_ptr connection) -{ - m_connection = connection; - Log.OutF(Logs::General, Logs::Headless_Client, "Connecting..."); -} - -void LoginConnection::OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) -{ - if (to == EQ::Net::StatusConnected) { - Log.OutF(Logs::General, Logs::Headless_Client, "Login connected."); - SendSessionReady(); - } - - if (to == EQ::Net::StatusDisconnected) { - Log.OutF(Logs::General, Logs::Headless_Client, "Login connection lost, reconnecting."); - m_key.clear(); - m_dbid = 0; - m_connection.reset(); - m_connection_manager->Connect(m_host, m_host_port); - } -} - -void LoginConnection::OnStatusChangeInactive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) -{ - if (to == EQ::Net::StatusDisconnected) { - m_key.clear(); - m_dbid = 0; - m_connection.reset(); - } -} - -void LoginConnection::OnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p) -{ - auto opcode = p.GetUInt16(0); - switch (opcode) { - case 0x0017: //OP_ChatMessage - SendLogin(); - break; - case 0x0018: - ProcessLoginResponse(p); - break; - case 0x0019: - ProcessServerPacketList(p); - break; - case 0x0022: - ProcessServerPlayResponse(p); - break; - } -} - -void LoginConnection::Kill() -{ - m_connection_manager->OnConnectionStateChange(std::bind(&LoginConnection::OnStatusChangeInactive, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - m_key.clear(); - m_dbid = 0; - m_connection->Close(); -} - -void LoginConnection::Start() -{ - m_connection_manager->OnConnectionStateChange(std::bind(&LoginConnection::OnStatusChangeActive, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - m_connection_manager->Connect(m_host, m_host_port); -} - -void LoginConnection::SendSessionReady() -{ - EQ::Net::DynamicPacket p; - p.PutUInt16(0, 1); //OP_SessionReady - p.PutUInt32(2, 2); - - m_connection->QueuePacket(p); -} - -void LoginConnection::SendLogin() -{ - size_t buffer_len = m_username.length() + m_password.length() + 2; - std::unique_ptr buffer(new char[buffer_len]); - - strcpy(&buffer[0], m_username.c_str()); - strcpy(&buffer[m_username.length() + 1], m_password.c_str()); - - size_t encrypted_len = buffer_len; - - if (encrypted_len % 8 > 0) { - encrypted_len = ((encrypted_len / 8) + 1) * 8; - } - - EQ::Net::DynamicPacket p; - p.Resize(12 + encrypted_len); - p.PutUInt16(0, 2); //OP_Login - p.PutUInt32(2, 3); - - eqcrypt_block(&buffer[0], buffer_len, (char*)p.Data() + 12, true); - - m_connection->QueuePacket(p); -} - -void LoginConnection::SendServerRequest() -{ - EQ::Net::DynamicPacket p; - p.PutUInt16(0, 4); //OP_ServerListRequest - p.PutUInt32(2, 4); - - m_connection->QueuePacket(p); -} - -void LoginConnection::SendPlayRequest(uint32_t id) -{ - EQ::Net::DynamicPacket p; - p.PutUInt16(0, 0x000d); - p.PutUInt16(2, 5); - p.PutUInt32(4, 0); - p.PutUInt32(8, 0); - p.PutUInt32(12, id); - - m_connection->QueuePacket(p); -} - -void LoginConnection::ProcessLoginResponse(const EQ::Net::Packet &p) -{ - auto encrypt_size = p.Length() - 12; - if (encrypt_size % 8 > 0) { - encrypt_size = (encrypt_size / 8) * 8; - } - - std::unique_ptr decrypted(new char[encrypt_size]); - - eqcrypt_block((char*)p.Data() + 12, encrypt_size, &decrypted[0], false); - - EQ::Net::StaticPacket sp(&decrypted[0], encrypt_size); - auto response_error = sp.GetUInt16(1); - - if (response_error > 101) { - Log.OutF(Logs::General, Logs::Headless_Client, "Error logging in response code: {0}", response_error); - Kill(); - } - else { - m_key = sp.GetCString(12); - m_dbid = sp.GetUInt32(8); - - Log.OutF(Logs::General, Logs::Headless_Client, "Logged in successfully with dbid {0} and key {1}", m_dbid, m_key); - SendServerRequest(); - } -} - -void LoginConnection::ProcessServerPacketList(const EQ::Net::Packet &p) -{ - m_world_servers.clear(); - auto number_of_servers = p.GetUInt32(18); - size_t idx = 22; - - for (auto i = 0U; i < number_of_servers; ++i) { - WorldServer ws; - ws.address = p.GetCString(idx); - idx += (ws.address.length() + 1); - - ws.type = p.GetInt32(idx); - idx += 4; - - auto id = p.GetUInt32(idx); - idx += 4; - - ws.long_name = p.GetCString(idx); - idx += (ws.long_name.length() + 1); - - ws.lang = p.GetCString(idx); - idx += (ws.lang.length() + 1); - - ws.region = p.GetCString(idx); - idx += (ws.region.length() + 1); - - ws.status = p.GetInt32(idx); - idx += 4; - - ws.players = p.GetInt32(idx); - idx += 4; - - m_world_servers[id] = ws; - } - - for (auto server : m_world_servers) { - if (server.second.long_name.compare(m_server) == 0) { - Log.OutF(Logs::General, Logs::Headless_Client, "Found world server {0}, attempting to login.", m_server); - SendPlayRequest(server.first); - return; - } - } - - Log.OutF(Logs::General, Logs::Headless_Client, "Got response from login server but could not find world server {0} disconnecting.", m_server); - Kill(); -} - -void LoginConnection::ProcessServerPlayResponse(const EQ::Net::Packet &p) -{ - auto allowed = p.GetUInt8(12); - - if (allowed) { - auto server = p.GetUInt32(18); - auto ws = m_world_servers.find(server); - if (ws != m_world_servers.end()) { - if (m_on_can_login_world) { - m_on_can_login_world(ws->second, m_key, m_dbid); - } - - Kill(); - } - } - else { - auto message = p.GetUInt16(13); - Log.OutF(Logs::General, Logs::Headless_Client, "Failed to login to server with message {0}"); - Kill(); - } -} -*/ \ No newline at end of file diff --git a/hc/login.h b/hc/login.h deleted file mode 100644 index bec7c3cdd9..0000000000 --- a/hc/login.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include "../common/net/reliable_stream_connection.h" -#include "../common/event/timer.h" -#include - -struct WorldServer -{ - std::string long_name; - std::string address; - int type; - std::string lang; - std::string region; - int status; - int players; -}; - -class LoginConnection -{ -public: - LoginConnection(const std::string &username, const std::string &password, const std::string &host, int host_port, const std::string &server); - void OnCanLoginToWorld(std::function cb) { m_on_can_login_world = cb; } - - ~LoginConnection(); -private: - void OnNewConnection(std::shared_ptr connection); - void OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void OnStatusChangeInactive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void OnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p); - void Kill(); - void Start(); - - void SendSessionReady(); - void SendLogin(); - void SendServerRequest(); - void SendPlayRequest(uint32_t id); - void ProcessLoginResponse(const EQ::Net::Packet &p); - void ProcessServerPacketList(const EQ::Net::Packet &p); - void ProcessServerPlayResponse(const EQ::Net::Packet &p); - - std::unique_ptr m_connection_manager; - std::shared_ptr m_connection; - bool m_connecting; - std::unique_ptr m_connect_timer; - - std::string m_username; - std::string m_password; - std::string m_host; - int m_host_port; - std::string m_server; - - std::string m_key; - uint32_t m_dbid; - std::map m_world_servers; - std::function m_on_can_login_world; -}; \ No newline at end of file diff --git a/hc/main.cpp b/hc/main.cpp deleted file mode 100644 index f461aa6665..0000000000 --- a/hc/main.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "../common/event/event_loop.h" -#include "../common/eqemu_logsys.h" -#include "../common/crash.h" -#include "../common/platform.h" -#include "../common/json_config.h" -#include - -#include "eq.h" - -EQEmuLogSys Log; - -int main() { - RegisterExecutablePlatform(ExePlatformHC); - Log.LoadLogSettingsDefaults(); - set_exception_handler(); - - Log.OutF(Logs::General, Logs::Headless_Client, "Starting EQEmu Headless Client."); - - auto config = EQ::JsonConfigFile::Load("hc.json"); - auto config_handle = config.RawHandle(); - - std::vector> eq_list; - - try { - for (int i = 0; i < config_handle.size(); ++i) { - auto c = config_handle[i]; - - auto host = c["host"].asString(); - auto port = c["port"].asInt(); - auto user = c["user"].asString(); - auto pass = c["pass"].asString(); - auto server = c["server"].asString(); - auto character = c["character"].asString(); - - Log.OutF(Logs::General, Logs::Headless_Client, "Connecting to {0}:{1} as Account '{2}' to Server '{3}' under Character '{4}'", host, port, user, server, character); - - eq_list.push_back(std::unique_ptr(new EverQuest(host, port, user, pass, server, character))); - } - } - catch (std::exception &ex) { - Log.OutF(Logs::General, Logs::Headless_Client, "Error parsing config file: {0}", ex.what()); - return 0; - } - - for (;;) { - EQ::EventLoop::Get().Process(); - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - - return 0; -} diff --git a/hc/world.cpp b/hc/world.cpp deleted file mode 100644 index c9d690f62b..0000000000 --- a/hc/world.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "world.h" -#include "../common/eqemu_logsys.h" - -WorldConnection::WorldConnection(const std::string &key, uint32_t dbid, const std::string &host) -{ - m_connecting = false; - m_host = host; - m_key = key; - m_dbid = dbid; - - m_connection_manager.reset(new EQ::Net::ReliableStreamConnectionManager()); - m_connection_manager->OnNewConnection(std::bind(&WorldConnection::OnNewConnection, this, std::placeholders::_1)); - m_connection_manager->OnConnectionStateChange(std::bind(&WorldConnection::OnStatusChangeActive, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - m_connection_manager->OnPacketRecv(std::bind(&WorldConnection::OnPacketRecv, this, std::placeholders::_1, std::placeholders::_2)); - m_connection_manager->Connect(host, 9000); -} - -WorldConnection::~WorldConnection() { -} - -void WorldConnection::OnNewConnection(std::shared_ptr connection) -{ - m_connection = connection; - Log.OutF(Logs::General, Logs::Headless_Client, "Connecting to world..."); -} - -void WorldConnection::OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) -{ - if (to == EQ::Net::StatusConnected) { - Log.OutF(Logs::General, Logs::Headless_Client, "World connected."); - SendClientAuth(); - } - - if (to == EQ::Net::StatusDisconnected) { - Log.OutF(Logs::General, Logs::Headless_Client, "World connection lost, reconnecting."); - m_connection.reset(); - m_connection_manager->Connect(m_host, 9000); - } -} - -void WorldConnection::OnStatusChangeInactive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to) -{ - if (to == EQ::Net::StatusDisconnected) { - m_connection.reset(); - } -} - -void WorldConnection::OnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p) -{ - auto opcode = p.GetUInt16(0); - Log.OutF(Logs::General, Logs::Headless_Client, "Packet in:\n{0}", p.ToString()); -} - -void WorldConnection::Kill() -{ - m_connection_manager->OnConnectionStateChange(std::bind(&WorldConnection::OnStatusChangeInactive, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - m_connection->Close(); -} - -void WorldConnection::Start() -{ - m_connection_manager->OnConnectionStateChange(std::bind(&WorldConnection::OnStatusChangeActive, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - m_connection_manager->Connect(m_host, 9000); -} - -void WorldConnection::SendClientAuth() -{ - EQ::Net::DynamicPacket p; - p.Resize(2 + 464); - - p.PutUInt16(0, 0x7a09U); - std::string dbid_str = std::to_string(m_dbid); - - p.PutCString(2, dbid_str.c_str()); - p.PutCString(2 + dbid_str.length() + 1, m_key.c_str()); - - m_connection->QueuePacket(p); -} diff --git a/hc/world.h b/hc/world.h deleted file mode 100644 index b1df83894f..0000000000 --- a/hc/world.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "../common/net/reliable_stream_connection.h" -#include "../common/event/timer.h" -#include - -class WorldConnection -{ -public: - WorldConnection(const std::string &key, uint32_t dbid, const std::string &host); - ~WorldConnection(); -private: - void OnNewConnection(std::shared_ptr connection); - void OnStatusChangeActive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void OnStatusChangeInactive(std::shared_ptr conn, EQ::Net::DbProtocolStatus from, EQ::Net::DbProtocolStatus to); - void OnPacketRecv(std::shared_ptr conn, const EQ::Net::Packet &p); - void Kill(); - void Start(); - - void SendClientAuth(); - - std::unique_ptr m_connection_manager; - std::shared_ptr m_connection; - bool m_connecting; - std::unique_ptr m_connect_timer; - - std::string m_host; - - std::string m_key; - uint32_t m_dbid; -}; \ No newline at end of file diff --git a/hc/zone.cpp b/hc/zone.cpp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/hc/zone.h b/hc/zone.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index d5b325aeca..802a6327d3 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -1,7 +1,7 @@ -IF(EQEMU_BUILD_LUA) - ADD_SUBDIRECTORY(luabind) -ENDIF(EQEMU_BUILD_LUA) +if(EQEMU_BUILD_LUA) + add_subdirectory(luabind) +endif() -IF(EQEMU_BUILD_PERL) - ADD_SUBDIRECTORY(perlbind) -ENDIF(EQEMU_BUILD_PERL) +if(EQEMU_BUILD_PERL) + add_subdirectory(perlbind) +endif() diff --git a/libs/luabind/CMakeLists.txt b/libs/luabind/CMakeLists.txt index 74d95ee702..ef93f9a03a 100644 --- a/libs/luabind/CMakeLists.txt +++ b/libs/luabind/CMakeLists.txt @@ -1,6 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.12) +cmake_minimum_required(VERSION 3.20.0) -SET(lb_sources +set(lb_sources src/class.cpp src/class_info.cpp src/class_registry.cpp @@ -20,19 +20,16 @@ SET(lb_sources src/wrapper_base.cpp ) -SET(lb_headers +add_library(luabind ${lb_sources}) +target_include_directories(luabind PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${LUAJIT_INCLUDE_DIR}) +target_link_libraries(luabind PUBLIC Boost::dynamic_bitset Boost::tuple Boost::foreach ${LUAJIT_LIBRARY}) -) - -ADD_LIBRARY(luabind ${lb_sources} ${lb_headers}) - - -IF(UNIX) +if(UNIX) set_source_files_properties(${lb_sources} PROPERTY COMPILE_FLAGS -Wno-deprecated-declarations) -ENDIF(UNIX) +endif() -IF(MSVC) +if(MSVC) set_source_files_properties(${lb_sources} PROPERTY COMPILE_FLAGS " /W0 " ) -ENDIF(MSVC) +endif() -SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/libs/perlbind/CMakeLists.txt b/libs/perlbind/CMakeLists.txt index c03dd8e3a1..dcbcdb9f8b 100644 --- a/libs/perlbind/CMakeLists.txt +++ b/libs/perlbind/CMakeLists.txt @@ -1,11 +1,7 @@ -cmake_minimum_required(VERSION 3.7) +cmake_minimum_required(VERSION 3.20.0) project(perlbind LANGUAGES CXX) -set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".so" ".a") - -find_package(PerlLibs) - set(PERLBIND_HEADERS include/perlbind/array.h include/perlbind/forward.h diff --git a/libs/zlibng/.gitattributes b/libs/zlibng/.gitattributes deleted file mode 100644 index 68ec3a174e..0000000000 --- a/libs/zlibng/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -* text=auto -*.c text -*.h text -Makefile text diff --git a/libs/zlibng/.github/workflows/analyze.yml b/libs/zlibng/.github/workflows/analyze.yml deleted file mode 100644 index 7c848ef025..0000000000 --- a/libs/zlibng/.github/workflows/analyze.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: CI Static Analysis -on: [push, pull_request] -jobs: - GCC-10: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Install packages (Ubuntu) - run: | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - sudo apt-get install -y gcc-10 - - name: Generate project files - run: | - cmake . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DWITH_FUZZERS=OFF -DWITH_CODE_COVERAGE=OFF -DWITH_MAINTAINER_WARNINGS=OFF - env: - CC: gcc-10 - CFLAGS: "-fanalyzer -Werror -Wanalyzer-double-fclose -Wanalyzer-double-free -Wanalyzer-exposure-through-output-file -Wanalyzer-file-leak -Wanalyzer-free-of-non-heap -Wanalyzer-malloc-leak -Wanalyzer-null-argument -Wanalyzer-null-dereference -Wanalyzer-possible-null-argument -Wanalyzer-possible-null-dereference -Wanalyzer-stale-setjmp-buffer -Wanalyzer-tainted-array-index -Wanalyzer-unsafe-call-within-signal-handler -Wanalyzer-use-after-free -Wanalyzer-use-of-pointer-in-stale-stack-frame" - CI: true - - name: Compile source code - run: | - cmake --build . --config Release > /dev/null - Clang-12: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Install packages (Ubuntu) - run: | - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - - sudo apt-add-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main" -y - sudo apt install clang-tools-12 -y - - name: Generate project files - run: | - scan-build-12 --status-bugs cmake . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DWITH_FUZZERS=OFF -DWITH_CODE_COVERAGE=OFF -DWITH_MAINTAINER_WARNINGS=OFF - env: - CI: true - - name: Compile source code - run: | - scan-build-12 --status-bugs cmake --build . --config Release > /dev/null diff --git a/libs/zlibng/.github/workflows/cmake.yml b/libs/zlibng/.github/workflows/cmake.yml deleted file mode 100644 index 4eaec6c4bf..0000000000 --- a/libs/zlibng/.github/workflows/cmake.yml +++ /dev/null @@ -1,381 +0,0 @@ -name: CI CMake -on: [push, pull_request] -jobs: - ci-cmake: - name: ${{ matrix.name }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - name: Ubuntu GCC - os: ubuntu-latest - compiler: gcc - cmake-args: -DWITH_SANITIZER=Address - codecov: ubuntu_gcc - - - name: Ubuntu GCC OSB -O1 No Unaligned64 - os: ubuntu-latest - compiler: gcc - cmake-args: -DWITH_UNALIGNED=ON -DUNALIGNED64_OK=OFF -DWITH_SANITIZER=Undefined - build-dir: ../build - build-src-dir: ../zlib-ng - codecov: ubuntu_gcc_osb - cflags: -O1 -g3 - - - name: Ubuntu GCC -O3 No Unaligned - os: ubuntu-latest - compiler: gcc - cmake-args: -DWITH_UNALIGNED=OFF - codecov: ubuntu_gcc_o3 - cflags: -O3 - - - name: Ubuntu GCC Link Zlib - os: ubuntu-latest - compiler: gcc - cmake-args: -DZLIB_DUAL_LINK=ON - - - name: Ubuntu GCC No AVX2 - os: ubuntu-latest - compiler: gcc - cmake-args: -DWITH_AVX2=OFF -DWITH_SANITIZER=Undefined - codecov: ubuntu_gcc_no_avx2 - - - name: Ubuntu GCC No SSE2 - os: ubuntu-latest - compiler: gcc - cmake-args: -DWITH_SSE2=OFF -DWITH_SANITIZER=Undefined - codecov: ubuntu_gcc_no_sse2 - - - name: Ubuntu GCC No SSE4 - os: ubuntu-latest - compiler: gcc - cmake-args: -DWITH_SSE4=OFF -DWITH_SANITIZER=Undefined - codecov: ubuntu_gcc_no_sse4 - - - name: Ubuntu GCC No PCLMULQDQ - os: ubuntu-latest - compiler: gcc - cmake-args: -DWITH_PCLMULQDQ=OFF -DWITH_SANITIZER=Undefined - codecov: ubuntu_gcc_no_pclmulqdq - - - name: Ubuntu GCC Compat No Opt - os: ubuntu-latest - compiler: gcc - cmake-args: -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Address - codecov: ubuntu_gcc_compat_no_opt - cflags: -DNOT_TWEAK_COMPILER - - - name: Ubuntu GCC ARM SF - os: ubuntu-latest - compiler: arm-linux-gnueabi-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi -DWITH_SANITIZER=Address - packages: qemu gcc-arm-linux-gnueabi libc-dev-armel-cross - codecov: ubuntu_gcc_armsf - - - name: Ubuntu GCC ARM SF Compat No Opt - os: ubuntu-latest - compiler: arm-linux-gnueabi-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined - packages: qemu gcc-arm-linux-gnueabi libc-dev-armel-cross - codecov: ubuntu_gcc_armsf_compat_no_opt - - - name: Ubuntu GCC ARM HF - os: ubuntu-latest - compiler: arm-linux-gnueabihf-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DWITH_SANITIZER=Address - packages: qemu gcc-arm-linux-gnueabihf libc-dev-armel-cross - codecov: ubuntu_gcc_armhf - - - name: Ubuntu GCC ARM HF No ACLE - os: ubuntu-latest - compiler: arm-linux-gnueabihf-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DWITH_ACLE=OFF -DWITH_SANITIZER=Address - packages: qemu gcc-arm-linux-gnueabihf libc-dev-armel-cross - codecov: ubuntu_gcc_armhf_no_acle - - - name: Ubuntu GCC ARM HF No NEON - os: ubuntu-latest - compiler: arm-linux-gnueabihf-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DWITH_NEON=OFF -DWITH_SANITIZER=Address - packages: qemu gcc-arm-linux-gnueabihf libc-dev-armel-cross - codecov: ubuntu_gcc_armhf_no_neon - - - name: Ubuntu GCC ARM HF Compat No Opt - os: ubuntu-latest - compiler: arm-linux-gnueabihf-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined - packages: qemu gcc-arm-linux-gnueabihf libc-dev-armel-cross - codecov: ubuntu_gcc_armhf_compat_no_opt - - - name: Ubuntu GCC AARCH64 - os: ubuntu-latest - compiler: aarch64-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_SANITIZER=Address - asan-options: detect_leaks=0 - packages: qemu gcc-aarch64-linux-gnu libc-dev-arm64-cross - codecov: ubuntu_gcc_aarch64 - - - name: Ubuntu GCC AARCH64 No ACLE - os: ubuntu-latest - compiler: aarch64-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_ACLE=OFF -DWITH_SANITIZER=Undefined - asan-options: detect_leaks=0 - packages: qemu gcc-aarch64-linux-gnu libc-dev-arm64-cross - codecov: ubuntu_gcc_aarch64_no_acle - - - name: Ubuntu GCC AARCH64 No NEON - os: ubuntu-latest - compiler: aarch64-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_NEON=OFF -DWITH_SANITIZER=Undefined - asan-options: detect_leaks=0 - packages: qemu gcc-aarch64-linux-gnu libc-dev-arm64-cross - codecov: ubuntu_gcc_aarch64_no_neon - - - name: Ubuntu GCC AARCH64 Compat No Opt - os: ubuntu-latest - compiler: aarch64-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined - asan-options: detect_leaks=0 - packages: qemu gcc-aarch64-linux-gnu libc-dev-arm64-cross - codecov: ubuntu_gcc_aarch64_compat_no_opt - - - name: Ubuntu GCC PPC - os: ubuntu-latest - compiler: powerpc-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake - packages: qemu gcc-powerpc-linux-gnu libc-dev-powerpc-cross - ldflags: -static - codecov: ubuntu_gcc_ppc - - - name: Ubuntu GCC PPC64 - os: ubuntu-latest - compiler: powerpc64-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64.cmake - packages: qemu gcc-powerpc64-linux-gnu libc-dev-ppc64-cross - ldflags: -static - codecov: ubuntu_gcc_ppc64 - - - name: Ubuntu GCC PPC64LE - os: ubuntu-latest - compiler: powerpc64le-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le.cmake - packages: qemu gcc-powerpc64le-linux-gnu libc-dev-ppc64el-cross - codecov: ubuntu_gcc_ppc64le - - - name: Ubuntu GCC SPARC64 - os: ubuntu-latest - compiler: sparc64-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-sparc64.cmake - packages: qemu gcc-sparc64-linux-gnu libc-dev-sparc64-cross - ldflags: -static - codecov: ubuntu_gcc_sparc64 - - - name: Ubuntu GCC S390X - os: ubuntu-latest - compiler: s390x-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_SANITIZER=Address - packages: qemu gcc-s390x-linux-gnu libc-dev-s390x-cross - ldflags: -static - codecov: ubuntu_gcc_s390x - - - name: Ubuntu GCC S390X DFLTCC - os: ubuntu-latest - compiler: s390x-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Address - packages: qemu gcc-s390x-linux-gnu libc-dev-s390x-cross - ldflags: -static - codecov: ubuntu_gcc_s390x - - - name: Ubuntu GCC S390X DFLTCC Compat - os: ubuntu-latest - compiler: s390x-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DZLIB_COMPAT=ON -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Undefined - packages: qemu gcc-s390x-linux-gnu libc-dev-s390x-cross - ldflags: -static - codecov: ubuntu_gcc_s390x - - - name: Ubuntu MinGW i686 - os: ubuntu-latest - compiler: i686-w64-mingw32-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-i686.cmake - packages: wine32 gcc-mingw-w64 - # Codecov disabled due to gcov locking issue error - - - name: Ubuntu MinGW x86_64 - os: ubuntu-latest - compiler: x86_64-w64-mingw32-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-x86_64.cmake - packages: wine-stable gcc-mingw-w64 - codecov: ubuntu_gcc_mingw_x86_64 - - - name: Ubuntu Clang - os: ubuntu-latest - compiler: clang - packages: llvm-6.0 - gcov-exec: llvm-cov-6.0 gcov - codecov: ubuntu_clang - - - name: Ubuntu Clang Inflate Strict - os: ubuntu-latest - compiler: clang - cmake-args: -DWITH_INFLATE_STRICT=ON - packages: llvm-6.0 - gcov-exec: llvm-cov-6.0 gcov - codecov: ubuntu_clang_inflate_strict - - - name: Ubuntu Clang Inflate Allow Invalid Dist - os: ubuntu-latest - compiler: clang - cmake-args: -DWITH_INFLATE_ALLOW_INVALID_DIST=ON - packages: llvm-6.0 - gcov-exec: llvm-cov-6.0 gcov - codecov: ubuntu_clang_inflate_allow_invalid_dist - - - name: Ubuntu Clang Memory Map - os: ubuntu-latest - compiler: clang - cflags: -DUSE_MMAP - packages: llvm-6.0 - gcov-exec: llvm-cov-6.0 gcov - codecov: ubuntu_clang_mmap - - - name: Ubuntu Clang Debug - os: ubuntu-latest - compiler: clang - packages: llvm-6.0 - gcov-exec: llvm-cov-6.0 gcov - codecov: ubuntu_clang_debug - build-config: Debug - - - name: Ubuntu Clang MSAN - os: ubuntu-latest - compiler: clang - cmake-args: -GNinja -DWITH_SANITIZER=Memory - packages: ninja-build llvm-6.0 - gcov-exec: llvm-cov-6.0 gcov - cflags: -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-memory-track-origins - codecov: ubuntu_clang_msan - - - name: Windows MSVC Win32 - os: windows-latest - compiler: cl - cmake-args: -A Win32 - - - name: Windows MSVC Win64 - os: windows-latest - compiler: cl - cmake-args: -A x64 - - - name: Windows MSVC ARM No Test - os: windows-latest - compiler: cl - cmake-args: -A ARM - - - name: Windows MSVC ARM64 No Test - os: windows-latest - compiler: cl - cmake-args: -A ARM64 - - - name: Windows GCC - os: windows-latest - compiler: gcc - cmake-args: -G Ninja - codecov: win64_gcc - - - name: Windows GCC Compat No Opt - os: windows-latest - compiler: gcc - cmake-args: -G Ninja -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF - codecov: win64_gcc_compat_no_opt - - - name: macOS Clang - os: macos-latest - compiler: clang - cmake-args: -DWITH_SANITIZER=Address - codecov: macos_clang - - - name: macOS GCC - os: macos-latest - compiler: gcc-10 - cmake-args: -DWITH_SANITIZER=Undefined - packages: gcc@10 - gcov-exec: gcov-10 - codecov: macos_gcc - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Checkout test corpora - uses: actions/checkout@v2 - with: - repository: nmoinvaz/corpora - path: test/data/corpora - - - name: Install packages (Ubuntu) - if: runner.os == 'Linux' && matrix.packages - run: | - sudo dpkg --add-architecture i386 # Required for wine32 - sudo apt-get update - sudo apt-get install -y ${{ matrix.packages }} - - - name: Install packages (Windows) - if: runner.os == 'Windows' - run: | - choco install ninja ${{ matrix.packages }} --no-progress - - - name: Install packages (macOS) - if: runner.os == 'macOS' - run: | - brew install ninja ${{ matrix.packages }} - env: - HOMEBREW_NO_INSTALL_CLEANUP: 1 - - - name: Install codecov.io tools - if: matrix.codecov - run: | - python -u -m pip install codecov - - - name: Generate project files - # Shared libaries turned off for qemu ppc* and sparc & reduce code coverage sources - run: | - mkdir ${{ matrix.build-dir || '.not-used' }} - cd ${{ matrix.build-dir || '.' }} - cmake ${{ matrix.build-src-dir || '.' }} ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=${{ matrix.build-config || 'Release' }} -DBUILD_SHARED_LIBS=OFF -DWITH_FUZZERS=ON -DWITH_CODE_COVERAGE=ON -DWITH_MAINTAINER_WARNINGS=ON - env: - CC: ${{ matrix.compiler }} - CFLAGS: ${{ matrix.cflags }} - LDFLAGS: ${{ matrix.ldflags }} - CI: true - - - name: Compile source code - run: | - cd ${{ matrix.build-dir || '.' }} - cmake --build . --config ${{ matrix.build-config || 'Release' }} - - - name: Run test cases - # Don't run tests on Windows ARM - if: runner.os != 'Windows' || contains(matrix.name, 'ARM') == false - run: | - cd ${{ matrix.build-dir || '.' }} - ctest --verbose -C Release --output-on-failure --max-width 120 -j 6 - env: - ASAN_OPTIONS: ${{ matrix.asan-options || 'verbosity=0' }}:abort_on_error=1 - MSAN_OPTIONS: ${{ matrix.msan-options || 'verbosity=0' }}:abort_on_error=1 - TSAN_OPTIONS: ${{ matrix.tsan-options || 'verbosity=0' }}:abort_on_error=1 - LSAN_OPTIONS: ${{ matrix.lsan-options || 'verbosity=0' }}:abort_on_error=1 - - - name: Upload coverage report - if: matrix.codecov && ( env.CODECOV_TOKEN_SECRET != '' || github.repository == 'zlib-ng/zlib-ng' ) - shell: bash - run: | - bash tools/codecov-upload.sh - env: - # Codecov does not yet support GitHub Actions - CODECOV_TOKEN_SECRET: "${{secrets.CODECOV_TOKEN}}" - CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN || 'e4fdf847-f541-4ab1-9d50-3d27e5913906' }}" - CODECOV_FLAGS: "${{ matrix.codecov }}" - CODECOV_NAME: "${{ matrix.name }}" - CODECOV_EXEC: "${{ matrix.gcov-exec || 'gcov' }}" - CODECOV_DIR: "${{ matrix.build-dir || '.' }}" diff --git a/libs/zlibng/.github/workflows/configure.yml b/libs/zlibng/.github/workflows/configure.yml deleted file mode 100644 index 750f30d713..0000000000 --- a/libs/zlibng/.github/workflows/configure.yml +++ /dev/null @@ -1,185 +0,0 @@ -name: CI Configure -on: [push, pull_request] -jobs: - ci-configure: - name: ${{ matrix.name }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - name: Ubuntu GCC - os: ubuntu-latest - compiler: gcc - configure-args: --warn - - - name: Ubuntu GCC OSB - os: ubuntu-latest - compiler: gcc - configure-args: --warn - build-dir: ../build - build-src-dir: ../zlib-ng - - - name: Ubuntu GCC Compat No Opt - os: ubuntu-latest - compiler: gcc - configure-args: --warn --zlib-compat --without-optimizations --without-new-strategies - - - name: Ubuntu GCC ARM SF - os: ubuntu-latest - compiler: arm-linux-gnueabi-gcc - configure-args: --warn - chost: arm-linux-gnueabi - packages: qemu gcc-arm-linux-gnueabi libc-dev-armel-cross - - - name: Ubuntu GCC ARM SF Compat No Opt - os: ubuntu-latest - compiler: arm-linux-gnueabi-gcc - configure-args: --warn --zlib-compat --without-optimizations --without-new-strategies - chost: arm-linux-gnueabi - packages: qemu gcc-arm-linux-gnueabi libc-dev-armel-cross - - - name: Ubuntu GCC ARM HF - os: ubuntu-latest - compiler: arm-linux-gnueabihf-gcc - configure-args: --warn - chost: arm-linux-gnueabihf - packages: qemu gcc-arm-linux-gnueabihf libc-dev-armel-cross - - - name: Ubuntu GCC ARM HF No ACLE - os: ubuntu-latest - compiler: arm-linux-gnueabihf-gcc - configure-args: --warn --without-acle - chost: arm-linux-gnueabihf - packages: qemu gcc-arm-linux-gnueabihf libc-dev-armel-cross - - - name: Ubuntu GCC ARM HF No NEON - os: ubuntu-latest - compiler: arm-linux-gnueabihf-gcc - configure-args: --warn --without-neon - chost: arm-linux-gnueabihf - packages: qemu gcc-arm-linux-gnueabihf libc-dev-armel-cross - - - name: Ubuntu GCC ARM HF Compat No Opt - os: ubuntu-latest - compiler: arm-linux-gnueabihf-gcc - configure-args: --warn --zlib-compat --without-optimizations --without-new-strategies - chost: arm-linux-gnueabihf - packages: qemu gcc-arm-linux-gnueabihf libc-dev-armel-cross - - - name: Ubuntu GCC AARCH64 - os: ubuntu-latest - compiler: aarch64-linux-gnu-gcc - configure-args: --warn - chost: aarch64-linux-gnu - packages: qemu gcc-aarch64-linux-gnu libc-dev-arm64-cross - - - name: Ubuntu GCC AARCH64 No ACLE - os: ubuntu-latest - compiler: aarch64-linux-gnu-gcc - configure-args: --warn --without-acle - chost: aarch64-linux-gnu - packages: qemu gcc-aarch64-linux-gnu libc-dev-arm64-cross - - - name: Ubuntu GCC AARCH64 No NEON - os: ubuntu-latest - compiler: aarch64-linux-gnu-gcc - configure-args: --warn --without-neon - chost: aarch64-linux-gnu - packages: qemu gcc-aarch64-linux-gnu libc-dev-arm64-cross - - - name: Ubuntu GCC AARCH64 Compat No Opt - os: ubuntu-latest - compiler: aarch64-linux-gnu-gcc - configure-args: --warn --zlib-compat --without-optimizations --without-new-strategies - chost: aarch64-linux-gnu - packages: qemu gcc-aarch64-linux-gnu libc-dev-arm64-cross - - - name: Ubuntu GCC PPC - os: ubuntu-latest - compiler: powerpc-linux-gnu-gcc - configure-args: --warn --static - chost: powerpc-linux-gnu - packages: qemu gcc-powerpc-linux-gnu libc-dev-powerpc-cross - cflags: -static - ldflags: -static - - - name: Ubuntu GCC PPC64 - os: ubuntu-latest - compiler: powerpc64-linux-gnu-gcc - configure-args: --warn --static - chost: powerpc-linux-gnu - packages: qemu gcc-powerpc64-linux-gnu libc-dev-ppc64-cross - cflags: -static - ldflags: -static - - - name: Ubuntu GCC PPC64LE - os: ubuntu-latest - compiler: powerpc64le-linux-gnu-gcc - configure-args: --warn - chost: powerpc64le-linux-gnu - packages: qemu gcc-powerpc64le-linux-gnu libc-dev-ppc64el-cross - - - name: Ubuntu GCC S390X - os: ubuntu-latest - compiler: s390x-linux-gnu-gcc - configure-args: --warn --static - chost: s390x-linux-gnu - packages: qemu gcc-s390x-linux-gnu libc-dev-s390x-cross - cflags: -static - ldflags: -static - - - name: Ubuntu GCC S390X DFLTCC - os: ubuntu-latest - compiler: s390x-linux-gnu-gcc - configure-args: --warn --static --with-dfltcc-deflate --with-dfltcc-inflate - chost: s390x-linux-gnu - packages: qemu gcc-s390x-linux-gnu libc-dev-s390x-cross - cflags: -static - ldflags: -static - - - name: Ubuntu GCC S390X DFLTCC Compat - os: ubuntu-latest - compiler: s390x-linux-gnu-gcc - configure-args: --warn --zlib-compat --static --with-dfltcc-deflate --with-dfltcc-inflate - chost: s390x-linux-gnu - packages: qemu gcc-s390x-linux-gnu libc-dev-s390x-cross - cflags: -static - ldflags: -static - - - name: macOS GCC - os: macOS-latest - compiler: gcc - configure-args: --warn - - steps: - - name: Checkout repository - uses: actions/checkout@v1 - - - name: Install packages (Ubuntu) - if: runner.os == 'Linux' && matrix.packages - run: | - sudo apt-get update - sudo apt-get install -y ${{ matrix.packages }} - - - name: Generate project files - run: | - mkdir ${{ matrix.build-dir || '.not-used' }} - cd ${{ matrix.build-dir || '.' }} - ${{ matrix.build-src-dir || '.' }}/configure ${{ matrix.configure-args }} - env: - CC: ${{ matrix.compiler }} - CFLAGS: ${{ matrix.cflags }} - LDFLAGS: ${{ matrix.ldflags }} - CHOST: ${{ matrix.chost }} - CI: true - - - name: Compile source code - run: | - cd ${{ matrix.build-dir || '.' }} - make -j2 - - - name: Run test cases - run: | - cd ${{ matrix.build-dir || '.' }} - make test diff --git a/libs/zlibng/.github/workflows/fuzz.yml b/libs/zlibng/.github/workflows/fuzz.yml deleted file mode 100644 index e7ddaea5b5..0000000000 --- a/libs/zlibng/.github/workflows/fuzz.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: CI Fuzz -on: [pull_request] -jobs: - Fuzzing: - runs-on: ubuntu-latest - steps: - - name: Build Fuzzers - uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master - with: - oss-fuzz-project-name: 'zlib-ng' - dry-run: false - - name: Run Fuzzers - uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master - with: - oss-fuzz-project-name: 'zlib-ng' - fuzz-seconds: 600 - dry-run: false - - name: Upload Crash - uses: actions/upload-artifact@v1 - if: failure() - with: - name: artifacts - path: ./out/artifacts diff --git a/libs/zlibng/.github/workflows/libpng.yml b/libs/zlibng/.github/workflows/libpng.yml deleted file mode 100644 index fe970dd155..0000000000 --- a/libs/zlibng/.github/workflows/libpng.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: CI Libpng -on: [pull_request] -jobs: - pngtest: - name: Ubuntu Clang - runs-on: ubuntu-latest - - steps: - - name: Checkout repository (zlib-ng) - uses: actions/checkout@v1 - - - name: Generate project files (zlib-ng) - run: | - cmake . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DZLIB_COMPAT=ON -DZLIB_ENABLE_TESTS=OFF - env: - CC: clang - CFLAGS: -fPIC - CI: true - - - name: Compile source code (zlib-ng) - run: | - cmake --build . --config Release - - - name: Checkout repository (libpng) - uses: actions/checkout@v2 - with: - repository: glennrp/libpng - path: libpng - - - name: Generate project files (libpng) - run: | - cd libpng - cmake . -DCMAKE_BUILD_TYPE=Release -DPNG_TESTS=ON -DPNG_STATIC=OFF -DZLIB_INCLUDE_DIR=.. -DZLIB_LIBRARY=$PWD/../libz.a - env: - CC: clang - CI: true - - - name: Compile source code (libpng) - run: | - cd libpng - cmake --build . --config Release - - - name: Run test cases (libpng) - run: | - cd libpng - ctest -C Release --output-on-failure --max-width 120 diff --git a/libs/zlibng/.github/workflows/nmake.yml b/libs/zlibng/.github/workflows/nmake.yml deleted file mode 100644 index 38c0b42ebf..0000000000 --- a/libs/zlibng/.github/workflows/nmake.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: CI NMake -on: [push, pull_request] -jobs: - ci-cmake: - name: ${{ matrix.name }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - name: Windows NMake x86 - os: windows-latest - makefile: win32/Makefile.msc - vc-vars: x86 - - - name: Windows NMake x64 - os: windows-latest - makefile: win32/Makefile.msc - vc-vars: x86_amd64 - - - name: Windows NMake ARM No Test - os: windows-latest - makefile: win32/Makefile.arm - vc-vars: x86_arm - - - name: Windows NMake ARM64 No Test - os: windows-latest - makefile: win32/Makefile.a64 - vc-vars: x86_arm64 - - steps: - - name: Checkout repository - uses: actions/checkout@v1 - - - name: Compile source code - shell: cmd - run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.vc-vars }} - nmake -f ${{ matrix.makefile }} - - - name: Run test cases - shell: cmd - # Don't run tests on Windows ARM - if: contains(matrix.vc-vars, 'arm') == false - run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.vc-vars }} - nmake -f ${{ matrix.makefile }} test - nmake -f ${{ matrix.makefile }} testdll diff --git a/libs/zlibng/.github/workflows/pkgcheck.yml b/libs/zlibng/.github/workflows/pkgcheck.yml deleted file mode 100644 index a34ad94f34..0000000000 --- a/libs/zlibng/.github/workflows/pkgcheck.yml +++ /dev/null @@ -1,121 +0,0 @@ -name: CI Pkgcheck -on: [push, pull_request] -jobs: - ci-pkgcheck: - name: ${{ matrix.name }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - name: Ubuntu GCC - os: ubuntu-latest - compiler: gcc - - - name: Ubuntu GCC -m32 - os: ubuntu-latest - compiler: gcc - packages: gcc-multilib - cmake-args: -DCMAKE_C_FLAGS=-m32 - cflags: -m32 - ldflags: -m32 - - - name: Ubuntu GCC ARM HF - os: ubuntu-latest - chost: arm-linux-gnueabihf - compiler: arm-linux-gnueabihf-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf - packages: qemu gcc-arm-linux-gnueabihf libc6-dev-armhf-cross - - - name: Ubuntu GCC AARCH64 - os: ubuntu-latest - chost: aarch64-linux-gnu - compiler: aarch64-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake - packages: qemu gcc-aarch64-linux-gnu libc6-dev-arm64-cross - - - name: Ubuntu GCC PPC - os: ubuntu-latest - chost: powerpc-linux-gnu - compiler: powerpc-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake - packages: qemu gcc-powerpc-linux-gnu libc6-dev-powerpc-cross - - - name: Ubuntu GCC PPC64LE - os: ubuntu-latest - chost: powerpc64le-linux-gnu - compiler: powerpc64le-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le.cmake - packages: qemu gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross - - - name: macOS Clang - os: macOS-latest - compiler: clang - - steps: - - name: Checkout repository - uses: actions/checkout@v1 - - - name: Install packages (Ubuntu) - if: runner.os == 'Linux' - run: | - sudo apt-get update - sudo apt-get install -y --no-install-recommends abigail-tools ninja-build diffoscope ${{ matrix.packages }} - - - name: Install packages (macOS) - if: runner.os == 'macOS' - run: | - brew install ninja diffoscope ${{ matrix.packages }} - env: - HOMEBREW_NO_INSTALL_CLEANUP: 1 - - - name: Select Xcode version (macOS) - # Use a version of Xcode that supports ZERO_AR_DATE until CMake supports - # AppleClang linking with libtool using -D argument - # https://gitlab.kitware.com/cmake/cmake/-/issues/19852 - if: runner.os == 'macOS' - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: '12.1.1' - - - name: Compare builds - run: | - sh test/pkgcheck.sh - env: - CC: ${{ matrix.compiler }} - CFLAGS: ${{ matrix.cflags }} - CHOST: ${{ matrix.chost }} - CMAKE_ARGS: ${{ matrix.cmake-args }} - LDFLAGS: ${{ matrix.ldflags }} - - - name: Compare builds (compat) - run: | - sh test/pkgcheck.sh --zlib-compat - env: - CC: ${{ matrix.compiler }} - CFLAGS: ${{ matrix.cflags }} - CHOST: ${{ matrix.chost }} - CMAKE_ARGS: ${{ matrix.cmake-args }} - LDFLAGS: ${{ matrix.ldflags }} - - - name: Check ABI - # macOS runner does not contain abigail - if: runner.os != 'macOS' - run: | - sh test/abicheck.sh --refresh_if - env: - CC: ${{ matrix.compiler }} - CFLAGS: ${{ matrix.cflags }} - CHOST: ${{ matrix.chost }} - LDFLAGS: ${{ matrix.ldflags }} - - - name: Check ABI (compat) - # macOS runner does not contain abigail - if: runner.os != 'macOS' - run: | - sh test/abicheck.sh --zlib-compat --refresh_if - env: - CC: ${{ matrix.compiler }} - CFLAGS: ${{ matrix.cflags }} - CHOST: ${{ matrix.chost }} - LDFLAGS: ${{ matrix.ldflags }} diff --git a/libs/zlibng/.github/workflows/release.yml b/libs/zlibng/.github/workflows/release.yml deleted file mode 100644 index c2a306172c..0000000000 --- a/libs/zlibng/.github/workflows/release.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: CI Release -on: - push: - tags: - - '*' -jobs: - ci-cmake: - name: ${{ matrix.name }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - name: Windows MSVC Win32 - os: windows-latest - compiler: cl - cmake-args: -A Win32 - deploy-name: win32 - - - name: Windows MSVC Win32 Compat - os: windows-latest - compiler: cl - cmake-args: -A Win32 -DZLIB_COMPAT=ON - deploy-name: win32-compat - - - name: Windows MSVC Win64 - os: windows-latest - compiler: cl - cmake-args: -A x64 - deploy-name: win64 - - - name: Windows MSVC Win64 Compat - os: windows-latest - compiler: cl - cmake-args: -A x64 -DZLIB_COMPAT=ON - deploy-name: win64-compat - - steps: - - name: Checkout repository - uses: actions/checkout@v1 - - - name: Set environment variables - shell: bash - run: echo "tag=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV - - - name: Generate project files - run: | - cmake . ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=Release -DZLIB_ENABLE_TESTS=ON -DCMAKE_INSTALL_PREFIX=out -DINSTALL_UTILS=ON - env: - CC: ${{ matrix.compiler }} - CI: true - - - name: Compile source code - run: | - cmake --build . --config Release --target install - - - name: Package release (Windows) - if: runner.os == 'Windows' - run: | - cd out - 7z a -tzip ../zlib-ng-${{ matrix.deploy-name }}.zip bin include lib ../LICENSE.md ../README.md - - - name: Upload release (Windows) - uses: svenstaro/upload-release-action@v1-release - if: runner.os == 'Windows' - with: - asset_name: zlib-ng-${{ matrix.deploy-name }}.zip - file: zlib-ng-${{ matrix.deploy-name }}.zip - tag: ${{env.tag}} - repo_token: ${{ secrets.GITHUB_TOKEN }} - overwrite: true - env: - GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/libs/zlibng/.gitignore b/libs/zlibng/.gitignore deleted file mode 100644 index 23f9fd1590..0000000000 --- a/libs/zlibng/.gitignore +++ /dev/null @@ -1,86 +0,0 @@ -*.diff -*.patch -*.orig -*.rej - -*~ -*.a -*.lo -*.o -*.dylib - -*.gcda -*.gcno -*.gcov - -/adler32_test -/adler32_testsh -/example -/example64 -/examplesh -/libz.so* -/libz-ng.so* -/makefixed -/minigzip -/minigzip64 -/minigzipsh -/switchlevels -/zlib.pc -/zlib-ng.pc -/CVE-2003-0107 - -.DS_Store -*_fuzzer -*.obj -*.exe -*.pdb -*.exp -*.lib -*.dll -*.res -foo.gz -*.manifest -*.opensdf -*.sln -*.sdf -*.vcxproj -*.vcxproj.filters -.vs - -CMakeCache.txt -CMakeFiles -Testing -/*.cmake -*.stackdump -*._h -zconf.h -zconf.h.cmakein -zconf.h.included -zconf-ng.h -zconf-ng.h.cmakein -ztest* - -configure.log -a.out - -/Makefile -/arch/arm/Makefile -/arch/generic/Makefile -/arch/power/Makefile -/arch/x86/Makefile -.kdev4 -*.kdev4 - -/Debug -/example.dir -/minigzip.dir -/zlib.dir -/zlibstatic.dir -/win32/Debug -/build/ -/build[.-]*/ -/btmp[12]/ -/pkgtmp[12]/ - -/.idea -/cmake-build-debug diff --git a/libs/zlibng/.shellcheckrc b/libs/zlibng/.shellcheckrc deleted file mode 100644 index 89a1625ff5..0000000000 --- a/libs/zlibng/.shellcheckrc +++ /dev/null @@ -1 +0,0 @@ -disable=SC2140,SC2086,SC2046,SC2015,SC1097,SC1035,SC1036,SC1007,SC2154,SC2155,SC2000,SC2034,SC2016,SC1091,SC1090,SC2212,SC2143,SC2129,SC2102,SC2069,SC1041,SC1042,SC1044,SC1046,SC1119,SC1110,SC1111,SC1112,SC1102,SC1105,SC1101,SC1004,SC1003,SC1012,SC2068,SC2065,SC2064,SC2063,SC2059,SC2053,SC2048,SC2044,SC2032,SC2031,SC2030,SC2029,SC2025,SC2024,SC2022,SC2018,SC2019,SC2017,SC2014,SC2013,SC2012,SC2009,SC2001,SC2098,SC2096,SC2094,SC2091,SC2092,SC2088,SC2087,SC2076,SC2072,SC2071,SC2223,SC2221,SC2222,SC2217,SC2207,SC2206,SC2205,SC2190,SC2188,SC2187,SC2185,SC2179,SC2178,SC2174,SC2168,SC2167,SC2163,SC2161,SC2160,SC2153,SC2150,SC2148,SC2147,SC2146,SC2142,SC2139,SC2126,SC2123,SC2120,SC2119,SC2117,SC2114,SC1117,SC2164,SC1083,SC2004,SC2125,SC2128,SC2011,SC1008,SC1019,SC2093,SC1132,SC1129,SC2236,SC2237,SC2231,SC2230,SC2229,SC2106,SC2102,SC2243,SC2244,SC2245,SC2247,SC2248,SC2249,SC2250,SC2251,SC2252,SC2181 diff --git a/libs/zlibng/CMakeLists.txt b/libs/zlibng/CMakeLists.txt deleted file mode 100644 index 05087781e7..0000000000 --- a/libs/zlibng/CMakeLists.txt +++ /dev/null @@ -1,1285 +0,0 @@ -cmake_minimum_required(VERSION 3.5.1) -if(CMAKE_VERSION VERSION_LESS 3.12) - cmake_policy(VERSION ${CMAKE_VERSION}) -else() - cmake_policy(VERSION 3.5.1...3.13.2) -endif() -message(STATUS "Using CMake version ${CMAKE_VERSION}") - -set(CMAKE_MACOSX_RPATH 1) - -# If not specified on the command line, enable C99 as the default -# Configuration items that affect the global compiler envirionment standards -# should be issued before the "project" command. -if(NOT CMAKE_C_STANDARD) - set(CMAKE_C_STANDARD 99) # The C standard whose features are requested to build this target -endif() -if(NOT CMAKE_C_STANDARD_REQUIRED) - set(CMAKE_C_STANDARD_REQUIRED ON) # Boolean describing whether the value of C_STANDARD is a requirement -endif() -if(NOT CMAKE_C_EXTENSIONS) - set(CMAKE_C_EXTENSIONS OFF) # Boolean specifying whether compiler specific extensions are requested -endif() -set(VALID_C_STANDARDS "99" "11") -if(NOT CMAKE_C_STANDARD IN_LIST VALID_C_STANDARDS) - MESSAGE(FATAL_ERROR "CMAKE_C_STANDARD:STRING=${CMAKE_C_STANDARD} not in know standards list\n ${VALID_C_STANDARDS}") -endif() - -# Parse the full version number from zlib.h and include in ZLIB_FULL_VERSION -file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.h _zlib_h_contents) -string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([0-9]+.[0-9]+.[0-9]+).*\".*" - "\\1" ZLIB_HEADER_VERSION ${_zlib_h_contents}) -string(REGEX REPLACE ".*#define[ \t]+ZLIBNG_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" - "\\1" ZLIBNG_HEADER_VERSION ${_zlib_h_contents}) -message(STATUS "ZLIB_HEADER_VERSION: ${ZLIB_HEADER_VERSION}") -message(STATUS "ZLIBNG_HEADER_VERSION: ${ZLIBNG_HEADER_VERSION}") - -project(zlib VERSION ${ZLIB_HEADER_VERSION} LANGUAGES C) - -set(BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") -set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") -set(INC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") -set(MAN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") -set(PKGCONFIG_INSTALL_DIR "${LIB_INSTALL_DIR}/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") - -include(CheckTypeSize) -include(CheckSymbolExists) -include(CheckFunctionExists) -include(CheckIncludeFile) -include(CheckCSourceCompiles) -include(CheckCSourceRuns) -include(CMakeDependentOption) -include(FeatureSummary) - -include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/detect-arch.cmake) -include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/detect-sanitizer.cmake) - -if(CMAKE_TOOLCHAIN_FILE) - message(STATUS "Using CMake toolchain: ${CMAKE_TOOLCHAIN_FILE}") -endif() - -# Make sure we use an appropriate BUILD_TYPE by default, "Release" to be exact -# this should select the maximum generic optimisation on the current platform (i.e. -O3 for gcc/clang) -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release" CACHE STRING - "Choose the type of build, standard options are: Debug Release RelWithDebInfo MinSizeRel." - FORCE) - add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (default)") -else() - add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (selected)") -endif() - -# -# Options parsing -# -macro(add_option name description value) - option(${name} ${description} ${value}) - add_feature_info(${name} ${name} ${description}) -endmacro() - -add_option(WITH_GZFILEOP "Compile with support for gzFile related functions" ON) -add_option(ZLIB_COMPAT "Compile with zlib compatible API" OFF) -add_option(ZLIB_ENABLE_TESTS "Build test binaries" ON) -add_option(ZLIB_DUAL_LINK "Dual link tests against system zlib" OFF) -add_option(WITH_SANITIZER "Build with sanitizer (Memory, Address, Undefined)" OFF) -add_option(WITH_FUZZERS "Build test/fuzz" OFF) -add_option(WITH_OPTIM "Build with optimisation" ON) -add_option(WITH_NEW_STRATEGIES "Use new strategies" ON) -add_option(WITH_NATIVE_INSTRUCTIONS - "Instruct the compiler to use the full instruction set on this host (gcc/clang -march=native)" OFF) -add_option(WITH_MAINTAINER_WARNINGS "Build with project maintainer warnings" OFF) -add_option(WITH_CODE_COVERAGE "Enable code coverage reporting" OFF) -add_option(WITH_INFLATE_STRICT "Build with strict inflate distance checking" OFF) -add_option(WITH_INFLATE_ALLOW_INVALID_DIST "Build with zero fill for inflate invalid distances" OFF) -add_option(WITH_UNALIGNED "Support unaligned reads on platforms that support it" ON) - -if(BASEARCH_ARM_FOUND) - add_option(WITH_ACLE "Build with ACLE" ON) - add_option(WITH_NEON "Build with NEON intrinsics" ON) -elseif(BASEARCH_PPC_FOUND) - add_option(WITH_POWER8 "Build with optimisations for POWER8" ON) -elseif(BASEARCH_S360_FOUND) - add_option(WITH_DFLTCC_DEFLATE "Use DEFLATE CONVERSION CALL instruction for compression on IBM Z" OFF) - add_option(WITH_DFLTCC_INFLATE "Use DEFLATE CONVERSION CALL instruction for decompression on IBM Z" OFF) -elseif(BASEARCH_X86_FOUND) - add_option(WITH_AVX2 "Build with AVX2" ON) - add_option(WITH_SSE2 "Build with SSE2" ON) - add_option(WITH_SSSE3 "Build with SSSE3" ON) - add_option(WITH_SSE4 "Build with SSE4" ON) - add_option(WITH_PCLMULQDQ "Build with PCLMULQDQ" ON) -endif() -add_option(INSTALL_UTILS "Copy minigzip and minideflate during install" OFF) - -mark_as_advanced(FORCE - ZLIB_DUAL_LINK - WITH_ACLE WITH_NEON - WITH_DFLTCC_DEFLATE - WITH_DFLTCC_INFLATE - WITH_AVX2 WITH_SSE2 - WITH_SSSE3 WITH_SSE4 - WITH_PCLMULQDQ - WITH_POWER8 - WITH_INFLATE_STRICT - WITH_INFLATE_ALLOW_INVALID_DIST - WITH_UNALIGNED - INSTALL_UTILS - ) - -if(ZLIB_COMPAT) - add_definitions(-DZLIB_COMPAT) - set(WITH_GZFILEOP ON) - set(SUFFIX "-ng") -else() - set(SUFFIX "-ng") -endif() - -if(WITH_GZFILEOP) - add_definitions(-DWITH_GZFILEOP) -endif() - -if("${CMAKE_C_COMPILER}" MATCHES "icc" OR "${CMAKE_C_COMPILER}" MATCHES "icpc" OR "${CMAKE_C_COMPILER}" MATCHES "icl") - if(CMAKE_HOST_UNIX OR APPLE) - set(WARNFLAGS "-w3") - set(WARNFLAGS_MAINTAINER "-w3 -Wcheck -Wremarks") - set(WARNFLAGS_DISABLE "") - if(BASEARCH_X86_FOUND) - set(AVX2FLAG "-mavx2") - set(SSE2FLAG "-msse2") - set(SSSE3FLAG "-mssse3") - set(SSE4FLAG "-msse4.2") - endif() - else() - set(WARNFLAGS "/W3") - set(WARNFLAGS_MAINTAINER "/W5") - set(WARNFLAGS_DISABLE "") - if(BASEARCH_X86_FOUND) - set(AVX2FLAG "/arch:AVX2") - set(SSE2FLAG "/arch:SSE2") - set(SSSE3FLAG "/arch:SSSE3") - set(SSE4FLAG "/arch:SSE4.2") - endif() - endif() - if(WITH_NATIVE_INSTRUCTIONS) - message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration") - endif() -elseif(MSVC) - # TODO. ICC can be used through MSVC. I'm not sure if we'd ever see that combination - # (who'd use cmake from an IDE...) but checking for ICC before checking for MSVC should - # avoid mistakes. - # /Oi ? - set(WARNFLAGS "/W3") - set(WARNFLAGS_MAINTAINER "/W4") - set(WARNFLAGS_DISABLE "") - if(BASEARCH_ARM_FOUND) - add_definitions(-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE) - if(NOT "${ARCH}" MATCHES "aarch64") - set(NEONFLAG "/arch:VFPv4") - endif() - elseif(BASEARCH_X86_FOUND) - if(NOT "${ARCH}" MATCHES "x86_64") - set(SSE2FLAG "/arch:SSE2") - endif() - endif() - if(WITH_NATIVE_INSTRUCTIONS) - message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration") - endif() -else() - # catch all GNU C compilers as well as Clang and AppleClang - if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") - set(__GNUC__ ON) - endif() - # Enable warnings in GCC and Clang - if(__GNUC__) - set(WARNFLAGS "-Wall") - set(WARNFLAGS_MAINTAINER "-Wextra -Wpedantic") - set(WARNFLAGS_DISABLE "-Wno-implicit-fallthrough") - endif() - if(WITH_NATIVE_INSTRUCTIONS) - if(__GNUC__) - if(BASEARCH_PPC_FOUND) - set(NATIVEFLAG "-mcpu=native") - else() - set(NATIVEFLAG "-march=native") - endif() - else() - message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not implemented yet on this configuration") - endif() - endif() - if(NOT NATIVEFLAG) - if(__GNUC__) - if(BASEARCH_ARM_FOUND) - if(NOT CMAKE_C_FLAGS MATCHES "-mfloat-abi") - # Check support for ARM floating point - execute_process(COMMAND ${CMAKE_C_COMPILER} "-dumpmachine" - OUTPUT_VARIABLE GCC_MACHINE) - if("${GCC_MACHINE}" MATCHES "gnueabihf") - set(FLOATABI "-mfloat-abi=hard") - elseif("${GCC_MACHINE}" MATCHES ".*gnueabi") - set(FLOATABI "-mfloat-abi=softfp") - endif() - message(STATUS "ARM floating point arch: ${FLOATABI}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLOATABI}") - endif() - # NEON - if("${ARCH}" MATCHES "aarch64") - set(NEONFLAG "-march=armv8-a+simd") - else() - # Check whether -mfpu=neon is available - set(CMAKE_REQUIRED_FLAGS "-mfpu=neon") - check_c_source_compiles( - "int main() { return 0; }" - MFPU_NEON_AVAILABLE FAIL_REGEX "not supported") - set(CMAKE_REQUIRED_FLAGS) - if(MFPU_NEON_AVAILABLE) - set(NEONFLAG "-mfpu=neon") - endif() - endif() - # ACLE - set(ACLEFLAG "-march=armv8-a+crc") - elseif(BASEARCH_PPC_FOUND) - set(POWER8FLAG "-mcpu=power8") - elseif(BASEARCH_X86_FOUND) - set(AVX2FLAG "-mavx2") - set(SSE2FLAG "-msse2") - set(SSSE3FLAG "-mssse3") - set(SSE4FLAG "-msse4") - set(PCLMULFLAG "-mpclmul") - endif() - endif() - endif() -endif() - -# Replace optimization level 3 added by default with level 2 -if(NOT MSVC AND NOT CMAKE_C_FLAGS MATCHES "([\\/\\-]O)3") - string(REGEX REPLACE "([\\/\\-]O)3" "\\12" - CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE}) -endif() - -# Set architecture alignment requirements -if(WITH_UNALIGNED) - if(BASEARCH_ARM_FOUND OR (BASEARCH_PPC_FOUND AND "${ARCH}" MATCHES "powerpc64le") OR BASEARCH_X86_FOUND) - if(NOT DEFINED UNALIGNED_OK) - set(UNALIGNED_OK TRUE) - endif() - endif() - if(UNALIGNED_OK) - add_definitions(-DUNALIGNED_OK) - message(STATUS "Architecture supports unaligned reads") - endif() - if(BASEARCH_ARM_FOUND) - if(NOT DEFINED UNALIGNED64_OK) - if("${ARCH}" MATCHES "(arm(v[8-9])?|aarch64)") - set(UNALIGNED64_OK TRUE) - endif() - endif() - endif() - if(BASEARCH_PPC_FOUND) - if(NOT DEFINED UNALIGNED64_OK) - if("${ARCH}" MATCHES "powerpc64le") - set(UNALIGNED64_OK TRUE) - endif() - endif() - endif() - if(BASEARCH_X86_FOUND) - if(NOT DEFINED UNALIGNED64_OK) - set(UNALIGNED64_OK TRUE) - endif() - endif() - if(UNALIGNED64_OK) - add_definitions(-DUNALIGNED64_OK) - message(STATUS "Architecture supports unaligned reads of > 4 bytes") - endif() -else() - message(STATUS "Unaligned reads manually disabled") -endif() - -# Apply warning compiler flags -if(WITH_MAINTAINER_WARNINGS) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNFLAGS} ${WARNFLAGS_MAINTAINER} ${WARNFLAGS_DISABLE}") -else() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNFLAGS} ${WARNFLAGS_DISABLE}") -endif() - -# Set code coverage compiler flags -if(WITH_CODE_COVERAGE) - if(CMAKE_C_COMPILER_ID MATCHES "Clang") - set(CMAKE_C_FLAGS "-O0 ${CMAKE_C_FLAGS} -coverage") - elseif(__GNUC__) - # Some versions of GCC don't support -coverage shorthand - set(CMAKE_C_FLAGS "-O0 ${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs -fprofile-values") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov -fprofile-arcs") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lgcov -fprofile-arcs") - endif() -endif() - -# Set native instruction set compiler flag -if(WITH_NATIVE_INSTRUCTIONS AND DEFINED NATIVEFLAG) - # Apply flag to all source files and compilation checks - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NATIVEFLAG}") -endif() - -# -# Check for stndard/system includes -# -check_include_file(sys/types.h HAVE_SYS_TYPES_H) -check_include_file(stdarg.h HAVE_STDARG_H) -check_include_file(stdint.h HAVE_STDINT_H) -check_include_file(stddef.h HAVE_STDDEF_H) -check_include_file(sys/sdt.h HAVE_SYS_SDT_H) -check_include_file(unistd.h HAVE_UNISTD_H) - -# -# Check to see if we have large file support -# -set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64) -check_type_size(off64_t OFF64_T) -if(HAVE_OFF64_T) - add_definitions(-D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64) -else() - check_type_size(_off64_t _OFF64_T) - if(HAVE__OFF64_T) - add_definitions(-D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64) - else() - check_type_size(__off64_t __OFF64_T) - endif() -endif() -set(CMAKE_REQUIRED_DEFINITIONS) # clear variable - -# -# Check for fseeko and other optional functions -# -check_function_exists(fseeko HAVE_FSEEKO) -if(NOT HAVE_FSEEKO) - add_definitions(-DNO_FSEEKO) -endif() -check_function_exists(strerror HAVE_STRERROR) -if(NOT HAVE_STRERROR) - add_definitions(-DNO_STRERROR) -endif() - -if(WITH_SANITIZER STREQUAL "Address") - add_address_sanitizer() -elseif(WITH_SANITIZER STREQUAL "Memory") - add_memory_sanitizer() -elseif(WITH_SANITIZER STREQUAL "Undefined") - add_undefined_sanitizer() -endif() - -# -# Check whether compiler supports -fno-semantic-interposition parameter -# -set(CMAKE_REQUIRED_FLAGS "-fno-semantic-interposition") -check_c_source_compiles( - "int main() { return 0; }" - HAVE_NO_INTERPOSITION -) -set(CMAKE_REQUIRED_FLAGS) - -# -# Check if we can hide zlib internal symbols that are linked between separate source files using hidden -# -check_c_source_compiles( - "#define Z_INTERNAL __attribute__((visibility (\"hidden\"))) - int Z_INTERNAL foo; - int main() { - return 0; - }" - HAVE_ATTRIBUTE_VISIBILITY_HIDDEN FAIL_REGEX "not supported") -if(HAVE_ATTRIBUTE_VISIBILITY_HIDDEN) - add_definitions(-DHAVE_VISIBILITY_HIDDEN) -endif() - -# -# Check if we can hide zlib internal symbols that are linked between separate source files using internal -# -check_c_source_compiles( - "#define Z_INTERNAL __attribute__((visibility (\"internal\"))) - int Z_INTERNAL foo; - int main() { - return 0; - }" - HAVE_ATTRIBUTE_VISIBILITY_INTERNAL FAIL_REGEX "not supported") -if(HAVE_ATTRIBUTE_VISIBILITY_INTERNAL) - add_definitions(-DHAVE_VISIBILITY_INTERNAL) -endif() - -# -# check for __builtin_ctz() support in the compiler -# -check_c_source_compiles( - "int main(void) { - unsigned int zero = 0; - long test = __builtin_ctz(zero); - (void)test; - return 0; - }" - HAVE_BUILTIN_CTZ -) -if(HAVE_BUILTIN_CTZ) - add_definitions(-DHAVE_BUILTIN_CTZ) -endif() -# -# check for __builtin_ctzll() support in the compiler -# -check_c_source_compiles( - "int main(void) { - unsigned int zero = 0; - long test = __builtin_ctzll(zero); - (void)test; - return 0; - }" - HAVE_BUILTIN_CTZLL -) -if(HAVE_BUILTIN_CTZLL) - add_definitions(-DHAVE_BUILTIN_CTZLL) -endif() - -# -# check for ptrdiff_t support -# -check_c_source_compiles( - "#include - int main() { - ptrdiff_t *a; - (void)a; - return 0; - }" - HAVE_PTRDIFF_T -) -if(NOT HAVE_PTRDIFF_T) - set(NEED_PTRDIFF_T 1) - - check_type_size("void *" SIZEOF_DATA_PTR) - message(STATUS "sizeof(void *) is ${SIZEOF_DATA_PTR} bytes") - - if(${SIZEOF_DATA_PTR} MATCHES "4") - set(PTRDIFF_TYPE "uint32_t") - elseif(${SIZEOF_DATA_PTR} MATCHES "8") - set(PTRDIFF_TYPE "uint64_t") - else() - message(FATAL_ERROR "sizeof(void *) is neither 32 nor 64 bit") - endif() -endif() - -# Macro to check if source compiles -# (and, when compiling very natively, also runs). -macro(check_c_source_compile_or_run source flag) - if(CMAKE_CROSSCOMPILING OR NOT WITH_NATIVE_INSTRUCTIONS) - check_c_source_compiles("${source}" ${flag}) - else() - check_c_source_runs("${source}" ${flag}) - endif() -endmacro() - -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DZLIB_DEBUG") - -if(MSVC) - set(CMAKE_DEBUG_POSTFIX "d") - add_definitions(-D_CRT_SECURE_NO_DEPRECATE) - add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) -endif() - -if(BASEARCH_PPC_FOUND) - # Check if we have what we need for POWER8 optimizations - set(CMAKE_REQUIRED_FLAGS "${POWER8FLAG}") - check_c_source_compiles( - "#include - int main() { - return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); - }" - HAVE_POWER8 - ) - set(CMAKE_REQUIRED_FLAGS) -elseif(BASEARCH_X86_FOUND) - # Check whether compiler supports SSE2 instrinics - set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG}") - check_c_source_compile_or_run( - "#include - int main(void) { - __m128i zero = _mm_setzero_si128(); - (void)zero; - return 0; - }" - HAVE_SSE2_INTRIN - ) - # Check whether compiler supports SSSE3 intrinsics - set(CMAKE_REQUIRED_FLAGS "${SSSE3FLAG}") - check_c_source_compile_or_run( - "#include - int main(void) { - __m128i u, v, w; - u = _mm_set1_epi32(1); - v = _mm_set1_epi32(2); - w = _mm_hadd_epi32(u, v); - (void)w; - return 0; - }" - HAVE_SSSE3_INTRIN - ) - # Check whether compiler supports SSE4 CRC inline asm - set(CMAKE_REQUIRED_FLAGS "${SSE4FLAG}") - check_c_source_compile_or_run( - "int main(void) { - unsigned val = 0, h = 0; - #if defined(_MSC_VER) - { __asm mov edx, h __asm mov eax, val __asm crc32 eax, edx __asm mov val, eax } - #else - __asm__ __volatile__ ( \"crc32 %1,%0\" : \"+r\" (h) : \"r\" (val) ); - #endif - return (int)h; - }" - HAVE_SSE42CRC_INLINE_ASM - ) - # Check whether compiler supports SSE4 CRC intrinsics - check_c_source_compile_or_run( - "#include - int main(void) { - unsigned crc = 0; - char c = 'c'; - #if defined(_MSC_VER) - crc = _mm_crc32_u32(crc, c); - #else - crc = __builtin_ia32_crc32qi(crc, c); - #endif - (void)crc; - return 0; - }" - HAVE_SSE42CRC_INTRIN - ) - # Check whether compiler supports SSE4.2 compare string instrinics - check_c_source_compile_or_run( - "#include - int main(void) { - unsigned char a[64] = { 0 }; - unsigned char b[64] = { 0 }; - __m128i xmm_src0, xmm_src1; - xmm_src0 = _mm_loadu_si128((__m128i *)(char *)a); - xmm_src1 = _mm_loadu_si128((__m128i *)(char *)b); - return _mm_cmpestri(xmm_src0, 16, xmm_src1, 16, 0); - }" - HAVE_SSE42CMPSTR_INTRIN - ) - # Check whether compiler supports PCLMULQDQ intrinsics - set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG}") - if(NOT (APPLE AND "${ARCH}" MATCHES "i386")) - # The pclmul code currently crashes on Mac in 32bit mode. Avoid for now. - check_c_source_compile_or_run( - "#include - int main(void) { - __m128i a = _mm_setzero_si128(); - __m128i b = _mm_setzero_si128(); - __m128i c = _mm_clmulepi64_si128(a, b, 0x10); - (void)c; - return 0; - }" - HAVE_PCLMULQDQ_INTRIN - ) - else() - set(HAVE_PCLMULQDQ_INTRIN NO) - endif() - # Check whether compiler supports AVX2 intrinics - set(CMAKE_REQUIRED_FLAGS "${AVX2FLAG}") - check_c_source_compile_or_run( - "#include - int main(void) { - __m256i x = _mm256_set1_epi16(2); - const __m256i y = _mm256_set1_epi16(1); - x = _mm256_subs_epu16(x, y); - (void)x; - return 0; - }" - HAVE_AVX2_INTRIN - ) - set(CMAKE_REQUIRED_FLAGS) - - # FORCE_SSE2 option will only be shown if HAVE_SSE2_INTRIN is true - if("${ARCH}" MATCHES "i[3-6]86") - cmake_dependent_option(FORCE_SSE2 "Always assume CPU is SSE2 capable" OFF "HAVE_SSE2_INTRIN" OFF) - endif() -endif() - -# -# Enable deflate_quick at level 1 -# -if(NOT WITH_NEW_STRATEGIES) - add_definitions(-DNO_QUICK_STRATEGY) -endif() -# -# Enable deflate_medium at level 4-6 -# -if(NOT WITH_NEW_STRATEGIES) - add_definitions(-DNO_MEDIUM_STRATEGY) -endif() -# -# Enable inflate compilation options -# -if(WITH_INFLATE_STRICT) - add_definitions(-DINFLATE_STRICT) - message(STATUS "Inflate strict distance checking enabled") -endif() -if(WITH_INFLATE_ALLOW_INVALID_DIST) - add_definitions(-DINFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR) - message(STATUS "Inflate zero data for invalid distances enabled") -endif() - - -set(ZLIB_ARCH_SRCS) -set(ZLIB_ARCH_HDRS) -set(ARCHDIR "arch/generic") -if(BASEARCH_ARM_FOUND) - set(ARCHDIR "arch/arm") -elseif(BASEARCH_PPC_FOUND) - set(ARCHDIR "arch/power") -elseif(BASEARCH_S360_FOUND) - set(ARCHDIR "arch/s390") -elseif(BASEARCH_X86_FOUND) - set(ARCHDIR "arch/x86") - if(NOT ${ARCH} MATCHES "x86_64") - add_feature_info(SSE2 1 "Support the SSE2 instruction set, using \"${SSE2FLAG}\"") - endif() -else() - message(STATUS "No optimized architecture: using ${ARCHDIR}") -endif() - -if(WITH_OPTIM) - if(BASEARCH_ARM_FOUND) - add_definitions(-DARM_FEATURES) - list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/arm.h) - list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/armfeature.c) - if(WITH_ACLE AND NOT MSVC) - add_definitions(-DARM_ACLE_CRC_HASH) - set(ACLE_SRCS ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c) - set_property(SOURCE ${ACLE_SRCS} PROPERTY COMPILE_FLAGS "${ACLEFLAG}") - list(APPEND ZLIB_ARCH_SRCS ${ACLE_SRCS}) - add_feature_info(ACLE_CRC 1 "Support ACLE optimized CRC hash generation, using \"${ACLEFLAG}\"") - endif() - if(WITH_NEON) - add_definitions(-DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH) - set(NEON_SRCS ${ARCHDIR}/adler32_neon.c ${ARCHDIR}/chunkset_neon.c ${ARCHDIR}/slide_neon.c) - list(APPEND ZLIB_ARCH_SRCS ${NEON_SRCS}) - set_property(SOURCE ${NEON_SRCS} PROPERTY COMPILE_FLAGS "${NEONFLAG}") - if(MSVC) - add_definitions(-D__ARM_NEON__) - endif() - add_feature_info(NEON_ADLER32 1 "Support NEON instructions in adler32, using \"${NEONFLAG}\"") - add_feature_info(NEON_SLIDEHASH 1 "Support NEON instructions in slide_hash, using \"${NEONFLAG}\"") - endif() - elseif(BASEARCH_PPC_FOUND) - if(WITH_POWER8 AND HAVE_POWER8) - add_definitions(-DPOWER8) - add_definitions(-DPOWER_FEATURES) - add_definitions(-DPOWER8_VSX_ADLER32) - add_definitions(-DPOWER8_VSX_SLIDEHASH) - list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/power.h) - list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power.c) - set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/slide_hash_power8.c) - list(APPEND ZLIB_ARCH_SRCS ${POWER8_SRCS}) - set_property(SOURCE ${POWER8_SRCS} PROPERTY COMPILE_FLAGS "${POWER8FLAG}") - endif() - elseif(BASEARCH_S360_FOUND) - if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE) - list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/dfltcc_common.c) - add_definitions(-DGZBUFSIZE=262144) - endif() - if(WITH_DFLTCC_DEFLATE) - add_definitions(-DS390_DFLTCC_DEFLATE) - list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/dfltcc_deflate.c) - endif() - if(WITH_DFLTCC_INFLATE) - add_definitions(-DS390_DFLTCC_INFLATE) - list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/dfltcc_inflate.c) - endif() - elseif(BASEARCH_X86_FOUND) - add_definitions(-DX86_FEATURES) - list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/x86.h) - list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/x86.c) - if(MSVC) - list(APPEND ZLIB_ARCH_HDRS fallback_builtins.h) - endif() - if(WITH_AVX2 AND HAVE_AVX2_INTRIN) - add_definitions(-DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET) - set(AVX2_SRCS ${ARCHDIR}/slide_avx.c) - add_feature_info(AVX2_SLIDEHASH 1 "Support AVX2 optimized slide_hash, using \"${AVX2FLAG}\"") - list(APPEND AVX2_SRCS ${ARCHDIR}/chunkset_avx.c) - add_feature_info(AVX_CHUNKSET 1 "Support AVX optimized chunkset, using \"${AVX2FLAG}\"") - list(APPEND AVX2_SRCS ${ARCHDIR}/compare258_avx.c) - add_feature_info(AVX2_COMPARE258 1 "Support AVX2 optimized compare258, using \"${AVX2FLAG}\"") - list(APPEND AVX2_SRCS ${ARCHDIR}/adler32_avx.c) - add_feature_info(AVX2_ADLER32 1 "Support AVX2-accelerated adler32, using \"${AVX2FLAG}\"") - list(APPEND ZLIB_ARCH_SRCS ${AVX2_SRCS}) - set_property(SOURCE ${AVX2_SRCS} PROPERTY COMPILE_FLAGS "${AVX2FLAG}") - endif() - if(WITH_SSE4 AND (HAVE_SSE42CRC_INLINE_ASM OR HAVE_SSE42CRC_INTRIN)) - add_definitions(-DX86_SSE42_CRC_HASH) - set(SSE42_SRCS ${ARCHDIR}/insert_string_sse.c) - add_feature_info(SSE42_CRC 1 "Support SSE4.2 optimized CRC hash generation, using \"${SSE4FLAG}\"") - list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) - set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG}") - if(HAVE_SSE42CRC_INTRIN) - add_definitions(-DX86_SSE42_CRC_INTRIN) - endif() - endif() - if(HAVE_SSE42CMPSTR_INTRIN) - add_definitions(-DX86_SSE42_CMP_STR) - set(SSE42_SRCS ${ARCHDIR}/compare258_sse.c) - add_feature_info(SSE42_COMPARE258 1 "Support SSE4.2 optimized compare258, using \"${SSE4FLAG}\"") - list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) - set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG}") - endif() - if(WITH_SSE2 AND HAVE_SSE2_INTRIN) - add_definitions(-DX86_SSE2 -DX86_SSE2_CHUNKSET -DX86_SSE2_SLIDEHASH) - set(SSE2_SRCS ${ARCHDIR}/chunkset_sse.c ${ARCHDIR}/slide_sse.c) - list(APPEND ZLIB_ARCH_SRCS ${SSE2_SRCS}) - if(NOT ${ARCH} MATCHES "x86_64") - set_property(SOURCE ${SSE2_SRCS} PROPERTY COMPILE_FLAGS "${SSE2FLAG}") - add_feature_info(FORCE_SSE2 FORCE_SSE2 "Assume CPU is SSE2 capable") - if(FORCE_SSE2) - add_definitions(-DX86_NOCHECK_SSE2) - endif() - endif() - endif() - if(WITH_SSSE3 AND HAVE_SSSE3_INTRIN) - add_definitions(-DX86_SSSE3 -DX86_SSSE3_ADLER32) - set(SSSE3_SRCS ${ARCHDIR}/adler32_ssse3.c) - add_feature_info(SSSE3_ADLER32 1 "Support SSSE3-accelerated adler32, using \"${SSSE3FLAG}\"") - list(APPEND ZLIB_ARCH_SRCS ${SSSE3_SRCS}) - set_property(SOURCE ${SSSE3_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG}") - endif() - if(WITH_PCLMULQDQ AND HAVE_PCLMULQDQ_INTRIN AND WITH_SSSE3 AND WITH_SSE4) - add_definitions(-DX86_PCLMULQDQ_CRC) - set(PCLMULQDQ_SRCS ${ARCHDIR}/crc_folding.c) - add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG}\"") - list(APPEND ZLIB_ARCH_SRCS ${PCLMULQDQ_SRCS}) - set_property(SOURCE ${PCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG}") - endif() - endif() -endif() -message(STATUS "Architecture-specific source files: ${ZLIB_ARCH_SRCS}") - -#============================================================================ -# zconf.h -#============================================================================ - -macro(generate_cmakein input output) - file(REMOVE ${output}) - file(STRINGS ${input} _lines) - foreach(_line IN LISTS _lines) - string(REGEX REPLACE "#ifdef HAVE_UNISTD_H.*" "@ZCONF_UNISTD_LINE@" _line "${_line}") - string(REGEX REPLACE "#ifdef HAVE_STDARG_H.*" "@ZCONF_STDARG_LINE@" _line "${_line}") - string(REGEX REPLACE "#ifdef NEED_PTRDIFF_T.*" "@ZCONF_PTRDIFF_LINE@" _line "${_line}") - if(NEED_PTRDIFF_T) - string(REGEX REPLACE "typedef PTRDIFF_TYPE" "typedef @PTRDIFF_TYPE@" _line "${_line}") - endif() - file(APPEND ${output} "${_line}\n") - endforeach() -endmacro(generate_cmakein) - -generate_cmakein( ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.in ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h.cmakein ) - -if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) - # If we're doing an out of source build and the user has a zconf.h - # in their source tree... - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h) - message(STATUS "Renaming") - message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h") - message(STATUS "to 'zconf${SUFFIX}.h.included' because this file is included with zlib") - message(STATUS "but CMake generates it automatically in the build directory.") - file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.included) - endif() - - # If we're doing an out of source build and the user has a zconf.h.cmakein - # in their source tree... - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakein) - message(STATUS "Renaming") - message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakein") - message(STATUS "to 'zconf${SUFFIX}.h.cmakeincluded' because this file is included with zlib") - message(STATUS "but CMake generates it automatically in the build directory.") - file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakein ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakeincluded) - endif() -endif() - -# Refer to prefix symbolically to ease relocation by end user, -# as Makefile-generated .pc file does. -if(INC_INSTALL_DIR STREQUAL "${CMAKE_INSTALL_PREFIX}/include") - set(PC_INC_INSTALL_DIR "\${prefix}/include") -else() - set(PC_INC_INSTALL_DIR "${INSTALL_INC_DIR}") -endif() -if(LIB_INSTALL_DIR STREQUAL "${CMAKE_INSTALL_PREFIX}/lib") - set(PC_LIB_INSTALL_DIR "\${exec_prefix}/lib") -else() - set(PC_LIB_INSTALL_DIR "${INSTALL_LIB_DIR}") -endif() - -#============================================================================ -# zlib -#============================================================================ - -set(ZLIB_PUBLIC_HDRS - ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h - zlib${SUFFIX}.h -) -set(ZLIB_PRIVATE_HDRS - adler32_p.h - chunkset_tpl.h - crc32_p.h - crc32_tbl.h - crc32_comb_tbl.h - deflate.h - deflate_p.h - functable.h - inffast.h - inffixed_tbl.h - inflate.h - inflate_p.h - inftrees.h - insert_string_tpl.h - match_tpl.h - trees.h - trees_emit.h - trees_tbl.h - zbuild.h - zendian.h - zutil.h -) -set(ZLIB_SRCS - adler32.c - chunkset.c - compare258.c - compress.c - crc32.c - crc32_comb.c - deflate.c - deflate_fast.c - deflate_medium.c - deflate_quick.c - deflate_slow.c - functable.c - infback.c - inffast.c - inflate.c - inftrees.c - insert_string.c - trees.c - uncompr.c - zutil.c -) - -set(ZLIB_GZFILE_PRIVATE_HDRS - gzguts.h -) -set(ZLIB_GZFILE_SRCS - gzlib.c - gzread.c - gzwrite.c -) - -if(NOT MINGW AND NOT MSYS) - set(ZLIB_DLL_SRCS - win32/zlib${SUFFIX}1.rc # If present will override custom build rule below. - ) -endif() - -if(MINGW OR MSYS) - # This gets us DLL resource information when compiling on MinGW. - if(NOT CMAKE_RC_COMPILER) - set(CMAKE_RC_COMPILER windres.exe) - endif() - - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - COMMAND ${CMAKE_RC_COMPILER} - -D GCC_WINDRES - -I ${CMAKE_CURRENT_SOURCE_DIR} - -I ${CMAKE_CURRENT_BINARY_DIR} - -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib${SUFFIX}1.rc) - set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) -endif() - -set(ZLIB_ALL_SRCS ${ZLIB_SRCS} ${ZLIB_ARCH_HDRS} ${ZLIB_ARCH_SRCS} ${ZLIB_DLL_SRCS} - ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -if(WITH_GZFILEOP) - list(APPEND ZLIB_ALL_SRCS ${ZLIB_GZFILE_PRIVATE_HDRS} ${ZLIB_GZFILE_SRCS}) -endif() - -if(NOT DEFINED BUILD_SHARED_LIBS) - add_library(zlib SHARED ${ZLIB_ALL_SRCS}) - add_library(zlibstatic STATIC ${ZLIB_ALL_SRCS}) - - set(ZLIB_INSTALL_LIBRARIES zlib zlibstatic) -else() - add_library(zlib ${ZLIB_ALL_SRCS}) - - set(ZLIB_INSTALL_LIBRARIES zlib) -endif() - -foreach(ZLIB_INSTALL_LIBRARY ${ZLIB_INSTALL_LIBRARIES}) - target_include_directories(${ZLIB_INSTALL_LIBRARY} PUBLIC - ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) -endforeach() - -if(WIN32) - set_target_properties(${ZLIB_INSTALL_LIBRARIES} PROPERTIES OUTPUT_NAME zlib${SUFFIX}) -else() - # On unix-like platforms the library is almost always called libz - set_target_properties(${ZLIB_INSTALL_LIBRARIES} PROPERTIES OUTPUT_NAME z${SUFFIX}) -endif() - -if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) - set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) - - if(ZLIB_COMPAT) - set(ZLIB_FULL_VERSION ${ZLIB_HEADER_VERSION}.zlib-ng) - set_target_properties(zlib PROPERTIES SOVERSION 1) - else() - set(ZLIB_FULL_VERSION ${ZLIBNG_HEADER_VERSION}) - set_target_properties(zlib PROPERTIES SOVERSION 2) - endif() - - if(NOT CYGWIN) - # This property causes shared libraries on Linux to have the full version - # encoded into their final filename. We disable this on Cygwin because - # it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll - # seems to be the default. - # - # This has no effect with MSVC, on that platform the version info for - # the DLL comes from the resource file win32/zlib1.rc - set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION}) - endif() - - if(UNIX) - if(HAVE_NO_INTERPOSITION) - set_target_properties(zlib PROPERTIES COMPILE_FLAGS "-fno-semantic-interposition") - endif() - if(NOT APPLE) - set_target_properties(zlib PROPERTIES LINK_FLAGS - "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.map\"") - else() - # Match configure/make's behavior (i.e. don't use @rpath on mac). - set_target_properties(zlib PROPERTIES INSTALL_NAME_DIR "${LIB_INSTALL_DIR}") - endif() - elseif(MSYS) - # Suppress version number from shared library name - set(CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION 0) - elseif(WIN32) - # Creates zlib1.dll when building shared library version - if(ZLIB_COMPAT) - set_target_properties(zlib PROPERTIES SUFFIX "1.dll") - else() - set_target_properties(zlib PROPERTIES SUFFIX "2.dll") - endif() - endif() -endif() - -if(HAVE_STDARG_H) - SET(ZCONF_STDARG_LINE "#if 1 /* was set to #if 1 by configure/cmake/etc */") -else() - SET(ZCONF_STDARG_LINE "#ifdef HAVE_STDARG_H /* may be set to #if 1 by configure/cmake/etc */") -endif() -if(HAVE_UNISTD_H) - SET(ZCONF_UNISTD_LINE "#if 1 /* was set to #if 1 by configure/cmake/etc */") -else() - SET(ZCONF_UNISTD_LINE "#ifdef HAVE_UNISTD_H /* may be set to #if 1 by configure/cmake/etc */") -endif() -if(NEED_PTRDIFF_T) - SET(ZCONF_PTRDIFF_LINE "#if 1 /* was set to #if 1 by configure/cmake/etc */") -else() - SET(ZCONF_PTRDIFF_LINE "#ifdef NEED_PTRDIFF_T /* may be set to #if 1 by configure/cmake/etc */") -endif() - -set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib${SUFFIX}.pc) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein - ${ZLIB_PC} @ONLY) -configure_file(${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h.cmakein - ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h @ONLY) - -if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL) - install(TARGETS ${ZLIB_INSTALL_LIBRARIES} - RUNTIME DESTINATION "${BIN_INSTALL_DIR}" - ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" - LIBRARY DESTINATION "${LIB_INSTALL_DIR}") -endif() -if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL) - install(FILES zlib${SUFFIX}.h - DESTINATION "${INC_INSTALL_DIR}" RENAME zlib${SUFFIX}.h) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h - DESTINATION "${INC_INSTALL_DIR}" RENAME zconf${SUFFIX}.h) -endif() -if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL) - install(FILES zlib.3 DESTINATION "${MAN_INSTALL_DIR}/man3" RENAME zlib${SUFFIX}.3) -endif() -if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL) - install(FILES ${ZLIB_PC} DESTINATION "${PKGCONFIG_INSTALL_DIR}") -endif() - -#============================================================================ -# Example binaries -#============================================================================ - -option(ZLIB_ENABLE_TESTS "Build test binaries" ON) -if(ZLIB_ENABLE_TESTS) - enable_testing() - macro(configure_test_executable target) - target_include_directories(${target} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - if(NOT WITH_GZFILEOP) - target_compile_definitions(${target} PUBLIC -DWITH_GZFILEOP) - target_sources(${target} PRIVATE ${ZLIB_GZFILE_PRIVATE_HDRS} ${ZLIB_GZFILE_SRCS}) - endif() - if(ZLIB_DUAL_LINK) - find_package(ZLIB) - if(ZLIB_FOUND) - target_link_libraries(${target} ${ZLIB_LIBRARIES}) - endif() - endif() - endmacro() - - add_executable(adler32_test test/adler32_test.c) - configure_test_executable(adler32_test) - target_link_libraries(adler32_test zlib) - - set(ADLER32TEST_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_test(NAME adler32_test COMMAND ${ADLER32TEST_COMMAND}) - - add_executable(example test/example.c) - configure_test_executable(example) - target_link_libraries(example zlib) - - set(EXAMPLE_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_test(NAME example COMMAND ${EXAMPLE_COMMAND}) - - set(MINIGZIP_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_executable(minigzip test/minigzip.c) - configure_test_executable(minigzip) - if(NOT DEFINED BUILD_SHARED_LIBS) - target_link_libraries(minigzip zlibstatic) - else() - target_link_libraries(minigzip zlib) - endif() - if(BASEARCH_S360_FOUND) - if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE) - set_source_files_properties(test/minigzip.c PROPERTIES COMPILE_DEFINITIONS BUFLEN=262144) - endif() - endif() - - set(MINIDEFLATE_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_executable(minideflate test/minideflate.c) - configure_test_executable(minideflate) - target_link_libraries(minideflate zlib) - - if(INSTALL_UTILS) - install(TARGETS minigzip minideflate - RUNTIME DESTINATION "${BIN_INSTALL_DIR}" - ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" - LIBRARY DESTINATION "${LIB_INSTALL_DIR}") - endif() - - set(SWITCHLEVELS_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_executable(switchlevels test/switchlevels.c) - configure_test_executable(switchlevels) - target_link_libraries(switchlevels zlib) - - add_executable(infcover test/infcover.c inftrees.c) - configure_test_executable(infcover) - target_link_libraries(infcover zlib) - - add_executable(makefixed tools/makefixed.c inftrees.c) - target_include_directories(makefixed PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) - - set(MAKEFIXED_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_test(NAME makefixed - COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${MAKEFIXED_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_SOURCE_DIR}/inffixed_tbl._h - -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/inffixed_tbl.h - -DIGNORE_LINE_ENDINGS=ON - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) - - add_executable(maketrees tools/maketrees.c trees.c zutil.c) - target_include_directories(maketrees PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) - - set(MAKETREES_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_test(NAME maketrees - COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${MAKETREES_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_SOURCE_DIR}/trees_tbl._h - -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/trees_tbl.h - -DIGNORE_LINE_ENDINGS=ON - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) - - add_executable(makecrct tools/makecrct.c) - target_include_directories(makecrct PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) - - set(MAKECRCT_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_test(NAME makecrct-crc32 - COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${MAKECRCT_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_SOURCE_DIR}/crc32_tbl._h - -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/crc32_tbl.h - -DIGNORE_LINE_ENDINGS=ON - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) - - set(MAKECRCT_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ -c) - add_test(NAME makecrct-crc32-combine - COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${MAKECRCT_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_SOURCE_DIR}/crc32_comb_tbl._h - -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/crc32_comb_tbl.h - -DIGNORE_LINE_ENDINGS=ON - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) - - if(WITH_FUZZERS) - set(FUZZERS checksum compress example_small example_large example_flush example_dict minigzip) - file(GLOB ALL_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*") - foreach(FUZZER ${FUZZERS}) - add_executable(${FUZZER}_fuzzer test/fuzz/${FUZZER}_fuzzer.c test/fuzz/standalone_fuzz_target_runner.c) - configure_test_executable(${FUZZER}_fuzzer) - target_link_libraries(${FUZZER}_fuzzer zlib) - set(FUZZER_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ ${ALL_SRC_FILES}) - add_test(NAME ${FUZZER}_fuzzer COMMAND ${FUZZER_COMMAND}) - endforeach() - endif() - - macro(test_minigzip name path) - # Construct compression arguments for minigzip - set(compress_args -k -c) - foreach(extra_arg IN ITEMS "${ARGN}") - list(APPEND compress_args ${extra_arg}) - endforeach() - - # Create unique friendly string for test - string(REPLACE ";" "" arg_list "${ARGN}") - string(REPLACE " " "" arg_list "${arg_list}") - string(REPLACE "-" "" arg_list "${arg_list}") - - set(test_id minigzip-${name}-${arg_list}) - - if(NOT TEST ${test_id}) - add_test(NAME ${test_id} - COMMAND ${CMAKE_COMMAND} - "-DTARGET=${MINIGZIP_COMMAND}" - "-DCOMPRESS_ARGS=${compress_args}" - "-DDECOMPRESS_ARGS=-d;-c" - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/${path} - -DOUTPUT=${CMAKE_CURRENT_SOURCE_DIR}/${path}-${test_id}.gz - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - endif() - endmacro() - - set(TEST_CONFIGS - -R # Z_RLE - -h # Z_HUFFMAN_ONLY - -T # Direct store - -0 # No compression - -1 # Deflate quick - -4 # Deflate medium (lazy matches) - "-5;-F" # Deflate medium (Z_FIXED) - -6 # Deflate medium - -9 # Deflate slow - "-9;-f" # Deflate slow (Z_FILTERED) - ) - - file(GLOB_RECURSE TEST_FILE_PATHS - LIST_DIRECTORIES false - RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/test/data/*) - - foreach(TEST_FILE_PATH ${TEST_FILE_PATHS}) - if("${TEST_FILE_PATH}" MATCHES ".gz$" OR "${TEST_FILE_PATH}" MATCHES ".out$" OR - "${TEST_FILE_PATH}" MATCHES "/.git/" OR "${TEST_FILE_PATH}" MATCHES ".md$") - continue() - endif() - foreach(TEST_CONFIG ${TEST_CONFIGS}) - get_filename_component(TEST_NAME ${TEST_FILE_PATH} NAME_WE) - if (TEST_NAME STREQUAL "") - continue() - endif() - test_minigzip(${TEST_NAME} ${TEST_FILE_PATH} ${TEST_CONFIG}) - endforeach() - endforeach() - - test_minigzip("detect-text" "test/data/lcet10.txt" -A) - test_minigzip("detect-binary" "test/data/paper-100k.pdf" -A) - - set(CVES CVE-2002-0059 CVE-2004-0797 CVE-2005-1849 CVE-2005-2096) - foreach(CVE ${CVES}) - set(CVE_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ -d) - add_test(NAME ${CVE} - COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${CVE_COMMAND}" - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/${CVE}/test.gz - "-DSUCCESS_EXIT=0;1" - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake) - endforeach() - - if(NOT WIN32 AND ZLIB_COMPAT) - add_executable(CVE-2003-0107 test/CVE-2003-0107.c) - target_link_libraries(CVE-2003-0107 zlib) - set(CVE20030107_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_test(NAME CVE-2003-0107 COMMAND ${CVE20030107_COMMAND}) - endif() - - set(INFCOVER_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_test(NAME infcover COMMAND ${INFCOVER_COMMAND}) - - add_test(NAME GH-361 - COMMAND ${CMAKE_COMMAND} - "-DTARGET=${MINIGZIP_COMMAND}" - "-DCOMPRESS_ARGS=-c;-k;-4" - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/GH-361/test.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME GH-364 - COMMAND ${CMAKE_COMMAND} - "-DCOMPRESS_TARGET=${SWITCHLEVELS_COMMAND}" - "-DCOMPRESS_ARGS=1;5;9;3" - "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/GH-364/test.bin - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME GH-382 - COMMAND ${CMAKE_COMMAND} - "-DTARGET=${MINIDEFLATE_COMMAND}" - "-DCOMPRESS_ARGS=-c;-m;1;-w;-15;-1;-s;4" - "-DDECOMPRESS_ARGS=-c;-d;-m;1;-w;-15" - -DGZIP_VERIFY=OFF - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/GH-382/defneg3.dat - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME GH-536-segfault - COMMAND ${CMAKE_COMMAND} - "-DCOMPRESS_TARGET=${SWITCHLEVELS_COMMAND}" - "-DCOMPRESS_ARGS=6;9744;1;91207" - "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" - -DCOMPARE=OFF - -DGZIP_VERIFY=OFF - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/data/lcet10.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME GH-536-incomplete-read - COMMAND ${CMAKE_COMMAND} - "-DCOMPRESS_TARGET=${SWITCHLEVELS_COMMAND}" - "-DCOMPRESS_ARGS=6;88933;1;195840;2;45761" - "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" - -DCOMPARE=OFF - -DGZIP_VERIFY=OFF - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/data/lcet10.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME GH-536-zero-stored-block - COMMAND ${CMAKE_COMMAND} - "-DCOMPRESS_TARGET=${SWITCHLEVELS_COMMAND}" - "-DCOMPRESS_ARGS=6;15248;1;1050;2;25217" - "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" - -DCOMPARE=OFF - -DGZIP_VERIFY=OFF - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/data/lcet10.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME GH-751 - COMMAND ${CMAKE_COMMAND} - "-DTARGET=${MINIGZIP_COMMAND}" - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/GH-751/test.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) -endif() - -FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES) diff --git a/libs/zlibng/FAQ.zlib b/libs/zlibng/FAQ.zlib deleted file mode 100644 index f234f3e592..0000000000 --- a/libs/zlibng/FAQ.zlib +++ /dev/null @@ -1,374 +0,0 @@ -## -# THIS IS AN UNMAINTAINED COPY OF THE ORIGINAL FILE DISTRIBUTED WITH ZLIB 1.2.11 -## - - - - - Frequently Asked Questions about zlib - - -If your question is not there, please check the zlib home page -http://zlib.net/ which may have more recent information. -The lastest zlib FAQ is at http://zlib.net/zlib_faq.html - - - 1. Is zlib Y2K-compliant? - - Yes. zlib doesn't handle dates. - - 2. Where can I get a Windows DLL version? - - The zlib sources can be compiled without change to produce a DLL. See the - file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the - precompiled DLL are found in the zlib web site at http://zlib.net/ . - - 3. Where can I get a Visual Basic interface to zlib? - - See - * http://marknelson.us/1997/01/01/zlib-engine/ - * win32/DLL_FAQ.txt in the zlib distribution - - 4. compress() returns Z_BUF_ERROR. - - Make sure that before the call of compress(), the length of the compressed - buffer is equal to the available size of the compressed buffer and not - zero. For Visual Basic, check that this parameter is passed by reference - ("as any"), not by value ("as long"). - - 5. deflate() or inflate() returns Z_BUF_ERROR. - - Before making the call, make sure that avail_in and avail_out are not zero. - When setting the parameter flush equal to Z_FINISH, also make sure that - avail_out is big enough to allow processing all pending input. Note that a - Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be - made with more input or output space. A Z_BUF_ERROR may in fact be - unavoidable depending on how the functions are used, since it is not - possible to tell whether or not there is more output pending when - strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a - heavily annotated example. - - 6. Where's the zlib documentation (man pages, etc.)? - - It's in zlib.h . Examples of zlib usage are in the files test/example.c - and test/minigzip.c, with more in examples/ . - - 7. Why don't you use GNU autoconf or libtool or ...? - - Because we would like to keep zlib as a very small and simple package. - zlib is rather portable and doesn't need much configuration. - - 8. I found a bug in zlib. - - Most of the time, such problems are due to an incorrect usage of zlib. - Please try to reproduce the problem with a small program and send the - corresponding source to us at zlib@gzip.org . Do not send multi-megabyte - data files without prior agreement. - - 9. Why do I get "undefined reference to gzputc"? - - If "make test" produces something like - - example.o(.text+0x154): undefined reference to `gzputc' - - check that you don't have old files libz.* in /usr/lib, /usr/local/lib or - /usr/X11R6/lib. Remove any old versions, then do "make install". - -10. I need a Delphi interface to zlib. - - See the contrib/delphi directory in the zlib distribution. - -11. Can zlib handle .zip archives? - - Not by itself, no. See the directory contrib/minizip in the zlib - distribution. - -12. Can zlib handle .Z files? - - No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt - the code of uncompress on your own. - -13. How can I make a Unix shared library? - - By default a shared (and a static) library is built for Unix. So: - - make distclean - ./configure - make - -14. How do I install a shared zlib library on Unix? - - After the above, then: - - make install - - However, many flavors of Unix come with a shared zlib already installed. - Before going to the trouble of compiling a shared version of zlib and - trying to install it, you may want to check if it's already there! If you - can #include , it's there. The -lz option will probably link to - it. You can check the version at the top of zlib.h or with the - ZLIB_VERSION symbol defined in zlib.h . - -15. I have a question about OttoPDF. - - We are not the authors of OttoPDF. The real author is on the OttoPDF web - site: Joel Hainley, jhainley@myndkryme.com. - -16. Can zlib decode Flate data in an Adobe PDF file? - - Yes. See http://www.pdflib.com/ . To modify PDF forms, see - http://sourceforge.net/projects/acroformtool/ . - -17. Why am I getting this "register_frame_info not found" error on Solaris? - - After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib - generates an error such as: - - ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: - symbol __register_frame_info: referenced symbol not found - - The symbol __register_frame_info is not part of zlib, it is generated by - the C compiler (cc or gcc). You must recompile applications using zlib - which have this problem. This problem is specific to Solaris. See - http://www.sunfreeware.com for Solaris versions of zlib and applications - using zlib. - -18. Why does gzip give an error on a file I make with compress/deflate? - - The compress and deflate functions produce data in the zlib format, which - is different and incompatible with the gzip format. The gz* functions in - zlib on the other hand use the gzip format. Both the zlib and gzip formats - use the same compressed data format internally, but have different headers - and trailers around the compressed data. - -19. Ok, so why are there two different formats? - - The gzip format was designed to retain the directory information about a - single file, such as the name and last modification date. The zlib format - on the other hand was designed for in-memory and communication channel - applications, and has a much more compact header and trailer and uses a - faster integrity check than gzip. - -20. Well that's nice, but how do I make a gzip file in memory? - - You can request that deflate write the gzip format instead of the zlib - format using deflateInit2(). You can also request that inflate decode the - gzip format using inflateInit2(). Read zlib.h for more details. - -21. Is zlib thread-safe? - - Yes. However any library routines that zlib uses and any application- - provided memory allocation routines must also be thread-safe. zlib's gz* - functions use stdio library routines, and most of zlib's functions use the - library memory allocation routines by default. zlib's *Init* functions - allow for the application to provide custom memory allocation routines. - - Of course, you should only operate on any given zlib or gzip stream from a - single thread at a time. - -22. Can I use zlib in my commercial application? - - Yes. Please read the license in zlib.h. - -23. Is zlib under the GNU license? - - No. Please read the license in zlib.h. - -24. The license says that altered source versions must be "plainly marked". So - what exactly do I need to do to meet that requirement? - - You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In - particular, the final version number needs to be changed to "f", and an - identification string should be appended to ZLIB_VERSION. Version numbers - x.x.x.f are reserved for modifications to zlib by others than the zlib - maintainers. For example, if the version of the base zlib you are altering - is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and - ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also - update the version strings in deflate.c and inftrees.c. - - For altered source distributions, you should also note the origin and - nature of the changes in zlib.h, as well as in ChangeLog and README, along - with the dates of the alterations. The origin should include at least your - name (or your company's name), and an email address to contact for help or - issues with the library. - - Note that distributing a compiled zlib library along with zlib.h and - zconf.h is also a source distribution, and so you should change - ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes - in zlib.h as you would for a full source distribution. - -25. Will zlib work on a big-endian or little-endian architecture, and can I - exchange compressed data between them? - - Yes and yes. - -26. Will zlib work on a 64-bit machine? - - Yes. It has been tested on 64-bit machines, and has no dependence on any - data types being limited to 32-bits in length. If you have any - difficulties, please provide a complete problem report to zlib@gzip.org - -27. Will zlib decompress data from the PKWare Data Compression Library? - - No. The PKWare DCL uses a completely different compressed data format than - does PKZIP and zlib. However, you can look in zlib's contrib/blast - directory for a possible solution to your problem. - -28. Can I access data randomly in a compressed stream? - - No, not without some preparation. If when compressing you periodically use - Z_FULL_FLUSH, carefully write all the pending data at those points, and - keep an index of those locations, then you can start decompression at those - points. You have to be careful to not use Z_FULL_FLUSH too often, since it - can significantly degrade compression. Alternatively, you can scan a - deflate stream once to generate an index, and then use that index for - random access. See examples/zran.c . - -29. Does zlib work on MVS, OS/390, CICS, etc.? - - It has in the past, but we have not heard of any recent evidence. There - were working ports of zlib 1.1.4 to MVS, but those links no longer work. - If you know of recent, successful applications of zlib on these operating - systems, please let us know. Thanks. - -30. Is there some simpler, easier to read version of inflate I can look at to - understand the deflate format? - - First off, you should read RFC 1951. Second, yes. Look in zlib's - contrib/puff directory. - -31. Does zlib infringe on any patents? - - As far as we know, no. In fact, that was originally the whole point behind - zlib. Look here for some more information: - - http://www.gzip.org/#faq11 - -32. Can zlib work with greater than 4 GB of data? - - Yes. inflate() and deflate() will process any amount of data correctly. - Each call of inflate() or deflate() is limited to input and output chunks - of the maximum value that can be stored in the compiler's "unsigned int" - type, but there is no limit to the number of chunks. Note however that the - strm.total_in and strm_total_out counters may be limited to 4 GB. These - counters are provided as a convenience and are not used internally by - inflate() or deflate(). The application can easily set up its own counters - updated after each call of inflate() or deflate() to count beyond 4 GB. - compress() and uncompress() may be limited to 4 GB, since they operate in a - single call. gzseek() and gztell() may be limited to 4 GB depending on how - zlib is compiled. See the zlibCompileFlags() function in zlib.h. - - The word "may" appears several times above since there is a 4 GB limit only - if the compiler's "long" type is 32 bits. If the compiler's "long" type is - 64 bits, then the limit is 16 exabytes. - -33. Does zlib have any security vulnerabilities? - - The only one that we are aware of is potentially in gzprintf(). If zlib is - compiled to use sprintf() or vsprintf(), then there is no protection - against a buffer overflow of an 8K string space (or other value as set by - gzbuffer()), other than the caller of gzprintf() assuring that the output - will not exceed 8K. On the other hand, if zlib is compiled to use - snprintf() or vsnprintf(), which should normally be the case, then there is - no vulnerability. The ./configure script will display warnings if an - insecure variation of sprintf() will be used by gzprintf(). Also the - zlibCompileFlags() function will return information on what variant of - sprintf() is used by gzprintf(). - - If you don't have snprintf() or vsnprintf() and would like one, you can - find a portable implementation here: - - http://www.ijs.si/software/snprintf/ - - Note that you should be using the most recent version of zlib. Versions - 1.1.3 and before were subject to a double-free vulnerability, and versions - 1.2.1 and 1.2.2 were subject to an access exception when decompressing - invalid compressed data. - -34. Is there a Java version of zlib? - - Probably what you want is to use zlib in Java. zlib is already included - as part of the Java SDK in the java.util.zip package. If you really want - a version of zlib written in the Java language, look on the zlib home - page for links: http://zlib.net/ . - -35. I get this or that compiler or source-code scanner warning when I crank it - up to maximally-pedantic. Can't you guys write proper code? - - Many years ago, we gave up attempting to avoid warnings on every compiler - in the universe. It just got to be a waste of time, and some compilers - were downright silly as well as contradicted each other. So now, we simply - make sure that the code always works. - -36. Valgrind (or some similar memory access checker) says that deflate is - performing a conditional jump that depends on an uninitialized value. - Isn't that a bug? - - No. That is intentional for performance reasons, and the output of deflate - is not affected. This only started showing up recently since zlib 1.2.x - uses malloc() by default for allocations, whereas earlier versions used - calloc(), which zeros out the allocated memory. Even though the code was - correct, versions 1.2.4 and later was changed to not stimulate these - checkers. - -37. Will zlib read the (insert any ancient or arcane format here) compressed - data format? - - Probably not. Look in the comp.compression FAQ for pointers to various - formats and associated software. - -38. How can I encrypt/decrypt zip files with zlib? - - zlib doesn't support encryption. The original PKZIP encryption is very - weak and can be broken with freely available programs. To get strong - encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib - compression. For PKZIP compatible "encryption", look at - http://www.info-zip.org/ - -39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? - - "gzip" is the gzip format, and "deflate" is the zlib format. They should - probably have called the second one "zlib" instead to avoid confusion with - the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 - correctly points to the zlib specification in RFC 1950 for the "deflate" - transfer encoding, there have been reports of servers and browsers that - incorrectly produce or expect raw deflate data per the deflate - specification in RFC 1951, most notably Microsoft. So even though the - "deflate" transfer encoding using the zlib format would be the more - efficient approach (and in fact exactly what the zlib format was designed - for), using the "gzip" transfer encoding is probably more reliable due to - an unfortunate choice of name on the part of the HTTP 1.1 authors. - - Bottom line: use the gzip format for HTTP 1.1 encoding. - -40. Does zlib support the new "Deflate64" format introduced by PKWare? - - No. PKWare has apparently decided to keep that format proprietary, since - they have not documented it as they have previous compression formats. In - any case, the compression improvements are so modest compared to other more - modern approaches, that it's not worth the effort to implement. - -41. I'm having a problem with the zip functions in zlib, can you help? - - There are no zip functions in zlib. You are probably using minizip by - Giles Vollant, which is found in the contrib directory of zlib. It is not - part of zlib. In fact none of the stuff in contrib is part of zlib. The - files in there are not supported by the zlib authors. You need to contact - the authors of the respective contribution for help. - -42. The match.asm code in contrib is under the GNU General Public License. - Since it's part of zlib, doesn't that mean that all of zlib falls under the - GNU GPL? - - No. The files in contrib are not part of zlib. They were contributed by - other authors and are provided as a convenience to the user within the zlib - distribution. Each item in contrib has its own license. - -43. Is zlib subject to export controls? What is its ECCN? - - zlib is not subject to export controls, and so is classified as EAR99. - -44. Can you please sign these lengthy legal documents and fax them back to us - so that we can use your software in our product? - - No. Go away. Shoo. diff --git a/libs/zlibng/INDEX.md b/libs/zlibng/INDEX.md deleted file mode 100644 index 5be081c4e1..0000000000 --- a/libs/zlibng/INDEX.md +++ /dev/null @@ -1,37 +0,0 @@ -Contents --------- - -| Name | Description | -|:-----------------|:---------------------------------------------------------------| -| arch/ | Architecture-specific code | -| doc/ | Documentation for formats and algorithms | -| test/example.c | Zlib usages examples for build testing | -| test/minigzip.c | Minimal gzip-like functionality for build testing | -| test/infcover.c | Inflate code coverage for build testing | -| win32/ | Shared library version resources for Windows | -| CMakeLists.txt | Cmake build script | -| configure | Bash configure/build script | -| adler32.c | Compute the Adler-32 checksum of a data stream | -| chunkset.* | Inline functions to copy small data chunks | -| compress.c | Compress a memory buffer | -| deflate.* | Compress data using the deflate algorithm | -| deflate_fast.c | Compress data using the deflate algorithm with fast strategy | -| deflate_medium.c | Compress data using the deflate algorithm with medium strategy | -| deflate_slow.c | Compress data using the deflate algorithm with slow strategy | -| functable.* | Struct containing function pointers to optimized functions | -| gzguts.h | Internal definitions for gzip operations | -| gzlib.c | Functions common to reading and writing gzip files | -| gzread.c | Read gzip files | -| gzwrite.c | Write gzip files | -| infback.* | Inflate using a callback interface | -| inflate.* | Decompress data | -| inffast.* | Decompress data with speed optimizations | -| inffixed_tbl.h | Table for decoding fixed codes | -| inftrees.h | Generate Huffman trees for efficient decoding | -| trees.* | Output deflated data using Huffman coding | -| uncompr.c | Decompress a memory buffer | -| zconf.h.cmakein | zconf.h template for cmake | -| zendian.h | BYTE_ORDER for endian tests | -| zlib.3 | Man page for zlib | -| zlib.map | Linux symbol information | -| zlib.pc.in | Pkg-config template | diff --git a/libs/zlibng/LICENSE.md b/libs/zlibng/LICENSE.md deleted file mode 100644 index adb48d4729..0000000000 --- a/libs/zlibng/LICENSE.md +++ /dev/null @@ -1,19 +0,0 @@ -(C) 1995-2013 Jean-loup Gailly and Mark Adler - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - -3. This notice may not be removed or altered from any source distribution. diff --git a/libs/zlibng/Makefile.in b/libs/zlibng/Makefile.in deleted file mode 100644 index 8de3192c98..0000000000 --- a/libs/zlibng/Makefile.in +++ /dev/null @@ -1,441 +0,0 @@ -# Makefile for zlib -# Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler -# For conditions of distribution and use, see copyright notice in zlib.h - -# To compile and test, type: -# ./configure; make test -# Normally configure builds both a static and a shared library. -# If you want to build just a static library, use: ./configure --static - -# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: -# make install -# To install in $HOME instead of /usr/local, use: -# make install prefix=$HOME - -CC=cc - -CFLAGS=-O -#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-g -DZLIB_DEBUG -#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ -# -Wstrict-prototypes -Wmissing-prototypes - -SFLAGS=-O -LDFLAGS=-L. -LIBNAME1=libz-ng -LIBNAME2=zlib-ng -SUFFIX=-ng -TEST_LIBS=$(LIBNAME1).a -LDSHARED=$(CC) -LDSHAREDFLAGS=-shared - -VER=2.0.0-RC2 -VER1=2 - -STATICLIB=$(LIBNAME1).a -SHAREDLIB=$(LIBNAME1).so -SHAREDLIBV=$(LIBNAME1).so.$(VER) -SHAREDLIBM=$(LIBNAME1).so.$(VER1) -IMPORTLIB= -SHAREDTARGET=$(LIBNAME1).so.$(VER) -PKGFILE=$(LIBNAME2).pc - -LIBS=$(STATICLIB) $(SHAREDTARGET) - -AR=ar -ARFLAGS=rc -DEFFILE= -RC= -RCFLAGS= -RCOBJS= -STRIP= -RANLIB=ranlib -LDCONFIG=ldconfig -LDSHAREDLIBC= -EXE= - -SRCDIR=. -INCLUDES=-I$(SRCDIR) - -ARCHDIR=arch/generic -ARCH_STATIC_OBJS= -ARCH_SHARED_OBJS= - -prefix = /usr/local -exec_prefix = ${prefix} -bindir = ${exec_prefix}/bin -libdir = ${exec_prefix}/lib -sharedlibdir = ${libdir} -includedir = ${prefix}/include -mandir = ${prefix}/share/man -man3dir = ${mandir}/man3 -pkgconfigdir = ${libdir}/pkgconfig - -OBJZ = \ - adler32.o \ - chunkset.o \ - compare258.o \ - compress.o \ - crc32.o \ - crc32_comb.o \ - deflate.o \ - deflate_fast.o \ - deflate_medium.o \ - deflate_quick.o \ - deflate_slow.o \ - functable.o \ - infback.o \ - inffast.o \ - inflate.o \ - inftrees.o \ - insert_string.o \ - trees.o \ - uncompr.o \ - zutil.o \ - $(ARCH_STATIC_OBJS) - -OBJG = \ - gzlib.o \ - gzread.o \ - gzwrite.o - -OBJC = $(OBJZ) $(OBJG) - -PIC_OBJZ = \ - adler32.lo \ - chunkset.lo \ - compare258.lo \ - compress.lo \ - crc32.lo \ - crc32_comb.lo \ - deflate.lo \ - deflate_fast.lo \ - deflate_medium.lo \ - deflate_quick.lo \ - deflate_slow.lo \ - functable.lo \ - infback.lo \ - inffast.lo \ - inflate.lo \ - inftrees.lo \ - insert_string.lo \ - trees.lo \ - uncompr.lo \ - zutil.lo \ - $(ARCH_SHARED_OBJS) - -PIC_OBJG = \ - gzlib.lo \ - gzread.lo \ - gzwrite.lo - -PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG) - -OBJS = $(OBJC) - -PIC_OBJS = $(PIC_OBJC) - -all: static shared - -static: adler32_test$(EXE) example$(EXE) minigzip$(EXE) fuzzers makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) - -shared: adler32_testsh$(EXE) examplesh$(EXE) minigzipsh$(EXE) - -check: test - -.SECONDARY: - -$(ARCHDIR)/%.o: $(SRCDIR)/$(ARCHDIR)/%.c - $(MAKE) -C $(ARCHDIR) $(notdir $@) - -$(ARCHDIR)/%.lo: $(SRCDIR)/$(ARCHDIR)/%.c - $(MAKE) -C $(ARCHDIR) $(notdir $@) - -%.o: $(ARCHDIR)/%.o - -cp $< $@ - -%.lo: $(ARCHDIR)/%.lo - -cp $< $@ - -test: all - $(MAKE) -C test - -# This variable is set by configure. -WITH_FUZZERS= - -# By default, use our own standalone_fuzz_target_runner. -# This runner does no fuzzing, but simply executes the inputs -# provided via parameters. -# Run e.g. "make all LIB_FUZZING_ENGINE=/path/to/libFuzzer.a" -# to link the fuzzer(s) against a real fuzzing engine. -ifeq (,$(LIB_FUZZING_ENGINE)) - LIB_FUZZING_ENGINE = standalone_fuzz_target_runner.o -else - # OSS-Fuzz will define its own value for LIB_FUZZING_ENGINE. - WITH_FUZZERS=1 -endif - -ifeq (1,$(WITH_FUZZERS)) -fuzzers: checksum_fuzzer$(EXE) compress_fuzzer$(EXE) example_small_fuzzer$(EXE) example_large_fuzzer$(EXE) example_flush_fuzzer$(EXE) example_dict_fuzzer$(EXE) minigzip_fuzzer$(EXE) -else -fuzzers: -endif - -# The standalone fuzz target runner. -standalone_fuzz_target_runner.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -checksum_fuzzer.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -compress_fuzzer.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -example_small_fuzzer.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -example_large_fuzzer.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -example_flush_fuzzer.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -example_dict_fuzzer.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -minigzip_fuzzer.o: - $(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $< -checksum_fuzzer$(EXE): checksum_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) checksum_fuzzer.o $(STATICLIB) -lpthread -compress_fuzzer$(EXE): compress_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) compress_fuzzer.o $(STATICLIB) -lpthread -example_small_fuzzer$(EXE): example_small_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_small_fuzzer.o $(STATICLIB) -lpthread -example_large_fuzzer$(EXE): example_large_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_large_fuzzer.o $(STATICLIB) -lpthread -example_flush_fuzzer$(EXE): example_flush_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_flush_fuzzer.o $(STATICLIB) -lpthread -example_dict_fuzzer$(EXE): example_dict_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_dict_fuzzer.o $(STATICLIB) -lpthread -minigzip_fuzzer$(EXE): minigzip_fuzzer.o standalone_fuzz_target_runner.o $(OBJG) $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) minigzip_fuzzer.o $(OBJG) $(STATICLIB) -lpthread - -infcover.o: $(SRCDIR)/test/infcover.c $(SRCDIR)/zlib$(SUFFIX).h zconf$(SUFFIX).h - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/infcover.c - -infcover$(EXE): infcover.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ infcover.o $(STATICLIB) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - -cover: infcover$(EXE) - rm -f *.gcda - ./infcover - gcov inf*.c - -$(STATICLIB): $(OBJS) - $(AR) $(ARFLAGS) $@ $(OBJS) - -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 - -adler32_test.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/adler32_test.c - -example.o: - $(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $(SRCDIR)/test/example.c - -minigzip.o: - $(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $(SRCDIR)/test/minigzip.c - -makefixed.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/tools/makefixed.c - -maketrees.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/tools/maketrees.c - -makecrct.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/tools/makecrct.c - -zlibrc.o: win32/zlib$(SUFFIX)1.rc - $(RC) $(RCFLAGS) -o $@ win32/zlib$(SUFFIX)1.rc - -.SUFFIXES: .lo - -%.o: $(SRCDIR)/%.c - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< - -%.lo: $(SRCDIR)/%.c - $(CC) $(SFLAGS) -DPIC $(INCLUDES) -c -o $@ $< - -$(OBJG): %.o: $(SRCDIR)/%.c - $(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $< - -$(SHAREDTARGET): $(PIC_OBJS) $(DEFFILE) $(RCOBJS) -ifneq ($(SHAREDTARGET),) - $(LDSHARED) $(CFLAGS) $(LDSHAREDFLAGS) $(LDFLAGS) -o $@ $(DEFFILE) $(PIC_OBJS) $(RCOBJS) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif -ifneq ($(SHAREDLIB),$(SHAREDTARGET)) - rm -f $(SHAREDLIB) $(SHAREDLIBM) - ln -s $@ $(SHAREDLIB) - ln -s $@ $(SHAREDLIBM) -endif -endif - -adler32_test$(EXE): adler32_test.o $(OBJG) $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ adler32_test.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - -example$(EXE): example.o $(OBJG) $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - -minigzip$(EXE): minigzip.o $(OBJG) $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - -adler32_testsh$(EXE): adler32_test.o $(OBJG) $(SHAREDTARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ adler32_test.o $(OBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - -examplesh$(EXE): example.o $(OBJG) $(SHAREDTARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(OBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - -minigzipsh$(EXE): minigzip.o $(OBJG) $(SHAREDTARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(OBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - -makefixed$(EXE): makefixed.o $(OBJG) $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ makefixed.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - -maketrees$(EXE): maketrees.o $(OBJG) $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ maketrees.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - -makecrct$(EXE): makecrct.o $(OBJG) $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ makecrct.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - -install-shared: $(SHAREDTARGET) -ifneq ($(SHAREDTARGET),) - -@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi - rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDTARGET) - cp $(SHAREDTARGET) $(DESTDIR)$(sharedlibdir) - chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDTARGET) -ifneq ($(SHAREDLIB),$(SHAREDTARGET)) - rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM) - ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) - ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM) - ($(LDCONFIG) || true) >/dev/null 2>&1 -# ldconfig is for Linux -endif -ifneq ($(IMPORTLIB),) - cp $(IMPORTLIB) $(DESTDIR)$(sharedlibdir) - chmod 644 $(DESTDIR)$(sharedlibdir)/$(IMPORTLIB) -endif -endif - -install-static: $(STATICLIB) - -@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi - rm -f $(DESTDIR)$(libdir)/$(STATICLIB) - cp $(STATICLIB) $(DESTDIR)$(libdir) - chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB) - -@($(RANLIB) $(DESTDIR)$(libdir)/$(STATICLIB) || true) >/dev/null 2>&1 -# The ranlib in install-static is needed on NeXTSTEP which checks file times - -install-libs: install-shared install-static - -@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi - -@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi - rm -f $(DESTDIR)$(man3dir)/zlib$(SUFFIX).3 - cp $(SRCDIR)/zlib.3 $(DESTDIR)$(man3dir)/zlib$(SUFFIX).3 - chmod 644 $(DESTDIR)$(man3dir)/zlib$(SUFFIX).3 - rm -f $(DESTDIR)$(pkgconfigdir)/$(PKGFILE) - cp $(PKGFILE) $(DESTDIR)$(pkgconfigdir) - chmod 644 $(DESTDIR)$(pkgconfigdir)/$(PKGFILE) - -install: install-libs - -@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi - rm -f $(DESTDIR)$(includedir)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).h - cp $(SRCDIR)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zlib$(SUFFIX).h - cp zconf$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).h - chmod 644 $(DESTDIR)$(includedir)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).h - -uninstall-static: - cd $(DESTDIR)$(libdir) && rm -f $(STATICLIB) - -uninstall-shared: -ifneq ($(SHAREDLIB),) - cd $(DESTDIR)$(sharedlibdir) && rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM) -endif -ifneq ($(IMPORTLIB),) - cd $(DESTDIR)$(sharedlibdir) && rm -f $(IMPORTLIB) -endif - -uninstall: uninstall-static uninstall-shared - cd $(DESTDIR)$(includedir) && rm -f zlib$(SUFFIX).h zconf$(SUFFIX).h - cd $(DESTDIR)$(man3dir) && rm -f zlib$(SUFFIX).3 - cd $(DESTDIR)$(pkgconfigdir) && rm -f $(PKGFILE) - -docs: zlib.3.pdf - -zlib.3.pdf: $(SRCDIR)/zlib.3 - groff -mandoc -f H -T ps $(SRCDIR)/zlib.3 | ps2pdf - zlib.3.pdf - -mostlyclean: clean -clean: - @if [ -f $(ARCHDIR)/Makefile ]; then $(MAKE) -C $(ARCHDIR) clean; fi - @if [ -f test/Makefile ]; then $(MAKE) -C test clean; fi - rm -f *.o *.lo *~ \ - adler32_test$(EXE) example$(EXE) minigzip$(EXE) \ - adler32_testsh$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ - checksum_fuzzer$(EXE) compress_fuzzer$(EXE) example_small_fuzzer$(EXE) example_large_fuzzer$(EXE) \ - example_flush_fuzzer$(EXE) example_dict_fuzzer$(EXE) minigzip_fuzzer$(EXE) \ - infcover makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) \ - $(STATICLIB) $(IMPORTLIB) $(SHAREDLIB) $(SHAREDLIBV) $(SHAREDLIBM) \ - foo.gz so_locations \ - _match.s maketree - rm -rf objs - rm -f *.gcda *.gcno *.gcov - rm -f a.out a.exe - rm -f *.pc - rm -f *._h - rm -rf btmp1 btmp2 pkgtmp1 pkgtmp2 - -maintainer-clean: distclean -distclean: clean - @if [ -f $(ARCHDIR)/Makefile ]; then $(MAKE) -C $(ARCHDIR) distclean; fi - @if [ -f test/Makefile ]; then $(MAKE) -C test distclean; fi - rm -f $(PKGFILE) configure.log zconf.h zconf.h.cmakein - -@rm -f .DS_Store -# Reset Makefile if building inside source tree - @if [ -f Makefile.in ]; then \ - printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile ; \ - printf '\ndistclean:\n\t$(MAKE) -f Makefile.in distclean\n' >> Makefile ; \ - touch -r $(SRCDIR)/Makefile.in Makefile ; fi -# Reset zconf.h and zconf.h.cmakein if building inside source tree - @if [ -f zconf.h.in ]; then \ - cp -p $(SRCDIR)/zconf.h.in zconf.h ; \ - grep -v '^#cmakedefine' $(SRCDIR)/zconf.h.in > zconf.h.cmakein &&\ - touch -r $(SRCDIR)/zconf.h.in zconf.h.cmakein ; fi -# Cleanup these files if building outside source tree - @if [ ! -f zlib.3 ]; then rm -f zlib.3.pdf Makefile; fi -# Remove arch and test directory if building outside source tree - @if [ ! -f $(ARCHDIR)/Makefile.in ]; then rm -rf arch; fi - @if [ ! -f test/Makefile.in ]; then rm -rf test; fi - -tags: - etags $(SRCDIR)/*.[ch] diff --git a/libs/zlibng/README.md b/libs/zlibng/README.md deleted file mode 100644 index ad14c3ff42..0000000000 --- a/libs/zlibng/README.md +++ /dev/null @@ -1,206 +0,0 @@ -## zlib-ng -*zlib data compression library for the next generation systems* - -Maintained by Hans Kristian Rosbach - aka Dead2 (zlib-ng àt circlestorm dót org) - -|CI|Status| -|:-|-| -|GitHub Actions|[![Master Branch Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20CMake/badge.svg)](https://github.com/zlib-ng/zlib-ng/actions) [![Master Branch Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20Configure/badge.svg)](https://github.com/zlib-ng/zlib-ng/actions) [![Master Branch Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20NMake/badge.svg)](https://github.com/zlib-ng/zlib-ng/actions)| -|Buildkite|[![Build status](https://badge.buildkite.com/7bb1ef84356d3baee26202706cc053ee1de871c0c712b65d26.svg?branch=develop)](https://buildkite.com/circlestorm-productions/zlib-ng)| -|CodeFactor|[![CodeFactor](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/badge)](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng)| -|OSS-Fuzz|[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/zlib-ng.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:zlib-ng) -|Codecov|[![codecov.io](https://codecov.io/github/zlib-ng/zlib-ng/coverage.svg?branch=develop)](https://codecov.io/github/zlib-ng/zlib-ng/)| - -Features --------- - -* Zlib compatible API with support for dual-linking -* Modernized native API based on zlib API for ease of porting -* Modern C99 syntax and a clean code layout -* Deflate medium and quick algorithms based on Intels zlib fork -* Support for CPU intrinsics when available - * Adler32 implementation using SSSE3, AVX2, Neon & VSX - * CRC32-B implementation using PCLMULQDQ & ACLE - * Hash table implementation using CRC32-C intrinsics on x86 and ARM - * Slide hash implementations using SSE2, AVX2, Neon & VSX - * Compare256/258 implementations using SSE4.2 & AVX2 - * Inflate chunk copying using SSE2, AVX2 & Neon - * Support for hardware-accelerated deflate using IBM Z DFLTCC -* Unaligned memory read/writes and large bit buffer improvements -* Includes improvements from Cloudflare and Intel forks -* Configure, CMake, and NMake build system support -* Comprehensive set of CMake unit tests -* Code sanitizers, fuzzing, and coverage -* GitHub Actions continuous integration on Windows, macOS, and Linux - * Emulated CI for ARM, AARCH64, PPC, PPC64, SPARC64, S390x using qemu - -Fork Motivation ---------------------------- - -The motivation for this fork was due to seeing several 3rd party -contributions containing new optimizations not getting implemented -into the official zlib repository. - -Mark Adler has been maintaining zlib for a very long time, and he has -done a great job and hopefully he will continue for a long time yet. -The idea of zlib-ng is not to replace zlib, but to co-exist as a -drop-in replacement with a lower threshold for code change. - -zlib has a long history and is incredibly portable, even supporting -lots of systems that predate the Internet. This is great, but it does -complicate further development and maintainability. -The zlib code has numerous workarounds for old compilers that do not -understand ANSI-C or to accommodate systems with limitations such as -operating in a 16-bit environment. - -Many of these workarounds are only maintenance burdens, some of them -are pretty huge code-wise. For example, the [v]s[n]printf workaround -code has a whopping 8 different implementations just to cater to -various old compilers. With this many workarounds cluttered throughout -the code, new programmers with an idea/interest for zlib will need -to take some time to figure out why all of these seemingly strange -things are used, and how to work within those confines. - -So I decided to make a fork, merge all the Intel optimizations, merge -the Cloudflare optimizations that did not conflict, plus a couple -of other smaller patches. Then I started cleaning out workarounds, -various dead code, all contrib and example code as there is little -point in having those in this fork for various reasons. - -A lot of improvements have gone into zlib-ng since its start, and -numerous people and companies have contributed both small and big -improvements, or valuable testing. - -Please read LICENSE.md, it is very simple and very liberal. - -Build ------ - -There are two ways to build zlib-ng: - -### Cmake - -To build zlib-ng using the cross-platform makefile generator cmake. - -``` -cmake . -cmake --build . --config Release -ctest --verbose -C Release -``` - -Alternatively, you can use the cmake configuration GUI tool ccmake: - -``` -ccmake . -``` - -### Configure - -To build zlib-ng using the bash configure script: - -``` -./configure -make -make test -``` - -Build Options -------------- -| CMake | configure | Description | Default | -|:-------------------------|:-------------------------|:--------------------------------------------------------------------------------------|---------| -| ZLIB_COMPAT | --zlib-compat | Compile with zlib compatible API | OFF | -| ZLIB_ENABLE_TESTS | | Build test binaries | ON | -| WITH_GZFILEOP | --without-gzfileops | Compile with support for gzFile related functions | ON | -| WITH_OPTIM | --without-optimizations | Build with optimisations | ON | -| WITH_NEW_STRATEGIES | --without-new-strategies | Use new strategies | ON | -| WITH_NATIVE_INSTRUCTIONS | --native | Compiles with full instruction set supported on this host (gcc/clang -march=native) | OFF | -| WITH_SANITIZER | --with-sanitizer | Build with sanitizer (memory, address, undefined) | OFF | -| WITH_FUZZERS | --with-fuzzers | Build test/fuzz | OFF | -| WITH_MAINTAINER_WARNINGS | | Build with project maintainer warnings | OFF | -| WITH_CODE_COVERAGE | | Enable code coverage reporting | OFF | - -Install -------- - -WARNING: We do not recommend manually installing unless you really -know what you are doing, because this can potentially override the system -default zlib library, and any incompatibility or wrong configuration of -zlib-ng can make the whole system unusable, requiring recovery or reinstall. -If you still want a manual install, we recommend using the /opt/ path prefix. - -For Linux distros, an alternative way to use zlib-ng (if compiled in -zlib-compat mode) instead of zlib, is through the use of the -_LD_PRELOAD_ environment variable. If the program is dynamically linked -with zlib, then zlib-ng will temporarily be used instead by the program, -without risking system-wide instability. - -``` -LD_PRELOAD=/opt/zlib-ng/libz.so.1.2.11.zlib-ng /usr/bin/program -``` - -### Cmake - -To install zlib-ng system-wide using cmake: - -``` -cmake --build . --target install -``` - -### Configure - -To install zlib-ng system-wide using the configure script: - -``` -make install -``` - -Contributing ------------- - -Zlib-ng is a aiming to be open to contributions, and we would be -delighted to receive pull requests on github. -Just remember that any code you submit must be your own and it must -be zlib licensed. -Help with testing and reviewing of pull requests etc is also very -much appreciated. - -If you are interested in contributing, please consider joining our -IRC channel #zlib-ng on the Freenode IRC network. - - -Acknowledgments ----------------- - -Thanks to Servebolt.com for sponsoring my maintainership of zlib-ng. - -Thanks go out to all the people and companies who have taken the time -to contribute code reviews, testing and/or patches. Zlib-ng would not -have been nearly as good without you. - -The deflate format used by zlib was defined by Phil Katz. -The deflate and zlib specifications were written by L. Peter Deutsch. - -zlib was originally created by Jean-loup Gailly (compression) -and Mark Adler (decompression). - -Advanced Build Options ----------------------- - -| CMake | configure | Description | Default | -|:--------------------------------|:----------------------|:--------------------------------------------------------------------|------------------------| -| ZLIB_DUAL_LINK | | Dual link tests with system zlib | OFF | -| | --force-sse2 | Assume SSE2 instructions are always available | ON (x86), OFF (x86_64) | -| WITH_AVX2 | | Build with AVX2 intrinsics | ON | -| WITH_SSE2 | | Build with SSE2 intrinsics | ON | -| WITH_SSE4 | | Build with SSE4 intrinsics | ON | -| WITH_PCLMULQDQ | | Build with PCLMULQDQ intrinsics | ON | -| WITH_ACLE | --without-acle | Build with ACLE intrinsics | ON | -| WITH_NEON | --without-neon | Build with NEON intrinsics | ON | -| WITH_POWER8 | | Build with POWER8 optimisations | ON | -| WITH_DFLTCC_DEFLATE | --with-dfltcc-deflate | Use DEFLATE COMPRESSION CALL instruction for compression on IBM Z | OFF | -| WITH_DFLTCC_INFLATE | --with-dfltcc-inflate | Use DEFLATE COMPRESSION CALL instruction for decompression on IBM Z | OFF | -| WITH_UNALIGNED | | Allow optimizations that use unaligned reads if safe on current arch| ON | -| WITH_INFLATE_STRICT | | Build with strict inflate distance checking | OFF | -| WITH_INFLATE_ALLOW_INVALID_DIST | | Build with zero fill for inflate invalid distances | OFF | -| INSTALL_UTILS | | Copy minigzip and minideflate during install | OFF | diff --git a/libs/zlibng/adler32.c b/libs/zlibng/adler32.c deleted file mode 100644 index 7b245fc849..0000000000 --- a/libs/zlibng/adler32.c +++ /dev/null @@ -1,139 +0,0 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2011, 2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "zutil.h" -#include "functable.h" -#include "adler32_p.h" - -/* ========================================================================= */ -Z_INTERNAL uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t len) { - uint32_t sum2; - unsigned n; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (UNLIKELY(len == 1)) - return adler32_len_1(adler, buf, sum2); - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (UNLIKELY(buf == NULL)) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (UNLIKELY(len < 16)) - return adler32_len_16(adler, buf, len, sum2); - - /* do length NMAX blocks -- requires just one modulo operation */ - while (len >= NMAX) { - len -= NMAX; -#ifdef UNROLL_MORE - n = NMAX / 16; /* NMAX is divisible by 16 */ -#else - n = NMAX / 8; /* NMAX is divisible by 8 */ -#endif - do { -#ifdef UNROLL_MORE - DO16(adler, sum2, buf); /* 16 sums unrolled */ - buf += 16; -#else - DO8(adler, sum2, buf, 0); /* 8 sums unrolled */ - buf += 8; -#endif - } while (--n); - adler %= BASE; - sum2 %= BASE; - } - - /* do remaining bytes (less than NMAX, still just one modulo) */ - if (len) { /* avoid modulos if none remaining */ -#ifdef UNROLL_MORE - while (len >= 16) { - len -= 16; - DO16(adler, sum2, buf); - buf += 16; -#else - while (len >= 8) { - len -= 8; - DO8(adler, sum2, buf, 0); - buf += 8; -#endif - } - while (len) { - --len; - adler += *buf++; - sum2 += adler; - } - adler %= BASE; - sum2 %= BASE; - } - - /* return recombined sums */ - return adler | (sum2 << 16); -} - -#ifdef ZLIB_COMPAT -unsigned long Z_EXPORT PREFIX(adler32_z)(unsigned long adler, const unsigned char *buf, size_t len) { - return (unsigned long)functable.adler32((uint32_t)adler, buf, len); -} -#else -uint32_t Z_EXPORT PREFIX(adler32_z)(uint32_t adler, const unsigned char *buf, size_t len) { - return functable.adler32(adler, buf, len); -} -#endif - -/* ========================================================================= */ -#ifdef ZLIB_COMPAT -unsigned long Z_EXPORT PREFIX(adler32)(unsigned long adler, const unsigned char *buf, unsigned int len) { - return (unsigned long)functable.adler32((uint32_t)adler, buf, len); -} -#else -uint32_t Z_EXPORT PREFIX(adler32)(uint32_t adler, const unsigned char *buf, uint32_t len) { - return functable.adler32(adler, buf, len); -} -#endif - -/* ========================================================================= */ -static uint32_t adler32_combine_(uint32_t adler1, uint32_t adler2, z_off64_t len2) { - uint32_t sum1; - uint32_t sum2; - unsigned rem; - - /* for negative len, return invalid adler32 as a clue for debugging */ - if (len2 < 0) - return 0xffffffff; - - /* the derivation of this formula is left as an exercise for the reader */ - len2 %= BASE; /* assumes len2 >= 0 */ - rem = (unsigned)len2; - sum1 = adler1 & 0xffff; - sum2 = rem * sum1; - sum2 %= BASE; - sum1 += (adler2 & 0xffff) + BASE - 1; - sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; - if (sum1 >= BASE) sum1 -= BASE; - if (sum1 >= BASE) sum1 -= BASE; - if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); - if (sum2 >= BASE) sum2 -= BASE; - return sum1 | (sum2 << 16); -} - -/* ========================================================================= */ -#ifdef ZLIB_COMPAT -unsigned long Z_EXPORT PREFIX(adler32_combine)(unsigned long adler1, unsigned long adler2, z_off_t len2) { - return (unsigned long)adler32_combine_((uint32_t)adler1, (uint32_t)adler2, len2); -} - -unsigned long Z_EXPORT PREFIX4(adler32_combine)(unsigned long adler1, unsigned long adler2, z_off64_t len2) { - return (unsigned long)adler32_combine_((uint32_t)adler1, (uint32_t)adler2, len2); -} -#else -uint32_t Z_EXPORT PREFIX4(adler32_combine)(uint32_t adler1, uint32_t adler2, z_off64_t len2) { - return adler32_combine_(adler1, adler2, len2); -} -#endif diff --git a/libs/zlibng/adler32_p.h b/libs/zlibng/adler32_p.h deleted file mode 100644 index 7f75c71e2e..0000000000 --- a/libs/zlibng/adler32_p.h +++ /dev/null @@ -1,53 +0,0 @@ -/* adler32_p.h -- Private inline functions and macros shared with - * different computation of the Adler-32 checksum - * of a data stream. - * Copyright (C) 1995-2011, 2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef ADLER32_P_H -#define ADLER32_P_H - -#define BASE 65521U /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#define DO1(sum1, sum2, buf, i) {(sum1) += buf[(i)]; (sum2) += (sum1);} -#define DO2(sum1, sum2, buf, i) {DO1(sum1, sum2, buf, i); DO1(sum1, sum2, buf, i+1);} -#define DO4(sum1, sum2, buf, i) {DO2(sum1, sum2, buf, i); DO2(sum1, sum2, buf, i+2);} -#define DO8(sum1, sum2, buf, i) {DO4(sum1, sum2, buf, i); DO4(sum1, sum2, buf, i+4);} -#define DO16(sum1, sum2, buf) {DO8(sum1, sum2, buf, 0); DO8(sum1, sum2, buf, 8);} - -static inline uint32_t adler32_len_1(uint32_t adler, const unsigned char *buf, uint32_t sum2) { - adler += buf[0]; - if (adler >= BASE) - adler -= BASE; - sum2 += adler; - if (sum2 >= BASE) - sum2 -= BASE; - return adler | (sum2 << 16); -} - -static inline uint32_t adler32_len_16(uint32_t adler, const unsigned char *buf, size_t len, uint32_t sum2) { - while (len) { - --len; - adler += *buf++; - sum2 += adler; - } - if (adler >= BASE) - adler -= BASE; - sum2 %= BASE; /* only added so many BASE's */ - return adler | (sum2 << 16); -} - -static inline uint32_t adler32_len_64(uint32_t adler, const unsigned char *buf, size_t len, uint32_t sum2) { - while (len >= 16) { - len -= 16; - DO16(adler, sum2, buf); - buf += 16; - } - /* Process tail (len < 16). */ - return adler32_len_16(adler, buf, len, sum2); -} - -#endif /* ADLER32_P_H */ diff --git a/libs/zlibng/arch/.gitignore b/libs/zlibng/arch/.gitignore deleted file mode 100644 index 2c3af0a08c..0000000000 --- a/libs/zlibng/arch/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# ignore Makefiles; they're all automatically generated -Makefile diff --git a/libs/zlibng/arch/arm/Makefile.in b/libs/zlibng/arch/arm/Makefile.in deleted file mode 100644 index a728d5ab24..0000000000 --- a/libs/zlibng/arch/arm/Makefile.in +++ /dev/null @@ -1,68 +0,0 @@ -# Makefile for zlib -# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler -# For conditions of distribution and use, see copyright notice in zlib.h - -CC= -CFLAGS= -SFLAGS= -INCLUDES= -ACLEFLAG= -NEONFLAG= -SUFFIX= - -SRCDIR=. -SRCTOP=../.. -TOPDIR=$(SRCTOP) - -all: \ - adler32_neon.o adler32_neon.lo \ - armfeature.o armfeature.lo \ - chunkset_neon.o chunkset_neon.lo \ - crc32_acle.o crc32_acle.lo \ - slide_neon.o slide_neon.lo \ - insert_string_acle.o insert_string_acle.lo - -adler32_neon.o: - $(CC) $(CFLAGS) $(NEONFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_neon.c - -adler32_neon.lo: - $(CC) $(SFLAGS) $(NEONFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_neon.c - -armfeature.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/armfeature.c - -armfeature.lo: - $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/armfeature.c - -chunkset_neon.o: - $(CC) $(CFLAGS) $(NEONFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_neon.c - -chunkset_neon.lo: - $(CC) $(SFLAGS) $(NEONFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_neon.c - -crc32_acle.o: - $(CC) $(CFLAGS) $(ACLEFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c - -crc32_acle.lo: - $(CC) $(SFLAGS) $(ACLEFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c - -slide_neon.o: - $(CC) $(CFLAGS) $(NEONFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_neon.c - -slide_neon.lo: - $(CC) $(SFLAGS) $(NEONFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_neon.c - -insert_string_acle.o: - $(CC) $(CFLAGS) $(ACLEFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c - -insert_string_acle.lo: - $(CC) $(SFLAGS) $(ACLEFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c - -mostlyclean: clean -clean: - rm -f *.o *.lo *~ - rm -rf objs - rm -f *.gcda *.gcno *.gcov - -distclean: - rm -f Makefile diff --git a/libs/zlibng/arch/arm/adler32_neon.c b/libs/zlibng/arch/arm/adler32_neon.c deleted file mode 100644 index adda6f61d8..0000000000 --- a/libs/zlibng/arch/arm/adler32_neon.c +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (C) 1995-2011, 2016 Mark Adler - * Copyright (C) 2017 ARM Holdings Inc. - * Author: Adenilson Cavalcanti - * - * For conditions of distribution and use, see copyright notice in zlib.h - */ -#ifdef ARM_NEON_ADLER32 -#ifdef _M_ARM64 -# include -#else -# include -#endif -#include "../../zutil.h" -#include "../../adler32_p.h" - -static void NEON_accum32(uint32_t *s, const unsigned char *buf, size_t len) { - static const uint8_t taps[32] = { - 32, 31, 30, 29, 28, 27, 26, 25, - 24, 23, 22, 21, 20, 19, 18, 17, - 16, 15, 14, 13, 12, 11, 10, 9, - 8, 7, 6, 5, 4, 3, 2, 1 }; - - uint32x2_t adacc2, s2acc2, as; - uint8x16_t t0 = vld1q_u8(taps), t1 = vld1q_u8(taps + 16); - - uint32x4_t adacc = vdupq_n_u32(0), s2acc = vdupq_n_u32(0); - adacc = vsetq_lane_u32(s[0], adacc, 0); - s2acc = vsetq_lane_u32(s[1], s2acc, 0); - - while (len >= 2) { - uint8x16_t d0 = vld1q_u8(buf), d1 = vld1q_u8(buf + 16); - uint16x8_t adler, sum2; - s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 5)); - adler = vpaddlq_u8( d0); - adler = vpadalq_u8(adler, d1); - sum2 = vmull_u8( vget_low_u8(t0), vget_low_u8(d0)); - sum2 = vmlal_u8(sum2, vget_high_u8(t0), vget_high_u8(d0)); - sum2 = vmlal_u8(sum2, vget_low_u8(t1), vget_low_u8(d1)); - sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d1)); - adacc = vpadalq_u16(adacc, adler); - s2acc = vpadalq_u16(s2acc, sum2); - len -= 2; - buf += 32; - } - - while (len > 0) { - uint8x16_t d0 = vld1q_u8(buf); - uint16x8_t adler, sum2; - s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 4)); - adler = vpaddlq_u8(d0); - sum2 = vmull_u8( vget_low_u8(t1), vget_low_u8(d0)); - sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d0)); - adacc = vpadalq_u16(adacc, adler); - s2acc = vpadalq_u16(s2acc, sum2); - buf += 16; - len--; - } - - adacc2 = vpadd_u32(vget_low_u32(adacc), vget_high_u32(adacc)); - s2acc2 = vpadd_u32(vget_low_u32(s2acc), vget_high_u32(s2acc)); - as = vpadd_u32(adacc2, s2acc2); - s[0] = vget_lane_u32(as, 0); - s[1] = vget_lane_u32(as, 1); -} - -static void NEON_handle_tail(uint32_t *pair, const unsigned char *buf, size_t len) { - unsigned int i; - for (i = 0; i < len; ++i) { - pair[0] += buf[i]; - pair[1] += pair[0]; - } -} - -uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len) { - /* split Adler-32 into component sums */ - uint32_t sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (len == 1) - return adler32_len_1(adler, buf, sum2); - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (buf == NULL) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (len < 16) - return adler32_len_16(adler, buf, len, sum2); - - uint32_t pair[2]; - int n = NMAX; - unsigned int done = 0; - unsigned int i; - - /* Split Adler-32 into component sums, it can be supplied by - * the caller sites (e.g. in a PNG file). - */ - pair[0] = adler; - pair[1] = sum2; - - for (i = 0; i < len; i += n) { - if ((i + n) > len) - n = (int)(len - i); - - if (n < 16) - break; - - NEON_accum32(pair, buf + i, n / 16); - pair[0] %= BASE; - pair[1] %= BASE; - - done += (n / 16) * 16; - } - - /* Handle the tail elements. */ - if (done < len) { - NEON_handle_tail(pair, (buf + done), len - done); - pair[0] %= BASE; - pair[1] %= BASE; - } - - /* D = B * 65536 + A, see: https://en.wikipedia.org/wiki/Adler-32. */ - return (pair[1] << 16) | pair[0]; -} -#endif diff --git a/libs/zlibng/arch/arm/arm.h b/libs/zlibng/arch/arm/arm.h deleted file mode 100644 index 378006efbd..0000000000 --- a/libs/zlibng/arch/arm/arm.h +++ /dev/null @@ -1,13 +0,0 @@ -/* arm.h -- check for ARM features. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef ARM_H_ -#define ARM_H_ - -extern int arm_cpu_has_neon; -extern int arm_cpu_has_crc32; - -void Z_INTERNAL arm_check_features(void); - -#endif /* ARM_H_ */ diff --git a/libs/zlibng/arch/arm/armfeature.c b/libs/zlibng/arch/arm/armfeature.c deleted file mode 100644 index cf31a48f0c..0000000000 --- a/libs/zlibng/arch/arm/armfeature.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "../../zutil.h" - -#if defined(__linux__) -# include -# include -#elif defined(__FreeBSD__) && defined(__aarch64__) -# include -# ifndef ID_AA64ISAR0_CRC32_VAL -# define ID_AA64ISAR0_CRC32_VAL ID_AA64ISAR0_CRC32 -# endif -#elif defined(__APPLE__) -# include -#elif defined(_WIN32) -# include -#endif - -static int arm_has_crc32() { -#if defined(__linux__) && defined(HWCAP2_CRC32) - return (getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0 ? 1 : 0; -#elif defined(__FreeBSD__) && defined(__aarch64__) - return getenv("QEMU_EMULATING") == NULL - && ID_AA64ISAR0_CRC32_VAL(READ_SPECIALREG(id_aa64isar0_el1)) >= ID_AA64ISAR0_CRC32_BASE; -#elif defined(__APPLE__) - int hascrc32; - size_t size = sizeof(hascrc32); - return sysctlbyname("hw.optional.armv8_crc32", &hascrc32, &size, NULL, 0) == 0 - && hascrc32 == 1; -#elif defined(ARM_NOCHECK_ACLE) - return 1; -#else - return 0; -#endif -} - -/* AArch64 has neon. */ -#if !defined(__aarch64__) && !defined(_M_ARM64) -static inline int arm_has_neon() { -#if defined(__linux__) && defined(HWCAP_NEON) - return (getauxval(AT_HWCAP) & HWCAP_NEON) != 0 ? 1 : 0; -#elif defined(__APPLE__) - int hasneon; - size_t size = sizeof(hasneon); - return sysctlbyname("hw.optional.neon", &hasneon, &size, NULL, 0) == 0 - && hasneon == 1; -#elif defined(_M_ARM) && defined(WINAPI_FAMILY_PARTITION) -# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) - return 1; /* Always supported */ -# endif -#endif - -#if defined(ARM_NOCHECK_NEON) - return 1; -#else - return 0; -#endif -} -#endif - -Z_INTERNAL int arm_cpu_has_neon; -Z_INTERNAL int arm_cpu_has_crc32; - -void Z_INTERNAL arm_check_features(void) { -#if defined(__aarch64__) || defined(_M_ARM64) - arm_cpu_has_neon = 1; /* always available */ -#else - arm_cpu_has_neon = arm_has_neon(); -#endif - arm_cpu_has_crc32 = arm_has_crc32(); -} diff --git a/libs/zlibng/arch/arm/chunkset_neon.c b/libs/zlibng/arch/arm/chunkset_neon.c deleted file mode 100644 index e9cbcb1bab..0000000000 --- a/libs/zlibng/arch/arm/chunkset_neon.c +++ /dev/null @@ -1,54 +0,0 @@ -/* chunkset_neon.c -- NEON inline functions to copy small data chunks. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifdef ARM_NEON_CHUNKSET -#ifdef _M_ARM64 -# include -#else -# include -#endif -#include "../../zbuild.h" -#include "../../zutil.h" - -typedef uint8x16_t chunk_t; - -#define HAVE_CHUNKMEMSET_1 -#define HAVE_CHUNKMEMSET_2 -#define HAVE_CHUNKMEMSET_4 -#define HAVE_CHUNKMEMSET_8 - -static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { - *chunk = vld1q_dup_u8(from); -} - -static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { - *chunk = vreinterpretq_u8_s16(vdupq_n_s16(*(int16_t *)from)); -} - -static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { - *chunk = vreinterpretq_u8_s32(vdupq_n_s32(*(int32_t *)from)); -} - -static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { - *chunk = vcombine_u8(vld1_u8(from), vld1_u8(from)); -} - -#define CHUNKSIZE chunksize_neon -#define CHUNKCOPY chunkcopy_neon -#define CHUNKCOPY_SAFE chunkcopy_safe_neon -#define CHUNKUNROLL chunkunroll_neon -#define CHUNKMEMSET chunkmemset_neon -#define CHUNKMEMSET_SAFE chunkmemset_safe_neon - -static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { - *chunk = vld1q_u8(s); -} - -static inline void storechunk(uint8_t *out, chunk_t *chunk) { - vst1q_u8(out, *chunk); -} - -#include "chunkset_tpl.h" - -#endif diff --git a/libs/zlibng/arch/arm/crc32_acle.c b/libs/zlibng/arch/arm/crc32_acle.c deleted file mode 100644 index 88ba6c38c6..0000000000 --- a/libs/zlibng/arch/arm/crc32_acle.c +++ /dev/null @@ -1,110 +0,0 @@ -/* crc32_acle.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler - * Copyright (C) 2016 Yang Zhang - * For conditions of distribution and use, see copyright notice in zlib.h - * -*/ - -#ifdef ARM_ACLE_CRC_HASH -#ifndef _MSC_VER -# include -#endif -#include "../../zutil.h" - -uint32_t crc32_acle(uint32_t crc, const unsigned char *buf, uint64_t len) { - Z_REGISTER uint32_t c; - Z_REGISTER const uint16_t *buf2; - Z_REGISTER const uint32_t *buf4; - - c = ~crc; - if (len && ((ptrdiff_t)buf & 1)) { - c = __crc32b(c, *buf++); - len--; - } - - if ((len > sizeof(uint16_t)) && ((ptrdiff_t)buf & sizeof(uint16_t))) { - buf2 = (const uint16_t *) buf; - c = __crc32h(c, *buf2++); - len -= sizeof(uint16_t); - buf4 = (const uint32_t *) buf2; - } else { - buf4 = (const uint32_t *) buf; - } - -#if defined(__aarch64__) - if ((len > sizeof(uint32_t)) && ((ptrdiff_t)buf & sizeof(uint32_t))) { - c = __crc32w(c, *buf4++); - len -= sizeof(uint32_t); - } - - const uint64_t *buf8 = (const uint64_t *) buf4; - -#ifdef UNROLL_MORE - while (len >= 4 * sizeof(uint64_t)) { - c = __crc32d(c, *buf8++); - c = __crc32d(c, *buf8++); - c = __crc32d(c, *buf8++); - c = __crc32d(c, *buf8++); - len -= 4 * sizeof(uint64_t); - } -#endif - - while (len >= sizeof(uint64_t)) { - c = __crc32d(c, *buf8++); - len -= sizeof(uint64_t); - } - - if (len >= sizeof(uint32_t)) { - buf4 = (const uint32_t *) buf8; - c = __crc32w(c, *buf4++); - len -= sizeof(uint32_t); - buf2 = (const uint16_t *) buf4; - } else { - buf2 = (const uint16_t *) buf8; - } - - if (len >= sizeof(uint16_t)) { - c = __crc32h(c, *buf2++); - len -= sizeof(uint16_t); - } - - buf = (const unsigned char *) buf2; -#else /* __aarch64__ */ - -# ifdef UNROLL_MORE - while (len >= 8 * sizeof(uint32_t)) { - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - len -= 8 * sizeof(uint32_t); - } -# endif - - while (len >= sizeof(uint32_t)) { - c = __crc32w(c, *buf4++); - len -= sizeof(uint32_t); - } - - if (len >= sizeof(uint16_t)) { - buf2 = (const uint16_t *) buf4; - c = __crc32h(c, *buf2++); - len -= sizeof(uint16_t); - buf = (const unsigned char *) buf2; - } else { - buf = (const unsigned char *) buf4; - } -#endif /* __aarch64__ */ - - if (len) { - c = __crc32b(c, *buf); - } - - c = ~c; - return c; -} -#endif diff --git a/libs/zlibng/arch/arm/ctzl.h b/libs/zlibng/arch/arm/ctzl.h deleted file mode 100644 index 77218deec3..0000000000 --- a/libs/zlibng/arch/arm/ctzl.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef ARM_CTZL_H -#define ARM_CTZL_H - -#include - -#if defined(_MSC_VER) && !defined(__clang__) -static __forceinline unsigned long __builtin_ctzl(unsigned long value) { - return _arm_clz(_arm_rbit(value)); -} -#endif - -#endif diff --git a/libs/zlibng/arch/arm/insert_string_acle.c b/libs/zlibng/arch/arm/insert_string_acle.c deleted file mode 100644 index 2daf9ba3e1..0000000000 --- a/libs/zlibng/arch/arm/insert_string_acle.c +++ /dev/null @@ -1,22 +0,0 @@ -/* insert_string_acle.c -- insert_string variant using ACLE's CRC instructions - * - * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - */ - -#ifdef ARM_ACLE_CRC_HASH -#ifndef _MSC_VER -# include -#endif -#include "../../zbuild.h" -#include "../../deflate.h" - -#define UPDATE_HASH(s, h, val) \ - h = __crc32w(0, val) - -#define INSERT_STRING insert_string_acle -#define QUICK_INSERT_STRING quick_insert_string_acle - -#include "../../insert_string_tpl.h" -#endif diff --git a/libs/zlibng/arch/arm/slide_neon.c b/libs/zlibng/arch/arm/slide_neon.c deleted file mode 100644 index f64fa5b5b4..0000000000 --- a/libs/zlibng/arch/arm/slide_neon.c +++ /dev/null @@ -1,52 +0,0 @@ -/* slide_neon.c -- Optimized hash table shifting for ARM with support for NEON instructions - * Copyright (C) 2017-2020 Mika T. Lindqvist - * - * Authors: - * Mika T. Lindqvist - * Jun He - * - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#if defined(ARM_NEON_SLIDEHASH) -#ifdef _M_ARM64 -# include -#else -# include -#endif -#include "../../zbuild.h" -#include "../../deflate.h" - -/* SIMD version of hash_chain rebase */ -static inline void slide_hash_chain(Pos *table, unsigned int entries, uint16_t window_size) { - Z_REGISTER uint16x8_t v, *p; - Z_REGISTER size_t n; - - size_t size = entries*sizeof(table[0]); - Assert((size % sizeof(uint16x8_t) * 8 == 0), "hash table size err"); - - Assert(sizeof(Pos) == 2, "Wrong Pos size"); - v = vdupq_n_u16(window_size); - - p = (uint16x8_t *)table; - n = size / (sizeof(uint16x8_t) * 8); - do { - p[0] = vqsubq_u16(p[0], v); - p[1] = vqsubq_u16(p[1], v); - p[2] = vqsubq_u16(p[2], v); - p[3] = vqsubq_u16(p[3], v); - p[4] = vqsubq_u16(p[4], v); - p[5] = vqsubq_u16(p[5], v); - p[6] = vqsubq_u16(p[6], v); - p[7] = vqsubq_u16(p[7], v); - p += 8; - } while (--n); -} - -Z_INTERNAL void slide_hash_neon(deflate_state *s) { - unsigned int wsize = s->w_size; - - slide_hash_chain(s->head, HASH_SIZE, wsize); - slide_hash_chain(s->prev, wsize, wsize); -} -#endif diff --git a/libs/zlibng/arch/generic/Makefile.in b/libs/zlibng/arch/generic/Makefile.in deleted file mode 100644 index be8c185454..0000000000 --- a/libs/zlibng/arch/generic/Makefile.in +++ /dev/null @@ -1,21 +0,0 @@ -# Makefile for zlib -# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler -# For conditions of distribution and use, see copyright notice in zlib.h - -CC= -CFLAGS= -SFLAGS= -INCLUDES= - -SRCDIR=. -SRCTOP=../.. -TOPDIR=$(SRCTOP) - -all: - - -mostlyclean: clean -clean: - rm -f *.o *.lo *~ \ - rm -rf objs - rm -f *.gcda *.gcno *.gcov diff --git a/libs/zlibng/arch/power/Makefile.in b/libs/zlibng/arch/power/Makefile.in deleted file mode 100644 index 25ebc9d1d5..0000000000 --- a/libs/zlibng/arch/power/Makefile.in +++ /dev/null @@ -1,49 +0,0 @@ -# Makefile for POWER-specific files -# Copyright (C) 2020 Matheus Castanho , IBM -# For conditions of distribution and use, see copyright notice in zlib.h - -CC= -CFLAGS= -SFLAGS= -INCLUDES= -SUFFIX= - -SRCDIR=. -SRCTOP=../.. -TOPDIR=$(SRCTOP) - -P8FLAGS=-mcpu=power8 - -all: power.o \ - power.lo \ - adler32_power8.o \ - adler32_power8.lo \ - slide_hash_power8.o \ - slide_hash_power8.lo - -power.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/power.c - -power.lo: - $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/power.c - -adler32_power8.o: - $(CC) $(CFLAGS) $(P8FLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_power8.c - -adler32_power8.lo: - $(CC) $(SFLAGS) $(P8FLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_power8.c - -slide_hash_power8.o: - $(CC) $(CFLAGS) $(P8FLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c - -slide_hash_power8.lo: - $(CC) $(SFLAGS) $(P8FLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c - -mostlyclean: clean -clean: - rm -f *.o *.lo *~ - rm -rf objs - rm -f *.gcda *.gcno *.gcov - -distclean: - rm -f Makefile diff --git a/libs/zlibng/arch/power/adler32_power8.c b/libs/zlibng/arch/power/adler32_power8.c deleted file mode 100644 index cda51aa807..0000000000 --- a/libs/zlibng/arch/power/adler32_power8.c +++ /dev/null @@ -1,154 +0,0 @@ -/* Adler32 for POWER8 using VSX instructions. - * Copyright (C) 2020 IBM Corporation - * Author: Rogerio Alves - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Calculate adler32 checksum for 16 bytes at once using POWER8+ VSX (vector) - * instructions. - * - * If adler32 do 1 byte at time on the first iteration s1 is s1_0 (_n means - * iteration n) is the initial value of adler - at start _0 is 1 unless - * adler initial value is different than 1. So s1_1 = s1_0 + c[0] after - * the first calculation. For the iteration s1_2 = s1_1 + c[1] and so on. - * Hence, for iteration N, s1_N = s1_(N-1) + c[N] is the value of s1 on - * after iteration N. - * - * Therefore, for s2 and iteration N, s2_N = s2_0 + N*s1_N + N*c[0] + - * N-1*c[1] + ... + c[N] - * - * In a more general way: - * - * s1_N = s1_0 + sum(i=1 to N)c[i] - * s2_N = s2_0 + N*s1 + sum (i=1 to N)(N-i+1)*c[i] - * - * Where s1_N, s2_N are the values for s1, s2 after N iterations. So if we - * can process N-bit at time we can do this at once. - * - * Since VSX can support 16-bit vector instructions, we can process - * 16-bit at time using N = 16 we have: - * - * s1 = s1_16 = s1_(16-1) + c[16] = s1_0 + sum(i=1 to 16)c[i] - * s2 = s2_16 = s2_0 + 16*s1 + sum(i=1 to 16)(16-i+1)*c[i] - * - * After the first iteration we calculate the adler32 checksum for 16 bytes. - * - * For more background about adler32 please check the RFC: - * https://www.ietf.org/rfc/rfc1950.txt - */ - -#ifdef POWER8_VSX_ADLER32 - -#include -#include "zbuild.h" -#include "zutil.h" -#include "adler32_p.h" - -/* Vector across sum unsigned int (saturate). */ -inline vector unsigned int vec_sumsu(vector unsigned int __a, vector unsigned int __b) { - __b = vec_sld(__a, __a, 8); - __b = vec_add(__b, __a); - __a = vec_sld(__b, __b, 4); - __a = vec_add(__a, __b); - - return __a; -} - -uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, size_t len) { - uint32_t s1 = adler & 0xffff; - uint32_t s2 = (adler >> 16) & 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (UNLIKELY(len == 1)) - return adler32_len_1(s1, buf, s2); - - /* If buffer is empty or len=0 we need to return adler initial value. */ - if (UNLIKELY(buf == NULL)) - return 1; - - /* This is faster than VSX code for len < 64. */ - if (len < 64) - return adler32_len_64(s1, buf, len, s2); - - /* Use POWER VSX instructions for len >= 64. */ - const vector unsigned int v_zeros = { 0 }; - const vector unsigned char v_mul = {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, - 6, 5, 4, 3, 2, 1}; - const vector unsigned char vsh = vec_splat_u8(4); - const vector unsigned int vmask = {0xffffffff, 0x0, 0x0, 0x0}; - vector unsigned int vs1 = { 0 }; - vector unsigned int vs2 = { 0 }; - vector unsigned int vs1_save = { 0 }; - vector unsigned int vsum1, vsum2; - vector unsigned char vbuf; - int n; - - vs1[0] = s1; - vs2[0] = s2; - - /* Do length bigger than NMAX in blocks of NMAX size. */ - while (len >= NMAX) { - len -= NMAX; - n = NMAX / 16; - do { - vbuf = vec_xl(0, (unsigned char *) buf); - vsum1 = vec_sum4s(vbuf, v_zeros); /* sum(i=1 to 16) buf[i]. */ - /* sum(i=1 to 16) buf[i]*(16-i+1). */ - vsum2 = vec_msum(vbuf, v_mul, v_zeros); - /* Save vs1. */ - vs1_save = vec_add(vs1_save, vs1); - /* Accumulate the sums. */ - vs1 = vec_add(vsum1, vs1); - vs2 = vec_add(vsum2, vs2); - - buf += 16; - } while (--n); - /* Once each block of NMAX size. */ - vs1 = vec_sumsu(vs1, vsum1); - vs1_save = vec_sll(vs1_save, vsh); /* 16*vs1_save. */ - vs2 = vec_add(vs1_save, vs2); - vs2 = vec_sumsu(vs2, vsum2); - - /* vs1[0] = (s1_i + sum(i=1 to 16)buf[i]) mod 65521. */ - vs1[0] = vs1[0] % BASE; - /* vs2[0] = s2_i + 16*s1_save + - sum(i=1 to 16)(16-i+1)*buf[i] mod 65521. */ - vs2[0] = vs2[0] % BASE; - - vs1 = vec_and(vs1, vmask); - vs2 = vec_and(vs2, vmask); - vs1_save = v_zeros; - } - - /* len is less than NMAX one modulo is needed. */ - if (len >= 16) { - while (len >= 16) { - len -= 16; - - vbuf = vec_xl(0, (unsigned char *) buf); - - vsum1 = vec_sum4s(vbuf, v_zeros); /* sum(i=1 to 16) buf[i]. */ - /* sum(i=1 to 16) buf[i]*(16-i+1). */ - vsum2 = vec_msum(vbuf, v_mul, v_zeros); - /* Save vs1. */ - vs1_save = vec_add(vs1_save, vs1); - /* Accumulate the sums. */ - vs1 = vec_add(vsum1, vs1); - vs2 = vec_add(vsum2, vs2); - - buf += 16; - } - /* Since the size will be always less than NMAX we do this once. */ - vs1 = vec_sumsu(vs1, vsum1); - vs1_save = vec_sll(vs1_save, vsh); /* 16*vs1_save. */ - vs2 = vec_add(vs1_save, vs2); - vs2 = vec_sumsu(vs2, vsum2); - } - /* Copy result back to s1, s2 (mod 65521). */ - s1 = vs1[0] % BASE; - s2 = vs2[0] % BASE; - - /* Process tail (len < 16).and return */ - return adler32_len_16(s1, buf, len, s2); -} - -#endif /* POWER8_VSX_ADLER32 */ diff --git a/libs/zlibng/arch/power/power.c b/libs/zlibng/arch/power/power.c deleted file mode 100644 index f93b586d50..0000000000 --- a/libs/zlibng/arch/power/power.c +++ /dev/null @@ -1,19 +0,0 @@ -/* POWER feature check - * Copyright (C) 2020 Matheus Castanho , IBM - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include -#include "../../zutil.h" - -Z_INTERNAL int power_cpu_has_arch_2_07; - -void Z_INTERNAL power_check_features(void) { - unsigned long hwcap2; - hwcap2 = getauxval(AT_HWCAP2); - -#ifdef POWER8 - if (hwcap2 & PPC_FEATURE2_ARCH_2_07) - power_cpu_has_arch_2_07 = 1; -#endif -} diff --git a/libs/zlibng/arch/power/power.h b/libs/zlibng/arch/power/power.h deleted file mode 100644 index b36c261410..0000000000 --- a/libs/zlibng/arch/power/power.h +++ /dev/null @@ -1,13 +0,0 @@ -/* power.h -- check for POWER CPU features - * Copyright (C) 2020 Matheus Castanho , IBM - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef POWER_H_ -#define POWER_H_ - -extern int power_cpu_has_arch_2_07; - -void Z_INTERNAL power_check_features(void); - -#endif /* POWER_H_ */ diff --git a/libs/zlibng/arch/power/slide_hash_power8.c b/libs/zlibng/arch/power/slide_hash_power8.c deleted file mode 100644 index b1e30cea09..0000000000 --- a/libs/zlibng/arch/power/slide_hash_power8.c +++ /dev/null @@ -1,60 +0,0 @@ -/* Optimized slide_hash for POWER processors - * Copyright (C) 2019-2020 IBM Corporation - * Author: Matheus Castanho - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifdef POWER8_VSX_SLIDEHASH - -#include -#include "zbuild.h" -#include "deflate.h" - -static inline void slide_hash_power8_loop(deflate_state *s, unsigned n_elems, Pos *table_end) { - vector unsigned short vw, vm, *vp; - unsigned chunks; - - /* Each vector register (chunk) corresponds to 128 bits == 8 Posf, - * so instead of processing each of the n_elems in the hash table - * individually, we can do it in chunks of 8 with vector instructions. - * - * This function is only called from slide_hash_power8(), and both calls - * pass n_elems as a power of 2 higher than 2^7, as defined by - * deflateInit2_(), so n_elems will always be a multiple of 8. */ - chunks = n_elems >> 3; - Assert(n_elems % 8 == 0, "Weird hash table size!"); - - /* This type casting is safe since s->w_size is always <= 64KB - * as defined by deflateInit2_() and Posf == unsigned short */ - vw[0] = (Pos) s->w_size; - vw = vec_splat(vw,0); - - vp = (vector unsigned short *) table_end; - - do { - /* Processing 8 elements at a time */ - vp--; - vm = *vp; - - /* This is equivalent to: m >= w_size ? m - w_size : 0 - * Since we are using a saturated unsigned subtraction, any - * values that are > w_size will be set to 0, while the others - * will be subtracted by w_size. */ - *vp = vec_subs(vm,vw); - } while (--chunks); -} - -void Z_INTERNAL slide_hash_power8(deflate_state *s) { - unsigned int n; - Pos *p; - - n = HASH_SIZE; - p = &s->head[n]; - slide_hash_power8_loop(s,n,p); - - n = s->w_size; - p = &s->prev[n]; - slide_hash_power8_loop(s,n,p); -} - -#endif /* POWER8_VSX_SLIDEHASH */ diff --git a/libs/zlibng/arch/s390/Makefile.in b/libs/zlibng/arch/s390/Makefile.in deleted file mode 100644 index 2652fe62d9..0000000000 --- a/libs/zlibng/arch/s390/Makefile.in +++ /dev/null @@ -1,40 +0,0 @@ -# Makefile for zlib-ng -# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler -# For conditions of distribution and use, see copyright notice in zlib.h - -CC= -CFLAGS= -SFLAGS= -INCLUDES= -SUFFIX= - -SRCDIR=. -SRCTOP=../.. -TOPDIR=$(SRCTOP) - -dfltcc_common.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_common.c - -dfltcc_common.lo: - $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_common.c - -dfltcc_deflate.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_deflate.c - -dfltcc_deflate.lo: - $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_deflate.c - -dfltcc_inflate.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_inflate.c - -dfltcc_inflate.lo: - $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_inflate.c - -mostlyclean: clean -clean: - rm -f *.o *.lo *~ - rm -rf objs - rm -f *.gcda *.gcno *.gcov - -distclean: - rm -f Makefile diff --git a/libs/zlibng/arch/s390/README.md b/libs/zlibng/arch/s390/README.md deleted file mode 100644 index 641c63a832..0000000000 --- a/libs/zlibng/arch/s390/README.md +++ /dev/null @@ -1,216 +0,0 @@ -# Introduction - -This directory contains SystemZ deflate hardware acceleration support. -It can be enabled using the following build commands: - - $ ./configure --with-dfltcc-deflate --with-dfltcc-inflate - $ make - -or - - $ cmake -DWITH_DFLTCC_DEFLATE=1 -DWITH_DFLTCC_INFLATE=1 . - $ make - -When built like this, zlib-ng would compress using hardware on level 1, -and using software on all other levels. Decompression will always happen -in hardware. In order to enable hardware compression for levels 1-6 -(i.e. to make it used by default) one could add -`-DDFLTCC_LEVEL_MASK=0x7e` to CFLAGS when building zlib-ng. - -SystemZ deflate hardware acceleration is available on [IBM z15]( -https://www.ibm.com/products/z15) and newer machines under the name [ -"Integrated Accelerator for zEnterprise Data Compression"]( -https://www.ibm.com/support/z-content-solutions/compression/). The -programming interface to it is a machine instruction called DEFLATE -CONVERSION CALL (DFLTCC). It is documented in Chapter 26 of [Principles -of Operation](http://publibfp.dhe.ibm.com/epubs/pdf/a227832c.pdf). Both -the code and the rest of this document refer to this feature simply as -"DFLTCC". - -# Performance - -Performance figures are published [here]( -https://github.com/iii-i/zlib-ng/wiki/Performance-with-dfltcc-patch-applied-and-dfltcc-support-built-on-dfltcc-enabled-machine -). The compression speed-up can be as high as 110x and the decompression -speed-up can be as high as 15x. - -# Limitations - -Two DFLTCC compression calls with identical inputs are not guaranteed to -produce identical outputs. Therefore care should be taken when using -hardware compression when reproducible results are desired. In -particular, zlib-ng-specific `zng_deflateSetParams` call allows setting -`Z_DEFLATE_REPRODUCIBLE` parameter, which disables DFLTCC support for a -particular stream. - -DFLTCC does not support every single zlib-ng feature, in particular: - -* `inflate(Z_BLOCK)` and `inflate(Z_TREES)` -* `inflateMark()` -* `inflatePrime()` -* `inflateSyncPoint()` - -When used, these functions will either switch to software, or, in case -this is not possible, gracefully fail. - -# Code structure - -All SystemZ-specific code lives in `arch/s390` directory and is -integrated with the rest of zlib-ng using hook macros. - -## Hook macros - -DFLTCC takes as arguments a parameter block, an input buffer, an output -buffer and a window. `ZALLOC_STATE()`, `ZFREE_STATE()`, `ZCOPY_STATE()`, -`ZALLOC_WINDOW()` and `TRY_FREE_WINDOW()` macros encapsulate allocation -details for the parameter block (which is allocated alongside zlib-ng -state) and the window (which must be page-aligned). - -While inflate software and hardware window formats match, this is not -the case for deflate. Therefore, `deflateSetDictionary()` and -`deflateGetDictionary()` need special handling, which is triggered using -`DEFLATE_SET_DICTIONARY_HOOK()` and `DEFLATE_GET_DICTIONARY_HOOK()` -macros. - -`deflateResetKeep()` and `inflateResetKeep()` update the DFLTCC -parameter block using `DEFLATE_RESET_KEEP_HOOK()` and -`INFLATE_RESET_KEEP_HOOK()` macros. - -`INFLATE_PRIME_HOOK()`, `INFLATE_MARK_HOOK()` and -`INFLATE_SYNC_POINT_HOOK()` macros make the respective unsupported -calls gracefully fail. - -`DEFLATE_PARAMS_HOOK()` implements switching between hardware and -software compression mid-stream using `deflateParams()`. Switching -normally entails flushing the current block, which might not be possible -in low memory situations. `deflateParams()` uses `DEFLATE_DONE()` hook -in order to detect and gracefully handle such situations. - -The algorithm implemented in hardware has different compression ratio -than the one implemented in software. `DEFLATE_BOUND_ADJUST_COMPLEN()` -and `DEFLATE_NEED_CONSERVATIVE_BOUND()` macros make `deflateBound()` -return the correct results for the hardware implementation. - -Actual compression and decompression are handled by `DEFLATE_HOOK()` and -`INFLATE_TYPEDO_HOOK()` macros. Since inflation with DFLTCC manages the -window on its own, calling `updatewindow()` is suppressed using -`INFLATE_NEED_UPDATEWINDOW()` macro. - -In addition to compression, DFLTCC computes CRC-32 and Adler-32 -checksums, therefore, whenever it's used, software checksumming is -suppressed using `DEFLATE_NEED_CHECKSUM()` and `INFLATE_NEED_CHECKSUM()` -macros. - -While software always produces reproducible compression results, this -is not the case for DFLTCC. Therefore, zlib-ng users are given the -ability to specify whether or not reproducible compression results -are required. While it is always possible to specify this setting -before the compression begins, it is not always possible to do so in -the middle of a deflate stream - the exact conditions for that are -determined by `DEFLATE_CAN_SET_REPRODUCIBLE()` macro. - -## SystemZ-specific code - -When zlib-ng is built with DFLTCC, the hooks described above are -converted to calls to functions, which are implemented in -`arch/s390/dfltcc_*` files. The functions can be grouped in three broad -categories: - -* Base DFLTCC support, e.g. wrapping the machine instruction - - `dfltcc()` and allocating aligned memory - `dfltcc_alloc_state()`. -* Translating between software and hardware data formats, e.g. - `dfltcc_deflate_set_dictionary()`. -* Translating between software and hardware state machines, e.g. - `dfltcc_deflate()` and `dfltcc_inflate()`. - -The functions from the first two categories are fairly simple, however, -various quirks in both software and hardware state machines make the -functions from the third category quite complicated. - -### `dfltcc_deflate()` function - -This function is called by `deflate()` and has the following -responsibilities: - -* Checking whether DFLTCC can be used with the current stream. If this - is not the case, then it returns `0`, making `deflate()` use some - other function in order to compress in software. Otherwise it returns - `1`. -* Block management and Huffman table generation. DFLTCC ends blocks only - when explicitly instructed to do so by the software. Furthermore, - whether to use fixed or dynamic Huffman tables must also be determined - by the software. Since looking at data in order to gather statistics - would negate performance benefits, the following approach is used: the - first `DFLTCC_FIRST_FHT_BLOCK_SIZE` bytes are placed into a fixed - block, and every next `DFLTCC_BLOCK_SIZE` bytes are placed into - dynamic blocks. -* Writing EOBS. Block Closing Control bit in the parameter block - instructs DFLTCC to write EOBS, however, certain conditions need to be - met: input data length must be non-zero or Continuation Flag must be - set. To put this in simpler terms, DFLTCC will silently refuse to - write EOBS if this is the only thing that it is asked to do. Since the - code has to be able to emit EOBS in software anyway, in order to avoid - tricky corner cases Block Closing Control is never used. Whether to - write EOBS is instead controlled by `soft_bcc` variable. -* Triggering block post-processing. Depending on flush mode, `deflate()` - must perform various additional actions when a block or a stream ends. - `dfltcc_deflate()` informs `deflate()` about this using - `block_state *result` parameter. -* Converting software state fields into hardware parameter block fields, - and vice versa. For example, `wrap` and Check Value Type or `bi_valid` - and Sub-Byte Boundary. Certain fields cannot be translated and must - persist untouched in the parameter block between calls, for example, - Continuation Flag or Continuation State Buffer. -* Handling flush modes and low-memory situations. These aspects are - quite intertwined and pervasive. The general idea here is that the - code must not do anything in software - whether explicitly by e.g. - calling `send_eobs()`, or implicitly - by returning to `deflate()` - with certain return and `*result` values, when Continuation Flag is - set. -* Ending streams. When a new block is started and flush mode is - `Z_FINISH`, Block Header Final parameter block bit is used to mark - this block as final. However, sometimes an empty final block is - needed, and, unfortunately, just like with EOBS, DFLTCC will silently - refuse to do this. The general idea of DFLTCC implementation is to - rely as much as possible on the existing code. Here in order to do - this, the code pretends that it does not support DFLTCC, which makes - `deflate()` call a software compression function, which writes an - empty final block. Whether this is required is controlled by - `need_empty_block` variable. -* Error handling. This is simply converting - Operation-Ending-Supplemental Code to string. Errors can only happen - due to things like memory corruption, and therefore they don't affect - the `deflate()` return code. - -### `dfltcc_inflate()` function - -This function is called by `inflate()` from the `TYPEDO` state (that is, -when all the metadata is parsed and the stream is positioned at the type -bits of deflate block header) and it's responsible for the following: - -* Falling back to software when flush mode is `Z_BLOCK` or `Z_TREES`. - Unfortunately, there is no way to ask DFLTCC to stop decompressing on - block or tree boundary. -* `inflate()` decompression loop management. This is controlled using - the return value, which can be either `DFLTCC_INFLATE_BREAK` or - `DFLTCC_INFLATE_CONTINUE`. -* Converting software state fields into hardware parameter block fields, - and vice versa. For example, `whave` and History Length or `wnext` and - History Offset. -* Ending streams. This instructs `inflate()` to return `Z_STREAM_END` - and is controlled by `last` state field. -* Error handling. Like deflate, error handling comprises - Operation-Ending-Supplemental Code to string conversion. Unlike - deflate, errors may happen due to bad inputs, therefore they are - propagated to `inflate()` by setting `mode` field to `MEM` or `BAD`. - -# Testing - -Given complexity of DFLTCC machine instruction, it is not clear whether -QEMU TCG will ever support it. At the time of writing, one has to have -access to an IBM z15+ VM or LPAR in order to test DFLTCC support. Since -DFLTCC is a non-privileged instruction, neither special VM/LPAR -configuration nor root are required. - -Still, zlib-ng CI has a few QEMU TCG-based configurations that check -whether fallback to software is working. diff --git a/libs/zlibng/arch/s390/dfltcc_common.c b/libs/zlibng/arch/s390/dfltcc_common.c deleted file mode 100644 index c82c3b220c..0000000000 --- a/libs/zlibng/arch/s390/dfltcc_common.c +++ /dev/null @@ -1,89 +0,0 @@ -/* dfltcc_deflate.c - IBM Z DEFLATE CONVERSION CALL general support. */ - -#include "../../zbuild.h" -#include "dfltcc_common.h" -#include "dfltcc_detail.h" - -/* - Memory management. - - DFLTCC requires parameter blocks and window to be aligned. zlib-ng allows - users to specify their own allocation functions, so using e.g. - `posix_memalign' is not an option. Thus, we overallocate and take the - aligned portion of the buffer. -*/ -static inline int is_dfltcc_enabled(void) { - uint64_t facilities[(DFLTCC_FACILITY / 64) + 1]; - Z_REGISTER uint8_t r0 __asm__("r0"); - - memset(facilities, 0, sizeof(facilities)); - r0 = sizeof(facilities) / sizeof(facilities[0]) - 1; - /* STFLE is supported since z9-109 and only in z/Architecture mode. When - * compiling with -m31, gcc defaults to ESA mode, however, since the kernel - * is 64-bit, it's always z/Architecture mode at runtime. - */ - __asm__ volatile( -#ifndef __clang__ - ".machinemode push\n" - ".machinemode zarch\n" -#endif - "stfle %[facilities]\n" -#ifndef __clang__ - ".machinemode pop\n" -#endif - : [facilities] "=Q" (facilities), [r0] "+r" (r0) :: "cc"); - return is_bit_set((const char *)facilities, DFLTCC_FACILITY); -} - -void Z_INTERNAL dfltcc_reset(PREFIX3(streamp) strm, uInt size) { - struct dfltcc_state *dfltcc_state = (struct dfltcc_state *)((char *)strm->state + ALIGN_UP(size, 8)); - struct dfltcc_qaf_param *param = (struct dfltcc_qaf_param *)&dfltcc_state->param; - - /* Initialize available functions */ - if (is_dfltcc_enabled()) { - dfltcc(DFLTCC_QAF, param, NULL, NULL, NULL, NULL, NULL); - memmove(&dfltcc_state->af, param, sizeof(dfltcc_state->af)); - } else - memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af)); - - /* Initialize parameter block */ - memset(&dfltcc_state->param, 0, sizeof(dfltcc_state->param)); - dfltcc_state->param.nt = 1; - - /* Initialize tuning parameters */ - dfltcc_state->level_mask = DFLTCC_LEVEL_MASK; - dfltcc_state->block_size = DFLTCC_BLOCK_SIZE; - dfltcc_state->block_threshold = DFLTCC_FIRST_FHT_BLOCK_SIZE; - dfltcc_state->dht_threshold = DFLTCC_DHT_MIN_SAMPLE_SIZE; - dfltcc_state->param.ribm = DFLTCC_RIBM; -} - -void Z_INTERNAL *dfltcc_alloc_state(PREFIX3(streamp) strm, uInt items, uInt size) { - return ZALLOC(strm, ALIGN_UP(items * size, 8) + sizeof(struct dfltcc_state), sizeof(unsigned char)); -} - -void Z_INTERNAL dfltcc_copy_state(void *dst, const void *src, uInt size) { - memcpy(dst, src, ALIGN_UP(size, 8) + sizeof(struct dfltcc_state)); -} - -static const int PAGE_ALIGN = 0x1000; - -void Z_INTERNAL *dfltcc_alloc_window(PREFIX3(streamp) strm, uInt items, uInt size) { - void *p; - void *w; - - /* To simplify freeing, we store the pointer to the allocated buffer right - * before the window. - */ - p = ZALLOC(strm, sizeof(void *) + items * size + PAGE_ALIGN, sizeof(unsigned char)); - if (p == NULL) - return NULL; - w = ALIGN_UP((char *)p + sizeof(void *), PAGE_ALIGN); - *(void **)((char *)w - sizeof(void *)) = p; - return w; -} - -void Z_INTERNAL dfltcc_free_window(PREFIX3(streamp) strm, void *w) { - if (w) - ZFREE(strm, *(void **)((unsigned char *)w - sizeof(void *))); -} diff --git a/libs/zlibng/arch/s390/dfltcc_common.h b/libs/zlibng/arch/s390/dfltcc_common.h deleted file mode 100644 index 5c3be91b97..0000000000 --- a/libs/zlibng/arch/s390/dfltcc_common.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef DFLTCC_COMMON_H -#define DFLTCC_COMMON_H - -#ifdef ZLIB_COMPAT -#include "../../zlib.h" -#else -#include "../../zlib-ng.h" -#endif -#include "../../zutil.h" - -void Z_INTERNAL *dfltcc_alloc_state(PREFIX3(streamp) strm, uInt items, uInt size); -void Z_INTERNAL dfltcc_copy_state(void *dst, const void *src, uInt size); -void Z_INTERNAL dfltcc_reset(PREFIX3(streamp) strm, uInt size); -void Z_INTERNAL *dfltcc_alloc_window(PREFIX3(streamp) strm, uInt items, uInt size); -void Z_INTERNAL dfltcc_free_window(PREFIX3(streamp) strm, void *w); - -#define ZALLOC_STATE dfltcc_alloc_state - -#define ZFREE_STATE ZFREE - -#define ZCOPY_STATE dfltcc_copy_state - -#define ZALLOC_WINDOW dfltcc_alloc_window - -#define ZFREE_WINDOW dfltcc_free_window - -#define TRY_FREE_WINDOW dfltcc_free_window - -#endif diff --git a/libs/zlibng/arch/s390/dfltcc_deflate.c b/libs/zlibng/arch/s390/dfltcc_deflate.c deleted file mode 100644 index 1878656676..0000000000 --- a/libs/zlibng/arch/s390/dfltcc_deflate.c +++ /dev/null @@ -1,406 +0,0 @@ -/* dfltcc_deflate.c - IBM Z DEFLATE CONVERSION CALL compression support. */ - -/* - Use the following commands to build zlib-ng with DFLTCC compression support: - - $ ./configure --with-dfltcc-deflate - or - - $ cmake -DWITH_DFLTCC_DEFLATE=1 . - - and then - - $ make -*/ - -#include "../../zbuild.h" -#include "../../zutil.h" -#include "../../deflate.h" -#include "../../trees_emit.h" -#include "dfltcc_deflate.h" -#include "dfltcc_detail.h" - -static inline int dfltcc_can_deflate_with_params(PREFIX3(streamp) strm, int level, uInt window_bits, int strategy, - int reproducible) { - deflate_state *state = (deflate_state *)strm->state; - struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - - /* Unsupported compression settings */ - if ((dfltcc_state->level_mask & (1 << level)) == 0) - return 0; - if (window_bits != HB_BITS) - return 0; - if (strategy != Z_FIXED && strategy != Z_DEFAULT_STRATEGY) - return 0; - if (reproducible) - return 0; - - /* Unsupported hardware */ - if (!is_bit_set(dfltcc_state->af.fns, DFLTCC_GDHT) || - !is_bit_set(dfltcc_state->af.fns, DFLTCC_CMPR) || - !is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0)) - return 0; - - return 1; -} - -int Z_INTERNAL dfltcc_can_deflate(PREFIX3(streamp) strm) { - deflate_state *state = (deflate_state *)strm->state; - - return dfltcc_can_deflate_with_params(strm, state->level, state->w_bits, state->strategy, state->reproducible); -} - -static inline void dfltcc_gdht(PREFIX3(streamp) strm) { - deflate_state *state = (deflate_state *)strm->state; - struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param; - size_t avail_in = strm->avail_in; - - dfltcc(DFLTCC_GDHT, param, NULL, NULL, &strm->next_in, &avail_in, NULL); -} - -static inline dfltcc_cc dfltcc_cmpr(PREFIX3(streamp) strm) { - deflate_state *state = (deflate_state *)strm->state; - struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param; - size_t avail_in = strm->avail_in; - size_t avail_out = strm->avail_out; - dfltcc_cc cc; - - cc = dfltcc(DFLTCC_CMPR | HBT_CIRCULAR, - param, &strm->next_out, &avail_out, - &strm->next_in, &avail_in, state->window); - strm->total_in += (strm->avail_in - avail_in); - strm->total_out += (strm->avail_out - avail_out); - strm->avail_in = avail_in; - strm->avail_out = avail_out; - return cc; -} - -static inline void send_eobs(PREFIX3(streamp) strm, const struct dfltcc_param_v0 *param) { - deflate_state *state = (deflate_state *)strm->state; - - send_bits(state, bi_reverse(param->eobs >> (15 - param->eobl), param->eobl), param->eobl, state->bi_buf, state->bi_valid); - flush_pending(strm); - if (state->pending != 0) { - /* The remaining data is located in pending_out[0:pending]. If someone - * calls put_byte() - this might happen in deflate() - the byte will be - * placed into pending_buf[pending], which is incorrect. Move the - * remaining data to the beginning of pending_buf so that put_byte() is - * usable again. - */ - memmove(state->pending_buf, state->pending_out, state->pending); - state->pending_out = state->pending_buf; - } -#ifdef ZLIB_DEBUG - state->compressed_len += param->eobl; -#endif -} - -int Z_INTERNAL dfltcc_deflate(PREFIX3(streamp) strm, int flush, block_state *result) { - deflate_state *state = (deflate_state *)strm->state; - struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - struct dfltcc_param_v0 *param = &dfltcc_state->param; - uInt masked_avail_in; - dfltcc_cc cc; - int need_empty_block; - int soft_bcc; - int no_flush; - - if (!dfltcc_can_deflate(strm)) { - /* Clear history. */ - if (flush == Z_FULL_FLUSH) - param->hl = 0; - return 0; - } - -again: - masked_avail_in = 0; - soft_bcc = 0; - no_flush = flush == Z_NO_FLUSH; - - /* No input data. Return, except when Continuation Flag is set, which means - * that DFLTCC has buffered some output in the parameter block and needs to - * be called again in order to flush it. - */ - if (strm->avail_in == 0 && !param->cf) { - /* A block is still open, and the hardware does not support closing - * blocks without adding data. Thus, close it manually. - */ - if (!no_flush && param->bcf) { - send_eobs(strm, param); - param->bcf = 0; - } - /* Let one of deflate_* functions write a trailing empty block. */ - if (flush == Z_FINISH) - return 0; - /* Clear history. */ - if (flush == Z_FULL_FLUSH) - param->hl = 0; - /* Trigger block post-processing if necessary. */ - *result = no_flush ? need_more : block_done; - return 1; - } - - /* There is an open non-BFINAL block, we are not going to close it just - * yet, we have compressed more than DFLTCC_BLOCK_SIZE bytes and we see - * more than DFLTCC_DHT_MIN_SAMPLE_SIZE bytes. Open a new block with a new - * DHT in order to adapt to a possibly changed input data distribution. - */ - if (param->bcf && no_flush && - strm->total_in > dfltcc_state->block_threshold && - strm->avail_in >= dfltcc_state->dht_threshold) { - if (param->cf) { - /* We need to flush the DFLTCC buffer before writing the - * End-of-block Symbol. Mask the input data and proceed as usual. - */ - masked_avail_in += strm->avail_in; - strm->avail_in = 0; - no_flush = 0; - } else { - /* DFLTCC buffer is empty, so we can manually write the - * End-of-block Symbol right away. - */ - send_eobs(strm, param); - param->bcf = 0; - dfltcc_state->block_threshold = strm->total_in + dfltcc_state->block_size; - } - } - - /* No space for compressed data. If we proceed, dfltcc_cmpr() will return - * DFLTCC_CC_OP1_TOO_SHORT without buffering header bits, but we will still - * set BCF=1, which is wrong. Avoid complications and return early. - */ - if (strm->avail_out == 0) { - *result = need_more; - return 1; - } - - /* The caller gave us too much data. Pass only one block worth of - * uncompressed data to DFLTCC and mask the rest, so that on the next - * iteration we start a new block. - */ - if (no_flush && strm->avail_in > dfltcc_state->block_size) { - masked_avail_in += (strm->avail_in - dfltcc_state->block_size); - strm->avail_in = dfltcc_state->block_size; - } - - /* When we have an open non-BFINAL deflate block and caller indicates that - * the stream is ending, we need to close an open deflate block and open a - * BFINAL one. - */ - need_empty_block = flush == Z_FINISH && param->bcf && !param->bhf; - - /* Translate stream to parameter block */ - param->cvt = state->wrap == 2 ? CVT_CRC32 : CVT_ADLER32; - if (!no_flush) - /* We need to close a block. Always do this in software - when there is - * no input data, the hardware will not honor BCC. */ - soft_bcc = 1; - if (flush == Z_FINISH && !param->bcf) - /* We are about to open a BFINAL block, set Block Header Final bit - * until the stream ends. - */ - param->bhf = 1; - /* DFLTCC-CMPR will write to next_out, so make sure that buffers with - * higher precedence are empty. - */ - Assert(state->pending == 0, "There must be no pending bytes"); - Assert(state->bi_valid < 8, "There must be less than 8 pending bits"); - param->sbb = (unsigned int)state->bi_valid; - if (param->sbb > 0) - *strm->next_out = (unsigned char)state->bi_buf; - /* Honor history and check value */ - param->nt = 0; - param->cv = state->wrap == 2 ? ZSWAP32(strm->adler) : strm->adler; - - /* When opening a block, choose a Huffman-Table Type */ - if (!param->bcf) { - if (state->strategy == Z_FIXED || (strm->total_in == 0 && dfltcc_state->block_threshold > 0)) - param->htt = HTT_FIXED; - else { - param->htt = HTT_DYNAMIC; - dfltcc_gdht(strm); - } - } - - /* Deflate */ - do { - cc = dfltcc_cmpr(strm); - if (strm->avail_in < 4096 && masked_avail_in > 0) - /* We are about to call DFLTCC with a small input buffer, which is - * inefficient. Since there is masked data, there will be at least - * one more DFLTCC call, so skip the current one and make the next - * one handle more data. - */ - break; - } while (cc == DFLTCC_CC_AGAIN); - - /* Translate parameter block to stream */ - strm->msg = oesc_msg(dfltcc_state->msg, param->oesc); - state->bi_valid = param->sbb; - if (state->bi_valid == 0) - state->bi_buf = 0; /* Avoid accessing next_out */ - else - state->bi_buf = *strm->next_out & ((1 << state->bi_valid) - 1); - strm->adler = state->wrap == 2 ? ZSWAP32(param->cv) : param->cv; - - /* Unmask the input data */ - strm->avail_in += masked_avail_in; - masked_avail_in = 0; - - /* If we encounter an error, it means there is a bug in DFLTCC call */ - Assert(cc != DFLTCC_CC_OP2_CORRUPT || param->oesc == 0, "BUG"); - - /* Update Block-Continuation Flag. It will be used to check whether to call - * GDHT the next time. - */ - if (cc == DFLTCC_CC_OK) { - if (soft_bcc) { - send_eobs(strm, param); - param->bcf = 0; - dfltcc_state->block_threshold = strm->total_in + dfltcc_state->block_size; - } else - param->bcf = 1; - if (flush == Z_FINISH) { - if (need_empty_block) - /* Make the current deflate() call also close the stream */ - return 0; - else { - bi_windup(state); - *result = finish_done; - } - } else { - if (flush == Z_FULL_FLUSH) - param->hl = 0; /* Clear history */ - *result = flush == Z_NO_FLUSH ? need_more : block_done; - } - } else { - param->bcf = 1; - *result = need_more; - } - if (strm->avail_in != 0 && strm->avail_out != 0) - goto again; /* deflate() must use all input or all output */ - return 1; -} - -/* - Switching between hardware and software compression. - - DFLTCC does not support all zlib settings, e.g. generation of non-compressed - blocks or alternative window sizes. When such settings are applied on the - fly with deflateParams, we need to convert between hardware and software - window formats. -*/ -static int dfltcc_was_deflate_used(PREFIX3(streamp) strm) { - deflate_state *state = (deflate_state *)strm->state; - struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param; - - return strm->total_in > 0 || param->nt == 0 || param->hl > 0; -} - -int Z_INTERNAL dfltcc_deflate_params(PREFIX3(streamp) strm, int level, int strategy, int *flush) { - deflate_state *state = (deflate_state *)strm->state; - int could_deflate = dfltcc_can_deflate(strm); - int can_deflate = dfltcc_can_deflate_with_params(strm, level, state->w_bits, strategy, state->reproducible); - - if (can_deflate == could_deflate) - /* We continue to work in the same mode - no changes needed */ - return Z_OK; - - if (!dfltcc_was_deflate_used(strm)) - /* DFLTCC was not used yet - no changes needed */ - return Z_OK; - - /* For now, do not convert between window formats - simply get rid of the old data instead */ - *flush = Z_FULL_FLUSH; - return Z_OK; -} - -int Z_INTERNAL dfltcc_deflate_done(PREFIX3(streamp) strm, int flush) { - deflate_state *state = (deflate_state *)strm->state; - struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - struct dfltcc_param_v0 *param = &dfltcc_state->param; - - /* When deflate(Z_FULL_FLUSH) is called with small avail_out, it might - * close the block without resetting the compression state. Detect this - * situation and return that deflation is not done. - */ - if (flush == Z_FULL_FLUSH && strm->avail_out == 0) - return 0; - - /* Return that deflation is not done if DFLTCC is used and either it - * buffered some data (Continuation Flag is set), or has not written EOBS - * yet (Block-Continuation Flag is set). - */ - return !dfltcc_can_deflate(strm) || (!param->cf && !param->bcf); -} - -int Z_INTERNAL dfltcc_can_set_reproducible(PREFIX3(streamp) strm, int reproducible) { - deflate_state *state = (deflate_state *)strm->state; - - return reproducible != state->reproducible && !dfltcc_was_deflate_used(strm); -} - -/* - Preloading history. -*/ -static void append_history(struct dfltcc_param_v0 *param, unsigned char *history, const unsigned char *buf, uInt count) { - size_t offset; - size_t n; - - /* Do not use more than 32K */ - if (count > HB_SIZE) { - buf += count - HB_SIZE; - count = HB_SIZE; - } - offset = (param->ho + param->hl) % HB_SIZE; - if (offset + count <= HB_SIZE) - /* Circular history buffer does not wrap - copy one chunk */ - memcpy(history + offset, buf, count); - else { - /* Circular history buffer wraps - copy two chunks */ - n = HB_SIZE - offset; - memcpy(history + offset, buf, n); - memcpy(history, buf + n, count - n); - } - n = param->hl + count; - if (n <= HB_SIZE) - /* All history fits into buffer - no need to discard anything */ - param->hl = n; - else { - /* History does not fit into buffer - discard extra bytes */ - param->ho = (param->ho + (n - HB_SIZE)) % HB_SIZE; - param->hl = HB_SIZE; - } -} - -int Z_INTERNAL dfltcc_deflate_set_dictionary(PREFIX3(streamp) strm, - const unsigned char *dictionary, uInt dict_length) { - deflate_state *state = (deflate_state *)strm->state; - struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - struct dfltcc_param_v0 *param = &dfltcc_state->param; - - append_history(param, state->window, dictionary, dict_length); - state->strstart = 1; /* Add FDICT to zlib header */ - state->block_start = state->strstart; /* Make deflate_stored happy */ - return Z_OK; -} - -int Z_INTERNAL dfltcc_deflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt *dict_length) { - deflate_state *state = (deflate_state *)strm->state; - struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - struct dfltcc_param_v0 *param = &dfltcc_state->param; - - if (dictionary) { - if (param->ho + param->hl <= HB_SIZE) - /* Circular history buffer does not wrap - copy one chunk */ - memcpy(dictionary, state->window + param->ho, param->hl); - else { - /* Circular history buffer wraps - copy two chunks */ - memcpy(dictionary, state->window + param->ho, HB_SIZE - param->ho); - memcpy(dictionary + HB_SIZE - param->ho, state->window, param->ho + param->hl - HB_SIZE); - } - } - if (dict_length) - *dict_length = param->hl; - return Z_OK; -} diff --git a/libs/zlibng/arch/s390/dfltcc_deflate.h b/libs/zlibng/arch/s390/dfltcc_deflate.h deleted file mode 100644 index 7e32380bd8..0000000000 --- a/libs/zlibng/arch/s390/dfltcc_deflate.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef DFLTCC_DEFLATE_H -#define DFLTCC_DEFLATE_H - -#include "dfltcc_common.h" - -int Z_INTERNAL dfltcc_can_deflate(PREFIX3(streamp) strm); -int Z_INTERNAL dfltcc_deflate(PREFIX3(streamp) strm, int flush, block_state *result); -int Z_INTERNAL dfltcc_deflate_params(PREFIX3(streamp) strm, int level, int strategy, int *flush); -int Z_INTERNAL dfltcc_deflate_done(PREFIX3(streamp) strm, int flush); -int Z_INTERNAL dfltcc_can_set_reproducible(PREFIX3(streamp) strm, int reproducible); -int Z_INTERNAL dfltcc_deflate_set_dictionary(PREFIX3(streamp) strm, - const unsigned char *dictionary, uInt dict_length); -int Z_INTERNAL dfltcc_deflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt* dict_length); - -#define DEFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) \ - do { \ - if (dfltcc_can_deflate((strm))) \ - return dfltcc_deflate_set_dictionary((strm), (dict), (dict_len)); \ - } while (0) - -#define DEFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) \ - do { \ - if (dfltcc_can_deflate((strm))) \ - return dfltcc_deflate_get_dictionary((strm), (dict), (dict_len)); \ - } while (0) - -#define DEFLATE_RESET_KEEP_HOOK(strm) \ - dfltcc_reset((strm), sizeof(deflate_state)) - -#define DEFLATE_PARAMS_HOOK(strm, level, strategy, hook_flush) \ - do { \ - int err; \ -\ - err = dfltcc_deflate_params((strm), (level), (strategy), (hook_flush)); \ - if (err == Z_STREAM_ERROR) \ - return err; \ - } while (0) - -#define DEFLATE_DONE dfltcc_deflate_done - -#define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, source_len) \ - do { \ - if (dfltcc_can_deflate((strm))) \ - (complen) = (3 + 5 + 5 + 4 + 19 * 3 + (286 + 30) * 7 + \ - (source_len) * 16 + 15 + 7) >> 3; \ - } while (0) - -#define DEFLATE_NEED_CONSERVATIVE_BOUND(strm) (dfltcc_can_deflate((strm))) - -#define DEFLATE_HOOK dfltcc_deflate - -#define DEFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_deflate((strm))) - -#define DEFLATE_CAN_SET_REPRODUCIBLE dfltcc_can_set_reproducible - -#endif diff --git a/libs/zlibng/arch/s390/dfltcc_detail.h b/libs/zlibng/arch/s390/dfltcc_detail.h deleted file mode 100644 index 4ec03f8097..0000000000 --- a/libs/zlibng/arch/s390/dfltcc_detail.h +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include -#include - -#ifdef HAVE_SYS_SDT_H -#include -#endif - -/* - Tuning parameters. - */ -#ifndef DFLTCC_LEVEL_MASK -#define DFLTCC_LEVEL_MASK 0x2 -#endif -#ifndef DFLTCC_BLOCK_SIZE -#define DFLTCC_BLOCK_SIZE 1048576 -#endif -#ifndef DFLTCC_FIRST_FHT_BLOCK_SIZE -#define DFLTCC_FIRST_FHT_BLOCK_SIZE 4096 -#endif -#ifndef DFLTCC_DHT_MIN_SAMPLE_SIZE -#define DFLTCC_DHT_MIN_SAMPLE_SIZE 4096 -#endif -#ifndef DFLTCC_RIBM -#define DFLTCC_RIBM 0 -#endif - -/* - C wrapper for the DEFLATE CONVERSION CALL instruction. - */ -typedef enum { - DFLTCC_CC_OK = 0, - DFLTCC_CC_OP1_TOO_SHORT = 1, - DFLTCC_CC_OP2_TOO_SHORT = 2, - DFLTCC_CC_OP2_CORRUPT = 2, - DFLTCC_CC_AGAIN = 3, -} dfltcc_cc; - -#define DFLTCC_QAF 0 -#define DFLTCC_GDHT 1 -#define DFLTCC_CMPR 2 -#define DFLTCC_XPND 4 -#define HBT_CIRCULAR (1 << 7) -#define HB_BITS 15 -#define HB_SIZE (1 << HB_BITS) -#define DFLTCC_FACILITY 151 - -static inline dfltcc_cc dfltcc(int fn, void *param, - unsigned char **op1, size_t *len1, z_const unsigned char **op2, size_t *len2, void *hist) { - unsigned char *t2 = op1 ? *op1 : NULL; - size_t t3 = len1 ? *len1 : 0; - z_const unsigned char *t4 = op2 ? *op2 : NULL; - size_t t5 = len2 ? *len2 : 0; - Z_REGISTER int r0 __asm__("r0") = fn; - Z_REGISTER void *r1 __asm__("r1") = param; - Z_REGISTER unsigned char *r2 __asm__("r2") = t2; - Z_REGISTER size_t r3 __asm__("r3") = t3; - Z_REGISTER z_const unsigned char *r4 __asm__("r4") = t4; - Z_REGISTER size_t r5 __asm__("r5") = t5; - int cc; - - __asm__ volatile( -#ifdef HAVE_SYS_SDT_H - STAP_PROBE_ASM(zlib, dfltcc_entry, STAP_PROBE_ASM_TEMPLATE(5)) -#endif - ".insn rrf,0xb9390000,%[r2],%[r4],%[hist],0\n" -#ifdef HAVE_SYS_SDT_H - STAP_PROBE_ASM(zlib, dfltcc_exit, STAP_PROBE_ASM_TEMPLATE(5)) -#endif - "ipm %[cc]\n" - : [r2] "+r" (r2) - , [r3] "+r" (r3) - , [r4] "+r" (r4) - , [r5] "+r" (r5) - , [cc] "=r" (cc) - : [r0] "r" (r0) - , [r1] "r" (r1) - , [hist] "r" (hist) -#ifdef HAVE_SYS_SDT_H - , STAP_PROBE_ASM_OPERANDS(5, r2, r3, r4, r5, hist) -#endif - : "cc", "memory"); - t2 = r2; t3 = r3; t4 = r4; t5 = r5; - - if (op1) - *op1 = t2; - if (len1) - *len1 = t3; - if (op2) - *op2 = t4; - if (len2) - *len2 = t5; - return (cc >> 28) & 3; -} - -/* - Parameter Block for Query Available Functions. - */ -#define static_assert(c, msg) __attribute__((unused)) static char static_assert_failed_ ## msg[c ? 1 : -1] - -struct dfltcc_qaf_param { - char fns[16]; - char reserved1[8]; - char fmts[2]; - char reserved2[6]; -}; - -static_assert(sizeof(struct dfltcc_qaf_param) == 32, sizeof_struct_dfltcc_qaf_param_is_32); - -static inline int is_bit_set(const char *bits, int n) { - return bits[n / 8] & (1 << (7 - (n % 8))); -} - -static inline void clear_bit(char *bits, int n) { - bits[n / 8] &= ~(1 << (7 - (n % 8))); -} - -#define DFLTCC_FMT0 0 - -/* - Parameter Block for Generate Dynamic-Huffman Table, Compress and Expand. - */ -#define CVT_CRC32 0 -#define CVT_ADLER32 1 -#define HTT_FIXED 0 -#define HTT_DYNAMIC 1 - -struct dfltcc_param_v0 { - uint16_t pbvn; /* Parameter-Block-Version Number */ - uint8_t mvn; /* Model-Version Number */ - uint8_t ribm; /* Reserved for IBM use */ - uint32_t reserved32 : 31; - uint32_t cf : 1; /* Continuation Flag */ - uint8_t reserved64[8]; - uint32_t nt : 1; /* New Task */ - uint32_t reserved129 : 1; - uint32_t cvt : 1; /* Check Value Type */ - uint32_t reserved131 : 1; - uint32_t htt : 1; /* Huffman-Table Type */ - uint32_t bcf : 1; /* Block-Continuation Flag */ - uint32_t bcc : 1; /* Block Closing Control */ - uint32_t bhf : 1; /* Block Header Final */ - uint32_t reserved136 : 1; - uint32_t reserved137 : 1; - uint32_t dhtgc : 1; /* DHT Generation Control */ - uint32_t reserved139 : 5; - uint32_t reserved144 : 5; - uint32_t sbb : 3; /* Sub-Byte Boundary */ - uint8_t oesc; /* Operation-Ending-Supplemental Code */ - uint32_t reserved160 : 12; - uint32_t ifs : 4; /* Incomplete-Function Status */ - uint16_t ifl; /* Incomplete-Function Length */ - uint8_t reserved192[8]; - uint8_t reserved256[8]; - uint8_t reserved320[4]; - uint16_t hl; /* History Length */ - uint32_t reserved368 : 1; - uint16_t ho : 15; /* History Offset */ - uint32_t cv; /* Check Value */ - uint32_t eobs : 15; /* End-of-block Symbol */ - uint32_t reserved431: 1; - uint8_t eobl : 4; /* End-of-block Length */ - uint32_t reserved436 : 12; - uint32_t reserved448 : 4; - uint16_t cdhtl : 12; /* Compressed-Dynamic-Huffman Table - Length */ - uint8_t reserved464[6]; - uint8_t cdht[288]; - uint8_t reserved[32]; - uint8_t csb[1152]; -}; - -static_assert(sizeof(struct dfltcc_param_v0) == 1536, sizeof_struct_dfltcc_param_v0_is_1536); - -static inline z_const char *oesc_msg(char *buf, int oesc) { - if (oesc == 0x00) - return NULL; /* Successful completion */ - else { - sprintf(buf, "Operation-Ending-Supplemental Code is 0x%.2X", oesc); - return buf; - } -} - -/* - Extension of inflate_state and deflate_state. Must be doubleword-aligned. -*/ -struct dfltcc_state { - struct dfltcc_param_v0 param; /* Parameter block. */ - struct dfltcc_qaf_param af; /* Available functions. */ - uint16_t level_mask; /* Levels on which to use DFLTCC */ - uint32_t block_size; /* New block each X bytes */ - size_t block_threshold; /* New block after total_in > X */ - uint32_t dht_threshold; /* New block only if avail_in >= X */ - char msg[64]; /* Buffer for strm->msg */ -}; - -#define ALIGN_UP(p, size) (__typeof__(p))(((uintptr_t)(p) + ((size) - 1)) & ~((size) - 1)) - -#define GET_DFLTCC_STATE(state) ((struct dfltcc_state *)((char *)(state) + ALIGN_UP(sizeof(*state), 8))) diff --git a/libs/zlibng/arch/s390/dfltcc_inflate.c b/libs/zlibng/arch/s390/dfltcc_inflate.c deleted file mode 100644 index f6a7e8f865..0000000000 --- a/libs/zlibng/arch/s390/dfltcc_inflate.c +++ /dev/null @@ -1,137 +0,0 @@ -/* dfltcc_inflate.c - IBM Z DEFLATE CONVERSION CALL decompression support. */ - -/* - Use the following commands to build zlib-ng with DFLTCC decompression support: - - $ ./configure --with-dfltcc-inflate - or - - $ cmake -DWITH_DFLTCC_INFLATE=1 . - - and then - - $ make -*/ - -#include "../../zbuild.h" -#include "../../zutil.h" -#include "../../inftrees.h" -#include "../../inflate.h" -#include "dfltcc_inflate.h" -#include "dfltcc_detail.h" - -int Z_INTERNAL dfltcc_can_inflate(PREFIX3(streamp) strm) { - struct inflate_state *state = (struct inflate_state *)strm->state; - struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - - /* Unsupported compression settings */ - if (state->wbits != HB_BITS) - return 0; - - /* Unsupported hardware */ - return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) && is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0); -} - -static inline dfltcc_cc dfltcc_xpnd(PREFIX3(streamp) strm) { - struct inflate_state *state = (struct inflate_state *)strm->state; - struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param; - size_t avail_in = strm->avail_in; - size_t avail_out = strm->avail_out; - dfltcc_cc cc; - - cc = dfltcc(DFLTCC_XPND | HBT_CIRCULAR, - param, &strm->next_out, &avail_out, - &strm->next_in, &avail_in, state->window); - strm->avail_in = avail_in; - strm->avail_out = avail_out; - return cc; -} - -dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush, int *ret) { - struct inflate_state *state = (struct inflate_state *)strm->state; - struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - struct dfltcc_param_v0 *param = &dfltcc_state->param; - dfltcc_cc cc; - - if (flush == Z_BLOCK || flush == Z_TREES) { - /* DFLTCC does not support stopping on block boundaries */ - if (dfltcc_inflate_disable(strm)) { - *ret = Z_STREAM_ERROR; - return DFLTCC_INFLATE_BREAK; - } else - return DFLTCC_INFLATE_SOFTWARE; - } - - if (state->last) { - if (state->bits != 0) { - strm->next_in++; - strm->avail_in--; - state->bits = 0; - } - state->mode = CHECK; - return DFLTCC_INFLATE_CONTINUE; - } - - if (strm->avail_in == 0 && !param->cf) - return DFLTCC_INFLATE_BREAK; - - if (inflate_ensure_window(state)) { - state->mode = MEM; - return DFLTCC_INFLATE_CONTINUE; - } - - /* Translate stream to parameter block */ - param->cvt = state->flags ? CVT_CRC32 : CVT_ADLER32; - param->sbb = state->bits; - param->hl = state->whave; /* Software and hardware history formats match */ - param->ho = (state->wnext - state->whave) & ((1 << HB_BITS) - 1); - if (param->hl) - param->nt = 0; /* Honor history for the first block */ - param->cv = state->flags ? ZSWAP32(state->check) : state->check; - - /* Inflate */ - do { - cc = dfltcc_xpnd(strm); - } while (cc == DFLTCC_CC_AGAIN); - - /* Translate parameter block to stream */ - strm->msg = oesc_msg(dfltcc_state->msg, param->oesc); - state->last = cc == DFLTCC_CC_OK; - state->bits = param->sbb; - state->whave = param->hl; - state->wnext = (param->ho + param->hl) & ((1 << HB_BITS) - 1); - state->check = state->flags ? ZSWAP32(param->cv) : param->cv; - if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) { - /* Report an error if stream is corrupted */ - state->mode = BAD; - return DFLTCC_INFLATE_CONTINUE; - } - state->mode = TYPEDO; - /* Break if operands are exhausted, otherwise continue looping */ - return (cc == DFLTCC_CC_OP1_TOO_SHORT || cc == DFLTCC_CC_OP2_TOO_SHORT) ? - DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE; -} - -int Z_INTERNAL dfltcc_was_inflate_used(PREFIX3(streamp) strm) { - struct inflate_state *state = (struct inflate_state *)strm->state; - struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param; - - return !param->nt; -} - -int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm) { - struct inflate_state *state = (struct inflate_state *)strm->state; - struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - - if (!dfltcc_can_inflate(strm)) - return 0; - if (dfltcc_was_inflate_used(strm)) - /* DFLTCC has already decompressed some data. Since there is not - * enough information to resume decompression in software, the call - * must fail. - */ - return 1; - /* DFLTCC was not used yet - decompress in software */ - memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af)); - return 0; -} diff --git a/libs/zlibng/arch/s390/dfltcc_inflate.h b/libs/zlibng/arch/s390/dfltcc_inflate.h deleted file mode 100644 index fc8a000f7b..0000000000 --- a/libs/zlibng/arch/s390/dfltcc_inflate.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef DFLTCC_INFLATE_H -#define DFLTCC_INFLATE_H - -#include "dfltcc_common.h" - -int Z_INTERNAL dfltcc_can_inflate(PREFIX3(streamp) strm); -typedef enum { - DFLTCC_INFLATE_CONTINUE, - DFLTCC_INFLATE_BREAK, - DFLTCC_INFLATE_SOFTWARE, -} dfltcc_inflate_action; -dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush, int *ret); -int Z_INTERNAL dfltcc_was_inflate_used(PREFIX3(streamp) strm); -int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm); - -#define INFLATE_RESET_KEEP_HOOK(strm) \ - dfltcc_reset((strm), sizeof(struct inflate_state)) - -#define INFLATE_PRIME_HOOK(strm, bits, value) \ - do { if (dfltcc_inflate_disable((strm))) return Z_STREAM_ERROR; } while (0) - -#define INFLATE_TYPEDO_HOOK(strm, flush) \ - if (dfltcc_can_inflate((strm))) { \ - dfltcc_inflate_action action; \ -\ - RESTORE(); \ - action = dfltcc_inflate((strm), (flush), &ret); \ - LOAD(); \ - if (action == DFLTCC_INFLATE_CONTINUE) \ - break; \ - else if (action == DFLTCC_INFLATE_BREAK) \ - goto inf_leave; \ - } - -#define INFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_inflate((strm))) - -#define INFLATE_NEED_UPDATEWINDOW(strm) (!dfltcc_can_inflate((strm))) - -#define INFLATE_MARK_HOOK(strm) \ - do { \ - if (dfltcc_was_inflate_used((strm))) return -(1L << 16); \ - } while (0) - -#define INFLATE_SYNC_POINT_HOOK(strm) \ - do { \ - if (dfltcc_was_inflate_used((strm))) return Z_STREAM_ERROR; \ - } while (0) - -#endif diff --git a/libs/zlibng/arch/x86/INDEX.md b/libs/zlibng/arch/x86/INDEX.md deleted file mode 100644 index 8bf6d08e5d..0000000000 --- a/libs/zlibng/arch/x86/INDEX.md +++ /dev/null @@ -1,8 +0,0 @@ -Contents --------- - -|Name|Description| -|:-|:-| -|deflate_quick.c|SSE4 optimized deflate strategy for use as level 1| -|crc_folding.c|SSE4 + PCLMULQDQ optimized CRC folding implementation| -|slide_sse2.c|SSE2 optimized slide_hash| diff --git a/libs/zlibng/arch/x86/Makefile.in b/libs/zlibng/arch/x86/Makefile.in deleted file mode 100644 index 4f6594e6df..0000000000 --- a/libs/zlibng/arch/x86/Makefile.in +++ /dev/null @@ -1,107 +0,0 @@ -# Makefile for zlib -# Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler -# For conditions of distribution and use, see copyright notice in zlib.h - -CC= -CFLAGS= -SFLAGS= -INCLUDES= -SUFFIX= - -AVX2FLAG=-mavx2 -SSE2FLAG=-msse2 -SSSE3FLAG=-mssse3 -SSE4FLAG=-msse4 -PCLMULFLAG=-mpclmul - -SRCDIR=. -SRCTOP=../.. -TOPDIR=$(SRCTOP) - -all: \ - x86.o x86.lo \ - adler32_avx.o adler32.lo \ - adler32_ssse3.o adler32_ssse3.lo \ - chunkset_avx.o chunkset_avx.lo \ - chunkset_sse.o chunkset_sse.lo \ - compare258_avx.o compare258_avx.lo \ - compare258_sse.o compare258_sse.lo \ - insert_string_sse.o insert_string_sse.lo \ - crc_folding.o crc_folding.lo \ - slide_avx.o slide_avx.lo \ - slide_sse.o slide_sse.lo - -x86.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86.c - -x86.lo: - $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86.c - -chunkset_avx.o: - $(CC) $(CFLAGS) $(AVX2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx.c - -chunkset_avx.lo: - $(CC) $(SFLAGS) $(AVX2FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx.c - -chunkset_sse.o: - $(CC) $(CFLAGS) $(SSE2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse.c - -chunkset_sse.lo: - $(CC) $(SFLAGS) $(SSE2FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse.c - -compare258_avx.o: - $(CC) $(CFLAGS) $(AVX2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_avx.c - -compare258_avx.lo: - $(CC) $(SFLAGS) $(AVX2FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_avx.c - -compare258_sse.o: - $(CC) $(CFLAGS) $(SSE4FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse.c - -compare258_sse.lo: - $(CC) $(SFLAGS) $(SSE4FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse.c - -insert_string_sse.o: - $(CC) $(CFLAGS) $(SSE4FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c - -insert_string_sse.lo: - $(CC) $(SFLAGS) $(SSE4FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c - -crc_folding.o: - $(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE4FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc_folding.c - -crc_folding.lo: - $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE4FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc_folding.c - -slide_avx.o: - $(CC) $(CFLAGS) $(AVX2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_avx.c - -slide_avx.lo: - $(CC) $(SFLAGS) $(AVX2FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_avx.c - -slide_sse.o: - $(CC) $(CFLAGS) $(SSE2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_sse.c - -slide_sse.lo: - $(CC) $(SFLAGS) $(SSE2FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_sse.c - -adler32_avx.o: $(SRCDIR)/adler32_avx.c - $(CC) $(CFLAGS) $(AVX2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx.c - -adler32_avx.lo: $(SRCDIR)/adler32_avx.c - $(CC) $(SFLAGS) $(AVX2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx.c - -adler32_ssse3.o: $(SRCDIR)/adler32_ssse3.c - $(CC) $(CFLAGS) $(SSSE3FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c - -adler32_ssse3.lo: $(SRCDIR)/adler32_ssse3.c - $(CC) $(SFLAGS) $(SSSE3FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c - -mostlyclean: clean -clean: - rm -f *.o *.lo *~ - rm -rf objs - rm -f *.gcda *.gcno *.gcov - -distclean: - rm -f Makefile diff --git a/libs/zlibng/arch/x86/adler32_avx.c b/libs/zlibng/arch/x86/adler32_avx.c deleted file mode 100644 index 1063246549..0000000000 --- a/libs/zlibng/arch/x86/adler32_avx.c +++ /dev/null @@ -1,117 +0,0 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2011 Mark Adler - * Authors: - * Brian Bockelman - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "../../zbuild.h" -#include "../../zutil.h" - -#include "../../adler32_p.h" - -#include - -#ifdef X86_AVX2_ADLER32 - -Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len) { - uint32_t sum2; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (UNLIKELY(len == 1)) - return adler32_len_1(adler, buf, sum2); - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (UNLIKELY(buf == NULL)) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (UNLIKELY(len < 16)) - return adler32_len_16(adler, buf, len, sum2); - - uint32_t ALIGNED_(32) s1[8], s2[8]; - - memset(s1, 0, sizeof(s1)); s1[7] = adler; // TODO: would a masked load be faster? - memset(s2, 0, sizeof(s2)); s2[7] = sum2; - - char ALIGNED_(32) dot1[32] = \ - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - __m256i dot1v = _mm256_load_si256((__m256i*)dot1); - char ALIGNED_(32) dot2[32] = \ - {32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, - 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; - __m256i dot2v = _mm256_load_si256((__m256i*)dot2); - short ALIGNED_(32) dot3[16] = \ - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - __m256i dot3v = _mm256_load_si256((__m256i*)dot3); - - // We will need to multiply by - char ALIGNED_(32) shift[16] = {5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - __m128i shiftv = _mm_load_si128((__m128i*)shift); - - while (len >= 32) { - __m256i vs1 = _mm256_load_si256((__m256i*)s1); - __m256i vs2 = _mm256_load_si256((__m256i*)s2); - __m256i vs1_0 = vs1; - - int k = (len < NMAX ? (int)len : NMAX); - k -= k % 32; - len -= k; - - while (k >= 32) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) - */ - __m256i vbuf = _mm256_loadu_si256((__m256i*)buf); - buf += 32; - k -= 32; - - __m256i v_short_sum1 = _mm256_maddubs_epi16(vbuf, dot1v); // multiply-add, resulting in 8 shorts. - __m256i vsum1 = _mm256_madd_epi16(v_short_sum1, dot3v); // sum 8 shorts to 4 int32_t; - __m256i v_short_sum2 = _mm256_maddubs_epi16(vbuf, dot2v); - vs1 = _mm256_add_epi32(vsum1, vs1); - __m256i vsum2 = _mm256_madd_epi16(v_short_sum2, dot3v); - vs1_0 = _mm256_sll_epi32(vs1_0, shiftv); - vsum2 = _mm256_add_epi32(vsum2, vs2); - vs2 = _mm256_add_epi32(vsum2, vs1_0); - vs1_0 = vs1; - } - - // At this point, we have partial sums stored in vs1 and vs2. There are AVX512 instructions that - // would allow us to sum these quickly (VP4DPWSSD). For now, just unpack and move on. - uint32_t ALIGNED_(32) s1_unpack[8]; - uint32_t ALIGNED_(32) s2_unpack[8]; - - _mm256_store_si256((__m256i*)s1_unpack, vs1); - _mm256_store_si256((__m256i*)s2_unpack, vs2); - - adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE) + - (s1_unpack[4] % BASE) + (s1_unpack[5] % BASE) + (s1_unpack[6] % BASE) + (s1_unpack[7] % BASE); - adler %= BASE; - s1[7] = adler; - - sum2 = (s2_unpack[0] % BASE) + (s2_unpack[1] % BASE) + (s2_unpack[2] % BASE) + (s2_unpack[3] % BASE) + - (s2_unpack[4] % BASE) + (s2_unpack[5] % BASE) + (s2_unpack[6] % BASE) + (s2_unpack[7] % BASE); - sum2 %= BASE; - s2[7] = sum2; - } - - while (len) { - len--; - adler += *buf++; - sum2 += adler; - } - adler %= BASE; - sum2 %= BASE; - - /* return recombined sums */ - return adler | (sum2 << 16); -} - -#endif diff --git a/libs/zlibng/arch/x86/adler32_ssse3.c b/libs/zlibng/arch/x86/adler32_ssse3.c deleted file mode 100644 index 101df4fe4d..0000000000 --- a/libs/zlibng/arch/x86/adler32_ssse3.c +++ /dev/null @@ -1,118 +0,0 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2011 Mark Adler - * Authors: - * Brian Bockelman - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "../../zbuild.h" -#include "../../zutil.h" - -#include "../../adler32_p.h" - -#ifdef X86_SSSE3_ADLER32 - -#include - -Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len) { - uint32_t sum2; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (UNLIKELY(len == 1)) - return adler32_len_1(adler, buf, sum2); - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (UNLIKELY(buf == NULL)) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (UNLIKELY(len < 16)) - return adler32_len_16(adler, buf, len, sum2); - - uint32_t ALIGNED_(16) s1[4], s2[4]; - - s1[0] = s1[1] = s1[2] = 0; s1[3] = adler; - s2[0] = s2[1] = s2[2] = 0; s2[3] = sum2; - - char ALIGNED_(16) dot1[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - __m128i dot1v = _mm_load_si128((__m128i*)dot1); - char ALIGNED_(16) dot2[16] = {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; - __m128i dot2v = _mm_load_si128((__m128i*)dot2); - short ALIGNED_(16) dot3[8] = {1, 1, 1, 1, 1, 1, 1, 1}; - __m128i dot3v = _mm_load_si128((__m128i*)dot3); - - // We will need to multiply by - //char ALIGNED_(16) shift[4] = {0, 0, 0, 4}; //{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}; - - char ALIGNED_(16) shift[16] = {4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - __m128i shiftv = _mm_load_si128((__m128i*)shift); - - while (len >= 16) { - __m128i vs1 = _mm_load_si128((__m128i*)s1); - __m128i vs2 = _mm_load_si128((__m128i*)s2); - __m128i vs1_0 = vs1; - - int k = (len < NMAX ? (int)len : NMAX); - k -= k % 16; - len -= k; - - while (k >= 16) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) - - NOTE: 256-bit equivalents are: - _mm256_maddubs_epi16 <- operates on 32 bytes to 16 shorts - _mm256_madd_epi16 <- Sums 16 shorts to 8 int32_t. - We could rewrite the below to use 256-bit instructions instead of 128-bit. - */ - __m128i vbuf = _mm_loadu_si128((__m128i*)buf); - buf += 16; - k -= 16; - - __m128i v_short_sum1 = _mm_maddubs_epi16(vbuf, dot1v); // multiply-add, resulting in 8 shorts. - __m128i vsum1 = _mm_madd_epi16(v_short_sum1, dot3v); // sum 8 shorts to 4 int32_t; - __m128i v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); - vs1 = _mm_add_epi32(vsum1, vs1); - __m128i vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); - vs1_0 = _mm_sll_epi32(vs1_0, shiftv); - vsum2 = _mm_add_epi32(vsum2, vs2); - vs2 = _mm_add_epi32(vsum2, vs1_0); - vs1_0 = vs1; - } - - // At this point, we have partial sums stored in vs1 and vs2. There are AVX512 instructions that - // would allow us to sum these quickly (VP4DPWSSD). For now, just unpack and move on. - - uint32_t ALIGNED_(16) s1_unpack[4]; - uint32_t ALIGNED_(16) s2_unpack[4]; - - _mm_store_si128((__m128i*)s1_unpack, vs1); - _mm_store_si128((__m128i*)s2_unpack, vs2); - - adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE); - adler %= BASE; - s1[3] = adler; - - sum2 = (s2_unpack[0] % BASE) + (s2_unpack[1] % BASE) + (s2_unpack[2] % BASE) + (s2_unpack[3] % BASE); - sum2 %= BASE; - s2[3] = sum2; - } - - while (len) { - len--; - adler += *buf++; - sum2 += adler; - } - adler %= BASE; - sum2 %= BASE; - - /* return recombined sums */ - return adler | (sum2 << 16); -} - -#endif diff --git a/libs/zlibng/arch/x86/chunkset_avx.c b/libs/zlibng/arch/x86/chunkset_avx.c deleted file mode 100644 index eb76c0db99..0000000000 --- a/libs/zlibng/arch/x86/chunkset_avx.c +++ /dev/null @@ -1,50 +0,0 @@ -/* chunkset_avx.c -- AVX inline functions to copy small data chunks. - * For conditions of distribution and use, see copyright notice in zlib.h - */ -#include "zbuild.h" -#include "zutil.h" - -#ifdef X86_AVX_CHUNKSET -#include - -typedef __m256i chunk_t; - -#define HAVE_CHUNKMEMSET_1 -#define HAVE_CHUNKMEMSET_2 -#define HAVE_CHUNKMEMSET_4 -#define HAVE_CHUNKMEMSET_8 - -static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { - *chunk = _mm256_set1_epi8(*(int8_t *)from); -} - -static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { - *chunk = _mm256_set1_epi16(*(int16_t *)from); -} - -static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { - *chunk = _mm256_set1_epi32(*(int32_t *)from); -} - -static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { - *chunk = _mm256_set1_epi64x(*(int64_t *)from); -} - -static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { - *chunk = _mm256_loadu_si256((__m256i *)s); -} - -static inline void storechunk(uint8_t *out, chunk_t *chunk) { - _mm256_storeu_si256((__m256i *)out, *chunk); -} - -#define CHUNKSIZE chunksize_avx -#define CHUNKCOPY chunkcopy_avx -#define CHUNKCOPY_SAFE chunkcopy_safe_avx -#define CHUNKUNROLL chunkunroll_avx -#define CHUNKMEMSET chunkmemset_avx -#define CHUNKMEMSET_SAFE chunkmemset_safe_avx - -#include "chunkset_tpl.h" - -#endif diff --git a/libs/zlibng/arch/x86/chunkset_sse.c b/libs/zlibng/arch/x86/chunkset_sse.c deleted file mode 100644 index 1d5a0faa93..0000000000 --- a/libs/zlibng/arch/x86/chunkset_sse.c +++ /dev/null @@ -1,51 +0,0 @@ -/* chunkset_sse.c -- SSE inline functions to copy small data chunks. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "zutil.h" - -#ifdef X86_SSE2 -#include - -typedef __m128i chunk_t; - -#define HAVE_CHUNKMEMSET_1 -#define HAVE_CHUNKMEMSET_2 -#define HAVE_CHUNKMEMSET_4 -#define HAVE_CHUNKMEMSET_8 - -static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { - *chunk = _mm_set1_epi8(*(int8_t *)from); -} - -static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { - *chunk = _mm_set1_epi16(*(int16_t *)from); -} - -static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { - *chunk = _mm_set1_epi32(*(int32_t *)from); -} - -static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { - *chunk = _mm_set1_epi64x(*(int64_t *)from); -} - -static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { - *chunk = _mm_loadu_si128((__m128i *)s); -} - -static inline void storechunk(uint8_t *out, chunk_t *chunk) { - _mm_storeu_si128((__m128i *)out, *chunk); -} - -#define CHUNKSIZE chunksize_sse2 -#define CHUNKCOPY chunkcopy_sse2 -#define CHUNKCOPY_SAFE chunkcopy_safe_sse2 -#define CHUNKUNROLL chunkunroll_sse2 -#define CHUNKMEMSET chunkmemset_sse2 -#define CHUNKMEMSET_SAFE chunkmemset_safe_sse2 - -#include "chunkset_tpl.h" - -#endif diff --git a/libs/zlibng/arch/x86/compare258_avx.c b/libs/zlibng/arch/x86/compare258_avx.c deleted file mode 100644 index d9108fdeb0..0000000000 --- a/libs/zlibng/arch/x86/compare258_avx.c +++ /dev/null @@ -1,67 +0,0 @@ -/* compare258_avx.c -- AVX2 version of compare258 - * Copyright Mika T. Lindqvist - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "../../zbuild.h" -#include "../../zutil.h" - -#include "fallback_builtins.h" - -#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) - -#include -#ifdef _MSC_VER -# include -#endif - -/* UNALIGNED_OK, AVX2 intrinsic comparison */ -static inline uint32_t compare256_unaligned_avx2_static(const unsigned char *src0, const unsigned char *src1) { - uint32_t len = 0; - - do { - __m256i ymm_src0, ymm_src1, ymm_cmp; - ymm_src0 = _mm256_loadu_si256((__m256i*)src0); - ymm_src1 = _mm256_loadu_si256((__m256i*)src1); - ymm_cmp = _mm256_cmpeq_epi8(ymm_src0, ymm_src1); /* non-identical bytes = 00, identical bytes = FF */ - unsigned mask = (unsigned)_mm256_movemask_epi8(ymm_cmp); - if (mask != 0xFFFFFFFF) { - uint32_t match_byte = (uint32_t)__builtin_ctz(~mask); /* Invert bits so identical = 0 */ - return len + match_byte; - } - - src0 += 32, src1 += 32, len += 32; - - ymm_src0 = _mm256_loadu_si256((__m256i*)src0); - ymm_src1 = _mm256_loadu_si256((__m256i*)src1); - ymm_cmp = _mm256_cmpeq_epi8(ymm_src0, ymm_src1); - mask = (unsigned)_mm256_movemask_epi8(ymm_cmp); - if (mask != 0xFFFFFFFF) { - uint32_t match_byte = (uint32_t)__builtin_ctz(~mask); - return len + match_byte; - } - - src0 += 32, src1 += 32, len += 32; - } while (len < 256); - - return 256; -} - -static inline uint32_t compare258_unaligned_avx2_static(const unsigned char *src0, const unsigned char *src1) { - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return (*src0 == *src1); - - return compare256_unaligned_avx2_static(src0+2, src1+2) + 2; -} - -Z_INTERNAL uint32_t compare258_unaligned_avx2(const unsigned char *src0, const unsigned char *src1) { - return compare258_unaligned_avx2_static(src0, src1); -} - -#define LONGEST_MATCH longest_match_unaligned_avx2 -#define COMPARE256 compare256_unaligned_avx2_static -#define COMPARE258 compare258_unaligned_avx2_static - -#include "match_tpl.h" - -#endif diff --git a/libs/zlibng/arch/x86/compare258_sse.c b/libs/zlibng/arch/x86/compare258_sse.c deleted file mode 100644 index 17534c0519..0000000000 --- a/libs/zlibng/arch/x86/compare258_sse.c +++ /dev/null @@ -1,74 +0,0 @@ -/* compare258_sse.c -- SSE4.2 version of compare258 - * - * Copyright (C) 2013 Intel Corporation. All rights reserved. - * Authors: - * Wajdi Feghali - * Jim Guilford - * Vinodh Gopal - * Erdinc Ozturk - * Jim Kukunas - * - * Portions are Copyright (C) 2016 12Sided Technology, LLC. - * Author: - * Phil Vachon - * - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "../../zbuild.h" -#include "../../zutil.h" - -#ifdef X86_SSE42_CMP_STR - -#include -#ifdef _MSC_VER -# include -#endif - -/* UNALIGNED_OK, SSE4.2 intrinsic comparison */ -static inline uint32_t compare256_unaligned_sse4_static(const unsigned char *src0, const unsigned char *src1) { - uint32_t len = 0; - - do { - #define mode _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_EACH | _SIDD_NEGATIVE_POLARITY - __m128i xmm_src0, xmm_src1; - uint32_t ret; - - xmm_src0 = _mm_loadu_si128((__m128i *)src0); - xmm_src1 = _mm_loadu_si128((__m128i *)src1); - ret = (uint32_t)_mm_cmpestri(xmm_src0, 16, xmm_src1, 16, mode); - if (_mm_cmpestrc(xmm_src0, 16, xmm_src1, 16, mode)) { - return len + ret; - } - src0 += 16, src1 += 16, len += 16; - - xmm_src0 = _mm_loadu_si128((__m128i *)src0); - xmm_src1 = _mm_loadu_si128((__m128i *)src1); - ret = (uint32_t)_mm_cmpestri(xmm_src0, 16, xmm_src1, 16, mode); - if (_mm_cmpestrc(xmm_src0, 16, xmm_src1, 16, mode)) { - return len + ret; - } - src0 += 16, src1 += 16, len += 16; - } while (len < 256); - - return 256; -} - -static inline uint32_t compare258_unaligned_sse4_static(const unsigned char *src0, const unsigned char *src1) { - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return (*src0 == *src1); - - return compare256_unaligned_sse4_static(src0+2, src1+2) + 2; -} - -Z_INTERNAL uint32_t compare258_unaligned_sse4(const unsigned char *src0, const unsigned char *src1) { - return compare258_unaligned_sse4_static(src0, src1); -} - -#define LONGEST_MATCH longest_match_unaligned_sse4 -#define COMPARE256 compare256_unaligned_sse4_static -#define COMPARE258 compare258_unaligned_sse4_static - -#include "match_tpl.h" - -#endif diff --git a/libs/zlibng/arch/x86/crc_folding.c b/libs/zlibng/arch/x86/crc_folding.c deleted file mode 100644 index 918bd94681..0000000000 --- a/libs/zlibng/arch/x86/crc_folding.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ - * instruction. - * - * A white paper describing this algorithm can be found at: - * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf - * - * Copyright (C) 2013 Intel Corporation. All rights reserved. - * Authors: - * Wajdi Feghali - * Jim Guilford - * Vinodh Gopal - * Erdinc Ozturk - * Jim Kukunas - * - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifdef X86_PCLMULQDQ_CRC - -#include "../../zbuild.h" -#include -#include -#include - -#include "crc_folding.h" - -Z_INTERNAL void crc_fold_init(deflate_state *const s) { - /* CRC_SAVE */ - _mm_storeu_si128((__m128i *)s->crc0 + 0, _mm_cvtsi32_si128(0x9db42487)); - _mm_storeu_si128((__m128i *)s->crc0 + 1, _mm_setzero_si128()); - _mm_storeu_si128((__m128i *)s->crc0 + 2, _mm_setzero_si128()); - _mm_storeu_si128((__m128i *)s->crc0 + 3, _mm_setzero_si128()); - - s->strm->adler = 0; -} - -static void fold_1(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { - const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, - 0x00000001, 0xc6e41596); - __m128i x_tmp3; - __m128 ps_crc0, ps_crc3, ps_res; - - x_tmp3 = *xmm_crc3; - - *xmm_crc3 = *xmm_crc0; - *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); - *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); - ps_crc0 = _mm_castsi128_ps(*xmm_crc0); - ps_crc3 = _mm_castsi128_ps(*xmm_crc3); - ps_res = _mm_xor_ps(ps_crc0, ps_crc3); - - *xmm_crc0 = *xmm_crc1; - *xmm_crc1 = *xmm_crc2; - *xmm_crc2 = x_tmp3; - *xmm_crc3 = _mm_castps_si128(ps_res); -} - -static void fold_2(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { - const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, - 0x00000001, 0xc6e41596); - __m128i x_tmp3, x_tmp2; - __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res31, ps_res20; - - x_tmp3 = *xmm_crc3; - x_tmp2 = *xmm_crc2; - - *xmm_crc3 = *xmm_crc1; - *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); - *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); - ps_crc3 = _mm_castsi128_ps(*xmm_crc3); - ps_crc1 = _mm_castsi128_ps(*xmm_crc1); - ps_res31 = _mm_xor_ps(ps_crc3, ps_crc1); - - *xmm_crc2 = *xmm_crc0; - *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); - *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10); - ps_crc0 = _mm_castsi128_ps(*xmm_crc0); - ps_crc2 = _mm_castsi128_ps(*xmm_crc2); - ps_res20 = _mm_xor_ps(ps_crc0, ps_crc2); - - *xmm_crc0 = x_tmp2; - *xmm_crc1 = x_tmp3; - *xmm_crc2 = _mm_castps_si128(ps_res20); - *xmm_crc3 = _mm_castps_si128(ps_res31); -} - -static void fold_3(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { - const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, - 0x00000001, 0xc6e41596); - __m128i x_tmp3; - __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res32, ps_res21, ps_res10; - - x_tmp3 = *xmm_crc3; - - *xmm_crc3 = *xmm_crc2; - *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01); - *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); - ps_crc2 = _mm_castsi128_ps(*xmm_crc2); - ps_crc3 = _mm_castsi128_ps(*xmm_crc3); - ps_res32 = _mm_xor_ps(ps_crc2, ps_crc3); - - *xmm_crc2 = *xmm_crc1; - *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); - *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10); - ps_crc1 = _mm_castsi128_ps(*xmm_crc1); - ps_crc2 = _mm_castsi128_ps(*xmm_crc2); - ps_res21 = _mm_xor_ps(ps_crc1, ps_crc2); - - *xmm_crc1 = *xmm_crc0; - *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); - *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x10); - ps_crc0 = _mm_castsi128_ps(*xmm_crc0); - ps_crc1 = _mm_castsi128_ps(*xmm_crc1); - ps_res10 = _mm_xor_ps(ps_crc0, ps_crc1); - - *xmm_crc0 = x_tmp3; - *xmm_crc1 = _mm_castps_si128(ps_res10); - *xmm_crc2 = _mm_castps_si128(ps_res21); - *xmm_crc3 = _mm_castps_si128(ps_res32); -} - -static void fold_4(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { - const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, - 0x00000001, 0xc6e41596); - __m128i x_tmp0, x_tmp1, x_tmp2, x_tmp3; - __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3; - __m128 ps_t0, ps_t1, ps_t2, ps_t3; - __m128 ps_res0, ps_res1, ps_res2, ps_res3; - - x_tmp0 = *xmm_crc0; - x_tmp1 = *xmm_crc1; - x_tmp2 = *xmm_crc2; - x_tmp3 = *xmm_crc3; - - *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); - x_tmp0 = _mm_clmulepi64_si128(x_tmp0, xmm_fold4, 0x10); - ps_crc0 = _mm_castsi128_ps(*xmm_crc0); - ps_t0 = _mm_castsi128_ps(x_tmp0); - ps_res0 = _mm_xor_ps(ps_crc0, ps_t0); - - *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); - x_tmp1 = _mm_clmulepi64_si128(x_tmp1, xmm_fold4, 0x10); - ps_crc1 = _mm_castsi128_ps(*xmm_crc1); - ps_t1 = _mm_castsi128_ps(x_tmp1); - ps_res1 = _mm_xor_ps(ps_crc1, ps_t1); - - *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01); - x_tmp2 = _mm_clmulepi64_si128(x_tmp2, xmm_fold4, 0x10); - ps_crc2 = _mm_castsi128_ps(*xmm_crc2); - ps_t2 = _mm_castsi128_ps(x_tmp2); - ps_res2 = _mm_xor_ps(ps_crc2, ps_t2); - - *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x01); - x_tmp3 = _mm_clmulepi64_si128(x_tmp3, xmm_fold4, 0x10); - ps_crc3 = _mm_castsi128_ps(*xmm_crc3); - ps_t3 = _mm_castsi128_ps(x_tmp3); - ps_res3 = _mm_xor_ps(ps_crc3, ps_t3); - - *xmm_crc0 = _mm_castps_si128(ps_res0); - *xmm_crc1 = _mm_castps_si128(ps_res1); - *xmm_crc2 = _mm_castps_si128(ps_res2); - *xmm_crc3 = _mm_castps_si128(ps_res3); -} - -static const unsigned ALIGNED_(32) pshufb_shf_table[60] = { - 0x84838281, 0x88878685, 0x8c8b8a89, 0x008f8e8d, /* shl 15 (16 - 1)/shr1 */ - 0x85848382, 0x89888786, 0x8d8c8b8a, 0x01008f8e, /* shl 14 (16 - 3)/shr2 */ - 0x86858483, 0x8a898887, 0x8e8d8c8b, 0x0201008f, /* shl 13 (16 - 4)/shr3 */ - 0x87868584, 0x8b8a8988, 0x8f8e8d8c, 0x03020100, /* shl 12 (16 - 4)/shr4 */ - 0x88878685, 0x8c8b8a89, 0x008f8e8d, 0x04030201, /* shl 11 (16 - 5)/shr5 */ - 0x89888786, 0x8d8c8b8a, 0x01008f8e, 0x05040302, /* shl 10 (16 - 6)/shr6 */ - 0x8a898887, 0x8e8d8c8b, 0x0201008f, 0x06050403, /* shl 9 (16 - 7)/shr7 */ - 0x8b8a8988, 0x8f8e8d8c, 0x03020100, 0x07060504, /* shl 8 (16 - 8)/shr8 */ - 0x8c8b8a89, 0x008f8e8d, 0x04030201, 0x08070605, /* shl 7 (16 - 9)/shr9 */ - 0x8d8c8b8a, 0x01008f8e, 0x05040302, 0x09080706, /* shl 6 (16 -10)/shr10*/ - 0x8e8d8c8b, 0x0201008f, 0x06050403, 0x0a090807, /* shl 5 (16 -11)/shr11*/ - 0x8f8e8d8c, 0x03020100, 0x07060504, 0x0b0a0908, /* shl 4 (16 -12)/shr12*/ - 0x008f8e8d, 0x04030201, 0x08070605, 0x0c0b0a09, /* shl 3 (16 -13)/shr13*/ - 0x01008f8e, 0x05040302, 0x09080706, 0x0d0c0b0a, /* shl 2 (16 -14)/shr14*/ - 0x0201008f, 0x06050403, 0x0a090807, 0x0e0d0c0b /* shl 1 (16 -15)/shr15*/ -}; - -static void partial_fold(const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, - __m128i *xmm_crc3, __m128i *xmm_crc_part) { - - const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, - 0x00000001, 0xc6e41596); - const __m128i xmm_mask3 = _mm_set1_epi32(0x80808080); - - __m128i xmm_shl, xmm_shr, xmm_tmp1, xmm_tmp2, xmm_tmp3; - __m128i xmm_a0_0, xmm_a0_1; - __m128 ps_crc3, psa0_0, psa0_1, ps_res; - - xmm_shl = _mm_load_si128((__m128i *)pshufb_shf_table + (len - 1)); - xmm_shr = xmm_shl; - xmm_shr = _mm_xor_si128(xmm_shr, xmm_mask3); - - xmm_a0_0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shl); - - *xmm_crc0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shr); - xmm_tmp1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shl); - *xmm_crc0 = _mm_or_si128(*xmm_crc0, xmm_tmp1); - - *xmm_crc1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shr); - xmm_tmp2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shl); - *xmm_crc1 = _mm_or_si128(*xmm_crc1, xmm_tmp2); - - *xmm_crc2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shr); - xmm_tmp3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shl); - *xmm_crc2 = _mm_or_si128(*xmm_crc2, xmm_tmp3); - - *xmm_crc3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shr); - *xmm_crc_part = _mm_shuffle_epi8(*xmm_crc_part, xmm_shl); - *xmm_crc3 = _mm_or_si128(*xmm_crc3, *xmm_crc_part); - - xmm_a0_1 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x10); - xmm_a0_0 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x01); - - ps_crc3 = _mm_castsi128_ps(*xmm_crc3); - psa0_0 = _mm_castsi128_ps(xmm_a0_0); - psa0_1 = _mm_castsi128_ps(xmm_a0_1); - - ps_res = _mm_xor_ps(ps_crc3, psa0_0); - ps_res = _mm_xor_ps(ps_res, psa0_1); - - *xmm_crc3 = _mm_castps_si128(ps_res); -} - -Z_INTERNAL void crc_fold_copy(deflate_state *const s, unsigned char *dst, const unsigned char *src, long len) { - unsigned long algn_diff; - __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; - char ALIGNED_(16) partial_buf[16] = { 0 }; - - /* CRC_LOAD */ - __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)s->crc0 + 0); - __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)s->crc0 + 1); - __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)s->crc0 + 2); - __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)s->crc0 + 3); - __m128i xmm_crc_part; - - if (len < 16) { - if (len == 0) - return; - - memcpy(partial_buf, src, len); - xmm_crc_part = _mm_loadu_si128((const __m128i *)partial_buf); - memcpy(dst, partial_buf, len); - goto partial; - } - - algn_diff = ((uintptr_t)16 - ((uintptr_t)src & 0xF)) & 0xF; - if (algn_diff) { - xmm_crc_part = _mm_loadu_si128((__m128i *)src); - _mm_storeu_si128((__m128i *)dst, xmm_crc_part); - - dst += algn_diff; - src += algn_diff; - len -= algn_diff; - - partial_fold(algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); - } else { - xmm_crc_part = _mm_setzero_si128(); - } - - while ((len -= 64) >= 0) { - /* CRC_LOAD */ - xmm_t0 = _mm_load_si128((__m128i *)src); - xmm_t1 = _mm_load_si128((__m128i *)src + 1); - xmm_t2 = _mm_load_si128((__m128i *)src + 2); - xmm_t3 = _mm_load_si128((__m128i *)src + 3); - - fold_4(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - /* CRC_SAVE */ - _mm_storeu_si128((__m128i *)dst, xmm_t0); - _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); - _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); - _mm_storeu_si128((__m128i *)dst + 3, xmm_t3); - - xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0); - xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t1); - xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t2); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t3); - - src += 64; - dst += 64; - } - - /* - * len = num bytes left - 64 - */ - if (len + 16 >= 0) { - len += 16; - - xmm_t0 = _mm_load_si128((__m128i *)src); - xmm_t1 = _mm_load_si128((__m128i *)src + 1); - xmm_t2 = _mm_load_si128((__m128i *)src + 2); - - fold_3(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - _mm_storeu_si128((__m128i *)dst, xmm_t0); - _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); - _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); - - xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t0); - xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2); - - if (len == 0) - goto done; - - dst += 48; - memcpy(&xmm_crc_part, (__m128i *)src + 3, len); - } else if (len + 32 >= 0) { - len += 32; - - xmm_t0 = _mm_load_si128((__m128i *)src); - xmm_t1 = _mm_load_si128((__m128i *)src + 1); - - fold_2(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - _mm_storeu_si128((__m128i *)dst, xmm_t0); - _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); - - xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t0); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t1); - - if (len == 0) - goto done; - - dst += 32; - memcpy(&xmm_crc_part, (__m128i *)src + 2, len); - } else if (len + 48 >= 0) { - len += 48; - - xmm_t0 = _mm_load_si128((__m128i *)src); - - fold_1(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - _mm_storeu_si128((__m128i *)dst, xmm_t0); - - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); - - if (len == 0) - goto done; - - dst += 16; - memcpy(&xmm_crc_part, (__m128i *)src + 1, len); - } else { - len += 64; - if (len == 0) - goto done; - memcpy(&xmm_crc_part, src, len); - } - - _mm_storeu_si128((__m128i *)partial_buf, xmm_crc_part); - memcpy(dst, partial_buf, len); - -partial: - partial_fold(len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); -done: - /* CRC_SAVE */ - _mm_storeu_si128((__m128i *)s->crc0 + 0, xmm_crc0); - _mm_storeu_si128((__m128i *)s->crc0 + 1, xmm_crc1); - _mm_storeu_si128((__m128i *)s->crc0 + 2, xmm_crc2); - _mm_storeu_si128((__m128i *)s->crc0 + 3, xmm_crc3); - _mm_storeu_si128((__m128i *)s->crc0 + 4, xmm_crc_part); -} - -static const unsigned ALIGNED_(16) crc_k[] = { - 0xccaa009e, 0x00000000, /* rk1 */ - 0x751997d0, 0x00000001, /* rk2 */ - 0xccaa009e, 0x00000000, /* rk5 */ - 0x63cd6124, 0x00000001, /* rk6 */ - 0xf7011640, 0x00000001, /* rk7 */ - 0xdb710640, 0x00000001 /* rk8 */ -}; - -static const unsigned ALIGNED_(16) crc_mask[4] = { - 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 -}; - -static const unsigned ALIGNED_(16) crc_mask2[4] = { - 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF -}; - -uint32_t Z_INTERNAL crc_fold_512to32(deflate_state *const s) { - const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask); - const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2); - - uint32_t crc; - __m128i x_tmp0, x_tmp1, x_tmp2, crc_fold; - - /* CRC_LOAD */ - __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)s->crc0 + 0); - __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)s->crc0 + 1); - __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)s->crc0 + 2); - __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)s->crc0 + 3); - - /* - * k1 - */ - crc_fold = _mm_load_si128((__m128i *)crc_k); - - x_tmp0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x10); - xmm_crc0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x01); - xmm_crc1 = _mm_xor_si128(xmm_crc1, x_tmp0); - xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_crc0); - - x_tmp1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x10); - xmm_crc1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x01); - xmm_crc2 = _mm_xor_si128(xmm_crc2, x_tmp1); - xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_crc1); - - x_tmp2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x10); - xmm_crc2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x01); - xmm_crc3 = _mm_xor_si128(xmm_crc3, x_tmp2); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); - - /* - * k5 - */ - crc_fold = _mm_load_si128((__m128i *)crc_k + 1); - - xmm_crc0 = xmm_crc3; - xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0); - xmm_crc0 = _mm_srli_si128(xmm_crc0, 8); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0); - - xmm_crc0 = xmm_crc3; - xmm_crc3 = _mm_slli_si128(xmm_crc3, 4); - xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0); - xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask2); - - /* - * k7 - */ - xmm_crc1 = xmm_crc3; - xmm_crc2 = xmm_crc3; - crc_fold = _mm_load_si128((__m128i *)crc_k + 2); - - xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); - xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask); - - xmm_crc2 = xmm_crc3; - xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc1); - - crc = _mm_extract_epi32(xmm_crc3, 2); - return ~crc; -} - -#endif diff --git a/libs/zlibng/arch/x86/crc_folding.h b/libs/zlibng/arch/x86/crc_folding.h deleted file mode 100644 index 0d3c24b29f..0000000000 --- a/libs/zlibng/arch/x86/crc_folding.h +++ /dev/null @@ -1,19 +0,0 @@ -/* crc_folding.h - * - * Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ - * instruction. - * - * Copyright (C) 2013 Intel Corporation Jim Kukunas - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef CRC_FOLDING_H_ -#define CRC_FOLDING_H_ - -#include "../../deflate.h" - -Z_INTERNAL void crc_fold_init(deflate_state *const); -Z_INTERNAL uint32_t crc_fold_512to32(deflate_state *const); -Z_INTERNAL void crc_fold_copy(deflate_state *const, unsigned char *, const unsigned char *, long); - -#endif diff --git a/libs/zlibng/arch/x86/insert_string_sse.c b/libs/zlibng/arch/x86/insert_string_sse.c deleted file mode 100644 index d0c316b199..0000000000 --- a/libs/zlibng/arch/x86/insert_string_sse.c +++ /dev/null @@ -1,46 +0,0 @@ -/* insert_string_sse -- insert_string variant using SSE4.2's CRC instructions - * - * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - */ - -#include "../../zbuild.h" -#include -#ifdef _MSC_VER -# include -#endif -#include "../../deflate.h" - -#ifdef X86_SSE42_CRC_INTRIN -# ifdef _MSC_VER -# define UPDATE_HASH(s, h, val)\ - h = _mm_crc32_u32(h, val) -# else -# define UPDATE_HASH(s, h, val)\ - h = __builtin_ia32_crc32si(h, val) -# endif -#else -# ifdef _MSC_VER -# define UPDATE_HASH(s, h, val) {\ - __asm mov edx, h\ - __asm mov eax, val\ - __asm crc32 eax, edx\ - __asm mov val, eax\ - } -# else -# define UPDATE_HASH(s, h, val) \ - __asm__ __volatile__ (\ - "crc32 %1,%0\n\t"\ - : "+r" (h)\ - : "r" (val)\ - ); -# endif -#endif - -#define INSERT_STRING insert_string_sse4 -#define QUICK_INSERT_STRING quick_insert_string_sse4 - -#ifdef X86_SSE42_CRC_HASH -# include "../../insert_string_tpl.h" -#endif diff --git a/libs/zlibng/arch/x86/slide_avx.c b/libs/zlibng/arch/x86/slide_avx.c deleted file mode 100644 index be9a9b7ea2..0000000000 --- a/libs/zlibng/arch/x86/slide_avx.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * AVX2 optimized hash slide, based on Intel's slide_sse implementation - * - * Copyright (C) 2017 Intel Corporation - * Authors: - * Arjan van de Ven - * Jim Kukunas - * Mika T. Lindqvist - * - * For conditions of distribution and use, see copyright notice in zlib.h - */ -#include "../../zbuild.h" -#include "../../deflate.h" - -#include - -Z_INTERNAL void slide_hash_avx2(deflate_state *s) { - Pos *p; - unsigned n; - uint16_t wsize = (uint16_t)s->w_size; - const __m256i ymm_wsize = _mm256_set1_epi16((short)wsize); - - n = HASH_SIZE; - p = &s->head[n] - 16; - do { - __m256i value, result; - - value = _mm256_loadu_si256((__m256i *)p); - result= _mm256_subs_epu16(value, ymm_wsize); - _mm256_storeu_si256((__m256i *)p, result); - p -= 16; - n -= 16; - } while (n > 0); - - n = wsize; - p = &s->prev[n] - 16; - do { - __m256i value, result; - - value = _mm256_loadu_si256((__m256i *)p); - result= _mm256_subs_epu16(value, ymm_wsize); - _mm256_storeu_si256((__m256i *)p, result); - - p -= 16; - n -= 16; - } while (n > 0); -} diff --git a/libs/zlibng/arch/x86/slide_sse.c b/libs/zlibng/arch/x86/slide_sse.c deleted file mode 100644 index abf4474752..0000000000 --- a/libs/zlibng/arch/x86/slide_sse.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SSE optimized hash slide - * - * Copyright (C) 2017 Intel Corporation - * Authors: - * Arjan van de Ven - * Jim Kukunas - * - * For conditions of distribution and use, see copyright notice in zlib.h - */ -#include "../../zbuild.h" -#include "../../deflate.h" - -#include - -Z_INTERNAL void slide_hash_sse2(deflate_state *s) { - Pos *p; - unsigned n; - uint16_t wsize = (uint16_t)s->w_size; - const __m128i xmm_wsize = _mm_set1_epi16((short)wsize); - - n = HASH_SIZE; - p = &s->head[n] - 8; - do { - __m128i value, result; - - value = _mm_loadu_si128((__m128i *)p); - result= _mm_subs_epu16(value, xmm_wsize); - _mm_storeu_si128((__m128i *)p, result); - p -= 8; - n -= 8; - } while (n > 0); - - n = wsize; - p = &s->prev[n] - 8; - do { - __m128i value, result; - - value = _mm_loadu_si128((__m128i *)p); - result= _mm_subs_epu16(value, xmm_wsize); - _mm_storeu_si128((__m128i *)p, result); - - p -= 8; - n -= 8; - } while (n > 0); -} diff --git a/libs/zlibng/arch/x86/x86.c b/libs/zlibng/arch/x86/x86.c deleted file mode 100644 index e782cb8ee3..0000000000 --- a/libs/zlibng/arch/x86/x86.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * x86 feature check - * - * Copyright (C) 2013 Intel Corporation. All rights reserved. - * Author: - * Jim Kukunas - * - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "../../zutil.h" - -#ifdef _MSC_VER -# include -#else -// Newer versions of GCC and clang come with cpuid.h -# include -#endif - -Z_INTERNAL int x86_cpu_has_avx2; -Z_INTERNAL int x86_cpu_has_sse2; -Z_INTERNAL int x86_cpu_has_ssse3; -Z_INTERNAL int x86_cpu_has_sse42; -Z_INTERNAL int x86_cpu_has_pclmulqdq; -Z_INTERNAL int x86_cpu_has_tzcnt; - -static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { -#ifdef _MSC_VER - unsigned int registers[4]; - __cpuid((int *)registers, info); - - *eax = registers[0]; - *ebx = registers[1]; - *ecx = registers[2]; - *edx = registers[3]; -#else - __cpuid(info, *eax, *ebx, *ecx, *edx); -#endif -} - -static void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { -#ifdef _MSC_VER - unsigned int registers[4]; - __cpuidex((int *)registers, info, subinfo); - - *eax = registers[0]; - *ebx = registers[1]; - *ecx = registers[2]; - *edx = registers[3]; -#else - __cpuid_count(info, subinfo, *eax, *ebx, *ecx, *edx); -#endif -} - -void Z_INTERNAL x86_check_features(void) { - unsigned eax, ebx, ecx, edx; - unsigned maxbasic; - - cpuid(0, &maxbasic, &ebx, &ecx, &edx); - - cpuid(1 /*CPU_PROCINFO_AND_FEATUREBITS*/, &eax, &ebx, &ecx, &edx); - - x86_cpu_has_sse2 = edx & 0x4000000; - x86_cpu_has_ssse3 = ecx & 0x200; - x86_cpu_has_sse42 = ecx & 0x100000; - x86_cpu_has_pclmulqdq = ecx & 0x2; - - if (maxbasic >= 7) { - cpuidex(7, 0, &eax, &ebx, &ecx, &edx); - - // check BMI1 bit - // Reference: https://software.intel.com/sites/default/files/article/405250/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family.pdf - x86_cpu_has_tzcnt = ebx & 0x8; - // check AVX2 bit - x86_cpu_has_avx2 = ebx & 0x20; - } else { - x86_cpu_has_tzcnt = 0; - x86_cpu_has_avx2 = 0; - } -} diff --git a/libs/zlibng/arch/x86/x86.h b/libs/zlibng/arch/x86/x86.h deleted file mode 100644 index 8471e155cd..0000000000 --- a/libs/zlibng/arch/x86/x86.h +++ /dev/null @@ -1,18 +0,0 @@ -/* cpu.h -- check for CPU features -* Copyright (C) 2013 Intel Corporation Jim Kukunas -* For conditions of distribution and use, see copyright notice in zlib.h -*/ - -#ifndef CPU_H_ -#define CPU_H_ - -extern int x86_cpu_has_avx2; -extern int x86_cpu_has_sse2; -extern int x86_cpu_has_ssse3; -extern int x86_cpu_has_sse42; -extern int x86_cpu_has_pclmulqdq; -extern int x86_cpu_has_tzcnt; - -void Z_INTERNAL x86_check_features(void); - -#endif /* CPU_H_ */ diff --git a/libs/zlibng/chunkset.c b/libs/zlibng/chunkset.c deleted file mode 100644 index 2aa8d4e47f..0000000000 --- a/libs/zlibng/chunkset.c +++ /dev/null @@ -1,81 +0,0 @@ -/* chunkset.c -- inline functions to copy small data chunks. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "zutil.h" - -// We need sizeof(chunk_t) to be 8, no matter what. -#if defined(UNALIGNED64_OK) -typedef uint64_t chunk_t; -#elif defined(UNALIGNED_OK) -typedef struct chunk_t { uint32_t u32[2]; } chunk_t; -#else -typedef struct chunk_t { uint8_t u8[8]; } chunk_t; -#endif - -#define HAVE_CHUNKMEMSET_1 -#define HAVE_CHUNKMEMSET_4 -#define HAVE_CHUNKMEMSET_8 - -static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { -#if defined(UNALIGNED64_OK) - *chunk = 0x0101010101010101 * (uint8_t)*from; -#elif defined(UNALIGNED_OK) - chunk->u32[0] = 0x01010101 * (uint8_t)*from; - chunk->u32[1] = chunk->u32[0]; -#else - memset(chunk, *from, sizeof(chunk_t)); -#endif -} - -static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { -#if defined(UNALIGNED64_OK) - uint32_t half_chunk; - half_chunk = *(uint32_t *)from; - *chunk = 0x0000000100000001 * (uint64_t)half_chunk; -#elif defined(UNALIGNED_OK) - chunk->u32[0] = *(uint32_t *)from; - chunk->u32[1] = chunk->u32[0]; -#else - uint8_t *chunkptr = (uint8_t *)chunk; - memcpy(chunkptr, from, 4); - memcpy(chunkptr+4, from, 4); -#endif -} - -static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { -#if defined(UNALIGNED64_OK) - *chunk = *(uint64_t *)from; -#elif defined(UNALIGNED_OK) - uint32_t* p = (uint32_t *)from; - chunk->u32[0] = p[0]; - chunk->u32[1] = p[1]; -#else - memcpy(chunk, from, sizeof(chunk_t)); -#endif -} - -static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { - chunkmemset_8((uint8_t *)s, chunk); -} - -static inline void storechunk(uint8_t *out, chunk_t *chunk) { -#if defined(UNALIGNED64_OK) - *(uint64_t *)out = *chunk; -#elif defined(UNALIGNED_OK) - ((uint32_t *)out)[0] = chunk->u32[0]; - ((uint32_t *)out)[1] = chunk->u32[1]; -#else - memcpy(out, chunk, sizeof(chunk_t)); -#endif -} - -#define CHUNKSIZE chunksize_c -#define CHUNKCOPY chunkcopy_c -#define CHUNKCOPY_SAFE chunkcopy_safe_c -#define CHUNKUNROLL chunkunroll_c -#define CHUNKMEMSET chunkmemset_c -#define CHUNKMEMSET_SAFE chunkmemset_safe_c - -#include "chunkset_tpl.h" diff --git a/libs/zlibng/chunkset_tpl.h b/libs/zlibng/chunkset_tpl.h deleted file mode 100644 index 9e8ede5591..0000000000 --- a/libs/zlibng/chunkset_tpl.h +++ /dev/null @@ -1,172 +0,0 @@ -/* chunkset_tpl.h -- inline functions to copy small data chunks. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* Returns the chunk size */ -Z_INTERNAL uint32_t CHUNKSIZE(void) { - return sizeof(chunk_t); -} - -/* Behave like memcpy, but assume that it's OK to overwrite at least - chunk_t bytes of output even if the length is shorter than this, - that the length is non-zero, and that `from` lags `out` by at least - sizeof chunk_t bytes (or that they don't overlap at all or simply that - the distance is less than the length of the copy). - - Aside from better memory bus utilisation, this means that short copies - (chunk_t bytes or fewer) will fall straight through the loop - without iteration, which will hopefully make the branch prediction more - reliable. */ -Z_INTERNAL uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { - chunk_t chunk; - --len; - loadchunk(from, &chunk); - storechunk(out, &chunk); - out += (len % sizeof(chunk_t)) + 1; - from += (len % sizeof(chunk_t)) + 1; - len /= sizeof(chunk_t); - while (len > 0) { - loadchunk(from, &chunk); - storechunk(out, &chunk); - out += sizeof(chunk_t); - from += sizeof(chunk_t); - --len; - } - return out; -} - -/* Behave like chunkcopy, but avoid writing beyond of legal output. */ -Z_INTERNAL uint8_t* CHUNKCOPY_SAFE(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe) { - if ((safe - out) < (ptrdiff_t)sizeof(chunk_t)) { - int32_t use_chunk16 = sizeof(chunk_t) > 16 && (len & 16); - if (use_chunk16) { - memcpy(out, from, 16); - out += 16; - from += 16; - } - if (len & 8) { - memcpy(out, from, 8); - out += 8; - from += 8; - } - if (len & 4) { - memcpy(out, from, 4); - out += 4; - from += 4; - } - if (len & 2) { - memcpy(out, from, 2); - out += 2; - from += 2; - } - if (len & 1) { - *out++ = *from++; - } - return out; - } - return CHUNKCOPY(out, from, len); -} - -/* Perform short copies until distance can be rewritten as being at least - sizeof chunk_t. - - This assumes that it's OK to overwrite at least the first - 2*sizeof(chunk_t) bytes of output even if the copy is shorter than this. - This assumption holds because inflate_fast() starts every iteration with at - least 258 bytes of output space available (258 being the maximum length - output from a single token; see inflate_fast()'s assumptions below). */ -Z_INTERNAL uint8_t* CHUNKUNROLL(uint8_t *out, unsigned *dist, unsigned *len) { - unsigned char const *from = out - *dist; - chunk_t chunk; - while (*dist < *len && *dist < sizeof(chunk_t)) { - loadchunk(from, &chunk); - storechunk(out, &chunk); - out += *dist; - *len -= *dist; - *dist += *dist; - } - return out; -} - -/* Copy DIST bytes from OUT - DIST into OUT + DIST * k, for 0 <= k < LEN/DIST. - Return OUT + LEN. */ -Z_INTERNAL uint8_t* CHUNKMEMSET(uint8_t *out, unsigned dist, unsigned len) { - /* Debug performance related issues when len < sizeof(uint64_t): - Assert(len >= sizeof(uint64_t), "chunkmemset should be called on larger chunks"); */ - Assert(dist > 0, "cannot have a distance 0"); - - unsigned char *from = out - dist; - chunk_t chunk; - unsigned sz = sizeof(chunk); - if (len < sz) { - do { - *out++ = *from++; - --len; - } while (len != 0); - return out; - } - -#ifdef HAVE_CHUNKMEMSET_1 - if (dist == 1) { - chunkmemset_1(from, &chunk); - } else -#endif -#ifdef HAVE_CHUNKMEMSET_2 - if (dist == 2) { - chunkmemset_2(from, &chunk); - } else -#endif -#ifdef HAVE_CHUNKMEMSET_4 - if (dist == 4) { - chunkmemset_4(from, &chunk); - } else -#endif -#ifdef HAVE_CHUNKMEMSET_8 - if (dist == 8) { - chunkmemset_8(from, &chunk); - } else -#endif - if (dist == sz) { - loadchunk(from, &chunk); - } else if (dist < sz) { - unsigned char *end = out + len - 1; - while (len > dist) { - out = CHUNKCOPY_SAFE(out, from, dist, end); - len -= dist; - } - if (len > 0) { - out = CHUNKCOPY_SAFE(out, from, len, end); - } - return out; - } else { - out = CHUNKUNROLL(out, &dist, &len); - return CHUNKCOPY(out, out - dist, len); - } - - unsigned rem = len % sz; - len -= rem; - while (len) { - storechunk(out, &chunk); - out += sz; - len -= sz; - } - - /* Last, deal with the case when LEN is not a multiple of SZ. */ - if (rem) - memcpy(out, from, rem); - out += rem; - - return out; -} - -Z_INTERNAL uint8_t* CHUNKMEMSET_SAFE(uint8_t *out, unsigned dist, unsigned len, unsigned left) { - if (left < (unsigned)(3 * sizeof(chunk_t))) { - while (len > 0) { - *out = *(out - dist); - out++; - --len; - } - return out; - } - return CHUNKMEMSET(out, dist, len); -} diff --git a/libs/zlibng/cmake/detect-arch.c b/libs/zlibng/cmake/detect-arch.c deleted file mode 100644 index 571553582a..0000000000 --- a/libs/zlibng/cmake/detect-arch.c +++ /dev/null @@ -1,99 +0,0 @@ -// archdetect.c -- Detect compiler architecture and raise preprocessor error -// containing a simple arch identifier. -// Copyright (C) 2019 Hans Kristian Rosbach -// Licensed under the Zlib license, see LICENSE.md for details - -// x86_64 -#if defined(__x86_64__) || defined(_M_X64) - #error archfound x86_64 - -// x86 -#elif defined(__i386) || defined(_M_IX86) - #error archfound i686 - -// ARM -#elif defined(__aarch64__) || defined(_M_ARM64) - #error archfound aarch64 -#elif defined(__arm__) || defined(__arm) || defined(_M_ARM) || defined(__TARGET_ARCH_ARM) - #if defined(__ARM64_ARCH_8__) || defined(__ARMv8__) || defined(__ARMv8_A__) - #error archfound armv8 - #elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) - #error archfound armv7 - #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6M__) - #error archfound armv6 - #elif defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__) - #error archfound armv5 - #elif defined(__ARM_ARCH_4T__) || defined(__TARGET_ARCH_5E__) - #error archfound armv4 - #elif defined(__ARM_ARCH_3__) || defined(__TARGET_ARCH_3M__) - #error archfound armv3 - #elif defined(__ARM_ARCH_2__) - #error archfound armv2 - #endif - -// PowerPC -#elif defined(__powerpc__) || defined(_ppc__) || defined(__PPC__) - #if defined(__64BIT__) || defined(__powerpc64__) || defined(__ppc64__) - #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #error archfound powerpc64le - #else - #error archfound powerpc64 - #endif - #else - #error archfound powerpc - #endif - -// --------------- Less common architectures alphabetically below --------------- - -// ALPHA -#elif defined(__alpha__) || defined(__alpha) - #error archfound alpha - -// Blackfin -#elif defined(__BFIN__) - #error archfound blackfin - -// Itanium -#elif defined(__ia64) || defined(_M_IA64) - #error archfound ia64 - -// MIPS -#elif defined(__mips__) || defined(__mips) - #error archfound mips - -// Motorola 68000-series -#elif defined(__m68k__) - #error archfound m68k - -// SuperH -#elif defined(__sh__) - #error archfound sh - -// SPARC -#elif defined(__sparc__) || defined(__sparc) - #if defined(__sparcv9) || defined(__sparc_v9__) - #error archfound sparc9 - #elif defined(__sparcv8) || defined(__sparc_v8__) - #error archfound sparc8 - #endif - -// SystemZ -#elif defined(__370__) - #error archfound s370 -#elif defined(__s390__) - #error archfound s390 -#elif defined(__s390x) || defined(__zarch__) - #error archfound s390x - -// PARISC -#elif defined(__hppa__) - #error archfound parisc - -// RS-6000 -#elif defined(__THW_RS6000) - #error archfound rs6000 - -// return 'unrecognized' if we do not know what architecture this is -#else - #error archfound unrecognized -#endif diff --git a/libs/zlibng/cmake/detect-arch.cmake b/libs/zlibng/cmake/detect-arch.cmake deleted file mode 100644 index b80d6666f2..0000000000 --- a/libs/zlibng/cmake/detect-arch.cmake +++ /dev/null @@ -1,93 +0,0 @@ -# detect-arch.cmake -- Detect compiler architecture and set ARCH and BASEARCH -# Copyright (C) 2019 Hans Kristian Rosbach -# Licensed under the Zlib license, see LICENSE.md for details -set(ARCHDETECT_FOUND TRUE) - -if(CMAKE_OSX_ARCHITECTURES) - # If multiple architectures are requested (universal build), pick only the first - list(GET CMAKE_OSX_ARCHITECTURES 0 ARCH) -elseif(MSVC) - if("${MSVC_C_ARCHITECTURE_ID}" STREQUAL "X86") - set(ARCH "i686") - elseif("${MSVC_C_ARCHITECTURE_ID}" STREQUAL "x64") - set(ARCH "x86_64") - elseif("${MSVC_C_ARCHITECTURE_ID}" STREQUAL "ARM" OR "${MSVC_C_ARCHITECTURE_ID}" STREQUAL "ARMV7") - set(ARCH "arm") - elseif ("${MSVC_C_ARCHITECTURE_ID}" STREQUAL "ARM64") - set(ARCH "aarch64") - endif() -elseif(CMAKE_CROSSCOMPILING) - set(ARCH ${CMAKE_C_COMPILER_TARGET}) -else() - # Let preprocessor parse archdetect.c and raise an error containing the arch identifier - enable_language(C) - try_run( - run_result_unused - compile_result_unused - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/detect-arch.c - COMPILE_OUTPUT_VARIABLE RAWOUTPUT - CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} - ) - - # Find basearch tag, and extract the arch word into BASEARCH variable - string(REGEX REPLACE ".*archfound ([a-zA-Z0-9_]+).*" "\\1" ARCH "${RAWOUTPUT}") - if(NOT ARCH) - set(ARCH unknown) - endif() -endif() - -# Make sure we have ARCH set -if(NOT ARCH OR ARCH STREQUAL "unknown") - set(ARCH ${CMAKE_SYSTEM_PROCESSOR}) - message(STATUS "Arch not recognized, falling back to cmake arch: '${ARCH}'") -else() - message(STATUS "Arch detected: '${ARCH}'") -endif() - -# Base arch detection -if("${ARCH}" MATCHES "(x86_64|AMD64|i[3-6]86)") - set(BASEARCH "x86") - set(BASEARCH_X86_FOUND TRUE) -elseif("${ARCH}" MATCHES "(arm(v[0-9])?|aarch64)") - set(BASEARCH "arm") - set(BASEARCH_ARM_FOUND TRUE) -elseif("${ARCH}" MATCHES "ppc(64(le)?)?|powerpc(64(le)?)?") - set(BASEARCH "ppc") - set(BASEARCH_PPC_FOUND TRUE) -elseif("${ARCH}" MATCHES "alpha") - set(BASEARCH "alpha") - set(BASEARCH_ALPHA_FOUND TRUE) -elseif("${ARCH}" MATCHES "blackfin") - set(BASEARCH "blackfin") - set(BASEARCH_BLACKFIN_FOUND TRUE) -elseif("${ARCH}" MATCHES "ia64") - set(BASEARCH "ia64") - set(BASEARCH_IA64_FOUND TRUE) -elseif("${ARCH}" MATCHES "mips") - set(BASEARCH "mips") - set(BASEARCH_MIPS_FOUND TRUE) -elseif("${ARCH}" MATCHES "m68k") - set(BASEARCH "m68k") - set(BASEARCH_M68K_FOUND TRUE) -elseif("${ARCH}" MATCHES "sh") - set(BASEARCH "sh") - set(BASEARCH_SH_FOUND TRUE) -elseif("${ARCH}" MATCHES "sparc[89]?") - set(BASEARCH "sparc") - set(BASEARCH_SPARC_FOUND TRUE) -elseif("${ARCH}" MATCHES "s3[679]0x?") - set(BASEARCH "s360") - set(BASEARCH_S360_FOUND TRUE) -elseif("${ARCH}" MATCHES "parisc") - set(BASEARCH "parisc") - set(BASEARCH_PARISC_FOUND TRUE) -elseif("${ARCH}" MATCHES "rs6000") - set(BASEARCH "rs6000") - set(BASEARCH_RS6000_FOUND TRUE) -else() - set(BASEARCH "x86") - set(BASEARCH_X86_FOUND TRUE) - message(STATUS "Basearch '${ARCH}' not recognized, defaulting to 'x86'.") -endif() -message(STATUS "Basearch of '${ARCH}' has been detected as: '${BASEARCH}'") diff --git a/libs/zlibng/cmake/detect-sanitizer.cmake b/libs/zlibng/cmake/detect-sanitizer.cmake deleted file mode 100644 index 172a8d5583..0000000000 --- a/libs/zlibng/cmake/detect-sanitizer.cmake +++ /dev/null @@ -1,123 +0,0 @@ -# detect-sanitizer.cmake -- Detect supported compiler sanitizer flags -# Licensed under the Zlib license, see LICENSE.md for details - -macro(check_sanitizer_support known_checks supported_checks) - set(available_checks "") - - # Build list of supported sanitizer flags by incrementally trying compilation with - # known sanitizer checks - - foreach(check ${known_checks}) - if(available_checks STREQUAL "") - set(compile_checks "${check}") - else() - set(compile_checks "${available_checks},${check}") - endif() - - set(CMAKE_REQUIRED_FLAGS "-fsanitize=${compile_checks}") - - check_c_source_compiles("int main() { return 0; }" HAS_SANITIZER_${check} - FAIL_REGEX "not supported|unrecognized command|unknown option") - - set(CMAKE_REQUIRED_FLAGS) - - if(HAS_SANITIZER_${check}) - set(available_checks ${compile_checks}) - endif() - endforeach() - - set(${supported_checks} ${available_checks}) -endmacro() - -macro(add_address_sanitizer) - set(known_checks - address - pointer-compare - pointer-subtract - ) - - check_sanitizer_support("${known_checks}" supported_checks) - if(NOT ${supported_checks} STREQUAL "") - message(STATUS "Address sanitizer is enabled: ${supported_checks}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") - else() - message(STATUS "Address sanitizer is not supported") - endif() - - if(CMAKE_CROSSCOMPILING_EMULATOR) - # Only check for leak sanitizer if not cross-compiling due to qemu crash - message(WARNING "Leak sanitizer is not supported when cross compiling") - else() - # Leak sanitizer requires address sanitizer - check_sanitizer_support("leak" supported_checks) - if(NOT ${supported_checks} STREQUAL "") - message(STATUS "Leak sanitizer is enabled: ${supported_checks}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") - else() - message(STATUS "Leak sanitizer is not supported") - endif() - endif() -endmacro() - -macro(add_memory_sanitizer) - check_sanitizer_support("memory" supported_checks) - if(NOT ${supported_checks} STREQUAL "") - message(STATUS "Memory sanitizer is enabled: ${supported_checks}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") - else() - message(STATUS "Memory sanitizer is not supported") - endif() -endmacro() - -macro(add_undefined_sanitizer) - set(known_checks - array-bounds - bool - bounds - builtin - enum - float-cast-overflow - float-divide-by-zero - function - integer-divide-by-zero - local-bounds - null - nonnull-attribute - pointer-overflow - return - returns-nonnull-attribute - shift - shift-base - shift-exponent - signed-integer-overflow - undefined - unsigned-integer-overflow - unsigned-shift-base - vla-bound - vptr - ) - - # Only check for alignment sanitizer flag if unaligned access is not supported - if(NOT UNALIGNED_OK) - list(APPEND known_checks alignment) - endif() - # Object size sanitizer has no effect at -O0 and produces compiler warning if enabled - if(NOT CMAKE_C_FLAGS MATCHES "-O0") - list(APPEND known_checks object-size) - endif() - - check_sanitizer_support("${known_checks}" supported_checks) - - if(NOT ${supported_checks} STREQUAL "") - message(STATUS "Undefined behavior sanitizer is enabled: ${supported_checks}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") - - # Group sanitizer flag -fsanitize=undefined will automatically add alignment, even if - # it is not in our sanitize flag list, so we need to explicitly disable alignment sanitizing. - if(UNALIGNED_OK) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=alignment") - endif() - else() - message(STATUS "UNdefined behavior sanitizer is not supported") - endif() -endmacro() \ No newline at end of file diff --git a/libs/zlibng/cmake/run-and-compare.cmake b/libs/zlibng/cmake/run-and-compare.cmake deleted file mode 100644 index 0e93433731..0000000000 --- a/libs/zlibng/cmake/run-and-compare.cmake +++ /dev/null @@ -1,48 +0,0 @@ -if(NOT DEFINED OUTPUT OR NOT DEFINED COMPARE OR NOT DEFINED COMMAND) - message(FATAL_ERROR "Run and compare arguments missing") -endif() - -if(INPUT) - # Run command with stdin input and redirect stdout to output - execute_process(COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${COMMAND}" - -DINPUT=${INPUT} - -DOUTPUT=${OUTPUT} - "-DSUCCESS_EXIT=${SUCCESS_EXIT}" - -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake - RESULT_VARIABLE CMD_RESULT) -else() - # Run command and redirect stdout to output - execute_process(COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${COMMAND}" - -DOUTPUT=${OUTPUT} - "-DSUCCESS_EXIT=${SUCCESS_EXIT}" - -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake - RESULT_VARIABLE CMD_RESULT) -endif() - -if(CMD_RESULT) - message(FATAL_ERROR "Run before compare failed: ${CMD_RESULT}") -endif() - -# Use configure_file to normalize line-endings -if(IGNORE_LINE_ENDINGS) - configure_file(${COMPARE} ${COMPARE}.cmp NEWLINE_STYLE LF) - set(COMPARE ${COMPARE}.cmp) - configure_file(${OUTPUT} ${OUTPUT}.cmp NEWLINE_STYLE LF) - set(OUTPUT ${OUTPUT}.cmp) -endif() - -# Compare that output is equal to specified file -execute_process(COMMAND ${CMAKE_COMMAND} - -E compare_files ${COMPARE} ${OUTPUT} - RESULT_VARIABLE CMD_RESULT) - -# Delete temporary files used to normalize line-endings -if(IGNORE_LINE_ENDINGS) - file(REMOVE ${COMPARE} ${OUTPUT}) -endif() - -if(CMD_RESULT) - message(FATAL_ERROR "Run compare failed: ${CMD_RESULT}") -endif() \ No newline at end of file diff --git a/libs/zlibng/cmake/run-and-redirect.cmake b/libs/zlibng/cmake/run-and-redirect.cmake deleted file mode 100644 index 30c5741121..0000000000 --- a/libs/zlibng/cmake/run-and-redirect.cmake +++ /dev/null @@ -1,38 +0,0 @@ -# If no output is specified, discard output -if(NOT DEFINED OUTPUT) - if(WIN32) - set(OUTPUT NUL) - else() - set(OUTPUT /dev/null) - endif() -endif() - -if(INPUT) - # Check to see that input file exists - if(NOT EXISTS ${INPUT}) - message(FATAL_ERROR "Cannot find input: ${INPUT}") - endif() - # Execute with both stdin and stdout file - execute_process(COMMAND ${COMMAND} - RESULT_VARIABLE CMD_RESULT - INPUT_FILE ${INPUT} - OUTPUT_FILE ${OUTPUT}) -else() - # Execute with only stdout file - execute_process(COMMAND ${COMMAND} - RESULT_VARIABLE CMD_RESULT - OUTPUT_FILE ${OUTPUT}) -endif() - -# Check if exit code is in list of successful exit codes -if(SUCCESS_EXIT) - list(FIND SUCCESS_EXIT ${CMD_RESULT} _INDEX) - if (${_INDEX} GREATER -1) - set(CMD_RESULT 0) - endif() -endif() - -# Check to see if successful -if(CMD_RESULT) - message(FATAL_ERROR "${COMMAND} failed: ${CMD_RESULT}") -endif() diff --git a/libs/zlibng/cmake/test-compress.cmake b/libs/zlibng/cmake/test-compress.cmake deleted file mode 100644 index 75355bc737..0000000000 --- a/libs/zlibng/cmake/test-compress.cmake +++ /dev/null @@ -1,188 +0,0 @@ -if(TARGET) - set(COMPRESS_TARGET ${TARGET}) - set(DECOMPRESS_TARGET ${TARGET}) -endif() - -if(NOT DEFINED INPUT OR NOT DEFINED COMPRESS_TARGET OR NOT DEFINED DECOMPRESS_TARGET) - message(FATAL_ERROR "Compress test arguments missing") -endif() - -# Set default values -if(NOT DEFINED COMPARE) - set(COMPARE ON) -endif() -if(NOT DEFINED COMPRESS_ARGS) - set(COMPRESS_ARGS -c -k) -endif() -if(NOT DEFINED DECOMPRESS_ARGS) - set(DECOMPRESS_ARGS -d -c) -endif() -if(NOT DEFINED GZIP_VERIFY) - set(GZIP_VERIFY ON) -endif() -if(NOT DEFINED SUCCESS_EXIT) - set(SUCCESS_EXIT 0) -endif() - -# Generate unique output path so multiple tests can be executed at the same time -if(NOT OUTPUT) - # Output name based on input and unique id - string(RANDOM UNIQUE_ID) - set(OUTPUT ${INPUT}-${UNIQUE_ID}) -else() - # Output name appends unique id in case multiple tests with same output name - string(RANDOM LENGTH 6 UNIQUE_ID) - set(OUTPUT ${OUTPUT}-${UNIQUE_ID}) -endif() -string(REPLACE ".gz" "" OUTPUT "${OUTPUT}") - -macro(cleanup) - # Cleanup temporary mingizip files - file(REMOVE ${OUTPUT}.gz ${OUTPUT}.out) - # Cleanup temporary gzip files - file(REMOVE ${OUTPUT}.gzip.gz ${OUTPUT}.gzip.out) -endmacro() - -# Compress input file -if(NOT EXISTS ${INPUT}) - message(FATAL_ERROR "Cannot find compress input: ${INPUT}") -endif() - -set(COMPRESS_COMMAND ${COMPRESS_TARGET} ${COMPRESS_ARGS}) - -execute_process(COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${COMPRESS_COMMAND}" - -DINPUT=${INPUT} - -DOUTPUT=${OUTPUT}.gz - "-DSUCCESS_EXIT=${SUCCESS_EXIT}" - -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake - RESULT_VARIABLE CMD_RESULT) - -if(CMD_RESULT) - cleanup() - message(FATAL_ERROR "Compress failed: ${CMD_RESULT}") -endif() - -# Decompress output -if(NOT EXISTS ${OUTPUT}.gz) - cleanup() - message(FATAL_ERROR "Cannot find decompress input: ${OUTPUT}.gz") -endif() - -set(DECOMPRESS_COMMAND ${DECOMPRESS_TARGET} ${DECOMPRESS_ARGS}) - -execute_process(COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${DECOMPRESS_COMMAND}" - -DINPUT=${OUTPUT}.gz - -DOUTPUT=${OUTPUT}.out - "-DSUCCESS_EXIT=${SUCCESS_EXIT}" - -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake - RESULT_VARIABLE CMD_RESULT) - -if(CMD_RESULT) - cleanup() - message(FATAL_ERROR "Decompress failed: ${CMD_RESULT}") -endif() - -if(COMPARE) - # Compare decompressed output with original input file - execute_process(COMMAND ${CMAKE_COMMAND} - -E compare_files ${INPUT} ${OUTPUT}.out - RESULT_VARIABLE CMD_RESULT) - - if(CMD_RESULT) - cleanup() - message(FATAL_ERROR "Compare minigzip decompress failed: ${CMD_RESULT}") - endif() -endif() - -if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") - # Transparent writing does not use gzip format - find_program(GZIP gzip) - if(GZIP) - if(NOT EXISTS ${OUTPUT}.gz) - cleanup() - message(FATAL_ERROR "Cannot find gzip decompress input: ${OUTPUT}.gz") - endif() - - # Check gzip can decompress our compressed output - set(GZ_DECOMPRESS_COMMAND ${GZIP} --decompress) - - execute_process(COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${GZ_DECOMPRESS_COMMAND}" - -DINPUT=${OUTPUT}.gz - -DOUTPUT=${OUTPUT}.gzip.out - "-DSUCCESS_EXIT=${SUCCESS_EXIT}" - -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake - RESULT_VARIABLE CMD_RESULT) - - if(CMD_RESULT) - cleanup() - message(FATAL_ERROR "Gzip decompress failed: ${CMD_RESULT}") - endif() - - # Compare gzip output with original input file - execute_process(COMMAND ${CMAKE_COMMAND} - -E compare_files ${INPUT} ${OUTPUT}.gzip.out - RESULT_VARIABLE CMD_RESULT) - - if(CMD_RESULT) - cleanup() - message(FATAL_ERROR "Compare gzip decompress failed: ${CMD_RESULT}") - endif() - - if(NOT EXISTS ${OUTPUT}.gz) - cleanup() - message(FATAL_ERROR "Cannot find gzip compress input: ${INPUT}") - endif() - - # Compress input file with gzip - set(GZ_COMPRESS_COMMAND ${GZIP} --stdout) - - execute_process(COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${GZ_COMPRESS_COMMAND}" - -DINPUT=${INPUT} - -DOUTPUT=${OUTPUT}.gzip.gz - "-DSUCCESS_EXIT=${SUCCESS_EXIT}" - -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake - RESULT_VARIABLE CMD_RESULT) - - if(CMD_RESULT) - cleanup() - message(FATAL_ERROR "Gzip compress failed: ${CMD_RESULT}") - endif() - - if(NOT EXISTS ${OUTPUT}.gz) - cleanup() - message(FATAL_ERROR "Cannot find minigzip decompress input: ${OUTPUT}.gzip.gz") - endif() - - # Check minigzip can decompress gzip compressed output - execute_process(COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${DECOMPRESS_COMMAND}" - -DINPUT=${OUTPUT}.gzip.gz - -DOUTPUT=${OUTPUT}.gzip.out - "-DSUCCESS_EXIT=${SUCCESS_EXIT}" - -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake - RESULT_VARIABLE CMD_RESULT) - - if(CMD_RESULT) - cleanup() - message(FATAL_ERROR "Minigzip decompress gzip failed: ${CMD_RESULT}") - endif() - - if(COMPARE) - # Compare original input file with gzip decompressed output - execute_process(COMMAND ${CMAKE_COMMAND} - -E compare_files ${INPUT} ${OUTPUT}.gzip.out - RESULT_VARIABLE CMD_RESULT) - - if(CMD_RESULT) - cleanup() - message(FATAL_ERROR "Compare minigzip decompress gzip failed: ${CMD_RESULT}") - endif() - endif() - endif() -endif() - -cleanup() \ No newline at end of file diff --git a/libs/zlibng/cmake/toolchain-aarch64.cmake b/libs/zlibng/cmake/toolchain-aarch64.cmake deleted file mode 100644 index 31894fdcd5..0000000000 --- a/libs/zlibng/cmake/toolchain-aarch64.cmake +++ /dev/null @@ -1,26 +0,0 @@ -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR aarch64) -set(CMAKE_SYSTEM_VERSION 1) - -message(STATUS "Using cross-compile toolchain: ${CROSS_COMPILE_TOOLCHAIN}") - -set(CMAKE_C_COMPILER_TARGET "aarch64-linux-gnu") -set(CMAKE_CXX_COMPILER_TARGET "aarch64-linux-gnu") - -set(CMAKE_CROSSCOMPILING TRUE) -set(CMAKE_CROSSCOMPILING_EMULATOR qemu-aarch64 -L /usr/${CMAKE_C_COMPILER_TARGET}/) - -SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) - -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) -if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") -endif() -set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) - -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) -if(CXX_COMPILER_FULL_PATH) - set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) -endif() diff --git a/libs/zlibng/cmake/toolchain-arm.cmake b/libs/zlibng/cmake/toolchain-arm.cmake deleted file mode 100644 index 0e3c5c377e..0000000000 --- a/libs/zlibng/cmake/toolchain-arm.cmake +++ /dev/null @@ -1,24 +0,0 @@ -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR arm) -set(CMAKE_SYSTEM_VERSION 1) - -message(STATUS "Using cross-compile toolchain: ${CMAKE_C_COMPILER_TARGET}") - -set(CMAKE_CROSSCOMPILING TRUE) -set(CMAKE_CROSSCOMPILING_EMULATOR qemu-arm -L /usr/${CMAKE_C_COMPILER_TARGET}/) - -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) -if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") -endif() -set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) - -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) -if(CXX_COMPILER_FULL_PATH) - set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) -endif() diff --git a/libs/zlibng/cmake/toolchain-mingw-i686.cmake b/libs/zlibng/cmake/toolchain-mingw-i686.cmake deleted file mode 100644 index 588ec0ef9c..0000000000 --- a/libs/zlibng/cmake/toolchain-mingw-i686.cmake +++ /dev/null @@ -1,16 +0,0 @@ -set(CMAKE_SYSTEM_NAME Windows) - -set(CMAKE_C_COMPILER_TARGET i686) -set(CMAKE_CXX_COMPILER_TARGET i686) - -set(CMAKE_C_COMPILER i686-w64-mingw32-gcc) -set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) -set(CMAKE_RC_COMPILER i686-w64-mingw32-windres) - -set(CMAKE_CROSSCOMPILING TRUE) -set(CMAKE_CROSSCOMPILING_EMULATOR wine) - -set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/libs/zlibng/cmake/toolchain-mingw-x86_64.cmake b/libs/zlibng/cmake/toolchain-mingw-x86_64.cmake deleted file mode 100644 index c778b72227..0000000000 --- a/libs/zlibng/cmake/toolchain-mingw-x86_64.cmake +++ /dev/null @@ -1,16 +0,0 @@ -set(CMAKE_SYSTEM_NAME Windows) - -set(CMAKE_C_COMPILER_TARGET x86_64) -set(CMAKE_CXX_COMPILER_TARGET x86_64) - -set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) -set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) -set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) - -set(CMAKE_CROSSCOMPILING TRUE) -set(CMAKE_CROSSCOMPILING_EMULATOR wine) - -set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/libs/zlibng/cmake/toolchain-powerpc.cmake b/libs/zlibng/cmake/toolchain-powerpc.cmake deleted file mode 100644 index 4f7f8e92f5..0000000000 --- a/libs/zlibng/cmake/toolchain-powerpc.cmake +++ /dev/null @@ -1,25 +0,0 @@ -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR powerpc) -set(CMAKE_SYSTEM_VERSION 1) - -set(CMAKE_C_COMPILER_TARGET "powerpc-linux-gnu") -set(CMAKE_CXX_COMPILER_TARGET "powerpc-linux-gnu") - -set(CMAKE_CROSSCOMPILING TRUE) -set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc -L /usr/${CMAKE_C_COMPILER_TARGET}/) - -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) -if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") -endif() -set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) - -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) -if(CXX_COMPILER_FULL_PATH) - set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) -endif() diff --git a/libs/zlibng/cmake/toolchain-powerpc64.cmake b/libs/zlibng/cmake/toolchain-powerpc64.cmake deleted file mode 100644 index 4be3bbd59c..0000000000 --- a/libs/zlibng/cmake/toolchain-powerpc64.cmake +++ /dev/null @@ -1,25 +0,0 @@ -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR ppc64) -set(CMAKE_SYSTEM_VERSION 1) - -set(CMAKE_C_COMPILER_TARGET "powerpc64-linux-gnu") -set(CMAKE_CXX_COMPILER_TARGET "powerpc64-linux-gnu") - -set(CMAKE_CROSSCOMPILING TRUE) -set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64 -L /usr/${CMAKE_C_COMPILER_TARGET}/) - -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) -if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") -endif() -set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) - -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) -if(CXX_COMPILER_FULL_PATH) - set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) -endif() diff --git a/libs/zlibng/cmake/toolchain-powerpc64le.cmake b/libs/zlibng/cmake/toolchain-powerpc64le.cmake deleted file mode 100644 index 5535f616f6..0000000000 --- a/libs/zlibng/cmake/toolchain-powerpc64le.cmake +++ /dev/null @@ -1,25 +0,0 @@ -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR ppc64le) -set(CMAKE_SYSTEM_VERSION 1) - -set(CMAKE_C_COMPILER_TARGET "powerpc64le-linux-gnu") -set(CMAKE_CXX_COMPILER_TARGET "powerpc64le-linux-gnu") - -set(CMAKE_CROSSCOMPILING TRUE) -set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64le -L /usr/${CMAKE_C_COMPILER_TARGET}/) - -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) -if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") -endif() -set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) - -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) -if(CXX_COMPILER_FULL_PATH) - set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) -endif() diff --git a/libs/zlibng/cmake/toolchain-s390x.cmake b/libs/zlibng/cmake/toolchain-s390x.cmake deleted file mode 100644 index 41bc0d1011..0000000000 --- a/libs/zlibng/cmake/toolchain-s390x.cmake +++ /dev/null @@ -1,25 +0,0 @@ -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR s390x) -set(CMAKE_SYSTEM_VERSION 1) - -set(CMAKE_C_COMPILER_TARGET "s390x-linux-gnu") -set(CMAKE_CXX_COMPILER_TARGET "s390x-linux-gnu") - -set(CMAKE_CROSSCOMPILING TRUE) -set(CMAKE_CROSSCOMPILING_EMULATOR qemu-s390x -L /usr/${CMAKE_C_COMPILER_TARGET}/) - -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) -if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") -endif() -set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) - -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) -if(CXX_COMPILER_FULL_PATH) - set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) -endif() diff --git a/libs/zlibng/cmake/toolchain-sparc64.cmake b/libs/zlibng/cmake/toolchain-sparc64.cmake deleted file mode 100644 index f0cd99565e..0000000000 --- a/libs/zlibng/cmake/toolchain-sparc64.cmake +++ /dev/null @@ -1,25 +0,0 @@ -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR sparc64) -set(CMAKE_SYSTEM_VERSION 1) - -set(CMAKE_C_COMPILER_TARGET "sparc64-linux-gnu") -set(CMAKE_CXX_COMPILER_TARGET "sparc64-linux-gnu") - -set(CMAKE_CROSSCOMPILING TRUE) -set(CMAKE_CROSSCOMPILING_EMULATOR qemu-sparc64 -L /usr/${CMAKE_C_COMPILER_TARGET}/) - -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) -if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") -endif() -set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) - -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) -if(CXX_COMPILER_FULL_PATH) - set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) -endif() diff --git a/libs/zlibng/compare258.c b/libs/zlibng/compare258.c deleted file mode 100644 index bc41638ae8..0000000000 --- a/libs/zlibng/compare258.c +++ /dev/null @@ -1,186 +0,0 @@ -/* compare258.c -- aligned and unaligned versions of compare258 - * Copyright (C) 2020 Nathan Moinvaziri - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "zutil.h" - -#include "fallback_builtins.h" - -/* ALIGNED, byte comparison */ -static inline uint32_t compare256_c_static(const unsigned char *src0, const unsigned char *src1) { - uint32_t len = 0; - - do { - if (*src0 != *src1) - return len + (*src0 == *src1); - src0 += 1, src1 += 1, len += 1; - if (*src0 != *src1) - return len + (*src0 == *src1); - src0 += 1, src1 += 1, len += 1; - if (*src0 != *src1) - return len + (*src0 == *src1); - src0 += 1, src1 += 1, len += 1; - if (*src0 != *src1) - return len + (*src0 == *src1); - src0 += 1, src1 += 1, len += 1; - if (*src0 != *src1) - return len + (*src0 == *src1); - src0 += 1, src1 += 1, len += 1; - if (*src0 != *src1) - return len + (*src0 == *src1); - src0 += 1, src1 += 1, len += 1; - if (*src0 != *src1) - return len + (*src0 == *src1); - src0 += 1, src1 += 1, len += 1; - if (*src0 != *src1) - return len + (*src0 == *src1); - src0 += 1, src1 += 1, len += 1; - } while (len < 256); - - return 256; -} - -static inline uint32_t compare258_c_static(const unsigned char *src0, const unsigned char *src1) { - if (*src0 != *src1) - return 0; - src0 += 1, src1 += 1; - if (*src0 != *src1) - return 1; - src0 += 1, src1 += 1; - - return compare256_c_static(src0, src1) + 2; -} - -Z_INTERNAL uint32_t compare258_c(const unsigned char *src0, const unsigned char *src1) { - return compare258_c_static(src0, src1); -} - -#define LONGEST_MATCH longest_match_c -#define COMPARE256 compare256_c_static -#define COMPARE258 compare258_c_static - -#include "match_tpl.h" - -#ifdef UNALIGNED_OK -/* UNALIGNED_OK, 16-bit integer comparison */ -static inline uint32_t compare256_unaligned_16_static(const unsigned char *src0, const unsigned char *src1) { - uint32_t len = 0; - - do { - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return len + (*src0 == *src1); - src0 += 2, src1 += 2, len += 2; - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return len + (*src0 == *src1); - src0 += 2, src1 += 2, len += 2; - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return len + (*src0 == *src1); - src0 += 2, src1 += 2, len += 2; - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return len + (*src0 == *src1); - src0 += 2, src1 += 2, len += 2; - } while (len < 256); - - return 256; -} - -static inline uint32_t compare258_unaligned_16_static(const unsigned char *src0, const unsigned char *src1) { - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return (*src0 == *src1); - - return compare256_unaligned_16_static(src0+2, src1+2) + 2; -} - -Z_INTERNAL uint32_t compare258_unaligned_16(const unsigned char *src0, const unsigned char *src1) { - return compare258_unaligned_16_static(src0, src1); -} - -#define LONGEST_MATCH longest_match_unaligned_16 -#define COMPARE256 compare256_unaligned_16_static -#define COMPARE258 compare258_unaligned_16_static - -#include "match_tpl.h" - -#ifdef HAVE_BUILTIN_CTZ -/* UNALIGNED_OK, 32-bit integer comparison */ -static inline uint32_t compare256_unaligned_32_static(const unsigned char *src0, const unsigned char *src1) { - uint32_t len = 0; - - do { - uint32_t sv = *(uint32_t *)src0; - uint32_t mv = *(uint32_t *)src1; - uint32_t diff = sv ^ mv; - - if (diff) { - uint32_t match_byte = __builtin_ctz(diff) / 8; - return len + match_byte; - } - - src0 += 4, src1 += 4, len += 4; - } while (len < 256); - - return 256; -} - -static inline uint32_t compare258_unaligned_32_static(const unsigned char *src0, const unsigned char *src1) { - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return (*src0 == *src1); - - return compare256_unaligned_32_static(src0+2, src1+2) + 2; -} - -Z_INTERNAL uint32_t compare258_unaligned_32(const unsigned char *src0, const unsigned char *src1) { - return compare258_unaligned_32_static(src0, src1); -} - -#define LONGEST_MATCH longest_match_unaligned_32 -#define COMPARE256 compare256_unaligned_32_static -#define COMPARE258 compare258_unaligned_32_static - -#include "match_tpl.h" - -#endif - -#if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) -/* UNALIGNED64_OK, 64-bit integer comparison */ -static inline uint32_t compare256_unaligned_64_static(const unsigned char *src0, const unsigned char *src1) { - uint32_t len = 0; - - do { - uint64_t sv = *(uint64_t *)src0; - uint64_t mv = *(uint64_t *)src1; - uint64_t diff = sv ^ mv; - - if (diff) { - uint64_t match_byte = __builtin_ctzll(diff) / 8; - return len + (uint32_t)match_byte; - } - - src0 += 8, src1 += 8, len += 8; - } while (len < 256); - - return 256; -} - -static inline uint32_t compare258_unaligned_64_static(const unsigned char *src0, const unsigned char *src1) { - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return (*src0 == *src1); - - return compare256_unaligned_64_static(src0+2, src1+2) + 2; -} - -Z_INTERNAL uint32_t compare258_unaligned_64(const unsigned char *src0, const unsigned char *src1) { - return compare258_unaligned_64_static(src0, src1); -} - -#define LONGEST_MATCH longest_match_unaligned_64 -#define COMPARE256 compare256_unaligned_64_static -#define COMPARE258 compare258_unaligned_64_static - -#include "match_tpl.h" - -#endif - -#endif diff --git a/libs/zlibng/compress.c b/libs/zlibng/compress.c deleted file mode 100644 index d5379591d1..0000000000 --- a/libs/zlibng/compress.c +++ /dev/null @@ -1,83 +0,0 @@ -/* compress.c -- compress a memory buffer - * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#define ZLIB_INTERNAL -#include "zbuild.h" -#if defined(ZLIB_COMPAT) -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -/* =========================================================================== - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ -int Z_EXPORT PREFIX(compress2)(unsigned char *dest, z_size_t *destLen, const unsigned char *source, - z_size_t sourceLen, int level) { - PREFIX3(stream) stream; - int err; - const unsigned int max = (unsigned int)-1; - z_size_t left; - - left = *destLen; - *destLen = 0; - - stream.zalloc = NULL; - stream.zfree = NULL; - stream.opaque = NULL; - - err = PREFIX(deflateInit)(&stream, level); - if (err != Z_OK) - return err; - - stream.next_out = dest; - stream.avail_out = 0; - stream.next_in = (z_const unsigned char *)source; - stream.avail_in = 0; - - do { - if (stream.avail_out == 0) { - stream.avail_out = left > (unsigned long)max ? max : (unsigned int)left; - left -= stream.avail_out; - } - if (stream.avail_in == 0) { - stream.avail_in = sourceLen > (unsigned long)max ? max : (unsigned int)sourceLen; - sourceLen -= stream.avail_in; - } - err = PREFIX(deflate)(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); - } while (err == Z_OK); - - *destLen = (z_size_t)stream.total_out; - PREFIX(deflateEnd)(&stream); - return err == Z_STREAM_END ? Z_OK : err; -} - -/* =========================================================================== - */ -int Z_EXPORT PREFIX(compress)(unsigned char *dest, z_size_t *destLen, const unsigned char *source, z_size_t sourceLen) { - return PREFIX(compress2)(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); -} - -/* =========================================================================== - If the default memLevel or windowBits for deflateInit() is changed, then - this function needs to be updated. - */ -z_size_t Z_EXPORT PREFIX(compressBound)(z_size_t sourceLen) { -#ifndef NO_QUICK_STRATEGY - /* Quick deflate strategy worse case is 9 bits per literal, rounded to nearest byte, - plus the size of block & gzip headers and footers */ - return sourceLen + ((sourceLen + 13 + 7) >> 3) + 18; -#else - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13; -#endif -} diff --git a/libs/zlibng/configure b/libs/zlibng/configure deleted file mode 100644 index 171a76876f..0000000000 --- a/libs/zlibng/configure +++ /dev/null @@ -1,1725 +0,0 @@ -#!/usr/bin/env bash -# configure script for zlib. -# -# Normally configure builds both a static and a shared library. -# If you want to build just a static library, use: ./configure --static -# -# To impose specific compiler or flags or install directory, use for example: -# prefix=$HOME CC=cc CFLAGS="-O4" ./configure -# or for csh/tcsh users: -# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure) - -# Incorrect settings of CC or CFLAGS may prevent creating a shared library. -# If you have problems, try without defining CC and CFLAGS before reporting -# an error. - -# start off configure.log -echo -------------------- >> configure.log -echo $0 $* >> configure.log -date >> configure.log - -SRCDIR=$(cd $(dirname $0); pwd) -BUILDDIR=$(pwd) - -# set command prefix for cross-compilation -if [ -n "${CHOST}" ]; then - # normalize the chost before parsing it - NORM_CHOST=$(sh "$SRCDIR"/tools/config.sub $CHOST) - uname="$(echo "${NORM_CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/')" - CROSS_PREFIX="${CHOST}-" - ARCH="$(echo "${NORM_CHOST}" | sed -e 's/-.*//')" -else - ARCH="`uname -m`" -fi - -case "${ARCH}" in - x86_64) - case "${CFLAGS}" in - *-m32*) - ARCH=i686 - ;; - esac - ;; - i386 | i486 | i586 | i686) - case "${CFLAGS}" in - *-m64*) - ARCH=x86_64 - ;; - esac - ;; -esac - -# destination name for windows import library -IMPORTLIB= - -# establish commands for library building -if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then - AR=${AR-"${CROSS_PREFIX}ar"} - test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log -else - AR=${AR-"ar"} - test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log -fi -ARFLAGS=${ARFLAGS-"rc"} -if "${CROSS_PREFIX}ranlib" --version >/dev/null 2>/dev/null || test $? -lt 126; then - RANLIB=${RANLIB-"${CROSS_PREFIX}ranlib"} - test -n "${CROSS_PREFIX}" && echo Using ${RANLIB} | tee -a configure.log -else - RANLIB=${RANLIB-"ranlib"} -fi - -# set defaults before processing command line options -LDCONFIG=${LDCONFIG-"ldconfig"} -LDFLAGS=${LDFLAGS} -LDSHAREDLIBC="${LDSHAREDLIBC}" -DEFFILE= -RC= -RCFLAGS= -RCOBJS= -STRIP= -ARCHS= -prefix=${prefix-/usr/local} -exec_prefix=${exec_prefix-'${prefix}'} -bindir=${bindir-'${exec_prefix}/bin'} -libdir=${libdir-'${exec_prefix}/lib'} -sharedlibdir=${sharedlibdir-'${libdir}'} -includedir=${includedir-'${prefix}/include'} -mandir=${mandir-'${prefix}/share/man'} -shared_ext='.so' -shared=1 -gzfileops=1 -compat=0 -cover=0 -build32=0 -build64=0 -buildacle=1 -buildneon=1 -builddfltccdeflate=0 -builddfltccinflate=0 -with_sanitizer="" -with_fuzzers=0 -floatabi= -native=0 -forcesse2=0 -avx2flag="-mavx2" -sse2flag="-msse2" -ssse3flag="-mssse3" -sse4flag="-msse4" -sse42flag="-msse4.2" -pclmulflag="-mpclmul" -acleflag= -neonflag= -without_optimizations=0 -without_new_strategies=0 -gcc=0 -warn=0 -debug=0 -old_cc="$CC" -old_cflags="$CFLAGS" -OBJC='$(OBJZ)' -PIC_OBJC='$(PIC_OBJZ)' -INSTALLTARGETS="install-shared install-static" -UNINSTALLTARGETS="uninstall-shared uninstall-static" - -TEST="teststatic" - -# leave this script, optionally in a bad way -leave() -{ - if test "$*" != "0"; then - echo "** $0 aborting." | tee -a configure.log - fi - rm -f $test.[co] $test $test$shared_ext $test.gcno ./--version - echo -------------------- >> configure.log - echo >> configure.log - echo >> configure.log - exit $1 -} - -# process command line options -while test $# -ge 1 -do -case "$1" in - -h* | --help) - echo 'usage:' | tee -a configure.log - echo ' configure [--prefix=PREFIX] [--eprefix=EXPREFIX]' | tee -a configure.log - echo ' [--static] [--32] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log - echo ' [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log - echo ' [--warn] Enables extra compiler warnings' | tee -a configure.log - echo ' [--debug] Enables extra debug prints during operation' | tee -a configure.log - echo ' [--zlib-compat] Compiles for zlib-compatible API instead of zlib-ng API' | tee -a configure.log - echo ' [--without-gzfileops] Compiles with the gzfile parts of the API enabled' | tee -a configure.log - echo ' [--without-optimizations] Compiles without support for optional instruction sets' | tee -a configure.log - echo ' [--without-new-strategies] Compiles without using new additional deflate strategies' | tee -a configure.log - echo ' [--without-acle] Compiles without ARM C Language Extensions' | tee -a configure.log - echo ' [--without-neon] Compiles without ARM Neon SIMD instruction set' | tee -a configure.log - echo ' [--with-dfltcc-deflate] Use DEFLATE CONVERSION CALL instruction for compression on IBM Z' | tee -a configure.log - echo ' [--with-dfltcc-inflate] Use DEFLATE CONVERSION CALL instruction for decompression on IBM Z' | tee -a configure.log - echo ' [--force-sse2] Assume SSE2 instructions are always available (disabled by default on x86, enabled on x86_64)' | tee -a configure.log - echo ' [--with-sanitizer] Build with sanitizer (memory, address, undefined)' | tee -a configure.log - echo ' [--with-fuzzers] Build test/fuzz (disabled by default)' | tee -a configure.log - echo ' [--native] Compiles with full instruction set supported on this host' | tee -a configure.log - exit 0 ;; - -p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;; - -e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;; - -l*=* | --libdir=*) libdir=`echo $1 | sed 's/.*=//'`; shift ;; - --sharedlibdir=*) sharedlibdir=`echo $1 | sed 's/.*=//'`; shift ;; - -i*=* | --includedir=*) includedir=`echo $1 | sed 's/.*=//'`;shift ;; - -u*=* | --uname=*) uname=`echo $1 | sed 's/.*=//'`;shift ;; - -p* | --prefix) prefix="$2"; shift; shift ;; - -e* | --eprefix) exec_prefix="$2"; shift; shift ;; - -l* | --libdir) libdir="$2"; shift; shift ;; - -i* | --includedir) includedir="$2"; shift; shift ;; - -s* | --shared | --enable-shared) shared=1; shift ;; - -t | --static) shared=0; shift ;; - --zlib-compat) compat=1; shift ;; - --without-gzfileops) gzfileops=0; shift ;; - --cover) cover=1; shift ;; - -3* | --32) build32=1; shift ;; - -6* | --64) build64=1; shift ;; - --without-acle) buildacle=0; shift ;; - --without-neon) buildneon=0; shift ;; - --with-dfltcc-deflate) builddfltccdeflate=1; shift ;; - --with-dfltcc-inflate) builddfltccinflate=1; shift ;; - --force-sse2) forcesse2=1; shift ;; - -n | --native) native=1; shift ;; - -a*=* | --archs=*) ARCHS=`echo $1 | sed 's/.*=//'`; shift ;; - --sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;; - --localstatedir=*) echo "ignored option: --localstatedir" | tee -a configure.log; shift ;; - -noopt | --without-optimizations) without_optimizations=1; shift;; - -oldstrat | --without-new-strategies) without_new_strategies=1; shift;; - -w* | --warn) warn=1; shift ;; - -d* | --debug) debug=1; shift ;; - --with-sanitizer=*) with_sanitizer=`echo $1 | sed 's/.*=//'`; shift ;; - --with-fuzzers) with_fuzzers=1; shift ;; - - *) - echo "unknown option: $1" | tee -a configure.log - echo "$0 --help for help" | tee -a configure.log - leave 1;; - esac -done - -# temporary file name -test=ztest$$ - -# put arguments in log, also put test file in log if used in arguments -show() -{ - case "$*" in - *$test.c*) - echo === $test.c === >> configure.log - cat $test.c >> configure.log - echo === >> configure.log;; - esac - echo $* >> configure.log -} - -# check for gcc vs. cc and set compile and link flags based on the system identified by uname -cat > $test.c <&1` in - *gcc*) gcc=1 ;; - *clang*) gcc=1 ;; -esac - -if test $build32 -eq 1; then - CFLAGS="${CFLAGS} -m32" - SFLAGS="${SFLAGS} -m32" - LDFLAGS="${LDFLAGS} -m32" -fi -if test $build64 -eq 1; then - CFLAGS="${CFLAGS} -m64" - SFLAGS="${SFLAGS} -m64" - LDFLAGS="${LDFLAGS} -m64" -fi - -# Set library name depending on zlib-compat option -if test $compat -eq 0; then - LIBNAME=libz-ng - LIBNAME2=zlib-ng - SUFFIX=-ng -else - LIBNAME=libz - LIBNAME2=zlib - SUFFIX="" -fi - -STATICLIB=${LIBNAME}.a -MAPNAME=${LIBNAME2}.map - -# extract zlib version numbers from zlib.h -if test $compat -eq 0; then - VER=`sed -n -e '/ZLIBNG_VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}/zlib-ng.h` - VER3=`sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}/zlib-ng.h` - VER2=`sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < ${SRCDIR}/zlib-ng.h` - VER1=`sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}/zlib-ng.h` -else - VER=`sed -n -e '/ZLIB_VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}/zlib.h` - VER3=`sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}/zlib.h` - VER2=`sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < ${SRCDIR}/zlib.h` - VER1=`sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}/zlib.h` -fi - -show $cc -c $test.c -if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then - echo "$cc" | tee -a configure.log - CC="$cc" - CFLAGS="${CFLAGS} -std=c99" - - # Re-check ARCH if the compiler is a cross-compiler. - if $CC -print-multiarch 1> /dev/null 2>&1 && test -n "$($CC -print-multiarch)" 1> /dev/null 2>&1; then - CC_ARCH=`$CC $CFLAGS -print-multiarch | sed 's/-.*//g'` - else - CC_ARCH=`$CC $CFLAGS -dumpmachine | sed 's/-.*//g'` - fi - case $CC_ARCH in - i386 | i486 | i586 | i686) - # Honor user choice if gcc is multilib and 64-bit is requested - if test $build64 -eq 1; then - ARCH=x86_64 - else - ARCH=$CC_ARCH - fi ;; - x86_64) - # Honor user choice if gcc is multilib and 32-bit is requested - if test $build32 -ne 1; then - ARCH=$CC_ARCH - fi ;; - arm | armeb) - if test $native -eq 0; then - ARCH=arm - else - ARCH=native - fi - if test "${uname}" = "eabi"; then - # No ACLE support - uname=arm - if test $buildacle -eq 1; then - echo ACLE support not available - buildacle=0 - fi - fi - if test $buildacle -eq 1; then - if test $native -eq 0; then - ARCH=armv8-a+crc - fi - fi ;; - armv8l) - if test $native -eq 0; then - ARCH=armv8-a - else - ARCH=native - fi ;; - aarch64 | aarch64_be) - if test "${uname}" = "elf"; then - uname=aarch64 - fi - if test $native -eq 0; then - ARCH=aarch64 - else - ARCH=native - fi ;; - powerpc | ppc) - ARCH=powerpc ;; - powerpc64 | ppc64) - ARCH=powerpc64 ;; - powerpc64le | ppc64le) - ARCH=powerpc64le ;; - esac - CFLAGS="-O2 ${CFLAGS}" - if test -n "${ARCHS}"; then - CFLAGS="${CFLAGS} ${ARCHS}" - LDFLAGS="${LDFLAGS} ${ARCHS}" - fi - CFLAGS="${CFLAGS} -Wall" - SFLAGS="${CFLAGS} -fPIC" - if test $native -eq 1; then - case $ARCH in - powerpc*) - NATIVE_FLAG="-mcpu=native" ;; - *) - NATIVE_FLAG="-march=native" ;; - esac - CFLAGS="${CFLAGS} ${NATIVE_FLAG}" - SFLAGS="${SFLAGS} ${NATIVE_FLAG}" - fi - if test "$warn" -eq 1; then - CFLAGS="${CFLAGS} -Wextra -Wpedantic -Wno-implicit-fallthrough" - fi - if test $debug -eq 1; then - CFLAGS="${CFLAGS} -DZLIB_DEBUG" - SFLAGS="${SFLAGS} -DZLIB_DEBUG" - fi - if test -z "$uname"; then - uname=`(uname -s || echo unknown) 2>/dev/null` - fi - case "$uname" in - Linux* | linux* | GNU | GNU/* | solaris*) - LDSHARED=${LDSHARED-"$cc"} - LDSHAREDFLAGS="-shared -Wl,-soname,${LIBNAME}.so.${VER1},--version-script,${SRCDIR}/${MAPNAME}" ;; - *BSD | *bsd* | DragonFly) - LDSHARED=${LDSHARED-"$cc"} - LDSHAREDFLAGS="-shared -Wl,-soname,${LIBNAME}.so.${VER1},--version-script,${SRCDIR}/${MAPNAME}" - LDCONFIG="ldconfig -m" ;; - CYGWIN* | Cygwin* | cygwin*) - ARFLAGS="rcs" - SFLAGS="${CFLAGS}" - shared_ext='.dll' - sharedlibdir='${bindir}' - if test $compat -eq 0; then - SHAREDLIB=cygz-ng$shared_ext - else - SHAREDLIB=cygz$shared_ext - fi - SHAREDLIBM='' - SHAREDLIBV='' - SHAREDTARGET=$SHAREDLIB - IMPORTLIB="${LIBNAME}.dll.a" - LDSHARED=${LDSHARED-"$cc"} - LDSHAREDFLAGS="-shared -Wl,--out-implib,${IMPORTLIB},--version-script,${SRCDIR}/${MAPNAME}" - LDSHAREDLIBC="" - DEFFILE='win32/${LIBNAME2}.def' - RC="${CROSS_PREFIX}windres" - RCFLAGS='--define GCC_WINDRES' - RCOBJS='zlibrc.o' - STRIP="${CROSS_PREFIX}strip" - EXE='.exe' ;; - MSYS* | msys*) - ARFLAGS="rcs" - SFLAGS="${CFLAGS}" - shared_ext='.dll' - sharedlibdir='${bindir}' - if test $compat -eq 0; then - SHAREDLIB=msys-z-ng$shared_ext - else - SHAREDLIB=msys-z$shared_ext - fi - SHAREDLIBM='' - SHAREDLIBV='' - SHAREDTARGET=$SHAREDLIB - IMPORTLIB="${LIBNAME}.dll.a" - LDSHARED=${LDSHARED-"$cc"} - LDSHAREDFLAGS="-shared -Wl,--out-implib,${IMPORTLIB}" - LDSHAREDLIBC="" - DEFFILE='win32/${LIBNAME2}.def' - RC="${CROSS_PREFIX}windres" - RCFLAGS='--define GCC_WINDRES' - RCOBJS='zlibrc.o' - STRIP="${CROSS_PREFIX}strip" - EXE='.exe' ;; - MINGW* | mingw*) - ARFLAGS="rcs" - CFLAGS="${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_GNU_SOURCE=1" - SFLAGS="${CFLAGS}" - shared_ext='.dll' - sharedlibdir='${bindir}' - SHAREDLIB=${LIBNAME}-$VER1$shared_ext - SHAREDLIBM='' - SHAREDLIBV='' - SHAREDTARGET=$SHAREDLIB - IMPORTLIB="${LIBNAME}.dll.a" - LDSHARED=${LDSHARED-"$cc"} - LDSHAREDFLAGS="-shared -Wl,--out-implib=${IMPORTLIB} -Wl,--version-script=${SRCDIR}/${MAPNAME}" - LDSHAREDLIBC="" - DEFFILE='win32/${LIBNAME2}.def' - RC="${CROSS_PREFIX}windres" - RCFLAGS='--define GCC_WINDRES' - if [ "$CC" == "mingw32-gcc" ]; then - case $ARCH in - i386 | i486 | i586 | i686) RCFLAGS="${RCFLAGS} -F pe-i386";; - esac; - fi - RCOBJS='zlibrc.o' - STRIP="${CROSS_PREFIX}strip" - EXE='.exe' ;; - QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 - # (alain.bonnefoy@icbt.com) - LDSHARED=${LDSHARED-"$cc"} - LDSHAREDFLAGS="-shared -Wl,-h${LIBNAME}.so.${VER1}" ;; - HP-UX*) - LDSHARED=${LDSHARED-"$cc"} - LDSHAREDFLAGS="-shared" - case `(uname -m || echo unknown) 2>/dev/null` in - ia64) - shared_ext='.so' - SHAREDLIB='${LIBNAME}.so' ;; - *) - shared_ext='.sl' - SHAREDLIB='${LIBNAME}.sl' ;; - esac ;; - Darwin* | darwin*) - shared_ext='.dylib' - SHAREDLIB=${LIBNAME}$shared_ext - SHAREDLIBV=${LIBNAME}.$VER$shared_ext - SHAREDLIBM=${LIBNAME}.$VER1$shared_ext - SHAREDTARGET=$SHAREDLIBV - LDSHARED=${LDSHARED-"$cc"} - LDSHAREDFLAGS="-dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3" - if libtool -V 2>&1 | grep Apple > /dev/null; then - AR="libtool" - else - AR="/usr/bin/libtool" - fi - ARFLAGS="-o" ;; - aarch64) - LDSHARED=${LDSHARED-"$cc"} - LDSHAREDFLAGS="-shared -Wl,-soname,${LIBNAME}.so.${VER1} -Wl,--version-script,${SRCDIR}/${MAPNAME}" - LDSHAREDLIBC="-Wl,--start-group -lc -lrdimon -Wl,--end-group" ;; - *) - LDSHARED=${LDSHARED-"$cc"} - LDSHAREDFLAGS="-shared" ;; - esac -else - # find system name and corresponding cc options - CC=${CC-cc} - gcc=0 - echo "$CC" | tee -a configure.log - if test -z "$uname"; then - uname=`(uname -sr || echo unknown) 2>/dev/null` - fi - case "$uname" in - HP-UX*) SFLAGS=${CFLAGS-"-O +z"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"ld"} - LDSHAREDFLAGS="-b" - case `(uname -m || echo unknown) 2>/dev/null` in - ia64) - shared_ext='.so' - SHAREDLIB='${LIBNAME}.so' ;; - *) - shared_ext='.sl' - SHAREDLIB='${LIBNAME}.sl' ;; - esac ;; - AIX*) # Courtesy of dbakker@arrayasolutions.com - SFLAGS=${CFLAGS-"-O -qmaxmem=8192"} - CFLAGS=${CFLAGS-"-O -qmaxmem=8192"} - LDSHARED=${LDSHARED-"xlc"} - LDSHAREDFLAGS="-G" ;; - # send working options for other systems to zlib@gzip.org - *) SFLAGS=${CFLAGS-"-O"} - CFLAGS=${CFLAGS-"-O"} - LDSHARED=${LDSHARED-"cc"} - LDSHAREDFLAGS="-shared" ;; - esac -fi - -# destination names for shared library if not defined above -SHAREDLIB=${SHAREDLIB-"${LIBNAME}$shared_ext"} -SHAREDLIBV=${SHAREDLIBV-"${LIBNAME}$shared_ext.$VER"} -SHAREDLIBM=${SHAREDLIBM-"${LIBNAME}$shared_ext.$VER1"} -SHAREDTARGET=${SHAREDTARGET-"${LIBNAME}$shared_ext.$VER"} - -echo >> configure.log - -# define functions for testing compiler and library characteristics and logging the results - -cat > $test.c </dev/null; then - try() - { - show $* - test "`( $* ) 2>&1 | tee -a configure.log`" = "" - } - echo - using any output from compiler to indicate an error >> configure.log -else -try() -{ - show $* - ( $* ) >> configure.log 2>&1 - ret=$? - if test $ret -ne 0; then - echo "(exit code "$ret")" >> configure.log - fi - return $ret -} -fi - -tryboth() -{ - show $* - got=`( $* ) 2>&1` - ret=$? - printf %s "$got" >> configure.log - if test $ret -ne 0; then - return $ret - fi - test "$got" = "" -} - -cat > $test.c << EOF -int foo() { return 0; } -EOF -echo "Checking for obsessive-compulsive compiler options..." >> configure.log -if try $CC -c $CFLAGS $test.c; then - : -else - echo "Compiler error reporting is too harsh for $0 (perhaps remove -Werror)." | tee -a configure.log - leave 1 -fi - -echo >> configure.log - -if test "$with_sanitizer" = "address"; then - echo -n "Checking for address sanitizer... " | tee -a configure.log - sanitizers="" - for san in address pointer-compare pointer-subtract; do - if try $CC -c $CFLAGS $test.c -fsanitize=$san ; then - if test -n "$sanitizers"; then - sanitizers="$sanitizers,$san" - else - sanitizers="$san" - fi - fi - done - - if test -n "$sanitizers"; then - echo "-fsanitize=$sanitizers" | tee -a configure.log - CFLAGS="$CFLAGS -fsanitize=$sanitizers" - SFLAGS="$SFLAGS -fsanitize=$sanitizers" - LDFLAGS="$LDFLAGS -fsanitize=$sanitizers" - else - echo No | tee -a configure.log - fi - - echo -n "Checking for leak sanitizer... " | tee -a configure.log - if try $CC -c $CFLAGS $test.c -fsanitize=leak; then - echo "-fsanitize=leak" | tee -a configure.log - CFLAGS="$CFLAGS -fsanitize=leak" - SFLAGS="$SFLAGS -fsanitize=leak" - LDFLAGS="$LDFLAGS -fsanitize=leak" - else - echo No | tee -a configure.log - fi - - echo >> configure.log -fi - -if test "$with_sanitizer" = "memory"; then - echo -n "Checking for memory sanitizer... " | tee -a configure.log - if try $CC -c $CFLAGS $test.c -fsanitize=memory ; then - echo "-fsanitize=memory" | tee -a configure.log - CFLAGS="$CFLAGS -fsanitize=memory" - SFLAGS="$SFLAGS -fsanitize=memory" - LDFLAGS="$LDFLAGS -fsanitize=memory" - else - echo No | tee -a configure.log - fi - - echo >> configure.log -fi - -if test "$with_sanitizer" = "undefined"; then - echo -n "Checking for undefined behavior sanitizer... " | tee -a configure.log - sanitizers="" - for san in array-bounds bool bounds builtin enum float-cast-overflow float-divide-by-zero function integer-divide-by-zero local-bounds null nonnull-attribute object-size pointer-overflow return returns-nonnull-attribute shift shift-base shift-exponent signed-integer-overflow undefined unsigned-integer-overflow unsigned-shift-base vla-bound vptr; do - if try $CC -c $CFLAGS $test.c -fsanitize=$san; then - if test -n "$sanitizers"; then - sanitizers="$sanitizers,$san" - else - sanitizers="$san" - fi - fi - done - - if test -n "$sanitizers"; then - echo "-fsanitize=$sanitizers" | tee -a configure.log - CFLAGS="$CFLAGS -fsanitize=$sanitizers" - SFLAGS="$SFLAGS -fsanitize=$sanitizers" - LDFLAGS="$LDFLAGS -fsanitize=$sanitizers" - else - echo No | tee -a configure.log - fi - - echo >> configure.log -fi - -# see if shared library build supported -cat > $test.c <> configure.log - -# check for large file support, and if none, check for fseeko() -cat > $test.c < -off64_t dummy = 0; -EOF -if try $CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c; then - CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1" - SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1" - echo "Checking for off64_t... Yes." | tee -a configure.log - echo "Checking for fseeko... Yes." | tee -a configure.log -else - echo "Checking for off64_t... No." | tee -a configure.log - echo >> configure.log - cat > $test.c < -int main() { - _off64_t dummy = 0; - return 0; -} -EOF - if try $CC $CFLAGS -o $test $test.c $LDSHAREDLIBC; then - echo "Checking for _off64_t... Yes." | tee -a configure.log - else - echo "Checking for _off64_t... No." | tee -a configure.log - fi - echo >> configure.log - cat > $test.c < -int main(void) { - fseeko(NULL, 0, 0); - return 0; -} -EOF - if try $CC $CFLAGS -o $test $test.c $LDSHAREDLIBC; then - echo "Checking for fseeko... Yes." | tee -a configure.log - else - CFLAGS="${CFLAGS} -DNO_FSEEKO" - SFLAGS="${SFLAGS} -DNO_FSEEKO" - echo "Checking for fseeko... No." | tee -a configure.log - fi -fi - -echo >> configure.log - -# check for strerror() for use by gz* functions -cat > $test.c < -#include -int main() { return strlen(strerror(errno)); } -EOF -if try $CC $CFLAGS -o $test $test.c $LDSHAREDLIBC; then - echo "Checking for strerror... Yes." | tee -a configure.log -else - CFLAGS="${CFLAGS} -DNO_STRERROR" - SFLAGS="${SFLAGS} -DNO_STRERROR" - echo "Checking for strerror... No." | tee -a configure.log -fi - -# We need to remove zconf.h from source directory if building outside of it -if [ "$SRCDIR" != "$BUILDDIR" ]; then - rm -f $SRCDIR/zconf${SUFFIX}.h -fi - -# copy clean zconf.h for subsequent edits -cp -p $SRCDIR/zconf${SUFFIX}.h.in zconf${SUFFIX}.h - -echo >> configure.log - -# check for unistd.h and save result in zconf.h -cat > $test.c < -int main() { return 0; } -EOF -if try $CC -c $CFLAGS $test.c; then - sed < zconf${SUFFIX}.h "/^#ifdef HAVE_UNISTD_H.* may be/s/def HAVE_UNISTD_H\(.*\) may be/ 1\1 was/" > zconf${SUFFIX}.temp.h - mv zconf${SUFFIX}.temp.h zconf${SUFFIX}.h - echo "Checking for unistd.h... Yes." | tee -a configure.log -else - echo "Checking for unistd.h... No." | tee -a configure.log -fi - -echo >> configure.log - -# check for ptrdiff_t and save result in zconf.h -echo -n "Checking for ptrdiff_t... " | tee -a configure.log -cat > $test.c < -int fun(ptrdiff_t *a) { (void)a; return 0; } -EOF -if try $CC -c $CFLAGS $test.c; then - echo "Yes." | tee -a configure.log -else - echo "No." | tee -a configure.log - sed < zconf${SUFFIX}.h "/^#ifdef NEED_PTRDIFF_T.* may be/s/def NEED_PTRDIFF_T\(.*\) may be/ 1\1 was/" > zconf${SUFFIX}.temp.h - mv zconf${SUFFIX}.temp.h zconf${SUFFIX}.h - - echo -n "Checking for sizeof(void *)... " | tee -a configure.log - cat > $test.c < -#define COMPILE_TIME_ASSERT(pred) struct s { int x: (pred) ? 1 : -1; } -COMPILE_TIME_ASSERT(sizeof(int32_t) == sizeof(void *)); -EOF - if try $CC -c $CFLAGS $test.c; then - echo "sizeof(int32_t)." | tee -a configure.log - sed < zconf${SUFFIX}.h "s/^typedef PTRDIFF_TYPE ptrdiff_t;/typedef int32_t ptrdiff_t;/g" > zconf${SUFFIX}.temp.h - mv zconf${SUFFIX}.temp.h zconf${SUFFIX}.h - else - cat > $test.c < -#define COMPILE_TIME_ASSERT(pred) struct s { int x: (pred) ? 1 : -1; } -COMPILE_TIME_ASSERT(sizeof(int64_t) == sizeof(void *)); -EOF - if try $CC -c $CFLAGS $test.c; then - echo "sizeof(int64_t)." | tee -a configure.log - sed < zconf${SUFFIX}.h "s/^typedef PTRDIFF_TYPE ptrdiff_t;/typedef int64_t ptrdiff_t;/g" > zconf${SUFFIX}.temp.h - mv zconf${SUFFIX}.temp.h zconf${SUFFIX}.h - else - echo "unknown." | tee -a configure.log - exit 1 - fi - fi -fi - -# if --zlib-compat was requested -if test $compat -eq 1; then - gzfileops=1 - CFLAGS="${CFLAGS} -DZLIB_COMPAT" - SFLAGS="${SFLAGS} -DZLIB_COMPAT" - case "$uname" in - CYGWIN* | Cygwin* | cygwin* | MSYS* | msys* | MINGW* | mingw*) - DEFFILE="win32/zlibcompat.def" ;; - esac -fi - -# if --gzfileops was requested -if test $gzfileops -eq 1; then - CFLAGS="${CFLAGS} -DWITH_GZFILEOP" - SFLAGS="${SFLAGS} -DWITH_GZFILEOP" - OBJC="${OBJC} \$(OBJG)" - PIC_OBJC="${PIC_OBJC} \$(PIC_OBJG)" -fi - -# if code coverage testing was requested, use older gcc if defined, e.g. "gcc-4.2" on Mac OS X -if test $cover -eq 1; then - CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage" - LDFLAGS="${LDFLAGS} -fprofile-arcs -ftest-coverage" - if test -n "$GCC_CLASSIC"; then - CC=$GCC_CLASSIC - fi -fi - -echo >> configure.log - -# Check for ANSI C compliant compiler -cat > $test.c < -#include -#include "zconf${SUFFIX}.h" -int main() { -#ifdef STDC - return 0; -#endif - return 1; -} -EOF -if try $CC -c $CFLAGS $test.c; then - echo "Checking for ANSI C compliant compiler... Yes." | tee -a configure.log - : -else - echo "Checking for ANSI C compliant compiler... No." | tee -a configure.log - echo "Error: ANSI C compatible compiler needed, cannot continue." | tee -a configure.log - leave 1 -fi - -# Check for -fno-semantic-interposition compiler support -echo "" > test.c - cat > $test.c <> configure.log 2>&1; then - echo "Checking for -no-semantic-interposition... Yes." | tee -a configure.log - SFLAGS="$SFLAGS -fno-semantic-interposition" -else - echo "Checking for -no-semantic-interposition... No." | tee -a configure.log -fi - -# see if we can hide zlib internal symbols that are linked between separate source files using hidden -if test "$gcc" -eq 1; then - echo >> configure.log - cat > $test.c <> configure.log - echo "Checking for attribute(visibility(hidden)) support... Yes." | tee -a configure.log - else - echo >> configure.log - echo "Checking for attribute(visibility(hidden)) support... No." | tee -a configure.log - fi -fi - -# see if we can hide zlib internal symbols that are linked between separate source files using internal -if test "$gcc" -eq 1; then - echo >> configure.log - cat > $test.c <> configure.log - echo "Checking for attribute(visibility(internal)) support... Yes." | tee -a configure.log - else - echo >> configure.log - echo "Checking for attribute(visibility(internal)) support... No." | tee -a configure.log - fi -fi - -# Check for __builtin_ctz() support in compiler -cat > $test.c << EOF -int main(void) { - unsigned int zero = 0; - long test = __builtin_ctz(zero); - (void)test; - return 0; -} -EOF -if try ${CC} ${CFLAGS} $test.c $LDSHAREDLIBC; then - echo "Checking for __builtin_ctz ... Yes." | tee -a configure.log - CFLAGS="$CFLAGS -DHAVE_BUILTIN_CTZ" - SFLAGS="$SFLAGS -DHAVE_BUILTIN_CTZ" -else - echo "Checking for __builtin_ctz ... No." | tee -a configure.log -fi - -# Check for __builtin_ctzll() support in compiler -cat > $test.c << EOF -int main(void) { - unsigned long long zero = 0; - long test = __builtin_ctzll(zero); - (void)test; - return 0; -} -EOF -if try ${CC} ${CFLAGS} $test.c $LDSHAREDLIBC; then - echo "Checking for __builtin_ctzll ... Yes." | tee -a configure.log - CFLAGS="$CFLAGS -DHAVE_BUILTIN_CTZLL" - SFLAGS="$SFLAGS -DHAVE_BUILTIN_CTZLL" -else - echo "Checking for __builtin_ctzll ... No." | tee -a configure.log -fi - -# Check for SSE2 intrinsics -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - cat > $test.c << EOF -#include -int main(void) { - __m128i zero = _mm_setzero_si128(); - (void)zero; - return 0; -} -EOF - if try ${CC} ${CFLAGS} ${sse2flag} $test.c; then - echo "Checking for SSE2 intrinsics ... Yes." | tee -a configure.log - HAVE_SSE2_INTRIN=1 - else - echo "Checking for SSE2 intrinsics ... No." | tee -a configure.log - HAVE_SSE2_INTRIN=0 - fi - ;; -esac - -# Check for SSSE3 intrinsics - -cat > $test.c << EOF -#include -int main(void) -{ - __m128i u, v, w; - u = _mm_set1_epi32(1); - v = _mm_set1_epi32(2); - w = _mm_hadd_epi32(u, v); - (void)w; - return 0; -} -EOF -if try ${CC} ${CFLAGS} ${ssse3flag} $test.c; then - echo "Checking for SSSE3 intrinsics ... Yes." | tee -a configure.log - HAVE_SSSE3_INTRIN=1 -else - echo "Checking for SSSE3 intrinsics ... No." | tee -a configure.log - HAVE_SSSE3_INTRIN=0 -fi - -# Check for SSE4.2 CRC inline assembly -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - cat > $test.c << EOF -int main(void) { - unsigned val = 0, h = 0; - __asm__ __volatile__ ( "crc32 %1,%0" : "+r" (h) : "r" (val) ); - return (int) h; -} -EOF - if try ${CC} ${CFLAGS} ${sse42flag} $test.c; then - echo "Checking for SSE4.2 CRC inline assembly ... Yes." | tee -a configure.log - HAVE_SSE42CRC_INLINE_ASM=1 - else - echo "Checking for SSE4.2 CRC inline assembly ... No." | tee -a configure.log - HAVE_SSE42CRC_INLINE_ASM=0 - fi - ;; -esac - -# Check for SSE4.2 CRC intrinsics -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - cat > $test.c << EOF -int main(void) { - unsigned crc = 0; - char c = 'c'; - crc = __builtin_ia32_crc32qi(crc, c); - (void)crc; - return 0; -} -EOF - if try ${CC} ${CFLAGS} ${sse42flag} $test.c; then - echo "Checking for SSE4.2 CRC intrinsics ... Yes." | tee -a configure.log - HAVE_SSE42CRC_INTRIN=1 - else - echo "Checking for SSE4.2 CRC intrinsics ... No." | tee -a configure.log - HAVE_SSE42CRC_INTRIN=0 - fi - ;; -esac - -# Check for SSE4.2 compare string intrinsics -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - cat > $test.c << EOF -#include -int main(void) -{ - unsigned char a[64] = { 0 }; - unsigned char b[64] = { 0 }; - __m128i xmm_src0, xmm_src1; - xmm_src0 = _mm_loadu_si128((__m128i *)(char *)a); - xmm_src1 = _mm_loadu_si128((__m128i *)(char *)b); - return _mm_cmpestri(xmm_src0, 16, xmm_src1, 16, 0); -} -EOF - if try ${CC} ${CFLAGS} ${sse42flag} $test.c; then - echo "Checking for SSE4.2 compare string intrinsics ... Yes." | tee -a configure.log - HAVE_SSE42CMPSTR_INTRIN=1 - else - echo "Checking for SSE4.2 compare string intrinsics ... No." | tee -a configure.log - HAVE_SSE42CMPSTR_INTRIN=0 - fi - ;; -esac - -# Check for PCLMULQDQ intrinsics -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - cat > $test.c << EOF -#include -#include -int main(void) { - __m128i a = _mm_setzero_si128(); - __m128i b = _mm_setzero_si128(); - __m128i c = _mm_clmulepi64_si128(a, b, 0x10); - (void)c; - return 0; -} -EOF - if try ${CC} ${CFLAGS} ${pclmulflag} $test.c; then - echo "Checking for PCLMULQDQ intrinsics ... Yes." | tee -a configure.log - HAVE_PCLMULQDQ_INTRIN=1 - else - echo "Checking for PCLMULQDQ intrinsics ... No." | tee -a configure.log - HAVE_PCLMULQDQ_INTRIN=0 - fi - - # Enable deflate_medium at level 1 - if test $without_new_strategies -eq 1; then - CFLAGS="${CFLAGS} -DNO_QUICK_STRATEGY" - SFLAGS="${SFLAGS} -DNO_QUICK_STRATEGY" - fi - # Enable deflate_medium at level 4-6 - if test $without_new_strategies -eq 1; then - CFLAGS="${CFLAGS} -DNO_MEDIUM_STRATEGY" - SFLAGS="${SFLAGS} -DNO_MEDIUM_STRATEGY" - fi - ;; -esac - -# Check for AVX2 intrinsics -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - cat > $test.c << EOF -#include -int main(void) { - __m256i x = _mm256_set1_epi16(2); - const __m256i y = _mm256_set1_epi16(1); - x = _mm256_subs_epu16(x, y); - (void)x; - return 0; -} -EOF - if try ${CC} ${CFLAGS} ${avx2flag} $test.c; then - echo "Checking for AVX2 intrinsics ... Yes." | tee -a configure.log - HAVE_AVX2_INTRIN=1 - else - echo "Checking for AVX2 intrinsics ... No." | tee -a configure.log - HAVE_AVX2_INTRIN=0 - fi - ;; -esac - - -# Check whether -mfpu=neon is available on ARM processors. -case "${ARCH}" in - arm*) - cat > $test.c << EOF -int main() { return 0; } -EOF - if try $CC -c $CFLAGS -mfpu=neon $test.c; then - MFPU_NEON_AVAILABLE=1 - echo "Check whether -mfpu=neon is available ... Yes." | tee -a configure.log - else - MFPU_NEON_AVAILABLE=0 - echo "Check whether -mfpu=neon is available ... No." | tee -a configure.log - fi - ;; -esac - -# Check whether features needed by POWER optimisations are available -case "${ARCH}" in - powerpc*) - cat > $test.c << EOF -#include -int main() { return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); } -EOF - if try $CC -c $CFLAGS -mcpu=power8 $test.c; then - HAVE_POWER8=1 - echo "Check whether POWER8 instructions are available ... Yes." | tee -a configure.log - else - HAVE_POWER8=0 - echo "Check whether POWER8 instructions are available ... No." | tee -a configure.log - fi -esac - -# Check whether sys/sdt.h is available -cat > $test.c << EOF -#include -int main() { return 0; } -EOF -if try ${CC} ${CFLAGS} $test.c; then - echo "Checking for sys/sdt.h ... Yes." | tee -a configure.log - CFLAGS="$CFLAGS -DHAVE_SYS_SDT_H" - SFLAGS="$SFLAGS -DHAVE_SYS_SDT_H" -else - echo "Checking for sys/sdt.h ... No." | tee -a configure.log -fi - -ARCHDIR='arch/generic' -ARCH_STATIC_OBJS='' -ARCH_SHARED_OBJS='' - -# Set ARCH specific FLAGS -case "${ARCH}" in - # x86/amd64 specific optimizations - i386 | i486 | i586 | i686 |x86_64) - ARCHDIR=arch/x86 - - CFLAGS="${CFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - - # Enable arch-specific optimizations - if test $without_optimizations -eq 0; then - CFLAGS="${CFLAGS} -DX86_FEATURES" - SFLAGS="${SFLAGS} -DX86_FEATURES" - - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} x86.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} x86.lo" - - if test ${HAVE_AVX2_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET" - SFLAGS="${SFLAGS} -DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} slide_avx.o chunkset_avx.o compare258_avx.o adler32_avx.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} slide_avx.lo chunkset_avx.lo compare258_avx.lo adler32_avx.lo" - fi - - if test ${HAVE_SSE42CRC_INTRIN} -eq 1 || test ${HAVE_SSE42CRC_INLINE_ASM} -eq 1; then - CFLAGS="${CFLAGS} -DX86_SSE42_CRC_HASH" - SFLAGS="${SFLAGS} -DX86_SSE42_CRC_HASH" - - if test ${HAVE_SSE42CRC_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_SSE42_CRC_INTRIN" - SFLAGS="${SFLAGS} -DX86_SSE42_CRC_INTRIN" - fi - - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} insert_string_sse.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} insert_string_sse.lo" - fi - - if test ${HAVE_SSE42CMPSTR_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_SSE42_CMP_STR" - SFLAGS="${SFLAGS} -DX86_SSE42_CMP_STR" - - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} compare258_sse.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} compare258_sse.lo" - fi - - if test ${HAVE_SSE2_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_SSE2 -DX86_SSE2_CHUNKSET" - SFLAGS="${SFLAGS} -DX86_SSE2 -DX86_SSE2_CHUNKSET" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} chunkset_sse.o slide_sse.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} chunkset_sse.lo slide_sse.lo" - - if test $forcesse2 -eq 1; then - CFLAGS="${CFLAGS} -DX86_NOCHECK_SSE2" - SFLAGS="${SFLAGS} -DX86_NOCHECK_SSE2" - fi - fi - - if test ${HAVE_SSSE3_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_SSSE3 -DX86_SSSE3_ADLER32" - SFLAGS="${SFLAGS} -DX86_SSSE3 -DX86_SSSE3_ADLER32" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_ssse3.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_ssse3.lo" - fi - - if test ${HAVE_PCLMULQDQ_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_PCLMULQDQ_CRC" - SFLAGS="${SFLAGS} -DX86_PCLMULQDQ_CRC" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc_folding.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc_folding.lo" - fi - fi - ;; - - # ARM specific optimizations - arm*) - [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=arm - ARCHDIR=arch/arm - - if test $without_optimizations -eq 0; then - CFLAGS="${CFLAGS} -DARM_FEATURES" - SFLAGS="${SFLAGS} -DARM_FEATURES" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} armfeature.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} armfeature.lo" - fi - - GCC_MACHINE=$(${CC} -dumpmachine) - case "${GCC_MACHINE}" in - *gnueabihf) - floatabi="-mfloat-abi=hard" ;; - *gnueabi) - floatabi="-mfloat-abi=softfp" ;; - esac - CFLAGS="${CFLAGS} ${floatabi}" - SFLAGS="${SFLAGS} ${floatabi}" - - case "${ARCH}" in - armv[345]*) - if test $without_optimizations -eq 0; then - if test $buildacle -eq 1; then - echo ACLE support not available - fi - - if test $buildneon -eq 1; then - echo NEON support not available - fi - fi - ;; - armv6l | armv6hl) - CFLAGS="${CFLAGS} -DUNALIGNED_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK" - - if test $without_optimizations -eq 0; then - if test $buildacle -eq 1; then - echo ACLE support not available - fi - - if test $buildneon -eq 1; then - echo NEON support not available - fi - fi - ;; - arm | armv7*) - CFLAGS="${CFLAGS} -DUNALIGNED_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK" - - if test $without_optimizations -eq 0; then - if test $buildacle -eq 1; then - echo ACLE support not available - fi - - if test $buildneon -eq 1; then - if test $MFPU_NEON_AVAILABLE -eq 1;then - neonflag="-mfpu=neon" - fi - - CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_neon.lo" - fi - fi - ;; - armv8-a | armv8-a+simd) - CFLAGS="${CFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - - if test $without_optimizations -eq 0; then - if test $buildacle -eq 1; then - echo ACLE support not available - fi - - if test $buildneon -eq 1; then - if test $MFPU_NEON_AVAILABLE -eq 1;then - neonflag="-mfpu=neon" - fi - - CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_neon.lo" - fi - fi - ;; - armv8-a+crc | armv8-a+crc+simd | armv8.[1234]-a | armv8.[1234]-a+simd) - CFLAGS="${CFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - - acleflag="-march=${ARCH}" - - if test $without_optimizations -eq 0; then - CFLAGS="${CFLAGS} -DARM_ACLE_CRC_HASH" - SFLAGS="${SFLAGS} -DARM_ACLE_CRC_HASH" - - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_acle.o insert_string_acle.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_acle.lo insert_string_acle.lo" - - if test $buildneon -eq 1; then - if test $MFPU_NEON_AVAILABLE -eq 1;then - neonflag="-mfpu=neon" - fi - - CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_neon.lo" - fi - fi - ;; - esac - - ;; - # 64-bit ARM specific optimizations - aarch64) - [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=aarch64 - ARCHDIR=arch/arm - - if test $native -eq 0; then - ARCH="armv8-a" - else - ARCH="native" - fi - - if test $without_optimizations -eq 0; then - CFLAGS="${CFLAGS} -DARM_FEATURES" - SFLAGS="${SFLAGS} -DARM_FEATURES" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} armfeature.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} armfeature.lo" - - if test $buildacle -eq 1; then - if test $native -eq 0; then - ARCH="${ARCH}+crc" - fi - CFLAGS="${CFLAGS} -DARM_ACLE_CRC_HASH" - SFLAGS="${SFLAGS} -DARM_ACLE_CRC_HASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_acle.o insert_string_acle.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_acle.lo insert_string_acle.lo" - fi - - if test $buildneon -eq 1; then - if test $native -eq 0; then - ARCH="${ARCH}+simd" - fi - CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_neon.lo" - fi - fi - - neonflag="-march=${ARCH}" - acleflag="-march=${ARCH}" - - CFLAGS="${CFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - ;; - powerpc*) - case "${ARCH}" in - powerpc) - [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=ppc - ;; - powerpc64) - [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=ppc64 - ;; - powerpc64le) - [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=ppc64le - CFLAGS="${CFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - ;; - esac - - ARCHDIR=arch/power - - if test $without_optimizations -eq 0; then - if test $HAVE_POWER8 -eq 1; then - CFLAGS="${CFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_SLIDEHASH" - SFLAGS="${SFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_SLIDEHASH" - - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} power.o adler32_power8.o slide_hash_power8.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} power.lo adler32_power8.lo slide_hash_power8.lo" - fi - fi - ;; - s390x) - [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=s390x - ARCHDIR=arch/s390 - - if test $without_optimizations -eq 0; then - if test $builddfltccdeflate -eq 1 -o $builddfltccinflate -eq 1; then - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} dfltcc_common.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} dfltcc_common.lo" - fi - - if test $builddfltccdeflate -eq 1; then - CFLAGS="${CFLAGS} -DS390_DFLTCC_DEFLATE" - SFLAGS="${SFLAGS} -DS390_DFLTCC_DEFLATE" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} dfltcc_deflate.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} dfltcc_deflate.lo" - ARCH="${ARCH}+dfltcc-deflate" - fi - - if test $builddfltccinflate -eq 1; then - CFLAGS="${CFLAGS} -DS390_DFLTCC_INFLATE" - SFLAGS="${SFLAGS} -DS390_DFLTCC_INFLATE" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} dfltcc_inflate.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} dfltcc_inflate.lo" - ARCH="${ARCH}+dfltcc-inflate" - fi - fi - ;; - *) - [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=$ARCH - ;; -esac - -echo "ARCH: ${ARCH}" -echo "Using arch directory: ${ARCHDIR}" - -# show the results in the log -echo >> configure.log -echo ALL = $ALL >> configure.log -echo AR = $AR >> configure.log -echo ARFLAGS = $ARFLAGS >> configure.log -echo CC = $CC >> configure.log -echo CFLAGS = $CFLAGS >> configure.log -echo EXE = $EXE >> configure.log -echo LDCONFIG = $LDCONFIG >> configure.log -echo LDFLAGS = $LDFLAGS >> configure.log -echo LDSHARED = $LDSHARED >> configure.log -echo LDSHAREDFLAGS = $LDSHAREDFLAGS >> configure.log -echo LDSHAREDLIBC = $LDSHAREDLIBC >> configure.log -echo DEFFILE = $DEFFILE >> configure.log -echo RC = $RC >> configure.log -echo RCFLAGS = $RCFLAGS >> configure.log -echo RCOBJS = $RCOBJS >> configure.log -echo STRIP = $STRIP >> configure.log -echo OBJC = $OBJC >> configure.log -echo PIC_OBJC = $PIC_OBJC >> configure.log -echo RANLIB = $RANLIB >> configure.log -echo SFLAGS = $SFLAGS >> configure.log -echo SHAREDLIB = $SHAREDLIB >> configure.log -echo SHAREDLIBM = $SHAREDLIBM >> configure.log -echo SHAREDLIBV = $SHAREDLIBV >> configure.log -echo SHAREDTARGET = $SHAREDTARGET >> configure.log -echo IMPORTLIB = $IMPORTLIB >> configure.log -echo INSTALLTARGETS = $INSTALLTARGETS >> configure.log -echo UNINSTALLTARGETS = $UNINSTALLTARGETS >> configure.log -echo SRCDIR = $SRCDIR >> configure.log -echo BUILDDIR = $BUILDDIR >> configure.log -echo STATICLIB = $STATICLIB >> configure.log -echo TEST = $TEST >> configure.log -echo VER = $VER >> configure.log -echo exec_prefix = $exec_prefix >> configure.log -echo includedir = $includedir >> configure.log -echo bindir = $bindir >> configure.log -echo libdir = $libdir >> configure.log -echo mandir = $mandir >> configure.log -echo prefix = $prefix >> configure.log -echo sharedlibdir = $sharedlibdir >> configure.log -echo uname = $uname >> configure.log -echo sse2flag = $sse2flag >> configure.log -echo ssse3flag = $ssse3flag >> configure.log -echo sse4flag = $sse4flag >> configure.log -echo pclmulflag = $pclmulflag >> configure.log -echo acleflag = $acleflag >> configure.log -echo neonflag = $neonflag >> configure.log -echo ARCHDIR = ${ARCHDIR} >> configure.log -echo ARCH_STATIC_OBJS = ${ARCH_STATIC_OBJS} >> configure.log -echo ARCH_SHARED_OBJS = ${ARCH_SHARED_OBJS} >> configure.log - -# Handle sed incompatibilities when using -i -replace_in_file() { - if [ "$OS" = 'Darwin' ]; then - sed -i '.tmp' -e "$1" "$2" - else - sed -i'.tmp' -e "$1" "$2" - fi -} - -# update Makefile with the configure results - -INCLUDES="-I$SRCDIR" -if [ "$SRCDIR" != "$BUILDDIR" ]; then INCLUDES="-I$BUILDDIR ${INCLUDES}"; fi - -sed < $SRCDIR/Makefile.in " -/^CC *=/s#=.*#=$CC# -/^CFLAGS *=/s#=.*#=$CFLAGS# -/^WITH_FUZZERS *=/s#=.*#=$with_fuzzers# -/^SFLAGS *=/s#=.*#=$SFLAGS# -/^LDFLAGS *=/s#=.*#=$LDFLAGS# -/^LDSHARED *=/s#=.*#=$LDSHARED# -/^LDSHAREDFLAGS *=/s#=.*#=$LDSHAREDFLAGS# -/^LIBNAME1 *=/s#=.*#=$LIBNAME# -/^LIBNAME2 *=/s#=.*#=$LIBNAME2# -/^SUFFIX *=/s#=.*#=$SUFFIX# -/^STATICLIB *=/s#=.*#=$STATICLIB# -/^SHAREDLIB *=/s#=.*#=$SHAREDLIB# -/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# -/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# -/^SHAREDTARGET *=/s#=.*#=$SHAREDTARGET# -/^IMPORTLIB *=/s#=.*#=$IMPORTLIB# -/^VER *=/s#=.*#=$VER# -/^VER1 *=/s#=.*#=$VER1# -/^AR *=/s#=.*#=$AR# -/^ARFLAGS *=/s#=.*#=$ARFLAGS# -/^RANLIB *=/s#=.*#=$RANLIB# -/^LDCONFIG *=/s#=.*#=$LDCONFIG# -/^LDSHAREDLIBC *=/s#=.*#=$LDSHAREDLIBC# -/^DEFFILE *=/s#=.*#=$DEFFILE# -/^RC *=/s#=.*#=$RC# -/^RCFLAGS *=/s#=.*#=$RCFLAGS# -/^RCOBJS *=/s#=.*#=$RCOBJS# -/^STRIP *=/s#=.*#=$STRIP# -/^EXE *=/s#=.*#=$EXE# -/^prefix *=/s#=.*#= $prefix# -/^exec_prefix *=/s#=.*#= $exec_prefix# -/^bindir *=/s#=.*#= $bindir# -/^libdir *=/s#=.*#= $libdir# -/^sharedlibdir *=/s#=.*#= $sharedlibdir# -/^includedir *=/s#=.*#= $includedir# -/^mandir *=/s#=.*#= $mandir# -/^SRCDIR *=/s#=.*#=$SRCDIR# -/^INCLUDES *=/s#=.*#=$INCLUDES# -/^OBJC *=/s#=.*#= $OBJC# -/^PIC_OBJC *=/s#=.*#= $PIC_OBJC# -/^all: */s#:.*#: $ALL# -/^install-libs: */s#:.*#: $INSTALLTARGETS# -/^uninstall-libs: */s#:.*#: $UNINSTALLTARGETS# -/^ARCHDIR *=/s#=.*#=$ARCHDIR# -/^ARCH_STATIC_OBJS *=/s#=.*#=$ARCH_STATIC_OBJS# -/^ARCH_SHARED_OBJS *=/s#=.*#=$ARCH_SHARED_OBJS# -" > Makefile - -# Append header files dependences. -for file in $(ls -1 $SRCDIR/*.c $SRCDIR/test/*.c $SRCDIR/test/fuzz/*.c $SRCDIR/$ARCHDIR/*.c $SRCDIR/tools/*.c); do - short_name=$(echo $file | sed -e "s#$SRCDIR/##g") - incs=$(grep -h include $file | sed -n 's/# *\include *"\(.*\.h\)".*/\1/p' | sort | uniq) - includes=$(for i in $incs; do - # Check that the include file exists in the current dir, - # otherwise it may be one of the system include header. - if test -e $SRCDIR/$i; then - echo -n " \$(SRCDIR)/$i" - fi - # We also need to check whether the include file is in the ARCHDIR. - if test -e $SRCDIR/$ARCHDIR/$i; then - echo -n " \$(SRCDIR)/$ARCHDIR/$i" - fi - done) - obj=$(basename $(echo $file | sed -e 's/\.c/\.o/g' -e 's#^\./##g')) - lobj=$(basename $(echo $file | sed -e 's/\.c/\.lo/g' -e 's#^\./##g')) - - if grep -q "^$obj:" Makefile; then - # Replace the existing line with a line with all dependences. - $(replace_in_file "s#$obj:.*#$obj: \$(SRCDIR)/$short_name $includes#g" Makefile) - else - # Append at the end of Makefile a new line with the header dependences. - echo "$obj: \$(SRCDIR)/$short_name $includes" >> Makefile - - # In case this is one of the ARCHDIR files, append a dependence line - # that will force the `$(MAKE) -C $(ARCHDIR)` generic rule. Without this - # we would only execute the copy rule from ARCHDIR to SRCDIR. - if test -e $SRCDIR/$ARCHDIR/$(basename $file); then - echo "$ARCHDIR/$obj: \$(SRCDIR)/$short_name $includes" >> Makefile - fi - fi - - if grep -q "^$lobj:" Makefile; then - # Replace the existing line with a line with all dependences. - $(replace_in_file "s#$lobj:.*#$lobj: \$(SRCDIR)/$short_name $includes#g" Makefile) - else - # Append at the end of Makefile a new line with the header dependences. - echo "$lobj: \$(SRCDIR)/$short_name $includes" >> Makefile - fi -done - -# Generate Makefile in arch dir -mkdir -p $ARCHDIR - -ARCHINCLUDES="-I$SRCDIR/$ARCHDIR -I$SRCDIR" -if [ "$SRCDIR" != "$BUILDDIR" ]; then ARCHINCLUDES="-I$BUILDDIR ${ARCHINCLUDES}"; fi - -sed < $SRCDIR/$ARCHDIR/Makefile.in " -/^CC *=/s#=.*#=$CC# -/^CFLAGS *=/s#=.*#=$CFLAGS# -/^SFLAGS *=/s#=.*#=$SFLAGS# -/^LDFLAGS *=/s#=.*#=$LDFLAGS# -/^INCLUDES *=/s#=.*#=$ARCHINCLUDES# -/^SUFFIX *=/s#=.*#=$SUFFIX# -/^SRCDIR *=/s#=.*#=$SRCDIR/$ARCHDIR# -/^SRCTOP *=/s#=.*#=$SRCDIR# -/^TOPDIR *=/s#=.*#=$BUILDDIR# -/^AVX2FLAG *=/s#=.*#=$avx2flag# -/^SSE2FLAG *=/s#=.*#=$sse2flag# -/^SSSE3FLAG *=/s#=.*#=$ssse3flag# -/^SSE4FLAG *=/s#=.*#=$sse4flag# -/^PCLMULFLAG *=/s#=.*#=$pclmulflag# -/^ACLEFLAG *=/s#=.*#=$acleflag# -/^NEONFLAG *=/s#=.*#=$neonflag# -" > $ARCHDIR/Makefile - -# Append header files dependences. -for file in $(ls -1 $SRCDIR/$ARCHDIR/*.c); do - incs=$(grep -h include $file | sed -n 's/# *\include *"\(.*\.h\)".*/\1/p' | sort | uniq) - includes=$(for i in $incs; do - # Check that the include file exists in the current dir, - # otherwise it may be one of the system include header. - if test -e $SRCDIR/$i; then - echo -n " \$(SRCTOP)/$i" - fi - # We also need to check whether the include file is in the ARCHDIR. - if test -e $SRCDIR/$ARCHDIR/$i; then - echo -n " \$(SRCDIR)/$i" - fi - done) - obj=$(basename $(echo $file | sed -e 's/\.c/\.o/g' -e 's#^\./##g')) - lobj=$(basename $(echo $file | sed -e 's/\.c/\.lo/g' -e 's#^\./##g')) - short_name=$(basename $file) - if grep -q "^$obj:" $ARCHDIR/Makefile; then - # Replace the existing line with a line with all dependences. - $(replace_in_file "s#$obj:.*#$obj: \$(SRCDIR)/$short_name $includes#g" $ARCHDIR/Makefile) - else - # Append at the end of Makefile a new line with the header dependences. - echo "$obj: \$(SRCDIR)/$short_name $includes" >> $ARCHDIR/Makefile - fi - - if grep -q "^$lobj:" $ARCHDIR/Makefile; then - # Replace the existing line with a line with all dependences. - $(replace_in_file "s#$lobj:.*#$lobj: \$(SRCDIR)/$short_name $includes#g" $ARCHDIR/Makefile) - else - # Append at the end of Makefile a new line with the header dependences. - echo "$lobj: \$(SRCDIR)/$short_name $includes" >> $ARCHDIR/Makefile - fi -done - -# Generate Makefile in test dir -mkdir -p test -if test $compat -eq 1; then COMPATTESTS="compattests"; fi -if test $QEMU_ARCH; then QEMU_RUN="qemu-$QEMU_ARCH -L /usr/${CHOST}/"; fi -sed < $SRCDIR/test/Makefile.in " -/^CC *=/s#=.*#=$CC# -/^CFLAGS *=/s#=.*#=$CFLAGS# -/^LDFLAGS *=/s#=.*#=$LDFLAGS# -/^EXE *=/s#=.*#=$EXE# -/^oldtests: */s#:.*#: $TEST# -/^SRCDIR *=/s#=.*#=$SRCDIR/test# -/^SRCTOP *=/s#=.*#=$SRCDIR# -/^COMPATTESTS *=/s#=.*#=$COMPATTESTS# -/^QEMU_RUN *=/s#=.*#=$QEMU_RUN# -/^WITH_FUZZERS *=/s#=.*#=$with_fuzzers# -/^LIBNAME *=/s#=.*#=$LIBNAME# -" > test/Makefile - -# create zlib.pc with the configure results -sed < $SRCDIR/zlib.pc.in " -/^CC *=/s#=.*#=$CC# -/^CFLAGS *=/s#=.*#=$CFLAGS# -/^LDFLAGS *=/s#=.*#=$LDFLAGS# -/^LDSHARED *=/s#=.*#=$LDSHARED# -/^LDSHAREDFLAGS *=/s#=.*#=$LDSHAREDFLAGS# -/^STATICLIB *=/s#=.*#=$STATICLIB# -/^SHAREDLIB *=/s#=.*#=$SHAREDLIB# -/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# -/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# -/^IMPORTLIB *=/s#=.*#=$IMPORTLIB# -/^AR *=/s#=.*#=$AR# -/^ARFLAGS *=/s#=.*#=$ARFLAGS# -/^RANLIB *=/s#=.*#=$RANLIB# -/^EXE *=/s#=.*#=$EXE# -/^prefix *=/s#=.*#=$prefix# -/^exec_prefix *=/s#=.*#=$exec_prefix# -/^bindir *=/s#=.*#=$bindir# -/^libdir *=/s#=.*#=$libdir# -/^sharedlibdir *=/s#=.*#=$sharedlibdir# -/^includedir *=/s#=.*#=$includedir# -/^mandir *=/s#=.*#=$mandir# -/^LDFLAGS *=/s#=.*#=$LDFLAGS# -" | sed -e " -s/\@VERSION\@/$VER/g; -s/\@SUFFIX\@/$SUFFIX/g; -" > ${LIBNAME2}.pc - -# done -leave 0 diff --git a/libs/zlibng/crc32.c b/libs/zlibng/crc32.c deleted file mode 100644 index 4b488e617e..0000000000 --- a/libs/zlibng/crc32.c +++ /dev/null @@ -1,202 +0,0 @@ -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Thanks to Rodney Brown for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. - */ - -#include "zbuild.h" -#include "zendian.h" -#include -#include "deflate.h" -#include "functable.h" -#include "crc32_tbl.h" - -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ -const uint32_t * Z_EXPORT PREFIX(get_crc_table)(void) { - return (const uint32_t *)crc_table; -} - -#ifdef ZLIB_COMPAT -unsigned long Z_EXPORT PREFIX(crc32_z)(unsigned long crc, const unsigned char *buf, size_t len) { - if (buf == NULL) return 0; - - return (unsigned long)functable.crc32((uint32_t)crc, buf, len); -} -#else -uint32_t Z_EXPORT PREFIX(crc32_z)(uint32_t crc, const unsigned char *buf, size_t len) { - if (buf == NULL) return 0; - - return functable.crc32(crc, buf, len); -} -#endif -/* ========================================================================= */ -#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) -#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 -#define DO4 DO1; DO1; DO1; DO1 - -/* ========================================================================= */ -Z_INTERNAL uint32_t crc32_generic(uint32_t crc, const unsigned char *buf, uint64_t len) { - crc = crc ^ 0xffffffff; - -#ifdef UNROLL_MORE - while (len >= 8) { - DO8; - len -= 8; - } -#else - while (len >= 4) { - DO4; - len -= 4; - } -#endif - - if (len) do { - DO1; - } while (--len); - return crc ^ 0xffffffff; -} - -#ifdef ZLIB_COMPAT -unsigned long Z_EXPORT PREFIX(crc32)(unsigned long crc, const unsigned char *buf, unsigned int len) { - return (unsigned long)PREFIX(crc32_z)((uint32_t)crc, buf, len); -} -#else -uint32_t Z_EXPORT PREFIX(crc32)(uint32_t crc, const unsigned char *buf, uint32_t len) { - return PREFIX(crc32_z)(crc, buf, len); -} -#endif - -/* - This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit - integer pointer type. This violates the strict aliasing rule, where a - compiler can assume, for optimization purposes, that two pointers to - fundamentally different types won't ever point to the same memory. This can - manifest as a problem only if one of the pointers is written to. This code - only reads from those pointers. So long as this code remains isolated in - this compilation unit, there won't be a problem. For this reason, this code - should not be copied and pasted into a compilation unit in which other code - writes to the buffer that is passed to these routines. - */ - -/* ========================================================================= */ -#if BYTE_ORDER == LITTLE_ENDIAN -#define DOLIT4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] -#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 - -/* ========================================================================= */ -Z_INTERNAL uint32_t crc32_little(uint32_t crc, const unsigned char *buf, uint64_t len) { - Z_REGISTER uint32_t c; - Z_REGISTER const uint32_t *buf4; - - c = crc; - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - len--; - } - - buf4 = (const uint32_t *)(const void *)buf; - -#ifdef UNROLL_MORE - while (len >= 32) { - DOLIT32; - len -= 32; - } -#endif - - while (len >= 4) { - DOLIT4; - len -= 4; - } - buf = (const unsigned char *)buf4; - - if (len) do { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - } while (--len); - c = ~c; - return c; -} -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -/* ========================================================================= */ -#if BYTE_ORDER == BIG_ENDIAN -#define DOBIG4 c ^= *buf4++; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] -#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 - -/* ========================================================================= */ -Z_INTERNAL uint32_t crc32_big(uint32_t crc, const unsigned char *buf, uint64_t len) { - Z_REGISTER uint32_t c; - Z_REGISTER const uint32_t *buf4; - - c = ZSWAP32(crc); - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - len--; - } - - buf4 = (const uint32_t *)(const void *)buf; - -#ifdef UNROLL_MORE - while (len >= 32) { - DOBIG32; - len -= 32; - } -#endif - - while (len >= 4) { - DOBIG4; - len -= 4; - } - buf = (const unsigned char *)buf4; - - if (len) do { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - } while (--len); - c = ~c; - return ZSWAP32(c); -} -#endif /* BYTE_ORDER == BIG_ENDIAN */ - -#ifdef X86_PCLMULQDQ_CRC -#include "arch/x86/x86.h" -#include "arch/x86/crc_folding.h" - -Z_INTERNAL void crc_finalize(deflate_state *const s) { - if (x86_cpu_has_pclmulqdq) - s->strm->adler = crc_fold_512to32(s); -} -#endif - -Z_INTERNAL void crc_reset(deflate_state *const s) { -#ifdef X86_PCLMULQDQ_CRC - x86_check_features(); - if (x86_cpu_has_pclmulqdq) { - crc_fold_init(s); - return; - } -#endif - s->strm->adler = PREFIX(crc32)(0L, NULL, 0); -} - -Z_INTERNAL void copy_with_crc(PREFIX3(stream) *strm, unsigned char *dst, unsigned long size) { -#ifdef X86_PCLMULQDQ_CRC - if (x86_cpu_has_pclmulqdq) { - crc_fold_copy(strm->state, dst, strm->next_in, size); - return; - } -#endif - memcpy(dst, strm->next_in, size); - strm->adler = PREFIX(crc32)(strm->adler, dst, size); -} diff --git a/libs/zlibng/crc32_comb.c b/libs/zlibng/crc32_comb.c deleted file mode 100644 index 092c595d9c..0000000000 --- a/libs/zlibng/crc32_comb.c +++ /dev/null @@ -1,108 +0,0 @@ -/* crc32_comb.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Thanks to Rodney Brown for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. - */ - -#include "zbuild.h" -#include -#include "deflate.h" -#include "crc32_p.h" -#include "crc32_comb_tbl.h" - - -/* Local functions for crc concatenation */ -static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2); -static void crc32_combine_gen_(uint32_t *op, z_off64_t len2); - -/* ========================================================================= */ -static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2) { - int n; - - if (len2 > 0) - /* operator for 2^n zeros repeats every GF2_DIM n values */ - for (n = 0; len2; n = (n + 1) % GF2_DIM, len2 >>= 1) - if (len2 & 1) - crc1 = gf2_matrix_times(crc_comb[n], crc1); - return crc1 ^ crc2; -} - -/* ========================================================================= */ -#ifdef ZLIB_COMPAT -unsigned long Z_EXPORT PREFIX(crc32_combine)(unsigned long crc1, unsigned long crc2, z_off_t len2) { - return (unsigned long)crc32_combine_((uint32_t)crc1, (uint32_t)crc2, len2); -} - -unsigned long Z_EXPORT PREFIX4(crc32_combine)(unsigned long crc1, unsigned long crc2, z_off64_t len2) { - return (unsigned long)crc32_combine_((uint32_t)crc1, (uint32_t)crc2, len2); -} -#else -uint32_t Z_EXPORT PREFIX4(crc32_combine)(uint32_t crc1, uint32_t crc2, z_off64_t len2) { - return crc32_combine_(crc1, crc2, len2); -} -#endif - -/* ========================================================================= */ - -static void crc32_combine_gen_(uint32_t *op, z_off64_t len2) { - uint32_t row; - int j; - unsigned i; - - /* if len2 is zero or negative, return the identity matrix */ - if (len2 <= 0) { - row = 1; - for (j = 0; j < GF2_DIM; j++) { - op[j] = row; - row <<= 1; - } - return; - } - - /* at least one bit in len2 is set -- find it, and copy the operator - corresponding to that position into op */ - i = 0; - for (;;) { - if (len2 & 1) { - for (j = 0; j < GF2_DIM; j++) - op[j] = crc_comb[i][j]; - break; - } - len2 >>= 1; - i = (i + 1) % GF2_DIM; - } - - /* for each remaining bit set in len2 (if any), multiply op by the operator - corresponding to that position */ - for (;;) { - len2 >>= 1; - i = (i + 1) % GF2_DIM; - if (len2 == 0) - break; - if (len2 & 1) - for (j = 0; j < GF2_DIM; j++) - op[j] = gf2_matrix_times(crc_comb[i], op[j]); - } -} - -/* ========================================================================= */ - -#ifdef ZLIB_COMPAT -void Z_EXPORT PREFIX(crc32_combine_gen)(uint32_t *op, z_off_t len2) { - crc32_combine_gen_(op, len2); -} -#endif - -void Z_EXPORT PREFIX4(crc32_combine_gen)(uint32_t *op, z_off64_t len2) { - crc32_combine_gen_(op, len2); -} - -/* ========================================================================= */ -uint32_t Z_EXPORT PREFIX(crc32_combine_op)(uint32_t crc1, uint32_t crc2, const uint32_t *op) { - return gf2_matrix_times(op, crc1) ^ crc2; -} diff --git a/libs/zlibng/crc32_comb_tbl.h b/libs/zlibng/crc32_comb_tbl.h deleted file mode 100644 index 43818c3e03..0000000000 --- a/libs/zlibng/crc32_comb_tbl.h +++ /dev/null @@ -1,300 +0,0 @@ -#ifndef CRC32_COMB_TBL_H_ -#define CRC32_COMB_TBL_H_ - -/* crc32_comb_tbl.h -- zero operators table for CRC combine - * Generated automatically by makecrct.c - */ - -static const uint32_t crc_comb[32][32] = -{ - { - 0x77073096, 0xee0e612c, 0x076dc419, 0x0edb8832, 0x1db71064, - 0x3b6e20c8, 0x76dc4190, 0xedb88320, 0x00000001, 0x00000002, - 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, - 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, - 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, - 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, - 0x00400000, 0x00800000 - }, - { - 0x191b3141, 0x32366282, 0x646cc504, 0xc8d98a08, 0x4ac21251, - 0x958424a2, 0xf0794f05, 0x3b83984b, 0x77073096, 0xee0e612c, - 0x076dc419, 0x0edb8832, 0x1db71064, 0x3b6e20c8, 0x76dc4190, - 0xedb88320, 0x00000001, 0x00000002, 0x00000004, 0x00000008, - 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, - 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, - 0x00004000, 0x00008000 - }, - { - 0xb8bc6765, 0xaa09c88b, 0x8f629757, 0xc5b428ef, 0x5019579f, - 0xa032af3e, 0x9b14583d, 0xed59b63b, 0x01c26a37, 0x0384d46e, - 0x0709a8dc, 0x0e1351b8, 0x1c26a370, 0x384d46e0, 0x709a8dc0, - 0xe1351b80, 0x191b3141, 0x32366282, 0x646cc504, 0xc8d98a08, - 0x4ac21251, 0x958424a2, 0xf0794f05, 0x3b83984b, 0x77073096, - 0xee0e612c, 0x076dc419, 0x0edb8832, 0x1db71064, 0x3b6e20c8, - 0x76dc4190, 0xedb88320 - }, - { - 0xccaa009e, 0x4225077d, 0x844a0efa, 0xd3e51bb5, 0x7cbb312b, - 0xf9766256, 0x299dc2ed, 0x533b85da, 0xa6770bb4, 0x979f1129, - 0xf44f2413, 0x33ef4e67, 0x67de9cce, 0xcfbd399c, 0x440b7579, - 0x8816eaf2, 0xcb5cd3a5, 0x4dc8a10b, 0x9b914216, 0xec53826d, - 0x03d6029b, 0x07ac0536, 0x0f580a6c, 0x1eb014d8, 0x3d6029b0, - 0x7ac05360, 0xf580a6c0, 0x30704bc1, 0x60e09782, 0xc1c12f04, - 0x58f35849, 0xb1e6b092 - }, - { - 0xae689191, 0x87a02563, 0xd4314c87, 0x73139f4f, 0xe6273e9e, - 0x173f7b7d, 0x2e7ef6fa, 0x5cfdedf4, 0xb9fbdbe8, 0xa886b191, - 0x8a7c6563, 0xcf89cc87, 0x44629f4f, 0x88c53e9e, 0xcafb7b7d, - 0x4e87f0bb, 0x9d0fe176, 0xe16ec4ad, 0x19ac8f1b, 0x33591e36, - 0x66b23c6c, 0xcd6478d8, 0x41b9f7f1, 0x8373efe2, 0xdd96d985, - 0x605cb54b, 0xc0b96a96, 0x5a03d36d, 0xb407a6da, 0xb37e4bf5, - 0xbd8d91ab, 0xa06a2517 - }, - { - 0xf1da05aa, 0x38c50d15, 0x718a1a2a, 0xe3143454, 0x1d596ee9, - 0x3ab2ddd2, 0x7565bba4, 0xeacb7748, 0x0ee7e8d1, 0x1dcfd1a2, - 0x3b9fa344, 0x773f4688, 0xee7e8d10, 0x078c1c61, 0x0f1838c2, - 0x1e307184, 0x3c60e308, 0x78c1c610, 0xf1838c20, 0x38761e01, - 0x70ec3c02, 0xe1d87804, 0x18c1f649, 0x3183ec92, 0x6307d924, - 0xc60fb248, 0x576e62d1, 0xaedcc5a2, 0x86c88d05, 0xd6e01c4b, - 0x76b13ed7, 0xed627dae - }, - { - 0x8f352d95, 0xc51b5d6b, 0x5147bc97, 0xa28f792e, 0x9e6ff41d, - 0xe7aeee7b, 0x142cdab7, 0x2859b56e, 0x50b36adc, 0xa166d5b8, - 0x99bcad31, 0xe8085c23, 0x0b61be07, 0x16c37c0e, 0x2d86f81c, - 0x5b0df038, 0xb61be070, 0xb746c6a1, 0xb5fc8b03, 0xb0881047, - 0xba6126cf, 0xafb34bdf, 0x841791ff, 0xd35e25bf, 0x7dcd4d3f, - 0xfb9a9a7e, 0x2c4432bd, 0x5888657a, 0xb110caf4, 0xb95093a9, - 0xa9d02113, 0x88d14467 - }, - { - 0x33fff533, 0x67ffea66, 0xcfffd4cc, 0x448eafd9, 0x891d5fb2, - 0xc94bb925, 0x49e6740b, 0x93cce816, 0xfce8d66d, 0x22a0aa9b, - 0x45415536, 0x8a82aa6c, 0xce745299, 0x4799a373, 0x8f3346e6, - 0xc5178b8d, 0x515e115b, 0xa2bc22b6, 0x9e09432d, 0xe763801b, - 0x15b60677, 0x2b6c0cee, 0x56d819dc, 0xadb033b8, 0x80116131, - 0xdb53c423, 0x6dd68e07, 0xdbad1c0e, 0x6c2b3e5d, 0xd8567cba, - 0x6bddff35, 0xd7bbfe6a - }, - { - 0xce3371cb, 0x4717e5d7, 0x8e2fcbae, 0xc72e911d, 0x552c247b, - 0xaa5848f6, 0x8fc197ad, 0xc4f2291b, 0x52955477, 0xa52aa8ee, - 0x9124579d, 0xf939a97b, 0x290254b7, 0x5204a96e, 0xa40952dc, - 0x9363a3f9, 0xfdb641b3, 0x201d8527, 0x403b0a4e, 0x8076149c, - 0xdb9d2f79, 0x6c4b58b3, 0xd896b166, 0x6a5c648d, 0xd4b8c91a, - 0x72009475, 0xe40128ea, 0x13735795, 0x26e6af2a, 0x4dcd5e54, - 0x9b9abca8, 0xec447f11 - }, - { - 0x1072db28, 0x20e5b650, 0x41cb6ca0, 0x8396d940, 0xdc5cb4c1, - 0x63c86fc3, 0xc790df86, 0x5450b94d, 0xa8a1729a, 0x8a33e375, - 0xcf16c0ab, 0x455c8717, 0x8ab90e2e, 0xce031a1d, 0x4777327b, - 0x8eee64f6, 0xc6adcfad, 0x562a991b, 0xac553236, 0x83db622d, - 0xdcc7c21b, 0x62fe8277, 0xc5fd04ee, 0x508b0f9d, 0xa1161f3a, - 0x995d3835, 0xe9cb762b, 0x08e7ea17, 0x11cfd42e, 0x239fa85c, - 0x473f50b8, 0x8e7ea170 - }, - { - 0xf891f16f, 0x2a52e49f, 0x54a5c93e, 0xa94b927c, 0x89e622b9, - 0xc8bd4333, 0x4a0b8027, 0x9417004e, 0xf35f06dd, 0x3dcf0bfb, - 0x7b9e17f6, 0xf73c2fec, 0x35095999, 0x6a12b332, 0xd4256664, - 0x733bca89, 0xe6779512, 0x179e2c65, 0x2f3c58ca, 0x5e78b194, - 0xbcf16328, 0xa293c011, 0x9e568663, 0xe7dc0a87, 0x14c9134f, - 0x2992269e, 0x53244d3c, 0xa6489a78, 0x97e032b1, 0xf4b16323, - 0x3213c007, 0x6427800e - }, - { - 0x88b6ba63, 0xca1c7287, 0x4f49e34f, 0x9e93c69e, 0xe6568b7d, - 0x17dc10bb, 0x2fb82176, 0x5f7042ec, 0xbee085d8, 0xa6b00df1, - 0x96111da3, 0xf7533d07, 0x35d77c4f, 0x6baef89e, 0xd75df13c, - 0x75cae439, 0xeb95c872, 0x0c5a96a5, 0x18b52d4a, 0x316a5a94, - 0x62d4b528, 0xc5a96a50, 0x5023d2e1, 0xa047a5c2, 0x9bfe4dc5, - 0xec8d9dcb, 0x026a3dd7, 0x04d47bae, 0x09a8f75c, 0x1351eeb8, - 0x26a3dd70, 0x4d47bae0 - }, - { - 0x5ad8a92c, 0xb5b15258, 0xb013a2f1, 0xbb5643a3, 0xaddd8107, - 0x80ca044f, 0xdae50edf, 0x6ebb1bff, 0xdd7637fe, 0x619d69bd, - 0xc33ad37a, 0x5d04a0b5, 0xba09416a, 0xaf638495, 0x85b60f6b, - 0xd01d1897, 0x7b4b376f, 0xf6966ede, 0x365ddbfd, 0x6cbbb7fa, - 0xd9776ff4, 0x699fd9a9, 0xd33fb352, 0x7d0e60e5, 0xfa1cc1ca, - 0x2f4885d5, 0x5e910baa, 0xbd221754, 0xa13528e9, 0x991b5793, - 0xe947a967, 0x09fe548f - }, - { - 0xb566f6e2, 0xb1bceb85, 0xb808d14b, 0xab60a4d7, 0x8db04fef, - 0xc011999f, 0x5b52357f, 0xb6a46afe, 0xb639d3bd, 0xb702a13b, - 0xb5744437, 0xb1998e2f, 0xb8421a1f, 0xabf5327f, 0x8c9b62bf, - 0xc247c33f, 0x5ffe803f, 0xbffd007e, 0xa48b06bd, 0x92670b3b, - 0xffbf1037, 0x240f262f, 0x481e4c5e, 0x903c98bc, 0xfb083739, - 0x2d616833, 0x5ac2d066, 0xb585a0cc, 0xb07a47d9, 0xbb8589f3, - 0xac7a15a7, 0x83852d0f - }, - { - 0x9d9129bf, 0xe053553f, 0x1bd7ac3f, 0x37af587e, 0x6f5eb0fc, - 0xdebd61f8, 0x660bc5b1, 0xcc178b62, 0x435e1085, 0x86bc210a, - 0xd6094455, 0x77638eeb, 0xeec71dd6, 0x06ff3ded, 0x0dfe7bda, - 0x1bfcf7b4, 0x37f9ef68, 0x6ff3ded0, 0xdfe7bda0, 0x64be7d01, - 0xc97cfa02, 0x4988f245, 0x9311e48a, 0xfd52cf55, 0x21d498eb, - 0x43a931d6, 0x875263ac, 0xd5d5c119, 0x70da8473, 0xe1b508e6, - 0x181b178d, 0x30362f1a - }, - { - 0x2ee43a2c, 0x5dc87458, 0xbb90e8b0, 0xac50d721, 0x83d0a803, - 0xdcd05647, 0x62d1aacf, 0xc5a3559e, 0x5037ad7d, 0xa06f5afa, - 0x9bafb3b5, 0xec2e612b, 0x032dc417, 0x065b882e, 0x0cb7105c, - 0x196e20b8, 0x32dc4170, 0x65b882e0, 0xcb7105c0, 0x4d930dc1, - 0x9b261b82, 0xed3d3145, 0x010b64cb, 0x0216c996, 0x042d932c, - 0x085b2658, 0x10b64cb0, 0x216c9960, 0x42d932c0, 0x85b26580, - 0xd015cd41, 0x7b5a9cc3 - }, - { - 0x1b4511ee, 0x368a23dc, 0x6d1447b8, 0xda288f70, 0x6f2018a1, - 0xde403142, 0x67f164c5, 0xcfe2c98a, 0x44b49555, 0x89692aaa, - 0xc9a35315, 0x4837a06b, 0x906f40d6, 0xfbaf87ed, 0x2c2e099b, - 0x585c1336, 0xb0b8266c, 0xba014a99, 0xaf739373, 0x859620a7, - 0xd05d470f, 0x7bcb885f, 0xf79710be, 0x345f273d, 0x68be4e7a, - 0xd17c9cf4, 0x79883fa9, 0xf3107f52, 0x3d51f8e5, 0x7aa3f1ca, - 0xf547e394, 0x31fec169 - }, - { - 0xbce15202, 0xa2b3a245, 0x9e1642cb, 0xe75d83d7, 0x15ca01ef, - 0x2b9403de, 0x572807bc, 0xae500f78, 0x87d118b1, 0xd4d33723, - 0x72d76807, 0xe5aed00e, 0x102ca65d, 0x20594cba, 0x40b29974, - 0x816532e8, 0xd9bb6391, 0x6807c163, 0xd00f82c6, 0x7b6e03cd, - 0xf6dc079a, 0x36c90975, 0x6d9212ea, 0xdb2425d4, 0x6d394de9, - 0xda729bd2, 0x6f9431e5, 0xdf2863ca, 0x6521c1d5, 0xca4383aa, - 0x4ff60115, 0x9fec022a - }, - { - 0xff08e5ef, 0x2560cd9f, 0x4ac19b3e, 0x9583367c, 0xf0776ab9, - 0x3b9fd333, 0x773fa666, 0xee7f4ccc, 0x078f9fd9, 0x0f1f3fb2, - 0x1e3e7f64, 0x3c7cfec8, 0x78f9fd90, 0xf1f3fb20, 0x3896f001, - 0x712de002, 0xe25bc004, 0x1fc68649, 0x3f8d0c92, 0x7f1a1924, - 0xfe343248, 0x271962d1, 0x4e32c5a2, 0x9c658b44, 0xe3ba10c9, - 0x1c0527d3, 0x380a4fa6, 0x70149f4c, 0xe0293e98, 0x1b237b71, - 0x3646f6e2, 0x6c8dedc4 - }, - { - 0x6f76172e, 0xdeec2e5c, 0x66a95af9, 0xcd52b5f2, 0x41d46da5, - 0x83a8db4a, 0xdc20b0d5, 0x633067eb, 0xc660cfd6, 0x57b099ed, - 0xaf6133da, 0x85b361f5, 0xd017c5ab, 0x7b5e8d17, 0xf6bd1a2e, - 0x360b321d, 0x6c16643a, 0xd82cc874, 0x6b2896a9, 0xd6512d52, - 0x77d35ce5, 0xefa6b9ca, 0x043c75d5, 0x0878ebaa, 0x10f1d754, - 0x21e3aea8, 0x43c75d50, 0x878ebaa0, 0xd46c7301, 0x73a9e043, - 0xe753c086, 0x15d6874d - }, - { - 0x56f5cab9, 0xadeb9572, 0x80a62ca5, 0xda3d5f0b, 0x6f0bb857, - 0xde1770ae, 0x675fe71d, 0xcebfce3a, 0x460e9a35, 0x8c1d346a, - 0xc34b6e95, 0x5de7db6b, 0xbbcfb6d6, 0xacee6bed, 0x82add19b, - 0xde2aa577, 0x67244caf, 0xce48995e, 0x47e034fd, 0x8fc069fa, - 0xc4f1d5b5, 0x5292ad2b, 0xa5255a56, 0x913bb2ed, 0xf906639b, - 0x297dc177, 0x52fb82ee, 0xa5f705dc, 0x909f0df9, 0xfa4f1db3, - 0x2fef3d27, 0x5fde7a4e - }, - { - 0x385993ac, 0x70b32758, 0xe1664eb0, 0x19bd9b21, 0x337b3642, - 0x66f66c84, 0xcdecd908, 0x40a8b451, 0x815168a2, 0xd9d3d705, - 0x68d6a84b, 0xd1ad5096, 0x782ba76d, 0xf0574eda, 0x3bdf9bf5, - 0x77bf37ea, 0xef7e6fd4, 0x058dd9e9, 0x0b1bb3d2, 0x163767a4, - 0x2c6ecf48, 0x58dd9e90, 0xb1bb3d20, 0xb8077c01, 0xab7ffe43, - 0x8d8efac7, 0xc06cf3cf, 0x5ba8e1df, 0xb751c3be, 0xb5d2813d, - 0xb0d4043b, 0xbad90e37 - }, - { - 0xb4247b20, 0xb339f001, 0xbd02e643, 0xa174cac7, 0x999893cf, - 0xe84021df, 0x0bf145ff, 0x17e28bfe, 0x2fc517fc, 0x5f8a2ff8, - 0xbf145ff0, 0xa559b9a1, 0x91c27503, 0xf8f5ec47, 0x2a9adecf, - 0x5535bd9e, 0xaa6b7b3c, 0x8fa7f039, 0xc43ee633, 0x530cca27, - 0xa619944e, 0x97422edd, 0xf5f55bfb, 0x309bb1b7, 0x6137636e, - 0xc26ec6dc, 0x5fac8bf9, 0xbf5917f2, 0xa5c329a5, 0x90f7550b, - 0xfa9fac57, 0x2e4e5eef - }, - { - 0x695186a7, 0xd2a30d4e, 0x7e371cdd, 0xfc6e39ba, 0x23ad7535, - 0x475aea6a, 0x8eb5d4d4, 0xc61aafe9, 0x57445993, 0xae88b326, - 0x8660600d, 0xd7b1c65b, 0x74128af7, 0xe82515ee, 0x0b3b2d9d, - 0x16765b3a, 0x2cecb674, 0x59d96ce8, 0xb3b2d9d0, 0xbc14b5e1, - 0xa3586d83, 0x9dc1dd47, 0xe0f2bccf, 0x1a947fdf, 0x3528ffbe, - 0x6a51ff7c, 0xd4a3fef8, 0x7236fbb1, 0xe46df762, 0x13aae885, - 0x2755d10a, 0x4eaba214 - }, - { - 0x66bc001e, 0xcd78003c, 0x41810639, 0x83020c72, 0xdd751ea5, - 0x619b3b0b, 0xc3367616, 0x5d1dea6d, 0xba3bd4da, 0xaf06aff5, - 0x857c59ab, 0xd189b517, 0x78626c6f, 0xf0c4d8de, 0x3af8b7fd, - 0x75f16ffa, 0xebe2dff4, 0x0cb4b9a9, 0x19697352, 0x32d2e6a4, - 0x65a5cd48, 0xcb4b9a90, 0x4de63361, 0x9bcc66c2, 0xece9cbc5, - 0x02a291cb, 0x05452396, 0x0a8a472c, 0x15148e58, 0x2a291cb0, - 0x54523960, 0xa8a472c0 - }, - { - 0xb58b27b3, 0xb0674927, 0xbbbf940f, 0xac0e2e5f, 0x836d5aff, - 0xddabb3bf, 0x6026613f, 0xc04cc27e, 0x5be882bd, 0xb7d1057a, - 0xb4d30cb5, 0xb2d71f2b, 0xbedf3817, 0xa6cf766f, 0x96efea9f, - 0xf6aed37f, 0x362ca0bf, 0x6c59417e, 0xd8b282fc, 0x6a1403b9, - 0xd4280772, 0x732108a5, 0xe642114a, 0x17f524d5, 0x2fea49aa, - 0x5fd49354, 0xbfa926a8, 0xa4234b11, 0x93379063, 0xfd1e2687, - 0x214d4b4f, 0x429a969e - }, - { - 0xfe273162, 0x273f6485, 0x4e7ec90a, 0x9cfd9214, 0xe28a2269, - 0x1e654293, 0x3cca8526, 0x79950a4c, 0xf32a1498, 0x3d252f71, - 0x7a4a5ee2, 0xf494bdc4, 0x32587dc9, 0x64b0fb92, 0xc961f724, - 0x49b2e809, 0x9365d012, 0xfdbaa665, 0x20044a8b, 0x40089516, - 0x80112a2c, 0xdb535219, 0x6dd7a273, 0xdbaf44e6, 0x6c2f8f8d, - 0xd85f1f1a, 0x6bcf3875, 0xd79e70ea, 0x744de795, 0xe89bcf2a, - 0x0a469815, 0x148d302a - }, - { - 0xd3c98813, 0x7ce21667, 0xf9c42cce, 0x28f95fdd, 0x51f2bfba, - 0xa3e57f74, 0x9cbbf8a9, 0xe206f713, 0x1f7ce867, 0x3ef9d0ce, - 0x7df3a19c, 0xfbe74338, 0x2cbf8031, 0x597f0062, 0xb2fe00c4, - 0xbe8d07c9, 0xa66b09d3, 0x97a715e7, 0xf43f2d8f, 0x330f5d5f, - 0x661ebabe, 0xcc3d757c, 0x430becb9, 0x8617d972, 0xd75eb4a5, - 0x75cc6f0b, 0xeb98de16, 0x0c40ba6d, 0x188174da, 0x3102e9b4, - 0x6205d368, 0xc40ba6d0 - }, - { - 0xf7d6deb4, 0x34dcbb29, 0x69b97652, 0xd372eca4, 0x7d94df09, - 0xfb29be12, 0x2d227a65, 0x5a44f4ca, 0xb489e994, 0xb262d569, - 0xbfb4ac93, 0xa4185f67, 0x9341b88f, 0xfdf2775f, 0x2095e8ff, - 0x412bd1fe, 0x8257a3fc, 0xdfde41b9, 0x64cd8533, 0xc99b0a66, - 0x4847128d, 0x908e251a, 0xfa6d4c75, 0x2fab9eab, 0x5f573d56, - 0xbeae7aac, 0xa62df319, 0x972ae073, 0xf524c6a7, 0x31388b0f, - 0x6271161e, 0xc4e22c3c - }, - { - 0xedb88320, 0x00000001, 0x00000002, 0x00000004, 0x00000008, - 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, - 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, - 0x00004000, 0x00008000, 0x00010000, 0x00020000, 0x00040000, - 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, - 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, - 0x20000000, 0x40000000 - }, - { - 0x76dc4190, 0xedb88320, 0x00000001, 0x00000002, 0x00000004, - 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, - 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, - 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, - 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, - 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000 - }, - { - 0x1db71064, 0x3b6e20c8, 0x76dc4190, 0xedb88320, 0x00000001, - 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, - 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, - 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000, - 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, - 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, - 0x04000000, 0x08000000 - } -}; - -#endif /* CRC32_COMB_TBL_H_ */ diff --git a/libs/zlibng/crc32_p.h b/libs/zlibng/crc32_p.h deleted file mode 100644 index 47b4b3751b..0000000000 --- a/libs/zlibng/crc32_p.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef CRC32_P_H_ -#define CRC32_P_H_ - -#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ - - -static inline uint32_t gf2_matrix_times(const uint32_t *mat, uint32_t vec) { - uint32_t sum = 0; - while (vec) { - if (vec & 1) - sum ^= *mat; - vec >>= 1; - mat++; - } - return sum; -} - - -#endif /* CRC32_P_H_ */ diff --git a/libs/zlibng/crc32_tbl.h b/libs/zlibng/crc32_tbl.h deleted file mode 100644 index ee2030c6ce..0000000000 --- a/libs/zlibng/crc32_tbl.h +++ /dev/null @@ -1,444 +0,0 @@ -#ifndef CRC32_TBL_H_ -#define CRC32_TBL_H_ - -/* crc32_tbl.h -- tables for rapid CRC calculation - * Generated automatically by makecrct.c - */ - -static const uint32_t crc_table[8][256] = -{ - { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, - 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, - 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, - 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, - 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, - 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, - 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, - 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, - 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, - 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, - 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, - 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, - 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, - 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, - 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, - 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, - 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, - 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, - 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, - 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, - 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, - 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, - 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, - 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, - 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, - 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, - 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, - 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, - 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, - 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, - 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, - 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, - 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, - 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, - 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, - 0x2d02ef8d - }, - { - 0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, - 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, - 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, - 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, - 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, - 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, - 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, - 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, - 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, - 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, - 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, - 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, - 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, - 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, - 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, - 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, - 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, - 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, - 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, - 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, - 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, - 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, - 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, - 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, - 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, - 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, - 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, - 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, - 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, - 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, - 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, - 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, - 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, - 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, - 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, - 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, - 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, - 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, - 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, - 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, - 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, - 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, - 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, - 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, - 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, - 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, - 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, - 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, - 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, - 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, - 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, - 0x9324fd72 - }, - { - 0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, - 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, - 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, - 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, - 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, - 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, - 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, - 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, - 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, - 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, - 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, - 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, - 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, - 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, - 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, - 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, - 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, - 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, - 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, - 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, - 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, - 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, - 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, - 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, - 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, - 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, - 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, - 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, - 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, - 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, - 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, - 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, - 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, - 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, - 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, - 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, - 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, - 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, - 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, - 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, - 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, - 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, - 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, - 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, - 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, - 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, - 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, - 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, - 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, - 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, - 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, - 0xbe9834ed - }, - { - 0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, - 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, - 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, - 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, - 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, - 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, - 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, - 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, - 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, - 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, - 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, - 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, - 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, - 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, - 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, - 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, - 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, - 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, - 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, - 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, - 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, - 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, - 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, - 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, - 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, - 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, - 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, - 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, - 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, - 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, - 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, - 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, - 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, - 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, - 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, - 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, - 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, - 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, - 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, - 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, - 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, - 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, - 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, - 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, - 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, - 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, - 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, - 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, - 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, - 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, - 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, - 0xde0506f1 - }, - { - 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, - 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, - 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, - 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, - 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, - 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, - 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, - 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, - 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, - 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, - 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, - 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, - 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, - 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, - 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, - 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, - 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, - 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, - 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, - 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, - 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, - 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, - 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, - 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, - 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, - 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, - 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, - 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, - 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, - 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, - 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, - 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, - 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, - 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, - 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, - 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, - 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, - 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, - 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, - 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, - 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, - 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, - 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, - 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, - 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, - 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, - 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, - 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, - 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, - 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, - 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, - 0x8def022d - }, - { - 0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64, - 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1, - 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e, - 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61, - 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82, - 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff, - 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7, - 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da, - 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139, - 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6, - 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89, - 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c, - 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0, - 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d, - 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a, - 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177, - 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de, - 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b, - 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824, - 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e, - 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad, - 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0, - 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d, - 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60, - 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83, - 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822, - 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d, - 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8, - 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171, - 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c, - 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b, - 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6, - 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca, - 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f, - 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430, - 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf, - 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c, - 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51, - 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9, - 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84, - 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67, - 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398, - 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7, - 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62, - 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e, - 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923, - 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4, - 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9, - 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070, - 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5, - 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a, - 0x72fd2493 - }, - { - 0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907, - 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f, - 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a, - 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e, - 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512, - 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14, - 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b, - 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d, - 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731, - 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925, - 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620, - 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28, - 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70, - 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176, - 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d, - 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b, - 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b, - 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63, - 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266, - 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a, - 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446, - 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40, - 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557, - 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51, - 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d, - 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0, - 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5, - 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed, - 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd, - 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb, - 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0, - 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6, - 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de, - 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6, - 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3, - 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7, - 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb, - 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd, - 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92, - 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094, - 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598, - 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c, - 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489, - 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81, - 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9, - 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af, - 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4, - 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2, - 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2, - 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba, - 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf, - 0xed3498be - }, - { - 0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f, - 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d, - 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0, - 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42, - 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95, - 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2, - 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a, - 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d, - 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea, - 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748, - 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5, - 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27, - 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b, - 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac, - 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4, - 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3, - 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44, - 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6, - 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b, - 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329, - 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe, - 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9, - 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1, - 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6, - 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921, - 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555, - 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8, - 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a, - 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd, - 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a, - 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2, - 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5, - 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2, - 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330, - 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad, - 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f, - 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8, - 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef, - 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc, - 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb, - 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c, - 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e, - 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03, - 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1, - 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6, - 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1, - 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9, - 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e, - 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409, - 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb, - 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966, - 0xf10605de - } -}; - -#endif /* CRC32_TBL_H_ */ diff --git a/libs/zlibng/deflate.c b/libs/zlibng/deflate.c deleted file mode 100644 index 1707f75c20..0000000000 --- a/libs/zlibng/deflate.c +++ /dev/null @@ -1,1782 +0,0 @@ -/* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2016 Jean-loup Gailly and Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process depends on being able to identify portions - * of the input text which are identical to earlier input (within a - * sliding window trailing behind the input currently being processed). - * - * The most straightforward technique turns out to be the fastest for - * most input files: try all possible matches and select the longest. - * The key feature of this algorithm is that insertions into the string - * dictionary are very simple and thus fast, and deletions are avoided - * completely. Insertions are performed at each input character, whereas - * string matches are performed only when the previous match ends. So it - * is preferable to spend more time in matches to allow very fast string - * insertions and avoid deletions. The matching algorithm for small - * strings is inspired from that of Rabin & Karp. A brute force approach - * is used to find longer strings when a small match has been found. - * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - * (by Leonid Broukhis). - * A previous version of this file used a more sophisticated algorithm - * (by Fiala and Greene) which is guaranteed to run in linear amortized - * time, but has a larger average cost, uses more memory and is patented. - * However the F&G algorithm may be faster for some highly redundant - * files if the parameter max_chain_length (described below) is too large. - * - * ACKNOWLEDGEMENTS - * - * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and - * I found it in 'freeze' written by Leonid Broukhis. - * Thanks to many people for bug reports and testing. - * - * REFERENCES - * - * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://tools.ietf.org/html/rfc1951 - * - * A description of the Rabin and Karp algorithm is given in the book - * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. - * - * Fiala,E.R., and Greene,D.H. - * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 - * - */ - -#include "zbuild.h" -#include "deflate.h" -#include "deflate_p.h" -#include "functable.h" - -const char PREFIX(deflate_copyright)[] = " deflate 1.2.11.f Copyright 1995-2016 Jean-loup Gailly and Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* =========================================================================== - * Architecture-specific hooks. - */ -#ifdef S390_DFLTCC_DEFLATE -# include "arch/s390/dfltcc_deflate.h" -#else -/* Memory management for the deflate state. Useful for allocating arch-specific extension blocks. */ -# define ZALLOC_STATE(strm, items, size) ZALLOC(strm, items, size) -# define ZFREE_STATE(strm, addr) ZFREE(strm, addr) -# define ZCOPY_STATE(dst, src, size) memcpy(dst, src, size) -/* Memory management for the window. Useful for allocation the aligned window. */ -# define ZALLOC_WINDOW(strm, items, size) ZALLOC(strm, items, size) -# define TRY_FREE_WINDOW(strm, addr) TRY_FREE(strm, addr) -/* Invoked at the beginning of deflateSetDictionary(). Useful for checking arch-specific window data. */ -# define DEFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) -/* Invoked at the beginning of deflateGetDictionary(). Useful for adjusting arch-specific window data. */ -# define DEFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) -/* Invoked at the end of deflateResetKeep(). Useful for initializing arch-specific extension blocks. */ -# define DEFLATE_RESET_KEEP_HOOK(strm) do {} while (0) -/* Invoked at the beginning of deflateParams(). Useful for updating arch-specific compression parameters. */ -# define DEFLATE_PARAMS_HOOK(strm, level, strategy, hook_flush) do {} while (0) -/* Returns whether the last deflate(flush) operation did everything it's supposed to do. */ -# define DEFLATE_DONE(strm, flush) 1 -/* Adjusts the upper bound on compressed data length based on compression parameters and uncompressed data length. - * Useful when arch-specific deflation code behaves differently than regular zlib-ng algorithms. */ -# define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, sourceLen) do {} while (0) -/* Returns whether an optimistic upper bound on compressed data length should *not* be used. - * Useful when arch-specific deflation code behaves differently than regular zlib-ng algorithms. */ -# define DEFLATE_NEED_CONSERVATIVE_BOUND(strm) 0 -/* Invoked for each deflate() call. Useful for plugging arch-specific deflation code. */ -# define DEFLATE_HOOK(strm, flush, bstate) 0 -/* Returns whether zlib-ng should compute a checksum. Set to 0 if arch-specific deflation code already does that. */ -# define DEFLATE_NEED_CHECKSUM(strm) 1 -/* Returns whether reproducibility parameter can be set to a given value. */ -# define DEFLATE_CAN_SET_REPRODUCIBLE(strm, reproducible) 1 -#endif - -/* =========================================================================== - * Function prototypes. - */ -typedef block_state (*compress_func) (deflate_state *s, int flush); -/* Compression function. Returns the block state after the call. */ - -static int deflateStateCheck (PREFIX3(stream) *strm); -static block_state deflate_stored (deflate_state *s, int flush); -Z_INTERNAL block_state deflate_fast (deflate_state *s, int flush); -Z_INTERNAL block_state deflate_quick (deflate_state *s, int flush); -#ifndef NO_MEDIUM_STRATEGY -Z_INTERNAL block_state deflate_medium (deflate_state *s, int flush); -#endif -Z_INTERNAL block_state deflate_slow (deflate_state *s, int flush); -static block_state deflate_rle (deflate_state *s, int flush); -static block_state deflate_huff (deflate_state *s, int flush); -static void lm_init (deflate_state *s); -Z_INTERNAL unsigned read_buf (PREFIX3(stream) *strm, unsigned char *buf, unsigned size); - -extern void crc_reset(deflate_state *const s); -#ifdef X86_PCLMULQDQ_CRC -extern void crc_finalize(deflate_state *const s); -#endif -extern void copy_with_crc(PREFIX3(stream) *strm, unsigned char *dst, unsigned long size); - -/* =========================================================================== - * Local data - */ - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -typedef struct config_s { - uint16_t good_length; /* reduce lazy search above this match length */ - uint16_t max_lazy; /* do not perform lazy search above this match length */ - uint16_t nice_length; /* quit search above this match length */ - uint16_t max_chain; - compress_func func; -} config; - -static const config configuration_table[10] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ - -#ifndef NO_QUICK_STRATEGY -/* 1 */ {4, 4, 8, 4, deflate_quick}, -/* 2 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ -#else -/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ -/* 2 */ {4, 5, 16, 8, deflate_fast}, -#endif - -/* 3 */ {4, 6, 32, 32, deflate_fast}, - -#ifdef NO_MEDIUM_STRATEGY -/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32, deflate_slow}, -/* 6 */ {8, 16, 128, 128, deflate_slow}, -#else -/* 4 */ {4, 4, 16, 16, deflate_medium}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32, deflate_medium}, -/* 6 */ {8, 16, 128, 128, deflate_medium}, -#endif - -/* 7 */ {8, 32, 128, 256, deflate_slow}, -/* 8 */ {32, 128, 258, 1024, deflate_slow}, -/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ - -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * For deflate_fast() (levels <= 3) good is ignored and lazy has a different - * meaning. - */ - -/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ -#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) - - -/* =========================================================================== - * Initialize the hash table. prev[] will be initialized on the fly. - */ -#define CLEAR_HASH(s) do { \ - memset((unsigned char *)s->head, 0, HASH_SIZE * sizeof(*s->head)); \ - } while (0) - -/* =========================================================================== - * Slide the hash table when sliding the window down (could be avoided with 32 - * bit values at the expense of memory usage). We slide even when level == 0 to - * keep the hash table consistent if we switch back to level > 0 later. - */ -Z_INTERNAL void slide_hash_c(deflate_state *s) { - Pos *p; - unsigned n; - unsigned int wsize = s->w_size; - - n = HASH_SIZE; - p = &s->head[n]; -#ifdef NOT_TWEAK_COMPILER - do { - unsigned m; - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : 0); - } while (--n); -#else - /* As of I make this change, gcc (4.8.*) isn't able to vectorize - * this hot loop using saturated-subtraction on x86-64 architecture. - * To avoid this defect, we can change the loop such that - * o. the pointer advance forward, and - * o. demote the variable 'm' to be local to the loop, and - * choose type "Pos" (instead of 'unsigned int') for the - * variable to avoid unncessary zero-extension. - */ - { - unsigned int i; - Pos *q = p - n; - for (i = 0; i < n; i++) { - Pos m = *q; - Pos t = (Pos)wsize; - *q++ = (Pos)(m >= t ? m-t: 0); - } - } -#endif /* NOT_TWEAK_COMPILER */ - - n = wsize; - p = &s->prev[n]; -#ifdef NOT_TWEAK_COMPILER - do { - unsigned m; - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : 0); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#else - { - unsigned int i; - Pos *q = p - n; - for (i = 0; i < n; i++) { - Pos m = *q; - Pos t = (Pos)wsize; - *q++ = (Pos)(m >= t ? m-t: 0); - } - } -#endif /* NOT_TWEAK_COMPILER */ -} - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflateInit_)(PREFIX3(stream) *strm, int32_t level, const char *version, int32_t stream_size) { - return PREFIX(deflateInit2_)(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); - /* Todo: ignore strm->next_in if we use it as window */ -} - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflateInit2_)(PREFIX3(stream) *strm, int32_t level, int32_t method, int32_t windowBits, - int32_t memLevel, int32_t strategy, const char *version, int32_t stream_size) { - uint32_t window_padding = 0; - deflate_state *s; - int wrap = 1; - static const char my_version[] = PREFIX2(VERSION); - -#if defined(X86_FEATURES) - x86_check_features(); -#elif defined(ARM_FEATURES) - arm_check_features(); -#endif - - if (version == NULL || version[0] != my_version[0] || stream_size != sizeof(PREFIX3(stream))) { - return Z_VERSION_ERROR; - } - if (strm == NULL) - return Z_STREAM_ERROR; - - strm->msg = NULL; - if (strm->zalloc == NULL) { - strm->zalloc = zng_calloc; - strm->opaque = NULL; - } - if (strm->zfree == NULL) - strm->zfree = zng_cfree; - - if (level == Z_DEFAULT_COMPRESSION) - level = 6; - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; -#ifdef GZIP - } else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; -#endif - } - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || - windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED || - (windowBits == 8 && wrap != 1)) { - return Z_STREAM_ERROR; - } - if (windowBits == 8) - windowBits = 9; /* until 256-byte window bug fixed */ - -#if !defined(NO_QUICK_STRATEGY) && !defined(S390_DFLTCC_DEFLATE) - if (level == 1) - windowBits = 13; -#endif - - s = (deflate_state *) ZALLOC_STATE(strm, 1, sizeof(deflate_state)); - if (s == NULL) - return Z_MEM_ERROR; - strm->state = (struct internal_state *)s; - s->strm = strm; - s->status = INIT_STATE; /* to pass state test in deflateReset() */ - - s->wrap = wrap; - s->gzhead = NULL; - s->w_bits = (unsigned int)windowBits; - s->w_size = 1 << s->w_bits; - s->w_mask = s->w_size - 1; - -#ifdef X86_PCLMULQDQ_CRC - window_padding = 8; -#endif - - s->window = (unsigned char *) ZALLOC_WINDOW(strm, s->w_size + window_padding, 2*sizeof(unsigned char)); - s->prev = (Pos *) ZALLOC(strm, s->w_size, sizeof(Pos)); - memset(s->prev, 0, s->w_size * sizeof(Pos)); - s->head = (Pos *) ZALLOC(strm, HASH_SIZE, sizeof(Pos)); - - s->high_water = 0; /* nothing written to s->window yet */ - - s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - /* We overlay pending_buf and sym_buf. This works since the average size - * for length/distance pairs over any compressed block is assured to be 31 - * bits or less. - * - * Analysis: The longest fixed codes are a length code of 8 bits plus 5 - * extra bits, for lengths 131 to 257. The longest fixed distance codes are - * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest - * possible fixed-codes length/distance pair is then 31 bits total. - * - * sym_buf starts one-fourth of the way into pending_buf. So there are - * three bytes in sym_buf for every four bytes in pending_buf. Each symbol - * in sym_buf is three bytes -- two for the distance and one for the - * literal/length. As each symbol is consumed, the pointer to the next - * sym_buf value to read moves forward three bytes. From that symbol, up to - * 31 bits are written to pending_buf. The closest the written pending_buf - * bits gets to the next sym_buf symbol to read is just before the last - * code is written. At that time, 31*(n-2) bits have been written, just - * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at - * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1 - * symbols are written.) The closest the writing gets to what is unread is - * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and - * can range from 128 to 32768. - * - * Therefore, at a minimum, there are 142 bits of space between what is - * written and what is read in the overlain buffers, so the symbols cannot - * be overwritten by the compressed data. That space is actually 139 bits, - * due to the three-bit fixed-code block header. - * - * That covers the case where either Z_FIXED is specified, forcing fixed - * codes, or when the use of fixed codes is chosen, because that choice - * results in a smaller compressed block than dynamic codes. That latter - * condition then assures that the above analysis also covers all dynamic - * blocks. A dynamic-code block will only be chosen to be emitted if it has - * fewer bits than a fixed-code block would for the same set of symbols. - * Therefore its average symbol length is assured to be less than 31. So - * the compressed data for a dynamic block also cannot overwrite the - * symbols from which it is being constructed. - */ - - s->pending_buf = (unsigned char *) ZALLOC(strm, s->lit_bufsize, 4); - s->pending_buf_size = s->lit_bufsize * 4; - - if (s->window == NULL || s->prev == NULL || s->head == NULL || s->pending_buf == NULL) { - s->status = FINISH_STATE; - strm->msg = ERR_MSG(Z_MEM_ERROR); - PREFIX(deflateEnd)(strm); - return Z_MEM_ERROR; - } - s->sym_buf = s->pending_buf + s->lit_bufsize; - s->sym_end = (s->lit_bufsize - 1) * 3; - /* We avoid equality with lit_bufsize*3 because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ - - s->level = level; - s->strategy = strategy; - s->block_open = 0; - s->reproducible = 0; - - return PREFIX(deflateReset)(strm); -} - -/* ========================================================================= - * Check for a valid deflate stream state. Return 0 if ok, 1 if not. - */ -static int deflateStateCheck (PREFIX3(stream) *strm) { - deflate_state *s; - if (strm == NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) - return 1; - s = strm->state; - if (s == NULL || s->strm != strm || (s->status != INIT_STATE && -#ifdef GZIP - s->status != GZIP_STATE && -#endif - s->status != EXTRA_STATE && - s->status != NAME_STATE && - s->status != COMMENT_STATE && - s->status != HCRC_STATE && - s->status != BUSY_STATE && - s->status != FINISH_STATE)) - return 1; - return 0; -} - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflateSetDictionary)(PREFIX3(stream) *strm, const uint8_t *dictionary, uint32_t dictLength) { - deflate_state *s; - unsigned int str, n; - int wrap; - uint32_t avail; - const unsigned char *next; - - if (deflateStateCheck(strm) || dictionary == NULL) - return Z_STREAM_ERROR; - s = strm->state; - wrap = s->wrap; - if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) - return Z_STREAM_ERROR; - - /* when using zlib wrappers, compute Adler-32 for provided dictionary */ - if (wrap == 1) - strm->adler = functable.adler32(strm->adler, dictionary, dictLength); - DEFLATE_SET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */ - s->wrap = 0; /* avoid computing Adler-32 in read_buf */ - - /* if dictionary would fill window, just replace the history */ - if (dictLength >= s->w_size) { - if (wrap == 0) { /* already empty otherwise */ - CLEAR_HASH(s); - s->strstart = 0; - s->block_start = 0; - s->insert = 0; - } - dictionary += dictLength - s->w_size; /* use the tail */ - dictLength = s->w_size; - } - - /* insert dictionary into window and hash */ - avail = strm->avail_in; - next = strm->next_in; - strm->avail_in = dictLength; - strm->next_in = (z_const unsigned char *)dictionary; - fill_window(s); - while (s->lookahead >= MIN_MATCH) { - str = s->strstart; - n = s->lookahead - (MIN_MATCH-1); - functable.insert_string(s, str, n); - s->strstart = str + n; - s->lookahead = MIN_MATCH-1; - fill_window(s); - } - s->strstart += s->lookahead; - s->block_start = (int)s->strstart; - s->insert = s->lookahead; - s->lookahead = 0; - s->prev_length = MIN_MATCH-1; - s->match_available = 0; - strm->next_in = (z_const unsigned char *)next; - strm->avail_in = avail; - s->wrap = wrap; - return Z_OK; -} - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflateGetDictionary)(PREFIX3(stream) *strm, uint8_t *dictionary, uint32_t *dictLength) { - deflate_state *s; - unsigned int len; - - if (deflateStateCheck(strm)) - return Z_STREAM_ERROR; - DEFLATE_GET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */ - s = strm->state; - len = s->strstart + s->lookahead; - if (len > s->w_size) - len = s->w_size; - if (dictionary != NULL && len) - memcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); - if (dictLength != NULL) - *dictLength = len; - return Z_OK; -} - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflateResetKeep)(PREFIX3(stream) *strm) { - deflate_state *s; - - if (deflateStateCheck(strm)) - return Z_STREAM_ERROR; - - strm->total_in = strm->total_out = 0; - strm->msg = NULL; /* use zfree if we ever allocate msg dynamically */ - strm->data_type = Z_UNKNOWN; - - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; - - if (s->wrap < 0) - s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ - - s->status = -#ifdef GZIP - s->wrap == 2 ? GZIP_STATE : -#endif - INIT_STATE; - -#ifdef GZIP - if (s->wrap == 2) - crc_reset(s); - else -#endif - strm->adler = ADLER32_INITIAL_VALUE; - s->last_flush = -2; - - zng_tr_init(s); - - DEFLATE_RESET_KEEP_HOOK(strm); /* hook for IBM Z DFLTCC */ - - return Z_OK; -} - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflateReset)(PREFIX3(stream) *strm) { - int ret; - - ret = PREFIX(deflateResetKeep)(strm); - if (ret == Z_OK) - lm_init(strm->state); - return ret; -} - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflateSetHeader)(PREFIX3(stream) *strm, PREFIX(gz_headerp) head) { - if (deflateStateCheck(strm) || strm->state->wrap != 2) - return Z_STREAM_ERROR; - strm->state->gzhead = head; - return Z_OK; -} - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflatePending)(PREFIX3(stream) *strm, uint32_t *pending, int32_t *bits) { - if (deflateStateCheck(strm)) - return Z_STREAM_ERROR; - if (pending != NULL) - *pending = strm->state->pending; - if (bits != NULL) - *bits = strm->state->bi_valid; - return Z_OK; -} - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflatePrime)(PREFIX3(stream) *strm, int32_t bits, int32_t value) { - deflate_state *s; - uint64_t value64 = (uint64_t)value; - int32_t put; - - if (deflateStateCheck(strm)) - return Z_STREAM_ERROR; - s = strm->state; - if (bits < 0 || bits > BIT_BUF_SIZE || bits > (int32_t)(sizeof(value) << 3) || - s->sym_buf < s->pending_out + ((BIT_BUF_SIZE + 7) >> 3)) - return Z_BUF_ERROR; - do { - put = BIT_BUF_SIZE - s->bi_valid; - if (put > bits) - put = bits; - if (s->bi_valid == 0) - s->bi_buf = value64; - else - s->bi_buf |= (value64 & ((UINT64_C(1) << put) - 1)) << s->bi_valid; - s->bi_valid += put; - zng_tr_flush_bits(s); - value64 >>= put; - bits -= put; - } while (bits); - return Z_OK; -} - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflateParams)(PREFIX3(stream) *strm, int32_t level, int32_t strategy) { - deflate_state *s; - compress_func func; - int hook_flush = Z_NO_FLUSH; - - if (deflateStateCheck(strm)) - return Z_STREAM_ERROR; - s = strm->state; - - if (level == Z_DEFAULT_COMPRESSION) - level = 6; - if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) - return Z_STREAM_ERROR; - DEFLATE_PARAMS_HOOK(strm, level, strategy, &hook_flush); /* hook for IBM Z DFLTCC */ - func = configuration_table[s->level].func; - - if (((strategy != s->strategy || func != configuration_table[level].func) && s->last_flush != -2) - || hook_flush != Z_NO_FLUSH) { - /* Flush the last buffer. Use Z_BLOCK mode, unless the hook requests a "stronger" one. */ - int flush = RANK(hook_flush) > RANK(Z_BLOCK) ? hook_flush : Z_BLOCK; - int err = PREFIX(deflate)(strm, flush); - if (err == Z_STREAM_ERROR) - return err; - if (strm->avail_in || ((int)s->strstart - s->block_start) + s->lookahead || !DEFLATE_DONE(strm, flush)) - return Z_BUF_ERROR; - } - if (s->level != level) { - if (s->level == 0 && s->matches != 0) { - if (s->matches == 1) { - functable.slide_hash(s); - } else { - CLEAR_HASH(s); - } - s->matches = 0; - } - s->level = level; - s->max_lazy_match = configuration_table[level].max_lazy; - s->good_match = configuration_table[level].good_length; - s->nice_match = configuration_table[level].nice_length; - s->max_chain_length = configuration_table[level].max_chain; - } - s->strategy = strategy; - return Z_OK; -} - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflateTune)(PREFIX3(stream) *strm, int32_t good_length, int32_t max_lazy, int32_t nice_length, int32_t max_chain) { - deflate_state *s; - - if (deflateStateCheck(strm)) - return Z_STREAM_ERROR; - s = strm->state; - s->good_match = (unsigned int)good_length; - s->max_lazy_match = (unsigned int)max_lazy; - s->nice_match = nice_length; - s->max_chain_length = (unsigned int)max_chain; - return Z_OK; -} - -/* ========================================================================= - * For the default windowBits of 15 and memLevel of 8, this function returns - * a close to exact, as well as small, upper bound on the compressed size. - * They are coded as constants here for a reason--if the #define's are - * changed, then this function needs to be changed as well. The return - * value for 15 and 8 only works for those exact settings. - * - * For any setting other than those defaults for windowBits and memLevel, - * the value returned is a conservative worst case for the maximum expansion - * resulting from using fixed blocks instead of stored blocks, which deflate - * can emit on compressed data for some combinations of the parameters. - * - * This function could be more sophisticated to provide closer upper bounds for - * every combination of windowBits and memLevel. But even the conservative - * upper bound of about 14% expansion does not seem onerous for output buffer - * allocation. - */ -unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long sourceLen) { - deflate_state *s; - unsigned long complen, wraplen; - - /* conservative upper bound for compressed data */ - complen = sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; - DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, sourceLen); /* hook for IBM Z DFLTCC */ - - /* if can't get parameters, return conservative bound plus zlib wrapper */ - if (deflateStateCheck(strm)) - return complen + 6; - - /* compute wrapper length */ - s = strm->state; - switch (s->wrap) { - case 0: /* raw deflate */ - wraplen = 0; - break; - case 1: /* zlib wrapper */ - wraplen = 6 + (s->strstart ? 4 : 0); - break; -#ifdef GZIP - case 2: /* gzip wrapper */ - wraplen = 18; - if (s->gzhead != NULL) { /* user-supplied gzip header */ - unsigned char *str; - if (s->gzhead->extra != NULL) { - wraplen += 2 + s->gzhead->extra_len; - } - str = s->gzhead->name; - if (str != NULL) { - do { - wraplen++; - } while (*str++); - } - str = s->gzhead->comment; - if (str != NULL) { - do { - wraplen++; - } while (*str++); - } - if (s->gzhead->hcrc) - wraplen += 2; - } - break; -#endif - default: /* for compiler happiness */ - wraplen = 6; - } - - /* if not default parameters, return conservative bound */ - if (DEFLATE_NEED_CONSERVATIVE_BOUND(strm) || /* hook for IBM Z DFLTCC */ - s->w_bits != 15 || HASH_BITS < 15) - return complen + wraplen; - - /* default settings: return tight bound for that case */ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13 - 6 + wraplen; -} - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output, except for - * some deflate_stored() output, goes through this function so some - * applications may wish to modify it to avoid allocating a large - * strm->next_out buffer and copying into it. (See also read_buf()). - */ -Z_INTERNAL void flush_pending(PREFIX3(stream) *strm) { - uint32_t len; - deflate_state *s = strm->state; - - zng_tr_flush_bits(s); - len = s->pending; - if (len > strm->avail_out) - len = strm->avail_out; - if (len == 0) - return; - - Tracev((stderr, "[FLUSH]")); - memcpy(strm->next_out, s->pending_out, len); - strm->next_out += len; - s->pending_out += len; - strm->total_out += len; - strm->avail_out -= len; - s->pending -= len; - if (s->pending == 0) - s->pending_out = s->pending_buf; -} - -/* =========================================================================== - * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. - */ -#define HCRC_UPDATE(beg) \ - do { \ - if (s->gzhead->hcrc && s->pending > (beg)) \ - strm->adler = PREFIX(crc32)(strm->adler, s->pending_buf + (beg), s->pending - (beg)); \ - } while (0) - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { - int32_t old_flush; /* value of flush param for previous deflate call */ - deflate_state *s; - - if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) - return Z_STREAM_ERROR; - s = strm->state; - - if (strm->next_out == NULL || (strm->avail_in != 0 && strm->next_in == NULL) - || (s->status == FINISH_STATE && flush != Z_FINISH)) { - ERR_RETURN(strm, Z_STREAM_ERROR); - } - if (strm->avail_out == 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - old_flush = s->last_flush; - s->last_flush = flush; - - /* Flush as much pending output as possible */ - if (s->pending != 0) { - flush_pending(strm); - if (strm->avail_out == 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s->last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && flush != Z_FINISH) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* Write the header */ - if (s->status == INIT_STATE && s->wrap == 0) - s->status = BUSY_STATE; - if (s->status == INIT_STATE) { - /* zlib header */ - unsigned int header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - unsigned int level_flags; - - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) - header |= PRESET_DICT; - header += 31 - (header % 31); - - put_short_msb(s, (uint16_t)header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) - put_uint32_msb(s, strm->adler); - strm->adler = ADLER32_INITIAL_VALUE; - s->status = BUSY_STATE; - - /* Compression must start with an empty pending buffer */ - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - } -#ifdef GZIP - if (s->status == GZIP_STATE) { - /* gzip header */ - crc_reset(s); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == NULL) { - put_uint32(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - - /* Compression must start with an empty pending buffer */ - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - } else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == NULL ? 0 : 4) + - (s->gzhead->name == NULL ? 0 : 8) + - (s->gzhead->comment == NULL ? 0 : 16) - ); - put_uint32(s, s->gzhead->time); - put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != NULL) - put_short(s, (uint16_t)s->gzhead->extra_len); - if (s->gzhead->hcrc) - strm->adler = PREFIX(crc32)(strm->adler, s->pending_buf, s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } - if (s->status == EXTRA_STATE) { - if (s->gzhead->extra != NULL) { - uint32_t beg = s->pending; /* start of bytes to update crc */ - uint32_t left = (s->gzhead->extra_len & 0xffff) - s->gzindex; - - while (s->pending + left > s->pending_buf_size) { - uint32_t copy = s->pending_buf_size - s->pending; - memcpy(s->pending_buf + s->pending, s->gzhead->extra + s->gzindex, copy); - s->pending = s->pending_buf_size; - HCRC_UPDATE(beg); - s->gzindex += copy; - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - beg = 0; - left -= copy; - } - memcpy(s->pending_buf + s->pending, s->gzhead->extra + s->gzindex, left); - s->pending += left; - HCRC_UPDATE(beg); - s->gzindex = 0; - } - s->status = NAME_STATE; - } - if (s->status == NAME_STATE) { - if (s->gzhead->name != NULL) { - uint32_t beg = s->pending; /* start of bytes to update crc */ - unsigned char val; - - do { - if (s->pending == s->pending_buf_size) { - HCRC_UPDATE(beg); - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - beg = 0; - } - val = s->gzhead->name[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - HCRC_UPDATE(beg); - s->gzindex = 0; - } - s->status = COMMENT_STATE; - } - if (s->status == COMMENT_STATE) { - if (s->gzhead->comment != NULL) { - uint32_t beg = s->pending; /* start of bytes to update crc */ - unsigned char val; - - do { - if (s->pending == s->pending_buf_size) { - HCRC_UPDATE(beg); - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - beg = 0; - } - val = s->gzhead->comment[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - HCRC_UPDATE(beg); - } - s->status = HCRC_STATE; - } - if (s->status == HCRC_STATE) { - if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) { - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - } - put_short(s, (uint16_t)strm->adler); - crc_reset(s); - } - s->status = BUSY_STATE; - - /* Compression must start with an empty pending buffer */ - flush_pending(strm); - if (s->pending != 0) { - s->last_flush = -1; - return Z_OK; - } - } -#endif - - /* Start a new block or continue the current one. - */ - if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { - block_state bstate; - - bstate = DEFLATE_HOOK(strm, flush, &bstate) ? bstate : /* hook for IBM Z DFLTCC */ - s->level == 0 ? deflate_stored(s, flush) : - s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : - s->strategy == Z_RLE ? deflate_rle(s, flush) : - (*(configuration_table[s->level].func))(s, flush); - - if (bstate == finish_started || bstate == finish_done) { - s->status = FINISH_STATE; - } - if (bstate == need_more || bstate == finish_started) { - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate == block_done) { - if (flush == Z_PARTIAL_FLUSH) { - zng_tr_align(s); - } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - zng_tr_stored_block(s, (char*)0, 0L, 0); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush == Z_FULL_FLUSH) { - CLEAR_HASH(s); /* forget history */ - if (s->lookahead == 0) { - s->strstart = 0; - s->block_start = 0; - s->insert = 0; - } - } - } - flush_pending(strm); - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - - if (flush != Z_FINISH) - return Z_OK; - - /* Write the trailer */ -#ifdef GZIP - if (s->wrap == 2) { -# ifdef X86_PCLMULQDQ_CRC - crc_finalize(s); -# endif - put_uint32(s, strm->adler); - put_uint32(s, (uint32_t)strm->total_in); - } else -#endif - if (s->wrap == 1) - put_uint32_msb(s, strm->adler); - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s->wrap > 0) - s->wrap = -s->wrap; /* write the trailer only once! */ - if (s->pending == 0) { - Assert(s->bi_valid == 0, "bi_buf not flushed"); - return Z_STREAM_END; - } - return Z_OK; -} - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflateEnd)(PREFIX3(stream) *strm) { - int32_t status; - - if (deflateStateCheck(strm)) - return Z_STREAM_ERROR; - - status = strm->state->status; - - /* Deallocate in reverse order of allocations: */ - TRY_FREE(strm, strm->state->pending_buf); - TRY_FREE(strm, strm->state->head); - TRY_FREE(strm, strm->state->prev); - TRY_FREE_WINDOW(strm, strm->state->window); - - ZFREE_STATE(strm, strm->state); - strm->state = NULL; - - return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; -} - -/* ========================================================================= - * Copy the source state to the destination state. - */ -int32_t Z_EXPORT PREFIX(deflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *source) { - deflate_state *ds; - deflate_state *ss; - uint32_t window_padding = 0; - - if (deflateStateCheck(source) || dest == NULL) - return Z_STREAM_ERROR; - - ss = source->state; - - memcpy((void *)dest, (void *)source, sizeof(PREFIX3(stream))); - - ds = (deflate_state *) ZALLOC_STATE(dest, 1, sizeof(deflate_state)); - if (ds == NULL) - return Z_MEM_ERROR; - dest->state = (struct internal_state *) ds; - ZCOPY_STATE((void *)ds, (void *)ss, sizeof(deflate_state)); - ds->strm = dest; - -#ifdef X86_PCLMULQDQ_CRC - window_padding = 8; -#endif - - ds->window = (unsigned char *) ZALLOC_WINDOW(dest, ds->w_size + window_padding, 2*sizeof(unsigned char)); - ds->prev = (Pos *) ZALLOC(dest, ds->w_size, sizeof(Pos)); - ds->head = (Pos *) ZALLOC(dest, HASH_SIZE, sizeof(Pos)); - ds->pending_buf = (unsigned char *) ZALLOC(dest, ds->lit_bufsize, 4); - - if (ds->window == NULL || ds->prev == NULL || ds->head == NULL || ds->pending_buf == NULL) { - PREFIX(deflateEnd)(dest); - return Z_MEM_ERROR; - } - - memcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(unsigned char)); - memcpy((void *)ds->prev, (void *)ss->prev, ds->w_size * sizeof(Pos)); - memcpy((void *)ds->head, (void *)ss->head, HASH_SIZE * sizeof(Pos)); - memcpy(ds->pending_buf, ss->pending_buf, ds->pending_buf_size); - - ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->sym_buf = ds->pending_buf + ds->lit_bufsize; - - ds->l_desc.dyn_tree = ds->dyn_ltree; - ds->d_desc.dyn_tree = ds->dyn_dtree; - ds->bl_desc.dyn_tree = ds->bl_tree; - - return Z_OK; -} - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -Z_INTERNAL unsigned read_buf(PREFIX3(stream) *strm, unsigned char *buf, unsigned size) { - uint32_t len = strm->avail_in; - - if (len > size) - len = size; - if (len == 0) - return 0; - - strm->avail_in -= len; - - if (!DEFLATE_NEED_CHECKSUM(strm)) { - memcpy(buf, strm->next_in, len); -#ifdef GZIP - } else if (strm->state->wrap == 2) { - copy_with_crc(strm, buf, len); -#endif - } else { - memcpy(buf, strm->next_in, len); - if (strm->state->wrap == 1) - strm->adler = functable.adler32(strm->adler, buf, len); - } - strm->next_in += len; - strm->total_in += len; - - return len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -static void lm_init(deflate_state *s) { - s->window_size = 2 * s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0; - s->lookahead = 0; - s->insert = 0; - s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->match_start = 0; -} - -#ifdef ZLIB_DEBUG -#define EQUAL 0 -/* result of memcmp for equal strings */ - -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -void check_match(deflate_state *s, Pos start, Pos match, int length) { - /* check that the match length is valid*/ - if (length < MIN_MATCH || length > MAX_MATCH) { - fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); - z_error("invalid match length"); - } - /* check that the match isn't at the same position as the start string */ - if (match == start) { - fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); - z_error("invalid match position"); - } - /* check that the match is indeed a match */ - if (memcmp(s->window + match, s->window + start, length) != EQUAL) { - int32_t i = 0; - fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); - do { - fprintf(stderr, " %03d: match [%02x] start [%02x]\n", i++, s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr, "\\[%u,%d]", start-match, length); - do { - putc(s->window[start++], stderr); - } while (--length != 0); - } -} -#else -# define check_match(s, start, match, length) -#endif /* ZLIB_DEBUG */ - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ - -void Z_INTERNAL fill_window(deflate_state *s) { - unsigned n; - unsigned int more; /* Amount of free space at the end of the window. */ - unsigned int wsize = s->w_size; - - Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = s->window_size - s->lookahead - s->strstart; - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s->strstart >= wsize+MAX_DIST(s)) { - memcpy(s->window, s->window+wsize, (unsigned)wsize); - if (s->match_start >= wsize) { - s->match_start -= wsize; - } else { - s->match_start = 0; - s->prev_length = 0; - } - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (int)wsize; - if (s->insert > s->strstart) - s->insert = s->strstart; - functable.slide_hash(s); - more += wsize; - } - if (s->strm->avail_in == 0) - break; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead + s->insert >= MIN_MATCH) { - unsigned int str = s->strstart - s->insert; - if (str >= 1) - functable.quick_insert_string(s, str + 2 - MIN_MATCH); -#if MIN_MATCH != 3 -#error Call insert_string() MIN_MATCH-3 more times - while (s->insert) { - functable.quick_insert_string(s, str); - str++; - s->insert--; - if (s->lookahead + s->insert < MIN_MATCH) - break; - } -#else - unsigned int count; - if (UNLIKELY(s->lookahead == 1)) { - count = s->insert - 1; - } else { - count = s->insert; - } - if (count > 0) { - functable.insert_string(s, str, count); - s->insert -= count; - } -#endif - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - if (s->high_water < s->window_size) { - unsigned int curr = s->strstart + s->lookahead; - unsigned int init; - - if (s->high_water < curr) { - /* Previous high water mark below current data -- zero WIN_INIT - * bytes or up to end of window, whichever is less. - */ - init = s->window_size - curr; - if (init > WIN_INIT) - init = WIN_INIT; - memset(s->window + curr, 0, init); - s->high_water = curr + init; - } else if (s->high_water < curr + WIN_INIT) { - /* High water mark at or above current data, but below current data - * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - * to end of window, whichever is less. - */ - init = curr + WIN_INIT - s->high_water; - if (init > s->window_size - s->high_water) - init = s->window_size - s->high_water; - memset(s->window + s->high_water, 0, init); - s->high_water += init; - } - } - - Assert((unsigned long)s->strstart <= s->window_size - MIN_LOOKAHEAD, - "not enough room for search"); -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * - * In case deflateParams() is used to later switch to a non-zero compression - * level, s->matches (otherwise unused when storing) keeps track of the number - * of hash table slides to perform. If s->matches is 1, then one hash table - * slide will be done when switching. If s->matches is 2, the maximum value - * allowed here, then the hash table will be cleared, since two or more slides - * is the same as a clear. - * - * deflate_stored() is written to minimize the number of times an input byte is - * copied. It is most efficient with large input and output buffers, which - * maximizes the opportunites to have a single copy from next_in to next_out. - */ -static block_state deflate_stored(deflate_state *s, int flush) { - /* Smallest worthy block size when not flushing or finishing. By default - * this is 32K. This can be as small as 507 bytes for memLevel == 1. For - * large input and output buffers, the stored block size will be larger. - */ - unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); - - /* Copy as many min_block or larger stored blocks directly to next_out as - * possible. If flushing, copy the remaining available input to next_out as - * stored blocks, if there is enough space. - */ - unsigned len, left, have, last = 0; - unsigned used = s->strm->avail_in; - do { - /* Set len to the maximum size block that we can copy directly with the - * available input data and output space. Set left to how much of that - * would be copied from what's left in the window. - */ - len = MAX_STORED; /* maximum deflate stored block length */ - have = (s->bi_valid + 42) >> 3; /* number of header bytes */ - if (s->strm->avail_out < have) /* need room for header */ - break; - /* maximum stored block length that will fit in avail_out: */ - have = s->strm->avail_out - have; - left = (int)s->strstart - s->block_start; /* bytes left in window */ - if (len > (unsigned long)left + s->strm->avail_in) - len = left + s->strm->avail_in; /* limit len to the input */ - if (len > have) - len = have; /* limit len to the output */ - - /* If the stored block would be less than min_block in length, or if - * unable to copy all of the available input when flushing, then try - * copying to the window and the pending buffer instead. Also don't - * write an empty block when flushing -- deflate() does that. - */ - if (len < min_block && ((len == 0 && flush != Z_FINISH) || flush == Z_NO_FLUSH || len != left + s->strm->avail_in)) - break; - - /* Make a dummy stored block in pending to get the header bytes, - * including any pending bits. This also updates the debugging counts. - */ - last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; - zng_tr_stored_block(s, (char *)0, 0L, last); - - /* Replace the lengths in the dummy stored block with len. */ - s->pending -= 4; - put_short(s, (uint16_t)len); - put_short(s, (uint16_t)~len); - - /* Write the stored block header bytes. */ - flush_pending(s->strm); - - /* Update debugging counts for the data about to be copied. */ - cmpr_bits_add(s, len << 3); - sent_bits_add(s, len << 3); - - /* Copy uncompressed bytes from the window to next_out. */ - if (left) { - if (left > len) - left = len; - memcpy(s->strm->next_out, s->window + s->block_start, left); - s->strm->next_out += left; - s->strm->avail_out -= left; - s->strm->total_out += left; - s->block_start += (int)left; - len -= left; - } - - /* Copy uncompressed bytes directly from next_in to next_out, updating - * the check value. - */ - if (len) { - read_buf(s->strm, s->strm->next_out, len); - s->strm->next_out += len; - s->strm->avail_out -= len; - s->strm->total_out += len; - } - } while (last == 0); - - /* Update the sliding window with the last s->w_size bytes of the copied - * data, or append all of the copied data to the existing window if less - * than s->w_size bytes were copied. Also update the number of bytes to - * insert in the hash tables, in the event that deflateParams() switches to - * a non-zero compression level. - */ - used -= s->strm->avail_in; /* number of input bytes directly copied */ - if (used) { - /* If any input was used, then no unused input remains in the window, - * therefore s->block_start == s->strstart. - */ - if (used >= s->w_size) { /* supplant the previous history */ - s->matches = 2; /* clear hash */ - memcpy(s->window, s->strm->next_in - s->w_size, s->w_size); - s->strstart = s->w_size; - s->insert = s->strstart; - } else { - if (s->window_size - s->strstart <= used) { - /* Slide the window down. */ - s->strstart -= s->w_size; - memcpy(s->window, s->window + s->w_size, s->strstart); - if (s->matches < 2) - s->matches++; /* add a pending slide_hash() */ - if (s->insert > s->strstart) - s->insert = s->strstart; - } - memcpy(s->window + s->strstart, s->strm->next_in - used, used); - s->strstart += used; - s->insert += MIN(used, s->w_size - s->insert); - } - s->block_start = (int)s->strstart; - } - if (s->high_water < s->strstart) - s->high_water = s->strstart; - - /* If the last block was written to next_out, then done. */ - if (last) - return finish_done; - - /* If flushing and all input has been consumed, then done. */ - if (flush != Z_NO_FLUSH && flush != Z_FINISH && s->strm->avail_in == 0 && (int)s->strstart == s->block_start) - return block_done; - - /* Fill the window with any remaining input. */ - have = s->window_size - s->strstart; - if (s->strm->avail_in > have && s->block_start >= (int)s->w_size) { - /* Slide the window down. */ - s->block_start -= (int)s->w_size; - s->strstart -= s->w_size; - memcpy(s->window, s->window + s->w_size, s->strstart); - if (s->matches < 2) - s->matches++; /* add a pending slide_hash() */ - have += s->w_size; /* more space now */ - if (s->insert > s->strstart) - s->insert = s->strstart; - } - if (have > s->strm->avail_in) - have = s->strm->avail_in; - if (have) { - read_buf(s->strm, s->window + s->strstart, have); - s->strstart += have; - s->insert += MIN(have, s->w_size - s->insert); - } - if (s->high_water < s->strstart) - s->high_water = s->strstart; - - /* There was not enough avail_out to write a complete worthy or flushed - * stored block to next_out. Write a stored block to pending instead, if we - * have enough input for a worthy block, or if flushing and there is enough - * room for the remaining input as a stored block in the pending buffer. - */ - have = (s->bi_valid + 42) >> 3; /* number of header bytes */ - /* maximum stored block length that will fit in pending: */ - have = MIN(s->pending_buf_size - have, MAX_STORED); - min_block = MIN(have, s->w_size); - left = (int)s->strstart - s->block_start; - if (left >= min_block || ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && s->strm->avail_in == 0 && left <= have)) { - len = MIN(left, have); - last = flush == Z_FINISH && s->strm->avail_in == 0 && len == left ? 1 : 0; - zng_tr_stored_block(s, (char *)s->window + s->block_start, len, last); - s->block_start += (int)len; - flush_pending(s->strm); - } - - /* We've done all we can with the available input and output. */ - return last ? finish_started : need_more; -} - - -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -static block_state deflate_rle(deflate_state *s, int flush) { - int bflush = 0; /* set if current block must be flushed */ - unsigned int prev; /* byte at distance one to match */ - unsigned char *scan, *strend; /* scan goes up to strend for length of run */ - uint32_t match_len = 0; - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s->lookahead <= MAX_MATCH) { - fill_window(s); - if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) - return need_more; - if (s->lookahead == 0) - break; /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - if (s->lookahead >= MIN_MATCH && s->strstart > 0) { - scan = s->window + s->strstart - 1; - prev = *scan; - if (prev == *++scan && prev == *++scan && prev == *++scan) { - strend = s->window + s->strstart + MAX_MATCH; - do { - } while (prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - scan < strend); - match_len = MAX_MATCH - (unsigned int)(strend - scan); - if (match_len > s->lookahead) - match_len = s->lookahead; - } - Assert(scan <= s->window + s->window_size - 1, "wild scan"); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (match_len >= MIN_MATCH) { - check_match(s, s->strstart, s->strstart - 1, match_len); - - bflush = zng_tr_tally_dist(s, 1, match_len - MIN_MATCH); - - s->lookahead -= match_len; - s->strstart += match_len; - match_len = 0; - } else { - /* No match, output a literal byte */ - bflush = zng_tr_tally_lit(s, s->window[s->strstart]); - s->lookahead--; - s->strstart++; - } - if (bflush) - FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->sym_next) - FLUSH_BLOCK(s, 0); - return block_done; -} - -/* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ -static block_state deflate_huff(deflate_state *s, int flush) { - int bflush = 0; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we have a literal to write. */ - if (s->lookahead == 0) { - fill_window(s); - if (s->lookahead == 0) { - if (flush == Z_NO_FLUSH) - return need_more; - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - bflush = zng_tr_tally_lit(s, s->window[s->strstart]); - s->lookahead--; - s->strstart++; - if (bflush) - FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->sym_next) - FLUSH_BLOCK(s, 0); - return block_done; -} - -#ifndef ZLIB_COMPAT -/* ========================================================================= - * Checks whether buffer size is sufficient and whether this parameter is a duplicate. - */ -static int32_t deflateSetParamPre(zng_deflate_param_value **out, size_t min_size, zng_deflate_param_value *param) { - int32_t buf_error = param->size < min_size; - - if (*out != NULL) { - (*out)->status = Z_BUF_ERROR; - buf_error = 1; - } - *out = param; - return buf_error; -} - -/* ========================================================================= */ -int32_t Z_EXPORT zng_deflateSetParams(zng_stream *strm, zng_deflate_param_value *params, size_t count) { - size_t i; - deflate_state *s; - zng_deflate_param_value *new_level = NULL; - zng_deflate_param_value *new_strategy = NULL; - zng_deflate_param_value *new_reproducible = NULL; - int param_buf_error; - int version_error = 0; - int buf_error = 0; - int stream_error = 0; - int ret; - int val; - - /* Initialize the statuses. */ - for (i = 0; i < count; i++) - params[i].status = Z_OK; - - /* Check whether the stream state is consistent. */ - if (deflateStateCheck(strm)) - return Z_STREAM_ERROR; - s = strm->state; - - /* Check buffer sizes and detect duplicates. */ - for (i = 0; i < count; i++) { - switch (params[i].param) { - case Z_DEFLATE_LEVEL: - param_buf_error = deflateSetParamPre(&new_level, sizeof(int), ¶ms[i]); - break; - case Z_DEFLATE_STRATEGY: - param_buf_error = deflateSetParamPre(&new_strategy, sizeof(int), ¶ms[i]); - break; - case Z_DEFLATE_REPRODUCIBLE: - param_buf_error = deflateSetParamPre(&new_reproducible, sizeof(int), ¶ms[i]); - break; - default: - params[i].status = Z_VERSION_ERROR; - version_error = 1; - param_buf_error = 0; - break; - } - if (param_buf_error) { - params[i].status = Z_BUF_ERROR; - buf_error = 1; - } - } - /* Exit early if small buffers or duplicates are detected. */ - if (buf_error) - return Z_BUF_ERROR; - - /* Apply changes, remember if there were errors. */ - if (new_level != NULL || new_strategy != NULL) { - ret = PREFIX(deflateParams)(strm, new_level == NULL ? s->level : *(int *)new_level->buf, - new_strategy == NULL ? s->strategy : *(int *)new_strategy->buf); - if (ret != Z_OK) { - if (new_level != NULL) - new_level->status = Z_STREAM_ERROR; - if (new_strategy != NULL) - new_strategy->status = Z_STREAM_ERROR; - stream_error = 1; - } - } - if (new_reproducible != NULL) { - val = *(int *)new_reproducible->buf; - if (DEFLATE_CAN_SET_REPRODUCIBLE(strm, val)) { - s->reproducible = val; - } else { - new_reproducible->status = Z_STREAM_ERROR; - stream_error = 1; - } - } - - /* Report version errors only if there are no real errors. */ - return stream_error ? Z_STREAM_ERROR : (version_error ? Z_VERSION_ERROR : Z_OK); -} - -/* ========================================================================= */ -int32_t Z_EXPORT zng_deflateGetParams(zng_stream *strm, zng_deflate_param_value *params, size_t count) { - deflate_state *s; - size_t i; - int32_t buf_error = 0; - int32_t version_error = 0; - - /* Initialize the statuses. */ - for (i = 0; i < count; i++) - params[i].status = Z_OK; - - /* Check whether the stream state is consistent. */ - if (deflateStateCheck(strm)) - return Z_STREAM_ERROR; - s = strm->state; - - for (i = 0; i < count; i++) { - switch (params[i].param) { - case Z_DEFLATE_LEVEL: - if (params[i].size < sizeof(int)) - params[i].status = Z_BUF_ERROR; - else - *(int *)params[i].buf = s->level; - break; - case Z_DEFLATE_STRATEGY: - if (params[i].size < sizeof(int)) - params[i].status = Z_BUF_ERROR; - else - *(int *)params[i].buf = s->strategy; - break; - case Z_DEFLATE_REPRODUCIBLE: - if (params[i].size < sizeof(int)) - params[i].status = Z_BUF_ERROR; - else - *(int *)params[i].buf = s->reproducible; - break; - default: - params[i].status = Z_VERSION_ERROR; - version_error = 1; - break; - } - if (params[i].status == Z_BUF_ERROR) - buf_error = 1; - } - return buf_error ? Z_BUF_ERROR : (version_error ? Z_VERSION_ERROR : Z_OK); -} -#endif diff --git a/libs/zlibng/deflate.h b/libs/zlibng/deflate.h deleted file mode 100644 index 03ea3126ff..0000000000 --- a/libs/zlibng/deflate.h +++ /dev/null @@ -1,411 +0,0 @@ -#ifndef DEFLATE_H_ -#define DEFLATE_H_ -/* deflate.h -- internal compression state - * Copyright (C) 1995-2016 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#include "zutil.h" -#include "zendian.h" - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer creation by deflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip encoding - should be left enabled. */ -#ifndef NO_GZIP -# define GZIP -#endif - -/* =========================================================================== - * Internal compression state. - */ - -#define LENGTH_CODES 29 -/* number of length codes, not counting the special END_BLOCK code */ - -#define LITERALS 256 -/* number of literal bytes 0..255 */ - -#define L_CODES (LITERALS+1+LENGTH_CODES) -/* number of Literal or Length codes, including the END_BLOCK code */ - -#define D_CODES 30 -/* number of distance codes */ - -#define BL_CODES 19 -/* number of codes used to transfer the bit lengths */ - -#define HEAP_SIZE (2*L_CODES+1) -/* maximum heap size */ - -#define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ - -#define BIT_BUF_SIZE 64 -/* size of bit buffer in bi_buf */ - -#define END_BLOCK 256 -/* end of block literal code */ - -#define INIT_STATE 42 /* zlib header -> BUSY_STATE */ -#ifdef GZIP -# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ -#endif -#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ -#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ -#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ -#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ -#define BUSY_STATE 113 /* deflate -> FINISH_STATE */ -#define FINISH_STATE 666 /* stream complete */ -/* Stream status */ - -#define HASH_BITS 16u /* log2(HASH_SIZE) */ -#define HASH_SIZE 65536u /* number of elements in hash table */ -#define HASH_MASK (HASH_SIZE - 1u) /* HASH_SIZE-1 */ - - -/* Data structure describing a single value and its code string. */ -typedef struct ct_data_s { - union { - uint16_t freq; /* frequency count */ - uint16_t code; /* bit string */ - } fc; - union { - uint16_t dad; /* father node in Huffman tree */ - uint16_t len; /* length of bit string */ - } dl; -} ct_data; - -#define Freq fc.freq -#define Code fc.code -#define Dad dl.dad -#define Len dl.len - -typedef struct static_tree_desc_s static_tree_desc; - -typedef struct tree_desc_s { - ct_data *dyn_tree; /* the dynamic tree */ - int max_code; /* largest code with non zero frequency */ - const static_tree_desc *stat_desc; /* the corresponding static tree */ -} tree_desc; - -typedef uint16_t Pos; - -/* A Pos is an index in the character window. We use short instead of int to - * save space in the various tables. - */ - -typedef struct internal_state { - PREFIX3(stream) *strm; /* pointer back to this zlib stream */ - unsigned char *pending_buf; /* output still pending */ - unsigned char *pending_out; /* next pending byte to output to the stream */ - uint32_t pending_buf_size; /* size of pending_buf */ - uint32_t pending; /* nb of bytes in the pending buffer */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - uint32_t gzindex; /* where in extra, name, or comment */ - PREFIX(gz_headerp) gzhead; /* gzip header information to write */ - int status; /* as the name implies */ - int last_flush; /* value of flush param for previous deflate call */ - int reproducible; /* Whether reproducible compression results are required. */ - - int block_open; - /* Whether or not a block is currently open for the QUICK deflation scheme. - * This is set to 1 if there is an active block, or 0 if the block was just closed. - */ - - /* used by deflate.c: */ - - unsigned int w_size; /* LZ77 window size (32K by default) */ - unsigned int w_bits; /* log2(w_size) (8..16) */ - unsigned int w_mask; /* w_size - 1 */ - unsigned int lookahead; /* number of valid bytes ahead in window */ - - unsigned int high_water; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ - - unsigned int window_size; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - unsigned char *window; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. Also, it limits - * the window size to 64K, which is quite useful on MSDOS. - * To do: use the user input buffer as sliding window. - */ - - Pos *prev; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - Pos *head; /* Heads of the hash chains or 0. */ - - int block_start; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - unsigned int match_length; /* length of best match */ - Pos prev_match; /* previous match */ - int match_available; /* set if previous match exists */ - unsigned int strstart; /* start of string to insert */ - unsigned int match_start; /* start of matching string */ - - unsigned int prev_length; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - unsigned int max_chain_length; - /* To speed up deflation, hash chains are never searched beyond this length. - * A higher limit improves compression ratio but degrades the speed. - */ - - unsigned int max_lazy_match; - /* Attempt to find a better match only when the current match is strictly smaller - * than this value. This mechanism is used only for compression levels >= 4. - */ -# define max_insert_length max_lazy_match - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - int level; /* compression level (1..9) */ - int strategy; /* favor or force Huffman coding*/ - - unsigned int good_match; - /* Use a faster search when the previous match is longer than this */ - - int nice_match; /* Stop searching when current match exceeds this */ - -#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) - /* Only used if X86_PCLMULQDQ_CRC is defined */ - unsigned crc0[4 * 5]; -#endif - - /* used by trees.c: */ - /* Didn't use ct_data typedef below to suppress compiler warning */ - struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - struct tree_desc_s l_desc; /* desc. for literal tree */ - struct tree_desc_s d_desc; /* desc. for distance tree */ - struct tree_desc_s bl_desc; /* desc. for bit length tree */ - - uint16_t bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - int heap_len; /* number of elements in the heap */ - int heap_max; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - unsigned char depth[2*L_CODES+1]; - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - unsigned int lit_bufsize; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - unsigned char *sym_buf; /* buffer for distances and literals/lengths */ - unsigned int sym_next; /* running index in sym_buf */ - unsigned int sym_end; /* symbol table full when sym_next reaches this */ - - unsigned long opt_len; /* bit length of current block with optimal trees */ - unsigned long static_len; /* bit length of current block with static trees */ - unsigned int matches; /* number of string matches in current block */ - unsigned int insert; /* bytes at end of window left to insert */ - - /* compressed_len and bits_sent are only used if ZLIB_DEBUG is defined */ - unsigned long compressed_len; /* total bit length of compressed file mod 2^32 */ - unsigned long bits_sent; /* bit length of compressed data sent mod 2^32 */ - - /* Reserved for future use and alignment purposes */ - char *reserved_p; - - uint64_t bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least significant bits). */ - - int32_t bi_valid; - /* Number of valid bits in bi_buf. All bits above the last valid bit are always zero. */ - - /* Reserved for future use and alignment purposes */ - int32_t reserved[11]; -} ALIGNED_(8) deflate_state; - -typedef enum { - need_more, /* block not completed, need more input or more output */ - block_done, /* block flush performed */ - finish_started, /* finish started, need only more output at next deflate */ - finish_done /* finish done, accept no more input or output */ -} block_state; - -/* Output a byte on the stream. - * IN assertion: there is enough room in pending_buf. - */ -#define put_byte(s, c) { \ - s->pending_buf[s->pending++] = (unsigned char)(c); \ -} - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pending_buf. - */ -static inline void put_short(deflate_state *s, uint16_t w) { -#if defined(UNALIGNED_OK) - *(uint16_t *)(&s->pending_buf[s->pending]) = w; - s->pending += 2; -#else - put_byte(s, (w & 0xff)); - put_byte(s, ((w >> 8) & 0xff)); -#endif -} - -/* =========================================================================== - * Output a short MSB first on the stream. - * IN assertion: there is enough room in pending_buf. - */ -static inline void put_short_msb(deflate_state *s, uint16_t w) { - put_byte(s, ((w >> 8) & 0xff)); - put_byte(s, (w & 0xff)); -} - -/* =========================================================================== - * Output a 32-bit unsigned int LSB first on the stream. - * IN assertion: there is enough room in pending_buf. - */ -static inline void put_uint32(deflate_state *s, uint32_t dw) { -#if defined(UNALIGNED_OK) - *(uint32_t *)(&s->pending_buf[s->pending]) = dw; - s->pending += 4; -#else - put_byte(s, (dw & 0xff)); - put_byte(s, ((dw >> 8) & 0xff)); - put_byte(s, ((dw >> 16) & 0xff)); - put_byte(s, ((dw >> 24) & 0xff)); -#endif -} - -/* =========================================================================== - * Output a 32-bit unsigned int MSB first on the stream. - * IN assertion: there is enough room in pending_buf. - */ -static inline void put_uint32_msb(deflate_state *s, uint32_t dw) { -#if defined(UNALIGNED_OK) - *(uint32_t *)(&s->pending_buf[s->pending]) = ZSWAP32(dw); - s->pending += 4; -#else - put_byte(s, ((dw >> 24) & 0xff)); - put_byte(s, ((dw >> 16) & 0xff)); - put_byte(s, ((dw >> 8) & 0xff)); - put_byte(s, (dw & 0xff)); -#endif -} - -/* =========================================================================== - * Output a 64-bit unsigned int LSB first on the stream. - * IN assertion: there is enough room in pending_buf. - */ -static inline void put_uint64(deflate_state *s, uint64_t lld) { -#if defined(UNALIGNED64_OK) - *(uint64_t *)(&s->pending_buf[s->pending]) = lld; - s->pending += 8; -#elif defined(UNALIGNED_OK) - *(uint32_t *)(&s->pending_buf[s->pending]) = lld & 0xffffffff; - s->pending += 4; - *(uint32_t *)(&s->pending_buf[s->pending]) = (lld >> 32) & 0xffffffff; - s->pending += 4; -#else - put_byte(s, (lld & 0xff)); - put_byte(s, ((lld >> 8) & 0xff)); - put_byte(s, ((lld >> 16) & 0xff)); - put_byte(s, ((lld >> 24) & 0xff)); - put_byte(s, ((lld >> 32) & 0xff)); - put_byte(s, ((lld >> 40) & 0xff)); - put_byte(s, ((lld >> 48) & 0xff)); - put_byte(s, ((lld >> 56) & 0xff)); -#endif -} - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - -#define WIN_INIT MAX_MATCH -/* Number of bytes after end of data in window to initialize in order to avoid - memory checker errors from longest match routines */ - - -void Z_INTERNAL fill_window(deflate_state *s); -void Z_INTERNAL slide_hash_c(deflate_state *s); - - /* in trees.c */ -void Z_INTERNAL zng_tr_init(deflate_state *s); -void Z_INTERNAL zng_tr_flush_block(deflate_state *s, char *buf, uint32_t stored_len, int last); -void Z_INTERNAL zng_tr_flush_bits(deflate_state *s); -void Z_INTERNAL zng_tr_align(deflate_state *s); -void Z_INTERNAL zng_tr_stored_block(deflate_state *s, char *buf, uint32_t stored_len, int last); -unsigned Z_INTERNAL bi_reverse(unsigned code, int len); -void Z_INTERNAL flush_pending(PREFIX3(streamp) strm); -#define d_code(dist) ((dist) < 256 ? zng_dist_code[dist] : zng_dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. zng_dist_code[256] and zng_dist_code[257] are never - * used. - */ - -/* Bit buffer and compress bits calculation debugging */ -#ifdef ZLIB_DEBUG -# define cmpr_bits_add(s, len) s->compressed_len += (len) -# define cmpr_bits_align(s) s->compressed_len = (s->compressed_len + 7) & ~7L -# define sent_bits_add(s, bits) s->bits_sent += (bits) -# define sent_bits_align(s) s->bits_sent = (s->bits_sent + 7) & ~7L -#else -# define cmpr_bits_add(s, len) (void)(len) -# define cmpr_bits_align(s) -# define sent_bits_add(s, bits) (void)(bits) -# define sent_bits_align(s) -#endif - -#endif /* DEFLATE_H_ */ diff --git a/libs/zlibng/deflate_fast.c b/libs/zlibng/deflate_fast.c deleted file mode 100644 index 14718ba14c..0000000000 --- a/libs/zlibng/deflate_fast.c +++ /dev/null @@ -1,106 +0,0 @@ -/* deflate_fast.c -- compress data using the fast strategy of deflation algorithm - * - * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "deflate.h" -#include "deflate_p.h" -#include "functable.h" - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -Z_INTERNAL block_state deflate_fast(deflate_state *s, int flush) { - Pos hash_head; /* head of the hash chain */ - int bflush = 0; /* set if current block must be flushed */ - int64_t dist; - uint32_t match_len = 0; - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (UNLIKELY(s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH)) { - return need_more; - } - if (UNLIKELY(s->lookahead == 0)) - break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (s->lookahead >= MIN_MATCH) { - hash_head = functable.quick_insert_string(s, s->strstart); - dist = (int64_t)s->strstart - hash_head; - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match length < MIN_MATCH - */ - - if (dist <= MAX_DIST(s) && dist > 0) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - match_len = functable.longest_match(s, hash_head); - /* longest_match() sets match_start */ - } - } - - if (match_len >= MIN_MATCH) { - check_match(s, s->strstart, s->match_start, match_len); - - bflush = zng_tr_tally_dist(s, s->strstart - s->match_start, match_len - MIN_MATCH); - - s->lookahead -= match_len; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (match_len <= s->max_insert_length && s->lookahead >= MIN_MATCH) { - match_len--; /* string at strstart already in table */ - s->strstart++; - - functable.insert_string(s, s->strstart, match_len); - s->strstart += match_len; - } else { - s->strstart += match_len; -#if MIN_MATCH != 3 - functable.insert_string(s, s->strstart + 2 - MIN_MATCH, MIN_MATCH - 2); -#else - functable.quick_insert_string(s, s->strstart + 2 - MIN_MATCH); -#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - match_len = 0; - } else { - /* No match, output a literal byte */ - bflush = zng_tr_tally_lit(s, s->window[s->strstart]); - s->lookahead--; - s->strstart++; - } - if (UNLIKELY(bflush)) - FLUSH_BLOCK(s, 0); - } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; - if (UNLIKELY(flush == Z_FINISH)) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (UNLIKELY(s->sym_next)) - FLUSH_BLOCK(s, 0); - return block_done; -} diff --git a/libs/zlibng/deflate_medium.c b/libs/zlibng/deflate_medium.c deleted file mode 100644 index dad550cd10..0000000000 --- a/libs/zlibng/deflate_medium.c +++ /dev/null @@ -1,293 +0,0 @@ -/* deflate_medium.c -- The deflate_medium deflate strategy - * - * Copyright (C) 2013 Intel Corporation. All rights reserved. - * Authors: - * Arjan van de Ven - * - * For conditions of distribution and use, see copyright notice in zlib.h - */ -#ifndef NO_MEDIUM_STRATEGY -#include -#include "zbuild.h" -#include "deflate.h" -#include "deflate_p.h" -#include "functable.h" - -struct match { - uint16_t match_start; - uint16_t match_length; - uint16_t strstart; - uint16_t orgstart; -}; - -static int emit_match(deflate_state *s, struct match match) { - int bflush = 0; - - /* matches that are not long enough we need to emit as literals */ - if (match.match_length < MIN_MATCH) { - while (match.match_length) { - bflush += zng_tr_tally_lit(s, s->window[match.strstart]); - s->lookahead--; - match.strstart++; - match.match_length--; - } - return bflush; - } - - check_match(s, match.strstart, match.match_start, match.match_length); - - bflush += zng_tr_tally_dist(s, match.strstart - match.match_start, match.match_length - MIN_MATCH); - - s->lookahead -= match.match_length; - return bflush; -} - -static void insert_match(deflate_state *s, struct match match) { - if (UNLIKELY(s->lookahead <= (unsigned int)(match.match_length + MIN_MATCH))) - return; - - /* matches that are not long enough we need to emit as literals */ - if (LIKELY(match.match_length < MIN_MATCH)) { - match.strstart++; - match.match_length--; - if (UNLIKELY(match.match_length > 0)) { - if (match.strstart >= match.orgstart) { - if (match.strstart + match.match_length - 1 >= match.orgstart) { - functable.insert_string(s, match.strstart, match.match_length); - } else { - functable.insert_string(s, match.strstart, match.orgstart - match.strstart + 1); - } - match.strstart += match.match_length; - match.match_length = 0; - } - } - return; - } - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (match.match_length <= 16* s->max_insert_length && s->lookahead >= MIN_MATCH) { - match.match_length--; /* string at strstart already in table */ - match.strstart++; - - if (LIKELY(match.strstart >= match.orgstart)) { - if (LIKELY(match.strstart + match.match_length - 1 >= match.orgstart)) { - functable.insert_string(s, match.strstart, match.match_length); - } else { - functable.insert_string(s, match.strstart, match.orgstart - match.strstart + 1); - } - } else if (match.orgstart < match.strstart + match.match_length) { - functable.insert_string(s, match.orgstart, match.strstart + match.match_length - match.orgstart); - } - match.strstart += match.match_length; - match.match_length = 0; - } else { - match.strstart += match.match_length; - match.match_length = 0; - if (match.strstart >= (MIN_MATCH - 2)) -#if MIN_MATCH != 3 - functable.insert_string(s, match.strstart + 2 - MIN_MATCH, MIN_MATCH - 2); -#else - functable.quick_insert_string(s, match.strstart + 2 - MIN_MATCH); -#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } -} - -static void fizzle_matches(deflate_state *s, struct match *current, struct match *next) { - Pos limit; - unsigned char *match, *orig; - int changed = 0; - struct match c, n; - /* step zero: sanity checks */ - - if (current->match_length <= 1) - return; - - if (UNLIKELY(current->match_length > 1 + next->match_start)) - return; - - if (UNLIKELY(current->match_length > 1 + next->strstart)) - return; - - match = s->window - current->match_length + 1 + next->match_start; - orig = s->window - current->match_length + 1 + next->strstart; - - /* quick exit check.. if this fails then don't bother with anything else */ - if (LIKELY(*match != *orig)) - return; - - c = *current; - n = *next; - - /* step one: try to move the "next" match to the left as much as possible */ - limit = next->strstart > MAX_DIST(s) ? next->strstart - (Pos)MAX_DIST(s) : 0; - - match = s->window + n.match_start - 1; - orig = s->window + n.strstart - 1; - - while (*match == *orig) { - if (UNLIKELY(c.match_length < 1)) - break; - if (UNLIKELY(n.strstart <= limit)) - break; - if (UNLIKELY(n.match_length >= 256)) - break; - if (UNLIKELY(n.match_start <= 1)) - break; - - n.strstart--; - n.match_start--; - n.match_length++; - c.match_length--; - match--; - orig--; - changed++; - } - - if (!changed) - return; - - if (c.match_length <= 1 && n.match_length != 2) { - n.orgstart++; - *current = c; - *next = n; - } else { - return; - } -} - -Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { - /* Align the first struct to start on a new cacheline, this allows us to fit both structs in one cacheline */ - ALIGNED_(16) struct match current_match; - struct match next_match; - - memset(¤t_match, 0, sizeof(struct match)); - memset(&next_match, 0, sizeof(struct match)); - - for (;;) { - Pos hash_head = 0; /* head of the hash chain */ - int bflush = 0; /* set if current block must be flushed */ - int64_t dist; - - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next current_match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (UNLIKELY(s->lookahead == 0)) - break; /* flush the current block */ - next_match.match_length = 0; - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - - /* If we already have a future match from a previous round, just use that */ - if (next_match.match_length > 0) { - current_match = next_match; - next_match.match_length = 0; - } else { - hash_head = 0; - if (s->lookahead >= MIN_MATCH) { - hash_head = functable.quick_insert_string(s, s->strstart); - } - - current_match.strstart = (uint16_t)s->strstart; - current_match.orgstart = current_match.strstart; - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - - dist = (int64_t)s->strstart - hash_head; - if (dist <= MAX_DIST(s) && dist > 0) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - current_match.match_length = (uint16_t)functable.longest_match(s, hash_head); - current_match.match_start = (uint16_t)s->match_start; - if (UNLIKELY(current_match.match_length < MIN_MATCH)) - current_match.match_length = 1; - if (UNLIKELY(current_match.match_start >= current_match.strstart)) { - /* this can happen due to some restarts */ - current_match.match_length = 1; - } - } else { - /* Set up the match to be a 1 byte literal */ - current_match.match_start = 0; - current_match.match_length = 1; - } - } - - insert_match(s, current_match); - - /* now, look ahead one */ - if (LIKELY(s->lookahead > MIN_LOOKAHEAD && (uint32_t)(current_match.strstart + current_match.match_length) < (s->window_size - MIN_LOOKAHEAD))) { - s->strstart = current_match.strstart + current_match.match_length; - hash_head = functable.quick_insert_string(s, s->strstart); - - next_match.strstart = (uint16_t)s->strstart; - next_match.orgstart = next_match.strstart; - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - - dist = (int64_t)s->strstart - hash_head; - if (dist <= MAX_DIST(s) && dist > 0) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - next_match.match_length = (uint16_t)functable.longest_match(s, hash_head); - next_match.match_start = (uint16_t)s->match_start; - if (UNLIKELY(next_match.match_start >= next_match.strstart)) { - /* this can happen due to some restarts */ - next_match.match_length = 1; - } - if (next_match.match_length < MIN_MATCH) - next_match.match_length = 1; - else - fizzle_matches(s, ¤t_match, &next_match); - } else { - /* Set up the match to be a 1 byte literal */ - next_match.match_start = 0; - next_match.match_length = 1; - } - - s->strstart = current_match.strstart; - } else { - next_match.match_length = 0; - } - - /* now emit the current match */ - bflush = emit_match(s, current_match); - - /* move the "cursor" forward */ - s->strstart += current_match.match_length; - - if (UNLIKELY(bflush)) - FLUSH_BLOCK(s, 0); - } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (UNLIKELY(s->sym_next)) - FLUSH_BLOCK(s, 0); - - return block_done; -} -#endif diff --git a/libs/zlibng/deflate_p.h b/libs/zlibng/deflate_p.h deleted file mode 100644 index 102a4de066..0000000000 --- a/libs/zlibng/deflate_p.h +++ /dev/null @@ -1,82 +0,0 @@ -/* deflate_p.h -- Private inline functions and macros shared with more than - * one deflate method - * - * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - */ - -#ifndef DEFLATE_P_H -#define DEFLATE_P_H - -/* Forward declare common non-inlined functions declared in deflate.c */ - -#ifdef ZLIB_DEBUG -void check_match(deflate_state *s, Pos start, Pos match, int length); -#else -#define check_match(s, start, match, length) -#endif -void flush_pending(PREFIX3(stream) *strm); - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ - -extern const unsigned char Z_INTERNAL zng_length_code[]; -extern const unsigned char Z_INTERNAL zng_dist_code[]; - -static inline int zng_tr_tally_lit(deflate_state *s, unsigned char c) { - /* c is the unmatched char */ - s->sym_buf[s->sym_next++] = 0; - s->sym_buf[s->sym_next++] = 0; - s->sym_buf[s->sym_next++] = c; - s->dyn_ltree[c].Freq++; - Tracevv((stderr, "%c", c)); - Assert(c <= (MAX_MATCH-MIN_MATCH), "zng_tr_tally: bad literal"); - return (s->sym_next == s->sym_end); -} - -static inline int zng_tr_tally_dist(deflate_state *s, uint32_t dist, uint32_t len) { - /* dist: distance of matched string */ - /* len: match length-MIN_MATCH */ - s->sym_buf[s->sym_next++] = (uint8_t)(dist); - s->sym_buf[s->sym_next++] = (uint8_t)(dist >> 8); - s->sym_buf[s->sym_next++] = (uint8_t)len; - s->matches++; - dist--; - Assert(dist < MAX_DIST(s) && (uint16_t)d_code(dist) < (uint16_t)D_CODES, - "zng_tr_tally: bad match"); - - s->dyn_ltree[zng_length_code[len]+LITERALS+1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - return (s->sym_next == s->sym_end); -} - -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ -#define FLUSH_BLOCK_ONLY(s, last) { \ - zng_tr_flush_block(s, (s->block_start >= 0 ? \ - (char *)&s->window[(unsigned)s->block_start] : \ - NULL), \ - (uint32_t)((int)s->strstart - s->block_start), \ - (last)); \ - s->block_start = (int)s->strstart; \ - flush_pending(s->strm); \ -} - -/* Same but force premature exit if necessary. */ -#define FLUSH_BLOCK(s, last) { \ - FLUSH_BLOCK_ONLY(s, last); \ - if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ -} - -/* Maximum stored block length in deflate format (not including header). */ -#define MAX_STORED 65535 - -/* Minimum of a and b. */ -#define MIN(a, b) ((a) > (b) ? (b) : (a)) - -#endif diff --git a/libs/zlibng/deflate_quick.c b/libs/zlibng/deflate_quick.c deleted file mode 100644 index 268cce80d1..0000000000 --- a/libs/zlibng/deflate_quick.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * The deflate_quick deflate strategy, designed to be used when cycles are - * at a premium. - * - * Copyright (C) 2013 Intel Corporation. All rights reserved. - * Authors: - * Wajdi Feghali - * Jim Guilford - * Vinodh Gopal - * Erdinc Ozturk - * Jim Kukunas - * - * Portions are Copyright (C) 2016 12Sided Technology, LLC. - * Author: - * Phil Vachon - * - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "deflate.h" -#include "deflate_p.h" -#include "functable.h" -#include "trees_emit.h" - -extern const ct_data static_ltree[L_CODES+2]; -extern const ct_data static_dtree[D_CODES]; - -#define QUICK_START_BLOCK(s, last) { \ - zng_tr_emit_tree(s, STATIC_TREES, last); \ - s->block_open = 1 + (int)last; \ - s->block_start = (int)s->strstart; \ -} - -#define QUICK_END_BLOCK(s, last) { \ - if (s->block_open) { \ - zng_tr_emit_end_block(s, static_ltree, last); \ - s->block_open = 0; \ - s->block_start = (int)s->strstart; \ - flush_pending(s->strm); \ - if (s->strm->avail_out == 0) \ - return (last) ? finish_started : need_more; \ - } \ -} - -Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { - Pos hash_head; - int64_t dist; - unsigned match_len, last; - - - last = (flush == Z_FINISH) ? 1 : 0; - if (UNLIKELY(last && s->block_open != 2)) { - /* Emit end of previous block */ - QUICK_END_BLOCK(s, 0); - /* Emit start of last block */ - QUICK_START_BLOCK(s, last); - } else if (UNLIKELY(s->block_open == 0 && s->lookahead > 0)) { - /* Start new block only when we have lookahead data, so that if no - input data is given an empty block will not be written */ - QUICK_START_BLOCK(s, last); - } - - for (;;) { - if (UNLIKELY(s->pending + ((BIT_BUF_SIZE + 7) >> 3) >= s->pending_buf_size)) { - flush_pending(s->strm); - if (s->strm->avail_out == 0) { - return (last && s->strm->avail_in == 0) ? finish_started : need_more; - } - } - - if (UNLIKELY(s->lookahead < MIN_LOOKAHEAD)) { - fill_window(s); - if (UNLIKELY(s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH)) { - return need_more; - } - if (UNLIKELY(s->lookahead == 0)) - break; - - if (UNLIKELY(s->block_open == 0)) { - /* Start new block when we have lookahead data, so that if no - input data is given an empty block will not be written */ - QUICK_START_BLOCK(s, last); - } - } - - if (LIKELY(s->lookahead >= MIN_MATCH)) { - hash_head = functable.quick_insert_string(s, s->strstart); - dist = (int64_t)s->strstart - hash_head; - - if (dist <= MAX_DIST(s) && dist > 0) { - match_len = functable.compare258(s->window + s->strstart, s->window + hash_head); - - if (match_len >= MIN_MATCH) { - if (UNLIKELY(match_len > s->lookahead)) - match_len = s->lookahead; - - check_match(s, s->strstart, hash_head, match_len); - - zng_tr_emit_dist(s, static_ltree, static_dtree, match_len - MIN_MATCH, (uint32_t)dist); - s->lookahead -= match_len; - s->strstart += match_len; - continue; - } - } - } - - zng_tr_emit_lit(s, static_ltree, s->window[s->strstart]); - s->strstart++; - s->lookahead--; - } - - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; - if (UNLIKELY(last)) { - QUICK_END_BLOCK(s, 1); - return finish_done; - } - - QUICK_END_BLOCK(s, 0); - return block_done; -} diff --git a/libs/zlibng/deflate_slow.c b/libs/zlibng/deflate_slow.c deleted file mode 100644 index cac8a96299..0000000000 --- a/libs/zlibng/deflate_slow.c +++ /dev/null @@ -1,137 +0,0 @@ -/* deflate_slow.c -- compress data using the slow strategy of deflation algorithm - * - * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "deflate.h" -#include "deflate_p.h" -#include "functable.h" - -/* =========================================================================== - * Same as deflate_medium, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { - Pos hash_head; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ - int64_t dist; - uint32_t match_len; - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (UNLIKELY(s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH)) { - return need_more; - } - if (UNLIKELY(s->lookahead == 0)) - break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0; - if (LIKELY(s->lookahead >= MIN_MATCH)) { - hash_head = functable.quick_insert_string(s, s->strstart); - } - - /* Find the longest match, discarding those <= prev_length. - */ - s->prev_match = (Pos)s->match_start; - match_len = MIN_MATCH-1; - dist = (int64_t)s->strstart - hash_head; - - if (dist <= MAX_DIST(s) && dist > 0 && s->prev_length < s->max_lazy_match) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - match_len = functable.longest_match(s, hash_head); - /* longest_match() sets match_start */ - - if (match_len <= 5 && (s->strategy == Z_FILTERED)) { - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - match_len = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s->prev_length >= MIN_MATCH && match_len <= s->prev_length) { - unsigned int max_insert = s->strstart + s->lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - check_match(s, s->strstart-1, s->prev_match, s->prev_length); - - bflush = zng_tr_tally_dist(s, s->strstart -1 - s->prev_match, s->prev_length - MIN_MATCH); - - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s->lookahead -= s->prev_length-1; - - unsigned int mov_fwd = s->prev_length - 2; - if (max_insert > s->strstart) { - unsigned int insert_cnt = mov_fwd; - if (UNLIKELY(insert_cnt > max_insert - s->strstart)) - insert_cnt = max_insert - s->strstart; - - functable.insert_string(s, s->strstart + 1, insert_cnt); - } - s->prev_length = 0; - s->match_available = 0; - s->strstart += mov_fwd + 1; - - if (UNLIKELY(bflush)) - FLUSH_BLOCK(s, 0); - - } else if (s->match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - bflush = zng_tr_tally_lit(s, s->window[s->strstart-1]); - if (UNLIKELY(bflush)) - FLUSH_BLOCK_ONLY(s, 0); - s->prev_length = match_len; - s->strstart++; - s->lookahead--; - if (UNLIKELY(s->strm->avail_out == 0)) - return need_more; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s->prev_length = match_len; - s->match_available = 1; - s->strstart++; - s->lookahead--; - } - } - Assert(flush != Z_NO_FLUSH, "no flush?"); - if (UNLIKELY(s->match_available)) { - (void) zng_tr_tally_lit(s, s->window[s->strstart-1]); - s->match_available = 0; - } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; - if (UNLIKELY(flush == Z_FINISH)) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (UNLIKELY(s->sym_next)) - FLUSH_BLOCK(s, 0); - return block_done; -} diff --git a/libs/zlibng/doc/algorithm.txt b/libs/zlibng/doc/algorithm.txt deleted file mode 100644 index c97f495020..0000000000 --- a/libs/zlibng/doc/algorithm.txt +++ /dev/null @@ -1,209 +0,0 @@ -1. Compression algorithm (deflate) - -The deflation algorithm used by gzip (also zip and zlib) is a variation of -LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in -the input data. The second occurrence of a string is replaced by a -pointer to the previous string, in the form of a pair (distance, -length). Distances are limited to 32K bytes, and lengths are limited -to 258 bytes. When a string does not occur anywhere in the previous -32K bytes, it is emitted as a sequence of literal bytes. (In this -description, `string' must be taken as an arbitrary sequence of bytes, -and is not restricted to printable characters.) - -Literals or match lengths are compressed with one Huffman tree, and -match distances are compressed with another tree. The trees are stored -in a compact form at the start of each block. The blocks can have any -size (except that the compressed data for one block must fit in -available memory). A block is terminated when deflate() determines that -it would be useful to start another block with fresh trees. (This is -somewhat similar to the behavior of LZW-based _compress_.) - -Duplicated strings are found using a hash table. All input strings of -length 3 are inserted in the hash table. A hash index is computed for -the next 3 bytes. If the hash chain for this index is not empty, all -strings in the chain are compared with the current input string, and -the longest match is selected. - -The hash chains are searched starting with the most recent strings, to -favor small distances and thus take advantage of the Huffman encoding. -The hash chains are singly linked. There are no deletions from the -hash chains, the algorithm simply discards matches that are too old. - -To avoid a worst-case situation, very long hash chains are arbitrarily -truncated at a certain length, determined by a runtime option (level -parameter of deflateInit). So deflate() does not always find the longest -possible match but generally finds a match which is long enough. - -deflate() also defers the selection of matches with a lazy evaluation -mechanism. After a match of length N has been found, deflate() searches for -a longer match at the next input byte. If a longer match is found, the -previous match is truncated to a length of one (thus producing a single -literal byte) and the process of lazy evaluation begins again. Otherwise, -the original match is kept, and the next match search is attempted only N -steps later. - -The lazy match evaluation is also subject to a runtime parameter. If -the current match is long enough, deflate() reduces the search for a longer -match, thus speeding up the whole process. If compression ratio is more -important than speed, deflate() attempts a complete second search even if -the first match is already long enough. - -The lazy match evaluation is not performed for the fastest compression -modes (level parameter 1 to 3). For these fast modes, new strings -are inserted in the hash table only when no match was found, or -when the match is not too long. This degrades the compression ratio -but saves time since there are both fewer insertions and fewer searches. - - -2. Decompression algorithm (inflate) - -2.1 Introduction - -The key question is how to represent a Huffman code (or any prefix code) so -that you can decode fast. The most important characteristic is that shorter -codes are much more common than longer codes, so pay attention to decoding the -short codes fast, and let the long codes take longer to decode. - -inflate() sets up a first level table that covers some number of bits of -input less than the length of longest code. It gets that many bits from the -stream, and looks it up in the table. The table will tell if the next -code is that many bits or less and how many, and if it is, it will tell -the value, else it will point to the next level table for which inflate() -grabs more bits and tries to decode a longer code. - -How many bits to make the first lookup is a tradeoff between the time it -takes to decode and the time it takes to build the table. If building the -table took no time (and if you had infinite memory), then there would only -be a first level table to cover all the way to the longest code. However, -building the table ends up taking a lot longer for more bits since short -codes are replicated many times in such a table. What inflate() does is -simply to make the number of bits in the first table a variable, and then -to set that variable for the maximum speed. - -For inflate, which has 286 possible codes for the literal/length tree, the size -of the first table is nine bits. Also the distance trees have 30 possible -values, and the size of the first table is six bits. Note that for each of -those cases, the table ended up one bit longer than the ``average'' code -length, i.e. the code length of an approximately flat code which would be a -little more than eight bits for 286 symbols and a little less than five bits -for 30 symbols. - - -2.2 More details on the inflate table lookup - -Ok, you want to know what this cleverly obfuscated inflate tree actually -looks like. You are correct that it's not a Huffman tree. It is simply a -lookup table for the first, let's say, nine bits of a Huffman symbol. The -symbol could be as short as one bit or as long as 15 bits. If a particular -symbol is shorter than nine bits, then that symbol's translation is duplicated -in all those entries that start with that symbol's bits. For example, if the -symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a -symbol is nine bits long, it appears in the table once. - -If the symbol is longer than nine bits, then that entry in the table points -to another similar table for the remaining bits. Again, there are duplicated -entries as needed. The idea is that most of the time the symbol will be short -and there will only be one table look up. (That's whole idea behind data -compression in the first place.) For the less frequent long symbols, there -will be two lookups. If you had a compression method with really long -symbols, you could have as many levels of lookups as is efficient. For -inflate, two is enough. - -So a table entry either points to another table (in which case nine bits in -the above example are gobbled), or it contains the translation for the symbol -and the number of bits to gobble. Then you start again with the next -ungobbled bit. - -You may wonder: why not just have one lookup table for how ever many bits the -longest symbol is? The reason is that if you do that, you end up spending -more time filling in duplicate symbol entries than you do actually decoding. -At least for deflate's output that generates new trees every several 10's of -kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code -would take too long if you're only decoding several thousand symbols. At the -other extreme, you could make a new table for every bit in the code. In fact, -that's essentially a Huffman tree. But then you spend too much time -traversing the tree while decoding, even for short symbols. - -So the number of bits for the first lookup table is a trade of the time to -fill out the table vs. the time spent looking at the second level and above of -the table. - -Here is an example, scaled down: - -The code being decoded, with 10 symbols, from 1 to 6 bits long: - -A: 0 -B: 10 -C: 1100 -D: 11010 -E: 11011 -F: 11100 -G: 11101 -H: 11110 -I: 111110 -J: 111111 - -Let's make the first table three bits long (eight entries): - -000: A,1 -001: A,1 -010: A,1 -011: A,1 -100: B,2 -101: B,2 -110: -> table X (gobble 3 bits) -111: -> table Y (gobble 3 bits) - -Each entry is what the bits decode as and how many bits that is, i.e. how -many bits to gobble. Or the entry points to another table, with the number of -bits to gobble implicit in the size of the table. - -Table X is two bits long since the longest code starting with 110 is five bits -long: - -00: C,1 -01: C,1 -10: D,2 -11: E,2 - -Table Y is three bits long since the longest code starting with 111 is six -bits long: - -000: F,2 -001: F,2 -010: G,2 -011: G,2 -100: H,2 -101: H,2 -110: I,3 -111: J,3 - -So what we have here are three tables with a total of 20 entries that had to -be constructed. That's compared to 64 entries for a single table. Or -compared to 16 entries for a Huffman tree (six two entry tables and one four -entry table). Assuming that the code ideally represents the probability of -the symbols, it takes on the average 1.25 lookups per symbol. That's compared -to one lookup for the single table, or 1.66 lookups per symbol for the -Huffman tree. - -There, I think that gives you a picture of what's going on. For inflate, the -meaning of a particular symbol is often more than just a letter. It can be a -byte (a "literal"), or it can be either a length or a distance which -indicates a base value and a number of bits to fetch after the code that is -added to the base value. Or it might be the special end-of-block code. The -data structures created in inftrees.c try to encode all that information -compactly in the tables. - - -Jean-loup Gailly Mark Adler -jloup@gzip.org madler@alumni.caltech.edu - - -References: - -[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data -Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, -pp. 337-343. - -``DEFLATE Compressed Data Format Specification'' available in -http://tools.ietf.org/html/rfc1951 diff --git a/libs/zlibng/doc/rfc1950.txt b/libs/zlibng/doc/rfc1950.txt deleted file mode 100644 index ce6428a0f2..0000000000 --- a/libs/zlibng/doc/rfc1950.txt +++ /dev/null @@ -1,619 +0,0 @@ - - - - - - -Network Working Group P. Deutsch -Request for Comments: 1950 Aladdin Enterprises -Category: Informational J-L. Gailly - Info-ZIP - May 1996 - - - ZLIB Compressed Data Format Specification version 3.3 - -Status of This Memo - - This memo provides information for the Internet community. This memo - does not specify an Internet standard of any kind. Distribution of - this memo is unlimited. - -IESG Note: - - The IESG takes no position on the validity of any Intellectual - Property Rights statements contained in this document. - -Notices - - Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly - - Permission is granted to copy and distribute this document for any - purpose and without charge, including translations into other - languages and incorporation into compilations, provided that the - copyright notice and this notice are preserved, and that any - substantive changes or deletions from the original are clearly - marked. - - A pointer to the latest version of this and related documentation in - HTML format can be found at the URL - . - -Abstract - - This specification defines a lossless compressed data format. The - data can be produced or consumed, even for an arbitrarily long - sequentially presented input data stream, using only an a priori - bounded amount of intermediate storage. The format presently uses - the DEFLATE compression method but can be easily extended to use - other compression methods. It can be implemented readily in a manner - not covered by patents. This specification also defines the ADLER-32 - checksum (an extension and improvement of the Fletcher checksum), - used for detection of data corruption, and provides an algorithm for - computing it. - - - - -Deutsch & Gailly Informational [Page 1] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - -Table of Contents - - 1. Introduction ................................................... 2 - 1.1. Purpose ................................................... 2 - 1.2. Intended audience ......................................... 3 - 1.3. Scope ..................................................... 3 - 1.4. Compliance ................................................ 3 - 1.5. Definitions of terms and conventions used ................ 3 - 1.6. Changes from previous versions ............................ 3 - 2. Detailed specification ......................................... 3 - 2.1. Overall conventions ....................................... 3 - 2.2. Data format ............................................... 4 - 2.3. Compliance ................................................ 7 - 3. References ..................................................... 7 - 4. Source code .................................................... 8 - 5. Security Considerations ........................................ 8 - 6. Acknowledgements ............................................... 8 - 7. Authors' Addresses ............................................. 8 - 8. Appendix: Rationale ............................................ 9 - 9. Appendix: Sample code ..........................................10 - -1. Introduction - - 1.1. Purpose - - The purpose of this specification is to define a lossless - compressed data format that: - - * Is independent of CPU type, operating system, file system, - and character set, and hence can be used for interchange; - - * Can be produced or consumed, even for an arbitrarily long - sequentially presented input data stream, using only an a - priori bounded amount of intermediate storage, and hence can - be used in data communications or similar structures such as - Unix filters; - - * Can use a number of different compression methods; - - * Can be implemented readily in a manner not covered by - patents, and hence can be practiced freely. - - The data format defined by this specification does not attempt to - allow random access to compressed data. - - - - - - - -Deutsch & Gailly Informational [Page 2] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - 1.2. Intended audience - - This specification is intended for use by implementors of software - to compress data into zlib format and/or decompress data from zlib - format. - - The text of the specification assumes a basic background in - programming at the level of bits and other primitive data - representations. - - 1.3. Scope - - The specification specifies a compressed data format that can be - used for in-memory compression of a sequence of arbitrary bytes. - - 1.4. Compliance - - Unless otherwise indicated below, a compliant decompressor must be - able to accept and decompress any data set that conforms to all - the specifications presented here; a compliant compressor must - produce data sets that conform to all the specifications presented - here. - - 1.5. Definitions of terms and conventions used - - byte: 8 bits stored or transmitted as a unit (same as an octet). - (For this specification, a byte is exactly 8 bits, even on - machines which store a character on a number of bits different - from 8.) See below, for the numbering of bits within a byte. - - 1.6. Changes from previous versions - - Version 3.1 was the first public release of this specification. - In version 3.2, some terminology was changed and the Adler-32 - sample code was rewritten for clarity. In version 3.3, the - support for a preset dictionary was introduced, and the - specification was converted to RFC style. - -2. Detailed specification - - 2.1. Overall conventions - - In the diagrams below, a box like this: - - +---+ - | | <-- the vertical bars might be missing - +---+ - - - - -Deutsch & Gailly Informational [Page 3] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - represents one byte; a box like this: - - +==============+ - | | - +==============+ - - represents a variable number of bytes. - - Bytes stored within a computer do not have a "bit order", since - they are always treated as a unit. However, a byte considered as - an integer between 0 and 255 does have a most- and least- - significant bit, and since we write numbers with the most- - significant digit on the left, we also write bytes with the most- - significant bit on the left. In the diagrams below, we number the - bits of a byte so that bit 0 is the least-significant bit, i.e., - the bits are numbered: - - +--------+ - |76543210| - +--------+ - - Within a computer, a number may occupy multiple bytes. All - multi-byte numbers in the format described here are stored with - the MOST-significant byte first (at the lower memory address). - For example, the decimal number 520 is stored as: - - 0 1 - +--------+--------+ - |00000010|00001000| - +--------+--------+ - ^ ^ - | | - | + less significant byte = 8 - + more significant byte = 2 x 256 - - 2.2. Data format - - A zlib stream has the following structure: - - 0 1 - +---+---+ - |CMF|FLG| (more-->) - +---+---+ - - - - - - - - -Deutsch & Gailly Informational [Page 4] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - (if FLG.FDICT set) - - 0 1 2 3 - +---+---+---+---+ - | DICTID | (more-->) - +---+---+---+---+ - - +=====================+---+---+---+---+ - |...compressed data...| ADLER32 | - +=====================+---+---+---+---+ - - Any data which may appear after ADLER32 are not part of the zlib - stream. - - CMF (Compression Method and flags) - This byte is divided into a 4-bit compression method and a 4- - bit information field depending on the compression method. - - bits 0 to 3 CM Compression method - bits 4 to 7 CINFO Compression info - - CM (Compression method) - This identifies the compression method used in the file. CM = 8 - denotes the "deflate" compression method with a window size up - to 32K. This is the method used by gzip and PNG (see - references [1] and [2] in Chapter 3, below, for the reference - documents). CM = 15 is reserved. It might be used in a future - version of this specification to indicate the presence of an - extra field before the compressed data. - - CINFO (Compression info) - For CM = 8, CINFO is the base-2 logarithm of the LZ77 window - size, minus eight (CINFO=7 indicates a 32K window size). Values - of CINFO above 7 are not allowed in this version of the - specification. CINFO is not defined in this specification for - CM not equal to 8. - - FLG (FLaGs) - This flag byte is divided as follows: - - bits 0 to 4 FCHECK (check bits for CMF and FLG) - bit 5 FDICT (preset dictionary) - bits 6 to 7 FLEVEL (compression level) - - The FCHECK value must be such that CMF and FLG, when viewed as - a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG), - is a multiple of 31. - - - - -Deutsch & Gailly Informational [Page 5] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - FDICT (Preset dictionary) - If FDICT is set, a DICT dictionary identifier is present - immediately after the FLG byte. The dictionary is a sequence of - bytes which are initially fed to the compressor without - producing any compressed output. DICT is the Adler-32 checksum - of this sequence of bytes (see the definition of ADLER32 - below). The decompressor can use this identifier to determine - which dictionary has been used by the compressor. - - FLEVEL (Compression level) - These flags are available for use by specific compression - methods. The "deflate" method (CM = 8) sets these flags as - follows: - - 0 - compressor used fastest algorithm - 1 - compressor used fast algorithm - 2 - compressor used default algorithm - 3 - compressor used maximum compression, slowest algorithm - - The information in FLEVEL is not needed for decompression; it - is there to indicate if recompression might be worthwhile. - - compressed data - For compression method 8, the compressed data is stored in the - deflate compressed data format as described in the document - "DEFLATE Compressed Data Format Specification" by L. Peter - Deutsch. (See reference [3] in Chapter 3, below) - - Other compressed data formats are not specified in this version - of the zlib specification. - - ADLER32 (Adler-32 checksum) - This contains a checksum value of the uncompressed data - (excluding any dictionary data) computed according to Adler-32 - algorithm. This algorithm is a 32-bit extension and improvement - of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 - standard. See references [4] and [5] in Chapter 3, below) - - Adler-32 is composed of two sums accumulated per byte: s1 is - the sum of all bytes, s2 is the sum of all s1 values. Both sums - are done modulo 65521. s1 is initialized to 1, s2 to zero. The - Adler-32 checksum is stored as s2*65536 + s1 in most- - significant-byte first (network) order. - - - - - - - - -Deutsch & Gailly Informational [Page 6] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - 2.3. Compliance - - A compliant compressor must produce streams with correct CMF, FLG - and ADLER32, but need not support preset dictionaries. When the - zlib data format is used as part of another standard data format, - the compressor may use only preset dictionaries that are specified - by this other data format. If this other format does not use the - preset dictionary feature, the compressor must not set the FDICT - flag. - - A compliant decompressor must check CMF, FLG, and ADLER32, and - provide an error indication if any of these have incorrect values. - A compliant decompressor must give an error indication if CM is - not one of the values defined in this specification (only the - value 8 is permitted in this version), since another value could - indicate the presence of new features that would cause subsequent - data to be interpreted incorrectly. A compliant decompressor must - give an error indication if FDICT is set and DICTID is not the - identifier of a known preset dictionary. A decompressor may - ignore FLEVEL and still be compliant. When the zlib data format - is being used as a part of another standard format, a compliant - decompressor must support all the preset dictionaries specified by - the other format. When the other format does not use the preset - dictionary feature, a compliant decompressor must reject any - stream in which the FDICT flag is set. - -3. References - - [1] Deutsch, L.P.,"GZIP Compressed Data Format Specification", - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ - - [2] Thomas Boutell, "PNG (Portable Network Graphics) specification", - available in ftp://ftp.uu.net/graphics/png/documents/ - - [3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ - - [4] Fletcher, J. G., "An Arithmetic Checksum for Serial - Transmissions," IEEE Transactions on Communications, Vol. COM-30, - No. 1, January 1982, pp. 247-252. - - [5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms," - November, 1993, pp. 144, 145. (Available from - gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073. - - - - - - - -Deutsch & Gailly Informational [Page 7] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - -4. Source code - - Source code for a C language implementation of a "zlib" compliant - library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/. - -5. Security Considerations - - A decoder that fails to check the ADLER32 checksum value may be - subject to undetected data corruption. - -6. Acknowledgements - - Trademarks cited in this document are the property of their - respective owners. - - Jean-Loup Gailly and Mark Adler designed the zlib format and wrote - the related software described in this specification. Glenn - Randers-Pehrson converted this document to RFC and HTML format. - -7. Authors' Addresses - - L. Peter Deutsch - Aladdin Enterprises - 203 Santa Margarita Ave. - Menlo Park, CA 94025 - - Phone: (415) 322-0103 (AM only) - FAX: (415) 322-1734 - EMail: - - - Jean-Loup Gailly - - EMail: - - Questions about the technical content of this specification can be - sent by email to - - Jean-Loup Gailly and - Mark Adler - - Editorial comments on this specification can be sent by email to - - L. Peter Deutsch and - Glenn Randers-Pehrson - - - - - - -Deutsch & Gailly Informational [Page 8] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - -8. Appendix: Rationale - - 8.1. Preset dictionaries - - A preset dictionary is specially useful to compress short input - sequences. The compressor can take advantage of the dictionary - context to encode the input in a more compact manner. The - decompressor can be initialized with the appropriate context by - virtually decompressing a compressed version of the dictionary - without producing any output. However for certain compression - algorithms such as the deflate algorithm this operation can be - achieved without actually performing any decompression. - - The compressor and the decompressor must use exactly the same - dictionary. The dictionary may be fixed or may be chosen among a - certain number of predefined dictionaries, according to the kind - of input data. The decompressor can determine which dictionary has - been chosen by the compressor by checking the dictionary - identifier. This document does not specify the contents of - predefined dictionaries, since the optimal dictionaries are - application specific. Standard data formats using this feature of - the zlib specification must precisely define the allowed - dictionaries. - - 8.2. The Adler-32 algorithm - - The Adler-32 algorithm is much faster than the CRC32 algorithm yet - still provides an extremely low probability of undetected errors. - - The modulo on unsigned long accumulators can be delayed for 5552 - bytes, so the modulo operation time is negligible. If the bytes - are a, b, c, the second sum is 3a + 2b + c + 3, and so is position - and order sensitive, unlike the first sum, which is just a - checksum. That 65521 is prime is important to avoid a possible - large class of two-byte errors that leave the check unchanged. - (The Fletcher checksum uses 255, which is not prime and which also - makes the Fletcher check insensitive to single byte changes 0 <-> - 255.) - - The sum s1 is initialized to 1 instead of zero to make the length - of the sequence part of s2, so that the length does not have to be - checked separately. (Any sequence of zeroes has a Fletcher - checksum of zero.) - - - - - - - - -Deutsch & Gailly Informational [Page 9] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - -9. Appendix: Sample code - - The following C code computes the Adler-32 checksum of a data buffer. - It is written for clarity, not for speed. The sample code is in the - ANSI C programming language. Non C users may find it easier to read - with these hints: - - & Bitwise AND operator. - >> Bitwise right shift operator. When applied to an - unsigned quantity, as here, right shift inserts zero bit(s) - at the left. - << Bitwise left shift operator. Left shift inserts zero - bit(s) at the right. - ++ "n++" increments the variable n. - % modulo operator: a % b is the remainder of a divided by b. - - #define BASE 65521 /* largest prime smaller than 65536 */ - - /* - Update a running Adler-32 checksum with the bytes buf[0..len-1] - and return the updated checksum. The Adler-32 checksum should be - initialized to 1. - - Usage example: - - unsigned long adler = 1L; - - while (read_buffer(buffer, length) != EOF) { - adler = update_adler32(adler, buffer, length); - } - if (adler != original_adler) error(); - */ - unsigned long update_adler32(unsigned long adler, - unsigned char *buf, int len) - { - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int n; - - for (n = 0; n < len; n++) { - s1 = (s1 + buf[n]) % BASE; - s2 = (s2 + s1) % BASE; - } - return (s2 << 16) + s1; - } - - /* Return the adler32 of the bytes buf[0..len-1] */ - - - - -Deutsch & Gailly Informational [Page 10] - -RFC 1950 ZLIB Compressed Data Format Specification May 1996 - - - unsigned long adler32(unsigned char *buf, int len) - { - return update_adler32(1L, buf, len); - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Deutsch & Gailly Informational [Page 11] - diff --git a/libs/zlibng/doc/rfc1951.txt b/libs/zlibng/doc/rfc1951.txt deleted file mode 100644 index 403c8c722f..0000000000 --- a/libs/zlibng/doc/rfc1951.txt +++ /dev/null @@ -1,955 +0,0 @@ - - - - - - -Network Working Group P. Deutsch -Request for Comments: 1951 Aladdin Enterprises -Category: Informational May 1996 - - - DEFLATE Compressed Data Format Specification version 1.3 - -Status of This Memo - - This memo provides information for the Internet community. This memo - does not specify an Internet standard of any kind. Distribution of - this memo is unlimited. - -IESG Note: - - The IESG takes no position on the validity of any Intellectual - Property Rights statements contained in this document. - -Notices - - Copyright (c) 1996 L. Peter Deutsch - - Permission is granted to copy and distribute this document for any - purpose and without charge, including translations into other - languages and incorporation into compilations, provided that the - copyright notice and this notice are preserved, and that any - substantive changes or deletions from the original are clearly - marked. - - A pointer to the latest version of this and related documentation in - HTML format can be found at the URL - . - -Abstract - - This specification defines a lossless compressed data format that - compresses data using a combination of the LZ77 algorithm and Huffman - coding, with efficiency comparable to the best currently available - general-purpose compression methods. The data can be produced or - consumed, even for an arbitrarily long sequentially presented input - data stream, using only an a priori bounded amount of intermediate - storage. The format can be implemented readily in a manner not - covered by patents. - - - - - - - - -Deutsch Informational [Page 1] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - -Table of Contents - - 1. Introduction ................................................... 2 - 1.1. Purpose ................................................... 2 - 1.2. Intended audience ......................................... 3 - 1.3. Scope ..................................................... 3 - 1.4. Compliance ................................................ 3 - 1.5. Definitions of terms and conventions used ................ 3 - 1.6. Changes from previous versions ............................ 4 - 2. Compressed representation overview ............................. 4 - 3. Detailed specification ......................................... 5 - 3.1. Overall conventions ....................................... 5 - 3.1.1. Packing into bytes .................................. 5 - 3.2. Compressed block format ................................... 6 - 3.2.1. Synopsis of prefix and Huffman coding ............... 6 - 3.2.2. Use of Huffman coding in the "deflate" format ....... 7 - 3.2.3. Details of block format ............................. 9 - 3.2.4. Non-compressed blocks (BTYPE=00) ................... 11 - 3.2.5. Compressed blocks (length and distance codes) ...... 11 - 3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12 - 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13 - 3.3. Compliance ............................................... 14 - 4. Compression algorithm details ................................. 14 - 5. References .................................................... 16 - 6. Security Considerations ....................................... 16 - 7. Source code ................................................... 16 - 8. Acknowledgements .............................................. 16 - 9. Author's Address .............................................. 17 - -1. Introduction - - 1.1. Purpose - - The purpose of this specification is to define a lossless - compressed data format that: - * Is independent of CPU type, operating system, file system, - and character set, and hence can be used for interchange; - * Can be produced or consumed, even for an arbitrarily long - sequentially presented input data stream, using only an a - priori bounded amount of intermediate storage, and hence - can be used in data communications or similar structures - such as Unix filters; - * Compresses data with efficiency comparable to the best - currently available general-purpose compression methods, - and in particular considerably better than the "compress" - program; - * Can be implemented readily in a manner not covered by - patents, and hence can be practiced freely; - - - -Deutsch Informational [Page 2] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - * Is compatible with the file format produced by the current - widely used gzip utility, in that conforming decompressors - will be able to read data produced by the existing gzip - compressor. - - The data format defined by this specification does not attempt to: - - * Allow random access to compressed data; - * Compress specialized data (e.g., raster graphics) as well - as the best currently available specialized algorithms. - - A simple counting argument shows that no lossless compression - algorithm can compress every possible input data set. For the - format defined here, the worst case expansion is 5 bytes per 32K- - byte block, i.e., a size increase of 0.015% for large data sets. - English text usually compresses by a factor of 2.5 to 3; - executable files usually compress somewhat less; graphical data - such as raster images may compress much more. - - 1.2. Intended audience - - This specification is intended for use by implementors of software - to compress data into "deflate" format and/or decompress data from - "deflate" format. - - The text of the specification assumes a basic background in - programming at the level of bits and other primitive data - representations. Familiarity with the technique of Huffman coding - is helpful but not required. - - 1.3. Scope - - The specification specifies a method for representing a sequence - of bytes as a (usually shorter) sequence of bits, and a method for - packing the latter bit sequence into bytes. - - 1.4. Compliance - - Unless otherwise indicated below, a compliant decompressor must be - able to accept and decompress any data set that conforms to all - the specifications presented here; a compliant compressor must - produce data sets that conform to all the specifications presented - here. - - 1.5. Definitions of terms and conventions used - - Byte: 8 bits stored or transmitted as a unit (same as an octet). - For this specification, a byte is exactly 8 bits, even on machines - - - -Deutsch Informational [Page 3] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - which store a character on a number of bits different from eight. - See below, for the numbering of bits within a byte. - - String: a sequence of arbitrary bytes. - - 1.6. Changes from previous versions - - There have been no technical changes to the deflate format since - version 1.1 of this specification. In version 1.2, some - terminology was changed. Version 1.3 is a conversion of the - specification to RFC style. - -2. Compressed representation overview - - A compressed data set consists of a series of blocks, corresponding - to successive blocks of input data. The block sizes are arbitrary, - except that non-compressible blocks are limited to 65,535 bytes. - - Each block is compressed using a combination of the LZ77 algorithm - and Huffman coding. The Huffman trees for each block are independent - of those for previous or subsequent blocks; the LZ77 algorithm may - use a reference to a duplicated string occurring in a previous block, - up to 32K input bytes before. - - Each block consists of two parts: a pair of Huffman code trees that - describe the representation of the compressed data part, and a - compressed data part. (The Huffman trees themselves are compressed - using Huffman encoding.) The compressed data consists of a series of - elements of two types: literal bytes (of strings that have not been - detected as duplicated within the previous 32K input bytes), and - pointers to duplicated strings, where a pointer is represented as a - pair . The representation used in the - "deflate" format limits distances to 32K bytes and lengths to 258 - bytes, but does not limit the size of a block, except for - uncompressible blocks, which are limited as noted above. - - Each type of value (literals, distances, and lengths) in the - compressed data is represented using a Huffman code, using one code - tree for literals and lengths and a separate code tree for distances. - The code trees for each block appear in a compact form just before - the compressed data for that block. - - - - - - - - - - -Deutsch Informational [Page 4] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - -3. Detailed specification - - 3.1. Overall conventions In the diagrams below, a box like this: - - +---+ - | | <-- the vertical bars might be missing - +---+ - - represents one byte; a box like this: - - +==============+ - | | - +==============+ - - represents a variable number of bytes. - - Bytes stored within a computer do not have a "bit order", since - they are always treated as a unit. However, a byte considered as - an integer between 0 and 255 does have a most- and least- - significant bit, and since we write numbers with the most- - significant digit on the left, we also write bytes with the most- - significant bit on the left. In the diagrams below, we number the - bits of a byte so that bit 0 is the least-significant bit, i.e., - the bits are numbered: - - +--------+ - |76543210| - +--------+ - - Within a computer, a number may occupy multiple bytes. All - multi-byte numbers in the format described here are stored with - the least-significant byte first (at the lower memory address). - For example, the decimal number 520 is stored as: - - 0 1 - +--------+--------+ - |00001000|00000010| - +--------+--------+ - ^ ^ - | | - | + more significant byte = 2 x 256 - + less significant byte = 8 - - 3.1.1. Packing into bytes - - This document does not address the issue of the order in which - bits of a byte are transmitted on a bit-sequential medium, - since the final data format described here is byte- rather than - - - -Deutsch Informational [Page 5] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - bit-oriented. However, we describe the compressed block format - in below, as a sequence of data elements of various bit - lengths, not a sequence of bytes. We must therefore specify - how to pack these data elements into bytes to form the final - compressed byte sequence: - - * Data elements are packed into bytes in order of - increasing bit number within the byte, i.e., starting - with the least-significant bit of the byte. - * Data elements other than Huffman codes are packed - starting with the least-significant bit of the data - element. - * Huffman codes are packed starting with the most- - significant bit of the code. - - In other words, if one were to print out the compressed data as - a sequence of bytes, starting with the first byte at the - *right* margin and proceeding to the *left*, with the most- - significant bit of each byte on the left as usual, one would be - able to parse the result from right to left, with fixed-width - elements in the correct MSB-to-LSB order and Huffman codes in - bit-reversed order (i.e., with the first bit of the code in the - relative LSB position). - - 3.2. Compressed block format - - 3.2.1. Synopsis of prefix and Huffman coding - - Prefix coding represents symbols from an a priori known - alphabet by bit sequences (codes), one code for each symbol, in - a manner such that different symbols may be represented by bit - sequences of different lengths, but a parser can always parse - an encoded string unambiguously symbol-by-symbol. - - We define a prefix code in terms of a binary tree in which the - two edges descending from each non-leaf node are labeled 0 and - 1 and in which the leaf nodes correspond one-for-one with (are - labeled with) the symbols of the alphabet; then the code for a - symbol is the sequence of 0's and 1's on the edges leading from - the root to the leaf labeled with that symbol. For example: - - - - - - - - - - - -Deutsch Informational [Page 6] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - /\ Symbol Code - 0 1 ------ ---- - / \ A 00 - /\ B B 1 - 0 1 C 011 - / \ D 010 - A /\ - 0 1 - / \ - D C - - A parser can decode the next symbol from an encoded input - stream by walking down the tree from the root, at each step - choosing the edge corresponding to the next input bit. - - Given an alphabet with known symbol frequencies, the Huffman - algorithm allows the construction of an optimal prefix code - (one which represents strings with those symbol frequencies - using the fewest bits of any possible prefix codes for that - alphabet). Such a code is called a Huffman code. (See - reference [1] in Chapter 5, references for additional - information on Huffman codes.) - - Note that in the "deflate" format, the Huffman codes for the - various alphabets must not exceed certain maximum code lengths. - This constraint complicates the algorithm for computing code - lengths from symbol frequencies. Again, see Chapter 5, - references for details. - - 3.2.2. Use of Huffman coding in the "deflate" format - - The Huffman codes used for each alphabet in the "deflate" - format have two additional rules: - - * All codes of a given bit length have lexicographically - consecutive values, in the same order as the symbols - they represent; - - * Shorter codes lexicographically precede longer codes. - - - - - - - - - - - - -Deutsch Informational [Page 7] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - We could recode the example above to follow this rule as - follows, assuming that the order of the alphabet is ABCD: - - Symbol Code - ------ ---- - A 10 - B 0 - C 110 - D 111 - - I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are - lexicographically consecutive. - - Given this rule, we can define the Huffman code for an alphabet - just by giving the bit lengths of the codes for each symbol of - the alphabet in order; this is sufficient to determine the - actual codes. In our example, the code is completely defined - by the sequence of bit lengths (2, 1, 3, 3). The following - algorithm generates the codes as integers, intended to be read - from most- to least-significant bit. The code lengths are - initially in tree[I].Len; the codes are produced in - tree[I].Code. - - 1) Count the number of codes for each code length. Let - bl_count[N] be the number of codes of length N, N >= 1. - - 2) Find the numerical value of the smallest code for each - code length: - - code = 0; - bl_count[0] = 0; - for (bits = 1; bits <= MAX_BITS; bits++) { - code = (code + bl_count[bits-1]) << 1; - next_code[bits] = code; - } - - 3) Assign numerical values to all codes, using consecutive - values for all codes of the same length with the base - values determined at step 2. Codes that are never used - (which have a bit length of zero) must not be assigned a - value. - - for (n = 0; n <= max_code; n++) { - len = tree[n].Len; - if (len != 0) { - tree[n].Code = next_code[len]; - next_code[len]++; - } - - - -Deutsch Informational [Page 8] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - } - - Example: - - Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3, - 3, 2, 4, 4). After step 1, we have: - - N bl_count[N] - - ----------- - 2 1 - 3 5 - 4 2 - - Step 2 computes the following next_code values: - - N next_code[N] - - ------------ - 1 0 - 2 0 - 3 2 - 4 14 - - Step 3 produces the following code values: - - Symbol Length Code - ------ ------ ---- - A 3 010 - B 3 011 - C 3 100 - D 3 101 - E 3 110 - F 2 00 - G 4 1110 - H 4 1111 - - 3.2.3. Details of block format - - Each block of compressed data begins with 3 header bits - containing the following data: - - first bit BFINAL - next 2 bits BTYPE - - Note that the header bits do not necessarily begin on a byte - boundary, since a block does not necessarily occupy an integral - number of bytes. - - - - - -Deutsch Informational [Page 9] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - BFINAL is set if and only if this is the last block of the data - set. - - BTYPE specifies how the data are compressed, as follows: - - 00 - no compression - 01 - compressed with fixed Huffman codes - 10 - compressed with dynamic Huffman codes - 11 - reserved (error) - - The only difference between the two compressed cases is how the - Huffman codes for the literal/length and distance alphabets are - defined. - - In all cases, the decoding algorithm for the actual data is as - follows: - - do - read block header from input stream. - if stored with no compression - skip any remaining bits in current partially - processed byte - read LEN and NLEN (see next section) - copy LEN bytes of data to output - otherwise - if compressed with dynamic Huffman codes - read representation of code trees (see - subsection below) - loop (until end of block code recognized) - decode literal/length value from input stream - if value < 256 - copy value (literal byte) to output stream - otherwise - if value = end of block (256) - break from loop - otherwise (value = 257..285) - decode distance from input stream - - move backwards distance bytes in the output - stream, and copy length bytes from this - position to the output stream. - end loop - while not last block - - Note that a duplicated string reference may refer to a string - in a previous block; i.e., the backward distance may cross one - or more block boundaries. However a distance cannot refer past - the beginning of the output stream. (An application using a - - - -Deutsch Informational [Page 10] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - preset dictionary might discard part of the output stream; a - distance can refer to that part of the output stream anyway) - Note also that the referenced string may overlap the current - position; for example, if the last 2 bytes decoded have values - X and Y, a string reference with - adds X,Y,X,Y,X to the output stream. - - We now specify each compression method in turn. - - 3.2.4. Non-compressed blocks (BTYPE=00) - - Any bits of input up to the next byte boundary are ignored. - The rest of the block consists of the following information: - - 0 1 2 3 4... - +---+---+---+---+================================+ - | LEN | NLEN |... LEN bytes of literal data...| - +---+---+---+---+================================+ - - LEN is the number of data bytes in the block. NLEN is the - one's complement of LEN. - - 3.2.5. Compressed blocks (length and distance codes) - - As noted above, encoded data blocks in the "deflate" format - consist of sequences of symbols drawn from three conceptually - distinct alphabets: either literal bytes, from the alphabet of - byte values (0..255), or pairs, - where the length is drawn from (3..258) and the distance is - drawn from (1..32,768). In fact, the literal and length - alphabets are merged into a single alphabet (0..285), where - values 0..255 represent literal bytes, the value 256 indicates - end-of-block, and values 257..285 represent length codes - (possibly in conjunction with extra bits following the symbol - code) as follows: - - - - - - - - - - - - - - - - -Deutsch Informational [Page 11] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - Extra Extra Extra - Code Bits Length(s) Code Bits Lengths Code Bits Length(s) - ---- ---- ------ ---- ---- ------- ---- ---- ------- - 257 0 3 267 1 15,16 277 4 67-82 - 258 0 4 268 1 17,18 278 4 83-98 - 259 0 5 269 2 19-22 279 4 99-114 - 260 0 6 270 2 23-26 280 4 115-130 - 261 0 7 271 2 27-30 281 5 131-162 - 262 0 8 272 2 31-34 282 5 163-194 - 263 0 9 273 3 35-42 283 5 195-226 - 264 0 10 274 3 43-50 284 5 227-257 - 265 1 11,12 275 3 51-58 285 0 258 - 266 1 13,14 276 3 59-66 - - The extra bits should be interpreted as a machine integer - stored with the most-significant bit first, e.g., bits 1110 - represent the value 14. - - Extra Extra Extra - Code Bits Dist Code Bits Dist Code Bits Distance - ---- ---- ---- ---- ---- ------ ---- ---- -------- - 0 0 1 10 4 33-48 20 9 1025-1536 - 1 0 2 11 4 49-64 21 9 1537-2048 - 2 0 3 12 5 65-96 22 10 2049-3072 - 3 0 4 13 5 97-128 23 10 3073-4096 - 4 1 5,6 14 6 129-192 24 11 4097-6144 - 5 1 7,8 15 6 193-256 25 11 6145-8192 - 6 2 9-12 16 7 257-384 26 12 8193-12288 - 7 2 13-16 17 7 385-512 27 12 12289-16384 - 8 3 17-24 18 8 513-768 28 13 16385-24576 - 9 3 25-32 19 8 769-1024 29 13 24577-32768 - - 3.2.6. Compression with fixed Huffman codes (BTYPE=01) - - The Huffman codes for the two alphabets are fixed, and are not - represented explicitly in the data. The Huffman code lengths - for the literal/length alphabet are: - - Lit Value Bits Codes - --------- ---- ----- - 0 - 143 8 00110000 through - 10111111 - 144 - 255 9 110010000 through - 111111111 - 256 - 279 7 0000000 through - 0010111 - 280 - 287 8 11000000 through - 11000111 - - - -Deutsch Informational [Page 12] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - The code lengths are sufficient to generate the actual codes, - as described above; we show the codes in the table for added - clarity. Literal/length values 286-287 will never actually - occur in the compressed data, but participate in the code - construction. - - Distance codes 0-31 are represented by (fixed-length) 5-bit - codes, with possible additional bits as shown in the table - shown in Paragraph 3.2.5, above. Note that distance codes 30- - 31 will never actually occur in the compressed data. - - 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) - - The Huffman codes for the two alphabets appear in the block - immediately after the header bits and before the actual - compressed data, first the literal/length code and then the - distance code. Each code is defined by a sequence of code - lengths, as discussed in Paragraph 3.2.2, above. For even - greater compactness, the code length sequences themselves are - compressed using a Huffman code. The alphabet for code lengths - is as follows: - - 0 - 15: Represent code lengths of 0 - 15 - 16: Copy the previous code length 3 - 6 times. - The next 2 bits indicate repeat length - (0 = 3, ... , 3 = 6) - Example: Codes 8, 16 (+2 bits 11), - 16 (+2 bits 10) will expand to - 12 code lengths of 8 (1 + 6 + 5) - 17: Repeat a code length of 0 for 3 - 10 times. - (3 bits of length) - 18: Repeat a code length of 0 for 11 - 138 times - (7 bits of length) - - A code length of 0 indicates that the corresponding symbol in - the literal/length or distance alphabet will not occur in the - block, and should not participate in the Huffman code - construction algorithm given earlier. If only one distance - code is used, it is encoded using one bit, not zero bits; in - this case there is a single code length of one, with one unused - code. One distance code of zero bits means that there are no - distance codes used at all (the data is all literals). - - We can now define the format of the block: - - 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286) - 5 Bits: HDIST, # of Distance codes - 1 (1 - 32) - 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19) - - - -Deutsch Informational [Page 13] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - (HCLEN + 4) x 3 bits: code lengths for the code length - alphabet given just above, in the order: 16, 17, 18, - 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 - - These code lengths are interpreted as 3-bit integers - (0-7); as above, a code length of 0 means the - corresponding symbol (literal/length or distance code - length) is not used. - - HLIT + 257 code lengths for the literal/length alphabet, - encoded using the code length Huffman code - - HDIST + 1 code lengths for the distance alphabet, - encoded using the code length Huffman code - - The actual compressed data of the block, - encoded using the literal/length and distance Huffman - codes - - The literal/length symbol 256 (end of data), - encoded using the literal/length Huffman code - - The code length repeat codes can cross from HLIT + 257 to the - HDIST + 1 code lengths. In other words, all code lengths form - a single sequence of HLIT + HDIST + 258 values. - - 3.3. Compliance - - A compressor may limit further the ranges of values specified in - the previous section and still be compliant; for example, it may - limit the range of backward pointers to some value smaller than - 32K. Similarly, a compressor may limit the size of blocks so that - a compressible block fits in memory. - - A compliant decompressor must accept the full range of possible - values defined in the previous section, and must accept blocks of - arbitrary size. - -4. Compression algorithm details - - While it is the intent of this document to define the "deflate" - compressed data format without reference to any particular - compression algorithm, the format is related to the compressed - formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below); - since many variations of LZ77 are patented, it is strongly - recommended that the implementor of a compressor follow the general - algorithm presented here, which is known not to be patented per se. - The material in this section is not part of the definition of the - - - -Deutsch Informational [Page 14] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - - specification per se, and a compressor need not follow it in order to - be compliant. - - The compressor terminates a block when it determines that starting a - new block with fresh trees would be useful, or when the block size - fills up the compressor's block buffer. - - The compressor uses a chained hash table to find duplicated strings, - using a hash function that operates on 3-byte sequences. At any - given point during compression, let XYZ be the next 3 input bytes to - be examined (not necessarily all different, of course). First, the - compressor examines the hash chain for XYZ. If the chain is empty, - the compressor simply writes out X as a literal byte and advances one - byte in the input. If the hash chain is not empty, indicating that - the sequence XYZ (or, if we are unlucky, some other 3 bytes with the - same hash function value) has occurred recently, the compressor - compares all strings on the XYZ hash chain with the actual input data - sequence starting at the current point, and selects the longest - match. - - The compressor searches the hash chains starting with the most recent - strings, to favor small distances and thus take advantage of the - Huffman encoding. The hash chains are singly linked. There are no - deletions from the hash chains; the algorithm simply discards matches - that are too old. To avoid a worst-case situation, very long hash - chains are arbitrarily truncated at a certain length, determined by a - run-time parameter. - - To improve overall compression, the compressor optionally defers the - selection of matches ("lazy matching"): after a match of length N has - been found, the compressor searches for a longer match starting at - the next input byte. If it finds a longer match, it truncates the - previous match to a length of one (thus producing a single literal - byte) and then emits the longer match. Otherwise, it emits the - original match, and, as described above, advances N bytes before - continuing. - - Run-time parameters also control this "lazy match" procedure. If - compression ratio is most important, the compressor attempts a - complete second search regardless of the length of the first match. - In the normal case, if the current match is "long enough", the - compressor reduces the search for a longer match, thus speeding up - the process. If speed is most important, the compressor inserts new - strings in the hash table only when no match was found, or when the - match is not "too long". This degrades the compression ratio but - saves time since there are both fewer insertions and fewer searches. - - - - - -Deutsch Informational [Page 15] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - -5. References - - [1] Huffman, D. A., "A Method for the Construction of Minimum - Redundancy Codes", Proceedings of the Institute of Radio - Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101. - - [2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data - Compression", IEEE Transactions on Information Theory, Vol. 23, - No. 3, pp. 337-343. - - [3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources, - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ - - [4] Gailly, J.-L., and Adler, M., GZIP documentation and sources, - available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/ - - [5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix - encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169. - - [6] Hirschberg and Lelewer, "Efficient decoding of prefix codes," - Comm. ACM, 33,4, April 1990, pp. 449-459. - -6. Security Considerations - - Any data compression method involves the reduction of redundancy in - the data. Consequently, any corruption of the data is likely to have - severe effects and be difficult to correct. Uncompressed text, on - the other hand, will probably still be readable despite the presence - of some corrupted bytes. - - It is recommended that systems using this data format provide some - means of validating the integrity of the compressed data. See - reference [3], for example. - -7. Source code - - Source code for a C language implementation of a "deflate" compliant - compressor and decompressor is available within the zlib package at - ftp://ftp.uu.net/pub/archiving/zip/zlib/. - -8. Acknowledgements - - Trademarks cited in this document are the property of their - respective owners. - - Phil Katz designed the deflate format. Jean-Loup Gailly and Mark - Adler wrote the related software described in this specification. - Glenn Randers-Pehrson converted this document to RFC and HTML format. - - - -Deutsch Informational [Page 16] - -RFC 1951 DEFLATE Compressed Data Format Specification May 1996 - - -9. Author's Address - - L. Peter Deutsch - Aladdin Enterprises - 203 Santa Margarita Ave. - Menlo Park, CA 94025 - - Phone: (415) 322-0103 (AM only) - FAX: (415) 322-1734 - EMail: - - Questions about the technical content of this specification can be - sent by email to: - - Jean-Loup Gailly and - Mark Adler - - Editorial comments on this specification can be sent by email to: - - L. Peter Deutsch and - Glenn Randers-Pehrson - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Deutsch Informational [Page 17] - diff --git a/libs/zlibng/doc/rfc1952.txt b/libs/zlibng/doc/rfc1952.txt deleted file mode 100644 index a8e51b4567..0000000000 --- a/libs/zlibng/doc/rfc1952.txt +++ /dev/null @@ -1,675 +0,0 @@ - - - - - - -Network Working Group P. Deutsch -Request for Comments: 1952 Aladdin Enterprises -Category: Informational May 1996 - - - GZIP file format specification version 4.3 - -Status of This Memo - - This memo provides information for the Internet community. This memo - does not specify an Internet standard of any kind. Distribution of - this memo is unlimited. - -IESG Note: - - The IESG takes no position on the validity of any Intellectual - Property Rights statements contained in this document. - -Notices - - Copyright (c) 1996 L. Peter Deutsch - - Permission is granted to copy and distribute this document for any - purpose and without charge, including translations into other - languages and incorporation into compilations, provided that the - copyright notice and this notice are preserved, and that any - substantive changes or deletions from the original are clearly - marked. - - A pointer to the latest version of this and related documentation in - HTML format can be found at the URL - . - -Abstract - - This specification defines a lossless compressed data format that is - compatible with the widely used GZIP utility. The format includes a - cyclic redundancy check value for detecting data corruption. The - format presently uses the DEFLATE method of compression but can be - easily extended to use other compression methods. The format can be - implemented readily in a manner not covered by patents. - - - - - - - - - - -Deutsch Informational [Page 1] - -RFC 1952 GZIP File Format Specification May 1996 - - -Table of Contents - - 1. Introduction ................................................... 2 - 1.1. Purpose ................................................... 2 - 1.2. Intended audience ......................................... 3 - 1.3. Scope ..................................................... 3 - 1.4. Compliance ................................................ 3 - 1.5. Definitions of terms and conventions used ................. 3 - 1.6. Changes from previous versions ............................ 3 - 2. Detailed specification ......................................... 4 - 2.1. Overall conventions ....................................... 4 - 2.2. File format ............................................... 5 - 2.3. Member format ............................................. 5 - 2.3.1. Member header and trailer ........................... 6 - 2.3.1.1. Extra field ................................... 8 - 2.3.1.2. Compliance .................................... 9 - 3. References .................................................. 9 - 4. Security Considerations .................................... 10 - 5. Acknowledgements ........................................... 10 - 6. Author's Address ........................................... 10 - 7. Appendix: Jean-Loup Gailly's gzip utility .................. 11 - 8. Appendix: Sample CRC Code .................................. 11 - -1. Introduction - - 1.1. Purpose - - The purpose of this specification is to define a lossless - compressed data format that: - - * Is independent of CPU type, operating system, file system, - and character set, and hence can be used for interchange; - * Can compress or decompress a data stream (as opposed to a - randomly accessible file) to produce another data stream, - using only an a priori bounded amount of intermediate - storage, and hence can be used in data communications or - similar structures such as Unix filters; - * Compresses data with efficiency comparable to the best - currently available general-purpose compression methods, - and in particular considerably better than the "compress" - program; - * Can be implemented readily in a manner not covered by - patents, and hence can be practiced freely; - * Is compatible with the file format produced by the current - widely used gzip utility, in that conforming decompressors - will be able to read data produced by the existing gzip - compressor. - - - - -Deutsch Informational [Page 2] - -RFC 1952 GZIP File Format Specification May 1996 - - - The data format defined by this specification does not attempt to: - - * Provide random access to compressed data; - * Compress specialized data (e.g., raster graphics) as well as - the best currently available specialized algorithms. - - 1.2. Intended audience - - This specification is intended for use by implementors of software - to compress data into gzip format and/or decompress data from gzip - format. - - The text of the specification assumes a basic background in - programming at the level of bits and other primitive data - representations. - - 1.3. Scope - - The specification specifies a compression method and a file format - (the latter assuming only that a file can store a sequence of - arbitrary bytes). It does not specify any particular interface to - a file system or anything about character sets or encodings - (except for file names and comments, which are optional). - - 1.4. Compliance - - Unless otherwise indicated below, a compliant decompressor must be - able to accept and decompress any file that conforms to all the - specifications presented here; a compliant compressor must produce - files that conform to all the specifications presented here. The - material in the appendices is not part of the specification per se - and is not relevant to compliance. - - 1.5. Definitions of terms and conventions used - - byte: 8 bits stored or transmitted as a unit (same as an octet). - (For this specification, a byte is exactly 8 bits, even on - machines which store a character on a number of bits different - from 8.) See below for the numbering of bits within a byte. - - 1.6. Changes from previous versions - - There have been no technical changes to the gzip format since - version 4.1 of this specification. In version 4.2, some - terminology was changed, and the sample CRC code was rewritten for - clarity and to eliminate the requirement for the caller to do pre- - and post-conditioning. Version 4.3 is a conversion of the - specification to RFC style. - - - -Deutsch Informational [Page 3] - -RFC 1952 GZIP File Format Specification May 1996 - - -2. Detailed specification - - 2.1. Overall conventions - - In the diagrams below, a box like this: - - +---+ - | | <-- the vertical bars might be missing - +---+ - - represents one byte; a box like this: - - +==============+ - | | - +==============+ - - represents a variable number of bytes. - - Bytes stored within a computer do not have a "bit order", since - they are always treated as a unit. However, a byte considered as - an integer between 0 and 255 does have a most- and least- - significant bit, and since we write numbers with the most- - significant digit on the left, we also write bytes with the most- - significant bit on the left. In the diagrams below, we number the - bits of a byte so that bit 0 is the least-significant bit, i.e., - the bits are numbered: - - +--------+ - |76543210| - +--------+ - - This document does not address the issue of the order in which - bits of a byte are transmitted on a bit-sequential medium, since - the data format described here is byte- rather than bit-oriented. - - Within a computer, a number may occupy multiple bytes. All - multi-byte numbers in the format described here are stored with - the least-significant byte first (at the lower memory address). - For example, the decimal number 520 is stored as: - - 0 1 - +--------+--------+ - |00001000|00000010| - +--------+--------+ - ^ ^ - | | - | + more significant byte = 2 x 256 - + less significant byte = 8 - - - -Deutsch Informational [Page 4] - -RFC 1952 GZIP File Format Specification May 1996 - - - 2.2. File format - - A gzip file consists of a series of "members" (compressed data - sets). The format of each member is specified in the following - section. The members simply appear one after another in the file, - with no additional information before, between, or after them. - - 2.3. Member format - - Each member has the following structure: - - +---+---+---+---+---+---+---+---+---+---+ - |ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->) - +---+---+---+---+---+---+---+---+---+---+ - - (if FLG.FEXTRA set) - - +---+---+=================================+ - | XLEN |...XLEN bytes of "extra field"...| (more-->) - +---+---+=================================+ - - (if FLG.FNAME set) - - +=========================================+ - |...original file name, zero-terminated...| (more-->) - +=========================================+ - - (if FLG.FCOMMENT set) - - +===================================+ - |...file comment, zero-terminated...| (more-->) - +===================================+ - - (if FLG.FHCRC set) - - +---+---+ - | CRC16 | - +---+---+ - - +=======================+ - |...compressed blocks...| (more-->) - +=======================+ - - 0 1 2 3 4 5 6 7 - +---+---+---+---+---+---+---+---+ - | CRC32 | ISIZE | - +---+---+---+---+---+---+---+---+ - - - - -Deutsch Informational [Page 5] - -RFC 1952 GZIP File Format Specification May 1996 - - - 2.3.1. Member header and trailer - - ID1 (IDentification 1) - ID2 (IDentification 2) - These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139 - (0x8b, \213), to identify the file as being in gzip format. - - CM (Compression Method) - This identifies the compression method used in the file. CM - = 0-7 are reserved. CM = 8 denotes the "deflate" - compression method, which is the one customarily used by - gzip and which is documented elsewhere. - - FLG (FLaGs) - This flag byte is divided into individual bits as follows: - - bit 0 FTEXT - bit 1 FHCRC - bit 2 FEXTRA - bit 3 FNAME - bit 4 FCOMMENT - bit 5 reserved - bit 6 reserved - bit 7 reserved - - If FTEXT is set, the file is probably ASCII text. This is - an optional indication, which the compressor may set by - checking a small amount of the input data to see whether any - non-ASCII characters are present. In case of doubt, FTEXT - is cleared, indicating binary data. For systems which have - different file formats for ascii text and binary data, the - decompressor can use FTEXT to choose the appropriate format. - We deliberately do not specify the algorithm used to set - this bit, since a compressor always has the option of - leaving it cleared and a decompressor always has the option - of ignoring it and letting some other program handle issues - of data conversion. - - If FHCRC is set, a CRC16 for the gzip header is present, - immediately before the compressed data. The CRC16 consists - of the two least significant bytes of the CRC32 for all - bytes of the gzip header up to and not including the CRC16. - [The FHCRC bit was never set by versions of gzip up to - 1.2.4, even though it was documented with a different - meaning in gzip 1.2.4.] - - If FEXTRA is set, optional extra fields are present, as - described in a following section. - - - -Deutsch Informational [Page 6] - -RFC 1952 GZIP File Format Specification May 1996 - - - If FNAME is set, an original file name is present, - terminated by a zero byte. The name must consist of ISO - 8859-1 (LATIN-1) characters; on operating systems using - EBCDIC or any other character set for file names, the name - must be translated to the ISO LATIN-1 character set. This - is the original name of the file being compressed, with any - directory components removed, and, if the file being - compressed is on a file system with case insensitive names, - forced to lower case. There is no original file name if the - data was compressed from a source other than a named file; - for example, if the source was stdin on a Unix system, there - is no file name. - - If FCOMMENT is set, a zero-terminated file comment is - present. This comment is not interpreted; it is only - intended for human consumption. The comment must consist of - ISO 8859-1 (LATIN-1) characters. Line breaks should be - denoted by a single line feed character (10 decimal). - - Reserved FLG bits must be zero. - - MTIME (Modification TIME) - This gives the most recent modification time of the original - file being compressed. The time is in Unix format, i.e., - seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this - may cause problems for MS-DOS and other systems that use - local rather than Universal time.) If the compressed data - did not come from a file, MTIME is set to the time at which - compression started. MTIME = 0 means no time stamp is - available. - - XFL (eXtra FLags) - These flags are available for use by specific compression - methods. The "deflate" method (CM = 8) sets these flags as - follows: - - XFL = 2 - compressor used maximum compression, - slowest algorithm - XFL = 4 - compressor used fastest algorithm - - OS (Operating System) - This identifies the type of file system on which compression - took place. This may be useful in determining end-of-line - convention for text files. The currently defined values are - as follows: - - - - - - -Deutsch Informational [Page 7] - -RFC 1952 GZIP File Format Specification May 1996 - - - 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32) - 1 - Amiga - 2 - VMS (or OpenVMS) - 3 - Unix - 4 - VM/CMS - 5 - Atari TOS - 6 - HPFS filesystem (OS/2, NT) - 7 - Macintosh - 8 - Z-System - 9 - CP/M - 10 - TOPS-20 - 11 - NTFS filesystem (NT) - 12 - QDOS - 13 - Acorn RISCOS - 255 - unknown - - XLEN (eXtra LENgth) - If FLG.FEXTRA is set, this gives the length of the optional - extra field. See below for details. - - CRC32 (CRC-32) - This contains a Cyclic Redundancy Check value of the - uncompressed data computed according to CRC-32 algorithm - used in the ISO 3309 standard and in section 8.1.1.6.2 of - ITU-T recommendation V.42. (See http://www.iso.ch for - ordering ISO documents. See gopher://info.itu.ch for an - online version of ITU-T V.42.) - - ISIZE (Input SIZE) - This contains the size of the original (uncompressed) input - data modulo 2^32. - - 2.3.1.1. Extra field - - If the FLG.FEXTRA bit is set, an "extra field" is present in - the header, with total length XLEN bytes. It consists of a - series of subfields, each of the form: - - +---+---+---+---+==================================+ - |SI1|SI2| LEN |... LEN bytes of subfield data ...| - +---+---+---+---+==================================+ - - SI1 and SI2 provide a subfield ID, typically two ASCII letters - with some mnemonic value. Jean-Loup Gailly - is maintaining a registry of subfield - IDs; please send him any subfield ID you wish to use. Subfield - IDs with SI2 = 0 are reserved for future use. The following - IDs are currently defined: - - - -Deutsch Informational [Page 8] - -RFC 1952 GZIP File Format Specification May 1996 - - - SI1 SI2 Data - ---------- ---------- ---- - 0x41 ('A') 0x70 ('P') Apollo file type information - - LEN gives the length of the subfield data, excluding the 4 - initial bytes. - - 2.3.1.2. Compliance - - A compliant compressor must produce files with correct ID1, - ID2, CM, CRC32, and ISIZE, but may set all the other fields in - the fixed-length part of the header to default values (255 for - OS, 0 for all others). The compressor must set all reserved - bits to zero. - - A compliant decompressor must check ID1, ID2, and CM, and - provide an error indication if any of these have incorrect - values. It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC - at least so it can skip over the optional fields if they are - present. It need not examine any other part of the header or - trailer; in particular, a decompressor may ignore FTEXT and OS - and always produce binary output, and still be compliant. A - compliant decompressor must give an error indication if any - reserved bit is non-zero, since such a bit could indicate the - presence of a new field that would cause subsequent data to be - interpreted incorrectly. - -3. References - - [1] "Information Processing - 8-bit single-byte coded graphic - character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987). - The ISO 8859-1 (Latin-1) character set is a superset of 7-bit - ASCII. Files defining this character set are available as - iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/ - - [2] ISO 3309 - - [3] ITU-T recommendation V.42 - - [4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", - available in ftp://ftp.uu.net/pub/archiving/zip/doc/ - - [5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in - ftp://prep.ai.mit.edu/pub/gnu/ - - [6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table - Look-Up", Communications of the ACM, 31(8), pp.1008-1013. - - - - -Deutsch Informational [Page 9] - -RFC 1952 GZIP File Format Specification May 1996 - - - [7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal, - pp.118-133. - - [8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt, - describing the CRC concept. - -4. Security Considerations - - Any data compression method involves the reduction of redundancy in - the data. Consequently, any corruption of the data is likely to have - severe effects and be difficult to correct. Uncompressed text, on - the other hand, will probably still be readable despite the presence - of some corrupted bytes. - - It is recommended that systems using this data format provide some - means of validating the integrity of the compressed data, such as by - setting and checking the CRC-32 check value. - -5. Acknowledgements - - Trademarks cited in this document are the property of their - respective owners. - - Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler, - the related software described in this specification. Glenn - Randers-Pehrson converted this document to RFC and HTML format. - -6. Author's Address - - L. Peter Deutsch - Aladdin Enterprises - 203 Santa Margarita Ave. - Menlo Park, CA 94025 - - Phone: (415) 322-0103 (AM only) - FAX: (415) 322-1734 - EMail: - - Questions about the technical content of this specification can be - sent by email to: - - Jean-Loup Gailly and - Mark Adler - - Editorial comments on this specification can be sent by email to: - - L. Peter Deutsch and - Glenn Randers-Pehrson - - - -Deutsch Informational [Page 10] - -RFC 1952 GZIP File Format Specification May 1996 - - -7. Appendix: Jean-Loup Gailly's gzip utility - - The most widely used implementation of gzip compression, and the - original documentation on which this specification is based, were - created by Jean-Loup Gailly . Since this - implementation is a de facto standard, we mention some more of its - features here. Again, the material in this section is not part of - the specification per se, and implementations need not follow it to - be compliant. - - When compressing or decompressing a file, gzip preserves the - protection, ownership, and modification time attributes on the local - file system, since there is no provision for representing protection - attributes in the gzip file format itself. Since the file format - includes a modification time, the gzip decompressor provides a - command line switch that assigns the modification time from the file, - rather than the local modification time of the compressed input, to - the decompressed output. - -8. Appendix: Sample CRC Code - - The following sample code represents a practical implementation of - the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42 - for a formal specification.) - - The sample code is in the ANSI C programming language. Non C users - may find it easier to read with these hints: - - & Bitwise AND operator. - ^ Bitwise exclusive-OR operator. - >> Bitwise right shift operator. When applied to an - unsigned quantity, as here, right shift inserts zero - bit(s) at the left. - ! Logical NOT operator. - ++ "n++" increments the variable n. - 0xNNN 0x introduces a hexadecimal (base 16) constant. - Suffix L indicates a long value (at least 32 bits). - - /* Table of CRCs of all 8-bit messages. */ - unsigned long crc_table[256]; - - /* Flag: has the table been computed? Initially false. */ - int crc_table_computed = 0; - - /* Make the table for a fast CRC. */ - void make_crc_table(void) - { - unsigned long c; - - - -Deutsch Informational [Page 11] - -RFC 1952 GZIP File Format Specification May 1996 - - - int n, k; - for (n = 0; n < 256; n++) { - c = (unsigned long) n; - for (k = 0; k < 8; k++) { - if (c & 1) { - c = 0xedb88320L ^ (c >> 1); - } else { - c = c >> 1; - } - } - crc_table[n] = c; - } - crc_table_computed = 1; - } - - /* - Update a running crc with the bytes buf[0..len-1] and return - the updated crc. The crc should be initialized to zero. Pre- and - post-conditioning (one's complement) is performed within this - function so it shouldn't be done by the caller. Usage example: - - unsigned long crc = 0L; - - while (read_buffer(buffer, length) != EOF) { - crc = update_crc(crc, buffer, length); - } - if (crc != original_crc) error(); - */ - unsigned long update_crc(unsigned long crc, - unsigned char *buf, int len) - { - unsigned long c = crc ^ 0xffffffffL; - int n; - - if (!crc_table_computed) - make_crc_table(); - for (n = 0; n < len; n++) { - c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); - } - return c ^ 0xffffffffL; - } - - /* Return the CRC of the bytes buf[0..len-1]. */ - unsigned long crc(unsigned char *buf, int len) - { - return update_crc(0L, buf, len); - } - - - - -Deutsch Informational [Page 12] - diff --git a/libs/zlibng/doc/txtvsbin.txt b/libs/zlibng/doc/txtvsbin.txt deleted file mode 100644 index 3d0f0634f7..0000000000 --- a/libs/zlibng/doc/txtvsbin.txt +++ /dev/null @@ -1,107 +0,0 @@ -A Fast Method for Identifying Plain Text Files -============================================== - - -Introduction ------------- - -Given a file coming from an unknown source, it is sometimes desirable -to find out whether the format of that file is plain text. Although -this may appear like a simple task, a fully accurate detection of the -file type requires heavy-duty semantic analysis on the file contents. -It is, however, possible to obtain satisfactory results by employing -various heuristics. - -Previous versions of PKZip and other zip-compatible compression tools -were using a crude detection scheme: if more than 80% (4/5) of the bytes -found in a certain buffer are within the range [7..127], the file is -labeled as plain text, otherwise it is labeled as binary. A prominent -limitation of this scheme is the restriction to Latin-based alphabets. -Other alphabets, like Greek, Cyrillic or Asian, make extensive use of -the bytes within the range [128..255], and texts using these alphabets -are most often misidentified by this scheme; in other words, the rate -of false negatives is sometimes too high, which means that the recall -is low. Another weakness of this scheme is a reduced precision, due to -the false positives that may occur when binary files containing large -amounts of textual characters are misidentified as plain text. - -In this article we propose a new, simple detection scheme that features -a much increased precision and a near-100% recall. This scheme is -designed to work on ASCII, Unicode and other ASCII-derived alphabets, -and it handles single-byte encodings (ISO-8859, MacRoman, KOI8, etc.) -and variable-sized encodings (ISO-2022, UTF-8, etc.). Wider encodings -(UCS-2/UTF-16 and UCS-4/UTF-32) are not handled, however. - - -The Algorithm -------------- - -The algorithm works by dividing the set of bytecodes [0..255] into three -categories: -- The white list of textual bytecodes: - 9 (TAB), 10 (LF), 13 (CR), 32 (SPACE) to 255. -- The gray list of tolerated bytecodes: - 7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC). -- The black list of undesired, non-textual bytecodes: - 0 (NUL) to 6, 14 to 31. - -If a file contains at least one byte that belongs to the white list and -no byte that belongs to the black list, then the file is categorized as -plain text; otherwise, it is categorized as binary. (The boundary case, -when the file is empty, automatically falls into the latter category.) - - -Rationale ---------- - -The idea behind this algorithm relies on two observations. - -The first observation is that, although the full range of 7-bit codes -[0..127] is properly specified by the ASCII standard, most control -characters in the range [0..31] are not used in practice. The only -widely-used, almost universally-portable control codes are 9 (TAB), -10 (LF) and 13 (CR). There are a few more control codes that are -recognized on a reduced range of platforms and text viewers/editors: -7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB) and 27 (ESC); but these -codes are rarely (if ever) used alone, without being accompanied by -some printable text. Even the newer, portable text formats such as -XML avoid using control characters outside the list mentioned here. - -The second observation is that most of the binary files tend to contain -control characters, especially 0 (NUL). Even though the older text -detection schemes observe the presence of non-ASCII codes from the range -[128..255], the precision rarely has to suffer if this upper range is -labeled as textual, because the files that are genuinely binary tend to -contain both control characters and codes from the upper range. On the -other hand, the upper range needs to be labeled as textual, because it -is used by virtually all ASCII extensions. In particular, this range is -used for encoding non-Latin scripts. - -Since there is no counting involved, other than simply observing the -presence or the absence of some byte values, the algorithm produces -consistent results, regardless what alphabet encoding is being used. -(If counting were involved, it could be possible to obtain different -results on a text encoded, say, using ISO-8859-16 versus UTF-8.) - -There is an extra category of plain text files that are "polluted" with -one or more black-listed codes, either by mistake or by peculiar design -considerations. In such cases, a scheme that tolerates a small fraction -of black-listed codes would provide an increased recall (i.e. more true -positives). This, however, incurs a reduced precision overall, since -false positives are more likely to appear in binary files that contain -large chunks of textual data. Furthermore, "polluted" plain text should -be regarded as binary by general-purpose text detection schemes, because -general-purpose text processing algorithms might not be applicable. -Under this premise, it is safe to say that our detection method provides -a near-100% recall. - -Experiments have been run on many files coming from various platforms -and applications. We tried plain text files, system logs, source code, -formatted office documents, compiled object code, etc. The results -confirm the optimistic assumptions about the capabilities of this -algorithm. - - --- -Cosmin Truta -Last updated: 2006-May-28 diff --git a/libs/zlibng/fallback_builtins.h b/libs/zlibng/fallback_builtins.h deleted file mode 100644 index 314ad3267f..0000000000 --- a/libs/zlibng/fallback_builtins.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef X86_BUILTIN_CTZ_H -#define X86_BUILTIN_CTZ_H - -#if defined(_MSC_VER) && !defined(__clang__) -#if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM64) - -#include -#ifdef X86_FEATURES -# include "arch/x86/x86.h" -#endif - -/* This is not a general purpose replacement for __builtin_ctz. The function expects that value is != 0 - * Because of that assumption trailing_zero is not initialized and the return value of _BitScanForward is not checked - */ -static __forceinline unsigned long __builtin_ctz(uint32_t value) { -#ifdef X86_FEATURES - if (x86_cpu_has_tzcnt) - return _tzcnt_u32(value); -#endif - unsigned long trailing_zero; - _BitScanForward(&trailing_zero, value); - return trailing_zero; -} -#define HAVE_BUILTIN_CTZ - -#ifdef _M_AMD64 -/* This is not a general purpose replacement for __builtin_ctzll. The function expects that value is != 0 - * Because of that assumption trailing_zero is not initialized and the return value of _BitScanForward64 is not checked - */ -static __forceinline unsigned long long __builtin_ctzll(uint64_t value) { -#ifdef X86_FEATURES - if (x86_cpu_has_tzcnt) - return _tzcnt_u64(value); -#endif - unsigned long trailing_zero; - _BitScanForward64(&trailing_zero, value); - return trailing_zero; -} -#define HAVE_BUILTIN_CTZLL -#endif - -#endif -#endif -#endif diff --git a/libs/zlibng/functable.c b/libs/zlibng/functable.c deleted file mode 100644 index acae446419..0000000000 --- a/libs/zlibng/functable.c +++ /dev/null @@ -1,466 +0,0 @@ -/* functable.c -- Choose relevant optimized functions at runtime - * Copyright (C) 2017 Hans Kristian Rosbach - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "zendian.h" -#include "deflate.h" -#include "deflate_p.h" - -#include "functable.h" - -#ifdef X86_FEATURES -# include "fallback_builtins.h" -#endif - -/* insert_string */ -extern void insert_string_c(deflate_state *const s, const uint32_t str, uint32_t count); -#ifdef X86_SSE42_CRC_HASH -extern void insert_string_sse4(deflate_state *const s, const uint32_t str, uint32_t count); -#elif defined(ARM_ACLE_CRC_HASH) -extern void insert_string_acle(deflate_state *const s, const uint32_t str, uint32_t count); -#endif - -/* quick_insert_string */ -extern Pos quick_insert_string_c(deflate_state *const s, const uint32_t str); -#ifdef X86_SSE42_CRC_HASH -extern Pos quick_insert_string_sse4(deflate_state *const s, const uint32_t str); -#elif defined(ARM_ACLE_CRC_HASH) -extern Pos quick_insert_string_acle(deflate_state *const s, const uint32_t str); -#endif - -/* slide_hash */ -#ifdef X86_SSE2 -void slide_hash_sse2(deflate_state *s); -#elif defined(ARM_NEON_SLIDEHASH) -void slide_hash_neon(deflate_state *s); -#elif defined(POWER8_VSX_SLIDEHASH) -void slide_hash_power8(deflate_state *s); -#endif -#ifdef X86_AVX2 -void slide_hash_avx2(deflate_state *s); -#endif - -/* adler32 */ -extern uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t len); -#ifdef ARM_NEON_ADLER32 -extern uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len); -#endif -#ifdef X86_SSSE3_ADLER32 -extern uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len); -#endif -#ifdef X86_AVX2_ADLER32 -extern uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len); -#endif -#ifdef POWER8_VSX_ADLER32 -extern uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, size_t len); -#endif - -/* memory chunking */ -extern uint32_t chunksize_c(void); -extern uint8_t* chunkcopy_c(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_c(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); -extern uint8_t* chunkunroll_c(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_c(uint8_t *out, unsigned dist, unsigned len); -extern uint8_t* chunkmemset_safe_c(uint8_t *out, unsigned dist, unsigned len, unsigned left); -#ifdef X86_SSE2_CHUNKSET -extern uint32_t chunksize_sse2(void); -extern uint8_t* chunkcopy_sse2(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_sse2(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); -extern uint8_t* chunkunroll_sse2(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_sse2(uint8_t *out, unsigned dist, unsigned len); -extern uint8_t* chunkmemset_safe_sse2(uint8_t *out, unsigned dist, unsigned len, unsigned left); -#endif -#ifdef X86_AVX_CHUNKSET -extern uint32_t chunksize_avx(void); -extern uint8_t* chunkcopy_avx(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_avx(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); -extern uint8_t* chunkunroll_avx(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_avx(uint8_t *out, unsigned dist, unsigned len); -extern uint8_t* chunkmemset_safe_avx(uint8_t *out, unsigned dist, unsigned len, unsigned left); -#endif -#ifdef ARM_NEON_CHUNKSET -extern uint32_t chunksize_neon(void); -extern uint8_t* chunkcopy_neon(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_neon(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); -extern uint8_t* chunkunroll_neon(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_neon(uint8_t *out, unsigned dist, unsigned len); -extern uint8_t* chunkmemset_safe_neon(uint8_t *out, unsigned dist, unsigned len, unsigned left); -#endif - -/* CRC32 */ -Z_INTERNAL uint32_t crc32_generic(uint32_t, const unsigned char *, uint64_t); - -#ifdef ARM_ACLE_CRC_HASH -extern uint32_t crc32_acle(uint32_t, const unsigned char *, uint64_t); -#endif - -#if BYTE_ORDER == LITTLE_ENDIAN -extern uint32_t crc32_little(uint32_t, const unsigned char *, uint64_t); -#elif BYTE_ORDER == BIG_ENDIAN -extern uint32_t crc32_big(uint32_t, const unsigned char *, uint64_t); -#endif - -/* compare258 */ -extern uint32_t compare258_c(const unsigned char *src0, const unsigned char *src1); -#ifdef UNALIGNED_OK -extern uint32_t compare258_unaligned_16(const unsigned char *src0, const unsigned char *src1); -extern uint32_t compare258_unaligned_32(const unsigned char *src0, const unsigned char *src1); -#ifdef UNALIGNED64_OK -extern uint32_t compare258_unaligned_64(const unsigned char *src0, const unsigned char *src1); -#endif -#ifdef X86_SSE42_CMP_STR -extern uint32_t compare258_unaligned_sse4(const unsigned char *src0, const unsigned char *src1); -#endif -#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t compare258_unaligned_avx2(const unsigned char *src0, const unsigned char *src1); -#endif -#endif - -/* longest_match */ -extern uint32_t longest_match_c(deflate_state *const s, Pos cur_match); -#ifdef UNALIGNED_OK -extern uint32_t longest_match_unaligned_16(deflate_state *const s, Pos cur_match); -extern uint32_t longest_match_unaligned_32(deflate_state *const s, Pos cur_match); -#ifdef UNALIGNED64_OK -extern uint32_t longest_match_unaligned_64(deflate_state *const s, Pos cur_match); -#endif -#ifdef X86_SSE42_CMP_STR -extern uint32_t longest_match_unaligned_sse4(deflate_state *const s, Pos cur_match); -#endif -#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t longest_match_unaligned_avx2(deflate_state *const s, Pos cur_match); -#endif -#endif - -Z_INTERNAL Z_TLS struct functable_s functable; - -Z_INTERNAL void cpu_check_features(void) -{ - static int features_checked = 0; - if (features_checked) - return; -#if defined(X86_FEATURES) - x86_check_features(); -#elif defined(ARM_FEATURES) - arm_check_features(); -#elif defined(POWER_FEATURES) - power_check_features(); -#endif - features_checked = 1; -} - -/* stub functions */ -Z_INTERNAL void insert_string_stub(deflate_state *const s, const uint32_t str, uint32_t count) { - // Initialize default - - functable.insert_string = &insert_string_c; - cpu_check_features(); - -#ifdef X86_SSE42_CRC_HASH - if (x86_cpu_has_sse42) - functable.insert_string = &insert_string_sse4; -#elif defined(ARM_ACLE_CRC_HASH) - if (arm_cpu_has_crc32) - functable.insert_string = &insert_string_acle; -#endif - - functable.insert_string(s, str, count); -} - -Z_INTERNAL Pos quick_insert_string_stub(deflate_state *const s, const uint32_t str) { - functable.quick_insert_string = &quick_insert_string_c; - -#ifdef X86_SSE42_CRC_HASH - if (x86_cpu_has_sse42) - functable.quick_insert_string = &quick_insert_string_sse4; -#elif defined(ARM_ACLE_CRC_HASH) - if (arm_cpu_has_crc32) - functable.quick_insert_string = &quick_insert_string_acle; -#endif - - return functable.quick_insert_string(s, str); -} - -Z_INTERNAL void slide_hash_stub(deflate_state *s) { - - functable.slide_hash = &slide_hash_c; - cpu_check_features(); - -#ifdef X86_SSE2 -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - functable.slide_hash = &slide_hash_sse2; -#elif defined(ARM_NEON_SLIDEHASH) -# ifndef ARM_NOCHECK_NEON - if (arm_cpu_has_neon) -# endif - functable.slide_hash = &slide_hash_neon; -#endif -#ifdef X86_AVX2 - if (x86_cpu_has_avx2) - functable.slide_hash = &slide_hash_avx2; -#endif -#ifdef POWER8_VSX_SLIDEHASH - if (power_cpu_has_arch_2_07) - functable.slide_hash = &slide_hash_power8; -#endif - - functable.slide_hash(s); -} - -Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_t len) { - // Initialize default - functable.adler32 = &adler32_c; - cpu_check_features(); - -#ifdef ARM_NEON_ADLER32 -# ifndef ARM_NOCHECK_NEON - if (arm_cpu_has_neon) -# endif - functable.adler32 = &adler32_neon; -#endif -#ifdef X86_SSSE3_ADLER32 - if (x86_cpu_has_ssse3) - functable.adler32 = &adler32_ssse3; -#endif -#ifdef X86_AVX2_ADLER32 - if (x86_cpu_has_avx2) - functable.adler32 = &adler32_avx2; -#endif -#ifdef POWER8_VSX_ADLER32 - if (power_cpu_has_arch_2_07) - functable.adler32 = &adler32_power8; -#endif - - return functable.adler32(adler, buf, len); -} - -Z_INTERNAL uint32_t chunksize_stub(void) { - // Initialize default - functable.chunksize = &chunksize_c; - -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - functable.chunksize = &chunksize_sse2; -#endif -#ifdef X86_AVX_CHUNKSET - if (x86_cpu_has_avx2) - functable.chunksize = &chunksize_avx; -#endif -#ifdef ARM_NEON_CHUNKSET - if (arm_cpu_has_neon) - functable.chunksize = &chunksize_neon; -#endif - - return functable.chunksize(); -} - -Z_INTERNAL uint8_t* chunkcopy_stub(uint8_t *out, uint8_t const *from, unsigned len) { - // Initialize default - functable.chunkcopy = &chunkcopy_c; - -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - functable.chunkcopy = &chunkcopy_sse2; -#endif -#ifdef X86_AVX_CHUNKSET - if (x86_cpu_has_avx2) - functable.chunkcopy = &chunkcopy_avx; -#endif -#ifdef ARM_NEON_CHUNKSET - if (arm_cpu_has_neon) - functable.chunkcopy = &chunkcopy_neon; -#endif - - return functable.chunkcopy(out, from, len); -} - -Z_INTERNAL uint8_t* chunkcopy_safe_stub(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe) { - // Initialize default - functable.chunkcopy_safe = &chunkcopy_safe_c; - -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - functable.chunkcopy_safe = &chunkcopy_safe_sse2; -#endif -#ifdef X86_AVX_CHUNKSET - if (x86_cpu_has_avx2) - functable.chunkcopy_safe = &chunkcopy_safe_avx; -#endif -#ifdef ARM_NEON_CHUNKSET - if (arm_cpu_has_neon) - functable.chunkcopy_safe = &chunkcopy_safe_neon; -#endif - - return functable.chunkcopy_safe(out, from, len, safe); -} - -Z_INTERNAL uint8_t* chunkunroll_stub(uint8_t *out, unsigned *dist, unsigned *len) { - // Initialize default - functable.chunkunroll = &chunkunroll_c; - -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - functable.chunkunroll = &chunkunroll_sse2; -#endif -#ifdef X86_AVX_CHUNKSET - if (x86_cpu_has_avx2) - functable.chunkunroll = &chunkunroll_avx; -#endif -#ifdef ARM_NEON_CHUNKSET - if (arm_cpu_has_neon) - functable.chunkunroll = &chunkunroll_neon; -#endif - - return functable.chunkunroll(out, dist, len); -} - -Z_INTERNAL uint8_t* chunkmemset_stub(uint8_t *out, unsigned dist, unsigned len) { - // Initialize default - functable.chunkmemset = &chunkmemset_c; - -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - functable.chunkmemset = &chunkmemset_sse2; -#endif -#ifdef X86_AVX_CHUNKSET - if (x86_cpu_has_avx2) - functable.chunkmemset = &chunkmemset_avx; -#endif -#ifdef ARM_NEON_CHUNKSET - if (arm_cpu_has_neon) - functable.chunkmemset = &chunkmemset_neon; -#endif - - return functable.chunkmemset(out, dist, len); -} - -Z_INTERNAL uint8_t* chunkmemset_safe_stub(uint8_t *out, unsigned dist, unsigned len, unsigned left) { - // Initialize default - functable.chunkmemset_safe = &chunkmemset_safe_c; - -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - functable.chunkmemset_safe = &chunkmemset_safe_sse2; -#endif -#ifdef X86_AVX_CHUNKSET - if (x86_cpu_has_avx2) - functable.chunkmemset_safe = &chunkmemset_safe_avx; -#endif -#ifdef ARM_NEON_CHUNKSET - if (arm_cpu_has_neon) - functable.chunkmemset_safe = &chunkmemset_safe_neon; -#endif - - return functable.chunkmemset_safe(out, dist, len, left); -} - -Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t len) { - int32_t use_byfour = sizeof(void *) == sizeof(ptrdiff_t); - - Assert(sizeof(uint64_t) >= sizeof(size_t), - "crc32_z takes size_t but internally we have a uint64_t len"); - /* return a function pointer for optimized arches here after a capability test */ - - cpu_check_features(); - - if (use_byfour) { -#if BYTE_ORDER == LITTLE_ENDIAN - functable.crc32 = crc32_little; -# if defined(ARM_ACLE_CRC_HASH) - if (arm_cpu_has_crc32) - functable.crc32 = crc32_acle; -# endif -#elif BYTE_ORDER == BIG_ENDIAN - functable.crc32 = crc32_big; -#else -# error No endian defined -#endif - } else { - functable.crc32 = crc32_generic; - } - - return functable.crc32(crc, buf, len); -} - -Z_INTERNAL uint32_t compare258_stub(const unsigned char *src0, const unsigned char *src1) { - - functable.compare258 = &compare258_c; - -#ifdef UNALIGNED_OK -# if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - functable.compare258 = &compare258_unaligned_64; -# elif defined(HAVE_BUILTIN_CTZ) - functable.compare258 = &compare258_unaligned_32; -# else - functable.compare258 = &compare258_unaligned_16; -# endif -# ifdef X86_SSE42_CMP_STR - if (x86_cpu_has_sse42) - functable.compare258 = &compare258_unaligned_sse4; -# endif -# if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_avx2) - functable.compare258 = &compare258_unaligned_avx2; -# endif -#endif - - return functable.compare258(src0, src1); -} - -Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { - - functable.longest_match = &longest_match_c; - -#ifdef UNALIGNED_OK -# if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - functable.longest_match = &longest_match_unaligned_64; -# elif defined(HAVE_BUILTIN_CTZ) - functable.longest_match = &longest_match_unaligned_32; -# else - functable.longest_match = &longest_match_unaligned_16; -# endif -# ifdef X86_SSE42_CMP_STR - if (x86_cpu_has_sse42) - functable.longest_match = &longest_match_unaligned_sse4; -# endif -# if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_avx2) - functable.longest_match = &longest_match_unaligned_avx2; -# endif -#endif - - return functable.longest_match(s, cur_match); -} - -/* functable init */ -Z_INTERNAL Z_TLS struct functable_s functable = { - insert_string_stub, - quick_insert_string_stub, - adler32_stub, - crc32_stub, - slide_hash_stub, - compare258_stub, - longest_match_stub, - chunksize_stub, - chunkcopy_stub, - chunkcopy_safe_stub, - chunkunroll_stub, - chunkmemset_stub, - chunkmemset_safe_stub -}; diff --git a/libs/zlibng/functable.h b/libs/zlibng/functable.h deleted file mode 100644 index 276c284a09..0000000000 --- a/libs/zlibng/functable.h +++ /dev/null @@ -1,29 +0,0 @@ -/* functable.h -- Struct containing function pointers to optimized functions - * Copyright (C) 2017 Hans Kristian Rosbach - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef FUNCTABLE_H_ -#define FUNCTABLE_H_ - -#include "deflate.h" - -struct functable_s { - void (* insert_string) (deflate_state *const s, const uint32_t str, uint32_t count); - Pos (* quick_insert_string)(deflate_state *const s, const uint32_t str); - uint32_t (* adler32) (uint32_t adler, const unsigned char *buf, size_t len); - uint32_t (* crc32) (uint32_t crc, const unsigned char *buf, uint64_t len); - void (* slide_hash) (deflate_state *s); - uint32_t (* compare258) (const unsigned char *src0, const unsigned char *src1); - uint32_t (* longest_match) (deflate_state *const s, Pos cur_match); - uint32_t (* chunksize) (void); - uint8_t* (* chunkcopy) (uint8_t *out, uint8_t const *from, unsigned len); - uint8_t* (* chunkcopy_safe) (uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); - uint8_t* (* chunkunroll) (uint8_t *out, unsigned *dist, unsigned *len); - uint8_t* (* chunkmemset) (uint8_t *out, unsigned dist, unsigned len); - uint8_t* (* chunkmemset_safe) (uint8_t *out, unsigned dist, unsigned len, unsigned left); -}; - -Z_INTERNAL extern Z_TLS struct functable_s functable; - -#endif diff --git a/libs/zlibng/gzguts.h b/libs/zlibng/gzguts.h deleted file mode 100644 index 16029607f7..0000000000 --- a/libs/zlibng/gzguts.h +++ /dev/null @@ -1,154 +0,0 @@ -#ifndef GZGUTS_H_ -#define GZGUTS_H_ -/* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifdef _LARGEFILE64_SOURCE -# ifndef _LARGEFILE_SOURCE -# define _LARGEFILE_SOURCE 1 -# endif -# ifdef _FILE_OFFSET_BITS -# undef _FILE_OFFSET_BITS -# endif -#endif - -#if defined(HAVE_VISIBILITY_INTERNAL) -# define Z_INTERNAL __attribute__((visibility ("internal"))) -#elif defined(HAVE_VISIBILITY_HIDDEN) -# define Z_INTERNAL __attribute__((visibility ("hidden"))) -#else -# define Z_INTERNAL -#endif - -#include -#include -#include -#include -#include - -#if defined(ZLIB_COMPAT) -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -#ifdef _WIN32 -# include -#endif - -#if !defined(_MSC_VER) || defined(__MINGW__) -# include /* for lseek(), read(), close(), write(), unlink() */ -#endif - -#if defined(_WIN32) -# include -# define WIDECHAR -#endif - -#ifdef WINAPI_FAMILY -# define open _open -# define read _read -# define write _write -# define close _close -#endif - -/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -#if !defined(STDC99) && !defined(__CYGWIN__) && !defined(__MINGW__) && defined(_WIN32) -# if !defined(vsnprintf) -# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) -# define vsnprintf _vsnprintf -# endif -# endif -#endif - -/* unlike snprintf (which is required in C99), _snprintf does not guarantee - null termination of the result -- however this is only used in gzlib.c - where the result is assured to fit in the space provided */ -#if defined(_MSC_VER) && _MSC_VER < 1900 -# define snprintf _snprintf -#endif - -/* get errno and strerror definition */ -#ifndef NO_STRERROR -# include -# define zstrerror() strerror(errno) -#else -# define zstrerror() "stdio error (consult errno)" -#endif - -/* default memLevel */ -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif - -/* default i/o buffer size -- double this for output when reading (this and - twice this must be able to fit in an unsigned type) */ -#ifndef GZBUFSIZE -# define GZBUFSIZE 8192 -#endif - -/* gzip modes, also provide a little integrity check on the passed structure */ -#define GZ_NONE 0 -#define GZ_READ 7247 -#define GZ_WRITE 31153 -#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ - -/* values for gz_state how */ -#define LOOK 0 /* look for a gzip header */ -#define COPY 1 /* copy input directly */ -#define GZIP 2 /* decompress a gzip stream */ - -/* internal gzip file state data structure */ -typedef struct { - /* exposed contents for gzgetc() macro */ - struct gzFile_s x; /* "x" for exposed */ - /* x.have: number of bytes available at x.next */ - /* x.next: next output data to deliver or write */ - /* x.pos: current position in uncompressed data */ - /* used for both reading and writing */ - int mode; /* see gzip modes above */ - int fd; /* file descriptor */ - char *path; /* path or fd for error messages */ - unsigned size; /* buffer size, zero if not allocated yet */ - unsigned want; /* requested buffer size, default is GZBUFSIZE */ - unsigned char *in; /* input buffer (double-sized when writing) */ - unsigned char *out; /* output buffer (double-sized when reading) */ - int direct; /* 0 if processing gzip, 1 if transparent */ - /* just for reading */ - int how; /* 0: get header, 1: copy, 2: decompress */ - z_off64_t start; /* where the gzip data started, for rewinding */ - int eof; /* true if end of input file reached */ - int past; /* true if read requested past end */ - /* just for writing */ - int level; /* compression level */ - int strategy; /* compression strategy */ - int reset; /* true if a reset is pending after a Z_FINISH */ - /* seek request */ - z_off64_t skip; /* amount to skip (already rewound if backwards) */ - int seek; /* true if seek request pending */ - /* error information */ - int err; /* error code */ - char *msg; /* error message */ - /* zlib inflate or deflate stream */ - PREFIX3(stream) strm; /* stream structure in-place (not a pointer) */ -} gz_state; -typedef gz_state *gz_statep; - -/* shared functions */ -void Z_INTERNAL gz_error(gz_state *, int, const char *); - -/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t - value -- needed when comparing unsigned to z_off64_t, which is signed - (possible z_off64_t types off_t, off64_t, and long are all signed) */ -#ifdef INT_MAX -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) -#else -unsigned Z_INTERNAL gz_intmax(void); -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) -#endif - -#endif /* GZGUTS_H_ */ diff --git a/libs/zlibng/gzlib.c b/libs/zlibng/gzlib.c deleted file mode 100644 index 490551667a..0000000000 --- a/libs/zlibng/gzlib.c +++ /dev/null @@ -1,543 +0,0 @@ -/* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004-2017 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "zutil_p.h" -#include "gzguts.h" - -#if defined(_WIN32) -# define LSEEK _lseeki64 -#else -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 -# define LSEEK lseek64 -#else -# define LSEEK lseek -#endif -#endif - -/* Local functions */ -static void gz_reset(gz_state *); -static gzFile gz_open(const void *, int, const char *); - -/* Reset gzip file state */ -static void gz_reset(gz_state *state) { - state->x.have = 0; /* no output data available */ - if (state->mode == GZ_READ) { /* for reading ... */ - state->eof = 0; /* not at end of file */ - state->past = 0; /* have not read past end yet */ - state->how = LOOK; /* look for gzip header */ - } - else /* for writing ... */ - state->reset = 0; /* no deflateReset pending */ - state->seek = 0; /* no seek request pending */ - gz_error(state, Z_OK, NULL); /* clear error */ - state->x.pos = 0; /* no uncompressed data yet */ - state->strm.avail_in = 0; /* no input data yet */ -} - -/* Open a gzip file either by name or file descriptor. */ -static gzFile gz_open(const void *path, int fd, const char *mode) { - gz_state *state; - size_t len; - int oflag; -#ifdef O_CLOEXEC - int cloexec = 0; -#endif -#ifdef O_EXCL - int exclusive = 0; -#endif - - /* check input */ - if (path == NULL) - return NULL; - - /* allocate gzFile structure to return */ - state = (gz_state *)zng_alloc(sizeof(gz_state)); - if (state == NULL) - return NULL; - state->size = 0; /* no buffers allocated yet */ - state->want = GZBUFSIZE; /* requested buffer size */ - state->msg = NULL; /* no error message yet */ - - /* interpret mode */ - state->mode = GZ_NONE; - state->level = Z_DEFAULT_COMPRESSION; - state->strategy = Z_DEFAULT_STRATEGY; - state->direct = 0; - while (*mode) { - if (*mode >= '0' && *mode <= '9') { - state->level = *mode - '0'; - } else { - switch (*mode) { - case 'r': - state->mode = GZ_READ; - break; -#ifndef NO_GZCOMPRESS - case 'w': - state->mode = GZ_WRITE; - break; - case 'a': - state->mode = GZ_APPEND; - break; -#endif - case '+': /* can't read and write at the same time */ - zng_free(state); - return NULL; - case 'b': /* ignore -- will request binary anyway */ - break; -#ifdef O_CLOEXEC - case 'e': - cloexec = 1; - break; -#endif -#ifdef O_EXCL - case 'x': - exclusive = 1; - break; -#endif - case 'f': - state->strategy = Z_FILTERED; - break; - case 'h': - state->strategy = Z_HUFFMAN_ONLY; - break; - case 'R': - state->strategy = Z_RLE; - break; - case 'F': - state->strategy = Z_FIXED; - break; - case 'T': - state->direct = 1; - break; - default: /* could consider as an error, but just ignore */ - {} - } - } - mode++; - } - - /* must provide an "r", "w", or "a" */ - if (state->mode == GZ_NONE) { - zng_free(state); - return NULL; - } - - /* can't force transparent read */ - if (state->mode == GZ_READ) { - if (state->direct) { - zng_free(state); - return NULL; - } - state->direct = 1; /* for empty file */ - } - - /* save the path name for error messages */ -#ifdef WIDECHAR - if (fd == -2) { - len = wcstombs(NULL, (const wchar_t *)path, 0); - if (len == (size_t)-1) - len = 0; - } else -#endif - len = strlen((const char *)path); - state->path = (char *)malloc(len + 1); - if (state->path == NULL) { - zng_free(state); - return NULL; - } -#ifdef WIDECHAR - if (fd == -2) - if (len) { - wcstombs(state->path, (const wchar_t *)path, len + 1); - } else { - *(state->path) = 0; - } - else -#endif - (void)snprintf(state->path, len + 1, "%s", (const char *)path); - - /* compute the flags for open() */ - oflag = -#ifdef O_LARGEFILE - O_LARGEFILE | -#endif -#ifdef O_BINARY - O_BINARY | -#endif -#ifdef O_CLOEXEC - (cloexec ? O_CLOEXEC : 0) | -#endif - (state->mode == GZ_READ ? - O_RDONLY : - (O_WRONLY | O_CREAT | -#ifdef O_EXCL - (exclusive ? O_EXCL : 0) | -#endif - (state->mode == GZ_WRITE ? - O_TRUNC : - O_APPEND))); - - /* open the file with the appropriate flags (or just use fd) */ - state->fd = fd > -1 ? fd : ( -#if defined(_WIN32) - fd == -2 ? _wopen((const wchar_t *)path, oflag, 0666) : -#elif __CYGWIN__ - fd == -2 ? open(state->path, oflag, 0666) : -#endif - open((const char *)path, oflag, 0666)); - if (state->fd == -1) { - free(state->path); - zng_free(state); - return NULL; - } - if (state->mode == GZ_APPEND) { - LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ - state->mode = GZ_WRITE; /* simplify later checks */ - } - - /* save the current position for rewinding (only if reading) */ - if (state->mode == GZ_READ) { - state->start = LSEEK(state->fd, 0, SEEK_CUR); - if (state->start == -1) state->start = 0; - } - - /* initialize stream */ - gz_reset(state); - - /* return stream */ - return (gzFile)state; -} - -/* -- see zlib.h -- */ -gzFile Z_EXPORT PREFIX(gzopen)(const char *path, const char *mode) { - return gz_open(path, -1, mode); -} - -#ifdef ZLIB_COMPAT -gzFile Z_EXPORT PREFIX4(gzopen)(const char *path, const char *mode) { - return gz_open(path, -1, mode); -} -#endif - -/* -- see zlib.h -- */ -gzFile Z_EXPORT PREFIX(gzdopen)(int fd, const char *mode) { - char *path; /* identifier for error messages */ - gzFile gz; - - if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) - return NULL; - (void)snprintf(path, 7 + 3 * sizeof(int), "", fd); /* for debugging */ - gz = gz_open(path, fd, mode); - free(path); - return gz; -} - -/* -- see zlib.h -- */ -#ifdef WIDECHAR -gzFile Z_EXPORT PREFIX(gzopen_w)(const wchar_t *path, const char *mode) { - return gz_open(path, -2, mode); -} -#endif - -int Z_EXPORT PREFIX(gzclose)(gzFile file) { -#ifndef NO_GZCOMPRESS - gz_state *state; - - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_state *)file; - - return state->mode == GZ_READ ? PREFIX(gzclose_r)(file) : PREFIX(gzclose_w)(file); -#else - return PREFIX(gzclose_r)(file); -#endif -} - -/* -- see zlib.h -- */ -int Z_EXPORT PREFIX(gzbuffer)(gzFile file, unsigned size) { - gz_state *state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_state *)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* make sure we haven't already allocated memory */ - if (state->size != 0) - return -1; - - /* check and set requested size */ - if ((size << 1) < size) - return -1; /* need to be able to double it */ - if (size < 2) - size = 2; /* need two bytes to check magic header */ - state->want = size; - return 0; -} - -/* -- see zlib.h -- */ -int Z_EXPORT PREFIX(gzrewind)(gzFile file) { - gz_state *state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_state *)file; - - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* back up and start over */ - if (LSEEK(state->fd, state->start, SEEK_SET) == -1) - return -1; - gz_reset(state); - return 0; -} - -/* -- see zlib.h -- */ -z_off64_t Z_EXPORT PREFIX4(gzseek)(gzFile file, z_off64_t offset, int whence) { - unsigned n; - z_off64_t ret; - gz_state *state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_state *)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* check that there's no error */ - if (state->err != Z_OK && state->err != Z_BUF_ERROR) - return -1; - - /* can only seek from start or relative to current position */ - if (whence != SEEK_SET && whence != SEEK_CUR) - return -1; - - /* normalize offset to a SEEK_CUR specification */ - if (whence == SEEK_SET) - offset -= state->x.pos; - else if (state->seek) - offset += state->skip; - state->seek = 0; - - /* if within raw area while reading, just go there */ - if (state->mode == GZ_READ && state->how == COPY && state->x.pos + offset >= 0) { - ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR); - if (ret == -1) - return -1; - state->x.have = 0; - state->eof = 0; - state->past = 0; - state->seek = 0; - gz_error(state, Z_OK, NULL); - state->strm.avail_in = 0; - state->x.pos += offset; - return state->x.pos; - } - - /* calculate skip amount, rewinding if needed for back seek when reading */ - if (offset < 0) { - if (state->mode != GZ_READ) /* writing -- can't go backwards */ - return -1; - offset += state->x.pos; - if (offset < 0) /* before start of file! */ - return -1; - if (PREFIX(gzrewind)(file) == -1) /* rewind, then skip to offset */ - return -1; - } - - /* if reading, skip what's in output buffer (one less gzgetc() check) */ - if (state->mode == GZ_READ) { - n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? (unsigned)offset : state->x.have; - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - offset -= n; - } - - /* request skip (if not zero) */ - if (offset) { - state->seek = 1; - state->skip = offset; - } - return state->x.pos + offset; -} - -/* -- see zlib.h -- */ -#ifdef ZLIB_COMPAT -z_off_t Z_EXPORT PREFIX(gzseek)(gzFile file, z_off_t offset, int whence) { - z_off64_t ret; - - ret = PREFIX4(gzseek)(file, (z_off64_t)offset, whence); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} -#endif - -/* -- see zlib.h -- */ -z_off64_t Z_EXPORT PREFIX4(gztell)(gzFile file) { - gz_state *state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_state *)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* return position */ - return state->x.pos + (state->seek ? state->skip : 0); -} - -/* -- see zlib.h -- */ -#ifdef ZLIB_COMPAT -z_off_t Z_EXPORT PREFIX(gztell)(gzFile file) { - - z_off64_t ret; - - ret = PREFIX4(gztell)(file); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} -#endif - -/* -- see zlib.h -- */ -z_off64_t Z_EXPORT PREFIX4(gzoffset)(gzFile file) { - z_off64_t offset; - gz_state *state; - - /* get internal structure and check integrity */ - if (file == NULL) - return -1; - state = (gz_state *)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return -1; - - /* compute and return effective offset in file */ - offset = LSEEK(state->fd, 0, SEEK_CUR); - if (offset == -1) - return -1; - if (state->mode == GZ_READ) /* reading */ - offset -= state->strm.avail_in; /* don't count buffered input */ - return offset; -} - -/* -- see zlib.h -- */ -#ifdef ZLIB_COMPAT -z_off_t Z_EXPORT PREFIX(gzoffset)(gzFile file) { - z_off64_t ret; - - ret = PREFIX4(gzoffset)(file); - return ret == (z_off_t)ret ? (z_off_t)ret : -1; -} -#endif - -/* -- see zlib.h -- */ -int Z_EXPORT PREFIX(gzeof)(gzFile file) { - gz_state *state; - - /* get internal structure and check integrity */ - if (file == NULL) - return 0; - state = (gz_state *)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return 0; - - /* return end-of-file state */ - return state->mode == GZ_READ ? state->past : 0; -} - -/* -- see zlib.h -- */ -const char * Z_EXPORT PREFIX(gzerror)(gzFile file, int *errnum) { - gz_state *state; - - /* get internal structure and check integrity */ - if (file == NULL) - return NULL; - state = (gz_state *)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return NULL; - - /* return error information */ - if (errnum != NULL) - *errnum = state->err; - return state->err == Z_MEM_ERROR ? "out of memory" : (state->msg == NULL ? "" : state->msg); -} - -/* -- see zlib.h -- */ -void Z_EXPORT PREFIX(gzclearerr)(gzFile file) { - gz_state *state; - - /* get internal structure and check integrity */ - if (file == NULL) - return; - state = (gz_state *)file; - if (state->mode != GZ_READ && state->mode != GZ_WRITE) - return; - - /* clear error and end-of-file */ - if (state->mode == GZ_READ) { - state->eof = 0; - state->past = 0; - } - gz_error(state, Z_OK, NULL); -} - -/* Create an error message in allocated memory and set state->err and - state->msg accordingly. Free any previous error message already there. Do - not try to free or allocate space if the error is Z_MEM_ERROR (out of - memory). Simply save the error message as a static string. If there is an - allocation failure constructing the error message, then convert the error to - out of memory. */ -void Z_INTERNAL gz_error(gz_state *state, int err, const char *msg) { - /* free previously allocated message and clear */ - if (state->msg != NULL) { - if (state->err != Z_MEM_ERROR) - free(state->msg); - state->msg = NULL; - } - - /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ - if (err != Z_OK && err != Z_BUF_ERROR) - state->x.have = 0; - - /* set error code, and if no message, then done */ - state->err = err; - if (msg == NULL) - return; - - /* for an out of memory error, return literal string when requested */ - if (err == Z_MEM_ERROR) - return; - - /* construct error message with path */ - if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { - state->err = Z_MEM_ERROR; - return; - } - (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, "%s%s%s", state->path, ": ", msg); -} - -#ifndef INT_MAX -/* portably return maximum value for an int (when limits.h presumed not - available) -- we need to do this to cover cases where 2's complement not - used, since C standard permits 1's complement and sign-bit representations, - otherwise we could just use ((unsigned)-1) >> 1 */ -unsigned Z_INTERNAL gz_intmax() { - unsigned p, q; - - p = 1; - do { - q = p; - p <<= 1; - p++; - } while (p > q); - return q >> 1; -} -#endif diff --git a/libs/zlibng/gzread.c b/libs/zlibng/gzread.c deleted file mode 100644 index c3b3a035fc..0000000000 --- a/libs/zlibng/gzread.c +++ /dev/null @@ -1,602 +0,0 @@ -/* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "zutil_p.h" -#include "gzguts.h" - -/* Local functions */ -static int gz_load(gz_state *, unsigned char *, unsigned, unsigned *); -static int gz_avail(gz_state *); -static int gz_look(gz_state *); -static int gz_decomp(gz_state *); -static int gz_fetch(gz_state *); -static int gz_skip(gz_state *, z_off64_t); -static size_t gz_read(gz_state *, void *, size_t); - -/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from - state->fd, and update state->eof, state->err, and state->msg as appropriate. - This function needs to loop on read(), since read() is not guaranteed to - read the number of bytes requested, depending on the type of descriptor. */ -static int gz_load(gz_state *state, unsigned char *buf, unsigned len, unsigned *have) { - ssize_t ret; - - *have = 0; - do { - ret = read(state->fd, buf + *have, len - *have); - if (ret <= 0) - break; - *have += (unsigned)ret; - } while (*have < len); - if (ret < 0) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - if (ret == 0) - state->eof = 1; - return 0; -} - -/* Load up input buffer and set eof flag if last data loaded -- return -1 on - error, 0 otherwise. Note that the eof flag is set when the end of the input - file is reached, even though there may be unused data in the buffer. Once - that data has been used, no more attempts will be made to read the file. - If strm->avail_in != 0, then the current data is moved to the beginning of - the input buffer, and then the remainder of the buffer is loaded with the - available data from the input file. */ -static int gz_avail(gz_state *state) { - unsigned got; - PREFIX3(stream) *strm = &(state->strm); - - if (state->err != Z_OK && state->err != Z_BUF_ERROR) - return -1; - if (state->eof == 0) { - if (strm->avail_in) { /* copy what's there to the start */ - unsigned char *p = state->in; - unsigned const char *q = strm->next_in; - unsigned n = strm->avail_in; - do { - *p++ = *q++; - } while (--n); - } - if (gz_load(state, state->in + strm->avail_in, state->size - strm->avail_in, &got) == -1) - return -1; - strm->avail_in += got; - strm->next_in = state->in; - } - return 0; -} - -/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. - If this is the first time in, allocate required memory. state->how will be - left unchanged if there is no more input data available, will be set to COPY - if there is no gzip header and direct copying will be performed, or it will - be set to GZIP for decompression. If direct copying, then leftover input - data from the input buffer will be copied to the output buffer. In that - case, all further file reads will be directly to either the output buffer or - a user buffer. If decompressing, the inflate state will be initialized. - gz_look() will return 0 on success or -1 on failure. */ -static int gz_look(gz_state *state) { - PREFIX3(stream) *strm = &(state->strm); - - /* allocate read buffers and inflate memory */ - if (state->size == 0) { - /* allocate buffers */ - state->in = (unsigned char *)zng_alloc(state->want); - state->out = (unsigned char *)zng_alloc(state->want << 1); - if (state->in == NULL || state->out == NULL) { - zng_free(state->out); - zng_free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - state->size = state->want; - - /* allocate inflate memory */ - state->strm.zalloc = NULL; - state->strm.zfree = NULL; - state->strm.opaque = NULL; - state->strm.avail_in = 0; - state->strm.next_in = NULL; - if (PREFIX(inflateInit2)(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ - zng_free(state->out); - zng_free(state->in); - state->size = 0; - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - } - - /* get at least the magic bytes in the input buffer */ - if (strm->avail_in < 2) { - if (gz_avail(state) == -1) - return -1; - if (strm->avail_in == 0) - return 0; - } - - /* look for gzip magic bytes -- if there, do gzip decoding (note: there is - a logical dilemma here when considering the case of a partially written - gzip file, to wit, if a single 31 byte is written, then we cannot tell - whether this is a single-byte file, or just a partially written gzip - file -- for here we assume that if a gzip file is being written, then - the header will be written in a single operation, so that reading a - single byte is sufficient indication that it is not a gzip file) */ - if (strm->avail_in > 1 && - strm->next_in[0] == 31 && strm->next_in[1] == 139) { - PREFIX(inflateReset)(strm); - state->how = GZIP; - state->direct = 0; - return 0; - } - - /* no gzip header -- if we were decoding gzip before, then this is trailing - garbage. Ignore the trailing garbage and finish. */ - if (state->direct == 0) { - strm->avail_in = 0; - state->eof = 1; - state->x.have = 0; - return 0; - } - - /* doing raw i/o, copy any leftover input to output -- this assumes that - the output buffer is larger than the input buffer, which also assures - space for gzungetc() */ - state->x.next = state->out; - if (strm->avail_in) { - memcpy(state->x.next, strm->next_in, strm->avail_in); - state->x.have = strm->avail_in; - strm->avail_in = 0; - } - state->how = COPY; - state->direct = 1; - return 0; -} - -/* Decompress from input to the provided next_out and avail_out in the state. - On return, state->x.have and state->x.next point to the just decompressed - data. If the gzip stream completes, state->how is reset to LOOK to look for - the next gzip stream or raw data, once state->x.have is depleted. Returns 0 - on success, -1 on failure. */ -static int gz_decomp(gz_state *state) { - int ret = Z_OK; - unsigned had; - PREFIX3(stream) *strm = &(state->strm); - - /* fill output buffer up to end of deflate stream */ - had = strm->avail_out; - do { - /* get more input for inflate() */ - if (strm->avail_in == 0 && gz_avail(state) == -1) - return -1; - if (strm->avail_in == 0) { - gz_error(state, Z_BUF_ERROR, "unexpected end of file"); - break; - } - - /* decompress and handle errors */ - ret = PREFIX(inflate)(strm, Z_NO_FLUSH); - if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { - gz_error(state, Z_STREAM_ERROR, "internal error: inflate stream corrupt"); - return -1; - } - if (ret == Z_MEM_ERROR) { - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ - gz_error(state, Z_DATA_ERROR, strm->msg == NULL ? "compressed data error" : strm->msg); - return -1; - } - } while (strm->avail_out && ret != Z_STREAM_END); - - /* update available output */ - state->x.have = had - strm->avail_out; - state->x.next = strm->next_out - state->x.have; - - /* if the gzip stream completed successfully, look for another */ - if (ret == Z_STREAM_END) - state->how = LOOK; - - /* good decompression */ - return 0; -} - -/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. - Data is either copied from the input file or decompressed from the input - file depending on state->how. If state->how is LOOK, then a gzip header is - looked for to determine whether to copy or decompress. Returns -1 on error, - otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the - end of the input file has been reached and all data has been processed. */ -static int gz_fetch(gz_state *state) { - PREFIX3(stream) *strm = &(state->strm); - - do { - switch (state->how) { - case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ - if (gz_look(state) == -1) - return -1; - if (state->how == LOOK) - return 0; - break; - case COPY: /* -> COPY */ - if (gz_load(state, state->out, state->size << 1, &(state->x.have)) - == -1) - return -1; - state->x.next = state->out; - return 0; - case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ - strm->avail_out = state->size << 1; - strm->next_out = state->out; - if (gz_decomp(state) == -1) - return -1; - } - } while (state->x.have == 0 && (!state->eof || strm->avail_in)); - return 0; -} - -/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ -static int gz_skip(gz_state *state, z_off64_t len) { - unsigned n; - - /* skip over len bytes or reach end-of-file, whichever comes first */ - while (len) - /* skip over whatever is in output buffer */ - if (state->x.have) { - n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? - (unsigned)len : state->x.have; - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - len -= n; - } else if (state->eof && state->strm.avail_in == 0) { - /* output buffer empty -- return if we're at the end of the input */ - break; - } else { - /* need more data to skip -- load up output buffer */ - /* get more output, looking for header if required */ - if (gz_fetch(state) == -1) - return -1; - } - return 0; -} - -/* Read len bytes into buf from file, or less than len up to the end of the - input. Return the number of bytes read. If zero is returned, either the - end of file was reached, or there was an error. state->err must be - consulted in that case to determine which. */ -static size_t gz_read(gz_state *state, void *buf, size_t len) { - size_t got; - unsigned n; - - /* if len is zero, avoid unnecessary operations */ - if (len == 0) - return 0; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return 0; - } - - /* get len bytes to buf, or less than len if at the end */ - got = 0; - do { - /* set n to the maximum amount of len that fits in an unsigned int */ - n = (unsigned)-1; - if (n > len) - n = (unsigned)len; - - /* first just try copying data from the output buffer */ - if (state->x.have) { - if (state->x.have < n) - n = state->x.have; - memcpy(buf, state->x.next, n); - state->x.next += n; - state->x.have -= n; - } - - /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && state->strm.avail_in == 0) { - state->past = 1; /* tried to read past end */ - break; - } - - /* need output data -- for small len or new stream load up our output - buffer */ - else if (state->how == LOOK || n < (state->size << 1)) { - /* get more output, looking for header if required */ - if (gz_fetch(state) == -1) - return 0; - continue; /* no progress yet -- go back to copy above */ - /* the copy above assures that we will leave with space in the - output buffer, allowing at least one gzungetc() to succeed */ - } - - /* large len -- read directly into user buffer */ - else if (state->how == COPY) { /* read directly */ - if (gz_load(state, (unsigned char *)buf, n, &n) == -1) - return 0; - } - - /* large len -- decompress directly into user buffer */ - else { /* state->how == GZIP */ - state->strm.avail_out = n; - state->strm.next_out = (unsigned char *)buf; - if (gz_decomp(state) == -1) - return 0; - n = state->x.have; - state->x.have = 0; - } - - /* update progress */ - len -= n; - buf = (char *)buf + n; - got += n; - state->x.pos += n; - } while (len); - - /* return number of bytes read into user buffer */ - return got; -} - -/* -- see zlib.h -- */ -int Z_EXPORT PREFIX(gzread)(gzFile file, void *buf, unsigned len) { - gz_state *state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_state *)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids a flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); - return -1; - } - - /* read len or fewer bytes to buf */ - len = (unsigned)gz_read(state, buf, len); - - /* check for an error */ - if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) - return -1; - - /* return the number of bytes read (this is assured to fit in an int) */ - return (int)len; -} - -/* -- see zlib.h -- */ -size_t Z_EXPORT PREFIX(gzfread)(void *buf, size_t size, size_t nitems, gzFile file) { - size_t len; - gz_state *state; - - /* Exit early if size is zero, also prevents potential division by zero */ - if (size == 0) - return 0; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_state *)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return 0; - - /* compute bytes to read -- error on overflow */ - if (size && SIZE_MAX / size < nitems) { - gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); - return 0; - } - len = nitems * size; - - /* read len or fewer bytes to buf, return the number of full items read */ - return len ? gz_read(state, buf, len) / size : 0; -} - -/* -- see zlib.h -- */ -#undef gzgetc -#undef zng_gzgetc -int Z_EXPORT PREFIX(gzgetc)(gzFile file) { - unsigned char buf[1]; - gz_state *state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_state *)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* try output buffer (no need to check for skip request) */ - if (state->x.have) { - state->x.have--; - state->x.pos++; - return *(state->x.next)++; - } - - /* nothing there -- try gz_read() */ - return gz_read(state, buf, 1) < 1 ? -1 : buf[0]; -} - -int Z_EXPORT PREFIX(gzgetc_)(gzFile file) { - return PREFIX(gzgetc)(file); -} - -/* -- see zlib.h -- */ -int Z_EXPORT PREFIX(gzungetc)(int c, gzFile file) { - gz_state *state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_state *)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return -1; - } - - /* can't push EOF */ - if (c < 0) - return -1; - - /* if output buffer empty, put byte at end (allows more pushing) */ - if (state->x.have == 0) { - state->x.have = 1; - state->x.next = state->out + (state->size << 1) - 1; - state->x.next[0] = (unsigned char)c; - state->x.pos--; - state->past = 0; - return c; - } - - /* if no room, give up (must have already done a gzungetc()) */ - if (state->x.have == (state->size << 1)) { - gz_error(state, Z_DATA_ERROR, "out of room to push characters"); - return -1; - } - - /* slide output data if needed and insert byte before existing data */ - if (state->x.next == state->out) { - unsigned char *src = state->out + state->x.have; - unsigned char *dest = state->out + (state->size << 1); - while (src > state->out) - *--dest = *--src; - state->x.next = dest; - } - state->x.have++; - state->x.next--; - state->x.next[0] = (unsigned char)c; - state->x.pos--; - state->past = 0; - return c; -} - -/* -- see zlib.h -- */ -char * Z_EXPORT PREFIX(gzgets)(gzFile file, char *buf, int len) { - unsigned left, n; - char *str; - unsigned char *eol; - gz_state *state; - - /* check parameters and get internal structure */ - if (file == NULL || buf == NULL || len < 1) - return NULL; - state = (gz_state *)file; - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return NULL; - - /* process a skip request */ - if (state->seek) { - state->seek = 0; - if (gz_skip(state, state->skip) == -1) - return NULL; - } - - /* copy output bytes up to new line or len - 1, whichever comes first -- - append a terminating zero to the string (we don't check for a zero in - the contents, let the user worry about that) */ - str = buf; - left = (unsigned)len - 1; - if (left) { - do { - /* assure that something is in the output buffer */ - if (state->x.have == 0 && gz_fetch(state) == -1) - return NULL; /* error */ - if (state->x.have == 0) { /* end of file */ - state->past = 1; /* read past end */ - break; /* return what we have */ - } - - /* look for end-of-line in current output buffer */ - n = state->x.have > left ? left : state->x.have; - eol = (unsigned char *)memchr(state->x.next, '\n', n); - if (eol != NULL) - n = (unsigned)(eol - state->x.next) + 1; - - /* copy through end-of-line, or remainder if not found */ - memcpy(buf, state->x.next, n); - state->x.have -= n; - state->x.next += n; - state->x.pos += n; - left -= n; - buf += n; - } while (left && eol == NULL); - } - - /* return terminated string, or if nothing, end of file */ - if (buf == str) - return NULL; - buf[0] = 0; - return str; -} - -/* -- see zlib.h -- */ -int Z_EXPORT PREFIX(gzdirect)(gzFile file) { - gz_state *state; - - /* get internal structure */ - if (file == NULL) - return 0; - - state = (gz_state *)file; - - /* if the state is not known, but we can find out, then do so (this is - mainly for right after a gzopen() or gzdopen()) */ - if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) - (void)gz_look(state); - - /* return 1 if transparent, 0 if processing a gzip stream */ - return state->direct; -} - -/* -- see zlib.h -- */ -int Z_EXPORT PREFIX(gzclose_r)(gzFile file) { - int ret, err; - gz_state *state; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - - state = (gz_state *)file; - - /* check that we're reading */ - if (state->mode != GZ_READ) - return Z_STREAM_ERROR; - - /* free memory and close file */ - if (state->size) { - PREFIX(inflateEnd)(&(state->strm)); - zng_free(state->out); - zng_free(state->in); - } - err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; - gz_error(state, Z_OK, NULL); - free(state->path); - ret = close(state->fd); - zng_free(state); - return ret ? Z_ERRNO : err; -} diff --git a/libs/zlibng/gzwrite.c b/libs/zlibng/gzwrite.c deleted file mode 100644 index c4e178f9ad..0000000000 --- a/libs/zlibng/gzwrite.c +++ /dev/null @@ -1,526 +0,0 @@ -/* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004-2017 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "zutil_p.h" -#include -#include "gzguts.h" - -/* Local functions */ -static int gz_init(gz_state *); -static int gz_comp(gz_state *, int); -static int gz_zero(gz_state *, z_off64_t); -static size_t gz_write(gz_state *, void const *, size_t); - -/* Initialize state for writing a gzip file. Mark initialization by setting - state->size to non-zero. Return -1 on a memory allocation failure, or 0 on - success. */ -static int gz_init(gz_state *state) { - int ret; - PREFIX3(stream) *strm = &(state->strm); - - /* allocate input buffer (double size for gzprintf) */ - state->in = (unsigned char *)zng_alloc(state->want << 1); - if (state->in == NULL) { - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - memset(state->in, 0, state->want << 1); - - /* only need output buffer and deflate state if compressing */ - if (!state->direct) { - /* allocate output buffer */ - state->out = (unsigned char *)zng_alloc(state->want); - if (state->out == NULL) { - zng_free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - - /* allocate deflate memory, set up for gzip compression */ - strm->zalloc = NULL; - strm->zfree = NULL; - strm->opaque = NULL; - ret = PREFIX(deflateInit2)(strm, state->level, Z_DEFLATED, MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); - if (ret != Z_OK) { - zng_free(state->out); - zng_free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; - } - strm->next_in = NULL; - } - - /* mark state as initialized */ - state->size = state->want; - - /* initialize write buffer if compressing */ - if (!state->direct) { - strm->avail_out = state->size; - strm->next_out = state->out; - state->x.next = strm->next_out; - } - return 0; -} - -/* Compress whatever is at avail_in and next_in and write to the output file. - Return -1 if there is an error writing to the output file or if gz_init() - fails to allocate memory, otherwise 0. flush is assumed to be a valid - deflate() flush value. If flush is Z_FINISH, then the deflate() state is - reset to start a new gzip stream. If gz->direct is true, then simply write - to the output file without compressing, and ignore flush. */ -static int gz_comp(gz_state *state, int flush) { - int ret; - ssize_t got; - unsigned have; - PREFIX3(stream) *strm = &(state->strm); - - /* allocate memory if this is the first time through */ - if (state->size == 0 && gz_init(state) == -1) - return -1; - - /* write directly if requested */ - if (state->direct) { - got = write(state->fd, strm->next_in, strm->avail_in); - if (got < 0 || (unsigned)got != strm->avail_in) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - strm->avail_in = 0; - return 0; - } - - /* check for a pending reset */ - if (state->reset) { - /* don't start a new gzip member unless there is data to write */ - if (strm->avail_in == 0) - return 0; - PREFIX(deflateReset)(strm); - state->reset = 0; - } - - /* run deflate() on provided input until it produces no more output */ - ret = Z_OK; - do { - /* write out current buffer contents if full, or if flushing, but if - doing Z_FINISH then don't write until we get to Z_STREAM_END */ - if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) { - have = (unsigned)(strm->next_out - state->x.next); - if (have && ((got = write(state->fd, state->x.next, (unsigned long)have)) < 0 || (unsigned)got != have)) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; - } - if (strm->avail_out == 0) { - strm->avail_out = state->size; - strm->next_out = state->out; - state->x.next = state->out; - } - state->x.next = strm->next_out; - } - - /* compress */ - have = strm->avail_out; - ret = PREFIX(deflate)(strm, flush); - if (ret == Z_STREAM_ERROR) { - gz_error(state, Z_STREAM_ERROR, "internal error: deflate stream corrupt"); - return -1; - } - have -= strm->avail_out; - } while (have); - - /* if that completed a deflate stream, allow another to start */ - if (flush == Z_FINISH) - state->reset = 1; - /* all done, no errors */ - return 0; -} - -/* Compress len zeros to output. Return -1 on a write error or memory - allocation failure by gz_comp(), or 0 on success. */ -static int gz_zero(gz_state *state, z_off64_t len) { - int first; - unsigned n; - PREFIX3(stream) *strm = &(state->strm); - - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return -1; - - /* compress len zeros (len guaranteed > 0) */ - first = 1; - while (len) { - n = GT_OFF(state->size) || (z_off64_t)state->size > len ? (unsigned)len : state->size; - if (first) { - memset(state->in, 0, n); - first = 0; - } - strm->avail_in = n; - strm->next_in = state->in; - state->x.pos += n; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return -1; - len -= n; - } - return 0; -} - -/* Write len bytes from buf to file. Return the number of bytes written. If - the returned value is less than len, then there was an error. */ -static size_t gz_write(gz_state *state, void const *buf, size_t len) { - size_t put = len; - - /* if len is zero, avoid unnecessary operations */ - if (len == 0) - return 0; - - /* allocate memory if this is the first time through */ - if (state->size == 0 && gz_init(state) == -1) - return 0; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return 0; - } - - /* for small len, copy to input buffer, otherwise compress directly */ - if (len < state->size) { - /* copy to input buffer, compress when full */ - do { - unsigned have, copy; - - if (state->strm.avail_in == 0) - state->strm.next_in = state->in; - have = (unsigned)((state->strm.next_in + state->strm.avail_in) - - state->in); - copy = state->size - have; - if (copy > len) - copy = (unsigned)len; - memcpy(state->in + have, buf, copy); - state->strm.avail_in += copy; - state->x.pos += copy; - buf = (const char *)buf + copy; - len -= copy; - if (len && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - } while (len); - } else { - /* consume whatever's left in the input buffer */ - if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* directly compress user buffer to file */ - state->strm.next_in = (z_const unsigned char *) buf; - do { - unsigned n = (unsigned)-1; - if (n > len) - n = (unsigned)len; - state->strm.avail_in = n; - state->x.pos += n; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - len -= n; - } while (len); - } - - /* input was all buffered or compressed */ - return put; -} - -/* -- see zlib.h -- */ -int Z_EXPORT PREFIX(gzwrite)(gzFile file, void const *buf, unsigned len) { - gz_state *state; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_state *)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids a flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); - return 0; - } - - /* write len bytes from buf (the return value will fit in an int) */ - return (int)gz_write(state, buf, len); -} - -/* -- see zlib.h -- */ -size_t Z_EXPORT PREFIX(gzfwrite)(void const *buf, size_t size, size_t nitems, gzFile file) { - size_t len; - gz_state *state; - - /* Exit early if size is zero, also prevents potential division by zero */ - if (size == 0) - return 0; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_state *)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* compute bytes to read -- error on overflow */ - len = nitems * size; - if (size && len / size != nitems) { - gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); - return 0; - } - - /* write len bytes to buf, return the number of full items written */ - return len ? gz_write(state, buf, len) / size : 0; -} - -/* -- see zlib.h -- */ -int Z_EXPORT PREFIX(gzputc)(gzFile file, int c) { - unsigned have; - unsigned char buf[1]; - gz_state *state; - PREFIX3(stream) *strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_state *)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return -1; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return -1; - } - - /* try writing to input buffer for speed (state->size == 0 if buffer not - initialized) */ - if (state->size) { - if (strm->avail_in == 0) - strm->next_in = state->in; - have = (unsigned)((strm->next_in + strm->avail_in) - state->in); - if (have < state->size) { - state->in[have] = (unsigned char)c; - strm->avail_in++; - state->x.pos++; - return c & 0xff; - } - } - - /* no room in buffer or not initialized, use gz_write() */ - buf[0] = (unsigned char)c; - if (gz_write(state, buf, 1) != 1) - return -1; - return c & 0xff; -} - -/* -- see zlib.h -- */ -int Z_EXPORT PREFIX(gzputs)(gzFile file, const char *s) { - size_t len, put; - gz_state *state; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_state *)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return -1; - - /* write string */ - len = strlen(s); - if ((int)len < 0 || (unsigned)len != len) { - gz_error(state, Z_STREAM_ERROR, "string length does not fit in int"); - return -1; - } - put = gz_write(state, s, len); - return put < len ? -1 : (int)len; -} - -/* -- see zlib.h -- */ -int Z_EXPORTVA PREFIX(gzvprintf)(gzFile file, const char *format, va_list va) { - int len; - unsigned left; - char *next; - gz_state *state; - PREFIX3(stream) *strm; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_state *)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* make sure we have some buffer space */ - if (state->size == 0 && gz_init(state) == -1) - return state->err; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->err; - } - - /* do the printf() into the input buffer, put length in len -- the input - buffer is double-sized just for this function, so there is guaranteed to - be state->size bytes available after the current contents */ - if (strm->avail_in == 0) - strm->next_in = state->in; - next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in); - next[state->size - 1] = 0; - len = vsnprintf(next, state->size, format, va); - - /* check that printf() results fit in buffer */ - if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0) - return 0; - - /* update buffer and position, compress first half if past that */ - strm->avail_in += (unsigned)len; - state->x.pos += len; - if (strm->avail_in >= state->size) { - left = strm->avail_in - state->size; - strm->avail_in = state->size; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return state->err; - memmove(state->in, state->in + state->size, left); - strm->next_in = state->in; - strm->avail_in = left; - } - return len; -} - -int Z_EXPORTVA PREFIX(gzprintf)(gzFile file, const char *format, ...) { - va_list va; - int ret; - - va_start(va, format); - ret = PREFIX(gzvprintf)(file, format, va); - va_end(va); - return ret; -} - -/* -- see zlib.h -- */ -int Z_EXPORT PREFIX(gzflush)(gzFile file, int flush) { - gz_state *state; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_state *)file; - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* check flush parameter */ - if (flush < 0 || flush > Z_FINISH) - return Z_STREAM_ERROR; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->err; - } - - /* compress remaining data with requested flush */ - (void)gz_comp(state, flush); - return state->err; -} - -/* -- see zlib.h -- */ -int Z_EXPORT PREFIX(gzsetparams)(gzFile file, int level, int strategy) { - gz_state *state; - PREFIX3(stream) *strm; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_state *)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return Z_STREAM_ERROR; - - /* if no change is requested, then do nothing */ - if (level == state->level && strategy == state->strategy) - return Z_OK; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - return state->err; - } - - /* change compression parameters for subsequent input */ - if (state->size) { - /* flush previous input with previous parameters before changing */ - if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1) - return state->err; - PREFIX(deflateParams)(strm, level, strategy); - } - state->level = level; - state->strategy = strategy; - return Z_OK; -} - -/* -- see zlib.h -- */ -int Z_EXPORT PREFIX(gzclose_w)(gzFile file) { - int ret = Z_OK; - gz_state *state; - - /* get internal structure */ - if (file == NULL) - return Z_STREAM_ERROR; - state = (gz_state *)file; - - /* check that we're writing */ - if (state->mode != GZ_WRITE) - return Z_STREAM_ERROR; - - /* check for seek request */ - if (state->seek) { - state->seek = 0; - if (gz_zero(state, state->skip) == -1) - ret = state->err; - } - - /* flush, free memory, and close file */ - if (gz_comp(state, Z_FINISH) == -1) - ret = state->err; - if (state->size) { - if (!state->direct) { - (void)PREFIX(deflateEnd)(&(state->strm)); - zng_free(state->out); - } - zng_free(state->in); - } - gz_error(state, Z_OK, NULL); - free(state->path); - if (close(state->fd) == -1) - ret = Z_ERRNO; - zng_free(state); - return ret; -} diff --git a/libs/zlibng/infback.c b/libs/zlibng/infback.c deleted file mode 100644 index eecf03ada4..0000000000 --- a/libs/zlibng/infback.c +++ /dev/null @@ -1,510 +0,0 @@ -/* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - This code is largely copied from inflate.c. Normally either infback.o or - inflate.o would be linked into an application--not both. The interface - with inffast.c is retained so that optimized assembler-coded versions of - inflate_fast() can be used with either inflate.c or infback.c. - */ - -#include "zbuild.h" -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" -#include "inflate_p.h" -#include "functable.h" - -/* - strm provides memory allocation functions in zalloc and zfree, or - NULL to use the library memory allocation functions. - - windowBits is in the range 8..15, and window is a user-supplied - window and output buffer that is 2**windowBits bytes. - */ -int32_t Z_EXPORT PREFIX(inflateBackInit_)(PREFIX3(stream) *strm, int32_t windowBits, uint8_t *window, - const char *version, int32_t stream_size) { - struct inflate_state *state; - - if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != (int)(sizeof(PREFIX3(stream)))) - return Z_VERSION_ERROR; - if (strm == NULL || window == NULL || windowBits < 8 || windowBits > 15) - return Z_STREAM_ERROR; - strm->msg = NULL; /* in case we return an error */ - if (strm->zalloc == NULL) { - strm->zalloc = zng_calloc; - strm->opaque = NULL; - } - if (strm->zfree == NULL) - strm->zfree = zng_cfree; - state = (struct inflate_state *) ZALLOC(strm, 1, sizeof(struct inflate_state)); - if (state == NULL) - return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state *)state; - state->dmax = 32768U; - state->wbits = (unsigned int)windowBits; - state->wsize = 1U << windowBits; - state->window = window; - state->wnext = 0; - state->whave = 0; - state->chunksize = functable.chunksize(); - return Z_OK; -} - -/* - Private macros for inflateBack() - Look in inflate_p.h for macros shared with inflate() -*/ - -/* Assure that some input is available. If input is requested, but denied, - then return a Z_BUF_ERROR from inflateBack(). */ -#define PULL() \ - do { \ - if (have == 0) { \ - have = in(in_desc, &next); \ - if (have == 0) { \ - next = NULL; \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflateBack() - with an error if there is no input available. */ -#define PULLBYTE() \ - do { \ - PULL(); \ - have--; \ - hold += ((unsigned)(*next++) << bits); \ - bits += 8; \ - } while (0) - -/* Assure that some output space is available, by writing out the window - if it's full. If the write fails, return from inflateBack() with a - Z_BUF_ERROR. */ -#define ROOM() \ - do { \ - if (left == 0) { \ - put = state->window; \ - left = state->wsize; \ - state->whave = left; \ - if (out(out_desc, put, left)) { \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* - strm provides the memory allocation functions and window buffer on input, - and provides information on the unused input on return. For Z_DATA_ERROR - returns, strm will also provide an error message. - - in() and out() are the call-back input and output functions. When - inflateBack() needs more input, it calls in(). When inflateBack() has - filled the window with output, or when it completes with data in the - window, it calls out() to write out the data. The application must not - change the provided input until in() is called again or inflateBack() - returns. The application must not change the window/output buffer until - inflateBack() returns. - - in() and out() are called with a descriptor parameter provided in the - inflateBack() call. This parameter can be a structure that provides the - information required to do the read or write, as well as accumulated - information on the input and output such as totals and check values. - - in() should return zero on failure. out() should return non-zero on - failure. If either in() or out() fails, than inflateBack() returns a - Z_BUF_ERROR. strm->next_in can be checked for NULL to see whether it - was in() or out() that caused in the error. Otherwise, inflateBack() - returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format - error, or Z_MEM_ERROR if it could not allocate memory for the state. - inflateBack() can also return Z_STREAM_ERROR if the input parameters - are not correct, i.e. strm is NULL or the state was not initialized. - */ -int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in_desc, out_func out, void *out_desc) { - struct inflate_state *state; - z_const unsigned char *next; /* next input */ - unsigned char *put; /* next output */ - unsigned have, left; /* available input and output */ - uint32_t hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char *from; /* where to copy match bytes from */ - code here; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int32_t ret; /* return code */ - static const uint16_t order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - /* Check that the strm exists and that the state was initialized */ - if (strm == NULL || strm->state == NULL) - return Z_STREAM_ERROR; - state = (struct inflate_state *)strm->state; - - /* Reset the state */ - strm->msg = NULL; - state->mode = TYPE; - state->last = 0; - state->whave = 0; - next = strm->next_in; - have = next != NULL ? strm->avail_in : 0; - hold = 0; - bits = 0; - put = state->window; - left = state->wsize; - - /* Inflate until end of block marked as last */ - for (;;) - switch (state->mode) { - case TYPE: - /* determine and dispatch block type */ - if (state->last) { - BYTEBITS(); - state->mode = DONE; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); - state->mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - - case STORED: - /* get and verify stored block length */ - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (uint16_t)hold; - Tracev((stderr, "inflate: stored length %u\n", state->length)); - INITBITS(); - - /* copy stored block from input to output */ - while (state->length != 0) { - copy = state->length; - PULL(); - ROOM(); - if (copy > have) copy = have; - if (copy > left) copy = left; - memcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - - case TABLE: - /* get dynamic table entries descriptor */ - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - state->have = 0; - - /* get code length code lengths (not a typo) */ - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (uint16_t)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (const code *)(state->next); - state->lenbits = 7; - ret = zng_inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - state->have = 0; - - /* get length and distance code code lengths */ - while (state->have < state->nlen + state->ndist) { - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if (here.bits <= bits) break; - PULLBYTE(); - } - if (here.val < 16) { - DROPBITS(here.bits); - state->lens[state->have++] = here.val; - } else { - if (here.val == 16) { - NEEDBITS(here.bits + 2); - DROPBITS(here.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = state->lens[state->have - 1]; - copy = 3 + BITS(2); - DROPBITS(2); - } else if (here.val == 17) { - NEEDBITS(here.bits + 3); - DROPBITS(here.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } else { - NEEDBITS(here.bits + 7); - DROPBITS(here.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy) { - --copy; - state->lens[state->have++] = (uint16_t)len; - } - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) - break; - - /* check for end-of-block code (better have one) */ - if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; - state->mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state->next = state->codes; - state->lencode = (const code *)(state->next); - state->lenbits = 9; - ret = zng_inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (const code *)(state->next); - state->distbits = 6; - ret = zng_inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN; - - case LEN: - /* use inflate_fast() if we have enough input and output */ - if (have >= INFLATE_FAST_MIN_HAVE && - left >= INFLATE_FAST_MIN_LEFT) { - RESTORE(); - if (state->whave < state->wsize) - state->whave = state->wsize - left; - zng_inflate_fast(strm, state->wsize); - LOAD(); - break; - } - - /* get a literal, length, or end-of-block code */ - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if (here.bits <= bits) - break; - PULLBYTE(); - } - if (here.op && (here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)last.bits + (unsigned)here.bits <= bits) - break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - state->length = here.val; - - /* process literal */ - if ((int)(here.op) == 0) { - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - ROOM(); - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - } - - /* process end of block */ - if (here.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - - /* invalid code */ - if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - - /* length code -- get extra bits, if any */ - state->extra = (here.op & 15); - if (state->extra) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - - /* get distance code */ - for (;;) { - here = state->distcode[BITS(state->distbits)]; - if (here.bits <= bits) - break; - PULLBYTE(); - } - if ((here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)last.bits + (unsigned)here.bits <= bits) - break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(here.bits); - if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = here.val; - state->extra = (here.op & 15); - - /* get distance extra bits, if any */ - if (state->extra) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - } -#ifdef INFLATE_STRICT - if (state->offset > state->wsize - (state->whave < state->wsize ? left : 0)) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - - /* copy match from window to output */ - do { - ROOM(); - copy = state->wsize - state->offset; - if (copy < left) { - from = put + copy; - copy = left - copy; - } else { - from = put - state->offset; - copy = left; - } - if (copy > state->length) - copy = state->length; - state->length -= copy; - left -= copy; - do { - *put++ = *from++; - } while (--copy); - } while (state->length != 0); - break; - - case DONE: - /* inflate stream terminated properly -- write leftover output */ - ret = Z_STREAM_END; - if (left < state->wsize) { - if (out(out_desc, state->window, state->wsize - left)) - ret = Z_BUF_ERROR; - } - goto inf_leave; - - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - - default: /* can't happen, but makes compilers happy */ - ret = Z_STREAM_ERROR; - goto inf_leave; - } - - /* Return unused input */ - inf_leave: - strm->next_in = next; - strm->avail_in = have; - return ret; -} - -int32_t Z_EXPORT PREFIX(inflateBackEnd)(PREFIX3(stream) *strm) { - if (strm == NULL || strm->state == NULL || strm->zfree == NULL) - return Z_STREAM_ERROR; - ZFREE(strm, strm->state); - strm->state = NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} diff --git a/libs/zlibng/inffast.c b/libs/zlibng/inffast.c deleted file mode 100644 index 18ce570e9c..0000000000 --- a/libs/zlibng/inffast.c +++ /dev/null @@ -1,325 +0,0 @@ -/* inffast.c -- fast decoding - * Copyright (C) 1995-2017 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" -#include "inflate_p.h" -#include "functable.h" - - -/* Load 64 bits from IN and place the bytes at offset BITS in the result. */ -static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) { - uint64_t chunk; - memcpy(&chunk, in, sizeof(chunk)); - -#if BYTE_ORDER == LITTLE_ENDIAN - return chunk << bits; -#else - return ZSWAP64(chunk) << bits; -#endif -} -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= INFLATE_FAST_MIN_HAVE - strm->avail_out >= INFLATE_FAST_MIN_LEFT - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - On some architectures, it can be significantly faster (e.g. up to 1.2x - faster on x86_64) to load from strm->next_in 64 bits, or 8 bytes, at a - time, so INFLATE_FAST_MIN_HAVE == 8. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ -void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { - /* start: inflate()'s starting value for strm->avail_out */ - struct inflate_state *state; - z_const unsigned char *in; /* local strm->next_in */ - const unsigned char *last; /* have enough input while in < last */ - unsigned char *out; /* local strm->next_out */ - unsigned char *beg; /* inflate()'s initial strm->next_out */ - unsigned char *end; /* while out < end, enough space available */ - unsigned char *safe; /* can use chunkcopy provided out < safe */ -#ifdef INFLATE_STRICT - unsigned dmax; /* maximum distance from zlib header */ -#endif - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned wnext; /* window write index */ - unsigned char *window; /* allocated sliding window, if wsize != 0 */ - - /* hold is a local copy of strm->hold. By default, hold satisfies the same - invariants that strm->hold does, namely that (hold >> bits) == 0. This - invariant is kept by loading bits into hold one byte at a time, like: - - hold |= next_byte_of_input << bits; in++; bits += 8; - - If we need to ensure that bits >= 15 then this code snippet is simply - repeated. Over one iteration of the outermost do/while loop, this - happens up to six times (48 bits of input), as described in the NOTES - above. - - However, on some little endian architectures, it can be significantly - faster to load 64 bits once instead of 8 bits six times: - - if (bits <= 16) { - hold |= next_8_bytes_of_input << bits; in += 6; bits += 48; - } - - Unlike the simpler one byte load, shifting the next_8_bytes_of_input - by bits will overflow and lose those high bits, up to 2 bytes' worth. - The conservative estimate is therefore that we have read only 6 bytes - (48 bits). Again, as per the NOTES above, 48 bits is sufficient for the - rest of the iteration, and we will not need to load another 8 bytes. - - Inside this function, we no longer satisfy (hold >> bits) == 0, but - this is not problematic, even if that overflow does not land on an 8 bit - byte boundary. Those excess bits will eventually shift down lower as the - Huffman decoder consumes input, and when new input bits need to be loaded - into the bits variable, the same input bits will be or'ed over those - existing bits. A bitwise or is idempotent: (a | b | b) equals (a | b). - Note that we therefore write that load operation as "hold |= etc" and not - "hold += etc". - - Outside that loop, at the end of the function, hold is bitwise and'ed - with (1<hold >> state->bits) == 0. - */ - uint64_t hold; /* local strm->hold */ - unsigned bits; /* local strm->bits */ - code const *lcode; /* local strm->lencode */ - code const *dcode; /* local strm->distcode */ - unsigned lmask; /* mask for first level of length codes */ - unsigned dmask; /* mask for first level of distance codes */ - const code *here; /* retrieved table entry */ - unsigned op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - unsigned len; /* match length, unused bytes */ - unsigned dist; /* match distance */ - unsigned char *from; /* where to copy match from */ - - /* copy state to local variables */ - state = (struct inflate_state *)strm->state; - in = strm->next_in; - last = in + (strm->avail_in - (INFLATE_FAST_MIN_HAVE - 1)); - out = strm->next_out; - beg = out - (start - strm->avail_out); - end = out + (strm->avail_out - (INFLATE_FAST_MIN_LEFT - 1)); - safe = out + strm->avail_out; -#ifdef INFLATE_STRICT - dmax = state->dmax; -#endif - wsize = state->wsize; - whave = state->whave; - wnext = state->wnext; - window = state->window; - hold = state->hold; - bits = state->bits; - lcode = state->lencode; - dcode = state->distcode; - lmask = (1U << state->lenbits) - 1; - dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - do { - if (bits < 15) { - hold |= load_64_bits(in, bits); - in += 6; - bits += 48; - } - here = lcode + (hold & lmask); - dolen: - DROPBITS(here->bits); - op = here->op; - if (op == 0) { /* literal */ - Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here->val)); - *out++ = (unsigned char)(here->val); - } else if (op & 16) { /* length base */ - len = here->val; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold |= load_64_bits(in, bits); - in += 6; - bits += 48; - } - len += BITS(op); - DROPBITS(op); - Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold |= load_64_bits(in, bits); - in += 6; - bits += 48; - } - here = dcode + (hold & dmask); - dodist: - DROPBITS(here->bits); - op = here->op; - if (op & 16) { /* distance base */ - dist = here->val; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold |= load_64_bits(in, bits); - in += 6; - bits += 48; - } - dist += BITS(op); -#ifdef INFLATE_STRICT - if (dist > dmax) { - SET_BAD("invalid distance too far back"); - break; - } -#endif - DROPBITS(op); - Tracevv((stderr, "inflate: distance %u\n", dist)); - op = (unsigned)(out - beg); /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state->sane) { - SET_BAD("invalid distance too far back"); - break; - } -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - if (len <= op - whave) { - do { - *out++ = 0; - } while (--len); - continue; - } - len -= op - whave; - do { - *out++ = 0; - } while (--op > whave); - if (op == 0) { - from = out - dist; - do { - *out++ = *from++; - } while (--len); - continue; - } -#endif - } - from = window; - if (wnext == 0) { /* very common case */ - from += wsize - op; - } else if (wnext >= op) { /* contiguous in window */ - from += wnext - op; - } else { /* wrap around window */ - op -= wnext; - from += wsize - op; - if (op < len) { /* some from end of window */ - len -= op; - out = functable.chunkcopy_safe(out, from, op, safe); - from = window; /* more from start of window */ - op = wnext; - /* This (rare) case can create a situation where - the first chunkcopy below must be checked. - */ - } - } - if (op < len) { /* still need some from output */ - len -= op; - out = functable.chunkcopy_safe(out, from, op, safe); - out = functable.chunkunroll(out, &dist, &len); - out = functable.chunkcopy_safe(out, out - dist, len, safe); - } else { - out = functable.chunkcopy_safe(out, from, len, safe); - } - } else { - /* Whole reference is in range of current output. No range checks are - necessary because we start with room for at least 258 bytes of output, - so unroll and roundoff operations can write beyond `out+len` so long - as they stay within 258 bytes of `out`. - */ - if (dist >= len || dist >= state->chunksize) - out = functable.chunkcopy(out, out - dist, len); - else - out = functable.chunkmemset(out, dist, len); - } - } else if ((op & 64) == 0) { /* 2nd level distance code */ - here = dcode + here->val + BITS(op); - goto dodist; - } else { - SET_BAD("invalid distance code"); - break; - } - } else if ((op & 64) == 0) { /* 2nd level length code */ - here = lcode + here->val + BITS(op); - goto dolen; - } else if (op & 32) { /* end-of-block */ - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } else { - SET_BAD("invalid literal/length code"); - break; - } - } while (in < last && out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - in -= len; - bits -= len << 3; - hold &= (UINT64_C(1) << bits) - 1; - - /* update state and return */ - strm->next_in = in; - strm->next_out = out; - strm->avail_in = (unsigned)(in < last ? (INFLATE_FAST_MIN_HAVE - 1) + (last - in) - : (INFLATE_FAST_MIN_HAVE - 1) - (in - last)); - strm->avail_out = (unsigned)(out < end ? (INFLATE_FAST_MIN_LEFT - 1) + (end - out) - : (INFLATE_FAST_MIN_LEFT - 1) - (out - end)); - - Assert(bits <= 32, "Remaining bits greater than 32"); - state->hold = (uint32_t)hold; - state->bits = bits; - return; -} - -/* - inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - - Using bit fields for code structure - - Different op definition to avoid & for extra bits (do & for table bits) - - Three separate decoding do-loops for direct, window, and wnext == 0 - - Special case for distance > 1 copies to do overlapped load and store copy - - Explicit branch predictions (based on measured branch probabilities) - - Deferring match copy and interspersed it with decoding subsequent codes - - Swapping literal/length else - - Swapping window/direct else - - Larger unrolled copy loops (three is about right) - - Moving len -= 3 statement into middle of loop - */ diff --git a/libs/zlibng/inffast.h b/libs/zlibng/inffast.h deleted file mode 100644 index 179a65da60..0000000000 --- a/libs/zlibng/inffast.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef INFFAST_H_ -#define INFFAST_H_ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995-2003, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start); - -#define INFLATE_FAST_MIN_HAVE 8 -#define INFLATE_FAST_MIN_LEFT 258 - -#endif /* INFFAST_H_ */ diff --git a/libs/zlibng/inffixed_tbl.h b/libs/zlibng/inffixed_tbl.h deleted file mode 100644 index 7292fa06ec..0000000000 --- a/libs/zlibng/inffixed_tbl.h +++ /dev/null @@ -1,94 +0,0 @@ -/* inffixed_tbl.h -- table for decoding fixed codes - * Generated automatically by makefixed(). - */ - -/* WARNING: this file should *not* be used by applications. - * It is part of the implementation of this library and is - * subject to change. Applications should only use zlib.h. - */ - -static const code lenfix[512] = { - {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, - {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, - {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, - {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, - {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, - {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, - {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, - {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, - {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, - {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, - {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, - {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, - {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, - {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, - {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, - {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, - {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, - {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, - {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, - {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, - {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, - {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, - {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, - {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, - {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, - {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, - {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, - {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, - {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, - {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, - {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, - {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, - {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, - {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, - {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, - {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, - {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, - {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, - {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, - {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, - {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, - {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, - {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, - {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, - {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, - {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, - {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, - {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, - {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, - {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, - {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, - {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, - {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, - {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, - {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, - {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, - {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, - {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, - {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, - {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, - {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, - {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, - {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, - {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, - {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, - {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, - {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, - {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, - {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, - {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, - {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, - {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, - {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, - {0,9,255} -}; - -static const code distfix[32] = { - {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, - {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, - {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, - {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, - {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, - {22,5,193},{64,5,0} -}; diff --git a/libs/zlibng/inflate.c b/libs/zlibng/inflate.c deleted file mode 100644 index 5c30816ddf..0000000000 --- a/libs/zlibng/inflate.c +++ /dev/null @@ -1,1329 +0,0 @@ -/* inflate.c -- zlib decompression - * Copyright (C) 1995-2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" -#include "inflate_p.h" -#include "inffixed_tbl.h" -#include "functable.h" - -/* Architecture-specific hooks. */ -#ifdef S390_DFLTCC_INFLATE -# include "arch/s390/dfltcc_inflate.h" -#else -/* Memory management for the inflate state. Useful for allocating arch-specific extension blocks. */ -# define ZALLOC_STATE(strm, items, size) ZALLOC(strm, items, size) -# define ZFREE_STATE(strm, addr) ZFREE(strm, addr) -# define ZCOPY_STATE(dst, src, size) memcpy(dst, src, size) -/* Memory management for the window. Useful for allocation the aligned window. */ -# define ZALLOC_WINDOW(strm, items, size) ZALLOC(strm, items, size) -# define ZFREE_WINDOW(strm, addr) ZFREE(strm, addr) -/* Invoked at the end of inflateResetKeep(). Useful for initializing arch-specific extension blocks. */ -# define INFLATE_RESET_KEEP_HOOK(strm) do {} while (0) -/* Invoked at the beginning of inflatePrime(). Useful for updating arch-specific buffers. */ -# define INFLATE_PRIME_HOOK(strm, bits, value) do {} while (0) -/* Invoked at the beginning of each block. Useful for plugging arch-specific inflation code. */ -# define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0) -/* Returns whether zlib-ng should compute a checksum. Set to 0 if arch-specific inflation code already does that. */ -# define INFLATE_NEED_CHECKSUM(strm) 1 -/* Returns whether zlib-ng should update a window. Set to 0 if arch-specific inflation code already does that. */ -# define INFLATE_NEED_UPDATEWINDOW(strm) 1 -/* Invoked at the beginning of inflateMark(). Useful for updating arch-specific pointers and offsets. */ -# define INFLATE_MARK_HOOK(strm) do {} while (0) -/* Invoked at the beginning of inflateSyncPoint(). Useful for performing arch-specific state checks. */ -#define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0) -#endif - -/* function prototypes */ -static int inflateStateCheck(PREFIX3(stream) *strm); -static int updatewindow(PREFIX3(stream) *strm, const unsigned char *end, uint32_t copy); -static uint32_t syncsearch(uint32_t *have, const unsigned char *buf, uint32_t len); - -static int inflateStateCheck(PREFIX3(stream) *strm) { - struct inflate_state *state; - if (strm == NULL || strm->zalloc == NULL || strm->zfree == NULL) - return 1; - state = (struct inflate_state *)strm->state; - if (state == NULL || state->strm != strm || state->mode < HEAD || state->mode > SYNC) - return 1; - return 0; -} - -int32_t Z_EXPORT PREFIX(inflateResetKeep)(PREFIX3(stream) *strm) { - struct inflate_state *state; - - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - state = (struct inflate_state *)strm->state; - strm->total_in = strm->total_out = state->total = 0; - strm->msg = NULL; - if (state->wrap) /* to support ill-conceived Java test suite */ - strm->adler = state->wrap & 1; - state->mode = HEAD; - state->check = ADLER32_INITIAL_VALUE; - state->last = 0; - state->havedict = 0; - state->flags = -1; - state->dmax = 32768U; - state->head = NULL; - state->hold = 0; - state->bits = 0; - state->lencode = state->distcode = state->next = state->codes; - state->sane = 1; - state->back = -1; - INFLATE_RESET_KEEP_HOOK(strm); /* hook for IBM Z DFLTCC */ - Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -int32_t Z_EXPORT PREFIX(inflateReset)(PREFIX3(stream) *strm) { - struct inflate_state *state; - - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - state = (struct inflate_state *)strm->state; - state->wsize = 0; - state->whave = 0; - state->wnext = 0; - return PREFIX(inflateResetKeep)(strm); -} - -int32_t Z_EXPORT PREFIX(inflateReset2)(PREFIX3(stream) *strm, int32_t windowBits) { - int wrap; - struct inflate_state *state; - - /* get the state */ - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - state = (struct inflate_state *)strm->state; - - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } else { - wrap = (windowBits >> 4) + 5; -#ifdef GUNZIP - if (windowBits < 48) - windowBits &= 15; -#endif - } - - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) - return Z_STREAM_ERROR; - if (state->window != NULL && state->wbits != (unsigned)windowBits) { - ZFREE_WINDOW(strm, state->window); - state->window = NULL; - } - - /* update state and reset the rest of it */ - state->wrap = wrap; - state->wbits = (unsigned)windowBits; - return PREFIX(inflateReset)(strm); -} - -int32_t Z_EXPORT PREFIX(inflateInit2_)(PREFIX3(stream) *strm, int32_t windowBits, const char *version, int32_t stream_size) { - int32_t ret; - struct inflate_state *state; - -#if defined(X86_FEATURES) - x86_check_features(); -#elif defined(ARM_FEATURES) - arm_check_features(); -#endif - - if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != (int)(sizeof(PREFIX3(stream)))) - return Z_VERSION_ERROR; - if (strm == NULL) - return Z_STREAM_ERROR; - strm->msg = NULL; /* in case we return an error */ - if (strm->zalloc == NULL) { - strm->zalloc = zng_calloc; - strm->opaque = NULL; - } - if (strm->zfree == NULL) - strm->zfree = zng_cfree; - state = (struct inflate_state *) ZALLOC_STATE(strm, 1, sizeof(struct inflate_state)); - if (state == NULL) - return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state *)state; - state->strm = strm; - state->window = NULL; - state->mode = HEAD; /* to pass state test in inflateReset2() */ - state->chunksize = functable.chunksize(); - ret = PREFIX(inflateReset2)(strm, windowBits); - if (ret != Z_OK) { - ZFREE_STATE(strm, state); - strm->state = NULL; - } - return ret; -} - -int32_t Z_EXPORT PREFIX(inflateInit_)(PREFIX3(stream) *strm, const char *version, int32_t stream_size) { - return PREFIX(inflateInit2_)(strm, DEF_WBITS, version, stream_size); -} - -int32_t Z_EXPORT PREFIX(inflatePrime)(PREFIX3(stream) *strm, int32_t bits, int32_t value) { - struct inflate_state *state; - - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - INFLATE_PRIME_HOOK(strm, bits, value); /* hook for IBM Z DFLTCC */ - state = (struct inflate_state *)strm->state; - if (bits < 0) { - state->hold = 0; - state->bits = 0; - return Z_OK; - } - if (bits > 16 || state->bits + (unsigned int)bits > 32) - return Z_STREAM_ERROR; - value &= (1L << bits) - 1; - state->hold += (unsigned)value << state->bits; - state->bits += (unsigned int)bits; - return Z_OK; -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. This returns fixed tables from inffixed_tbl.h. - */ - -void Z_INTERNAL fixedtables(struct inflate_state *state) { - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -int Z_INTERNAL inflate_ensure_window(struct inflate_state *state) { - /* if it hasn't been done already, allocate space for the window */ - if (state->window == NULL) { - unsigned wsize = 1U << state->wbits; - state->window = (unsigned char *) ZALLOC_WINDOW(state->strm, wsize + state->chunksize, sizeof(unsigned char)); - if (state->window == Z_NULL) - return 1; - memset(state->window + wsize, 0, state->chunksize); - } - - /* if window not in use yet, initialize */ - if (state->wsize == 0) { - state->wsize = 1U << state->wbits; - state->wnext = 0; - state->whave = 0; - } - - return 0; -} - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -static int32_t updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t copy) { - struct inflate_state *state; - uint32_t dist; - - state = (struct inflate_state *)strm->state; - - if (inflate_ensure_window(state)) return 1; - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state->wsize) { - memcpy(state->window, end - state->wsize, state->wsize); - state->wnext = 0; - state->whave = state->wsize; - } else { - dist = state->wsize - state->wnext; - if (dist > copy) - dist = copy; - memcpy(state->window + state->wnext, end - copy, dist); - copy -= dist; - if (copy) { - memcpy(state->window, end - copy, copy); - state->wnext = copy; - state->whave = state->wsize; - } else { - state->wnext += dist; - if (state->wnext == state->wsize) - state->wnext = 0; - if (state->whave < state->wsize) - state->whave += dist; - } - } - return 0; -} - - -/* - Private macros for inflate() - Look in inflate_p.h for macros shared with inflateBack() -*/ - -/* Get a byte of input into the bit accumulator, or return from inflate() if there is no input available. */ -#define PULLBYTE() \ - do { \ - if (have == 0) goto inf_leave; \ - have--; \ - hold += ((unsigned)(*next++) << bits); \ - bits += 8; \ - } while (0) - -/* - inflate() uses a state machine to process as much input data and generate as - much output data as possible before returning. The state machine is - structured roughly as follows: - - for (;;) switch (state) { - ... - case STATEn: - if (not enough input data or output space to make progress) - return; - ... make progress ... - state = STATEm; - break; - ... - } - - so when inflate() is called again, the same case is attempted again, and - if the appropriate resources are provided, the machine proceeds to the - next state. The NEEDBITS() macro is usually the way the state evaluates - whether it can proceed or should return. NEEDBITS() does the return if - the requested bits are not available. The typical use of the BITS macros - is: - - NEEDBITS(n); - ... do something with BITS(n) ... - DROPBITS(n); - - where NEEDBITS(n) either returns from inflate() if there isn't enough - input left to load n bits into the accumulator, or it continues. BITS(n) - gives the low n bits in the accumulator. When done, DROPBITS(n) drops - the low n bits off the accumulator. INITBITS() clears the accumulator - and sets the number of available bits to zero. BYTEBITS() discards just - enough bits to put the accumulator on a byte boundary. After BYTEBITS() - and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. - - NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return - if there is no input available. The decoding of variable length codes uses - PULLBYTE() directly in order to pull just enough bytes to decode the next - code, and no more. - - Some states loop until they get enough input, making sure that enough - state information is maintained to continue the loop where it left off - if NEEDBITS() returns in the loop. For example, want, need, and keep - would all have to actually be part of the saved state in case NEEDBITS() - returns: - - case STATEw: - while (want < need) { - NEEDBITS(n); - keep[want++] = BITS(n); - DROPBITS(n); - } - state = STATEx; - case STATEx: - - As shown above, if the next state is also the next case, then the break - is omitted. - - A state may also return if there is not enough output space available to - complete that state. Those states are copying stored data, writing a - literal byte, and copying a matching string. - - When returning, a "goto inf_leave" is used to update the total counters, - update the check value, and determine whether any progress has been made - during that inflate() call in order to return the proper return code. - Progress is defined as a change in either strm->avail_in or strm->avail_out. - When there is a window, goto inf_leave will update the window with the last - output written. If a goto inf_leave occurs in the middle of decompression - and there is no window currently, goto inf_leave will create one and copy - output to the window for the next call of inflate(). - - In this implementation, the flush parameter of inflate() only affects the - return code (per zlib.h). inflate() always writes as much as possible to - strm->next_out, given the space available and the provided input--the effect - documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers - the allocation of and copying into a sliding window until necessary, which - provides the effect documented in zlib.h for Z_FINISH when the entire input - stream available. So the only thing the flush parameter actually does is: - when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it - will return Z_BUF_ERROR if it has not reached the end of the stream. - */ - -int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { - struct inflate_state *state; - const unsigned char *next; /* next input */ - unsigned char *put; /* next output */ - unsigned have, left; /* available input and output */ - uint32_t hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - uint32_t in, out; /* save starting available input and output */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char *from; /* where to copy match bytes from */ - code here; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int32_t ret; /* return code */ -#ifdef GUNZIP - unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ -#endif - static const uint16_t order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - if (inflateStateCheck(strm) || strm->next_out == NULL || - (strm->next_in == NULL && strm->avail_in != 0)) - return Z_STREAM_ERROR; - - state = (struct inflate_state *)strm->state; - if (state->mode == TYPE) /* skip check */ - state->mode = TYPEDO; - LOAD(); - in = have; - out = left; - ret = Z_OK; - for (;;) - switch (state->mode) { - case HEAD: - if (state->wrap == 0) { - state->mode = TYPEDO; - break; - } - NEEDBITS(16); -#ifdef GUNZIP - if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ - if (state->wbits == 0) - state->wbits = 15; - state->check = PREFIX(crc32)(0L, NULL, 0); - CRC2(state->check, hold); - INITBITS(); - state->mode = FLAGS; - break; - } - if (state->head != NULL) - state->head->done = -1; - if (!(state->wrap & 1) || /* check if zlib header allowed */ -#else - if ( -#endif - ((BITS(8) << 8) + (hold >> 8)) % 31) { - SET_BAD("incorrect header check"); - break; - } - if (BITS(4) != Z_DEFLATED) { - SET_BAD("unknown compression method"); - break; - } - DROPBITS(4); - len = BITS(4) + 8; - if (state->wbits == 0) - state->wbits = len; - if (len > 15 || len > state->wbits) { - SET_BAD("invalid window size"); - break; - } - state->dmax = 1U << len; - state->flags = 0; /* indicate zlib header */ - Tracev((stderr, "inflate: zlib header ok\n")); - strm->adler = state->check = ADLER32_INITIAL_VALUE; - state->mode = hold & 0x200 ? DICTID : TYPE; - INITBITS(); - break; -#ifdef GUNZIP - - case FLAGS: - NEEDBITS(16); - state->flags = (int)(hold); - if ((state->flags & 0xff) != Z_DEFLATED) { - SET_BAD("unknown compression method"); - break; - } - if (state->flags & 0xe000) { - SET_BAD("unknown header flags set"); - break; - } - if (state->head != NULL) - state->head->text = (int)((hold >> 8) & 1); - if ((state->flags & 0x0200) && (state->wrap & 4)) - CRC2(state->check, hold); - INITBITS(); - state->mode = TIME; - - case TIME: - NEEDBITS(32); - if (state->head != NULL) - state->head->time = hold; - if ((state->flags & 0x0200) && (state->wrap & 4)) - CRC4(state->check, hold); - INITBITS(); - state->mode = OS; - - case OS: - NEEDBITS(16); - if (state->head != NULL) { - state->head->xflags = (int)(hold & 0xff); - state->head->os = (int)(hold >> 8); - } - if ((state->flags & 0x0200) && (state->wrap & 4)) - CRC2(state->check, hold); - INITBITS(); - state->mode = EXLEN; - - case EXLEN: - if (state->flags & 0x0400) { - NEEDBITS(16); - state->length = (uint16_t)hold; - if (state->head != NULL) - state->head->extra_len = (uint16_t)hold; - if ((state->flags & 0x0200) && (state->wrap & 4)) - CRC2(state->check, hold); - INITBITS(); - } else if (state->head != NULL) { - state->head->extra = NULL; - } - state->mode = EXTRA; - - case EXTRA: - if (state->flags & 0x0400) { - copy = state->length; - if (copy > have) - copy = have; - if (copy) { - if (state->head != NULL && state->head->extra != NULL) { - len = state->head->extra_len - state->length; - memcpy(state->head->extra + len, next, - len + copy > state->head->extra_max ? - state->head->extra_max - len : copy); - } - if ((state->flags & 0x0200) && (state->wrap & 4)) - state->check = PREFIX(crc32)(state->check, next, copy); - have -= copy; - next += copy; - state->length -= copy; - } - if (state->length) - goto inf_leave; - } - state->length = 0; - state->mode = NAME; - - case NAME: - if (state->flags & 0x0800) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != NULL && state->head->name != NULL && state->length < state->head->name_max) - state->head->name[state->length++] = (unsigned char)len; - } while (len && copy < have); - if ((state->flags & 0x0200) && (state->wrap & 4)) - state->check = PREFIX(crc32)(state->check, next, copy); - have -= copy; - next += copy; - if (len) - goto inf_leave; - } else if (state->head != NULL) { - state->head->name = NULL; - } - state->length = 0; - state->mode = COMMENT; - - case COMMENT: - if (state->flags & 0x1000) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != NULL && state->head->comment != NULL - && state->length < state->head->comm_max) - state->head->comment[state->length++] = (unsigned char)len; - } while (len && copy < have); - if ((state->flags & 0x0200) && (state->wrap & 4)) - state->check = PREFIX(crc32)(state->check, next, copy); - have -= copy; - next += copy; - if (len) - goto inf_leave; - } else if (state->head != NULL) { - state->head->comment = NULL; - } - state->mode = HCRC; - - case HCRC: - if (state->flags & 0x0200) { - NEEDBITS(16); - if ((state->wrap & 4) && hold != (state->check & 0xffff)) { - SET_BAD("header crc mismatch"); - break; - } - INITBITS(); - } - if (state->head != NULL) { - state->head->hcrc = (int)((state->flags >> 9) & 1); - state->head->done = 1; - } - strm->adler = state->check = PREFIX(crc32)(0L, NULL, 0); - state->mode = TYPE; - break; -#endif - case DICTID: - NEEDBITS(32); - strm->adler = state->check = ZSWAP32(hold); - INITBITS(); - state->mode = DICT; - - case DICT: - if (state->havedict == 0) { - RESTORE(); - return Z_NEED_DICT; - } - strm->adler = state->check = ADLER32_INITIAL_VALUE; - state->mode = TYPE; - - case TYPE: - if (flush == Z_BLOCK || flush == Z_TREES) - goto inf_leave; - - case TYPEDO: - /* determine and dispatch block type */ - INFLATE_TYPEDO_HOOK(strm, flush); /* hook for IBM Z DFLTCC */ - if (state->last) { - BYTEBITS(); - state->mode = CHECK; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); - state->mode = LEN_; /* decode codes */ - if (flush == Z_TREES) { - DROPBITS(2); - goto inf_leave; - } - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - SET_BAD("invalid block type"); - } - DROPBITS(2); - break; - - case STORED: - /* get and verify stored block length */ - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - SET_BAD("invalid stored block lengths"); - break; - } - state->length = (uint16_t)hold; - Tracev((stderr, "inflate: stored length %u\n", state->length)); - INITBITS(); - state->mode = COPY_; - if (flush == Z_TREES) - goto inf_leave; - - case COPY_: - state->mode = COPY; - - case COPY: - /* copy stored block from input to output */ - copy = state->length; - if (copy) { - if (copy > have) copy = have; - if (copy > left) copy = left; - if (copy == 0) goto inf_leave; - memcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - break; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - - case TABLE: - /* get dynamic table entries descriptor */ - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - SET_BAD("too many length or distance symbols"); - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - state->have = 0; - state->mode = LENLENS; - - case LENLENS: - /* get code length code lengths (not a typo) */ - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (uint16_t)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (const code *)(state->next); - state->lenbits = 7; - ret = zng_inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); - if (ret) { - SET_BAD("invalid code lengths set"); - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - state->have = 0; - state->mode = CODELENS; - - case CODELENS: - /* get length and distance code code lengths */ - while (state->have < state->nlen + state->ndist) { - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if (here.bits <= bits) break; - PULLBYTE(); - } - if (here.val < 16) { - DROPBITS(here.bits); - state->lens[state->have++] = here.val; - } else { - if (here.val == 16) { - NEEDBITS(here.bits + 2); - DROPBITS(here.bits); - if (state->have == 0) { - SET_BAD("invalid bit length repeat"); - break; - } - len = state->lens[state->have - 1]; - copy = 3 + BITS(2); - DROPBITS(2); - } else if (here.val == 17) { - NEEDBITS(here.bits + 3); - DROPBITS(here.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } else { - NEEDBITS(here.bits + 7); - DROPBITS(here.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - SET_BAD("invalid bit length repeat"); - break; - } - while (copy) { - --copy; - state->lens[state->have++] = (uint16_t)len; - } - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) - break; - - /* check for end-of-block code (better have one) */ - if (state->lens[256] == 0) { - SET_BAD("invalid code -- missing end-of-block"); - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state->next = state->codes; - state->lencode = (const code *)(state->next); - state->lenbits = 9; - ret = zng_inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); - if (ret) { - SET_BAD("invalid literal/lengths set"); - break; - } - state->distcode = (const code *)(state->next); - state->distbits = 6; - ret = zng_inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - SET_BAD("invalid distances set"); - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN_; - if (flush == Z_TREES) - goto inf_leave; - - case LEN_: - state->mode = LEN; - - case LEN: - /* use inflate_fast() if we have enough input and output */ - if (have >= INFLATE_FAST_MIN_HAVE && left >= INFLATE_FAST_MIN_LEFT) { - RESTORE(); - zng_inflate_fast(strm, out); - LOAD(); - if (state->mode == TYPE) - state->back = -1; - break; - } - state->back = 0; - - /* get a literal, length, or end-of-block code */ - for (;;) { - here = state->lencode[BITS(state->lenbits)]; - if (here.bits <= bits) - break; - PULLBYTE(); - } - if (here.op && (here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)last.bits + (unsigned)here.bits <= bits) - break; - PULLBYTE(); - } - DROPBITS(last.bits); - state->back += last.bits; - } - DROPBITS(here.bits); - state->back += here.bits; - state->length = here.val; - - /* process literal */ - if ((int)(here.op) == 0) { - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - state->mode = LIT; - break; - } - - /* process end of block */ - if (here.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->back = -1; - state->mode = TYPE; - break; - } - - /* invalid code */ - if (here.op & 64) { - SET_BAD("invalid literal/length code"); - break; - } - - /* length code */ - state->extra = (here.op & 15); - state->mode = LENEXT; - - case LENEXT: - /* get extra bits, if any */ - if (state->extra) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - state->back += state->extra; - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - state->was = state->length; - state->mode = DIST; - - case DIST: - /* get distance code */ - for (;;) { - here = state->distcode[BITS(state->distbits)]; - if (here.bits <= bits) - break; - PULLBYTE(); - } - if ((here.op & 0xf0) == 0) { - last = here; - for (;;) { - here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)last.bits + (unsigned)here.bits <= bits) - break; - PULLBYTE(); - } - DROPBITS(last.bits); - state->back += last.bits; - } - DROPBITS(here.bits); - state->back += here.bits; - if (here.op & 64) { - SET_BAD("invalid distance code"); - break; - } - state->offset = here.val; - state->extra = (here.op & 15); - state->mode = DISTEXT; - - case DISTEXT: - /* get distance extra bits, if any */ - if (state->extra) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - state->back += state->extra; - } -#ifdef INFLATE_STRICT - if (state->offset > state->dmax) { - SET_BAD("invalid distance too far back"); - break; - } -#endif - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - state->mode = MATCH; - - case MATCH: - /* copy match from window to output */ - if (left == 0) goto inf_leave; - copy = out - left; - if (state->offset > copy) { /* copy from window */ - copy = state->offset - copy; - if (copy > state->whave) { - if (state->sane) { - SET_BAD("invalid distance too far back"); - break; - } -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - Trace((stderr, "inflate.c too far\n")); - copy -= state->whave; - if (copy > state->length) - copy = state->length; - if (copy > left) - copy = left; - left -= copy; - state->length -= copy; - do { - *put++ = 0; - } while (--copy); - if (state->length == 0) - state->mode = LEN; - break; -#endif - } - if (copy > state->wnext) { - copy -= state->wnext; - from = state->window + (state->wsize - copy); - } else { - from = state->window + (state->wnext - copy); - } - if (copy > state->length) - copy = state->length; - if (copy > left) - copy = left; - - put = functable.chunkcopy_safe(put, from, copy, put + left); - } else { /* copy from output */ - copy = state->length; - if (copy > left) - copy = left; - - put = functable.chunkmemset_safe(put, state->offset, copy, left); - } - left -= copy; - state->length -= copy; - if (state->length == 0) - state->mode = LEN; - break; - - case LIT: - if (left == 0) - goto inf_leave; - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - - case CHECK: - if (state->wrap) { - NEEDBITS(32); - out -= left; - strm->total_out += out; - state->total += out; - if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4) && out) - strm->adler = state->check = UPDATE(state->check, put - out, out); - out = left; - if ((state->wrap & 4) && ( -#ifdef GUNZIP - state->flags ? hold : -#endif - ZSWAP32(hold)) != state->check) { - SET_BAD("incorrect data check"); - break; - } - INITBITS(); - Tracev((stderr, "inflate: check matches trailer\n")); - } -#ifdef GUNZIP - state->mode = LENGTH; - - case LENGTH: - if (state->wrap && state->flags) { - NEEDBITS(32); - if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { - SET_BAD("incorrect length check"); - break; - } - INITBITS(); - Tracev((stderr, "inflate: length matches trailer\n")); - } -#endif - state->mode = DONE; - - case DONE: - /* inflate stream terminated properly */ - ret = Z_STREAM_END; - goto inf_leave; - - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - - case MEM: - return Z_MEM_ERROR; - - case SYNC: - - default: /* can't happen, but makes compilers happy */ - return Z_STREAM_ERROR; - } - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - inf_leave: - RESTORE(); - if (INFLATE_NEED_UPDATEWINDOW(strm) && - (state->wsize || (out != strm->avail_out && state->mode < BAD && - (state->mode < CHECK || flush != Z_FINISH)))) { - if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - } - in -= strm->avail_in; - out -= strm->avail_out; - strm->total_in += in; - strm->total_out += out; - state->total += out; - if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4) && out) - strm->adler = state->check = UPDATE(state->check, strm->next_out - out, out); - strm->data_type = (int)state->bits + (state->last ? 64 : 0) + - (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); - if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) - ret = Z_BUF_ERROR; - return ret; -} - -int32_t Z_EXPORT PREFIX(inflateEnd)(PREFIX3(stream) *strm) { - struct inflate_state *state; - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - state = (struct inflate_state *)strm->state; - if (state->window != NULL) - ZFREE_WINDOW(strm, state->window); - ZFREE_STATE(strm, strm->state); - strm->state = NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} - -int32_t Z_EXPORT PREFIX(inflateGetDictionary)(PREFIX3(stream) *strm, uint8_t *dictionary, uint32_t *dictLength) { - struct inflate_state *state; - - /* check state */ - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - state = (struct inflate_state *)strm->state; - - /* copy dictionary */ - if (state->whave && dictionary != NULL) { - memcpy(dictionary, state->window + state->wnext, state->whave - state->wnext); - memcpy(dictionary + state->whave - state->wnext, state->window, state->wnext); - } - if (dictLength != NULL) - *dictLength = state->whave; - return Z_OK; -} - -int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8_t *dictionary, uint32_t dictLength) { - struct inflate_state *state; - unsigned long dictid; - int32_t ret; - - /* check state */ - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - state = (struct inflate_state *)strm->state; - if (state->wrap != 0 && state->mode != DICT) - return Z_STREAM_ERROR; - - /* check for correct dictionary identifier */ - if (state->mode == DICT) { - dictid = functable.adler32(ADLER32_INITIAL_VALUE, dictionary, dictLength); - if (dictid != state->check) - return Z_DATA_ERROR; - } - - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - ret = updatewindow(strm, dictionary + dictLength, dictLength); - if (ret) { - state->mode = MEM; - return Z_MEM_ERROR; - } - state->havedict = 1; - Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} - -int32_t Z_EXPORT PREFIX(inflateGetHeader)(PREFIX3(stream) *strm, PREFIX(gz_headerp) head) { - struct inflate_state *state; - - /* check state */ - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - state = (struct inflate_state *)strm->state; - if ((state->wrap & 2) == 0) - return Z_STREAM_ERROR; - - /* save header structure */ - state->head = head; - head->done = 0; - return Z_OK; -} - -/* - Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found - or when out of input. When called, *have is the number of pattern bytes - found in order so far, in 0..3. On return *have is updated to the new - state. If on return *have equals four, then the pattern was found and the - return value is how many bytes were read including the last byte of the - pattern. If *have is less than four, then the pattern has not been found - yet and the return value is len. In the latter case, syncsearch() can be - called again with more data and the *have state. *have is initialized to - zero for the first call. - */ -static uint32_t syncsearch(uint32_t *have, const uint8_t *buf, uint32_t len) { - uint32_t got, next; - - got = *have; - next = 0; - while (next < len && got < 4) { - if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) - got++; - else if (buf[next]) - got = 0; - else - got = 4 - got; - next++; - } - *have = got; - return next; -} - -int32_t Z_EXPORT PREFIX(inflateSync)(PREFIX3(stream) *strm) { - unsigned len; /* number of bytes to look at or looked at */ - int flags; /* temporary to save header status */ - size_t in, out; /* temporary to save total_in and total_out */ - unsigned char buf[4]; /* to restore bit buffer to byte string */ - struct inflate_state *state; - - /* check parameters */ - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - state = (struct inflate_state *)strm->state; - if (strm->avail_in == 0 && state->bits < 8) - return Z_BUF_ERROR; - - /* if first time, start search in bit buffer */ - if (state->mode != SYNC) { - state->mode = SYNC; - state->hold <<= state->bits & 7; - state->bits -= state->bits & 7; - len = 0; - while (state->bits >= 8) { - buf[len++] = (unsigned char)(state->hold); - state->hold >>= 8; - state->bits -= 8; - } - state->have = 0; - syncsearch(&(state->have), buf, len); - } - - /* search available input */ - len = syncsearch(&(state->have), strm->next_in, strm->avail_in); - strm->avail_in -= len; - strm->next_in += len; - strm->total_in += len; - - /* return no joy or set up to restart inflate() on a new block */ - if (state->have != 4) - return Z_DATA_ERROR; - if (state->flags == -1) - state->wrap = 0; /* if no header yet, treat as raw */ - else - state->wrap &= ~4; /* no point in computing a check value now */ - flags = state->flags; - in = strm->total_in; - out = strm->total_out; - PREFIX(inflateReset)(strm); - strm->total_in = in; - strm->total_out = out; - state->flags = flags; - state->mode = TYPE; - return Z_OK; -} - -/* - Returns true if inflate is currently at the end of a block generated by - Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - implementation to provide an additional safety check. PPP uses - Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored - block. When decompressing, PPP checks that at the end of input packet, - inflate is waiting for these length bytes. - */ -int32_t Z_EXPORT PREFIX(inflateSyncPoint)(PREFIX3(stream) *strm) { - struct inflate_state *state; - - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - INFLATE_SYNC_POINT_HOOK(strm); - state = (struct inflate_state *)strm->state; - return state->mode == STORED && state->bits == 0; -} - -int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *source) { - struct inflate_state *state; - struct inflate_state *copy; - unsigned char *window; - unsigned wsize; - - /* check input */ - if (inflateStateCheck(source) || dest == NULL) - return Z_STREAM_ERROR; - state = (struct inflate_state *)source->state; - - /* allocate space */ - copy = (struct inflate_state *)ZALLOC_STATE(source, 1, sizeof(struct inflate_state)); - if (copy == NULL) - return Z_MEM_ERROR; - window = NULL; - if (state->window != NULL) { - window = (unsigned char *)ZALLOC_WINDOW(source, 1U << state->wbits, sizeof(unsigned char)); - if (window == NULL) { - ZFREE_STATE(source, copy); - return Z_MEM_ERROR; - } - } - - /* copy state */ - memcpy((void *)dest, (void *)source, sizeof(PREFIX3(stream))); - ZCOPY_STATE((void *)copy, (void *)state, sizeof(struct inflate_state)); - copy->strm = dest; - if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { - copy->lencode = copy->codes + (state->lencode - state->codes); - copy->distcode = copy->codes + (state->distcode - state->codes); - } - copy->next = copy->codes + (state->next - state->codes); - if (window != NULL) { - wsize = 1U << state->wbits; - memcpy(window, state->window, wsize); - } - copy->window = window; - dest->state = (struct internal_state *)copy; - return Z_OK; -} - -int32_t Z_EXPORT PREFIX(inflateUndermine)(PREFIX3(stream) *strm, int32_t subvert) { - struct inflate_state *state; - - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - state = (struct inflate_state *)strm->state; -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - state->sane = !subvert; - return Z_OK; -#else - (void)subvert; - state->sane = 1; - return Z_DATA_ERROR; -#endif -} - -int32_t Z_EXPORT PREFIX(inflateValidate)(PREFIX3(stream) *strm, int32_t check) { - struct inflate_state *state; - - if (inflateStateCheck(strm)) - return Z_STREAM_ERROR; - state = (struct inflate_state *)strm->state; - if (check && state->wrap) - state->wrap |= 4; - else - state->wrap &= ~4; - return Z_OK; -} - -long Z_EXPORT PREFIX(inflateMark)(PREFIX3(stream) *strm) { - struct inflate_state *state; - - if (inflateStateCheck(strm)) - return -65536; - INFLATE_MARK_HOOK(strm); /* hook for IBM Z DFLTCC */ - state = (struct inflate_state *)strm->state; - return (long)(((unsigned long)((long)state->back)) << 16) + - (state->mode == COPY ? state->length : - (state->mode == MATCH ? state->was - state->length : 0)); -} - -unsigned long Z_EXPORT PREFIX(inflateCodesUsed)(PREFIX3(stream) *strm) { - struct inflate_state *state; - if (strm == NULL || strm->state == NULL) - return (unsigned long)-1; - state = (struct inflate_state *)strm->state; - return (unsigned long)(state->next - state->codes); -} diff --git a/libs/zlibng/inflate.h b/libs/zlibng/inflate.h deleted file mode 100644 index a427494659..0000000000 --- a/libs/zlibng/inflate.h +++ /dev/null @@ -1,134 +0,0 @@ -/* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef INFLATE_H_ -#define INFLATE_H_ - -/* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). - NO_GZIP would be used to avoid linking in the crc code when it is not needed. - For shared libraries, gzip decoding should be left enabled. */ -#ifndef NO_GZIP -# define GUNZIP -#endif - -/* Possible inflate modes between inflate() calls */ -typedef enum { - HEAD = 16180, /* i: waiting for magic header */ - FLAGS, /* i: waiting for method and flags (gzip) */ - TIME, /* i: waiting for modification time (gzip) */ - OS, /* i: waiting for extra flags and operating system (gzip) */ - EXLEN, /* i: waiting for extra length (gzip) */ - EXTRA, /* i: waiting for extra bytes (gzip) */ - NAME, /* i: waiting for end of file name (gzip) */ - COMMENT, /* i: waiting for end of comment (gzip) */ - HCRC, /* i: waiting for header crc (gzip) */ - DICTID, /* i: waiting for dictionary check value */ - DICT, /* waiting for inflateSetDictionary() call */ - TYPE, /* i: waiting for type bits, including last-flag bit */ - TYPEDO, /* i: same, but skip check to exit inflate on new block */ - STORED, /* i: waiting for stored size (length and complement) */ - COPY_, /* i/o: same as COPY below, but only first time in */ - COPY, /* i/o: waiting for input or output to copy stored block */ - TABLE, /* i: waiting for dynamic block table lengths */ - LENLENS, /* i: waiting for code length code lengths */ - CODELENS, /* i: waiting for length/lit and distance code lengths */ - LEN_, /* i: same as LEN below, but only first time in */ - LEN, /* i: waiting for length/lit/eob code */ - LENEXT, /* i: waiting for length extra bits */ - DIST, /* i: waiting for distance code */ - DISTEXT, /* i: waiting for distance extra bits */ - MATCH, /* o: waiting for output space to copy string */ - LIT, /* o: waiting for output space to write literal */ - CHECK, /* i: waiting for 32-bit check value */ - LENGTH, /* i: waiting for 32-bit length (gzip) */ - DONE, /* finished check, done -- remain here until reset */ - BAD, /* got a data error -- remain here until reset */ - MEM, /* got an inflate() memory error -- remain here until reset */ - SYNC /* looking for synchronization bytes to restart inflate() */ -} inflate_mode; - -/* - State transitions between above modes - - - (most modes can go to BAD or MEM on error -- not shown for clarity) - - Process header: - HEAD -> (gzip) or (zlib) or (raw) - (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> - HCRC -> TYPE - (zlib) -> DICTID or TYPE - DICTID -> DICT -> TYPE - (raw) -> TYPEDO - Read deflate blocks: - TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK - STORED -> COPY_ -> COPY -> TYPE - TABLE -> LENLENS -> CODELENS -> LEN_ - LEN_ -> LEN - Read deflate codes in fixed or dynamic block: - LEN -> LENEXT or LIT or TYPE - LENEXT -> DIST -> DISTEXT -> MATCH -> LEN - LIT -> LEN - Process trailer: - CHECK -> LENGTH -> DONE - */ - -/* State maintained between inflate() calls -- approximately 7K bytes, not - including the allocated sliding window, which is up to 32K bytes. */ -struct inflate_state { - PREFIX3(stream) *strm; /* pointer back to this zlib stream */ - inflate_mode mode; /* current inflate mode */ - int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip, - bit 2 true to validate check value */ - int havedict; /* true if dictionary provided */ - int flags; /* gzip header method and flags, 0 if zlib, or - -1 if raw or no header yet */ - unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ - unsigned long check; /* protected copy of check value */ - unsigned long total; /* protected copy of output count */ - PREFIX(gz_headerp) head; /* where to save gzip header information */ - /* sliding window */ - unsigned wbits; /* log base 2 of requested window size */ - uint32_t wsize; /* window size or zero if not using window */ - uint32_t whave; /* valid bytes in the window */ - uint32_t wnext; /* window write index */ - unsigned char *window; /* allocated sliding window, if needed */ - /* bit accumulator */ - uint32_t hold; /* input bit accumulator */ - unsigned bits; /* number of bits in "in" */ - /* for string and stored block copying */ - uint32_t length; /* literal or length of data to copy */ - unsigned offset; /* distance back to copy string from */ - /* for table and code decoding */ - unsigned extra; /* extra bits needed */ - /* fixed and dynamic code tables */ - code const *lencode; /* starting table for length/literal codes */ - code const *distcode; /* starting table for distance codes */ - unsigned lenbits; /* index bits for lencode */ - unsigned distbits; /* index bits for distcode */ - /* dynamic table building */ - unsigned ncode; /* number of code length code lengths */ - unsigned nlen; /* number of length code lengths */ - unsigned ndist; /* number of distance code lengths */ - uint32_t have; /* number of code lengths in lens[] */ - code *next; /* next available space in codes[] */ - uint16_t lens[320]; /* temporary storage for code lengths */ - uint16_t work[288]; /* work area for code table building */ - code codes[ENOUGH]; /* space for code tables */ - int sane; /* if false, allow invalid distance too far */ - int back; /* bits back of last unprocessed length/lit */ - unsigned was; /* initial length of match */ - uint32_t chunksize; /* size of memory copying chunk */ -}; - -int Z_INTERNAL inflate_ensure_window(struct inflate_state *state); -void Z_INTERNAL fixedtables(struct inflate_state *state); - -#endif /* INFLATE_H_ */ diff --git a/libs/zlibng/inflate_p.h b/libs/zlibng/inflate_p.h deleted file mode 100644 index 76fe2dccbe..0000000000 --- a/libs/zlibng/inflate_p.h +++ /dev/null @@ -1,101 +0,0 @@ -/* inflate_p.h -- Private inline functions and macros shared with more than one deflate method - * - */ - -#ifndef INFLATE_P_H -#define INFLATE_P_H - -/* - * Macros shared by inflate() and inflateBack() - */ - -/* check function to use adler32() for zlib or crc32() for gzip */ -#ifdef GUNZIP -# define UPDATE(check, buf, len) \ - (state->flags ? PREFIX(crc32)(check, buf, len) : functable.adler32(check, buf, len)) -#else -# define UPDATE(check, buf, len) functable.adler32(check, buf, len) -#endif - -/* check macros for header crc */ -#ifdef GUNZIP -# define CRC2(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - check = PREFIX(crc32)(check, hbuf, 2); \ - } while (0) - -# define CRC4(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - hbuf[2] = (unsigned char)((word) >> 16); \ - hbuf[3] = (unsigned char)((word) >> 24); \ - check = PREFIX(crc32)(check, hbuf, 4); \ - } while (0) -#endif - -/* Load registers with state in inflate() for speed */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Restore state from registers in inflate() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = (z_const unsigned char *)next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Ensure that there is at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflate()/inflateBack(). */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - (hold & ((1U << (unsigned)(n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -#endif - -/* Set mode=BAD and prepare error message */ -#define SET_BAD(errmsg) \ - do { \ - state->mode = BAD; \ - strm->msg = (char *)errmsg; \ - } while (0) diff --git a/libs/zlibng/inftrees.c b/libs/zlibng/inftrees.c deleted file mode 100644 index faf1d249d6..0000000000 --- a/libs/zlibng/inftrees.c +++ /dev/null @@ -1,297 +0,0 @@ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "zutil.h" -#include "inftrees.h" - -#define MAXBITS 15 - -const char PREFIX(inflate_copyright)[] = " inflate 1.2.11.f Copyright 1995-2016 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* - Build a set of tables to decode the provided canonical Huffman code. - The code lengths are lens[0..codes-1]. The result starts at *table, - whose indices are 0..2^bits-1. work is a writable array of at least - lens shorts, which is used as a work area. type is the type of code - to be generated, CODES, LENS, or DISTS. On return, zero is success, - -1 is an invalid code, and +1 means that ENOUGH isn't enough. table - on return points to the next available entry's address. bits is the - requested root table index bits, and on return it is the actual root - table index bits. It will differ if the request is greater than the - longest code or if it is less than the shortest code. - */ -int Z_INTERNAL zng_inflate_table(codetype type, uint16_t *lens, unsigned codes, - code * *table, unsigned *bits, uint16_t *work) { - unsigned len; /* a code's length in bits */ - unsigned sym; /* index of code symbols */ - unsigned min, max; /* minimum and maximum code lengths */ - unsigned root; /* number of index bits for root table */ - unsigned curr; /* number of index bits for current table */ - unsigned drop; /* code bits to drop for sub-table */ - int left; /* number of prefix codes available */ - unsigned used; /* code entries in table used */ - unsigned huff; /* Huffman code */ - unsigned incr; /* for incrementing code, index */ - unsigned fill; /* index for replicating entries */ - unsigned low; /* low bits for current root entry */ - unsigned mask; /* mask for low root bits */ - code here; /* table entry for duplication */ - code *next; /* next available space in table */ - const uint16_t *base; /* base value table to use */ - const uint16_t *extra; /* extra bits table to use */ - unsigned match; /* use base and extra for symbol >= match */ - uint16_t count[MAXBITS+1]; /* number of codes of each length */ - uint16_t offs[MAXBITS+1]; /* offsets in table for each length */ - static const uint16_t lbase[31] = { /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - static const uint16_t lext[31] = { /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202}; - static const uint16_t dbase[32] = { /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0}; - static const uint16_t dext[32] = { /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64}; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) - count[len] = 0; - for (sym = 0; sym < codes; sym++) - count[lens[sym]]++; - - /* bound code lengths, force root to be within code lengths */ - root = *bits; - for (max = MAXBITS; max >= 1; max--) - if (count[max] != 0) break; - if (root > max) root = max; - if (max == 0) { /* no symbols to code at all */ - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)1; - here.val = (uint16_t)0; - *(*table)++ = here; /* make a table to force an error */ - *(*table)++ = here; - *bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) - if (count[min] != 0) break; - if (root < min) root = min; - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) return -1; /* over-subscribed */ - } - if (left > 0 && (type == CODES || max != 1)) - return -1; /* incomplete set */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + count[len]; - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) - if (lens[sym] != 0) work[offs[lens[sym]]++] = (uint16_t)sym; - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - switch (type) { - case CODES: - base = extra = work; /* dummy value--not used */ - match = 20; - break; - case LENS: - base = lbase; - extra = lext; - match = 257; - break; - default: /* DISTS */ - base = dbase; - extra = dext; - match = 0; - } - - /* initialize state for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = *table; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = (unsigned)(-1); /* trigger new sub-table when len > root */ - used = 1U << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if ((type == LENS && used > ENOUGH_LENS) || - (type == DISTS && used > ENOUGH_DISTS)) - return 1; - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - here.bits = (unsigned char)(len - drop); - if (work[sym] + 1U < match) { - here.op = (unsigned char)0; - here.val = work[sym]; - } else if (work[sym] >= match) { - here.op = (unsigned char)(extra[work[sym] - match]); - here.val = base[work[sym] - match]; - } else { - here.op = (unsigned char)(32 + 64); /* end of block */ - here.val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1U << (len - drop); - fill = 1U << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - next[(huff >> drop) + fill] = here; - } while (fill != 0); - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } else { - huff = 0; - } - - /* go to next symbol, update count, len */ - sym++; - if (--(count[len]) == 0) { - if (len == max) - break; - len = lens[work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) != low) { - /* if first time, transition to sub-tables */ - if (drop == 0) - drop = root; - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = (int)(1 << curr); - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) - break; - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1U << curr; - if ((type == LENS && used > ENOUGH_LENS) || (type == DISTS && used > ENOUGH_DISTS)) - return 1; - - /* point entry in root table to sub-table */ - low = huff & mask; - (*table)[low].op = (unsigned char)curr; - (*table)[low].bits = (unsigned char)root; - (*table)[low].val = (uint16_t)(next - *table); - } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff != 0) { - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)(len - drop); - here.val = (uint16_t)0; - next[huff] = here; - } - - /* set return parameters */ - *table += used; - *bits = root; - return 0; -} diff --git a/libs/zlibng/inftrees.h b/libs/zlibng/inftrees.h deleted file mode 100644 index 7758737c2e..0000000000 --- a/libs/zlibng/inftrees.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef INFTREES_H_ -#define INFTREES_H_ - -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2005, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Structure for decoding tables. Each entry provides either the - information needed to do the operation requested by the code that - indexed that table entry, or it provides a pointer to another - table that indexes more bits of the code. op indicates whether - the entry is a pointer to another table, a literal, a length or - distance, an end-of-block, or an invalid code. For a table - pointer, the low four bits of op is the number of index bits of - that table. For a length or distance, the low four bits of op - is the number of extra bits to get after the code. bits is - the number of bits in this code or part of the code to drop off - of the bit buffer. val is the actual byte to output in the case - of a literal, the base length or distance, or the offset from - the current table to the next table. Each entry is four bytes. */ -typedef struct { - unsigned char op; /* operation, extra bits, table bits */ - unsigned char bits; /* bits in this part of the code */ - uint16_t val; /* offset in table or code value */ -} code; - -/* op values as set by inflate_table(): - 00000000 - literal - 0000tttt - table link, tttt != 0 is the number of table index bits - 0001eeee - length or distance, eeee is the number of extra bits - 01100000 - end of block - 01000000 - invalid code - */ - -/* Maximum size of the dynamic table. The maximum number of code structures is - 1444, which is the sum of 852 for literal/length codes and 592 for distance - codes. These values were found by exhaustive searches using the program - examples/enough.c found in the zlib distribtution. The arguments to that - program are the number of symbols, the initial root table size, and the - maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 30 6 15" for distance codes returns 592. - The initial root table size (9 or 6) is found in the fifth argument of the - inflate_table() calls in inflate.c and infback.c. If the root table size is - changed, then these maximum sizes would be need to be recalculated and - updated. */ -#define ENOUGH_LENS 852 -#define ENOUGH_DISTS 592 -#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) - -/* Type of code to build for inflate_table() */ -typedef enum { - CODES, - LENS, - DISTS -} codetype; - -int Z_INTERNAL zng_inflate_table (codetype type, uint16_t *lens, unsigned codes, - code * *table, unsigned *bits, uint16_t *work); - -#endif /* INFTREES_H_ */ diff --git a/libs/zlibng/insert_string.c b/libs/zlibng/insert_string.c deleted file mode 100644 index 4ddf9ae5db..0000000000 --- a/libs/zlibng/insert_string.c +++ /dev/null @@ -1,25 +0,0 @@ -/* insert_string_c -- insert_string variant for c - * - * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - */ - -#include "zbuild.h" -#include "deflate.h" - -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. - */ -#define HASH_SLIDE 16 // Number of bits to slide hash - -#define UPDATE_HASH(s, h, val) \ - h = ((val * 2654435761U) >> HASH_SLIDE); - -#define INSERT_STRING insert_string_c -#define QUICK_INSERT_STRING quick_insert_string_c - -#include "insert_string_tpl.h" diff --git a/libs/zlibng/insert_string_tpl.h b/libs/zlibng/insert_string_tpl.h deleted file mode 100644 index 9796e5196c..0000000000 --- a/libs/zlibng/insert_string_tpl.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef INSERT_STRING_H_ -#define INSERT_STRING_H_ - -/* insert_string.h -- Private insert_string functions shared with more than - * one insert string implementation - * - * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - * - * Copyright (C) 2013 Intel Corporation. All rights reserved. - * Authors: - * Wajdi Feghali - * Jim Guilford - * Vinodh Gopal - * Erdinc Ozturk - * Jim Kukunas - * - * Portions are Copyright (C) 2016 12Sided Technology, LLC. - * Author: - * Phil Vachon - * - * For conditions of distribution and use, see copyright notice in zlib.h - * - */ - -/* =========================================================================== - * Quick insert string str in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - */ -Z_INTERNAL Pos QUICK_INSERT_STRING(deflate_state *const s, const uint32_t str) { - Pos head; - uint8_t *strstart = s->window + str; - uint32_t val, hm, h = 0; - -#ifdef UNALIGNED_OK - val = *(uint32_t *)(strstart); -#else - val = ((uint32_t)(strstart[0])); - val |= ((uint32_t)(strstart[1]) << 8); - val |= ((uint32_t)(strstart[2]) << 16); - val |= ((uint32_t)(strstart[3]) << 24); -#endif - - UPDATE_HASH(s, h, val); - hm = h & HASH_MASK; - - head = s->head[hm]; - if (LIKELY(head != str)) { - s->prev[str & s->w_mask] = head; - s->head[hm] = (Pos)str; - } - return head; -} - -/* =========================================================================== - * Insert string str in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). - */ -Z_INTERNAL void INSERT_STRING(deflate_state *const s, const uint32_t str, uint32_t count) { - uint8_t *strstart = s->window + str; - uint8_t *strend = strstart + count - 1; /* last position */ - - for (Pos idx = (Pos)str; strstart <= strend; idx++, strstart++) { - uint32_t val, hm, h = 0; - -#ifdef UNALIGNED_OK - val = *(uint32_t *)(strstart); -#else - val = ((uint32_t)(strstart[0])); - val |= ((uint32_t)(strstart[1]) << 8); - val |= ((uint32_t)(strstart[2]) << 16); - val |= ((uint32_t)(strstart[3]) << 24); -#endif - - UPDATE_HASH(s, h, val); - hm = h & HASH_MASK; - - Pos head = s->head[hm]; - if (LIKELY(head != idx)) { - s->prev[idx & s->w_mask] = head; - s->head[hm] = idx; - } - } -} -#endif diff --git a/libs/zlibng/match_tpl.h b/libs/zlibng/match_tpl.h deleted file mode 100644 index b15ca17b91..0000000000 --- a/libs/zlibng/match_tpl.h +++ /dev/null @@ -1,180 +0,0 @@ - -#include "zbuild.h" -#include "deflate.h" -#include "functable.h" - -#ifndef MATCH_TPL_H -#define MATCH_TPL_H - -#ifdef UNALIGNED_OK -# ifdef UNALIGNED64_OK -typedef uint64_t bestcmp_t; -# else -typedef uint32_t bestcmp_t; -# endif -#else -typedef uint8_t bestcmp_t; -#endif - -#define EARLY_EXIT_TRIGGER_LEVEL 5 - -#endif - -/* Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is garbage. - * - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >=1 - * OUT assertion: the match length is not greater than s->lookahead - */ -Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { - unsigned int strstart = s->strstart; - const unsigned wmask = s->w_mask; - unsigned char *window = s->window; - unsigned char *scan = window + strstart; - Z_REGISTER unsigned char *mbase_start = window; - Z_REGISTER unsigned char *mbase_end; - const Pos *prev = s->prev; - Pos limit; - int32_t early_exit; - uint32_t chain_length, nice_match, best_len, offset; - uint32_t lookahead = s->lookahead; - bestcmp_t scan_end; -#ifndef UNALIGNED_OK - bestcmp_t scan_end0; -#else - bestcmp_t scan_start; -#endif - -#define GOTO_NEXT_CHAIN \ - if (--chain_length && (cur_match = prev[cur_match & wmask]) > limit) \ - continue; \ - return best_len; - - /* The code is optimized for MAX_MATCH-2 multiple of 16. */ - Assert(MAX_MATCH == 258, "Code too clever"); - - best_len = s->prev_length ? s->prev_length : 1; - - /* Calculate read offset which should only extend an extra byte - * to find the next best match length. - */ - offset = best_len-1; -#ifdef UNALIGNED_OK - if (best_len >= sizeof(uint32_t)) { - offset -= 2; -#ifdef UNALIGNED64_OK - if (best_len >= sizeof(uint64_t)) - offset -= 4; -#endif - } -#endif - - scan_end = *(bestcmp_t *)(scan+offset); -#ifndef UNALIGNED_OK - scan_end0 = *(bestcmp_t *)(scan+offset+1); -#else - scan_start = *(bestcmp_t *)(scan); -#endif - mbase_end = (mbase_start+offset); - - /* Do not waste too much time if we already have a good match */ - chain_length = s->max_chain_length; - early_exit = s->level < EARLY_EXIT_TRIGGER_LEVEL; - if (best_len >= s->good_match) - chain_length >>= 2; - nice_match = (uint32_t)s->nice_match; - - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0 - */ - limit = strstart > MAX_DIST(s) ? (Pos)(strstart - MAX_DIST(s)) : 0; - - Assert((unsigned long)strstart <= s->window_size - MIN_LOOKAHEAD, "need lookahead"); - for (;;) { - if (cur_match >= strstart) - break; - - /* Skip to next match if the match length cannot increase or if the match length is - * less than 2. Note that the checks below for insufficient lookahead only occur - * occasionally for performance reasons. - * Therefore uninitialized memory will be accessed and conditional jumps will be made - * that depend on those values. However the length of the match is limited to the - * lookahead, so the output of deflate is not affected by the uninitialized values. - */ -#ifdef UNALIGNED_OK - if (best_len < sizeof(uint32_t)) { - for (;;) { - if (*(uint16_t *)(mbase_end+cur_match) == (uint16_t)scan_end && - *(uint16_t *)(mbase_start+cur_match) == (uint16_t)scan_start) - break; - GOTO_NEXT_CHAIN; - } -# ifdef UNALIGNED64_OK - } else if (best_len >= sizeof(uint64_t)) { - for (;;) { - if (*(uint64_t *)(mbase_end+cur_match) == (uint64_t)scan_end && - *(uint64_t *)(mbase_start+cur_match) == (uint64_t)scan_start) - break; - GOTO_NEXT_CHAIN; - } -# endif - } else { - for (;;) { - if (*(uint32_t *)(mbase_end+cur_match) == (uint32_t)scan_end && - *(uint32_t *)(mbase_start+cur_match) == (uint32_t)scan_start) - break; - GOTO_NEXT_CHAIN; - } - } -#else - for (;;) { - if (mbase_end[cur_match] == scan_end && mbase_end[cur_match+1] == scan_end0 && - mbase_start[cur_match] == scan[0] && mbase_start[cur_match+1] == scan[1]) - break; - GOTO_NEXT_CHAIN; - } -#endif - uint32_t len = COMPARE256(scan+2, mbase_start+cur_match+2) + 2; - Assert(scan+len <= window+(unsigned)(s->window_size-1), "wild scan"); - - if (len > best_len) { - s->match_start = cur_match; - /* Do not look for matches beyond the end of the input. */ - if (len > lookahead) - return lookahead; - best_len = len; - if (best_len >= nice_match) - return best_len; - - offset = best_len-1; -#ifdef UNALIGNED_OK - if (best_len >= sizeof(uint32_t)) { - offset -= 2; -#ifdef UNALIGNED64_OK - if (best_len >= sizeof(uint64_t)) - offset -= 4; -#endif - } -#endif - scan_end = *(bestcmp_t *)(scan+offset); -#ifndef UNALIGNED_OK - scan_end0 = *(bestcmp_t *)(scan+offset+1); -#endif - mbase_end = (mbase_start+offset); - } else if (UNLIKELY(early_exit)) { - /* The probability of finding a match later if we here is pretty low, so for - * performance it's best to outright stop here for the lower compression levels - */ - break; - } - GOTO_NEXT_CHAIN; - } - - return best_len; -} - -#undef LONGEST_MATCH -#undef COMPARE256 -#undef COMPARE258 diff --git a/libs/zlibng/test/.gitignore b/libs/zlibng/test/.gitignore deleted file mode 100644 index 96a3cad070..0000000000 --- a/libs/zlibng/test/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# ignore Makefiles; they're all automatically generated -Makefile -/switchlevels -/switchlevels.dSYM/ -/switchlevels.exe diff --git a/libs/zlibng/test/CVE-2002-0059/test.gz b/libs/zlibng/test/CVE-2002-0059/test.gz deleted file mode 100644 index c5c3e184b1a90692f1c2dc729eb106476d231378..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4610 zcmb2|=3oE==C>CV8G$T;1@EN)&o6EfRlAUMpn;K@jYq;DVU#f%2%{-sG#8BKg3(+s vnhQpA!DucR%>|>mU^Ewu=7P~&Fq#WSbHQjX7-G5L2b -#include -#include -#include - -int main(void) { - gzFile f; - int ret; - - if(!(f = gzopen("/dev/null", "w"))) { - perror("/dev/null"); - exit(1); - } - - ret = gzprintf(f, "%10240s", ""); - printf("gzprintf -> %d\n", ret); - ret = gzclose(f); - printf("gzclose -> %d [%d]\n", ret, errno); - - exit(0); -} diff --git a/libs/zlibng/test/CVE-2004-0797/test.gz b/libs/zlibng/test/CVE-2004-0797/test.gz deleted file mode 100644 index 62dcf34bddbfe2c2e861c7929c21dc2f731dd000..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52 ocmb2|=3oE==C>CV85!7kBn%P`G%zxAfEl}iz!@q6kpjs906!lM=l}o! diff --git a/libs/zlibng/test/CVE-2005-1849/test.gz b/libs/zlibng/test/CVE-2005-1849/test.gz deleted file mode 100644 index b28f278263c0a3154faeb3c3dd7b083a3a593c8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52 kcmb2|=3oE==C@ZA85!7kBn%P`G%zxAz!-252m>Ss01LtkQvd(} diff --git a/libs/zlibng/test/CVE-2005-2096/test.gz b/libs/zlibng/test/CVE-2005-2096/test.gz deleted file mode 100644 index 11590aeab9ac844087776ab66eb2f5d2c9f6d013..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52 pcmb2|=3oE==C>CV84oltGP4!m+X9 diff --git a/libs/zlibng/test/GH-382/defneg3.dat b/libs/zlibng/test/GH-382/defneg3.dat deleted file mode 100644 index 5fa6a08044..0000000000 --- a/libs/zlibng/test/GH-382/defneg3.dat +++ /dev/null @@ -1 +0,0 @@ -oÌ™Ì?ÌOÌÃÌḩÌÕÌ>ÌÌÌàÌ̹̘ÌÔÌEÌsÌ—ÌÌ4̢̙̑Ì6ÌÌØÌæÌ\ÌÌÌ5̪̲̕ÌmÌÌ–Ìç̺̜ÌÙ̧ÌÌíÌíÌ–ÌÌëÌmÌìÌÎ̵ÌGÌïÌOÌÛÌ ÌÃÌòÌÎÌôÌ„Ì;Ì”ÌýÌ’ÌÓÌÀÌ×Ì,ÌÑÌ¢ÌáÌAÌ9Ì»ÌæÌ‚ÌÂÌsÌý̼ÌÝÌÌ­ÌeÌòÌÝÌUÌuÌí̱ÌËÌwÌùÌ•ÌDÌß̋̽Ìt̞̣̹ÌöÌôÌOÌîÌíÌ…ÌpÌGÌḭ̀ÌÀÌ(ÌÌÌ̤Ì{Ì“ÌßÌïÌÕÌÌøÌÌMÌ#ÌÌí̵ÌdÌ·ÌIÌßÌhÌ_ÌpÌJÌÇÌ¢ÌÎÌÌoÌÌêÌÁÌ;Ì<̘ÌZÌÈÌÑÌoÌW̄̿Ì}ÌáÌÌÌ:Ìá̧̻̕ÌeÌFÌtÌ(ÌEÌoÌàÌpÌÌ¢Ì(Ì;ÌþÌëÌóÌ!̹̹ÌÉÌÌœÌîÌÖÌ4ÌÈÌ3ÌëÌ‹ÌBÌŽÌÆÌuÌPÌ6Ì“ÌþÌ&̦̳̕ÌÁÌðÌ»ÌÌÌTÌÀ̧ÌbÌÌÒÌÕÌëÌ{ÌÆÌ¡ÌÊÌNÌ9ÌÇÌÌBÌÑ \ No newline at end of file diff --git a/libs/zlibng/test/GH-751/test.txt b/libs/zlibng/test/GH-751/test.txt deleted file mode 100644 index ef2143ece8..0000000000 --- a/libs/zlibng/test/GH-751/test.txt +++ /dev/null @@ -1 +0,0 @@ -abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc diff --git a/libs/zlibng/test/Makefile.in b/libs/zlibng/test/Makefile.in deleted file mode 100644 index 97b8be7538..0000000000 --- a/libs/zlibng/test/Makefile.in +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler -# Copyright 2015, Daniel Axtens, IBM Corporation -# zlib license, see zlib.h - -CC= -CFLAGS= -EXE= -SRCDIR= -SRCTOP= -LIBNAME= -TEST_LDFLAGS=-L.. ../$(LIBNAME).a -WITH_FUZZERS= - -COMPATTESTS = -QEMU_RUN= -QEMU_VER:=$(shell command -v $(QEMU_RUN) --version 2> /dev/null) - -all: oldtests cvetests $(COMPATTESTS) fuzzer ghtests - -oldtests: #set by ../configure -check_cross_dep: -ifneq (,$(QEMU_RUN)) -ifeq (,$(QEMU_VER)) - $(error "You need QEMU to run tests on non-native platform") -endif -endif - -ALL_SRC_FILES := $(wildcard ../*) - -# Only check the fuzzer when it is a stand-alone executable. -ifneq (,$(LIB_FUZZING_ENGINE)) -fuzzer: -else - ifeq (0,$(WITH_FUZZERS)) -fuzzer: - else -fuzzer: - @${QEMU_RUN} ../checksum_fuzzer$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../compress_fuzzer$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../example_small_fuzzer$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../example_large_fuzzer$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../example_flush_fuzzer$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../example_dict_fuzzer$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../minigzip_fuzzer$(EXE) $(ALL_SRC_FILES) - endif -endif - -teststatic: check_cross_dep - @TMPST=tmpst_$$$$; \ - HELLOST=tmphellost_$$$$; \ - if echo hello world | ${QEMU_RUN} ../minigzip$(EXE) > $$HELLOST && ${QEMU_RUN} ../minigzip$(EXE) -d < $$HELLOST && ${QEMU_RUN} ../example$(EXE) $$TMPST && ${QEMU_RUN} ../adler32_test$(EXE); then \ - echo ' *** zlib test OK ***'; \ - else \ - echo ' *** zlib test FAILED ***'; exit 1; \ - fi; \ - rm -f $$TMPST $$HELLOST - -testshared: check_cross_dep - @LD_LIBRARY_PATH=`pwd`/..:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ - LD_LIBRARYN32_PATH=`pwd`/..:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \ - DYLD_LIBRARY_PATH=`pwd`/..:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ - SHLIB_PATH=`pwd`/..:$(SHLIB_PATH) ; export SHLIB_PATH; \ - TMPSH=tmpsh_$$$$; \ - HELLOSH=tmphellosh_$$$$; \ - if echo hello world | ${QEMU_RUN} ../minigzipsh$(EXE) > $$HELLOSH && ${QEMU_RUN} ../minigzipsh$(EXE) -d < $$HELLOSH && ${QEMU_RUN} ../examplesh$(EXE) $$TMPSH && ${QEMU_RUN} ../adler32_testsh$(EXE); then \ - echo ' *** zlib shared test OK ***'; \ - else \ - echo ' *** zlib shared test FAILED ***'; exit 1; \ - fi; \ - rm -f $$TMPSH $$HELLOSH - -cvetests: testCVEinputs - -# Tests requiring zlib-ng to be built with --zlib-compat -compattests: testCVE-2003-0107 - -testCVEinputs: check_cross_dep - @EXE=$(EXE) QEMU_RUN="${QEMU_RUN}" $(SRCDIR)/testCVEinputs.sh - -testCVE-2003-0107: CVE-2003-0107$(EXE) check_cross_dep - @if ${QEMU_RUN} ./CVE-2003-0107$(EXE); then \ - echo ' *** zlib not vulnerable to CVE-2003-0107 ***'; \ - else \ - echo ' *** zlib VULNERABLE to CVE-2003-0107 ***'; exit 1; \ - fi - -CVE-2003-0107.o: $(SRCDIR)/CVE-2003-0107.c - $(CC) $(CFLAGS) -I.. -I$(SRCTOP) -c -o $@ $(SRCDIR)/CVE-2003-0107.c - -CVE-2003-0107$(EXE): CVE-2003-0107.o - $(CC) $(CFLAGS) -o $@ CVE-2003-0107.o $(TEST_LDFLAGS) - -.PHONY: ghtests -ghtests: testGH-361 testGH-364 testGH-751 - -.PHONY: testGH-361 -testGH-361: - $(QEMU_RUN) ../minigzip$(EXE) -4 <$(SRCDIR)/GH-361/test.txt >/dev/null - -switchlevels$(EXE): $(SRCDIR)/switchlevels.c - $(CC) $(CFLAGS) -I.. -I$(SRCTOP) -o $@ $< $(TEST_LDFLAGS) - -.PHONY: testGH-364 -testGH-364: switchlevels$(EXE) - $(QEMU_RUN) ./switchlevels$(EXE) 1 5 9 3 <$(SRCDIR)/GH-364/test.bin >/dev/null - -.PHONY: testGH-751 -testGH-751: - $(QEMU_RUN) ../minigzip$(EXE) <$(SRCDIR)/GH-751/test.txt | $(QEMU_RUN) ../minigzip$(EXE) -d >/dev/null - -clean: - rm -f *.o *.gcda *.gcno *.gcov - rm -f CVE-2003-0107$(EXE) switchlevels$(EXE) - -distclean: - rm -f Makefile diff --git a/libs/zlibng/test/README.md b/libs/zlibng/test/README.md deleted file mode 100644 index 247d5bac74..0000000000 --- a/libs/zlibng/test/README.md +++ /dev/null @@ -1,36 +0,0 @@ -Contents --------- - -|Name|Description| -|-|-| -|[CVE-2003-0107.c](https://nvd.nist.gov/vuln/detail/CVE-2003-0107)|Buffer overflow in the gzprintf function, requires ZLIB_COMPAT| -|[CVE-2002-0059](https://nvd.nist.gov/vuln/detail/CVE-2002-0059)|inflateEnd to release memory more than once| -|[CVE-2004-0797](https://nvd.nist.gov/vuln/detail/CVE-2004-0797)|Error handling in inflate and inflateBack causes crash| -|[CVE-2005-1849](https://nvd.nist.gov/vuln/detail/CVE-2005-1849)|inftrees.h bug causes crash| -|[CVE-2005-2096](https://nvd.nist.gov/vuln/detail/CVE-2005-2096)|Buffer overflow when incomplete code description -|[GH-361](https://github.com/zlib-ng/zlib-ng/issues/361)|Test case for overlapping matches| -|[GH-364](https://github.com/zlib-ng/zlib-ng/issues/364)|Test case for switching compression levels| -|[GH-382](https://github.com/zlib-ng/zlib-ng/issues/382)|Test case for deflateEnd returning -3 in deflate quick| - -Copying -------- - -Some of the files in _test_ are licensed differently: - - - test/data/fireworks.jpeg is Copyright 2013 Steinar H. Gunderson, and - is licensed under the Creative Commons Attribution 3.0 license - (CC-BY-3.0). See https://creativecommons.org/licenses/by/3.0/ - for more information. - - - test/data/paper-100k.pdf is an excerpt (bytes 92160 to 194560) from the paper - “Combinatorial Modeling of Chromatin Features Quantitatively Predicts DNA - Replication Timing in _Drosophila_†by Federico Comoglio and Renato Paro, - which is licensed under the CC-BY license. See - http://www.ploscompbiol.org/static/license for more information. - - - test/data/lcet10.txt is from Project Gutenberg. It does not have expired - copyright, but is still in the public domain according to the license information. - (http://www.gutenberg.org/ebooks/53). - - - test/GH-382/defneg3.dat was the smallest file generated by Nathan Moinvaziri - that reproduced GH-382. It is licensed under the terms of the zlib license. diff --git a/libs/zlibng/test/abi/ignore b/libs/zlibng/test/abi/ignore deleted file mode 100644 index dba3639cb9..0000000000 --- a/libs/zlibng/test/abi/ignore +++ /dev/null @@ -1,12 +0,0 @@ -# See https://sourceware.org/libabigail/manual/libabigail-concepts.html#suppression-specifications - -[suppress_type] - name = internal_state - -[suppress_type] - name_regexp = z_stream.* - -# Size varies with version number -[suppress_variable] - name = zlibng_string - diff --git a/libs/zlibng/test/abi/zlib-v1.2.11-arm-linux-gnueabihf.abi b/libs/zlibng/test/abi/zlib-v1.2.11-arm-linux-gnueabihf.abi deleted file mode 100644 index 152a742cf9..0000000000 --- a/libs/zlibng/test/abi/zlib-v1.2.11-arm-linux-gnueabihf.abi +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/zlibng/test/abi/zlib-v1.2.11-x86_64-linux-gnu.abi b/libs/zlibng/test/abi/zlib-v1.2.11-x86_64-linux-gnu.abi deleted file mode 100644 index 00a520c63c..0000000000 --- a/libs/zlibng/test/abi/zlib-v1.2.11-x86_64-linux-gnu.abi +++ /dev/null @@ -1,1037 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/zlibng/test/abicheck.md b/libs/zlibng/test/abicheck.md deleted file mode 100644 index 6e9e58aade..0000000000 --- a/libs/zlibng/test/abicheck.md +++ /dev/null @@ -1,59 +0,0 @@ -ABI Compatibility test ----------------------- - -abicheck.sh uses libabigail to check ABI stability. -It will abort if the current source -tree has a change that breaks binary compatibility. - -This protects against the common scenario where: -- an app is compiled against the current zlib-ng -- the system package manager updates the zlib-ng shared library -- the app now crashes because some symbol is - missing or some public structure or parameter - has changed type or size - -If run with --zlib-compat, it verifies that the -current source tree generates a library that -is ABI-compatible with the reference release -of classic zlib. This ensures that building -zlib-ng with --zlib-compat does what it says on the tin. - -abicheck.sh is not perfect, but it can catch -many common compatibility issues. - -Cached files test/abi/*.abi ---------------------------- - -Comparing to the old version of zlib (or zlib-ng) -means someone has to check out and build -the previous source tree and extract its .abi -using abidw. This can be slow. - -If you don't mind the slowness, run abicheck.sh --refresh_if, -and it will download and build the reference version -and extract the .abi on the spot if needed. -(FIXME: should this be the default?) - -On the next run, the reference .abi file will already be -present, and that step will be skipped. -It's stored in the tests/abi directory, -in a file with the architecture and git hash in the name. - -If you're running continuous integration -which clear out the source tree on each run, -and you don't want your build machines -constantly downloading and building the old -version, you can check the .abi file into git. - -To make this easier, a helper script could be written to automatically build -all the configurations tested by .github/worflows/abicheck.yml -Then they could be checked into git en masse by a maintainer -when a new platform is added or a new major version (which -intentionally breaks backwards compatibility) is being prepared. - -Further reading ---------------- - -- https://sourceware.org/libabigail/manual/ -- https://developers.redhat.com/blog/2014/10/23/comparing-abis-for-compatibility-with-libabigail-part-1/ -- https://developers.redhat.com/blog/2020/04/02/how-to-write-an-abi-compliance-checker-using-libabigail/ diff --git a/libs/zlibng/test/abicheck.sh b/libs/zlibng/test/abicheck.sh deleted file mode 100644 index 89199a59ab..0000000000 --- a/libs/zlibng/test/abicheck.sh +++ /dev/null @@ -1,164 +0,0 @@ -#!/bin/sh -set -ex -TESTDIR="$(cd $(dirname "$0"); pwd)" - -usage() { - cat <<_EOF_ -Usage: $0 [--zlib-compat][--refresh][--refresh-if] - -Build shared library with -ggdb, then compare its ABI to the stable -ABI, and abort if differences found. - -Options: ---zlib-compat - check the ABI of the zlib-compatible flavor of zlib-ng. ---refresh - build the reference library and extract its ABI rather than using a stored ABI file. ---refresh-if - refresh only if ABI file not present. - -Obeys CHOST, CONFIGURE_ARGS, CFLAGS, and LDFLAGS. - -Requires libabigail (on Ubuntu, install package abigail-tools). -_EOF_ -} - -# Print the multiarch tuple for the current (non-cross) machine, -# or the empty string if unavailable. -detect_chost() { - dpkg-architecture -qDEB_HOST_MULTIARCH || - $CC -print-multiarch || - $CC -print-search-dirs | sed 's/:/\n/g' | grep -E '^/lib/[^/]+$' | sed 's%.*/%%' || - true -} - -if ! test -f "configure" -then - echo "Please run from top of source tree" - exit 1 -fi - -suffix="-ng" -CONFIGURE_ARGS_NG="$CONFIGURE_ARGS" -refresh=false -refresh_if=false -for arg -do - case "$arg" in - --zlib-compat) - suffix="" - CONFIGURE_ARGS_NG="$CONFIGURE_ARGS_NG --zlib-compat" - ;; - --refresh) - refresh=true - ;; - --refresh_if) - refresh_if=true - ;; - --help) - usage - exit 0 - ;; - *) - echo "Unknown arg '$arg'" - usage - exit 1 - ;; - esac -done - -# Choose reference repo and commit -if test "$suffix" = "" -then - # Reference is zlib 1.2.11 - ABI_GIT_REPO=https://github.com/madler/zlib.git - ABI_GIT_COMMIT=v1.2.11 -else - # Reference should be the tag for zlib-ng 2.0 - # but until that bright, shining day, use some - # random recent SHA. Annoyingly, can't shorten it. - ABI_GIT_REPO=https://github.com/zlib-ng/zlib-ng.git - ABI_GIT_COMMIT=56ce27343bf295ae9457f8e3d38ec96d2f949a1c -fi -# FIXME: even when using a tag, check the hash. - -# Test compat build for ABI compatibility with zlib -if test "$CHOST" = "" -then - # Note: don't export CHOST here, as we don't want configure seeing it - # when it's just the name for the build machine. - # Leave it as a plain shell variable, not an environment variable. - CHOST=$(detect_chost) - # Support -m32 for non-cross builds. - case "$CFLAGS" in - *-m32*) M32="-m32";; - *) M32="";; - esac -fi - -# Canonicalize CHOST to work around bug in original zlib's configure -export CHOST=$(sh $TESTDIR/../tools/config.sub $CHOST) - -if test "$CHOST" = "" -then - echo "abicheck: SKIP, as we don't know CHOST" - exit 0 -fi - -ABIFILE="test/abi/zlib$suffix-$ABI_GIT_COMMIT-$CHOST$M32.abi" -if ! $refresh && $refresh_if && ! test -f "$ABIFILE" -then - refresh=true -fi -abidw --version - -if $refresh -then - # Check out reference source - rm -rf btmp1 - mkdir -p btmp1/src.d - cd btmp1/src.d - git init - git remote add origin $ABI_GIT_REPO - git fetch origin $ABI_GIT_COMMIT - git reset --hard FETCH_HEAD - cd .. - # Build unstripped, uninstalled, very debug shared library - CFLAGS="$CFLAGS -ggdb" sh src.d/configure $CONFIGURE_ARGS - make -j2 - cd .. - # Find shared library, extract its abi - dylib1=$(find btmp1 -type f -name '*.dylib*' -print -o -type f -name '*.so.*' -print) - abidw $dylib1 > "$ABIFILE" - # Maintainers may wish to check $ABIFILE into git when a new - # target is added, or when a major release happens that is - # intended to change the ABI. Alternately, this script could - # just always rebuild the reference source, and dispense with - # caching abi files in git (but that would slow builds down). -fi - -if test -f "$ABIFILE" -then - ABIFILE="$ABIFILE" -else - echo "abicheck: SKIP: $ABIFILE not found; rerun with --refresh or --refresh_if" - exit 0 -fi - -# Build unstripped, uninstalled, very debug shared library -rm -rf btmp2 -mkdir btmp2 -cd btmp2 -CFLAGS="$CFLAGS -ggdb" ../configure $CONFIGURE_ARGS_NG -make -j2 -cd .. -# Find shared library, extract its abi -dylib2=$(find btmp2 -type f -name '*.dylib*' -print -o -type f -name '*.so.*' -print) -abidw $dylib2 > btmp2/zlib${suffix}-built.abi - -# Compare it to the reference -# FIXME: use --no-added-syms for now, but we probably want to be more strict. -if abidiff --no-added-syms --suppressions test/abi/ignore "$ABIFILE" btmp2/zlib${suffix}-built.abi -then - echo "abicheck: PASS" -else - echo "abicheck: FAIL" - exit 1 -fi diff --git a/libs/zlibng/test/adler32_test.c b/libs/zlibng/test/adler32_test.c deleted file mode 100644 index f681877d31..0000000000 --- a/libs/zlibng/test/adler32_test.c +++ /dev/null @@ -1,365 +0,0 @@ -/* adler32_test.c -- unit test for adler32 in the zlib compression library - * Copyright (C) 2020 IBM Corporation - * Author: Rogerio Alves - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include -#include -#include - -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -typedef struct { - uint32_t line; - uint32_t adler; - const uint8_t *buf; - uint32_t len; - uint32_t expect; -} adler32_test; - -void test_adler32(uint32_t adler, const uint8_t *buf, uint32_t len, uint32_t chk, uint32_t line) { - uint32_t res = PREFIX(adler32)(adler, buf, len); - if (res != chk) { - fprintf(stderr, "FAIL [%d]: adler32 returned 0x%08X expected 0x%08X\n", - line, res, chk); - exit(1); - } -} - -static const uint8_t long_string[5552] = { - 'q','j','d','w','q','4','8','m','B','u','k','J','V','U','z','V','V','f','M','j','i','q','S','W','L','5','G','n','F','S','P','Q', - 'Q','D','i','6','m','E','9','Z','a','A','P','h','9','d','r','b','5','t','X','U','U','L','w','q','e','k','E','H','6','W','7','k', - 'A','x','N','Q','R','k','d','V','5','y','n','U','N','W','Q','Y','i','W','5','9','R','p','D','C','x','p','u','h','C','a','m','r', - 'z','n','z','A','d','J','6','u','N','e','r','x','7','Q','3','v','V','h','H','S','H','S','f','K','f','e','E','T','9','J','f','K', - 'w','t','x','J','2','y','7','B','x','X','X','p','G','b','T','g','3','k','U','6','E','Z','M','t','J','q','v','n','S','T','6','x', - '5','x','4','P','z','p','M','F','V','b','d','m','f','G','n','J','m','w','z','K','8','a','q','E','D','e','b','3','h','B','V','g', - 'y','3','P','L','5','8','r','z','X','b','Q','g','H','7','L','c','Z','B','3','C','4','y','t','u','k','z','h','v','C','Y','p','p', - '8','H','v','5','X','w','4','L','R','V','V','4','U','C','8','4','T','E','a','N','Z','S','7','U','u','z','f','H','p','P','J','u', - 'Y','Z','h','T','6','e','v','z','V','F','h','u','y','H','b','k','J','M','f','3','6','g','y','L','E','W','t','B','B','d','d','9', - 'u','M','Z','k','F','G','f','h','q','k','5','k','f','r','M','7','c','M','7','y','n','u','8','b','d','7','Q','f','E','m','F','K', - 'x','W','f','B','2','F','8','5','q','z','y','3','R','i','U','m','X','k','h','N','J','y','B','C','h','u','x','4','f','k','J','5', - '6','X','T','W','h','8','J','4','m','K','p','N','3','g','C','g','A','E','e','Z','x','A','P','2','E','4','t','Q','5','X','Y','j', - '6','m','b','h','G','a','v','6','t','v','6','C','M','G','P','u','B','C','A','V','b','2','9','d','2','c','5','a','b','X','w','V', - 'G','6','a','7','c','8','G','6','K','U','Q','m','w','P','V','5','N','x','b','v','x','E','N','C','A','N','t','v','N','B','z','X', - 'B','R','q','U','n','i','A','Q','d','m','a','D','7','Y','f','3','J','8','Y','m','w','Z','b','w','r','H','q','E','j','c','u','E', - 'i','i','S','b','n','G','P','a','F','j','c','R','D','D','G','F','v','i','a','i','M','7','B','e','w','m','L','E','F','2','Y','4', - '4','7','Y','C','t','y','q','7','2','V','G','m','m','E','e','V','u','m','L','p','R','X','W','z','V','K','E','k','p','V','r','J', - 'd','N','3','t','i','u','S','V','w','2','w','U','Q','3','F','q','4','h','q','k','B','7','R','X','B','F','Q','Z','b','b','4','E', - 'K','v','T','B','w','k','V','C','x','d','K','g','N','S','u','k','p','9','z','w','c','y','U','M','V','E','2','Y','P','F','h','9', - 'T','y','h','w','b','9','P','w','G','c','W','W','k','j','J','Q','N','B','U','G','6','9','U','b','v','a','N','9','N','C','G','n', - 'x','R','6','9','Q','C','h','e','j','P','U','h','U','R','i','4','T','B','W','5','w','m','J','p','e','7','r','9','t','c','9','Z', - 'j','p','r','F','C','e','U','P','x','T','A','N','7','6','a','i','y','e','w','F','C','X','H','Y','G','C','q','q','m','A','t','7', - 'z','u','D','S','L','U','C','f','7','e','t','G','V','F','u','c','x','5','M','7','N','i','M','6','h','2','n','H','S','h','K','M', - 'd','T','z','X','d','x','x','4','q','z','d','D','a','2','X','r','p','r','R','m','U','U','y','S','H','c','a','F','e','Z','a','U', - 'P','9','V','J','e','q','j','Y','M','x','e','v','K','7','M','P','N','2','b','6','f','P','h','H','4','U','X','k','n','f','Q','M', - '9','9','a','J','N','e','w','y','f','F','P','p','a','F','Y','a','M','L','W','i','T','M','B','3','U','v','X','v','G','p','7','a', - 'f','u','4','S','y','X','9','g','g','b','B','G','c','i','M','U','n','m','a','7','q','f','9','n','Q','2','V','L','6','e','T','R', - '2','4','9','d','6','Q','B','Y','q','2','4','9','G','Q','E','b','Y','5','u','2','T','Q','G','L','5','n','4','Y','2','y','G','F', - 'j','c','8','M','G','L','e','3','a','N','v','A','A','W','t','R','S','2','i','D','R','8','j','d','Q','3','6','C','V','M','e','w', - 'j','U','Z','w','M','4','b','m','8','J','P','Q','L','P','R','c','r','b','V','C','3','N','8','K','4','d','W','D','N','U','A','A', - '2','J','p','b','D','d','p','j','N','C','k','A','j','B','a','c','u','v','L','X','U','B','4','U','X','W','e','C','b','C','u','d', - 'A','v','U','z','P','t','D','e','5','y','Y','c','x','K','4','7','j','e','e','D','M','5','K','B','Q','6','d','p','T','T','R','j', - 'M','E','E','M','r','N','6','8','7','q','x','F','S','x','E','U','4','d','B','6','5','W','C','e','m','J','e','5','j','w','V','J', - 'w','v','d','7','v','f','K','u','m','8','h','W','T','e','Q','j','M','8','R','Y','d','B','R','2','r','F','j','7','d','E','q','V', - 'k','e','j','P','9','3','X','R','p','R','b','A','v','7','4','A','M','2','k','r','E','7','X','3','7','k','5','c','B','7','W','5', - 'u','J','B','Q','R','2','V','7','h','Q','h','9','g','G','y','c','c','x','M','z','7','G','2','J','w','v','j','5','9','E','b','k', - 'z','W','T','C','b','4','K','R','X','T','k','V','S','G','2','j','d','6','y','E','4','P','H','K','w','a','m','F','Z','x','9','j', - 'i','2','d','X','u','a','4','a','M','z','8','p','p','z','g','t','H','5','Y','L','Q','c','R','F','m','E','n','G','X','d','f','7', - 'x','8','j','g','J','z','D','S','a','S','h','y','5','h','Y','N','p','w','Y','W','h','E','N','v','8','Q','D','W','Z','k','f','e', - 'r','Z','D','7','R','D','T','2','H','X','z','G','X','f','v','E','z','P','v','U','H','e','4','R','W','U','x','t','t','4','w','p', - 'r','z','K','9','f','g','h','P','r','f','v','k','h','c','e','5','8','a','L','F','J','M','G','R','a','N','q','S','g','W','e','7', - 'R','K','R','A','B','z','6','v','S','p','w','n','e','x','k','E','r','j','f','Y','x','8','9','z','e','T','6','E','G','v','9','f', - 'D','A','N','v','y','U','7','D','M','2','E','5','W','G','6','b','9','q','g','Y','F','f','k','q','Q','E','x','Y','C','R','G','6', - 'R','h','4','J','d','U','D','b','9','b','8','r','f','V','d','g','b','2','z','Z','d','m','X','v','j','Y','d','w','K','8','G','r', - 'v','j','N','y','c','h','u','5','z','g','J','H','a','Z','b','z','G','C','r','P','f','y','P','6','F','P','h','7','9','w','7','y', - 'R','3','n','E','h','G','D','4','m','Y','E','q','k','a','f','a','R','B','q','t','W','E','T','p','H','7','k','X','2','d','X','6', - 'W','n','H','m','w','M','i','Y','M','E','F','5','R','p','p','y','c','b','q','R','9','Y','t','T','7','w','u','K','M','Q','z','n', - 'P','7','g','x','6','R','4','x','N','v','w','M','6','j','K','v','7','a','Y','4','a','M','6','n','z','3','E','2','V','N','4','i', - 'E','f','u','W','J','W','e','8','3','Q','e','a','F','P','c','3','P','k','i','z','d','q','m','q','M','a','d','8','D','3','F','M', - 'e','d','E','j','z','V','e','d','z','H','D','J','8','X','g','E','i','u','c','7','A','w','S','J','2','A','e','8','r','q','C','m', - '9','9','a','g','2','y','y','P','M','e','8','3','T','r','m','8','j','v','r','p','M','Z','Y','g','a','9','2','d','H','B','m','9', - '4','6','a','Z','V','u','S','H','g','3','X','h','i','N','3','B','S','E','k','9','k','2','9','R','A','i','3','L','X','M','B','S', - '4','S','F','F','F','w','u','d','M','T','9','K','B','7','R','U','R','8','D','8','T','5','U','t','E','R','x','n','x','h','v','k', - 'B','N','k','E','U','T','t','p','r','u','Z','h','t','E','4','i','P','z','f','z','q','M','p','f','A','K','2','D','t','j','f','c', - 'Y','E','N','M','x','k','g','7','T','U','2','c','d','V','g','2','z','L','i','j','Y','q','b','T','A','y','v','a','t','N','5','t', - 'Z','5','n','D','a','y','G','n','P','x','V','k','M','8','t','J','Z','G','g','5','9','R','h','P','P','J','N','X','p','G','J','p', - '2','y','A','v','d','G','U','z','3','V','M','y','q','U','N','M','Y','p','B','Z','U','h','j','q','z','q','x','w','7','d','J','Q', - 'u','F','q','3','m','9','c','Q','W','d','6','7','b','V','M','7','P','j','r','k','9','h','R','z','m','b','i','B','u','E','L','9', - 'k','v','h','h','W','2','K','e','M','U','Q','p','A','Q','Y','J','G','E','T','U','L','f','q','G','4','z','K','K','y','a','U','W', - 'K','D','P','c','N','D','V','S','Y','6','T','p','R','y','y','J','a','T','J','W','Q','9','p','F','P','X','y','k','9','z','z','4', - 'G','d','a','z','X','n','h','4','J','P','W','V','D','r','U','m','a','8','a','b','X','F','J','X','L','4','S','X','5','W','p','W', - 'h','y','x','B','f','d','C','X','w','7','r','g','V','T','H','a','i','4','N','v','c','w','n','2','3','A','i','A','J','9','N','c', - 'z','7','n','n','3','n','h','n','i','R','i','b','E','h','k','U','c','c','U','6','f','x','q','N','y','H','M','e','J','B','U','B', - 'r','g','a','8','V','a','G','V','y','u','c','c','v','C','H','W','y','g','z','Q','2','4','k','S','m','f','e','G','H','v','Q','3', - 'P','e','f','S','V','P','c','U','e','3','P','x','d','c','7','c','f','g','D','w','2','t','q','y','g','2','Q','V','4','K','a','Q', - 'g','B','b','L','x','9','m','a','K','4','i','x','g','Q','M','9','W','N','2','w','p','v','2','k','B','y','9','k','A','c','f','Z', - 'D','R','A','S','d','v','w','f','f','q','t','K','3','j','x','D','G','P','n','u','r','v','U','k','A','2','d','R','N','T','G','4', - 'B','g','k','t','h','7','J','k','F','A','C','g','W','g','J','F','z','S','Q','c','v','M','b','D','e','H','Q','S','j','v','G','E', - 'R','k','f','i','P','E','F','N','6','y','p','b','t','M','c','Q','B','7','g','w','J','7','3','d','V','E','m','z','6','6','P','P', - 'd','i','r','J','H','D','H','J','r','b','n','v','z','W','e','u','g','B','u','Z','2','m','D','5','h','F','X','B','2','r','6','w', - 'u','Y','4','N','X','K','a','v','V','3','j','B','r','r','C','c','w','R','g','S','8','V','b','F','2','N','M','c','K','8','Y','E', - 'E','N','K','X','K','V','B','x','n','Q','p','a','q','f','k','t','z','Y','E','P','Z','y','n','a','c','B','V','a','x','b','d','X', - 'r','d','8','P','H','F','v','r','V','5','g','J','w','6','i','h','d','d','p','J','c','c','Y','S','q','W','m','U','5','G','b','H', - 'N','z','E','Z','K','E','y','M','c','G','i','d','w','Z','D','N','N','w','S','t','g','y','a','Y','b','H','e','M','N','f','Y','Y', - '7','a','9','b','M','U','k','a','V','k','C','n','a','k','U','H','A','M','i','v','k','t','a','d','i','3','F','d','5','2','A','p', - 'U','c','J','U','R','h','G','d','A','Y','v','q','X','c','w','r','x','4','j','3','4','b','F','d','a','L','N','J','3','Z','g','6', - 'W','Q','R','u','P','t','M','A','3','F','6','y','K','Y','G','2','t','v','u','p','w','b','G','S','K','5','p','4','d','E','w','6', - 'g','t','V','4','b','2','n','b','Z','3','3','f','m','d','2','c','a','m','j','X','U','E','D','6','6','F','w','H','9','7','Z','Y', - 'd','X','C','K','i','g','p','F','Y','n','2','b','F','4','R','u','V','k','f','d','J','i','a','b','X','H','7','v','K','a','Q','i', - 'W','M','j','M','i','a','i','n','F','h','r','q','4','w','x','m','4','q','y','F','8','w','i','4','D','B','A','L','B','U','u','K', - 'v','K','n','a','Q','i','e','k','v','Q','U','5','w','Q','c','r','A','6','M','w','y','g','n','e','v','K','7','W','u','2','y','f', - 'Q','u','e','r','y','a','w','V','p','f','Q','z','C','u','i','i','9','S','P','q','L','r','C','H','S','3','E','p','8','S','m','Q', - 'S','K','r','V','b','J','R','m','w','c','n','Q','N','Q','4','M','u','f','X','S','f','U','Z','x','U','4','j','K','4','G','z','X', - '7','Q','j','R','h','i','G','m','q','c','V','T','x','U','a','E','b','Q','q','E','i','F','K','7','K','i','R','J','5','Y','F','V', - 'B','7','R','8','M','i','f','j','Z','w','j','b','B','u','p','N','Y','r','S','r','f','h','E','J','T','B','P','R','D','V','K','A', - 'Z','A','R','j','z','f','B','i','Y','L','F','G','V','Y','w','R','C','P','G','m','9','7','C','5','e','y','w','N','K','N','a','Q', - 'j','a','W','3','2','f','G','w','n','M','6','F','u','K','8','g','8','M','G','r','e','9','Z','z','y','2','G','U','k','G','6','m', - 'A','D','4','n','b','8','a','q','S','m','S','6','5','R','5','D','5','S','B','g','X','T','8','Q','V','d','A','n','g','y','8','a', - 'h','7','K','9','H','D','J','F','w','G','4','w','T','J','F','f','i','8','X','e','B','J','K','H','7','V','y','X','7','E','8','S', - 'A','d','b','w','S','8','Y','a','J','d','j','E','V','J','T','E','U','R','5','7','V','M','E','v','D','3','z','5','r','k','z','v', - 'e','m','A','7','P','8','j','X','E','f','Q','q','8','D','g','y','8','j','A','e','B','c','c','M','z','k','2','c','q','v','v','y', - 'Q','y','h','g','p','v','M','m','m','C','G','D','k','8','u','T','n','Q','H','G','H','f','b','J','j','5','X','c','i','7','7','q', - 'b','R','8','b','b','z','f','f','h','Y','Q','7','u','B','X','e','i','j','M','q','C','T','M','v','t','J','J','w','b','F','v','J', - 'm','e','2','u','e','8','L','V','G','q','A','j','m','7','m','g','m','5','i','r','p','p','U','y','F','6','f','b','u','6','q','L', - 'M','E','t','V','W','C','t','e','p','w','a','n','w','y','X','h','8','e','G','C','H','q','r','X','G','9','c','h','7','k','8','M', - 'G','b','a','m','Y','Q','w','8','J','z','a','F','r','4','W','M','j','P','q','a','z','U','y','u','3','b','Z','f','Y','5','7','g', - 'N','M','h','M','a','3','C','K','6','6','f','a','p','i','f','q','k','T','i','z','w','f','Z','c','H','L','X','g','6','m','g','r', - 'w','Y','u','K','8','L','p','8','P','R','A','R','A','b','Z','V','a','x','V','c','G','A','H','t','Y','6','P','T','L','W','N','z', - 'g','z','k','d','E','v','C','t','Z','M','Z','K','4','w','9','5','D','W','f','U','8','5','u','6','b','5','B','8','g','y','C','E', - 'Q','z','e','9','p','N','S','P','D','D','f','x','k','Z','4','R','v','X','V','k','p','b','n','t','c','F','R','e','x','9','C','D', - 'J','2','6','f','Z','D','w','J','R','j','j','9','b','w','N','N','p','R','f','Z','z','j','F','r','Q','e','F','x','f','t','V','V', - 'A','y','J','G','W','Z','H','r','D','5','M','u','H','V','L','N','U','V','X','z','j','9','r','v','e','d','R','c','u','V','x','r', - 'c','6','k','L','h','q','w','U','W','Q','g','G','F','C','t','E','a','D','h','x','9','5','P','R','Z','E','M','5','f','4','2','t', - 'A','6','f','r','X','G','X','Y','B','8','G','E','n','B','v','x','f','M','R','f','B','z','Y','3','2','q','z','G','t','P','C','6', - '6','r','z','J','r','c','n','d','6','h','e','w','D','D','h','V','L','u','i','b','5','K','d','S','y','9','N','p','E','r','D','k', - 'B','z','u','v','d','Q','p','K','5','m','J','r','b','Y','Z','7','p','M','J','F','E','q','x','f','E','K','U','U','4','f','a','6', - 'g','5','a','q','D','U','8','F','y','R','a','P','5','5','x','z','6','V','T','P','D','m','y','7','U','5','C','A','7','Q','h','w', - 'r','6','x','g','Q','i','b','K','F','p','B','X','Q','h','i','E','r','C','z','v','x','W','Q','6','p','6','b','M','K','V','x','u', - 'k','d','R','S','k','Q','p','n','h','d','Q','Y','x','n','x','5','K','t','5','w','A','5','p','k','F','z','W','p','j','U','y','V', - 'x','G','m','y','L','A','X','H','G','A','a','J','5','E','P','q','E','U','7','p','6','A','9','n','d','G','D','g','i','h','t','W', - 'b','c','E','2','P','d','y','J','M','u','4','g','P','S','X','J','v','w','3','v','D','q','U','i','U','T','q','E','Y','5','2','t', - 'b','j','P','2','j','D','9','y','i','B','5','Y','3','X','L','w','m','V','X','z','X','r','Z','d','H','L','A','H','k','R','X','5', - 'i','L','m','q','3','p','a','G','P','j','g','h','R','P','Y','U','z','M','5','R','M','A','E','Q','V','c','w','r','4','M','S','k', - 'N','D','i','R','R','x','t','q','T','i','u','N','K','R','x','Z','K','a','g','G','y','9','c','j','J','S','9','3','H','T','f','F', - 'q','6','D','W','F','K','h','e','p','p','b','q','N','k','A','C','m','y','u','B','J','v','q','D','e','j','e','b','2','w','R','t', - 'J','N','j','F','T','A','8','L','m','X','i','T','g','j','c','V','4','V','h','2','h','R','p','2','9','k','c','c','G','D','h','z', - 't','i','h','t','W','R','n','Y','i','8','u','6','G','9','T','P','9','9','J','P','Y','R','h','X','K','z','h','L','W','r','C','U', - '2','L','T','k','2','m','6','W','L','P','T','Z','z','t','i','H','5','G','w','t','E','v','z','k','b','H','b','b','W','W','u','b', - 'i','h','C','Q','n','H','N','u','5','u','K','X','r','M','W','U','3','Y','k','P','2','k','x','f','x','C','w','z','z','b','G','8', - 'y','W','e','j','v','2','v','r','t','q','z','p','Y','d','w','6','Z','D','J','L','9','F','z','G','U','4','a','8','H','6','U','a', - 'q','7','y','Q','J','v','m','D','P','S','j','q','v','t','n','t','g','j','3','t','8','f','K','K','7','b','W','d','F','i','N','K', - 'a','R','V','V','V','v','m','A','Q','2','y','j','c','t','f','k','j','7','X','y','j','b','U','F','w','W','3','9','6','A','S','J', - 'p','q','2','Z','7','L','p','b','7','b','5','i','p','r','r','h','P','M','h','j','c','y','e','u','h','B','d','9','9','u','f','d', - 'g','u','p','w','u','9','S','c','L','U','g','A','y','V','F','V','6','D','D','X','i','V','m','u','Y','P','J','v','L','T','A','F', - 'M','Q','H','Z','6','v','8','p','A','L','P','z','C','V','a','C','h','X','j','W','8','G','z','j','d','M','4','u','x','w','H','g', - 'V','q','K','z','b','g','2','3','D','N','y','G','X','F','T','v','T','L','y','v','L','9','g','c','C','R','8','L','A','7','Y','N', - 't','n','R','6','b','n','m','9','i','h','t','T','F','a','V','N','J','J','3','J','q','p','W','7','b','T','G','r','M','k','a','7', - 'D','H','v','y','T','A','C','U','P','u','q','L','R','Y','4','q','h','y','f','F','J','x','K','7','N','B','v','3','a','Z','M','t', - 'U','x','8','9','V','E','t','j','K','r','u','Y','Y','A','u','w','Y','2','y','Q','z','S','n','J','B','2','t','X','x','K','z','g', - '6','d','n','i','7','Z','N','F','Q','6','w','N','r','b','k','d','W','X','S','t','c','U','m','6','4','2','e','w','6','x','Z','a', - 'Q','A','7','4','h','H','z','r','e','J','q','j','w','4','q','c','i','R','4','x','n','r','j','r','P','g','E','7','t','k','b','Z', - 'r','A','b','d','g','i','G','V','D','E','U','L','b','J','U','q','2','S','K','m','A','U','L','k','Q','4','N','p','k','G','C','6', - 'R','Z','B','y','B','B','j','y','x','L','d','h','L','G','6','x','H','z','T','5','d','Y','4','2','m','q','Q','y','H','6','c','N', - 'u','m','U','v','i','Y','Z','7','4','L','K','F','b','v','2','Y','h','x','8','a','R','w','q','x','E','a','T','y','m','C','2','Q', - 'U','T','D','Q','v','u','M','9','D','8','r','8','b','m','p','E','7','C','T','9','B','A','G','k','b','G','z','Z','G','L','N','k', - 'h','3','k','J','e','f','d','x','F','8','W','K','7','T','6','h','H','V','C','h','P','u','H','e','v','w','z','P','K','r','D','G', - 'X','Z','B','X','f','H','Q','4','e','D','y','W','Z','6','4','K','A','e','a','F','S','N','h','x','S','W','J','c','E','P','g','j', - 'a','w','T','m','Z','X','E','P','Y','R','M','2','R','2','X','N','F','X','Y','W','x','z','p','J','g','n','D','4','i','p','6','N', - 'r','9','G','k','E','h','T','h','U','h','x','B','Q','9','H','7','w','U','P','Q','d','G','6','q','p','j','j','v','C','a','X','J', - 'N','G','Y','w','f','H','C','x','F','k','z','3','9','r','h','8','7','5','V','i','V','C','R','q','x','N','2','2','i','W','F','U', - '7','T','H','f','z','E','a','n','u','Q','t','U','Y','G','t','3','A','m','r','6','d','f','e','n','e','z','F','u','U','N','8','m', - 'h','p','R','N','S','H','6','6','V','M','S','t','q','P','E','i','u','y','g','8','L','Q','Y','Y','G','e','W','W','C','G','y','b', - 'y','t','u','P','R','P','5','m','N','K','B','Z','w','f','t','k','x','3','L','b','q','d','w','S','G','E','h','R','F','4','q','e', - '5','6','F','2','n','q','T','R','y','f','n','Y','h','2','F','u','x','M','i','i','h','w','G','C','Z','v','i','C','a','X','U','C', - 'Y','8','d','h','R','x','V','n','v','G','i','D','a','U','p','U','a','e','b','F','w','P','d','X','n','K','h','9','H','r','b','g', - '2','f','m','X','k','m','q','6','n','5','b','G','H','d','R','9','D','U','c','r','Z','Y','W','S','Z','x','p','t','x','y','4','k', - 'j','F','U','t','C','i','e','i','b','p','e','4','C','z','h','3','3','5','Q','P','n','G','i','A','8','c','Q','z','B','a','V','4', - '2','B','2','z','u','u','3','i','L','w','y','g','K','H','k','y','2','B','b','e','5','e','4','e','U','4','z','n','P','z','a','c', - 'E','f','u','M','G','C','g','z','j','4','E','7','R','t','D','K','c','t','p','g','W','H','C','H','J','Q','J','c','F','5','4','W', - 'K','7','j','h','A','T','K','z','t','S','f','f','j','C','c','8','n','7','c','T','U','R','Q','E','7','A','W','Z','z','K','5','j', - '2','H','k','a','j','g','g','W','w','4','T','A','9','J','U','e','S','N','P','K','d','k','L','Q','G','Z','e','W','i','H','u','j', - 'C','z','4','E','2','v','5','L','u','9','Z','a','9','A','b','C','M','G','X','B','C','2','Y','Z','e','U','n','E','5','Y','n','y', - 'F','h','H','p','9','j','Y','F','V','w','Y','r','8','Q','f','C','J','4','T','t','z','Q','N','M','e','7','4','3','y','E','M','m', - 'b','S','c','h','w','a','X','E','d','E','z','t','h','9','k','p','A','k','K','H','x','q','K','Z','B','u','a','9','3','U','U','u', - '8','E','D','v','y','k','W','Y','X','k','r','R','D','X','n','Q','V','d','e','D','g','x','E','V','Y','w','k','m','K','r','H','D', - 't','2','6','N','U','g','3','t','B','9','t','u','M','D','z','Y','K','z','K','r','V','5','i','e','p','M','d','t','w','6','a','f', - 'f','W','k','L','i','g','M','V','M','Y','b','x','e','4','h','h','Y','g','w','Z','m','e','e','6','R','W','M','x','G','y','V','n', - '6','e','g','A','g','K','a','N','7','p','a','u','E','4','6','M','t','X','h','g','b','j','p','5','x','x','B','P','3','J','M','7', - 'j','Z','P','y','e','Q','Z','e','t','j','3','t','F','V','x','m','b','b','B','y','J','L','L','9','3','R','a','5','j','S','V','t', - 'e','2','6','m','H','w','r','w','r','6','Q','3','x','z','m','A','d','x','t','E','H','c','Z','x','c','P','j','r','u','U','W','k', - '6','g','X','g','n','f','n','7','H','M','B','t','v','6','v','x','g','M','f','e','2','w','m','y','d','H','S','q','c','K','U','H', - '2','X','h','d','p','Q','7','J','X','i','X','f','a','z','V','A','F','2','8','z','v','h','C','h','e','4','g','z','w','z','h','q', - 'p','6','B','n','m','8','h','W','U','7','z','h','T','6','J','f','4','Z','n','Q','W','z','2','N','4','t','g','7','u','4','X','2', - 'C','F','L','n','J','n','m','j','3','P','3','Y','e','J','R','A','H','e','R','D','z','7','u','X','Y','y','D','w','J','m','G','U', - 'P','H','5','S','d','a','F','F','Y','c','M','f','3','3','L','v','V','B','U','C','A','d','N','H','Q','h','7','8','4','r','p','G', - 'v','M','D','H','7','e','E','r','i','K','Q','i','B','D','M','Z','p','c','R','G','u','c','H','a','N','k','E','f','9','R','7','x', - '6','3','5','u','x','3','h','v','p','6','q','r','j','u','f','W','T','q','P','n','Y','L','B','6','U','w','P','2','T','W','R','g', - '2','3','3','e','N','V','a','j','b','e','4','T','u','J','u','u','F','B','D','G','H','x','x','k','5','G','e','3','4','B','m','L', - 'S','b','i','t','T','p','M','D','Z','A','A','i','r','J','p','4','H','U','A','G','y','d','Q','5','U','R','F','8','q','a','S','H', - 'n','5','z','9','g','3','u','R','H','m','G','m','b','p','c','L','Z','Y','u','m','i','K','A','Q','R','T','X','G','t','b','8','7', - '7','6','w','M','N','f','R','G','r','L','m','q','n','7','5','k','X','8','g','u','K','7','Y','w','K','q','U','e','W','A','r','i', - 'Z','a','p','q','L','5','P','u','n','t','y','G','x','C','N','X','q','P','r','U','v','A','r','r','q','e','f','c','z','M','7','N', - '6','a','z','Z','a','t','f','p','4','v','J','Y','j','h','M','D','t','k','A','B','p','Q','A','y','x','X','7','p','S','8','m','M', - 'y','K','B','A','5','2','7','b','y','R','K','q','A','u','3','J'}; - -static const adler32_test tests[] = { - {__LINE__, 0x1, (const uint8_t *)0x0, 0, 0x1}, - {__LINE__, 0x1, (const uint8_t *)"", 1, 0x10001}, - {__LINE__, 0x1, (const uint8_t *)"a", 1, 0x620062}, - {__LINE__, 0x1, (const uint8_t *)"abacus", 6, 0x8400270}, - {__LINE__, 0x1, (const uint8_t *)"backlog", 7, 0xb1f02d4}, - {__LINE__, 0x1, (const uint8_t *)"campfire", 8, 0xea10348}, - {__LINE__, 0x1, (const uint8_t *)"delta", 5, 0x61a020b}, - {__LINE__, 0x1, (const uint8_t *)"executable", 10, 0x16fa0423}, - {__LINE__, 0x1, (const uint8_t *)"file", 4, 0x41401a1}, - {__LINE__, 0x1, (const uint8_t *)"greatest", 8, 0xefa0360}, - {__LINE__, 0x1, (const uint8_t *)"inverter", 8, 0xf6f0370}, - {__LINE__, 0x1, (const uint8_t *)"jigsaw", 6, 0x8bd0286}, - {__LINE__, 0x1, (const uint8_t *)"karate", 6, 0x8a50279}, - {__LINE__, 0x1, (const uint8_t *)"landscape", 9, 0x126a03ac}, - {__LINE__, 0x1, (const uint8_t *)"machine", 7, 0xb5302d6}, - {__LINE__, 0x1, (const uint8_t *)"nanometer", 9, 0x12d803ca}, - {__LINE__, 0x1, (const uint8_t *)"oblivion", 8, 0xf220363}, - {__LINE__, 0x1, (const uint8_t *)"panama", 6, 0x8a1026f}, - {__LINE__, 0x1, (const uint8_t *)"quest", 5, 0x6970233}, - {__LINE__, 0x1, (const uint8_t *)"resource", 8, 0xf8d0369}, - {__LINE__, 0x1, (const uint8_t *)"secret", 6, 0x8d10287}, - {__LINE__, 0x1, (const uint8_t *)"ultimate", 8, 0xf8d0366}, - {__LINE__, 0x1, (const uint8_t *)"vector", 6, 0x8fb0294}, - {__LINE__, 0x1, (const uint8_t *)"walrus", 6, 0x918029f}, - {__LINE__, 0x1, (const uint8_t *)"xeno", 4, 0x45e01bb}, - {__LINE__, 0x1, (const uint8_t *)"yelling", 7, 0xbfe02f5}, - {__LINE__, 0x1, (const uint8_t *)"zero", 4, 0x46e01c1}, - {__LINE__, 0x1, (const uint8_t *)"4BJD7PocN1VqX0jXVpWB", 20, 0x3eef064d}, - {__LINE__, 0x1, (const uint8_t *)"F1rPWI7XvDs6nAIRx41l", 20, 0x425d065f}, - {__LINE__, 0x1, (const uint8_t *)"ldhKlsVkPFOveXgkGtC2", 20, 0x4f1a073e}, - {__LINE__, 0x1, (const uint8_t *)"5KKnGOOrs8BvJ35iKTOS", 20, 0x42290650}, - {__LINE__, 0x1, (const uint8_t *)"0l1tw7GOcem06Ddu7yn4", 20, 0x43fd0690}, - {__LINE__, 0x1, (const uint8_t *)"MCr47CjPIn9R1IvE1Tm5", 20, 0x3f770609}, - {__LINE__, 0x1, (const uint8_t *)"UcixbzPKTIv0SvILHVdO", 20, 0x4c7c0703}, - {__LINE__, 0x1, (const uint8_t *)"dGnAyAhRQDsWw0ESou24", 20, 0x48ac06b7}, - {__LINE__, 0x1, (const uint8_t *)"di0nvmY9UYMYDh0r45XT", 20, 0x489a0698}, - {__LINE__, 0x1, (const uint8_t *)"2XKDwHfAhFsV0RhbqtvH", 20, 0x44a906e6}, - {__LINE__, 0x1, (const uint8_t *)"ZhrANFIiIvRnqClIVyeD", 20, 0x4a29071c}, - {__LINE__, 0x1, (const uint8_t *)"v7Q9ehzioTOVeDIZioT1", 20, 0x4a7706f9}, - {__LINE__, 0x1, (const uint8_t *)"Yod5hEeKcYqyhfXbhxj2", 20, 0x4ce60769}, - {__LINE__, 0x1, (const uint8_t *)"GehSWY2ay4uUKhehXYb0", 20, 0x48ae06e5}, - {__LINE__, 0x1, (const uint8_t *)"kwytJmq6UqpflV8Y8GoE", 20, 0x51d60750}, - {__LINE__, 0x1, (const uint8_t *)"70684206568419061514", 20, 0x2b100414}, - {__LINE__, 0x1, (const uint8_t *)"42015093765128581010", 20, 0x2a550405}, - {__LINE__, 0x1, (const uint8_t *)"88214814356148806939", 20, 0x2b450423}, - {__LINE__, 0x1, (const uint8_t *)"43472694284527343838", 20, 0x2b460421}, - {__LINE__, 0x1, (const uint8_t *)"49769333513942933689", 20, 0x2bc1042b}, - {__LINE__, 0x1, (const uint8_t *)"54979784887993251199", 20, 0x2ccd043d}, - {__LINE__, 0x1, (const uint8_t *)"58360544869206793220", 20, 0x2b68041a}, - {__LINE__, 0x1, (const uint8_t *)"27347953487840714234", 20, 0x2b84041d}, - {__LINE__, 0x1, (const uint8_t *)"07650690295365319082", 20, 0x2afa0417}, - {__LINE__, 0x1, (const uint8_t *)"42655507906821911703", 20, 0x2aff0412}, - {__LINE__, 0x1, (const uint8_t *)"29977409200786225655", 20, 0x2b8d0420}, - {__LINE__, 0x1, (const uint8_t *)"85181542907229116674", 20, 0x2b140419}, - {__LINE__, 0x1, (const uint8_t *)"87963594337989416799", 20, 0x2c8e043f}, - {__LINE__, 0x1, (const uint8_t *)"21395988329504168551", 20, 0x2b68041f}, - {__LINE__, 0x1, (const uint8_t *)"51991013580943379423", 20, 0x2af10417}, - {__LINE__, 0x1, (const uint8_t *)"*]+@!);({_$;}[_},?{?;(_?,=-][@", 30, 0x7c9d0841}, - {__LINE__, 0x1, (const uint8_t *)"_@:_).&(#.[:[{[:)$++-($_;@[)}+", 30, 0x71060751}, - {__LINE__, 0x1, (const uint8_t *)"&[!,[$_==}+.]@!;*(+},[;:)$;)-@", 30, 0x7095070a}, - {__LINE__, 0x1, (const uint8_t *)"]{.[.+?+[[=;[?}_#&;[=)__$$:+=_", 30, 0x82530815}, - {__LINE__, 0x1, (const uint8_t *)"-%.)=/[@].:.(:,()$;=%@-$?]{%+%", 30, 0x61250661}, - {__LINE__, 0x1, (const uint8_t *)"+]#$(@&.=:,*];/.!]%/{:){:@(;)$", 30, 0x642006a3}, - {__LINE__, 0x1, (const uint8_t *)")-._.:?[&:.=+}(*$/=!.${;(=$@!}", 30, 0x674206cb}, - {__LINE__, 0x1, (const uint8_t *)":(_*&%/[[}+,?#$&*+#[([*-/#;%(]", 30, 0x67670680}, - {__LINE__, 0x1, (const uint8_t *)"{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:", 30, 0x7547070f}, - {__LINE__, 0x1, (const uint8_t *)"_{$*,}(&,@.)):=!/%(&(,,-?$}}}!", 30, 0x69ea06ee}, - {__LINE__, 0x1, (const uint8_t *)"e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL", 100, 0x1b01e92}, - {__LINE__, 0x1, (const uint8_t *)"r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)", 100, 0xfbdb1e96}, - {__LINE__, 0x1, (const uint8_t *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 100, 0x47a61ec8}, - {__LINE__, 0x1, (const uint8_t *)long_string, 5552, 0x8b81718f}, - {__LINE__, 0x7a30360d, (const uint8_t *)0x0, 0, 0x1}, - {__LINE__, 0x6fd767ee, (const uint8_t *)"", 1, 0xd7c567ee}, - {__LINE__, 0xefeb7589, (const uint8_t *)"a", 1, 0x65e475ea}, - {__LINE__, 0x61cf7e6b, (const uint8_t *)"abacus", 6, 0x60b880da}, - {__LINE__, 0xdc712e2, (const uint8_t *)"backlog", 7, 0x9d0d15b5}, - {__LINE__, 0xad23c7fd, (const uint8_t *)"campfire", 8, 0xfbfecb44}, - {__LINE__, 0x85cb2317, (const uint8_t *)"delta", 5, 0x3b622521}, - {__LINE__, 0x9eed31b0, (const uint8_t *)"executable", 10, 0xa6db35d2}, - {__LINE__, 0xb94f34ca, (const uint8_t *)"file", 4, 0x9096366a}, - {__LINE__, 0xab058a2, (const uint8_t *)"greatest", 8, 0xded05c01}, - {__LINE__, 0x5bff2b7a, (const uint8_t *)"inverter", 8, 0xc7452ee9}, - {__LINE__, 0x605c9a5f, (const uint8_t *)"jigsaw", 6, 0x7899ce4}, - {__LINE__, 0x51bdeea5, (const uint8_t *)"karate", 6, 0xf285f11d}, - {__LINE__, 0x85c21c79, (const uint8_t *)"landscape", 9, 0x98732024}, - {__LINE__, 0x97216f56, (const uint8_t *)"machine", 7, 0xadf4722b}, - {__LINE__, 0x18444af2, (const uint8_t *)"nanometer", 9, 0xcdb34ebb}, - {__LINE__, 0xbe6ce359, (const uint8_t *)"oblivion", 8, 0xe8b7e6bb}, - {__LINE__, 0x843071f1, (const uint8_t *)"panama", 6, 0x389e745f}, - {__LINE__, 0xf2480c60, (const uint8_t *)"quest", 5, 0x36c90e92}, - {__LINE__, 0x2d2feb3d, (const uint8_t *)"resource", 8, 0x9705eea5}, - {__LINE__, 0x7490310a, (const uint8_t *)"secret", 6, 0xa3a63390}, - {__LINE__, 0x97d247d4, (const uint8_t *)"ultimate", 8, 0xe6154b39}, - {__LINE__, 0x93cf7599, (const uint8_t *)"vector", 6, 0x5e87782c}, - {__LINE__, 0x73c84278, (const uint8_t *)"walrus", 6, 0xbc84516}, - {__LINE__, 0x228a87d1, (const uint8_t *)"xeno", 4, 0x4646898b}, - {__LINE__, 0xa7a048d0, (const uint8_t *)"yelling", 7, 0xb1654bc4}, - {__LINE__, 0x1f0ded40, (const uint8_t *)"zero", 4, 0xd8a4ef00}, - {__LINE__, 0xa804a62f, (const uint8_t *)"4BJD7PocN1VqX0jXVpWB", 20, 0xe34eac7b}, - {__LINE__, 0x508fae6a, (const uint8_t *)"F1rPWI7XvDs6nAIRx41l", 20, 0x33f2b4c8}, - {__LINE__, 0xe5adaf4f, (const uint8_t *)"ldhKlsVkPFOveXgkGtC2", 20, 0xe7b1b68c}, - {__LINE__, 0x67136a40, (const uint8_t *)"5KKnGOOrs8BvJ35iKTOS", 20, 0xf6a0708f}, - {__LINE__, 0xb00c4a10, (const uint8_t *)"0l1tw7GOcem06Ddu7yn4", 20, 0xbd8f509f}, - {__LINE__, 0x2e0c84b5, (const uint8_t *)"MCr47CjPIn9R1IvE1Tm5", 20, 0xcc298abd}, - {__LINE__, 0x81238d44, (const uint8_t *)"UcixbzPKTIv0SvILHVdO", 20, 0xd7809446}, - {__LINE__, 0xf853aa92, (const uint8_t *)"dGnAyAhRQDsWw0ESou24", 20, 0x9525b148}, - {__LINE__, 0x5a692325, (const uint8_t *)"di0nvmY9UYMYDh0r45XT", 20, 0x620029bc}, - {__LINE__, 0x3275b9f, (const uint8_t *)"2XKDwHfAhFsV0RhbqtvH", 20, 0x70916284}, - {__LINE__, 0x38371feb, (const uint8_t *)"ZhrANFIiIvRnqClIVyeD", 20, 0xd52706}, - {__LINE__, 0xafc8bf62, (const uint8_t *)"v7Q9ehzioTOVeDIZioT1", 20, 0xeeb4c65a}, - {__LINE__, 0x9b07db73, (const uint8_t *)"Yod5hEeKcYqyhfXbhxj2", 20, 0xde3e2db}, - {__LINE__, 0xe75b214, (const uint8_t *)"GehSWY2ay4uUKhehXYb0", 20, 0x4171b8f8}, - {__LINE__, 0x72d0fe6f, (const uint8_t *)"kwytJmq6UqpflV8Y8GoE", 20, 0xa66a05cd}, - {__LINE__, 0xf857a4b1, (const uint8_t *)"70684206568419061514", 20, 0x1f9a8c4}, - {__LINE__, 0x54b8e14, (const uint8_t *)"42015093765128581010", 20, 0x49c19218}, - {__LINE__, 0xd6aa5616, (const uint8_t *)"88214814356148806939", 20, 0xbbfc5a38}, - {__LINE__, 0x11e63098, (const uint8_t *)"43472694284527343838", 20, 0x93434b8}, - {__LINE__, 0xbe92385, (const uint8_t *)"49769333513942933689", 20, 0xfe1827af}, - {__LINE__, 0x49511de0, (const uint8_t *)"54979784887993251199", 20, 0xcba8221c}, - {__LINE__, 0x3db13bc1, (const uint8_t *)"58360544869206793220", 20, 0x14643fda}, - {__LINE__, 0xbb899bea, (const uint8_t *)"27347953487840714234", 20, 0x1604a006}, - {__LINE__, 0xf6cd9436, (const uint8_t *)"07650690295365319082", 20, 0xb69f984c}, - {__LINE__, 0x9109e6c3, (const uint8_t *)"42655507906821911703", 20, 0xc43eead4}, - {__LINE__, 0x75770fc, (const uint8_t *)"29977409200786225655", 20, 0x707751b}, - {__LINE__, 0x69b1d19b, (const uint8_t *)"85181542907229116674", 20, 0xf5bdd5b3}, - {__LINE__, 0xc6132975, (const uint8_t *)"87963594337989416799", 20, 0x2fed2db3}, - {__LINE__, 0xd58cb00c, (const uint8_t *)"21395988329504168551", 20, 0xc2a2b42a}, - {__LINE__, 0xb63b8caa, (const uint8_t *)"51991013580943379423", 20, 0xdf0590c0}, - {__LINE__, 0x8a45a2b8, (const uint8_t *)"*]+@!);({_$;}[_},?{?;(_?,=-][@", 30, 0x1980aaf8}, - {__LINE__, 0xcbe95b78, (const uint8_t *)"_@:_).&(#.[:[{[:)$++-($_;@[)}+", 30, 0xf58662c8}, - {__LINE__, 0x4ef8a54b, (const uint8_t *)"&[!,[$_==}+.]@!;*(+},[;:)$;)-@", 30, 0x1f65ac54}, - {__LINE__, 0x76ad267a, (const uint8_t *)"]{.[.+?+[[=;[?}_#&;[=)__$$:+=_", 30, 0x7b792e8e}, - {__LINE__, 0x569e613c, (const uint8_t *)"-%.)=/[@].:.(:,()$;=%@-$?]{%+%", 30, 0x1d61679c}, - {__LINE__, 0x36aa61da, (const uint8_t *)"+]#$(@&.=:,*];/.!]%/{:){:@(;)$", 30, 0x12ec687c}, - {__LINE__, 0xf67222df, (const uint8_t *)")-._.:?[&:.=+}(*$/=!.${;(=$@!}", 30, 0x740329a9}, - {__LINE__, 0x74b34fd3, (const uint8_t *)":(_*&%/[[}+,?#$&*+#[([*-/#;%(]", 30, 0x374c5652}, - {__LINE__, 0x351fd770, (const uint8_t *)"{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:", 30, 0xeadfde7e}, - {__LINE__, 0xc45aef77, (const uint8_t *)"_{$*,}(&,@.)):=!/%(&(,,-?$}}}!", 30, 0x3fcbf664}, - {__LINE__, 0xd034ea71, (const uint8_t *)"e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL", 100, 0x6b080911}, - {__LINE__, 0xdeadc0de, (const uint8_t *)"r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)", 100, 0x355fdf73}, - {__LINE__, 0xba5eba11, (const uint8_t *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 100, 0xb48bd8d8}, - {__LINE__, 0x7712aa45, (const uint8_t *)long_string, 5552, 0x7dc51be2}, -}; - -static const int test_size = sizeof(tests) / sizeof(tests[0]); - -int main(void) { - int i; - for (i = 0; i < test_size; i++) { - test_adler32(tests[i].adler, tests[i].buf, tests[i].len, tests[i].expect, tests[i].line); - } - - return 0; -} diff --git a/libs/zlibng/test/data/fireworks.jpg b/libs/zlibng/test/data/fireworks.jpg deleted file mode 100644 index 078cf1755dc0853e97ad30fc7af4d6af0b67047e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 123093 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
ma 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

3ZRBxkF?%H#_f~x|{{V*%h1A?S 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 AYXATM diff --git a/libs/zlibng/test/data/lcet10.txt b/libs/zlibng/test/data/lcet10.txt deleted file mode 100644 index 26b187d048..0000000000 --- a/libs/zlibng/test/data/lcet10.txt +++ /dev/null @@ -1,7519 +0,0 @@ - - -The Project Gutenberg Etext of LOC WORKSHOP ON ELECTRONIC TEXTS - - - - - WORKSHOP ON ELECTRONIC TEXTS - - PROCEEDINGS - - - - Edited by James Daly - - - - - - - - 9-10 June 1992 - - - Library of Congress - Washington, D.C. - - - - Supported by a Grant from the David and Lucile Packard Foundation - - - *** *** *** ****** *** *** *** - - - TABLE OF CONTENTS - - -Acknowledgements - -Introduction - -Proceedings - Welcome - Prosser Gifford and Carl Fleischhauer - - Session I. Content in a New Form: Who Will Use It and What Will They Do? - James Daly (Moderator) - Avra Michelson, Overview - Susan H. Veccia, User Evaluation - Joanne Freeman, Beyond the Scholar - Discussion - - Session II. Show and Tell - Jacqueline Hess (Moderator) - Elli Mylonas, Perseus Project - Discussion - Eric M. Calaluca, Patrologia Latina Database - Carl Fleischhauer and Ricky Erway, American Memory - Discussion - Dorothy Twohig, The Papers of George Washington - Discussion - Maria L. Lebron, The Online Journal of Current Clinical Trials - Discussion - Lynne K. Personius, Cornell mathematics books - Discussion - - Session III. Distribution, Networks, and Networking: - Options for Dissemination - Robert G. Zich (Moderator) - Clifford A. Lynch - Discussion - Howard Besser - Discussion - Ronald L. Larsen - Edwin B. Brownrigg - Discussion - - Session IV. Image Capture, Text Capture, Overview of Text and - Image Storage Formats - William L. Hooton (Moderator) - A) Principal Methods for Image Capture of Text: - direct scanning, use of microform - Anne R. Kenney - Pamela Q.J. Andre - Judith A. Zidar - Donald J. Waters - Discussion - B) Special Problems: bound volumes, conservation, - reproducing printed halftones - George Thoma - Carl Fleischhauer - Discussion - C) Image Standards and Implications for Preservation - Jean Baronas - Patricia Battin - Discussion - D) Text Conversion: OCR vs. rekeying, standards of accuracy - and use of imperfect texts, service bureaus - Michael Lesk - Ricky Erway - Judith A. Zidar - Discussion - - Session V. Approaches to Preparing Electronic Texts - Susan Hockey (Moderator) - Stuart Weibel - Discussion - C.M. Sperberg-McQueen - Discussion - Eric M. Calaluca - Discussion - - Session VI. Copyright Issues - Marybeth Peters - - Session VII. Conclusion - Prosser Gifford (Moderator) - General discussion - -Appendix I: Program - -Appendix II: Abstracts - -Appendix III: Directory of Participants - - - *** *** *** ****** *** *** *** - - - Acknowledgements - -I would like to thank Carl Fleischhauer and Prosser Gifford for the -opportunity to learn about areas of human activity unknown to me a scant -ten months ago, and the David and Lucile Packard Foundation for -supporting that opportunity. The help given by others is acknowledged on -a separate page. - - 19 October 1992 - - - *** *** *** ****** *** *** *** - - - INTRODUCTION - -The Workshop on Electronic Texts (1) drew together representatives of -various projects and interest groups to compare ideas, beliefs, -experiences, and, in particular, methods of placing and presenting -historical textual materials in computerized form. Most attendees gained -much in insight and outlook from the event. But the assembly did not -form a new nation, or, to put it another way, the diversity of projects -and interests was too great to draw the representatives into a cohesive, -action-oriented body.(2) - -Everyone attending the Workshop shared an interest in preserving and -providing access to historical texts. But within this broad field the -attendees represented a variety of formal, informal, figurative, and -literal groups, with many individuals belonging to more than one. These -groups may be defined roughly according to the following topics or -activities: - -* Imaging -* Searchable coded texts -* National and international computer networks -* CD-ROM production and dissemination -* Methods and technology for converting older paper materials into -electronic form -* Study of the use of digital materials by scholars and others - -This summary is arranged thematically and does not follow the actual -sequence of presentations. - -NOTES: - (1) In this document, the phrase electronic text is used to mean - any computerized reproduction or version of a document, book, - article, or manuscript (including images), and not merely a machine- - readable or machine-searchable text. - - (2) The Workshop was held at the Library of Congress on 9-10 June - 1992, with funding from the David and Lucile Packard Foundation. - The document that follows represents a summary of the presentations - made at the Workshop and was compiled by James DALY. This - introduction was written by DALY and Carl FLEISCHHAUER. - - -PRESERVATION AND IMAGING - -Preservation, as that term is used by archivists,(3) was most explicitly -discussed in the context of imaging. Anne KENNEY and Lynne PERSONIUS -explained how the concept of a faithful copy and the user-friendliness of -the traditional book have guided their project at Cornell University.(4) -Although interested in computerized dissemination, participants in the -Cornell project are creating digital image sets of older books in the -public domain as a source for a fresh paper facsimile or, in a future -phase, microfilm. The books returned to the library shelves are -high-quality and useful replacements on acid-free paper that should last -a long time. To date, the Cornell project has placed little or no -emphasis on creating searchable texts; one would not be surprised to find -that the project participants view such texts as new editions, and thus -not as faithful reproductions. - -In her talk on preservation, Patricia BATTIN struck an ecumenical and -flexible note as she endorsed the creation and dissemination of a variety -of types of digital copies. Do not be too narrow in defining what counts -as a preservation element, BATTIN counseled; for the present, at least, -digital copies made with preservation in mind cannot be as narrowly -standardized as, say, microfilm copies with the same objective. Setting -standards precipitously can inhibit creativity, but delay can result in -chaos, she advised. - -In part, BATTIN's position reflected the unsettled nature of image-format -standards, and attendees could hear echoes of this unsettledness in the -comments of various speakers. For example, Jean BARONAS reviewed the -status of several formal standards moving through committees of experts; -and Clifford LYNCH encouraged the use of a new guideline for transmitting -document images on Internet. Testimony from participants in the National -Agricultural Library's (NAL) Text Digitization Program and LC's American -Memory project highlighted some of the challenges to the actual creation -or interchange of images, including difficulties in converting -preservation microfilm to digital form. Donald WATERS reported on the -progress of a master plan for a project at Yale University to convert -books on microfilm to digital image sets, Project Open Book (POB). - -The Workshop offered rather less of an imaging practicum than planned, -but "how-to" hints emerge at various points, for example, throughout -KENNEY's presentation and in the discussion of arcana such as -thresholding and dithering offered by George THOMA and FLEISCHHAUER. - -NOTES: - (3) Although there is a sense in which any reproductions of - historical materials preserve the human record, specialists in the - field have developed particular guidelines for the creation of - acceptable preservation copies. - - (4) Titles and affiliations of presenters are given at the - beginning of their respective talks and in the Directory of - Participants (Appendix III). - - -THE MACHINE-READABLE TEXT: MARKUP AND USE - -The sections of the Workshop that dealt with machine-readable text tended -to be more concerned with access and use than with preservation, at least -in the narrow technical sense. Michael SPERBERG-McQUEEN made a forceful -presentation on the Text Encoding Initiative's (TEI) implementation of -the Standard Generalized Markup Language (SGML). His ideas were echoed -by Susan HOCKEY, Elli MYLONAS, and Stuart WEIBEL. While the -presentations made by the TEI advocates contained no practicum, their -discussion focused on the value of the finished product, what the -European Community calls reusability, but what may also be termed -durability. They argued that marking up--that is, coding--a text in a -well-conceived way will permit it to be moved from one computer -environment to another, as well as to be used by various users. Two -kinds of markup were distinguished: 1) procedural markup, which -describes the features of a text (e.g., dots on a page), and 2) -descriptive markup, which describes the structure or elements of a -document (e.g., chapters, paragraphs, and front matter). - -The TEI proponents emphasized the importance of texts to scholarship. -They explained how heavily coded (and thus analyzed and annotated) texts -can underlie research, play a role in scholarly communication, and -facilitate classroom teaching. SPERBERG-McQUEEN reminded listeners that -a written or printed item (e.g., a particular edition of a book) is -merely a representation of the abstraction we call a text. To concern -ourselves with faithfully reproducing a printed instance of the text, -SPERBERG-McQUEEN argued, is to concern ourselves with the representation -of a representation ("images as simulacra for the text"). The TEI proponents' -interest in images tends to focus on corollary materials for use in teaching, -for example, photographs of the Acropolis to accompany a Greek text. - -By the end of the Workshop, SPERBERG-McQUEEN confessed to having been -converted to a limited extent to the view that electronic images -constitute a promising alternative to microfilming; indeed, an -alternative probably superior to microfilming. But he was not convinced -that electronic images constitute a serious attempt to represent text in -electronic form. HOCKEY and MYLONAS also conceded that their experience -at the Pierce Symposium the previous week at Georgetown University and -the present conference at the Library of Congress had compelled them to -reevaluate their perspective on the usefulness of text as images. -Attendees could see that the text and image advocates were in -constructive tension, so to say. - -Three nonTEI presentations described approaches to preparing -machine-readable text that are less rigorous and thus less expensive. In -the case of the Papers of George Washington, Dorothy TWOHIG explained -that the digital version will provide a not-quite-perfect rendering of -the transcribed text--some 135,000 documents, available for research -during the decades while the perfect or print version is completed. -Members of the American Memory team and the staff of NAL's Text -Digitization Program (see below) also outlined a middle ground concerning -searchable texts. In the case of American Memory, contractors produce -texts with about 99-percent accuracy that serve as "browse" or -"reference" versions of written or printed originals. End users who need -faithful copies or perfect renditions must refer to accompanying sets of -digital facsimile images or consult copies of the originals in a nearby -library or archive. American Memory staff argued that the high cost of -producing 100-percent accurate copies would prevent LC from offering -access to large parts of its collections. - - -THE MACHINE-READABLE TEXT: METHODS OF CONVERSION - -Although the Workshop did not include a systematic examination of the -methods for converting texts from paper (or from facsimile images) into -machine-readable form, nevertheless, various speakers touched upon this -matter. For example, WEIBEL reported that OCLC has experimented with a -merging of multiple optical character recognition systems that will -reduce errors from an unacceptable rate of 5 characters out of every -l,000 to an unacceptable rate of 2 characters out of every l,000. - -Pamela ANDRE presented an overview of NAL's Text Digitization Program and -Judith ZIDAR discussed the technical details. ZIDAR explained how NAL -purchased hardware and software capable of performing optical character -recognition (OCR) and text conversion and used its own staff to convert -texts. The process, ZIDAR said, required extensive editing and project -staff found themselves considering alternatives, including rekeying -and/or creating abstracts or summaries of texts. NAL reckoned costs at -$7 per page. By way of contrast, Ricky ERWAY explained that American -Memory had decided from the start to contract out conversion to external -service bureaus. The criteria used to select these contractors were cost -and quality of results, as opposed to methods of conversion. ERWAY noted -that historical documents or books often do not lend themselves to OCR. -Bound materials represent a special problem. In her experience, quality -control--inspecting incoming materials, counting errors in samples--posed -the most time-consuming aspect of contracting out conversion. ERWAY -reckoned American Memory's costs at $4 per page, but cautioned that fewer -cost-elements had been included than in NAL's figure. - - -OPTIONS FOR DISSEMINATION - -The topic of dissemination proper emerged at various points during the -Workshop. At the session devoted to national and international computer -networks, LYNCH, Howard BESSER, Ronald LARSEN, and Edwin BROWNRIGG -highlighted the virtues of Internet today and of the network that will -evolve from Internet. Listeners could discern in these narratives a -vision of an information democracy in which millions of citizens freely -find and use what they need. LYNCH noted that a lack of standards -inhibits disseminating multimedia on the network, a topic also discussed -by BESSER. LARSEN addressed the issues of network scalability and -modularity and commented upon the difficulty of anticipating the effects -of growth in orders of magnitude. BROWNRIGG talked about the ability of -packet radio to provide certain links in a network without the need for -wiring. However, the presenters also called attention to the -shortcomings and incongruities of present-day computer networks. For -example: 1) Network use is growing dramatically, but much network -traffic consists of personal communication (E-mail). 2) Large bodies of -information are available, but a user's ability to search across their -entirety is limited. 3) There are significant resources for science and -technology, but few network sources provide content in the humanities. -4) Machine-readable texts are commonplace, but the capability of the -system to deal with images (let alone other media formats) lags behind. -A glimpse of a multimedia future for networks, however, was provided by -Maria LEBRON in her overview of the Online Journal of Current Clinical -Trials (OJCCT), and the process of scholarly publishing on-line. - -The contrasting form of the CD-ROM disk was never systematically -analyzed, but attendees could glean an impression from several of the -show-and-tell presentations. The Perseus and American Memory examples -demonstrated recently published disks, while the descriptions of the -IBYCUS version of the Papers of George Washington and Chadwyck-Healey's -Patrologia Latina Database (PLD) told of disks to come. According to -Eric CALALUCA, PLD's principal focus has been on converting Jacques-Paul -Migne's definitive collection of Latin texts to machine-readable form. -Although everyone could share the network advocates' enthusiasm for an -on-line future, the possibility of rolling up one's sleeves for a session -with a CD-ROM containing both textual materials and a powerful retrieval -engine made the disk seem an appealing vessel indeed. The overall -discussion suggested that the transition from CD-ROM to on-line networked -access may prove far slower and more difficult than has been anticipated. - - -WHO ARE THE USERS AND WHAT DO THEY DO? - -Although concerned with the technicalities of production, the Workshop -never lost sight of the purposes and uses of electronic versions of -textual materials. As noted above, those interested in imaging discussed -the problematical matter of digital preservation, while the TEI proponents -described how machine-readable texts can be used in research. This latter -topic received thorough treatment in the paper read by Avra MICHELSON. -She placed the phenomenon of electronic texts within the context of -broader trends in information technology and scholarly communication. - -Among other things, MICHELSON described on-line conferences that -represent a vigorous and important intellectual forum for certain -disciplines. Internet now carries more than 700 conferences, with about -80 percent of these devoted to topics in the social sciences and the -humanities. Other scholars use on-line networks for "distance learning." -Meanwhile, there has been a tremendous growth in end-user computing; -professors today are less likely than their predecessors to ask the -campus computer center to process their data. Electronic texts are one -key to these sophisticated applications, MICHELSON reported, and more and -more scholars in the humanities now work in an on-line environment. -Toward the end of the Workshop, Michael LESK presented a corollary to -MICHELSON's talk, reporting the results of an experiment that compared -the work of one group of chemistry students using traditional printed -texts and two groups using electronic sources. The experiment -demonstrated that in the event one does not know what to read, one needs -the electronic systems; the electronic systems hold no advantage at the -moment if one knows what to read, but neither do they impose a penalty. - -DALY provided an anecdotal account of the revolutionizing impact of the -new technology on his previous methods of research in the field of classics. -His account, by extrapolation, served to illustrate in part the arguments -made by MICHELSON concerning the positive effects of the sudden and radical -transformation being wrought in the ways scholars work. - -Susan VECCIA and Joanne FREEMAN delineated the use of electronic -materials outside the university. The most interesting aspect of their -use, FREEMAN said, could be seen as a paradox: teachers in elementary -and secondary schools requested access to primary source materials but, -at the same time, found that "primariness" itself made these materials -difficult for their students to use. - - -OTHER TOPICS - -Marybeth PETERS reviewed copyright law in the United States and offered -advice during a lively discussion of this subject. But uncertainty -remains concerning the price of copyright in a digital medium, because a -solution remains to be worked out concerning management and synthesis of -copyrighted and out-of-copyright pieces of a database. - -As moderator of the final session of the Workshop, Prosser GIFFORD directed -discussion to future courses of action and the potential role of LC in -advancing them. Among the recommendations that emerged were the following: - - * Workshop participants should 1) begin to think about working - with image material, but structure and digitize it in such a - way that at a later stage it can be interpreted into text, and - 2) find a common way to build text and images together so that - they can be used jointly at some stage in the future, with - appropriate network support, because that is how users will want - to access these materials. The Library might encourage attempts - to bring together people who are working on texts and images. - - * A network version of American Memory should be developed or - consideration should be given to making the data in it - available to people interested in doing network multimedia. - Given the current dearth of digital data that is appealing and - unencumbered by extremely complex rights problems, developing a - network version of American Memory could do much to help make - network multimedia a reality. - - * Concerning the thorny issue of electronic deposit, LC should - initiate a catalytic process in terms of distributed - responsibility, that is, bring together the distributed - organizations and set up a study group to look at all the - issues related to electronic deposit and see where we as a - nation should move. For example, LC might attempt to persuade - one major library in each state to deal with its state - equivalent publisher, which might produce a cooperative project - that would be equitably distributed around the country, and one - in which LC would be dealing with a minimal number of publishers - and minimal copyright problems. LC must also deal with the - concept of on-line publishing, determining, among other things, - how serials such as OJCCT might be deposited for copyright. - - * Since a number of projects are planning to carry out - preservation by creating digital images that will end up in - on-line or near-line storage at some institution, LC might play - a helpful role, at least in the near term, by accelerating how - to catalog that information into the Research Library Information - Network (RLIN) and then into OCLC, so that it would be accessible. - This would reduce the possibility of multiple institutions digitizing - the same work. - - -CONCLUSION - -The Workshop was valuable because it brought together partisans from -various groups and provided an occasion to compare goals and methods. -The more committed partisans frequently communicate with others in their -groups, but less often across group boundaries. The Workshop was also -valuable to attendees--including those involved with American Memory--who -came less committed to particular approaches or concepts. These -attendees learned a great deal, and plan to select and employ elements of -imaging, text-coding, and networked distribution that suit their -respective projects and purposes. - -Still, reality rears its ugly head: no breakthrough has been achieved. -On the imaging side, one confronts a proliferation of competing -data-interchange standards and a lack of consensus on the role of digital -facsimiles in preservation. In the realm of machine-readable texts, one -encounters a reasonably mature standard but methodological difficulties -and high costs. These latter problems, of course, represent a special -impediment to the desire, as it is sometimes expressed in the popular -press, "to put the [contents of the] Library of Congress on line." In -the words of one participant, there was "no solution to the economic -problems--the projects that are out there are surviving, but it is going -to be a lot of work to transform the information industry, and so far the -investment to do that is not forthcoming" (LESK, per litteras). - - - *** *** *** ****** *** *** *** - - - PROCEEDINGS - - -WELCOME - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -GIFFORD * Origin of Workshop in current Librarian's desire to make LC's -collections more widely available * Desiderata arising from the prospect -of greater interconnectedness * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -After welcoming participants on behalf of the Library of Congress, -American Memory (AM), and the National Demonstration Lab, Prosser -GIFFORD, director for scholarly programs, Library of Congress, located -the origin of the Workshop on Electronic Texts in a conversation he had -had considerably more than a year ago with Carl FLEISCHHAUER concerning -some of the issues faced by AM. On the assumption that numerous other -people were asking the same questions, the decision was made to bring -together as many of these people as possible to ask the same questions -together. In a deeper sense, GIFFORD said, the origin of the Workshop -lay in the desire of the current Librarian of Congress, James H. -Billington, to make the collections of the Library, especially those -offering unique or unusual testimony on aspects of the American -experience, available to a much wider circle of users than those few -people who can come to Washington to use them. This meant that the -emphasis of AM, from the outset, has been on archival collections of the -basic material, and on making these collections themselves available, -rather than selected or heavily edited products. - -From AM's emphasis followed the questions with which the Workshop began: -who will use these materials, and in what form will they wish to use -them. But an even larger issue deserving mention, in GIFFORD's view, was -the phenomenal growth in Internet connectivity. He expressed the hope -that the prospect of greater interconnectedness than ever before would -lead to: 1) much more cooperative and mutually supportive endeavors; 2) -development of systems of shared and distributed responsibilities to -avoid duplication and to ensure accuracy and preservation of unique -materials; and 3) agreement on the necessary standards and development of -the appropriate directories and indices to make navigation -straightforward among the varied resources that are, and increasingly -will be, available. In this connection, GIFFORD requested that -participants reflect from the outset upon the sorts of outcomes they -thought the Workshop might have. Did those present constitute a group -with sufficient common interests to propose a next step or next steps, -and if so, what might those be? They would return to these questions the -following afternoon. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -FLEISCHHAUER * Core of Workshop concerns preparation and production of -materials * Special challenge in conversion of textual materials * -Quality versus quantity * Do the several groups represented share common -interests? * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Carl FLEISCHHAUER, coordinator, American Memory, Library of Congress, -emphasized that he would attempt to represent the people who perform some -of the work of converting or preparing materials and that the core of -the Workshop had to do with preparation and production. FLEISCHHAUER -then drew a distinction between the long term, when many things would be -available and connected in the ways that GIFFORD described, and the short -term, in which AM not only has wrestled with the issue of what is the -best course to pursue but also has faced a variety of technical -challenges. - -FLEISCHHAUER remarked AM's endeavors to deal with a wide range of library -formats, such as motion picture collections, sound-recording collections, -and pictorial collections of various sorts, especially collections of -photographs. In the course of these efforts, AM kept coming back to -textual materials--manuscripts or rare printed matter, bound materials, -etc. Text posed the greatest conversion challenge of all. Thus, the -genesis of the Workshop, which reflects the problems faced by AM. These -problems include physical problems. For example, those in the library -and archive business deal with collections made up of fragile and rare -manuscript items, bound materials, especially the notoriously brittle -bound materials of the late nineteenth century. These are precious -cultural artifacts, however, as well as interesting sources of -information, and LC desires to retain and conserve them. AM needs to -handle things without damaging them. Guillotining a book to run it -through a sheet feeder must be avoided at all costs. - -Beyond physical problems, issues pertaining to quality arose. For -example, the desire to provide users with a searchable text is affected -by the question of acceptable level of accuracy. One hundred percent -accuracy is tremendously expensive. On the other hand, the output of -optical character recognition (OCR) can be tremendously inaccurate. -Although AM has attempted to find a middle ground, uncertainty persists -as to whether or not it has discovered the right solution. - -Questions of quality arose concerning images as well. FLEISCHHAUER -contrasted the extremely high level of quality of the digital images in -the Cornell Xerox Project with AM's efforts to provide a browse-quality -or access-quality image, as opposed to an archival or preservation image. -FLEISCHHAUER therefore welcomed the opportunity to compare notes. - -FLEISCHHAUER observed in passing that conversations he had had about -networks have begun to signal that for various forms of media a -determination may be made that there is a browse-quality item, or a -distribution-and-access-quality item that may coexist in some systems -with a higher quality archival item that would be inconvenient to send -through the network because of its size. FLEISCHHAUER referred, of -course, to images more than to searchable text. - -As AM considered those questions, several conceptual issues arose: ought -AM occasionally to reproduce materials entirely through an image set, at -other times, entirely through a text set, and in some cases, a mix? -There probably would be times when the historical authenticity of an -artifact would require that its image be used. An image might be -desirable as a recourse for users if one could not provide 100-percent -accurate text. Again, AM wondered, as a practical matter, if a -distinction could be drawn between rare printed matter that might exist -in multiple collections--that is, in ten or fifteen libraries. In such -cases, the need for perfect reproduction would be less than for unique -items. Implicit in his remarks, FLEISCHHAUER conceded, was the admission -that AM has been tilting strongly towards quantity and drawing back a -little from perfect quality. That is, it seemed to AM that society would -be better served if more things were distributed by LC--even if they were -not quite perfect--than if fewer things, perfectly represented, were -distributed. This was stated as a proposition to be tested, with -responses to be gathered from users. - -In thinking about issues related to reproduction of materials and seeing -other people engaged in parallel activities, AM deemed it useful to -convene a conference. Hence, the Workshop. FLEISCHHAUER thereupon -surveyed the several groups represented: 1) the world of images (image -users and image makers); 2) the world of text and scholarship and, within -this group, those concerned with language--FLEISCHHAUER confessed to finding -delightful irony in the fact that some of the most advanced thinkers on -computerized texts are those dealing with ancient Greek and Roman materials; -3) the network world; and 4) the general world of library science, which -includes people interested in preservation and cataloging. - -FLEISCHHAUER concluded his remarks with special thanks to the David and -Lucile Packard Foundation for its support of the meeting, the American -Memory group, the Office for Scholarly Programs, the National -Demonstration Lab, and the Office of Special Events. He expressed the -hope that David Woodley Packard might be able to attend, noting that -Packard's work and the work of the foundation had sponsored a number of -projects in the text area. - - ****** - -SESSION I. CONTENT IN A NEW FORM: WHO WILL USE IT AND WHAT WILL THEY DO? - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DALY * Acknowledgements * A new Latin authors disk * Effects of the new -technology on previous methods of research * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Serving as moderator, James DALY acknowledged the generosity of all the -presenters for giving of their time, counsel, and patience in planning -the Workshop, as well as of members of the American Memory project and -other Library of Congress staff, and the David and Lucile Packard -Foundation and its executive director, Colburn S. Wilbur. - -DALY then recounted his visit in March to the Center for Electronic Texts -in the Humanities (CETH) and the Department of Classics at Rutgers -University, where an old friend, Lowell Edmunds, introduced him to the -department's IBYCUS scholarly personal computer, and, in particular, the -new Latin CD-ROM, containing, among other things, almost all classical -Latin literary texts through A.D. 200. Packard Humanities Institute -(PHI), Los Altos, California, released this disk late in 1991, with a -nominal triennial licensing fee. - -Playing with the disk for an hour or so at Rutgers brought home to DALY -at once the revolutionizing impact of the new technology on his previous -methods of research. Had this disk been available two or three years -earlier, DALY contended, when he was engaged in preparing a commentary on -Book 10 of Virgil's Aeneid for Cambridge University Press, he would not -have required a forty-eight-square-foot table on which to spread the -numerous, most frequently consulted items, including some ten or twelve -concordances to key Latin authors, an almost equal number of lexica to -authors who lacked concordances, and where either lexica or concordances -were lacking, numerous editions of authors antedating and postdating Virgil. - -Nor, when checking each of the average six to seven words contained in -the Virgilian hexameter for its usage elsewhere in Virgil's works or -other Latin authors, would DALY have had to maintain the laborious -mechanical process of flipping through these concordances, lexica, and -editions each time. Nor would he have had to frequent as often the -Milton S. Eisenhower Library at the Johns Hopkins University to consult -the Thesaurus Linguae Latinae. Instead of devoting countless hours, or -the bulk of his research time, to gathering data concerning Virgil's use -of words, DALY--now freed by PHI's Latin authors disk from the -tyrannical, yet in some ways paradoxically happy scholarly drudgery-- -would have been able to devote that same bulk of time to analyzing and -interpreting Virgilian verbal usage. - -Citing Theodore Brunner, Gregory Crane, Elli MYLONAS, and Avra MICHELSON, -DALY argued that this reversal in his style of work, made possible by the -new technology, would perhaps have resulted in better, more productive -research. Indeed, even in the course of his browsing the Latin authors -disk at Rutgers, its powerful search, retrieval, and highlighting -capabilities suggested to him several new avenues of research into -Virgil's use of sound effects. This anecdotal account, DALY maintained, -may serve to illustrate in part the sudden and radical transformation -being wrought in the ways scholars work. - - ****** - -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -MICHELSON * Elements related to scholarship and technology * Electronic -texts within the context of broader trends within information technology -and scholarly communication * Evaluation of the prospects for the use of -electronic texts * Relationship of electronic texts to processes of -scholarly communication in humanities research * New exchange formats -created by scholars * Projects initiated to increase scholarly access to -converted text * Trend toward making electronic resources available -through research and education networks * Changes taking place in -scholarly communication among humanities scholars * Network-mediated -scholarship transforming traditional scholarly practices * Key -information technology trends affecting the conduct of scholarly -communication over the next decade * The trend toward end-user computing -* The trend toward greater connectivity * Effects of these trends * Key -transformations taking place * Summary of principal arguments * -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Avra MICHELSON, Archival Research and Evaluation Staff, National Archives -and Records Administration (NARA), argued that establishing who will use -electronic texts and what they will use them for involves a consideration -of both information technology and scholarship trends. This -consideration includes several elements related to scholarship and -technology: 1) the key trends in information technology that are most -relevant to scholarship; 2) the key trends in the use of currently -available technology by scholars in the nonscientific community; and 3) -the relationship between these two very distinct but interrelated trends. -The investment in understanding this relationship being made by -information providers, technologists, and public policy developers, as -well as by scholars themselves, seems to be pervasive and growing, -MICHELSON contended. She drew on collaborative work with Jeff Rothenberg -on the scholarly use of technology. - -MICHELSON sought to place the phenomenon of electronic texts within the -context of broader trends within information technology and scholarly -communication. She argued that electronic texts are of most use to -researchers to the extent that the researchers' working context (i.e., -their relevant bibliographic sources, collegial feedback, analytic tools, -notes, drafts, etc.), along with their field's primary and secondary -sources, also is accessible in electronic form and can be integrated in -ways that are unique to the on-line environment. - -Evaluation of the prospects for the use of electronic texts includes two -elements: 1) an examination of the ways in which researchers currently -are using electronic texts along with other electronic resources, and 2) -an analysis of key information technology trends that are affecting the -long-term conduct of scholarly communication. MICHELSON limited her -discussion of the use of electronic texts to the practices of humanists -and noted that the scientific community was outside the panel's overview. - -MICHELSON examined the nature of the current relationship of electronic -texts in particular, and electronic resources in general, to what she -maintained were, essentially, five processes of scholarly communication -in humanities research. Researchers 1) identify sources, 2) communicate -with their colleagues, 3) interpret and analyze data, 4) disseminate -their research findings, and 5) prepare curricula to instruct the next -generation of scholars and students. This examination would produce a -clearer understanding of the synergy among these five processes that -fuels the tendency of the use of electronic resources for one process to -stimulate its use for other processes of scholarly communication. - -For the first process of scholarly communication, the identification of -sources, MICHELSON remarked the opportunity scholars now enjoy to -supplement traditional word-of-mouth searches for sources among their -colleagues with new forms of electronic searching. So, for example, -instead of having to visit the library, researchers are able to explore -descriptions of holdings in their offices. Furthermore, if their own -institutions' holdings prove insufficient, scholars can access more than -200 major American library catalogues over Internet, including the -universities of California, Michigan, Pennsylvania, and Wisconsin. -Direct access to the bibliographic databases offers intellectual -empowerment to scholars by presenting a comprehensive means of browsing -through libraries from their homes and offices at their convenience. - -The second process of communication involves communication among -scholars. Beyond the most common methods of communication, scholars are -using E-mail and a variety of new electronic communications formats -derived from it for further academic interchange. E-mail exchanges are -growing at an astonishing rate, reportedly 15 percent a month. They -currently constitute approximately half the traffic on research and -education networks. Moreover, the global spread of E-mail has been so -rapid that it is now possible for American scholars to use it to -communicate with colleagues in close to 140 other countries. - -Other new exchange formats created by scholars and operating on Internet -include more than 700 conferences, with about 80 percent of these devoted -to topics in the social sciences and humanities. The rate of growth of -these scholarly electronic conferences also is astonishing. From l990 to -l991, 200 new conferences were identified on Internet. From October 1991 -to June 1992, an additional 150 conferences in the social sciences and -humanities were added to this directory of listings. Scholars have -established conferences in virtually every field, within every different -discipline. For example, there are currently close to 600 active social -science and humanities conferences on topics such as art and -architecture, ethnomusicology, folklore, Japanese culture, medical -education, and gifted and talented education. The appeal to scholars of -communicating through these conferences is that, unlike any other medium, -electronic conferences today provide a forum for global communication -with peers at the front end of the research process. - -Interpretation and analysis of sources constitutes the third process of -scholarly communication that MICHELSON discussed in terms of texts and -textual resources. The methods used to analyze sources fall somewhere on -a continuum from quantitative analysis to qualitative analysis. -Typically, evidence is culled and evaluated using methods drawn from both -ends of this continuum. At one end, quantitative analysis involves the -use of mathematical processes such as a count of frequencies and -distributions of occurrences or, on a higher level, regression analysis. -At the other end of the continuum, qualitative analysis typically -involves nonmathematical processes oriented toward language -interpretation or the building of theory. Aspects of this work involve -the processing--either manual or computational--of large and sometimes -massive amounts of textual sources, although the use of nontextual -sources as evidence, such as photographs, sound recordings, film footage, -and artifacts, is significant as well. - -Scholars have discovered that many of the methods of interpretation and -analysis that are related to both quantitative and qualitative methods -are processes that can be performed by computers. For example, computers -can count. They can count brush strokes used in a Rembrandt painting or -perform regression analysis for understanding cause and effect. By means -of advanced technologies, computers can recognize patterns, analyze text, -and model concepts. Furthermore, computers can complete these processes -faster with more sources and with greater precision than scholars who -must rely on manual interpretation of data. But if scholars are to use -computers for these processes, source materials must be in a form -amenable to computer-assisted analysis. For this reason many scholars, -once they have identified the sources that are key to their research, are -converting them to machine-readable form. Thus, a representative example -of the numerous textual conversion projects organized by scholars around -the world in recent years to support computational text analysis is the -TLG, the Thesaurus Linguae Graecae. This project is devoted to -converting the extant ancient texts of classical Greece. (Editor's note: -according to the TLG Newsletter of May l992, TLG was in use in thirty-two -different countries. This figure updates MICHELSON's previous count by one.) - -The scholars performing these conversions have been asked to recognize -that the electronic sources they are converting for one use possess value -for other research purposes as well. As a result, during the past few -years, humanities scholars have initiated a number of projects to -increase scholarly access to converted text. So, for example, the Text -Encoding Initiative (TEI), about which more is said later in the program, -was established as an effort by scholars to determine standard elements -and methods for encoding machine-readable text for electronic exchange. -In a second effort to facilitate the sharing of converted text, scholars -have created a new institution, the Center for Electronic Texts in the -Humanities (CETH). The center estimates that there are 8,000 series of -source texts in the humanities that have been converted to -machine-readable form worldwide. CETH is undertaking an international -search for converted text in the humanities, compiling it into an -electronic library, and preparing bibliographic descriptions of the -sources for the Research Libraries Information Network's (RLIN) -machine-readable data file. The library profession has begun to initiate -large conversion projects as well, such as American Memory. - -While scholars have been making converted text available to one another, -typically on disk or on CD-ROM, the clear trend is toward making these -resources available through research and education networks. Thus, the -American and French Research on the Treasury of the French Language -(ARTFL) and the Dante Project are already available on Internet. -MICHELSON summarized this section on interpretation and analysis by -noting that: 1) increasing numbers of humanities scholars in the library -community are recognizing the importance to the advancement of -scholarship of retrospective conversion of source materials in the arts -and humanities; and 2) there is a growing realization that making the -sources available on research and education networks maximizes their -usefulness for the analysis performed by humanities scholars. - -The fourth process of scholarly communication is dissemination of -research findings, that is, publication. Scholars are using existing -research and education networks to engineer a new type of publication: -scholarly-controlled journals that are electronically produced and -disseminated. Although such journals are still emerging as a -communication format, their number has grown, from approximately twelve -to thirty-six during the past year (July 1991 to June 1992). Most of -these electronic scholarly journals are devoted to topics in the -humanities. As with network conferences, scholarly enthusiasm for these -electronic journals stems from the medium's unique ability to advance -scholarship in a way that no other medium can do by supporting global -feedback and interchange, practically in real time, early in the research -process. Beyond scholarly journals, MICHELSON remarked the delivery of -commercial full-text products, such as articles in professional journals, -newsletters, magazines, wire services, and reference sources. These are -being delivered via on-line local library catalogues, especially through -CD-ROMs. Furthermore, according to MICHELSON, there is general optimism -that the copyright and fees issues impeding the delivery of full text on -existing research and education networks soon will be resolved. - -The final process of scholarly communication is curriculum development -and instruction, and this involves the use of computer information -technologies in two areas. The first is the development of -computer-oriented instructional tools, which includes simulations, -multimedia applications, and computer tools that are used to assist in -the analysis of sources in the classroom, etc. The Perseus Project, a -database that provides a multimedia curriculum on classical Greek -civilization, is a good example of the way in which entire curricula are -being recast using information technologies. It is anticipated that the -current difficulty in exchanging electronically computer-based -instructional software, which in turn makes it difficult for one scholar -to build upon the work of others, will be resolved before too long. -Stand-alone curricular applications that involve electronic text will be -sharable through networks, reinforcing their significance as intellectual -products as well as instructional tools. - -The second aspect of electronic learning involves the use of research and -education networks for distance education programs. Such programs -interactively link teachers with students in geographically scattered -locations and rely on the availability of electronic instructional -resources. Distance education programs are gaining wide appeal among -state departments of education because of their demonstrated capacity to -bring advanced specialized course work and an array of experts to many -classrooms. A recent report found that at least 32 states operated at -least one statewide network for education in 1991, with networks under -development in many of the remaining states. - -MICHELSON summarized this section by noting two striking changes taking -place in scholarly communication among humanities scholars. First is the -extent to which electronic text in particular, and electronic resources -in general, are being infused into each of the five processes described -above. As mentioned earlier, there is a certain synergy at work here. -The use of electronic resources for one process tends to stimulate its -use for other processes, because the chief course of movement is toward a -comprehensive on-line working context for humanities scholars that -includes on-line availability of key bibliographies, scholarly feedback, -sources, analytical tools, and publications. MICHELSON noted further -that the movement toward a comprehensive on-line working context for -humanities scholars is not new. In fact, it has been underway for more -than forty years in the humanities, since Father Roberto Busa began -developing an electronic concordance of the works of Saint Thomas Aquinas -in 1949. What we are witnessing today, MICHELSON contended, is not the -beginning of this on-line transition but, for at least some humanities -scholars, the turning point in the transition from a print to an -electronic working context. Coinciding with the on-line transition, the -second striking change is the extent to which research and education -networks are becoming the new medium of scholarly communication. The -existing Internet and the pending National Education and Research Network -(NREN) represent the new meeting ground where scholars are going for -bibliographic information, scholarly dialogue and feedback, the most -current publications in their field, and high-level educational -offerings. Traditional scholarly practices are undergoing tremendous -transformations as a result of the emergence and growing prominence of -what is called network-mediated scholarship. - -MICHELSON next turned to the second element of the framework she proposed -at the outset of her talk for evaluating the prospects for electronic -text, namely the key information technology trends affecting the conduct -of scholarly communication over the next decade: 1) end-user computing -and 2) connectivity. - -End-user computing means that the person touching the keyboard, or -performing computations, is the same as the person who initiates or -consumes the computation. The emergence of personal computers, along -with a host of other forces, such as ubiquitous computing, advances in -interface design, and the on-line transition, is prompting the consumers -of computation to do their own computing, and is thus rendering obsolete -the traditional distinction between end users and ultimate users. - -The trend toward end-user computing is significant to consideration of -the prospects for electronic texts because it means that researchers are -becoming more adept at doing their own computations and, thus, more -competent in the use of electronic media. By avoiding programmer -intermediaries, computation is becoming central to the researcher's -thought process. This direct involvement in computing is changing the -researcher's perspective on the nature of research itself, that is, the -kinds of questions that can be posed, the analytical methodologies that -can be used, the types and amount of sources that are appropriate for -analyses, and the form in which findings are presented. The trend toward -end-user computing means that, increasingly, electronic media and -computation are being infused into all processes of humanities -scholarship, inspiring remarkable transformations in scholarly -communication. - -The trend toward greater connectivity suggests that researchers are using -computation increasingly in network environments. Connectivity is -important to scholarship because it erases the distance that separates -students from teachers and scholars from their colleagues, while allowing -users to access remote databases, share information in many different -media, connect to their working context wherever they are, and -collaborate in all phases of research. - -The combination of the trend toward end-user computing and the trend -toward connectivity suggests that the scholarly use of electronic -resources, already evident among some researchers, will soon become an -established feature of scholarship. The effects of these trends, along -with ongoing changes in scholarly practices, point to a future in which -humanities researchers will use computation and electronic communication -to help them formulate ideas, access sources, perform research, -collaborate with colleagues, seek peer review, publish and disseminate -results, and engage in many other professional and educational activities. - -In summary, MICHELSON emphasized four points: 1) A portion of humanities -scholars already consider electronic texts the preferred format for -analysis and dissemination. 2) Scholars are using these electronic -texts, in conjunction with other electronic resources, in all the -processes of scholarly communication. 3) The humanities scholars' -working context is in the process of changing from print technology to -electronic technology, in many ways mirroring transformations that have -occurred or are occurring within the scientific community. 4) These -changes are occurring in conjunction with the development of a new -communication medium: research and education networks that are -characterized by their capacity to advance scholarship in a wholly unique -way. - -MICHELSON also reiterated her three principal arguments: l) Electronic -texts are best understood in terms of the relationship to other -electronic resources and the growing prominence of network-mediated -scholarship. 2) The prospects for electronic texts lie in their capacity -to be integrated into the on-line network of electronic resources that -comprise the new working context for scholars. 3) Retrospective conversion -of portions of the scholarly record should be a key strategy as information -providers respond to changes in scholarly communication practices. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -VECCIA * AM's evaluation project and public users of electronic resources -* AM and its design * Site selection and evaluating the Macintosh -implementation of AM * Characteristics of the six public libraries -selected * Characteristics of AM's users in these libraries * Principal -ways AM is being used * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Susan VECCIA, team leader, and Joanne FREEMAN, associate coordinator, -American Memory, Library of Congress, gave a joint presentation. First, -by way of introduction, VECCIA explained her and FREEMAN's roles in -American Memory (AM). Serving principally as an observer, VECCIA has -assisted with the evaluation project of AM, placing AM collections in a -variety of different sites around the country and helping to organize and -implement that project. FREEMAN has been an associate coordinator of AM -and has been involved principally with the interpretative materials, -preparing some of the electronic exhibits and printed historical -information that accompanies AM and that is requested by users. VECCIA -and FREEMAN shared anecdotal observations concerning AM with public users -of electronic resources. Notwithstanding a fairly structured evaluation -in progress, both VECCIA and FREEMAN chose not to report on specifics in -terms of numbers, etc., because they felt it was too early in the -evaluation project to do so. - -AM is an electronic archive of primary source materials from the Library -of Congress, selected collections representing a variety of formats-- -photographs, graphic arts, recorded sound, motion pictures, broadsides, -and soon, pamphlets and books. In terms of the design of this system, -the interpretative exhibits have been kept separate from the primary -resources, with good reason. Accompanying this collection are printed -documentation and user guides, as well as guides that FREEMAN prepared for -teachers so that they may begin using the content of the system at once. - -VECCIA described the evaluation project before talking about the public -users of AM, limiting her remarks to public libraries, because FREEMAN -would talk more specifically about schools from kindergarten to twelfth -grade (K-12). Having started in spring 1991, the evaluation currently -involves testing of the Macintosh implementation of AM. Since the -primary goal of this evaluation is to determine the most appropriate -audience or audiences for AM, very different sites were selected. This -makes evaluation difficult because of the varying degrees of technology -literacy among the sites. AM is situated in forty-four locations, of -which six are public libraries and sixteen are schools. Represented -among the schools are elementary, junior high, and high schools. -District offices also are involved in the evaluation, which will -conclude in summer 1993. - -VECCIA focused the remainder of her talk on the six public libraries, one -of which doubles as a state library. They represent a range of -geographic areas and a range of demographic characteristics. For -example, three are located in urban settings, two in rural settings, and -one in a suburban setting. A range of technical expertise is to be found -among these facilities as well. For example, one is an "Apple library of -the future," while two others are rural one-room libraries--in one, AM -sits at the front desk next to a tractor manual. - -All public libraries have been extremely enthusiastic, supportive, and -appreciative of the work that AM has been doing. VECCIA characterized -various users: Most users in public libraries describe themselves as -general readers; of the students who use AM in the public libraries, -those in fourth grade and above seem most interested. Public libraries -in rural sites tend to attract retired people, who have been highly -receptive to AM. Users tend to fall into two additional categories: -people interested in the content and historical connotations of these -primary resources, and those fascinated by the technology. The format -receiving the most comments has been motion pictures. The adult users in -public libraries are more comfortable with IBM computers, whereas young -people seem comfortable with either IBM or Macintosh, although most of -them seem to come from a Macintosh background. This same tendency is -found in the schools. - -What kinds of things do users do with AM? In a public library there are -two main goals or ways that AM is being used: as an individual learning -tool, and as a leisure activity. Adult learning was one area that VECCIA -would highlight as a possible application for a tool such as AM. She -described a patron of a rural public library who comes in every day on -his lunch hour and literally reads AM, methodically going through the -collection image by image. At the end of his hour he makes an electronic -bookmark, puts it in his pocket, and returns to work. The next day he -comes in and resumes where he left off. Interestingly, this man had -never been in the library before he used AM. In another small, rural -library, the coordinator reports that AM is a popular activity for some -of the older, retired people in the community, who ordinarily would not -use "those things,"--computers. Another example of adult learning in -public libraries is book groups, one of which, in particular, is using AM -as part of its reading on industrialization, integration, and urbanization -in the early 1900s. - -One library reports that a family is using AM to help educate their -children. In another instance, individuals from a local museum came in -to use AM to prepare an exhibit on toys of the past. These two examples -emphasize the mission of the public library as a cultural institution, -reaching out to people who do not have the same resources available to -those who live in a metropolitan area or have access to a major library. -One rural library reports that junior high school students in large -numbers came in one afternoon to use AM for entertainment. A number of -public libraries reported great interest among postcard collectors in the -Detroit collection, which was essentially a collection of images used on -postcards around the turn of the century. Train buffs are similarly -interested because that was a time of great interest in railroading. -People, it was found, relate to things that they know of firsthand. For -example, in both rural public libraries where AM was made available, -observers reported that the older people with personal remembrances of -the turn of the century were gravitating to the Detroit collection. -These examples served to underscore MICHELSON's observation re the -integration of electronic tools and ideas--that people learn best when -the material relates to something they know. - -VECCIA made the final point that in many cases AM serves as a -public-relations tool for the public libraries that are testing it. In -one case, AM is being used as a vehicle to secure additional funding for -the library. In another case, AM has served as an inspiration to the -staff of a major local public library in the South to think about ways to -make its own collection of photographs more accessible to the public. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -FREEMAN * AM and archival electronic resources in a school environment * -Questions concerning context * Questions concerning the electronic format -itself * Computer anxiety * Access and availability of the system * -Hardware * Strengths gained through the use of archival resources in -schools * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Reiterating an observation made by VECCIA, that AM is an archival -resource made up of primary materials with very little interpretation, -FREEMAN stated that the project has attempted to bridge the gap between -these bare primary materials and a school environment, and in that cause -has created guided introductions to AM collections. Loud demand from the -educational community, chiefly from teachers working with the upper -grades of elementary school through high school, greeted the announcement -that AM would be tested around the country. - -FREEMAN reported not only on what was learned about AM in a school -environment, but also on several universal questions that were raised -concerning archival electronic resources in schools. She discussed -several strengths of this type of material in a school environment as -opposed to a highly structured resource that offers a limited number of -paths to follow. - -FREEMAN first raised several questions about using AM in a school -environment. There is often some difficulty in developing a sense of -what the system contains. Many students sit down at a computer resource -and assume that, because AM comes from the Library of Congress, all of -American history is now at their fingertips. As a result of that sort of -mistaken judgment, some students are known to conclude that AM contains -nothing of use to them when they look for one or two things and do not -find them. It is difficult to discover that middle ground where one has -a sense of what the system contains. Some students grope toward the idea -of an archive, a new idea to them, since they have not previously -experienced what it means to have access to a vast body of somewhat -random information. - -Other questions raised by FREEMAN concerned the electronic format itself. -For instance, in a school environment it is often difficult both for -teachers and students to gain a sense of what it is they are viewing. -They understand that it is a visual image, but they do not necessarily -know that it is a postcard from the turn of the century, a panoramic -photograph, or even machine-readable text of an eighteenth-century -broadside, a twentieth-century printed book, or a nineteenth-century -diary. That distinction is often difficult for people in a school -environment to grasp. Because of that, it occasionally becomes difficult -to draw conclusions from what one is viewing. - -FREEMAN also noted the obvious fear of the computer, which constitutes a -difficulty in using an electronic resource. Though students in general -did not suffer from this anxiety, several older students feared that they -were computer-illiterate, an assumption that became self-fulfilling when -they searched for something but failed to find it. FREEMAN said she -believed that some teachers also fear computer resources, because they -believe they lack complete control. FREEMAN related the example of -teachers shooing away students because it was not their time to use the -system. This was a case in which the situation had to be extremely -structured so that the teachers would not feel that they had lost their -grasp on what the system contained. - -A final question raised by FREEMAN concerned access and availability of -the system. She noted the occasional existence of a gap in communication -between school librarians and teachers. Often AM sits in a school -library and the librarian is the person responsible for monitoring the -system. Teachers do not always take into their world new library -resources about which the librarian is excited. Indeed, at the sites -where AM had been used most effectively within a library, the librarian -was required to go to specific teachers and instruct them in its use. As -a result, several AM sites will have in-service sessions over a summer, -in the hope that perhaps, with a more individualized link, teachers will -be more likely to use the resource. - -A related issue in the school context concerned the number of -workstations available at any one location. Centralization of equipment -at the district level, with teachers invited to download things and walk -away with them, proved unsuccessful because the hours these offices were -open were also school hours. - -Another issue was hardware. As VECCIA observed, a range of sites exists, -some technologically advanced and others essentially acquiring their -first computer for the primary purpose of using it in conjunction with -AM's testing. Users at technologically sophisticated sites want even -more sophisticated hardware, so that they can perform even more -sophisticated tasks with the materials in AM. But once they acquire a -newer piece of hardware, they must learn how to use that also; at an -unsophisticated site it takes an extremely long time simply to become -accustomed to the computer, not to mention the program offered with the -computer. All of these small issues raise one large question, namely, -are systems like AM truly rewarding in a school environment, or do they -simply act as innovative toys that do little more than spark interest? - -FREEMAN contended that the evaluation project has revealed several strengths -that were gained through the use of archival resources in schools, including: - - * Psychic rewards from using AM as a vast, rich database, with - teachers assigning various projects to students--oral presentations, - written reports, a documentary, a turn-of-the-century newspaper-- - projects that start with the materials in AM but are completed using - other resources; AM thus is used as a research tool in conjunction - with other electronic resources, as well as with books and items in - the library where the system is set up. - - * Students are acquiring computer literacy in a humanities context. - - * This sort of system is overcoming the isolation between disciplines - that often exists in schools. For example, many English teachers are - requiring their students to write papers on historical topics - represented in AM. Numerous teachers have reported that their - students are learning critical thinking skills using the system. - - * On a broader level, AM is introducing primary materials, not only - to students but also to teachers, in an environment where often - simply none exist--an exciting thing for the students because it - helps them learn to conduct research, to interpret, and to draw - their own conclusions. In learning to conduct research and what it - means, students are motivated to seek knowledge. That relates to - another positive outcome--a high level of personal involvement of - students with the materials in this system and greater motivation to - conduct their own research and draw their own conclusions. - - * Perhaps the most ironic strength of these kinds of archival - electronic resources is that many of the teachers AM interviewed - were desperate, it is no exaggeration to say, not only for primary - materials but for unstructured primary materials. These would, they - thought, foster personally motivated research, exploration, and - excitement in their students. Indeed, these materials have done - just that. Ironically, however, this lack of structure produces - some of the confusion to which the newness of these kinds of - resources may also contribute. The key to effective use of archival - products in a school environment is a clear, effective introduction - to the system and to what it contains. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Nothing known, quantitatively, about the number of -humanities scholars who must see the original versus those who would -settle for an edited transcript, or about the ways in which humanities -scholars are using information technology * Firm conclusions concerning -the manner and extent of the use of supporting materials in print -provided by AM to await completion of evaluative study * A listener's -reflections on additional applications of electronic texts * Role of -electronic resources in teaching elementary research skills to students * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -During the discussion that followed the presentations by MICHELSON, -VECCIA, and FREEMAN, additional points emerged. - -LESK asked if MICHELSON could give any quantitative estimate of the -number of humanities scholars who must see or want to see the original, -or the best possible version of the material, versus those who typically -would settle for an edited transcript. While unable to provide a figure, -she offered her impressions as an archivist who has done some reference -work and has discussed this issue with other archivists who perform -reference, that those who use archives and those who use primary sources -for what would be considered very high-level scholarly research, as -opposed to, say, undergraduate papers, were few in number, especially -given the public interest in using primary sources to conduct -genealogical or avocational research and the kind of professional -research done by people in private industry or the federal government. -More important in MICHELSON's view was that, quantitatively, nothing is -known about the ways in which, for example, humanities scholars are using -information technology. No studies exist to offer guidance in creating -strategies. The most recent study was conducted in 1985 by the American -Council of Learned Societies (ACLS), and what it showed was that 50 -percent of humanities scholars at that time were using computers. That -constitutes the extent of our knowledge. - -Concerning AM's strategy for orienting people toward the scope of -electronic resources, FREEMAN could offer no hard conclusions at this -point, because she and her colleagues were still waiting to see, -particularly in the schools, what has been made of their efforts. Within -the system, however, AM has provided what are called electronic exhibits- --such as introductions to time periods and materials--and these are -intended to offer a student user a sense of what a broadside is and what -it might tell her or him. But FREEMAN conceded that the project staff -would have to talk with students next year, after teachers have had a -summer to use the materials, and attempt to discover what the students -were learning from the materials. In addition, FREEMAN described -supporting materials in print provided by AM at the request of local -teachers during a meeting held at LC. These included time lines, -bibliographies, and other materials that could be reproduced on a -photocopier in a classroom. Teachers could walk away with and use these, -and in this way gain a better understanding of the contents. But again, -reaching firm conclusions concerning the manner and extent of their use -would have to wait until next year. - -As to the changes she saw occurring at the National Archives and Records -Administration (NARA) as a result of the increasing emphasis on -technology in scholarly research, MICHELSON stated that NARA at this -point was absorbing the report by her and Jeff Rothenberg addressing -strategies for the archival profession in general, although not for the -National Archives specifically. NARA is just beginning to establish its -role and what it can do. In terms of changes and initiatives that NARA -can take, no clear response could be given at this time. - -GREENFIELD remarked two trends mentioned in the session. Reflecting on -DALY's opening comments on how he could have used a Latin collection of -text in an electronic form, he said that at first he thought most scholars -would be unwilling to do that. But as he thought of that in terms of the -original meaning of research--that is, having already mastered these texts, -researching them for critical and comparative purposes--for the first time, -the electronic format made a lot of sense. GREENFIELD could envision -growing numbers of scholars learning the new technologies for that very -aspect of their scholarship and for convenience's sake. - -Listening to VECCIA and FREEMAN, GREENFIELD thought of an additional -application of electronic texts. He realized that AM could be used as a -guide to lead someone to original sources. Students cannot be expected -to have mastered these sources, things they have never known about -before. Thus, AM is leading them, in theory, to a vast body of -information and giving them a superficial overview of it, enabling them -to select parts of it. GREENFIELD asked if any evidence exists that this -resource will indeed teach the new user, the K-12 students, how to do -research. Scholars already know how to do research and are applying -these new tools. But he wondered why students would go beyond picking -out things that were most exciting to them. - -FREEMAN conceded the correctness of GREENFIELD's observation as applied -to a school environment. The risk is that a student would sit down at a -system, play with it, find some things of interest, and then walk away. -But in the relatively controlled situation of a school library, much will -depend on the instructions a teacher or a librarian gives a student. She -viewed the situation not as one of fine-tuning research skills but of -involving students at a personal level in understanding and researching -things. Given the guidance one can receive at school, it then becomes -possible to teach elementary research skills to students, which in fact -one particular librarian said she was teaching her fifth graders. -FREEMAN concluded that introducing the idea of following one's own path -of inquiry, which is essentially what research entails, involves more -than teaching specific skills. To these comments VECCIA added the -observation that the individual teacher and the use of a creative -resource, rather than AM itself, seemed to make the key difference. -Some schools and some teachers are making excellent use of the nature -of critical thinking and teaching skills, she said. - -Concurring with these remarks, DALY closed the session with the thought that -the more that producers produced for teachers and for scholars to use with -their students, the more successful their electronic products would prove. - - ****** - -SESSION II. SHOW AND TELL - -Jacqueline HESS, director, National Demonstration Laboratory, served as -moderator of the "show-and-tell" session. She noted that a -question-and-answer period would follow each presentation. - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -MYLONAS * Overview and content of Perseus * Perseus' primary materials -exist in a system-independent, archival form * A concession * Textual -aspects of Perseus * Tools to use with the Greek text * Prepared indices -and full-text searches in Perseus * English-Greek word search leads to -close study of words and concepts * Navigating Perseus by tracing down -indices * Using the iconography to perform research * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Elli MYLONAS, managing editor, Perseus Project, Harvard University, first -gave an overview of Perseus, a large, collaborative effort based at -Harvard University but with contributors and collaborators located at -numerous universities and colleges in the United States (e.g., Bowdoin, -Maryland, Pomona, Chicago, Virginia). Funded primarily by the -Annenberg/CPB Project, with additional funding from Apple, Harvard, and -the Packard Humanities Institute, among others, Perseus is a multimedia, -hypertextual database for teaching and research on classical Greek -civilization, which was released in February 1992 in version 1.0 and -distributed by Yale University Press. - -Consisting entirely of primary materials, Perseus includes ancient Greek -texts and translations of those texts; catalog entries--that is, museum -catalog entries, not library catalog entries--on vases, sites, coins, -sculpture, and archaeological objects; maps; and a dictionary, among -other sources. The number of objects and the objects for which catalog -entries exist are accompanied by thousands of color images, which -constitute a major feature of the database. Perseus contains -approximately 30 megabytes of text, an amount that will double in -subsequent versions. In addition to these primary materials, the Perseus -Project has been building tools for using them, making access and -navigation easier, the goal being to build part of the electronic -environment discussed earlier in the morning in which students or -scholars can work with their sources. - -The demonstration of Perseus will show only a fraction of the real work -that has gone into it, because the project had to face the dilemma of -what to enter when putting something into machine-readable form: should -one aim for very high quality or make concessions in order to get the -material in? Since Perseus decided to opt for very high quality, all of -its primary materials exist in a system-independent--insofar as it is -possible to be system-independent--archival form. Deciding what that -archival form would be and attaining it required much work and thought. -For example, all the texts are marked up in SGML, which will be made -compatible with the guidelines of the Text Encoding Initiative (TEI) when -they are issued. - -Drawings are postscript files, not meeting international standards, but -at least designed to go across platforms. Images, or rather the real -archival forms, consist of the best available slides, which are being -digitized. Much of the catalog material exists in database form--a form -that the average user could use, manipulate, and display on a personal -computer, but only at great cost. Thus, this is where the concession -comes in: All of this rich, well-marked-up information is stripped of -much of its content; the images are converted into bit-maps and the text -into small formatted chunks. All this information can then be imported -into HyperCard and run on a mid-range Macintosh, which is what Perseus -users have. This fact has made it possible for Perseus to attain wide -use fairly rapidly. Without those archival forms the HyperCard version -being demonstrated could not be made easily, and the project could not -have the potential to move to other forms and machines and software as -they appear, none of which information is in Perseus on the CD. - -Of the numerous multimedia aspects of Perseus, MYLONAS focused on the -textual. Part of what makes Perseus such a pleasure to use, MYLONAS -said, is this effort at seamless integration and the ability to move -around both visual and textual material. Perseus also made the decision -not to attempt to interpret its material any more than one interprets by -selecting. But, MYLONAS emphasized, Perseus is not courseware: No -syllabus exists. There is no effort to define how one teaches a topic -using Perseus, although the project may eventually collect papers by -people who have used it to teach. Rather, Perseus aims to provide -primary material in a kind of electronic library, an electronic sandbox, -so to say, in which students and scholars who are working on this -material can explore by themselves. With that, MYLONAS demonstrated -Perseus, beginning with the Perseus gateway, the first thing one sees -upon opening Perseus--an effort in part to solve the contextualizing -problem--which tells the user what the system contains. - -MYLONAS demonstrated only a very small portion, beginning with primary -texts and running off the CD-ROM. Having selected Aeschylus' Prometheus -Bound, which was viewable in Greek and English pretty much in the same -segments together, MYLONAS demonstrated tools to use with the Greek text, -something not possible with a book: looking up the dictionary entry form -of an unfamiliar word in Greek after subjecting it to Perseus' -morphological analysis for all the texts. After finding out about a -word, a user may then decide to see if it is used anywhere else in Greek. -Because vast amounts of indexing support all of the primary material, one -can find out where else all forms of a particular Greek word appear-- -often not a trivial matter because Greek is highly inflected. Further, -since the story of Prometheus has to do with the origins of sacrifice, a -user may wish to study and explore sacrifice in Greek literature; by -typing sacrifice into a small window, a user goes to the English-Greek -word list--something one cannot do without the computer (Perseus has -indexed the definitions of its dictionary)--the string sacrifice appears -in the definitions of these sixty-five words. One may then find out -where any of those words is used in the work(s) of a particular author. -The English definitions are not lemmatized. - -All of the indices driving this kind of usage were originally devised for -speed, MYLONAS observed; in other words, all that kind of information-- -all forms of all words, where they exist, the dictionary form they belong -to--were collected into databases, which will expedite searching. Then -it was discovered that one can do things searching in these databases -that could not be done searching in the full texts. Thus, although there -are full-text searches in Perseus, much of the work is done behind the -scenes, using prepared indices. Re the indexing that is done behind the -scenes, MYLONAS pointed out that without the SGML forms of the text, it -could not be done effectively. Much of this indexing is based on the -structures that are made explicit by the SGML tagging. - -It was found that one of the things many of Perseus' non-Greek-reading -users do is start from the dictionary and then move into the close study -of words and concepts via this kind of English-Greek word search, by which -means they might select a concept. This exercise has been assigned to -students in core courses at Harvard--to study a concept by looking for the -English word in the dictionary, finding the Greek words, and then finding -the words in the Greek but, of course, reading across in the English. -That tells them a great deal about what a translation means as well. - -Should one also wish to see images that have to do with sacrifice, that -person would go to the object key word search, which allows one to -perform a similar kind of index retrieval on the database of -archaeological objects. Without words, pictures are useless; Perseus has -not reached the point where it can do much with images that are not -cataloged. Thus, although it is possible in Perseus with text and images -to navigate by knowing where one wants to end up--for example, a -red-figure vase from the Boston Museum of Fine Arts--one can perform this -kind of navigation very easily by tracing down indices. MYLONAS -illustrated several generic scenes of sacrifice on vases. The features -demonstrated derived from Perseus 1.0; version 2.0 will implement even -better means of retrieval. - -MYLONAS closed by looking at one of the pictures and noting again that -one can do a great deal of research using the iconography as well as the -texts. For instance, students in a core course at Harvard this year were -highly interested in Greek concepts of foreigners and representations of -non-Greeks. So they performed a great deal of research, both with texts -(e.g., Herodotus) and with iconography on vases and coins, on how the -Greeks portrayed non-Greeks. At the same time, art historians who study -iconography were also interested, and were able to use this material. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Indexing and searchability of all English words in Perseus * -Several features of Perseus 1.0 * Several levels of customization -possible * Perseus used for general education * Perseus' effects on -education * Contextual information in Perseus * Main challenge and -emphasis of Perseus * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Several points emerged in the discussion that followed MYLONAS's presentation. - -Although MYLONAS had not demonstrated Perseus' ability to cross-search -documents, she confirmed that all English words in Perseus are indexed -and can be searched. So, for example, sacrifice could have been searched -in all texts, the historical essay, and all the catalogue entries with -their descriptions--in short, in all of Perseus. - -Boolean logic is not in Perseus 1.0 but will be added to the next -version, although an effort is being made not to restrict Perseus to a -database in which one just performs searching, Boolean or otherwise. It -is possible to move laterally through the documents by selecting a word -one is interested in and selecting an area of information one is -interested in and trying to look that word up in that area. - -Since Perseus was developed in HyperCard, several levels of customization -are possible. Simple authoring tools exist that allow one to create -annotated paths through the information, which are useful for note-taking -and for guided tours for teaching purposes and for expository writing. -With a little more ingenuity it is possible to begin to add or substitute -material in Perseus. - -Perseus has not been used so much for classics education as for general -education, where it seemed to have an impact on the students in the core -course at Harvard (a general required course that students must take in -certain areas). Students were able to use primary material much more. - -The Perseus Project has an evaluation team at the University of Maryland -that has been documenting Perseus' effects on education. Perseus is very -popular, and anecdotal evidence indicates that it is having an effect at -places other than Harvard, for example, test sites at Ball State -University, Drury College, and numerous small places where opportunities -to use vast amounts of primary data may not exist. One documented effect -is that archaeological, anthropological, and philological research is -being done by the same person instead of by three different people. - -The contextual information in Perseus includes an overview essay, a -fairly linear historical essay on the fifth century B.C. that provides -links into the primary material (e.g., Herodotus, Thucydides, and -Plutarch), via small gray underscoring (on the screen) of linked -passages. These are handmade links into other material. - -To different extents, most of the production work was done at Harvard, -where the people and the equipment are located. Much of the -collaborative activity involved data collection and structuring, because -the main challenge and the emphasis of Perseus is the gathering of -primary material, that is, building a useful environment for studying -classical Greece, collecting data, and making it useful. -Systems-building is definitely not the main concern. Thus, much of the -work has involved writing essays, collecting information, rewriting it, -and tagging it. That can be done off site. The creative link for the -overview essay as well as for both systems and data was collaborative, -and was forged via E-mail and paper mail with professors at Pomona and -Bowdoin. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -CALALUCA * PLD's principal focus and contribution to scholarship * -Various questions preparatory to beginning the project * Basis for -project * Basic rule in converting PLD * Concerning the images in PLD * -Running PLD under a variety of retrieval softwares * Encoding the -database a hard-fought issue * Various features demonstrated * Importance -of user documentation * Limitations of the CD-ROM version * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Eric CALALUCA, vice president, Chadwyck-Healey, Inc., demonstrated a -software interpretation of the Patrologia Latina Database (PLD). PLD's -principal focus from the beginning of the project about three-and-a-half -years ago was on converting Migne's Latin series, and in the end, -CALALUCA suggested, conversion of the text will be the major contribution -to scholarship. CALALUCA stressed that, as possibly the only private -publishing organization at the Workshop, Chadwyck-Healey had sought no -federal funds or national foundation support before embarking upon the -project, but instead had relied upon a great deal of homework and -marketing to accomplish the task of conversion. - -Ever since the possibilities of computer-searching have emerged, scholars -in the field of late ancient and early medieval studies (philosophers, -theologians, classicists, and those studying the history of natural law -and the history of the legal development of Western civilization) have -been longing for a fully searchable version of Western literature, for -example, all the texts of Augustine and Bernard of Clairvaux and -Boethius, not to mention all the secondary and tertiary authors. - -Various questions arose, CALALUCA said. Should one convert Migne? -Should the database be encoded? Is it necessary to do that? How should -it be delivered? What about CD-ROM? Since this is a transitional -medium, why even bother to create software to run on a CD-ROM? Since -everybody knows people will be networking information, why go to the -trouble--which is far greater with CD-ROM than with the production of -magnetic data? Finally, how does one make the data available? Can many -of the hurdles to using electronic information that some publishers have -imposed upon databases be eliminated? - -The PLD project was based on the principle that computer-searching of -texts is most effective when it is done with a large database. Because -PLD represented a collection that serves so many disciplines across so -many periods, it was irresistible. - -The basic rule in converting PLD was to do no harm, to avoid the sins of -intrusion in such a database: no introduction of newer editions, no -on-the-spot changes, no eradicating of all possible falsehoods from an -edition. Thus, PLD is not the final act in electronic publishing for -this discipline, but simply the beginning. The conversion of PLD has -evoked numerous unanticipated questions: How will information be used? -What about networking? Can the rights of a database be protected? -Should one protect the rights of a database? How can it be made -available? - -Those converting PLD also tried to avoid the sins of omission, that is, -excluding portions of the collections or whole sections. What about the -images? PLD is full of images, some are extremely pious -nineteenth-century representations of the Fathers, while others contain -highly interesting elements. The goal was to cover all the text of Migne -(including notes, in Greek and in Hebrew, the latter of which, in -particular, causes problems in creating a search structure), all the -indices, and even the images, which are being scanned in separately -searchable files. - -Several North American institutions that have placed acquisition requests -for the PLD database have requested it in magnetic form without software, -which means they are already running it without software, without -anything demonstrated at the Workshop. - -What cannot practically be done is go back and reconvert and re-encode -data, a time-consuming and extremely costly enterprise. CALALUCA sees -PLD as a database that can, and should, be run under a variety of -retrieval softwares. This will permit the widest possible searches. -Consequently, the need to produce a CD-ROM of PLD, as well as to develop -software that could handle some 1.3 gigabyte of heavily encoded text, -developed out of conversations with collection development and reference -librarians who wanted software both compassionate enough for the -pedestrian but also capable of incorporating the most detailed -lexicographical studies that a user desires to conduct. In the end, the -encoding and conversion of the data will prove the most enduring -testament to the value of the project. - -The encoding of the database was also a hard-fought issue: Did the -database need to be encoded? Were there normative structures for encoding -humanist texts? Should it be SGML? What about the TEI--will it last, -will it prove useful? CALALUCA expressed some minor doubts as to whether -a data bank can be fully TEI-conformant. Every effort can be made, but -in the end to be TEI-conformant means to accept the need to make some -firm encoding decisions that can, indeed, be disputed. The TEI points -the publisher in a proper direction but does not presume to make all the -decisions for him or her. Essentially, the goal of encoding was to -eliminate, as much as possible, the hindrances to information-networking, -so that if an institution acquires a database, everybody associated with -the institution can have access to it. - -CALALUCA demonstrated a portion of Volume 160, because it had the most -anomalies in it. The software was created by Electronic Book -Technologies of Providence, RI, and is called Dynatext. The software -works only with SGML-coded data. - -Viewing a table of contents on the screen, the audience saw how Dynatext -treats each element as a book and attempts to simplify movement through a -volume. Familiarity with the Patrologia in print (i.e., the text, its -source, and the editions) will make the machine-readable versions highly -useful. (Software with a Windows application was sought for PLD, -CALALUCA said, because this was the main trend for scholarly use.) - -CALALUCA also demonstrated how a user can perform a variety of searches -and quickly move to any part of a volume; the look-up screen provides -some basic, simple word-searching. - -CALALUCA argued that one of the major difficulties is not the software. -Rather, in creating a product that will be used by scholars representing -a broad spectrum of computer sophistication, user documentation proves -to be the most important service one can provide. - -CALALUCA next illustrated a truncated search under mysterium within ten -words of virtus and how one would be able to find its contents throughout -the entire database. He said that the exciting thing about PLD is that -many of the applications in the retrieval software being written for it -will exceed the capabilities of the software employed now for the CD-ROM -version. The CD-ROM faces genuine limitations, in terms of speed and -comprehensiveness, in the creation of a retrieval software to run it. -CALALUCA said he hoped that individual scholars will download the data, -if they wish, to their personal computers, and have ready access to -important texts on a constant basis, which they will be able to use in -their research and from which they might even be able to publish. - -(CALALUCA explained that the blue numbers represented Migne's column numbers, -which are the standard scholarly references. Pulling up a note, he stated -that these texts were heavily edited and the image files would appear simply -as a note as well, so that one could quickly access an image.) - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -FLEISCHHAUER/ERWAY * Several problems with which AM is still wrestling * -Various search and retrieval capabilities * Illustration of automatic -stemming and a truncated search * AM's attempt to find ways to connect -cataloging to the texts * AM's gravitation towards SGML * Striking a -balance between quantity and quality * How AM furnishes users recourse to -images * Conducting a search in a full-text environment * Macintosh and -IBM prototypes of AM * Multimedia aspects of AM * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -A demonstration of American Memory by its coordinator, Carl FLEISCHHAUER, -and Ricky ERWAY, associate coordinator, Library of Congress, concluded -the morning session. Beginning with a collection of broadsides from the -Continental Congress and the Constitutional Convention, the only text -collection in a presentable form at the time of the Workshop, FLEISCHHAUER -highlighted several of the problems with which AM is still wrestling. -(In its final form, the disk will contain two collections, not only the -broadsides but also the full text with illustrations of a set of -approximately 300 African-American pamphlets from the period 1870 to 1910.) - -As FREEMAN had explained earlier, AM has attempted to use a small amount -of interpretation to introduce collections. In the present case, the -contractor, a company named Quick Source, in Silver Spring, MD., used -software called Toolbook and put together a modestly interactive -introduction to the collection. Like the two preceding speakers, -FLEISCHHAUER argued that the real asset was the underlying collection. - -FLEISCHHAUER proceeded to describe various search and retrieval -capabilities while ERWAY worked the computer. In this particular package -the "go to" pull-down allowed the user in effect to jump out of Toolbook, -where the interactive program was located, and enter the third-party -software used by AM for this text collection, which is called Personal -Librarian. This was the Windows version of Personal Librarian, a -software application put together by a company in Rockville, Md. - -Since the broadsides came from the Revolutionary War period, a search was -conducted using the words British or war, with the default operator reset -as or. FLEISCHHAUER demonstrated both automatic stemming (which finds -other forms of the same root) and a truncated search. One of Personal -Librarian's strongest features, the relevance ranking, was represented by -a chart that indicated how often words being sought appeared in -documents, with the one receiving the most "hits" obtaining the highest -score. The "hit list" that is supplied takes the relevance ranking into -account, making the first hit, in effect, the one the software has -selected as the most relevant example. - -While in the text of one of the broadside documents, FLEISCHHAUER -remarked AM's attempt to find ways to connect cataloging to the texts, -which it does in different ways in different manifestations. In the case -shown, the cataloging was pasted on: AM took MARC records that were -written as on-line records right into one of the Library's mainframe -retrieval programs, pulled them out, and handed them off to the contractor, -who massaged them somewhat to display them in the manner shown. One of -AM's questions is, Does the cataloguing normally performed in the mainframe -work in this context, or had AM ought to think through adjustments? - -FLEISCHHAUER made the additional point that, as far as the text goes, AM -has gravitated towards SGML (he pointed to the boldface in the upper part -of the screen). Although extremely limited in its ability to translate -or interpret SGML, Personal Librarian will furnish both bold and italics -on screen; a fairly easy thing to do, but it is one of the ways in which -SGML is useful. - -Striking a balance between quantity and quality has been a major concern -of AM, with accuracy being one of the places where project staff have -felt that less than 100-percent accuracy was not unacceptable. -FLEISCHHAUER cited the example of the standard of the rekeying industry, -namely 99.95 percent; as one service bureau informed him, to go from -99.95 to 100 percent would double the cost. - -FLEISCHHAUER next demonstrated how AM furnishes users recourse to images, -and at the same time recalled LESK's pointed question concerning the -number of people who would look at those images and the number who would -work only with the text. If the implication of LESK's question was -sound, FLEISCHHAUER said, it raised the stakes for text accuracy and -reduced the value of the strategy for images. - -Contending that preservation is always a bugaboo, FLEISCHHAUER -demonstrated several images derived from a scan of a preservation -microfilm that AM had made. He awarded a grade of C at best, perhaps a -C minus or a C plus, for how well it worked out. Indeed, the matter of -learning if other people had better ideas about scanning in general, and, -in particular, scanning from microfilm, was one of the factors that drove -AM to attempt to think through the agenda for the Workshop. Skew, for -example, was one of the issues that AM in its ignorance had not reckoned -would prove so difficult. - -Further, the handling of images of the sort shown, in a desktop computer -environment, involved a considerable amount of zooming and scrolling. -Ultimately, AM staff feel that perhaps the paper copy that is printed out -might be the most useful one, but they remain uncertain as to how much -on-screen reading users will do. - -Returning to the text, FLEISCHHAUER asked viewers to imagine a person who -might be conducting a search in a full-text environment. With this -scenario, he proceeded to illustrate other features of Personal Librarian -that he considered helpful; for example, it provides the ability to -notice words as one reads. Clicking the "include" button on the bottom -of the search window pops the words that have been highlighted into the -search. Thus, a user can refine the search as he or she reads, -re-executing the search and continuing to find things in the quest for -materials. This software not only contains relevance ranking, Boolean -operators, and truncation, it also permits one to perform word algebra, -so to say, where one puts two or three words in parentheses and links -them with one Boolean operator and then a couple of words in another set -of parentheses and asks for things within so many words of others. - -Until they became acquainted recently with some of the work being done in -classics, the AM staff had not realized that a large number of the -projects that involve electronic texts were being done by people with a -profound interest in language and linguistics. Their search strategies -and thinking are oriented to those fields, as is shown in particular by -the Perseus example. As amateur historians, the AM staff were thinking -more of searching for concepts and ideas than for particular words. -Obviously, FLEISCHHAUER conceded, searching for concepts and ideas and -searching for words may be two rather closely related things. - -While displaying several images, FLEISCHHAUER observed that the Macintosh -prototype built by AM contains a greater diversity of formats. Echoing a -previous speaker, he said that it was easier to stitch things together in -the Macintosh, though it tended to be a little more anemic in search and -retrieval. AM, therefore, increasingly has been investigating -sophisticated retrieval engines in the IBM format. - -FLEISCHHAUER demonstrated several additional examples of the prototype -interfaces: One was AM's metaphor for the network future, in which a -kind of reading-room graphic suggests how one would be able to go around -to different materials. AM contains a large number of photographs in -analog video form worked up from a videodisc, which enable users to make -copies to print or incorporate in digital documents. A frame-grabber is -built into the system, making it possible to bring an image into a window -and digitize or print it out. - -FLEISCHHAUER next demonstrated sound recording, which included texts. -Recycled from a previous project, the collection included sixty 78-rpm -phonograph records of political speeches that were made during and -immediately after World War I. These constituted approximately three -hours of audio, as AM has digitized it, which occupy 150 megabytes on a -CD. Thus, they are considerably compressed. From the catalogue card, -FLEISCHHAUER proceeded to a transcript of a speech with the audio -available and with highlighted text following it as it played. -A photograph has been added and a transcription made. - -Considerable value has been added beyond what the Library of Congress -normally would do in cataloguing a sound recording, which raises several -questions for AM concerning where to draw lines about how much value it can -afford to add and at what point, perhaps, this becomes more than AM could -reasonably do or reasonably wish to do. FLEISCHHAUER also demonstrated -a motion picture. As FREEMAN had reported earlier, the motion picture -materials have proved the most popular, not surprisingly. This says more -about the medium, he thought, than about AM's presentation of it. - -Because AM's goal was to bring together things that could be used by -historians or by people who were curious about history, -turn-of-the-century footage seemed to represent the most appropriate -collections from the Library of Congress in motion pictures. These were -the very first films made by Thomas Edison's company and some others at -that time. The particular example illustrated was a Biograph film, -brought in with a frame-grabber into a window. A single videodisc -contains about fifty titles and pieces of film from that period, all of -New York City. Taken together, AM believes, they provide an interesting -documentary resource. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Using the frame-grabber in AM * Volume of material processed -and to be processed * Purpose of AM within LC * Cataloguing and the -nature of AM's material * SGML coding and the question of quality versus -quantity * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -During the question-and-answer period that followed FLEISCHHAUER's -presentation, several clarifications were made. - -AM is bringing in motion pictures from a videodisc. The frame-grabber -devices create a window on a computer screen, which permits users to -digitize a single frame of the movie or one of the photographs. It -produces a crude, rough-and-ready image that high school students can -incorporate into papers, and that has worked very nicely in this way. - -Commenting on FLEISCHHAUER's assertion that AM was looking more at -searching ideas than words, MYLONAS argued that without words an idea -does not exist. FLEISCHHAUER conceded that he ought to have articulated -his point more clearly. MYLONAS stated that they were in fact both -talking about the same thing. By searching for words and by forcing -people to focus on the word, the Perseus Project felt that they would get -them to the idea. The way one reviews results is tailored more to one -kind of user than another. - -Concerning the total volume of material that has been processed in this -way, AM at this point has in retrievable form seven or eight collections, -all of them photographic. In the Macintosh environment, for example, -there probably are 35,000-40,000 photographs. The sound recordings -number sixty items. The broadsides number about 300 items. There are -500 political cartoons in the form of drawings. The motion pictures, as -individual items, number sixty to seventy. - -AM also has a manuscript collection, the life history portion of one of -the federal project series, which will contain 2,900 individual -documents, all first-person narratives. AM has in process about 350 -African-American pamphlets, or about 12,000 printed pages for the period -1870-1910. Also in the works are some 4,000 panoramic photographs. AM -has recycled a fair amount of the work done by LC's Prints and -Photographs Division during the Library's optical disk pilot project in -the 1980s. For example, a special division of LC has tooled up and -thought through all the ramifications of electronic presentation of -photographs. Indeed, they are wheeling them out in great barrel loads. -The purpose of AM within the Library, it is hoped, is to catalyze several -of the other special collection divisions which have no particular -experience with, in some cases, mixed feelings about, an activity such as -AM. Moreover, in many cases the divisions may be characterized as not -only lacking experience in "electronifying" things but also in automated -cataloguing. MARC cataloguing as practiced in the United States is -heavily weighted toward the description of monograph and serial -materials, but is much thinner when one enters the world of manuscripts -and things that are held in the Library's music collection and other -units. In response to a comment by LESK, that AM's material is very -heavily photographic, and is so primarily because individual records have -been made for each photograph, FLEISCHHAUER observed that an item-level -catalog record exists, for example, for each photograph in the Detroit -Publishing collection of 25,000 pictures. In the case of the Federal -Writers Project, for which nearly 3,000 documents exist, representing -information from twenty-six different states, AM with the assistance of -Karen STUART of the Manuscript Division will attempt to find some way not -only to have a collection-level record but perhaps a MARC record for each -state, which will then serve as an umbrella for the 100-200 documents -that come under it. But that drama remains to be enacted. The AM staff -is conservative and clings to cataloguing, though of course visitors tout -artificial intelligence and neural networks in a manner that suggests that -perhaps one need not have cataloguing or that much of it could be put aside. - -The matter of SGML coding, FLEISCHHAUER conceded, returned the discussion -to the earlier treated question of quality versus quantity in the Library -of Congress. Of course, text conversion can be done with 100-percent -accuracy, but it means that when one's holdings are as vast as LC's only -a tiny amount will be exposed, whereas permitting lower levels of -accuracy can lead to exposing or sharing larger amounts, but with the -quality correspondingly impaired. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TWOHIG * A contrary experience concerning electronic options * Volume of -material in the Washington papers and a suggestion of David Packard * -Implications of Packard's suggestion * Transcribing the documents for the -CD-ROM * Accuracy of transcriptions * The CD-ROM edition of the Founding -Fathers documents * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Finding encouragement in a comment of MICHELSON's from the morning -session--that numerous people in the humanities were choosing electronic -options to do their work--Dorothy TWOHIG, editor, The Papers of George -Washington, opened her illustrated talk by noting that her experience -with literary scholars and numerous people in editing was contrary to -MICHELSON's. TWOHIG emphasized literary scholars' complete ignorance of -the technological options available to them or their reluctance or, in -some cases, their downright hostility toward these options. - -After providing an overview of the five Founding Fathers projects -(Jefferson at Princeton, Franklin at Yale, John Adams at the -Massachusetts Historical Society, and Madison down the hall from her at -the University of Virginia), TWOHIG observed that the Washington papers, -like all of the projects, include both sides of the Washington -correspondence and deal with some 135,000 documents to be published with -extensive annotation in eighty to eighty-five volumes, a project that -will not be completed until well into the next century. Thus, it was -with considerable enthusiasm several years ago that the Washington Papers -Project (WPP) greeted David Packard's suggestion that the papers of the -Founding Fathers could be published easily and inexpensively, and to the -great benefit of American scholarship, via CD-ROM. - -In pragmatic terms, funding from the Packard Foundation would expedite -the transcription of thousands of documents waiting to be put on disk in -the WPP offices. Further, since the costs of collecting, editing, and -converting the Founding Fathers documents into letterpress editions were -running into the millions of dollars, and the considerable staffs -involved in all of these projects were devoting their careers to -producing the work, the Packard Foundation's suggestion had a -revolutionary aspect: Transcriptions of the entire corpus of the -Founding Fathers papers would be available on CD-ROM to public and -college libraries, even high schools, at a fraction of the cost-- -$100-$150 for the annual license fee--to produce a limited university -press run of 1,000 of each volume of the published papers at $45-$150 per -printed volume. Given the current budget crunch in educational systems -and the corresponding constraints on librarians in smaller institutions -who wish to add these volumes to their collections, producing the -documents on CD-ROM would likely open a greatly expanded audience for the -papers. TWOHIG stressed, however, that development of the Founding -Fathers CD-ROM is still in its infancy. Serious software problems remain -to be resolved before the material can be put into readable form. - -Funding from the Packard Foundation resulted in a major push to -transcribe the 75,000 or so documents of the Washington papers remaining -to be transcribed onto computer disks. Slides illustrated several of the -problems encountered, for example, the present inability of CD-ROM to -indicate the cross-outs (deleted material) in eighteenth century -documents. TWOHIG next described documents from various periods in the -eighteenth century that have been transcribed in chronological order and -delivered to the Packard offices in California, where they are converted -to the CD-ROM, a process that is expected to consume five years to -complete (that is, reckoning from David Packard's suggestion made several -years ago, until about July 1994). TWOHIG found an encouraging -indication of the project's benefits in the ongoing use made by scholars -of the search functions of the CD-ROM, particularly in reducing the time -spent in manually turning the pages of the Washington papers. - -TWOHIG next furnished details concerning the accuracy of transcriptions. -For instance, the insertion of thousands of documents on the CD-ROM -currently does not permit each document to be verified against the -original manuscript several times as in the case of documents that appear -in the published edition. However, the transcriptions receive a cursory -check for obvious typos, the misspellings of proper names, and other -errors from the WPP CD-ROM editor. Eventually, all documents that appear -in the electronic version will be checked by project editors. Although -this process has met with opposition from some of the editors on the -grounds that imperfect work may leave their offices, the advantages in -making this material available as a research tool outweigh fears about the -misspelling of proper names and other relatively minor editorial matters. - -Completion of all five Founding Fathers projects (i.e., retrievability -and searchability of all of the documents by proper names, alternate -spellings, or varieties of subjects) will provide one of the richest -sources of this size for the history of the United States in the latter -part of the eighteenth century. Further, publication on CD-ROM will -allow editors to include even minutiae, such as laundry lists, not -included in the printed volumes. - -It seems possible that the extensive annotation provided in the printed -volumes eventually will be added to the CD-ROM edition, pending -negotiations with the publishers of the papers. At the moment, the -Founding Fathers CD-ROM is accessible only on the IBYCUS, a computer -developed out of the Thesaurus Linguae Graecae project and designed for -the use of classical scholars. There are perhaps 400 IBYCUS computers in -the country, most of which are in university classics departments. -Ultimately, it is anticipated that the CD-ROM edition of the Founding -Fathers documents will run on any IBM-compatible or Macintosh computer -with a CD-ROM drive. Numerous changes in the software will also occur -before the project is completed. (Editor's note: an IBYCUS was -unavailable to demonstrate the CD-ROM.) - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Several additional features of WPP clarified * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Discussion following TWOHIG's presentation served to clarify several -additional features, including (1) that the project's primary -intellectual product consists in the electronic transcription of the -material; (2) that the text transmitted to the CD-ROM people is not -marked up; (3) that cataloging and subject-indexing of the material -remain to be worked out (though at this point material can be retrieved -by name); and (4) that because all the searching is done in the hardware, -the IBYCUS is designed to read a CD-ROM which contains only sequential -text files. Technically, it then becomes very easy to read the material -off and put it on another device. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -LEBRON * Overview of the history of the joint project between AAAS and -OCLC * Several practices the on-line environment shares with traditional -publishing on hard copy * Several technical and behavioral barriers to -electronic publishing * How AAAS and OCLC arrived at the subject of -clinical trials * Advantages of the electronic format and other features -of OJCCT * An illustrated tour of the journal * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Maria LEBRON, managing editor, The Online Journal of Current Clinical -Trials (OJCCT), presented an illustrated overview of the history of the -joint project between the American Association for the Advancement of -Science (AAAS) and the Online Computer Library Center, Inc. (OCLC). The -joint venture between AAAS and OCLC owes its beginning to a -reorganization launched by the new chief executive officer at OCLC about -three years ago and combines the strengths of these two disparate -organizations. In short, OJCCT represents the process of scholarly -publishing on line. - -LEBRON next discussed several practices the on-line environment shares -with traditional publishing on hard copy--for example, peer review of -manuscripts--that are highly important in the academic world. LEBRON -noted in particular the implications of citation counts for tenure -committees and grants committees. In the traditional hard-copy -environment, citation counts are readily demonstrable, whereas the -on-line environment represents an ethereal medium to most academics. - -LEBRON remarked several technical and behavioral barriers to electronic -publishing, for instance, the problems in transmission created by special -characters or by complex graphics and halftones. In addition, she noted -economic limitations such as the storage costs of maintaining back issues -and market or audience education. - -Manuscripts cannot be uploaded to OJCCT, LEBRON explained, because it is -not a bulletin board or E-mail, forms of electronic transmission of -information that have created an ambience clouding people's understanding -of what the journal is attempting to do. OJCCT, which publishes -peer-reviewed medical articles dealing with the subject of clinical -trials, includes text, tabular material, and graphics, although at this -time it can transmit only line illustrations. - -Next, LEBRON described how AAAS and OCLC arrived at the subject of -clinical trials: It is 1) a highly statistical discipline that 2) does -not require halftones but can satisfy the needs of its audience with line -illustrations and graphic material, and 3) there is a need for the speedy -dissemination of high-quality research results. Clinical trials are -research activities that involve the administration of a test treatment -to some experimental unit in order to test its usefulness before it is -made available to the general population. LEBRON proceeded to give -additional information on OJCCT concerning its editor-in-chief, editorial -board, editorial content, and the types of articles it publishes -(including peer-reviewed research reports and reviews), as well as -features shared by other traditional hard-copy journals. - -Among the advantages of the electronic format are faster dissemination of -information, including raw data, and the absence of space constraints -because pages do not exist. (This latter fact creates an interesting -situation when it comes to citations.) Nor are there any issues. AAAS's -capacity to download materials directly from the journal to a -subscriber's printer, hard drive, or floppy disk helps ensure highly -accurate transcription. Other features of OJCCT include on-screen alerts -that allow linkage of subsequently published documents to the original -documents; on-line searching by subject, author, title, etc.; indexing of -every single word that appears in an article; viewing access to an -article by component (abstract, full text, or graphs); numbered -paragraphs to replace page counts; publication in Science every thirty -days of indexing of all articles published in the journal; -typeset-quality screens; and Hypertext links that enable subscribers to -bring up Medline abstracts directly without leaving the journal. - -After detailing the two primary ways to gain access to the journal, -through the OCLC network and Compuserv if one desires graphics or through -the Internet if just an ASCII file is desired, LEBRON illustrated the -speedy editorial process and the coding of the document using SGML tags -after it has been accepted for publication. She also gave an illustrated -tour of the journal, its search-and-retrieval capabilities in particular, -but also including problems associated with scanning in illustrations, -and the importance of on-screen alerts to the medical profession re -retractions or corrections, or more frequently, editorials, letters to -the editors, or follow-up reports. She closed by inviting the audience -to join AAAS on 1 July, when OJCCT was scheduled to go on-line. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Additional features of OJCCT * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -In the lengthy discussion that followed LEBRON's presentation, these -points emerged: - - * The SGML text can be tailored as users wish. - - * All these articles have a fairly simple document definition. - - * Document-type definitions (DTDs) were developed and given to OJCCT - for coding. - - * No articles will be removed from the journal. (Because there are - no back issues, there are no lost issues either. Once a subscriber - logs onto the journal he or she has access not only to the currently - published materials, but retrospectively to everything that has been - published in it. Thus the table of contents grows bigger. The date - of publication serves to distinguish between currently published - materials and older materials.) - - * The pricing system for the journal resembles that for most medical - journals: for 1992, $95 for a year, plus telecommunications charges - (there are no connect time charges); for 1993, $110 for the - entire year for single users, though the journal can be put on a - local area network (LAN). However, only one person can access the - journal at a time. Site licenses may come in the future. - - * AAAS is working closely with colleagues at OCLC to display - mathematical equations on screen. - - * Without compromising any steps in the editorial process, the - technology has reduced the time lag between when a manuscript is - originally submitted and the time it is accepted; the review process - does not differ greatly from the standard six-to-eight weeks - employed by many of the hard-copy journals. The process still - depends on people. - - * As far as a preservation copy is concerned, articles will be - maintained on the computer permanently and subscribers, as part of - their subscription, will receive a microfiche-quality archival copy - of everything published during that year; in addition, reprints can - be purchased in much the same way as in a hard-copy environment. - Hard copies are prepared but are not the primary medium for the - dissemination of the information. - - * Because OJCCT is not yet on line, it is difficult to know how many - people would simply browse through the journal on the screen as - opposed to downloading the whole thing and printing it out; a mix of - both types of users likely will result. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -PERSONIUS * Developments in technology over the past decade * The CLASS -Project * Advantages for technology and for the CLASS Project * -Developing a network application an underlying assumption of the project -* Details of the scanning process * Print-on-demand copies of books * -Future plans include development of a browsing tool * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Lynne PERSONIUS, assistant director, Cornell Information Technologies for -Scholarly Information Services, Cornell University, first commented on -the tremendous impact that developments in technology over the past ten -years--networking, in particular--have had on the way information is -handled, and how, in her own case, these developments have counterbalanced -Cornell's relative geographical isolation. Other significant technologies -include scanners, which are much more sophisticated than they were ten years -ago; mass storage and the dramatic savings that result from it in terms of -both space and money relative to twenty or thirty years ago; new and -improved printing technologies, which have greatly affected the distribution -of information; and, of course, digital technologies, whose applicability to -library preservation remains at issue. - -Given that context, PERSONIUS described the College Library Access and -Storage System (CLASS) Project, a library preservation project, -primarily, and what has been accomplished. Directly funded by the -Commission on Preservation and Access and by the Xerox Corporation, which -has provided a significant amount of hardware, the CLASS Project has been -working with a development team at Xerox to develop a software -application tailored to library preservation requirements. Within -Cornell, participants in the project have been working jointly with both -library and information technologies. The focus of the project has been -on reformatting and saving books that are in brittle condition. -PERSONIUS showed Workshop participants a brittle book, and described how -such books were the result of developments in papermaking around the -beginning of the Industrial Revolution. The papermaking process was -changed so that a significant amount of acid was introduced into the -actual paper itself, which deteriorates as it sits on library shelves. - -One of the advantages for technology and for the CLASS Project is that -the information in brittle books is mostly out of copyright and thus -offers an opportunity to work with material that requires library -preservation, and to create and work on an infrastructure to save the -material. Acknowledging the familiarity of those working in preservation -with this information, PERSONIUS noted that several things are being -done: the primary preservation technology used today is photocopying of -brittle material. Saving the intellectual content of the material is the -main goal. With microfilm copy, the intellectual content is preserved on -the assumption that in the future the image can be reformatted in any -other way that then exists. - -An underlying assumption of the CLASS Project from the beginning was -that it would develop a network application. Project staff scan books -at a workstation located in the library, near the brittle material. -An image-server filing system is located at a distance from that -workstation, and a printer is located in another building. All of the -materials digitized and stored on the image-filing system are cataloged -in the on-line catalogue. In fact, a record for each of these electronic -books is stored in the RLIN database so that a record exists of what is -in the digital library throughout standard catalogue procedures. In the -future, researchers working from their own workstations in their offices, -or their networks, will have access--wherever they might be--through a -request server being built into the new digital library. A second -assumption is that the preferred means of finding the material will be by -looking through a catalogue. PERSONIUS described the scanning process, -which uses a prototype scanner being developed by Xerox and which scans a -very high resolution image at great speed. Another significant feature, -because this is a preservation application, is the placing of the pages -that fall apart one for one on the platen. Ordinarily, a scanner could -be used with some sort of a document feeder, but because of this -application that is not feasible. Further, because CLASS is a -preservation application, after the paper replacement is made there, a -very careful quality control check is performed. An original book is -compared to the printed copy and verification is made, before proceeding, -that all of the image, all of the information, has been captured. Then, -a new library book is produced: The printed images are rebound by a -commercial binder and a new book is returned to the shelf. -Significantly, the books returned to the library shelves are beautiful -and useful replacements on acid-free paper that should last a long time, -in effect, the equivalent of preservation photocopies. Thus, the project -has a library of digital books. In essence, CLASS is scanning and -storing books as 600 dot-per-inch bit-mapped images, compressed using -Group 4 CCITT (i.e., the French acronym for International Consultative -Committee for Telegraph and Telephone) compression. They are stored as -TIFF files on an optical filing system that is composed of a database -used for searching and locating the books and an optical jukebox that -stores 64 twelve-inch platters. A very-high-resolution printed copy of -these books at 600 dots per inch is created, using a Xerox DocuTech -printer to make the paper replacements on acid-free paper. - -PERSONIUS maintained that the CLASS Project presents an opportunity to -introduce people to books as digital images by using a paper medium. -Books are returned to the shelves while people are also given the ability -to print on demand--to make their own copies of books. (PERSONIUS -distributed copies of an engineering journal published by engineering -students at Cornell around 1900 as an example of what a print-on-demand -copy of material might be like. This very cheap copy would be available -to people to use for their own research purposes and would bridge the gap -between an electronic work and the paper that readers like to have.) -PERSONIUS then attempted to illustrate a very early prototype of -networked access to this digital library. Xerox Corporation has -developed a prototype of a view station that can send images across the -network to be viewed. - -The particular library brought down for demonstration contained two -mathematics books. CLASS is developing and will spend the next year -developing an application that allows people at workstations to browse -the books. Thus, CLASS is developing a browsing tool, on the assumption -that users do not want to read an entire book from a workstation, but -would prefer to be able to look through and decide if they would like to -have a printed copy of it. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Re retrieval software * "Digital file copyright" * Scanning -rate during production * Autosegmentation * Criteria employed in -selecting books for scanning * Compression and decompression of images * -OCR not precluded * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -During the question-and-answer period that followed her presentation, -PERSONIUS made these additional points: - - * Re retrieval software, Cornell is developing a Unix-based server - as well as clients for the server that support multiple platforms - (Macintosh, IBM and Sun workstations), in the hope that people from - any of those platforms will retrieve books; a further operating - assumption is that standard interfaces will be used as much as - possible, where standards can be put in place, because CLASS - considers this retrieval software a library application and would - like to be able to look at material not only at Cornell but at other - institutions. - - * The phrase "digital file copyright by Cornell University" was - added at the advice of Cornell's legal staff with the caveat that it - probably would not hold up in court. Cornell does not want people - to copy its books and sell them but would like to keep them - available for use in a library environment for library purposes. - - * In production the scanner can scan about 300 pages per hour, - capturing 600 dots per inch. - - * The Xerox software has filters to scan halftone material and avoid - the moire patterns that occur when halftone material is scanned. - Xerox has been working on hardware and software that would enable - the scanner itself to recognize this situation and deal with it - appropriately--a kind of autosegmentation that would enable the - scanner to handle halftone material as well as text on a single page. - - * The books subjected to the elaborate process described above were - selected because CLASS is a preservation project, with the first 500 - books selected coming from Cornell's mathematics collection, because - they were still being heavily used and because, although they were - in need of preservation, the mathematics library and the mathematics - faculty were uncomfortable having them microfilmed. (They wanted a - printed copy.) Thus, these books became a logical choice for this - project. Other books were chosen by the project's selection committees - for experiments with the technology, as well as to meet a demand or need. - - * Images will be decompressed before they are sent over the line; at - this time they are compressed and sent to the image filing system - and then sent to the printer as compressed images; they are returned - to the workstation as compressed 600-dpi images and the workstation - decompresses and scales them for display--an inefficient way to - access the material though it works quite well for printing and - other purposes. - - * CLASS is also decompressing on Macintosh and IBM, a slow process - right now. Eventually, compression and decompression will take - place on an image conversion server. Trade-offs will be made, based - on future performance testing, concerning where the file is - compressed and what resolution image is sent. - - * OCR has not been precluded; images are being stored that have been - scanned at a high resolution, which presumably would suit them well - to an OCR process. Because the material being scanned is about 100 - years old and was printed with less-than-ideal technologies, very - early and preliminary tests have not produced good results. But the - project is capturing an image that is of sufficient resolution to be - subjected to OCR in the future. Moreover, the system architecture - and the system plan have a logical place to store an OCR image if it - has been captured. But that is not being done now. - - ****** - -SESSION III. DISTRIBUTION, NETWORKS, AND NETWORKING: OPTIONS FOR -DISSEMINATION - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -ZICH * Issues pertaining to CD-ROMs * Options for publishing in CD-ROM * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Robert ZICH, special assistant to the associate librarian for special -projects, Library of Congress, and moderator of this session, first noted -the blessed but somewhat awkward circumstance of having four very -distinguished people representing networks and networking or at least -leaning in that direction, while lacking anyone to speak from the -strongest possible background in CD-ROMs. ZICH expressed the hope that -members of the audience would join the discussion. He stressed the -subtitle of this particular session, "Options for Dissemination," and, -concerning CD-ROMs, the importance of determining when it would be wise -to consider dissemination in CD-ROM versus networks. A shopping list of -issues pertaining to CD-ROMs included: the grounds for selecting -commercial publishers, and in-house publication where possible versus -nonprofit or government publication. A similar list for networks -included: determining when one should consider dissemination through a -network, identifying the mechanisms or entities that exist to place items -on networks, identifying the pool of existing networks, determining how a -producer would choose between networks, and identifying the elements of -a business arrangement in a network. - -Options for publishing in CD-ROM: an outside publisher versus -self-publication. If an outside publisher is used, it can be nonprofit, -such as the Government Printing Office (GPO) or the National Technical -Information Service (NTIS), in the case of government. The pros and cons -associated with employing an outside publisher are obvious. Among the -pros, there is no trouble getting accepted. One pays the bill and, in -effect, goes one's way. Among the cons, when one pays an outside -publisher to perform the work, that publisher will perform the work it is -obliged to do, but perhaps without the production expertise and skill in -marketing and dissemination that some would seek. There is the body of -commercial publishers that do possess that kind of expertise in -distribution and marketing but that obviously are selective. In -self-publication, one exercises full control, but then one must handle -matters such as distribution and marketing. Such are some of the options -for publishing in the case of CD-ROM. - -In the case of technical and design issues, which are also important, -there are many matters which many at the Workshop already knew a good -deal about: retrieval system requirements and costs, what to do about -images, the various capabilities and platforms, the trade-offs between -cost and performance, concerns about local-area networkability, -interoperability, etc. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -LYNCH * Creating networked information is different from using networks -as an access or dissemination vehicle * Networked multimedia on a large -scale does not yet work * Typical CD-ROM publication model a two-edged -sword * Publishing information on a CD-ROM in the present world of -immature standards * Contrast between CD-ROM and network pricing * -Examples demonstrated earlier in the day as a set of insular information -gems * Paramount need to link databases * Layering to become increasingly -necessary * Project NEEDS and the issues of information reuse and active -versus passive use * X-Windows as a way of differentiating between -network access and networked information * Barriers to the distribution -of networked multimedia information * Need for good, real-time delivery -protocols * The question of presentation integrity in client-server -computing in the academic world * Recommendations for producing multimedia -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Clifford LYNCH, director, Library Automation, University of California, -opened his talk with the general observation that networked information -constituted a difficult and elusive topic because it is something just -starting to develop and not yet fully understood. LYNCH contended that -creating genuinely networked information was different from using -networks as an access or dissemination vehicle and was more sophisticated -and more subtle. He invited the members of the audience to extrapolate, -from what they heard about the preceding demonstration projects, to what -sort of a world of electronics information--scholarly, archival, -cultural, etc.--they wished to end up with ten or fifteen years from now. -LYNCH suggested that to extrapolate directly from these projects would -produce unpleasant results. - -Putting the issue of CD-ROM in perspective before getting into -generalities on networked information, LYNCH observed that those engaged -in multimedia today who wish to ship a product, so to say, probably do -not have much choice except to use CD-ROM: networked multimedia on a -large scale basically does not yet work because the technology does not -exist. For example, anybody who has tried moving images around over the -Internet knows that this is an exciting touch-and-go process, a -fascinating and fertile area for experimentation, research, and -development, but not something that one can become deeply enthusiastic -about committing to production systems at this time. - -This situation will change, LYNCH said. He differentiated CD-ROM from -the practices that have been followed up to now in distributing data on -CD-ROM. For LYNCH the problem with CD-ROM is not its portability or its -slowness but the two-edged sword of having the retrieval application and -the user interface inextricably bound up with the data, which is the -typical CD-ROM publication model. It is not a case of publishing data -but of distributing a typically stand-alone, typically closed system, -all--software, user interface, and data--on a little disk. Hence, all -the between-disk navigational issues as well as the impossibility in most -cases of integrating data on one disk with that on another. Most CD-ROM -retrieval software does not network very gracefully at present. However, -in the present world of immature standards and lack of understanding of -what network information is or what the ground rules are for creating or -using it, publishing information on a CD-ROM does add value in a very -real sense. - -LYNCH drew a contrast between CD-ROM and network pricing and in doing so -highlighted something bizarre in information pricing. A large -institution such as the University of California has vendors who will -offer to sell information on CD-ROM for a price per year in four digits, -but for the same data (e.g., an abstracting and indexing database) on -magnetic tape, regardless of how many people may use it concurrently, -will quote a price in six digits. - -What is packaged with the CD-ROM in one sense adds value--a complete -access system, not just raw, unrefined information--although it is not -generally perceived that way. This is because the access software, -although it adds value, is viewed by some people, particularly in the -university environment where there is a very heavy commitment to -networking, as being developed in the wrong direction. - -Given that context, LYNCH described the examples demonstrated as a set of -insular information gems--Perseus, for example, offers nicely linked -information, but would be very difficult to integrate with other -databases, that is, to link together seamlessly with other source files -from other sources. It resembles an island, and in this respect is -similar to numerous stand-alone projects that are based on videodiscs, -that is, on the single-workstation concept. - -As scholarship evolves in a network environment, the paramount need will -be to link databases. We must link personal databases to public -databases, to group databases, in fairly seamless ways--which is -extremely difficult in the environments under discussion with copies of -databases proliferating all over the place. - -The notion of layering also struck LYNCH as lurking in several of the -projects demonstrated. Several databases in a sense constitute -information archives without a significant amount of navigation built in. -Educators, critics, and others will want a layered structure--one that -defines or links paths through the layers to allow users to reach -specific points. In LYNCH's view, layering will become increasingly -necessary, and not just within a single resource but across resources -(e.g., tracing mythology and cultural themes across several classics -databases as well as a database of Renaissance culture). This ability to -organize resources, to build things out of multiple other things on the -network or select pieces of it, represented for LYNCH one of the key -aspects of network information. - -Contending that information reuse constituted another significant issue, -LYNCH commended to the audience's attention Project NEEDS (i.e., National -Engineering Education Delivery System). This project's objective is to -produce a database of engineering courseware as well as the components -that can be used to develop new courseware. In a number of the existing -applications, LYNCH said, the issue of reuse (how much one can take apart -and reuse in other applications) was not being well considered. He also -raised the issue of active versus passive use, one aspect of which is -how much information will be manipulated locally by users. Most people, -he argued, may do a little browsing and then will wish to print. LYNCH -was uncertain how these resources would be used by the vast majority of -users in the network environment. - -LYNCH next said a few words about X-Windows as a way of differentiating -between network access and networked information. A number of the -applications demonstrated at the Workshop could be rewritten to use X -across the network, so that one could run them from any X-capable device- --a workstation, an X terminal--and transact with a database across the -network. Although this opens up access a little, assuming one has enough -network to handle it, it does not provide an interface to develop a -program that conveniently integrates information from multiple databases. -X is a viewing technology that has limits. In a real sense, it is just a -graphical version of remote log-in across the network. X-type applications -represent only one step in the progression towards real access. - -LYNCH next discussed barriers to the distribution of networked multimedia -information. The heart of the problem is a lack of standards to provide -the ability for computers to talk to each other, retrieve information, -and shuffle it around fairly casually. At the moment, little progress is -being made on standards for networked information; for example, present -standards do not cover images, digital voice, and digital video. A -useful tool kit of exchange formats for basic texts is only now being -assembled. The synchronization of content streams (i.e., synchronizing a -voice track to a video track, establishing temporal relations between -different components in a multimedia object) constitutes another issue -for networked multimedia that is just beginning to receive attention. - -Underlying network protocols also need some work; good, real-time -delivery protocols on the Internet do not yet exist. In LYNCH's view, -highly important in this context is the notion of networked digital -object IDs, the ability of one object on the network to point to another -object (or component thereof) on the network. Serious bandwidth issues -also exist. LYNCH was uncertain if billion-bit-per-second networks would -prove sufficient if numerous people ran video in parallel. - -LYNCH concluded by offering an issue for database creators to consider, -as well as several comments about what might constitute good trial -multimedia experiments. In a networked information world the database -builder or service builder (publisher) does not exercise the same -extensive control over the integrity of the presentation; strange -programs "munge" with one's data before the user sees it. Serious -thought must be given to what guarantees integrity of presentation. Part -of that is related to where one draws the boundaries around a networked -information service. This question of presentation integrity in -client-server computing has not been stressed enough in the academic -world, LYNCH argued, though commercial service providers deal with it -regularly. - -Concerning multimedia, LYNCH observed that good multimedia at the moment -is hideously expensive to produce. He recommended producing multimedia -with either very high sale value, or multimedia with a very long life -span, or multimedia that will have a very broad usage base and whose -costs therefore can be amortized among large numbers of users. In this -connection, historical and humanistically oriented material may be a good -place to start, because it tends to have a longer life span than much of -the scientific material, as well as a wider user base. LYNCH noted, for -example, that American Memory fits many of the criteria outlined. He -remarked the extensive discussion about bringing the Internet or the -National Research and Education Network (NREN) into the K-12 environment -as a way of helping the American educational system. - -LYNCH closed by noting that the kinds of applications demonstrated struck -him as excellent justifications of broad-scale networking for K-12, but -that at this time no "killer" application exists to mobilize the K-12 -community to obtain connectivity. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Dearth of genuinely interesting applications on the network -a slow-changing situation * The issue of the integrity of presentation in -a networked environment * Several reasons why CD-ROM software does not -network * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -During the discussion period that followed LYNCH's presentation, several -additional points were made. - -LYNCH reiterated even more strongly his contention that, historically, -once one goes outside high-end science and the group of those who need -access to supercomputers, there is a great dearth of genuinely -interesting applications on the network. He saw this situation changing -slowly, with some of the scientific databases and scholarly discussion -groups and electronic journals coming on as well as with the availability -of Wide Area Information Servers (WAIS) and some of the databases that -are being mounted there. However, many of those things do not seem to -have piqued great popular interest. For instance, most high school -students of LYNCH's acquaintance would not qualify as devotees of serious -molecular biology. - -Concerning the issue of the integrity of presentation, LYNCH believed -that a couple of information providers have laid down the law at least on -certain things. For example, his recollection was that the National -Library of Medicine feels strongly that one needs to employ the -identifier field if he or she is to mount a database commercially. The -problem with a real networked environment is that one does not know who -is reformatting and reprocessing one's data when one enters a client -server mode. It becomes anybody's guess, for example, if the network -uses a Z39.50 server, or what clients are doing with one's data. A data -provider can say that his contract will only permit clients to have -access to his data after he vets them and their presentation and makes -certain it suits him. But LYNCH held out little expectation that the -network marketplace would evolve in that way, because it required too -much prior negotiation. - -CD-ROM software does not network for a variety of reasons, LYNCH said. -He speculated that CD-ROM publishers are not eager to have their products -really hook into wide area networks, because they fear it will make their -data suppliers nervous. Moreover, until relatively recently, one had to -be rather adroit to run a full TCP/IP stack plus applications on a -PC-size machine, whereas nowadays it is becoming easier as PCs grow -bigger and faster. LYNCH also speculated that software providers had not -heard from their customers until the last year or so, or had not heard -from enough of their customers. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -BESSER * Implications of disseminating images on the network; planning -the distribution of multimedia documents poses two critical -implementation problems * Layered approach represents the way to deal -with users' capabilities * Problems in platform design; file size and its -implications for networking * Transmission of megabyte size images -impractical * Compression and decompression at the user's end * Promising -trends for compression * A disadvantage of using X-Windows * A project at -the Smithsonian that mounts images on several networks * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Howard BESSER, School of Library and Information Science, University of -Pittsburgh, spoke primarily about multimedia, focusing on images and the -broad implications of disseminating them on the network. He argued that -planning the distribution of multimedia documents posed two critical -implementation problems, which he framed in the form of two questions: -1) What platform will one use and what hardware and software will users -have for viewing of the material? and 2) How can one deliver a -sufficiently robust set of information in an accessible format in a -reasonable amount of time? Depending on whether network or CD-ROM is the -medium used, this question raises different issues of storage, -compression, and transmission. - -Concerning the design of platforms (e.g., sound, gray scale, simple -color, etc.) and the various capabilities users may have, BESSER -maintained that a layered approach was the way to deal with users' -capabilities. A result would be that users with less powerful -workstations would simply have less functionality. He urged members of -the audience to advocate standards and accompanying software that handle -layered functionality across a wide variety of platforms. - -BESSER also addressed problems in platform design, namely, deciding how -large a machine to design for situations when the largest number of users -have the lowest level of the machine, and one desires higher -functionality. BESSER then proceeded to the question of file size and -its implications for networking. He discussed still images in the main. -For example, a digital color image that fills the screen of a standard -mega-pel workstation (Sun or Next) will require one megabyte of storage -for an eight-bit image or three megabytes of storage for a true color or -twenty-four-bit image. Lossless compression algorithms (that is, -computational procedures in which no data is lost in the process of -compressing [and decompressing] an image--the exact bit-representation is -maintained) might bring storage down to a third of a megabyte per image, -but not much further than that. The question of size makes it difficult -to fit an appropriately sized set of these images on a single disk or to -transmit them quickly enough on a network. - -With these full screen mega-pel images that constitute a third of a -megabyte, one gets 1,000-3,000 full-screen images on a one-gigabyte disk; -a standard CD-ROM represents approximately 60 percent of that. Storing -images the size of a PC screen (just 8 bit color) increases storage -capacity to 4,000-12,000 images per gigabyte; 60 percent of that gives -one the size of a CD-ROM, which in turn creates a major problem. One -cannot have full-screen, full-color images with lossless compression; one -must compress them or use a lower resolution. For megabyte-size images, -anything slower than a T-1 speed is impractical. For example, on a -fifty-six-kilobaud line, it takes three minutes to transfer a -one-megabyte file, if it is not compressed; and this speed assumes ideal -circumstances (no other user contending for network bandwidth). Thus, -questions of disk access, remote display, and current telephone -connection speed make transmission of megabyte-size images impractical. - -BESSER then discussed ways to deal with these large images, for example, -compression and decompression at the user's end. In this connection, the -issues of how much one is willing to lose in the compression process and -what image quality one needs in the first place are unknown. But what is -known is that compression entails some loss of data. BESSER urged that -more studies be conducted on image quality in different situations, for -example, what kind of images are needed for what kind of disciplines, and -what kind of image quality is needed for a browsing tool, an intermediate -viewing tool, and archiving. - -BESSER remarked two promising trends for compression: from a technical -perspective, algorithms that use what is called subjective redundancy -employ principles from visual psycho-physics to identify and remove -information from the image that the human eye cannot perceive; from an -interchange and interoperability perspective, the JPEG (i.e., Joint -Photographic Experts Group, an ISO standard) compression algorithms also -offer promise. These issues of compression and decompression, BESSER -argued, resembled those raised earlier concerning the design of different -platforms. Gauging the capabilities of potential users constitutes a -primary goal. BESSER advocated layering or separating the images from -the applications that retrieve and display them, to avoid tying them to -particular software. - -BESSER detailed several lessons learned from his work at Berkeley with -Imagequery, especially the advantages and disadvantages of using -X-Windows. In the latter category, for example, retrieval is tied -directly to one's data, an intolerable situation in the long run on a -networked system. Finally, BESSER described a project of Jim Wallace at -the Smithsonian Institution, who is mounting images in a extremely -rudimentary way on the Compuserv and Genie networks and is preparing to -mount them on America On Line. Although the average user takes over -thirty minutes to download these images (assuming a fairly fast modem), -nevertheless, images have been downloaded 25,000 times. - -BESSER concluded his talk with several comments on the business -arrangement between the Smithsonian and Compuserv. He contended that not -enough is known concerning the value of images. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Creating digitized photographic collections nearly -impossible except with large organizations like museums * Need for study -to determine quality of images users will tolerate * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -During the brief exchange between LESK and BESSER that followed, several -clarifications emerged. - -LESK argued that the photographers were far ahead of BESSER: It is -almost impossible to create such digitized photographic collections -except with large organizations like museums, because all the -photographic agencies have been going crazy about this and will not sign -licensing agreements on any sort of reasonable terms. LESK had heard -that National Geographic, for example, had tried to buy the right to use -some image in some kind of educational production for $100 per image, but -the photographers will not touch it. They want accounting and payment -for each use, which cannot be accomplished within the system. BESSER -responded that a consortium of photographers, headed by a former National -Geographic photographer, had started assembling its own collection of -electronic reproductions of images, with the money going back to the -cooperative. - -LESK contended that BESSER was unnecessarily pessimistic about multimedia -images, because people are accustomed to low-quality images, particularly -from video. BESSER urged the launching of a study to determine what -users would tolerate, what they would feel comfortable with, and what -absolutely is the highest quality they would ever need. Conceding that -he had adopted a dire tone in order to arouse people about the issue, -BESSER closed on a sanguine note by saying that he would not be in this -business if he did not think that things could be accomplished. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -LARSEN * Issues of scalability and modularity * Geometric growth of the -Internet and the role played by layering * Basic functions sustaining -this growth * A library's roles and functions in a network environment * -Effects of implementation of the Z39.50 protocol for information -retrieval on the library system * The trade-off between volumes of data -and its potential usage * A snapshot of current trends * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Ronald LARSEN, associate director for information technology, University -of Maryland at College Park, first addressed the issues of scalability -and modularity. He noted the difficulty of anticipating the effects of -orders-of-magnitude growth, reflecting on the twenty years of experience -with the Arpanet and Internet. Recalling the day's demonstrations of -CD-ROM and optical disk material, he went on to ask if the field has yet -learned how to scale new systems to enable delivery and dissemination -across large-scale networks. - -LARSEN focused on the geometric growth of the Internet from its inception -circa 1969 to the present, and the adjustments required to respond to -that rapid growth. To illustrate the issue of scalability, LARSEN -considered computer networks as including three generic components: -computers, network communication nodes, and communication media. Each -component scales (e.g., computers range from PCs to supercomputers; -network nodes scale from interface cards in a PC through sophisticated -routers and gateways; and communication media range from 2,400-baud -dial-up facilities through 4.5-Mbps backbone links, and eventually to -multigigabit-per-second communication lines), and architecturally, the -components are organized to scale hierarchically from local area networks -to international-scale networks. Such growth is made possible by -building layers of communication protocols, as BESSER pointed out. -By layering both physically and logically, a sense of scalability is -maintained from local area networks in offices, across campuses, through -bridges, routers, campus backbones, fiber-optic links, etc., up into -regional networks and ultimately into national and international -networks. - -LARSEN then illustrated the geometric growth over a two-year period-- -through September 1991--of the number of networks that comprise the -Internet. This growth has been sustained largely by the availability of -three basic functions: electronic mail, file transfer (ftp), and remote -log-on (telnet). LARSEN also reviewed the growth in the kind of traffic -that occurs on the network. Network traffic reflects the joint contributions -of a larger population of users and increasing use per user. Today one sees -serious applications involving moving images across the network--a rarity -ten years ago. LARSEN recalled and concurred with BESSER's main point -that the interesting problems occur at the application level. - -LARSEN then illustrated a model of a library's roles and functions in a -network environment. He noted, in particular, the placement of on-line -catalogues onto the network and patrons obtaining access to the library -increasingly through local networks, campus networks, and the Internet. -LARSEN supported LYNCH's earlier suggestion that we need to address -fundamental questions of networked information in order to build -environments that scale in the information sense as well as in the -physical sense. - -LARSEN supported the role of the library system as the access point into -the nation's electronic collections. Implementation of the Z39.50 -protocol for information retrieval would make such access practical and -feasible. For example, this would enable patrons in Maryland to search -California libraries, or other libraries around the world that are -conformant with Z39.50 in a manner that is familiar to University of -Maryland patrons. This client-server model also supports moving beyond -secondary content into primary content. (The notion of how one links -from secondary content to primary content, LARSEN said, represents a -fundamental problem that requires rigorous thought.) After noting -numerous network experiments in accessing full-text materials, including -projects supporting the ordering of materials across the network, LARSEN -revisited the issue of transmitting high-density, high-resolution color -images across the network and the large amounts of bandwidth they -require. He went on to address the bandwidth and synchronization -problems inherent in sending full-motion video across the network. - -LARSEN illustrated the trade-off between volumes of data in bytes or -orders of magnitude and the potential usage of that data. He discussed -transmission rates (particularly, the time it takes to move various forms -of information), and what one could do with a network supporting -multigigabit-per-second transmission. At the moment, the network -environment includes a composite of data-transmission requirements, -volumes and forms, going from steady to bursty (high-volume) and from -very slow to very fast. This aggregate must be considered in the design, -construction, and operation of multigigabyte networks. - -LARSEN's objective is to use the networks and library systems now being -constructed to increase access to resources wherever they exist, and -thus, to evolve toward an on-line electronic virtual library. - -LARSEN concluded by offering a snapshot of current trends: continuing -geometric growth in network capacity and number of users; slower -development of applications; and glacial development and adoption of -standards. The challenge is to design and develop each new application -system with network access and scalability in mind. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -BROWNRIGG * Access to the Internet cannot be taken for granted * Packet -radio and the development of MELVYL in 1980-81 in the Division of Library -Automation at the University of California * Design criteria for packet -radio * A demonstration project in San Diego and future plans * Spread -spectrum * Frequencies at which the radios will run and plans to -reimplement the WAIS server software in the public domain * Need for an -infrastructure of radios that do not move around * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Edwin BROWNRIGG, executive director, Memex Research Institute, first -polled the audience in order to seek out regular users of the Internet as -well as those planning to use it some time in the future. With nearly -everybody in the room falling into one category or the other, BROWNRIGG -made a point re access, namely that numerous individuals, especially those -who use the Internet every day, take for granted their access to it, the -speeds with which they are connected, and how well it all works. -However, as BROWNRIGG discovered between 1987 and 1989 in Australia, -if one wants access to the Internet but cannot afford it or has some -physical boundary that prevents her or him from gaining access, it can -be extremely frustrating. He suggested that because of economics and -physical barriers we were beginning to create a world of haves and have-nots -in the process of scholarly communication, even in the United States. - -BROWNRIGG detailed the development of MELVYL in academic year 1980-81 in -the Division of Library Automation at the University of California, in -order to underscore the issue of access to the system, which at the -outset was extremely limited. In short, the project needed to build a -network, which at that time entailed use of satellite technology, that is, -putting earth stations on campus and also acquiring some terrestrial links -from the State of California's microwave system. The installation of -satellite links, however, did not solve the problem (which actually -formed part of a larger problem involving politics and financial resources). -For while the project team could get a signal onto a campus, it had no means -of distributing the signal throughout the campus. The solution involved -adopting a recent development in wireless communication called packet radio, -which combined the basic notion of packet-switching with radio. The project -used this technology to get the signal from a point on campus where it -came down, an earth station for example, into the libraries, because it -found that wiring the libraries, especially the older marble buildings, -would cost $2,000-$5,000 per terminal. - -BROWNRIGG noted that, ten years ago, the project had neither the public -policy nor the technology that would have allowed it to use packet radio -in any meaningful way. Since then much had changed. He proceeded to -detail research and development of the technology, how it is being -deployed in California, and what direction he thought it would take. -The design criteria are to produce a high-speed, one-time, low-cost, -high-quality, secure, license-free device (packet radio) that one can -plug in and play today, forget about it, and have access to the Internet. -By high speed, BROWNRIGG meant 1 megabyte and 1.5 megabytes. Those units -have been built, he continued, and are in the process of being -type-certified by an independent underwriting laboratory so that they can -be type-licensed by the Federal Communications Commission. As is the -case with citizens band, one will be able to purchase a unit and not have -to worry about applying for a license. - -The basic idea, BROWNRIGG elaborated, is to take high-speed radio data -transmission and create a backbone network that at certain strategic -points in the network will "gateway" into a medium-speed packet radio -(i.e., one that runs at 38.4 kilobytes), so that perhaps by 1994-1995 -people, like those in the audience for the price of a VCR could purchase -a medium-speed radio for the office or home, have full network connectivity -to the Internet, and partake of all its services, with no need for an FCC -license and no regular bill from the local common carrier. BROWNRIGG -presented several details of a demonstration project currently taking -place in San Diego and described plans, pending funding, to install a -full-bore network in the San Francisco area. This network will have 600 -nodes running at backbone speeds, and 100 of these nodes will be libraries, -which in turn will be the gateway ports to the 38.4 kilobyte radios that -will give coverage for the neighborhoods surrounding the libraries. - -BROWNRIGG next explained Part 15.247, a new rule within Title 47 of the -Code of Federal Regulations enacted by the FCC in 1985. This rule -challenged the industry, which has only now risen to the occasion, to -build a radio that would run at no more than one watt of output power and -use a fairly exotic method of modulating the radio wave called spread -spectrum. Spread spectrum in fact permits the building of networks so -that numerous data communications can occur simultaneously, without -interfering with each other, within the same wide radio channel. - -BROWNRIGG explained that the frequencies at which the radios would run -are very short wave signals. They are well above standard microwave and -radar. With a radio wave that small, one watt becomes a tremendous punch -per bit and thus makes transmission at reasonable speed possible. In -order to minimize the potential for congestion, the project is -undertaking to reimplement software which has been available in the -networking business and is taken for granted now, for example, TCP/IP, -routing algorithms, bridges, and gateways. In addition, the project -plans to take the WAIS server software in the public domain and -reimplement it so that one can have a WAIS server on a Mac instead of a -Unix machine. The Memex Research Institute believes that libraries, in -particular, will want to use the WAIS servers with packet radio. This -project, which has a team of about twelve people, will run through 1993 -and will include the 100 libraries already mentioned as well as other -professionals such as those in the medical profession, engineering, and -law. Thus, the need is to create an infrastructure of radios that do not -move around, which, BROWNRIGG hopes, will solve a problem not only for -libraries but for individuals who, by and large today, do not have access -to the Internet from their homes and offices. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Project operating frequencies * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -During a brief discussion period, which also concluded the day's -proceedings, BROWNRIGG stated that the project was operating in four -frequencies. The slow speed is operating at 435 megahertz, and it would -later go up to 920 megahertz. With the high-speed frequency, the -one-megabyte radios will run at 2.4 gigabits, and 1.5 will run at 5.7. -At 5.7, rain can be a factor, but it would have to be tropical rain, -unlike what falls in most parts of the United States. - - ****** - -SESSION IV. IMAGE CAPTURE, TEXT CAPTURE, OVERVIEW OF TEXT AND - IMAGE STORAGE FORMATS - -William HOOTON, vice president of operations, I-NET, moderated this session. - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -KENNEY * Factors influencing development of CXP * Advantages of using -digital technology versus photocopy and microfilm * A primary goal of -CXP; publishing challenges * Characteristics of copies printed * Quality -of samples achieved in image capture * Several factors to be considered -in choosing scanning * Emphasis of CXP on timely and cost-effective -production of black-and-white printed facsimiles * Results of producing -microfilm from digital files * Advantages of creating microfilm * Details -concerning production * Costs * Role of digital technology in library -preservation * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Anne KENNEY, associate director, Department of Preservation and -Conservation, Cornell University, opened her talk by observing that the -Cornell Xerox Project (CXP) has been guided by the assumption that the -ability to produce printed facsimiles or to replace paper with paper -would be important, at least for the present generation of users and -equipment. She described three factors that influenced development of -the project: 1) Because the project has emphasized the preservation of -deteriorating brittle books, the quality of what was produced had to be -sufficiently high to return a paper replacement to the shelf. CXP was -only interested in using: 2) a system that was cost-effective, which -meant that it had to be cost-competitive with the processes currently -available, principally photocopy and microfilm, and 3) new or currently -available product hardware and software. - -KENNEY described the advantages that using digital technology offers over -both photocopy and microfilm: 1) The potential exists to create a higher -quality reproduction of a deteriorating original than conventional -light-lens technology. 2) Because a digital image is an encoded -representation, it can be reproduced again and again with no resulting -loss of quality, as opposed to the situation with light-lens processes, -in which there is discernible difference between a second and a -subsequent generation of an image. 3) A digital image can be manipulated -in a number of ways to improve image capture; for example, Xerox has -developed a windowing application that enables one to capture a page -containing both text and illustrations in a manner that optimizes the -reproduction of both. (With light-lens technology, one must choose which -to optimize, text or the illustration; in preservation microfilming, the -current practice is to shoot an illustrated page twice, once to highlight -the text and the second time to provide the best capture for the -illustration.) 4) A digital image can also be edited, density levels -adjusted to remove underlining and stains, and to increase legibility for -faint documents. 5) On-screen inspection can take place at the time of -initial setup and adjustments made prior to scanning, factors that -substantially reduce the number of retakes required in quality control. - -A primary goal of CXP has been to evaluate the paper output printed on -the Xerox DocuTech, a high-speed printer that produces 600-dpi pages from -scanned images at a rate of 135 pages a minute. KENNEY recounted several -publishing challenges to represent faithful and legible reproductions of -the originals that the 600-dpi copy for the most part successfully -captured. For example, many of the deteriorating volumes in the project -were heavily illustrated with fine line drawings or halftones or came in -languages such as Japanese, in which the buildup of characters comprised -of varying strokes is difficult to reproduce at lower resolutions; a -surprising number of them came with annotations and mathematical -formulas, which it was critical to be able to duplicate exactly. - -KENNEY noted that 1) the copies are being printed on paper that meets the -ANSI standards for performance, 2) the DocuTech printer meets the machine -and toner requirements for proper adhesion of print to page, as described -by the National Archives, and thus 3) paper product is considered to be -the archival equivalent of preservation photocopy. - -KENNEY then discussed several samples of the quality achieved in the -project that had been distributed in a handout, for example, a copy of a -print-on-demand version of the 1911 Reed lecture on the steam turbine, -which contains halftones, line drawings, and illustrations embedded in -text; the first four loose pages in the volume compared the capture -capabilities of scanning to photocopy for a standard test target, the -IEEE standard 167A 1987 test chart. In all instances scanning proved -superior to photocopy, though only slightly more so in one. - -Conceding the simplistic nature of her review of the quality of scanning -to photocopy, KENNEY described it as one representation of the kinds of -settings that could be used with scanning capabilities on the equipment -CXP uses. KENNEY also pointed out that CXP investigated the quality -achieved with binary scanning only, and noted the great promise in gray -scale and color scanning, whose advantages and disadvantages need to be -examined. She argued further that scanning resolutions and file formats -can represent a complex trade-off between the time it takes to capture -material, file size, fidelity to the original, and on-screen display; and -printing and equipment availability. All these factors must be taken -into consideration. - -CXP placed primary emphasis on the production in a timely and -cost-effective manner of printed facsimiles that consisted largely of -black-and-white text. With binary scanning, large files may be -compressed efficiently and in a lossless manner (i.e., no data is lost in -the process of compressing [and decompressing] an image--the exact -bit-representation is maintained) using Group 4 CCITT (i.e., the French -acronym for International Consultative Committee for Telegraph and -Telephone) compression. CXP was getting compression ratios of about -forty to one. Gray-scale compression, which primarily uses JPEG, is much -less economical and can represent a lossy compression (i.e., not -lossless), so that as one compresses and decompresses, the illustration -is subtly changed. While binary files produce a high-quality printed -version, it appears 1) that other combinations of spatial resolution with -gray and/or color hold great promise as well, and 2) that gray scale can -represent a tremendous advantage for on-screen viewing. The quality -associated with binary and gray scale also depends on the equipment used. -For instance, binary scanning produces a much better copy on a binary -printer. - -Among CXP's findings concerning the production of microfilm from digital -files, KENNEY reported that the digital files for the same Reed lecture -were used to produce sample film using an electron beam recorder. The -resulting film was faithful to the image capture of the digital files, -and while CXP felt that the text and image pages represented in the Reed -lecture were superior to that of the light-lens film, the resolution -readings for the 600 dpi were not as high as standard microfilming. -KENNEY argued that the standards defined for light-lens technology are -not totally transferable to a digital environment. Moreover, they are -based on definition of quality for a preservation copy. Although making -this case will prove to be a long, uphill struggle, CXP plans to continue -to investigate the issue over the course of the next year. - -KENNEY concluded this portion of her talk with a discussion of the -advantages of creating film: it can serve as a primary backup and as a -preservation master to the digital file; it could then become the print -or production master and service copies could be paper, film, optical -disks, magnetic media, or on-screen display. - -Finally, KENNEY presented details re production: - - * Development and testing of a moderately-high resolution production - scanning workstation represented a third goal of CXP; to date, 1,000 - volumes have been scanned, or about 300,000 images. - - * The resulting digital files are stored and used to produce - hard-copy replacements for the originals and additional prints on - demand; although the initial costs are high, scanning technology - offers an affordable means for reformatting brittle material. - - * A technician in production mode can scan 300 pages per hour when - performing single-sheet scanning, which is a necessity when working - with truly brittle paper; this figure is expected to increase - significantly with subsequent iterations of the software from Xerox; - a three-month time-and-cost study of scanning found that the average - 300-page book would take about an hour and forty minutes to scan - (this figure included the time for setup, which involves keying in - primary bibliographic data, going into quality control mode to - define page size, establishing front-to-back registration, and - scanning sample pages to identify a default range of settings for - the entire book--functions not dissimilar to those performed by - filmers or those preparing a book for photocopy). - - * The final step in the scanning process involved rescans, which - happily were few and far between, representing well under 1 percent - of the total pages scanned. - -In addition to technician time, CXP costed out equipment, amortized over -four years, the cost of storing and refreshing the digital files every -four years, and the cost of printing and binding, book-cloth binding, a -paper reproduction. The total amounted to a little under $65 per single -300-page volume, with 30 percent overhead included--a figure competitive -with the prices currently charged by photocopy vendors. - -Of course, with scanning, in addition to the paper facsimile, one is left -with a digital file from which subsequent copies of the book can be -produced for a fraction of the cost of photocopy, with readers afforded -choices in the form of these copies. - -KENNEY concluded that digital technology offers an electronic means for a -library preservation effort to pay for itself. If a brittle-book program -included the means of disseminating reprints of books that are in demand -by libraries and researchers alike, the initial investment in capture -could be recovered and used to preserve additional but less popular -books. She disclosed that an economic model for a self-sustaining -program could be developed for CXP's report to the Commission on -Preservation and Access (CPA). - -KENNEY stressed that the focus of CXP has been on obtaining high quality -in a production environment. The use of digital technology is viewed as -an affordable alternative to other reformatting options. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -ANDRE * Overview and history of NATDP * Various agricultural CD-ROM -products created inhouse and by service bureaus * Pilot project on -Internet transmission * Additional products in progress * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Pamela ANDRE, associate director for automation, National Agricultural -Text Digitizing Program (NATDP), National Agricultural Library (NAL), -presented an overview of NATDP, which has been underway at NAL the last -four years, before Judith ZIDAR discussed the technical details. ANDRE -defined agricultural information as a broad range of material going from -basic and applied research in the hard sciences to the one-page pamphlets -that are distributed by the cooperative state extension services on such -things as how to grow blueberries. - -NATDP began in late 1986 with a meeting of representatives from the -land-grant library community to deal with the issue of electronic -information. NAL and forty-five of these libraries banded together to -establish this project--to evaluate the technology for converting what -were then source documents in paper form into electronic form, to provide -access to that digital information, and then to distribute it. -Distributing that material to the community--the university community as -well as the extension service community, potentially down to the county -level--constituted the group's chief concern. - -Since January 1988 (when the microcomputer-based scanning system was -installed at NAL), NATDP has done a variety of things, concerning which -ZIDAR would provide further details. For example, the first technology -considered in the project's discussion phase was digital videodisc, which -indicates how long ago it was conceived. - -Over the four years of this project, four separate CD-ROM products on -four different agricultural topics were created, two at a -scanning-and-OCR station installed at NAL, and two by service bureaus. -Thus, NATDP has gained comparative information in terms of those relative -costs. Each of these products contained the full ASCII text as well as -page images of the material, or between 4,000 and 6,000 pages of material -on these disks. Topics included aquaculture, food, agriculture and -science (i.e., international agriculture and research), acid rain, and -Agent Orange, which was the final product distributed (approximately -eighteen months before the Workshop). - -The third phase of NATDP focused on delivery mechanisms other than -CD-ROM. At the suggestion of Clifford LYNCH, who was a technical -consultant to the project at this point, NATDP became involved with the -Internet and initiated a project with the help of North Carolina State -University, in which fourteen of the land-grant university libraries are -transmitting digital images over the Internet in response to interlibrary -loan requests--a topic for another meeting. At this point, the pilot -project had been completed for about a year and the final report would be -available shortly after the Workshop. In the meantime, the project's -success had led to its extension. (ANDRE noted that one of the first -things done under the program title was to select a retrieval package to -use with subsequent products; Windows Personal Librarian was the package -of choice after a lengthy evaluation.) - -Three additional products had been planned and were in progress: - - 1) An arrangement with the American Society of Agronomy--a - professional society that has published the Agronomy Journal since - about 1908--to scan and create bit-mapped images of its journal. - ASA granted permission first to put and then to distribute this - material in electronic form, to hold it at NAL, and to use these - electronic images as a mechanism to deliver documents or print out - material for patrons, among other uses. Effectively, NAL has the - right to use this material in support of its program. - (Significantly, this arrangement offers a potential cooperative - model for working with other professional societies in agriculture - to try to do the same thing--put the journals of particular interest - to agriculture research into electronic form.) - - 2) An extension of the earlier product on aquaculture. - - 3) The George Washington Carver Papers--a joint project with - Tuskegee University to scan and convert from microfilm some 3,500 - images of Carver's papers, letters, and drawings. - -It was anticipated that all of these products would appear no more than -six months after the Workshop. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -ZIDAR * (A separate arena for scanning) * Steps in creating a database * -Image capture, with and without performing OCR * Keying in tracking data -* Scanning, with electronic and manual tracking * Adjustments during -scanning process * Scanning resolutions * Compression * De-skewing and -filtering * Image capture from microform: the papers and letters of -George Washington Carver * Equipment used for a scanning system * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Judith ZIDAR, coordinator, National Agricultural Text Digitizing Program -(NATDP), National Agricultural Library (NAL), illustrated the technical -details of NATDP, including her primary responsibility, scanning and -creating databases on a topic and putting them on CD-ROM. - -(ZIDAR remarked a separate arena from the CD-ROM projects, although the -processing of the material is nearly identical, in which NATDP is also -scanning material and loading it on a Next microcomputer, which in turn -is linked to NAL's integrated library system. Thus, searches in NAL's -bibliographic database will enable people to pull up actual page images -and text for any documents that have been entered.) - -In accordance with the session's topic, ZIDAR focused her illustrated -talk on image capture, offering a primer on the three main steps in the -process: 1) assemble the printed publications; 2) design the database -(database design occurs in the process of preparing the material for -scanning; this step entails reviewing and organizing the material, -defining the contents--what will constitute a record, what kinds of -fields will be captured in terms of author, title, etc.); 3) perform a -certain amount of markup on the paper publications. NAL performs this -task record by record, preparing work sheets or some other sort of -tracking material and designing descriptors and other enhancements to be -added to the data that will not be captured from the printed publication. -Part of this process also involves determining NATDP's file and directory -structure: NATDP attempts to avoid putting more than approximately 100 -images in a directory, because placing more than that on a CD-ROM would -reduce the access speed. - -This up-front process takes approximately two weeks for a -6,000-7,000-page database. The next step is to capture the page images. -How long this process takes is determined by the decision whether or not -to perform OCR. Not performing OCR speeds the process, whereas text -capture requires greater care because of the quality of the image: it -has to be straighter and allowance must be made for text on a page, not -just for the capture of photographs. - -NATDP keys in tracking data, that is, a standard bibliographic record -including the title of the book and the title of the chapter, which will -later either become the access information or will be attached to the -front of a full-text record so that it is searchable. - -Images are scanned from a bound or unbound publication, chiefly from -bound publications in the case of NATDP, however, because often they are -the only copies and the publications are returned to the shelves. NATDP -usually scans one record at a time, because its database tracking system -tracks the document in that way and does not require further logical -separating of the images. After performing optical character -recognition, NATDP moves the images off the hard disk and maintains a -volume sheet. Though the system tracks electronically, all the -processing steps are also tracked manually with a log sheet. - -ZIDAR next illustrated the kinds of adjustments that one can make when -scanning from paper and microfilm, for example, redoing images that need -special handling, setting for dithering or gray scale, and adjusting for -brightness or for the whole book at one time. - -NATDP is scanning at 300 dots per inch, a standard scanning resolution. -Though adequate for capturing text that is all of a standard size, 300 -dpi is unsuitable for any kind of photographic material or for very small -text. Many scanners allow for different image formats, TIFF, of course, -being a de facto standard. But if one intends to exchange images with -other people, the ability to scan other image formats, even if they are -less common, becomes highly desirable. - -CCITT Group 4 is the standard compression for normal black-and-white -images, JPEG for gray scale or color. ZIDAR recommended 1) using the -standard compressions, particularly if one attempts to make material -available and to allow users to download images and reuse them from -CD-ROMs; and 2) maintaining the ability to output an uncompressed image, -because in image exchange uncompressed images are more likely to be able -to cross platforms. - -ZIDAR emphasized the importance of de-skewing and filtering as -requirements on NATDP's upgraded system. For instance, scanning bound -books, particularly books published by the federal government whose pages -are skewed, and trying to scan them straight if OCR is to be performed, -is extremely time-consuming. The same holds for filtering of -poor-quality or older materials. - -ZIDAR described image capture from microform, using as an example three -reels from a sixty-seven-reel set of the papers and letters of George -Washington Carver that had been produced by Tuskegee University. These -resulted in approximately 3,500 images, which NATDP had had scanned by -its service contractor, Science Applications International Corporation -(SAIC). NATDP also created bibliographic records for access. (NATDP did -not have such specialized equipment as a microfilm scanner. - -Unfortunately, the process of scanning from microfilm was not an -unqualified success, ZIDAR reported: because microfilm frame sizes vary, -occasionally some frames were missed, which without spending much time -and money could not be recaptured. - -OCR could not be performed from the scanned images of the frames. The -bleeding in the text simply output text, when OCR was run, that could not -even be edited. NATDP tested for negative versus positive images, -landscape versus portrait orientation, and single- versus dual-page -microfilm, none of which seemed to affect the quality of the image; but -also on none of them could OCR be performed. - -In selecting the microfilm they would use, therefore, NATDP had other -factors in mind. ZIDAR noted two factors that influenced the quality of -the images: 1) the inherent quality of the original and 2) the amount of -size reduction on the pages. - -The Carver papers were selected because they are informative and visually -interesting, treat a single subject, and are valuable in their own right. -The images were scanned and divided into logical records by SAIC, then -delivered, and loaded onto NATDP's system, where bibliographic -information taken directly from the images was added. Scanning was -completed in summer 1991 and by the end of summer 1992 the disk was -scheduled to be published. - -Problems encountered during processing included the following: Because -the microfilm scanning had to be done in a batch, adjustment for -individual page variations was not possible. The frame size varied on -account of the nature of the material, and therefore some of the frames -were missed while others were just partial frames. The only way to go -back and capture this material was to print out the page with the -microfilm reader from the missing frame and then scan it in from the -page, which was extremely time-consuming. The quality of the images -scanned from the printout of the microfilm compared unfavorably with that -of the original images captured directly from the microfilm. The -inability to perform OCR also was a major disappointment. At the time, -computer output microfilm was unavailable to test. - -The equipment used for a scanning system was the last topic addressed by -ZIDAR. The type of equipment that one would purchase for a scanning -system included: a microcomputer, at least a 386, but preferably a 486; -a large hard disk, 380 megabyte at minimum; a multi-tasking operating -system that allows one to run some things in batch in the background -while scanning or doing text editing, for example, Unix or OS/2 and, -theoretically, Windows; a high-speed scanner and scanning software that -allows one to make the various adjustments mentioned earlier; a -high-resolution monitor (150 dpi ); OCR software and hardware to perform -text recognition; an optical disk subsystem on which to archive all the -images as the processing is done; file management and tracking software. - -ZIDAR opined that the software one purchases was more important than the -hardware and might also cost more than the hardware, but it was likely to -prove critical to the success or failure of one's system. In addition to -a stand-alone scanning workstation for image capture, then, text capture -requires one or two editing stations networked to this scanning station -to perform editing. Editing the text takes two or three times as long as -capturing the images. - -Finally, ZIDAR stressed the importance of buying an open system that allows -for more than one vendor, complies with standards, and can be upgraded. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -WATERS *Yale University Library's master plan to convert microfilm to -digital imagery (POB) * The place of electronic tools in the library of -the future * The uses of images and an image library * Primary input from -preservation microfilm * Features distinguishing POB from CXP and key -hypotheses guiding POB * Use of vendor selection process to facilitate -organizational work * Criteria for selecting vendor * Finalists and -results of process for Yale * Key factor distinguishing vendors * -Components, design principles, and some estimated costs of POB * Role of -preservation materials in developing imaging market * Factors affecting -quality and cost * Factors affecting the usability of complex documents -in image form * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Donald WATERS, head of the Systems Office, Yale University Library, -reported on the progress of a master plan for a project at Yale to -convert microfilm to digital imagery, Project Open Book (POB). Stating -that POB was in an advanced stage of planning, WATERS detailed, in -particular, the process of selecting a vendor partner and several key -issues under discussion as Yale prepares to move into the project itself. -He commented first on the vision that serves as the context of POB and -then described its purpose and scope. - -WATERS sees the library of the future not necessarily as an electronic -library but as a place that generates, preserves, and improves for its -clients ready access to both intellectual and physical recorded -knowledge. Electronic tools must find a place in the library in the -context of this vision. Several roles for electronic tools include -serving as: indirect sources of electronic knowledge or as "finding" -aids (the on-line catalogues, the article-level indices, registers for -documents and archives); direct sources of recorded knowledge; full-text -images; and various kinds of compound sources of recorded knowledge (the -so-called compound documents of Hypertext, mixed text and image, -mixed-text image format, and multimedia). - -POB is looking particularly at images and an image library, the uses to -which images will be put (e.g., storage, printing, browsing, and then use -as input for other processes), OCR as a subsequent process to image -capture, or creating an image library, and also possibly generating -microfilm. - -While input will come from a variety of sources, POB is considering -especially input from preservation microfilm. A possible outcome is that -the film and paper which provide the input for the image library -eventually may go off into remote storage, and that the image library may -be the primary access tool. - -The purpose and scope of POB focus on imaging. Though related to CXP, -POB has two features which distinguish it: 1) scale--conversion of -10,000 volumes into digital image form; and 2) source--conversion from -microfilm. Given these features, several key working hypotheses guide -POB, including: 1) Since POB is using microfilm, it is not concerned with -the image library as a preservation medium. 2) Digital imagery can improve -access to recorded knowledge through printing and network distribution at -a modest incremental cost of microfilm. 3) Capturing and storing documents -in a digital image form is necessary to further improvements in access. -(POB distinguishes between the imaging, digitizing process and OCR, -which at this stage it does not plan to perform.) - -Currently in its first or organizational phase, POB found that it could -use a vendor selection process to facilitate a good deal of the -organizational work (e.g., creating a project team and advisory board, -confirming the validity of the plan, establishing the cost of the project -and a budget, selecting the materials to convert, and then raising the -necessary funds). - -POB developed numerous selection criteria, including: a firm committed -to image-document management, the ability to serve as systems integrator -in a large-scale project over several years, interest in developing the -requisite software as a standard rather than a custom product, and a -willingness to invest substantial resources in the project itself. - -Two vendors, DEC and Xerox, were selected as finalists in October 1991, -and with the support of the Commission on Preservation and Access, each -was commissioned to generate a detailed requirements analysis for the -project and then to submit a formal proposal for the completion of the -project, which included a budget and costs. The terms were that POB would -pay the loser. The results for Yale of involving a vendor included: -broad involvement of Yale staff across the board at a relatively low -cost, which may have long-term significance in carrying out the project -(twenty-five to thirty university people are engaged in POB); better -understanding of the factors that affect corporate response to markets -for imaging products; a competitive proposal; and a more sophisticated -view of the imaging markets. - -The most important factor that distinguished the vendors under -consideration was their identification with the customer. The size and -internal complexity of the company also was an important factor. POB was -looking at large companies that had substantial resources. In the end, -the process generated for Yale two competitive proposals, with Xerox's -the clear winner. WATERS then described the components of the proposal, -the design principles, and some of the costs estimated for the process. - -Components are essentially four: a conversion subsystem, a -network-accessible storage subsystem for 10,000 books (and POB expects -200 to 600 dpi storage), browsing stations distributed on the campus -network, and network access to the image printers. - -Among the design principles, POB wanted conversion at the highest -possible resolution. Assuming TIFF files, TIFF files with Group 4 -compression, TCP/IP, and ethernet network on campus, POB wanted a -client-server approach with image documents distributed to the -workstations and made accessible through native workstation interfaces -such as Windows. POB also insisted on a phased approach to -implementation: 1) a stand-alone, single-user, low-cost entry into the -business with a workstation focused on conversion and allowing POB to -explore user access; 2) movement into a higher-volume conversion with -network-accessible storage and multiple access stations; and 3) a -high-volume conversion, full-capacity storage, and multiple browsing -stations distributed throughout the campus. - -The costs proposed for start-up assumed the existence of the Yale network -and its two DocuTech image printers. Other start-up costs are estimated -at $1 million over the three phases. At the end of the project, the annual -operating costs estimated primarily for the software and hardware proposed -come to about $60,000, but these exclude costs for labor needed in the -conversion process, network and printer usage, and facilities management. - -Finally, the selection process produced for Yale a more sophisticated -view of the imaging markets: the management of complex documents in -image form is not a preservation problem, not a library problem, but a -general problem in a broad, general industry. Preservation materials are -useful for developing that market because of the qualities of the -material. For example, much of it is out of copyright. The resolution -of key issues such as the quality of scanning and image browsing also -will affect development of that market. - -The technology is readily available but changing rapidly. In this -context of rapid change, several factors affect quality and cost, to -which POB intends to pay particular attention, for example, the various -levels of resolution that can be achieved. POB believes it can bring -resolution up to 600 dpi, but an interpolation process from 400 to 600 is -more likely. The variation quality in microfilm will prove to be a -highly important factor. POB may reexamine the standards used to film in -the first place by looking at this process as a follow-on to microfilming. - -Other important factors include: the techniques available to the -operator for handling material, the ways of integrating quality control -into the digitizing work flow, and a work flow that includes indexing and -storage. POB's requirement was to be able to deal with quality control -at the point of scanning. Thus, thanks to Xerox, POB anticipates having -a mechanism which will allow it not only to scan in batch form, but to -review the material as it goes through the scanner and control quality -from the outset. - -The standards for measuring quality and costs depend greatly on the uses -of the material, including subsequent OCR, storage, printing, and -browsing. But especially at issue for POB is the facility for browsing. -This facility, WATERS said, is perhaps the weakest aspect of imaging -technology and the most in need of development. - -A variety of factors affect the usability of complex documents in image -form, among them: 1) the ability of the system to handle the full range -of document types, not just monographs but serials, multi-part -monographs, and manuscripts; 2) the location of the database of record -for bibliographic information about the image document, which POB wants -to enter once and in the most useful place, the on-line catalog; 3) a -document identifier for referencing the bibliographic information in one -place and the images in another; 4) the technique for making the basic -internal structure of the document accessible to the reader; and finally, -5) the physical presentation on the CRT of those documents. POB is ready -to complete this phase now. One last decision involves deciding which -material to scan. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * TIFF files constitute de facto standard * NARA's experience -with image conversion software and text conversion * RFC 1314 * -Considerable flux concerning available hardware and software solutions * -NAL through-put rate during scanning * Window management questions * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -In the question-and-answer period that followed WATERS's presentation, -the following points emerged: - - * ZIDAR's statement about using TIFF files as a standard meant de - facto standard. This is what most people use and typically exchange - with other groups, across platforms, or even occasionally across - display software. - - * HOLMES commented on the unsuccessful experience of NARA in - attempting to run image-conversion software or to exchange between - applications: What are supposedly TIFF files go into other software - that is supposed to be able to accept TIFF but cannot recognize the - format and cannot deal with it, and thus renders the exchange - useless. Re text conversion, he noted the different recognition - rates obtained by substituting the make and model of scanners in - NARA's recent test of an "intelligent" character-recognition product - for a new company. In the selection of hardware and software, - HOLMES argued, software no longer constitutes the overriding factor - it did until about a year ago; rather it is perhaps important to - look at both now. - - * Danny Cohen and Alan Katz of the University of Southern California - Information Sciences Institute began circulating as an Internet RFC - (RFC 1314) about a month ago a standard for a TIFF interchange - format for Internet distribution of monochrome bit-mapped images, - which LYNCH said he believed would be used as a de facto standard. - - * FLEISCHHAUER's impression from hearing these reports and thinking - about AM's experience was that there is considerable flux concerning - available hardware and software solutions. HOOTON agreed and - commented at the same time on ZIDAR's statement that the equipment - employed affects the results produced. One cannot draw a complete - conclusion by saying it is difficult or impossible to perform OCR - from scanning microfilm, for example, with that device, that set of - parameters, and system requirements, because numerous other people - are accomplishing just that, using other components, perhaps. - HOOTON opined that both the hardware and the software were highly - important. Most of the problems discussed today have been solved in - numerous different ways by other people. Though it is good to be - cognizant of various experiences, this is not to say that it will - always be thus. - - * At NAL, the through-put rate of the scanning process for paper, - page by page, performing OCR, ranges from 300 to 600 pages per day; - not performing OCR is considerably faster, although how much faster - is not known. This is for scanning from bound books, which is much - slower. - - * WATERS commented on window management questions: DEC proposed an - X-Windows solution which was problematical for two reasons. One was - POB's requirement to be able to manipulate images on the workstation - and bring them down to the workstation itself and the other was - network usage. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -THOMA * Illustration of deficiencies in scanning and storage process * -Image quality in this process * Different costs entailed by better image -quality * Techniques for overcoming various de-ficiencies: fixed -thresholding, dynamic thresholding, dithering, image merge * Page edge -effects * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -George THOMA, chief, Communications Engineering Branch, National Library -of Medicine (NLM), illustrated several of the deficiencies discussed by -the previous speakers. He introduced the topic of special problems by -noting the advantages of electronic imaging. For example, it is regenerable -because it is a coded file, and real-time quality control is possible with -electronic capture, whereas in photographic capture it is not. - -One of the difficulties discussed in the scanning and storage process was -image quality which, without belaboring the obvious, means different -things for maps, medical X-rays, or broadcast television. In the case of -documents, THOMA said, image quality boils down to legibility of the -textual parts, and fidelity in the case of gray or color photo print-type -material. Legibility boils down to scan density, the standard in most -cases being 300 dpi. Increasing the resolution with scanners that -perform 600 or 1200 dpi, however, comes at a cost. - -Better image quality entails at least four different kinds of costs: 1) -equipment costs, because the CCD (i.e., charge-couple device) with -greater number of elements costs more; 2) time costs that translate to -the actual capture costs, because manual labor is involved (the time is -also dependent on the fact that more data has to be moved around in the -machine in the scanning or network devices that perform the scanning as -well as the storage); 3) media costs, because at high resolutions larger -files have to be stored; and 4) transmission costs, because there is just -more data to be transmitted. - -But while resolution takes care of the issue of legibility in image -quality, other deficiencies have to do with contrast and elements on the -page scanned or the image that needed to be removed or clarified. Thus, -THOMA proceeded to illustrate various deficiencies, how they are -manifested, and several techniques to overcome them. - -Fixed thresholding was the first technique described, suitable for -black-and-white text, when the contrast does not vary over the page. One -can have many different threshold levels in scanning devices. Thus, -THOMA offered an example of extremely poor contrast, which resulted from -the fact that the stock was a heavy red. This is the sort of image that -when microfilmed fails to provide any legibility whatsoever. Fixed -thresholding is the way to change the black-to-red contrast to the -desired black-to-white contrast. - -Other examples included material that had been browned or yellowed by -age. This was also a case of contrast deficiency, and correction was -done by fixed thresholding. A final example boils down to the same -thing, slight variability, but it is not significant. Fixed thresholding -solves this problem as well. The microfilm equivalent is certainly legible, -but it comes with dark areas. Though THOMA did not have a slide of the -microfilm in this case, he did show the reproduced electronic image. - -When one has variable contrast over a page or the lighting over the page -area varies, especially in the case where a bound volume has light -shining on it, the image must be processed by a dynamic thresholding -scheme. One scheme, dynamic averaging, allows the threshold level not to -be fixed but to be recomputed for every pixel from the neighboring -characteristics. The neighbors of a pixel determine where the threshold -should be set for that pixel. - -THOMA showed an example of a page that had been made deficient by a -variety of techniques, including a burn mark, coffee stains, and a yellow -marker. Application of a fixed-thresholding scheme, THOMA argued, might -take care of several deficiencies on the page but not all of them. -Performing the calculation for a dynamic threshold setting, however, -removes most of the deficiencies so that at least the text is legible. - -Another problem is representing a gray level with black-and-white pixels -by a process known as dithering or electronic screening. But dithering -does not provide good image quality for pure black-and-white textual -material. THOMA illustrated this point with examples. Although its -suitability for photoprint is the reason for electronic screening or -dithering, it cannot be used for every compound image. In the document -that was distributed by CXP, THOMA noticed that the dithered image of the -IEEE test chart evinced some deterioration in the text. He presented an -extreme example of deterioration in the text in which compounded -documents had to be set right by other techniques. The technique -illustrated by the present example was an image merge in which the page -is scanned twice and the settings go from fixed threshold to the -dithering matrix; the resulting images are merged to give the best -results with each technique. - -THOMA illustrated how dithering is also used in nonphotographic or -nonprint materials with an example of a grayish page from a medical text, -which was reproduced to show all of the gray that appeared in the -original. Dithering provided a reproduction of all the gray in the -original of another example from the same text. - -THOMA finally illustrated the problem of bordering, or page-edge, -effects. Books and bound volumes that are placed on a photocopy machine -or a scanner produce page-edge effects that are undesirable for two -reasons: 1) the aesthetics of the image; after all, if the image is to -be preserved, one does not necessarily want to keep all of its -deficiencies; 2) compression (with the bordering problem THOMA -illustrated, the compression ratio deteriorated tremendously). One way -to eliminate this more serious problem is to have the operator at the -point of scanning window the part of the image that is desirable and -automatically turn all of the pixels out of that picture to white. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -FLEISCHHAUER * AM's experience with scanning bound materials * Dithering -* -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Carl FLEISCHHAUER, coordinator, American Memory, Library of Congress, -reported AM's experience with scanning bound materials, which he likened -to the problems involved in using photocopying machines. Very few -devices in the industry offer book-edge scanning, let alone book cradles. -The problem may be unsolvable, FLEISCHHAUER said, because a large enough -market does not exist for a preservation-quality scanner. AM is using a -Kurzweil scanner, which is a book-edge scanner now sold by Xerox. - -Devoting the remainder of his brief presentation to dithering, -FLEISCHHAUER related AM's experience with a contractor who was using -unsophisticated equipment and software to reduce moire patterns from -printed halftones. AM took the same image and used the dithering -algorithm that forms part of the same Kurzweil Xerox scanner; it -disguised moire patterns much more effectively. - -FLEISCHHAUER also observed that dithering produces a binary file which is -useful for numerous purposes, for example, printing it on a laser printer -without having to "re-halftone" it. But it tends to defeat efficient -compression, because the very thing that dithers to reduce moire patterns -also tends to work against compression schemes. AM thought the -difference in image quality was worth it. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Relative use as a criterion for POB's selection of books to -be converted into digital form * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -During the discussion period, WATERS noted that one of the criteria for -selecting books among the 10,000 to be converted into digital image form -would be how much relative use they would receive--a subject still -requiring evaluation. The challenge will be to understand whether -coherent bodies of material will increase usage or whether POB should -seek material that is being used, scan that, and make it more accessible. -POB might decide to digitize materials that are already heavily used, in -order to make them more accessible and decrease wear on them. Another -approach would be to provide a large body of intellectually coherent -material that may be used more in digital form than it is currently used -in microfilm. POB would seek material that was out of copyright. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -BARONAS * Origin and scope of AIIM * Types of documents produced in -AIIM's standards program * Domain of AIIM's standardization work * AIIM's -structure * TC 171 and MS23 * Electronic image management standards * -Categories of EIM standardization where AIIM standards are being -developed * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Jean BARONAS, senior manager, Department of Standards and Technology, -Association for Information and Image Management (AIIM), described the -not-for-profit association and the national and international programs -for standardization in which AIIM is active. - -Accredited for twenty-five years as the nation's standards development -organization for document image management, AIIM began life in a library -community developing microfilm standards. Today the association -maintains both its library and business-image management standardization -activities--and has moved into electronic image-management -standardization (EIM). - -BARONAS defined the program's scope. AIIM deals with: 1) the -terminology of standards and of the technology it uses; 2) methods of -measurement for the systems, as well as quality; 3) methodologies for -users to evaluate and measure quality; 4) the features of apparatus used -to manage and edit images; and 5) the procedures used to manage images. - -BARONAS noted that three types of documents are produced in the AIIM -standards program: the first two, accredited by the American National -Standards Institute (ANSI), are standards and standard recommended -practices. Recommended practices differ from standards in that they -contain more tutorial information. A technical report is not an ANSI -standard. Because AIIM's policies and procedures for developing -standards are approved by ANSI, its standards are labeled ANSI/AIIM, -followed by the number and title of the standard. - -BARONAS then illustrated the domain of AIIM's standardization work. For -example, AIIM is the administrator of the U.S. Technical Advisory Group -(TAG) to the International Standards Organization's (ISO) technical -committee, TC l7l Micrographics and Optical Memories for Document and -Image Recording, Storage, and Use. AIIM officially works through ANSI in -the international standardization process. - -BARONAS described AIIM's structure, including its board of directors, its -standards board of twelve individuals active in the image-management -industry, its strategic planning and legal admissibility task forces, and -its National Standards Council, which is comprised of the members of a -number of organizations who vote on every AIIM standard before it is -published. BARONAS pointed out that AIIM's liaisons deal with numerous -other standards developers, including the optical disk community, office -and publishing systems, image-codes-and-character set committees, and the -National Information Standards Organization (NISO). - -BARONAS illustrated the procedures of TC l7l, which covers all aspects of -image management. When AIIM's national program has conceptualized a new -project, it is usually submitted to the international level, so that the -member countries of TC l7l can simultaneously work on the development of -the standard or the technical report. BARONAS also illustrated a classic -microfilm standard, MS23, which deals with numerous imaging concepts that -apply to electronic imaging. Originally developed in the l970s, revised -in the l980s, and revised again in l991, this standard is scheduled for -another revision. MS23 is an active standard whereby users may propose -new density ranges and new methods of evaluating film images in the -standard's revision. - -BARONAS detailed several electronic image-management standards, for -instance, ANSI/AIIM MS44, a quality-control guideline for scanning 8.5" -by 11" black-and-white office documents. This standard is used with the -IEEE fax image--a continuous tone photographic image with gray scales, -text, and several continuous tone pictures--and AIIM test target number -2, a representative document used in office document management. - -BARONAS next outlined the four categories of EIM standardization in which -AIIM standards are being developed: transfer and retrieval, evaluation, -optical disc and document scanning applications, and design and -conversion of documents. She detailed several of the main projects of -each: 1) in the category of image transfer and retrieval, a bi-level -image transfer format, ANSI/AIIM MS53, which is a proposed standard that -describes a file header for image transfer between unlike systems when -the images are compressed using G3 and G4 compression; 2) the category of -image evaluation, which includes the AIIM-proposed TR26 tutorial on image -resolution (this technical report will treat the differences and -similarities between classical or photographic and electronic imaging); -3) design and conversion, which includes a proposed technical report -called "Forms Design Optimization for EIM" (this report considers how -general-purpose business forms can be best designed so that scanning is -optimized; reprographic characteristics such as type, rules, background, -tint, and color will likewise be treated in the technical report); 4) -disk and document scanning applications includes a project a) on planning -platters and disk management, b) on generating an application profile for -EIM when images are stored and distributed on CD-ROM, and c) on -evaluating SCSI2, and how a common command set can be generated for SCSI2 -so that document scanners are more easily integrated. (ANSI/AIIM MS53 -will also apply to compressed images.) - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -BATTIN * The implications of standards for preservation * A major -obstacle to successful cooperation * A hindrance to access in the digital -environment * Standards a double-edged sword for those concerned with the -preservation of the human record * Near-term prognosis for reliable -archival standards * Preservation concerns for electronic media * Need -for reconceptualizing our preservation principles * Standards in the real -world and the politics of reproduction * Need to redefine the concept of -archival and to begin to think in terms of life cycles * Cooperation and -the La Guardia Eight * Concerns generated by discussions on the problems -of preserving text and image * General principles to be adopted in a -world without standards * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Patricia BATTIN, president, the Commission on Preservation and Access -(CPA), addressed the implications of standards for preservation. She -listed several areas where the library profession and the analog world of -the printed book had made enormous contributions over the past hundred -years--for example, in bibliographic formats, binding standards, and, most -important, in determining what constitutes longevity or archival quality. - -Although standards have lightened the preservation burden through the -development of national and international collaborative programs, -nevertheless, a pervasive mistrust of other people's standards remains a -major obstacle to successful cooperation, BATTIN said. - -The zeal to achieve perfection, regardless of the cost, has hindered -rather than facilitated access in some instances, and in the digital -environment, where no real standards exist, has brought an ironically -just reward. - -BATTIN argued that standards are a double-edged sword for those concerned -with the preservation of the human record, that is, the provision of -access to recorded knowledge in a multitude of media as far into the -future as possible. Standards are essential to facilitate -interconnectivity and access, but, BATTIN said, as LYNCH pointed out -yesterday, if set too soon they can hinder creativity, expansion of -capability, and the broadening of access. The characteristics of -standards for digital imagery differ radically from those for analog -imagery. And the nature of digital technology implies continuing -volatility and change. To reiterate, precipitous standard-setting can -inhibit creativity, but delayed standard-setting results in chaos. - -Since in BATTIN'S opinion the near-term prognosis for reliable archival -standards, as defined by librarians in the analog world, is poor, two -alternatives remain: standing pat with the old technology, or -reconceptualizing. - -Preservation concerns for electronic media fall into two general domains. -One is the continuing assurance of access to knowledge originally -generated, stored, disseminated, and used in electronic form. This -domain contains several subdivisions, including 1) the closed, -proprietary systems discussed the previous day, bundled information such -as electronic journals and government agency records, and electronically -produced or captured raw data; and 2) the application of digital -technologies to the reformatting of materials originally published on a -deteriorating analog medium such as acid paper or videotape. - -The preservation of electronic media requires a reconceptualizing of our -preservation principles during a volatile, standardless transition which -may last far longer than any of us envision today. BATTIN urged the -necessity of shifting focus from assessing, measuring, and setting -standards for the permanence of the medium to the concept of managing -continuing access to information stored on a variety of media and -requiring a variety of ever-changing hardware and software for access--a -fundamental shift for the library profession. - -BATTIN offered a primer on how to move forward with reasonable confidence -in a world without standards. Her comments fell roughly into two sections: -1) standards in the real world and 2) the politics of reproduction. - -In regard to real-world standards, BATTIN argued the need to redefine the -concept of archive and to begin to think in terms of life cycles. In -the past, the naive assumption that paper would last forever produced a -cavalier attitude toward life cycles. The transient nature of the -electronic media has compelled people to recognize and accept upfront the -concept of life cycles in place of permanency. - -Digital standards have to be developed and set in a cooperative context -to ensure efficient exchange of information. Moreover, during this -transition period, greater flexibility concerning how concepts such as -backup copies and archival copies in the CXP are defined is necessary, -or the opportunity to move forward will be lost. - -In terms of cooperation, particularly in the university setting, BATTIN -also argued the need to avoid going off in a hundred different -directions. The CPA has catalyzed a small group of universities called -the La Guardia Eight--because La Guardia Airport is where meetings take -place--Harvard, Yale, Cornell, Princeton, Penn State, Tennessee, -Stanford, and USC, to develop a digital preservation consortium to look -at all these issues and develop de facto standards as we move along, -instead of waiting for something that is officially blessed. Continuing -to apply analog values and definitions of standards to the digital -environment, BATTIN said, will effectively lead to forfeiture of the -benefits of digital technology to research and scholarship. - -Under the second rubric, the politics of reproduction, BATTIN reiterated -an oft-made argument concerning the electronic library, namely, that it -is more difficult to transform than to create, and nowhere is that belief -expressed more dramatically than in the conversion of brittle books to -new media. Preserving information published in electronic media involves -making sure the information remains accessible and that digital -information is not lost through reproduction. In the analog world of -photocopies and microfilm, the issue of fidelity to the original becomes -paramount, as do issues of "Whose fidelity?" and "Whose original?" - -BATTIN elaborated these arguments with a few examples from a recent study -conducted by the CPA on the problems of preserving text and image. -Discussions with scholars, librarians, and curators in a variety of -disciplines dependent on text and image generated a variety of concerns, -for example: 1) Copy what is, not what the technology is capable of. -This is very important for the history of ideas. Scholars wish to know -what the author saw and worked from. And make available at the -workstation the opportunity to erase all the defects and enhance the -presentation. 2) The fidelity of reproduction--what is good enough, what -can we afford, and the difference it makes--issues of subjective versus -objective resolution. 3) The differences between primary and secondary -users. Restricting the definition of primary user to the one in whose -discipline the material has been published runs one headlong into the -reality that these printed books have had a host of other users from a -host of other disciplines, who not only were looking for very different -things, but who also shared values very different from those of the -primary user. 4) The relationship of the standard of reproduction to new -capabilities of scholarship--the browsing standard versus an archival -standard. How good must the archival standard be? Can a distinction be -drawn between potential users in setting standards for reproduction? -Archival storage, use copies, browsing copies--ought an attempt to set -standards even be made? 5) Finally, costs. How much are we prepared to -pay to capture absolute fidelity? What are the trade-offs between vastly -enhanced access, degrees of fidelity, and costs? - -These standards, BATTIN concluded, serve to complicate further the -reproduction process, and add to the long list of technical standards -that are necessary to ensure widespread access. Ways to articulate and -analyze the costs that are attached to the different levels of standards -must be found. - -Given the chaos concerning standards, which promises to linger for the -foreseeable future, BATTIN urged adoption of the following general -principles: - - * Strive to understand the changing information requirements of - scholarly disciplines as more and more technology is integrated into - the process of research and scholarly communication in order to meet - future scholarly needs, not to build for the past. Capture - deteriorating information at the highest affordable resolution, even - though the dissemination and display technologies will lag. - - * Develop cooperative mechanisms to foster agreement on protocols - for document structure and other interchange mechanisms necessary - for widespread dissemination and use before official standards are - set. - - * Accept that, in a transition period, de facto standards will have - to be developed. - - * Capture information in a way that keeps all options open and - provides for total convertibility: OCR, scanning of microfilm, - producing microfilm from scanned documents, etc. - - * Work closely with the generators of information and the builders - of networks and databases to ensure that continuing accessibility is - a primary concern from the beginning. - - * Piggyback on standards under development for the broad market, and - avoid library-specific standards; work with the vendors, in order to - take advantage of that which is being standardized for the rest of - the world. - - * Concentrate efforts on managing permanence in the digital world, - rather than perfecting the longevity of a particular medium. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Additional comments on TIFF * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -During the brief discussion period that followed BATTIN's presentation, -BARONAS explained that TIFF was not developed in collaboration with or -under the auspices of AIIM. TIFF is a company product, not a standard, -is owned by two corporations, and is always changing. BARONAS also -observed that ANSI/AIIM MS53, a bi-level image file transfer format that -allows unlike systems to exchange images, is compatible with TIFF as well -as with DEC's architecture and IBM's MODCA/IOCA. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -HOOTON * Several questions to be considered in discussing text conversion -* -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -HOOTON introduced the final topic, text conversion, by noting that it is -becoming an increasingly important part of the imaging business. Many -people now realize that it enhances their system to be able to have more -and more character data as part of their imaging system. Re the issue of -OCR versus rekeying, HOOTON posed several questions: How does one get -text into computer-readable form? Does one use automated processes? -Does one attempt to eliminate the use of operators where possible? -Standards for accuracy, he said, are extremely important: it makes a -major difference in cost and time whether one sets as a standard 98.5 -percent acceptance or 99.5 percent. He mentioned outsourcing as a -possibility for converting text. Finally, what one does with the image -to prepare it for the recognition process is also important, he said, -because such preparation changes how recognition is viewed, as well as -facilitates recognition itself. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -LESK * Roles of participants in CORE * Data flow * The scanning process * -The image interface * Results of experiments involving the use of -electronic resources and traditional paper copies * Testing the issue of -serendipity * Conclusions * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Michael LESK, executive director, Computer Science Research, Bell -Communications Research, Inc. (Bellcore), discussed the Chemical Online -Retrieval Experiment (CORE), a cooperative project involving Cornell -University, OCLC, Bellcore, and the American Chemical Society (ACS). - -LESK spoke on 1) how the scanning was performed, including the unusual -feature of page segmentation, and 2) the use made of the text and the -image in experiments. - -Working with the chemistry journals (because ACS has been saving its -typesetting tapes since the mid-1970s and thus has a significant back-run -of the most important chemistry journals in the United States), CORE is -attempting to create an automated chemical library. Approximately a -quarter of the pages by square inch are made up of images of -quasi-pictorial material; dealing with the graphic components of the -pages is extremely important. LESK described the roles of participants -in CORE: 1) ACS provides copyright permission, journals on paper, -journals on microfilm, and some of the definitions of the files; 2) at -Bellcore, LESK chiefly performs the data preparation, while Dennis Egan -performs experiments on the users of chemical abstracts, and supplies the -indexing and numerous magnetic tapes; 3) Cornell provides the site of the -experiment; 4) OCLC develops retrieval software and other user interfaces. -Various manufacturers and publishers have furnished other help. - -Concerning data flow, Bellcore receives microfilm and paper from ACS; the -microfilm is scanned by outside vendors, while the paper is scanned -inhouse on an Improvision scanner, twenty pages per minute at 300 dpi, -which provides sufficient quality for all practical uses. LESK would -prefer to have more gray level, because one of the ACS journals prints on -some colored pages, which creates a problem. - -Bellcore performs all this scanning, creates a page-image file, and also -selects from the pages the graphics, to mix with the text file (which is -discussed later in the Workshop). The user is always searching the ASCII -file, but she or he may see a display based on the ASCII or a display -based on the images. - -LESK illustrated how the program performs page analysis, and the image -interface. (The user types several words, is presented with a list-- -usually of the titles of articles contained in an issue--that derives -from the ASCII, clicks on an icon and receives an image that mirrors an -ACS page.) LESK also illustrated an alternative interface, based on text -on the ASCII, the so-called SuperBook interface from Bellcore. - -LESK next presented the results of an experiment conducted by Dennis Egan -and involving thirty-six students at Cornell, one third of them -undergraduate chemistry majors, one third senior undergraduate chemistry -majors, and one third graduate chemistry students. A third of them -received the paper journals, the traditional paper copies and chemical -abstracts on paper. A third received image displays of the pictures of -the pages, and a third received the text display with pop-up graphics. - -The students were given several questions made up by some chemistry -professors. The questions fell into five classes, ranging from very easy -to very difficult, and included questions designed to simulate browsing -as well as a traditional information retrieval-type task. - -LESK furnished the following results. In the straightforward question -search--the question being, what is the phosphorus oxygen bond distance -and hydroxy phosphate?--the students were told that they could take -fifteen minutes and, then, if they wished, give up. The students with -paper took more than fifteen minutes on average, and yet most of them -gave up. The students with either electronic format, text or image, -received good scores in reasonable time, hardly ever had to give up, and -usually found the right answer. - -In the browsing study, the students were given a list of eight topics, -told to imagine that an issue of the Journal of the American Chemical -Society had just appeared on their desks, and were also told to flip -through it and to find topics mentioned in the issue. The average scores -were about the same. (The students were told to answer yes or no about -whether or not particular topics appeared.) The errors, however, were -quite different. The students with paper rarely said that something -appeared when it had not. But they often failed to find something -actually mentioned in the issue. The computer people found numerous -things, but they also frequently said that a topic was mentioned when it -was not. (The reason, of course, was that they were performing word -searches. They were finding that words were mentioned and they were -concluding that they had accomplished their task.) - -This question also contained a trick to test the issue of serendipity. -The students were given another list of eight topics and instructed, -without taking a second look at the journal, to recall how many of this -new list of eight topics were in this particular issue. This was an -attempt to see if they performed better at remembering what they were not -looking for. They all performed about the same, paper or electronics, -about 62 percent accurate. In short, LESK said, people were not very -good when it came to serendipity, but they were no worse at it with -computers than they were with paper. - -(LESK gave a parenthetical illustration of the learning curve of students -who used SuperBook.) - -The students using the electronic systems started off worse than the ones -using print, but by the third of the three sessions in the series had -caught up to print. As one might expect, electronics provide a much -better means of finding what one wants to read; reading speeds, once the -object of the search has been found, are about the same. - -Almost none of the students could perform the hard task--the analogous -transformation. (It would require the expertise of organic chemists to -complete.) But an interesting result was that the students using the text -search performed terribly, while those using the image system did best. -That the text search system is driven by text offers the explanation. -Everything is focused on the text; to see the pictures, one must press -on an icon. Many students found the right article containing the answer -to the question, but they did not click on the icon to bring up the right -figure and see it. They did not know that they had found the right place, -and thus got it wrong. - -The short answer demonstrated by this experiment was that in the event -one does not know what to read, one needs the electronic systems; the -electronic systems hold no advantage at the moment if one knows what to -read, but neither do they impose a penalty. - -LESK concluded by commenting that, on one hand, the image system was easy -to use. On the other hand, the text display system, which represented -twenty man-years of work in programming and polishing, was not winning, -because the text was not being read, just searched. The much easier -system is highly competitive as well as remarkably effective for the -actual chemists. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -ERWAY * Most challenging aspect of working on AM * Assumptions guiding -AM's approach * Testing different types of service bureaus * AM's -requirement for 99.95 percent accuracy * Requirements for text-coding * -Additional factors influencing AM's approach to coding * Results of AM's -experience with rekeying * Other problems in dealing with service bureaus -* Quality control the most time-consuming aspect of contracting out -conversion * Long-term outlook uncertain * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -To Ricky ERWAY, associate coordinator, American Memory, Library of -Congress, the constant variety of conversion projects taking place -simultaneously represented perhaps the most challenging aspect of working -on AM. Thus, the challenge was not to find a solution for text -conversion but a tool kit of solutions to apply to LC's varied -collections that need to be converted. ERWAY limited her remarks to the -process of converting text to machine-readable form, and the variety of -LC's text collections, for example, bound volumes, microfilm, and -handwritten manuscripts. - -Two assumptions have guided AM's approach, ERWAY said: 1) A desire not -to perform the conversion inhouse. Because of the variety of formats and -types of texts, to capitalize the equipment and have the talents and -skills to operate them at LC would be extremely expensive. Further, the -natural inclination to upgrade to newer and better equipment each year -made it reasonable for AM to focus on what it did best and seek external -conversion services. Using service bureaus also allowed AM to have -several types of operations take place at the same time. 2) AM was not a -technology project, but an effort to improve access to library -collections. Hence, whether text was converted using OCR or rekeying -mattered little to AM. What mattered were cost and accuracy of results. - -AM considered different types of service bureaus and selected three to -perform several small tests in order to acquire a sense of the field. -The sample collections with which they worked included handwritten -correspondence, typewritten manuscripts from the 1940s, and -eighteenth-century printed broadsides on microfilm. On none of these -samples was OCR performed; they were all rekeyed. AM had several special -requirements for the three service bureaus it had engaged. For instance, -any errors in the original text were to be retained. Working from bound -volumes or anything that could not be sheet-fed also constituted a factor -eliminating companies that would have performed OCR. - -AM requires 99.95 percent accuracy, which, though it sounds high, often -means one or two errors per page. The initial batch of test samples -contained several handwritten materials for which AM did not require -text-coding. The results, ERWAY reported, were in all cases fairly -comparable: for the most part, all three service bureaus achieved 99.95 -percent accuracy. AM was satisfied with the work but surprised at the cost. - -As AM began converting whole collections, it retained the requirement for -99.95 percent accuracy and added requirements for text-coding. AM needed -to begin performing work more than three years ago before LC requirements -for SGML applications had been established. Since AM's goal was simply -to retain any of the intellectual content represented by the formatting -of the document (which would be lost if one performed a straight ASCII -conversion), AM used "SGML-like" codes. These codes resembled SGML tags -but were used without the benefit of document-type definitions. AM found -that many service bureaus were not yet SGML-proficient. - -Additional factors influencing the approach AM took with respect to -coding included: 1) the inability of any known microcomputer-based -user-retrieval software to take advantage of SGML coding; and 2) the -multiple inconsistencies in format of the older documents, which -confirmed AM in its desire not to attempt to force the different formats -to conform to a single document-type definition (DTD) and thus create the -need for a separate DTD for each document. - -The five text collections that AM has converted or is in the process of -converting include a collection of eighteenth-century broadsides, a -collection of pamphlets, two typescript document collections, and a -collection of 150 books. - -ERWAY next reviewed the results of AM's experience with rekeying, noting -again that because the bulk of AM's materials are historical, the quality -of the text often does not lend itself to OCR. While non-English -speakers are less likely to guess or elaborate or correct typos in the -original text, they are also less able to infer what we would; they also -are nearly incapable of converting handwritten text. Another -disadvantage of working with overseas keyers is that they are much less -likely to telephone with questions, especially on the coding, with the -result that they develop their own rules as they encounter new -situations. - -Government contracting procedures and time frames posed a major challenge -to performing the conversion. Many service bureaus are not accustomed to -retaining the image, even if they perform OCR. Thus, questions of image -format and storage media were somewhat novel to many of them. ERWAY also -remarked other problems in dealing with service bureaus, for example, -their inability to perform text conversion from the kind of microfilm -that LC uses for preservation purposes. - -But quality control, in ERWAY's experience, was the most time-consuming -aspect of contracting out conversion. AM has been attempting to perform -a 10-percent quality review, looking at either every tenth document or -every tenth page to make certain that the service bureaus are maintaining -99.95 percent accuracy. But even if they are complying with the -requirement for accuracy, finding errors produces a desire to correct -them and, in turn, to clean up the whole collection, which defeats the -purpose to some extent. Even a double entry requires a -character-by-character comparison to the original to meet the accuracy -requirement. LC is not accustomed to publish imperfect texts, which -makes attempting to deal with the industry standard an emotionally -fraught issue for AM. As was mentioned in the previous day's discussion, -going from 99.95 to 99.99 percent accuracy usually doubles costs and -means a third keying or another complete run-through of the text. - -Although AM has learned much from its experiences with various collections -and various service bureaus, ERWAY concluded pessimistically that no -breakthrough has been achieved. Incremental improvements have occurred -in some of the OCR technology, some of the processes, and some of the -standards acceptances, which, though they may lead to somewhat lower costs, -do not offer much encouragement to many people who are anxiously awaiting -the day that the entire contents of LC are available on-line. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -ZIDAR * Several answers to why one attempts to perform full-text -conversion * Per page cost of performing OCR * Typical problems -encountered during editing * Editing poor copy OCR vs. rekeying * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Judith ZIDAR, coordinator, National Agricultural Text Digitizing Program -(NATDP), National Agricultural Library (NAL), offered several answers to -the question of why one attempts to perform full-text conversion: 1) -Text in an image can be read by a human but not by a computer, so of -course it is not searchable and there is not much one can do with it. 2) -Some material simply requires word-level access. For instance, the legal -profession insists on full-text access to its material; with taxonomic or -geographic material, which entails numerous names, one virtually requires -word-level access. 3) Full text permits rapid browsing and searching, -something that cannot be achieved in an image with today's technology. -4) Text stored as ASCII and delivered in ASCII is standardized and highly -portable. 5) People just want full-text searching, even those who do not -know how to do it. NAL, for the most part, is performing OCR at an -actual cost per average-size page of approximately $7. NAL scans the -page to create the electronic image and passes it through the OCR device. - -ZIDAR next rehearsed several typical problems encountered during editing. -Praising the celerity of her student workers, ZIDAR observed that editing -requires approximately five to ten minutes per page, assuming that there -are no large tables to audit. Confusion among the three characters I, 1, -and l, constitutes perhaps the most common problem encountered. Zeroes -and O's also are frequently confused. Double M's create a particular -problem, even on clean pages. They are so wide in most fonts that they -touch, and the system simply cannot tell where one letter ends and the -other begins. Complex page formats occasionally fail to columnate -properly, which entails rescanning as though one were working with a -single column, entering the ASCII, and decolumnating for better -searching. With proportionally spaced text, OCR can have difficulty -discerning what is a space and what are merely spaces between letters, as -opposed to spaces between words, and therefore will merge text or break -up words where it should not. - -ZIDAR said that it can often take longer to edit a poor-copy OCR than to -key it from scratch. NAL has also experimented with partial editing of -text, whereby project workers go into and clean up the format, removing -stray characters but not running a spell-check. NAL corrects typos in -the title and authors' names, which provides a foothold for searching and -browsing. Even extremely poor-quality OCR (e.g., 60-percent accuracy) -can still be searched, because numerous words are correct, while the -important words are probably repeated often enough that they are likely -to be found correct somewhere. Librarians, however, cannot tolerate this -situation, though end users seem more willing to use this text for -searching, provided that NAL indicates that it is unedited. ZIDAR -concluded that rekeying of text may be the best route to take, in spite -of numerous problems with quality control and cost. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Modifying an image before performing OCR * NAL's costs per -page *AM's costs per page and experience with Federal Prison Industries * -Elements comprising NATDP's costs per page * OCR and structured markup * -Distinction between the structure of a document and its representation -when put on the screen or printed * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -HOOTON prefaced the lengthy discussion that followed with several -comments about modifying an image before one reaches the point of -performing OCR. For example, in regard to an application containing a -significant amount of redundant data, such as form-type data, numerous -companies today are working on various kinds of form renewal, prior to -going through a recognition process, by using dropout colors. Thus, -acquiring access to form design or using electronic means are worth -considering. HOOTON also noted that conversion usually makes or breaks -one's imaging system. It is extremely important, extremely costly in -terms of either capital investment or service, and determines the quality -of the remainder of one's system, because it determines the character of -the raw material used by the system. - -Concerning the four projects undertaken by NAL, two inside and two -performed by outside contractors, ZIDAR revealed that an in-house service -bureau executed the first at a cost between $8 and $10 per page for -everything, including building of the database. The project undertaken -by the Consultative Group on International Agricultural Research (CGIAR) -cost approximately $10 per page for the conversion, plus some expenses -for the software and building of the database. The Acid Rain Project--a -two-disk set produced by the University of Vermont, consisting of -Canadian publications on acid rain--cost $6.70 per page for everything, -including keying of the text, which was double keyed, scanning of the -images, and building of the database. The in-house project offered -considerable ease of convenience and greater control of the process. On -the other hand, the service bureaus know their job and perform it -expeditiously, because they have more people. - -As a useful comparison, ERWAY revealed AM's costs as follows: $0.75 -cents to $0.85 cents per thousand characters, with an average page -containing 2,700 characters. Requirements for coding and imaging -increase the costs. Thus, conversion of the text, including the coding, -costs approximately $3 per page. (This figure does not include the -imaging and database-building included in the NAL costs.) AM also -enjoyed a happy experience with Federal Prison Industries, which -precluded the necessity of going through the request-for-proposal process -to award a contract, because it is another government agency. The -prisoners performed AM's rekeying just as well as other service bureaus -and proved handy as well. AM shipped them the books, which they would -photocopy on a book-edge scanner. They would perform the markup on -photocopies, return the books as soon as they were done with them, -perform the keying, and return the material to AM on WORM disks. - -ZIDAR detailed the elements that constitute the previously noted cost of -approximately $7 per page. Most significant is the editing, correction -of errors, and spell-checkings, which though they may sound easy to -perform require, in fact, a great deal of time. Reformatting text also -takes a while, but a significant amount of NAL's expenses are for equipment, -which was extremely expensive when purchased because it was one of the few -systems on the market. The costs of equipment are being amortized over -five years but are still quite high, nearly $2,000 per month. - -HOCKEY raised a general question concerning OCR and the amount of editing -required (substantial in her experience) to generate the kind of -structured markup necessary for manipulating the text on the computer or -loading it into any retrieval system. She wondered if the speakers could -extend the previous question about the cost-benefit of adding or exerting -structured markup. ERWAY noted that several OCR systems retain italics, -bolding, and other spatial formatting. While the material may not be in -the format desired, these systems possess the ability to remove the -original materials quickly from the hands of the people performing the -conversion, as well as to retain that information so that users can work -with it. HOCKEY rejoined that the current thinking on markup is that one -should not say that something is italic or bold so much as why it is that -way. To be sure, one needs to know that something was italicized, but -how can one get from one to the other? One can map from the structure to -the typographic representation. - -FLEISCHHAUER suggested that, given the 100 million items the Library -holds, it may not be possible for LC to do more than report that a thing -was in italics as opposed to why it was italics, although that may be -desirable in some contexts. Promising to talk a bit during the afternoon -session about several experiments OCLC performed on automatic recognition -of document elements, and which they hoped to extend, WEIBEL said that in -fact one can recognize the major elements of a document with a fairly -high degree of reliability, at least as good as OCR. STEVENS drew a -useful distinction between standard, generalized markup (i.e., defining -for a document-type definition the structure of the document), and what -he termed a style sheet, which had to do with italics, bolding, and other -forms of emphasis. Thus, two different components are at work, one being -the structure of the document itself (its logic), and the other being its -representation when it is put on the screen or printed. - - ****** - -SESSION V. APPROACHES TO PREPARING ELECTRONIC TEXTS - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -HOCKEY * Text in ASCII and the representation of electronic text versus -an image * The need to look at ways of using markup to assist retrieval * -The need for an encoding format that will be reusable and multifunctional -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Susan HOCKEY, director, Center for Electronic Texts in the Humanities -(CETH), Rutgers and Princeton Universities, announced that one talk -(WEIBEL's) was moved into this session from the morning and that David -Packard was unable to attend. The session would attempt to focus more on -what one can do with a text in ASCII and the representation of electronic -text rather than just an image, what one can do with a computer that -cannot be done with a book or an image. It would be argued that one can -do much more than just read a text, and from that starting point one can -use markup and methods of preparing the text to take full advantage of -the capability of the computer. That would lead to a discussion of what -the European Community calls REUSABILITY, what may better be termed -DURABILITY, that is, how to prepare or make a text that will last a long -time and that can be used for as many applications as possible, which -would lead to issues of improving intellectual access. - -HOCKEY urged the need to look at ways of using markup to facilitate retrieval, -not just for referencing or to help locate an item that is retrieved, but also to put markup tags in -a text to help retrieve the thing sought either with linguistic tagging or -interpretation. HOCKEY also argued that little advancement had occurred in -the software tools currently available for retrieving and searching text. -She pressed the desideratum of going beyond Boolean searches and performing -more sophisticated searching, which the insertion of more markup in the text -would facilitate. Thinking about electronic texts as opposed to images means -considering material that will never appear in print form, or print will not -be its primary form, that is, material which only appears in electronic form. -HOCKEY alluded to the history and the need for markup and tagging and -electronic text, which was developed through the use of computers in the -humanities; as MICHELSON had observed, Father Busa had started in 1949 -to prepare the first-ever text on the computer. - -HOCKEY remarked several large projects, particularly in Europe, for the -compilation of dictionaries, language studies, and language analysis, in -which people have built up archives of text and have begun to recognize -the need for an encoding format that will be reusable and multifunctional, -that can be used not just to print the text, which may be assumed to be a -byproduct of what one wants to do, but to structure it inside the computer -so that it can be searched, built into a Hypertext system, etc. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -WEIBEL * OCLC's approach to preparing electronic text: retroconversion, -keying of texts, more automated ways of developing data * Project ADAPT -and the CORE Project * Intelligent character recognition does not exist * -Advantages of SGML * Data should be free of procedural markup; -descriptive markup strongly advocated * OCLC's interface illustrated * -Storage requirements and costs for putting a lot of information on line * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Stuart WEIBEL, senior research scientist, Online Computer Library Center, -Inc. (OCLC), described OCLC's approach to preparing electronic text. He -argued that the electronic world into which we are moving must -accommodate not only the future but the past as well, and to some degree -even the present. Thus, starting out at one end with retroconversion and -keying of texts, one would like to move toward much more automated ways -of developing data. - -For example, Project ADAPT had to do with automatically converting -document images into a structured document database with OCR text as -indexing and also a little bit of automatic formatting and tagging of -that text. The CORE project hosted by Cornell University, Bellcore, -OCLC, the American Chemical Society, and Chemical Abstracts, constitutes -WEIBEL's principal concern at the moment. This project is an example of -converting text for which one already has a machine-readable version into -a format more suitable for electronic delivery and database searching. -(Since Michael LESK had previously described CORE, WEIBEL would say -little concerning it.) Borrowing a chemical phrase, de novo synthesis, -WEIBEL cited the Online Journal of Current Clinical Trials as an example -of de novo electronic publishing, that is, a form in which the primary -form of the information is electronic. - -Project ADAPT, then, which OCLC completed a couple of years ago and in -fact is about to resume, is a model in which one takes page images either -in paper or microfilm and converts them automatically to a searchable -electronic database, either on-line or local. The operating assumption -is that accepting some blemishes in the data, especially for -retroconversion of materials, will make it possible to accomplish more. -Not enough money is available to support perfect conversion. - -WEIBEL related several steps taken to perform image preprocessing -(processing on the image before performing optical character -recognition), as well as image postprocessing. He denied the existence -of intelligent character recognition and asserted that what is wanted is -page recognition, which is a long way off. OCLC has experimented with -merging of multiple optical character recognition systems that will -reduce errors from an unacceptable rate of 5 characters out of every -l,000 to an unacceptable rate of 2 characters out of every l,000, but it -is not good enough. It will never be perfect. - -Concerning the CORE Project, WEIBEL observed that Bellcore is taking the -topography files, extracting the page images, and converting those -topography files to SGML markup. LESK hands that data off to OCLC, which -builds that data into a Newton database, the same system that underlies -the on-line system in virtually all of the reference products at OCLC. -The long-term goal is to make the systems interoperable so that not just -Bellcore's system and OCLC's system can access this data, but other -systems can as well, and the key to that is the Z39.50 common command -language and the full-text extension. Z39.50 is fine for MARC records, -but is not enough to do it for full text (that is, make full texts -interoperable). - -WEIBEL next outlined the critical role of SGML for a variety of purposes, -for example, as noted by HOCKEY, in the world of extremely large -databases, using highly structured data to perform field searches. -WEIBEL argued that by building the structure of the data in (i.e., the -structure of the data originally on a printed page), it becomes easy to -look at a journal article even if one cannot read the characters and know -where the title or author is, or what the sections of that document would be. -OCLC wants to make that structure explicit in the database, because it will -be important for retrieval purposes. - -The second big advantage of SGML is that it gives one the ability to -build structure into the database that can be used for display purposes -without contaminating the data with instructions about how to format -things. The distinction lies between procedural markup, which tells one -where to put dots on the page, and descriptive markup, which describes -the elements of a document. - -WEIBEL believes that there should be no procedural markup in the data at -all, that the data should be completely unsullied by information about -italics or boldness. That should be left up to the display device, -whether that display device is a page printer or a screen display device. -By keeping one's database free of that kind of contamination, one can -make decisions down the road, for example, reorganize the data in ways -that are not cramped by built-in notions of what should be italic and -what should be bold. WEIBEL strongly advocated descriptive markup. As -an example, he illustrated the index structure in the CORE data. With -subsequent illustrated examples of markup, WEIBEL acknowledged the common -complaint that SGML is hard to read in its native form, although markup -decreases considerably once one gets into the body. Without the markup, -however, one would not have the structure in the data. One can pass -markup through a LaTeX processor and convert it relatively easily to a -printed version of the document. - -WEIBEL next illustrated an extremely cluttered screen dump of OCLC's -system, in order to show as much as possible the inherent capability on -the screen. (He noted parenthetically that he had become a supporter of -X-Windows as a result of the progress of the CORE Project.) WEIBEL also -illustrated the two major parts of the interface: l) a control box that -allows one to generate lists of items, which resembles a small table of -contents based on key words one wishes to search, and 2) a document -viewer, which is a separate process in and of itself. He demonstrated -how to follow links through the electronic database simply by selecting -the appropriate button and bringing them up. He also noted problems that -remain to be accommodated in the interface (e.g., as pointed out by LESK, -what happens when users do not click on the icon for the figure). - -Given the constraints of time, WEIBEL omitted a large number of ancillary -items in order to say a few words concerning storage requirements and -what will be required to put a lot of things on line. Since it is -extremely expensive to reconvert all of this data, especially if it is -just in paper form (and even if it is in electronic form in typesetting -tapes), he advocated building journals electronically from the start. In -that case, if one only has text graphics and indexing (which is all that -one needs with de novo electronic publishing, because there is no need to -go back and look at bit-maps of pages), one can get 10,000 journals of -full text, or almost 6 million pages per year. These pages can be put in -approximately 135 gigabytes of storage, which is not all that much, -WEIBEL said. For twenty years, something less than three terabytes would -be required. WEIBEL calculated the costs of storing this information as -follows: If a gigabyte costs approximately $1,000, then a terabyte costs -approximately $1 million to buy in terms of hardware. One also needs a -building to put it in and a staff like OCLC to handle that information. -So, to support a terabyte, multiply by five, which gives $5 million per -year for a supported terabyte of data. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Tapes saved by ACS are the typography files originally -supporting publication of the journal * Cost of building tagged text into -the database * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -During the question-and-answer period that followed WEIBEL's -presentation, these clarifications emerged. The tapes saved by the -American Chemical Society are the typography files that originally -supported the publication of the journal. Although they are not tagged -in SGML, they are tagged in very fine detail. Every single sentence is -marked, all the registry numbers, all the publications issues, dates, and -volumes. No cost figures on tagging material on a per-megabyte basis -were available. Because ACS's typesetting system runs from tagged text, -there is no extra cost per article. It was unknown what it costs ACS to -keyboard the tagged text rather than just keyboard the text in the -cheapest process. In other words, since one intends to publish things -and will need to build tagged text into a typography system in any case, -if one does that in such a way that it can drive not only typography but -an electronic system (which is what ACS intends to do--move to SGML -publishing), the marginal cost is zero. The marginal cost represents the -cost of building tagged text into the database, which is small. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -SPERBERG-McQUEEN * Distinction between texts and computers * Implications -of recognizing that all representation is encoding * Dealing with -complicated representations of text entails the need for a grammar of -documents * Variety of forms of formal grammars * Text as a bit-mapped -image does not represent a serious attempt to represent text in -electronic form * SGML, the TEI, document-type declarations, and the -reusability and longevity of data * TEI conformance explicitly allows -extension or modification of the TEI tag set * Administrative background -of the TEI * Several design goals for the TEI tag set * An absolutely -fixed requirement of the TEI Guidelines * Challenges the TEI has -attempted to face * Good texts not beyond economic feasibility * The -issue of reproducibility or processability * The issue of mages as -simulacra for the text redux * One's model of text determines what one's -software can do with a text and has economic consequences * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Prior to speaking about SGML and markup, Michael SPERBERG-McQUEEN, editor, -Text Encoding Initiative (TEI), University of Illinois-Chicago, first drew -a distinction between texts and computers: Texts are abstract cultural -and linguistic objects while computers are complicated physical devices, -he said. Abstract objects cannot be placed inside physical devices; with -computers one can only represent text and act upon those representations. - -The recognition that all representation is encoding, SPERBERG-McQUEEN -argued, leads to the recognition of two things: 1) The topic description -for this session is slightly misleading, because there can be no discussion -of pros and cons of text-coding unless what one means is pros and cons of -working with text with computers. 2) No text can be represented in a -computer without some sort of encoding; images are one way of encoding text, -ASCII is another, SGML yet another. There is no encoding without some -information loss, that is, there is no perfect reproduction of a text that -allows one to do away with the original. Thus, the question becomes, -What is the most useful representation of text for a serious work? -This depends on what kind of serious work one is talking about. - -The projects demonstrated the previous day all involved highly complex -information and fairly complex manipulation of the textual material. -In order to use that complicated information, one has to calculate it -slowly or manually and store the result. It needs to be stored, therefore, -as part of one's representation of the text. Thus, one needs to store the -structure in the text. To deal with complicated representations of text, -one needs somehow to control the complexity of the representation of a text; -that means one needs a way of finding out whether a document and an -electronic representation of a document is legal or not; and that -means one needs a grammar of documents. - -SPERBERG-McQUEEN discussed the variety of forms of formal grammars, -implicit and explicit, as applied to text, and their capabilities. He -argued that these grammars correspond to different models of text that -different developers have. For example, one implicit model of the text -is that there is no internal structure, but just one thing after another, -a few characters and then perhaps a start-title command, and then a few -more characters and an end-title command. SPERBERG-McQUEEN also -distinguished several kinds of text that have a sort of hierarchical -structure that is not very well defined, which, typically, corresponds -to grammars that are not very well defined, as well as hierarchies that -are very well defined (e.g., the Thesaurus Linguae Graecae) and extremely -complicated things such as SGML, which handle strictly hierarchical data -very nicely. - -SPERBERG-McQUEEN conceded that one other model not illustrated on his two -displays was the model of text as a bit-mapped image, an image of a page, -and confessed to having been converted to a limited extent by the -Workshop to the view that electronic images constitute a promising, -probably superior alternative to microfilming. But he was not convinced -that electronic images represent a serious attempt to represent text in -electronic form. Many of their problems stem from the fact that they are -not direct attempts to represent the text but attempts to represent the -page, thus making them representations of representations. - -In this situation of increasingly complicated textual information and the -need to control that complexity in a useful way (which begs the question -of the need for good textual grammars), one has the introduction of SGML. -With SGML, one can develop specific document-type declarations -for specific text types or, as with the TEI, attempts to generate -general document-type declarations that can handle all sorts of text. -The TEI is an attempt to develop formats for text representation that -will ensure the kind of reusability and longevity of data discussed earlier. -It offers a way to stay alive in the state of permanent technological -revolution. - -It has been a continuing challenge in the TEI to create document grammars -that do some work in controlling the complexity of the textual object but -also allowing one to represent the real text that one will find. -Fundamental to the notion of the TEI is that TEI conformance allows one -the ability to extend or modify the TEI tag set so that it fits the text -that one is attempting to represent. - -SPERBERG-McQUEEN next outlined the administrative background of the TEI. -The TEI is an international project to develop and disseminate guidelines -for the encoding and interchange of machine-readable text. It is -sponsored by the Association for Computers in the Humanities, the -Association for Computational Linguistics, and the Association for -Literary and Linguistic Computing. Representatives of numerous other -professional societies sit on its advisory board. The TEI has a number -of affiliated projects that have provided assistance by testing drafts of -the guidelines. - -Among the design goals for the TEI tag set, the scheme first of all must -meet the needs of research, because the TEI came out of the research -community, which did not feel adequately served by existing tag sets. -The tag set must be extensive as well as compatible with existing and -emerging standards. In 1990, version 1.0 of the Guidelines was released -(SPERBERG-McQUEEN illustrated their contents). - -SPERBERG-McQUEEN noted that one problem besetting electronic text has -been the lack of adequate internal or external documentation for many -existing electronic texts. The TEI guidelines as currently formulated -contain few fixed requirements, but one of them is this: There must -always be a document header, an in-file SGML tag that provides -1) a bibliographic description of the electronic object one is talking -about (that is, who included it, when, what for, and under which title); -and 2) the copy text from which it was derived, if any. If there was -no copy text or if the copy text is unknown, then one states as much. -Version 2.0 of the Guidelines was scheduled to be completed in fall 1992 -and a revised third version is to be presented to the TEI advisory board -for its endorsement this coming winter. The TEI itself exists to provide -a markup language, not a marked-up text. - -Among the challenges the TEI has attempted to face is the need for a -markup language that will work for existing projects, that is, handle the -level of markup that people are using now to tag only chapter, section, -and paragraph divisions and not much else. At the same time, such a -language also will be able to scale up gracefully to handle the highly -detailed markup which many people foresee as the future destination of -much electronic text, and which is not the future destination but the -present home of numerous electronic texts in specialized areas. - -SPERBERG-McQUEEN dismissed the lowest-common-denominator approach as -unable to support the kind of applications that draw people who have -never been in the public library regularly before, and make them come -back. He advocated more interesting text and more intelligent text. -Asserting that it is not beyond economic feasibility to have good texts, -SPERBERG-McQUEEN noted that the TEI Guidelines listing 200-odd tags -contains tags that one is expected to enter every time the relevant -textual feature occurs. It contains all the tags that people need now, -and it is not expected that everyone will tag things in the same way. - -The question of how people will tag the text is in large part a function -of their reaction to what SPERBERG-McQUEEN termed the issue of -reproducibility. What one needs to be able to reproduce are the things -one wants to work with. Perhaps a more useful concept than that of -reproducibility or recoverability is that of processability, that is, -what can one get from an electronic text without reading it again -in the original. He illustrated this contention with a page from -Jan Comenius's bilingual Introduction to Latin. - -SPERBERG-McQUEEN returned at length to the issue of images as simulacra -for the text, in order to reiterate his belief that in the long run more -than images of pages of particular editions of the text are needed, -because just as second-generation photocopies and second-generation -microfilm degenerate, so second-generation representations tend to -degenerate, and one tends to overstress some relatively trivial aspects -of the text such as its layout on the page, which is not always -significant, despite what the text critics might say, and slight other -pieces of information such as the very important lexical ties between the -English and Latin versions of Comenius's bilingual text, for example. -Moreover, in many crucial respects it is easy to fool oneself concerning -what a scanned image of the text will accomplish. For example, in order -to study the transmission of texts, information concerning the text -carrier is necessary, which scanned images simply do not always handle. -Further, even the high-quality materials being produced at Cornell use -much of the information that one would need if studying those books as -physical objects. It is a choice that has been made. It is an arguably -justifiable choice, but one does not know what color those pen strokes in -the margin are or whether there was a stain on the page, because it has -been filtered out. One does not know whether there were rips in the page -because they do not show up, and on a couple of the marginal marks one -loses half of the mark because the pen is very light and the scanner -failed to pick it up, and so what is clearly a checkmark in the margin of -the original becomes a little scoop in the margin of the facsimile. -Standard problems for facsimile editions, not new to electronics, but -also true of light-lens photography, and are remarked here because it is -important that we not fool ourselves that even if we produce a very nice -image of this page with good contrast, we are not replacing the -manuscript any more than microfilm has replaced the manuscript. - -The TEI comes from the research community, where its first allegiance -lies, but it is not just an academic exercise. It has relevance far -beyond those who spend all of their time studying text, because one's -model of text determines what one's software can do with a text. Good -models lead to good software. Bad models lead to bad software. That has -economic consequences, and it is these economic consequences that have -led the European Community to help support the TEI, and that will lead, -SPERBERG-McQUEEN hoped, some software vendors to realize that if they -provide software with a better model of the text they can make a killing. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Implications of different DTDs and tag sets * ODA versus SGML * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -During the discussion that followed, several additional points were made. -Neither AAP (i.e., Association of American Publishers) nor CALS (i.e., -Computer-aided Acquisition and Logistics Support) has a document-type -definition for ancient Greek drama, although the TEI will be able to -handle that. Given this state of affairs and assuming that the -technical-journal producers and the commercial vendors decide to use the -other two types, then an institution like the Library of Congress, which -might receive all of their publications, would have to be able to handle -three different types of document definitions and tag sets and be able to -distinguish among them. - -Office Document Architecture (ODA) has some advantages that flow from its -tight focus on office documents and clear directions for implementation. -Much of the ODA standard is easier to read and clearer at first reading -than the SGML standard, which is extremely general. What that means is -that if one wants to use graphics in TIFF and ODA, one is stuck, because -ODA defines graphics formats while TIFF does not, whereas SGML says the -world is not waiting for this work group to create another graphics format. -What is needed is an ability to use whatever graphics format one wants. - -The TEI provides a socket that allows one to connect the SGML document to -the graphics. The notation that the graphics are in is clearly a choice -that one needs to make based on her or his environment, and that is one -advantage. SGML is less megalomaniacal in attempting to define formats -for all kinds of information, though more megalomaniacal in attempting to -cover all sorts of documents. The other advantage is that the model of -text represented by SGML is simply an order of magnitude richer and more -flexible than the model of text offered by ODA. Both offer hierarchical -structures, but SGML recognizes that the hierarchical model of the text -that one is looking at may not have been in the minds of the designers, -whereas ODA does not. - -ODA is not really aiming for the kind of document that the TEI wants to -encompass. The TEI can handle the kind of material ODA has, as well as a -significantly broader range of material. ODA seems to be very much -focused on office documents, which is what it started out being called-- -office document architecture. - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -CALALUCA * Text-encoding from a publisher's perspective * -Responsibilities of a publisher * Reproduction of Migne's Latin series -whole and complete with SGML tags based on perceived need and expected -use * Particular decisions arising from the general decision to produce -and publish PLD * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -The final speaker in this session, Eric CALALUCA, vice president, -Chadwyck-Healey, Inc., spoke from the perspective of a publisher re -text-encoding, rather than as one qualified to discuss methods of -encoding data, and observed that the presenters sitting in the room, -whether they had chosen to or not, were acting as publishers: making -choices, gathering data, gathering information, and making assessments. -CALALUCA offered the hard-won conviction that in publishing very large -text files (such as PLD), one cannot avoid making personal judgments of -appropriateness and structure. - -In CALALUCA's view, encoding decisions stem from prior judgments. Two -notions have become axioms for him in the consideration of future sources -for electronic publication: 1) electronic text publishing is as personal -as any other kind of publishing, and questions of if and how to encode -the data are simply a consequence of that prior decision; 2) all -personal decisions are open to criticism, which is unavoidable. - -CALALUCA rehearsed his role as a publisher or, better, as an intermediary -between what is viewed as a sound idea and the people who would make use -of it. Finding the specialist to advise in this process is the core of -that function. The publisher must monitor and hug the fine line between -giving users what they want and suggesting what they might need. One -responsibility of a publisher is to represent the desires of scholars and -research librarians as opposed to bullheadedly forcing them into areas -they would not choose to enter. - -CALALUCA likened the questions being raised today about data structure -and standards to the decisions faced by the Abbe Migne himself during -production of the Patrologia series in the mid-nineteenth century. -Chadwyck-Healey's decision to reproduce Migne's Latin series whole and -complete with SGML tags was also based upon a perceived need and an -expected use. In the same way that Migne's work came to be far more than -a simple handbook for clerics, PLD is already far more than a database -for theologians. It is a bedrock source for the study of Western -civilization, CALALUCA asserted. - -In regard to the decision to produce and publish PLD, the editorial board -offered direct judgments on the question of appropriateness of these -texts for conversion, their encoding and their distribution, and -concluded that the best possible project was one that avoided overt -intrusions or exclusions in so important a resource. Thus, the general -decision to transmit the original collection as clearly as possible with -the widest possible avenues for use led to other decisions: 1) To encode -the data or not, SGML or not, TEI or not. Again, the expected user -community asserted the need for normative tagging structures of important -humanities texts, and the TEI seemed the most appropriate structure for -that purpose. Research librarians, who are trained to view the larger -impact of electronic text sources on 80 or 90 or 100 doctoral -disciplines, loudly approved the decision to include tagging. They see -what is coming better than the specialist who is completely focused on -one edition of Ambrose's De Anima, and they also understand that the -potential uses exceed present expectations. 2) What will be tagged and -what will not. Once again, the board realized that one must tag the -obvious. But in no way should one attempt to identify through encoding -schemes every single discrete area of a text that might someday be -searched. That was another decision. Searching by a column number, an -author, a word, a volume, permitting combination searches, and tagging -notations seemed logical choices as core elements. 3) How does one make -the data available? Tieing it to a CD-ROM edition creates limitations, -but a magnetic tape file that is very large, is accompanied by the -encoding specifications, and that allows one to make local modifications -also allows one to incorporate any changes one may desire within the -bounds of private research, though exporting tag files from a CD-ROM -could serve just as well. Since no one on the board could possibly -anticipate each and every way in which a scholar might choose to mine -this data bank, it was decided to satisfy the basics and make some -provisions for what might come. 4) Not to encode the database would rob -it of the interchangeability and portability these important texts should -accommodate. For CALALUCA, the extensive options presented by full-text -searching require care in text selection and strongly support encoding of -data to facilitate the widest possible search strategies. Better -software can always be created, but summoning the resources, the people, -and the energy to reconvert the text is another matter. - -PLD is being encoded, captured, and distributed, because to -Chadwyck-Healey and the board it offers the widest possible array of -future research applications that can be seen today. CALALUCA concluded -by urging the encoding of all important text sources in whatever way -seems most appropriate and durable at the time, without blanching at the -thought that one's work may require emendation in the future. (Thus, -Chadwyck-Healey produced a very large humanities text database before the -final release of the TEI Guidelines.) - - ****** - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -DISCUSSION * Creating texts with markup advocated * Trends in encoding * -The TEI and the issue of interchangeability of standards * A -misconception concerning the TEI * Implications for an institution like -LC in the event that a multiplicity of DTDs develops * Producing images -as a first step towards possible conversion to full text through -character recognition * The AAP tag sets as a common starting point and -the need for caution * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -HOCKEY prefaced the discussion that followed with several comments in -favor of creating texts with markup and on trends in encoding. In the -future, when many more texts are available for on-line searching, real -problems in finding what is wanted will develop, if one is faced with -millions of words of data. It therefore becomes important to consider -putting markup in texts to help searchers home in on the actual things -they wish to retrieve. Various approaches to refining retrieval methods -toward this end include building on a computer version of a dictionary -and letting the computer look up words in it to obtain more information -about the semantic structure or semantic field of a word, its grammatical -structure, and syntactic structure. - -HOCKEY commented on the present keen interest in the encoding world -in creating: 1) machine-readable versions of dictionaries that can be -initially tagged in SGML, which gives a structure to the dictionary entry; -these entries can then be converted into a more rigid or otherwise -different database structure inside the computer, which can be treated as -a dynamic tool for searching mechanisms; 2) large bodies of text to study -the language. In order to incorporate more sophisticated mechanisms, -more about how words behave needs to be known, which can be learned in -part from information in dictionaries. However, the last ten years have -seen much interest in studying the structure of printed dictionaries -converted into computer-readable form. The information one derives about -many words from those is only partial, one or two definitions of the -common or the usual meaning of a word, and then numerous definitions of -unusual usages. If the computer is using a dictionary to help retrieve -words in a text, it needs much more information about the common usages, -because those are the ones that occur over and over again. Hence the -current interest in developing large bodies of text in computer-readable -form in order to study the language. Several projects are engaged in -compiling, for example, 100 million words. HOCKEY described one with -which she was associated briefly at Oxford University involving -compilation of 100 million words of British English: about 10 percent of -that will contain detailed linguistic tagging encoded in SGML; it will -have word class taggings, with words identified as nouns, verbs, -adjectives, or other parts of speech. This tagging can then be used by -programs which will begin to learn a bit more about the structure of the -language, and then, can go to tag more text. - -HOCKEY said that the more that is tagged accurately, the more one can -refine the tagging process and thus the bigger body of text one can build -up with linguistic tagging incorporated into it. Hence, the more tagging -or annotation there is in the text, the more one may begin to learn about -language and the more it will help accomplish more intelligent OCR. She -recommended the development of software tools that will help one begin to -understand more about a text, which can then be applied to scanning -images of that text in that format and to using more intelligence to help -one interpret or understand the text. - -HOCKEY posited the need to think about common methods of text-encoding -for a long time to come, because building these large bodies of text is -extremely expensive and will only be done once. - -In the more general discussion on approaches to encoding that followed, -these points were made: - -BESSER identified the underlying problem with standards that all have to -struggle with in adopting a standard, namely, the tension between a very -highly defined standard that is very interchangeable but does not work -for everyone because something is lacking, and a standard that is less -defined, more open, more adaptable, but less interchangeable. Contending -that the way in which people use SGML is not sufficiently defined, BESSER -wondered 1) if people resist the TEI because they think it is too defined -in certain things they do not fit into, and 2) how progress with -interchangeability can be made without frightening people away. - -SPERBERG-McQUEEN replied that the published drafts of the TEI had met -with surprisingly little objection on the grounds that they do not allow -one to handle X or Y or Z. Particular concerns of the affiliated -projects have led, in practice, to discussions of how extensions are to -be made; the primary concern of any project has to be how it can be -represented locally, thus making interchange secondary. The TEI has -received much criticism based on the notion that everything in it is -required or even recommended, which, as it happens, is a misconception -from the beginning, because none of it is required and very little is -actually actively recommended for all cases, except that one document -one's source. - -SPERBERG-McQUEEN agreed with BESSER about this trade-off: all the -projects in a set of twenty TEI-conformant projects will not necessarily -tag the material in the same way. One result of the TEI will be that the -easiest problems will be solved--those dealing with the external form of -the information; but the problem that is hardest in interchange is that -one is not encoding what another wants, and vice versa. Thus, after -the adoption of a common notation, the differences in the underlying -conceptions of what is interesting about texts become more visible. -The success of a standard like the TEI will lie in the ability of -the recipient of interchanged texts to use some of what it contains -and to add the information that was not encoded that one wants, in a -layered way, so that texts can be gradually enriched and one does not -have to put in everything all at once. Hence, having a well-behaved -markup scheme is important. - -STEVENS followed up on the paradoxical analogy that BESSER alluded to in -the example of the MARC records, namely, the formats that are the same -except that they are different. STEVENS drew a parallel between -document-type definitions and MARC records for books and serials and maps, -where one has a tagging structure and there is a text-interchange. -STEVENS opined that the producers of the information will set the terms -for the standard (i.e., develop document-type definitions for the users -of their products), creating a situation that will be problematical for -an institution like the Library of Congress, which will have to deal with -the DTDs in the event that a multiplicity of them develops. Thus, -numerous people are seeking a standard but cannot find the tag set that -will be acceptable to them and their clients. SPERBERG-McQUEEN agreed -with this view, and said that the situation was in a way worse: attempting -to unify arbitrary DTDs resembled attempting to unify a MARC record with a -bibliographic record done according to the Prussian instructions. -According to STEVENS, this situation occurred very early in the process. - -WATERS recalled from early discussions on Project Open Book the concern -of many people that merely by producing images, POB was not really -enhancing intellectual access to the material. Nevertheless, not wishing -to overemphasize the opposition between imaging and full text, WATERS -stated that POB views getting the images as a first step toward possibly -converting to full text through character recognition, if the technology -is appropriate. WATERS also emphasized that encoding is involved even -with a set of images. - -SPERBERG-McQUEEN agreed with WATERS that one can create an SGML document -consisting wholly of images. At first sight, organizing graphic images -with an SGML document may not seem to offer great advantages, but the -advantages of the scheme WATERS described would be precisely that -ability to move into something that is more of a multimedia document: -a combination of transcribed text and page images. WEIBEL concurred in -this judgment, offering evidence from Project ADAPT, where a page is -divided into text elements and graphic elements, and in fact the text -elements are organized by columns and lines. These lines may be used as -the basis for distributing documents in a network environment. As one -develops software intelligent enough to recognize what those elements -are, it makes sense to apply SGML to an image initially, that may, in -fact, ultimately become more and more text, either through OCR or edited -OCR or even just through keying. For WATERS, the labor of composing the -document and saying this set of documents or this set of images belongs -to this document constitutes a significant investment. - -WEIBEL also made the point that the AAP tag sets, while not excessively -prescriptive, offer a common starting point; they do not define the -structure of the documents, though. They have some recommendations about -DTDs one could use as examples, but they do just suggest tag sets. For -example, the CORE project attempts to use the AAP markup as much as -possible, but there are clearly areas where structure must be added. -That in no way contradicts the use of AAP tag sets. - -SPERBERG-McQUEEN noted that the TEI prepared a long working paper early -on about the AAP tag set and what it lacked that the TEI thought it -needed, and a fairly long critique of the naming conventions, which has -led to a very different style of naming in the TEI. He stressed the -importance of the opposition between prescriptive markup, the kind that a -publisher or anybody can do when producing documents de novo, and -descriptive markup, in which one has to take what the text carrier -provides. In these particular tag sets it is easy to overemphasize this -opposition, because the AAP tag set is extremely flexible. Even if one -just used the DTDs, they allow almost anything to appear almost anywhere. - - ****** - -SESSION VI. COPYRIGHT ISSUES - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -PETERS * Several cautions concerning copyright in an electronic -environment * Review of copyright law in the United States * The notion -of the public good and the desirability of incentives to promote it * -What copyright protects * Works not protected by copyright * The rights -of copyright holders * Publishers' concerns in today's electronic -environment * Compulsory licenses * The price of copyright in a digital -medium and the need for cooperation * Additional clarifications * Rough -justice oftentimes the outcome in numerous copyright matters * Copyright -in an electronic society * Copyright law always only sets up the -boundaries; anything can be changed by contract * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Marybeth PETERS, policy planning adviser to the Register of Copyrights, -Library of Congress, made several general comments and then opened the -floor to discussion of subjects of interest to the audience. - -Having attended several sessions in an effort to gain a sense of what -people did and where copyright would affect their lives, PETERS expressed -the following cautions: - - * If one takes and converts materials and puts them in new forms, - then, from a copyright point of view, one is creating something and - will receive some rights. - - * However, if what one is converting already exists, a question - immediately arises about the status of the materials in question. - - * Putting something in the public domain in the United States offers - some freedom from anxiety, but distributing it throughout the world - on a network is another matter, even if one has put it in the public - domain in the United States. Re foreign laws, very frequently a - work can be in the public domain in the United States but protected - in other countries. Thus, one must consider all of the places a - work may reach, lest one unwittingly become liable to being faced - with a suit for copyright infringement, or at least a letter - demanding discussion of what one is doing. - -PETERS reviewed copyright law in the United States. The U.S. -Constitution effectively states that Congress has the power to enact -copyright laws for two purposes: 1) to encourage the creation and -dissemination of intellectual works for the good of society as a whole; -and, significantly, 2) to give creators and those who package and -disseminate materials the economic rewards that are due them. - -Congress strives to strike a balance, which at times can become an -emotional issue. The United States has never accepted the notion of the -natural right of an author so much as it has accepted the notion of the -public good and the desirability of incentives to promote it. This state -of affairs, however, has created strains on the international level and -is the reason for several of the differences in the laws that we have. -Today the United States protects almost every kind of work that can be -called an expression of an author. The standard for gaining copyright -protection is simply originality. This is a low standard and means that -a work is not copied from something else, as well as shows a certain -minimal amount of authorship. One can also acquire copyright protection -for making a new version of preexisting material, provided it manifests -some spark of creativity. - -However, copyright does not protect ideas, methods, systems--only the way -that one expresses those things. Nor does copyright protect anything -that is mechanical, anything that does not involve choice, or criteria -concerning whether or not one should do a thing. For example, the -results of a process called declicking, in which one mechanically removes -impure sounds from old recordings, are not copyrightable. On the other -hand, the choice to record a song digitally and to increase the sound of -violins or to bring up the tympani constitutes the results of conversion -that are copyrightable. Moreover, if a work is protected by copyright in -the United States, one generally needs the permission of the copyright -owner to convert it. Normally, who will own the new--that is, converted- --material is a matter of contract. In the absence of a contract, the -person who creates the new material is the author and owner. But people -do not generally think about the copyright implications until after the -fact. PETERS stressed the need when dealing with copyrighted works to -think about copyright in advance. One's bargaining power is much greater -up front than it is down the road. - -PETERS next discussed works not protected by copyright, for example, any -work done by a federal employee as part of his or her official duties is -in the public domain in the United States. The issue is not wholly free -of doubt concerning whether or not the work is in the public domain -outside the United States. Other materials in the public domain include: -any works published more than seventy-five years ago, and any work -published in the United States more than twenty-eight years ago, whose -copyright was not renewed. In talking about the new technology and -putting material in a digital form to send all over the world, PETERS -cautioned, one must keep in mind that while the rights may not be an -issue in the United States, they may be in different parts of the world, -where most countries previously employed a copyright term of the life of -the author plus fifty years. - -PETERS next reviewed the economics of copyright holding. Simply, -economic rights are the rights to control the reproduction of a work in -any form. They belong to the author, or in the case of a work made for -hire, the employer. The second right, which is critical to conversion, -is the right to change a work. The right to make new versions is perhaps -one of the most significant rights of authors, particularly in an -electronic world. The third right is the right to publish the work and -the right to disseminate it, something that everyone who deals in an -electronic medium needs to know. The basic rule is if a copy is sold, -all rights of distribution are extinguished with the sale of that copy. -The key is that it must be sold. A number of companies overcome this -obstacle by leasing or renting their product. These companies argue that -if the material is rented or leased and not sold, they control the uses -of a work. The fourth right, and one very important in a digital world, -is a right of public performance, which means the right to show the work -sequentially. For example, copyright owners control the showing of a -CD-ROM product in a public place such as a public library. The reverse -side of public performance is something called the right of public -display. Moral rights also exist, which at the federal level apply only -to very limited visual works of art, but in theory may apply under -contract and other principles. Moral rights may include the right of an -author to have his or her name on a work, the right of attribution, and -the right to object to distortion or mutilation--the right of integrity. - -The way copyright law is worded gives much latitude to activities such as -preservation; to use of material for scholarly and research purposes when -the user does not make multiple copies; and to the generation of -facsimile copies of unpublished works by libraries for themselves and -other libraries. But the law does not allow anyone to become the -distributor of the product for the entire world. In today's electronic -environment, publishers are extremely concerned that the entire world is -networked and can obtain the information desired from a single copy in a -single library. Hence, if there is to be only one sale, which publishers -may choose to live with, they will obtain their money in other ways, for -example, from access and use. Hence, the development of site licenses -and other kinds of agreements to cover what publishers believe they -should be compensated for. Any solution that the United States takes -today has to consider the international arena. - -Noting that the United States is a member of the Berne Convention and -subscribes to its provisions, PETERS described the permissions process. -She also defined compulsory licenses. A compulsory license, of which the -United States has had a few, builds into the law the right to use a work -subject to certain terms and conditions. In the international arena, -however, the ability to use compulsory licenses is extremely limited. -Thus, clearinghouses and other collectives comprise one option that has -succeeded in providing for use of a work. Often overlooked when one -begins to use copyrighted material and put products together is how -expensive the permissions process and managing it is. According to -PETERS, the price of copyright in a digital medium, whatever solution is -worked out, will include managing and assembling the database. She -strongly recommended that publishers and librarians or people with -various backgrounds cooperate to work out administratively feasible -systems, in order to produce better results. - -In the lengthy question-and-answer period that followed PETERS's -presentation, the following points emerged: - - * The Copyright Office maintains that anything mechanical and - totally exhaustive probably is not protected. In the event that - what an individual did in developing potentially copyrightable - material is not understood, the Copyright Office will ask about the - creative choices the applicant chose to make or not to make. As a - practical matter, if one believes she or he has made enough of those - choices, that person has a right to assert a copyright and someone - else must assert that the work is not copyrightable. The more - mechanical, the more automatic, a thing is, the less likely it is to - be copyrightable. - - * Nearly all photographs are deemed to be copyrightable, but no one - worries about them much, because everyone is free to take the same - image. Thus, a photographic copyright represents what is called a - "thin" copyright. The photograph itself must be duplicated, in - order for copyright to be violated. - - * The Copyright Office takes the position that X-rays are not - copyrightable because they are mechanical. It can be argued - whether or not image enhancement in scanning can be protected. One - must exercise care with material created with public funds and - generally in the public domain. An article written by a federal - employee, if written as part of official duties, is not - copyrightable. However, control over a scientific article written - by a National Institutes of Health grantee (i.e., someone who - receives money from the U.S. government), depends on NIH policy. If - the government agency has no policy (and that policy can be - contained in its regulations, the contract, or the grant), the - author retains copyright. If a provision of the contract, grant, or - regulation states that there will be no copyright, then it does not - exist. When a work is created, copyright automatically comes into - existence unless something exists that says it does not. - - * An enhanced electronic copy of a print copy of an older reference - work in the public domain that does not contain copyrightable new - material is a purely mechanical rendition of the original work, and - is not copyrightable. - - * Usually, when a work enters the public domain, nothing can remove - it. For example, Congress recently passed into law the concept of - automatic renewal, which means that copyright on any work published - between l964 and l978 does not have to be renewed in order to - receive a seventy-five-year term. But any work not renewed before - 1964 is in the public domain. - - * Concerning whether or not the United States keeps track of when - authors die, nothing was ever done, nor is anything being done at - the moment by the Copyright Office. - - * Software that drives a mechanical process is itself copyrightable. - If one changes platforms, the software itself has a copyright. The - World Intellectual Property Organization will hold a symposium 28 - March through 2 April l993, at Harvard University, on digital - technology, and will study this entire issue. If one purchases a - computer software package, such as MacPaint, and creates something - new, one receives protection only for that which has been added. - -PETERS added that often in copyright matters, rough justice is the -outcome, for example, in collective licensing, ASCAP (i.e., American -Society of Composers, Authors, and Publishers), and BMI (i.e., Broadcast -Music, Inc.), where it may seem that the big guys receive more than their -due. Of course, people ought not to copy a creative product without -paying for it; there should be some compensation. But the truth of the -world, and it is not a great truth, is that the big guy gets played on -the radio more frequently than the little guy, who has to do much more -until he becomes a big guy. That is true of every author, every -composer, everyone, and, unfortunately, is part of life. - -Copyright always originates with the author, except in cases of works -made for hire. (Most software falls into this category.) When an author -sends his article to a journal, he has not relinquished copyright, though -he retains the right to relinquish it. The author receives absolutely -everything. The less prominent the author, the more leverage the -publisher will have in contract negotiations. In order to transfer the -rights, the author must sign an agreement giving them away. - -In an electronic society, it is important to be able to license a writer -and work out deals. With regard to use of a work, it usually is much -easier when a publisher holds the rights. In an electronic era, a real -problem arises when one is digitizing and making information available. -PETERS referred again to electronic licensing clearinghouses. Copyright -ought to remain with the author, but as one moves forward globally in the -electronic arena, a middleman who can handle the various rights becomes -increasingly necessary. - -The notion of copyright law is that it resides with the individual, but -in an on-line environment, where a work can be adapted and tinkered with -by many individuals, there is concern. If changes are authorized and -there is no agreement to the contrary, the person who changes a work owns -the changes. To put it another way, the person who acquires permission -to change a work technically will become the author and the owner, unless -some agreement to the contrary has been made. It is typical for the -original publisher to try to control all of the versions and all of the -uses. Copyright law always only sets up the boundaries. Anything can be -changed by contract. - - ****** - -SESSION VII. CONCLUSION - -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -GENERAL DISCUSSION * Two questions for discussion * Different emphases in -the Workshop * Bringing the text and image partisans together * -Desiderata in planning the long-term development of something * Questions -surrounding the issue of electronic deposit * Discussion of electronic -deposit as an allusion to the issue of standards * Need for a directory -of preservation projects in digital form and for access to their -digitized files * CETH's catalogue of machine-readable texts in the -humanities * What constitutes a publication in the electronic world? * -Need for LC to deal with the concept of on-line publishing * LC's Network -Development Office exploring the limits of MARC as a standard in terms -of handling electronic information * Magnitude of the problem and the -need for distributed responsibility in order to maintain and store -electronic information * Workshop participants to be viewed as a starting -point * Development of a network version of AM urged * A step toward AM's -construction of some sort of apparatus for network access * A delicate -and agonizing policy question for LC * Re the issue of electronic -deposit, LC urged to initiate a catalytic process in terms of distributed -responsibility * Suggestions for cooperative ventures * Commercial -publishers' fears * Strategic questions for getting the image and text -people to think through long-term cooperation * Clarification of the -driving force behind both the Perseus and the Cornell Xerox projects * -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -In his role as moderator of the concluding session, GIFFORD raised two -questions he believed would benefit from discussion: 1) Are there enough -commonalities among those of us that have been here for two days so that -we can see courses of action that should be taken in the future? And, if -so, what are they and who might take them? 2) Partly derivative from -that, but obviously very dangerous to LC as host, do you see a role for -the Library of Congress in all this? Of course, the Library of Congress -holds a rather special status in a number of these matters, because it is -not perceived as a player with an economic stake in them, but are there -roles that LC can play that can help advance us toward where we are heading? - -Describing himself as an uninformed observer of the technicalities of the -last two days, GIFFORD detected three different emphases in the Workshop: -1) people who are very deeply committed to text; 2) people who are almost -passionate about images; and 3) a few people who are very committed to -what happens to the networks. In other words, the new networking -dimension, the accessibility of the processability, the portability of -all this across the networks. How do we pull those three together? - -Adding a question that reflected HOCKEY's comment that this was the -fourth workshop she had attended in the previous thirty days, FLEISCHHAUER -wondered to what extent this meeting had reinvented the wheel, or if it -had contributed anything in the way of bringing together a different group -of people from those who normally appear on the workshop circuit. - -HOCKEY confessed to being struck at this meeting and the one the -Electronic Pierce Consortium organized the previous week that this was a -coming together of people working on texts and not images. Attempting to -bring the two together is something we ought to be thinking about for the -future: How one can think about working with image material to begin -with, but structuring it and digitizing it in such a way that at a later -stage it can be interpreted into text, and find a common way of building -text and images together so that they can be used jointly in the future, -with the network support to begin there because that is how people will -want to access it. - -In planning the long-term development of something, which is what is -being done in electronic text, HOCKEY stressed the importance not only -of discussing the technical aspects of how one does it but particularly -of thinking about what the people who use the stuff will want to do. -But conversely, there are numerous things that people start to do with -electronic text or material that nobody ever thought of in the beginning. - -LESK, in response to the question concerning the role of the Library of -Congress, remarked the often suggested desideratum of having electronic -deposit: Since everything is now computer-typeset, an entire decade of -material that was machine-readable exists, but the publishers frequently -did not save it; has LC taken any action to have its copyright deposit -operation start collecting these machine-readable versions? In the -absence of PETERS, GIFFORD replied that the question was being -actively considered but that that was only one dimension of the problem. -Another dimension is the whole question of the integrity of the original -electronic document. It becomes highly important in science to prove -authorship. How will that be done? - -ERWAY explained that, under the old policy, to make a claim for a -copyright for works that were published in electronic form, including -software, one had to submit a paper copy of the first and last twenty -pages of code--something that represented the work but did not include -the entire work itself and had little value to anyone. As a temporary -measure, LC has claimed the right to demand electronic versions of -electronic publications. This measure entails a proactive role for the -Library to say that it wants a particular electronic version. Publishers -then have perhaps a year to submit it. But the real problem for LC is -what to do with all this material in all these different formats. Will -the Library mount it? How will it give people access to it? How does LC -keep track of the appropriate computers, software, and media? The situation -is so hard to control, ERWAY said, that it makes sense for each publishing -house to maintain its own archive. But LC cannot enforce that either. - -GIFFORD acknowledged LESK's suggestion that establishing a priority -offered the solution, albeit a fairly complicated one. But who maintains -that register?, he asked. GRABER noted that LC does attempt to collect a -Macintosh version and the IBM-compatible version of software. It does -not collect other versions. But while true for software, BYRUM observed, -this reply does not speak to materials, that is, all the materials that -were published that were on somebody's microcomputer or driver tapes -at a publishing office across the country. LC does well to acquire -specific machine-readable products selectively that were intended to be -machine-readable. Materials that were in machine-readable form at one time, -BYRUM said, would be beyond LC's capability at the moment, insofar as -attempting to acquire, organize, and preserve them are concerned--and -preservation would be the most important consideration. In this -connection, GIFFORD reiterated the need to work out some sense of -distributive responsibility for a number of these issues, which -inevitably will require significant cooperation and discussion. -Nobody can do it all. - -LESK suggested that some publishers may look with favor on LC beginning -to serve as a depository of tapes in an electronic manuscript standard. -Publishers may view this as a service that they did not have to perform -and they might send in tapes. However, SPERBERG-McQUEEN countered, -although publishers have had equivalent services available to them for a -long time, the electronic text archive has never turned away or been -flooded with tapes and is forever sending feedback to the depositor. -Some publishers do send in tapes. - -ANDRE viewed this discussion as an allusion to the issue of standards. -She recommended that the AAP standard and the TEI, which has already been -somewhat harmonized internationally and which also shares several -compatibilities with the AAP, be harmonized to ensure sufficient -compatibility in the software. She drew the line at saying LC ought to -be the locus or forum for such harmonization. - -Taking the group in a slightly different direction, but one where at -least in the near term LC might play a helpful role, LYNCH remarked the -plans of a number of projects to carry out preservation by creating -digital images that will end up in on-line or near-line storage at some -institution. Presumably, LC will link this material somehow to its -on-line catalog in most cases. Thus, it is in a digital form. LYNCH had -the impression that many of these institutions would be willing to make -those files accessible to other people outside the institution, provided -that there is no copyright problem. This desideratum will require -propagating the knowledge that those digitized files exist, so that they -can end up in other on-line catalogs. Although uncertain about the -mechanism for achieving this result, LYNCH said that it warranted -scrutiny because it seemed to be connected to some of the basic issues of -cataloging and distribution of records. It would be foolish, given the -amount of work that all of us have to do and our meager resources, to -discover multiple institutions digitizing the same work. Re microforms, -LYNCH said, we are in pretty good shape. - -BATTIN called this a big problem and noted that the Cornell people (who -had already departed) were working on it. At issue from the beginning -was to learn how to catalog that information into RLIN and then into -OCLC, so that it would be accessible. That issue remains to be resolved. -LYNCH rejoined that putting it into OCLC or RLIN was helpful insofar as -somebody who is thinking of performing preservation activity on that work -could learn about it. It is not necessarily helpful for institutions to -make that available. BATTIN opined that the idea was that it not only be -for preservation purposes but for the convenience of people looking for -this material. She endorsed LYNCH's dictum that duplication of this -effort was to be avoided by every means. - -HOCKEY informed the Workshop about one major current activity of CETH, -namely a catalogue of machine-readable texts in the humanities. Held on -RLIN at present, the catalogue has been concentrated on ASCII as opposed -to digitized images of text. She is exploring ways to improve the -catalogue and make it more widely available, and welcomed suggestions -about these concerns. CETH owns the records, which are not just -restricted to RLIN, and can distribute them however it wishes. - -Taking up LESK's earlier question, BATTIN inquired whether LC, since it -is accepting electronic files and designing a mechanism for dealing with -that rather than putting books on shelves, would become responsible for -the National Copyright Depository of Electronic Materials. Of course -that could not be accomplished overnight, but it would be something LC -could plan for. GIFFORD acknowledged that much thought was being devoted -to that set of problems and returned the discussion to the issue raised -by LYNCH--whether or not putting the kind of records that both BATTIN and -HOCKEY have been talking about in RLIN is not a satisfactory solution. -It seemed to him that RLIN answered LYNCH's original point concerning -some kind of directory for these kinds of materials. In a situation -where somebody is attempting to decide whether or not to scan this or -film that or to learn whether or not someone has already done so, LYNCH -suggested, RLIN is helpful, but it is not helpful in the case of a local, -on-line catalogue. Further, one would like to have her or his system be -aware that that exists in digital form, so that one can present it to a -patron, even though one did not digitize it, if it is out of copyright. -The only way to make those linkages would be to perform a tremendous -amount of real-time look-up, which would be awkward at best, or -periodically to yank the whole file from RLIN and match it against one's -own stuff, which is a nuisance. - -But where, ERWAY inquired, does one stop including things that are -available with Internet, for instance, in one's local catalogue? -It almost seems that that is LC's means to acquire access to them. -That represents LC's new form of library loan. Perhaps LC's new on-line -catalogue is an amalgamation of all these catalogues on line. LYNCH -conceded that perhaps that was true in the very long term, but was not -applicable to scanning in the short term. In his view, the totals cited -by Yale, 10,000 books over perhaps a four-year period, and 1,000-1,500 -books from Cornell, were not big numbers, while searching all over -creation for relatively rare occurrences will prove to be less efficient. -As GIFFORD wondered if this would not be a separable file on RLIN and -could be requested from them, BATTIN interjected that it was easily -accessible to an institution. SEVERTSON pointed out that that file, cum -enhancements, was available with reference information on CD-ROM, which -makes it a little more available. - -In HOCKEY's view, the real question facing the Workshop is what to put in -this catalogue, because that raises the question of what constitutes a -publication in the electronic world. (WEIBEL interjected that Eric Joule -in OCLC's Office of Research is also wrestling with this particular -problem, while GIFFORD thought it sounded fairly generic.) HOCKEY -contended that a majority of texts in the humanities are in the hands -of either a small number of large research institutions or individuals -and are not generally available for anyone else to access at all. -She wondered if these texts ought to be catalogued. - -After argument proceeded back and forth for several minutes over why -cataloguing might be a necessary service, LEBRON suggested that this -issue involved the responsibility of a publisher. The fact that someone -has created something electronically and keeps it under his or her -control does not constitute publication. Publication implies -dissemination. While it would be important for a scholar to let other -people know that this creation exists, in many respects this is no -different from an unpublished manuscript. That is what is being accessed -in there, except that now one is not looking at it in the hard-copy but -in the electronic environment. - -LEBRON expressed puzzlement at the variety of ways electronic publishing -has been viewed. Much of what has been discussed throughout these two -days has concerned CD-ROM publishing, whereas in the on-line environment -that she confronts, the constraints and challenges are very different. -Sooner or later LC will have to deal with the concept of on-line -publishing. Taking up the comment ERWAY made earlier about storing -copies, LEBRON gave her own journal as an example. How would she deposit -OJCCT for copyright?, she asked, because the journal will exist in the -mainframe at OCLC and people will be able to access it. Here the -situation is different, ownership versus access, and is something that -arises with publication in the on-line environment, faster than is -sometimes realized. Lacking clear answers to all of these questions -herself, LEBRON did not anticipate that LC would be able to take a role -in helping to define some of them for quite a while. - -GREENFIELD observed that LC's Network Development Office is attempting, -among other things, to explore the limits of MARC as a standard in terms -of handling electronic information. GREENFIELD also noted that Rebecca -GUENTHER from that office gave a paper to the American Society for -Information Science (ASIS) summarizing several of the discussion papers -that were coming out of the Network Development Office. GREENFIELD said -he understood that that office had a list-server soliciting just the kind -of feedback received today concerning the difficulties of identifying and -cataloguing electronic information. GREENFIELD hoped that everybody -would be aware of that and somehow contribute to that conversation. - -Noting two of LC's roles, first, to act as a repository of record for -material that is copyrighted in this country, and second, to make -materials it holds available in some limited form to a clientele that -goes beyond Congress, BESSER suggested that it was incumbent on LC to -extend those responsibilities to all the things being published in -electronic form. This would mean eventually accepting electronic -formats. LC could require that at some point they be in a certain -limited set of formats, and then develop mechanisms for allowing people -to access those in the same way that other things are accessed. This -does not imply that they are on the network and available to everyone. -LC does that with most of its bibliographic records, BESSER said, which -end up migrating to the utility (e.g., OCLC) or somewhere else. But just -as most of LC's books are available in some form through interlibrary -loan or some other mechanism, so in the same way electronic formats ought -to be available to others in some format, though with some copyright -considerations. BESSER was not suggesting that these mechanisms be -established tomorrow, only that they seemed to fall within LC's purview, -and that there should be long-range plans to establish them. - -Acknowledging that those from LC in the room agreed with BESSER -concerning the need to confront difficult questions, GIFFORD underscored -the magnitude of the problem of what to keep and what to select. GIFFORD -noted that LC currently receives some 31,000 items per day, not counting -electronic materials, and argued for much more distributed responsibility -in order to maintain and store electronic information. - -BESSER responded that the assembled group could be viewed as a starting -point, whose initial operating premise could be helping to move in this -direction and defining how LC could do so, for example, in areas of -standardization or distribution of responsibility. - -FLEISCHHAUER added that AM was fully engaged, wrestling with some of the -questions that pertain to the conversion of older historical materials, -which would be one thing that the Library of Congress might do. Several -points mentioned by BESSER and several others on this question have a -much greater impact on those who are concerned with cataloguing and the -networking of bibliographic information, as well as preservation itself. - -Speaking directly to AM, which he considered was a largely uncopyrighted -database, LYNCH urged development of a network version of AM, or -consideration of making the data in it available to people interested in -doing network multimedia. On account of the current great shortage of -digital data that is both appealing and unencumbered by complex rights -problems, this course of action could have a significant effect on making -network multimedia a reality. - -In this connection, FLEISCHHAUER reported on a fragmentary prototype in -LC's Office of Information Technology Services that attempts to associate -digital images of photographs with cataloguing information in ways that -work within a local area network--a step, so to say, toward AM's -construction of some sort of apparatus for access. Further, AM has -attempted to use standard data forms in order to help make that -distinction between the access tools and the underlying data, and thus -believes that the database is networkable. - -A delicate and agonizing policy question for LC, however, which comes -back to resources and unfortunately has an impact on this, is to find -some appropriate, honorable, and legal cost-recovery possibilities. A -certain skittishness concerning cost-recovery has made people unsure -exactly what to do. AM would be highly receptive to discussing further -LYNCH's offer to test or demonstrate its database in a network -environment, FLEISCHHAUER said. - -Returning the discussion to what she viewed as the vital issue of -electronic deposit, BATTIN recommended that LC initiate a catalytic -process in terms of distributed responsibility, that is, bring together -the distributed organizations and set up a study group to look at all -these issues and see where we as a nation should move. The broader -issues of how we deal with the management of electronic information will -not disappear, but only grow worse. - -LESK took up this theme and suggested that LC attempt to persuade one -major library in each state to deal with its state equivalent publisher, -which might produce a cooperative project that would be equitably -distributed around the country, and one in which LC would be dealing with -a minimal number of publishers and minimal copyright problems. - -GRABER remarked the recent development in the scientific community of a -willingness to use SGML and either deposit or interchange on a fairly -standardized format. He wondered if a similar movement was taking place -in the humanities. Although the National Library of Medicine found only -a few publishers to cooperate in a like venture two or three years ago, a -new effort might generate a much larger number willing to cooperate. - -KIMBALL recounted his unit's (Machine-Readable Collections Reading Room) -troubles with the commercial publishers of electronic media in acquiring -materials for LC's collections, in particular the publishers' fear that -they would not be able to cover their costs and would lose control of -their products, that LC would give them away or sell them and make -profits from them. He doubted that the publishing industry was prepared -to move into this area at the moment, given its resistance to allowing LC -to use its machine-readable materials as the Library would like. - -The copyright law now addresses compact disk as a medium, and LC can -request one copy of that, or two copies if it is the only version, and -can request copies of software, but that fails to address magazines or -books or anything like that which is in machine-readable form. - -GIFFORD acknowledged the thorny nature of this issue, which he illustrated -with the example of the cumbersome process involved in putting a copy of a -scientific database on a LAN in LC's science reading room. He also -acknowledged that LC needs help and could enlist the energies and talents -of Workshop participants in thinking through a number of these problems. - -GIFFORD returned the discussion to getting the image and text people to -think through together where they want to go in the long term. MYLONAS -conceded that her experience at the Pierce Symposium the previous week at -Georgetown University and this week at LC had forced her to reevaluate -her perspective on the usefulness of text as images. MYLONAS framed the -issues in a series of questions: How do we acquire machine-readable -text? Do we take pictures of it and perform OCR on it later? Is it -important to obtain very high-quality images and text, etc.? -FLEISCHHAUER agreed with MYLONAS's framing of strategic questions, adding -that a large institution such as LC probably has to do all of those -things at different times. Thus, the trick is to exercise judgment. The -Workshop had added to his and AM's considerations in making those -judgments. Concerning future meetings or discussions, MYLONAS suggested -that screening priorities would be helpful. - -WEIBEL opined that the diversity reflected in this group was a sign both -of the health and of the immaturity of the field, and more time would -have to pass before we convince one another concerning standards. - -An exchange between MYLONAS and BATTIN clarified the point that the -driving force behind both the Perseus and the Cornell Xerox projects was -the preservation of knowledge for the future, not simply for particular -research use. In the case of Perseus, MYLONAS said, the assumption was -that the texts would not be entered again into electronically readable -form. SPERBERG-McQUEEN added that a scanned image would not serve as an -archival copy for purposes of preservation in the case of, say, the Bill -of Rights, in the sense that the scanned images are effectively the -archival copies for the Cornell mathematics books. - - - *** *** *** ****** *** *** *** - - - Appendix I: PROGRAM - - - - WORKSHOP - ON - ELECTRONIC - TEXTS - - - - 9-10 June 1992 - - Library of Congress - Washington, D.C. - - - - Supported by a Grant from the David and Lucile Packard Foundation - - -Tuesday, 9 June 1992 - -NATIONAL DEMONSTRATION LAB, ATRIUM, LIBRARY MADISON - -8:30 AM Coffee and Danish, registration - -9:00 AM Welcome - - Prosser Gifford, Director for Scholarly Programs, and Carl - Fleischhauer, Coordinator, American Memory, Library of - Congress - -9:l5 AM Session I. Content in a New Form: Who Will Use It and What - Will They Do? - - Broad description of the range of electronic information. - Characterization of who uses it and how it is or may be used. - In addition to a look at scholarly uses, this session will - include a presentation on use by students (K-12 and college) - and the general public. - - Moderator: James Daly - Avra Michelson, Archival Research and Evaluation Staff, - National Archives and Records Administration (Overview) - Susan H. Veccia, Team Leader, American Memory, User Evaluation, - and - Joanne Freeman, Associate Coordinator, American Memory, Library - of Congress (Beyond the scholar) - -10:30- -11:00 AM Break - -11:00 AM Session II. Show and Tell. - - Each presentation to consist of a fifteen-minute - statement/show; group discussion will follow lunch. - - Moderator: Jacqueline Hess, Director, National Demonstration - Lab - - 1. A classics project, stressing texts and text retrieval - more than multimedia: Perseus Project, Harvard - University - Elli Mylonas, Managing Editor - - 2. Other humanities projects employing the emerging norms of - the Text Encoding Initiative (TEI): Chadwyck-Healey's - The English Poetry Full Text Database and/or Patrologia - Latina Database - Eric M. Calaluca, Vice President, Chadwyck-Healey, Inc. - - 3. American Memory - Carl Fleischhauer, Coordinator, and - Ricky Erway, Associate Coordinator, Library of Congress - - 4. Founding Fathers example from Packard Humanities - Institute: The Papers of George Washington, University - of Virginia - Dorothy Twohig, Managing Editor, and/or - David Woodley Packard - - 5. An electronic medical journal offering graphics and - full-text searchability: The Online Journal of Current - Clinical Trials, American Association for the Advancement - of Science - Maria L. Lebron, Managing Editor - - 6. A project that offers facsimile images of pages but omits - searchable text: Cornell math books - Lynne K. Personius, Assistant Director, Cornell - Information Technologies for Scholarly Information - Sources, Cornell University - -12:30 PM Lunch (Dining Room A, Library Madison 620. Exhibits - available.) - -1:30 PM Session II. Show and Tell (Cont'd.). - -3:00- -3:30 PM Break - -3:30- -5:30 PM Session III. Distribution, Networks, and Networking: Options - for Dissemination. - - Published disks: University presses and public-sector - publishers, private-sector publishers - Computer networks - - Moderator: Robert G. Zich, Special Assistant to the Associate - Librarian for Special Projects, Library of Congress - Clifford A. Lynch, Director, Library Automation, University of - California - Howard Besser, School of Library and Information Science, - University of Pittsburgh - Ronald L. Larsen, Associate Director of Libraries for - Information Technology, University of Maryland at College - Park - Edwin B. Brownrigg, Executive Director, Memex Research - Institute - -6:30 PM Reception (Montpelier Room, Library Madison 619.) - - ****** - -Wednesday, 10 June 1992 - -DINING ROOM A, LIBRARY MADISON 620 - -8:30 AM Coffee and Danish - -9:00 AM Session IV. Image Capture, Text Capture, Overview of Text and - Image Storage Formats. - - Moderator: William L. Hooton, Vice President of Operations, - I-NET - - A) Principal Methods for Image Capture of Text: - Direct scanning - Use of microform - - Anne R. Kenney, Assistant Director, Department of Preservation - and Conservation, Cornell University - Pamela Q.J. Andre, Associate Director, Automation, and - Judith A. Zidar, Coordinator, National Agricultural Text - Digitizing Program (NATDP), National Agricultural Library - (NAL) - Donald J. Waters, Head, Systems Office, Yale University Library - - B) Special Problems: - Bound volumes - Conservation - Reproducing printed halftones - - Carl Fleischhauer, Coordinator, American Memory, Library of - Congress - George Thoma, Chief, Communications Engineering Branch, - National Library of Medicine (NLM) - -10:30- -11:00 AM Break - -11:00 AM Session IV. Image Capture, Text Capture, Overview of Text and - Image Storage Formats (Cont'd.). - - C) Image Standards and Implications for Preservation - - Jean Baronas, Senior Manager, Department of Standards and - Technology, Association for Information and Image Management - (AIIM) - Patricia Battin, President, The Commission on Preservation and - Access (CPA) - - D) Text Conversion: - OCR vs. rekeying - Standards of accuracy and use of imperfect texts - Service bureaus - - Stuart Weibel, Senior Research Specialist, Online Computer - Library Center, Inc. (OCLC) - Michael Lesk, Executive Director, Computer Science Research, - Bellcore - Ricky Erway, Associate Coordinator, American Memory, Library of - Congress - Pamela Q.J. Andre, Associate Director, Automation, and - Judith A. Zidar, Coordinator, National Agricultural Text - Digitizing Program (NATDP), National Agricultural Library - (NAL) - -12:30- -1:30 PM Lunch - -1:30 PM Session V. Approaches to Preparing Electronic Texts. - - Discussion of approaches to structuring text for the computer; - pros and cons of text coding, description of methods in - practice, and comparison of text-coding methods. - - Moderator: Susan Hockey, Director, Center for Electronic Texts - in the Humanities (CETH), Rutgers and Princeton Universities - David Woodley Packard - C.M. Sperberg-McQueen, Editor, Text Encoding Initiative (TEI), - University of Illinois-Chicago - Eric M. Calaluca, Vice President, Chadwyck-Healey, Inc. - -3:30- -4:00 PM Break - -4:00 PM Session VI. Copyright Issues. - - Marybeth Peters, Policy Planning Adviser to the Register of - Copyrights, Library of Congress - -5:00 PM Session VII. Conclusion. - - General discussion. - What topics were omitted or given short shrift that anyone - would like to talk about now? - Is there a "group" here? What should the group do next, if - anything? What should the Library of Congress do next, if - anything? - Moderator: Prosser Gifford, Director for Scholarly Programs, - Library of Congress - -6:00 PM Adjourn - - - *** *** *** ****** *** *** *** - - - Appendix II: ABSTRACTS - - -SESSION I - -Avra MICHELSON Forecasting the Use of Electronic Texts by - Social Sciences and Humanities Scholars - -This presentation explores the ways in which electronic texts are likely -to be used by the non-scientific scholarly community. Many of the -remarks are drawn from a report the speaker coauthored with Jeff -Rothenberg, a computer scientist at The RAND Corporation. - -The speaker assesses 1) current scholarly use of information technology -and 2) the key trends in information technology most relevant to the -research process, in order to predict how social sciences and humanities -scholars are apt to use electronic texts. In introducing the topic, -current use of electronic texts is explored broadly within the context of -scholarly communication. From the perspective of scholarly -communication, the work of humanities and social sciences scholars -involves five processes: 1) identification of sources, 2) communication -with colleagues, 3) interpretation and analysis of data, 4) dissemination -of research findings, and 5) curriculum development and instruction. The -extent to which computation currently permeates aspects of scholarly -communication represents a viable indicator of the prospects for -electronic texts. - -The discussion of current practice is balanced by an analysis of key -trends in the scholarly use of information technology. These include the -trends toward end-user computing and connectivity, which provide a -framework for forecasting the use of electronic texts through this -millennium. The presentation concludes with a summary of the ways in -which the nonscientific scholarly community can be expected to use -electronic texts, and the implications of that use for information -providers. - -Susan VECCIA and Joanne FREEMAN Electronic Archives for the Public: - Use of American Memory in Public and - School Libraries - -This joint discussion focuses on nonscholarly applications of electronic -library materials, specifically addressing use of the Library of Congress -American Memory (AM) program in a small number of public and school -libraries throughout the United States. AM consists of selected Library -of Congress primary archival materials, stored on optical media -(CD-ROM/videodisc), and presented with little or no editing. Many -collections are accompanied by electronic introductions and user's guides -offering background information and historical context. Collections -represent a variety of formats including photographs, graphic arts, -motion pictures, recorded sound, music, broadsides and manuscripts, -books, and pamphlets. - -In 1991, the Library of Congress began a nationwide evaluation of AM in -different types of institutions. Test sites include public libraries, -elementary and secondary school libraries, college and university -libraries, state libraries, and special libraries. Susan VECCIA and -Joanne FREEMAN will discuss their observations on the use of AM by the -nonscholarly community, using evidence gleaned from this ongoing -evaluation effort. - -VECCIA will comment on the overall goals of the evaluation project, and -the types of public and school libraries included in this study. Her -comments on nonscholarly use of AM will focus on the public library as a -cultural and community institution, often bridging the gap between formal -and informal education. FREEMAN will discuss the use of AM in school -libraries. Use by students and teachers has revealed some broad -questions about the use of electronic resources, as well as definite -benefits gained by the "nonscholar." Topics will include the problem of -grasping content and context in an electronic environment, the stumbling -blocks created by "new" technologies, and the unique skills and interests -awakened through use of electronic resources. - -SESSION II - -Elli MYLONAS The Perseus Project: Interactive Sources and - Studies in Classical Greece - -The Perseus Project (5) has just released Perseus 1.0, the first publicly -available version of its hypertextual database of multimedia materials on -classical Greece. Perseus is designed to be used by a wide audience, -comprised of readers at the student and scholar levels. As such, it must -be able to locate information using different strategies, and it must -contain enough detail to serve the different needs of its users. In -addition, it must be delivered so that it is affordable to its target -audience. [These problems and the solutions we chose are described in -Mylonas, "An Interface to Classical Greek Civilization," JASIS 43:2, -March 1992.] - -In order to achieve its objective, the project staff decided to make a -conscious separation between selecting and converting textual, database, -and image data on the one hand, and putting it into a delivery system on -the other. That way, it is possible to create the electronic data -without thinking about the restrictions of the delivery system. We have -made a great effort to choose system-independent formats for our data, -and to put as much thought and work as possible into structuring it so -that the translation from paper to electronic form will enhance the value -of the data. [A discussion of these solutions as of two years ago is in -Elli Mylonas, Gregory Crane, Kenneth Morrell, and D. Neel Smith, "The -Perseus Project: Data in the Electronic Age," in Accessing Antiquity: -The Computerization of Classical Databases, J. Solomon and T. Worthen -(eds.), University of Arizona Press, in press.] - -Much of the work on Perseus is focused on collecting and converting the -data on which the project is based. At the same time, it is necessary to -provide means of access to the information, in order to make it usable, -and them to investigate how it is used. As we learn more about what -students and scholars from different backgrounds do with Perseus, we can -adjust our data collection, and also modify the system to accommodate -them. In creating a delivery system for general use, we have tried to -avoid favoring any one type of use by allowing multiple forms of access -to and navigation through the system. - -The way text is handled exemplifies some of these principles. All text -in Perseus is tagged using SGML, following the guidelines of the Text -Encoding Initiative (TEI). This markup is used to index the text, and -process it so that it can be imported into HyperCard. No SGML markup -remains in the text that reaches the user, because currently it would be -too expensive to create a system that acts on SGML in real time. -However, the regularity provided by SGML is essential for verifying the -content of the texts, and greatly speeds all the processing performed on -them. The fact that the texts exist in SGML ensures that they will be -relatively easy to port to different hardware and software, and so will -outlast the current delivery platform. Finally, the SGML markup -incorporates existing canonical reference systems (chapter, verse, line, -etc.); indexing and navigation are based on these features. This ensures -that the same canonical reference will always resolve to the same point -within a text, and that all versions of our texts, regardless of delivery -platform (even paper printouts) will function the same way. - -In order to provide tools for users, the text is processed by a -morphological analyzer, and the results are stored in a database. -Together with the index, the Greek-English Lexicon, and the index of all -the English words in the definitions of the lexicon, the morphological -analyses comprise a set of linguistic tools that allow users of all -levels to work with the textual information, and to accomplish different -tasks. For example, students who read no Greek may explore a concept as -it appears in Greek texts by using the English-Greek index, and then -looking up works in the texts and translations, or scholars may do -detailed morphological studies of word use by using the morphological -analyses of the texts. Because these tools were not designed for any one -use, the same tools and the same data can be used by both students and -scholars. - -NOTES: - (5) Perseus is based at Harvard University, with collaborators at - several other universities. The project has been funded primarily - by the Annenberg/CPB Project, as well as by Harvard University, - Apple Computer, and others. It is published by Yale University - Press. Perseus runs on Macintosh computers, under the HyperCard - program. - -Eric CALALUCA - -Chadwyck-Healey embarked last year on two distinct yet related full-text -humanities database projects. - -The English Poetry Full-Text Database and the Patrologia Latina Database -represent new approaches to linguistic research resources. The size and -complexity of the projects present problems for electronic publishers, -but surmountable ones if they remain abreast of the latest possibilities -in data capture and retrieval software techniques. - -The issues which required address prior to the commencement of the -projects were legion: - - 1. Editorial selection (or exclusion) of materials in each - database - - 2. Deciding whether or not to incorporate a normative encoding - structure into the databases? - A. If one is selected, should it be SGML? - B. If SGML, then the TEI? - - 3. Deliver as CD-ROM, magnetic tape, or both? - - 4. Can one produce retrieval software advanced enough for the - postdoctoral linguist, yet accessible enough for unattended - general use? Should one try? - - 5. Re fair and liberal networking policies, what are the risks to - an electronic publisher? - - 6. How does the emergence of national and international education - networks affect the use and viability of research projects - requiring high investment? Do the new European Community - directives concerning database protection necessitate two - distinct publishing projects, one for North America and one for - overseas? - -From new notions of "scholarly fair use" to the future of optical media, -virtually every issue related to electronic publishing was aired. The -result is two projects which have been constructed to provide the quality -research resources with the fewest encumbrances to use by teachers and -private scholars. - -Dorothy TWOHIG - -In spring 1988 the editors of the papers of George Washington, John -Adams, Thomas Jefferson, James Madison, and Benjamin Franklin were -approached by classics scholar David Packard on behalf of the Packard -Humanities Foundation with a proposal to produce a CD-ROM edition of the -complete papers of each of the Founding Fathers. This electronic edition -will supplement the published volumes, making the documents widely -available to students and researchers at reasonable cost. We estimate -that our CD-ROM edition of Washington's Papers will be substantially -completed within the next two years and ready for publication. Within -the next ten years or so, similar CD-ROM editions of the Franklin, Adams, -Jefferson, and Madison papers also will be available. At the Library of -Congress's session on technology, I would like to discuss not only the -experience of the Washington Papers in producing the CD-ROM edition, but -the impact technology has had on these major editorial projects. -Already, we are editing our volumes with an eye to the material that will -be readily available in the CD-ROM edition. The completed electronic -edition will provide immense possibilities for the searching of documents -for information in a way never possible before. The kind of technical -innovations that are currently available and on the drawing board will -soon revolutionize historical research and the production of historical -documents. Unfortunately, much of this new technology is not being used -in the planning stages of historical projects, simply because many -historians are aware only in the vaguest way of its existence. At least -two major new historical editing projects are considering microfilm -editions, simply because they are not aware of the possibilities of -electronic alternatives and the advantages of the new technology in terms -of flexibility and research potential compared to microfilm. In fact, -too many of us in history and literature are still at the stage of -struggling with our PCs. There are many historical editorial projects in -progress presently, and an equal number of literary projects. While the -two fields have somewhat different approaches to textual editing, there -are ways in which electronic technology can be of service to both. - -Since few of the editors involved in the Founding Fathers CD-ROM editions -are technical experts in any sense, I hope to point out in my discussion -of our experience how many of these electronic innovations can be used -successfully by scholars who are novices in the world of new technology. -One of the major concerns of the sponsors of the multitude of new -scholarly editions is the limited audience reached by the published -volumes. Most of these editions are being published in small quantities -and the publishers' price for them puts them out of the reach not only of -individual scholars but of most public libraries and all but the largest -educational institutions. However, little attention is being given to -ways in which technology can bypass conventional publication to make -historical and literary documents more widely available. - -What attracted us most to the CD-ROM edition of The Papers of George -Washington was the fact that David Packard's aim was to make a complete -edition of all of the 135,000 documents we have collected available in an -inexpensive format that would be placed in public libraries, small -colleges, and even high schools. This would provide an audience far -beyond our present 1,000-copy, $45 published edition. Since the CD-ROM -edition will carry none of the explanatory annotation that appears in the -published volumes, we also feel that the use of the CD-ROM will lead many -researchers to seek out the published volumes. - -In addition to ignorance of new technical advances, I have found that too -many editors--and historians and literary scholars--are resistant and -even hostile to suggestions that electronic technology may enhance their -work. I intend to discuss some of the arguments traditionalists are -advancing to resist technology, ranging from distrust of the speed with -which it changes (we are already wondering what is out there that is -better than CD-ROM) to suspicion of the technical language used to -describe electronic developments. - -Maria LEBRON - -The Online Journal of Current Clinical Trials, a joint venture of the -American Association for the Advancement of Science (AAAS) and the Online -Computer Library Center, Inc. (OCLC), is the first peer-reviewed journal -to provide full text, tabular material, and line illustrations on line. -This presentation will discuss the genesis and start-up period of the -journal. Topics of discussion will include historical overview, -day-to-day management of the editorial peer review, and manuscript -tagging and publication. A demonstration of the journal and its features -will accompany the presentation. - -Lynne PERSONIUS - -Cornell University Library, Cornell Information Technologies, and Xerox -Corporation, with the support of the Commission on Preservation and -Access, and Sun Microsystems, Inc., have been collaborating in a project -to test a prototype system for recording brittle books as digital images -and producing, on demand, high-quality archival paper replacements. The -project goes beyond that, however, to investigate some of the issues -surrounding scanning, storing, retrieving, and providing access to -digital images in a network environment. - -The Joint Study in Digital Preservation began in January 1990. Xerox -provided the College Library Access and Storage System (CLASS) software, -a prototype 600-dots-per-inch (dpi) scanner, and the hardware necessary -to support network printing on the DocuTech printer housed in Cornell's -Computing and Communications Center (CCC). - -The Cornell staff using the hardware and software became an integral part -of the development and testing process for enhancements to the CLASS -software system. The collaborative nature of this relationship is -resulting in a system that is specifically tailored to the preservation -application. - -A digital library of 1,000 volumes (or approximately 300,000 images) has -been created and is stored on an optical jukebox that resides in CCC. -The library includes a collection of select mathematics monographs that -provides mathematics faculty with an opportunity to use the electronic -library. The remaining volumes were chosen for the library to test the -various capabilities of the scanning system. - -One project objective is to provide users of the Cornell library and the -library staff with the ability to request facsimiles of digitized images -or to retrieve the actual electronic image for browsing. A prototype -viewing workstation has been created by Xerox, with input into the design -by a committee of Cornell librarians and computer professionals. This -will allow us to experiment with patron access to the images that make up -the digital library. The viewing station provides search, retrieval, and -(ultimately) printing functions with enhancements to facilitate -navigation through multiple documents. - -Cornell currently is working to extend access to the digital library to -readers using workstations from their offices. This year is devoted to -the development of a network resident image conversion and delivery -server, and client software that will support readers who use Apple -Macintosh computers, IBM windows platforms, and Sun workstations. -Equipment for this development was provided by Sun Microsystems with -support from the Commission on Preservation and Access. - -During the show-and-tell session of the Workshop on Electronic Texts, a -prototype view station will be demonstrated. In addition, a display of -original library books that have been digitized will be available for -review with associated printed copies for comparison. The fifteen-minute -overview of the project will include a slide presentation that -constitutes a "tour" of the preservation digitizing process. - -The final network-connected version of the viewing station will provide -library users with another mechanism for accessing the digital library, -and will also provide the capability of viewing images directly. This -will not require special software, although a powerful computer with good -graphics will be needed. - -The Joint Study in Digital Preservation has generated a great deal of -interest in the library community. Unfortunately, or perhaps -fortunately, this project serves to raise a vast number of other issues -surrounding the use of digital technology for the preservation and use of -deteriorating library materials, which subsequent projects will need to -examine. Much work remains. - -SESSION III - -Howard BESSER Networking Multimedia Databases - -What do we have to consider in building and distributing databases of -visual materials in a multi-user environment? This presentation examines -a variety of concerns that need to be addressed before a multimedia -database can be set up in a networked environment. - -In the past it has not been feasible to implement databases of visual -materials in shared-user environments because of technological barriers. -Each of the two basic models for multi-user multimedia databases has -posed its own problem. The analog multimedia storage model (represented -by Project Athena's parallel analog and digital networks) has required an -incredibly complex (and expensive) infrastructure. The economies of -scale that make multi-user setups cheaper per user served do not operate -in an environment that requires a computer workstation, videodisc player, -and two display devices for each user. - -The digital multimedia storage model has required vast amounts of storage -space (as much as one gigabyte per thirty still images). In the past the -cost of such a large amount of storage space made this model a -prohibitive choice as well. But plunging storage costs are finally -making this second alternative viable. - -If storage no longer poses such an impediment, what do we need to -consider in building digitally stored multi-user databases of visual -materials? This presentation will examine the networking and -telecommunication constraints that must be overcome before such databases -can become commonplace and useful to a large number of people. - -The key problem is the vast size of multimedia documents, and how this -affects not only storage but telecommunications transmission time. -Anything slower than T-1 speed is impractical for files of 1 megabyte or -larger (which is likely to be small for a multimedia document). For -instance, even on a 56 Kb line it would take three minutes to transfer a -1-megabyte file. And these figures assume ideal circumstances, and do -not take into consideration other users contending for network bandwidth, -disk access time, or the time needed for remote display. Current common -telephone transmission rates would be completely impractical; few users -would be willing to wait the hour necessary to transmit a single image at -2400 baud. - -This necessitates compression, which itself raises a number of other -issues. In order to decrease file sizes significantly, we must employ -lossy compression algorithms. But how much quality can we afford to -lose? To date there has been only one significant study done of -image-quality needs for a particular user group, and this study did not -look at loss resulting from compression. Only after identifying -image-quality needs can we begin to address storage and network bandwidth -needs. - -Experience with X-Windows-based applications (such as Imagequery, the -University of California at Berkeley image database) demonstrates the -utility of a client-server topology, but also points to the limitation of -current software for a distributed environment. For example, -applications like Imagequery can incorporate compression, but current X -implementations do not permit decompression at the end user's -workstation. Such decompression at the host computer alleviates storage -capacity problems while doing nothing to address problems of -telecommunications bandwidth. - -We need to examine the effects on network through-put of moving -multimedia documents around on a network. We need to examine various -topologies that will help us avoid bottlenecks around servers and -gateways. Experience with applications such as these raise still broader -questions. How closely is the multimedia document tied to the software -for viewing it? Can it be accessed and viewed from other applications? -Experience with the MARC format (and more recently with the Z39.50 -protocols) shows how useful it can be to store documents in a form in -which they can be accessed by a variety of application software. - -Finally, from an intellectual-access standpoint, we need to address the -issue of providing access to these multimedia documents in -interdisciplinary environments. We need to examine terminology and -indexing strategies that will allow us to provide access to this material -in a cross-disciplinary way. - -Ronald LARSEN Directions in High-Performance Networking for - Libraries - -The pace at which computing technology has advanced over the past forty -years shows no sign of abating. Roughly speaking, each five-year period -has yielded an order-of-magnitude improvement in price and performance of -computing equipment. No fundamental hurdles are likely to prevent this -pace from continuing for at least the next decade. It is only in the -past five years, though, that computing has become ubiquitous in -libraries, affecting all staff and patrons, directly or indirectly. - -During these same five years, communications rates on the Internet, the -principal academic computing network, have grown from 56 kbps to 1.5 -Mbps, and the NSFNet backbone is now running 45 Mbps. Over the next five -years, communication rates on the backbone are expected to exceed 1 Gbps. -Growth in both the population of network users and the volume of network -traffic has continued to grow geometrically, at rates approaching 15 -percent per month. This flood of capacity and use, likened by some to -"drinking from a firehose," creates immense opportunities and challenges -for libraries. Libraries must anticipate the future implications of this -technology, participate in its development, and deploy it to ensure -access to the world's information resources. - -The infrastructure for the information age is being put in place. -Libraries face strategic decisions about their role in the development, -deployment, and use of this infrastructure. The emerging infrastructure -is much more than computers and communication lines. It is more than the -ability to compute at a remote site, send electronic mail to a peer -across the country, or move a file from one library to another. The next -five years will witness substantial development of the information -infrastructure of the network. - -In order to provide appropriate leadership, library professionals must -have a fundamental understanding of and appreciation for computer -networking, from local area networks to the National Research and -Education Network (NREN). This presentation addresses these -fundamentals, and how they relate to libraries today and in the near -future. - -Edwin BROWNRIGG Electronic Library Visions and Realities - -The electronic library has been a vision desired by many--and rejected by -some--since Vannevar Bush coined the term memex to describe an automated, -intelligent, personal information system. Variations on this vision have -included Ted Nelson's Xanadau, Alan Kay's Dynabook, and Lancaster's -"paperless library," with the most recent incarnation being the -"Knowledge Navigator" described by John Scully of Apple. But the reality -of library service has been less visionary and the leap to the electronic -library has eluded universities, publishers, and information technology -files. - -The Memex Research Institute (MemRI), an independent, nonprofit research -and development organization, has created an Electronic Library Program -of shared research and development in order to make the collective vision -more concrete. The program is working toward the creation of large, -indexed publicly available electronic image collections of published -documents in academic, special, and public libraries. This strategic -plan is the result of the first stage of the program, which has been an -investigation of the information technologies available to support such -an effort, the economic parameters of electronic service compared to -traditional library operations, and the business and political factors -affecting the shift from print distribution to electronic networked -access. - -The strategic plan envisions a combination of publicly searchable access -databases, image (and text) document collections stored on network "file -servers," local and remote network access, and an intellectual property -management-control system. This combination of technology and -information content is defined in this plan as an E-library or E-library -collection. Some participating sponsors are already developing projects -based on MemRI's recommended directions. - -The E-library strategy projected in this plan is a visionary one that can -enable major changes and improvements in academic, public, and special -library service. This vision is, though, one that can be realized with -today's technology. At the same time, it will challenge the political -and social structure within which libraries operate: in academic -libraries, the traditional emphasis on local collections, extending to -accreditation issues; in public libraries, the potential of electronic -branch and central libraries fully available to the public; and for -special libraries, new opportunities for shared collections and networks. - -The environment in which this strategic plan has been developed is, at -the moment, dominated by a sense of library limits. The continued -expansion and rapid growth of local academic library collections is now -clearly at an end. Corporate libraries, and even law libraries, are -faced with operating within a difficult economic climate, as well as with -very active competition from commercial information sources. For -example, public libraries may be seen as a desirable but not critical -municipal service in a time when the budgets of safety and health -agencies are being cut back. - -Further, libraries in general have a very high labor-to-cost ratio in -their budgets, and labor costs are still increasing, notwithstanding -automation investments. It is difficult for libraries to obtain capital, -startup, or seed funding for innovative activities, and those -technology-intensive initiatives that offer the potential of decreased -labor costs can provoke the opposition of library staff. - -However, libraries have achieved some considerable successes in the past -two decades by improving both their service and their credibility within -their organizations--and these positive changes have been accomplished -mostly with judicious use of information technologies. The advances in -computing and information technology have been well-chronicled: the -continuing precipitous drop in computing costs, the growth of the -Internet and private networks, and the explosive increase in publicly -available information databases. - -For example, OCLC has become one of the largest computer network -organizations in the world by creating a cooperative cataloging network -of more than 6,000 libraries worldwide. On-line public access catalogs -now serve millions of users on more than 50,000 dedicated terminals in -the United States alone. The University of California MELVYL on-line -catalog system has now expanded into an index database reference service -and supports more than six million searches a year. And, libraries have -become the largest group of customers of CD-ROM publishing technology; -more than 30,000 optical media publications such as those offered by -InfoTrac and Silver Platter are subscribed to by U.S. libraries. - -This march of technology continues and in the next decade will result in -further innovations that are extremely difficult to predict. What is -clear is that libraries can now go beyond automation of their order files -and catalogs to automation of their collections themselves--and it is -possible to circumvent the fiscal limitations that appear to obtain -today. - -This Electronic Library Strategic Plan recommends a paradigm shift in -library service, and demonstrates the steps necessary to provide improved -library services with limited capacities and operating investments. - -SESSION IV-A - -Anne KENNEY - -The Cornell/Xerox Joint Study in Digital Preservation resulted in the -recording of 1,000 brittle books as 600-dpi digital images and the -production, on demand, of high-quality and archivally sound paper -replacements. The project, which was supported by the Commission on -Preservation and Access, also investigated some of the issues surrounding -scanning, storing, retrieving, and providing access to digital images in -a network environment. - -Anne Kenney will focus on some of the issues surrounding direct scanning -as identified in the Cornell Xerox Project. Among those to be discussed -are: image versus text capture; indexing and access; image-capture -capabilities; a comparison to photocopy and microfilm; production and -cost analysis; storage formats, protocols, and standards; and the use of -this scanning technology for preservation purposes. - -The 600-dpi digital images produced in the Cornell Xerox Project proved -highly acceptable for creating paper replacements of deteriorating -originals. The 1,000 scanned volumes provided an array of image-capture -challenges that are common to nineteenth-century printing techniques and -embrittled material, and that defy the use of text-conversion processes. -These challenges include diminished contrast between text and background, -fragile and deteriorated pages, uneven printing, elaborate type faces, -faint and bold text adjacency, handwritten text and annotations, nonRoman -languages, and a proliferation of illustrated material embedded in text. -The latter category included high-frequency and low-frequency halftones, -continuous tone photographs, intricate mathematical drawings, maps, -etchings, reverse-polarity drawings, and engravings. - -The Xerox prototype scanning system provided a number of important -features for capturing this diverse material. Technicians used multiple -threshold settings, filters, line art and halftone definitions, -autosegmentation, windowing, and software-editing programs to optimize -image capture. At the same time, this project focused on production. -The goal was to make scanning as affordable and acceptable as -photocopying and microfilming for preservation reformatting. A -time-and-cost study conducted during the last three months of this -project confirmed the economic viability of digital scanning, and these -findings will be discussed here. - -From the outset, the Cornell Xerox Project was predicated on the use of -nonproprietary standards and the use of common protocols when standards -did not exist. Digital files were created as TIFF images which were -compressed prior to storage using Group 4 CCITT compression. The Xerox -software is MS DOS based and utilizes off-the shelf programs such as -Microsoft Windows and Wang Image Wizard. The digital library is designed -to be hardware-independent and to provide interchangeability with other -institutions through network connections. Access to the digital files -themselves is two-tiered: Bibliographic records for the computer files -are created in RLIN and Cornell's local system and access into the actual -digital images comprising a book is provided through a document control -structure and a networked image file-server, both of which will be -described. - -The presentation will conclude with a discussion of some of the issues -surrounding the use of this technology as a preservation tool (storage, -refreshing, backup). - -Pamela ANDRE and Judith ZIDAR - -The National Agricultural Library (NAL) has had extensive experience with -raster scanning of printed materials. Since 1987, the Library has -participated in the National Agricultural Text Digitizing Project (NATDP) -a cooperative effort between NAL and forty-five land grant university -libraries. An overview of the project will be presented, giving its -history and NAL's strategy for the future. - -An in-depth discussion of NATDP will follow, including a description of -the scanning process, from the gathering of the printed materials to the -archiving of the electronic pages. The type of equipment required for a -stand-alone scanning workstation and the importance of file management -software will be discussed. Issues concerning the images themselves will -be addressed briefly, such as image format; black and white versus color; -gray scale versus dithering; and resolution. - -Also described will be a study currently in progress by NAL to evaluate -the usefulness of converting microfilm to electronic images in order to -improve access. With the cooperation of Tuskegee University, NAL has -selected three reels of microfilm from a collection of sixty-seven reels -containing the papers, letters, and drawings of George Washington Carver. -The three reels were converted into 3,500 electronic images using a -specialized microfilm scanner. The selection, filming, and indexing of -this material will be discussed. - -Donald WATERS - -Project Open Book, the Yale University Library's effort to convert 10, -000 books from microfilm to digital imagery, is currently in an advanced -state of planning and organization. The Yale Library has selected a -major vendor to serve as a partner in the project and as systems -integrator. In its proposal, the successful vendor helped isolate areas -of risk and uncertainty as well as key issues to be addressed during the -life of the project. The Yale Library is now poised to decide what -material it will convert to digital image form and to seek funding, -initially for the first phase and then for the entire project. - -The proposal that Yale accepted for the implementation of Project Open -Book will provide at the end of three phases a conversion subsystem, -browsing stations distributed on the campus network within the Yale -Library, a subsystem for storing 10,000 books at 200 and 600 dots per -inch, and network access to the image printers. Pricing for the system -implementation assumes the existence of Yale's campus ethernet network -and its high-speed image printers, and includes other requisite hardware -and software, as well as system integration services. Proposed operating -costs include hardware and software maintenance, but do not include -estimates for the facilities management of the storage devices and image -servers. - -Yale selected its vendor partner in a formal process, partly funded by -the Commission for Preservation and Access. Following a request for -proposal, the Yale Library selected two vendors as finalists to work with -Yale staff to generate a detailed analysis of requirements for Project -Open Book. Each vendor used the results of the requirements analysis to -generate and submit a formal proposal for the entire project. This -competitive process not only enabled the Yale Library to select its -primary vendor partner but also revealed much about the state of the -imaging industry, about the varying, corporate commitments to the markets -for imaging technology, and about the varying organizational dynamics -through which major companies are responding to and seeking to develop -these markets. - -Project Open Book is focused specifically on the conversion of images -from microfilm to digital form. The technology for scanning microfilm is -readily available but is changing rapidly. In its project requirements, -the Yale Library emphasized features of the technology that affect the -technical quality of digital image production and the costs of creating -and storing the image library: What levels of digital resolution can be -achieved by scanning microfilm? How does variation in the quality of -microfilm, particularly in film produced to preservation standards, -affect the quality of the digital images? What technologies can an -operator effectively and economically apply when scanning film to -separate two-up images and to control for and correct image -imperfections? How can quality control best be integrated into -digitizing work flow that includes document indexing and storage? - -The actual and expected uses of digital images--storage, browsing, -printing, and OCR--help determine the standards for measuring their -quality. Browsing is especially important, but the facilities available -for readers to browse image documents is perhaps the weakest aspect of -imaging technology and most in need of development. As it defined its -requirements, the Yale Library concentrated on some fundamental aspects -of usability for image documents: Does the system have sufficient -flexibility to handle the full range of document types, including -monographs, multi-part and multivolume sets, and serials, as well as -manuscript collections? What conventions are necessary to identify a -document uniquely for storage and retrieval? Where is the database of -record for storing bibliographic information about the image document? -How are basic internal structures of documents, such as pagination, made -accessible to the reader? How are the image documents physically -presented on the screen to the reader? - -The Yale Library designed Project Open Book on the assumption that -microfilm is more than adequate as a medium for preserving the content of -deteriorated library materials. As planning in the project has advanced, -it is increasingly clear that the challenge of digital image technology -and the key to the success of efforts like Project Open Book is to -provide a means of both preserving and improving access to those -deteriorated materials. - -SESSION IV-B - -George THOMA - -In the use of electronic imaging for document preservation, there are -several issues to consider, such as: ensuring adequate image quality, -maintaining substantial conversion rates (through-put), providing unique -identification for automated access and retrieval, and accommodating -bound volumes and fragile material. - -To maintain high image quality, image processing functions are required -to correct the deficiencies in the scanned image. Some commercially -available systems include these functions, while some do not. The -scanned raw image must be processed to correct contrast deficiencies-- -both poor overall contrast resulting from light print and/or dark -background, and variable contrast resulting from stains and -bleed-through. Furthermore, the scan density must be adequate to allow -legibility of print and sufficient fidelity in the pseudo-halftoned gray -material. Borders or page-edge effects must be removed for both -compactibility and aesthetics. Page skew must be corrected for aesthetic -reasons and to enable accurate character recognition if desired. -Compound images consisting of both two-toned text and gray-scale -illustrations must be processed appropriately to retain the quality of -each. - -SESSION IV-C - -Jean BARONAS - -Standards publications being developed by scientists, engineers, and -business managers in Association for Information and Image Management -(AIIM) standards committees can be applied to electronic image management -(EIM) processes including: document (image) transfer, retrieval and -evaluation; optical disk and document scanning; and document design and -conversion. When combined with EIM system planning and operations, -standards can assist in generating image databases that are -interchangeable among a variety of systems. The applications of -different approaches for image-tagging, indexing, compression, and -transfer often cause uncertainty concerning EIM system compatibility, -calibration, performance, and upward compatibility, until standard -implementation parameters are established. The AIIM standards that are -being developed for these applications can be used to decrease the -uncertainty, successfully integrate imaging processes, and promote "open -systems." AIIM is an accredited American National Standards Institute -(ANSI) standards developer with more than twenty committees comprised of -300 volunteers representing users, vendors, and manufacturers. The -standards publications that are developed in these committees have -national acceptance and provide the basis for international harmonization -in the development of new International Organization for Standardization -(ISO) standards. - -This presentation describes the development of AIIM's EIM standards and a -new effort at AIIM, a database on standards projects in a wide framework -of imaging industries including capture, recording, processing, -duplication, distribution, display, evaluation, and preservation. The -AIIM Imagery Database will cover imaging standards being developed by -many organizations in many different countries. It will contain -standards publications' dates, origins, related national and -international projects, status, key words, and abstracts. The ANSI Image -Technology Standards Board requested that such a database be established, -as did the ISO/International Electrotechnical Commission Joint Task Force -on Imagery. AIIM will take on the leadership role for the database and -coordinate its development with several standards developers. - -Patricia BATTIN - - Characteristics of standards for digital imagery: - - * Nature of digital technology implies continuing volatility. - - * Precipitous standard-setting not possible and probably not - desirable. - - * Standards are a complex issue involving the medium, the - hardware, the software, and the technical capacity for - reproductive fidelity and clarity. - - * The prognosis for reliable archival standards (as defined by - librarians) in the foreseeable future is poor. - - Significant potential and attractiveness of digital technology as a - preservation medium and access mechanism. - - Productive use of digital imagery for preservation requires a - reconceptualizing of preservation principles in a volatile, - standardless world. - - Concept of managing continuing access in the digital environment - rather than focusing on the permanence of the medium and long-term - archival standards developed for the analog world. - - Transition period: How long and what to do? - - * Redefine "archival." - - * Remove the burden of "archival copy" from paper artifacts. - - * Use digital technology for storage, develop management - strategies for refreshing medium, hardware and software. - - * Create acid-free paper copies for transition period backup - until we develop reliable procedures for ensuring continuing - access to digital files. - -SESSION IV-D - -Stuart WEIBEL The Role of SGML Markup in the CORE Project (6) - -The emergence of high-speed telecommunications networks as a basic -feature of the scholarly workplace is driving the demand for electronic -document delivery. Three distinct categories of electronic -publishing/republishing are necessary to support access demands in this -emerging environment: - - 1.) Conversion of paper or microfilm archives to electronic format - 2.) Conversion of electronic files to formats tailored to - electronic retrieval and display - 3.) Primary electronic publishing (materials for which the - electronic version is the primary format) - -OCLC has experimental or product development activities in each of these -areas. Among the challenges that lie ahead is the integration of these -three types of information stores in coherent distributed systems. - -The CORE (Chemistry Online Retrieval Experiment) Project is a model for -the conversion of large text and graphics collections for which -electronic typesetting files are available (category 2). The American -Chemical Society has made available computer typography files dating from -1980 for its twenty journals. This collection of some 250 journal-years -is being converted to an electronic format that will be accessible -through several end-user applications. - -The use of Standard Generalized Markup Language (SGML) offers the means -to capture the structural richness of the original articles in a way that -will support a variety of retrieval, navigation, and display options -necessary to navigate effectively in very large text databases. - -An SGML document consists of text that is marked up with descriptive tags -that specify the function of a given element within the document. As a -formal language construct, an SGML document can be parsed against a -document-type definition (DTD) that unambiguously defines what elements -are allowed and where in the document they can (or must) occur. This -formalized map of article structure allows the user interface design to -be uncoupled from the underlying database system, an important step -toward interoperability. Demonstration of this separability is a part of -the CORE project, wherein user interface designs born of very different -philosophies will access the same database. - -NOTES: - (6) The CORE project is a collaboration among Cornell University's - Mann Library, Bell Communications Research (Bellcore), the American - Chemical Society (ACS), the Chemical Abstracts Service (CAS), and - OCLC. - -Michael LESK The CORE Electronic Chemistry Library - -A major on-line file of chemical journal literature complete with -graphics is being developed to test the usability of fully electronic -access to documents, as a joint project of Cornell University, the -American Chemical Society, the Chemical Abstracts Service, OCLC, and -Bellcore (with additional support from Sun Microsystems, Springer-Verlag, -DigitaI Equipment Corporation, Sony Corporation of America, and Apple -Computers). Our file contains the American Chemical Society's on-line -journals, supplemented with the graphics from the paper publication. The -indexing of the articles from Chemical Abstracts Documents is available -in both image and text format, and several different interfaces can be -used. Our goals are (1) to assess the effectiveness and acceptability of -electronic access to primary journals as compared with paper, and (2) to -identify the most desirable functions of the user interface to an -electronic system of journals, including in particular a comparison of -page-image display with ASCII display interfaces. Early experiments with -chemistry students on a variety of tasks suggest that searching tasks are -completed much faster with any electronic system than with paper, but -that for reading all versions of the articles are roughly equivalent. - -Pamela ANDRE and Judith ZIDAR - -Text conversion is far more expensive and time-consuming than image -capture alone. NAL's experience with optical character recognition (OCR) -will be related and compared with the experience of having text rekeyed. -What factors affect OCR accuracy? How accurate does full text have to be -in order to be useful? How do different users react to imperfect text? -These are questions that will be explored. For many, a service bureau -may be a better solution than performing the work inhouse; this will also -be discussed. - -SESSION VI - -Marybeth PETERS - -Copyright law protects creative works. Protection granted by the law to -authors and disseminators of works includes the right to do or authorize -the following: reproduce the work, prepare derivative works, distribute -the work to the public, and publicly perform or display the work. In -addition, copyright owners of sound recordings and computer programs have -the right to control rental of their works. These rights are not -unlimited; there are a number of exceptions and limitations. - -An electronic environment places strains on the copyright system. -Copyright owners want to control uses of their work and be paid for any -use; the public wants quick and easy access at little or no cost. The -marketplace is working in this area. Contracts, guidelines on electronic -use, and collective licensing are in use and being refined. - -Issues concerning the ability to change works without detection are more -difficult to deal with. Questions concerning the integrity of the work -and the status of the changed version under the copyright law are to be -addressed. These are public policy issues which require informed -dialogue. - - - *** *** *** ****** *** *** *** - - - Appendix III: DIRECTORY OF PARTICIPANTS - - -PRESENTERS: - - Pamela Q.J. Andre - Associate Director, Automation - National Agricultural Library - 10301 Baltimore Boulevard - Beltsville, MD 20705-2351 - Phone: (301) 504-6813 - Fax: (301) 504-7473 - E-mail: INTERNET: PANDRE@ASRR.ARSUSDA.GOV - - Jean Baronas, Senior Manager - Department of Standards and Technology - Association for Information and Image Management (AIIM) - 1100 Wayne Avenue, Suite 1100 - Silver Spring, MD 20910 - Phone: (301) 587-8202 - Fax: (301) 587-2711 - - Patricia Battin, President - The Commission on Preservation and Access - 1400 16th Street, N.W. - Suite 740 - Washington, DC 20036-2217 - Phone: (202) 939-3400 - Fax: (202) 939-3407 - E-mail: CPA@GWUVM.BITNET - - Howard Besser - Centre Canadien d'Architecture - (Canadian Center for Architecture) - 1920, rue Baile - Montreal, Quebec H3H 2S6 - CANADA - Phone: (514) 939-7001 - Fax: (514) 939-7020 - E-mail: howard@lis.pitt.edu - - Edwin B. Brownrigg, Executive Director - Memex Research Institute - 422 Bonita Avenue - Roseville, CA 95678 - Phone: (916) 784-2298 - Fax: (916) 786-7559 - E-mail: BITNET: MEMEX@CALSTATE.2 - - Eric M. Calaluca, Vice President - Chadwyck-Healey, Inc. - 1101 King Street - Alexandria, VA 223l4 - Phone: (800) 752-05l5 - Fax: (703) 683-7589 - - James Daly - 4015 Deepwood Road - Baltimore, MD 21218-1404 - Phone: (410) 235-0763 - - Ricky Erway, Associate Coordinator - American Memory - Library of Congress - Phone: (202) 707-6233 - Fax: (202) 707-3764 - - Carl Fleischhauer, Coordinator - American Memory - Library of Congress - Phone: (202) 707-6233 - Fax: (202) 707-3764 - - Joanne Freeman - 2000 Jefferson Park Avenue, No. 7 - Charlottesville, VA 22903 - - Prosser Gifford - Director for Scholarly Programs - Library of Congress - Phone: (202) 707-1517 - Fax: (202) 707-9898 - E-mail: pgif@seq1.loc.gov - - Jacqueline Hess, Director - National Demonstration Laboratory - for Interactive Information Technologies - Library of Congress - Phone: (202) 707-4157 - Fax: (202) 707-2829 - - Susan Hockey, Director - Center for Electronic Texts in the Humanities (CETH) - Alexander Library - Rutgers University - 169 College Avenue - New Brunswick, NJ 08903 - Phone: (908) 932-1384 - Fax: (908) 932-1386 - E-mail: hockey@zodiac.rutgers.edu - - William L. Hooton, Vice President - Business & Technical Development - Imaging & Information Systems Group - I-NET - 6430 Rockledge Drive, Suite 400 - Bethesda, MD 208l7 - Phone: (301) 564-6750 - Fax: (513) 564-6867 - - Anne R. Kenney, Associate Director - Department of Preservation and Conservation - 701 Olin Library - Cornell University - Ithaca, NY 14853 - Phone: (607) 255-6875 - Fax: (607) 255-9346 - E-mail: LYDY@CORNELLA.BITNET - - Ronald L. Larsen - Associate Director for Information Technology - University of Maryland at College Park - Room B0224, McKeldin Library - College Park, MD 20742-7011 - Phone: (301) 405-9194 - Fax: (301) 314-9865 - E-mail: rlarsen@libr.umd.edu - - Maria L. Lebron, Managing Editor - The Online Journal of Current Clinical Trials - l333 H Street, N.W. - Washington, DC 20005 - Phone: (202) 326-6735 - Fax: (202) 842-2868 - E-mail: PUBSAAAS@GWUVM.BITNET - - Michael Lesk, Executive Director - Computer Science Research - Bell Communications Research, Inc. - Rm 2A-385 - 445 South Street - Morristown, NJ 07960-l9l0 - Phone: (201) 829-4070 - Fax: (201) 829-5981 - E-mail: lesk@bellcore.com (Internet) or bellcore!lesk (uucp) - - Clifford A. Lynch - Director, Library Automation - University of California, - Office of the President - 300 Lakeside Drive, 8th Floor - Oakland, CA 94612-3350 - Phone: (510) 987-0522 - Fax: (510) 839-3573 - E-mail: calur@uccmvsa - - Avra Michelson - National Archives and Records Administration - NSZ Rm. 14N - 7th & Pennsylvania, N.W. - Washington, D.C. 20408 - Phone: (202) 501-5544 - Fax: (202) 501-5533 - E-mail: tmi@cu.nih.gov - - Elli Mylonas, Managing Editor - Perseus Project - Department of the Classics - Harvard University - 319 Boylston Hall - Cambridge, MA 02138 - Phone: (617) 495-9025, (617) 495-0456 (direct) - Fax: (617) 496-8886 - E-mail: Elli@IKAROS.Harvard.EDU or elli@wjh12.harvard.edu - - David Woodley Packard - Packard Humanities Institute - 300 Second Street, Suite 201 - Los Altos, CA 94002 - Phone: (415) 948-0150 (PHI) - Fax: (415) 948-5793 - - Lynne K. Personius, Assistant Director - Cornell Information Technologies for - Scholarly Information Sources - 502 Olin Library - Cornell University - Ithaca, NY 14853 - Phone: (607) 255-3393 - Fax: (607) 255-9346 - E-mail: JRN@CORNELLC.BITNET - - Marybeth Peters - Policy Planning Adviser to the - Register of Copyrights - Library of Congress - Office LM 403 - Phone: (202) 707-8350 - Fax: (202) 707-8366 - - C. Michael Sperberg-McQueen - Editor, Text Encoding Initiative - Computer Center (M/C 135) - University of Illinois at Chicago - Box 6998 - Chicago, IL 60680 - Phone: (312) 413-0317 - Fax: (312) 996-6834 - E-mail: u35395@uicvm..cc.uic.edu or u35395@uicvm.bitnet - - George R. Thoma, Chief - Communications Engineering Branch - National Library of Medicine - 8600 Rockville Pike - Bethesda, MD 20894 - Phone: (301) 496-4496 - Fax: (301) 402-0341 - E-mail: thoma@lhc.nlm.nih.gov - - Dorothy Twohig, Editor - The Papers of George Washington - 504 Alderman Library - University of Virginia - Charlottesville, VA 22903-2498 - Phone: (804) 924-0523 - Fax: (804) 924-4337 - - Susan H. Veccia, Team leader - American Memory, User Evaluation - Library of Congress - American Memory Evaluation Project - Phone: (202) 707-9104 - Fax: (202) 707-3764 - E-mail: svec@seq1.loc.gov - - Donald J. Waters, Head - Systems Office - Yale University Library - New Haven, CT 06520 - Phone: (203) 432-4889 - Fax: (203) 432-7231 - E-mail: DWATERS@YALEVM.BITNET or DWATERS@YALEVM.YCC.YALE.EDU - - Stuart Weibel, Senior Research Scientist - OCLC - 6565 Frantz Road - Dublin, OH 43017 - Phone: (614) 764-608l - Fax: (614) 764-2344 - E-mail: INTERNET: Stu@rsch.oclc.org - - Robert G. Zich - Special Assistant to the Associate Librarian - for Special Projects - Library of Congress - Phone: (202) 707-6233 - Fax: (202) 707-3764 - E-mail: rzic@seq1.loc.gov - - Judith A. Zidar, Coordinator - National Agricultural Text Digitizing Program - Information Systems Division - National Agricultural Library - 10301 Baltimore Boulevard - Beltsville, MD 20705-2351 - Phone: (301) 504-6813 or 504-5853 - Fax: (301) 504-7473 - E-mail: INTERNET: JZIDAR@ASRR.ARSUSDA.GOV - - -OBSERVERS: - - Helen Aguera, Program Officer - Division of Research - Room 318 - National Endowment for the Humanities - 1100 Pennsylvania Avenue, N.W. - Washington, D.C. 20506 - Phone: (202) 786-0358 - Fax: (202) 786-0243 - - M. Ellyn Blanton, Deputy Director - National Demonstration Laboratory - for Interactive Information Technologies - Library of Congress - Phone: (202) 707-4157 - Fax: (202) 707-2829 - - Charles M. Dollar - National Archives and Records Administration - NSZ Rm. 14N - 7th & Pennsylvania, N.W. - Washington, DC 20408 - Phone: (202) 501-5532 - Fax: (202) 501-5512 - - Jeffrey Field, Deputy to the Director - Division of Preservation and Access - Room 802 - National Endowment for the Humanities - 1100 Pennsylvania Avenue, N.W. - Washington, DC 20506 - Phone: (202) 786-0570 - Fax: (202) 786-0243 - - Lorrin Garson - American Chemical Society - Research and Development Department - 1155 16th Street, N.W. - Washington, D.C. 20036 - Phone: (202) 872-4541 - Fax: E-mail: INTERNET: LRG96@ACS.ORG - - William M. Holmes, Jr. - National Archives and Records Administration - NSZ Rm. 14N - 7th & Pennsylvania, N.W. - Washington, DC 20408 - Phone: (202) 501-5540 - Fax: (202) 501-5512 - E-mail: WHOLMES@AMERICAN.EDU - - Sperling Martin - Information Resource Management - 20030 Doolittle Street - Gaithersburg, MD 20879 - Phone: (301) 924-1803 - - Michael Neuman, Director - The Center for Text and Technology - Academic Computing Center - 238 Reiss Science Building - Georgetown University - Washington, DC 20057 - Phone: (202) 687-6096 - Fax: (202) 687-6003 - E-mail: neuman@guvax.bitnet, neuman@guvax.georgetown.edu - - Barbara Paulson, Program Officer - Division of Preservation and Access - Room 802 - National Endowment for the Humanities - 1100 Pennsylvania Avenue, N.W. - Washington, DC 20506 - Phone: (202) 786-0577 - Fax: (202) 786-0243 - - Allen H. Renear - Senior Academic Planning Analyst - Brown University Computing and Information Services - 115 Waterman Street - Campus Box 1885 - Providence, R.I. 02912 - Phone: (401) 863-7312 - Fax: (401) 863-7329 - E-mail: BITNET: Allen@BROWNVM or - INTERNET: Allen@brownvm.brown.edu - - Susan M. Severtson, President - Chadwyck-Healey, Inc. - 1101 King Street - Alexandria, VA 223l4 - Phone: (800) 752-05l5 - Fax: (703) 683-7589 - - Frank Withrow - U.S. Department of Education - 555 New Jersey Avenue, N.W. - Washington, DC 20208-5644 - Phone: (202) 219-2200 - Fax: (202) 219-2106 - - -(LC STAFF) - - Linda L. Arret - Machine-Readable Collections Reading Room LJ 132 - (202) 707-1490 - - John D. Byrum, Jr. - Descriptive Cataloging Division LM 540 - (202) 707-5194 - - Mary Jane Cavallo - Science and Technology Division LA 5210 - (202) 707-1219 - - Susan Thea David - Congressional Research Service LM 226 - (202) 707-7169 - - Robert Dierker - Senior Adviser for Multimedia Activities LM 608 - (202) 707-6151 - - William W. Ellis - Associate Librarian for Science and Technology LM 611 - (202) 707-6928 - - Ronald Gephart - Manuscript Division LM 102 - (202) 707-5097 - - James Graber - Information Technology Services LM G51 - (202) 707-9628 - - Rich Greenfield - American Memory LM 603 - (202) 707-6233 - - Rebecca Guenther - Network Development LM 639 - (202) 707-5092 - - Kenneth E. Harris - Preservation LM G21 - (202) 707-5213 - - Staley Hitchcock - Manuscript Division LM 102 - (202) 707-5383 - - Bohdan Kantor - Office of Special Projects LM 612 - (202) 707-0180 - - John W. Kimball, Jr - Machine-Readable Collections Reading Room LJ 132 - (202) 707-6560 - - Basil Manns - Information Technology Services LM G51 - (202) 707-8345 - - Sally Hart McCallum - Network Development LM 639 - (202) 707-6237 - - Dana J. Pratt - Publishing Office LM 602 - (202) 707-6027 - - Jane Riefenhauser - American Memory LM 603 - (202) 707-6233 - - William Z. Schenck - Collections Development LM 650 - (202) 707-7706 - - Chandru J. Shahani - Preservation Research and Testing Office (R&T) LM G38 - (202) 707-5607 - - William J. Sittig - Collections Development LM 650 - (202) 707-7050 - - Paul Smith - Manuscript Division LM 102 - (202) 707-5097 - - James L. Stevens - Information Technology Services LM G51 - (202) 707-9688 - - Karen Stuart - Manuscript Division LM 130 - (202) 707-5389 - - Tamara Swora - Preservation Microfilming Office LM G05 - (202) 707-6293 - - Sarah Thomas - Collections Cataloging LM 642 - (202) 707-5333 - - - END - ************************************************************* - -Note: This file has been edited for use on computer networks. This -editing required the removal of diacritics, underlining, and fonts such -as italics and bold. - -kde 11/92 - -[A few of the italics (when used for emphasis) were replaced by CAPS mh] - -*End of The Project Gutenberg Etext of LOC WORKSHOP ON ELECTRONIC ETEXTS - diff --git a/libs/zlibng/test/data/paper-100k.pdf b/libs/zlibng/test/data/paper-100k.pdf deleted file mode 100644 index b3325e4a2bb578419d6c7fa412aaa78d493ff274..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102400 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 f+ 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 - -#include -#include -#include -#include - -#define TESTFILE "foo.gz" - -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - -static const char hello[] = "hello, hello!"; -/* "hello world" would be more standard, but the repeated "hello" - * stresses the compression code better, sorry... - */ - -static const char dictionary[] = "hello"; -static unsigned long dictId = 0; /* Adler32 value of the dictionary */ - - -void test_compress (unsigned char *compr, z_size_t comprLen,unsigned char *uncompr, z_size_t uncomprLen); -void test_gzio (const char *fname, unsigned char *uncompr, z_size_t uncomprLen); -void test_deflate (unsigned char *compr, size_t comprLen); -void test_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen); -void test_large_deflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen, int zng_params); -void test_large_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen); -void test_flush (unsigned char *compr, z_size_t *comprLen); -void test_sync (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen); -void test_dict_deflate (unsigned char *compr, size_t comprLen); -void test_dict_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen); -int main (int argc, char *argv[]); - - -static alloc_func zalloc = NULL; -static free_func zfree = NULL; - -/* =========================================================================== - * Test compress() and uncompress() - */ -void test_compress(unsigned char *compr, z_size_t comprLen, unsigned char *uncompr, z_size_t uncomprLen) { - int err; - size_t len = strlen(hello)+1; - - err = PREFIX(compress)(compr, &comprLen, (const unsigned char*)hello, (z_size_t)len); - CHECK_ERR(err, "compress"); - - strcpy((char*)uncompr, "garbage"); - - err = PREFIX(uncompress)(uncompr, &uncomprLen, compr, comprLen); - CHECK_ERR(err, "uncompress"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad uncompress\n"); - exit(1); - } else { - printf("uncompress(): %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test read/write of .gz files - */ -void test_gzio(const char *fname, unsigned char *uncompr, z_size_t uncomprLen) { -#ifdef NO_GZCOMPRESS - fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); -#else - int err; - size_t read; - size_t len = strlen(hello)+1; - gzFile file; - z_off64_t pos; - z_off64_t comprLen; - - /* Write gz file with test data */ - file = PREFIX(gzopen)(fname, "wb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } - /* Write hello, hello! using gzputs and gzprintf */ - PREFIX(gzputc)(file, 'h'); - if (PREFIX(gzputs)(file, "ello") != 4) { - fprintf(stderr, "gzputs err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } - if (PREFIX(gzprintf)(file, ", %s!", "hello") != 8) { - fprintf(stderr, "gzprintf err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } - /* Write string null-teriminator using gzseek */ - if (PREFIX(gzseek)(file, 1L, SEEK_CUR) < 0) - { - fprintf(stderr, "gzseek error, gztell=%ld\n", (long)PREFIX(gztell)(file)); - exit(1); - } - /* Write hello, hello! using gzfwrite using best compression level */ - if (PREFIX(gzsetparams)(file, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY) != Z_OK) { - fprintf(stderr, "gzsetparams err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } - if (PREFIX(gzfwrite)(hello, len, 1, file) == 0) { - fprintf(stderr, "gzfwrite err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } - /* Flush compressed bytes to file */ - if (PREFIX(gzflush)(file, Z_SYNC_FLUSH) != Z_OK) { - fprintf(stderr, "gzflush err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } - comprLen = PREFIX(gzoffset)(file); - if (comprLen <= 0) { - fprintf(stderr, "gzoffset err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } - PREFIX(gzclose)(file); - - /* Open gz file we previously wrote */ - file = PREFIX(gzopen)(fname, "rb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } - /* Read uncompressed data - hello, hello! string twice */ - strcpy((char*)uncompr, "garbages"); - if (PREFIX(gzread)(file, uncompr, (unsigned)uncomprLen) != (int)(len + len)) { - fprintf(stderr, "gzread err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); - exit(1); - } else { - printf("gzread(): %s\n", (char*)uncompr); - } - /* Check position at the end of the gz file */ - if (PREFIX(gzeof)(file) != 1) { - fprintf(stderr, "gzeof err: not reporting end of stream\n"); - exit(1); - } - /* Seek backwards mid-string and check char reading with gzgetc and gzungetc */ - pos = PREFIX(gzseek)(file, -22L, SEEK_CUR); - if (pos != 6 || PREFIX(gztell)(file) != pos) { - fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", - (long)pos, (long)PREFIX(gztell)(file)); - exit(1); - } - if (PREFIX(gzgetc)(file) != ' ') { - fprintf(stderr, "gzgetc error\n"); - exit(1); - } - if (PREFIX(gzungetc)(' ', file) != ' ') { - fprintf(stderr, "gzungetc error\n"); - exit(1); - } - /* Read first hello, hello! string with gzgets */ - strcpy((char*)uncompr, "garbages"); - PREFIX(gzgets)(file, (char*)uncompr, (int)uncomprLen); - if (strlen((char*)uncompr) != 7) { /* " hello!" */ - fprintf(stderr, "gzgets err after gzseek: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello + 6)) { - fprintf(stderr, "bad gzgets after gzseek\n"); - exit(1); - } else { - printf("gzgets() after gzseek: %s\n", (char*)uncompr); - } - /* Seek to second hello, hello! string */ - pos = PREFIX(gzseek)(file, 14L, SEEK_SET); - if (pos != 14 || PREFIX(gztell)(file) != pos) { - fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", - (long)pos, (long)PREFIX(gztell)(file)); - exit(1); - } - /* Check position not at end of file */ - if (PREFIX(gzeof)(file) != 0) { - fprintf(stderr, "gzeof err: reporting end of stream\n"); - exit(1); - } - /* Read first hello, hello! string with gzfread */ - strcpy((char*)uncompr, "garbages"); - read = PREFIX(gzfread)(uncompr, uncomprLen, 1, file); - if (strcmp((const char *)uncompr, hello) != 0) { - fprintf(stderr, "bad gzgets\n"); - exit(1); - } else { - printf("gzgets(): %s\n", (char*)uncompr); - } - pos = PREFIX(gzoffset)(file); - if (pos < 0 || pos != (comprLen + 10)) { - fprintf(stderr, "gzoffset err: wrong offset at end\n"); - exit(1); - } - /* Trigger an error and clear it with gzclearerr */ - PREFIX(gzfread)(uncompr, (size_t)-1, (size_t)-1, file); - PREFIX(gzerror)(file, &err); - if (err == 0) { - fprintf(stderr, "gzerror err: no error returned\n"); - exit(1); - } - PREFIX(gzclearerr)(file); - PREFIX(gzerror)(file, &err); - if (err != 0) { - fprintf(stderr, "gzclearerr err: not zero %d\n", err); - exit(1); - } - - PREFIX(gzclose)(file); - - if (PREFIX(gzclose)(NULL) != Z_STREAM_ERROR) { - fprintf(stderr, "gzclose unexpected return when handle null\n"); - exit(1); - } - (void)read; -#endif -} - -/* =========================================================================== - * Test deflate() with small buffers - */ -void test_deflate(unsigned char *compr, size_t comprLen) { - PREFIX3(stream) c_stream; /* compression stream */ - int err; - size_t len = strlen(hello)+1; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (void *)0; - c_stream.total_in = 0; - c_stream.total_out = 0; - - err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.next_out = compr; - - while (c_stream.total_in != len && c_stream.total_out < comprLen) { - c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ - err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - } - /* Finish the stream, still forcing small buffers: */ - for (;;) { - c_stream.avail_out = 1; - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - } - - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with small buffers - */ -void test_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) { - int err; - PREFIX3(stream) d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (void *)0; - - d_stream.next_in = compr; - d_stream.avail_in = 0; - d_stream.next_out = uncompr; - d_stream.total_in = 0; - d_stream.total_out = 0; - - err = PREFIX(inflateInit)(&d_stream); - CHECK_ERR(err, "inflateInit"); - - while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { - d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ - err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "inflate"); - } - - err = PREFIX(inflateEnd)(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate\n"); - exit(1); - } else { - printf("inflate(): %s\n", (char *)uncompr); - } -} - -static unsigned int diff; - -/* =========================================================================== - * Test deflate() with large buffers and dynamic change of compression level - */ -void test_large_deflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen, int zng_params) { - PREFIX3(stream) c_stream; /* compression stream */ - int err; -#ifndef ZLIB_COMPAT - int level = -1; - int strategy = -1; - zng_deflate_param_value params[2]; - - params[0].param = Z_DEFLATE_LEVEL; - params[0].buf = &level; - params[0].size = sizeof(level); - - params[1].param = Z_DEFLATE_STRATEGY; - params[1].buf = &strategy; - params[1].size = sizeof(strategy); -#endif - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (void *)0; - - err = PREFIX(deflateInit)(&c_stream, Z_BEST_SPEED); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_out = compr; - c_stream.avail_out = (unsigned int)comprLen; - - /* At this point, uncompr is still mostly zeroes, so it should compress - * very well: - */ - c_stream.next_in = uncompr; - c_stream.avail_in = (unsigned int)uncomprLen; - err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - if (c_stream.avail_in != 0) { - fprintf(stderr, "deflate not greedy\n"); - exit(1); - } - - /* Feed in already compressed data and switch to no compression: */ - if (zng_params) { -#ifndef ZLIB_COMPAT - zng_deflateGetParams(&c_stream, params, sizeof(params) / sizeof(params[0])); - if (level != Z_BEST_SPEED) { - fprintf(stderr, "Expected compression level Z_BEST_SPEED, got %d\n", level); - exit(1); - } - if (strategy != Z_DEFAULT_STRATEGY) { - fprintf(stderr, "Expected compression strategy Z_DEFAULT_STRATEGY, got %d\n", strategy); - exit(1); - } - level = Z_NO_COMPRESSION; - strategy = Z_DEFAULT_STRATEGY; - zng_deflateSetParams(&c_stream, params, sizeof(params) / sizeof(params[0])); -#else - fprintf(stderr, "test_large_deflate() called with zng_params=1 in compat mode\n"); - exit(1); -#endif - } else { - PREFIX(deflateParams)(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); - } - c_stream.next_in = compr; - diff = (unsigned int)(c_stream.next_out - compr); - c_stream.avail_in = diff; - err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - /* Switch back to compressing mode: */ - if (zng_params) { -#ifndef ZLIB_COMPAT - level = -1; - strategy = -1; - zng_deflateGetParams(&c_stream, params, sizeof(params) / sizeof(params[0])); - if (level != Z_NO_COMPRESSION) { - fprintf(stderr, "Expected compression level Z_NO_COMPRESSION, got %d\n", level); - exit(1); - } - if (strategy != Z_DEFAULT_STRATEGY) { - fprintf(stderr, "Expected compression strategy Z_DEFAULT_STRATEGY, got %d\n", strategy); - exit(1); - } - level = Z_BEST_COMPRESSION; - strategy = Z_FILTERED; - zng_deflateSetParams(&c_stream, params, sizeof(params) / sizeof(params[0])); -#else - fprintf(stderr, "test_large_deflate() called with zng_params=1 in compat mode\n"); - exit(1); -#endif - } else { - PREFIX(deflateParams)(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); - } - c_stream.next_in = uncompr; - c_stream.avail_in = (unsigned int)uncomprLen; - err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with large buffers - */ -void test_large_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) { - int err; - PREFIX3(stream) d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (void *)0; - - d_stream.next_in = compr; - d_stream.avail_in = (unsigned int)comprLen; - d_stream.total_in = 0; - d_stream.total_out = 0; - - err = PREFIX(inflateInit)(&d_stream); - CHECK_ERR(err, "inflateInit"); - - for (;;) { - d_stream.next_out = uncompr; /* discard the output */ - d_stream.avail_out = (unsigned int)uncomprLen; - err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "large inflate"); - } - - err = PREFIX(inflateEnd)(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (d_stream.total_out != 2*uncomprLen + diff) { - fprintf(stderr, "bad large inflate: %" PRIu64 "\n", (uint64_t)d_stream.total_out); - exit(1); - } else { - printf("large_inflate(): OK\n"); - } -} - -/* =========================================================================== - * Test deflate() with full flush - */ -void test_flush(unsigned char *compr, z_size_t *comprLen) { - PREFIX3(stream) c_stream; /* compression stream */ - int err; - unsigned int len = (unsigned int)strlen(hello)+1; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (void *)0; - - err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.next_out = compr; - c_stream.avail_in = 3; - c_stream.avail_out = (unsigned int)*comprLen; - err = PREFIX(deflate)(&c_stream, Z_FULL_FLUSH); - CHECK_ERR(err, "deflate"); - - compr[3]++; /* force an error in first compressed block */ - c_stream.avail_in = len - 3; - - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - CHECK_ERR(err, "deflate"); - } - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - *comprLen = (z_size_t)c_stream.total_out; -} - -/* =========================================================================== - * Test inflateSync() - */ -void test_sync(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) { - int err; - PREFIX3(stream) d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (void *)0; - - d_stream.next_in = compr; - d_stream.avail_in = 2; /* just read the zlib header */ - - err = PREFIX(inflateInit)(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (unsigned int)uncomprLen; - - err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); - CHECK_ERR(err, "inflate"); - - d_stream.avail_in = (unsigned int)comprLen-2; /* read all compressed data */ - err = PREFIX(inflateSync)(&d_stream); /* but skip the damaged part */ - CHECK_ERR(err, "inflateSync"); - - err = PREFIX(inflate)(&d_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "inflate should report Z_STREAM_END\n"); - exit(1); - } - err = PREFIX(inflateEnd)(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - printf("after inflateSync(): hel%s\n", (char *)uncompr); -} - -/* =========================================================================== - * Test deflate() with preset dictionary - */ -void test_dict_deflate(unsigned char *compr, size_t comprLen) { - PREFIX3(stream) c_stream; /* compression stream */ - int err; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (void *)0; - c_stream.adler = 0; - - err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - err = PREFIX(deflateSetDictionary)(&c_stream, - (const unsigned char*)dictionary, (int)sizeof(dictionary)); - CHECK_ERR(err, "deflateSetDictionary"); - - dictId = c_stream.adler; - c_stream.next_out = compr; - c_stream.avail_out = (unsigned int)comprLen; - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.avail_in = (unsigned int)strlen(hello)+1; - - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with a preset dictionary - */ -void test_dict_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) { - int err; - PREFIX3(stream) d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage garbage garbage"); - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (void *)0; - d_stream.adler = 0; - d_stream.next_in = compr; - d_stream.avail_in = (unsigned int)comprLen; - - err = PREFIX(inflateInit)(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (unsigned int)uncomprLen; - - for (;;) { - err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - if (err == Z_NEED_DICT) { - if (d_stream.adler != dictId) { - fprintf(stderr, "unexpected dictionary"); - exit(1); - } - err = PREFIX(inflateSetDictionary)(&d_stream, (const unsigned char*)dictionary, - (int)sizeof(dictionary)); - } - CHECK_ERR(err, "inflate with dict"); - } - - err = PREFIX(inflateEnd)(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strncmp((char*)uncompr, hello, sizeof(hello))) { - fprintf(stderr, "bad inflate with dict\n"); - exit(1); - } else { - printf("inflate with dictionary: %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test deflateBound() with small buffers - */ -void test_deflate_bound(void) { - PREFIX3(stream) c_stream; /* compression stream */ - int err; - unsigned int len = (unsigned int)strlen(hello)+1; - int estimateLen = 0; - unsigned char *outBuf = NULL; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - c_stream.avail_in = len; - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.avail_out = 0; - c_stream.next_out = outBuf; - - err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - /* calculate actual output length and update structure */ - estimateLen = PREFIX(deflateBound)(&c_stream, len); - outBuf = malloc(estimateLen); - - if (outBuf != NULL) { - /* update zlib configuration */ - c_stream.avail_out = estimateLen; - c_stream.next_out = outBuf; - - /* do the compression */ - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) { - printf("deflateBound(): OK\n"); - } else { - CHECK_ERR(err, "deflate"); - } - } - - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - free(outBuf); -} - -/* =========================================================================== - * Test deflateCopy() with small buffers - */ -void test_deflate_copy(unsigned char *compr, size_t comprLen) { - PREFIX3(stream) c_stream, c_stream_copy; /* compression stream */ - int err; - size_t len = strlen(hello)+1; - - memset(&c_stream, 0, sizeof(c_stream)); - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.next_out = compr; - - while (c_stream.total_in != len && c_stream.total_out < comprLen) { - c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ - err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - } - - /* Finish the stream, still forcing small buffers: */ - for (;;) { - c_stream.avail_out = 1; - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - } - - err = PREFIX(deflateCopy)(&c_stream_copy, &c_stream); - CHECK_ERR(err, "deflate_copy"); - - if (c_stream.state->status == c_stream_copy.state->status) { - printf("deflate_copy(): OK\n"); - } - - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd original"); - - err = PREFIX(deflateEnd)(&c_stream_copy); - CHECK_ERR(err, "deflateEnd copy"); -} - -/* =========================================================================== - * Test deflateGetDictionary() with small buffers - */ -void test_deflate_get_dict(unsigned char *compr, size_t comprLen) { - PREFIX3(stream) c_stream; /* compression stream */ - int err; - unsigned char *dictNew = NULL; - unsigned int *dictLen; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_out = compr; - c_stream.avail_out = (uInt)comprLen; - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.avail_in = (unsigned int)strlen(hello)+1; - - err = PREFIX(deflate)(&c_stream, Z_FINISH); - - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - - dictNew = calloc(256, 1); - dictLen = (unsigned int *)calloc(4, 1); - err = PREFIX(deflateGetDictionary)(&c_stream, dictNew, dictLen); - - CHECK_ERR(err, "deflateGetDictionary"); - if (err == Z_OK) { - printf("deflateGetDictionary(): %s\n", dictNew); - } - - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - free(dictNew); - free(dictLen); -} - -/* =========================================================================== - * Test deflatePending() with small buffers - */ -void test_deflate_pending(unsigned char *compr, size_t comprLen) { - PREFIX3(stream) c_stream; /* compression stream */ - int err; - int *bits = calloc(256, 1); - unsigned *ped = calloc(256, 1); - size_t len = strlen(hello)+1; - - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.next_out = compr; - - while (c_stream.total_in != len && c_stream.total_out < comprLen) { - c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ - err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - } - - err = PREFIX(deflatePending)(&c_stream, ped, bits); - CHECK_ERR(err, "deflatePending"); - - if (*bits >= 0 && *bits <= 7) { - printf("deflatePending(): OK\n"); - } else { - printf("deflatePending(): error\n"); - } - - /* Finish the stream, still forcing small buffers: */ - for (;;) { - c_stream.avail_out = 1; - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - } - - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - free(bits); - free(ped); -} - -/* =========================================================================== - * Test deflatePrime() wrapping gzip around deflate stream - */ -void test_deflate_prime(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) { - PREFIX3(stream) c_stream; /* compression stream */ - PREFIX3(stream) d_stream; /* decompression stream */ - int err; - size_t len = strlen(hello)+1; - uint32_t crc = 0; - - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - /* Raw deflate windowBits is -15 */ - err = PREFIX(deflateInit2)(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY); - CHECK_ERR(err, "deflateInit2"); - - /* Gzip magic number */ - err = PREFIX(deflatePrime)(&c_stream, 16, 0x8b1f); - CHECK_ERR(err, "deflatePrime"); - /* Gzip compression method (deflate) */ - err = PREFIX(deflatePrime)(&c_stream, 8, 0x08); - CHECK_ERR(err, "deflatePrime"); - /* Gzip flags (one byte, using two odd bit calls) */ - err = PREFIX(deflatePrime)(&c_stream, 3, 0x0); - CHECK_ERR(err, "deflatePrime"); - err = PREFIX(deflatePrime)(&c_stream, 5, 0x0); - CHECK_ERR(err, "deflatePrime"); - /* Gzip modified time */ - err = PREFIX(deflatePrime)(&c_stream, 32, 0x0); - CHECK_ERR(err, "deflatePrime"); - /* Gzip extra flags */ - err = PREFIX(deflatePrime)(&c_stream, 8, 0x0); - CHECK_ERR(err, "deflatePrime"); - /* Gzip operating system */ - err = PREFIX(deflatePrime)(&c_stream, 8, 255); - CHECK_ERR(err, "deflatePrime"); - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.avail_in = (uint32_t)len; - c_stream.next_out = compr; - c_stream.avail_out = (uint32_t)comprLen; - - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) - CHECK_ERR(err, "deflate"); - - /* Gzip uncompressed data crc32 */ - crc = PREFIX(crc32)(0, (const uint8_t *)hello, (uint32_t)len); - err = PREFIX(deflatePrime)(&c_stream, 32, crc); - CHECK_ERR(err, "deflatePrime"); - /* Gzip uncompressed data length */ - err = PREFIX(deflatePrime)(&c_stream, 32, (uint32_t)len); - CHECK_ERR(err, "deflatePrime"); - - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (void *)0; - - d_stream.next_in = compr; - d_stream.avail_in = (uint32_t)c_stream.total_out; - d_stream.next_out = uncompr; - d_stream.avail_out = (uint32_t)uncomprLen; - d_stream.total_in = 0; - d_stream.total_out = 0; - - /* Inflate with gzip header */ - err = PREFIX(inflateInit2)(&d_stream, MAX_WBITS + 32); - CHECK_ERR(err, "inflateInit"); - - err = PREFIX(inflate)(&d_stream, Z_FINISH); - if (err != Z_BUF_ERROR) { - CHECK_ERR(err, "inflate"); - } - - err = PREFIX(inflateEnd)(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((const char *)uncompr, hello) != 0) { - fprintf(stderr, "bad deflatePrime\n"); - exit(1); - } - - if (err == Z_OK) { - printf("deflatePrime(): OK\n"); - } -} - -/* =========================================================================== - * Test deflateSetHeader() with small buffers - */ -void test_deflate_set_header(unsigned char *compr, size_t comprLen) { - PREFIX(gz_header) *head = calloc(1, sizeof(PREFIX(gz_header))); - PREFIX3(stream) c_stream; /* compression stream */ - int err; - size_t len = strlen(hello)+1; - - - if (head == NULL) { - printf("out of memory\n"); - exit(1); - } - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - /* gzip */ - err = PREFIX(deflateInit2)(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY); - CHECK_ERR(err, "deflateInit2"); - - head->text = 1; - err = PREFIX(deflateSetHeader)(&c_stream, head); - CHECK_ERR(err, "deflateSetHeader"); - if (err == Z_OK) { - printf("deflateSetHeader(): OK\n"); - } - - c_stream.next_in = (unsigned char *)hello; - c_stream.next_out = compr; - - while (c_stream.total_in != len && c_stream.total_out < comprLen) { - c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ - err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - } - - /* Finish the stream, still forcing small buffers: */ - for (;;) { - c_stream.avail_out = 1; - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - } - - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - free(head); -} - -/* =========================================================================== - * Test deflateTune() with small buffers - */ -void test_deflate_tune(unsigned char *compr, size_t comprLen) { - PREFIX3(stream) c_stream; /* compression stream */ - int err; - int good_length = 3; - int max_lazy = 5; - int nice_length = 18; - int max_chain = 6; - size_t len = strlen(hello)+1; - - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (voidpf)0; - - err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - err = PREFIX(deflateTune)(&c_stream,(uInt)good_length,(uInt)max_lazy,nice_length,(uInt)max_chain); - CHECK_ERR(err, "deflateTune"); - if (err == Z_OK) { - printf("deflateTune(): OK\n"); - } - - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.next_out = compr; - - while (c_stream.total_in != len && c_stream.total_out < comprLen) { - c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ - err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - } - - /* Finish the stream, still forcing small buffers: */ - for (;;) { - c_stream.avail_out = 1; - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - } - - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Usage: example [output.gz [input.gz]] - */ -int main(int argc, char *argv[]) { - unsigned char *compr, *uncompr; - z_size_t comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ - z_size_t uncomprLen = comprLen; - static const char* myVersion = PREFIX2(VERSION); - - if (zVersion()[0] != myVersion[0]) { - fprintf(stderr, "incompatible zlib version\n"); - exit(1); - - } else if (strcmp(zVersion(), PREFIX2(VERSION)) != 0) { - fprintf(stderr, "warning: different zlib version\n"); - } - - printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", - PREFIX2(VERSION), PREFIX2(VERNUM), PREFIX(zlibCompileFlags)()); - - compr = (unsigned char*)calloc((unsigned int)comprLen, 1); - uncompr = (unsigned char*)calloc((unsigned int)uncomprLen, 1); - /* compr and uncompr are cleared to avoid reading uninitialized - * data and to ensure that uncompr compresses well. - */ - if (compr == NULL || uncompr == NULL) { - printf("out of memory\n"); - exit(1); - } - - test_compress(compr, comprLen, uncompr, uncomprLen); - - test_gzio((argc > 1 ? argv[1] : TESTFILE), - uncompr, uncomprLen); - - test_deflate(compr, comprLen); - test_inflate(compr, comprLen, uncompr, uncomprLen); - - test_large_deflate(compr, comprLen, uncompr, uncomprLen, 0); - test_large_inflate(compr, comprLen, uncompr, uncomprLen); - -#ifndef ZLIB_COMPAT - test_large_deflate(compr, comprLen, uncompr, uncomprLen, 1); - test_large_inflate(compr, comprLen, uncompr, uncomprLen); -#endif - - test_flush(compr, &comprLen); - test_sync(compr, comprLen, uncompr, uncomprLen); - comprLen = uncomprLen; - - test_dict_deflate(compr, comprLen); - test_dict_inflate(compr, comprLen, uncompr, uncomprLen); - - test_deflate_bound(); - test_deflate_copy(compr, comprLen); - test_deflate_get_dict(compr, comprLen); - test_deflate_set_header(compr, comprLen); - test_deflate_tune(compr, comprLen); - test_deflate_pending(compr, comprLen); - test_deflate_prime(compr, comprLen, uncompr, uncomprLen); - - free(compr); - free(uncompr); - - return 0; -} diff --git a/libs/zlibng/test/fuzz/checksum_fuzzer.c b/libs/zlibng/test/fuzz/checksum_fuzzer.c deleted file mode 100644 index ef99421116..0000000000 --- a/libs/zlibng/test/fuzz/checksum_fuzzer.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) { - uint32_t crc0 = PREFIX(crc32)(0L, NULL, 0); - uint32_t crc1 = crc0; - uint32_t crc2 = crc0; - uint32_t adler0 = PREFIX(adler32)(0L, NULL, 0); - uint32_t adler1 = adler0; - uint32_t adler2 = adler0; - uint32_t combine1, combine2; - /* Checksum with a buffer of size equal to the first byte in the input. */ - uint32_t buffSize = data[0]; - uint32_t offset = 0; - uint32_t op[32]; - - /* Discard inputs larger than 1Mb. */ - static size_t kMaxSize = 1024 * 1024; - if (dataLen < 1 || dataLen > kMaxSize) - return 0; - - /* Make sure the buffer has at least a byte. */ - if (buffSize == 0) - ++buffSize; - - /* CRC32 */ - PREFIX(crc32_combine_gen)(op, buffSize); - for (offset = 0; offset + buffSize <= dataLen; offset += buffSize) { - uint32_t crc3 = PREFIX(crc32_z)(crc0, data + offset, buffSize); - uint32_t crc4 = PREFIX(crc32_combine_op)(crc1, crc3, op); - crc1 = PREFIX(crc32_z)(crc1, data + offset, buffSize); - assert(crc1 == crc4); - (void)crc1; - (void)crc4; - } - crc1 = PREFIX(crc32_z)(crc1, data + offset, dataLen % buffSize); - - crc2 = PREFIX(crc32_z)(crc2, data, dataLen); - - assert(crc1 == crc2); - (void)crc1; - (void)crc2; - combine1 = PREFIX(crc32_combine)(crc1, crc2, (z_off_t)dataLen); - combine2 = PREFIX(crc32_combine)(crc1, crc1, (z_off_t)dataLen); - assert(combine1 == combine2); - - /* Fast CRC32 combine. */ - PREFIX(crc32_combine_gen)(op, (z_off_t)dataLen); - combine1 = PREFIX(crc32_combine_op)(crc1, crc2, op); - combine2 = PREFIX(crc32_combine_op)(crc2, crc1, op); - assert(combine1 == combine2); - combine1 = PREFIX(crc32_combine)(crc1, crc2, (z_off_t)dataLen); - combine2 = PREFIX(crc32_combine_op)(crc2, crc1, op); - assert(combine1 == combine2); - - /* Adler32 */ - for (offset = 0; offset + buffSize <= dataLen; offset += buffSize) - adler1 = PREFIX(adler32_z)(adler1, data + offset, buffSize); - adler1 = PREFIX(adler32_z)(adler1, data + offset, dataLen % buffSize); - - adler2 = PREFIX(adler32_z)(adler2, data, dataLen); - - assert(adler1 == adler2); - (void)adler1; - (void)adler2; - combine1 = PREFIX(adler32_combine)(adler1, adler2, (z_off_t)dataLen); - combine2 = PREFIX(adler32_combine)(adler1, adler1, (z_off_t)dataLen); - assert(combine1 == combine2); - (void)combine1; - (void)combine2; - - /* This function must return 0. */ - return 0; -} diff --git a/libs/zlibng/test/fuzz/compress_fuzzer.c b/libs/zlibng/test/fuzz/compress_fuzzer.c deleted file mode 100644 index 9712e882a1..0000000000 --- a/libs/zlibng/test/fuzz/compress_fuzzer.c +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -static const uint8_t *data; -static size_t dataLen; - -static void check_compress_level(uint8_t *compr, z_size_t comprLen, - uint8_t *uncompr, z_size_t uncomprLen, - int level) { - PREFIX(compress2)(compr, &comprLen, data, dataLen, level); - PREFIX(uncompress)(uncompr, &uncomprLen, compr, comprLen); - - /* Make sure compress + uncompress gives back the input data. */ - assert(dataLen == uncomprLen); - assert(0 == memcmp(data, uncompr, dataLen)); -} - -#define put_byte(s, i, c) {s[i] = (unsigned char)(c);} - -static void write_zlib_header(uint8_t *s) { - unsigned level_flags = 0; /* compression level (0..3) */ - unsigned w_bits = 8; /* window size log2(w_size) (8..16) */ - unsigned int header = (Z_DEFLATED + ((w_bits-8)<<4)) << 8; - header |= (level_flags << 6); - - header += 31 - (header % 31); - - /* s is guaranteed to be longer than 2 bytes. */ - put_byte(s, 0, (header >> 8)); - put_byte(s, 1, (header & 0xff)); -} - -static void check_decompress(uint8_t *compr, size_t comprLen) { - /* We need to write a valid zlib header of size two bytes. Copy the input data - in a larger buffer. Do not modify the input data to avoid libFuzzer error: - fuzz target overwrites its const input. */ - size_t copyLen = dataLen + 2; - uint8_t *copy = (uint8_t *)malloc(copyLen); - memcpy(copy + 2, data, dataLen); - write_zlib_header(copy); - - PREFIX(uncompress)(compr, &comprLen, copy, copyLen); - free(copy); -} - -int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) { - /* compressBound does not provide enough space for low compression levels. */ - z_size_t comprLen = 100 + 2 * PREFIX(compressBound)(size); - z_size_t uncomprLen = (z_size_t)size; - uint8_t *compr, *uncompr; - - /* Discard inputs larger than 1Mb. */ - static size_t kMaxSize = 1024 * 1024; - - if (size < 1 || size > kMaxSize) - return 0; - - data = d; - dataLen = size; - compr = (uint8_t *)calloc(1, comprLen); - uncompr = (uint8_t *)calloc(1, uncomprLen); - - check_compress_level(compr, comprLen, uncompr, uncomprLen, 1); - check_compress_level(compr, comprLen, uncompr, uncomprLen, 3); - check_compress_level(compr, comprLen, uncompr, uncomprLen, 6); - check_compress_level(compr, comprLen, uncompr, uncomprLen, 7); - - check_decompress(compr, comprLen); - - free(compr); - free(uncompr); - - /* This function must return 0. */ - return 0; -} diff --git a/libs/zlibng/test/fuzz/example_dict_fuzzer.c b/libs/zlibng/test/fuzz/example_dict_fuzzer.c deleted file mode 100644 index 027c9a806a..0000000000 --- a/libs/zlibng/test/fuzz/example_dict_fuzzer.c +++ /dev/null @@ -1,169 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - -static const uint8_t *data; -static size_t dataLen; -static alloc_func zalloc = NULL; -static free_func zfree = NULL; -static unsigned int dictionaryLen = 0; -static unsigned long dictId; /* Adler32 value of the dictionary */ - -/* =========================================================================== - * Test deflate() with preset dictionary - */ -void test_dict_deflate(unsigned char **compr, size_t *comprLen) { - PREFIX3(stream) c_stream; /* compression stream */ - int err; - int level = data[0] % 11 - 1; /* [-1..9] - compression levels - #define Z_NO_COMPRESSION 0 - #define Z_BEST_SPEED 1 - #define Z_BEST_COMPRESSION 9 - #define Z_DEFAULT_COMPRESSION (-1) */ - - int method = Z_DEFLATED; /* The deflate compression method (the only one - supported in this version) */ - int windowBits = 8 + data[0] % 8; /* The windowBits parameter is the base - two logarithm of the window size (the size of the history buffer). It - should be in the range 8..15 for this version of the library. */ - int memLevel = 1 + data[0] % 9; /* memLevel=1 uses minimum memory but is - slow and reduces compression ratio; memLevel=9 uses maximum memory for - optimal speed. */ - int strategy = data[0] % 5; /* [0..4] - #define Z_FILTERED 1 - #define Z_HUFFMAN_ONLY 2 - #define Z_RLE 3 - #define Z_FIXED 4 - #define Z_DEFAULT_STRATEGY 0 */ - - /* deflate would fail for no-compression or for speed levels. */ - if (level == 0 || level == 1) - level = -1; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (void *)0; - - err = PREFIX(deflateInit2)(&c_stream, level, method, windowBits, memLevel, - strategy); - CHECK_ERR(err, "deflateInit"); - - err = PREFIX(deflateSetDictionary)( - &c_stream, (const unsigned char *)data, dictionaryLen); - CHECK_ERR(err, "deflateSetDictionary"); - - /* deflateBound does not provide enough space for low compression levels. */ - *comprLen = 100 + 2 * PREFIX(deflateBound)(&c_stream, (unsigned long)dataLen); - *compr = (uint8_t *)calloc(1, *comprLen); - - dictId = c_stream.adler; - c_stream.next_out = *compr; - c_stream.avail_out = (unsigned int)(*comprLen); - - c_stream.next_in = (z_const unsigned char *)data; - c_stream.avail_in = (uint32_t)dataLen; - - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate dict should report Z_STREAM_END\n"); - exit(1); - } - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with a preset dictionary - */ -void test_dict_inflate(unsigned char *compr, size_t comprLen) { - int err; - PREFIX3(stream) d_stream; /* decompression stream */ - unsigned char *uncompr; - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (void *)0; - - d_stream.next_in = compr; - d_stream.avail_in = (unsigned int)comprLen; - - err = PREFIX(inflateInit)(&d_stream); - CHECK_ERR(err, "inflateInit"); - - uncompr = (uint8_t *)calloc(1, dataLen); - d_stream.next_out = uncompr; - d_stream.avail_out = (unsigned int)dataLen; - - for (;;) { - err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) - break; - if (err == Z_NEED_DICT) { - if (d_stream.adler != dictId) { - fprintf(stderr, "unexpected dictionary"); - exit(1); - } - err = PREFIX(inflateSetDictionary)( - &d_stream, (const unsigned char *)data, dictionaryLen); - } - CHECK_ERR(err, "inflate with dict"); - } - - err = PREFIX(inflateEnd)(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (memcmp(uncompr, data, dataLen)) { - fprintf(stderr, "bad inflate with dict\n"); - exit(1); - } - - free(uncompr); -} - -int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) { - size_t comprLen = 0; - uint8_t *compr; - - /* Discard inputs larger than 100Kb. */ - static size_t kMaxSize = 100 * 1024; - - if (size < 1 || size > kMaxSize) - return 0; - - data = d; - dataLen = size; - - /* Set up the contents of the dictionary. The size of the dictionary is - intentionally selected to be of unusual size. To help cover more corner - cases, the size of the dictionary is read from the input data. */ - dictionaryLen = data[0]; - if (dictionaryLen > dataLen) - dictionaryLen = (unsigned int)dataLen; - - test_dict_deflate(&compr, &comprLen); - test_dict_inflate(compr, comprLen); - - free(compr); - - /* This function must return 0. */ - return 0; -} diff --git a/libs/zlibng/test/fuzz/example_flush_fuzzer.c b/libs/zlibng/test/fuzz/example_flush_fuzzer.c deleted file mode 100644 index 81ec7e36d5..0000000000 --- a/libs/zlibng/test/fuzz/example_flush_fuzzer.c +++ /dev/null @@ -1,124 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - -static const uint8_t *data; -static size_t dataLen; -static alloc_func zalloc = NULL; -static free_func zfree = NULL; - -/* =========================================================================== - * Test deflate() with full flush - */ -void test_flush(unsigned char *compr, z_size_t *comprLen) { - PREFIX3(stream) c_stream; /* compression stream */ - int err; - unsigned int len = (unsigned int)dataLen; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (void *)0; - - err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (z_const unsigned char *)data; - c_stream.next_out = compr; - c_stream.avail_in = 3; - c_stream.avail_out = (unsigned int)*comprLen; - err = PREFIX(deflate)(&c_stream, Z_FULL_FLUSH); - CHECK_ERR(err, "deflate flush 1"); - - compr[3]++; /* force an error in first compressed block */ - c_stream.avail_in = len - 3; - - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - CHECK_ERR(err, "deflate flush 2"); - } - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - *comprLen = (z_size_t)c_stream.total_out; -} - -/* =========================================================================== - * Test inflateSync() - */ -void test_sync(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) { - int err; - PREFIX3(stream) d_stream; /* decompression stream */ - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (void *)0; - - d_stream.next_in = compr; - d_stream.avail_in = 2; /* just read the zlib header */ - - err = PREFIX(inflateInit)(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (unsigned int)uncomprLen; - - err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); - CHECK_ERR(err, "inflate"); - - d_stream.avail_in = (unsigned int)comprLen - 2; /* read all compressed data */ - err = PREFIX(inflateSync)(&d_stream); /* but skip the damaged part */ - CHECK_ERR(err, "inflateSync"); - - err = PREFIX(inflate)(&d_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "inflate should report Z_STREAM_END\n"); - exit(1); - } - err = PREFIX(inflateEnd)(&d_stream); - CHECK_ERR(err, "inflateEnd"); -} - -int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) { - z_size_t comprLen = 100 + 2 * PREFIX(compressBound)(size); - z_size_t uncomprLen = (z_size_t)size; - uint8_t *compr, *uncompr; - - /* Discard inputs larger than 1Mb. */ - static size_t kMaxSize = 1024 * 1024; - - // This test requires at least 3 bytes of input data. - if (size <= 3 || size > kMaxSize) - return 0; - - data = d; - dataLen = size; - compr = (uint8_t *)calloc(1, comprLen); - uncompr = (uint8_t *)calloc(1, uncomprLen); - - test_flush(compr, &comprLen); - test_sync(compr, comprLen, uncompr, uncomprLen); - - free(compr); - free(uncompr); - - /* This function must return 0. */ - return 0; -} diff --git a/libs/zlibng/test/fuzz/example_large_fuzzer.c b/libs/zlibng/test/fuzz/example_large_fuzzer.c deleted file mode 100644 index bd27a84f12..0000000000 --- a/libs/zlibng/test/fuzz/example_large_fuzzer.c +++ /dev/null @@ -1,141 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - -static const uint8_t *data; -static size_t dataLen; -static alloc_func zalloc = NULL; -static free_func zfree = NULL; -static unsigned int diff; - -/* =========================================================================== - * Test deflate() with large buffers and dynamic change of compression level - */ -void test_large_deflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) { - PREFIX3(stream) c_stream; /* compression stream */ - int err; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (void *)0; - - err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_out = compr; - c_stream.avail_out = (unsigned int)comprLen; - - /* At this point, uncompr is still mostly zeroes, so it should compress - * very well: - */ - c_stream.next_in = uncompr; - c_stream.avail_in = (unsigned int)uncomprLen; - err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate large 1"); - if (c_stream.avail_in != 0) { - fprintf(stderr, "deflate not greedy\n"); - exit(1); - } - - /* Feed in already compressed data and switch to no compression: */ - PREFIX(deflateParams)(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); - c_stream.next_in = compr; - diff = (unsigned int)(c_stream.next_out - compr); - c_stream.avail_in = diff; - err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate large 2"); - - /* Switch back to compressing mode: */ - PREFIX(deflateParams)(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); - c_stream.next_in = uncompr; - c_stream.avail_in = (unsigned int)uncomprLen; - err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate large 3"); - - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate large should report Z_STREAM_END\n"); - exit(1); - } - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with large buffers - */ -void test_large_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) { - int err; - PREFIX3(stream) d_stream; /* decompression stream */ - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (void *)0; - - d_stream.next_in = compr; - d_stream.avail_in = (unsigned int)comprLen; - - err = PREFIX(inflateInit)(&d_stream); - CHECK_ERR(err, "inflateInit"); - - for (;;) { - d_stream.next_out = uncompr; /* discard the output */ - d_stream.avail_out = (unsigned int)uncomprLen; - err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) - break; - CHECK_ERR(err, "large inflate"); - } - - err = PREFIX(inflateEnd)(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (d_stream.total_out != 2 * uncomprLen + diff) { - fprintf(stderr, "bad large inflate: %" PRIu64 "\n", (uint64_t)d_stream.total_out); - exit(1); - } -} - -int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) { - size_t comprLen = 100 + 3 * size; - size_t uncomprLen = comprLen; - uint8_t *compr, *uncompr; - - /* Discard inputs larger than 512Kb. */ - static size_t kMaxSize = 512 * 1024; - - if (size < 1 || size > kMaxSize) - return 0; - - data = d; - dataLen = size; - compr = (uint8_t *)calloc(1, comprLen); - uncompr = (uint8_t *)calloc(1, uncomprLen); - - test_large_deflate(compr, comprLen, uncompr, uncomprLen); - test_large_inflate(compr, comprLen, uncompr, uncomprLen); - - free(compr); - free(uncompr); - - /* This function must return 0. */ - return 0; -} diff --git a/libs/zlibng/test/fuzz/example_small_fuzzer.c b/libs/zlibng/test/fuzz/example_small_fuzzer.c deleted file mode 100644 index d02a812de6..0000000000 --- a/libs/zlibng/test/fuzz/example_small_fuzzer.c +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - -static const uint8_t *data; -static size_t dataLen; -static alloc_func zalloc = NULL; -static free_func zfree = NULL; - -/* =========================================================================== - * Test deflate() with small buffers - */ -void test_deflate(unsigned char *compr, size_t comprLen) { - PREFIX3(stream) c_stream; /* compression stream */ - int err; - unsigned long len = (unsigned long)dataLen; - - c_stream.zalloc = zalloc; - c_stream.zfree = zfree; - c_stream.opaque = (void *)0; - - err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (z_const unsigned char *)data; - c_stream.next_out = compr; - - while (c_stream.total_in != len && c_stream.total_out < comprLen) { - c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ - err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate small 1"); - } - /* Finish the stream, still forcing small buffers: */ - for (;;) { - c_stream.avail_out = 1; - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) - break; - CHECK_ERR(err, "deflate small 2"); - } - - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with small buffers - */ -void test_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) { - int err; - PREFIX3(stream) d_stream; /* decompression stream */ - - d_stream.zalloc = zalloc; - d_stream.zfree = zfree; - d_stream.opaque = (void *)0; - - d_stream.next_in = compr; - d_stream.avail_in = 0; - d_stream.next_out = uncompr; - - err = PREFIX(inflateInit)(&d_stream); - CHECK_ERR(err, "inflateInit"); - - while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { - d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ - err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) - break; - CHECK_ERR(err, "inflate"); - } - - err = PREFIX(inflateEnd)(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (memcmp(uncompr, data, dataLen)) { - fprintf(stderr, "bad inflate\n"); - exit(1); - } -} - -int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) { - size_t comprLen = PREFIX(compressBound)(size); - size_t uncomprLen = size; - uint8_t *compr, *uncompr; - - /* Discard inputs larger than 1Mb. */ - static size_t kMaxSize = 1024 * 1024; - - if (size < 1 || size > kMaxSize) - return 0; - - data = d; - dataLen = size; - compr = (uint8_t *)calloc(1, comprLen); - uncompr = (uint8_t *)calloc(1, uncomprLen); - - test_deflate(compr, comprLen); - test_inflate(compr, comprLen, uncompr, uncomprLen); - - free(compr); - free(uncompr); - - /* This function must return 0. */ - return 0; -} diff --git a/libs/zlibng/test/fuzz/minigzip_fuzzer.c b/libs/zlibng/test/fuzz/minigzip_fuzzer.c deleted file mode 100644 index 1f19126f44..0000000000 --- a/libs/zlibng/test/fuzz/minigzip_fuzzer.c +++ /dev/null @@ -1,321 +0,0 @@ -/* minigzip.c -- simulate gzip using the zlib compression library - * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * minigzip is a minimal implementation of the gzip utility. This is - * only an example of using zlib and isn't meant to replace the - * full-featured gzip. No attempt is made to deal with file systems - * limiting names to 14 or 8+3 characters, etc... Error checking is - * very limited. So use minigzip only for testing; use gzip for the - * real thing. - */ - -#define _POSIX_SOURCE 1 /* This file needs POSIX for fileno(). */ -#define _POSIX_C_SOURCE 200112 /* For snprintf(). */ - -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif -#include -#include -#include -#include - -#ifdef USE_MMAP -# include -# include -# include -#endif - -#ifndef UNALIGNED_OK -# include -#endif - -#if defined(_WIN32) || defined(__CYGWIN__) -# include -# include -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1900 -# define snprintf _snprintf -#endif - -#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) -#ifndef _WIN32 /* unlink already in stdio.h for Win32 */ -extern int unlink (const char *); -#endif -#endif - -#ifndef GZ_SUFFIX -# define GZ_SUFFIX ".gz" -#endif -#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) - -#define BUFLEN 16384 /* read buffer size */ -#define BUFLENW (BUFLEN * 3) /* write buffer size */ -#define MAX_NAME_LEN 1024 - -static const char *prog = "minigzip_fuzzer"; - -void error (const char *msg); -void gz_compress (FILE *in, gzFile out); -#ifdef USE_MMAP -int gz_compress_mmap (FILE *in, gzFile out); -#endif -void gz_uncompress (gzFile in, FILE *out); -void file_compress (char *file, char *mode); -void file_uncompress (char *file); -int main (int argc, char *argv[]); - -/* =========================================================================== - * Display error message and exit - */ -void error(const char *msg) { - fprintf(stderr, "%s: %s\n", prog, msg); - exit(1); -} - -/* =========================================================================== - * Compress input to output then close both files. - */ - -void gz_compress(FILE *in, gzFile out) { - char buf[BUFLEN]; - int len; - int err; - -#ifdef USE_MMAP - /* Try first compressing with mmap. If mmap fails (minigzip used in a - * pipe), use the normal fread loop. - */ - if (gz_compress_mmap(in, out) == Z_OK) return; -#endif - /* Clear out the contents of buf before reading from the file to avoid - MemorySanitizer: use-of-uninitialized-value warnings. */ - memset(buf, 0, sizeof(buf)); - for (;;) { - len = (int)fread(buf, 1, sizeof(buf), in); - if (ferror(in)) { - perror("fread"); - exit(1); - } - if (len == 0) break; - - if (PREFIX(gzwrite)(out, buf, (unsigned)len) != len) error(PREFIX(gzerror)(out, &err)); - } - fclose(in); - if (PREFIX(gzclose)(out) != Z_OK) error("failed gzclose"); -} - -#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ - -/* Try compressing the input file at once using mmap. Return Z_OK if - * if success, Z_ERRNO otherwise. - */ -int gz_compress_mmap(FILE *in, gzFile out) { - int len; - int err; - int ifd = fileno(in); - char *buf; /* mmap'ed buffer for the entire input file */ - off_t buf_len; /* length of the input file */ - struct stat sb; - - /* Determine the size of the file, needed for mmap: */ - if (fstat(ifd, &sb) < 0) return Z_ERRNO; - buf_len = sb.st_size; - if (buf_len <= 0) return Z_ERRNO; - - /* Now do the actual mmap: */ - buf = mmap((void *)0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); - if (buf == (char *)(-1)) return Z_ERRNO; - - /* Compress the whole file at once: */ - len = PREFIX(gzwrite)(out, (char *)buf, (unsigned)buf_len); - - if (len != (int)buf_len) error(PREFIX(gzerror)(out, &err)); - - munmap(buf, buf_len); - fclose(in); - if (PREFIX(gzclose)(out) != Z_OK) error("failed gzclose"); - return Z_OK; -} -#endif /* USE_MMAP */ - -/* =========================================================================== - * Uncompress input to output then close both files. - */ -void gz_uncompress(gzFile in, FILE *out) { - char buf[BUFLENW]; - int len; - int err; - - for (;;) { - len = PREFIX(gzread)(in, buf, sizeof(buf)); - if (len < 0) error (PREFIX(gzerror)(in, &err)); - if (len == 0) break; - - if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { - error("failed fwrite"); - } - } - if (fclose(out)) error("failed fclose"); - - if (PREFIX(gzclose)(in) != Z_OK) error("failed gzclose"); -} - - -/* =========================================================================== - * Compress the given file: create a corresponding .gz file and remove the - * original. - */ -void file_compress(char *file, char *mode) { - char outfile[MAX_NAME_LEN]; - FILE *in; - gzFile out; - - if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { - fprintf(stderr, "%s: filename too long\n", prog); - exit(1); - } - - snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX); - - in = fopen(file, "rb"); - if (in == NULL) { - perror(file); - exit(1); - } - out = PREFIX(gzopen)(outfile, mode); - if (out == NULL) { - fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); - exit(1); - } - gz_compress(in, out); - - unlink(file); -} - - -/* =========================================================================== - * Uncompress the given file and remove the original. - */ -void file_uncompress(char *file) { - char buf[MAX_NAME_LEN]; - char *infile, *outfile; - FILE *out; - gzFile in; - size_t len = strlen(file); - - if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { - fprintf(stderr, "%s: filename too long\n", prog); - exit(1); - } - - snprintf(buf, sizeof(buf), "%s", file); - - if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { - infile = file; - outfile = buf; - outfile[len-3] = '\0'; - } else { - outfile = file; - infile = buf; - snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX); - } - in = PREFIX(gzopen)(infile, "rb"); - if (in == NULL) { - fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); - exit(1); - } - out = fopen(outfile, "wb"); - if (out == NULL) { - perror(file); - exit(1); - } - - gz_uncompress(in, out); - - unlink(infile); -} - -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) { - char *inFileName = "minigzip_fuzzer.out"; - char *outFileName = "minigzip_fuzzer.out.gz"; - char outmode[20]; - FILE *in; - char buf[BUFLEN]; - uint32_t offset = 0; - - /* Discard inputs larger than 1Mb. */ - static size_t kMaxSize = 1024 * 1024; - if (dataLen < 1 || dataLen > kMaxSize) - return 0; - - in = fopen(inFileName, "wb"); - if (fwrite(data, 1, (unsigned)dataLen, in) != dataLen) - error("failed fwrite"); - if (fclose(in)) - error("failed fclose"); - - memset(outmode, 0, sizeof(outmode)); - snprintf(outmode, sizeof(outmode), "%s", "wb"); - - /* Compression level: [0..9]. */ - outmode[2] = data[0] % 10; - - switch (data[0] % 4) { - default: - case 0: - outmode[3] = 0; - break; - case 1: - /* compress with Z_FILTERED */ - outmode[3] = 'f'; - break; - case 2: - /* compress with Z_HUFFMAN_ONLY */ - outmode[3] = 'h'; - break; - case 3: - /* compress with Z_RLE */ - outmode[3] = 'R'; - break; - } - - file_compress(inFileName, outmode); - file_uncompress(outFileName); - - /* Check that the uncompressed file matches the input data. */ - in = fopen(inFileName, "rb"); - if (in == NULL) { - perror(inFileName); - exit(1); - } - - memset(buf, 0, sizeof(buf)); - for (;;) { - int len = (int)fread(buf, 1, sizeof(buf), in); - if (ferror(in)) { - perror("fread"); - exit(1); - } - if (len == 0) - break; - assert(0 == memcmp(data + offset, buf, len)); - offset += len; - } - - if (fclose(in)) - error("failed fclose"); - - /* This function must return 0. */ - return 0; -} diff --git a/libs/zlibng/test/fuzz/standalone_fuzz_target_runner.c b/libs/zlibng/test/fuzz/standalone_fuzz_target_runner.c deleted file mode 100644 index a291b48823..0000000000 --- a/libs/zlibng/test/fuzz/standalone_fuzz_target_runner.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include - -extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); - -int main(int argc, char **argv) { - int i; - fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1); - - for (i = 1; i < argc; i++) { - size_t len, n_read, err; - unsigned char *buf; - FILE *f = fopen(argv[i], "rb+"); - if (!f) { - /* Failed to open this file: it may be a directory. */ - fprintf(stderr, "Skipping: %s\n", argv[i]); - continue; - } - fprintf(stderr, "Running: %s %s\n", argv[0], argv[i]); - fseek(f, 0, SEEK_END); - len = ftell(f); - fseek(f, 0, SEEK_SET); - buf = (unsigned char *)malloc(len); - n_read = fread(buf, 1, len, f); - assert(n_read == len); - LLVMFuzzerTestOneInput(buf, len); - free(buf); - err = fclose(f); - assert(err == 0); - (void)err; - fprintf(stderr, "Done: %s: (%d bytes)\n", argv[i], (int)n_read); - } - - return 0; -} diff --git a/libs/zlibng/test/infcover.c b/libs/zlibng/test/infcover.c deleted file mode 100644 index 3466b202dc..0000000000 --- a/libs/zlibng/test/infcover.c +++ /dev/null @@ -1,682 +0,0 @@ -/* infcover.c -- test zlib's inflate routines with full code coverage - * Copyright (C) 2011, 2016 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* to use, do: ./configure --cover && make cover */ - -#include -#include -#include -#undef NDEBUG -#include -#include -#include - -/* get definition of internal structure so we can mess with it (see pull()), - and so we can call inflate_trees() (see cover5()) */ -#define ZLIB_INTERNAL -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif -#include "inftrees.h" -#include "inflate.h" - -/* -- memory tracking routines -- */ - -/* - These memory tracking routines are provided to zlib and track all of zlib's - allocations and deallocations, check for LIFO operations, keep a current - and high water mark of total bytes requested, optionally set a limit on the - total memory that can be allocated, and when done check for memory leaks. - - They are used as follows: - - PREFIX3(stream) strm; - mem_setup(&strm) initializes the memory tracking and sets the - zalloc, zfree, and opaque members of strm to use - memory tracking for all zlib operations on strm - mem_limit(&strm, limit) sets a limit on the total bytes requested -- a - request that exceeds this limit will result in an - allocation failure (returns NULL) -- setting the - limit to zero means no limit, which is the default - after mem_setup() - mem_used(&strm, "msg") prints to stderr "msg" and the total bytes used - mem_high(&strm, "msg") prints to stderr "msg" and the high water mark - mem_done(&strm, "msg") ends memory tracking, releases all allocations - for the tracking as well as leaked zlib blocks, if - any. If there was anything unusual, such as leaked - blocks, non-FIFO frees, or frees of addresses not - allocated, then "msg" and information about the - problem is printed to stderr. If everything is - normal, nothing is printed. mem_done resets the - strm members to NULL to use the default memory - allocation routines on the next zlib initialization - using strm. - */ - -/* these items are strung together in a linked list, one for each allocation */ -struct mem_item { - void *ptr; /* pointer to allocated memory */ - size_t size; /* requested size of allocation */ - struct mem_item *next; /* pointer to next item in list, or NULL */ -}; - -/* this structure is at the root of the linked list, and tracks statistics */ -struct mem_zone { - struct mem_item *first; /* pointer to first item in list, or NULL */ - size_t total, highwater; /* total allocations, and largest total */ - size_t limit; /* memory allocation limit, or 0 if no limit */ - int notlifo, rogue; /* counts of non-LIFO frees and rogue frees */ -}; - -/* memory allocation routine to pass to zlib */ -static void *mem_alloc(void *mem, unsigned count, unsigned size) { - void *ptr; - struct mem_item *item; - struct mem_zone *zone = mem; - size_t len = count * (size_t)size; - - /* induced allocation failure */ - if (zone == NULL || (zone->limit && zone->total + len > zone->limit)) - return NULL; - - /* perform allocation using the standard library, fill memory with a - non-zero value to make sure that the code isn't depending on zeros */ - ptr = malloc(len); - if (ptr == NULL) - return NULL; - memset(ptr, 0xa5, len); - - /* create a new item for the list */ - item = malloc(sizeof(struct mem_item)); - if (item == NULL) { - free(ptr); - return NULL; - } - item->ptr = ptr; - item->size = len; - - /* insert item at the beginning of the list */ - item->next = zone->first; - zone->first = item; - - /* update the statistics */ - zone->total += item->size; - if (zone->total > zone->highwater) - zone->highwater = zone->total; - - /* return the allocated memory */ - return ptr; -} - -/* memory free routine to pass to zlib */ -static void mem_free(void *mem, void *ptr) { - struct mem_item *item, *next; - struct mem_zone *zone = mem; - - /* if no zone, just do a free */ - if (zone == NULL) { - free(ptr); - return; - } - - /* point next to the item that matches ptr, or NULL if not found -- remove - the item from the linked list if found */ - next = zone->first; - if (next) { - if (next->ptr == ptr) - zone->first = next->next; /* first one is it, remove from list */ - else { - do { /* search the linked list */ - item = next; - next = item->next; - } while (next != NULL && next->ptr != ptr); - if (next) { /* if found, remove from linked list */ - item->next = next->next; - zone->notlifo++; /* not a LIFO free */ - } - - } - } - - /* if found, update the statistics and free the item */ - if (next) { - zone->total -= next->size; - free(next); - } - - /* if not found, update the rogue count */ - else - zone->rogue++; - - /* in any case, do the requested free with the standard library function */ - free(ptr); -} - -/* set up a controlled memory allocation space for monitoring, set the stream - parameters to the controlled routines, with opaque pointing to the space */ -static void mem_setup(PREFIX3(stream) *strm) { - struct mem_zone *zone; - - zone = malloc(sizeof(struct mem_zone)); - assert(zone != NULL); - zone->first = NULL; - zone->total = 0; - zone->highwater = 0; - zone->limit = 0; - zone->notlifo = 0; - zone->rogue = 0; - strm->opaque = zone; - strm->zalloc = mem_alloc; - strm->zfree = mem_free; -} - -/* set a limit on the total memory allocation, or 0 to remove the limit */ -static void mem_limit(PREFIX3(stream) *strm, size_t limit) { - struct mem_zone *zone = strm->opaque; - - zone->limit = limit; -} - -/* show the current total requested allocations in bytes */ -static void mem_used(PREFIX3(stream) *strm, char *prefix) { - struct mem_zone *zone = strm->opaque; - - fprintf(stderr, "%s: %" PRIu64 " allocated\n", prefix, (uint64_t)zone->total); -} - -/* show the high water allocation in bytes */ -static void mem_high(PREFIX3(stream) *strm, char *prefix) { - struct mem_zone *zone = strm->opaque; - - fprintf(stderr, "%s: %" PRIu64 " high water mark\n", prefix, (uint64_t)zone->highwater); -} - -/* release the memory allocation zone -- if there are any surprises, notify */ -static void mem_done(PREFIX3(stream) *strm, char *prefix) { - int count = 0; - struct mem_item *item, *next; - struct mem_zone *zone = strm->opaque; - - /* show high water mark */ - mem_high(strm, prefix); - - /* free leftover allocations and item structures, if any */ - item = zone->first; - while (item != NULL) { - free(item->ptr); - next = item->next; - free(item); - item = next; - count++; - } - - /* issue alerts about anything unexpected */ - if (count || zone->total) - fprintf(stderr, "** %s: %" PRIu64 " bytes in %d blocks not freed\n", - prefix, (uint64_t)zone->total, count); - if (zone->notlifo) - fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo); - if (zone->rogue) - fprintf(stderr, "** %s: %d frees not recognized\n", - prefix, zone->rogue); - - /* free the zone and delete from the stream */ - free(zone); - strm->opaque = NULL; - strm->zalloc = NULL; - strm->zfree = NULL; -} - -/* -- inflate test routines -- */ - -/* Decode a hexadecimal string, set *len to length, in[] to the bytes. This - decodes liberally, in that hex digits can be adjacent, in which case two in - a row writes a byte. Or they can be delimited by any non-hex character, - where the delimiters are ignored except when a single hex digit is followed - by a delimiter, where that single digit writes a byte. The returned data is - allocated and must eventually be freed. NULL is returned if out of memory. - If the length is not needed, then len can be NULL. */ -static unsigned char *h2b(const char *hex, unsigned *len) { - unsigned char *in, *re; - unsigned next, val; - size_t inlen; - - inlen = (strlen(hex) + 1) >> 1; - assert(inlen != 0); /* tell static analyzer we won't call malloc(0) */ - in = malloc(inlen); - if (in == NULL) - return NULL; - next = 0; - val = 1; - do { - if (*hex >= '0' && *hex <= '9') - val = (val << 4) + *hex - '0'; - else if (*hex >= 'A' && *hex <= 'F') - val = (val << 4) + *hex - 'A' + 10; - else if (*hex >= 'a' && *hex <= 'f') - val = (val << 4) + *hex - 'a' + 10; - else if (val != 1 && val < 32) /* one digit followed by delimiter */ - val += 240; /* make it look like two digits */ - if (val > 255) { /* have two digits */ - in[next++] = val & 0xff; /* save the decoded byte */ - val = 1; /* start over */ - } - } while (*hex++); /* go through the loop with the terminating null */ - if (len != NULL) - *len = next; - assert(next != 0); /* tell static analyzer we won't call realloc(in, 0) */ - re = realloc(in, next); - return re == NULL ? in : re; -} - -/* generic inflate() run, where hex is the hexadecimal input data, what is the - text to include in an error message, step is how much input data to feed - inflate() on each call, or zero to feed it all, win is the window bits - parameter to inflateInit2(), len is the size of the output buffer, and err - is the error code expected from the first inflate() call (the second - inflate() call is expected to return Z_STREAM_END). If win is 47, then - header information is collected with inflateGetHeader(). If a zlib stream - is looking for a dictionary, then an empty dictionary is provided. - inflate() is run until all of the input data is consumed. */ -static void inf(char *hex, char *what, unsigned step, int win, unsigned len, int err) { - int ret; - unsigned have; - unsigned char *in, *out; - PREFIX3(stream) strm, copy; - PREFIX(gz_header) head; - - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = NULL; - ret = PREFIX(inflateInit2)(&strm, win); - if (ret != Z_OK) { - mem_done(&strm, what); - return; - } - out = malloc(len); assert(out != NULL); - if (win == 47) { - head.extra = out; - head.extra_max = len; - head.name = out; - head.name_max = len; - head.comment = out; - head.comm_max = len; - ret = PREFIX(inflateGetHeader)(&strm, &head); - assert(ret == Z_OK); - } - in = h2b(hex, &have); assert(in != NULL); - if (step == 0 || step > have) - step = have; - strm.avail_in = step; - have -= step; - strm.next_in = in; - do { - strm.avail_out = len; - strm.next_out = out; - ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); - assert(err == 9 || ret == err); - if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_NEED_DICT) - break; - if (ret == Z_NEED_DICT) { - ret = PREFIX(inflateSetDictionary)(&strm, in, 1); - assert(ret == Z_DATA_ERROR); - mem_limit(&strm, 1); - ret = PREFIX(inflateSetDictionary)(&strm, out, 0); - assert(ret == Z_MEM_ERROR); - mem_limit(&strm, 0); - ((struct inflate_state *)strm.state)->mode = DICT; - ret = PREFIX(inflateSetDictionary)(&strm, out, 0); - assert(ret == Z_OK); - ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); - assert(ret == Z_BUF_ERROR); - } - ret = PREFIX(inflateCopy)(©, &strm); - assert(ret == Z_OK); - ret = PREFIX(inflateEnd)(©); assert(ret == Z_OK); - err = 9; /* don't care next time around */ - have += strm.avail_in; - strm.avail_in = step > have ? have : step; - have -= strm.avail_in; - } while (strm.avail_in); - free(in); - free(out); - ret = PREFIX(inflateReset2)(&strm, -8); assert(ret == Z_OK); - ret = PREFIX(inflateEnd)(&strm); assert(ret == Z_OK); - mem_done(&strm, what); - (void)err; -} - -/* cover all of the lines in inflate.c up to inflate() */ -static void cover_support(void) { - int ret; - PREFIX3(stream) strm; - - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = NULL; - ret = PREFIX(inflateInit)(&strm); assert(ret == Z_OK); - mem_used(&strm, "inflate init"); - ret = PREFIX(inflatePrime)(&strm, 5, 31); assert(ret == Z_OK); - ret = PREFIX(inflatePrime)(&strm, -1, 0); assert(ret == Z_OK); - ret = PREFIX(inflateSetDictionary)(&strm, NULL, 0); - assert(ret == Z_STREAM_ERROR); - ret = PREFIX(inflateEnd)(&strm); assert(ret == Z_OK); - mem_done(&strm, "prime"); - - inf("63 0", "force window allocation", 0, -15, 1, Z_OK); - inf("63 18 5", "force window replacement", 0, -8, 259, Z_OK); - inf("63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, Z_OK); - inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END); - inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR); - - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = NULL; - ret = PREFIX(inflateInit_)(&strm, &PREFIX2(VERSION)[1], (int)sizeof(PREFIX3(stream))); - assert(ret == Z_VERSION_ERROR); - mem_done(&strm, "wrong version"); - - strm.avail_in = 0; - strm.next_in = NULL; - ret = PREFIX(inflateInit)(&strm); assert(ret == Z_OK); - ret = PREFIX(inflateEnd)(&strm); assert(ret == Z_OK); - fputs("inflate built-in memory routines\n", stderr); - (void)ret; -} - -/* cover all inflate() header and trailer cases and code after inflate() */ -static void cover_wrap(void) { - int ret; - PREFIX3(stream) strm, copy; - unsigned char dict[257]; - - ret = PREFIX(inflate)(NULL, 0); assert(ret == Z_STREAM_ERROR); - ret = PREFIX(inflateEnd)(NULL); assert(ret == Z_STREAM_ERROR); - ret = PREFIX(inflateCopy)(NULL, NULL); assert(ret == Z_STREAM_ERROR); - fputs("inflate bad parameters\n", stderr); - - inf("1f 8b 0 0", "bad gzip method", 0, 31, 0, Z_DATA_ERROR); - inf("1f 8b 8 80", "bad gzip flags", 0, 31, 0, Z_DATA_ERROR); - inf("77 85", "bad zlib method", 0, 15, 0, Z_DATA_ERROR); - inf("8 99", "set window size from header", 0, 0, 0, Z_OK); - inf("78 9c", "bad zlib window size", 0, 8, 0, Z_DATA_ERROR); - inf("78 9c 63 0 0 0 1 0 1", "check adler32", 0, 15, 1, Z_STREAM_END); - inf("1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1, - Z_DATA_ERROR); - inf("1f 8b 8 2 0 0 0 0 0 0 1d 26 3 0 0 0 0 0 0 0 0 0", "check gzip length", - 0, 47, 0, Z_STREAM_END); - inf("78 90", "bad zlib header check", 0, 47, 0, Z_DATA_ERROR); - inf("8 b8 0 0 0 1", "need dictionary", 0, 8, 0, Z_NEED_DICT); - inf("78 9c 63 0", "compute adler32", 0, 15, 1, Z_OK); - - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = NULL; - ret = PREFIX(inflateInit2)(&strm, -8); - strm.avail_in = 2; - strm.next_in = (void *)"\x63"; - strm.avail_out = 1; - strm.next_out = (void *)&ret; - mem_limit(&strm, 1); - ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); - ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); - mem_limit(&strm, 0); - memset(dict, 0, 257); - ret = PREFIX(inflateSetDictionary)(&strm, dict, 257); - assert(ret == Z_OK); - mem_limit(&strm, (sizeof(struct inflate_state) << 1) + 256); - ret = PREFIX(inflatePrime)(&strm, 16, 0); assert(ret == Z_OK); - strm.avail_in = 2; - strm.next_in = (void *)"\x80"; - ret = PREFIX(inflateSync)(&strm); assert(ret == Z_DATA_ERROR); - ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); assert(ret == Z_STREAM_ERROR); - strm.avail_in = 4; - strm.next_in = (void *)"\0\0\xff\xff"; - ret = PREFIX(inflateSync)(&strm); assert(ret == Z_OK); - (void)PREFIX(inflateSyncPoint)(&strm); - ret = PREFIX(inflateCopy)(©, &strm); assert(ret == Z_MEM_ERROR); - mem_limit(&strm, 0); - ret = PREFIX(inflateUndermine)(&strm, 1); -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - assert(ret == Z_OK); -#else - assert(ret == Z_DATA_ERROR); -#endif - (void)PREFIX(inflateMark)(&strm); - ret = PREFIX(inflateEnd)(&strm); assert(ret == Z_OK); - mem_done(&strm, "miscellaneous, force memory errors"); -} - -/* input and output functions for inflateBack() */ -static unsigned pull(void *desc, z_const unsigned char **buf) { - static unsigned int next = 0; - static unsigned char dat[] = {0x63, 0, 2, 0}; - struct inflate_state *state; - - if (desc == NULL) { - next = 0; - return 0; /* no input (already provided at next_in) */ - } - state = (void *)((PREFIX3(stream) *)desc)->state; - if (state != NULL) - state->mode = SYNC; /* force an otherwise impossible situation */ - return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0; -} - -static int push(void *desc, unsigned char *buf, unsigned len) { - buf += len; - (void)buf; - return desc != NULL; /* force error if desc not null */ -} - -/* cover inflateBack() up to common deflate data cases and after those */ -static void cover_back(void) { - int ret; - PREFIX3(stream) strm; - unsigned char win[32768]; - - ret = PREFIX(inflateBackInit_)(NULL, 0, win, 0, 0); - assert(ret == Z_VERSION_ERROR); - ret = PREFIX(inflateBackInit)(NULL, 0, win); - assert(ret == Z_STREAM_ERROR); - ret = PREFIX(inflateBack)(NULL, NULL, NULL, NULL, NULL); - assert(ret == Z_STREAM_ERROR); - ret = PREFIX(inflateBackEnd)(NULL); assert(ret == Z_STREAM_ERROR); - fputs("inflateBack bad parameters\n", stderr); - - mem_setup(&strm); - ret = PREFIX(inflateBackInit)(&strm, 15, win); - assert(ret == Z_OK); - strm.avail_in = 2; - strm.next_in = (void *)"\x03"; - ret = PREFIX(inflateBack)(&strm, pull, NULL, push, NULL); - assert(ret == Z_STREAM_END); - /* force output error */ - strm.avail_in = 3; - strm.next_in = (void *)"\x63\x00"; - ret = PREFIX(inflateBack)(&strm, pull, NULL, push, &strm); - assert(ret == Z_BUF_ERROR); - /* force mode error by mucking with state */ - ret = PREFIX(inflateBack)(&strm, pull, &strm, push, NULL); - assert(ret == Z_STREAM_ERROR); - ret = PREFIX(inflateBackEnd)(&strm); assert(ret == Z_OK); - mem_done(&strm, "inflateBack bad state"); - - ret = PREFIX(inflateBackInit)(&strm, 15, win); - assert(ret == Z_OK); - ret = PREFIX(inflateBackEnd)(&strm); assert(ret == Z_OK); - fputs("inflateBack built-in memory routines\n", stderr); - (void)ret; -} - -/* do a raw inflate of data in hexadecimal with both inflate and inflateBack */ -static int try(char *hex, char *id, int err) { - int ret; - unsigned len, size; - unsigned char *in, *out, *win; - char *prefix; - PREFIX3(stream) strm; - - /* convert to hex */ - in = h2b(hex, &len); - assert(in != NULL); - - /* allocate work areas */ - size = len << 3; - out = malloc(size); - assert(out != NULL); - win = malloc(32768); - assert(win != NULL); - prefix = malloc(strlen(id) + 6); - assert(prefix != NULL); - - /* first with inflate */ - strcpy(prefix, id); - strcat(prefix, "-late"); - mem_setup(&strm); - strm.avail_in = 0; - strm.next_in = NULL; - ret = PREFIX(inflateInit2)(&strm, err < 0 ? 47 : -15); - assert(ret == Z_OK); - strm.avail_in = len; - strm.next_in = in; - do { - strm.avail_out = size; - strm.next_out = out; - ret = PREFIX(inflate)(&strm, Z_TREES); - assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR); - if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT) - break; - } while (strm.avail_in || strm.avail_out == 0); - if (err) { - assert(ret == Z_DATA_ERROR); - assert(strcmp(id, strm.msg) == 0); - } - PREFIX(inflateEnd)(&strm); - mem_done(&strm, prefix); - - /* then with inflateBack */ - if (err >= 0) { - strcpy(prefix, id); - strcat(prefix, "-back"); - mem_setup(&strm); - ret = PREFIX(inflateBackInit)(&strm, 15, win); - assert(ret == Z_OK); - strm.avail_in = len; - strm.next_in = in; - ret = PREFIX(inflateBack)(&strm, pull, NULL, push, NULL); - assert(ret != Z_STREAM_ERROR); - if (err && ret != Z_BUF_ERROR) { - assert(ret == Z_DATA_ERROR); - assert(strcmp(id, strm.msg) == 0); - } - PREFIX(inflateBackEnd)(&strm); - mem_done(&strm, prefix); - } - - /* clean up */ - free(prefix); - free(win); - free(out); - free(in); - return ret; -} - -/* cover deflate data cases in both inflate() and inflateBack() */ -static void cover_inflate(void) { - try("0 0 0 0 0", "invalid stored block lengths", 1); - try("3 0", "fixed", 0); - try("6", "invalid block type", 1); - try("1 1 0 fe ff 0", "stored", 0); - try("fc 0 0", "too many length or distance symbols", 1); - try("4 0 fe ff", "invalid code lengths set", 1); - try("4 0 24 49 0", "invalid bit length repeat", 1); - try("4 0 24 e9 ff ff", "invalid bit length repeat", 1); - try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1); - try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0", - "invalid literal/lengths set", 1); - try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1); - try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1); - try("2 7e ff ff", "invalid distance code", 1); -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 0); -#else - try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1); -#endif - - /* also trailer mismatch just in inflate() */ - try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1); - try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1", - "incorrect length check", -1); - try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0); - try("5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f", - "long code", 0); - try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0); - try("ed cf c1 b1 2c 47 10 c4 30 fa 6f 35 1d 1 82 59 3d fb be 2e 2a fc f c", - "long distance and extra", 0); - try("ed c0 81 0 0 0 0 80 a0 fd a9 17 a9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " - "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0); - inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258, - Z_STREAM_END); - inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK); -} - -/* cover remaining lines in inftrees.c */ -static void cover_trees(void) { - int ret; - unsigned bits; - uint16_t lens[16], work[16]; - code *next, table[ENOUGH_DISTS]; - - /* we need to call inflate_table() directly in order to manifest not- - enough errors, since zlib insures that enough is always enough */ - for (bits = 0; bits < 15; bits++) - lens[bits] = (uint16_t)(bits + 1); - lens[15] = 15; - next = table; - bits = 15; - ret = zng_inflate_table(DISTS, lens, 16, &next, &bits, work); - assert(ret == 1); - next = table; - bits = 1; - ret = zng_inflate_table(DISTS, lens, 16, &next, &bits, work); - assert(ret == 1); - fputs("inflate_table not enough errors\n", stderr); - (void)ret; -} - -/* cover remaining inffast.c decoding and window copying */ -static void cover_fast(void) { - inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68" - " ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR); - inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49" - " 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258, - Z_DATA_ERROR); - inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258, - Z_DATA_ERROR); - inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258, - Z_DATA_ERROR); - inf("d c7 1 ae eb 38 c 4 41 a0 87 72 de df fb 1f b8 36 b1 38 5d ff ff 0", - "fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR); - inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK); - inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0", - "contiguous and wrap around window", 6, -8, 259, Z_OK); - inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259, - Z_STREAM_END); -} - -int main(void) { - fprintf(stderr, "%s\n", zVersion()); - cover_support(); - cover_wrap(); - cover_back(); - cover_inflate(); - cover_trees(); - cover_fast(); - return 0; -} diff --git a/libs/zlibng/test/minideflate.c b/libs/zlibng/test/minideflate.c deleted file mode 100644 index 392516852d..0000000000 --- a/libs/zlibng/test/minideflate.c +++ /dev/null @@ -1,307 +0,0 @@ -/* minideflate.c -- test deflate/inflate under specific conditions - * Copyright (C) 2020 Nathan Moinvaziri - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -#if defined(_WIN32) || defined(__CYGWIN__) -# include -# include -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif - -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - -/* =========================================================================== - * deflate() using specialized parameters - */ -void deflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_buf_size, int32_t level, - int32_t window_bits, int32_t mem_level, int32_t strategy, int32_t flush) { - PREFIX3(stream) c_stream; /* compression stream */ - uint8_t *read_buf; - uint8_t *write_buf; - int32_t read; - int err; - - read_buf = (uint8_t *)malloc(read_buf_size); - if (read_buf == NULL) { - fprintf(stderr, "failed to create read buffer (%d)\n", read_buf_size); - return; - } - write_buf = (uint8_t *)malloc(write_buf_size); - if (write_buf == NULL) { - fprintf(stderr, "failed to create write buffer (%d)\n", write_buf_size); - free(read_buf); - return; - } - - c_stream.zalloc = NULL; - c_stream.zfree = NULL; - c_stream.opaque = (void *)0; - c_stream.total_in = 0; - c_stream.total_out = 0; - - err = PREFIX(deflateInit2)(&c_stream, level, Z_DEFLATED, window_bits, mem_level, strategy); - CHECK_ERR(err, "deflateInit2"); - - /* Process input using our read buffer and flush type, - * output to stdout only once write buffer is full */ - do { - read = (int32_t)fread(read_buf, 1, read_buf_size, fin); - if (read <= 0) - break; - - c_stream.next_in = (z_const uint8_t *)read_buf; - c_stream.next_out = write_buf; - c_stream.avail_in = read; - - do { - c_stream.avail_out = write_buf_size; - err = PREFIX(deflate)(&c_stream, flush); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - - if (c_stream.next_out == write_buf + write_buf_size) { - fwrite(write_buf, 1, write_buf_size, fout); - c_stream.next_out = write_buf; - } - } while (c_stream.next_in < read_buf + read); - } while (err == Z_OK); - - /* Finish the stream if necessary */ - if (flush != Z_FINISH) { - c_stream.avail_in = 0; - do { - if (c_stream.next_out == write_buf + write_buf_size) { - fwrite(write_buf, 1, write_buf_size, fout); - c_stream.next_out = write_buf; - } - - c_stream.avail_out = write_buf_size; - err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - } while (err == Z_OK); - } - - /* Output remaining data in write buffer */ - if (c_stream.next_out != write_buf) { - fwrite(write_buf, 1, c_stream.next_out - write_buf, fout); - } - - err = PREFIX(deflateEnd)(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - free(read_buf); - free(write_buf); -} - -/* =========================================================================== - * inflate() using specialized parameters - */ -void inflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_buf_size, int32_t window_bits, - int32_t flush) { - PREFIX3(stream) d_stream; /* decompression stream */ - uint8_t *read_buf; - uint8_t *write_buf; - int32_t read; - int err; - - - read_buf = (uint8_t *)malloc(read_buf_size); - if (read_buf == NULL) { - fprintf(stderr, "failed to create read buffer (%d)\n", read_buf_size); - return; - } - write_buf = (uint8_t *)malloc(write_buf_size); - if (write_buf == NULL) { - fprintf(stderr, "failed to create write buffer (%d)\n", write_buf_size); - free(read_buf); - return; - } - - d_stream.zalloc = NULL; - d_stream.zfree = NULL; - d_stream.opaque = (void *)0; - d_stream.total_in = 0; - d_stream.total_out = 0; - - err = PREFIX(inflateInit2)(&d_stream, window_bits); - CHECK_ERR(err, "inflateInit2"); - - /* Process input using our read buffer and flush type, - * output to stdout only once write buffer is full */ - do { - read = (int32_t)fread(read_buf, 1, read_buf_size, fin); - if (read <= 0) - break; - - d_stream.next_in = (z_const uint8_t *)read_buf; - d_stream.next_out = write_buf; - d_stream.avail_in = read; - - do { - d_stream.avail_out = write_buf_size; - err = PREFIX(inflate)(&d_stream, flush); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - - if (d_stream.next_out == write_buf + write_buf_size) { - fwrite(write_buf, 1, write_buf_size, fout); - d_stream.next_out = write_buf; - } - } while (d_stream.next_in < read_buf + read); - } while (err == Z_OK); - - /* Finish the stream if necessary */ - if (flush != Z_FINISH) { - d_stream.avail_in = 0; - do { - if (d_stream.next_out == write_buf + write_buf_size) { - fwrite(write_buf, 1, write_buf_size, fout); - d_stream.next_out = write_buf; - } - - d_stream.avail_out = write_buf_size; - err = PREFIX(inflate)(&d_stream, Z_FINISH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "inflate"); - } while (err == Z_OK); - } - - /* Output remaining data in write buffer */ - if (d_stream.next_out != write_buf) { - fwrite(write_buf, 1, d_stream.next_out - write_buf, fout); - } - - err = PREFIX(inflateEnd)(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - free(read_buf); - free(write_buf); -} - -void show_help(void) { - printf("Usage: minideflate [-c] [-f|-h|-R|-F] [-m level] [-r/-t size] [-s flush] [-w bits] [-0 to -9] [input file]\n\n" \ - " -c : write to standard output\n" \ - " -d : decompress\n" \ - " -f : compress with Z_FILTERED\n" \ - " -h : compress with Z_HUFFMAN_ONLY\n" \ - " -R : compress with Z_RLE\n" \ - " -F : compress with Z_FIXED\n" \ - " -m : memory level (1 to 8)\n" \ - " -w : window bits (8 to 15 for gzip, -8 to -15 for zlib)\n" \ - " -s : flush type (0 to 5)\n" \ - " -r : read buffer size\n" \ - " -t : write buffer size\n" \ - " -0 to -9 : compression level\n\n"); -} - -int main(int argc, char **argv) { - int32_t i; - int32_t mem_level = DEF_MEM_LEVEL; - int32_t window_bits = MAX_WBITS; - int32_t strategy = Z_DEFAULT_STRATEGY; - int32_t level = Z_DEFAULT_COMPRESSION; - int32_t read_buf_size = 4096; - int32_t write_buf_size = 4096; - int32_t flush = Z_NO_FLUSH; - uint8_t copyout = 0; - uint8_t uncompr = 0; - char out_file[320]; - FILE *fin = stdin; - FILE *fout = stdout; - - for (i = 1; i < argc; i++) { - if ((strcmp(argv[i], "-m") == 0) && (i + 1 < argc)) - mem_level = atoi(argv[++i]); - else if ((strcmp(argv[i], "-w") == 0) && (i + 1 < argc)) - window_bits = atoi(argv[++i]); - else if ((strcmp(argv[i], "-r") == 0) && (i + 1 < argc)) - read_buf_size = atoi(argv[++i]); - else if ((strcmp(argv[i], "-t") == 0) && (i + 1 < argc)) - write_buf_size = atoi(argv[++i]); - else if ((strcmp(argv[i], "-s") == 0) && (i + 1 < argc)) - flush = atoi(argv[++i]); - else if (strcmp(argv[i], "-c") == 0) - copyout = 1; - else if (strcmp(argv[i], "-d") == 0) - uncompr = 1; - else if (strcmp(argv[i], "-f") == 0) - strategy = Z_FILTERED; - else if (strcmp(argv[i], "-h") == 0) - strategy = Z_HUFFMAN_ONLY; - else if (strcmp(argv[i], "-R") == 0) - strategy = Z_RLE; - else if (argv[i][0] == '-' && argv[i][1] >= '0' && argv[i][1] <= '9' && argv[i][2] == 0) - level = argv[i][1] - '0'; - else if (strcmp(argv[i], "--help") == 0) { - show_help(); - return 0; - } else if (argv[i][0] == '-') { - show_help(); - return 64; /* EX_USAGE */ - } else - break; - } - - SET_BINARY_MODE(stdin); - SET_BINARY_MODE(stdout); - if (i != argc) { - fin = fopen(argv[i], "rb+"); - if (fin == NULL) { - fprintf(stderr, "Failed to open file: %s\n", argv[i]); - exit(1); - } - if (!copyout) { - snprintf(out_file, sizeof(out_file), "%s%s", argv[i], (window_bits < 0) ? ".zz" : ".gz"); - fout = fopen(out_file, "wb"); - if (fout == NULL) { - fprintf(stderr, "Failed to open file: %s\n", out_file); - exit(1); - } - } - } - - if (uncompr) { - inflate_params(fin, fout, read_buf_size, write_buf_size, window_bits, flush); - } else { - deflate_params(fin, fout, read_buf_size, write_buf_size, level, window_bits, mem_level, strategy, flush); - } - - if (fin != stdin) { - fclose(fin); - } - if (fout != stdout) { - fclose(fout); - } - - return 0; -} diff --git a/libs/zlibng/test/minigzip.c b/libs/zlibng/test/minigzip.c deleted file mode 100644 index 2e4ef8e2a5..0000000000 --- a/libs/zlibng/test/minigzip.c +++ /dev/null @@ -1,376 +0,0 @@ -/* minigzip.c -- simulate gzip using the zlib compression library - * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * minigzip is a minimal implementation of the gzip utility. This is - * only an example of using zlib and isn't meant to replace the - * full-featured gzip. No attempt is made to deal with file systems - * limiting names to 14 or 8+3 characters, etc... Error checking is - * very limited. So use minigzip only for testing; use gzip for the - * real thing. - */ - -#define _POSIX_SOURCE 1 /* This file needs POSIX for fdopen(). */ -#define _POSIX_C_SOURCE 200112 /* For snprintf(). */ - -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif -#include - -#include -#include - -#ifdef USE_MMAP -# include -# include -# include -#endif - -#ifndef UNALIGNED_OK -# include -#endif - -#if defined(_WIN32) || defined(__CYGWIN__) -# include -# include -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1900 -# define snprintf _snprintf -#endif - -#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) -#ifndef _WIN32 /* unlink already in stdio.h for Win32 */ -extern int unlink (const char *); -#endif -#endif - -#ifndef GZ_SUFFIX -# define GZ_SUFFIX ".gz" -#endif -#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) - -#ifndef BUFLEN -# define BUFLEN 16384 /* read buffer size */ -#endif -#define BUFLENW (BUFLEN * 3) /* write buffer size */ -#define MAX_NAME_LEN 1024 - -static char *prog; - -void error (const char *msg); -void gz_compress (FILE *in, gzFile out); -#ifdef USE_MMAP -int gz_compress_mmap (FILE *in, gzFile out); -#endif -void gz_uncompress (gzFile in, FILE *out); -void file_compress (char *file, char *mode, int keep); -void file_uncompress (char *file, int keep); -int main (int argc, char *argv[]); - -/* =========================================================================== - * Display error message and exit - */ -void error(const char *msg) { - fprintf(stderr, "%s: %s\n", prog, msg); - exit(1); -} - -/* =========================================================================== - * Compress input to output then close both files. - */ - -void gz_compress(FILE *in, gzFile out) { - char *buf; - int len; - int err; - -#ifdef USE_MMAP - /* Try first compressing with mmap. If mmap fails (minigzip used in a - * pipe), use the normal fread loop. - */ - if (gz_compress_mmap(in, out) == Z_OK) return; -#endif - buf = (char *)calloc(BUFLEN, 1); - if (buf == NULL) { - perror("out of memory"); - exit(1); - } - - for (;;) { - len = (int)fread(buf, 1, BUFLEN, in); - if (ferror(in)) { - free(buf); - perror("fread"); - exit(1); - } - if (len == 0) break; - - if (PREFIX(gzwrite)(out, buf, (unsigned)len) != len) error(PREFIX(gzerror)(out, &err)); - } - free(buf); - fclose(in); - if (PREFIX(gzclose)(out) != Z_OK) error("failed gzclose"); -} - -#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ - -/* Try compressing the input file at once using mmap. Return Z_OK if - * if success, Z_ERRNO otherwise. - */ -int gz_compress_mmap(FILE *in, gzFile out) { - int len; - int err; - int ifd = fileno(in); - char *buf; /* mmap'ed buffer for the entire input file */ - off_t buf_len; /* length of the input file */ - struct stat sb; - - /* Determine the size of the file, needed for mmap: */ - if (fstat(ifd, &sb) < 0) return Z_ERRNO; - buf_len = sb.st_size; - if (buf_len <= 0) return Z_ERRNO; - - /* Now do the actual mmap: */ - buf = mmap((void *)0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); - if (buf == (char *)(-1)) return Z_ERRNO; - - /* Compress the whole file at once: */ - len = PREFIX(gzwrite)(out, buf, (unsigned)buf_len); - - if (len != (int)buf_len) error(PREFIX(gzerror)(out, &err)); - - munmap(buf, buf_len); - fclose(in); - if (PREFIX(gzclose)(out) != Z_OK) error("failed gzclose"); - return Z_OK; -} -#endif /* USE_MMAP */ - -/* =========================================================================== - * Uncompress input to output then close both files. - */ -void gz_uncompress(gzFile in, FILE *out) { - char *buf = (char *)malloc(BUFLENW); - int len; - int err; - - if (buf == NULL) error("out of memory"); - - for (;;) { - len = PREFIX(gzread)(in, buf, BUFLENW); - if (len < 0) { - free(buf); - error(PREFIX(gzerror)(in, &err)); - } - if (len == 0) break; - - if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { - free(buf); - error("failed fwrite"); - } - } - free(buf); - if (fclose(out)) error("failed fclose"); - - if (PREFIX(gzclose)(in) != Z_OK) error("failed gzclose"); -} - - -/* =========================================================================== - * Compress the given file: create a corresponding .gz file and remove the - * original. - */ -void file_compress(char *file, char *mode, int keep) { - char outfile[MAX_NAME_LEN]; - FILE *in; - gzFile out; - - if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { - fprintf(stderr, "%s: filename too long\n", prog); - exit(1); - } - - snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX); - - in = fopen(file, "rb"); - if (in == NULL) { - perror(file); - exit(1); - } - out = PREFIX(gzopen)(outfile, mode); - if (out == NULL) { - fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); - exit(1); - } - gz_compress(in, out); - - if (!keep) - unlink(file); -} - - -/* =========================================================================== - * Uncompress the given file and remove the original. - */ -void file_uncompress(char *file, int keep) { - char buf[MAX_NAME_LEN]; - char *infile, *outfile; - FILE *out; - gzFile in; - size_t len = strlen(file); - - if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { - fprintf(stderr, "%s: filename too long\n", prog); - exit(1); - } - - snprintf(buf, sizeof(buf), "%s", file); - - if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { - infile = file; - outfile = buf; - outfile[len-3] = '\0'; - } else { - outfile = file; - infile = buf; - snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX); - } - in = PREFIX(gzopen)(infile, "rb"); - if (in == NULL) { - fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); - exit(1); - } - out = fopen(outfile, "wb"); - if (out == NULL) { - perror(file); - exit(1); - } - - gz_uncompress(in, out); - - if (!keep) - unlink(infile); -} - -void show_help(void) { - printf("Usage: minigzip [-c] [-d] [-k] [-f|-h|-R|-F|-T] [-A] [-0 to -9] [files...]\n\n" \ - " -c : write to standard output\n" \ - " -d : decompress\n" \ - " -k : keep input files\n" \ - " -f : compress with Z_FILTERED\n" \ - " -h : compress with Z_HUFFMAN_ONLY\n" \ - " -R : compress with Z_RLE\n" \ - " -F : compress with Z_FIXED\n" \ - " -T : stored raw\n" \ - " -A : auto detect type\n" \ - " -0 to -9 : compression level\n\n"); -} - -int main(int argc, char *argv[]) { - int copyout = 0; - int uncompr = 0; - int keep = 0; - int i = 0; - gzFile file; - char *bname, outmode[20]; - char *strategy = ""; - char *level = "6"; - char *type = "b"; - - prog = argv[i]; - bname = strrchr(argv[i], '/'); - if (bname) - bname++; - else - bname = argv[i]; - - if (!strcmp(bname, "gunzip")) - uncompr = 1; - else if (!strcmp(bname, "zcat")) - copyout = uncompr = 1; - - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-c") == 0) - copyout = 1; - else if (strcmp(argv[i], "-d") == 0) - uncompr = 1; - else if (strcmp(argv[i], "-k") == 0) - keep = 1; - else if (strcmp(argv[i], "-A") == 0) - type = ""; - else if (argv[i][0] == '-' && (argv[i][1] == 'f' || argv[i][1] == 'h' || - argv[i][1] == 'R' || argv[i][1] == 'F' || argv[i][1] == 'T') && argv[i][2] == 0) - strategy = argv[i] + 1; - else if (argv[i][0] == '-' && argv[i][1] >= '0' && argv[i][1] <= '9' && argv[i][2] == 0) - level = argv[i] + 1; - else if (strcmp(argv[i], "--help") == 0) { - show_help(); - return 0; - } else if (argv[i][0] == '-') { - show_help(); - return 64; /* EX_USAGE */ - } else { - break; - } - } - - snprintf(outmode, sizeof(outmode), "w%s%s%s", type, strategy, level); - - if (i == argc) { - SET_BINARY_MODE(stdin); - SET_BINARY_MODE(stdout); - if (uncompr) { - file = PREFIX(gzdopen)(fileno(stdin), "rb"); - if (file == NULL) error("can't gzdopen stdin"); - gz_uncompress(file, stdout); - } else { - file = PREFIX(gzdopen)(fileno(stdout), outmode); - if (file == NULL) error("can't gzdopen stdout"); - gz_compress(stdin, file); - } - } else { - if (copyout) { - SET_BINARY_MODE(stdout); - } - do { - if (uncompr) { - if (copyout) { - file = PREFIX(gzopen)(argv[i], "rb"); - if (file == NULL) - fprintf(stderr, "%s: can't gzopen %s\n", prog, argv[i]); - else - gz_uncompress(file, stdout); - } else { - file_uncompress(argv[i], keep); - } - } else { - if (copyout) { - FILE * in = fopen(argv[i], "rb"); - - if (in == NULL) { - perror(argv[i]); - } else { - file = PREFIX(gzdopen)(fileno(stdout), outmode); - if (file == NULL) error("can't gzdopen stdout"); - - gz_compress(in, file); - } - - } else { - file_compress(argv[i], outmode, keep); - } - } - } while (++i < argc); - } - return 0; -} diff --git a/libs/zlibng/test/pkgcheck.sh b/libs/zlibng/test/pkgcheck.sh deleted file mode 100644 index 4c757dff10..0000000000 --- a/libs/zlibng/test/pkgcheck.sh +++ /dev/null @@ -1,176 +0,0 @@ -#!/bin/sh - -usage() { - cat <<"_EOF_" -Usage: sh test/pkgcheck.sh [--zlib-compat] - -Verifies that the various build systems produce identical results on a Unixlike system. -If --zlib-compat, tests with zlib compatible builds. - -To build the 32 bit version for the current 64 bit arch: - -$ sudo apt install ninja-build diffoscope gcc-multilib -$ export CMAKE_ARGS="-DCMAKE_C_FLAGS=-m32" CFLAGS=-m32 LDFLAGS=-m32 -$ sh test/pkgcheck.sh - -To cross-build, install the appropriate qemu and gcc packages, -and set the environment variables used by configure or cmake. -On Ubuntu, for example (values taken from .github/workflows/pkgconf.yml): - -arm HF: -$ sudo apt install ninja-build diffoscope qemu gcc-arm-linux-gnueabihf libc6-dev-armhf-cross -$ export CHOST=arm-linux-gnueabihf -$ export CMAKE_ARGS="-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=${CHOST}" - -aarch64: -$ sudo apt install ninja-build diffoscope qemu gcc-aarch64-linux-gnu libc6-dev-arm64-cross -$ export CHOST=aarch64-linux-gnu -$ export CMAKE_ARGS="-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DCMAKE_C_COMPILER_TARGET=${CHOST}" - -ppc (32 bit big endian): -$ sudo apt install ninja-build diffoscope qemu gcc-powerpc-linux-gnu libc6-dev-powerpc-cross -$ export CHOST=powerpc-linux-gnu -$ export CMAKE_ARGS="-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake" - -ppc64le: -$ sudo apt install ninja-build diffoscope qemu gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross -$ export CHOST=powerpc64le-linux-gnu -$ export CMAKE_ARGS="-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le.cmake" - -then: -$ export CC=${CHOST}-gcc -$ sh test/pkgcheck.sh [--zlib-compat] - -Note: on Mac, you may also need to do 'sudo xcode-select -r' to get cmake to match configure/make's behavior (i.e. omit -isysroot). -_EOF_ -} - -set -ex - -# Caller can also set CMAKE_ARGS or CONFIGURE_ARGS if desired -CMAKE_ARGS=${CMAKE_ARGS} -CONFIGURE_ARGS=${CONFIGURE_ARGS} - -case "$1" in ---zlib-compat) - suffix="" - CMAKE_ARGS="$CMAKE_ARGS -DZLIB_COMPAT=ON" - CONFIGURE_ARGS="$CONFIGURE_ARGS --zlib-compat" - ;; -"") - suffix="-ng" - ;; -*) - echo "Unknown arg '$1'" - usage - exit 1 - ;; -esac - -if ! test -f "configure" -then - echo "Please run from top of source tree" - exit 1 -fi - -# Tell GNU's ld etc. to use Jan 1 1970 when embedding timestamps -# Probably only needed on older systems (ubuntu 14.04, BSD?) -export SOURCE_DATE_EPOCH=0 -case $(uname) in -Darwin) - # Tell Apple's ar etc. to use zero timestamps - export ZERO_AR_DATE=1 - # What CPU are we running on, exactly? - sysctl -n machdep.cpu.brand_string - sysctl -n machdep.cpu.features - sysctl -n machdep.cpu.leaf7_features - sysctl -n machdep.cpu.extfeatures - ;; -esac - -# Use same compiler for make and cmake builds -if test "$CC"x = ""x -then - if clang --version - then - export CC=clang - elif gcc --version - then - export CC=gcc - fi -fi - -# New build system -# Happens to delete top-level zconf.h -# (which itself is a bug, https://github.com/madler/zlib/issues/162 ) -# which triggers another bug later in configure, -# https://github.com/madler/zlib/issues/499 -rm -rf btmp2 pkgtmp2 -mkdir btmp2 pkgtmp2 -export DESTDIR=$(pwd)/pkgtmp2 -cd btmp2 - cmake -G Ninja ${CMAKE_ARGS} .. - ninja -v - ninja install -cd .. - -# Original build system -rm -rf btmp1 pkgtmp1 -mkdir btmp1 pkgtmp1 -export DESTDIR=$(pwd)/pkgtmp1 -cd btmp1 - case $(uname) in - Darwin) - export LDFLAGS="-Wl,-headerpad_max_install_names" - ;; - esac - ../configure $CONFIGURE_ARGS - make - make install -cd .. - -repack_ar() { - if ! cmp --silent pkgtmp1/usr/local/lib/libz$suffix.a pkgtmp2/usr/local/lib/libz$suffix.a - then - echo "libz$suffix.a does not match. Probably filenames differ (.o vs .c.o). Unpacking and renaming..." - # Note: %% is posix shell syntax meaning "Remove Largest Suffix Pattern", see - # https://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02 - cd pkgtmp1; ar x usr/local/lib/libz$suffix.a; rm usr/local/lib/libz$suffix.a; cd .. - cd pkgtmp2; ar x usr/local/lib/libz$suffix.a; rm usr/local/lib/libz$suffix.a; for a in *.c.o; do mv $a ${a%%.c.o}.o; done; cd .. - # Also, remove __.SYMDEF SORTED if present, as it has those funky .c.o names embedded in it. - rm -f pkgtmp[12]/__.SYMDEF\ SORTED - fi -} - -case $(uname) in -Darwin) - # Remove the build uuid. - dylib1=$(find pkgtmp1 -type f -name '*.dylib*') - dylib2=$(find pkgtmp2 -type f -name '*.dylib*') - strip -x -no_uuid "$dylib1" - strip -x -no_uuid "$dylib2" - ;; -esac - -# The ar on newer systems defaults to -D (i.e. deterministic), -# but FreeBSD 12.1, Debian 8, and Ubuntu 14.04 seem to not do that. -# I had trouble passing -D safely to the ar inside CMakeLists.txt, -# so punt and unpack the archive if needed before comparing. -# Also, cmake uses different .o suffix anyway... -repack_ar - -if diff -Nur pkgtmp1 pkgtmp2 -then - echo pkgcheck-cmake-bits-identical PASS -else - echo pkgcheck-cmake-bits-identical FAIL - dylib1=$(find pkgtmp1 -type f -name '*.dylib*' -print -o -type f -name '*.so.*' -print) - dylib2=$(find pkgtmp2 -type f -name '*.dylib*' -print -o -type f -name '*.so.*' -print) - diffoscope $dylib1 $dylib2 | cat - exit 1 -fi - -rm -rf btmp1 btmp2 pkgtmp1 pkgtmp2 - -# any failure would have caused an early exit already -echo "pkgcheck: PASS" diff --git a/libs/zlibng/test/switchlevels.c b/libs/zlibng/test/switchlevels.c deleted file mode 100644 index 0f850113e2..0000000000 --- a/libs/zlibng/test/switchlevels.c +++ /dev/null @@ -1,169 +0,0 @@ -/* Compresses a user-specified number of chunks from stdin into stdout as a single gzip stream. - * Each chunk is compressed with a user-specified level. - */ - -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -#include -#include -#include - -#if defined(_WIN32) || defined(__CYGWIN__) -# include -# include -# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -#else -# define SET_BINARY_MODE(file) -#endif - -static int read_all(unsigned char *buf, size_t size) { - size_t total_read = 0; - while (total_read < size) { - size_t n_read = fread(buf + total_read, 1, size - total_read, stdin); - if (ferror(stdin)) { - perror("fread\n"); - return 1; - } - if (n_read == 0) { - fprintf(stderr, "Premature EOF\n"); - return 1; - } - total_read += n_read; - } - return 0; -} - -static int write_all(unsigned char *buf, size_t size) { - size_t total_written = 0; - while (total_written < size) { - size_t n_written = fwrite(buf + total_written, 1, size - total_written, stdout); - if (ferror(stdout)) { - perror("fwrite\n"); - return 1; - } - total_written += n_written; - } - return 0; -} - -static int compress_chunk(PREFIX3(stream) *strm, int level, int size, int last) { - int ret = 1; - int err = 0; - unsigned long compsize; - unsigned char *buf; - - if (size <= 0) { - fprintf(stderr, "compress_chunk() invalid size %d\n", size); - goto done; - } - if (level < 0 || level > 9) { - fprintf(stderr, "compress_chunk() invalid level %d\n", level); - goto done; - } - - compsize = 100 + 2 * PREFIX(deflateBound)(strm, size); - buf = malloc(size + compsize); - if (buf == NULL) { - fprintf(stderr, "Out of memory\n"); - goto done; - } - if (read_all(buf, size) != 0) { - goto free_buf; - } - - /* Provide only output buffer to deflateParams(). It might need some space to flush the leftovers from the last - * deflate(), but we don't want it to compress anything new. */ - strm->next_in = NULL; - strm->avail_in = 0; - strm->next_out = buf + size; - strm->avail_out = compsize; - err = PREFIX(deflateParams)(strm, level, Z_DEFAULT_STRATEGY); - if (err != Z_OK) { - fprintf(stderr, "deflateParams() failed with code %d\n", err); - goto free_buf; - } - - /* Provide input buffer to deflate(). */ - strm->next_in = buf; - strm->avail_in = size; - err = PREFIX(deflate)(strm, last ? Z_FINISH : Z_SYNC_FLUSH); - if ((!last && err != Z_OK) || (last && err != Z_STREAM_END)) { - fprintf(stderr, "deflate() failed with code %d\n", err); - goto free_buf; - } - if (strm->avail_in != 0) { - fprintf(stderr, "deflate() did not consume %d bytes of input\n", strm->avail_in); - goto free_buf; - } - if (write_all(buf + size, compsize - strm->avail_out) != 0) { - goto free_buf; - } - ret = 0; - -free_buf: - free(buf); -done: - return ret; -} - -void show_help(void) -{ - printf("Usage: switchlevels [-w bits] level1 size1 [level2 size2 ...]\n\n" \ - " -w : window bits (8 to 15 for gzip, -8 to -15 for zlib)\n\n"); -} - -int main(int argc, char **argv) { - int ret = EXIT_FAILURE; - int err = 0; - int size = 0; - int level = Z_DEFAULT_COMPRESSION; - int level_arg = 1; - int window_bits = MAX_WBITS + 16; - PREFIX3(stream) strm; - - - if ((argc == 1) || (argc == 2 && strcmp(argv[1], "--help") == 0)) { - show_help(); - return 0; - } - - SET_BINARY_MODE(stdin); - SET_BINARY_MODE(stdout); - - memset(&strm, 0, sizeof(strm)); - - for (int i = 1; i < argc - 1; i++) { - if (strcmp(argv[i], "-w") == 0 && i+1 < argc) { - window_bits = atoi(argv[++i]); - } else { - level_arg = i; - level = atoi(argv[i]); - break; - } - } - - err = PREFIX(deflateInit2)(&strm, level, Z_DEFLATED, window_bits, 8, Z_DEFAULT_STRATEGY); - if (err != Z_OK) { - fprintf(stderr, "deflateInit() failed with code %d\n", err); - goto done; - } - - for (int i = level_arg; i < argc - 1; i += 2) { - level = atoi(argv[i]); - size = atoi(argv[i + 1]); - if (compress_chunk(&strm, level, size, i + 2 >= argc - 1) != 0) { - goto deflate_end; - } - } - ret = EXIT_SUCCESS; - -deflate_end: - PREFIX(deflateEnd)(&strm); -done: - return ret; -} diff --git a/libs/zlibng/test/testCVEinputs.sh b/libs/zlibng/test/testCVEinputs.sh deleted file mode 100644 index 84f6b31c54..0000000000 --- a/libs/zlibng/test/testCVEinputs.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -TESTDIR="$(dirname "$0")" - -# check for QEMU if QEMU_RUN is set -if [ ! -z "${QEMU_RUN}" ]; then - QEMU_VERSION=$(${QEMU_RUN} --version 2> /dev/null) - if [ -z "${QEMU_VERSION}" ]; then - echo "**** You need QEMU to run tests on non-native platform" - exit 1 - fi -fi - -CVEs="CVE-2002-0059 CVE-2004-0797 CVE-2005-1849 CVE-2005-2096" - -for CVE in $CVEs; do - fail=0 - for testcase in ${TESTDIR}/${CVE}/*.gz; do - ${QEMU_RUN} ../minigzip${EXE} -d < "$testcase" - # we expect that a 1 error code is OK - # for a vulnerable failure we'd expect 134 or similar - if [ $? -ne 1 ] && [ $? -ne 0 ]; then - fail=1 - fi - done - if [ $fail -eq 0 ]; then - echo " --- zlib not vulnerable to $CVE ---"; - else - echo " --- zlib VULNERABLE to $CVE ---"; exit 1; - fi -done diff --git a/libs/zlibng/tools/codecov-upload.sh b/libs/zlibng/tools/codecov-upload.sh deleted file mode 100644 index e3a48aab76..0000000000 --- a/libs/zlibng/tools/codecov-upload.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -set -ux -cd "$CODECOV_DIR" -python -m codecov --required --flags "$CODECOV_FLAGS" --name "$CODECOV_NAME" --gcov-exec="$CODECOV_EXEC" -if [ $? -ne 0 ]; then - sleep 30 - python -m codecov --required --flags "$CODECOV_FLAGS" --name "$CODECOV_NAME" --gcov-exec="$CODECOV_EXEC" --tries=25 -fi -exit $? diff --git a/libs/zlibng/tools/config.sub b/libs/zlibng/tools/config.sub deleted file mode 100644 index dba175ae31..0000000000 --- a/libs/zlibng/tools/config.sub +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -# Canonicalize CHOST. -# In particular, converts Debian multiarch tuples into GNU triplets. -# See also -# https://wiki.debian.org/Multiarch/Tuples -# https://wiki.gentoo.org/wiki/CHOST -# If you need an architecture not listed here, file a bug at github.com/zlib-ng/zlib-ng -# and work around the problem by dropping libtool's much more comprehensive config.sub -# on top of this file, see -# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub - -case "$1" in -*-*-linux-gnu*) echo $1;; -i686-linux-gnu*|x86_64-linux-gnu*) echo $1 | sed 's/-linux-gnu/-pc-linux-gnu/';; -*-linux-gnu*) echo $1 | sed 's/-linux-gnu/-unknown-linux-gnu/';; -*) echo $1;; -esac diff --git a/libs/zlibng/tools/makecrct.c b/libs/zlibng/tools/makecrct.c deleted file mode 100644 index 323d0c03dd..0000000000 --- a/libs/zlibng/tools/makecrct.c +++ /dev/null @@ -1,177 +0,0 @@ -/* crc32.c -- output crc32 tables - * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h -*/ - -#include -#include -#include "zbuild.h" -#include "deflate.h" -#include "crc32_p.h" - -static uint32_t crc_table[8][256]; -static uint32_t crc_comb[GF2_DIM][GF2_DIM]; - -static void gf2_matrix_square(uint32_t *square, const uint32_t *mat); -static void make_crc_table(void); -static void make_crc_combine_table(void); -static void print_crc_table(void); -static void print_crc_combine_table(void); -static void write_table(const uint32_t *, int); - - -/* ========================================================================= */ -static void gf2_matrix_square(uint32_t *square, const uint32_t *mat) { - int n; - - for (n = 0; n < GF2_DIM; n++) - square[n] = gf2_matrix_times(mat, mat[n]); -} - -/* ========================================================================= - Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The first table is simply the CRC of all possible eight bit values. This is - all the information needed to generate CRCs on data a byte at a time for all - combinations of CRC register values and incoming bytes. The remaining tables - allow for word-at-a-time CRC calculation for both big-endian and little- - endian machines, where a word is four bytes. -*/ -static void make_crc_table(void) { - int n, k; - uint32_t c; - uint32_t poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static const unsigned char p[] = {0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26}; - - /* make exclusive-or pattern from polynomial (0xedb88320) */ - poly = 0; - for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) - poly |= (uint32_t)1 << (31 - p[n]); - - /* generate a crc for every 8-bit value */ - for (n = 0; n < 256; n++) { - c = (uint32_t)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[0][n] = c; - } - - /* generate crc for each value followed by one, two, and three zeros, - and then the byte reversal of those as well as the first table */ - for (n = 0; n < 256; n++) { - c = crc_table[0][n]; - crc_table[4][n] = ZSWAP32(c); - for (k = 1; k < 4; k++) { - c = crc_table[0][c & 0xff] ^ (c >> 8); - crc_table[k][n] = c; - crc_table[k + 4][n] = ZSWAP32(c); - } - } -} - -static void make_crc_combine_table(void) { - int n, k; - /* generate zero operators table for crc32_combine() */ - - /* generate the operator to apply a single zero bit to a CRC -- the - first row adds the polynomial if the low bit is a 1, and the - remaining rows shift the CRC right one bit */ - k = GF2_DIM - 3; - crc_comb[k][0] = 0xedb88320UL; /* CRC-32 polynomial */ - uint32_t row = 1; - for (n = 1; n < GF2_DIM; n++) { - crc_comb[k][n] = row; - row <<= 1; - } - /* generate operators that apply 2, 4, and 8 zeros to a CRC, putting - the last one, the operator for one zero byte, at the 0 position */ - gf2_matrix_square(crc_comb[k + 1], crc_comb[k]); - gf2_matrix_square(crc_comb[k + 2], crc_comb[k + 1]); - gf2_matrix_square(crc_comb[0], crc_comb[k + 2]); - - /* generate operators for applying 2^n zero bytes to a CRC, filling out - the remainder of the table -- the operators repeat after GF2_DIM - values of n, so the table only needs GF2_DIM entries, regardless of - the size of the length being processed */ - for (n = 1; n < k; n++) - gf2_matrix_square(crc_comb[n], crc_comb[n - 1]); -} - -static void write_table(const uint32_t *table, int k) { - int n; - - for (n = 0; n < k; n++) - printf("%s0x%08" PRIx32 "%s", n % 5 ? "" : " ", - (uint32_t)(table[n]), - n == k - 1 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); -} - -static void print_crc_table(void) { - int k; - printf("#ifndef CRC32_TBL_H_\n"); - printf("#define CRC32_TBL_H_\n\n"); - printf("/* crc32_tbl.h -- tables for rapid CRC calculation\n"); - printf(" * Generated automatically by makecrct.c\n */\n\n"); - - /* print CRC table */ - printf("static const uint32_t "); - printf("crc_table[8][256] =\n{\n {\n"); - write_table(crc_table[0], 256); - for (k = 1; k < 8; k++) { - printf(" },\n {\n"); - write_table(crc_table[k], 256); - } - printf(" }\n};\n\n"); - - printf("#endif /* CRC32_TBL_H_ */\n"); -} - -static void print_crc_combine_table(void) { - int k; - printf("#ifndef CRC32_COMB_TBL_H_\n"); - printf("#define CRC32_COMB_TBL_H_\n\n"); - printf("/* crc32_comb_tbl.h -- zero operators table for CRC combine\n"); - printf(" * Generated automatically by makecrct.c\n */\n\n"); - - /* print zero operator table */ - printf("static const uint32_t "); - printf("crc_comb[%d][%d] =\n{\n {\n", GF2_DIM, GF2_DIM); - write_table(crc_comb[0], GF2_DIM); - for (k = 1; k < GF2_DIM; k++) { - printf(" },\n {\n"); - write_table(crc_comb[k], GF2_DIM); - } - printf(" }\n};\n\n"); - - printf("#endif /* CRC32_COMB_TBL_H_ */\n"); -} - -// The output of this application can be piped out to recreate crc32.h -int main(int argc, char *argv[]) { - if (argc > 1 && strcmp(argv[1], "-c") == 0) { - make_crc_combine_table(); - print_crc_combine_table(); - } else { - make_crc_table(); - print_crc_table(); - } - return 0; -} diff --git a/libs/zlibng/tools/makefixed.c b/libs/zlibng/tools/makefixed.c deleted file mode 100644 index 7fe71e75ee..0000000000 --- a/libs/zlibng/tools/makefixed.c +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include "zbuild.h" -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" - -// Build and return state with length and distance decoding tables and index sizes set to fixed code decoding. -void Z_INTERNAL buildfixedtables(struct inflate_state *state) { - static code *lenfix, *distfix; - static code fixed[544]; - - // build fixed huffman tables - unsigned sym, bits; - static code *next; - - // literal/length table - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - zng_inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - // distance table - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - zng_inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - - -// Create fixed tables on the fly and write out a inffixed_tbl.h file that is #include'd above. -// makefixed() writes those tables to stdout, which would be piped to inffixed_tbl.h. -void makefixed(void) { - unsigned low, size; - struct inflate_state state; - - memset(&state, 0, sizeof(state)); - buildfixedtables(&state); - puts("/* inffixed_tbl.h -- table for decoding fixed codes"); - puts(" * Generated automatically by makefixed()."); - puts(" */"); - puts(""); - puts("/* WARNING: this file should *not* be used by applications."); - puts(" * It is part of the implementation of this library and is"); - puts(" * subject to change. Applications should only use zlib.h."); - puts(" */"); - puts(""); - size = 1U << 9; - printf("static const code lenfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 7) == 0) - printf("\n "); - printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, - state.lencode[low].bits, state.lencode[low].val); - if (++low == size) - break; - putchar(','); - } - puts("\n};"); - size = 1U << 5; - printf("\nstatic const code distfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 6) == 0) - printf("\n "); - printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, state.distcode[low].val); - if (++low == size) - break; - putchar(','); - } - puts("\n};"); -} - -// The output of this application can be piped out to recreate inffixed_tbl.h -int main(void) { - makefixed(); - return 0; -} diff --git a/libs/zlibng/tools/maketrees.c b/libs/zlibng/tools/maketrees.c deleted file mode 100644 index 337f2fc070..0000000000 --- a/libs/zlibng/tools/maketrees.c +++ /dev/null @@ -1,147 +0,0 @@ -/* maketrees.c -- output static huffman trees - * Copyright (C) 1995-2017 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include -#include "zbuild.h" -#include "deflate.h" -#include "trees.h" - -static ct_data static_ltree[L_CODES+2]; -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see zng_tr_init). - */ - -static ct_data static_dtree[D_CODES]; -/* The static distance tree. (Actually a trivial tree since all codes use 5 bits.) - */ - -static unsigned char dist_code[DIST_CODE_LEN]; -/* Distance codes. The first 256 values correspond to the distances 3 .. 258, - * the last 256 values correspond to the top 8 bits of the 15 bit distances. - */ - -static unsigned char length_code[MAX_MATCH-MIN_MATCH+1]; -/* length code for each normalized match length (0 == MIN_MATCH) */ - -static int base_length[LENGTH_CODES]; -/* First normalized length for each code (0 = MIN_MATCH) */ - -static int base_dist[D_CODES]; -/* First normalized distance for each code (0 = distance of 1) */ - - -static void tr_static_init(void) { - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - uint16_t bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1 << extra_lbits[code]); n++) { - length_code[length++] = (unsigned char)code; - } - } - Assert(length == 256, "tr_static_init: length != 256"); - /* Note that the length 255 (match length 258) can be represented in two different - * ways: code 284 + 5 bits or code 285, so we overwrite length_code[255] to use the best encoding: - */ - length_code[length-1] = (unsigned char)code; - - /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ - dist = 0; - for (code = 0; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1 << extra_dbits[code]); n++) { - dist_code[dist++] = (unsigned char)code; - } - } - Assert(dist == 256, "tr_static_init: dist != 256"); - dist >>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1 << (extra_dbits[code]-7)); n++) { - dist_code[256 + dist++] = (unsigned char)code; - } - } - Assert(dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) - bl_count[bits] = 0; - n = 0; - while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the tree construction - * to get a canonical Huffman tree (longest code all ones) - */ - gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = (uint16_t)bi_reverse((unsigned)n, 5); - } -} - -# define SEPARATOR(i, last, width) \ - ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) - -static void gen_trees_header() { - int i; - - printf("#ifndef TREES_TBL_H_\n"); - printf("#define TREES_TBL_H_\n\n"); - - printf("/* header created automatically with maketrees.c */\n\n"); - - printf("Z_INTERNAL const ct_data static_ltree[L_CODES+2] = {\n"); - for (i = 0; i < L_CODES+2; i++) { - printf("{{%3u},{%u}}%s", static_ltree[i].Code, static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); - } - - printf("Z_INTERNAL const ct_data static_dtree[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - printf("{{%2u},{%u}}%s", static_dtree[i].Code, static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); - } - - printf("const unsigned char Z_INTERNAL zng_dist_code[DIST_CODE_LEN] = {\n"); - for (i = 0; i < DIST_CODE_LEN; i++) { - printf("%2u%s", dist_code[i], SEPARATOR(i, DIST_CODE_LEN-1, 20)); - } - - printf("const unsigned char Z_INTERNAL zng_length_code[MAX_MATCH-MIN_MATCH+1] = {\n"); - for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { - printf("%2u%s", length_code[i], SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); - } - - printf("Z_INTERNAL const int base_length[LENGTH_CODES] = {\n"); - for (i = 0; i < LENGTH_CODES; i++) { - printf("%d%s", base_length[i], SEPARATOR(i, LENGTH_CODES-1, 20)); - } - - printf("Z_INTERNAL const int base_dist[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - printf("%5d%s", base_dist[i], SEPARATOR(i, D_CODES-1, 10)); - } - - printf("#endif /* TREES_TBL_H_ */\n"); -} - -// The output of this application can be piped out to recreate trees.h -int main(void) { - tr_static_init(); - gen_trees_header(); - return 0; -} diff --git a/libs/zlibng/trees.c b/libs/zlibng/trees.c deleted file mode 100644 index efd4d49fb9..0000000000 --- a/libs/zlibng/trees.c +++ /dev/null @@ -1,822 +0,0 @@ -/* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2017 Jean-loup Gailly - * detect_data_type() function provided freely by Cosmin Truta, 2006 - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process uses several Huffman trees. The more - * common source values are represented by shorter bit sequences. - * - * Each code tree is stored in a compressed form which is itself - * a Huffman encoding of the lengths of all the code strings (in - * ascending order by source values). The actual code strings are - * reconstructed from the lengths in the inflate process, as described - * in the deflate specification. - * - * REFERENCES - * - * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". - * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc - * - * Storer, James A. - * Data Compression: Methods and Theory, pp. 49-50. - * Computer Science Press, 1988. ISBN 0-7167-8156-5. - * - * Sedgewick, R. - * Algorithms, p290. - * Addison-Wesley, 1983. ISBN 0-201-06672-6. - */ - -#include "zbuild.h" -#include "deflate.h" -#include "trees.h" -#include "trees_emit.h" -#include "trees_tbl.h" - -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -struct static_tree_desc_s { - const ct_data *static_tree; /* static tree or NULL */ - const int *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - unsigned int max_length; /* max bit length for the codes */ -}; - -static const static_tree_desc static_l_desc = -{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; - -static const static_tree_desc static_d_desc = -{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; - -static const static_tree_desc static_bl_desc = -{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; - -/* =========================================================================== - * Local (static) routines in this file. - */ - -static void init_block (deflate_state *s); -static void pqdownheap (deflate_state *s, ct_data *tree, int k); -static void gen_bitlen (deflate_state *s, tree_desc *desc); -static void build_tree (deflate_state *s, tree_desc *desc); -static void scan_tree (deflate_state *s, ct_data *tree, int max_code); -static void send_tree (deflate_state *s, ct_data *tree, int max_code); -static int build_bl_tree (deflate_state *s); -static void send_all_trees (deflate_state *s, int lcodes, int dcodes, int blcodes); -static void compress_block (deflate_state *s, const ct_data *ltree, const ct_data *dtree); -static int detect_data_type (deflate_state *s); -static void bi_flush (deflate_state *s); - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -void Z_INTERNAL zng_tr_init(deflate_state *s) { - s->l_desc.dyn_tree = s->dyn_ltree; - s->l_desc.stat_desc = &static_l_desc; - - s->d_desc.dyn_tree = s->dyn_dtree; - s->d_desc.stat_desc = &static_d_desc; - - s->bl_desc.dyn_tree = s->bl_tree; - s->bl_desc.stat_desc = &static_bl_desc; - - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef ZLIB_DEBUG - s->compressed_len = 0L; - s->bits_sent = 0L; -#endif - - /* Initialize the first block of the first file: */ - init_block(s); -} - -/* =========================================================================== - * Initialize a new block. - */ -static void init_block(deflate_state *s) { - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) - s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) - s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) - s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->sym_next = s->matches = 0; -} - -#define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ - - -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ -#define pqremove(s, tree, top) \ -{\ - top = s->heap[SMALLEST]; \ - s->heap[SMALLEST] = s->heap[s->heap_len--]; \ - pqdownheap(s, tree, SMALLEST); \ -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -#define smaller(tree, n, m, depth) \ - (tree[n].Freq < tree[m].Freq || \ - (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -static void pqdownheap(deflate_state *s, ct_data *tree, int k) { - /* tree: the tree to restore */ - /* k: node to move down */ - int v = s->heap[k]; - int j = k << 1; /* left son of k */ - while (j <= s->heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s->heap_len && smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s->heap[j], s->depth)) - break; - - /* Exchange v with the smallest son */ - s->heap[k] = s->heap[j]; - k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s->heap[k] = v; -} - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -static void gen_bitlen(deflate_state *s, tree_desc *desc) { - /* desc: the tree descriptor */ - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - const ct_data *stree = desc->stat_desc->static_tree; - const int *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - unsigned int max_length = desc->stat_desc->max_length; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - unsigned int bits; /* bit length */ - int xbits; /* extra bits */ - uint16_t f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) - s->bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - - for (h = s->heap_max + 1; h < HEAP_SIZE; h++) { - n = s->heap[h]; - bits = tree[tree[n].Dad].Len + 1u; - if (bits > max_length){ - bits = max_length; - overflow++; - } - tree[n].Len = (uint16_t)bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) /* not a leaf node */ - continue; - - s->bl_count[bits]++; - xbits = 0; - if (n >= base) - xbits = extra[n-base]; - f = tree[n].Freq; - s->opt_len += (unsigned long)f * (unsigned int)(bits + xbits); - if (stree) - s->static_len += (unsigned long)f * (unsigned int)(stree[n].Len + xbits); - } - if (overflow == 0) - return; - - Tracev((stderr, "\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length - 1; - while (s->bl_count[bits] == 0) - bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2u; /* move one overflow item as its brother */ - s->bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = s->bl_count[bits]; - while (n != 0) { - m = s->heap[--h]; - if (m > max_code) - continue; - if (tree[m].Len != bits) { - Tracev((stderr, "code %d bits %d->%u\n", m, tree[m].Len, bits)); - s->opt_len += (unsigned long)(bits * tree[m].Freq); - s->opt_len -= (unsigned long)(tree[m].Len * tree[m].Freq); - tree[m].Len = (uint16_t)bits; - } - n--; - } - } -} - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -Z_INTERNAL void gen_codes(ct_data *tree, int max_code, uint16_t *bl_count) { - /* tree: the tree to decorate */ - /* max_code: largest code with non zero frequency */ - /* bl_count: number of codes at each bit length */ - uint16_t next_code[MAX_BITS+1]; /* next code value for each bit length */ - unsigned int code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - code = (code + bl_count[bits-1]) << 1; - next_code[bits] = (uint16_t)code; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert(code + bl_count[MAX_BITS]-1 == (1 << MAX_BITS)-1, "inconsistent bit counts"); - Tracev((stderr, "\ngen_codes: max_code %d ", max_code)); - - for (n = 0; n <= max_code; n++) { - int len = tree[n].Len; - if (len == 0) - continue; - /* Now reverse the bits */ - tree[n].Code = (uint16_t)bi_reverse(next_code[len]++, len); - - Tracecv(tree != static_ltree, (stderr, "\nn %3d %c l %2d c %4x (%x) ", - n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); - } -} - -/* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ -static void build_tree(deflate_state *s, tree_desc *desc) { - /* desc: the tree descriptor */ - ct_data *tree = desc->dyn_tree; - const ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s->heap_len = 0; - s->heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - s->heap[++(s->heap_len)] = max_code = n; - s->depth[n] = 0; - } else { - tree[n].Len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s->heap_len < 2) { - node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); - tree[node].Freq = 1; - s->depth[node] = 0; - s->opt_len--; - if (stree) - s->static_len -= stree[node].Len; - /* node is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s->heap_len/2; n >= 1; n--) - pqdownheap(s, tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - pqremove(s, tree, n); /* n = node of least frequency */ - m = s->heap[SMALLEST]; /* m = node of next least frequency */ - - s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ - s->heap[--(s->heap_max)] = m; - - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - s->depth[node] = (unsigned char)((s->depth[n] >= s->depth[m] ? - s->depth[n] : s->depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (uint16_t)node; -#ifdef DUMP_BL_TREE - if (tree == s->bl_tree) { - fprintf(stderr, "\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); - } -#endif - /* and insert the new node in the heap */ - s->heap[SMALLEST] = node++; - pqdownheap(s, tree, SMALLEST); - } while (s->heap_len >= 2); - - s->heap[--(s->heap_max)] = s->heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, (tree_desc *)desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes((ct_data *)tree, max_code, s->bl_count); -} - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -static void scan_tree(deflate_state *s, ct_data *tree, int max_code) { - /* tree: the tree to be scanned */ - /* max_code: and its largest code of non zero frequency */ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - uint16_t count = 0; /* repeat count of the current code */ - uint16_t max_count = 7; /* max repeat count */ - uint16_t min_count = 4; /* min repeat count */ - - if (nextlen == 0) - max_count = 138, min_count = 3; - - tree[max_code+1].Len = (uint16_t)0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) - s->bl_tree[curlen].Freq++; - s->bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - s->bl_tree[REPZ_3_10].Freq++; - } else { - s->bl_tree[REPZ_11_138].Freq++; - } - count = 0; - prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -static void send_tree(deflate_state *s, ct_data *tree, int max_code) { - /* tree: the tree to be scanned */ - /* max_code and its largest code of non zero frequency */ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen == 0) - max_count = 138, min_count = 3; - - // Temp local variables - uint32_t bi_valid = s->bi_valid; - uint64_t bi_buf = s->bi_buf; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { - send_code(s, curlen, s->bl_tree, bi_buf, bi_valid); - } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(s, curlen, s->bl_tree, bi_buf, bi_valid); - count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree, bi_buf, bi_valid); - send_bits(s, count-3, 2, bi_buf, bi_valid); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree, bi_buf, bi_valid); - send_bits(s, count-3, 3, bi_buf, bi_valid); - - } else { - send_code(s, REPZ_11_138, s->bl_tree, bi_buf, bi_valid); - send_bits(s, count-11, 7, bi_buf, bi_valid); - } - count = 0; - prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } - - // Store back temp variables - s->bi_buf = bi_buf; - s->bi_valid = bi_valid; -} - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -static int build_bl_tree(deflate_state *s) { - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); - scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s->bl_tree[bl_order[max_blindex]].Len != 0) - break; - } - /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*((unsigned long)max_blindex+1) + 5+5+4; - Tracev((stderr, "\ndyn trees: dyn %lu, stat %lu", s->opt_len, s->static_len)); - - return max_blindex; -} - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -static void send_all_trees(deflate_state *s, int lcodes, int dcodes, int blcodes) { - int rank; /* index in bl_order */ - - Assert(lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert(lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); - - // Temp local variables - uint32_t bi_valid = s->bi_valid; - uint64_t bi_buf = s->bi_buf; - - Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5, bi_buf, bi_valid); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5, bi_buf, bi_valid); - send_bits(s, blcodes-4, 4, bi_buf, bi_valid); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Tracev((stderr, "\nbl code %2u ", bl_order[rank])); - send_bits(s, s->bl_tree[bl_order[rank]].Len, 3, bi_buf, bi_valid); - } - Tracev((stderr, "\nbl tree: sent %lu", s->bits_sent)); - - // Store back temp variables - s->bi_buf = bi_buf; - s->bi_valid = bi_valid; - - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ - Tracev((stderr, "\nlit tree: sent %lu", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ - Tracev((stderr, "\ndist tree: sent %lu", s->bits_sent)); -} - -/* =========================================================================== - * Send a stored block - */ -void Z_INTERNAL zng_tr_stored_block(deflate_state *s, char *buf, uint32_t stored_len, int last) { - /* buf: input block */ - /* stored_len: length of input block */ - /* last: one if this is the last block for a file */ - zng_tr_emit_tree(s, STORED_BLOCK, last); /* send block type */ - zng_tr_emit_align(s); /* align on byte boundary */ - cmpr_bits_align(s); - put_short(s, (uint16_t)stored_len); - put_short(s, (uint16_t)~stored_len); - cmpr_bits_add(s, 32); - sent_bits_add(s, 32); - if (stored_len) { - memcpy(s->pending_buf + s->pending, (unsigned char *)buf, stored_len); - s->pending += stored_len; - cmpr_bits_add(s, stored_len << 3); - sent_bits_add(s, stored_len << 3); - } -} - -/* =========================================================================== - * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) - */ -void Z_INTERNAL zng_tr_flush_bits(deflate_state *s) { - bi_flush(s); -} - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ -void Z_INTERNAL zng_tr_align(deflate_state *s) { - zng_tr_emit_tree(s, STATIC_TREES, 0); - zng_tr_emit_end_block(s, static_ltree, 0); - bi_flush(s); -} - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and write out the encoded block. - */ -void Z_INTERNAL zng_tr_flush_block(deflate_state *s, char *buf, uint32_t stored_len, int last) { - /* buf: input block, or NULL if too old */ - /* stored_len: length of input block */ - /* last: one if this is the last block for a file */ - unsigned long opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (UNLIKELY(s->sym_next == 0)) { - /* Emit an empty static tree block with no codes */ - opt_lenb = static_lenb = 0; - s->static_len = 7; - } else if (s->level > 0) { - /* Check if the file is binary or text */ - if (s->strm->data_type == Z_UNKNOWN) - s->strm->data_type = detect_data_type(s); - - /* Construct the literal and distance trees */ - build_tree(s, (tree_desc *)(&(s->l_desc))); - Tracev((stderr, "\nlit data: dyn %lu, stat %lu", s->opt_len, s->static_len)); - - build_tree(s, (tree_desc *)(&(s->d_desc))); - Tracev((stderr, "\ndist data: dyn %lu, stat %lu", s->opt_len, s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s->opt_len+3+7) >> 3; - static_lenb = (s->static_len+3+7) >> 3; - - Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %u lit %u ", - opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->sym_next / 3)); - - if (static_lenb <= opt_lenb) - opt_lenb = static_lenb; - - } else { - Assert(buf != NULL, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - - if (stored_len+4 <= opt_lenb && buf != NULL) { - /* 4: two words for the lengths - * The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - zng_tr_stored_block(s, buf, stored_len, last); - - } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { - zng_tr_emit_tree(s, STATIC_TREES, last); - compress_block(s, (const ct_data *)static_ltree, (const ct_data *)static_dtree); - cmpr_bits_add(s, s->static_len); - } else { - zng_tr_emit_tree(s, DYN_TREES, last); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, max_blindex+1); - compress_block(s, (const ct_data *)s->dyn_ltree, (const ct_data *)s->dyn_dtree); - cmpr_bits_add(s, s->opt_len); - } - Assert(s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and unsigned long implemented on 32 bits. - */ - init_block(s); - - if (last) { - zng_tr_emit_align(s); - } - Tracev((stderr, "\ncomprlen %lu(%lu) ", s->compressed_len>>3, s->compressed_len-7*last)); -} - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -static void compress_block(deflate_state *s, const ct_data *ltree, const ct_data *dtree) { - /* ltree: literal tree */ - /* dtree: distance tree */ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned sx = 0; /* running index in sym_buf */ - - if (s->sym_next != 0) { - do { - dist = s->sym_buf[sx++] & 0xff; - dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; - lc = s->sym_buf[sx++]; - if (dist == 0) { - zng_emit_lit(s, ltree, lc); - } else { - zng_emit_dist(s, ltree, dtree, lc, dist); - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and sym_buf is ok: */ - Assert(s->pending < s->lit_bufsize + sx, "pending_buf overflow"); - } while (sx < s->sym_next); - } - - zng_emit_end_block(s, ltree, 0); -} - -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -static int detect_data_type(deflate_state *s) { - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - unsigned long black_mask = 0xf3ffc07fUL; - int n; - - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>= 1) - if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) - return Z_BINARY; - - /* Check for textual ("white-listed") bytes. */ - if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 || s->dyn_ltree[13].Freq != 0) - return Z_TEXT; - for (n = 32; n < LITERALS; n++) - if (s->dyn_ltree[n].Freq != 0) - return Z_TEXT; - - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -static void bi_flush(deflate_state *s) { - if (s->bi_valid == 64) { - put_uint64(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else { - if (s->bi_valid >= 32) { - put_uint32(s, (uint32_t)s->bi_buf); - s->bi_buf >>= 32; - s->bi_valid -= 32; - } - if (s->bi_valid >= 16) { - put_short(s, (uint16_t)s->bi_buf); - s->bi_buf >>= 16; - s->bi_valid -= 16; - } - if (s->bi_valid >= 8) { - put_byte(s, s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } - } -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -Z_INTERNAL unsigned bi_reverse(unsigned code, int len) { - /* code: the value to invert */ - /* len: its bit length */ - Z_REGISTER unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} diff --git a/libs/zlibng/trees.h b/libs/zlibng/trees.h deleted file mode 100644 index e57f926489..0000000000 --- a/libs/zlibng/trees.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef TREES_H_ -#define TREES_H_ - -/* Constants */ - -#define DIST_CODE_LEN 512 -/* see definition of array dist_code in trees.c */ - -#define MAX_BL_BITS 7 -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -#define REP_3_6 16 -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -#define REPZ_3_10 17 -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -#define REPZ_11_138 18 -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -static const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ - = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; - -static const int extra_dbits[D_CODES] /* extra bits for each distance code */ - = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -static const int extra_blbits[BL_CODES] /* extra bits for each bit length code */ - = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -static const unsigned char bl_order[BL_CODES] - = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; - /* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - - -/* Function definitions */ -void gen_codes (ct_data *tree, int max_code, uint16_t *bl_count); - -#endif diff --git a/libs/zlibng/trees_emit.h b/libs/zlibng/trees_emit.h deleted file mode 100644 index 118dbb2d8f..0000000000 --- a/libs/zlibng/trees_emit.h +++ /dev/null @@ -1,228 +0,0 @@ -#ifndef TREES_EMIT_H_ -#define TREES_EMIT_H_ - -#include "zbuild.h" -#include "trees.h" - -#ifdef ZLIB_DEBUG -# include -# include -# include -#endif - - -/* trees.h */ -extern Z_INTERNAL const ct_data static_ltree[L_CODES+2]; -extern Z_INTERNAL const ct_data static_dtree[D_CODES]; - -extern const unsigned char Z_INTERNAL zng_dist_code[DIST_CODE_LEN]; -extern const unsigned char Z_INTERNAL zng_length_code[MAX_MATCH-MIN_MATCH+1]; - -extern Z_INTERNAL const int base_length[LENGTH_CODES]; -extern Z_INTERNAL const int base_dist[D_CODES]; - -/* Bit buffer and deflate code stderr tracing */ -#ifdef ZLIB_DEBUG -# define send_bits_trace(s, value, length) { \ - Tracevv((stderr, " l %2d v %4llx ", (int)(length), (long long)(value))); \ - Assert(length > 0 && length <= BIT_BUF_SIZE, "invalid length"); \ - } -# define send_code_trace(s, c) \ - if (z_verbose > 2) { \ - fprintf(stderr, "\ncd %3d ", (c)); \ - } -#else -# define send_bits_trace(s, value, length) -# define send_code_trace(s, c) -#endif - -/* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (64 - bi_valid) bits from value, leaving (width - (64-bi_valid)) - * unused bits in value. - */ -#define send_bits(s, t_val, t_len, bi_buf, bi_valid) {\ - uint64_t val = (uint64_t)t_val;\ - uint32_t len = (uint32_t)t_len;\ - uint32_t total_bits = bi_valid + len;\ - send_bits_trace(s, val, len);\ - sent_bits_add(s, len);\ - if (total_bits < BIT_BUF_SIZE) {\ - bi_buf |= val << bi_valid;\ - bi_valid = total_bits;\ - } else if (bi_valid == BIT_BUF_SIZE) {\ - put_uint64(s, bi_buf);\ - bi_buf = val;\ - bi_valid = len;\ - } else {\ - bi_buf |= val << bi_valid;\ - put_uint64(s, bi_buf);\ - bi_buf = val >> (BIT_BUF_SIZE - bi_valid);\ - bi_valid = total_bits - BIT_BUF_SIZE;\ - }\ -} - -/* Send a code of the given tree. c and tree must not have side effects */ -#ifdef ZLIB_DEBUG -# define send_code(s, c, tree, bi_buf, bi_valid) { \ - send_code_trace(s, c); \ - send_bits(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid); \ -} -#else -# define send_code(s, c, tree, bi_buf, bi_valid) \ - send_bits(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid) -#endif - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -static void bi_windup(deflate_state *s) { - if (s->bi_valid > 56) { - put_uint64(s, s->bi_buf); - } else { - if (s->bi_valid > 24) { - put_uint32(s, (uint32_t)s->bi_buf); - s->bi_buf >>= 32; - s->bi_valid -= 32; - } - if (s->bi_valid > 8) { - put_short(s, (uint16_t)s->bi_buf); - s->bi_buf >>= 16; - s->bi_valid -= 16; - } - if (s->bi_valid > 0) { - put_byte(s, s->bi_buf); - } - } - s->bi_buf = 0; - s->bi_valid = 0; -} - -/* =========================================================================== - * Emit literal code - */ -static inline uint32_t zng_emit_lit(deflate_state *s, const ct_data *ltree, unsigned c) { - uint32_t bi_valid = s->bi_valid; - uint64_t bi_buf = s->bi_buf; - - send_code(s, c, ltree, bi_buf, bi_valid); - - s->bi_valid = bi_valid; - s->bi_buf = bi_buf; - - Tracecv(isgraph(c), (stderr, " '%c' ", c)); - - return ltree[c].Len; -} - -/* =========================================================================== - * Emit match distance/length code - */ -static inline uint32_t zng_emit_dist(deflate_state *s, const ct_data *ltree, const ct_data *dtree, - uint32_t lc, uint32_t dist) { - uint32_t c, extra; - uint8_t code; - uint64_t match_bits; - uint32_t match_bits_len; - uint32_t bi_valid = s->bi_valid; - uint64_t bi_buf = s->bi_buf; - - /* Send the length code, len is the match length - MIN_MATCH */ - code = zng_length_code[lc]; - c = code+LITERALS+1; - Assert(c < L_CODES, "bad l_code"); - send_code_trace(s, c); - - match_bits = ltree[c].Code; - match_bits_len = ltree[c].Len; - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - match_bits |= ((uint64_t)lc << match_bits_len); - match_bits_len += extra; - } - - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert(code < D_CODES, "bad d_code"); - send_code_trace(s, code); - - /* Send the distance code */ - match_bits |= ((uint64_t)dtree[code].Code << match_bits_len); - match_bits_len += dtree[code].Len; - extra = extra_dbits[code]; - if (extra != 0) { - dist -= base_dist[code]; - match_bits |= ((uint64_t)dist << match_bits_len); - match_bits_len += extra; - } - - send_bits(s, match_bits, match_bits_len, bi_buf, bi_valid); - - s->bi_valid = bi_valid; - s->bi_buf = bi_buf; - - return match_bits_len; -} - -/* =========================================================================== - * Emit end block - */ -static inline void zng_emit_end_block(deflate_state *s, const ct_data *ltree, const int last) { - uint32_t bi_valid = s->bi_valid; - uint64_t bi_buf = s->bi_buf; - send_code(s, END_BLOCK, ltree, bi_buf, bi_valid); - s->bi_valid = bi_valid; - s->bi_buf = bi_buf; - Tracev((stderr, "\n+++ Emit End Block: Last: %u Pending: %u Total Out: %" PRIu64 "\n", - last, s->pending, (uint64_t)s->strm->total_out)); - (void)last; -} - -/* =========================================================================== - * Emit literal and count bits - */ -static inline void zng_tr_emit_lit(deflate_state *s, const ct_data *ltree, unsigned c) { - cmpr_bits_add(s, zng_emit_lit(s, ltree, c)); -} - -/* =========================================================================== - * Emit match and count bits - */ -static inline void zng_tr_emit_dist(deflate_state *s, const ct_data *ltree, const ct_data *dtree, - uint32_t lc, uint32_t dist) { - cmpr_bits_add(s, zng_emit_dist(s, ltree, dtree, lc, dist)); -} - -/* =========================================================================== - * Emit start of block - */ -static inline void zng_tr_emit_tree(deflate_state *s, int type, const int last) { - uint32_t bi_valid = s->bi_valid; - uint64_t bi_buf = s->bi_buf; - uint32_t header_bits = (type << 1) + last; - send_bits(s, header_bits, 3, bi_buf, bi_valid); - cmpr_bits_add(s, 3); - s->bi_valid = bi_valid; - s->bi_buf = bi_buf; - Tracev((stderr, "\n--- Emit Tree: Last: %u\n", last)); -} - -/* =========================================================================== - * Align bit buffer on a byte boundary and count bits - */ -static inline void zng_tr_emit_align(deflate_state *s) { - bi_windup(s); /* align on byte boundary */ - sent_bits_align(s); -} - -/* =========================================================================== - * Emit an end block and align bit buffer if last block - */ -static inline void zng_tr_emit_end_block(deflate_state *s, const ct_data *ltree, const int last) { - zng_emit_end_block(s, ltree, last); - cmpr_bits_add(s, 7); - if (last) - zng_tr_emit_align(s); -} - -#endif diff --git a/libs/zlibng/trees_tbl.h b/libs/zlibng/trees_tbl.h deleted file mode 100644 index a4c68a5665..0000000000 --- a/libs/zlibng/trees_tbl.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef TREES_TBL_H_ -#define TREES_TBL_H_ - -/* header created automatically with maketrees.c */ - -Z_INTERNAL const ct_data static_ltree[L_CODES+2] = { -{{ 12},{8}}, {{140},{8}}, {{ 76},{8}}, {{204},{8}}, {{ 44},{8}}, -{{172},{8}}, {{108},{8}}, {{236},{8}}, {{ 28},{8}}, {{156},{8}}, -{{ 92},{8}}, {{220},{8}}, {{ 60},{8}}, {{188},{8}}, {{124},{8}}, -{{252},{8}}, {{ 2},{8}}, {{130},{8}}, {{ 66},{8}}, {{194},{8}}, -{{ 34},{8}}, {{162},{8}}, {{ 98},{8}}, {{226},{8}}, {{ 18},{8}}, -{{146},{8}}, {{ 82},{8}}, {{210},{8}}, {{ 50},{8}}, {{178},{8}}, -{{114},{8}}, {{242},{8}}, {{ 10},{8}}, {{138},{8}}, {{ 74},{8}}, -{{202},{8}}, {{ 42},{8}}, {{170},{8}}, {{106},{8}}, {{234},{8}}, -{{ 26},{8}}, {{154},{8}}, {{ 90},{8}}, {{218},{8}}, {{ 58},{8}}, -{{186},{8}}, {{122},{8}}, {{250},{8}}, {{ 6},{8}}, {{134},{8}}, -{{ 70},{8}}, {{198},{8}}, {{ 38},{8}}, {{166},{8}}, {{102},{8}}, -{{230},{8}}, {{ 22},{8}}, {{150},{8}}, {{ 86},{8}}, {{214},{8}}, -{{ 54},{8}}, {{182},{8}}, {{118},{8}}, {{246},{8}}, {{ 14},{8}}, -{{142},{8}}, {{ 78},{8}}, {{206},{8}}, {{ 46},{8}}, {{174},{8}}, -{{110},{8}}, {{238},{8}}, {{ 30},{8}}, {{158},{8}}, {{ 94},{8}}, -{{222},{8}}, {{ 62},{8}}, {{190},{8}}, {{126},{8}}, {{254},{8}}, -{{ 1},{8}}, {{129},{8}}, {{ 65},{8}}, {{193},{8}}, {{ 33},{8}}, -{{161},{8}}, {{ 97},{8}}, {{225},{8}}, {{ 17},{8}}, {{145},{8}}, -{{ 81},{8}}, {{209},{8}}, {{ 49},{8}}, {{177},{8}}, {{113},{8}}, -{{241},{8}}, {{ 9},{8}}, {{137},{8}}, {{ 73},{8}}, {{201},{8}}, -{{ 41},{8}}, {{169},{8}}, {{105},{8}}, {{233},{8}}, {{ 25},{8}}, -{{153},{8}}, {{ 89},{8}}, {{217},{8}}, {{ 57},{8}}, {{185},{8}}, -{{121},{8}}, {{249},{8}}, {{ 5},{8}}, {{133},{8}}, {{ 69},{8}}, -{{197},{8}}, {{ 37},{8}}, {{165},{8}}, {{101},{8}}, {{229},{8}}, -{{ 21},{8}}, {{149},{8}}, {{ 85},{8}}, {{213},{8}}, {{ 53},{8}}, -{{181},{8}}, {{117},{8}}, {{245},{8}}, {{ 13},{8}}, {{141},{8}}, -{{ 77},{8}}, {{205},{8}}, {{ 45},{8}}, {{173},{8}}, {{109},{8}}, -{{237},{8}}, {{ 29},{8}}, {{157},{8}}, {{ 93},{8}}, {{221},{8}}, -{{ 61},{8}}, {{189},{8}}, {{125},{8}}, {{253},{8}}, {{ 19},{9}}, -{{275},{9}}, {{147},{9}}, {{403},{9}}, {{ 83},{9}}, {{339},{9}}, -{{211},{9}}, {{467},{9}}, {{ 51},{9}}, {{307},{9}}, {{179},{9}}, -{{435},{9}}, {{115},{9}}, {{371},{9}}, {{243},{9}}, {{499},{9}}, -{{ 11},{9}}, {{267},{9}}, {{139},{9}}, {{395},{9}}, {{ 75},{9}}, -{{331},{9}}, {{203},{9}}, {{459},{9}}, {{ 43},{9}}, {{299},{9}}, -{{171},{9}}, {{427},{9}}, {{107},{9}}, {{363},{9}}, {{235},{9}}, -{{491},{9}}, {{ 27},{9}}, {{283},{9}}, {{155},{9}}, {{411},{9}}, -{{ 91},{9}}, {{347},{9}}, {{219},{9}}, {{475},{9}}, {{ 59},{9}}, -{{315},{9}}, {{187},{9}}, {{443},{9}}, {{123},{9}}, {{379},{9}}, -{{251},{9}}, {{507},{9}}, {{ 7},{9}}, {{263},{9}}, {{135},{9}}, -{{391},{9}}, {{ 71},{9}}, {{327},{9}}, {{199},{9}}, {{455},{9}}, -{{ 39},{9}}, {{295},{9}}, {{167},{9}}, {{423},{9}}, {{103},{9}}, -{{359},{9}}, {{231},{9}}, {{487},{9}}, {{ 23},{9}}, {{279},{9}}, -{{151},{9}}, {{407},{9}}, {{ 87},{9}}, {{343},{9}}, {{215},{9}}, -{{471},{9}}, {{ 55},{9}}, {{311},{9}}, {{183},{9}}, {{439},{9}}, -{{119},{9}}, {{375},{9}}, {{247},{9}}, {{503},{9}}, {{ 15},{9}}, -{{271},{9}}, {{143},{9}}, {{399},{9}}, {{ 79},{9}}, {{335},{9}}, -{{207},{9}}, {{463},{9}}, {{ 47},{9}}, {{303},{9}}, {{175},{9}}, -{{431},{9}}, {{111},{9}}, {{367},{9}}, {{239},{9}}, {{495},{9}}, -{{ 31},{9}}, {{287},{9}}, {{159},{9}}, {{415},{9}}, {{ 95},{9}}, -{{351},{9}}, {{223},{9}}, {{479},{9}}, {{ 63},{9}}, {{319},{9}}, -{{191},{9}}, {{447},{9}}, {{127},{9}}, {{383},{9}}, {{255},{9}}, -{{511},{9}}, {{ 0},{7}}, {{ 64},{7}}, {{ 32},{7}}, {{ 96},{7}}, -{{ 16},{7}}, {{ 80},{7}}, {{ 48},{7}}, {{112},{7}}, {{ 8},{7}}, -{{ 72},{7}}, {{ 40},{7}}, {{104},{7}}, {{ 24},{7}}, {{ 88},{7}}, -{{ 56},{7}}, {{120},{7}}, {{ 4},{7}}, {{ 68},{7}}, {{ 36},{7}}, -{{100},{7}}, {{ 20},{7}}, {{ 84},{7}}, {{ 52},{7}}, {{116},{7}}, -{{ 3},{8}}, {{131},{8}}, {{ 67},{8}}, {{195},{8}}, {{ 35},{8}}, -{{163},{8}}, {{ 99},{8}}, {{227},{8}} -}; - -Z_INTERNAL const ct_data static_dtree[D_CODES] = { -{{ 0},{5}}, {{16},{5}}, {{ 8},{5}}, {{24},{5}}, {{ 4},{5}}, -{{20},{5}}, {{12},{5}}, {{28},{5}}, {{ 2},{5}}, {{18},{5}}, -{{10},{5}}, {{26},{5}}, {{ 6},{5}}, {{22},{5}}, {{14},{5}}, -{{30},{5}}, {{ 1},{5}}, {{17},{5}}, {{ 9},{5}}, {{25},{5}}, -{{ 5},{5}}, {{21},{5}}, {{13},{5}}, {{29},{5}}, {{ 3},{5}}, -{{19},{5}}, {{11},{5}}, {{27},{5}}, {{ 7},{5}}, {{23},{5}} -}; - -const unsigned char Z_INTERNAL zng_dist_code[DIST_CODE_LEN] = { - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, -10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, -11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, -12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, -18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 -}; - -const unsigned char Z_INTERNAL zng_length_code[MAX_MATCH-MIN_MATCH+1] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, -13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, -17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, -19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, -21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, -22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 -}; - -Z_INTERNAL const int base_length[LENGTH_CODES] = { -0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, -64, 80, 96, 112, 128, 160, 192, 224, 0 -}; - -Z_INTERNAL const int base_dist[D_CODES] = { - 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, - 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, - 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 -}; - -#endif /* TREES_TBL_H_ */ diff --git a/libs/zlibng/uncompr.c b/libs/zlibng/uncompr.c deleted file mode 100644 index 1435fab975..0000000000 --- a/libs/zlibng/uncompr.c +++ /dev/null @@ -1,85 +0,0 @@ -/* uncompr.c -- decompress a memory buffer - * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#define Z_INTERNAL -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -/* =========================================================================== - Decompresses the source buffer into the destination buffer. *sourceLen is - the byte length of the source buffer. Upon entry, *destLen is the total size - of the destination buffer, which must be large enough to hold the entire - uncompressed data. (The size of the uncompressed data must have been saved - previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, - *destLen is the size of the decompressed data and *sourceLen is the number - of source bytes consumed. Upon return, source + *sourceLen points to the - first unused input byte. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, or - Z_DATA_ERROR if the input data was corrupted, including if the input data is - an incomplete zlib stream. -*/ -int Z_EXPORT PREFIX(uncompress2)(unsigned char *dest, z_size_t *destLen, const unsigned char *source, z_size_t *sourceLen) { - PREFIX3(stream) stream; - int err; - const unsigned int max = (unsigned int)-1; - z_size_t len, left; - unsigned char buf[1]; /* for detection of incomplete stream when *destLen == 0 */ - - len = *sourceLen; - if (*destLen) { - left = *destLen; - *destLen = 0; - } else { - left = 1; - dest = buf; - } - - stream.next_in = (z_const unsigned char *)source; - stream.avail_in = 0; - stream.zalloc = NULL; - stream.zfree = NULL; - stream.opaque = NULL; - - err = PREFIX(inflateInit)(&stream); - if (err != Z_OK) return err; - - stream.next_out = dest; - stream.avail_out = 0; - - do { - if (stream.avail_out == 0) { - stream.avail_out = left > (unsigned long)max ? max : (unsigned int)left; - left -= stream.avail_out; - } - if (stream.avail_in == 0) { - stream.avail_in = len > (unsigned long)max ? max : (unsigned int)len; - len -= stream.avail_in; - } - err = PREFIX(inflate)(&stream, Z_NO_FLUSH); - } while (err == Z_OK); - - *sourceLen -= len + stream.avail_in; - if (dest != buf) - *destLen = (z_size_t)stream.total_out; - else if (stream.total_out && err == Z_BUF_ERROR) - left = 1; - - PREFIX(inflateEnd)(&stream); - return err == Z_STREAM_END ? Z_OK : - err == Z_NEED_DICT ? Z_DATA_ERROR : - err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR : - err; -} - -int Z_EXPORT PREFIX(uncompress)(unsigned char *dest, z_size_t *destLen, const unsigned char *source, z_size_t sourceLen) { - return PREFIX(uncompress2)(dest, destLen, source, &sourceLen); -} diff --git a/libs/zlibng/win32/DLL_FAQ.txt b/libs/zlibng/win32/DLL_FAQ.txt deleted file mode 100644 index c212985967..0000000000 --- a/libs/zlibng/win32/DLL_FAQ.txt +++ /dev/null @@ -1,397 +0,0 @@ - - Frequently Asked Questions about ZLIB1.DLL - - -This document describes the design, the rationale, and the usage -of the official DLL build of zlib, named ZLIB1.DLL. If you have -general questions about zlib, you should see the file "FAQ" found -in the zlib distribution, or at the following location: - http://www.gzip.org/zlib/zlib_faq.html - - - 1. What is ZLIB1.DLL, and how can I get it? - - - ZLIB1.DLL is the official build of zlib as a DLL. - (Please remark the character '1' in the name.) - - Pointers to a precompiled ZLIB1.DLL can be found in the zlib - web site at: - http://www.zlib.net/ - - Applications that link to ZLIB1.DLL can rely on the following - specification: - - * The exported symbols are exclusively defined in the source - files "zlib.h" and "zlib.def", found in an official zlib - source distribution. - * The symbols are exported by name, not by ordinal. - * The exported names are undecorated. - * The calling convention of functions is "C" (CDECL). - * The ZLIB1.DLL binary is linked to MSVCRT.DLL. - - The archive in which ZLIB1.DLL is bundled contains compiled - test programs that must run with a valid build of ZLIB1.DLL. - It is recommended to download the prebuilt DLL from the zlib - web site, instead of building it yourself, to avoid potential - incompatibilities that could be introduced by your compiler - and build settings. If you do build the DLL yourself, please - make sure that it complies with all the above requirements, - and it runs with the precompiled test programs, bundled with - the original ZLIB1.DLL distribution. - - If, for any reason, you need to build an incompatible DLL, - please use a different file name. - - - 2. Why did you change the name of the DLL to ZLIB1.DLL? - What happened to the old ZLIB.DLL? - - - The old ZLIB.DLL, built from zlib-1.1.4 or earlier, required - compilation settings that were incompatible to those used by - a static build. The DLL settings were supposed to be enabled - by defining the macro ZLIB_DLL, before including "zlib.h". - Incorrect handling of this macro was silently accepted at - build time, resulting in two major problems: - - * ZLIB_DLL was missing from the old makefile. When building - the DLL, not all people added it to the build options. In - consequence, incompatible incarnations of ZLIB.DLL started - to circulate around the net. - - * When switching from using the static library to using the - DLL, applications had to define the ZLIB_DLL macro and - to recompile all the sources that contained calls to zlib - functions. Failure to do so resulted in creating binaries - that were unable to run with the official ZLIB.DLL build. - - The only possible solution that we could foresee was to make - a binary-incompatible change in the DLL interface, in order to - remove the dependency on the ZLIB_DLL macro, and to release - the new DLL under a different name. - - We chose the name ZLIB1.DLL, where '1' indicates the major - zlib version number. We hope that we will not have to break - the binary compatibility again, at least not as long as the - zlib-1.x series will last. - - There is still a ZLIB_DLL macro, that can trigger a more - efficient build and use of the DLL, but compatibility no - longer dependents on it. - - - 3. Can I build ZLIB.DLL from the new zlib sources, and replace - an old ZLIB.DLL, that was built from zlib-1.1.4 or earlier? - - - In principle, you can do it by assigning calling convention - keywords to the macros Z_EXPORT and Z_EXPORTVA. In practice, - it depends on what you mean by "an old ZLIB.DLL", because the - old DLL exists in several mutually-incompatible versions. - You have to find out first what kind of calling convention is - being used in your particular ZLIB.DLL build, and to use the - same one in the new build. If you don't know what this is all - about, you might be better off if you would just leave the old - DLL intact. - - - 4. Can I compile my application using the new zlib interface, and - link it to an old ZLIB.DLL, that was built from zlib-1.1.4 or - earlier? - - - The official answer is "no"; the real answer depends again on - what kind of ZLIB.DLL you have. Even if you are lucky, this - course of action is unreliable. - - If you rebuild your application and you intend to use a newer - version of zlib (post- 1.1.4), it is strongly recommended to - link it to the new ZLIB1.DLL. - - - 5. Why are the zlib symbols exported by name, and not by ordinal? - - - Although exporting symbols by ordinal is a little faster, it - is risky. Any single glitch in the maintenance or use of the - DEF file that contains the ordinals can result in incompatible - builds and frustrating crashes. Simply put, the benefits of - exporting symbols by ordinal do not justify the risks. - - Technically, it should be possible to maintain ordinals in - the DEF file, and still export the symbols by name. Ordinals - exist in every DLL, and even if the dynamic linking performed - at the DLL startup is searching for names, ordinals serve as - hints, for a faster name lookup. However, if the DEF file - contains ordinals, the Microsoft linker automatically builds - an implib that will cause the executables linked to it to use - those ordinals, and not the names. It is interesting to - notice that the GNU linker for Win32 does not suffer from this - problem. - - It is possible to avoid the DEF file if the exported symbols - are accompanied by a "__declspec(dllexport)" attribute in the - source files. You can do this in zlib by predefining the - ZLIB_DLL macro. - - - 6. I see that the ZLIB1.DLL functions use the "C" (CDECL) calling - convention. Why not use the STDCALL convention? - STDCALL is the standard convention in Win32, and I need it in - my Visual Basic project! - - (For readability, we use CDECL to refer to the convention - triggered by the "__cdecl" keyword, STDCALL to refer to - the convention triggered by "__stdcall", and FASTCALL to - refer to the convention triggered by "__fastcall".) - - - Most of the native Windows API functions (without varargs) use - indeed the WINAPI convention (which translates to STDCALL in - Win32), but the standard C functions use CDECL. If a user - application is intrinsically tied to the Windows API (e.g. - it calls native Windows API functions such as CreateFile()), - sometimes it makes sense to decorate its own functions with - WINAPI. But if ANSI C or POSIX portability is a goal (e.g. - it calls standard C functions such as fopen()), it is not a - sound decision to request the inclusion of , or to - use non-ANSI constructs, for the sole purpose to make the user - functions STDCALL-able. - - The functionality offered by zlib is not in the category of - "Windows functionality", but is more like "C functionality". - - Technically, STDCALL is not bad; in fact, it is slightly - faster than CDECL, and it works with variable-argument - functions, just like CDECL. It is unfortunate that, in spite - of using STDCALL in the Windows API, it is not the default - convention used by the C compilers that run under Windows. - The roots of the problem reside deep inside the unsafety of - the K&R-style function prototypes, where the argument types - are not specified; but that is another story for another day. - - The remaining fact is that CDECL is the default convention. - Even if an explicit convention is hard-coded into the function - prototypes inside C headers, problems may appear. The - necessity to expose the convention in users' callbacks is one - of these problems. - - The calling convention issues are also important when using - zlib in other programming languages. Some of them, like Ada - (GNAT) and Fortran (GNU G77), have C bindings implemented - initially on Unix, and relying on the C calling convention. - On the other hand, the pre- .NET versions of Microsoft Visual - Basic require STDCALL, while Borland Delphi prefers, although - it does not require, FASTCALL. - - In fairness to all possible uses of zlib outside the C - programming language, we choose the default "C" convention. - Anyone interested in different bindings or conventions is - encouraged to maintain specialized projects. The "contrib/" - directory from the zlib distribution already holds a couple - of foreign bindings, such as Ada, C++, and Delphi. - - - 7. I need a DLL for my Visual Basic project. What can I do? - - - Define the ZLIB_WINAPI macro before including "zlib.h", when - building both the DLL and the user application (except that - you don't need to define anything when using the DLL in Visual - Basic). The ZLIB_WINAPI macro will switch on the WINAPI - (STDCALL) convention. The name of this DLL must be different - than the official ZLIB1.DLL. - - Gilles Vollant has contributed a build named ZLIBWAPI.DLL, - with the ZLIB_WINAPI macro turned on, and with the minizip - functionality built in. For more information, please read - the notes inside "contrib/vstudio/readme.txt", found in the - zlib distribution. - - - 8. I need to use zlib in my Microsoft .NET project. What can I - do? - - - Henrik Ravn has contributed a .NET wrapper around zlib. Look - into contrib/dotzlib/, inside the zlib distribution. - - - 9. If my application uses ZLIB1.DLL, should I link it to - MSVCRT.DLL? Why? - - - It is not required, but it is recommended to link your - application to MSVCRT.DLL, if it uses ZLIB1.DLL. - - The executables (.EXE, .DLL, etc.) that are involved in the - same process and are using the C run-time library (i.e. they - are calling standard C functions), must link to the same - library. There are several libraries in the Win32 system: - CRTDLL.DLL, MSVCRT.DLL, the static C libraries, etc. - Since ZLIB1.DLL is linked to MSVCRT.DLL, the executables that - depend on it should also be linked to MSVCRT.DLL. - - -10. Why are you saying that ZLIB1.DLL and my application should - be linked to the same C run-time (CRT) library? I linked my - application and my DLLs to different C libraries (e.g. my - application to a static library, and my DLLs to MSVCRT.DLL), - and everything works fine. - - - If a user library invokes only pure Win32 API (accessible via - and the related headers), its DLL build will work - in any context. But if this library invokes standard C API, - things get more complicated. - - There is a single Win32 library in a Win32 system. Every - function in this library resides in a single DLL module, that - is safe to call from anywhere. On the other hand, there are - multiple versions of the C library, and each of them has its - own separate internal state. Standalone executables and user - DLLs that call standard C functions must link to a C run-time - (CRT) library, be it static or shared (DLL). Intermixing - occurs when an executable (not necessarily standalone) and a - DLL are linked to different CRTs, and both are running in the - same process. - - Intermixing multiple CRTs is possible, as long as their - internal states are kept intact. The Microsoft Knowledge Base - articles KB94248 "HOWTO: Use the C Run-Time" and KB140584 - "HOWTO: Link with the Correct C Run-Time (CRT) Library" - mention the potential problems raised by intermixing. - - If intermixing works for you, it's because your application - and DLLs are avoiding the corruption of each of the CRTs' - internal states, maybe by careful design, or maybe by fortune. - - Also note that linking ZLIB1.DLL to non-Microsoft CRTs, such - as those provided by Borland, raises similar problems. - - -11. Why are you linking ZLIB1.DLL to MSVCRT.DLL? - - - MSVCRT.DLL exists on every Windows 95 with a new service pack - installed, or with Microsoft Internet Explorer 4 or later, and - on all other Windows 4.x or later (Windows 98, Windows NT 4, - or later). It is freely distributable; if not present in the - system, it can be downloaded from Microsoft or from other - software provider for free. - - The fact that MSVCRT.DLL does not exist on a virgin Windows 95 - is not so problematic. Windows 95 is scarcely found nowadays, - Microsoft ended its support a long time ago, and many recent - applications from various vendors, including Microsoft, do not - even run on it. Furthermore, no serious user should run - Windows 95 without a proper update installed. - - -12. Why are you not linking ZLIB1.DLL to - <> ? - - - We considered and abandoned the following alternatives: - - * Linking ZLIB1.DLL to a static C library (LIBC.LIB, or - LIBCMT.LIB) is not a good option. People are using the DLL - mainly to save disk space. If you are linking your program - to a static C library, you may as well consider linking zlib - in statically, too. - - * Linking ZLIB1.DLL to CRTDLL.DLL looks appealing, because - CRTDLL.DLL is present on every Win32 installation. - Unfortunately, it has a series of problems: it does not - work properly with Microsoft's C++ libraries, it does not - provide support for 64-bit file offsets, (and so on...), - and Microsoft discontinued its support a long time ago. - - * Linking ZLIB1.DLL to MSVCR70.DLL or MSVCR71.DLL, supplied - with the Microsoft .NET platform, and Visual C++ 7.0/7.1, - raises problems related to the status of ZLIB1.DLL as a - system component. According to the Microsoft Knowledge Base - article KB326922 "INFO: Redistribution of the Shared C - Runtime Component in Visual C++ .NET", MSVCR70.DLL and - MSVCR71.DLL are not supposed to function as system DLLs, - because they may clash with MSVCRT.DLL. Instead, the - application's installer is supposed to put these DLLs - (if needed) in the application's private directory. - If ZLIB1.DLL depends on a non-system runtime, it cannot - function as a redistributable system component. - - * Linking ZLIB1.DLL to non-Microsoft runtimes, such as - Borland's, or Cygwin's, raises problems related to the - reliable presence of these runtimes on Win32 systems. - It's easier to let the DLL build of zlib up to the people - who distribute these runtimes, and who may proceed as - explained in the answer to Question 14. - - -13. If ZLIB1.DLL cannot be linked to MSVCR70.DLL or MSVCR71.DLL, - how can I build/use ZLIB1.DLL in Microsoft Visual C++ 7.0 - (Visual Studio .NET) or newer? - - - Due to the problems explained in the Microsoft Knowledge Base - article KB326922 (see the previous answer), the C runtime that - comes with the VC7 environment is no longer considered a - system component. That is, it should not be assumed that this - runtime exists, or may be installed in a system directory. - Since ZLIB1.DLL is supposed to be a system component, it may - not depend on a non-system component. - - In order to link ZLIB1.DLL and your application to MSVCRT.DLL - in VC7, you need the library of Visual C++ 6.0 or older. If - you don't have this library at hand, it's probably best not to - use ZLIB1.DLL. - - We are hoping that, in the future, Microsoft will provide a - way to build applications linked to a proper system runtime, - from the Visual C++ environment. Until then, you have a - couple of alternatives, such as linking zlib in statically. - If your application requires dynamic linking, you may proceed - as explained in the answer to Question 14. - - -14. I need to link my own DLL build to a CRT different than - MSVCRT.DLL. What can I do? - - - Feel free to rebuild the DLL from the zlib sources, and link - it the way you want. You should, however, clearly state that - your build is unofficial. You should give it a different file - name, and/or install it in a private directory that can be - accessed by your application only, and is not visible to the - others (i.e. it's neither in the PATH, nor in the SYSTEM or - SYSTEM32 directories). Otherwise, your build may clash with - applications that link to the official build. - - For example, in Cygwin, zlib is linked to the Cygwin runtime - CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL. - - -15. May I include additional pieces of code that I find useful, - link them in ZLIB1.DLL, and export them? - - - No. A legitimate build of ZLIB1.DLL must not include code - that does not originate from the official zlib source code. - But you can make your own private DLL build, under a different - file name, as suggested in the previous answer. - - For example, zlib is a part of the VCL library, distributed - with Borland Delphi and C++ Builder. The DLL build of VCL - is a redistributable file, named VCLxx.DLL. - - -16. May I remove some functionality out of ZLIB1.DLL, by enabling - macros like NO_GZCOMPRESS or NO_GZIP at compile time? - - - No. A legitimate build of ZLIB1.DLL must provide the complete - zlib functionality, as implemented in the official zlib source - code. But you can make your own private DLL build, under a - different file name, as suggested in the previous answer. - - -17. I made my own ZLIB1.DLL build. Can I test it for compliance? - - - We prefer that you download the official DLL from the zlib - web site. If you need something peculiar from this DLL, you - can send your suggestion to the zlib mailing list. - - However, in case you do rebuild the DLL yourself, you can run - it with the test programs found in the DLL distribution. - Running these test programs is not a guarantee of compliance, - but a failure can imply a detected problem. - -** - -This document is written and maintained by -Cosmin Truta diff --git a/libs/zlibng/win32/Makefile.a64 b/libs/zlibng/win32/Makefile.a64 deleted file mode 100644 index a2f2e6a608..0000000000 --- a/libs/zlibng/win32/Makefile.a64 +++ /dev/null @@ -1,208 +0,0 @@ -# Makefile for zlib using Microsoft (Visual) C -# zlib is copyright (C) 1995-2006 Jean-loup Gailly and Mark Adler -# -# Usage: -# nmake -f win32/Makefile.a64 (standard build) -# nmake -f win32/Makefile.a64 LOC=-DFOO (nonstandard build) - -# The toplevel directory of the source tree. -# -TOP = . - -# optional build flags -LOC = - -# variables -STATICLIB = zlib.lib -SHAREDLIB = zlib1.dll -IMPLIB = zdll.lib - -CC = cl -LD = link -AR = lib -RC = rc -CP = copy /y -CFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC) -WFLAGS = \ - -D_CRT_SECURE_NO_DEPRECATE \ - -D_CRT_NONSTDC_NO_DEPRECATE \ - -DUNALIGNED_OK \ - -DUNALIGNED64_OK \ - -D_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 \ - -DARM_FEATURES \ - # -LDFLAGS = -nologo -debug -incremental:no -opt:ref -manifest -ARFLAGS = -nologo -RCFLAGS = /dARM64 /r -DEFFILE = zlib.def -RCFILE = zlib1.rc -RESFILE = zlib1.res -WITH_GZFILEOP = yes -ZLIB_COMPAT = -SUFFIX = - -OBJS = \ - adler32.obj \ - armfeature.obj \ - chunkset.obj \ - compare258.obj \ - compress.obj \ - crc32.obj \ - crc32_comb.obj \ - deflate.obj \ - deflate_fast.obj \ - deflate_slow.obj \ - deflate_quick.obj \ - deflate_medium.obj \ - functable.obj \ - infback.obj \ - inflate.obj \ - inftrees.obj \ - inffast.obj \ - insert_string.obj \ - trees.obj \ - uncompr.obj \ - zutil.obj \ - # -!if "$(ZLIB_COMPAT)" != "" -WITH_GZFILEOP = yes -WFLAGS = $(WFLAGS) -DZLIB_COMPAT -DEFFILE = zlibcompat.def -!else -STATICLIB = zlib-ng.lib -SHAREDLIB = zlib-ng1.dll -IMPLIB = zngdll.lib -DEFFILE = zlib-ng.def -RCFILE = zlib-ng1.rc -RESFILE = zlib-ng1.res -SUFFIX = -ng -!endif - -!if "$(WITH_GZFILEOP)" != "" -WFLAGS = $(WFLAGS) -DWITH_GZFILEOP -OBJS = $(OBJS) gzlib.obj gzread.obj gzwrite.obj -!endif - -WFLAGS = $(WFLAGS) \ - -DARM_ACLE_CRC_HASH \ - -D__ARM_NEON__=1 \ - -DARM_NEON_ADLER32 \ - -DARM_NEON_CHUNKSET \ - -DARM_NEON_SLIDEHASH \ - -DARM_NOCHECK_NEON \ - # -OBJS = $(OBJS) crc32_acle.obj insert_string_acle.obj adler32_neon.obj chunkset_neon.obj slide_neon.obj - -# targets -all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ - example.exe minigzip.exe example_d.exe minigzip_d.exe - -zconf: $(TOP)/zconf$(SUFFIX).h.in - $(CP) $(TOP)\zconf$(SUFFIX).h.in $(TOP)\zconf$(SUFFIX).h - -$(STATICLIB): zconf $(OBJS) - $(AR) $(ARFLAGS) -out:$@ $(OBJS) - -$(IMPLIB): $(SHAREDLIB) - -$(SHAREDLIB): zconf $(TOP)/win32/$(DEFFILE) $(OBJS) $(RESFILE) - $(LD) $(LDFLAGS) -def:$(TOP)/win32/$(DEFFILE) -dll -implib:$(IMPLIB) \ - -out:$@ -base:0x55A4C0000 $(OBJS) $(RESFILE) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;2 - -example.exe: example.obj gzlib2.obj gzread2.obj gzwrite2.obj $(STATICLIB) - $(LD) $(LDFLAGS) example.obj gzlib2.obj gzread2.obj gzwrite2.obj $(STATICLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -minigzip.exe: minigzip.obj gzlib2.obj gzread2.obj gzwrite2.obj $(STATICLIB) - $(LD) $(LDFLAGS) minigzip.obj gzlib2.obj gzread2.obj gzwrite2.obj $(STATICLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -example_d.exe: example.obj gzlib2.obj gzread2.obj gzwrite2.obj $(IMPLIB) - $(LD) $(LDFLAGS) -out:$@ example.obj gzlib2.obj gzread2.obj gzwrite2.obj $(IMPLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -minigzip_d.exe: minigzip.obj gzlib2.obj gzread2.obj gzwrite2.obj $(IMPLIB) - $(LD) $(LDFLAGS) -out:$@ minigzip.obj gzlib2.obj gzread2.obj gzwrite2.obj $(IMPLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -{$(TOP)}.c.obj: - $(CC) -c $(WFLAGS) $(CFLAGS) $< - -gzlib2.obj: gzlib.c - $(CC) -c $(WFLAGS) $(CFLAGS) -DWITH_GZFILEOP -Fogzlib2.obj gzlib.c - -gzread2.obj: gzread.c - $(CC) -c $(WFLAGS) $(CFLAGS) -DWITH_GZFILEOP -Fogzread2.obj gzread.c - -gzwrite2.obj: gzwrite.c - $(CC) -c $(WFLAGS) $(CFLAGS) -DWITH_GZFILEOP -Fogzwrite2.obj gzwrite.c - -{$(TOP)/arch/arm}.c.obj: - $(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $< - -{$(TOP)/test}.c.obj: - $(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) -DWITH_GZFILEOP $< - -$(TOP)/zconf$(SUFFIX).h: zconf - -SRCDIR = $(TOP) -# Keep the dependences in sync with top-level Makefile.in -adler32.obj: $(SRCDIR)/adler32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/functable.h $(SRCDIR)/adler32_p.h -chunkset.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h -functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/zendian.h $(SRCDIR)/arch/x86/x86.h -gzlib.obj: $(SRCDIR)/gzlib.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h -gzread.obj: $(SRCDIR)/gzread.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h -gzwrite.obj: $(SRCDIR)/gzwrite.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h -compress.obj: $(SRCDIR)/compress.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h -uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h -crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h -crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h -deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -deflate_quick.obj: $(SRCDIR)/deflate_quick.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h $(SRCDIR)/trees_emit.h -deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -deflate_medium.obj: $(SRCDIR)/deflate_medium.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -deflate_slow.obj: $(SRCDIR)/deflate_slow.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h -inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h -inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h -inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h -trees.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/trees_tbl.h -zutil.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/zutil_p.h - -example.obj: $(TOP)/test/example.c $(TOP)/zbuild.h $(TOP)/zlib$(SUFFIX).h - -minigzip.obj: $(TOP)/test/minigzip.c $(TOP)/zbuild.h $(TOP)/zlib$(SUFFIX).h - -$(RESFILE): $(TOP)/win32/$(RCFILE) - $(RC) $(RCFLAGS) /fo$@ $(TOP)/win32/$(RCFILE) - -# testing -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -testdll: example_d.exe minigzip_d.exe - example_d - echo hello world | minigzip_d | minigzip_d -d - - -# cleanup -clean: - -del $(STATICLIB) - -del $(SHAREDLIB) - -del $(IMPLIB) - -del *.obj - -del *.res - -del *.exp - -del *.exe - -del *.pdb - -del *.manifest - -distclean: clean - -del zconf$(SUFFIX).h diff --git a/libs/zlibng/win32/Makefile.arm b/libs/zlibng/win32/Makefile.arm deleted file mode 100644 index 5ed53f5f3e..0000000000 --- a/libs/zlibng/win32/Makefile.arm +++ /dev/null @@ -1,220 +0,0 @@ -# Makefile for zlib using Microsoft (Visual) C -# zlib is copyright (C) 1995-2006 Jean-loup Gailly and Mark Adler -# -# Usage: -# nmake -f win32/Makefile.arm (standard build) -# nmake -f win32/Makefile.arm LOC=-DFOO (nonstandard build) - -# The toplevel directory of the source tree. -# -TOP = . - -# optional build flags -LOC = - -# variables -STATICLIB = zlib.lib -SHAREDLIB = zlib1.dll -IMPLIB = zdll.lib - -CC = cl -LD = link -AR = lib -RC = rc -CP = copy /y -CFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC) -WFLAGS = \ - -D_CRT_SECURE_NO_DEPRECATE \ - -D_CRT_NONSTDC_NO_DEPRECATE \ - -DUNALIGNED_OK \ - -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 \ - -DARM_FEATURES \ - # -LDFLAGS = -nologo -debug -incremental:no -opt:ref -manifest -ARFLAGS = -nologo -RCFLAGS = /dARM /r -DEFFILE = zlib.def -RCFILE = zlib1.rc -RESFILE = zlib1.res -WITH_GZFILEOP = yes -ZLIB_COMPAT = -WITH_ACLE = -WITH_NEON = -WITH_VFPV3 = -NEON_ARCH = /arch:VFPv4 -SUFFIX = - -OBJS = \ - adler32.obj \ - armfeature.obj \ - chunkset.obj \ - compare258.obj \ - compress.obj \ - crc32.obj \ - crc32_comb.obj \ - deflate.obj \ - deflate_fast.obj \ - deflate_slow.obj \ - deflate_quick.obj \ - deflate_medium.obj \ - functable.obj \ - infback.obj \ - inflate.obj \ - inftrees.obj \ - inffast.obj \ - insert_string.obj \ - trees.obj \ - uncompr.obj \ - zutil.obj \ - # -!if "$(ZLIB_COMPAT)" != "" -WITH_GZFILEOP = yes -WFLAGS = $(WFLAGS) -DZLIB_COMPAT -DEFFILE = zlibcompat.def -!else -STATICLIB = zlib-ng.lib -SHAREDLIB = zlib-ng1.dll -IMPLIB = zngdll.lib -DEFFILE = zlib-ng.def -RCFILE = zlib-ng1.rc -RESFILE = zlib-ng1.res -SUFFIX = -ng -!endif - -!if "$(WITH_GZFILEOP)" != "" -WFLAGS = $(WFLAGS) -DWITH_GZFILEOP -OBJS = $(OBJS) gzlib.obj gzread.obj gzwrite.obj -!endif - -!if "$(WITH_ACLE)" != "" -WFLAGS = $(WFLAGS) -DARM_ACLE_CRC_HASH -OBJS = $(OBJS) crc32_acle.obj insert_string_acle.obj -!endif -!if "$(WITH_VFPV3)" != "" -NEON_ARCH = /arch:VFPv3 -!endif -!if "$(WITH_NEON)" != "" -CFLAGS = $(CFLAGS) $(NEON_ARCH) -WFLAGS = $(WFLAGS) \ - -D__ARM_NEON__=1 \ - -DARM_NEON_ADLER32 \ - -DARM_NEON_CHUNKSET \ - -DARM_NEON_SLIDEHASH \ - -DARM_NOCHECK_NEON \ - # -OBJS = $(OBJS) adler32_neon.obj chunkset_neon.obj slide_neon.obj -!endif - -# targets -all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ - example.exe minigzip.exe example_d.exe minigzip_d.exe - -zconf: $(TOP)/zconf$(SUFFIX).h.in - $(CP) $(TOP)\zconf$(SUFFIX).h.in $(TOP)\zconf$(SUFFIX).h - -$(STATICLIB): zconf $(OBJS) - $(AR) $(ARFLAGS) -out:$@ $(OBJS) - -$(IMPLIB): $(SHAREDLIB) - -$(SHAREDLIB): zconf $(TOP)/win32/$(DEFFILE) $(OBJS) $(RESFILE) - $(LD) $(LDFLAGS) -def:$(TOP)/win32/$(DEFFILE) -dll -implib:$(IMPLIB) \ - -out:$@ -base:0x5A4C0000 $(OBJS) $(RESFILE) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;2 - -example.exe: example.obj gzlib2.obj gzread2.obj gzwrite2.obj $(STATICLIB) - $(LD) $(LDFLAGS) example.obj gzlib2.obj gzread2.obj gzwrite2.obj $(STATICLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -minigzip.exe: minigzip.obj gzlib2.obj gzread2.obj gzwrite2.obj $(STATICLIB) - $(LD) $(LDFLAGS) minigzip.obj gzlib2.obj gzread2.obj gzwrite2.obj $(STATICLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -example_d.exe: example.obj gzlib2.obj gzread2.obj gzwrite2.obj $(IMPLIB) - $(LD) $(LDFLAGS) -out:$@ example.obj gzlib2.obj gzread2.obj gzwrite2.obj $(IMPLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -minigzip_d.exe: minigzip.obj gzlib2.obj gzread2.obj gzwrite2.obj $(IMPLIB) - $(LD) $(LDFLAGS) -out:$@ minigzip.obj gzlib2.obj gzread2.obj gzwrite2.obj $(IMPLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -{$(TOP)}.c.obj: - $(CC) -c $(WFLAGS) $(CFLAGS) $< - -gzlib2.obj: gzlib.c - $(CC) -c $(WFLAGS) $(CFLAGS) -DWITH_GZFILEOP -Fogzlib2.obj gzlib.c - -gzread2.obj: gzread.c - $(CC) -c $(WFLAGS) $(CFLAGS) -DWITH_GZFILEOP -Fogzread2.obj gzread.c - -gzwrite2.obj: gzwrite.c - $(CC) -c $(WFLAGS) $(CFLAGS) -DWITH_GZFILEOP -Fogzwrite2.obj gzwrite.c - -{$(TOP)/arch/arm}.c.obj: - $(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $< - -{$(TOP)/test}.c.obj: - $(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) -DWITH_GZFILEOP $< - -$(TOP)/zconf$(SUFFIX).h: zconf - -SRCDIR = $(TOP) -# Keep the dependences in sync with top-level Makefile.in -adler32.obj: $(SRCDIR)/adler32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/functable.h $(SRCDIR)/adler32_p.h -functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/zendian.h $(SRCDIR)/arch/x86/x86.h -gzlib.obj: $(SRCDIR)/gzlib.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h -gzread.obj: $(SRCDIR)/gzread.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h -gzwrite.obj: $(SRCDIR)/gzwrite.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h -compress.obj: $(SRCDIR)/compress.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h -uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h -chunkset.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h -crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h -crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h -deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -deflate_medium.obj: $(SRCDIR)/deflate_medium.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -deflate_quick.obj: $(SRCDIR)/deflate_quick.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h $(SRCDIR)/trees_emit.h -deflate_slow.obj: $(SRCDIR)/deflate_slow.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h -inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h -inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h -inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h -trees.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/trees_tbl.h -zutil.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/zutil_p.h - -example.obj: $(TOP)/test/example.c $(TOP)/zbuild.h $(TOP)/zlib$(SUFFIX).h - -minigzip.obj: $(TOP)/test/minigzip.c $(TOP)/zbuild.h $(TOP)/zlib$(SUFFIX).h - -$(RESFILE): $(TOP)/win32/$(RCFILE) - $(RC) $(RCFLAGS) /fo$@ $(TOP)/win32/$(RCFILE) - -# testing -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -testdll: example_d.exe minigzip_d.exe - example_d - echo hello world | minigzip_d | minigzip_d -d - - -# cleanup -clean: - -del $(STATICLIB) - -del $(SHAREDLIB) - -del $(IMPLIB) - -del *.obj - -del *.res - -del *.exp - -del *.exe - -del *.pdb - -del *.manifest - -distclean: clean - -del zconf$(SUFFIX).h diff --git a/libs/zlibng/win32/Makefile.msc b/libs/zlibng/win32/Makefile.msc deleted file mode 100644 index 85d27b9d76..0000000000 --- a/libs/zlibng/win32/Makefile.msc +++ /dev/null @@ -1,215 +0,0 @@ -# Makefile for zlib using Microsoft (Visual) C -# zlib is copyright (C) 1995-2006 Jean-loup Gailly and Mark Adler -# -# Usage: -# nmake -f win32/Makefile.msc (standard build) -# nmake -f win32/Makefile.msc LOC=-DFOO (nonstandard build) - -# The toplevel directory of the source tree. -# -TOP = . - -# optional build flags -LOC = - -# variables -STATICLIB = zlib.lib -SHAREDLIB = zlib1.dll -IMPLIB = zdll.lib - -CC = cl -LD = link -AR = lib -RC = rc -CP = copy /y -CFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC) -WFLAGS = \ - -D_CRT_SECURE_NO_DEPRECATE \ - -D_CRT_NONSTDC_NO_DEPRECATE \ - -DX86_FEATURES \ - -DX86_PCLMULQDQ_CRC \ - -DX86_SSE2 \ - -DX86_SSE42_CRC_INTRIN \ - -DX86_SSE42_CRC_HASH \ - -DX86_AVX2 \ - -DX86_AVX_CHUNKSET \ - -DX86_SSE2_CHUNKSET \ - -DUNALIGNED_OK \ - -DUNALIGNED64_OK \ - # -LDFLAGS = -nologo -debug -incremental:no -opt:ref -manifest -ARFLAGS = -nologo -RCFLAGS = /dWIN32 /r -DEFFILE = zlib.def -RCFILE = zlib1.rc -RESFILE = zlib1.res -WITH_GZFILEOP = yes -ZLIB_COMPAT = -SUFFIX = - -OBJS = \ - adler32.obj \ - chunkset.obj \ - chunkset_avx.obj \ - chunkset_sse.obj \ - compare258.obj \ - compare258_avx.obj \ - compare258_sse.obj \ - compress.obj \ - crc32.obj \ - crc32_comb.obj \ - crc_folding.obj \ - deflate.obj \ - deflate_fast.obj \ - deflate_quick.obj \ - deflate_slow.obj \ - deflate_medium.obj \ - functable.obj \ - infback.obj \ - inflate.obj \ - inftrees.obj \ - inffast.obj \ - insert_string.obj \ - insert_string_sse.obj \ - slide_avx.obj \ - slide_sse.obj \ - trees.obj \ - uncompr.obj \ - zutil.obj \ - x86.obj \ - # -!if "$(ZLIB_COMPAT)" != "" -WITH_GZFILEOP = yes -WFLAGS = $(WFLAGS) -DZLIB_COMPAT -DEFFILE = zlibcompat.def -!else -STATICLIB = zlib-ng.lib -SHAREDLIB = zlib-ng1.dll -IMPLIB = zngdll.lib -DEFFILE = zlib-ng.def -RCFILE = zlib-ng1.rc -RESFILE = zlib-ng1.res -SUFFIX = -ng -!endif - -!if "$(WITH_GZFILEOP)" != "" -WFLAGS = $(WFLAGS) -DWITH_GZFILEOP -OBJS = $(OBJS) gzlib.obj gzread.obj gzwrite.obj -!endif - -# targets -all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ - example.exe minigzip.exe example_d.exe minigzip_d.exe - -zconf: $(TOP)/zconf$(SUFFIX).h.in - $(CP) $(TOP)\zconf$(SUFFIX).h.in $(TOP)\zconf$(SUFFIX).h - -$(STATICLIB): zconf $(OBJS) - $(AR) $(ARFLAGS) -out:$@ $(OBJS) - -$(IMPLIB): $(SHAREDLIB) - -$(SHAREDLIB): zconf $(TOP)/win32/$(DEFFILE) $(OBJS) $(RESFILE) - $(LD) $(LDFLAGS) -def:$(TOP)/win32/$(DEFFILE) -dll -implib:$(IMPLIB) \ - -out:$@ -base:0x5A4C0000 $(OBJS) $(RESFILE) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;2 - -example.exe: example.obj gzlib2.obj gzread2.obj gzwrite2.obj $(STATICLIB) - $(LD) $(LDFLAGS) example.obj gzlib2.obj gzread2.obj gzwrite2.obj $(STATICLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -minigzip.exe: minigzip.obj gzlib2.obj gzread2.obj gzwrite2.obj $(STATICLIB) - $(LD) $(LDFLAGS) minigzip.obj gzlib2.obj gzread2.obj gzwrite2.obj $(STATICLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -example_d.exe: example.obj gzlib2.obj gzread2.obj gzwrite2.obj $(IMPLIB) - $(LD) $(LDFLAGS) -out:$@ example.obj gzlib2.obj gzread2.obj gzwrite2.obj $(IMPLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -minigzip_d.exe: minigzip.obj gzlib2.obj gzread2.obj gzwrite2.obj $(IMPLIB) - $(LD) $(LDFLAGS) -out:$@ minigzip.obj gzlib2.obj gzread2.obj gzwrite2.obj $(IMPLIB) - if exist $@.manifest \ - mt -nologo -manifest $@.manifest -outputresource:$@;1 - -{$(TOP)}.c.obj: - $(CC) -c $(WFLAGS) $(CFLAGS) $< - -gzlib2.obj: gzlib.c - $(CC) -c $(WFLAGS) $(CFLAGS) -DWITH_GZFILEOP -Fogzlib2.obj gzlib.c - -gzread2.obj: gzread.c - $(CC) -c $(WFLAGS) $(CFLAGS) -DWITH_GZFILEOP -Fogzread2.obj gzread.c - -gzwrite2.obj: gzwrite.c - $(CC) -c $(WFLAGS) $(CFLAGS) -DWITH_GZFILEOP -Fogzwrite2.obj gzwrite.c - -{$(TOP)/arch/x86}.c.obj: - $(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $< - -{$(TOP)/test}.c.obj: - $(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) -DWITH_GZFILEOP $< - -$(TOP)/zconf$(SUFFIX).h: zconf - -SRCDIR = $(TOP) -# Keep the dependences in sync with top-level Makefile.in -adler32.obj: $(SRCDIR)/adler32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/functable.h $(SRCDIR)/adler32_p.h -functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/zendian.h $(SRCDIR)/arch/x86/x86.h -gzlib.obj: $(SRCDIR)/gzlib.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h -gzread.obj: $(SRCDIR)/gzread.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h -gzwrite.obj: $(SRCDIR)/gzwrite.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h -compress.obj: $(SRCDIR)/compress.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h -uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h -chunkset.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h -chunkset_avx.obj: $(SRCDIR)/arch/x86/chunkset_avx.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h -chunkset_sse.obj: $(SRCDIR)/arch/x86/chunkset_sse.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h -crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h -crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h -deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -deflate_medium.obj: $(SRCDIR)/deflate_medium.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -deflate_quick.obj: $(SRCDIR)/deflate_quick.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h $(SRCDIR)/trees_emit.h -deflate_slow.obj: $(SRCDIR)/deflate_slow.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h -inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h -inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h -inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h -slide_sse.obj: $(SRCDIR)/arch/x86/slide_sse.c $(SRCDIR)/deflate.h -trees.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/trees_tbl.h -zutil.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/zutil_p.h - -example.obj: $(TOP)/test/example.c $(TOP)/zbuild.h $(TOP)/zlib$(SUFFIX).h - -minigzip.obj: $(TOP)/test/minigzip.c $(TOP)/zbuild.h $(TOP)/zlib$(SUFFIX).h - -$(RESFILE): $(TOP)/win32/$(RCFILE) - $(RC) $(RCFLAGS) /fo$@ $(TOP)/win32/$(RCFILE) - -# testing -test: example.exe minigzip.exe - example - echo hello world | minigzip | minigzip -d - -testdll: example_d.exe minigzip_d.exe - example_d - echo hello world | minigzip_d | minigzip_d -d - - -# cleanup -clean: - -del $(STATICLIB) - -del $(SHAREDLIB) - -del $(IMPLIB) - -del *.obj - -del *.res - -del *.exp - -del *.exe - -del *.pdb - -del *.manifest - -distclean: clean - -del zconf$(SUFFIX).h diff --git a/libs/zlibng/win32/README-WIN32.txt b/libs/zlibng/win32/README-WIN32.txt deleted file mode 100644 index 7a859bb234..0000000000 --- a/libs/zlibng/win32/README-WIN32.txt +++ /dev/null @@ -1,103 +0,0 @@ -ZLIB DATA COMPRESSION LIBRARY - -zlib 1.2.11 is a general purpose data compression library. All the code is -thread safe. The data format used by the zlib library is described by RFCs -(Request for Comments) 1950 to 1952 in the files -http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) -and rfc1952.txt (gzip format). - -All functions of the compression library are documented in the file zlib.h -(volunteer to write man pages welcome, contact zlib@gzip.org). Two compiled -examples are distributed in this package, example and minigzip. The example_d -and minigzip_d flavors validate that the zlib1.dll file is working correctly. - -Questions about zlib should be sent to . The zlib home page -is http://zlib.net/ . Before reporting a problem, please check this site to -verify that you have the latest version of zlib; otherwise get the latest -version and check whether the problem still exists or not. - -PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html -before asking for help. - - -Manifest: - -The package zlib-1.2.11-win32-x86.zip will contain the following files: - - README-WIN32.txt This document - ChangeLog Changes since previous zlib packages - DLL_FAQ.txt Frequently asked questions about zlib1.dll - zlib.3.pdf Documentation of this library in Adobe Acrobat format - - example.exe A statically-bound example (using zlib.lib, not the dll) - example.pdb Symbolic information for debugging example.exe - - example_d.exe A zlib1.dll bound example (using zdll.lib) - example_d.pdb Symbolic information for debugging example_d.exe - - minigzip.exe A statically-bound test program (using zlib.lib, not the dll) - minigzip.pdb Symbolic information for debugging minigzip.exe - - minigzip_d.exe A zlib1.dll bound test program (using zdll.lib) - minigzip_d.pdb Symbolic information for debugging minigzip_d.exe - - zlib.h Install these files into the compilers' INCLUDE path to - zconf.h compile programs which use zlib.lib or zdll.lib - - zdll.lib Install these files into the compilers' LIB path if linking - zdll.exp a compiled program to the zlib1.dll binary - - zlib.lib Install these files into the compilers' LIB path to link zlib - zlib.pdb into compiled programs, without zlib1.dll runtime dependency - (zlib.pdb provides debugging info to the compile time linker) - - zlib1.dll Install this binary shared library into the system PATH, or - the program's runtime directory (where the .exe resides) - zlib1.pdb Install in the same directory as zlib1.dll, in order to debug - an application crash using WinDbg or similar tools. - -All .pdb files above are entirely optional, but are very useful to a developer -attempting to diagnose program misbehavior or a crash. Many additional -important files for developers can be found in the zlib127.zip source package -available from http://zlib.net/ - review that package's README file for details. - - -Acknowledgments: - -The deflate format used by zlib was defined by Phil Katz. The deflate and -zlib specifications were written by L. Peter Deutsch. Thanks to all the -people who reported problems and suggested various improvements in zlib; they -are too numerous to cite here. - - -Copyright notice: - - (C) 1995-2012 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - -If you use the zlib library in a product, we would appreciate *not* receiving -lengthy legal documents to sign. The sources are provided for free but without -warranty of any kind. The library has been entirely written by Jean-loup -Gailly and Mark Adler; it does not include third-party code. - -If you redistribute modified sources, we would appreciate that you include in -the file ChangeLog history information documenting your changes. Please read -the FAQ for more information on the distribution of modified source versions. diff --git a/libs/zlibng/win32/zlib-ng.def b/libs/zlibng/win32/zlib-ng.def deleted file mode 100644 index 467d790097..0000000000 --- a/libs/zlibng/win32/zlib-ng.def +++ /dev/null @@ -1,60 +0,0 @@ -; zlib-ng data compression library -EXPORTS -; basic functions - zlibng_version - zng_deflate - zng_deflateEnd - zng_inflate - zng_inflateEnd -; advanced functions - zng_deflateSetDictionary - zng_deflateGetDictionary - zng_deflateCopy - zng_deflateReset - zng_deflateParams - zng_deflateTune - zng_deflateBound - zng_deflatePending - zng_deflatePrime - zng_deflateSetHeader - zng_deflateSetParams - zng_deflateGetParams - zng_inflateSetDictionary - zng_inflateGetDictionary - zng_inflateSync - zng_inflateCopy - zng_inflateReset - zng_inflateReset2 - zng_inflatePrime - zng_inflateMark - zng_inflateGetHeader - zng_inflateBack - zng_inflateBackEnd - zng_zlibCompileFlags -; utility functions - zng_compress - zng_compress2 - zng_compressBound - zng_uncompress - zng_uncompress2 -; checksum functions - zng_adler32 - zng_adler32_z - zng_crc32 - zng_crc32_z - zng_adler32_combine - zng_crc32_combine -; various hacks, don't look :) - zng_deflateInit_ - zng_deflateInit2_ - zng_inflateInit_ - zng_inflateInit2_ - zng_inflateBackInit_ - zng_zError - zng_inflateSyncPoint - zng_get_crc_table - zng_inflateUndermine - zng_inflateValidate - zng_inflateCodesUsed - zng_inflateResetKeep - zng_deflateResetKeep diff --git a/libs/zlibng/win32/zlib-ng1.rc b/libs/zlibng/win32/zlib-ng1.rc deleted file mode 100644 index fdac56ff68..0000000000 --- a/libs/zlibng/win32/zlib-ng1.rc +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include "../zlib-ng.h" - -#ifdef GCC_WINDRES -VS_VERSION_INFO VERSIONINFO -#else -VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE -#endif - FILEVERSION ZLIBNG_VER_MAJOR,ZLIBNG_VER_MINOR,ZLIBNG_VER_REVISION,0 - PRODUCTVERSION ZLIBNG_VER_MAJOR,ZLIBNG_VER_MINOR,ZLIBNG_VER_REVISION,0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS 1 -#else - FILEFLAGS 0 -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - BEGIN - VALUE "FileDescription", "zlib data compression library\0" - VALUE "FileVersion", ZLIBNG_VERSION "\0" - VALUE "InternalName", "zlib-ng1.dll\0" - VALUE "LegalCopyright", "(C) 1995-2013 Jean-loup Gailly & Mark Adler\0" - VALUE "OriginalFilename", "zlib-ng1.dll\0" - VALUE "ProductName", "zlib\0" - VALUE "ProductVersion", ZLIBNG_VERSION "\0" - VALUE "Comments", "For more information visit http://www.zlib.net/\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/libs/zlibng/win32/zlib.def b/libs/zlibng/win32/zlib.def deleted file mode 100644 index 67644205a7..0000000000 --- a/libs/zlibng/win32/zlib.def +++ /dev/null @@ -1,61 +0,0 @@ -; zlib data compression library -EXPORTS -; basic functions - zlibVersion - deflate - deflateEnd - inflate - inflateEnd -; advanced functions - deflateSetDictionary - deflateGetDictionary - deflateCopy - deflateReset - deflateParams - deflateTune - deflateBound - deflatePending - deflatePrime - deflateSetHeader - inflateSetDictionary - inflateGetDictionary - inflateSync - inflateCopy - inflateReset - inflateReset2 - inflatePrime - inflateMark - inflateGetHeader - inflateBack - inflateBackEnd - zlibCompileFlags -; utility functions - compress - compress2 - compressBound - uncompress - uncompress2 -; large file functions - adler32_combine64 - crc32_combine64 -; checksum functions - adler32 - adler32_z - crc32 - crc32_z - adler32_combine - crc32_combine -; various hacks, don't look :) - deflateInit_ - deflateInit2_ - inflateInit_ - inflateInit2_ - inflateBackInit_ - zError - inflateSyncPoint - get_crc_table - inflateUndermine - inflateValidate - inflateCodesUsed - inflateResetKeep - deflateResetKeep diff --git a/libs/zlibng/win32/zlib1.rc b/libs/zlibng/win32/zlib1.rc deleted file mode 100644 index 5c0feed1b4..0000000000 --- a/libs/zlibng/win32/zlib1.rc +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include "../zlib.h" - -#ifdef GCC_WINDRES -VS_VERSION_INFO VERSIONINFO -#else -VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE -#endif - FILEVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 - PRODUCTVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS 1 -#else - FILEFLAGS 0 -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0 // not used -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - //language ID = U.S. English, char set = Windows, Multilingual - BEGIN - VALUE "FileDescription", "zlib data compression library\0" - VALUE "FileVersion", ZLIB_VERSION "\0" - VALUE "InternalName", "zlib1.dll\0" - VALUE "LegalCopyright", "(C) 1995-2013 Jean-loup Gailly & Mark Adler\0" - VALUE "OriginalFilename", "zlib1.dll\0" - VALUE "ProductName", "zlib\0" - VALUE "ProductVersion", ZLIB_VERSION "\0" - VALUE "Comments", "For more information visit http://www.zlib.net/\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 1252 - END -END diff --git a/libs/zlibng/win32/zlibcompat.def b/libs/zlibng/win32/zlibcompat.def deleted file mode 100644 index a2188b0006..0000000000 --- a/libs/zlibng/win32/zlibcompat.def +++ /dev/null @@ -1,94 +0,0 @@ -; zlib data compression library -EXPORTS -; basic functions - zlibVersion - deflate - deflateEnd - inflate - inflateEnd -; advanced functions - deflateSetDictionary - deflateGetDictionary - deflateCopy - deflateReset - deflateParams - deflateTune - deflateBound - deflatePending - deflatePrime - deflateSetHeader - inflateSetDictionary - inflateGetDictionary - inflateSync - inflateCopy - inflateReset - inflateReset2 - inflatePrime - inflateMark - inflateGetHeader - inflateBack - inflateBackEnd - zlibCompileFlags -; utility functions - compress - compress2 - compressBound - uncompress - uncompress2 - gzopen - gzdopen - gzbuffer - gzsetparams - gzread - gzfread - gzwrite - gzfwrite - gzprintf - gzvprintf - gzputs - gzgets - gzputc - gzgetc - gzungetc - gzflush - gzseek - gzrewind - gztell - gzoffset - gzeof - gzdirect - gzclose - gzclose_r - gzclose_w - gzerror - gzclearerr -; large file functions - gzopen64 - gzseek64 - gztell64 - gzoffset64 - adler32_combine64 - crc32_combine64 -; checksum functions - adler32 - adler32_z - crc32 - crc32_z - adler32_combine - crc32_combine -; various hacks, don't look :) - deflateInit_ - deflateInit2_ - inflateInit_ - inflateInit2_ - inflateBackInit_ - gzgetc_ - zError - inflateSyncPoint - get_crc_table - inflateUndermine - inflateValidate - inflateCodesUsed - inflateResetKeep - deflateResetKeep - gzopen_w diff --git a/libs/zlibng/zbuild.h b/libs/zlibng/zbuild.h deleted file mode 100644 index 3bd4f4898d..0000000000 --- a/libs/zlibng/zbuild.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _ZBUILD_H -#define _ZBUILD_H - -/* This has to be first include that defines any types */ -#if defined(_MSC_VER) -# if defined(_WIN64) - typedef __int64 ssize_t; -# else - typedef long ssize_t; -# endif -#endif - -#if defined(ZLIB_COMPAT) -# define PREFIX(x) x -# define PREFIX2(x) ZLIB_ ## x -# define PREFIX3(x) z_ ## x -# define PREFIX4(x) x ## 64 -# define zVersion zlibVersion -# define z_size_t unsigned long -#else -# define PREFIX(x) zng_ ## x -# define PREFIX2(x) ZLIBNG_ ## x -# define PREFIX3(x) zng_ ## x -# define PREFIX4(x) zng_ ## x -# define zVersion zlibng_version -# define z_size_t size_t -#endif - -#endif diff --git a/libs/zlibng/zconf-ng.h.in b/libs/zlibng/zconf-ng.h.in deleted file mode 100644 index 7d54668d36..0000000000 --- a/libs/zlibng/zconf-ng.h.in +++ /dev/null @@ -1,177 +0,0 @@ -/* zconf-ng.h -- configuration of the zlib-ng compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef ZCONFNG_H -#define ZCONFNG_H - -#if !defined(_WIN32) && defined(__WIN32__) -# define _WIN32 -#endif - -#ifdef __STDC_VERSION__ -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif - -/* Clang macro for detecting declspec support - * https://clang.llvm.org/docs/LanguageExtensions.html#has-declspec-attribute - */ -#ifndef __has_declspec_attribute -# define __has_declspec_attribute(x) 0 -#endif - -/* Always define z_const as const */ -#define z_const const - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# define MAX_MEM_LEVEL 9 -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus about 7 kilobytes - for small objects. -*/ - -/* Type declarations */ - -#ifdef ZLIB_INTERNAL -# define Z_INTERNAL ZLIB_INTERNAL -#endif - -/* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -#if defined(ZLIB_DLL) && (defined(_WIN32) || (__has_declspec_attribute(dllexport) && __has_declspec_attribute(dllimport))) -# ifdef Z_INTERNAL -# define Z_EXTERN extern __declspec(dllexport) -# else -# define Z_EXTERN extern __declspec(dllimport) -# endif -#endif - -/* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -#if defined(ZLIB_WINAPI) && defined(_WIN32) -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define Z_EXPORT WINAPI -# define Z_EXPORTVA WINAPIV -#endif - -#ifndef Z_EXTERN -# define Z_EXTERN extern -#endif -#ifndef Z_EXPORT -# define Z_EXPORT -#endif -#ifndef Z_EXPORTVA -# define Z_EXPORTVA -#endif - -/* Fallback for something that includes us. */ -typedef unsigned char Byte; -typedef Byte Bytef; - -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -typedef char charf; -typedef int intf; -typedef uInt uIntf; -typedef uLong uLongf; - -typedef void const *voidpc; -typedef void *voidpf; -typedef void *voidp; - -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by configure/cmake/etc */ -# define Z_HAVE_UNISTD_H -#endif - -#ifdef NEED_PTRDIFF_T /* may be set to #if 1 by configure/cmake/etc */ -typedef PTRDIFF_TYPE ptrdiff_t; -#endif - -#include /* for off_t */ -#include /* for va_list */ - -#include /* for wchar_t and NULL */ - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ -# ifndef z_off_t -# define z_off_t off_t -# endif -#endif - -#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 -# define Z_LFS64 -#endif - -#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) -# define Z_LARGE64 -#endif - -#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) -# define Z_WANT64 -#endif - -#if !defined(SEEK_SET) && defined(WITH_GZFILEOP) -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if !defined(_WIN32) && defined(Z_LARGE64) -# define z_off64_t off64_t -#else -# if defined(__MSYS__) -# define z_off64_t _off64_t -# elif defined(_WIN32) && !defined(__GNUC__) -# define z_off64_t __int64 -# else -# define z_off64_t z_off_t -# endif -#endif - -#endif /* ZCONFNG_H */ diff --git a/libs/zlibng/zconf.h.in b/libs/zlibng/zconf.h.in deleted file mode 100644 index fcbcbb6b15..0000000000 --- a/libs/zlibng/zconf.h.in +++ /dev/null @@ -1,185 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef ZCONF_H -#define ZCONF_H - -#if !defined(_WIN32) && defined(__WIN32__) -# define _WIN32 -#endif - -#ifdef __STDC_VERSION__ -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif - -/* Clang macro for detecting declspec support - * https://clang.llvm.org/docs/LanguageExtensions.html#has-declspec-attribute - */ -#ifndef __has_declspec_attribute -# define __has_declspec_attribute(x) 0 -#endif - -#if defined(ZLIB_CONST) && !defined(z_const) -# define z_const const -#else -# define z_const -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# define MAX_MEM_LEVEL 9 -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus about 7 kilobytes - for small objects. -*/ - -/* Type declarations */ - - -#ifndef OF /* function prototypes */ -# define OF(args) args -#endif - -#ifdef ZLIB_INTERNAL -# define Z_INTERNAL ZLIB_INTERNAL -#endif - -/* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -#if defined(ZLIB_DLL) && (defined(_WIN32) || (__has_declspec_attribute(dllexport) && __has_declspec_attribute(dllimport))) -# ifdef Z_INTERNAL -# define Z_EXTERN extern __declspec(dllexport) -# else -# define Z_EXTERN extern __declspec(dllimport) -# endif -#endif - -/* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -#if defined(ZLIB_WINAPI) && defined(_WIN32) -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define Z_EXPORT WINAPI -# define Z_EXPORTVA WINAPIV -#endif - -#ifndef Z_EXTERN -# define Z_EXTERN extern -#endif -#ifndef Z_EXPORT -# define Z_EXPORT -#endif -#ifndef Z_EXPORTVA -# define Z_EXPORTVA -#endif - -/* Fallback for something that includes us. */ -typedef unsigned char Byte; -typedef Byte Bytef; - -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -typedef char charf; -typedef int intf; -typedef uInt uIntf; -typedef uLong uLongf; - -typedef void const *voidpc; -typedef void *voidpf; -typedef void *voidp; - -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by configure/cmake/etc */ -# define Z_HAVE_UNISTD_H -#endif - -#ifdef NEED_PTRDIFF_T /* may be set to #if 1 by configure/cmake/etc */ -typedef PTRDIFF_TYPE ptrdiff_t; -#endif - -#include /* for off_t */ -#include /* for va_list */ - -#include /* for wchar_t and NULL */ - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ -# ifndef z_off_t -# define z_off_t off_t -# endif -#endif - -#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 -# define Z_LFS64 -#endif - -#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) -# define Z_LARGE64 -#endif - -#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) -# define Z_WANT64 -#endif - -#if !defined(SEEK_SET) -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if !defined(_WIN32) && defined(Z_LARGE64) -# define z_off64_t off64_t -#else -# if defined(__MSYS__) -# define z_off64_t _off64_t -# elif defined(_WIN32) && !defined(__GNUC__) -# define z_off64_t __int64 -# else -# define z_off64_t z_off_t -# endif -#endif - -#endif /* ZCONF_H */ diff --git a/libs/zlibng/zendian.h b/libs/zlibng/zendian.h deleted file mode 100644 index 54718ed14f..0000000000 --- a/libs/zlibng/zendian.h +++ /dev/null @@ -1,60 +0,0 @@ -/* zendian.h -- define BYTE_ORDER for endian tests - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef ENDIAN_H_ -#define ENDIAN_H_ - -/* First check whether the compiler knows the target __BYTE_ORDER__. */ -#if defined(__BYTE_ORDER__) -# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# if !defined(LITTLE_ENDIAN) -# define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ -# endif -# if !defined(BYTE_ORDER) -# define BYTE_ORDER LITTLE_ENDIAN -# endif -# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# if !defined(BIG_ENDIAN) -# define BIG_ENDIAN __ORDER_BIG_ENDIAN__ -# endif -# if !defined(BYTE_ORDER) -# define BYTE_ORDER BIG_ENDIAN -# endif -# endif -#elif defined(__MINGW32__) -# include -#elif defined(_WIN32) -# define LITTLE_ENDIAN 1234 -# define BIG_ENDIAN 4321 -# if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64) || defined (_M_ARM) || defined (_M_ARM64) -# define BYTE_ORDER LITTLE_ENDIAN -# else -# error Unknown endianness! -# endif -#elif defined(__linux__) -# include -#elif defined(__APPLE__) || defined(__arm__) || defined(__aarch64__) -# include -#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) -# include -#elif defined(__sun) || defined(sun) -# include -# if !defined(LITTLE_ENDIAN) -# define LITTLE_ENDIAN 4321 -# endif -# if !defined(BIG_ENDIAN) -# define BIG_ENDIAN 1234 -# endif -# if !defined(BYTE_ORDER) -# if defined(_BIG_ENDIAN) -# define BYTE_ORDER BIG_ENDIAN -# else -# define BYTE_ORDER LITTLE_ENDIAN -# endif -# endif -#else -# include -#endif - -#endif diff --git a/libs/zlibng/zlib-ng.h b/libs/zlibng/zlib-ng.h deleted file mode 100644 index 275ded7035..0000000000 --- a/libs/zlibng/zlib-ng.h +++ /dev/null @@ -1,1888 +0,0 @@ -#ifndef ZNGLIB_H_ -#define ZNGLIB_H_ -/* zlib-ng.h -- interface of the 'zlib-ng' compression library, forked from zlib. - - Copyright (C) 1995-2016 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 - (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). -*/ - -#include -#include "zconf-ng.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIBNG_VERSION "2.0.0-RC2" -#define ZLIBNG_VERNUM 0x2000 -#define ZLIBNG_VER_MAJOR 2 -#define ZLIBNG_VER_MINOR 0 -#define ZLIBNG_VER_REVISION 0 -#define ZLIBNG_VER_SUBREVISION 0 - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed data. - This version of the library supports only one compression method (deflation) - but other algorithms will be added later and will have the same stream - interface. - - Compression can be done in a single step if the buffers are large enough, - or can be done by repeated calls of the compression function. In the latter - case, the application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip and raw deflate streams in - memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never crash - even in the case of corrupted input. -*/ - -typedef void *(*alloc_func) (void *opaque, unsigned int items, unsigned int size); -typedef void (*free_func) (void *opaque, void *address); - -struct internal_state; - -typedef struct zng_stream_s { - const uint8_t *next_in; /* next input byte */ - uint32_t avail_in; /* number of bytes available at next_in */ - size_t total_in; /* total number of input bytes read so far */ - - uint8_t *next_out; /* next output byte will go here */ - uint32_t avail_out; /* remaining free space at next_out */ - size_t total_out; /* total number of bytes output so far */ - - const char *msg; /* last error message, NULL if no error */ - struct internal_state *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - void *opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: binary or text - for deflate, or the decoding state for inflate */ - uint32_t adler; /* Adler-32 or CRC-32 value of the uncompressed data */ - unsigned long reserved; /* reserved for future use */ -} zng_stream; - -typedef zng_stream *zng_streamp; /* Obsolete type, retained for compatibility only */ - -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -typedef struct zng_gz_header_s { - int32_t text; /* true if compressed data believed to be text */ - unsigned long time; /* modification time */ - int32_t xflags; /* extra flags (not used when writing a gzip file) */ - int32_t os; /* operating system */ - uint8_t *extra; /* pointer to extra field or NULL if none */ - uint32_t extra_len; /* extra field length (valid if extra != NULL) */ - uint32_t extra_max; /* space at extra (only when reading header) */ - uint8_t *name; /* pointer to zero-terminated file name or NULL */ - uint32_t name_max; /* space at name (only when reading header) */ - uint8_t *comment; /* pointer to zero-terminated comment or NULL */ - uint32_t comm_max; /* space at comment (only when reading header) */ - int32_t hcrc; /* true if there was or will be a header crc */ - int32_t done; /* true when done reading gzip header (not used when writing a gzip file) */ -} zng_gz_header; - -typedef zng_gz_header *zng_gz_headerp; - -/* - The application must update next_in and avail_in when avail_in has dropped - to zero. It must update next_out and avail_out when avail_out has dropped - to zero. The application must initialize zalloc, zfree and opaque before - calling the init function. All other fields are set by the compression - library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. In that case, zlib is thread-safe. When zalloc and zfree are - Z_NULL on entry to the initialization function, they are set to internal - routines that use the standard library functions malloc() and free(). - - The fields total_in and total_out can be used for statistics or progress - reports. After compression, total_in holds the total size of the - uncompressed data and may be saved for use by the decompressor (particularly - if the decompressor wants to decompress everything in a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -#define Z_TREES 6 -/* Allowed flush values; see deflate() and inflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ -#define Z_UNKNOWN 2 -/* Possible values of the data_type field for deflate() */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL NULL /* for compatibility with zlib, was for initializing zalloc, zfree, opaque */ - - - /* basic functions */ - -Z_EXTERN Z_EXPORT -const char *zlibng_version(void); -/* The application can compare zlibng_version and ZLIBNG_VERSION for consistency. - If the first character differs, the library code actually used is not - compatible with the zlib-ng.h header file used by the application. This check - is automatically made by deflateInit and inflateInit. - */ - -/* -Z_EXTERN Z_EXPORT -int zng_deflateInit(zng_stream *strm, int level); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. If - zalloc and zfree are set to NULL, deflateInit updates them to use default - allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at all - (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION - requests a default compromise between speed and compression (currently - equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if level is not a valid compression level, or - Z_VERSION_ERROR if the zlib library version (zng_version) is incompatible - with the version assumed by the caller (ZLIBNG_VERSION). msg is set to null - if there is no error message. deflateInit does not perform any compression: - this will be done by deflate(). -*/ - - -Z_EXTERN Z_EXPORT -int32_t zng_deflate(zng_stream *strm, int32_t flush); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Generate more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary. Some output may be provided even if - flush is zero. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating avail_in or avail_out accordingly; avail_out should - never be zero before the call. The application can consume the compressed - output when it wants, for example when the output buffer is full (avail_out - == 0), or after each call of deflate(). If deflate returns Z_OK and with - zero avail_out, it must be called again after making room in the output - buffer because there might be more output pending. See deflatePending(), - which can be used if desired to determine whether or not there is more ouput - in that case. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumulate before producing output, in order to - maximize compression. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In - particular avail_in is zero after the call if enough output space has been - provided before the call.) Flushing may degrade compression for some - compression algorithms and so it should be used only when necessary. This - completes the current deflate block and follows it with an empty stored block - that is three bits plus filler bits to the next byte, followed by four bytes - (00 00 ff ff). - - If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the - output buffer, but the output is not aligned to a byte boundary. All of the - input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. - This completes the current deflate block and follows it with an empty fixed - codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed - codes block. - - If flush is set to Z_BLOCK, a deflate block is completed and emitted, as - for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to - seven bits of the current block are held to be written as the next byte after - the next deflate block is completed. In this case, the decompressor may not - be provided enough bits at this point in order to complete decompression of - the data provided so far to the compressor. It may need to wait for the next - block to be emitted. This is for advanced applications that need to control - the emission of deflate blocks. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there was - enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this - function must be called again with Z_FINISH and more output space (updated - avail_out) but no more input data, until it returns with Z_STREAM_END or an - error. After deflate has returned Z_STREAM_END, the only possible operations - on the stream are deflateReset or deflateEnd. - - Z_FINISH can be used in the first deflate call after deflateInit if all the - compression is to be done in a single step. In order to complete in one - call, avail_out must be at least the value returned by deflateBound (see - below). Then deflate is guaranteed to return Z_STREAM_END. If not enough - output space is provided, deflate will not return Z_STREAM_END, and it must - be called again as described above. - - deflate() sets strm->adler to the Adler-32 checksum of all input read - so far (that is, total_in bytes). If a gzip stream is being generated, then - strm->adler will be the CRC-32 checksum of the input read so far. (See - deflateInit2 below.) - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is - considered binary. This field is only for information purposes and does not - affect the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL) or the state was inadvertently written over - by the application), or Z_BUF_ERROR if no progress is possible (for example - avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and - deflate() can be called again with more input and more output space to - continue compressing. -*/ - - -Z_EXTERN Z_EXPORT -int32_t zng_deflateEnd(zng_stream *strm); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, msg - may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -Z_EXTERN Z_EXPORT -int zng_inflateInit(zng_stream *strm); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. In the current version of inflate, the provided input is not - read or consumed. The allocation of a sliding window will be deferred to - the first call of inflate (if the decompression does not complete on the - first call). If zalloc and zfree are set to NULL, inflateInit updates - them to use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression. - Actual decompression will be done by inflate(). So next_in, and avail_in, - next_out, and avail_out are unused and unchanged. The current - implementation of inflateInit() does not process any header information -- - that is deferred until inflate() is called. -*/ - - -Z_EXTERN Z_EXPORT -int32_t zng_inflate(zng_stream *strm, int32_t flush); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), then next_in and avail_in are updated - accordingly, and processing will resume at this point for the next call of - inflate(). - - - Generate more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there is - no more input data or no more space in the output buffer (see below about - the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. If the - caller of inflate() does not provide both available input and available - output space, it is possible that there will be no progress made. The - application can consume the uncompressed output when it wants, for example - when the output buffer is full (avail_out == 0), or after each call of - inflate(). If inflate returns Z_OK and with zero avail_out, it must be - called again after making room in the output buffer because there might be - more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, - Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() - stop if and when it gets to the next deflate block boundary. When decoding - the zlib or gzip format, this will cause inflate() to return immediately - after the header and before the first block. When doing a raw inflate, - inflate() will go ahead and process the first block, and will return when it - gets to the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - To assist in this, on return inflate() always sets strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 if - inflate() is currently decoding the last block in the deflate stream, plus - 128 if inflate() returned immediately after decoding an end-of-block code or - decoding the complete header up to just before the first byte of the deflate - stream. The end-of-block will not be indicated until all of the uncompressed - data from that block has been written to strm->next_out. The number of - unused bits may in general be greater than seven, except when bit 7 of - data_type is set, in which case the number of unused bits will be less than - eight. data_type is set as noted here every time inflate() returns for all - flush options, and so can be used to determine the amount of currently - consumed input in bits. - - The Z_TREES option behaves as Z_BLOCK does, but it also returns when the - end of each deflate block header is reached, before any actual data in that - block is decoded. This allows the caller to determine the length of the - deflate block header for later use in random access within a deflate block. - 256 is added to the value of strm->data_type when inflate() returns - immediately after reaching the end of the deflate block header. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step (a - single call of inflate), the parameter flush should be set to Z_FINISH. In - this case all pending input is processed and all pending output is flushed; - avail_out must be large enough to hold all of the uncompressed data for the - operation to complete. (The size of the uncompressed data may have been - saved by the compressor for this purpose.) The use of Z_FINISH is not - required to perform an inflation in one step. However it may be used to - inform inflate that a faster approach can be used for the single inflate() - call. Z_FINISH also informs inflate to not maintain a sliding window if the - stream completes, which reduces inflate's memory footprint. If the stream - does not complete, either because not all of the stream is provided or not - enough output space is provided, then a sliding window will be allocated and - inflate() can be called again to continue the operation as if Z_NO_FLUSH had - been used. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the effects of the flush parameter in this implementation are - on the return value of inflate() as noted below, when inflate() returns early - when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of - memory for a sliding window when Z_FINISH is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the Adler-32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the Adler-32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed Adler-32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() can decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically, if requested when - initializing with inflateInit2(). Any information contained in the gzip - header is not retained unless inflateGetHeader() is used. When processing - gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output - produced so far. The CRC-32 is checked against the gzip trailer, as is the - uncompressed length, modulo 2^32. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value, in which case strm->msg points to a string with a more specific - error), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was NULL, or the state was inadvertently written over - by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR - if no progress is possible or if there was not enough room in the output - buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may - then call inflateSync() to look for a good compression block if a partial - recovery of the data is to be attempted. -*/ - - -Z_EXTERN Z_EXPORT -int32_t zng_inflateEnd(zng_stream *strm); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state - was inconsistent. -*/ - - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -Z_EXTERN Z_EXPORT -int zng_deflateInit2(zng_stream *strm, int level, int method, int windowBits, int memLevel, int strategy); - - This is another version of deflateInit with more compression options. The - fields zalloc, zfree and opaque must be initialized before by the caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - For the current implementation of deflate(), a windowBits value of 8 (a - window size of 256 bytes) is not supported. As a result, a request for 8 - will result in 9 (a 512-byte window). In that case, providing 8 to - inflateInit2() will result in an error when the zlib header with 9 is - checked against the initialization of inflate(). The remedy is to not use 8 - with deflateInit2() with this initialization, or at least in that case use 9 - with inflateInit2(). - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute a check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to the appropriate value, - if the operating system was determined at compile time. If a gzip stream is - being written, strm->adler is a CRC-32 instead of an Adler-32. - - For raw deflate or gzip encoding, a request for a 256-byte window is - rejected as invalid, since only the zlib header provides a means of - transmitting the window size to the decompressor. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but is - slow and reduces compression ratio; memLevel=9 uses maximum memory for - optimal speed. The default value is 8. See zconf.h for total memory usage - as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as - fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The - strategy parameter only affects the compression ratio but not the - correctness of the compressed output even if it is not set appropriately. - Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler - decoder for special applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid - method), or Z_VERSION_ERROR if the zlib library version (zng_version) is - incompatible with the version assumed by the caller (ZLIBNG_VERSION). msg is - set to null if there is no error message. deflateInit2 does not perform any - compression: this will be done by deflate(). -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_deflateSetDictionary(zng_stream *strm, const uint8_t *dictionary, uint32_t dictLength); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. When using the zlib format, this - function must be called immediately after deflateInit, deflateInit2 or - deflateReset, and before any call of deflate. When doing raw deflate, this - function must be called either before any call of deflate, or immediately - after the completion of a deflate block, i.e. after all input has been - consumed and all output has been delivered when using any of the flush - options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The - compressor and decompressor must use exactly the same dictionary (see - inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size - provided in deflateInit or deflateInit2. Thus the strings most likely to be - useful should be put at the end of the dictionary, not at the front. In - addition, the current implementation of deflate will use at most the window - size minus 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the Adler-32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The Adler-32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - Adler-32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being NULL) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if not at a block boundary for raw deflate). deflateSetDictionary does - not perform any compression: this will be done by deflate(). -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_deflateGetDictionary(zng_stream *strm, uint8_t *dictionary, uint32_t *dictLength); -/* - Returns the sliding dictionary being maintained by deflate. dictLength is - set to the number of bytes in the dictionary, and that many bytes are copied - to dictionary. dictionary must have enough space, where 32768 bytes is - always enough. If deflateGetDictionary() is called with dictionary equal to - Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. - - deflateGetDictionary() may return a length less than the window size, even - when more than the window size in input has been provided. It may return up - to 258 bytes less in that case, due to how zlib's implementation of deflate - manages the sliding window and lookahead for matches, where matches can be - up to 258 bytes long. If the application needs the last window-size bytes of - input, then that would need to be saved by the application outside of zlib. - - deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the - stream state is inconsistent. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_deflateCopy(zng_stream *dest, zng_stream *source); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and can - consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_deflateReset(zng_stream *strm); -/* - This function is equivalent to deflateEnd followed by deflateInit, but - does not free and reallocate the internal compression state. The stream - will leave the compression level and any other attributes that may have been - set unchanged. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_deflateParams(zng_stream *strm, int32_t level, int32_t strategy); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2(). This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different strategy. - If the compression approach (which is a function of the level) or the - strategy is changed, and if there have been any deflate() calls since the - state was initialized or reset, then the input available so far is - compressed with the old level and strategy using deflate(strm, Z_BLOCK). - There are three approaches for the compression levels 0, 1..3, and 4..9 - respectively. The new level and strategy will take effect at the next call - of deflate(). - - If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does - not have enough output space to complete, then the parameter change will not - take effect. In this case, deflateParams() can be called again with the - same parameters and more output space to try again. - - In order to assure a change in the parameters on the first try, the - deflate stream should be flushed using deflate() with Z_BLOCK or other flush - request until strm.avail_out is not zero, before calling deflateParams(). - Then no more input data should be provided before the deflateParams() call. - If this is done, the old level and strategy will be applied to the data - compressed before deflateParams(), and the new level and strategy will be - applied to the the data compressed after deflateParams(). - - deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream - state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if - there was not enough output space to complete the compression of the - available input data before a change in the strategy or approach. Note that - in the case of a Z_BUF_ERROR, the parameters are not changed. A return - value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be - retried with more output space. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_deflateTune(zng_stream *strm, int32_t good_length, int32_t max_lazy, int32_t nice_length, int32_t max_chain); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -Z_EXTERN Z_EXPORT -unsigned long zng_deflateBound(zng_stream *strm, unsigned long sourceLen); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() or - deflateInit2(), and after deflateSetHeader(), if used. This would be used - to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). If that first deflate() call is provided the - sourceLen input bytes, an output buffer allocated to the size returned by - deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed - to return Z_STREAM_END. Note that it is possible for the compressed size to - be larger than the value returned by deflateBound() if flush options other - than Z_FINISH or Z_NO_FLUSH are used. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_deflatePending(zng_stream *strm, uint32_t *pending, int32_t *bits); -/* - deflatePending() returns the number of bytes and bits of output that have - been generated, but not yet provided in the available output. The bytes not - provided would be due to the available output space having being consumed. - The number of bits of output not provided are between 0 and 7, where they - await more bits to join them in order to fill out a full byte. If pending - or bits are NULL, then those values are not set. - - deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. - */ - -Z_EXTERN Z_EXPORT -int32_t zng_deflatePrime(zng_stream *strm, int32_t bits, int32_t value); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the bits - leftover from a previous deflate stream when appending to it. As such, this - function can only be used for raw deflate, and must be used before the first - deflate() call after a deflateInit2() or deflateReset(). bits must be less - than or equal to 16, and that many of the least significant bits of value - will be inserted in the output. - - deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough - room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the - source stream state was inconsistent. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_deflateSetHeader(zng_stream *strm, zng_gz_headerp head); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided zng_gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not NULL, name and comment are terminated with - a zero byte, and that if extra is not NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -Z_EXTERN Z_EXPORT -int zng_inflateInit2(zng_stream *strm, int windowBits); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be zero to request that inflate use the window size in - the zlib header of the compressed stream. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an Adler-32 or a CRC-32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see - below), inflate() will *not* automatically decode concatenated gzip members. - inflate() will return Z_STREAM_END at the end of the gzip member. The state - would need to be reset to continue decoding a subsequent gzip member. This - *must* be done if there is more data after a gzip member, in order for the - decompression to be compliant with the gzip standard (RFC 1952). - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit2 does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit2() does not process any header information -- that is - deferred until inflate() is called. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_inflateSetDictionary(zng_stream *strm, const uint8_t *dictionary, uint32_t dictLength); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the Adler-32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called at any - time to set the dictionary. If the provided dictionary is smaller than the - window and there is already data in the window, then the provided dictionary - will amend what's there. The application must insure that the dictionary - that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being NULL) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect Adler-32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_inflateGetDictionary(zng_stream *strm, uint8_t *dictionary, uint32_t *dictLength); -/* - Returns the sliding dictionary being maintained by inflate. dictLength is - set to the number of bytes in the dictionary, and that many bytes are copied - to dictionary. dictionary must have enough space, where 32768 bytes is - always enough. If inflateGetDictionary() is called with dictionary equal to - NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is NULL, then it is not set. - - inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the - stream state is inconsistent. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_inflateSync(zng_stream *strm); -/* - Skips invalid compressed data until a possible full flush point (see above - for the description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync searches for a 00 00 FF FF pattern in the compressed data. - All full flush points have this pattern, but not all occurrences of this - pattern are full flush points. - - inflateSync returns Z_OK if a possible full flush point has been found, - Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point - has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. - In the success case, the application may save the current current value of - total_in which indicates where valid compressed data was found. In the - error case, the application may repeatedly call inflateSync, providing more - input each time, until success or end of the input data. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_inflateCopy(zng_stream *dest, zng_stream *source); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_inflateReset(zng_stream *strm); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate the internal decompression state. The - stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_inflateReset2(zng_stream *strm, int32_t windowBits); -/* - This function is the same as inflateReset, but it also permits changing - the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. If the window size is changed, then the - memory allocated for the window is freed, and the window will be reallocated - by inflate() if needed. - - inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL), or if - the windowBits parameter is invalid. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_inflatePrime(zng_stream *strm, int32_t bits, int32_t value); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - If bits is negative, then the input stream bit buffer is emptied. Then - inflatePrime() can be called again to put bits in the buffer. This is used - to clear out bits leftover after feeding inflate a block description prior - to feeding inflate codes. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -Z_EXTERN Z_EXPORT -long zng_inflateMark(zng_stream *strm); -/* - This function returns two values, one in the lower 16 bits of the return - value, and the other in the remaining upper bits, obtained by shifting the - return value down 16 bits. If the upper value is -1 and the lower value is - zero, then inflate() is currently decoding information outside of a block. - If the upper value is -1 and the lower value is non-zero, then inflate is in - the middle of a stored block, with the lower value equaling the number of - bytes from the input remaining to copy. If the upper value is not -1, then - it is the number of bits back from the current bit position in the input of - the code (literal or length/distance pair) currently being processed. In - that case the lower value is the number of bytes already emitted for that - code. - - A code is being processed if inflate is waiting for more input to complete - decoding of the code, or if it has completed decoding but is waiting for - more output space to write the literal or match data. - - inflateMark() is used to mark locations in the input data for random - access, which may be at bit positions, and to note those cases where the - output of a code may span boundaries of random access blocks. The current - location in the input stream can be determined from avail_in and data_type - as noted in the description for the Z_BLOCK flush parameter for inflate. - - inflateMark returns the value noted above, or -65536 if the provided - source stream state was inconsistent. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_inflateGetHeader(zng_stream *strm, zng_gz_headerp head); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided zng_gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be - used to force inflate() to return immediately after header processing is - complete and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When any - of extra, name, or comment are not NULL and the respective field is not - present in the header, then that field is set to NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -Z_EXTERN Z_EXPORT -int zng_inflateBackInit(zng_stream *strm, int windowBits, unsigned char *window); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the parameters are invalid, Z_MEM_ERROR if the internal state could not be - allocated, or Z_VERSION_ERROR if the version of the library does not match - the version of the header file. -*/ - -typedef uint32_t (*in_func) (void *, const uint8_t * *); -typedef int32_t (*out_func) (void *, uint8_t *, uint32_t); - -Z_EXTERN Z_EXPORT -int32_t zng_inflateBack(zng_stream *strm, in_func in, void *in_desc, out_func out, void *out_desc); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is potentially more efficient than - inflate() for file i/o applications, in that it avoids copying between the - output and the sliding window by simply making the window itself the output - buffer. inflate() can be faster on modern CPUs when used with large - buffers. inflateBack() trusts the application to not change the output - buffer passed by the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free the - allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the default - behavior of inflate(), which expects a zlib header and trailer around the - deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero -- buf is ignored in that - case -- and inflateBack() will return a buffer error. inflateBack() will - call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. - out() should return zero on success, or non-zero on failure. If out() - returns non-zero, inflateBack() will return with an error. Neither in() nor - out() are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is NULL, then in() will be called - immediately for input. If strm->next_in is not NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format error - in the deflate stream (in which case strm->msg is set to indicate the nature - of the error), or Z_STREAM_ERROR if the stream was not properly initialized. - In the case of Z_BUF_ERROR, an input or output error can be distinguished - using strm->next_in which will be NULL only if in() returned an error. If - strm->next_in is not NULL, then the Z_BUF_ERROR was due to out() returning - non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() - cannot return Z_OK. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_inflateBackEnd(zng_stream *strm); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -Z_EXTERN Z_EXPORT -unsigned long zng_zlibCompileFlags(void); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of unsigned int - 3.2: size of unsigned long - 5.4: size of void * (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: ZLIB_DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed (not supported by zlib-ng) - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - - - /* utility functions */ - -/* - The following utility functions are implemented on top of the basic - stream-oriented functions. To simplify the interface, some default options - are assumed (compression level and memory usage, standard memory allocation - functions). The source code of these utility functions can be modified if - you need special options. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_compress(uint8_t *dest, size_t *destLen, const uint8_t *source, size_t sourceLen); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed data. compress() is equivalent to compress2() with a level - parameter of Z_DEFAULT_COMPRESSION. - - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_compress2(uint8_t *dest, size_t *destLen, const uint8_t *source, size_t sourceLen, int32_t level); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed data. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -Z_EXTERN Z_EXPORT -size_t zng_compressBound(size_t sourceLen); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before a - compress() or compress2() call to allocate the destination buffer. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_uncompress(uint8_t *dest, size_t *destLen, const uint8_t *source, size_t sourceLen); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be large enough to hold the entire - uncompressed data. (The size of the uncompressed data must have been saved - previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed data. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In - the case where there is not enough room, uncompress() will fill the output - buffer with the uncompressed data up to that point. -*/ - - -Z_EXTERN Z_EXPORT -int32_t zng_uncompress2(uint8_t *dest, size_t *destLen, const uint8_t *source, size_t *sourceLen); -/* - Same as uncompress, except that sourceLen is a pointer, where the - length of the source is *sourceLen. On return, *sourceLen is the number of - source bytes consumed. -*/ - - -#ifdef WITH_GZFILEOP - /* gzip file access functions */ - -/* - This library supports reading and writing files in gzip (.gz) format with - an interface similar to that of stdio, using the functions that start with - "gz". The gzip format is different from the zlib format. gzip is a gzip - wrapper, documented in RFC 1952, wrapped around a deflate stream. -*/ - -typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ - -Z_EXTERN Z_EXPORT -gzFile zng_gzopen(const char *path, const char *mode); -/* - Opens a gzip (.gz) file for reading or writing. The mode parameter is as - in fopen ("rb" or "wb") but can also include a compression level ("wb9") or - a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only - compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' - for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) 'T' will - request transparent writing or appending with no compression and not using - the gzip format. - - "a" can be used instead of "w" to request that the gzip stream that will - be written be appended to the file. "+" will result in an error, since - reading and writing to the same gzip file is not supported. The addition of - "x" when writing will create the file exclusively, which fails if the file - already exists. On systems that support it, the addition of "e" when - reading or writing will set the flag to close the file on an execve() call. - - These functions, as well as gzip, will read and decode a sequence of gzip - streams in a file. The append function of gzopen() can be used to create - such a file. (Also see gzflush() for another way to do this.) When - appending, gzopen does not test whether the file begins with a gzip stream, - nor does it look for the end of the gzip streams to begin appending. gzopen - will simply append a gzip stream to the existing file. - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. When - reading, this will be detected automatically by looking for the magic two- - byte gzip header. - - gzopen returns NULL if the file could not be opened, if there was - insufficient memory to allocate the gzFile state, or if an invalid mode was - specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). - errno can be checked to determine if the reason gzopen failed was that the - file could not be opened. -*/ - -Z_EXTERN Z_EXPORT -gzFile zng_gzdopen(int fd, const char *mode); -/* - gzdopen associates a gzFile with the file descriptor fd. File descriptors - are obtained from calls like open, dup, creat, pipe or fileno (if the file - has been previously opened with fopen). The mode parameter is as in gzopen. - - The next call of gzclose on the returned gzFile will also close the file - descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor - fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, - mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. If you are using fileno() to get the - file descriptor from a FILE *, then you will have to use dup() to avoid - double-close()ing the file descriptor. Both gzclose() and fclose() will - close the associated file descriptor, so they need to have different file - descriptors. - - gzdopen returns NULL if there was insufficient memory to allocate the - gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not - provided, or '+' was provided), or if fd is -1. The file descriptor is not - used until the next gz* read, write, seek, or close operation, so gzdopen - will not detect if fd is invalid (unless fd is -1). -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzbuffer(gzFile file, uint32_t size); -/* - Set the internal buffer size used by this library's functions. The - default buffer size is 8192 bytes. This function must be called after - gzopen() or gzdopen(), and before any other calls that read or write the - file. The buffer memory allocation is always deferred to the first read or - write. Three times that size in buffer space is allocated. A larger buffer - size of, for example, 64K or 128K bytes will noticeably increase the speed - of decompression (reading). - - The new buffer size also affects the maximum length for gzprintf(). - - gzbuffer() returns 0 on success, or -1 on failure, such as being called - too late. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzsetparams(gzFile file, int32_t level, int32_t strategy); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. Previously provided - data is flushed before the parameter change. - - gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not - opened for writing, Z_ERRNO if there is an error writing the flushed data, - or Z_MEM_ERROR if there is a memory allocation error. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzread(gzFile file, void *buf, uint32_t len); -/* - Reads the given number of uncompressed bytes from the compressed file. If - the input file is not in gzip format, gzread copies the given number of - bytes into the buffer directly from the file. - - After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream. Any number of gzip streams may be - concatenated in the input file, and will all be decompressed by gzread(). - If something other than a gzip stream is encountered after a gzip stream, - that remaining trailing garbage is ignored (and no error is returned). - - gzread can be used to read a gzip file that is being concurrently written. - Upon reaching the end of the input, gzread will return with the available - data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then - gzclearerr can be used to clear the end of file indicator in order to permit - gzread to be tried again. Z_OK indicates that a gzip stream was completed - on the last gzread. Z_BUF_ERROR indicates that the input file ended in the - middle of a gzip stream. Note that gzread does not return -1 in the event - of an incomplete gzip stream. This error is deferred until gzclose(), which - will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip - stream. Alternatively, gzerror can be used before gzclose to detect this - case. - - gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. If len is too large to fit in an int, - then nothing is read, -1 is returned, and the error state is set to - Z_STREAM_ERROR. -*/ - -Z_EXTERN Z_EXPORT -size_t zng_gzfread(void *buf, size_t size, size_t nitems, gzFile file); -/* - Read up to nitems items of size size from file to buf, otherwise operating - as gzread() does. This duplicates the interface of stdio's fread(), with - size_t request and return types. - - gzfread() returns the number of full items read of size size, or zero if - the end of the file was reached and a full item could not be read, or if - there was an error. gzerror() must be consulted if zero is returned in - order to determine if there was an error. If the multiplication of size and - nitems overflows, i.e. the product does not fit in a size_t, then nothing - is read, zero is returned, and the error state is set to Z_STREAM_ERROR. - - In the event that the end of file is reached and only a partial item is - available at the end, i.e. the remaining uncompressed data length is not a - multiple of size, then the final partial item is nevertheless read into buf - and the end-of-file flag is set. The length of the partial item read is not - provided, but could be inferred from the result of gztell(). This behavior - is the same as the behavior of fread() implementations in common libraries, - but it prevents the direct use of gzfread() to read a concurrently written - file, reseting and retrying on end-of-file, when size is not 1. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzwrite(gzFile file, void const *buf, uint32_t len); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes written or 0 in case of - error. -*/ - -Z_EXTERN Z_EXPORT -size_t zng_gzfwrite(void const *buf, size_t size, size_t nitems, gzFile file); -/* - gzfwrite() writes nitems items of size size from buf to file, duplicating - the interface of stdio's fwrite(), with size_t request and return types. - - gzfwrite() returns the number of full items written of size size, or zero - if there was an error. If the multiplication of size and nitems overflows, - i.e. the product does not fit in a size_t, then nothing is written, zero - is returned, and the error state is set to Z_STREAM_ERROR. -*/ - -Z_EXTERN Z_EXPORTVA -int32_t zng_gzprintf(gzFile file, const char *format, ...); -/* - Converts, formats, and writes the arguments to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or a negative zlib error code in case - of error. The number of uncompressed bytes written is limited to 8191, or - one less than the buffer size given to gzbuffer(). The caller should assure - that this limit is not exceeded. If it is exceeded, then gzprintf() will - return an error (0) with nothing written. In this case, there may also be a - buffer overflow with unpredictable consequences, which is possible only if - zlib was compiled with the insecure functions sprintf() or vsprintf() - because the secure snprintf() or vsnprintf() functions were not available. - This can be determined using zlibCompileFlags(). -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzputs(gzFile file, const char *s); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - - gzputs returns the number of characters written, or -1 in case of error. -*/ - -Z_EXTERN Z_EXPORT -char * zng_gzgets(gzFile file, char *buf, int32_t len); -/* - Reads bytes from the compressed file until len-1 characters are read, or a - newline character is read and transferred to buf, or an end-of-file - condition is encountered. If any characters are read or if len == 1, the - string is terminated with a null character. If no characters are read due - to an end-of-file or len < 1, then the buffer is left untouched. - - gzgets returns buf which is a null-terminated string, or it returns NULL - for end-of-file or in case of error. If there was an error, the contents at - buf are indeterminate. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzputc(gzFile file, int32_t c); -/* - Writes c, converted to an unsigned char, into the compressed file. gzputc - returns the value that was written, or -1 in case of error. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzgetc(gzFile file); -/* - Reads one byte from the compressed file. gzgetc returns this byte or -1 - in case of end of file or error. This is implemented as a macro for speed. - As such, it does not do all of the checking the other functions do. I.e. - it does not check to see if file is NULL, nor whether the structure file - points to has been clobbered or not. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzungetc(int32_t c, gzFile file); -/* - Push one character back onto the stream to be read as the first character - on the next read. At least one character of push-back is allowed. - gzungetc() returns the character pushed, or -1 on failure. gzungetc() will - fail if c is -1, and may fail if a character has been pushed but not read - yet. If gzungetc is used immediately after gzopen or gzdopen, at least the - output buffer size of pushed characters is allowed. (See gzbuffer above.) - The pushed character will be discarded if the stream is repositioned with - gzseek() or gzrewind(). -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzflush(gzFile file, int32_t flush); -/* - Flushes all pending output into the compressed file. The parameter flush - is as in the deflate() function. The return value is the zlib error number - (see function gzerror below). gzflush is only permitted when writing. - - If the flush parameter is Z_FINISH, the remaining data is written and the - gzip stream is completed in the output. If gzwrite() is called again, a new - gzip stream will be started in the output. gzread() is able to read such - concatenated gzip streams. - - gzflush should be called only when strictly necessary because it will - degrade compression if called too often. -*/ - -Z_EXTERN Z_EXPORT -z_off64_t zng_gzseek(gzFile file, z_off64_t offset, int whence); -/* - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzrewind(gzFile file); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -Z_EXTERN Z_EXPORT -z_off64_t zng_gztell(gzFile file); -/* - Returns the starting position for the next gzread or gzwrite on the given - compressed file. This position represents a number of bytes in the - uncompressed data stream, and is zero when starting, even if appending or - reading a gzip stream from the middle of a file using gzdopen(). - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -Z_EXTERN Z_EXPORT -z_off64_t zng_gzoffset(gzFile file); -/* - Returns the current offset in the file being read or written. This offset - includes the count of bytes that precede the gzip stream, for example when - appending or when using gzdopen() for reading. When reading, the offset - does not include as yet unused buffered input. This information can be used - for a progress indicator. On error, gzoffset() returns -1. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzeof(gzFile file); -/* - Returns true (1) if the end-of-file indicator has been set while reading, - false (0) otherwise. Note that the end-of-file indicator is set only if the - read tried to go past the end of the input, but came up short. Therefore, - just like feof(), gzeof() may return false even if there is no more data to - read, in the event that the last read request was for the exact number of - bytes remaining in the input file. This will happen if the input file size - is an exact multiple of the buffer size. - - If gzeof() returns true, then the read functions will return no more data, - unless the end-of-file indicator is reset by gzclearerr() and the input file - has grown since the previous end of file was detected. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzdirect(gzFile file); -/* - Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. - - If the input file is empty, gzdirect() will return true, since the input - does not contain a gzip stream. - - If gzdirect() is used immediately after gzopen() or gzdopen() it will - cause buffers to be allocated to allow reading the file to determine if it - is a gzip file. Therefore if gzbuffer() is used, it should be called before - gzdirect(). - - When writing, gzdirect() returns true (1) if transparent writing was - requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: - gzdirect() is not needed when writing. Transparent writing must be - explicitly requested, so the application already knows the answer. When - linking statically, using gzdirect() will include all of the zlib code for - gzip file reading and decompression, which may not be desired.) -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzclose(gzFile file); -/* - Flushes all pending output if necessary, closes the compressed file and - deallocates the (de)compression state. Note that once file is closed, you - cannot call gzerror with file, since its structures have been deallocated. - gzclose must not be called more than once on the same file, just as free - must not be called more than once on the same allocation. - - gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the - last read ended in the middle of a gzip stream, or Z_OK on success. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_gzclose_r(gzFile file); -Z_EXTERN Z_EXPORT -int32_t zng_gzclose_w(gzFile file); -/* - Same as gzclose(), but gzclose_r() is only for use when reading, and - gzclose_w() is only for use when writing or appending. The advantage to - using these instead of gzclose() is that they avoid linking in zlib - compression or decompression code that is not used when only reading or only - writing respectively. If gzclose() is used, then both compression and - decompression code will be included the application when linking to a static - zlib library. -*/ - -Z_EXTERN Z_EXPORT -const char * zng_gzerror(gzFile file, int32_t *errnum); -/* - Returns the error message for the last error which occurred on the given - compressed file. errnum is set to zlib error number. If an error occurred - in the file system and not in the compression library, errnum is set to - Z_ERRNO and the application may consult errno to get the exact error code. - - The application must not modify the returned string. Future calls to - this function may invalidate the previously returned string. If file is - closed, then the string previously returned by gzerror will no longer be - available. - - gzerror() should be used to distinguish errors from end-of-file for those - functions above that do not distinguish those cases in their return values. -*/ - -Z_EXTERN Z_EXPORT -void zng_gzclearerr(gzFile file); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - -#endif /* WITH_GZFILEOP */ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the compression - library. -*/ - -Z_EXTERN Z_EXPORT -uint32_t zng_adler32(uint32_t adler, const uint8_t *buf, uint32_t len); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns the - required initial value for the checksum. - - An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed - much faster. - - Usage example: - - uint32_t adler = adler32(0L, NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -Z_EXTERN Z_EXPORT -uint32_t zng_adler32_z(uint32_t adler, const uint8_t *buf, size_t len); -/* - Same as adler32(), but with a size_t length. -*/ - -Z_EXTERN Z_EXPORT -uint32_t zng_adler32_combine(uint32_t adler1, uint32_t adler2, z_off64_t len2); -/* - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note - that the z_off_t type (like off_t) is a signed integer. If len2 is - negative, the result has no meaning or utility. -*/ - -Z_EXTERN Z_EXPORT -uint32_t zng_crc32(uint32_t crc, const uint8_t *buf, uint32_t len); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is NULL, this function returns the required - initial value for the crc. Pre- and post-conditioning (one's complement) is - performed within this function so it shouldn't be done by the application. - - Usage example: - - uint32_t crc = crc32(0L, NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - -Z_EXTERN Z_EXPORT -uint32_t zng_crc32_z(uint32_t crc, const uint8_t *buf, size_t len); -/* - Same as crc32(), but with a size_t length. -*/ - -Z_EXTERN Z_EXPORT -uint32_t zng_crc32_combine(uint32_t crc1, uint32_t crc2, z_off64_t len2); - -/* - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - -Z_EXTERN Z_EXPORT -void zng_crc32_combine_gen(uint32_t op[32], z_off64_t len2); - -/* - Generate the operator op corresponding to length len2, to be used with - crc32_combine_op(). op must have room for 32 uint32_t values. (32 is the - number of bits in the CRC.) -*/ - -Z_EXTERN Z_EXPORT -uint32_t zng_crc32_combine_op(uint32_t crc1, uint32_t crc2, const uint32_t *op); -/* - Give the same result as crc32_combine(), using op in place of len2. op is - is generated from len2 by crc32_combine_gen(). This will be faster than - crc32_combine() if the generated op is used many times. -*/ - - /* various hacks, don't look :) */ - -/* zng_deflateInit and zng_inflateInit are macros to allow checking the zlib version - * and the compiler's view of zng_stream: - */ -Z_EXTERN Z_EXPORT int32_t zng_deflateInit_(zng_stream *strm, int32_t level, const char *version, int32_t stream_size); -Z_EXTERN Z_EXPORT int32_t zng_inflateInit_(zng_stream *strm, const char *version, int32_t stream_size); -Z_EXTERN Z_EXPORT int32_t zng_deflateInit2_(zng_stream *strm, int32_t level, int32_t method, int32_t windowBits, int32_t memLevel, - int32_t strategy, const char *version, int32_t stream_size); -Z_EXTERN Z_EXPORT int32_t zng_inflateInit2_(zng_stream *strm, int32_t windowBits, const char *version, int32_t stream_size); -Z_EXTERN Z_EXPORT int32_t zng_inflateBackInit_(zng_stream *strm, int32_t windowBits, uint8_t *window, - const char *version, int32_t stream_size); - -#define zng_deflateInit(strm, level) zng_deflateInit_((strm), (level), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) -#define zng_inflateInit(strm) zng_inflateInit_((strm), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) -#define zng_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - zng_deflateInit2_((strm), (level), (method), (windowBits), (memLevel), \ - (strategy), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) -#define zng_inflateInit2(strm, windowBits) zng_inflateInit2_((strm), (windowBits), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) -#define zng_inflateBackInit(strm, windowBits, window) \ - zng_inflateBackInit_((strm), (windowBits), (window), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) - -#ifdef WITH_GZFILEOP - -/* gzgetc() macro and its supporting function and exposed data structure. Note - * that the real internal state is much larger than the exposed structure. - * This abbreviated structure exposes just enough for the gzgetc() macro. The - * user should not mess with these exposed elements, since their names or - * behavior could change in the future, perhaps even capriciously. They can - * only be used by the gzgetc() macro. You have been warned. - */ -struct gzFile_s { - unsigned have; - unsigned char *next; - z_off64_t pos; -}; -Z_EXTERN Z_EXPORT int32_t zng_gzgetc_(gzFile file); /* backward compatibility */ -# define zng_gzgetc(g) ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (zng_gzgetc)(g)) - -#endif /* WITH_GZFILEOP */ - - -typedef enum { - Z_DEFLATE_LEVEL = 0, /* compression level, represented as an int */ - Z_DEFLATE_STRATEGY = 1, /* compression strategy, represented as an int */ - Z_DEFLATE_REPRODUCIBLE = 2, - /* - Whether reproducible compression results are required. Represented as an int, where 0 means that it is allowed - to trade reproducibility for e.g. improved performance or compression ratio, and non-0 means that - reproducibility is strictly required. Reproducibility is guaranteed only when using an identical zlib-ng build. - Default is 0. - */ -} zng_deflate_param; - -typedef struct { - zng_deflate_param param; /* parameter ID */ - void *buf; /* parameter value */ - size_t size; /* parameter value size */ - int32_t status; /* result of the last set/get call */ -} zng_deflate_param_value; - -Z_EXTERN Z_EXPORT -int32_t zng_deflateSetParams(zng_stream *strm, zng_deflate_param_value *params, size_t count); -/* - Sets the values of the given zlib-ng deflate stream parameters. All the buffers are copied internally, so the - caller still owns them after this function returns. Returns Z_OK if success. - - If the size of at least one of the buffers is too small to hold the entire value of the corresponding parameter, - or if the same parameter is specified multiple times, Z_BUF_ERROR is returned. The caller may inspect status fields - in order to determine which of the parameters caused this error. No other changes are performed. - - If the stream state is inconsistent or if at least one of the values cannot be updated, Z_STREAM_ERROR is - returned. The caller may inspect status fields in order to determine which of the parameters caused this error. - Parameters, whose status field is equal to Z_OK, have been applied successfully. If all status fields are not equal - to Z_STREAM_ERROR, then the error was caused by a stream state inconsistency. - - If there are no other errors, but at least one parameter is not supported by the current zlib-ng version, - Z_VERSION_ERROR is returned. The caller may inspect status fields in order to determine which of the parameters - caused this error. -*/ - -Z_EXTERN Z_EXPORT -int32_t zng_deflateGetParams(zng_stream *strm, zng_deflate_param_value *params, size_t count); -/* - Copies the values of the given zlib-ng deflate stream parameters into the user-provided buffers. Returns Z_OK if - success, Z_VERSION_ERROR if at least one parameter is not supported by the current zlib-ng version, Z_STREAM_ERROR - if the stream state is inconsistent, and Z_BUF_ERROR if the size of at least one buffer is too small to hold the - entire value of the corresponding parameter. -*/ - -/* undocumented functions */ -Z_EXTERN Z_EXPORT const char * zng_zError (int32_t); -Z_EXTERN Z_EXPORT int32_t zng_inflateSyncPoint (zng_stream *); -Z_EXTERN Z_EXPORT const uint32_t * zng_get_crc_table (void); -Z_EXTERN Z_EXPORT int32_t zng_inflateUndermine (zng_stream *, int32_t); -Z_EXTERN Z_EXPORT int32_t zng_inflateValidate (zng_stream *, int32_t); -Z_EXTERN Z_EXPORT unsigned long zng_inflateCodesUsed (zng_stream *); -Z_EXTERN Z_EXPORT int32_t zng_inflateResetKeep (zng_stream *); -Z_EXTERN Z_EXPORT int32_t zng_deflateResetKeep (zng_stream *); - -#ifdef WITH_GZFILEOP -# if defined(_WIN32) - Z_EXTERN Z_EXPORT gzFile zng_gzopen_w(const wchar_t *path, const char *mode); -# endif -Z_EXTERN Z_EXPORTVA int32_t zng_gzvprintf(gzFile file, const char *format, va_list va); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* ZNGLIB_H_ */ diff --git a/libs/zlibng/zlib-ng.map b/libs/zlibng/zlib-ng.map deleted file mode 100644 index b0046034cf..0000000000 --- a/libs/zlibng/zlib-ng.map +++ /dev/null @@ -1,107 +0,0 @@ -ZLIB_NG_2.0.0 { - global: - zng_adler32; - zng_adler32_c; - zng_adler32_combine; - zng_adler32_z; - zng_compress; - zng_compress2; - zng_compressBound; - zng_crc32; - zng_crc32_combine; - zng_crc32_combine_gen; - zng_crc32_combine_op; - zng_crc32_z; - zng_deflate; - zng_deflateBound; - zng_deflateCopy; - zng_deflateEnd; - zng_deflateGetDictionary; - zng_deflateGetParams; - zng_deflateInit_; - zng_deflateInit2_; - zng_deflateParams; - zng_deflatePending; - zng_deflatePrime; - zng_deflateReset; - zng_deflateResetKeep; - zng_deflateSetDictionary; - zng_deflateSetHeader; - zng_deflateSetParams; - zng_deflateTune; - zng_get_crc_table; - zng_inflate; - zng_inflateBack; - zng_inflateBackEnd; - zng_inflateBackInit_; - zng_inflateCodesUsed; - zng_inflateCopy; - zng_inflateEnd; - zng_inflateGetDictionary; - zng_inflateGetHeader; - zng_inflateInit_; - zng_inflateInit2_; - zng_inflateMark; - zng_inflatePrime; - zng_inflateReset; - zng_inflateReset2; - zng_inflateResetKeep; - zng_inflateSetDictionary; - zng_inflateSync; - zng_inflateSyncPoint; - zng_inflateUndermine; - zng_inflateValidate; - zng_uncompress; - zng_uncompress2; - zng_zError; - zng_zlibCompileFlags; - zng_zlibng_string; - zng_version; - local: - zng_deflate_copyright; - zng_inflate_copyright; - zng_inflate_fast; - zng_inflate_table; - zng_zcalloc; - zng_zcfree; - zng_z_errmsg; - zng_gz_error; - zng_gz_intmax; - _*; -}; - -ZLIB_NG_GZ_2.0.0 { - global: - zng_gzbuffer; - zng_gzclearerr; - zng_gzclose; - zng_gzclose_r; - zng_gzclose_w; - zng_gzdirect; - zng_gzdopen; - zng_gzeof; - zng_gzerror; - zng_gzflush; - zng_gzfread; - zng_gzfwrite; - zng_gzgetc; - zng_gzgetc_; - zng_gzgets; - zng_gzoffset; - zng_gzoffset64; - zng_gzopen; - zng_gzopen64; - zng_gzprintf; - zng_gzputc; - zng_gzputs; - zng_gzread; - zng_gzrewind; - zng_gzseek; - zng_gzseek64; - zng_gzsetparams; - zng_gztell; - zng_gztell64; - zng_gzungetc; - zng_gzvprintf; - zng_gzwrite; -}; diff --git a/libs/zlibng/zlib.3 b/libs/zlibng/zlib.3 deleted file mode 100644 index eddeec0244..0000000000 --- a/libs/zlibng/zlib.3 +++ /dev/null @@ -1,149 +0,0 @@ -.TH ZLIB 3 "15 Jan 2017" -.SH NAME -zlib \- compression/decompression library -.SH SYNOPSIS -[see -.I zlib.h -for full description] -.SH DESCRIPTION -The -.I zlib -library is a general purpose data compression library. -The code is thread safe, assuming that the standard library functions -used are thread safe, such as memory allocation routines. -It provides in-memory compression and decompression functions, -including integrity checks of the uncompressed data. -This version of the library supports only one compression method (deflation) -but other algorithms may be added later -with the same stream interface. -.LP -Compression can be done in a single step if the buffers are large enough -or can be done by repeated calls of the compression function. -In the latter case, -the application must provide more input and/or consume the output -(providing more output space) before each call. -.LP -The library also supports reading and writing files in -.IR gzip (1) -(.gz) format -with an interface similar to that of stdio. -.LP -The library does not install any signal handler. -The decoder checks the consistency of the compressed data, -so the library should never crash even in the case of corrupted input. -.LP -All functions of the compression library are documented in the file -.IR zlib.h . -The distribution source includes examples of use of the library -in the files -.I test/example.c -and -.IR test/minigzip.c, -as well as other examples in the -.IR examples/ -directory. -.LP -Changes to this version are documented in the file -.I ChangeLog -that accompanies the source. -.LP -.I zlib -is built in to many languages and operating systems, including but not limited to -Java, Python, .NET, PHP, Perl, Ruby, Swift, and Go. -.LP -An experimental package to read and write files in the .zip format, -written on top of -.I zlib -by Gilles Vollant (info@winimage.com), -is available at: -.IP -http://www.winimage.com/zLibDll/minizip.html -and also in the -.I contrib/minizip -directory of the main -.I zlib -source distribution. -.SH "SEE ALSO" -The -.I zlib -web site can be found at: -.IP -http://zlib.net/ -.LP -The data format used by the -.I zlib -library is described by RFC -(Request for Comments) 1950 to 1952 in the files: -.IP -http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format) -.br -http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format) -.br -http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format) -.LP -Mark Nelson wrote an article about -.I zlib -for the Jan. 1997 issue of Dr. Dobb's Journal; -a copy of the article is available at: -.IP -http://marknelson.us/1997/01/01/zlib-engine/ -.SH "REPORTING PROBLEMS" -Before reporting a problem, -please check the -.I zlib -web site to verify that you have the latest version of -.IR zlib ; -otherwise, -obtain the latest version and see if the problem still exists. -Please read the -.I zlib -FAQ at: -.IP -http://zlib.net/zlib_faq.html -.LP -before asking for help. -Send questions and/or comments to zlib@gzip.org, -or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). -.SH AUTHORS AND LICENSE -Version 1.2.11 -.LP -Copyright (C) 1995-2016 Jean-loup Gailly and Mark Adler -.LP -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. -.LP -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: -.LP -.nr step 1 1 -.IP \n[step]. 3 -The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software -in a product, an acknowledgment in the product documentation would be -appreciated but is not required. -.IP \n+[step]. -Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -.IP \n+[step]. -This notice may not be removed or altered from any source distribution. -.LP -Jean-loup Gailly Mark Adler -.br -jloup@gzip.org madler@alumni.caltech.edu -.LP -The deflate format used by -.I zlib -was defined by Phil Katz. -The deflate and -.I zlib -specifications were written by L. Peter Deutsch. -Thanks to all the people who reported problems and suggested various -improvements in -.IR zlib ; -who are too numerous to cite here. -.LP -UNIX manual page by R. P. C. Rodgers, -U.S. National Library of Medicine (rodgers@nlm.nih.gov). -.\" end of man page diff --git a/libs/zlibng/zlib.h b/libs/zlibng/zlib.h deleted file mode 100644 index 688fe440e7..0000000000 --- a/libs/zlibng/zlib.h +++ /dev/null @@ -1,1831 +0,0 @@ -#ifndef ZLIB_H_ -#define ZLIB_H_ -/* zlib.h -- interface of the 'zlib-ng' compression library - Forked from and compatible with zlib 1.2.11 - - Copyright (C) 1995-2016 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 - (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). -*/ - -#include -#include -#include "zconf-ng.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIBNG_VERSION "2.0.0-RC2" -#define ZLIBNG_VERNUM 0x2000 -#define ZLIBNG_VER_MAJOR 2 -#define ZLIBNG_VER_MINOR 0 -#define ZLIBNG_VER_REVISION 0 -#define ZLIBNG_VER_SUBREVISION 0 - -#define ZLIB_VERSION "1.2.11.zlib-ng" -#define ZLIB_VERNUM 0x12bf -#define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 11 -#define ZLIB_VER_SUBREVISION 0 - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed data. - This version of the library supports only one compression method (deflation) - but other algorithms will be added later and will have the same stream - interface. - - Compression can be done in a single step if the buffers are large enough, - or can be done by repeated calls of the compression function. In the latter - case, the application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip and raw deflate streams in - memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never crash - even in the case of corrupted input. -*/ - -typedef void *(*alloc_func) (void *opaque, unsigned int items, unsigned int size); -typedef void (*free_func) (void *opaque, void *address); - -struct internal_state; - -typedef struct z_stream_s { - z_const unsigned char *next_in; /* next input byte */ - uint32_t avail_in; /* number of bytes available at next_in */ - unsigned long total_in; /* total number of input bytes read so far */ - - unsigned char *next_out; /* next output byte will go here */ - uint32_t avail_out; /* remaining free space at next_out */ - unsigned long total_out; /* total number of bytes output so far */ - - z_const char *msg; /* last error message, NULL if no error */ - struct internal_state *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - void *opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: binary or text - for deflate, or the decoding state for inflate */ - unsigned long adler; /* Adler-32 or CRC-32 value of the uncompressed data */ - unsigned long reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream *z_streamp; /* Obsolete type, retained for compatibility only */ - -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -typedef struct gz_header_s { - int text; /* true if compressed data believed to be text */ - unsigned long time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - unsigned char *extra; /* pointer to extra field or NULL if none */ - unsigned int extra_len; /* extra field length (valid if extra != NULL) */ - unsigned int extra_max; /* space at extra (only when reading header) */ - unsigned char *name; /* pointer to zero-terminated file name or NULL */ - unsigned int name_max; /* space at name (only when reading header) */ - unsigned char *comment; /* pointer to zero-terminated comment or NULL */ - unsigned int comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used when writing a gzip file) */ -} gz_header; - -typedef gz_header *gz_headerp; - -/* - The application must update next_in and avail_in when avail_in has dropped - to zero. It must update next_out and avail_out when avail_out has dropped - to zero. The application must initialize zalloc, zfree and opaque before - calling the init function. All other fields are set by the compression - library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. In that case, zlib is thread-safe. When zalloc and zfree are - Z_NULL on entry to the initialization function, they are set to internal - routines that use the standard library functions malloc() and free(). - - The fields total_in and total_out can be used for statistics or progress - reports. After compression, total_in holds the total size of the - uncompressed data and may be saved for use by the decompressor (particularly - if the decompressor wants to decompress everything in a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -#define Z_TREES 6 -/* Allowed flush values; see deflate() and inflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ -#define Z_UNKNOWN 2 -/* Possible values of the data_type field for deflate() */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL NULL /* for compatibility with zlib, was for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - - /* basic functions */ - -Z_EXTERN const char * Z_EXPORT zlibVersion(void); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is not - compatible with the zlib.h header file used by the application. This check - is automatically made by deflateInit and inflateInit. - */ - -/* -Z_EXTERN int Z_EXPORT deflateInit (z_stream *strm, int level); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. If - zalloc and zfree are set to NULL, deflateInit updates them to use default - allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at all - (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION - requests a default compromise between speed and compression (currently - equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if level is not a valid compression level, or - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). msg is set to null - if there is no error message. deflateInit does not perform any compression: - this will be done by deflate(). -*/ - - -Z_EXTERN int Z_EXPORT deflate(z_stream *strm, int flush); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Generate more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary. Some output may be provided even if - flush is zero. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating avail_in or avail_out accordingly; avail_out should - never be zero before the call. The application can consume the compressed - output when it wants, for example when the output buffer is full (avail_out - == 0), or after each call of deflate(). If deflate returns Z_OK and with - zero avail_out, it must be called again after making room in the output - buffer because there might be more output pending. See deflatePending(), - which can be used if desired to determine whether or not there is more ouput - in that case. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumulate before producing output, in order to - maximize compression. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In - particular avail_in is zero after the call if enough output space has been - provided before the call.) Flushing may degrade compression for some - compression algorithms and so it should be used only when necessary. This - completes the current deflate block and follows it with an empty stored block - that is three bits plus filler bits to the next byte, followed by four bytes - (00 00 ff ff). - - If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the - output buffer, but the output is not aligned to a byte boundary. All of the - input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. - This completes the current deflate block and follows it with an empty fixed - codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed - codes block. - - If flush is set to Z_BLOCK, a deflate block is completed and emitted, as - for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to - seven bits of the current block are held to be written as the next byte after - the next deflate block is completed. In this case, the decompressor may not - be provided enough bits at this point in order to complete decompression of - the data provided so far to the compressor. It may need to wait for the next - block to be emitted. This is for advanced applications that need to control - the emission of deflate blocks. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there was - enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this - function must be called again with Z_FINISH and more output space (updated - avail_out) but no more input data, until it returns with Z_STREAM_END or an - error. After deflate has returned Z_STREAM_END, the only possible operations - on the stream are deflateReset or deflateEnd. - - Z_FINISH can be used in the first deflate call after deflateInit if all the - compression is to be done in a single step. In order to complete in one - call, avail_out must be at least the value returned by deflateBound (see - below). Then deflate is guaranteed to return Z_STREAM_END. If not enough - output space is provided, deflate will not return Z_STREAM_END, and it must - be called again as described above. - - deflate() sets strm->adler to the Adler-32 checksum of all input read - so far (that is, total_in bytes). If a gzip stream is being generated, then - strm->adler will be the CRC-32 checksum of the input read so far. (See - deflateInit2 below.) - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is - considered binary. This field is only for information purposes and does not - affect the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL) or the state was inadvertently written over - by the application), or Z_BUF_ERROR if no progress is possible (for example - avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and - deflate() can be called again with more input and more output space to - continue compressing. -*/ - - -Z_EXTERN int Z_EXPORT deflateEnd(z_stream *strm); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, msg - may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -Z_EXTERN int Z_EXPORT inflateInit (z_stream *strm); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. In the current version of inflate, the provided input is not - read or consumed. The allocation of a sliding window will be deferred to - the first call of inflate (if the decompression does not complete on the - first call). If zalloc and zfree are set to NULL, inflateInit updates - them to use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression. - Actual decompression will be done by inflate(). So next_in, and avail_in, - next_out, and avail_out are unused and unchanged. The current - implementation of inflateInit() does not process any header information -- - that is deferred until inflate() is called. -*/ - - -Z_EXTERN int Z_EXPORT inflate(z_stream *strm, int flush); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), then next_in and avail_in are updated - accordingly, and processing will resume at this point for the next call of - inflate(). - - - Generate more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there is - no more input data or no more space in the output buffer (see below about - the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. If the - caller of inflate() does not provide both available input and available - output space, it is possible that there will be no progress made. The - application can consume the uncompressed output when it wants, for example - when the output buffer is full (avail_out == 0), or after each call of - inflate(). If inflate returns Z_OK and with zero avail_out, it must be - called again after making room in the output buffer because there might be - more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, - Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() - stop if and when it gets to the next deflate block boundary. When decoding - the zlib or gzip format, this will cause inflate() to return immediately - after the header and before the first block. When doing a raw inflate, - inflate() will go ahead and process the first block, and will return when it - gets to the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - To assist in this, on return inflate() always sets strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 if - inflate() is currently decoding the last block in the deflate stream, plus - 128 if inflate() returned immediately after decoding an end-of-block code or - decoding the complete header up to just before the first byte of the deflate - stream. The end-of-block will not be indicated until all of the uncompressed - data from that block has been written to strm->next_out. The number of - unused bits may in general be greater than seven, except when bit 7 of - data_type is set, in which case the number of unused bits will be less than - eight. data_type is set as noted here every time inflate() returns for all - flush options, and so can be used to determine the amount of currently - consumed input in bits. - - The Z_TREES option behaves as Z_BLOCK does, but it also returns when the - end of each deflate block header is reached, before any actual data in that - block is decoded. This allows the caller to determine the length of the - deflate block header for later use in random access within a deflate block. - 256 is added to the value of strm->data_type when inflate() returns - immediately after reaching the end of the deflate block header. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step (a - single call of inflate), the parameter flush should be set to Z_FINISH. In - this case all pending input is processed and all pending output is flushed; - avail_out must be large enough to hold all of the uncompressed data for the - operation to complete. (The size of the uncompressed data may have been - saved by the compressor for this purpose.) The use of Z_FINISH is not - required to perform an inflation in one step. However it may be used to - inform inflate that a faster approach can be used for the single inflate() - call. Z_FINISH also informs inflate to not maintain a sliding window if the - stream completes, which reduces inflate's memory footprint. If the stream - does not complete, either because not all of the stream is provided or not - enough output space is provided, then a sliding window will be allocated and - inflate() can be called again to continue the operation as if Z_NO_FLUSH had - been used. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the effects of the flush parameter in this implementation are - on the return value of inflate() as noted below, when inflate() returns early - when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of - memory for a sliding window when Z_FINISH is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the Adler-32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the Adler-32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed Adler-32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() can decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically, if requested when - initializing with inflateInit2(). Any information contained in the gzip - header is not retained unless inflateGetHeader() is used. When processing - gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output - produced so far. The CRC-32 is checked against the gzip trailer, as is the - uncompressed length, modulo 2^32. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value, in which case strm->msg points to a string with a more specific - error), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was NULL, or the state was inadvertently written over - by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR - if no progress is possible or if there was not enough room in the output - buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may - then call inflateSync() to look for a good compression block if a partial - recovery of the data is to be attempted. -*/ - - -Z_EXTERN int Z_EXPORT inflateEnd(z_stream *strm); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state - was inconsistent. -*/ - - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -Z_EXTERN int Z_EXPORT deflateInit2 (z_stream *strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy); - - This is another version of deflateInit with more compression options. The - fields zalloc, zfree and opaque must be initialized before by the caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - For the current implementation of deflate(), a windowBits value of 8 (a - window size of 256 bytes) is not supported. As a result, a request for 8 - will result in 9 (a 512-byte window). In that case, providing 8 to - inflateInit2() will result in an error when the zlib header with 9 is - checked against the initialization of inflate(). The remedy is to not use 8 - with deflateInit2() with this initialization, or at least in that case use 9 - with inflateInit2(). - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute a check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to the appropriate value, - if the operating system was determined at compile time. If a gzip stream is - being written, strm->adler is a CRC-32 instead of an Adler-32. - - For raw deflate or gzip encoding, a request for a 256-byte window is - rejected as invalid, since only the zlib header provides a means of - transmitting the window size to the decompressor. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but is - slow and reduces compression ratio; memLevel=9 uses maximum memory for - optimal speed. The default value is 8. See zconf.h for total memory usage - as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as - fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The - strategy parameter only affects the compression ratio but not the - correctness of the compressed output even if it is not set appropriately. - Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler - decoder for special applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid - method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is - incompatible with the version assumed by the caller (ZLIB_VERSION). msg is - set to null if there is no error message. deflateInit2 does not perform any - compression: this will be done by deflate(). -*/ - -Z_EXTERN int Z_EXPORT deflateSetDictionary(z_stream *strm, - const unsigned char *dictionary, - unsigned int dictLength); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. When using the zlib format, this - function must be called immediately after deflateInit, deflateInit2 or - deflateReset, and before any call of deflate. When doing raw deflate, this - function must be called either before any call of deflate, or immediately - after the completion of a deflate block, i.e. after all input has been - consumed and all output has been delivered when using any of the flush - options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The - compressor and decompressor must use exactly the same dictionary (see - inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size - provided in deflateInit or deflateInit2. Thus the strings most likely to be - useful should be put at the end of the dictionary, not at the front. In - addition, the current implementation of deflate will use at most the window - size minus 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the Adler-32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The Adler-32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - Adler-32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being NULL) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if not at a block boundary for raw deflate). deflateSetDictionary does - not perform any compression: this will be done by deflate(). -*/ - -Z_EXTERN int Z_EXPORT deflateGetDictionary (z_stream *strm, unsigned char *dictionary, unsigned int *dictLength); -/* - Returns the sliding dictionary being maintained by deflate. dictLength is - set to the number of bytes in the dictionary, and that many bytes are copied - to dictionary. dictionary must have enough space, where 32768 bytes is - always enough. If deflateGetDictionary() is called with dictionary equal to - Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. - - deflateGetDictionary() may return a length less than the window size, even - when more than the window size in input has been provided. It may return up - to 258 bytes less in that case, due to how zlib's implementation of deflate - manages the sliding window and lookahead for matches, where matches can be - up to 258 bytes long. If the application needs the last window-size bytes of - input, then that would need to be saved by the application outside of zlib. - - deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the - stream state is inconsistent. -*/ - -Z_EXTERN int Z_EXPORT deflateCopy(z_stream *dest, z_stream *source); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and can - consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -Z_EXTERN int Z_EXPORT deflateReset(z_stream *strm); -/* - This function is equivalent to deflateEnd followed by deflateInit, but - does not free and reallocate the internal compression state. The stream - will leave the compression level and any other attributes that may have been - set unchanged. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -Z_EXTERN int Z_EXPORT deflateParams(z_stream *strm, int level, int strategy); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2(). This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different strategy. - If the compression approach (which is a function of the level) or the - strategy is changed, and if there have been any deflate() calls since the - state was initialized or reset, then the input available so far is - compressed with the old level and strategy using deflate(strm, Z_BLOCK). - There are three approaches for the compression levels 0, 1..3, and 4..9 - respectively. The new level and strategy will take effect at the next call - of deflate(). - - If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does - not have enough output space to complete, then the parameter change will not - take effect. In this case, deflateParams() can be called again with the - same parameters and more output space to try again. - - In order to assure a change in the parameters on the first try, the - deflate stream should be flushed using deflate() with Z_BLOCK or other flush - request until strm.avail_out is not zero, before calling deflateParams(). - Then no more input data should be provided before the deflateParams() call. - If this is done, the old level and strategy will be applied to the data - compressed before deflateParams(), and the new level and strategy will be - applied to the the data compressed after deflateParams(). - - deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream - state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if - there was not enough output space to complete the compression of the - available input data before a change in the strategy or approach. Note that - in the case of a Z_BUF_ERROR, the parameters are not changed. A return - value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be - retried with more output space. -*/ - -Z_EXTERN int Z_EXPORT deflateTune(z_stream *strm, int good_length, int max_lazy, int nice_length, int max_chain); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -Z_EXTERN unsigned long Z_EXPORT deflateBound(z_stream *strm, unsigned long sourceLen); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() or - deflateInit2(), and after deflateSetHeader(), if used. This would be used - to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). If that first deflate() call is provided the - sourceLen input bytes, an output buffer allocated to the size returned by - deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed - to return Z_STREAM_END. Note that it is possible for the compressed size to - be larger than the value returned by deflateBound() if flush options other - than Z_FINISH or Z_NO_FLUSH are used. -*/ - -Z_EXTERN int Z_EXPORT deflatePending(z_stream *strm, uint32_t *pending, int *bits); -/* - deflatePending() returns the number of bytes and bits of output that have - been generated, but not yet provided in the available output. The bytes not - provided would be due to the available output space having being consumed. - The number of bits of output not provided are between 0 and 7, where they - await more bits to join them in order to fill out a full byte. If pending - or bits are NULL, then those values are not set. - - deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. - */ - -Z_EXTERN int Z_EXPORT deflatePrime(z_stream *strm, int bits, int value); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the bits - leftover from a previous deflate stream when appending to it. As such, this - function can only be used for raw deflate, and must be used before the first - deflate() call after a deflateInit2() or deflateReset(). bits must be less - than or equal to 16, and that many of the least significant bits of value - will be inserted in the output. - - deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough - room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the - source stream state was inconsistent. -*/ - -Z_EXTERN int Z_EXPORT deflateSetHeader(z_stream *strm, gz_headerp head); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not NULL, name and comment are terminated with - a zero byte, and that if extra is not NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -Z_EXTERN int Z_EXPORT inflateInit2(z_stream *strm, int windowBits); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be zero to request that inflate use the window size in - the zlib header of the compressed stream. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an Adler-32 or a CRC-32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see - below), inflate() will *not* automatically decode concatenated gzip members. - inflate() will return Z_STREAM_END at the end of the gzip member. The state - would need to be reset to continue decoding a subsequent gzip member. This - *must* be done if there is more data after a gzip member, in order for the - decompression to be compliant with the gzip standard (RFC 1952). - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit2 does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit2() does not process any header information -- that is - deferred until inflate() is called. -*/ - -Z_EXTERN int Z_EXPORT inflateSetDictionary(z_stream *strm, const unsigned char *dictionary, unsigned int dictLength); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the Adler-32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called at any - time to set the dictionary. If the provided dictionary is smaller than the - window and there is already data in the window, then the provided dictionary - will amend what's there. The application must insure that the dictionary - that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being NULL) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect Adler-32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -Z_EXTERN int Z_EXPORT inflateGetDictionary(z_stream *strm, unsigned char *dictionary, unsigned int *dictLength); -/* - Returns the sliding dictionary being maintained by inflate. dictLength is - set to the number of bytes in the dictionary, and that many bytes are copied - to dictionary. dictionary must have enough space, where 32768 bytes is - always enough. If inflateGetDictionary() is called with dictionary equal to - NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is NULL, then it is not set. - - inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the - stream state is inconsistent. -*/ - -Z_EXTERN int Z_EXPORT inflateSync(z_stream *strm); -/* - Skips invalid compressed data until a possible full flush point (see above - for the description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync searches for a 00 00 FF FF pattern in the compressed data. - All full flush points have this pattern, but not all occurrences of this - pattern are full flush points. - - inflateSync returns Z_OK if a possible full flush point has been found, - Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point - has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. - In the success case, the application may save the current current value of - total_in which indicates where valid compressed data was found. In the - error case, the application may repeatedly call inflateSync, providing more - input each time, until success or end of the input data. -*/ - -Z_EXTERN int Z_EXPORT inflateCopy(z_stream *dest, z_stream *source); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -Z_EXTERN int Z_EXPORT inflateReset(z_stream *strm); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate the internal decompression state. The - stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -Z_EXTERN int Z_EXPORT inflateReset2(z_stream *strm, int windowBits); -/* - This function is the same as inflateReset, but it also permits changing - the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. If the window size is changed, then the - memory allocated for the window is freed, and the window will be reallocated - by inflate() if needed. - - inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL), or if - the windowBits parameter is invalid. -*/ - -Z_EXTERN int Z_EXPORT inflatePrime(z_stream *strm, int bits, int value); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - If bits is negative, then the input stream bit buffer is emptied. Then - inflatePrime() can be called again to put bits in the buffer. This is used - to clear out bits leftover after feeding inflate a block description prior - to feeding inflate codes. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -Z_EXTERN long Z_EXPORT inflateMark(z_stream *strm); -/* - This function returns two values, one in the lower 16 bits of the return - value, and the other in the remaining upper bits, obtained by shifting the - return value down 16 bits. If the upper value is -1 and the lower value is - zero, then inflate() is currently decoding information outside of a block. - If the upper value is -1 and the lower value is non-zero, then inflate is in - the middle of a stored block, with the lower value equaling the number of - bytes from the input remaining to copy. If the upper value is not -1, then - it is the number of bits back from the current bit position in the input of - the code (literal or length/distance pair) currently being processed. In - that case the lower value is the number of bytes already emitted for that - code. - - A code is being processed if inflate is waiting for more input to complete - decoding of the code, or if it has completed decoding but is waiting for - more output space to write the literal or match data. - - inflateMark() is used to mark locations in the input data for random - access, which may be at bit positions, and to note those cases where the - output of a code may span boundaries of random access blocks. The current - location in the input stream can be determined from avail_in and data_type - as noted in the description for the Z_BLOCK flush parameter for inflate. - - inflateMark returns the value noted above, or -65536 if the provided - source stream state was inconsistent. -*/ - -Z_EXTERN int Z_EXPORT inflateGetHeader(z_stream *strm, gz_headerp head); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be - used to force inflate() to return immediately after header processing is - complete and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When any - of extra, name, or comment are not NULL and the respective field is not - present in the header, then that field is set to NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -Z_EXTERN int Z_EXPORT inflateBackInit (z_stream *strm, int windowBits, unsigned char *window); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the parameters are invalid, Z_MEM_ERROR if the internal state could not be - allocated, or Z_VERSION_ERROR if the version of the library does not match - the version of the header file. -*/ - -typedef uint32_t (*in_func) (void *, z_const unsigned char * *); -typedef int (*out_func) (void *, unsigned char *, uint32_t); - -Z_EXTERN int Z_EXPORT inflateBack(z_stream *strm, in_func in, void *in_desc, out_func out, void *out_desc); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is potentially more efficient than - inflate() for file i/o applications, in that it avoids copying between the - output and the sliding window by simply making the window itself the output - buffer. inflate() can be faster on modern CPUs when used with large - buffers. inflateBack() trusts the application to not change the output - buffer passed by the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free the - allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the default - behavior of inflate(), which expects a zlib header and trailer around the - deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero -- buf is ignored in that - case -- and inflateBack() will return a buffer error. inflateBack() will - call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. - out() should return zero on success, or non-zero on failure. If out() - returns non-zero, inflateBack() will return with an error. Neither in() nor - out() are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is NULL, then in() will be called - immediately for input. If strm->next_in is not NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format error - in the deflate stream (in which case strm->msg is set to indicate the nature - of the error), or Z_STREAM_ERROR if the stream was not properly initialized. - In the case of Z_BUF_ERROR, an input or output error can be distinguished - using strm->next_in which will be NULL only if in() returned an error. If - strm->next_in is not NULL, then the Z_BUF_ERROR was due to out() returning - non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() - cannot return Z_OK. -*/ - -Z_EXTERN int Z_EXPORT inflateBackEnd(z_stream *strm); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -Z_EXTERN unsigned long Z_EXPORT zlibCompileFlags(void); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of unsigned int - 3.2: size of unsigned long - 5.4: size of void * (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: ZLIB_DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed (not supported by zlib-ng) - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - - - /* utility functions */ - -/* - The following utility functions are implemented on top of the basic - stream-oriented functions. To simplify the interface, some default options - are assumed (compression level and memory usage, standard memory allocation - functions). The source code of these utility functions can be modified if - you need special options. -*/ - -Z_EXTERN int Z_EXPORT compress(unsigned char *dest, unsigned long *destLen, const unsigned char *source, unsigned long sourceLen); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed data. compress() is equivalent to compress2() with a level - parameter of Z_DEFAULT_COMPRESSION. - - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -Z_EXTERN int Z_EXPORT compress2(unsigned char *dest, unsigned long *destLen, const unsigned char *source, - unsigned long sourceLen, int level); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed data. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -Z_EXTERN unsigned long Z_EXPORT compressBound(unsigned long sourceLen); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before a - compress() or compress2() call to allocate the destination buffer. -*/ - -Z_EXTERN int Z_EXPORT uncompress(unsigned char *dest, unsigned long *destLen, const unsigned char *source, unsigned long sourceLen); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be large enough to hold the entire - uncompressed data. (The size of the uncompressed data must have been saved - previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed data. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In - the case where there is not enough room, uncompress() will fill the output - buffer with the uncompressed data up to that point. -*/ - - -Z_EXTERN int Z_EXPORT uncompress2 (unsigned char *dest, unsigned long *destLen, - const unsigned char *source, unsigned long *sourceLen); -/* - Same as uncompress, except that sourceLen is a pointer, where the - length of the source is *sourceLen. On return, *sourceLen is the number of - source bytes consumed. -*/ - - - /* gzip file access functions */ - -/* - This library supports reading and writing files in gzip (.gz) format with - an interface similar to that of stdio, using the functions that start with - "gz". The gzip format is different from the zlib format. gzip is a gzip - wrapper, documented in RFC 1952, wrapped around a deflate stream. -*/ - -typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ - -/* -Z_EXTERN gzFile Z_EXPORT gzopen(const char *path, const char *mode); - - Opens a gzip (.gz) file for reading or writing. The mode parameter is as - in fopen ("rb" or "wb") but can also include a compression level ("wb9") or - a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only - compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' - for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) 'T' will - request transparent writing or appending with no compression and not using - the gzip format. - - "a" can be used instead of "w" to request that the gzip stream that will - be written be appended to the file. "+" will result in an error, since - reading and writing to the same gzip file is not supported. The addition of - "x" when writing will create the file exclusively, which fails if the file - already exists. On systems that support it, the addition of "e" when - reading or writing will set the flag to close the file on an execve() call. - - These functions, as well as gzip, will read and decode a sequence of gzip - streams in a file. The append function of gzopen() can be used to create - such a file. (Also see gzflush() for another way to do this.) When - appending, gzopen does not test whether the file begins with a gzip stream, - nor does it look for the end of the gzip streams to begin appending. gzopen - will simply append a gzip stream to the existing file. - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. When - reading, this will be detected automatically by looking for the magic two- - byte gzip header. - - gzopen returns NULL if the file could not be opened, if there was - insufficient memory to allocate the gzFile state, or if an invalid mode was - specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). - errno can be checked to determine if the reason gzopen failed was that the - file could not be opened. -*/ - -Z_EXTERN gzFile Z_EXPORT gzdopen(int fd, const char *mode); -/* - gzdopen associates a gzFile with the file descriptor fd. File descriptors - are obtained from calls like open, dup, creat, pipe or fileno (if the file - has been previously opened with fopen). The mode parameter is as in gzopen. - - The next call of gzclose on the returned gzFile will also close the file - descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor - fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, - mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. If you are using fileno() to get the - file descriptor from a FILE *, then you will have to use dup() to avoid - double-close()ing the file descriptor. Both gzclose() and fclose() will - close the associated file descriptor, so they need to have different file - descriptors. - - gzdopen returns NULL if there was insufficient memory to allocate the - gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not - provided, or '+' was provided), or if fd is -1. The file descriptor is not - used until the next gz* read, write, seek, or close operation, so gzdopen - will not detect if fd is invalid (unless fd is -1). -*/ - -Z_EXTERN int Z_EXPORT gzbuffer(gzFile file, unsigned size); -/* - Set the internal buffer size used by this library's functions. The - default buffer size is 8192 bytes. This function must be called after - gzopen() or gzdopen(), and before any other calls that read or write the - file. The buffer memory allocation is always deferred to the first read or - write. Three times that size in buffer space is allocated. A larger buffer - size of, for example, 64K or 128K bytes will noticeably increase the speed - of decompression (reading). - - The new buffer size also affects the maximum length for gzprintf(). - - gzbuffer() returns 0 on success, or -1 on failure, such as being called - too late. -*/ - -Z_EXTERN int Z_EXPORT gzsetparams(gzFile file, int level, int strategy); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. Previously provided - data is flushed before the parameter change. - - gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not - opened for writing, Z_ERRNO if there is an error writing the flushed data, - or Z_MEM_ERROR if there is a memory allocation error. -*/ - -Z_EXTERN int Z_EXPORT gzread(gzFile file, void *buf, unsigned len); -/* - Reads the given number of uncompressed bytes from the compressed file. If - the input file is not in gzip format, gzread copies the given number of - bytes into the buffer directly from the file. - - After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream. Any number of gzip streams may be - concatenated in the input file, and will all be decompressed by gzread(). - If something other than a gzip stream is encountered after a gzip stream, - that remaining trailing garbage is ignored (and no error is returned). - - gzread can be used to read a gzip file that is being concurrently written. - Upon reaching the end of the input, gzread will return with the available - data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then - gzclearerr can be used to clear the end of file indicator in order to permit - gzread to be tried again. Z_OK indicates that a gzip stream was completed - on the last gzread. Z_BUF_ERROR indicates that the input file ended in the - middle of a gzip stream. Note that gzread does not return -1 in the event - of an incomplete gzip stream. This error is deferred until gzclose(), which - will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip - stream. Alternatively, gzerror can be used before gzclose to detect this - case. - - gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. If len is too large to fit in an int, - then nothing is read, -1 is returned, and the error state is set to - Z_STREAM_ERROR. -*/ - -Z_EXTERN size_t Z_EXPORT gzfread (void *buf, size_t size, size_t nitems, gzFile file); -/* - Read up to nitems items of size size from file to buf, otherwise operating - as gzread() does. This duplicates the interface of stdio's fread(), with - size_t request and return types. - - gzfread() returns the number of full items read of size size, or zero if - the end of the file was reached and a full item could not be read, or if - there was an error. gzerror() must be consulted if zero is returned in - order to determine if there was an error. If the multiplication of size and - nitems overflows, i.e. the product does not fit in a size_t, then nothing - is read, zero is returned, and the error state is set to Z_STREAM_ERROR. - - In the event that the end of file is reached and only a partial item is - available at the end, i.e. the remaining uncompressed data length is not a - multiple of size, then the final partial item is nevertheless read into buf - and the end-of-file flag is set. The length of the partial item read is not - provided, but could be inferred from the result of gztell(). This behavior - is the same as the behavior of fread() implementations in common libraries, - but it prevents the direct use of gzfread() to read a concurrently written - file, reseting and retrying on end-of-file, when size is not 1. -*/ - -Z_EXTERN int Z_EXPORT gzwrite(gzFile file, void const *buf, unsigned len); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes written or 0 in case of - error. -*/ - -Z_EXTERN size_t Z_EXPORT gzfwrite(void const *buf, size_t size, size_t nitems, gzFile file); -/* - gzfwrite() writes nitems items of size size from buf to file, duplicating - the interface of stdio's fwrite(), with size_t request and return types. - - gzfwrite() returns the number of full items written of size size, or zero - if there was an error. If the multiplication of size and nitems overflows, - i.e. the product does not fit in a size_t, then nothing is written, zero - is returned, and the error state is set to Z_STREAM_ERROR. -*/ - -Z_EXTERN int Z_EXPORTVA gzprintf(gzFile file, const char *format, ...); -/* - Converts, formats, and writes the arguments to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or a negative zlib error code in case - of error. The number of uncompressed bytes written is limited to 8191, or - one less than the buffer size given to gzbuffer(). The caller should assure - that this limit is not exceeded. If it is exceeded, then gzprintf() will - return an error (0) with nothing written. In this case, there may also be a - buffer overflow with unpredictable consequences, which is possible only if - zlib was compiled with the insecure functions sprintf() or vsprintf() - because the secure snprintf() or vsnprintf() functions were not available. - This can be determined using zlibCompileFlags(). -*/ - -Z_EXTERN int Z_EXPORT gzputs(gzFile file, const char *s); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - - gzputs returns the number of characters written, or -1 in case of error. -*/ - -Z_EXTERN char * Z_EXPORT gzgets(gzFile file, char *buf, int len); -/* - Reads bytes from the compressed file until len-1 characters are read, or a - newline character is read and transferred to buf, or an end-of-file - condition is encountered. If any characters are read or if len == 1, the - string is terminated with a null character. If no characters are read due - to an end-of-file or len < 1, then the buffer is left untouched. - - gzgets returns buf which is a null-terminated string, or it returns NULL - for end-of-file or in case of error. If there was an error, the contents at - buf are indeterminate. -*/ - -Z_EXTERN int Z_EXPORT gzputc(gzFile file, int c); -/* - Writes c, converted to an unsigned char, into the compressed file. gzputc - returns the value that was written, or -1 in case of error. -*/ - -Z_EXTERN int Z_EXPORT gzgetc(gzFile file); -/* - Reads one byte from the compressed file. gzgetc returns this byte or -1 - in case of end of file or error. This is implemented as a macro for speed. - As such, it does not do all of the checking the other functions do. I.e. - it does not check to see if file is NULL, nor whether the structure file - points to has been clobbered or not. -*/ - -Z_EXTERN int Z_EXPORT gzungetc(int c, gzFile file); -/* - Push one character back onto the stream to be read as the first character - on the next read. At least one character of push-back is allowed. - gzungetc() returns the character pushed, or -1 on failure. gzungetc() will - fail if c is -1, and may fail if a character has been pushed but not read - yet. If gzungetc is used immediately after gzopen or gzdopen, at least the - output buffer size of pushed characters is allowed. (See gzbuffer above.) - The pushed character will be discarded if the stream is repositioned with - gzseek() or gzrewind(). -*/ - -Z_EXTERN int Z_EXPORT gzflush(gzFile file, int flush); -/* - Flushes all pending output into the compressed file. The parameter flush - is as in the deflate() function. The return value is the zlib error number - (see function gzerror below). gzflush is only permitted when writing. - - If the flush parameter is Z_FINISH, the remaining data is written and the - gzip stream is completed in the output. If gzwrite() is called again, a new - gzip stream will be started in the output. gzread() is able to read such - concatenated gzip streams. - - gzflush should be called only when strictly necessary because it will - degrade compression if called too often. -*/ - -/* -Z_EXTERN z_off_t Z_EXPORT gzseek (gzFile file, z_off_t offset, int whence); - - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -Z_EXTERN int Z_EXPORT gzrewind(gzFile file); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -/* -Z_EXTERN z_off_t Z_EXPORT gztell(gzFile file); - - Returns the starting position for the next gzread or gzwrite on the given - compressed file. This position represents a number of bytes in the - uncompressed data stream, and is zero when starting, even if appending or - reading a gzip stream from the middle of a file using gzdopen(). - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -/* -Z_EXTERN z_off_t Z_EXPORT gzoffset(gzFile file); - - Returns the current offset in the file being read or written. This offset - includes the count of bytes that precede the gzip stream, for example when - appending or when using gzdopen() for reading. When reading, the offset - does not include as yet unused buffered input. This information can be used - for a progress indicator. On error, gzoffset() returns -1. -*/ - -Z_EXTERN int Z_EXPORT gzeof(gzFile file); -/* - Returns true (1) if the end-of-file indicator has been set while reading, - false (0) otherwise. Note that the end-of-file indicator is set only if the - read tried to go past the end of the input, but came up short. Therefore, - just like feof(), gzeof() may return false even if there is no more data to - read, in the event that the last read request was for the exact number of - bytes remaining in the input file. This will happen if the input file size - is an exact multiple of the buffer size. - - If gzeof() returns true, then the read functions will return no more data, - unless the end-of-file indicator is reset by gzclearerr() and the input file - has grown since the previous end of file was detected. -*/ - -Z_EXTERN int Z_EXPORT gzdirect(gzFile file); -/* - Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. - - If the input file is empty, gzdirect() will return true, since the input - does not contain a gzip stream. - - If gzdirect() is used immediately after gzopen() or gzdopen() it will - cause buffers to be allocated to allow reading the file to determine if it - is a gzip file. Therefore if gzbuffer() is used, it should be called before - gzdirect(). - - When writing, gzdirect() returns true (1) if transparent writing was - requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: - gzdirect() is not needed when writing. Transparent writing must be - explicitly requested, so the application already knows the answer. When - linking statically, using gzdirect() will include all of the zlib code for - gzip file reading and decompression, which may not be desired.) -*/ - -Z_EXTERN int Z_EXPORT gzclose(gzFile file); -/* - Flushes all pending output if necessary, closes the compressed file and - deallocates the (de)compression state. Note that once file is closed, you - cannot call gzerror with file, since its structures have been deallocated. - gzclose must not be called more than once on the same file, just as free - must not be called more than once on the same allocation. - - gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the - last read ended in the middle of a gzip stream, or Z_OK on success. -*/ - -Z_EXTERN int Z_EXPORT gzclose_r(gzFile file); -Z_EXTERN int Z_EXPORT gzclose_w(gzFile file); -/* - Same as gzclose(), but gzclose_r() is only for use when reading, and - gzclose_w() is only for use when writing or appending. The advantage to - using these instead of gzclose() is that they avoid linking in zlib - compression or decompression code that is not used when only reading or only - writing respectively. If gzclose() is used, then both compression and - decompression code will be included the application when linking to a static - zlib library. -*/ - -Z_EXTERN const char * Z_EXPORT gzerror(gzFile file, int *errnum); -/* - Returns the error message for the last error which occurred on the given - compressed file. errnum is set to zlib error number. If an error occurred - in the file system and not in the compression library, errnum is set to - Z_ERRNO and the application may consult errno to get the exact error code. - - The application must not modify the returned string. Future calls to - this function may invalidate the previously returned string. If file is - closed, then the string previously returned by gzerror will no longer be - available. - - gzerror() should be used to distinguish errors from end-of-file for those - functions above that do not distinguish those cases in their return values. -*/ - -Z_EXTERN void Z_EXPORT gzclearerr(gzFile file); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the compression - library. -*/ - -Z_EXTERN unsigned long Z_EXPORT adler32(unsigned long adler, const unsigned char *buf, unsigned int len); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns the - required initial value for the checksum. - - An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed - much faster. - - Usage example: - - uint32_t adler = adler32(0L, NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -Z_EXTERN unsigned long Z_EXPORT adler32_z(unsigned long adler, const unsigned char *buf, size_t len); -/* - Same as adler32(), but with a size_t length. -*/ - -/* -Z_EXTERN unsigned long Z_EXPORT adler32_combine(unsigned long adler1, unsigned long adler2, z_off_t len2); - - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note - that the z_off_t type (like off_t) is a signed integer. If len2 is - negative, the result has no meaning or utility. -*/ - -Z_EXTERN unsigned long Z_EXPORT crc32(unsigned long crc, const unsigned char *buf, unsigned int len); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is NULL, this function returns the required - initial value for the crc. Pre- and post-conditioning (one's complement) is - performed within this function so it shouldn't be done by the application. - - Usage example: - - uint32_t crc = crc32(0L, NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - -Z_EXTERN unsigned long Z_EXPORT crc32_z(unsigned long crc, const unsigned char *buf, size_t len); -/* - Same as crc32(), but with a size_t length. -*/ - -/* -Z_EXTERN unsigned long Z_EXPORT crc32_combine(unsigned long crc1, unsigned long crc2, z_off64_t len2); - - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - -/* -Z_EXTERN void Z_EXPORT crc32_combine_gen(uint32_t op[32], z_off_t len2); - - Generate the operator op corresponding to length len2, to be used with - crc32_combine_op(). op must have room for 32 z_crc_t values. (32 is the - number of bits in the CRC.) -*/ - -Z_EXTERN uint32_t Z_EXPORT crc32_combine_op(uint32_t crc1, uint32_t crc2, - const uint32_t *op); -/* - Give the same result as crc32_combine(), using op in place of len2. op is - is generated from len2 by crc32_combine_gen(). This will be faster than - crc32_combine() if the generated op is used many times. -*/ - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -Z_EXTERN int Z_EXPORT deflateInit_(z_stream *strm, int level, const char *version, int stream_size); -Z_EXTERN int Z_EXPORT inflateInit_(z_stream *strm, const char *version, int stream_size); -Z_EXTERN int Z_EXPORT deflateInit2_(z_stream *strm, int level, int method, int windowBits, int memLevel, - int strategy, const char *version, int stream_size); -Z_EXTERN int Z_EXPORT inflateInit2_(z_stream *strm, int windowBits, const char *version, int stream_size); -Z_EXTERN int Z_EXPORT inflateBackInit_(z_stream *strm, int windowBits, unsigned char *window, - const char *version, int stream_size); -#define deflateInit(strm, level) deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit(strm) inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm), (level), (method), (windowBits), (memLevel), \ - (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit2(strm, windowBits) inflateInit2_((strm), (windowBits), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), ZLIB_VERSION, (int)sizeof(z_stream)) - - -/* gzgetc() macro and its supporting function and exposed data structure. Note - * that the real internal state is much larger than the exposed structure. - * This abbreviated structure exposes just enough for the gzgetc() macro. The - * user should not mess with these exposed elements, since their names or - * behavior could change in the future, perhaps even capriciously. They can - * only be used by the gzgetc() macro. You have been warned. - */ -struct gzFile_s { - unsigned have; - unsigned char *next; - z_off64_t pos; -}; -Z_EXTERN int Z_EXPORT gzgetc_(gzFile file); /* backward compatibility */ -# define gzgetc(g) ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) - -/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or - * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if - * both are true, the application gets the *64 functions, and the regular - * functions are changed to 64 bits) -- in case these are set on systems - * without large file support, _LFS64_LARGEFILE must also be true - */ -#ifdef Z_LARGE64 - Z_EXTERN gzFile Z_EXPORT gzopen64(const char *, const char *); - Z_EXTERN z_off64_t Z_EXPORT gzseek64(gzFile, z_off64_t, int); - Z_EXTERN z_off64_t Z_EXPORT gztell64(gzFile); - Z_EXTERN z_off64_t Z_EXPORT gzoffset64(gzFile); - Z_EXTERN unsigned long Z_EXPORT adler32_combine64(unsigned long, unsigned long, z_off64_t); - Z_EXTERN unsigned long Z_EXPORT crc32_combine64(unsigned long, unsigned long, z_off64_t); - Z_EXTERN void Z_EXPORT crc32_combine_gen64(uint32_t *op, z_off64_t); -#endif - -#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# define crc32_combine_gen crc32_combine_gen64 -# ifndef Z_LARGE64 - Z_EXTERN gzFile Z_EXPORT gzopen64(const char *, const char *); - Z_EXTERN z_off_t Z_EXPORT gzseek64(gzFile, z_off_t, int); - Z_EXTERN z_off_t Z_EXPORT gztell64(gzFile); - Z_EXTERN z_off_t Z_EXPORT gzoffset64(gzFile); - Z_EXTERN unsigned long Z_EXPORT adler32_combine64(unsigned long, unsigned long, z_off_t); - Z_EXTERN unsigned long Z_EXPORT crc32_combine64(unsigned long, unsigned long, z_off_t); - Z_EXTERN void Z_EXPORT crc32_combine_gen64(uint32_t *op, z_off64_t); -# endif -#else - Z_EXTERN gzFile Z_EXPORT gzopen(const char *, const char *); - Z_EXTERN z_off_t Z_EXPORT gzseek(gzFile, z_off_t, int); - Z_EXTERN z_off_t Z_EXPORT gztell(gzFile); - Z_EXTERN z_off_t Z_EXPORT gzoffset(gzFile); - Z_EXTERN unsigned long Z_EXPORT adler32_combine(unsigned long, unsigned long, z_off_t); - Z_EXTERN unsigned long Z_EXPORT crc32_combine(unsigned long, unsigned long, z_off_t); - Z_EXTERN void Z_EXPORT crc32_combine_gen(uint32_t *op, z_off_t); -#endif - -/* undocumented functions */ -Z_EXTERN const char * Z_EXPORT zError (int); -Z_EXTERN int Z_EXPORT inflateSyncPoint (z_stream *); -Z_EXTERN const uint32_t * Z_EXPORT get_crc_table (void); -Z_EXTERN int Z_EXPORT inflateUndermine (z_stream *, int); -Z_EXTERN int Z_EXPORT inflateValidate (z_stream *, int); -Z_EXTERN unsigned long Z_EXPORT inflateCodesUsed (z_stream *); -Z_EXTERN int Z_EXPORT inflateResetKeep (z_stream *); -Z_EXTERN int Z_EXPORT deflateResetKeep (z_stream *); - -#if defined(_WIN32) - Z_EXTERN gzFile Z_EXPORT gzopen_w(const wchar_t *path, const char *mode); -#endif -Z_EXTERN int Z_EXPORTVA gzvprintf(gzFile file, const char *format, va_list va); - -#ifdef __cplusplus -} -#endif - -#endif /* ZLIB_H_ */ diff --git a/libs/zlibng/zlib.map b/libs/zlibng/zlib.map deleted file mode 100644 index f608f2bd51..0000000000 --- a/libs/zlibng/zlib.map +++ /dev/null @@ -1,100 +0,0 @@ -ZLIB_1.2.0 { - global: - compressBound; - deflateBound; - inflateBack; - inflateBackEnd; - inflateBackInit_; - inflateCopy; - local: - deflate_copyright; - inflate_copyright; - inflate_fast; - inflate_table; - zcalloc; - zcfree; - z_errmsg; - gz_error; - gz_intmax; - _*; -}; - -ZLIB_1.2.0.2 { - gzclearerr; - gzungetc; - zlibCompileFlags; -} ZLIB_1.2.0; - -ZLIB_1.2.0.8 { - deflatePrime; -} ZLIB_1.2.0.2; - -ZLIB_1.2.2 { - adler32_combine; - crc32_combine; - deflateSetHeader; - inflateGetHeader; -} ZLIB_1.2.0.8; - -ZLIB_1.2.2.3 { - deflateTune; - gzdirect; -} ZLIB_1.2.2; - -ZLIB_1.2.2.4 { - inflatePrime; -} ZLIB_1.2.2.3; - -ZLIB_1.2.3.3 { - adler32_combine64; - crc32_combine64; - gzopen64; - gzseek64; - gztell64; - inflateUndermine; -} ZLIB_1.2.2.4; - -ZLIB_1.2.3.4 { - inflateReset2; - inflateMark; -} ZLIB_1.2.3.3; - -ZLIB_1.2.3.5 { - gzbuffer; - gzoffset; - gzoffset64; - gzclose_r; - gzclose_w; -} ZLIB_1.2.3.4; - -ZLIB_1.2.5.1 { - deflatePending; -} ZLIB_1.2.3.5; - -ZLIB_1.2.5.2 { - deflateResetKeep; - gzgetc_; - inflateResetKeep; -} ZLIB_1.2.5.1; - -ZLIB_1.2.7.1 { - inflateGetDictionary; - gzvprintf; -} ZLIB_1.2.5.2; - -ZLIB_1.2.9 { - inflateCodesUsed; - inflateValidate; - uncompress2; - gzfread; - gzfwrite; - deflateGetDictionary; - adler32_z; - crc32_z; -} ZLIB_1.2.7.1; - -ZLIB_1.2.12 { - crc32_combine_gen; - crc32_combine_gen64; - crc32_combine_op; -} ZLIB_1.2.9; diff --git a/libs/zlibng/zlib.pc.cmakein b/libs/zlibng/zlib.pc.cmakein deleted file mode 100644 index 9b64252dc2..0000000000 --- a/libs/zlibng/zlib.pc.cmakein +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=${prefix} -libdir=@PC_LIB_INSTALL_DIR@ -sharedlibdir=${libdir} -includedir=@PC_INC_INSTALL_DIR@ - -Name: zlib@SUFFIX@ -Description: zlib-ng compression library -Version: @ZLIB_FULL_VERSION@ - -Requires: -Libs: -L${libdir} -L${sharedlibdir} -lz@SUFFIX@ -Cflags: -I${includedir} diff --git a/libs/zlibng/zlib.pc.in b/libs/zlibng/zlib.pc.in deleted file mode 100644 index d0a6766b5c..0000000000 --- a/libs/zlibng/zlib.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -sharedlibdir=@sharedlibdir@ -includedir=@includedir@ - -Name: zlib@SUFFIX@ -Description: zlib-ng compression library -Version: @VERSION@ - -Requires: -Libs: -L${libdir} -L${sharedlibdir} -lz@SUFFIX@ -Cflags: -I${includedir} diff --git a/libs/zlibng/zutil.c b/libs/zlibng/zutil.c deleted file mode 100644 index ba36e93f90..0000000000 --- a/libs/zlibng/zutil.c +++ /dev/null @@ -1,111 +0,0 @@ -/* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2017 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#include "zutil.h" -#include "zutil_p.h" - -z_const char * const PREFIX(z_errmsg)[10] = { - (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ - (z_const char *)"stream end", /* Z_STREAM_END 1 */ - (z_const char *)"", /* Z_OK 0 */ - (z_const char *)"file error", /* Z_ERRNO (-1) */ - (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ - (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ - (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ - (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ - (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ - (z_const char *)"" -}; - -const char zlibng_string[] = - " zlib-ng 2.0.0-RC2 forked from zlib"; - -#ifdef ZLIB_COMPAT -const char * Z_EXPORT zlibVersion(void) { - return ZLIB_VERSION; -} -#endif - -const char * Z_EXPORT zlibng_version(void) { - return ZLIBNG_VERSION; -} - -unsigned long Z_EXPORT PREFIX(zlibCompileFlags)(void) { - unsigned long flags; - - flags = 0; - switch ((int)(sizeof(unsigned int))) { - case 2: break; - case 4: flags += 1; break; - case 8: flags += 2; break; - default: flags += 3; - } - switch ((int)(sizeof(unsigned long))) { - case 2: break; - case 4: flags += 1 << 2; break; - case 8: flags += 2 << 2; break; - default: flags += 3 << 2; - } - switch ((int)(sizeof(void *))) { - case 2: break; - case 4: flags += 1 << 4; break; - case 8: flags += 2 << 4; break; - default: flags += 3 << 4; - } - switch ((int)(sizeof(z_off_t))) { - case 2: break; - case 4: flags += 1 << 6; break; - case 8: flags += 2 << 6; break; - default: flags += 3 << 6; - } -#ifdef ZLIB_DEBUG - flags += 1 << 8; -#endif -#ifdef ZLIB_WINAPI - flags += 1 << 10; -#endif - /* Bit 13 reserved for DYNAMIC_CRC_TABLE */ -#ifdef NO_GZCOMPRESS - flags += 1L << 16; -#endif -#ifdef NO_GZIP - flags += 1L << 17; -#endif -#ifdef PKZIP_BUG_WORKAROUND - flags += 1L << 20; -#endif - return flags; -} - -#ifdef ZLIB_DEBUG -# include -# ifndef verbose -# define verbose 0 -# endif -int Z_INTERNAL z_verbose = verbose; - -void Z_INTERNAL z_error(char *m) { - fprintf(stderr, "%s\n", m); - exit(1); -} -#endif - -/* exported to allow conversion of error code to string for compress() and - * uncompress() - */ -const char * Z_EXPORT PREFIX(zError)(int err) { - return ERR_MSG(err); -} - -void Z_INTERNAL *zng_calloc(void *opaque, unsigned items, unsigned size) { - (void)opaque; - return zng_alloc((size_t)items * (size_t)size); -} - -void Z_INTERNAL zng_cfree(void *opaque, void *ptr) { - (void)opaque; - zng_free(ptr); -} diff --git a/libs/zlibng/zutil.h b/libs/zlibng/zutil.h deleted file mode 100644 index 497cb22b40..0000000000 --- a/libs/zlibng/zutil.h +++ /dev/null @@ -1,254 +0,0 @@ -#ifndef ZUTIL_H_ -#define ZUTIL_H_ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#if defined(HAVE_VISIBILITY_INTERNAL) -# define Z_INTERNAL __attribute__((visibility ("internal"))) -#elif defined(HAVE_VISIBILITY_HIDDEN) -# define Z_INTERNAL __attribute__((visibility ("hidden"))) -#else -# define Z_INTERNAL -#endif - -#ifndef __cplusplus -# define Z_REGISTER register -#else -# define Z_REGISTER -#endif - -#ifndef Z_TLS -# define Z_TLS -#endif - -#include -#include -#include -#include -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif -#include "zbuild.h" - -typedef unsigned char uch; /* Included for compatibility with external code only */ -typedef uint16_t ush; /* Included for compatibility with external code only */ -typedef unsigned long ulg; - -extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ -/* (size given to avoid silly warnings with Visual C++) */ - -#define ERR_MSG(err) PREFIX(z_errmsg)[Z_NEED_DICT-(err)] - -#define ERR_RETURN(strm, err) return (strm->msg = ERR_MSG(err), (err)) -/* To be used only when the state is known to be valid */ - - /* common constants */ - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - -#define ADLER32_INITIAL_VALUE 1 /* initial adler-32 hash value */ - - /* target dependencies */ - -#ifdef AMIGA -# define OS_CODE 1 -#endif - -#ifdef __370__ -# if __TARGET_LIB__ < 0x20000000 -# define OS_CODE 4 -# elif __TARGET_LIB__ < 0x40000000 -# define OS_CODE 11 -# else -# define OS_CODE 8 -# endif -#endif - -#if defined(ATARI) || defined(atarist) -# define OS_CODE 5 -#endif - -#ifdef OS2 -# define OS_CODE 6 -#endif - -#if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 7 -#endif - -#ifdef __acorn -# define OS_CODE 13 -#endif - -#if defined(_WIN32) && !defined(__CYGWIN__) -# define OS_CODE 10 -#endif - -#ifdef __APPLE__ -# define OS_CODE 19 -#endif - -#if (defined(_MSC_VER) && (_MSC_VER > 600)) -# define fdopen(fd, type) _fdopen(fd, type) -#endif - -/* MS Visual Studio does not allow inline in C, only C++. - But it provides __inline instead, so use that. */ -#if defined(_MSC_VER) && !defined(inline) && !defined(__cplusplus) -# define inline __inline -#endif - - /* common defaults */ - -#ifndef OS_CODE -# define OS_CODE 3 /* assume Unix */ -#endif - - /* functions */ - -/* Diagnostic functions */ -#ifdef ZLIB_DEBUG -# include - extern int Z_INTERNAL z_verbose; - extern void Z_INTERNAL z_error(char *m); -# define Assert(cond, msg) {if (!(cond)) z_error(msg);} -# define Trace(x) {if (z_verbose >= 0) fprintf x;} -# define Tracev(x) {if (z_verbose > 0) fprintf x;} -# define Tracevv(x) {if (z_verbose > 1) fprintf x;} -# define Tracec(c, x) {if (z_verbose > 0 && (c)) fprintf x;} -# define Tracecv(c, x) {if (z_verbose > 1 && (c)) fprintf x;} -#else -# define Assert(cond, msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c, x) -# define Tracecv(c, x) -#endif - -void Z_INTERNAL *zng_calloc(void *opaque, unsigned items, unsigned size); -void Z_INTERNAL zng_cfree(void *opaque, void *ptr); - -#define ZALLOC(strm, items, size) (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (void *)(addr)) -#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} - -/* Reverse the bytes in a value. Use compiler intrinsics when - possible to take advantage of hardware implementations. */ -#if defined(_MSC_VER) && (_MSC_VER >= 1300) -# pragma intrinsic(_byteswap_ulong) -# define ZSWAP16(q) _byteswap_ushort(q) -# define ZSWAP32(q) _byteswap_ulong(q) -# define ZSWAP64(q) _byteswap_uint64(q) - -#elif defined(__Clang__) || (defined(__GNUC__) && \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) -# define ZSWAP16(q) __builtin_bswap16(q) -# define ZSWAP32(q) __builtin_bswap32(q) -# define ZSWAP64(q) __builtin_bswap64(q) - -#elif defined(__GNUC__) && (__GNUC__ >= 2) && defined(__linux__) -# include -# define ZSWAP16(q) bswap_16(q) -# define ZSWAP32(q) bswap_32(q) -# define ZSWAP64(q) bswap_64(q) - -#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) -# include -# define ZSWAP16(q) bswap16(q) -# define ZSWAP32(q) bswap32(q) -# define ZSWAP64(q) bswap64(q) - -#elif defined(__INTEL_COMPILER) -/* ICC does not provide a two byte swap. */ -# define ZSWAP16(q) ((((q) & 0xff) << 8) | (((q) & 0xff00) >> 8)) -# define ZSWAP32(q) _bswap(q) -# define ZSWAP64(q) _bswap64(q) - -#else -# define ZSWAP16(q) ((((q) & 0xff) << 8) | (((q) & 0xff00) >> 8)) -# define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) -# define ZSWAP64(q) \ - ((q & 0xFF00000000000000u) >> 56u) | \ - ((q & 0x00FF000000000000u) >> 40u) | \ - ((q & 0x0000FF0000000000u) >> 24u) | \ - ((q & 0x000000FF00000000u) >> 8u) | \ - ((q & 0x00000000FF000000u) << 8u) | \ - ((q & 0x0000000000FF0000u) << 24u) | \ - ((q & 0x000000000000FF00u) << 40u) | \ - ((q & 0x00000000000000FFu) << 56u) -#endif - -/* Only enable likely/unlikely if the compiler is known to support it */ -#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__INTEL_COMPILER) || defined(__Clang__) -# define LIKELY_NULL(x) __builtin_expect((x) != 0, 0) -# define LIKELY(x) __builtin_expect(!!(x), 1) -# define UNLIKELY(x) __builtin_expect(!!(x), 0) -# define PREFETCH_L1(addr) __builtin_prefetch(addr, 0, 3) -# define PREFETCH_L2(addr) __builtin_prefetch(addr, 0, 2) -# define PREFETCH_RW(addr) __builtin_prefetch(addr, 1, 2) -#elif defined(__WIN__) -# include -# define LIKELY_NULL(x) x -# define LIKELY(x) x -# define UNLIKELY(x) x -# define PREFETCH_L1(addr) _mm_prefetch((char *) addr, _MM_HINT_T0) -# define PREFETCH_L2(addr) _mm_prefetch((char *) addr, _MM_HINT_T1) -# define PREFETCH_RW(addr) _mm_prefetch((char *) addr, _MM_HINT_T1) -#else -# define LIKELY_NULL(x) x -# define LIKELY(x) x -# define UNLIKELY(x) x -# define PREFETCH_L1(addr) addr -# define PREFETCH_L2(addr) addr -# define PREFETCH_RW(addr) addr -#endif /* (un)likely */ - -#if defined(_MSC_VER) -# define ALIGNED_(x) __declspec(align(x)) -#else -# if defined(__GNUC__) -# define ALIGNED_(x) __attribute__ ((aligned(x))) -# endif -#endif - -#if defined(X86_FEATURES) -# include "arch/x86/x86.h" -#elif defined(ARM_FEATURES) -# include "arch/arm/arm.h" -#elif defined(POWER_FEATURES) -# include "arch/power/power.h" -#endif - -#endif /* ZUTIL_H_ */ diff --git a/libs/zlibng/zutil_p.h b/libs/zlibng/zutil_p.h deleted file mode 100644 index a5f2e525d1..0000000000 --- a/libs/zlibng/zutil_p.h +++ /dev/null @@ -1,34 +0,0 @@ -/* zutil_p.h -- Private inline functions used internally in zlib-ng - * - */ - -#ifndef ZUTIL_P_H -#define ZUTIL_P_H - -#ifdef __APPLE__ -# include -#else -# include -#endif - -/* Function to allocate 16 or 64-byte aligned memory */ -static inline void *zng_alloc(size_t size) { -#if defined(_WIN32) - return (void *)_aligned_malloc(size, 64); -#elif defined(__APPLE__) - return (void *)malloc(size); /* MacOS always aligns to 16 bytes */ -#else - return (void *)memalign(64, size); -#endif -} - -/* Function that can free aligned memory */ -static inline void zng_free(void *ptr) { -#if defined(_WIN32) - _aligned_free(ptr); -#else - free(ptr); -#endif -} - -#endif diff --git a/loginserver/CMakeLists.txt b/loginserver/CMakeLists.txt index 5f2b432489..ca89bd3578 100644 --- a/loginserver/CMakeLists.txt +++ b/loginserver/CMakeLists.txt @@ -1,6 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.12) +cmake_minimum_required(VERSION 3.20) -SET(eqlogin_sources +set(eqlogin_sources account_management.cpp client.cpp client_manager.cpp @@ -12,7 +12,7 @@ SET(eqlogin_sources world_server.cpp ) -SET(eqlogin_headers +set(eqlogin_headers account_management.h client.h client_manager.h @@ -26,10 +26,12 @@ SET(eqlogin_headers world_server.h ) -ADD_EXECUTABLE(loginserver ${eqlogin_sources} ${eqlogin_headers}) +add_compile_definitions(EQEMU_USE_OPENSSL) -INSTALL(TARGETS loginserver RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +add_executable(loginserver ${eqlogin_sources} ${eqlogin_headers}) -TARGET_LINK_LIBRARIES(loginserver ${SERVER_LIBS}) +install(TARGETS loginserver RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +target_link_libraries(loginserver common) + +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/queryserv/CMakeLists.txt b/queryserv/CMakeLists.txt index 82613065a3..39dc0b0483 100644 --- a/queryserv/CMakeLists.txt +++ b/queryserv/CMakeLists.txt @@ -1,6 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.12) +cmake_minimum_required(VERSION 3.20) -SET(qserv_sources +set(qserv_sources database.cpp lfguild.cpp queryserv.cpp @@ -10,7 +10,7 @@ SET(qserv_sources zoneserver.cpp ) -SET(qserv_headers +set(qserv_headers database.h lfguild.h queryservconfig.h @@ -19,12 +19,12 @@ SET(qserv_headers zoneserver.h ) -ADD_EXECUTABLE(queryserv ${qserv_sources} ${qserv_headers}) +add_executable(queryserv ${qserv_sources} ${qserv_headers}) -INSTALL(TARGETS queryserv RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS queryserv RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -ADD_DEFINITIONS(-DQSERV) +add_definitions(-DQSERV) -TARGET_LINK_LIBRARIES(queryserv ${SERVER_LIBS}) +target_link_libraries(queryserv common) -SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/shared_memory/CMakeLists.txt b/shared_memory/CMakeLists.txt index c192e65406..099d27b5bd 100644 --- a/shared_memory/CMakeLists.txt +++ b/shared_memory/CMakeLists.txt @@ -1,20 +1,20 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.12) +cmake_minimum_required(VERSION 3.17.0) -SET(shared_memory_sources +set(shared_memory_sources items.cpp main.cpp spells.cpp ) -SET(shared_memory_headers +set(shared_memory_headers items.h spells.h ) -ADD_EXECUTABLE(shared_memory ${shared_memory_sources} ${shared_memory_headers}) +add_executable(shared_memory ${shared_memory_sources} ${shared_memory_headers}) -INSTALL(TARGETS shared_memory RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS shared_memory RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -TARGET_LINK_LIBRARIES(shared_memory ${SERVER_LIBS}) +target_link_libraries(shared_memory common) -SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/submodules/cereal b/submodules/cereal deleted file mode 160000 index ebef1e9298..0000000000 --- a/submodules/cereal +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ebef1e929807629befafbb2918ea1a08c7194554 diff --git a/submodules/fmt b/submodules/fmt deleted file mode 160000 index e69e5f977d..0000000000 --- a/submodules/fmt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e69e5f977d458f2650bb346dadf2ad30c5320281 diff --git a/submodules/glm b/submodules/glm deleted file mode 160000 index 9749727c2d..0000000000 --- a/submodules/glm +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9749727c2db4742369219e1d452f43e918734b4e diff --git a/submodules/libuv b/submodules/libuv deleted file mode 160000 index 8fb9cb9194..0000000000 --- a/submodules/libuv +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8fb9cb919489a48880680a56efecff6a7dfb4504 diff --git a/submodules/recastnavigation b/submodules/recastnavigation deleted file mode 160000 index 710dabee70..0000000000 --- a/submodules/recastnavigation +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 710dabee701710431938c92d2348849a072f4e27 diff --git a/submodules/vcpkg b/submodules/vcpkg new file mode 160000 index 0000000000..d1ff36c652 --- /dev/null +++ b/submodules/vcpkg @@ -0,0 +1 @@ +Subproject commit d1ff36c6520ee43f1a656c03cd6425c2974a449e diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6ed82f5b83..7fa45d2fc8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,12 +1,12 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) +cmake_minimum_required(VERSION 3.20.0) -ADD_SUBDIRECTORY(cppunit) +add_subdirectory(cppunit) -SET(tests_sources +set(tests_sources main.cpp ) -SET(tests_headers +set(tests_headers atobool_test.h data_verification_test.h fixed_memory_test.h @@ -19,30 +19,30 @@ SET(tests_headers task_state_test.h ) -ADD_EXECUTABLE(tests ${tests_sources} ${tests_headers}) +add_executable(tests ${tests_sources} ${tests_headers}) -TARGET_LINK_LIBRARIES(tests common cppunit fmt ${SERVER_LIBS}) +target_link_libraries(tests common cppunit) -INSTALL(TARGETS tests RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS tests RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -IF(MSVC) - SET_TARGET_PROPERTIES(tests PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") - TARGET_LINK_LIBRARIES(tests "Ws2_32.lib") -ENDIF(MSVC) +if(MSVC) + set_target_properties(tests PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") + target_link_libraries(tests "Ws2_32.lib") +endif() -IF(MINGW) - TARGET_LINK_LIBRARIES(tests "WS2_32") -ENDIF(MINGW) +if(MINGW) + target_link_libraries(tests "WS2_32") +endif() -IF(UNIX) - TARGET_LINK_LIBRARIES(tests "${CMAKE_DL_LIBS}") - TARGET_LINK_LIBRARIES(tests "z") - TARGET_LINK_LIBRARIES(tests "m") - IF(NOT DARWIN) - TARGET_LINK_LIBRARIES(tests "rt") - ENDIF(NOT DARWIN) - TARGET_LINK_LIBRARIES(tests "pthread") - ADD_DEFINITIONS(-fPIC) -ENDIF(UNIX) +if(UNIX) + target_link_libraries(tests "${CMAKE_DL_LIBS}") + target_link_libraries(tests "z") + target_link_libraries(tests "m") + if(NOT DARWIN) + target_link_libraries(tests "rt") + endif() + target_link_libraries(tests "pthread") + add_definitions(-fPIC) +endif() -SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/tests/cppunit/CMakeLists.txt b/tests/cppunit/CMakeLists.txt index 7b7e4c7490..a6f82df878 100644 --- a/tests/cppunit/CMakeLists.txt +++ b/tests/cppunit/CMakeLists.txt @@ -1,6 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.2) +cmake_minimum_required(VERSION 3.20.0) -SET(cppunit_sources +set(cppunit_sources collectoroutput.cpp compileroutput.cpp htmloutput.cpp @@ -12,7 +12,7 @@ SET(cppunit_sources utils.cpp ) -SET(cppunit_headers +set(cppunit_headers cpptest-assert.h cpptest-collectoroutput.h cpptest-compileroutput.h @@ -28,11 +28,11 @@ SET(cppunit_headers winconfig.h ) -ADD_LIBRARY(cppunit ${cppunit_sources} ${cppunit_headers}) +add_library(cppunit ${cppunit_sources} ${cppunit_headers}) -IF(UNIX) - ADD_DEFINITIONS(-fPIC) -ENDIF(UNIX) +if(UNIX) + add_definitions(-fPIC) +endif() -SET(LIBRARY_OUTPUT_PATH ../../bin) +set(LIBRARY_OUTPUT_PATH ../../bin) diff --git a/ucs/CMakeLists.txt b/ucs/CMakeLists.txt index 660d168d8d..188b79a936 100644 --- a/ucs/CMakeLists.txt +++ b/ucs/CMakeLists.txt @@ -1,5 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.12) -SET(ucs_sources +cmake_minimum_required(VERSION 3.20) + +set(ucs_sources chatchannel.cpp clientlist.cpp database.cpp @@ -8,7 +9,7 @@ SET(ucs_sources worldserver.cpp ) -SET(ucs_headers +set(ucs_headers chatchannel.h clientlist.h database.h @@ -16,12 +17,12 @@ SET(ucs_headers worldserver.h ) -ADD_EXECUTABLE(ucs ${ucs_sources} ${ucs_headers}) +add_executable(ucs ${ucs_sources} ${ucs_headers}) -INSTALL(TARGETS ucs RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS ucs RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -ADD_DEFINITIONS(-DUCS) +add_definitions(-DUCS) -TARGET_LINK_LIBRARIES(ucs ${SERVER_LIBS}) +target_link_libraries(ucs common) -SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000000..fdd4e296f3 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,20 @@ +{ + "name": "eqemu", + "version-string": "24.10.3", + "builtin-baseline": "d1ff36c6520ee43f1a656c03cd6425c2974a449e", + "dependencies": [ + "boost-dynamic-bitset", + "boost-foreach", + "boost-tuple", + "libmariadb", + "zlib", + "openssl", + "luajit", + "cereal", + "fmt", + "glm", + "libuv", + "recastnavigation", + "libsodium" + ] +} diff --git a/world/CMakeLists.txt b/world/CMakeLists.txt index 1963c83aef..9a3931ebb0 100644 --- a/world/CMakeLists.txt +++ b/world/CMakeLists.txt @@ -1,17 +1,35 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.12) +cmake_minimum_required(VERSION 3.20) -SET(world_sources +set(world_sources adventure.cpp adventure_manager.cpp + cli/cli_bots_disable.cpp + cli/cli_bots_enable.cpp + cli/cli_copy_character.cpp + cli/cli_database_concurrency.cpp + cli/cli_database_dump.cpp + cli/cli_database_get_schema.cpp + cli/cli_database_set_account_status.cpp + cli/cli_database_updates.cpp + cli/cli_database_version.cpp + cli/cli_etl_get_settings.cpp + cli/cli_mercs_disable.cpp + cli/cli_mercs_enable.cpp + cli/cli_test.cpp + cli/cli_test_colors.cpp + cli/cli_test_expansion.cpp + cli/cli_test_repository.cpp + cli/cli_test_repository_2.cpp + cli/cli_test_string_benchmark.cpp + cli/cli_version.cpp client.cpp cliententry.cpp clientlist.cpp console.cpp - ../common/data_bucket.cpp dynamic_zone.cpp dynamic_zone_manager.cpp - eql_config.cpp eqemu_api_world_data_service.cpp + eql_config.cpp launcher_link.cpp launcher_list.cpp lfplist.cpp @@ -25,17 +43,17 @@ SET(world_sources web_interface.cpp web_interface_eqw.cpp wguild_mgr.cpp - world_event_scheduler.cpp + world_boot.cpp world_config.cpp world_console_connection.cpp + world_event_scheduler.cpp world_server_cli.cpp worlddb.cpp - world_boot.cpp zonelist.cpp zoneserver.cpp - ) +) -SET(world_headers +set(world_headers adventure.h adventure_manager.h adventure_template.h @@ -43,11 +61,10 @@ SET(world_headers cliententry.h clientlist.h console.h - ../common/data_bucket.h dynamic_zone.h dynamic_zone_manager.h - eql_config.h eqemu_api_world_data_service.h + eql_config.h launcher_link.h launcher_list.h lfplist.h @@ -61,27 +78,29 @@ SET(world_headers web_interface.h web_interface_eqw.h wguild_mgr.h + world_boot.h world_config.h world_console_connection.h - world_tcp_connection.h + world_event_scheduler.h world_server_cli.h + world_tcp_connection.h worlddb.h - world_boot.h - world_event_scheduler.h zonelist.h zoneserver.h - ) +) + +source_group("cli" REGULAR_EXPRESSION "cli/.*") -ADD_EXECUTABLE(world ${world_sources} ${world_headers}) +add_executable(world ${world_sources} ${world_headers}) -INSTALL(TARGETS world RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +target_compile_definitions(world PRIVATE WORLD) -IF (WIN32 AND EQEMU_BUILD_PCH) - TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/std-pch.h) -ENDIF () +target_link_libraries(world common) -ADD_DEFINITIONS(-DWORLD) +if(WIN32 AND EQEMU_BUILD_PCH) + target_precompile_headers(world PRIVATE ../common/pch/std-pch.h) +endif() -TARGET_LINK_LIBRARIES(world ${SERVER_LIBS}) +install(TARGETS world RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) \ No newline at end of file diff --git a/world/cli/bots_disable.cpp b/world/cli/cli_bots_disable.cpp similarity index 96% rename from world/cli/bots_disable.cpp rename to world/cli/cli_bots_disable.cpp index b8b36dcc7b..0df7b9873f 100644 --- a/world/cli/bots_disable.cpp +++ b/world/cli/cli_bots_disable.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include "../worlddb.h" #include "../../common/database_schema.h" diff --git a/world/cli/bots_enable.cpp b/world/cli/cli_bots_enable.cpp similarity index 95% rename from world/cli/bots_enable.cpp rename to world/cli/cli_bots_enable.cpp index f029507422..e503f93c97 100644 --- a/world/cli/bots_enable.cpp +++ b/world/cli/cli_bots_enable.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include "../worlddb.h" #include "../../common/rulesys.h" diff --git a/world/cli/copy_character.cpp b/world/cli/cli_copy_character.cpp similarity index 93% rename from world/cli/copy_character.cpp rename to world/cli/cli_copy_character.cpp index ebe8e1831b..047b81944c 100644 --- a/world/cli/copy_character.cpp +++ b/world/cli/cli_copy_character.cpp @@ -1,3 +1,5 @@ +#include "../world_server_cli.h" +#include "../../common/eqemu_logsys.h" #include "../../common/eqemu_logsys_log_aliases.h" #include "../worlddb.h" diff --git a/world/cli/database_concurrency.cpp b/world/cli/cli_database_concurrency.cpp similarity index 97% rename from world/cli/database_concurrency.cpp rename to world/cli/cli_database_concurrency.cpp index bb20f4eba0..0479a90a11 100644 --- a/world/cli/database_concurrency.cpp +++ b/world/cli/cli_database_concurrency.cpp @@ -1,4 +1,5 @@ #include +#include "../world_server_cli.h" #include "../../common/repositories/zone_repository.h" #include "../../common/eqemu_config.h" #include diff --git a/world/cli/database_dump.cpp b/world/cli/cli_database_dump.cpp similarity index 98% rename from world/cli/database_dump.cpp rename to world/cli/cli_database_dump.cpp index 67a591fb0a..2cedd6392e 100644 --- a/world/cli/database_dump.cpp +++ b/world/cli/cli_database_dump.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include "../../common/database/database_dump_service.h" void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description) diff --git a/world/cli/database_get_schema.cpp b/world/cli/cli_database_get_schema.cpp similarity index 98% rename from world/cli/database_get_schema.cpp rename to world/cli/cli_database_get_schema.cpp index b711393584..d4b71c1c4d 100644 --- a/world/cli/database_get_schema.cpp +++ b/world/cli/cli_database_get_schema.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include "../../common/database_schema.h" #include "../../common/json/json.h" diff --git a/world/cli/database_set_account_status.cpp b/world/cli/cli_database_set_account_status.cpp similarity index 93% rename from world/cli/database_set_account_status.cpp rename to world/cli/cli_database_set_account_status.cpp index 39dbeeb281..d0e94b23c9 100644 --- a/world/cli/database_set_account_status.cpp +++ b/world/cli/cli_database_set_account_status.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include "../worlddb.h" void WorldserverCLI::DatabaseSetAccountStatus(int argc, char **argv, argh::parser &cmd, std::string &description) diff --git a/world/cli/database_updates.cpp b/world/cli/cli_database_updates.cpp similarity index 89% rename from world/cli/database_updates.cpp rename to world/cli/cli_database_updates.cpp index f967349fa9..763a1f3c39 100644 --- a/world/cli/database_updates.cpp +++ b/world/cli/cli_database_updates.cpp @@ -1,3 +1,5 @@ +#include "../world_server_cli.h" +#include "../worlddb.h" #include "../../common/database/database_update.h" void WorldserverCLI::DatabaseUpdates(int argc, char **argv, argh::parser &cmd, std::string &description) diff --git a/world/cli/database_version.cpp b/world/cli/cli_database_version.cpp similarity index 95% rename from world/cli/database_version.cpp rename to world/cli/cli_database_version.cpp index 2426d9d729..ee11bb7b1c 100644 --- a/world/cli/database_version.cpp +++ b/world/cli/cli_database_version.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include "../../common/version.h" #include "../../common/json/json.h" #include "../../common/rulesys.h" diff --git a/world/cli/etl_get_settings.cpp b/world/cli/cli_etl_get_settings.cpp similarity index 96% rename from world/cli/etl_get_settings.cpp rename to world/cli/cli_etl_get_settings.cpp index eb1d873aca..c17d0b8e8d 100644 --- a/world/cli/etl_get_settings.cpp +++ b/world/cli/cli_etl_get_settings.cpp @@ -1,3 +1,5 @@ +#include "../world_server_cli.h" +#include "../worlddb.h" #include "../../common/events/player_event_logs.h" #include "../../common/json/json.h" diff --git a/world/cli/mercs_disable.cpp b/world/cli/cli_mercs_disable.cpp similarity index 96% rename from world/cli/mercs_disable.cpp rename to world/cli/cli_mercs_disable.cpp index 0af5d4b0e6..9018d271ba 100644 --- a/world/cli/mercs_disable.cpp +++ b/world/cli/cli_mercs_disable.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include "../worlddb.h" #include "../../common/database_schema.h" diff --git a/world/cli/mercs_enable.cpp b/world/cli/cli_mercs_enable.cpp similarity index 97% rename from world/cli/mercs_enable.cpp rename to world/cli/cli_mercs_enable.cpp index efb0054213..2e69472d5b 100644 --- a/world/cli/mercs_enable.cpp +++ b/world/cli/cli_mercs_enable.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include "../worlddb.h" #include "../../common/database_schema.h" diff --git a/world/cli/test.cpp b/world/cli/cli_test.cpp similarity index 96% rename from world/cli/test.cpp rename to world/cli/cli_test.cpp index 172d46d21f..305f22d2fe 100644 --- a/world/cli/test.cpp +++ b/world/cli/cli_test.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include #include #include diff --git a/world/cli/test_colors.cpp b/world/cli/cli_test_colors.cpp similarity index 99% rename from world/cli/test_colors.cpp rename to world/cli/cli_test_colors.cpp index aeff8d61bf..477c133338 100644 --- a/world/cli/test_colors.cpp +++ b/world/cli/cli_test_colors.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include "../../common/zone_store.h" #include "../../common/termcolor/rang.hpp" diff --git a/world/cli/test_expansion.cpp b/world/cli/cli_test_expansion.cpp similarity index 97% rename from world/cli/test_expansion.cpp rename to world/cli/cli_test_expansion.cpp index 856e053d81..24e227472d 100644 --- a/world/cli/test_expansion.cpp +++ b/world/cli/cli_test_expansion.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include "../../common/rulesys.h" #include "../../common/repositories/content_flags_repository.h" #include "../../common/content/world_content_service.h" diff --git a/world/cli/test_repository.cpp b/world/cli/cli_test_repository.cpp similarity index 98% rename from world/cli/test_repository.cpp rename to world/cli/cli_test_repository.cpp index a4c8f59b17..bd2ee5449e 100644 --- a/world/cli/test_repository.cpp +++ b/world/cli/cli_test_repository.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include "../../common/repositories/instance_list_repository.h" #include "../worlddb.h" diff --git a/world/cli/test_repository_2.cpp b/world/cli/cli_test_repository_2.cpp similarity index 88% rename from world/cli/test_repository_2.cpp rename to world/cli/cli_test_repository_2.cpp index 06a2a624b6..6091b0220c 100644 --- a/world/cli/test_repository_2.cpp +++ b/world/cli/cli_test_repository_2.cpp @@ -1,3 +1,5 @@ +#include "../world_server_cli.h" +#include "../worlddb.h" #include "../../common/repositories/zone_repository.h" void WorldserverCLI::TestRepository2(int argc, char **argv, argh::parser &cmd, std::string &description) diff --git a/world/cli/test_string_benchmark.cpp b/world/cli/cli_test_string_benchmark.cpp similarity index 98% rename from world/cli/test_string_benchmark.cpp rename to world/cli/cli_test_string_benchmark.cpp index 32d5e9020c..e064a266a5 100644 --- a/world/cli/test_string_benchmark.cpp +++ b/world/cli/cli_test_string_benchmark.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include #include #include "../../common/events/player_events.h" diff --git a/world/cli/version.cpp b/world/cli/cli_version.cpp similarity index 95% rename from world/cli/version.cpp rename to world/cli/cli_version.cpp index 383b69ac7d..c82ea9967b 100644 --- a/world/cli/version.cpp +++ b/world/cli/cli_version.cpp @@ -1,3 +1,4 @@ +#include "../world_server_cli.h" #include "../../common/json/json.h" #include "../../common/version.h" diff --git a/world/client.cpp b/world/client.cpp index 674d096399..91aaf3e9f0 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -2530,9 +2530,9 @@ void Client::SendUnsupportedClientPacket(const std::string& message) void Client::LoadDataBucketsCache() { - DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Account, {GetAccountID()}); + DataBucket::BulkLoadEntitiesToCache(&database, DataBucketLoadType::Account, {GetAccountID()}); const auto ids = CharacterDataRepository::GetCharacterIDsByAccountID(database, GetAccountID()); - DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Client, ids); + DataBucket::BulkLoadEntitiesToCache(&database, DataBucketLoadType::Client, ids); } void Client::ClearDataBucketsCache() diff --git a/world/world_server_cli.cpp b/world/world_server_cli.cpp index 3af88f9535..111929a0c4 100644 --- a/world/world_server_cli.cpp +++ b/world/world_server_cli.cpp @@ -39,22 +39,3 @@ void WorldserverCLI::CommandHandler(int argc, char **argv) EQEmuCommand::HandleMenu(function_map, cmd, argc, argv); } -#include "cli/database_concurrency.cpp" -#include "cli/bots_enable.cpp" -#include "cli/bots_disable.cpp" -#include "cli/mercs_enable.cpp" -#include "cli/mercs_disable.cpp" -#include "cli/copy_character.cpp" -#include "cli/database_updates.cpp" -#include "cli/database_dump.cpp" -#include "cli/database_get_schema.cpp" -#include "cli/database_set_account_status.cpp" -#include "cli/database_version.cpp" -#include "cli/test.cpp" -#include "cli/test_colors.cpp" -#include "cli/test_expansion.cpp" -#include "cli/test_repository.cpp" -#include "cli/test_repository_2.cpp" -#include "cli/test_string_benchmark.cpp" -#include "cli/version.cpp" -#include "cli/etl_get_settings.cpp" diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index ffea99f781..acd2142b9c 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -1,6 +1,6 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.12) +cmake_minimum_required(VERSION 3.20) -SET(zone_sources +set(zone_sources aa.cpp aa_ability.cpp aggro.cpp @@ -11,21 +11,27 @@ SET(zone_sources beacon.cpp bonuses.cpp bot.cpp - bot_raid.cpp bot_database.cpp + bot_raid.cpp botspellsai.cpp cheat_manager.cpp + cli/cli_benchmark_databuckets.cpp + cli/cli_sidecar_serve_http.cpp + cli/tests/cli_databuckets.cpp + cli/tests/cli_npc_handins.cpp + cli/tests/cli_npc_handins_multiquest.cpp + cli/tests/cli_test_util.cpp + cli/tests/cli_zone_state.cpp client.cpp - client_evolving_items.cpp client_bot.cpp + client_evolving_items.cpp client_mods.cpp client_packet.cpp client_process.cpp combat_record.cpp corpse.cpp - ../common/data_bucket.cpp - doors.cpp dialogue_window.cpp + doors.cpp dynamic_zone.cpp effects.cpp embparser.cpp @@ -38,24 +44,12 @@ SET(zone_sources fastmath.cpp fearpath.cpp forage.cpp - groups.cpp - guild.cpp - guild_mgr.cpp - hate_list.cpp - heal_rotation.cpp - horse.cpp - inventory.cpp - loot.cpp - embperl.cpp - entity.cpp - exp.cpp - fearpath.cpp - forage.cpp global_loot_manager.cpp groups.cpp guild.cpp guild_mgr.cpp hate_list.cpp + heal_rotation.cpp horse.cpp inventory.cpp loot.cpp @@ -65,8 +59,8 @@ SET(zone_sources mob.cpp mob_ai.cpp mob_appearance.cpp - mob_movement_manager.cpp mob_info.cpp + mob_movement_manager.cpp npc.cpp npc_scale_manager.cpp object.cpp @@ -81,16 +75,15 @@ SET(zone_sources position.cpp qglobals.cpp queryserv.cpp - questmgr.cpp quest_db.cpp quest_parser_collection.cpp + questmgr.cpp raids.cpp raycast_mesh.cpp - sidecar_api/sidecar_api.cpp - sidecar_api/loot_simulator_controller.cpp shared_task_zone_messaging.cpp + sidecar_api/loot_simulator_controller.cpp + sidecar_api/sidecar_api.cpp spawn2.cpp - spawn2.h spawngroup.cpp special_attacks.cpp spell_effects.cpp @@ -111,17 +104,19 @@ SET(zone_sources worldserver.cpp xtargetautohaters.cpp zone.cpp - zone_config.cpp - zonedb.cpp zone_base_data.cpp + zone_cli.cpp + zone_config.cpp zone_event_scheduler.cpp + zone_loot.cpp zone_npc_factions.cpp zone_reload.cpp zone_save_state.cpp + zonedb.cpp zoning.cpp ) -SET(zone_headers +set(zone_headers aa.h aa_ability.h aggromanager.h @@ -139,9 +134,8 @@ SET(zone_headers command.h common.h corpse.h - ../common/data_bucket.h - doors.h dialogue_window.h + doors.h dynamic_zone.h embparser.h embperl.h @@ -157,8 +151,8 @@ SET(zone_headers hate_list.h heal_rotation.h horse.h - lua_bot.h lua_bit.h + lua_bot.h lua_buff.h lua_client.h lua_corpse.h @@ -206,17 +200,15 @@ SET(zone_headers pets.h position.h qglobals.h - quest_interface.h queryserv.h - quest_interface.h - questmgr.h quest_db.h + quest_interface.h quest_parser_collection.h + questmgr.h raids.h raycast_mesh.h - sidecar_api/sidecar_api.h shared_task_zone_messaging.h - spawn2.cpp + sidecar_api/sidecar_api.h spawn2.h spawngroup.h string_ids.h @@ -231,22 +223,21 @@ SET(zone_headers worldserver.h xtargetautohaters.h zone.h - zone_event_scheduler.h - zone_config.h - zonedb.h - zonedump.h zone_cli.h + zone_config.h + zone_event_scheduler.h zone_reload.h zone_save_state.h - zone_cli.cpp) + zonedb.h + zonedump.h +) -# lua unity build set(lua_sources - lua_bot.cpp lua_bit.cpp + lua_bot.cpp lua_buff.cpp - lua_corpse.cpp lua_client.cpp + lua_corpse.cpp lua_database.cpp lua_door.cpp lua_encounter.cpp @@ -277,7 +268,6 @@ set(lua_sources add_library(lua_zone STATIC ${lua_sources}) set_target_properties(lua_zone PROPERTIES UNITY_BUILD ON UNITY_BUILD_BATCH_SIZE 8) -# perl unity build set(perl_sources perl_bot.cpp perl_buff.cpp @@ -308,10 +298,71 @@ set(perl_sources add_library(perl_zone STATIC ${perl_sources}) set_target_properties(perl_zone PROPERTIES UNITY_BUILD ON UNITY_BUILD_BATCH_SIZE 8) -# gm commands set(gm_command_sources - command.cpp bot_command.cpp + bot_commands/bot_actionable.cpp + bot_commands/bot_appearance.cpp + bot_commands/bot_apply_poison.cpp + bot_commands/bot_apply_potion.cpp + bot_commands/bot_attack.cpp + bot_commands/bot_behind_mob.cpp + bot_commands/bot_blocked_buffs.cpp + bot_commands/bot_bot.cpp + bot_commands/bot_bot_settings.cpp + bot_commands/bot_cast.cpp + bot_commands/bot_class_race_list.cpp + bot_commands/bot_click_item.cpp + bot_commands/bot_copy_settings.cpp + bot_commands/bot_default_settings.cpp + bot_commands/bot_depart.cpp + bot_commands/bot_discipline.cpp + bot_commands/bot_distance_ranged.cpp + bot_commands/bot_find_aliases.cpp + bot_commands/bot_follow.cpp + bot_commands/bot_guard.cpp + bot_commands/bot_heal_rotation.cpp + bot_commands/bot_help.cpp + bot_commands/bot_hold.cpp + bot_commands/bot_illusion_block.cpp + bot_commands/bot_inventory.cpp + bot_commands/bot_item_use.cpp + bot_commands/bot_max_melee_range.cpp + bot_commands/bot_name.cpp + bot_commands/bot_owner_option.cpp + bot_commands/bot_pet.cpp + bot_commands/bot_pick_lock.cpp + bot_commands/bot_pickpocket.cpp + bot_commands/bot_precombat.cpp + bot_commands/bot_pull.cpp + bot_commands/bot_release.cpp + bot_commands/bot_set_assistee.cpp + bot_commands/bot_sit_hp_percent.cpp + bot_commands/bot_sit_in_combat.cpp + bot_commands/bot_sit_mana_percent.cpp + bot_commands/bot_spell.cpp + bot_commands/bot_spell_aggro_checks.cpp + bot_commands/bot_spell_announce_cast.cpp + bot_commands/bot_spell_delays.cpp + bot_commands/bot_spell_engaged_priority.cpp + bot_commands/bot_spell_holds.cpp + bot_commands/bot_spell_idle_priority.cpp + bot_commands/bot_spell_max_hp_pct.cpp + bot_commands/bot_spell_max_mana_pct.cpp + bot_commands/bot_spell_max_thresholds.cpp + bot_commands/bot_spell_min_hp_pct.cpp + bot_commands/bot_spell_min_mana_pct.cpp + bot_commands/bot_spell_min_thresholds.cpp + bot_commands/bot_spell_pursue_priority.cpp + bot_commands/bot_spell_resist_limits.cpp + bot_commands/bot_spell_target_count.cpp + bot_commands/bot_spelltypes.cpp + bot_commands/bot_summon.cpp + bot_commands/bot_suspend.cpp + bot_commands/bot_taunt.cpp + bot_commands/bot_timer.cpp + bot_commands/bot_track.cpp + bot_commands/bot_view_combos.cpp + command.cpp gm_commands/acceptrules.cpp gm_commands/advnpcspawn.cpp gm_commands/aggrozone.cpp @@ -351,11 +402,37 @@ set(gm_command_sources gm_commands/emptyinventory.cpp gm_commands/enablerecipe.cpp gm_commands/entityvariable.cpp + gm_commands/evolving_items.cpp gm_commands/exptoggle.cpp gm_commands/faction.cpp - gm_commands/evolving_items.cpp + gm_commands/faction_association.cpp gm_commands/feature.cpp gm_commands/find.cpp + gm_commands/find/find_aa.cpp + gm_commands/find/find_account.cpp + gm_commands/find/find_body_type.cpp + gm_commands/find/find_bot.cpp + gm_commands/find/find_bug_category.cpp + gm_commands/find/find_character.cpp + gm_commands/find/find_class.cpp + gm_commands/find/find_comparison_type.cpp + gm_commands/find/find_currency.cpp + gm_commands/find/find_deity.cpp + gm_commands/find/find_emote.cpp + gm_commands/find/find_faction.cpp + gm_commands/find/find_item.cpp + gm_commands/find/find_language.cpp + gm_commands/find/find_ldon_theme.cpp + gm_commands/find/find_npctype.cpp + gm_commands/find/find_object_type.cpp + gm_commands/find/find_race.cpp + gm_commands/find/find_recipe.cpp + gm_commands/find/find_skill.cpp + gm_commands/find/find_special_ability.cpp + gm_commands/find/find_spell.cpp + gm_commands/find/find_stance.cpp + gm_commands/find/find_task.cpp + gm_commands/find/find_zone.cpp gm_commands/fish.cpp gm_commands/fixmob.cpp gm_commands/flagedit.cpp @@ -380,9 +457,9 @@ set(gm_command_sources gm_commands/kill.cpp gm_commands/killallnpcs.cpp gm_commands/list.cpp - gm_commands/lootsim.cpp gm_commands/loc.cpp gm_commands/logs.cpp + gm_commands/lootsim.cpp gm_commands/makepet.cpp gm_commands/memspell.cpp gm_commands/merchantshop.cpp @@ -434,12 +511,119 @@ set(gm_command_sources gm_commands/sensetrap.cpp gm_commands/serverrules.cpp gm_commands/set.cpp + gm_commands/set/set_aa_exp.cpp + gm_commands/set/set_aa_points.cpp + gm_commands/set/set_adventure_points.cpp + gm_commands/set/set_alternate_currency.cpp + gm_commands/set/set_animation.cpp + gm_commands/set/set_anon.cpp + gm_commands/set/set_auto_login.cpp + gm_commands/set/set_bind_point.cpp + gm_commands/set/set_checksum.cpp + gm_commands/set/set_class_permanent.cpp + gm_commands/set/set_crystals.cpp + gm_commands/set/set_date.cpp + gm_commands/set/set_endurance.cpp + gm_commands/set/set_endurance_full.cpp + gm_commands/set/set_exp.cpp + gm_commands/set/set_flymode.cpp + gm_commands/set/set_frozen.cpp + gm_commands/set/set_gender.cpp + gm_commands/set/set_gender_permanent.cpp + gm_commands/set/set_gm.cpp + gm_commands/set/set_gm_speed.cpp + gm_commands/set/set_gm_status.cpp + gm_commands/set/set_god_mode.cpp + gm_commands/set/set_haste.cpp + gm_commands/set/set_hero_model.cpp + gm_commands/set/set_hide_me.cpp + gm_commands/set/set_hp.cpp + gm_commands/set/set_hp_full.cpp + gm_commands/set/set_invulnerable.cpp + gm_commands/set/set_language.cpp + gm_commands/set/set_last_name.cpp + gm_commands/set/set_level.cpp + gm_commands/set/set_loginserver_info.cpp + gm_commands/set/set_mana.cpp + gm_commands/set/set_mana_full.cpp + gm_commands/set/set_motd.cpp + gm_commands/set/set_name.cpp + gm_commands/set/set_ooc_mute.cpp + gm_commands/set/set_password.cpp + gm_commands/set/set_pvp.cpp + gm_commands/set/set_pvp_points.cpp + gm_commands/set/set_race.cpp + gm_commands/set/set_race_permanent.cpp + gm_commands/set/set_server_locked.cpp + gm_commands/set/set_skill.cpp + gm_commands/set/set_skill_all.cpp + gm_commands/set/set_skill_all_max.cpp + gm_commands/set/set_start_zone.cpp + gm_commands/set/set_temporary_name.cpp + gm_commands/set/set_texture.cpp + gm_commands/set/set_time.cpp + gm_commands/set/set_time_zone.cpp + gm_commands/set/set_title.cpp + gm_commands/set/set_title_suffix.cpp + gm_commands/set/set_weather.cpp + gm_commands/set/set_zone.cpp gm_commands/show.cpp + gm_commands/show/show_aa_points.cpp + gm_commands/show/show_aas.cpp + gm_commands/show/show_aggro.cpp + gm_commands/show/show_auto_login.cpp + gm_commands/show/show_buffs.cpp + gm_commands/show/show_buried_corpse_count.cpp + gm_commands/show/show_client_version_summary.cpp + gm_commands/show/show_content_flags.cpp + gm_commands/show/show_currencies.cpp + gm_commands/show/show_distance.cpp + gm_commands/show/show_emotes.cpp + gm_commands/show/show_field_of_view.cpp + gm_commands/show/show_flags.cpp + gm_commands/show/show_group_info.cpp + gm_commands/show/show_hatelist.cpp + gm_commands/show/show_inventory.cpp + gm_commands/show/show_ip_lookup.cpp + gm_commands/show/show_keyring.cpp + gm_commands/show/show_line_of_sight.cpp + gm_commands/show/show_network.cpp + gm_commands/show/show_network_stats.cpp + gm_commands/show/show_npc_global_loot.cpp + gm_commands/show/show_npc_stats.cpp + gm_commands/show/show_npc_type.cpp + gm_commands/show/show_peqzone_flags.cpp + gm_commands/show/show_petition.cpp + gm_commands/show/show_petition_info.cpp + gm_commands/show/show_proximity.cpp + gm_commands/show/show_quest_errors.cpp + gm_commands/show/show_quest_globals.cpp + gm_commands/show/show_recipe.cpp + gm_commands/show/show_server_info.cpp + gm_commands/show/show_skills.cpp + gm_commands/show/show_spawn_status.cpp + gm_commands/show/show_special_abilities.cpp + gm_commands/show/show_spells.cpp + gm_commands/show/show_spells_list.cpp + gm_commands/show/show_stats.cpp + gm_commands/show/show_timers.cpp + gm_commands/show/show_traps.cpp + gm_commands/show/show_uptime.cpp + gm_commands/show/show_variable.cpp + gm_commands/show/show_version.cpp + gm_commands/show/show_waypoints.cpp + gm_commands/show/show_who.cpp + gm_commands/show/show_xtargets.cpp + gm_commands/show/show_zone_data.cpp + gm_commands/show/show_zone_global_loot.cpp + gm_commands/show/show_zone_loot.cpp + gm_commands/show/show_zone_points.cpp + gm_commands/show/show_zone_status.cpp + gm_commands/show/show_zone_variables.cpp gm_commands/shutdown.cpp gm_commands/spawn.cpp gm_commands/spawneditmass.cpp gm_commands/spawnfix.cpp - gm_commands/faction_association.cpp gm_commands/stun.cpp gm_commands/summon.cpp gm_commands/summonburiedplayercorpse.cpp @@ -463,46 +647,58 @@ set(gm_command_sources gm_commands/wp.cpp gm_commands/wpadd.cpp gm_commands/zone.cpp + gm_commands/zone_instance.cpp + gm_commands/zone_shard.cpp gm_commands/zonebootup.cpp gm_commands/zoneshutdown.cpp gm_commands/zonevariable.cpp - gm_commands/zone_instance.cpp - gm_commands/zone_shard.cpp gm_commands/zsave.cpp ) +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Source Files" FILES ${zone_sources}) +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Header Files" FILES ${zone_headers}) +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Source Files" FILES ${gm_command_sources}) + add_library(gm_commands_zone STATIC ${gm_command_sources}) +target_link_libraries(gm_commands_zone PRIVATE common) set_target_properties(gm_commands_zone PROPERTIES UNITY_BUILD ON UNITY_BUILD_BATCH_SIZE 32) -# zone combine sources and headers -ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers}) +add_executable(zone ${zone_sources} ${zone_headers}) -# binary output directory -INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +install(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -# precompiled headers -IF (EQEMU_BUILD_PCH) +if(EQEMU_BUILD_PCH) TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/pch/app-pch.h) TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/pch/std-pch.h) TARGET_PRECOMPILE_HEADERS(zone PRIVATE ./pch/pch.h) -ENDIF() +endif() -ADD_DEFINITIONS(-DZONE) +add_definitions(-DZONE) -# link lua_zone unity build against luabind -target_link_libraries(lua_zone PRIVATE luabind) -if (EQEMU_BUILD_STATIC AND LUA_LIBRARY) - target_link_libraries(zone PRIVATE ${LUA_LIBRARY}) +if(EQEMU_BUILD_LUA) + target_compile_definitions(lua_zone PUBLIC LUA_EQEMU) + target_link_libraries(lua_zone PUBLIC luabind Boost::dynamic_bitset Boost::tuple Boost::foreach common) + if (EQEMU_BUILD_STATIC AND LUA_LIBRARY) + target_link_libraries(zone PRIVATE ${LUA_LIBRARY}) + endif() endif() -# perl unity build links against perl_zone -target_link_libraries(perl_zone PRIVATE perlbind) -if (EQEMU_BUILD_STATIC AND PERL_LIBRARY) - target_link_libraries(zone PRIVATE ${PERL_LIBRARY}) +if(EQEMU_BUILD_PERL) + target_compile_definitions(perl_zone PUBLIC EMBPERL EMBPERL_PLUGIN PERLBIND_NO_STRICT_SCALAR_TYPES) + target_link_libraries(perl_zone PUBLIC perlbind common ${PERL_LIBRARY}) + if (EQEMU_BUILD_STATIC AND PERL_LIBRARY) + target_link_libraries(zone PRIVATE ${PERL_LIBRARY}) + endif() endif() -# link zone against common libraries -target_link_libraries(zone PRIVATE lua_zone perl_zone gm_commands_zone ${ZONE_LIBS}) +target_link_libraries(zone PRIVATE gm_commands_zone common RecastNavigation::Detour) + +if(EQEMU_BUILD_LUA) + target_link_libraries(zone PRIVATE lua_zone) +endif() -SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +if(EQEMU_BUILD_PERL) + target_link_libraries(zone PRIVATE perl_zone) +endif() +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) \ No newline at end of file diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 0cc44cac33..c1beab76fd 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -5901,7 +5901,7 @@ float Mob::CheckHeroicBonusesDataBuckets(std::string bucket_name) DataBucketKey k = GetScopedBucketKeys(); k.key = bucket_name; if (IsOfClientBot()) { - bucket_value = DataBucket::GetData(k).value; + bucket_value = DataBucket::GetData(&database, k).value; } if (bucket_value.empty() || !Strings::IsNumber(bucket_value)) { diff --git a/zone/bot.cpp b/zone/bot.cpp index 1aeb0c09ac..d0d83fbc81 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -8224,13 +8224,13 @@ bool Bot::CheckDataBucket(std::string bucket_name, const std::string& bucket_val DataBucketKey k = GetScopedBucketKeys(); k.key = bucket_name; - auto b = DataBucket::GetData(k); + auto b = DataBucket::GetData(&database, k); if (b.value.empty() && GetBotOwner()) { // fetch from owner k = GetBotOwner()->GetScopedBucketKeys(); k.key = bucket_name; - b = DataBucket::GetData(k); + b = DataBucket::GetData(&database, k); if (b.value.empty()) { return false; } diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index a697fc6bbb..0e202540cf 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -863,65 +863,3 @@ void SendSpellTypeWindow(Client* c, const Seperator* sep) { c->SendPopupToClient("Spell Types", popup_text.c_str()); } -#include "bot_commands/actionable.cpp" -#include "bot_commands/appearance.cpp" -#include "bot_commands/apply_poison.cpp" -#include "bot_commands/apply_potion.cpp" -#include "bot_commands/attack.cpp" -#include "bot_commands/behind_mob.cpp" -#include "bot_commands/blocked_buffs.cpp" -#include "bot_commands/bot.cpp" -#include "bot_commands/bot_settings.cpp" -#include "bot_commands/cast.cpp" -#include "bot_commands/class_race_list.cpp" -#include "bot_commands/click_item.cpp" -#include "bot_commands/copy_settings.cpp" -#include "bot_commands/default_settings.cpp" -#include "bot_commands/depart.cpp" -#include "bot_commands/discipline.cpp" -#include "bot_commands/distance_ranged.cpp" -#include "bot_commands/find_aliases.cpp" -#include "bot_commands/follow.cpp" -#include "bot_commands/guard.cpp" -#include "bot_commands/heal_rotation.cpp" -#include "bot_commands/help.cpp" -#include "bot_commands/hold.cpp" -#include "bot_commands/illusion_block.cpp" -#include "bot_commands/inventory.cpp" -#include "bot_commands/item_use.cpp" -#include "bot_commands/max_melee_range.cpp" -#include "bot_commands/name.cpp" -#include "bot_commands/owner_option.cpp" -#include "bot_commands/pet.cpp" -#include "bot_commands/pick_lock.cpp" -#include "bot_commands/pickpocket.cpp" -#include "bot_commands/precombat.cpp" -#include "bot_commands/pull.cpp" -#include "bot_commands/release.cpp" -#include "bot_commands/set_assistee.cpp" -#include "bot_commands/sit_hp_percent.cpp" -#include "bot_commands/sit_in_combat.cpp" -#include "bot_commands/sit_mana_percent.cpp" -#include "bot_commands/spell.cpp" -#include "bot_commands/spell_aggro_checks.cpp" -#include "bot_commands/spell_announce_cast.cpp" -#include "bot_commands/spell_delays.cpp" -#include "bot_commands/spell_engaged_priority.cpp" -#include "bot_commands/spell_holds.cpp" -#include "bot_commands/spell_idle_priority.cpp" -#include "bot_commands/spell_max_hp_pct.cpp" -#include "bot_commands/spell_max_mana_pct.cpp" -#include "bot_commands/spell_max_thresholds.cpp" -#include "bot_commands/spell_min_hp_pct.cpp" -#include "bot_commands/spell_min_mana_pct.cpp" -#include "bot_commands/spell_min_thresholds.cpp" -#include "bot_commands/spell_pursue_priority.cpp" -#include "bot_commands/spell_resist_limits.cpp" -#include "bot_commands/spell_target_count.cpp" -#include "bot_commands/spelltypes.cpp" -#include "bot_commands/summon.cpp" -#include "bot_commands/suspend.cpp" -#include "bot_commands/taunt.cpp" -#include "bot_commands/timer.cpp" -#include "bot_commands/track.cpp" -#include "bot_commands/view_combos.cpp" diff --git a/zone/bot_commands/actionable.cpp b/zone/bot_commands/bot_actionable.cpp similarity index 100% rename from zone/bot_commands/actionable.cpp rename to zone/bot_commands/bot_actionable.cpp diff --git a/zone/bot_commands/appearance.cpp b/zone/bot_commands/bot_appearance.cpp similarity index 100% rename from zone/bot_commands/appearance.cpp rename to zone/bot_commands/bot_appearance.cpp diff --git a/zone/bot_commands/apply_poison.cpp b/zone/bot_commands/bot_apply_poison.cpp similarity index 100% rename from zone/bot_commands/apply_poison.cpp rename to zone/bot_commands/bot_apply_poison.cpp diff --git a/zone/bot_commands/apply_potion.cpp b/zone/bot_commands/bot_apply_potion.cpp similarity index 100% rename from zone/bot_commands/apply_potion.cpp rename to zone/bot_commands/bot_apply_potion.cpp diff --git a/zone/bot_commands/attack.cpp b/zone/bot_commands/bot_attack.cpp similarity index 100% rename from zone/bot_commands/attack.cpp rename to zone/bot_commands/bot_attack.cpp diff --git a/zone/bot_commands/behind_mob.cpp b/zone/bot_commands/bot_behind_mob.cpp similarity index 100% rename from zone/bot_commands/behind_mob.cpp rename to zone/bot_commands/bot_behind_mob.cpp diff --git a/zone/bot_commands/blocked_buffs.cpp b/zone/bot_commands/bot_blocked_buffs.cpp similarity index 100% rename from zone/bot_commands/blocked_buffs.cpp rename to zone/bot_commands/bot_blocked_buffs.cpp diff --git a/zone/bot_commands/bot.cpp b/zone/bot_commands/bot_bot.cpp similarity index 100% rename from zone/bot_commands/bot.cpp rename to zone/bot_commands/bot_bot.cpp diff --git a/zone/bot_commands/bot_settings.cpp b/zone/bot_commands/bot_bot_settings.cpp similarity index 100% rename from zone/bot_commands/bot_settings.cpp rename to zone/bot_commands/bot_bot_settings.cpp diff --git a/zone/bot_commands/cast.cpp b/zone/bot_commands/bot_cast.cpp similarity index 100% rename from zone/bot_commands/cast.cpp rename to zone/bot_commands/bot_cast.cpp diff --git a/zone/bot_commands/class_race_list.cpp b/zone/bot_commands/bot_class_race_list.cpp similarity index 100% rename from zone/bot_commands/class_race_list.cpp rename to zone/bot_commands/bot_class_race_list.cpp diff --git a/zone/bot_commands/click_item.cpp b/zone/bot_commands/bot_click_item.cpp similarity index 100% rename from zone/bot_commands/click_item.cpp rename to zone/bot_commands/bot_click_item.cpp diff --git a/zone/bot_commands/copy_settings.cpp b/zone/bot_commands/bot_copy_settings.cpp similarity index 100% rename from zone/bot_commands/copy_settings.cpp rename to zone/bot_commands/bot_copy_settings.cpp diff --git a/zone/bot_commands/default_settings.cpp b/zone/bot_commands/bot_default_settings.cpp similarity index 100% rename from zone/bot_commands/default_settings.cpp rename to zone/bot_commands/bot_default_settings.cpp diff --git a/zone/bot_commands/depart.cpp b/zone/bot_commands/bot_depart.cpp similarity index 100% rename from zone/bot_commands/depart.cpp rename to zone/bot_commands/bot_depart.cpp diff --git a/zone/bot_commands/discipline.cpp b/zone/bot_commands/bot_discipline.cpp similarity index 100% rename from zone/bot_commands/discipline.cpp rename to zone/bot_commands/bot_discipline.cpp diff --git a/zone/bot_commands/distance_ranged.cpp b/zone/bot_commands/bot_distance_ranged.cpp similarity index 100% rename from zone/bot_commands/distance_ranged.cpp rename to zone/bot_commands/bot_distance_ranged.cpp diff --git a/zone/bot_commands/find_aliases.cpp b/zone/bot_commands/bot_find_aliases.cpp similarity index 100% rename from zone/bot_commands/find_aliases.cpp rename to zone/bot_commands/bot_find_aliases.cpp diff --git a/zone/bot_commands/follow.cpp b/zone/bot_commands/bot_follow.cpp similarity index 100% rename from zone/bot_commands/follow.cpp rename to zone/bot_commands/bot_follow.cpp diff --git a/zone/bot_commands/guard.cpp b/zone/bot_commands/bot_guard.cpp similarity index 100% rename from zone/bot_commands/guard.cpp rename to zone/bot_commands/bot_guard.cpp diff --git a/zone/bot_commands/heal_rotation.cpp b/zone/bot_commands/bot_heal_rotation.cpp similarity index 100% rename from zone/bot_commands/heal_rotation.cpp rename to zone/bot_commands/bot_heal_rotation.cpp diff --git a/zone/bot_commands/help.cpp b/zone/bot_commands/bot_help.cpp similarity index 100% rename from zone/bot_commands/help.cpp rename to zone/bot_commands/bot_help.cpp diff --git a/zone/bot_commands/hold.cpp b/zone/bot_commands/bot_hold.cpp similarity index 100% rename from zone/bot_commands/hold.cpp rename to zone/bot_commands/bot_hold.cpp diff --git a/zone/bot_commands/illusion_block.cpp b/zone/bot_commands/bot_illusion_block.cpp similarity index 100% rename from zone/bot_commands/illusion_block.cpp rename to zone/bot_commands/bot_illusion_block.cpp diff --git a/zone/bot_commands/inventory.cpp b/zone/bot_commands/bot_inventory.cpp similarity index 100% rename from zone/bot_commands/inventory.cpp rename to zone/bot_commands/bot_inventory.cpp diff --git a/zone/bot_commands/item_use.cpp b/zone/bot_commands/bot_item_use.cpp similarity index 100% rename from zone/bot_commands/item_use.cpp rename to zone/bot_commands/bot_item_use.cpp diff --git a/zone/bot_commands/max_melee_range.cpp b/zone/bot_commands/bot_max_melee_range.cpp similarity index 100% rename from zone/bot_commands/max_melee_range.cpp rename to zone/bot_commands/bot_max_melee_range.cpp diff --git a/zone/bot_commands/name.cpp b/zone/bot_commands/bot_name.cpp similarity index 100% rename from zone/bot_commands/name.cpp rename to zone/bot_commands/bot_name.cpp diff --git a/zone/bot_commands/owner_option.cpp b/zone/bot_commands/bot_owner_option.cpp similarity index 100% rename from zone/bot_commands/owner_option.cpp rename to zone/bot_commands/bot_owner_option.cpp diff --git a/zone/bot_commands/pet.cpp b/zone/bot_commands/bot_pet.cpp similarity index 100% rename from zone/bot_commands/pet.cpp rename to zone/bot_commands/bot_pet.cpp diff --git a/zone/bot_commands/pick_lock.cpp b/zone/bot_commands/bot_pick_lock.cpp similarity index 98% rename from zone/bot_commands/pick_lock.cpp rename to zone/bot_commands/bot_pick_lock.cpp index 7815833eea..49096a8f56 100644 --- a/zone/bot_commands/pick_lock.cpp +++ b/zone/bot_commands/bot_pick_lock.cpp @@ -1,4 +1,5 @@ #include "../bot_command.h" +#include "../doors.h" void bot_command_pick_lock(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/pickpocket.cpp b/zone/bot_commands/bot_pickpocket.cpp similarity index 100% rename from zone/bot_commands/pickpocket.cpp rename to zone/bot_commands/bot_pickpocket.cpp diff --git a/zone/bot_commands/precombat.cpp b/zone/bot_commands/bot_precombat.cpp similarity index 100% rename from zone/bot_commands/precombat.cpp rename to zone/bot_commands/bot_precombat.cpp diff --git a/zone/bot_commands/pull.cpp b/zone/bot_commands/bot_pull.cpp similarity index 100% rename from zone/bot_commands/pull.cpp rename to zone/bot_commands/bot_pull.cpp diff --git a/zone/bot_commands/release.cpp b/zone/bot_commands/bot_release.cpp similarity index 100% rename from zone/bot_commands/release.cpp rename to zone/bot_commands/bot_release.cpp diff --git a/zone/bot_commands/set_assistee.cpp b/zone/bot_commands/bot_set_assistee.cpp similarity index 100% rename from zone/bot_commands/set_assistee.cpp rename to zone/bot_commands/bot_set_assistee.cpp diff --git a/zone/bot_commands/sit_hp_percent.cpp b/zone/bot_commands/bot_sit_hp_percent.cpp similarity index 100% rename from zone/bot_commands/sit_hp_percent.cpp rename to zone/bot_commands/bot_sit_hp_percent.cpp diff --git a/zone/bot_commands/sit_in_combat.cpp b/zone/bot_commands/bot_sit_in_combat.cpp similarity index 100% rename from zone/bot_commands/sit_in_combat.cpp rename to zone/bot_commands/bot_sit_in_combat.cpp diff --git a/zone/bot_commands/sit_mana_percent.cpp b/zone/bot_commands/bot_sit_mana_percent.cpp similarity index 100% rename from zone/bot_commands/sit_mana_percent.cpp rename to zone/bot_commands/bot_sit_mana_percent.cpp diff --git a/zone/bot_commands/spell.cpp b/zone/bot_commands/bot_spell.cpp similarity index 100% rename from zone/bot_commands/spell.cpp rename to zone/bot_commands/bot_spell.cpp diff --git a/zone/bot_commands/spell_aggro_checks.cpp b/zone/bot_commands/bot_spell_aggro_checks.cpp similarity index 100% rename from zone/bot_commands/spell_aggro_checks.cpp rename to zone/bot_commands/bot_spell_aggro_checks.cpp diff --git a/zone/bot_commands/spell_announce_cast.cpp b/zone/bot_commands/bot_spell_announce_cast.cpp similarity index 100% rename from zone/bot_commands/spell_announce_cast.cpp rename to zone/bot_commands/bot_spell_announce_cast.cpp diff --git a/zone/bot_commands/spell_delays.cpp b/zone/bot_commands/bot_spell_delays.cpp similarity index 100% rename from zone/bot_commands/spell_delays.cpp rename to zone/bot_commands/bot_spell_delays.cpp diff --git a/zone/bot_commands/spell_engaged_priority.cpp b/zone/bot_commands/bot_spell_engaged_priority.cpp similarity index 100% rename from zone/bot_commands/spell_engaged_priority.cpp rename to zone/bot_commands/bot_spell_engaged_priority.cpp diff --git a/zone/bot_commands/spell_holds.cpp b/zone/bot_commands/bot_spell_holds.cpp similarity index 100% rename from zone/bot_commands/spell_holds.cpp rename to zone/bot_commands/bot_spell_holds.cpp diff --git a/zone/bot_commands/spell_idle_priority.cpp b/zone/bot_commands/bot_spell_idle_priority.cpp similarity index 100% rename from zone/bot_commands/spell_idle_priority.cpp rename to zone/bot_commands/bot_spell_idle_priority.cpp diff --git a/zone/bot_commands/spell_max_hp_pct.cpp b/zone/bot_commands/bot_spell_max_hp_pct.cpp similarity index 100% rename from zone/bot_commands/spell_max_hp_pct.cpp rename to zone/bot_commands/bot_spell_max_hp_pct.cpp diff --git a/zone/bot_commands/spell_max_mana_pct.cpp b/zone/bot_commands/bot_spell_max_mana_pct.cpp similarity index 100% rename from zone/bot_commands/spell_max_mana_pct.cpp rename to zone/bot_commands/bot_spell_max_mana_pct.cpp diff --git a/zone/bot_commands/spell_max_thresholds.cpp b/zone/bot_commands/bot_spell_max_thresholds.cpp similarity index 100% rename from zone/bot_commands/spell_max_thresholds.cpp rename to zone/bot_commands/bot_spell_max_thresholds.cpp diff --git a/zone/bot_commands/spell_min_hp_pct.cpp b/zone/bot_commands/bot_spell_min_hp_pct.cpp similarity index 100% rename from zone/bot_commands/spell_min_hp_pct.cpp rename to zone/bot_commands/bot_spell_min_hp_pct.cpp diff --git a/zone/bot_commands/spell_min_mana_pct.cpp b/zone/bot_commands/bot_spell_min_mana_pct.cpp similarity index 100% rename from zone/bot_commands/spell_min_mana_pct.cpp rename to zone/bot_commands/bot_spell_min_mana_pct.cpp diff --git a/zone/bot_commands/spell_min_thresholds.cpp b/zone/bot_commands/bot_spell_min_thresholds.cpp similarity index 100% rename from zone/bot_commands/spell_min_thresholds.cpp rename to zone/bot_commands/bot_spell_min_thresholds.cpp diff --git a/zone/bot_commands/spell_pursue_priority.cpp b/zone/bot_commands/bot_spell_pursue_priority.cpp similarity index 100% rename from zone/bot_commands/spell_pursue_priority.cpp rename to zone/bot_commands/bot_spell_pursue_priority.cpp diff --git a/zone/bot_commands/spell_resist_limits.cpp b/zone/bot_commands/bot_spell_resist_limits.cpp similarity index 100% rename from zone/bot_commands/spell_resist_limits.cpp rename to zone/bot_commands/bot_spell_resist_limits.cpp diff --git a/zone/bot_commands/spell_target_count.cpp b/zone/bot_commands/bot_spell_target_count.cpp similarity index 100% rename from zone/bot_commands/spell_target_count.cpp rename to zone/bot_commands/bot_spell_target_count.cpp diff --git a/zone/bot_commands/spelltypes.cpp b/zone/bot_commands/bot_spelltypes.cpp similarity index 100% rename from zone/bot_commands/spelltypes.cpp rename to zone/bot_commands/bot_spelltypes.cpp diff --git a/zone/bot_commands/summon.cpp b/zone/bot_commands/bot_summon.cpp similarity index 100% rename from zone/bot_commands/summon.cpp rename to zone/bot_commands/bot_summon.cpp diff --git a/zone/bot_commands/suspend.cpp b/zone/bot_commands/bot_suspend.cpp similarity index 100% rename from zone/bot_commands/suspend.cpp rename to zone/bot_commands/bot_suspend.cpp diff --git a/zone/bot_commands/taunt.cpp b/zone/bot_commands/bot_taunt.cpp similarity index 100% rename from zone/bot_commands/taunt.cpp rename to zone/bot_commands/bot_taunt.cpp diff --git a/zone/bot_commands/timer.cpp b/zone/bot_commands/bot_timer.cpp similarity index 100% rename from zone/bot_commands/timer.cpp rename to zone/bot_commands/bot_timer.cpp diff --git a/zone/bot_commands/track.cpp b/zone/bot_commands/bot_track.cpp similarity index 100% rename from zone/bot_commands/track.cpp rename to zone/bot_commands/bot_track.cpp diff --git a/zone/bot_commands/view_combos.cpp b/zone/bot_commands/bot_view_combos.cpp similarity index 100% rename from zone/bot_commands/view_combos.cpp rename to zone/bot_commands/bot_view_combos.cpp diff --git a/zone/cli/benchmark_databuckets.cpp b/zone/cli/cli_benchmark_databuckets.cpp similarity index 96% rename from zone/cli/benchmark_databuckets.cpp rename to zone/cli/cli_benchmark_databuckets.cpp index af0dcb84a6..d2d1dc01cb 100644 --- a/zone/cli/benchmark_databuckets.cpp +++ b/zone/cli/cli_benchmark_databuckets.cpp @@ -1,6 +1,8 @@ #include #include #include +#include "../zone_cli.h" +#include "../../common/cli/eqemu_command_handler.h" #include "../../common/http/httplib.h" #include "../../common/eqemu_logsys.h" #include "../sidecar_api/sidecar_api.h" @@ -116,7 +118,7 @@ void RunBenchmarkCycle(uint64_t target_rows) break; } - DataBucket::SetData(e); + DataBucket::SetData(&database, e); inserted_keys.emplace_back(e); } @@ -129,7 +131,7 @@ void RunBenchmarkCycle(uint64_t target_rows) auto update_start = std::chrono::high_resolution_clock::now(); for (auto &key: inserted_keys) { // 🔠Retrieve existing bucket using scoped `GetData` - auto e = DataBucket::GetData(key); + auto e = DataBucket::GetData(&database, key); if (e.id > 0) { // create a new key object with the updated values DataBucketKey bucket_entry_key{ @@ -145,7 +147,7 @@ void RunBenchmarkCycle(uint64_t target_rows) }; // 🔄 Update using DataBucket class - DataBucket::SetData(bucket_entry_key); + DataBucket::SetData(&database, bucket_entry_key); } } auto update_end = std::chrono::high_resolution_clock::now(); @@ -188,7 +190,7 @@ void RunBenchmarkCycle(uint64_t target_rows) k.instance_id = entity_choice; } - DataBucket::GetData(key); + DataBucket::GetData(&database, key); } auto read_cached_end = std::chrono::high_resolution_clock::now(); std::chrono::duration read_cached_time = read_cached_end - read_cached_start; @@ -206,7 +208,7 @@ void RunBenchmarkCycle(uint64_t target_rows) .character_id = 999999999, // use scoped value }; - DataBucket::GetData(k); + DataBucket::GetData(&database, k); } auto read_client_cache_miss_end = std::chrono::high_resolution_clock::now(); std::chrono::duration read_client_cache_miss_time = read_client_cache_miss_end - read_client_cache_miss_start; @@ -260,7 +262,7 @@ void RunBenchmarkCycle(uint64_t target_rows) k.instance_id = entity_choice; } - DataBucket::DeleteData(k); + DataBucket::DeleteData(&database, k); } auto delete_end = std::chrono::high_resolution_clock::now(); std::chrono::duration delete_time = delete_end - delete_start; diff --git a/zone/cli/sidecar_serve_http.cpp b/zone/cli/cli_sidecar_serve_http.cpp similarity index 88% rename from zone/cli/sidecar_serve_http.cpp rename to zone/cli/cli_sidecar_serve_http.cpp index 334ef3eff5..7e82f89434 100644 --- a/zone/cli/sidecar_serve_http.cpp +++ b/zone/cli/cli_sidecar_serve_http.cpp @@ -1,3 +1,5 @@ +#include "../zone_cli.h" +#include "../../common/cli/eqemu_command_handler.h" #include "../../common/http/httplib.h" #include "../../common/eqemu_logsys.h" #include "../sidecar_api/sidecar_api.h" diff --git a/zone/cli/tests/databuckets.cpp b/zone/cli/tests/cli_databuckets.cpp similarity index 97% rename from zone/cli/tests/databuckets.cpp rename to zone/cli/tests/cli_databuckets.cpp index 28a3604d40..7974c06d21 100644 --- a/zone/cli/tests/databuckets.cpp +++ b/zone/cli/tests/cli_databuckets.cpp @@ -1,3 +1,5 @@ +#include "../../zone_cli.h" +#include "../../common/cli/eqemu_command_handler.h" #include "../../common/http/httplib.h" #include "../../common/eqemu_logsys.h" #include "../../common/platform.h" @@ -7,6 +9,10 @@ extern Zone* zone; +void RunTest(const std::string& test_name, const std::string& expected, const std::string& actual); +void RunTest(const std::string& test_name, bool expected, bool actual); +void RunTest(const std::string& test_name, int expected, int actual); + void ZoneCLI::TestDataBuckets(int argc, char** argv, argh::parser& cmd, std::string& description) { if (cmd[{"-h", "--help"}]) { diff --git a/zone/cli/tests/npc_handins.cpp b/zone/cli/tests/cli_npc_handins.cpp similarity index 97% rename from zone/cli/tests/npc_handins.cpp rename to zone/cli/tests/cli_npc_handins.cpp index c9eed484d1..da606cf230 100644 --- a/zone/cli/tests/npc_handins.cpp +++ b/zone/cli/tests/cli_npc_handins.cpp @@ -1,3 +1,5 @@ +#include "../../zone_cli.h" +#include "../../common/cli/eqemu_command_handler.h" #include "../../common/http/httplib.h" #include "../../common/eqemu_logsys.h" #include "../../common/platform.h" @@ -9,6 +11,10 @@ extern Zone *zone; using json = nlohmann::json; +void RunTest(const std::string& test_name, const std::string& expected, const std::string& actual); +void RunTest(const std::string& test_name, bool expected, bool actual); +void RunTest(const std::string& test_name, int expected, int actual); + struct HandinEntry { std::string item_id = "0"; uint32 count = 0; diff --git a/zone/cli/tests/npc_handins_multiquest.cpp b/zone/cli/tests/cli_npc_handins_multiquest.cpp similarity index 93% rename from zone/cli/tests/npc_handins_multiquest.cpp rename to zone/cli/tests/cli_npc_handins_multiquest.cpp index 1c560cdc9c..faaffb765e 100644 --- a/zone/cli/tests/npc_handins_multiquest.cpp +++ b/zone/cli/tests/cli_npc_handins_multiquest.cpp @@ -1,3 +1,5 @@ +#include "../../zone_cli.h" +#include "../../common/cli/eqemu_command_handler.h" #include "../../common/eqemu_logsys.h" #include "../../common/platform.h" #include "../../zone.h" @@ -6,6 +8,10 @@ extern Zone *zone; +void RunTest(const std::string& test_name, const std::string& expected, const std::string& actual); +void RunTest(const std::string& test_name, bool expected, bool actual); +void RunTest(const std::string& test_name, int expected, int actual); + void ZoneCLI::TestNpcHandinsMultiQuest(int argc, char **argv, argh::parser &cmd, std::string &description) { if (cmd[{"-h", "--help"}]) { diff --git a/zone/cli/tests/_test_util.cpp b/zone/cli/tests/cli_test_util.cpp similarity index 81% rename from zone/cli/tests/_test_util.cpp rename to zone/cli/tests/cli_test_util.cpp index 0bd1181667..3f6e7fe2e0 100644 --- a/zone/cli/tests/_test_util.cpp +++ b/zone/cli/tests/cli_test_util.cpp @@ -1,6 +1,6 @@ #include "../../zone.h" -inline void RunTest(const std::string &test_name, const std::string &expected, const std::string &actual) +void RunTest(const std::string &test_name, const std::string &expected, const std::string &actual) { if (expected == actual) { std::cout << "[✅] " << test_name << " PASSED\n"; @@ -12,7 +12,7 @@ inline void RunTest(const std::string &test_name, const std::string &expected, c } } -inline void RunTest(const std::string &test_name, bool expected, bool actual) +void RunTest(const std::string &test_name, bool expected, bool actual) { if (expected == actual) { std::cout << "[✅] " << test_name << " PASSED\n"; @@ -25,7 +25,7 @@ inline void RunTest(const std::string &test_name, bool expected, bool actual) } } -inline void RunTest(const std::string &test_name, int expected, int actual) +void RunTest(const std::string &test_name, int expected, int actual) { if (expected == actual) { std::cout << "[✅] " << test_name << " PASSED\n"; @@ -40,7 +40,7 @@ inline void RunTest(const std::string &test_name, int expected, int actual) extern Zone *zone; -inline void SetupZone(std::string zone_short_name, uint32 instance_id = 0) { +void SetupZone(std::string zone_short_name, uint32 instance_id = 0) { EQEmuLogSys::Instance()->SilenceConsoleLogging(); EQEmuLogSys::Instance()->log_settings[Logs::ZoneState].log_to_console = std::getenv("DEBUG") ? 3 : 0; diff --git a/zone/cli/tests/zone_state.cpp b/zone/cli/tests/cli_zone_state.cpp similarity index 98% rename from zone/cli/tests/zone_state.cpp rename to zone/cli/tests/cli_zone_state.cpp index b527f5a4f6..235891fa50 100644 --- a/zone/cli/tests/zone_state.cpp +++ b/zone/cli/tests/cli_zone_state.cpp @@ -1,11 +1,18 @@ -extern Zone *zone; - +#include "../../zone_cli.h" +#include "../../common/cli/eqemu_command_handler.h" #include #include #include "../../common/repositories/npc_types_repository.h" #include "../../corpse.h" #include "../../../common/repositories/respawn_times_repository.h" +extern Zone* zone; + +void RunTest(const std::string& test_name, const std::string& expected, const std::string& actual); +void RunTest(const std::string& test_name, bool expected, bool actual); +void RunTest(const std::string& test_name, int expected, int actual); +void SetupZone(std::string zone_short_name, uint32 instance_id = 0); + inline void ClearState() { ZoneStateSpawnsRepository::DeleteWhere(database, "zone_id = 32 and instance_id = 0"); diff --git a/zone/client.cpp b/zone/client.cpp index 5ed9eddec1..07fa25ba6d 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -4840,7 +4840,7 @@ bool Client::IsNameChangeAllowed() { auto k = GetScopedBucketKeys(); k.key = "name_change_allowed"; - auto b = DataBucket::GetData(k); + auto b = DataBucket::GetData(&database, k); if (!b.value.empty()) { return true; } @@ -4856,7 +4856,7 @@ bool Client::ClearNameChange() { auto k = GetScopedBucketKeys(); k.key = "name_change_allowed"; - DataBucket::DeleteData(k); + DataBucket::DeleteData(&database, k); return true; } @@ -4878,7 +4878,7 @@ void Client::GrantNameChange() { auto k = GetScopedBucketKeys(); k.key = "name_change_allowed"; k.value = "allowed"; // potentially put a timestamp here - DataBucket::SetData(k); + DataBucket::SetData(&database, k); InvokeChangeNameWindow(true); } @@ -4891,7 +4891,7 @@ bool Client::IsPetNameChangeAllowed() { DataBucketKey k = GetScopedBucketKeys(); k.key = "PetNameChangesAllowed"; - auto b = DataBucket::GetData(k); + auto b = DataBucket::GetData(&database, k); if (!b.value.empty()) { return true; } @@ -4915,7 +4915,7 @@ void Client::GrantPetNameChange() { DataBucketKey k = GetScopedBucketKeys(); k.key = "PetNameChangesAllowed"; k.value = "true"; - DataBucket::SetData(k); + DataBucket::SetData(&database, k); InvokeChangePetName(true); } @@ -4924,7 +4924,7 @@ void Client::ClearPetNameChange() { DataBucketKey k = GetScopedBucketKeys(); k.key = "PetNameChangesAllowed"; - DataBucket::DeleteData(k); + DataBucket::DeleteData(&database, k); } bool Client::ChangePetName(std::string new_name) @@ -9671,9 +9671,9 @@ void Client::SetDevToolsEnabled(bool in_dev_tools_enabled) const auto dev_tools_key = fmt::format("{}-dev-tools-disabled", AccountID()); if (in_dev_tools_enabled) { - DataBucket::DeleteData(dev_tools_key); + DataBucket::DeleteData(&database, dev_tools_key); } else { - DataBucket::SetData(dev_tools_key, "true"); + DataBucket::SetData(&database, dev_tools_key, "true"); } Client::dev_tools_enabled = in_dev_tools_enabled; @@ -9846,7 +9846,7 @@ void Client::SendToGuildHall() uint32 expiration_time = (RuleI(Instances, GuildHallExpirationDays) * 86400); uint16 instance_id = 0; std::string guild_hall_instance_key = fmt::format("guild-hall-instance-{}", GuildID()); - std::string instance_data = DataBucket::GetData(guild_hall_instance_key); + std::string instance_data = DataBucket::GetData(&database, guild_hall_instance_key); if (!instance_data.empty() && Strings::ToInt(instance_data) > 0) { instance_id = Strings::ToInt(instance_data); } @@ -9863,6 +9863,7 @@ void Client::SendToGuildHall() } DataBucket::SetData( + &database, guild_hall_instance_key, std::to_string(instance_id), std::to_string(expiration_time) @@ -10915,7 +10916,7 @@ void Client::SendToInstance(std::string instance_type, std::string zone_short_na instance_identifier, zone_short_name ); - std::string current_bucket_value = DataBucket::GetData(full_bucket_name); + std::string current_bucket_value = DataBucket::GetData(&database, full_bucket_name); uint16 instance_id = 0; if (current_bucket_value.length() > 0) { @@ -10931,7 +10932,7 @@ void Client::SendToInstance(std::string instance_type, std::string zone_short_na return; } - DataBucket::SetData(full_bucket_name, itoa(instance_id), itoa(duration)); + DataBucket::SetData(&database, full_bucket_name, itoa(instance_id), itoa(duration)); } AssignToInstance(instance_id); @@ -13149,7 +13150,7 @@ std::string Client::GetAccountBucket(std::string bucket_name) k.account_id = AccountID(); k.key = bucket_name; - return DataBucket::GetData(k).value; + return DataBucket::GetData(&database, k).value; } void Client::SetAccountBucket(std::string bucket_name, std::string bucket_value, std::string expiration) @@ -13160,7 +13161,7 @@ void Client::SetAccountBucket(std::string bucket_name, std::string bucket_value, k.expires = expiration; k.value = bucket_value; - DataBucket::SetData(k); + DataBucket::SetData(&database, k); } void Client::DeleteAccountBucket(std::string bucket_name) @@ -13169,7 +13170,7 @@ void Client::DeleteAccountBucket(std::string bucket_name) k.account_id = AccountID(); k.key = bucket_name; - DataBucket::DeleteData(k); + DataBucket::DeleteData(&database, k); } std::string Client::GetAccountBucketExpires(std::string bucket_name) @@ -13178,7 +13179,7 @@ std::string Client::GetAccountBucketExpires(std::string bucket_name) k.account_id = AccountID(); k.key = bucket_name; - return DataBucket::GetDataExpires(k); + return DataBucket::GetDataExpires(&database, k); } std::string Client::GetAccountBucketRemaining(std::string bucket_name) @@ -13187,7 +13188,7 @@ std::string Client::GetAccountBucketRemaining(std::string bucket_name) k.account_id = AccountID(); k.key = bucket_name; - return DataBucket::GetDataRemaining(k); + return DataBucket::GetDataRemaining(&database, k); } std::string Client::GetBandolierName(uint8 bandolier_slot) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a059bef659..c7bb4a05c8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1853,7 +1853,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) */ if (Admin() >= EQ::DevTools::GM_ACCOUNT_STATUS_LEVEL) { const auto dev_tools_key = fmt::format("{}-dev-tools-disabled", AccountID()); - if (DataBucket::GetData(dev_tools_key) == "true") { + if (DataBucket::GetData(&database, dev_tools_key) == "true") { dev_tools_enabled = false; } } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index e14985763d..19440e3bb1 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -874,7 +874,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { DataBucketKey k = GetScopedBucketKeys(); k.key = bucket_name; - auto b = DataBucket::GetData(k); + auto b = DataBucket::GetData(&database, k); if (b.value.empty()) { continue; } diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index feedab7fd4..b56cb51d84 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -2485,27 +2485,27 @@ std::string Perl__get_rule(const char* rule_name) std::string Perl__get_data(std::string bucket_key) { - return DataBucket::GetData(bucket_key); + return DataBucket::GetData(&database, bucket_key); } std::string Perl__get_data_expires(std::string bucket_key) { - return DataBucket::GetDataExpires(bucket_key); + return DataBucket::GetDataExpires(&database, bucket_key); } void Perl__set_data(std::string key, std::string value) { - DataBucket::SetData(key, value); + DataBucket::SetData(&database, key, value); } void Perl__set_data(std::string key, std::string value, std::string expires_at) { - DataBucket::SetData(key, value, expires_at); + DataBucket::SetData(&database, key, value, expires_at); } bool Perl__delete_data(std::string bucket_key) { - return DataBucket::DeleteData(bucket_key); + return DataBucket::DeleteData(&database, bucket_key); } bool Perl__IsClassicEnabled() @@ -3045,7 +3045,7 @@ void Perl__rename(std::string name) std::string Perl__get_data_remaining(std::string bucket_name) { - return DataBucket::GetDataRemaining(bucket_name); + return DataBucket::GetDataRemaining(&database, bucket_name); } const int Perl__getitemstat(uint32 item_id, std::string identifier) diff --git a/zone/embperl.cpp b/zone/embperl.cpp index b48c714e3b..75bc1793c6 100644 --- a/zone/embperl.cpp +++ b/zone/embperl.cpp @@ -75,15 +75,15 @@ void Embperl::DoInit() throw "Failed to init Perl (perl_alloc)"; } PERL_SET_CONTEXT(my_perl); - PERL_SET_INTERP(my_perl); + PL_curinterp = (PerlInterpreter*)(my_perl); PL_perl_destruct_level = 1; perl_construct(my_perl); perl_parse(my_perl, xs_init, argc, argv, nullptr); perl_run(my_perl); - + //a little routine we use a lot. eval_pv("sub my_eval { eval $_[0];}", TRUE); //dies on error - + //ruin the perl exit and command: eval_pv("sub my_exit {}", TRUE); eval_pv("sub my_sleep {}", TRUE); @@ -95,7 +95,7 @@ void Embperl::DoInit() GvCV_set(sleepgp, perl_get_cv("my_sleep", TRUE)); //dies on error GvIMPORTED_CV_on(sleepgp); } - + //declare our file eval routine. try { init_eval_file(); @@ -181,7 +181,7 @@ Embperl::~Embperl() void Embperl::Reinit() { PERL_SET_CONTEXT(my_perl); - PERL_SET_INTERP(my_perl); + PL_curinterp = (PerlInterpreter*)(my_perl); PL_perl_destruct_level = 1; perl_destruct(my_perl); perl_free(my_perl); diff --git a/zone/exp.cpp b/zone/exp.cpp index e3016f8b25..1f64d8b712 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -1299,7 +1299,7 @@ uint8 Client::GetCharMaxLevelFromBucket() DataBucketKey k = GetScopedBucketKeys(); k.key = "CharMaxLevel"; - auto b = DataBucket::GetData(k); + auto b = DataBucket::GetData(&database, k); if (!b.value.empty()) { if (Strings::IsNumber(b.value)) { return static_cast(Strings::ToUnsignedInt(b.value)); diff --git a/zone/gm_commands/CMakeLists.txt b/zone/gm_commands/CMakeLists.txt new file mode 100644 index 0000000000..01af3a4267 --- /dev/null +++ b/zone/gm_commands/CMakeLists.txt @@ -0,0 +1,169 @@ +cmake_minimum_required(VERSION 3.20) + +# gm commands +set(gm_command_sources + command.cpp + bot_command.cpp + gm_commands/acceptrules.cpp + gm_commands/advnpcspawn.cpp + gm_commands/aggrozone.cpp + gm_commands/ai.cpp + gm_commands/appearance.cpp + gm_commands/appearanceeffects.cpp + gm_commands/attack.cpp + gm_commands/augmentitem.cpp + gm_commands/ban.cpp + gm_commands/bugs.cpp + gm_commands/camerashake.cpp + gm_commands/castspell.cpp + gm_commands/chat.cpp + gm_commands/clearxtargets.cpp + gm_commands/copycharacter.cpp + gm_commands/corpse.cpp + gm_commands/corpsefix.cpp + gm_commands/countitem.cpp + gm_commands/damage.cpp + gm_commands/databuckets.cpp + gm_commands/dbspawn2.cpp + gm_commands/delacct.cpp + gm_commands/delpetition.cpp + gm_commands/depop.cpp + gm_commands/depopzone.cpp + gm_commands/devtools.cpp + gm_commands/disablerecipe.cpp + gm_commands/disarmtrap.cpp + gm_commands/doanim.cpp + gm_commands/door.cpp + gm_commands/door_manipulation.cpp + gm_commands/dye.cpp + gm_commands/dz.cpp + gm_commands/dzkickplayers.cpp + gm_commands/editmassrespawn.cpp + gm_commands/emote.cpp + gm_commands/emptyinventory.cpp + gm_commands/enablerecipe.cpp + gm_commands/entityvariable.cpp + gm_commands/exptoggle.cpp + gm_commands/faction.cpp + gm_commands/evolving_items.cpp + gm_commands/feature.cpp + gm_commands/find.cpp + gm_commands/fish.cpp + gm_commands/fixmob.cpp + gm_commands/flagedit.cpp + gm_commands/fleeinfo.cpp + gm_commands/forage.cpp + gm_commands/gearup.cpp + gm_commands/giveitem.cpp + gm_commands/givemoney.cpp + gm_commands/gmzone.cpp + gm_commands/goto.cpp + gm_commands/grantaa.cpp + gm_commands/grid.cpp + gm_commands/guild.cpp + gm_commands/hp.cpp + gm_commands/illusion_block.cpp + gm_commands/instance.cpp + gm_commands/interrogateinv.cpp + gm_commands/interrupt.cpp + gm_commands/invsnapshot.cpp + gm_commands/ipban.cpp + gm_commands/kick.cpp + gm_commands/kill.cpp + gm_commands/killallnpcs.cpp + gm_commands/list.cpp + gm_commands/lootsim.cpp + gm_commands/loc.cpp + gm_commands/logs.cpp + gm_commands/makepet.cpp + gm_commands/memspell.cpp + gm_commands/merchantshop.cpp + gm_commands/modifynpcstat.cpp + gm_commands/movechar.cpp + gm_commands/movement.cpp + gm_commands/myskills.cpp + gm_commands/mysql.cpp + gm_commands/mystats.cpp + gm_commands/npccast.cpp + gm_commands/npcedit.cpp + gm_commands/npceditmass.cpp + gm_commands/npcemote.cpp + gm_commands/npcloot.cpp + gm_commands/npcsay.cpp + gm_commands/npcshout.cpp + gm_commands/npcspawn.cpp + gm_commands/npctypespawn.cpp + gm_commands/nudge.cpp + gm_commands/nukebuffs.cpp + gm_commands/nukeitem.cpp + gm_commands/object.cpp + gm_commands/object_manipulation.cpp + gm_commands/parcels.cpp + gm_commands/path.cpp + gm_commands/peqzone.cpp + gm_commands/petitems.cpp + gm_commands/petname.cpp + gm_commands/picklock.cpp + gm_commands/profanity.cpp + gm_commands/push.cpp + gm_commands/raidloot.cpp + gm_commands/randomfeatures.cpp + gm_commands/refreshgroup.cpp + gm_commands/reload.cpp + gm_commands/removeitem.cpp + gm_commands/repop.cpp + gm_commands/resetaa.cpp + gm_commands/resetaa_timer.cpp + gm_commands/resetdisc_timer.cpp + gm_commands/revoke.cpp + gm_commands/roambox.cpp + gm_commands/rules.cpp + gm_commands/save.cpp + gm_commands/scale.cpp + gm_commands/scribespell.cpp + gm_commands/scribespells.cpp + gm_commands/sendzonespawns.cpp + gm_commands/sensetrap.cpp + gm_commands/serverrules.cpp + gm_commands/set.cpp + gm_commands/show.cpp + gm_commands/shutdown.cpp + gm_commands/spawn.cpp + gm_commands/spawneditmass.cpp + gm_commands/spawnfix.cpp + gm_commands/faction_association.cpp + gm_commands/stun.cpp + gm_commands/summon.cpp + gm_commands/summonburiedplayercorpse.cpp + gm_commands/summonitem.cpp + gm_commands/suspend.cpp + gm_commands/suspendmulti.cpp + gm_commands/takeplatinum.cpp + gm_commands/task.cpp + gm_commands/traindisc.cpp + gm_commands/tune.cpp + gm_commands/undye.cpp + gm_commands/unmemspell.cpp + gm_commands/unmemspells.cpp + gm_commands/unscribespell.cpp + gm_commands/unscribespells.cpp + gm_commands/untraindisc.cpp + gm_commands/untraindiscs.cpp + gm_commands/wc.cpp + gm_commands/worldshutdown.cpp + gm_commands/worldwide.cpp + gm_commands/wp.cpp + gm_commands/wpadd.cpp + gm_commands/zone.cpp + gm_commands/zonebootup.cpp + gm_commands/zoneshutdown.cpp + gm_commands/zonevariable.cpp + gm_commands/zone_instance.cpp + gm_commands/zone_shard.cpp + gm_commands/zsave.cpp +) + +add_library(gm_commands_zone STATIC ${gm_command_sources}) +target_link_libraries(gm_commands_zone PRIVATE common) +set_target_properties(gm_commands_zone PROPERTIES UNITY_BUILD ON UNITY_BUILD_BATCH_SIZE 32) + diff --git a/zone/gm_commands/databuckets.cpp b/zone/gm_commands/databuckets.cpp index af78f528ec..ca2b17808a 100755 --- a/zone/gm_commands/databuckets.cpp +++ b/zone/gm_commands/databuckets.cpp @@ -50,7 +50,7 @@ void command_databuckets(Client *c, const Seperator *sep) !npc_id && !bot_id ) { - if (!DataBucket::DeleteData(key_filter)) { + if (!DataBucket::DeleteData(&database, key_filter)) { c->Message( Chat::White, fmt::format( @@ -76,7 +76,7 @@ void command_databuckets(Client *c, const Seperator *sep) k.npc_id = npc_id; k.bot_id = bot_id; - if (!DataBucket::DeleteData(k)) { + if (!DataBucket::DeleteData(&database, k)) { c->Message( Chat::White, fmt::format( @@ -123,7 +123,7 @@ void command_databuckets(Client *c, const Seperator *sep) const std::string& expires_string = expires == 0 ? "Never" : std::to_string(expires); - DataBucket::SetData(k); + DataBucket::SetData(&database, k); c->Message( Chat::White, diff --git a/zone/gm_commands/find.cpp b/zone/gm_commands/find.cpp index 6ee5815cb4..a5e2bad3d2 100644 --- a/zone/gm_commands/find.cpp +++ b/zone/gm_commands/find.cpp @@ -1,29 +1,30 @@ #include "../client.h" -#include "find/aa.cpp" -#include "find/account.cpp" -#include "find/body_type.cpp" -#include "find/bot.cpp" -#include "find/bug_category.cpp" -#include "find/character.cpp" -#include "find/class.cpp" -#include "find/comparison_type.cpp" -#include "find/currency.cpp" -#include "find/deity.cpp" -#include "find/emote.cpp" -#include "find/faction.cpp" -#include "find/item.cpp" -#include "find/language.cpp" -#include "find/ldon_theme.cpp" -#include "find/npctype.cpp" -#include "find/object_type.cpp" -#include "find/race.cpp" -#include "find/recipe.cpp" -#include "find/skill.cpp" -#include "find/stance.cpp" -#include "find/spell.cpp" -#include "find/special_ability.cpp" -#include "find/task.cpp" -#include "find/zone.cpp" + +void FindAA(Client* c, const Seperator* sep); +void FindAccount(Client* c, const Seperator* sep); +void FindBodyType(Client* c, const Seperator* sep); +void FindBot(Client* c, const Seperator* sep); +void FindBugCategory(Client* c, const Seperator* sep); +void FindCharacter(Client* c, const Seperator* sep); +void FindClass(Client* c, const Seperator* sep); +void FindComparisonType(Client* c, const Seperator* sep); +void FindCurrency(Client* c, const Seperator* sep); +void FindDeity(Client* c, const Seperator* sep); +void FindEmote(Client* c, const Seperator* sep); +void FindFaction(Client* c, const Seperator* sep); +void FindItem(Client* c, const Seperator* sep); +void FindLanguage(Client* c, const Seperator* sep); +void FindLDoNTheme(Client* c, const Seperator* sep); +void FindNPCType(Client* c, const Seperator* sep); +void FindObjectType(Client* c, const Seperator* sep); +void FindRace(Client* c, const Seperator* sep); +void FindRecipe(Client* c, const Seperator* sep); +void FindSkill(Client* c, const Seperator* sep); +void FindSpecialAbility(Client* c, const Seperator* sep); +void FindStance(Client* c, const Seperator* sep); +void FindSpell(Client* c, const Seperator* sep); +void FindTask(Client* c, const Seperator* sep); +void FindZone(Client* c, const Seperator* sep); void command_find(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/aa.cpp b/zone/gm_commands/find/find_aa.cpp similarity index 100% rename from zone/gm_commands/find/aa.cpp rename to zone/gm_commands/find/find_aa.cpp diff --git a/zone/gm_commands/find/account.cpp b/zone/gm_commands/find/find_account.cpp similarity index 94% rename from zone/gm_commands/find/account.cpp rename to zone/gm_commands/find/find_account.cpp index 1265c8431f..17512b2a8a 100644 --- a/zone/gm_commands/find/account.cpp +++ b/zone/gm_commands/find/find_account.cpp @@ -1,5 +1,5 @@ #include "../../client.h" -#include "../../common/repositories/account_repository.h" +#include "../../../common/repositories/account_repository.h" void FindAccount(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/body_type.cpp b/zone/gm_commands/find/find_body_type.cpp similarity index 100% rename from zone/gm_commands/find/body_type.cpp rename to zone/gm_commands/find/find_body_type.cpp diff --git a/zone/gm_commands/find/bot.cpp b/zone/gm_commands/find/find_bot.cpp similarity index 96% rename from zone/gm_commands/find/bot.cpp rename to zone/gm_commands/find/find_bot.cpp index 061d4c4287..fd403d6707 100644 --- a/zone/gm_commands/find/bot.cpp +++ b/zone/gm_commands/find/find_bot.cpp @@ -1,5 +1,5 @@ #include "../../client.h" -#include "../../common/repositories/bot_data_repository.h" +#include "../../../common/repositories/bot_data_repository.h" void FindBot(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/bug_category.cpp b/zone/gm_commands/find/find_bug_category.cpp similarity index 100% rename from zone/gm_commands/find/bug_category.cpp rename to zone/gm_commands/find/find_bug_category.cpp diff --git a/zone/gm_commands/find/character.cpp b/zone/gm_commands/find/find_character.cpp similarity index 95% rename from zone/gm_commands/find/character.cpp rename to zone/gm_commands/find/find_character.cpp index 9029c252e0..0c1842eff2 100644 --- a/zone/gm_commands/find/character.cpp +++ b/zone/gm_commands/find/find_character.cpp @@ -1,5 +1,5 @@ #include "../../client.h" -#include "../../common/repositories/character_data_repository.h" +#include "../../../common/repositories/character_data_repository.h" void FindCharacter(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/class.cpp b/zone/gm_commands/find/find_class.cpp similarity index 100% rename from zone/gm_commands/find/class.cpp rename to zone/gm_commands/find/find_class.cpp diff --git a/zone/gm_commands/find/comparison_type.cpp b/zone/gm_commands/find/find_comparison_type.cpp similarity index 100% rename from zone/gm_commands/find/comparison_type.cpp rename to zone/gm_commands/find/find_comparison_type.cpp diff --git a/zone/gm_commands/find/currency.cpp b/zone/gm_commands/find/find_currency.cpp similarity index 100% rename from zone/gm_commands/find/currency.cpp rename to zone/gm_commands/find/find_currency.cpp diff --git a/zone/gm_commands/find/deity.cpp b/zone/gm_commands/find/find_deity.cpp similarity index 100% rename from zone/gm_commands/find/deity.cpp rename to zone/gm_commands/find/find_deity.cpp diff --git a/zone/gm_commands/find/emote.cpp b/zone/gm_commands/find/find_emote.cpp similarity index 100% rename from zone/gm_commands/find/emote.cpp rename to zone/gm_commands/find/find_emote.cpp diff --git a/zone/gm_commands/find/faction.cpp b/zone/gm_commands/find/find_faction.cpp similarity index 100% rename from zone/gm_commands/find/faction.cpp rename to zone/gm_commands/find/find_faction.cpp diff --git a/zone/gm_commands/find/item.cpp b/zone/gm_commands/find/find_item.cpp similarity index 97% rename from zone/gm_commands/find/item.cpp rename to zone/gm_commands/find/find_item.cpp index 7963e8cb6a..0f48707011 100644 --- a/zone/gm_commands/find/item.cpp +++ b/zone/gm_commands/find/find_item.cpp @@ -1,5 +1,5 @@ #include "../../client.h" -#include "../../common/repositories/items_repository.h" +#include "../../../common/repositories/items_repository.h" void FindItem(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/language.cpp b/zone/gm_commands/find/find_language.cpp similarity index 100% rename from zone/gm_commands/find/language.cpp rename to zone/gm_commands/find/find_language.cpp diff --git a/zone/gm_commands/find/ldon_theme.cpp b/zone/gm_commands/find/find_ldon_theme.cpp similarity index 100% rename from zone/gm_commands/find/ldon_theme.cpp rename to zone/gm_commands/find/find_ldon_theme.cpp diff --git a/zone/gm_commands/find/npctype.cpp b/zone/gm_commands/find/find_npctype.cpp similarity index 100% rename from zone/gm_commands/find/npctype.cpp rename to zone/gm_commands/find/find_npctype.cpp diff --git a/zone/gm_commands/find/object_type.cpp b/zone/gm_commands/find/find_object_type.cpp similarity index 100% rename from zone/gm_commands/find/object_type.cpp rename to zone/gm_commands/find/find_object_type.cpp diff --git a/zone/gm_commands/find/race.cpp b/zone/gm_commands/find/find_race.cpp similarity index 100% rename from zone/gm_commands/find/race.cpp rename to zone/gm_commands/find/find_race.cpp diff --git a/zone/gm_commands/find/recipe.cpp b/zone/gm_commands/find/find_recipe.cpp similarity index 96% rename from zone/gm_commands/find/recipe.cpp rename to zone/gm_commands/find/find_recipe.cpp index 5aefe10449..260c6dccf9 100644 --- a/zone/gm_commands/find/recipe.cpp +++ b/zone/gm_commands/find/find_recipe.cpp @@ -1,6 +1,6 @@ #include "../../client.h" #include "../../command.h" -#include "../../common/repositories/tradeskill_recipe_repository.h" +#include "../../../common/repositories/tradeskill_recipe_repository.h" void FindRecipe(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/skill.cpp b/zone/gm_commands/find/find_skill.cpp similarity index 100% rename from zone/gm_commands/find/skill.cpp rename to zone/gm_commands/find/find_skill.cpp diff --git a/zone/gm_commands/find/special_ability.cpp b/zone/gm_commands/find/find_special_ability.cpp similarity index 100% rename from zone/gm_commands/find/special_ability.cpp rename to zone/gm_commands/find/find_special_ability.cpp diff --git a/zone/gm_commands/find/spell.cpp b/zone/gm_commands/find/find_spell.cpp similarity index 97% rename from zone/gm_commands/find/spell.cpp rename to zone/gm_commands/find/find_spell.cpp index ddfc832705..b5f1a88e83 100644 --- a/zone/gm_commands/find/spell.cpp +++ b/zone/gm_commands/find/find_spell.cpp @@ -1,5 +1,7 @@ #include "../../client.h" +uint8 GetCommandStatus(std::string command_name); + void FindSpell(Client *c, const Seperator *sep) { if (SPDAT_RECORDS <= 0) { diff --git a/zone/gm_commands/find/stance.cpp b/zone/gm_commands/find/find_stance.cpp similarity index 100% rename from zone/gm_commands/find/stance.cpp rename to zone/gm_commands/find/find_stance.cpp diff --git a/zone/gm_commands/find/task.cpp b/zone/gm_commands/find/find_task.cpp similarity index 97% rename from zone/gm_commands/find/task.cpp rename to zone/gm_commands/find/find_task.cpp index c51f1892d7..0873ebe30b 100644 --- a/zone/gm_commands/find/task.cpp +++ b/zone/gm_commands/find/find_task.cpp @@ -1,5 +1,7 @@ #include "../../client.h" +uint8 GetCommandStatus(std::string command_name); + void FindTask(Client *c, const Seperator *sep) { if (!RuleB(TaskSystem, EnableTaskSystem)) { diff --git a/zone/gm_commands/find/zone.cpp b/zone/gm_commands/find/find_zone.cpp similarity index 98% rename from zone/gm_commands/find/zone.cpp rename to zone/gm_commands/find/find_zone.cpp index c943f3e1d5..6715649d99 100644 --- a/zone/gm_commands/find/zone.cpp +++ b/zone/gm_commands/find/find_zone.cpp @@ -1,5 +1,5 @@ #include "../../client.h" -#include "../../common/content/world_content_service.h" +#include "../../../common/content/world_content_service.h" void FindZone(Client* c, const Seperator* sep) { diff --git a/zone/gm_commands/fixmob.cpp b/zone/gm_commands/fixmob.cpp index 14cf3e9801..d691b0f2ef 100755 --- a/zone/gm_commands/fixmob.cpp +++ b/zone/gm_commands/fixmob.cpp @@ -1,5 +1,21 @@ #include "../client.h" +void SendFixMobSubCommands(Client* c) +{ + c->Message(Chat::White, "Usage: #fixmob beard [Next|Previous]"); + c->Message(Chat::White, "Usage: #fixmob beard_color [Next|Previous]"); + c->Message(Chat::White, "Usage: #fixmob drakkin_details [Next|Previous]"); + c->Message(Chat::White, "Usage: #fixmob drakkin_heritage [Next|Previous]"); + c->Message(Chat::White, "Usage: #fixmob drakkin_tattoo [Next|Previous]"); + c->Message(Chat::White, "Usage: #fixmob face [Next|Previous]"); + c->Message(Chat::White, "Usage: #fixmob gender [Next|Previous]"); + c->Message(Chat::White, "Usage: #fixmob hair [Next|Previous]"); + c->Message(Chat::White, "Usage: #fixmob hair_color [Next|Previous]"); + c->Message(Chat::White, "Usage: #fixmob helm [Next|Previous]"); + c->Message(Chat::White, "Usage: #fixmob race [Next|Previous]"); + c->Message(Chat::White, "Usage: #fixmob texture [Next|Previous]"); +} + void command_fixmob(Client *c, const Seperator *sep) { const int arguments = sep->argnum; @@ -269,18 +285,3 @@ void command_fixmob(Client *c, const Seperator *sep) ); } -void SendFixMobSubCommands(Client *c) -{ - c->Message(Chat::White, "Usage: #fixmob beard [Next|Previous]"); - c->Message(Chat::White, "Usage: #fixmob beard_color [Next|Previous]"); - c->Message(Chat::White, "Usage: #fixmob drakkin_details [Next|Previous]"); - c->Message(Chat::White, "Usage: #fixmob drakkin_heritage [Next|Previous]"); - c->Message(Chat::White, "Usage: #fixmob drakkin_tattoo [Next|Previous]"); - c->Message(Chat::White, "Usage: #fixmob face [Next|Previous]"); - c->Message(Chat::White, "Usage: #fixmob gender [Next|Previous]"); - c->Message(Chat::White, "Usage: #fixmob hair [Next|Previous]"); - c->Message(Chat::White, "Usage: #fixmob hair_color [Next|Previous]"); - c->Message(Chat::White, "Usage: #fixmob helm [Next|Previous]"); - c->Message(Chat::White, "Usage: #fixmob race [Next|Previous]"); - c->Message(Chat::White, "Usage: #fixmob texture [Next|Previous]"); -} diff --git a/zone/gm_commands/gmzone.cpp b/zone/gm_commands/gmzone.cpp index a26a09d054..9aefd58bc7 100755 --- a/zone/gm_commands/gmzone.cpp +++ b/zone/gm_commands/gmzone.cpp @@ -58,7 +58,7 @@ void command_gmzone(Client *c, const Seperator *sep) zone_version ); - auto existing_zone_instance = DataBucket::GetData(bucket_key); + auto existing_zone_instance = DataBucket::GetData(&database, bucket_key); uint16 instance_id = 0; uint32 duration = 100000000; @@ -99,6 +99,7 @@ void command_gmzone(Client *c, const Seperator *sep) ); DataBucket::SetData( + &database, bucket_key, std::to_string(instance_id) ); diff --git a/zone/gm_commands/set.cpp b/zone/gm_commands/set.cpp index 654cab281d..1460ea029e 100644 --- a/zone/gm_commands/set.cpp +++ b/zone/gm_commands/set.cpp @@ -1,60 +1,61 @@ #include "../client.h" -#include "set/aa_exp.cpp" -#include "set/aa_points.cpp" -#include "set/adventure_points.cpp" -#include "set/alternate_currency.cpp" -#include "set/animation.cpp" -#include "set/anon.cpp" -#include "set/auto_login.cpp" -#include "set/bind_point.cpp" -#include "set/checksum.cpp" -#include "set/class_permanent.cpp" -#include "set/crystals.cpp" -#include "set/date.cpp" -#include "set/endurance.cpp" -#include "set/endurance_full.cpp" -#include "set/exp.cpp" -#include "set/flymode.cpp" -#include "set/frozen.cpp" -#include "set/gender.cpp" -#include "set/gender_permanent.cpp" -#include "set/gm.cpp" -#include "set/gm_speed.cpp" -#include "set/gm_status.cpp" -#include "set/god_mode.cpp" -#include "set/haste.cpp" -#include "set/hero_model.cpp" -#include "set/hide_me.cpp" -#include "set/hp.cpp" -#include "set/hp_full.cpp" -#include "set/invulnerable.cpp" -#include "set/language.cpp" -#include "set/last_name.cpp" -#include "set/level.cpp" -#include "set/loginserver_info.cpp" -#include "set/mana.cpp" -#include "set/mana_full.cpp" -#include "set/motd.cpp" -#include "set/name.cpp" -#include "set/ooc_mute.cpp" -#include "set/password.cpp" -#include "set/pvp.cpp" -#include "set/pvp_points.cpp" -#include "set/race.cpp" -#include "set/race_permanent.cpp" -#include "set/server_locked.cpp" -#include "set/skill.cpp" -#include "set/skill_all.cpp" -#include "set/skill_all_max.cpp" -#include "set/start_zone.cpp" -#include "set/temporary_name.cpp" -#include "set/texture.cpp" -#include "set/time.cpp" -#include "set/time_zone.cpp" -#include "set/title.cpp" -#include "set/title_suffix.cpp" -#include "set/weather.cpp" -#include "set/zone.cpp" + +void SetAAEXP(Client *c, const Seperator *sep); +void SetAAPoints(Client *c, const Seperator *sep); +void SetAdventurePoints(Client *c, const Seperator *sep); +void SetAlternateCurrency(Client *c, const Seperator *sep); +void SetAnimation(Client *c, const Seperator *sep); +void SetAnon(Client *c, const Seperator *sep); +void SetAutoLogin(Client *c, const Seperator *sep); +void SetBindPoint(Client *c, const Seperator *sep); +void SetChecksum(Client *c, const Seperator *sep); +void SetClassPermanent(Client *c, const Seperator *sep); +void SetCrystals(Client *c, const Seperator *sep); +void SetDate(Client *c, const Seperator *sep); +void SetEndurance(Client *c, const Seperator *sep); +void SetEnduranceFull(Client *c, const Seperator *sep); +void SetEXP(Client *c, const Seperator *sep); +void SetFlymode(Client *c, const Seperator *sep); +void SetFrozen(Client *c, const Seperator *sep); +void SetGender(Client *c, const Seperator *sep); +void SetGenderPermanent(Client *c, const Seperator *sep); +void SetGM(Client *c, const Seperator *sep); +void SetGMSpeed(Client *c, const Seperator *sep); +void SetGMStatus(Client *c, const Seperator *sep); +void SetGodMode(Client *c, const Seperator *sep); +void SetHaste(Client *c, const Seperator *sep); +void SetHideMe(Client *c, const Seperator *sep); +void SetHeroModel(Client *c, const Seperator *sep); +void SetHP(Client *c, const Seperator *sep); +void SetHPFull(Client *c, const Seperator *sep); +void SetInvulnerable(Client *c, const Seperator *sep); +void SetLanguage(Client *c, const Seperator *sep); +void SetLastName(Client *c, const Seperator *sep); +void SetLevel(Client *c, const Seperator *sep); +void SetLoginserverInfo(Client *c, const Seperator *sep); +void SetMana(Client *c, const Seperator *sep); +void SetManaFull(Client *c, const Seperator *sep); +void SetMOTD(Client *c, const Seperator *sep); +void SetName(Client *c, const Seperator *sep); +void SetOOCMute(Client *c, const Seperator *sep); +void SetPassword(Client *c, const Seperator *sep); +void SetPVP(Client *c, const Seperator *sep); +void SetPVPPoints(Client *c, const Seperator *sep); +void SetRace(Client *c, const Seperator *sep); +void SetRacePermanent(Client *c, const Seperator *sep); +void SetServerLocked(Client *c, const Seperator *sep); +void SetSkill(Client *c, const Seperator *sep); +void SetSkillAll(Client *c, const Seperator *sep); +void SetSkillAllMax(Client *c, const Seperator *sep); +void SetStartZone(Client *c, const Seperator *sep); +void SetTemporaryName(Client *c, const Seperator *sep); +void SetTexture(Client *c, const Seperator *sep); +void SetTime(Client *c, const Seperator *sep); +void SetTimeZone(Client *c, const Seperator *sep); +void SetTitle(Client *c, const Seperator *sep); +void SetTitleSuffix(Client *c, const Seperator *sep); +void SetWeather(Client *c, const Seperator *sep); +void SetZoneData(Client *c, const Seperator *sep); void command_set(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/aa_exp.cpp b/zone/gm_commands/set/set_aa_exp.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/aa_exp.cpp rename to zone/gm_commands/set/set_aa_exp.cpp diff --git a/zone/gm_commands/set/aa_points.cpp b/zone/gm_commands/set/set_aa_points.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/aa_points.cpp rename to zone/gm_commands/set/set_aa_points.cpp diff --git a/zone/gm_commands/set/adventure_points.cpp b/zone/gm_commands/set/set_adventure_points.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/adventure_points.cpp rename to zone/gm_commands/set/set_adventure_points.cpp diff --git a/zone/gm_commands/set/alternate_currency.cpp b/zone/gm_commands/set/set_alternate_currency.cpp similarity index 100% rename from zone/gm_commands/set/alternate_currency.cpp rename to zone/gm_commands/set/set_alternate_currency.cpp diff --git a/zone/gm_commands/set/animation.cpp b/zone/gm_commands/set/set_animation.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/animation.cpp rename to zone/gm_commands/set/set_animation.cpp diff --git a/zone/gm_commands/set/anon.cpp b/zone/gm_commands/set/set_anon.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/anon.cpp rename to zone/gm_commands/set/set_anon.cpp diff --git a/zone/gm_commands/set/auto_login.cpp b/zone/gm_commands/set/set_auto_login.cpp old mode 100755 new mode 100644 similarity index 95% rename from zone/gm_commands/set/auto_login.cpp rename to zone/gm_commands/set/set_auto_login.cpp index 4cf219fe86..829c739e30 --- a/zone/gm_commands/set/auto_login.cpp +++ b/zone/gm_commands/set/set_auto_login.cpp @@ -2,7 +2,7 @@ #include "../../groups.h" #include "../../raids.h" #include "../../raids.h" -#include "../../common/repositories/account_repository.h" +#include "../../../common/repositories/account_repository.h" void SetAutoLogin(Client* c, const Seperator* sep) { diff --git a/zone/gm_commands/set/bind_point.cpp b/zone/gm_commands/set/set_bind_point.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/bind_point.cpp rename to zone/gm_commands/set/set_bind_point.cpp diff --git a/zone/gm_commands/set/checksum.cpp b/zone/gm_commands/set/set_checksum.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/checksum.cpp rename to zone/gm_commands/set/set_checksum.cpp diff --git a/zone/gm_commands/set/class_permanent.cpp b/zone/gm_commands/set/set_class_permanent.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/class_permanent.cpp rename to zone/gm_commands/set/set_class_permanent.cpp diff --git a/zone/gm_commands/set/crystals.cpp b/zone/gm_commands/set/set_crystals.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/crystals.cpp rename to zone/gm_commands/set/set_crystals.cpp diff --git a/zone/gm_commands/set/date.cpp b/zone/gm_commands/set/set_date.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/date.cpp rename to zone/gm_commands/set/set_date.cpp diff --git a/zone/gm_commands/set/endurance.cpp b/zone/gm_commands/set/set_endurance.cpp similarity index 100% rename from zone/gm_commands/set/endurance.cpp rename to zone/gm_commands/set/set_endurance.cpp diff --git a/zone/gm_commands/set/endurance_full.cpp b/zone/gm_commands/set/set_endurance_full.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/endurance_full.cpp rename to zone/gm_commands/set/set_endurance_full.cpp diff --git a/zone/gm_commands/set/exp.cpp b/zone/gm_commands/set/set_exp.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/exp.cpp rename to zone/gm_commands/set/set_exp.cpp diff --git a/zone/gm_commands/set/flymode.cpp b/zone/gm_commands/set/set_flymode.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/flymode.cpp rename to zone/gm_commands/set/set_flymode.cpp diff --git a/zone/gm_commands/set/frozen.cpp b/zone/gm_commands/set/set_frozen.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/frozen.cpp rename to zone/gm_commands/set/set_frozen.cpp diff --git a/zone/gm_commands/set/gender.cpp b/zone/gm_commands/set/set_gender.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/gender.cpp rename to zone/gm_commands/set/set_gender.cpp diff --git a/zone/gm_commands/set/gender_permanent.cpp b/zone/gm_commands/set/set_gender_permanent.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/gender_permanent.cpp rename to zone/gm_commands/set/set_gender_permanent.cpp diff --git a/zone/gm_commands/set/gm.cpp b/zone/gm_commands/set/set_gm.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/gm.cpp rename to zone/gm_commands/set/set_gm.cpp diff --git a/zone/gm_commands/set/gm_speed.cpp b/zone/gm_commands/set/set_gm_speed.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/gm_speed.cpp rename to zone/gm_commands/set/set_gm_speed.cpp diff --git a/zone/gm_commands/set/gm_status.cpp b/zone/gm_commands/set/set_gm_status.cpp similarity index 100% rename from zone/gm_commands/set/gm_status.cpp rename to zone/gm_commands/set/set_gm_status.cpp diff --git a/zone/gm_commands/set/god_mode.cpp b/zone/gm_commands/set/set_god_mode.cpp similarity index 100% rename from zone/gm_commands/set/god_mode.cpp rename to zone/gm_commands/set/set_god_mode.cpp diff --git a/zone/gm_commands/set/haste.cpp b/zone/gm_commands/set/set_haste.cpp similarity index 100% rename from zone/gm_commands/set/haste.cpp rename to zone/gm_commands/set/set_haste.cpp diff --git a/zone/gm_commands/set/hero_model.cpp b/zone/gm_commands/set/set_hero_model.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/hero_model.cpp rename to zone/gm_commands/set/set_hero_model.cpp diff --git a/zone/gm_commands/set/hide_me.cpp b/zone/gm_commands/set/set_hide_me.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/hide_me.cpp rename to zone/gm_commands/set/set_hide_me.cpp diff --git a/zone/gm_commands/set/hp.cpp b/zone/gm_commands/set/set_hp.cpp similarity index 100% rename from zone/gm_commands/set/hp.cpp rename to zone/gm_commands/set/set_hp.cpp diff --git a/zone/gm_commands/set/hp_full.cpp b/zone/gm_commands/set/set_hp_full.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/hp_full.cpp rename to zone/gm_commands/set/set_hp_full.cpp diff --git a/zone/gm_commands/set/invulnerable.cpp b/zone/gm_commands/set/set_invulnerable.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/invulnerable.cpp rename to zone/gm_commands/set/set_invulnerable.cpp diff --git a/zone/gm_commands/set/language.cpp b/zone/gm_commands/set/set_language.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/language.cpp rename to zone/gm_commands/set/set_language.cpp diff --git a/zone/gm_commands/set/last_name.cpp b/zone/gm_commands/set/set_last_name.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/last_name.cpp rename to zone/gm_commands/set/set_last_name.cpp diff --git a/zone/gm_commands/set/level.cpp b/zone/gm_commands/set/set_level.cpp similarity index 100% rename from zone/gm_commands/set/level.cpp rename to zone/gm_commands/set/set_level.cpp diff --git a/zone/gm_commands/set/loginserver_info.cpp b/zone/gm_commands/set/set_loginserver_info.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/loginserver_info.cpp rename to zone/gm_commands/set/set_loginserver_info.cpp diff --git a/zone/gm_commands/set/mana.cpp b/zone/gm_commands/set/set_mana.cpp similarity index 100% rename from zone/gm_commands/set/mana.cpp rename to zone/gm_commands/set/set_mana.cpp diff --git a/zone/gm_commands/set/mana_full.cpp b/zone/gm_commands/set/set_mana_full.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/mana_full.cpp rename to zone/gm_commands/set/set_mana_full.cpp diff --git a/zone/gm_commands/set/motd.cpp b/zone/gm_commands/set/set_motd.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/motd.cpp rename to zone/gm_commands/set/set_motd.cpp diff --git a/zone/gm_commands/set/name.cpp b/zone/gm_commands/set/set_name.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/name.cpp rename to zone/gm_commands/set/set_name.cpp diff --git a/zone/gm_commands/set/ooc_mute.cpp b/zone/gm_commands/set/set_ooc_mute.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/ooc_mute.cpp rename to zone/gm_commands/set/set_ooc_mute.cpp diff --git a/zone/gm_commands/set/password.cpp b/zone/gm_commands/set/set_password.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/password.cpp rename to zone/gm_commands/set/set_password.cpp diff --git a/zone/gm_commands/set/pvp.cpp b/zone/gm_commands/set/set_pvp.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/pvp.cpp rename to zone/gm_commands/set/set_pvp.cpp diff --git a/zone/gm_commands/set/pvp_points.cpp b/zone/gm_commands/set/set_pvp_points.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/pvp_points.cpp rename to zone/gm_commands/set/set_pvp_points.cpp diff --git a/zone/gm_commands/set/race.cpp b/zone/gm_commands/set/set_race.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/race.cpp rename to zone/gm_commands/set/set_race.cpp diff --git a/zone/gm_commands/set/race_permanent.cpp b/zone/gm_commands/set/set_race_permanent.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/race_permanent.cpp rename to zone/gm_commands/set/set_race_permanent.cpp diff --git a/zone/gm_commands/set/server_locked.cpp b/zone/gm_commands/set/set_server_locked.cpp similarity index 100% rename from zone/gm_commands/set/server_locked.cpp rename to zone/gm_commands/set/set_server_locked.cpp diff --git a/zone/gm_commands/set/skill.cpp b/zone/gm_commands/set/set_skill.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/skill.cpp rename to zone/gm_commands/set/set_skill.cpp diff --git a/zone/gm_commands/set/skill_all.cpp b/zone/gm_commands/set/set_skill_all.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/skill_all.cpp rename to zone/gm_commands/set/set_skill_all.cpp diff --git a/zone/gm_commands/set/skill_all_max.cpp b/zone/gm_commands/set/set_skill_all_max.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/skill_all_max.cpp rename to zone/gm_commands/set/set_skill_all_max.cpp diff --git a/zone/gm_commands/set/start_zone.cpp b/zone/gm_commands/set/set_start_zone.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/start_zone.cpp rename to zone/gm_commands/set/set_start_zone.cpp diff --git a/zone/gm_commands/set/temporary_name.cpp b/zone/gm_commands/set/set_temporary_name.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/temporary_name.cpp rename to zone/gm_commands/set/set_temporary_name.cpp diff --git a/zone/gm_commands/set/texture.cpp b/zone/gm_commands/set/set_texture.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/texture.cpp rename to zone/gm_commands/set/set_texture.cpp diff --git a/zone/gm_commands/set/time.cpp b/zone/gm_commands/set/set_time.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/time.cpp rename to zone/gm_commands/set/set_time.cpp diff --git a/zone/gm_commands/set/time_zone.cpp b/zone/gm_commands/set/set_time_zone.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/time_zone.cpp rename to zone/gm_commands/set/set_time_zone.cpp diff --git a/zone/gm_commands/set/title.cpp b/zone/gm_commands/set/set_title.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/title.cpp rename to zone/gm_commands/set/set_title.cpp diff --git a/zone/gm_commands/set/title_suffix.cpp b/zone/gm_commands/set/set_title_suffix.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/title_suffix.cpp rename to zone/gm_commands/set/set_title_suffix.cpp diff --git a/zone/gm_commands/set/weather.cpp b/zone/gm_commands/set/set_weather.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/set/weather.cpp rename to zone/gm_commands/set/set_weather.cpp diff --git a/zone/gm_commands/set/zone.cpp b/zone/gm_commands/set/set_zone.cpp old mode 100755 new mode 100644 similarity index 99% rename from zone/gm_commands/set/zone.cpp rename to zone/gm_commands/set/set_zone.cpp index 0ff3c24cb9..d2bfecaedd --- a/zone/gm_commands/set/zone.cpp +++ b/zone/gm_commands/set/set_zone.cpp @@ -1,4 +1,7 @@ #include "../../client.h" +#include "../../worldserver.h" + +extern WorldServer worldserver; void SetZoneData(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show.cpp b/zone/gm_commands/show.cpp index 5a5de45606..651cde5376 100755 --- a/zone/gm_commands/show.cpp +++ b/zone/gm_commands/show.cpp @@ -1,56 +1,57 @@ #include "../client.h" -#include "show/aas.cpp" -#include "show/aa_points.cpp" -#include "show/aggro.cpp" -#include "show/auto_login.cpp" -#include "show/buffs.cpp" -#include "show/buried_corpse_count.cpp" -#include "show/client_version_summary.cpp" -#include "show/content_flags.cpp" -#include "show/currencies.cpp" -#include "show/distance.cpp" -#include "show/emotes.cpp" -#include "show/field_of_view.cpp" -#include "show/flags.cpp" -#include "show/group_info.cpp" -#include "show/hatelist.cpp" -#include "show/inventory.cpp" -#include "show/keyring.cpp" -#include "show/ip_lookup.cpp" -#include "show/line_of_sight.cpp" -#include "show/network.cpp" -#include "show/network_stats.cpp" -#include "show/npc_global_loot.cpp" -#include "show/npc_stats.cpp" -#include "show/npc_type.cpp" -#include "show/peqzone_flags.cpp" -#include "show/petition.cpp" -#include "show/petition_info.cpp" -#include "show/proximity.cpp" -#include "show/quest_errors.cpp" -#include "show/quest_globals.cpp" -#include "show/recipe.cpp" -#include "show/server_info.cpp" -#include "show/skills.cpp" -#include "show/spawn_status.cpp" -#include "show/special_abilities.cpp" -#include "show/spells.cpp" -#include "show/spells_list.cpp" -#include "show/stats.cpp" -#include "show/timers.cpp" -#include "show/traps.cpp" -#include "show/uptime.cpp" -#include "show/variable.cpp" -#include "show/version.cpp" -#include "show/waypoints.cpp" -#include "show/who.cpp" -#include "show/xtargets.cpp" -#include "show/zone_data.cpp" -#include "show/zone_global_loot.cpp" -#include "show/zone_loot.cpp" -#include "show/zone_points.cpp" -#include "show/zone_status.cpp" -#include "show/zone_variables.cpp" + +void ShowAAs(Client* c, const Seperator* sep); +void ShowAAPoints(Client* c, const Seperator* sep); +void ShowAggro(Client* c, const Seperator* sep); +void ShowAutoLogin(Client* c, const Seperator* sep); +void ShowBuffs(Client* c, const Seperator* sep); +void ShowBuriedCorpseCount(Client* c, const Seperator* sep); +void ShowClientVersionSummary(Client* c, const Seperator* sep); +void ShowContentFlags(Client* c, const Seperator* sep); +void ShowCurrencies(Client* c, const Seperator* sep); +void ShowDistance(Client* c, const Seperator* sep); +void ShowEmotes(Client* c, const Seperator* sep); +void ShowFieldOfView(Client* c, const Seperator* sep); +void ShowFlags(Client* c, const Seperator* sep); +void ShowGroupInfo(Client* c, const Seperator* sep); +void ShowHateList(Client* c, const Seperator* sep); +void ShowInventory(Client* c, const Seperator* sep); +void ShowIPLookup(Client* c, const Seperator* sep); +void ShowKeyring(Client* c, const Seperator* sep); +void ShowLineOfSight(Client* c, const Seperator* sep); +void ShowNetwork(Client* c, const Seperator* sep); +void ShowNetworkStats(Client* c, const Seperator* sep); +void ShowNPCGlobalLoot(Client* c, const Seperator* sep); +void ShowNPCStats(Client* c, const Seperator* sep); +void ShowNPCType(Client* c, const Seperator* sep); +void ShowPEQZoneFlags(Client* c, const Seperator* sep); +void ShowPetition(Client* c, const Seperator* sep); +void ShowPetitionInfo(Client* c, const Seperator* sep); +void ShowProximity(Client* c, const Seperator* sep); +void ShowQuestErrors(Client* c, const Seperator* sep); +void ShowQuestGlobals(Client* c, const Seperator* sep); +void ShowRecipe(Client* c, const Seperator* sep); +void ShowServerInfo(Client* c, const Seperator* sep); +void ShowSkills(Client* c, const Seperator* sep); +void ShowSpawnStatus(Client* c, const Seperator* sep); +void ShowSpecialAbilities(Client* c, const Seperator* sep); +void ShowSpells(Client* c, const Seperator* sep); +void ShowSpellsList(Client* c, const Seperator* sep); +void ShowStats(Client* c, const Seperator* sep); +void ShowTimers(Client* c, const Seperator* sep); +void ShowTraps(Client* c, const Seperator* sep); +void ShowUptime(Client* c, const Seperator* sep); +void ShowVariable(Client* c, const Seperator* sep); +void ShowVersion(Client* c, const Seperator* sep); +void ShowWaypoints(Client* c, const Seperator* sep); +void ShowWho(Client* c, const Seperator* sep); +void ShowXTargets(Client* c, const Seperator* sep); +void ShowZoneData(Client* c, const Seperator* sep); +void ShowZoneGlobalLoot(Client* c, const Seperator* sep); +void ShowZoneLoot(Client* c, const Seperator* sep); +void ShowZonePoints(Client* c, const Seperator* sep); +void ShowZoneStatus(Client* c, const Seperator* sep); +void ShowZoneVariables(Client* c, const Seperator* sep); void command_show(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/aa_points.cpp b/zone/gm_commands/show/show_aa_points.cpp similarity index 100% rename from zone/gm_commands/show/aa_points.cpp rename to zone/gm_commands/show/show_aa_points.cpp diff --git a/zone/gm_commands/show/aas.cpp b/zone/gm_commands/show/show_aas.cpp similarity index 100% rename from zone/gm_commands/show/aas.cpp rename to zone/gm_commands/show/show_aas.cpp diff --git a/zone/gm_commands/show/aggro.cpp b/zone/gm_commands/show/show_aggro.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/show/aggro.cpp rename to zone/gm_commands/show/show_aggro.cpp diff --git a/zone/gm_commands/show/auto_login.cpp b/zone/gm_commands/show/show_auto_login.cpp similarity index 92% rename from zone/gm_commands/show/auto_login.cpp rename to zone/gm_commands/show/show_auto_login.cpp index 3a39230a5a..2a82e5b0b2 100644 --- a/zone/gm_commands/show/auto_login.cpp +++ b/zone/gm_commands/show/show_auto_login.cpp @@ -1,5 +1,5 @@ #include "../../client.h" -#include "../../common/repositories/account_repository.h" +#include "../../../common/repositories/account_repository.h" void ShowAutoLogin(Client* c, const Seperator* sep) { diff --git a/zone/gm_commands/show/buffs.cpp b/zone/gm_commands/show/show_buffs.cpp similarity index 100% rename from zone/gm_commands/show/buffs.cpp rename to zone/gm_commands/show/show_buffs.cpp diff --git a/zone/gm_commands/show/buried_corpse_count.cpp b/zone/gm_commands/show/show_buried_corpse_count.cpp similarity index 100% rename from zone/gm_commands/show/buried_corpse_count.cpp rename to zone/gm_commands/show/show_buried_corpse_count.cpp diff --git a/zone/gm_commands/show/client_version_summary.cpp b/zone/gm_commands/show/show_client_version_summary.cpp similarity index 100% rename from zone/gm_commands/show/client_version_summary.cpp rename to zone/gm_commands/show/show_client_version_summary.cpp diff --git a/zone/gm_commands/show/content_flags.cpp b/zone/gm_commands/show/show_content_flags.cpp similarity index 100% rename from zone/gm_commands/show/content_flags.cpp rename to zone/gm_commands/show/show_content_flags.cpp diff --git a/zone/gm_commands/show/currencies.cpp b/zone/gm_commands/show/show_currencies.cpp similarity index 100% rename from zone/gm_commands/show/currencies.cpp rename to zone/gm_commands/show/show_currencies.cpp diff --git a/zone/gm_commands/show/distance.cpp b/zone/gm_commands/show/show_distance.cpp similarity index 100% rename from zone/gm_commands/show/distance.cpp rename to zone/gm_commands/show/show_distance.cpp diff --git a/zone/gm_commands/show/emotes.cpp b/zone/gm_commands/show/show_emotes.cpp similarity index 100% rename from zone/gm_commands/show/emotes.cpp rename to zone/gm_commands/show/show_emotes.cpp diff --git a/zone/gm_commands/show/field_of_view.cpp b/zone/gm_commands/show/show_field_of_view.cpp similarity index 100% rename from zone/gm_commands/show/field_of_view.cpp rename to zone/gm_commands/show/show_field_of_view.cpp diff --git a/zone/gm_commands/show/flags.cpp b/zone/gm_commands/show/show_flags.cpp similarity index 100% rename from zone/gm_commands/show/flags.cpp rename to zone/gm_commands/show/show_flags.cpp diff --git a/zone/gm_commands/show/group_info.cpp b/zone/gm_commands/show/show_group_info.cpp similarity index 100% rename from zone/gm_commands/show/group_info.cpp rename to zone/gm_commands/show/show_group_info.cpp diff --git a/zone/gm_commands/show/hatelist.cpp b/zone/gm_commands/show/show_hatelist.cpp similarity index 100% rename from zone/gm_commands/show/hatelist.cpp rename to zone/gm_commands/show/show_hatelist.cpp diff --git a/zone/gm_commands/show/inventory.cpp b/zone/gm_commands/show/show_inventory.cpp similarity index 100% rename from zone/gm_commands/show/inventory.cpp rename to zone/gm_commands/show/show_inventory.cpp diff --git a/zone/gm_commands/show/ip_lookup.cpp b/zone/gm_commands/show/show_ip_lookup.cpp similarity index 100% rename from zone/gm_commands/show/ip_lookup.cpp rename to zone/gm_commands/show/show_ip_lookup.cpp diff --git a/zone/gm_commands/show/keyring.cpp b/zone/gm_commands/show/show_keyring.cpp similarity index 100% rename from zone/gm_commands/show/keyring.cpp rename to zone/gm_commands/show/show_keyring.cpp diff --git a/zone/gm_commands/show/line_of_sight.cpp b/zone/gm_commands/show/show_line_of_sight.cpp similarity index 100% rename from zone/gm_commands/show/line_of_sight.cpp rename to zone/gm_commands/show/show_line_of_sight.cpp diff --git a/zone/gm_commands/show/network.cpp b/zone/gm_commands/show/show_network.cpp similarity index 100% rename from zone/gm_commands/show/network.cpp rename to zone/gm_commands/show/show_network.cpp diff --git a/zone/gm_commands/show/network_stats.cpp b/zone/gm_commands/show/show_network_stats.cpp similarity index 100% rename from zone/gm_commands/show/network_stats.cpp rename to zone/gm_commands/show/show_network_stats.cpp diff --git a/zone/gm_commands/show/npc_global_loot.cpp b/zone/gm_commands/show/show_npc_global_loot.cpp similarity index 100% rename from zone/gm_commands/show/npc_global_loot.cpp rename to zone/gm_commands/show/show_npc_global_loot.cpp diff --git a/zone/gm_commands/show/npc_stats.cpp b/zone/gm_commands/show/show_npc_stats.cpp similarity index 100% rename from zone/gm_commands/show/npc_stats.cpp rename to zone/gm_commands/show/show_npc_stats.cpp diff --git a/zone/gm_commands/show/npc_type.cpp b/zone/gm_commands/show/show_npc_type.cpp similarity index 100% rename from zone/gm_commands/show/npc_type.cpp rename to zone/gm_commands/show/show_npc_type.cpp diff --git a/zone/gm_commands/show/peqzone_flags.cpp b/zone/gm_commands/show/show_peqzone_flags.cpp similarity index 100% rename from zone/gm_commands/show/peqzone_flags.cpp rename to zone/gm_commands/show/show_peqzone_flags.cpp diff --git a/zone/gm_commands/show/petition.cpp b/zone/gm_commands/show/show_petition.cpp similarity index 94% rename from zone/gm_commands/show/petition.cpp rename to zone/gm_commands/show/show_petition.cpp index f93338ec05..1c15036a9e 100644 --- a/zone/gm_commands/show/petition.cpp +++ b/zone/gm_commands/show/show_petition.cpp @@ -1,5 +1,5 @@ #include "../../client.h" -#include "../../common/repositories/petitions_repository.h" +#include "../../../common/repositories/petitions_repository.h" void ShowPetition(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/petition_info.cpp b/zone/gm_commands/show/show_petition_info.cpp similarity index 96% rename from zone/gm_commands/show/petition_info.cpp rename to zone/gm_commands/show/show_petition_info.cpp index fa1616dde6..d4a45599b2 100644 --- a/zone/gm_commands/show/petition_info.cpp +++ b/zone/gm_commands/show/show_petition_info.cpp @@ -1,5 +1,5 @@ #include "../../client.h" -#include "../../common/repositories/petitions_repository.h" +#include "../../../common/repositories/petitions_repository.h" void ShowPetitionInfo(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/proximity.cpp b/zone/gm_commands/show/show_proximity.cpp similarity index 100% rename from zone/gm_commands/show/proximity.cpp rename to zone/gm_commands/show/show_proximity.cpp diff --git a/zone/gm_commands/show/quest_errors.cpp b/zone/gm_commands/show/show_quest_errors.cpp similarity index 100% rename from zone/gm_commands/show/quest_errors.cpp rename to zone/gm_commands/show/show_quest_errors.cpp diff --git a/zone/gm_commands/show/quest_globals.cpp b/zone/gm_commands/show/show_quest_globals.cpp similarity index 100% rename from zone/gm_commands/show/quest_globals.cpp rename to zone/gm_commands/show/show_quest_globals.cpp diff --git a/zone/gm_commands/show/recipe.cpp b/zone/gm_commands/show/show_recipe.cpp similarity index 93% rename from zone/gm_commands/show/recipe.cpp rename to zone/gm_commands/show/show_recipe.cpp index e9f8db6660..c66e252180 100644 --- a/zone/gm_commands/show/recipe.cpp +++ b/zone/gm_commands/show/show_recipe.cpp @@ -1,7 +1,7 @@ #include "../../client.h" #include "../../command.h" -#include "../../common/repositories/tradeskill_recipe_repository.h" -#include "../../common/repositories/tradeskill_recipe_entries_repository.h" +#include "../../../common/repositories/tradeskill_recipe_repository.h" +#include "../../../common/repositories/tradeskill_recipe_entries_repository.h" void ShowRecipe(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/server_info.cpp b/zone/gm_commands/show/show_server_info.cpp similarity index 98% rename from zone/gm_commands/show/server_info.cpp rename to zone/gm_commands/show/show_server_info.cpp index ff3070aa79..6a8d8b7173 100644 --- a/zone/gm_commands/show/server_info.cpp +++ b/zone/gm_commands/show/show_server_info.cpp @@ -1,6 +1,6 @@ #include "../../client.h" #include "../../dialogue_window.h" -#include "../../common/serverinfo.h" +#include "../../../common/serverinfo.h" void ShowServerInfo(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/skills.cpp b/zone/gm_commands/show/show_skills.cpp similarity index 100% rename from zone/gm_commands/show/skills.cpp rename to zone/gm_commands/show/show_skills.cpp diff --git a/zone/gm_commands/show/spawn_status.cpp b/zone/gm_commands/show/show_spawn_status.cpp similarity index 100% rename from zone/gm_commands/show/spawn_status.cpp rename to zone/gm_commands/show/show_spawn_status.cpp diff --git a/zone/gm_commands/show/special_abilities.cpp b/zone/gm_commands/show/show_special_abilities.cpp similarity index 100% rename from zone/gm_commands/show/special_abilities.cpp rename to zone/gm_commands/show/show_special_abilities.cpp diff --git a/zone/gm_commands/show/spells.cpp b/zone/gm_commands/show/show_spells.cpp similarity index 100% rename from zone/gm_commands/show/spells.cpp rename to zone/gm_commands/show/show_spells.cpp diff --git a/zone/gm_commands/show/spells_list.cpp b/zone/gm_commands/show/show_spells_list.cpp similarity index 100% rename from zone/gm_commands/show/spells_list.cpp rename to zone/gm_commands/show/show_spells_list.cpp diff --git a/zone/gm_commands/show/stats.cpp b/zone/gm_commands/show/show_stats.cpp similarity index 100% rename from zone/gm_commands/show/stats.cpp rename to zone/gm_commands/show/show_stats.cpp diff --git a/zone/gm_commands/show/timers.cpp b/zone/gm_commands/show/show_timers.cpp similarity index 100% rename from zone/gm_commands/show/timers.cpp rename to zone/gm_commands/show/show_timers.cpp diff --git a/zone/gm_commands/show/traps.cpp b/zone/gm_commands/show/show_traps.cpp similarity index 100% rename from zone/gm_commands/show/traps.cpp rename to zone/gm_commands/show/show_traps.cpp diff --git a/zone/gm_commands/show/uptime.cpp b/zone/gm_commands/show/show_uptime.cpp similarity index 100% rename from zone/gm_commands/show/uptime.cpp rename to zone/gm_commands/show/show_uptime.cpp diff --git a/zone/gm_commands/show/variable.cpp b/zone/gm_commands/show/show_variable.cpp similarity index 100% rename from zone/gm_commands/show/variable.cpp rename to zone/gm_commands/show/show_variable.cpp diff --git a/zone/gm_commands/show/version.cpp b/zone/gm_commands/show/show_version.cpp similarity index 100% rename from zone/gm_commands/show/version.cpp rename to zone/gm_commands/show/show_version.cpp diff --git a/zone/gm_commands/show/waypoints.cpp b/zone/gm_commands/show/show_waypoints.cpp similarity index 100% rename from zone/gm_commands/show/waypoints.cpp rename to zone/gm_commands/show/show_waypoints.cpp diff --git a/zone/gm_commands/show/who.cpp b/zone/gm_commands/show/show_who.cpp old mode 100755 new mode 100644 similarity index 100% rename from zone/gm_commands/show/who.cpp rename to zone/gm_commands/show/show_who.cpp diff --git a/zone/gm_commands/show/xtargets.cpp b/zone/gm_commands/show/show_xtargets.cpp similarity index 94% rename from zone/gm_commands/show/xtargets.cpp rename to zone/gm_commands/show/show_xtargets.cpp index b3416b561d..f9d07387e9 100644 --- a/zone/gm_commands/show/xtargets.cpp +++ b/zone/gm_commands/show/show_xtargets.cpp @@ -1,5 +1,5 @@ #include "../../client.h" -#include "../../common/data_verification.h" +#include "../../../common/data_verification.h" void ShowXTargets(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/zone_data.cpp b/zone/gm_commands/show/show_zone_data.cpp similarity index 100% rename from zone/gm_commands/show/zone_data.cpp rename to zone/gm_commands/show/show_zone_data.cpp diff --git a/zone/gm_commands/show/zone_global_loot.cpp b/zone/gm_commands/show/show_zone_global_loot.cpp similarity index 100% rename from zone/gm_commands/show/zone_global_loot.cpp rename to zone/gm_commands/show/show_zone_global_loot.cpp diff --git a/zone/gm_commands/show/zone_loot.cpp b/zone/gm_commands/show/show_zone_loot.cpp similarity index 100% rename from zone/gm_commands/show/zone_loot.cpp rename to zone/gm_commands/show/show_zone_loot.cpp diff --git a/zone/gm_commands/show/zone_points.cpp b/zone/gm_commands/show/show_zone_points.cpp similarity index 100% rename from zone/gm_commands/show/zone_points.cpp rename to zone/gm_commands/show/show_zone_points.cpp diff --git a/zone/gm_commands/show/zone_status.cpp b/zone/gm_commands/show/show_zone_status.cpp similarity index 100% rename from zone/gm_commands/show/zone_status.cpp rename to zone/gm_commands/show/show_zone_status.cpp diff --git a/zone/gm_commands/show/zone_variables.cpp b/zone/gm_commands/show/show_zone_variables.cpp similarity index 100% rename from zone/gm_commands/show/zone_variables.cpp rename to zone/gm_commands/show/show_zone_variables.cpp diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 1873aec0b6..73a1e29bae 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -933,23 +933,23 @@ std::string lua_get_rule(std::string rule_name) { } std::string lua_get_data(std::string bucket_key) { - return DataBucket::GetData(bucket_key); + return DataBucket::GetData(&database, bucket_key); } std::string lua_get_data_expires(std::string bucket_key) { - return DataBucket::GetDataExpires(bucket_key); + return DataBucket::GetDataExpires(&database, bucket_key); } void lua_set_data(std::string bucket_key, std::string bucket_value) { - DataBucket::SetData(bucket_key, bucket_value); + DataBucket::SetData(&database, bucket_key, bucket_value); } void lua_set_data(std::string bucket_key, std::string bucket_value, std::string expires_at) { - DataBucket::SetData(bucket_key, bucket_value, expires_at); + DataBucket::SetData(&database, bucket_key, bucket_value, expires_at); } bool lua_delete_data(std::string bucket_key) { - return DataBucket::DeleteData(bucket_key); + return DataBucket::DeleteData(&database, bucket_key); } std::string lua_get_char_name_by_id(uint32 char_id) { @@ -2030,7 +2030,7 @@ void lua_rename(std::string name) { } std::string lua_get_data_remaining(std::string bucket_name) { - return DataBucket::GetDataRemaining(bucket_name); + return DataBucket::GetDataRemaining(&database, bucket_name); } const int lua_get_item_stat(uint32 item_id, std::string identifier) { diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 3e3a5257fa..00f89e6d62 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -434,7 +434,6 @@ LuaParser::LuaParser() { ZoneArgumentDispatch[EVENT_TIMER_RESUME] = handle_zone_timer_pause_resume_start; ZoneArgumentDispatch[EVENT_TIMER_START] = handle_zone_timer_pause_resume_start; ZoneArgumentDispatch[EVENT_TIMER_STOP] = handle_zone_timer_stop; -#endif L = nullptr; } @@ -2295,3 +2294,5 @@ void LuaParser::LoadZoneScript(std::string filename) { void LuaParser::LoadGlobalZoneScript(std::string filename) { LoadScript(filename, "global_zone"); } + +#endif diff --git a/zone/mob.cpp b/zone/mob.cpp index 1302246b25..69d1ce8269 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -8161,7 +8161,7 @@ void Mob::DeleteBucket(std::string bucket_name) DataBucketKey k = GetScopedBucketKeys(); k.key = bucket_name; - DataBucket::DeleteData(k); + DataBucket::DeleteData(&database, k); } std::string Mob::GetBucket(std::string bucket_name) @@ -8169,7 +8169,7 @@ std::string Mob::GetBucket(std::string bucket_name) DataBucketKey k = GetScopedBucketKeys(); k.key = bucket_name; - auto b = DataBucket::GetData(k); + auto b = DataBucket::GetData(&database, k); if (!b.value.empty()) { return b.value; } @@ -8181,7 +8181,7 @@ std::string Mob::GetBucketExpires(std::string bucket_name) DataBucketKey k = GetScopedBucketKeys(); k.key = bucket_name; - std::string bucket_expiration = DataBucket::GetDataExpires(k); + std::string bucket_expiration = DataBucket::GetDataExpires(&database, k); if (!bucket_expiration.empty()) { return bucket_expiration; } @@ -8194,7 +8194,7 @@ std::string Mob::GetBucketRemaining(std::string bucket_name) DataBucketKey k = GetScopedBucketKeys(); k.key = bucket_name; - std::string bucket_remaining = DataBucket::GetDataRemaining(k); + std::string bucket_remaining = DataBucket::GetDataRemaining(&database, k); if (!bucket_remaining.empty() && Strings::ToInt(bucket_remaining) > 0) { return bucket_remaining; } @@ -8212,7 +8212,7 @@ void Mob::SetBucket(std::string bucket_name, std::string bucket_value, std::stri k.expires = expiration; k.value = bucket_value; - DataBucket::SetData(k); + DataBucket::SetData(&database, k); } std::string Mob::GetMobDescription() @@ -8783,12 +8783,12 @@ bool Mob::LoadDataBucketsCache() } if (IsBot()) { - DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Bot, {id}); + DataBucket::BulkLoadEntitiesToCache(&database, DataBucketLoadType::Bot, {id}); } else if (IsClient()) { uint32 account_id = CastToClient()->AccountID(); - DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Account, {account_id}); - DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Client, {id}); + DataBucket::BulkLoadEntitiesToCache(&database, DataBucketLoadType::Account, {account_id}); + DataBucket::BulkLoadEntitiesToCache(&database, DataBucketLoadType::Client, {id}); } return true; diff --git a/zone/pathfinder_nav_mesh.cpp b/zone/pathfinder_nav_mesh.cpp index 22dd12249f..5cf89f0911 100644 --- a/zone/pathfinder_nav_mesh.cpp +++ b/zone/pathfinder_nav_mesh.cpp @@ -2,8 +2,8 @@ #include #include #include "pathfinder_nav_mesh.h" -#include -#include +#include +#include #include "zone.h" #include "water_map.h" diff --git a/zone/pathfinder_nav_mesh.h b/zone/pathfinder_nav_mesh.h index 9f7bf4120f..3b10cc23cc 100644 --- a/zone/pathfinder_nav_mesh.h +++ b/zone/pathfinder_nav_mesh.h @@ -2,7 +2,7 @@ #include "pathfinder_interface.h" #include -#include +#include class PathfinderNavmesh : public IPathfinder { diff --git a/zone/sidecar_api/log_handler.cpp b/zone/sidecar_api/log_handler.cpp deleted file mode 100644 index 5c0e47c019..0000000000 --- a/zone/sidecar_api/log_handler.cpp +++ /dev/null @@ -1,18 +0,0 @@ -void SidecarApi::RequestLogHandler(const httplib::Request &req, const httplib::Response &res) -{ - if (!req.path.empty()) { - std::vector params; - for (auto &p: req.params) { - params.emplace_back(fmt::format("{}={}", p.first, p.second)); - } - - LogInfo( - "[API] Request [{}] [{}{}] via [{}:{}]", - res.status, - req.path, - (!params.empty() ? "?" + Strings::Join(params, "&") : ""), - req.remote_addr, - req.remote_port - ); - } -} diff --git a/zone/sidecar_api/map_best_z_controller.cpp b/zone/sidecar_api/map_best_z_controller.cpp deleted file mode 100644 index abb714ac5c..0000000000 --- a/zone/sidecar_api/map_best_z_controller.cpp +++ /dev/null @@ -1,4 +0,0 @@ -void SidecarApi::MapBestZController(const httplib::Request &req, httplib::Response &res) -{ - -} diff --git a/zone/sidecar_api/sidecar_api.cpp b/zone/sidecar_api/sidecar_api.cpp index d6e6596c9c..583506798e 100644 --- a/zone/sidecar_api/sidecar_api.cpp +++ b/zone/sidecar_api/sidecar_api.cpp @@ -16,9 +16,39 @@ void CatchSidecarSignal(int sig_num) std::exit(0); } -#include "log_handler.cpp" -#include "test_controller.cpp" -#include "map_best_z_controller.cpp" +void SidecarApi::RequestLogHandler(const httplib::Request& req, const httplib::Response& res) +{ + if (!req.path.empty()) { + std::vector params; + for (auto& p : req.params) { + params.emplace_back(fmt::format("{}={}", p.first, p.second)); + } + + LogInfo( + "[API] Request [{}] [{}{}] via [{}:{}]", + res.status, + req.path, + (!params.empty() ? "?" + Strings::Join(params, "&") : ""), + req.remote_addr, + req.remote_port + ); + } +} + +void SidecarApi::TestController(const httplib::Request& req, httplib::Response& res) +{ + nlohmann::json j; + + j["data"]["test"] = "test"; + + res.set_content(j.dump(), "application/json"); +} + +void SidecarApi::MapBestZController(const httplib::Request& req, httplib::Response& res) +{ + +} + #include "../../common/file.h" constexpr static int HTTP_RESPONSE_OK = 200; diff --git a/zone/sidecar_api/test_controller.cpp b/zone/sidecar_api/test_controller.cpp deleted file mode 100644 index a1cb7d4a77..0000000000 --- a/zone/sidecar_api/test_controller.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "sidecar_api.h" - -void SidecarApi::TestController(const httplib::Request &req, httplib::Response &res) -{ - nlohmann::json j; - - j["data"]["test"] = "test"; - - res.set_content(j.dump(), "application/json"); -} diff --git a/zone/spells.cpp b/zone/spells.cpp index c37fa4467d..6636a092cc 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -6275,7 +6275,7 @@ bool Client::SpellBucketCheck(uint16 spell_id, uint32 character_id) k.key = e.bucket_name; - const auto& b = DataBucket::GetData(k); + const auto& b = DataBucket::GetData(&database, k); return zone->CompareDataBucket(e.bucket_comparison, e.bucket_value, b.value); } diff --git a/zone/zone.cpp b/zone/zone.cpp index eea9d8a97a..771ac95385 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -170,7 +170,7 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool is_static) { zone->RequestUCSServerStatus(); zone->StartShutdownTimer(); - DataBucket::LoadZoneCache(iZoneID, iInstanceID); + DataBucket::LoadZoneCache(&database, iZoneID, iInstanceID); /* * Set Logging @@ -3186,7 +3186,7 @@ std::string Zone::GetBucket(const std::string& bucket_name) k.instance_id = instanceid; k.key = bucket_name; - return DataBucket::GetData(k).value; + return DataBucket::GetData(&database, k).value; } void Zone::SetBucket(const std::string& bucket_name, const std::string& bucket_value, const std::string& expiration) @@ -3198,7 +3198,7 @@ void Zone::SetBucket(const std::string& bucket_name, const std::string& bucket_v k.expires = expiration; k.value = bucket_value; - DataBucket::SetData(k); + DataBucket::SetData(&database, k); } void Zone::DeleteBucket(const std::string& bucket_name) @@ -3208,7 +3208,7 @@ void Zone::DeleteBucket(const std::string& bucket_name) k.instance_id = instanceid; k.key = bucket_name; - DataBucket::DeleteData(k); + DataBucket::DeleteData(&database, k); } std::string Zone::GetBucketExpires(const std::string& bucket_name) @@ -3218,7 +3218,7 @@ std::string Zone::GetBucketExpires(const std::string& bucket_name) k.instance_id = instanceid; k.key = bucket_name; - return DataBucket::GetDataExpires(k); + return DataBucket::GetDataExpires(&database, k); } std::string Zone::GetBucketRemaining(const std::string& bucket_name) @@ -3228,7 +3228,7 @@ std::string Zone::GetBucketRemaining(const std::string& bucket_name) k.instance_id = instanceid; k.key = bucket_name; - return DataBucket::GetDataRemaining(k); + return DataBucket::GetDataRemaining(&database, k); } void Zone::DisableRespawnTimers() @@ -3584,5 +3584,3 @@ std::vector Zone::GetTimers() return v; } - -#include "zone_loot.cpp" diff --git a/zone/zone_cli.cpp b/zone/zone_cli.cpp index 33177e8f66..59ddee18db 100644 --- a/zone/zone_cli.cpp +++ b/zone/zone_cli.cpp @@ -39,13 +39,3 @@ void ZoneCLI::CommandHandler(int argc, char **argv) EQEmuCommand::HandleMenu(function_map, cmd, argc, argv); } -// cli -#include "cli/benchmark_databuckets.cpp" -#include "cli/sidecar_serve_http.cpp" - -// tests -#include "cli/tests/_test_util.cpp" -#include "cli/tests/databuckets.cpp" -#include "cli/tests/npc_handins.cpp" -#include "cli/tests/npc_handins_multiquest.cpp" -#include "cli/tests/zone_state.cpp" From 0bc0ee609a45e9cd36bdfe6f527b77ad72c8110d Mon Sep 17 00:00:00 2001 From: nytmyr <53322305+nytmyr@users.noreply.github.com> Date: Sun, 14 Dec 2025 01:28:51 -0600 Subject: [PATCH 057/194] [Bots] Add 'all' argument to ^spellannouncecasts (#5037) --- zone/bot_commands/bot_spell_announce_cast.cpp | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/zone/bot_commands/bot_spell_announce_cast.cpp b/zone/bot_commands/bot_spell_announce_cast.cpp index 4825997249..cb8f06d954 100644 --- a/zone/bot_commands/bot_spell_announce_cast.cpp +++ b/zone/bot_commands/bot_spell_announce_cast.cpp @@ -11,6 +11,7 @@ void bot_command_spell_announce_cast(Client* c, const Seperator* sep) { BotCommandHelpParams p; p.description = { "Allows you to enable or disable cast announcements for bots by spell type." }; + p.notes = { fmt::format("- You can use the 'all' argument to change all spell types at once. IE '{} all 0' or '{} all 0 spawned' to disable for the targeted bot or all bots.", sep->arg[0], sep->arg[0]) }; p.example_format = { fmt::format("{} [Type Shortname] [value] [actionable]", sep->arg[0]), @@ -88,6 +89,7 @@ void bot_command_spell_announce_cast(Client* c, const Seperator* sep) { bool current_check = false; uint16 spell_type = 0; uint32 type_value = 0; + bool all_types = false; // String/Int type checks if (sep->IsNumber(1)) { @@ -99,6 +101,9 @@ void bot_command_spell_announce_cast(Client* c, const Seperator* sep) { return; } } + else if (!arg1.compare("all")) { + all_types = true; + } else { if (Bot::GetSpellTypeIDByShortName(arg1) != UINT16_MAX) { spell_type = Bot::GetSpellTypeIDByShortName(arg1); @@ -129,6 +134,11 @@ void bot_command_spell_announce_cast(Client* c, const Seperator* sep) { } } else if (!arg2.compare("current")) { + if (all_types) { + c->Message(Chat::Yellow, "You must specify a single type to check the current state of."); + + return; + } ++ab_arg; current_check = true; } @@ -183,8 +193,17 @@ void bot_command_spell_announce_cast(Client* c, const Seperator* sep) { ); } else { - my_bot->SetSpellTypeAnnounceCast(spell_type, type_value); - ++success_count; + if (all_types) { + for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) { + my_bot->SetSpellTypeAnnounceCast(i, type_value); + } + + ++success_count; + } + else { + my_bot->SetSpellTypeAnnounceCast(spell_type, type_value); + ++success_count; + } } } if (!current_check) { @@ -194,8 +213,8 @@ void bot_command_spell_announce_cast(Client* c, const Seperator* sep) { fmt::format( "{} says, 'I will {} announce [{}] casts.'", first_found->GetCleanName(), - (first_found->GetSpellTypeAnnounceCast(spell_type) ? "now" : "no longer"), - Bot::GetSpellTypeNameByID(spell_type) + (type_value ? "now" : "no longer"), + (all_types ? "all" : Bot::GetSpellTypeNameByID(spell_type)) ).c_str() ); } From 6c057308da66754b44000c665391e766347c16f7 Mon Sep 17 00:00:00 2001 From: nytmyr <53322305+nytmyr@users.noreply.github.com> Date: Sun, 14 Dec 2025 01:29:06 -0600 Subject: [PATCH 058/194] [Bots] Allow melee to sit to med/heal when out of combat (#5036) --- zone/bot.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/bot.cpp b/zone/bot.cpp index d0d83fbc81..a702c5e5ae 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2601,6 +2601,8 @@ void Bot::DoOutOfCombatChecks(Client* bot_owner, Mob* follow_mob, float leash_di if (GetClass() == Class::Bard && AI_HasSpells() && TryBardMovementCasts()) { return; } + + TryMeditate(); } // This is as close as I could get without modifying the aggro mechanics and making it an expensive process... From f1ff227fbdf504152c891338a77f0ef727cccd0c Mon Sep 17 00:00:00 2001 From: brainiac Date: Tue, 16 Dec 2025 20:27:23 -0800 Subject: [PATCH 059/194] Do not enforce lf line endings, that just creates mixed line endings errors on windows --- .editorconfig | 4 +--- .gitattributes | 4 ---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.editorconfig b/.editorconfig index 03f7824943..e181959dce 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,9 +3,7 @@ # top-most EditorConfig file root = true -# Unix-style newlines with a newline ending every file [*] -end_of_line = lf insert_final_newline = true # Matches multiple files with brace expansion notation @@ -20,4 +18,4 @@ indent_style = tab # Tab indentation (no size specified) [Makefile] -indent_style = tab \ No newline at end of file +indent_style = tab diff --git a/.gitattributes b/.gitattributes index c89cdbf70c..1202f64159 100644 --- a/.gitattributes +++ b/.gitattributes @@ -20,7 +20,3 @@ *.css text *.js text *.types text - -*.vcproj text merge=union -*.csproj text merge=union -*.sln text merge=union eol=crlf From a8551f20c9868ffdb3ceea0218900b08d3536a27 Mon Sep 17 00:00:00 2001 From: brainiac Date: Tue, 16 Dec 2025 20:30:47 -0800 Subject: [PATCH 060/194] cmake: add project folders - Add static libraries to "libraries" folder - Add servers to "executables/servers" folder - Add tools to "executables/tools" folder - Add tests to "executables/tests" folder - Add contrib projects to "contrib" folder --- CMakeLists.txt | 2 ++ client_files/export/CMakeLists.txt | 1 + client_files/import/CMakeLists.txt | 1 + common/CMakeLists.txt | 3 ++- eqlaunch/CMakeLists.txt | 1 + libs/luabind/CMakeLists.txt | 1 + loginserver/CMakeLists.txt | 1 + queryserv/CMakeLists.txt | 1 + shared_memory/CMakeLists.txt | 1 + tests/CMakeLists.txt | 1 + ucs/CMakeLists.txt | 1 + world/CMakeLists.txt | 3 ++- zone/CMakeLists.txt | 7 ++++++- 13 files changed, 21 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8470bbbf47..03e375fea1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,8 @@ project(EQEmu LANGUAGES CXX ) +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + #explicitly set CMP0167 for Find Boost if(POLICY CMP0167) cmake_policy(SET CMP0167 NEW) diff --git a/client_files/export/CMakeLists.txt b/client_files/export/CMakeLists.txt index c35a22efea..3ed4949367 100644 --- a/client_files/export/CMakeLists.txt +++ b/client_files/export/CMakeLists.txt @@ -14,3 +14,4 @@ install(TARGETS export_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/ target_link_libraries(export_client_files common) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set_property(TARGET export_client_files PROPERTY FOLDER executables/tools) diff --git a/client_files/import/CMakeLists.txt b/client_files/import/CMakeLists.txt index af7f4da0ce..491d0cde96 100644 --- a/client_files/import/CMakeLists.txt +++ b/client_files/import/CMakeLists.txt @@ -14,3 +14,4 @@ install(TARGETS import_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/ target_link_libraries(import_client_files common) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set_property(TARGET import_client_files PROPERTY FOLDER executables/tools) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 8c65626142..23fbcff69a 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -819,4 +819,5 @@ if(EQEMU_BUILD_PCH) set_source_files_properties("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES SKIP_PRECOMPILE_HEADERS ON) endif() -set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) \ No newline at end of file +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set_property(TARGET common PROPERTY FOLDER libraries) diff --git a/eqlaunch/CMakeLists.txt b/eqlaunch/CMakeLists.txt index beafeb7f02..048335c733 100644 --- a/eqlaunch/CMakeLists.txt +++ b/eqlaunch/CMakeLists.txt @@ -18,3 +18,4 @@ install(TARGETS eqlaunch RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) target_link_libraries(eqlaunch common) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set_property(TARGET eqlaunch PROPERTY FOLDER executables/tools) diff --git a/libs/luabind/CMakeLists.txt b/libs/luabind/CMakeLists.txt index ef93f9a03a..e871cdf140 100644 --- a/libs/luabind/CMakeLists.txt +++ b/libs/luabind/CMakeLists.txt @@ -33,3 +33,4 @@ if(MSVC) endif() set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set_property(TARGET luabind PROPERTY FOLDER contrib) diff --git a/loginserver/CMakeLists.txt b/loginserver/CMakeLists.txt index ca89bd3578..013c64d5fb 100644 --- a/loginserver/CMakeLists.txt +++ b/loginserver/CMakeLists.txt @@ -35,3 +35,4 @@ install(TARGETS loginserver RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) target_link_libraries(loginserver common) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set_property(TARGET loginserver PROPERTY FOLDER executables/servers) diff --git a/queryserv/CMakeLists.txt b/queryserv/CMakeLists.txt index 39dc0b0483..968a3f6f06 100644 --- a/queryserv/CMakeLists.txt +++ b/queryserv/CMakeLists.txt @@ -28,3 +28,4 @@ add_definitions(-DQSERV) target_link_libraries(queryserv common) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set_property(TARGET queryserv PROPERTY FOLDER executables/servers) diff --git a/shared_memory/CMakeLists.txt b/shared_memory/CMakeLists.txt index 099d27b5bd..4ef414693f 100644 --- a/shared_memory/CMakeLists.txt +++ b/shared_memory/CMakeLists.txt @@ -18,3 +18,4 @@ install(TARGETS shared_memory RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) target_link_libraries(shared_memory common) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set_property(TARGET shared_memory PROPERTY FOLDER executables/servers) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7fa45d2fc8..b81c6e0b22 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -46,3 +46,4 @@ if(UNIX) endif() set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set_property(TARGET tests PROPERTY FOLDER executables/tests) diff --git a/ucs/CMakeLists.txt b/ucs/CMakeLists.txt index 188b79a936..73a78abb81 100644 --- a/ucs/CMakeLists.txt +++ b/ucs/CMakeLists.txt @@ -26,3 +26,4 @@ add_definitions(-DUCS) target_link_libraries(ucs common) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set_property(TARGET ucs PROPERTY FOLDER executables/servers) diff --git a/world/CMakeLists.txt b/world/CMakeLists.txt index 9a3931ebb0..1e44afc59e 100644 --- a/world/CMakeLists.txt +++ b/world/CMakeLists.txt @@ -103,4 +103,5 @@ endif() install(TARGETS world RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) -set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) \ No newline at end of file +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set_property(TARGET world PROPERTY FOLDER executables/servers) diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index acd2142b9c..9d8b90cab5 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -266,6 +266,8 @@ set(lua_sources ) add_library(lua_zone STATIC ${lua_sources}) + +set_property(TARGET lua_zone PROPERTY FOLDER libraries) set_target_properties(lua_zone PROPERTIES UNITY_BUILD ON UNITY_BUILD_BATCH_SIZE 8) set(perl_sources @@ -296,6 +298,7 @@ set(perl_sources ) add_library(perl_zone STATIC ${perl_sources}) +set_property(TARGET perl_zone PROPERTY FOLDER libraries) set_target_properties(perl_zone PROPERTIES UNITY_BUILD ON UNITY_BUILD_BATCH_SIZE 8) set(gm_command_sources @@ -662,6 +665,7 @@ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Source Files" FILES ${gm add_library(gm_commands_zone STATIC ${gm_command_sources}) target_link_libraries(gm_commands_zone PRIVATE common) set_target_properties(gm_commands_zone PROPERTIES UNITY_BUILD ON UNITY_BUILD_BATCH_SIZE 32) +set_property(TARGET gm_commands_zone PROPERTY FOLDER libraries) add_executable(zone ${zone_sources} ${zone_headers}) @@ -701,4 +705,5 @@ if(EQEMU_BUILD_PERL) target_link_libraries(zone PRIVATE perl_zone) endif() -SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) \ No newline at end of file +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set_property(TARGET zone PROPERTY FOLDER executables/servers) From 418e31911c09b2ab0251fca5f71cdfaab734760a Mon Sep 17 00:00:00 2001 From: brainiac Date: Tue, 16 Dec 2025 20:31:45 -0800 Subject: [PATCH 061/194] cmake: remove unused copy of gm_commands CMakeLists.txt --- zone/gm_commands/CMakeLists.txt | 169 -------------------------------- 1 file changed, 169 deletions(-) delete mode 100644 zone/gm_commands/CMakeLists.txt diff --git a/zone/gm_commands/CMakeLists.txt b/zone/gm_commands/CMakeLists.txt deleted file mode 100644 index 01af3a4267..0000000000 --- a/zone/gm_commands/CMakeLists.txt +++ /dev/null @@ -1,169 +0,0 @@ -cmake_minimum_required(VERSION 3.20) - -# gm commands -set(gm_command_sources - command.cpp - bot_command.cpp - gm_commands/acceptrules.cpp - gm_commands/advnpcspawn.cpp - gm_commands/aggrozone.cpp - gm_commands/ai.cpp - gm_commands/appearance.cpp - gm_commands/appearanceeffects.cpp - gm_commands/attack.cpp - gm_commands/augmentitem.cpp - gm_commands/ban.cpp - gm_commands/bugs.cpp - gm_commands/camerashake.cpp - gm_commands/castspell.cpp - gm_commands/chat.cpp - gm_commands/clearxtargets.cpp - gm_commands/copycharacter.cpp - gm_commands/corpse.cpp - gm_commands/corpsefix.cpp - gm_commands/countitem.cpp - gm_commands/damage.cpp - gm_commands/databuckets.cpp - gm_commands/dbspawn2.cpp - gm_commands/delacct.cpp - gm_commands/delpetition.cpp - gm_commands/depop.cpp - gm_commands/depopzone.cpp - gm_commands/devtools.cpp - gm_commands/disablerecipe.cpp - gm_commands/disarmtrap.cpp - gm_commands/doanim.cpp - gm_commands/door.cpp - gm_commands/door_manipulation.cpp - gm_commands/dye.cpp - gm_commands/dz.cpp - gm_commands/dzkickplayers.cpp - gm_commands/editmassrespawn.cpp - gm_commands/emote.cpp - gm_commands/emptyinventory.cpp - gm_commands/enablerecipe.cpp - gm_commands/entityvariable.cpp - gm_commands/exptoggle.cpp - gm_commands/faction.cpp - gm_commands/evolving_items.cpp - gm_commands/feature.cpp - gm_commands/find.cpp - gm_commands/fish.cpp - gm_commands/fixmob.cpp - gm_commands/flagedit.cpp - gm_commands/fleeinfo.cpp - gm_commands/forage.cpp - gm_commands/gearup.cpp - gm_commands/giveitem.cpp - gm_commands/givemoney.cpp - gm_commands/gmzone.cpp - gm_commands/goto.cpp - gm_commands/grantaa.cpp - gm_commands/grid.cpp - gm_commands/guild.cpp - gm_commands/hp.cpp - gm_commands/illusion_block.cpp - gm_commands/instance.cpp - gm_commands/interrogateinv.cpp - gm_commands/interrupt.cpp - gm_commands/invsnapshot.cpp - gm_commands/ipban.cpp - gm_commands/kick.cpp - gm_commands/kill.cpp - gm_commands/killallnpcs.cpp - gm_commands/list.cpp - gm_commands/lootsim.cpp - gm_commands/loc.cpp - gm_commands/logs.cpp - gm_commands/makepet.cpp - gm_commands/memspell.cpp - gm_commands/merchantshop.cpp - gm_commands/modifynpcstat.cpp - gm_commands/movechar.cpp - gm_commands/movement.cpp - gm_commands/myskills.cpp - gm_commands/mysql.cpp - gm_commands/mystats.cpp - gm_commands/npccast.cpp - gm_commands/npcedit.cpp - gm_commands/npceditmass.cpp - gm_commands/npcemote.cpp - gm_commands/npcloot.cpp - gm_commands/npcsay.cpp - gm_commands/npcshout.cpp - gm_commands/npcspawn.cpp - gm_commands/npctypespawn.cpp - gm_commands/nudge.cpp - gm_commands/nukebuffs.cpp - gm_commands/nukeitem.cpp - gm_commands/object.cpp - gm_commands/object_manipulation.cpp - gm_commands/parcels.cpp - gm_commands/path.cpp - gm_commands/peqzone.cpp - gm_commands/petitems.cpp - gm_commands/petname.cpp - gm_commands/picklock.cpp - gm_commands/profanity.cpp - gm_commands/push.cpp - gm_commands/raidloot.cpp - gm_commands/randomfeatures.cpp - gm_commands/refreshgroup.cpp - gm_commands/reload.cpp - gm_commands/removeitem.cpp - gm_commands/repop.cpp - gm_commands/resetaa.cpp - gm_commands/resetaa_timer.cpp - gm_commands/resetdisc_timer.cpp - gm_commands/revoke.cpp - gm_commands/roambox.cpp - gm_commands/rules.cpp - gm_commands/save.cpp - gm_commands/scale.cpp - gm_commands/scribespell.cpp - gm_commands/scribespells.cpp - gm_commands/sendzonespawns.cpp - gm_commands/sensetrap.cpp - gm_commands/serverrules.cpp - gm_commands/set.cpp - gm_commands/show.cpp - gm_commands/shutdown.cpp - gm_commands/spawn.cpp - gm_commands/spawneditmass.cpp - gm_commands/spawnfix.cpp - gm_commands/faction_association.cpp - gm_commands/stun.cpp - gm_commands/summon.cpp - gm_commands/summonburiedplayercorpse.cpp - gm_commands/summonitem.cpp - gm_commands/suspend.cpp - gm_commands/suspendmulti.cpp - gm_commands/takeplatinum.cpp - gm_commands/task.cpp - gm_commands/traindisc.cpp - gm_commands/tune.cpp - gm_commands/undye.cpp - gm_commands/unmemspell.cpp - gm_commands/unmemspells.cpp - gm_commands/unscribespell.cpp - gm_commands/unscribespells.cpp - gm_commands/untraindisc.cpp - gm_commands/untraindiscs.cpp - gm_commands/wc.cpp - gm_commands/worldshutdown.cpp - gm_commands/worldwide.cpp - gm_commands/wp.cpp - gm_commands/wpadd.cpp - gm_commands/zone.cpp - gm_commands/zonebootup.cpp - gm_commands/zoneshutdown.cpp - gm_commands/zonevariable.cpp - gm_commands/zone_instance.cpp - gm_commands/zone_shard.cpp - gm_commands/zsave.cpp -) - -add_library(gm_commands_zone STATIC ${gm_command_sources}) -target_link_libraries(gm_commands_zone PRIVATE common) -set_target_properties(gm_commands_zone PROPERTIES UNITY_BUILD ON UNITY_BUILD_BATCH_SIZE 32) - From 723ca13482922d000227f736a4cd3f357aca40dc Mon Sep 17 00:00:00 2001 From: brainiac Date: Wed, 17 Dec 2025 09:17:00 -0800 Subject: [PATCH 062/194] normalize includes: client_files --- client_files/export/CMakeLists.txt | 1 + client_files/export/main.cpp | 42 +++++++++++++++--------------- client_files/import/CMakeLists.txt | 1 + client_files/import/main.cpp | 30 ++++++++++----------- 4 files changed, 38 insertions(+), 36 deletions(-) diff --git a/client_files/export/CMakeLists.txt b/client_files/export/CMakeLists.txt index 3ed4949367..c81977fb06 100644 --- a/client_files/export/CMakeLists.txt +++ b/client_files/export/CMakeLists.txt @@ -12,6 +12,7 @@ add_executable(export_client_files ${export_sources} ${export_headers}) install(TARGETS export_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) target_link_libraries(export_client_files common) +target_include_directories(export_client_files PRIVATE ../..) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set_property(TARGET export_client_files PROPERTY FOLDER executables/tools) diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index 8d0a27a3ca..1e845441aa 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -16,27 +16,27 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include - -#include "../../common/eqemu_logsys.h" -#include "../../common/global_define.h" -#include "../../common/shareddb.h" -#include "../../common/eqemu_config.h" -#include "../../common/platform.h" -#include "../../common/crash.h" -#include "../../common/rulesys.h" -#include "../../common/strings.h" -#include "../../common/content/world_content_service.h" -#include "../../common/zone_store.h" -#include "../../common/path_manager.h" -#include "../../common/repositories/base_data_repository.h" -#include "../../common/repositories/db_str_repository.h" -#include "../../common/repositories/skill_caps_repository.h" -#include "../../common/repositories/spells_new_repository.h" -#include "../../common/file.h" -#include "../../common/events/player_event_logs.h" -#include "../../common/skill_caps.h" -#include "../../common/evolving_items.h" +#include "common/content/world_content_service.h" +#include "common/crash.h" +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/evolving_items.h" +#include "common/file.h" +#include "common/global_define.h" +#include "common/path_manager.h" +#include "common/platform.h" +#include "common/repositories/base_data_repository.h" +#include "common/repositories/db_str_repository.h" +#include "common/repositories/skill_caps_repository.h" +#include "common/repositories/spells_new_repository.h" +#include "common/rulesys.h" +#include "common/shareddb.h" +#include "common/skill_caps.h" +#include "common/strings.h" +#include "common/zone_store.h" + +#include void ExportSpells(SharedDatabase *db); void ExportSkillCaps(SharedDatabase *db); diff --git a/client_files/import/CMakeLists.txt b/client_files/import/CMakeLists.txt index 491d0cde96..7966eb3b3e 100644 --- a/client_files/import/CMakeLists.txt +++ b/client_files/import/CMakeLists.txt @@ -12,6 +12,7 @@ add_executable(import_client_files ${import_sources} ${import_headers}) install(TARGETS import_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) target_link_libraries(import_client_files common) +target_include_directories(import_client_files PRIVATE ../..) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set_property(TARGET import_client_files PROPERTY FOLDER executables/tools) diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp index b7be706d76..e24cdff8e5 100644 --- a/client_files/import/main.cpp +++ b/client_files/import/main.cpp @@ -16,21 +16,21 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../../common/eqemu_logsys.h" -#include "../../common/global_define.h" -#include "../../common/shareddb.h" -#include "../../common/eqemu_config.h" -#include "../../common/platform.h" -#include "../../common/crash.h" -#include "../../common/rulesys.h" -#include "../../common/strings.h" -#include "../../common/content/world_content_service.h" -#include "../../common/zone_store.h" -#include "../../common/path_manager.h" -#include "../../common/repositories/base_data_repository.h" -#include "../../common/file.h" -#include "../../common/events/player_event_logs.h" -#include "../../common/evolving_items.h" +#include "common/content/world_content_service.h" +#include "common/crash.h" +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/evolving_items.h" +#include "common/file.h" +#include "common/global_define.h" +#include "common/path_manager.h" +#include "common/platform.h" +#include "common/repositories/base_data_repository.h" +#include "common/rulesys.h" +#include "common/shareddb.h" +#include "common/strings.h" +#include "common/zone_store.h" void ImportSpells(SharedDatabase *db); void ImportSkillCaps(SharedDatabase *db); From 451eb0806a81a46c5501859eedd3cffbdfbb2b9e Mon Sep 17 00:00:00 2001 From: brainiac Date: Wed, 17 Dec 2025 09:32:44 -0800 Subject: [PATCH 063/194] normalize includes: common --- common/CMakeLists.txt | 1 + common/additive_lagged_fibonacci_engine.h | 4 +- common/base_packet.cpp | 8 +- common/base_packet.h | 16 ++-- common/bazaar.cpp | 5 +- common/bazaar.h | 11 +-- common/bodytypes.cpp | 5 +- common/bodytypes.h | 9 +- common/classes.cpp | 12 ++- common/classes.h | 13 ++- common/cli/eqemu_command_handler.cpp | 10 +- common/compression.cpp | 11 ++- common/compression.h | 2 + common/condition.h | 11 +-- common/content/world_content_service.cpp | 14 +-- common/content/world_content_service.h | 13 ++- common/crash.cpp | 25 ++--- common/crash.h | 5 +- common/crc16.cpp | 5 +- common/crc16.h | 8 +- common/crc32.cpp | 3 +- common/crc32.h | 7 +- common/cron/croncpp.h | 8 +- common/data_bucket.cpp | 11 ++- common/data_bucket.h | 14 ++- common/database.cpp | 91 +++++++++---------- common/database.h | 22 ++--- common/database/database_dump_service.cpp | 23 +++-- common/database/database_dump_service.h | 7 +- common/database/database_update.cpp | 23 +++-- common/database/database_update.h | 8 +- common/database/database_update_manifest.h | 4 + .../database/database_update_manifest_bots.h | 4 + .../database_update_manifest_custom.h | 4 + common/database_instances.cpp | 37 ++++---- common/database_schema.h | 5 +- common/dbcore.cpp | 22 ++--- common/dbcore.h | 18 +--- common/deity.h | 8 +- common/discord/discord.cpp | 16 ++-- common/discord/discord.h | 15 ++- common/discord/discord_manager.cpp | 5 +- common/discord/discord_manager.h | 19 ++-- common/dynamic_zone_base.cpp | 19 ++-- common/dynamic_zone_base.h | 16 ++-- common/dynamic_zone_lockout.cpp | 9 +- common/dynamic_zone_lockout.h | 3 +- common/emu_constants.cpp | 12 +-- common/emu_constants.h | 13 +-- common/emu_limits.h | 9 +- common/emu_opcodes.cpp | 10 +- common/emu_opcodes.h | 7 +- common/emu_versions.cpp | 4 +- common/emu_versions.h | 10 +- common/eq_constants.h | 9 +- common/eq_limits.cpp | 6 +- common/eq_limits.h | 23 ++--- common/eq_packet.cpp | 22 ++--- common/eq_packet.h | 13 +-- common/eq_packet_structs.h | 28 +++--- common/eq_stream.cpp | 38 ++++---- common/eq_stream.h | 27 +++--- common/eq_stream_factory.cpp | 23 +++-- common/eq_stream_factory.h | 14 +-- common/eq_stream_ident.cpp | 14 +-- common/eq_stream_ident.h | 14 ++- common/eq_stream_intf.h | 15 ++- common/eq_stream_locator.h | 14 +-- common/eq_stream_proxy.cpp | 9 +- common/eq_stream_proxy.h | 10 +- common/eq_stream_type.h | 5 +- common/eqdb.cpp | 9 +- common/eqdb.h | 15 ++- common/eqdb_res.cpp | 7 +- common/eqdb_res.h | 13 ++- common/eqemu_config.cpp | 13 +-- common/eqemu_config.h | 16 ++-- common/eqemu_exception.h | 5 +- common/eqemu_logsys.cpp | 36 ++++---- common/eqemu_logsys.h | 18 ++-- common/eqemu_logsys_log_aliases.h | 8 +- common/eqtime.cpp | 13 ++- common/eqtime.h | 8 +- common/event/event_loop.h | 5 +- common/event/task.h | 6 +- common/event/task_scheduler.h | 9 +- common/event/timer.h | 4 +- common/event_sub.h | 2 +- .../events/player_event_discord_formatter.cpp | 15 +-- .../events/player_event_discord_formatter.h | 16 ++-- common/events/player_event_logs.cpp | 22 +++-- common/events/player_event_logs.h | 48 +++++----- common/events/player_events.h | 15 ++- common/evolving_items.cpp | 7 +- common/evolving_items.h | 11 +-- common/extprofile.cpp | 4 +- common/extprofile.h | 14 ++- common/faction.cpp | 6 +- common/faction.h | 10 +- common/features.h | 9 +- common/file.cpp | 17 ++-- common/file.h | 5 +- common/fixed_memory_hash_set.h | 11 +-- common/fixed_memory_variable_hash_set.h | 10 +- common/global_define.h | 6 +- common/guild_base.cpp | 26 +++--- common/guild_base.h | 15 ++- common/guilds.cpp | 8 +- common/guilds.h | 7 +- common/inventory_profile.cpp | 20 ++-- common/inventory_profile.h | 12 +-- common/inventory_slot.cpp | 5 +- common/inventory_slot.h | 7 +- common/ip_util.cpp | 19 ++-- common/ip_util.h | 10 +- common/ipc_mutex.cpp | 13 ++- common/ipc_mutex.h | 5 +- common/item_data.cpp | 6 +- common/item_data.h | 9 +- common/item_instance.cpp | 19 ++-- common/item_instance.h | 25 +++-- common/json_config.cpp | 1 + common/json_config.h | 2 + common/light_source.cpp | 1 - common/light_source.h | 8 +- common/linked_list.h | 9 +- common/loot.h | 8 +- common/md5.cpp | 9 +- common/md5.h | 9 +- common/memory/ksm.hpp | 9 +- common/memory_buffer.h | 11 +-- common/memory_mapped_file.cpp | 7 +- common/memory_mapped_file.h | 8 +- common/misc.cpp | 28 +++--- common/misc.h | 8 +- common/misc_functions.cpp | 56 ++++++------ common/misc_functions.h | 10 +- common/mutex.cpp | 7 +- common/mutex.h | 19 ++-- common/mysql_request_result.h | 23 +---- common/mysql_request_row.h | 16 +--- common/mysql_stmt.cpp | 8 +- common/mysql_stmt.h | 2 +- common/net/console_server.cpp | 7 +- common/net/console_server.h | 1 + common/net/console_server_connection.cpp | 17 ++-- common/net/console_server_connection.h | 3 +- common/net/crc32.cpp | 1 - common/net/crc32.h | 4 +- common/net/dns.h | 5 +- common/net/endian.h | 2 +- common/net/eqstream.cpp | 3 +- common/net/eqstream.h | 11 ++- common/net/packet.cpp | 7 +- common/net/packet.h | 12 ++- common/net/reliable_stream_connection.cpp | 13 +-- common/net/reliable_stream_connection.h | 16 ++-- common/net/reliable_stream_pooling.h | 13 +-- common/net/reliable_stream_structs.h | 5 +- common/net/servertalk_client_connection.cpp | 5 +- common/net/servertalk_client_connection.h | 8 +- common/net/servertalk_common.h | 2 +- .../servertalk_legacy_client_connection.cpp | 5 +- .../net/servertalk_legacy_client_connection.h | 8 +- common/net/servertalk_server.h | 7 +- common/net/servertalk_server_connection.cpp | 7 +- common/net/servertalk_server_connection.h | 7 +- common/net/tcp_connection.cpp | 4 +- common/net/tcp_connection.h | 7 +- common/net/tcp_connection_pooling.h | 11 ++- common/net/tcp_server.cpp | 3 +- common/net/tcp_server.h | 4 +- common/net/websocket_server.cpp | 13 +-- common/net/websocket_server.h | 8 +- common/net/websocket_server_connection.cpp | 11 ++- common/net/websocket_server_connection.h | 11 ++- common/op_codes.h | 5 +- common/opcode_map.cpp | 3 +- common/opcodemgr.cpp | 5 +- common/opcodemgr.h | 12 +-- common/packet_dump.cpp | 8 +- common/packet_dump.h | 11 +-- common/packet_dump_file.cpp | 2 +- common/packet_dump_file.h | 10 +- common/packet_functions.cpp | 16 ++-- common/packet_functions.h | 9 +- common/packetfile.cpp | 14 +-- common/packetfile.h | 7 +- common/patches/patches.cpp | 14 +-- common/patches/patches.h | 5 +- common/patches/rof.cpp | 31 +++---- common/patches/rof.h | 9 +- common/patches/rof2.cpp | 39 ++++---- common/patches/rof2.h | 7 +- common/patches/rof2_limits.cpp | 2 +- common/patches/rof2_limits.h | 13 +-- common/patches/rof2_structs.h | 23 +++-- common/patches/rof_limits.cpp | 2 +- common/patches/rof_limits.h | 13 +-- common/patches/rof_structs.h | 18 ++-- common/patches/sod.cpp | 31 +++---- common/patches/sod.h | 9 +- common/patches/sod_limits.cpp | 2 +- common/patches/sod_limits.h | 13 +-- common/patches/sod_structs.h | 19 ++-- common/patches/sof.cpp | 29 +++--- common/patches/sof.h | 9 +- common/patches/sof_limits.cpp | 2 +- common/patches/sof_limits.h | 13 +-- common/patches/sof_structs.h | 19 ++-- common/patches/template.cpp | 38 ++------ common/patches/template.h | 10 +- common/patches/template_limits.h | 5 +- common/patches/template_structs.h | 25 +---- common/patches/titanium.cpp | 33 ++++--- common/patches/titanium.h | 9 +- common/patches/titanium_limits.cpp | 2 +- common/patches/titanium_limits.h | 13 +-- common/patches/titanium_structs.h | 20 ++-- common/patches/uf.cpp | 40 ++++---- common/patches/uf.h | 7 +- common/patches/uf_limits.cpp | 2 +- common/patches/uf_limits.h | 13 +-- common/patches/uf_structs.h | 19 ++-- common/path_manager.cpp | 9 +- common/path_manager.h | 6 +- common/pch/app-pch.h | 14 +-- common/pch/std-pch.h | 18 ++-- common/perl_eqdb.cpp | 6 +- common/perl_eqdb_res.cpp | 6 +- common/platform.h | 7 +- common/proc_launcher.cpp | 32 +++---- common/proc_launcher.h | 11 +-- common/process.cpp | 7 +- common/process.h | 6 +- common/process/process.cpp | 6 +- common/process/process.h | 8 +- common/profanity_manager.cpp | 11 ++- common/profanity_manager.h | 10 +- common/profiler.h | 10 +- common/ptimer.cpp | 20 ++-- common/ptimer.h | 9 +- common/queue.h | 6 +- common/races.cpp | 5 +- common/races.h | 10 +- common/raid.h | 6 +- common/random.h | 8 +- common/rdtsc.cpp | 11 ++- common/rdtsc.h | 9 +- common/rulesys.cpp | 16 ++-- common/rulesys.h | 18 ++-- common/say_link.cpp | 11 ++- common/say_link.h | 11 +-- common/seperator.h | 9 +- common/serialize_buffer.h | 8 +- common/server_event_scheduler.cpp | 8 +- common/server_event_scheduler.h | 8 +- common/server_reload_types.h | 9 +- common/serverinfo.cpp | 3 +- common/serverinfo.h | 2 +- common/servertalk.h | 33 +++---- common/shared_tasks.cpp | 4 +- common/shared_tasks.h | 27 +++--- common/shareddb.cpp | 67 ++++++-------- common/shareddb.h | 25 +++-- common/skill_caps.cpp | 3 +- common/skill_caps.h | 14 +-- common/skills.cpp | 3 +- common/skills.h | 9 +- common/spdat.cpp | 24 +++-- common/spdat.h | 12 +-- common/spdat_bot.cpp | 3 +- common/strings.cpp | 20 ++-- common/strings.h | 19 ++-- common/strings_legacy.cpp | 25 ++--- common/strings_misc.cpp | 23 ++--- common/struct_strategy.cpp | 35 +------ common/struct_strategy.h | 42 ++------- common/tasks.h | 12 +-- common/textures.h | 8 +- common/timeoutmgr.cpp | 7 +- common/timeoutmgr.h | 16 ++-- common/timer.cpp | 4 +- common/timer.h | 11 +-- common/types.h | 8 +- common/unix.cpp | 3 +- common/unix.h | 3 +- common/useperl.h | 7 +- common/util/directory.cpp | 2 +- common/util/memory_stream.h | 2 +- common/util/uuid.cpp | 4 +- common/util/uuid.h | 2 +- common/version.h | 6 +- common/zone_store.cpp | 10 +- common/zone_store.h | 11 +-- 295 files changed, 1589 insertions(+), 2006 deletions(-) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 23fbcff69a..f250adbb17 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -765,6 +765,7 @@ add_library(common ${common_sources} ${common_headers} ${repositories}) target_compile_definitions(common PUBLIC BOOST_BIND_GLOBAL_PLACEHOLDERS GLM_FORCE_RADIANS GLM_FORCE_CTOR_INIT GLM_ENABLE_EXPERIMENTAL ENABLE_SECURITY) target_include_directories(common PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../submodules/websocketpp") +target_include_directories(common PRIVATE ..) target_link_libraries(common PUBLIC cereal::cereal fmt::fmt unofficial::libmariadb $,libuv::uv_a,libuv::uv> OpenSSL::SSL OpenSSL::Crypto ZLIB::ZLIB unofficial-sodium::sodium) # Requires libgoogle-perftools-dev google-perftools packages for linux (debian) diff --git a/common/additive_lagged_fibonacci_engine.h b/common/additive_lagged_fibonacci_engine.h index b396b44362..0cd9c6a52f 100644 --- a/common/additive_lagged_fibonacci_engine.h +++ b/common/additive_lagged_fibonacci_engine.h @@ -18,11 +18,11 @@ #pragma once +#include #include +#include #include #include -#include -#include /* * This is an additive lagged fibonacci generator as seen in The Art of Computer Programming, Vol. 2 diff --git a/common/base_packet.cpp b/common/base_packet.cpp index 67f8f90340..15608c2bb7 100644 --- a/common/base_packet.cpp +++ b/common/base_packet.cpp @@ -16,10 +16,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "global_define.h" -#include "base_packet.h" -#include "misc.h" -#include "packet_dump.h" +#include "common/base_packet.h" +#include "common/global_define.h" +#include "common/misc.h" +#include "common/packet_dump.h" BasePacket::BasePacket(const unsigned char *buf, uint32 len) { diff --git a/common/base_packet.h b/common/base_packet.h index 3b92e3e90e..803f37b8d2 100644 --- a/common/base_packet.h +++ b/common/base_packet.h @@ -15,13 +15,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef BASEPACKET_H_ -#define BASEPACKET_H_ -#include "types.h" -#include "serialize_buffer.h" -#include -#include +#pragma once + +#include "common/serialize_buffer.h" +#include "common/types.h" + +#include +#include #ifdef _WINDOWS #include @@ -93,6 +94,3 @@ class BasePacket { extern void DumpPacketHex(const BasePacket* app); extern void DumpPacketAscii(const BasePacket* app); extern void DumpPacketBin(const BasePacket* app); - -#endif /*BASEPACKET_H_*/ - diff --git a/common/bazaar.cpp b/common/bazaar.cpp index 8244d5c52f..870d275a25 100644 --- a/common/bazaar.cpp +++ b/common/bazaar.cpp @@ -1,7 +1,8 @@ #include "bazaar.h" -#include "../../common/item_instance.h" -#include "repositories/trader_repository.h" +#include "common/item_instance.h" +#include "common/repositories/trader_repository.h" + #include std::vector diff --git a/common/bazaar.h b/common/bazaar.h index bec1ae264b..aa7f24975e 100644 --- a/common/bazaar.h +++ b/common/bazaar.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BAZAAR_H -#define EQEMU_BAZAAR_H +#pragma once + +#include "common/item_instance.h" +#include "common/shareddb.h" #include -#include "shareddb.h" -#include "../../common/item_instance.h" class Bazaar { public: @@ -11,6 +11,3 @@ class Bazaar { GetSearchResults(Database &content_db, Database &db, BazaarSearchCriteria_Struct search, unsigned int char_zone_id, int char_zone_instance_id); }; - - -#endif //EQEMU_BAZAAR_H diff --git a/common/bodytypes.cpp b/common/bodytypes.cpp index d8f2441bb8..9de4130f4f 100644 --- a/common/bodytypes.cpp +++ b/common/bodytypes.cpp @@ -1,5 +1,6 @@ -#include "../common/global_define.h" -#include "../common/bodytypes.h" +#include "bodytypes.h" + +#include "common/global_define.h" std::string BodyType::GetName(uint8 body_type_id) { diff --git a/common/bodytypes.h b/common/bodytypes.h index e887734613..658cc063e3 100644 --- a/common/bodytypes.h +++ b/common/bodytypes.h @@ -15,10 +15,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef BODYTYPES_H -#define BODYTYPES_H -#include "types.h" +#pragma once + +#include "common/types.h" + #include #include @@ -109,5 +110,3 @@ static std::map body_type_names = { { BodyType::InvisibleMan, "Invisible Man" }, { BodyType::Special, "Special" }, }; - -#endif diff --git a/common/classes.cpp b/common/classes.cpp index df13500043..704c3c97f0 100644 --- a/common/classes.cpp +++ b/common/classes.cpp @@ -15,11 +15,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include "../common/global_define.h" -#include "../common/classes.h" -#include "data_verification.h" + +#include "classes.h" + +#include "common/data_verification.h" +#include "common/global_define.h" + +#include "fmt/format.h" const char *GetClassIDName(uint8 class_id, uint8 level) { diff --git a/common/classes.h b/common/classes.h index dc586ceebf..fefae49409 100644 --- a/common/classes.h +++ b/common/classes.h @@ -15,13 +15,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef CLASSES_CH -#define CLASSES_CH -#include "../common/types.h" -#include "../common/rulesys.h" -#include +#pragma once + +#include "common/rulesys.h" +#include "common/types.h" + #include +#include namespace Class { constexpr uint8 None = 0; @@ -156,5 +157,3 @@ bool IsChainClass(uint8 class_id); bool IsLeatherClass(uint8 class_id); bool IsClothClass(uint8 class_id); uint8 ClassArmorType(uint8 class_id); - -#endif diff --git a/common/cli/eqemu_command_handler.cpp b/common/cli/eqemu_command_handler.cpp index bf796b42b1..75626670a9 100644 --- a/common/cli/eqemu_command_handler.cpp +++ b/common/cli/eqemu_command_handler.cpp @@ -18,11 +18,11 @@ * */ -#include -#include -#include "eqemu_command_handler.h" -#include "terminal_color.hpp" -#include "../platform.h" +#include "common/cli/eqemu_command_handler.h" +#include "common/cli/terminal_color.hpp" +#include "common/platform.h" + +#include "fmt/format.h" namespace EQEmuCommand { diff --git a/common/compression.cpp b/common/compression.cpp index 07fe13d65e..2f8233b286 100644 --- a/common/compression.cpp +++ b/common/compression.cpp @@ -1,7 +1,10 @@ -#include "global_define.h" -#include "types.h" -#include -#include +#include "compression.h" + +#include "common/global_define.h" +#include "common/types.h" + +#include "zlib.h" +#include namespace EQ { diff --git a/common/compression.h b/common/compression.h index 20a4103be2..0ef2b0e5fd 100644 --- a/common/compression.h +++ b/common/compression.h @@ -1,5 +1,7 @@ #pragma once +#include "common/types.h" + namespace EQ { uint32 EstimateDeflateBuffer(uint32 len); diff --git a/common/condition.h b/common/condition.h index 9c4cd9f7b1..7402589e7b 100644 --- a/common/condition.h +++ b/common/condition.h @@ -15,11 +15,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __CONDITION_H -#define __CONDITION_H -#include "global_define.h" -#include "mutex.h" +#pragma once + +#include "common/global_define.h" +#include "common/mutex.h" #ifndef WIN32 #include #endif @@ -52,6 +52,3 @@ class Condition { // bool TimedWait(unsigned long usec); ~Condition(); }; - -#endif - diff --git a/common/content/world_content_service.cpp b/common/content/world_content_service.cpp index d6511e7108..994906dfc1 100644 --- a/common/content/world_content_service.cpp +++ b/common/content/world_content_service.cpp @@ -1,13 +1,13 @@ #include "world_content_service.h" -#include -#include -#include "../database.h" -#include "../rulesys.h" -#include "../eqemu_logsys.h" -#include "../repositories/instance_list_repository.h" -#include "../zone_store.h" +#include "common/database.h" +#include "common/eqemu_logsys.h" +#include "common/repositories/instance_list_repository.h" +#include "common/rulesys.h" +#include "common/zone_store.h" +#include "glm/vec3.hpp" +#include WorldContentService::WorldContentService() { diff --git a/common/content/world_content_service.h b/common/content/world_content_service.h index 0f84682d76..5532d3f3b7 100644 --- a/common/content/world_content_service.h +++ b/common/content/world_content_service.h @@ -1,11 +1,12 @@ -#ifndef EQEMU_WORLD_CONTENT_SERVICE_H -#define EQEMU_WORLD_CONTENT_SERVICE_H + +#pragma once + +#include "common/repositories/content_flags_repository.h" +#include "common/repositories/instance_list_repository.h" +#include "common/repositories/zone_repository.h" #include #include -#include "../repositories/content_flags_repository.h" -#include "../repositories/zone_repository.h" -#include "../repositories/instance_list_repository.h" class Database; @@ -199,5 +200,3 @@ class WorldContentService { WorldContentService *LoadStaticGlobalZoneInstances(); std::vector m_zone_static_instances; }; - -#endif //EQEMU_WORLD_CONTENT_SERVICE_H diff --git a/common/crash.cpp b/common/crash.cpp index b7dcac7a47..93eb739ea8 100644 --- a/common/crash.cpp +++ b/common/crash.cpp @@ -1,16 +1,17 @@ -#include "global_define.h" -#include "eqemu_logsys.h" #include "crash.h" -#include "strings.h" -#include "process/process.h" -#include "http/httplib.h" -#include "http/uri.h" -#include "json/json.h" -#include "version.h" -#include "eqemu_config.h" -#include "serverinfo.h" -#include "rulesys.h" -#include "platform.h" + +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/http/httplib.h" +#include "common/http/uri.h" +#include "common/json/json.h" +#include "common/platform.h" +#include "common/process/process.h" +#include "common/rulesys.h" +#include "common/serverinfo.h" +#include "common/strings.h" +#include "common/version.h" #include #include diff --git a/common/crash.h b/common/crash.h index ca53d620ea..7da1b7a4ad 100644 --- a/common/crash.h +++ b/common/crash.h @@ -1,6 +1,3 @@ -#ifndef __EQEMU_CRASH_H -#define __EQEMU_CRASH_H +#pragma once void set_exception_handler(); - -#endif diff --git a/common/crc16.cpp b/common/crc16.cpp index 9e79dc4703..38c8ac7ea8 100644 --- a/common/crc16.cpp +++ b/common/crc16.cpp @@ -1,4 +1,6 @@ -#include "crc32.h" +#include "crc16.h" + +#include "common/crc32.h" uint16 CRC16(const unsigned char *buf, int size, int key) { @@ -12,4 +14,3 @@ uint16 CRC16(const unsigned char *buf, int size, int key) crc = CRC32::Update(buf, size, crc); return CRC32::Finish(crc) & 0xffff; } - diff --git a/common/crc16.h b/common/crc16.h index 04de64e1e2..f9059b492c 100644 --- a/common/crc16.h +++ b/common/crc16.h @@ -1,7 +1,5 @@ -#ifndef _CRC16_H -#define _CRC16_H -#include "types.h" +#pragma once -uint16 CRC16(const unsigned char *buf, int size, int key); +#include "common/types.h" -#endif +uint16 CRC16(const unsigned char *buf, int size, int key); diff --git a/common/crc32.cpp b/common/crc32.cpp index 0e9746a089..4d7bf89edb 100644 --- a/common/crc32.cpp +++ b/common/crc32.cpp @@ -1,5 +1,6 @@ #include "crc32.h" -#include + +#include #include uint32 CRC32Table[256] = diff --git a/common/crc32.h b/common/crc32.h index 3a391a5648..023d63359a 100644 --- a/common/crc32.h +++ b/common/crc32.h @@ -1,6 +1,6 @@ -#ifndef CRC32_H -#define CRC32_H -#include "types.h" +#pragma once + +#include "common/types.h" class CRC32 { public: @@ -17,4 +17,3 @@ class CRC32 { private: static inline void Calc(const uint8 byte, uint32& crc32); }; -#endif diff --git a/common/cron/croncpp.h b/common/cron/croncpp.h index 3034dc9523..40c37863f0 100644 --- a/common/cron/croncpp.h +++ b/common/cron/croncpp.h @@ -1,13 +1,13 @@ #pragma once -#include -#include -#include +#include #include #include #include #include -#include +#include +#include +#include #if __cplusplus > 201402L #include diff --git a/common/data_bucket.cpp b/common/data_bucket.cpp index 0378c379f3..e138320367 100644 --- a/common/data_bucket.cpp +++ b/common/data_bucket.cpp @@ -1,8 +1,11 @@ -#include "../common/data_bucket.h" -#include "database.h" -#include +#include "data_bucket.h" + +#include "common/data_bucket.h" +#include "common/database.h" +#include "common/json/json.hpp" + #include -#include "../common/json/json.hpp" +#include using json = nlohmann::json; diff --git a/common/data_bucket.h b/common/data_bucket.h index c93d98b2c3..7625a545f8 100644 --- a/common/data_bucket.h +++ b/common/data_bucket.h @@ -1,11 +1,11 @@ -#ifndef EQEMU_DATABUCKET_H -#define EQEMU_DATABUCKET_H +#pragma once + +#include "common/json/json_archive_single_line.h" +#include "common/repositories/data_buckets_repository.h" +#include "common/shareddb.h" +#include "common/types.h" #include -#include "types.h" -#include "repositories/data_buckets_repository.h" -#include "json/json_archive_single_line.h" -#include "shareddb.h" struct DataBucketKey { std::string key; @@ -69,5 +69,3 @@ class DataBucket { static DataBucketsRepository::DataBuckets ExtractNestedValue(const DataBucketsRepository::DataBuckets &bucket, const std::string &full_key); }; - -#endif //EQEMU_DATABUCKET_H diff --git a/common/database.cpp b/common/database.cpp index 3052fd722c..e0532037dc 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -16,42 +16,56 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/rulesys.h" +#include "common/data_verification.h" +#include "common/database_schema.h" +#include "common/database.h" +#include "common/eq_packet_structs.h" +#include "common/events/player_event_logs.h" +#include "common/extprofile.h" +#include "common/global_define.h" +#include "common/http/httplib.h" +#include "common/http/uri.h" +#include "common/repositories/account_repository.h" +#include "common/repositories/adventure_stats_repository.h" +#include "common/repositories/bot_data_repository.h" +#include "common/repositories/buyer_repository.h" +#include "common/repositories/character_bind_repository.h" +#include "common/repositories/character_data_repository.h" +#include "common/repositories/character_languages_repository.h" +#include "common/repositories/character_leadership_abilities_repository.h" +#include "common/repositories/character_parcels_repository.h" +#include "common/repositories/character_pet_name_repository.h" +#include "common/repositories/character_skills_repository.h" +#include "common/repositories/data_buckets_repository.h" +#include "common/repositories/group_id_repository.h" +#include "common/repositories/group_leaders_repository.h" +#include "common/repositories/guild_members_repository.h" +#include "common/repositories/instance_list_repository.h" +#include "common/repositories/inventory_snapshots_repository.h" +#include "common/repositories/ip_exemptions_repository.h" +#include "common/repositories/merchantlist_temp_repository.h" +#include "common/repositories/name_filter_repository.h" +#include "common/repositories/npc_types_repository.h" +#include "common/repositories/raid_details_repository.h" +#include "common/repositories/raid_members_repository.h" +#include "common/repositories/reports_repository.h" +#include "common/repositories/trader_repository.h" +#include "common/repositories/variables_repository.h" +#include "common/repositories/zone_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "common/zone_store.h" + +#include "mysqld_error.h" #include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include - -#include "../common/repositories/account_repository.h" -#include "../common/repositories/adventure_stats_repository.h" -#include "../common/repositories/character_bind_repository.h" -#include "../common/repositories/character_data_repository.h" -#include "../common/repositories/character_languages_repository.h" -#include "../common/repositories/character_leadership_abilities_repository.h" -#include "../common/repositories/character_parcels_repository.h" -#include "../common/repositories/character_skills_repository.h" -#include "../common/repositories/data_buckets_repository.h" -#include "../common/repositories/group_id_repository.h" -#include "../common/repositories/group_leaders_repository.h" -#include "../common/repositories/guild_members_repository.h" -#include "../common/repositories/instance_list_repository.h" -#include "../common/repositories/inventory_snapshots_repository.h" -#include "../common/repositories/ip_exemptions_repository.h" -#include "../common/repositories/name_filter_repository.h" -#include "../common/repositories/npc_types_repository.h" -#include "../common/repositories/raid_details_repository.h" -#include "../common/repositories/raid_members_repository.h" -#include "../common/repositories/reports_repository.h" -#include "../common/repositories/variables_repository.h" -#include "../common/repositories/character_pet_name_repository.h" -#include "../common/events/player_event_logs.h" // Disgrace: for windows compile #ifdef _WINDOWS @@ -63,25 +77,8 @@ #include "unix.h" #include #include - #endif -#include "database.h" -#include "data_verification.h" -#include "eq_packet_structs.h" -#include "extprofile.h" -#include "strings.h" -#include "database_schema.h" -#include "http/httplib.h" -#include "http/uri.h" - -#include "repositories/zone_repository.h" -#include "zone_store.h" -#include "repositories/merchantlist_temp_repository.h" -#include "repositories/bot_data_repository.h" -#include "repositories/trader_repository.h" -#include "repositories/buyer_repository.h" - extern Client client; Database::Database() { } diff --git a/common/database.h b/common/database.h index 9b81f66a0d..8a0f333d06 100644 --- a/common/database.h +++ b/common/database.h @@ -15,25 +15,23 @@ 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_DATABASE_H -#define EQEMU_DATABASE_H -#define AUTHENTICATION_TIMEOUT 60 -#define INVALID_ID 0xFFFFFFFF +#pragma once -#include "global_define.h" -#include "eqemu_logsys.h" - -#include "types.h" -#include "dbcore.h" -#include "linked_list.h" -#include "eq_packet_structs.h" +#include "common/dbcore.h" +#include "common/eq_packet_structs.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/linked_list.h" +#include "common/types.h" #include #include #include #include +#define AUTHENTICATION_TIMEOUT 60 +#define INVALID_ID 0xFFFFFFFF class MySQLRequestResult; class Client; @@ -292,5 +290,3 @@ class Database : public DBcore { void ClearAllRaidDetails(); void ClearAllRaidLeaders(); }; - -#endif diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index 6cbea2d480..dc36040ee4 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -18,27 +18,26 @@ * */ -#include -#include -#include #include "database_dump_service.h" -#include "../eqemu_logsys.h" -#include "../strings.h" -#include "../eqemu_config.h" -#include "../database_schema.h" -#include "../file.h" -#include "../process/process.h" -#include "../termcolor/rang.hpp" +#include "common/database_schema.h" +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/file.h" +#include "common/process/process.h" +#include "common/strings.h" +#include "common/termcolor/rang.hpp" + +#include #include +#include +#include #if _WIN32 #include #else - #include #include - #endif #define DATABASE_DUMP_PATH "backups/" diff --git a/common/database/database_dump_service.h b/common/database/database_dump_service.h index fde5dc218a..6169011a16 100644 --- a/common/database/database_dump_service.h +++ b/common/database/database_dump_service.h @@ -18,9 +18,9 @@ * */ -#ifndef EQEMU_DATABASE_DUMP_SERVICE_H -#define EQEMU_DATABASE_DUMP_SERVICE_H +#pragma once +#include class DatabaseDumpService { public: @@ -97,6 +97,3 @@ class DatabaseDumpService { void BuildCredentialsFile(); void RemoveCredentialsFile(); }; - - -#endif //EQEMU_DATABASE_DUMP_SERVICE_H diff --git a/common/database/database_update.cpp b/common/database/database_update.cpp index d1837b448b..493da59186 100644 --- a/common/database/database_update.cpp +++ b/common/database/database_update.cpp @@ -1,14 +1,17 @@ -#include #include "database_update.h" -#include "../eqemu_logsys.h" -#include "../database.h" -#include "../strings.h" -#include "../rulesys.h" -#include "../http/httplib.h" -#include "database_dump_service.h" -#include "database_update_manifest.h" -#include "database_update_manifest_custom.h" -#include "database_update_manifest_bots.h" + +#include "common/database.h" +#include "common/database/database_dump_service.h" +#include "common/database/database_update_manifest_bots.h" +#include "common/database/database_update_manifest_custom.h" +#include "common/database/database_update_manifest.h" +#include "common/eqemu_logsys.h" +#include "common/http/httplib.h" +#include "common/rulesys.h" +#include "common/strings.h" + +#include + constexpr int BREAK_LENGTH = 70; diff --git a/common/database/database_update.h b/common/database/database_update.h index a445422bc8..39084f4b50 100644 --- a/common/database/database_update.h +++ b/common/database/database_update.h @@ -1,7 +1,6 @@ -#ifndef EQEMU_DATABASE_UPDATE_H -#define EQEMU_DATABASE_UPDATE_H +#pragma once -#include "../database.h" +#include "common/database.h" struct ManifestEntry { int version{}; // database version of the migration @@ -47,7 +46,4 @@ class DatabaseUpdate { static bool CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b); void InjectBotsVersionColumn(); void InjectCustomVersionColumn(); - }; - -#endif //EQEMU_DATABASE_UPDATE_H diff --git a/common/database/database_update_manifest.h b/common/database/database_update_manifest.h index 6e88d04819..a32ec7db8e 100644 --- a/common/database/database_update_manifest.h +++ b/common/database/database_update_manifest.h @@ -1,5 +1,9 @@ #pragma once +#include "common/database/database_update.h" + +#include + std::vector manifest_entries = { ManifestEntry{ .version = 9000, diff --git a/common/database/database_update_manifest_bots.h b/common/database/database_update_manifest_bots.h index 4f492bda7b..6c58df2744 100644 --- a/common/database/database_update_manifest_bots.h +++ b/common/database/database_update_manifest_bots.h @@ -1,5 +1,9 @@ #pragma once +#include "common/database/database_update.h" + +#include + std::vector bot_manifest_entries = { ManifestEntry{ .version = 9035, diff --git a/common/database/database_update_manifest_custom.h b/common/database/database_update_manifest_custom.h index 61bc102961..70d6dbb1c0 100644 --- a/common/database/database_update_manifest_custom.h +++ b/common/database/database_update_manifest_custom.h @@ -1,5 +1,9 @@ #pragma once +#include "common/database/database_update.h" + +#include + std::vector manifest_entries_custom = { ManifestEntry{ .version = 1, diff --git a/common/database_instances.cpp b/common/database_instances.cpp index e32720f382..05af2aeccb 100644 --- a/common/database_instances.cpp +++ b/common/database_instances.cpp @@ -16,24 +16,25 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/rulesys.h" -#include "../common/strings.h" -#include "../common/timer.h" -#include "../common/repositories/character_corpses_repository.h" -#include "../common/repositories/dynamic_zone_members_repository.h" -#include "../common/repositories/dynamic_zones_repository.h" -#include "../common/repositories/group_id_repository.h" -#include "../common/repositories/instance_list_repository.h" -#include "../common/repositories/instance_list_player_repository.h" -#include "../common/repositories/raid_members_repository.h" -#include "../common/repositories/respawn_times_repository.h" -#include "../common/repositories/spawn_condition_values_repository.h" -#include "repositories/spawn2_disabled_repository.h" -#include "repositories/data_buckets_repository.h" -#include "repositories/zone_state_spawns_repository.h" #include "database.h" +#include "common/global_define.h" +#include "common/repositories/character_corpses_repository.h" +#include "common/repositories/data_buckets_repository.h" +#include "common/repositories/dynamic_zone_members_repository.h" +#include "common/repositories/dynamic_zones_repository.h" +#include "common/repositories/group_id_repository.h" +#include "common/repositories/instance_list_player_repository.h" +#include "common/repositories/instance_list_repository.h" +#include "common/repositories/raid_members_repository.h" +#include "common/repositories/respawn_times_repository.h" +#include "common/repositories/spawn_condition_values_repository.h" +#include "common/repositories/spawn2_disabled_repository.h" +#include "common/repositories/zone_state_spawns_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "common/timer.h" + #include #include @@ -44,8 +45,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define strncasecmp _strnicmp #define strcasecmp _stricmp #else -#include "unix.h" -#include "../zone/zonedb.h" +#include "common/unix.h" +#include "zone/zonedb.h" #include #include #endif diff --git a/common/database_schema.h b/common/database_schema.h index de6f8472fb..091e5a7ac9 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -18,8 +18,7 @@ * */ -#ifndef EQEMU_DATABASE_SCHEMA_H -#define EQEMU_DATABASE_SCHEMA_H +#pragma once #include #include @@ -438,5 +437,3 @@ namespace DatabaseSchema { } } - -#endif //EQEMU_DATABASE_SCHEMA_H diff --git a/common/dbcore.cpp b/common/dbcore.cpp index bb233536c2..6b8ae9dc4e 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -1,30 +1,26 @@ -#ifdef _WINDOWS -#include -#endif +#include "dbcore.h" -#include "misc_functions.h" -#include "eqemu_logsys.h" -#include "timer.h" +#include "common/eqemu_logsys.h" +#include "common/misc_functions.h" +#include "common/mysql_stmt.h" +#include "common/strings.h" +#include "common/timer.h" -#include "dbcore.h" -#include "mysql_stmt.h" +#include "mysqld_error.h" #include #include -#include #include -#include "strings.h" #ifdef _WINDOWS #define snprintf _snprintf #define strncasecmp _strnicmp #define strcasecmp _stricmp #include +#include #else - -#include "unix.h" +#include "common/unix.h" #include - #endif #ifdef _EQDEBUG diff --git a/common/dbcore.h b/common/dbcore.h index 6d07f1bdb7..978ab96bc4 100644 --- a/common/dbcore.h +++ b/common/dbcore.h @@ -1,16 +1,11 @@ -#ifndef DBCORE_H -#define DBCORE_H +#pragma once -#ifdef _WINDOWS -#include -#include -#endif +#include "common/mutex.h" +#include "common/mysql_request_result.h" +#include "common/types.h" -#include "../common/mutex.h" -#include "../common/mysql_request_result.h" -#include "../common/types.h" +#include "mysql.h" -#include #include #include @@ -102,6 +97,3 @@ class DBcore { mysql_set_server_option(mysql, MYSQL_OPTION_MULTI_STATEMENTS_OFF); } }; - - -#endif diff --git a/common/deity.h b/common/deity.h index 370e009b6d..6b676e2b72 100644 --- a/common/deity.h +++ b/common/deity.h @@ -17,10 +17,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_DEITY_H -#define COMMON_DEITY_H +#pragma once + +#include "common/types.h" -#include "types.h" #include #include #include @@ -113,5 +113,3 @@ static std::map deity_bitmasks = { { Deity::Tunare, Deity::Bitmask::Tunare }, { Deity::Veeshan, Deity::Bitmask::Veeshan } }; - -#endif /* COMMON_DEITY_H */ diff --git a/common/discord/discord.cpp b/common/discord/discord.cpp index ec75e05603..3f3c5e492c 100644 --- a/common/discord/discord.cpp +++ b/common/discord/discord.cpp @@ -1,11 +1,13 @@ -#include -#include #include "discord.h" -#include "../http/httplib.h" -#include "../json/json.h" -#include "../strings.h" -#include "../eqemu_logsys.h" -#include "../events/player_event_logs.h" + +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/http/httplib.h" +#include "common/json/json.h" +#include "common/strings.h" + +#include "cereal/archives/binary.hpp" +#include "cereal/archives/json.hpp" constexpr int MAX_RETRIES = 10; diff --git a/common/discord/discord.h b/common/discord/discord.h index 8b8a19290e..47ab075699 100644 --- a/common/discord/discord.h +++ b/common/discord/discord.h @@ -1,19 +1,16 @@ -#ifndef EQEMU_DISCORD_H -#define EQEMU_DISCORD_H +#pragma once +#include "common/events/player_events.h" +#include "common/repositories/player_event_logs_repository.h" +#include "common/types.h" #include -#include "../types.h" -#include "../repositories/player_event_logs_repository.h" -#include "../events/player_events.h" -class Discord { +class Discord +{ public: static void SendWebhookMessage(const std::string& message, const std::string& webhook_url); static std::string FormatDiscordMessage(uint16 category_id, const std::string& message); static void SendPlayerEventMessage(const PlayerEvent::PlayerEventContainer& e, const std::string &webhook_url); static bool ValidateWebhookUrl(const std::string &webhook_url); }; - - -#endif //EQEMU_DISCORD_H diff --git a/common/discord/discord_manager.cpp b/common/discord/discord_manager.cpp index fef6debb4a..5ff5810ab5 100644 --- a/common/discord/discord_manager.cpp +++ b/common/discord/discord_manager.cpp @@ -1,6 +1,7 @@ #include "discord_manager.h" -#include "../../common/discord/discord.h" -#include "../events/player_event_logs.h" + +#include "common/discord/discord.h" +#include "common/events/player_event_logs.h" void DiscordManager::QueueWebhookMessage(uint32 webhook_id, const std::string &message) { diff --git a/common/discord/discord_manager.h b/common/discord/discord_manager.h index d021808596..611e3f03cd 100644 --- a/common/discord/discord_manager.h +++ b/common/discord/discord_manager.h @@ -1,14 +1,16 @@ -#ifndef EQEMU_DISCORD_MANAGER_H -#define EQEMU_DISCORD_MANAGER_H -#include +#pragma once + +#include "common/events/player_events.h" +#include "common/repositories/player_event_logs_repository.h" +#include "common/types.h" + #include +#include #include -#include "../../common/types.h" -#include "../repositories/player_event_logs_repository.h" -#include "../events/player_events.h" -class DiscordManager { +class DiscordManager +{ public: void QueueWebhookMessage(uint32 webhook_id, const std::string& message); void ProcessMessageQueue(); @@ -23,6 +25,3 @@ class DiscordManager { std::mutex webhook_queue_lock{}; std::map> webhook_message_queue{}; }; - - -#endif diff --git a/common/dynamic_zone_base.cpp b/common/dynamic_zone_base.cpp index 4ad08c2db3..0df0e2ba9f 100644 --- a/common/dynamic_zone_base.cpp +++ b/common/dynamic_zone_base.cpp @@ -1,13 +1,14 @@ #include "dynamic_zone_base.h" -#include "database.h" -#include "eqemu_logsys.h" -#include "rulesys.h" -#include "servertalk.h" -#include "util/uuid.h" -#include "repositories/character_expedition_lockouts_repository.h" -#include "repositories/dynamic_zone_lockouts_repository.h" -#include "repositories/instance_list_repository.h" -#include "repositories/instance_list_player_repository.h" + +#include "common/database.h" +#include "common/eqemu_logsys.h" +#include "common/repositories/character_expedition_lockouts_repository.h" +#include "common/repositories/dynamic_zone_lockouts_repository.h" +#include "common/repositories/instance_list_player_repository.h" +#include "common/repositories/instance_list_repository.h" +#include "common/rulesys.h" +#include "common/servertalk.h" +#include "common/util/uuid.h" DynamicZoneBase::DynamicZoneBase(DynamicZonesRepository::DynamicZoneInstance&& entry) { diff --git a/common/dynamic_zone_base.h b/common/dynamic_zone_base.h index 6a43449f40..d0dfe91402 100644 --- a/common/dynamic_zone_base.h +++ b/common/dynamic_zone_base.h @@ -1,11 +1,11 @@ -#ifndef COMMON_DYNAMIC_ZONE_BASE_H -#define COMMON_DYNAMIC_ZONE_BASE_H +#pragma once + +#include "common/dynamic_zone_lockout.h" +#include "common/eq_constants.h" +#include "common/repositories/dynamic_zone_members_repository.h" +#include "common/repositories/dynamic_zone_templates_repository.h" +#include "common/repositories/dynamic_zones_repository.h" -#include "dynamic_zone_lockout.h" -#include "eq_constants.h" -#include "repositories/dynamic_zones_repository.h" -#include "repositories/dynamic_zone_members_repository.h" -#include "repositories/dynamic_zone_templates_repository.h" #include #include #include @@ -270,5 +270,3 @@ class DynamicZoneBase ); } }; - -#endif diff --git a/common/dynamic_zone_lockout.cpp b/common/dynamic_zone_lockout.cpp index a714dc1015..a43e0e5351 100644 --- a/common/dynamic_zone_lockout.cpp +++ b/common/dynamic_zone_lockout.cpp @@ -1,10 +1,11 @@ #include "dynamic_zone_lockout.h" -#include "strings.h" #include "rulesys.h" +#include "strings.h" #include "util/uuid.h" -#include -#include -#include + +#include "fmt/format.h" +#include "cereal/types/chrono.hpp" +#include "cereal/archives/binary.hpp" DzLockout::DzLockout(std::string uuid, std::string expedition, std::string event, uint64_t expire_time, uint32_t duration) : m_uuid(std::move(uuid)) diff --git a/common/dynamic_zone_lockout.h b/common/dynamic_zone_lockout.h index 72dc132bd9..eb800067cd 100644 --- a/common/dynamic_zone_lockout.h +++ b/common/dynamic_zone_lockout.h @@ -1,8 +1,9 @@ #pragma once +#include "repositories/base/base_dynamic_zone_lockouts_repository.h" + #include #include -#include "repositories/base/base_dynamic_zone_lockouts_repository.h" class DzLockout { diff --git a/common/emu_constants.cpp b/common/emu_constants.cpp index ecb1e4c580..8f783c17a6 100644 --- a/common/emu_constants.cpp +++ b/common/emu_constants.cpp @@ -17,12 +17,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "emu_constants.h" -#include "bodytypes.h" -#include "data_verification.h" -#include "eqemu_logsys.h" -#include "eqemu_logsys_log_aliases.h" -#include "rulesys.h" +#include "common/bodytypes.h" +#include "common/data_verification.h" +#include "common/emu_constants.h" +#include "common/eqemu_logsys_log_aliases.h" +#include "common/eqemu_logsys.h" +#include "common/rulesys.h" int16 EQ::invtype::GetInvTypeSize(int16 inv_type) { static const int16 local_array[] = { diff --git a/common/emu_constants.h b/common/emu_constants.h index 0c762ffb8c..e1f9840fed 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -17,14 +17,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_EMU_CONSTANTS_H -#define COMMON_EMU_CONSTANTS_H +#pragma once -#include "eq_limits.h" -#include "emu_versions.h" -#include "bodytypes.h" +#include "common/bodytypes.h" +#include "common/emu_versions.h" +#include "common/eq_limits.h" -#include +#include namespace AccountStatus { constexpr uint8 Player = 0; @@ -918,5 +917,3 @@ namespace PetType { std::string GetName(uint8 pet_type); bool IsValid(uint8 pet_type); } - -#endif /*COMMON_EMU_CONSTANTS_H*/ diff --git a/common/emu_limits.h b/common/emu_limits.h index c855f44ab5..3d61c07ebc 100644 --- a/common/emu_limits.h +++ b/common/emu_limits.h @@ -17,12 +17,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_EMU_LIMITS_H -#define COMMON_EMU_LIMITS_H +#pragma once -#include "types.h" +#include "common/types.h" -#include +#include namespace EntityLimits @@ -124,5 +123,3 @@ namespace EntityLimits } /*Pet*/ }; /*EntityLimits*/ - -#endif /*COMMON_EMU_LIMITS_H*/ diff --git a/common/emu_opcodes.cpp b/common/emu_opcodes.cpp index 00f45fa25a..6e9ad93f82 100644 --- a/common/emu_opcodes.cpp +++ b/common/emu_opcodes.cpp @@ -16,8 +16,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA */ -#include "global_define.h" -#include "emu_opcodes.h" +#include "common/emu_opcodes.h" +#include "common/global_define.h" const char *OpcodeNames[_maxEmuOpcode+1] = { "OP_Unknown", @@ -30,9 +30,3 @@ const char *OpcodeNames[_maxEmuOpcode+1] = { "" }; - - - - - - diff --git a/common/emu_opcodes.h b/common/emu_opcodes.h index 9d5079beae..4c20ccf7b8 100644 --- a/common/emu_opcodes.h +++ b/common/emu_opcodes.h @@ -15,8 +15,8 @@ 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 04111-1307 USA */ -#ifndef EMU_OPCODES_H -#define EMU_OPCODES_H + +#pragma once //this is the highest opcode possibly used in the regular EQ protocol #define MAX_EQ_OPCODE 0xFFFF @@ -47,6 +47,3 @@ typedef enum { //EQEmu internal opcodes list constexpr int format_as(EmuOpcode opcode) { return static_cast(opcode); } extern const char *OpcodeNames[_maxEmuOpcode+1]; - -#endif - diff --git a/common/emu_versions.cpp b/common/emu_versions.cpp index ea8ddba733..30447b3001 100644 --- a/common/emu_versions.cpp +++ b/common/emu_versions.cpp @@ -17,8 +17,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "emu_versions.h" -#include "emu_constants.h" +#include "common/emu_versions.h" +#include "common/emu_constants.h" bool EQ::versions::IsValidClientVersion(ClientVersion client_version) diff --git a/common/emu_versions.h b/common/emu_versions.h index 75f6808c39..d78ac503fc 100644 --- a/common/emu_versions.h +++ b/common/emu_versions.h @@ -17,13 +17,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_EMU_VERSIONS_H -#define COMMON_EMU_VERSIONS_H +#pragma once -#include "types.h" - -#include +#include "common/types.h" +#include namespace EQ { @@ -218,5 +216,3 @@ namespace EQ } /*expansions*/ } /*EQEmu*/ - -#endif /*COMMON_EMU_VERSIONS_H*/ diff --git a/common/eq_constants.h b/common/eq_constants.h index b577b9fb34..815073e157 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -17,11 +17,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_EQ_CONSTANTS_H -#define COMMON_EQ_CONSTANTS_H +#pragma once -#include "skills.h" -#include "types.h" +#include "common/skills.h" +#include "common/types.h" namespace AppearanceType { constexpr uint32 Die = 0; // Causes the client to keel over and zone to bind point (default action) @@ -1096,5 +1095,3 @@ enum ExpSource namespace DoorType { constexpr uint32 BuyerStall = 155; } - -#endif /*COMMON_EQ_CONSTANTS_H*/ diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 1bfbb6d293..600d5dc36b 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -17,9 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "emu_constants.h" -#include "emu_limits.h" -#include "rulesys.h" +#include "common/emu_constants.h" +#include "common/emu_limits.h" +#include "common/rulesys.h" #include diff --git a/common/eq_limits.h b/common/eq_limits.h index 6c00e411ec..4bed002b69 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -17,18 +17,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_EQ_LIMITS_H -#define COMMON_EQ_LIMITS_H +#pragma once -#include "types.h" -#include "eq_constants.h" -#include "emu_versions.h" -#include "../common/patches/titanium_limits.h" -#include "../common/patches/sof_limits.h" -#include "../common/patches/sod_limits.h" -#include "../common/patches/uf_limits.h" -#include "../common/patches/rof_limits.h" -#include "../common/patches/rof2_limits.h" +#include "common/emu_versions.h" +#include "common/eq_constants.h" +#include "common/patches/rof_limits.h" +#include "common/patches/rof2_limits.h" +#include "common/patches/sod_limits.h" +#include "common/patches/sof_limits.h" +#include "common/patches/titanium_limits.h" +#include "common/patches/uf_limits.h" +#include "common/types.h" namespace EQ @@ -268,5 +267,3 @@ namespace Client62 } // namespace constants } /*Client62*/ - -#endif /*COMMON_EQ_LIMITS_H*/ diff --git a/common/eq_packet.cpp b/common/eq_packet.cpp index b2c3f60627..f8797b67df 100644 --- a/common/eq_packet.cpp +++ b/common/eq_packet.cpp @@ -16,25 +16,19 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "crc16.h" -#include "global_define.h" #include "eq_packet.h" -#include "misc.h" -#include "op_codes.h" -#include "platform.h" -#include -#include -#include -#include +#include "common/global_define.h" +#include "common/misc.h" +#include "common/op_codes.h" #ifndef STATIC_OPCODE -#include "opcodemgr.h" +#include "common/opcodemgr.h" #endif +#include "common/packet_dump.h" +#include "common/packet_functions.h" +#include "common/platform.h" -#include "packet_dump.h" -#include "packet_functions.h" -#include -#include +#include EQPacket::EQPacket(EmuOpcode op, const unsigned char *buf, uint32 len) : BasePacket(buf, len), diff --git a/common/eq_packet.h b/common/eq_packet.h index 7eb79a75b6..395a7d702b 100644 --- a/common/eq_packet.h +++ b/common/eq_packet.h @@ -15,18 +15,17 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _EQPACKET_H -#define _EQPACKET_H -#include "base_packet.h" -#include "platform.h" -#include +#pragma once + +#include "common/base_packet.h" +#include "common/platform.h" #ifdef STATIC_OPCODE typedef unsigned short EmuOpcode; static const EmuOpcode OP_Unknown = 0; #else -#include "emu_opcodes.h" +#include "common/emu_opcodes.h" #endif class EQPacket : public BasePacket { @@ -152,5 +151,3 @@ class EQRawApplicationPacket : public EQApplicationPacket { extern void DumpPacket(const EQApplicationPacket* app, bool iShowInfo = false); extern std::string DumpPacketToString(const EQApplicationPacket* app); - -#endif diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index cb0cc7732b..4ea72a1989 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -16,20 +16,20 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef EQ_PACKET_STRUCTS_H -#define EQ_PACKET_STRUCTS_H +#pragma once +#include "common/emu_constants.h" +#include "common/textures.h" +#include "common/types.h" +#include "common/version.h" + +#include "cereal/archives/binary.hpp" +#include "cereal/types/string.hpp" +#include "cereal/types/vector.hpp" #include -#include +#include #include -#include -#include -#include -#include -#include "../common/version.h" -#include "emu_constants.h" -#include "textures.h" -#include "types.h" +#include static const uint32 BUFF_COUNT = 42; static const uint32 PET_BUFF_COUNT = 30; @@ -45,6 +45,7 @@ static const uint32 ADVANCED_LORE_LENGTH = 8192; ** Compiler override to ensure ** byte aligned structures */ +#pragma pack(push) #pragma pack(1) struct LoginInfo { @@ -6562,7 +6563,4 @@ struct EvolveGetNextItem { }; // Restore structure packing to default -#pragma pack() - -#endif - +#pragma pack(pop) diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp index d17ed54c0f..5ae937137b 100644 --- a/common/eq_stream.cpp +++ b/common/eq_stream.cpp @@ -16,31 +16,32 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "global_define.h" -#include "eqemu_logsys.h" -#include "eq_packet.h" #include "eq_stream.h" -#include "op_codes.h" -#include "crc16.h" -#include "platform.h" -#include "strings.h" -#include +#include "common/crc16.h" +#include "common/eq_packet.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/op_codes.h" +#include "common/platform.h" +#include "common/strings.h" + +#include #include +#include #include -#include #ifdef _WINDOWS - #include +#include #else - #include - #include - #include - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include +#include +#include +#include #endif //for logsys @@ -1437,4 +1438,3 @@ EQStream::MatchState EQStream::CheckSignature(const Signature *sig) { return(res); } - diff --git a/common/eq_stream.h b/common/eq_stream.h index a05fb5319e..23ec89b7f0 100644 --- a/common/eq_stream.h +++ b/common/eq_stream.h @@ -1,24 +1,22 @@ -#ifndef _EQSTREAM_H -#define _EQSTREAM_H +#pragma once -#include +#include "common/eq_packet.h" +#include "common/eq_stream_intf.h" +#include "common/eq_stream_type.h" +#include "common/misc.h" +#include "common/mutex.h" +#include "common/opcodemgr.h" +#include "common/timer.h" + +#include #include #include -#include +#include #ifndef WIN32 #include #endif -#include "../common/misc.h" -#include "../common/opcodemgr.h" -#include "../common/timer.h" - -#include "eq_packet.h" -#include "eq_stream_intf.h" -#include "eq_stream_type.h" -#include "mutex.h" - class EQApplicationPacket; class EQProtocolPacket; @@ -314,6 +312,3 @@ class EQStream : public EQStreamInterface { virtual MatchState CheckSignature(const Signature *sig); }; - -#endif - diff --git a/common/eq_stream_factory.cpp b/common/eq_stream_factory.cpp index 429f258f6d..470ac5b73d 100644 --- a/common/eq_stream_factory.cpp +++ b/common/eq_stream_factory.cpp @@ -1,19 +1,18 @@ -#include "global_define.h" -#include "eqemu_logsys.h" #include "eq_stream_factory.h" +#include "common/global_define.h" #ifdef _WINDOWS - #include - #include - #include - #include +#include +#include +#include +#include #else - #include - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include +#include #endif #include diff --git a/common/eq_stream_factory.h b/common/eq_stream_factory.h index 86ffff9791..2aa2b56e48 100644 --- a/common/eq_stream_factory.h +++ b/common/eq_stream_factory.h @@ -1,14 +1,12 @@ -#ifndef _EQSTREAMFACTORY_H +#pragma once -#define _EQSTREAMFACTORY_H +#include "common/condition.h" +#include "common/eq_stream.h" +#include "common/timeoutmgr.h" +#include #include #include -#include - -#include "../common/eq_stream.h" -#include "../common/condition.h" -#include "../common/timeoutmgr.h" class EQStream; class Timer; @@ -57,5 +55,3 @@ class EQStreamFactory : private Timeoutable { void StopWriter() { MWriterRunning.lock(); WriterRunning=false; MWriterRunning.unlock(); WriterWork.Signal(); } void SignalWriter() { WriterWork.Signal(); } }; - -#endif diff --git a/common/eq_stream_ident.cpp b/common/eq_stream_ident.cpp index 8668b72202..f07a54533c 100644 --- a/common/eq_stream_ident.cpp +++ b/common/eq_stream_ident.cpp @@ -1,10 +1,11 @@ -#include -#include "global_define.h" -#include "eqemu_logsys.h" -#include "eq_stream_ident.h" -#include "eq_stream_proxy.h" -#include "misc.h" +#include "common/eq_stream_ident.h" +#include "common/eq_stream_proxy.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/misc.h" + +#include EQStreamIdentifier::~EQStreamIdentifier() { while(!m_identified.empty()) { @@ -162,4 +163,3 @@ EQStreamIdentifier::Record::Record(std::shared_ptr s) expire(STREAM_IDENT_WAIT_MS) { } - diff --git a/common/eq_stream_ident.h b/common/eq_stream_ident.h index e34db5879b..fbce0cf5f4 100644 --- a/common/eq_stream_ident.h +++ b/common/eq_stream_ident.h @@ -1,11 +1,11 @@ -#ifndef EQSTREAMIDENT_H_ -#define EQSTREAMIDENT_H_ +#pragma once + +#include "common/eq_stream_intf.h" +#include "common/timer.h" -#include "eq_stream_intf.h" -#include "timer.h" -#include -#include #include +#include +#include #define STREAM_IDENT_WAIT_MS 30000 @@ -47,5 +47,3 @@ class EQStreamIdentifier { std::vector m_streams; //we own these objects, and the streams contained in them. std::queue m_identified; //we own these objects }; - -#endif /*EQSTREAMIDENT_H_*/ diff --git a/common/eq_stream_intf.h b/common/eq_stream_intf.h index 5b2d24c825..9431fbedf0 100644 --- a/common/eq_stream_intf.h +++ b/common/eq_stream_intf.h @@ -1,12 +1,13 @@ -#ifndef EQSTREAMINTF_H_ -#define EQSTREAMINTF_H_ +#pragma once -//this is the only part of an EQStream that is seen by the application. +#include "common/emu_versions.h" +#include "common/eq_packet.h" +#include "common/net/reliable_stream_connection.h" #include -#include "emu_versions.h" -#include "eq_packet.h" -#include "net/reliable_stream_connection.h" + +//this is the only part of an EQStream that is seen by the application. + typedef enum { ESTABLISHED, @@ -106,5 +107,3 @@ class EQStreamInterface { virtual void ResetStats() = 0; virtual EQStreamManagerInterface* GetManager() const = 0; }; - -#endif /*EQSTREAMINTF_H_*/ diff --git a/common/eq_stream_locator.h b/common/eq_stream_locator.h index 5732c2ef17..17bdabdb4d 100644 --- a/common/eq_stream_locator.h +++ b/common/eq_stream_locator.h @@ -15,16 +15,18 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _EQSTREAM_LOCATOR_H -#define _EQSTREAM_LOCATOR_H -/* -This did not turn out nearly as nice as I hoped. -*/ +#pragma once + +#include "common/types.h" #include #include +/* +This did not turn out nearly as nice as I hoped. +*/ + class EQStreamInfo { public: EQStreamInfo() {} @@ -168,5 +170,3 @@ class EQStreamLocator { protected: std::map streams; }; - -#endif diff --git a/common/eq_stream_proxy.cpp b/common/eq_stream_proxy.cpp index 824e680138..e2e0884913 100644 --- a/common/eq_stream_proxy.cpp +++ b/common/eq_stream_proxy.cpp @@ -1,9 +1,10 @@ -#include "global_define.h" #include "eq_stream_proxy.h" -#include "struct_strategy.h" -#include "eqemu_logsys.h" -#include "opcodemgr.h" + +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/opcodemgr.h" +#include "common/struct_strategy.h" EQStreamProxy::EQStreamProxy(std::shared_ptr &stream, const StructStrategy *structs, OpcodeManager **opcodes) diff --git a/common/eq_stream_proxy.h b/common/eq_stream_proxy.h index fce5b557f2..6be9241cc8 100644 --- a/common/eq_stream_proxy.h +++ b/common/eq_stream_proxy.h @@ -1,9 +1,8 @@ -#ifndef EQSTREAMPROXY_H_ -#define EQSTREAMPROXY_H_ +#pragma once +#include "common/eq_stream_intf.h" +#include "common/types.h" -#include "types.h" -#include "eq_stream_intf.h" #include class StructStrategy; @@ -44,6 +43,3 @@ class EQStreamProxy : public EQStreamInterface { OpcodeManager **const m_opcodes; //we do not own this object. }; - -#endif /*EQSTREAMPROXY_H_*/ - diff --git a/common/eq_stream_type.h b/common/eq_stream_type.h index 6319633238..267dcf2b34 100644 --- a/common/eq_stream_type.h +++ b/common/eq_stream_type.h @@ -1,5 +1,4 @@ -#ifndef _EQSTREAMTYPE_H -#define _EQSTREAMTYPE_H +#pragma once typedef enum { UnknownStream=0, @@ -11,5 +10,3 @@ typedef enum { MailStream } EQStreamType; - -#endif diff --git a/common/eqdb.cpp b/common/eqdb.cpp index 74af894739..f2a4b8a527 100644 --- a/common/eqdb.cpp +++ b/common/eqdb.cpp @@ -15,10 +15,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "global_define.h" + #include "eqdb.h" -#include "database.h" -#include + +#include "common/database.h" +#include "common/global_define.h" + +#include "mysql.h" #include EQDB EQDB::s_EQDB; diff --git a/common/eqdb.h b/common/eqdb.h index 86000db8bf..32492d607c 100644 --- a/common/eqdb.h +++ b/common/eqdb.h @@ -15,15 +15,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef EQDB_H_ -#define EQDB_H_ +#pragma once + +#include "common/eqdb_res.h" +#include "common/types.h" + +#include "mysql.h" +#include #include #include -#include -#include "types.h" -#include "eqdb_res.h" -#include //this is the main object exported to perl. class EQDB { @@ -50,5 +51,3 @@ class EQDB { static EQDB s_EQDB; MYSQL *mysql_ref; }; - -#endif /*EQDB_H_*/ diff --git a/common/eqdb_res.cpp b/common/eqdb_res.cpp index 11d90459dc..1fc7b2ecbb 100644 --- a/common/eqdb_res.cpp +++ b/common/eqdb_res.cpp @@ -15,9 +15,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "global_define.h" + #include "eqdb_res.h" -#include + +#include "common/global_define.h" +#include "mysql.h" std::vector EQDBRes::fetch_row_array() { std::vector array; @@ -49,4 +51,3 @@ std::map EQDBRes::fetch_row_hash() { return rowhash; } - diff --git a/common/eqdb_res.h b/common/eqdb_res.h index 67ce5f869c..5c774e532f 100644 --- a/common/eqdb_res.h +++ b/common/eqdb_res.h @@ -15,15 +15,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef EQDBRes_H_ -#define EQDBRes_H_ +#pragma once + +#include "common/database.h" +#include "common/types.h" + +#include "mysql.h" #include #include #include -#include "types.h" -#include "database.h" -#include //this is the main object exported to perl. class EQDBRes { @@ -44,5 +45,3 @@ class EQDBRes { private: MYSQL_RES *res; }; - -#endif /*EQDBRes_H_*/ diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index e2f35106c1..963607ace6 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -16,16 +16,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" #include "eqemu_config.h" -#include "misc_functions.h" -#include "strings.h" -#include "eqemu_logsys.h" -#include "json/json.hpp" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/json/json.hpp" +#include "common/misc_functions.h" +#include "common/strings.h" + +#include #include #include -#include std::string EQEmuConfig::ConfigFile = "eqemu_config.json"; EQEmuConfig *EQEmuConfig::_config = nullptr; diff --git a/common/eqemu_config.h b/common/eqemu_config.h index 94b0fea521..fcaf1326f4 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -15,15 +15,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __EQEmuConfig_H -#define __EQEmuConfig_H -#include "json/json.h" -#include "linked_list.h" -#include "path_manager.h" +#pragma once + +#include "common/json/json.h" +#include "common/linked_list.h" +#include "common/path_manager.h" + +#include "fmt/format.h" #include -#include -#include struct LoginConfig { std::string LoginHost; @@ -211,5 +211,3 @@ class EQEmuConfig void Dump() const; void CheckUcsConfigConversion(); }; - -#endif diff --git a/common/eqemu_exception.h b/common/eqemu_exception.h index 9649c7a989..6970c1b4cc 100644 --- a/common/eqemu_exception.h +++ b/common/eqemu_exception.h @@ -16,8 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _EQEMU_EQEMUEXCEPTION_H -#define _EQEMU_EQEMUEXCEPTION_H +#pragma once #include #include @@ -106,5 +105,3 @@ namespace EQ #ifndef EQ_EXCEPT #define EQ_EXCEPT(n, d) throw EQ::Exception(n, d, __FILE__, __LINE__) #endif - -#endif diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp index 0d735b407d..8af9dcc6d5 100644 --- a/common/eqemu_logsys.cpp +++ b/common/eqemu_logsys.cpp @@ -19,39 +19,37 @@ */ #include "eqemu_logsys.h" -#include "rulesys.h" -#include "platform.h" -#include "strings.h" -#include "repositories/discord_webhooks_repository.h" -#include "repositories/logsys_categories_repository.h" -#include "termcolor/rang.hpp" -#include "path_manager.h" -#include "file.h" +#include "common/file.h" +#include "common/path_manager.h" +#include "common/platform.h" +#include "common/repositories/discord_webhooks_repository.h" +#include "common/repositories/logsys_categories_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "common/termcolor/rang.hpp" + +#include #include #include -#include #include - -std::ofstream process_log; - -#include +#include #ifdef _WINDOWS -#include #include -#include +#include #include -#include +#include #include +#include #else - -#include #include #include - +#include #endif +std::ofstream process_log; + /** * EQEmuLogSys Constructor */ diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index 210d784f8e..97b99361c3 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -18,14 +18,16 @@ * */ -#ifndef EQEMU_LOGSYS_H -#define EQEMU_LOGSYS_H +#pragma once -#include -#include +#include "common/types.h" + +#include "fmt/format.h" +#include #include +#include #include -#include +#include #ifdef _WIN32 #ifdef utf16_to_utf8 @@ -33,10 +35,6 @@ #endif #endif -#include -#include -#include "types.h" - namespace Logs { enum DebugLevel { General = 1, // 1 - Low-Level general debugging, useful info on single line @@ -463,5 +461,3 @@ void OutF( do { \ ls->Out(debug_level, log_category, file, func, line, fmt::format(formatStr, ##__VA_ARGS__).c_str()); \ } while(0) - -#endif diff --git a/common/eqemu_logsys_log_aliases.h b/common/eqemu_logsys_log_aliases.h index a2c88a03f5..261408c536 100644 --- a/common/eqemu_logsys_log_aliases.h +++ b/common/eqemu_logsys_log_aliases.h @@ -18,8 +18,9 @@ * */ -#ifndef EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H -#define EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H +#pragma once + +#include "common/eqemu_logsys.h" inline auto logsys = EQEmuLogSys::Instance(); @@ -935,6 +936,3 @@ inline auto logsys = EQEmuLogSys::Instance(); if (logsys->IsLogEnabled(debug_level, log_category))\ OutF(logsys, debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) - - -#endif //EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H diff --git a/common/eqtime.cpp b/common/eqtime.cpp index 1478dafd87..7fc34315c5 100644 --- a/common/eqtime.cpp +++ b/common/eqtime.cpp @@ -16,13 +16,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "eqtime.h" + +#include "common/eq_packet_structs.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" + #include -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/eqtime.h" -#include "../common/eq_packet_structs.h" -#include #include +#include + /*#ifdef _CRTDBG_MAP_ALLOC #undef new #endif*/ diff --git a/common/eqtime.h b/common/eqtime.h index f79d274f8e..960570b1aa 100644 --- a/common/eqtime.h +++ b/common/eqtime.h @@ -1,7 +1,7 @@ -#ifndef EQTIME_H -#define EQTIME_H +#pragma once + +#include "common/eq_packet_structs.h" -#include "../common/eq_packet_structs.h" #include //Struct @@ -48,5 +48,3 @@ class EQTime //This is our tz offset int32 timezone; }; - -#endif diff --git a/common/event/event_loop.h b/common/event/event_loop.h index 537c3280a0..8d7ee6a0dd 100644 --- a/common/event/event_loop.h +++ b/common/event/event_loop.h @@ -1,7 +1,8 @@ #pragma once + +#include "uv.h" + #include -#include -#include namespace EQ { diff --git a/common/event/task.h b/common/event/task.h index a58fd875ad..e711ade7fd 100644 --- a/common/event/task.h +++ b/common/event/task.h @@ -1,8 +1,10 @@ #pragma once + +#include "event_loop.h" + #include -#include #include -#include "event_loop.h" +#include namespace EQ { class Task diff --git a/common/event/task_scheduler.h b/common/event/task_scheduler.h index 7f4c0401b0..03e197d92b 100644 --- a/common/event/task_scheduler.h +++ b/common/event/task_scheduler.h @@ -1,11 +1,12 @@ #pragma once -#include -#include -#include + #include #include -#include #include +#include +#include +#include +#include namespace EQ { diff --git a/common/event/timer.h b/common/event/timer.h index 73ac7af352..c9fe757d91 100644 --- a/common/event/timer.h +++ b/common/event/timer.h @@ -1,7 +1,9 @@ #pragma once -#include + #include "event_loop.h" +#include + namespace EQ { class Timer { diff --git a/common/event_sub.h b/common/event_sub.h index 389b4ed079..cd45314ea2 100644 --- a/common/event_sub.h +++ b/common/event_sub.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include class EventSubscriptionWatcher { diff --git a/common/events/player_event_discord_formatter.cpp b/common/events/player_event_discord_formatter.cpp index b25680902d..3b49c040a7 100644 --- a/common/events/player_event_discord_formatter.cpp +++ b/common/events/player_event_discord_formatter.cpp @@ -1,11 +1,14 @@ #include "player_event_discord_formatter.h" -#include "../repositories/character_data_repository.h" -#include "../json/json_archive_single_line.h" + +#include "common/json/json_archive_single_line.h" +#include "common/repositories/character_data_repository.h" + +#include "cereal/archives/json.hpp" +#include "cereal/types/vector.hpp" +#include "fmt/format.h" +#include "fmt/ranges.h" + #include -#include -#include -#include -#include std::string PlayerEventDiscordFormatter::GetCurrentTimestamp() { diff --git a/common/events/player_event_discord_formatter.h b/common/events/player_event_discord_formatter.h index aef518ace7..622a41cee0 100644 --- a/common/events/player_event_discord_formatter.h +++ b/common/events/player_event_discord_formatter.h @@ -1,11 +1,12 @@ -#ifndef EQEMU_PLAYER_EVENT_DISCORD_FORMATTER_H -#define EQEMU_PLAYER_EVENT_DISCORD_FORMATTER_H +#pragma once + +#include "common/events/player_events.h" +#include "common/repositories/base/base_player_event_logs_repository.h" + +#include "cereal/archives/json.hpp" +#include "cereal/types/vector.hpp" #include -#include "player_events.h" -#include "../repositories/base/base_player_event_logs_repository.h" -#include -#include struct DiscordField { std::string name; @@ -209,6 +210,3 @@ class PlayerEventDiscordFormatter { std::vector &embeds ); }; - - -#endif //EQEMU_PLAYER_EVENT_DISCORD_FORMATTER_H diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index daa8cd17c7..b06632a597 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -1,14 +1,16 @@ #include "player_event_logs.h" -#include - -#include "../platform.h" -#include "../rulesys.h" -#include "player_event_discord_formatter.h" -#include "../repositories/player_event_loot_items_repository.h" -#include "../repositories/player_event_merchant_sell_repository.h" -#include "../repositories/player_event_merchant_purchase_repository.h" -#include "../repositories/player_event_npc_handin_repository.h" -#include "../repositories/player_event_npc_handin_entries_repository.h" + +#include "common/events/player_event_discord_formatter.h" +#include "common/platform.h" +#include "common/repositories/player_event_loot_items_repository.h" +#include "common/repositories/player_event_merchant_purchase_repository.h" +#include "common/repositories/player_event_merchant_sell_repository.h" +#include "common/repositories/player_event_npc_handin_entries_repository.h" +#include "common/repositories/player_event_npc_handin_repository.h" +#include "common/rulesys.h" + +#include "cereal/archives/json.hpp" +#include "fmt/ranges.h" const uint32 PROCESS_RETENTION_TRUNCATION_TIMER_INTERVAL = 60 * 60 * 1000; // 1 hour diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index 3c22de4c00..a4bcba0a99 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -1,28 +1,26 @@ -#ifndef EQEMU_PLAYER_EVENT_LOGS_H -#define EQEMU_PLAYER_EVENT_LOGS_H - -#include +#pragma once + +#include "common/eqemu_config.h" +#include "common/json/json_archive_single_line.h" +#include "common/repositories/player_event_aa_purchase_repository.h" +#include "common/repositories/player_event_killed_named_npc_repository.h" +#include "common/repositories/player_event_killed_npc_repository.h" +#include "common/repositories/player_event_killed_raid_npc_repository.h" +#include "common/repositories/player_event_log_settings_repository.h" +#include "common/repositories/player_event_logs_repository.h" +#include "common/repositories/player_event_loot_items_repository.h" +#include "common/repositories/player_event_merchant_purchase_repository.h" +#include "common/repositories/player_event_merchant_sell_repository.h" +#include "common/repositories/player_event_npc_handin_entries_repository.h" +#include "common/repositories/player_event_npc_handin_repository.h" +#include "common/repositories/player_event_speech_repository.h" +#include "common/repositories/player_event_trade_entries_repository.h" +#include "common/repositories/player_event_trade_repository.h" +#include "common/servertalk.h" +#include "common/timer.h" + +#include "cereal/archives/json.hpp" #include -#include "../json/json_archive_single_line.h" -#include "../servertalk.h" -#include "../timer.h" -#include "../eqemu_config.h" - -#include "../repositories/player_event_log_settings_repository.h" -#include "../repositories/player_event_logs_repository.h" -#include "../repositories/player_event_loot_items_repository.h" -#include "../repositories/player_event_merchant_purchase_repository.h" -#include "../repositories/player_event_merchant_sell_repository.h" -#include "../repositories/player_event_npc_handin_repository.h" -#include "../repositories/player_event_npc_handin_entries_repository.h" -#include "../repositories/player_event_trade_repository.h" -#include "../repositories/player_event_trade_entries_repository.h" -#include "../repositories/player_event_speech_repository.h" -#include "../repositories/player_event_killed_npc_repository.h" -#include "../repositories/player_event_killed_named_npc_repository.h" -#include "../repositories/player_event_killed_raid_npc_repository.h" -#include "../repositories/player_event_aa_purchase_repository.h" - class PlayerEventLogs { @@ -134,5 +132,3 @@ class PlayerEventLogs { public: std::map &GetEtlSettings() { return m_etl_settings;} }; - -#endif //EQEMU_PLAYER_EVENT_LOGS_H diff --git a/common/events/player_events.h b/common/events/player_events.h index 02ea2a26bf..a3279b10c3 100644 --- a/common/events/player_events.h +++ b/common/events/player_events.h @@ -1,11 +1,12 @@ -#ifndef EQEMU_PLAYER_EVENTS_H -#define EQEMU_PLAYER_EVENTS_H +#pragma once + +#include "common/repositories/player_event_logs_repository.h" +#include "common/rulesys.h" +#include "common/types.h" + +#include "cereal/cereal.hpp" #include -#include -#include "../types.h" -#include "../rulesys.h" -#include "../repositories/player_event_logs_repository.h" #define CEREAL_NVP_IF_NONZERO(ar, name) \ if ((name) != 0) ar(cereal::make_nvp(#name, name)) @@ -1753,8 +1754,6 @@ namespace PlayerEvent { }; } -#endif //EQEMU_PLAYER_EVENTS_H - #define RecordPlayerEventLog(event_type, event_data) do {\ if (PlayerEventLogs::Instance()->IsEventEnabled(event_type)) {\ if (RuleB(Logging, PlayerEventsQSProcess)) {\ diff --git a/common/evolving_items.cpp b/common/evolving_items.cpp index f14a733f3f..e23e585992 100644 --- a/common/evolving_items.cpp +++ b/common/evolving_items.cpp @@ -1,7 +1,8 @@ #include "evolving_items.h" -#include "item_instance.h" -#include "events/player_event_logs.h" -#include "repositories/character_evolving_items_repository.h" + +#include "common/events/player_event_logs.h" +#include "common/item_instance.h" +#include "common/repositories/character_evolving_items_repository.h" EvolvingItemsManager::EvolvingItemsManager() { diff --git a/common/evolving_items.h b/common/evolving_items.h index 3bdb4d6971..ec23f7ade4 100644 --- a/common/evolving_items.h +++ b/common/evolving_items.h @@ -1,9 +1,8 @@ -#ifndef EVOLVING_H -#define EVOLVING_H +#pragma once -#include "shareddb.h" -#include "events/player_events.h" -#include "repositories/items_evolving_details_repository.h" +#include "common/events/player_events.h" +#include "common/repositories/items_evolving_details_repository.h" +#include "common/shareddb.h" namespace EQ { class ItemInstance; @@ -66,5 +65,3 @@ class EvolvingItemsManager Database * m_db; Database * m_content_db; }; - -#endif //EVOLVING_H diff --git a/common/extprofile.cpp b/common/extprofile.cpp index f29ec1e6ea..5fd4d44711 100644 --- a/common/extprofile.cpp +++ b/common/extprofile.cpp @@ -16,9 +16,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "global_define.h" #include "extprofile.h" +#include "common/global_define.h" + //Set defaults in the extended profile... void InitExtendedProfile(ExtendedProfile_Struct *p) { memset(p, 0, sizeof(ExtendedProfile_Struct)); @@ -49,4 +50,3 @@ bool SetExtendedProfile(ExtendedProfile_Struct *to, char *old, unsigned int len) return(false); } - diff --git a/common/extprofile.h b/common/extprofile.h index 5f69a449d3..7bddcf6f7f 100644 --- a/common/extprofile.h +++ b/common/extprofile.h @@ -15,12 +15,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef EXTENDED_PROFILE_H -#define EXTENDED_PROFILE_H -#include "eq_packet_structs.h" -#include "inventory_profile.h" +#pragma once +#include "common/eq_packet_structs.h" +#include "common/inventory_profile.h" + +#pragma pack(push) #pragma pack(1) /* @@ -58,10 +59,7 @@ struct ExtendedProfile_Struct { uint32 next_invsnapshot_time; /* Used */ }; -#pragma pack() +#pragma pack(pop) void InitExtendedProfile(ExtendedProfile_Struct *p); bool SetExtendedProfile(ExtendedProfile_Struct *to, char *old, unsigned int len); - - -#endif diff --git a/common/faction.cpp b/common/faction.cpp index 793991593c..1432e94e01 100644 --- a/common/faction.cpp +++ b/common/faction.cpp @@ -17,8 +17,9 @@ */ #include "faction.h" -#include "races.h" -#include "rulesys.h" + +#include "common/races.h" +#include "common/rulesys.h" const char *FactionValueToString(FACTION_VALUE faction_value) { @@ -163,4 +164,3 @@ bool IsOfIndiffRace(int r1, int r2) } return false; } - diff --git a/common/faction.h b/common/faction.h index a4aac84a26..368a8dbc8e 100755 --- a/common/faction.h +++ b/common/faction.h @@ -15,11 +15,12 @@ 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_FACTION_H -#define _EQEMU_FACTION_H -#include "types.h" -#include "features.h" +#pragma once + +#include "common/features.h" +#include "common/types.h" + #include #include @@ -75,4 +76,3 @@ struct NPCFaction const char *FactionValueToString(FACTION_VALUE faction_value); FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value); -#endif diff --git a/common/features.h b/common/features.h index 0e157a6529..e0fbc293ee 100644 --- a/common/features.h +++ b/common/features.h @@ -15,8 +15,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef FEATURES_H -#define FEATURES_H + +#pragma once /* @@ -257,8 +257,3 @@ Developer configuration #define PROFILE_DUMP_TIME 180 #endif //EQPROFILE - - - -#endif - diff --git a/common/file.cpp b/common/file.cpp index df15255afc..8d56470b16 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -18,9 +18,16 @@ * */ -#include #include "file.h" +#include "fmt/format.h" + +#include +#include +#include +#include +#include + #ifdef _WINDOWS #include #include @@ -29,18 +36,10 @@ #include #include #else - #include #include - #endif -#include -#include -#include -#include -#include -#include namespace fs = std::filesystem; diff --git a/common/file.h b/common/file.h index 7991101c46..ec99a1b36d 100644 --- a/common/file.h +++ b/common/file.h @@ -18,8 +18,7 @@ * */ -#ifndef EQEMU_FILE_H -#define EQEMU_FILE_H +#pragma once #include @@ -40,5 +39,3 @@ class File { }; bool Exists(const std::string& name); - -#endif //EQEMU_FILE_H diff --git a/common/fixed_memory_hash_set.h b/common/fixed_memory_hash_set.h index d029002602..17e8d9013c 100644 --- a/common/fixed_memory_hash_set.h +++ b/common/fixed_memory_hash_set.h @@ -16,12 +16,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _EQEMU_FIXED_MEMORY_HASHSET_H -#define _EQEMU_FIXED_MEMORY_HASHSET_H +#pragma once + +#include "common/eqemu_exception.h" +#include "common/types.h" #include -#include "eqemu_exception.h" -#include "types.h" namespace EQ { @@ -247,6 +247,3 @@ namespace EQ { value_type *elements_; }; } // EQEmu - -#endif - diff --git a/common/fixed_memory_variable_hash_set.h b/common/fixed_memory_variable_hash_set.h index cc0f7979e3..f04387c0c9 100644 --- a/common/fixed_memory_variable_hash_set.h +++ b/common/fixed_memory_variable_hash_set.h @@ -16,12 +16,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _EQEMU_FIXED_MEMORY_VARIABLE_HASHSET_H -#define _EQEMU_FIXED_MEMORY_VARIABLE_HASHSET_H +#pragma once + +#include "common/eqemu_exception.h" +#include "common/types.h" #include -#include "eqemu_exception.h" -#include "types.h" namespace EQ { @@ -237,5 +237,3 @@ namespace EQ { byte *elements_; }; } // EQEmu - -#endif diff --git a/common/global_define.h b/common/global_define.h index e27f313af8..8c4755d842 100644 --- a/common/global_define.h +++ b/common/global_define.h @@ -16,6 +16,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#pragma once + // WHY IS THIS UP HERE #if defined(_DEBUG) && defined(WIN32) #ifndef _CRTDBG_MAP_ALLOC @@ -24,12 +26,8 @@ #endif #endif -#ifndef EQDEBUG_H -#define EQDEBUG_H #ifdef _WINDOWS #include #include #endif - -#endif diff --git a/common/guild_base.cpp b/common/guild_base.cpp index 3f34c36253..13c2af3c99 100644 --- a/common/guild_base.cpp +++ b/common/guild_base.cpp @@ -17,23 +17,21 @@ */ #include "guild_base.h" -#include "database.h" -#include "../common/rulesys.h" -#include "../common/repositories/guilds_repository.h" -#include "../common/repositories/guild_ranks_repository.h" -#include "../common/repositories/guild_permissions_repository.h" -#include "../common/repositories/guild_members_repository.h" -#include "../common/repositories/guild_bank_repository.h" -#include "../common/repositories/guild_tributes_repository.h" - - -//#include "misc_functions.h" -#include "strings.h" + +#include "common/database.h" +#include "common/eq_packet_structs.h" +#include "common/repositories/guild_bank_repository.h" +#include "common/repositories/guild_members_repository.h" +#include "common/repositories/guild_permissions_repository.h" +#include "common/repositories/guild_ranks_repository.h" +#include "common/repositories/guild_tributes_repository.h" +#include "common/repositories/guilds_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" + #include #include -//until we move MAX_NUMBER_GUILDS -#include "eq_packet_structs.h" std::vector default_permissions = { {GUILD_ACTION_BANK_CHANGE_ITEM_PERMISSIONS, 128}, diff --git a/common/guild_base.h b/common/guild_base.h index 0cd4fe5f85..9554c06657 100644 --- a/common/guild_base.h +++ b/common/guild_base.h @@ -1,13 +1,13 @@ -#ifndef GUILD_BASE_H_ -#define GUILD_BASE_H_ +#pragma once + +#include "common/guilds.h" +#include "common/repositories/guild_members_repository.h" +#include "common/repositories/guilds_repository.h" +#include "common/timer.h" -#include "guilds.h" #include #include #include -#include "timer.h" -#include "../common/repositories/guild_members_repository.h" -#include "../common/repositories/guilds_repository.h" struct DefaultPermissionStruct { GuildAction id; @@ -210,6 +210,3 @@ class BaseGuildManager GuildInfo* _CreateGuild(uint32 guild_id, std::string guild_name, uint32 leader_char_id, uint8 minstatus, std::string guild_motd, std::string motd_setter, std::string Channel, std::string URL, uint32 favour); GuildsRepository::Guilds CreateGuildRepoFromGuildInfo(uint32 guild_id, BaseGuildManager::GuildInfo& in); }; -#endif /*GUILD_BASE_H_*/ - - diff --git a/common/guilds.cpp b/common/guilds.cpp index 408f287140..09e92f39b7 100644 --- a/common/guilds.cpp +++ b/common/guilds.cpp @@ -16,12 +16,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "misc_functions.h" #include "guilds.h" -#include "database.h" -#include "eq_packet_structs.h" +#include "common/database.h" +#include "common/eq_packet_structs.h" +#include "common/global_define.h" +#include "common/misc_functions.h" #ifndef WIN32 #include //for htonl diff --git a/common/guilds.h b/common/guilds.h index 11a6af704a..aca44a1cff 100644 --- a/common/guilds.h +++ b/common/guilds.h @@ -16,10 +16,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef GUILDS_H -#define GUILDS_H +#pragma once -#include "types.h" +#include "common/types.h" #define GUILD_NONE 0xFFFFFFFF // user has no guild @@ -82,5 +81,3 @@ typedef enum { } GuildAction; constexpr int format_as(GuildAction action) { return static_cast(action); } - -#endif diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index 7017184d9b..6d16f50b09 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -17,20 +17,12 @@ */ #include "inventory_profile.h" -#include "textures.h" -#include "eqemu_logsys.h" -//#include "classes.h" -//#include "global_define.h" -//#include "item_instance.h" -//#include "races.h" -//#include "rulesys.h" -//#include "shareddb.h" -#include "strings.h" - -#include "../common/light_source.h" -#include "data_verification.h" - -//#include + +#include "common/data_verification.h" +#include "common/eqemu_logsys.h" +#include "common/light_source.h" +#include "common/strings.h" +#include "common/textures.h" #include diff --git a/common/inventory_profile.h b/common/inventory_profile.h index 5773427854..1297be0d76 100644 --- a/common/inventory_profile.h +++ b/common/inventory_profile.h @@ -21,13 +21,11 @@ // These classes could be optimized with database reads/writes by storing // a status flag indicating how object needs to interact with database -#ifndef COMMON_INVENTORY_PROFILE_H -#define COMMON_INVENTORY_PROFILE_H +#pragma once - -#include "item_instance.h" -#include "classes.h" -#include "races.h" +#include "common/classes.h" +#include "common/item_instance.h" +#include "common/races.h" #include #include @@ -253,5 +251,3 @@ namespace EQ const inventory::LookupEntry* m_lookup; }; } - -#endif /*COMMON_INVENTORY_PROFILE_H*/ diff --git a/common/inventory_slot.cpp b/common/inventory_slot.cpp index a63512ae21..081147d8f0 100644 --- a/common/inventory_slot.cpp +++ b/common/inventory_slot.cpp @@ -18,8 +18,9 @@ */ #include "inventory_slot.h" -#include "textures.h" -#include "strings.h" + +#include "common/textures.h" +#include "common/strings.h" int8 EQ::inventory::ConvertEquipmentIndexToTextureIndex(int16 slot_index) diff --git a/common/inventory_slot.h b/common/inventory_slot.h index d61d8acb08..dc85763992 100644 --- a/common/inventory_slot.h +++ b/common/inventory_slot.h @@ -17,10 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_INVENTORY_SLOT -#define COMMON_INVENTORY_SLOT +#pragma once -#include "emu_constants.h" +#include "common/emu_constants.h" namespace EQ @@ -129,5 +128,3 @@ namespace EQ bool operator!=(const InventorySlot& lhs, const InventorySlot& rhs) { return (!(lhs == rhs)); } } /*EQEmu*/ - -#endif /*COMMON_INVENTORY_SLOT*/ diff --git a/common/ip_util.cpp b/common/ip_util.cpp index c0316ea109..b5c18948f1 100644 --- a/common/ip_util.cpp +++ b/common/ip_util.cpp @@ -18,18 +18,19 @@ * */ +#include "ip_util.h" + +#include "common/eqemu_logsys.h" +#include "common/event/event_loop.h" +#include "common/event/task_scheduler.h" +#include "common/http/httplib.h" +#include "common/http/uri.h" +#include "common/net/dns.h" + +#include "fmt/format.h" #include -#include -#include #include #include -#include "ip_util.h" -#include "http/httplib.h" -#include "http/uri.h" -#include "eqemu_logsys.h" -#include "event/event_loop.h" -#include "net/dns.h" -#include "event/task_scheduler.h" /** * @param ip diff --git a/common/ip_util.h b/common/ip_util.h index 3d96f219ce..255167aff7 100644 --- a/common/ip_util.h +++ b/common/ip_util.h @@ -18,11 +18,11 @@ * */ -#ifndef EQEMU_IP_UTIL_H -#define EQEMU_IP_UTIL_H +#pragma once -#include "types.h" -#include "iostream" +#include "common/types.h" + +#include class IpUtil { public: @@ -40,5 +40,3 @@ class IpUtil { static bool IsPortInUse(const std::string& ip, int port); }; - -#endif //EQEMU_IP_UTIL_H diff --git a/common/ipc_mutex.cpp b/common/ipc_mutex.cpp index ebd13a6930..48af9b3881 100644 --- a/common/ipc_mutex.cpp +++ b/common/ipc_mutex.cpp @@ -17,20 +17,23 @@ */ #include "ipc_mutex.h" + +#include "common/eqemu_config.h" +#include "common/eqemu_exception.h" +#include "common/path_manager.h" +#include "common/types.h" + #ifdef _WINDOWS +#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN +#endif #include -#undef WIN32_LEAN_AND_MEAN #else #include #include #include #include #endif -#include "types.h" -#include "eqemu_exception.h" -#include "eqemu_config.h" -#include "path_manager.h" namespace EQ { struct IPCMutex::Implementation { diff --git a/common/ipc_mutex.h b/common/ipc_mutex.h index 4418f91896..f4ef94ed27 100644 --- a/common/ipc_mutex.h +++ b/common/ipc_mutex.h @@ -16,8 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _MUTEX_H_ -#define _MUTEX_H_ +#pragma once #include @@ -61,5 +60,3 @@ namespace EQ { Implementation *imp_; }; } - -#endif diff --git a/common/item_data.cpp b/common/item_data.cpp index c31bad37cd..f49dcf08ba 100644 --- a/common/item_data.cpp +++ b/common/item_data.cpp @@ -18,9 +18,9 @@ */ #include "item_data.h" -#include "classes.h" -#include "races.h" -//#include "deity.h" + +#include "common/classes.h" +#include "common/races.h" uint32 EQ::item::ConvertAugTypeToAugTypeBit(uint8 aug_type) diff --git a/common/item_data.h b/common/item_data.h index 6967c218c1..30ad2e459c 100644 --- a/common/item_data.h +++ b/common/item_data.h @@ -17,9 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA */ -#ifndef COMMON_ITEM_DATA_H -#define COMMON_ITEM_DATA_H +#pragma once +#include "common/emu_constants.h" /* * Note: (Doodman) @@ -44,9 +44,6 @@ * Made ya look! Ha! */ -#include "emu_constants.h" - - namespace EQ { namespace item { @@ -558,5 +555,3 @@ namespace EQ }; } /*EQEmu*/ - -#endif /*COMMON_ITEM_DATA_H*/ diff --git a/common/item_instance.cpp b/common/item_instance.cpp index bb048b1fbd..c624140e09 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -17,21 +17,14 @@ */ #include "inventory_profile.h" -#include "../common/data_verification.h" -//#include "classes.h" -//#include "global_define.h" -//#include "item_instance.h" -//#include "races.h" -#include "rulesys.h" -#include "shareddb.h" -#include "strings.h" -#include "evolving_items.h" - -//#include "../common/light_source.h" -#include +#include "common/data_verification.h" +#include "common/evolving_items.h" +#include "common/rulesys.h" +#include "common/shareddb.h" +#include "common/strings.h" -//#include +#include int32 next_item_serial_number = 1; std::unordered_set guids{}; diff --git a/common/item_instance.h b/common/item_instance.h index 99edfb570a..8c96de1088 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -21,24 +21,22 @@ // These classes could be optimized with database reads/writes by storing // a status flag indicating how object needs to interact with database -#ifndef COMMON_ITEM_INSTANCE_H -#define COMMON_ITEM_INSTANCE_H -#include "evolving_items.h" +#pragma once +#include "common/bodytypes.h" +#include "common/deity.h" +#include "common/eq_constants.h" +#include "common/evolving_items.h" +#include "common/item_data.h" +#include "common/memory_buffer.h" +#include "common/repositories/character_evolving_items_repository.h" +#include "common/timer.h" + +#include class ItemParse; // Parses item packets class EvolveInfo; // Stores information about an evolving item family -#include "../common/eq_constants.h" -#include "../common/item_data.h" -#include "../common/timer.h" -#include "../common/bodytypes.h" -#include "../common/deity.h" -#include "../common/memory_buffer.h" -#include "../common/repositories/character_evolving_items_repository.h" - -#include - // Specifies usage type for item inside EQ::ItemInstance enum ItemInstTypes @@ -376,4 +374,3 @@ namespace EQ mutable std::map m_timers {}; }; } -#endif /*COMMON_ITEM_INSTANCE_H*/ diff --git a/common/json_config.cpp b/common/json_config.cpp index 5f4c47b71c..b41a8fc5bf 100644 --- a/common/json_config.cpp +++ b/common/json_config.cpp @@ -1,4 +1,5 @@ #include "json_config.h" + #include #include diff --git a/common/json_config.h b/common/json_config.h index aa4d2d8f67..29fbb86c59 100644 --- a/common/json_config.h +++ b/common/json_config.h @@ -2,6 +2,8 @@ #include "json/json.h" +#include + namespace EQ { class JsonConfigFile diff --git a/common/light_source.cpp b/common/light_source.cpp index 7aeb4d166b..1574144adf 100644 --- a/common/light_source.cpp +++ b/common/light_source.cpp @@ -21,7 +21,6 @@ #include - uint8 EQ::lightsource::TypeToLevel(uint8 light_type) { switch (light_type) { diff --git a/common/light_source.h b/common/light_source.h index f68f7fe87e..4c6d479f1f 100644 --- a/common/light_source.h +++ b/common/light_source.h @@ -17,11 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_LIGHT_SOURCE_H -#define COMMON_LIGHT_SOURCE_H - -#include "types.h" +#pragma once +#include "common/types.h" namespace EQ { @@ -111,5 +109,3 @@ namespace EQ }; } /*EQEmu*/ - -#endif /*COMMON_LIGHT_SOURCE_H*/ diff --git a/common/linked_list.h b/common/linked_list.h index 8ac4b51d85..0c7e390415 100644 --- a/common/linked_list.h +++ b/common/linked_list.h @@ -15,10 +15,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef LINKEDLIST_H -#define LINKEDLIST_H -#include "types.h" +#pragma once + +#include "common/types.h" enum direction{FORWARD,BACKWARD}; @@ -433,6 +433,3 @@ TYPE LinkedList::PeekTop() { return first->GetData(); return 0; } - -#endif - diff --git a/common/loot.h b/common/loot.h index 62baf14258..c386a4577f 100644 --- a/common/loot.h +++ b/common/loot.h @@ -1,9 +1,9 @@ -#ifndef CODE_LOOT_H -#define CODE_LOOT_H +#pragma once + +#include "common/types.h" #include #include -#include "../common/types.h" struct LootItem { uint32 item_id; @@ -30,5 +30,3 @@ struct LootItem { typedef std::list LootItems; - -#endif //CODE_LOOT_H diff --git a/common/md5.cpp b/common/md5.cpp index ca2e38eb22..2326fc5e7f 100644 --- a/common/md5.cpp +++ b/common/md5.cpp @@ -7,10 +7,13 @@ * MD5Update as needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. */ + +#include "md5.h" + +#include "common/strings.h" +#include "common/seperator.h" + #include /* for memcpy() */ -#include "../common/md5.h" -#include "../common/strings.h" -#include "../common/seperator.h" MD5::MD5() { memset(pMD5, 0, 16); diff --git a/common/md5.h b/common/md5.h index 13dfd5f9e9..af4182823c 100644 --- a/common/md5.h +++ b/common/md5.h @@ -1,9 +1,9 @@ -#ifndef MD5_H -#define MD5_H -#include "../common/types.h" +#pragma once +#include "common/types.h" -class MD5 { +class MD5 +{ public: struct MD5Context { uint32 hash[4]; @@ -42,4 +42,3 @@ class MD5 { static void Transform(uint32 hash[4], const uint32 input[16]); char pMD5String[33]; }; -#endif diff --git a/common/memory/ksm.hpp b/common/memory/ksm.hpp index 079b83f1a5..ad9c4de5ac 100644 --- a/common/memory/ksm.hpp +++ b/common/memory/ksm.hpp @@ -1,7 +1,7 @@ -#ifndef EQEMU_KSM_HPP -#define EQEMU_KSM_HPP +#pragma once + +#include "common/eqemu_logsys.h" -#include "../eqemu_logsys.h" #include #include #include @@ -214,7 +214,4 @@ namespace KSM { MarkMemoryForKSM(start, size); #endif } - } - -#endif // EQEMU_KSM_HPP diff --git a/common/memory_buffer.h b/common/memory_buffer.h index a2e19d3643..bd191d4a5c 100644 --- a/common/memory_buffer.h +++ b/common/memory_buffer.h @@ -17,15 +17,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_MEMORY_BUFFER -#define COMMON_MEMORY_BUFFER +#pragma once -#include "types.h" +#include "common/types.h" -#include +#include #include #include -#include +#include namespace EQ @@ -130,5 +129,3 @@ namespace EQ }; } /*EQEmu*/ - -#endif /*COMMON_MEMORY_BUFFER*/ diff --git a/common/memory_mapped_file.cpp b/common/memory_mapped_file.cpp index a1a16d5dbd..ed77f5bf73 100644 --- a/common/memory_mapped_file.cpp +++ b/common/memory_mapped_file.cpp @@ -17,6 +17,11 @@ */ #include "memory_mapped_file.h" + +#include "common/eqemu_exception.h" + +#include + #ifdef _WINDOWS #include #else @@ -28,12 +33,10 @@ #include #include #endif -#include "eqemu_exception.h" #ifdef FREEBSD #include #endif -#include namespace fs = std::filesystem; namespace EQ { diff --git a/common/memory_mapped_file.h b/common/memory_mapped_file.h index d3e832cef0..f228db90ca 100644 --- a/common/memory_mapped_file.h +++ b/common/memory_mapped_file.h @@ -16,11 +16,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _EQEMU_MEMORYMAPPEDFILE_H_ -#define _EQEMU_MEMORYMAPPEDFILE_H_ +#pragma once + +#include "common/types.h" #include -#include "types.h" namespace EQ { @@ -82,5 +82,3 @@ namespace EQ { Implementation *imp_; //!< Underlying implementation. }; } // EQEmu - -#endif diff --git a/common/misc.cpp b/common/misc.cpp index 4c5103fa3e..5927dbb414 100644 --- a/common/misc.cpp +++ b/common/misc.cpp @@ -1,25 +1,21 @@ -#ifdef _WINDOWS - // VS6 doesn't like the length of STL generated names: disabling - #pragma warning(disable:4786) -#endif -#include "global_define.h" -#include +#include "misc.h" + +#include "common/global_define.h" +#include "common/strings.h" +#include "common/types.h" + +#include "zlib.h" +#include +#include +#include #include #include -#include -#include -#include - +#include +#include #ifndef WIN32 #include #endif -#include -#include "misc.h" -#include "types.h" -#include -#include "strings.h" - std::map DBFieldNames; #ifndef WIN32 diff --git a/common/misc.h b/common/misc.h index bb1c3550df..da827ca377 100644 --- a/common/misc.h +++ b/common/misc.h @@ -1,9 +1,8 @@ -#ifndef _MISC_H +#pragma once -#define _MISC_H +#include #include #include -#include #define ITEMFIELDCOUNT 116 @@ -28,6 +27,3 @@ int EQsprintf(char *buffer, const char *pattern, const char *arg1, const char *a std::string generate_key(int length); void build_hex_line(const char *buffer, unsigned long length, unsigned long offset, char *out_buffer, unsigned char padding=4); void print_hex(const char *buffer, unsigned long length); - -#endif - diff --git a/common/misc_functions.cpp b/common/misc_functions.cpp index dfa0349449..8e10073867 100644 --- a/common/misc_functions.cpp +++ b/common/misc_functions.cpp @@ -16,45 +16,41 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "../common/global_define.h" #include "misc_functions.h" -#include -#include -#include "strings.h" -#ifndef WIN32 -#include -#include -#endif -#include +#include "common/global_define.h" +#include "common/seperator.h" +#include "common/strings.h" +#include "common/timer.h" + #include -#ifdef _WINDOWS - #include -#endif -#include "../common/timer.h" -#include "../common/seperator.h" +#include +#include +#include #ifdef _WINDOWS - #include +#include +#include - #define snprintf _snprintf - #define strncasecmp _strnicmp - #define strcasecmp _stricmp +#define snprintf _snprintf +#define strncasecmp _strnicmp +#define strcasecmp _stricmp #else - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include +#include +#include #ifdef FREEBSD //Timothy Whitman - January 7, 2003 - #include - #include +#include +#include #endif - #include - #include - #include - #include +#include +#include +#include +#include #endif void CoutTimestamp(bool ms) { diff --git a/common/misc_functions.h b/common/misc_functions.h index 62a6745c1d..2590877ca2 100644 --- a/common/misc_functions.h +++ b/common/misc_functions.h @@ -15,10 +15,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef MISCFUNCTIONS_H -#define MISCFUNCTIONS_H -#include "types.h" +#pragma once + +#include "common/types.h" + #include #include @@ -86,6 +87,3 @@ class InitWinsock { InitWinsock(); ~InitWinsock(); }; - -#endif - diff --git a/common/mutex.cpp b/common/mutex.cpp index 1dfacb5bbd..9f2fe3889c 100644 --- a/common/mutex.cpp +++ b/common/mutex.cpp @@ -15,14 +15,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/mutex.h" + +#include "mutex.h" + +#include "common/global_define.h" #include #define DEBUG_MUTEX_CLASS 0 #if DEBUG_MUTEX_CLASS >= 1 - #endif #ifdef _WINDOWS diff --git a/common/mutex.h b/common/mutex.h index 48f58bcaca..d6bbac916c 100644 --- a/common/mutex.h +++ b/common/mutex.h @@ -15,16 +15,18 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef MYMUTEX_H -#define MYMUTEX_H + +#pragma once + +#include "common/types.h" + #ifdef _WINDOWS - #include - #include +#include +#include #else - #include - #include "../common/unix.h" +#include "common/unix.h" +#include #endif -#include "../common/types.h" class Mutex { public: @@ -78,6 +80,3 @@ class MRMutex { int32 wl; // write locks in effect (should never be more than 1) Mutex MCounters; }; - -#endif - diff --git a/common/mysql_request_result.h b/common/mysql_request_result.h index cb2a4e7195..1cd1d2aa3e 100644 --- a/common/mysql_request_result.h +++ b/common/mysql_request_result.h @@ -1,21 +1,10 @@ -#ifndef MYSQL_REQUEST_RESULT_H -#define MYSQL_REQUEST_RESULT_H +#pragma once -#ifdef _WINDOWS - #include - #include -#endif +#include "common/mysql_request_row.h" +#include "common/types.h" +#include "mysql.h" #include -#include -#include "types.h" -#include "mysql_request_row.h" - -#ifdef __FreeBSD__ - #include - #include - #include -#endif class MySQLRequestResult { private: @@ -73,7 +62,3 @@ class MySQLRequestResult { void FreeInternals(); void ZeroOut(); }; - - -#endif - diff --git a/common/mysql_request_row.h b/common/mysql_request_row.h index 5f160ac63f..eb19d7ee83 100644 --- a/common/mysql_request_row.h +++ b/common/mysql_request_row.h @@ -1,14 +1,9 @@ -#ifndef MYSQL_REQUEST_ROW_H -#define MYSQL_REQUEST_ROW_H +#pragma once -#ifdef _WINDOWS - #include - #include -#endif +#include "common/types.h" -#include +#include "mysql.h" #include -#include "types.h" class MySQLRequestRow { @@ -36,9 +31,4 @@ class MySQLRequestRow bool operator!=(const MySQLRequestRow& rhs); MySQLRequestRow operator*(); char* operator[](int index); - }; - - - -#endif diff --git a/common/mysql_stmt.cpp b/common/mysql_stmt.cpp index 872df0086c..dba8eca621 100644 --- a/common/mysql_stmt.cpp +++ b/common/mysql_stmt.cpp @@ -1,7 +1,9 @@ #include "mysql_stmt.h" -#include "eqemu_logsys.h" -#include "mutex.h" -#include "timer.h" + +#include "common/eqemu_logsys.h" +#include "common/mutex.h" +#include "common/timer.h" + #include namespace mysql diff --git a/common/mysql_stmt.h b/common/mysql_stmt.h index eb1483f176..2592f19f7e 100644 --- a/common/mysql_stmt.h +++ b/common/mysql_stmt.h @@ -6,8 +6,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/common/net/console_server.cpp b/common/net/console_server.cpp index 4cc2b21269..a737c5a4d6 100644 --- a/common/net/console_server.cpp +++ b/common/net/console_server.cpp @@ -1,7 +1,8 @@ #include "console_server.h" -#include "../strings.h" -#include -#include + +#include "common/strings.h" + +#include "fmt/format.h" EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port) { diff --git a/common/net/console_server.h b/common/net/console_server.h index d28f438443..e984c884f6 100644 --- a/common/net/console_server.h +++ b/common/net/console_server.h @@ -1,6 +1,7 @@ #pragma once #include "console_server_connection.h" + #include #include diff --git a/common/net/console_server_connection.cpp b/common/net/console_server_connection.cpp index 47e321b805..88be73d964 100644 --- a/common/net/console_server_connection.cpp +++ b/common/net/console_server_connection.cpp @@ -1,11 +1,12 @@ -#include "console_server.h" -#include "../util/uuid.h" -#include "../net/packet.h" -#include "../eqemu_logsys.h" -#include "../servertalk.h" -#include "../rulesys.h" -#include -#include +#include "console_server_connection.h" + +#include "common/util/uuid.h" +#include "common/net/console_server.h" +#include "common/net/packet.h" +#include "common/servertalk.h" +#include "common/rulesys.h" + +#include "fmt/format.h" EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr connection) { diff --git a/common/net/console_server_connection.h b/common/net/console_server_connection.h index a497008414..ba9f47ff52 100644 --- a/common/net/console_server_connection.h +++ b/common/net/console_server_connection.h @@ -1,8 +1,9 @@ #pragma once #include "tcp_server.h" -#include + #include +#include struct ServerChannelMessage_Struct; diff --git a/common/net/crc32.cpp b/common/net/crc32.cpp index 6f6f277ced..52ec128ff0 100644 --- a/common/net/crc32.cpp +++ b/common/net/crc32.cpp @@ -1,5 +1,4 @@ #include "crc32.h" -#include unsigned int CRC32EncodeTable[256] = { diff --git a/common/net/crc32.h b/common/net/crc32.h index b10f05c762..c4ab85c8b0 100644 --- a/common/net/crc32.h +++ b/common/net/crc32.h @@ -1,9 +1,7 @@ #pragma once -#include - namespace EQ { int Crc32(const void *data, int size); int Crc32(const void *data, int size, int key); -} \ No newline at end of file +} diff --git a/common/net/dns.h b/common/net/dns.h index d43f415665..c762855636 100644 --- a/common/net/dns.h +++ b/common/net/dns.h @@ -1,8 +1,9 @@ #pragma once -#include "../event/event_loop.h" -#include +#include "common/event/event_loop.h" + #include +#include namespace EQ { diff --git a/common/net/endian.h b/common/net/endian.h index 8eb3caf2af..a4d28da1bd 100644 --- a/common/net/endian.h +++ b/common/net/endian.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include namespace EQ diff --git a/common/net/eqstream.cpp b/common/net/eqstream.cpp index 633dea4c9a..dfed5609b0 100644 --- a/common/net/eqstream.cpp +++ b/common/net/eqstream.cpp @@ -1,5 +1,6 @@ #include "eqstream.h" -#include "../eqemu_logsys.h" + +#include "common/eqemu_logsys.h" EQ::Net::EQStreamManager::EQStreamManager(const EQStreamManagerInterfaceOptions &options) : EQStreamManagerInterface(options), m_reliable_stream(options.reliable_stream_options) { diff --git a/common/net/eqstream.h b/common/net/eqstream.h index 4a8e6ddd98..1f78523c75 100644 --- a/common/net/eqstream.h +++ b/common/net/eqstream.h @@ -1,12 +1,13 @@ #pragma once -#include "../eq_packet.h" -#include "../eq_stream_intf.h" -#include "../opcodemgr.h" -#include "reliable_stream_connection.h" -#include +#include "common/eq_packet.h" +#include "common/eq_stream_intf.h" +#include "common/net/reliable_stream_connection.h" +#include "common/opcodemgr.h" + #include #include +#include namespace EQ { diff --git a/common/net/packet.cpp b/common/net/packet.cpp index a4ec4b4982..61e3749ae5 100644 --- a/common/net/packet.cpp +++ b/common/net/packet.cpp @@ -1,8 +1,9 @@ #include "packet.h" -#include "endian.h" + +#include "common/net/endian.h" + +#include "fmt/format.h" #include -#include -#include void EQ::Net::Packet::PutInt8(size_t offset, int8_t value) { diff --git a/common/net/packet.h b/common/net/packet.h index 4ff5f85101..e846934076 100644 --- a/common/net/packet.h +++ b/common/net/packet.h @@ -1,12 +1,14 @@ #pragma once +#include "common/util/memory_stream.h" + +#include "cereal/archives/binary.hpp" +#include "cereal/cereal.hpp" + #include -#include -#include #include -#include "../util/memory_stream.h" -#include -#include +#include +#include namespace EQ { namespace Net { diff --git a/common/net/reliable_stream_connection.cpp b/common/net/reliable_stream_connection.cpp index c75bfe77ab..0c93a72452 100644 --- a/common/net/reliable_stream_connection.cpp +++ b/common/net/reliable_stream_connection.cpp @@ -1,10 +1,11 @@ #include "reliable_stream_connection.h" -#include "../event/event_loop.h" -#include "../data_verification.h" -#include "crc32.h" -#include -#include -#include + +#include "common/event/event_loop.h" +#include "common/data_verification.h" +#include "common/net/crc32.h" + +#include "zlib.h" +#include "fmt/format.h" // observed client receive window is 300 packets, 140KB constexpr size_t MAX_CLIENT_RECV_PACKETS_PER_WINDOW = 300; diff --git a/common/net/reliable_stream_connection.h b/common/net/reliable_stream_connection.h index 97e1982c72..e3f4f16d28 100644 --- a/common/net/reliable_stream_connection.h +++ b/common/net/reliable_stream_connection.h @@ -1,16 +1,18 @@ #pragma once -#include "../random.h" -#include "packet.h" -#include "reliable_stream_structs.h" -#include "reliable_stream_pooling.h" -#include +#include "common/random.h" +#include "common/net/packet.h" +#include "common/net/reliable_stream_structs.h" +#include "common/net/reliable_stream_pooling.h" + +#include "uv.h" + #include #include -#include +#include #include +#include #include -#include namespace EQ { diff --git a/common/net/reliable_stream_pooling.h b/common/net/reliable_stream_pooling.h index e374ecdc7b..37b1655f69 100644 --- a/common/net/reliable_stream_pooling.h +++ b/common/net/reliable_stream_pooling.h @@ -1,14 +1,15 @@ #pragma once -#include +#include "common/eqemu_logsys.h" + +#include "uv.h" + +#include #include #include -#include -#include #include -#include -#include "../eqemu_logsys.h" -#include +#include +#include constexpr size_t UDP_BUFFER_SIZE = 512; diff --git a/common/net/reliable_stream_structs.h b/common/net/reliable_stream_structs.h index f48e1f9c35..1c89049475 100644 --- a/common/net/reliable_stream_structs.h +++ b/common/net/reliable_stream_structs.h @@ -1,8 +1,9 @@ #pragma once -#include +#include "common/net/endian.h" + +#include "cereal/cereal.hpp" #include -#include "endian.h" namespace EQ { diff --git a/common/net/servertalk_client_connection.cpp b/common/net/servertalk_client_connection.cpp index 524c9d496d..5f6e8b179a 100644 --- a/common/net/servertalk_client_connection.cpp +++ b/common/net/servertalk_client_connection.cpp @@ -1,6 +1,7 @@ #include "servertalk_client_connection.h" -#include "dns.h" -#include "../eqemu_logsys.h" + +#include "common/eqemu_logsys.h" +#include "common/net/dns.h" EQ::Net::ServertalkClient::ServertalkClient(const std::string &addr, int port, bool ipv6, const std::string &identifier, const std::string &credentials) : m_timer(std::make_unique(100, true, std::bind(&EQ::Net::ServertalkClient::Connect, this))) diff --git a/common/net/servertalk_client_connection.h b/common/net/servertalk_client_connection.h index 5a1e3db322..988797884a 100644 --- a/common/net/servertalk_client_connection.h +++ b/common/net/servertalk_client_connection.h @@ -1,9 +1,9 @@ #pragma once -#include "tcp_connection.h" -#include "../event/timer.h" -#include "servertalk_common.h" -#include "packet.h" +#include "common/event/timer.h" +#include "common/net/packet.h" +#include "common/net/servertalk_common.h" +#include "common/net/tcp_connection.h" namespace EQ { diff --git a/common/net/servertalk_common.h b/common/net/servertalk_common.h index aa779b5ed9..91d1d6914d 100644 --- a/common/net/servertalk_common.h +++ b/common/net/servertalk_common.h @@ -1,6 +1,6 @@ #pragma once -#include "../servertalk.h" +#include "common/servertalk.h" namespace EQ { diff --git a/common/net/servertalk_legacy_client_connection.cpp b/common/net/servertalk_legacy_client_connection.cpp index deba4a4641..d745b7c585 100644 --- a/common/net/servertalk_legacy_client_connection.cpp +++ b/common/net/servertalk_legacy_client_connection.cpp @@ -1,6 +1,7 @@ #include "servertalk_legacy_client_connection.h" -#include "dns.h" -#include "../eqemu_logsys.h" + +#include "common/net/dns.h" +#include "common/eqemu_logsys.h" EQ::Net::ServertalkLegacyClient::ServertalkLegacyClient(const std::string &addr, int port, bool ipv6) : m_timer(std::make_unique(100, true, std::bind(&EQ::Net::ServertalkLegacyClient::Connect, this))) diff --git a/common/net/servertalk_legacy_client_connection.h b/common/net/servertalk_legacy_client_connection.h index f773de12bd..9fa75b10aa 100644 --- a/common/net/servertalk_legacy_client_connection.h +++ b/common/net/servertalk_legacy_client_connection.h @@ -1,9 +1,9 @@ #pragma once -#include "tcp_connection.h" -#include "../event/timer.h" -#include "servertalk_common.h" -#include "packet.h" +#include "common/event/timer.h" +#include "common/net/tcp_connection.h" +#include "common/net/packet.h" +#include "common/net/servertalk_common.h" namespace EQ { diff --git a/common/net/servertalk_server.h b/common/net/servertalk_server.h index f58243e98f..8637728307 100644 --- a/common/net/servertalk_server.h +++ b/common/net/servertalk_server.h @@ -1,9 +1,10 @@ #pragma once -#include "tcp_server.h" -#include "servertalk_server_connection.h" -#include +#include "common/net/servertalk_server_connection.h" +#include "common/net/tcp_server.h" + #include +#include namespace EQ { diff --git a/common/net/servertalk_server_connection.cpp b/common/net/servertalk_server_connection.cpp index efc2d572ec..a429ddb69a 100644 --- a/common/net/servertalk_server_connection.cpp +++ b/common/net/servertalk_server_connection.cpp @@ -1,7 +1,8 @@ #include "servertalk_server_connection.h" -#include "servertalk_server.h" -#include "../eqemu_logsys.h" -#include "../util/uuid.h" + +#include "common/eqemu_logsys.h" +#include "common/net/servertalk_server.h" +#include "common/util/uuid.h" EQ::Net::ServertalkServerConnection::ServertalkServerConnection(std::shared_ptr c, EQ::Net::ServertalkServer *parent) { diff --git a/common/net/servertalk_server_connection.h b/common/net/servertalk_server_connection.h index 8e262baa1f..17686c2049 100644 --- a/common/net/servertalk_server_connection.h +++ b/common/net/servertalk_server_connection.h @@ -1,8 +1,9 @@ #pragma once -#include "tcp_connection.h" -#include "servertalk_common.h" -#include "packet.h" +#include "common/net/packet.h" +#include "common/net/servertalk_common.h" +#include "common/net/tcp_connection.h" + #include namespace EQ diff --git a/common/net/tcp_connection.cpp b/common/net/tcp_connection.cpp index f277e95e86..f57a1838c6 100644 --- a/common/net/tcp_connection.cpp +++ b/common/net/tcp_connection.cpp @@ -1,5 +1,7 @@ #include "tcp_connection.h" -#include "../event/event_loop.h" + +#include "common/event/event_loop.h" + #include WriteReqPool tcp_write_pool; diff --git a/common/net/tcp_connection.h b/common/net/tcp_connection.h index d64695dd24..f8fe211420 100644 --- a/common/net/tcp_connection.h +++ b/common/net/tcp_connection.h @@ -1,10 +1,11 @@ #pragma once -#include "tcp_connection_pooling.h" +#include "common/net/tcp_connection_pooling.h" + +#include "uv.h" #include -#include #include -#include +#include namespace EQ { diff --git a/common/net/tcp_connection_pooling.h b/common/net/tcp_connection_pooling.h index 44f0abe926..4166b5ed64 100644 --- a/common/net/tcp_connection_pooling.h +++ b/common/net/tcp_connection_pooling.h @@ -1,14 +1,15 @@ #pragma once -#include "../eqemu_logsys.h" -#include +#include "common/eqemu_logsys.h" + +#include "uv.h" #include #include +#include #include -#include #include -#include -#include +#include +#include namespace EQ { namespace Net { class TCPConnection; } } diff --git a/common/net/tcp_server.cpp b/common/net/tcp_server.cpp index 777c92be5e..40761e540e 100644 --- a/common/net/tcp_server.cpp +++ b/common/net/tcp_server.cpp @@ -1,5 +1,6 @@ #include "tcp_server.h" -#include "../event/event_loop.h" + +#include "common/event/event_loop.h" void on_close_tcp_server_handle(uv_handle_t* handle) { delete (uv_tcp_t *)handle; diff --git a/common/net/tcp_server.h b/common/net/tcp_server.h index 6f8280d3c1..9350b66a63 100644 --- a/common/net/tcp_server.h +++ b/common/net/tcp_server.h @@ -1,6 +1,6 @@ #pragma once -#include "tcp_connection.h" +#include "common/net/tcp_connection.h" namespace EQ { @@ -22,4 +22,4 @@ namespace EQ uv_tcp_t *m_socket; }; } -} \ No newline at end of file +} diff --git a/common/net/websocket_server.cpp b/common/net/websocket_server.cpp index 1e8b80b64e..dcbab2f046 100644 --- a/common/net/websocket_server.cpp +++ b/common/net/websocket_server.cpp @@ -1,12 +1,13 @@ #include "websocket_server.h" -#include "../event/event_loop.h" -#include "../event/timer.h" -#include -#include + +#include "common/emu_constants.h" +#include "common/event/event_loop.h" +#include "common/event/timer.h" + +#include "fmt/format.h" +#include #include #include -#include -#include "../emu_constants.h" struct MethodHandlerEntry { diff --git a/common/net/websocket_server.h b/common/net/websocket_server.h index 4d5df580bc..37e0574319 100644 --- a/common/net/websocket_server.h +++ b/common/net/websocket_server.h @@ -1,11 +1,11 @@ #pragma once -#include "websocket_server_connection.h" +#include "common/json/json.h" +#include "common/net/websocket_server_connection.h" -#include "../json/json.h" -#include -#include #include +#include +#include namespace EQ { diff --git a/common/net/websocket_server_connection.cpp b/common/net/websocket_server_connection.cpp index 36e85eb743..0fc913d2e5 100644 --- a/common/net/websocket_server_connection.cpp +++ b/common/net/websocket_server_connection.cpp @@ -1,10 +1,11 @@ #include "websocket_server_connection.h" -#include "websocket_server.h" -#include "../timer.h" -#include "../util/uuid.h" + +#include "common/net/websocket_server.h" +#include "common/timer.h" +#include "common/util/uuid.h" + +#include "fmt/format.h" #include -#include -#include struct EQ::Net::WebsocketServerConnection::Impl { WebsocketServer *parent; diff --git a/common/net/websocket_server_connection.h b/common/net/websocket_server_connection.h index 5ea8b40297..9d75882616 100644 --- a/common/net/websocket_server_connection.h +++ b/common/net/websocket_server_connection.h @@ -1,10 +1,11 @@ #pragma once -#include "tcp_server.h" -#include "../types.h" -#include "../json/json-forwards.h" -#include -#include +#include "common/json/json-forwards.h" +#include "common/net/tcp_server.h" +#include "common/types.h" + +#include "websocketpp/config/core.hpp" +#include "websocketpp/server.hpp" namespace EQ { diff --git a/common/op_codes.h b/common/op_codes.h index 4142c61f32..b9554aa73c 100644 --- a/common/op_codes.h +++ b/common/op_codes.h @@ -1,6 +1,5 @@ -#ifndef _OP_CODES_H +#pragma once -#define _OP_CODES_H static const char OP_SessionRequest = 0x01; static const char OP_SessionResponse = 0x02; @@ -15,5 +14,3 @@ static const char OP_OutOfOrderAck = 0x11; static const char OP_Ack = 0x15; static const char OP_AppCombined = 0x19; static const char OP_OutOfSession = 0x1d; - -#endif diff --git a/common/opcode_map.cpp b/common/opcode_map.cpp index c0556cf2ab..8d1aae5b7a 100644 --- a/common/opcode_map.cpp +++ b/common/opcode_map.cpp @@ -1,4 +1,5 @@ -#include "global_define.h" +#include "common/global_define.h" + #include #include diff --git a/common/opcodemgr.cpp b/common/opcodemgr.cpp index 70bcff7027..771fb439c8 100644 --- a/common/opcodemgr.cpp +++ b/common/opcodemgr.cpp @@ -16,10 +16,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "eqemu_logsys.h" -#include "emu_opcodes.h" #include "opcodemgr.h" +#include "common/emu_opcodes.h" +#include "common/eqemu_logsys.h" + #include #include #include diff --git a/common/opcodemgr.h b/common/opcodemgr.h index 138fadd971..8846ed6191 100644 --- a/common/opcodemgr.h +++ b/common/opcodemgr.h @@ -16,12 +16,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef OPCODE_MANAGER_H -#define OPCODE_MANAGER_H +#pragma once -#include "types.h" -#include "mutex.h" -#include "emu_opcodes.h" +#include "common/emu_opcodes.h" +#include "common/mutex.h" +#include "common/types.h" #include @@ -158,6 +157,3 @@ class EmptyOpcodeManager : public MutableOpcodeManager { std::map emu_to_eq; std::map eq_to_emu; }; - -#endif - diff --git a/common/packet_dump.cpp b/common/packet_dump.cpp index a4ecba7811..33c7196055 100644 --- a/common/packet_dump.cpp +++ b/common/packet_dump.cpp @@ -16,14 +16,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "packet_dump.h" + +#include "common/servertalk.h" + #include #include #include #include -#include "packet_dump.h" -#include "../common/servertalk.h" - void DumpPacketAscii(const uchar* buf, uint32 size, uint32 cols, uint32 skip) { // Output as ASCII for(uint32 i=skip; i #include diff --git a/common/packet_dump_file.h b/common/packet_dump_file.h index aa50b04202..c3f3dcc17c 100644 --- a/common/packet_dump_file.h +++ b/common/packet_dump_file.h @@ -15,12 +15,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PACKET_DUMP_FILE_H -#define PACKET_DUMP_FILE_H -#include +#pragma once + +#include "common/types.h" -#include "../common/types.h" +#include class EQApplicationPacket; @@ -32,5 +32,3 @@ void FileDumpPacket(const char* filename, const uchar* buf, uint32 size); void FileDumpPacket(const char* filename, const EQApplicationPacket* app); void FilePrintLine(const char* filename, bool prefix_timestamp = false, const char* text = 0, ...); void FilePrint(const char* filename, bool newline = true, bool prefix_timestamp = false, const char* text = 0, ...); -#endif - diff --git a/common/packet_functions.cpp b/common/packet_functions.cpp index dbd10f14f9..a882107f2a 100644 --- a/common/packet_functions.cpp +++ b/common/packet_functions.cpp @@ -15,16 +15,18 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include -#include -#include -#include -#include "packet_dump.h" + #include "packet_functions.h" +#include "common/global_define.h" +#include "common/packet_dump.h" + +#include "zlib.h" +#include +#include +#include #ifndef WIN32 - #include +#include #endif void EncryptProfilePacket(EQApplicationPacket* app) { diff --git a/common/packet_functions.h b/common/packet_functions.h index 3746c7c795..8c400534de 100644 --- a/common/packet_functions.h +++ b/common/packet_functions.h @@ -15,9 +15,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PACKET_FUNCTIONS_H -#define PACKET_FUNCTIONS_H -#include "types.h" + +#pragma once + +#include "common/types.h" class EQApplicationPacket; @@ -39,5 +40,3 @@ void EncryptZoneSpawnPacket(uchar* pBuffer, uint32 size); int DeflatePacket(const unsigned char* in_data, int in_length, unsigned char* out_data, int max_out_length); uint32 InflatePacket(const uchar* indata, uint32 indatalen, uchar* outdata, uint32 outdatalen, bool iQuiet = false); uint32 GenerateCRC(uint32 b, uint32 bufsize, uchar *buf); - -#endif diff --git a/common/packetfile.cpp b/common/packetfile.cpp index 5885382ffa..eea6ef3745 100644 --- a/common/packetfile.cpp +++ b/common/packetfile.cpp @@ -1,16 +1,12 @@ -#ifndef WIN32 -#include -#else -#include -#endif +#include "packetfile.h" + +#include "common/eq_opcodes.h" +#include "common/eq_packet_structs.h" +#include "common/misc.h" #include #include #include -#include "packetfile.h" -#include "../common/eq_opcodes.h" -#include "../common/eq_packet_structs.h" -#include "../common/misc.h" #include PacketFileWriter::PacketFileWriter(bool _force_flush) { diff --git a/common/packetfile.h b/common/packetfile.h index bacbbc2b40..953ad73806 100644 --- a/common/packetfile.h +++ b/common/packetfile.h @@ -1,10 +1,9 @@ -#ifndef PACKET_FILE_H -#define PACKET_FILE_H +#pragma once + +#include "common/types.h" -#include "../common/types.h" #include #include -//#include //constants used in the packet file header #define PACKET_FILE_MAGIC 0x93a7b6f6 diff --git a/common/patches/patches.cpp b/common/patches/patches.cpp index 775e4e3dc9..6158499726 100644 --- a/common/patches/patches.cpp +++ b/common/patches/patches.cpp @@ -17,15 +17,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../global_define.h" #include "patches.h" -#include "titanium.h" -#include "uf.h" -#include "sof.h" -#include "sod.h" -#include "rof.h" -#include "rof2.h" +#include "common/global_define.h" +#include "common/patches/rof.h" +#include "common/patches/rof2.h" +#include "common/patches/sod.h" +#include "common/patches/sof.h" +#include "common/patches/titanium.h" +#include "common/patches/uf.h" void RegisterAllPatches(EQStreamIdentifier &into) diff --git a/common/patches/patches.h b/common/patches/patches.h index 38fd549be8..d5a5661b5b 100644 --- a/common/patches/patches.h +++ b/common/patches/patches.h @@ -17,8 +17,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_PATCHES_H -#define COMMON_PATCHES_H +#pragma once /*enum { @@ -31,5 +30,3 @@ class EQStreamIdentifier; void RegisterAllPatches(EQStreamIdentifier &into); void ReloadAllPatches(); - -#endif /*COMMON_PATCHES_H*/ diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 15b745b163..0e6f48861a 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -17,24 +17,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../global_define.h" -#include "../eqemu_config.h" -#include "../eqemu_logsys.h" #include "rof.h" -#include "../opcodemgr.h" - -#include "../eq_stream_ident.h" -#include "../crc32.h" - -#include "../eq_packet_structs.h" -#include "../misc_functions.h" -#include "../strings.h" -#include "../inventory_profile.h" #include "rof_structs.h" -#include "../rulesys.h" -#include "../path_manager.h" -#include "../races.h" -#include "../raid.h" + +#include "common/crc32.h" +#include "common/eq_packet_structs.h" +#include "common/eq_stream_ident.h" +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/inventory_profile.h" +#include "common/misc_functions.h" +#include "common/opcodemgr.h" +#include "common/path_manager.h" +#include "common/races.h" +#include "common/raid.h" +#include "common/rulesys.h" +#include "common/strings.h" #include #include diff --git a/common/patches/rof.h b/common/patches/rof.h index 21a525192d..a2d6f8fda9 100644 --- a/common/patches/rof.h +++ b/common/patches/rof.h @@ -17,10 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_ROF_H -#define COMMON_ROF_H +#pragma once -#include "../struct_strategy.h" +#include "common/struct_strategy.h" class EQStreamIdentifier; @@ -50,6 +49,4 @@ namespace RoF #include "rof_ops.h" }; -}; /*RoF*/ - -#endif /*COMMON_ROF_H*/ +} /*RoF*/ diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index b250a5de61..ecefc46321 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -17,31 +17,30 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../global_define.h" -#include "../eqemu_config.h" -#include "../eqemu_logsys.h" #include "rof2.h" -#include "../opcodemgr.h" - -#include "../eq_stream_ident.h" -#include "../crc32.h" - -#include "../eq_packet_structs.h" -#include "../misc_functions.h" -#include "../strings.h" -#include "../inventory_profile.h" #include "rof2_structs.h" -#include "../rulesys.h" -#include "../path_manager.h" -#include "../classes.h" -#include "../races.h" -#include "../raid.h" -#include -#include -#include +#include "common/classes.h" +#include "common/crc32.h" +#include "common/eq_packet_structs.h" +#include "common/eq_stream_ident.h" +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/inventory_profile.h" +#include "common/misc_functions.h" +#include "common/opcodemgr.h" +#include "common/path_manager.h" +#include "common/races.h" +#include "common/raid.h" +#include "common/rulesys.h" +#include "common/strings.h" + #include #include +#include +#include +#include namespace RoF2 diff --git a/common/patches/rof2.h b/common/patches/rof2.h index f5f00db477..7775fff002 100644 --- a/common/patches/rof2.h +++ b/common/patches/rof2.h @@ -17,10 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_ROF2_H -#define COMMON_ROF2_H +#pragma once -#include "../struct_strategy.h" +#include "common/struct_strategy.h" class EQStreamIdentifier; @@ -51,5 +50,3 @@ namespace RoF2 }; }; /*RoF2*/ - -#endif /*COMMON_ROF2_H*/ diff --git a/common/patches/rof2_limits.cpp b/common/patches/rof2_limits.cpp index 6df113f514..4cd5a69443 100644 --- a/common/patches/rof2_limits.cpp +++ b/common/patches/rof2_limits.cpp @@ -19,7 +19,7 @@ #include "rof2_limits.h" -#include "../strings.h" +#include "common/strings.h" int16 RoF2::invtype::GetInvTypeSize(int16 inv_type) diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index 668b0df74a..fbf4fc677b 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -17,12 +17,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_ROF2_LIMITS_H -#define COMMON_ROF2_LIMITS_H +#pragma once -#include "../types.h" -#include "../emu_versions.h" -#include "../skills.h" +#include "common/emu_versions.h" +#include "common/skills.h" +#include "common/types.h" namespace RoF2 @@ -360,6 +359,4 @@ namespace RoF2 } /*spells*/ -}; /*RoF2*/ - -#endif /*COMMON_ROF2_LIMITS_H*/ +} /*RoF2*/ diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index b6ad6bbf1c..84c026d5d0 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -17,18 +17,24 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_ROF2_STRUCTS_H -#define COMMON_ROF2_STRUCTS_H +#pragma once +#include "common/eq_packet_structs.h" +#include "common/patches/rof2_limits.h" +#include "common/strings.h" +#include "common/textures.h" +#include "common/types.h" + +#include "fmt/format.h" -namespace RoF2 -{ - namespace structs { + +namespace RoF2 { namespace structs { /* ** Compiler override to ensure ** byte aligned structures */ +#pragma pack(push) #pragma pack(1) struct LoginInfo_Struct { @@ -5426,7 +5432,8 @@ struct Parcel_Struct /*216*/ uint32 unknown_216; /*220*/ uint32 unknown_220; }; - }; /*structs*/ + +} /*structs*/ struct EvolveItemToggle_Struct { uint32 action; @@ -5454,6 +5461,6 @@ struct EvolveXPWindowSendDetails_Struct { /*030*/ char serialize_data[]; }; -}; /*RoF2*/ +#pragma pack(pop) -#endif /*COMMON_ROF2_STRUCTS_H*/ +} /*RoF2*/ diff --git a/common/patches/rof_limits.cpp b/common/patches/rof_limits.cpp index beb2bdbbc0..0011c9dcea 100644 --- a/common/patches/rof_limits.cpp +++ b/common/patches/rof_limits.cpp @@ -19,7 +19,7 @@ #include "rof_limits.h" -#include "../strings.h" +#include "common/strings.h" int16 RoF::invtype::GetInvTypeSize(int16 inv_type) diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index 4df54d1c25..e8f4637f87 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -17,12 +17,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_ROF_LIMITS_H -#define COMMON_ROF_LIMITS_H +#pragma once -#include "../types.h" -#include "../emu_versions.h" -#include "../skills.h" +#include "common/emu_versions.h" +#include "common/skills.h" +#include "common/types.h" namespace RoF @@ -314,6 +313,4 @@ namespace RoF } /*spells*/ -}; /*RoF*/ - -#endif /*COMMON_ROF_LIMITS_H*/ +} /*RoF*/ diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index d065a2b043..ec00432e2a 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -17,18 +17,19 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_ROF_STRUCTS_H -#define COMMON_ROF_STRUCTS_H +#pragma once +#include "common/patches/rof_limits.h" +#include "common/textures.h" +#include "common/types.h" -namespace RoF -{ - namespace structs { +namespace RoF { namespace structs { /* ** Compiler override to ensure ** byte aligned structures */ +#pragma pack(push) #pragma pack(1) struct LoginInfo_Struct { @@ -5139,8 +5140,7 @@ struct SayLinkBodyFrame_Struct { /*055*/ }; - }; /*structs*/ - -}; /*RoF*/ +#pragma pack(pop) -#endif /*COMMON_ROF_STRUCTS_H*/ +} /*structs*/ +} /*RoF*/ diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 72a3a3c488..01bf5f8cf3 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -17,24 +17,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../global_define.h" -#include "../eqemu_config.h" -#include "../eqemu_logsys.h" #include "sod.h" -#include "../opcodemgr.h" - -#include "../eq_stream_ident.h" -#include "../crc32.h" - -#include "../eq_packet_structs.h" -#include "../misc_functions.h" -#include "../strings.h" -#include "../item_instance.h" #include "sod_structs.h" -#include "../rulesys.h" -#include "../path_manager.h" -#include "../races.h" -#include "../raid.h" + +#include "common/crc32.h" +#include "common/eq_packet_structs.h" +#include "common/eq_stream_ident.h" +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/item_instance.h" +#include "common/misc_functions.h" +#include "common/opcodemgr.h" +#include "common/path_manager.h" +#include "common/races.h" +#include "common/raid.h" +#include "common/rulesys.h" +#include "common/strings.h" #include #include diff --git a/common/patches/sod.h b/common/patches/sod.h index 1a0188f6ee..d8e2cd8824 100644 --- a/common/patches/sod.h +++ b/common/patches/sod.h @@ -17,10 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_SOD_H -#define COMMON_SOD_H +#pragma once -#include "../struct_strategy.h" +#include "common/struct_strategy.h" class EQStreamIdentifier; @@ -50,6 +49,4 @@ namespace SoD #include "sod_ops.h" }; -}; /*SoD*/ - -#endif /*COMMON_SOD_H*/ +} /*SoD*/ diff --git a/common/patches/sod_limits.cpp b/common/patches/sod_limits.cpp index 87acff88a5..9141e08e23 100644 --- a/common/patches/sod_limits.cpp +++ b/common/patches/sod_limits.cpp @@ -19,7 +19,7 @@ #include "sod_limits.h" -#include "../strings.h" +#include "common/strings.h" int16 SoD::invtype::GetInvTypeSize(int16 inv_type) diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index 46d8293fe5..bcf566bdac 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -17,12 +17,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_SOD_LIMITS_H -#define COMMON_SOD_LIMITS_H +#pragma once -#include "../types.h" -#include "../emu_versions.h" -#include "../skills.h" +#include "common/emu_versions.h" +#include "common/skills.h" +#include "common/types.h" namespace SoD @@ -339,6 +338,4 @@ namespace SoD } /*spells*/ -}; /*SoD*/ - -#endif /*COMMON_SOD_LIMITS_H*/ +} /*SoD*/ diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 03648c1166..5519e5b7d1 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -17,13 +17,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_SOD_STRUCTS_H -#define COMMON_SOD_STRUCTS_H +#pragma once +#include "common/eq_packet_structs.h" +#include "common/patches/sod_limits.h" +#include "common/textures.h" +#include "common/types.h" -namespace SoD -{ - namespace structs { +namespace SoD { namespace structs { static const uint32 BUFF_COUNT = 25; @@ -32,6 +33,7 @@ static const uint32 BUFF_COUNT = 25; ** Compiler override to ensure ** byte aligned structures */ +#pragma pack(push) #pragma pack(1) struct LoginInfo_Struct { @@ -4528,8 +4530,7 @@ struct SayLinkBodyFrame_Struct { /*050*/ }; - }; /*structs*/ - -}; /*SoD*/ +#pragma pack(pop) -#endif /*COMMON_SOD_STRUCTS_H*/ +} /*structs*/ +} /*SoD*/ diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 444b33b35a..1ae60f054b 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -17,23 +17,22 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../global_define.h" -#include "../eqemu_config.h" -#include "../eqemu_logsys.h" #include "sof.h" -#include "../opcodemgr.h" - -#include "../eq_stream_ident.h" -#include "../crc32.h" - -#include "../eq_packet_structs.h" -#include "../misc_functions.h" -#include "../strings.h" -#include "../item_instance.h" #include "sof_structs.h" -#include "../rulesys.h" -#include "../path_manager.h" -#include "../raid.h" + +#include "common/crc32.h" +#include "common/eq_packet_structs.h" +#include "common/eq_stream_ident.h" +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/item_instance.h" +#include "common/misc_functions.h" +#include "common/opcodemgr.h" +#include "common/path_manager.h" +#include "common/raid.h" +#include "common/rulesys.h" +#include "common/strings.h" #include #include diff --git a/common/patches/sof.h b/common/patches/sof.h index 47a6433ac6..e240d7c615 100644 --- a/common/patches/sof.h +++ b/common/patches/sof.h @@ -17,10 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_SOF_H -#define COMMON_SOF_H +#pragma once -#include "../struct_strategy.h" +#include "common/struct_strategy.h" class EQStreamIdentifier; @@ -50,6 +49,4 @@ namespace SoF #include "sof_ops.h" }; -}; /*SoF*/ - -#endif /*COMMON_SOF_H*/ +} /*SoF*/ diff --git a/common/patches/sof_limits.cpp b/common/patches/sof_limits.cpp index a646991da5..8af38cc495 100644 --- a/common/patches/sof_limits.cpp +++ b/common/patches/sof_limits.cpp @@ -19,7 +19,7 @@ #include "sof_limits.h" -#include "../strings.h" +#include "common/strings.h" int16 SoF::invtype::GetInvTypeSize(int16 inv_type) diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 063644e18b..16aab91bc5 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -17,12 +17,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_SOF_LIMITS_H -#define COMMON_SOF_LIMITS_H +#pragma once -#include "../types.h" -#include "../emu_versions.h" -#include "../skills.h" +#include "common/emu_versions.h" +#include "common/skills.h" +#include "common/types.h" namespace SoF @@ -344,6 +343,4 @@ namespace SoF } /*spells*/ -}; /*SoF*/ - -#endif /*COMMON_SOF_LIMITS_H*/ +} /*SoF*/ diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 918f8e32a1..8224910e31 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -17,13 +17,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_SOF_STRUCTS_H -#define COMMON_SOF_STRUCTS_H +#pragma once +#include "common/eq_packet_structs.h" +#include "common/patches/sof_limits.h" +#include "common/textures.h" +#include "common/types.h" -namespace SoF -{ - namespace structs { +namespace SoF { namespace structs { static const uint32 BUFF_COUNT = 25; @@ -32,6 +33,7 @@ static const uint32 BUFF_COUNT = 25; ** Compiler override to ensure ** byte aligned structures */ +#pragma pack(push) #pragma pack(1) struct LoginInfo_Struct { @@ -4298,8 +4300,7 @@ struct SayLinkBodyFrame_Struct { /*050*/ }; - }; /*structs*/ - -}; /*SoF*/ +#pragma pack(pop) -#endif /*COMMON_SOF_STRUCTS_H*/ +} /*structs*/ +} /*SoF*/ diff --git a/common/patches/template.cpp b/common/patches/template.cpp index 5e075ea8a9..14fe921454 100644 --- a/common/patches/template.cpp +++ b/common/patches/template.cpp @@ -1,12 +1,12 @@ #include "TEMPLATE.h" -#include "../opcodemgr.h" -#include "../logsys.h" -#include "../eq_stream_ident.h" - -#include "../eq_packet_structs.h" #include "TEMPLATE_structs.h" +#include "common/eq_packet_structs.h" +#include "common/eq_stream_ident.h" +#include "common/logsys.h" +#include "common/opcodemgr.h" + namespace TEMPLATE { static const char *name = "CHANGEME"; @@ -146,30 +146,4 @@ DECODE(OP_SetServerFilter) { FINISH_DIRECT_DECODE(); } - - - - - - - - - - - - - - - - - - - - -} //end namespace TEMPLATE - - - - - - +} // namespace TEMPLATE diff --git a/common/patches/template.h b/common/patches/template.h index f264cf3fd7..990a474fa0 100644 --- a/common/patches/template.h +++ b/common/patches/template.h @@ -1,8 +1,6 @@ -#ifndef TEMPLATE_H_ -#define TEMPLATE_H_ +#pragma once -#include "../struct_strategy.h" -#include "../eqemu_config_extern.h" +#include "common/struct_strategy.h" class EQStreamIdentifier; @@ -32,7 +30,3 @@ namespace TEMPLATE { }; }; - - - -#endif /*TEMPLATE_H_*/ diff --git a/common/patches/template_limits.h b/common/patches/template_limits.h index 54690d3c10..901055da75 100644 --- a/common/patches/template_limits.h +++ b/common/patches/template_limits.h @@ -17,8 +17,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_TEMPLATE_LIMITS_H -#define COMMON_TEMPLATE_LIMITS_H +#pragma once namespace TEMPLATE @@ -27,5 +26,3 @@ namespace TEMPLATE // put constants here and #include appropriately }; /* TEMPLATE */ - -#endif /*COMMON_TEMPLATE_LIMITS_H*/ diff --git a/common/patches/template_structs.h b/common/patches/template_structs.h index 78d085f916..8da39d72be 100644 --- a/common/patches/template_structs.h +++ b/common/patches/template_structs.h @@ -1,28 +1,11 @@ -#ifndef TEMPLATE_STRUCTS_H_ -#define TEMPLATE_STRUCTS_H_ +#pragma once -namespace TEMPLATE { - namespace structs { +namespace TEMPLATE { namespace structs { //paste contents of eq_packet_structs.h here... - }; //end namespace structs -}; //end namespace TEMPLATE - - - - -#endif /*TEMPLATE_STRUCTS_H_*/ - - - - - - - - - - +} // namespace structs +} // namespace TEMPLATE diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index c93b925814..3852c88085 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -17,25 +17,24 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../global_define.h" -#include "../eqemu_config.h" -#include "../eqemu_logsys.h" #include "titanium.h" -#include "../opcodemgr.h" - -#include "../eq_stream_ident.h" -#include "../crc32.h" -#include "../races.h" - -#include "../eq_packet_structs.h" -#include "../misc_functions.h" -#include "../strings.h" -#include "../item_instance.h" #include "titanium_structs.h" -#include "../rulesys.h" -#include "../path_manager.h" -#include "../raid.h" -#include "../guilds.h" + +#include "common/crc32.h" +#include "common/eq_packet_structs.h" +#include "common/eq_stream_ident.h" +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/guilds.h" +#include "common/item_instance.h" +#include "common/misc_functions.h" +#include "common/opcodemgr.h" +#include "common/path_manager.h" +#include "common/races.h" +#include "common/raid.h" +#include "common/rulesys.h" +#include "common/strings.h" #include diff --git a/common/patches/titanium.h b/common/patches/titanium.h index 9e5cc7af58..25362503cb 100644 --- a/common/patches/titanium.h +++ b/common/patches/titanium.h @@ -17,10 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_TITANIUM_H -#define COMMON_TITANIUM_H +#pragma once -#include "../struct_strategy.h" +#include "common/struct_strategy.h" class EQStreamIdentifier; @@ -50,6 +49,4 @@ namespace Titanium #include "titanium_ops.h" }; -}; /*Titanium*/ - -#endif /*COMMON_TITANIUM_H*/ +} /*Titanium*/ diff --git a/common/patches/titanium_limits.cpp b/common/patches/titanium_limits.cpp index 76da83b632..dbe6e82da3 100644 --- a/common/patches/titanium_limits.cpp +++ b/common/patches/titanium_limits.cpp @@ -19,7 +19,7 @@ #include "titanium_limits.h" -#include "../strings.h" +#include "common/strings.h" int16 Titanium::invtype::GetInvTypeSize(int16 inv_type) diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index cd7d9e5d8f..2ed5337e6f 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -17,12 +17,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_TITANIUM_LIMITS_H -#define COMMON_TITANIUM_LIMITS_H +#pragma once -#include "../types.h" -#include "../emu_versions.h" -#include "../skills.h" +#include "common/emu_versions.h" +#include "common/skills.h" +#include "common/types.h" namespace Titanium @@ -340,6 +339,4 @@ namespace Titanium } /*spells*/ -}; /*Titanium*/ - -#endif /*COMMON_TITANIUM_LIMITS_H*/ +} /*Titanium*/ diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 2d92759425..ff3ad0272b 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -17,13 +17,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_TITANIUM_STRUCTS_H -#define COMMON_TITANIUM_STRUCTS_H +#pragma once +#include "common/eq_packet_structs.h" +#include "common/patches/titanium_limits.h" +#include "common/textures.h" +#include "common/types.h" -namespace Titanium -{ - namespace structs { + +namespace Titanium { namespace structs { static const uint32 BUFF_COUNT = 25; @@ -32,6 +34,7 @@ static const uint32 BUFF_COUNT = 25; ** Compiler override to ensure ** byte aligned structures */ +#pragma pack(push) #pragma pack(1) struct LoginInfo_Struct { @@ -3774,8 +3777,7 @@ enum TiBazaarTraderBuyerActions { ReconcileItems = 20 }; - }; /*structs*/ - -}; /*Titanium*/ +#pragma pack(pop) -#endif /*COMMON_TITANIUM_STRUCTS_H*/ +} /*structs*/ +} /*Titanium*/ diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index c414b3353b..d2ba9c20c6 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -17,29 +17,27 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../global_define.h" -#include "../eqemu_config.h" -#include "../eqemu_logsys.h" #include "uf.h" -#include "../opcodemgr.h" - -#include "../eq_stream_ident.h" -#include "../crc32.h" - -#include "../eq_packet_structs.h" -#include "../misc_functions.h" -#include "../strings.h" -#include "../item_instance.h" #include "uf_structs.h" -#include "../rulesys.h" -#include "../path_manager.h" -#include "../classes.h" -#include "../races.h" -#include "../raid.h" -#include "../guilds.h" -//#include "../repositories/trader_repository.h" -#include +#include "common/classes.h" +#include "common/crc32.h" +#include "common/eq_packet_structs.h" +#include "common/eq_stream_ident.h" +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/guilds.h" +#include "common/item_instance.h" +#include "common/misc_functions.h" +#include "common/opcodemgr.h" +#include "common/path_manager.h" +#include "common/races.h" +#include "common/raid.h" +#include "common/rulesys.h" +#include "common/strings.h" + +#include "cereal/types/vector.hpp" #include #include @@ -2716,7 +2714,7 @@ namespace UF buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); dest->FastQueuePacket(&outapp, ack_req); delete in; diff --git a/common/patches/uf.h b/common/patches/uf.h index 465f32e740..8eb4e3488a 100644 --- a/common/patches/uf.h +++ b/common/patches/uf.h @@ -17,10 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_UF_H -#define COMMON_UF_H +#pragma once -#include "../struct_strategy.h" +#include "common/struct_strategy.h" class EQStreamIdentifier; @@ -51,5 +50,3 @@ namespace UF }; }; /*UF*/ - -#endif /*COMMON_UF_H*/ diff --git a/common/patches/uf_limits.cpp b/common/patches/uf_limits.cpp index f0083d0866..6f75f4474a 100644 --- a/common/patches/uf_limits.cpp +++ b/common/patches/uf_limits.cpp @@ -19,7 +19,7 @@ #include "uf_limits.h" -#include "../strings.h" +#include "common/strings.h" int16 UF::invtype::GetInvTypeSize(int16 inv_type) diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index 29eb2495bb..ccde464285 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -17,12 +17,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_UF_LIMITS_H -#define COMMON_UF_LIMITS_H +#pragma once -#include "../types.h" -#include "../emu_versions.h" -#include "../skills.h" +#include "common/emu_versions.h" +#include "common/skills.h" +#include "common/types.h" namespace UF @@ -343,6 +342,4 @@ namespace UF } /*spells*/ -}; /*UF*/ - -#endif /*COMMON_UF_LIMITS_H*/ +} /*UF*/ diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 7f48929c55..40d7e5691e 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -17,13 +17,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_UF_STRUCTS_H -#define COMMON_UF_STRUCTS_H +#pragma once +#include "common/eq_packet_structs.h" +#include "common/patches/uf_limits.h" +#include "common/textures.h" +#include "common/types.h" -namespace UF -{ - namespace structs { +namespace UF { namespace structs { static const uint32 BUFF_COUNT = 30; @@ -32,6 +33,7 @@ static const uint32 BUFF_COUNT = 30; ** Compiler override to ensure ** byte aligned structures */ +#pragma pack(push) #pragma pack(1) struct LoginInfo_Struct { @@ -4710,8 +4712,7 @@ enum UFBazaarTraderBuyerActions { ReconcileItems = 20 }; - }; /*structs*/ - -}; /*UF*/ +#pragma pack(pop) -#endif /*COMMON_UF_STRUCTS_H*/ +} /*structs*/ +} /*UF*/ diff --git a/common/path_manager.cpp b/common/path_manager.cpp index c638358545..18dd1eb1dd 100644 --- a/common/path_manager.cpp +++ b/common/path_manager.cpp @@ -1,8 +1,9 @@ #include "path_manager.h" -#include "file.h" -#include "eqemu_logsys.h" -#include "eqemu_config.h" -#include "strings.h" + +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/file.h" +#include "common/strings.h" #include diff --git a/common/path_manager.h b/common/path_manager.h index 67919511e8..7bf2fa2808 100644 --- a/common/path_manager.h +++ b/common/path_manager.h @@ -1,6 +1,4 @@ -#ifndef EQEMU_PATH_MANAGER_H -#define EQEMU_PATH_MANAGER_H - +#pragma once #include #include @@ -43,5 +41,3 @@ class PathManager { std::string m_server_path; std::string m_shared_memory_path; }; - -#endif //EQEMU_PATH_MANAGER_H diff --git a/common/pch/app-pch.h b/common/pch/app-pch.h index aa2244f13e..32d2b070db 100644 --- a/common/pch/app-pch.h +++ b/common/pch/app-pch.h @@ -1,9 +1,9 @@ #pragma once -#include "../types.h" -#include "../database.h" -#include "../strings.h" -#include "../eqemu_logsys.h" -#include "../eqemu_logsys_log_aliases.h" -#include "../features.h" -#include "../global_define.h" +#include "common/types.h" +#include "common/database.h" +#include "common/strings.h" +#include "common/eqemu_logsys.h" +#include "common/eqemu_logsys_log_aliases.h" +#include "common/features.h" +#include "common/global_define.h" diff --git a/common/pch/std-pch.h b/common/pch/std-pch.h index 3b1b9faad9..77ca1ce6f0 100644 --- a/common/pch/std-pch.h +++ b/common/pch/std-pch.h @@ -1,14 +1,14 @@ #pragma once +// fmt +#include "fmt/format.h" + // Lightweight, widely used -#include -#include +#include +#include +#include #include -#include #include -#include -#include -#include - -// fmt -#include +#include +#include +#include diff --git a/common/perl_eqdb.cpp b/common/perl_eqdb.cpp index 1aea51c0df..53f3059df7 100644 --- a/common/perl_eqdb.cpp +++ b/common/perl_eqdb.cpp @@ -28,9 +28,9 @@ typedef const char Const_char; #ifdef EMBPERL -#include "global_define.h" -#include "eqdb.h" -#include "useperl.h" +#include "common/global_define.h" +#include "common/eqdb.h" +#include "common/useperl.h" #ifdef THIS /* this macro seems to leak out on some systems */ #undef THIS diff --git a/common/perl_eqdb_res.cpp b/common/perl_eqdb_res.cpp index 185c4456b9..32a588ece2 100644 --- a/common/perl_eqdb_res.cpp +++ b/common/perl_eqdb_res.cpp @@ -28,9 +28,9 @@ typedef const char Const_char; #ifdef EMBPERL -#include "global_define.h" -#include "eqdb_res.h" -#include "useperl.h" +#include "common/global_define.h" +#include "common/eqdb_res.h" +#include "common/useperl.h" XS(XS_EQDBRes_num_rows); /* prototype to pass -Wmissing-prototypes */ diff --git a/common/platform.h b/common/platform.h index 81bd55a291..626eb4b176 100644 --- a/common/platform.h +++ b/common/platform.h @@ -18,10 +18,9 @@ * */ -#ifndef EQEMU_PLATFORM_H -#define EQEMU_PLATFORM_H +#pragma once -#include "iostream" +#include enum EQEmuExePlatform { @@ -47,5 +46,3 @@ int GetExecutablePlatformInt(); std::string GetPlatformName(); bool IsWorld(); bool IsQueryServ(); - -#endif diff --git a/common/proc_launcher.cpp b/common/proc_launcher.cpp index 9f87573266..0be460a8e8 100644 --- a/common/proc_launcher.cpp +++ b/common/proc_launcher.cpp @@ -16,25 +16,26 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "proc_launcher.h" + +#include "common/global_define.h" +#include "common/types.h" + #include #include - -#include "global_define.h" -#include "types.h" -#include "proc_launcher.h" #ifdef _WINDOWS - #include +#include #else - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #endif ProcLauncher ProcLauncher::s_launcher; @@ -353,4 +354,3 @@ ProcLauncher::Spec &ProcLauncher::Spec::operator=(const Spec &other) { logFile = other.logFile; return(*this); } - diff --git a/common/proc_launcher.h b/common/proc_launcher.h index 23b7e523cf..15ff0dd732 100644 --- a/common/proc_launcher.h +++ b/common/proc_launcher.h @@ -15,14 +15,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PROCLAUNCHER_H_ -#define PROCLAUNCHER_H_ -#include "global_define.h" +#pragma once +#include "common/global_define.h" + +#include #include #include -#include #ifdef __FreeBSD__ #include @@ -92,6 +92,3 @@ class ProcLauncher { static void HandleSigChild(int signum); #endif }; - -#endif /*PROCLAUNCHER_H_*/ - diff --git a/common/process.cpp b/common/process.cpp index 3563d57e25..152fc2d181 100644 --- a/common/process.cpp +++ b/common/process.cpp @@ -1,8 +1,9 @@ -#include -#include -#include #include "process.h" +#include +#include +#include + inline std::string random_string(size_t length) { auto randchar = []() -> char { diff --git a/common/process.h b/common/process.h index 15affd5ef0..c9f62b4e93 100644 --- a/common/process.h +++ b/common/process.h @@ -1,10 +1,6 @@ -#ifndef EQEMU_PROCESS_H -#define EQEMU_PROCESS_H +#pragma once class Process { public: static std::string execute(const std::string &cmd, bool return_result = true); }; - - -#endif //EQEMU_PROCESS_H diff --git a/common/process/process.cpp b/common/process/process.cpp index 92bf757f48..ddd620cbe3 100644 --- a/common/process/process.cpp +++ b/common/process/process.cpp @@ -1,8 +1,8 @@ +#include "process.h" + +#include "fmt/format.h" #include #include -#include "process.h" -#include -#include std::string Process::execute(const std::string &cmd) { diff --git a/common/process/process.h b/common/process/process.h index 34dbb27c6b..a357674adb 100644 --- a/common/process/process.h +++ b/common/process/process.h @@ -1,7 +1,6 @@ -#ifndef EQEMU_PROCESS_H -#define EQEMU_PROCESS_H +#pragma once -#include "../strings.h" +#include "common/strings.h" #include @@ -14,6 +13,3 @@ class Process { public: static std::string execute(const std::string &cmd); }; - - -#endif //EQEMU_PROCESS_H diff --git a/common/profanity_manager.cpp b/common/profanity_manager.cpp index e522681f6c..b254459969 100644 --- a/common/profanity_manager.cpp +++ b/common/profanity_manager.cpp @@ -18,13 +18,14 @@ */ #include "profanity_manager.h" -#include "eqemu_logsys.h" -#include "dbcore.h" -#include "strings.h" -#include -#include +#include "common/dbcore.h" +#include "common/eqemu_logsys.h" +#include "common/strings.h" + #include +#include +#include static std::list profanity_list; diff --git a/common/profanity_manager.h b/common/profanity_manager.h index 165b6516e0..c2f2ed91e6 100644 --- a/common/profanity_manager.h +++ b/common/profanity_manager.h @@ -17,13 +17,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_PROFANITY_MANAGER_H -#define COMMON_PROFANITY_MANAGER_H +#pragma once -#include +#include "fmt/format.h" #include -#include -#include +#include class DBcore; @@ -58,5 +56,3 @@ namespace EQ }; } /*EQEmu*/ - -#endif /*COMMON_PROFANITY_MANAGER_H*/ diff --git a/common/profiler.h b/common/profiler.h index a66e3ac88a..c0b1e5eb43 100644 --- a/common/profiler.h +++ b/common/profiler.h @@ -15,13 +15,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PROFILER_H -#define PROFILER_H + +#pragma once #ifdef EQPROFILE -#include "../common/rdtsc.h" -#include "../common/types.h" +#include "common/rdtsc.h" +#include "common/types.h" class ScopedProfiler; @@ -88,5 +88,3 @@ class ScopedProfiler { #define _GP(obj, pkg, name) ; #endif - -#endif diff --git a/common/ptimer.cpp b/common/ptimer.cpp index d5f6ca1622..dfba5f6f97 100644 --- a/common/ptimer.cpp +++ b/common/ptimer.cpp @@ -16,23 +16,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "global_define.h" - -#include "timer.h" #include "ptimer.h" -#include "database.h" -#include "strings.h" + +#include "common/database.h" +#include "common/global_define.h" +#include "common/strings.h" +#include "common/timer.h" #ifdef _WINDOWS - #include - #include - int gettimeofday (timeval *tp, ...); +#include +#include +int gettimeofday (timeval *tp, ...); #else - #include +#include #endif #if EQDEBUG > 10 - #define DEBUG_PTIMERS +#define DEBUG_PTIMERS #endif diff --git a/common/ptimer.h b/common/ptimer.h index ad5e5a8c8c..fa116f84d1 100644 --- a/common/ptimer.h +++ b/common/ptimer.h @@ -15,10 +15,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PTIMER_H -#define PTIMER_H -#include "types.h" +#pragma once + +#include "common/types.h" + #include #include @@ -144,5 +145,3 @@ class PTimerList { std::map _list; }; - -#endif diff --git a/common/queue.h b/common/queue.h index 00dd48cace..b7e6515df3 100644 --- a/common/queue.h +++ b/common/queue.h @@ -15,8 +15,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef QUEUE_H -#define QUEUE_H + +#pragma once template class MyQueue; @@ -122,5 +122,3 @@ class MyQueue MyQueueNode* head; MyQueueNode* tail; }; - -#endif diff --git a/common/races.cpp b/common/races.cpp index a01597640e..603c775f81 100644 --- a/common/races.cpp +++ b/common/races.cpp @@ -16,8 +16,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/races.h" -#include "data_verification.h" +#include "races.h" + +#include "common/data_verification.h" const char* GetRaceIDName(uint16 race_id) { diff --git a/common/races.h b/common/races.h index 3d9d9f8d34..86a296ca85 100644 --- a/common/races.h +++ b/common/races.h @@ -16,9 +16,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef RACES_H -#define RACES_H -#include "../common/types.h" +#pragma once + +#include "common/types.h" + #include const char* GetRaceIDName(uint16 race_id); @@ -863,6 +864,3 @@ namespace RaceAppearance { constexpr int DrakkinMale = (Race::Drakkin << 8) | Gender::Male; constexpr int DrakkinFemale = (Race::Drakkin << 8) | Gender::Female; } - -#endif - diff --git a/common/raid.h b/common/raid.h index 605636fd4b..e2dbe9c2c7 100644 --- a/common/raid.h +++ b/common/raid.h @@ -16,8 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef RAID_H -#define RAID_H +#pragma once enum { //raid packet types: raidAdd = 0, @@ -67,6 +66,3 @@ enum { //raid command types RaidCommandSetMotd = 35, RaidCommandSetNote = 36, }; - - -#endif diff --git a/common/random.h b/common/random.h index 73b14369ea..a55dece0f4 100644 --- a/common/random.h +++ b/common/random.h @@ -16,8 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __random_h__ -#define __random_h__ +#pragma once #include #include @@ -36,7 +35,7 @@ #endif #ifdef USE_ADDITIVE_LFIB_PRNG -#include "additive_lagged_fibonacci_engine.h" +#include "common/additive_lagged_fibonacci_engine.h" #elif defined(USE_SFMT19937) #include #endif @@ -143,6 +142,3 @@ namespace EQ { m_gen; }; } - -#endif /* !__random_h__ */ - diff --git a/common/rdtsc.cpp b/common/rdtsc.cpp index 53962f1d59..fc3bdfd3d9 100644 --- a/common/rdtsc.cpp +++ b/common/rdtsc.cpp @@ -17,14 +17,15 @@ */ #include "rdtsc.h" -#include "types.h" + +#include "common/types.h" #ifdef _WINDOWS - #include - #include "../common/timer.h" +#include +#include "common/timer.h" #else - #include - #include +#include +#include #endif #ifdef i386 diff --git a/common/rdtsc.h b/common/rdtsc.h index 2a36cac0f1..44861f18d1 100644 --- a/common/rdtsc.h +++ b/common/rdtsc.h @@ -15,9 +15,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef RDTSC_H -#define RDTSC_H +#pragma once + +#include "common/types.h" #define CALIBRATE_LOOPS 3 #define SLEEP_TIME 10 //in ms @@ -33,8 +34,6 @@ All calculations are carried out in 64 bit integers. */ -#include "types.h" - class RDTSC_Timer { public: RDTSC_Timer(); @@ -82,5 +81,3 @@ class RDTSC_Collector : public RDTSC_Timer { int64 _sum; int64 _count; }; - -#endif diff --git a/common/rulesys.cpp b/common/rulesys.cpp index 3e6f833a8f..27c5724f44 100644 --- a/common/rulesys.cpp +++ b/common/rulesys.cpp @@ -17,16 +17,16 @@ */ #include "rulesys.h" -#include "eqemu_logsys.h" -#include "database.h" -#include "strings.h" + +#include "common/database.h" +#include "common/eqemu_logsys.h" +#include "common/repositories/rule_sets_repository.h" +#include "common/repositories/rule_values_repository.h" +#include "common/strings.h" + +#include "fmt/format.h" #include #include -#include -#include - -#include "../common/repositories/rule_sets_repository.h" -#include "../common/repositories/rule_values_repository.h" const char *RuleManager::s_categoryNames[_CatCount + 1] = { #define RULE_CATEGORY(category_name) \ diff --git a/common/rulesys.h b/common/rulesys.h index eab3af6b8e..f6e7801363 100644 --- a/common/rulesys.h +++ b/common/rulesys.h @@ -15,8 +15,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef RULESYS_H_ -#define RULESYS_H_ + +#pragma once + +#include "common/types.h" + +#include +#include +#include /* * Access to the rules system in normal code is done with three calls: @@ -40,12 +46,6 @@ RuleManager::Instance()->GetStringRule( RuleManager::String__##rule_name ) -#include -#include -#include - -#include "types.h" - class Database; class RuleManager { @@ -193,5 +193,3 @@ class RuleManager { } RuleInfo; static const RuleInfo s_RuleInfo[]; }; - -#endif /*RULESYS_H_*/ diff --git a/common/say_link.cpp b/common/say_link.cpp index 8edc536f94..ff67185887 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -18,12 +18,13 @@ */ #include "say_link.h" -#include "emu_constants.h" -#include "strings.h" -#include "item_instance.h" -#include "item_data.h" -#include "../zone/zonedb.h" +#include "common/emu_constants.h" +#include "common/strings.h" +#include "common/item_instance.h" +#include "common/item_data.h" +#include "zone/zonedb.h" + #include // static bucket global diff --git a/common/say_link.h b/common/say_link.h index 4f37e6c820..ee1e6566d6 100644 --- a/common/say_link.h +++ b/common/say_link.h @@ -17,14 +17,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_SAY_LINK_H -#define COMMON_SAY_LINK_H +#pragma once -#include "types.h" +#include "common/loot.h" +#include "common/repositories/saylink_repository.h" +#include "common/types.h" #include -#include "repositories/saylink_repository.h" -#include "loot.h" struct LootItem; @@ -133,5 +132,3 @@ class Saylink { static std::string Create(const std::string &saylink_text, bool silent = false, const std::string &link_name = ""); static std::string Silent(const std::string &saylink_text, const std::string &link_name = ""); }; - -#endif /*COMMON_SAY_LINK_H*/ diff --git a/common/seperator.h b/common/seperator.h index 11ddfef265..f4d6ac3807 100644 --- a/common/seperator.h +++ b/common/seperator.h @@ -20,10 +20,11 @@ // Seperator.argplus[i] is a pointer to the original string so it doesnt end at the div // Written by Quagmire -#ifndef SEPERATOR_H -#define SEPERATOR_H -#include "types.h" +#pragma once + +#include "common/types.h" + #include #include @@ -154,5 +155,3 @@ class Seperator private: uint16 maxargnum; }; - -#endif diff --git a/common/serialize_buffer.h b/common/serialize_buffer.h index 65ae36f701..c05456f05d 100644 --- a/common/serialize_buffer.h +++ b/common/serialize_buffer.h @@ -1,10 +1,10 @@ -#ifndef SERIALIZE_BUFFER_H -#define SERIALIZE_BUFFER_H -#include +#pragma once + #include #include #include +#include class SerializeBuffer { @@ -195,5 +195,3 @@ class SerializeBuffer size_t m_capacity; size_t m_pos; }; - -#endif /* !SERIALIZE_BUFFER_H */ diff --git a/common/server_event_scheduler.cpp b/common/server_event_scheduler.cpp index 039da168f9..5e964f38b3 100644 --- a/common/server_event_scheduler.cpp +++ b/common/server_event_scheduler.cpp @@ -1,7 +1,9 @@ -#include "../common/database.h" -#include "../common/strings.h" #include "server_event_scheduler.h" -#include "../common/cron/croncpp.h" + +#include "common/cron/croncpp.h" +#include "common/database.h" +#include "common/strings.h" + #include #include #include diff --git a/common/server_event_scheduler.h b/common/server_event_scheduler.h index a198e73fa6..a3c48e9fd5 100644 --- a/common/server_event_scheduler.h +++ b/common/server_event_scheduler.h @@ -1,7 +1,7 @@ -#ifndef EQEMU_SERVER_EVENT_SCHEDULER_H -#define EQEMU_SERVER_EVENT_SCHEDULER_H +#pragma once + +#include "common/repositories/server_scheduled_events_repository.h" -#include "../common/repositories/server_scheduled_events_repository.h" #include #include @@ -53,5 +53,3 @@ class ServerEventScheduler { Database *m_database; bool ValidateDatabaseConnection(); }; - -#endif //EQEMU_SERVER_EVENT_SCHEDULER_H diff --git a/common/server_reload_types.h b/common/server_reload_types.h index af42bec368..2446c10f6b 100644 --- a/common/server_reload_types.h +++ b/common/server_reload_types.h @@ -1,9 +1,10 @@ -#ifndef EQEMU_SERVER_RELOAD_TYPES_H -#define EQEMU_SERVER_RELOAD_TYPES_H +#pragma once +#include "common/types.h" + +#include #include #include -#include namespace ServerReload { enum Type { @@ -141,5 +142,3 @@ namespace ServerReload { uint32_t zone_server_id = 0; }; } - -#endif //EQEMU_SERVER_RELOAD_TYPES_H diff --git a/common/serverinfo.cpp b/common/serverinfo.cpp index db31e95611..b80a95aa1a 100644 --- a/common/serverinfo.cpp +++ b/common/serverinfo.cpp @@ -17,7 +17,8 @@ */ #include "serverinfo.h" -#include + +#include "uv.h" size_t EQ::GetRSS() { diff --git a/common/serverinfo.h b/common/serverinfo.h index d62549f11a..e3301dfa5e 100644 --- a/common/serverinfo.h +++ b/common/serverinfo.h @@ -17,9 +17,9 @@ */ #pragma once +#include #include #include -#include typedef struct eq_cpu_info_s { std::string model; diff --git a/common/servertalk.h b/common/servertalk.h index 9985c875c5..121d6d7de5 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -1,17 +1,17 @@ -#ifndef EQ_SOPCODES_H -#define EQ_SOPCODES_H - -#include "../common/types.h" -#include "../common/packet_functions.h" -#include "../common/eq_packet_structs.h" -#include "../common/net/packet.h" -#include "../common/guilds.h" -#include -#include -#include -#include -#include -#include +#pragma once + +#include "common/eq_packet_structs.h" +#include "common/guilds.h" +#include "common/net/packet.h" +#include "common/packet_functions.h" +#include "common/types.h" + +#include "cereal/cereal.hpp" +#include "cereal/archives/binary.hpp" +#include "cereal/types/chrono.hpp" +#include "cereal/types/string.hpp" +#include "cereal/types/vector.hpp" +#include "glm/vec4.hpp" #define SERVER_TIMEOUT 45000 // how often keepalive gets sent #define INTERSERVER_TIMER 10000 @@ -1779,7 +1779,4 @@ struct BazaarPurchaseMessaging_Struct { uint32 id; }; - -#pragma pack() - -#endif +#pragma pack(pop) diff --git a/common/shared_tasks.cpp b/common/shared_tasks.cpp index 62b24350cb..deb76340b0 100644 --- a/common/shared_tasks.cpp +++ b/common/shared_tasks.cpp @@ -1,5 +1,7 @@ #include "shared_tasks.h" -#include "repositories/character_data_repository.h" + +#include "common/repositories/character_data_repository.h" + #include std::vector SharedTask::GetActivityState() const diff --git a/common/shared_tasks.h b/common/shared_tasks.h index b12053a4c0..7b2255834b 100644 --- a/common/shared_tasks.h +++ b/common/shared_tasks.h @@ -1,17 +1,16 @@ -#ifndef EQEMU_SHARED_TASKS_H -#define EQEMU_SHARED_TASKS_H - -#include "database.h" -#include "timer.h" -#include "tasks.h" -#include "types.h" -#include "repositories/character_data_repository.h" -#include "repositories/tasks_repository.h" -#include "repositories/task_activities_repository.h" -#include "repositories/shared_tasks_repository.h" -#include +#pragma once + +#include "common/database.h" +#include "common/repositories/character_data_repository.h" +#include "common/repositories/shared_tasks_repository.h" +#include "common/repositories/task_activities_repository.h" +#include "common/repositories/tasks_repository.h" +#include "common/tasks.h" +#include "common/timer.h" +#include "common/types.h" + #include -#include +#include // ops #define ServerOP_SharedTaskRequest 0x0300 // zone -> world. Player trying to get task. Relayed world -> zone on confirmation @@ -232,5 +231,3 @@ class SharedTask { TasksRepository::Tasks m_task_data; std::vector m_task_activity_data; }; - -#endif //EQEMU_SHARED_TASKS_H diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 89da73410f..a38bc8e303 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -16,46 +16,35 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER >= 1800 - #include -#endif - -#include "classes.h" -#include "eq_packet_structs.h" -#include "faction.h" -#include "features.h" -#include "ipc_mutex.h" -#include "inventory_profile.h" -#include "memory_mapped_file.h" -#include "mysql.h" -#include "rulesys.h" #include "shareddb.h" -#include "strings.h" -#include "eqemu_config.h" -#include "data_verification.h" -#include "evolving_items.h" -#include "repositories/criteria/content_filter_criteria.h" -#include "repositories/account_repository.h" -#include "repositories/faction_association_repository.h" -#include "repositories/starting_items_repository.h" -#include "path_manager.h" -#include "../zone/client.h" -#include "repositories/loottable_repository.h" -#include "repositories/character_item_recast_repository.h" -#include "repositories/character_corpses_repository.h" -#include "repositories/skill_caps_repository.h" -#include "repositories/inventory_repository.h" -#include "repositories/books_repository.h" -#include "repositories/sharedbank_repository.h" -#include "repositories/character_inspect_messages_repository.h" -#include "repositories/spells_new_repository.h" -#include "repositories/damageshieldtypes_repository.h" -#include "repositories/items_repository.h" + +#include "common/classes.h" +#include "common/data_verification.h" +#include "common/eq_packet_structs.h" +#include "common/eqemu_config.h" +#include "common/evolving_items.h" +#include "common/faction.h" +#include "common/inventory_profile.h" +#include "common/ipc_mutex.h" +#include "common/memory_mapped_file.h" +#include "common/path_manager.h" +#include "common/repositories/account_repository.h" +#include "common/repositories/books_repository.h" +#include "common/repositories/character_corpses_repository.h" +#include "common/repositories/character_inspect_messages_repository.h" +#include "common/repositories/character_item_recast_repository.h" +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/damageshieldtypes_repository.h" +#include "common/repositories/inventory_repository.h" +#include "common/repositories/items_repository.h" +#include "common/repositories/sharedbank_repository.h" +#include "common/repositories/starting_items_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "zone/client.h" + +#include "fmt/format.h" +#include SharedDatabase::SharedDatabase() : Database() diff --git a/common/shareddb.h b/common/shareddb.h index 2a78be670d..559570fc97 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -18,18 +18,17 @@ * */ -#ifndef SHAREDDB_H_ -#define SHAREDDB_H_ - -#include "database.h" -#include "skills.h" -#include "spdat.h" -#include "fixed_memory_hash_set.h" -#include "fixed_memory_variable_hash_set.h" -#include "say_link.h" -#include "repositories/command_subsettings_repository.h" -#include "repositories/items_evolving_details_repository.h" -#include "../common/repositories/character_evolving_items_repository.h" +#pragma once + +#include "common/database.h" +#include "common/fixed_memory_hash_set.h" +#include "common/fixed_memory_variable_hash_set.h" +#include "common/repositories/character_evolving_items_repository.h" +#include "common/repositories/command_subsettings_repository.h" +#include "common/repositories/items_evolving_details_repository.h" +#include "common/say_link.h" +#include "common/skills.h" +#include "common/spdat.h" #include #include @@ -203,5 +202,3 @@ class SharedDatabase : public Database { uint32 m_shared_items_count = 0; uint32 m_shared_spells_count = 0; }; - -#endif /*SHAREDDB_H_*/ diff --git a/common/skill_caps.cpp b/common/skill_caps.cpp index c8b75c4f51..b7436a3a6a 100644 --- a/common/skill_caps.cpp +++ b/common/skill_caps.cpp @@ -1,5 +1,6 @@ #include "skill_caps.h" -#include "timer.h" + +#include "common/timer.h" // cache the skill cap max level in the database std::map skill_max_level = {}; diff --git a/common/skill_caps.h b/common/skill_caps.h index 6566a11046..a83d183e14 100644 --- a/common/skill_caps.h +++ b/common/skill_caps.h @@ -1,10 +1,9 @@ -#ifndef CODE_SKILL_CAPS_H -#define CODE_SKILL_CAPS_H +#pragma once -#include "repositories/skill_caps_repository.h" -#include "types.h" -#include "classes.h" -#include "skills.h" +#include "common/classes.h" +#include "common/repositories/skill_caps_repository.h" +#include "common/skills.h" +#include "common/types.h" class SkillCaps { public: @@ -26,6 +25,3 @@ class SkillCaps { Database *m_content_database{}; std::map m_skill_caps = {}; }; - - -#endif //CODE_SKILL_CAPS_H diff --git a/common/skills.cpp b/common/skills.cpp index 80562184d5..85fae5a27a 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -18,7 +18,8 @@ */ #include "skills.h" -#include "classes.h" + +#include "common/classes.h" #include diff --git a/common/skills.h b/common/skills.h index e9b280d535..2f61c23146 100644 --- a/common/skills.h +++ b/common/skills.h @@ -17,13 +17,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_SKILLS_H -#define COMMON_SKILLS_H +#pragma once -#include "types.h" +#include "common/types.h" -#include #include +#include #include namespace EQ @@ -309,5 +308,3 @@ namespace EQ }; } /*EQEmu*/ - -#endif /*COMMON_SKILLS_H*/ diff --git a/common/spdat.cpp b/common/spdat.cpp index f4d3df2558..6c5eaf62e7 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -16,6 +16,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "spdat.h" + +#include "common/classes.h" +#include "common/eqemu_logsys.h" +#include "common/rulesys.h" +#include "common/strings.h" + +#ifndef WIN32 +#include "common/unix.h" +#endif +#include /* @@ -71,19 +82,6 @@ */ - -#include "../common/eqemu_logsys.h" - -#include "classes.h" -#include "spdat.h" -#include "../common/rulesys.h" -#include "../common/strings.h" - -#ifndef WIN32 -#include -#include "unix.h" -#endif - /////////////////////////////////////////////////////////////////////////////// // spell property testing functions diff --git a/common/spdat.h b/common/spdat.h index 11130d6a4e..ca35734013 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -15,12 +15,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef SPDAT_H -#define SPDAT_H -#include "classes.h" -#include "skills.h" -#include "item_data.h" +#pragma once + +#include "common/classes.h" +#include "common/item_data.h" +#include "common/skills.h" #define SPELL_UNKNOWN 0xFFFF #define POISON_PROC 0xFFFE @@ -1917,5 +1917,3 @@ bool IsDamageShieldOnlySpell(uint16 spell_id); bool IsDamageShieldAndResistSpell(uint16 spell_id); bool IsHateSpell(uint16 spell_id); bool IsDisciplineTome(const EQ::ItemData* item); - -#endif diff --git a/common/spdat_bot.cpp b/common/spdat_bot.cpp index 3a9ecf71eb..23b7f50401 100644 --- a/common/spdat_bot.cpp +++ b/common/spdat_bot.cpp @@ -1,5 +1,6 @@ #include "spdat.h" -#include "../zone/bot.h" + +#include "zone/bot.h" bool IsBotSpellTypeDetrimental(uint16 spell_type) { switch (spell_type) { diff --git a/common/strings.cpp b/common/strings.cpp index 62aec29759..024d8e4417 100644 --- a/common/strings.cpp +++ b/common/strings.cpp @@ -34,25 +34,19 @@ */ #include "strings.h" -#include -#include -#include + +#include "cereal/external/rapidjson/document.h" +#include "fmt/format.h" #include #include - -#include -#include +#include +#include +#include #include -#include - #include +#include #include -#ifdef _WINDOWS -#include -#include -#endif - std::string Strings::Random(size_t length) { static auto &chrs = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; diff --git a/common/strings.h b/common/strings.h index 8ae8fee25a..e00c11ab0a 100644 --- a/common/strings.h +++ b/common/strings.h @@ -32,22 +32,19 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _STRINGUTIL_H_ -#define _STRINGUTIL_H_ +#pragma once + +#include "common/types.h" + +#include #include +#include #include #include #include -#include -#include #include - -#ifdef _WIN32 -#include -#endif - -#include "types.h" +#include class Strings { public: @@ -133,5 +130,3 @@ void RemoveApostrophes(std::string &s); std::string FormatName(const std::string &char_name); bool IsAllowedWorldServerCharacterList(char c); void SanitizeWorldServerName(char *name); - -#endif diff --git a/common/strings_legacy.cpp b/common/strings_legacy.cpp index e1d324d455..a98d69c08c 100644 --- a/common/strings_legacy.cpp +++ b/common/strings_legacy.cpp @@ -1,23 +1,18 @@ -#include -#include "strings.h" -#include +#include "common/strings.h" + +#include "fmt/format.h" #include #include #include - +#include +#include +#include +#include #ifdef _WINDOWS #include - -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp - -#else - -#include -#include -#include - +#define snprintf _snprintf +#define strncasecmp _strnicmp +#define strcasecmp _stricmp #endif #ifndef va_copy diff --git a/common/strings_misc.cpp b/common/strings_misc.cpp index 08355e15ee..bd21ecc5b6 100644 --- a/common/strings_misc.cpp +++ b/common/strings_misc.cpp @@ -1,22 +1,17 @@ -#include #include "strings.h" -#include + +#include "fmt/format.h" #include #include - +#include +#include +#include +#include #ifdef _WINDOWS #include - -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp - -#else - -#include -#include -#include - +#define snprintf _snprintf +#define strncasecmp _strnicmp +#define strcasecmp _stricmp #endif #ifndef va_copy diff --git a/common/struct_strategy.cpp b/common/struct_strategy.cpp index ca633143ab..12372a6e29 100644 --- a/common/struct_strategy.cpp +++ b/common/struct_strategy.cpp @@ -1,10 +1,10 @@ - -#include "global_define.h" -#include "eqemu_logsys.h" #include "struct_strategy.h" -#include "eq_stream_intf.h" -#include "opcodemgr.h" +#include "common/eq_stream_intf.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/opcodemgr.h" + #include #include @@ -72,28 +72,3 @@ namespace StructStrategyFactory { } }; - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/common/struct_strategy.h b/common/struct_strategy.h index d3f7327ab3..73df1d178b 100644 --- a/common/struct_strategy.h +++ b/common/struct_strategy.h @@ -1,13 +1,14 @@ -#ifndef STRUCTSTRATEGY_H_ -#define STRUCTSTRATEGY_H_ +#pragma once -class EQApplicationPacket; -class EQStreamInterface; -#include "emu_opcodes.h" -#include "emu_versions.h" +#include "common/emu_opcodes.h" +#include "common/emu_versions.h" -#include #include +#include + + +class EQApplicationPacket; +class EQStreamInterface; class StructStrategy { public: @@ -44,30 +45,3 @@ class StructStrategy { namespace StructStrategyFactory { void RegisterPatch(EmuOpcode first_opcode, const StructStrategy *structs); }; - - -#endif /*STRUCTSTRATEGY_H_*/ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/common/tasks.h b/common/tasks.h index 8cf98335b7..ad8887ecc0 100644 --- a/common/tasks.h +++ b/common/tasks.h @@ -1,8 +1,10 @@ -#ifndef EQEMU_TASKS_H -#define EQEMU_TASKS_H +#pragma once + +#include "common/emu_versions.h" +#include "common/eqemu_logsys.h" +#include "common/serialize_buffer.h" +#include "common/strings.h" -#include "../common/strings.h" -#include "serialize_buffer.h" #include #include @@ -564,5 +566,3 @@ namespace TaskStr { return "Unknown EQStr"; } } - -#endif //EQEMU_TASKS_H diff --git a/common/textures.h b/common/textures.h index 919a5fed47..2f45f5eecf 100644 --- a/common/textures.h +++ b/common/textures.h @@ -17,11 +17,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_TEXTURES_H -#define COMMON_TEXTURES_H - -#include "types.h" +#pragma once +#include "common/types.h" namespace EQ { @@ -160,5 +158,3 @@ namespace EQ }; } /*EQEmu*/ - -#endif /*COMMON_TEXTURES_H*/ diff --git a/common/timeoutmgr.cpp b/common/timeoutmgr.cpp index f8ee628696..ab0746d168 100644 --- a/common/timeoutmgr.cpp +++ b/common/timeoutmgr.cpp @@ -15,12 +15,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" - -//#define TIMEOUT_DEBUG #include "timeoutmgr.h" +#include "common/global_define.h" + +//#define TIMEOUT_DEBUG + Timeoutable::Timeoutable(uint32 check_frequency) : next_check(check_frequency) { diff --git a/common/timeoutmgr.h b/common/timeoutmgr.h index 4e5224a30f..e8a466d8d6 100644 --- a/common/timeoutmgr.h +++ b/common/timeoutmgr.h @@ -15,19 +15,19 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TIMEOUT_MANAGER_H -#define TIMEOUT_MANAGER_H + +#pragma once + +#include "common/timer.h" +#include "common/types.h" + +#include //ms between checking all timeouts //timeouts are generally somewhat large, so its safe to use a //value on the order of seconds here. #define TIMEOUT_GRANULARITY 1000 -#include "types.h" -#include "timer.h" - -#include - //timeoutable objects automatically register themselves //with the global TimeoutManager object class TimeoutManager; @@ -62,5 +62,3 @@ class TimeoutManager { }; extern TimeoutManager timeout_manager; - -#endif diff --git a/common/timer.cpp b/common/timer.cpp index 1910746184..32911f9d99 100644 --- a/common/timer.cpp +++ b/common/timer.cpp @@ -16,6 +16,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "timer.h" + // Disgrace: for windows compile #ifndef WIN32 #include @@ -23,8 +25,6 @@ #include #endif -#include "timer.h" - uint32 current_time = 0; uint32 last_time = 0; diff --git a/common/timer.h b/common/timer.h index cd550c9dfc..9a2e2765a7 100644 --- a/common/timer.h +++ b/common/timer.h @@ -15,11 +15,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TIMER_H -#define TIMER_H -#include "types.h" -#include +#pragma once + +#include "common/types.h" // Disgrace: for windows compile #ifdef _WINDOWS @@ -27,6 +26,8 @@ int gettimeofday (timeval *tp, ...); #endif +#include + class Timer { public: @@ -93,5 +94,3 @@ struct BenchTimer private: std::chrono::time_point start_time; }; - -#endif diff --git a/common/types.h b/common/types.h index 8124d9f3de..bb4b39a839 100644 --- a/common/types.h +++ b/common/types.h @@ -15,10 +15,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TYPES_H -#define TYPES_H -#include +#pragma once + +#include typedef uint8_t byte; typedef uint8_t uint8; typedef uint16_t uint16; @@ -97,5 +97,3 @@ typedef const char Const_char; //for perl XS # define htonll(x) htobe64(x) # define ntohll(x) be64toh(x) #endif - -#endif diff --git a/common/unix.cpp b/common/unix.cpp index 0e69a3b699..45702280cb 100644 --- a/common/unix.cpp +++ b/common/unix.cpp @@ -18,6 +18,7 @@ #ifndef _WINDOWS #include "unix.h" + #include #include @@ -42,7 +43,5 @@ char* strlwr(char* tmp) { return tmp; } -#else - int joe = 1; #endif /* !WIN32 */ diff --git a/common/unix.h b/common/unix.h index d4155f9464..e593e3776b 100644 --- a/common/unix.h +++ b/common/unix.h @@ -16,6 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _WINDOWS + #ifndef __UNIX_H__ #define __UNIX_H__ #include @@ -28,5 +29,5 @@ char* strupr(char* tmp); char* strlwr(char* tmp); #endif #endif -#endif +#endif diff --git a/common/useperl.h b/common/useperl.h index fb638be571..5816944e6f 100644 --- a/common/useperl.h +++ b/common/useperl.h @@ -1,6 +1,4 @@ -#ifndef EMU_PERL_H_ -#define EMU_PERL_H_ - +#pragma once //headers from the Perl distribution #include @@ -64,6 +62,3 @@ extern "C" { //the perl headers dont do this for us... #undef do_close #endif #endif - -#endif /*EMU_PERL_H_*/ - diff --git a/common/util/directory.cpp b/common/util/directory.cpp index 9bc075bbe4..f8ed6b1494 100644 --- a/common/util/directory.cpp +++ b/common/util/directory.cpp @@ -1,7 +1,7 @@ #include "directory.h" #ifdef _WIN32 -#include "win_dirent.h" +#include "common/util/win_dirent.h" #else #include #endif diff --git a/common/util/memory_stream.h b/common/util/memory_stream.h index f6792458cf..9fc99d6012 100644 --- a/common/util/memory_stream.h +++ b/common/util/memory_stream.h @@ -1,8 +1,8 @@ #pragma once -#include #include #include +#include namespace EQ { diff --git a/common/util/uuid.cpp b/common/util/uuid.cpp index 1e221b5b9c..0a6375ddbb 100644 --- a/common/util/uuid.cpp +++ b/common/util/uuid.cpp @@ -1,8 +1,8 @@ #include "uuid.h" +#include "fmt/format.h" + #include -#include -#include #ifdef _WIN32 #include diff --git a/common/util/uuid.h b/common/util/uuid.h index d1e49a0e79..7a7c96d42e 100644 --- a/common/util/uuid.h +++ b/common/util/uuid.h @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include namespace EQ { diff --git a/common/version.h b/common/version.h index c119346d45..34958bcef7 100644 --- a/common/version.h +++ b/common/version.h @@ -18,8 +18,7 @@ * */ -#ifndef EQEMU_VERSION_H -#define EQEMU_VERSION_H +#pragma once #define EQEMU_PROTOCOL_VERSION "0.3.10" @@ -45,6 +44,3 @@ #define CURRENT_BINARY_DATABASE_VERSION 9328 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054 #define CUSTOM_BINARY_DATABASE_VERSION 0 - -#endif - diff --git a/common/zone_store.cpp b/common/zone_store.cpp index fa64bd4924..1b3d1164e9 100644 --- a/common/zone_store.cpp +++ b/common/zone_store.cpp @@ -17,6 +17,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ + +#include "zone_store.h" + +#include "common/content/world_content_service.h" +#include "common/stacktrace/backward.hpp" + #define DEFAULT_MINIMUM_CLIP 50.0f #define DEFAULT_MAXIMUM_CLIP 175.0f @@ -41,10 +47,6 @@ #define SNOW_SLOT_THREE 3 #define SNOW_SLOT_FOUR 4 -#include "zone_store.h" -#include "../common/content/world_content_service.h" -#include "stacktrace/backward.hpp" - ZoneStore::ZoneStore() = default; ZoneStore::~ZoneStore() = default; diff --git a/common/zone_store.h b/common/zone_store.h index 4a6940f4d7..48bded65cf 100644 --- a/common/zone_store.h +++ b/common/zone_store.h @@ -18,13 +18,12 @@ * */ -#ifndef EQEMU_ZONE_STORE_H -#define EQEMU_ZONE_STORE_H +#pragma once -#include "../common/repositories/zone_repository.h" -#include "../common/repositories/base/base_content_flags_repository.h" +#include "common/repositories/base/base_content_flags_repository.h" +#include "common/repositories/zone_repository.h" -#include +#include "glm/vec4.hpp" class ZoneStore { public: @@ -149,5 +148,3 @@ inline ZoneRepository::Zone *GetZoneVersionWithFallback(uint32 zone_id, int vers version ); }; - -#endif //EQEMU_ZONE_STORE_H From d306e139e8de3e47371ceda9201369f072e808d8 Mon Sep 17 00:00:00 2001 From: brainiac Date: Wed, 17 Dec 2025 09:33:09 -0800 Subject: [PATCH 064/194] normalize includes: common/repositories --- common/repositories/aa_ability_repository.h | 12 ++++----- .../repositories/aa_rank_effects_repository.h | 12 ++++----- .../repositories/aa_rank_prereqs_repository.h | 12 ++++----- common/repositories/aa_ranks_repository.h | 12 ++++----- .../repositories/account_flags_repository.h | 12 ++++----- common/repositories/account_ip_repository.h | 12 ++++----- common/repositories/account_repository.h | 12 ++++----- .../repositories/account_rewards_repository.h | 12 ++++----- .../adventure_details_repository.h | 12 ++++----- .../adventure_members_repository.h | 12 ++++----- .../repositories/adventure_stats_repository.h | 12 ++++----- ...venture_template_entry_flavor_repository.h | 12 ++++----- .../adventure_template_entry_repository.h | 12 ++++----- .../adventure_template_repository.h | 12 ++++----- .../alternate_currency_repository.h | 12 ++++----- common/repositories/auras_repository.h | 12 ++++----- .../base/base_aa_ability_repository.h | 12 ++++----- .../base/base_aa_rank_effects_repository.h | 12 ++++----- .../base/base_aa_rank_prereqs_repository.h | 12 ++++----- .../base/base_aa_ranks_repository.h | 12 ++++----- .../base/base_account_flags_repository.h | 12 ++++----- .../base/base_account_ip_repository.h | 12 ++++----- .../base/base_account_repository.h | 12 ++++----- .../base/base_account_rewards_repository.h | 12 ++++----- .../base/base_adventure_details_repository.h | 12 ++++----- .../base/base_adventure_members_repository.h | 12 ++++----- .../base/base_adventure_stats_repository.h | 12 ++++----- ...venture_template_entry_flavor_repository.h | 12 ++++----- ...base_adventure_template_entry_repository.h | 12 ++++----- .../base/base_adventure_template_repository.h | 10 +++----- .../base/base_alternate_currency_repository.h | 12 ++++----- .../repositories/base/base_auras_repository.h | 12 ++++----- .../base/base_base_data_repository.h | 12 ++++----- .../base/base_blocked_spells_repository.h | 12 ++++----- .../repositories/base/base_books_repository.h | 12 ++++----- .../base/base_bot_blocked_buffs_repository.h | 12 ++++----- .../base/base_bot_buffs_repository.h | 12 ++++----- .../base_bot_create_combinations_repository.h | 13 ++++------ .../base/base_bot_data_repository.h | 12 ++++----- .../base/base_bot_group_members_repository.h | 12 ++++----- .../base/base_bot_groups_repository.h | 12 ++++----- .../base/base_bot_guild_members_repository.h | 10 +++----- ...ase_bot_heal_rotation_members_repository.h | 12 ++++----- ...ase_bot_heal_rotation_targets_repository.h | 12 ++++----- .../base/base_bot_heal_rotations_repository.h | 12 ++++----- .../base_bot_inspect_messages_repository.h | 13 ++++------ .../base/base_bot_inventories_repository.h | 12 ++++----- .../base/base_bot_owner_options_repository.h | 12 ++++----- .../base/base_bot_pet_buffs_repository.h | 12 ++++----- .../base_bot_pet_inventories_repository.h | 12 ++++----- .../base/base_bot_pets_repository.h | 12 ++++----- .../base/base_bot_settings_repository.h | 12 ++++----- ...ase_bot_spell_casting_chances_repository.h | 12 ++++----- .../base/base_bot_spell_settings_repository.h | 12 ++++----- .../base/base_bot_spells_entries_repository.h | 12 ++++----- .../base/base_bot_stances_repository.h | 12 ++++----- .../base/base_bot_starting_items_repository.h | 12 ++++----- .../base/base_bot_timers_repository.h | 12 ++++----- .../base/base_bug_reports_repository.h | 12 ++++----- .../repositories/base/base_bugs_repository.h | 12 ++++----- .../base/base_buyer_buy_lines_repository.h | 12 ++++----- .../repositories/base/base_buyer_repository.h | 12 ++++----- .../base/base_buyer_trade_items_repository.h | 12 ++++----- ...base_char_create_combinations_repository.h | 12 ++++----- ...char_create_point_allocations_repository.h | 12 ++++----- .../base/base_char_recipe_list_repository.h | 12 ++++----- .../base_character_activities_repository.h | 12 ++++----- .../base_character_alt_currency_repository.h | 12 ++++----- ...character_alternate_abilities_repository.h | 12 ++++----- .../base/base_character_auras_repository.h | 12 ++++----- .../base_character_bandolier_repository.h | 12 ++++----- .../base/base_character_bind_repository.h | 12 ++++----- .../base/base_character_buffs_repository.h | 12 ++++----- .../base_character_corpse_items_repository.h | 12 ++++----- .../base/base_character_corpses_repository.h | 12 ++++----- .../base/base_character_currency_repository.h | 12 ++++----- .../base/base_character_data_repository.h | 12 ++++----- .../base_character_disciplines_repository.h | 12 ++++----- ...base_character_evolving_items_repository.h | 12 ++++----- .../base_character_exp_modifiers_repository.h | 12 ++++----- ...character_expedition_lockouts_repository.h | 12 ++++----- ...se_character_inspect_messages_repository.h | 12 ++++----- ...haracter_instance_safereturns_repository.h | 12 ++++----- .../base_character_item_recast_repository.h | 12 ++++----- .../base_character_languages_repository.h | 12 ++++----- ...haracter_leadership_abilities_repository.h | 12 ++++----- .../base/base_character_material_repository.h | 12 ++++----- .../base_character_memmed_spells_repository.h | 12 ++++----- ..._character_parcels_containers_repository.h | 12 ++++----- .../base/base_character_parcels_repository.h | 12 ++++----- .../base_character_peqzone_flags_repository.h | 12 ++++----- .../base_character_pet_buffs_repository.h | 12 ++++----- .../base/base_character_pet_info_repository.h | 12 ++++----- .../base_character_pet_inventory_repository.h | 12 ++++----- .../base/base_character_pet_name_repository.h | 12 ++++----- .../base_character_potionbelt_repository.h | 12 ++++----- .../base/base_character_skills_repository.h | 12 ++++----- .../base/base_character_spells_repository.h | 12 ++++----- .../base_character_stats_record_repository.h | 12 ++++----- .../base_character_task_timers_repository.h | 12 ++++----- .../base/base_character_tasks_repository.h | 12 ++++----- .../base/base_character_tribute_repository.h | 12 ++++----- ...se_chatchannel_reserved_names_repository.h | 12 ++++----- .../base/base_chatchannels_repository.h | 12 ++++----- .../base_command_subsettings_repository.h | 12 ++++----- ...ed_shared_task_activity_state_repository.h | 12 ++++----- ...completed_shared_task_members_repository.h | 12 ++++----- .../base_completed_shared_tasks_repository.h | 12 ++++----- .../base/base_completed_tasks_repository.h | 12 ++++----- .../base/base_content_flags_repository.h | 12 ++++----- .../base/base_damageshieldtypes_repository.h | 12 ++++----- .../base/base_data_buckets_repository.h | 12 ++++----- .../base/base_db_str_repository.h | 12 ++++----- .../base/base_discord_webhooks_repository.h | 12 ++++----- .../base/base_discovered_items_repository.h | 12 ++++----- .../repositories/base/base_doors_repository.h | 12 ++++----- .../base_dynamic_zone_lockouts_repository.h | 12 ++++----- .../base_dynamic_zone_members_repository.h | 12 ++++----- .../base_dynamic_zone_templates_repository.h | 12 ++++----- .../base/base_dynamic_zones_repository.h | 12 ++++----- .../base_faction_association_repository.h | 12 ++++----- .../base/base_faction_base_data_repository.h | 12 ++++----- .../base/base_faction_list_mod_repository.h | 12 ++++----- .../base/base_faction_list_repository.h | 12 ++++----- .../base/base_faction_values_repository.h | 12 ++++----- .../base/base_fishing_repository.h | 12 ++++----- .../base/base_forage_repository.h | 12 ++++----- .../base/base_friends_repository.h | 12 ++++----- .../base/base_global_loot_repository.h | 12 ++++----- .../base/base_gm_ips_repository.h | 12 ++++----- .../base/base_graveyard_repository.h | 12 ++++----- .../base/base_grid_entries_repository.h | 12 ++++----- .../repositories/base/base_grid_repository.h | 12 ++++----- .../base/base_ground_spawns_repository.h | 12 ++++----- .../base/base_group_id_repository.h | 12 ++++----- .../base/base_group_leaders_repository.h | 12 ++++----- .../base/base_guild_bank_repository.h | 12 ++++----- .../base/base_guild_members_repository.h | 12 ++++----- .../base/base_guild_permissions_repository.h | 12 ++++----- .../base/base_guild_ranks_repository.h | 12 ++++----- .../base/base_guild_relations_repository.h | 12 ++++----- .../base/base_guild_tributes_repository.h | 12 ++++----- .../base/base_guilds_repository.h | 12 ++++----- .../base/base_horses_repository.h | 12 ++++----- .../base_instance_list_player_repository.h | 12 ++++----- .../base/base_instance_list_repository.h | 12 ++++----- .../base/base_inventory_repository.h | 12 ++++----- .../base_inventory_snapshots_repository.h | 12 ++++----- .../base/base_ip_exemptions_repository.h | 12 ++++----- .../base_items_evolving_details_repository.h | 12 ++++----- .../repositories/base/base_items_repository.h | 12 ++++----- .../base/base_keyring_repository.h | 10 +++----- .../base/base_launcher_repository.h | 9 +++---- .../base/base_ldon_trap_entries_repository.h | 12 ++++----- .../base_ldon_trap_templates_repository.h | 12 ++++----- .../base/base_level_exp_mods_repository.h | 12 ++++----- .../base/base_lfguild_repository.h | 12 ++++----- .../base/base_login_accounts_repository.h | 12 ++++----- .../base/base_login_api_tokens_repository.h | 12 ++++----- .../base_login_server_admins_repository.h | 12 ++++----- .../base_login_server_list_types_repository.h | 12 ++++----- .../base_login_world_servers_repository.h | 12 ++++----- .../base/base_logsys_categories_repository.h | 12 ++++----- .../base/base_lootdrop_entries_repository.h | 12 ++++----- .../base/base_lootdrop_repository.h | 12 ++++----- .../base/base_loottable_entries_repository.h | 12 ++++----- .../base/base_loottable_repository.h | 12 ++++----- .../repositories/base/base_mail_repository.h | 12 ++++----- .../base/base_merc_armorinfo_repository.h | 12 ++++----- .../base/base_merc_buffs_repository.h | 12 ++++----- .../base/base_merc_inventory_repository.h | 12 ++++----- .../base_merc_merchant_entries_repository.h | 12 ++++----- ...erc_merchant_template_entries_repository.h | 12 ++++----- .../base_merc_merchant_templates_repository.h | 12 ++++----- .../base/base_merc_name_types_repository.h | 12 ++++----- .../base/base_merc_npc_types_repository.h | 12 ++++----- .../base_merc_spell_list_entries_repository.h | 12 ++++----- .../base/base_merc_spell_lists_repository.h | 12 ++++----- .../base_merc_stance_entries_repository.h | 12 ++++----- .../base/base_merc_stats_repository.h | 12 ++++----- .../base/base_merc_subtypes_repository.h | 12 ++++----- .../base/base_merc_templates_repository.h | 12 ++++----- .../base/base_merc_types_repository.h | 12 ++++----- .../base/base_merc_weaponinfo_repository.h | 12 ++++----- .../base/base_merchantlist_repository.h | 12 ++++----- .../base/base_merchantlist_temp_repository.h | 12 ++++----- .../repositories/base/base_mercs_repository.h | 12 ++++----- .../base/base_name_filter_repository.h | 12 ++++----- .../base/base_npc_emotes_repository.h | 12 ++++----- .../base_npc_faction_entries_repository.h | 12 ++++----- .../base/base_npc_faction_repository.h | 12 ++++----- .../base_npc_scale_global_base_repository.h | 12 ++++----- ...se_npc_spells_effects_entries_repository.h | 12 ++++----- .../base/base_npc_spells_effects_repository.h | 12 ++++----- .../base/base_npc_spells_entries_repository.h | 12 ++++----- .../base/base_npc_spells_repository.h | 12 ++++----- .../base/base_npc_types_repository.h | 12 ++++----- .../base/base_npc_types_tint_repository.h | 12 ++++----- .../base/base_object_contents_repository.h | 12 ++++----- .../base/base_object_repository.h | 12 ++++----- ...se_perl_event_export_settings_repository.h | 12 ++++----- .../base/base_petitions_repository.h | 12 ++++----- .../base_pets_beastlord_data_repository.h | 12 ++++----- ...ase_pets_equipmentset_entries_repository.h | 12 ++++----- .../base/base_pets_equipmentset_repository.h | 12 ++++----- .../repositories/base/base_pets_repository.h | 12 ++++----- ...base_player_event_aa_purchase_repository.h | 12 ++++----- ...player_event_killed_named_npc_repository.h | 12 ++++----- .../base_player_event_killed_npc_repository.h | 12 ++++----- ..._player_event_killed_raid_npc_repository.h | 12 ++++----- ...ase_player_event_log_settings_repository.h | 12 ++++----- .../base/base_player_event_logs_repository.h | 12 ++++----- .../base_player_event_loot_items_repository.h | 12 ++++----- ...layer_event_merchant_purchase_repository.h | 12 ++++----- ...se_player_event_merchant_sell_repository.h | 12 ++++----- ...ayer_event_npc_handin_entries_repository.h | 12 ++++----- .../base_player_event_npc_handin_repository.h | 12 ++++----- .../base_player_event_speech_repository.h | 12 ++++----- ...se_player_event_trade_entries_repository.h | 12 ++++----- .../base/base_player_event_trade_repository.h | 12 ++++----- .../base/base_player_titlesets_repository.h | 12 ++++----- .../base/base_quest_globals_repository.h | 12 ++++----- .../base/base_raid_details_repository.h | 12 ++++----- .../base/base_raid_members_repository.h | 12 ++++----- .../base/base_reports_repository.h | 12 ++++----- .../base/base_respawn_times_repository.h | 12 ++++----- .../base/base_rule_sets_repository.h | 12 ++++----- .../base/base_rule_values_repository.h | 12 ++++----- .../base/base_saylink_repository.h | 12 ++++----- .../base_server_scheduled_events_repository.h | 12 ++++----- ...se_shared_task_activity_state_repository.h | 12 ++++----- ...ase_shared_task_dynamic_zones_repository.h | 12 ++++----- .../base_shared_task_members_repository.h | 12 ++++----- .../base/base_shared_tasks_repository.h | 12 ++++----- .../base/base_sharedbank_repository.h | 12 ++++----- .../base/base_skill_caps_repository.h | 12 ++++----- .../base/base_spawn2_disabled_repository.h | 12 ++++----- .../base/base_spawn2_repository.h | 12 ++++----- .../base_spawn_condition_values_repository.h | 12 ++++----- .../base/base_spawn_conditions_repository.h | 12 ++++----- .../base/base_spawn_events_repository.h | 12 ++++----- .../base/base_spawnentry_repository.h | 12 ++++----- .../base/base_spawngroup_repository.h | 12 ++++----- .../base/base_spell_buckets_repository.h | 12 ++++----- .../base/base_spell_globals_repository.h | 12 ++++----- .../base/base_spells_new_repository.h | 12 ++++----- .../base/base_start_zones_repository.h | 12 ++++----- .../base/base_starting_items_repository.h | 12 ++++----- .../base/base_task_activities_repository.h | 12 ++++----- .../repositories/base/base_tasks_repository.h | 12 ++++----- .../base/base_tasksets_repository.h | 12 ++++----- .../base/base_timers_repository.h | 12 ++++----- .../base/base_titles_repository.h | 12 ++++----- .../base/base_tool_game_objects_repository.h | 10 +++----- .../base/base_trader_repository.h | 12 ++++----- ...ase_tradeskill_recipe_entries_repository.h | 12 ++++----- .../base/base_tradeskill_recipe_repository.h | 12 ++++----- .../repositories/base/base_traps_repository.h | 12 ++++----- .../base/base_tribute_levels_repository.h | 12 ++++----- .../base/base_tributes_repository.h | 12 ++++----- .../base/base_variables_repository.h | 12 ++++----- ...base_veteran_reward_templates_repository.h | 12 ++++----- .../base/base_zone_flags_repository.h | 12 ++++----- .../base/base_zone_points_repository.h | 12 ++++----- .../repositories/base/base_zone_repository.h | 12 ++++----- .../base/base_zone_state_spawns_repository.h | 12 ++++----- common/repositories/base_data_repository.h | 12 ++++----- .../repositories/blocked_spells_repository.h | 12 ++++----- common/repositories/books_repository.h | 12 ++++----- .../bot_blocked_buffs_repository.h | 12 ++++----- common/repositories/bot_buffs_repository.h | 12 ++++----- .../bot_create_combinations_repository.h | 12 ++++----- common/repositories/bot_data_repository.h | 12 ++++----- .../bot_group_members_repository.h | 12 ++++----- common/repositories/bot_groups_repository.h | 12 ++++----- .../bot_guild_members_repository.h | 12 ++++----- .../bot_heal_rotation_members_repository.h | 12 ++++----- .../bot_heal_rotation_targets_repository.h | 12 ++++----- .../bot_heal_rotations_repository.h | 12 ++++----- .../bot_inspect_messages_repository.h | 12 ++++----- .../repositories/bot_inventories_repository.h | 12 ++++----- .../bot_owner_options_repository.h | 12 ++++----- .../repositories/bot_pet_buffs_repository.h | 12 ++++----- .../bot_pet_inventories_repository.h | 12 ++++----- common/repositories/bot_pets_repository.h | 12 ++++----- common/repositories/bot_settings_repository.h | 12 ++++----- .../bot_spell_casting_chances_repository.h | 12 ++++----- .../bot_spell_settings_repository.h | 12 ++++----- .../bot_spells_entries_repository.h | 12 ++++----- common/repositories/bot_stances_repository.h | 12 ++++----- .../bot_starting_items_repository.h | 12 ++++----- common/repositories/bot_timers_repository.h | 12 ++++----- common/repositories/bug_reports_repository.h | 12 ++++----- common/repositories/bugs_repository.h | 12 ++++----- .../repositories/buyer_buy_lines_repository.h | 19 ++++++-------- common/repositories/buyer_repository.h | 12 ++++----- .../buyer_trade_items_repository.h | 12 ++++----- .../char_create_combinations_repository.h | 12 ++++----- ...char_create_point_allocations_repository.h | 12 ++++----- .../char_recipe_list_repository.h | 12 ++++----- .../character_activities_repository.h | 12 ++++----- .../character_alt_currency_repository.h | 12 ++++----- ...character_alternate_abilities_repository.h | 12 ++++----- .../repositories/character_auras_repository.h | 12 ++++----- .../character_bandolier_repository.h | 12 ++++----- .../repositories/character_bind_repository.h | 12 ++++----- .../repositories/character_buffs_repository.h | 12 ++++----- .../character_corpse_items_repository.h | 12 ++++----- .../character_corpses_repository.h | 16 ++++++------ .../character_currency_repository.h | 12 ++++----- .../repositories/character_data_repository.h | 12 ++++----- .../character_disciplines_repository.h | 12 ++++----- .../character_evolving_items_repository.h | 12 ++++----- .../character_exp_modifiers_repository.h | 12 ++++----- ...character_expedition_lockouts_repository.h | 15 ++++++----- .../character_inspect_messages_repository.h | 12 ++++----- ...haracter_instance_safereturns_repository.h | 12 ++++----- .../character_item_recast_repository.h | 12 ++++----- .../character_languages_repository.h | 12 ++++----- ...haracter_leadership_abilities_repository.h | 12 ++++----- .../character_material_repository.h | 12 ++++----- .../character_memmed_spells_repository.h | 12 ++++----- .../character_parcels_containers_repository.h | 12 ++++----- .../character_parcels_repository.h | 12 ++++----- .../character_peqzone_flags_repository.h | 12 ++++----- .../character_pet_buffs_repository.h | 12 ++++----- .../character_pet_info_repository.h | 12 ++++----- .../character_pet_inventory_repository.h | 12 ++++----- .../character_pet_name_repository.h | 12 ++++----- .../character_potionbelt_repository.h | 12 ++++----- .../character_skills_repository.h | 12 ++++----- .../character_spells_repository.h | 12 ++++----- .../character_stats_record_repository.h | 12 ++++----- .../character_task_timers_repository.h | 12 ++++----- .../repositories/character_tasks_repository.h | 12 ++++----- .../character_tribute_repository.h | 12 ++++----- .../chatchannel_reserved_names_repository.h | 12 ++++----- common/repositories/chatchannels_repository.h | 12 ++++----- .../command_subsettings_repository.h | 12 ++++----- ...ed_shared_task_activity_state_repository.h | 12 ++++----- ...completed_shared_task_members_repository.h | 12 ++++----- .../completed_shared_tasks_repository.h | 12 ++++----- .../repositories/completed_tasks_repository.h | 12 ++++----- .../repositories/content_flags_repository.h | 12 ++++----- .../criteria/content_filter_criteria.h | 10 +++----- .../damageshieldtypes_repository.h | 12 ++++----- common/repositories/data_buckets_repository.h | 12 ++++----- common/repositories/db_str_repository.h | 12 ++++----- .../discord_webhooks_repository.h | 12 ++++----- .../discovered_items_repository.h | 12 ++++----- common/repositories/doors_repository.h | 12 ++++----- .../dynamic_zone_lockouts_repository.h | 14 +++++------ .../dynamic_zone_members_repository.h | 12 ++++----- .../dynamic_zone_templates_repository.h | 12 ++++----- .../repositories/dynamic_zones_repository.h | 12 ++++----- .../faction_association_repository.h | 12 ++++----- .../faction_base_data_repository.h | 12 ++++----- .../faction_list_mod_repository.h | 12 ++++----- common/repositories/faction_list_repository.h | 12 ++++----- .../repositories/faction_values_repository.h | 12 ++++----- common/repositories/fishing_repository.h | 12 ++++----- common/repositories/forage_repository.h | 12 ++++----- common/repositories/friends_repository.h | 12 ++++----- common/repositories/global_loot_repository.h | 12 ++++----- common/repositories/gm_ips_repository.h | 12 ++++----- common/repositories/graveyard_repository.h | 12 ++++----- common/repositories/grid_entries_repository.h | 12 ++++----- common/repositories/grid_repository.h | 12 ++++----- .../repositories/ground_spawns_repository.h | 12 ++++----- common/repositories/group_id_repository.h | 12 ++++----- .../repositories/group_leaders_repository.h | 12 ++++----- common/repositories/guild_bank_repository.h | 12 ++++----- .../repositories/guild_members_repository.h | 12 ++++----- .../guild_permissions_repository.h | 12 ++++----- common/repositories/guild_ranks_repository.h | 12 ++++----- .../repositories/guild_relations_repository.h | 12 ++++----- .../repositories/guild_tributes_repository.h | 12 ++++----- common/repositories/guilds_repository.h | 12 ++++----- common/repositories/horses_repository.h | 12 ++++----- .../instance_list_player_repository.h | 13 +++++----- .../repositories/instance_list_repository.h | 12 ++++----- common/repositories/inventory_repository.h | 12 ++++----- .../inventory_snapshots_repository.h | 12 ++++----- .../inventory_versions_repository.h | 9 +++---- .../repositories/ip_exemptions_repository.h | 12 ++++----- .../items_evolving_details_repository.h | 12 ++++----- common/repositories/items_repository.h | 12 ++++----- common/repositories/keyring_repository.h | 12 ++++----- .../ldon_trap_entries_repository.h | 12 ++++----- .../ldon_trap_templates_repository.h | 12 ++++----- .../repositories/level_exp_mods_repository.h | 12 ++++----- common/repositories/lfguild_repository.h | 12 ++++----- .../repositories/login_accounts_repository.h | 16 ++++++------ .../login_api_tokens_repository.h | 12 ++++----- .../login_server_admins_repository.h | 12 ++++----- .../login_server_list_types_repository.h | 12 ++++----- .../login_world_servers_repository.h | 12 ++++----- .../logsys_categories_repository.h | 12 ++++----- .../lootdrop_entries_repository.h | 12 ++++----- common/repositories/lootdrop_repository.h | 12 ++++----- .../loottable_entries_repository.h | 12 ++++----- common/repositories/loottable_repository.h | 12 ++++----- common/repositories/mail_repository.h | 12 ++++----- .../repositories/merc_armorinfo_repository.h | 12 ++++----- common/repositories/merc_buffs_repository.h | 12 ++++----- .../repositories/merc_inventory_repository.h | 12 ++++----- .../merc_merchant_entries_repository.h | 12 ++++----- ...erc_merchant_template_entries_repository.h | 12 ++++----- .../merc_merchant_templates_repository.h | 12 ++++----- .../repositories/merc_name_types_repository.h | 12 ++++----- .../repositories/merc_npc_types_repository.h | 12 ++++----- .../merc_spell_list_entries_repository.h | 12 ++++----- .../merc_spell_lists_repository.h | 12 ++++----- .../merc_stance_entries_repository.h | 12 ++++----- common/repositories/merc_stats_repository.h | 12 ++++----- .../repositories/merc_subtypes_repository.h | 12 ++++----- .../repositories/merc_templates_repository.h | 12 ++++----- common/repositories/merc_types_repository.h | 12 ++++----- .../repositories/merc_weaponinfo_repository.h | 12 ++++----- common/repositories/merchantlist_repository.h | 12 ++++----- .../merchantlist_temp_repository.h | 12 ++++----- common/repositories/mercs_repository.h | 12 ++++----- common/repositories/name_filter_repository.h | 12 ++++----- common/repositories/npc_emotes_repository.h | 12 ++++----- .../npc_faction_entries_repository.h | 12 ++++----- common/repositories/npc_faction_repository.h | 12 ++++----- .../npc_scale_global_base_repository.h | 12 ++++----- .../npc_spells_effects_entries_repository.h | 12 ++++----- .../npc_spells_effects_repository.h | 12 ++++----- .../npc_spells_entries_repository.h | 12 ++++----- common/repositories/npc_spells_repository.h | 12 ++++----- common/repositories/npc_types_repository.h | 12 ++++----- .../repositories/npc_types_tint_repository.h | 12 ++++----- .../repositories/object_contents_repository.h | 12 ++++----- common/repositories/object_repository.h | 12 ++++----- .../perl_event_export_settings_repository.h | 12 ++++----- common/repositories/petitions_repository.h | 12 ++++----- .../pets_beastlord_data_repository.h | 12 ++++----- .../pets_equipmentset_entries_repository.h | 12 ++++----- .../pets_equipmentset_repository.h | 12 ++++----- common/repositories/pets_repository.h | 12 ++++----- .../player_event_aa_purchase_repository.h | 12 ++++----- ...player_event_killed_named_npc_repository.h | 12 ++++----- .../player_event_killed_npc_repository.h | 12 ++++----- .../player_event_killed_raid_npc_repository.h | 12 ++++----- .../player_event_log_settings_repository.h | 15 ++++++----- .../player_event_logs_repository.h | 12 ++++----- .../player_event_loot_items_repository.h | 12 ++++----- ...layer_event_merchant_purchase_repository.h | 12 ++++----- .../player_event_merchant_sell_repository.h | 12 ++++----- ...ayer_event_npc_handin_entries_repository.h | 12 ++++----- .../player_event_npc_handin_repository.h | 12 ++++----- .../player_event_speech_repository.h | 12 ++++----- .../player_event_trade_entries_repository.h | 12 ++++----- .../player_event_trade_repository.h | 12 ++++----- .../player_titlesets_repository.h | 12 ++++----- .../repositories/quest_globals_repository.h | 12 ++++----- common/repositories/raid_details_repository.h | 12 ++++----- common/repositories/raid_members_repository.h | 13 +++++----- common/repositories/reports_repository.h | 12 ++++----- .../repositories/respawn_times_repository.h | 12 ++++----- common/repositories/rule_sets_repository.h | 12 ++++----- common/repositories/rule_values_repository.h | 12 ++++----- common/repositories/saylink_repository.h | 12 ++++----- .../server_scheduled_events_repository.h | 12 ++++----- .../shared_task_activity_state_repository.h | 12 ++++----- .../shared_task_dynamic_zones_repository.h | 12 ++++----- .../shared_task_members_repository.h | 12 ++++----- common/repositories/shared_tasks_repository.h | 12 ++++----- common/repositories/sharedbank_repository.h | 12 ++++----- common/repositories/skill_caps_repository.h | 12 ++++----- .../repositories/spawn2_disabled_repository.h | 12 ++++----- common/repositories/spawn2_repository.h | 12 ++++----- .../spawn_condition_values_repository.h | 12 ++++----- .../spawn_conditions_repository.h | 12 ++++----- common/repositories/spawn_events_repository.h | 12 ++++----- common/repositories/spawnentry_repository.h | 12 ++++----- common/repositories/spawngroup_repository.h | 12 ++++----- .../repositories/spell_buckets_repository.h | 12 ++++----- .../repositories/spell_globals_repository.h | 12 ++++----- common/repositories/spells_new_repository.h | 12 ++++----- common/repositories/start_zones_repository.h | 12 ++++----- .../repositories/starting_items_repository.h | 12 ++++----- .../repositories/task_activities_repository.h | 12 ++++----- common/repositories/tasks_repository.h | 12 ++++----- common/repositories/tasksets_repository.h | 12 ++++----- .../template/base_repository.template | 14 +++++------ .../repositories/template/repository.template | 12 ++++----- common/repositories/timers_repository.h | 12 ++++----- common/repositories/titles_repository.h | 12 ++++----- .../tool_game_objects_repository.h | 12 ++++----- common/repositories/trader_audit_repository.h | 9 +++---- common/repositories/trader_repository.h | 25 +++++++++---------- .../tradeskill_recipe_entries_repository.h | 12 ++++----- .../tradeskill_recipe_repository.h | 12 ++++----- common/repositories/traps_repository.h | 12 ++++----- .../repositories/tribute_levels_repository.h | 12 ++++----- common/repositories/tributes_repository.h | 12 ++++----- common/repositories/variables_repository.h | 12 ++++----- .../veteran_reward_templates_repository.h | 12 ++++----- common/repositories/zone_flags_repository.h | 12 ++++----- common/repositories/zone_points_repository.h | 12 ++++----- common/repositories/zone_repository.h | 12 ++++----- .../zone_state_spawns_repository.h | 13 +++++----- 504 files changed, 2533 insertions(+), 3539 deletions(-) diff --git a/common/repositories/aa_ability_repository.h b/common/repositories/aa_ability_repository.h index 59bc165e4d..3713cfb593 100644 --- a/common/repositories/aa_ability_repository.h +++ b/common/repositories/aa_ability_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_AA_ABILITY_REPOSITORY_H -#define EQEMU_AA_ABILITY_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_aa_ability_repository.h" +#include "common/repositories/base/base_aa_ability_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AaAbilityRepository: public BaseAaAbilityRepository { public: @@ -46,5 +46,3 @@ class AaAbilityRepository: public BaseAaAbilityRepository { // Custom extended repository methods here }; - -#endif //EQEMU_AA_ABILITY_REPOSITORY_H diff --git a/common/repositories/aa_rank_effects_repository.h b/common/repositories/aa_rank_effects_repository.h index ebec6814c2..39cb9f0024 100644 --- a/common/repositories/aa_rank_effects_repository.h +++ b/common/repositories/aa_rank_effects_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_AA_RANK_EFFECTS_REPOSITORY_H -#define EQEMU_AA_RANK_EFFECTS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_aa_rank_effects_repository.h" +#include "common/repositories/base/base_aa_rank_effects_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AaRankEffectsRepository: public BaseAaRankEffectsRepository { public: @@ -46,5 +46,3 @@ class AaRankEffectsRepository: public BaseAaRankEffectsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_AA_RANK_EFFECTS_REPOSITORY_H diff --git a/common/repositories/aa_rank_prereqs_repository.h b/common/repositories/aa_rank_prereqs_repository.h index 76dbeea01e..5d0b17adc8 100644 --- a/common/repositories/aa_rank_prereqs_repository.h +++ b/common/repositories/aa_rank_prereqs_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_AA_RANK_PREREQS_REPOSITORY_H -#define EQEMU_AA_RANK_PREREQS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_aa_rank_prereqs_repository.h" +#include "common/repositories/base/base_aa_rank_prereqs_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AaRankPrereqsRepository: public BaseAaRankPrereqsRepository { public: @@ -46,5 +46,3 @@ class AaRankPrereqsRepository: public BaseAaRankPrereqsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_AA_RANK_PREREQS_REPOSITORY_H diff --git a/common/repositories/aa_ranks_repository.h b/common/repositories/aa_ranks_repository.h index 170548cad6..1a9812af34 100644 --- a/common/repositories/aa_ranks_repository.h +++ b/common/repositories/aa_ranks_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_AA_RANKS_REPOSITORY_H -#define EQEMU_AA_RANKS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_aa_ranks_repository.h" +#include "common/repositories/base/base_aa_ranks_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AaRanksRepository: public BaseAaRanksRepository { public: @@ -46,5 +46,3 @@ class AaRanksRepository: public BaseAaRanksRepository { // Custom extended repository methods here }; - -#endif //EQEMU_AA_RANKS_REPOSITORY_H diff --git a/common/repositories/account_flags_repository.h b/common/repositories/account_flags_repository.h index b9ebea21d0..f554072eda 100644 --- a/common/repositories/account_flags_repository.h +++ b/common/repositories/account_flags_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ACCOUNT_FLAGS_REPOSITORY_H -#define EQEMU_ACCOUNT_FLAGS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_account_flags_repository.h" +#include "common/repositories/base/base_account_flags_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AccountFlagsRepository: public BaseAccountFlagsRepository { public: @@ -74,5 +74,3 @@ class AccountFlagsRepository: public BaseAccountFlagsRepository { ); } }; - -#endif //EQEMU_ACCOUNT_FLAGS_REPOSITORY_H diff --git a/common/repositories/account_ip_repository.h b/common/repositories/account_ip_repository.h index d7278708bb..1159d8c86f 100644 --- a/common/repositories/account_ip_repository.h +++ b/common/repositories/account_ip_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ACCOUNT_IP_REPOSITORY_H -#define EQEMU_ACCOUNT_IP_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_account_ip_repository.h" +#include "common/repositories/base/base_account_ip_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AccountIpRepository: public BaseAccountIpRepository { public: @@ -46,5 +46,3 @@ class AccountIpRepository: public BaseAccountIpRepository { // Custom extended repository methods here }; - -#endif //EQEMU_ACCOUNT_IP_REPOSITORY_H diff --git a/common/repositories/account_repository.h b/common/repositories/account_repository.h index 5f2b085812..42a301ec1a 100644 --- a/common/repositories/account_repository.h +++ b/common/repositories/account_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ACCOUNT_REPOSITORY_H -#define EQEMU_ACCOUNT_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_account_repository.h" +#include "common/repositories/base/base_account_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AccountRepository: public BaseAccountRepository { public: @@ -108,5 +108,3 @@ class AccountRepository: public BaseAccountRepository { return AccountRepository::UpdateOne(db, e); } }; - -#endif //EQEMU_ACCOUNT_REPOSITORY_H diff --git a/common/repositories/account_rewards_repository.h b/common/repositories/account_rewards_repository.h index 3db8f653a2..7e2183c8f5 100644 --- a/common/repositories/account_rewards_repository.h +++ b/common/repositories/account_rewards_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ACCOUNT_REWARDS_REPOSITORY_H -#define EQEMU_ACCOUNT_REWARDS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_account_rewards_repository.h" +#include "common/repositories/base/base_account_rewards_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AccountRewardsRepository: public BaseAccountRewardsRepository { public: @@ -46,5 +46,3 @@ class AccountRewardsRepository: public BaseAccountRewardsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_ACCOUNT_REWARDS_REPOSITORY_H diff --git a/common/repositories/adventure_details_repository.h b/common/repositories/adventure_details_repository.h index c81ac5cc39..0bd4875e3d 100644 --- a/common/repositories/adventure_details_repository.h +++ b/common/repositories/adventure_details_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ADVENTURE_DETAILS_REPOSITORY_H -#define EQEMU_ADVENTURE_DETAILS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_adventure_details_repository.h" +#include "common/repositories/base/base_adventure_details_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AdventureDetailsRepository: public BaseAdventureDetailsRepository { public: @@ -46,5 +46,3 @@ class AdventureDetailsRepository: public BaseAdventureDetailsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_ADVENTURE_DETAILS_REPOSITORY_H diff --git a/common/repositories/adventure_members_repository.h b/common/repositories/adventure_members_repository.h index d430d8eb27..fed4e9996f 100644 --- a/common/repositories/adventure_members_repository.h +++ b/common/repositories/adventure_members_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ADVENTURE_MEMBERS_REPOSITORY_H -#define EQEMU_ADVENTURE_MEMBERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_adventure_members_repository.h" +#include "common/repositories/base/base_adventure_members_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AdventureMembersRepository: public BaseAdventureMembersRepository { public: @@ -46,5 +46,3 @@ class AdventureMembersRepository: public BaseAdventureMembersRepository { // Custom extended repository methods here }; - -#endif //EQEMU_ADVENTURE_MEMBERS_REPOSITORY_H diff --git a/common/repositories/adventure_stats_repository.h b/common/repositories/adventure_stats_repository.h index 5b93a7fe13..3330c84260 100644 --- a/common/repositories/adventure_stats_repository.h +++ b/common/repositories/adventure_stats_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ADVENTURE_STATS_REPOSITORY_H -#define EQEMU_ADVENTURE_STATS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_adventure_stats_repository.h" +#include "common/repositories/base/base_adventure_stats_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AdventureStatsRepository: public BaseAdventureStatsRepository { public: @@ -104,5 +104,3 @@ class AdventureStatsRepository: public BaseAdventureStatsRepository { db.QueryDatabase(query); } }; - -#endif //EQEMU_ADVENTURE_STATS_REPOSITORY_H diff --git a/common/repositories/adventure_template_entry_flavor_repository.h b/common/repositories/adventure_template_entry_flavor_repository.h index c0d1d63c97..d5624a0d46 100644 --- a/common/repositories/adventure_template_entry_flavor_repository.h +++ b/common/repositories/adventure_template_entry_flavor_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ADVENTURE_TEMPLATE_ENTRY_FLAVOR_REPOSITORY_H -#define EQEMU_ADVENTURE_TEMPLATE_ENTRY_FLAVOR_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_adventure_template_entry_flavor_repository.h" +#include "common/repositories/base/base_adventure_template_entry_flavor_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AdventureTemplateEntryFlavorRepository: public BaseAdventureTemplateEntryFlavorRepository { public: @@ -46,5 +46,3 @@ class AdventureTemplateEntryFlavorRepository: public BaseAdventureTemplateEntryF // Custom extended repository methods here }; - -#endif //EQEMU_ADVENTURE_TEMPLATE_ENTRY_FLAVOR_REPOSITORY_H diff --git a/common/repositories/adventure_template_entry_repository.h b/common/repositories/adventure_template_entry_repository.h index 95db9f229d..6b9b004fd3 100644 --- a/common/repositories/adventure_template_entry_repository.h +++ b/common/repositories/adventure_template_entry_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ADVENTURE_TEMPLATE_ENTRY_REPOSITORY_H -#define EQEMU_ADVENTURE_TEMPLATE_ENTRY_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_adventure_template_entry_repository.h" +#include "common/repositories/base/base_adventure_template_entry_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AdventureTemplateEntryRepository: public BaseAdventureTemplateEntryRepository { public: @@ -46,5 +46,3 @@ class AdventureTemplateEntryRepository: public BaseAdventureTemplateEntryReposit // Custom extended repository methods here }; - -#endif //EQEMU_ADVENTURE_TEMPLATE_ENTRY_REPOSITORY_H diff --git a/common/repositories/adventure_template_repository.h b/common/repositories/adventure_template_repository.h index 39c8699b74..50d5f74de2 100644 --- a/common/repositories/adventure_template_repository.h +++ b/common/repositories/adventure_template_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ADVENTURE_TEMPLATE_REPOSITORY_H -#define EQEMU_ADVENTURE_TEMPLATE_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_adventure_template_repository.h" +#include "common/repositories/base/base_adventure_template_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AdventureTemplateRepository: public BaseAdventureTemplateRepository { public: @@ -46,5 +46,3 @@ class AdventureTemplateRepository: public BaseAdventureTemplateRepository { // Custom extended repository methods here }; - -#endif //EQEMU_ADVENTURE_TEMPLATE_REPOSITORY_H diff --git a/common/repositories/alternate_currency_repository.h b/common/repositories/alternate_currency_repository.h index cd2a95f526..2b616b1f22 100644 --- a/common/repositories/alternate_currency_repository.h +++ b/common/repositories/alternate_currency_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ALTERNATE_CURRENCY_REPOSITORY_H -#define EQEMU_ALTERNATE_CURRENCY_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_alternate_currency_repository.h" +#include "common/repositories/base/base_alternate_currency_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AlternateCurrencyRepository: public BaseAlternateCurrencyRepository { public: @@ -46,5 +46,3 @@ class AlternateCurrencyRepository: public BaseAlternateCurrencyRepository { // Custom extended repository methods here }; - -#endif //EQEMU_ALTERNATE_CURRENCY_REPOSITORY_H diff --git a/common/repositories/auras_repository.h b/common/repositories/auras_repository.h index 7d97503fbf..d118b2c02c 100644 --- a/common/repositories/auras_repository.h +++ b/common/repositories/auras_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_AURAS_REPOSITORY_H -#define EQEMU_AURAS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_auras_repository.h" +#include "common/repositories/base/base_auras_repository.h" + +#include "common/database.h" +#include "common/strings.h" class AurasRepository: public BaseAurasRepository { public: @@ -46,5 +46,3 @@ class AurasRepository: public BaseAurasRepository { // Custom extended repository methods here }; - -#endif //EQEMU_AURAS_REPOSITORY_H diff --git a/common/repositories/base/base_aa_ability_repository.h b/common/repositories/base/base_aa_ability_repository.h index 923a3ca36e..7a3e2a8ee4 100644 --- a/common/repositories/base/base_aa_ability_repository.h +++ b/common/repositories/base/base_aa_ability_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_AA_ABILITY_REPOSITORY_H -#define EQEMU_BASE_AA_ABILITY_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAaAbilityRepository { @@ -544,5 +544,3 @@ class BaseAaAbilityRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_AA_ABILITY_REPOSITORY_H diff --git a/common/repositories/base/base_aa_rank_effects_repository.h b/common/repositories/base/base_aa_rank_effects_repository.h index 5ce73f2fee..11418fef93 100644 --- a/common/repositories/base/base_aa_rank_effects_repository.h +++ b/common/repositories/base/base_aa_rank_effects_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_AA_RANK_EFFECTS_REPOSITORY_H -#define EQEMU_BASE_AA_RANK_EFFECTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAaRankEffectsRepository { @@ -424,5 +424,3 @@ class BaseAaRankEffectsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_AA_RANK_EFFECTS_REPOSITORY_H diff --git a/common/repositories/base/base_aa_rank_prereqs_repository.h b/common/repositories/base/base_aa_rank_prereqs_repository.h index c227ef3c81..77b561f134 100644 --- a/common/repositories/base/base_aa_rank_prereqs_repository.h +++ b/common/repositories/base/base_aa_rank_prereqs_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_AA_RANK_PREREQS_REPOSITORY_H -#define EQEMU_BASE_AA_RANK_PREREQS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAaRankPrereqsRepository { @@ -400,5 +400,3 @@ class BaseAaRankPrereqsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_AA_RANK_PREREQS_REPOSITORY_H diff --git a/common/repositories/base/base_aa_ranks_repository.h b/common/repositories/base/base_aa_ranks_repository.h index 0667bf2823..d2cc845b3d 100644 --- a/common/repositories/base/base_aa_ranks_repository.h +++ b/common/repositories/base/base_aa_ranks_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_AA_RANKS_REPOSITORY_H -#define EQEMU_BASE_AA_RANKS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAaRanksRepository { @@ -520,5 +520,3 @@ class BaseAaRanksRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_AA_RANKS_REPOSITORY_H diff --git a/common/repositories/base/base_account_flags_repository.h b/common/repositories/base/base_account_flags_repository.h index a40c0c3ef6..8c76b0b196 100644 --- a/common/repositories/base/base_account_flags_repository.h +++ b/common/repositories/base/base_account_flags_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ACCOUNT_FLAGS_REPOSITORY_H -#define EQEMU_BASE_ACCOUNT_FLAGS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAccountFlagsRepository { @@ -400,5 +400,3 @@ class BaseAccountFlagsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ACCOUNT_FLAGS_REPOSITORY_H diff --git a/common/repositories/base/base_account_ip_repository.h b/common/repositories/base/base_account_ip_repository.h index c61a696f00..58187baaa2 100644 --- a/common/repositories/base/base_account_ip_repository.h +++ b/common/repositories/base/base_account_ip_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ACCOUNT_IP_REPOSITORY_H -#define EQEMU_BASE_ACCOUNT_IP_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAccountIpRepository { @@ -412,5 +412,3 @@ class BaseAccountIpRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ACCOUNT_IP_REPOSITORY_H diff --git a/common/repositories/base/base_account_repository.h b/common/repositories/base/base_account_repository.h index 33b198f0e0..bdb613f25b 100644 --- a/common/repositories/base/base_account_repository.h +++ b/common/repositories/base/base_account_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ACCOUNT_REPOSITORY_H -#define EQEMU_BASE_ACCOUNT_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAccountRepository { @@ -663,5 +663,3 @@ class BaseAccountRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ACCOUNT_REPOSITORY_H diff --git a/common/repositories/base/base_account_rewards_repository.h b/common/repositories/base/base_account_rewards_repository.h index dc97053fa6..2d4317db41 100644 --- a/common/repositories/base/base_account_rewards_repository.h +++ b/common/repositories/base/base_account_rewards_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ACCOUNT_REWARDS_REPOSITORY_H -#define EQEMU_BASE_ACCOUNT_REWARDS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAccountRewardsRepository { @@ -400,5 +400,3 @@ class BaseAccountRewardsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ACCOUNT_REWARDS_REPOSITORY_H diff --git a/common/repositories/base/base_adventure_details_repository.h b/common/repositories/base/base_adventure_details_repository.h index 0a2834c7af..7874acf9ce 100644 --- a/common/repositories/base/base_adventure_details_repository.h +++ b/common/repositories/base/base_adventure_details_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ADVENTURE_DETAILS_REPOSITORY_H -#define EQEMU_BASE_ADVENTURE_DETAILS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAdventureDetailsRepository { @@ -471,5 +471,3 @@ class BaseAdventureDetailsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ADVENTURE_DETAILS_REPOSITORY_H diff --git a/common/repositories/base/base_adventure_members_repository.h b/common/repositories/base/base_adventure_members_repository.h index 4b78079d85..3a6f004c02 100644 --- a/common/repositories/base/base_adventure_members_repository.h +++ b/common/repositories/base/base_adventure_members_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ADVENTURE_MEMBERS_REPOSITORY_H -#define EQEMU_BASE_ADVENTURE_MEMBERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAdventureMembersRepository { @@ -388,5 +388,3 @@ class BaseAdventureMembersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ADVENTURE_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_adventure_stats_repository.h b/common/repositories/base/base_adventure_stats_repository.h index 3e95ca6949..f6d3d7e1e1 100644 --- a/common/repositories/base/base_adventure_stats_repository.h +++ b/common/repositories/base/base_adventure_stats_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ADVENTURE_STATS_REPOSITORY_H -#define EQEMU_BASE_ADVENTURE_STATS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAdventureStatsRepository { @@ -496,5 +496,3 @@ class BaseAdventureStatsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ADVENTURE_STATS_REPOSITORY_H diff --git a/common/repositories/base/base_adventure_template_entry_flavor_repository.h b/common/repositories/base/base_adventure_template_entry_flavor_repository.h index 1181245609..bdfa80e577 100644 --- a/common/repositories/base/base_adventure_template_entry_flavor_repository.h +++ b/common/repositories/base/base_adventure_template_entry_flavor_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ADVENTURE_TEMPLATE_ENTRY_FLAVOR_REPOSITORY_H -#define EQEMU_BASE_ADVENTURE_TEMPLATE_ENTRY_FLAVOR_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAdventureTemplateEntryFlavorRepository { @@ -388,5 +388,3 @@ class BaseAdventureTemplateEntryFlavorRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ADVENTURE_TEMPLATE_ENTRY_FLAVOR_REPOSITORY_H diff --git a/common/repositories/base/base_adventure_template_entry_repository.h b/common/repositories/base/base_adventure_template_entry_repository.h index 6c885ffb1a..30d434490b 100644 --- a/common/repositories/base/base_adventure_template_entry_repository.h +++ b/common/repositories/base/base_adventure_template_entry_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ADVENTURE_TEMPLATE_ENTRY_REPOSITORY_H -#define EQEMU_BASE_ADVENTURE_TEMPLATE_ENTRY_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAdventureTemplateEntryRepository { @@ -388,5 +388,3 @@ class BaseAdventureTemplateEntryRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ADVENTURE_TEMPLATE_ENTRY_REPOSITORY_H diff --git a/common/repositories/base/base_adventure_template_repository.h b/common/repositories/base/base_adventure_template_repository.h index 25662aeacf..fdbc9a3214 100644 --- a/common/repositories/base/base_adventure_template_repository.h +++ b/common/repositories/base/base_adventure_template_repository.h @@ -9,11 +9,11 @@ * @docs https://docs.eqemu.io/developer/repositories */ -#ifndef EQEMU_BASE_ADVENTURE_TEMPLATE_REPOSITORY_H -#define EQEMU_BASE_ADVENTURE_TEMPLATE_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAdventureTemplateRepository { @@ -757,5 +757,3 @@ class BaseAdventureTemplateRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ADVENTURE_TEMPLATE_REPOSITORY_H diff --git a/common/repositories/base/base_alternate_currency_repository.h b/common/repositories/base/base_alternate_currency_repository.h index 4c6bbc5640..a95f287895 100644 --- a/common/repositories/base/base_alternate_currency_repository.h +++ b/common/repositories/base/base_alternate_currency_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ALTERNATE_CURRENCY_REPOSITORY_H -#define EQEMU_BASE_ALTERNATE_CURRENCY_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAlternateCurrencyRepository { @@ -388,5 +388,3 @@ class BaseAlternateCurrencyRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ALTERNATE_CURRENCY_REPOSITORY_H diff --git a/common/repositories/base/base_auras_repository.h b/common/repositories/base/base_auras_repository.h index ae1c3f4593..fd279538c8 100644 --- a/common/repositories/base/base_auras_repository.h +++ b/common/repositories/base/base_auras_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_AURAS_REPOSITORY_H -#define EQEMU_BASE_AURAS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseAurasRepository { @@ -496,5 +496,3 @@ class BaseAurasRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_AURAS_REPOSITORY_H diff --git a/common/repositories/base/base_base_data_repository.h b/common/repositories/base/base_base_data_repository.h index 91d9d4bc2b..9430f757d2 100644 --- a/common/repositories/base/base_base_data_repository.h +++ b/common/repositories/base/base_base_data_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BASE_DATA_REPOSITORY_H -#define EQEMU_BASE_BASE_DATA_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBaseDataRepository { @@ -484,5 +484,3 @@ class BaseBaseDataRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BASE_DATA_REPOSITORY_H diff --git a/common/repositories/base/base_blocked_spells_repository.h b/common/repositories/base/base_blocked_spells_repository.h index 5e9e0dabe2..7732db416e 100644 --- a/common/repositories/base/base_blocked_spells_repository.h +++ b/common/repositories/base/base_blocked_spells_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BLOCKED_SPELLS_REPOSITORY_H -#define EQEMU_BASE_BLOCKED_SPELLS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBlockedSpellsRepository { @@ -555,5 +555,3 @@ class BaseBlockedSpellsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BLOCKED_SPELLS_REPOSITORY_H diff --git a/common/repositories/base/base_books_repository.h b/common/repositories/base/base_books_repository.h index 499b581cfd..46386a1b0f 100644 --- a/common/repositories/base/base_books_repository.h +++ b/common/repositories/base/base_books_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOOKS_REPOSITORY_H -#define EQEMU_BASE_BOOKS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBooksRepository { @@ -411,5 +411,3 @@ class BaseBooksRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOOKS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_blocked_buffs_repository.h b/common/repositories/base/base_bot_blocked_buffs_repository.h index 77b0ee2cdf..2b0d7fef73 100644 --- a/common/repositories/base/base_bot_blocked_buffs_repository.h +++ b/common/repositories/base/base_bot_blocked_buffs_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_BLOCKED_BUFFS_REPOSITORY_H -#define EQEMU_BASE_BOT_BLOCKED_BUFFS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotBlockedBuffsRepository { @@ -412,5 +412,3 @@ class BaseBotBlockedBuffsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_BLOCKED_BUFFS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_buffs_repository.h b/common/repositories/base/base_bot_buffs_repository.h index a4e226c498..3a027509d7 100644 --- a/common/repositories/base/base_bot_buffs_repository.h +++ b/common/repositories/base/base_bot_buffs_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_BUFFS_REPOSITORY_H -#define EQEMU_BASE_BOT_BUFFS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotBuffsRepository { @@ -603,5 +603,3 @@ class BaseBotBuffsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_BUFFS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_create_combinations_repository.h b/common/repositories/base/base_bot_create_combinations_repository.h index a759d08f45..7b4563c3f7 100644 --- a/common/repositories/base/base_bot_create_combinations_repository.h +++ b/common/repositories/base/base_bot_create_combinations_repository.h @@ -6,16 +6,15 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_CREATE_COMBINATIONS_REPOSITORY_H -#define EQEMU_BASE_BOT_CREATE_COMBINATIONS_REPOSITORY_H +#pragma once -#include "../../database.h" -#include "../../strings.h" -#include +#include "common/database.h" +#include "common/strings.h" +#include class BaseBotCreateCombinationsRepository { public: struct BotCreateCombinations { @@ -388,5 +387,3 @@ class BaseBotCreateCombinationsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_CREATE_COMBINATIONS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_data_repository.h b/common/repositories/base/base_bot_data_repository.h index 2cd4b1d041..5b7314cf2c 100644 --- a/common/repositories/base/base_bot_data_repository.h +++ b/common/repositories/base/base_bot_data_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_DATA_REPOSITORY_H -#define EQEMU_BASE_BOT_DATA_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotDataRepository { @@ -915,5 +915,3 @@ class BaseBotDataRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_DATA_REPOSITORY_H diff --git a/common/repositories/base/base_bot_group_members_repository.h b/common/repositories/base/base_bot_group_members_repository.h index 2fbd9c0caa..99d647862f 100644 --- a/common/repositories/base/base_bot_group_members_repository.h +++ b/common/repositories/base/base_bot_group_members_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_GROUP_MEMBERS_REPOSITORY_H -#define EQEMU_BASE_BOT_GROUP_MEMBERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotGroupMembersRepository { @@ -338,5 +338,3 @@ class BaseBotGroupMembersRepository { } }; - -#endif //EQEMU_BASE_BOT_GROUP_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_groups_repository.h b/common/repositories/base/base_bot_groups_repository.h index ac86e329e6..da7986b79d 100644 --- a/common/repositories/base/base_bot_groups_repository.h +++ b/common/repositories/base/base_bot_groups_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_GROUPS_REPOSITORY_H -#define EQEMU_BASE_BOT_GROUPS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotGroupsRepository { @@ -348,5 +348,3 @@ class BaseBotGroupsRepository { } }; - -#endif //EQEMU_BASE_BOT_GROUPS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_guild_members_repository.h b/common/repositories/base/base_bot_guild_members_repository.h index 1629382749..3a192d81b3 100644 --- a/common/repositories/base/base_bot_guild_members_repository.h +++ b/common/repositories/base/base_bot_guild_members_repository.h @@ -9,11 +9,11 @@ * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories */ -#ifndef EQEMU_BASE_BOT_GUILD_MEMBERS_REPOSITORY_H -#define EQEMU_BASE_BOT_GUILD_MEMBERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotGuildMembersRepository { @@ -399,5 +399,3 @@ class BaseBotGuildMembersRepository { } }; - -#endif //EQEMU_BASE_BOT_GUILD_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_heal_rotation_members_repository.h b/common/repositories/base/base_bot_heal_rotation_members_repository.h index 240161360d..a3b2bde695 100644 --- a/common/repositories/base/base_bot_heal_rotation_members_repository.h +++ b/common/repositories/base/base_bot_heal_rotation_members_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H -#define EQEMU_BASE_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotHealRotationMembersRepository { @@ -399,5 +399,3 @@ class BaseBotHealRotationMembersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_heal_rotation_targets_repository.h b/common/repositories/base/base_bot_heal_rotation_targets_repository.h index 6d8c144c10..5064208896 100644 --- a/common/repositories/base/base_bot_heal_rotation_targets_repository.h +++ b/common/repositories/base/base_bot_heal_rotation_targets_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H -#define EQEMU_BASE_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotHealRotationTargetsRepository { @@ -399,5 +399,3 @@ class BaseBotHealRotationTargetsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_heal_rotations_repository.h b/common/repositories/base/base_bot_heal_rotations_repository.h index d0fef3823f..a3d79410a3 100644 --- a/common/repositories/base/base_bot_heal_rotations_repository.h +++ b/common/repositories/base/base_bot_heal_rotations_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_HEAL_ROTATIONS_REPOSITORY_H -#define EQEMU_BASE_BOT_HEAL_ROTATIONS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotHealRotationsRepository { @@ -525,5 +525,3 @@ class BaseBotHealRotationsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_HEAL_ROTATIONS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_inspect_messages_repository.h b/common/repositories/base/base_bot_inspect_messages_repository.h index 58f6727435..2c44c67306 100644 --- a/common/repositories/base/base_bot_inspect_messages_repository.h +++ b/common/repositories/base/base_bot_inspect_messages_repository.h @@ -6,16 +6,15 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_INSPECT_MESSAGES_REPOSITORY_H -#define EQEMU_BASE_BOT_INSPECT_MESSAGES_REPOSITORY_H +#pragma once -#include "../../database.h" -#include "../../strings.h" -#include +#include "common/database.h" +#include "common/strings.h" +#include class BaseBotInspectMessagesRepository { public: struct BotInspectMessages { @@ -388,5 +387,3 @@ class BaseBotInspectMessagesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_INSPECT_MESSAGES_REPOSITORY_H diff --git a/common/repositories/base/base_bot_inventories_repository.h b/common/repositories/base/base_bot_inventories_repository.h index ef8aeb7936..97bb85e625 100644 --- a/common/repositories/base/base_bot_inventories_repository.h +++ b/common/repositories/base/base_bot_inventories_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_INVENTORIES_REPOSITORY_H -#define EQEMU_BASE_BOT_INVENTORIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotInventoriesRepository { @@ -567,5 +567,3 @@ class BaseBotInventoriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_INVENTORIES_REPOSITORY_H diff --git a/common/repositories/base/base_bot_owner_options_repository.h b/common/repositories/base/base_bot_owner_options_repository.h index acf10a04e6..6f4f23b9aa 100644 --- a/common/repositories/base/base_bot_owner_options_repository.h +++ b/common/repositories/base/base_bot_owner_options_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_OWNER_OPTIONS_REPOSITORY_H -#define EQEMU_BASE_BOT_OWNER_OPTIONS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotOwnerOptionsRepository { @@ -400,5 +400,3 @@ class BaseBotOwnerOptionsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_OWNER_OPTIONS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_pet_buffs_repository.h b/common/repositories/base/base_bot_pet_buffs_repository.h index 0d807c8b62..c0d8c03a56 100644 --- a/common/repositories/base/base_bot_pet_buffs_repository.h +++ b/common/repositories/base/base_bot_pet_buffs_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_PET_BUFFS_REPOSITORY_H -#define EQEMU_BASE_BOT_PET_BUFFS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotPetBuffsRepository { @@ -423,5 +423,3 @@ class BaseBotPetBuffsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_PET_BUFFS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_pet_inventories_repository.h b/common/repositories/base/base_bot_pet_inventories_repository.h index 0899cedd0f..4cf90a9ed7 100644 --- a/common/repositories/base/base_bot_pet_inventories_repository.h +++ b/common/repositories/base/base_bot_pet_inventories_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_PET_INVENTORIES_REPOSITORY_H -#define EQEMU_BASE_BOT_PET_INVENTORIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotPetInventoriesRepository { @@ -399,5 +399,3 @@ class BaseBotPetInventoriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_PET_INVENTORIES_REPOSITORY_H diff --git a/common/repositories/base/base_bot_pets_repository.h b/common/repositories/base/base_bot_pets_repository.h index d98af748c0..993c2900b6 100644 --- a/common/repositories/base/base_bot_pets_repository.h +++ b/common/repositories/base/base_bot_pets_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_PETS_REPOSITORY_H -#define EQEMU_BASE_BOT_PETS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotPetsRepository { @@ -435,5 +435,3 @@ class BaseBotPetsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_PETS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_settings_repository.h b/common/repositories/base/base_bot_settings_repository.h index 8fbaff17d0..44e7964acb 100644 --- a/common/repositories/base/base_bot_settings_repository.h +++ b/common/repositories/base/base_bot_settings_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_SETTINGS_REPOSITORY_H -#define EQEMU_BASE_BOT_SETTINGS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotSettingsRepository { @@ -460,5 +460,3 @@ class BaseBotSettingsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_SETTINGS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_spell_casting_chances_repository.h b/common/repositories/base/base_bot_spell_casting_chances_repository.h index cd42f49652..318941f891 100644 --- a/common/repositories/base/base_bot_spell_casting_chances_repository.h +++ b/common/repositories/base/base_bot_spell_casting_chances_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H -#define EQEMU_BASE_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotSpellCastingChancesRepository { @@ -603,5 +603,3 @@ class BaseBotSpellCastingChancesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H diff --git a/common/repositories/base/base_bot_spell_settings_repository.h b/common/repositories/base/base_bot_spell_settings_repository.h index 3cea77636e..5bb5c16153 100644 --- a/common/repositories/base/base_bot_spell_settings_repository.h +++ b/common/repositories/base/base_bot_spell_settings_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_SPELL_SETTINGS_REPOSITORY_H -#define EQEMU_BASE_BOT_SPELL_SETTINGS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotSpellSettingsRepository { @@ -447,5 +447,3 @@ class BaseBotSpellSettingsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_SPELL_SETTINGS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_spells_entries_repository.h b/common/repositories/base/base_bot_spells_entries_repository.h index f96d487457..a564fbeb46 100644 --- a/common/repositories/base/base_bot_spells_entries_repository.h +++ b/common/repositories/base/base_bot_spells_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_SPELLS_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_BOT_SPELLS_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotSpellsEntriesRepository { @@ -543,5 +543,3 @@ class BaseBotSpellsEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_SPELLS_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_bot_stances_repository.h b/common/repositories/base/base_bot_stances_repository.h index 8cb6dad570..af452b115c 100644 --- a/common/repositories/base/base_bot_stances_repository.h +++ b/common/repositories/base/base_bot_stances_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_STANCES_REPOSITORY_H -#define EQEMU_BASE_BOT_STANCES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotStancesRepository { @@ -388,5 +388,3 @@ class BaseBotStancesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_STANCES_REPOSITORY_H diff --git a/common/repositories/base/base_bot_starting_items_repository.h b/common/repositories/base/base_bot_starting_items_repository.h index 1fd030e49b..2704af4094 100644 --- a/common/repositories/base/base_bot_starting_items_repository.h +++ b/common/repositories/base/base_bot_starting_items_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_STARTING_ITEMS_REPOSITORY_H -#define EQEMU_BASE_BOT_STARTING_ITEMS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotStartingItemsRepository { @@ -567,5 +567,3 @@ class BaseBotStartingItemsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_STARTING_ITEMS_REPOSITORY_H diff --git a/common/repositories/base/base_bot_timers_repository.h b/common/repositories/base/base_bot_timers_repository.h index 7fc3ccff8a..5d22f7ddc9 100644 --- a/common/repositories/base/base_bot_timers_repository.h +++ b/common/repositories/base/base_bot_timers_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BOT_TIMERS_REPOSITORY_H -#define EQEMU_BASE_BOT_TIMERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBotTimersRepository { @@ -472,5 +472,3 @@ class BaseBotTimersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BOT_TIMERS_REPOSITORY_H diff --git a/common/repositories/base/base_bug_reports_repository.h b/common/repositories/base/base_bug_reports_repository.h index 41f22bd4e8..dca4961da9 100644 --- a/common/repositories/base/base_bug_reports_repository.h +++ b/common/repositories/base/base_bug_reports_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BUG_REPORTS_REPOSITORY_H -#define EQEMU_BASE_BUG_REPORTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBugReportsRepository { @@ -747,5 +747,3 @@ class BaseBugReportsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BUG_REPORTS_REPOSITORY_H diff --git a/common/repositories/base/base_bugs_repository.h b/common/repositories/base/base_bugs_repository.h index 51a087c073..3a8bd261bb 100644 --- a/common/repositories/base/base_bugs_repository.h +++ b/common/repositories/base/base_bugs_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BUGS_REPOSITORY_H -#define EQEMU_BASE_BUGS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBugsRepository { @@ -519,5 +519,3 @@ class BaseBugsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BUGS_REPOSITORY_H diff --git a/common/repositories/base/base_buyer_buy_lines_repository.h b/common/repositories/base/base_buyer_buy_lines_repository.h index 5c041a2899..e6b2709c4f 100644 --- a/common/repositories/base/base_buyer_buy_lines_repository.h +++ b/common/repositories/base/base_buyer_buy_lines_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BUYER_BUY_LINES_REPOSITORY_H -#define EQEMU_BASE_BUYER_BUY_LINES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBuyerBuyLinesRepository { @@ -471,5 +471,3 @@ class BaseBuyerBuyLinesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BUYER_BUY_LINES_REPOSITORY_H diff --git a/common/repositories/base/base_buyer_repository.h b/common/repositories/base/base_buyer_repository.h index 3dc52b1401..9d7315644e 100644 --- a/common/repositories/base/base_buyer_repository.h +++ b/common/repositories/base/base_buyer_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BUYER_REPOSITORY_H -#define EQEMU_BASE_BUYER_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBuyerRepository { @@ -459,5 +459,3 @@ class BaseBuyerRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BUYER_REPOSITORY_H diff --git a/common/repositories/base/base_buyer_trade_items_repository.h b/common/repositories/base/base_buyer_trade_items_repository.h index 4ef1e9459f..b2904d76a7 100644 --- a/common/repositories/base/base_buyer_trade_items_repository.h +++ b/common/repositories/base/base_buyer_trade_items_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_BUYER_TRADE_ITEMS_REPOSITORY_H -#define EQEMU_BASE_BUYER_TRADE_ITEMS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseBuyerTradeItemsRepository { @@ -435,5 +435,3 @@ class BaseBuyerTradeItemsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_BUYER_TRADE_ITEMS_REPOSITORY_H diff --git a/common/repositories/base/base_char_create_combinations_repository.h b/common/repositories/base/base_char_create_combinations_repository.h index 82caa9ba4d..b6a7a4d16c 100644 --- a/common/repositories/base/base_char_create_combinations_repository.h +++ b/common/repositories/base/base_char_create_combinations_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHAR_CREATE_COMBINATIONS_REPOSITORY_H -#define EQEMU_BASE_CHAR_CREATE_COMBINATIONS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharCreateCombinationsRepository { @@ -436,5 +436,3 @@ class BaseCharCreateCombinationsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHAR_CREATE_COMBINATIONS_REPOSITORY_H diff --git a/common/repositories/base/base_char_create_point_allocations_repository.h b/common/repositories/base/base_char_create_point_allocations_repository.h index f0e7fdeb05..74187e650a 100644 --- a/common/repositories/base/base_char_create_point_allocations_repository.h +++ b/common/repositories/base/base_char_create_point_allocations_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHAR_CREATE_POINT_ALLOCATIONS_REPOSITORY_H -#define EQEMU_BASE_CHAR_CREATE_POINT_ALLOCATIONS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharCreatePointAllocationsRepository { @@ -544,5 +544,3 @@ class BaseCharCreatePointAllocationsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHAR_CREATE_POINT_ALLOCATIONS_REPOSITORY_H diff --git a/common/repositories/base/base_char_recipe_list_repository.h b/common/repositories/base/base_char_recipe_list_repository.h index 83fb6d6091..0db11317da 100644 --- a/common/repositories/base/base_char_recipe_list_repository.h +++ b/common/repositories/base/base_char_recipe_list_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHAR_RECIPE_LIST_REPOSITORY_H -#define EQEMU_BASE_CHAR_RECIPE_LIST_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharRecipeListRepository { @@ -400,5 +400,3 @@ class BaseCharRecipeListRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHAR_RECIPE_LIST_REPOSITORY_H diff --git a/common/repositories/base/base_character_activities_repository.h b/common/repositories/base/base_character_activities_repository.h index e7b380ecc3..5e3e28a33a 100644 --- a/common/repositories/base/base_character_activities_repository.h +++ b/common/repositories/base/base_character_activities_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_ACTIVITIES_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_ACTIVITIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterActivitiesRepository { @@ -424,5 +424,3 @@ class BaseCharacterActivitiesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_ACTIVITIES_REPOSITORY_H diff --git a/common/repositories/base/base_character_alt_currency_repository.h b/common/repositories/base/base_character_alt_currency_repository.h index f4cd4d76be..a037b26f82 100644 --- a/common/repositories/base/base_character_alt_currency_repository.h +++ b/common/repositories/base/base_character_alt_currency_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_ALT_CURRENCY_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_ALT_CURRENCY_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterAltCurrencyRepository { @@ -400,5 +400,3 @@ class BaseCharacterAltCurrencyRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_ALT_CURRENCY_REPOSITORY_H diff --git a/common/repositories/base/base_character_alternate_abilities_repository.h b/common/repositories/base/base_character_alternate_abilities_repository.h index 951b0aec8a..b02aed7b5c 100644 --- a/common/repositories/base/base_character_alternate_abilities_repository.h +++ b/common/repositories/base/base_character_alternate_abilities_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterAlternateAbilitiesRepository { @@ -412,5 +412,3 @@ class BaseCharacterAlternateAbilitiesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H diff --git a/common/repositories/base/base_character_auras_repository.h b/common/repositories/base/base_character_auras_repository.h index d2389f7212..cddce43558 100644 --- a/common/repositories/base/base_character_auras_repository.h +++ b/common/repositories/base/base_character_auras_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_AURAS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_AURAS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterAurasRepository { @@ -400,5 +400,3 @@ class BaseCharacterAurasRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_AURAS_REPOSITORY_H diff --git a/common/repositories/base/base_character_bandolier_repository.h b/common/repositories/base/base_character_bandolier_repository.h index 8ad4d057f1..38dbc2c731 100644 --- a/common/repositories/base/base_character_bandolier_repository.h +++ b/common/repositories/base/base_character_bandolier_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_BANDOLIER_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_BANDOLIER_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterBandolierRepository { @@ -436,5 +436,3 @@ class BaseCharacterBandolierRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_BANDOLIER_REPOSITORY_H diff --git a/common/repositories/base/base_character_bind_repository.h b/common/repositories/base/base_character_bind_repository.h index 0dfb3eb455..3140b02655 100644 --- a/common/repositories/base/base_character_bind_repository.h +++ b/common/repositories/base/base_character_bind_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_BIND_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_BIND_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterBindRepository { @@ -459,5 +459,3 @@ class BaseCharacterBindRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_BIND_REPOSITORY_H diff --git a/common/repositories/base/base_character_buffs_repository.h b/common/repositories/base/base_character_buffs_repository.h index 775848a294..90003f7467 100644 --- a/common/repositories/base/base_character_buffs_repository.h +++ b/common/repositories/base/base_character_buffs_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_BUFFS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_BUFFS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterBuffsRepository { @@ -568,5 +568,3 @@ class BaseCharacterBuffsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_BUFFS_REPOSITORY_H diff --git a/common/repositories/base/base_character_corpse_items_repository.h b/common/repositories/base/base_character_corpse_items_repository.h index 87cb4fa81c..3fc5aa8421 100644 --- a/common/repositories/base/base_character_corpse_items_repository.h +++ b/common/repositories/base/base_character_corpse_items_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_CORPSE_ITEMS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_CORPSE_ITEMS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterCorpseItemsRepository { @@ -544,5 +544,3 @@ class BaseCharacterCorpseItemsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_CORPSE_ITEMS_REPOSITORY_H diff --git a/common/repositories/base/base_character_corpses_repository.h b/common/repositories/base/base_character_corpses_repository.h index 2c61799ea6..814f7ecda2 100644 --- a/common/repositories/base/base_character_corpses_repository.h +++ b/common/repositories/base/base_character_corpses_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_CORPSES_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_CORPSES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterCorpsesRepository { @@ -987,5 +987,3 @@ class BaseCharacterCorpsesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_CORPSES_REPOSITORY_H diff --git a/common/repositories/base/base_character_currency_repository.h b/common/repositories/base/base_character_currency_repository.h index c0ef4ed1f8..bf0a19adca 100644 --- a/common/repositories/base/base_character_currency_repository.h +++ b/common/repositories/base/base_character_currency_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_CURRENCY_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_CURRENCY_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterCurrencyRepository { @@ -568,5 +568,3 @@ class BaseCharacterCurrencyRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_CURRENCY_REPOSITORY_H diff --git a/common/repositories/base/base_character_data_repository.h b/common/repositories/base/base_character_data_repository.h index 85374f7fc3..0eab216a01 100644 --- a/common/repositories/base/base_character_data_repository.h +++ b/common/repositories/base/base_character_data_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_DATA_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_DATA_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterDataRepository { @@ -1635,5 +1635,3 @@ class BaseCharacterDataRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_DATA_REPOSITORY_H diff --git a/common/repositories/base/base_character_disciplines_repository.h b/common/repositories/base/base_character_disciplines_repository.h index 931d522f9d..b03a9eaa53 100644 --- a/common/repositories/base/base_character_disciplines_repository.h +++ b/common/repositories/base/base_character_disciplines_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_DISCIPLINES_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_DISCIPLINES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterDisciplinesRepository { @@ -400,5 +400,3 @@ class BaseCharacterDisciplinesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_DISCIPLINES_REPOSITORY_H diff --git a/common/repositories/base/base_character_evolving_items_repository.h b/common/repositories/base/base_character_evolving_items_repository.h index 9aa6c1773a..0d3fd01003 100644 --- a/common/repositories/base/base_character_evolving_items_repository.h +++ b/common/repositories/base/base_character_evolving_items_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_EVOLVING_ITEMS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_EVOLVING_ITEMS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterEvolvingItemsRepository { @@ -471,5 +471,3 @@ class BaseCharacterEvolvingItemsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_EVOLVING_ITEMS_REPOSITORY_H diff --git a/common/repositories/base/base_character_exp_modifiers_repository.h b/common/repositories/base/base_character_exp_modifiers_repository.h index e11f242949..5203c0c162 100644 --- a/common/repositories/base/base_character_exp_modifiers_repository.h +++ b/common/repositories/base/base_character_exp_modifiers_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_EXP_MODIFIERS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_EXP_MODIFIERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterExpModifiersRepository { @@ -424,5 +424,3 @@ class BaseCharacterExpModifiersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_EXP_MODIFIERS_REPOSITORY_H diff --git a/common/repositories/base/base_character_expedition_lockouts_repository.h b/common/repositories/base/base_character_expedition_lockouts_repository.h index 35d34502a6..8b78859f5d 100644 --- a/common/repositories/base/base_character_expedition_lockouts_repository.h +++ b/common/repositories/base/base_character_expedition_lockouts_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterExpeditionLockoutsRepository { @@ -447,5 +447,3 @@ class BaseCharacterExpeditionLockoutsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H diff --git a/common/repositories/base/base_character_inspect_messages_repository.h b/common/repositories/base/base_character_inspect_messages_repository.h index b20e510d2b..c4d6961bf0 100644 --- a/common/repositories/base/base_character_inspect_messages_repository.h +++ b/common/repositories/base/base_character_inspect_messages_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_INSPECT_MESSAGES_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_INSPECT_MESSAGES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterInspectMessagesRepository { @@ -388,5 +388,3 @@ class BaseCharacterInspectMessagesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_INSPECT_MESSAGES_REPOSITORY_H diff --git a/common/repositories/base/base_character_instance_safereturns_repository.h b/common/repositories/base/base_character_instance_safereturns_repository.h index 0501d5c291..2019637494 100644 --- a/common/repositories/base/base_character_instance_safereturns_repository.h +++ b/common/repositories/base/base_character_instance_safereturns_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_INSTANCE_SAFERETURNS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_INSTANCE_SAFERETURNS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterInstanceSafereturnsRepository { @@ -471,5 +471,3 @@ class BaseCharacterInstanceSafereturnsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_INSTANCE_SAFERETURNS_REPOSITORY_H diff --git a/common/repositories/base/base_character_item_recast_repository.h b/common/repositories/base/base_character_item_recast_repository.h index 3e16755b69..c144ed8a38 100644 --- a/common/repositories/base/base_character_item_recast_repository.h +++ b/common/repositories/base/base_character_item_recast_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_ITEM_RECAST_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_ITEM_RECAST_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterItemRecastRepository { @@ -400,5 +400,3 @@ class BaseCharacterItemRecastRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_ITEM_RECAST_REPOSITORY_H diff --git a/common/repositories/base/base_character_languages_repository.h b/common/repositories/base/base_character_languages_repository.h index 7942d80f5a..7007f98c78 100644 --- a/common/repositories/base/base_character_languages_repository.h +++ b/common/repositories/base/base_character_languages_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_LANGUAGES_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_LANGUAGES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterLanguagesRepository { @@ -399,5 +399,3 @@ class BaseCharacterLanguagesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_LANGUAGES_REPOSITORY_H diff --git a/common/repositories/base/base_character_leadership_abilities_repository.h b/common/repositories/base/base_character_leadership_abilities_repository.h index 8aad02e908..bd2557fb71 100644 --- a/common/repositories/base/base_character_leadership_abilities_repository.h +++ b/common/repositories/base/base_character_leadership_abilities_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterLeadershipAbilitiesRepository { @@ -400,5 +400,3 @@ class BaseCharacterLeadershipAbilitiesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H diff --git a/common/repositories/base/base_character_material_repository.h b/common/repositories/base/base_character_material_repository.h index 3f9d8a8cb8..1de976453b 100644 --- a/common/repositories/base/base_character_material_repository.h +++ b/common/repositories/base/base_character_material_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_MATERIAL_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_MATERIAL_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterMaterialRepository { @@ -447,5 +447,3 @@ class BaseCharacterMaterialRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_MATERIAL_REPOSITORY_H diff --git a/common/repositories/base/base_character_memmed_spells_repository.h b/common/repositories/base/base_character_memmed_spells_repository.h index 440b405837..6c824a6a6a 100644 --- a/common/repositories/base/base_character_memmed_spells_repository.h +++ b/common/repositories/base/base_character_memmed_spells_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_MEMMED_SPELLS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_MEMMED_SPELLS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterMemmedSpellsRepository { @@ -400,5 +400,3 @@ class BaseCharacterMemmedSpellsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_MEMMED_SPELLS_REPOSITORY_H diff --git a/common/repositories/base/base_character_parcels_containers_repository.h b/common/repositories/base/base_character_parcels_containers_repository.h index 12ca611b75..668fc9e30b 100644 --- a/common/repositories/base/base_character_parcels_containers_repository.h +++ b/common/repositories/base/base_character_parcels_containers_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_PARCELS_CONTAINERS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_PARCELS_CONTAINERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterParcelsContainersRepository { @@ -507,5 +507,3 @@ class BaseCharacterParcelsContainersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_PARCELS_CONTAINERS_REPOSITORY_H diff --git a/common/repositories/base/base_character_parcels_repository.h b/common/repositories/base/base_character_parcels_repository.h index df7242aedd..bc5934c7d5 100644 --- a/common/repositories/base/base_character_parcels_repository.h +++ b/common/repositories/base/base_character_parcels_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_PARCELS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_PARCELS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterParcelsRepository { @@ -543,5 +543,3 @@ class BaseCharacterParcelsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_PARCELS_REPOSITORY_H diff --git a/common/repositories/base/base_character_peqzone_flags_repository.h b/common/repositories/base/base_character_peqzone_flags_repository.h index a4fe7f1cd2..ab6d128b3f 100644 --- a/common/repositories/base/base_character_peqzone_flags_repository.h +++ b/common/repositories/base/base_character_peqzone_flags_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_PEQZONE_FLAGS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_PEQZONE_FLAGS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterPeqzoneFlagsRepository { @@ -388,5 +388,3 @@ class BaseCharacterPeqzoneFlagsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_PEQZONE_FLAGS_REPOSITORY_H diff --git a/common/repositories/base/base_character_pet_buffs_repository.h b/common/repositories/base/base_character_pet_buffs_repository.h index 262a40e3a1..74f0b1ec40 100644 --- a/common/repositories/base/base_character_pet_buffs_repository.h +++ b/common/repositories/base/base_character_pet_buffs_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_PET_BUFFS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_PET_BUFFS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterPetBuffsRepository { @@ -496,5 +496,3 @@ class BaseCharacterPetBuffsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_PET_BUFFS_REPOSITORY_H diff --git a/common/repositories/base/base_character_pet_info_repository.h b/common/repositories/base/base_character_pet_info_repository.h index d176cf65a8..c3037d0177 100644 --- a/common/repositories/base/base_character_pet_info_repository.h +++ b/common/repositories/base/base_character_pet_info_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_PET_INFO_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_PET_INFO_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterPetInfoRepository { @@ -472,5 +472,3 @@ class BaseCharacterPetInfoRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_PET_INFO_REPOSITORY_H diff --git a/common/repositories/base/base_character_pet_inventory_repository.h b/common/repositories/base/base_character_pet_inventory_repository.h index d9e590663f..15292a517d 100644 --- a/common/repositories/base/base_character_pet_inventory_repository.h +++ b/common/repositories/base/base_character_pet_inventory_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_PET_INVENTORY_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_PET_INVENTORY_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterPetInventoryRepository { @@ -412,5 +412,3 @@ class BaseCharacterPetInventoryRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_PET_INVENTORY_REPOSITORY_H diff --git a/common/repositories/base/base_character_pet_name_repository.h b/common/repositories/base/base_character_pet_name_repository.h index 59a8a572f2..69585ab43a 100644 --- a/common/repositories/base/base_character_pet_name_repository.h +++ b/common/repositories/base/base_character_pet_name_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_PET_NAME_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_PET_NAME_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterPetNameRepository { @@ -388,5 +388,3 @@ class BaseCharacterPetNameRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_PET_NAME_REPOSITORY_H diff --git a/common/repositories/base/base_character_potionbelt_repository.h b/common/repositories/base/base_character_potionbelt_repository.h index d150c377df..acf710c37a 100644 --- a/common/repositories/base/base_character_potionbelt_repository.h +++ b/common/repositories/base/base_character_potionbelt_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_POTIONBELT_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_POTIONBELT_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterPotionbeltRepository { @@ -412,5 +412,3 @@ class BaseCharacterPotionbeltRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_POTIONBELT_REPOSITORY_H diff --git a/common/repositories/base/base_character_skills_repository.h b/common/repositories/base/base_character_skills_repository.h index 6b2f579ab0..a4620eb156 100644 --- a/common/repositories/base/base_character_skills_repository.h +++ b/common/repositories/base/base_character_skills_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_SKILLS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_SKILLS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterSkillsRepository { @@ -399,5 +399,3 @@ class BaseCharacterSkillsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_SKILLS_REPOSITORY_H diff --git a/common/repositories/base/base_character_spells_repository.h b/common/repositories/base/base_character_spells_repository.h index 7b313644dd..58179ad3aa 100644 --- a/common/repositories/base/base_character_spells_repository.h +++ b/common/repositories/base/base_character_spells_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_SPELLS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_SPELLS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterSpellsRepository { @@ -399,5 +399,3 @@ class BaseCharacterSpellsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_SPELLS_REPOSITORY_H diff --git a/common/repositories/base/base_character_stats_record_repository.h b/common/repositories/base/base_character_stats_record_repository.h index aac41280a4..141d7f61ba 100644 --- a/common/repositories/base/base_character_stats_record_repository.h +++ b/common/repositories/base/base_character_stats_record_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_STATS_RECORD_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_STATS_RECORD_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterStatsRecordRepository { @@ -1264,5 +1264,3 @@ class BaseCharacterStatsRecordRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_STATS_RECORD_REPOSITORY_H diff --git a/common/repositories/base/base_character_task_timers_repository.h b/common/repositories/base/base_character_task_timers_repository.h index 60240a8a42..6d9880bd08 100644 --- a/common/repositories/base/base_character_task_timers_repository.h +++ b/common/repositories/base/base_character_task_timers_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_TASK_TIMERS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_TASK_TIMERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterTaskTimersRepository { @@ -435,5 +435,3 @@ class BaseCharacterTaskTimersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_TASK_TIMERS_REPOSITORY_H diff --git a/common/repositories/base/base_character_tasks_repository.h b/common/repositories/base/base_character_tasks_repository.h index e28e5f7dfb..1b9154cd38 100644 --- a/common/repositories/base/base_character_tasks_repository.h +++ b/common/repositories/base/base_character_tasks_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_TASKS_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_TASKS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterTasksRepository { @@ -436,5 +436,3 @@ class BaseCharacterTasksRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_TASKS_REPOSITORY_H diff --git a/common/repositories/base/base_character_tribute_repository.h b/common/repositories/base/base_character_tribute_repository.h index 53edda1d4c..2c9a51c3bf 100644 --- a/common/repositories/base/base_character_tribute_repository.h +++ b/common/repositories/base/base_character_tribute_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHARACTER_TRIBUTE_REPOSITORY_H -#define EQEMU_BASE_CHARACTER_TRIBUTE_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCharacterTributeRepository { @@ -411,5 +411,3 @@ class BaseCharacterTributeRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHARACTER_TRIBUTE_REPOSITORY_H diff --git a/common/repositories/base/base_chatchannel_reserved_names_repository.h b/common/repositories/base/base_chatchannel_reserved_names_repository.h index 7a8d715d8a..674434677a 100644 --- a/common/repositories/base/base_chatchannel_reserved_names_repository.h +++ b/common/repositories/base/base_chatchannel_reserved_names_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H -#define EQEMU_BASE_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseChatchannelReservedNamesRepository { @@ -387,5 +387,3 @@ class BaseChatchannelReservedNamesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H diff --git a/common/repositories/base/base_chatchannels_repository.h b/common/repositories/base/base_chatchannels_repository.h index 4bea08c82a..29bba05028 100644 --- a/common/repositories/base/base_chatchannels_repository.h +++ b/common/repositories/base/base_chatchannels_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CHATCHANNELS_REPOSITORY_H -#define EQEMU_BASE_CHATCHANNELS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseChatchannelsRepository { @@ -423,5 +423,3 @@ class BaseChatchannelsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CHATCHANNELS_REPOSITORY_H diff --git a/common/repositories/base/base_command_subsettings_repository.h b/common/repositories/base/base_command_subsettings_repository.h index d12bf22508..ef5b030ea4 100644 --- a/common/repositories/base/base_command_subsettings_repository.h +++ b/common/repositories/base/base_command_subsettings_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_COMMAND_SUBSETTINGS_REPOSITORY_H -#define EQEMU_BASE_COMMAND_SUBSETTINGS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCommandSubsettingsRepository { @@ -423,5 +423,3 @@ class BaseCommandSubsettingsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_COMMAND_SUBSETTINGS_REPOSITORY_H diff --git a/common/repositories/base/base_completed_shared_task_activity_state_repository.h b/common/repositories/base/base_completed_shared_task_activity_state_repository.h index 9de6c4696b..d97f7b4583 100644 --- a/common/repositories/base/base_completed_shared_task_activity_state_repository.h +++ b/common/repositories/base/base_completed_shared_task_activity_state_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_COMPLETED_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H -#define EQEMU_BASE_COMPLETED_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCompletedSharedTaskActivityStateRepository { @@ -424,5 +424,3 @@ class BaseCompletedSharedTaskActivityStateRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_COMPLETED_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H diff --git a/common/repositories/base/base_completed_shared_task_members_repository.h b/common/repositories/base/base_completed_shared_task_members_repository.h index a748097f8e..a476dfc23f 100644 --- a/common/repositories/base/base_completed_shared_task_members_repository.h +++ b/common/repositories/base/base_completed_shared_task_members_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_COMPLETED_SHARED_TASK_MEMBERS_REPOSITORY_H -#define EQEMU_BASE_COMPLETED_SHARED_TASK_MEMBERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCompletedSharedTaskMembersRepository { @@ -400,5 +400,3 @@ class BaseCompletedSharedTaskMembersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_COMPLETED_SHARED_TASK_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_completed_shared_tasks_repository.h b/common/repositories/base/base_completed_shared_tasks_repository.h index 7ebc6cb07c..ad90a02208 100644 --- a/common/repositories/base/base_completed_shared_tasks_repository.h +++ b/common/repositories/base/base_completed_shared_tasks_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_COMPLETED_SHARED_TASKS_REPOSITORY_H -#define EQEMU_BASE_COMPLETED_SHARED_TASKS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCompletedSharedTasksRepository { @@ -436,5 +436,3 @@ class BaseCompletedSharedTasksRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_COMPLETED_SHARED_TASKS_REPOSITORY_H diff --git a/common/repositories/base/base_completed_tasks_repository.h b/common/repositories/base/base_completed_tasks_repository.h index 1e936d65ed..33870e3638 100644 --- a/common/repositories/base/base_completed_tasks_repository.h +++ b/common/repositories/base/base_completed_tasks_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_COMPLETED_TASKS_REPOSITORY_H -#define EQEMU_BASE_COMPLETED_TASKS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseCompletedTasksRepository { @@ -412,5 +412,3 @@ class BaseCompletedTasksRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_COMPLETED_TASKS_REPOSITORY_H diff --git a/common/repositories/base/base_content_flags_repository.h b/common/repositories/base/base_content_flags_repository.h index 339d7a95c8..7b89bf4326 100644 --- a/common/repositories/base/base_content_flags_repository.h +++ b/common/repositories/base/base_content_flags_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_CONTENT_FLAGS_REPOSITORY_H -#define EQEMU_BASE_CONTENT_FLAGS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseContentFlagsRepository { @@ -411,5 +411,3 @@ class BaseContentFlagsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_CONTENT_FLAGS_REPOSITORY_H diff --git a/common/repositories/base/base_damageshieldtypes_repository.h b/common/repositories/base/base_damageshieldtypes_repository.h index 775c7c6f8d..b373ebc5ec 100644 --- a/common/repositories/base/base_damageshieldtypes_repository.h +++ b/common/repositories/base/base_damageshieldtypes_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_DAMAGESHIELDTYPES_REPOSITORY_H -#define EQEMU_BASE_DAMAGESHIELDTYPES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseDamageshieldtypesRepository { @@ -388,5 +388,3 @@ class BaseDamageshieldtypesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_DAMAGESHIELDTYPES_REPOSITORY_H diff --git a/common/repositories/base/base_data_buckets_repository.h b/common/repositories/base/base_data_buckets_repository.h index e111eaabfb..54e4d4c99a 100644 --- a/common/repositories/base/base_data_buckets_repository.h +++ b/common/repositories/base/base_data_buckets_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_DATA_BUCKETS_REPOSITORY_H -#define EQEMU_BASE_DATA_BUCKETS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include #include class BaseDataBucketsRepository { @@ -501,5 +501,3 @@ class BaseDataBucketsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_DATA_BUCKETS_REPOSITORY_H diff --git a/common/repositories/base/base_db_str_repository.h b/common/repositories/base/base_db_str_repository.h index f520e1ca95..bb6a8b84bb 100644 --- a/common/repositories/base/base_db_str_repository.h +++ b/common/repositories/base/base_db_str_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_DB_STR_REPOSITORY_H -#define EQEMU_BASE_DB_STR_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseDbStrRepository { @@ -400,5 +400,3 @@ class BaseDbStrRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_DB_STR_REPOSITORY_H diff --git a/common/repositories/base/base_discord_webhooks_repository.h b/common/repositories/base/base_discord_webhooks_repository.h index 90dbf4afec..c4f0244701 100644 --- a/common/repositories/base/base_discord_webhooks_repository.h +++ b/common/repositories/base/base_discord_webhooks_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_DISCORD_WEBHOOKS_REPOSITORY_H -#define EQEMU_BASE_DISCORD_WEBHOOKS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseDiscordWebhooksRepository { @@ -423,5 +423,3 @@ class BaseDiscordWebhooksRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_DISCORD_WEBHOOKS_REPOSITORY_H diff --git a/common/repositories/base/base_discovered_items_repository.h b/common/repositories/base/base_discovered_items_repository.h index cdb8a92b1c..d6f08d503a 100644 --- a/common/repositories/base/base_discovered_items_repository.h +++ b/common/repositories/base/base_discovered_items_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_DISCOVERED_ITEMS_REPOSITORY_H -#define EQEMU_BASE_DISCOVERED_ITEMS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseDiscoveredItemsRepository { @@ -412,5 +412,3 @@ class BaseDiscoveredItemsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_DISCOVERED_ITEMS_REPOSITORY_H diff --git a/common/repositories/base/base_doors_repository.h b/common/repositories/base/base_doors_repository.h index bab8fb8335..8887b4fe9e 100644 --- a/common/repositories/base/base_doors_repository.h +++ b/common/repositories/base/base_doors_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_DOORS_REPOSITORY_H -#define EQEMU_BASE_DOORS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseDoorsRepository { @@ -807,5 +807,3 @@ class BaseDoorsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_DOORS_REPOSITORY_H diff --git a/common/repositories/base/base_dynamic_zone_lockouts_repository.h b/common/repositories/base/base_dynamic_zone_lockouts_repository.h index b787d6c3bd..1e1f5268f3 100644 --- a/common/repositories/base/base_dynamic_zone_lockouts_repository.h +++ b/common/repositories/base/base_dynamic_zone_lockouts_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H -#define EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseDynamicZoneLockoutsRepository { @@ -435,5 +435,3 @@ class BaseDynamicZoneLockoutsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H diff --git a/common/repositories/base/base_dynamic_zone_members_repository.h b/common/repositories/base/base_dynamic_zone_members_repository.h index 807300378d..ce7d0e8887 100644 --- a/common/repositories/base/base_dynamic_zone_members_repository.h +++ b/common/repositories/base/base_dynamic_zone_members_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H -#define EQEMU_BASE_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseDynamicZoneMembersRepository { @@ -399,5 +399,3 @@ class BaseDynamicZoneMembersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_dynamic_zone_templates_repository.h b/common/repositories/base/base_dynamic_zone_templates_repository.h index 56c701447e..c1a59058d1 100644 --- a/common/repositories/base/base_dynamic_zone_templates_repository.h +++ b/common/repositories/base/base_dynamic_zone_templates_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H -#define EQEMU_BASE_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseDynamicZoneTemplatesRepository { @@ -627,5 +627,3 @@ class BaseDynamicZoneTemplatesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/base/base_dynamic_zones_repository.h b/common/repositories/base/base_dynamic_zones_repository.h index d9231c54e7..921b333e5d 100644 --- a/common/repositories/base/base_dynamic_zones_repository.h +++ b/common/repositories/base/base_dynamic_zones_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_DYNAMIC_ZONES_REPOSITORY_H -#define EQEMU_BASE_DYNAMIC_ZONES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseDynamicZonesRepository { @@ -663,5 +663,3 @@ class BaseDynamicZonesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_DYNAMIC_ZONES_REPOSITORY_H diff --git a/common/repositories/base/base_faction_association_repository.h b/common/repositories/base/base_faction_association_repository.h index 0fd1a6e277..df5a1139ce 100644 --- a/common/repositories/base/base_faction_association_repository.h +++ b/common/repositories/base/base_faction_association_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_FACTION_ASSOCIATION_REPOSITORY_H -#define EQEMU_BASE_FACTION_ASSOCIATION_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseFactionAssociationRepository { @@ -616,5 +616,3 @@ class BaseFactionAssociationRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_FACTION_ASSOCIATION_REPOSITORY_H diff --git a/common/repositories/base/base_faction_base_data_repository.h b/common/repositories/base/base_faction_base_data_repository.h index 1455fe53bf..1d05928713 100644 --- a/common/repositories/base/base_faction_base_data_repository.h +++ b/common/repositories/base/base_faction_base_data_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_FACTION_BASE_DATA_REPOSITORY_H -#define EQEMU_BASE_FACTION_BASE_DATA_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseFactionBaseDataRepository { @@ -436,5 +436,3 @@ class BaseFactionBaseDataRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_FACTION_BASE_DATA_REPOSITORY_H diff --git a/common/repositories/base/base_faction_list_mod_repository.h b/common/repositories/base/base_faction_list_mod_repository.h index d778322bc8..ab41df8741 100644 --- a/common/repositories/base/base_faction_list_mod_repository.h +++ b/common/repositories/base/base_faction_list_mod_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_FACTION_LIST_MOD_REPOSITORY_H -#define EQEMU_BASE_FACTION_LIST_MOD_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseFactionListModRepository { @@ -411,5 +411,3 @@ class BaseFactionListModRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_FACTION_LIST_MOD_REPOSITORY_H diff --git a/common/repositories/base/base_faction_list_repository.h b/common/repositories/base/base_faction_list_repository.h index 30ebb07544..411745a186 100644 --- a/common/repositories/base/base_faction_list_repository.h +++ b/common/repositories/base/base_faction_list_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_FACTION_LIST_REPOSITORY_H -#define EQEMU_BASE_FACTION_LIST_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseFactionListRepository { @@ -400,5 +400,3 @@ class BaseFactionListRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_FACTION_LIST_REPOSITORY_H diff --git a/common/repositories/base/base_faction_values_repository.h b/common/repositories/base/base_faction_values_repository.h index fdaeb1903c..b5591c917b 100644 --- a/common/repositories/base/base_faction_values_repository.h +++ b/common/repositories/base/base_faction_values_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_FACTION_VALUES_REPOSITORY_H -#define EQEMU_BASE_FACTION_VALUES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseFactionValuesRepository { @@ -412,5 +412,3 @@ class BaseFactionValuesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_FACTION_VALUES_REPOSITORY_H diff --git a/common/repositories/base/base_fishing_repository.h b/common/repositories/base/base_fishing_repository.h index fde25e7bc8..6666ab5cc5 100644 --- a/common/repositories/base/base_fishing_repository.h +++ b/common/repositories/base/base_fishing_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_FISHING_REPOSITORY_H -#define EQEMU_BASE_FISHING_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseFishingRepository { @@ -495,5 +495,3 @@ class BaseFishingRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_FISHING_REPOSITORY_H diff --git a/common/repositories/base/base_forage_repository.h b/common/repositories/base/base_forage_repository.h index 1fb1df3e46..e855dace26 100644 --- a/common/repositories/base/base_forage_repository.h +++ b/common/repositories/base/base_forage_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_FORAGE_REPOSITORY_H -#define EQEMU_BASE_FORAGE_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseForageRepository { @@ -471,5 +471,3 @@ class BaseForageRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_FORAGE_REPOSITORY_H diff --git a/common/repositories/base/base_friends_repository.h b/common/repositories/base/base_friends_repository.h index 84d7ba5940..7c5ed52d85 100644 --- a/common/repositories/base/base_friends_repository.h +++ b/common/repositories/base/base_friends_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_FRIENDS_REPOSITORY_H -#define EQEMU_BASE_FRIENDS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseFriendsRepository { @@ -400,5 +400,3 @@ class BaseFriendsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_FRIENDS_REPOSITORY_H diff --git a/common/repositories/base/base_global_loot_repository.h b/common/repositories/base/base_global_loot_repository.h index 7128207be9..4976d0cdf6 100644 --- a/common/repositories/base/base_global_loot_repository.h +++ b/common/repositories/base/base_global_loot_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GLOBAL_LOOT_REPOSITORY_H -#define EQEMU_BASE_GLOBAL_LOOT_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseGlobalLootRepository { @@ -567,5 +567,3 @@ class BaseGlobalLootRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GLOBAL_LOOT_REPOSITORY_H diff --git a/common/repositories/base/base_gm_ips_repository.h b/common/repositories/base/base_gm_ips_repository.h index eeba74d34c..411396188a 100644 --- a/common/repositories/base/base_gm_ips_repository.h +++ b/common/repositories/base/base_gm_ips_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GM_IPS_REPOSITORY_H -#define EQEMU_BASE_GM_IPS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseGmIpsRepository { @@ -400,5 +400,3 @@ class BaseGmIpsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GM_IPS_REPOSITORY_H diff --git a/common/repositories/base/base_graveyard_repository.h b/common/repositories/base/base_graveyard_repository.h index 139e469aaf..8635e63497 100644 --- a/common/repositories/base/base_graveyard_repository.h +++ b/common/repositories/base/base_graveyard_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GRAVEYARD_REPOSITORY_H -#define EQEMU_BASE_GRAVEYARD_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseGraveyardRepository { @@ -435,5 +435,3 @@ class BaseGraveyardRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GRAVEYARD_REPOSITORY_H diff --git a/common/repositories/base/base_grid_entries_repository.h b/common/repositories/base/base_grid_entries_repository.h index dbfb6adfda..f048db6437 100644 --- a/common/repositories/base/base_grid_entries_repository.h +++ b/common/repositories/base/base_grid_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GRID_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_GRID_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseGridEntriesRepository { @@ -472,5 +472,3 @@ class BaseGridEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GRID_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_grid_repository.h b/common/repositories/base/base_grid_repository.h index b7bbe21928..623f1c8b77 100644 --- a/common/repositories/base/base_grid_repository.h +++ b/common/repositories/base/base_grid_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GRID_REPOSITORY_H -#define EQEMU_BASE_GRID_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseGridRepository { @@ -412,5 +412,3 @@ class BaseGridRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GRID_REPOSITORY_H diff --git a/common/repositories/base/base_ground_spawns_repository.h b/common/repositories/base/base_ground_spawns_repository.h index ac8cbc2ec7..83d3d2722f 100644 --- a/common/repositories/base/base_ground_spawns_repository.h +++ b/common/repositories/base/base_ground_spawns_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GROUND_SPAWNS_REPOSITORY_H -#define EQEMU_BASE_GROUND_SPAWNS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseGroundSpawnsRepository { @@ -591,5 +591,3 @@ class BaseGroundSpawnsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GROUND_SPAWNS_REPOSITORY_H diff --git a/common/repositories/base/base_group_id_repository.h b/common/repositories/base/base_group_id_repository.h index 689d5ae707..78211e437e 100644 --- a/common/repositories/base/base_group_id_repository.h +++ b/common/repositories/base/base_group_id_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GROUP_ID_REPOSITORY_H -#define EQEMU_BASE_GROUP_ID_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseGroupIdRepository { @@ -424,5 +424,3 @@ class BaseGroupIdRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GROUP_ID_REPOSITORY_H diff --git a/common/repositories/base/base_group_leaders_repository.h b/common/repositories/base/base_group_leaders_repository.h index 6d80fb2f18..3a61ddd5cf 100644 --- a/common/repositories/base/base_group_leaders_repository.h +++ b/common/repositories/base/base_group_leaders_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GROUP_LEADERS_REPOSITORY_H -#define EQEMU_BASE_GROUP_LEADERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseGroupLeadersRepository { @@ -472,5 +472,3 @@ class BaseGroupLeadersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GROUP_LEADERS_REPOSITORY_H diff --git a/common/repositories/base/base_guild_bank_repository.h b/common/repositories/base/base_guild_bank_repository.h index a857987ac5..a8fc38a255 100644 --- a/common/repositories/base/base_guild_bank_repository.h +++ b/common/repositories/base/base_guild_bank_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GUILD_BANK_REPOSITORY_H -#define EQEMU_BASE_GUILD_BANK_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseGuildBankRepository { @@ -543,5 +543,3 @@ class BaseGuildBankRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GUILD_BANK_REPOSITORY_H diff --git a/common/repositories/base/base_guild_members_repository.h b/common/repositories/base/base_guild_members_repository.h index ae60596302..fe7946b533 100644 --- a/common/repositories/base/base_guild_members_repository.h +++ b/common/repositories/base/base_guild_members_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GUILD_MEMBERS_REPOSITORY_H -#define EQEMU_BASE_GUILD_MEMBERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseGuildMembersRepository { @@ -484,5 +484,3 @@ class BaseGuildMembersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GUILD_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_guild_permissions_repository.h b/common/repositories/base/base_guild_permissions_repository.h index 57bffb6777..c435b3ba1e 100644 --- a/common/repositories/base/base_guild_permissions_repository.h +++ b/common/repositories/base/base_guild_permissions_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GUILD_PERMISSIONS_REPOSITORY_H -#define EQEMU_BASE_GUILD_PERMISSIONS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -412,5 +412,3 @@ class BaseGuildPermissionsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GUILD_PERMISSIONS_REPOSITORY_H diff --git a/common/repositories/base/base_guild_ranks_repository.h b/common/repositories/base/base_guild_ranks_repository.h index 67b4102685..2e4cedefe9 100644 --- a/common/repositories/base/base_guild_ranks_repository.h +++ b/common/repositories/base/base_guild_ranks_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GUILD_RANKS_REPOSITORY_H -#define EQEMU_BASE_GUILD_RANKS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseGuildRanksRepository { @@ -400,5 +400,3 @@ class BaseGuildRanksRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GUILD_RANKS_REPOSITORY_H diff --git a/common/repositories/base/base_guild_relations_repository.h b/common/repositories/base/base_guild_relations_repository.h index 567eaeff51..9957f0b003 100644 --- a/common/repositories/base/base_guild_relations_repository.h +++ b/common/repositories/base/base_guild_relations_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GUILD_RELATIONS_REPOSITORY_H -#define EQEMU_BASE_GUILD_RELATIONS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseGuildRelationsRepository { @@ -400,5 +400,3 @@ class BaseGuildRelationsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GUILD_RELATIONS_REPOSITORY_H diff --git a/common/repositories/base/base_guild_tributes_repository.h b/common/repositories/base/base_guild_tributes_repository.h index be74e12b6e..13cffce11f 100644 --- a/common/repositories/base/base_guild_tributes_repository.h +++ b/common/repositories/base/base_guild_tributes_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GUILD_TRIBUTES_REPOSITORY_H -#define EQEMU_BASE_GUILD_TRIBUTES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -449,5 +449,3 @@ class BaseGuildTributesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GUILD_TRIBUTES_REPOSITORY_H diff --git a/common/repositories/base/base_guilds_repository.h b/common/repositories/base/base_guilds_repository.h index 61745b14f3..df7b2d40c2 100644 --- a/common/repositories/base/base_guilds_repository.h +++ b/common/repositories/base/base_guilds_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_GUILDS_REPOSITORY_H -#define EQEMU_BASE_GUILDS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -484,5 +484,3 @@ class BaseGuildsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_GUILDS_REPOSITORY_H diff --git a/common/repositories/base/base_horses_repository.h b/common/repositories/base/base_horses_repository.h index 5c49b99675..172b279fd2 100644 --- a/common/repositories/base/base_horses_repository.h +++ b/common/repositories/base/base_horses_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_HORSES_REPOSITORY_H -#define EQEMU_BASE_HORSES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseHorsesRepository { @@ -459,5 +459,3 @@ class BaseHorsesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_HORSES_REPOSITORY_H diff --git a/common/repositories/base/base_instance_list_player_repository.h b/common/repositories/base/base_instance_list_player_repository.h index 28e4879985..6e16b800d3 100644 --- a/common/repositories/base/base_instance_list_player_repository.h +++ b/common/repositories/base/base_instance_list_player_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_INSTANCE_LIST_PLAYER_REPOSITORY_H -#define EQEMU_BASE_INSTANCE_LIST_PLAYER_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseInstanceListPlayerRepository { @@ -388,5 +388,3 @@ class BaseInstanceListPlayerRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_INSTANCE_LIST_PLAYER_REPOSITORY_H diff --git a/common/repositories/base/base_instance_list_repository.h b/common/repositories/base/base_instance_list_repository.h index 80e64d4534..381ea04f43 100644 --- a/common/repositories/base/base_instance_list_repository.h +++ b/common/repositories/base/base_instance_list_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_INSTANCE_LIST_REPOSITORY_H -#define EQEMU_BASE_INSTANCE_LIST_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseInstanceListRepository { @@ -471,5 +471,3 @@ class BaseInstanceListRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_INSTANCE_LIST_REPOSITORY_H diff --git a/common/repositories/base/base_inventory_repository.h b/common/repositories/base/base_inventory_repository.h index 9a4b5122b6..f1e325d5fe 100644 --- a/common/repositories/base/base_inventory_repository.h +++ b/common/repositories/base/base_inventory_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_INVENTORY_REPOSITORY_H -#define EQEMU_BASE_INVENTORY_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseInventoryRepository { @@ -568,5 +568,3 @@ class BaseInventoryRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_INVENTORY_REPOSITORY_H diff --git a/common/repositories/base/base_inventory_snapshots_repository.h b/common/repositories/base/base_inventory_snapshots_repository.h index 0b68637277..08b162a0c9 100644 --- a/common/repositories/base/base_inventory_snapshots_repository.h +++ b/common/repositories/base/base_inventory_snapshots_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_INVENTORY_SNAPSHOTS_REPOSITORY_H -#define EQEMU_BASE_INVENTORY_SNAPSHOTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseInventorySnapshotsRepository { @@ -580,5 +580,3 @@ class BaseInventorySnapshotsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_INVENTORY_SNAPSHOTS_REPOSITORY_H diff --git a/common/repositories/base/base_ip_exemptions_repository.h b/common/repositories/base/base_ip_exemptions_repository.h index 7137dee626..d4de8c3414 100644 --- a/common/repositories/base/base_ip_exemptions_repository.h +++ b/common/repositories/base/base_ip_exemptions_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_IP_EXEMPTIONS_REPOSITORY_H -#define EQEMU_BASE_IP_EXEMPTIONS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseIpExemptionsRepository { @@ -399,5 +399,3 @@ class BaseIpExemptionsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_IP_EXEMPTIONS_REPOSITORY_H diff --git a/common/repositories/base/base_items_evolving_details_repository.h b/common/repositories/base/base_items_evolving_details_repository.h index 5930b3cd81..7ba6e6ba28 100644 --- a/common/repositories/base/base_items_evolving_details_repository.h +++ b/common/repositories/base/base_items_evolving_details_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ITEMS_EVOLVING_DETAILS_REPOSITORY_H -#define EQEMU_BASE_ITEMS_EVOLVING_DETAILS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseItemsEvolvingDetailsRepository { @@ -447,5 +447,3 @@ class BaseItemsEvolvingDetailsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ITEMS_EVOLVING_DETAILS_REPOSITORY_H diff --git a/common/repositories/base/base_items_repository.h b/common/repositories/base/base_items_repository.h index eb344f4a3b..35f856de23 100644 --- a/common/repositories/base/base_items_repository.h +++ b/common/repositories/base/base_items_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ITEMS_REPOSITORY_H -#define EQEMU_BASE_ITEMS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseItemsRepository { @@ -3784,5 +3784,3 @@ class BaseItemsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ITEMS_REPOSITORY_H diff --git a/common/repositories/base/base_keyring_repository.h b/common/repositories/base/base_keyring_repository.h index fa12e90d21..7ded4d9cd9 100644 --- a/common/repositories/base/base_keyring_repository.h +++ b/common/repositories/base/base_keyring_repository.h @@ -9,11 +9,11 @@ * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories */ -#ifndef EQEMU_BASE_KEYRING_REPOSITORY_H -#define EQEMU_BASE_KEYRING_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -340,5 +340,3 @@ class BaseKeyringRepository { } }; - -#endif //EQEMU_BASE_KEYRING_REPOSITORY_H diff --git a/common/repositories/base/base_launcher_repository.h b/common/repositories/base/base_launcher_repository.h index 15317105e1..1d27c40148 100644 --- a/common/repositories/base/base_launcher_repository.h +++ b/common/repositories/base/base_launcher_repository.h @@ -5,11 +5,10 @@ * be made by the generator only */ -#ifndef EQEMU_BASE_LAUNCHER_REPOSITORY_H -#define EQEMU_BASE_LAUNCHER_REPOSITORY_H +#pragma once -#include "../../database.h" -#include "../../strings.h" +#include "common/database.h" +#include "common/strings.h" class BaseLauncherRepository { public: @@ -284,5 +283,3 @@ class BaseLauncherRepository { } }; - -#endif //EQEMU_BASE_LAUNCHER_REPOSITORY_H diff --git a/common/repositories/base/base_ldon_trap_entries_repository.h b/common/repositories/base/base_ldon_trap_entries_repository.h index 193d8fdb45..4a01bdcca5 100644 --- a/common/repositories/base/base_ldon_trap_entries_repository.h +++ b/common/repositories/base/base_ldon_trap_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LDON_TRAP_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_LDON_TRAP_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLdonTrapEntriesRepository { @@ -388,5 +388,3 @@ class BaseLdonTrapEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LDON_TRAP_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_ldon_trap_templates_repository.h b/common/repositories/base/base_ldon_trap_templates_repository.h index 29584e7e00..926e56eec6 100644 --- a/common/repositories/base/base_ldon_trap_templates_repository.h +++ b/common/repositories/base/base_ldon_trap_templates_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LDON_TRAP_TEMPLATES_REPOSITORY_H -#define EQEMU_BASE_LDON_TRAP_TEMPLATES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLdonTrapTemplatesRepository { @@ -424,5 +424,3 @@ class BaseLdonTrapTemplatesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LDON_TRAP_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/base/base_level_exp_mods_repository.h b/common/repositories/base/base_level_exp_mods_repository.h index 3df29fa440..aba92dfb0b 100644 --- a/common/repositories/base/base_level_exp_mods_repository.h +++ b/common/repositories/base/base_level_exp_mods_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LEVEL_EXP_MODS_REPOSITORY_H -#define EQEMU_BASE_LEVEL_EXP_MODS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLevelExpModsRepository { @@ -400,5 +400,3 @@ class BaseLevelExpModsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LEVEL_EXP_MODS_REPOSITORY_H diff --git a/common/repositories/base/base_lfguild_repository.h b/common/repositories/base/base_lfguild_repository.h index 5f91668d3a..80fc98dfa2 100644 --- a/common/repositories/base/base_lfguild_repository.h +++ b/common/repositories/base/base_lfguild_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LFGUILD_REPOSITORY_H -#define EQEMU_BASE_LFGUILD_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLfguildRepository { @@ -472,5 +472,3 @@ class BaseLfguildRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LFGUILD_REPOSITORY_H diff --git a/common/repositories/base/base_login_accounts_repository.h b/common/repositories/base/base_login_accounts_repository.h index ed7610e4e1..16e0669843 100644 --- a/common/repositories/base/base_login_accounts_repository.h +++ b/common/repositories/base/base_login_accounts_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LOGIN_ACCOUNTS_REPOSITORY_H -#define EQEMU_BASE_LOGIN_ACCOUNTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLoginAccountsRepository { @@ -472,5 +472,3 @@ class BaseLoginAccountsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LOGIN_ACCOUNTS_REPOSITORY_H diff --git a/common/repositories/base/base_login_api_tokens_repository.h b/common/repositories/base/base_login_api_tokens_repository.h index b7ad51f9ad..4192dc189a 100644 --- a/common/repositories/base/base_login_api_tokens_repository.h +++ b/common/repositories/base/base_login_api_tokens_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LOGIN_API_TOKENS_REPOSITORY_H -#define EQEMU_BASE_LOGIN_API_TOKENS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLoginApiTokensRepository { @@ -435,5 +435,3 @@ class BaseLoginApiTokensRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LOGIN_API_TOKENS_REPOSITORY_H diff --git a/common/repositories/base/base_login_server_admins_repository.h b/common/repositories/base/base_login_server_admins_repository.h index 2ec6237c2e..9d944713b1 100644 --- a/common/repositories/base/base_login_server_admins_repository.h +++ b/common/repositories/base/base_login_server_admins_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LOGIN_SERVER_ADMINS_REPOSITORY_H -#define EQEMU_BASE_LOGIN_SERVER_ADMINS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLoginServerAdminsRepository { @@ -459,5 +459,3 @@ class BaseLoginServerAdminsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LOGIN_SERVER_ADMINS_REPOSITORY_H diff --git a/common/repositories/base/base_login_server_list_types_repository.h b/common/repositories/base/base_login_server_list_types_repository.h index 0a1314a4df..76cd2c1953 100644 --- a/common/repositories/base/base_login_server_list_types_repository.h +++ b/common/repositories/base/base_login_server_list_types_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LOGIN_SERVER_LIST_TYPES_REPOSITORY_H -#define EQEMU_BASE_LOGIN_SERVER_LIST_TYPES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLoginServerListTypesRepository { @@ -388,5 +388,3 @@ class BaseLoginServerListTypesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LOGIN_SERVER_LIST_TYPES_REPOSITORY_H diff --git a/common/repositories/base/base_login_world_servers_repository.h b/common/repositories/base/base_login_world_servers_repository.h index b4112ac8cf..9638d5426e 100644 --- a/common/repositories/base/base_login_world_servers_repository.h +++ b/common/repositories/base/base_login_world_servers_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LOGIN_WORLD_SERVERS_REPOSITORY_H -#define EQEMU_BASE_LOGIN_WORLD_SERVERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLoginWorldServersRepository { @@ -483,5 +483,3 @@ class BaseLoginWorldServersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LOGIN_WORLD_SERVERS_REPOSITORY_H diff --git a/common/repositories/base/base_logsys_categories_repository.h b/common/repositories/base/base_logsys_categories_repository.h index b10c20964b..9b95303bad 100644 --- a/common/repositories/base/base_logsys_categories_repository.h +++ b/common/repositories/base/base_logsys_categories_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LOGSYS_CATEGORIES_REPOSITORY_H -#define EQEMU_BASE_LOGSYS_CATEGORIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLogsysCategoriesRepository { @@ -448,5 +448,3 @@ class BaseLogsysCategoriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LOGSYS_CATEGORIES_REPOSITORY_H diff --git a/common/repositories/base/base_lootdrop_entries_repository.h b/common/repositories/base/base_lootdrop_entries_repository.h index e8ecd4ddb1..9367f2e00a 100644 --- a/common/repositories/base/base_lootdrop_entries_repository.h +++ b/common/repositories/base/base_lootdrop_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LOOTDROP_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_LOOTDROP_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLootdropEntriesRepository { @@ -544,5 +544,3 @@ class BaseLootdropEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LOOTDROP_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_lootdrop_repository.h b/common/repositories/base/base_lootdrop_repository.h index b76cd7a58b..ee62570078 100644 --- a/common/repositories/base/base_lootdrop_repository.h +++ b/common/repositories/base/base_lootdrop_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LOOTDROP_REPOSITORY_H -#define EQEMU_BASE_LOOTDROP_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLootdropRepository { @@ -435,5 +435,3 @@ class BaseLootdropRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LOOTDROP_REPOSITORY_H diff --git a/common/repositories/base/base_loottable_entries_repository.h b/common/repositories/base/base_loottable_entries_repository.h index 3bea648390..3a65418fec 100644 --- a/common/repositories/base/base_loottable_entries_repository.h +++ b/common/repositories/base/base_loottable_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LOOTTABLE_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_LOOTTABLE_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLoottableEntriesRepository { @@ -436,5 +436,3 @@ class BaseLoottableEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LOOTTABLE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_loottable_repository.h b/common/repositories/base/base_loottable_repository.h index 41994884ae..63149805ee 100644 --- a/common/repositories/base/base_loottable_repository.h +++ b/common/repositories/base/base_loottable_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_LOOTTABLE_REPOSITORY_H -#define EQEMU_BASE_LOOTTABLE_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseLoottableRepository { @@ -483,5 +483,3 @@ class BaseLoottableRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_LOOTTABLE_REPOSITORY_H diff --git a/common/repositories/base/base_mail_repository.h b/common/repositories/base/base_mail_repository.h index d13cb9bb2a..0f446a37d5 100644 --- a/common/repositories/base/base_mail_repository.h +++ b/common/repositories/base/base_mail_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MAIL_REPOSITORY_H -#define EQEMU_BASE_MAIL_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseMailRepository { @@ -459,5 +459,3 @@ class BaseMailRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MAIL_REPOSITORY_H diff --git a/common/repositories/base/base_merc_armorinfo_repository.h b/common/repositories/base/base_merc_armorinfo_repository.h index 0700ef1666..c74dac0d32 100644 --- a/common/repositories/base/base_merc_armorinfo_repository.h +++ b/common/repositories/base/base_merc_armorinfo_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_ARMORINFO_REPOSITORY_H -#define EQEMU_BASE_MERC_ARMORINFO_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -484,5 +484,3 @@ class BaseMercArmorinfoRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_ARMORINFO_REPOSITORY_H diff --git a/common/repositories/base/base_merc_buffs_repository.h b/common/repositories/base/base_merc_buffs_repository.h index 48d0b229c9..21f19a61a8 100644 --- a/common/repositories/base/base_merc_buffs_repository.h +++ b/common/repositories/base/base_merc_buffs_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_BUFFS_REPOSITORY_H -#define EQEMU_BASE_MERC_BUFFS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseMercBuffsRepository { @@ -591,5 +591,3 @@ class BaseMercBuffsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_BUFFS_REPOSITORY_H diff --git a/common/repositories/base/base_merc_inventory_repository.h b/common/repositories/base/base_merc_inventory_repository.h index abb677843c..c255be8e49 100644 --- a/common/repositories/base/base_merc_inventory_repository.h +++ b/common/repositories/base/base_merc_inventory_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_INVENTORY_REPOSITORY_H -#define EQEMU_BASE_MERC_INVENTORY_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -424,5 +424,3 @@ class BaseMercInventoryRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_INVENTORY_REPOSITORY_H diff --git a/common/repositories/base/base_merc_merchant_entries_repository.h b/common/repositories/base/base_merc_merchant_entries_repository.h index 5816a37bc0..1e91e9d742 100644 --- a/common/repositories/base/base_merc_merchant_entries_repository.h +++ b/common/repositories/base/base_merc_merchant_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_MERCHANT_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_MERC_MERCHANT_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -400,5 +400,3 @@ class BaseMercMerchantEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_MERCHANT_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_merchant_template_entries_repository.h b/common/repositories/base/base_merc_merchant_template_entries_repository.h index 0d863a7d74..ec08beb1a3 100644 --- a/common/repositories/base/base_merc_merchant_template_entries_repository.h +++ b/common/repositories/base/base_merc_merchant_template_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_MERCHANT_TEMPLATE_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_MERC_MERCHANT_TEMPLATE_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -400,5 +400,3 @@ class BaseMercMerchantTemplateEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_MERCHANT_TEMPLATE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_merchant_templates_repository.h b/common/repositories/base/base_merc_merchant_templates_repository.h index f009a04c26..516fee5940 100644 --- a/common/repositories/base/base_merc_merchant_templates_repository.h +++ b/common/repositories/base/base_merc_merchant_templates_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_MERCHANT_TEMPLATES_REPOSITORY_H -#define EQEMU_BASE_MERC_MERCHANT_TEMPLATES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -400,5 +400,3 @@ class BaseMercMerchantTemplatesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_MERCHANT_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_name_types_repository.h b/common/repositories/base/base_merc_name_types_repository.h index 281450cc7b..5966971b87 100644 --- a/common/repositories/base/base_merc_name_types_repository.h +++ b/common/repositories/base/base_merc_name_types_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_NAME_TYPES_REPOSITORY_H -#define EQEMU_BASE_MERC_NAME_TYPES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -413,5 +413,3 @@ class BaseMercNameTypesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_NAME_TYPES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_npc_types_repository.h b/common/repositories/base/base_merc_npc_types_repository.h index 6209dd171e..78b7dc8749 100644 --- a/common/repositories/base/base_merc_npc_types_repository.h +++ b/common/repositories/base/base_merc_npc_types_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_NPC_TYPES_REPOSITORY_H -#define EQEMU_BASE_MERC_NPC_TYPES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -424,5 +424,3 @@ class BaseMercNpcTypesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_NPC_TYPES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_spell_list_entries_repository.h b/common/repositories/base/base_merc_spell_list_entries_repository.h index ebb9b71c63..4e99585cbf 100644 --- a/common/repositories/base/base_merc_spell_list_entries_repository.h +++ b/common/repositories/base/base_merc_spell_list_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_SPELL_LIST_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_MERC_SPELL_LIST_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -472,5 +472,3 @@ class BaseMercSpellListEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_SPELL_LIST_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_spell_lists_repository.h b/common/repositories/base/base_merc_spell_lists_repository.h index 093fb66cc6..c8ee56fb33 100644 --- a/common/repositories/base/base_merc_spell_lists_repository.h +++ b/common/repositories/base/base_merc_spell_lists_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_SPELL_LISTS_REPOSITORY_H -#define EQEMU_BASE_MERC_SPELL_LISTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -412,5 +412,3 @@ class BaseMercSpellListsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_SPELL_LISTS_REPOSITORY_H diff --git a/common/repositories/base/base_merc_stance_entries_repository.h b/common/repositories/base/base_merc_stance_entries_repository.h index 6655bdf8fd..7eeb3edec8 100644 --- a/common/repositories/base/base_merc_stance_entries_repository.h +++ b/common/repositories/base/base_merc_stance_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_STANCE_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_MERC_STANCE_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -424,5 +424,3 @@ class BaseMercStanceEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_STANCE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_stats_repository.h b/common/repositories/base/base_merc_stats_repository.h index eb082b6892..0730bd4215 100644 --- a/common/repositories/base/base_merc_stats_repository.h +++ b/common/repositories/base/base_merc_stats_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_STATS_REPOSITORY_H -#define EQEMU_BASE_MERC_STATS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -761,5 +761,3 @@ class BaseMercStatsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_STATS_REPOSITORY_H diff --git a/common/repositories/base/base_merc_subtypes_repository.h b/common/repositories/base/base_merc_subtypes_repository.h index 84b828b43c..20272f27dd 100644 --- a/common/repositories/base/base_merc_subtypes_repository.h +++ b/common/repositories/base/base_merc_subtypes_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_SUBTYPES_REPOSITORY_H -#define EQEMU_BASE_MERC_SUBTYPES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -412,5 +412,3 @@ class BaseMercSubtypesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_SUBTYPES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_templates_repository.h b/common/repositories/base/base_merc_templates_repository.h index 41d207429b..21444159a1 100644 --- a/common/repositories/base/base_merc_templates_repository.h +++ b/common/repositories/base/base_merc_templates_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_TEMPLATES_REPOSITORY_H -#define EQEMU_BASE_MERC_TEMPLATES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -448,5 +448,3 @@ class BaseMercTemplatesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_types_repository.h b/common/repositories/base/base_merc_types_repository.h index aeb47806de..84c0fa791f 100644 --- a/common/repositories/base/base_merc_types_repository.h +++ b/common/repositories/base/base_merc_types_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_TYPES_REPOSITORY_H -#define EQEMU_BASE_MERC_TYPES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -424,5 +424,3 @@ class BaseMercTypesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_TYPES_REPOSITORY_H diff --git a/common/repositories/base/base_merc_weaponinfo_repository.h b/common/repositories/base/base_merc_weaponinfo_repository.h index 07a7b86c6c..ea509095ef 100644 --- a/common/repositories/base/base_merc_weaponinfo_repository.h +++ b/common/repositories/base/base_merc_weaponinfo_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERC_WEAPONINFO_REPOSITORY_H -#define EQEMU_BASE_MERC_WEAPONINFO_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include @@ -460,5 +460,3 @@ class BaseMercWeaponinfoRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERC_WEAPONINFO_REPOSITORY_H diff --git a/common/repositories/base/base_merchantlist_repository.h b/common/repositories/base/base_merchantlist_repository.h index 9468127b71..f54a8fdfea 100644 --- a/common/repositories/base/base_merchantlist_repository.h +++ b/common/repositories/base/base_merchantlist_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERCHANTLIST_REPOSITORY_H -#define EQEMU_BASE_MERCHANTLIST_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseMerchantlistRepository { @@ -568,5 +568,3 @@ class BaseMerchantlistRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERCHANTLIST_REPOSITORY_H diff --git a/common/repositories/base/base_merchantlist_temp_repository.h b/common/repositories/base/base_merchantlist_temp_repository.h index 35f1bc2157..884356072d 100644 --- a/common/repositories/base/base_merchantlist_temp_repository.h +++ b/common/repositories/base/base_merchantlist_temp_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERCHANTLIST_TEMP_REPOSITORY_H -#define EQEMU_BASE_MERCHANTLIST_TEMP_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseMerchantlistTempRepository { @@ -436,5 +436,3 @@ class BaseMerchantlistTempRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERCHANTLIST_TEMP_REPOSITORY_H diff --git a/common/repositories/base/base_mercs_repository.h b/common/repositories/base/base_mercs_repository.h index 5402126ef8..6592715857 100644 --- a/common/repositories/base/base_mercs_repository.h +++ b/common/repositories/base/base_mercs_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_MERCS_REPOSITORY_H -#define EQEMU_BASE_MERCS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseMercsRepository { @@ -651,5 +651,3 @@ class BaseMercsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_MERCS_REPOSITORY_H diff --git a/common/repositories/base/base_name_filter_repository.h b/common/repositories/base/base_name_filter_repository.h index 3871c879b6..973b972d62 100644 --- a/common/repositories/base/base_name_filter_repository.h +++ b/common/repositories/base/base_name_filter_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_NAME_FILTER_REPOSITORY_H -#define EQEMU_BASE_NAME_FILTER_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseNameFilterRepository { @@ -387,5 +387,3 @@ class BaseNameFilterRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_NAME_FILTER_REPOSITORY_H diff --git a/common/repositories/base/base_npc_emotes_repository.h b/common/repositories/base/base_npc_emotes_repository.h index 6826d38a2d..301ea98851 100644 --- a/common/repositories/base/base_npc_emotes_repository.h +++ b/common/repositories/base/base_npc_emotes_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_NPC_EMOTES_REPOSITORY_H -#define EQEMU_BASE_NPC_EMOTES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseNpcEmotesRepository { @@ -423,5 +423,3 @@ class BaseNpcEmotesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_NPC_EMOTES_REPOSITORY_H diff --git a/common/repositories/base/base_npc_faction_entries_repository.h b/common/repositories/base/base_npc_faction_entries_repository.h index b7c60fae3a..7ade2668b3 100644 --- a/common/repositories/base/base_npc_faction_entries_repository.h +++ b/common/repositories/base/base_npc_faction_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_NPC_FACTION_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_NPC_FACTION_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseNpcFactionEntriesRepository { @@ -424,5 +424,3 @@ class BaseNpcFactionEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_NPC_FACTION_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_npc_faction_repository.h b/common/repositories/base/base_npc_faction_repository.h index bb3a13d0cd..d7f6d223a7 100644 --- a/common/repositories/base/base_npc_faction_repository.h +++ b/common/repositories/base/base_npc_faction_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_NPC_FACTION_REPOSITORY_H -#define EQEMU_BASE_NPC_FACTION_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseNpcFactionRepository { @@ -411,5 +411,3 @@ class BaseNpcFactionRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_NPC_FACTION_REPOSITORY_H diff --git a/common/repositories/base/base_npc_scale_global_base_repository.h b/common/repositories/base/base_npc_scale_global_base_repository.h index f01f5d38a3..78bf0e7c40 100644 --- a/common/repositories/base/base_npc_scale_global_base_repository.h +++ b/common/repositories/base/base_npc_scale_global_base_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_NPC_SCALE_GLOBAL_BASE_REPOSITORY_H -#define EQEMU_BASE_NPC_SCALE_GLOBAL_BASE_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseNpcScaleGlobalBaseRepository { @@ -760,5 +760,3 @@ class BaseNpcScaleGlobalBaseRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_NPC_SCALE_GLOBAL_BASE_REPOSITORY_H diff --git a/common/repositories/base/base_npc_spells_effects_entries_repository.h b/common/repositories/base/base_npc_spells_effects_entries_repository.h index 35381cff06..02bd46c40c 100644 --- a/common/repositories/base/base_npc_spells_effects_entries_repository.h +++ b/common/repositories/base/base_npc_spells_effects_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_NPC_SPELLS_EFFECTS_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_NPC_SPELLS_EFFECTS_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseNpcSpellsEffectsEntriesRepository { @@ -459,5 +459,3 @@ class BaseNpcSpellsEffectsEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_NPC_SPELLS_EFFECTS_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_npc_spells_effects_repository.h b/common/repositories/base/base_npc_spells_effects_repository.h index b425c42c8b..c2f11f6332 100644 --- a/common/repositories/base/base_npc_spells_effects_repository.h +++ b/common/repositories/base/base_npc_spells_effects_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_NPC_SPELLS_EFFECTS_REPOSITORY_H -#define EQEMU_BASE_NPC_SPELLS_EFFECTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseNpcSpellsEffectsRepository { @@ -399,5 +399,3 @@ class BaseNpcSpellsEffectsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_NPC_SPELLS_EFFECTS_REPOSITORY_H diff --git a/common/repositories/base/base_npc_spells_entries_repository.h b/common/repositories/base/base_npc_spells_entries_repository.h index 446944d87e..129255ee58 100644 --- a/common/repositories/base/base_npc_spells_entries_repository.h +++ b/common/repositories/base/base_npc_spells_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_NPC_SPELLS_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_NPC_SPELLS_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseNpcSpellsEntriesRepository { @@ -555,5 +555,3 @@ class BaseNpcSpellsEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_NPC_SPELLS_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_npc_spells_repository.h b/common/repositories/base/base_npc_spells_repository.h index e9868d419b..558f2bc256 100644 --- a/common/repositories/base/base_npc_spells_repository.h +++ b/common/repositories/base/base_npc_spells_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_NPC_SPELLS_REPOSITORY_H -#define EQEMU_BASE_NPC_SPELLS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseNpcSpellsRepository { @@ -615,5 +615,3 @@ class BaseNpcSpellsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_NPC_SPELLS_REPOSITORY_H diff --git a/common/repositories/base/base_npc_types_repository.h b/common/repositories/base/base_npc_types_repository.h index f6019e9875..e42af292e8 100644 --- a/common/repositories/base/base_npc_types_repository.h +++ b/common/repositories/base/base_npc_types_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_NPC_TYPES_REPOSITORY_H -#define EQEMU_BASE_NPC_TYPES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseNpcTypesRepository { @@ -1935,5 +1935,3 @@ class BaseNpcTypesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_NPC_TYPES_REPOSITORY_H diff --git a/common/repositories/base/base_npc_types_tint_repository.h b/common/repositories/base/base_npc_types_tint_repository.h index f7d02b9bce..f9766c1848 100644 --- a/common/repositories/base/base_npc_types_tint_repository.h +++ b/common/repositories/base/base_npc_types_tint_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_NPC_TYPES_TINT_REPOSITORY_H -#define EQEMU_BASE_NPC_TYPES_TINT_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseNpcTypesTintRepository { @@ -712,5 +712,3 @@ class BaseNpcTypesTintRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_NPC_TYPES_TINT_REPOSITORY_H diff --git a/common/repositories/base/base_object_contents_repository.h b/common/repositories/base/base_object_contents_repository.h index d3bf93f3d4..a9142cb268 100644 --- a/common/repositories/base/base_object_contents_repository.h +++ b/common/repositories/base/base_object_contents_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_OBJECT_CONTENTS_REPOSITORY_H -#define EQEMU_BASE_OBJECT_CONTENTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseObjectContentsRepository { @@ -508,5 +508,3 @@ class BaseObjectContentsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_OBJECT_CONTENTS_REPOSITORY_H diff --git a/common/repositories/base/base_object_repository.h b/common/repositories/base/base_object_repository.h index aabecdeef5..7d360988d1 100644 --- a/common/repositories/base/base_object_repository.h +++ b/common/repositories/base/base_object_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_OBJECT_REPOSITORY_H -#define EQEMU_BASE_OBJECT_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseObjectRepository { @@ -723,5 +723,3 @@ class BaseObjectRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_OBJECT_REPOSITORY_H diff --git a/common/repositories/base/base_perl_event_export_settings_repository.h b/common/repositories/base/base_perl_event_export_settings_repository.h index e22fadb1ec..df4f71dcb8 100644 --- a/common/repositories/base/base_perl_event_export_settings_repository.h +++ b/common/repositories/base/base_perl_event_export_settings_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PERL_EVENT_EXPORT_SETTINGS_REPOSITORY_H -#define EQEMU_BASE_PERL_EVENT_EXPORT_SETTINGS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePerlEventExportSettingsRepository { @@ -448,5 +448,3 @@ class BasePerlEventExportSettingsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PERL_EVENT_EXPORT_SETTINGS_REPOSITORY_H diff --git a/common/repositories/base/base_petitions_repository.h b/common/repositories/base/base_petitions_repository.h index f73f529fb1..746421bd31 100644 --- a/common/repositories/base/base_petitions_repository.h +++ b/common/repositories/base/base_petitions_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PETITIONS_REPOSITORY_H -#define EQEMU_BASE_PETITIONS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePetitionsRepository { @@ -555,5 +555,3 @@ class BasePetitionsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PETITIONS_REPOSITORY_H diff --git a/common/repositories/base/base_pets_beastlord_data_repository.h b/common/repositories/base/base_pets_beastlord_data_repository.h index 9960a8c36d..46208feaaf 100644 --- a/common/repositories/base/base_pets_beastlord_data_repository.h +++ b/common/repositories/base/base_pets_beastlord_data_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PETS_BEASTLORD_DATA_REPOSITORY_H -#define EQEMU_BASE_PETS_BEASTLORD_DATA_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePetsBeastlordDataRepository { @@ -448,5 +448,3 @@ class BasePetsBeastlordDataRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PETS_BEASTLORD_DATA_REPOSITORY_H diff --git a/common/repositories/base/base_pets_equipmentset_entries_repository.h b/common/repositories/base/base_pets_equipmentset_entries_repository.h index c341184889..0c5187e764 100644 --- a/common/repositories/base/base_pets_equipmentset_entries_repository.h +++ b/common/repositories/base/base_pets_equipmentset_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PETS_EQUIPMENTSET_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_PETS_EQUIPMENTSET_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePetsEquipmentsetEntriesRepository { @@ -400,5 +400,3 @@ class BasePetsEquipmentsetEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PETS_EQUIPMENTSET_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_pets_equipmentset_repository.h b/common/repositories/base/base_pets_equipmentset_repository.h index ee369a69af..3d96c7b2c9 100644 --- a/common/repositories/base/base_pets_equipmentset_repository.h +++ b/common/repositories/base/base_pets_equipmentset_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PETS_EQUIPMENTSET_REPOSITORY_H -#define EQEMU_BASE_PETS_EQUIPMENTSET_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePetsEquipmentsetRepository { @@ -400,5 +400,3 @@ class BasePetsEquipmentsetRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PETS_EQUIPMENTSET_REPOSITORY_H diff --git a/common/repositories/base/base_pets_repository.h b/common/repositories/base/base_pets_repository.h index bb2346b3ad..f5042eea29 100644 --- a/common/repositories/base/base_pets_repository.h +++ b/common/repositories/base/base_pets_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PETS_REPOSITORY_H -#define EQEMU_BASE_PETS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePetsRepository { @@ -471,5 +471,3 @@ class BasePetsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PETS_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_aa_purchase_repository.h b/common/repositories/base/base_player_event_aa_purchase_repository.h index ca8fb27246..e26149c840 100644 --- a/common/repositories/base/base_player_event_aa_purchase_repository.h +++ b/common/repositories/base/base_player_event_aa_purchase_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePlayerEventAaPurchaseRepository { @@ -435,5 +435,3 @@ class BasePlayerEventAaPurchaseRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_killed_named_npc_repository.h b/common/repositories/base/base_player_event_killed_named_npc_repository.h index 027e5afbf9..1c61dbe2dc 100644 --- a/common/repositories/base/base_player_event_killed_named_npc_repository.h +++ b/common/repositories/base/base_player_event_killed_named_npc_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePlayerEventKilledNamedNpcRepository { @@ -447,5 +447,3 @@ class BasePlayerEventKilledNamedNpcRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_killed_npc_repository.h b/common/repositories/base/base_player_event_killed_npc_repository.h index 13fb3fe86d..47611c5a26 100644 --- a/common/repositories/base/base_player_event_killed_npc_repository.h +++ b/common/repositories/base/base_player_event_killed_npc_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePlayerEventKilledNpcRepository { @@ -447,5 +447,3 @@ class BasePlayerEventKilledNpcRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_killed_raid_npc_repository.h b/common/repositories/base/base_player_event_killed_raid_npc_repository.h index beba705c69..bc834b10a1 100644 --- a/common/repositories/base/base_player_event_killed_raid_npc_repository.h +++ b/common/repositories/base/base_player_event_killed_raid_npc_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePlayerEventKilledRaidNpcRepository { @@ -447,5 +447,3 @@ class BasePlayerEventKilledRaidNpcRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_log_settings_repository.h b/common/repositories/base/base_player_event_log_settings_repository.h index 94a53b9814..5c34551335 100644 --- a/common/repositories/base/base_player_event_log_settings_repository.h +++ b/common/repositories/base/base_player_event_log_settings_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include #include class BasePlayerEventLogSettingsRepository { @@ -450,5 +450,3 @@ class BasePlayerEventLogSettingsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_logs_repository.h b/common/repositories/base/base_player_event_logs_repository.h index 3a23feec83..c7e976fe34 100644 --- a/common/repositories/base/base_player_event_logs_repository.h +++ b/common/repositories/base/base_player_event_logs_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_LOGS_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_LOGS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include #include class BasePlayerEventLogsRepository { @@ -553,5 +553,3 @@ class BasePlayerEventLogsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_LOGS_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_loot_items_repository.h b/common/repositories/base/base_player_event_loot_items_repository.h index 42c1c928a1..191a1194b3 100644 --- a/common/repositories/base/base_player_event_loot_items_repository.h +++ b/common/repositories/base/base_player_event_loot_items_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePlayerEventLootItemsRepository { @@ -519,5 +519,3 @@ class BasePlayerEventLootItemsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_merchant_purchase_repository.h b/common/repositories/base/base_player_event_merchant_purchase_repository.h index 99ed4e7c5d..f7d17bad2c 100644 --- a/common/repositories/base/base_player_event_merchant_purchase_repository.h +++ b/common/repositories/base/base_player_event_merchant_purchase_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePlayerEventMerchantPurchaseRepository { @@ -507,5 +507,3 @@ class BasePlayerEventMerchantPurchaseRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_merchant_sell_repository.h b/common/repositories/base/base_player_event_merchant_sell_repository.h index 13c0181654..861b90f225 100644 --- a/common/repositories/base/base_player_event_merchant_sell_repository.h +++ b/common/repositories/base/base_player_event_merchant_sell_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePlayerEventMerchantSellRepository { @@ -507,5 +507,3 @@ class BasePlayerEventMerchantSellRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_npc_handin_entries_repository.h b/common/repositories/base/base_player_event_npc_handin_entries_repository.h index 4d2ee2ead8..27200115bc 100644 --- a/common/repositories/base/base_player_event_npc_handin_entries_repository.h +++ b/common/repositories/base/base_player_event_npc_handin_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePlayerEventNpcHandinEntriesRepository { @@ -519,5 +519,3 @@ class BasePlayerEventNpcHandinEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_npc_handin_repository.h b/common/repositories/base/base_player_event_npc_handin_repository.h index acf460c50b..9bba1d2a0c 100644 --- a/common/repositories/base/base_player_event_npc_handin_repository.h +++ b/common/repositories/base/base_player_event_npc_handin_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePlayerEventNpcHandinRepository { @@ -519,5 +519,3 @@ class BasePlayerEventNpcHandinRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_speech_repository.h b/common/repositories/base/base_player_event_speech_repository.h index 80823f3e6a..7f63f05889 100644 --- a/common/repositories/base/base_player_event_speech_repository.h +++ b/common/repositories/base/base_player_event_speech_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_SPEECH_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_SPEECH_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePlayerEventSpeechRepository { @@ -459,5 +459,3 @@ class BasePlayerEventSpeechRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_SPEECH_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_trade_entries_repository.h b/common/repositories/base/base_player_event_trade_entries_repository.h index ae117e32a9..2a9f09ce98 100644 --- a/common/repositories/base/base_player_event_trade_entries_repository.h +++ b/common/repositories/base/base_player_event_trade_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePlayerEventTradeEntriesRepository { @@ -531,5 +531,3 @@ class BasePlayerEventTradeEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_player_event_trade_repository.h b/common/repositories/base/base_player_event_trade_repository.h index 58409a5cbd..fcc2ec9c37 100644 --- a/common/repositories/base/base_player_event_trade_repository.h +++ b/common/repositories/base/base_player_event_trade_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_EVENT_TRADE_REPOSITORY_H -#define EQEMU_BASE_PLAYER_EVENT_TRADE_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePlayerEventTradeRepository { @@ -507,5 +507,3 @@ class BasePlayerEventTradeRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_EVENT_TRADE_REPOSITORY_H diff --git a/common/repositories/base/base_player_titlesets_repository.h b/common/repositories/base/base_player_titlesets_repository.h index 094411d48a..35ef9b07d5 100644 --- a/common/repositories/base/base_player_titlesets_repository.h +++ b/common/repositories/base/base_player_titlesets_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_PLAYER_TITLESETS_REPOSITORY_H -#define EQEMU_BASE_PLAYER_TITLESETS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BasePlayerTitlesetsRepository { @@ -399,5 +399,3 @@ class BasePlayerTitlesetsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_PLAYER_TITLESETS_REPOSITORY_H diff --git a/common/repositories/base/base_quest_globals_repository.h b/common/repositories/base/base_quest_globals_repository.h index 692ba49f79..78e5ebf59a 100644 --- a/common/repositories/base/base_quest_globals_repository.h +++ b/common/repositories/base/base_quest_globals_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_QUEST_GLOBALS_REPOSITORY_H -#define EQEMU_BASE_QUEST_GLOBALS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseQuestGlobalsRepository { @@ -436,5 +436,3 @@ class BaseQuestGlobalsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_QUEST_GLOBALS_REPOSITORY_H diff --git a/common/repositories/base/base_raid_details_repository.h b/common/repositories/base/base_raid_details_repository.h index fc3b0e3f28..771afd9369 100644 --- a/common/repositories/base/base_raid_details_repository.h +++ b/common/repositories/base/base_raid_details_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_RAID_DETAILS_REPOSITORY_H -#define EQEMU_BASE_RAID_DETAILS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseRaidDetailsRepository { @@ -520,5 +520,3 @@ class BaseRaidDetailsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_RAID_DETAILS_REPOSITORY_H diff --git a/common/repositories/base/base_raid_members_repository.h b/common/repositories/base/base_raid_members_repository.h index 2f269ad4b6..d93418e61f 100644 --- a/common/repositories/base/base_raid_members_repository.h +++ b/common/repositories/base/base_raid_members_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_RAID_MEMBERS_REPOSITORY_H -#define EQEMU_BASE_RAID_MEMBERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseRaidMembersRepository { @@ -531,5 +531,3 @@ class BaseRaidMembersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_RAID_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_reports_repository.h b/common/repositories/base/base_reports_repository.h index 1a3eac65b1..4c3a2acccc 100644 --- a/common/repositories/base/base_reports_repository.h +++ b/common/repositories/base/base_reports_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_REPORTS_REPOSITORY_H -#define EQEMU_BASE_REPORTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseReportsRepository { @@ -411,5 +411,3 @@ class BaseReportsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_REPORTS_REPOSITORY_H diff --git a/common/repositories/base/base_respawn_times_repository.h b/common/repositories/base/base_respawn_times_repository.h index 303296c10a..25a56bad96 100644 --- a/common/repositories/base/base_respawn_times_repository.h +++ b/common/repositories/base/base_respawn_times_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_RESPAWN_TIMES_REPOSITORY_H -#define EQEMU_BASE_RESPAWN_TIMES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseRespawnTimesRepository { @@ -424,5 +424,3 @@ class BaseRespawnTimesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_RESPAWN_TIMES_REPOSITORY_H diff --git a/common/repositories/base/base_rule_sets_repository.h b/common/repositories/base/base_rule_sets_repository.h index e4f51f69dd..0007a2c7e9 100644 --- a/common/repositories/base/base_rule_sets_repository.h +++ b/common/repositories/base/base_rule_sets_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_RULE_SETS_REPOSITORY_H -#define EQEMU_BASE_RULE_SETS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseRuleSetsRepository { @@ -387,5 +387,3 @@ class BaseRuleSetsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_RULE_SETS_REPOSITORY_H diff --git a/common/repositories/base/base_rule_values_repository.h b/common/repositories/base/base_rule_values_repository.h index 6486e2b863..571f7425fb 100644 --- a/common/repositories/base/base_rule_values_repository.h +++ b/common/repositories/base/base_rule_values_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_RULE_VALUES_REPOSITORY_H -#define EQEMU_BASE_RULE_VALUES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseRuleValuesRepository { @@ -412,5 +412,3 @@ class BaseRuleValuesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_RULE_VALUES_REPOSITORY_H diff --git a/common/repositories/base/base_saylink_repository.h b/common/repositories/base/base_saylink_repository.h index 01de6506f9..78c61dfc59 100644 --- a/common/repositories/base/base_saylink_repository.h +++ b/common/repositories/base/base_saylink_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SAYLINK_REPOSITORY_H -#define EQEMU_BASE_SAYLINK_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSaylinkRepository { @@ -387,5 +387,3 @@ class BaseSaylinkRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SAYLINK_REPOSITORY_H diff --git a/common/repositories/base/base_server_scheduled_events_repository.h b/common/repositories/base/base_server_scheduled_events_repository.h index d6793bb24b..e23f0a4fd4 100644 --- a/common/repositories/base/base_server_scheduled_events_repository.h +++ b/common/repositories/base/base_server_scheduled_events_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SERVER_SCHEDULED_EVENTS_REPOSITORY_H -#define EQEMU_BASE_SERVER_SCHEDULED_EVENTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseServerScheduledEventsRepository { @@ -567,5 +567,3 @@ class BaseServerScheduledEventsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SERVER_SCHEDULED_EVENTS_REPOSITORY_H diff --git a/common/repositories/base/base_shared_task_activity_state_repository.h b/common/repositories/base/base_shared_task_activity_state_repository.h index aaad53b66a..bcb6399dad 100644 --- a/common/repositories/base/base_shared_task_activity_state_repository.h +++ b/common/repositories/base/base_shared_task_activity_state_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H -#define EQEMU_BASE_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSharedTaskActivityStateRepository { @@ -424,5 +424,3 @@ class BaseSharedTaskActivityStateRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H diff --git a/common/repositories/base/base_shared_task_dynamic_zones_repository.h b/common/repositories/base/base_shared_task_dynamic_zones_repository.h index 27a40be72e..07d67ad0c2 100644 --- a/common/repositories/base/base_shared_task_dynamic_zones_repository.h +++ b/common/repositories/base/base_shared_task_dynamic_zones_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SHARED_TASK_DYNAMIC_ZONES_REPOSITORY_H -#define EQEMU_BASE_SHARED_TASK_DYNAMIC_ZONES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSharedTaskDynamicZonesRepository { @@ -388,5 +388,3 @@ class BaseSharedTaskDynamicZonesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SHARED_TASK_DYNAMIC_ZONES_REPOSITORY_H diff --git a/common/repositories/base/base_shared_task_members_repository.h b/common/repositories/base/base_shared_task_members_repository.h index 8c05bbc8f8..1f06590802 100644 --- a/common/repositories/base/base_shared_task_members_repository.h +++ b/common/repositories/base/base_shared_task_members_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SHARED_TASK_MEMBERS_REPOSITORY_H -#define EQEMU_BASE_SHARED_TASK_MEMBERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSharedTaskMembersRepository { @@ -400,5 +400,3 @@ class BaseSharedTaskMembersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SHARED_TASK_MEMBERS_REPOSITORY_H diff --git a/common/repositories/base/base_shared_tasks_repository.h b/common/repositories/base/base_shared_tasks_repository.h index 85b9194022..88d47ac0ae 100644 --- a/common/repositories/base/base_shared_tasks_repository.h +++ b/common/repositories/base/base_shared_tasks_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SHARED_TASKS_REPOSITORY_H -#define EQEMU_BASE_SHARED_TASKS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSharedTasksRepository { @@ -435,5 +435,3 @@ class BaseSharedTasksRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SHARED_TASKS_REPOSITORY_H diff --git a/common/repositories/base/base_sharedbank_repository.h b/common/repositories/base/base_sharedbank_repository.h index d208251da4..4c48940212 100644 --- a/common/repositories/base/base_sharedbank_repository.h +++ b/common/repositories/base/base_sharedbank_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SHAREDBANK_REPOSITORY_H -#define EQEMU_BASE_SHAREDBANK_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSharedbankRepository { @@ -556,5 +556,3 @@ class BaseSharedbankRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SHAREDBANK_REPOSITORY_H diff --git a/common/repositories/base/base_skill_caps_repository.h b/common/repositories/base/base_skill_caps_repository.h index 4b3c86e625..d5a10dc859 100644 --- a/common/repositories/base/base_skill_caps_repository.h +++ b/common/repositories/base/base_skill_caps_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SKILL_CAPS_REPOSITORY_H -#define EQEMU_BASE_SKILL_CAPS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSkillCapsRepository { @@ -435,5 +435,3 @@ class BaseSkillCapsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SKILL_CAPS_REPOSITORY_H diff --git a/common/repositories/base/base_spawn2_disabled_repository.h b/common/repositories/base/base_spawn2_disabled_repository.h index 9df03bc7dc..6ff80b70f3 100644 --- a/common/repositories/base/base_spawn2_disabled_repository.h +++ b/common/repositories/base/base_spawn2_disabled_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SPAWN2_DISABLED_REPOSITORY_H -#define EQEMU_BASE_SPAWN2_DISABLED_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSpawn2DisabledRepository { @@ -411,5 +411,3 @@ class BaseSpawn2DisabledRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SPAWN2_DISABLED_REPOSITORY_H diff --git a/common/repositories/base/base_spawn2_repository.h b/common/repositories/base/base_spawn2_repository.h index 91b31822af..5d6e071fbf 100644 --- a/common/repositories/base/base_spawn2_repository.h +++ b/common/repositories/base/base_spawn2_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SPAWN2_REPOSITORY_H -#define EQEMU_BASE_SPAWN2_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSpawn2Repository { @@ -591,5 +591,3 @@ class BaseSpawn2Repository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SPAWN2_REPOSITORY_H diff --git a/common/repositories/base/base_spawn_condition_values_repository.h b/common/repositories/base/base_spawn_condition_values_repository.h index 3464c1c01f..1186a2507c 100644 --- a/common/repositories/base/base_spawn_condition_values_repository.h +++ b/common/repositories/base/base_spawn_condition_values_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SPAWN_CONDITION_VALUES_REPOSITORY_H -#define EQEMU_BASE_SPAWN_CONDITION_VALUES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSpawnConditionValuesRepository { @@ -412,5 +412,3 @@ class BaseSpawnConditionValuesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SPAWN_CONDITION_VALUES_REPOSITORY_H diff --git a/common/repositories/base/base_spawn_conditions_repository.h b/common/repositories/base/base_spawn_conditions_repository.h index 521a39e5f7..bddfa29366 100644 --- a/common/repositories/base/base_spawn_conditions_repository.h +++ b/common/repositories/base/base_spawn_conditions_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SPAWN_CONDITIONS_REPOSITORY_H -#define EQEMU_BASE_SPAWN_CONDITIONS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSpawnConditionsRepository { @@ -424,5 +424,3 @@ class BaseSpawnConditionsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SPAWN_CONDITIONS_REPOSITORY_H diff --git a/common/repositories/base/base_spawn_events_repository.h b/common/repositories/base/base_spawn_events_repository.h index f4d8944adf..c61b4f0880 100644 --- a/common/repositories/base/base_spawn_events_repository.h +++ b/common/repositories/base/base_spawn_events_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SPAWN_EVENTS_REPOSITORY_H -#define EQEMU_BASE_SPAWN_EVENTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSpawnEventsRepository { @@ -531,5 +531,3 @@ class BaseSpawnEventsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SPAWN_EVENTS_REPOSITORY_H diff --git a/common/repositories/base/base_spawnentry_repository.h b/common/repositories/base/base_spawnentry_repository.h index 70d7e18073..ebf20287f9 100644 --- a/common/repositories/base/base_spawnentry_repository.h +++ b/common/repositories/base/base_spawnentry_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SPAWNENTRY_REPOSITORY_H -#define EQEMU_BASE_SPAWNENTRY_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSpawnentryRepository { @@ -484,5 +484,3 @@ class BaseSpawnentryRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SPAWNENTRY_REPOSITORY_H diff --git a/common/repositories/base/base_spawngroup_repository.h b/common/repositories/base/base_spawngroup_repository.h index dd7a3e1b02..1942e1309f 100644 --- a/common/repositories/base/base_spawngroup_repository.h +++ b/common/repositories/base/base_spawngroup_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SPAWNGROUP_REPOSITORY_H -#define EQEMU_BASE_SPAWNGROUP_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSpawngroupRepository { @@ -519,5 +519,3 @@ class BaseSpawngroupRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SPAWNGROUP_REPOSITORY_H diff --git a/common/repositories/base/base_spell_buckets_repository.h b/common/repositories/base/base_spell_buckets_repository.h index 734e02155a..88096b3676 100644 --- a/common/repositories/base/base_spell_buckets_repository.h +++ b/common/repositories/base/base_spell_buckets_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SPELL_BUCKETS_REPOSITORY_H -#define EQEMU_BASE_SPELL_BUCKETS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSpellBucketsRepository { @@ -412,5 +412,3 @@ class BaseSpellBucketsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SPELL_BUCKETS_REPOSITORY_H diff --git a/common/repositories/base/base_spell_globals_repository.h b/common/repositories/base/base_spell_globals_repository.h index b4d3dc1cf7..b9052fd75f 100644 --- a/common/repositories/base/base_spell_globals_repository.h +++ b/common/repositories/base/base_spell_globals_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SPELL_GLOBALS_REPOSITORY_H -#define EQEMU_BASE_SPELL_GLOBALS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSpellGlobalsRepository { @@ -412,5 +412,3 @@ class BaseSpellGlobalsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SPELL_GLOBALS_REPOSITORY_H diff --git a/common/repositories/base/base_spells_new_repository.h b/common/repositories/base/base_spells_new_repository.h index 019e8eaea0..3a887544cf 100644 --- a/common/repositories/base/base_spells_new_repository.h +++ b/common/repositories/base/base_spells_new_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_SPELLS_NEW_REPOSITORY_H -#define EQEMU_BASE_SPELLS_NEW_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseSpellsNewRepository { @@ -3208,5 +3208,3 @@ class BaseSpellsNewRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_SPELLS_NEW_REPOSITORY_H diff --git a/common/repositories/base/base_start_zones_repository.h b/common/repositories/base/base_start_zones_repository.h index 54344e685a..59bf18da0a 100644 --- a/common/repositories/base/base_start_zones_repository.h +++ b/common/repositories/base/base_start_zones_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_START_ZONES_REPOSITORY_H -#define EQEMU_BASE_START_ZONES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseStartZonesRepository { @@ -592,5 +592,3 @@ class BaseStartZonesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_START_ZONES_REPOSITORY_H diff --git a/common/repositories/base/base_starting_items_repository.h b/common/repositories/base/base_starting_items_repository.h index ebe6fb3f92..3d50f486d7 100644 --- a/common/repositories/base/base_starting_items_repository.h +++ b/common/repositories/base/base_starting_items_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_STARTING_ITEMS_REPOSITORY_H -#define EQEMU_BASE_STARTING_ITEMS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseStartingItemsRepository { @@ -591,5 +591,3 @@ class BaseStartingItemsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_STARTING_ITEMS_REPOSITORY_H diff --git a/common/repositories/base/base_task_activities_repository.h b/common/repositories/base/base_task_activities_repository.h index b47f5b86d0..c553465d5c 100644 --- a/common/repositories/base/base_task_activities_repository.h +++ b/common/repositories/base/base_task_activities_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_TASK_ACTIVITIES_REPOSITORY_H -#define EQEMU_BASE_TASK_ACTIVITIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseTaskActivitiesRepository { @@ -664,5 +664,3 @@ class BaseTaskActivitiesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_TASK_ACTIVITIES_REPOSITORY_H diff --git a/common/repositories/base/base_tasks_repository.h b/common/repositories/base/base_tasks_repository.h index d1a30f7113..775c9e96f6 100644 --- a/common/repositories/base/base_tasks_repository.h +++ b/common/repositories/base/base_tasks_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_TASKS_REPOSITORY_H -#define EQEMU_BASE_TASKS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseTasksRepository { @@ -712,5 +712,3 @@ class BaseTasksRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_TASKS_REPOSITORY_H diff --git a/common/repositories/base/base_tasksets_repository.h b/common/repositories/base/base_tasksets_repository.h index 9aa96368b5..5d7d5171af 100644 --- a/common/repositories/base/base_tasksets_repository.h +++ b/common/repositories/base/base_tasksets_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_TASKSETS_REPOSITORY_H -#define EQEMU_BASE_TASKSETS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseTasksetsRepository { @@ -388,5 +388,3 @@ class BaseTasksetsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_TASKSETS_REPOSITORY_H diff --git a/common/repositories/base/base_timers_repository.h b/common/repositories/base/base_timers_repository.h index bcf2efbd9f..523ec06136 100644 --- a/common/repositories/base/base_timers_repository.h +++ b/common/repositories/base/base_timers_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_TIMERS_REPOSITORY_H -#define EQEMU_BASE_TIMERS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseTimersRepository { @@ -424,5 +424,3 @@ class BaseTimersRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_TIMERS_REPOSITORY_H diff --git a/common/repositories/base/base_titles_repository.h b/common/repositories/base/base_titles_repository.h index 638c711d64..1df0686c5e 100644 --- a/common/repositories/base/base_titles_repository.h +++ b/common/repositories/base/base_titles_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_TITLES_REPOSITORY_H -#define EQEMU_BASE_TITLES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseTitlesRepository { @@ -531,5 +531,3 @@ class BaseTitlesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_TITLES_REPOSITORY_H diff --git a/common/repositories/base/base_tool_game_objects_repository.h b/common/repositories/base/base_tool_game_objects_repository.h index 908844df7a..e44a901973 100644 --- a/common/repositories/base/base_tool_game_objects_repository.h +++ b/common/repositories/base/base_tool_game_objects_repository.h @@ -9,11 +9,11 @@ * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories */ -#ifndef EQEMU_BASE_TOOL_GAME_OBJECTS_REPOSITORY_H -#define EQEMU_BASE_TOOL_GAME_OBJECTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseToolGameObjectsRepository { @@ -342,5 +342,3 @@ class BaseToolGameObjectsRepository { } }; - -#endif //EQEMU_BASE_TOOL_GAME_OBJECTS_REPOSITORY_H diff --git a/common/repositories/base/base_trader_repository.h b/common/repositories/base/base_trader_repository.h index 99236fcacd..9199c27c9d 100644 --- a/common/repositories/base/base_trader_repository.h +++ b/common/repositories/base/base_trader_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_TRADER_REPOSITORY_H -#define EQEMU_BASE_TRADER_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseTraderRepository { @@ -579,5 +579,3 @@ class BaseTraderRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_TRADER_REPOSITORY_H diff --git a/common/repositories/base/base_tradeskill_recipe_entries_repository.h b/common/repositories/base/base_tradeskill_recipe_entries_repository.h index 85eb5b281e..455e00fca6 100644 --- a/common/repositories/base/base_tradeskill_recipe_entries_repository.h +++ b/common/repositories/base/base_tradeskill_recipe_entries_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_TRADESKILL_RECIPE_ENTRIES_REPOSITORY_H -#define EQEMU_BASE_TRADESKILL_RECIPE_ENTRIES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseTradeskillRecipeEntriesRepository { @@ -459,5 +459,3 @@ class BaseTradeskillRecipeEntriesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_TRADESKILL_RECIPE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/base/base_tradeskill_recipe_repository.h b/common/repositories/base/base_tradeskill_recipe_repository.h index e7070382a1..19ced3202d 100644 --- a/common/repositories/base/base_tradeskill_recipe_repository.h +++ b/common/repositories/base/base_tradeskill_recipe_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_TRADESKILL_RECIPE_REPOSITORY_H -#define EQEMU_BASE_TRADESKILL_RECIPE_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseTradeskillRecipeRepository { @@ -555,5 +555,3 @@ class BaseTradeskillRecipeRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_TRADESKILL_RECIPE_REPOSITORY_H diff --git a/common/repositories/base/base_traps_repository.h b/common/repositories/base/base_traps_repository.h index e5efc26b5d..863eba234b 100644 --- a/common/repositories/base/base_traps_repository.h +++ b/common/repositories/base/base_traps_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_TRAPS_REPOSITORY_H -#define EQEMU_BASE_TRAPS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseTrapsRepository { @@ -663,5 +663,3 @@ class BaseTrapsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_TRAPS_REPOSITORY_H diff --git a/common/repositories/base/base_tribute_levels_repository.h b/common/repositories/base/base_tribute_levels_repository.h index 28be3327fd..c721359b42 100644 --- a/common/repositories/base/base_tribute_levels_repository.h +++ b/common/repositories/base/base_tribute_levels_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_TRIBUTE_LEVELS_REPOSITORY_H -#define EQEMU_BASE_TRIBUTE_LEVELS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseTributeLevelsRepository { @@ -412,5 +412,3 @@ class BaseTributeLevelsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_TRIBUTE_LEVELS_REPOSITORY_H diff --git a/common/repositories/base/base_tributes_repository.h b/common/repositories/base/base_tributes_repository.h index 5c6b7c4022..ff3cc30f0d 100644 --- a/common/repositories/base/base_tributes_repository.h +++ b/common/repositories/base/base_tributes_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_TRIBUTES_REPOSITORY_H -#define EQEMU_BASE_TRIBUTES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseTributesRepository { @@ -424,5 +424,3 @@ class BaseTributesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_TRIBUTES_REPOSITORY_H diff --git a/common/repositories/base/base_variables_repository.h b/common/repositories/base/base_variables_repository.h index 9f3516c90d..84cd137740 100644 --- a/common/repositories/base/base_variables_repository.h +++ b/common/repositories/base/base_variables_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_VARIABLES_REPOSITORY_H -#define EQEMU_BASE_VARIABLES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseVariablesRepository { @@ -423,5 +423,3 @@ class BaseVariablesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_VARIABLES_REPOSITORY_H diff --git a/common/repositories/base/base_veteran_reward_templates_repository.h b/common/repositories/base/base_veteran_reward_templates_repository.h index fc5f52a0d4..13e5ede316 100644 --- a/common/repositories/base/base_veteran_reward_templates_repository.h +++ b/common/repositories/base/base_veteran_reward_templates_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_VETERAN_REWARD_TEMPLATES_REPOSITORY_H -#define EQEMU_BASE_VETERAN_REWARD_TEMPLATES_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseVeteranRewardTemplatesRepository { @@ -424,5 +424,3 @@ class BaseVeteranRewardTemplatesRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_VETERAN_REWARD_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/base/base_zone_flags_repository.h b/common/repositories/base/base_zone_flags_repository.h index dfda1f18a8..8d8e17d010 100644 --- a/common/repositories/base/base_zone_flags_repository.h +++ b/common/repositories/base/base_zone_flags_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ZONE_FLAGS_REPOSITORY_H -#define EQEMU_BASE_ZONE_FLAGS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseZoneFlagsRepository { @@ -388,5 +388,3 @@ class BaseZoneFlagsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ZONE_FLAGS_REPOSITORY_H diff --git a/common/repositories/base/base_zone_points_repository.h b/common/repositories/base/base_zone_points_repository.h index b4e91c20de..536f754371 100644 --- a/common/repositories/base/base_zone_points_repository.h +++ b/common/repositories/base/base_zone_points_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ZONE_POINTS_REPOSITORY_H -#define EQEMU_BASE_ZONE_POINTS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseZonePointsRepository { @@ -651,5 +651,3 @@ class BaseZonePointsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ZONE_POINTS_REPOSITORY_H diff --git a/common/repositories/base/base_zone_repository.h b/common/repositories/base/base_zone_repository.h index 1b42931098..a131cd5704 100644 --- a/common/repositories/base/base_zone_repository.h +++ b/common/repositories/base/base_zone_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ZONE_REPOSITORY_H -#define EQEMU_BASE_ZONE_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseZoneRepository { @@ -1551,5 +1551,3 @@ class BaseZoneRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ZONE_REPOSITORY_H diff --git a/common/repositories/base/base_zone_state_spawns_repository.h b/common/repositories/base/base_zone_state_spawns_repository.h index d77e11b475..197e52eae4 100644 --- a/common/repositories/base/base_zone_state_spawns_repository.h +++ b/common/repositories/base/base_zone_state_spawns_repository.h @@ -6,14 +6,14 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_ZONE_STATE_SPAWNS_REPOSITORY_H -#define EQEMU_BASE_ZONE_STATE_SPAWNS_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" #include class BaseZoneStateSpawnsRepository { @@ -711,5 +711,3 @@ class BaseZoneStateSpawnsRepository { return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_ZONE_STATE_SPAWNS_REPOSITORY_H diff --git a/common/repositories/base_data_repository.h b/common/repositories/base_data_repository.h index fc9cc584b5..21b3bf20a4 100644 --- a/common/repositories/base_data_repository.h +++ b/common/repositories/base_data_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BASE_DATA_REPOSITORY_H -#define EQEMU_BASE_DATA_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_base_data_repository.h" +#include "common/repositories/base/base_base_data_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BaseDataRepository: public BaseBaseDataRepository { public: @@ -63,5 +63,3 @@ class BaseDataRepository: public BaseBaseDataRepository { return lines; } }; - -#endif //EQEMU_BASE_DATA_REPOSITORY_H diff --git a/common/repositories/blocked_spells_repository.h b/common/repositories/blocked_spells_repository.h index b5d669df2c..652ced8935 100644 --- a/common/repositories/blocked_spells_repository.h +++ b/common/repositories/blocked_spells_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BLOCKED_SPELLS_REPOSITORY_H -#define EQEMU_BLOCKED_SPELLS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_blocked_spells_repository.h" +#include "common/repositories/base/base_blocked_spells_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BlockedSpellsRepository: public BaseBlockedSpellsRepository { public: @@ -46,5 +46,3 @@ class BlockedSpellsRepository: public BaseBlockedSpellsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BLOCKED_SPELLS_REPOSITORY_H diff --git a/common/repositories/books_repository.h b/common/repositories/books_repository.h index d174e9194e..3aeedb6778 100644 --- a/common/repositories/books_repository.h +++ b/common/repositories/books_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOOKS_REPOSITORY_H -#define EQEMU_BOOKS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_books_repository.h" +#include "common/repositories/base/base_books_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BooksRepository: public BaseBooksRepository { public: @@ -46,5 +46,3 @@ class BooksRepository: public BaseBooksRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOOKS_REPOSITORY_H diff --git a/common/repositories/bot_blocked_buffs_repository.h b/common/repositories/bot_blocked_buffs_repository.h index be6466cbbe..8734e4c0d3 100644 --- a/common/repositories/bot_blocked_buffs_repository.h +++ b/common/repositories/bot_blocked_buffs_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_BLOCKED_BUFFS_REPOSITORY_H -#define EQEMU_BOT_BLOCKED_BUFFS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_blocked_buffs_repository.h" +#include "common/repositories/base/base_bot_blocked_buffs_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotBlockedBuffsRepository: public BaseBotBlockedBuffsRepository { public: @@ -46,5 +46,3 @@ class BotBlockedBuffsRepository: public BaseBotBlockedBuffsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_BLOCKED_BUFFS_REPOSITORY_H diff --git a/common/repositories/bot_buffs_repository.h b/common/repositories/bot_buffs_repository.h index e7019601c4..2e0b85fffa 100644 --- a/common/repositories/bot_buffs_repository.h +++ b/common/repositories/bot_buffs_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_BUFFS_REPOSITORY_H -#define EQEMU_BOT_BUFFS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_buffs_repository.h" +#include "common/repositories/base/base_bot_buffs_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotBuffsRepository: public BaseBotBuffsRepository { public: @@ -46,5 +46,3 @@ class BotBuffsRepository: public BaseBotBuffsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_BUFFS_REPOSITORY_H diff --git a/common/repositories/bot_create_combinations_repository.h b/common/repositories/bot_create_combinations_repository.h index 3955c91555..ea003e31ab 100644 --- a/common/repositories/bot_create_combinations_repository.h +++ b/common/repositories/bot_create_combinations_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_CREATE_COMBINATIONS_REPOSITORY_H -#define EQEMU_BOT_CREATE_COMBINATIONS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_create_combinations_repository.h" +#include "common/repositories/base/base_bot_create_combinations_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotCreateCombinationsRepository: public BaseBotCreateCombinationsRepository { public: @@ -46,5 +46,3 @@ class BotCreateCombinationsRepository: public BaseBotCreateCombinationsRepositor // Custom extended repository methods here }; - -#endif //EQEMU_BOT_CREATE_COMBINATIONS_REPOSITORY_H diff --git a/common/repositories/bot_data_repository.h b/common/repositories/bot_data_repository.h index e8d0038a44..0d36d9ff95 100644 --- a/common/repositories/bot_data_repository.h +++ b/common/repositories/bot_data_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_DATA_REPOSITORY_H -#define EQEMU_BOT_DATA_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_data_repository.h" +#include "common/repositories/base/base_bot_data_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotDataRepository: public BaseBotDataRepository { public: @@ -45,5 +45,3 @@ class BotDataRepository: public BaseBotDataRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_DATA_REPOSITORY_H diff --git a/common/repositories/bot_group_members_repository.h b/common/repositories/bot_group_members_repository.h index 837a5167e1..2c932962ff 100644 --- a/common/repositories/bot_group_members_repository.h +++ b/common/repositories/bot_group_members_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_GROUP_MEMBERS_REPOSITORY_H -#define EQEMU_BOT_GROUP_MEMBERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_group_members_repository.h" +#include "common/repositories/base/base_bot_group_members_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotGroupMembersRepository: public BaseBotGroupMembersRepository { public: @@ -46,5 +46,3 @@ class BotGroupMembersRepository: public BaseBotGroupMembersRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_GROUP_MEMBERS_REPOSITORY_H diff --git a/common/repositories/bot_groups_repository.h b/common/repositories/bot_groups_repository.h index bd58f13562..cc1f2c627e 100644 --- a/common/repositories/bot_groups_repository.h +++ b/common/repositories/bot_groups_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_GROUPS_REPOSITORY_H -#define EQEMU_BOT_GROUPS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_groups_repository.h" +#include "common/repositories/base/base_bot_groups_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotGroupsRepository: public BaseBotGroupsRepository { public: @@ -46,5 +46,3 @@ class BotGroupsRepository: public BaseBotGroupsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_GROUPS_REPOSITORY_H diff --git a/common/repositories/bot_guild_members_repository.h b/common/repositories/bot_guild_members_repository.h index 314a24b239..d51eb3f63d 100644 --- a/common/repositories/bot_guild_members_repository.h +++ b/common/repositories/bot_guild_members_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_GUILD_MEMBERS_REPOSITORY_H -#define EQEMU_BOT_GUILD_MEMBERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_guild_members_repository.h" +#include "common/repositories/base/base_bot_guild_members_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotGuildMembersRepository: public BaseBotGuildMembersRepository { public: @@ -46,5 +46,3 @@ class BotGuildMembersRepository: public BaseBotGuildMembersRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_GUILD_MEMBERS_REPOSITORY_H diff --git a/common/repositories/bot_heal_rotation_members_repository.h b/common/repositories/bot_heal_rotation_members_repository.h index 4e0c1d0576..91bf040bdc 100644 --- a/common/repositories/bot_heal_rotation_members_repository.h +++ b/common/repositories/bot_heal_rotation_members_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H -#define EQEMU_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_heal_rotation_members_repository.h" +#include "common/repositories/base/base_bot_heal_rotation_members_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotHealRotationMembersRepository: public BaseBotHealRotationMembersRepository { public: @@ -46,5 +46,3 @@ class BotHealRotationMembersRepository: public BaseBotHealRotationMembersReposit // Custom extended repository methods here }; - -#endif //EQEMU_BOT_HEAL_ROTATION_MEMBERS_REPOSITORY_H diff --git a/common/repositories/bot_heal_rotation_targets_repository.h b/common/repositories/bot_heal_rotation_targets_repository.h index 1faa29ac46..a91dd62061 100644 --- a/common/repositories/bot_heal_rotation_targets_repository.h +++ b/common/repositories/bot_heal_rotation_targets_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H -#define EQEMU_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_heal_rotation_targets_repository.h" +#include "common/repositories/base/base_bot_heal_rotation_targets_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotHealRotationTargetsRepository: public BaseBotHealRotationTargetsRepository { public: @@ -46,5 +46,3 @@ class BotHealRotationTargetsRepository: public BaseBotHealRotationTargetsReposit // Custom extended repository methods here }; - -#endif //EQEMU_BOT_HEAL_ROTATION_TARGETS_REPOSITORY_H diff --git a/common/repositories/bot_heal_rotations_repository.h b/common/repositories/bot_heal_rotations_repository.h index a5994fc5dd..a816e8598b 100644 --- a/common/repositories/bot_heal_rotations_repository.h +++ b/common/repositories/bot_heal_rotations_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_HEAL_ROTATIONS_REPOSITORY_H -#define EQEMU_BOT_HEAL_ROTATIONS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_heal_rotations_repository.h" +#include "common/repositories/base/base_bot_heal_rotations_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotHealRotationsRepository: public BaseBotHealRotationsRepository { public: @@ -46,5 +46,3 @@ class BotHealRotationsRepository: public BaseBotHealRotationsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_HEAL_ROTATIONS_REPOSITORY_H diff --git a/common/repositories/bot_inspect_messages_repository.h b/common/repositories/bot_inspect_messages_repository.h index bf9bef7107..396409223c 100644 --- a/common/repositories/bot_inspect_messages_repository.h +++ b/common/repositories/bot_inspect_messages_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_INSPECT_MESSAGES_REPOSITORY_H -#define EQEMU_BOT_INSPECT_MESSAGES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_inspect_messages_repository.h" +#include "common/repositories/base/base_bot_inspect_messages_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotInspectMessagesRepository: public BaseBotInspectMessagesRepository { public: @@ -75,5 +75,3 @@ class BotInspectMessagesRepository: public BaseBotInspectMessagesRepository { return results.Success(); } }; - -#endif //EQEMU_BOT_INSPECT_MESSAGES_REPOSITORY_H diff --git a/common/repositories/bot_inventories_repository.h b/common/repositories/bot_inventories_repository.h index b16a1237f6..1dc2856ae4 100644 --- a/common/repositories/bot_inventories_repository.h +++ b/common/repositories/bot_inventories_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_INVENTORIES_REPOSITORY_H -#define EQEMU_BOT_INVENTORIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_inventories_repository.h" +#include "common/repositories/base/base_bot_inventories_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotInventoriesRepository: public BaseBotInventoriesRepository { public: @@ -96,5 +96,3 @@ class BotInventoriesRepository: public BaseBotInventoriesRepository { return results.Success(); } }; - -#endif //EQEMU_BOT_INVENTORIES_REPOSITORY_H diff --git a/common/repositories/bot_owner_options_repository.h b/common/repositories/bot_owner_options_repository.h index ecc698e7db..e9c0176e8b 100644 --- a/common/repositories/bot_owner_options_repository.h +++ b/common/repositories/bot_owner_options_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_OWNER_OPTIONS_REPOSITORY_H -#define EQEMU_BOT_OWNER_OPTIONS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_owner_options_repository.h" +#include "common/repositories/base/base_bot_owner_options_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotOwnerOptionsRepository: public BaseBotOwnerOptionsRepository { public: @@ -46,5 +46,3 @@ class BotOwnerOptionsRepository: public BaseBotOwnerOptionsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_OWNER_OPTIONS_REPOSITORY_H diff --git a/common/repositories/bot_pet_buffs_repository.h b/common/repositories/bot_pet_buffs_repository.h index 546b94f8b6..69fc84c143 100644 --- a/common/repositories/bot_pet_buffs_repository.h +++ b/common/repositories/bot_pet_buffs_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_PET_BUFFS_REPOSITORY_H -#define EQEMU_BOT_PET_BUFFS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_pet_buffs_repository.h" +#include "common/repositories/base/base_bot_pet_buffs_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotPetBuffsRepository: public BaseBotPetBuffsRepository { public: @@ -46,5 +46,3 @@ class BotPetBuffsRepository: public BaseBotPetBuffsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_PET_BUFFS_REPOSITORY_H diff --git a/common/repositories/bot_pet_inventories_repository.h b/common/repositories/bot_pet_inventories_repository.h index 0ad1c74607..ee220dd8fc 100644 --- a/common/repositories/bot_pet_inventories_repository.h +++ b/common/repositories/bot_pet_inventories_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_PET_INVENTORIES_REPOSITORY_H -#define EQEMU_BOT_PET_INVENTORIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_pet_inventories_repository.h" +#include "common/repositories/base/base_bot_pet_inventories_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotPetInventoriesRepository: public BaseBotPetInventoriesRepository { public: @@ -46,5 +46,3 @@ class BotPetInventoriesRepository: public BaseBotPetInventoriesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_PET_INVENTORIES_REPOSITORY_H diff --git a/common/repositories/bot_pets_repository.h b/common/repositories/bot_pets_repository.h index 808d52bc28..c66ac638a6 100644 --- a/common/repositories/bot_pets_repository.h +++ b/common/repositories/bot_pets_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_PETS_REPOSITORY_H -#define EQEMU_BOT_PETS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_pets_repository.h" +#include "common/repositories/base/base_bot_pets_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotPetsRepository: public BaseBotPetsRepository { public: @@ -46,5 +46,3 @@ class BotPetsRepository: public BaseBotPetsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_PETS_REPOSITORY_H diff --git a/common/repositories/bot_settings_repository.h b/common/repositories/bot_settings_repository.h index 7cf1d0dbd1..29c1920fac 100644 --- a/common/repositories/bot_settings_repository.h +++ b/common/repositories/bot_settings_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_SETTINGS_REPOSITORY_H -#define EQEMU_BOT_SETTINGS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_settings_repository.h" +#include "common/repositories/base/base_bot_settings_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotSettingsRepository: public BaseBotSettingsRepository { public: @@ -46,5 +46,3 @@ class BotSettingsRepository: public BaseBotSettingsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_SETTINGS_REPOSITORY_H diff --git a/common/repositories/bot_spell_casting_chances_repository.h b/common/repositories/bot_spell_casting_chances_repository.h index b8c2ac9215..bd6c50329b 100644 --- a/common/repositories/bot_spell_casting_chances_repository.h +++ b/common/repositories/bot_spell_casting_chances_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H -#define EQEMU_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_spell_casting_chances_repository.h" +#include "common/repositories/base/base_bot_spell_casting_chances_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotSpellCastingChancesRepository: public BaseBotSpellCastingChancesRepository { public: @@ -46,5 +46,3 @@ class BotSpellCastingChancesRepository: public BaseBotSpellCastingChancesReposit // Custom extended repository methods here }; - -#endif //EQEMU_BOT_SPELL_CASTING_CHANCES_REPOSITORY_H diff --git a/common/repositories/bot_spell_settings_repository.h b/common/repositories/bot_spell_settings_repository.h index 595e085259..0daf696530 100644 --- a/common/repositories/bot_spell_settings_repository.h +++ b/common/repositories/bot_spell_settings_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_SPELL_SETTINGS_REPOSITORY_H -#define EQEMU_BOT_SPELL_SETTINGS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_spell_settings_repository.h" +#include "common/repositories/base/base_bot_spell_settings_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotSpellSettingsRepository: public BaseBotSpellSettingsRepository { public: @@ -71,5 +71,3 @@ class BotSpellSettingsRepository: public BaseBotSpellSettingsRepository { return (results.Success() ? true : false); } }; - -#endif //EQEMU_BOT_SPELL_SETTINGS_REPOSITORY_H diff --git a/common/repositories/bot_spells_entries_repository.h b/common/repositories/bot_spells_entries_repository.h index 5901df341b..3ee67551ee 100644 --- a/common/repositories/bot_spells_entries_repository.h +++ b/common/repositories/bot_spells_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_SPELLS_ENTRIES_REPOSITORY_H -#define EQEMU_BOT_SPELLS_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_spells_entries_repository.h" +#include "common/repositories/base/base_bot_spells_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotSpellsEntriesRepository: public BaseBotSpellsEntriesRepository { public: @@ -46,5 +46,3 @@ class BotSpellsEntriesRepository: public BaseBotSpellsEntriesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_SPELLS_ENTRIES_REPOSITORY_H diff --git a/common/repositories/bot_stances_repository.h b/common/repositories/bot_stances_repository.h index a9a0e49e0c..5a896ac69c 100644 --- a/common/repositories/bot_stances_repository.h +++ b/common/repositories/bot_stances_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_STANCES_REPOSITORY_H -#define EQEMU_BOT_STANCES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_stances_repository.h" +#include "common/repositories/base/base_bot_stances_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotStancesRepository: public BaseBotStancesRepository { public: @@ -46,5 +46,3 @@ class BotStancesRepository: public BaseBotStancesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_STANCES_REPOSITORY_H diff --git a/common/repositories/bot_starting_items_repository.h b/common/repositories/bot_starting_items_repository.h index 6dbb5915d7..8583732a3f 100644 --- a/common/repositories/bot_starting_items_repository.h +++ b/common/repositories/bot_starting_items_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_STARTING_ITEMS_REPOSITORY_H -#define EQEMU_BOT_STARTING_ITEMS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_starting_items_repository.h" +#include "common/repositories/base/base_bot_starting_items_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotStartingItemsRepository: public BaseBotStartingItemsRepository { public: @@ -46,5 +46,3 @@ class BotStartingItemsRepository: public BaseBotStartingItemsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_STARTING_ITEMS_REPOSITORY_H diff --git a/common/repositories/bot_timers_repository.h b/common/repositories/bot_timers_repository.h index 19cf9269e0..d9d9d165e4 100644 --- a/common/repositories/bot_timers_repository.h +++ b/common/repositories/bot_timers_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BOT_TIMERS_REPOSITORY_H -#define EQEMU_BOT_TIMERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bot_timers_repository.h" +#include "common/repositories/base/base_bot_timers_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BotTimersRepository: public BaseBotTimersRepository { public: @@ -46,5 +46,3 @@ class BotTimersRepository: public BaseBotTimersRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BOT_TIMERS_REPOSITORY_H diff --git a/common/repositories/bug_reports_repository.h b/common/repositories/bug_reports_repository.h index a6f622d28d..dfbe7e1641 100644 --- a/common/repositories/bug_reports_repository.h +++ b/common/repositories/bug_reports_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BUG_REPORTS_REPOSITORY_H -#define EQEMU_BUG_REPORTS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bug_reports_repository.h" +#include "common/repositories/base/base_bug_reports_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BugReportsRepository: public BaseBugReportsRepository { public: @@ -46,5 +46,3 @@ class BugReportsRepository: public BaseBugReportsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BUG_REPORTS_REPOSITORY_H diff --git a/common/repositories/bugs_repository.h b/common/repositories/bugs_repository.h index f55d886582..22f2b25f42 100644 --- a/common/repositories/bugs_repository.h +++ b/common/repositories/bugs_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BUGS_REPOSITORY_H -#define EQEMU_BUGS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_bugs_repository.h" +#include "common/repositories/base/base_bugs_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BugsRepository: public BaseBugsRepository { public: @@ -46,5 +46,3 @@ class BugsRepository: public BaseBugsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_BUGS_REPOSITORY_H diff --git a/common/repositories/buyer_buy_lines_repository.h b/common/repositories/buyer_buy_lines_repository.h index 4fa374229b..8b236a48ee 100644 --- a/common/repositories/buyer_buy_lines_repository.h +++ b/common/repositories/buyer_buy_lines_repository.h @@ -1,14 +1,13 @@ -#ifndef EQEMU_BUYER_BUY_LINES_REPOSITORY_H -#define EQEMU_BUYER_BUY_LINES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_buyer_buy_lines_repository.h" -#include "buyer_trade_items_repository.h" -#include "character_data_repository.h" -#include "buyer_repository.h" +#include "common/repositories/base/base_buyer_buy_lines_repository.h" -#include "../eq_packet_structs.h" +#include "common/database.h" +#include "common/eq_packet_structs.h" +#include "common/repositories/buyer_repository.h" +#include "common/repositories/buyer_trade_items_repository.h" +#include "common/repositories/character_data_repository.h" +#include "common/strings.h" class BuyerBuyLinesRepository: public BaseBuyerBuyLinesRepository { public: @@ -356,5 +355,3 @@ class BuyerBuyLinesRepository: public BaseBuyerBuyLinesRepository { } }; - -#endif //EQEMU_BUYER_BUY_LINES_REPOSITORY_H diff --git a/common/repositories/buyer_repository.h b/common/repositories/buyer_repository.h index 2d402b0dca..8888acf7ff 100644 --- a/common/repositories/buyer_repository.h +++ b/common/repositories/buyer_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BUYER_REPOSITORY_H -#define EQEMU_BUYER_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_buyer_repository.h" +#include "common/repositories/base/base_buyer_repository.h" + +#include "common/database.h" +#include "common/strings.h" #include "base/base_buyer_trade_items_repository.h" #include "base/base_buyer_buy_lines_repository.h" @@ -176,5 +176,3 @@ class BuyerRepository: public BaseBuyerRepository { return true; } }; - -#endif //EQEMU_BUYER_REPOSITORY_H diff --git a/common/repositories/buyer_trade_items_repository.h b/common/repositories/buyer_trade_items_repository.h index f90430eb35..81b0848429 100644 --- a/common/repositories/buyer_trade_items_repository.h +++ b/common/repositories/buyer_trade_items_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_BUYER_TRADE_ITEMS_REPOSITORY_H -#define EQEMU_BUYER_TRADE_ITEMS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_buyer_trade_items_repository.h" +#include "common/repositories/base/base_buyer_trade_items_repository.h" + +#include "common/database.h" +#include "common/strings.h" class BuyerTradeItemsRepository: public BaseBuyerTradeItemsRepository { public: @@ -77,5 +77,3 @@ class BuyerTradeItemsRepository: public BaseBuyerTradeItemsRepository { return all_entries; } }; - -#endif //EQEMU_BUYER_TRADE_ITEMS_REPOSITORY_H diff --git a/common/repositories/char_create_combinations_repository.h b/common/repositories/char_create_combinations_repository.h index 42baebb021..cc81eb32b0 100644 --- a/common/repositories/char_create_combinations_repository.h +++ b/common/repositories/char_create_combinations_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHAR_CREATE_COMBINATIONS_REPOSITORY_H -#define EQEMU_CHAR_CREATE_COMBINATIONS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_char_create_combinations_repository.h" +#include "common/repositories/base/base_char_create_combinations_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharCreateCombinationsRepository: public BaseCharCreateCombinationsRepository { public: @@ -46,5 +46,3 @@ class CharCreateCombinationsRepository: public BaseCharCreateCombinationsReposit // Custom extended repository methods here }; - -#endif //EQEMU_CHAR_CREATE_COMBINATIONS_REPOSITORY_H diff --git a/common/repositories/char_create_point_allocations_repository.h b/common/repositories/char_create_point_allocations_repository.h index 8828d2521c..da0f42b256 100644 --- a/common/repositories/char_create_point_allocations_repository.h +++ b/common/repositories/char_create_point_allocations_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHAR_CREATE_POINT_ALLOCATIONS_REPOSITORY_H -#define EQEMU_CHAR_CREATE_POINT_ALLOCATIONS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_char_create_point_allocations_repository.h" +#include "common/repositories/base/base_char_create_point_allocations_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharCreatePointAllocationsRepository: public BaseCharCreatePointAllocationsRepository { public: @@ -46,5 +46,3 @@ class CharCreatePointAllocationsRepository: public BaseCharCreatePointAllocation // Custom extended repository methods here }; - -#endif //EQEMU_CHAR_CREATE_POINT_ALLOCATIONS_REPOSITORY_H diff --git a/common/repositories/char_recipe_list_repository.h b/common/repositories/char_recipe_list_repository.h index ee2cb67b82..32fc1958b7 100644 --- a/common/repositories/char_recipe_list_repository.h +++ b/common/repositories/char_recipe_list_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHAR_RECIPE_LIST_REPOSITORY_H -#define EQEMU_CHAR_RECIPE_LIST_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_char_recipe_list_repository.h" +#include "common/repositories/base/base_char_recipe_list_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharRecipeListRepository: public BaseCharRecipeListRepository { public: @@ -78,5 +78,3 @@ class CharRecipeListRepository: public BaseCharRecipeListRepository { } }; - -#endif //EQEMU_CHAR_RECIPE_LIST_REPOSITORY_H diff --git a/common/repositories/character_activities_repository.h b/common/repositories/character_activities_repository.h index 420548887a..aebb7c96ad 100644 --- a/common/repositories/character_activities_repository.h +++ b/common/repositories/character_activities_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_ACTIVITIES_REPOSITORY_H -#define EQEMU_CHARACTER_ACTIVITIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_activities_repository.h" +#include "common/repositories/base/base_character_activities_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterActivitiesRepository: public BaseCharacterActivitiesRepository { public: @@ -46,5 +46,3 @@ class CharacterActivitiesRepository: public BaseCharacterActivitiesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_ACTIVITIES_REPOSITORY_H diff --git a/common/repositories/character_alt_currency_repository.h b/common/repositories/character_alt_currency_repository.h index 1ef74dd58a..e7c211c24e 100644 --- a/common/repositories/character_alt_currency_repository.h +++ b/common/repositories/character_alt_currency_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_ALT_CURRENCY_REPOSITORY_H -#define EQEMU_CHARACTER_ALT_CURRENCY_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_alt_currency_repository.h" +#include "common/repositories/base/base_character_alt_currency_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterAltCurrencyRepository: public BaseCharacterAltCurrencyRepository { public: @@ -46,5 +46,3 @@ class CharacterAltCurrencyRepository: public BaseCharacterAltCurrencyRepository // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_ALT_CURRENCY_REPOSITORY_H diff --git a/common/repositories/character_alternate_abilities_repository.h b/common/repositories/character_alternate_abilities_repository.h index d3514c91fe..82df4ca00c 100644 --- a/common/repositories/character_alternate_abilities_repository.h +++ b/common/repositories/character_alternate_abilities_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H -#define EQEMU_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_alternate_abilities_repository.h" +#include "common/repositories/base/base_character_alternate_abilities_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterAlternateAbilitiesRepository: public BaseCharacterAlternateAbilitiesRepository { public: @@ -46,5 +46,3 @@ class CharacterAlternateAbilitiesRepository: public BaseCharacterAlternateAbilit // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_ALTERNATE_ABILITIES_REPOSITORY_H diff --git a/common/repositories/character_auras_repository.h b/common/repositories/character_auras_repository.h index f03154a3ba..9e9f39d621 100644 --- a/common/repositories/character_auras_repository.h +++ b/common/repositories/character_auras_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_AURAS_REPOSITORY_H -#define EQEMU_CHARACTER_AURAS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_auras_repository.h" +#include "common/repositories/base/base_character_auras_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterAurasRepository: public BaseCharacterAurasRepository { public: @@ -46,5 +46,3 @@ class CharacterAurasRepository: public BaseCharacterAurasRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_AURAS_REPOSITORY_H diff --git a/common/repositories/character_bandolier_repository.h b/common/repositories/character_bandolier_repository.h index ff2a6dcc00..fca31af3a5 100644 --- a/common/repositories/character_bandolier_repository.h +++ b/common/repositories/character_bandolier_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_BANDOLIER_REPOSITORY_H -#define EQEMU_CHARACTER_BANDOLIER_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_bandolier_repository.h" +#include "common/repositories/base/base_character_bandolier_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterBandolierRepository: public BaseCharacterBandolierRepository { public: @@ -46,5 +46,3 @@ class CharacterBandolierRepository: public BaseCharacterBandolierRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_BANDOLIER_REPOSITORY_H diff --git a/common/repositories/character_bind_repository.h b/common/repositories/character_bind_repository.h index a78bef4159..a2b576f823 100644 --- a/common/repositories/character_bind_repository.h +++ b/common/repositories/character_bind_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_BIND_REPOSITORY_H -#define EQEMU_CHARACTER_BIND_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_bind_repository.h" +#include "common/repositories/base/base_character_bind_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterBindRepository: public BaseCharacterBindRepository { public: @@ -46,5 +46,3 @@ class CharacterBindRepository: public BaseCharacterBindRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_BIND_REPOSITORY_H diff --git a/common/repositories/character_buffs_repository.h b/common/repositories/character_buffs_repository.h index 92a81fe056..ce4587b11f 100644 --- a/common/repositories/character_buffs_repository.h +++ b/common/repositories/character_buffs_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_BUFFS_REPOSITORY_H -#define EQEMU_CHARACTER_BUFFS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_buffs_repository.h" +#include "common/repositories/base/base_character_buffs_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterBuffsRepository: public BaseCharacterBuffsRepository { public: @@ -46,5 +46,3 @@ class CharacterBuffsRepository: public BaseCharacterBuffsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_BUFFS_REPOSITORY_H diff --git a/common/repositories/character_corpse_items_repository.h b/common/repositories/character_corpse_items_repository.h index 1a0352d8f1..e1da52f0a5 100644 --- a/common/repositories/character_corpse_items_repository.h +++ b/common/repositories/character_corpse_items_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_CORPSE_ITEMS_REPOSITORY_H -#define EQEMU_CHARACTER_CORPSE_ITEMS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_corpse_items_repository.h" +#include "common/repositories/base/base_character_corpse_items_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterCorpseItemsRepository: public BaseCharacterCorpseItemsRepository { public: @@ -46,5 +46,3 @@ class CharacterCorpseItemsRepository: public BaseCharacterCorpseItemsRepository // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_CORPSE_ITEMS_REPOSITORY_H diff --git a/common/repositories/character_corpses_repository.h b/common/repositories/character_corpses_repository.h index 0e60949fb8..7d81c1bd06 100644 --- a/common/repositories/character_corpses_repository.h +++ b/common/repositories/character_corpses_repository.h @@ -1,10 +1,12 @@ -#ifndef EQEMU_CHARACTER_CORPSES_REPOSITORY_H -#define EQEMU_CHARACTER_CORPSES_REPOSITORY_H +#pragma once -#include -#include "../database.h" -#include "../strings.h" -#include "base/base_character_corpses_repository.h" +#include "common/repositories/base/base_character_corpses_repository.h" +#include "common/rulesys.h" + +#include "common/database.h" +#include "common/strings.h" + +#include "glm/vec4.hpp" class CharacterCorpsesRepository: public BaseCharacterCorpsesRepository { public: @@ -247,5 +249,3 @@ class CharacterCorpsesRepository: public BaseCharacterCorpsesRepository { return results.Success() ? results.RowsAffected() : 0; } }; - -#endif //EQEMU_CHARACTER_CORPSES_REPOSITORY_H diff --git a/common/repositories/character_currency_repository.h b/common/repositories/character_currency_repository.h index 833e6cbf2e..3c94246f73 100644 --- a/common/repositories/character_currency_repository.h +++ b/common/repositories/character_currency_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_CURRENCY_REPOSITORY_H -#define EQEMU_CHARACTER_CURRENCY_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_currency_repository.h" +#include "common/repositories/base/base_character_currency_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterCurrencyRepository: public BaseCharacterCurrencyRepository { public: @@ -46,5 +46,3 @@ class CharacterCurrencyRepository: public BaseCharacterCurrencyRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_CURRENCY_REPOSITORY_H diff --git a/common/repositories/character_data_repository.h b/common/repositories/character_data_repository.h index 68390fc35e..6e5eff5f2a 100644 --- a/common/repositories/character_data_repository.h +++ b/common/repositories/character_data_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_DATA_REPOSITORY_H -#define EQEMU_CHARACTER_DATA_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_data_repository.h" +#include "common/repositories/base/base_character_data_repository.h" + +#include "common/database.h" +#include "common/strings.h" @@ -208,5 +208,3 @@ class CharacterDataRepository: public BaseCharacterDataRepository { return Strings::ToUnsignedInt(row[0]); } }; - -#endif //EQEMU_CHARACTER_DATA_REPOSITORY_H diff --git a/common/repositories/character_disciplines_repository.h b/common/repositories/character_disciplines_repository.h index a6a0ff2257..20755c794e 100644 --- a/common/repositories/character_disciplines_repository.h +++ b/common/repositories/character_disciplines_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_DISCIPLINES_REPOSITORY_H -#define EQEMU_CHARACTER_DISCIPLINES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_disciplines_repository.h" +#include "common/repositories/base/base_character_disciplines_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterDisciplinesRepository: public BaseCharacterDisciplinesRepository { public: @@ -46,5 +46,3 @@ class CharacterDisciplinesRepository: public BaseCharacterDisciplinesRepository // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_DISCIPLINES_REPOSITORY_H diff --git a/common/repositories/character_evolving_items_repository.h b/common/repositories/character_evolving_items_repository.h index 8bc379505d..7a039dcad7 100644 --- a/common/repositories/character_evolving_items_repository.h +++ b/common/repositories/character_evolving_items_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_EVOLVING_ITEMS_REPOSITORY_H -#define EQEMU_CHARACTER_EVOLVING_ITEMS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_evolving_items_repository.h" +#include "common/repositories/base/base_character_evolving_items_repository.h" + +#include "common/database.h" +#include "common/strings.h" #include @@ -62,5 +62,3 @@ class CharacterEvolvingItemsRepository: public BaseCharacterEvolvingItemsReposit return UpdateOne(db, e); } }; - -#endif //EQEMU_CHARACTER_EVOLVING_ITEMS_REPOSITORY_H diff --git a/common/repositories/character_exp_modifiers_repository.h b/common/repositories/character_exp_modifiers_repository.h index 71d8f1c6bb..69ab3d5e14 100644 --- a/common/repositories/character_exp_modifiers_repository.h +++ b/common/repositories/character_exp_modifiers_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_EXP_MODIFIERS_REPOSITORY_H -#define EQEMU_CHARACTER_EXP_MODIFIERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_exp_modifiers_repository.h" +#include "common/repositories/base/base_character_exp_modifiers_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterExpModifiersRepository: public BaseCharacterExpModifiersRepository { public: @@ -102,5 +102,3 @@ class CharacterExpModifiersRepository: public BaseCharacterExpModifiersRepositor ); } }; - -#endif //EQEMU_CHARACTER_EXP_MODIFIERS_REPOSITORY_H diff --git a/common/repositories/character_expedition_lockouts_repository.h b/common/repositories/character_expedition_lockouts_repository.h index 54fcc87044..6bc0f91893 100644 --- a/common/repositories/character_expedition_lockouts_repository.h +++ b/common/repositories/character_expedition_lockouts_repository.h @@ -1,10 +1,11 @@ -#ifndef EQEMU_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H -#define EQEMU_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H +#pragma once + +#include "common/repositories/base/base_character_expedition_lockouts_repository.h" + +#include "common/database.h" +#include "common/dynamic_zone_lockout.h" +#include "common/strings.h" -#include "../database.h" -#include "../dynamic_zone_lockout.h" -#include "../strings.h" -#include "base/base_character_expedition_lockouts_repository.h" #include class CharacterExpeditionLockoutsRepository: public BaseCharacterExpeditionLockoutsRepository { @@ -225,5 +226,3 @@ class CharacterExpeditionLockoutsRepository: public BaseCharacterExpeditionLocko } }; - -#endif //EQEMU_CHARACTER_EXPEDITION_LOCKOUTS_REPOSITORY_H diff --git a/common/repositories/character_inspect_messages_repository.h b/common/repositories/character_inspect_messages_repository.h index b3c8b5cbc7..d4abfb7d69 100644 --- a/common/repositories/character_inspect_messages_repository.h +++ b/common/repositories/character_inspect_messages_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_INSPECT_MESSAGES_REPOSITORY_H -#define EQEMU_CHARACTER_INSPECT_MESSAGES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_inspect_messages_repository.h" +#include "common/repositories/base/base_character_inspect_messages_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterInspectMessagesRepository: public BaseCharacterInspectMessagesRepository { public: @@ -46,5 +46,3 @@ class CharacterInspectMessagesRepository: public BaseCharacterInspectMessagesRep // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_INSPECT_MESSAGES_REPOSITORY_H diff --git a/common/repositories/character_instance_safereturns_repository.h b/common/repositories/character_instance_safereturns_repository.h index 681f4f6ad9..dc240a68a3 100644 --- a/common/repositories/character_instance_safereturns_repository.h +++ b/common/repositories/character_instance_safereturns_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_INSTANCE_SAFERETURNS_REPOSITORY_H -#define EQEMU_CHARACTER_INSTANCE_SAFERETURNS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_instance_safereturns_repository.h" +#include "common/repositories/base/base_character_instance_safereturns_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterInstanceSafereturnsRepository: public BaseCharacterInstanceSafereturnsRepository { public: @@ -84,5 +84,3 @@ class CharacterInstanceSafereturnsRepository: public BaseCharacterInstanceSafere return NewEntity(); } }; - -#endif //EQEMU_CHARACTER_INSTANCE_SAFERETURNS_REPOSITORY_H diff --git a/common/repositories/character_item_recast_repository.h b/common/repositories/character_item_recast_repository.h index 35a36559d0..1a1ecc295c 100644 --- a/common/repositories/character_item_recast_repository.h +++ b/common/repositories/character_item_recast_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_ITEM_RECAST_REPOSITORY_H -#define EQEMU_CHARACTER_ITEM_RECAST_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_item_recast_repository.h" +#include "common/repositories/base/base_character_item_recast_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterItemRecastRepository: public BaseCharacterItemRecastRepository { public: @@ -46,5 +46,3 @@ class CharacterItemRecastRepository: public BaseCharacterItemRecastRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_ITEM_RECAST_REPOSITORY_H diff --git a/common/repositories/character_languages_repository.h b/common/repositories/character_languages_repository.h index b4b866666c..4e3639da44 100644 --- a/common/repositories/character_languages_repository.h +++ b/common/repositories/character_languages_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_LANGUAGES_REPOSITORY_H -#define EQEMU_CHARACTER_LANGUAGES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_languages_repository.h" +#include "common/repositories/base/base_character_languages_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterLanguagesRepository: public BaseCharacterLanguagesRepository { public: @@ -46,5 +46,3 @@ class CharacterLanguagesRepository: public BaseCharacterLanguagesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_LANGUAGES_REPOSITORY_H diff --git a/common/repositories/character_leadership_abilities_repository.h b/common/repositories/character_leadership_abilities_repository.h index 5f688d9d52..66c8b52c52 100644 --- a/common/repositories/character_leadership_abilities_repository.h +++ b/common/repositories/character_leadership_abilities_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H -#define EQEMU_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_leadership_abilities_repository.h" +#include "common/repositories/base/base_character_leadership_abilities_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterLeadershipAbilitiesRepository: public BaseCharacterLeadershipAbilitiesRepository { public: @@ -46,5 +46,3 @@ class CharacterLeadershipAbilitiesRepository: public BaseCharacterLeadershipAbil // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_LEADERSHIP_ABILITIES_REPOSITORY_H diff --git a/common/repositories/character_material_repository.h b/common/repositories/character_material_repository.h index eb59890256..f98e259bc2 100644 --- a/common/repositories/character_material_repository.h +++ b/common/repositories/character_material_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_MATERIAL_REPOSITORY_H -#define EQEMU_CHARACTER_MATERIAL_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_material_repository.h" +#include "common/repositories/base/base_character_material_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterMaterialRepository: public BaseCharacterMaterialRepository { public: @@ -46,5 +46,3 @@ class CharacterMaterialRepository: public BaseCharacterMaterialRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_MATERIAL_REPOSITORY_H diff --git a/common/repositories/character_memmed_spells_repository.h b/common/repositories/character_memmed_spells_repository.h index cdf5cc5f0c..5cbf6ee2c3 100644 --- a/common/repositories/character_memmed_spells_repository.h +++ b/common/repositories/character_memmed_spells_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_MEMMED_SPELLS_REPOSITORY_H -#define EQEMU_CHARACTER_MEMMED_SPELLS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_memmed_spells_repository.h" +#include "common/repositories/base/base_character_memmed_spells_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterMemmedSpellsRepository: public BaseCharacterMemmedSpellsRepository { public: @@ -46,5 +46,3 @@ class CharacterMemmedSpellsRepository: public BaseCharacterMemmedSpellsRepositor // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_MEMMED_SPELLS_REPOSITORY_H diff --git a/common/repositories/character_parcels_containers_repository.h b/common/repositories/character_parcels_containers_repository.h index 80f23ad359..9ae52c8123 100644 --- a/common/repositories/character_parcels_containers_repository.h +++ b/common/repositories/character_parcels_containers_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_PARCELS_CONTAINERS_REPOSITORY_H -#define EQEMU_CHARACTER_PARCELS_CONTAINERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_parcels_containers_repository.h" +#include "common/repositories/base/base_character_parcels_containers_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterParcelsContainersRepository: public BaseCharacterParcelsContainersRepository { public: @@ -46,5 +46,3 @@ class CharacterParcelsContainersRepository: public BaseCharacterParcelsContainer // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_PARCELS_CONTAINERS_REPOSITORY_H diff --git a/common/repositories/character_parcels_repository.h b/common/repositories/character_parcels_repository.h index 5403d64370..35ab01cc74 100644 --- a/common/repositories/character_parcels_repository.h +++ b/common/repositories/character_parcels_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_PARCELS_REPOSITORY_H -#define EQEMU_CHARACTER_PARCELS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_parcels_repository.h" +#include "common/repositories/base/base_character_parcels_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterParcelsRepository: public BaseCharacterParcelsRepository { public: @@ -110,5 +110,3 @@ class CharacterParcelsRepository: public BaseCharacterParcelsRepository { return INVALID_INDEX; } }; - -#endif //EQEMU_CHARACTER_PARCELS_REPOSITORY_H diff --git a/common/repositories/character_peqzone_flags_repository.h b/common/repositories/character_peqzone_flags_repository.h index 3295a6c8cf..1b6e501f94 100644 --- a/common/repositories/character_peqzone_flags_repository.h +++ b/common/repositories/character_peqzone_flags_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_PEQZONE_FLAGS_REPOSITORY_H -#define EQEMU_CHARACTER_PEQZONE_FLAGS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_peqzone_flags_repository.h" +#include "common/repositories/base/base_character_peqzone_flags_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterPeqzoneFlagsRepository: public BaseCharacterPeqzoneFlagsRepository { public: @@ -58,5 +58,3 @@ class CharacterPeqzoneFlagsRepository: public BaseCharacterPeqzoneFlagsRepositor return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_CHARACTER_PEQZONE_FLAGS_REPOSITORY_H diff --git a/common/repositories/character_pet_buffs_repository.h b/common/repositories/character_pet_buffs_repository.h index b5ed82c630..a0fcd4b4c8 100644 --- a/common/repositories/character_pet_buffs_repository.h +++ b/common/repositories/character_pet_buffs_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_PET_BUFFS_REPOSITORY_H -#define EQEMU_CHARACTER_PET_BUFFS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_pet_buffs_repository.h" +#include "common/repositories/base/base_character_pet_buffs_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterPetBuffsRepository: public BaseCharacterPetBuffsRepository { public: @@ -46,5 +46,3 @@ class CharacterPetBuffsRepository: public BaseCharacterPetBuffsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_PET_BUFFS_REPOSITORY_H diff --git a/common/repositories/character_pet_info_repository.h b/common/repositories/character_pet_info_repository.h index 45c4f28549..062e4fb074 100644 --- a/common/repositories/character_pet_info_repository.h +++ b/common/repositories/character_pet_info_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_PET_INFO_REPOSITORY_H -#define EQEMU_CHARACTER_PET_INFO_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_pet_info_repository.h" +#include "common/repositories/base/base_character_pet_info_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterPetInfoRepository: public BaseCharacterPetInfoRepository { public: @@ -46,5 +46,3 @@ class CharacterPetInfoRepository: public BaseCharacterPetInfoRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_PET_INFO_REPOSITORY_H diff --git a/common/repositories/character_pet_inventory_repository.h b/common/repositories/character_pet_inventory_repository.h index 21fb5c3620..659a4da087 100644 --- a/common/repositories/character_pet_inventory_repository.h +++ b/common/repositories/character_pet_inventory_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_PET_INVENTORY_REPOSITORY_H -#define EQEMU_CHARACTER_PET_INVENTORY_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_pet_inventory_repository.h" +#include "common/repositories/base/base_character_pet_inventory_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterPetInventoryRepository: public BaseCharacterPetInventoryRepository { public: @@ -46,5 +46,3 @@ class CharacterPetInventoryRepository: public BaseCharacterPetInventoryRepositor // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_PET_INVENTORY_REPOSITORY_H diff --git a/common/repositories/character_pet_name_repository.h b/common/repositories/character_pet_name_repository.h index 8fbb1e94bf..43b39c27cb 100644 --- a/common/repositories/character_pet_name_repository.h +++ b/common/repositories/character_pet_name_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_CHARACTER_PET_NAME_REPOSITORY_H -#define EQEMU_CHARACTER_PET_NAME_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_pet_name_repository.h" +#include "common/repositories/base/base_character_pet_name_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterPetNameRepository: public BaseCharacterPetNameRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_PET_NAME_REPOSITORY_H diff --git a/common/repositories/character_potionbelt_repository.h b/common/repositories/character_potionbelt_repository.h index 1a69e67112..e6a2c8697c 100644 --- a/common/repositories/character_potionbelt_repository.h +++ b/common/repositories/character_potionbelt_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_POTIONBELT_REPOSITORY_H -#define EQEMU_CHARACTER_POTIONBELT_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_potionbelt_repository.h" +#include "common/repositories/base/base_character_potionbelt_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterPotionbeltRepository: public BaseCharacterPotionbeltRepository { public: @@ -46,5 +46,3 @@ class CharacterPotionbeltRepository: public BaseCharacterPotionbeltRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_POTIONBELT_REPOSITORY_H diff --git a/common/repositories/character_skills_repository.h b/common/repositories/character_skills_repository.h index c8c60e1042..9141ed94fb 100644 --- a/common/repositories/character_skills_repository.h +++ b/common/repositories/character_skills_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_SKILLS_REPOSITORY_H -#define EQEMU_CHARACTER_SKILLS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_skills_repository.h" +#include "common/repositories/base/base_character_skills_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterSkillsRepository: public BaseCharacterSkillsRepository { public: @@ -46,5 +46,3 @@ class CharacterSkillsRepository: public BaseCharacterSkillsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_SKILLS_REPOSITORY_H diff --git a/common/repositories/character_spells_repository.h b/common/repositories/character_spells_repository.h index 81c3f9697f..8408d266a1 100644 --- a/common/repositories/character_spells_repository.h +++ b/common/repositories/character_spells_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_SPELLS_REPOSITORY_H -#define EQEMU_CHARACTER_SPELLS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_spells_repository.h" +#include "common/repositories/base/base_character_spells_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterSpellsRepository: public BaseCharacterSpellsRepository { public: @@ -46,5 +46,3 @@ class CharacterSpellsRepository: public BaseCharacterSpellsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_SPELLS_REPOSITORY_H diff --git a/common/repositories/character_stats_record_repository.h b/common/repositories/character_stats_record_repository.h index 2539a869ba..5823bf0bdb 100644 --- a/common/repositories/character_stats_record_repository.h +++ b/common/repositories/character_stats_record_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_STATS_RECORD_REPOSITORY_H -#define EQEMU_CHARACTER_STATS_RECORD_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_stats_record_repository.h" +#include "common/repositories/base/base_character_stats_record_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterStatsRecordRepository: public BaseCharacterStatsRecordRepository { public: @@ -46,5 +46,3 @@ class CharacterStatsRecordRepository: public BaseCharacterStatsRecordRepository // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_STATS_RECORD_REPOSITORY_H diff --git a/common/repositories/character_task_timers_repository.h b/common/repositories/character_task_timers_repository.h index 4b153cd014..8791d29554 100644 --- a/common/repositories/character_task_timers_repository.h +++ b/common/repositories/character_task_timers_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_TASK_TIMERS_REPOSITORY_H -#define EQEMU_CHARACTER_TASK_TIMERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_task_timers_repository.h" +#include "common/repositories/base/base_character_task_timers_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterTaskTimersRepository: public BaseCharacterTaskTimersRepository { public: @@ -46,5 +46,3 @@ class CharacterTaskTimersRepository: public BaseCharacterTaskTimersRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_TASK_TIMERS_REPOSITORY_H diff --git a/common/repositories/character_tasks_repository.h b/common/repositories/character_tasks_repository.h index 15b44ccff5..dd29b73d4a 100644 --- a/common/repositories/character_tasks_repository.h +++ b/common/repositories/character_tasks_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_TASKS_REPOSITORY_H -#define EQEMU_CHARACTER_TASKS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_tasks_repository.h" +#include "common/repositories/base/base_character_tasks_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterTasksRepository: public BaseCharacterTasksRepository { public: @@ -46,5 +46,3 @@ class CharacterTasksRepository: public BaseCharacterTasksRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_TASKS_REPOSITORY_H diff --git a/common/repositories/character_tribute_repository.h b/common/repositories/character_tribute_repository.h index 64fbb9012a..f881885509 100644 --- a/common/repositories/character_tribute_repository.h +++ b/common/repositories/character_tribute_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHARACTER_TRIBUTE_REPOSITORY_H -#define EQEMU_CHARACTER_TRIBUTE_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_character_tribute_repository.h" +#include "common/repositories/base/base_character_tribute_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CharacterTributeRepository: public BaseCharacterTributeRepository { public: @@ -46,5 +46,3 @@ class CharacterTributeRepository: public BaseCharacterTributeRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHARACTER_TRIBUTE_REPOSITORY_H diff --git a/common/repositories/chatchannel_reserved_names_repository.h b/common/repositories/chatchannel_reserved_names_repository.h index 44fa806218..5da75b8576 100644 --- a/common/repositories/chatchannel_reserved_names_repository.h +++ b/common/repositories/chatchannel_reserved_names_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H -#define EQEMU_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_chatchannel_reserved_names_repository.h" +#include "common/repositories/base/base_chatchannel_reserved_names_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ChatchannelReservedNamesRepository: public BaseChatchannelReservedNamesRepository { public: @@ -46,5 +46,3 @@ class ChatchannelReservedNamesRepository: public BaseChatchannelReservedNamesRep // Custom extended repository methods here }; - -#endif //EQEMU_CHATCHANNEL_RESERVED_NAMES_REPOSITORY_H diff --git a/common/repositories/chatchannels_repository.h b/common/repositories/chatchannels_repository.h index 0b388d301f..132b8fd5c0 100644 --- a/common/repositories/chatchannels_repository.h +++ b/common/repositories/chatchannels_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CHATCHANNELS_REPOSITORY_H -#define EQEMU_CHATCHANNELS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_chatchannels_repository.h" +#include "common/repositories/base/base_chatchannels_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ChatchannelsRepository: public BaseChatchannelsRepository { public: @@ -46,5 +46,3 @@ class ChatchannelsRepository: public BaseChatchannelsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CHATCHANNELS_REPOSITORY_H diff --git a/common/repositories/command_subsettings_repository.h b/common/repositories/command_subsettings_repository.h index aa99d164a2..16aa9f8a97 100644 --- a/common/repositories/command_subsettings_repository.h +++ b/common/repositories/command_subsettings_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_COMMAND_SUBSETTINGS_REPOSITORY_H -#define EQEMU_COMMAND_SUBSETTINGS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_command_subsettings_repository.h" +#include "common/repositories/base/base_command_subsettings_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CommandSubsettingsRepository: public BaseCommandSubsettingsRepository { public: @@ -228,5 +228,3 @@ class CommandSubsettingsRepository: public BaseCommandSubsettingsRepository { return db_sub_settings; } }; - -#endif //EQEMU_COMMAND_SUBSETTINGS_REPOSITORY_H diff --git a/common/repositories/completed_shared_task_activity_state_repository.h b/common/repositories/completed_shared_task_activity_state_repository.h index 144bb124c0..a4315cd828 100644 --- a/common/repositories/completed_shared_task_activity_state_repository.h +++ b/common/repositories/completed_shared_task_activity_state_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_COMPLETED_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H -#define EQEMU_COMPLETED_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_completed_shared_task_activity_state_repository.h" +#include "common/repositories/base/base_completed_shared_task_activity_state_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CompletedSharedTaskActivityStateRepository: public BaseCompletedSharedTaskActivityStateRepository { public: @@ -46,5 +46,3 @@ class CompletedSharedTaskActivityStateRepository: public BaseCompletedSharedTask // Custom extended repository methods here }; - -#endif //EQEMU_COMPLETED_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H diff --git a/common/repositories/completed_shared_task_members_repository.h b/common/repositories/completed_shared_task_members_repository.h index 5e456f3c57..0d3523f805 100644 --- a/common/repositories/completed_shared_task_members_repository.h +++ b/common/repositories/completed_shared_task_members_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_COMPLETED_SHARED_TASK_MEMBERS_REPOSITORY_H -#define EQEMU_COMPLETED_SHARED_TASK_MEMBERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_completed_shared_task_members_repository.h" +#include "common/repositories/base/base_completed_shared_task_members_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CompletedSharedTaskMembersRepository: public BaseCompletedSharedTaskMembersRepository { public: @@ -46,5 +46,3 @@ class CompletedSharedTaskMembersRepository: public BaseCompletedSharedTaskMember // Custom extended repository methods here }; - -#endif //EQEMU_COMPLETED_SHARED_TASK_MEMBERS_REPOSITORY_H diff --git a/common/repositories/completed_shared_tasks_repository.h b/common/repositories/completed_shared_tasks_repository.h index 555a5775a5..a3a458646e 100644 --- a/common/repositories/completed_shared_tasks_repository.h +++ b/common/repositories/completed_shared_tasks_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_COMPLETED_SHARED_TASKS_REPOSITORY_H -#define EQEMU_COMPLETED_SHARED_TASKS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_completed_shared_tasks_repository.h" +#include "common/repositories/base/base_completed_shared_tasks_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CompletedSharedTasksRepository: public BaseCompletedSharedTasksRepository { public: @@ -46,5 +46,3 @@ class CompletedSharedTasksRepository: public BaseCompletedSharedTasksRepository // Custom extended repository methods here }; - -#endif //EQEMU_COMPLETED_SHARED_TASKS_REPOSITORY_H diff --git a/common/repositories/completed_tasks_repository.h b/common/repositories/completed_tasks_repository.h index 8bb00017ea..9257f364e4 100644 --- a/common/repositories/completed_tasks_repository.h +++ b/common/repositories/completed_tasks_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_COMPLETED_TASKS_REPOSITORY_H -#define EQEMU_COMPLETED_TASKS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_completed_tasks_repository.h" +#include "common/repositories/base/base_completed_tasks_repository.h" + +#include "common/database.h" +#include "common/strings.h" class CompletedTasksRepository: public BaseCompletedTasksRepository { public: @@ -46,5 +46,3 @@ class CompletedTasksRepository: public BaseCompletedTasksRepository { // Custom extended repository methods here }; - -#endif //EQEMU_COMPLETED_TASKS_REPOSITORY_H diff --git a/common/repositories/content_flags_repository.h b/common/repositories/content_flags_repository.h index b777155cd9..5f98a25d00 100644 --- a/common/repositories/content_flags_repository.h +++ b/common/repositories/content_flags_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CONTENT_FLAGS_REPOSITORY_H -#define EQEMU_CONTENT_FLAGS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_content_flags_repository.h" +#include "common/repositories/base/base_content_flags_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ContentFlagsRepository: public BaseContentFlagsRepository { public: @@ -46,5 +46,3 @@ class ContentFlagsRepository: public BaseContentFlagsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_CONTENT_FLAGS_REPOSITORY_H diff --git a/common/repositories/criteria/content_filter_criteria.h b/common/repositories/criteria/content_filter_criteria.h index e53fcab771..b94795c1c5 100644 --- a/common/repositories/criteria/content_filter_criteria.h +++ b/common/repositories/criteria/content_filter_criteria.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_CONTENT_FILTER_CRITERIA_H -#define EQEMU_CONTENT_FILTER_CRITERIA_H +#pragma once + +#include "common/content/world_content_service.h" +#include "common/strings.h" #include -#include "../../content/world_content_service.h" -#include "../../strings.h" namespace ContentFilterCriteria { static std::string apply(std::string table_prefix = "") @@ -69,5 +69,3 @@ namespace ContentFilterCriteria { return std::string(criteria); }; } - -#endif //EQEMU_CONTENT_FILTER_CRITERIA_H diff --git a/common/repositories/damageshieldtypes_repository.h b/common/repositories/damageshieldtypes_repository.h index ec7c829f0d..5a6c1ca2a0 100644 --- a/common/repositories/damageshieldtypes_repository.h +++ b/common/repositories/damageshieldtypes_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_DAMAGESHIELDTYPES_REPOSITORY_H -#define EQEMU_DAMAGESHIELDTYPES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_damageshieldtypes_repository.h" +#include "common/repositories/base/base_damageshieldtypes_repository.h" + +#include "common/database.h" +#include "common/strings.h" class DamageshieldtypesRepository: public BaseDamageshieldtypesRepository { public: @@ -46,5 +46,3 @@ class DamageshieldtypesRepository: public BaseDamageshieldtypesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_DAMAGESHIELDTYPES_REPOSITORY_H diff --git a/common/repositories/data_buckets_repository.h b/common/repositories/data_buckets_repository.h index 606dbdfaa6..225991a3b6 100644 --- a/common/repositories/data_buckets_repository.h +++ b/common/repositories/data_buckets_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_DATA_BUCKETS_REPOSITORY_H -#define EQEMU_DATA_BUCKETS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_data_buckets_repository.h" +#include "common/repositories/base/base_data_buckets_repository.h" + +#include "common/database.h" +#include "common/strings.h" class DataBucketsRepository: public BaseDataBucketsRepository { public: @@ -46,5 +46,3 @@ class DataBucketsRepository: public BaseDataBucketsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_DATA_BUCKETS_REPOSITORY_H diff --git a/common/repositories/db_str_repository.h b/common/repositories/db_str_repository.h index 9eeb21587c..f8d3bfee2b 100644 --- a/common/repositories/db_str_repository.h +++ b/common/repositories/db_str_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_DB_STR_REPOSITORY_H -#define EQEMU_DB_STR_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_db_str_repository.h" +#include "common/repositories/base/base_db_str_repository.h" + +#include "common/database.h" +#include "common/strings.h" class DbStrRepository: public BaseDbStrRepository { public: @@ -63,5 +63,3 @@ class DbStrRepository: public BaseDbStrRepository { return lines; } }; - -#endif //EQEMU_DB_STR_REPOSITORY_H diff --git a/common/repositories/discord_webhooks_repository.h b/common/repositories/discord_webhooks_repository.h index 064fadfbfb..a0d5c1c2c2 100644 --- a/common/repositories/discord_webhooks_repository.h +++ b/common/repositories/discord_webhooks_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_DISCORD_WEBHOOKS_REPOSITORY_H -#define EQEMU_DISCORD_WEBHOOKS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_discord_webhooks_repository.h" +#include "common/repositories/base/base_discord_webhooks_repository.h" + +#include "common/database.h" +#include "common/strings.h" class DiscordWebhooksRepository: public BaseDiscordWebhooksRepository { public: @@ -46,5 +46,3 @@ class DiscordWebhooksRepository: public BaseDiscordWebhooksRepository { // Custom extended repository methods here }; - -#endif //EQEMU_DISCORD_WEBHOOKS_REPOSITORY_H diff --git a/common/repositories/discovered_items_repository.h b/common/repositories/discovered_items_repository.h index 6fcd7968e9..27e9e79136 100644 --- a/common/repositories/discovered_items_repository.h +++ b/common/repositories/discovered_items_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_DISCOVERED_ITEMS_REPOSITORY_H -#define EQEMU_DISCOVERED_ITEMS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_discovered_items_repository.h" +#include "common/repositories/base/base_discovered_items_repository.h" + +#include "common/database.h" +#include "common/strings.h" class DiscoveredItemsRepository: public BaseDiscoveredItemsRepository { public: @@ -46,5 +46,3 @@ class DiscoveredItemsRepository: public BaseDiscoveredItemsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_DISCOVERED_ITEMS_REPOSITORY_H diff --git a/common/repositories/doors_repository.h b/common/repositories/doors_repository.h index f0e46fdee2..b65ce438b4 100644 --- a/common/repositories/doors_repository.h +++ b/common/repositories/doors_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_DOORS_REPOSITORY_H -#define EQEMU_DOORS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_doors_repository.h" +#include "common/repositories/base/base_doors_repository.h" + +#include "common/database.h" +#include "common/strings.h" class DoorsRepository: public BaseDoorsRepository { public: @@ -46,5 +46,3 @@ class DoorsRepository: public BaseDoorsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_DOORS_REPOSITORY_H diff --git a/common/repositories/dynamic_zone_lockouts_repository.h b/common/repositories/dynamic_zone_lockouts_repository.h index f7babc2f04..ab1476ef4d 100644 --- a/common/repositories/dynamic_zone_lockouts_repository.h +++ b/common/repositories/dynamic_zone_lockouts_repository.h @@ -1,10 +1,10 @@ -#ifndef EQEMU_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H -#define EQEMU_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "../dynamic_zone_lockout.h" -#include "base/base_dynamic_zone_lockouts_repository.h" +#include "common/repositories/base/base_dynamic_zone_lockouts_repository.h" + +#include "common/database.h" +#include "common/dynamic_zone_lockout.h" +#include "common/strings.h" class DynamicZoneLockoutsRepository: public BaseDynamicZoneLockoutsRepository { public: @@ -80,5 +80,3 @@ class DynamicZoneLockoutsRepository: public BaseDynamicZoneLockoutsRepository { } }; - -#endif //EQEMU_DYNAMIC_ZONE_LOCKOUTS_REPOSITORY_H diff --git a/common/repositories/dynamic_zone_members_repository.h b/common/repositories/dynamic_zone_members_repository.h index 51b5121f26..1e8351e53b 100644 --- a/common/repositories/dynamic_zone_members_repository.h +++ b/common/repositories/dynamic_zone_members_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H -#define EQEMU_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_dynamic_zone_members_repository.h" +#include "common/repositories/base/base_dynamic_zone_members_repository.h" + +#include "common/database.h" +#include "fmt/ranges.h" class DynamicZoneMembersRepository: public BaseDynamicZoneMembersRepository { public: @@ -176,5 +176,3 @@ class DynamicZoneMembersRepository: public BaseDynamicZoneMembersRepository { return results.Success() ? results.RowsAffected() : 0; } }; - -#endif //EQEMU_DYNAMIC_ZONE_MEMBERS_REPOSITORY_H diff --git a/common/repositories/dynamic_zone_templates_repository.h b/common/repositories/dynamic_zone_templates_repository.h index 0dfe1183e5..d101faf91a 100644 --- a/common/repositories/dynamic_zone_templates_repository.h +++ b/common/repositories/dynamic_zone_templates_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H -#define EQEMU_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_dynamic_zone_templates_repository.h" +#include "common/repositories/base/base_dynamic_zone_templates_repository.h" + +#include "common/database.h" +#include "common/strings.h" class DynamicZoneTemplatesRepository: public BaseDynamicZoneTemplatesRepository { public: @@ -46,5 +46,3 @@ class DynamicZoneTemplatesRepository: public BaseDynamicZoneTemplatesRepository // Custom extended repository methods here }; - -#endif //EQEMU_DYNAMIC_ZONE_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/dynamic_zones_repository.h b/common/repositories/dynamic_zones_repository.h index 2065a10d5e..6d957b8f77 100644 --- a/common/repositories/dynamic_zones_repository.h +++ b/common/repositories/dynamic_zones_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_DYNAMIC_ZONES_REPOSITORY_H -#define EQEMU_DYNAMIC_ZONES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_dynamic_zones_repository.h" +#include "common/repositories/base/base_dynamic_zones_repository.h" + +#include "common/database.h" +#include "fmt/ranges.h" class DynamicZonesRepository: public BaseDynamicZonesRepository { public: @@ -427,5 +427,3 @@ class DynamicZonesRepository: public BaseDynamicZonesRepository { return entries; } }; - -#endif //EQEMU_DYNAMIC_ZONES_REPOSITORY_H diff --git a/common/repositories/faction_association_repository.h b/common/repositories/faction_association_repository.h index 18cb67729b..601089354c 100644 --- a/common/repositories/faction_association_repository.h +++ b/common/repositories/faction_association_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_FACTION_ASSOCIATION_REPOSITORY_H -#define EQEMU_FACTION_ASSOCIATION_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_faction_association_repository.h" +#include "common/repositories/base/base_faction_association_repository.h" + +#include "common/database.h" +#include "common/strings.h" class FactionAssociationRepository: public BaseFactionAssociationRepository { public: @@ -46,5 +46,3 @@ class FactionAssociationRepository: public BaseFactionAssociationRepository { // Custom extended repository methods here }; - -#endif //EQEMU_FACTION_ASSOCIATION_REPOSITORY_H diff --git a/common/repositories/faction_base_data_repository.h b/common/repositories/faction_base_data_repository.h index 0cabe09cf5..09bce71692 100644 --- a/common/repositories/faction_base_data_repository.h +++ b/common/repositories/faction_base_data_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_FACTION_BASE_DATA_REPOSITORY_H -#define EQEMU_FACTION_BASE_DATA_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_faction_base_data_repository.h" +#include "common/repositories/base/base_faction_base_data_repository.h" + +#include "common/database.h" +#include "common/strings.h" class FactionBaseDataRepository: public BaseFactionBaseDataRepository { public: @@ -46,5 +46,3 @@ class FactionBaseDataRepository: public BaseFactionBaseDataRepository { // Custom extended repository methods here }; - -#endif //EQEMU_FACTION_BASE_DATA_REPOSITORY_H diff --git a/common/repositories/faction_list_mod_repository.h b/common/repositories/faction_list_mod_repository.h index 029abb2cba..7fa475168c 100644 --- a/common/repositories/faction_list_mod_repository.h +++ b/common/repositories/faction_list_mod_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_FACTION_LIST_MOD_REPOSITORY_H -#define EQEMU_FACTION_LIST_MOD_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_faction_list_mod_repository.h" +#include "common/repositories/base/base_faction_list_mod_repository.h" + +#include "common/database.h" +#include "common/strings.h" class FactionListModRepository: public BaseFactionListModRepository { public: @@ -46,5 +46,3 @@ class FactionListModRepository: public BaseFactionListModRepository { // Custom extended repository methods here }; - -#endif //EQEMU_FACTION_LIST_MOD_REPOSITORY_H diff --git a/common/repositories/faction_list_repository.h b/common/repositories/faction_list_repository.h index f37e47a3bf..4a41b44887 100644 --- a/common/repositories/faction_list_repository.h +++ b/common/repositories/faction_list_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_FACTION_LIST_REPOSITORY_H -#define EQEMU_FACTION_LIST_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_faction_list_repository.h" +#include "common/repositories/base/base_faction_list_repository.h" + +#include "common/database.h" +#include "common/strings.h" class FactionListRepository: public BaseFactionListRepository { public: @@ -46,5 +46,3 @@ class FactionListRepository: public BaseFactionListRepository { // Custom extended repository methods here }; - -#endif //EQEMU_FACTION_LIST_REPOSITORY_H diff --git a/common/repositories/faction_values_repository.h b/common/repositories/faction_values_repository.h index 9ab862045d..8dd860ba8b 100644 --- a/common/repositories/faction_values_repository.h +++ b/common/repositories/faction_values_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_FACTION_VALUES_REPOSITORY_H -#define EQEMU_FACTION_VALUES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_faction_values_repository.h" +#include "common/repositories/base/base_faction_values_repository.h" + +#include "common/database.h" +#include "common/strings.h" class FactionValuesRepository: public BaseFactionValuesRepository { public: @@ -46,5 +46,3 @@ class FactionValuesRepository: public BaseFactionValuesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_FACTION_VALUES_REPOSITORY_H diff --git a/common/repositories/fishing_repository.h b/common/repositories/fishing_repository.h index 90e8aa82bc..3fb4f51c19 100644 --- a/common/repositories/fishing_repository.h +++ b/common/repositories/fishing_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_FISHING_REPOSITORY_H -#define EQEMU_FISHING_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_fishing_repository.h" +#include "common/repositories/base/base_fishing_repository.h" + +#include "common/database.h" +#include "common/strings.h" class FishingRepository: public BaseFishingRepository { public: @@ -46,5 +46,3 @@ class FishingRepository: public BaseFishingRepository { // Custom extended repository methods here }; - -#endif //EQEMU_FISHING_REPOSITORY_H diff --git a/common/repositories/forage_repository.h b/common/repositories/forage_repository.h index 5f158e69d0..e84f7bfbfc 100644 --- a/common/repositories/forage_repository.h +++ b/common/repositories/forage_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_FORAGE_REPOSITORY_H -#define EQEMU_FORAGE_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_forage_repository.h" +#include "common/repositories/base/base_forage_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ForageRepository: public BaseForageRepository { public: @@ -46,5 +46,3 @@ class ForageRepository: public BaseForageRepository { // Custom extended repository methods here }; - -#endif //EQEMU_FORAGE_REPOSITORY_H diff --git a/common/repositories/friends_repository.h b/common/repositories/friends_repository.h index 3917f9f02f..3c842e028f 100644 --- a/common/repositories/friends_repository.h +++ b/common/repositories/friends_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_FRIENDS_REPOSITORY_H -#define EQEMU_FRIENDS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_friends_repository.h" +#include "common/repositories/base/base_friends_repository.h" + +#include "common/database.h" +#include "common/strings.h" class FriendsRepository: public BaseFriendsRepository { public: @@ -46,5 +46,3 @@ class FriendsRepository: public BaseFriendsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_FRIENDS_REPOSITORY_H diff --git a/common/repositories/global_loot_repository.h b/common/repositories/global_loot_repository.h index ca1783d21c..e4bfe5dfc4 100644 --- a/common/repositories/global_loot_repository.h +++ b/common/repositories/global_loot_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GLOBAL_LOOT_REPOSITORY_H -#define EQEMU_GLOBAL_LOOT_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_global_loot_repository.h" +#include "common/repositories/base/base_global_loot_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GlobalLootRepository: public BaseGlobalLootRepository { public: @@ -46,5 +46,3 @@ class GlobalLootRepository: public BaseGlobalLootRepository { // Custom extended repository methods here }; - -#endif //EQEMU_GLOBAL_LOOT_REPOSITORY_H diff --git a/common/repositories/gm_ips_repository.h b/common/repositories/gm_ips_repository.h index bf62bbd1b6..ad1b99b414 100644 --- a/common/repositories/gm_ips_repository.h +++ b/common/repositories/gm_ips_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GM_IPS_REPOSITORY_H -#define EQEMU_GM_IPS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_gm_ips_repository.h" +#include "common/repositories/base/base_gm_ips_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GmIpsRepository: public BaseGmIpsRepository { public: @@ -46,5 +46,3 @@ class GmIpsRepository: public BaseGmIpsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_GM_IPS_REPOSITORY_H diff --git a/common/repositories/graveyard_repository.h b/common/repositories/graveyard_repository.h index 12bf4c5657..95f21df07a 100644 --- a/common/repositories/graveyard_repository.h +++ b/common/repositories/graveyard_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GRAVEYARD_REPOSITORY_H -#define EQEMU_GRAVEYARD_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_graveyard_repository.h" +#include "common/repositories/base/base_graveyard_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GraveyardRepository: public BaseGraveyardRepository { public: @@ -46,5 +46,3 @@ class GraveyardRepository: public BaseGraveyardRepository { // Custom extended repository methods here }; - -#endif //EQEMU_GRAVEYARD_REPOSITORY_H diff --git a/common/repositories/grid_entries_repository.h b/common/repositories/grid_entries_repository.h index bdae0a518c..8ce80ee76b 100644 --- a/common/repositories/grid_entries_repository.h +++ b/common/repositories/grid_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GRID_ENTRIES_REPOSITORY_H -#define EQEMU_GRID_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_grid_entries_repository.h" +#include "common/repositories/base/base_grid_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GridEntriesRepository: public BaseGridEntriesRepository { public: @@ -119,5 +119,3 @@ class GridEntriesRepository: public BaseGridEntriesRepository { return Strings::ToInt(row[0]) + 1; } }; - -#endif //EQEMU_GRID_ENTRIES_REPOSITORY_H diff --git a/common/repositories/grid_repository.h b/common/repositories/grid_repository.h index afdc07f753..e8ad663898 100644 --- a/common/repositories/grid_repository.h +++ b/common/repositories/grid_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GRID_REPOSITORY_H -#define EQEMU_GRID_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_grid_repository.h" +#include "common/repositories/base/base_grid_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GridRepository: public BaseGridRepository { public: @@ -93,5 +93,3 @@ class GridRepository: public BaseGridRepository { return Strings::ToInt(row[0]); } }; - -#endif //EQEMU_GRID_REPOSITORY_H diff --git a/common/repositories/ground_spawns_repository.h b/common/repositories/ground_spawns_repository.h index 800dd0b3aa..e8f4d8f5c5 100644 --- a/common/repositories/ground_spawns_repository.h +++ b/common/repositories/ground_spawns_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GROUND_SPAWNS_REPOSITORY_H -#define EQEMU_GROUND_SPAWNS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_ground_spawns_repository.h" +#include "common/repositories/base/base_ground_spawns_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GroundSpawnsRepository: public BaseGroundSpawnsRepository { public: @@ -46,5 +46,3 @@ class GroundSpawnsRepository: public BaseGroundSpawnsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_GROUND_SPAWNS_REPOSITORY_H diff --git a/common/repositories/group_id_repository.h b/common/repositories/group_id_repository.h index 84aad59040..7f2429b632 100644 --- a/common/repositories/group_id_repository.h +++ b/common/repositories/group_id_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GROUP_ID_REPOSITORY_H -#define EQEMU_GROUP_ID_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_group_id_repository.h" +#include "common/repositories/base/base_group_id_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GroupIdRepository: public BaseGroupIdRepository { public: @@ -54,5 +54,3 @@ class GroupIdRepository: public BaseGroupIdRepository { ); } }; - -#endif //EQEMU_GROUP_ID_REPOSITORY_H diff --git a/common/repositories/group_leaders_repository.h b/common/repositories/group_leaders_repository.h index a004078f0d..20cca407cc 100644 --- a/common/repositories/group_leaders_repository.h +++ b/common/repositories/group_leaders_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GROUP_LEADERS_REPOSITORY_H -#define EQEMU_GROUP_LEADERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_group_leaders_repository.h" +#include "common/repositories/base/base_group_leaders_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GroupLeadersRepository: public BaseGroupLeadersRepository { public: @@ -67,5 +67,3 @@ class GroupLeadersRepository: public BaseGroupLeadersRepository { return UpdateOne(db, m); } }; - -#endif //EQEMU_GROUP_LEADERS_REPOSITORY_H diff --git a/common/repositories/guild_bank_repository.h b/common/repositories/guild_bank_repository.h index a24aa2c1ce..357710f7e2 100644 --- a/common/repositories/guild_bank_repository.h +++ b/common/repositories/guild_bank_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GUILD_BANK_REPOSITORY_H -#define EQEMU_GUILD_BANK_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_guild_bank_repository.h" +#include "common/repositories/base/base_guild_bank_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GuildBankRepository: public BaseGuildBankRepository { public: @@ -46,5 +46,3 @@ class GuildBankRepository: public BaseGuildBankRepository { // Custom extended repository methods here }; - -#endif //EQEMU_GUILD_BANK_REPOSITORY_H diff --git a/common/repositories/guild_members_repository.h b/common/repositories/guild_members_repository.h index de4a3b29db..550b46078c 100644 --- a/common/repositories/guild_members_repository.h +++ b/common/repositories/guild_members_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GUILD_MEMBERS_REPOSITORY_H -#define EQEMU_GUILD_MEMBERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_guild_members_repository.h" +#include "common/repositories/base/base_guild_members_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GuildMembersRepository : public BaseGuildMembersRepository { public: @@ -202,5 +202,3 @@ class GuildMembersRepository : public BaseGuildMembersRepository { ); } }; - -#endif //EQEMU_GUILD_MEMBERS_REPOSITORY_H diff --git a/common/repositories/guild_permissions_repository.h b/common/repositories/guild_permissions_repository.h index 62d67621b1..997c8c0a9f 100644 --- a/common/repositories/guild_permissions_repository.h +++ b/common/repositories/guild_permissions_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GUILD_PERMISSIONS_REPOSITORY_H -#define EQEMU_GUILD_PERMISSIONS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_guild_permissions_repository.h" +#include "common/repositories/base/base_guild_permissions_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GuildPermissionsRepository: public BaseGuildPermissionsRepository { public: @@ -71,5 +71,3 @@ class GuildPermissionsRepository: public BaseGuildPermissionsRepository { return all_entries; } }; - -#endif //EQEMU_GUILD_PERMISSIONS_REPOSITORY_H diff --git a/common/repositories/guild_ranks_repository.h b/common/repositories/guild_ranks_repository.h index 0bdd23bd56..7cb7196611 100644 --- a/common/repositories/guild_ranks_repository.h +++ b/common/repositories/guild_ranks_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GUILD_RANKS_REPOSITORY_H -#define EQEMU_GUILD_RANKS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_guild_ranks_repository.h" +#include "common/repositories/base/base_guild_ranks_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GuildRanksRepository: public BaseGuildRanksRepository { public: @@ -85,5 +85,3 @@ class GuildRanksRepository: public BaseGuildRanksRepository { return all_entries; } }; - -#endif //EQEMU_GUILD_RANKS_REPOSITORY_H diff --git a/common/repositories/guild_relations_repository.h b/common/repositories/guild_relations_repository.h index a86c80c643..1af13ee987 100644 --- a/common/repositories/guild_relations_repository.h +++ b/common/repositories/guild_relations_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GUILD_RELATIONS_REPOSITORY_H -#define EQEMU_GUILD_RELATIONS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_guild_relations_repository.h" +#include "common/repositories/base/base_guild_relations_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GuildRelationsRepository: public BaseGuildRelationsRepository { public: @@ -46,5 +46,3 @@ class GuildRelationsRepository: public BaseGuildRelationsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_GUILD_RELATIONS_REPOSITORY_H diff --git a/common/repositories/guild_tributes_repository.h b/common/repositories/guild_tributes_repository.h index a4db8cd1bf..0cd6d45cf3 100644 --- a/common/repositories/guild_tributes_repository.h +++ b/common/repositories/guild_tributes_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GUILD_TRIBUTES_REPOSITORY_H -#define EQEMU_GUILD_TRIBUTES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_guild_tributes_repository.h" +#include "common/repositories/base/base_guild_tributes_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GuildTributesRepository: public BaseGuildTributesRepository { public: @@ -73,5 +73,3 @@ class GuildTributesRepository: public BaseGuildTributesRepository { } }; - -#endif //EQEMU_GUILD_TRIBUTES_REPOSITORY_H diff --git a/common/repositories/guilds_repository.h b/common/repositories/guilds_repository.h index 83262e33ef..73c2d86487 100644 --- a/common/repositories/guilds_repository.h +++ b/common/repositories/guilds_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_GUILDS_REPOSITORY_H -#define EQEMU_GUILDS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_guilds_repository.h" +#include "common/repositories/base/base_guilds_repository.h" + +#include "common/database.h" +#include "common/strings.h" class GuildsRepository : public BaseGuildsRepository { public: @@ -58,5 +58,3 @@ class GuildsRepository : public BaseGuildsRepository { return UpdateOne(db, g); } }; - -#endif //EQEMU_GUILDS_REPOSITORY_H diff --git a/common/repositories/horses_repository.h b/common/repositories/horses_repository.h index 18c1abbfca..a112d64322 100644 --- a/common/repositories/horses_repository.h +++ b/common/repositories/horses_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_HORSES_REPOSITORY_H -#define EQEMU_HORSES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_horses_repository.h" +#include "common/repositories/base/base_horses_repository.h" + +#include "common/database.h" +#include "common/strings.h" class HorsesRepository: public BaseHorsesRepository { public: @@ -46,5 +46,3 @@ class HorsesRepository: public BaseHorsesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_HORSES_REPOSITORY_H diff --git a/common/repositories/instance_list_player_repository.h b/common/repositories/instance_list_player_repository.h index 348ddc6252..2d1267f23b 100644 --- a/common/repositories/instance_list_player_repository.h +++ b/common/repositories/instance_list_player_repository.h @@ -1,9 +1,10 @@ -#ifndef EQEMU_INSTANCE_LIST_PLAYER_REPOSITORY_H -#define EQEMU_INSTANCE_LIST_PLAYER_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_instance_list_player_repository.h" +#include "common/repositories/base/base_instance_list_player_repository.h" + +#include "common/database.h" +#include "common/strings.h" +#include "fmt/ranges.h" class InstanceListPlayerRepository: public BaseInstanceListPlayerRepository { public: @@ -88,5 +89,3 @@ class InstanceListPlayerRepository: public BaseInstanceListPlayerRepository { return false; } }; - -#endif //EQEMU_INSTANCE_LIST_PLAYER_REPOSITORY_H diff --git a/common/repositories/instance_list_repository.h b/common/repositories/instance_list_repository.h index dbaf8d2a45..c396db9061 100644 --- a/common/repositories/instance_list_repository.h +++ b/common/repositories/instance_list_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_INSTANCE_LIST_REPOSITORY_H -#define EQEMU_INSTANCE_LIST_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_instance_list_repository.h" +#include "common/repositories/base/base_instance_list_repository.h" + +#include "common/database.h" +#include "common/strings.h" class InstanceListRepository: public BaseInstanceListRepository { public: @@ -44,5 +44,3 @@ class InstanceListRepository: public BaseInstanceListRepository { return Strings::ToUnsignedInt(row[0]); } }; - -#endif //EQEMU_INSTANCE_LIST_REPOSITORY_H diff --git a/common/repositories/inventory_repository.h b/common/repositories/inventory_repository.h index 8b4b859ee3..20306c4d45 100644 --- a/common/repositories/inventory_repository.h +++ b/common/repositories/inventory_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_INVENTORY_REPOSITORY_H -#define EQEMU_INVENTORY_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_inventory_repository.h" +#include "common/repositories/base/base_inventory_repository.h" + +#include "common/database.h" +#include "common/strings.h" class InventoryRepository: public BaseInventoryRepository { public: @@ -46,5 +46,3 @@ class InventoryRepository: public BaseInventoryRepository { // Custom extended repository methods here }; - -#endif //EQEMU_INVENTORY_REPOSITORY_H diff --git a/common/repositories/inventory_snapshots_repository.h b/common/repositories/inventory_snapshots_repository.h index 0fb1f815cc..b0605c0d96 100644 --- a/common/repositories/inventory_snapshots_repository.h +++ b/common/repositories/inventory_snapshots_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_INVENTORY_SNAPSHOTS_REPOSITORY_H -#define EQEMU_INVENTORY_SNAPSHOTS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_inventory_snapshots_repository.h" +#include "common/repositories/base/base_inventory_snapshots_repository.h" + +#include "common/database.h" +#include "common/strings.h" class InventorySnapshotsRepository: public BaseInventorySnapshotsRepository { public: @@ -69,5 +69,3 @@ class InventorySnapshotsRepository: public BaseInventorySnapshotsRepository { return count; } }; - -#endif //EQEMU_INVENTORY_SNAPSHOTS_REPOSITORY_H diff --git a/common/repositories/inventory_versions_repository.h b/common/repositories/inventory_versions_repository.h index 7b279a6fee..4799273ea4 100644 --- a/common/repositories/inventory_versions_repository.h +++ b/common/repositories/inventory_versions_repository.h @@ -1,8 +1,7 @@ -#ifndef EQEMU_INVENTORY_VERSIONS_REPOSITORY_H -#define EQEMU_INVENTORY_VERSIONS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" +#include "common/database.h" +#include "common/strings.h" class InventoryVersionsRepository { public: @@ -245,5 +244,3 @@ class InventoryVersionsRepository { } }; - -#endif //EQEMU_INVENTORY_VERSIONS_REPOSITORY_H diff --git a/common/repositories/ip_exemptions_repository.h b/common/repositories/ip_exemptions_repository.h index 64b5f76037..53a69013ff 100644 --- a/common/repositories/ip_exemptions_repository.h +++ b/common/repositories/ip_exemptions_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_IP_EXEMPTIONS_REPOSITORY_H -#define EQEMU_IP_EXEMPTIONS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_ip_exemptions_repository.h" +#include "common/repositories/base/base_ip_exemptions_repository.h" + +#include "common/database.h" +#include "common/strings.h" class IpExemptionsRepository: public BaseIpExemptionsRepository { public: @@ -46,5 +46,3 @@ class IpExemptionsRepository: public BaseIpExemptionsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_IP_EXEMPTIONS_REPOSITORY_H diff --git a/common/repositories/items_evolving_details_repository.h b/common/repositories/items_evolving_details_repository.h index 906bb60951..8890b721a6 100644 --- a/common/repositories/items_evolving_details_repository.h +++ b/common/repositories/items_evolving_details_repository.h @@ -1,14 +1,12 @@ -#ifndef EQEMU_ITEMS_EVOLVING_DETAILS_REPOSITORY_H -#define EQEMU_ITEMS_EVOLVING_DETAILS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_items_evolving_details_repository.h" +#include "common/repositories/base/base_items_evolving_details_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ItemsEvolvingDetailsRepository: public BaseItemsEvolvingDetailsRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_ITEMS_EVOLVING_DETAILS_REPOSITORY_H diff --git a/common/repositories/items_repository.h b/common/repositories/items_repository.h index 4e5a8868e4..6e3d8875c2 100644 --- a/common/repositories/items_repository.h +++ b/common/repositories/items_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ITEMS_REPOSITORY_H -#define EQEMU_ITEMS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_items_repository.h" +#include "common/repositories/base/base_items_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ItemsRepository: public BaseItemsRepository { public: @@ -92,5 +92,3 @@ class ItemsRepository: public BaseItemsRepository { } }; - -#endif //EQEMU_ITEMS_REPOSITORY_H diff --git a/common/repositories/keyring_repository.h b/common/repositories/keyring_repository.h index c4367eaf45..cab495dca5 100644 --- a/common/repositories/keyring_repository.h +++ b/common/repositories/keyring_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_KEYRING_REPOSITORY_H -#define EQEMU_KEYRING_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_keyring_repository.h" +#include "common/repositories/base/base_keyring_repository.h" + +#include "common/database.h" +#include "common/strings.h" class KeyringRepository: public BaseKeyringRepository { public: @@ -46,5 +46,3 @@ class KeyringRepository: public BaseKeyringRepository { // Custom extended repository methods here }; - -#endif //EQEMU_KEYRING_REPOSITORY_H diff --git a/common/repositories/ldon_trap_entries_repository.h b/common/repositories/ldon_trap_entries_repository.h index e2d6a882af..0f1a421e1d 100644 --- a/common/repositories/ldon_trap_entries_repository.h +++ b/common/repositories/ldon_trap_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LDON_TRAP_ENTRIES_REPOSITORY_H -#define EQEMU_LDON_TRAP_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_ldon_trap_entries_repository.h" +#include "common/repositories/base/base_ldon_trap_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class LdonTrapEntriesRepository: public BaseLdonTrapEntriesRepository { public: @@ -46,5 +46,3 @@ class LdonTrapEntriesRepository: public BaseLdonTrapEntriesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_LDON_TRAP_ENTRIES_REPOSITORY_H diff --git a/common/repositories/ldon_trap_templates_repository.h b/common/repositories/ldon_trap_templates_repository.h index 7d94f80b41..b2b8145aec 100644 --- a/common/repositories/ldon_trap_templates_repository.h +++ b/common/repositories/ldon_trap_templates_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LDON_TRAP_TEMPLATES_REPOSITORY_H -#define EQEMU_LDON_TRAP_TEMPLATES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_ldon_trap_templates_repository.h" +#include "common/repositories/base/base_ldon_trap_templates_repository.h" + +#include "common/database.h" +#include "common/strings.h" class LdonTrapTemplatesRepository: public BaseLdonTrapTemplatesRepository { public: @@ -46,5 +46,3 @@ class LdonTrapTemplatesRepository: public BaseLdonTrapTemplatesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_LDON_TRAP_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/level_exp_mods_repository.h b/common/repositories/level_exp_mods_repository.h index 6bc893aeda..032febba0d 100644 --- a/common/repositories/level_exp_mods_repository.h +++ b/common/repositories/level_exp_mods_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LEVEL_EXP_MODS_REPOSITORY_H -#define EQEMU_LEVEL_EXP_MODS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_level_exp_mods_repository.h" +#include "common/repositories/base/base_level_exp_mods_repository.h" + +#include "common/database.h" +#include "common/strings.h" class LevelExpModsRepository: public BaseLevelExpModsRepository { public: @@ -46,5 +46,3 @@ class LevelExpModsRepository: public BaseLevelExpModsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_LEVEL_EXP_MODS_REPOSITORY_H diff --git a/common/repositories/lfguild_repository.h b/common/repositories/lfguild_repository.h index 9f415c944b..f7ddbadcd4 100644 --- a/common/repositories/lfguild_repository.h +++ b/common/repositories/lfguild_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LFGUILD_REPOSITORY_H -#define EQEMU_LFGUILD_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_lfguild_repository.h" +#include "common/repositories/base/base_lfguild_repository.h" + +#include "common/database.h" +#include "common/strings.h" class LfguildRepository: public BaseLfguildRepository { public: @@ -46,5 +46,3 @@ class LfguildRepository: public BaseLfguildRepository { // Custom extended repository methods here }; - -#endif //EQEMU_LFGUILD_REPOSITORY_H diff --git a/common/repositories/login_accounts_repository.h b/common/repositories/login_accounts_repository.h index 052f4fb16b..c9002454b3 100644 --- a/common/repositories/login_accounts_repository.h +++ b/common/repositories/login_accounts_repository.h @@ -1,11 +1,11 @@ -#ifndef EQEMU_LOGIN_ACCOUNTS_REPOSITORY_H -#define EQEMU_LOGIN_ACCOUNTS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_login_accounts_repository.h" -#include "../../loginserver/encryption.h" -#include "../../loginserver/login_types.h" +#include "common/repositories/base/base_login_accounts_repository.h" + +#include "common/database.h" +#include "common/strings.h" +#include "loginserver/encryption.h" +#include "loginserver/login_types.h" class LoginAccountsRepository : public BaseLoginAccountsRepository { public: @@ -93,5 +93,3 @@ class LoginAccountsRepository : public BaseLoginAccountsRepository { return success ? a : NewEntity(); } }; - -#endif //EQEMU_LOGIN_ACCOUNTS_REPOSITORY_H diff --git a/common/repositories/login_api_tokens_repository.h b/common/repositories/login_api_tokens_repository.h index 46bfd33165..f7060fd713 100644 --- a/common/repositories/login_api_tokens_repository.h +++ b/common/repositories/login_api_tokens_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LOGIN_API_TOKENS_REPOSITORY_H -#define EQEMU_LOGIN_API_TOKENS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_login_api_tokens_repository.h" +#include "common/repositories/base/base_login_api_tokens_repository.h" + +#include "common/database.h" +#include "common/strings.h" class LoginApiTokensRepository: public BaseLoginApiTokensRepository { public: @@ -46,5 +46,3 @@ class LoginApiTokensRepository: public BaseLoginApiTokensRepository { // Custom extended repository methods here }; - -#endif //EQEMU_LOGIN_API_TOKENS_REPOSITORY_H diff --git a/common/repositories/login_server_admins_repository.h b/common/repositories/login_server_admins_repository.h index f8b126a601..e68abae36e 100644 --- a/common/repositories/login_server_admins_repository.h +++ b/common/repositories/login_server_admins_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LOGIN_SERVER_ADMINS_REPOSITORY_H -#define EQEMU_LOGIN_SERVER_ADMINS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_login_server_admins_repository.h" +#include "common/repositories/base/base_login_server_admins_repository.h" + +#include "common/database.h" +#include "common/strings.h" class LoginServerAdminsRepository : public BaseLoginServerAdminsRepository { public: @@ -24,5 +24,3 @@ class LoginServerAdminsRepository : public BaseLoginServerAdminsRepository { return NewEntity(); } }; - -#endif //EQEMU_LOGIN_SERVER_ADMINS_REPOSITORY_H diff --git a/common/repositories/login_server_list_types_repository.h b/common/repositories/login_server_list_types_repository.h index 37aef18eb5..6539c44603 100644 --- a/common/repositories/login_server_list_types_repository.h +++ b/common/repositories/login_server_list_types_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LOGIN_SERVER_LIST_TYPES_REPOSITORY_H -#define EQEMU_LOGIN_SERVER_LIST_TYPES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_login_server_list_types_repository.h" +#include "common/repositories/base/base_login_server_list_types_repository.h" + +#include "common/database.h" +#include "common/strings.h" class LoginServerListTypesRepository: public BaseLoginServerListTypesRepository { public: @@ -46,5 +46,3 @@ class LoginServerListTypesRepository: public BaseLoginServerListTypesRepository // Custom extended repository methods here }; - -#endif //EQEMU_LOGIN_SERVER_LIST_TYPES_REPOSITORY_H diff --git a/common/repositories/login_world_servers_repository.h b/common/repositories/login_world_servers_repository.h index 50516686ca..797871abff 100644 --- a/common/repositories/login_world_servers_repository.h +++ b/common/repositories/login_world_servers_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LOGIN_WORLD_SERVERS_REPOSITORY_H -#define EQEMU_LOGIN_WORLD_SERVERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_login_world_servers_repository.h" +#include "common/repositories/base/base_login_world_servers_repository.h" + +#include "common/database.h" +#include "common/strings.h" class LoginWorldServersRepository: public BaseLoginWorldServersRepository { public: @@ -29,5 +29,3 @@ class LoginWorldServersRepository: public BaseLoginWorldServersRepository { return e; } }; - -#endif //EQEMU_LOGIN_WORLD_SERVERS_REPOSITORY_H diff --git a/common/repositories/logsys_categories_repository.h b/common/repositories/logsys_categories_repository.h index 7d2f0898af..d523713a08 100644 --- a/common/repositories/logsys_categories_repository.h +++ b/common/repositories/logsys_categories_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LOGSYS_CATEGORIES_REPOSITORY_H -#define EQEMU_LOGSYS_CATEGORIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_logsys_categories_repository.h" +#include "common/repositories/base/base_logsys_categories_repository.h" + +#include "common/database.h" +#include "common/strings.h" class LogsysCategoriesRepository: public BaseLogsysCategoriesRepository { public: @@ -46,5 +46,3 @@ class LogsysCategoriesRepository: public BaseLogsysCategoriesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_LOGSYS_CATEGORIES_REPOSITORY_H diff --git a/common/repositories/lootdrop_entries_repository.h b/common/repositories/lootdrop_entries_repository.h index 8f1c21b81c..cd940c687f 100644 --- a/common/repositories/lootdrop_entries_repository.h +++ b/common/repositories/lootdrop_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LOOTDROP_ENTRIES_REPOSITORY_H -#define EQEMU_LOOTDROP_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_lootdrop_entries_repository.h" +#include "common/repositories/base/base_lootdrop_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class LootdropEntriesRepository: public BaseLootdropEntriesRepository { public: @@ -28,5 +28,3 @@ class LootdropEntriesRepository: public BaseLootdropEntriesRepository { } }; - -#endif //EQEMU_LOOTDROP_ENTRIES_REPOSITORY_H diff --git a/common/repositories/lootdrop_repository.h b/common/repositories/lootdrop_repository.h index abd2ec8442..1f50198b56 100644 --- a/common/repositories/lootdrop_repository.h +++ b/common/repositories/lootdrop_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LOOTDROP_REPOSITORY_H -#define EQEMU_LOOTDROP_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_lootdrop_repository.h" +#include "common/repositories/base/base_lootdrop_repository.h" + +#include "common/database.h" +#include "common/strings.h" class LootdropRepository: public BaseLootdropRepository { public: @@ -46,5 +46,3 @@ class LootdropRepository: public BaseLootdropRepository { // Custom extended repository methods here }; - -#endif //EQEMU_LOOTDROP_REPOSITORY_H diff --git a/common/repositories/loottable_entries_repository.h b/common/repositories/loottable_entries_repository.h index 9e2c9d9898..aed594a838 100644 --- a/common/repositories/loottable_entries_repository.h +++ b/common/repositories/loottable_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LOOTTABLE_ENTRIES_REPOSITORY_H -#define EQEMU_LOOTTABLE_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_loottable_entries_repository.h" +#include "common/repositories/base/base_loottable_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class LoottableEntriesRepository: public BaseLoottableEntriesRepository { public: @@ -46,5 +46,3 @@ class LoottableEntriesRepository: public BaseLoottableEntriesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_LOOTTABLE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/loottable_repository.h b/common/repositories/loottable_repository.h index ef9845c876..4b301e4822 100644 --- a/common/repositories/loottable_repository.h +++ b/common/repositories/loottable_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LOOTTABLE_REPOSITORY_H -#define EQEMU_LOOTTABLE_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_loottable_repository.h" +#include "common/repositories/base/base_loottable_repository.h" + +#include "common/database.h" +#include "common/strings.h" class LoottableRepository: public BaseLoottableRepository { public: @@ -46,5 +46,3 @@ class LoottableRepository: public BaseLoottableRepository { // Custom extended repository methods here }; - -#endif //EQEMU_LOOTTABLE_REPOSITORY_H diff --git a/common/repositories/mail_repository.h b/common/repositories/mail_repository.h index c1e2934aea..365c938fd0 100644 --- a/common/repositories/mail_repository.h +++ b/common/repositories/mail_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MAIL_REPOSITORY_H -#define EQEMU_MAIL_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_mail_repository.h" +#include "common/repositories/base/base_mail_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MailRepository: public BaseMailRepository { public: @@ -46,5 +46,3 @@ class MailRepository: public BaseMailRepository { // Custom extended repository methods here }; - -#endif //EQEMU_MAIL_REPOSITORY_H diff --git a/common/repositories/merc_armorinfo_repository.h b/common/repositories/merc_armorinfo_repository.h index 6861ea0d04..210589e2ba 100644 --- a/common/repositories/merc_armorinfo_repository.h +++ b/common/repositories/merc_armorinfo_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_ARMORINFO_REPOSITORY_H -#define EQEMU_MERC_ARMORINFO_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_armorinfo_repository.h" +#include "common/repositories/base/base_merc_armorinfo_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercArmorinfoRepository: public BaseMercArmorinfoRepository { public: @@ -46,5 +46,3 @@ class MercArmorinfoRepository: public BaseMercArmorinfoRepository { // Custom extended repository methods here }; - -#endif //EQEMU_MERC_ARMORINFO_REPOSITORY_H diff --git a/common/repositories/merc_buffs_repository.h b/common/repositories/merc_buffs_repository.h index c8c56c2062..eb6540a9eb 100644 --- a/common/repositories/merc_buffs_repository.h +++ b/common/repositories/merc_buffs_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_BUFFS_REPOSITORY_H -#define EQEMU_MERC_BUFFS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_buffs_repository.h" +#include "common/repositories/base/base_merc_buffs_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercBuffsRepository: public BaseMercBuffsRepository { public: @@ -46,5 +46,3 @@ class MercBuffsRepository: public BaseMercBuffsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_MERC_BUFFS_REPOSITORY_H diff --git a/common/repositories/merc_inventory_repository.h b/common/repositories/merc_inventory_repository.h index 43a2415642..8068613966 100644 --- a/common/repositories/merc_inventory_repository.h +++ b/common/repositories/merc_inventory_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_INVENTORY_REPOSITORY_H -#define EQEMU_MERC_INVENTORY_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_inventory_repository.h" +#include "common/repositories/base/base_merc_inventory_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercInventoryRepository: public BaseMercInventoryRepository { public: @@ -46,5 +46,3 @@ class MercInventoryRepository: public BaseMercInventoryRepository { // Custom extended repository methods here }; - -#endif //EQEMU_MERC_INVENTORY_REPOSITORY_H diff --git a/common/repositories/merc_merchant_entries_repository.h b/common/repositories/merc_merchant_entries_repository.h index 2ad0a833be..4714a532d0 100644 --- a/common/repositories/merc_merchant_entries_repository.h +++ b/common/repositories/merc_merchant_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_MERCHANT_ENTRIES_REPOSITORY_H -#define EQEMU_MERC_MERCHANT_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_merchant_entries_repository.h" +#include "common/repositories/base/base_merc_merchant_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercMerchantEntriesRepository: public BaseMercMerchantEntriesRepository { public: @@ -46,5 +46,3 @@ class MercMerchantEntriesRepository: public BaseMercMerchantEntriesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_MERC_MERCHANT_ENTRIES_REPOSITORY_H diff --git a/common/repositories/merc_merchant_template_entries_repository.h b/common/repositories/merc_merchant_template_entries_repository.h index 8d60acfab2..0059411bc2 100644 --- a/common/repositories/merc_merchant_template_entries_repository.h +++ b/common/repositories/merc_merchant_template_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_MERCHANT_TEMPLATE_ENTRIES_REPOSITORY_H -#define EQEMU_MERC_MERCHANT_TEMPLATE_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_merchant_template_entries_repository.h" +#include "common/repositories/base/base_merc_merchant_template_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercMerchantTemplateEntriesRepository: public BaseMercMerchantTemplateEntriesRepository { public: @@ -46,5 +46,3 @@ class MercMerchantTemplateEntriesRepository: public BaseMercMerchantTemplateEntr // Custom extended repository methods here }; - -#endif //EQEMU_MERC_MERCHANT_TEMPLATE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/merc_merchant_templates_repository.h b/common/repositories/merc_merchant_templates_repository.h index b2798a201b..8069e6fa77 100644 --- a/common/repositories/merc_merchant_templates_repository.h +++ b/common/repositories/merc_merchant_templates_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_MERCHANT_TEMPLATES_REPOSITORY_H -#define EQEMU_MERC_MERCHANT_TEMPLATES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_merchant_templates_repository.h" +#include "common/repositories/base/base_merc_merchant_templates_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercMerchantTemplatesRepository: public BaseMercMerchantTemplatesRepository { public: @@ -46,5 +46,3 @@ class MercMerchantTemplatesRepository: public BaseMercMerchantTemplatesRepositor // Custom extended repository methods here }; - -#endif //EQEMU_MERC_MERCHANT_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/merc_name_types_repository.h b/common/repositories/merc_name_types_repository.h index 994241bd5e..bcca5e38ad 100644 --- a/common/repositories/merc_name_types_repository.h +++ b/common/repositories/merc_name_types_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_NAME_TYPES_REPOSITORY_H -#define EQEMU_MERC_NAME_TYPES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_name_types_repository.h" +#include "common/repositories/base/base_merc_name_types_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercNameTypesRepository: public BaseMercNameTypesRepository { public: @@ -46,5 +46,3 @@ class MercNameTypesRepository: public BaseMercNameTypesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_MERC_NAME_TYPES_REPOSITORY_H diff --git a/common/repositories/merc_npc_types_repository.h b/common/repositories/merc_npc_types_repository.h index 2604bda308..e91957795c 100644 --- a/common/repositories/merc_npc_types_repository.h +++ b/common/repositories/merc_npc_types_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_NPC_TYPES_REPOSITORY_H -#define EQEMU_MERC_NPC_TYPES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_npc_types_repository.h" +#include "common/repositories/base/base_merc_npc_types_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercNpcTypesRepository: public BaseMercNpcTypesRepository { public: @@ -46,5 +46,3 @@ class MercNpcTypesRepository: public BaseMercNpcTypesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_MERC_NPC_TYPES_REPOSITORY_H diff --git a/common/repositories/merc_spell_list_entries_repository.h b/common/repositories/merc_spell_list_entries_repository.h index 4a841a221d..3566c82db0 100644 --- a/common/repositories/merc_spell_list_entries_repository.h +++ b/common/repositories/merc_spell_list_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_SPELL_LIST_ENTRIES_REPOSITORY_H -#define EQEMU_MERC_SPELL_LIST_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_spell_list_entries_repository.h" +#include "common/repositories/base/base_merc_spell_list_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercSpellListEntriesRepository: public BaseMercSpellListEntriesRepository { public: @@ -46,5 +46,3 @@ class MercSpellListEntriesRepository: public BaseMercSpellListEntriesRepository // Custom extended repository methods here }; - -#endif //EQEMU_MERC_SPELL_LIST_ENTRIES_REPOSITORY_H diff --git a/common/repositories/merc_spell_lists_repository.h b/common/repositories/merc_spell_lists_repository.h index 525149b492..4196216b52 100644 --- a/common/repositories/merc_spell_lists_repository.h +++ b/common/repositories/merc_spell_lists_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_SPELL_LISTS_REPOSITORY_H -#define EQEMU_MERC_SPELL_LISTS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_spell_lists_repository.h" +#include "common/repositories/base/base_merc_spell_lists_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercSpellListsRepository: public BaseMercSpellListsRepository { public: @@ -46,5 +46,3 @@ class MercSpellListsRepository: public BaseMercSpellListsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_MERC_SPELL_LISTS_REPOSITORY_H diff --git a/common/repositories/merc_stance_entries_repository.h b/common/repositories/merc_stance_entries_repository.h index 25816bb93c..4c5b6c3bde 100644 --- a/common/repositories/merc_stance_entries_repository.h +++ b/common/repositories/merc_stance_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_STANCE_ENTRIES_REPOSITORY_H -#define EQEMU_MERC_STANCE_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_stance_entries_repository.h" +#include "common/repositories/base/base_merc_stance_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercStanceEntriesRepository: public BaseMercStanceEntriesRepository { public: @@ -77,5 +77,3 @@ class MercStanceEntriesRepository: public BaseMercStanceEntriesRepository { return v; } }; - -#endif //EQEMU_MERC_STANCE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/merc_stats_repository.h b/common/repositories/merc_stats_repository.h index 383131a9f6..4b2f7618c9 100644 --- a/common/repositories/merc_stats_repository.h +++ b/common/repositories/merc_stats_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_STATS_REPOSITORY_H -#define EQEMU_MERC_STATS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_stats_repository.h" +#include "common/repositories/base/base_merc_stats_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercStatsRepository: public BaseMercStatsRepository { public: @@ -46,5 +46,3 @@ class MercStatsRepository: public BaseMercStatsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_MERC_STATS_REPOSITORY_H diff --git a/common/repositories/merc_subtypes_repository.h b/common/repositories/merc_subtypes_repository.h index 1a5f365a95..a18a7c9955 100644 --- a/common/repositories/merc_subtypes_repository.h +++ b/common/repositories/merc_subtypes_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_SUBTYPES_REPOSITORY_H -#define EQEMU_MERC_SUBTYPES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_subtypes_repository.h" +#include "common/repositories/base/base_merc_subtypes_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercSubtypesRepository: public BaseMercSubtypesRepository { public: @@ -66,5 +66,3 @@ class MercSubtypesRepository: public BaseMercSubtypesRepository { return l[0].merc_subtype_id; } }; - -#endif //EQEMU_MERC_SUBTYPES_REPOSITORY_H diff --git a/common/repositories/merc_templates_repository.h b/common/repositories/merc_templates_repository.h index 714dcccef8..7c98393f17 100644 --- a/common/repositories/merc_templates_repository.h +++ b/common/repositories/merc_templates_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_TEMPLATES_REPOSITORY_H -#define EQEMU_MERC_TEMPLATES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_templates_repository.h" +#include "common/repositories/base/base_merc_templates_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercTemplatesRepository: public BaseMercTemplatesRepository { public: @@ -46,5 +46,3 @@ class MercTemplatesRepository: public BaseMercTemplatesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_MERC_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/merc_types_repository.h b/common/repositories/merc_types_repository.h index 4d91145d5d..baf014bec8 100644 --- a/common/repositories/merc_types_repository.h +++ b/common/repositories/merc_types_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_TYPES_REPOSITORY_H -#define EQEMU_MERC_TYPES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_types_repository.h" +#include "common/repositories/base/base_merc_types_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercTypesRepository: public BaseMercTypesRepository { public: @@ -46,5 +46,3 @@ class MercTypesRepository: public BaseMercTypesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_MERC_TYPES_REPOSITORY_H diff --git a/common/repositories/merc_weaponinfo_repository.h b/common/repositories/merc_weaponinfo_repository.h index 0c73fd71a0..49642e26f0 100644 --- a/common/repositories/merc_weaponinfo_repository.h +++ b/common/repositories/merc_weaponinfo_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERC_WEAPONINFO_REPOSITORY_H -#define EQEMU_MERC_WEAPONINFO_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merc_weaponinfo_repository.h" +#include "common/repositories/base/base_merc_weaponinfo_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercWeaponinfoRepository: public BaseMercWeaponinfoRepository { public: @@ -46,5 +46,3 @@ class MercWeaponinfoRepository: public BaseMercWeaponinfoRepository { // Custom extended repository methods here }; - -#endif //EQEMU_MERC_WEAPONINFO_REPOSITORY_H diff --git a/common/repositories/merchantlist_repository.h b/common/repositories/merchantlist_repository.h index 37f4c82ef7..3d94d6189c 100644 --- a/common/repositories/merchantlist_repository.h +++ b/common/repositories/merchantlist_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERCHANTLIST_REPOSITORY_H -#define EQEMU_MERCHANTLIST_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merchantlist_repository.h" +#include "common/repositories/base/base_merchantlist_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MerchantlistRepository: public BaseMerchantlistRepository { public: @@ -46,5 +46,3 @@ class MerchantlistRepository: public BaseMerchantlistRepository { // Custom extended repository methods here }; - -#endif //EQEMU_MERCHANTLIST_REPOSITORY_H diff --git a/common/repositories/merchantlist_temp_repository.h b/common/repositories/merchantlist_temp_repository.h index ccf250f814..74d3802073 100644 --- a/common/repositories/merchantlist_temp_repository.h +++ b/common/repositories/merchantlist_temp_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERCHANTLIST_TEMP_REPOSITORY_H -#define EQEMU_MERCHANTLIST_TEMP_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_merchantlist_temp_repository.h" +#include "common/repositories/base/base_merchantlist_temp_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MerchantlistTempRepository: public BaseMerchantlistTempRepository { public: @@ -54,5 +54,3 @@ class MerchantlistTempRepository: public BaseMerchantlistTempRepository { ); } }; - -#endif //EQEMU_MERCHANTLIST_TEMP_REPOSITORY_H diff --git a/common/repositories/mercs_repository.h b/common/repositories/mercs_repository.h index b2d1ea199f..cdfeea6a83 100644 --- a/common/repositories/mercs_repository.h +++ b/common/repositories/mercs_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_MERCS_REPOSITORY_H -#define EQEMU_MERCS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_mercs_repository.h" +#include "common/repositories/base/base_mercs_repository.h" + +#include "common/database.h" +#include "common/strings.h" class MercsRepository: public BaseMercsRepository { public: @@ -62,5 +62,3 @@ class MercsRepository: public BaseMercsRepository { return l[0]; } }; - -#endif //EQEMU_MERCS_REPOSITORY_H diff --git a/common/repositories/name_filter_repository.h b/common/repositories/name_filter_repository.h index 43dc3ecf09..a5d6d6cf54 100644 --- a/common/repositories/name_filter_repository.h +++ b/common/repositories/name_filter_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_NAME_FILTER_REPOSITORY_H -#define EQEMU_NAME_FILTER_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_name_filter_repository.h" +#include "common/repositories/base/base_name_filter_repository.h" + +#include "common/database.h" +#include "common/strings.h" class NameFilterRepository: public BaseNameFilterRepository { public: @@ -46,5 +46,3 @@ class NameFilterRepository: public BaseNameFilterRepository { // Custom extended repository methods here }; - -#endif //EQEMU_NAME_FILTER_REPOSITORY_H diff --git a/common/repositories/npc_emotes_repository.h b/common/repositories/npc_emotes_repository.h index 438ad9be45..7f18f82c8b 100644 --- a/common/repositories/npc_emotes_repository.h +++ b/common/repositories/npc_emotes_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_NPC_EMOTES_REPOSITORY_H -#define EQEMU_NPC_EMOTES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_npc_emotes_repository.h" +#include "common/repositories/base/base_npc_emotes_repository.h" + +#include "common/database.h" +#include "common/strings.h" class NpcEmotesRepository: public BaseNpcEmotesRepository { public: @@ -46,5 +46,3 @@ class NpcEmotesRepository: public BaseNpcEmotesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_NPC_EMOTES_REPOSITORY_H diff --git a/common/repositories/npc_faction_entries_repository.h b/common/repositories/npc_faction_entries_repository.h index eb9d92b447..2669b52a6e 100644 --- a/common/repositories/npc_faction_entries_repository.h +++ b/common/repositories/npc_faction_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_NPC_FACTION_ENTRIES_REPOSITORY_H -#define EQEMU_NPC_FACTION_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_npc_faction_entries_repository.h" +#include "common/repositories/base/base_npc_faction_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class NpcFactionEntriesRepository: public BaseNpcFactionEntriesRepository { public: @@ -46,5 +46,3 @@ class NpcFactionEntriesRepository: public BaseNpcFactionEntriesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_NPC_FACTION_ENTRIES_REPOSITORY_H diff --git a/common/repositories/npc_faction_repository.h b/common/repositories/npc_faction_repository.h index 0e4cbbbc4f..3a6eddfa7e 100644 --- a/common/repositories/npc_faction_repository.h +++ b/common/repositories/npc_faction_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_NPC_FACTION_REPOSITORY_H -#define EQEMU_NPC_FACTION_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_npc_faction_repository.h" +#include "common/repositories/base/base_npc_faction_repository.h" + +#include "common/database.h" +#include "common/strings.h" class NpcFactionRepository: public BaseNpcFactionRepository { public: @@ -46,5 +46,3 @@ class NpcFactionRepository: public BaseNpcFactionRepository { // Custom extended repository methods here }; - -#endif //EQEMU_NPC_FACTION_REPOSITORY_H diff --git a/common/repositories/npc_scale_global_base_repository.h b/common/repositories/npc_scale_global_base_repository.h index 1ef4ffb1ad..8f46986ccf 100644 --- a/common/repositories/npc_scale_global_base_repository.h +++ b/common/repositories/npc_scale_global_base_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_NPC_SCALE_GLOBAL_BASE_REPOSITORY_H -#define EQEMU_NPC_SCALE_GLOBAL_BASE_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_npc_scale_global_base_repository.h" +#include "common/repositories/base/base_npc_scale_global_base_repository.h" + +#include "common/database.h" +#include "common/strings.h" class NpcScaleGlobalBaseRepository: public BaseNpcScaleGlobalBaseRepository { public: @@ -46,5 +46,3 @@ class NpcScaleGlobalBaseRepository: public BaseNpcScaleGlobalBaseRepository { // Custom extended repository methods here }; - -#endif //EQEMU_NPC_SCALE_GLOBAL_BASE_REPOSITORY_H diff --git a/common/repositories/npc_spells_effects_entries_repository.h b/common/repositories/npc_spells_effects_entries_repository.h index 87570ceef9..c05736ac9d 100644 --- a/common/repositories/npc_spells_effects_entries_repository.h +++ b/common/repositories/npc_spells_effects_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_NPC_SPELLS_EFFECTS_ENTRIES_REPOSITORY_H -#define EQEMU_NPC_SPELLS_EFFECTS_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_npc_spells_effects_entries_repository.h" +#include "common/repositories/base/base_npc_spells_effects_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class NpcSpellsEffectsEntriesRepository: public BaseNpcSpellsEffectsEntriesRepository { public: @@ -46,5 +46,3 @@ class NpcSpellsEffectsEntriesRepository: public BaseNpcSpellsEffectsEntriesRepos // Custom extended repository methods here }; - -#endif //EQEMU_NPC_SPELLS_EFFECTS_ENTRIES_REPOSITORY_H diff --git a/common/repositories/npc_spells_effects_repository.h b/common/repositories/npc_spells_effects_repository.h index 46a56819a3..d38c0f1e70 100644 --- a/common/repositories/npc_spells_effects_repository.h +++ b/common/repositories/npc_spells_effects_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_NPC_SPELLS_EFFECTS_REPOSITORY_H -#define EQEMU_NPC_SPELLS_EFFECTS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_npc_spells_effects_repository.h" +#include "common/repositories/base/base_npc_spells_effects_repository.h" + +#include "common/database.h" +#include "common/strings.h" class NpcSpellsEffectsRepository: public BaseNpcSpellsEffectsRepository { public: @@ -46,5 +46,3 @@ class NpcSpellsEffectsRepository: public BaseNpcSpellsEffectsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_NPC_SPELLS_EFFECTS_REPOSITORY_H diff --git a/common/repositories/npc_spells_entries_repository.h b/common/repositories/npc_spells_entries_repository.h index 4b21beff48..c2448e2a1e 100644 --- a/common/repositories/npc_spells_entries_repository.h +++ b/common/repositories/npc_spells_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_NPC_SPELLS_ENTRIES_REPOSITORY_H -#define EQEMU_NPC_SPELLS_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_npc_spells_entries_repository.h" +#include "common/repositories/base/base_npc_spells_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class NpcSpellsEntriesRepository: public BaseNpcSpellsEntriesRepository { public: @@ -46,5 +46,3 @@ class NpcSpellsEntriesRepository: public BaseNpcSpellsEntriesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_NPC_SPELLS_ENTRIES_REPOSITORY_H diff --git a/common/repositories/npc_spells_repository.h b/common/repositories/npc_spells_repository.h index e9b0170857..3dabf66fb6 100644 --- a/common/repositories/npc_spells_repository.h +++ b/common/repositories/npc_spells_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_NPC_SPELLS_REPOSITORY_H -#define EQEMU_NPC_SPELLS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_npc_spells_repository.h" +#include "common/repositories/base/base_npc_spells_repository.h" + +#include "common/database.h" +#include "common/strings.h" class NpcSpellsRepository: public BaseNpcSpellsRepository { public: @@ -46,5 +46,3 @@ class NpcSpellsRepository: public BaseNpcSpellsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_NPC_SPELLS_REPOSITORY_H diff --git a/common/repositories/npc_types_repository.h b/common/repositories/npc_types_repository.h index 75ec706fcf..90571ce259 100644 --- a/common/repositories/npc_types_repository.h +++ b/common/repositories/npc_types_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_NPC_TYPES_REPOSITORY_H -#define EQEMU_NPC_TYPES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_npc_types_repository.h" +#include "common/repositories/base/base_npc_types_repository.h" + +#include "common/database.h" +#include "common/strings.h" class NpcTypesRepository: public BaseNpcTypesRepository { public: @@ -71,5 +71,3 @@ class NpcTypesRepository: public BaseNpcTypesRepository { return npc_id < max_id ? npc_id : 0; } }; - -#endif //EQEMU_NPC_TYPES_REPOSITORY_H diff --git a/common/repositories/npc_types_tint_repository.h b/common/repositories/npc_types_tint_repository.h index aa501acf88..56fa452076 100644 --- a/common/repositories/npc_types_tint_repository.h +++ b/common/repositories/npc_types_tint_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_NPC_TYPES_TINT_REPOSITORY_H -#define EQEMU_NPC_TYPES_TINT_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_npc_types_tint_repository.h" +#include "common/repositories/base/base_npc_types_tint_repository.h" + +#include "common/database.h" +#include "common/strings.h" class NpcTypesTintRepository: public BaseNpcTypesTintRepository { public: @@ -46,5 +46,3 @@ class NpcTypesTintRepository: public BaseNpcTypesTintRepository { // Custom extended repository methods here }; - -#endif //EQEMU_NPC_TYPES_TINT_REPOSITORY_H diff --git a/common/repositories/object_contents_repository.h b/common/repositories/object_contents_repository.h index 6ed16bd333..15e4621e07 100644 --- a/common/repositories/object_contents_repository.h +++ b/common/repositories/object_contents_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_OBJECT_CONTENTS_REPOSITORY_H -#define EQEMU_OBJECT_CONTENTS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_object_contents_repository.h" +#include "common/repositories/base/base_object_contents_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ObjectContentsRepository: public BaseObjectContentsRepository { public: @@ -46,5 +46,3 @@ class ObjectContentsRepository: public BaseObjectContentsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_OBJECT_CONTENTS_REPOSITORY_H diff --git a/common/repositories/object_repository.h b/common/repositories/object_repository.h index 151572b358..304db497e1 100644 --- a/common/repositories/object_repository.h +++ b/common/repositories/object_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_OBJECT_REPOSITORY_H -#define EQEMU_OBJECT_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_object_repository.h" +#include "common/repositories/base/base_object_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ObjectRepository: public BaseObjectRepository { public: @@ -46,5 +46,3 @@ class ObjectRepository: public BaseObjectRepository { // Custom extended repository methods here }; - -#endif //EQEMU_OBJECT_REPOSITORY_H diff --git a/common/repositories/perl_event_export_settings_repository.h b/common/repositories/perl_event_export_settings_repository.h index a7e195f547..9f28296ed6 100644 --- a/common/repositories/perl_event_export_settings_repository.h +++ b/common/repositories/perl_event_export_settings_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_PERL_EVENT_EXPORT_SETTINGS_REPOSITORY_H -#define EQEMU_PERL_EVENT_EXPORT_SETTINGS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_perl_event_export_settings_repository.h" +#include "common/repositories/base/base_perl_event_export_settings_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PerlEventExportSettingsRepository: public BasePerlEventExportSettingsRepository { public: @@ -46,5 +46,3 @@ class PerlEventExportSettingsRepository: public BasePerlEventExportSettingsRepos // Custom extended repository methods here }; - -#endif //EQEMU_PERL_EVENT_EXPORT_SETTINGS_REPOSITORY_H diff --git a/common/repositories/petitions_repository.h b/common/repositories/petitions_repository.h index 0625845a8b..6efc97766c 100644 --- a/common/repositories/petitions_repository.h +++ b/common/repositories/petitions_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_PETITIONS_REPOSITORY_H -#define EQEMU_PETITIONS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_petitions_repository.h" +#include "common/repositories/base/base_petitions_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PetitionsRepository: public BasePetitionsRepository { public: @@ -46,5 +46,3 @@ class PetitionsRepository: public BasePetitionsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_PETITIONS_REPOSITORY_H diff --git a/common/repositories/pets_beastlord_data_repository.h b/common/repositories/pets_beastlord_data_repository.h index 598c154d26..83941df8f8 100644 --- a/common/repositories/pets_beastlord_data_repository.h +++ b/common/repositories/pets_beastlord_data_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_PETS_BEASTLORD_DATA_REPOSITORY_H -#define EQEMU_PETS_BEASTLORD_DATA_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_pets_beastlord_data_repository.h" +#include "common/repositories/base/base_pets_beastlord_data_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PetsBeastlordDataRepository: public BasePetsBeastlordDataRepository { public: @@ -46,5 +46,3 @@ class PetsBeastlordDataRepository: public BasePetsBeastlordDataRepository { // Custom extended repository methods here }; - -#endif //EQEMU_PETS_BEASTLORD_DATA_REPOSITORY_H diff --git a/common/repositories/pets_equipmentset_entries_repository.h b/common/repositories/pets_equipmentset_entries_repository.h index b66f739c10..3a87b12d3b 100644 --- a/common/repositories/pets_equipmentset_entries_repository.h +++ b/common/repositories/pets_equipmentset_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_PETS_EQUIPMENTSET_ENTRIES_REPOSITORY_H -#define EQEMU_PETS_EQUIPMENTSET_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_pets_equipmentset_entries_repository.h" +#include "common/repositories/base/base_pets_equipmentset_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PetsEquipmentsetEntriesRepository: public BasePetsEquipmentsetEntriesRepository { public: @@ -46,5 +46,3 @@ class PetsEquipmentsetEntriesRepository: public BasePetsEquipmentsetEntriesRepos // Custom extended repository methods here }; - -#endif //EQEMU_PETS_EQUIPMENTSET_ENTRIES_REPOSITORY_H diff --git a/common/repositories/pets_equipmentset_repository.h b/common/repositories/pets_equipmentset_repository.h index e676ebe5b3..36fd58265c 100644 --- a/common/repositories/pets_equipmentset_repository.h +++ b/common/repositories/pets_equipmentset_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_PETS_EQUIPMENTSET_REPOSITORY_H -#define EQEMU_PETS_EQUIPMENTSET_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_pets_equipmentset_repository.h" +#include "common/repositories/base/base_pets_equipmentset_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PetsEquipmentsetRepository: public BasePetsEquipmentsetRepository { public: @@ -46,5 +46,3 @@ class PetsEquipmentsetRepository: public BasePetsEquipmentsetRepository { // Custom extended repository methods here }; - -#endif //EQEMU_PETS_EQUIPMENTSET_REPOSITORY_H diff --git a/common/repositories/pets_repository.h b/common/repositories/pets_repository.h index df8e66bc82..0bb89634dc 100644 --- a/common/repositories/pets_repository.h +++ b/common/repositories/pets_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_PETS_REPOSITORY_H -#define EQEMU_PETS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_pets_repository.h" +#include "common/repositories/base/base_pets_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PetsRepository: public BasePetsRepository { public: @@ -46,5 +46,3 @@ class PetsRepository: public BasePetsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_PETS_REPOSITORY_H diff --git a/common/repositories/player_event_aa_purchase_repository.h b/common/repositories/player_event_aa_purchase_repository.h index 189c6c619b..b4402364b5 100644 --- a/common/repositories/player_event_aa_purchase_repository.h +++ b/common/repositories/player_event_aa_purchase_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_event_aa_purchase_repository.h" +#include "common/repositories/base/base_player_event_aa_purchase_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerEventAaPurchaseRepository: public BasePlayerEventAaPurchaseRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_EVENT_AA_PURCHASE_REPOSITORY_H diff --git a/common/repositories/player_event_killed_named_npc_repository.h b/common/repositories/player_event_killed_named_npc_repository.h index bd93fa8ce5..b68a9bf258 100644 --- a/common/repositories/player_event_killed_named_npc_repository.h +++ b/common/repositories/player_event_killed_named_npc_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_event_killed_named_npc_repository.h" +#include "common/repositories/base/base_player_event_killed_named_npc_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerEventKilledNamedNpcRepository: public BasePlayerEventKilledNamedNpcRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_EVENT_KILLED_NAMED_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_killed_npc_repository.h b/common/repositories/player_event_killed_npc_repository.h index fcbacf7c50..1cc9cef657 100644 --- a/common/repositories/player_event_killed_npc_repository.h +++ b/common/repositories/player_event_killed_npc_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_event_killed_npc_repository.h" +#include "common/repositories/base/base_player_event_killed_npc_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerEventKilledNpcRepository: public BasePlayerEventKilledNpcRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_EVENT_KILLED_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_killed_raid_npc_repository.h b/common/repositories/player_event_killed_raid_npc_repository.h index 8b4002c7b0..c9f27ca081 100644 --- a/common/repositories/player_event_killed_raid_npc_repository.h +++ b/common/repositories/player_event_killed_raid_npc_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_event_killed_raid_npc_repository.h" +#include "common/repositories/base/base_player_event_killed_raid_npc_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerEventKilledRaidNpcRepository: public BasePlayerEventKilledRaidNpcRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_EVENT_KILLED_RAID_NPC_REPOSITORY_H diff --git a/common/repositories/player_event_log_settings_repository.h b/common/repositories/player_event_log_settings_repository.h index 10aebc135b..455de33059 100644 --- a/common/repositories/player_event_log_settings_repository.h +++ b/common/repositories/player_event_log_settings_repository.h @@ -1,14 +1,13 @@ -#ifndef EQEMU_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../events/player_events.h" -#include "../strings.h" -#include "base/base_player_event_log_settings_repository.h" -#include "base/base_player_event_loot_items_repository.h" +#include "common/repositories/base/base_player_event_log_settings_repository.h" + +#include "common/database.h" +#include "common/events/player_events.h" +#include "common/repositories/base/base_player_event_loot_items_repository.h" +#include "common/strings.h" class PlayerEventLogSettingsRepository: public BasePlayerEventLogSettingsRepository { public: // Custom extended repository methods here }; -#endif //EQEMU_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H diff --git a/common/repositories/player_event_logs_repository.h b/common/repositories/player_event_logs_repository.h index 59de5e46c1..5df841bce5 100644 --- a/common/repositories/player_event_logs_repository.h +++ b/common/repositories/player_event_logs_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_PLAYER_EVENT_LOGS_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_LOGS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_event_logs_repository.h" +#include "common/repositories/base/base_player_event_logs_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerEventLogsRepository: public BasePlayerEventLogsRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_EVENT_LOGS_REPOSITORY_H diff --git a/common/repositories/player_event_loot_items_repository.h b/common/repositories/player_event_loot_items_repository.h index 5767d1fb4a..75241dfb7e 100644 --- a/common/repositories/player_event_loot_items_repository.h +++ b/common/repositories/player_event_loot_items_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_event_loot_items_repository.h" +#include "common/repositories/base/base_player_event_loot_items_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerEventLootItemsRepository: public BasePlayerEventLootItemsRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_EVENT_LOOT_ITEMS_REPOSITORY_H diff --git a/common/repositories/player_event_merchant_purchase_repository.h b/common/repositories/player_event_merchant_purchase_repository.h index 9be7aef6a0..760d97f30a 100644 --- a/common/repositories/player_event_merchant_purchase_repository.h +++ b/common/repositories/player_event_merchant_purchase_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_event_merchant_purchase_repository.h" +#include "common/repositories/base/base_player_event_merchant_purchase_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerEventMerchantPurchaseRepository: public BasePlayerEventMerchantPurchaseRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_EVENT_MERCHANT_PURCHASE_REPOSITORY_H diff --git a/common/repositories/player_event_merchant_sell_repository.h b/common/repositories/player_event_merchant_sell_repository.h index c93131b7a4..ef11cd9f1c 100644 --- a/common/repositories/player_event_merchant_sell_repository.h +++ b/common/repositories/player_event_merchant_sell_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_event_merchant_sell_repository.h" +#include "common/repositories/base/base_player_event_merchant_sell_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerEventMerchantSellRepository: public BasePlayerEventMerchantSellRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_EVENT_MERCHANT_SELL_REPOSITORY_H diff --git a/common/repositories/player_event_npc_handin_entries_repository.h b/common/repositories/player_event_npc_handin_entries_repository.h index f3c6d3bbe6..76503cf5bb 100644 --- a/common/repositories/player_event_npc_handin_entries_repository.h +++ b/common/repositories/player_event_npc_handin_entries_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_event_npc_handin_entries_repository.h" +#include "common/repositories/base/base_player_event_npc_handin_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerEventNpcHandinEntriesRepository: public BasePlayerEventNpcHandinEntriesRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_EVENT_NPC_HANDIN_ENTRIES_REPOSITORY_H diff --git a/common/repositories/player_event_npc_handin_repository.h b/common/repositories/player_event_npc_handin_repository.h index 2b3e233868..ead99fc9c1 100644 --- a/common/repositories/player_event_npc_handin_repository.h +++ b/common/repositories/player_event_npc_handin_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_event_npc_handin_repository.h" +#include "common/repositories/base/base_player_event_npc_handin_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerEventNpcHandinRepository: public BasePlayerEventNpcHandinRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_EVENT_NPC_HANDIN_REPOSITORY_H diff --git a/common/repositories/player_event_speech_repository.h b/common/repositories/player_event_speech_repository.h index 22f9158fb5..65d1590501 100644 --- a/common/repositories/player_event_speech_repository.h +++ b/common/repositories/player_event_speech_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_PLAYER_EVENT_SPEECH_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_SPEECH_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_event_speech_repository.h" +#include "common/repositories/base/base_player_event_speech_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerEventSpeechRepository: public BasePlayerEventSpeechRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_EVENT_SPEECH_REPOSITORY_H diff --git a/common/repositories/player_event_trade_entries_repository.h b/common/repositories/player_event_trade_entries_repository.h index 775d833702..832e6e9f3a 100644 --- a/common/repositories/player_event_trade_entries_repository.h +++ b/common/repositories/player_event_trade_entries_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_event_trade_entries_repository.h" +#include "common/repositories/base/base_player_event_trade_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerEventTradeEntriesRepository: public BasePlayerEventTradeEntriesRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_EVENT_TRADE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/player_event_trade_repository.h b/common/repositories/player_event_trade_repository.h index 7813e6fcd6..119c2b334b 100644 --- a/common/repositories/player_event_trade_repository.h +++ b/common/repositories/player_event_trade_repository.h @@ -1,13 +1,11 @@ -#ifndef EQEMU_PLAYER_EVENT_TRADE_REPOSITORY_H -#define EQEMU_PLAYER_EVENT_TRADE_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_event_trade_repository.h" +#include "common/repositories/base/base_player_event_trade_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerEventTradeRepository: public BasePlayerEventTradeRepository { public: // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_EVENT_TRADE_REPOSITORY_H diff --git a/common/repositories/player_titlesets_repository.h b/common/repositories/player_titlesets_repository.h index f2f6793479..62e46c420d 100644 --- a/common/repositories/player_titlesets_repository.h +++ b/common/repositories/player_titlesets_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_PLAYER_TITLESETS_REPOSITORY_H -#define EQEMU_PLAYER_TITLESETS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_player_titlesets_repository.h" +#include "common/repositories/base/base_player_titlesets_repository.h" + +#include "common/database.h" +#include "common/strings.h" class PlayerTitlesetsRepository: public BasePlayerTitlesetsRepository { public: @@ -46,5 +46,3 @@ class PlayerTitlesetsRepository: public BasePlayerTitlesetsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_PLAYER_TITLESETS_REPOSITORY_H diff --git a/common/repositories/quest_globals_repository.h b/common/repositories/quest_globals_repository.h index efdc6d5f0e..7b2c9696c3 100644 --- a/common/repositories/quest_globals_repository.h +++ b/common/repositories/quest_globals_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_QUEST_GLOBALS_REPOSITORY_H -#define EQEMU_QUEST_GLOBALS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_quest_globals_repository.h" +#include "common/repositories/base/base_quest_globals_repository.h" + +#include "common/database.h" +#include "common/strings.h" class QuestGlobalsRepository: public BaseQuestGlobalsRepository { public: @@ -46,5 +46,3 @@ class QuestGlobalsRepository: public BaseQuestGlobalsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_QUEST_GLOBALS_REPOSITORY_H diff --git a/common/repositories/raid_details_repository.h b/common/repositories/raid_details_repository.h index 6903db2a3b..967915e2e3 100644 --- a/common/repositories/raid_details_repository.h +++ b/common/repositories/raid_details_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_RAID_DETAILS_REPOSITORY_H -#define EQEMU_RAID_DETAILS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_raid_details_repository.h" +#include "common/repositories/base/base_raid_details_repository.h" + +#include "common/database.h" +#include "common/strings.h" class RaidDetailsRepository: public BaseRaidDetailsRepository { public: @@ -77,5 +77,3 @@ class RaidDetailsRepository: public BaseRaidDetailsRepository { ); } }; - -#endif //EQEMU_RAID_DETAILS_REPOSITORY_H diff --git a/common/repositories/raid_members_repository.h b/common/repositories/raid_members_repository.h index 822f3e1f69..0807b99c43 100644 --- a/common/repositories/raid_members_repository.h +++ b/common/repositories/raid_members_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_RAID_MEMBERS_REPOSITORY_H -#define EQEMU_RAID_MEMBERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_raid_members_repository.h" +#include "common/repositories/base/base_raid_members_repository.h" + +#include "common/database.h" +#include "common/strings.h" class RaidMembersRepository: public BaseRaidMembersRepository { public: @@ -108,5 +108,4 @@ class RaidMembersRepository: public BaseRaidMembersRepository { ) ); } -}; -#endif //EQEMU_RAID_MEMBERS_REPOSITORY_H +}; \ No newline at end of file diff --git a/common/repositories/reports_repository.h b/common/repositories/reports_repository.h index 96639f9d10..e14a8089c2 100644 --- a/common/repositories/reports_repository.h +++ b/common/repositories/reports_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_REPORTS_REPOSITORY_H -#define EQEMU_REPORTS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_reports_repository.h" +#include "common/repositories/base/base_reports_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ReportsRepository: public BaseReportsRepository { public: @@ -46,5 +46,3 @@ class ReportsRepository: public BaseReportsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_REPORTS_REPOSITORY_H diff --git a/common/repositories/respawn_times_repository.h b/common/repositories/respawn_times_repository.h index 3f2ddfa8bd..a0abf793aa 100644 --- a/common/repositories/respawn_times_repository.h +++ b/common/repositories/respawn_times_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_RESPAWN_TIMES_REPOSITORY_H -#define EQEMU_RESPAWN_TIMES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_respawn_times_repository.h" +#include "common/repositories/base/base_respawn_times_repository.h" + +#include "common/database.h" +#include "common/strings.h" class RespawnTimesRepository: public BaseRespawnTimesRepository { public: @@ -47,5 +47,3 @@ class RespawnTimesRepository: public BaseRespawnTimesRepository { RespawnTimesRepository::DeleteWhere(db, fmt::format("`instance_id` = {}", id)); } }; - -#endif //EQEMU_RESPAWN_TIMES_REPOSITORY_H diff --git a/common/repositories/rule_sets_repository.h b/common/repositories/rule_sets_repository.h index d4633c4226..bcd7a0bfa6 100644 --- a/common/repositories/rule_sets_repository.h +++ b/common/repositories/rule_sets_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_RULE_SETS_REPOSITORY_H -#define EQEMU_RULE_SETS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_rule_sets_repository.h" +#include "common/repositories/base/base_rule_sets_repository.h" + +#include "common/database.h" +#include "common/strings.h" class RuleSetsRepository: public BaseRuleSetsRepository { public: @@ -92,5 +92,3 @@ class RuleSetsRepository: public BaseRuleSetsRepository { return std::string(row[0]); } }; - -#endif //EQEMU_RULE_SETS_REPOSITORY_H diff --git a/common/repositories/rule_values_repository.h b/common/repositories/rule_values_repository.h index d7eb1530e5..e64ed9a6ae 100644 --- a/common/repositories/rule_values_repository.h +++ b/common/repositories/rule_values_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_RULE_VALUES_REPOSITORY_H -#define EQEMU_RULE_VALUES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_rule_values_repository.h" +#include "common/repositories/base/base_rule_values_repository.h" + +#include "common/database.h" +#include "common/strings.h" class RuleValuesRepository: public BaseRuleValuesRepository { public: @@ -184,5 +184,3 @@ class RuleValuesRepository: public BaseRuleValuesRepository { } }; - -#endif //EQEMU_RULE_VALUES_REPOSITORY_H diff --git a/common/repositories/saylink_repository.h b/common/repositories/saylink_repository.h index 4efc13ff1b..41baebb4bd 100644 --- a/common/repositories/saylink_repository.h +++ b/common/repositories/saylink_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SAYLINK_REPOSITORY_H -#define EQEMU_SAYLINK_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_saylink_repository.h" +#include "common/repositories/base/base_saylink_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SaylinkRepository: public BaseSaylinkRepository { public: @@ -46,5 +46,3 @@ class SaylinkRepository: public BaseSaylinkRepository { // Custom extended repository methods here }; - -#endif //EQEMU_SAYLINK_REPOSITORY_H diff --git a/common/repositories/server_scheduled_events_repository.h b/common/repositories/server_scheduled_events_repository.h index e42fa372d1..c5e29a9442 100644 --- a/common/repositories/server_scheduled_events_repository.h +++ b/common/repositories/server_scheduled_events_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SERVER_SCHEDULED_EVENTS_REPOSITORY_H -#define EQEMU_SERVER_SCHEDULED_EVENTS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_server_scheduled_events_repository.h" +#include "common/repositories/base/base_server_scheduled_events_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ServerScheduledEventsRepository: public BaseServerScheduledEventsRepository { public: @@ -46,5 +46,3 @@ class ServerScheduledEventsRepository: public BaseServerScheduledEventsRepositor // Custom extended repository methods here }; - -#endif //EQEMU_SERVER_SCHEDULED_EVENTS_REPOSITORY_H diff --git a/common/repositories/shared_task_activity_state_repository.h b/common/repositories/shared_task_activity_state_repository.h index 25aaa4391f..2ce9aa7dd5 100644 --- a/common/repositories/shared_task_activity_state_repository.h +++ b/common/repositories/shared_task_activity_state_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H -#define EQEMU_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_shared_task_activity_state_repository.h" +#include "common/repositories/base/base_shared_task_activity_state_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SharedTaskActivityStateRepository: public BaseSharedTaskActivityStateRepository { public: @@ -46,5 +46,3 @@ class SharedTaskActivityStateRepository: public BaseSharedTaskActivityStateRepos // Custom extended repository methods here }; - -#endif //EQEMU_SHARED_TASK_ACTIVITY_STATE_REPOSITORY_H diff --git a/common/repositories/shared_task_dynamic_zones_repository.h b/common/repositories/shared_task_dynamic_zones_repository.h index e3148cd9e4..5c98b30014 100644 --- a/common/repositories/shared_task_dynamic_zones_repository.h +++ b/common/repositories/shared_task_dynamic_zones_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SHARED_TASK_DYNAMIC_ZONES_REPOSITORY_H -#define EQEMU_SHARED_TASK_DYNAMIC_ZONES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_shared_task_dynamic_zones_repository.h" +#include "common/repositories/base/base_shared_task_dynamic_zones_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SharedTaskDynamicZonesRepository: public BaseSharedTaskDynamicZonesRepository { public: @@ -46,5 +46,3 @@ class SharedTaskDynamicZonesRepository: public BaseSharedTaskDynamicZonesReposit // Custom extended repository methods here }; - -#endif //EQEMU_SHARED_TASK_DYNAMIC_ZONES_REPOSITORY_H diff --git a/common/repositories/shared_task_members_repository.h b/common/repositories/shared_task_members_repository.h index d55289c17b..a1ee1f62c1 100644 --- a/common/repositories/shared_task_members_repository.h +++ b/common/repositories/shared_task_members_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SHARED_TASK_MEMBERS_REPOSITORY_H -#define EQEMU_SHARED_TASK_MEMBERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_shared_task_members_repository.h" +#include "common/repositories/base/base_shared_task_members_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SharedTaskMembersRepository: public BaseSharedTaskMembersRepository { public: @@ -46,5 +46,3 @@ class SharedTaskMembersRepository: public BaseSharedTaskMembersRepository { // Custom extended repository methods here }; - -#endif //EQEMU_SHARED_TASK_MEMBERS_REPOSITORY_H diff --git a/common/repositories/shared_tasks_repository.h b/common/repositories/shared_tasks_repository.h index 827597b84c..f073fe3744 100644 --- a/common/repositories/shared_tasks_repository.h +++ b/common/repositories/shared_tasks_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SHARED_TASKS_REPOSITORY_H -#define EQEMU_SHARED_TASKS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_shared_tasks_repository.h" +#include "common/repositories/base/base_shared_tasks_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SharedTasksRepository: public BaseSharedTasksRepository { public: @@ -46,5 +46,3 @@ class SharedTasksRepository: public BaseSharedTasksRepository { // Custom extended repository methods here }; - -#endif //EQEMU_SHARED_TASKS_REPOSITORY_H diff --git a/common/repositories/sharedbank_repository.h b/common/repositories/sharedbank_repository.h index d0aa47eafb..7684a92122 100644 --- a/common/repositories/sharedbank_repository.h +++ b/common/repositories/sharedbank_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SHAREDBANK_REPOSITORY_H -#define EQEMU_SHAREDBANK_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_sharedbank_repository.h" +#include "common/repositories/base/base_sharedbank_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SharedbankRepository: public BaseSharedbankRepository { public: @@ -46,5 +46,3 @@ class SharedbankRepository: public BaseSharedbankRepository { // Custom extended repository methods here }; - -#endif //EQEMU_SHAREDBANK_REPOSITORY_H diff --git a/common/repositories/skill_caps_repository.h b/common/repositories/skill_caps_repository.h index 05be76b0b2..b41f8b204e 100644 --- a/common/repositories/skill_caps_repository.h +++ b/common/repositories/skill_caps_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SKILL_CAPS_REPOSITORY_H -#define EQEMU_SKILL_CAPS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_skill_caps_repository.h" +#include "common/repositories/base/base_skill_caps_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SkillCapsRepository: public BaseSkillCapsRepository { public: @@ -62,5 +62,3 @@ class SkillCapsRepository: public BaseSkillCapsRepository { return lines; } }; - -#endif //EQEMU_SKILL_CAPS_REPOSITORY_H diff --git a/common/repositories/spawn2_disabled_repository.h b/common/repositories/spawn2_disabled_repository.h index 86bb81d1f8..41ee133eba 100644 --- a/common/repositories/spawn2_disabled_repository.h +++ b/common/repositories/spawn2_disabled_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SPAWN2_DISABLED_REPOSITORY_H -#define EQEMU_SPAWN2_DISABLED_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_spawn2_disabled_repository.h" +#include "common/repositories/base/base_spawn2_disabled_repository.h" + +#include "common/database.h" +#include "common/strings.h" class Spawn2DisabledRepository: public BaseSpawn2DisabledRepository { public: @@ -46,5 +46,3 @@ class Spawn2DisabledRepository: public BaseSpawn2DisabledRepository { // Custom extended repository methods here }; - -#endif //EQEMU_SPAWN2_DISABLED_REPOSITORY_H diff --git a/common/repositories/spawn2_repository.h b/common/repositories/spawn2_repository.h index 8fc53ad1d8..b980f26d78 100644 --- a/common/repositories/spawn2_repository.h +++ b/common/repositories/spawn2_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SPAWN2_REPOSITORY_H -#define EQEMU_SPAWN2_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_spawn2_repository.h" +#include "common/repositories/base/base_spawn2_repository.h" + +#include "common/database.h" +#include "common/strings.h" class Spawn2Repository: public BaseSpawn2Repository { public: @@ -74,5 +74,3 @@ class Spawn2Repository: public BaseSpawn2Repository { ); } }; - -#endif //EQEMU_SPAWN2_REPOSITORY_H diff --git a/common/repositories/spawn_condition_values_repository.h b/common/repositories/spawn_condition_values_repository.h index 14a1360374..22deebe3bd 100644 --- a/common/repositories/spawn_condition_values_repository.h +++ b/common/repositories/spawn_condition_values_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SPAWN_CONDITION_VALUES_REPOSITORY_H -#define EQEMU_SPAWN_CONDITION_VALUES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_spawn_condition_values_repository.h" +#include "common/repositories/base/base_spawn_condition_values_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SpawnConditionValuesRepository: public BaseSpawnConditionValuesRepository { public: @@ -46,5 +46,3 @@ class SpawnConditionValuesRepository: public BaseSpawnConditionValuesRepository // Custom extended repository methods here }; - -#endif //EQEMU_SPAWN_CONDITION_VALUES_REPOSITORY_H diff --git a/common/repositories/spawn_conditions_repository.h b/common/repositories/spawn_conditions_repository.h index 0ff130faaa..a55f5be725 100644 --- a/common/repositories/spawn_conditions_repository.h +++ b/common/repositories/spawn_conditions_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SPAWN_CONDITIONS_REPOSITORY_H -#define EQEMU_SPAWN_CONDITIONS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_spawn_conditions_repository.h" +#include "common/repositories/base/base_spawn_conditions_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SpawnConditionsRepository: public BaseSpawnConditionsRepository { public: @@ -46,5 +46,3 @@ class SpawnConditionsRepository: public BaseSpawnConditionsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_SPAWN_CONDITIONS_REPOSITORY_H diff --git a/common/repositories/spawn_events_repository.h b/common/repositories/spawn_events_repository.h index 4e008e79d7..294da1d962 100644 --- a/common/repositories/spawn_events_repository.h +++ b/common/repositories/spawn_events_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SPAWN_EVENTS_REPOSITORY_H -#define EQEMU_SPAWN_EVENTS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_spawn_events_repository.h" +#include "common/repositories/base/base_spawn_events_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SpawnEventsRepository: public BaseSpawnEventsRepository { public: @@ -46,5 +46,3 @@ class SpawnEventsRepository: public BaseSpawnEventsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_SPAWN_EVENTS_REPOSITORY_H diff --git a/common/repositories/spawnentry_repository.h b/common/repositories/spawnentry_repository.h index 0a61a5287a..89bc58d0a8 100644 --- a/common/repositories/spawnentry_repository.h +++ b/common/repositories/spawnentry_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SPAWNENTRY_REPOSITORY_H -#define EQEMU_SPAWNENTRY_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_spawnentry_repository.h" +#include "common/repositories/base/base_spawnentry_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SpawnentryRepository: public BaseSpawnentryRepository { public: @@ -46,5 +46,3 @@ class SpawnentryRepository: public BaseSpawnentryRepository { // Custom extended repository methods here }; - -#endif //EQEMU_SPAWNENTRY_REPOSITORY_H diff --git a/common/repositories/spawngroup_repository.h b/common/repositories/spawngroup_repository.h index 6e0a7b59b2..5377305d03 100644 --- a/common/repositories/spawngroup_repository.h +++ b/common/repositories/spawngroup_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SPAWNGROUP_REPOSITORY_H -#define EQEMU_SPAWNGROUP_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_spawngroup_repository.h" +#include "common/repositories/base/base_spawngroup_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SpawngroupRepository: public BaseSpawngroupRepository { public: @@ -46,5 +46,3 @@ class SpawngroupRepository: public BaseSpawngroupRepository { // Custom extended repository methods here }; - -#endif //EQEMU_SPAWNGROUP_REPOSITORY_H diff --git a/common/repositories/spell_buckets_repository.h b/common/repositories/spell_buckets_repository.h index ddba4be0cc..f09da8056b 100644 --- a/common/repositories/spell_buckets_repository.h +++ b/common/repositories/spell_buckets_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SPELL_BUCKETS_REPOSITORY_H -#define EQEMU_SPELL_BUCKETS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_spell_buckets_repository.h" +#include "common/repositories/base/base_spell_buckets_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SpellBucketsRepository: public BaseSpellBucketsRepository { public: @@ -46,5 +46,3 @@ class SpellBucketsRepository: public BaseSpellBucketsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_SPELL_BUCKETS_REPOSITORY_H diff --git a/common/repositories/spell_globals_repository.h b/common/repositories/spell_globals_repository.h index 91cb74caf4..54f40a4bed 100644 --- a/common/repositories/spell_globals_repository.h +++ b/common/repositories/spell_globals_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SPELL_GLOBALS_REPOSITORY_H -#define EQEMU_SPELL_GLOBALS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_spell_globals_repository.h" +#include "common/repositories/base/base_spell_globals_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SpellGlobalsRepository: public BaseSpellGlobalsRepository { public: @@ -46,5 +46,3 @@ class SpellGlobalsRepository: public BaseSpellGlobalsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_SPELL_GLOBALS_REPOSITORY_H diff --git a/common/repositories/spells_new_repository.h b/common/repositories/spells_new_repository.h index 0e25e9c6e2..1f32fe2ee0 100644 --- a/common/repositories/spells_new_repository.h +++ b/common/repositories/spells_new_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_SPELLS_NEW_REPOSITORY_H -#define EQEMU_SPELLS_NEW_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_spells_new_repository.h" +#include "common/repositories/base/base_spells_new_repository.h" + +#include "common/database.h" +#include "common/strings.h" class SpellsNewRepository: public BaseSpellsNewRepository { public: @@ -64,5 +64,3 @@ class SpellsNewRepository: public BaseSpellsNewRepository { return lines; } }; - -#endif //EQEMU_SPELLS_NEW_REPOSITORY_H diff --git a/common/repositories/start_zones_repository.h b/common/repositories/start_zones_repository.h index 99f29da211..70951a1101 100644 --- a/common/repositories/start_zones_repository.h +++ b/common/repositories/start_zones_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_START_ZONES_REPOSITORY_H -#define EQEMU_START_ZONES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_start_zones_repository.h" +#include "common/repositories/base/base_start_zones_repository.h" + +#include "common/database.h" +#include "common/strings.h" class StartZonesRepository: public BaseStartZonesRepository { public: @@ -46,5 +46,3 @@ class StartZonesRepository: public BaseStartZonesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_START_ZONES_REPOSITORY_H diff --git a/common/repositories/starting_items_repository.h b/common/repositories/starting_items_repository.h index 8389008ac1..dbb01fffe4 100644 --- a/common/repositories/starting_items_repository.h +++ b/common/repositories/starting_items_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_STARTING_ITEMS_REPOSITORY_H -#define EQEMU_STARTING_ITEMS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_starting_items_repository.h" +#include "common/repositories/base/base_starting_items_repository.h" + +#include "common/database.h" +#include "common/strings.h" class StartingItemsRepository: public BaseStartingItemsRepository { public: @@ -46,5 +46,3 @@ class StartingItemsRepository: public BaseStartingItemsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_STARTING_ITEMS_REPOSITORY_H diff --git a/common/repositories/task_activities_repository.h b/common/repositories/task_activities_repository.h index 3a57ccdc49..70e1f9ae86 100644 --- a/common/repositories/task_activities_repository.h +++ b/common/repositories/task_activities_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_TASK_ACTIVITIES_REPOSITORY_H -#define EQEMU_TASK_ACTIVITIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_task_activities_repository.h" +#include "common/repositories/base/base_task_activities_repository.h" + +#include "common/database.h" +#include "common/strings.h" class TaskActivitiesRepository: public BaseTaskActivitiesRepository { public: @@ -46,5 +46,3 @@ class TaskActivitiesRepository: public BaseTaskActivitiesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_TASK_ACTIVITIES_REPOSITORY_H diff --git a/common/repositories/tasks_repository.h b/common/repositories/tasks_repository.h index 59c2f14fa3..b1c4bd82ed 100644 --- a/common/repositories/tasks_repository.h +++ b/common/repositories/tasks_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_TASKS_REPOSITORY_H -#define EQEMU_TASKS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_tasks_repository.h" +#include "common/repositories/base/base_tasks_repository.h" + +#include "common/database.h" +#include "common/strings.h" class TasksRepository: public BaseTasksRepository { public: @@ -46,5 +46,3 @@ class TasksRepository: public BaseTasksRepository { // Custom extended repository methods here }; - -#endif //EQEMU_TASKS_REPOSITORY_H diff --git a/common/repositories/tasksets_repository.h b/common/repositories/tasksets_repository.h index 44dd1fc471..a9a1edc3eb 100644 --- a/common/repositories/tasksets_repository.h +++ b/common/repositories/tasksets_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_TASKSETS_REPOSITORY_H -#define EQEMU_TASKSETS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_tasksets_repository.h" +#include "common/repositories/base/base_tasksets_repository.h" + +#include "common/database.h" +#include "common/strings.h" class TasksetsRepository: public BaseTasksetsRepository { public: @@ -46,5 +46,3 @@ class TasksetsRepository: public BaseTasksetsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_TASKSETS_REPOSITORY_H diff --git a/common/repositories/template/base_repository.template b/common/repositories/template/base_repository.template index 5a7000ee02..be28ac208c 100644 --- a/common/repositories/template/base_repository.template +++ b/common/repositories/template/base_repository.template @@ -6,16 +6,16 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://docs.eqemu.io/developer/repositories + * @docs https://docs.eqemu.dev/developer/repositories */ -#ifndef EQEMU_BASE_{{TABLE_NAME_UPPER}}_REPOSITORY_H -#define EQEMU_BASE_{{TABLE_NAME_UPPER}}_REPOSITORY_H +#pragma once + +#include "common/database.h" +#include "common/strings.h" -#include "../../database.h" -#include "../../strings.h" -#include {{ADDITIONAL_INCLUDES}} +#include class Base{{TABLE_NAME_CLASS}}Repository { public: @@ -376,5 +376,3 @@ public: return (results.Success() ? results.RowsAffected() : 0); } }; - -#endif //EQEMU_BASE_{{TABLE_NAME_UPPER}}_REPOSITORY_H diff --git a/common/repositories/template/repository.template b/common/repositories/template/repository.template index d5de51e4ee..5ef2380b44 100644 --- a/common/repositories/template/repository.template +++ b/common/repositories/template/repository.template @@ -1,9 +1,9 @@ -#ifndef EQEMU_{{TABLE_NAME_UPPER}}_REPOSITORY_H -#define EQEMU_{{TABLE_NAME_UPPER}}_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_{{TABLE_NAME_VAR}}_repository.h" +#include "common/repositories/base/base_{{TABLE_NAME_VAR}}_repository.h" + +#include "common/database.h" +#include "common/strings.h" class {{TABLE_NAME_CLASS}}Repository: public Base{{TABLE_NAME_CLASS}}Repository { public: @@ -46,5 +46,3 @@ public: // Custom extended repository methods here }; - -#endif //EQEMU_{{TABLE_NAME_UPPER}}_REPOSITORY_H diff --git a/common/repositories/timers_repository.h b/common/repositories/timers_repository.h index eb497f12b9..3658615be0 100644 --- a/common/repositories/timers_repository.h +++ b/common/repositories/timers_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_TIMERS_REPOSITORY_H -#define EQEMU_TIMERS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_timers_repository.h" +#include "common/repositories/base/base_timers_repository.h" + +#include "common/database.h" +#include "common/strings.h" class TimersRepository: public BaseTimersRepository { public: @@ -46,5 +46,3 @@ class TimersRepository: public BaseTimersRepository { // Custom extended repository methods here }; - -#endif //EQEMU_TIMERS_REPOSITORY_H diff --git a/common/repositories/titles_repository.h b/common/repositories/titles_repository.h index 3ff4544aef..6927b9dd6d 100644 --- a/common/repositories/titles_repository.h +++ b/common/repositories/titles_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_TITLES_REPOSITORY_H -#define EQEMU_TITLES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_titles_repository.h" +#include "common/repositories/base/base_titles_repository.h" + +#include "common/database.h" +#include "common/strings.h" class TitlesRepository: public BaseTitlesRepository { public: @@ -46,5 +46,3 @@ class TitlesRepository: public BaseTitlesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_TITLES_REPOSITORY_H diff --git a/common/repositories/tool_game_objects_repository.h b/common/repositories/tool_game_objects_repository.h index 0afbf23341..fe7fb9f356 100644 --- a/common/repositories/tool_game_objects_repository.h +++ b/common/repositories/tool_game_objects_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_TOOL_GAME_OBJECTS_REPOSITORY_H -#define EQEMU_TOOL_GAME_OBJECTS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_tool_game_objects_repository.h" +#include "common/repositories/base/base_tool_game_objects_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ToolGameObjectsRepository: public BaseToolGameObjectsRepository { public: @@ -46,5 +46,3 @@ class ToolGameObjectsRepository: public BaseToolGameObjectsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_TOOL_GAME_OBJECTS_REPOSITORY_H diff --git a/common/repositories/trader_audit_repository.h b/common/repositories/trader_audit_repository.h index 491a4c1a69..3d6f90168f 100644 --- a/common/repositories/trader_audit_repository.h +++ b/common/repositories/trader_audit_repository.h @@ -1,8 +1,7 @@ -#ifndef EQEMU_TRADER_AUDIT_REPOSITORY_H -#define EQEMU_TRADER_AUDIT_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" +#include "common/database.h" +#include "common/strings.h" class TraderAuditRepository { public: @@ -277,5 +276,3 @@ class TraderAuditRepository { } }; - -#endif //EQEMU_TRADER_AUDIT_REPOSITORY_H diff --git a/common/repositories/trader_repository.h b/common/repositories/trader_repository.h index 3c5fbdafc9..2dcc30dc73 100644 --- a/common/repositories/trader_repository.h +++ b/common/repositories/trader_repository.h @@ -1,14 +1,15 @@ -#ifndef EQEMU_TRADER_REPOSITORY_H -#define EQEMU_TRADER_REPOSITORY_H - -#include "../../common/shareddb.h" -#include "../strings.h" -#include "base/base_trader_repository.h" -#include "items_repository.h" -#include "../../common/item_data.h" -#include "../../common/races.h" -#include -#include +#pragma once + +#include "common/repositories/base/base_trader_repository.h" + +#include "common/item_data.h" +#include "common/races.h" +#include "common/repositories/items_repository.h" +#include "common/shareddb.h" +#include "common/strings.h" + +#include "cereal/archives/binary.hpp" +#include "cereal/types/string.hpp" class TraderRepository : public BaseTraderRepository { public: @@ -335,5 +336,3 @@ class TraderRepository : public BaseTraderRepository { return all_entries; } }; - -#endif //EQEMU_TRADER_REPOSITORY_H diff --git a/common/repositories/tradeskill_recipe_entries_repository.h b/common/repositories/tradeskill_recipe_entries_repository.h index cb575ed9ce..a94cb5d82c 100644 --- a/common/repositories/tradeskill_recipe_entries_repository.h +++ b/common/repositories/tradeskill_recipe_entries_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_TRADESKILL_RECIPE_ENTRIES_REPOSITORY_H -#define EQEMU_TRADESKILL_RECIPE_ENTRIES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_tradeskill_recipe_entries_repository.h" +#include "common/repositories/base/base_tradeskill_recipe_entries_repository.h" + +#include "common/database.h" +#include "common/strings.h" class TradeskillRecipeEntriesRepository: public BaseTradeskillRecipeEntriesRepository { public: @@ -46,5 +46,3 @@ class TradeskillRecipeEntriesRepository: public BaseTradeskillRecipeEntriesRepos // Custom extended repository methods here }; - -#endif //EQEMU_TRADESKILL_RECIPE_ENTRIES_REPOSITORY_H diff --git a/common/repositories/tradeskill_recipe_repository.h b/common/repositories/tradeskill_recipe_repository.h index 287fecd996..f1a07dfed9 100644 --- a/common/repositories/tradeskill_recipe_repository.h +++ b/common/repositories/tradeskill_recipe_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_TRADESKILL_RECIPE_REPOSITORY_H -#define EQEMU_TRADESKILL_RECIPE_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_tradeskill_recipe_repository.h" +#include "common/repositories/base/base_tradeskill_recipe_repository.h" + +#include "common/database.h" +#include "common/strings.h" class TradeskillRecipeRepository: public BaseTradeskillRecipeRepository { public: @@ -46,5 +46,3 @@ class TradeskillRecipeRepository: public BaseTradeskillRecipeRepository { // Custom extended repository methods here }; - -#endif //EQEMU_TRADESKILL_RECIPE_REPOSITORY_H diff --git a/common/repositories/traps_repository.h b/common/repositories/traps_repository.h index a32465fc5c..4e3f60f8b1 100644 --- a/common/repositories/traps_repository.h +++ b/common/repositories/traps_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_TRAPS_REPOSITORY_H -#define EQEMU_TRAPS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_traps_repository.h" +#include "common/repositories/base/base_traps_repository.h" + +#include "common/database.h" +#include "common/strings.h" class TrapsRepository: public BaseTrapsRepository { public: @@ -46,5 +46,3 @@ class TrapsRepository: public BaseTrapsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_TRAPS_REPOSITORY_H diff --git a/common/repositories/tribute_levels_repository.h b/common/repositories/tribute_levels_repository.h index 26fb01a243..01705b6244 100644 --- a/common/repositories/tribute_levels_repository.h +++ b/common/repositories/tribute_levels_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_TRIBUTE_LEVELS_REPOSITORY_H -#define EQEMU_TRIBUTE_LEVELS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_tribute_levels_repository.h" +#include "common/repositories/base/base_tribute_levels_repository.h" + +#include "common/database.h" +#include "common/strings.h" class TributeLevelsRepository: public BaseTributeLevelsRepository { public: @@ -46,5 +46,3 @@ class TributeLevelsRepository: public BaseTributeLevelsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_TRIBUTE_LEVELS_REPOSITORY_H diff --git a/common/repositories/tributes_repository.h b/common/repositories/tributes_repository.h index ea0145057a..93371daa7c 100644 --- a/common/repositories/tributes_repository.h +++ b/common/repositories/tributes_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_TRIBUTES_REPOSITORY_H -#define EQEMU_TRIBUTES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_tributes_repository.h" +#include "common/repositories/base/base_tributes_repository.h" + +#include "common/database.h" +#include "common/strings.h" class TributesRepository: public BaseTributesRepository { public: @@ -46,5 +46,3 @@ class TributesRepository: public BaseTributesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_TRIBUTES_REPOSITORY_H diff --git a/common/repositories/variables_repository.h b/common/repositories/variables_repository.h index 216e234b31..bb66dc385e 100644 --- a/common/repositories/variables_repository.h +++ b/common/repositories/variables_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_VARIABLES_REPOSITORY_H -#define EQEMU_VARIABLES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_variables_repository.h" +#include "common/repositories/base/base_variables_repository.h" + +#include "common/database.h" +#include "common/strings.h" class VariablesRepository: public BaseVariablesRepository { public: @@ -44,5 +44,3 @@ class VariablesRepository: public BaseVariablesRepository { // Custom extended repository methods here }; - -#endif //EQEMU_VARIABLES_REPOSITORY_H diff --git a/common/repositories/veteran_reward_templates_repository.h b/common/repositories/veteran_reward_templates_repository.h index 24dfb94f38..0cb39af840 100644 --- a/common/repositories/veteran_reward_templates_repository.h +++ b/common/repositories/veteran_reward_templates_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_VETERAN_REWARD_TEMPLATES_REPOSITORY_H -#define EQEMU_VETERAN_REWARD_TEMPLATES_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_veteran_reward_templates_repository.h" +#include "common/repositories/base/base_veteran_reward_templates_repository.h" + +#include "common/database.h" +#include "common/strings.h" class VeteranRewardTemplatesRepository: public BaseVeteranRewardTemplatesRepository { public: @@ -46,5 +46,3 @@ class VeteranRewardTemplatesRepository: public BaseVeteranRewardTemplatesReposit // Custom extended repository methods here }; - -#endif //EQEMU_VETERAN_REWARD_TEMPLATES_REPOSITORY_H diff --git a/common/repositories/zone_flags_repository.h b/common/repositories/zone_flags_repository.h index a8c40a8910..339d1d48d7 100644 --- a/common/repositories/zone_flags_repository.h +++ b/common/repositories/zone_flags_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ZONE_FLAGS_REPOSITORY_H -#define EQEMU_ZONE_FLAGS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_zone_flags_repository.h" +#include "common/repositories/base/base_zone_flags_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ZoneFlagsRepository: public BaseZoneFlagsRepository { public: @@ -46,5 +46,3 @@ class ZoneFlagsRepository: public BaseZoneFlagsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_ZONE_FLAGS_REPOSITORY_H diff --git a/common/repositories/zone_points_repository.h b/common/repositories/zone_points_repository.h index bcf37abe92..6d410ab285 100644 --- a/common/repositories/zone_points_repository.h +++ b/common/repositories/zone_points_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ZONE_POINTS_REPOSITORY_H -#define EQEMU_ZONE_POINTS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_zone_points_repository.h" +#include "common/repositories/base/base_zone_points_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ZonePointsRepository: public BaseZonePointsRepository { public: @@ -46,5 +46,3 @@ class ZonePointsRepository: public BaseZonePointsRepository { // Custom extended repository methods here }; - -#endif //EQEMU_ZONE_POINTS_REPOSITORY_H diff --git a/common/repositories/zone_repository.h b/common/repositories/zone_repository.h index 8b005d8652..f4902f19f6 100644 --- a/common/repositories/zone_repository.h +++ b/common/repositories/zone_repository.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_ZONE_REPOSITORY_H -#define EQEMU_ZONE_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_zone_repository.h" +#include "common/repositories/base/base_zone_repository.h" + +#include "common/database.h" +#include "common/strings.h" class ZoneRepository: public BaseZoneRepository { public: @@ -59,5 +59,3 @@ class ZoneRepository: public BaseZoneRepository { return results.Success(); } }; - -#endif //EQEMU_ZONE_REPOSITORY_H diff --git a/common/repositories/zone_state_spawns_repository.h b/common/repositories/zone_state_spawns_repository.h index adb48edec1..8a3bbbdbab 100644 --- a/common/repositories/zone_state_spawns_repository.h +++ b/common/repositories/zone_state_spawns_repository.h @@ -1,9 +1,10 @@ -#ifndef EQEMU_ZONE_STATE_SPAWNS_REPOSITORY_H -#define EQEMU_ZONE_STATE_SPAWNS_REPOSITORY_H +#pragma once -#include "../database.h" -#include "../strings.h" -#include "base/base_zone_state_spawns_repository.h" +#include "common/repositories/base/base_zone_state_spawns_repository.h" + +#include "common/database.h" +#include "common/strings.h" +#include "fmt/ranges.h" class ZoneStateSpawnsRepository : public BaseZoneStateSpawnsRepository { public: @@ -78,5 +79,3 @@ class ZoneStateSpawnsRepository : public BaseZoneStateSpawnsRepository { } }; - -#endif //EQEMU_ZONE_STATE_SPAWNS_REPOSITORY_H From 227553337e552b919767e369129eb69ae48aa95a Mon Sep 17 00:00:00 2001 From: brainiac Date: Wed, 17 Dec 2025 09:33:40 -0800 Subject: [PATCH 065/194] normalize includes: eqlaunch --- eqlaunch/CMakeLists.txt | 1 + eqlaunch/eqlaunch.cpp | 23 ++++++++++++----------- eqlaunch/worldserver.cpp | 13 +++++++------ eqlaunch/worldserver.h | 13 ++++++------- eqlaunch/zone_launch.cpp | 9 +++++---- eqlaunch/zone_launch.h | 11 +++++------ 6 files changed, 36 insertions(+), 34 deletions(-) diff --git a/eqlaunch/CMakeLists.txt b/eqlaunch/CMakeLists.txt index 048335c733..b4b4f99753 100644 --- a/eqlaunch/CMakeLists.txt +++ b/eqlaunch/CMakeLists.txt @@ -16,6 +16,7 @@ add_executable(eqlaunch ${eqlaunch_sources} ${eqlaunch_headers}) install(TARGETS eqlaunch RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) target_link_libraries(eqlaunch common) +target_include_directories(eqlaunch PRIVATE ..) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set_property(TARGET eqlaunch PROPERTY FOLDER executables/tools) diff --git a/eqlaunch/eqlaunch.cpp b/eqlaunch/eqlaunch.cpp index edc50aea7b..864852c69f 100644 --- a/eqlaunch/eqlaunch.cpp +++ b/eqlaunch/eqlaunch.cpp @@ -16,17 +16,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/proc_launcher.h" -#include "../common/eqemu_config.h" -#include "../common/servertalk.h" -#include "../common/path_manager.h" -#include "../common/platform.h" -#include "../common/crash.h" -#include "../common/unix.h" -#include "worldserver.h" -#include "zone_launch.h" +#include "common/crash.h" +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/path_manager.h" +#include "common/platform.h" +#include "common/proc_launcher.h" +#include "common/servertalk.h" +#include "common/unix.h" +#include "eqlaunch/worldserver.h" +#include "eqlaunch/zone_launch.h" + #include #include #include diff --git a/eqlaunch/worldserver.cpp b/eqlaunch/worldserver.cpp index 98e34da811..ae365c924a 100644 --- a/eqlaunch/worldserver.cpp +++ b/eqlaunch/worldserver.cpp @@ -16,13 +16,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/servertalk.h" -#include "../common/eqemu_config.h" -#include "../common/strings.h" #include "worldserver.h" -#include "zone_launch.h" + +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/servertalk.h" +#include "common/strings.h" +#include "eqlaunch/zone_launch.h" WorldServer::WorldServer(std::map &zones, const char *name, const EQEmuConfig *config) : m_name(name), diff --git a/eqlaunch/worldserver.h b/eqlaunch/worldserver.h index ac04dd6239..f0e20f2e5b 100644 --- a/eqlaunch/worldserver.h +++ b/eqlaunch/worldserver.h @@ -15,14 +15,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef WORLDSERVER_H -#define WORLDSERVER_H -#include "../common/net/servertalk_client_connection.h" +#pragma once + +#include "common/net/servertalk_client_connection.h" + +#include #include -#include #include -#include +#include class ZoneLaunch; class EQEmuConfig; @@ -44,5 +45,3 @@ class WorldServer { const EQEmuConfig *const m_config; std::map &m_zones; }; -#endif - diff --git a/eqlaunch/zone_launch.cpp b/eqlaunch/zone_launch.cpp index 15943f3150..84f7ac5634 100644 --- a/eqlaunch/zone_launch.cpp +++ b/eqlaunch/zone_launch.cpp @@ -16,11 +16,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/eqemu_config.h" #include "zone_launch.h" -#include "worldserver.h" + +#include "common/eqemu_config.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "eqlaunch/worldserver.h" //static const uint32 ZONE_RESTART_DELAY = 10000; //static const uint32 ZONE_TERMINATE_WAIT = 10000; diff --git a/eqlaunch/zone_launch.h b/eqlaunch/zone_launch.h index d52a93bb2c..f48d707541 100644 --- a/eqlaunch/zone_launch.h +++ b/eqlaunch/zone_launch.h @@ -15,11 +15,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef ZONELAUNCH_H_ -#define ZONELAUNCH_H_ -#include "../common/proc_launcher.h" -#include "../common/timer.h" +#pragma once + +#include "common/proc_launcher.h" +#include "common/timer.h" + #include class WorldServer; @@ -71,5 +72,3 @@ class ZoneLaunch : protected ProcLauncher::EventHandler { static int s_running; static Timer s_startTimer; }; - -#endif /*ZONELAUNCH_H_*/ From 91defcad99cfdecedba69b51f89a01e2499ec41f Mon Sep 17 00:00:00 2001 From: brainiac Date: Wed, 17 Dec 2025 09:34:27 -0800 Subject: [PATCH 066/194] normalize includes: queryserv --- queryserv/CMakeLists.txt | 1 + queryserv/database.cpp | 11 +++++---- queryserv/database.h | 25 +++++++++----------- queryserv/lfguild.cpp | 9 +++---- queryserv/lfguild.h | 10 ++++---- queryserv/queryserv.cpp | 38 ++++++++++++++++-------------- queryserv/queryservconfig.cpp | 3 ++- queryserv/queryservconfig.h | 8 ++----- queryserv/worldserver.cpp | 44 +++++++++++++++++------------------ queryserv/worldserver.h | 11 ++++----- queryserv/zonelist.cpp | 5 ++-- queryserv/zonelist.h | 14 +++++------ queryserv/zoneserver.cpp | 11 +++++---- queryserv/zoneserver.h | 19 +++++++-------- 14 files changed, 101 insertions(+), 108 deletions(-) diff --git a/queryserv/CMakeLists.txt b/queryserv/CMakeLists.txt index 968a3f6f06..641d3385e7 100644 --- a/queryserv/CMakeLists.txt +++ b/queryserv/CMakeLists.txt @@ -26,6 +26,7 @@ install(TARGETS queryserv RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) add_definitions(-DQSERV) target_link_libraries(queryserv common) +target_include_directories(queryserv PRIVATE ..) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set_property(TARGET queryserv PROPERTY FOLDER executables/servers) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index db6be3ce2a..5af3e3edc3 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -1,9 +1,12 @@ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" + +#include "database.h" + +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/strings.h" + #include #include -#include "database.h" -#include "../common/strings.h" // this function does not delete the ServerPacket, so it must be handled at call site void QSDatabase::GeneralQueryReceive(ServerPacket *pack) diff --git a/queryserv/database.h b/queryserv/database.h index 69b0b8e36c..083b232f71 100644 --- a/queryserv/database.h +++ b/queryserv/database.h @@ -1,23 +1,20 @@ -#ifndef CHATSERVER_DATABASE_H -#define CHATSERVER_DATABASE_H +#pragma once -#define AUTHENTICATION_TIMEOUT 60 -#define INVALID_ID 0xFFFFFFFF +#include "common/database.h" +#include "common/eqemu_logsys.h" +#include "common/global_define.h" +#include "common/linked_list.h" +#include "common/servertalk.h" +#include "common/types.h" -#include "../common/eqemu_logsys.h" -#include "../common/global_define.h" -#include "../common/types.h" -#include "../common/database.h" -#include "../common/linked_list.h" -#include "../common/servertalk.h" +#include #include #include -#include + +#define AUTHENTICATION_TIMEOUT 60 +#define INVALID_ID 0xFFFFFFFF class QSDatabase : public Database { public: void GeneralQueryReceive(ServerPacket *pack); }; - -#endif - diff --git a/queryserv/lfguild.cpp b/queryserv/lfguild.cpp index 688102ed1a..07b12c4f48 100644 --- a/queryserv/lfguild.cpp +++ b/queryserv/lfguild.cpp @@ -1,8 +1,9 @@ #include "lfguild.h" -#include "database.h" -#include "worldserver.h" -#include "../common/strings.h" -#include "../common/rulesys.h" + +#include "common/rulesys.h" +#include "common/strings.h" +#include "queryserv/database.h" +#include "queryserv/worldserver.h" extern WorldServer *worldserver; extern QSDatabase qs_database; diff --git a/queryserv/lfguild.h b/queryserv/lfguild.h index 1c0cb1cdd6..0f655e766b 100644 --- a/queryserv/lfguild.h +++ b/queryserv/lfguild.h @@ -1,14 +1,13 @@ -#ifndef LFGUILD_H -#define LFGUILD_H +#pragma once + +#include "common/servertalk.h" +#include "common/types.h" #include #include -#include "../common/types.h" -#include "../common/servertalk.h" class PlayerLookingForGuild { - public: PlayerLookingForGuild(char *Name, char *Comments, uint32 Level, uint32 Class, uint32 AACount, uint32 Timezone, uint32 TimePosted); @@ -60,4 +59,3 @@ class LFGuildManager std::list Players; std::list Guilds; }; -#endif /* LFGUILD_H */ diff --git a/queryserv/queryserv.cpp b/queryserv/queryserv.cpp index b6bf21a712..b5dd1b5f9e 100644 --- a/queryserv/queryserv.cpp +++ b/queryserv/queryserv.cpp @@ -1,25 +1,27 @@ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/opcodemgr.h" -#include "../common/rulesys.h" -#include "../common/platform.h" -#include "../common/crash.h" -#include "../common/strings.h" -#include "../common/event/event_loop.h" -#include "../common/timer.h" -#include "database.h" + +#include "common/crash.h" +#include "common/eqemu_logsys.h" +#include "common/event/event_loop.h" +#include "common/events/player_event_logs.h" +#include "common/global_define.h" +#include "common/net/console_server.h" +#include "common/net/servertalk_server.h" +#include "common/opcodemgr.h" +#include "common/platform.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "common/timer.h" +#include "common/zone_store.h" +#include "queryserv/database.h" +#include "queryserv/lfguild.h" +#include "queryserv/worldserver.h" +#include "queryserv/zonelist.h" +#include "queryserv/zoneserver.h" #include "queryservconfig.h" -#include "lfguild.h" -#include "worldserver.h" -#include "../common/zone_store.h" -#include "../common/events/player_event_logs.h" + #include #include #include -#include "../common/net/servertalk_server.h" -#include "../common/net/console_server.h" -#include "../queryserv/zonelist.h" -#include "../queryserv/zoneserver.h" volatile bool RunLoops = true; diff --git a/queryserv/queryservconfig.cpp b/queryserv/queryservconfig.cpp index 716ae0618f..2383b76f61 100644 --- a/queryserv/queryservconfig.cpp +++ b/queryserv/queryservconfig.cpp @@ -17,9 +17,10 @@ */ -#include "../common/global_define.h" #include "queryservconfig.h" +#include "common/global_define.h" + queryservconfig *queryservconfig::_chat_config = nullptr; std::string queryservconfig::GetByName(const std::string &var_name) const { diff --git a/queryserv/queryservconfig.h b/queryserv/queryservconfig.h index 5c9d63bd60..b7afa7a6d8 100644 --- a/queryserv/queryservconfig.h +++ b/queryserv/queryservconfig.h @@ -17,10 +17,9 @@ */ -#ifndef __queryservconfig_H -#define __queryservconfig_H +#pragma once -#include "../common/eqemu_config.h" +#include "common/eqemu_config.h" class queryservconfig : public EQEmuConfig { public: @@ -50,6 +49,3 @@ class queryservconfig : public EQEmuConfig { } }; - -#endif - diff --git a/queryserv/worldserver.cpp b/queryserv/worldserver.cpp index 051a8f0099..78d55a1777 100644 --- a/queryserv/worldserver.cpp +++ b/queryserv/worldserver.cpp @@ -1,27 +1,25 @@ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/md5.h" -#include "../common/packet_dump.h" -#include "../common/packet_functions.h" -#include "../common/servertalk.h" -#include "../common/net/packet.h" - -#include "database.h" -#include "lfguild.h" -#include "queryservconfig.h" #include "worldserver.h" -#include "../common/events/player_events.h" -#include "../common/events/player_event_logs.h" -#include "../common/server_reload_types.h" -#include -#include -#include -#include -#include -#include -#include - -#include "zonelist.h" + +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/events/player_events.h" +#include "common/global_define.h" +#include "common/md5.h" +#include "common/net/packet.h" +#include "common/packet_dump.h" +#include "common/packet_functions.h" +#include "common/server_reload_types.h" +#include "common/servertalk.h" +#include "queryserv/database.h" +#include "queryserv/lfguild.h" +#include "queryserv/queryservconfig.h" +#include "queryserv/zonelist.h" + +#include +#include +#include +#include +#include extern WorldServer worldserver; extern const queryservconfig *Config; diff --git a/queryserv/worldserver.h b/queryserv/worldserver.h index 5774f5ca89..54ad69bee3 100644 --- a/queryserv/worldserver.h +++ b/queryserv/worldserver.h @@ -15,12 +15,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef WORLDSERVER_H -#define WORLDSERVER_H + +#pragma once + +#include "common/eq_packet_structs.h" +#include "common/net/servertalk_client_connection.h" #include -#include "../common/eq_packet_structs.h" -#include "../common/net/servertalk_client_connection.h" class WorldServer { public: @@ -38,5 +39,3 @@ class WorldServer { std::unique_ptr m_connection; }; -#endif - diff --git a/queryserv/zonelist.cpp b/queryserv/zonelist.cpp index 16ad65371e..2b204c999f 100644 --- a/queryserv/zonelist.cpp +++ b/queryserv/zonelist.cpp @@ -1,6 +1,7 @@ #include "zonelist.h" -#include "zoneserver.h" -#include "../common/strings.h" + +#include "queryserv/zoneserver.h" +#include "common/strings.h" void ZSList::Add(ZoneServer* zoneserver) { zone_server_list.emplace_back(std::unique_ptr(zoneserver)); diff --git a/queryserv/zonelist.h b/queryserv/zonelist.h index 5bcf1b29bc..dc8dc4f326 100644 --- a/queryserv/zonelist.h +++ b/queryserv/zonelist.h @@ -1,12 +1,12 @@ -#ifndef ZONELIST_H_ -#define ZONELIST_H_ +#pragma once -#include "../common/types.h" +#include "common/types.h" +#include "queryserv/zoneserver.h" + +#include +#include #include #include -#include -#include -#include "zoneserver.h" class WorldTCPConnection; @@ -26,5 +26,3 @@ class ZSList { private: std::list> zone_server_list; }; - -#endif /*ZONELIST_H_*/ diff --git a/queryserv/zoneserver.cpp b/queryserv/zoneserver.cpp index 2aa9b9b9d3..ca482c7838 100644 --- a/queryserv/zoneserver.cpp +++ b/queryserv/zoneserver.cpp @@ -1,9 +1,10 @@ #include "zoneserver.h" -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/repositories/player_event_logs_repository.h" -#include "../common/events/player_event_logs.h" -#include "../common/discord/discord_manager.h" + +#include "common/discord/discord_manager.h" +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/global_define.h" +#include "common/repositories/player_event_logs_repository.h" ZoneServer::ZoneServer( std::shared_ptr in_connection, diff --git a/queryserv/zoneserver.h b/queryserv/zoneserver.h index f4a4b08e63..374051c4bc 100644 --- a/queryserv/zoneserver.h +++ b/queryserv/zoneserver.h @@ -1,12 +1,12 @@ -#ifndef ZONESERVER_H -#define ZONESERVER_H +#pragma once + +#include "common/emu_constants.h" +#include "common/event/timer.h" +#include "common/net/servertalk_server.h" +#include "common/timer.h" +#include "world/console.h" +#include "world/world_tcp_connection.h" -#include "../world/world_tcp_connection.h" -#include "../common/net/servertalk_server.h" -#include "../common/event/timer.h" -#include "../common/timer.h" -#include "../common/emu_constants.h" -#include "../world/console.h" #include class Client; @@ -28,6 +28,3 @@ class ZoneServer : public WorldTCPConnection { bool m_is_zone_connected = false; EQ::Net::ConsoleServer *m_console; }; - -#endif - From 2c6d8795f90a84a53bb6c7777c4259369ee76d0f Mon Sep 17 00:00:00 2001 From: brainiac Date: Wed, 17 Dec 2025 09:35:43 -0800 Subject: [PATCH 067/194] normalize includes: shared_memory --- shared_memory/CMakeLists.txt | 1 + shared_memory/items.cpp | 13 ++++++------ shared_memory/items.h | 8 +++----- shared_memory/main.cpp | 40 ++++++++++++++++-------------------- shared_memory/spells.cpp | 13 ++++++------ shared_memory/spells.h | 8 +++----- 6 files changed, 39 insertions(+), 44 deletions(-) diff --git a/shared_memory/CMakeLists.txt b/shared_memory/CMakeLists.txt index 4ef414693f..6284291d06 100644 --- a/shared_memory/CMakeLists.txt +++ b/shared_memory/CMakeLists.txt @@ -16,6 +16,7 @@ add_executable(shared_memory ${shared_memory_sources} ${shared_memory_headers}) install(TARGETS shared_memory RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) target_link_libraries(shared_memory common) +target_include_directories(shared_memory PRIVATE ..) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set_property(TARGET shared_memory PROPERTY FOLDER executables/servers) diff --git a/shared_memory/items.cpp b/shared_memory/items.cpp index b1052730c9..ebd3bc8dc1 100644 --- a/shared_memory/items.cpp +++ b/shared_memory/items.cpp @@ -17,12 +17,13 @@ */ #include "items.h" -#include "../common/global_define.h" -#include "../common/shareddb.h" -#include "../common/ipc_mutex.h" -#include "../common/memory_mapped_file.h" -#include "../common/eqemu_exception.h" -#include "../common/item_data.h" + +#include "common/eqemu_exception.h" +#include "common/global_define.h" +#include "common/ipc_mutex.h" +#include "common/item_data.h" +#include "common/memory_mapped_file.h" +#include "common/shareddb.h" void LoadItems(SharedDatabase *database, const std::string &prefix) { EQ::IPCMutex mutex("items"); diff --git a/shared_memory/items.h b/shared_memory/items.h index 47dcbaac95..4bc891d90c 100644 --- a/shared_memory/items.h +++ b/shared_memory/items.h @@ -16,13 +16,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __EQEMU_SHARED_MEMORY_ITEMS_H -#define __EQEMU_SHARED_MEMORY_ITEMS_H +#pragma once + +#include "common/eqemu_config.h" #include -#include "../common/eqemu_config.h" class SharedDatabase; void LoadItems(SharedDatabase *database, const std::string &prefix); - -#endif diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index d29bd31e46..b3f1d83af0 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -16,33 +16,29 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include - -#include "../common/eqemu_logsys.h" -#include "../common/global_define.h" -#include "../common/shareddb.h" -#include "../common/eqemu_config.h" -#include "../common/platform.h" -#include "../common/crash.h" -#include "../common/rulesys.h" -#include "../common/eqemu_exception.h" -#include "../common/strings.h" -#include "items.h" -#include "spells.h" -#include "../common/content/world_content_service.h" -#include "../common/zone_store.h" -#include "../common/path_manager.h" -#include "../common/events/player_event_logs.h" -#include "../common/evolving_items.h" - +#include "shared_memory/items.h" +#include "shared_memory/spells.h" +#include "common/content/world_content_service.h" +#include "common/crash.h" +#include "common/eqemu_config.h" +#include "common/eqemu_exception.h" +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/evolving_items.h" +#include "common/global_define.h" +#include "common/path_manager.h" +#include "common/platform.h" +#include "common/rulesys.h" +#include "common/shareddb.h" +#include "common/strings.h" +#include "common/zone_store.h" + +#include #ifdef _WINDOWS #include #else - #include - #endif - #include inline bool MakeDirectory(const std::string &directory_name) diff --git a/shared_memory/spells.cpp b/shared_memory/spells.cpp index 0faf5d7644..e5db69cdcd 100644 --- a/shared_memory/spells.cpp +++ b/shared_memory/spells.cpp @@ -17,12 +17,13 @@ */ #include "spells.h" -#include "../common/global_define.h" -#include "../common/shareddb.h" -#include "../common/ipc_mutex.h" -#include "../common/memory_mapped_file.h" -#include "../common/eqemu_exception.h" -#include "../common/spdat.h" + +#include "common/eqemu_exception.h" +#include "common/global_define.h" +#include "common/ipc_mutex.h" +#include "common/memory_mapped_file.h" +#include "common/shareddb.h" +#include "common/spdat.h" void LoadSpells(SharedDatabase *database, const std::string &prefix) { EQ::IPCMutex mutex("spells"); diff --git a/shared_memory/spells.h b/shared_memory/spells.h index bdda1eac40..f6fd196537 100644 --- a/shared_memory/spells.h +++ b/shared_memory/spells.h @@ -16,13 +16,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __EQEMU_SHARED_MEMORY_SPELLS_H -#define __EQEMU_SHARED_MEMORY_SPELLS_H +#pragma once + +#include "common/eqemu_config.h" #include -#include "../common/eqemu_config.h" class SharedDatabase; void LoadSpells(SharedDatabase *database, const std::string &prefix); - -#endif From 0b8369c858229289b77811fade0b9a34fc6a947b Mon Sep 17 00:00:00 2001 From: brainiac Date: Wed, 17 Dec 2025 09:36:01 -0800 Subject: [PATCH 068/194] normalize includes: tests --- tests/CMakeLists.txt | 1 + tests/atobool_test.h | 7 ++----- tests/cppunit/CMakeLists.txt | 1 + tests/data_verification_test.h | 7 ++----- tests/fixed_memory_test.h | 9 +++------ tests/fixed_memory_variable_test.h | 7 ++----- tests/hextoi_32_64_test.h | 7 ++----- tests/ipc_mutex_test.h | 9 +++------ tests/main.cpp | 25 +++++++++++++------------ tests/memory_mapped_file_test.h | 7 ++----- tests/skills_util_test.h | 7 ++----- tests/string_util_test.h | 7 ++----- tests/task_state_test.h | 6 +++--- 13 files changed, 38 insertions(+), 62 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b81c6e0b22..346128d607 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -22,6 +22,7 @@ set(tests_headers add_executable(tests ${tests_sources} ${tests_headers}) target_link_libraries(tests common cppunit) +target_include_directories(tests PRIVATE ..) install(TARGETS tests RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tests/atobool_test.h b/tests/atobool_test.h index 21ef277d15..19da10d3ec 100644 --- a/tests/atobool_test.h +++ b/tests/atobool_test.h @@ -16,11 +16,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __EQEMU_TESTS_ATOBOOL_H -#define __EQEMU_TESTS_ATOBOOL_H +#pragma once +#include "common/strings.h" #include "cppunit/cpptest.h" -#include "../common/strings.h" class atoboolTest : public Test::Suite { typedef void(atoboolTest::*TestFunction)(void); @@ -99,5 +98,3 @@ class atoboolTest : public Test::Suite { } }; - -#endif diff --git a/tests/cppunit/CMakeLists.txt b/tests/cppunit/CMakeLists.txt index a6f82df878..4b4763d958 100644 --- a/tests/cppunit/CMakeLists.txt +++ b/tests/cppunit/CMakeLists.txt @@ -36,3 +36,4 @@ if(UNIX) endif() set(LIBRARY_OUTPUT_PATH ../../bin) +set_property(TARGET cppunit PROPERTY FOLDER contrib) diff --git a/tests/data_verification_test.h b/tests/data_verification_test.h index 5053b922a7..e0af47bfee 100644 --- a/tests/data_verification_test.h +++ b/tests/data_verification_test.h @@ -16,11 +16,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __EQEMU_TESTS_DATA_VERIFICATION_H -#define __EQEMU_TESTS_DATA_VERIFICATION_H +#pragma once +#include "common/data_verification.h" #include "cppunit/cpptest.h" -#include "../common/data_verification.h" class DataVerificationTest : public Test::Suite { typedef void(DataVerificationTest::*TestFunction)(void); @@ -104,5 +103,3 @@ class DataVerificationTest : public Test::Suite { TEST_ASSERT(!EQ::ValueWithin(value_i, 600, 900)); } }; - -#endif diff --git a/tests/fixed_memory_test.h b/tests/fixed_memory_test.h index faddc963f4..c2059ab3b9 100644 --- a/tests/fixed_memory_test.h +++ b/tests/fixed_memory_test.h @@ -16,12 +16,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __EQEMU_TESTS_FIXED_MEMORY_H -#define __EQEMU_TESTS_FIXED_MEMORY_H +#pragma once +#include "common/fixed_memory_hash_set.h" +#include "common/item_instance.h" #include "cppunit/cpptest.h" -#include "../common/fixed_memory_hash_set.h" -#include "../common/item_instance.h" class FixedMemoryHashTest : public Test::Suite { typedef void(FixedMemoryHashTest::*TestFunction)(void); @@ -233,5 +232,3 @@ class FixedMemoryHashTest : public Test::Suite { uint8 *data_; size_t size_; }; - -#endif diff --git a/tests/fixed_memory_variable_test.h b/tests/fixed_memory_variable_test.h index 4bb89e1b65..ea79487102 100644 --- a/tests/fixed_memory_variable_test.h +++ b/tests/fixed_memory_variable_test.h @@ -16,11 +16,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __EQEMU_TESTS_FIXED_MEMORY_VARIABLE_H -#define __EQEMU_TESTS_FIXED_MEMORY_VARIABLE_H +#pragma once +#include "common/fixed_memory_variable_hash_set.h" #include "cppunit/cpptest.h" -#include "../common/fixed_memory_variable_hash_set.h" struct test_struct { char name[512]; @@ -129,5 +128,3 @@ class FixedMemoryVariableHashTest : public Test::Suite { uint8 *data_; uint32 size_; }; - -#endif diff --git a/tests/hextoi_32_64_test.h b/tests/hextoi_32_64_test.h index cd7bb83bd1..119d66dc80 100644 --- a/tests/hextoi_32_64_test.h +++ b/tests/hextoi_32_64_test.h @@ -16,11 +16,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __EQEMU_TESTS_HEXTOI_32_64_H -#define __EQEMU_TESTS_HEXTOI_32_64_H +#pragma once +#include "common/strings.h" #include "cppunit/cpptest.h" -#include "../common/strings.h" class hextoi_32_64_Test : public Test::Suite { typedef void(hextoi_32_64_Test::*TestFunction)(void); @@ -209,5 +208,3 @@ class hextoi_32_64_Test : public Test::Suite { } }; - -#endif diff --git a/tests/ipc_mutex_test.h b/tests/ipc_mutex_test.h index c4323d4256..da2a930162 100644 --- a/tests/ipc_mutex_test.h +++ b/tests/ipc_mutex_test.h @@ -16,12 +16,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __EQEMU_TESTS_IPC_MUTEX_H -#define __EQEMU_TESTS_IPC_MUTEX_H +#pragma once +#include "common/eqemu_config.h" +#include "common/ipc_mutex.h" #include "cppunit/cpptest.h" -#include "../common/ipc_mutex.h" -#include "../common/eqemu_config.h" extern const EQEmuConfig *Config; @@ -63,5 +62,3 @@ class IPCMutexTest : public Test::Suite { TEST_ASSERT(!mutex.Unlock()); } }; - -#endif diff --git a/tests/main.cpp b/tests/main.cpp index 9c9af40c9b..cfec4abcd6 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -16,22 +16,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "tests/atobool_test.h" +#include "tests/data_verification_test.h" +#include "tests/fixed_memory_test.h" +#include "tests/fixed_memory_variable_test.h" +#include "tests/hextoi_32_64_test.h" +#include "tests/ipc_mutex_test.h" +#include "tests/memory_mapped_file_test.h" +#include "tests/skills_util_test.h" +#include "tests/string_util_test.h" +#include "tests/task_state_test.h" + +#include "common/path_manager.h" +#include "common/platform.h" #include #include #include -#include "../common/platform.h" -#include "../common/path_manager.h" -#include "memory_mapped_file_test.h" -#include "ipc_mutex_test.h" -#include "fixed_memory_test.h" -#include "fixed_memory_variable_test.h" -#include "atobool_test.h" -#include "hextoi_32_64_test.h" -#include "string_util_test.h" -#include "data_verification_test.h" -#include "skills_util_test.h" -#include "task_state_test.h" const EQEmuConfig *Config; diff --git a/tests/memory_mapped_file_test.h b/tests/memory_mapped_file_test.h index b23f6568df..75db90b53b 100644 --- a/tests/memory_mapped_file_test.h +++ b/tests/memory_mapped_file_test.h @@ -16,11 +16,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __EQEMU_TESTS_MEMORY_MAPPED_FILE_H -#define __EQEMU_TESTS_MEMORY_MAPPED_FILE_H +#pragma once +#include "common/memory_mapped_file.h" #include "cppunit/cpptest.h" -#include "../common/memory_mapped_file.h" class MemoryMappedFileTest : public Test::Suite { typedef void(MemoryMappedFileTest::*TestFunction)(void); @@ -56,5 +55,3 @@ class MemoryMappedFileTest : public Test::Suite { TEST_ASSERT(val == 562); } }; - -#endif diff --git a/tests/skills_util_test.h b/tests/skills_util_test.h index 77616ea145..da8f78181e 100644 --- a/tests/skills_util_test.h +++ b/tests/skills_util_test.h @@ -16,11 +16,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __EQEMU_TESTS_SKILLS_UTILS_H -#define __EQEMU_TESTS_SKILLS_UTILS_H +#pragma once +#include "common/skills.h" #include "cppunit/cpptest.h" -#include "../common/skills.h" class SkillsUtilsTest: public Test::Suite { typedef void(SkillsUtilsTest::*TestFunction)(void); @@ -44,5 +43,3 @@ class SkillsUtilsTest: public Test::Suite { TEST_ASSERT(!EQ::skills::IsSpecializedSkill(EQ::skills::SkillConjuration)) } }; - -#endif diff --git a/tests/string_util_test.h b/tests/string_util_test.h index 37bd539f71..1bcdb2fa9e 100644 --- a/tests/string_util_test.h +++ b/tests/string_util_test.h @@ -16,11 +16,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __EQEMU_TESTS_STRING_UTIL_H -#define __EQEMU_TESTS_STRING_UTIL_H +#pragma once +#include "common/strings.h" #include "cppunit/cpptest.h" -#include "../common/strings.h" class StringUtilTest : public Test::Suite { typedef void(StringUtilTest::*TestFunction)(void); @@ -135,5 +134,3 @@ class StringUtilTest : public Test::Suite { TEST_ASSERT_EQUALS(Strings::IsNumber("18446744073709551616.0f"), false); // 64 } }; - -#endif diff --git a/tests/task_state_test.h b/tests/task_state_test.h index 729c02c04a..a271ca3f83 100644 --- a/tests/task_state_test.h +++ b/tests/task_state_test.h @@ -1,9 +1,9 @@ #pragma once +#include "common/eqemu_logsys.h" +#include "common/shared_tasks.h" +#include "common/tasks.h" #include "cppunit/cpptest.h" -#include "../common/eqemu_logsys.h" -#include "../common/tasks.h" -#include "../common/shared_tasks.h" class TaskStateTest: public Test::Suite { From 6fd4a7d620782752c72552ccd5f3b91ffdcad2f8 Mon Sep 17 00:00:00 2001 From: brainiac Date: Wed, 17 Dec 2025 09:36:22 -0800 Subject: [PATCH 069/194] normalize includes: common/repositories --- utils/scripts/generators/repository-generator.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/generators/repository-generator.pl b/utils/scripts/generators/repository-generator.pl index 3def505063..104f307615 100644 --- a/utils/scripts/generators/repository-generator.pl +++ b/utils/scripts/generators/repository-generator.pl @@ -442,7 +442,7 @@ { ar(\n" . $cereal_columns . "\n\t\t\t);\n\t\t}"; - $additional_includes .= "#include "; + $additional_includes .= "#include \"cereal/cereal.hpp\""; } chomp($column_names_quoted); From 260042a429a8bbf00ca61be769185ec20018ed16 Mon Sep 17 00:00:00 2001 From: brainiac Date: Wed, 17 Dec 2025 17:58:37 -0800 Subject: [PATCH 070/194] normalize includes: common --- common/patches/uf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index d2ba9c20c6..f126870681 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2714,7 +2714,7 @@ namespace UF buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); dest->FastQueuePacket(&outapp, ack_req); delete in; From ab1edbf537c03c6a6af417bbfe1fbc61d09c94af Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 00:22:54 -0800 Subject: [PATCH 071/194] Remove unused and unmaintained sources --- common/CMakeLists.txt | 4 +- common/SocketLib/Base64.cpp | 266 ----- common/SocketLib/Base64.h | 67 -- common/SocketLib/File.cpp | 126 --- common/SocketLib/File.h | 76 -- common/SocketLib/HTTPSocket.cpp | 366 ------- common/SocketLib/HTTPSocket.h | 137 --- common/SocketLib/HttpdCookies.cpp | 250 ----- common/SocketLib/HttpdCookies.h | 91 -- common/SocketLib/HttpdForm.cpp | 621 ------------ common/SocketLib/HttpdForm.h | 115 --- common/SocketLib/HttpdSocket.cpp | 352 ------- common/SocketLib/HttpdSocket.h | 99 -- common/SocketLib/IFile.h | 65 -- common/SocketLib/MemFile.cpp | 212 ---- common/SocketLib/MemFile.h | 93 -- common/SocketLib/Mime.cpp | 92 -- common/SocketLib/Mime.h | 55 - common/SocketLib/Parse.cpp | 327 ------ common/SocketLib/Parse.h | 95 -- common/SocketLib/README.eqemu | 5 - common/SocketLib/README.macosx | 5 - common/SocketLib/Utility.cpp | 167 ---- common/SocketLib/Utility.h | 70 -- common/SocketLib/gpl.txt | 340 ------- common/SocketLib/socket_include.cpp | 87 -- common/SocketLib/socket_include.h | 218 ---- common/eq_stream.cpp | 1440 --------------------------- common/eq_stream.h | 314 ------ common/eq_stream_factory.cpp | 298 ------ common/eq_stream_factory.h | 57 -- common/eq_stream_type.h | 12 - common/guilds.cpp | 28 - common/tcp_connection.cpp | 942 ------------------ common/tcp_server.cpp | 231 ----- world/eqw.cpp | 375 ------- world/eqw.h | 93 -- world/eqw_http_handler.cpp | 335 ------- world/eqw_parser.cpp | 348 ------- world/http_request.cpp | 80 -- world/http_request.h | 58 -- 41 files changed, 1 insertion(+), 9011 deletions(-) delete mode 100644 common/SocketLib/Base64.cpp delete mode 100644 common/SocketLib/Base64.h delete mode 100644 common/SocketLib/File.cpp delete mode 100644 common/SocketLib/File.h delete mode 100644 common/SocketLib/HTTPSocket.cpp delete mode 100644 common/SocketLib/HTTPSocket.h delete mode 100644 common/SocketLib/HttpdCookies.cpp delete mode 100644 common/SocketLib/HttpdCookies.h delete mode 100644 common/SocketLib/HttpdForm.cpp delete mode 100644 common/SocketLib/HttpdForm.h delete mode 100644 common/SocketLib/HttpdSocket.cpp delete mode 100644 common/SocketLib/HttpdSocket.h delete mode 100644 common/SocketLib/IFile.h delete mode 100644 common/SocketLib/MemFile.cpp delete mode 100644 common/SocketLib/MemFile.h delete mode 100644 common/SocketLib/Mime.cpp delete mode 100644 common/SocketLib/Mime.h delete mode 100644 common/SocketLib/Parse.cpp delete mode 100644 common/SocketLib/Parse.h delete mode 100644 common/SocketLib/README.eqemu delete mode 100644 common/SocketLib/README.macosx delete mode 100644 common/SocketLib/Utility.cpp delete mode 100644 common/SocketLib/Utility.h delete mode 100644 common/SocketLib/gpl.txt delete mode 100644 common/SocketLib/socket_include.cpp delete mode 100644 common/SocketLib/socket_include.h delete mode 100644 common/eq_stream.cpp delete mode 100644 common/eq_stream.h delete mode 100644 common/eq_stream_factory.cpp delete mode 100644 common/eq_stream_factory.h delete mode 100644 common/eq_stream_type.h delete mode 100644 common/guilds.cpp delete mode 100644 common/tcp_connection.cpp delete mode 100644 common/tcp_server.cpp delete mode 100644 world/eqw.cpp delete mode 100644 world/eqw.h delete mode 100644 world/eqw_http_handler.cpp delete mode 100644 world/eqw_parser.cpp delete mode 100644 world/http_request.cpp delete mode 100644 world/http_request.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index f250adbb17..d5fb90abbb 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -45,7 +45,6 @@ set(common_sources faction.cpp file.cpp guild_base.cpp - guilds.cpp inventory_profile.cpp inventory_slot.cpp ip_util.cpp @@ -759,7 +758,7 @@ if(CMAKE_COMPILER_IS_GNUCXX) mark_as_advanced(EQEMU_SFMT19937) endif() -include_directories(Patches SocketLib StackWalker) +include_directories(Patches StackWalker) add_library(common ${common_sources} ${common_headers} ${repositories}) @@ -807,7 +806,6 @@ endif() if(UNIX) target_link_libraries(common PUBLIC uuid) - set_source_files_properties("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) set_source_files_properties("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0) endif() diff --git a/common/SocketLib/Base64.cpp b/common/SocketLib/Base64.cpp deleted file mode 100644 index eb6a2fd0af..0000000000 --- a/common/SocketLib/Base64.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/** \file Base64.cpp - ** \date 2004-02-13 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 "Base64.h" - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -const char *Base64::bstr = - "ABCDEFGHIJKLMNOPQ" - "RSTUVWXYZabcdefgh" - "ijklmnopqrstuvwxy" - "z0123456789+/"; - -const char Base64::rstr[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, - 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0}; - - -void Base64::encode(FILE *fil, std::string& output, bool add_crlf) -{ - size_t remain; - size_t i = 0; - size_t o = 0; - char input[4]; - - output = ""; - remain = fread(input,1,3,fil); - while (remain > 0) - { - if (add_crlf && o && o % 76 == 0) - output += "\n"; - switch (remain) - { - case 1: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) ]; - output += "=="; - break; - case 2: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; - output += bstr[ ((input[i + 1] << 2) & 0x3c) ]; - output += "="; - break; - default: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; - output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ]; - output += bstr[ (input[i + 2] & 0x3f) ]; - } - o += 4; - // - remain = fread(input,1,3,fil); - } -} - - -void Base64::encode(const std::string& str_in, std::string& str_out, bool add_crlf) -{ - encode(str_in.c_str(), str_in.size(), str_out, add_crlf); -} - - -void Base64::encode(const char* input,size_t l,std::string& output, bool add_crlf) -{ - size_t i = 0; - size_t o = 0; - - output = ""; - while (i < l) - { - size_t remain = l - i; - if (add_crlf && o && o % 76 == 0) - output += "\n"; - switch (remain) - { - case 1: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) ]; - output += "=="; - break; - case 2: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; - output += bstr[ ((input[i + 1] << 2) & 0x3c) ]; - output += "="; - break; - default: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; - output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ]; - output += bstr[ (input[i + 2] & 0x3f) ]; - } - o += 4; - i += 3; - } -} - - -void Base64::encode(unsigned char* input,size_t l,std::string& output,bool add_crlf) -{ - size_t i = 0; - size_t o = 0; - - output = ""; - while (i < l) - { - size_t remain = l - i; - if (add_crlf && o && o % 76 == 0) - output += "\n"; - switch (remain) - { - case 1: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) ]; - output += "=="; - break; - case 2: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; - output += bstr[ ((input[i + 1] << 2) & 0x3c) ]; - output += "="; - break; - default: - output += bstr[ ((input[i] >> 2) & 0x3f) ]; - output += bstr[ ((input[i] << 4) & 0x30) + ((input[i + 1] >> 4) & 0x0f) ]; - output += bstr[ ((input[i + 1] << 2) & 0x3c) + ((input[i + 2] >> 6) & 0x03) ]; - output += bstr[ (input[i + 2] & 0x3f) ]; - } - o += 4; - i += 3; - } -} - - -void Base64::decode(const std::string& input,std::string& output) -{ - size_t i = 0; - size_t l = input.size(); - - output = ""; - while (i < l) - { - while (i < l && (input[i] == 13 || input[i] == 10)) - i++; - if (i < l) - { - char b1 = (char)((rstr[(int)input[i]] << 2 & 0xfc) + - (rstr[(int)input[i + 1]] >> 4 & 0x03)); - output += b1; - if (input[i + 2] != '=') - { - char b2 = (char)((rstr[(int)input[i + 1]] << 4 & 0xf0) + - (rstr[(int)input[i + 2]] >> 2 & 0x0f)); - output += b2; - } - if (input[i + 3] != '=') - { - char b3 = (char)((rstr[(int)input[i + 2]] << 6 & 0xc0) + - rstr[(int)input[i + 3]]); - output += b3; - } - i += 4; - } - } -} - - -void Base64::decode(const std::string& input, unsigned char *output, size_t& sz) -{ - size_t i = 0; - size_t l = input.size(); - size_t j = 0; - - while (i < l) - { - while (i < l && (input[i] == 13 || input[i] == 10)) - i++; - if (i < l) - { - unsigned char b1 = (unsigned char)((rstr[(int)input[i]] << 2 & 0xfc) + - (rstr[(int)input[i + 1]] >> 4 & 0x03)); - if (output) - { - output[j] = b1; - } - j++; - if (input[i + 2] != '=') - { - unsigned char b2 = (unsigned char)((rstr[(int)input[i + 1]] << 4 & 0xf0) + - (rstr[(int)input[i + 2]] >> 2 & 0x0f)); - if (output) - { - output[j] = b2; - } - j++; - } - if (input[i + 3] != '=') - { - unsigned char b3 = (unsigned char)((rstr[(int)input[i + 2]] << 6 & 0xc0) + - rstr[(int)input[i + 3]]); - if (output) - { - output[j] = b3; - } - j++; - } - i += 4; - } - } - sz = j; -} - - -size_t Base64::decode_length(const std::string& str64) -{ - if (!str64.size() || str64.size() % 4) - return 0; - size_t l = 3 * (str64.size() / 4 - 1) + 1; - if (str64[str64.size() - 2] != '=') - l++; - if (str64[str64.size() - 1] != '=') - l++; - return l; -} - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/Base64.h b/common/SocketLib/Base64.h deleted file mode 100644 index 95608e30ad..0000000000 --- a/common/SocketLib/Base64.h +++ /dev/null @@ -1,67 +0,0 @@ -/** \file Base64.h - ** \date 2004-02-13 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _BASE64_H -#define _BASE64_H - -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -/** \defgroup util Utilities */ - -/** Base64 encode/decode. - \ingroup util */ -class Base64 { -public: - - static void encode(FILE *, std::string& , bool add_crlf = true); - static void encode(const std::string&, std::string& , bool add_crlf = true); - static void encode(const char *, size_t, std::string& , bool add_crlf = true); - static void encode(unsigned char *, size_t, std::string& , bool add_crlf = true); - - static void decode(const std::string&, std::string& ); - static void decode(const std::string& in, unsigned char *out, size_t&); - - static size_t decode_length(const std::string& ); - -private: -static const char *bstr; -static const char rstr[128]; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _BASE64_H diff --git a/common/SocketLib/File.cpp b/common/SocketLib/File.cpp deleted file mode 100644 index a49e6caad8..0000000000 --- a/common/SocketLib/File.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/** \file File.cpp - ** \date 2005-04-25 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 -#include -#include -#include -#ifndef _WIN32 -#include -#endif - -#include "File.h" - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -File::File() -:m_fil(nullptr) -{ -} - - -File::~File() -{ -} - - -bool File::fopen(const std::string& path, const std::string& mode) -{ - m_path = path; - m_mode = mode; - m_fil = ::fopen(path.c_str(), mode.c_str()); - return m_fil ? true : false; -} - - -void File::fclose() -{ - if (m_fil) - ::fclose(m_fil); -} - - - -size_t File::fread(char *ptr, size_t size, size_t nmemb) -{ - return m_fil ? ::fread(ptr, size, nmemb, m_fil) : 0; -} - - -size_t File::fwrite(const char *ptr, size_t size, size_t nmemb) -{ - return m_fil ? ::fwrite(ptr, size, nmemb, m_fil) : 0; -} - - - -char *File::fgets(char *s, int size) -{ - return m_fil ? ::fgets(s, size, m_fil) : nullptr; -} - - -void File::fprintf(char *format, ...) -{ - va_list ap; - va_start(ap, format); - vfprintf(m_fil, format, ap); - va_end(ap); -} - - -off_t File::size() -{ - struct stat st; - if (stat(m_path.c_str(), &st) == -1) - { - return 0; - } - return st.st_size; -} - - -bool File::eof() -{ - if (m_fil) - { - if (feof(m_fil)) - return true; - } - return false; -} - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/File.h b/common/SocketLib/File.h deleted file mode 100644 index a575d09738..0000000000 --- a/common/SocketLib/File.h +++ /dev/null @@ -1,76 +0,0 @@ -/** \file File.h - ** \date 2005-04-25 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _FILE_H -#define _FILE_H - -#include "IFile.h" - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -/** IFile implementation of a disk file. - \ingroup file */ -class File : public IFile -{ -public: - File(); - ~File(); - - bool fopen(const std::string&, const std::string&); - void fclose(); - - size_t fread(char *, size_t, size_t); - size_t fwrite(const char *, size_t, size_t); - - char *fgets(char *, int); - void fprintf(char *format, ...); - - off_t size(); - bool eof(); - -private: - File(const File& ) {} // copy constructor - File& operator=(const File& ) { return *this; } // assignment operator - - std::string m_path; - std::string m_mode; - FILE *m_fil; -}; - - - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _FILE_H diff --git a/common/SocketLib/HTTPSocket.cpp b/common/SocketLib/HTTPSocket.cpp deleted file mode 100644 index da4f2264c8..0000000000 --- a/common/SocketLib/HTTPSocket.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* EQEMu: Everquest Server Emulator - * - * This code originated from `C++ Sockets Library` referenced below. - * Taken and stripped/modified to remove dependancies on parts of - * the library which we are not using, and to suit other needs. - * 2006 - EQEMu Development Team (http://eqemulator.net) - * - * - */ - -/** \file HTTPSocket.cpp - ** \date 2004-04-06 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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. -*/ -#ifdef _WIN32 -#pragma warning(disable:4786) -#endif -#include "../global_define.h" -#include -#include -#include -#include "Parse.h" -#include "HTTPSocket.h" -#include "../tcp_connection.h" -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - - - -HTTPSocket::HTTPSocket(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) -:TCPConnection(ID,in_socket,irIP,irPort) -,m_first(true) -,m_header(true) -,m_http_version("HTTP/1.0") -,m_request(false) -,m_response(false) -{ -} - - -HTTPSocket::~HTTPSocket() -{ -} - -/* - * eqemu stuff - */ - -bool HTTPSocket::ProcessReceivedData(char *errbuf) -{ - if (errbuf) - errbuf[0] = 0; - if (!recvbuf) - return true; - - char *buff=(char *)recvbuf; - unsigned long bufflen=recvbuf_used; - - while(1) { - if (m_header) { - char *ptr=(char *)memchr(buff,'\n',bufflen); - if (!ptr) - break; - int length=(ptr-buff)+1; - std::string line; - line.append(buff,length-2); - OnLine(line); - - buff+=length; - bufflen-=length; - } else { - OnData(buff,bufflen); - buff+=bufflen; - bufflen=0; - break; - } - } - - if (bufflen) { - memmove(recvbuf,buff,bufflen); - recvbuf_used=bufflen; - } else { - safe_delete_array(recvbuf); - } -} - -bool HTTPSocket::SendString(const char *str) { - return(TCPConnection::Send((const uchar *) str, strlen(str))); -} - -bool HTTPSocket::SendBuf(const char *dat, unsigned int len) { - return(TCPConnection::Send((const uchar *) dat, len)); -} - -/* - * /eqemu stuff - */ - -void HTTPSocket::OnLine(const std::string& line) -{ - if (m_first) - { - Parse pa(line); - std::string str = pa.getword(); - if (str.substr(0,4) == "HTTP") // response - { - m_http_version = str; - m_status = pa.getword(); - m_status_text = pa.getrest(); - m_response = true; - } - else // request - { - m_method = str; - m_url = pa.getword(); - size_t spl = m_url.find("?"); - if (spl != std::string::npos) - { - m_uri = m_url.substr(0,spl); - m_query_string = m_url.substr(spl + 1); - } - else - { - m_uri = m_url; - } - m_http_version = pa.getword(); - m_request = true; - } - m_first = false; - OnFirst(); - return; - } - if (!line.size()) - { -// SetLineProtocol(false); - m_header = false; - OnHeaderComplete(); - return; - } - Parse pa(line,":"); - std::string key = pa.getword(); - std::string value = pa.getrest(); - OnHeader(key,value); - /* If remote end tells us to keep connection alive, and we're operating - in http/1.1 mode (not http/1.0 mode), then we mark the socket to be - retained. */ -/* if (!strcasecmp(key.c_str(), "connection") && - !strcasecmp(value.c_str(), "keep-alive") ) - { - SetRetain(); - }*/ -} - - -void HTTPSocket::SendResponse() -{ - std::string msg; - msg = m_http_version + " " + m_status + " " + m_status_text + "\r\n"; - for (string_m::iterator it = m_response_header.begin(); it != m_response_header.end(); it++) - { - std::string key = (*it).first; - std::string val = (*it).second; - msg += key + ": " + val + "\r\n"; - } - msg += "\r\n"; - SendString( msg.c_str() ); -} - - -void HTTPSocket::AddResponseHeader(const std::string& header, const char *format, ...) -{ - static char slask[5000]; - va_list ap; - - va_start(ap, format); -#ifdef _WIN32 - vsprintf(slask, format, ap); -#else - vsnprintf(slask, 5000, format, ap); -#endif - va_end(ap); - - m_response_header[header] = slask; -} - - -void HTTPSocket::SendRequest() -{ - std::string msg; - msg = m_method + " " + m_url + " " + m_http_version + "\r\n"; - for (string_m::iterator it = m_response_header.begin(); it != m_response_header.end(); it++) - { - std::string key = (*it).first; - std::string val = (*it).second; - msg += key + ": " + val + "\r\n"; - } - msg += "\r\n"; - SendString( msg.c_str() ); -} - - -std::string HTTPSocket::MyUseragent() -{ - std::string version = "C++Sockets/"; -#ifdef _VERSION - version += _VERSION; -#endif - return version; -} - - -void HTTPSocket::Reset() -{ - m_first = true; - m_header = true; - m_request = false; - m_response = false; -// SetLineProtocol(true); - while (m_response_header.size()) - { - string_m::iterator it = m_response_header.begin(); - m_response_header.erase(it); - } - -} - - -const std::string& HTTPSocket::GetMethod() -{ - return m_method; -} - - -void HTTPSocket::SetMethod(const std::string& x) -{ - m_method = x; -} - - -const std::string& HTTPSocket::GetUrl() -{ - return m_url; -} - - -void HTTPSocket::SetUrl(const std::string& x) -{ - m_url = x; -} - - -const std::string& HTTPSocket::GetUri() -{ - return m_uri; -} - - -const std::string& HTTPSocket::GetQueryString() -{ - return m_query_string; -} - - -const std::string& HTTPSocket::GetHttpVersion() -{ - return m_http_version; -} - - -const std::string& HTTPSocket::GetStatus() -{ - return m_status; -} - - -const std::string& HTTPSocket::GetStatusText() -{ - return m_status_text; -} - - -bool HTTPSocket::IsRequest() -{ - return m_request; -} - - -bool HTTPSocket::IsResponse() -{ - return m_response; -} - - -void HTTPSocket::SetHttpVersion(const std::string& x) -{ - m_http_version = x; -} - - -void HTTPSocket::SetStatus(const std::string& num, const std::string& text) { - m_status = num; - m_status_text = text; -} - -void HTTPSocket::SetStatus(const std::string& x) -{ - m_status = x; -} - - -void HTTPSocket::SetStatusText(const std::string& x) -{ - m_status_text = x; -} - - -void HTTPSocket::AddResponseHeader(const std::string& x,const std::string& y) -{ - m_response_header[x] = y; -} - - -void HTTPSocket::SetUri(const std::string& x) -{ - m_uri = x; -} - -void HTTPSocket::SendResponse(const std::string& status_num, const std::string& status_text) { - SetStatus(status_num, status_text); - SendResponse(); -} - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/HTTPSocket.h b/common/SocketLib/HTTPSocket.h deleted file mode 100644 index 409c90bce0..0000000000 --- a/common/SocketLib/HTTPSocket.h +++ /dev/null @@ -1,137 +0,0 @@ -/* EQEMu: Everquest Server Emulator - * - * This code originated from `C++ Sockets Library` referenced below. - * Taken and stripped/modified to remove dependancies on parts of - * the library which we are not using, and to suit other needs. - * 2006 - EQEMu Development Team (http://eqemulator.net) - * - * - */ - -/** \file HTTPSocket.h Class HTTPSocket definition. - ** \date 2004-04-06 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _HTTPSOCKET_H -#define _HTTPSOCKET_H - -#include -#include -#include "../tcp_connection.h" - - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -/** \defgroup http HTTP Sockets */ -/** HTTP request/response base class. - \ingroup http */ -class HTTPSocket : public TCPConnection -{ - /** map to hold http header values. */ - typedef std::map string_m; -public: - HTTPSocket(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort); - virtual ~HTTPSocket(); - - void OnLine(const std::string& line); - - /** Callback executes when first line has been received. - GetMethod, GetUrl/GetUri, and GetHttpVersion are valid when this callback is executed. */ - virtual void OnFirst() = 0; - /** For each header line this callback is executed. - \param key Http header name - \param value Http header value */ - virtual void OnHeader(const std::string& key,const std::string& value) = 0; - /** Callback fires when all http headers have been received. */ - virtual void OnHeaderComplete() = 0; - /** Chunk of http body data recevied. */ - virtual void OnData(const char *,size_t) = 0; - - const std::string& GetMethod(); - void SetMethod(const std::string& x); - const std::string& GetUrl(); - void SetUrl(const std::string& x); - const std::string& GetUri(); - void SetUri(const std::string& x); - const std::string& GetQueryString(); - const std::string& GetHttpVersion(); - const std::string& GetStatus(); - const std::string& GetStatusText(); - bool IsRequest(); - bool IsResponse(); - - void SetHttpVersion(const std::string& x); - void SetStatus(const std::string& x); - void SetStatus(const std::string& num, const std::string& text); - void SetStatusText(const std::string& x); - void AddResponseHeader(const std::string& x,const std::string& y); - void AddResponseHeader(const std::string& x,const char *format, ...); - void SendResponse(); - void SendResponse(const std::string& status_num, const std::string& status_text); - void SendRequest(); - - /** Implement this to return your own User-agent string. */ - virtual std::string MyUseragent(); - -protected: - /** Reset state of socket to sucessfully implement keep-alive. */ - virtual void Reset(); - - //stubs for crap which used to be in our parent class (TcpSocket) - bool SendString(const char *str); - bool SendBuf(const char *dat, unsigned int len); - - virtual bool ProcessReceivedData(char* errbuf = 0); - -private: -// HTTPSocket& operator=(const HTTPSocket& ) { return *this; } - bool m_first; - bool m_header; - std::string m_line; - std::string m_method; - std::string m_url; - std::string m_uri; - std::string m_query_string; - std::string m_http_version; - std::string m_status; - std::string m_status_text; - bool m_request; - bool m_response; - string_m m_response_header; -}; - - - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _HTTPSOCKET_H diff --git a/common/SocketLib/HttpdCookies.cpp b/common/SocketLib/HttpdCookies.cpp deleted file mode 100644 index a40200aab6..0000000000 --- a/common/SocketLib/HttpdCookies.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/** \file HttpdCookies.cpp -*/ -/* -Copyright (C) 2003-2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 "../global_define.h" -#ifdef _WIN32 -#pragma warning(disable:4786) -#endif -#include "Parse.h" -#include "Utility.h" -#include "HTTPSocket.h" -#include "HttpdCookies.h" -#include "../types.h" -#include -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -HttpdCookies::HttpdCookies() -{ -} - -HttpdCookies::HttpdCookies(const std::string& s) -{ - Parse *pa = new Parse(s,";"); - - std::string slask = pa -> getword(); - while (slask.size()) - { - Parse *pa2 = new Parse(slask,"="); - std::string name = pa2 -> getword(); - std::string value = pa2 -> getword(); - delete pa2; - COOKIE *c = new COOKIE(name,value); - m_cookies.push_back(c); - // - slask = pa -> getword(); - } - delete pa; -} - -HttpdCookies::~HttpdCookies() -{ - for (cookie_v::iterator it = m_cookies.begin(); it != m_cookies.end(); it++) - { - COOKIE *c = *it; - delete c; - } -} - -bool HttpdCookies::getvalue(const std::string& name,std::string& buffer) //char *buffer,size_t length) -{ - for (cookie_v::iterator it = m_cookies.begin(); it != m_cookies.end(); it++) - { - COOKIE *c = *it; - if (!strcasecmp(c -> name.c_str(),name.c_str())) - { - buffer = c -> value; - return true; - } - } - buffer = ""; - return false; -} - -void HttpdCookies::replacevalue(const std::string& name,const std::string& value) -{ - COOKIE *c = nullptr; - - for (cookie_v::iterator it = m_cookies.begin(); it != m_cookies.end(); it++) - { - c = *it; - if (!strcasecmp(c -> name.c_str(),name.c_str())) - break; - c = nullptr; - } - - if (c) - { - c -> value = value; - } - else - { - c = new COOKIE(name,value); - m_cookies.push_back(c); - } -} - -void HttpdCookies::replacevalue(const std::string& name,long l) -{ - replacevalue(name, Utility::l2string(l)); -} - -void HttpdCookies::replacevalue(const std::string& name,int i) -{ - replacevalue(name, Utility::l2string(i)); -} - -size_t HttpdCookies::getlength(const std::string& name) -{ - COOKIE *c = nullptr; - - for (cookie_v::iterator it = m_cookies.begin(); it != m_cookies.end(); it++) - { - c = *it; - if (!strcasecmp(c -> name.c_str(),name.c_str())) - break; - c = nullptr; - } - return c ? c -> value.size() : 0; -} - -void HttpdCookies::setcookie(HTTPSocket *sock, const std::string& domain, const std::string& path, const std::string& name, const std::string& value) -{ - char *str = new char[name.size() + value.size() + domain.size() + path.size() + 100]; - - // set-cookie response - if (domain.size()) - { - sprintf(str, "%s=%s; domain=%s; path=%s; expires=%s", - name.c_str(), value.c_str(), - domain.c_str(), - path.c_str(), - expiredatetime().c_str()); - } - else - { - sprintf(str, "%s=%s; path=%s; expires=%s", - name.c_str(), value.c_str(), - path.c_str(), - expiredatetime().c_str()); - } - sock -> AddResponseHeader("Set-cookie", str); - delete[] str; - - replacevalue(name, value); -} - -void HttpdCookies::setcookie(HTTPSocket *sock, const std::string& domain, const std::string& path, const std::string& name, long value) -{ - char *str = new char[name.size() + domain.size() + path.size() + 100]; - char dt[80]; - - // set-cookie response - if (domain.size()) - { - sprintf(str, "%s=%ld; domain=%s; path=%s; expires=%s", - name.c_str(), value, - domain.c_str(), - path.c_str(), - expiredatetime().c_str()); - } - else - { - sprintf(str, "%s=%ld; path=%s; expires=%s", - name.c_str(), value, - path.c_str(), - expiredatetime().c_str()); - } - sock -> AddResponseHeader("Set-cookie", str); - delete[] str; - - sprintf(dt, "%ld", value); - replacevalue(name, dt); -} - -void HttpdCookies::setcookie(HTTPSocket *sock, const std::string& domain, const std::string& path, const std::string& name, int value) -{ - char *str = new char[name.size() + domain.size() + path.size() + 100]; - char dt[80]; - - // set-cookie response - if (domain.size()) - { - sprintf(str, "%s=%d; domain=%s; path=%s; expires=%s", - name.c_str(), value, - domain.c_str(), - path.c_str(), - expiredatetime().c_str()); - } - else - { - sprintf(str, "%s=%d; path=%s; expires=%s", - name.c_str(), value, - path.c_str(), - expiredatetime().c_str()); - } - sock -> AddResponseHeader("Set-cookie", str); - delete[] str; - - sprintf(dt, "%d", value); - replacevalue(name, dt); -} - - -const std::string& HttpdCookies::expiredatetime() -{ - time_t t = time(nullptr); - struct tm * tp = gmtime(&t); - const char *days[7] = {"Sunday", "Monday", - "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; - const char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", - "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - char dt[100]; - - sprintf(dt, "%s, %02d-%s-%04d %02d:%02d:%02d GMT", - days[tp -> tm_wday], - tp -> tm_mday, - months[tp -> tm_mon], - tp -> tm_year + 1910, - tp -> tm_hour, - tp -> tm_min, - tp -> tm_sec); - m_date = dt; - return m_date; -} - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/HttpdCookies.h b/common/SocketLib/HttpdCookies.h deleted file mode 100644 index 7dea224b62..0000000000 --- a/common/SocketLib/HttpdCookies.h +++ /dev/null @@ -1,91 +0,0 @@ -/** \file HttpdCookies.h -*/ -/* -Copyright (C) 2003-2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _COOKIES_H -#define _COOKIES_H - -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -//! Store the cookies name/value pairs. - - - -//! Retrieve and manage cookies during a cgi call. -class HTTPSocket; - -/** HTTP Cookie parse/container class. -\sa HttpdSocket -\sa HttpdForm -\ingroup webserver */ -class HttpdCookies -{ - /** Name/value pair store struct. - \ingroup webserver */ - struct COOKIE - { - COOKIE(const std::string& n,const std::string& v) : name(n),value(v) {} - std::string name; - std::string value; - }; - /** list of key/value structs. */ - typedef std::list cookie_v; -public: - HttpdCookies(); - HttpdCookies(const std::string& query_string); - ~HttpdCookies(); - -// int getvalue(const std::string& ,char *,size_t); // (name, buffer, length) - bool getvalue(const std::string&,std::string&); - void replacevalue(const std::string& ,const std::string& ); - void replacevalue(const std::string& ,long); - void replacevalue(const std::string& ,int); - size_t getlength(const std::string& ); - void setcookie(HTTPSocket *,const std::string& d,const std::string& p,const std::string& c,const std::string& v); - void setcookie(HTTPSocket *,const std::string& d,const std::string& p,const std::string& c,long v); - void setcookie(HTTPSocket *,const std::string& d,const std::string& p,const std::string& c,int v); - const std::string& expiredatetime(); - - cookie_v& GetHttpdCookies() { return m_cookies; } - -private: - cookie_v m_cookies; - std::string m_date; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _COOKIES_H diff --git a/common/SocketLib/HttpdForm.cpp b/common/SocketLib/HttpdForm.cpp deleted file mode 100644 index b7eb4ada8a..0000000000 --- a/common/SocketLib/HttpdForm.cpp +++ /dev/null @@ -1,621 +0,0 @@ -/** \file HttpdForm.cpp - read stdin, parse cgi input - ** - ** Written: 1999-Feb-10 grymse@alhem.net - **/ - -/* -Copyright (C) 1999-2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 -#ifdef _WIN32 -#pragma warning(disable:4786) -#include -#endif -#include "socket_include.h" -#include "Parse.h" -#include "IFile.h" -#include "HttpdForm.h" -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -HttpdForm::HttpdForm(IFile *infil) : raw(false) -{ - CGI *cgi = nullptr; - char *c_t = getenv("CONTENT_TYPE"); - char *c_l = getenv("CONTENT_LENGTH"); - size_t extra = 2; - char name[200]; - - m_current = m_cgi.end(); - *name = 0; - - if (c_t && !strncmp(c_t, "multipart/form-data",19)) - { - Parse pa(c_t,";="); - char *tempcmp = nullptr; - size_t tc = 0; - size_t l = 0; - std::string str = pa.getword(); - m_strBoundary = ""; - while (str.size()) - { - if (!strcmp(str.c_str(),"boundary")) - { - m_strBoundary = pa.getword(); - l = m_strBoundary.size(); - tempcmp = new char[l + extra]; - } - // - str = pa.getword(); - } - if (m_strBoundary.size()) - { - std::string content_type; - std::string current_name; - std::string current_filename; - char slask[2000]; - infil -> fgets(slask, 200); - while (!infil -> eof()) - { - while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10)) - { - slask[strlen(slask) - 1] = 0; - } - content_type = ""; - current_name = ""; - current_filename = ""; - if ((strstr(slask,m_strBoundary.c_str()) || strstr(m_strBoundary.c_str(),slask)) && strcmp(slask, m_strBoundary.c_str())) - { - m_strBoundary = slask; - l = m_strBoundary.size(); - delete[] tempcmp; - tempcmp = new char[l + extra]; - } - if (!strcmp(slask, m_strBoundary.c_str())) - { - // Get headers until empty line - infil -> fgets(slask, 200); - while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10)) - { - slask[strlen(slask) - 1] = 0; - } - while (!infil -> eof() && *slask) - { - Parse pa(slask,";"); - std::string h = pa.getword(); - if (!strcasecmp(h.c_str(),"Content-type:")) - { - content_type = pa.getword(); - } - else - if (!strcasecmp(h.c_str(),"Content-Disposition:")) - { - h = pa.getword(); - if (!strcmp(h.c_str(),"form-data")) - { - pa.EnableQuote(true); - h = pa.getword(); - while (h.size()) - { - Parse pa2(slask,"="); - std::string name = pa2.getword(); - std::string h = pa2.getrest(); - if (!strcmp(name.c_str(),"name")) - { - if (h.size() && h[0] == '"') - { - current_name = h.substr(1, h.size() - 2); - } - else - { - current_name = h; - } - } - else - if (!strcmp(name.c_str(),"filename")) - { - if (h.size() && h[0] == '"') - { - current_filename = h.substr(1, h.size() - 2); - } - else - { - current_filename = h; - } - size_t x = 0; - for (size_t i = 0; i < current_filename.size(); i++) - { - if (current_filename[i] == '/' || current_filename[i] == '\\') - x = i + 1; - } - if (x) - { - current_filename = current_filename.substr(x); - } - } - h = pa.getword(); - } - } - } - // get next header value - infil -> fgets(slask, 200); - while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10)) - { - slask[strlen(slask) - 1] = 0; - } - } - // Read content, save...? - if (!current_filename.size()) // not a file - { - std::string val; - infil -> fgets(slask,1000); - while (!infil -> eof() && strncmp(slask,m_strBoundary.c_str(),m_strBoundary.size() )) - { - val += slask; - infil -> fgets(slask,1000); - } - // remove trailing cr/linefeed - while (val.size() && (val[val.size() - 1] == 13 || val[val.size() - 1] == 10)) - { - val = val.substr(0,val.size() - 1); - } - cgi = new CGI(current_name, val); - m_cgi.push_back(cgi); - } - else // current_filename.size() > 0 - { - // read until m_strBoundary... - FILE *fil; - int out = 0; - char c; - char fn[1000]; // where post'd file will be saved -#ifdef _WIN32 - { - char tmp_path[1000]; - ::GetTempPath(1000, tmp_path); - if (tmp_path[strlen(tmp_path) - 1] != '\\') - { - strcat(tmp_path, "\\"); - } - sprintf(fn,"%s%s",tmp_path,current_filename.c_str()); - } -#else - sprintf(fn,"/tmp/%s",current_filename.c_str()); -#endif - if ((fil = fopen(fn, "wb")) != nullptr) - { - infil -> fread(&c,1,1); - while (!infil -> eof()) - { - if (out) - { - fwrite(&tempcmp[tc],1,1,fil); - } - tempcmp[tc] = c; - tc++; - if (tc >= l + extra) - { - tc = 0; - out = 1; - } - if (tc) - { - if (!strncmp(tempcmp + tc + extra, m_strBoundary.c_str(), l - tc) && - !strncmp(tempcmp, m_strBoundary.c_str() + l - tc, tc)) - { - break; - } - } - else - { - if (!strncmp(tempcmp + extra, m_strBoundary.c_str(), l)) - { - break; - } - } - infil -> fread(&c,1,1); - } - fclose(fil); - - cgi = new CGI(current_name,fn,fn); - m_cgi.push_back(cgi); - - strcpy(slask, m_strBoundary.c_str()); - infil -> fgets(slask + strlen(slask), 200); // next line - } - else - { - // couldn't open file - break; - } - } - } - else - { - // Probably '--' - break; - } - } // while (!infil -> eof()) - } // if (m_strBoundary) - if (tempcmp) - { - delete[] tempcmp; - } - } - else - { - int i = 0; - int cl = c_l ? atoi(c_l) : -1; - char c,chigh,clow; - char *slask = new char[8888]; - bool got_name = false; - m_current = m_cgi.end(); - - *name = 0; - - infil -> fread(&c,1,1); - cl--; - while (cl >= 0) - { - switch (c) - { - case '=': /* end of name */ - slask[i] = 0; - i = 0; - strcpy(name,slask); - got_name = true; - break; - case '&': /* end of value */ - slask[i] = 0; - i = 0; - if(got_name) { - got_name = false; - cgi = new CGI(name,slask); - m_cgi.push_back(cgi); - } else { - cgi = new CGI(slask,""); - m_cgi.push_back(cgi); - } - break; - case '+': /* space */ - slask[i++] = ' '; - break; - case '%': /* hex value */ - infil -> fread(&chigh,1,1); - cl--; - chigh -= 48; - chigh &= 0xff - 32; - if (chigh > 9) - chigh -= 7; - infil -> fread(&clow,1,1); - cl--; - clow -= 48; - clow &= 0xff - 32; - if (clow > 9) - clow -= 7; - slask[i++] = (char)(chigh * 16 + clow); - break; - default: /* just another char */ - slask[i++] = c; - break; - } - if(infil -> eof()) - break; - // - if (cl > 0) - { - infil -> fread(&c,1,1); - } - cl--; - } - slask[i] = 0; - i = 0; - if(got_name) { - cgi = new CGI(name,slask); - m_cgi.push_back(cgi); - } else { - cgi = new CGI(slask,""); - m_cgi.push_back(cgi); - } - delete[] slask; - } -} - - -// HttpdForm(buffer,l) -- request_method GET - -HttpdForm::HttpdForm(const std::string& buffer,size_t l) : raw(false) -{ - CGI *cgi = nullptr; - char slask[8888]; - char name[200]; - int i = 0; - char c,chigh,clow; - bool got_name = false; - size_t ptr = 0; - - m_current = m_cgi.end(); - - *name = 0; - - ptr = 0; - while (ptr < l) - { - c = buffer[ptr++]; - switch (c) - { - case '=': /* end of name */ - slask[i] = 0; - i = 0; - got_name = true; - strcpy(name,slask); - break; - case '&': /* end of value */ - slask[i] = 0; - i = 0; - if(got_name) { - got_name = false; - cgi = new CGI(name,slask); - m_cgi.push_back(cgi); - } else { - cgi = new CGI(slask, ""); - m_cgi.push_back(cgi); - } - break; - case '+': /* space */ - slask[i++] = ' '; - break; - case '%': /* hex value */ - chigh = buffer[ptr++]; - chigh -= 48; - chigh &= 0xff - 32; - if (chigh > 9) - chigh -= 7; - clow = buffer[ptr++]; - clow -= 48; - clow &= 0xff - 32; - if (clow > 9) - clow -= 7; - slask[i++] = (char)(chigh * 16 + clow); - break; - default: /* just another char */ - slask[i++] = c; - break; - } - } - slask[i] = 0; - i = 0; - if(got_name) { - cgi = new CGI(name,slask); - m_cgi.push_back(cgi); - } else { - cgi = new CGI(slask, ""); - m_cgi.push_back(cgi); - } -} - - -HttpdForm::~HttpdForm() -{ - CGI *cgi = nullptr; //,*tmp; - - for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++) - { - cgi = *it; - delete cgi; - } -} - - -void HttpdForm::EnableRaw(bool b) -{ - raw = b; -} - - -void HttpdForm::strcpyval(std::string& v,const char *value) //,size_t len) -{ - v = ""; - for (size_t i = 0; i < strlen(value); i++) - { - if (value[i] == '<') - { - v += "<"; - } - else - if (value[i] == '>') - { - v += ">"; - } - else - if (value[i] == '&') - { - v += "&"; - } - else - { - v += value[i]; - } - } -} - - -bool HttpdForm::getfirst(std::string& n) //char *n,size_t len) -{ - m_current = m_cgi.begin(); - return getnext(n); -} - - -bool HttpdForm::getnext(std::string& n) //char *n,size_t len) -{ - if (m_current != m_cgi.end() ) - { - CGI *current = *m_current; - n = current -> name; - m_current++; - return true; - } - else - { - n = ""; - } - return false; -} - - -bool HttpdForm::getfirst(std::string& n,std::string& v) //char *n,size_t len,char *v,size_t vlen) -{ - m_current = m_cgi.begin(); - return getnext(n,v); -} - - -bool HttpdForm::getnext(std::string& n,std::string& v) //char *n,size_t len,char *v,size_t vlen) -{ - if (m_current != m_cgi.end() ) - { - CGI *current = *m_current; - n = current -> name; - if (raw) - { - v = current -> value; - } - else - { - strcpyval(v,current -> value.c_str()); - } - m_current++; - return true; - } - else - { - n = ""; - } - return false; -} - - -int HttpdForm::getvalue(const std::string& n,std::string& v) //char *v,size_t len) -{ - CGI *cgi = nullptr; - int r = 0; - - for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++) - { - cgi = *it; - if (cgi -> name == n) - break; - cgi = nullptr; - } - if (cgi) - { - if (raw) - { - v = cgi -> value; - } - else - { - strcpyval(v,cgi -> value.c_str()); - } - r++; - } - else - { - v = ""; - } - - return r; -} - - -std::string HttpdForm::getvalue(const std::string& n) -{ - for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++) - { - CGI *cgi = *it; - if (cgi -> name == n) - { - return cgi -> value; - } - } - return ""; -} - - -size_t HttpdForm::getlength(const std::string& n) -{ - CGI *cgi = nullptr; - size_t l; - - for (cgi_v::iterator it = m_cgi.begin(); it != m_cgi.end(); it++) - { - cgi = *it; - if (cgi -> name == n) - break; - cgi = nullptr; - } - l = cgi ? cgi -> value.size() : 0; - if (cgi && !raw) - { - for (size_t i = 0; i < cgi -> value.size(); i++) - { - switch (cgi -> value[i]) - { - case '<': // < - case '>': // > - l += 4; - break; - case '&': // & - l += 5; - break; - } - } - } - return l; -} - - -HttpdForm::cgi_v& HttpdForm::getbase() -{ - return m_cgi; -} - - -const std::string& HttpdForm::GetBoundary() -{ - return m_strBoundary; -} - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/HttpdForm.h b/common/SocketLib/HttpdForm.h deleted file mode 100644 index a8209d98ba..0000000000 --- a/common/SocketLib/HttpdForm.h +++ /dev/null @@ -1,115 +0,0 @@ -/** \file HttpdForm.h - read stdin, parse cgi input - ** - ** Written: 1999-Feb-10 grymse@alhem.net - **/ - -/* -Copyright (C) 1999-2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _FORM_H -#define _FORM_H - -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -class IFile; - -/** Parse/store a http query_string/form-data body. - \ingroup webserver */ -class HttpdForm -{ - /** - * Store the name/value pairs from a GET/POST operation. - * "name" does not have to be unique. - \ingroup webserver - */ - struct CGI - { - CGI(const std::string& n,const std::string& v) : name(n),value(v) {} - CGI(const std::string& n,const std::string& v,const std::string& p) : name(n),value(v),path(p) {} - std::string name; - std::string value; - std::string path; - }; - /** list of key/value pairs. */ - typedef std::list cgi_v; - -public: - /** - * Default constructor (used in POST operations). - * Input is read from stdin. Number of characters to read - * can be found in the environment variable CONTENT_LENGTH. - */ - HttpdForm(IFile *); - /** - * Another constructor (used in GET operations). - * Input is read from the environment variable QUERY_STRING. - * @param query_string The httpd server provided QUERY_STRING - * @param length Query string length. - */ - HttpdForm(const std::string& query_string,size_t length); - ~HttpdForm(); - - void EnableRaw(bool); - - void strcpyval(std::string&,const char *); //,size_t); - - /* get names */ - bool getfirst(std::string& n); //char *,size_t); - bool getnext(std::string& n); //char *,size_t); - - /* get names and values */ - bool getfirst(std::string& n,std::string& v); //char *,size_t,char *,size_t); - bool getnext(std::string& n,std::string& v); //char *,size_t,char *,size_t); - - /* get value */ - int getvalue(const std::string& ,std::string& ); //char *,size_t); - std::string getvalue(const std::string& ); - size_t getlength(const std::string& ); - cgi_v& getbase(); - - const std::string& GetBoundary(); - -private: - HttpdForm(const HttpdForm& ) {} - HttpdForm& operator=(const HttpdForm& ) { return *this; } - cgi_v m_cgi; - cgi_v::iterator m_current; - std::string m_strBoundary; - bool raw; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _FORM_H diff --git a/common/SocketLib/HttpdSocket.cpp b/common/SocketLib/HttpdSocket.cpp deleted file mode 100644 index 21c2938d47..0000000000 --- a/common/SocketLib/HttpdSocket.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/** \file HttpdSocket.cpp -*/ -/* -Copyright (C) 2001-2004,2005 Anders Hedstrom (grymse@alhem.net) - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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. -*/ -#ifdef _WIN32 -#pragma warning(disable:4786) -#endif -#include "../global_define.h" -#include "Utility.h" -#include "HttpdCookies.h" -#include "HttpdForm.h" -#include "MemFile.h" -#include "HttpdSocket.h" -#include "../types.h" -#include -#include -#include -#include - -#define DEB(x) -/* -#define DEB(x) { \ - FILE *fil = fopen("httpdlog","at"); \ - if (!fil) \ - fil = fopen("httpdlog","wt"); \ - if (fil) { x; fclose(fil); } \ -} -*/ - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - - -// statics -int HttpdSocket::m_request_count = 0; -std::string HttpdSocket::m_start = ""; - - -HttpdSocket::HttpdSocket(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) -: HTTPSocket(ID,in_socket,irIP,irPort) -,m_content_length(0) -,m_file(nullptr) -,m_received(0) -,m_request_id(++m_request_count) -,m_cookies(nullptr) -,m_form(nullptr) -{ - m_http_date = datetime2httpdate(GetDate()); - if (!m_start.size()) - m_start = m_http_date; -} - - -HttpdSocket::~HttpdSocket() -{ - if (m_file) - { - delete m_file; - } - if (m_cookies) - delete m_cookies; - if (m_form) - delete m_form; -} - - -void HttpdSocket::OnFirst() -{ -// printf("Request: %s %s %s\n",GetMethod().c_str(),GetUrl().c_str(),GetHttpVersion().c_str()); -} - - -void HttpdSocket::OnHeader(const std::string& key,const std::string& value) -{ - if (!strcasecmp(key.c_str(),"content-length")) - { - m_content_length = atoi(value.c_str()); - m_content_length_str = value; - } - else - if (!strcasecmp(key.c_str(),"cookie")) - { - m_http_cookie = value; - } - else - if (!strcasecmp(key.c_str(),"content-type")) - { - m_content_type = value; - } - else - if (!strcasecmp(key.c_str(),"if-modified-since")) - { - m_if_modified_since = value; - } -} - - -void HttpdSocket::OnHeaderComplete() -{ - m_cookies = new HttpdCookies(m_http_cookie); - -#if (defined(SOLARIS8) || defined(SOLARIS)) - { - char slask[1000]; - if (GetMethod() == "GET") - { - sprintf(slask,"QUERY_STRING=%s", GetQueryString().c_str()); - putenv(slask); - } - sprintf(slask,"REQUEST_METHOD=%s", GetMethod().c_str()); - putenv(slask); - sprintf(slask,"HTTP_COOKIE=%s", m_http_cookie.c_str()); - putenv(slask); - sprintf(slask,"CONTENT_TYPE=%s", m_content_type.c_str()); - putenv(slask); - sprintf(slask,"CONTENT_LENGTH=%s", m_content_length_str.c_str()); - putenv(slask); - } -#elif defined _WIN32 - { - char slask[1000]; - if (GetMethod() == "GET") - { - sprintf(slask,"QUERY_STRING=%s", GetQueryString().c_str()); - _putenv(slask); - } - sprintf(slask,"REQUEST_METHOD=%s", GetMethod().c_str()); - _putenv(slask); - sprintf(slask,"HTTP_COOKIE=%s", m_http_cookie.c_str()); - _putenv(slask); - sprintf(slask,"CONTENT_TYPE=%s", m_content_type.c_str()); - _putenv(slask); - sprintf(slask,"CONTENT_LENGTH=%s", m_content_length_str.c_str()); - _putenv(slask); - } -#else - if (GetMethod() == "GET") - { - setenv("QUERY_STRING", GetQueryString().c_str(), 1); - } - setenv("REQUEST_METHOD", GetMethod().c_str(), 1); - setenv("HTTP_COOKIE", m_http_cookie.c_str(), 1); - setenv("CONTENT_TYPE", m_content_type.c_str(), 1); - setenv("CONTENT_LENGTH", m_content_length_str.c_str(), 1); -#endif - - if (GetMethod() == "POST") - { - m_file = new MemFile; - } - else - if (GetMethod() == "GET") - { - m_form = new HttpdForm(GetQueryString(), GetQueryString().size() ); - AddResponseHeader("Date", datetime2httpdate(GetDate()) ); - Exec(); - Reset(); // prepare for next request - } - else - { - AddResponseHeader("Date", GetHttpDate()); - AddResponseHeader("Connection", "close"); - SetStatus("405"); - SetStatusText("Method not allowed"); - SendResponse(); - } -} - - -void HttpdSocket::OnData(const char *p,size_t l) -{ - if (m_file) - { - m_file -> fwrite(p,1,l); - } - m_received += l; - if (m_received >= m_content_length && m_content_length) - { - // all done - if (m_file && !m_form) - { - m_form = new HttpdForm(m_file); - AddResponseHeader("Date", datetime2httpdate(GetDate()) ); - Exec(); - Reset(); // prepare for next request - } - } -} - - -void HttpdSocket::Send64(const std::string& str64, const std::string& type) -{ - if (!strcasecmp(m_start.c_str(), m_if_modified_since.c_str())) - { - SetStatus("304"); - SetStatusText("Not Modified"); - SendResponse(); - } - else - { - size_t len = Base64::decode_length(str64); - unsigned char *buf = new unsigned char[len]; - - SetStatus("200"); - SetStatusText("OK"); - - AddResponseHeader("Content-length", Utility::l2string( (long)len) ); - AddResponseHeader("Content-type", type ); - AddResponseHeader("Last-modified", m_start); - SendResponse(); - - Base64::decode(str64, buf, len); - SendBuf( (char *)buf, len); - delete[] buf; - } -} - - -std::string HttpdSocket::datetime2httpdate(const std::string& dt) -{ - struct tm tp; - time_t t; - const char *days[] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" }; - const char *months[] = { "Jan","Feb","Mar","Apr","May","Jun", - "Jul","Aug","Sep","Oct","Nov","Dec" }; - int i; - char s[40]; - -/* 1997-12-16 09:50:40 */ - - if (dt.size() == 19) - { - tp.tm_year = atoi(dt.substr(0,4).c_str()) - 1900; - i = atoi(dt.substr(5,2).c_str()) - 1; - tp.tm_mon = i >= 0 ? i : 0; - tp.tm_mday = atoi(dt.substr(8,2).c_str()); - tp.tm_hour = atoi(dt.substr(11,2).c_str()); - tp.tm_min = atoi(dt.substr(14,2).c_str()); - tp.tm_sec = atoi(dt.substr(17,2).c_str()); - tp.tm_wday = 0; - tp.tm_yday = 0; - tp.tm_isdst = 0; - t = mktime(&tp); - /*if (t == -1) - { - Handler().LogError(this, "datetime2httpdate", 0, "mktime() failed"); - }*/ - - sprintf(s,"%s, %02d %s %d %02d:%02d:%02d GMT", - days[tp.tm_wday], - tp.tm_mday, - months[tp.tm_mon], - tp.tm_year + 1900, - tp.tm_hour,tp.tm_min,tp.tm_sec); - } - else - { - *s = 0; - } - return s; -} - - -std::string HttpdSocket::GetDate() -{ - time_t t = time(nullptr); - struct tm* tp = localtime(&t); - char slask[40]; - if (tp) - { - sprintf(slask,"%d-%02d-%02d %02d:%02d:%02d", - tp -> tm_year + 1900, - tp -> tm_mon + 1, - tp -> tm_mday, - tp -> tm_hour,tp -> tm_min,tp -> tm_sec); - } - else - { - *slask = 0; - } - return slask; -} - - -void HttpdSocket::Reset() -{ - HTTPSocket::Reset(); - m_content_length = 0; - if (m_file) - { - delete m_file; - m_file = nullptr; - } - m_received = 0; - m_request_id = ++m_request_count; - if (m_cookies) - delete m_cookies; - m_cookies = nullptr; - if (m_form) - delete m_form; - m_form = nullptr; -} - - -const std::string& HttpdSocket::GetHttpDate() -{ - return m_http_date; -} - - -HttpdCookies *HttpdSocket::GetCookies() -{ - return m_cookies; -} - - -HttpdForm *HttpdSocket::GetHttpForm() -{ - return m_form; -} - - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/HttpdSocket.h b/common/SocketLib/HttpdSocket.h deleted file mode 100644 index 33d0f4a1f2..0000000000 --- a/common/SocketLib/HttpdSocket.h +++ /dev/null @@ -1,99 +0,0 @@ -/** \file HttpdSocket.h -*/ -/* -Copyright (C) 2001-2004,2005 Anders Hedstrom (grymse@alhem.net) - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _HTTPDSOCKET_H -#define _HTTPDSOCKET_H - -#include "HTTPSocket.h" - -class TCPConnection; - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -class HttpdCookies; -class HttpdForm; -class IFile; - -/** \defgroup webserver Webserver framework */ -/** Web server socket framework. - \ingroup webserver */ -class HttpdSocket : public HTTPSocket -{ -public: - HttpdSocket(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort); - ~HttpdSocket(); - - void OnFirst(); - void OnHeader(const std::string& key,const std::string& value); - void OnHeaderComplete(); - void OnData(const char *,size_t); - - /** This method needs to be implemented with logic to produce - a response to an incoming request. */ - virtual void Exec() = 0; - /** Get current date in http rfc format. */ - const std::string& GetHttpDate(); - /** Get pointer to cookie class. */ - HttpdCookies *GetCookies(); - /** Get pointer to query string/form data class. */ - HttpdForm *GetHttpForm(); - -protected: - /** Decode and send a base64-encoded string. - \param str64 Base64-encoded string - \param type Mime type of content (content-type header) */ - void Send64(const std::string& str64, const std::string& type); - std::string datetime2httpdate(const std::string& dt); - std::string GetDate(); - void Reset(); - // headers - std::string m_http_cookie; - std::string m_content_type; - std::string m_content_length_str; - std::string m_if_modified_since; - -private: -static int m_request_count; -static std::string m_start; - size_t m_content_length; - IFile *m_file; - size_t m_received; - int m_request_id; - std::string m_http_date; - HttpdCookies *m_cookies; - HttpdForm *m_form; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _HTTPDSOCKET_H diff --git a/common/SocketLib/IFile.h b/common/SocketLib/IFile.h deleted file mode 100644 index 3eb2c59ba8..0000000000 --- a/common/SocketLib/IFile.h +++ /dev/null @@ -1,65 +0,0 @@ -/** \file IFile.h - ** \date 2005-04-25 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _IFILE_H -#define _IFILE_H - -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -/** \defgroup file File handling */ -/** Pure virtual file I/O interface. - \ingroup file */ -class IFile -{ -public: - virtual ~IFile() {} - - virtual bool fopen(const std::string&, const std::string&) = 0; - virtual void fclose() = 0; - - virtual size_t fread(char *, size_t, size_t) = 0; - virtual size_t fwrite(const char *, size_t, size_t) = 0; - - virtual char *fgets(char *, int) = 0; - virtual void fprintf(char *format, ...) = 0; - - virtual off_t size() = 0; - virtual bool eof() = 0; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _IFILE_H diff --git a/common/SocketLib/MemFile.cpp b/common/SocketLib/MemFile.cpp deleted file mode 100644 index c621666e5b..0000000000 --- a/common/SocketLib/MemFile.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/** \file MemFile.cpp - ** \date 2005-04-25 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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. -*/ -#ifdef _WIN32 -#pragma warning(disable:4786) -#endif -#include -#include - -#include "MemFile.h" -#include -#include - -#ifdef _DEBUG -#define DEB(x) x -#else -#define DEB(x) -#endif - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -std::map MemFile::m_files; - - -MemFile::MemFile() -:m_temporary(true) -,m_base(new block_t) -,m_current_read(m_base) -,m_current_write(m_base) -,m_read_ptr(0) -,m_write_ptr(0) -{ -} - - -MemFile::MemFile(const std::string& path) -:m_path(path) -,m_temporary(false) -,m_base(m_files[path]) -,m_current_read(nullptr) -,m_current_write(nullptr) -,m_read_ptr(0) -,m_write_ptr(0) -{ - if (!m_base) - { - m_base = new block_t; - m_files[path] = m_base; - } - m_current_read = m_base; - m_current_write = m_base; -} - - -MemFile::~MemFile() -{ - while (m_base && m_temporary) - { - block_t *p = m_base; - m_base = p -> next; - delete p; - } -} - - -bool MemFile::fopen(const std::string& path, const std::string& mode) -{ - return true; -} - - -void MemFile::fclose() -{ -} - - - -size_t MemFile::fread(char *ptr, size_t size, size_t nmemb) -{ - size_t p = m_read_ptr % BLOCKSIZE; - size_t sz = size * nmemb; - if (p + sz < BLOCKSIZE) - { - memcpy(ptr, m_current_read -> data + p, sz); - m_read_ptr += sz; - } - else - { - size_t sz1 = BLOCKSIZE - p; - size_t sz2 = size - sz1; - memcpy(ptr, m_current_read -> data + p, sz1); - m_read_ptr += sz1; - if (m_current_read -> next) - { - m_current_read = m_current_read -> next; - memcpy(ptr + sz1, m_current_read -> data, sz2); - m_read_ptr += sz2; - } - else - { -DEB(printf("Read beyond available data\n");) - return sz1; - } - } - return sz; -} - - -size_t MemFile::fwrite(const char *ptr, size_t size, size_t nmemb) -{ - size_t p = m_write_ptr % BLOCKSIZE; - size_t sz = size * nmemb; - if (p + sz < BLOCKSIZE) - { - memcpy(m_current_write -> data + p, ptr, sz); - m_write_ptr += sz; - } - else - { - size_t sz1 = BLOCKSIZE - p; - size_t sz2 = size - sz1; - memcpy(m_current_write -> data + p, ptr, sz1); - block_t *next = new block_t; - m_current_write -> next = next; - m_current_write = next; - memcpy(m_current_write -> data, ptr + sz1, sz2); - m_write_ptr += sz; - } - return sz; -} - - - -char *MemFile::fgets(char *s, int size) -{ - int n = 0; - while (n < size - 1 && !eof()) - { - char c; - fread(&c, 1, 1); - if (c == 10) - { - s[n] = 0; - return s; - } - s[n++] = c; - } - s[n] = 0; - return s; -} - - -void MemFile::fprintf(char *format, ...) -{ - va_list ap; - char tmp[BLOCKSIZE]; - va_start(ap, format); -#ifdef _WIN32 - vsprintf(tmp, format, ap); -#else - vsnprintf(tmp, BLOCKSIZE - 1, format, ap); -#endif - va_end(ap); - fwrite(tmp, 1, strlen(tmp)); -} - - -off_t MemFile::size() -{ - return (off_t)m_write_ptr; -} - - -bool MemFile::eof() -{ - return (m_read_ptr < m_write_ptr) ? false : true; -} - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/MemFile.h b/common/SocketLib/MemFile.h deleted file mode 100644 index de777e4240..0000000000 --- a/common/SocketLib/MemFile.h +++ /dev/null @@ -1,93 +0,0 @@ -/** \file MemFile.h - ** \date 2005-04-25 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _MEMFILE_H -#define _MEMFILE_H - -#include -#include "IFile.h" - -#define BLOCKSIZE 32768 - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -/** Implements a memory file. - \ingroup file */ -class MemFile : public IFile -{ -public: - /** File block structure. - \ingroup file */ - struct block_t { - block_t() : next(nullptr) {} - struct block_t *next; - char data[BLOCKSIZE]; - }; -public: - MemFile(); - MemFile(const std::string& path); - ~MemFile(); - - bool fopen(const std::string& path, const std::string& mode); - void fclose(); - - size_t fread(char *ptr, size_t size, size_t nmemb); - size_t fwrite(const char *ptr, size_t size, size_t nmemb); - - char *fgets(char *s, int size); - void fprintf(char *format, ...); - - off_t size(); - bool eof(); - -private: - MemFile(const MemFile& ) {} // copy constructor - MemFile& operator=(const MemFile& ) { return *this; } // assignment operator - -static std::map m_files; - std::string m_path; - bool m_temporary; - block_t *m_base; - block_t *m_current_read; - block_t *m_current_write; - size_t m_read_ptr; - size_t m_write_ptr; -}; - - - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _MEMFILE_H diff --git a/common/SocketLib/Mime.cpp b/common/SocketLib/Mime.cpp deleted file mode 100644 index 282a34e772..0000000000 --- a/common/SocketLib/Mime.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/** - ** File ......... Mime.cpp - ** Published .... 2004-07-13 - ** Author ....... grymse@alhem.net -**/ -/* -Copyright (C) 2004 Anders Hedstrom - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 - -#include "Parse.h" -#include "Mime.h" -#include - - - -Mime::Mime() { -} - -Mime::Mime(const std::string& filename) { - LoadMimeFile(filename); -} - -bool Mime::LoadMimeFile(const std::string& filename) { - FILE *fil; - if ((fil = fopen(filename.c_str(),"rt")) != nullptr) { - char * slask = new char[1000]; - fgets(slask,1000,fil); - while (!feof(fil)) - { - while (strlen(slask) && (slask[strlen(slask) - 1] == 13 || slask[strlen(slask) - 1] == 10)) - { - slask[strlen(slask) - 1] = 0; - } - Parse pa(slask); - std::string mime_type = pa.getword(); - std::string ext = pa.getword(); - while (ext.size()) - { - m_mime[ext] = mime_type; - ext = pa.getword(); - } - // - fgets(slask,1000,fil); - } - delete[] slask; - fclose(fil); - return(true); - } - return(false); -} - - -Mime::~Mime() -{ -} - -void Mime::Clear() { - m_mime.clear(); -} - -std::string Mime::GetMimeFromFilename(const std::string &filename) const { - std::string::size_type pos = filename.find_last_of('.'); - if(pos == std::string::npos) - return(std::string("text/plain")); - return(GetMimeFromExtension(filename.substr(pos+1))); -} - -std::string Mime::GetMimeFromExtension(const std::string& ext) const { - mime_m::const_iterator res; - res = m_mime.find(ext); - if(res == m_mime.end()) - return(std::string("text/plain")); - - return res->second; -} - - diff --git a/common/SocketLib/Mime.h b/common/SocketLib/Mime.h deleted file mode 100644 index 337f9397ae..0000000000 --- a/common/SocketLib/Mime.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - ** File ......... Mime.h - ** Published .... 2004-07-13 - ** Author ....... grymse@alhem.net -**/ -/* -Copyright (C) 2004 Anders Hedstrom - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _MIME_H -#define _MIME_H - -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -class Mime { - typedef std::map mime_m; -public: - Mime(); - Mime(const std::string& mime_file); - ~Mime(); - - void Clear(); - bool LoadMimeFile(const std::string& mime_file); - - std::string GetMimeFromFilename(const std::string &filename) const; - std::string GetMimeFromExtension(const std::string &ext) const; - -private: - mime_m m_mime; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _MIME_H diff --git a/common/SocketLib/Parse.cpp b/common/SocketLib/Parse.cpp deleted file mode 100644 index 946c83e684..0000000000 --- a/common/SocketLib/Parse.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/** \file Parse.cpp - parse a string - ** - ** Written: 1999-Feb-10 grymse@alhem.net - **/ - -/* -Copyright (C) 1999-2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 -#include -#include - -#include "Parse.h" - -#ifdef _DEBUG -#define DEB(x) -#else -#define DEB(x) -#endif - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -/* implementation of class Parse */ - -Parse::Parse() -:pa_the_str("") -,pa_splits("") -,pa_ord("") -,pa_the_ptr(0) -,pa_breakchar(0) -,pa_enable(0) -,pa_disable(0) -,pa_nospace(0) -,pa_quote(false) -{ -} - -Parse::Parse(const std::string&s) -:pa_the_str(s) -,pa_splits("") -,pa_ord("") -,pa_the_ptr(0) -,pa_breakchar(0) -,pa_enable(0) -,pa_disable(0) -,pa_nospace(0) -,pa_quote(false) -{ -} - -Parse::Parse(const std::string&s,const std::string&sp) -:pa_the_str(s) -,pa_splits(sp) -,pa_ord("") -,pa_the_ptr(0) -,pa_breakchar(0) -,pa_enable(0) -,pa_disable(0) -,pa_nospace(0) -,pa_quote(false) -{ -} - -Parse::Parse(const std::string&s,const std::string&sp,short nospace) -:pa_the_str(s) -,pa_splits(sp) -,pa_ord("") -,pa_the_ptr(0) -,pa_breakchar(0) -,pa_enable(0) -,pa_disable(0) -,pa_nospace(1) -,pa_quote(false) -{ -} - - -Parse::~Parse() -{ -} - -#define C ((pa_the_ptr - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -/***************************************************/ -/* interface of class Parse */ - -/** Splits a string whatever way you want. - \ingroup util */ -class Parse -{ -public: - Parse(); - Parse(const std::string&); - Parse(const std::string&,const std::string&); - Parse(const std::string&,const std::string&,short); - ~Parse(); - short issplit(char); - void getsplit(void); - void getsplit(std::string&); - std::string getword(void); - void getword(std::string&); - void getword(std::string&,std::string&,int); - std::string getrest(); - void getrest(std::string&); - long getvalue(void); - void setbreak(char); - int getwordlen(void); - int getrestlen(void); - void enablebreak(char c) { - pa_enable = c; - } - void disablebreak(char c) { - pa_disable = c; - } - void getline(void); - void getline(std::string&); - size_t getptr(void) { return pa_the_ptr; } - void EnableQuote(bool b) { pa_quote = b; } - -private: - std::string pa_the_str; - std::string pa_splits; - std::string pa_ord; - size_t pa_the_ptr; - char pa_breakchar; - char pa_enable; - char pa_disable; - short pa_nospace; - bool pa_quote; -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _PARSE_H diff --git a/common/SocketLib/README.eqemu b/common/SocketLib/README.eqemu deleted file mode 100644 index 4d14b5332a..0000000000 --- a/common/SocketLib/README.eqemu +++ /dev/null @@ -1,5 +0,0 @@ -EQEmu took this code from `C++ Sockets Library` -http://www.alhem.net/Sockets/ -and integrated it into our world server. We did not care for the actual -socket code (didnt work on windows) so we scrapped all of it, and just -used the HTTP framework code. diff --git a/common/SocketLib/README.macosx b/common/SocketLib/README.macosx deleted file mode 100644 index ee23d974a8..0000000000 --- a/common/SocketLib/README.macosx +++ /dev/null @@ -1,5 +0,0 @@ -Find uuid.h here - http://www.die.net/doc/linux/include/uuid/uuid.h -or here - http://www.thedna.net/uuid.h - diff --git a/common/SocketLib/Utility.cpp b/common/SocketLib/Utility.cpp deleted file mode 100644 index e3c411fbb2..0000000000 --- a/common/SocketLib/Utility.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/** \file Utility.cpp - ** \date 2004-02-13 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 "Utility.h" - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - - -std::string Utility::base64(const std::string& str_in) -{ - std::string str; - Base64::encode(str_in, str, false); // , false == do not add cr/lf - return str; -} - - -std::string Utility::base64d(const std::string& str_in) -{ - std::string str; - Base64::decode(str_in, str); - return str; -} - - -std::string Utility::l2string(long l) -{ - std::string str; - char tmp[100]; - sprintf(tmp,"%ld",l); - str = tmp; - return str; -} - - -std::string Utility::bigint2string(uint64_t l) -{ - std::string str; - uint64_t tmp = l; - while (tmp) - { - uint64_t a = tmp % 10; - str = (char)(a + 48) + str; - tmp /= 10; - } - if (!str.size()) - { - str = "0"; - } - return str; -} - - -uint64_t Utility::atoi64(const std::string& str) -{ - uint64_t l = 0; - for (size_t i = 0; i < str.size(); i++) - { - l = l * 10 + str[i] - 48; - } - return l; -} - - -unsigned int Utility::hex2unsigned(const std::string& str) -{ - unsigned int r = 0; - for (size_t i = 0; i < str.size(); i++) - { - r = r * 16 + str[i] - 48 - ((str[i] >= 'A') ? 7 : 0) - ((str[i] >= 'a') ? 32 : 0); - } - return r; -} - - -/* -* Encode string per RFC1738 URL encoding rules -* tnx rstaveley -*/ -std::string Utility::rfc1738_encode(const std::string& src) -{ -static char hex[] = "0123456789ABCDEF"; - std::string dst; - for (size_t i = 0; i < src.size(); i++) - { - if (isalnum(src[i])) - { - dst += src[i]; - } - else - if (src[i] == ' ') - { - dst += '+'; - } - else - { - dst += '%'; - dst += hex[src[i] / 16]; - dst += hex[src[i] % 16]; - } - } - return dst; -} // rfc1738_encode - - -/* -* Decode string per RFC1738 URL encoding rules -* tnx rstaveley -*/ -std::string Utility::rfc1738_decode(const std::string& src) -{ - std::string dst; - for (size_t i = 0; i < src.size(); i++) - { - if (src[i] == '%' && isxdigit(src[i + 1]) && isxdigit(src[i + 2])) - { - char c1 = src[++i]; - char c2 = src[++i]; - c1 = c1 - 48 - ((c1 >= 'A') ? 7 : 0) - ((c1 >= 'a') ? 32 : 0); - c2 = c2 - 48 - ((c2 >= 'A') ? 7 : 0) - ((c2 >= 'a') ? 32 : 0); - dst += (char)(c1 * 16 + c2); - } - else - if (src[i] == '+') - { - dst += ' '; - } - else - { - dst += src[i]; - } - } - return dst; -} // rfc1738_decode - - -#ifdef SOCKETS_NAMESPACE -} -#endif - diff --git a/common/SocketLib/Utility.h b/common/SocketLib/Utility.h deleted file mode 100644 index 1100a99e2c..0000000000 --- a/common/SocketLib/Utility.h +++ /dev/null @@ -1,70 +0,0 @@ -/** \file Utility.h - ** \date 2004-02-13 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _UTILITY_H -#define _UTILITY_H - -#include -#ifdef _WIN32 -typedef unsigned __int64 uint64_t; -#else -#include -#ifdef SOLARIS -# include -#else -# include -#endif -#endif -#include "Base64.h" - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -/** Conversion utilities. - \ingroup util */ -class Utility -{ -public: - static std::string base64(const std::string& str_in); - static std::string base64d(const std::string& str_in); - static std::string l2string(long l); - static std::string bigint2string(uint64_t l); - static uint64_t atoi64(const std::string& str); - static unsigned int hex2unsigned(const std::string& str); - static std::string rfc1738_encode(const std::string& src); - static std::string rfc1738_decode(const std::string& src); -}; - - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // _UTILITY_H diff --git a/common/SocketLib/gpl.txt b/common/SocketLib/gpl.txt deleted file mode 100644 index 5b6e7c66c2..0000000000 --- a/common/SocketLib/gpl.txt +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; 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 - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/common/SocketLib/socket_include.cpp b/common/SocketLib/socket_include.cpp deleted file mode 100644 index 353206dcc5..0000000000 --- a/common/SocketLib/socket_include.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/** \file socket_include.cpp - ** \date 2004-11-28 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 - -// only to be included in win32 projects -const char *StrError(int x) -{ -static char tmp[100]; - switch (x) - { - case 10004: return "Interrupted function call."; - case 10013: return "Permission denied."; - case 10014: return "Bad address."; - case 10022: return "Invalid argument."; - case 10024: return "Too many open files."; - case 10035: return "Resource temporarily unavailable."; - case 10036: return "Operation now in progress."; - case 10037: return "Operation already in progress."; - case 10038: return "Socket operation on nonsocket."; - case 10039: return "Destination address required."; - case 10040: return "Message too long."; - case 10041: return "Protocol wrong type for socket."; - case 10042: return "Bad protocol option."; - case 10043: return "Protocol not supported."; - case 10044: return "Socket type not supported."; - case 10045: return "Operation not supported."; - case 10046: return "Protocol family not supported."; - case 10047: return "Address family not supported by protocol family."; - case 10048: return "Address already in use."; - case 10049: return "Cannot assign requested address."; - case 10050: return "Network is down."; - case 10051: return "Network is unreachable."; - case 10052: return "Network dropped connection on reset."; - case 10053: return "Software caused connection abort."; - case 10054: return "Connection reset by peer."; - case 10055: return "No buffer space available."; - case 10056: return "Socket is already connected."; - case 10057: return "Socket is not connected."; - case 10058: return "Cannot send after socket shutdown."; - case 10060: return "Connection timed out."; - case 10061: return "Connection refused."; - case 10064: return "Host is down."; - case 10065: return "No route to host."; - case 10067: return "Too many processes."; - case 10091: return "Network subsystem is unavailable."; - case 10092: return "Winsock.dll version out of range."; - case 10093: return "Successful WSAStartup not yet performed."; - case 10101: return "Graceful shutdown in progress."; - case 10109: return "Class type not found."; - case 11001: return "Host not found."; - case 11002: return "Nonauthoritative host not found."; - case 11003: return "This is a nonrecoverable error."; - case 11004: return "Valid name, no data record of requested type."; - - default: - break; - } - sprintf(tmp, "Winsock error code: %d", x); - return tmp; -} diff --git a/common/SocketLib/socket_include.h b/common/SocketLib/socket_include.h deleted file mode 100644 index c7489ffa3c..0000000000 --- a/common/SocketLib/socket_include.h +++ /dev/null @@ -1,218 +0,0 @@ -/** \file socket_include.h - ** \date 2005-04-12 - ** \author grymse@alhem.net -**/ -/* -Copyright (C) 2004,2005 Anders Hedstrom - -This library is made available under the terms of the GNU GPL. - -If you would like to use this library in a closed-source application, -a separate license agreement is available. For information about -the closed-source license agreement for the C++ sockets library, -please visit http://www.alhem.net/Sockets/license.html and/or -email license@alhem.net. - -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; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; 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 _SOCKET_INCLUDE_H -#define _SOCKET_INCLUDE_H - -#if (defined(__unix__) || defined(unix)) && !defined(USG) -#include -#endif - - -#ifndef _WIN32 -// ---------------------------------------- -// common unix includes / defines -#include -#include -#include -#include -#include -#include -#include - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -#define Errno errno -#define StrError strerror - -// WIN32 adapt -#define closesocket close -#define INVALID_SOCKET -1 -#define SOCKET_ERROR -1 -typedef int SOCKET; - -#ifndef INADDR_NONE -#define INADDR_NONE ((unsigned long) -1) -#endif // INADDR_NONE - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#endif // !_WIN32 - - -// ---------------------------------------- -// Generic -#ifndef SOL_IP -#define SOL_IP IPPROTO_IP -#endif - - -// ---------------------------------------- -// OS specific adaptions - -#ifdef SOLARIS -// ---------------------------------------- -// Solaris -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -typedef unsigned short port_t; -#ifdef SOCKETS_NAMESPACE -} -#endif - -#define s6_addr16 _S6_un._S6_u8 -#define MSG_NOSIGNAL 0 - -#elif defined __FreeBSD__ -// ---------------------------------------- -// FreeBSD -# if __FreeBSD_version >= 400014 -# define s6_addr16 __u6_addr.__u6_addr16 -# if !defined(MSG_NOSIGNAL) -# define MSG_NOSIGNAL 0 -# endif -# include -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -typedef in_addr_t ipaddr_t; -typedef in_port_t port_t; -#ifdef SOCKETS_NAMESPACE -} -#endif - -# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -# define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP -# else -# error FreeBSD versions prior to 400014 does not support ipv6 -# endif - -#elif defined MACOSX -// ---------------------------------------- -// Mac OS X -#include -#include -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -typedef unsigned long ipaddr_t; -#ifdef SOCKETS_NAMESPACE -} -#endif - -#define s6_addr16 __u6_addr.__u6_addr16 -#define MSG_NOSIGNAL 0 // oops - thanks Derek -#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP - -#elif defined _WIN32 -// ---------------------------------------- -// Win32 -#pragma comment(lib, "wsock32.lib") -#define strcasecmp _stricmp - -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -typedef unsigned long ipaddr_t; -typedef unsigned short port_t; -typedef int socklen_t; -#ifdef SOCKETS_NAMESPACE -} -#endif - -#define MSG_NOSIGNAL 0 -#define SHUT_RDWR 2 - -// 1.8.6: define FD_SETSIZE to something bigger than 64 if there are a lot of -// simultaneous connections (must be done before including winsock.h) -//#define FD_SETSIZE 1024 -#include - -#define Errno WSAGetLastError() -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -const char *StrError(int x); - -// class WSAInitializer is a part of the Socket class (on win32) -// as a static instance - so whenever an application uses a Socket, -// winsock is initialized -class WSAInitializer // Winsock Initializer -{ -public: - WSAInitializer() { - if (WSAStartup(0x101,&m_wsadata)) - { - exit(-1); - } - } - ~WSAInitializer() { - WSACleanup(); - } -private: - WSADATA m_wsadata; -}; - -#ifdef SOCKETS_NAMESPACE -} -#endif - -#else -// ---------------------------------------- -// LINUX -#ifdef SOCKETS_NAMESPACE -namespace SOCKETS_NAMESPACE { -#endif - -typedef unsigned long ipaddr_t; -typedef unsigned short port_t; -#ifdef SOCKETS_NAMESPACE -} -#endif - - -#endif - -#ifdef _THREADSAFE_SOCKETS -#include "mutex.h" -#include "Lock.h" -#endif - -#endif // _SOCKET_INCLUDE_H diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp deleted file mode 100644 index 5ae937137b..0000000000 --- a/common/eq_stream.cpp +++ /dev/null @@ -1,1440 +0,0 @@ -/* - Copyright (C) 2005 Michael S. Finger - - 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 "eq_stream.h" - -#include "common/crc16.h" -#include "common/eq_packet.h" -#include "common/eqemu_logsys.h" -#include "common/global_define.h" -#include "common/op_codes.h" -#include "common/platform.h" -#include "common/strings.h" - -#include -#include -#include -#include - -#ifdef _WINDOWS -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -//for logsys -#define _L "%s:%d: " -#define __L , long2ip(remote_ip).c_str(), ntohs(remote_port) - -uint16 EQStream::MaxWindowSize=2048; - -void EQStream::init(bool resetSession) { - // we only reset these statistics if it is a 'new' connection - if ( resetSession ) - { - streamactive = false; - sessionAttempts = 0; - } - active_users = 0; - Session=0; - Key=0; - MaxLen=0; - NextInSeq=0; - NextOutSeq=0; - NextAckToSend=-1; - LastAckSent=-1; - MaxSends=5; - LastPacket=0; - oversize_buffer=nullptr; - oversize_length=0; - oversize_offset=0; - RateThreshold=RATEBASE/250; - DecayRate=DECAYBASE/250; - BytesWritten=0; - sent_packet_count = 0; - received_packet_count = 0; - SequencedBase = 0; - AverageDelta = 500; - - if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - retransmittimer = Timer::GetCurrentTime(); - retransmittimeout = 500 * RETRANSMIT_TIMEOUT_MULT; - } - - OpMgr = nullptr; - if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - LogNetcode(_L "init Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); - } -} - -EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p) -{ - EQRawApplicationPacket *ap=nullptr; - LogNetcode(_L "Creating new application packet, length [{}]" __L, p->size); - // _raw(NET__APP_CREATE_HEX, 0xFFFF, p); - ap = p->MakeAppPacket(); - return ap; -} - -EQRawApplicationPacket *EQStream::MakeApplicationPacket(const unsigned char *buf, uint32 len) -{ - EQRawApplicationPacket *ap=nullptr; - LogNetcode(_L "Creating new application packet, length [{}]" __L, len); - ap = new EQRawApplicationPacket(buf, len); - return ap; -} - -EQProtocolPacket *EQStream::MakeProtocolPacket(const unsigned char *buf, uint32 len) { - uint16 proto_opcode = ntohs(*(const uint16 *)buf); - - //advance over opcode. - buf += 2; - len -= 2; - - return(new EQProtocolPacket(proto_opcode, buf, len)); -} - -void EQStream::ProcessPacket(EQProtocolPacket *p) -{ - uint32 processed=0, subpacket_length=0; - if (p == nullptr) - return; - // Raw Application packet - if (p->opcode > 0xff) { - p->opcode = htons(p->opcode); //byte order is backwards in the protocol packet - EQRawApplicationPacket *ap=MakeApplicationPacket(p); - if (ap) - InboundQueuePush(ap); - return; - } - - if (!Session && p->opcode!=OP_SessionRequest && p->opcode!=OP_SessionResponse) { - LogNetcode(_L "Session not initialized, packet ignored" __L); - // _raw(NET__DEBUG, 0xFFFF, p); - return; - } - - switch (p->opcode) { - case OP_Combined: { - processed=0; - while(processed < p->size) { - subpacket_length=*(p->pBuffer+processed); - EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+processed+1,subpacket_length); - LogNetcode(_L "Extracting combined packet of length [{}]" __L, subpacket_length); - // _raw(NET__NET_CREATE_HEX, 0xFFFF, subp); - subp->copyInfo(p); - ProcessPacket(subp); - delete subp; - processed+=subpacket_length+1; - } - } - break; - - case OP_AppCombined: { - processed=0; - while(processedsize) { - EQRawApplicationPacket *ap=nullptr; - if ((subpacket_length=(unsigned char)*(p->pBuffer+processed))!=0xff) { - LogNetcode(_L "Extracting combined app packet of length [{}], short len" __L, subpacket_length); - ap=MakeApplicationPacket(p->pBuffer+processed+1,subpacket_length); - processed+=subpacket_length+1; - } else { - subpacket_length=ntohs(*(uint16 *)(p->pBuffer+processed+1)); - LogNetcode(_L "Extracting combined app packet of length [{}], short len" __L, subpacket_length); - ap=MakeApplicationPacket(p->pBuffer+processed+3,subpacket_length); - processed+=subpacket_length+3; - } - if (ap) { - ap->copyInfo(p); - InboundQueuePush(ap); - } - } - } - break; - - case OP_Packet: { - if(!p->pBuffer || (p->Size() < 4)) - { - LogNetcode(_L "Received OP_Packet that was of malformed size" __L); - break; - } - uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); - SeqOrder check=CompareSequence(NextInSeq,seq); - if (check == SeqFuture) { - LogNetcode(_L "Future OP_Packet: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq); - // _raw(NET__DEBUG, seq, p); - - PacketQueue[seq]=p->Copy(); - LogNetcode(_L "OP_Packet Queue size=[{}]" __L, PacketQueue.size()); - - //SendOutOfOrderAck(seq); - - } else if (check == SeqPast) { - LogNetcode(_L "Duplicate OP_Packet: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq); - // _raw(NET__DEBUG, seq, p); - SendOutOfOrderAck(seq); //we already got this packet but it was out of order - } else { - // In case we did queue one before as well. - EQProtocolPacket *qp=RemoveQueue(seq); - if (qp) { - LogNetcode("[NET_TRACE] OP_Packet: Removing older queued packet with sequence [{}]", seq); - delete qp; - } - - SetNextAckToSend(seq); - NextInSeq++; - // Check for an embedded OP_AppCombinded (protocol level 0x19) - if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) { - EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+2,p->size-2); - LogNetcode(_L "seq [{}], Extracting combined packet of length [{}]" __L, seq, subp->size); - // _raw(NET__NET_CREATE_HEX, seq, subp); - subp->copyInfo(p); - ProcessPacket(subp); - delete subp; - } else { - EQRawApplicationPacket *ap=MakeApplicationPacket(p->pBuffer+2,p->size-2); - if (ap) { - ap->copyInfo(p); - InboundQueuePush(ap); - } - } - } - } - break; - - case OP_Fragment: { - if(!p->pBuffer || (p->Size() < 4)) - { - LogNetcode(_L "Received OP_Fragment that was of malformed size" __L); - break; - } - uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); - SeqOrder check=CompareSequence(NextInSeq,seq); - if (check == SeqFuture) { - LogNetcode(_L "Future OP_Fragment: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq); - // _raw(NET__DEBUG, seq, p); - - PacketQueue[seq]=p->Copy(); - LogNetcode(_L "OP_Fragment Queue size=[{}]" __L, PacketQueue.size()); - - //SendOutOfOrderAck(seq); - - } else if (check == SeqPast) { - LogNetcode(_L "Duplicate OP_Fragment: Expecting Seq=[{}], but got Seq=[{}]" __L, NextInSeq, seq); - // _raw(NET__DEBUG, seq, p); - SendOutOfOrderAck(seq); - } else { - // In case we did queue one before as well. - EQProtocolPacket *qp=RemoveQueue(seq); - if (qp) { - LogNetcode("[NET_TRACE] OP_Fragment: Removing older queued packet with sequence [{}]", seq); - delete qp; - } - SetNextAckToSend(seq); - NextInSeq++; - if (oversize_buffer) { - memcpy(oversize_buffer+oversize_offset,p->pBuffer+2,p->size-2); - oversize_offset+=p->size-2; - LogNetcode(_L "Fragment of oversized of length [{}], seq [{}]: now at [{}]/[{}]" __L, p->size-2, seq, oversize_offset, oversize_length); - if (oversize_offset==oversize_length) { - if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) { - EQProtocolPacket *subp=MakeProtocolPacket(oversize_buffer,oversize_offset); - LogNetcode(_L "seq [{}], Extracting combined oversize packet of length [{}]" __L, seq, subp->size); - //// _raw(NET__NET_CREATE_HEX, subp); - subp->copyInfo(p); - ProcessPacket(subp); - delete subp; - } else { - EQRawApplicationPacket *ap=MakeApplicationPacket(oversize_buffer,oversize_offset); - LogNetcode(_L "seq [{}], completed combined oversize packet of length [{}]" __L, seq, ap->size); - if (ap) { - ap->copyInfo(p); - InboundQueuePush(ap); - } - } - delete[] oversize_buffer; - oversize_buffer=nullptr; - oversize_offset=0; - } - } else { - oversize_length=ntohl(*(uint32 *)(p->pBuffer+2)); - oversize_buffer=new unsigned char[oversize_length]; - memcpy(oversize_buffer,p->pBuffer+6,p->size-6); - oversize_offset=p->size-6; - LogNetcode(_L "First fragment of oversized of seq [{}]: now at [{}]/[{}]" __L, seq, oversize_offset, oversize_length); - } - } - } - break; - case OP_KeepAlive: { - NonSequencedPush(new EQProtocolPacket(p->opcode,p->pBuffer,p->size)); - LogNetcode(_L "Received and queued reply to keep alive" __L); - } - break; - case OP_Ack: { - if(!p->pBuffer || (p->Size() < 4)) - { - LogNetcode(_L "Received OP_Ack that was of malformed size" __L); - break; - } - uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); - AckPackets(seq); - - if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - retransmittimer = Timer::GetCurrentTime(); - } - } - break; - case OP_SessionRequest: { - if(p->Size() < sizeof(SessionRequest)) - { - LogNetcode(_L "Received OP_SessionRequest that was of malformed size" __L); - break; - } - if (GetState()==ESTABLISHED) { - LogNetcode(_L "Received OP_SessionRequest in ESTABLISHED state ([{}]) streamactive ([{}]) attempt ([{}])" __L, GetState(),streamactive,sessionAttempts); - - // client seems to try a max of 30 times (initial+3 retries) then gives up, giving it a few more attempts just in case - // streamactive means we identified the opcode for the stream, we cannot re-establish this connection - if ( streamactive || ( sessionAttempts > MAX_SESSION_RETRIES ) ) - { - _SendDisconnect(); - SetState(CLOSED); - break; - } - } - sessionAttempts++; - // we set established below, so statistics will not be reset for session attempts/stream active. - init(GetState()!=ESTABLISHED); - OutboundQueueClear(); - SessionRequest *Request=(SessionRequest *)p->pBuffer; - Session=ntohl(Request->Session); - SetMaxLen(ntohl(Request->MaxLength)); - LogNetcode(_L "Received OP_SessionRequest: session [{}], maxlen [{}]" __L, (unsigned long)Session, MaxLen); - SetState(ESTABLISHED); - Key=0x11223344; - SendSessionResponse(); - } - break; - case OP_SessionResponse: { - if(p->Size() < sizeof(SessionResponse)) - { - LogNetcode(_L "Received OP_SessionResponse that was of malformed size" __L); - break; - } - - init(); - OutboundQueueClear(); - SessionResponse *Response=(SessionResponse *)p->pBuffer; - SetMaxLen(ntohl(Response->MaxLength)); - Key=ntohl(Response->Key); - NextInSeq=0; - SetState(ESTABLISHED); - if (!Session) - Session=ntohl(Response->Session); - compressed=(Response->Format&FLAG_COMPRESSED); - encoded=(Response->Format&FLAG_ENCODED); - - LogNetcode(_L "Received OP_SessionResponse: session [{}], maxlen [{}], key [{}], compressed? [{}], encoded? [{}]" __L, (unsigned long)Session, MaxLen, (unsigned long)Key, compressed?"yes":"no", encoded?"yes":"no"); - - // Kinda kludgy, but trie for now - if (StreamType==UnknownStream) { - if (compressed) { - if (remote_port==9000 || (remote_port==0 && p->src_port==9000)) { - SetStreamType(WorldStream); - } else { - SetStreamType(ZoneStream); - } - } else if (encoded) { - SetStreamType(ChatOrMailStream); - } else { - SetStreamType(LoginStream); - } - } - } - break; - case OP_SessionDisconnect: { - //NextInSeq=0; - EQStreamState state = GetState(); - if(state == ESTABLISHED) { - //client initiated disconnect? - LogNetcode(_L "Received unsolicited OP_SessionDisconnect. Treating like a client-initiated disconnect" __L); - _SendDisconnect(); - SetState(CLOSED); - } else if(state == CLOSING) { - //we were waiting for this anyways, ignore pending messages, send the reply and be closed. - LogNetcode(_L "Received OP_SessionDisconnect when we have a pending close, they beat us to it. Were happy though" __L); - _SendDisconnect(); - SetState(CLOSED); - } else { - //we are expecting this (or have already gotten it, but dont care either way) - LogNetcode(_L "Received expected OP_SessionDisconnect. Moving to closed state" __L); - SetState(CLOSED); - } - } - break; - case OP_OutOfOrderAck: { - if(!p->pBuffer || (p->Size() < 4)) - { - LogNetcode(_L "Received OP_OutOfOrderAck that was of malformed size" __L); - break; - } - uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); - MOutboundQueue.lock(); - - if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - LogNetcode(_L "Pre-OOA Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); - } - - //if the packet they got out of order is between our last acked packet and the last sent packet, then its valid. - if (CompareSequence(SequencedBase,seq) != SeqPast && CompareSequence(NextOutSeq,seq) == SeqPast) { - Log(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck for sequence %d, starting retransmit at the start of our unacked buffer (seq %d, was %d)." __L, - seq, SequencedBase, SequencedBase+SequencedQueue.size()); - - uint16 sqsize = SequencedQueue.size(); - uint16 index = seq - SequencedBase; - LogNetcode(_L "OP_OutOfOrderAck marking packet acked in queue (queue index = [{}], queue size = [{}])" __L, index, sqsize); - if (index < sqsize) { - SequencedQueue[index]->acked = true; - // flag packets for a resend - uint16 count = 0; - uint32 timeout = AverageDelta * 2 + 100; - for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end() && count < index; ++sitr, ++count) { - if (!(*sitr)->acked && (*sitr)->sent_time > 0 && (((*sitr)->sent_time + timeout) < Timer::GetCurrentTime())) { - (*sitr)->sent_time = 0; - LogNetcode(_L "OP_OutOfOrderAck Flagging packet [{}] for retransmission" __L, SequencedBase + count); - } - } - } - - if(RETRANSMIT_TIMEOUT_MULT) { - retransmittimer = Timer::GetCurrentTime(); - } - } else { - LogNetcode(_L "Received OP_OutOfOrderAck for out-of-window [{}]. Window ([{}]->[{}])" __L, seq, SequencedBase, NextOutSeq); - } - - if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - LogNetcode(_L "Post-OOA Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); - } - - MOutboundQueue.unlock(); - } - break; - case OP_SessionStatRequest: { - if(p->Size() < sizeof(ClientSessionStats)) - { - LogNetcode(_L "Received OP_SessionStatRequest that was of malformed size" __L); - break; - } - ClientSessionStats *ClientStats=(ClientSessionStats *)p->pBuffer; - Log(Logs::Detail, Logs::Netcode, _L "Received Stats: %lu packets received, %lu packets sent, Deltas: local %lu, (%lu <- %lu -> %lu) remote %lu" __L, - (unsigned long)ntohl(ClientStats->packets_received), (unsigned long)ntohl(ClientStats->packets_sent), (unsigned long)ntohl(ClientStats->last_local_delta), - (unsigned long)ntohl(ClientStats->low_delta), (unsigned long)ntohl(ClientStats->average_delta), - (unsigned long)ntohl(ClientStats->high_delta), (unsigned long)ntohl(ClientStats->last_remote_delta)); - - AdjustRates(ntohl(ClientStats->average_delta)); - - if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - if (RETRANSMIT_TIMEOUT_MULT && ntohl(ClientStats->average_delta)) { - //recalculate retransmittimeout using the larger of the last rtt or average rtt, which is multiplied by the rule value - if ((ntohl(ClientStats->last_local_delta) + ntohl(ClientStats->last_remote_delta)) > (ntohl(ClientStats->average_delta) * 2)) { - retransmittimeout = (ntohl(ClientStats->last_local_delta) + ntohl(ClientStats->last_remote_delta)) - * RETRANSMIT_TIMEOUT_MULT; - } else { - retransmittimeout = ntohl(ClientStats->average_delta) * 2 * RETRANSMIT_TIMEOUT_MULT; - } - retransmittimeout += 300; - if(retransmittimeout > RETRANSMIT_TIMEOUT_MAX) - retransmittimeout = RETRANSMIT_TIMEOUT_MAX; - LogNetcode(_L "Retransmit timeout recalculated to [{}]ms" __L, retransmittimeout); - } - } - - ServerSessionStats *ServerStats = (ServerSessionStats *)p->pBuffer; - - //ServerStats->RequestID = ClientStats->RequestID; // no change - ServerStats->ServerTime = htonl(Timer::GetCurrentTime()); - ServerStats->packets_sent_echo = ClientStats->packets_sent; // still in htonll format - ServerStats->packets_received_echo = ClientStats->packets_received; // still in htonll format - ServerStats->packets_sent = htonll(GetPacketsSent()); - ServerStats->packets_received = htonll(GetPacketsReceived()); - - NonSequencedPush(new EQProtocolPacket(OP_SessionStatResponse, p->pBuffer, p->size)); - } - break; - case OP_SessionStatResponse: { - LogNetcode(_L "Received OP_SessionStatResponse. Ignoring" __L); - } - break; - case OP_OutOfSession: { - LogNetcode(_L "Received OP_OutOfSession. Ignoring" __L); - } - break; - default: - EQRawApplicationPacket *ap = MakeApplicationPacket(p); - if (ap) - InboundQueuePush(ap); - break; - } -} - -void EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req) -{ - if(p == nullptr) - return; - - EQApplicationPacket *newp = p->Copy(); - - if (newp != nullptr) - FastQueuePacket(&newp, ack_req); -} - -void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req) -{ - EQApplicationPacket *pack=*p; - *p = nullptr; //clear caller's pointer.. effectively takes ownership - - if(pack == nullptr) - return; - - if(OpMgr == nullptr || *OpMgr == nullptr) { - LogNetcode(_L "Packet enqueued into a stream with no opcode manager, dropping" __L); - delete pack; - return; - } - - uint16 opcode = 0; - if(pack->GetOpcodeBypass() != 0) { - opcode = pack->GetOpcodeBypass(); - } else { - opcode = (*OpMgr)->EmuToEQ(pack->GetOpcode()); - } - - if (!ack_req) { - NonSequencedPush(new EQProtocolPacket(opcode, pack->pBuffer, pack->size)); - delete pack; - } else { - SendPacket(opcode, pack); - } -} - -void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) -{ - uint32 chunksize, used; - uint32 length; - - if (EQEmuLogSys::Instance()->log_settings[Logs::Server_Client_Packet].is_category_enabled == 1){ - if (p->GetOpcode() != OP_SpecialMesg){ - Log(Logs::General, Logs::Server_Client_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size()); - } - } - - if (EQEmuLogSys::Instance()->log_settings[Logs::Server_Client_Packet_With_Dump].is_category_enabled == 1){ - if (p->GetOpcode() != OP_SpecialMesg){ - Log(Logs::General, Logs::Server_Client_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str()); - } - } - - // Convert the EQApplicationPacket to 1 or more EQProtocolPackets - if (p->size>(MaxLen-8)) { // proto-op(2), seq(2), app-op(2) ... data ... crc(2) - LogNetcode(_L "Making oversized packet, len [{}]" __L, p->Size()); - - auto tmpbuff = new unsigned char[p->size + 3]; - length=p->serialize(opcode, tmpbuff); - if (length != p->Size()) - LogNetcode(_L "Packet adjustment, len [{}] to [{}]" __L, p->Size(), length); - - auto out = new EQProtocolPacket(OP_Fragment, nullptr, MaxLen - 4); - *(uint32 *)(out->pBuffer+2)=htonl(length); - used=MaxLen-10; - memcpy(out->pBuffer+6,tmpbuff,used); - LogNetcode(_L "First fragment: used [{}]/[{}]. Payload size [{}] in the packet" __L, used, length, p->size); - SequencedPush(out); - - - while (usedpBuffer+2,tmpbuff+used,chunksize); - out->size=chunksize+2; - SequencedPush(out); - used+=chunksize; - LogNetcode(_L "Subsequent fragment: len [{}], used [{}]/[{}]" __L, chunksize, used, length); - } - delete p; - delete[] tmpbuff; - } else { - - auto tmpbuff = new unsigned char[p->Size() + 3]; - length=p->serialize(opcode, tmpbuff+2) + 2; - - auto out = new EQProtocolPacket(OP_Packet, tmpbuff, length); - - delete[] tmpbuff; - SequencedPush(out); - delete p; - } -} - -void EQStream::SequencedPush(EQProtocolPacket *p) -{ - MOutboundQueue.lock(); - if (uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - Log(Logs::Detail, Logs::Netcode, _L "Pre-Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, - SequencedBase, SequencedQueue.size(), NextOutSeq); - } - - Log(Logs::Detail, Logs::Netcode, _L "Pushing sequenced packet %d of length %d. Base Seq is %d." __L, - NextOutSeq, p->size, SequencedBase); - *(uint16 *)(p->pBuffer) = htons(NextOutSeq); - SequencedQueue.push_back(p); - NextOutSeq++; - - if (uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - Log(Logs::Detail, Logs::Netcode, _L "Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, - SequencedBase, SequencedQueue.size(), NextOutSeq); - } - - MOutboundQueue.unlock(); -} - -void EQStream::NonSequencedPush(EQProtocolPacket *p) -{ - MOutboundQueue.lock(); - LogNetcode(_L "Pushing non-sequenced packet of length [{}]" __L, p->size); - NonSequencedQueue.push(p); - MOutboundQueue.unlock(); -} - -void EQStream::SendAck(uint16 seq) -{ -uint16 Seq=htons(seq); - LogNetcode(_L "Sending ack with sequence [{}]" __L, seq); - SetLastAckSent(seq); - NonSequencedPush(new EQProtocolPacket(OP_Ack,(unsigned char *)&Seq,sizeof(uint16))); -} - -void EQStream::SendOutOfOrderAck(uint16 seq) -{ - LogNetcode(_L "Sending out of order ack with sequence [{}]" __L, seq); -uint16 Seq=htons(seq); - NonSequencedPush(new EQProtocolPacket(OP_OutOfOrderAck,(unsigned char *)&Seq,sizeof(uint16))); -} - -void EQStream::Write(int eq_fd) -{ - std::queue ReadyToSend; - bool SeqEmpty=false, NonSeqEmpty=false; - std::deque::iterator sitr; - - // Check our rate to make sure we can send more - MRate.lock(); - int32 threshold=RateThreshold; - MRate.unlock(); - if (BytesWritten > threshold) { - return; - } - - // If we got more packets to we need to ack, send an ack on the highest one - MAcks.lock(); - if (CompareSequence(LastAckSent, NextAckToSend) == SeqFuture) - SendAck(NextAckToSend); - MAcks.unlock(); - - // Lock the outbound queues while we process - MOutboundQueue.lock(); - - // Place to hold the base packet t combine into - EQProtocolPacket *p=nullptr; - - // Find the next sequenced packet to send from the "queue" - sitr = SequencedQueue.begin(); - - uint16 count = 0; - // get to start of packets - while (sitr != SequencedQueue.end() && (*sitr)->sent_time > 0) { - ++sitr; - ++count; - } - - // Loop until both are empty or MaxSends is reached - while(!SeqEmpty || !NonSeqEmpty) { - - // See if there are more non-sequenced packets left - if (!NonSequencedQueue.empty()) { - if (!p) { - // If we don't have a packet to try to combine into, use this one as the base - // And remove it form the queue - p = NonSequencedQueue.front(); - LogNetcode(_L "Starting combined packet with non-seq packet of len [{}]" __L, p->size); - NonSequencedQueue.pop(); - } else if (!p->combine(NonSequencedQueue.front())) { - // Trying to combine this packet with the base didn't work (too big maybe) - // So just send the base packet (we'll try this packet again later) - LogNetcode(_L "Combined packet full at len [{}], next non-seq packet is len [{}]" __L, p->size, (NonSequencedQueue.front())->size); - ReadyToSend.push(p); - BytesWritten+=p->size; - p=nullptr; - - if (BytesWritten > threshold) { - // Sent enough this round, lets stop to be fair - LogNetcode(_L "Exceeded write threshold in nonseq ([{}] > [{}])" __L, BytesWritten, threshold); - break; - } - } else { - // Combine worked, so just remove this packet and it's spot in the queue - LogNetcode(_L "Combined non-seq packet of len [{}], yeilding [{}] combined" __L, (NonSequencedQueue.front())->size, p->size); - delete NonSequencedQueue.front(); - NonSequencedQueue.pop(); - } - } else { - // No more non-sequenced packets - NonSeqEmpty=true; - } - - if (sitr != SequencedQueue.end()) { - uint16 seq_send = SequencedBase + count; //just for logging... - - if(SequencedQueue.empty()) { - LogNetcode(_L "Tried to write a packet with an empty queue ([{}] is past next out [{}])" __L, seq_send, NextOutSeq); - SeqEmpty=true; - continue; - } - - if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - if ((*sitr)->acked || (*sitr)->sent_time != 0) { - ++sitr; - ++count; - if (p) { - LogNetcode(_L "Final combined packet not full, len [{}]" __L, p->size); - ReadyToSend.push(p); - BytesWritten += p->size; - p = nullptr; - } - LogNetcode(_L "Not retransmitting seq packet [{}] because already marked as acked" __L, seq_send); - } else if (!p) { - // If we don't have a packet to try to combine into, use this one as the base - // Copy it first as it will still live until it is acked - p=(*sitr)->Copy(); - LogNetcode(_L "Starting combined packet with seq packet [{}] of len [{}]" __L, seq_send, p->size); - (*sitr)->sent_time = Timer::GetCurrentTime(); - ++sitr; - ++count; - } else if (!p->combine(*sitr)) { - // Trying to combine this packet with the base didn't work (too big maybe) - // So just send the base packet (we'll try this packet again later) - LogNetcode(_L "Combined packet full at len [{}], next seq packet [{}] is len [{}]" __L, p->size, seq_send + 1, (*sitr)->size); - ReadyToSend.push(p); - BytesWritten+=p->size; - p=nullptr; - if ((*sitr)->opcode != OP_Fragment && BytesWritten > threshold) { - // Sent enough this round, lets stop to be fair - LogNetcode(_L "Exceeded write threshold in seq ([{}] > [{}])" __L, BytesWritten, threshold); - break; - } - } else { - // Combine worked - LogNetcode(_L "Combined seq packet [{}] of len [{}], yeilding [{}] combined" __L, seq_send, (*sitr)->size, p->size); - (*sitr)->sent_time = Timer::GetCurrentTime(); - ++sitr; - ++count; - } - } else { - if ((*sitr)->sent_time != 0) { - ++sitr; - ++count; - if (p) { - LogNetcode(_L "Final combined packet not full, len [{}]" __L, p->size); - ReadyToSend.push(p); - BytesWritten += p->size; - p = nullptr; - } - } else if (!p) { - // If we don't have a packet to try to combine into, use this one as the base - // Copy it first as it will still live until it is acked - p=(*sitr)->Copy(); - (*sitr)->sent_time = Timer::GetCurrentTime(); - LogNetcode(_L "Starting combined packet with seq packet [{}] of len [{}]" __L, seq_send, p->size); - ++sitr; - ++count; - } else if (!p->combine(*sitr)) { - // Trying to combine this packet with the base didn't work (too big maybe) - // So just send the base packet (we'll try this packet again later) - LogNetcode(_L "Combined packet full at len [{}], next seq packet [{}] is len [{}]" __L, p->size, seq_send, (*sitr)->size); - ReadyToSend.push(p); - BytesWritten+=p->size; - p=nullptr; - - if (BytesWritten > threshold) { - // Sent enough this round, lets stop to be fair - LogNetcode(_L "Exceeded write threshold in seq ([{}] > [{}])" __L, BytesWritten, threshold); - break; - } - } else { - // Combine worked - LogNetcode(_L "Combined seq packet [{}] of len [{}], yielding [{}] combined" __L, seq_send, (*sitr)->size, p->size); - (*sitr)->sent_time = Timer::GetCurrentTime(); - ++sitr; - ++count; - } - } - - if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - LogNetcode(_L "Post send Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); - } - } else { - // No more sequenced packets - SeqEmpty=true; - } - } - // Unlock the queue - MOutboundQueue.unlock(); - - // We have a packet still, must have run out of both seq and non-seq, so send it - if (p) { - LogNetcode(_L "Final combined packet not full, len [{}]" __L, p->size); - ReadyToSend.push(p); - BytesWritten+=p->size; - } - - // Send all the packets we "made" - while(!ReadyToSend.empty()) { - p = ReadyToSend.front(); - WritePacket(eq_fd,p); - delete p; - ReadyToSend.pop(); - } - - //see if we need to send our disconnect and finish our close - if(SeqEmpty && NonSeqEmpty) { - //no more data to send - if(CheckState(CLOSING)) { - LogNetcode(_L "All outgoing data flushed, closing stream" __L ); - //we are waiting for the queues to empty, now we can do our disconnect. - //this packet will not actually go out until the next call to Write(). - _SendDisconnect(); - SetState(DISCONNECTING); - } - } -} - -void EQStream::WritePacket(int eq_fd, EQProtocolPacket *p) -{ -uint32 length; -sockaddr_in address; - address.sin_family = AF_INET; - address.sin_addr.s_addr=remote_ip; - address.sin_port=remote_port; -#ifdef NOWAY - uint32 ip=address.sin_addr.s_addr; - std::cout << "Sending to: " - << (int)*(unsigned char *)&ip - << "." << (int)*((unsigned char *)&ip+1) - << "." << (int)*((unsigned char *)&ip+2) - << "." << (int)*((unsigned char *)&ip+3) - << "," << (int)ntohs(address.sin_port) << "(" << p->size << ")" << std::endl; - - p->DumpRaw(); - std::cout << "-------------" << std::endl; -#endif - length=p->serialize(buffer); - if (p->opcode!=OP_SessionRequest && p->opcode!=OP_SessionResponse) { - if (compressed) { - BytesWritten -= p->size; - uint32 newlen=EQProtocolPacket::Compress(buffer,length, _tempBuffer, 2048); - memcpy(buffer,_tempBuffer,newlen); - length=newlen; - BytesWritten += newlen; - } - if (encoded) { - EQProtocolPacket::ChatEncode(buffer,length,Key); - } - - *(uint16 *)(buffer+length)=htons(CRC16(buffer,length,Key)); - length+=2; - } - //dump_message_column(buffer,length,"Writer: "); - sendto(eq_fd,(char *)buffer,length,0,(sockaddr *)&address,sizeof(address)); - AddBytesSent(length); -} - -void EQStream::SendSessionResponse() -{ - auto out = new EQProtocolPacket(OP_SessionResponse, nullptr, sizeof(SessionResponse)); - SessionResponse *Response=(SessionResponse *)out->pBuffer; - Response->Session=htonl(Session); - Response->MaxLength=htonl(MaxLen); - Response->UnknownA=2; - Response->Format=0; - if (compressed) - Response->Format|=FLAG_COMPRESSED; - if (encoded) - Response->Format|=FLAG_ENCODED; - Response->Key=htonl(Key); - - out->size=sizeof(SessionResponse); - - Log(Logs::Detail, Logs::Netcode, _L "Sending OP_SessionResponse: session %lu, maxlen=%d, key=0x%x, compressed? %s, encoded? %s" __L, - (unsigned long)Session, MaxLen, Key, compressed?"yes":"no", encoded?"yes":"no"); - - NonSequencedPush(out); -} - -void EQStream::SendSessionRequest() -{ - auto out = new EQProtocolPacket(OP_SessionRequest, nullptr, sizeof(SessionRequest)); - SessionRequest *Request=(SessionRequest *)out->pBuffer; - memset(Request,0,sizeof(SessionRequest)); - Request->Session=htonl(time(nullptr)); - Request->MaxLength=htonl(512); - - LogNetcode(_L "Sending OP_SessionRequest: session [{}], maxlen=[{}]" __L, (unsigned long)ntohl(Request->Session), ntohl(Request->MaxLength)); - - NonSequencedPush(out); -} - -void EQStream::_SendDisconnect() -{ - if(GetState() == CLOSED) - return; - - auto out = new EQProtocolPacket(OP_SessionDisconnect, nullptr, sizeof(uint32)); - *(uint32 *)out->pBuffer=htonl(Session); - NonSequencedPush(out); - - LogNetcode(_L "Sending OP_SessionDisconnect: session [{}]" __L, (unsigned long)Session); -} - -void EQStream::InboundQueuePush(EQRawApplicationPacket *p) -{ - MInboundQueue.lock(); - InboundQueue.push_back(p); - MInboundQueue.unlock(); -} - -EQApplicationPacket *EQStream::PopPacket() -{ -EQRawApplicationPacket *p=nullptr; - - MInboundQueue.lock(); - if (!InboundQueue.empty()) { - auto itr = InboundQueue.begin(); - p=*itr; - InboundQueue.erase(itr); - } - MInboundQueue.unlock(); - - if (p) { - if (OpMgr != nullptr && *OpMgr != nullptr) { - EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode); - if (emu_op == OP_Unknown) { - // Log(Logs::General, Logs::Client_Server_Packet_Unhandled, "Unknown :: [%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->opcode, p->Size(), DumpPacketToString(p).c_str()); - } - p->SetOpcode(emu_op); - } - } - - return p; -} - -EQRawApplicationPacket *EQStream::PopRawPacket() -{ -EQRawApplicationPacket *p=nullptr; - - MInboundQueue.lock(); - if (!InboundQueue.empty()) { - auto itr = InboundQueue.begin(); - p=*itr; - InboundQueue.erase(itr); - } - MInboundQueue.unlock(); - - //resolve the opcode if we can. - if(p) { - if(OpMgr != nullptr && *OpMgr != nullptr) { - EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode); - if(emu_op == OP_Unknown) { - LogNetcode("Unable to convert EQ opcode {:#04x} to an Application opcode", p->opcode); - } - - p->SetOpcode(emu_op); - } - } - - return p; -} - -EQRawApplicationPacket *EQStream::PeekPacket() -{ -EQRawApplicationPacket *p=nullptr; - - MInboundQueue.lock(); - if (!InboundQueue.empty()) { - auto itr = InboundQueue.begin(); - p=*itr; - } - MInboundQueue.unlock(); - - return p; -} - -void EQStream::InboundQueueClear() -{ -EQApplicationPacket *p=nullptr; - - LogNetcode(_L "Clearing inbound queue" __L); - - MInboundQueue.lock(); - if (!InboundQueue.empty()) { - std::vector::iterator itr; - for(itr=InboundQueue.begin();itr!=InboundQueue.end();++itr) { - p=*itr; - delete p; - } - InboundQueue.clear(); - } - MInboundQueue.unlock(); -} - -bool EQStream::HasOutgoingData() -{ -bool flag; - - //once closed, we have nothing more to say - if(CheckClosed()) - return(false); - - MOutboundQueue.lock(); - flag=(!NonSequencedQueue.empty()); - if (!flag) { - //not only wait until we send it all, but wait until they ack everything. - flag = !SequencedQueue.empty(); - } - MOutboundQueue.unlock(); - - if (!flag) { - MAcks.lock(); - flag= (NextAckToSend>LastAckSent); - MAcks.unlock(); - } - - return flag; -} - -void EQStream::OutboundQueueClear() -{ -EQProtocolPacket *p=nullptr; - - LogNetcode(_L "Clearing outbound queue" __L); - - MOutboundQueue.lock(); - while(!NonSequencedQueue.empty()) { - delete NonSequencedQueue.front(); - NonSequencedQueue.pop(); - } - if(!SequencedQueue.empty()) { - std::deque::iterator itr; - for(itr=SequencedQueue.begin();itr!=SequencedQueue.end();++itr) { - p=*itr; - delete p; - } - SequencedQueue.clear(); - } - MOutboundQueue.unlock(); -} - -void EQStream::PacketQueueClear() -{ -EQProtocolPacket *p=nullptr; - - LogNetcode(_L "Clearing future packet queue" __L); - - if(!PacketQueue.empty()) { - std::map::iterator itr; - for(itr=PacketQueue.begin();itr!=PacketQueue.end();++itr) { - p=itr->second; - delete p; - } - PacketQueue.clear(); - } -} - -void EQStream::Process(const unsigned char *buffer, const uint32 length) -{ - static unsigned char newbuffer[2048]; - uint32 newlength=0; - if (EQProtocolPacket::ValidateCRC(buffer,length,Key)) { - if (compressed) { - newlength=EQProtocolPacket::Decompress(buffer,length,newbuffer,2048); - } else { - memcpy(newbuffer,buffer,length); - newlength=length; - if (encoded) - EQProtocolPacket::ChatDecode(newbuffer,newlength-2,Key); - } - if (buffer[1]!=0x01 && buffer[1]!=0x02 && buffer[1]!=0x1d) - newlength-=2; - EQProtocolPacket *p = MakeProtocolPacket(newbuffer,newlength); - ProcessPacket(p); - delete p; - ProcessQueue(); - } else { - LogNetcode(_L "Incoming packet failed checksum" __L); - } -} - -long EQStream::GetNextAckToSend() -{ - MAcks.lock(); - long l=NextAckToSend; - MAcks.unlock(); - - return l; -} - -long EQStream::GetLastAckSent() -{ - MAcks.lock(); - long l=LastAckSent; - MAcks.unlock(); - - return l; -} - -void EQStream::AckPackets(uint16 seq) -{ -std::deque::iterator itr, tmp; - - MOutboundQueue.lock(); - - SeqOrder ord = CompareSequence(SequencedBase, seq); - if(ord == SeqInOrder) { - //they are not acking anything new... - LogNetcode(_L "Received an ack with no window advancement (seq [{}])" __L, seq); - } else if(ord == SeqPast) { - //they are nacking blocks going back before our buffer, wtf? - LogNetcode(_L "Received an ack with backward window advancement (they gave [{}], our window starts at [{}]). This is bad" __L, seq, SequencedBase); - } else { - LogNetcode(_L "Received an ack up through sequence [{}]. Our base is [{}]" __L, seq, SequencedBase); - - - //this is a good ack, we get to ack some blocks. - seq++; //we stop at the block right after their ack, counting on the wrap of both numbers. - while(SequencedBase != seq) { - if(SequencedQueue.empty()) { - LogNetcode(_L "OUT OF PACKETS acked packet with sequence [{}]. Next send is [{}] before this" __L, (unsigned long)SequencedBase, SequencedQueue.size()); - SequencedBase = NextOutSeq; - break; - } - LogNetcode(_L "Removing acked packet with sequence [{}]" __L, (unsigned long)SequencedBase); - //clean out the acked packet - delete SequencedQueue.front(); - SequencedQueue.pop_front(); - //advance the base sequence number to the seq of the block after the one we just got rid of. - SequencedBase++; - } - if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - LogNetcode(_L "Post-Ack on [{}] Invalid Sequenced queue: BS [{}] + SQ [{}] != NOS [{}]" __L, seq, SequencedBase, SequencedQueue.size(), NextOutSeq); - } - } - - MOutboundQueue.unlock(); -} - -void EQStream::SetNextAckToSend(uint32 seq) -{ - MAcks.lock(); - LogNetcode(_L "Set Next Ack To Send to [{}]" __L, (unsigned long)seq); - NextAckToSend=seq; - MAcks.unlock(); -} - -void EQStream::SetLastAckSent(uint32 seq) -{ - MAcks.lock(); - LogNetcode(_L "Set Last Ack Sent to [{}]" __L, (unsigned long)seq); - LastAckSent=seq; - MAcks.unlock(); -} - -void EQStream::ProcessQueue() -{ - if(PacketQueue.empty()) { - return; - } - - EQProtocolPacket *qp=nullptr; - while((qp=RemoveQueue(NextInSeq))!=nullptr) { - LogNetcode(_L "Processing Queued Packet: Seq=[{}]" __L, NextInSeq); - ProcessPacket(qp); - delete qp; - LogNetcode(_L "OP_Packet Queue size=[{}]" __L, PacketQueue.size()); - } -} - -EQProtocolPacket *EQStream::RemoveQueue(uint16 seq) -{ -std::map::iterator itr; -EQProtocolPacket *qp=nullptr; - if ((itr=PacketQueue.find(seq))!=PacketQueue.end()) { - qp=itr->second; - PacketQueue.erase(itr); - LogNetcode(_L "OP_Packet Queue size=[{}]" __L, PacketQueue.size()); - } - return qp; -} - -void EQStream::SetStreamType(EQStreamType type) -{ - LogNetcode(_L "Changing stream type from [{}] to [{}]" __L, StreamTypeString(StreamType), StreamTypeString(type)); - StreamType=type; - switch (StreamType) { - case LoginStream: - app_opcode_size=1; - compressed=false; - encoded=false; - LogNetcode(_L "Login stream has app opcode size [{}], is not compressed or encoded" __L, app_opcode_size); - break; - case ChatOrMailStream: - case ChatStream: - case MailStream: - app_opcode_size=1; - compressed=false; - encoded=true; - LogNetcode(_L "Chat/Mail stream has app opcode size [{}], is not compressed, and is encoded" __L, app_opcode_size); - break; - case ZoneStream: - case WorldStream: - default: - app_opcode_size=2; - compressed=true; - encoded=false; - LogNetcode(_L "World/Zone stream has app opcode size [{}], is compressed, and is not encoded" __L, app_opcode_size); - break; - } -} - -const char *EQStream::StreamTypeString(EQStreamType t) -{ - switch (t) { - case LoginStream: - return "Login"; - break; - case WorldStream: - return "World"; - break; - case ZoneStream: - return "Zone"; - break; - case ChatOrMailStream: - return "Chat/Mail"; - break; - case ChatStream: - return "Chat"; - break; - case MailStream: - return "Mail"; - break; - case UnknownStream: - return "Unknown"; - break; - } - return "UnknownType"; -} - -//returns SeqFuture if `seq` is later than `expected_seq` -EQStream::SeqOrder EQStream::CompareSequence(uint16 expected_seq , uint16 seq) -{ - if (expected_seq==seq) { - // Curent - return SeqInOrder; - } else if ((seq > expected_seq && (uint32)seq < ((uint32)expected_seq + EQStream::MaxWindowSize)) || seq < (expected_seq - EQStream::MaxWindowSize)) { - // Future - return SeqFuture; - } else { - // Past - return SeqPast; - } -} - -void EQStream::SetState(EQStreamState state) { - MState.lock(); - LogNetcode(_L "Changing state from [{}] to [{}]" __L, State, state); - State=state; - MState.unlock(); -} - - -void EQStream::CheckTimeout(uint32 now, uint32 timeout) { - - bool outgoing_data = HasOutgoingData(); //up here to avoid recursive locking - - EQStreamState orig_state = GetState(); - if (orig_state == CLOSING && !outgoing_data) { - LogNetcode(_L "Out of data in closing state, disconnecting" __L); - _SendDisconnect(); - SetState(DISCONNECTING); - } else if (LastPacket && (now-LastPacket) > timeout) { - switch(orig_state) { - case CLOSING: - //if we time out in the closing state, they are not acking us, just give up - LogNetcode(_L "Timeout expired in closing state. Moving to closed state" __L); - _SendDisconnect(); - SetState(CLOSED); - break; - case DISCONNECTING: - //we timed out waiting for them to send us the disconnect reply, just give up. - LogNetcode(_L "Timeout expired in disconnecting state. Moving to closed state" __L); - SetState(CLOSED); - break; - case CLOSED: - LogNetcode(_L "Timeout expired in closed state??" __L); - break; - case ESTABLISHED: - //we timed out during normal operation. Try to be nice about it. - //we will almost certainly time out again waiting for the disconnect reply, but oh well. - LogNetcode(_L "Timeout expired in established state. Closing connection" __L); - _SendDisconnect(); - SetState(DISCONNECTING); - break; - default: - break; - } - } -} - -void EQStream::Decay() -{ - MRate.lock(); - uint32 rate=DecayRate; - MRate.unlock(); - if (BytesWritten>0) { - BytesWritten-=rate; - if (BytesWritten<0) - BytesWritten=0; - } - // check for any timed out acks - if ((GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) && RETRANSMIT_TIMEOUT_MULT && retransmittimeout) { - int count = 0; - MOutboundQueue.lock(); - for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end(); ++sitr, count++) { - if (!(*sitr)->acked && (*sitr)->sent_time > 0 && ((*sitr)->sent_time + retransmittimeout) < Timer::GetCurrentTime()) { - (*sitr)->sent_time = 0; - LogNetcode(_L "Timeout exceeded for seq [{}]. Flagging packet for retransmission" __L, SequencedBase + count); - } - } - MOutboundQueue.unlock(); - } -} - -void EQStream::AdjustRates(uint32 average_delta) -{ - if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - if (average_delta && (average_delta <= AVERAGE_DELTA_MAX)) { - MRate.lock(); - AverageDelta = average_delta; - RateThreshold=RATEBASE/average_delta; - DecayRate=DECAYBASE/average_delta; - if (BytesWritten > RateThreshold) - BytesWritten = RateThreshold + DecayRate; - Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, - RateThreshold, DecayRate, average_delta); - MRate.unlock(); - } else { - Log(Logs::Detail, Logs::Netcode, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L, - average_delta, AVERAGE_DELTA_MAX); - AverageDelta = AVERAGE_DELTA_MAX; - } - } else { - if (average_delta) { - MRate.lock(); - AverageDelta = average_delta; - BytesWritten = 0; - RateThreshold=RATEBASE/average_delta; - DecayRate=DECAYBASE/average_delta; - Log(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, - RateThreshold, DecayRate, average_delta); - MRate.unlock(); - } - } -} - -void EQStream::Close() { - if(HasOutgoingData()) { - //there is pending data, wait for it to go out. - LogNetcode(_L "Stream requested to Close(), but there is pending data, waiting for it" __L); - SetState(CLOSING); - } else { - //otherwise, we are done, we can drop immediately. - _SendDisconnect(); - LogNetcode(_L "Stream closing immediate due to Close()" __L); - SetState(DISCONNECTING); - } -} - - -//this could be expanded to check more than the fitst opcode if -//we needed more complex matching -EQStream::MatchState EQStream::CheckSignature(const Signature *sig) { - EQRawApplicationPacket *p = nullptr; - MatchState res = MatchNotReady; - - MInboundQueue.lock(); - if (!InboundQueue.empty()) { - //this is already getting hackish... - p = InboundQueue.front(); - if(sig->ignore_eq_opcode != 0 && p->opcode == sig->ignore_eq_opcode) { - if(InboundQueue.size() > 1) { - p = InboundQueue[1]; - } else { - p = nullptr; - } - } - if(p == nullptr) { - //first opcode is ignored, and nothing else remains... keep waiting - } else if(p->opcode == sig->first_eq_opcode) { - //opcode matches, check length.. - if(p->size == sig->first_length) { - LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode matched {:#04x} and length matched [{}]", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size); - res = MatchSuccessful; - } else if(sig->first_length == 0) { - LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode matched {:#04x} and length ([{}]) is ignored", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size); - res = MatchSuccessful; - } else { - //opcode matched but length did not. - LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode matched {:#04x}, but length [{}] did not match expected [{}]", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size, sig->first_length); - res = MatchFailed; - } - } else { - //first opcode did not match.. - LogNetcode("[StreamIdentify] [{}]:[{}]: First opcode {:#04x} did not match expected {:#04x}", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), p->opcode, sig->first_eq_opcode); - res = MatchFailed; - } - } - MInboundQueue.unlock(); - - return(res); -} diff --git a/common/eq_stream.h b/common/eq_stream.h deleted file mode 100644 index 23ec89b7f0..0000000000 --- a/common/eq_stream.h +++ /dev/null @@ -1,314 +0,0 @@ -#pragma once - -#include "common/eq_packet.h" -#include "common/eq_stream_intf.h" -#include "common/eq_stream_type.h" -#include "common/misc.h" -#include "common/mutex.h" -#include "common/opcodemgr.h" -#include "common/timer.h" - -#include -#include -#include -#include - -#ifndef WIN32 -#include -#endif - -class EQApplicationPacket; -class EQProtocolPacket; - -#define FLAG_COMPRESSED 0x01 -#define FLAG_ENCODED 0x04 - -#ifndef RATEBASE -#define RATEBASE 1048576 -#endif - -#ifndef DECAYBASE -#define DECAYBASE 78642 -#endif - -#ifndef RETRANSMIT_TIMEOUT_MULT -#define RETRANSMIT_TIMEOUT_MULT 3.0 -#endif - -#ifndef RETRANSMIT_TIMEOUT_MAX -#define RETRANSMIT_TIMEOUT_MAX 5000 -#endif - -#ifndef AVERAGE_DELTA_MAX -#define AVERAGE_DELTA_MAX 2500 -#endif - -#ifndef RETRANSMIT_ACKED_PACKETS -#define RETRANSMIT_ACKED_PACKETS true -#endif - -#ifndef MAX_SESSION_RETRIES -#define MAX_SESSION_RETRIES 30 -#endif - -#pragma pack(1) -struct SessionRequest { - uint32 UnknownA; - uint32 Session; - uint32 MaxLength; -}; - -struct SessionResponse { - uint32 Session; - uint32 Key; - uint8 UnknownA; - uint8 Format; - uint8 UnknownB; - uint32 MaxLength; - uint32 UnknownD; -}; - -//Deltas are in ms, representing round trip times -struct ClientSessionStats { -/*000*/ uint16 RequestID; -/*002*/ uint32 last_local_delta; -/*006*/ uint32 average_delta; -/*010*/ uint32 low_delta; -/*014*/ uint32 high_delta; -/*018*/ uint32 last_remote_delta; -/*022*/ uint64 packets_sent; -/*030*/ uint64 packets_received; -/*038*/ -}; - -struct ServerSessionStats { -/*000*/ uint16 RequestID; -/*002*/ uint32 ServerTime; -/*006*/ uint64 packets_sent_echo; -/*014*/ uint64 packets_received_echo; -/*022*/ uint64 packets_sent; -/*030*/ uint64 packets_received; -/*038*/ -}; - -#pragma pack() - -class OpcodeManager; -class EQRawApplicationPacket; - -class EQStream : public EQStreamInterface { - friend class EQStreamPair; //for collector. - protected: - typedef enum { - SeqPast, - SeqInOrder, - SeqFuture - } SeqOrder; - - uint32 remote_ip; - uint16 remote_port; - uint8 buffer[8192]; - unsigned char *oversize_buffer; - uint32 oversize_offset,oversize_length; - uint8 app_opcode_size; - EQStreamType StreamType; - bool compressed,encoded; - uint32 retransmittimer; - uint32 retransmittimeout; - - uint16 sessionAttempts; - bool streamactive; - - //uint32 buffer_len; - - uint32 Session, Key; - uint16 NextInSeq; - uint32 MaxLen; - uint16 MaxSends; - - uint8 active_users; //how many things are actively using this - Mutex MInUse; - - EQStreamState State; - Mutex MState; - - uint32 LastPacket; - Mutex MVarlock; - - // Ack sequence tracking. - long NextAckToSend; - long LastAckSent; - long GetNextAckToSend(); - long GetLastAckSent(); - void AckPackets(uint16 seq); - void SetNextAckToSend(uint32); - void SetLastAckSent(uint32); - - Mutex MAcks; - - // Packets waiting to be sent (all protected by MOutboundQueue) - std::queue NonSequencedQueue; - std::deque SequencedQueue; - uint16 NextOutSeq; - uint16 SequencedBase; //the sequence number of SequencedQueue[0] - Mutex MOutboundQueue; - - //a buffer we use for compression/decompression - unsigned char _tempBuffer[2048]; - - // Packets waiting to be processed - std::vector InboundQueue; - std::map PacketQueue; //not mutex protected, only accessed by caller of Process() - Mutex MInboundQueue; - - static uint16 MaxWindowSize; - - int32 BytesWritten; - - uint64 sent_packet_count; - uint64 received_packet_count; - - Mutex MRate; - int32 RateThreshold; - int32 DecayRate; - uint32 AverageDelta; - - OpcodeManager **OpMgr; - - EQRawApplicationPacket *MakeApplicationPacket(EQProtocolPacket *p); - EQRawApplicationPacket *MakeApplicationPacket(const unsigned char *buf, uint32 len); - EQProtocolPacket *MakeProtocolPacket(const unsigned char *buf, uint32 len); - void SendPacket(uint16 opcode, EQApplicationPacket *p); - - void SetState(EQStreamState state); - - void SendSessionResponse(); - void SendSessionRequest(); - void SendAck(uint16 seq); - void SendOutOfOrderAck(uint16 seq); - void QueuePacket(EQProtocolPacket *p); - void SendPacket(EQProtocolPacket *p); - void NonSequencedPush(EQProtocolPacket *p); - void SequencedPush(EQProtocolPacket *p); - void WritePacket(int fd,EQProtocolPacket *p); - - - uint32 GetKey() { return Key; } - void SetKey(uint32 k) { Key=k; } - void SetSession(uint32 s) { Session=s; } - - void ProcessPacket(EQProtocolPacket *p); - - bool Stale(uint32 now, uint32 timeout=30) { return (LastPacket && (now-LastPacket) > timeout); } - - void InboundQueuePush(EQRawApplicationPacket *p); - EQRawApplicationPacket *PeekPacket(); //for collector. - EQRawApplicationPacket *PopRawPacket(); //for collector. - - void InboundQueueClear(); - void OutboundQueueClear(); - void PacketQueueClear(); - - void ProcessQueue(); - EQProtocolPacket *RemoveQueue(uint16 seq); - - void _SendDisconnect(); - - void init(bool resetSession=true); - public: - EQStream() { init(); remote_ip = 0; remote_port = 0; State = UNESTABLISHED; - StreamType = UnknownStream; compressed = true; encoded = false; app_opcode_size = 2; - bytes_sent = 0; bytes_recv = 0; create_time = Timer::GetTimeSeconds(); sessionAttempts = 0; - streamactive = false; } - EQStream(sockaddr_in addr) { init(); remote_ip = addr.sin_addr.s_addr; - remote_port = addr.sin_port; State = UNESTABLISHED; StreamType = UnknownStream; - compressed = true; encoded = false; app_opcode_size = 2; bytes_sent = 0; bytes_recv = 0; - create_time = Timer::GetTimeSeconds(); } - virtual ~EQStream() { RemoveData(); SetState(CLOSED); } - void SetMaxLen(uint32 length) { MaxLen=length; } - - //interface used by application (EQStreamInterface) - virtual void QueuePacket(const EQApplicationPacket *p, bool ack_req=true); - virtual void FastQueuePacket(EQApplicationPacket **p, bool ack_req=true); - virtual EQApplicationPacket *PopPacket(); - virtual void Close(); - virtual uint32 GetRemoteIP() const { return remote_ip; } - virtual uint16 GetRemotePort() const { return remote_port; } - virtual void ReleaseFromUse() { MInUse.lock(); if(active_users > 0) active_users--; MInUse.unlock(); } - virtual void RemoveData() { InboundQueueClear(); OutboundQueueClear(); PacketQueueClear(); /*if (CombinedAppPacket) delete CombinedAppPacket;*/ } - virtual bool CheckState(EQStreamState state) { return GetState() == state; } - virtual std::string Describe() const { return("Direct EQStream"); } - - virtual void SetOpcodeManager(OpcodeManager **opm) { OpMgr = opm; } - - virtual OpcodeManager* GetOpcodeManager() const - { - return (*OpMgr); - }; - - void CheckTimeout(uint32 now, uint32 timeout=30); - bool HasOutgoingData(); - void Process(const unsigned char *data, const uint32 length); - void SetLastPacketTime(uint32 t) {LastPacket=t;} - void Write(int eq_fd); - - // whether or not the stream has been assigned (we passed our stream match) - virtual void SetActive(bool val) { streamactive = val; } - - // - inline bool IsInUse() { bool flag; MInUse.lock(); flag=(active_users>0); MInUse.unlock(); return flag; } - inline void PutInUse() { MInUse.lock(); active_users++; MInUse.unlock(); } - - virtual EQStreamState GetState() { EQStreamState s; MState.lock(); s=State; MState.unlock(); return s; } - - static SeqOrder CompareSequence(uint16 expected_seq , uint16 seq); - - bool CheckActive() { return GetState()==ESTABLISHED; } - bool CheckClosed() { return GetState()==CLOSED; } - void SetOpcodeSize(uint8 s) { app_opcode_size = s; } - void SetStreamType(EQStreamType t); - inline const EQStreamType GetStreamType() const { return StreamType; } - static const char *StreamTypeString(EQStreamType t); - - void Decay(); - void AdjustRates(uint32 average_delta); - - uint32 bytes_sent; - uint32 bytes_recv; - uint32 create_time; - - void AddBytesSent(uint32 bytes) - { - bytes_sent += bytes; - ++sent_packet_count; - } - - void AddBytesRecv(uint32 bytes) - { - bytes_recv += bytes; - ++received_packet_count; - } - - virtual const uint32 GetBytesSent() const { return bytes_sent; } - virtual const uint32 GetBytesRecieved() const { return bytes_recv; } - virtual const uint32 GetBytesSentPerSecond() const - { - if((Timer::GetTimeSeconds() - create_time) == 0) - return 0; - return bytes_sent / (Timer::GetTimeSeconds() - create_time); - } - - virtual const uint32 GetBytesRecvPerSecond() const - { - if((Timer::GetTimeSeconds() - create_time) == 0) - return 0; - return bytes_recv / (Timer::GetTimeSeconds() - create_time); - } - - const uint64 GetPacketsSent() { return sent_packet_count; } - const uint64 GetPacketsReceived() { return received_packet_count; } - - //used for dynamic stream identification - virtual MatchState CheckSignature(const Signature *sig); - -}; diff --git a/common/eq_stream_factory.cpp b/common/eq_stream_factory.cpp deleted file mode 100644 index 470ac5b73d..0000000000 --- a/common/eq_stream_factory.cpp +++ /dev/null @@ -1,298 +0,0 @@ -#include "eq_stream_factory.h" - -#include "common/global_define.h" -#ifdef _WINDOWS -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#endif - -#include -#include - -#include "op_codes.h" - -ThreadReturnType EQStreamFactoryReaderLoop(void *eqfs) -{ - EQStreamFactory *fs=(EQStreamFactory *)eqfs; - - fs->ReaderLoop(); - - THREAD_RETURN(nullptr); -} - -ThreadReturnType EQStreamFactoryWriterLoop(void *eqfs) -{ - EQStreamFactory *fs=(EQStreamFactory *)eqfs; - - fs->WriterLoop(); - - THREAD_RETURN(nullptr); -} - -EQStreamFactory::EQStreamFactory(EQStreamType type, int port, uint32 timeout) - : Timeoutable(5000), stream_timeout(timeout) -{ - StreamType=type; - Port=port; - sock=-1; -} - -void EQStreamFactory::Close() -{ - Stop(); - -#ifdef _WINDOWS - closesocket(sock); -#else - close(sock); -#endif - sock=-1; -} - -bool EQStreamFactory::Open() -{ -struct sockaddr_in address; -#ifndef WIN32 - pthread_t t1,t2; -#endif - /* Setup internet address information. - This is used with the bind() call */ - memset((char *) &address, 0, sizeof(address)); - address.sin_family = AF_INET; - address.sin_port = htons(Port); - address.sin_addr.s_addr = htonl(INADDR_ANY); - - /* Setting up UDP port for new clients */ - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - return false; - } - - if (bind(sock, (struct sockaddr *) &address, sizeof(address)) < 0) { - close(sock); - sock=-1; - return false; - } - #ifdef _WINDOWS - unsigned long nonblock = 1; - ioctlsocket(sock, FIONBIO, &nonblock); - #else - fcntl(sock, F_SETFL, O_NONBLOCK); - #endif - //moved these because on windows the output was delayed and causing the console window to look bad - #ifdef _WINDOWS - _beginthread(EQStreamFactoryReaderLoop,0, this); - _beginthread(EQStreamFactoryWriterLoop,0, this); - #else - pthread_create(&t1,nullptr,EQStreamFactoryReaderLoop,this); - pthread_create(&t2,nullptr,EQStreamFactoryWriterLoop,this); - #endif - return true; -} - -std::shared_ptr EQStreamFactory::Pop() -{ - std::shared_ptr s = nullptr; - MNewStreams.lock(); - if (!NewStreams.empty()) { - s = NewStreams.front(); - NewStreams.pop(); - s->PutInUse(); - } - MNewStreams.unlock(); - - return s; -} - -void EQStreamFactory::Push(std::shared_ptr s) -{ - MNewStreams.lock(); - NewStreams.push(s); - MNewStreams.unlock(); -} - -void EQStreamFactory::ReaderLoop() -{ - fd_set readset; - std::map, std::shared_ptr>::iterator stream_itr; - int num; - int length; - unsigned char buffer[2048]; - sockaddr_in from; - int socklen = sizeof(sockaddr_in); - timeval sleep_time; - ReaderRunning = true; - - while(sock!=-1) { - MReaderRunning.lock(); - if (!ReaderRunning) - break; - MReaderRunning.unlock(); - - FD_ZERO(&readset); - FD_SET(sock,&readset); - - sleep_time.tv_sec=30; - sleep_time.tv_usec=0; - if ((num=select(sock+1,&readset,nullptr,nullptr,&sleep_time))<0) { - // What do we wanna do? - continue; - } else if (num==0) - continue; - - if(sock == -1) - break; //somebody closed us while we were sleeping. - - if (FD_ISSET(sock,&readset)) { -#ifdef _WINDOWS - if ((length=recvfrom(sock,(char*)buffer,sizeof(buffer),0,(struct sockaddr*)&from,(int *)&socklen)) < 2) -#else - if ((length=recvfrom(sock,buffer,2048,0,(struct sockaddr *)&from,(socklen_t *)&socklen)) < 2) -#endif - { - // What do we wanna do? - } else { - MStreams.lock(); - stream_itr = Streams.find(std::make_pair(from.sin_addr.s_addr, from.sin_port)); - if (stream_itr == Streams.end()) { - if (buffer[1]==OP_SessionRequest) { - std::shared_ptr s = std::make_shared(from); - s->SetStreamType(StreamType); - Streams[std::make_pair(from.sin_addr.s_addr, from.sin_port)]=s; - WriterWork.Signal(); - Push(s); - s->AddBytesRecv(length); - s->Process(buffer,length); - s->SetLastPacketTime(Timer::GetCurrentTime()); - } - MStreams.unlock(); - } else { - std::shared_ptr curstream = stream_itr->second; - //dont bother processing incoming packets for closed connections - if(curstream->CheckClosed()) - curstream = nullptr; - else - curstream->PutInUse(); - //the in use flag prevents the stream from being deleted while we are using it. - - if(curstream) { - curstream->AddBytesRecv(length); - curstream->Process(buffer,length); - curstream->SetLastPacketTime(Timer::GetCurrentTime()); - curstream->ReleaseFromUse(); - } - MStreams.unlock(); - } - } - } - } -} - -void EQStreamFactory::CheckTimeout() -{ - //lock streams the entire time were checking timeouts, it should be fast. - MStreams.lock(); - - unsigned long now=Timer::GetCurrentTime(); - std::map, std::shared_ptr>::iterator stream_itr; - - for(stream_itr = Streams.begin(); stream_itr != Streams.end();) { - std::shared_ptr s = stream_itr->second; - - s->CheckTimeout(now, stream_timeout); - - EQStreamState state = s->GetState(); - - //not part of the else so we check it right away on state change - if (state==CLOSED) { - if (s->IsInUse()) { - //give it a little time for everybody to finish with it - } else { - //everybody is done, we can delete it now - auto temp = stream_itr; - ++stream_itr; - temp->second = nullptr; - Streams.erase(temp); - continue; - } - } - - ++stream_itr; - } - MStreams.unlock(); -} - -void EQStreamFactory::WriterLoop() -{ - bool havework = true; - std::vector> wants_write; - std::vector>::iterator cur, end; - bool decay = false; - uint32 stream_count; - Timer DecayTimer(20); - WriterRunning = true; - DecayTimer.Enable(); - - while (sock != -1) { - MWriterRunning.lock(); - if (!WriterRunning) - break; - MWriterRunning.unlock(); - - havework = false; - wants_write.clear(); - - decay = DecayTimer.Check(); - - // copy streams into a seperate list so we dont have to keep - // MStreams locked while we are writting - MStreams.lock(); - for (auto stream_itr = Streams.begin(); stream_itr != Streams.end(); ++stream_itr) { - // If it's time to decay the bytes sent, then let's do it before we try to write - if (decay) - stream_itr->second->Decay(); - - // bullshit checking, to see if this is really happening, GDB seems to think so... - if (stream_itr->second == nullptr) { - fprintf(stderr, - "ERROR: nullptr Stream encountered in EQStreamFactory::WriterLoop for: %i:%i", - stream_itr->first.first, stream_itr->first.second); - continue; - } - - if (stream_itr->second->HasOutgoingData()) { - havework = true; - stream_itr->second->PutInUse(); - wants_write.push_back(stream_itr->second); - } - } - MStreams.unlock(); - - // do the actual writes - cur = wants_write.begin(); - end = wants_write.end(); - for (; cur != end; ++cur) { - (*cur)->Write(sock); - (*cur)->ReleaseFromUse(); - } - - Sleep(10); - - MStreams.lock(); - stream_count = Streams.size(); - MStreams.unlock(); - if (!stream_count) { - WriterWork.Wait(); - } - } -} - diff --git a/common/eq_stream_factory.h b/common/eq_stream_factory.h deleted file mode 100644 index 2aa2b56e48..0000000000 --- a/common/eq_stream_factory.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include "common/condition.h" -#include "common/eq_stream.h" -#include "common/timeoutmgr.h" - -#include -#include -#include - -class EQStream; -class Timer; - -class EQStreamFactory : private Timeoutable { - private: - int sock; - int Port; - - bool ReaderRunning; - Mutex MReaderRunning; - bool WriterRunning; - Mutex MWriterRunning; - - Condition WriterWork; - - EQStreamType StreamType; - - std::queue> NewStreams; - Mutex MNewStreams; - - std::map, std::shared_ptr> Streams; - Mutex MStreams; - - virtual void CheckTimeout(); - - Timer *DecayTimer; - - uint32 stream_timeout; - - public: - EQStreamFactory(EQStreamType type, uint32 timeout = 135000) : Timeoutable(5000), stream_timeout(timeout) { ReaderRunning=false; WriterRunning=false; StreamType=type; sock=-1; } - EQStreamFactory(EQStreamType type, int port, uint32 timeout = 135000); - - std::shared_ptr Pop(); - void Push(std::shared_ptr s); - - bool Open(); - bool Open(unsigned long port) { Port=port; return Open(); } - bool IsOpen() { return sock!=-1; } - void Close(); - void ReaderLoop(); - void WriterLoop(); - void Stop() { StopReader(); StopWriter(); } - void StopReader() { MReaderRunning.lock(); ReaderRunning=false; MReaderRunning.unlock(); } - void StopWriter() { MWriterRunning.lock(); WriterRunning=false; MWriterRunning.unlock(); WriterWork.Signal(); } - void SignalWriter() { WriterWork.Signal(); } -}; diff --git a/common/eq_stream_type.h b/common/eq_stream_type.h deleted file mode 100644 index 267dcf2b34..0000000000 --- a/common/eq_stream_type.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -typedef enum { - UnknownStream=0, - LoginStream, - WorldStream, - ZoneStream, - ChatOrMailStream, - ChatStream, - MailStream -} EQStreamType; - diff --git a/common/guilds.cpp b/common/guilds.cpp deleted file mode 100644 index 09e92f39b7..0000000000 --- a/common/guilds.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) - - 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 "guilds.h" - -#include "common/database.h" -#include "common/eq_packet_structs.h" -#include "common/global_define.h" -#include "common/misc_functions.h" - -#ifndef WIN32 -#include //for htonl -#endif \ No newline at end of file diff --git a/common/tcp_connection.cpp b/common/tcp_connection.cpp deleted file mode 100644 index 3a44399116..0000000000 --- a/common/tcp_connection.cpp +++ /dev/null @@ -1,942 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 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 -*/ - -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" - -#include -#include -#include - -#include "tcp_connection.h" - -#ifdef FREEBSD //Timothy Whitman - January 7, 2003 - #define MSG_NOSIGNAL 0 -#endif -#ifdef DARWIN - #define MSG_NOSIGNAL SO_NOSIGPIPE // Corysia Taware - Sept. 27, 2013 - // See http://lists.apple.com/archives/macnetworkprog/2002/Dec/msg00091.html -#endif // DARWIN - -#ifdef _WINDOWS -InitWinsock winsock; -#endif - -#define LOOP_GRANULARITY 3 //# of ms between checking our socket/queues - -#define TCPN_DEBUG 0 -#define TCPN_DEBUG_Console 0 -#define TCPN_DEBUG_Memory 0 -#define TCPN_LOG_RAW_DATA_OUT 0 //1 = info, 2 = length limited dump, 3 = full dump -#define TCPN_LOG_RAW_DATA_IN 0 //1 = info, 2 = length limited dump, 3 = full dump - -//client version -TCPConnection::TCPConnection() -: ConnectionType(Outgoing), - connection_socket(0), - id(0), - rIP(0), - rPort(0) -{ - pState = TCPS_Ready; - pFree = false; - pEcho = false; - recvbuf = nullptr; - sendbuf = nullptr; - pRunLoop = false; - charAsyncConnect = 0; - pAsyncConnect = false; - m_previousLineEnd = false; -#if TCPN_DEBUG_Memory >= 7 - std::cout << "Constructor #2 on outgoing TCP# " << GetID() << std::endl; -#endif -} - -//server version -TCPConnection::TCPConnection(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) -: ConnectionType(Incoming), - connection_socket(in_socket), - id(ID), - rIP(irIP), - rPort(irPort) -{ - pState = TCPS_Connected; - pFree = false; - pEcho = false; - recvbuf = nullptr; - sendbuf = nullptr; - pRunLoop = false; - charAsyncConnect = 0; - pAsyncConnect = false; - m_previousLineEnd = false; -#if TCPN_DEBUG_Memory >= 7 - std::cout << "Constructor #2 on incoming TCP# " << GetID() << std::endl; -#endif -} - -TCPConnection::~TCPConnection() { - FinishDisconnect(); - ClearBuffers(); - if (ConnectionType == Outgoing) { - MRunLoop.lock(); - pRunLoop = false; - MRunLoop.unlock(); - MLoopRunning.lock(); - MLoopRunning.unlock(); -#if TCPN_DEBUG_Memory >= 6 - std::cout << "Deconstructor on outgoing TCP# " << GetID() << std::endl; -#endif - } -#if TCPN_DEBUG_Memory >= 5 - else { - std::cout << "Deconstructor on incoming TCP# " << GetID() << std::endl; - } -#endif - safe_delete_array(recvbuf); - safe_delete_array(sendbuf); - safe_delete_array(charAsyncConnect); -} - -void TCPConnection::SetState(State_t in_state) { - MState.lock(); - pState = in_state; - MState.unlock(); -} - -TCPConnection::State_t TCPConnection::GetState() const { - State_t ret; - MState.lock(); - ret = pState; - MState.unlock(); - return ret; -} - -bool TCPConnection::GetSockName(char *host, uint16 *port) -{ - bool result=false; - LockMutex lock(&MState); - if (!Connected()) - return false; - - struct sockaddr_in local; - -#ifdef _WINDOWS - int addrlen; -#else -#ifdef FREEBSD - socklen_t addrlen; -#else - size_t addrlen; -#endif -#endif - addrlen=sizeof(struct sockaddr_in); -#ifdef _WINDOWS - if (!getsockname(connection_socket,(struct sockaddr *)&local,&addrlen)) { -#else - if (!getsockname(connection_socket,(struct sockaddr *)&local,(socklen_t *)&addrlen)) { -#endif - unsigned long ip=local.sin_addr.s_addr; - sprintf(host,"%d.%d.%d.%d", - *(unsigned char *)&ip, - *((unsigned char *)&ip+1), - *((unsigned char *)&ip+2), - *((unsigned char *)&ip+3)); - *port=ntohs(local.sin_port); - - result=true; - } - - return result; -} - -void TCPConnection::Free() { - Disconnect(); - pFree = true; -} - -bool TCPConnection::Send(const uchar* data, int32 size) { - if (!Connected()) - return false; - if (!size) - return true; - ServerSendQueuePushEnd(data, size); - return true; -} - -void TCPConnection::ServerSendQueuePushEnd(const uchar* data, int32 size) { - MSendQueue.lock(); - if (sendbuf == nullptr) { - sendbuf = new uchar[size]; - sendbuf_size = size; - sendbuf_used = 0; - } - else if (size > (sendbuf_size - sendbuf_used)) { - sendbuf_size += size + 1024; - auto tmp = new uchar[sendbuf_size]; - memcpy(tmp, sendbuf, sendbuf_used); - safe_delete_array(sendbuf); - sendbuf = tmp; - } - memcpy(&sendbuf[sendbuf_used], data, size); - sendbuf_used += size; - MSendQueue.unlock(); -} - -void TCPConnection::ServerSendQueuePushEnd(uchar** data, int32 size) { - MSendQueue.lock(); - if (sendbuf == 0) { - sendbuf = *data; - sendbuf_size = size; - sendbuf_used = size; - MSendQueue.unlock(); - *data = 0; - return; - } - if (size > (sendbuf_size - sendbuf_used)) { - sendbuf_size += size; - auto tmp = new uchar[sendbuf_size]; - memcpy(tmp, sendbuf, sendbuf_used); - safe_delete_array(sendbuf); - sendbuf = tmp; - } - memcpy(&sendbuf[sendbuf_used], *data, size); - sendbuf_used += size; - MSendQueue.unlock(); - safe_delete_array(*data); -} - -void TCPConnection::ServerSendQueuePushFront(uchar* data, int32 size) { - MSendQueue.lock(); - if (sendbuf == 0) { - sendbuf = new uchar[size]; - sendbuf_size = size; - sendbuf_used = 0; - } - else if (size > (sendbuf_size - sendbuf_used)) { - sendbuf_size += size; - auto tmp = new uchar[sendbuf_size]; - memcpy(&tmp[size], sendbuf, sendbuf_used); - safe_delete_array(sendbuf); - sendbuf = tmp; - } - memcpy(sendbuf, data, size); - sendbuf_used += size; - MSendQueue.unlock(); -} - -bool TCPConnection::ServerSendQueuePop(uchar** data, int32* size) { - bool ret; - if (!MSendQueue.trylock()) - return false; - if (sendbuf) { - *data = sendbuf; - *size = sendbuf_used; - sendbuf = 0; - ret = true; - } - else { - ret = false; - } - MSendQueue.unlock(); - return ret; -} - -bool TCPConnection::ServerSendQueuePopForce(uchar** data, int32* size) { - bool ret; - MSendQueue.lock(); - if (sendbuf) { - *data = sendbuf; - *size = sendbuf_used; - sendbuf = 0; - ret = true; - } - else { - ret = false; - } - MSendQueue.unlock(); - return ret; -} - -char* TCPConnection::PopLine() { - char* ret; - if (!MLineOutQueue.trylock()) - return 0; - ret = (char*) LineOutQueue.pop(); - MLineOutQueue.unlock(); - return ret; -} - -bool TCPConnection::LineOutQueuePush(char* line) { - MLineOutQueue.lock(); - LineOutQueue.push(line); - MLineOutQueue.unlock(); - return(false); -} - - -void TCPConnection::FinishDisconnect() { - MState.lock(); - if (connection_socket != INVALID_SOCKET && connection_socket != 0) { - if (pState == TCPS_Connected || pState == TCPS_Disconnecting || pState == TCPS_Disconnected) { - bool sent_something = false; - SendData(sent_something); - } - pState = TCPS_Closing; - shutdown(connection_socket, 0x01); - shutdown(connection_socket, 0x00); -#ifdef _WINDOWS - closesocket(connection_socket); -#else - close(connection_socket); -#endif - connection_socket = 0; - rIP = 0; - rPort = 0; - ClearBuffers(); - } - pState = TCPS_Disconnected; - MState.unlock(); -} - -void TCPConnection::Disconnect() { - MState.lock(); - if(pState == TCPS_Connected || pState == TCPS_Connecting) { - pState = TCPS_Disconnecting; - } - MState.unlock(); -} - -bool TCPConnection::GetAsyncConnect() { - bool ret; - MAsyncConnect.lock(); - ret = pAsyncConnect; - MAsyncConnect.unlock(); - return ret; -} - -bool TCPConnection::SetAsyncConnect(bool iValue) { - bool ret; - MAsyncConnect.lock(); - ret = pAsyncConnect; - pAsyncConnect = iValue; - MAsyncConnect.unlock(); - return ret; -} - -bool TCPConnection::ConnectReady() const { - State_t s = GetState(); - if (s != TCPS_Ready && s != TCPS_Disconnected) - return(false); - return(ConnectionType == Outgoing); -} - -void TCPConnection::AsyncConnect(const char* irAddress, uint16 irPort) { - safe_delete_array(charAsyncConnect); - charAsyncConnect = new char[strlen(irAddress) + 1]; - strcpy(charAsyncConnect, irAddress); - AsyncConnect((uint32) 0, irPort); -} - -void TCPConnection::AsyncConnect(uint32 irIP, uint16 irPort) { - if (ConnectionType != Outgoing) { - // If this code runs, we got serious problems - // Crash and burn. - return; - } - if(!ConnectReady()) { -#if TCPN_DEBUG > 0 - printf("Trying to do async connect in invalid state %s\n", GetState()); -#endif - return; - } - MAsyncConnect.lock(); - if (pAsyncConnect) { - MAsyncConnect.unlock(); -#if TCPN_DEBUG > 0 - printf("Trying to do async connect when already doing one.\n"); -#endif - return; - } -#if TCPN_DEBUG > 0 - printf("Start async connect.\n"); -#endif - pAsyncConnect = true; - if(irIP != 0) - safe_delete_array(charAsyncConnect); - rIP = irIP; - rPort = irPort; - MAsyncConnect.unlock(); - if (!pRunLoop) { - pRunLoop = true; -#ifdef _WINDOWS - _beginthread(TCPConnectionLoop, 0, this); -#else - pthread_t thread; - pthread_create(&thread, nullptr, TCPConnectionLoop, this); -#endif - } - return; -} - -bool TCPConnection::Connect(const char* irAddress, uint16 irPort, char* errbuf) { - if (errbuf) - errbuf[0] = 0; - uint32 tmpIP = ResolveIP(irAddress); - if (!tmpIP) { - if (errbuf) { -#ifdef _WINDOWS - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): Couldnt resolve hostname. Error: %i", WSAGetLastError()); -#else - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): Couldnt resolve hostname. Error #%i: %s", errno, strerror(errno)); -#endif - } - return false; - } - return ConnectIP(tmpIP, irPort, errbuf); -} - -bool TCPConnection::ConnectIP(uint32 in_ip, uint16 in_port, char* errbuf) { - if (errbuf) - errbuf[0] = 0; - if (ConnectionType != Outgoing) { - // If this code runs, we got serious problems - // Crash and burn. - return false; - } - MState.lock(); - if (ConnectReady()) { - pState = TCPS_Connecting; - } else { - MState.unlock(); - SetAsyncConnect(false); - return false; - } - MState.unlock(); - if (!pRunLoop) { - pRunLoop = true; -#ifdef _WINDOWS - _beginthread(TCPConnectionLoop, 0, this); -#else - pthread_t thread; - pthread_create(&thread, nullptr, TCPConnectionLoop, this); -#endif - } - - connection_socket = INVALID_SOCKET; - struct sockaddr_in server_sin; - //struct in_addr in; - - if ((connection_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET || connection_socket == 0) { -#ifdef _WINDOWS - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): Allocating socket failed. Error: %i", WSAGetLastError()); -#else - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): Allocating socket failed. Error: %s", strerror(errno)); -#endif - SetState(TCPS_Ready); - SetAsyncConnect(false); - return false; - } - server_sin.sin_family = AF_INET; - server_sin.sin_addr.s_addr = in_ip; - server_sin.sin_port = htons(in_port); - - // Establish a connection to the server socket. -#ifdef _WINDOWS - if (connect(connection_socket, (PSOCKADDR) &server_sin, sizeof (server_sin)) == SOCKET_ERROR) { - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): connect() failed. Error: %i", WSAGetLastError()); - closesocket(connection_socket); - connection_socket = 0; - SetState(TCPS_Ready); - SetAsyncConnect(false); - return false; - } -#else - if (connect(connection_socket, (struct sockaddr *) &server_sin, sizeof (server_sin)) == SOCKET_ERROR) { - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): connect() failed. Error: %s", strerror(errno)); - close(connection_socket); - connection_socket = 0; - SetState(TCPS_Ready); - SetAsyncConnect(false); - return false; - } -#endif - int bufsize = 64 * 1024; // 64kbyte recieve buffer, up from default of 8k - setsockopt(connection_socket, SOL_SOCKET, SO_RCVBUF, (char*) &bufsize, sizeof(bufsize)); -#ifdef _WINDOWS - unsigned long nonblocking = 1; - ioctlsocket(connection_socket, FIONBIO, &nonblocking); -#else - fcntl(connection_socket, F_SETFL, O_NONBLOCK); -#endif - - SetEcho(false); - ClearBuffers(); - - rIP = in_ip; - rPort = in_port; - SetState(TCPS_Connected); - SetAsyncConnect(false); - return true; -} - -void TCPConnection::ClearBuffers() { - LockMutex lock1(&MSendQueue); - LockMutex lock3(&MRunLoop); - LockMutex lock4(&MState); - safe_delete_array(recvbuf); - safe_delete_array(sendbuf); - - char* line = 0; - while ((line = LineOutQueue.pop())) - safe_delete_array(line); -} - -bool TCPConnection::CheckNetActive() { - MState.lock(); - if (pState == TCPS_Connected || pState == TCPS_Disconnecting) { - MState.unlock(); - return true; - } - MState.unlock(); - return false; -} - -/* This is always called from an IO thread. Either the server socket's thread, or a - * special thread we create when we make an outbound connection. */ -bool TCPConnection::Process() { - char errbuf[TCPConnection_ErrorBufferSize]; - switch(GetState()) { - case TCPS_Ready: - case TCPS_Connecting: - if (ConnectionType == Outgoing) { - if (GetAsyncConnect()) { - if (charAsyncConnect) - rIP = ResolveIP(charAsyncConnect); - ConnectIP(rIP, rPort); - } - } - return(true); - - case TCPS_Connected: - // only receive data in the connected state, no others... - if (!RecvData(errbuf)) { - struct in_addr in; - in.s_addr = GetrIP(); - return false; - } - /* we break to do the send */ - break; - - case TCPS_Disconnecting: { - //waiting for any sending data to go out... - MSendQueue.lock(); - if(sendbuf) { - if(sendbuf_used > 0) { - //something left to send, keep processing... - MSendQueue.unlock(); - break; - } - //else, send buffer is empty. - safe_delete_array(sendbuf); - } //else, no send buffer, we are done. - MSendQueue.unlock(); - } - /* Fallthrough */ - - case TCPS_Disconnected: - FinishDisconnect(); - MRunLoop.lock(); - pRunLoop = false; - MRunLoop.unlock(); -// SetState(TCPS_Ready); //reset the state in case they want to use it again... - return(false); - - case TCPS_Closing: - //I dont understand this state... - - case TCPS_Error: - MRunLoop.lock(); - pRunLoop = false; - MRunLoop.unlock(); - return(false); - } - - /* we get here in connected or disconnecting with more data to send */ - - bool sent_something = false; - if (!SendData(sent_something, errbuf)) { - struct in_addr in; - in.s_addr = GetrIP(); - std::cout << inet_ntoa(in) << ":" << GetrPort() << ": " << errbuf << std::endl; - return false; - } - - return true; -} - -bool TCPConnection::RecvData(char* errbuf) { - if (errbuf) - errbuf[0] = 0; - if (!Connected()) { - return false; - } - - int status = 0; - if (recvbuf == 0) { - recvbuf = new uchar[5120]; - recvbuf_size = 5120; - recvbuf_used = 0; - recvbuf_echo = 0; - } - else if ((recvbuf_size - recvbuf_used) < 2048) { - auto tmpbuf = new uchar[recvbuf_size + 5120]; - memcpy(tmpbuf, recvbuf, recvbuf_used); - recvbuf_size += 5120; - safe_delete_array(recvbuf); - recvbuf = tmpbuf; - if (recvbuf_size >= MaxTCPReceiveBuffferSize) { - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): recvbuf_size >= MaxTCPReceiveBuffferSize"); - return false; - } - } - - status = recv(connection_socket, (char *) &recvbuf[recvbuf_used], (recvbuf_size - recvbuf_used), 0); - - if (status >= 1) { -#if TCPN_LOG_RAW_DATA_IN >= 1 - struct in_addr in; - in.s_addr = GetrIP(); - CoutTimestamp(true); - std::cout << ": Read " << status << " bytes from network. (recvbuf_used = " << recvbuf_used << ") " << inet_ntoa(in) << ":" << GetrPort(); - std::cout << std::endl; - #if TCPN_LOG_RAW_DATA_IN == 2 - int32 tmp = status; - if (tmp > 32) - tmp = 32; - DumpPacket(&recvbuf[recvbuf_used], status); - #elif TCPN_LOG_RAW_DATA_IN >= 3 - DumpPacket(&recvbuf[recvbuf_used], status); - #endif -#endif - recvbuf_used += status; - if (!ProcessReceivedData(errbuf)) - return false; - } - else if (status == SOCKET_ERROR) { -#ifdef _WINDOWS - if (!(WSAGetLastError() == WSAEWOULDBLOCK)) { - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): Error: %i", WSAGetLastError()); - return false; - } -#else - if (!(errno == EWOULDBLOCK)) { - if (errbuf) - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): Error: %s", strerror(errno)); - return false; - } -#endif - } else if (status == 0) { - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): Connection closed"); - return false; - } - - return true; -} - - -bool TCPConnection::GetEcho() { - bool ret; - ret = pEcho; - return ret; -} - -void TCPConnection::SetEcho(bool iValue) { - pEcho = iValue; -} - -bool TCPConnection::ProcessReceivedData(char* errbuf) { - if (errbuf) - errbuf[0] = 0; - if (!recvbuf) - return true; -#if TCPN_DEBUG_Console >= 4 - if (recvbuf_used) { - std::cout << "Starting Processing: recvbuf=" << recvbuf_used << std::endl; - DumpPacket(recvbuf, recvbuf_used); - } -#endif - for (int i=0; i < recvbuf_used; i++) { - if (GetEcho() && i >= recvbuf_echo) { - Send(&recvbuf[i], 1); - recvbuf_echo = i + 1; - } - switch(recvbuf[i]) { - case 0: { // 0 is the code for clear buffer - if (i==0) { - recvbuf_used--; - recvbuf_echo--; - memmove(recvbuf, &recvbuf[1], recvbuf_used); - i = -1; - } else { - if (i == recvbuf_used) { - safe_delete_array(recvbuf); - i = -1; - } - else { - uchar* tmpdel = recvbuf; - recvbuf = new uchar[recvbuf_size]; - memcpy(recvbuf, &tmpdel[i+1], recvbuf_used-i); - recvbuf_used -= i + 1; - recvbuf_echo -= i + 1; - safe_delete_array(tmpdel); - i = -1; - } - } -#if TCPN_DEBUG_Console >= 5 - std::cout << "Removed 0x00" << std::endl; - if (recvbuf_used) { - std::cout << "recvbuf left: " << recvbuf_used << std::endl; - DumpPacket(recvbuf, recvbuf_used); - } - else - std::cout << "recbuf left: None" << std::endl; -#endif - m_previousLineEnd = false; - break; - } - case 10: - case 13: // newline marker - { - char *line = nullptr; - if (i==0) { // empty line - if(!m_previousLineEnd) { - //char right before this was NOT a CR, report the empty line. - line = new char[1]; - line[0] = '\0'; - m_previousLineEnd = true; - } else { - m_previousLineEnd = false; - } - recvbuf_used--; - recvbuf_echo--; - memcpy(recvbuf, &recvbuf[1], recvbuf_used); - i = -1; - } else { - line = new char[i+1]; - memset(line, 0, i+1); - memcpy(line, recvbuf, i); -#if TCPN_DEBUG_Console >= 3 - std::cout << "Line Out: " << std::endl; - DumpPacket((uchar*) line, i); -#endif - //line[i] = 0; - uchar* tmpdel = recvbuf; - recvbuf = new uchar[recvbuf_size]; - recvbuf_used -= i+1; - recvbuf_echo -= i+1; - memcpy(recvbuf, &tmpdel[i+1], recvbuf_used); -#if TCPN_DEBUG_Console >= 5 - std::cout << "i+1=" << i+1 << std::endl; - if (recvbuf_used) { - std::cout << "recvbuf left: " << recvbuf_used << std::endl; - DumpPacket(recvbuf, recvbuf_used); - } - else - std::cout << "recbuf left: None" << std::endl; -#endif - safe_delete_array(tmpdel); - i = -1; - m_previousLineEnd = true; - } - - - if(line != nullptr) { - bool finish_proc = false; - finish_proc = LineOutQueuePush(line); - if(finish_proc) - return(true); //break early as requested by LineOutQueuePush - } - - break; - } - case 8: // backspace - { - if (i==0) { // nothin to backspace - recvbuf_used--; - recvbuf_echo--; - memmove(recvbuf, &recvbuf[1], recvbuf_used); - i = -1; - } else { - uchar* tmpdel = recvbuf; - recvbuf = new uchar[recvbuf_size]; - memcpy(recvbuf, tmpdel, i-1); - memcpy(&recvbuf[i-1], &tmpdel[i+1], recvbuf_used-i); - recvbuf_used -= 2; - recvbuf_echo -= 2; - safe_delete_array(tmpdel); - i -= 2; - } - break; - m_previousLineEnd = false; - } - default: - m_previousLineEnd = false; - } - } - if (recvbuf_used < 0) - safe_delete_array(recvbuf); - return true; -} - -bool TCPConnection::SendData(bool &sent_something, char* errbuf) { - if (errbuf) - errbuf[0] = 0; - /************ Get first send packet on queue and send it! ************/ - uchar* data = 0; - int32 size = 0; - int status = 0; - if (ServerSendQueuePop(&data, &size)) { -#ifdef _WINDOWS - status = send(connection_socket, (const char *) data, size, 0); -#else - status = send(connection_socket, data, size, MSG_NOSIGNAL); - if(errno==EPIPE) status = SOCKET_ERROR; -#endif - if (status >= 1) { -#if TCPN_LOG_RAW_DATA_OUT >= 1 - struct in_addr in; - in.s_addr = GetrIP(); - CoutTimestamp(true); - std::cout << ": Wrote " << status << " bytes to network. " << inet_ntoa(in) << ":" << GetrPort(); - std::cout << std::endl; - #if TCPN_LOG_RAW_DATA_OUT == 2 - int32 tmp = status; - if (tmp > 32) - tmp = 32; - DumpPacket(data, status); - #elif TCPN_LOG_RAW_DATA_OUT >= 3 - DumpPacket(data, status); - #endif -#endif - sent_something = true; - if (status < (signed)size) { -#if TCPN_LOG_RAW_DATA_OUT >= 1 - struct in_addr in; - in.s_addr = GetrIP(); - CoutTimestamp(true); - std::cout << ": Pushed " << (size - status) << " bytes back onto the send queue. " << inet_ntoa(in) << ":" << GetrPort(); - std::cout << std::endl; -#endif - // If there's network congestion, the number of bytes sent can be less than - // what we tried to give it... Push the extra back on the queue for later - ServerSendQueuePushFront(&data[status], size - status); - } - else if (status > (signed)size) { - return false; - } - // else if (status == size) {} - } - else { - ServerSendQueuePushFront(data, size); - } - - safe_delete_array(data); - if (status == SOCKET_ERROR) { -#ifdef _WINDOWS - if (WSAGetLastError() != WSAEWOULDBLOCK) -#else - if (errno != EWOULDBLOCK) -#endif - { - if (errbuf) { -#ifdef _WINDOWS - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::SendData(): send(): Errorcode: %i", WSAGetLastError()); -#else - snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::SendData(): send(): Errorcode: %s", strerror(errno)); -#endif - } - - //if we get an error while disconnecting, just jump to disconnected - MState.lock(); - if(pState == TCPS_Disconnecting) - pState = TCPS_Disconnected; - MState.unlock(); - - return false; - } - } - } - return true; -} - -ThreadReturnType TCPConnection::TCPConnectionLoop(void* tmp) { -#ifdef _WINDOWS - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); -#endif - if (tmp == 0) { - THREAD_RETURN(nullptr); - } - TCPConnection* tcpc = (TCPConnection*) tmp; -#ifndef WIN32 - Log(Logs::Detail, Logs::TCP_Connection, "%s Starting TCPConnectionLoop with thread ID %d", __FUNCTION__, pthread_self()); -#endif - tcpc->MLoopRunning.lock(); - while (tcpc->RunLoop()) { - Sleep(LOOP_GRANULARITY); - if (!tcpc->ConnectReady()) { - if (!tcpc->Process()) { - //the processing loop has detecting an error.. - //we want to drop the link immediately, so we clear buffers too. - tcpc->ClearBuffers(); - tcpc->Disconnect(); - } - Sleep(1); - } - else if (tcpc->GetAsyncConnect()) { - if (tcpc->charAsyncConnect) - tcpc->Connect(tcpc->charAsyncConnect, tcpc->GetrPort()); - else - tcpc->ConnectIP(tcpc->GetrIP(), tcpc->GetrPort()); - tcpc->SetAsyncConnect(false); - } - else - Sleep(10); //nothing to do. - } - tcpc->MLoopRunning.unlock(); - -#ifndef WIN32 - Log(Logs::Detail, Logs::TCP_Connection, "%s Ending TCPConnectionLoop with thread ID %d", __FUNCTION__, pthread_self()); -#endif - - THREAD_RETURN(nullptr); -} - -bool TCPConnection::RunLoop() { - bool ret; - MRunLoop.lock(); - ret = pRunLoop; - MRunLoop.unlock(); - return ret; -} - diff --git a/common/tcp_server.cpp b/common/tcp_server.cpp deleted file mode 100644 index 0009475fdd..0000000000 --- a/common/tcp_server.cpp +++ /dev/null @@ -1,231 +0,0 @@ -#include "global_define.h" -#include "tcp_server.h" -#include "../common/eqemu_logsys.h" - -#include -#include -#include - -#ifdef _WINDOWS - #include -#else - #include - #include - #include - #include - #include - #define INVALID_SOCKET -1 - #define SOCKET_ERROR -1 -#endif - -#define SERVER_LOOP_GRANULARITY 3 //# of ms between checking our socket/queues - -BaseTCPServer::BaseTCPServer(uint16 in_port) { - NextID = 1; - pPort = in_port; - sock = 0; - pRunLoop = true; -#ifdef _WINDOWS - _beginthread(BaseTCPServer::TCPServerLoop, 0, this); -#else - pthread_t thread; - pthread_create(&thread, nullptr, &BaseTCPServer::TCPServerLoop, this); -#endif -} - -BaseTCPServer::~BaseTCPServer() { - StopLoopAndWait(); -} - -void BaseTCPServer::StopLoopAndWait() { - MRunLoop.lock(); - if(pRunLoop) { - pRunLoop = false; - MRunLoop.unlock(); - //wait for loop to stop. - MLoopRunning.lock(); - MLoopRunning.unlock(); - } else { - MRunLoop.unlock(); - } -} - -bool BaseTCPServer::RunLoop() { - bool ret; - MRunLoop.lock(); - ret = pRunLoop; - MRunLoop.unlock(); - return ret; -} - -ThreadReturnType BaseTCPServer::TCPServerLoop(void* tmp) { -#ifdef _WINDOWS - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); -#endif - if (tmp == 0) { - THREAD_RETURN(nullptr); - } - BaseTCPServer* tcps = (BaseTCPServer*) tmp; - -#ifndef WIN32 - LogDebug( "Starting TCPServerLoop with thread ID [{}]", pthread_self()); -#endif - - tcps->MLoopRunning.lock(); - while (tcps->RunLoop()) { - Sleep(SERVER_LOOP_GRANULARITY); - tcps->Process(); - } - tcps->MLoopRunning.unlock(); - -#ifndef WIN32 - LogDebug( "Ending TCPServerLoop with thread ID [{}]", pthread_self()); -#endif - - THREAD_RETURN(nullptr); -} - -void BaseTCPServer::Process() { - ListenNewConnections(); -} - -void BaseTCPServer::ListenNewConnections() { - SOCKET tmpsock; - struct sockaddr_in from; - struct in_addr in; - unsigned int fromlen; - unsigned short port; - - from.sin_family = AF_INET; - fromlen = sizeof(from); - LockMutex lock(&MSock); -#ifndef DARWIN // Corysia - On OSX, 0 is a valid fd. - if (!sock) - return; -#else - if (sock == -1) return; -#endif - - // Check for pending connects -#ifdef _WINDOWS - unsigned long nonblocking = 1; - while ((tmpsock = accept(sock, (struct sockaddr*) &from, (int *) &fromlen)) != INVALID_SOCKET) { - ioctlsocket (tmpsock, FIONBIO, &nonblocking); -#else -#ifdef __CYGWIN__ - while ((tmpsock = accept(sock, (struct sockaddr *) &from, (int *) &fromlen)) != INVALID_SOCKET) { -#else - while ((tmpsock = accept(sock, (struct sockaddr*) &from, &fromlen)) != INVALID_SOCKET) { -#endif - fcntl(tmpsock, F_SETFL, O_NONBLOCK); -#endif - int bufsize = 64 * 1024; // 64kbyte recieve buffer, up from default of 8k - setsockopt(tmpsock, SOL_SOCKET, SO_RCVBUF, (char*) &bufsize, sizeof(bufsize)); - port = from.sin_port; - in.s_addr = from.sin_addr.s_addr; - - // New TCP connection, this must consume the socket. - CreateNewConnection(GetNextID(), tmpsock, in.s_addr, ntohs(from.sin_port)); - } -} - -bool BaseTCPServer::Open(uint16 in_port, char* errbuf) { - if (errbuf) - errbuf[0] = 0; - LockMutex lock(&MSock); - if (sock != 0) { - if (errbuf) - snprintf(errbuf, TCPServer_ErrorBufferSize, "Listening socket already open"); - return false; - } - if (in_port != 0) { - pPort = in_port; - } - -#ifdef _WINDOWS - SOCKADDR_IN address; - unsigned long nonblocking = 1; -#else - struct sockaddr_in address; -#endif - int reuse_addr = 1; - -// Setup internet address information. -// This is used with the bind() call - memset((char *) &address, 0, sizeof(address)); - address.sin_family = AF_INET; - address.sin_port = htons(pPort); - address.sin_addr.s_addr = htonl(INADDR_ANY); - -// Setting up TCP port for new TCP connections - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock == INVALID_SOCKET) { - if (errbuf) - snprintf(errbuf, TCPServer_ErrorBufferSize, "socket(): INVALID_SOCKET"); - return false; - } - -// Quag: dont think following is good stuff for TCP, good for UDP -// Mis: SO_REUSEADDR shouldn't be a problem for tcp--allows you to restart -// without waiting for conns in TIME_WAIT to die - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse_addr, sizeof(reuse_addr)); - - - if (bind(sock, (struct sockaddr *) &address, sizeof(address)) < 0) { -#ifdef _WINDOWS - closesocket(sock); -#else - close(sock); -#endif - sock = 0; - if (errbuf) - sprintf(errbuf, "bind(): <0"); - return false; - } - - int bufsize = 64 * 1024; // 64kbyte recieve buffer, up from default of 8k - setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*) &bufsize, sizeof(bufsize)); -#ifdef _WINDOWS - ioctlsocket (sock, FIONBIO, &nonblocking); -#else - fcntl(sock, F_SETFL, O_NONBLOCK); -#endif - - if (listen(sock, SOMAXCONN) == SOCKET_ERROR) { -#ifdef _WINDOWS - closesocket(sock); - if (errbuf) - snprintf(errbuf, TCPServer_ErrorBufferSize, "listen() failed, Error: %d", WSAGetLastError()); -#else - close(sock); - if (errbuf) - snprintf(errbuf, TCPServer_ErrorBufferSize, "listen() failed, Error: %s", strerror(errno)); -#endif - sock = 0; - return false; - } - - return true; -} - -void BaseTCPServer::Close() { - StopLoopAndWait(); - - LockMutex lock(&MSock); - if (sock) { -#ifdef _WINDOWS - closesocket(sock); -#else - close(sock); -#endif - } - sock = 0; -} - -bool BaseTCPServer::IsOpen() { - MSock.lock(); - bool ret = (bool) (sock != 0); - MSock.unlock(); - return ret; -} - diff --git a/world/eqw.cpp b/world/eqw.cpp deleted file mode 100644 index 8b0e17b43b..0000000000 --- a/world/eqw.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) - - 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 -*/ - -#ifdef EMBPERL - -#include "../common/global_define.h" -#include "eqw.h" -#include "eqw_parser.h" -#include "world_config.h" -#include "../common/races.h" -#include "../common/classes.h" -#include "../common/misc.h" -#include "../common/strings.h" -#include "zoneserver.h" -#include "zonelist.h" -#include "clientlist.h" -#include "cliententry.h" -#include "login_server.h" -#include "login_server_list.h" -#include "worlddb.h" -#include "client.h" -#include "launcher_list.h" -#include "launcher_link.h" -#include "wguild_mgr.h" -#include "../common/emu_constants.h" - -#ifdef seed -#undef seed -#endif - -#include - -extern uint32 numzones; -extern LauncherList launcher_list; -extern volatile bool RunLoops; - -EQW EQW::s_EQW; - -//IO Capture routine -XS(XS_EQWIO_PRINT); /* prototype to pass -Wmissing-prototypes */ -XS(XS_EQWIO_PRINT) -{ - dXSARGS; - if (items < 2) - return; - - int r; - for(r = 1; r < items; r++) { - char *str = SvPV_nolen(ST(r)); - EQW::Singleton()->AppendOutput(str); - } - - XSRETURN_EMPTY; -} - -EQW::EQW() { -} - -void EQW::AppendOutput(const char *str) { - m_outputBuffer += str; -// Log.LogDebugType(Logs::Detail, Logs::World_Server, "Append %d chars, yeilding result of length %d", strlen(str), m_outputBuffer.length()); -} - -const std::string &EQW::GetOutput() const { -// Log.LogDebugType(Logs::Detail, Logs::World_Server, "Getting, length %d", m_outputBuffer.length()); - return(m_outputBuffer); -} - -void EQW::LockWorld() { - WorldConfig::LockWorld(); - if (LoginServerList::Instance()->Connected()) { - LoginServerList::Instance()->SendStatus(); - } -} - -void EQW::UnlockWorld() { - WorldConfig::UnlockWorld(); - if (LoginServerList::Instance()->Connected()) { - LoginServerList::Instance()->SendStatus(); - } -} - -Const_char *EQW::GetConfig(Const_char *var_name) { - m_returnBuffer = WorldConfig::get()->GetByName(var_name); - return(m_returnBuffer.c_str()); -} - -bool EQW::LSConnected() { - return(LoginServerList::Instance()->Connected()); -} - -int EQW::CountZones() { - return(ZSList::Instance()->GetZoneCount()); -} - -//returns an array of zone_refs (opaque) -std::vector EQW::ListBootedZones() { - std::vector res; - - std::vector zones; - ZSList::Instance()->GetZoneIDList(zones); - - std::vector::iterator cur, end; - cur = zones.begin(); - end = zones.end(); - for(; cur != end; ++cur) { - res.push_back(itoa(*cur)); - } - - return(res); -} - -std::map EQW::GetZoneDetails(Const_char *zone_ref) { - std::map res; - - ZoneServer *zs = ZSList::Instance()->FindByID(Strings::ToInt(zone_ref)); - if(zs == nullptr) { - res["error"] = "Invalid zone."; - return(res); - } - - res["type"] = zs->IsStaticZone()?"static":"dynamic"; - res["zone_id"] = itoa(zs->GetZoneID()); - res["launch_name"] = zs->GetLaunchName(); - res["launched_name"] = zs->GetLaunchedName(); - res["short_name"] = zs->GetZoneName(); - res["long_name"] = zs->GetZoneLongName(); - res["port"] = itoa(zs->GetCPort()); - res["player_count"] = itoa(zs->NumPlayers()); - - //this isnt gunna work for dynamic zones... - res["launcher"] = ""; - if(zs->GetZoneID() != 0) { - LauncherLink *ll = launcher_list.FindByZone(zs->GetLaunchName()); - if(ll != nullptr) - res["launcher"] = ll->GetName(); - } - - return(res); -} - -int EQW::CountPlayers() { - return(ClientList::Instance()->GetClientCount()); -} - -//returns an array of character names in the zone (empty=all zones) -std::vector EQW::ListPlayers(Const_char *zone_name) { - std::vector res; - - std::vector list; - ClientList::Instance()->GetClients(zone_name, list); - - std::vector::iterator cur, end; - cur = list.begin(); - end = list.end(); - for(; cur != end; ++cur) { - res.push_back((*cur)->name()); - } - return(res); -} - -std::map EQW::GetPlayerDetails(Const_char *char_name) { - std::map res; - - ClientListEntry *cle = ClientList::Instance()->FindCharacter(char_name); - if(cle == nullptr) { - res["error"] = "1"; - return(res); - } - - res["character"] = cle->name(); - res["account"] = cle->AccountName(); - res["account_id"] = itoa(cle->AccountID()); - res["location_short"] = cle->zone()?ZoneName(cle->zone()):"No Zone"; - res["location_long"] = res["location_short"]; - res["location_id"] = itoa(cle->zone()); - res["ip"] = long2ip(cle->GetIP()); - res["level"] = itoa(cle->level()); - res["race"] = GetRaceIDName(cle->race()); - res["race_id"] = itoa(cle->race()); - res["class"] = GetClassIDName(cle->class_()); - res["class_id"] = itoa(cle->class_()); - res["guild_id"] = itoa(cle->GuildID()); - res["guild"] = guild_mgr.GetGuildName(cle->GuildID()); - res["status"] = itoa(cle->Admin()); -// res["patch"] = cle->DescribePatch(); - - return(res); -} - -int EQW::CountLaunchers(bool active_only) { - if(active_only) - return(launcher_list.GetLauncherCount()); - - std::vector it(EQW::ListLaunchers()); - return(it.size()); -} -/* -vector EQW::ListActiveLaunchers() { - vector launchers; - launcher_list.GetLauncherNameList(launchers); - return(launchers); -}*/ - -std::vector EQW::ListLaunchers() { -// vector list; -// database.GetLauncherList(list); - std::vector launchers; - launcher_list.GetLauncherNameList(launchers); - return(launchers); - -/* if(list.empty()) { - return(launchers); - } else if(launchers.empty()) { - return(list); - } - - //union the two lists. - vector::iterator curo, endo, curi, endi; - curo = list.begin(); - endo = list.end(); - for(; curo != endo; curo++) { - bool found = false; - curi = launchers.begin(); - endi = launchers.end(); - for(; curi != endi; curi++) { - if(*curo == *curi) { - found = true; - break; - } - } - if(found) - break; - launchers.push_back(*curo); - } - return(launchers);*/ -} - -EQLConfig * EQW::GetLauncher(Const_char *launcher_name) { - return(launcher_list.GetConfig(launcher_name)); -} - -void EQW::CreateLauncher(Const_char *launcher_name, int dynamic_count) { - launcher_list.CreateLauncher(launcher_name, dynamic_count); -} - -uint32 EQW::CreateGuild(const char* name, uint32 leader_char_id) { - uint32 id = guild_mgr.CreateGuild(name, leader_char_id); - if(id != GUILD_NONE) - ClientList::Instance()->UpdateClientGuild(leader_char_id, id); - return(id); -} - -bool EQW::DeleteGuild(uint32 guild_id) { - return(guild_mgr.DeleteGuild(guild_id)); -} - -bool EQW::RenameGuild(uint32 guild_id, const char* name) { - return(guild_mgr.RenameGuild(guild_id, name)); -} - -bool EQW::SetGuildMOTD(uint32 guild_id, const char* motd, const char *setter) { - return(guild_mgr.SetGuildMOTD(guild_id, motd, setter)); -} - -bool EQW::SetGuildLeader(uint32 guild_id, uint32 leader_char_id) { - return(guild_mgr.SetGuildLeader(guild_id, leader_char_id)); -} - -bool EQW::SetGuild(uint32 charid, uint32 guild_id, uint8 rank) { - ClientList::Instance()->UpdateClientGuild(charid, guild_id); - return(guild_mgr.SetGuild(charid, guild_id, rank)); -} - -bool EQW::SetGuildRank(uint32 charid, uint8 rank) { - return(guild_mgr.SetGuildRank(charid, rank)); -} - -bool EQW::SetBankerFlag(uint32 charid, bool is_banker) { - return(guild_mgr.SetBankerFlag(charid, is_banker)); -} - -bool EQW::SetTributeFlag(uint32 charid, bool enabled) { - return(guild_mgr.SetTributeFlag(charid, enabled)); -} - -bool EQW::SetPublicNote(uint32 charid, const char *note) { - return(guild_mgr.SetPublicNote(charid, note)); -} - -int EQW::CountBugs() { - std::string query = "SELECT count(*) FROM bugs where status = 0"; - auto results = database.QueryDatabase(query); - if (!results.Success()) - return 0; - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - return Strings::ToInt(row[0]); -} - -std::vector EQW::ListBugs(uint32 offset) { - std::vector res; - std::string query = StringFormat("SELECT id FROM bugs WHERE status = 0 limit %d, 30", offset); - auto results = database.QueryDatabase(query); - - if (!results.Success()) - return res; - - for (auto row = results.begin();row != results.end(); ++row) - res.push_back(row[0]); - - return res; -} - -std::map EQW::GetBugDetails(Const_char *id) { - std::map res; - std::string query = StringFormat("SELECT name, zone, x, y, z, target, bug FROM bugs WHERE id = %s", id); - auto results = database.QueryDatabase(query); - - if (!results.Success()) - return res; - - for(auto row = results.begin(); row != results.end(); ++row) { - res["name"] = row[0]; - res["zone"] = row[1]; - res["x"] = row[2]; - res["y"] = row[3]; - res["z"] = row[4]; - res["target"] = row[5]; - res["bug"] = row[6]; - res["id"] = id; - } - return res; -} - -void EQW::ResolveBug(const char *id) { - std::vector res; - std::string query = StringFormat("UPDATE bugs SET status=1 WHERE id=%s", id); - database.QueryDatabase(query); -} - -void EQW::SendMessage(uint32 type, const char *msg) { - ZSList::Instance()->SendEmoteMessage( - 0, - 0, - AccountStatus::Player, - type, - msg - ); -} - -void EQW::WorldShutDown(uint32 time, uint32 interval) { - ZSList::Instance()->WorldShutDown(time, interval); -} - -#endif //EMBPERL - diff --git a/world/eqw.h b/world/eqw.h deleted file mode 100644 index 99b917183e..0000000000 --- a/world/eqw.h +++ /dev/null @@ -1,93 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) - - 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 EQW_H_ -#define EQW_H_ - -#include -#include -#include -#include "../common/types.h" - -class EQLConfig; - -//this is the main object exported to perl. -class EQW { - EQW(); -public: - static EQW *Singleton() { return(&s_EQW); } - - void AppendOutput(const char *str); - const std::string &GetOutput() const; - void ClearOutput() { m_outputBuffer = ""; } - -//BEGIN PERL EXPORT - //NOTE: you must have a space after the * of a return value - Const_char * GetConfig(Const_char *var_name); - void LockWorld(); - void UnlockWorld(); - - bool LSConnected(); - - int CountZones(); - std::vector ListBootedZones(); //returns an array of zone_refs (opaque) - std::map GetZoneDetails(Const_char *zone_ref); //returns a hash ref of details - - int CountPlayers(); - std::vector ListPlayers(Const_char *zone_name = ""); //returns an array of player refs (opaque) - std::map GetPlayerDetails(Const_char *player_ref); //returns a hash ref of details - - int CountLaunchers(bool active_only); -// vector ListActiveLaunchers(); //returns an array of launcher names - std::vector ListLaunchers(); //returns an array of launcher names - EQLConfig * GetLauncher(Const_char *launcher_name); //returns the EQLConfig object for the specified launcher. - void CreateLauncher(Const_char *launcher_name, int dynamic_count); -// EQLConfig * FindLauncher(Const_char *zone_ref); - - //Guild routines, mostly wrappers around guild_mgr - uint32 CreateGuild(const char* name, uint32 leader_char_id); - bool DeleteGuild(uint32 guild_id); - bool RenameGuild(uint32 guild_id, const char* name); - bool SetGuildMOTD(uint32 guild_id, const char* motd, const char *setter); - bool SetGuildLeader(uint32 guild_id, uint32 leader_char_id); - bool SetGuild(uint32 charid, uint32 guild_id, uint8 rank); - bool SetGuildRank(uint32 charid, uint8 rank); - bool SetBankerFlag(uint32 charid, bool is_banker); - bool SetTributeFlag(uint32 charid, bool enabled); - bool SetPublicNote(uint32 charid, const char *note); - - //bugs - int CountBugs(); - std::vector ListBugs(uint32 offset); //returns an array of zone_refs (opaque) - std::map GetBugDetails(const char *id); - void ResolveBug(const char *id); - - void SendMessage(uint32 type, const char *msg); - void WorldShutDown(uint32 time, uint32 interval); -//END PERL EXPORT - -protected: - std::string m_outputBuffer; - std::string m_returnBuffer; - - bool m_worldLocked; - -private: - static EQW s_EQW; -}; - -#endif /*EQW_H_*/ diff --git a/world/eqw_http_handler.cpp b/world/eqw_http_handler.cpp deleted file mode 100644 index 5ae1b8b60a..0000000000 --- a/world/eqw_http_handler.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) - - 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 "../common/global_define.h" -#include "eqw_http_handler.h" -#include "../common/SocketLib/Base64.h" -#include "eqw_parser.h" -#include "eqw.h" -#include "http_request.h" - -#include "worlddb.h" -#include "console.h" - -Mime EQWHTTPHandler::s_mime; -#ifdef EMBPERL -EQWParser *EQWHTTPHandler::s_parser = nullptr; -#endif -const int EQWHTTPHandler::READ_BUFFER_LEN = 1024; //for page IO, was a static const member, but VC6 got mad. - -EQWHTTPHandler::EQWHTTPHandler(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) -: HttpdSocket(ID,in_socket,irIP,irPort), - m_closeOnFinish(false) -{ -} - -EQWHTTPHandler::~EQWHTTPHandler() { - -} - -#ifdef EMBPERL -EQWParser *EQWHTTPHandler::GetParser() { - if(s_parser == nullptr) { - EQW::Singleton()->ClearOutput(); - s_parser = new EQWParser(); - const std::string &res = EQW::Singleton()->GetOutput(); - if(!res.empty()) { - printf("EQWParser Init output:\n%s\n\n", res.c_str()); - EQW::Singleton()->ClearOutput(); - } - } - return(s_parser); -} -#endif - -/*void EQWHTTPHandler::OnWrite() { - HttpdSocket::OnWrite(); - if(m_closeOnFinish && GetOutputLength() == 0) { -// printf("CLOSING\n"); - Close(); - } -}*/ - - -void EQWHTTPHandler::Exec() { - m_sentHeaders = false; - m_responseCode = "200"; -// printf("Request: %s, %s, %s, %s.\n", GetMethod().c_str(), GetUrl().c_str(), GetUri().c_str(), GetQueryString().c_str()); - - SetHttpVersion("HTTP/1.0"); - AddResponseHeader("Connection", "close"); - - if(GetUri().find("..") != std::string::npos) { - SendResponse("403", "Forbidden"); - printf("%s is forbidden.\n", GetUri().c_str()); - return; - } - - if(!CheckAuth()) { - AddResponseHeader("Content-type", "text/plain"); - AddResponseHeader("WWW-Authenticate", "Basic realm=\"EQEmulator\""); - SendResponse("401", "Authorization Required"); - SendString("Gotta Authenticate."); - } else { - std::string::size_type start = GetUri().find_first_not_of('/'); - std::string page; - if(start != std::string::npos) - page = GetUri().substr(start); - else - page = "index.html"; - SendPage(page); - } -/* if (!Detach()) { - printf("Unable to detach...\n"); - } - if(GetOutputLength() > 0) { - //we cannot close yet - m_closeOnFinish = true; - } else { - Close(); - }*/ - Free(); //the "app" side (us) is done with this connection too... - Disconnect(); -} - -void EQWHTTPHandler::OnHeader(const std::string& key,const std::string& value) { - HttpdSocket::OnHeader(key, value); - - if (!strcasecmp(key.c_str(),"Authorization")) { - if(strncasecmp(value.c_str(), "Basic ", 6)) { - printf("Invalid auth type. Expected Basic: %s\n", value.c_str()); - return; - } - - std::string dec; - Base64::decode(value.c_str() + 6, dec); - - std::string::size_type cpos; - cpos = dec.find_first_of(':'); - if(cpos == std::string::npos) { - printf("Invalid auth string: %s\n", dec.c_str()); - return; - } - - m_username = dec.substr(0, cpos); - m_password = dec.substr(cpos+1); - } -} - -//we should prolly cache login info here... if we load a fresh page, we could be checking -//their auth dozens of times rather quickly... -bool EQWHTTPHandler::CheckAuth() const { - if(m_username.length() < 1) - return(false); - - int16 status = 0; - uint32 acctid = database.CheckLogin(m_username.c_str(), m_password.c_str(), &status); - if(acctid == 0) { - LogInfo("Login autentication failed for [{}] with [{}]", m_username.c_str(), m_password.c_str()); - return(false); - } - if(status < httpLoginStatus) { - LogInfo("Login of [{}] failed: status too low", m_username.c_str()); - return(false); - } - - return(true); -} - -void EQWHTTPHandler::SendPage(const std::string &file) { - - std::string path = "templates/"; - path += file; - - FILE *f = fopen(path.c_str(), "rb"); - if(f == nullptr) { - SendResponse("404", "Not Found"); - SendString("Not found."); - printf("%s not found.\n", file.c_str()); - return; - } - - std::string type = s_mime.GetMimeFromFilename(file); - AddResponseHeader("Content-type", type); - - bool process = false; -#ifdef EMBPERL - if(type == "text/html") - process = true; - else { - //not processing, send headers right away -#endif - SendResponse("200", "OK"); -#ifdef EMBPERL - } -#endif - - auto buffer = new char[READ_BUFFER_LEN + 1]; - size_t len; - std::string to_process; - while((len = fread(buffer, 1, READ_BUFFER_LEN, f)) > 0) { - buffer[len] = '\0'; - if(process) - to_process += buffer; - else - SendBuf(buffer, len); - } - delete[] buffer; - fclose(f); -#ifdef EMBPERL - if(process) { - //convert the base form into a useful perl exportable form - HTTPRequest req(this, GetHttpForm()); - GetParser()->SetHTTPRequest("testing", &req); - - //parse out the page and potentially pass some stuff on to perl. - ProcessAndSend(to_process); - - //clear out the form, just in case (since it gets destroyed next) - GetParser()->SetHTTPRequest("testing", nullptr); - } -#endif -} - -bool EQWHTTPHandler::LoadMimeTypes(const char *filename) { - return(s_mime.LoadMimeFile(filename)); -} - -#ifdef EMBPERL -void EQWHTTPHandler::ProcessAndSend(const std::string &str) { - std::string::size_type len = str.length(); - std::string::size_type start = 0; - std::string::size_type pos, end; - - while((pos = str.find("", pos+2); - if(end == std::string::npos) { - //terminal ?> not found... should issue a warning or something... - std::string scriptBody = str.substr(pos+2); - ProcessScript(scriptBody); - start = len; - break; - } else { - //script only consumes some of this buffer... - std::string scriptBody = str.substr(pos+2, end-pos-2); - ProcessScript(scriptBody); - start = end + 2; - } - } - - //send whatever is left over - if(start != len) - ProcessText(str.c_str() + start, len-start); -} - -void EQWHTTPHandler::ProcessScript(const std::string &script_body) { - const char *script = script_body.c_str(); - if(strcmp("perl", script) == 0) - script += 4; //allow EQW_eval("testing", script_body.c_str()); - const std::string &res = EQW::Singleton()->GetOutput(); - if(!res.empty()) { - ProcessText(res.c_str(), res.length()); - EQW::Singleton()->ClearOutput(); - } -} - -void EQWHTTPHandler::ProcessText(const char *txt, int len) { - if(!m_sentHeaders) { - SendResponse(m_responseCode, "OK"); - m_sentHeaders = true; - } - SendBuf(txt, len); -} -#endif - - -EQWHTTPServer::EQWHTTPServer() -: m_port(0) -{ -} - -void EQWHTTPServer::CreateNewConnection(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) { - auto conn = new EQWHTTPHandler(ID, in_socket, irIP, irPort); - AddConnection(conn); -} - -void EQWHTTPServer::Stop() { - LogInfo("Requesting that HTTP Service stop"); - m_running = false; - Close(); -} - -bool EQWHTTPServer::Start(uint16 port, const char *mime_file) { - if(m_running) { - LogInfo("HTTP Service is already running on port [{}]", m_port); - return(false); - } - - //load up our nice mime types - if(!EQWHTTPHandler::LoadMimeTypes(mime_file)) { - LogInfo("Failed to load mime types from [{}]", mime_file); - return(false); - } else { - LogInfo("Loaded mime types from [{}]", mime_file); - } - - //fire up the server thread - char errbuf[TCPServer_ErrorBufferSize]; - if(!Open(port, errbuf)) { - LogInfo("Unable to bind to port [{}] for HTTP service: [{}]", port, errbuf); - return(false); - } - - m_running = true; - m_port = port; - - /* - -#ifdef _WINDOWS - _beginthread(ThreadProc, 0, this); -#else - pthread_create(&m_thread, nullptr, ThreadProc, this); -#endif*/ - - return(true); -} - -/* -void EQWHTTPServer::Run() { - Log.LogDebugType(Logs::Detail, Logs::World_Server, "HTTP Processing thread started on port %d", m_port); - do { -#warning DELETE THIS IF YOU DONT USE IT - Sleep(10); - } while(m_running); - Log.LogDebugType(Logs::Detail, Logs::World_Server, "HTTP Processing thread terminating on port %d", m_port); -} - -ThreadReturnType EQWHTTPServer::ThreadProc(void *data) { - ((EQWHTTPServer *) data)->Run(); - THREAD_RETURN(nullptr); -}*/ - diff --git a/world/eqw_parser.cpp b/world/eqw_parser.cpp deleted file mode 100644 index 46cc4465c5..0000000000 --- a/world/eqw_parser.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) - - 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 -*/ - -//a lot of this is copied from embperl.cpp, but I didnt feel like factoring the common stuff out - -#ifdef EMBPERL - -#include "../common/global_define.h" -#include "eqw_parser.h" -#include "eqw.h" -#include "../common/eqdb.h" - -#include "worlddb.h" - -#ifndef GvCV_set -#define GvCV_set(gv,cv) (GvCV(gv) = (cv)) -#endif - -XS(XS_EQWIO_PRINT); - -//so embedded scripts can use xs extensions (ala 'use socket;') -EXTERN_C void boot_DynaLoader(pTHX_ CV* cv); -EXTERN_C XS(boot_EQW); -EXTERN_C XS(boot_EQDB); -EXTERN_C XS(boot_EQDBRes); -EXTERN_C XS(boot_HTTPRequest); -EXTERN_C XS(boot_EQLConfig); - -EXTERN_C void xs_init(pTHX) -{ - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = '\0'; - - char buf[128]; //shouldent have any function names longer than this. - - //add the strcpy stuff to get rid of const warnings.... - - newXS(strcpy(buf, "DynaLoader::boot_DynaLoader"), boot_DynaLoader, file); - newXS(strcpy(buf, "EQW::boot_EQW"), boot_EQW, file); - newXS(strcpy(buf, "EQDB::boot_EQDB"), boot_EQDB, file); - newXS(strcpy(buf, "EQDBRes::boot_EQDBRes"), boot_EQDBRes, file); - newXS(strcpy(buf, "HTTPRequest::boot_HTTPRequest"), boot_HTTPRequest, file); - newXS(strcpy(buf, "EQLConfig::boot_EQLConfig"), boot_EQLConfig, file); - newXS(strcpy(buf, "EQWIO::PRINT"), XS_EQWIO_PRINT, file); -} - -EQWParser::EQWParser() { - //setup perl... - my_perl = perl_alloc(); - _empty_sv = newSV(0); - if (!my_perl) { - LogInfo("Error: perl_alloc failed!"); - } - else { - DoInit(); - } -} - -void EQWParser::DoInit() { - const char *argv_eqemu[] = { "", - "-w", "-W", - "-e", "0;", nullptr }; - - int argc = 5; - - char **argv = (char **)argv_eqemu; - char **env = { nullptr }; - - PL_perl_destruct_level = 1; - - perl_construct(my_perl); - - PERL_SYS_INIT3(&argc, &argv, &env); - - perl_parse(my_perl, xs_init, argc, argv, env); - - perl_run(my_perl); - - //a little routine we use a lot. - eval_pv("sub my_eval {eval $_[0];}", TRUE); //dies on error - - //ruin the perl exit and command: - eval_pv("sub my_exit {}",TRUE); - eval_pv("sub my_sleep {}",TRUE); - if(gv_stashpv("CORE::GLOBAL", FALSE)) { - GV *exitgp = gv_fetchpv("CORE::GLOBAL::exit", TRUE, SVt_PVCV); - GvCV_set(exitgp, perl_get_cv("my_exit", TRUE)); //dies on error - GvIMPORTED_CV_on(exitgp); - GV *sleepgp = gv_fetchpv("CORE::GLOBAL::sleep", TRUE, SVt_PVCV); - GvCV_set(sleepgp, perl_get_cv("my_sleep", TRUE)); //dies on error - GvIMPORTED_CV_on(sleepgp); - } - - //setup eval_file - eval_pv( - "our %Cache;" - "use Symbol qw(delete_package);" - "sub eval_file {" - "my($package, $filename) = @_;" - "$filename=~s/\'//g;" - "if(! -r $filename) { print \"Unable to read perl file '$filename'\\n\"; return; }" - "my $mtime = -M $filename;" - "if(defined $Cache{$package}{mtime}&&$Cache{$package}{mtime} <= $mtime && !($package eq 'plugin')){" - " return;" - "} else {" - //we 'my' $filename,$mtime,$package,$sub to prevent them from changing our state up here. - " eval(\"package $package; my(\\$filename,\\$mtime,\\$package,\\$sub); \\$isloaded = 1; require '$filename'; \");" - "}" - "}" - ,FALSE); - - //make a tie-able class to capture IO and get it where it needs to go - eval_pv( - "package EQWIO; " -// "&boot_EQEmuIO;" - "sub TIEHANDLE { my $me = bless {}, $_[0]; $me->PRINT('Creating '.$me); return($me); } " - "sub WRITE { } " - "sub PRINTF { my $me = shift; my $fmt = shift; $me->PRINT(sprintf($fmt, @_)); } " - "sub CLOSE { my $me = shift; $me->PRINT('Closing '.$me); } " - "sub DESTROY { my $me = shift; $me->PRINT('Destroying '.$me); } " -//this ties us for all packages - "package MAIN;" - " if(tied *STDOUT) { untie(*STDOUT); }" - " if(tied *STDERR) { untie(*STDERR); }" - " tie *STDOUT, 'EQWIO';" - " tie *STDERR, 'EQWIO';" - ,FALSE); - - eval_pv( - "package world; " - ,FALSE - ); - - //make sure the EQW pointer is set up in this package - EQW *curc = EQW::Singleton(); - SV *l = get_sv("world::EQW", true); - if(curc != nullptr) { - sv_setref_pv(l, "EQW", curc); - } else { - //clear out the value, mainly to get rid of blessedness - sv_setsv(l, _empty_sv); - } - - //make sure the EQDB pointer is set up in this package - EQDB::SetMySQL(database.getMySQL()); - EQDB *curc_db = EQDB::Singleton(); - SV *l_db = get_sv("world::EQDB", true); - if(curc_db != nullptr) { - sv_setref_pv(l_db, "EQDB", curc_db); - } else { - //clear out the value, mainly to get rid of blessedness - sv_setsv(l_db, _empty_sv); - } - - //load up EQW - eval_pv( - "package EQW;" - "&boot_EQW;" //load our EQW XS - "package EQDB;" - "&boot_EQDB;" //load our EQW XS - "package EQDBRes;" - "&boot_EQDBRes;" //load our EQW XS - "package HTTPRequest;" - "&boot_HTTPRequest;" //load our HTTPRequest XS - "package EQLConfig;" - "&boot_EQLConfig;" //load our EQLConfig XS - , FALSE ); - - -#ifdef EMBPERL_PLUGIN - LogInfo("Loading worldui perl plugins"); - std::string err; - if(!eval_file("world", "worldui.pl", err)) { - LogInfo("Warning - world.pl: [{}]", err.c_str()); - } - - eval_pv( - "package world; " - "if(opendir(D,'worldui')) { " - " my @d = readdir(D);" - " closedir(D);" - " foreach(@d){ " - " next unless(/\\.pl$); " - " require 'templates/'.$_;" - " }" - "}" - ,FALSE); -#endif //EMBPERL_PLUGIN -} - -EQWParser::~EQWParser() { - //removed to try to stop perl from exploding on reload, we'll see -/* eval_pv( - "package quest;" - " untie *STDOUT;" - " untie *STDERR;" - ,FALSE); -*/ - perl_free(my_perl); -} - -bool EQWParser::eval_file(const char * packagename, const char * filename, std::string &error) -{ - std::vector args; - args.push_back(packagename); - args.push_back(filename); - return(dosub("eval_file", args, error)); -} - -bool EQWParser::dosub(const char * subname, const std::vector &args, std::string &error, int mode) { - bool err = false; - dSP; // initialize stack pointer - ENTER; // everything created after here - SAVETMPS; // ...is a temporary variable - PUSHMARK(SP); // remember the stack pointer - if(!args.empty()) - { - for (auto i = args.begin(); i != args.end(); ++i) { /* push the arguments onto the perl stack */ - XPUSHs(sv_2mortal(newSVpv(i->c_str(), i->length()))); - } - } - PUTBACK; // make local stack pointer global - call_pv(subname, mode); /*eval our code*/ - SPAGAIN; // refresh stack pointer - if(SvTRUE(ERRSV)) { - err = true; - } - FREETMPS; // free temp values - LEAVE; // ...and the XPUSHed "mortal" args. - - if(err) { - error = "Perl runtime error: "; - error += SvPVX(ERRSV); - return(false); - } - return(true); -} - -bool EQWParser::eval(const char * code, std::string &error) { - std::vector arg; - arg.push_back(code); - return(dosub("my_eval", arg, error, G_SCALAR|G_DISCARD|G_EVAL|G_KEEPERR)); -} - -void EQWParser::EQW_eval(const char *pkg, const char *code) { - char namebuf[64]; - - snprintf(namebuf, 64, "package %s;", pkg); - eval_pv(namebuf, FALSE); - - //make sure the EQW pointer is set up - EQW *curc = EQW::Singleton(); - snprintf(namebuf, 64, "EQW"); -// snprintf(namebuf, 64, "%s::EQW", pkg); - SV *l = get_sv(namebuf, true); - if(curc != nullptr) { - sv_setref_pv(l, "EQW", curc); - } else { - //clear out the value, mainly to get rid of blessedness - sv_setsv(l, _empty_sv); - } - //make sure the EQDB pointer is set up - EQDB *curc_db = EQDB::Singleton(); - snprintf(namebuf, 64, "EQDB"); -// snprintf(namebuf, 64, "%s::EQW", pkg); - SV *l_db = get_sv(namebuf, true); - if(curc_db != nullptr) { - sv_setref_pv(l_db, "EQDB", curc_db); - } else { - //clear out the value, mainly to get rid of blessedness - sv_setsv(l_db, _empty_sv); - } - - std::string err; - if(!eval(code, err)) { - EQW::Singleton()->AppendOutput(err.c_str()); - } -} - -void EQWParser::SetHTTPRequest(const char *pkg, HTTPRequest *it) { - char namebuf[64]; - - snprintf(namebuf, 64, "package %s;", pkg); - eval_pv(namebuf, FALSE); - - snprintf(namebuf, 64, "request"); -// snprintf(namebuf, 64, "%s::EQW", pkg); - SV *l = get_sv(namebuf, true); - if(it != nullptr) { - sv_setref_pv(l, "HTTPRequest", it); - } else { - //clear out the value, mainly to get rid of blessedness - sv_setsv(l, _empty_sv); - } - -} -/* -$editors = array(); -$editors["merchant"] = new MerchantEditor(); -#... for other editors - -if(defined($editors[$editor])) { - $edit = $editors[$editor]; - $edit->dispatch($action); -} - -class MerchantEditor extends BaseEditor { - MerchantEditor() { - $this->RegisterAction(0, "get_merchantlist", "merchant/merchant.tmpl.php", "no"); - $this->RegisterAction(1, "get_merchantlist", "merchant/merchant.edit.tmpl.php", "no"); - } -} - -function dispatch() { - my $dispatcher = $this->_dispatchers[$action]; - $body = new Template($dispatcher["template"]); - my $proc = $dispatcher["proc"]; - $vars = $this->$proc(); - if($dispatcher["guestmode"] == "no") { - check_authorization(); - } - if ($vars) { - foreach ($vars as $key=>$value) { - $body->set($key, $value); - } - } -} - -*/ - -#endif //EMBPERL - diff --git a/world/http_request.cpp b/world/http_request.cpp deleted file mode 100644 index 16be3c8dd9..0000000000 --- a/world/http_request.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) - - 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 "../common/global_define.h" -#include "http_request.h" -#include "eqw_http_handler.h" -#include "../common/eqdb.h" -#include "../common/SocketLib/HttpdForm.h" -#include - -HTTPRequest::HTTPRequest(EQWHTTPHandler *h, HttpdForm *form) -: m_handler(h) -{ - std::string name, value; - if(form->getfirst(name, value)) { - m_values[name] = value; - while(form->getnext(name, value)) - m_values[name] = value; - } -} - -const char *HTTPRequest::getEscaped(const char *name, const char *default_value) const { - return(EQDB::Singleton()->escape_string(get(name, default_value))); -} - -const char *HTTPRequest::get(const char *name, const char *default_value) const { - std::map::const_iterator res; - res = m_values.find(name); - if(res == m_values.end()) - return(default_value); - return(res->second.c_str()); -} - -std::map HTTPRequest::get_all() const { - return m_values; -} - -int HTTPRequest::getInt(const char *name, int default_value) const { - std::map::const_iterator res; - res = m_values.find(name); - if(res == m_values.end()) - return(default_value); - return(Strings::ToInt(res->second.c_str())); -} - -float HTTPRequest::getFloat(const char *name, float default_value) const { - std::map::const_iterator res; - res = m_values.find(name); - if(res == m_values.end()) - return(default_value); - return(Strings::ToFloat(res->second.c_str())); -} - -void HTTPRequest::header(Const_char *name, Const_char *value) { - m_handler->AddResponseHeader(name, value); -} - -void HTTPRequest::SetResponseCode(Const_char *code) { - m_handler->SetResponseCode(code); -} - -void HTTPRequest::redirect(Const_char *URL) { - header("Location", URL); - SetResponseCode("302"); -} - diff --git a/world/http_request.h b/world/http_request.h deleted file mode 100644 index 907d75ebdc..0000000000 --- a/world/http_request.h +++ /dev/null @@ -1,58 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) - - 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 HTTPREQUEST_H_ -#define HTTPREQUEST_H_ - -#include "../common/types.h" -#include -#include - -//this object acts as a friendlier interface to the HttpdForm object (perl exportable) -//which does more effecient lookups - - -class HttpdForm; -class EQWHTTPHandler; - -class HTTPRequest { -public: - HTTPRequest(EQWHTTPHandler *h, HttpdForm *form); - -//BEGIN PERL EXPORT - - Const_char * get(Const_char *name, Const_char *default_value = "") const; - int getInt(Const_char *name, int default_value = 0) const; - float getFloat(Const_char *name, float default_value = 0.0) const; - - //returns a database-safe string - Const_char * getEscaped(Const_char *name, Const_char *default_value = "") const; - - std::map get_all() const; - - void redirect(Const_char *URL); - void SetResponseCode(Const_char *code); - void header(Const_char *name, Const_char *value); -//END PERL EXPORT - -protected: - EQWHTTPHandler *const m_handler; - std::map m_values; -}; - -#endif /*HTTPREQUEST_H_*/ - From 360e01d824d6d22319d736f860eaa86896f0da90 Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 00:23:57 -0800 Subject: [PATCH 072/194] add new platform headers to simplify including windows/posix headers --- common/CMakeLists.txt | 6 ++++++ common/platform/inet.h | 4 ++++ common/platform/platform.h | 7 +++++++ common/platform/posix/include_inet.h | 8 ++++++++ common/platform/posix/include_pthreads.h | 8 ++++++++ common/platform/win/include_windows.h | 23 +++++++++++++++++++++++ common/platform/win/include_winsock2.h | 7 +++++++ 7 files changed, 63 insertions(+) create mode 100644 common/platform/inet.h create mode 100644 common/platform/platform.h create mode 100644 common/platform/posix/include_inet.h create mode 100644 common/platform/posix/include_pthreads.h create mode 100644 common/platform/win/include_windows.h create mode 100644 common/platform/win/include_winsock2.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index d5fb90abbb..22dd6f9030 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -101,6 +101,12 @@ set(common_sources perl_eqdb.cpp perl_eqdb_res.cpp platform.cpp + platform/inet.h + platform/platform.h + platform/posix/include_inet.h + platform/posix/include_pthreads.h + platform/win/include_windows.h + platform/win/include_winsock2.h proc_launcher.cpp process.cpp process/process.cpp diff --git a/common/platform/inet.h b/common/platform/inet.h new file mode 100644 index 0000000000..2cdf672ca2 --- /dev/null +++ b/common/platform/inet.h @@ -0,0 +1,4 @@ +#pragma once + +#include "common/platform/posix/include_inet.h" +#include "common/platform/win/include_winsock2.h" diff --git a/common/platform/platform.h b/common/platform/platform.h new file mode 100644 index 0000000000..81624a808c --- /dev/null +++ b/common/platform/platform.h @@ -0,0 +1,7 @@ +#pragma once + +#ifdef _WINDOWS +#include "common/platform/win/include_windows.h" +#else +#include +#endif diff --git a/common/platform/posix/include_inet.h b/common/platform/posix/include_inet.h new file mode 100644 index 0000000000..d50d9e164d --- /dev/null +++ b/common/platform/posix/include_inet.h @@ -0,0 +1,8 @@ +#pragma once + +#ifndef _WINDOWS + +#include +#include + +#endif // !_WINDOWS diff --git a/common/platform/posix/include_pthreads.h b/common/platform/posix/include_pthreads.h new file mode 100644 index 0000000000..c8e550baf2 --- /dev/null +++ b/common/platform/posix/include_pthreads.h @@ -0,0 +1,8 @@ +#pragma once + +#ifndef _WINDOWS + +#include "common/unix.h" +#include + +#endif // !_WINDOWS diff --git a/common/platform/win/include_windows.h b/common/platform/win/include_windows.h new file mode 100644 index 0000000000..9a1f218185 --- /dev/null +++ b/common/platform/win/include_windows.h @@ -0,0 +1,23 @@ +#pragma once + +#ifdef _WINDOWS + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include + +#ifdef GetCurrentTime +#undef GetCurrentTime +#endif + +#ifdef GetClassName +#undef GetClassName +#endif + +#endif // _WINDOWS diff --git a/common/platform/win/include_winsock2.h b/common/platform/win/include_winsock2.h new file mode 100644 index 0000000000..563a49b586 --- /dev/null +++ b/common/platform/win/include_winsock2.h @@ -0,0 +1,7 @@ +#pragma once + +#ifdef _WINDOWS + +#include + +#endif // _WINDOWS From b7fcee632e9b652682bcb67ba0f3fcca068338f4 Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 00:25:57 -0800 Subject: [PATCH 073/194] normalize includes: loginserver --- loginserver/CMakeLists.txt | 1 + loginserver/account_management.cpp | 7 ++-- loginserver/account_management.h | 15 +++----- loginserver/client.h | 1 - loginserver/client_manager.cpp | 10 ++--- loginserver/client_manager.h | 14 +++---- loginserver/encryption.h | 9 +++-- loginserver/eq_crypto_api.h | 6 +-- loginserver/login_server.h | 19 ++++------ loginserver/login_types.h | 11 ++++-- loginserver/loginserver_command_handler.cpp | 13 +++---- loginserver/loginserver_command_handler.h | 9 +---- loginserver/loginserver_webserver.cpp | 13 ++++--- loginserver/loginserver_webserver.h | 11 ++---- loginserver/main.cpp | 42 ++++++++++----------- loginserver/options.h | 9 ++--- loginserver/world_server.cpp | 13 ++++--- loginserver/world_server.h | 24 +++++------- loginserver/world_server_manager.cpp | 11 +++--- loginserver/world_server_manager.h | 19 ++++------ 20 files changed, 112 insertions(+), 145 deletions(-) diff --git a/loginserver/CMakeLists.txt b/loginserver/CMakeLists.txt index 013c64d5fb..71466df1bd 100644 --- a/loginserver/CMakeLists.txt +++ b/loginserver/CMakeLists.txt @@ -33,6 +33,7 @@ add_executable(loginserver ${eqlogin_sources} ${eqlogin_headers}) install(TARGETS loginserver RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) target_link_libraries(loginserver common) +target_include_directories(loginserver PRIVATE ..) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set_property(TARGET loginserver PROPERTY FOLDER executables/servers) diff --git a/loginserver/account_management.cpp b/loginserver/account_management.cpp index f7c0ed5353..314fb44920 100644 --- a/loginserver/account_management.cpp +++ b/loginserver/account_management.cpp @@ -1,7 +1,8 @@ #include "account_management.h" -#include "login_server.h" -#include "../common/event/task_scheduler.h" -#include "../common/repositories/login_accounts_repository.h" + +#include "common/event/task_scheduler.h" +#include "common/repositories/login_accounts_repository.h" +#include "loginserver/login_server.h" EQ::Event::TaskScheduler task_runner; diff --git a/loginserver/account_management.h b/loginserver/account_management.h index e047e44685..7f23c8775e 100644 --- a/loginserver/account_management.h +++ b/loginserver/account_management.h @@ -1,11 +1,9 @@ -#ifndef EQEMU_ACCOUNT_MANAGEMENT_H -#define EQEMU_ACCOUNT_MANAGEMENT_H +#pragma once -#include "iostream" -#include "../common/types.h" -#include "login_types.h" -#include "encryption.h" -#include "login_server.h" +#include "common/types.h" +#include "loginserver/login_types.h" +#include "loginserver/encryption.h" +#include "loginserver/login_server.h" extern LoginServer server; extern Database database; @@ -28,6 +26,3 @@ class AccountManagement { const std::string &ip_address = "" ); }; - - -#endif //EQEMU_ACCOUNT_MANAGEMENT_H diff --git a/loginserver/client.h b/loginserver/client.h index 0dc71d00c7..75d972f925 100644 --- a/loginserver/client.h +++ b/loginserver/client.h @@ -1,7 +1,6 @@ #ifndef EQEMU_CLIENT_H #define EQEMU_CLIENT_H -#include "../common/global_define.h" #include "../common/opcodemgr.h" #include "../common/random.h" #include "../common/eq_stream_intf.h" diff --git a/loginserver/client_manager.cpp b/loginserver/client_manager.cpp index 5767f538bf..87ea3ecd57 100644 --- a/loginserver/client_manager.cpp +++ b/loginserver/client_manager.cpp @@ -1,13 +1,13 @@ #include "client_manager.h" -#include "login_server.h" + +#include "common/file.h" +#include "common/misc.h" +#include "common/path_manager.h" +#include "loginserver/login_server.h" extern LoginServer server; extern bool run_server; -#include "../common/misc.h" -#include "../common/path_manager.h" -#include "../common/file.h" - void CheckTitaniumOpcodeFile(const std::string &path) { if (File::Exists(path)) { diff --git a/loginserver/client_manager.h b/loginserver/client_manager.h index 17c87b43d8..3171fdccac 100644 --- a/loginserver/client_manager.h +++ b/loginserver/client_manager.h @@ -1,10 +1,9 @@ -#ifndef EQEMU_CLIENTMANAGER_H -#define EQEMU_CLIENTMANAGER_H +#pragma once + +#include "common/net/eqstream.h" +#include "common/opcodemgr.h" +#include "loginserver/client.h" -#include "../common/global_define.h" -#include "../common/opcodemgr.h" -#include "../common/net/eqstream.h" -#include "client.h" #include class ClientManager { @@ -25,6 +24,3 @@ class ClientManager { OpcodeManager *m_larion_ops; EQ::Net::EQStreamManager *m_larion_stream; }; - -#endif - diff --git a/loginserver/encryption.h b/loginserver/encryption.h index 43d556d538..0ebb3e1fd9 100644 --- a/loginserver/encryption.h +++ b/loginserver/encryption.h @@ -1,10 +1,11 @@ #pragma once +#include "common/eqemu_logsys.h" +#include "common/strings.h" +#include "common/types.h" +#include "loginserver/login_types.h" + #include -#include "../common/types.h" -#include "login_types.h" -#include "../common/eqemu_logsys.h" -#include "../common/strings.h" enum EncryptionMode { EncryptionModeMD5 = 1, diff --git a/loginserver/eq_crypto_api.h b/loginserver/eq_crypto_api.h index 89d9cbe3c6..87461543ca 100644 --- a/loginserver/eq_crypto_api.h +++ b/loginserver/eq_crypto_api.h @@ -1,9 +1,5 @@ -#ifndef EQEMUCAPI__H -#define EQEMUCAPI__H +#pragma once char* DecryptUsernamePassword(const char* encryptedBuffer, unsigned int bufferSize, int mode); char* Encrypt(const char* buffer, unsigned int bufferSize, unsigned int &outSize); void _HeapDeleteCharBuffer(char *buffer); - -#endif - diff --git a/loginserver/login_server.h b/loginserver/login_server.h index 5104a48e07..0602ba528d 100644 --- a/loginserver/login_server.h +++ b/loginserver/login_server.h @@ -1,13 +1,13 @@ -#ifndef EQEMU_LOGINSERVER_H -#define EQEMU_LOGINSERVER_H +#pragma once + +#include "common/json_config.h" +#include "loginserver/client_manager.h" +#include "loginserver/encryption.h" +#include "loginserver/loginserver_webserver.h" +#include "loginserver/options.h" +#include "loginserver/world_server_manager.h" #include -#include "../common/json_config.h" -#include "encryption.h" -#include "options.h" -#include "world_server_manager.h" -#include "client_manager.h" -#include "loginserver_webserver.h" struct LoginServer { public: @@ -23,6 +23,3 @@ struct LoginServer { WorldServerManager *server_manager; ClientManager *client_manager{}; }; - -#endif - diff --git a/loginserver/login_types.h b/loginserver/login_types.h index 127514696c..b760eb7fe5 100644 --- a/loginserver/login_types.h +++ b/loginserver/login_types.h @@ -1,6 +1,10 @@ -#ifndef EQEMU_LOGINSTRUCTURES_H -#define EQEMU_LOGINSTRUCTURES_H +#pragma once +#include "common/types.h" + +#include + +#pragma pack(push) #pragma pack(1) // unencrypted base message header in all packets @@ -161,5 +165,4 @@ namespace LS { }; } -#endif - +#pragma pack(pop) diff --git a/loginserver/loginserver_command_handler.cpp b/loginserver/loginserver_command_handler.cpp index a445bcb4e5..d3552930a9 100644 --- a/loginserver/loginserver_command_handler.cpp +++ b/loginserver/loginserver_command_handler.cpp @@ -1,11 +1,10 @@ -#include -#include #include "loginserver_command_handler.h" -#include "../common/util/uuid.h" -#include "login_server.h" -#include "loginserver_webserver.h" -#include "account_management.h" -#include "../common/repositories/login_api_tokens_repository.h" + +#include "common/repositories/login_api_tokens_repository.h" +#include "common/util/uuid.h" +#include "loginserver/account_management.h" +#include "loginserver/login_server.h" +#include "loginserver/loginserver_webserver.h" extern LoginServer server; diff --git a/loginserver/loginserver_command_handler.h b/loginserver/loginserver_command_handler.h index fc2f2cbebf..265fb046cb 100644 --- a/loginserver/loginserver_command_handler.h +++ b/loginserver/loginserver_command_handler.h @@ -1,8 +1,6 @@ -#include "iostream" -#include "../common/cli/eqemu_command_handler.h" +#pragma once -#ifndef EQEMU_LOGINSERVER_COMMAND_HANDLER_H -#define EQEMU_LOGINSERVER_COMMAND_HANDLER_H +#include "common/cli/eqemu_command_handler.h" namespace LoginserverCommandHandler { void CommandHandler(int argc, char **argv); @@ -16,6 +14,3 @@ namespace LoginserverCommandHandler { void UpdateLoginserverWorldAdminAccountPassword(int argc, char **argv, argh::parser &cmd, std::string &description); void HealthCheckLogin(int argc, char **argv, argh::parser &cmd, std::string &description); }; - - -#endif //EQEMU_LOGINSERVER_COMMAND_HANDLER_H diff --git a/loginserver/loginserver_webserver.cpp b/loginserver/loginserver_webserver.cpp index a880feb857..2884e21080 100644 --- a/loginserver/loginserver_webserver.cpp +++ b/loginserver/loginserver_webserver.cpp @@ -1,10 +1,11 @@ #include "loginserver_webserver.h" -#include "world_server_manager.h" -#include "login_server.h" -#include "../common/json/json.h" -#include "../common/strings.h" -#include "account_management.h" -#include "../common/repositories/login_api_tokens_repository.h" + +#include "common/json/json.h" +#include "common/repositories/login_api_tokens_repository.h" +#include "common/strings.h" +#include "loginserver/account_management.h" +#include "loginserver/login_server.h" +#include "loginserver/world_server_manager.h" extern LoginServer server; diff --git a/loginserver/loginserver_webserver.h b/loginserver/loginserver_webserver.h index 9de510152f..dba59824ca 100644 --- a/loginserver/loginserver_webserver.h +++ b/loginserver/loginserver_webserver.h @@ -1,9 +1,8 @@ -#ifndef EQEMU_LOGINSERVER_WEBSERVER_H -#define EQEMU_LOGINSERVER_WEBSERVER_H +#pragma once -#include "../common/http/httplib.h" -#include "../common/json/json.h" -#include "../common/types.h" +#include "common/http/httplib.h" +#include "common/json/json.h" +#include "common/types.h" namespace LoginserverWebserver { @@ -35,5 +34,3 @@ namespace LoginserverWebserver { void SendResponse(const Json::Value &payload, httplib::Response &res); static Json::Value ParseRequestBody(const httplib::Request &request); }; - -#endif //EQEMU_LOGINSERVER_WEBSERVER_H diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 9047db8c81..636118d02a 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -1,34 +1,30 @@ -#include "../common/global_define.h" -#include "../common/types.h" -#include "../common/opcodemgr.h" -#include "../common/event/event_loop.h" -#include "../common/timer.h" -#include "../common/platform.h" -#include "../common/crash.h" -#include "../common/eqemu_logsys.h" -#include "../common/http/httplib.h" -#include "login_server.h" -#include "loginserver_webserver.h" -#include "loginserver_command_handler.h" -#include "../common/strings.h" -#include "../common/path_manager.h" -#include "../common/database.h" -#include "../common/events/player_event_logs.h" -#include "../common/zone_store.h" -#include +#include "common/crash.h" +#include "common/database.h" +#include "common/eqemu_logsys.h" +#include "common/event/event_loop.h" +#include "common/events/player_event_logs.h" +#include "common/http/httplib.h" +#include "common/opcodemgr.h" +#include "common/path_manager.h" +#include "common/platform.h" +#include "common/strings.h" +#include "common/timer.h" +#include "common/types.h" +#include "common/zone_store.h" +#include "loginserver/login_server.h" +#include "loginserver/loginserver_command_handler.h" +#include "loginserver/loginserver_webserver.h" + +#include #include #include -#include #include +#include LoginServer server; bool run_server = true; Database database; -void CatchSignal(int sig_num) -{ -} - void LoadDatabaseConnection() { LogInfo("MySQL Database Init"); diff --git a/loginserver/options.h b/loginserver/options.h index 73d6f62169..e2578454c5 100644 --- a/loginserver/options.h +++ b/loginserver/options.h @@ -1,5 +1,6 @@ -#ifndef EQEMU_OPTIONS_H -#define EQEMU_OPTIONS_H +#pragma once + +#include class Options { public: @@ -51,7 +52,3 @@ class Options { std::string m_eqemu_loginserver_address; std::string m_default_loginserver_name; }; - - -#endif - diff --git a/loginserver/world_server.cpp b/loginserver/world_server.cpp index 44e6049d1f..85b9d6c74f 100644 --- a/loginserver/world_server.cpp +++ b/loginserver/world_server.cpp @@ -1,10 +1,11 @@ #include "world_server.h" -#include "login_server.h" -#include "login_types.h" -#include "../common/ip_util.h" -#include "../common/strings.h" -#include "../common/repositories/login_world_servers_repository.h" -#include "../common/repositories/login_server_admins_repository.h" + +#include "common/ip_util.h" +#include "common/repositories/login_server_admins_repository.h" +#include "common/repositories/login_world_servers_repository.h" +#include "common/strings.h" +#include "loginserver/login_server.h" +#include "loginserver/login_types.h" extern LoginServer server; extern Database database; diff --git a/loginserver/world_server.h b/loginserver/world_server.h index f5120d38eb..5cd5043105 100644 --- a/loginserver/world_server.h +++ b/loginserver/world_server.h @@ -1,16 +1,15 @@ -#ifndef EQEMU_WORLDSERVER_H -#define EQEMU_WORLDSERVER_H +#pragma once + +#include "common/event/timer.h" +#include "common/net/servertalk_server_connection.h" +#include "common/packet_dump.h" +#include "common/repositories/login_server_admins_repository.h" +#include "common/servertalk.h" +#include "loginserver/client.h" +#include "loginserver/login_types.h" -#include "../common/global_define.h" -#include "../common/net/servertalk_server_connection.h" -#include "../common/servertalk.h" -#include "../common/packet_dump.h" -#include "../common/event/timer.h" -#include "login_types.h" -#include "client.h" -#include "../common/repositories/login_server_admins_repository.h" -#include #include +#include /** * World server class, controls the connected server processing. @@ -84,6 +83,3 @@ class WorldServer { static void FormatWorldServerName(char *name, int8 server_list_type); }; - -#endif - diff --git a/loginserver/world_server_manager.cpp b/loginserver/world_server_manager.cpp index f18b485375..9c12190719 100644 --- a/loginserver/world_server_manager.cpp +++ b/loginserver/world_server_manager.cpp @@ -1,10 +1,11 @@ #include "world_server_manager.h" -#include "login_server.h" -#include "login_types.h" -#include -#include "../common/eqemu_logsys.h" -#include "../common/ip_util.h" +#include "common/eqemu_logsys.h" +#include "common/ip_util.h" +#include "loginserver/login_server.h" +#include "loginserver/login_types.h" + +#include extern LoginServer server; extern bool run_server; diff --git a/loginserver/world_server_manager.h b/loginserver/world_server_manager.h index 711bc75603..6ed6ed96c6 100644 --- a/loginserver/world_server_manager.h +++ b/loginserver/world_server_manager.h @@ -1,12 +1,11 @@ -#ifndef EQEMU_SERVERMANAGER_H -#define EQEMU_SERVERMANAGER_H +#pragma once + +#include "common/net/servertalk_server.h" +#include "common/packet_dump.h" +#include "common/servertalk.h" +#include "loginserver/client.h" +#include "loginserver/world_server.h" -#include "../common/global_define.h" -#include "../common/servertalk.h" -#include "../common/packet_dump.h" -#include "../common/net/servertalk_server.h" -#include "world_server.h" -#include "client.h" #include class WorldServerManager { @@ -26,8 +25,4 @@ class WorldServerManager { private: std::unique_ptr m_server_connection; std::list> m_world_servers; - }; - -#endif - From ed2344dc99238809621f2d4e4cc6ef0ef845b34b Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 00:27:40 -0800 Subject: [PATCH 074/194] normalize includes: ucs --- ucs/CMakeLists.txt | 1 + ucs/chatchannel.cpp | 12 ++++++----- ucs/chatchannel.h | 11 ++++------ ucs/clientlist.cpp | 24 ++++++++++------------ ucs/clientlist.h | 14 ++++++------- ucs/database.cpp | 50 ++++++++++++++++----------------------------- ucs/database.h | 27 ++++++++++-------------- ucs/ucs.cpp | 42 ++++++++++++++++++------------------- ucs/ucsconfig.cpp | 2 -- ucs/ucsconfig.h | 8 ++------ ucs/worldserver.cpp | 41 ++++++++++++++++++------------------- ucs/worldserver.h | 11 +++++----- 12 files changed, 105 insertions(+), 138 deletions(-) diff --git a/ucs/CMakeLists.txt b/ucs/CMakeLists.txt index 73a78abb81..f33fa9a51a 100644 --- a/ucs/CMakeLists.txt +++ b/ucs/CMakeLists.txt @@ -24,6 +24,7 @@ install(TARGETS ucs RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) add_definitions(-DUCS) target_link_libraries(ucs common) +target_include_directories(ucs PRIVATE ..) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set_property(TARGET ucs PROPERTY FOLDER executables/servers) diff --git a/ucs/chatchannel.cpp b/ucs/chatchannel.cpp index 1e0e0598f1..001bf58b76 100644 --- a/ucs/chatchannel.cpp +++ b/ucs/chatchannel.cpp @@ -17,13 +17,15 @@ */ -#include "../common/eqemu_logsys.h" -#include "../common/strings.h" #include "chatchannel.h" -#include "clientlist.h" -#include "database.h" -#include + +#include "common/eqemu_logsys.h" +#include "common/strings.h" +#include "ucs/clientlist.h" +#include "ucs/database.h" + #include +#include extern UCSDatabase database; extern uint32 ChatMessagesSent; diff --git a/ucs/chatchannel.h b/ucs/chatchannel.h index f9bba0c958..260a0a0eb1 100644 --- a/ucs/chatchannel.h +++ b/ucs/chatchannel.h @@ -1,9 +1,8 @@ -#ifndef CHATCHANNEL_H -#define CHATCHANNEL_H +#pragma once + +#include "common/linked_list.h" +#include "common/timer.h" -//#include "clientlist.h" -#include "../common/linked_list.h" -#include "../common/timer.h" #include #include @@ -102,5 +101,3 @@ class ChatChannelList { }; std::string CapitaliseName(const std::string& inString); - -#endif diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index 749b9276f4..03ab790739 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -17,22 +17,20 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/strings.h" -#include "../common/eqemu_logsys.h" -#include "../common/misc_functions.h" - -#include "ucsconfig.h" -#include "clientlist.h" -#include "database.h" -#include "chatchannel.h" -#include "../common/path_manager.h" +#include "common/eqemu_logsys.h" +#include "common/misc_functions.h" +#include "common/path_manager.h" +#include "common/strings.h" +#include "ucs/chatchannel.h" +#include "ucs/clientlist.h" +#include "ucs/database.h" +#include "ucs/ucsconfig.h" +#include +#include #include -#include #include -#include -#include +#include extern UCSDatabase database; extern std::string WorldShortName; diff --git a/ucs/clientlist.h b/ucs/clientlist.h index feb136e2bd..90d9fa1935 100644 --- a/ucs/clientlist.h +++ b/ucs/clientlist.h @@ -17,13 +17,13 @@ */ -#ifndef CHATSERVER_CLIENTLIST_H -#define CHATSERVER_CLIENTLIST_H +#pragma once + +#include "common/net/eqstream.h" +#include "common/opcodemgr.h" +#include "common/rulesys.h" +#include "ucs/chatchannel.h" -#include "../common/opcodemgr.h" -#include "../common/net/eqstream.h" -#include "../common/rulesys.h" -#include "chatchannel.h" #include #include @@ -197,5 +197,3 @@ class Clientlist { OpcodeManager *ChatOpMgr; }; - -#endif diff --git a/ucs/database.cpp b/ucs/database.cpp index 356180a2e0..21df0c40b2 100644 --- a/ucs/database.cpp +++ b/ucs/database.cpp @@ -17,41 +17,27 @@ */ +#include "database.h" -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "common/eq_packet_structs.h" +#include "common/eqemu_logsys.h" +#include "common/misc_functions.h" +#include "common/platform/platform.h" +#include "common/repositories/chatchannel_reserved_names_repository.h" +#include "common/repositories/chatchannels_repository.h" +#include "common/repositories/name_filter_repository.h" +#include "common/strings.h" +#include "ucs/chatchannel.h" + +#include "mysqld_error.h" +#include +#include +#include +#include +#include +#include #include -// Disgrace: for windows compile -#ifdef _WINDOWS -#include -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#else - -#include "../common/unix.h" -#include - -#endif - -#include "database.h" -#include "../common/eq_packet_structs.h" -#include "../common/misc_functions.h" -#include "../common/strings.h" -#include "chatchannel.h" -#include "../common/repositories/chatchannel_reserved_names_repository.h" -#include "../common/repositories/chatchannels_repository.h" -#include "../common/repositories/name_filter_repository.h" - extern Clientlist *g_Clientlist; extern std::string GetMailPrefix(); extern ChatChannelList *ChannelList; diff --git a/ucs/database.h b/ucs/database.h index 3a5860348b..6bfbbeea9f 100644 --- a/ucs/database.h +++ b/ucs/database.h @@ -17,24 +17,22 @@ */ -#ifndef CHATSERVER_DATABASE_H -#define CHATSERVER_DATABASE_H +#pragma once -#define AUTHENTICATION_TIMEOUT 60 -#define INVALID_ID 0xFFFFFFFF +#include "common/database.h" +#include "common/database.h" +#include "common/linked_list.h" +#include "common/shareddb.h" +#include "common/types.h" +#include "ucs/chatchannel.h" +#include "ucs/clientlist.h" -#include "../common/global_define.h" -#include "../common/types.h" -#include "../common/database.h" -#include "../common/linked_list.h" -#include "../common/database.h" -#include "clientlist.h" -#include "chatchannel.h" -#include "../common/shareddb.h" +#include #include #include -#include +#define AUTHENTICATION_TIMEOUT 60 +#define INVALID_ID 0xFFFFFFFF class UCSDatabase : public Database { public: @@ -62,6 +60,3 @@ class UCSDatabase : public Database { void RemoveFriendOrIgnore(const int& char_id, const int& type, const std::string& name); void GetFriendsAndIgnore(const int& char_id, std::vector &Friends, std::vector &Ignorees); }; - -#endif - diff --git a/ucs/ucs.cpp b/ucs/ucs.cpp index f74bb79c16..57b4630be4 100644 --- a/ucs/ucs.cpp +++ b/ucs/ucs.cpp @@ -17,31 +17,29 @@ */ -#include "../common/eqemu_logsys.h" -#include "../common/global_define.h" -#include "clientlist.h" -#include "../common/opcodemgr.h" -#include "../common/rulesys.h" -#include "../common/servertalk.h" -#include "../common/platform.h" -#include "../common/crash.h" -#include "../common/event/event_loop.h" -#include "database.h" -#include "ucsconfig.h" -#include "chatchannel.h" -#include "worldserver.h" -#include -#include +#include "common/crash.h" +#include "common/discord/discord_manager.h" +#include "common/eqemu_logsys.h" +#include "common/event/event_loop.h" +#include "common/events/player_event_logs.h" +#include "common/net/servertalk_client_connection.h" +#include "common/net/tcp_server.h" +#include "common/opcodemgr.h" +#include "common/path_manager.h" +#include "common/platform.h" +#include "common/rulesys.h" +#include "common/servertalk.h" +#include "common/zone_store.h" +#include "ucs/chatchannel.h" +#include "ucs/clientlist.h" +#include "ucs/database.h" +#include "ucs/ucsconfig.h" +#include "ucs/worldserver.h" + #include +#include #include -#include "../common/net/tcp_server.h" -#include "../common/net/servertalk_client_connection.h" -#include "../common/discord/discord_manager.h" -#include "../common/path_manager.h" -#include "../common/zone_store.h" -#include "../common/events/player_event_logs.h" - ChatChannelList *ChannelList; Clientlist *g_Clientlist; UCSDatabase database; diff --git a/ucs/ucsconfig.cpp b/ucs/ucsconfig.cpp index dd8c73ab80..2d9d177830 100644 --- a/ucs/ucsconfig.cpp +++ b/ucs/ucsconfig.cpp @@ -17,7 +17,6 @@ */ -#include "../common/global_define.h" #include "ucsconfig.h" ucsconfig *ucsconfig::_chat_config = nullptr; @@ -25,4 +24,3 @@ ucsconfig *ucsconfig::_chat_config = nullptr; std::string ucsconfig::GetByName(const std::string &var_name) const { return(EQEmuConfig::GetByName(var_name)); } - diff --git a/ucs/ucsconfig.h b/ucs/ucsconfig.h index 887ff821b9..a6b8dc7787 100644 --- a/ucs/ucsconfig.h +++ b/ucs/ucsconfig.h @@ -17,10 +17,9 @@ */ -#ifndef __ucsconfig_H -#define __ucsconfig_H +#pragma once -#include "../common/eqemu_config.h" +#include "common/eqemu_config.h" class ucsconfig : public EQEmuConfig { public: @@ -50,6 +49,3 @@ class ucsconfig : public EQEmuConfig { } }; - -#endif - diff --git a/ucs/worldserver.cpp b/ucs/worldserver.cpp index 48e85f1813..c3ee7a0ca7 100644 --- a/ucs/worldserver.cpp +++ b/ucs/worldserver.cpp @@ -15,28 +15,27 @@ 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 "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/servertalk.h" -#include "../common/misc_functions.h" -#include "../common/packet_functions.h" -#include "../common/md5.h" -#include "../common/strings.h" + #include "worldserver.h" -#include "clientlist.h" -#include "ucsconfig.h" -#include "database.h" -#include "../common/discord/discord_manager.h" -#include "../common/events/player_event_logs.h" -#include "../common/server_reload_types.h" - -#include -#include -#include -#include -#include -#include -#include + +#include "common/discord/discord_manager.h" +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/md5.h" +#include "common/misc_functions.h" +#include "common/packet_functions.h" +#include "common/server_reload_types.h" +#include "common/servertalk.h" +#include "common/strings.h" +#include "ucs/clientlist.h" +#include "ucs/database.h" +#include "ucs/ucsconfig.h" + +#include +#include +#include +#include +#include extern WorldServer worldserver; extern Clientlist *g_Clientlist; diff --git a/ucs/worldserver.h b/ucs/worldserver.h index 9617a1f955..b425820694 100644 --- a/ucs/worldserver.h +++ b/ucs/worldserver.h @@ -15,11 +15,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef WORLDSERVER_H -#define WORLDSERVER_H -#include "../common/net/servertalk_client_connection.h" -#include "../common/eq_packet_structs.h" +#pragma once + +#include "common/eq_packet_structs.h" +#include "common/net/servertalk_client_connection.h" + #include class WorldServer @@ -33,5 +34,3 @@ class WorldServer std::unique_ptr m_connection; }; -#endif - From b95016c92f176aa8b65dab18c2d02bc94a59a1bd Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 00:28:20 -0800 Subject: [PATCH 075/194] remove global_define.h: queryserv & shared_memory --- queryserv/database.cpp | 2 -- queryserv/database.h | 1 - queryserv/queryserv.cpp | 1 - queryserv/queryservconfig.cpp | 1 - queryserv/worldserver.cpp | 1 - queryserv/zoneserver.cpp | 1 - shared_memory/items.cpp | 1 - shared_memory/main.cpp | 1 - shared_memory/spells.cpp | 1 - 9 files changed, 10 deletions(-) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index 5af3e3edc3..a69b958462 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -2,10 +2,8 @@ #include "database.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/strings.h" -#include #include // this function does not delete the ServerPacket, so it must be handled at call site diff --git a/queryserv/database.h b/queryserv/database.h index 083b232f71..0f9cc6e2ad 100644 --- a/queryserv/database.h +++ b/queryserv/database.h @@ -2,7 +2,6 @@ #include "common/database.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/linked_list.h" #include "common/servertalk.h" #include "common/types.h" diff --git a/queryserv/queryserv.cpp b/queryserv/queryserv.cpp index b5dd1b5f9e..aa0fb2a256 100644 --- a/queryserv/queryserv.cpp +++ b/queryserv/queryserv.cpp @@ -3,7 +3,6 @@ #include "common/eqemu_logsys.h" #include "common/event/event_loop.h" #include "common/events/player_event_logs.h" -#include "common/global_define.h" #include "common/net/console_server.h" #include "common/net/servertalk_server.h" #include "common/opcodemgr.h" diff --git a/queryserv/queryservconfig.cpp b/queryserv/queryservconfig.cpp index 2383b76f61..2db9604aec 100644 --- a/queryserv/queryservconfig.cpp +++ b/queryserv/queryservconfig.cpp @@ -19,7 +19,6 @@ #include "queryservconfig.h" -#include "common/global_define.h" queryservconfig *queryservconfig::_chat_config = nullptr; diff --git a/queryserv/worldserver.cpp b/queryserv/worldserver.cpp index 78d55a1777..52591aac2b 100644 --- a/queryserv/worldserver.cpp +++ b/queryserv/worldserver.cpp @@ -3,7 +3,6 @@ #include "common/eqemu_logsys.h" #include "common/events/player_event_logs.h" #include "common/events/player_events.h" -#include "common/global_define.h" #include "common/md5.h" #include "common/net/packet.h" #include "common/packet_dump.h" diff --git a/queryserv/zoneserver.cpp b/queryserv/zoneserver.cpp index ca482c7838..05df12f5a5 100644 --- a/queryserv/zoneserver.cpp +++ b/queryserv/zoneserver.cpp @@ -3,7 +3,6 @@ #include "common/discord/discord_manager.h" #include "common/eqemu_logsys.h" #include "common/events/player_event_logs.h" -#include "common/global_define.h" #include "common/repositories/player_event_logs_repository.h" ZoneServer::ZoneServer( diff --git a/shared_memory/items.cpp b/shared_memory/items.cpp index ebd3bc8dc1..b149e56e7a 100644 --- a/shared_memory/items.cpp +++ b/shared_memory/items.cpp @@ -19,7 +19,6 @@ #include "items.h" #include "common/eqemu_exception.h" -#include "common/global_define.h" #include "common/ipc_mutex.h" #include "common/item_data.h" #include "common/memory_mapped_file.h" diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index b3f1d83af0..5d18d78a6b 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -25,7 +25,6 @@ #include "common/eqemu_logsys.h" #include "common/events/player_event_logs.h" #include "common/evolving_items.h" -#include "common/global_define.h" #include "common/path_manager.h" #include "common/platform.h" #include "common/rulesys.h" diff --git a/shared_memory/spells.cpp b/shared_memory/spells.cpp index e5db69cdcd..d4c28d9498 100644 --- a/shared_memory/spells.cpp +++ b/shared_memory/spells.cpp @@ -19,7 +19,6 @@ #include "spells.h" #include "common/eqemu_exception.h" -#include "common/global_define.h" #include "common/ipc_mutex.h" #include "common/memory_mapped_file.h" #include "common/shareddb.h" From c191ec02d40a12592bc7e6f1fa6e327e4b42ec3f Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 00:40:06 -0800 Subject: [PATCH 076/194] remove global_define.h and adjust platform header includes - Remove unused MRMutex - Remove unused generate_key --- client_files/export/main.cpp | 1 - client_files/import/main.cpp | 1 - common/CMakeLists.txt | 1 - common/StackWalker/StackWalker.h | 2 +- common/base_packet.cpp | 1 - common/base_packet.h | 11 +-- common/bodytypes.cpp | 2 - common/classes.cpp | 1 - common/compression.cpp | 1 - common/condition.h | 6 +- common/crash.cpp | 5 - common/database.cpp | 22 +---- common/database.h | 1 - common/database/database_dump_service.cpp | 7 -- common/database_instances.cpp | 19 +--- common/emu_opcodes.cpp | 1 - common/eq_packet.cpp | 1 - common/eq_stream_ident.cpp | 1 - common/eq_stream_proxy.cpp | 1 - common/eqdb.cpp | 1 - common/eqdb_res.cpp | 1 - common/eqemu_config.cpp | 1 - common/eqtime.cpp | 8 -- common/event/event_loop.h | 5 +- common/extprofile.cpp | 2 - common/global_define.h | 14 --- common/misc.cpp | 21 ---- common/misc.h | 1 - common/misc_functions.cpp | 7 +- common/mutex.cpp | 99 ------------------- common/mutex.h | 37 +------ common/opcode_map.cpp | 2 - common/packet_dump_file.cpp | 26 ++--- common/packet_dump_file.h | 2 - common/packet_functions.cpp | 5 +- common/patches/patches.cpp | 1 - common/patches/rof.cpp | 1 - common/patches/rof2.cpp | 1 - common/patches/sod.cpp | 1 - common/patches/sof.cpp | 1 - common/patches/titanium.cpp | 1 - common/patches/uf.cpp | 1 - common/pch/app-pch.h | 1 - common/perl_eqdb.cpp | 1 - common/perl_eqdb_res.cpp | 1 - common/platform/platform.h | 2 +- common/proc_launcher.cpp | 4 +- common/proc_launcher.h | 6 +- common/ptimer.cpp | 1 - .../character_evolving_items_repository.h | 2 - ...character_expedition_lockouts_repository.h | 1 + common/struct_strategy.cpp | 1 - common/timeoutmgr.cpp | 2 - common/timer.cpp | 6 +- common/timer.h | 4 +- common/util/win_dirent.h | 5 +- eqlaunch/eqlaunch.cpp | 6 +- eqlaunch/worldserver.cpp | 1 - eqlaunch/zone_launch.cpp | 1 - 59 files changed, 38 insertions(+), 331 deletions(-) diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index 1e845441aa..333528b643 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -23,7 +23,6 @@ #include "common/events/player_event_logs.h" #include "common/evolving_items.h" #include "common/file.h" -#include "common/global_define.h" #include "common/path_manager.h" #include "common/platform.h" #include "common/repositories/base_data_repository.h" diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp index e24cdff8e5..b09eba0642 100644 --- a/client_files/import/main.cpp +++ b/client_files/import/main.cpp @@ -23,7 +23,6 @@ #include "common/events/player_event_logs.h" #include "common/evolving_items.h" #include "common/file.h" -#include "common/global_define.h" #include "common/path_manager.h" #include "common/platform.h" #include "common/repositories/base_data_repository.h" diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 22dd6f9030..3f8b299346 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -604,7 +604,6 @@ set(common_headers file.h fixed_memory_hash_set.h fixed_memory_variable_hash_set.h - global_define.h guild_base.h guilds.h http/httplib.h diff --git a/common/StackWalker/StackWalker.h b/common/StackWalker/StackWalker.h index 0c3236ffbe..ec233d9fa9 100644 --- a/common/StackWalker/StackWalker.h +++ b/common/StackWalker/StackWalker.h @@ -14,7 +14,7 @@ // so we need not to check the version (because we only support _MSC_VER >= 1100)! #pragma once -#include +#include "common/platform/win/include_windows.h" // special defines for VC5/6 (if no actual PSDK is installed): #if _MSC_VER < 1300 diff --git a/common/base_packet.cpp b/common/base_packet.cpp index 15608c2bb7..0fdfe22c12 100644 --- a/common/base_packet.cpp +++ b/common/base_packet.cpp @@ -17,7 +17,6 @@ */ #include "common/base_packet.h" -#include "common/global_define.h" #include "common/misc.h" #include "common/packet_dump.h" diff --git a/common/base_packet.h b/common/base_packet.h index 803f37b8d2..463bc2faf3 100644 --- a/common/base_packet.h +++ b/common/base_packet.h @@ -18,20 +18,11 @@ #pragma once +#include "common/platform/inet.h" #include "common/serialize_buffer.h" #include "common/types.h" #include -#include - -#ifdef _WINDOWS - #include - #include - #include -#else - #include - #include -#endif class BasePacket { public: diff --git a/common/bodytypes.cpp b/common/bodytypes.cpp index 9de4130f4f..650f25f585 100644 --- a/common/bodytypes.cpp +++ b/common/bodytypes.cpp @@ -1,7 +1,5 @@ #include "bodytypes.h" -#include "common/global_define.h" - std::string BodyType::GetName(uint8 body_type_id) { return IsValid(body_type_id) ? body_type_names[body_type_id] : "UNKNOWN BODY TYPE"; diff --git a/common/classes.cpp b/common/classes.cpp index 704c3c97f0..babd08d64b 100644 --- a/common/classes.cpp +++ b/common/classes.cpp @@ -19,7 +19,6 @@ #include "classes.h" #include "common/data_verification.h" -#include "common/global_define.h" #include "fmt/format.h" diff --git a/common/compression.cpp b/common/compression.cpp index 2f8233b286..7b45874614 100644 --- a/common/compression.cpp +++ b/common/compression.cpp @@ -1,6 +1,5 @@ #include "compression.h" -#include "common/global_define.h" #include "common/types.h" #include "zlib.h" diff --git a/common/condition.h b/common/condition.h index 7402589e7b..aba13eb12a 100644 --- a/common/condition.h +++ b/common/condition.h @@ -18,11 +18,9 @@ #pragma once -#include "common/global_define.h" #include "common/mutex.h" -#ifndef WIN32 -#include -#endif +#include "common/platform/posix/include_pthreads.h" +#include "common/platform/win/include_windows.h" //Sombody, someday needs to figure out how to implement a condition //system on windows... diff --git a/common/crash.cpp b/common/crash.cpp index 93eb739ea8..7cde8bb300 100644 --- a/common/crash.cpp +++ b/common/crash.cpp @@ -2,7 +2,6 @@ #include "common/eqemu_config.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/http/httplib.h" #include "common/http/uri.h" #include "common/json/json.h" @@ -16,10 +15,6 @@ #include #include -#ifdef _WINDOWS -#define popen _popen -#endif - void SendCrashReport(const std::string &crash_report) { // can configure multiple endpoints if need be diff --git a/common/database.cpp b/common/database.cpp index e0532037dc..7850dd8961 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -22,9 +22,9 @@ #include "common/eq_packet_structs.h" #include "common/events/player_event_logs.h" #include "common/extprofile.h" -#include "common/global_define.h" #include "common/http/httplib.h" #include "common/http/uri.h" +#include "common/platform/win/include_windows.h" #include "common/repositories/account_repository.h" #include "common/repositories/adventure_stats_repository.h" #include "common/repositories/bot_data_repository.h" @@ -56,29 +56,9 @@ #include "common/strings.h" #include "common/zone_store.h" -#include "mysqld_error.h" - -#include -#include -#include -#include -#include -#include #include #include -// Disgrace: for windows compile -#ifdef _WINDOWS -#include -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#else -#include "unix.h" -#include -#include -#endif - extern Client client; Database::Database() { } diff --git a/common/database.h b/common/database.h index 8a0f333d06..425cb58183 100644 --- a/common/database.h +++ b/common/database.h @@ -21,7 +21,6 @@ #include "common/dbcore.h" #include "common/eq_packet_structs.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/linked_list.h" #include "common/types.h" diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index dc36040ee4..ae66afff9b 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -28,17 +28,10 @@ #include "common/strings.h" #include "common/termcolor/rang.hpp" -#include #include #include #include -#if _WIN32 -#include -#else -#include -#include -#endif #define DATABASE_DUMP_PATH "backups/" diff --git a/common/database_instances.cpp b/common/database_instances.cpp index 05af2aeccb..117e47b42d 100644 --- a/common/database_instances.cpp +++ b/common/database_instances.cpp @@ -18,7 +18,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "database.h" -#include "common/global_define.h" +#include "common/platform/inet.h" +#include "common/platform/platform" +#include "common/platform/win/include_windows.h" #include "common/repositories/character_corpses_repository.h" #include "common/repositories/data_buckets_repository.h" #include "common/repositories/dynamic_zone_members_repository.h" @@ -34,22 +36,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "common/rulesys.h" #include "common/strings.h" #include "common/timer.h" - -#include -#include - -// Disgrace: for windows compile -#ifdef _WINDOWS -#include -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#else #include "common/unix.h" #include "zone/zonedb.h" -#include -#include -#endif + bool Database::AddClientToInstance(uint16 instance_id, uint32 character_id) diff --git a/common/emu_opcodes.cpp b/common/emu_opcodes.cpp index 6e9ad93f82..c39952cc86 100644 --- a/common/emu_opcodes.cpp +++ b/common/emu_opcodes.cpp @@ -17,7 +17,6 @@ */ #include "common/emu_opcodes.h" -#include "common/global_define.h" const char *OpcodeNames[_maxEmuOpcode+1] = { "OP_Unknown", diff --git a/common/eq_packet.cpp b/common/eq_packet.cpp index f8797b67df..1c494950cc 100644 --- a/common/eq_packet.cpp +++ b/common/eq_packet.cpp @@ -18,7 +18,6 @@ #include "eq_packet.h" -#include "common/global_define.h" #include "common/misc.h" #include "common/op_codes.h" #ifndef STATIC_OPCODE diff --git a/common/eq_stream_ident.cpp b/common/eq_stream_ident.cpp index f07a54533c..f6de9ca45b 100644 --- a/common/eq_stream_ident.cpp +++ b/common/eq_stream_ident.cpp @@ -2,7 +2,6 @@ #include "common/eq_stream_ident.h" #include "common/eq_stream_proxy.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/misc.h" #include diff --git a/common/eq_stream_proxy.cpp b/common/eq_stream_proxy.cpp index e2e0884913..f497e0e573 100644 --- a/common/eq_stream_proxy.cpp +++ b/common/eq_stream_proxy.cpp @@ -2,7 +2,6 @@ #include "eq_stream_proxy.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/opcodemgr.h" #include "common/struct_strategy.h" diff --git a/common/eqdb.cpp b/common/eqdb.cpp index f2a4b8a527..05b82b6448 100644 --- a/common/eqdb.cpp +++ b/common/eqdb.cpp @@ -19,7 +19,6 @@ #include "eqdb.h" #include "common/database.h" -#include "common/global_define.h" #include "mysql.h" #include diff --git a/common/eqdb_res.cpp b/common/eqdb_res.cpp index 1fc7b2ecbb..2229fa06c5 100644 --- a/common/eqdb_res.cpp +++ b/common/eqdb_res.cpp @@ -18,7 +18,6 @@ #include "eqdb_res.h" -#include "common/global_define.h" #include "mysql.h" std::vector EQDBRes::fetch_row_array() { diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index 963607ace6..db3faa6424 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -19,7 +19,6 @@ #include "eqemu_config.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/json/json.hpp" #include "common/misc_functions.h" #include "common/strings.h" diff --git a/common/eqtime.cpp b/common/eqtime.cpp index 7fc34315c5..001cdb8370 100644 --- a/common/eqtime.cpp +++ b/common/eqtime.cpp @@ -20,19 +20,11 @@ #include "common/eq_packet_structs.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include #include #include - /*#ifdef _CRTDBG_MAP_ALLOC - #undef new - #endif*/ - /*#ifdef _CRTDBG_MAP_ALLOC - #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) - #endif*/ - #define EQT_VERSION 1000 //Constructor diff --git a/common/event/event_loop.h b/common/event/event_loop.h index 8d7ee6a0dd..4ef532d98d 100644 --- a/common/event/event_loop.h +++ b/common/event/event_loop.h @@ -1,8 +1,7 @@ #pragma once -#include "uv.h" - -#include +#include "common/platform/win/include_windows.h" // uv.h is going to include it so lets do it first. +#include "uv.h" // FIXME: hide this namespace EQ { diff --git a/common/extprofile.cpp b/common/extprofile.cpp index 5fd4d44711..a4c8727a71 100644 --- a/common/extprofile.cpp +++ b/common/extprofile.cpp @@ -18,8 +18,6 @@ #include "extprofile.h" -#include "common/global_define.h" - //Set defaults in the extended profile... void InitExtendedProfile(ExtendedProfile_Struct *p) { memset(p, 0, sizeof(ExtendedProfile_Struct)); diff --git a/common/global_define.h b/common/global_define.h index 8c4755d842..350225ca52 100644 --- a/common/global_define.h +++ b/common/global_define.h @@ -17,17 +17,3 @@ */ #pragma once - -// WHY IS THIS UP HERE -#if defined(_DEBUG) && defined(WIN32) - #ifndef _CRTDBG_MAP_ALLOC - #include - #include - #endif -#endif - - -#ifdef _WINDOWS - #include - #include -#endif diff --git a/common/misc.cpp b/common/misc.cpp index 5927dbb414..52e5086bbd 100644 --- a/common/misc.cpp +++ b/common/misc.cpp @@ -1,6 +1,5 @@ #include "misc.h" -#include "common/global_define.h" #include "common/strings.h" #include "common/types.h" @@ -12,9 +11,6 @@ #include #include #include -#ifndef WIN32 -#include -#endif std::map DBFieldNames; @@ -341,23 +337,6 @@ char *bptr; return (bptr-buffer); } -std::string generate_key(int length) -{ -std::string key; -//TODO: write this for win32... -#ifndef WIN32 -int i; -timeval now; - static const char *chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - for(i=0;i -#include - +#include +#include #define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp #else #include #include diff --git a/common/mutex.cpp b/common/mutex.cpp index 9f2fe3889c..852f523436 100644 --- a/common/mutex.cpp +++ b/common/mutex.cpp @@ -18,8 +18,6 @@ #include "mutex.h" -#include "common/global_define.h" - #include #define DEBUG_MUTEX_CLASS 0 @@ -163,100 +161,3 @@ void LockMutex::lock() { mut->lock(); locked = true; } - - -MRMutex::MRMutex() { - rl = 0; - wr = 0; - rl = 0; -} - -MRMutex::~MRMutex() { -#ifdef _EQDEBUG - if (wl || rl) { - std::cout << "MRMutex::~MRMutex: poor cleanup detected: rl=" << rl << ", wl=" << wl << std::endl; - } -#endif -} - -void MRMutex::ReadLock() { - while (!TryReadLock()) { - Sleep(1); - } -} - -bool MRMutex::TryReadLock() { - MCounters.lock(); - if (!wr && !wl) { - rl++; - MCounters.unlock(); - return true; - } - else { - MCounters.unlock(); - return false; - } -} - -void MRMutex::UnReadLock() { - MCounters.lock(); - rl--; - MCounters.unlock(); -} - -void MRMutex::WriteLock() { - MCounters.lock(); - if (!rl && !wl) { - wl++; - MCounters.unlock(); - return; - } - else { - wr++; - MCounters.unlock(); - while (1) { - Sleep(1); - MCounters.lock(); - if (!rl && !wl) { - wr--; - MCounters.unlock(); - return; - } - MCounters.lock(); - } - } -} - -bool MRMutex::TryWriteLock() { - MCounters.lock(); - if (!rl && !wl) { - wl++; - MCounters.unlock(); - return true; - } - else { - MCounters.unlock(); - return false; - } -} - -void MRMutex::UnWriteLock() { - MCounters.lock(); - wl--; - MCounters.unlock(); -} - -int32 MRMutex::ReadLockCount() { - MCounters.lock(); - int32 ret = rl; - MCounters.unlock(); - return ret; -} - -int32 MRMutex::WriteLockCount() { - MCounters.lock(); - int32 ret = wl; - MCounters.unlock(); - return ret; -} - diff --git a/common/mutex.h b/common/mutex.h index d6bbac916c..fc4d248737 100644 --- a/common/mutex.h +++ b/common/mutex.h @@ -19,14 +19,8 @@ #pragma once #include "common/types.h" - -#ifdef _WINDOWS -#include -#include -#else -#include "common/unix.h" -#include -#endif +#include "common/platform/posix/include_pthreads.h" +#include "common/platform/win/include_windows.h" class Mutex { public: @@ -38,7 +32,7 @@ class Mutex { bool trylock(); protected: private: -#if defined WIN32 || defined WIN64 +#if defined _WINDOWS CRITICAL_SECTION CSMutex; #else pthread_mutex_t CSMutex; @@ -55,28 +49,3 @@ class LockMutex { bool locked; Mutex* mut; }; - - -// Somewhat untested... -// Multi-read, single write mutex -Quagmire -class MRMutex { -public: - MRMutex(); - ~MRMutex(); - - void ReadLock(); - bool TryReadLock(); - void UnReadLock(); - - void WriteLock(); - bool TryWriteLock(); - void UnWriteLock(); - - int32 ReadLockCount(); - int32 WriteLockCount(); -private: - int32 rl; // read locks in effect - int32 wr; // write lock requests pending - int32 wl; // write locks in effect (should never be more than 1) - Mutex MCounters; -}; diff --git a/common/opcode_map.cpp b/common/opcode_map.cpp index 8d1aae5b7a..7a07551a6a 100644 --- a/common/opcode_map.cpp +++ b/common/opcode_map.cpp @@ -1,5 +1,3 @@ -#include "common/global_define.h" - #include #include diff --git a/common/packet_dump_file.cpp b/common/packet_dump_file.cpp index f8e4f8ab9e..5d08c983de 100644 --- a/common/packet_dump_file.cpp +++ b/common/packet_dump_file.cpp @@ -16,29 +16,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "common/global_define.h" +#include "packet_dump_file.h" + +#include "common/eq_stream_intf.h" +#include +#include +#include #include #include #include -#include - -//#ifdef _CRTDBG_MAP_ALLOC -// #undef new -// #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) -//#endif -#include - -#ifdef _WINDOWS - #define snprintf _snprintf - #define strncasecmp _strnicmp - #define strcasecmp _stricmp -#else - #include -#endif - -#include "eq_stream_intf.h" -#include "packet_dump_file.h" + void FileDumpPacketAscii(const char* filename, const uchar* buf, uint32 size, uint32 cols, uint32 skip) { std::ofstream logfile(filename, std::ios::app); diff --git a/common/packet_dump_file.h b/common/packet_dump_file.h index c3f3dcc17c..d0e32d69a8 100644 --- a/common/packet_dump_file.h +++ b/common/packet_dump_file.h @@ -20,8 +20,6 @@ #include "common/types.h" -#include - class EQApplicationPacket; void FileDumpPacketAscii(const char* filename, const uchar* buf, uint32 size, uint32 cols=16, uint32 skip=0); diff --git a/common/packet_functions.cpp b/common/packet_functions.cpp index a882107f2a..4979f6d6bc 100644 --- a/common/packet_functions.cpp +++ b/common/packet_functions.cpp @@ -18,16 +18,13 @@ #include "packet_functions.h" -#include "common/global_define.h" #include "common/packet_dump.h" +#include "common/platform/inet.h" #include "zlib.h" #include #include #include -#ifndef WIN32 -#include -#endif void EncryptProfilePacket(EQApplicationPacket* app) { //EncryptProfilePacket(app->pBuffer, app->size); diff --git a/common/patches/patches.cpp b/common/patches/patches.cpp index 6158499726..359739788c 100644 --- a/common/patches/patches.cpp +++ b/common/patches/patches.cpp @@ -19,7 +19,6 @@ #include "patches.h" -#include "common/global_define.h" #include "common/patches/rof.h" #include "common/patches/rof2.h" #include "common/patches/sod.h" diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 0e6f48861a..06074a9293 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -25,7 +25,6 @@ #include "common/eq_stream_ident.h" #include "common/eqemu_config.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/inventory_profile.h" #include "common/misc_functions.h" #include "common/opcodemgr.h" diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index ecefc46321..ddddc27754 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -26,7 +26,6 @@ #include "common/eq_stream_ident.h" #include "common/eqemu_config.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/inventory_profile.h" #include "common/misc_functions.h" #include "common/opcodemgr.h" diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 01bf5f8cf3..27ffcf87dc 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -25,7 +25,6 @@ #include "common/eq_stream_ident.h" #include "common/eqemu_config.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/item_instance.h" #include "common/misc_functions.h" #include "common/opcodemgr.h" diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 1ae60f054b..8c6e3d586b 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -25,7 +25,6 @@ #include "common/eq_stream_ident.h" #include "common/eqemu_config.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/item_instance.h" #include "common/misc_functions.h" #include "common/opcodemgr.h" diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 3852c88085..98c463921d 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -25,7 +25,6 @@ #include "common/eq_stream_ident.h" #include "common/eqemu_config.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/guilds.h" #include "common/item_instance.h" #include "common/misc_functions.h" diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index f126870681..4f36881610 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -26,7 +26,6 @@ #include "common/eq_stream_ident.h" #include "common/eqemu_config.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/guilds.h" #include "common/item_instance.h" #include "common/misc_functions.h" diff --git a/common/pch/app-pch.h b/common/pch/app-pch.h index 32d2b070db..2611490639 100644 --- a/common/pch/app-pch.h +++ b/common/pch/app-pch.h @@ -6,4 +6,3 @@ #include "common/eqemu_logsys.h" #include "common/eqemu_logsys_log_aliases.h" #include "common/features.h" -#include "common/global_define.h" diff --git a/common/perl_eqdb.cpp b/common/perl_eqdb.cpp index 53f3059df7..7d1860c569 100644 --- a/common/perl_eqdb.cpp +++ b/common/perl_eqdb.cpp @@ -28,7 +28,6 @@ typedef const char Const_char; #ifdef EMBPERL -#include "common/global_define.h" #include "common/eqdb.h" #include "common/useperl.h" diff --git a/common/perl_eqdb_res.cpp b/common/perl_eqdb_res.cpp index 32a588ece2..e55dac5ab0 100644 --- a/common/perl_eqdb_res.cpp +++ b/common/perl_eqdb_res.cpp @@ -28,7 +28,6 @@ typedef const char Const_char; #ifdef EMBPERL -#include "common/global_define.h" #include "common/eqdb_res.h" #include "common/useperl.h" diff --git a/common/platform/platform.h b/common/platform/platform.h index 81624a808c..38d9aac321 100644 --- a/common/platform/platform.h +++ b/common/platform/platform.h @@ -3,5 +3,5 @@ #ifdef _WINDOWS #include "common/platform/win/include_windows.h" #else -#include +#include "common/unix.h" #endif diff --git a/common/proc_launcher.cpp b/common/proc_launcher.cpp index 0be460a8e8..80415fe21f 100644 --- a/common/proc_launcher.cpp +++ b/common/proc_launcher.cpp @@ -18,13 +18,13 @@ #include "proc_launcher.h" -#include "common/global_define.h" #include "common/types.h" #include #include + #ifdef _WINDOWS -#include +#include "common/platform/win/include_windows.h" #else #include #include diff --git a/common/proc_launcher.h b/common/proc_launcher.h index 15ff0dd732..5f1f7efff5 100644 --- a/common/proc_launcher.h +++ b/common/proc_launcher.h @@ -18,16 +18,12 @@ #pragma once -#include "common/global_define.h" +#include "common/platform/platform.h" #include #include #include -#ifdef __FreeBSD__ -#include -#endif - //I forced this object to become a singleton because it registers its //signal handler for UNIX class ProcLauncher { diff --git a/common/ptimer.cpp b/common/ptimer.cpp index dfba5f6f97..9ab6a8068d 100644 --- a/common/ptimer.cpp +++ b/common/ptimer.cpp @@ -19,7 +19,6 @@ #include "ptimer.h" #include "common/database.h" -#include "common/global_define.h" #include "common/strings.h" #include "common/timer.h" diff --git a/common/repositories/character_evolving_items_repository.h b/common/repositories/character_evolving_items_repository.h index 7a039dcad7..08dc95c89f 100644 --- a/common/repositories/character_evolving_items_repository.h +++ b/common/repositories/character_evolving_items_repository.h @@ -5,8 +5,6 @@ #include "common/database.h" #include "common/strings.h" -#include - class CharacterEvolvingItemsRepository: public BaseCharacterEvolvingItemsRepository { public: // Custom extended repository methods here diff --git a/common/repositories/character_expedition_lockouts_repository.h b/common/repositories/character_expedition_lockouts_repository.h index 6bc0f91893..4318dbbefc 100644 --- a/common/repositories/character_expedition_lockouts_repository.h +++ b/common/repositories/character_expedition_lockouts_repository.h @@ -5,6 +5,7 @@ #include "common/database.h" #include "common/dynamic_zone_lockout.h" #include "common/strings.h" +#include "fmt/ranges.h" #include diff --git a/common/struct_strategy.cpp b/common/struct_strategy.cpp index 12372a6e29..0c7dc04dd5 100644 --- a/common/struct_strategy.cpp +++ b/common/struct_strategy.cpp @@ -2,7 +2,6 @@ #include "common/eq_stream_intf.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/opcodemgr.h" #include diff --git a/common/timeoutmgr.cpp b/common/timeoutmgr.cpp index ab0746d168..b1b3d3e20f 100644 --- a/common/timeoutmgr.cpp +++ b/common/timeoutmgr.cpp @@ -18,8 +18,6 @@ #include "timeoutmgr.h" -#include "common/global_define.h" - //#define TIMEOUT_DEBUG Timeoutable::Timeoutable(uint32 check_frequency) diff --git a/common/timer.cpp b/common/timer.cpp index 32911f9d99..63b8d6d4bb 100644 --- a/common/timer.cpp +++ b/common/timer.cpp @@ -20,9 +20,11 @@ // Disgrace: for windows compile #ifndef WIN32 - #include +#include #else - #include +#include +#include +#undef GetCurrentTime #endif uint32 current_time = 0; diff --git a/common/timer.h b/common/timer.h index 9a2e2765a7..e7c343c8a9 100644 --- a/common/timer.h +++ b/common/timer.h @@ -22,8 +22,8 @@ // Disgrace: for windows compile #ifdef _WINDOWS - #include "global_define.h" - int gettimeofday (timeval *tp, ...); +struct timeval; +int gettimeofday (timeval *tp, ...); #endif #include diff --git a/common/util/win_dirent.h b/common/util/win_dirent.h index 89f4df49f8..cc78344ced 100644 --- a/common/util/win_dirent.h +++ b/common/util/win_dirent.h @@ -14,10 +14,7 @@ * Include windows.h without Windows Sockets 1.1 to prevent conflicts with * Windows Sockets 2.0. */ -#ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif -#include +#include "common/platform/win/include_windows.h" #include #include diff --git a/eqlaunch/eqlaunch.cpp b/eqlaunch/eqlaunch.cpp index 864852c69f..df5bad2f13 100644 --- a/eqlaunch/eqlaunch.cpp +++ b/eqlaunch/eqlaunch.cpp @@ -19,7 +19,6 @@ #include "common/crash.h" #include "common/eqemu_config.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/path_manager.h" #include "common/platform.h" #include "common/proc_launcher.h" @@ -28,11 +27,10 @@ #include "eqlaunch/worldserver.h" #include "eqlaunch/zone_launch.h" -#include +#include +#include #include #include -#include -#include bool RunLoops = false; diff --git a/eqlaunch/worldserver.cpp b/eqlaunch/worldserver.cpp index ae365c924a..d51841ba36 100644 --- a/eqlaunch/worldserver.cpp +++ b/eqlaunch/worldserver.cpp @@ -20,7 +20,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "common/eqemu_config.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "common/servertalk.h" #include "common/strings.h" #include "eqlaunch/zone_launch.h" diff --git a/eqlaunch/zone_launch.cpp b/eqlaunch/zone_launch.cpp index 84f7ac5634..c848be2efd 100644 --- a/eqlaunch/zone_launch.cpp +++ b/eqlaunch/zone_launch.cpp @@ -20,7 +20,6 @@ #include "common/eqemu_config.h" #include "common/eqemu_logsys.h" -#include "common/global_define.h" #include "eqlaunch/worldserver.h" //static const uint32 ZONE_RESTART_DELAY = 10000; From 3d7101876fe0e6a08347e3a39e57d3a9af196e44 Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 00:40:31 -0800 Subject: [PATCH 077/194] normalize includes: common --- common/cli/eqemu_command_handler.h | 12 ++--- common/crash.cpp | 4 +- common/database.h | 11 ----- common/database_instances.cpp | 2 +- common/dbcore.cpp | 16 +------ common/dbcore.h | 2 - common/eq_packet.cpp | 2 + common/eqemu_logsys.cpp | 4 +- common/event/event_loop.h | 4 +- common/event/timer.h | 1 + common/file.cpp | 13 +----- common/fixed_memory_hash_set.h | 2 +- common/fixed_memory_variable_hash_set.h | 2 +- common/http/httplib.h | 2 +- common/item_instance.cpp | 2 +- common/light_source.cpp | 2 +- common/md5.cpp | 2 +- common/memory_buffer.h | 2 +- common/misc.cpp | 6 +-- common/misc.h | 2 +- common/misc_functions.cpp | 60 +++---------------------- common/misc_functions.h | 7 +-- common/net/reliable_stream_connection.h | 1 - common/opcodemgr.cpp | 2 +- common/packet_dump.cpp | 2 +- common/packet_functions.cpp | 3 +- common/pch/std-pch.h | 5 +++ common/proc_launcher.cpp | 6 +-- common/proc_launcher.h | 1 + common/profanity_manager.cpp | 2 +- common/random.h | 1 - common/seperator.h | 4 +- common/serialize_buffer.h | 1 + common/server_event_scheduler.cpp | 2 +- common/server_event_scheduler.h | 2 +- common/servertalk.h | 1 + common/skills.cpp | 2 +- common/types.h | 3 +- common/unix.cpp | 4 +- 39 files changed, 59 insertions(+), 143 deletions(-) diff --git a/common/cli/eqemu_command_handler.h b/common/cli/eqemu_command_handler.h index d0b0b5b5ea..7ccd30dd93 100644 --- a/common/cli/eqemu_command_handler.h +++ b/common/cli/eqemu_command_handler.h @@ -18,10 +18,13 @@ * */ -#ifndef EQEMU_EQEMU_COMMAND_HANDLER_H -#define EQEMU_EQEMU_COMMAND_HANDLER_H +#pragma once -#include "argh.h" +#include "common/cli/argh.h" + +#include +#include +#include namespace EQEmuCommand { @@ -70,6 +73,3 @@ namespace EQEmuCommand { char **argv ); }; - - -#endif //EQEMU_EQEMU_COMMAND_HANDLER_H diff --git a/common/crash.cpp b/common/crash.cpp index 7cde8bb300..fb8e5a865d 100644 --- a/common/crash.cpp +++ b/common/crash.cpp @@ -220,8 +220,8 @@ void set_exception_handler() { } #else -#include -#include +#include +#include #include #include #include diff --git a/common/database.h b/common/database.h index 425cb58183..580d58add6 100644 --- a/common/database.h +++ b/common/database.h @@ -60,17 +60,6 @@ struct VarCache_Struct { class PTimerList; -#ifdef _WINDOWS -#if _MSC_VER > 1700 // greater than 2012 (2013+) -# define _ISNAN_(a) std::isnan(a) -#else -# include -# define _ISNAN_(a) _isnan(a) -#endif -#else -# define _ISNAN_(a) std::isnan(a) -#endif - #define SQL(...) #__VA_ARGS__ class Database : public DBcore { diff --git a/common/database_instances.cpp b/common/database_instances.cpp index 117e47b42d..674649ff7d 100644 --- a/common/database_instances.cpp +++ b/common/database_instances.cpp @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "database.h" #include "common/platform/inet.h" -#include "common/platform/platform" +#include "common/platform/platform.h" #include "common/platform/win/include_windows.h" #include "common/repositories/character_corpses_repository.h" #include "common/repositories/data_buckets_repository.h" diff --git a/common/dbcore.cpp b/common/dbcore.cpp index 6b8ae9dc4e..b9afaa1c63 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -5,24 +5,10 @@ #include "common/mysql_stmt.h" #include "common/strings.h" #include "common/timer.h" +#include "common/types.h" #include "mysqld_error.h" -#include -#include -#include - -#ifdef _WINDOWS -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#include -#include -#else -#include "common/unix.h" -#include -#endif - #ifdef _EQDEBUG #define DEBUG_MYSQL_QUERIES 0 #else diff --git a/common/dbcore.h b/common/dbcore.h index 978ab96bc4..3368dccfc0 100644 --- a/common/dbcore.h +++ b/common/dbcore.h @@ -5,8 +5,6 @@ #include "common/types.h" #include "mysql.h" - -#include #include #define CR_SERVER_GONE_ERROR 2006 diff --git a/common/eq_packet.cpp b/common/eq_packet.cpp index 1c494950cc..f025efb979 100644 --- a/common/eq_packet.cpp +++ b/common/eq_packet.cpp @@ -28,6 +28,8 @@ #include "common/platform.h" #include +#include +#include EQPacket::EQPacket(EmuOpcode op, const unsigned char *buf, uint32 len) : BasePacket(buf, len), diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp index 8af9dcc6d5..9390a15ef7 100644 --- a/common/eqemu_logsys.cpp +++ b/common/eqemu_logsys.cpp @@ -29,17 +29,15 @@ #include "common/strings.h" #include "common/termcolor/rang.hpp" +#include #include #include #include #include -#include #ifdef _WINDOWS #include #include -#include -#include #include #include #else diff --git a/common/event/event_loop.h b/common/event/event_loop.h index 4ef532d98d..20cc8a10a4 100644 --- a/common/event/event_loop.h +++ b/common/event/event_loop.h @@ -1,8 +1,10 @@ #pragma once -#include "common/platform/win/include_windows.h" // uv.h is going to include it so lets do it first. +#include "common/platform/win/include_windows.h" // uv.h is going to include it so let's do it first. #include "uv.h" // FIXME: hide this +#include + namespace EQ { class EventLoop diff --git a/common/event/timer.h b/common/event/timer.h index c9fe757d91..adf5efc36b 100644 --- a/common/event/timer.h +++ b/common/event/timer.h @@ -2,6 +2,7 @@ #include "event_loop.h" +#include #include namespace EQ { diff --git a/common/file.cpp b/common/file.cpp index 8d56470b16..3661c2ff9b 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -20,6 +20,7 @@ #include "file.h" +#include "common/platform/platform.h" #include "fmt/format.h" #include @@ -28,18 +29,6 @@ #include #include -#ifdef _WINDOWS -#include -#include -#include -#include -#include -#include -#else -#include -#include -#endif - namespace fs = std::filesystem; diff --git a/common/fixed_memory_hash_set.h b/common/fixed_memory_hash_set.h index 17e8d9013c..5677427d21 100644 --- a/common/fixed_memory_hash_set.h +++ b/common/fixed_memory_hash_set.h @@ -21,7 +21,7 @@ #include "common/eqemu_exception.h" #include "common/types.h" -#include +#include namespace EQ { diff --git a/common/fixed_memory_variable_hash_set.h b/common/fixed_memory_variable_hash_set.h index f04387c0c9..7aa8c67530 100644 --- a/common/fixed_memory_variable_hash_set.h +++ b/common/fixed_memory_variable_hash_set.h @@ -21,7 +21,7 @@ #include "common/eqemu_exception.h" #include "common/types.h" -#include +#include namespace EQ { diff --git a/common/http/httplib.h b/common/http/httplib.h index 3c024f9f02..9ade6d9efa 100644 --- a/common/http/httplib.h +++ b/common/http/httplib.h @@ -272,7 +272,7 @@ inline const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *asn1) { #include #endif -#include "../strings.h" +#include "common/strings.h" /* * Declaration diff --git a/common/item_instance.cpp b/common/item_instance.cpp index c624140e09..64ae0b4cc1 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -24,7 +24,7 @@ #include "common/shareddb.h" #include "common/strings.h" -#include +#include int32 next_item_serial_number = 1; std::unordered_set guids{}; diff --git a/common/light_source.cpp b/common/light_source.cpp index 1574144adf..e4f5336c6f 100644 --- a/common/light_source.cpp +++ b/common/light_source.cpp @@ -19,7 +19,7 @@ #include "light_source.h" -#include +#include uint8 EQ::lightsource::TypeToLevel(uint8 light_type) { diff --git a/common/md5.cpp b/common/md5.cpp index 2326fc5e7f..16328d6957 100644 --- a/common/md5.cpp +++ b/common/md5.cpp @@ -13,7 +13,7 @@ #include "common/strings.h" #include "common/seperator.h" -#include /* for memcpy() */ +#include /* for memcpy() */ MD5::MD5() { memset(pMD5, 0, 16); diff --git a/common/memory_buffer.h b/common/memory_buffer.h index bd191d4a5c..3f4ab031b4 100644 --- a/common/memory_buffer.h +++ b/common/memory_buffer.h @@ -21,8 +21,8 @@ #include "common/types.h" +#include #include -#include #include #include diff --git a/common/misc.cpp b/common/misc.cpp index 52e5086bbd..f3e436ae5d 100644 --- a/common/misc.cpp +++ b/common/misc.cpp @@ -4,13 +4,13 @@ #include "common/types.h" #include "zlib.h" +#include +#include #include +#include #include #include -#include -#include #include -#include std::map DBFieldNames; diff --git a/common/misc.h b/common/misc.h index e43bf34c3c..d488e854a8 100644 --- a/common/misc.h +++ b/common/misc.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #define ITEMFIELDCOUNT 116 diff --git a/common/misc_functions.cpp b/common/misc_functions.cpp index a01e7ce5ed..c4bcb7d8e6 100644 --- a/common/misc_functions.cpp +++ b/common/misc_functions.cpp @@ -18,69 +18,20 @@ #include "misc_functions.h" +#include "common/platform/inet.h" +#include "common/platform/platform.h" #include "common/seperator.h" #include "common/strings.h" #include "common/timer.h" +#include "common/types.h" -#include -#include -#include -#include +#include -#ifdef _WINDOWS -#include -#include -#include -#define snprintf _snprintf -#else -#include -#include -#include -#include -#include -#include -#include -#ifdef FREEBSD //Timothy Whitman - January 7, 2003 -#include -#include -#endif +#ifndef _WINDOWS #include -#include #include -#include #endif -void CoutTimestamp(bool ms) { - time_t rawtime; - struct tm* gmt_t; - time(&rawtime); - gmt_t = gmtime(&rawtime); - - struct timeval read_time; - gettimeofday(&read_time,0); - - std::cout << (gmt_t->tm_year + 1900) << "/" << std::setw(2) << std::setfill('0') << (gmt_t->tm_mon + 1) << "/" << std::setw(2) << std::setfill('0') << gmt_t->tm_mday << " " << std::setw(2) << std::setfill('0') << gmt_t->tm_hour << ":" << std::setw(2) << std::setfill('0') << gmt_t->tm_min << ":" << std::setw(2) << std::setfill('0') << gmt_t->tm_sec; - if (ms) - std::cout << "." << std::setw(3) << std::setfill('0') << (read_time.tv_usec / 1000); - std::cout << " GMT"; -} - - -int32 filesize(FILE* fp) { -#ifdef _WINDOWS - return _filelength(_fileno(fp)); -#else - struct stat file_stat; - fstat(fileno(fp), &file_stat); - return (int32) file_stat.st_size; -/* uint32 tmp = 0; - while (!feof(fp)) { - fseek(fp, tmp++, SEEK_SET); - } - return tmp;*/ -#endif -} - uint32 ResolveIP(const char* hostname, char* errbuf) { #ifdef _WINDOWS static InitWinsock ws; @@ -140,7 +91,6 @@ InitWinsock::InitWinsock() { InitWinsock::~InitWinsock() { WSACleanup(); } - #endif diff --git a/common/misc_functions.h b/common/misc_functions.h index 2590877ca2..1db55e4663 100644 --- a/common/misc_functions.h +++ b/common/misc_functions.h @@ -20,10 +20,6 @@ #include "common/types.h" -#include -#include - - #ifndef ERRBUF_SIZE #define ERRBUF_SIZE 1024 #endif @@ -46,10 +42,9 @@ return; \ } -int32 filesize(FILE* fp); uint32 ResolveIP(const char* hostname, char* errbuf = 0); bool ParseAddress(const char* iAddress, uint32* oIP, uint16* oPort, char* errbuf = 0); -void CoutTimestamp(bool ms = true); + float EQ13toFloat(int d); float EQ19toFloat(int d); float EQHtoFloat(int d); diff --git a/common/net/reliable_stream_connection.h b/common/net/reliable_stream_connection.h index e3f4f16d28..756857c77b 100644 --- a/common/net/reliable_stream_connection.h +++ b/common/net/reliable_stream_connection.h @@ -12,7 +12,6 @@ #include #include #include -#include namespace EQ { diff --git a/common/opcodemgr.cpp b/common/opcodemgr.cpp index 771fb439c8..b761f3b8cf 100644 --- a/common/opcodemgr.cpp +++ b/common/opcodemgr.cpp @@ -21,9 +21,9 @@ #include "common/emu_opcodes.h" #include "common/eqemu_logsys.h" +#include #include #include -#include #include OpcodeManager::OpcodeManager() { diff --git a/common/packet_dump.cpp b/common/packet_dump.cpp index 33c7196055..8e638768f8 100644 --- a/common/packet_dump.cpp +++ b/common/packet_dump.cpp @@ -20,10 +20,10 @@ #include "common/servertalk.h" +#include #include #include #include -#include void DumpPacketAscii(const uchar* buf, uint32 size, uint32 cols, uint32 skip) { // Output as ASCII diff --git a/common/packet_functions.cpp b/common/packet_functions.cpp index 4979f6d6bc..4783db9273 100644 --- a/common/packet_functions.cpp +++ b/common/packet_functions.cpp @@ -22,9 +22,8 @@ #include "common/platform/inet.h" #include "zlib.h" -#include +#include #include -#include void EncryptProfilePacket(EQApplicationPacket* app) { //EncryptProfilePacket(app->pBuffer, app->size); diff --git a/common/pch/std-pch.h b/common/pch/std-pch.h index 77ca1ce6f0..f8428dda5c 100644 --- a/common/pch/std-pch.h +++ b/common/pch/std-pch.h @@ -4,11 +4,16 @@ #include "fmt/format.h" // Lightweight, widely used +#include #include +#include #include +#include #include #include #include +#include #include +#include #include #include diff --git a/common/proc_launcher.cpp b/common/proc_launcher.cpp index 80415fe21f..9b11139242 100644 --- a/common/proc_launcher.cpp +++ b/common/proc_launcher.cpp @@ -20,6 +20,9 @@ #include "common/types.h" +#include +#include +#include #include #include @@ -28,14 +31,11 @@ #else #include #include -#include -#include #include #include #include #include #include -#include #endif ProcLauncher ProcLauncher::s_launcher; diff --git a/common/proc_launcher.h b/common/proc_launcher.h index 5f1f7efff5..5a9aa421ea 100644 --- a/common/proc_launcher.h +++ b/common/proc_launcher.h @@ -19,6 +19,7 @@ #pragma once #include "common/platform/platform.h" +#include "common/types.h" #include #include diff --git a/common/profanity_manager.cpp b/common/profanity_manager.cpp index b254459969..200d11f91e 100644 --- a/common/profanity_manager.cpp +++ b/common/profanity_manager.cpp @@ -24,8 +24,8 @@ #include "common/strings.h" #include +#include #include -#include static std::list profanity_list; diff --git a/common/random.h b/common/random.h index a55dece0f4..86dfe9b2b5 100644 --- a/common/random.h +++ b/common/random.h @@ -19,7 +19,6 @@ #pragma once #include -#include #include #include #include diff --git a/common/seperator.h b/common/seperator.h index f4d6ac3807..443f1bf595 100644 --- a/common/seperator.h +++ b/common/seperator.h @@ -25,8 +25,8 @@ #include "common/types.h" -#include -#include +#include +#include class Seperator { diff --git a/common/serialize_buffer.h b/common/serialize_buffer.h index c05456f05d..1155d75068 100644 --- a/common/serialize_buffer.h +++ b/common/serialize_buffer.h @@ -3,6 +3,7 @@ #include #include +#include #include #include diff --git a/common/server_event_scheduler.cpp b/common/server_event_scheduler.cpp index 5e964f38b3..b7294c5ced 100644 --- a/common/server_event_scheduler.cpp +++ b/common/server_event_scheduler.cpp @@ -5,8 +5,8 @@ #include "common/strings.h" #include +#include #include -#include ServerEventScheduler::ServerEventScheduler() { diff --git a/common/server_event_scheduler.h b/common/server_event_scheduler.h index a3c48e9fd5..480f4460ee 100644 --- a/common/server_event_scheduler.h +++ b/common/server_event_scheduler.h @@ -2,7 +2,7 @@ #include "common/repositories/server_scheduled_events_repository.h" -#include +#include #include namespace ServerEvents { diff --git a/common/servertalk.h b/common/servertalk.h index 121d6d7de5..b41e998a59 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -440,6 +440,7 @@ class ServerPacket uint32 destination; }; +#pragma pack(push) #pragma pack(1) struct SPackSendQueue { diff --git a/common/skills.cpp b/common/skills.cpp index 85fae5a27a..96a7ca27dd 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -21,7 +21,7 @@ #include "common/classes.h" -#include +#include bool EQ::skills::IsTradeskill(SkillType skill) { diff --git a/common/types.h b/common/types.h index bb4b39a839..ca00c76b28 100644 --- a/common/types.h +++ b/common/types.h @@ -19,6 +19,7 @@ #pragma once #include + typedef uint8_t byte; typedef uint8_t uint8; typedef uint16_t uint16; @@ -44,7 +45,7 @@ typedef const char Const_char; //for perl XS #ifdef _WINDOWS #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) - #define snprintf _snprintf + #define snprintf _snprintf #endif #define strncasecmp _strnicmp #define strcasecmp _stricmp diff --git a/common/unix.cpp b/common/unix.cpp index 45702280cb..afe3bfef6c 100644 --- a/common/unix.cpp +++ b/common/unix.cpp @@ -19,8 +19,8 @@ #include "unix.h" -#include -#include +#include +#include void Sleep(unsigned int x) { if (x > 0) From 6314b386efc848b057ed3a1c5f8800c520f7fc96 Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 00:40:51 -0800 Subject: [PATCH 078/194] add include dirs to luabind --- libs/luabind/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/luabind/CMakeLists.txt b/libs/luabind/CMakeLists.txt index e871cdf140..1588e882d3 100644 --- a/libs/luabind/CMakeLists.txt +++ b/libs/luabind/CMakeLists.txt @@ -21,8 +21,10 @@ set(lb_sources ) add_library(luabind ${lb_sources}) + target_include_directories(luabind PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${LUAJIT_INCLUDE_DIR}) target_link_libraries(luabind PUBLIC Boost::dynamic_bitset Boost::tuple Boost::foreach ${LUAJIT_LIBRARY}) +target_include_directories(luabind PRIVATE ..) if(UNIX) set_source_files_properties(${lb_sources} PROPERTY COMPILE_FLAGS -Wno-deprecated-declarations) From 552a908f92d0be921889a409b0c31d183594c31e Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 00:45:20 -0800 Subject: [PATCH 079/194] normalize includes: world --- world/CMakeLists.txt | 1 + world/adventure.cpp | 31 ++--- world/adventure.h | 15 +-- world/adventure_manager.cpp | 27 +++-- world/adventure_manager.h | 15 +-- world/adventure_template.h | 11 +- world/cli/cli_bots_disable.cpp | 7 +- world/cli/cli_bots_enable.cpp | 7 +- world/cli/cli_copy_character.cpp | 9 +- world/cli/cli_database_concurrency.cpp | 10 +- world/cli/cli_database_dump.cpp | 5 +- world/cli/cli_database_get_schema.cpp | 14 +-- world/cli/cli_database_set_account_status.cpp | 4 +- world/cli/cli_database_updates.cpp | 7 +- world/cli/cli_database_version.cpp | 11 +- world/cli/cli_etl_get_settings.cpp | 9 +- world/cli/cli_mercs_disable.cpp | 7 +- world/cli/cli_mercs_enable.cpp | 7 +- world/cli/cli_test.cpp | 12 +- world/cli/cli_test_colors.cpp | 7 +- world/cli/cli_test_expansion.cpp | 13 +- world/cli/cli_test_repository.cpp | 7 +- world/cli/cli_test_repository_2.cpp | 7 +- world/cli/cli_test_string_benchmark.cpp | 12 +- world/cli/cli_version.cpp | 9 +- world/client.cpp | 95 +++++++-------- world/client.h | 18 ++- world/cliententry.cpp | 16 +-- world/cliententry.h | 18 ++- world/clientlist.cpp | 36 +++--- world/clientlist.h | 27 ++--- world/console.cpp | 28 +++-- world/console.h | 2 +- world/dynamic_zone.cpp | 17 +-- world/dynamic_zone.h | 11 +- world/dynamic_zone_manager.cpp | 20 +-- world/dynamic_zone_manager.h | 10 +- world/eqemu_api_world_data_service.cpp | 28 +++-- world/eqemu_api_world_data_service.h | 8 +- world/eql_config.cpp | 14 ++- world/eql_config.h | 12 +- world/launcher_link.cpp | 21 ++-- world/launcher_link.h | 16 ++- world/launcher_list.cpp | 6 +- world/launcher_list.h | 16 ++- world/lfplist.cpp | 12 +- world/lfplist.h | 16 +-- world/login_server.cpp | 39 +++--- world/login_server.h | 23 ++-- world/login_server_list.cpp | 35 +++--- world/login_server_list.h | 19 ++- world/main.cpp | 114 +++++++----------- world/queryserv.cpp | 14 +-- world/queryserv.h | 13 +- world/shared_task_manager.cpp | 34 +++--- world/shared_task_manager.h | 13 +- world/shared_task_world_messaging.cpp | 29 ++--- world/shared_task_world_messaging.h | 22 ++-- world/sof_char_create_data.h | 7 +- world/ucs.cpp | 13 +- world/ucs.h | 14 +-- world/web_interface.cpp | 4 +- world/web_interface.h | 9 +- world/web_interface_eqw.cpp | 13 +- world/web_interface_eqw.h | 2 +- world/wguild_mgr.cpp | 32 ++--- world/wguild_mgr.h | 11 +- world/world_boot.cpp | 59 ++++----- world/world_boot.h | 13 +- world/world_config.cpp | 6 +- world/world_config.h | 8 +- world/world_console_connection.cpp | 5 +- world/world_console_connection.h | 6 +- world/world_event_scheduler.cpp | 8 +- world/world_event_scheduler.h | 9 +- world/world_server_cli.cpp | 5 - world/world_server_cli.h | 10 +- world/world_tcp_connection.h | 8 +- world/worlddb.cpp | 29 ++--- world/worlddb.h | 14 +-- world/zonelist.cpp | 49 ++++---- world/zonelist.h | 23 ++-- world/zoneserver.cpp | 69 +++++------ world/zoneserver.h | 21 ++-- 84 files changed, 715 insertions(+), 798 deletions(-) diff --git a/world/CMakeLists.txt b/world/CMakeLists.txt index 1e44afc59e..80be6aeb8e 100644 --- a/world/CMakeLists.txt +++ b/world/CMakeLists.txt @@ -96,6 +96,7 @@ add_executable(world ${world_sources} ${world_headers}) target_compile_definitions(world PRIVATE WORLD) target_link_libraries(world common) +target_include_directories(world PRIVATE ..) if(WIN32 AND EQEMU_BUILD_PCH) target_precompile_headers(world PRIVATE ../common/pch/std-pch.h) diff --git a/world/adventure.cpp b/world/adventure.cpp index 5249f1c476..fbf6f99042 100644 --- a/world/adventure.cpp +++ b/world/adventure.cpp @@ -1,19 +1,20 @@ -#include -#include "../common/global_define.h" -#include "../common/servertalk.h" -#include "../common/extprofile.h" -#include "../common/rulesys.h" -#include "../common/misc_functions.h" -#include "../common/strings.h" -#include "../common/random.h" #include "adventure.h" -#include "adventure_manager.h" -#include "worlddb.h" -#include "zonelist.h" -#include "clientlist.h" -#include "cliententry.h" -#include "../common/zone_store.h" -#include "../common/repositories/character_corpses_repository.h" + +#include "common/extprofile.h" +#include "common/misc_functions.h" +#include "common/random.h" +#include "common/repositories/character_corpses_repository.h" +#include "common/rulesys.h" +#include "common/servertalk.h" +#include "common/strings.h" +#include "common/zone_store.h" +#include "world/adventure_manager.h" +#include "world/cliententry.h" +#include "world/clientlist.h" +#include "world/worlddb.h" +#include "world/zonelist.h" + +#include "glm/vec4.hpp" extern EQ::Random emu_random; diff --git a/world/adventure.h b/world/adventure.h index 8f7e4c418f..6fd9667371 100644 --- a/world/adventure.h +++ b/world/adventure.h @@ -1,13 +1,12 @@ -#ifndef ADVENTURE_H -#define ADVENTURE_H +#pragma once -#include "../common/global_define.h" -#include "../common/types.h" -#include "../common/timer.h" -#include "adventure_template.h" +#include "common/timer.h" +#include "common/types.h" +#include "world/adventure_template.h" + +#include #include #include -#include enum AdventureStatus { @@ -97,5 +96,3 @@ class Adventure Timer *current_timer; int instance_id; }; - -#endif diff --git a/world/adventure_manager.cpp b/world/adventure_manager.cpp index 3ba718b536..edc12c19a7 100644 --- a/world/adventure_manager.cpp +++ b/world/adventure_manager.cpp @@ -1,18 +1,19 @@ -#include "../common/global_define.h" -#include "../common/misc_functions.h" -#include "../common/strings.h" -#include "../common/servertalk.h" -#include "../common/rulesys.h" -#include "../common/random.h" -#include "adventure.h" #include "adventure_manager.h" -#include "worlddb.h" -#include "zonelist.h" -#include "clientlist.h" -#include "cliententry.h" -#include "../common/zone_store.h" + +#include "common/misc_functions.h" +#include "common/random.h" +#include "common/rulesys.h" +#include "common/servertalk.h" +#include "common/strings.h" +#include "common/zone_store.h" +#include "world/adventure.h" +#include "world/cliententry.h" +#include "world/clientlist.h" +#include "world/worlddb.h" +#include "world/zonelist.h" + +#include #include -#include AdventureManager::AdventureManager() { diff --git a/world/adventure_manager.h b/world/adventure_manager.h index 9f84ce8382..d9934f8491 100644 --- a/world/adventure_manager.h +++ b/world/adventure_manager.h @@ -1,11 +1,10 @@ -#ifndef ADVENTURE_MANAGER_H -#define ADVENTURE_MANAGER_H +#pragma once + +#include "common/timer.h" +#include "common/types.h" +#include "world/adventure_template.h" +#include "world/adventure.h" -#include "../common/global_define.h" -#include "../common/types.h" -#include "../common/timer.h" -#include "adventure.h" -#include "adventure_template.h" #include #include @@ -94,5 +93,3 @@ class AdventureManager Timer *save_timer; Timer *leaderboard_info_timer; }; - -#endif diff --git a/world/adventure_template.h b/world/adventure_template.h index 89f8b99156..b35da738fc 100644 --- a/world/adventure_template.h +++ b/world/adventure_template.h @@ -1,9 +1,8 @@ -#ifndef ADVENTURE_TEMPLATE_H -#define ADVENTURE_TEMPLATE_H +#pragma once -#include "../common/global_define.h" -#include "../common/types.h" +#include "common/types.h" +#pragma pack(push) #pragma pack(1) struct AdventureTemplate @@ -42,6 +41,4 @@ struct AdventureTemplate float graveyard_radius; }; -#pragma pack() - -#endif +#pragma pack(pop) diff --git a/world/cli/cli_bots_disable.cpp b/world/cli/cli_bots_disable.cpp index 0df7b9873f..4cbe5ed7e1 100644 --- a/world/cli/cli_bots_disable.cpp +++ b/world/cli/cli_bots_disable.cpp @@ -1,6 +1,7 @@ -#include "../world_server_cli.h" -#include "../worlddb.h" -#include "../../common/database_schema.h" +#include "world/world_server_cli.h" + +#include "common/database_schema.h" +#include "world/worlddb.h" void WorldserverCLI::BotsDisable(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_bots_enable.cpp b/world/cli/cli_bots_enable.cpp index e503f93c97..7664431130 100644 --- a/world/cli/cli_bots_enable.cpp +++ b/world/cli/cli_bots_enable.cpp @@ -1,6 +1,7 @@ -#include "../world_server_cli.h" -#include "../worlddb.h" -#include "../../common/rulesys.h" +#include "world/world_server_cli.h" + +#include "common/rulesys.h" +#include "world/worlddb.h" void WorldserverCLI::BotsEnable(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_copy_character.cpp b/world/cli/cli_copy_character.cpp index 047b81944c..41e3bb349a 100644 --- a/world/cli/cli_copy_character.cpp +++ b/world/cli/cli_copy_character.cpp @@ -1,7 +1,8 @@ -#include "../world_server_cli.h" -#include "../../common/eqemu_logsys.h" -#include "../../common/eqemu_logsys_log_aliases.h" -#include "../worlddb.h" +#include "world/world_server_cli.h" + +#include "common/eqemu_logsys_log_aliases.h" +#include "common/eqemu_logsys.h" +#include "world/worlddb.h" void WorldserverCLI::CopyCharacter(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_database_concurrency.cpp b/world/cli/cli_database_concurrency.cpp index 0479a90a11..81b6619b12 100644 --- a/world/cli/cli_database_concurrency.cpp +++ b/world/cli/cli_database_concurrency.cpp @@ -1,8 +1,10 @@ +#include "world/world_server_cli.h" + +#include "common/eqemu_config.h" +#include "common/repositories/zone_repository.h" + +#include #include -#include "../world_server_cli.h" -#include "../../common/repositories/zone_repository.h" -#include "../../common/eqemu_config.h" -#include Database db; Database db2; diff --git a/world/cli/cli_database_dump.cpp b/world/cli/cli_database_dump.cpp index 2cedd6392e..00618606c8 100644 --- a/world/cli/cli_database_dump.cpp +++ b/world/cli/cli_database_dump.cpp @@ -1,5 +1,6 @@ -#include "../world_server_cli.h" -#include "../../common/database/database_dump_service.h" +#include "world/world_server_cli.h" + +#include "common/database/database_dump_service.h" void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_database_get_schema.cpp b/world/cli/cli_database_get_schema.cpp index d4b71c1c4d..37af405677 100644 --- a/world/cli/cli_database_get_schema.cpp +++ b/world/cli/cli_database_get_schema.cpp @@ -1,6 +1,9 @@ -#include "../world_server_cli.h" -#include "../../common/database_schema.h" -#include "../../common/json/json.h" +#include "world/world_server_cli.h" + +#include "common/database_schema.h" +#include "common/json/json.h" + +#include void WorldserverCLI::DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description) { @@ -62,8 +65,5 @@ void WorldserverCLI::DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, schema["version_tables"] = version_tables_json; schema["bot_tables"] = bot_tables_json; - std::stringstream payload; - payload << schema; - - std::cout << payload.str() << std::endl; + std::cout << schema << std::endl; } diff --git a/world/cli/cli_database_set_account_status.cpp b/world/cli/cli_database_set_account_status.cpp index d0e94b23c9..49e76307c6 100644 --- a/world/cli/cli_database_set_account_status.cpp +++ b/world/cli/cli_database_set_account_status.cpp @@ -1,5 +1,5 @@ -#include "../world_server_cli.h" -#include "../worlddb.h" +#include "world/world_server_cli.h" +#include "world/worlddb.h" void WorldserverCLI::DatabaseSetAccountStatus(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_database_updates.cpp b/world/cli/cli_database_updates.cpp index 763a1f3c39..f2f773849c 100644 --- a/world/cli/cli_database_updates.cpp +++ b/world/cli/cli_database_updates.cpp @@ -1,6 +1,7 @@ -#include "../world_server_cli.h" -#include "../worlddb.h" -#include "../../common/database/database_update.h" +#include "world/world_server_cli.h" + +#include "common/database/database_update.h" +#include "world/worlddb.h" void WorldserverCLI::DatabaseUpdates(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_database_version.cpp b/world/cli/cli_database_version.cpp index ee11bb7b1c..424bc4ee66 100644 --- a/world/cli/cli_database_version.cpp +++ b/world/cli/cli_database_version.cpp @@ -1,7 +1,10 @@ -#include "../world_server_cli.h" -#include "../../common/version.h" -#include "../../common/json/json.h" -#include "../../common/rulesys.h" +#include "world/world_server_cli.h" + +#include "common/json/json.h" +#include "common/rulesys.h" +#include "common/version.h" + +#include void WorldserverCLI::DatabaseVersion(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_etl_get_settings.cpp b/world/cli/cli_etl_get_settings.cpp index c17d0b8e8d..a96c8477f4 100644 --- a/world/cli/cli_etl_get_settings.cpp +++ b/world/cli/cli_etl_get_settings.cpp @@ -1,7 +1,8 @@ -#include "../world_server_cli.h" -#include "../worlddb.h" -#include "../../common/events/player_event_logs.h" -#include "../../common/json/json.h" +#include "world/world_server_cli.h" + +#include "common/events/player_event_logs.h" +#include "common/json/json.h" +#include "world/worlddb.h" void WorldserverCLI::EtlGetSettings(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_mercs_disable.cpp b/world/cli/cli_mercs_disable.cpp index 9018d271ba..737608ccf1 100644 --- a/world/cli/cli_mercs_disable.cpp +++ b/world/cli/cli_mercs_disable.cpp @@ -1,6 +1,7 @@ -#include "../world_server_cli.h" -#include "../worlddb.h" -#include "../../common/database_schema.h" +#include "world/world_server_cli.h" + +#include "common/database_schema.h" +#include "world/worlddb.h" void WorldserverCLI::MercsDisable(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_mercs_enable.cpp b/world/cli/cli_mercs_enable.cpp index 2e69472d5b..a4f6c2972a 100644 --- a/world/cli/cli_mercs_enable.cpp +++ b/world/cli/cli_mercs_enable.cpp @@ -1,6 +1,7 @@ -#include "../world_server_cli.h" -#include "../worlddb.h" -#include "../../common/database_schema.h" +#include "world/world_server_cli.h" + +#include "common/database_schema.h" +#include "world/worlddb.h" void WorldserverCLI::MercsEnable(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_test.cpp b/world/cli/cli_test.cpp index 305f22d2fe..ecbb1e5fa2 100644 --- a/world/cli/cli_test.cpp +++ b/world/cli/cli_test.cpp @@ -1,9 +1,11 @@ -#include "../world_server_cli.h" -#include -#include +#include "world/world_server_cli.h" + +#include "common/events/player_events.h" +#include "common/memory/ksm.hpp" + +#include "cereal/archives/json.hpp" +#include "cereal/types/vector.hpp" #include -#include "../../common/events/player_events.h" -#include "../../common/memory/ksm.hpp" void WorldserverCLI::TestCommand(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_test_colors.cpp b/world/cli/cli_test_colors.cpp index 477c133338..ae6e4cbd4c 100644 --- a/world/cli/cli_test_colors.cpp +++ b/world/cli/cli_test_colors.cpp @@ -1,6 +1,7 @@ -#include "../world_server_cli.h" -#include "../../common/zone_store.h" -#include "../../common/termcolor/rang.hpp" +#include "world/world_server_cli.h" + +#include "common/termcolor/rang.hpp" +#include "common/zone_store.h" void WorldserverCLI::TestColors(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_test_expansion.cpp b/world/cli/cli_test_expansion.cpp index 24e227472d..93dc94f298 100644 --- a/world/cli/cli_test_expansion.cpp +++ b/world/cli/cli_test_expansion.cpp @@ -1,9 +1,10 @@ -#include "../world_server_cli.h" -#include "../../common/rulesys.h" -#include "../../common/repositories/content_flags_repository.h" -#include "../../common/content/world_content_service.h" -#include "../../common/repositories/criteria/content_filter_criteria.h" -#include "../worlddb.h" +#include "world/world_server_cli.h" + +#include "common/content/world_content_service.h" +#include "common/repositories/content_flags_repository.h" +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/rulesys.h" +#include "world/worlddb.h" void WorldserverCLI::ExpansionTestCommand(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_test_repository.cpp b/world/cli/cli_test_repository.cpp index bd2ee5449e..038ce58711 100644 --- a/world/cli/cli_test_repository.cpp +++ b/world/cli/cli_test_repository.cpp @@ -1,6 +1,7 @@ -#include "../world_server_cli.h" -#include "../../common/repositories/instance_list_repository.h" -#include "../worlddb.h" +#include "world/world_server_cli.h" + +#include "common/repositories/instance_list_repository.h" +#include "world/worlddb.h" void WorldserverCLI::TestRepository(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_test_repository_2.cpp b/world/cli/cli_test_repository_2.cpp index 6091b0220c..4c914090f9 100644 --- a/world/cli/cli_test_repository_2.cpp +++ b/world/cli/cli_test_repository_2.cpp @@ -1,6 +1,7 @@ -#include "../world_server_cli.h" -#include "../worlddb.h" -#include "../../common/repositories/zone_repository.h" +#include "world/world_server_cli.h" + +#include "common/repositories/zone_repository.h" +#include "world/worlddb.h" void WorldserverCLI::TestRepository2(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_test_string_benchmark.cpp b/world/cli/cli_test_string_benchmark.cpp index e064a266a5..dd3edbb8f6 100644 --- a/world/cli/cli_test_string_benchmark.cpp +++ b/world/cli/cli_test_string_benchmark.cpp @@ -1,8 +1,10 @@ -#include "../world_server_cli.h" -#include -#include -#include "../../common/events/player_events.h" -#include "../../common/timer.h" +#include "world/world_server_cli.h" + +#include "common/events/player_events.h" +#include "common/timer.h" + +#include "cereal/archives/json.hpp" +#include "cereal/types/vector.hpp" void WorldserverCLI::TestStringBenchmarkCommand(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/cli/cli_version.cpp b/world/cli/cli_version.cpp index c82ea9967b..1f1502bb53 100644 --- a/world/cli/cli_version.cpp +++ b/world/cli/cli_version.cpp @@ -1,6 +1,9 @@ -#include "../world_server_cli.h" -#include "../../common/json/json.h" -#include "../../common/version.h" +#include "world/world_server_cli.h" + +#include "common/json/json.h" +#include "common/version.h" + +#include void WorldserverCLI::Version(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/world/client.cpp b/world/client.cpp index 91aaf3e9f0..555a0055a8 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -16,59 +16,54 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eq_packet.h" -#include "../common/eq_stream_intf.h" -#include "../common/misc.h" -#include "../common/rulesys.h" -#include "../common/emu_opcodes.h" -#include "../common/eq_packet_structs.h" -#include "../common/packet_dump.h" -#include "../common/eq_stream_intf.h" -#include "../common/inventory_profile.h" -#include "../common/races.h" -#include "../common/classes.h" -#include "../common/skills.h" -#include "../common/extprofile.h" -#include "../common/strings.h" -#include "../common/emu_versions.h" -#include "../common/random.h" -#include "../common/shareddb.h" -#include "../common/opcodemgr.h" -#include "../common/data_verification.h" -#include "../common/data_bucket.h" - #include "client.h" -#include "worlddb.h" -#include "world_config.h" -#include "login_server.h" -#include "login_server_list.h" -#include "zoneserver.h" -#include "zonelist.h" -#include "clientlist.h" -#include "wguild_mgr.h" -#include "sof_char_create_data.h" -#include "../common/zone_store.h" -#include "../common/repositories/account_repository.h" -#include "../common/repositories/player_event_logs_repository.h" -#include "../common/repositories/inventory_repository.h" -#include "../common/events/player_event_logs.h" -#include "../common/content/world_content_service.h" -#include "../common/repositories/group_id_repository.h" -#include "../common/repositories/character_data_repository.h" -#include "../common/skill_caps.h" -#include +#include "common/classes.h" +#include "common/content/world_content_service.h" +#include "common/data_bucket.h" +#include "common/data_verification.h" +#include "common/emu_opcodes.h" +#include "common/emu_versions.h" +#include "common/eq_packet_structs.h" +#include "common/eq_packet.h" +#include "common/eq_stream_intf.h" +#include "common/eq_stream_intf.h" +#include "common/events/player_event_logs.h" +#include "common/extprofile.h" +#include "common/inventory_profile.h" +#include "common/misc.h" +#include "common/opcodemgr.h" +#include "common/packet_dump.h" +#include "common/races.h" +#include "common/random.h" +#include "common/repositories/account_repository.h" +#include "common/repositories/character_data_repository.h" +#include "common/repositories/group_id_repository.h" +#include "common/repositories/inventory_repository.h" +#include "common/repositories/player_event_logs_repository.h" +#include "common/rulesys.h" +#include "common/shareddb.h" +#include "common/skill_caps.h" +#include "common/skills.h" +#include "common/strings.h" +#include "common/zone_store.h" +#include "world/clientlist.h" +#include "world/login_server_list.h" +#include "world/login_server.h" +#include "world/sof_char_create_data.h" +#include "world/wguild_mgr.h" +#include "world/world_config.h" +#include "world/worlddb.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" + +#include "zlib.h" +#include +#include +#include +#include #include - -#include -#include -#include -#include -#include - -//FatherNitwit: uncomment to enable my IP based authentication hack -//#define IPBASED_AUTH_HACK +#include // Disgrace: for windows compile #ifdef _WINDOWS diff --git a/world/client.h b/world/client.h index 5890cfcf00..f26dcaaacc 100644 --- a/world/client.h +++ b/world/client.h @@ -15,18 +15,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef CLIENT_H -#define CLIENT_H -#include +#pragma once -#include "../common/linked_list.h" -#include "../common/timer.h" -#include "../common/inventory_profile.h" -//#include "zoneserver.h" +#include "common/eq_packet_structs.h" +#include "common/inventory_profile.h" +#include "common/linked_list.h" +#include "common/timer.h" +#include "world/cliententry.h" -#include "../common/eq_packet_structs.h" -#include "cliententry.h" +#include class EQApplicationPacket; class EQStreamInterface; @@ -128,5 +126,3 @@ class Client { bool CheckCharCreateInfoSoF(CharCreate_Struct *cc); bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc); - -#endif diff --git a/world/cliententry.cpp b/world/cliententry.cpp index d6feb68dde..6b37f7b640 100644 --- a/world/cliententry.cpp +++ b/world/cliententry.cpp @@ -1,12 +1,12 @@ -#include "../common/global_define.h" #include "cliententry.h" -#include "clientlist.h" -#include "login_server.h" -#include "login_server_list.h" -#include "shared_task_manager.h" -#include "worlddb.h" -#include "zoneserver.h" -#include "world_config.h" + +#include "world/clientlist.h" +#include "world/login_server_list.h" +#include "world/login_server.h" +#include "world/shared_task_manager.h" +#include "world/world_config.h" +#include "world/worlddb.h" +#include "world/zoneserver.h" extern uint32 numplayers; extern volatile bool RunLoops; diff --git a/world/cliententry.h b/world/cliententry.h index bf9a2662cf..97c5e40024 100644 --- a/world/cliententry.h +++ b/world/cliententry.h @@ -1,11 +1,10 @@ -#ifndef CLIENTENTRY_H_ -#define CLIENTENTRY_H_ - -#include "../common/types.h" -#include "../common/md5.h" -//#include "../common/eq_packet_structs.h" -#include "../common/servertalk.h" -#include "../common/rulesys.h" +#pragma once + +#include "common/md5.h" +#include "common/rulesys.h" +#include "common/servertalk.h" +#include "common/types.h" + #include typedef enum { @@ -160,6 +159,3 @@ class ClientListEntry { std::unique_ptr m_dz_invite; }; - -#endif /*CLIENTENTRY_H_*/ - diff --git a/world/clientlist.cpp b/world/clientlist.cpp index d8f1d9fbc5..1aa59930e3 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -16,24 +16,24 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "clientlist.h" -#include "zoneserver.h" -#include "zonelist.h" -#include "client.h" -#include "worlddb.h" -#include "../common/strings.h" -#include "../common/guilds.h" -#include "../common/races.h" -#include "../common/classes.h" -#include "../common/packet_dump.h" -#include "../common/misc.h" -#include "../common/misc_functions.h" -#include "../common/json/json.h" -#include "../common/event_sub.h" -#include "web_interface.h" -#include "wguild_mgr.h" -#include "../common/zone_store.h" +#include "common/classes.h" +#include "common/event_sub.h" +#include "common/guilds.h" +#include "common/json/json.h" +#include "common/misc_functions.h" +#include "common/misc.h" +#include "common/packet_dump.h" +#include "common/races.h" +#include "common/strings.h" +#include "common/zone_store.h" +#include "world/client.h" +#include "world/clientlist.h" +#include "world/web_interface.h" +#include "world/wguild_mgr.h" +#include "world/worlddb.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" + #include uint32 numplayers = 0; //this really wants to be a member variable of ClientList... diff --git a/world/clientlist.h b/world/clientlist.h index b158ad28db..34970a7e6e 100644 --- a/world/clientlist.h +++ b/world/clientlist.h @@ -1,16 +1,16 @@ -#ifndef CLIENTLIST_H_ -#define CLIENTLIST_H_ - -#include "../common/eq_packet_structs.h" -#include "../common/linked_list.h" -#include "../common/json/json.h" -#include "../common/timer.h" -#include "../common/rulesys.h" -#include "../common/servertalk.h" -#include "../common/event/timer.h" -#include "../common/net/console_server_connection.h" -#include +#pragma once + +#include "common/eq_packet_structs.h" +#include "common/event/timer.h" +#include "common/json/json.h" +#include "common/linked_list.h" +#include "common/net/console_server_connection.h" +#include "common/rulesys.h" +#include "common/servertalk.h" +#include "common/timer.h" + #include +#include class Client; class ZoneServer; @@ -111,6 +111,3 @@ class ClientList { std::unordered_set m_gm_zone_server_ids; std::unordered_map> m_guild_zone_server_ids; }; - -#endif /*CLIENTLIST_H_*/ - diff --git a/world/console.cpp b/world/console.cpp index 41906239b2..cbf998c3c2 100644 --- a/world/console.cpp +++ b/world/console.cpp @@ -19,19 +19,21 @@ */ #include "console.h" -#include "clientlist.h" -#include "login_server.h" -#include "login_server_list.h" -#include "world_config.h" -#include "world_console_connection.h" -#include "worlddb.h" -#include "zonelist.h" -#include "zoneserver.h" -#include "../common/strings.h" -#include "../common/md5.h" -#include "eqemu_api_world_data_service.h" -#include "../common/zone_store.h" -#include + +#include "common/md5.h" +#include "common/strings.h" +#include "common/zone_store.h" +#include "world/clientlist.h" +#include "world/eqemu_api_world_data_service.h" +#include "world/login_server_list.h" +#include "world/login_server.h" +#include "world/world_config.h" +#include "world/world_console_connection.h" +#include "world/worlddb.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" + +#include "fmt/format.h" /** * @param username diff --git a/world/console.h b/world/console.h index 1743495956..b8d4d3d866 100644 --- a/world/console.h +++ b/world/console.h @@ -1,5 +1,5 @@ #pragma once -#include "../common/net/console_server.h" +#include "common/net/console_server.h" void RegisterConsoleFunctions(std::unique_ptr &console); diff --git a/world/dynamic_zone.cpp b/world/dynamic_zone.cpp index fd9406f5c6..832e2f6ca0 100644 --- a/world/dynamic_zone.cpp +++ b/world/dynamic_zone.cpp @@ -1,12 +1,13 @@ #include "dynamic_zone.h" -#include "cliententry.h" -#include "clientlist.h" -#include "dynamic_zone_manager.h" -#include "worlddb.h" -#include "zonelist.h" -#include "zoneserver.h" -#include "../common/eqemu_logsys.h" -#include "../common/repositories/instance_list_repository.h" + +#include "common/eqemu_logsys.h" +#include "common/repositories/instance_list_repository.h" +#include "world/cliententry.h" +#include "world/clientlist.h" +#include "world/dynamic_zone_manager.h" +#include "world/worlddb.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" Database& DynamicZone::GetDatabase() { diff --git a/world/dynamic_zone.h b/world/dynamic_zone.h index 48c7027893..770f06ab98 100644 --- a/world/dynamic_zone.h +++ b/world/dynamic_zone.h @@ -1,9 +1,8 @@ -#ifndef WORLD_DYNAMIC_ZONE_H -#define WORLD_DYNAMIC_ZONE_H +#pragma once -#include "../common/dynamic_zone_base.h" -#include "../common/rulesys.h" -#include "../common/timer.h" +#include "common/dynamic_zone_base.h" +#include "common/rulesys.h" +#include "common/timer.h" class Database; class ServerPacket; @@ -52,5 +51,3 @@ class DynamicZone : public DynamicZoneBase Timer m_choose_leader_cooldown_timer{ static_cast(RuleI(Expedition, ChooseLeaderCooldownTime)) }; Timer m_warning_cooldown_timer{ 1 }; // non-zero so it's enabled initially }; - -#endif diff --git a/world/dynamic_zone_manager.cpp b/world/dynamic_zone_manager.cpp index 8cf87affec..66cd5e7346 100644 --- a/world/dynamic_zone_manager.cpp +++ b/world/dynamic_zone_manager.cpp @@ -1,13 +1,15 @@ #include "dynamic_zone_manager.h" -#include "dynamic_zone.h" -#include "cliententry.h" -#include "clientlist.h" -#include "worlddb.h" -#include "zonelist.h" -#include "zoneserver.h" -#include "../common/rulesys.h" -#include "../common/repositories/dynamic_zone_lockouts_repository.h" -#include + +#include "common/repositories/dynamic_zone_lockouts_repository.h" +#include "common/rulesys.h" +#include "world/cliententry.h" +#include "world/clientlist.h" +#include "world/dynamic_zone.h" +#include "world/worlddb.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" + +#include "cereal/types/utility.hpp" DynamicZoneManager dynamic_zone_manager; diff --git a/world/dynamic_zone_manager.h b/world/dynamic_zone_manager.h index 0e70776392..42faa42a62 100644 --- a/world/dynamic_zone_manager.h +++ b/world/dynamic_zone_manager.h @@ -1,8 +1,8 @@ -#ifndef WORLD_DYNAMIC_ZONE_MANAGER_H -#define WORLD_DYNAMIC_ZONE_MANAGER_H +#pragma once + +#include "common/repositories/dynamic_zone_templates_repository.h" +#include "common/timer.h" -#include "../common/timer.h" -#include "../common/repositories/dynamic_zone_templates_repository.h" #include #include #include @@ -35,5 +35,3 @@ class DynamicZoneManager Timer m_process_throttle_timer{}; std::unordered_map m_dz_templates; }; - -#endif diff --git a/world/eqemu_api_world_data_service.cpp b/world/eqemu_api_world_data_service.cpp index eff7b7d943..8a4132e3e0 100644 --- a/world/eqemu_api_world_data_service.cpp +++ b/world/eqemu_api_world_data_service.cpp @@ -1,17 +1,19 @@ -#include -#include "clientlist.h" -#include "cliententry.h" #include "eqemu_api_world_data_service.h" -#include "zoneserver.h" -#include "zonelist.h" -#include "../common/database_schema.h" -#include "../common/server_reload_types.h" -#include "../common/zone_store.h" -#include "worlddb.h" -#include "wguild_mgr.h" -#include "world_config.h" -#include "ucs.h" -#include "queryserv.h" + +#include "common/database_schema.h" +#include "common/server_reload_types.h" +#include "common/zone_store.h" +#include "world/cliententry.h" +#include "world/clientlist.h" +#include "world/queryserv.h" +#include "world/ucs.h" +#include "world/wguild_mgr.h" +#include "world/world_config.h" +#include "world/worlddb.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" + +#include "fmt/format.h" extern WorldGuildManager guild_mgr; diff --git a/world/eqemu_api_world_data_service.h b/world/eqemu_api_world_data_service.h index f0952969e9..8065582870 100644 --- a/world/eqemu_api_world_data_service.h +++ b/world/eqemu_api_world_data_service.h @@ -18,10 +18,9 @@ * */ -#ifndef EQEMU_API_WORLD_DATA_SERVICE_H -#define EQEMU_API_WORLD_DATA_SERVICE_H +#pragma once -#include "../common/json/json.h" +#include "common/json/json.h" class EQEmuApiWorldDataService { public: @@ -30,6 +29,3 @@ class EQEmuApiWorldDataService { static void message(Json::Value &r, const std::string &message); static void callGetGuildDetails(Json::Value &response, const std::vector &args); }; - - -#endif //EQEMU_API_WORLD_DATA_SERVICE_H diff --git a/world/eql_config.cpp b/world/eql_config.cpp index 037372a948..74e4de6899 100644 --- a/world/eql_config.cpp +++ b/world/eql_config.cpp @@ -15,13 +15,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" + #include "eql_config.h" -#include "worlddb.h" -#include "launcher_link.h" -#include "launcher_list.h" -#include "../common/strings.h" -#include "../common/zone_store.h" + +#include "common/strings.h" +#include "common/zone_store.h" +#include "world/launcher_link.h" +#include "world/launcher_list.h" +#include "world/worlddb.h" + #include #include diff --git a/world/eql_config.h b/world/eql_config.h index 9988161656..1380e0bf97 100644 --- a/world/eql_config.h +++ b/world/eql_config.h @@ -15,11 +15,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef EQLCONFIG_H_ -#define EQLCONFIG_H_ -#include "../common/types.h" -#include "worlddb.h" +#pragma once + +#include "common/types.h" +#include "world/worlddb.h" + #include #include @@ -53,6 +54,3 @@ class EQLConfig { std::map m_zones; //static zones. }; - -#endif /*EQLCONFIG_H_*/ - diff --git a/world/launcher_link.cpp b/world/launcher_link.cpp index 3b1a3fc053..92c7c030b0 100644 --- a/world/launcher_link.cpp +++ b/world/launcher_link.cpp @@ -16,21 +16,20 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" #include "launcher_link.h" -#include "launcher_list.h" -#include "world_config.h" -#include "../common/md5.h" -#include "../common/packet_dump.h" -#include "../common/servertalk.h" -#include "../common/strings.h" -#include "../common/misc_functions.h" -#include "worlddb.h" -#include "eql_config.h" +#include "common/md5.h" +#include "common/misc_functions.h" +#include "common/packet_dump.h" +#include "common/servertalk.h" +#include "common/strings.h" +#include "world/eql_config.h" +#include "world/launcher_list.h" +#include "world/world_config.h" +#include "world/worlddb.h" -#include #include +#include extern LauncherList launcher_list; diff --git a/world/launcher_link.h b/world/launcher_link.h index 60d8540e9a..c22311d9ae 100644 --- a/world/launcher_link.h +++ b/world/launcher_link.h @@ -15,16 +15,17 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef LAUNCHERLINK_H_ -#define LAUNCHERLINK_H_ -#include "../common/timer.h" -#include "../common/net/servertalk_server_connection.h" -#include "../common/event/timer.h" +#pragma once + +#include "common/event/timer.h" +#include "common/net/servertalk_server_connection.h" +#include "common/timer.h" + +#include #include #include #include -#include class ServerPacket; @@ -76,6 +77,3 @@ class LauncherLink { } ZoneState; std::map m_states; }; - -#endif /*LAUNCHERLINK_H_*/ - diff --git a/world/launcher_list.cpp b/world/launcher_list.cpp index f9923f3452..e5c3555d9d 100644 --- a/world/launcher_list.cpp +++ b/world/launcher_list.cpp @@ -16,12 +16,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "../common/global_define.h" #include "launcher_list.h" -#include "launcher_link.h" -#include "eql_config.h" +#include "world/eql_config.h" +#include "world/launcher_link.h" LauncherList::LauncherList() : nextID(1) diff --git a/world/launcher_list.h b/world/launcher_list.h index f20dba0f4c..15e655e8c9 100644 --- a/world/launcher_list.h +++ b/world/launcher_list.h @@ -15,15 +15,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef LAUNCHERLIST_H_ -#define LAUNCHERLIST_H_ -#include "../common/types.h" -#include "../common/net/servertalk_server_connection.h" +#pragma once + +#include "common/types.h" +#include "common/net/servertalk_server_connection.h" + #include -#include -#include #include +#include +#include class LauncherLink; class EQLConfig; @@ -50,6 +51,3 @@ class LauncherList { std::vector m_pendingLaunchers; //we own these objects, have not yet identified themself int nextID; }; - -#endif /*LAUNCHERLIST_H_*/ - diff --git a/world/lfplist.cpp b/world/lfplist.cpp index fcdc9daf34..283ffe8a65 100644 --- a/world/lfplist.cpp +++ b/world/lfplist.cpp @@ -17,13 +17,13 @@ */ #include "lfplist.h" -#include "cliententry.h" -#include "clientlist.h" -#include "zoneserver.h" -#include "zonelist.h" -#include "../common/misc_functions.h" -#include "../common/classes.h" +#include "common/classes.h" +#include "common/misc_functions.h" +#include "world/cliententry.h" +#include "world/clientlist.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" GroupLFP::GroupLFP(uint32 inLeaderID) { diff --git a/world/lfplist.h b/world/lfplist.h index dbb4f89625..7524b3ca7f 100644 --- a/world/lfplist.h +++ b/world/lfplist.h @@ -16,13 +16,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef LFPENTRY_H -#define LFPENTRY_H +#pragma once -#include "../common/eq_packet_structs.h" -#include "../common/servertalk.h" -#include "../common/linked_list.h" -#include "../common/timer.h" +#include "common/eq_packet_structs.h" +#include "common/linked_list.h" +#include "common/servertalk.h" +#include "common/timer.h" class GroupLFP { @@ -59,9 +58,4 @@ class GroupLFPList { private: LinkedList LFPGroupList; Timer LFPStaleTimer; - - }; - -#endif - diff --git a/world/login_server.cpp b/world/login_server.cpp index 9bdc0c470f..f911004f80 100644 --- a/world/login_server.cpp +++ b/world/login_server.cpp @@ -1,24 +1,23 @@ -#include "../common/global_define.h" -#include -#include -#include -#include -#include -#include "../common/version.h" -#include "../common/servertalk.h" -#include "../common/misc_functions.h" -#include "../common/eq_packet_structs.h" -#include "../common/packet_dump.h" -#include "../common/strings.h" -#include "../common/eqemu_logsys.h" #include "login_server.h" -#include "login_server_list.h" -#include "zoneserver.h" -#include "worlddb.h" -#include "zonelist.h" -#include "clientlist.h" -#include "cliententry.h" -#include "world_config.h" + +#include "common/eq_packet_structs.h" +#include "common/eqemu_logsys.h" +#include "common/misc_functions.h" +#include "common/packet_dump.h" +#include "common/servertalk.h" +#include "common/strings.h" +#include "common/version.h" +#include "world/cliententry.h" +#include "world/clientlist.h" +#include "world/login_server_list.h" +#include "world/world_config.h" +#include "world/worlddb.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" + +#include +#include +#include extern uint32 numzones; extern uint32 numplayers; diff --git a/world/login_server.h b/world/login_server.h index 0a5e6a107a..e773664112 100644 --- a/world/login_server.h +++ b/world/login_server.h @@ -1,15 +1,15 @@ -#ifndef LOGINSERVER_H -#define LOGINSERVER_H +#pragma once + +#include "common/eq_packet_structs.h" +#include "common/event/timer.h" +#include "common/linked_list.h" +#include "common/mutex.h" +#include "common/net/servertalk_client_connection.h" +#include "common/net/servertalk_legacy_client_connection.h" +#include "common/queue.h" +#include "common/servertalk.h" +#include "common/timer.h" -#include "../common/servertalk.h" -#include "../common/linked_list.h" -#include "../common/timer.h" -#include "../common/queue.h" -#include "../common/eq_packet_structs.h" -#include "../common/mutex.h" -#include "../common/net/servertalk_client_connection.h" -#include "../common/net/servertalk_legacy_client_connection.h" -#include "../common/event/timer.h" #include class LoginServer{ @@ -63,4 +63,3 @@ class LoginServer{ bool m_can_account_update; bool m_is_legacy; }; -#endif diff --git a/world/login_server_list.cpp b/world/login_server_list.cpp index 5a2c8f3758..06f01e25fa 100644 --- a/world/login_server_list.cpp +++ b/world/login_server_list.cpp @@ -15,26 +15,25 @@ 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 "../common/global_define.h" -#include -#include -#include -#include -#include -#include "../common/version.h" -#define IGNORE_LS_FATAL_ERROR - -#include "../common/servertalk.h" -#include "login_server.h" #include "login_server_list.h" -#include "../common/eq_packet_structs.h" -#include "../common/packet_dump.h" -#include "zoneserver.h" -#include "worlddb.h" -#include "zonelist.h" -#include "clientlist.h" -#include "world_config.h" + +#include "common/eq_packet_structs.h" +#include "common/packet_dump.h" +#include "common/servertalk.h" +#include "common/version.h" +#include "world/clientlist.h" +#include "world/login_server.h" +#include "world/world_config.h" +#include "world/worlddb.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" + +#include +#include +#include + +#define IGNORE_LS_FATAL_ERROR extern uint32 numzones; extern uint32 numplayers; diff --git a/world/login_server_list.h b/world/login_server_list.h index 54de20befe..fe37f52747 100644 --- a/world/login_server_list.h +++ b/world/login_server_list.h @@ -1,11 +1,11 @@ -#ifndef LOGINSERVERLIST_H_ -#define LOGINSERVERLIST_H_ +#pragma once + +#include "common/eq_packet_structs.h" +#include "common/mutex.h" +#include "common/queue.h" +#include "common/servertalk.h" +#include "common/timer.h" -#include "../common/servertalk.h" -#include "../common/timer.h" -#include "../common/queue.h" -#include "../common/eq_packet_structs.h" -#include "../common/mutex.h" #include class LoginServer; @@ -31,8 +31,3 @@ class LoginServerList{ protected: std::list> m_list; }; - - - - -#endif /*LOGINSERVERLIST_H_*/ diff --git a/world/main.cpp b/world/main.cpp index c9386128e1..9aa7f50fe1 100644 --- a/world/main.cpp +++ b/world/main.cpp @@ -18,79 +18,55 @@ * */ -#include "../common/global_define.h" - -#include -#include -#include -#include -#include - -#include "../common/strings.h" -#include "../common/eqemu_logsys.h" -#include "../common/queue.h" -#include "../common/timer.h" -#include "../common/eq_packet.h" -#include "../common/seperator.h" -#include "../common/version.h" -#include "../common/eqtime.h" -#include "../common/event/event_loop.h" -#include "../common/net/eqstream.h" -#include "../common/opcodemgr.h" -#include "../common/guilds.h" -#include "../common/eq_stream_ident.h" -#include "../common/rulesys.h" -#include "../common/platform.h" -#include "../common/crash.h" -#include "../common/misc.h" -#include "client.h" -#include "worlddb.h" -#include "wguild_mgr.h" -#include "../common/evolving_items.h" - +#include "common/content/world_content_service.h" +#include "common/crash.h" +#include "common/eq_packet.h" +#include "common/eq_stream_ident.h" +#include "common/eqemu_logsys.h" +#include "common/eqtime.h" +#include "common/event/event_loop.h" +#include "common/events/player_event_logs.h" +#include "common/guilds.h" +#include "common/ip_util.h" +#include "common/misc.h" +#include "common/net/eqstream.h" +#include "common/patches/patches.h" +#include "common/path_manager.h" +#include "common/platform.h" +#include "common/repositories/character_expedition_lockouts_repository.h" +#include "common/repositories/character_task_timers_repository.h" +#include "common/rulesys.h" +#include "common/skill_caps.h" +#include "common/timer.h" +#include "common/version.h" +#include "world/adventure_manager.h" +#include "world/client.h" +#include "world/clientlist.h" +#include "world/console.h" +#include "world/dynamic_zone_manager.h" +#include "world/launcher_list.h" +#include "world/lfplist.h" +#include "world/login_server.h" +#include "world/queryserv.h" +#include "world/shared_task_manager.h" +#include "world/ucs.h" +#include "world/web_interface.h" +#include "world/wguild_mgr.h" +#include "world/world_boot.h" +#include "world/world_config.h" +#include "world/world_event_scheduler.h" +#include "world/world_server_cli.h" +#include "world/worlddb.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" + +#include "fmt/format.h" +#include +#include #ifdef _WINDOWS -#include -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp #include -#else - -#include -#include - #endif -#include "../common/patches/patches.h" -#include "zoneserver.h" -#include "login_server.h" -#include "login_server_list.h" -#include "world_config.h" -#include "zonelist.h" -#include "clientlist.h" -#include "launcher_list.h" -#include "lfplist.h" -#include "adventure_manager.h" -#include "ucs.h" -#include "queryserv.h" -#include "web_interface.h" -#include "console.h" -#include "dynamic_zone_manager.h" - -#include "world_server_cli.h" -#include "../common/content/world_content_service.h" -#include "../common/repositories/character_expedition_lockouts_repository.h" -#include "../common/repositories/character_task_timers_repository.h" -#include "../common/zone_store.h" -#include "world_event_scheduler.h" -#include "shared_task_manager.h" -#include "world_boot.h" -#include "../common/path_manager.h" -#include "../common/events/player_event_logs.h" -#include "../common/skill_caps.h" -#include "../common/repositories/character_parcels_repository.h" -#include "../common/ip_util.h" - GroupLFPList LFPGroupList; LauncherList launcher_list; volatile bool RunLoops = true; diff --git a/world/queryserv.cpp b/world/queryserv.cpp index 69185607c4..19bce076ca 100644 --- a/world/queryserv.cpp +++ b/world/queryserv.cpp @@ -1,13 +1,11 @@ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" #include "queryserv.h" -#include "world_config.h" -#include "clientlist.h" -#include "zonelist.h" - -#include "../common/md5.h" -#include "../common/packet_dump.h" +#include "common/eqemu_logsys.h" +#include "common/md5.h" +#include "common/packet_dump.h" +#include "world/clientlist.h" +#include "world/world_config.h" +#include "world/zonelist.h" QueryServConnection::QueryServConnection() { diff --git a/world/queryserv.h b/world/queryserv.h index 5366fbeb50..177da7b75f 100644 --- a/world/queryserv.h +++ b/world/queryserv.h @@ -1,10 +1,9 @@ -#ifndef QueryServ_H -#define QueryServ_H +#pragma once -#include "../common/types.h" -#include "../common/net/servertalk_server.h" -#include "../common/servertalk.h" -#include "../common/event/timer.h" +#include "common/types.h" +#include "common/net/servertalk_server.h" +#include "common/servertalk.h" +#include "common/event/timer.h" class QueryServConnection { @@ -26,5 +25,3 @@ class QueryServConnection std::map> m_streams; std::unique_ptr m_keepalive; }; - -#endif /*QueryServ_H_*/ diff --git a/world/shared_task_manager.cpp b/world/shared_task_manager.cpp index 914f409584..6eae5ef401 100644 --- a/world/shared_task_manager.cpp +++ b/world/shared_task_manager.cpp @@ -1,21 +1,21 @@ #include "shared_task_manager.h" -#include "cliententry.h" -#include "clientlist.h" -#include "dynamic_zone.h" -#include "dynamic_zone_manager.h" -#include "zonelist.h" -#include "zoneserver.h" -#include "shared_task_world_messaging.h" -#include "../common/rulesys.h" -#include "../common/repositories/character_data_repository.h" -#include "../common/repositories/character_task_timers_repository.h" -#include "../common/repositories/shared_task_members_repository.h" -#include "../common/repositories/shared_task_activity_state_repository.h" -#include "../common/repositories/completed_shared_tasks_repository.h" -#include "../common/repositories/completed_shared_task_members_repository.h" -#include "../common/repositories/completed_shared_task_activity_state_repository.h" -#include "../common/repositories/shared_task_dynamic_zones_repository.h" -#include + +#include "common/repositories/character_data_repository.h" +#include "common/repositories/character_task_timers_repository.h" +#include "common/repositories/completed_shared_task_activity_state_repository.h" +#include "common/repositories/completed_shared_task_members_repository.h" +#include "common/repositories/completed_shared_tasks_repository.h" +#include "common/repositories/shared_task_activity_state_repository.h" +#include "common/repositories/shared_task_dynamic_zones_repository.h" +#include "common/repositories/shared_task_members_repository.h" +#include "common/rulesys.h" +#include "world/cliententry.h" +#include "world/clientlist.h" +#include "world/dynamic_zone_manager.h" +#include "world/dynamic_zone.h" +#include "world/shared_task_world_messaging.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" SharedTaskManager::SharedTaskManager() : m_process_timer{ static_cast(RuleI(TaskSystem, SharedTasksWorldProcessRate)) } diff --git a/world/shared_task_manager.h b/world/shared_task_manager.h index 197a8bce25..bb8afe50c4 100644 --- a/world/shared_task_manager.h +++ b/world/shared_task_manager.h @@ -1,10 +1,9 @@ -#ifndef EQEMU_SHARED_TASK_MANAGER_H -#define EQEMU_SHARED_TASK_MANAGER_H +#pragma once -#include "../common/database.h" -#include "../common/shared_tasks.h" -#include "../common/timer.h" -#include "../common/repositories/character_task_timers_repository.h" +#include "common/database.h" +#include "common/repositories/character_task_timers_repository.h" +#include "common/shared_tasks.h" +#include "common/timer.h" class DynamicZone; @@ -147,5 +146,3 @@ class SharedTaskManager { // memory search std::vector FindCharactersInSharedTasks(const std::vector &find_characters); }; - -#endif //EQEMU_SHARED_TASK_MANAGER_H diff --git a/world/shared_task_world_messaging.cpp b/world/shared_task_world_messaging.cpp index 39f4af8046..526b144bc4 100644 --- a/world/shared_task_world_messaging.cpp +++ b/world/shared_task_world_messaging.cpp @@ -1,18 +1,19 @@ #include "shared_task_world_messaging.h" -#include "cliententry.h" -#include "worlddb.h" -#include "../common/shared_tasks.h" -#include "../common/eqemu_logsys.h" -#include "../common/repositories/tasks_repository.h" -#include "../common/tasks.h" -#include "cliententry.h" -#include "clientlist.h" -#include "zonelist.h" -#include "zoneserver.h" -#include "shared_task_manager.h" -#include "../common/repositories/shared_task_members_repository.h" -#include "../common/repositories/task_activities_repository.h" -#include "dynamic_zone.h" + +#include "common/eqemu_logsys.h" +#include "common/repositories/shared_task_members_repository.h" +#include "common/repositories/task_activities_repository.h" +#include "common/repositories/tasks_repository.h" +#include "common/shared_tasks.h" +#include "common/tasks.h" +#include "world/cliententry.h" +#include "world/cliententry.h" +#include "world/clientlist.h" +#include "world/dynamic_zone.h" +#include "world/shared_task_manager.h" +#include "world/worlddb.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" void SharedTaskWorldMessaging::HandleZoneMessage(ServerPacket *pack) { diff --git a/world/shared_task_world_messaging.h b/world/shared_task_world_messaging.h index e8062e2ecd..c841baf803 100644 --- a/world/shared_task_world_messaging.h +++ b/world/shared_task_world_messaging.h @@ -1,18 +1,14 @@ -#ifndef EQEMU_SHARED_TASK_WORLD_MESSAGING_H -#define EQEMU_SHARED_TASK_WORLD_MESSAGING_H +#pragma once -#include "../common/types.h" -#include "../common/servertalk.h" -#include "../common/shared_tasks.h" -#include "../common/eqemu_logsys.h" -#include "../common/repositories/tasks_repository.h" -#include "../common/tasks.h" +#include "common/eqemu_logsys.h" +#include "common/repositories/tasks_repository.h" +#include "common/servertalk.h" +#include "common/shared_tasks.h" +#include "common/tasks.h" +#include "common/types.h" -class SharedTaskWorldMessaging { +class SharedTaskWorldMessaging +{ public: static void HandleZoneMessage(ServerPacket *pack); }; - - -#endif //EQEMU_SHARED_TASK_WORLD_MESSAGING_H - diff --git a/world/sof_char_create_data.h b/world/sof_char_create_data.h index 97d9e8014d..c522507d62 100644 --- a/world/sof_char_create_data.h +++ b/world/sof_char_create_data.h @@ -1,6 +1,6 @@ -#ifndef SOFCHARCREATEDATA_H -#define SOFCHARCREATEDATA_H +#pragma once +#pragma pack(push) #pragma pack(1) struct RaceClassAllocation { @@ -26,6 +26,5 @@ struct RaceClassCombos { SoFCCStartZoneData StartZoneData[641]; }; */ -#pragma pack() -#endif +#pragma pack(pop) diff --git a/world/ucs.cpp b/world/ucs.cpp index 0cc70a0ea3..298c359fc5 100644 --- a/world/ucs.cpp +++ b/world/ucs.cpp @@ -1,12 +1,11 @@ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" #include "ucs.h" -#include "world_config.h" -#include "../common/misc_functions.h" -#include "../common/md5.h" -#include "../common/packet_dump.h" -#include "../common/event/timer.h" +#include "common/eqemu_logsys.h" +#include "common/event/timer.h" +#include "common/md5.h" +#include "common/misc_functions.h" +#include "common/packet_dump.h" +#include "world/world_config.h" UCSConnection::UCSConnection() { diff --git a/world/ucs.h b/world/ucs.h index a324d91fc9..520dff9297 100644 --- a/world/ucs.h +++ b/world/ucs.h @@ -1,10 +1,10 @@ -#ifndef UCS_H -#define UCS_H +#pragma once + +#include "common/event/timer.h" +#include "common/net/servertalk_server_connection.h" +#include "common/servertalk.h" +#include "common/types.h" -#include "../common/types.h" -#include "../common/net/servertalk_server_connection.h" -#include "../common/servertalk.h" -#include "../common/event/timer.h" #include class UCSConnection @@ -30,5 +30,3 @@ class UCSConnection std::shared_ptr connection; }; - -#endif /*UCS_H_*/ diff --git a/world/web_interface.cpp b/world/web_interface.cpp index 1de21b4e4d..e794b7074b 100644 --- a/world/web_interface.cpp +++ b/world/web_interface.cpp @@ -1,7 +1,7 @@ #include "web_interface.h" -#include "../common/json/json.h" -#include "web_interface_eqw.h" +#include "common/json/json.h" +#include "world/web_interface_eqw.h" #include diff --git a/world/web_interface.h b/world/web_interface.h index 0725c190af..4933d79050 100644 --- a/world/web_interface.h +++ b/world/web_interface.h @@ -1,12 +1,11 @@ #pragma once -#include "../common/net/servertalk_server_connection.h" -#include "../common/json/json.h" +#include "common/json/json.h" +#include "common/net/servertalk_server_connection.h" + +#include #include #include -#include - - class WebInterface { diff --git a/world/web_interface_eqw.cpp b/world/web_interface_eqw.cpp index 2601eccc8b..554b495f39 100644 --- a/world/web_interface_eqw.cpp +++ b/world/web_interface_eqw.cpp @@ -1,10 +1,11 @@ #include "web_interface_eqw.h" -#include "web_interface.h" -#include "world_config.h" -#include "login_server_list.h" -#include "clientlist.h" -#include "zonelist.h" -#include "launcher_list.h" + +#include "world/clientlist.h" +#include "world/launcher_list.h" +#include "world/login_server_list.h" +#include "world/web_interface.h" +#include "world/world_config.h" +#include "world/zonelist.h" extern LauncherList launcher_list; diff --git a/world/web_interface_eqw.h b/world/web_interface_eqw.h index 6ebceae157..d7a3f54f5d 100644 --- a/world/web_interface_eqw.h +++ b/world/web_interface_eqw.h @@ -2,4 +2,4 @@ class WebInterface; -void RegisterEQW(WebInterface *i); \ No newline at end of file +void RegisterEQW(WebInterface *i); diff --git a/world/wguild_mgr.cpp b/world/wguild_mgr.cpp index ace4d9e0f3..fbbbbcd78b 100644 --- a/world/wguild_mgr.cpp +++ b/world/wguild_mgr.cpp @@ -16,23 +16,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/eqemu_logsys.h" -#include "../common/global_define.h" #include "wguild_mgr.h" -#include "../common/servertalk.h" -#include "clientlist.h" -#include "zonelist.h" -#include "zoneserver.h" -#include "cliententry.h" -#include "client.h" -#include "../common/repositories/guilds_repository.h" -#include "../common/repositories/guild_ranks_repository.h" -#include "../common/repositories/guild_permissions_repository.h" -#include "../common/repositories/guild_members_repository.h" -#include "../common/repositories/guild_bank_repository.h" -#include "../common/repositories/guild_tributes_repository.h" -#include "../common/repositories/tributes_repository.h" -#include "../common/repositories/tribute_levels_repository.h" + +#include "common/eqemu_logsys.h" +#include "common/repositories/guild_bank_repository.h" +#include "common/repositories/guild_members_repository.h" +#include "common/repositories/guild_permissions_repository.h" +#include "common/repositories/guild_ranks_repository.h" +#include "common/repositories/guild_tributes_repository.h" +#include "common/repositories/guilds_repository.h" +#include "common/repositories/tribute_levels_repository.h" +#include "common/repositories/tributes_repository.h" +#include "common/servertalk.h" +#include "world/client.h" +#include "world/cliententry.h" +#include "world/clientlist.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" std::map tribute_list; diff --git a/world/wguild_mgr.h b/world/wguild_mgr.h index 9a02047602..f107086d99 100644 --- a/world/wguild_mgr.h +++ b/world/wguild_mgr.h @@ -1,8 +1,7 @@ -#ifndef WGUILD_MGR_H_ -#define WGUILD_MGR_H_ +#pragma once -#include "../common/types.h" -#include "../common/guild_base.h" +#include "common/types.h" +#include "common/guild_base.h" class Client; class ServerPacket; @@ -30,7 +29,3 @@ class WorldGuildManager : public BaseGuildManager { }; extern WorldGuildManager guild_mgr; - - -#endif /*WGUILD_MGR_H_*/ - diff --git a/world/world_boot.cpp b/world/world_boot.cpp index 19667927c6..337e5d1336 100644 --- a/world/world_boot.cpp +++ b/world/world_boot.cpp @@ -1,33 +1,34 @@ -#include "../common/content/world_content_service.h" -#include "../common/emu_constants.h" -#include "../common/eqemu_logsys.h" -#include "../common/http/httplib.h" -#include "../common/http/uri.h" -#include "../common/net/console_server.h" -#include "../common/net/servertalk_server.h" -#include "../common/repositories/character_expedition_lockouts_repository.h" -#include "../common/repositories/character_task_timers_repository.h" -#include "../common/rulesys.h" -#include "../common/strings.h" -#include "adventure_manager.h" -#include "dynamic_zone_manager.h" -#include "login_server_list.h" -#include "shared_task_manager.h" -#include "ucs.h" -#include "wguild_mgr.h" #include "world_boot.h" -#include "world_config.h" -#include "world_event_scheduler.h" -#include "world_server_cli.h" -#include "../common/zone_store.h" -#include "worlddb.h" -#include "zonelist.h" -#include "zoneserver.h" -#include "../common/ip_util.h" -#include "../common/zone_store.h" -#include "../common/path_manager.h" -#include "../common/database/database_update.h" -#include "../common/repositories/zone_state_spawns_repository.h" + +#include "common/content/world_content_service.h" +#include "common/database/database_update.h" +#include "common/emu_constants.h" +#include "common/eqemu_logsys.h" +#include "common/http/httplib.h" +#include "common/http/uri.h" +#include "common/ip_util.h" +#include "common/net/console_server.h" +#include "common/net/servertalk_server.h" +#include "common/path_manager.h" +#include "common/repositories/character_expedition_lockouts_repository.h" +#include "common/repositories/character_task_timers_repository.h" +#include "common/repositories/zone_state_spawns_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "common/zone_store.h" +#include "common/zone_store.h" +#include "world/adventure_manager.h" +#include "world/dynamic_zone_manager.h" +#include "world/login_server_list.h" +#include "world/shared_task_manager.h" +#include "world/ucs.h" +#include "world/wguild_mgr.h" +#include "world/world_config.h" +#include "world/world_event_scheduler.h" +#include "world/world_server_cli.h" +#include "world/worlddb.h" +#include "world/zonelist.h" +#include "world/zoneserver.h" extern WorldConfig Config; diff --git a/world/world_boot.h b/world/world_boot.h index e58b900c54..d8254d5862 100644 --- a/world/world_boot.h +++ b/world/world_boot.h @@ -1,10 +1,10 @@ -#ifndef EQEMU_WORLD_BOOT_H -#define EQEMU_WORLD_BOOT_H +#pragma once + +#include "common/discord/discord.h" +#include "common/types.h" +#include "world/ucs.h" #include -#include "../common/types.h" -#include "../common/discord/discord.h" -#include "ucs.h" class WorldBoot { public: @@ -27,6 +27,3 @@ class WorldBoot { SendDiscordMessage(webhook_id, message_prefix + Discord::FormatDiscordMessage(log_category, message)); }; }; - - -#endif //EQEMU_WORLD_BOOT_H diff --git a/world/world_config.cpp b/world/world_config.cpp index d49884740c..53055b2541 100644 --- a/world/world_config.cpp +++ b/world/world_config.cpp @@ -15,10 +15,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" + #include "world_config.h" +#include "common/eqemu_logsys.h" + WorldConfig *WorldConfig::_world_config = nullptr; std::string WorldConfig::GetByName(const std::string &var_name) const @@ -31,4 +32,3 @@ std::string WorldConfig::GetByName(const std::string &var_name) const } return (EQEmuConfig::GetByName(var_name)); } - diff --git a/world/world_config.h b/world/world_config.h index bcea602d34..ffe0114e1b 100644 --- a/world/world_config.h +++ b/world/world_config.h @@ -15,10 +15,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __WorldConfig_H -#define __WorldConfig_H -#include "../common/eqemu_config.h" +#pragma once + +#include "common/eqemu_config.h" class WorldConfig : public EQEmuConfig { public: @@ -64,5 +64,3 @@ class WorldConfig : public EQEmuConfig { void Dump() const; }; - -#endif diff --git a/world/world_console_connection.cpp b/world/world_console_connection.cpp index 930f6da950..196826954d 100644 --- a/world/world_console_connection.cpp +++ b/world/world_console_connection.cpp @@ -1,6 +1,7 @@ #include "world_console_connection.h" -#include -#include + +#include +#include void WorldConsoleTCPConnection::SendEmoteMessage(const char *to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char *message, ...) { diff --git a/world/world_console_connection.h b/world/world_console_connection.h index 5629f1defa..616fdbd128 100644 --- a/world/world_console_connection.h +++ b/world/world_console_connection.h @@ -15,10 +15,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #pragma once -#include "world_tcp_connection.h" -#include "../common/net/console_server_connection.h" +#include "common/net/console_server_connection.h" +#include "world/world_tcp_connection.h" class WorldConsoleTCPConnection : public WorldTCPConnection { @@ -33,4 +34,3 @@ class WorldConsoleTCPConnection : public WorldTCPConnection private: EQ::Net::ConsoleServerConnection *m_connection; }; - diff --git a/world/world_event_scheduler.cpp b/world/world_event_scheduler.cpp index c1ab226ab9..c9ceafc525 100644 --- a/world/world_event_scheduler.cpp +++ b/world/world_event_scheduler.cpp @@ -1,8 +1,10 @@ #include "world_event_scheduler.h" -#include "../common/servertalk.h" + +#include "common/rulesys.h" +#include "common/server_reload_types.h" +#include "common/servertalk.h" + #include -#include "../common/rulesys.h" -#include "../common/server_reload_types.h" void WorldEventScheduler::Process(ZSList *zs_list) { diff --git a/world/world_event_scheduler.h b/world/world_event_scheduler.h index 4819b14001..d5e333f645 100644 --- a/world/world_event_scheduler.h +++ b/world/world_event_scheduler.h @@ -1,8 +1,7 @@ -#ifndef EQEMU_EVENT_SCHEDULER_H -#define EQEMU_EVENT_SCHEDULER_H +#pragma once -#include "../common/server_event_scheduler.h" -#include "zonelist.h" +#include "common/server_event_scheduler.h" +#include "world/zonelist.h" class WorldEventScheduler : public ServerEventScheduler { public: @@ -14,5 +13,3 @@ class WorldEventScheduler : public ServerEventScheduler { return &instance; } }; - -#endif //EQEMU_EVENT_SCHEDULER_H diff --git a/world/world_server_cli.cpp b/world/world_server_cli.cpp index 111929a0c4..50b16f4e41 100644 --- a/world/world_server_cli.cpp +++ b/world/world_server_cli.cpp @@ -1,9 +1,5 @@ #include "world_server_cli.h" -/** - * @param argc - * @param argv - */ void WorldserverCLI::CommandHandler(int argc, char **argv) { if (argc == 1) { return; } @@ -38,4 +34,3 @@ void WorldserverCLI::CommandHandler(int argc, char **argv) EQEmuCommand::HandleMenu(function_map, cmd, argc, argv); } - diff --git a/world/world_server_cli.h b/world/world_server_cli.h index 1066158b9c..4fa4b434e1 100644 --- a/world/world_server_cli.h +++ b/world/world_server_cli.h @@ -1,8 +1,7 @@ -#include "iostream" -#include "../common/cli/eqemu_command_handler.h" -#ifndef EQEMU_WORLD_SERVER_COMMAND_HANDLER_H -#define EQEMU_WORLD_SERVER_COMMAND_HANDLER_H +#pragma once + +#include "common/cli/eqemu_command_handler.h" class WorldserverCLI { public: @@ -27,6 +26,3 @@ class WorldserverCLI { static void TestStringBenchmarkCommand(int argc, char **argv, argh::parser &cmd, std::string &description); static void EtlGetSettings(int argc, char **argv, argh::parser &cmd, std::string &description); }; - - -#endif //EQEMU_WORLD_SERVER_COMMAND_HANDLER_H diff --git a/world/world_tcp_connection.h b/world/world_tcp_connection.h index dd9ff7a5bf..960e072041 100644 --- a/world/world_tcp_connection.h +++ b/world/world_tcp_connection.h @@ -15,10 +15,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef WorldTCPCONNECTION_H -#define WorldTCPCONNECTION_H -#include "../common/types.h" +#pragma once + +#include "common/types.h" class WorldTCPConnection { @@ -31,5 +31,3 @@ class WorldTCPConnection virtual inline bool IsConsole() { return false; } virtual inline bool IsZoneServer() { return false; } }; - -#endif diff --git a/world/worlddb.cpp b/world/worlddb.cpp index f47cdb608d..b03478e8ba 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -17,22 +17,23 @@ */ #include "worlddb.h" -#include "../common/strings.h" -#include "../common/eq_packet_structs.h" -#include "../common/inventory_profile.h" -#include "../common/rulesys.h" -#include + +#include "common/eq_packet_structs.h" +#include "common/inventory_profile.h" +#include "common/repositories/character_bind_repository.h" +#include "common/repositories/character_data_repository.h" +#include "common/repositories/character_instance_safereturns_repository.h" +#include "common/repositories/character_material_repository.h" +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/inventory_repository.h" +#include "common/repositories/start_zones_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "common/zone_store.h" +#include "world/sof_char_create_data.h" + #include #include -#include "sof_char_create_data.h" -#include "../common/repositories/character_instance_safereturns_repository.h" -#include "../common/repositories/inventory_repository.h" -#include "../common/repositories/criteria/content_filter_criteria.h" -#include "../common/zone_store.h" -#include "../common/repositories/character_data_repository.h" -#include "../common/repositories/character_bind_repository.h" -#include "../common/repositories/character_material_repository.h" -#include "../common/repositories/start_zones_repository.h" WorldDatabase database; WorldDatabase content_db; diff --git a/world/worlddb.h b/world/worlddb.h index 5d9dab2e80..b6025b3d30 100644 --- a/world/worlddb.h +++ b/world/worlddb.h @@ -15,13 +15,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef WORLDDB_H_ -#define WORLDDB_H_ -#include "../common/shareddb.h" -#include "../common/eq_packet.h" -#include "../common/repositories/inventory_repository.h" -#include "../common/repositories/character_data_repository.h" +#pragma once + +#include "common/eq_packet.h" +#include "common/repositories/character_data_repository.h" +#include "common/repositories/inventory_repository.h" +#include "common/shareddb.h" struct PlayerProfile_Struct; struct CharCreate_Struct; @@ -54,5 +54,3 @@ class WorldDatabase : public SharedDatabase { extern WorldDatabase database; extern WorldDatabase content_db; - -#endif /*WORLDDB_H_*/ diff --git a/world/zonelist.cpp b/world/zonelist.cpp index f108031dc1..1f4ae80fcd 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -15,31 +15,32 @@ 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 "../common/global_define.h" + #include "zonelist.h" -#include "zoneserver.h" -#include "worlddb.h" -#include "world_config.h" -#include "../common/misc_functions.h" -#include "../common/servertalk.h" -#include "../common/strings.h" -#include "../common/random.h" -#include "../common/json/json.h" -#include "../common/event_sub.h" -#include "web_interface.h" -#include "../common/zone_store.h" -#include "../common/events/player_event_logs.h" -#include "../common/patches/patches.h" -#include "../common/skill_caps.h" -#include "../common/content/world_content_service.h" -#include "world_boot.h" -#include "shared_task_manager.h" -#include "dynamic_zone_manager.h" -#include "ucs.h" -#include "clientlist.h" -#include "queryserv.h" -#include "../common/repositories/trader_repository.h" -#include "../common/repositories/buyer_repository.h" + +#include "common/content/world_content_service.h" +#include "common/event_sub.h" +#include "common/events/player_event_logs.h" +#include "common/json/json.h" +#include "common/misc_functions.h" +#include "common/patches/patches.h" +#include "common/random.h" +#include "common/repositories/buyer_repository.h" +#include "common/repositories/trader_repository.h" +#include "common/servertalk.h" +#include "common/skill_caps.h" +#include "common/strings.h" +#include "common/zone_store.h" +#include "world/clientlist.h" +#include "world/dynamic_zone_manager.h" +#include "world/queryserv.h" +#include "world/shared_task_manager.h" +#include "world/ucs.h" +#include "world/web_interface.h" +#include "world/world_boot.h" +#include "world/world_config.h" +#include "world/worlddb.h" +#include "world/zoneserver.h" extern uint32 numzones; volatile bool UCSServerAvailable_ = false; diff --git a/world/zonelist.h b/world/zonelist.h index 43dd52b449..9263a1e903 100644 --- a/world/zonelist.h +++ b/world/zonelist.h @@ -1,15 +1,15 @@ -#ifndef ZONELIST_H_ -#define ZONELIST_H_ - -#include "../common/types.h" -#include "../common/eqtime.h" -#include "../common/timer.h" -#include "../common/event/timer.h" -#include "../common/server_reload_types.h" -#include -#include +#pragma once + +#include "common/eqtime.h" +#include "common/event/timer.h" +#include "common/server_reload_types.h" +#include "common/timer.h" +#include "common/types.h" + #include +#include #include +#include class WorldTCPConnection; class ServerPacket; @@ -97,6 +97,3 @@ class ZSList std::list> zone_server_list; }; - -#endif /*ZONELIST_H_*/ - diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 30e90cb094..8e6c7e72ee 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -16,41 +16,42 @@ 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 "../common/global_define.h" + #include "zoneserver.h" -#include "clientlist.h" -#include "login_server.h" -#include "login_server_list.h" -#include "zonelist.h" -#include "worlddb.h" -#include "client.h" -#include "../common/md5.h" -#include "world_config.h" -#include "../common/guilds.h" -#include "../common/packet_dump.h" -#include "../common/misc.h" -#include "../common/strings.h" -#include "cliententry.h" -#include "wguild_mgr.h" -#include "lfplist.h" -#include "adventure_manager.h" -#include "ucs.h" -#include "queryserv.h" -#include "../common/zone_store.h" -#include "dynamic_zone.h" -#include "dynamic_zone_manager.h" -#include "shared_task_world_messaging.h" -#include "../common/shared_tasks.h" -#include "shared_task_manager.h" -#include "../common/content/world_content_service.h" -#include "../common/repositories/player_event_logs_repository.h" -#include "../common/events/player_event_logs.h" -#include "../common/patches/patches.h" -#include "../common/repositories/guild_tributes_repository.h" -#include "../common/skill_caps.h" -#include "../common/server_reload_types.h" -#include "../common/repositories/trader_repository.h" -#include "../common/repositories/buyer_repository.h" + +#include "common/content/world_content_service.h" +#include "common/events/player_event_logs.h" +#include "common/guilds.h" +#include "common/md5.h" +#include "common/misc.h" +#include "common/packet_dump.h" +#include "common/patches/patches.h" +#include "common/repositories/buyer_repository.h" +#include "common/repositories/guild_tributes_repository.h" +#include "common/repositories/player_event_logs_repository.h" +#include "common/repositories/trader_repository.h" +#include "common/server_reload_types.h" +#include "common/shared_tasks.h" +#include "common/skill_caps.h" +#include "common/strings.h" +#include "common/zone_store.h" +#include "world/adventure_manager.h" +#include "world/client.h" +#include "world/cliententry.h" +#include "world/clientlist.h" +#include "world/dynamic_zone_manager.h" +#include "world/dynamic_zone.h" +#include "world/lfplist.h" +#include "world/login_server_list.h" +#include "world/login_server.h" +#include "world/queryserv.h" +#include "world/shared_task_manager.h" +#include "world/shared_task_world_messaging.h" +#include "world/ucs.h" +#include "world/wguild_mgr.h" +#include "world/world_config.h" +#include "world/worlddb.h" +#include "world/zonelist.h" extern GroupLFPList LFPGroupList; extern volatile bool RunLoops; diff --git a/world/zoneserver.h b/world/zoneserver.h index 4e93c9b7e3..30d06a18db 100644 --- a/world/zoneserver.h +++ b/world/zoneserver.h @@ -15,16 +15,18 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef ZONESERVER_H -#define ZONESERVER_H + +#pragma once #include "world_tcp_connection.h" -#include "../common/net/servertalk_server.h" -#include "../common/event/timer.h" -#include "../common/timer.h" -#include "../common/emu_constants.h" -#include "console.h" -#include + +#include "common/net/servertalk_server.h" +#include "common/event/timer.h" +#include "common/timer.h" +#include "common/emu_constants.h" +#include "world/console.h" + +#include #include class Client; @@ -102,6 +104,3 @@ class ZoneServer : public WorldTCPConnection { std::string launched_name; //the name of the zone we launched. EQ::Net::ConsoleServer *console; }; - -#endif - From 7fe49b563000f85f33e1419e538c82a551e84010 Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 00:59:27 -0800 Subject: [PATCH 080/194] normalize includes: zone --- zone/CMakeLists.txt | 9 +- zone/aa.cpp | 52 ++++---- zone/aa.h | 5 +- zone/aa_ability.cpp | 7 +- zone/aa_ability.h | 18 ++- zone/aa_rank.h | 15 +-- zone/aa_rank_effects.h | 13 +- zone/aggro.cpp | 24 ++-- zone/aggromanager.cpp | 2 - zone/aggromanager.h | 11 +- zone/api_service.cpp | 23 ++-- zone/api_service.h | 3 +- zone/attack.cpp | 47 +++----- zone/aura.cpp | 13 +- zone/aura.h | 17 ++- zone/beacon.cpp | 25 +--- zone/beacon.h | 12 +- zone/bonuses.cpp | 32 ++--- zone/bot.cpp | 23 ++-- zone/bot.h | 38 +++--- zone/bot_command.cpp | 48 ++++---- zone/bot_command.h | 11 +- zone/bot_database.cpp | 63 +++++----- zone/bot_database.h | 8 +- zone/bot_raid.cpp | 16 +-- zone/bot_raid.h | 39 +++--- zone/bot_structs.h | 13 +- zone/botspellsai.cpp | 7 +- zone/cheat_manager.cpp | 11 +- zone/cheat_manager.h | 19 ++- zone/cli/cli_benchmark_databuckets.cpp | 21 ++-- zone/cli/cli_sidecar_serve_http.cpp | 14 ++- zone/cli/tests/cli_databuckets.cpp | 18 +-- zone/cli/tests/cli_npc_handins.cpp | 20 +-- zone/cli/tests/cli_npc_handins_multiquest.cpp | 16 +-- zone/cli/tests/cli_test_util.cpp | 2 +- zone/cli/tests/cli_zone_state.cpp | 16 +-- zone/client.cpp | 114 ++++++++---------- zone/client.h | 93 ++++++-------- zone/client_bot.cpp | 3 +- zone/client_evolving_items.cpp | 12 +- zone/client_mods.cpp | 13 +- zone/client_packet.cpp | 98 +++++++-------- zone/client_process.cpp | 54 ++++----- zone/combat_record.cpp | 5 +- zone/combat_record.h | 8 +- zone/command.cpp | 57 ++++----- zone/command.h | 14 +-- zone/common.h | 15 +-- zone/corpse.cpp | 52 +++----- zone/corpse.h | 14 +-- zone/dialogue_window.h | 11 +- zone/doors.cpp | 35 +++--- zone/doors.h | 8 +- zone/dynamic_zone.cpp | 16 +-- zone/dynamic_zone.h | 8 +- zone/effects.cpp | 20 ++- zone/embparser.cpp | 22 ++-- zone/embparser.h | 19 ++- zone/embparser_api.cpp | 35 +++--- zone/embperl.cpp | 24 ++-- zone/embperl.h | 14 +-- zone/encounter.cpp | 16 +-- zone/encounter.h | 11 +- zone/entity.cpp | 51 +++----- zone/entity.h | 28 ++--- zone/event_codes.h | 6 +- zone/exp.cpp | 36 +++--- zone/expedition_request.cpp | 11 +- zone/expedition_request.h | 10 +- zone/fastmath.cpp | 9 +- zone/fastmath.h | 5 +- zone/fearpath.cpp | 13 +- zone/forage.cpp | 47 ++++---- zone/forage.h | 8 +- zone/global_loot_manager.cpp | 9 +- zone/global_loot_manager.h | 5 +- zone/groups.cpp | 23 ++-- zone/groups.h | 13 +- zone/guild.cpp | 11 +- zone/guild_mgr.cpp | 19 +-- zone/guild_mgr.h | 16 +-- zone/hate_list.cpp | 21 ++-- zone/hate_list.h | 11 +- zone/heal_rotation.cpp | 4 +- zone/heal_rotation.h | 8 +- zone/horse.cpp | 20 ++- zone/horse.h | 9 +- zone/inventory.cpp | 24 ++-- zone/loot.cpp | 27 ++--- zone/lua_bit.cpp | 2 +- zone/lua_bit.h | 5 +- zone/lua_bot.cpp | 19 +-- zone/lua_bot.h | 10 +- zone/lua_buff.cpp | 10 +- zone/lua_buff.h | 11 +- zone/lua_client.cpp | 37 +++--- zone/lua_client.h | 9 +- zone/lua_corpse.cpp | 15 +-- zone/lua_corpse.h | 9 +- zone/lua_database.cpp | 8 +- zone/lua_database.h | 7 +- zone/lua_door.cpp | 12 +- zone/lua_door.h | 9 +- zone/lua_encounter.cpp | 7 +- zone/lua_encounter.h | 10 +- zone/lua_entity.cpp | 24 ++-- zone/lua_entity.h | 9 +- zone/lua_entity_list.cpp | 32 ++--- zone/lua_entity_list.h | 9 +- zone/lua_expedition.cpp | 10 +- zone/lua_expedition.h | 10 +- zone/lua_general.cpp | 57 ++++----- zone/lua_general.h | 9 +- zone/lua_group.cpp | 20 +-- zone/lua_group.h | 9 +- zone/lua_hate_list.cpp | 13 +- zone/lua_hate_list.h | 9 +- zone/lua_inventory.cpp | 14 ++- zone/lua_inventory.h | 9 +- zone/lua_item.cpp | 9 +- zone/lua_item.h | 10 +- zone/lua_iteminst.cpp | 11 +- zone/lua_iteminst.h | 11 +- zone/lua_merc.cpp | 19 +-- zone/lua_merc.h | 7 +- zone/lua_mob.cpp | 31 ++--- zone/lua_mob.h | 10 +- zone/lua_mod.cpp | 48 ++++---- zone/lua_mod.h | 3 +- zone/lua_npc.cpp | 21 ++-- zone/lua_npc.h | 9 +- zone/lua_object.cpp | 11 +- zone/lua_object.h | 9 +- zone/lua_packet.cpp | 10 +- zone/lua_packet.h | 12 +- zone/lua_parser.cpp | 83 +++++++------ zone/lua_parser.h | 24 ++-- zone/lua_parser_events.cpp | 43 ++++--- zone/lua_parser_events.h | 28 ++++- zone/lua_ptr.h | 10 +- zone/lua_raid.cpp | 19 +-- zone/lua_raid.h | 9 +- zone/lua_spawn.cpp | 11 +- zone/lua_spawn.h | 9 +- zone/lua_spell.cpp | 10 +- zone/lua_spell.h | 9 +- zone/lua_stat_bonuses.cpp | 9 +- zone/lua_stat_bonuses.h | 6 +- zone/lua_zone.cpp | 12 +- zone/lua_zone.h | 10 +- zone/main.cpp | 102 +++++++--------- zone/map.cpp | 18 ++- zone/map.h | 11 +- zone/masterentity.h | 25 ++-- zone/merc.cpp | 21 ++-- zone/merc.h | 7 +- zone/mob.cpp | 43 ++++--- zone/mob.h | 38 +++--- zone/mob_ai.cpp | 41 +++---- zone/mob_appearance.cpp | 17 ++- zone/mob_info.cpp | 5 +- zone/mob_movement_manager.cpp | 21 ++-- zone/mob_movement_manager.h | 1 + zone/npc.cpp | 77 +++++------- zone/npc.h | 37 +++--- zone/npc_scale_manager.cpp | 5 +- zone/npc_scale_manager.h | 10 +- zone/object.cpp | 26 ++-- zone/object.h | 15 +-- zone/oriented_bounding_box.cpp | 6 +- zone/oriented_bounding_box.h | 9 +- zone/parcels.cpp | 16 +-- zone/pathfinder_interface.cpp | 13 +- zone/pathfinder_interface.h | 3 +- zone/pathfinder_nav_mesh.cpp | 19 +-- zone/pathfinder_nav_mesh.h | 5 +- zone/pathing.cpp | 9 +- zone/pch/pch.h | 18 +-- zone/perl_bot.cpp | 11 +- zone/perl_buff.cpp | 9 +- zone/perl_client.cpp | 13 +- zone/perl_database.cpp | 8 +- zone/perl_database.h | 4 +- zone/perl_doors.cpp | 7 +- zone/perl_entity.cpp | 14 +-- zone/perl_expedition.cpp | 9 +- zone/perl_groups.cpp | 9 +- zone/perl_hateentry.cpp | 9 +- zone/perl_inventory.cpp | 7 +- zone/perl_merc.cpp | 9 +- zone/perl_mob.cpp | 17 ++- zone/perl_npc.cpp | 7 +- zone/perl_object.cpp | 7 +- zone/perl_perlpacket.cpp | 11 +- zone/perl_player_corpse.cpp | 7 +- zone/perl_questitem.cpp | 7 +- zone/perl_questitem_data.cpp | 5 +- zone/perl_raids.cpp | 11 +- zone/perl_spawn.cpp | 8 +- zone/perl_spell.cpp | 7 +- zone/perl_stat_bonuses.cpp | 8 +- zone/perl_zone.cpp | 7 +- zone/perlpacket.cpp | 9 +- zone/perlpacket.h | 12 +- zone/petitions.cpp | 27 ++--- zone/petitions.h | 19 ++- zone/pets.cpp | 32 ++--- zone/pets.h | 15 +-- zone/position.cpp | 11 +- zone/position.h | 17 ++- zone/qglobals.cpp | 8 +- zone/qglobals.h | 5 +- zone/queryserv.cpp | 9 +- zone/queryserv.h | 15 +-- zone/quest_db.cpp | 5 +- zone/quest_interface.h | 11 +- zone/quest_parser_collection.cpp | 22 ++-- zone/quest_parser_collection.h | 37 +++--- zone/questmgr.cpp | 63 +++++----- zone/questmgr.h | 11 +- zone/raids.cpp | 35 +++--- zone/raids.h | 16 +-- zone/raycast_mesh.cpp | 16 +-- zone/raycast_mesh.h | 6 +- zone/shared_task_zone_messaging.cpp | 7 +- zone/shared_task_zone_messaging.h | 6 +- .../sidecar_api/loot_simulator_controller.cpp | 5 +- zone/sidecar_api/sidecar_api.cpp | 21 ++-- zone/sidecar_api/sidecar_api.h | 9 +- zone/spawn2.cpp | 36 +++--- zone/spawn2.h | 10 +- zone/spawngroup.cpp | 16 +-- zone/spawngroup.h | 10 +- zone/special_attacks.cpp | 20 +-- zone/spell_effects.cpp | 39 +++--- zone/spells.cpp | 64 ++++------ zone/string_ids.h | 6 +- zone/task_client_state.cpp | 32 ++--- zone/task_client_state.h | 14 +-- zone/task_manager.cpp | 30 ++--- zone/task_manager.h | 19 ++- zone/tasks.cpp | 20 +-- zone/tasks.h | 14 +-- zone/titles.cpp | 17 ++- zone/titles.h | 9 +- zone/tradeskills.cpp | 33 +++-- zone/trading.cpp | 32 +++-- zone/trap.cpp | 16 +-- zone/trap.h | 9 +- zone/tribute.cpp | 28 ++--- zone/tune.cpp | 40 +++--- zone/water_map.cpp | 13 +- zone/water_map.h | 12 +- zone/water_map_v1.h | 11 +- zone/water_map_v2.h | 12 +- zone/waypoints.cpp | 35 +++--- zone/worldserver.cpp | 112 ++++++++--------- zone/worldserver.h | 14 +-- zone/xtargetautohaters.cpp | 10 +- zone/xtargetautohaters.h | 7 +- zone/zone.cpp | 108 +++++++---------- zone/zone.h | 72 ++++++----- zone/zone_cli.cpp | 6 +- zone/zone_cli.h | 11 +- zone/zone_config.h | 8 +- zone/zone_event_scheduler.cpp | 1 + zone/zone_event_scheduler.h | 11 +- zone/zone_loot.cpp | 12 +- zone/zone_npc_factions.cpp | 8 +- zone/zone_reload.cpp | 3 +- zone/zone_reload.h | 7 +- zone/zone_save_state.cpp | 18 +-- zone/zone_save_state.h | 14 +-- zone/zonedb.cpp | 108 ++++++++--------- zone/zonedb.h | 30 ++--- zone/zonedump.h | 15 ++- zone/zoning.cpp | 33 +++-- 278 files changed, 2458 insertions(+), 2928 deletions(-) diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 9d8b90cab5..afb2ca5311 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -269,6 +269,7 @@ add_library(lua_zone STATIC ${lua_sources}) set_property(TARGET lua_zone PROPERTY FOLDER libraries) set_target_properties(lua_zone PROPERTIES UNITY_BUILD ON UNITY_BUILD_BATCH_SIZE 8) +target_include_directories(lua_zone PRIVATE ..) set(perl_sources perl_bot.cpp @@ -300,6 +301,8 @@ set(perl_sources add_library(perl_zone STATIC ${perl_sources}) set_property(TARGET perl_zone PROPERTY FOLDER libraries) set_target_properties(perl_zone PROPERTIES UNITY_BUILD ON UNITY_BUILD_BATCH_SIZE 8) +target_link_libraries(perl_zone PUBLIC cereal::cereal fmt::fmt unofficial::libmariadb) +target_include_directories(perl_zone PRIVATE ..) set(gm_command_sources bot_command.cpp @@ -359,7 +362,6 @@ set(gm_command_sources bot_commands/bot_spell_resist_limits.cpp bot_commands/bot_spell_target_count.cpp bot_commands/bot_spelltypes.cpp - bot_commands/bot_summon.cpp bot_commands/bot_suspend.cpp bot_commands/bot_taunt.cpp bot_commands/bot_timer.cpp @@ -664,6 +666,8 @@ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Source Files" FILES ${gm add_library(gm_commands_zone STATIC ${gm_command_sources}) target_link_libraries(gm_commands_zone PRIVATE common) +target_include_directories(gm_commands_zone PRIVATE ..) + set_target_properties(gm_commands_zone PROPERTIES UNITY_BUILD ON UNITY_BUILD_BATCH_SIZE 32) set_property(TARGET gm_commands_zone PROPERTY FOLDER libraries) @@ -688,7 +692,7 @@ if(EQEMU_BUILD_LUA) endif() if(EQEMU_BUILD_PERL) - target_compile_definitions(perl_zone PUBLIC EMBPERL EMBPERL_PLUGIN PERLBIND_NO_STRICT_SCALAR_TYPES) + target_compile_definitions(perl_zone PUBLIC EMBPERL EMBPERL_PLUGIN PERLBIND_NO_STRICT_SCALAR_TYPES) target_link_libraries(perl_zone PUBLIC perlbind common ${PERL_LIBRARY}) if (EQEMU_BUILD_STATIC AND PERL_LIBRARY) target_link_libraries(zone PRIVATE ${PERL_LIBRARY}) @@ -696,6 +700,7 @@ if(EQEMU_BUILD_PERL) endif() target_link_libraries(zone PRIVATE gm_commands_zone common RecastNavigation::Detour) +target_include_directories(zone PRIVATE ..) if(EQEMU_BUILD_LUA) target_link_libraries(zone PRIVATE lua_zone) diff --git a/zone/aa.cpp b/zone/aa.cpp index edefa361db..8b83054ac4 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -16,34 +16,32 @@ Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/classes.h" -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/eq_packet_structs.h" -#include "../common/races.h" -#include "../common/spdat.h" -#include "../common/strings.h" -#include "../common/events/player_event_logs.h" #include "aa.h" -#include "client.h" -#include "corpse.h" -#include "groups.h" -#include "mob.h" -#include "queryserv.h" -#include "quest_parser_collection.h" -#include "raids.h" -#include "string_ids.h" -#include "titles.h" -#include "zonedb.h" -#include "worldserver.h" - -#include "bot.h" - -#include "../common/repositories/character_alternate_abilities_repository.h" -#include "../common/repositories/aa_ability_repository.h" -#include "../common/repositories/aa_ranks_repository.h" -#include "../common/repositories/aa_rank_effects_repository.h" -#include "../common/repositories/aa_rank_prereqs_repository.h" + +#include "common/classes.h" +#include "common/eq_packet_structs.h" +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/races.h" +#include "common/repositories/aa_ability_repository.h" +#include "common/repositories/aa_rank_effects_repository.h" +#include "common/repositories/aa_rank_prereqs_repository.h" +#include "common/repositories/aa_ranks_repository.h" +#include "common/repositories/character_alternate_abilities_repository.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/corpse.h" +#include "zone/groups.h" +#include "zone/mob.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/raids.h" +#include "zone/string_ids.h" +#include "zone/titles.h" +#include "zone/worldserver.h" +#include "zone/zonedb.h" extern WorldServer worldserver; extern QueryServ* QServ; diff --git a/zone/aa.h b/zone/aa.h index 720fabfd88..350828b0ad 100644 --- a/zone/aa.h +++ b/zone/aa.h @@ -1,5 +1,4 @@ -#ifndef AA_H -#define AA_H +#pragma once #define MAX_SWARM_PETS 12 //this can change as long as you make more coords (swarm_pet_x/swarm_pet_y) #define WAKE_THE_DEAD_NPCTYPEID 500 //We use first pet in pets table as a template @@ -1556,5 +1555,3 @@ enum AATimers aaTimerWarcry, aaTimerMax }; - -#endif diff --git a/zone/aa_ability.cpp b/zone/aa_ability.cpp index 96982b89eb..8043f1625f 100644 --- a/zone/aa_ability.cpp +++ b/zone/aa_ability.cpp @@ -16,10 +16,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/types.h" -#include "masterentity.h" -#include "aa_ability.h" +#include "common/types.h" +#include "zone/masterentity.h" +#include "zone/aa_ability.h" AA::Rank *AA::Ability::GetRankByPointsSpent(int current_level) { if(current_level == 0) diff --git a/zone/aa_ability.h b/zone/aa_ability.h index eb102ca84c..b4902fba9b 100644 --- a/zone/aa_ability.h +++ b/zone/aa_ability.h @@ -16,20 +16,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef EQEMU_ZONE_AA_ABILITY_H -#define EQEMU_ZONE_AA_ABILITY_H +#pragma once -#include "../common/global_define.h" +#include "zone/aa_rank_effects.h" +#include "zone/aa_rank.h" + +#include #include #include -#include -#include "aa_rank_effects.h" -#include "aa_rank.h" class Mob; -namespace AA -{ +namespace AA { class Ability { @@ -57,6 +55,4 @@ class Ability Rank *first; }; -} - -#endif +} // namespace AA diff --git a/zone/aa_rank.h b/zone/aa_rank.h index ba3e4bb99e..5a27914471 100644 --- a/zone/aa_rank.h +++ b/zone/aa_rank.h @@ -16,11 +16,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef EQEMU_ZONE_AA_RANK_H -#define EQEMU_ZONE_AA_RANK_H +#pragma once -namespace AA -{ +#include "common/types.h" + +#include +#include + +namespace AA { class Ability; class Rank @@ -51,6 +54,4 @@ class Rank std::map prereqs; }; -} - -#endif +} // namespace AA diff --git a/zone/aa_rank_effects.h b/zone/aa_rank_effects.h index 83263eb56a..98baa98512 100644 --- a/zone/aa_rank_effects.h +++ b/zone/aa_rank_effects.h @@ -16,14 +16,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef EQEMU_ZONE_AA_RANK_EFFECTS_H -#define EQEMU_ZONE_AA_RANK_EFFECTS_H +#pragma once -#include "../common/global_define.h" -#include +#include "common/types.h" -namespace AA -{ +namespace AA { struct RankEffect { @@ -33,6 +30,4 @@ struct RankEffect int limit_value; }; -} - -#endif +} // namespace AA diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 136a09ded5..123780dab8 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -16,20 +16,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/faction.h" -#include "../common/rulesys.h" -#include "../common/spdat.h" - -#include "client.h" -#include "entity.h" -#include "mob.h" - -#include "bot.h" - -#include "map.h" -#include "water_map.h" +#include "common/eqemu_logsys.h" +#include "common/faction.h" +#include "common/rulesys.h" +#include "common/spdat.h" +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/map.h" +#include "zone/mob.h" +#include "zone/water_map.h" extern Zone* zone; //#define LOSDEBUG 6 diff --git a/zone/aggromanager.cpp b/zone/aggromanager.cpp index 8dd532c748..2398c5a65b 100644 --- a/zone/aggromanager.cpp +++ b/zone/aggromanager.cpp @@ -7,5 +7,3 @@ AggroMeter::AggroMeter() : lock_id(0), target_id(0), secondary_id(0), lock_chang data[i].pct = 0; } } - - diff --git a/zone/aggromanager.h b/zone/aggromanager.h index b140b07d79..06a1c8918d 100644 --- a/zone/aggromanager.h +++ b/zone/aggromanager.h @@ -1,8 +1,8 @@ -#ifndef AGGROMANAGER_H -#define AGGROMANAGER_H +#pragma once -#include "../common/types.h" -#include +#include "common/types.h" + +#include #include class AggroMeter @@ -75,6 +75,3 @@ class AggroMeter // fuck it, lets just use a buffer the size of the largest to work with const inline size_t max_packet_size() const { return sizeof(uint8) + sizeof(uint32) + sizeof(uint8) + (sizeof(uint8) + sizeof(uint16)) * AT_Max; } }; - - -#endif /* !AGGROMANAGER_H */ diff --git a/zone/api_service.cpp b/zone/api_service.cpp index 607ab64c6c..4e85e9373f 100644 --- a/zone/api_service.cpp +++ b/zone/api_service.cpp @@ -18,18 +18,19 @@ * */ -#include -#include "../common/net/websocket_server.h" -#include "../common/eqemu_logsys.h" -#include "zonedb.h" -#include "client.h" -#include "entity.h" -#include "corpse.h" #include "api_service.h" -#include "object.h" -#include "zone.h" -#include "doors.h" -#include + +#include "common/eqemu_logsys.h" +#include "common/net/websocket_server.h" +#include "zone/client.h" +#include "zone/corpse.h" +#include "zone/doors.h" +#include "zone/entity.h" +#include "zone/object.h" +#include "zone/zone.h" +#include "zone/zonedb.h" + +#include extern Zone *zone; diff --git a/zone/api_service.h b/zone/api_service.h index 52018838da..bf991cb089 100644 --- a/zone/api_service.h +++ b/zone/api_service.h @@ -20,7 +20,8 @@ #pragma once +#include "common/net/websocket_server.h" + #include -#include "../common/net/websocket_server.h" void RegisterApiService(std::unique_ptr &server); diff --git a/zone/attack.cpp b/zone/attack.cpp index f5552c47cb..e23bb3ffc5 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -16,38 +16,29 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eq_constants.h" -#include "../common/eq_packet_structs.h" -#include "../common/rulesys.h" -#include "../common/spdat.h" -#include "../common/strings.h" -#include "../common/data_verification.h" -#include "../common/misc_functions.h" -#include "../common/events/player_event_logs.h" -#include "queryserv.h" -#include "quest_parser_collection.h" -#include "string_ids.h" -#include "water_map.h" -#include "worldserver.h" -#include "zone.h" -#include "lua_parser.h" -#include "fastmath.h" -#include "mob.h" -#include "npc.h" - -#include "bot.h" +#include "common/data_verification.h" +#include "common/eq_constants.h" +#include "common/eq_packet_structs.h" +#include "common/events/player_event_logs.h" +#include "common/misc_functions.h" +#include "common/rulesys.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/fastmath.h" +#include "zone/lua_parser.h" +#include "zone/mob.h" +#include "zone/npc.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/water_map.h" +#include "zone/worldserver.h" +#include "zone/zone.h" extern QueryServ* QServ; extern WorldServer worldserver; extern FastMath g_Math; - -#ifdef _WINDOWS -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#endif - extern EntityList entity_list; extern Zone* zone; diff --git a/zone/aura.cpp b/zone/aura.cpp index a511b60823..77fd687ad0 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -1,10 +1,9 @@ -#include "../common/strings.h" -#include "../common/repositories/auras_repository.h" - -#include "aura.h" -#include "client.h" -#include "string_ids.h" -#include "raids.h" +#include "common/repositories/auras_repository.h" +#include "common/strings.h" +#include "zone/aura.h" +#include "zone/client.h" +#include "zone/raids.h" +#include "zone/string_ids.h" Aura::Aura(NPCType *type_data, Mob *owner, AuraRecord &record) : NPC(type_data, 0, owner->GetPosition(), GravityBehavior::Flying), spell_id(record.spell_id), diff --git a/zone/aura.h b/zone/aura.h index ae4cd0a4a0..c9a92b32b0 100644 --- a/zone/aura.h +++ b/zone/aura.h @@ -1,14 +1,14 @@ -#ifndef AURA_H -#define AURA_H + +#pragma once + +#include "common/timer.h" +#include "common/types.h" +#include "zone/mob.h" +#include "zone/npc.h" #include #include -#include "mob.h" -#include "npc.h" -#include "../common/types.h" -#include "../common/timer.h" - class Group; class Raid; class Mob; @@ -86,6 +86,3 @@ class Aura : public NPC std::set casted_on; // we keep track of the other entities we've casted on std::set spawned_for; }; - -#endif /* !AURA_H */ - diff --git a/zone/beacon.cpp b/zone/beacon.cpp index eed4944862..48106ac77c 100644 --- a/zone/beacon.cpp +++ b/zone/beacon.cpp @@ -17,31 +17,20 @@ */ /* - Beacon class, extends Mob. Used for AE rain spells to have a mob target to center around. - */ -class Zone; - -#ifdef _WINDOWS - #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) - #define snprintf _snprintf - #define vsnprintf _vsnprintf - #endif - #define strncasecmp _strnicmp - #define strcasecmp _stricmp -#endif - -#include "../common/races.h" -#include "beacon.h" -#include "entity.h" -#include "mob.h" +#include "common/races.h" +#include "zone/beacon.h" +#include "zone/entity.h" +#include "zone/mob.h" extern EntityList entity_list; extern Zone* zone; +class Zone; + // if lifetime is 0 this is a permanent beacon.. not sure if that'll be // useful for anything Beacon::Beacon(const glm::vec4 &in_pos, int lifetime) : Mob( @@ -179,5 +168,3 @@ void Beacon::AELocationSpell(Mob *caster, uint16 cast_spell_id, int16 in_resist_ spell_timer.Start(2500); spell_timer.Trigger(); } - - diff --git a/zone/beacon.h b/zone/beacon.h index ac5beb31eb..2692a7cb91 100644 --- a/zone/beacon.h +++ b/zone/beacon.h @@ -16,12 +16,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef BEACON_H -#define BEACON_H +#pragma once -#include "mob.h" -#include "../common/types.h" -#include "../common/timer.h" +#include "common/timer.h" +#include "common/types.h" +#include "zone/mob.h" class Group; class Raid; @@ -59,7 +58,4 @@ class Beacon : public Mob int max_targets; uint16 caster_id; -private: }; - -#endif diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index c1beab76fd..45718570a0 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -15,27 +15,19 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/classes.h" -#include "../common/data_verification.h" -#include "../common/global_define.h" -#include "../common/item_instance.h" -#include "../common/rulesys.h" -#include "../common/spdat.h" - -#include "client.h" -#include "entity.h" -#include "mob.h" - -#include "bot.h" - -#include "quest_parser_collection.h" - - -#ifndef WIN32 -#include -#include "../common/unix.h" -#endif +#include "common/classes.h" +#include "common/data_verification.h" +#include "common/item_instance.h" +#include "common/rulesys.h" +#include "common/spdat.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/mob.h" +#include "zone/bot.h" +#include "zone/quest_parser_collection.h" + +#include void Mob::CalcBonuses() { diff --git a/zone/bot.cpp b/zone/bot.cpp index a702c5e5ae..ca7f6134cd 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -17,17 +17,18 @@ */ #include "bot.h" -#include "object.h" -#include "raids.h" -#include "doors.h" -#include "quest_parser_collection.h" -#include "lua_parser.h" -#include "../common/repositories/bot_inventories_repository.h" -#include "../common/repositories/bot_spell_settings_repository.h" -#include "../common/repositories/bot_starting_items_repository.h" -#include "../common/data_verification.h" -#include "../common/repositories/criteria/content_filter_criteria.h" -#include "../common/skill_caps.h" + +#include "common/data_verification.h" +#include "common/repositories/bot_inventories_repository.h" +#include "common/repositories/bot_spell_settings_repository.h" +#include "common/repositories/bot_starting_items_repository.h" +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/skill_caps.h" +#include "zone/doors.h" +#include "zone/lua_parser.h" +#include "zone/object.h" +#include "zone/quest_parser_collection.h" +#include "zone/raids.h" /* TODO bot rewrite: diff --git a/zone/bot.h b/zone/bot.h index 434e8f7030..6985ba2b8e 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -16,26 +16,22 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef BOT_H -#define BOT_H - -#include "bot_structs.h" -#include "mob.h" -#include "client.h" -#include "pets.h" -#include "heal_rotation.h" -#include "groups.h" -#include "corpse.h" -#include "zonedb.h" -#include "../common/zone_store.h" -#include "string_ids.h" -#include "../common/misc_functions.h" -#include "../common/global_define.h" -#include "guild_mgr.h" -#include "worldserver.h" -#include "raids.h" - -#include +#pragma once + +#include "common/misc_functions.h" +#include "common/zone_store.h" +#include "zone/bot_structs.h" +#include "zone/client.h" +#include "zone/corpse.h" +#include "zone/groups.h" +#include "zone/guild_mgr.h" +#include "zone/heal_rotation.h" +#include "zone/mob.h" +#include "zone/pets.h" +#include "zone/raids.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" +#include "zone/zonedb.h" constexpr uint32 BOT_KEEP_ALIVE_INTERVAL = 5000; // 5 seconds @@ -1266,5 +1262,3 @@ class Bot : public NPC { }; bool IsSpellInBotList(DBbotspells_Struct* spell_list, uint16 spell_id); - -#endif // BOT_H diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 0e202540cf..c8cc1ce32e 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -32,34 +32,28 @@ */ -#include - -#ifdef _WINDOWS -#define strcasecmp _stricmp -#endif - -#include "../common/data_verification.h" -#include "../common/global_define.h" -#include "../common/eq_packet.h" -#include "../common/features.h" -#include "../common/ptimer.h" -#include "../common/rulesys.h" -#include "../common/serverinfo.h" -#include "../common/strings.h" -#include "../common/say_link.h" - #include "bot_command.h" -#include "zonedb.h" -#include "qglobals.h" -#include "queryserv.h" -#include "quest_parser_collection.h" -#include "titles.h" -#include "water_map.h" -#include "worldserver.h" -#include "mob.h" -#include "bot_database.h" - -#include + +#include "common/data_verification.h" +#include "common/eq_packet.h" +#include "common/features.h" +#include "common/ptimer.h" +#include "common/rulesys.h" +#include "common/say_link.h" +#include "common/serverinfo.h" +#include "common/strings.h" +#include "zone/bot_database.h" +#include "zone/mob.h" +#include "zone/qglobals.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/titles.h" +#include "zone/water_map.h" +#include "zone/worldserver.h" +#include "zone/zonedb.h" + +#include "fmt/format.h" +#include extern QueryServ* QServ; extern WorldServer worldserver; diff --git a/zone/bot_command.h b/zone/bot_command.h index 77d449c44d..c8a470bfdd 100644 --- a/zone/bot_command.h +++ b/zone/bot_command.h @@ -16,16 +16,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#pragma once -#ifndef BOT_COMMAND_H -#define BOT_COMMAND_H +#include "common/types.h" +#include "bot.h" +#include "dialogue_window.h" class Client; class Seperator; -#include "../common/types.h" -#include "bot.h" -#include "dialogue_window.h" namespace { @@ -1189,5 +1188,3 @@ bool helper_no_available_bots(Client *bot_owner, Bot *my_bot = nullptr); void helper_send_available_subcommands(Client *bot_owner, const char* command_simile, std::vector subcommand_list); void helper_send_usage_required_bots(Client *bot_owner, uint16 spell_type); void SendSpellTypeWindow(Client* c, const Seperator* sep); - -#endif diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 10d681913a..48ea9bee2e 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -16,38 +16,37 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/data_verification.h" -#include "../common/global_define.h" -#include "../common/rulesys.h" -#include "../common/strings.h" -#include "../common/eqemu_logsys.h" - -#include "../common/repositories/bot_blocked_buffs_repository.h" -#include "../common/repositories/bot_buffs_repository.h" -#include "../common/repositories/bot_create_combinations_repository.h" -#include "../common/repositories/bot_data_repository.h" -#include "../common/repositories/bot_heal_rotations_repository.h" -#include "../common/repositories/bot_heal_rotation_members_repository.h" -#include "../common/repositories/bot_heal_rotation_targets_repository.h" -#include "../common/repositories/bot_inspect_messages_repository.h" -#include "../common/repositories/bot_inventories_repository.h" -#include "../common/repositories/bot_owner_options_repository.h" -#include "../common/repositories/bot_pets_repository.h" -#include "../common/repositories/bot_pet_buffs_repository.h" -#include "../common/repositories/bot_pet_inventories_repository.h" -#include "../common/repositories/bot_spell_casting_chances_repository.h" -#include "../common/repositories/bot_spells_entries_repository.h" -#include "../common/repositories/bot_settings_repository.h" -#include "../common/repositories/bot_stances_repository.h" -#include "../common/repositories/bot_timers_repository.h" -#include "../common/repositories/character_data_repository.h" -#include "../common/repositories/group_id_repository.h" - -#include "zonedb.h" -#include "bot.h" -#include "client.h" - -#include +#include "bot_database.h" + +#include "common/data_verification.h" +#include "common/eqemu_logsys.h" +#include "common/repositories/bot_blocked_buffs_repository.h" +#include "common/repositories/bot_buffs_repository.h" +#include "common/repositories/bot_create_combinations_repository.h" +#include "common/repositories/bot_data_repository.h" +#include "common/repositories/bot_heal_rotation_members_repository.h" +#include "common/repositories/bot_heal_rotation_targets_repository.h" +#include "common/repositories/bot_heal_rotations_repository.h" +#include "common/repositories/bot_inspect_messages_repository.h" +#include "common/repositories/bot_inventories_repository.h" +#include "common/repositories/bot_owner_options_repository.h" +#include "common/repositories/bot_pet_buffs_repository.h" +#include "common/repositories/bot_pet_inventories_repository.h" +#include "common/repositories/bot_pets_repository.h" +#include "common/repositories/bot_settings_repository.h" +#include "common/repositories/bot_spell_casting_chances_repository.h" +#include "common/repositories/bot_spells_entries_repository.h" +#include "common/repositories/bot_stances_repository.h" +#include "common/repositories/bot_timers_repository.h" +#include "common/repositories/character_data_repository.h" +#include "common/repositories/group_id_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/zonedb.h" + +#include "fmt/format.h" bool BotDatabase::LoadBotCommandSettings(std::map>> &bot_command_settings) diff --git a/zone/bot_database.h b/zone/bot_database.h index 7dcdebc28c..279d226695 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -16,15 +16,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#pragma once -#ifndef BOT_DATABASE_H -#define BOT_DATABASE_H - +#include "zone/bot_structs.h" #include #include #include -#include "bot_structs.h" class Bot; class Client; @@ -220,5 +218,3 @@ class BotDatabase std::map> commanded_spell_type_min_levels; }; - -#endif diff --git a/zone/bot_raid.cpp b/zone/bot_raid.cpp index e1eb607484..3a100fe8f0 100644 --- a/zone/bot_raid.cpp +++ b/zone/bot_raid.cpp @@ -16,14 +16,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "bot.h" -#include "bot_command.h" -#include "client.h" -#include "object.h" -#include "raids.h" -#include "doors.h" -#include "quest_parser_collection.h" -#include "../common/data_verification.h" +#include "common/data_verification.h" +#include "zone/bot_command.h" +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/doors.h" +#include "zone/object.h" +#include "zone/quest_parser_collection.h" +#include "zone/raids.h" std::vector Raid::GetRaidGroupMembers(uint32 gid) { diff --git a/zone/bot_raid.h b/zone/bot_raid.h index 994b87e1bd..be0ff5658b 100644 --- a/zone/bot_raid.h +++ b/zone/bot_raid.h @@ -16,26 +16,19 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef BOT_RAID_H -#define BOT_RAID_H - - -#include "bot_structs.h" -#include "mob.h" -#include "client.h" -#include "pets.h" -#include "heal_rotation.h" -#include "groups.h" -#include "corpse.h" -#include "zonedb.h" -#include "../common/zone_store.h" -#include "string_ids.h" -#include "../common/misc_functions.h" -#include "../common/global_define.h" -#include "guild_mgr.h" -#include "worldserver.h" -#include "raids.h" - -#include - -#endif // BOT_RAID_H +#pragma once + +#include "common/misc_functions.h" +#include "common/zone_store.h" +#include "zone/bot_structs.h" +#include "zone/client.h" +#include "zone/corpse.h" +#include "zone/groups.h" +#include "zone/guild_mgr.h" +#include "zone/heal_rotation.h" +#include "zone/mob.h" +#include "zone/pets.h" +#include "zone/raids.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" +#include "zone/zonedb.h" diff --git a/zone/bot_structs.h b/zone/bot_structs.h index 2917cfc0b1..291718883a 100644 --- a/zone/bot_structs.h +++ b/zone/bot_structs.h @@ -16,14 +16,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef BOT_STRUCTS -#define BOT_STRUCTS +#pragma once -#include "../common/types.h" -#include "../common/timer.h" -#include "mob.h" - -#include +#include "common/types.h" +#include "common/timer.h" +#include "zone/mob.h" struct BotsAvailableList { uint32 bot_id; @@ -186,5 +183,3 @@ struct FindPositionInput { bool front_only; bool bypass_los; }; - -#endif // BOT_STRUCTS diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index b6ad79214b..74a2c69e64 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -17,9 +17,10 @@ */ #include "bot.h" -#include "../common/data_verification.h" -#include "../common/repositories/bot_spells_entries_repository.h" -#include "../common/repositories/npc_spells_repository.h" + +#include "common/data_verification.h" +#include "common/repositories/bot_spells_entries_repository.h" +#include "common/repositories/npc_spells_repository.h" bool Bot::AICastSpell(Mob* tar, uint8 chance, uint16 spell_type, uint16 sub_target_type, uint16 sub_type) { if (!tar) { diff --git a/zone/cheat_manager.cpp b/zone/cheat_manager.cpp index 2d4696658b..4c05bfe163 100644 --- a/zone/cheat_manager.cpp +++ b/zone/cheat_manager.cpp @@ -1,9 +1,10 @@ #include "cheat_manager.h" -#include "client.h" -#include "quest_parser_collection.h" -#include "../common/events/player_event_logs.h" -#include "worldserver.h" -#include "queryserv.h" + +#include "common/events/player_event_logs.h" +#include "zone/client.h" +#include "zone/quest_parser_collection.h" +#include "zone/worldserver.h" +#include "zone/queryserv.h" extern WorldServer worldserver; extern QueryServ *QServ; diff --git a/zone/cheat_manager.h b/zone/cheat_manager.h index 78aa89ba62..fff27e330b 100644 --- a/zone/cheat_manager.h +++ b/zone/cheat_manager.h @@ -1,14 +1,15 @@ -#ifndef ANTICHEAT_H -#define ANTICHEAT_H +#pragma once + +#include "common/eq_packet_structs.h" +#include "common/eq_packet.h" +#include "common/rulesys.h" +#include "common/timer.h" + +#include "glm/vec3.hpp" + class CheatManager; class Client; -#include "../common/timer.h" -#include "../common/rulesys.h" -#include -#include "../common/eq_packet_structs.h" -#include "../common/eq_packet.h" - typedef enum { Collision = 1, TeleportB, @@ -85,5 +86,3 @@ class CheatManager { Timer m_time_since_last_movement_history; uint32 m_warp_counter; }; - -#endif //ANTICHEAT_H diff --git a/zone/cli/cli_benchmark_databuckets.cpp b/zone/cli/cli_benchmark_databuckets.cpp index d2d1dc01cb..518ed27676 100644 --- a/zone/cli/cli_benchmark_databuckets.cpp +++ b/zone/cli/cli_benchmark_databuckets.cpp @@ -1,15 +1,18 @@ + +#include "zone/zone_cli.h" +#include "zone/sidecar_api/sidecar_api.h" +#include "zone/zonedb.h" + +#include "common/cli/eqemu_command_handler.h" +#include "common/http/httplib.h" +#include "common/eqemu_logsys.h" +#include "common/platform.h" +#include "common/data_bucket.h" +#include "common/repositories/data_buckets_repository.h" + #include #include #include -#include "../zone_cli.h" -#include "../../common/cli/eqemu_command_handler.h" -#include "../../common/http/httplib.h" -#include "../../common/eqemu_logsys.h" -#include "../sidecar_api/sidecar_api.h" -#include "../../common/platform.h" -#include "../../common/data_bucket.h" -#include "../zonedb.h" -#include "../../common/repositories/data_buckets_repository.h" void RunBenchmarkCycle(uint64_t target_rows) { diff --git a/zone/cli/cli_sidecar_serve_http.cpp b/zone/cli/cli_sidecar_serve_http.cpp index 7e82f89434..3126a42e82 100644 --- a/zone/cli/cli_sidecar_serve_http.cpp +++ b/zone/cli/cli_sidecar_serve_http.cpp @@ -1,9 +1,11 @@ -#include "../zone_cli.h" -#include "../../common/cli/eqemu_command_handler.h" -#include "../../common/http/httplib.h" -#include "../../common/eqemu_logsys.h" -#include "../sidecar_api/sidecar_api.h" -#include "../../common/platform.h" + +#include "zone/zone_cli.h" + +#include "zone/sidecar_api/sidecar_api.h" +#include "common/cli/eqemu_command_handler.h" +#include "common/eqemu_logsys.h" +#include "common/http/httplib.h" +#include "common/platform.h" void ZoneCLI::SidecarServeHttp(int argc, char **argv, argh::parser &cmd, std::string &description) { diff --git a/zone/cli/tests/cli_databuckets.cpp b/zone/cli/tests/cli_databuckets.cpp index 7974c06d21..6e2ed74dd5 100644 --- a/zone/cli/tests/cli_databuckets.cpp +++ b/zone/cli/tests/cli_databuckets.cpp @@ -1,11 +1,13 @@ -#include "../../zone_cli.h" -#include "../../common/cli/eqemu_command_handler.h" -#include "../../common/http/httplib.h" -#include "../../common/eqemu_logsys.h" -#include "../../common/platform.h" -#include "../../zone.h" -#include "../../client.h" -#include "../../common/net/eqstream.h" + +#include "zone/zone_cli.h" + +#include "zone/client.h" +#include "zone/zone.h" +#include "common/cli/eqemu_command_handler.h" +#include "common/eqemu_logsys.h" +#include "common/http/httplib.h" +#include "common/net/eqstream.h" +#include "common/platform.h" extern Zone* zone; diff --git a/zone/cli/tests/cli_npc_handins.cpp b/zone/cli/tests/cli_npc_handins.cpp index da606cf230..a51dbd873b 100644 --- a/zone/cli/tests/cli_npc_handins.cpp +++ b/zone/cli/tests/cli_npc_handins.cpp @@ -1,12 +1,14 @@ -#include "../../zone_cli.h" -#include "../../common/cli/eqemu_command_handler.h" -#include "../../common/http/httplib.h" -#include "../../common/eqemu_logsys.h" -#include "../../common/platform.h" -#include "../../zone.h" -#include "../../client.h" -#include "../../common/net/eqstream.h" -#include "../../common/json/json.hpp" + +#include "zone/zone_cli.h" + +#include "zone/client.h" +#include "zone/zone.h" +#include "common/cli/eqemu_command_handler.h" +#include "common/eqemu_logsys.h" +#include "common/http/httplib.h" +#include "common/json/json.hpp" +#include "common/net/eqstream.h" +#include "common/platform.h" extern Zone *zone; using json = nlohmann::json; diff --git a/zone/cli/tests/cli_npc_handins_multiquest.cpp b/zone/cli/tests/cli_npc_handins_multiquest.cpp index faaffb765e..5a8eca6d15 100644 --- a/zone/cli/tests/cli_npc_handins_multiquest.cpp +++ b/zone/cli/tests/cli_npc_handins_multiquest.cpp @@ -1,10 +1,12 @@ -#include "../../zone_cli.h" -#include "../../common/cli/eqemu_command_handler.h" -#include "../../common/eqemu_logsys.h" -#include "../../common/platform.h" -#include "../../zone.h" -#include "../../client.h" -#include "../../common/net/eqstream.h" + +#include "zone/zone_cli.h" + +#include "zone/client.h" +#include "zone/zone.h" +#include "common/cli/eqemu_command_handler.h" +#include "common/eqemu_logsys.h" +#include "common/net/eqstream.h" +#include "common/platform.h" extern Zone *zone; diff --git a/zone/cli/tests/cli_test_util.cpp b/zone/cli/tests/cli_test_util.cpp index 3f6e7fe2e0..a539303a88 100644 --- a/zone/cli/tests/cli_test_util.cpp +++ b/zone/cli/tests/cli_test_util.cpp @@ -1,4 +1,4 @@ -#include "../../zone.h" +#include "zone/zone.h" void RunTest(const std::string &test_name, const std::string &expected, const std::string &actual) { diff --git a/zone/cli/tests/cli_zone_state.cpp b/zone/cli/tests/cli_zone_state.cpp index 235891fa50..881873e61c 100644 --- a/zone/cli/tests/cli_zone_state.cpp +++ b/zone/cli/tests/cli_zone_state.cpp @@ -1,10 +1,12 @@ -#include "../../zone_cli.h" -#include "../../common/cli/eqemu_command_handler.h" -#include -#include -#include "../../common/repositories/npc_types_repository.h" -#include "../../corpse.h" -#include "../../../common/repositories/respawn_times_repository.h" +#include "zone/zone_cli.h" +#include "zone/corpse.h" + +#include "common/cli/eqemu_command_handler.h" +#include "common/repositories/npc_types_repository.h" +#include "common/repositories/respawn_times_repository.h" + +#include "cereal/archives/json.hpp" +#include "cereal/types/map.hpp" extern Zone* zone; diff --git a/zone/client.cpp b/zone/client.cpp index 07fa25ba6d..05cb01991a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -15,70 +15,57 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include -#include -#include -#include - -// for windows compile -#ifndef _WINDOWS - #include - #include - #include - #include "../common/unix.h" -#endif - -extern volatile bool RunLoops; - -#include "../common/eqemu_logsys.h" -#include "../common/features.h" -#include "../common/spdat.h" -#include "../common/guilds.h" -#include "../common/rulesys.h" -#include "../common/strings.h" -#include "../common/data_verification.h" -#include "../common/profanity_manager.h" -#include "../common/data_bucket.h" -#include "dynamic_zone.h" -#include "expedition_request.h" -#include "position.h" -#include "worldserver.h" -#include "zonedb.h" -#include "petitions.h" -#include "command.h" -#include "water_map.h" -#include "bot_command.h" -#include "string_ids.h" -#include "dialogue_window.h" - -#include "guild_mgr.h" -#include "quest_parser_collection.h" -#include "queryserv.h" -#include "mob_movement_manager.h" -#include "cheat_manager.h" -#include "lua_parser.h" - -#include "../common/repositories/character_alternate_abilities_repository.h" -#include "../common/repositories/character_expedition_lockouts_repository.h" -#include "../common/repositories/account_flags_repository.h" -#include "../common/repositories/bug_reports_repository.h" -#include "../common/repositories/char_recipe_list_repository.h" -#include "../common/repositories/character_spells_repository.h" -#include "../common/repositories/character_disciplines_repository.h" -#include "../common/repositories/character_data_repository.h" -#include "../common/repositories/character_pet_name_repository.h" -#include "../common/repositories/completed_tasks_repository.h" -#include "../common/repositories/discovered_items_repository.h" -#include "../common/repositories/inventory_repository.h" -#include "../common/repositories/keyring_repository.h" -#include "../common/repositories/tradeskill_recipe_repository.h" -#include "../common/events/player_events.h" -#include "../common/events/player_event_logs.h" -#include "dialogue_window.h" -#include "../common/zone_store.h" -#include "../common/skill_caps.h" +#include "client.h" + +#include "common/data_bucket.h" +#include "common/data_verification.h" +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/events/player_events.h" +#include "common/features.h" +#include "common/guilds.h" +#include "common/profanity_manager.h" +#include "common/repositories/account_flags_repository.h" +#include "common/repositories/bug_reports_repository.h" +#include "common/repositories/char_recipe_list_repository.h" +#include "common/repositories/character_alternate_abilities_repository.h" +#include "common/repositories/character_data_repository.h" +#include "common/repositories/character_disciplines_repository.h" +#include "common/repositories/character_expedition_lockouts_repository.h" +#include "common/repositories/character_pet_name_repository.h" +#include "common/repositories/character_spells_repository.h" +#include "common/repositories/completed_tasks_repository.h" +#include "common/repositories/discovered_items_repository.h" +#include "common/repositories/inventory_repository.h" +#include "common/repositories/keyring_repository.h" +#include "common/repositories/tradeskill_recipe_repository.h" +#include "common/rulesys.h" +#include "common/skill_caps.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "common/zone_store.h" +#include "zone/bot_command.h" +#include "zone/cheat_manager.h" +#include "zone/command.h" +#include "zone/dialogue_window.h" +#include "zone/dynamic_zone.h" +#include "zone/expedition_request.h" +#include "zone/guild_mgr.h" +#include "zone/lua_parser.h" +#include "zone/mob_movement_manager.h" +#include "zone/petitions.h" +#include "zone/position.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/water_map.h" +#include "zone/worldserver.h" +#include "zone/zonedb.h" + +#include +#include +#include extern QueryServ* QServ; extern EntityList entity_list; @@ -86,6 +73,7 @@ extern Zone* zone; extern volatile bool is_zone_loaded; extern WorldServer worldserver; extern uint32 numclients; +extern volatile bool RunLoops; void UpdateWindowTitle(char* iNewTitle); diff --git a/zone/client.h b/zone/client.h index d5e8f3ef4c..8f464681bb 100644 --- a/zone/client.h +++ b/zone/client.h @@ -15,8 +15,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef CLIENT_H -#define CLIENT_H + +#pragma once class Client; class EQApplicationPacket; @@ -38,59 +38,48 @@ namespace EQ struct ItemData; } -#include "../common/timer.h" -#include "../common/ptimer.h" -#include "../common/emu_opcodes.h" -#include "../common/eq_packet_structs.h" -#include "../common/emu_constants.h" -#include "../common/eq_stream_intf.h" -#include "../common/eq_packet.h" -#include "../common/linked_list.h" -#include "../common/extprofile.h" -#include "../common/races.h" -#include "../common/seperator.h" -#include "../common/inventory_profile.h" -#include "../common/guilds.h" -//#include "../common/item_data.h" -#include "xtargetautohaters.h" -#include "aggromanager.h" - -#include "common.h" -#include "merc.h" -#include "mob.h" -#include "qglobals.h" -#include "questmgr.h" -#include "zone.h" -#include "zonedb.h" -#include "../common/zone_store.h" -#include "task_manager.h" -#include "task_client_state.h" -#include "cheat_manager.h" -#include "../common/events/player_events.h" -#include "../common/data_verification.h" -#include "../common/repositories/character_parcels_repository.h" -#include "../common/repositories/trader_repository.h" -#include "../common/guild_base.h" -#include "../common/repositories/buyer_buy_lines_repository.h" -#include "../common/repositories/character_evolving_items_repository.h" -#include "../common/repositories/player_titlesets_repository.h" - -#include "bot_structs.h" - -#ifdef _WINDOWS - // since windows defines these within windef.h (which windows.h include) - // we are required to undefine these to use min and max from - #undef min - #undef max -#endif - -#include +#include "zone/aggromanager.h" +#include "zone/bot_structs.h" +#include "zone/cheat_manager.h" +#include "zone/common.h" +#include "zone/merc.h" +#include "zone/mob.h" +#include "zone/qglobals.h" +#include "zone/questmgr.h" +#include "zone/task_client_state.h" +#include "zone/task_manager.h" +#include "zone/xtargetautohaters.h" +#include "zone/zone.h" +#include "zone/zonedb.h" + +#include "common/data_verification.h" +#include "common/emu_constants.h" +#include "common/emu_opcodes.h" +#include "common/eq_packet_structs.h" +#include "common/eq_packet.h" +#include "common/eq_stream_intf.h" +#include "common/events/player_events.h" +#include "common/extprofile.h" +#include "common/guild_base.h" +#include "common/guilds.h" +#include "common/inventory_profile.h" +#include "common/linked_list.h" +#include "common/ptimer.h" +#include "common/races.h" +#include "common/repositories/buyer_buy_lines_repository.h" +#include "common/repositories/character_evolving_items_repository.h" +#include "common/repositories/character_parcels_repository.h" +#include "common/repositories/player_titlesets_repository.h" +#include "common/repositories/trader_repository.h" +#include "common/seperator.h" +#include "common/timer.h" +#include "common/zone_store.h" + +#include #include #include #include #include -#include - #define CLIENT_LD_TIMEOUT 30000 // length of time client stays in zone after LDing #define TARGETING_RANGE 200 // range for /assist and /target @@ -2434,5 +2423,3 @@ class Client : public Mob void CheckAutoIdleAFK(PlayerPositionUpdateClient_Struct *p); void SyncWorldPositionsToClient(bool ignore_idle = false); }; - -#endif diff --git a/zone/client_bot.cpp b/zone/client_bot.cpp index b5621840fa..83e27729da 100644 --- a/zone/client_bot.cpp +++ b/zone/client_bot.cpp @@ -1,6 +1,7 @@ -#include "bot.h" #include "client.h" +#include "zone/bot.h" + #define NO_BOT_LIMIT -1; bool Client::GetBotOption(BotOwnerOption boo) const { diff --git a/zone/client_evolving_items.cpp b/zone/client_evolving_items.cpp index 77c29a45e9..8abf4d52b4 100644 --- a/zone/client_evolving_items.cpp +++ b/zone/client_evolving_items.cpp @@ -1,11 +1,9 @@ -#include "../common/evolving_items.h" - -#include "../common/events/player_event_logs.h" -#include "../common/global_define.h" - #include "client.h" -#include "string_ids.h" -#include "worldserver.h" + +#include "common/events/player_event_logs.h" +#include "common/evolving_items.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" extern WorldServer worldserver; extern QueryServ* QServ; diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 6c7026185c..98e85c8b26 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -16,16 +16,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" - -#include "../common/rulesys.h" -#include "../common/spdat.h" - #include "client.h" -#include "mob.h" -#include "bot.h" +#include "common/eqemu_logsys.h" +#include "common/rulesys.h" +#include "common/spdat.h" +#include "zone/bot.h" +#include "zone/mob.h" #include diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index c7bb4a05c8..effa1017fd 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -15,65 +15,51 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/opcodemgr.h" -#include "../common/raid.h" +#include "client.h" +#include "common/data_bucket.h" +#include "common/data_verification.h" +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/opcodemgr.h" +#include "common/raid.h" +#include "common/rdtsc.h" +#include "common/repositories/account_repository.h" +#include "common/repositories/adventure_members_repository.h" +#include "common/repositories/buyer_buy_lines_repository.h" +#include "common/repositories/character_corpses_repository.h" +#include "common/repositories/character_instance_safereturns_repository.h" +#include "common/repositories/character_pet_name_repository.h" +#include "common/repositories/character_stats_record_repository.h" +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/guild_tributes_repository.h" +#include "common/repositories/tradeskill_recipe_entries_repository.h" +#include "common/rulesys.h" +#include "common/shared_tasks.h" +#include "zone/bot.h" +#include "zone/dialogue_window.h" +#include "zone/dynamic_zone.h" +#include "zone/event_codes.h" +#include "zone/gm_commands/door_manipulation.h" +#include "zone/gm_commands/object_manipulation.h" +#include "zone/guild_mgr.h" +#include "zone/merc.h" +#include "zone/mob_movement_manager.h" +#include "zone/petitions.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/titles.h" +#include "zone/water_map.h" +#include "zone/worldserver.h" +#include "zone/zone.h" + +#include "zlib.h" +#include #include #include -#include +#include #include -#include -#include -#include -#include "bot.h" - -#ifdef _WINDOWS -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#else -#include -#include -#include -#include -#endif - -#include "../common/data_verification.h" -#include "../common/rdtsc.h" -#include "../common/data_bucket.h" -#include "dynamic_zone.h" -#include "event_codes.h" -#include "guild_mgr.h" -#include "merc.h" -#include "petitions.h" -#include "queryserv.h" -#include "quest_parser_collection.h" -#include "string_ids.h" -#include "titles.h" -#include "water_map.h" -#include "worldserver.h" -#include "zone.h" -#include "mob_movement_manager.h" -#include "../common/repositories/character_instance_safereturns_repository.h" -#include "../common/repositories/criteria/content_filter_criteria.h" -#include "../common/shared_tasks.h" -#include "gm_commands/door_manipulation.h" -#include "gm_commands/object_manipulation.h" -#include "client.h" -#include "../common/repositories/account_repository.h" -#include "../common/repositories/character_corpses_repository.h" -#include "../common/repositories/guild_tributes_repository.h" -#include "../common/repositories/buyer_buy_lines_repository.h" -#include "../common/repositories/character_pet_name_repository.h" -#include "../common/repositories/tradeskill_recipe_entries_repository.h" - -#include "../common/events/player_event_logs.h" -#include "../common/repositories/character_stats_record_repository.h" -#include "dialogue_window.h" -#include "../common/rulesys.h" -#include "../common/repositories/adventure_members_repository.h" extern QueryServ* QServ; extern Zone* zone; @@ -4925,7 +4911,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { // Calculate angle from boat heading to EQ heading double theta = std::fmod(((boat->GetHeading() * 360.0) / 512.0),360.0); - double thetar = (theta * M_PI) / 180.0; + double thetar = (theta * std::numbers::pi) / 180.0; // Boat cx is inverted (positive to left) // Boat cy is normal (positive toward heading) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 19440e3bb1..479e49d516 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -19,39 +19,29 @@ Handles client login sequence and packets sent from client to zone */ -#include "../common/eqemu_logsys.h" -#include "../common/global_define.h" -#include +#include "client.h" + +#include "common/data_verification.h" +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/rulesys.h" +#include "common/skills.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "zone/dynamic_zone.h" +#include "zone/event_codes.h" +#include "zone/guild_mgr.h" +#include "zone/map.h" +#include "zone/petitions.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/water_map.h" +#include "zone/worldserver.h" +#include "zone/zone.h" +#include "zone/zonedb.h" -#ifdef _WINDOWS - #define snprintf _snprintf - #define strncasecmp _strnicmp - #define strcasecmp _stricmp -#else - #include - #include - #include - #include -#endif - -#include "../common/data_verification.h" -#include "../common/rulesys.h" -#include "../common/skills.h" -#include "../common/spdat.h" -#include "../common/strings.h" -#include "dynamic_zone.h" -#include "event_codes.h" -#include "guild_mgr.h" -#include "map.h" -#include "petitions.h" -#include "queryserv.h" -#include "quest_parser_collection.h" -#include "string_ids.h" -#include "worldserver.h" -#include "zone.h" -#include "zonedb.h" -#include "../common/events/player_event_logs.h" -#include "water_map.h" +#include extern QueryServ* QServ; extern Zone* zone; diff --git a/zone/combat_record.cpp b/zone/combat_record.cpp index b05831b9eb..a70917ab37 100644 --- a/zone/combat_record.cpp +++ b/zone/combat_record.cpp @@ -1,6 +1,7 @@ #include "combat_record.h" -#include "../common/eqemu_logsys.h" -#include "../common/strings.h" + +#include "common/eqemu_logsys.h" +#include "common/strings.h" void CombatRecord::Start(const std::string& in_mob_name) { diff --git a/zone/combat_record.h b/zone/combat_record.h index 32efb15353..bb3a48a0c5 100644 --- a/zone/combat_record.h +++ b/zone/combat_record.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_COMBAT_RECORD_H -#define EQEMU_COMBAT_RECORD_H +#pragma once + +#include "common/types.h" #include #include -#include "../common/types.h" class CombatRecord { public: @@ -25,5 +25,3 @@ class CombatRecord { int64 m_damage_received = 0; int64 m_heal_received = 0; }; - -#endif //EQEMU_COMBAT_RECORD_H diff --git a/zone/command.cpp b/zone/command.cpp index a31760828c..2bd2920603 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -1,36 +1,31 @@ -#include +#include "command.h" + +#include "common/data_bucket.h" +#include "common/eq_packet.h" +#include "common/events/player_event_logs.h" +#include "common/features.h" +#include "common/file.h" +#include "common/net/eqstream.h" +#include "common/ptimer.h" +#include "common/repositories/command_subsettings_repository.h" +#include "common/repositories/dynamic_zones_repository.h" +#include "common/rulesys.h" +#include "common/say_link.h" +#include "common/strings.h" +#include "zone/dynamic_zone.h" +#include "zone/fastmath.h" +#include "zone/mob_movement_manager.h" +#include "zone/npc_scale_manager.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/titles.h" +#include "zone/water_map.h" +#include "zone/worldserver.h" + +#include "fmt/format.h" #include +#include #include -#include -#include "../common/repositories/command_subsettings_repository.h" - -#ifdef _WINDOWS -#define strcasecmp _stricmp -#endif - -#include "../common/global_define.h" -#include "../common/eq_packet.h" -#include "../common/features.h" -#include "../common/ptimer.h" -#include "../common/rulesys.h" -#include "../common/strings.h" -#include "../common/say_link.h" -#include "../common/net/eqstream.h" -#include "../common/file.h" -#include "../common/repositories/dynamic_zones_repository.h" - -#include "../common/data_bucket.h" -#include "command.h" -#include "dynamic_zone.h" -#include "queryserv.h" -#include "quest_parser_collection.h" -#include "titles.h" -#include "water_map.h" -#include "worldserver.h" -#include "fastmath.h" -#include "mob_movement_manager.h" -#include "npc_scale_manager.h" -#include "../common/events/player_event_logs.h" extern QueryServ* QServ; extern WorldServer worldserver; diff --git a/zone/command.h b/zone/command.h index 0159d4d651..752c63bf15 100644 --- a/zone/command.h +++ b/zone/command.h @@ -1,12 +1,12 @@ -#ifndef COMMAND_H -#define COMMAND_H +#pragma once -class Client; -class Seperator; +#include "common/types.h" -#include "../common/types.h" #include +class Client; +class Seperator; + #define COMMAND_CHAR '#' typedef void (*CmdFuncPtr)(Client *, const Seperator *); @@ -200,8 +200,4 @@ void command_zonebootup(Client *c, const Seperator *sep); void command_zoneshutdown(Client *c, const Seperator *sep); void command_zonevariable(Client *c, const Seperator *sep); void command_zsave(Client *c, const Seperator *sep); - -#include "bot.h" void command_bot(Client*c, const Seperator *sep); - -#endif diff --git a/zone/common.h b/zone/common.h index 6a11f7255f..74673ef7e8 100644 --- a/zone/common.h +++ b/zone/common.h @@ -1,11 +1,11 @@ -#ifndef __EQEMU_ZONE_COMMON_H -#define __EQEMU_ZONE_COMMON_H -#include "../common/types.h" -#include "../common/spdat.h" -#include "../common/emu_constants.h" +#pragma once -#include +#include "common/types.h" +#include "common/spdat.h" +#include "common/emu_constants.h" + +#include "cereal/cereal.hpp" #define HIGHEST_RESIST 9 //Max resist type value #define MAX_SPELL_PROJECTILE 10 //Max amount of spell projectiles that can be active by a single mob. @@ -914,6 +914,3 @@ typedef enum { petTargetLock, //remain active as long something is on the hatelist. Don't listen to any commands petNone = 0xFF // not a pet } PetTypeOld; - -#endif - diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 9bd13d63b8..759ee08a7d 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1,38 +1,26 @@ +#include "corpse.h" -#ifdef _WINDOWS -#if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#endif -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#endif - -#include "../common/data_verification.h" -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/rulesys.h" -#include "../common/strings.h" -#include "../common/say_link.h" +#include "common/data_verification.h" +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/json/json.hpp" +#include "common/repositories/character_corpse_items_repository.h" +#include "common/repositories/character_corpses_repository.h" +#include "common/rulesys.h" +#include "common/say_link.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/dynamic_zone.h" +#include "zone/entity.h" +#include "zone/groups.h" +#include "zone/mob.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/raids.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" -#include "corpse.h" -#include "dynamic_zone.h" -#include "entity.h" -#include "groups.h" -#include "mob.h" -#include "raids.h" - -#include "bot.h" - -#include "quest_parser_collection.h" -#include "string_ids.h" -#include "worldserver.h" -#include "../common/events/player_event_logs.h" -#include "../common/repositories/character_corpses_repository.h" -#include "../common/repositories/character_corpse_items_repository.h" #include -#include "queryserv.h" -#include "../common/json/json.hpp" using json = nlohmann::json; diff --git a/zone/corpse.h b/zone/corpse.h index 65c4619506..2dbfc3986b 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -1,10 +1,10 @@ -#ifndef CORPSE_H -#define CORPSE_H -#include "mob.h" -#include "client.h" -#include "../common/loot.h" -#include "../common/repositories/character_corpses_repository.h" +#pragma once + +#include "common/loot.h" +#include "common/repositories/character_corpses_repository.h" +#include "zone/client.h" +#include "zone/mob.h" class EQApplicationPacket; class Group; @@ -288,5 +288,3 @@ class Corpse : public Mob { LootRequestType m_loot_request_type; uint32 m_account_id; }; - -#endif diff --git a/zone/dialogue_window.h b/zone/dialogue_window.h index 5787b818f7..4c233d0f45 100644 --- a/zone/dialogue_window.h +++ b/zone/dialogue_window.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_DIALOGUE_WINDOW_H -#define EQEMU_DIALOGUE_WINDOW_H - +#pragma once +#include #include -#include "client.h" + +class Client; static const std::map html_colors = { {"black", "#000000"}, @@ -462,6 +462,3 @@ class DialogueWindow { static std::string TableCell(std::string message = std::string()); static std::string TableRow(std::string message); }; - - -#endif //EQEMU_DIALOGUE_WINDOW_H diff --git a/zone/doors.cpp b/zone/doors.cpp index 858d63a3eb..9b6b4a4161 100644 --- a/zone/doors.cpp +++ b/zone/doors.cpp @@ -16,26 +16,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/strings.h" - -#include "../common/repositories/doors_repository.h" - -#include "client.h" #include "doors.h" -#include "entity.h" -#include "guild_mgr.h" -#include "mob.h" -#include "string_ids.h" -#include "worldserver.h" -#include "zonedb.h" -#include "../common/evolving_items.h" -#include "../common/repositories/criteria/content_filter_criteria.h" - -#include - -#include + +#include "common/eqemu_logsys.h" +#include "common/evolving_items.h" +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/doors_repository.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/guild_mgr.h" +#include "zone/mob.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" +#include "zone/zonedb.h" + +#include "glm/ext/matrix_transform.hpp" +#include #include #define OPEN_DOOR 0x02 diff --git a/zone/doors.h b/zone/doors.h index f600a280ba..807e3d6bac 100644 --- a/zone/doors.h +++ b/zone/doors.h @@ -1,8 +1,7 @@ -#ifndef DOORS_H -#define DOORS_H +#pragma once -#include "mob.h" -#include "../common/repositories/doors_repository.h" +#include "common/repositories/doors_repository.h" +#include "zone/mob.h" class Client; class Mob; @@ -113,4 +112,3 @@ class Doors : public Entity uint32 m_client_version_mask; bool m_is_blacklisted_to_open = false; // is door blacklisted to open by npcs }; -#endif diff --git a/zone/dynamic_zone.cpp b/zone/dynamic_zone.cpp index e6e993bc26..05e95c8547 100644 --- a/zone/dynamic_zone.cpp +++ b/zone/dynamic_zone.cpp @@ -19,13 +19,15 @@ */ #include "dynamic_zone.h" -#include "client.h" -#include "expedition_request.h" -#include "string_ids.h" -#include "worldserver.h" -#include "../common/repositories/character_expedition_lockouts_repository.h" -#include "../common/repositories/dynamic_zone_lockouts_repository.h" -#include + +#include "common/repositories/character_expedition_lockouts_repository.h" +#include "common/repositories/dynamic_zone_lockouts_repository.h" +#include "zone/client.h" +#include "zone/expedition_request.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" + +#include "cereal/types/utility.hpp" extern WorldServer worldserver; diff --git a/zone/dynamic_zone.h b/zone/dynamic_zone.h index 82d82263fd..845668e5a9 100644 --- a/zone/dynamic_zone.h +++ b/zone/dynamic_zone.h @@ -18,10 +18,10 @@ * */ -#ifndef DYNAMIC_ZONE_H -#define DYNAMIC_ZONE_H +#pragma once + +#include "common/dynamic_zone_base.h" -#include "../common/dynamic_zone_base.h" #include #include #include @@ -137,5 +137,3 @@ class DynamicZone : public DynamicZoneBase std::vector m_loot_events; // only valid inside dz zone }; - -#endif diff --git a/zone/effects.cpp b/zone/effects.cpp index 3efda3d5e0..5c81026b44 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -16,19 +16,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/spdat.h" -#include "../common/misc_functions.h" - -#include "client.h" -#include "entity.h" #include "mob.h" -#include "string_ids.h" -#include "worldserver.h" -#include "zonedb.h" -#include "position.h" +#include "common/eqemu_logsys.h" +#include "common/misc_functions.h" +#include "common/spdat.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/position.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" +#include "zone/zonedb.h" float Mob::GetActSpellRange(uint16 spell_id, float range) { diff --git a/zone/embparser.cpp b/zone/embparser.cpp index ad9708d527..a81bfa9d47 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -18,16 +18,16 @@ #ifdef EMBPERL -#include "../common/global_define.h" -#include "../common/seperator.h" -#include "../common/misc_functions.h" -#include "../common/strings.h" -#include "../common/features.h" -#include "masterentity.h" -#include "embparser.h" -#include "questmgr.h" -#include "qglobals.h" -#include "zone.h" +#include "common/features.h" +#include "common/misc_functions.h" +#include "common/seperator.h" +#include "common/strings.h" +#include "zone/embparser.h" +#include "zone/masterentity.h" +#include "zone/qglobals.h" +#include "zone/questmgr.h" +#include "zone/zone.h" + #include #include @@ -2911,4 +2911,4 @@ int PerlembParser::EventGlobalZone( ); } -#endif +#endif // EMBPERL diff --git a/zone/embparser.h b/zone/embparser.h index 5817ce15b5..5aa95dc54c 100644 --- a/zone/embparser.h +++ b/zone/embparser.h @@ -16,16 +16,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef EQEMU_EMBPARSER_H -#define EQEMU_EMBPARSER_H +#pragma once + #ifdef EMBPERL -#include "quest_parser_collection.h" -#include "quest_interface.h" -#include -#include +#include "zone/embperl.h" +#include "zone/quest_interface.h" +#include "zone/quest_parser_collection.h" + #include -#include "embperl.h" +#include +#include class Mob; class Client; @@ -309,6 +310,4 @@ class PerlembParser : public QuestInterface { std::map clear_vars_; }; -#endif -#endif - +#endif // EMBPERL diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index b56cb51d84..debe2c43bb 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -16,26 +16,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/features.h" -#include "../common/content/world_content_service.h" -#include "../common/zone_store.h" - #ifdef EMBPERL #ifdef EMBPERL_XS -#include "../common/global_define.h" -#include "../common/misc_functions.h" - -#include "dialogue_window.h" -#include "dynamic_zone.h" -#include "embperl.h" -#include "entity.h" -#include "queryserv.h" -#include "questmgr.h" -#include "zone.h" -#include "../common/data_bucket.h" -#include "../common/events/player_event_logs.h" -#include "worldserver.h" +#include "common/content/world_content_service.h" +#include "common/data_bucket.h" +#include "common/events/player_event_logs.h" +#include "common/features.h" +#include "common/misc_functions.h" +#include "common/zone_store.h" +#include "zone/dialogue_window.h" +#include "zone/dynamic_zone.h" +#include "zone/embperl.h" +#include "zone/entity.h" +#include "zone/queryserv.h" +#include "zone/questmgr.h" +#include "zone/worldserver.h" +#include "zone/zone.h" #include @@ -7059,5 +7056,5 @@ void perl_register_quest() } -#endif -#endif +#endif // EMBPERL_XS +#endif // EMBPERL diff --git a/zone/embperl.cpp b/zone/embperl.cpp index 75bc1793c6..7b960659a1 100644 --- a/zone/embperl.cpp +++ b/zone/embperl.cpp @@ -5,19 +5,16 @@ wraps a perl interpreter for use in eqemu Eglin */ -#ifndef EMBPERL_CPP -#define EMBPERL_CPP - #ifdef EMBPERL -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" +#include "common/eqemu_logsys.h" +#include "common/features.h" +#include "common/file.h" +#include "common/process/process.h" +#include "common/timer.h" +#include "zone/embperl.h" + #include -#include "embperl.h" -#include "../common/features.h" -#include "../common/process/process.h" -#include "../common/file.h" -#include "../common/timer.h" #ifndef GvCV_set #define GvCV_set(gv,cv) (GvCV(gv) = (cv)) @@ -354,8 +351,5 @@ XS(XS_EQEmuIO_PRINT) XSRETURN_EMPTY; } -#endif //EMBPERL_IO_CAPTURE - -#endif //EMBPERL - -#endif //EMBPERL_CPP +#endif // EMBPERL_IO_CAPTURE +#endif // EMBPERL diff --git a/zone/embperl.h b/zone/embperl.h index 0229710594..b47367e165 100644 --- a/zone/embperl.h +++ b/zone/embperl.h @@ -5,20 +5,19 @@ eqemu perl wrapper Eglin */ -#ifndef EMBPERL_H -#define EMBPERL_H +#pragma once #ifdef EMBPERL #include "zone_config.h" +#include "perlbind/perlbind.h" +#include +#include +#include #include #include -#include -#include -#include -#include namespace perl = perlbind; #undef connect @@ -149,6 +148,5 @@ class Embperl //check to see if a sub exists in package bool SubExists(const char* package, const char* sub); }; -#endif //EMBPERL -#endif //EMBPERL_H +#endif // EMBPERL diff --git a/zone/encounter.cpp b/zone/encounter.cpp index fc5586a1d6..f124d3631c 100644 --- a/zone/encounter.cpp +++ b/zone/encounter.cpp @@ -16,19 +16,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifdef _WINDOWS - #if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900)) - #define snprintf _snprintf - #define vsnprintf _vsnprintf - #endif - #define strncasecmp _strnicmp - #define strcasecmp _stricmp -#endif - -#include "../common/races.h" #include "encounter.h" -#include "entity.h" -#include "mob.h" + +#include "common/races.h" +#include "zone/entity.h" +#include "zone/mob.h" class Zone; diff --git a/zone/encounter.h b/zone/encounter.h index b0c6235626..70f0ea8cae 100644 --- a/zone/encounter.h +++ b/zone/encounter.h @@ -16,12 +16,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef ENCOUNTER_H -#define ENCOUNTER_H +#pragma once -#include "mob.h" -#include "../common/types.h" -#include "../common/timer.h" +#include "common/timer.h" +#include "common/types.h" +#include "zone/mob.h" class Group; class Raid; @@ -58,5 +57,3 @@ class Encounter : public Mob private: }; - -#endif diff --git a/zone/entity.cpp b/zone/entity.cpp index 37fa9b4adb..e6586a3253 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -15,41 +15,28 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/data_verification.h" -#include "../common/global_define.h" -#include -#include -#include -#include - -#ifdef _WINDOWS -#else -#include -#include "../common/unix.h" -#endif - -#include "../common/features.h" -#include "../common/guilds.h" #include "entity.h" -#include "dynamic_zone.h" -#include "guild_mgr.h" -#include "petitions.h" -#include "quest_parser_collection.h" -#include "raids.h" -#include "string_ids.h" -#include "worldserver.h" -#include "water_map.h" -#include "npc_scale_manager.h" -#include "dialogue_window.h" -#ifdef _WINDOWS - #define snprintf _snprintf - #define strncasecmp _strnicmp - #define strcasecmp _stricmp -#endif - -#include "bot.h" +#include "common/data_verification.h" +#include "common/features.h" +#include "common/guilds.h" +#include "zone/bot.h" +#include "zone/dialogue_window.h" +#include "zone/dynamic_zone.h" +#include "zone/guild_mgr.h" +#include "zone/npc_scale_manager.h" +#include "zone/petitions.h" +#include "zone/quest_parser_collection.h" +#include "zone/raids.h" +#include "zone/string_ids.h" +#include "zone/water_map.h" +#include "zone/worldserver.h" + +#include +#include +#include +#include extern Zone *zone; extern volatile bool is_zone_loaded; diff --git a/zone/entity.h b/zone/entity.h index 766cd7eda8..05fed5a718 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -15,22 +15,21 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef ENTITY_H -#define ENTITY_H -#include -#include +#pragma once -#include "../common/types.h" -#include "../common/linked_list.h" -#include "../common/servertalk.h" -#include "../common/bodytypes.h" -#include "../common/eq_constants.h" -#include "../common/emu_constants.h" +#include "common/bodytypes.h" +#include "common/emu_constants.h" +#include "common/eq_constants.h" +#include "common/linked_list.h" +#include "common/servertalk.h" +#include "common/types.h" +#include "zone/common.h" +#include "zone/position.h" +#include "zone/zonedump.h" -#include "position.h" -#include "zonedump.h" -#include "common.h" +#include +#include class Encounter; class Beacon; @@ -653,6 +652,3 @@ class BulkZoneSpawnPacket { NewSpawn_Struct* data; Client* pSendTo; }; - -#endif - diff --git a/zone/event_codes.h b/zone/event_codes.h index ff345abff5..09a437f22f 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -1,5 +1,4 @@ -#ifndef EVENT_CODES_H -#define EVENT_CODES_H +#pragma once typedef enum { EVENT_SAY = 0, @@ -156,6 +155,3 @@ typedef enum { } QuestEventID; extern const char *QuestEventSubroutines[_LargestEventID]; - -#endif - diff --git a/zone/exp.cpp b/zone/exp.cpp index 1f64d8b712..fe993f542f 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -16,26 +16,22 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/features.h" -#include "../common/rulesys.h" -#include "../common/strings.h" - -#include "client.h" -#include "../common/data_bucket.h" -#include "groups.h" -#include "mob.h" -#include "raids.h" - -#include "queryserv.h" -#include "quest_parser_collection.h" -#include "lua_parser.h" -#include "string_ids.h" -#include "../common/data_verification.h" - -#include "bot.h" -#include "../common/events/player_event_logs.h" -#include "worldserver.h" +#include "common/data_bucket.h" +#include "common/data_verification.h" +#include "common/events/player_event_logs.h" +#include "common/features.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/groups.h" +#include "zone/lua_parser.h" +#include "zone/mob.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/raids.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/expedition_request.cpp b/zone/expedition_request.cpp index 7c77637303..6c64258673 100644 --- a/zone/expedition_request.cpp +++ b/zone/expedition_request.cpp @@ -19,11 +19,12 @@ */ #include "expedition_request.h" -#include "client.h" -#include "groups.h" -#include "raids.h" -#include "string_ids.h" -#include "../common/repositories/character_expedition_lockouts_repository.h" + +#include "common/repositories/character_expedition_lockouts_repository.h" +#include "zone/client.h" +#include "zone/groups.h" +#include "zone/raids.h" +#include "zone/string_ids.h" ExpeditionRequest::ExpeditionRequest(const DynamicZone& dz, Client& client, bool silent) : m_dz(&dz), m_requester(&client), m_silent(silent) diff --git a/zone/expedition_request.h b/zone/expedition_request.h index 037c43ae3f..8f1493c444 100644 --- a/zone/expedition_request.h +++ b/zone/expedition_request.h @@ -18,11 +18,11 @@ * */ -#ifndef EXPEDITION_REQUEST_H -#define EXPEDITION_REQUEST_H +#pragma once + +#include "common/dynamic_zone_lockout.h" +#include "zone/dynamic_zone.h" -#include "dynamic_zone.h" -#include "../common/dynamic_zone_lockout.h" #include #include #include @@ -67,5 +67,3 @@ class ExpeditionRequest std::vector m_members; std::vector m_lockouts; }; - -#endif diff --git a/zone/fastmath.cpp b/zone/fastmath.cpp index 0da87dc87a..f4140c3169 100644 --- a/zone/fastmath.cpp +++ b/zone/fastmath.cpp @@ -1,9 +1,8 @@ -#if defined(_MSC_VER) -#define _USE_MATH_DEFINES -#endif -#include + #include "fastmath.h" +#include + FastMath g_Math; // This should match EQ's sin/cos LUTs @@ -14,7 +13,7 @@ FastMath::FastMath() int si = 128; float res; do { - res = std::cos(static_cast(ci) * M_PI * 2 / 512); + res = std::cos(static_cast(ci) * std::numbers::pi * 2 / 512); lut_cos[ci] = res; if (si == 512) si = 0; diff --git a/zone/fastmath.h b/zone/fastmath.h index 083198e487..a7ab756820 100644 --- a/zone/fastmath.h +++ b/zone/fastmath.h @@ -1,5 +1,4 @@ -#ifndef FASTMATH_H -#define FASTMATH_H +#pragma once class FastMath { @@ -14,5 +13,3 @@ class FastMath inline float FastCos(float a) { return lut_cos[static_cast(a) & 0x1ff]; } }; - -#endif /* !FASTMATH_H */ diff --git a/zone/fearpath.cpp b/zone/fearpath.cpp index e944b057da..7bd9c6319f 100644 --- a/zone/fearpath.cpp +++ b/zone/fearpath.cpp @@ -16,15 +16,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/rulesys.h" - -#include "map.h" -#include "water_map.h" -#include "zone.h" - -#ifdef _WINDOWS -#define snprintf _snprintf -#endif +#include "common/rulesys.h" +#include "zone/map.h" +#include "zone/water_map.h" +#include "zone/zone.h" extern Zone* zone; diff --git a/zone/forage.cpp b/zone/forage.cpp index 2b5933053b..3bf6689976 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -16,34 +16,31 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/misc_functions.h" -#include "../common/rulesys.h" -#include "../common/strings.h" - -#include "entity.h" #include "forage.h" -#include "npc.h" -#include "quest_parser_collection.h" -#include "string_ids.h" -#include "titles.h" -#include "water_map.h" -#include "zonedb.h" -#include "../common/repositories/criteria/content_filter_criteria.h" -#include "../common/repositories/forage_repository.h" -#include "../common/repositories/fishing_repository.h" -#include "../common/events/player_event_logs.h" -#include "worldserver.h" -#include "queryserv.h" + +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/misc_functions.h" +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/fishing_repository.h" +#include "common/repositories/forage_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "zone/entity.h" +#include "zone/npc.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/titles.h" +#include "zone/water_map.h" +#include "zone/worldserver.h" +#include "zone/zonedb.h" + +#include extern WorldServer worldserver; extern QueryServ *QServ; -#ifdef _WINDOWS -#define snprintf _snprintf -#endif - struct NPCType; //max number of items which can be in the foraging @@ -218,8 +215,8 @@ bool Client::CanFish() { HeadingDegrees = (int) ((GetHeading()*360)/512); HeadingDegrees = HeadingDegrees % 360; - rodPosition.x = m_Position.x + RodLength * sin(HeadingDegrees * M_PI/180.0f); - rodPosition.y = m_Position.y + RodLength * cos(HeadingDegrees * M_PI/180.0f); + rodPosition.x = m_Position.x + RodLength * sin(HeadingDegrees * std::numbers::pi / 180.0f); + rodPosition.y = m_Position.y + RodLength * cos(HeadingDegrees * std::numbers::pi / 180.0f); rodPosition.z = m_Position.z; float bestz = zone->zonemap->FindBestZ(rodPosition, nullptr); diff --git a/zone/forage.h b/zone/forage.h index c2f852fd86..4140c02816 100644 --- a/zone/forage.h +++ b/zone/forage.h @@ -16,11 +16,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef FORAGE_H -#define FORAGE_H -#include "../common/types.h" +#pragma once + +#include "common/types.h" #define MAX_COMMON_FOOD_IDS 8 #define MAX_COMMON_FISH_IDS 9 - -#endif diff --git a/zone/global_loot_manager.cpp b/zone/global_loot_manager.cpp index e9c63598fe..74e8c15493 100644 --- a/zone/global_loot_manager.cpp +++ b/zone/global_loot_manager.cpp @@ -1,8 +1,9 @@ #include "global_loot_manager.h" -#include "npc.h" -#include "client.h" -#include "zone.h" -#include "dialogue_window.h" + +#include "zone/client.h" +#include "zone/dialogue_window.h" +#include "zone/npc.h" +#include "zone/zone.h" extern Zone *zone; diff --git a/zone/global_loot_manager.h b/zone/global_loot_manager.h index 1de6e78316..8ee5dd3822 100644 --- a/zone/global_loot_manager.h +++ b/zone/global_loot_manager.h @@ -1,5 +1,4 @@ -#ifndef GLOBAL_LOOT_MANAGER_H -#define GLOBAL_LOOT_MANAGER_H +#pragma once #include #include @@ -58,5 +57,3 @@ class GlobalLootManager { void ShowZoneGlobalLoot(Client *to) const; void ShowNPCGlobalLoot(Client *to, NPC *who) const; }; - -#endif /* !GLOBAL_LOOT_MANAGER_H */ diff --git a/zone/groups.cpp b/zone/groups.cpp index b70f44f18e..b0a297a559 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -16,17 +16,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "dynamic_zone.h" -#include "masterentity.h" -#include "worldserver.h" -#include "string_ids.h" -#include "../common/events/player_event_logs.h" -#include "../common/repositories/character_expedition_lockouts_repository.h" -#include "../common/repositories/group_id_repository.h" -#include "../common/repositories/group_leaders_repository.h" -#include "queryserv.h" +#include "groups.h" + +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/repositories/character_expedition_lockouts_repository.h" +#include "common/repositories/group_id_repository.h" +#include "common/repositories/group_leaders_repository.h" +#include "zone/dynamic_zone.h" +#include "zone/masterentity.h" +#include "zone/queryserv.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" extern EntityList entity_list; diff --git a/zone/groups.h b/zone/groups.h index 8c312f6efd..b51223f252 100644 --- a/zone/groups.h +++ b/zone/groups.h @@ -15,14 +15,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef GROUPS_H -#define GROUPS_H -#include "../common/eq_packet_structs.h" -#include "../common/types.h" +#pragma once -#include "mob.h" -#include "xtargetautohaters.h" +#include "common/eq_packet_structs.h" +#include "common/types.h" +#include "zone/mob.h" +#include "zone/xtargetautohaters.h" class Client; class EQApplicationPacket; @@ -195,5 +194,3 @@ class Group : public GroupIDConsumer { XTargetAutoHaters m_autohatermgr; }; - -#endif diff --git a/zone/guild.cpp b/zone/guild.cpp index 9c48b5e3e3..8b1e1bbe5d 100644 --- a/zone/guild.cpp +++ b/zone/guild.cpp @@ -16,12 +16,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/database.h" -#include "../common/guilds.h" -#include "../common/strings.h" +#include "client.h" -#include "guild_mgr.h" -#include "worldserver.h" +#include "common/database.h" +#include "common/guilds.h" +#include "common/strings.h" +#include "zone/guild_mgr.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index aa2d9fd708..d13d04c1a0 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -17,15 +17,16 @@ */ #include "guild_mgr.h" -#include "../common/emu_versions.h" -#include "../common/repositories/guild_bank_repository.h" -#include "../common/repositories/guild_ranks_repository.h" -#include "../common/servertalk.h" -#include "../common/strings.h" -#include "client.h" -#include "string_ids.h" -#include "worldserver.h" -#include "zonedb.h" + +#include "common/emu_versions.h" +#include "common/repositories/guild_bank_repository.h" +#include "common/repositories/guild_ranks_repository.h" +#include "common/servertalk.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" +#include "zone/zonedb.h" ZoneGuildManager guild_mgr; diff --git a/zone/guild_mgr.h b/zone/guild_mgr.h index 0b59bd1f6c..c552ce194c 100644 --- a/zone/guild_mgr.h +++ b/zone/guild_mgr.h @@ -1,13 +1,12 @@ -#ifndef GUILD_MGR_H_ -#define GUILD_MGR_H_ +#pragma once + +#include "common/guild_base.h" +#include "common/repositories/guild_bank_repository.h" +#include "common/types.h" +#include "zone/petitions.h" #include #include -#include "../common/guild_base.h" -#include "../common/types.h" - -#include "../common/repositories/guild_bank_repository.h" -#include "../zone/petitions.h" //extern GuildRanks_Struct guilds[512]; //extern ZoneDatabase database; @@ -141,6 +140,3 @@ class GuildBankManager extern ZoneGuildManager guild_mgr; extern GuildBankManager *GuildBanks; - -#endif /*GUILD_MGR_H_*/ - diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 59f0aeb8df..d152d838ec 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -16,18 +16,17 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "client.h" -#include "entity.h" -#include "groups.h" -#include "mob.h" -#include "raids.h" - -#include "../common/data_verification.h" - #include "hate_list.h" -#include "quest_parser_collection.h" -#include "zone.h" -#include "water_map.h" + +#include "common/data_verification.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/groups.h" +#include "zone/mob.h" +#include "zone/quest_parser_collection.h" +#include "zone/raids.h" +#include "zone/water_map.h" +#include "zone/zone.h" #include diff --git a/zone/hate_list.h b/zone/hate_list.h index ef3dcfbbf3..32eea7cb5c 100644 --- a/zone/hate_list.h +++ b/zone/hate_list.h @@ -16,10 +16,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef HATELIST_H -#define HATELIST_H +#pragma once -#include "../common/emu_constants.h" +#include "common/emu_constants.h" +#include "common/types.h" + +#include class Client; class Group; @@ -102,6 +104,3 @@ class HateList { std::list list; Mob *hate_owner; }; - -#endif - diff --git a/zone/heal_rotation.cpp b/zone/heal_rotation.cpp index 66793c580e..fdb5bd7a80 100644 --- a/zone/heal_rotation.cpp +++ b/zone/heal_rotation.cpp @@ -16,7 +16,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "bot.h" +#include "heal_rotation.h" + +#include "zone/bot.h" #define SAFE_HP_RATIO_CLOTH 95.0f #define SAFE_HP_RATIO_LEATHER 90.0f diff --git a/zone/heal_rotation.h b/zone/heal_rotation.h index 888e45edbf..1773a042bc 100644 --- a/zone/heal_rotation.h +++ b/zone/heal_rotation.h @@ -16,11 +16,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#pragma once -#ifndef HEAL_ROTATION_H -#define HEAL_ROTATION_H - -#include "mob.h" +#include "zone/mob.h" #define CASTING_CYCLE_MINIMUM_INTERVAL 1000 #define CASTING_CYCLE_MINIMUM_INTERVAL_S 1 @@ -157,5 +155,3 @@ class HealRotation bool IsHealRotationMemberClass(uint8 class_id); bool IsHealRotationTargetMobType(Mob* target_mob); - -#endif diff --git a/zone/horse.cpp b/zone/horse.cpp index c705a7c047..a59d7c83ba 100644 --- a/zone/horse.cpp +++ b/zone/horse.cpp @@ -16,18 +16,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/linked_list.h" -#include "../common/strings.h" - -#include "../common/repositories/horses_repository.h" - -#include "client.h" -#include "entity.h" #include "horse.h" -#include "mob.h" -#include "string_ids.h" + +#include "common/eqemu_logsys.h" +#include "common/linked_list.h" +#include "common/repositories/horses_repository.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/mob.h" +#include "zone/string_ids.h" std::map Horse::horse_types; diff --git a/zone/horse.h b/zone/horse.h index 8c8a37df56..b458b261eb 100644 --- a/zone/horse.h +++ b/zone/horse.h @@ -15,11 +15,12 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef HORSES_H -#define HORSES_H -#include "npc.h" +#pragma once +#include "zone/npc.h" + +#include "glm/vec4.hpp" #include class Client; @@ -41,5 +42,3 @@ class Horse : public NPC { static const NPCType* GetHorseType(uint16 spell_id); static const NPCType* BuildHorseType(uint16 spell_id); }; - -#endif diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 847368d1b8..812d09aba4 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -16,18 +16,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" - -#include "../common/strings.h" -#include "quest_parser_collection.h" -#include "worldserver.h" -#include "zonedb.h" -#include "../common/events/player_event_logs.h" -#include "bot.h" -#include "../common/evolving_items.h" -#include "../common/repositories/character_corpse_items_repository.h" -#include "queryserv.h" +#include "client.h" + +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/evolving_items.h" +#include "common/repositories/character_corpse_items_repository.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/worldserver.h" +#include "zone/zonedb.h" extern WorldServer worldserver; extern QueryServ *QServ; diff --git a/zone/loot.cpp b/zone/loot.cpp index c93151bff0..519bf97c75 100644 --- a/zone/loot.cpp +++ b/zone/loot.cpp @@ -1,20 +1,15 @@ -#include "../common/global_define.h" -#include "../common/data_verification.h" - -#include "../common/loot.h" -#include "client.h" -#include "entity.h" -#include "mob.h" #include "npc.h" -#include "zonedb.h" -#include "global_loot_manager.h" -#include "../common/repositories/criteria/content_filter_criteria.h" -#include "../common/repositories/global_loot_repository.h" -#include "quest_parser_collection.h" - -#ifdef _WINDOWS -#define snprintf _snprintf -#endif + +#include "common/data_verification.h" +#include "common/loot.h" +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/global_loot_repository.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/global_loot_manager.h" +#include "zone/mob.h" +#include "zone/quest_parser_collection.h" +#include "zone/zonedb.h" void NPC::AddLootTable(uint32 loottable_id, bool is_global) { diff --git a/zone/lua_bit.cpp b/zone/lua_bit.cpp index b923d534d1..5c8af6fcc1 100644 --- a/zone/lua_bit.cpp +++ b/zone/lua_bit.cpp @@ -30,7 +30,7 @@ #define LUA_BITOP_VERSION "1.0.2" #include "lua.hpp" -#include +#include typedef int32_t SBits; typedef uint32_t UBits; diff --git a/zone/lua_bit.h b/zone/lua_bit.h index 67cd659ba6..50023e6efe 100644 --- a/zone/lua_bit.h +++ b/zone/lua_bit.h @@ -1,6 +1,3 @@ -#ifndef _LUABIT_H -#define _LUABIT_H +#pragma once int luaopen_bit(lua_State *L); - -#endif diff --git a/zone/lua_bot.cpp b/zone/lua_bot.cpp index 1e537d76a1..221beb33bb 100644 --- a/zone/lua_bot.cpp +++ b/zone/lua_bot.cpp @@ -1,14 +1,15 @@ #ifdef LUA_EQEMU -#include "lua.hpp" -#include - -#include "bot.h" #include "lua_bot.h" -#include "lua_iteminst.h" -#include "lua_mob.h" -#include "lua_group.h" -#include "lua_item.h" + +#include "zone/bot.h" +#include "zone/lua_iteminst.h" +#include "zone/lua_mob.h" +#include "zone/lua_group.h" +#include "zone/lua_item.h" + +#include "lua.hpp" +#include "luabind/luabind.hpp" void Lua_Bot::AddBotItem(uint16 slot_id, uint32 item_id) { Lua_Safe_Call_Void(); @@ -790,4 +791,4 @@ luabind::scope lua_register_bot() { .def("Stand", (void(Lua_Bot::*)(void))&Lua_Bot::Stand); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_bot.h b/zone/lua_bot.h index 86e3ca28bf..fb678533b1 100644 --- a/zone/lua_bot.h +++ b/zone/lua_bot.h @@ -1,9 +1,8 @@ -\ -#ifndef EQEMU_LUA_BOT_H -#define EQEMU_LUA_BOT_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_mob.h" +#include "zone/lua_mob.h" class Bot; class Lua_Bot; @@ -162,5 +161,4 @@ class Lua_Bot : public Lua_Mob void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_buff.cpp b/zone/lua_buff.cpp index 5873b9493a..7dba2550c6 100644 --- a/zone/lua_buff.cpp +++ b/zone/lua_buff.cpp @@ -1,11 +1,11 @@ #ifdef LUA_EQEMU -#include "lua.hpp" -#include -#include - #include "lua_buff.h" +#include "lua.hpp" +#include "luabind/iterator_policy.hpp" +#include "luabind/luabind.hpp" + uint16 Lua_Buff::GetCasterID() { Lua_Safe_Call_Int(); @@ -151,4 +151,4 @@ luabind::scope lua_register_buff() { .def("SendsClientUpdate", &Lua_Buff::SendsClientUpdate); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_buff.h b/zone/lua_buff.h index f94d09b7ec..03c9744d68 100644 --- a/zone/lua_buff.h +++ b/zone/lua_buff.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LUA_BUFF_H -#define EQEMU_LUA_BUFF_H +#pragma once + #ifdef LUA_EQEMU -#include "common.h" -#include "lua_ptr.h" +#include "zone/common.h" +#include "zone/lua_ptr.h" struct Buffs_Struct; @@ -47,5 +47,4 @@ class Lua_Buff : public Lua_Ptr bool SendsClientUpdate(); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 15ec526b64..0d917f3823 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1,22 +1,23 @@ #ifdef LUA_EQEMU -#include "lua.hpp" -#include - -#include "client.h" -#include "dynamic_zone.h" -#include "expedition_request.h" #include "lua_client.h" -#include "lua_expedition.h" -#include "lua_npc.h" -#include "lua_item.h" -#include "lua_iteminst.h" -#include "lua_inventory.h" -#include "lua_group.h" -#include "lua_raid.h" -#include "lua_packet.h" -#include "dialogue_window.h" -#include "titles.h" + +#include "zone/client.h" +#include "zone/dialogue_window.h" +#include "zone/dynamic_zone.h" +#include "zone/expedition_request.h" +#include "zone/lua_expedition.h" +#include "zone/lua_group.h" +#include "zone/lua_inventory.h" +#include "zone/lua_item.h" +#include "zone/lua_iteminst.h" +#include "zone/lua_npc.h" +#include "zone/lua_packet.h" +#include "zone/lua_raid.h" +#include "zone/titles.h" + +#include "lua.hpp" +#include "luabind/luabind.hpp" struct InventoryWhere { }; @@ -4241,6 +4242,4 @@ luabind::scope lua_register_inventory_where() { )]; } - - -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_client.h b/zone/lua_client.h index c85c061b67..0fcb6dde6e 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_CLIENT_H -#define EQEMU_LUA_CLIENT_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_mob.h" +#include "zone/lua_mob.h" class Client; class Lua_Expedition; @@ -649,5 +649,4 @@ class Lua_Client : public Lua_Mob void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clip_through_walls); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_corpse.cpp b/zone/lua_corpse.cpp index 2db6bad074..4997dd731b 100644 --- a/zone/lua_corpse.cpp +++ b/zone/lua_corpse.cpp @@ -1,12 +1,13 @@ #ifdef LUA_EQEMU -#include "lua.hpp" -#include -#include - -#include "corpse.h" #include "lua_corpse.h" -#include "lua_client.h" + +#include "zone/corpse.h" +#include "zone/lua_client.h" + +#include "lua.hpp" +#include "luabind/iterator_policy.hpp" +#include "luabind/luabind.hpp" struct Lua_Corpse_Loot_List { std::vector entries; @@ -266,4 +267,4 @@ luabind::scope lua_register_corpse_loot_list() { .def_readwrite("entries", &Lua_Corpse_Loot_List::entries, luabind::return_stl_iterator); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_corpse.h b/zone/lua_corpse.h index 58bfb7d056..66fee476a7 100644 --- a/zone/lua_corpse.h +++ b/zone/lua_corpse.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_CORPSE_H -#define EQEMU_LUA_CORPSE_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_mob.h" +#include "zone/lua_mob.h" class Corpse; class Lua_Client; @@ -68,5 +68,4 @@ class Lua_Corpse : public Lua_Mob Lua_Corpse_Loot_List GetLootList(lua_State* L); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_database.cpp b/zone/lua_database.cpp index aa2a5bea4b..796e36a7f2 100644 --- a/zone/lua_database.cpp +++ b/zone/lua_database.cpp @@ -1,9 +1,11 @@ #ifdef LUA_EQEMU #include "lua_database.h" -#include "zonedb.h" -#include -#include + +#include "zone/zonedb.h" + +#include "luabind/adopt_policy.hpp" +#include "luabind/luabind.hpp" // Luabind adopts the PreparedStmt wrapper object allocated with new and deletes it via GC // Lua GC is non-deterministic so handles should be closed explicitly to free db resources diff --git a/zone/lua_database.h b/zone/lua_database.h index ca81f67cdc..ccfa28b6c6 100644 --- a/zone/lua_database.h +++ b/zone/lua_database.h @@ -2,9 +2,10 @@ #ifdef LUA_EQEMU -#include "quest_db.h" -#include "../common/mysql_stmt.h" -#include +#include "common/mysql_stmt.h" +#include "zone/quest_db.h" + +#include "luabind/object.hpp" namespace luabind { struct scope; } luabind::scope lua_register_database(); diff --git a/zone/lua_door.cpp b/zone/lua_door.cpp index 91fd55316b..71d4df2f0c 100644 --- a/zone/lua_door.cpp +++ b/zone/lua_door.cpp @@ -1,12 +1,14 @@ #ifdef LUA_EQEMU -#include -#include - -#include "doors.h" -#include "lua_mob.h" #include "lua_door.h" +#include "zone/doors.h" +#include "zone/lua_mob.h" + +#include "luabind/luabind.hpp" +#include "luabind/object.hpp" + + void Lua_Door::SetDoorName(const char *name) { Lua_Safe_Call_Void(); self->SetDoorName(name); diff --git a/zone/lua_door.h b/zone/lua_door.h index a1a80eec6f..51b7900f50 100644 --- a/zone/lua_door.h +++ b/zone/lua_door.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_DOOR_H -#define EQEMU_LUA_DOOR_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_entity.h" +#include "zone/lua_entity.h" class Doors; class Lua_Mob; @@ -83,5 +83,4 @@ class Lua_Door : public Lua_Entity uint32 GetGuildID(); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_encounter.cpp b/zone/lua_encounter.cpp index 06e2f1d489..fb06784369 100644 --- a/zone/lua_encounter.cpp +++ b/zone/lua_encounter.cpp @@ -1,12 +1,13 @@ #ifdef LUA_EQEMU -#include #include "lua_encounter.h" -#include "encounter.h" +#include "zone/encounter.h" + +#include "luabind/luabind.hpp" luabind::scope lua_register_encounter() { return luabind::class_("Encounter"); } -#endif \ No newline at end of file +#endif // LUA_EQEMU \ No newline at end of file diff --git a/zone/lua_encounter.h b/zone/lua_encounter.h index f3d4598f78..07a8f65cb8 100644 --- a/zone/lua_encounter.h +++ b/zone/lua_encounter.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_ENCOUNTER_H -#define EQEMU_LUA_ENCOUNTER_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_ptr.h" +#include "zone/lua_ptr.h" class Encounter; @@ -28,5 +28,5 @@ class Lua_Encounter : public Lua_Ptr } }; -#endif -#endif + +#endif // LUA_EQEMU diff --git a/zone/lua_entity.cpp b/zone/lua_entity.cpp index 18ffdee2a5..660a04a1af 100644 --- a/zone/lua_entity.cpp +++ b/zone/lua_entity.cpp @@ -1,18 +1,18 @@ #ifdef LUA_EQEMU -#include - -#include "entity.h" #include "lua_entity.h" -#include "lua_mob.h" -#include "lua_client.h" -#include "lua_npc.h" -#include "lua_corpse.h" -#include "lua_object.h" -#include "lua_door.h" - -#include "lua_bot.h" -#include "lua_merc.h" + +#include "zone/entity.h" +#include "zone/lua_bot.h" +#include "zone/lua_client.h" +#include "zone/lua_corpse.h" +#include "zone/lua_door.h" +#include "zone/lua_merc.h" +#include "zone/lua_mob.h" +#include "zone/lua_npc.h" +#include "zone/lua_object.h" + +#include "luabind/luabind.hpp" bool Lua_Entity::IsClient() { Lua_Safe_Call_Bool(); diff --git a/zone/lua_entity.h b/zone/lua_entity.h index 3ac07a2e32..dbf60a1785 100644 --- a/zone/lua_entity.h +++ b/zone/lua_entity.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_ENTITY_H -#define EQEMU_LUA_ENTITY_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_ptr.h" +#include "zone/lua_ptr.h" class Entity; class Lua_Client; @@ -63,5 +63,4 @@ class Lua_Entity : public Lua_Ptr Lua_Merc CastToMerc(); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_entity_list.cpp b/zone/lua_entity_list.cpp index 4b99c869ec..ff6d8ca73c 100644 --- a/zone/lua_entity_list.cpp +++ b/zone/lua_entity_list.cpp @@ -1,22 +1,22 @@ #ifdef LUA_EQEMU -#include -#include - -#include "masterentity.h" #include "lua_entity_list.h" -#include "lua_mob.h" -#include "lua_client.h" -#include "lua_npc.h" -#include "lua_object.h" -#include "lua_door.h" -#include "lua_corpse.h" -#include "lua_group.h" -#include "lua_raid.h" -#include "lua_spawn.h" - -#include "lua_bot.h" -#include "lua_merc.h" + +#include "zone/lua_bot.h" +#include "zone/lua_client.h" +#include "zone/lua_corpse.h" +#include "zone/lua_door.h" +#include "zone/lua_group.h" +#include "zone/lua_merc.h" +#include "zone/lua_mob.h" +#include "zone/lua_npc.h" +#include "zone/lua_object.h" +#include "zone/lua_raid.h" +#include "zone/lua_spawn.h" +#include "zone/masterentity.h" + +#include "luabind/luabind.hpp" +#include "luabind/iterator_policy.hpp" struct Lua_Mob_List { std::vector entries; diff --git a/zone/lua_entity_list.h b/zone/lua_entity_list.h index ad4f0fbd5c..f1d9c596e2 100644 --- a/zone/lua_entity_list.h +++ b/zone/lua_entity_list.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_ENTITY_LIST_H -#define EQEMU_LUA_ENTITY_LIST_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_ptr.h" +#include "zone/lua_ptr.h" class EntityList; class Lua_Mob; @@ -161,5 +161,4 @@ class Lua_EntityList : public Lua_Ptr Lua_NPC_List GetNPCsByExcludedIDs(luabind::adl::object npc_ids); }; -#endif -#endif +#endif // LUA_EQEMU \ No newline at end of file diff --git a/zone/lua_expedition.cpp b/zone/lua_expedition.cpp index 41554b41e6..bdb17e3bc4 100644 --- a/zone/lua_expedition.cpp +++ b/zone/lua_expedition.cpp @@ -1,11 +1,13 @@ #ifdef LUA_EQEMU #include "lua_expedition.h" -#include "dynamic_zone.h" -#include "../common/zone_store.h" + +#include "common/zone_store.h" +#include "zone/dynamic_zone.h" + #include "lua.hpp" -#include -#include +#include "luabind/luabind.hpp" +#include "luabind/object.hpp" void Lua_Expedition::AddLockout(std::string event_name, uint32_t seconds) { Lua_Safe_Call_Void(); diff --git a/zone/lua_expedition.h b/zone/lua_expedition.h index f11e3d6d6c..943144f4bc 100644 --- a/zone/lua_expedition.h +++ b/zone/lua_expedition.h @@ -18,12 +18,13 @@ * */ -#ifndef EQEMU_LUA_EXPEDITION_H -#define EQEMU_LUA_EXPEDITION_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_ptr.h" -#include "../common/types.h" +#include "common/types.h" +#include "zone/lua_ptr.h" + #include class DynamicZone; @@ -96,4 +97,3 @@ class Lua_Expedition : public Lua_Ptr }; #endif // LUA_EQEMU -#endif // EQEMU_LUA_EXPEDITION_H diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 73a1e29bae..ff6b021236 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1,35 +1,36 @@ #ifdef LUA_EQEMU -#include "lua.hpp" -#include +#include "lua_general.h" + +#include "common/classes.h" +#include "common/content/world_content_service.h" +#include "common/data_bucket.h" +#include "common/events/player_event_logs.h" +#include "common/rulesys.h" +#include "common/timer.h" +#include "zone/dialogue_window.h" +#include "zone/dynamic_zone.h" +#include "zone/encounter.h" +#include "zone/lua_client.h" +#include "zone/lua_encounter.h" +#include "zone/lua_entity_list.h" +#include "zone/lua_expedition.h" +#include "zone/lua_item.h" +#include "zone/lua_iteminst.h" +#include "zone/lua_npc.h" +#include "zone/lua_spell.h" +#include "zone/lua_zone.h" +#include "zone/qglobals.h" +#include "zone/quest_parser_collection.h" +#include "zone/questmgr.h" +#include "zone/worldserver.h" +#include "zone/zone.h" -#include +#include "lua.hpp" +#include "luabind/luabind.hpp" #include #include - -#include "../common/content/world_content_service.h" -#include "../common/timer.h" -#include "../common/classes.h" -#include "../common/rulesys.h" -#include "lua_item.h" -#include "lua_iteminst.h" -#include "lua_client.h" -#include "lua_npc.h" -#include "lua_entity_list.h" -#include "lua_expedition.h" -#include "lua_spell.h" -#include "lua_zone.h" -#include "quest_parser_collection.h" -#include "questmgr.h" -#include "qglobals.h" -#include "encounter.h" -#include "lua_encounter.h" -#include "../common/data_bucket.h" -#include "dialogue_window.h" -#include "dynamic_zone.h" -#include "../common/events/player_event_logs.h" -#include "worldserver.h" -#include "zone.h" +#include struct Events { }; struct Factions { }; @@ -8082,4 +8083,4 @@ luabind::scope lua_register_exp_source() { )]; } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_general.h b/zone/lua_general.h index 6c195d817f..db9b0f91ab 100644 --- a/zone/lua_general.h +++ b/zone/lua_general.h @@ -1,7 +1,9 @@ -#ifndef EQEMU_LUA_GENERAL_H -#define EQEMU_LUA_GENERAL_H +#pragma once + #ifdef LUA_EQEMU +#include "luabind/luabind.hpp" + luabind::scope lua_register_general(); luabind::scope lua_register_random(); luabind::scope lua_register_events(); @@ -26,5 +28,4 @@ luabind::scope lua_register_journal_speakmode(); luabind::scope lua_register_journal_mode(); luabind::scope lua_register_exp_source(); -#endif -#endif +#endif // LUA_EQEMU \ No newline at end of file diff --git a/zone/lua_group.cpp b/zone/lua_group.cpp index 4bb1f4c4fd..b380c2b76f 100644 --- a/zone/lua_group.cpp +++ b/zone/lua_group.cpp @@ -1,16 +1,16 @@ #ifdef LUA_EQEMU -#include "../common/data_verification.h" +#include "lua_group.h" -#include -#include +#include "common/data_verification.h" +#include "zone/groups.h" +#include "zone/lua_client.h" +#include "zone/lua_mob.h" +#include "zone/lua_npc.h" +#include "zone/masterentity.h" -#include "groups.h" -#include "masterentity.h" -#include "lua_group.h" -#include "lua_mob.h" -#include "lua_client.h" -#include "lua_npc.h" +#include "luabind/luabind.hpp" +#include "luabind/object.hpp" void Lua_Group::DisbandGroup() { Lua_Safe_Call_Void(); @@ -182,4 +182,4 @@ luabind::scope lua_register_group() { .def("TeleportGroup", (void(Lua_Group::*)(Lua_Mob,uint32,uint32,float,float,float,float))&Lua_Group::TeleportGroup); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_group.h b/zone/lua_group.h index ee4e353bc5..45d4db982d 100644 --- a/zone/lua_group.h +++ b/zone/lua_group.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_GROUP_H -#define EQEMU_LUA_GROUP_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_ptr.h" +#include "zone/lua_ptr.h" class Group; class Lua_Mob; @@ -55,5 +55,4 @@ class Lua_Group : public Lua_Ptr bool DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name, int max_check_count); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_hate_list.cpp b/zone/lua_hate_list.cpp index 4ca52a5b14..b7e4745fbb 100644 --- a/zone/lua_hate_list.cpp +++ b/zone/lua_hate_list.cpp @@ -1,12 +1,13 @@ #ifdef LUA_EQEMU -#include -#include - -#include "masterentity.h" -#include "lua_mob.h" #include "lua_hate_list.h" +#include "zone/lua_mob.h" +#include "zone/masterentity.h" + +#include "luabind/iterator_policy.hpp" +#include "luabind/luabind.hpp" + Lua_Mob Lua_HateEntry::GetEnt() { Lua_Safe_Call_Class(Lua_Mob); return Lua_Mob(self->entity_on_hatelist); @@ -62,4 +63,4 @@ luabind::scope lua_register_hate_list() { .def_readwrite("entries", &Lua_HateList::entries, luabind::return_stl_iterator); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_hate_list.h b/zone/lua_hate_list.h index 036bd775af..590ab016f4 100644 --- a/zone/lua_hate_list.h +++ b/zone/lua_hate_list.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_HATE_LIST_H -#define EQEMU_LUA_HATE_LIST_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_ptr.h" +#include "zone/lua_ptr.h" class Lua_Mob; struct struct_HateList; @@ -33,5 +33,4 @@ struct Lua_HateList std::vector entries; }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_inventory.cpp b/zone/lua_inventory.cpp index 3d464a9152..99b1051f50 100644 --- a/zone/lua_inventory.cpp +++ b/zone/lua_inventory.cpp @@ -1,12 +1,14 @@ #ifdef LUA_EQEMU +#include "lua_inventory.h" + +#include "zone/lua_item.h" +#include "zone/lua_iteminst.h" +#include "zone/masterentity.h" + #include "lua.hpp" -#include +#include "luabind/luabind.hpp" -#include "masterentity.h" -#include "lua_inventory.h" -#include "lua_iteminst.h" -#include "lua_item.h" Lua_ItemInst Lua_Inventory::GetItem(int slot_id) { Lua_Safe_Call_Class(Lua_ItemInst); @@ -237,4 +239,4 @@ luabind::scope lua_register_inventory() { .def("SwapItem", (bool(Lua_Inventory::*)(int,int))&Lua_Inventory::SwapItem); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_inventory.h b/zone/lua_inventory.h index a9c5c8d5e7..2bee12f9df 100644 --- a/zone/lua_inventory.h +++ b/zone/lua_inventory.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_INVENTORY_H -#define EQEMU_LUA_INVENTORY_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_ptr.h" +#include "zone/lua_ptr.h" class Lua_ItemInst; class Lua_Item; @@ -71,5 +71,4 @@ class Lua_Inventory : public Lua_Ptr luabind::object GetAugmentIDsBySlotID(lua_State* L, int16 slot_id); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_item.cpp b/zone/lua_item.cpp index a27eea220e..776b075b80 100644 --- a/zone/lua_item.cpp +++ b/zone/lua_item.cpp @@ -1,10 +1,11 @@ #ifdef LUA_EQEMU -#include - -#include "masterentity.h" #include "lua_item.h" +#include "zone/masterentity.h" + +#include "luabind/luabind.hpp" + Lua_Item::Lua_Item(uint32 item_id) { const EQ::ItemData *t = database.GetItem(item_id); SetLuaPtrData(t); @@ -1089,4 +1090,4 @@ luabind::scope lua_register_item() { .def("Worn_Type", &Lua_Item::GetWorn_Type); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_item.h b/zone/lua_item.h index 5e62d8c80d..a7390b09f7 100644 --- a/zone/lua_item.h +++ b/zone/lua_item.h @@ -1,8 +1,9 @@ -#ifndef EQEMU_LUA_ITEM_H -#define EQEMU_LUA_ITEM_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_ptr.h" +#include "common/types.h" +#include "zone/lua_ptr.h" namespace EQ { @@ -206,5 +207,4 @@ class Lua_Item : public Lua_Ptr const char *GetScrollName(); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_iteminst.cpp b/zone/lua_iteminst.cpp index a911fcee09..4047db7f40 100644 --- a/zone/lua_iteminst.cpp +++ b/zone/lua_iteminst.cpp @@ -1,11 +1,12 @@ #ifdef LUA_EQEMU -#include -#include - -#include "masterentity.h" #include "lua_iteminst.h" -#include "lua_item.h" + +#include "zone/lua_item.h" +#include "zone/masterentity.h" + +#include "luabind/luabind.hpp" +#include "luabind/object.hpp" Lua_ItemInst::Lua_ItemInst(int item_id) { SetLuaPtrData(database.CreateItem(item_id)); diff --git a/zone/lua_iteminst.h b/zone/lua_iteminst.h index 4863780584..a75c657b19 100644 --- a/zone/lua_iteminst.h +++ b/zone/lua_iteminst.h @@ -1,10 +1,10 @@ -#ifndef EQEMU_LUA_ITEMINST_H -#define EQEMU_LUA_ITEMINST_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_ptr.h" +#include "common/types.h" +#include "zone/lua_ptr.h" -// Forward declaration class Lua_Item; namespace EQ @@ -111,5 +111,4 @@ class Lua_ItemInst : public Lua_Ptr bool cloned_; }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_merc.cpp b/zone/lua_merc.cpp index 8e153c19f7..c8437b9c81 100644 --- a/zone/lua_merc.cpp +++ b/zone/lua_merc.cpp @@ -1,15 +1,16 @@ #ifdef LUA_EQEMU -#include "lua.hpp" -#include - -#include "merc.h" -#include "lua_client.h" #include "lua_merc.h" -#include "lua_group.h" -#include "lua_item.h" -#include "lua_iteminst.h" -#include "lua_mob.h" + +#include "zone/lua_client.h" +#include "zone/lua_group.h" +#include "zone/lua_item.h" +#include "zone/lua_iteminst.h" +#include "zone/lua_mob.h" +#include "zone/merc.h" + +#include "lua.hpp" +#include "luabind/luabind.hpp" uint32 Lua_Merc::GetCostFormula() { diff --git a/zone/lua_merc.h b/zone/lua_merc.h index 90a7b3ab8f..9dbee8d997 100644 --- a/zone/lua_merc.h +++ b/zone/lua_merc.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_MERC_H -#define EQEMU_LUA_MERC_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_mob.h" +#include "zone/lua_mob.h" class Merc; class Lua_Group; @@ -60,4 +60,3 @@ class Lua_Merc : public Lua_Mob }; #endif // LUA_EQEMU -#endif // EQEMU_LUA_MERC_H diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index e23eb2d034..8e8108e7ee 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1,21 +1,22 @@ #ifdef LUA_EQEMU -#include "lua.hpp" -#include - -#include "bot.h" -#include "client.h" -#include "dialogue_window.h" -#include "lua_bot.h" -#include "lua_buff.h" -#include "lua_client.h" -#include "lua_hate_list.h" -#include "lua_item.h" -#include "lua_iteminst.h" #include "lua_mob.h" -#include "lua_npc.h" -#include "lua_stat_bonuses.h" -#include "npc.h" + +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" +#include "zone/lua_bot.h" +#include "zone/lua_buff.h" +#include "zone/lua_client.h" +#include "zone/lua_hate_list.h" +#include "zone/lua_item.h" +#include "zone/lua_iteminst.h" +#include "zone/lua_npc.h" +#include "zone/lua_stat_bonuses.h" +#include "zone/npc.h" + +#include "lua.hpp" +#include "luabind/luabind.hpp" struct SpecialAbilities { }; diff --git a/zone/lua_mob.h b/zone/lua_mob.h index b5019aa5f6..46b28cf8c2 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -1,8 +1,9 @@ -#ifndef EQEMU_LUA_MOB_H -#define EQEMU_LUA_MOB_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_entity.h" +#include "common/types.h" +#include "zone/lua_entity.h" class Mob; struct Lua_HateList; @@ -619,5 +620,4 @@ class Lua_Mob : public Lua_Entity void SetPetType(uint8 pet_type); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_mod.cpp b/zone/lua_mod.cpp index f6ee1a7703..3ed6a278e1 100644 --- a/zone/lua_mod.cpp +++ b/zone/lua_mod.cpp @@ -1,29 +1,30 @@ #ifdef LUA_EQEMU -#include "lua.hpp" -#include -#include +#include "lua_mod.h" -#include "../common/spdat.h" -#include "masterentity.h" -#include "zone.h" +#include "common/spdat.h" +#include "zone/masterentity.h" +#include "zone/zone.h" +#include "zone/lua_parser.h" +#include "zone/lua_item.h" +#include "zone/lua_iteminst.h" +#include "zone/lua_mob.h" +#include "zone/lua_hate_list.h" +#include "zone/lua_client.h" +#include "zone/lua_inventory.h" +#include "zone/lua_npc.h" +#include "zone/lua_group.h" +#include "zone/lua_raid.h" +#include "zone/lua_corpse.h" +#include "zone/lua_object.h" +#include "zone/lua_door.h" +#include "zone/lua_packet.h" +#include "zone/lua_stat_bonuses.h" + +#include "lua.hpp" +#include "luabind/luabind.hpp" +#include "luabind/object.hpp" -#include "lua_parser.h" -#include "lua_mod.h" -#include "lua_item.h" -#include "lua_iteminst.h" -#include "lua_mob.h" -#include "lua_hate_list.h" -#include "lua_client.h" -#include "lua_inventory.h" -#include "lua_npc.h" -#include "lua_group.h" -#include "lua_raid.h" -#include "lua_corpse.h" -#include "lua_object.h" -#include "lua_door.h" -#include "lua_packet.h" -#include "lua_stat_bonuses.h" void LuaMod::Init() { @@ -1082,4 +1083,5 @@ void LuaMod::HealDamage(Mob *self, Mob* caster, uint64 value, uint16 spell_id, u lua_pop(L, n); } } -#endif + +#endif // LUA_EQEMU diff --git a/zone/lua_mod.h b/zone/lua_mod.h index 9c8dcd9ea6..b19543c6fc 100644 --- a/zone/lua_mod.h +++ b/zone/lua_mod.h @@ -1,7 +1,8 @@ #pragma once +#include "common/repositories/bug_reports_repository.h" + #include -#include "../common/repositories/bug_reports_repository.h" struct lua_State; diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index b0cd59c49a..d6432af284 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -1,15 +1,16 @@ #ifdef LUA_EQEMU -#include "lua.hpp" -#include -#include - -#include "npc.h" #include "lua_npc.h" -#include "lua_client.h" -#include "lua_item.h" -#include "lua_iteminst.h" -#include "lua_spawn.h" + +#include "zone/lua_client.h" +#include "zone/lua_item.h" +#include "zone/lua_iteminst.h" +#include "zone/lua_spawn.h" +#include "zone/npc.h" + +#include "lua.hpp" +#include "luabind/iterator_policy.hpp" +#include "luabind/luabind.hpp" struct Lua_NPC_Loot_List { std::vector entries; @@ -1131,4 +1132,4 @@ luabind::scope lua_register_npc_loot_list() { .def_readwrite("entries", &Lua_NPC_Loot_List::entries, luabind::return_stl_iterator); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_npc.h b/zone/lua_npc.h index d166ccdffa..7ac11cc368 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_NPC_H -#define EQEMU_LUA_NPC_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_mob.h" +#include "zone/lua_mob.h" class NPC; class Lua_Mob; @@ -204,5 +204,4 @@ class Lua_NPC : public Lua_Mob }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_object.cpp b/zone/lua_object.cpp index bed74f4eb7..e56551f52c 100644 --- a/zone/lua_object.cpp +++ b/zone/lua_object.cpp @@ -1,11 +1,12 @@ #ifdef LUA_EQEMU -#include "lua.hpp" -#include - -#include "object.h" #include "lua_object.h" +#include "zone/object.h" + +#include "lua.hpp" +#include "luabind/luabind.hpp" + void Lua_Object::Depop() { Lua_Safe_Call_Void(); self->Depop(); @@ -247,4 +248,4 @@ luabind::scope lua_register_object() { .def("VarSave", (uint32(Lua_Object::*)(void))&Lua_Object::VarSave); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_object.h b/zone/lua_object.h index 65f5fbe80c..633a3026a9 100644 --- a/zone/lua_object.h +++ b/zone/lua_object.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_OBJECT_H -#define EQEMU_LUA_OBJECT_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_entity.h" +#include "zone/lua_entity.h" class Object; @@ -68,5 +68,4 @@ class Lua_Object : public Lua_Entity bool EntityVariableExists(std::string variable_name); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_packet.cpp b/zone/lua_packet.cpp index c9a20aab2e..9ea64d36c9 100644 --- a/zone/lua_packet.cpp +++ b/zone/lua_packet.cpp @@ -1,11 +1,13 @@ #ifdef LUA_EQEMU -#include -#include - -#include "masterentity.h" #include "lua_packet.h" +#include "zone/masterentity.h" + +#include "luabind/luabind.hpp" +#include "luabind/object.hpp" + + struct Opcodes { }; Lua_Packet::Lua_Packet(int opcode, int size) { diff --git a/zone/lua_packet.h b/zone/lua_packet.h index ede02c81f8..2754652e52 100644 --- a/zone/lua_packet.h +++ b/zone/lua_packet.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_LUA_PACKET_H -#define EQEMU_LUA_PACKET_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_ptr.h" -#include "../common/types.h" +#include "common/types.h" +#include "zone/lua_ptr.h" class EQApplicationPacket; @@ -67,5 +67,5 @@ class Lua_Packet : public Lua_Ptr bool owned_; }; -#endif -#endif +#endif // LUA_EQEMU + diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 00f89e6d62..9a445f5363 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -1,49 +1,48 @@ #ifdef LUA_EQEMU -#include "lua.hpp" -#include -#include +#include "lua_parser.h" + +#include "common/spdat.h" +#include "zone/lua_bit.h" +#include "zone/lua_bot.h" +#include "zone/lua_buff.h" +#include "zone/lua_client.h" +#include "zone/lua_corpse.h" +#include "zone/lua_database.h" +#include "zone/lua_door.h" +#include "zone/lua_encounter.h" +#include "zone/lua_entity_list.h" +#include "zone/lua_entity.h" +#include "zone/lua_expedition.h" +#include "zone/lua_general.h" +#include "zone/lua_group.h" +#include "zone/lua_hate_list.h" +#include "zone/lua_inventory.h" +#include "zone/lua_item.h" +#include "zone/lua_iteminst.h" +#include "zone/lua_merc.h" +#include "zone/lua_mob.h" +#include "zone/lua_npc.h" +#include "zone/lua_object.h" +#include "zone/lua_packet.h" +#include "zone/lua_raid.h" +#include "zone/lua_spawn.h" +#include "zone/lua_spell.h" +#include "zone/lua_stat_bonuses.h" +#include "zone/lua_zone.h" +#include "zone/masterentity.h" +#include "zone/questmgr.h" +#include "zone/zone_config.h" +#include "zone/zone.h" -#include -#include +#include "lua.hpp" +#include "luabind/luabind.hpp" +#include "luabind/object.hpp" +#include +#include +#include #include #include -#include - -#include "../common/spdat.h" -#include "masterentity.h" -#include "questmgr.h" -#include "zone.h" -#include "zone_config.h" - -#include "lua_bit.h" -#include "lua_bot.h" -#include "lua_buff.h" -#include "lua_client.h" -#include "lua_corpse.h" -#include "lua_door.h" -#include "lua_encounter.h" -#include "lua_entity.h" -#include "lua_entity_list.h" -#include "lua_expedition.h" -#include "lua_general.h" -#include "lua_group.h" -#include "lua_hate_list.h" -#include "lua_inventory.h" -#include "lua_item.h" -#include "lua_iteminst.h" -#include "lua_merc.h" -#include "lua_mob.h" -#include "lua_npc.h" -#include "lua_object.h" -#include "lua_packet.h" -#include "lua_parser.h" -#include "lua_raid.h" -#include "lua_spawn.h" -#include "lua_spell.h" -#include "lua_stat_bonuses.h" -#include "lua_database.h" -#include "lua_zone.h" const char *LuaEvents[_LargestEventID] = { "event_say", @@ -2295,4 +2294,4 @@ void LuaParser::LoadGlobalZoneScript(std::string filename) { LoadScript(filename, "global_zone"); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_parser.h b/zone/lua_parser.h index c1bad7088d..bda8161d31 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -1,18 +1,17 @@ -#ifndef _EQE_LUA_PARSER_H -#define _EQE_LUA_PARSER_H +#pragma once + #ifdef LUA_EQEMU -#include "quest_parser_collection.h" -#include "quest_interface.h" -#include +#include "common/repositories/bug_reports_repository.h" +#include "zone/lua_mod.h" +#include "zone/quest_interface.h" +#include "zone/quest_parser_collection.h" +#include "zone/zone_config.h" + +#include #include #include -#include - -#include "zone_config.h" -#include "lua_mod.h" - -#include "../common/repositories/bug_reports_repository.h" +#include extern const ZoneConfig *Config; @@ -360,5 +359,4 @@ class LuaParser : public QuestInterface { ZoneArgumentHandler ZoneArgumentDispatch[_LargestEventID]; }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index 68dd7ca2ab..42d8de0c0e 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -1,28 +1,27 @@ #ifdef LUA_EQEMU -#include -#include "lua.hpp" -#include -#include - -#include "quest_parser_collection.h" -#include "quest_interface.h" - -#include "masterentity.h" -#include "lua_item.h" -#include "lua_iteminst.h" -#include "lua_mob.h" -#include "lua_client.h" -#include "lua_npc.h" -#include "lua_spell.h" -#include "lua_corpse.h" -#include "lua_door.h" -#include "lua_object.h" -#include "lua_packet.h" -#include "lua_encounter.h" -#include "zone.h" #include "lua_parser_events.h" +#include "zone/lua_client.h" +#include "zone/lua_corpse.h" +#include "zone/lua_door.h" +#include "zone/lua_encounter.h" +#include "zone/lua_item.h" +#include "zone/lua_iteminst.h" +#include "zone/lua_mob.h" +#include "zone/lua_npc.h" +#include "zone/lua_object.h" +#include "zone/lua_packet.h" +#include "zone/lua_spell.h" +#include "zone/masterentity.h" +#include "zone/quest_interface.h" +#include "zone/quest_parser_collection.h" +#include "zone/zone.h" + +#include "lua.hpp" +#include "luabind/luabind.hpp" +#include "luabind/object.hpp" + //NPC void handle_npc_event_say( QuestInterface *parse, @@ -3195,4 +3194,4 @@ void handle_zone_timer_stop( lua_setfield(L, -2, "timer"); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_parser_events.h b/zone/lua_parser_events.h index 79135bd6e6..5c718eb1c4 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -1,7 +1,28 @@ -#ifndef _EQE_LUA_PARSER_EVENTS_H -#define _EQE_LUA_PARSER_EVENTS_H +#pragma once + #ifdef LUA_EQEMU +#include "common/types.h" + +#include +#include +#include + +class Bot; +class Client; +class Encounter; +class Merc; +class Mob; +class NPC; +class QuestInterface; +class Zone; +struct lua_State; + +namespace EQ +{ + class ItemInstance; +} + typedef void(*NPCArgumentHandler)(QuestInterface*, lua_State*, NPC*, Mob*, std::string, uint32, std::vector*); typedef void(*PlayerArgumentHandler)(QuestInterface*, lua_State*, Client*, std::string, uint32, std::vector*); typedef void(*ItemArgumentHandler)(QuestInterface*, lua_State*, Client*, EQ::ItemInstance*, Mob*, std::string, uint32, std::vector*); @@ -1434,5 +1455,4 @@ void handle_zone_timer_stop( std::vector *extra_pointers ); -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_ptr.h b/zone/lua_ptr.h index d337059aeb..52ca4c3cad 100644 --- a/zone/lua_ptr.h +++ b/zone/lua_ptr.h @@ -1,7 +1,10 @@ -#ifndef EQEMU_LUA_PTR_H -#define EQEMU_LUA_PTR_H +#pragma once + #ifdef LUA_EQEMU +#include "lua.hpp" +#include "luabind/luabind.hpp" + #ifndef EQEMU_UNSAFE_LUA #define Lua_Safe_Call_Void() if(!d_) { return; } NativeType *self = reinterpret_cast(d_) #define Lua_Safe_Call_Bool() if(!d_) { return false; } NativeType *self = reinterpret_cast(d_) @@ -51,5 +54,4 @@ class Lua_Ptr T *d_; }; -#endif -#endif \ No newline at end of file +#endif // LUA_EQEMU diff --git a/zone/lua_raid.cpp b/zone/lua_raid.cpp index 46290a861d..4c45d46dbc 100644 --- a/zone/lua_raid.cpp +++ b/zone/lua_raid.cpp @@ -1,15 +1,16 @@ #ifdef LUA_EQEMU -#include "../common/data_verification.h" +#include "lua_raid.h" -#include -#include +#include "common/data_verification.h" +#include "zone/lua_client.h" +#include "zone/lua_mob.h" +#include "zone/lua_npc.h" +#include "zone/masterentity.h" + +#include "luabind/luabind.hpp" +#include "luabind/object.hpp" -#include "masterentity.h" -#include "lua_raid.h" -#include "lua_mob.h" -#include "lua_client.h" -#include "lua_npc.h" bool Lua_Raid::IsRaidMember(const char *name) { Lua_Safe_Call_Bool(); @@ -201,4 +202,4 @@ luabind::scope lua_register_raid() { .def("TeleportRaid", (int(Lua_Raid::*)(Lua_Mob,uint32,uint32,float,float,float,float))&Lua_Raid::TeleportRaid); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_raid.h b/zone/lua_raid.h index ca9718a59d..7d32d73899 100644 --- a/zone/lua_raid.h +++ b/zone/lua_raid.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_RAID_H -#define EQEMU_LUA_RAID_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_ptr.h" +#include "zone/lua_ptr.h" class Raid; class Lua_Client; @@ -56,5 +56,4 @@ class Lua_Raid : public Lua_Ptr bool DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name, int max_check_count); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_spawn.cpp b/zone/lua_spawn.cpp index d5d7127575..a0a805e97f 100644 --- a/zone/lua_spawn.cpp +++ b/zone/lua_spawn.cpp @@ -1,11 +1,12 @@ #ifdef LUA_EQEMU -#include - -#include "spawn2.h" -#include "lua_npc.h" #include "lua_spawn.h" +#include "zone/spawn2.h" +#include "zone/lua_npc.h" + +#include "luabind/luabind.hpp" + void Lua_Spawn::LoadGrid() { Lua_Safe_Call_Void(); self->LoadGrid(); @@ -170,4 +171,4 @@ luabind::scope lua_register_spawn() { .def("SpawnGroupID", (uint32(Lua_Spawn::*)(void))&Lua_Spawn::SpawnGroupID); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_spawn.h b/zone/lua_spawn.h index c25bf34f55..bd470ca78d 100644 --- a/zone/lua_spawn.h +++ b/zone/lua_spawn.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_SPAWN_H -#define EQEMU_LUA_SPAWN_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_ptr.h" +#include "zone/lua_ptr.h" class Spawn2; class Lua_NPC; @@ -53,5 +53,4 @@ class Lua_Spawn : public Lua_Ptr uint32 GetKillCount(); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_spell.cpp b/zone/lua_spell.cpp index 6789cfd804..35cbb35f41 100644 --- a/zone/lua_spell.cpp +++ b/zone/lua_spell.cpp @@ -1,10 +1,12 @@ #ifdef LUA_EQEMU -#include - -#include "../common/spdat.h" #include "lua_spell.h" +#include "common/spdat.h" + +#include "luabind/luabind.hpp" + + Lua_Spell::Lua_Spell(int id) { if(IsValidSpell(id)) { SetLuaPtrData(&spells[id]); @@ -581,4 +583,4 @@ luabind::scope lua_register_spell() { .def("ZoneType", &Lua_Spell::GetZoneType); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_spell.h b/zone/lua_spell.h index b9af8a564c..9a91fc420a 100644 --- a/zone/lua_spell.h +++ b/zone/lua_spell.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_LUA_SPELL_H -#define EQEMU_LUA_SPELL_H +#pragma once + #ifdef LUA_EQEMU -#include "lua_ptr.h" +#include "zone/lua_ptr.h" struct SPDat_Spell_Struct; @@ -112,5 +112,4 @@ class Lua_Spell : public Lua_Ptr int GetRank(); }; -#endif -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_stat_bonuses.cpp b/zone/lua_stat_bonuses.cpp index 78374fdef6..db7e844fa4 100644 --- a/zone/lua_stat_bonuses.cpp +++ b/zone/lua_stat_bonuses.cpp @@ -1,10 +1,11 @@ #ifdef LUA_EQEMU -#include "../common/data_verification.h" +#include "lua_stat_bonuses.h" -#include +#include "common/data_verification.h" + +#include "luabind/luabind.hpp" -#include "lua_stat_bonuses.h" int32 Lua_StatBonuses::GetAC() const { Lua_Safe_Call_Int(); @@ -1557,4 +1558,4 @@ luabind::scope lua_register_stat_bonuses() { .def("XPRateMod", &Lua_StatBonuses::GetXPRateMod); } -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_stat_bonuses.h b/zone/lua_stat_bonuses.h index ff4e9f9325..577c260ca4 100644 --- a/zone/lua_stat_bonuses.h +++ b/zone/lua_stat_bonuses.h @@ -2,8 +2,8 @@ #ifdef LUA_EQEMU -#include "lua_ptr.h" -#include "common.h" +#include "zone/common.h" +#include "zone/lua_ptr.h" struct StatBonuses; @@ -284,4 +284,4 @@ class Lua_StatBonuses : public Lua_Ptr int32 GetReduceTradeskillFail(int idx) const; }; -#endif +#endif // LUA_EQEMU diff --git a/zone/lua_zone.cpp b/zone/lua_zone.cpp index 0375716205..58f2e59fa2 100644 --- a/zone/lua_zone.cpp +++ b/zone/lua_zone.cpp @@ -1,11 +1,12 @@ -#include "../common/features.h" -#include "zone.h" +#ifdef LUA_EQEMU - -#include -#include "../common/global_define.h" #include "lua_zone.h" +#include "common/features.h" +#include "zone/zone.h" + +#include "luabind/luabind.hpp" + bool Lua_Zone::BuffTimersSuspended() { Lua_Safe_Call_Bool(); @@ -1012,3 +1013,4 @@ luabind::scope lua_register_zone() { .def("VariableExists", &Lua_Zone::VariableExists); } +#endif // LUA_EQEMU diff --git a/zone/lua_zone.h b/zone/lua_zone.h index 42a1d88418..e6aeb2ba9b 100644 --- a/zone/lua_zone.h +++ b/zone/lua_zone.h @@ -2,10 +2,10 @@ #ifdef LUA_EQEMU -#include "lua_client.h" -#include "lua_ptr.h" -#include "common.h" -#include "zone.h" +#include "zone/common.h" +#include "zone/lua_client.h" +#include "zone/lua_ptr.h" +#include "zone/zone.h" class Lua_Zone; @@ -171,4 +171,4 @@ class Lua_Zone : public Lua_Ptr }; -#endif +#endif // LUA_EQEMU diff --git a/zone/main.cpp b/zone/main.cpp index 4f5916078e..e6be02f903 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -18,63 +18,57 @@ * */ -#define DONT_SHARED_OPCODES -#define PLATFORM_ZONE 1 - -#include "../common/global_define.h" -#include "../common/timer.h" -#include "../common/eq_packet_structs.h" -#include "../common/mutex.h" -#include "../common/opcodemgr.h" -#include "../common/guilds.h" -#include "../common/eq_stream_ident.h" -#include "../common/patches/patches.h" -#include "../common/rulesys.h" -#include "../common/profanity_manager.h" -#include "../common/strings.h" -#include "../common/crash.h" -#include "../common/memory_mapped_file.h" -#include "../common/spdat.h" -#include "../common/eqemu_logsys.h" -#include "../common/misc.h" - -#include "api_service.h" -#include "zone_config.h" -#include "masterentity.h" -#include "worldserver.h" -#include "zone.h" -#include "queryserv.h" -#include "command.h" -#include "bot_command.h" -#include "zonedb.h" -#include "titles.h" -#include "guild_mgr.h" -#include "task_manager.h" -#include "quest_parser_collection.h" -#include "embparser.h" -#include "../common/evolving_items.h" -#include "lua_parser.h" -#include "questmgr.h" -#include "npc_scale_manager.h" - -#include "../common/net/eqstream.h" - -#include +#include "common/crash.h" +#include "common/database/database_update.h" +#include "common/eq_packet_structs.h" +#include "common/eq_stream_ident.h" +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/evolving_items.h" +#include "common/file.h" +#include "common/guilds.h" +#include "common/memory_mapped_file.h" +#include "common/misc.h" +#include "common/mutex.h" +#include "common/net/eqstream.h" +#include "common/opcodemgr.h" +#include "common/patches/patches.h" +#include "common/path_manager.h" +#include "common/platform/posix/include_pthreads.h" +#include "common/profanity_manager.h" +#include "common/rulesys.h" +#include "common/skill_caps.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "common/timer.h" +#include "zone/api_service.h" +#include "zone/bot_command.h" +#include "zone/command.h" +#include "zone/embparser.h" +#include "zone/guild_mgr.h" +#include "zone/lua_parser.h" +#include "zone/masterentity.h" +#include "zone/npc_scale_manager.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/questmgr.h" +#include "zone/task_manager.h" +#include "zone/titles.h" +#include "zone/worldserver.h" +#include "zone/zone_cli.h" +#include "zone/zone_config.h" +#include "zone/zone_event_scheduler.h" +#include "zone/zone.h" +#include "zone/zonedb.h" + #include +#include #ifdef _CRTDBG_MAP_ALLOC #undef new #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) #endif -#ifdef _WINDOWS -#else - -#include -#include "../common/unix.h" - -#endif - volatile bool RunLoops = true; #ifdef __FreeBSD__ #include @@ -82,14 +76,6 @@ volatile bool RunLoops = true; extern volatile bool is_zone_loaded; -#include "zone_event_scheduler.h" -#include "../common/file.h" -#include "../common/events/player_event_logs.h" -#include "../common/path_manager.h" -#include "../common/database/database_update.h" -#include "../common/skill_caps.h" -#include "zone_cli.h" - EntityList entity_list; WorldServer worldserver; uint32 numclients = 0; diff --git a/zone/map.cpp b/zone/map.cpp index bf6ff68ecc..b91475fa4e 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -1,13 +1,11 @@ -#include "../common/global_define.h" -#include "../common/misc_functions.h" -#include "../common/compression.h" - -#include "client.h" -#include "map.h" -#include "raycast_mesh.h" -#include "zone.h" -#include "../common/file.h" -#include "../common/memory/ksm.hpp" +#include "common/compression.h" +#include "common/file.h" +#include "common/memory/ksm.hpp" +#include "common/misc_functions.h" +#include "zone/client.h" +#include "zone/map.h" +#include "zone/raycast_mesh.h" +#include "zone/zone.h" #include #include diff --git a/zone/map.h b/zone/map.h index 20fad6e95d..d19b4ec7cf 100644 --- a/zone/map.h +++ b/zone/map.h @@ -19,13 +19,12 @@ */ -#ifndef ZONE_MAP_H -#define ZONE_MAP_H +#pragma once -#include "position.h" -#include +#include "zone/position.h" +#include "zone/zone_config.h" -#include "zone_config.h" +#include #define BEST_Z_INVALID -99999 @@ -68,5 +67,3 @@ class Map struct impl; impl *imp; }; - -#endif diff --git a/zone/masterentity.h b/zone/masterentity.h index bdfa23b104..1e1981423b 100644 --- a/zone/masterentity.h +++ b/zone/masterentity.h @@ -1,16 +1,15 @@ //Trumpcard: EntityLists are composed of multiple list types. This is the //master that includes all types. When entity.h is required, many of these are as well. -#include "entity.h" -#include "groups.h" -#include "raids.h" -#include "client.h" -#include "object.h" -#include "corpse.h" -#include "doors.h" -#include "mob.h" -#include "trap.h" -#include "beacon.h" -#include "horse.h" - -#include "bot.h" +#include "zone/beacon.h" +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/corpse.h" +#include "zone/doors.h" +#include "zone/entity.h" +#include "zone/groups.h" +#include "zone/horse.h" +#include "zone/mob.h" +#include "zone/object.h" +#include "zone/raids.h" +#include "zone/trap.h" diff --git a/zone/merc.cpp b/zone/merc.cpp index c29faff18a..587f09fcf2 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1,15 +1,14 @@ - #include "merc.h" -#include "client.h" -#include "corpse.h" -#include "entity.h" -#include "groups.h" -#include "mob.h" -#include "quest_parser_collection.h" - -#include "zone.h" -#include "string_ids.h" -#include "../common/skill_caps.h" + +#include "common/skill_caps.h" +#include "zone/client.h" +#include "zone/corpse.h" +#include "zone/entity.h" +#include "zone/groups.h" +#include "zone/mob.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/zone.h" extern volatile bool is_zone_loaded; diff --git a/zone/merc.h b/zone/merc.h index 028b082997..ed5f98fed2 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -1,7 +1,6 @@ -#ifndef MERC_H -#define MERC_H +#pragma once -#include "npc.h" +#include "zone/npc.h" class Client; class Corpse; @@ -384,5 +383,3 @@ class Merc : public NPC { Timer confidence_timer; Timer check_target_timer; }; - -#endif // MERC_H diff --git a/zone/mob.cpp b/zone/mob.cpp index 69d1ce8269..9c60ff30ed 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -16,28 +16,27 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/data_verification.h" -#include "../common/spdat.h" -#include "../common/strings.h" -#include "../common/misc_functions.h" - -#include "../common/repositories/bot_data_repository.h" -#include "../common/repositories/character_data_repository.h" - -#include "../common/data_bucket.h" -#include "quest_parser_collection.h" -#include "string_ids.h" -#include "worldserver.h" -#include "mob_movement_manager.h" -#include "water_map.h" -#include "dialogue_window.h" - -#include -#include -#include -#include +#include "mob.h" + +#include "common/data_bucket.h" +#include "common/data_verification.h" +#include "common/misc_functions.h" +#include "common/repositories/bot_data_repository.h" +#include "common/repositories/character_data_repository.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/dialogue_window.h" +#include "zone/mob_movement_manager.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/water_map.h" +#include "zone/worldserver.h" -#include "bot.h" +#include +#include +#include +#include extern EntityList entity_list; @@ -641,7 +640,7 @@ void Mob::BreakCharmPetIfConditionsMet() { void Mob::CalcInvisibleLevel() { - bool was_invisible = invisible; + uint8 was_invisible = invisible; invisible = std::max({spellbonuses.invisibility, nobuff_invisible}); invisible_undead = spellbonuses.invisibility_verse_undead; diff --git a/zone/mob.h b/zone/mob.h index ca0abe2682..be9663f3ed 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -16,28 +16,27 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef MOB_H -#define MOB_H - -#include "common.h" -#include "../common/data_bucket.h" -#include "entity.h" -#include "hate_list.h" -#include "pathfinder_interface.h" -#include "position.h" -#include "aa_ability.h" -#include "aa.h" -#include "../common/light_source.h" -#include "../common/emu_constants.h" -#include "combat_record.h" -#include "event_codes.h" + +#pragma once + +#include "common/data_bucket.h" +#include "common/emu_constants.h" +#include "common/light_source.h" +#include "zone/aa_ability.h" +#include "zone/aa.h" +#include "zone/combat_record.h" +#include "zone/common.h" +#include "zone/entity.h" +#include "zone/event_codes.h" +#include "zone/hate_list.h" +#include "zone/heal_rotation.h" +#include "zone/pathfinder_interface.h" +#include "zone/position.h" #include +#include #include #include -#include - -#include "heal_rotation.h" char* strn0cpy(char* dest, const char* source, uint32 size); @@ -1953,6 +1952,3 @@ class Mob : public Entity { void DoSpellInterrupt(uint16 spell_id, int32 mana_cost, int my_curmana); void HandleDoorOpen(); }; - -#endif - diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 516df6384e..285db4b631 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -16,28 +16,26 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/features.h" -#include "../common/rulesys.h" -#include "../common/strings.h" - -#include "client.h" -#include "entity.h" -#include "map.h" #include "mob.h" -#include "npc.h" -#include "quest_parser_collection.h" -#include "string_ids.h" -#include "water_map.h" -#include "fastmath.h" -#include "../common/data_verification.h" - -#include "bot.h" -#include "../common/repositories/npc_spells_repository.h" -#include "../common/repositories/npc_spells_entries_repository.h" -#include "../common/repositories/criteria/content_filter_criteria.h" - -#include + +#include "common/data_verification.h" +#include "common/features.h" +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/npc_spells_entries_repository.h" +#include "common/repositories/npc_spells_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/fastmath.h" +#include "zone/map.h" +#include "zone/npc.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/water_map.h" + +#include "glm/gtx/projection.hpp" #include #include #include @@ -2992,4 +2990,3 @@ uint32 ZoneDatabase::GetMaxNPCSpellsEffectsID() { return Strings::ToInt(row[0]); } - diff --git a/zone/mob_appearance.cpp b/zone/mob_appearance.cpp index 2556a41b1e..6e6feaa48d 100644 --- a/zone/mob_appearance.cpp +++ b/zone/mob_appearance.cpp @@ -18,17 +18,16 @@ * */ -#include "../common/data_verification.h" -#include "../common/eqemu_logsys.h" -#include "../common/item_data.h" -#include "../common/spdat.h" -#include "../common/strings.h" - #include "mob.h" -#include "quest_parser_collection.h" -#include "zonedb.h" -#include "bot.h" +#include "common/data_verification.h" +#include "common/eqemu_logsys.h" +#include "common/item_data.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/quest_parser_collection.h" +#include "zone/zonedb.h" void Mob::SetMobTextureProfile( uint8 material_slot, diff --git a/zone/mob_info.cpp b/zone/mob_info.cpp index a896f8f016..812f9ab8fe 100644 --- a/zone/mob_info.cpp +++ b/zone/mob_info.cpp @@ -18,9 +18,10 @@ * */ -#include "client.h" #include "mob.h" -#include "npc_scale_manager.h" + +#include "zone/client.h" +#include "zone/npc_scale_manager.h" inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribute) { diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index e82202df61..214e68a566 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -1,17 +1,18 @@ #include "mob_movement_manager.h" -#include "client.h" -#include "mob.h" -#include "zone.h" -#include "position.h" -#include "water_map.h" -#include "../common/eq_packet_structs.h" -#include "../common/misc_functions.h" -#include "../common/data_verification.h" -#include +#include "common/data_verification.h" +#include "common/eq_packet_structs.h" +#include "common/misc_functions.h" +#include "zone/client.h" +#include "zone/mob.h" +#include "zone/position.h" +#include "zone/water_map.h" +#include "zone/zone.h" + +#include #include #include -#include +#include extern double frame_time; extern Zone *zone; diff --git a/zone/mob_movement_manager.h b/zone/mob_movement_manager.h index 85d0628045..4e41107583 100644 --- a/zone/mob_movement_manager.h +++ b/zone/mob_movement_manager.h @@ -1,4 +1,5 @@ #pragma once + #include class Mob; diff --git a/zone/npc.cpp b/zone/npc.cpp index 0a91d8e52c..64b61d33bc 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -16,55 +16,42 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/bodytypes.h" -#include "../common/classes.h" -#include "../common/global_define.h" -#include "../common/misc_functions.h" -#include "../common/rulesys.h" -#include "../common/seperator.h" -#include "../common/spdat.h" -#include "../common/strings.h" -#include "../common/emu_versions.h" -#include "../common/features.h" -#include "../common/item_instance.h" -#include "../common/linked_list.h" -#include "../common/servertalk.h" -#include "../common/say_link.h" -#include "../common/data_verification.h" - -#include "../common/repositories/npc_types_repository.h" -#include "../common/repositories/spawngroup_repository.h" -#include "../common/repositories/spawn2_repository.h" -#include "../common/repositories/spawnentry_repository.h" - -#include "client.h" -#include "entity.h" #include "npc.h" -#include "string_ids.h" -#include "spawn2.h" -#include "zone.h" -#include "quest_parser_collection.h" -#include "water_map.h" -#include "npc_scale_manager.h" - -#include "bot.h" -#include "../common/skill_caps.h" -#include "../common/events/player_event_logs.h" - -#include + +#include "common/bodytypes.h" +#include "common/classes.h" +#include "common/data_verification.h" +#include "common/emu_versions.h" +#include "common/events/player_event_logs.h" +#include "common/features.h" +#include "common/item_instance.h" +#include "common/linked_list.h" +#include "common/misc_functions.h" +#include "common/repositories/npc_types_repository.h" +#include "common/repositories/spawn2_repository.h" +#include "common/repositories/spawnentry_repository.h" +#include "common/repositories/spawngroup_repository.h" +#include "common/rulesys.h" +#include "common/say_link.h" +#include "common/seperator.h" +#include "common/servertalk.h" +#include "common/skill_caps.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/npc_scale_manager.h" +#include "zone/quest_parser_collection.h" +#include "zone/spawn2.h" +#include "zone/string_ids.h" +#include "zone/water_map.h" +#include "zone/zone.h" + +#include #include #include -#ifdef _WINDOWS -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#else -#include -#include - -#endif - extern Zone* zone; extern QueryServ* QServ; extern volatile bool is_zone_loaded; diff --git a/zone/npc.h b/zone/npc.h index 90569d12b2..c4b37d90f1 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -15,29 +15,23 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef NPC_H -#define NPC_H - -#include "../common/rulesys.h" - -#include "mob.h" -#include "qglobals.h" -#include "zonedb.h" -#include "../common/zone_store.h" -#include "zonedump.h" -#include "../common/repositories/npc_faction_entries_repository.h" -#include "../common/repositories/loottable_repository.h" -#include "../common/repositories/loottable_entries_repository.h" -#include "../common/repositories/lootdrop_repository.h" -#include "../common/repositories/lootdrop_entries_repository.h" -#include -#include +#pragma once +#include "common/repositories/lootdrop_entries_repository.h" +#include "common/repositories/lootdrop_repository.h" +#include "common/repositories/loottable_entries_repository.h" +#include "common/repositories/loottable_repository.h" +#include "common/repositories/npc_faction_entries_repository.h" +#include "common/rulesys.h" +#include "common/zone_store.h" +#include "zone/mob.h" +#include "zone/qglobals.h" +#include "zone/zonedb.h" +#include "zone/zonedump.h" -#ifdef _WINDOWS - #define M_PI 3.141592 -#endif +#include +#include typedef struct { float min_x; @@ -808,6 +802,3 @@ class NPC : public Mob bool m_record_loot_stats; std::vector m_rolled_items = {}; }; - -#endif - diff --git a/zone/npc_scale_manager.cpp b/zone/npc_scale_manager.cpp index 2a66b613a1..b2c7d879cf 100644 --- a/zone/npc_scale_manager.cpp +++ b/zone/npc_scale_manager.cpp @@ -19,8 +19,9 @@ */ #include "npc_scale_manager.h" -#include "../common/repositories/npc_scale_global_base_repository.h" -#include "../common/repositories/npc_types_repository.h" + +#include "common/repositories/npc_scale_global_base_repository.h" +#include "common/repositories/npc_types_repository.h" /** * @param npc diff --git a/zone/npc_scale_manager.h b/zone/npc_scale_manager.h index 2c37b3d7b3..0c2472bf77 100644 --- a/zone/npc_scale_manager.h +++ b/zone/npc_scale_manager.h @@ -18,11 +18,11 @@ * */ -#ifndef EQEMU_NPC_SCALE_MANAGER_H -#define EQEMU_NPC_SCALE_MANAGER_H +#pragma once + +#include "zone/npc.h" +#include "zone/zone.h" -#include "npc.h" -#include "zone.h" extern Zone* zone; class NpcScaleManager { @@ -119,5 +119,3 @@ class NpcScaleManager { }; extern NpcScaleManager *npc_scale_manager; - -#endif //EQEMU_NPC_SCALE_MANAGER_H diff --git a/zone/object.cpp b/zone/object.cpp index 6da171b23d..8eca194dd9 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -16,22 +16,20 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/strings.h" - -#include "client.h" -#include "entity.h" -#include "mob.h" #include "object.h" -#include "quest_parser_collection.h" -#include "worldserver.h" -#include "zonedb.h" -#include "../common/repositories/criteria/content_filter_criteria.h" -#include "../common/events/player_event_logs.h" -#include "../common/repositories/ground_spawns_repository.h" -#include "../common/repositories/object_repository.h" -#include "queryserv.h" +#include "common/events/player_event_logs.h" +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/ground_spawns_repository.h" +#include "common/repositories/object_repository.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/mob.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/worldserver.h" +#include "zone/zonedb.h" const char DEFAULT_OBJECT_NAME[] = "IT63_ACTORDEF"; diff --git a/zone/object.h b/zone/object.h index 5e66c3d196..2c6801554e 100644 --- a/zone/object.h +++ b/zone/object.h @@ -15,17 +15,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef OBJECT_H -#define OBJECT_H + +#pragma once // Object Class: // Represents Zone Objects (forges, ovens, brew barrels, items dropped to ground, etc) -#include "../common/eq_packet_structs.h" -#include "../common/timer.h" -#include "../common/types.h" - -#include "entity.h" +#include "common/eq_packet_structs.h" +#include "common/timer.h" +#include "common/types.h" +#include "zone/entity.h" class Client; class EQApplicationPacket; @@ -380,5 +379,3 @@ static std::map object_types = { { ObjectType::CollectibleBag, "Collectible Bag" }, { ObjectType::NoDeposit, "No Deposit" } }; - -#endif diff --git a/zone/oriented_bounding_box.cpp b/zone/oriented_bounding_box.cpp index ca248ba1da..2efab1c44d 100644 --- a/zone/oriented_bounding_box.cpp +++ b/zone/oriented_bounding_box.cpp @@ -1,6 +1,8 @@ + #include "oriented_bounding_box.h" -#include -#include + +#include "glm/gtc/matrix_transform.hpp" +#include "glm/gtx/transform.hpp" glm::mat4 CreateRotateMatrix(float rx, float ry, float rz) { glm::mat4 rot_x(1.0f); diff --git a/zone/oriented_bounding_box.h b/zone/oriented_bounding_box.h index bbc3cc6c3d..d6936ff624 100644 --- a/zone/oriented_bounding_box.h +++ b/zone/oriented_bounding_box.h @@ -1,8 +1,7 @@ -#ifndef EQEMU_ORIENTED_BOUNDNG_BOX_H -#define EQEMU_ORIENTED_BOUNDNG_BOX_H +#pragma once -#include -#include +#include "glm/vec3.hpp" +#include "glm/mat4x4.hpp" class OrientedBoundingBox { @@ -19,5 +18,3 @@ class OrientedBoundingBox glm::mat4 transformation; glm::mat4 inverted_transformation; }; - -#endif diff --git a/zone/parcels.cpp b/zone/parcels.cpp index f1dc874c1f..28e9b114af 100644 --- a/zone/parcels.cpp +++ b/zone/parcels.cpp @@ -16,15 +16,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/events/player_event_logs.h" -#include "../common/repositories/trader_repository.h" -#include "../common/repositories/character_parcels_repository.h" -#include "../common/repositories/character_parcels_containers_repository.h" -#include "worldserver.h" -#include "string_ids.h" #include "client.h" -#include "../common/ruletypes.h" + +#include "common/events/player_event_logs.h" +#include "common/repositories/character_parcels_containers_repository.h" +#include "common/repositories/character_parcels_repository.h" +#include "common/repositories/trader_repository.h" +#include "common/ruletypes.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" extern WorldServer worldserver; extern QueryServ *QServ; diff --git a/zone/pathfinder_interface.cpp b/zone/pathfinder_interface.cpp index e6aef0cd91..9ffb8f07ce 100644 --- a/zone/pathfinder_interface.cpp +++ b/zone/pathfinder_interface.cpp @@ -1,8 +1,11 @@ -#include "../common/seperator.h" -#include "client.h" -#include "pathfinder_null.h" -#include "pathfinder_nav_mesh.h" -#include +#include "pathfinder_interface.h" + +#include "common/seperator.h" +#include "zone/client.h" +#include "zone/pathfinder_nav_mesh.h" +#include "zone/pathfinder_null.h" + +#include "fmt/format.h" #include IPathfinder *IPathfinder::Load(const std::string &zone) { diff --git a/zone/pathfinder_interface.h b/zone/pathfinder_interface.h index d69dbac745..79b334f2e8 100644 --- a/zone/pathfinder_interface.h +++ b/zone/pathfinder_interface.h @@ -1,6 +1,7 @@ #pragma once -#include "map.h" +#include "zone/map.h" + #include class Client; diff --git a/zone/pathfinder_nav_mesh.cpp b/zone/pathfinder_nav_mesh.cpp index 5cf89f0911..71523021f5 100644 --- a/zone/pathfinder_nav_mesh.cpp +++ b/zone/pathfinder_nav_mesh.cpp @@ -1,14 +1,15 @@ -#include -#include -#include #include "pathfinder_nav_mesh.h" -#include -#include -#include "zone.h" -#include "water_map.h" -#include "client.h" -#include "../common/compression.h" +#include "common/compression.h" +#include "zone/client.h" +#include "zone/water_map.h" +#include "zone/zone.h" + +#include "recastnavigation/DetourCommon.h" +#include "recastnavigation/DetourNavMeshQuery.h" +#include +#include +#include extern Zone *zone; diff --git a/zone/pathfinder_nav_mesh.h b/zone/pathfinder_nav_mesh.h index 3b10cc23cc..2f8687dc47 100644 --- a/zone/pathfinder_nav_mesh.h +++ b/zone/pathfinder_nav_mesh.h @@ -1,8 +1,11 @@ #pragma once #include "pathfinder_interface.h" + +#include "glm/vec3.hpp" +#include "recastnavigation/DetourNavMesh.h" +#include #include -#include class PathfinderNavmesh : public IPathfinder { diff --git a/zone/pathing.cpp b/zone/pathing.cpp index 5a44b28327..5d3fde1acb 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -1,9 +1,8 @@ -#include "../common/global_define.h" -#include "../common/event/task.h" - #include "client.h" -#include "zone.h" -#include "water_map.h" + +#include "common/event/task.h" +#include "zone/water_map.h" +#include "zone/zone.h" extern Zone *zone; diff --git a/zone/pch/pch.h b/zone/pch/pch.h index a34b69021e..c8c509b310 100644 --- a/zone/pch/pch.h +++ b/zone/pch/pch.h @@ -1,11 +1,11 @@ #pragma once -#include "../merc.h" -#include "../mob.h" -#include "../npc.h" -#include "../corpse.h" -#include "../doors.h" -#include "../bot.h" -#include "../entity.h" -#include "../client.h" -#include "../zone.h" \ No newline at end of file +#include "zone/merc.h" +#include "zone/mob.h" +#include "zone/npc.h" +#include "zone/corpse.h" +#include "zone/doors.h" +#include "zone/bot.h" +#include "zone/entity.h" +#include "zone/client.h" +#include "zone/zone.h" diff --git a/zone/perl_bot.cpp b/zone/perl_bot.cpp index f667eaa446..8c90aa604e 100644 --- a/zone/perl_bot.cpp +++ b/zone/perl_bot.cpp @@ -1,8 +1,9 @@ -#include "../common/features.h" +#include "common/features.h" + #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" -#include "bot.h" + +#include "zone/bot.h" +#include "zone/embperl.h" Mob* Perl_Bot_GetOwner(Bot* self) // @categories Script Utility, Bot { @@ -741,4 +742,4 @@ void perl_register_bot() package.add("Stand", &Perl_Bot_Stand); } -#endif //EMBPERL_XS_CLASSES +#endif // EMBPERL_XS_CLASSES diff --git a/zone/perl_buff.cpp b/zone/perl_buff.cpp index 71c92cc4ea..62cb7ef71e 100644 --- a/zone/perl_buff.cpp +++ b/zone/perl_buff.cpp @@ -1,8 +1,9 @@ -#include "../common/features.h" +#include "common/features.h" + #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" -#include "common.h" + +#include "zone/common.h" +#include "zone/embperl.h" uint16 Perl_Buff_GetCasterID(Buffs_Struct* self) { diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 49a2d9d02f..c41003e116 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -1,13 +1,12 @@ -#include "../common/features.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" -#include "client.h" -#include "dynamic_zone.h" -#include "titles.h" -#include "dialogue_window.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" +#include "zone/dynamic_zone.h" +#include "zone/embperl.h" +#include "zone/titles.h" void Perl_Client_SendSound(Client* self) // @categories Script Utility { diff --git a/zone/perl_database.cpp b/zone/perl_database.cpp index d0e7c1609e..6b475a37c9 100644 --- a/zone/perl_database.cpp +++ b/zone/perl_database.cpp @@ -1,10 +1,10 @@ -#include "../common/features.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "embperl.h" -#include "perl_database.h" -#include "zonedb.h" +#include "zone/embperl.h" +#include "zone/perl_database.h" +#include "zone/zonedb.h" // Perl takes ownership of returned objects allocated with new and deletes // them via the DESTROY method when the last perl reference goes out of scope diff --git a/zone/perl_database.h b/zone/perl_database.h index 2c1922bb51..11a52c83b3 100644 --- a/zone/perl_database.h +++ b/zone/perl_database.h @@ -1,7 +1,7 @@ #pragma once -#include "quest_db.h" -#include "../common/mysql_stmt.h" +#include "common/mysql_stmt.h" +#include "zone/quest_db.h" class Perl_MySQLPreparedStmt; diff --git a/zone/perl_doors.cpp b/zone/perl_doors.cpp index 8fb9868991..64b692aa1d 100644 --- a/zone/perl_doors.cpp +++ b/zone/perl_doors.cpp @@ -1,10 +1,9 @@ -#include "../common/features.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" -#include "doors.h" +#include "zone/doors.h" +#include "zone/embperl.h" uint32_t Perl_Doors_GetDoorDBID(Doors* self) // @categories Doors { diff --git a/zone/perl_entity.cpp b/zone/perl_entity.cpp index eaad24db5e..767af3623e 100644 --- a/zone/perl_entity.cpp +++ b/zone/perl_entity.cpp @@ -1,13 +1,13 @@ -#include "../common/features.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "embperl.h" -#include "entity.h" -#include "mob.h" -#include "../common/global_define.h" -#include "../common/rulesys.h" -#include "../common/say_link.h" +#include "common/rulesys.h" +#include "common/say_link.h" +#include "zone/embperl.h" +#include "zone/entity.h" +#include "zone/mob.h" + #include Mob* Perl_EntityList_GetMobID(EntityList* self, uint16_t mob_id) // @categories Script Utility diff --git a/zone/perl_expedition.cpp b/zone/perl_expedition.cpp index a9b485f9a4..a1a4081bcd 100644 --- a/zone/perl_expedition.cpp +++ b/zone/perl_expedition.cpp @@ -1,11 +1,10 @@ -#include "../common/features.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "embperl.h" -#include "dynamic_zone.h" -#include "../common/zone_store.h" -#include "../common/global_define.h" +#include "common/zone_store.h" +#include "zone/dynamic_zone.h" +#include "zone/embperl.h" void Perl_Expedition_AddLockout(DynamicZone* self, std::string event_name, uint32_t seconds) { diff --git a/zone/perl_groups.cpp b/zone/perl_groups.cpp index a97716a28d..23247307d4 100644 --- a/zone/perl_groups.cpp +++ b/zone/perl_groups.cpp @@ -1,11 +1,10 @@ -#include "../common/features.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/data_verification.h" -#include "../common/global_define.h" -#include "embperl.h" -#include "groups.h" +#include "common/data_verification.h" +#include "zone/embperl.h" +#include "zone/groups.h" void Perl_Group_DisbandGroup(Group* self) // @categories Script Utility, Group { diff --git a/zone/perl_hateentry.cpp b/zone/perl_hateentry.cpp index 4e813b7b2c..0fbd2ef2b4 100644 --- a/zone/perl_hateentry.cpp +++ b/zone/perl_hateentry.cpp @@ -1,11 +1,10 @@ -#include "../common/features.h" -#include "client.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" -#include "hate_list.h" +#include "zone/client.h" +#include "zone/embperl.h" +#include "zone/hate_list.h" int64_t Perl_HateEntry_GetDamage(struct_HateList* self) // @categories Script Utility, Hate and Aggro { diff --git a/zone/perl_inventory.cpp b/zone/perl_inventory.cpp index a002a24a71..f943ba6e9c 100644 --- a/zone/perl_inventory.cpp +++ b/zone/perl_inventory.cpp @@ -1,10 +1,9 @@ -#include "../common/features.h" -#include "client.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" +#include "zone/client.h" +#include "zone/embperl.h" bool Perl_Inventory_CanItemFitInContainer(EQ::InventoryProfile* self, EQ::ItemInstance* item_to_check, EQ::ItemInstance* container_to_check) { diff --git a/zone/perl_merc.cpp b/zone/perl_merc.cpp index 00f7e46254..2e2ec358b2 100644 --- a/zone/perl_merc.cpp +++ b/zone/perl_merc.cpp @@ -1,8 +1,9 @@ -#include "../common/features.h" +#include "common/features.h" + #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" -#include "merc.h" + +#include "zone/embperl.h" +#include "zone/merc.h" uint32 Perl_Merc_GetCostFormula(Merc* self) { diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index dd06db33b8..5a207e1ad0 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -1,15 +1,14 @@ -#include "../common/features.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "../common/spdat.h" -#include "embperl.h" -#include "mob.h" -#include "client.h" -#include "dialogue_window.h" -#include "bot.h" -#include "questmgr.h" +#include "common/spdat.h" +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" +#include "zone/embperl.h" +#include "zone/mob.h" +#include "zone/questmgr.h" bool Perl_Mob_IsClient(Mob* self) // @categories Script Utility { diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index 6eaf0ac475..018d9be8ff 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -1,10 +1,9 @@ -#include "../common/features.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" -#include "npc.h" +#include "zone/embperl.h" +#include "zone/npc.h" void Perl_NPC_SignalNPC(NPC* self, int signal_id) // @categories Script Utility { diff --git a/zone/perl_object.cpp b/zone/perl_object.cpp index 0b744f93e3..7ecdbeffd0 100644 --- a/zone/perl_object.cpp +++ b/zone/perl_object.cpp @@ -1,10 +1,9 @@ -#include "../common/features.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" -#include "object.h" +#include "zone/embperl.h" +#include "zone/object.h" bool Perl_Object_IsGroundSpawn(Object* self) // @categories Objects { diff --git a/zone/perl_perlpacket.cpp b/zone/perl_perlpacket.cpp index 1f0a6411d9..4666fd5f91 100644 --- a/zone/perl_perlpacket.cpp +++ b/zone/perl_perlpacket.cpp @@ -1,9 +1,10 @@ -#include "../common/features.h" +#include "common/features.h" + #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "../common/types.h" -#include "embperl.h" -#include "perlpacket.h" + +#include "common/types.h" +#include "zone/embperl.h" +#include "zone/perlpacket.h" PerlPacket* Perl_PerlPacket_new(const char* class_name) { diff --git a/zone/perl_player_corpse.cpp b/zone/perl_player_corpse.cpp index c034e0312b..8ff9e97f19 100644 --- a/zone/perl_player_corpse.cpp +++ b/zone/perl_player_corpse.cpp @@ -1,10 +1,9 @@ -#include "../common/features.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" -#include "corpse.h" +#include "zone/corpse.h" +#include "zone/embperl.h" uint32_t Perl_Corpse_GetCharID(Corpse* self) // @categories Account and Character, Corpse { diff --git a/zone/perl_questitem.cpp b/zone/perl_questitem.cpp index 53e906de7e..d3cb071b0c 100644 --- a/zone/perl_questitem.cpp +++ b/zone/perl_questitem.cpp @@ -1,10 +1,9 @@ -#include "../common/features.h" -#include "client.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" +#include "zone/client.h" +#include "zone/embperl.h" std::string Perl_QuestItem_GetName(EQ::ItemInstance* self) // @categories Inventory and Items { diff --git a/zone/perl_questitem_data.cpp b/zone/perl_questitem_data.cpp index 18261b3da5..81d710a01d 100644 --- a/zone/perl_questitem_data.cpp +++ b/zone/perl_questitem_data.cpp @@ -1,10 +1,9 @@ -#include "../common/features.h" +#include "common/features.h" #include "client.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" +#include "zone/embperl.h" int Perl_QuestItemData_GetMinimumStatus(EQ::ItemData* self) { diff --git a/zone/perl_raids.cpp b/zone/perl_raids.cpp index c017851210..2cfa0802de 100644 --- a/zone/perl_raids.cpp +++ b/zone/perl_raids.cpp @@ -1,12 +1,11 @@ -#include "../common/features.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/data_verification.h" -#include "../common/global_define.h" -#include "embperl.h" -#include "raids.h" -#include "client.h" +#include "common/data_verification.h" +#include "zone/client.h" +#include "zone/embperl.h" +#include "zone/raids.h" bool Perl_Raid_IsRaidMember(Raid* self, const char* name) // @categories Raid { diff --git a/zone/perl_spawn.cpp b/zone/perl_spawn.cpp index 95c38aed1a..d0b5120e28 100644 --- a/zone/perl_spawn.cpp +++ b/zone/perl_spawn.cpp @@ -1,9 +1,9 @@ -#include "../common/features.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" -#include "spawn2.h" + +#include "zone/embperl.h" +#include "zone/spawn2.h" void Perl_Spawn_Depop(Spawn2* self) { diff --git a/zone/perl_spell.cpp b/zone/perl_spell.cpp index d8fd34509b..6d82b5a64a 100644 --- a/zone/perl_spell.cpp +++ b/zone/perl_spell.cpp @@ -1,10 +1,9 @@ -#include "../common/features.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "../common/spdat.h" -#include "embperl.h" +#include "common/spdat.h" +#include "zone/embperl.h" int Perl_Spell_GetActivated(SPDat_Spell_Struct* self) { diff --git a/zone/perl_stat_bonuses.cpp b/zone/perl_stat_bonuses.cpp index 2d232b898a..27e61fd930 100644 --- a/zone/perl_stat_bonuses.cpp +++ b/zone/perl_stat_bonuses.cpp @@ -1,10 +1,10 @@ -#include "../common/features.h" -#include "common.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "embperl.h" -#include "../common/data_verification.h" +#include "common/data_verification.h" +#include "zone/common.h" +#include "zone/embperl.h" int32 Perl_StatBonuses_GetAC(StatBonuses* self) { diff --git a/zone/perl_zone.cpp b/zone/perl_zone.cpp index b81bfe344d..d570ee87bb 100644 --- a/zone/perl_zone.cpp +++ b/zone/perl_zone.cpp @@ -1,10 +1,9 @@ -#include "../common/features.h" -#include "zone.h" +#include "common/features.h" #ifdef EMBPERL_XS_CLASSES -#include "../common/global_define.h" -#include "embperl.h" +#include "zone/embperl.h" +#include "zone/zone.h" bool Perl_Zone_BuffTimersSuspended(Zone* self) { diff --git a/zone/perlpacket.cpp b/zone/perlpacket.cpp index d0459ee3e9..48298e7c24 100644 --- a/zone/perlpacket.cpp +++ b/zone/perlpacket.cpp @@ -15,11 +15,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" + #include "perlpacket.h" -#include "client.h" -#include "../common/opcodemgr.h" -#include "../common/misc_functions.h" + +#include "common/misc_functions.h" +#include "common/opcodemgr.h" +#include "zone/client.h" PerlPacket::PerlPacket(const char *opcode, uint32 length) { SetOpcode(opcode); diff --git a/zone/perlpacket.h b/zone/perlpacket.h index 4f8e39f0eb..d42b802dfd 100644 --- a/zone/perlpacket.h +++ b/zone/perlpacket.h @@ -15,15 +15,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PERLPACKET_H -#define PERLPACKET_H + +#pragma once + +#include "common/emu_opcodes.h" +#include "common/types.h" #include #include -#include "../common/types.h" -#include "../common/emu_opcodes.h" - class Client; class PerlPacket { @@ -61,5 +61,3 @@ class PerlPacket { uint32 len; unsigned char *packet; }; - -#endif diff --git a/zone/petitions.cpp b/zone/petitions.cpp index 2790a0df88..781c50e459 100644 --- a/zone/petitions.cpp +++ b/zone/petitions.cpp @@ -15,28 +15,17 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include -#ifdef _WINDOWS -#else -#include -#endif - -#ifdef _WINDOWS - #define snprintf _snprintf - #define strncasecmp _strnicmp - #define strcasecmp _stricmp -#endif +#include "petitions.h" -#include "../common/eq_packet_structs.h" -#include "../common/servertalk.h" -#include "../common/strings.h" +#include "common/eq_packet_structs.h" +#include "common/eqemu_logsys.h" +#include "common/servertalk.h" +#include "common/strings.h" +#include "zone/entity.h" +#include "zone/worldserver.h" -#include "entity.h" -#include "petitions.h" -#include "worldserver.h" +#include extern WorldServer worldserver; diff --git a/zone/petitions.h b/zone/petitions.h index 20ddf81379..2ecee85fd6 100644 --- a/zone/petitions.h +++ b/zone/petitions.h @@ -15,17 +15,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PETITIONS_H -#define PETITIONS_H -#include "../common/linked_list.h" -#include "../common/misc_functions.h" -#include "../common/mutex.h" -#include "../common/types.h" +#pragma once -#include "client.h" -#include "zonedb.h" -#include "../common/zone_store.h" +#include "common/linked_list.h" +#include "common/misc_functions.h" +#include "common/mutex.h" +#include "common/types.h" +#include "common/zone_store.h" +#include "zone/client.h" +#include "zone/zonedb.h" class Client; @@ -122,5 +121,3 @@ class PetitionList LinkedList list; Mutex PList_Mutex; }; - -#endif diff --git a/zone/pets.cpp b/zone/pets.cpp index fea4c7f7ba..d4eec4dbe0 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -16,30 +16,20 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/spdat.h" -#include "../common/strings.h" - -#include "../common/repositories/pets_repository.h" -#include "../common/repositories/pets_beastlord_data_repository.h" -#include "../common/repositories/character_pet_name_repository.h" - -#include "entity.h" -#include "client.h" -#include "mob.h" - #include "pets.h" -#include "zonedb.h" -#include - -#include "bot.h" - -#ifndef WIN32 -#include -#include "../common/unix.h" -#endif +#include "common/repositories/character_pet_name_repository.h" +#include "common/repositories/pets_beastlord_data_repository.h" +#include "common/repositories/pets_repository.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/mob.h" +#include "zone/zonedb.h" +#include // need to pass in a char array of 64 chars void GetRandPetName(char *name) diff --git a/zone/pets.h b/zone/pets.h index dc656fb085..caa5023cd3 100644 --- a/zone/pets.h +++ b/zone/pets.h @@ -1,15 +1,10 @@ -#ifndef PETS_H -#define PETS_H +#pragma once class Mob; struct NPCType; class Pet : public NPC { - public: - Pet(NPCType *type_data, Mob *owner, uint8 pet_type, uint16 spell_id, int16 power); - virtual bool CheckSpellLevelRestriction(Mob *caster, uint16 spell_id); - - }; - -#endif - +public: + Pet(NPCType *type_data, Mob *owner, uint8 pet_type, uint16 spell_id, int16 power); + virtual bool CheckSpellLevelRestriction(Mob *caster, uint16 spell_id); +}; diff --git a/zone/position.cpp b/zone/position.cpp index 39cb5b6d43..e60e9f96f4 100644 --- a/zone/position.cpp +++ b/zone/position.cpp @@ -1,12 +1,13 @@ #include "position.h" -#include +#include "common/data_verification.h" +#include "common/strings.h" +#include "common/types.h" + +#include "fmt/format.h" #include -#include "../common/strings.h" -#include "../common/data_verification.h" #include -#include "../common/types.h" -#include +#include constexpr float position_eps = 0.0001f; diff --git a/zone/position.h b/zone/position.h index ae43aca4f5..b548bab893 100644 --- a/zone/position.h +++ b/zone/position.h @@ -15,15 +15,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef POSITION_H -#define POSITION_H +#pragma once + +#include "common/types.h" + +#include "glm/geometric.hpp" +#include "glm/vec2.hpp" +#include "glm/vec3.hpp" +#include "glm/vec4.hpp" #include -#include -#include -#include -#include -#include "../common/types.h" std::string to_string(const glm::vec4 &position); std::string to_string(const glm::vec3 &position); @@ -65,5 +66,3 @@ float CalculateHeadingAngleBetweenPositions(float x1, float y1, float x2, float bool IsWithinCircularArc(glm::vec4 arc_center, glm::vec4 point, uint32 arc_offset, uint32 arc_radius, uint32 arc_radius_limit); bool IsWithinSquare(glm::vec4 center, uint32 area, glm::vec4 position); - -#endif diff --git a/zone/qglobals.cpp b/zone/qglobals.cpp index 64a9cf65c5..4456a08bb4 100644 --- a/zone/qglobals.cpp +++ b/zone/qglobals.cpp @@ -1,8 +1,8 @@ -#include "../common/strings.h" - #include "qglobals.h" -#include "client.h" -#include "zone.h" + +#include "common/strings.h" +#include "zone/client.h" +#include "zone/zone.h" void QGlobalCache::AddGlobal(uint32 id, QGlobal global) { diff --git a/zone/qglobals.h b/zone/qglobals.h index 619f825de0..95c98da185 100644 --- a/zone/qglobals.h +++ b/zone/qglobals.h @@ -1,5 +1,4 @@ -#ifndef __QGLOBALS__H -#define __QGLOBALS__H +#pragma once #include @@ -41,5 +40,3 @@ class QGlobalCache void LoadBy(const std::string &query); std::list qGlobalBucket; }; - -#endif diff --git a/zone/queryserv.cpp b/zone/queryserv.cpp index 5a5200d5ff..3f0cd86869 100644 --- a/zone/queryserv.cpp +++ b/zone/queryserv.cpp @@ -1,10 +1,9 @@ -#include "../common/global_define.h" -#include "../common/servertalk.h" -#include "../common/strings.h" -#include "../common/events/player_event_logs.h" #include "queryserv.h" -#include "worldserver.h" +#include "common/events/player_event_logs.h" +#include "common/servertalk.h" +#include "common/strings.h" +#include "zone/worldserver.h" extern WorldServer worldserver; extern QueryServ* QServ; diff --git a/zone/queryserv.h b/zone/queryserv.h index f1a100c31b..834365f323 100644 --- a/zone/queryserv.h +++ b/zone/queryserv.h @@ -1,11 +1,10 @@ -#ifndef QUERYSERV_ZONE_H -#define QUERYSERV_ZONE_H +#pragma once -#include "../common/net/servertalk_server.h" -#include "../common/net/servertalk_client_connection.h" -#include "../common/event/timer.h" -#include "../common/rulesys.h" -#include "../common/eqemu_logsys.h" +#include "common/eqemu_logsys.h" +#include "common/event/timer.h" +#include "common/net/servertalk_client_connection.h" +#include "common/net/servertalk_server.h" +#include "common/rulesys.h" class QueryServ { public: @@ -58,5 +57,3 @@ class QueryServConnection { std::map> m_streams; std::unique_ptr m_keepalive; }; - -#endif /* QUERYSERV_ZONE_H */ diff --git a/zone/quest_db.cpp b/zone/quest_db.cpp index 5eda523d41..0efb9092ae 100644 --- a/zone/quest_db.cpp +++ b/zone/quest_db.cpp @@ -1,6 +1,7 @@ #include "quest_db.h" -#include "zonedb.h" -#include "zone_config.h" + +#include "zone/zone_config.h" +#include "zone/zonedb.h" // New connections avoid concurrency issues and allow use of unbuffered results // with prepared statements. Using zone connections w/o buffering would cause diff --git a/zone/quest_interface.h b/zone/quest_interface.h index f18e1dbece..1e668b9a79 100644 --- a/zone/quest_interface.h +++ b/zone/quest_interface.h @@ -16,11 +16,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _EQE_QUESTINTERFACE_H -#define _EQE_QUESTINTERFACE_H +#pragma once + +#include "common/types.h" +#include "zone/event_codes.h" -#include "../common/types.h" -#include "event_codes.h" #include class Client; @@ -383,6 +383,3 @@ class QuestInterface { protected: std::list errors_; }; - -#endif - diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index 9535cb89ab..f2b6a7fd5d 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -16,20 +16,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "quest_parser_collection.h" -#include "../common/global_define.h" -#include "../common/misc_functions.h" -#include "../common/features.h" +#include "common/features.h" +#include "common/file.h" +#include "common/misc_functions.h" +#include "common/path_manager.h" +#include "common/repositories/perl_event_export_settings_repository.h" +#include "zone/quest_interface.h" +#include "zone/questmgr.h" +#include "zone/zone.h" -#include "quest_parser_collection.h" -#include "quest_interface.h" -#include "zone.h" -#include "questmgr.h" -#include "../common/path_manager.h" -#include "../common/repositories/perl_event_export_settings_repository.h" -#include "../common/file.h" - -#include +#include // an encounter can register events before the object is loaded // examples diff --git a/zone/quest_parser_collection.h b/zone/quest_parser_collection.h index 5d7d1d3c08..f93854ddd8 100644 --- a/zone/quest_parser_collection.h +++ b/zone/quest_parser_collection.h @@ -16,25 +16,21 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _EQE_QUESTPARSERCOLLECTION_H -#define _EQE_QUESTPARSERCOLLECTION_H - -#include "../common/types.h" - -#include "encounter.h" -#include "beacon.h" -#include "client.h" -#include "corpse.h" -#include "doors.h" -#include "groups.h" -#include "mob.h" -#include "object.h" -#include "raids.h" -#include "trap.h" - -#include "quest_interface.h" - -#include "zone_config.h" +#pragma once + +#include "common/types.h" +#include "zone/beacon.h" +#include "zone/client.h" +#include "zone/corpse.h" +#include "zone/doors.h" +#include "zone/encounter.h" +#include "zone/groups.h" +#include "zone/mob.h" +#include "zone/object.h" +#include "zone/quest_interface.h" +#include "zone/raids.h" +#include "zone/trap.h" +#include "zone/zone_config.h" #include #include @@ -404,6 +400,3 @@ class QuestParserCollection { }; extern QuestParserCollection *parse; - -#endif - diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 342955fffc..4135b1e912 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -16,40 +16,37 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/classes.h" -#include "../common/data_verification.h" -#include "../common/global_define.h" -#include "../common/rulesys.h" -#include "../common/skills.h" -#include "../common/spdat.h" -#include "../common/strings.h" -#include "../common/say_link.h" -#include "../common/events/player_event_logs.h" - -#include "entity.h" -#include "event_codes.h" -#include "guild_mgr.h" -#include "qglobals.h" -#include "queryserv.h" -#include "quest_parser_collection.h" -#include "questmgr.h" -#include "spawn2.h" -#include "worldserver.h" -#include "zone.h" -#include "zonedb.h" -#include "dialogue_window.h" - -#include "../common/repositories/account_repository.h" -#include "../common/repositories/completed_tasks_repository.h" -#include "../common/repositories/tradeskill_recipe_repository.h" -#include "../common/repositories/instance_list_repository.h" -#include "../common/repositories/grid_entries_repository.h" - +#include "common/classes.h" +#include "common/data_verification.h" +#include "common/events/player_event_logs.h" +#include "common/repositories/account_repository.h" +#include "common/repositories/completed_tasks_repository.h" +#include "common/repositories/grid_entries_repository.h" +#include "common/repositories/instance_list_repository.h" +#include "common/repositories/tradeskill_recipe_repository.h" +#include "common/rulesys.h" +#include "common/say_link.h" +#include "common/skills.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/dialogue_window.h" +#include "zone/entity.h" +#include "zone/event_codes.h" +#include "zone/guild_mgr.h" +#include "zone/qglobals.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/questmgr.h" +#include "zone/spawn2.h" +#include "zone/worldserver.h" +#include "zone/zone.h" +#include "zone/zonedb.h" + +#include #include -#include #include - -#include "bot.h" +#include extern QueryServ* QServ; extern Zone* zone; @@ -4588,7 +4585,7 @@ void QuestManager::SpawnCircle(uint32 npc_id, glm::vec4 position, float radius, glm::vec4 npc_position = position; for (uint32 i = 0; i < points; i++) { - float angle = 2 * M_PI * i / points; + float angle = 2 * std::numbers::pi * i / points; npc_position.x = position.x + radius * std::cos(angle); npc_position.y = position.y + radius * std::sin(angle); diff --git a/zone/questmgr.h b/zone/questmgr.h index f58bb283a2..f7e3d4a856 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -15,11 +15,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __QUEST_MANAGER_H__ -#define __QUEST_MANAGER_H__ -#include "../common/timer.h" -#include "tasks.h" +#pragma once + +#include "common/timer.h" +#include "zone/tasks.h" #include #include @@ -414,6 +414,3 @@ class QuestManager { }; extern QuestManager quest_manager; - -#endif - diff --git a/zone/raids.cpp b/zone/raids.cpp index ee7c69f0f2..9fd5cd5d34 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -16,25 +16,22 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/strings.h" -#include "../common/events/player_event_logs.h" -#include "../common/repositories/character_expedition_lockouts_repository.h" -#include "../common/repositories/raid_details_repository.h" -#include "../common/repositories/raid_members_repository.h" -#include "../common/raid.h" - - -#include "client.h" -#include "dynamic_zone.h" -#include "entity.h" -#include "groups.h" -#include "mob.h" -#include "raids.h" -#include "string_ids.h" -#include "bot.h" - -#include "worldserver.h" -#include "queryserv.h" +#include "common/events/player_event_logs.h" +#include "common/raid.h" +#include "common/repositories/character_expedition_lockouts_repository.h" +#include "common/repositories/raid_details_repository.h" +#include "common/repositories/raid_members_repository.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/dynamic_zone.h" +#include "zone/entity.h" +#include "zone/groups.h" +#include "zone/mob.h" +#include "zone/queryserv.h" +#include "zone/raids.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" extern EntityList entity_list; extern WorldServer worldserver; diff --git a/zone/raids.h b/zone/raids.h index 05e2329848..46a5c6bc3e 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -15,13 +15,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef RAIDS_H -#define RAIDS_H -#include "../common/types.h" -#include "groups.h" -#include "xtargetautohaters.h" -#include "client.h" +#pragma once + +#include "common/types.h" +#include "zone/groups.h" +#include "zone/xtargetautohaters.h" +#include "zone/client.h" class Client; class EQApplicationPacket; @@ -299,7 +299,3 @@ class Raid : public GroupIDConsumer { XTargetAutoHaters m_autohatermgr; }; - - -#endif - diff --git a/zone/raycast_mesh.cpp b/zone/raycast_mesh.cpp index 20c3f6b710..405285cbf6 100644 --- a/zone/raycast_mesh.cpp +++ b/zone/raycast_mesh.cpp @@ -1,11 +1,13 @@ #include "raycast_mesh.h" -#include "../common/memory/ksm.hpp" -#include "../common/eqemu_logsys.h" -#include -#include -#include -#include -#include + +#include "common/eqemu_logsys.h" +#include "common/memory/ksm.hpp" + +#include +#include +#include +#include +#include #include // This code snippet allows you to create an axis aligned bounding volume tree for a triangle mesh so that you can do diff --git a/zone/raycast_mesh.h b/zone/raycast_mesh.h index 1aaa100cb8..14306df22e 100644 --- a/zone/raycast_mesh.h +++ b/zone/raycast_mesh.h @@ -1,6 +1,4 @@ -#ifndef RAYCAST_MESH_H - -#define RAYCAST_MESH_H +#pragma once // This code snippet allows you to create an axis aligned bounding volume tree for a triangle mesh so that you can do // high-speed raycasting. @@ -62,5 +60,3 @@ RaycastMesh * createRaycastMesh(RmUint32 vcount, // The number of vertices in t RaycastMesh* loadRaycastMesh(std::vector& rm_buffer, bool& load_success); void serializeRaycastMesh(RaycastMesh* rm, std::vector& rm_buffer); #endif /*USE_MAP_MMFS*/ - -#endif \ No newline at end of file diff --git a/zone/shared_task_zone_messaging.cpp b/zone/shared_task_zone_messaging.cpp index f3cbe09835..6d4b772cb2 100644 --- a/zone/shared_task_zone_messaging.cpp +++ b/zone/shared_task_zone_messaging.cpp @@ -1,7 +1,8 @@ #include "shared_task_zone_messaging.h" -#include "../common/shared_tasks.h" -#include "../common/servertalk.h" -#include "client.h" + +#include "common/servertalk.h" +#include "common/shared_tasks.h" +#include "zone/client.h" #include #include diff --git a/zone/shared_task_zone_messaging.h b/zone/shared_task_zone_messaging.h index 492e3ac922..86393bc018 100644 --- a/zone/shared_task_zone_messaging.h +++ b/zone/shared_task_zone_messaging.h @@ -1,5 +1,4 @@ -#ifndef EQEMU_SHARED_TASK_ZONE_MESSAGING_H -#define EQEMU_SHARED_TASK_ZONE_MESSAGING_H +#pragma once class ServerPacket; @@ -7,6 +6,3 @@ class SharedTaskZoneMessaging { public: static void HandleWorldMessage(ServerPacket *pack); }; - - -#endif //EQEMU_SHARED_TASK_ZONE_MESSAGING_H diff --git a/zone/sidecar_api/loot_simulator_controller.cpp b/zone/sidecar_api/loot_simulator_controller.cpp index ad61157efb..4975a97de2 100644 --- a/zone/sidecar_api/loot_simulator_controller.cpp +++ b/zone/sidecar_api/loot_simulator_controller.cpp @@ -1,6 +1,7 @@ #include "sidecar_api.h" -#include "../../common/json/json.hpp" -#include "../zone.h" + +#include "common/json/json.hpp" +#include "zone/zone.h" extern Zone *zone; diff --git a/zone/sidecar_api/sidecar_api.cpp b/zone/sidecar_api/sidecar_api.cpp index 583506798e..f8a9f74e3c 100644 --- a/zone/sidecar_api/sidecar_api.cpp +++ b/zone/sidecar_api/sidecar_api.cpp @@ -1,12 +1,15 @@ #include "sidecar_api.h" -#include "../../common/http/httplib.h" -#include "../../common/eqemu_logsys.h" -#include "../zonedb.h" -#include "../../common/process.h" -#include "../common.h" -#include "../zone.h" -#include "../client.h" -#include "../../common/json/json.hpp" + +#include "common/eqemu_logsys.h" +#include "common/file.h" +#include "common/http/httplib.h" +#include "common/json/json.hpp" +#include "common/process.h" +#include "zone/client.h" +#include "zone/common.h" +#include "zone/zone.h" +#include "zone/zonedb.h" + #include void CatchSidecarSignal(int sig_num) @@ -49,8 +52,6 @@ void SidecarApi::MapBestZController(const httplib::Request& req, httplib::Respon } -#include "../../common/file.h" - constexpr static int HTTP_RESPONSE_OK = 200; constexpr static int HTTP_RESPONSE_BAD_REQUEST = 400; constexpr static int HTTP_RESPONSE_UNAUTHORIZED = 401; diff --git a/zone/sidecar_api/sidecar_api.h b/zone/sidecar_api/sidecar_api.h index 0bf62223be..fbc6fd8b49 100644 --- a/zone/sidecar_api/sidecar_api.h +++ b/zone/sidecar_api/sidecar_api.h @@ -1,7 +1,7 @@ -#ifndef EQEMU_SIDECAR_API_H -#define EQEMU_SIDECAR_API_H -#include "../../common/http/httplib.h" +#pragma once + +#include "common/http/httplib.h" class SidecarApi { public: @@ -12,6 +12,3 @@ class SidecarApi { static void LootSimulatorController(const httplib::Request &req, httplib::Response &res); static void MapBestZController(const httplib::Request &req, httplib::Response &res); }; - - -#endif //EQEMU_SIDECAR_API_H diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index 9127ab3e63..f10a41e84f 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -16,25 +16,25 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include "../common/global_define.h" -#include "../common/strings.h" - -#include "client.h" -#include "entity.h" #include "spawn2.h" -#include "spawngroup.h" -#include "worldserver.h" -#include "zone.h" -#include "zonedb.h" -#include "../common/repositories/criteria/content_filter_criteria.h" -#include "../common/repositories/spawn_conditions_repository.h" -#include "../common/repositories/spawn_condition_values_repository.h" -#include "../common/repositories/spawn_events_repository.h" -#include "../common/repositories/spawn2_repository.h" -#include "../common/repositories/spawn2_disabled_repository.h" -#include "../common/repositories/respawn_times_repository.h" -#include "../common/repositories/zone_state_spawns_repository.h" + +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/respawn_times_repository.h" +#include "common/repositories/spawn_condition_values_repository.h" +#include "common/repositories/spawn_conditions_repository.h" +#include "common/repositories/spawn_events_repository.h" +#include "common/repositories/spawn2_disabled_repository.h" +#include "common/repositories/spawn2_repository.h" +#include "common/repositories/zone_state_spawns_repository.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/spawngroup.h" +#include "zone/worldserver.h" +#include "zone/zone.h" +#include "zone/zonedb.h" + +#include "cereal/archives/json.hpp" extern EntityList entity_list; extern Zone* zone; diff --git a/zone/spawn2.h b/zone/spawn2.h index f5b31022af..f77565b5db 100644 --- a/zone/spawn2.h +++ b/zone/spawn2.h @@ -15,11 +15,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef SPAWN2_H -#define SPAWN2_H -#include "../common/timer.h" -#include "npc.h" +#pragma once + +#include "common/timer.h" +#include "zone/npc.h" #define SC_AlwaysEnabled 0 @@ -186,5 +186,3 @@ class SpawnConditionManager { constexpr int format_as(SpawnCondition::OnChange val) { return static_cast(val); } constexpr int format_as(SpawnEvent::Action val) { return static_cast(val); } - -#endif diff --git a/zone/spawngroup.cpp b/zone/spawngroup.cpp index acf03f0718..bdce23a727 100644 --- a/zone/spawngroup.cpp +++ b/zone/spawngroup.cpp @@ -16,15 +16,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include "../common/global_define.h" -#include "../common/types.h" - -#include "entity.h" #include "spawngroup.h" -#include "zone.h" -#include "zonedb.h" -#include "../common/repositories/criteria/content_filter_criteria.h" + +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/types.h" +#include "zone/entity.h" +#include "zone/zone.h" +#include "zone/zonedb.h" + +#include "fmt/format.h" extern EntityList entity_list; extern Zone *zone; diff --git a/zone/spawngroup.h b/zone/spawngroup.h index 9fee729967..832c581382 100644 --- a/zone/spawngroup.h +++ b/zone/spawngroup.h @@ -15,13 +15,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef SPAWNGROUP_H -#define SPAWNGROUP_H -#include "../common/types.h" +#pragma once + +#include "common/types.h" -#include #include +#include #include class SpawnEntry { @@ -85,5 +85,3 @@ class SpawnGroupList { private: std::map> m_spawn_groups; }; - -#endif diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 57feb3f2e1..5f2de8c03e 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -16,18 +16,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/rulesys.h" -#include "../common/strings.h" - -#include "client.h" -#include "entity.h" #include "mob.h" -#include "string_ids.h" -#include "lua_parser.h" -#include "npc.h" -#include "bot.h" -#include +#include "common/rulesys.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/lua_parser.h" +#include "zone/npc.h" +#include "zone/string_ids.h" + +#include extern double frame_time; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 42078e3222..74e8246914 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -16,28 +16,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/eqemu_logsys.h" -#include "../common/bodytypes.h" -#include "../common/classes.h" -#include "../common/global_define.h" -#include "../common/item_instance.h" -#include "../common/rulesys.h" -#include "../common/spdat.h" -#include "../common/data_verification.h" -#include "../common/misc_functions.h" - -#include "bot.h" -#include "quest_parser_collection.h" -#include "lua_parser.h" -#include "string_ids.h" -#include "worldserver.h" - -#include - -#ifndef WIN32 -#include -#include "../common/unix.h" -#endif +#include "mob.h" + +#include "common/bodytypes.h" +#include "common/classes.h" +#include "common/data_verification.h" +#include "common/eqemu_logsys.h" +#include "common/item_instance.h" +#include "common/misc_functions.h" +#include "common/rulesys.h" +#include "common/spdat.h" +#include "zone/bot.h" +#include "zone/lua_parser.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" + +#include extern Zone* zone; diff --git a/zone/spells.cpp b/zone/spells.cpp index 6636a092cc..4e89bbba93 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -66,46 +66,34 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) and not SpellFinished(). */ -#include "../common/bodytypes.h" -#include "../common/classes.h" -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/item_instance.h" -#include "../common/rulesys.h" -#include "../common/spdat.h" -#include "../common/strings.h" -#include "../common/data_verification.h" -#include "../common/misc_functions.h" -#include "../common/events/player_event_logs.h" -#include "../common/repositories/character_corpses_repository.h" -#include "../common/repositories/spell_buckets_repository.h" - -#include "../common/data_bucket.h" -#include "quest_parser_collection.h" -#include "string_ids.h" -#include "worldserver.h" -#include "fastmath.h" -#include "lua_parser.h" - -#include -#include -#include "queryserv.h" - -#ifndef WIN32 - #include - #include "../common/unix.h" -#endif - -#ifdef _GOTFRAGS - #include "../common/packet_dump_file.h" -#endif +#include "mob.h" -#include "bot.h" +#include "common/bodytypes.h" +#include "common/classes.h" +#include "common/data_bucket.h" +#include "common/data_verification.h" +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/item_instance.h" +#include "common/misc_functions.h" +#include "common/repositories/character_corpses_repository.h" +#include "common/repositories/spell_buckets_repository.h" +#include "common/rulesys.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/client.h" +#include "zone/fastmath.h" +#include "zone/lua_parser.h" +#include "zone/mob_movement_manager.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/water_map.h" +#include "zone/worldserver.h" -#include "mob_movement_manager.h" -#include "client.h" -#include "mob.h" -#include "water_map.h" +#include +#include extern Zone *zone; extern volatile bool is_zone_loaded; diff --git a/zone/string_ids.h b/zone/string_ids.h index 5e929db02c..50fe61bfbe 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -1,5 +1,4 @@ -#ifndef STRING_IDS -#define STRING_IDS +#pragma once //These strings are loaded from eqstr_us.txt, but may vary between client versions. Maybe we could make this an enum that's dependent on the client version? #define GENERIC_9_STRINGS 1 //%1 %2 %3 %4 %5 %6 %7 %8 %9 @@ -600,6 +599,3 @@ #define GAIN_XP_BONUS 14541 //You gain experience (with a bonus)! #define GAIN_XP_PENALTY 14542 //You gain experience (with a penalty)! #define GENERIC_MISS 15041 //%1 missed %2 - -#endif - diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp index af9525a604..b2bd100bec 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -1,20 +1,20 @@ -#include "../common/global_define.h" -#include "../common/misc_functions.h" -#include "../common/repositories/character_activities_repository.h" -#include "../common/repositories/character_task_timers_repository.h" -#include "../common/repositories/character_tasks_repository.h" -#include "../common/repositories/completed_tasks_repository.h" -#include "../common/rulesys.h" -#include "client.h" -#include "queryserv.h" -#include "quest_parser_collection.h" #include "task_client_state.h" -#include "zonedb.h" -#include "../common/shared_tasks.h" -#include "worldserver.h" -#include "dynamic_zone.h" -#include "string_ids.h" -#include "../common/events/player_event_logs.h" + +#include "common/events/player_event_logs.h" +#include "common/misc_functions.h" +#include "common/repositories/character_activities_repository.h" +#include "common/repositories/character_task_timers_repository.h" +#include "common/repositories/character_tasks_repository.h" +#include "common/repositories/completed_tasks_repository.h" +#include "common/rulesys.h" +#include "common/shared_tasks.h" +#include "zone/client.h" +#include "zone/dynamic_zone.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" +#include "zone/zonedb.h" #define EBON_CRYSTAL 40902 #define RADIANT_CRYSTAL 40903 diff --git a/zone/task_client_state.h b/zone/task_client_state.h index 30c5dd69c5..e444619ebd 100644 --- a/zone/task_client_state.h +++ b/zone/task_client_state.h @@ -1,12 +1,12 @@ -#ifndef EQEMU_TASK_CLIENT_STATE_H -#define EQEMU_TASK_CLIENT_STATE_H +#pragma once -#include "tasks.h" -#include "../common/types.h" +#include "common/types.h" +#include "zone/tasks.h" + +#include #include -#include #include -#include +#include constexpr float MAX_TASK_SELECT_DISTANCE = 60.0f; // client closes window at this distance @@ -183,5 +183,3 @@ class ClientTaskState { ); bool HasActiveTasks(); }; - -#endif //EQEMU_TASK_CLIENT_STATE_H diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp index d6df2ebb92..8a7badbd4a 100644 --- a/zone/task_manager.cpp +++ b/zone/task_manager.cpp @@ -1,19 +1,19 @@ -#include "../common/global_define.h" -#include "../common/misc_functions.h" -#include "../common/repositories/character_activities_repository.h" -#include "../common/repositories/character_tasks_repository.h" -#include "../common/repositories/completed_tasks_repository.h" -#include "../common/repositories/task_activities_repository.h" -#include "../common/repositories/tasks_repository.h" -#include "../common/repositories/tasksets_repository.h" -#include "client.h" -#include "dynamic_zone.h" -#include "string_ids.h" #include "task_manager.h" -#include "../common/repositories/shared_task_activity_state_repository.h" -#include "../common/repositories/shared_task_members_repository.h" -#include "../common/shared_tasks.h" -#include "worldserver.h" + +#include "common/misc_functions.h" +#include "common/repositories/character_activities_repository.h" +#include "common/repositories/character_tasks_repository.h" +#include "common/repositories/completed_tasks_repository.h" +#include "common/repositories/shared_task_activity_state_repository.h" +#include "common/repositories/shared_task_members_repository.h" +#include "common/repositories/task_activities_repository.h" +#include "common/repositories/tasks_repository.h" +#include "common/repositories/tasksets_repository.h" +#include "common/shared_tasks.h" +#include "zone/client.h" +#include "zone/dynamic_zone.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/task_manager.h b/zone/task_manager.h index abd1255a44..83a4f95714 100644 --- a/zone/task_manager.h +++ b/zone/task_manager.h @@ -1,14 +1,14 @@ -#ifndef EQEMU_TASK_MANAGER_H -#define EQEMU_TASK_MANAGER_H +#pragma once -#include "tasks.h" -#include "task_client_state.h" -#include "../common/types.h" -#include "../common/repositories/character_tasks_repository.h" +#include "common/repositories/character_tasks_repository.h" +#include "common/types.h" +#include "zone/task_client_state.h" +#include "zone/tasks.h" + +#include #include -#include #include -#include +#include class Client; class Mob; @@ -97,6 +97,3 @@ class TaskManager { void SendSharedTaskSelector(Client* client, Mob* mob, const std::vector& tasks); void SyncClientSharedTaskStateToLocal(Client *c); }; - - -#endif //EQEMU_TASK_MANAGER_H diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 708a43e844..145c5d430c 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -1,14 +1,14 @@ -#include "../common/global_define.h" -#include "../common/misc_functions.h" -#include "../common/rulesys.h" -#include "../common/strings.h" -#include "client.h" -#include "queryserv.h" -#include "quest_parser_collection.h" -#include "string_ids.h" #include "tasks.h" -#include "zonedb.h" -#include "../common/repositories/character_task_timers_repository.h" + +#include "common/misc_functions.h" +#include "common/repositories/character_task_timers_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/zonedb.h" extern QueryServ *QServ; diff --git a/zone/tasks.h b/zone/tasks.h index 56be4fa8d7..5d6e764da4 100644 --- a/zone/tasks.h +++ b/zone/tasks.h @@ -1,12 +1,12 @@ -#ifndef TASKS_H -#define TASKS_H +#pragma once -#include "../common/types.h" -#include "../common/tasks.h" +#include "common/tasks.h" +#include "common/types.h" + +#include #include -#include #include -#include +#include class Client; class Mob; @@ -14,5 +14,3 @@ class Mob; namespace EQ { class ItemInstance; } - -#endif diff --git a/zone/titles.cpp b/zone/titles.cpp index 84ee2dd50b..ef1d771c88 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -1,13 +1,12 @@ -#include "../common/eq_packet_structs.h" -#include "../common/strings.h" -#include "../common/misc_functions.h" -#include "../common/repositories/player_titlesets_repository.h" - -#include "client.h" -#include "mob.h" - #include "titles.h" -#include "worldserver.h" + +#include "common/eq_packet_structs.h" +#include "common/misc_functions.h" +#include "common/repositories/player_titlesets_repository.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/mob.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/titles.h b/zone/titles.h index 5486e49c5f..4541810c08 100644 --- a/zone/titles.h +++ b/zone/titles.h @@ -1,8 +1,8 @@ -#ifndef TITLES_H -#define TITLES_H +#pragma once + +#include "common/repositories/titles_repository.h" #include -#include "../common/repositories/titles_repository.h" class Client; class EQApplicationPacket; @@ -30,6 +30,3 @@ class TitleManager }; extern TitleManager title_manager; - -#endif - diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index d307ca418a..756c5fcc87 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -16,29 +16,24 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/events/player_event_logs.h" +#include "client.h" + +#include "common/events/player_event_logs.h" +#include "common/repositories/char_recipe_list_repository.h" +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/tradeskill_recipe_entries_repository.h" +#include "common/repositories/tradeskill_recipe_repository.h" +#include "common/rulesys.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/titles.h" +#include "zone/worldserver.h" +#include "zone/zonedb.h" #include #include -#ifndef WIN32 -#include //for htonl -#endif - -#include "../common/rulesys.h" - -#include "queryserv.h" -#include "quest_parser_collection.h" -#include "string_ids.h" -#include "titles.h" -#include "zonedb.h" -#include "worldserver.h" -#include "../common/repositories/char_recipe_list_repository.h" -#include "../common/repositories/criteria/content_filter_criteria.h" -#include "../common/repositories/tradeskill_recipe_repository.h" -#include "../common/repositories/tradeskill_recipe_entries_repository.h" - extern QueryServ* QServ; extern WorldServer worldserver; diff --git a/zone/trading.cpp b/zone/trading.cpp index 9415c9e019..b5f26eb4d5 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -16,25 +16,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/rulesys.h" -#include "../common/strings.h" -#include "../common/eq_packet_structs.h" -#include "../common/misc_functions.h" -#include "../common/events/player_event_logs.h" -#include "../common/repositories/trader_repository.h" -#include "../common/repositories/buyer_repository.h" -#include "../common/repositories/buyer_buy_lines_repository.h" - #include "client.h" -#include "entity.h" -#include "mob.h" -#include "quest_parser_collection.h" -#include "string_ids.h" -#include "worldserver.h" -#include "../common/bazaar.h" +#include "common/bazaar.h" +#include "common/eq_packet_structs.h" +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/misc_functions.h" +#include "common/repositories/buyer_buy_lines_repository.h" +#include "common/repositories/buyer_repository.h" +#include "common/repositories/trader_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "zone/entity.h" +#include "zone/mob.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" #include class QueryServ; diff --git a/zone/trap.cpp b/zone/trap.cpp index 7377d58975..fbab075400 100644 --- a/zone/trap.cpp +++ b/zone/trap.cpp @@ -16,15 +16,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/spdat.h" -#include "../common/strings.h" - -#include "client.h" -#include "entity.h" -#include "mob.h" #include "trap.h" -#include "../common/repositories/criteria/content_filter_criteria.h" -#include "../common/repositories/traps_repository.h" + +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/traps_repository.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/mob.h" /* diff --git a/zone/trap.h b/zone/trap.h index 4c7e7daa19..23f8fedd15 100644 --- a/zone/trap.h +++ b/zone/trap.h @@ -15,10 +15,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _TRAP_H -#define _TRAP_H -#include "entity.h" +#pragma once + +#include "zone/entity.h" class Mob; class NPC; @@ -81,6 +81,3 @@ class Trap: public Entity protected: NPC *hiddenTrigger; }; - -#endif - diff --git a/zone/tribute.cpp b/zone/tribute.cpp index f9a9e73576..e783465ecb 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -16,30 +16,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eq_packet_structs.h" -#include "../common/features.h" -#include "../common/repositories/guild_tributes_repository.h" -#include "../common/guild_base.h" -#include "guild_mgr.h" -#include "worldserver.h" - #include "client.h" -#include +#include "common/eq_packet_structs.h" +#include "common/features.h" +#include "common/guild_base.h" +#include "common/repositories/guild_tributes_repository.h" +#include "zone/guild_mgr.h" +#include "zone/worldserver.h" -#ifdef _WINDOWS - #include - #define snprintf _snprintf - #define vsnprintf _vsnprintf - #define strncasecmp _strnicmp - #define strcasecmp _stricmp -#else - #include - #include - #include - #include "../common/unix.h" -#endif +#include /* diff --git a/zone/tune.cpp b/zone/tune.cpp index 6f94d7bbdb..0471d74df5 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -16,38 +16,26 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#if EQDEBUG >= 5 -//#define TUNE_DEBUG 20 -#endif - -#include "../common/global_define.h" -#include "../common/eq_constants.h" -#include "../common/eq_packet_structs.h" -#include "../common/rulesys.h" -#include "../common/spdat.h" -#include "../common/strings.h" -#include "../common/data_verification.h" -#include "queryserv.h" -#include "string_ids.h" -#include "water_map.h" -#include "worldserver.h" -#include "zone.h" -#include "lua_parser.h" -#include "fastmath.h" #include "mob.h" -#include "bot.h" +#include "common/data_verification.h" +#include "common/eq_constants.h" +#include "common/eq_packet_structs.h" +#include "common/rulesys.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/fastmath.h" +#include "zone/lua_parser.h" +#include "zone/queryserv.h" +#include "zone/string_ids.h" +#include "zone/water_map.h" +#include "zone/worldserver.h" +#include "zone/zone.h" extern QueryServ* QServ; extern WorldServer worldserver; extern FastMath g_Math; - -#ifdef _WINDOWS -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#endif - extern EntityList entity_list; extern Zone* zone; diff --git a/zone/water_map.cpp b/zone/water_map.cpp index e31bb0c75a..80fc2d58ee 100644 --- a/zone/water_map.cpp +++ b/zone/water_map.cpp @@ -1,14 +1,13 @@ - - #include "water_map.h" -#include "water_map_v1.h" -#include "water_map_v2.h" -#include "../common/eqemu_logsys.h" + +#include "common/eqemu_logsys.h" +#include "zone/water_map_v1.h" +#include "zone/water_map_v2.h" #include #include -#include -#include +#include +#include /** * @param zone_name diff --git a/zone/water_map.h b/zone/water_map.h index 975703b403..1eec456a9f 100644 --- a/zone/water_map.h +++ b/zone/water_map.h @@ -1,9 +1,9 @@ -#ifndef EQEMU_WATER_MAP_H -#define EQEMU_WATER_MAP_H +#pragma once + +#include "common/types.h" +#include "zone/position.h" +#include "zone/zone_config.h" -#include "../common/types.h" -#include "position.h" -#include "zone_config.h" #include extern const ZoneConfig *Config; @@ -39,5 +39,3 @@ class WaterMap protected: virtual bool Load(FILE *fp) { return false; } }; - -#endif diff --git a/zone/water_map_v1.h b/zone/water_map_v1.h index af4d4966f2..cdce61ccfc 100644 --- a/zone/water_map_v1.h +++ b/zone/water_map_v1.h @@ -1,8 +1,8 @@ -#ifndef EQEMU_WATER_MAP_V1_H -#define EQEMU_WATER_MAP_V1_H +#pragma once -#include "water_map.h" +#include "zone/water_map.h" +#pragma pack(push) #pragma pack(1) typedef struct ZBSP_Node { int32 node_number; @@ -11,7 +11,8 @@ typedef struct ZBSP_Node { int32 special; int32 left, right; } ZBSP_Node; -#pragma pack() + +#pragma pack(pop) class WaterMapV1 : public WaterMap { @@ -36,5 +37,3 @@ class WaterMapV1 : public WaterMap friend class WaterMap; }; - -#endif diff --git a/zone/water_map_v2.h b/zone/water_map_v2.h index 704d1a1196..5da8acdb8f 100644 --- a/zone/water_map_v2.h +++ b/zone/water_map_v2.h @@ -1,10 +1,10 @@ -#ifndef EQEMU_WATER_MAP_V2_H -#define EQEMU_WATER_MAP_V2_H +#pragma once + +#include "zone/oriented_bounding_box.h" +#include "zone/water_map.h" -#include "water_map.h" -#include "oriented_bounding_box.h" -#include #include +#include class WaterMapV2 : public WaterMap { @@ -26,5 +26,3 @@ class WaterMapV2 : public WaterMap std::vector> regions; friend class WaterMap; }; - -#endif diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 5904c83adf..4745b6c8c4 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -15,28 +15,24 @@ 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 "../common/global_define.h" -#ifdef _EQDEBUG -#include -#endif -#include "../common/rulesys.h" -#include "../common/strings.h" -#include "../common/misc_functions.h" -#include "../common/eqemu_logsys.h" - -#include "map.h" #include "npc.h" -#include "quest_parser_collection.h" -#include "water_map.h" -#include "fastmath.h" -#include "mob_movement_manager.h" - -#include "../common/repositories/grid_repository.h" -#include "../common/repositories/grid_entries_repository.h" -#include "../common/repositories/spawn2_repository.h" -#include +#include "common/eqemu_logsys.h" +#include "common/misc_functions.h" +#include "common/repositories/grid_entries_repository.h" +#include "common/repositories/grid_repository.h" +#include "common/repositories/spawn2_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/fastmath.h" +#include "zone/map.h" +#include "zone/mob_movement_manager.h" +#include "zone/quest_parser_collection.h" +#include "zone/water_map.h" + +#include extern FastMath g_Math; @@ -1266,7 +1262,6 @@ void NPC::RestoreGuardSpotCharm() /****************** * Bot-specific overloads to make them play nice with the new movement system */ -#include "bot.h" void Bot::WalkTo(float x, float y, float z) { diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 747302e24e..b73a55b6b4 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -16,63 +16,55 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include -#include -#include -#include - -#ifdef _WINDOWS -#include - -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#endif - -#include "../common/eq_packet_structs.h" -#include "../common/misc_functions.h" -#include "../common/rulesys.h" -#include "../common/say_link.h" -#include "../common/servertalk.h" -#include "../common/profanity_manager.h" - -#include "client.h" -#include "command.h" -#include "corpse.h" -#include "dynamic_zone.h" -#include "entity.h" -#include "quest_parser_collection.h" -#include "guild_mgr.h" -#include "mob.h" -#include "petitions.h" -#include "raids.h" -#include "string_ids.h" -#include "titles.h" #include "worldserver.h" -#include "zone.h" -#include "zone_config.h" -#include "../common/shared_tasks.h" -#include "shared_task_zone_messaging.h" -#include "dialogue_window.h" -#include "bot_command.h" -#include "../common/events/player_event_logs.h" -#include "../common/repositories/guild_tributes_repository.h" -#include "../common/patches/patches.h" -#include "../common/skill_caps.h" -#include "../common/server_reload_types.h" -#include "queryserv.h" + +#include "common/eq_packet_structs.h" +#include "common/events/player_event_logs.h" +#include "common/misc_functions.h" +#include "common/patches/patches.h" +#include "common/profanity_manager.h" +#include "common/repositories/guild_tributes_repository.h" +#include "common/rulesys.h" +#include "common/say_link.h" +#include "common/server_reload_types.h" +#include "common/servertalk.h" +#include "common/shared_tasks.h" +#include "common/skill_caps.h" +#include "zone/bot_command.h" +#include "zone/client.h" +#include "zone/command.h" +#include "zone/corpse.h" +#include "zone/dialogue_window.h" +#include "zone/dynamic_zone.h" +#include "zone/entity.h" +#include "zone/guild_mgr.h" +#include "zone/mob.h" +#include "zone/petitions.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/raids.h" +#include "zone/shared_task_zone_messaging.h" +#include "zone/string_ids.h" +#include "zone/titles.h" +#include "zone/zone_config.h" +#include "zone/zone.h" + +#include +#include +#include +#include extern EntityList entity_list; extern Zone *zone; extern volatile bool is_zone_loaded; -extern void Shutdown(); extern WorldServer worldserver; extern uint32 numclients; extern volatile bool RunLoops; extern QuestParserCollection *parse; extern QueryServ *QServ; +void Shutdown(); + // QuestParserCollection *parse = 0; WorldServer::WorldServer() @@ -2927,10 +2919,10 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) c->AssignTask(u->task_identifier, u->task_subidentifier, u->enforce_level_requirement); break; case CZTaskUpdateSubtype_DisableTask: - c->DisableTask(1, reinterpret_cast(u->task_identifier)); + c->DisableTask(1, reinterpret_cast(&u->task_identifier)); break; case CZTaskUpdateSubtype_EnableTask: - c->EnableTask(1, reinterpret_cast(u->task_identifier)); + c->EnableTask(1, reinterpret_cast(&u->task_identifier)); break; case CZTaskUpdateSubtype_FailTask: c->FailTask(u->task_identifier); @@ -2957,10 +2949,10 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) group_member->AssignTask(u->task_identifier, u->task_subidentifier, u->enforce_level_requirement); break; case CZTaskUpdateSubtype_DisableTask: - group_member->DisableTask(1, reinterpret_cast(u->task_identifier)); + group_member->DisableTask(1, reinterpret_cast(&u->task_identifier)); break; case CZTaskUpdateSubtype_EnableTask: - group_member->EnableTask(1, reinterpret_cast(u->task_identifier)); + group_member->EnableTask(1, reinterpret_cast(&u->task_identifier)); break; case CZTaskUpdateSubtype_FailTask: group_member->FailTask(u->task_identifier); @@ -2988,10 +2980,10 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) m.member->CastToClient()->AssignTask(u->task_identifier, u->task_subidentifier, u->enforce_level_requirement); break; case CZTaskUpdateSubtype_DisableTask: - m.member->CastToClient()->DisableTask(1, reinterpret_cast(u->task_identifier)); + m.member->CastToClient()->DisableTask(1, reinterpret_cast(&u->task_identifier)); break; case CZTaskUpdateSubtype_EnableTask: - m.member->CastToClient()->EnableTask(1, reinterpret_cast(u->task_identifier)); + m.member->CastToClient()->EnableTask(1, reinterpret_cast(&u->task_identifier)); break; case CZTaskUpdateSubtype_FailTask: m.member->CastToClient()->FailTask(u->task_identifier); @@ -3017,10 +3009,10 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) c.second->AssignTask(u->task_identifier, u->task_subidentifier, u->enforce_level_requirement); break; case CZTaskUpdateSubtype_DisableTask: - c.second->DisableTask(1, reinterpret_cast(u->task_identifier)); + c.second->DisableTask(1, reinterpret_cast(&u->task_identifier)); break; case CZTaskUpdateSubtype_EnableTask: - c.second->EnableTask(1, reinterpret_cast(u->task_identifier)); + c.second->EnableTask(1, reinterpret_cast(&u->task_identifier)); break; case CZTaskUpdateSubtype_FailTask: c.second->FailTask(u->task_identifier); @@ -3045,10 +3037,10 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) c.second->AssignTask(u->task_identifier, u->task_subidentifier, u->enforce_level_requirement); break; case CZTaskUpdateSubtype_DisableTask: - c.second->DisableTask(1, reinterpret_cast(u->task_identifier)); + c.second->DisableTask(1, reinterpret_cast(&u->task_identifier)); break; case CZTaskUpdateSubtype_EnableTask: - c.second->EnableTask(1, reinterpret_cast(u->task_identifier)); + c.second->EnableTask(1, reinterpret_cast(&u->task_identifier)); break; case CZTaskUpdateSubtype_FailTask: c.second->FailTask(u->task_identifier); @@ -3073,10 +3065,10 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) c->AssignTask(u->task_identifier, u->task_subidentifier, u->enforce_level_requirement); break; case CZTaskUpdateSubtype_DisableTask: - c->DisableTask(1, reinterpret_cast(u->task_identifier)); + c->DisableTask(1, reinterpret_cast(&u->task_identifier)); break; case CZTaskUpdateSubtype_EnableTask: - c->EnableTask(1, reinterpret_cast(u->task_identifier)); + c->EnableTask(1, reinterpret_cast(&u->task_identifier)); break; case CZTaskUpdateSubtype_FailTask: c->FailTask(u->task_identifier); @@ -3313,10 +3305,10 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) c.second->AssignTask(u->task_identifier, u->task_subidentifier, u->enforce_level_requirement); break; case WWTaskUpdateType_DisableTask: - c.second->DisableTask(1, reinterpret_cast(u->task_identifier)); + c.second->DisableTask(1, reinterpret_cast(&u->task_identifier)); break; case WWTaskUpdateType_EnableTask: - c.second->EnableTask(1, reinterpret_cast(u->task_identifier)); + c.second->EnableTask(1, reinterpret_cast(&u->task_identifier)); break; case WWTaskUpdateType_FailTask: c.second->FailTask(u->task_identifier); diff --git a/zone/worldserver.h b/zone/worldserver.h index 2e92169a56..7d59e6d850 100644 --- a/zone/worldserver.h +++ b/zone/worldserver.h @@ -15,13 +15,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef WORLDSERVER_H -#define WORLDSERVER_H -#include "../common/eq_packet_structs.h" -#include "../common/net/servertalk_client_connection.h" -#include "zone_event_scheduler.h" -#include "../common/server_reload_types.h" +#pragma once + +#include "common/eq_packet_structs.h" +#include "common/net/servertalk_client_connection.h" +#include "common/server_reload_types.h" +#include "zone/zone_event_scheduler.h" class ServerPacket; class EQApplicationPacket; @@ -88,5 +88,3 @@ class WorldServer { void SetScheduler(ZoneEventScheduler *scheduler); void SendReload(ServerReload::Type type, bool is_global = true); }; -#endif - diff --git a/zone/xtargetautohaters.cpp b/zone/xtargetautohaters.cpp index ab010d9dbb..5c49b08a38 100644 --- a/zone/xtargetautohaters.cpp +++ b/zone/xtargetautohaters.cpp @@ -1,8 +1,9 @@ #include "xtargetautohaters.h" -#include "mob.h" -#include "client.h" -#include "raids.h" -#include "groups.h" + +#include "zone/client.h" +#include "zone/groups.h" +#include "zone/mob.h" +#include "zone/raids.h" #include @@ -109,4 +110,3 @@ bool XTargetAutoHaters::contains_mob(int spawn_id) [spawn_id](const HatersCount &c) { return c.spawn_id == spawn_id; }); return it != m_haters.end(); } - diff --git a/zone/xtargetautohaters.h b/zone/xtargetautohaters.h index 73c0fa8d23..761331fa9c 100644 --- a/zone/xtargetautohaters.h +++ b/zone/xtargetautohaters.h @@ -1,5 +1,4 @@ -#ifndef XTARGETAUTOHATERS_H -#define XTARGETAUTOHATERS_H +#pragma once #include @@ -41,7 +40,3 @@ struct HatersCount { Group *m_group; Raid *m_raid; }; - - -#endif /* !XTARGETAUTOHATERS_H */ - diff --git a/zone/zone.cpp b/zone/zone.cpp index 771ac95385..34a635b3bb 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -16,69 +16,53 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include -#include - -#ifdef _WINDOWS -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#else -#include -#include "../common/unix.h" -#endif - -#include "../common/global_define.h" -#include "../common/features.h" -#include "../common/rulesys.h" -#include "../common/seperator.h" -#include "../common/strings.h" -#include "../common/eqemu_logsys.h" - -#include "dynamic_zone.h" -#include "guild_mgr.h" -#include "map.h" -#include "npc.h" -#include "object.h" -#include "pathfinder_null.h" -#include "petitions.h" -#include "quest_parser_collection.h" -#include "spawn2.h" -#include "spawngroup.h" -#include "water_map.h" -#include "worldserver.h" #include "zone.h" -#include "zone_config.h" -#include "mob_movement_manager.h" -#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/character_exp_modifiers_repository.h" -#include "../common/repositories/merchantlist_repository.h" -#include "../common/repositories/object_repository.h" -#include "../common/repositories/rule_sets_repository.h" -#include "../common/repositories/level_exp_mods_repository.h" -#include "../common/repositories/ldon_trap_entries_repository.h" -#include "../common/repositories/ldon_trap_templates_repository.h" -#include "../common/repositories/respawn_times_repository.h" -#include "../common/repositories/npc_emotes_repository.h" -#include "../common/repositories/zone_state_spawns_repository.h" -#include "../common/serverinfo.h" -#include "../common/repositories/merc_stance_entries_repository.h" -#include "../common/repositories/alternate_currency_repository.h" -#include "../common/repositories/graveyard_repository.h" -#include "../common/repositories/trader_repository.h" -#include "../common/repositories/buyer_repository.h" - -#include - -#ifdef _WINDOWS -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#endif + +#include "common/data_verification.h" +#include "common/eqemu_logsys.h" +#include "common/features.h" +#include "common/repositories/alternate_currency_repository.h" +#include "common/repositories/buyer_repository.h" +#include "common/repositories/character_exp_modifiers_repository.h" +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/graveyard_repository.h" +#include "common/repositories/ldon_trap_entries_repository.h" +#include "common/repositories/ldon_trap_templates_repository.h" +#include "common/repositories/level_exp_mods_repository.h" +#include "common/repositories/merc_stance_entries_repository.h" +#include "common/repositories/merchantlist_repository.h" +#include "common/repositories/npc_emotes_repository.h" +#include "common/repositories/object_repository.h" +#include "common/repositories/respawn_times_repository.h" +#include "common/repositories/rule_sets_repository.h" +#include "common/repositories/trader_repository.h" +#include "common/repositories/zone_state_spawns_repository.h" +#include "common/rulesys.h" +#include "common/seperator.h" +#include "common/serverinfo.h" +#include "common/strings.h" +#include "zone/dynamic_zone.h" +#include "zone/guild_mgr.h" +#include "zone/map.h" +#include "zone/mob_movement_manager.h" +#include "zone/npc_scale_manager.h" +#include "zone/npc.h" +#include "zone/object.h" +#include "zone/pathfinder_null.h" +#include "zone/petitions.h" +#include "zone/quest_parser_collection.h" +#include "zone/spawn2.h" +#include "zone/spawngroup.h" +#include "zone/water_map.h" +#include "zone/worldserver.h" +#include "zone/zone_config.h" +#include "zone/zone_reload.h" + +#include +#include +#include +#include +#include extern bool staticzone; extern QuestParserCollection* parse; diff --git a/zone/zone.h b/zone/zone.h index fe9d396505..ce6a731fd7 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -15,41 +15,41 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef ZONE_H -#define ZONE_H - -#include "../common/eqtime.h" -#include "../common/linked_list.h" -#include "../common/rulesys.h" -#include "../common/types.h" -#include "../common/random.h" -#include "../common/strings.h" -#include "zonedb.h" -#include "../common/zone_store.h" -#include "../common/repositories/grid_repository.h" -#include "../common/repositories/grid_entries_repository.h" -#include "../common/repositories/zone_points_repository.h" -#include "qglobals.h" -#include "spawn2.h" -#include "spawngroup.h" -#include "aa_ability.h" -#include "pathfinder_interface.h" -#include "global_loot_manager.h" -#include "queryserv.h" -#include "../common/discord/discord.h" -#include "../common/repositories/dynamic_zone_templates_repository.h" -#include "../common/repositories/npc_faction_repository.h" -#include "../common/repositories/npc_faction_entries_repository.h" -#include "../common/repositories/faction_association_repository.h" -#include "../common/repositories/loottable_repository.h" -#include "../common/repositories/loottable_entries_repository.h" -#include "../common/repositories/lootdrop_repository.h" -#include "../common/repositories/lootdrop_entries_repository.h" -#include "../common/repositories/base_data_repository.h" -#include "../common/repositories/skill_caps_repository.h" -#include "../common/repositories/zone_state_spawns_repository.h" -#include "../common/repositories/spawn2_disabled_repository.h" -#include "../common/repositories/player_titlesets_repository.h" + +#pragma once + +#include "common/discord/discord.h" +#include "common/eqtime.h" +#include "common/linked_list.h" +#include "common/random.h" +#include "common/repositories/base_data_repository.h" +#include "common/repositories/dynamic_zone_templates_repository.h" +#include "common/repositories/faction_association_repository.h" +#include "common/repositories/grid_entries_repository.h" +#include "common/repositories/grid_repository.h" +#include "common/repositories/lootdrop_entries_repository.h" +#include "common/repositories/lootdrop_repository.h" +#include "common/repositories/loottable_entries_repository.h" +#include "common/repositories/loottable_repository.h" +#include "common/repositories/npc_faction_entries_repository.h" +#include "common/repositories/npc_faction_repository.h" +#include "common/repositories/player_titlesets_repository.h" +#include "common/repositories/skill_caps_repository.h" +#include "common/repositories/spawn2_disabled_repository.h" +#include "common/repositories/zone_points_repository.h" +#include "common/repositories/zone_state_spawns_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "common/types.h" +#include "common/zone_store.h" +#include "zone/aa_ability.h" +#include "zone/global_loot_manager.h" +#include "zone/pathfinder_interface.h" +#include "zone/qglobals.h" +#include "zone/queryserv.h" +#include "zone/spawn2.h" +#include "zone/spawngroup.h" +#include "zone/zonedb.h" struct EXPModifier { @@ -585,5 +585,3 @@ class Zone { std::vector paused_zone_timers; std::deque m_zone_signals; }; - -#endif diff --git a/zone/zone_cli.cpp b/zone/zone_cli.cpp index 59ddee18db..88c310b287 100644 --- a/zone/zone_cli.cpp +++ b/zone/zone_cli.cpp @@ -1,6 +1,8 @@ #include "zone_cli.h" -#include "../common/cli/eqemu_command_handler.h" -#include + +#include "common/cli/eqemu_command_handler.h" + +#include bool ZoneCLI::RanConsoleCommand(int argc, char **argv) { diff --git a/zone/zone_cli.h b/zone/zone_cli.h index 7e5e6e81c0..d9dcfdfe2a 100644 --- a/zone/zone_cli.h +++ b/zone/zone_cli.h @@ -1,8 +1,9 @@ -#ifndef EQEMU_ZONE_CLI_H -#define EQEMU_ZONE_CLI_H -#include -#include "../common/cli/argh.h" +#pragma once + +#include "common/cli/argh.h" + +#include class ZoneCLI { public: @@ -17,5 +18,3 @@ class ZoneCLI { static void TestNpcHandinsMultiQuest(int argc, char **argv, argh::parser &cmd, std::string &description); static void TestZoneState(int argc, char **argv, argh::parser &cmd, std::string &description); }; - -#endif //EQEMU_ZONE_CLI_H diff --git a/zone/zone_config.h b/zone/zone_config.h index e527e06016..b556c7b324 100644 --- a/zone/zone_config.h +++ b/zone/zone_config.h @@ -15,10 +15,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __ZoneConfig_H -#define __ZoneConfig_H -#include "../common/eqemu_config.h" +#pragma once + +#include "common/eqemu_config.h" class ZoneConfig : public EQEmuConfig { public: @@ -59,5 +59,3 @@ class ZoneConfig : public EQEmuConfig { void Dump() const; }; - -#endif diff --git a/zone/zone_event_scheduler.cpp b/zone/zone_event_scheduler.cpp index 8d40e6a446..d6f78f6d5b 100644 --- a/zone/zone_event_scheduler.cpp +++ b/zone/zone_event_scheduler.cpp @@ -1,4 +1,5 @@ #include "zone_event_scheduler.h" + #include void ZoneEventScheduler::Process(Zone *zone, WorldContentService *content_service) diff --git a/zone/zone_event_scheduler.h b/zone/zone_event_scheduler.h index f92442402b..bd996a8ec0 100644 --- a/zone/zone_event_scheduler.h +++ b/zone/zone_event_scheduler.h @@ -1,9 +1,8 @@ -#ifndef EQEMU_ZONE_EVENT_SCHEDULER_H -#define EQEMU_ZONE_EVENT_SCHEDULER_H +#pragma once -#include "../common/server_event_scheduler.h" -#include "zone.h" -#include "../common/content/world_content_service.h" +#include "common/content/world_content_service.h" +#include "common/server_event_scheduler.h" +#include "zone/zone.h" class ZoneEventScheduler : public ServerEventScheduler { public: @@ -16,5 +15,3 @@ class ZoneEventScheduler : public ServerEventScheduler { return &instance; } }; - -#endif //EQEMU_ZONE_EVENT_SCHEDULER_H diff --git a/zone/zone_loot.cpp b/zone/zone_loot.cpp index 9a09bfcadd..076aeb291e 100644 --- a/zone/zone_loot.cpp +++ b/zone/zone_loot.cpp @@ -1,9 +1,11 @@ -#include #include "zone.h" -#include "../common/repositories/loottable_repository.h" -#include "../common/repositories/loottable_entries_repository.h" -#include "../common/repositories/lootdrop_repository.h" -#include "../common/repositories/lootdrop_entries_repository.h" + +#include "common/repositories/lootdrop_entries_repository.h" +#include "common/repositories/lootdrop_repository.h" +#include "common/repositories/loottable_entries_repository.h" +#include "common/repositories/loottable_repository.h" + +#include void Zone::LoadLootTables(const std::vector in_loottable_ids) { diff --git a/zone/zone_npc_factions.cpp b/zone/zone_npc_factions.cpp index 0a37ffb806..b9b07562a1 100644 --- a/zone/zone_npc_factions.cpp +++ b/zone/zone_npc_factions.cpp @@ -1,7 +1,9 @@ -#include #include "zone.h" -#include "../common/repositories/npc_faction_repository.h" -#include "../common/repositories/npc_faction_entries_repository.h" + +#include "common/repositories/npc_faction_entries_repository.h" +#include "common/repositories/npc_faction_repository.h" + +#include void Zone::LoadNPCFactions(const std::vector &npc_faction_ids) { diff --git a/zone/zone_reload.cpp b/zone/zone_reload.cpp index fbe9e55f7f..11adf7eafe 100644 --- a/zone/zone_reload.cpp +++ b/zone/zone_reload.cpp @@ -19,7 +19,8 @@ */ #include "zone_reload.h" -#include "quest_parser_collection.h" + +#include "zone/quest_parser_collection.h" void ZoneReload::HotReloadQuests() { diff --git a/zone/zone_reload.h b/zone/zone_reload.h index 1e4f95826e..0e721f16fd 100644 --- a/zone/zone_reload.h +++ b/zone/zone_reload.h @@ -18,14 +18,9 @@ * */ -#ifndef EQEMU_ZONE_RELOAD_H -#define EQEMU_ZONE_RELOAD_H - +#pragma once class ZoneReload { public: static void HotReloadQuests(); }; - - -#endif //EQEMU_ZONE_RELOAD_H diff --git a/zone/zone_save_state.cpp b/zone/zone_save_state.cpp index f36f3ee1c3..4b1c4c4f23 100644 --- a/zone/zone_save_state.cpp +++ b/zone/zone_save_state.cpp @@ -1,12 +1,14 @@ -#include -#include -#include -#include "npc.h" -#include "corpse.h" -#include "zone.h" #include "zone_save_state.h" -#include "../common/repositories/spawn2_repository.h" -#include "../common/repositories/criteria/content_filter_criteria.h" + +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/spawn2_repository.h" +#include "zone/corpse.h" +#include "zone/npc.h" +#include "zone/zone.h" + +#include "cereal/archives/json.hpp" +#include "cereal/types/map.hpp" +#include // IsZoneStateValid checks if the zone state is valid // if these fields are all empty or zero value for an entire zone state, it's considered invalid diff --git a/zone/zone_save_state.h b/zone/zone_save_state.h index 8d124240b6..cec63750ca 100644 --- a/zone/zone_save_state.h +++ b/zone/zone_save_state.h @@ -1,13 +1,13 @@ #pragma once +#include "common/repositories/spawn2_disabled_repository.h" +#include "common/repositories/zone_state_spawns_repository.h" +#include "zone/corpse.h" +#include "zone/npc.h" +#include "zone/zone.h" +#include "cereal/archives/json.hpp" +#include "cereal/types/map.hpp" #include -#include -#include -#include "npc.h" -#include "corpse.h" -#include "zone.h" -#include "../common/repositories/zone_state_spawns_repository.h" -#include "../common/repositories/spawn2_disabled_repository.h" struct LootEntryStateData { uint32 item_id = 0; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 0dc1436750..a0d6f24bfe 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1,62 +1,60 @@ - -#include "../common/eqemu_logsys.h" -#include "../common/extprofile.h" -#include "../common/rulesys.h" -#include "../common/strings.h" - -#include "client.h" -#include "corpse.h" -#include "groups.h" -#include "merc.h" -#include "zone.h" #include "zonedb.h" -#include "aura.h" -#include "../common/repositories/blocked_spells_repository.h" -#include "../common/repositories/character_tribute_repository.h" -#include "../common/repositories/character_data_repository.h" -#include "../common/repositories/character_disciplines_repository.h" -#include "../common/repositories/npc_types_repository.h" -#include "../common/repositories/character_bind_repository.h" -#include "../common/repositories/character_pet_buffs_repository.h" -#include "../common/repositories/character_pet_inventory_repository.h" -#include "../common/repositories/character_pet_info_repository.h" -#include "../common/repositories/character_buffs_repository.h" -#include "../common/repositories/character_languages_repository.h" -#include "../common/repositories/criteria/content_filter_criteria.h" -#include "../common/repositories/spawn2_disabled_repository.h" -#include "../common/repositories/character_leadership_abilities_repository.h" -#include "../common/repositories/character_material_repository.h" -#include "../common/repositories/character_memmed_spells_repository.h" -#include "../common/repositories/character_spells_repository.h" -#include "../common/repositories/character_skills_repository.h" -#include "../common/repositories/character_potionbelt_repository.h" -#include "../common/repositories/character_bandolier_repository.h" -#include "../common/repositories/character_currency_repository.h" -#include "../common/repositories/character_alternate_abilities_repository.h" -#include "../common/repositories/character_auras_repository.h" -#include "../common/repositories/character_alt_currency_repository.h" -#include "../common/repositories/character_item_recast_repository.h" -#include "../common/repositories/account_repository.h" -#include "../common/repositories/respawn_times_repository.h" -#include "../common/repositories/object_contents_repository.h" -#include "../common/repositories/mercs_repository.h" -#include "../common/repositories/merc_buffs_repository.h" -#include "../common/repositories/merc_inventory_repository.h" -#include "../common/repositories/merc_subtypes_repository.h" -#include "../common/repositories/npc_types_tint_repository.h" -#include "../common/repositories/merchantlist_temp_repository.h" -#include "../common/repositories/character_exp_modifiers_repository.h" -#include "../common/repositories/character_data_repository.h" -#include "../common/repositories/character_corpses_repository.h" -#include "../common/repositories/character_corpse_items_repository.h" -#include "../common/repositories/zone_repository.h" - -#include "../common/repositories/trader_repository.h" -#include "../common/repositories/character_evolving_items_repository.h" +#include "common/eqemu_logsys.h" +#include "common/extprofile.h" +#include "common/repositories/account_repository.h" +#include "common/repositories/blocked_spells_repository.h" +#include "common/repositories/character_alt_currency_repository.h" +#include "common/repositories/character_alternate_abilities_repository.h" +#include "common/repositories/character_auras_repository.h" +#include "common/repositories/character_bandolier_repository.h" +#include "common/repositories/character_bind_repository.h" +#include "common/repositories/character_buffs_repository.h" +#include "common/repositories/character_corpse_items_repository.h" +#include "common/repositories/character_corpses_repository.h" +#include "common/repositories/character_currency_repository.h" +#include "common/repositories/character_data_repository.h" +#include "common/repositories/character_data_repository.h" +#include "common/repositories/character_disciplines_repository.h" +#include "common/repositories/character_evolving_items_repository.h" +#include "common/repositories/character_exp_modifiers_repository.h" +#include "common/repositories/character_item_recast_repository.h" +#include "common/repositories/character_languages_repository.h" +#include "common/repositories/character_leadership_abilities_repository.h" +#include "common/repositories/character_material_repository.h" +#include "common/repositories/character_memmed_spells_repository.h" +#include "common/repositories/character_pet_buffs_repository.h" +#include "common/repositories/character_pet_info_repository.h" +#include "common/repositories/character_pet_inventory_repository.h" +#include "common/repositories/character_potionbelt_repository.h" +#include "common/repositories/character_skills_repository.h" +#include "common/repositories/character_spells_repository.h" +#include "common/repositories/character_tribute_repository.h" +#include "common/repositories/criteria/content_filter_criteria.h" +#include "common/repositories/merc_buffs_repository.h" +#include "common/repositories/merc_inventory_repository.h" +#include "common/repositories/merc_subtypes_repository.h" +#include "common/repositories/merchantlist_temp_repository.h" +#include "common/repositories/mercs_repository.h" +#include "common/repositories/npc_types_repository.h" +#include "common/repositories/npc_types_tint_repository.h" +#include "common/repositories/object_contents_repository.h" +#include "common/repositories/respawn_times_repository.h" +#include "common/repositories/spawn2_disabled_repository.h" +#include "common/repositories/trader_repository.h" +#include "common/repositories/zone_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "zone/aura.h" +#include "zone/client.h" +#include "zone/corpse.h" +#include "zone/groups.h" +#include "zone/merc.h" +#include "zone/zone.h" + +#include "fmt/format.h" #include #include -#include extern Zone* zone; diff --git a/zone/zonedb.h b/zone/zonedb.h index cda0a5ab26..5dee242fbe 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -1,20 +1,19 @@ -#ifndef ZONEDB_H_ -#define ZONEDB_H_ -#include +#pragma once -#include "../common/shareddb.h" -#include "../common/eq_packet_structs.h" -#include "position.h" -#include "../common/faction.h" -#include "../common/eqemu_logsys.h" -#include "aa_ability.h" -#include "event_codes.h" -#include "../common/repositories/doors_repository.h" -#include "../common/races.h" -#include "../common/repositories/npc_faction_entries_repository.h" +#include "common/eq_packet_structs.h" +#include "common/eqemu_logsys.h" +#include "common/faction.h" +#include "common/races.h" +#include "common/repositories/doors_repository.h" +#include "common/repositories/npc_faction_entries_repository.h" +#include "common/shareddb.h" +#include "zone/aa_ability.h" +#include "zone/bot_database.h" +#include "zone/event_codes.h" +#include "zone/position.h" -#include "bot_database.h" +#include class Client; class Corpse; @@ -674,6 +673,3 @@ class ZoneDatabase : public SharedDatabase { extern ZoneDatabase database; extern ZoneDatabase content_db; - -#endif /*ZONEDB_H_*/ - diff --git a/zone/zonedump.h b/zone/zonedump.h index 5d29a252b9..e811a61fad 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -24,12 +24,13 @@ npc_count int unsigned not null default 0, npcloot_count int unsigned not null d spawn2 mediumblob, npcs mediumblob, npc_loot mediumblob, gmspawntype mediumblob, time timestamp(14)); */ -#ifndef ZONEDUMP_H -#define ZONEDUMP_H -#include "../common/faction.h" -#include "../common/eq_packet_structs.h" -#include "../common/inventory_profile.h" +#pragma once +#include "common/faction.h" +#include "common/eq_packet_structs.h" +#include "common/inventory_profile.h" + +#pragma pack(push) #pragma pack(1) struct NPCType @@ -160,6 +161,4 @@ struct NPCType uint32 m_npc_tint_id; }; -#pragma pack() - -#endif +#pragma pack(pop) diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 96ad15dbc6..46bd4849c6 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -16,29 +16,26 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/global_define.h" -#include "../common/eqemu_logsys.h" -#include "../common/rulesys.h" -#include "../common/strings.h" - -#include "dynamic_zone.h" -#include "queryserv.h" -#include "quest_parser_collection.h" -#include "string_ids.h" -#include "worldserver.h" -#include "zone.h" - -#include "bot.h" +#include "client.h" + +#include "common/eqemu_logsys.h" +#include "common/events/player_event_logs.h" +#include "common/repositories/character_peqzone_flags_repository.h" +#include "common/repositories/zone_flags_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "zone/bot.h" +#include "zone/dynamic_zone.h" +#include "zone/queryserv.h" +#include "zone/quest_parser_collection.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" +#include "zone/zone.h" extern QueryServ* QServ; extern WorldServer worldserver; extern Zone* zone; -#include "../common/repositories/character_peqzone_flags_repository.h" -#include "../common/repositories/zone_flags_repository.h" -#include "../common/events/player_event_logs.h" - - void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { if (RuleB(Bots, Enabled)) { Bot::ProcessClientZoneChange(this); From d6f4904351394d8c6792b9cc63b3e2240940c58d Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 01:02:34 -0800 Subject: [PATCH 081/194] normalize includes: bot commands --- zone/bot_commands/bot_actionable.cpp | 2 +- zone/bot_commands/bot_appearance.cpp | 2 +- zone/bot_commands/bot_apply_poison.cpp | 2 +- zone/bot_commands/bot_apply_potion.cpp | 2 +- zone/bot_commands/bot_attack.cpp | 2 +- zone/bot_commands/bot_behind_mob.cpp | 2 +- zone/bot_commands/bot_blocked_buffs.cpp | 2 +- zone/bot_commands/bot_bot.cpp | 2 +- zone/bot_commands/bot_bot_settings.cpp | 2 +- zone/bot_commands/bot_cast.cpp | 2 +- zone/bot_commands/bot_class_race_list.cpp | 2 +- zone/bot_commands/bot_click_item.cpp | 2 +- zone/bot_commands/bot_copy_settings.cpp | 2 +- zone/bot_commands/bot_default_settings.cpp | 2 +- zone/bot_commands/bot_depart.cpp | 2 +- zone/bot_commands/bot_discipline.cpp | 2 +- zone/bot_commands/bot_distance_ranged.cpp | 2 +- zone/bot_commands/bot_find_aliases.cpp | 2 +- zone/bot_commands/bot_follow.cpp | 2 +- zone/bot_commands/bot_guard.cpp | 2 +- zone/bot_commands/bot_heal_rotation.cpp | 2 +- zone/bot_commands/bot_help.cpp | 2 +- zone/bot_commands/bot_hold.cpp | 2 +- zone/bot_commands/bot_illusion_block.cpp | 2 +- zone/bot_commands/bot_inventory.cpp | 2 +- zone/bot_commands/bot_item_use.cpp | 2 +- zone/bot_commands/bot_max_melee_range.cpp | 2 +- zone/bot_commands/bot_name.cpp | 2 +- zone/bot_commands/bot_owner_option.cpp | 2 +- zone/bot_commands/bot_pet.cpp | 4 ++-- zone/bot_commands/bot_pick_lock.cpp | 4 ++-- zone/bot_commands/bot_pickpocket.cpp | 2 +- zone/bot_commands/bot_precombat.cpp | 2 +- zone/bot_commands/bot_pull.cpp | 2 +- zone/bot_commands/bot_release.cpp | 2 +- zone/bot_commands/bot_set_assistee.cpp | 2 +- zone/bot_commands/bot_sit_hp_percent.cpp | 2 +- zone/bot_commands/bot_sit_in_combat.cpp | 2 +- zone/bot_commands/bot_sit_mana_percent.cpp | 2 +- zone/bot_commands/bot_spell.cpp | 2 +- zone/bot_commands/bot_spell_aggro_checks.cpp | 2 +- zone/bot_commands/bot_spell_announce_cast.cpp | 2 +- zone/bot_commands/bot_spell_delays.cpp | 2 +- zone/bot_commands/bot_spell_engaged_priority.cpp | 2 +- zone/bot_commands/bot_spell_holds.cpp | 2 +- zone/bot_commands/bot_spell_idle_priority.cpp | 2 +- zone/bot_commands/bot_spell_max_hp_pct.cpp | 2 +- zone/bot_commands/bot_spell_max_mana_pct.cpp | 2 +- zone/bot_commands/bot_spell_max_thresholds.cpp | 2 +- zone/bot_commands/bot_spell_min_hp_pct.cpp | 2 +- zone/bot_commands/bot_spell_min_mana_pct.cpp | 2 +- zone/bot_commands/bot_spell_min_thresholds.cpp | 2 +- zone/bot_commands/bot_spell_pursue_priority.cpp | 2 +- zone/bot_commands/bot_spell_resist_limits.cpp | 2 +- zone/bot_commands/bot_spell_target_count.cpp | 2 +- zone/bot_commands/bot_spelltypes.cpp | 2 ++ zone/bot_commands/bot_summon.cpp | 1 - zone/bot_commands/bot_suspend.cpp | 2 +- zone/bot_commands/bot_taunt.cpp | 2 +- zone/bot_commands/bot_timer.cpp | 2 +- zone/bot_commands/bot_track.cpp | 2 +- zone/bot_commands/bot_view_combos.cpp | 2 +- 62 files changed, 64 insertions(+), 63 deletions(-) delete mode 100644 zone/bot_commands/bot_summon.cpp diff --git a/zone/bot_commands/bot_actionable.cpp b/zone/bot_commands/bot_actionable.cpp index 94ed0b0c3b..c98e89edf3 100644 --- a/zone/bot_commands/bot_actionable.cpp +++ b/zone/bot_commands/bot_actionable.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_actionable(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_appearance.cpp b/zone/bot_commands/bot_appearance.cpp index 6707baea21..20b8cd8116 100644 --- a/zone/bot_commands/bot_appearance.cpp +++ b/zone/bot_commands/bot_appearance.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_appearance(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_apply_poison.cpp b/zone/bot_commands/bot_apply_poison.cpp index 444e370ed9..c6869ab98e 100644 --- a/zone/bot_commands/bot_apply_poison.cpp +++ b/zone/bot_commands/bot_apply_poison.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_apply_poison(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_apply_potion.cpp b/zone/bot_commands/bot_apply_potion.cpp index 2d27713c38..cbf9d1e80e 100644 --- a/zone/bot_commands/bot_apply_potion.cpp +++ b/zone/bot_commands/bot_apply_potion.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_apply_potion(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_attack.cpp b/zone/bot_commands/bot_attack.cpp index f91902d4c4..6183b5853f 100644 --- a/zone/bot_commands/bot_attack.cpp +++ b/zone/bot_commands/bot_attack.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_attack(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_behind_mob.cpp b/zone/bot_commands/bot_behind_mob.cpp index 48712a2e60..c96565ae28 100644 --- a/zone/bot_commands/bot_behind_mob.cpp +++ b/zone/bot_commands/bot_behind_mob.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_behind_mob(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_blocked_buffs.cpp b/zone/bot_commands/bot_blocked_buffs.cpp index 3b4ea56236..17b5fffc3c 100644 --- a/zone/bot_commands/bot_blocked_buffs.cpp +++ b/zone/bot_commands/bot_blocked_buffs.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_blocked_buffs(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_bot.cpp b/zone/bot_commands/bot_bot.cpp index 2d37c503a4..f1af6b4d63 100644 --- a/zone/bot_commands/bot_bot.cpp +++ b/zone/bot_commands/bot_bot.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_bot(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_bot_settings.cpp b/zone/bot_commands/bot_bot_settings.cpp index 98c4dccd75..55ccd32f41 100644 --- a/zone/bot_commands/bot_bot_settings.cpp +++ b/zone/bot_commands/bot_bot_settings.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_bot_settings(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_cast.cpp b/zone/bot_commands/bot_cast.cpp index 19368992c5..62499efaf8 100644 --- a/zone/bot_commands/bot_cast.cpp +++ b/zone/bot_commands/bot_cast.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_cast(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_class_race_list.cpp b/zone/bot_commands/bot_class_race_list.cpp index 84c611ab38..d076dbc711 100644 --- a/zone/bot_commands/bot_class_race_list.cpp +++ b/zone/bot_commands/bot_class_race_list.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_class_race_list(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_click_item.cpp b/zone/bot_commands/bot_click_item.cpp index 4927418214..cc7aa07584 100644 --- a/zone/bot_commands/bot_click_item.cpp +++ b/zone/bot_commands/bot_click_item.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_click_item(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_copy_settings.cpp b/zone/bot_commands/bot_copy_settings.cpp index ef9d3a8fd9..2b91de9558 100644 --- a/zone/bot_commands/bot_copy_settings.cpp +++ b/zone/bot_commands/bot_copy_settings.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_copy_settings(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_default_settings.cpp b/zone/bot_commands/bot_default_settings.cpp index 030eb028e7..8450ebeece 100644 --- a/zone/bot_commands/bot_default_settings.cpp +++ b/zone/bot_commands/bot_default_settings.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_default_settings(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_depart.cpp b/zone/bot_commands/bot_depart.cpp index 0a560e59c1..3175063518 100644 --- a/zone/bot_commands/bot_depart.cpp +++ b/zone/bot_commands/bot_depart.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_depart(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_discipline.cpp b/zone/bot_commands/bot_discipline.cpp index 570bdc56fa..1c9d6d51e7 100644 --- a/zone/bot_commands/bot_discipline.cpp +++ b/zone/bot_commands/bot_discipline.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_discipline(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_distance_ranged.cpp b/zone/bot_commands/bot_distance_ranged.cpp index 9ce66bf6cc..bc585b2fc7 100644 --- a/zone/bot_commands/bot_distance_ranged.cpp +++ b/zone/bot_commands/bot_distance_ranged.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_distance_ranged(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_find_aliases.cpp b/zone/bot_commands/bot_find_aliases.cpp index db8fcbfc90..949bdd9f73 100644 --- a/zone/bot_commands/bot_find_aliases.cpp +++ b/zone/bot_commands/bot_find_aliases.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_find_aliases(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_follow.cpp b/zone/bot_commands/bot_follow.cpp index fe780d32eb..c66a131b11 100644 --- a/zone/bot_commands/bot_follow.cpp +++ b/zone/bot_commands/bot_follow.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_follow(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_guard.cpp b/zone/bot_commands/bot_guard.cpp index 3138914eea..f931cd38f4 100644 --- a/zone/bot_commands/bot_guard.cpp +++ b/zone/bot_commands/bot_guard.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_guard(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_heal_rotation.cpp b/zone/bot_commands/bot_heal_rotation.cpp index 2ffd6df23b..32f7c9e5b7 100644 --- a/zone/bot_commands/bot_heal_rotation.cpp +++ b/zone/bot_commands/bot_heal_rotation.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_heal_rotation(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_help.cpp b/zone/bot_commands/bot_help.cpp index d2b143ee77..00a50cec71 100644 --- a/zone/bot_commands/bot_help.cpp +++ b/zone/bot_commands/bot_help.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_help(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_hold.cpp b/zone/bot_commands/bot_hold.cpp index 4d79fcce73..82b63479b1 100644 --- a/zone/bot_commands/bot_hold.cpp +++ b/zone/bot_commands/bot_hold.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_hold(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_illusion_block.cpp b/zone/bot_commands/bot_illusion_block.cpp index 01c9eafa46..65446a8519 100644 --- a/zone/bot_commands/bot_illusion_block.cpp +++ b/zone/bot_commands/bot_illusion_block.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_illusion_block(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_inventory.cpp b/zone/bot_commands/bot_inventory.cpp index 9d8511cf9d..9df63b86ec 100644 --- a/zone/bot_commands/bot_inventory.cpp +++ b/zone/bot_commands/bot_inventory.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_inventory(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_item_use.cpp b/zone/bot_commands/bot_item_use.cpp index b9cf6a803a..6550c7f0d8 100644 --- a/zone/bot_commands/bot_item_use.cpp +++ b/zone/bot_commands/bot_item_use.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_item_use(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_max_melee_range.cpp b/zone/bot_commands/bot_max_melee_range.cpp index 6f4630ab52..290703cb18 100644 --- a/zone/bot_commands/bot_max_melee_range.cpp +++ b/zone/bot_commands/bot_max_melee_range.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_max_melee_range(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_name.cpp b/zone/bot_commands/bot_name.cpp index 688b15bbf5..6801ad46f6 100644 --- a/zone/bot_commands/bot_name.cpp +++ b/zone/bot_commands/bot_name.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_surname(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_owner_option.cpp b/zone/bot_commands/bot_owner_option.cpp index 8ae597798b..70b8e36161 100644 --- a/zone/bot_commands/bot_owner_option.cpp +++ b/zone/bot_commands/bot_owner_option.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_owner_option(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_pet.cpp b/zone/bot_commands/bot_pet.cpp index d47726e5c0..74cad7b3d1 100644 --- a/zone/bot_commands/bot_pet.cpp +++ b/zone/bot_commands/bot_pet.cpp @@ -1,5 +1,5 @@ -#include "../bot_command.h" -#include "../bot.h" +#include "zone/bot_command.h" +#include "zone/bot.h" void bot_command_pet(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_pick_lock.cpp b/zone/bot_commands/bot_pick_lock.cpp index 49096a8f56..bf66cd2238 100644 --- a/zone/bot_commands/bot_pick_lock.cpp +++ b/zone/bot_commands/bot_pick_lock.cpp @@ -1,5 +1,5 @@ -#include "../bot_command.h" -#include "../doors.h" +#include "zone/bot_command.h" +#include "zone/doors.h" void bot_command_pick_lock(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_pickpocket.cpp b/zone/bot_commands/bot_pickpocket.cpp index 8b5339cca1..8bb227fece 100644 --- a/zone/bot_commands/bot_pickpocket.cpp +++ b/zone/bot_commands/bot_pickpocket.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_pickpocket(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_precombat.cpp b/zone/bot_commands/bot_precombat.cpp index a059e8eb1e..c8046bee21 100644 --- a/zone/bot_commands/bot_precombat.cpp +++ b/zone/bot_commands/bot_precombat.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_precombat(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_pull.cpp b/zone/bot_commands/bot_pull.cpp index 6bab8b0a68..6fd0a267a2 100644 --- a/zone/bot_commands/bot_pull.cpp +++ b/zone/bot_commands/bot_pull.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_pull(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_release.cpp b/zone/bot_commands/bot_release.cpp index 36f5df96ab..d20d6c2227 100644 --- a/zone/bot_commands/bot_release.cpp +++ b/zone/bot_commands/bot_release.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_release(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_set_assistee.cpp b/zone/bot_commands/bot_set_assistee.cpp index f5a1845fea..e70513ea4f 100644 --- a/zone/bot_commands/bot_set_assistee.cpp +++ b/zone/bot_commands/bot_set_assistee.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_set_assistee(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_sit_hp_percent.cpp b/zone/bot_commands/bot_sit_hp_percent.cpp index 0843aa5b92..6e2d6d9a4e 100644 --- a/zone/bot_commands/bot_sit_hp_percent.cpp +++ b/zone/bot_commands/bot_sit_hp_percent.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_sit_hp_percent(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_sit_in_combat.cpp b/zone/bot_commands/bot_sit_in_combat.cpp index 07a2f917e4..bde5a71ac2 100644 --- a/zone/bot_commands/bot_sit_in_combat.cpp +++ b/zone/bot_commands/bot_sit_in_combat.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_sit_in_combat(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_sit_mana_percent.cpp b/zone/bot_commands/bot_sit_mana_percent.cpp index e85d976c89..c66427bbc9 100644 --- a/zone/bot_commands/bot_sit_mana_percent.cpp +++ b/zone/bot_commands/bot_sit_mana_percent.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_sit_mana_percent(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell.cpp b/zone/bot_commands/bot_spell.cpp index 833c8ef7ab..cc18e1cb22 100644 --- a/zone/bot_commands/bot_spell.cpp +++ b/zone/bot_commands/bot_spell.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_list(Client* c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_spell_aggro_checks.cpp b/zone/bot_commands/bot_spell_aggro_checks.cpp index 41ae404447..8ba6415de0 100644 --- a/zone/bot_commands/bot_spell_aggro_checks.cpp +++ b/zone/bot_commands/bot_spell_aggro_checks.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_aggro_checks(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_announce_cast.cpp b/zone/bot_commands/bot_spell_announce_cast.cpp index cb8f06d954..ecbd4cf462 100644 --- a/zone/bot_commands/bot_spell_announce_cast.cpp +++ b/zone/bot_commands/bot_spell_announce_cast.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_announce_cast(Client* c, const Seperator* sep) { if (helper_command_alias_fail(c, "bot_command_spell_announce_cast", sep->arg[0], "spellannouncecasts")) { diff --git a/zone/bot_commands/bot_spell_delays.cpp b/zone/bot_commands/bot_spell_delays.cpp index 98efb3f225..31225491e5 100644 --- a/zone/bot_commands/bot_spell_delays.cpp +++ b/zone/bot_commands/bot_spell_delays.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_delays(Client* c, const Seperator* sep) { if (helper_command_alias_fail(c, "bot_command_spell_delays", sep->arg[0], "spelldelays")) { diff --git a/zone/bot_commands/bot_spell_engaged_priority.cpp b/zone/bot_commands/bot_spell_engaged_priority.cpp index 8f7c0afa9d..92622f9114 100644 --- a/zone/bot_commands/bot_spell_engaged_priority.cpp +++ b/zone/bot_commands/bot_spell_engaged_priority.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_engaged_priority(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_holds.cpp b/zone/bot_commands/bot_spell_holds.cpp index 26d42ad823..ed627644a3 100644 --- a/zone/bot_commands/bot_spell_holds.cpp +++ b/zone/bot_commands/bot_spell_holds.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_holds(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_idle_priority.cpp b/zone/bot_commands/bot_spell_idle_priority.cpp index 881fd5e980..f5a9843d47 100644 --- a/zone/bot_commands/bot_spell_idle_priority.cpp +++ b/zone/bot_commands/bot_spell_idle_priority.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_idle_priority(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_max_hp_pct.cpp b/zone/bot_commands/bot_spell_max_hp_pct.cpp index 249e9179d8..8802a2c091 100644 --- a/zone/bot_commands/bot_spell_max_hp_pct.cpp +++ b/zone/bot_commands/bot_spell_max_hp_pct.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_max_hp_pct(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_max_mana_pct.cpp b/zone/bot_commands/bot_spell_max_mana_pct.cpp index ab42ce8a5e..a5a72bdf09 100644 --- a/zone/bot_commands/bot_spell_max_mana_pct.cpp +++ b/zone/bot_commands/bot_spell_max_mana_pct.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_max_mana_pct(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_max_thresholds.cpp b/zone/bot_commands/bot_spell_max_thresholds.cpp index ca7f78aa32..72be87a865 100644 --- a/zone/bot_commands/bot_spell_max_thresholds.cpp +++ b/zone/bot_commands/bot_spell_max_thresholds.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_max_thresholds(Client* c, const Seperator* sep) { if (helper_command_alias_fail(c, "bot_command_spell_max_thresholds", sep->arg[0], "spellmaxthresholds")) { diff --git a/zone/bot_commands/bot_spell_min_hp_pct.cpp b/zone/bot_commands/bot_spell_min_hp_pct.cpp index 61d6313e37..05f5f2afce 100644 --- a/zone/bot_commands/bot_spell_min_hp_pct.cpp +++ b/zone/bot_commands/bot_spell_min_hp_pct.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_min_hp_pct(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_min_mana_pct.cpp b/zone/bot_commands/bot_spell_min_mana_pct.cpp index 71672cee9e..8f562a55f4 100644 --- a/zone/bot_commands/bot_spell_min_mana_pct.cpp +++ b/zone/bot_commands/bot_spell_min_mana_pct.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_min_mana_pct(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_min_thresholds.cpp b/zone/bot_commands/bot_spell_min_thresholds.cpp index ba614530c1..6ad3127456 100644 --- a/zone/bot_commands/bot_spell_min_thresholds.cpp +++ b/zone/bot_commands/bot_spell_min_thresholds.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_min_thresholds(Client* c, const Seperator* sep) { if (helper_command_alias_fail(c, "bot_command_spell_min_thresholds", sep->arg[0], "spellminthresholds")) { diff --git a/zone/bot_commands/bot_spell_pursue_priority.cpp b/zone/bot_commands/bot_spell_pursue_priority.cpp index 2b395d74fb..8b4e8e373c 100644 --- a/zone/bot_commands/bot_spell_pursue_priority.cpp +++ b/zone/bot_commands/bot_spell_pursue_priority.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_pursue_priority(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_resist_limits.cpp b/zone/bot_commands/bot_spell_resist_limits.cpp index e7c928c338..8a9272e789 100644 --- a/zone/bot_commands/bot_spell_resist_limits.cpp +++ b/zone/bot_commands/bot_spell_resist_limits.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_resist_limits(Client* c, const Seperator* sep) { if (helper_command_alias_fail(c, "bot_command_spell_resist_limits", sep->arg[0], "spellresistlimits")) { diff --git a/zone/bot_commands/bot_spell_target_count.cpp b/zone/bot_commands/bot_spell_target_count.cpp index ad938d9b52..3fd4b7496b 100644 --- a/zone/bot_commands/bot_spell_target_count.cpp +++ b/zone/bot_commands/bot_spell_target_count.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_spell_target_count(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spelltypes.cpp b/zone/bot_commands/bot_spelltypes.cpp index f91b3ed7e1..204778a1ba 100644 --- a/zone/bot_commands/bot_spelltypes.cpp +++ b/zone/bot_commands/bot_spelltypes.cpp @@ -1,3 +1,5 @@ +#include "zone/bot_command.h" + void bot_command_spelltype_ids(Client* c, const Seperator* sep) { SendSpellTypeWindow(c, sep); diff --git a/zone/bot_commands/bot_summon.cpp b/zone/bot_commands/bot_summon.cpp deleted file mode 100644 index dc2b7d8685..0000000000 --- a/zone/bot_commands/bot_summon.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "../bot_command.h" diff --git a/zone/bot_commands/bot_suspend.cpp b/zone/bot_commands/bot_suspend.cpp index 63c728fd3d..fcdabbd699 100644 --- a/zone/bot_commands/bot_suspend.cpp +++ b/zone/bot_commands/bot_suspend.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_suspend(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_taunt.cpp b/zone/bot_commands/bot_taunt.cpp index 72391b2d3a..2eb4b1c7ea 100644 --- a/zone/bot_commands/bot_taunt.cpp +++ b/zone/bot_commands/bot_taunt.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_taunt(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_timer.cpp b/zone/bot_commands/bot_timer.cpp index 99ad38001b..6413a9e9b0 100644 --- a/zone/bot_commands/bot_timer.cpp +++ b/zone/bot_commands/bot_timer.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_timer(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_track.cpp b/zone/bot_commands/bot_track.cpp index 18a21679a6..1a0c1ce576 100644 --- a/zone/bot_commands/bot_track.cpp +++ b/zone/bot_commands/bot_track.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_track(Client *c, const Seperator *sep) { diff --git a/zone/bot_commands/bot_view_combos.cpp b/zone/bot_commands/bot_view_combos.cpp index 7a44e53805..d8da5a3494 100644 --- a/zone/bot_commands/bot_view_combos.cpp +++ b/zone/bot_commands/bot_view_combos.cpp @@ -1,4 +1,4 @@ -#include "../bot_command.h" +#include "zone/bot_command.h" void bot_command_view_combos(Client *c, const Seperator *sep) { From 2af5f99fffc8cc47fbc4edc05362036d29a4ccc3 Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 01:03:02 -0800 Subject: [PATCH 082/194] normalize includes: loginserver --- loginserver/account_management.cpp | 3 +++ loginserver/account_management.h | 3 ++- loginserver/client.h | 20 ++++++++------------ loginserver/client_manager.h | 1 - loginserver/encryption.h | 2 +- loginserver/login_server.h | 3 --- loginserver/loginserver_webserver.h | 1 - loginserver/main.cpp | 7 +------ loginserver/world_server.h | 1 - loginserver/world_server_manager.cpp | 3 +-- loginserver/world_server_manager.h | 1 - 11 files changed, 16 insertions(+), 29 deletions(-) diff --git a/loginserver/account_management.cpp b/loginserver/account_management.cpp index 314fb44920..d7e85072ba 100644 --- a/loginserver/account_management.cpp +++ b/loginserver/account_management.cpp @@ -1,7 +1,10 @@ #include "account_management.h" +#include "common/event/event_loop.h" #include "common/event/task_scheduler.h" +#include "common/net/dns.h" #include "common/repositories/login_accounts_repository.h" +#include "common/types.h" #include "loginserver/login_server.h" EQ::Event::TaskScheduler task_runner; diff --git a/loginserver/account_management.h b/loginserver/account_management.h index 7f23c8775e..3a0edc5e68 100644 --- a/loginserver/account_management.h +++ b/loginserver/account_management.h @@ -2,9 +2,10 @@ #include "common/types.h" #include "loginserver/login_types.h" -#include "loginserver/encryption.h" #include "loginserver/login_server.h" +#include + extern LoginServer server; extern Database database; diff --git a/loginserver/client.h b/loginserver/client.h index 75d972f925..5baa4eebe7 100644 --- a/loginserver/client.h +++ b/loginserver/client.h @@ -1,13 +1,12 @@ -#ifndef EQEMU_CLIENT_H -#define EQEMU_CLIENT_H +#pragma once + +#include "common/eq_stream_intf.h" +#include "common/net/reliable_stream_connection.h" +#include "common/opcodemgr.h" +#include "common/random.h" +#include "common/repositories/login_accounts_repository.h" +#include "loginserver/login_types.h" -#include "../common/opcodemgr.h" -#include "../common/random.h" -#include "../common/eq_stream_intf.h" -#include "../common/net/dns.h" -#include "../common/net/reliable_stream_connection.h" -#include "login_types.h" -#include "../common/repositories/login_accounts_repository.h" #include class Client { @@ -62,6 +61,3 @@ class Client { return username == "healthcheckuser"; } }; - -#endif - diff --git a/loginserver/client_manager.h b/loginserver/client_manager.h index 3171fdccac..c98313fbf0 100644 --- a/loginserver/client_manager.h +++ b/loginserver/client_manager.h @@ -1,7 +1,6 @@ #pragma once #include "common/net/eqstream.h" -#include "common/opcodemgr.h" #include "loginserver/client.h" #include diff --git a/loginserver/encryption.h b/loginserver/encryption.h index 0ebb3e1fd9..b4b9242abd 100644 --- a/loginserver/encryption.h +++ b/loginserver/encryption.h @@ -41,7 +41,7 @@ struct EncryptionResult { std::string mode_name; }; -static EncryptionResult EncryptPasswordFromContext(LoginAccountContext c, int mode = EncryptionModeSCrypt) +inline EncryptionResult EncryptPasswordFromContext(LoginAccountContext c, int mode = EncryptionModeSCrypt) { if (mode == 0) { LogError("Encryption mode not set!"); diff --git a/loginserver/login_server.h b/loginserver/login_server.h index 0602ba528d..4d006ac7b6 100644 --- a/loginserver/login_server.h +++ b/loginserver/login_server.h @@ -2,13 +2,10 @@ #include "common/json_config.h" #include "loginserver/client_manager.h" -#include "loginserver/encryption.h" #include "loginserver/loginserver_webserver.h" #include "loginserver/options.h" #include "loginserver/world_server_manager.h" -#include - struct LoginServer { public: diff --git a/loginserver/loginserver_webserver.h b/loginserver/loginserver_webserver.h index dba59824ca..18972cbcb1 100644 --- a/loginserver/loginserver_webserver.h +++ b/loginserver/loginserver_webserver.h @@ -2,7 +2,6 @@ #include "common/http/httplib.h" #include "common/json/json.h" -#include "common/types.h" namespace LoginserverWebserver { diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 636118d02a..2aae375280 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -2,24 +2,19 @@ #include "common/database.h" #include "common/eqemu_logsys.h" #include "common/event/event_loop.h" +#include "common/event/timer.h" #include "common/events/player_event_logs.h" #include "common/http/httplib.h" -#include "common/opcodemgr.h" #include "common/path_manager.h" #include "common/platform.h" -#include "common/strings.h" #include "common/timer.h" #include "common/types.h" -#include "common/zone_store.h" #include "loginserver/login_server.h" #include "loginserver/loginserver_command_handler.h" #include "loginserver/loginserver_webserver.h" -#include -#include #include #include -#include LoginServer server; bool run_server = true; diff --git a/loginserver/world_server.h b/loginserver/world_server.h index 5cd5043105..94ed4b4a72 100644 --- a/loginserver/world_server.h +++ b/loginserver/world_server.h @@ -1,6 +1,5 @@ #pragma once -#include "common/event/timer.h" #include "common/net/servertalk_server_connection.h" #include "common/packet_dump.h" #include "common/repositories/login_server_admins_repository.h" diff --git a/loginserver/world_server_manager.cpp b/loginserver/world_server_manager.cpp index 9c12190719..fdf917e7ed 100644 --- a/loginserver/world_server_manager.cpp +++ b/loginserver/world_server_manager.cpp @@ -3,9 +3,8 @@ #include "common/eqemu_logsys.h" #include "common/ip_util.h" #include "loginserver/login_server.h" -#include "loginserver/login_types.h" -#include +#include extern LoginServer server; extern bool run_server; diff --git a/loginserver/world_server_manager.h b/loginserver/world_server_manager.h index 6ed6ed96c6..1885b16698 100644 --- a/loginserver/world_server_manager.h +++ b/loginserver/world_server_manager.h @@ -2,7 +2,6 @@ #include "common/net/servertalk_server.h" #include "common/packet_dump.h" -#include "common/servertalk.h" #include "loginserver/client.h" #include "loginserver/world_server.h" From 2bff404d229087db29c8edc7fd13c36a04d6b79f Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 01:06:22 -0800 Subject: [PATCH 083/194] normalize includes: gm commands --- utils/gm_commands/main.go | 183 ------------------ zone/gm_commands/acceptrules.cpp | 2 +- zone/gm_commands/advnpcspawn.cpp | 4 +- zone/gm_commands/aggrozone.cpp | 2 +- zone/gm_commands/ai.cpp | 2 +- zone/gm_commands/appearance.cpp | 2 +- zone/gm_commands/appearanceeffects.cpp | 2 +- zone/gm_commands/attack.cpp | 2 +- zone/gm_commands/augmentitem.cpp | 4 +- zone/gm_commands/ban.cpp | 4 +- zone/gm_commands/bugs.cpp | 4 +- zone/gm_commands/camerashake.cpp | 4 +- zone/gm_commands/castspell.cpp | 2 +- zone/gm_commands/chat.cpp | 4 +- zone/gm_commands/clearxtargets.cpp | 2 +- zone/gm_commands/copycharacter.cpp | 2 +- zone/gm_commands/corpse.cpp | 4 +- zone/gm_commands/corpsefix.cpp | 4 +- zone/gm_commands/countitem.cpp | 2 +- zone/gm_commands/damage.cpp | 2 +- zone/gm_commands/databuckets.cpp | 8 +- zone/gm_commands/dbspawn2.cpp | 2 +- zone/gm_commands/delacct.cpp | 4 +- zone/gm_commands/delpetition.cpp | 2 +- zone/gm_commands/depop.cpp | 4 +- zone/gm_commands/depopzone.cpp | 2 +- zone/gm_commands/devtools.cpp | 4 +- zone/gm_commands/disablerecipe.cpp | 2 +- zone/gm_commands/disarmtrap.cpp | 2 +- zone/gm_commands/doanim.cpp | 4 +- zone/gm_commands/door.cpp | 3 +- zone/gm_commands/door_manipulation.cpp | 7 +- zone/gm_commands/door_manipulation.h | 10 +- zone/gm_commands/dye.cpp | 2 +- zone/gm_commands/dz.cpp | 4 +- zone/gm_commands/dzkickplayers.cpp | 3 +- zone/gm_commands/editmassrespawn.cpp | 2 +- zone/gm_commands/emote.cpp | 4 +- zone/gm_commands/emptyinventory.cpp | 2 +- zone/gm_commands/enablerecipe.cpp | 2 +- zone/gm_commands/entityvariable.cpp | 2 +- zone/gm_commands/evolving_items.cpp | 6 +- zone/gm_commands/exptoggle.cpp | 2 +- zone/gm_commands/faction.cpp | 2 +- zone/gm_commands/faction_association.cpp | 2 +- zone/gm_commands/feature.cpp | 2 +- zone/gm_commands/find.cpp | 2 +- zone/gm_commands/find/find_aa.cpp | 3 +- zone/gm_commands/find/find_account.cpp | 4 +- zone/gm_commands/find/find_body_type.cpp | 2 +- zone/gm_commands/find/find_bot.cpp | 4 +- zone/gm_commands/find/find_bug_category.cpp | 2 +- zone/gm_commands/find/find_character.cpp | 4 +- zone/gm_commands/find/find_class.cpp | 2 +- .../gm_commands/find/find_comparison_type.cpp | 2 +- zone/gm_commands/find/find_currency.cpp | 3 +- zone/gm_commands/find/find_deity.cpp | 2 +- zone/gm_commands/find/find_emote.cpp | 2 +- zone/gm_commands/find/find_faction.cpp | 2 +- zone/gm_commands/find/find_item.cpp | 4 +- zone/gm_commands/find/find_language.cpp | 2 +- zone/gm_commands/find/find_ldon_theme.cpp | 2 +- zone/gm_commands/find/find_npctype.cpp | 3 +- zone/gm_commands/find/find_object_type.cpp | 4 +- zone/gm_commands/find/find_race.cpp | 2 +- zone/gm_commands/find/find_recipe.cpp | 6 +- zone/gm_commands/find/find_skill.cpp | 2 +- .../gm_commands/find/find_special_ability.cpp | 2 +- zone/gm_commands/find/find_spell.cpp | 2 +- zone/gm_commands/find/find_stance.cpp | 2 +- zone/gm_commands/find/find_task.cpp | 2 +- zone/gm_commands/find/find_zone.cpp | 4 +- zone/gm_commands/fish.cpp | 2 +- zone/gm_commands/fixmob.cpp | 2 +- zone/gm_commands/flagedit.cpp | 2 +- zone/gm_commands/fleeinfo.cpp | 2 +- zone/gm_commands/forage.cpp | 2 +- zone/gm_commands/gearup.cpp | 8 +- zone/gm_commands/giveitem.cpp | 2 +- zone/gm_commands/givemoney.cpp | 2 +- zone/gm_commands/gmzone.cpp | 4 +- zone/gm_commands/goto.cpp | 2 +- zone/gm_commands/grantaa.cpp | 2 +- zone/gm_commands/grid.cpp | 4 +- zone/gm_commands/guild.cpp | 13 +- zone/gm_commands/hp.cpp | 2 +- zone/gm_commands/illusion_block.cpp | 4 +- zone/gm_commands/instance.cpp | 2 +- zone/gm_commands/interrogateinv.cpp | 2 +- zone/gm_commands/interrupt.cpp | 2 +- zone/gm_commands/invsnapshot.cpp | 2 +- zone/gm_commands/ipban.cpp | 2 +- zone/gm_commands/kick.cpp | 4 +- zone/gm_commands/kill.cpp | 2 +- zone/gm_commands/killallnpcs.cpp | 2 +- zone/gm_commands/list.cpp | 10 +- zone/gm_commands/loc.cpp | 4 +- zone/gm_commands/logs.cpp | 4 +- zone/gm_commands/lootsim.cpp | 2 +- zone/gm_commands/makepet.cpp | 2 +- zone/gm_commands/memspell.cpp | 2 +- zone/gm_commands/merchantshop.cpp | 2 +- zone/gm_commands/modifynpcstat.cpp | 2 +- zone/gm_commands/movechar.cpp | 2 +- zone/gm_commands/movement.cpp | 4 +- zone/gm_commands/myskills.cpp | 2 +- zone/gm_commands/mysql.cpp | 2 +- zone/gm_commands/mystats.cpp | 4 +- zone/gm_commands/npccast.cpp | 2 +- zone/gm_commands/npcedit.cpp | 8 +- zone/gm_commands/npceditmass.cpp | 2 +- zone/gm_commands/npcemote.cpp | 2 +- zone/gm_commands/npcloot.cpp | 6 +- zone/gm_commands/npcsay.cpp | 2 +- zone/gm_commands/npcshout.cpp | 2 +- zone/gm_commands/npcspawn.cpp | 2 +- zone/gm_commands/npctypespawn.cpp | 2 +- zone/gm_commands/nudge.cpp | 2 +- zone/gm_commands/nukebuffs.cpp | 2 +- zone/gm_commands/nukeitem.cpp | 2 +- zone/gm_commands/object.cpp | 3 +- zone/gm_commands/object_manipulation.cpp | 10 +- zone/gm_commands/object_manipulation.h | 8 +- zone/gm_commands/parcels.cpp | 12 +- zone/gm_commands/path.cpp | 2 +- zone/gm_commands/peqzone.cpp | 2 +- zone/gm_commands/petitems.cpp | 4 +- zone/gm_commands/petname.cpp | 2 +- zone/gm_commands/picklock.cpp | 2 +- zone/gm_commands/profanity.cpp | 6 +- zone/gm_commands/push.cpp | 4 +- zone/gm_commands/raidloot.cpp | 7 +- zone/gm_commands/randomfeatures.cpp | 2 +- zone/gm_commands/refreshgroup.cpp | 4 +- zone/gm_commands/reload.cpp | 9 +- zone/gm_commands/removeitem.cpp | 2 +- zone/gm_commands/repop.cpp | 2 +- zone/gm_commands/resetaa.cpp | 2 +- zone/gm_commands/resetaa_timer.cpp | 2 +- zone/gm_commands/resetdisc_timer.cpp | 2 +- zone/gm_commands/revoke.cpp | 4 +- zone/gm_commands/roambox.cpp | 4 +- zone/gm_commands/rules.cpp | 9 +- zone/gm_commands/save.cpp | 4 +- zone/gm_commands/scale.cpp | 4 +- zone/gm_commands/scribespell.cpp | 2 +- zone/gm_commands/scribespells.cpp | 2 +- zone/gm_commands/sendzonespawns.cpp | 2 +- zone/gm_commands/sensetrap.cpp | 2 +- zone/gm_commands/serverrules.cpp | 2 +- zone/gm_commands/set.cpp | 2 +- zone/gm_commands/set/set_aa_exp.cpp | 7 +- zone/gm_commands/set/set_aa_points.cpp | 7 +- zone/gm_commands/set/set_adventure_points.cpp | 4 +- .../set/set_alternate_currency.cpp | 2 +- zone/gm_commands/set/set_animation.cpp | 2 +- zone/gm_commands/set/set_anon.cpp | 4 +- zone/gm_commands/set/set_auto_login.cpp | 9 +- zone/gm_commands/set/set_bind_point.cpp | 2 +- zone/gm_commands/set/set_checksum.cpp | 6 +- zone/gm_commands/set/set_class_permanent.cpp | 2 +- zone/gm_commands/set/set_crystals.cpp | 2 +- zone/gm_commands/set/set_date.cpp | 2 +- zone/gm_commands/set/set_endurance.cpp | 2 +- zone/gm_commands/set/set_endurance_full.cpp | 2 +- zone/gm_commands/set/set_exp.cpp | 2 +- zone/gm_commands/set/set_flymode.cpp | 4 +- zone/gm_commands/set/set_frozen.cpp | 2 +- zone/gm_commands/set/set_gender.cpp | 2 +- zone/gm_commands/set/set_gender_permanent.cpp | 2 +- zone/gm_commands/set/set_gm.cpp | 2 +- zone/gm_commands/set/set_gm_speed.cpp | 2 +- zone/gm_commands/set/set_gm_status.cpp | 4 +- zone/gm_commands/set/set_god_mode.cpp | 4 +- zone/gm_commands/set/set_haste.cpp | 4 +- zone/gm_commands/set/set_hero_model.cpp | 2 +- zone/gm_commands/set/set_hide_me.cpp | 2 +- zone/gm_commands/set/set_hp.cpp | 2 +- zone/gm_commands/set/set_hp_full.cpp | 2 +- zone/gm_commands/set/set_invulnerable.cpp | 2 +- zone/gm_commands/set/set_language.cpp | 4 +- zone/gm_commands/set/set_last_name.cpp | 2 +- zone/gm_commands/set/set_level.cpp | 4 +- zone/gm_commands/set/set_loginserver_info.cpp | 4 +- zone/gm_commands/set/set_mana.cpp | 2 +- zone/gm_commands/set/set_mana_full.cpp | 2 +- zone/gm_commands/set/set_motd.cpp | 4 +- zone/gm_commands/set/set_name.cpp | 2 +- zone/gm_commands/set/set_ooc_mute.cpp | 4 +- zone/gm_commands/set/set_password.cpp | 2 +- zone/gm_commands/set/set_pvp.cpp | 2 +- zone/gm_commands/set/set_pvp_points.cpp | 2 +- zone/gm_commands/set/set_race.cpp | 2 +- zone/gm_commands/set/set_race_permanent.cpp | 2 +- zone/gm_commands/set/set_server_locked.cpp | 4 +- zone/gm_commands/set/set_skill.cpp | 2 +- zone/gm_commands/set/set_skill_all.cpp | 2 +- zone/gm_commands/set/set_skill_all_max.cpp | 2 +- zone/gm_commands/set/set_start_zone.cpp | 2 +- zone/gm_commands/set/set_temporary_name.cpp | 2 +- zone/gm_commands/set/set_texture.cpp | 2 +- zone/gm_commands/set/set_time.cpp | 2 +- zone/gm_commands/set/set_time_zone.cpp | 2 +- zone/gm_commands/set/set_title.cpp | 4 +- zone/gm_commands/set/set_title_suffix.cpp | 4 +- zone/gm_commands/set/set_weather.cpp | 2 +- zone/gm_commands/set/set_zone.cpp | 4 +- zone/gm_commands/show.cpp | 2 +- zone/gm_commands/show/show_aa_points.cpp | 4 +- zone/gm_commands/show/show_aas.cpp | 2 +- zone/gm_commands/show/show_aggro.cpp | 2 +- zone/gm_commands/show/show_auto_login.cpp | 4 +- zone/gm_commands/show/show_buffs.cpp | 2 +- .../show/show_buried_corpse_count.cpp | 4 +- .../show/show_client_version_summary.cpp | 4 +- zone/gm_commands/show/show_content_flags.cpp | 4 +- zone/gm_commands/show/show_currencies.cpp | 4 +- zone/gm_commands/show/show_distance.cpp | 2 +- zone/gm_commands/show/show_emotes.cpp | 2 +- zone/gm_commands/show/show_field_of_view.cpp | 2 +- zone/gm_commands/show/show_flags.cpp | 2 +- zone/gm_commands/show/show_group_info.cpp | 6 +- zone/gm_commands/show/show_hatelist.cpp | 2 +- zone/gm_commands/show/show_inventory.cpp | 6 +- zone/gm_commands/show/show_ip_lookup.cpp | 4 +- zone/gm_commands/show/show_keyring.cpp | 4 +- zone/gm_commands/show/show_line_of_sight.cpp | 2 +- zone/gm_commands/show/show_network.cpp | 4 +- zone/gm_commands/show/show_network_stats.cpp | 4 +- .../gm_commands/show/show_npc_global_loot.cpp | 2 +- zone/gm_commands/show/show_npc_stats.cpp | 2 +- zone/gm_commands/show/show_npc_type.cpp | 2 +- zone/gm_commands/show/show_peqzone_flags.cpp | 2 +- zone/gm_commands/show/show_petition.cpp | 4 +- zone/gm_commands/show/show_petition_info.cpp | 4 +- zone/gm_commands/show/show_proximity.cpp | 2 +- zone/gm_commands/show/show_quest_errors.cpp | 4 +- zone/gm_commands/show/show_quest_globals.cpp | 2 +- zone/gm_commands/show/show_recipe.cpp | 8 +- zone/gm_commands/show/show_server_info.cpp | 6 +- zone/gm_commands/show/show_skills.cpp | 4 +- zone/gm_commands/show/show_spawn_status.cpp | 2 +- .../show/show_special_abilities.cpp | 2 +- zone/gm_commands/show/show_spells.cpp | 2 +- zone/gm_commands/show/show_spells_list.cpp | 2 +- zone/gm_commands/show/show_stats.cpp | 2 +- zone/gm_commands/show/show_timers.cpp | 4 +- zone/gm_commands/show/show_traps.cpp | 2 +- zone/gm_commands/show/show_uptime.cpp | 4 +- zone/gm_commands/show/show_variable.cpp | 2 +- zone/gm_commands/show/show_version.cpp | 4 +- zone/gm_commands/show/show_waypoints.cpp | 2 +- zone/gm_commands/show/show_who.cpp | 2 +- zone/gm_commands/show/show_xtargets.cpp | 4 +- zone/gm_commands/show/show_zone_data.cpp | 4 +- .../show/show_zone_global_loot.cpp | 2 +- zone/gm_commands/show/show_zone_loot.cpp | 2 +- zone/gm_commands/show/show_zone_points.cpp | 2 +- zone/gm_commands/show/show_zone_status.cpp | 4 +- zone/gm_commands/show/show_zone_variables.cpp | 4 +- zone/gm_commands/shutdown.cpp | 5 +- zone/gm_commands/spawn.cpp | 2 +- zone/gm_commands/spawneditmass.cpp | 2 +- zone/gm_commands/spawnfix.cpp | 2 +- zone/gm_commands/stun.cpp | 2 +- zone/gm_commands/summon.cpp | 4 +- zone/gm_commands/summonburiedplayercorpse.cpp | 4 +- zone/gm_commands/summonitem.cpp | 2 +- zone/gm_commands/suspend.cpp | 6 +- zone/gm_commands/suspendmulti.cpp | 6 +- zone/gm_commands/takeplatinum.cpp | 2 +- zone/gm_commands/task.cpp | 9 +- zone/gm_commands/traindisc.cpp | 2 +- zone/gm_commands/tune.cpp | 2 +- zone/gm_commands/undye.cpp | 2 +- zone/gm_commands/unmemspell.cpp | 2 +- zone/gm_commands/unmemspells.cpp | 2 +- zone/gm_commands/unscribespell.cpp | 4 +- zone/gm_commands/unscribespells.cpp | 2 +- zone/gm_commands/untraindisc.cpp | 4 +- zone/gm_commands/untraindiscs.cpp | 2 +- zone/gm_commands/wc.cpp | 4 +- zone/gm_commands/worldshutdown.cpp | 4 +- zone/gm_commands/worldwide.cpp | 2 +- zone/gm_commands/wp.cpp | 2 +- zone/gm_commands/wpadd.cpp | 2 +- zone/gm_commands/zone.cpp | 4 +- zone/gm_commands/zone_instance.cpp | 2 +- zone/gm_commands/zone_shard.cpp | 2 +- zone/gm_commands/zonebootup.cpp | 4 +- zone/gm_commands/zoneshutdown.cpp | 4 +- zone/gm_commands/zonevariable.cpp | 2 +- zone/gm_commands/zsave.cpp | 2 +- 293 files changed, 455 insertions(+), 644 deletions(-) delete mode 100644 utils/gm_commands/main.go diff --git a/utils/gm_commands/main.go b/utils/gm_commands/main.go deleted file mode 100644 index 4ef678d97a..0000000000 --- a/utils/gm_commands/main.go +++ /dev/null @@ -1,183 +0,0 @@ -package main - -import ( - "fmt" - "io/ioutil" - "log" - "os" - "sort" - "strings" -) - -func main() { - // zone/command.cpp - commands, err := os.ReadFile("./zone/command.cpp") - if err != nil { - log.Fatal(err) - } - commandsString := string(commands) - - s := strings.Split(commandsString, "void command_") - commandFiles := []string{} - if len(s) > 1 { - startListing := false - for i, chunk := range s { - if strings.Contains(chunk, "logcommand(Client *c") { - startListing = true - } - - // get function name - functionName := "" - nameSplit := strings.Split(chunk, "(Client") - if len(nameSplit) > 0 { - functionName = strings.TrimSpace(nameSplit[0]) - } - - if startListing && - len(s[i-1]) > 0 && - !strings.Contains(s[i-1], "#ifdef") && - !strings.Contains(chunk, "#ifdef") && - !strings.Contains(chunk, "#ifdef BOTS") && - !strings.Contains(chunk, "#ifdef EQPROFILE") && - !strings.Contains(functionName, "bot") && - !strings.Contains(functionName, "help") && - !strings.Contains(functionName, "findaliases") { - - fmt.Println(functionName) - - // build command file name - commandFile := fmt.Sprintf("zone/gm_commands/%v.cpp", functionName) - - // append command file nam eto list - commandFiles = append(commandFiles, commandFile) - - includes := "" - if strings.Contains(chunk, "Client") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../client.h\"") - } - if strings.Contains(chunk, "parse->") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../quest_parser_collection.h\"") - } - if strings.Contains(chunk, "worldserver.") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../worldserver.h\"") - includes = fmt.Sprintf("%v%v\n", includes, "extern WorldServer worldserver;") - } - if strings.Contains(chunk, "RegionType") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../water_map.h\"") - } - if strings.Contains(chunk, "Corpse") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../corpse.h\"") - } - if strings.Contains(chunk, "Object") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../object.h\"") - } - if strings.Contains(chunk, "DoorManipulation") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"door_manipulation.h\"") - } - if strings.Contains(chunk, "Group") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../groups.h\"") - } - if strings.Contains(chunk, "httplib") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/http/httplib.h\"") - } - if strings.Contains(chunk, "guild_mgr") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../guild_mgr.h\"") - } - if strings.Contains(chunk, "expedition") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../expedition.h\"") - } - if strings.Contains(chunk, "DataBucket::") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../data_bucket.h\"") - } - if strings.Contains(chunk, "file_exists") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/file_util.h\"") - } - if strings.Contains(chunk, "std::thread") { - includes = fmt.Sprintf("%v%v\n", includes, "#include ") - } - if strings.Contains(chunk, "Door") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../doors.h\"") - } - if strings.Contains(chunk, "NOW_INVISIBLE") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../string_ids.h\"") - } - if strings.Contains(chunk, "Expansion::") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/content/world_content_service.h\"") - } - if strings.Contains(chunk, "MobMovementManager::") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../mob_movement_manager.h\"") - } - if strings.Contains(chunk, "MobStuckBehavior::") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../mob_movement_manager.h\"") - } - if strings.Contains(chunk, "ReloadAllPatches") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/patches/patches.h\"") - } - if strings.Contains(chunk, "ProfanityManager") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/profanity_manager.h\"") - } - if strings.Contains(chunk, "npc_scale_manager") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../npc_scale_manager.h\"") - } - if strings.Contains(chunk, "g_Math") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../fastmath.h\"") - includes = fmt.Sprintf("%v%v\n", includes, "extern FastMath g_Math;") - } - if strings.Contains(chunk, "raid") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../raids.h\"") - } - if strings.Contains(chunk, "Raid") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../raids.h\"") - } - if strings.Contains(chunk, "GetOS") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/serverinfo.h\"") - } - if strings.Contains(chunk, "LANG_") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/languages.h\"") - } - if strings.Contains(chunk, "ServerOP_Shared") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../common/shared_tasks.h\"") - } - if strings.Contains(chunk, "title_manager") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../titles.h\"") - } - if strings.Contains(chunk, "CatchSignal") { - includes = fmt.Sprintf("%v%v\n", includes, "#include \"../../world/main.h\"") - } - - // build the contents of the command file - commandString := fmt.Sprintf("%v\nvoid command_%v", includes, chunk) - - //write file contents - err := ioutil.WriteFile(commandFile, []byte(commandString), 0777) - if err != nil { - fmt.Println(err) - } - - commandOnly := fmt.Sprintf("void command_%v", chunk) - commandsString = strings.ReplaceAll(commandsString, commandOnly, "") - - } - } - - // rewrite commands.cpp with functions removed - err := ioutil.WriteFile("zone/command.cpp", []byte(commandsString), 0777) - if err != nil { - fmt.Println(err) - } - - fmt.Println("# CmakeLists") - - // sort a-z - sort.Slice(commandFiles, func(i, j int) bool { - return commandFiles[i] < commandFiles[j] - }) - - for _, file := range commandFiles { - file = strings.ReplaceAll(file, "zone/", "") - fmt.Println(file) - } - } - - //fmt.Print(string(commands)) -} diff --git a/zone/gm_commands/acceptrules.cpp b/zone/gm_commands/acceptrules.cpp index c675eee8ba..6886cf21b3 100755 --- a/zone/gm_commands/acceptrules.cpp +++ b/zone/gm_commands/acceptrules.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_acceptrules(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/advnpcspawn.cpp b/zone/gm_commands/advnpcspawn.cpp index 235362f3fa..24f7d6b06d 100755 --- a/zone/gm_commands/advnpcspawn.cpp +++ b/zone/gm_commands/advnpcspawn.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../groups.h" +#include "zone/client.h" +#include "zone/groups.h" void command_advnpcspawn(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/aggrozone.cpp b/zone/gm_commands/aggrozone.cpp index 6b80c85d39..5503acac58 100755 --- a/zone/gm_commands/aggrozone.cpp +++ b/zone/gm_commands/aggrozone.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_aggrozone(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/ai.cpp b/zone/gm_commands/ai.cpp index b746ac0b45..84705a3e6a 100755 --- a/zone/gm_commands/ai.cpp +++ b/zone/gm_commands/ai.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_ai(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/appearance.cpp b/zone/gm_commands/appearance.cpp index 65ac7792fd..c4f52b132e 100755 --- a/zone/gm_commands/appearance.cpp +++ b/zone/gm_commands/appearance.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_appearance(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/appearanceeffects.cpp b/zone/gm_commands/appearanceeffects.cpp index d094a4f0a4..09ba6cb4ab 100644 --- a/zone/gm_commands/appearanceeffects.cpp +++ b/zone/gm_commands/appearanceeffects.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_appearanceeffects(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/attack.cpp b/zone/gm_commands/attack.cpp index 4623a85cab..e62743c43f 100755 --- a/zone/gm_commands/attack.cpp +++ b/zone/gm_commands/attack.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_attack(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/augmentitem.cpp b/zone/gm_commands/augmentitem.cpp index 81b5523aa8..ddf0559e92 100755 --- a/zone/gm_commands/augmentitem.cpp +++ b/zone/gm_commands/augmentitem.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../object.h" +#include "zone/client.h" +#include "zone/object.h" void command_augmentitem(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/ban.cpp b/zone/gm_commands/ban.cpp index 3d2530ab90..6050978f84 100755 --- a/zone/gm_commands/ban.cpp +++ b/zone/gm_commands/ban.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/bugs.cpp b/zone/gm_commands/bugs.cpp index 8263c2c11e..2aeea05070 100755 --- a/zone/gm_commands/bugs.cpp +++ b/zone/gm_commands/bugs.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../../common/repositories/bug_reports_repository.h" +#include "common/repositories/bug_reports_repository.h" +#include "zone/client.h" void command_bugs(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/camerashake.cpp b/zone/gm_commands/camerashake.cpp index dc6adf7990..13a26d9884 100755 --- a/zone/gm_commands/camerashake.cpp +++ b/zone/gm_commands/camerashake.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/castspell.cpp b/zone/gm_commands/castspell.cpp index 47597c19a9..9fc940947e 100755 --- a/zone/gm_commands/castspell.cpp +++ b/zone/gm_commands/castspell.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_castspell(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/chat.cpp b/zone/gm_commands/chat.cpp index 56c8e1cc69..eedcb81ff1 100755 --- a/zone/gm_commands/chat.cpp +++ b/zone/gm_commands/chat.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/clearxtargets.cpp b/zone/gm_commands/clearxtargets.cpp index 58700675bd..337d1de0ec 100644 --- a/zone/gm_commands/clearxtargets.cpp +++ b/zone/gm_commands/clearxtargets.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_clearxtargets(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/copycharacter.cpp b/zone/gm_commands/copycharacter.cpp index 84af276775..cfd8de48a4 100755 --- a/zone/gm_commands/copycharacter.cpp +++ b/zone/gm_commands/copycharacter.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_copycharacter(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/corpse.cpp b/zone/gm_commands/corpse.cpp index 14f914c7dd..560e993193 100755 --- a/zone/gm_commands/corpse.cpp +++ b/zone/gm_commands/corpse.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../corpse.h" +#include "zone/client.h" +#include "zone/corpse.h" void command_corpse(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/corpsefix.cpp b/zone/gm_commands/corpsefix.cpp index 0de35a8d39..3370e827b4 100755 --- a/zone/gm_commands/corpsefix.cpp +++ b/zone/gm_commands/corpsefix.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../corpse.h" +#include "zone/client.h" +#include "zone/corpse.h" void command_corpsefix(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/countitem.cpp b/zone/gm_commands/countitem.cpp index 306f489422..69aaa28323 100644 --- a/zone/gm_commands/countitem.cpp +++ b/zone/gm_commands/countitem.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_countitem(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/damage.cpp b/zone/gm_commands/damage.cpp index 2044cc483d..8ddd811380 100755 --- a/zone/gm_commands/damage.cpp +++ b/zone/gm_commands/damage.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_damage(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/databuckets.cpp b/zone/gm_commands/databuckets.cpp index ca2b17808a..bf9c1b84fa 100755 --- a/zone/gm_commands/databuckets.cpp +++ b/zone/gm_commands/databuckets.cpp @@ -1,7 +1,7 @@ -#include "../client.h" -#include "../../common/data_bucket.h" -#include "../dialogue_window.h" -#include "../../common/repositories/data_buckets_repository.h" +#include "common/data_bucket.h" +#include "common/repositories/data_buckets_repository.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void SendDataBucketsSubCommands(Client *c) { diff --git a/zone/gm_commands/dbspawn2.cpp b/zone/gm_commands/dbspawn2.cpp index e52419f28a..2db3449484 100755 --- a/zone/gm_commands/dbspawn2.cpp +++ b/zone/gm_commands/dbspawn2.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_dbspawn2(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/delacct.cpp b/zone/gm_commands/delacct.cpp index a4602a9a30..198e736b4a 100755 --- a/zone/gm_commands/delacct.cpp +++ b/zone/gm_commands/delacct.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../../common/repositories/account_repository.h" +#include "common/repositories/account_repository.h" +#include "zone/client.h" void command_delacct(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/delpetition.cpp b/zone/gm_commands/delpetition.cpp index 3630a9b3b2..f42cf27728 100755 --- a/zone/gm_commands/delpetition.cpp +++ b/zone/gm_commands/delpetition.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_delpetition(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/depop.cpp b/zone/gm_commands/depop.cpp index 1b69fb8f8a..0c10fc8f4a 100755 --- a/zone/gm_commands/depop.cpp +++ b/zone/gm_commands/depop.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../corpse.h" +#include "zone/client.h" +#include "zone/corpse.h" void command_depop(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/depopzone.cpp b/zone/gm_commands/depopzone.cpp index ef90d7c042..0d483cbd12 100755 --- a/zone/gm_commands/depopzone.cpp +++ b/zone/gm_commands/depopzone.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_depopzone(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/devtools.cpp b/zone/gm_commands/devtools.cpp index c362a6d051..2326c41299 100755 --- a/zone/gm_commands/devtools.cpp +++ b/zone/gm_commands/devtools.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../../common/data_bucket.h" +#include "common/data_bucket.h" +#include "zone/client.h" void command_devtools(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/disablerecipe.cpp b/zone/gm_commands/disablerecipe.cpp index f57fa97d00..b9936f3161 100755 --- a/zone/gm_commands/disablerecipe.cpp +++ b/zone/gm_commands/disablerecipe.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_disablerecipe(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/disarmtrap.cpp b/zone/gm_commands/disarmtrap.cpp index 44837c053d..2f21efd59a 100755 --- a/zone/gm_commands/disarmtrap.cpp +++ b/zone/gm_commands/disarmtrap.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_disarmtrap(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/doanim.cpp b/zone/gm_commands/doanim.cpp index 1f777a6048..2e050194a3 100755 --- a/zone/gm_commands/doanim.cpp +++ b/zone/gm_commands/doanim.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../dialogue_window.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void command_doanim(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/door.cpp b/zone/gm_commands/door.cpp index 33764af5bb..46ea56a93b 100755 --- a/zone/gm_commands/door.cpp +++ b/zone/gm_commands/door.cpp @@ -1,6 +1,7 @@ -#include "../client.h" #include "door_manipulation.h" +#include "zone/client.h" + void command_door(Client *c, const Seperator *sep) { DoorManipulation::CommandHandler(c, sep); diff --git a/zone/gm_commands/door_manipulation.cpp b/zone/gm_commands/door_manipulation.cpp index 614cc44844..28af983ddc 100644 --- a/zone/gm_commands/door_manipulation.cpp +++ b/zone/gm_commands/door_manipulation.cpp @@ -1,7 +1,8 @@ #include "door_manipulation.h" -#include "../doors.h" -#include "../../common/misc_functions.h" -#include "../../common/strings.h" + +#include "common/misc_functions.h" +#include "common/strings.h" +#include "zone/doors.h" #define MAX_CLIENT_MESSAGE_LENGTH 2000 diff --git a/zone/gm_commands/door_manipulation.h b/zone/gm_commands/door_manipulation.h index d448c3bc70..4a80ebeca4 100644 --- a/zone/gm_commands/door_manipulation.h +++ b/zone/gm_commands/door_manipulation.h @@ -1,8 +1,7 @@ -#ifndef EQEMU_DOOR_MANIPULATION_H -#define EQEMU_DOOR_MANIPULATION_H +#pragma once -#include "../client.h" -#include "../../common/repositories/tool_game_objects_repository.h" +#include "common/repositories/tool_game_objects_repository.h" +#include "zone/client.h" class DoorManipulation { @@ -18,6 +17,3 @@ class DoorManipulation { std::vector game_objects ); }; - - -#endif //EQEMU_DOOR_MANIPULATION_H diff --git a/zone/gm_commands/dye.cpp b/zone/gm_commands/dye.cpp index 7fa4c73a23..efd2104187 100755 --- a/zone/gm_commands/dye.cpp +++ b/zone/gm_commands/dye.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_dye(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/dz.cpp b/zone/gm_commands/dz.cpp index fe2ce1252b..8df3a434e5 100755 --- a/zone/gm_commands/dz.cpp +++ b/zone/gm_commands/dz.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../dynamic_zone.h" +#include "zone/client.h" +#include "zone/dynamic_zone.h" void command_dz(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/dzkickplayers.cpp b/zone/gm_commands/dzkickplayers.cpp index 1f56aee445..4a0ff340b8 100755 --- a/zone/gm_commands/dzkickplayers.cpp +++ b/zone/gm_commands/dzkickplayers.cpp @@ -1,4 +1,5 @@ -#include "../client.h" +#include "zone/client.h" +#include "zone/dynamic_zone.h" void command_dzkickplayers(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/editmassrespawn.cpp b/zone/gm_commands/editmassrespawn.cpp index a520ed6ccb..a48475c927 100755 --- a/zone/gm_commands/editmassrespawn.cpp +++ b/zone/gm_commands/editmassrespawn.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_editmassrespawn(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/emote.cpp b/zone/gm_commands/emote.cpp index 761f1fd12d..6fc0c6a721 100755 --- a/zone/gm_commands/emote.cpp +++ b/zone/gm_commands/emote.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/emptyinventory.cpp b/zone/gm_commands/emptyinventory.cpp index e37167db6a..869fea3d5f 100644 --- a/zone/gm_commands/emptyinventory.cpp +++ b/zone/gm_commands/emptyinventory.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_emptyinventory(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/enablerecipe.cpp b/zone/gm_commands/enablerecipe.cpp index 60c8fefbef..28f4cff1c0 100755 --- a/zone/gm_commands/enablerecipe.cpp +++ b/zone/gm_commands/enablerecipe.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_enablerecipe(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/entityvariable.cpp b/zone/gm_commands/entityvariable.cpp index d6e10d204c..fc64a67963 100644 --- a/zone/gm_commands/entityvariable.cpp +++ b/zone/gm_commands/entityvariable.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_entityvariable(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/evolving_items.cpp b/zone/gm_commands/evolving_items.cpp index 241a79a50d..cb58d67338 100644 --- a/zone/gm_commands/evolving_items.cpp +++ b/zone/gm_commands/evolving_items.cpp @@ -1,6 +1,6 @@ -#include "../client.h" -#include "../command.h" -#include "../../common/evolving_items.h" +#include "common/evolving_items.h" +#include "zone/client.h" +#include "zone/command.h" void command_evolvingitems(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/exptoggle.cpp b/zone/gm_commands/exptoggle.cpp index abc1d2b926..8aba5b627b 100644 --- a/zone/gm_commands/exptoggle.cpp +++ b/zone/gm_commands/exptoggle.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_exptoggle(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/faction.cpp b/zone/gm_commands/faction.cpp index 2e1dd726e1..c703d51c3a 100644 --- a/zone/gm_commands/faction.cpp +++ b/zone/gm_commands/faction.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_faction(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/faction_association.cpp b/zone/gm_commands/faction_association.cpp index a39f25dbce..8d900d3a9a 100644 --- a/zone/gm_commands/faction_association.cpp +++ b/zone/gm_commands/faction_association.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_faction_association(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/feature.cpp b/zone/gm_commands/feature.cpp index f43f279fa2..a0670686b6 100644 --- a/zone/gm_commands/feature.cpp +++ b/zone/gm_commands/feature.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_feature(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find.cpp b/zone/gm_commands/find.cpp index a5e2bad3d2..cf25624b24 100644 --- a/zone/gm_commands/find.cpp +++ b/zone/gm_commands/find.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void FindAA(Client* c, const Seperator* sep); void FindAccount(Client* c, const Seperator* sep); diff --git a/zone/gm_commands/find/find_aa.cpp b/zone/gm_commands/find/find_aa.cpp index 82e311bee3..e7155014e7 100644 --- a/zone/gm_commands/find/find_aa.cpp +++ b/zone/gm_commands/find/find_aa.cpp @@ -1,4 +1,5 @@ -#include "../../client.h" +#include "common/seperator.h" +#include "zone/client.h" void FindAA(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_account.cpp b/zone/gm_commands/find/find_account.cpp index 17512b2a8a..828daecb2c 100644 --- a/zone/gm_commands/find/find_account.cpp +++ b/zone/gm_commands/find/find_account.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/repositories/account_repository.h" +#include "common/repositories/account_repository.h" +#include "zone/client.h" void FindAccount(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_body_type.cpp b/zone/gm_commands/find/find_body_type.cpp index bcf57f400f..3e1bbed165 100644 --- a/zone/gm_commands/find/find_body_type.cpp +++ b/zone/gm_commands/find/find_body_type.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void FindBodyType(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_bot.cpp b/zone/gm_commands/find/find_bot.cpp index fd403d6707..f36ec7eac1 100644 --- a/zone/gm_commands/find/find_bot.cpp +++ b/zone/gm_commands/find/find_bot.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/repositories/bot_data_repository.h" +#include "common/repositories/bot_data_repository.h" +#include "zone/client.h" void FindBot(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_bug_category.cpp b/zone/gm_commands/find/find_bug_category.cpp index 5dc51f0d14..cba0369fcf 100644 --- a/zone/gm_commands/find/find_bug_category.cpp +++ b/zone/gm_commands/find/find_bug_category.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void FindBugCategory(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_character.cpp b/zone/gm_commands/find/find_character.cpp index 0c1842eff2..d822e3ed50 100644 --- a/zone/gm_commands/find/find_character.cpp +++ b/zone/gm_commands/find/find_character.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/repositories/character_data_repository.h" +#include "common/repositories/character_data_repository.h" +#include "zone/client.h" void FindCharacter(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_class.cpp b/zone/gm_commands/find/find_class.cpp index a89211e774..cff72b201c 100644 --- a/zone/gm_commands/find/find_class.cpp +++ b/zone/gm_commands/find/find_class.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void FindClass(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_comparison_type.cpp b/zone/gm_commands/find/find_comparison_type.cpp index 52a9dea6e6..9ee2ef49a2 100644 --- a/zone/gm_commands/find/find_comparison_type.cpp +++ b/zone/gm_commands/find/find_comparison_type.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void FindComparisonType(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_currency.cpp b/zone/gm_commands/find/find_currency.cpp index fbf640d851..41928b71a9 100644 --- a/zone/gm_commands/find/find_currency.cpp +++ b/zone/gm_commands/find/find_currency.cpp @@ -1,4 +1,5 @@ -#include "../../client.h" +#include "zone/client.h" +#include "zone/command.h" void FindCurrency(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_deity.cpp b/zone/gm_commands/find/find_deity.cpp index be295bfedf..a9b298a2a7 100644 --- a/zone/gm_commands/find/find_deity.cpp +++ b/zone/gm_commands/find/find_deity.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void FindDeity(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_emote.cpp b/zone/gm_commands/find/find_emote.cpp index a8f1c433c2..af95c08322 100644 --- a/zone/gm_commands/find/find_emote.cpp +++ b/zone/gm_commands/find/find_emote.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void FindEmote(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_faction.cpp b/zone/gm_commands/find/find_faction.cpp index 376140928a..8bd933b53a 100644 --- a/zone/gm_commands/find/find_faction.cpp +++ b/zone/gm_commands/find/find_faction.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void FindFaction(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_item.cpp b/zone/gm_commands/find/find_item.cpp index 0f48707011..537c441a31 100644 --- a/zone/gm_commands/find/find_item.cpp +++ b/zone/gm_commands/find/find_item.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/repositories/items_repository.h" +#include "zone/client.h" +#include "common/repositories/items_repository.h" void FindItem(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_language.cpp b/zone/gm_commands/find/find_language.cpp index 0df7f4a4d5..699c504464 100644 --- a/zone/gm_commands/find/find_language.cpp +++ b/zone/gm_commands/find/find_language.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void FindLanguage(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_ldon_theme.cpp b/zone/gm_commands/find/find_ldon_theme.cpp index aa7231297a..1310364de6 100644 --- a/zone/gm_commands/find/find_ldon_theme.cpp +++ b/zone/gm_commands/find/find_ldon_theme.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void FindLDoNTheme(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_npctype.cpp b/zone/gm_commands/find/find_npctype.cpp index c83be99baf..7cb177d79c 100644 --- a/zone/gm_commands/find/find_npctype.cpp +++ b/zone/gm_commands/find/find_npctype.cpp @@ -1,4 +1,5 @@ -#include "../../client.h" +#include "zone/client.h" +#include "zone/command.h" void FindNPCType(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_object_type.cpp b/zone/gm_commands/find/find_object_type.cpp index 1e7dc69aaa..c0768cc1fb 100644 --- a/zone/gm_commands/find/find_object_type.cpp +++ b/zone/gm_commands/find/find_object_type.cpp @@ -1,5 +1,5 @@ -#include "../../object.h" -#include "../../client.h" +#include "zone/client.h" +#include "zone/object.h" void FindObjectType(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_race.cpp b/zone/gm_commands/find/find_race.cpp index 4b15f12280..644ffce738 100644 --- a/zone/gm_commands/find/find_race.cpp +++ b/zone/gm_commands/find/find_race.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void FindRace(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_recipe.cpp b/zone/gm_commands/find/find_recipe.cpp index 260c6dccf9..7003c801ab 100644 --- a/zone/gm_commands/find/find_recipe.cpp +++ b/zone/gm_commands/find/find_recipe.cpp @@ -1,6 +1,6 @@ -#include "../../client.h" -#include "../../command.h" -#include "../../../common/repositories/tradeskill_recipe_repository.h" +#include "common/repositories/tradeskill_recipe_repository.h" +#include "zone/client.h" +#include "zone/command.h" void FindRecipe(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_skill.cpp b/zone/gm_commands/find/find_skill.cpp index 7c92f43598..12ceabb8a1 100644 --- a/zone/gm_commands/find/find_skill.cpp +++ b/zone/gm_commands/find/find_skill.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void FindSkill(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_special_ability.cpp b/zone/gm_commands/find/find_special_ability.cpp index ad29813df7..24cdce4474 100644 --- a/zone/gm_commands/find/find_special_ability.cpp +++ b/zone/gm_commands/find/find_special_ability.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void FindSpecialAbility(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_spell.cpp b/zone/gm_commands/find/find_spell.cpp index b5f1a88e83..2c2afae69d 100644 --- a/zone/gm_commands/find/find_spell.cpp +++ b/zone/gm_commands/find/find_spell.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" uint8 GetCommandStatus(std::string command_name); diff --git a/zone/gm_commands/find/find_stance.cpp b/zone/gm_commands/find/find_stance.cpp index daebebc153..7fb2ceecb5 100644 --- a/zone/gm_commands/find/find_stance.cpp +++ b/zone/gm_commands/find/find_stance.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void FindStance(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/find/find_task.cpp b/zone/gm_commands/find/find_task.cpp index 0873ebe30b..21ffe5b0da 100644 --- a/zone/gm_commands/find/find_task.cpp +++ b/zone/gm_commands/find/find_task.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" uint8 GetCommandStatus(std::string command_name); diff --git a/zone/gm_commands/find/find_zone.cpp b/zone/gm_commands/find/find_zone.cpp index 6715649d99..eb7a47ff68 100644 --- a/zone/gm_commands/find/find_zone.cpp +++ b/zone/gm_commands/find/find_zone.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/content/world_content_service.h" +#include "common/content/world_content_service.h" +#include "zone/client.h" void FindZone(Client* c, const Seperator* sep) { diff --git a/zone/gm_commands/fish.cpp b/zone/gm_commands/fish.cpp index 47af56009e..07632d3a05 100644 --- a/zone/gm_commands/fish.cpp +++ b/zone/gm_commands/fish.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_fish(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/fixmob.cpp b/zone/gm_commands/fixmob.cpp index d691b0f2ef..e91cefd17d 100755 --- a/zone/gm_commands/fixmob.cpp +++ b/zone/gm_commands/fixmob.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void SendFixMobSubCommands(Client* c) { diff --git a/zone/gm_commands/flagedit.cpp b/zone/gm_commands/flagedit.cpp index bb29620f1e..cb260e09e3 100755 --- a/zone/gm_commands/flagedit.cpp +++ b/zone/gm_commands/flagedit.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_flagedit(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/fleeinfo.cpp b/zone/gm_commands/fleeinfo.cpp index 1461bfd3c5..3c5f6ca734 100644 --- a/zone/gm_commands/fleeinfo.cpp +++ b/zone/gm_commands/fleeinfo.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_fleeinfo(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/forage.cpp b/zone/gm_commands/forage.cpp index b4717aac75..943de16914 100644 --- a/zone/gm_commands/forage.cpp +++ b/zone/gm_commands/forage.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_forage(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/gearup.cpp b/zone/gm_commands/gearup.cpp index 2d9cbc1c55..13c05da63d 100755 --- a/zone/gm_commands/gearup.cpp +++ b/zone/gm_commands/gearup.cpp @@ -1,8 +1,8 @@ -#include "../client.h" -#include "../../common/http/httplib.h" -#include "../../common/content/world_content_service.h" +#include "common/content/world_content_service.h" +#include "common/http/httplib.h" +#include "zone/client.h" -#include "../bot.h" +#include "zone/bot.h" void command_gearup(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/giveitem.cpp b/zone/gm_commands/giveitem.cpp index 66a05554e6..b0fc7f131d 100755 --- a/zone/gm_commands/giveitem.cpp +++ b/zone/gm_commands/giveitem.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_giveitem(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/givemoney.cpp b/zone/gm_commands/givemoney.cpp index 4cfd20389c..2965b755af 100755 --- a/zone/gm_commands/givemoney.cpp +++ b/zone/gm_commands/givemoney.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_givemoney(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/gmzone.cpp b/zone/gm_commands/gmzone.cpp index 9aefd58bc7..25351f7cbf 100755 --- a/zone/gm_commands/gmzone.cpp +++ b/zone/gm_commands/gmzone.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../../common/data_bucket.h" +#include "common/data_bucket.h" +#include "zone/client.h" void command_gmzone(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/goto.cpp b/zone/gm_commands/goto.cpp index 9ab3ad4d15..b9b177ab0a 100755 --- a/zone/gm_commands/goto.cpp +++ b/zone/gm_commands/goto.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_goto(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/grantaa.cpp b/zone/gm_commands/grantaa.cpp index b3afe7cde1..0d12fb717e 100644 --- a/zone/gm_commands/grantaa.cpp +++ b/zone/gm_commands/grantaa.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_grantaa(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/grid.cpp b/zone/gm_commands/grid.cpp index b8a7e7d3d0..62a0eba95a 100755 --- a/zone/gm_commands/grid.cpp +++ b/zone/gm_commands/grid.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../../common/repositories/grid_entries_repository.h" +#include "common/repositories/grid_entries_repository.h" +#include "zone/client.h" void command_grid(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/guild.cpp b/zone/gm_commands/guild.cpp index 97d280e80e..330fe793be 100755 --- a/zone/gm_commands/guild.cpp +++ b/zone/gm_commands/guild.cpp @@ -1,13 +1,12 @@ -#include "../client.h" -#include "../worldserver.h" -#include "../queryserv.h" +#include "zone/client.h" +#include "zone/doors.h" +#include "zone/guild_mgr.h" +#include "zone/queryserv.h" +#include "zone/worldserver.h" extern WorldServer worldserver; extern QueryServ *QServ; -#include "../guild_mgr.h" -#include "../doors.h" - void SendGuildSubCommands(Client* c) { c->Message(Chat::White, "#guild create [Character ID|Character Name] [Guild Name]"); @@ -691,4 +690,4 @@ void command_guild(Client* c, const Seperator* sep) // } } } -} \ No newline at end of file +} diff --git a/zone/gm_commands/hp.cpp b/zone/gm_commands/hp.cpp index 178ef98903..983704c417 100755 --- a/zone/gm_commands/hp.cpp +++ b/zone/gm_commands/hp.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_hp(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/illusion_block.cpp b/zone/gm_commands/illusion_block.cpp index 8aa274b4a2..822abf78cc 100644 --- a/zone/gm_commands/illusion_block.cpp +++ b/zone/gm_commands/illusion_block.cpp @@ -1,5 +1,5 @@ -#include "../dialogue_window.h" -#include "../client.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void command_illusion_block(Client* c, const Seperator* sep) { diff --git a/zone/gm_commands/instance.cpp b/zone/gm_commands/instance.cpp index 060bbcb81b..ef43c5cd6a 100755 --- a/zone/gm_commands/instance.cpp +++ b/zone/gm_commands/instance.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_instance(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/interrogateinv.cpp b/zone/gm_commands/interrogateinv.cpp index cf6a4fb75d..6cbfa74e94 100755 --- a/zone/gm_commands/interrogateinv.cpp +++ b/zone/gm_commands/interrogateinv.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_interrogateinv(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/interrupt.cpp b/zone/gm_commands/interrupt.cpp index 1a1200c1eb..7365a3b0d9 100755 --- a/zone/gm_commands/interrupt.cpp +++ b/zone/gm_commands/interrupt.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_interrupt(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/invsnapshot.cpp b/zone/gm_commands/invsnapshot.cpp index 425c04f58f..4a2fbec9ea 100755 --- a/zone/gm_commands/invsnapshot.cpp +++ b/zone/gm_commands/invsnapshot.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_invsnapshot(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/ipban.cpp b/zone/gm_commands/ipban.cpp index 40c9ed5009..cff87628c0 100755 --- a/zone/gm_commands/ipban.cpp +++ b/zone/gm_commands/ipban.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_ipban(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/kick.cpp b/zone/gm_commands/kick.cpp index a0dd45b188..2825312d8f 100755 --- a/zone/gm_commands/kick.cpp +++ b/zone/gm_commands/kick.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/kill.cpp b/zone/gm_commands/kill.cpp index 5a56838e1d..56c272fc82 100755 --- a/zone/gm_commands/kill.cpp +++ b/zone/gm_commands/kill.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_kill(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/killallnpcs.cpp b/zone/gm_commands/killallnpcs.cpp index 146ee1e2d0..94565845ba 100755 --- a/zone/gm_commands/killallnpcs.cpp +++ b/zone/gm_commands/killallnpcs.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_killallnpcs(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/list.cpp b/zone/gm_commands/list.cpp index d39b424baa..74c1eb7b0e 100755 --- a/zone/gm_commands/list.cpp +++ b/zone/gm_commands/list.cpp @@ -1,8 +1,8 @@ -#include "../client.h" -#include "../corpse.h" -#include "../object.h" -#include "../doors.h" -#include "../command.h" +#include "zone/client.h" +#include "zone/command.h" +#include "zone/corpse.h" +#include "zone/doors.h" +#include "zone/object.h" struct UniqueEntity { uint16 entity_id; diff --git a/zone/gm_commands/loc.cpp b/zone/gm_commands/loc.cpp index b7b627fcb6..6579a8d95d 100755 --- a/zone/gm_commands/loc.cpp +++ b/zone/gm_commands/loc.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../water_map.h" +#include "zone/client.h" +#include "zone/water_map.h" void command_loc(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/logs.cpp b/zone/gm_commands/logs.cpp index 366a56c793..33ace54e4e 100755 --- a/zone/gm_commands/logs.cpp +++ b/zone/gm_commands/logs.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/lootsim.cpp b/zone/gm_commands/lootsim.cpp index 7832062195..55a7dc9d96 100755 --- a/zone/gm_commands/lootsim.cpp +++ b/zone/gm_commands/lootsim.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_lootsim(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/makepet.cpp b/zone/gm_commands/makepet.cpp index 30dd086f65..d23e552c98 100755 --- a/zone/gm_commands/makepet.cpp +++ b/zone/gm_commands/makepet.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_makepet(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/memspell.cpp b/zone/gm_commands/memspell.cpp index c48e986a70..148a192730 100755 --- a/zone/gm_commands/memspell.cpp +++ b/zone/gm_commands/memspell.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_memspell(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/merchantshop.cpp b/zone/gm_commands/merchantshop.cpp index 686fe2c27b..4e950ac986 100755 --- a/zone/gm_commands/merchantshop.cpp +++ b/zone/gm_commands/merchantshop.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_merchantshop(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/modifynpcstat.cpp b/zone/gm_commands/modifynpcstat.cpp index 124f8cecaa..00ff3d9b31 100755 --- a/zone/gm_commands/modifynpcstat.cpp +++ b/zone/gm_commands/modifynpcstat.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" std::map GetModifyNPCStatMap() { diff --git a/zone/gm_commands/movechar.cpp b/zone/gm_commands/movechar.cpp index c20d6f229f..7dc31424b6 100755 --- a/zone/gm_commands/movechar.cpp +++ b/zone/gm_commands/movechar.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_movechar(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/movement.cpp b/zone/gm_commands/movement.cpp index b690f42099..992de368dc 100755 --- a/zone/gm_commands/movement.cpp +++ b/zone/gm_commands/movement.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../mob_movement_manager.h" +#include "zone/client.h" +#include "zone/mob_movement_manager.h" void command_movement(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/myskills.cpp b/zone/gm_commands/myskills.cpp index d781f50ca8..423783ff3a 100755 --- a/zone/gm_commands/myskills.cpp +++ b/zone/gm_commands/myskills.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_myskills(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/mysql.cpp b/zone/gm_commands/mysql.cpp index 1b915f4713..fc6dadedf6 100755 --- a/zone/gm_commands/mysql.cpp +++ b/zone/gm_commands/mysql.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_mysql(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/mystats.cpp b/zone/gm_commands/mystats.cpp index fc16929d43..428c8ed52b 100755 --- a/zone/gm_commands/mystats.cpp +++ b/zone/gm_commands/mystats.cpp @@ -1,5 +1,5 @@ -#include "../bot.h" -#include "../client.h" +#include "zone/bot.h" +#include "zone/client.h" void command_mystats(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/npccast.cpp b/zone/gm_commands/npccast.cpp index 14cdb8395f..2d3b5f5212 100755 --- a/zone/gm_commands/npccast.cpp +++ b/zone/gm_commands/npccast.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_npccast(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/npcedit.cpp b/zone/gm_commands/npcedit.cpp index ff0080e67d..a1b60ca7af 100755 --- a/zone/gm_commands/npcedit.cpp +++ b/zone/gm_commands/npcedit.cpp @@ -1,7 +1,7 @@ -#include "../client.h" -#include "../groups.h" -#include "../raids.h" -#include "../../common/repositories/npc_types_repository.h" +#include "common/repositories/npc_types_repository.h" +#include "zone/client.h" +#include "zone/groups.h" +#include "zone/raids.h" void SendNPCEditSubCommands(Client *c) { diff --git a/zone/gm_commands/npceditmass.cpp b/zone/gm_commands/npceditmass.cpp index a8542c9e46..4e32e24e33 100755 --- a/zone/gm_commands/npceditmass.cpp +++ b/zone/gm_commands/npceditmass.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_npceditmass(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/npcemote.cpp b/zone/gm_commands/npcemote.cpp index 52697c6d67..81552ce80f 100755 --- a/zone/gm_commands/npcemote.cpp +++ b/zone/gm_commands/npcemote.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_npcemote(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/npcloot.cpp b/zone/gm_commands/npcloot.cpp index 55ae48faf7..c33cac9bb8 100755 --- a/zone/gm_commands/npcloot.cpp +++ b/zone/gm_commands/npcloot.cpp @@ -1,6 +1,6 @@ -#include "../client.h" -#include "../corpse.h" -#include "../../common/data_verification.h" +#include "common/data_verification.h" +#include "zone/client.h" +#include "zone/corpse.h" void command_npcloot(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/npcsay.cpp b/zone/gm_commands/npcsay.cpp index ff13bd3d7b..6ffb6cf411 100755 --- a/zone/gm_commands/npcsay.cpp +++ b/zone/gm_commands/npcsay.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_npcsay(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/npcshout.cpp b/zone/gm_commands/npcshout.cpp index baadc3d07f..d3865fa707 100755 --- a/zone/gm_commands/npcshout.cpp +++ b/zone/gm_commands/npcshout.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_npcshout(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/npcspawn.cpp b/zone/gm_commands/npcspawn.cpp index 4e97bdf389..f3c274db14 100755 --- a/zone/gm_commands/npcspawn.cpp +++ b/zone/gm_commands/npcspawn.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_npcspawn(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/npctypespawn.cpp b/zone/gm_commands/npctypespawn.cpp index 9bbc77ba7b..4c0647e528 100755 --- a/zone/gm_commands/npctypespawn.cpp +++ b/zone/gm_commands/npctypespawn.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_npctypespawn(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/nudge.cpp b/zone/gm_commands/nudge.cpp index d1219261ea..2544f15747 100755 --- a/zone/gm_commands/nudge.cpp +++ b/zone/gm_commands/nudge.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_nudge(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/nukebuffs.cpp b/zone/gm_commands/nukebuffs.cpp index 27db600fbd..b4d27b1a25 100755 --- a/zone/gm_commands/nukebuffs.cpp +++ b/zone/gm_commands/nukebuffs.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_nukebuffs(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/nukeitem.cpp b/zone/gm_commands/nukeitem.cpp index 0918ce1e01..b7198e5c95 100755 --- a/zone/gm_commands/nukeitem.cpp +++ b/zone/gm_commands/nukeitem.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_nukeitem(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/object.cpp b/zone/gm_commands/object.cpp index 19a5d8db5f..9dbca5656e 100755 --- a/zone/gm_commands/object.cpp +++ b/zone/gm_commands/object.cpp @@ -1,6 +1,7 @@ -#include "../client.h" #include "object_manipulation.h" +#include "zone/client.h" + void command_object(Client *c, const Seperator *sep) { ObjectManipulation::CommandHandler(c, sep); diff --git a/zone/gm_commands/object_manipulation.cpp b/zone/gm_commands/object_manipulation.cpp index 9edce5f0e0..a5ae7f5558 100644 --- a/zone/gm_commands/object_manipulation.cpp +++ b/zone/gm_commands/object_manipulation.cpp @@ -1,9 +1,9 @@ +#include "common/misc_functions.h" +#include "common/repositories/object_repository.h" +#include "common/strings.h" #include "object_manipulation.h" -#include "../doors.h" -#include "../object.h" -#include "../../common/misc_functions.h" -#include "../../common/strings.h" -#include "../../common/repositories/object_repository.h" +#include "zone/doors.h" +#include "zone/object.h" #define MAX_CLIENT_MESSAGE_LENGTH 2000 diff --git a/zone/gm_commands/object_manipulation.h b/zone/gm_commands/object_manipulation.h index 57503b0144..b8ffe2b2f1 100644 --- a/zone/gm_commands/object_manipulation.h +++ b/zone/gm_commands/object_manipulation.h @@ -1,7 +1,6 @@ -#ifndef EQEMU_OBJECT_MANIPULATION_H -#define EQEMU_OBJECT_MANIPULATION_H +#pragma once -#include "../client.h" +#include "zone/client.h" class ObjectManipulation { @@ -10,6 +9,3 @@ class ObjectManipulation { static void CommandHeader(Client *c); static void SendSubcommands(Client *c); }; - - -#endif //EQEMU_OBJECT_MANIPULATION_H diff --git a/zone/gm_commands/parcels.cpp b/zone/gm_commands/parcels.cpp index 264b4b6702..da7e843ab0 100644 --- a/zone/gm_commands/parcels.cpp +++ b/zone/gm_commands/parcels.cpp @@ -1,8 +1,8 @@ -#include "../client.h" -#include "../queryserv.h" -#include "../worldserver.h" -#include "../../common/events/player_event_logs.h" -#include "../string_ids.h" +#include "common/events/player_event_logs.h" +#include "zone/client.h" +#include "zone/queryserv.h" +#include "zone/string_ids.h" +#include "zone/worldserver.h" extern QueryServ *QServ; extern WorldServer worldserver; @@ -319,4 +319,4 @@ void command_parcels(Client *c, const Seperator *sep) c->SendParcelDeliveryToWorld(ps); } } -} \ No newline at end of file +} diff --git a/zone/gm_commands/path.cpp b/zone/gm_commands/path.cpp index 79d33c3cd3..a4393a55aa 100755 --- a/zone/gm_commands/path.cpp +++ b/zone/gm_commands/path.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_path(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/peqzone.cpp b/zone/gm_commands/peqzone.cpp index 15b4109af5..052379bf1e 100755 --- a/zone/gm_commands/peqzone.cpp +++ b/zone/gm_commands/peqzone.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_peqzone(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/petitems.cpp b/zone/gm_commands/petitems.cpp index 6dd6462e50..c9f7e94818 100644 --- a/zone/gm_commands/petitems.cpp +++ b/zone/gm_commands/petitems.cpp @@ -1,5 +1,5 @@ -#include "../bot.h" -#include "../client.h" +#include "zone/bot.h" +#include "zone/client.h" void command_petitems(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/petname.cpp b/zone/gm_commands/petname.cpp index 44e8c73632..04cc71e5a2 100755 --- a/zone/gm_commands/petname.cpp +++ b/zone/gm_commands/petname.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_petname(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/picklock.cpp b/zone/gm_commands/picklock.cpp index 7d6efc607f..4ee3688287 100755 --- a/zone/gm_commands/picklock.cpp +++ b/zone/gm_commands/picklock.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_picklock(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/profanity.cpp b/zone/gm_commands/profanity.cpp index bea0886907..daf3309bd8 100755 --- a/zone/gm_commands/profanity.cpp +++ b/zone/gm_commands/profanity.cpp @@ -1,9 +1,9 @@ -#include "../client.h" -#include "../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; -#include "../../common/profanity_manager.h" +#include "common/profanity_manager.h" void command_profanity(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/push.cpp b/zone/gm_commands/push.cpp index 05042fb744..9bc4da240b 100755 --- a/zone/gm_commands/push.cpp +++ b/zone/gm_commands/push.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../fastmath.h" +#include "zone/client.h" +#include "zone/fastmath.h" extern FastMath g_Math; diff --git a/zone/gm_commands/raidloot.cpp b/zone/gm_commands/raidloot.cpp index 5bd3f3c8c5..745282c868 100755 --- a/zone/gm_commands/raidloot.cpp +++ b/zone/gm_commands/raidloot.cpp @@ -1,7 +1,6 @@ -#include "../client.h" -#include "../groups.h" -#include "../raids.h" -#include "../raids.h" +#include "zone/client.h" +#include "zone/groups.h" +#include "zone/raids.h" void command_raidloot(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/randomfeatures.cpp b/zone/gm_commands/randomfeatures.cpp index 4a771ba13c..a28b130654 100755 --- a/zone/gm_commands/randomfeatures.cpp +++ b/zone/gm_commands/randomfeatures.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_randomfeatures(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/refreshgroup.cpp b/zone/gm_commands/refreshgroup.cpp index e78a2d2cd0..4b1500b4b6 100755 --- a/zone/gm_commands/refreshgroup.cpp +++ b/zone/gm_commands/refreshgroup.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../groups.h" +#include "zone/client.h" +#include "zone/groups.h" void command_refreshgroup(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/reload.cpp b/zone/gm_commands/reload.cpp index d0081e34a5..6991a37be2 100644 --- a/zone/gm_commands/reload.cpp +++ b/zone/gm_commands/reload.cpp @@ -1,8 +1,9 @@ +#include "common/server_reload_types.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/worldserver.h" + #include -#include "../client.h" -#include "../../common/strings.h" -#include "../../common/server_reload_types.h" -#include "../worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/removeitem.cpp b/zone/gm_commands/removeitem.cpp index 0ed69eb454..05cfb26af8 100644 --- a/zone/gm_commands/removeitem.cpp +++ b/zone/gm_commands/removeitem.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_removeitem(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/repop.cpp b/zone/gm_commands/repop.cpp index 8527d92609..cd600b3d99 100755 --- a/zone/gm_commands/repop.cpp +++ b/zone/gm_commands/repop.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_repop(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/resetaa.cpp b/zone/gm_commands/resetaa.cpp index 3e50b627b3..40236ef4e5 100755 --- a/zone/gm_commands/resetaa.cpp +++ b/zone/gm_commands/resetaa.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_resetaa(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/resetaa_timer.cpp b/zone/gm_commands/resetaa_timer.cpp index 766c76b060..4107e2a9d0 100755 --- a/zone/gm_commands/resetaa_timer.cpp +++ b/zone/gm_commands/resetaa_timer.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_resetaa_timer(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/resetdisc_timer.cpp b/zone/gm_commands/resetdisc_timer.cpp index 4223aab620..86c98ebba3 100755 --- a/zone/gm_commands/resetdisc_timer.cpp +++ b/zone/gm_commands/resetdisc_timer.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_resetdisc_timer(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/revoke.cpp b/zone/gm_commands/revoke.cpp index abad1655b2..24d6e89339 100755 --- a/zone/gm_commands/revoke.cpp +++ b/zone/gm_commands/revoke.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/roambox.cpp b/zone/gm_commands/roambox.cpp index 410928f9d2..fd762373b2 100755 --- a/zone/gm_commands/roambox.cpp +++ b/zone/gm_commands/roambox.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../groups.h" +#include "zone/client.h" +#include "zone/groups.h" void command_roambox(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/rules.cpp b/zone/gm_commands/rules.cpp index 22d923709d..526f24861b 100755 --- a/zone/gm_commands/rules.cpp +++ b/zone/gm_commands/rules.cpp @@ -1,8 +1,7 @@ -#include "../client.h" -#include "../command.h" - -#include "../../common/repositories/rule_sets_repository.h" -#include "../../common/repositories/rule_values_repository.h" +#include "common/repositories/rule_sets_repository.h" +#include "common/repositories/rule_values_repository.h" +#include "zone/client.h" +#include "zone/command.h" void command_rules(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/save.cpp b/zone/gm_commands/save.cpp index 54d248dfc6..8d7df60c0a 100755 --- a/zone/gm_commands/save.cpp +++ b/zone/gm_commands/save.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../corpse.h" +#include "zone/client.h" +#include "zone/corpse.h" void command_save(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/scale.cpp b/zone/gm_commands/scale.cpp index 792d120663..8169ccd37b 100755 --- a/zone/gm_commands/scale.cpp +++ b/zone/gm_commands/scale.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../npc_scale_manager.h" +#include "zone/client.h" +#include "zone/npc_scale_manager.h" void command_scale(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/scribespell.cpp b/zone/gm_commands/scribespell.cpp index b3c5b3902f..7b5d40605b 100755 --- a/zone/gm_commands/scribespell.cpp +++ b/zone/gm_commands/scribespell.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_scribespell(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/scribespells.cpp b/zone/gm_commands/scribespells.cpp index 93ce215381..f9a016594e 100755 --- a/zone/gm_commands/scribespells.cpp +++ b/zone/gm_commands/scribespells.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_scribespells(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/sendzonespawns.cpp b/zone/gm_commands/sendzonespawns.cpp index caca8f6d0d..3834ad7fb0 100755 --- a/zone/gm_commands/sendzonespawns.cpp +++ b/zone/gm_commands/sendzonespawns.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_sendzonespawns(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/sensetrap.cpp b/zone/gm_commands/sensetrap.cpp index 0bfaa441fa..89b6e68299 100755 --- a/zone/gm_commands/sensetrap.cpp +++ b/zone/gm_commands/sensetrap.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_sensetrap(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/serverrules.cpp b/zone/gm_commands/serverrules.cpp index e555e4b716..aaf9768de5 100755 --- a/zone/gm_commands/serverrules.cpp +++ b/zone/gm_commands/serverrules.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_serverrules(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set.cpp b/zone/gm_commands/set.cpp index 1460ea029e..439881fee7 100644 --- a/zone/gm_commands/set.cpp +++ b/zone/gm_commands/set.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void SetAAEXP(Client *c, const Seperator *sep); void SetAAPoints(Client *c, const Seperator *sep); diff --git a/zone/gm_commands/set/set_aa_exp.cpp b/zone/gm_commands/set/set_aa_exp.cpp index d4fd23e4a5..2f3d177047 100644 --- a/zone/gm_commands/set/set_aa_exp.cpp +++ b/zone/gm_commands/set/set_aa_exp.cpp @@ -1,7 +1,6 @@ -#include "../../client.h" -#include "../../groups.h" -#include "../../raids.h" -#include "../../raids.h" +#include "zone/client.h" +#include "zone/groups.h" +#include "zone/raids.h" void SetAAEXP(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_aa_points.cpp b/zone/gm_commands/set/set_aa_points.cpp index ab1bb8bfde..8239441098 100644 --- a/zone/gm_commands/set/set_aa_points.cpp +++ b/zone/gm_commands/set/set_aa_points.cpp @@ -1,7 +1,6 @@ -#include "../../client.h" -#include "../../groups.h" -#include "../../raids.h" -#include "../../raids.h" +#include "zone/client.h" +#include "zone/groups.h" +#include "zone/raids.h" void SetAAPoints(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_adventure_points.cpp b/zone/gm_commands/set/set_adventure_points.cpp index 55465039a6..c904ea6ac9 100644 --- a/zone/gm_commands/set/set_adventure_points.cpp +++ b/zone/gm_commands/set/set_adventure_points.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/data_verification.h" +#include "common/data_verification.h" +#include "zone/client.h" void SetAdventurePoints(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_alternate_currency.cpp b/zone/gm_commands/set/set_alternate_currency.cpp index 3718076feb..47d7e81d45 100644 --- a/zone/gm_commands/set/set_alternate_currency.cpp +++ b/zone/gm_commands/set/set_alternate_currency.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetAlternateCurrency(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_animation.cpp b/zone/gm_commands/set/set_animation.cpp index 416235067f..8cc7b83035 100644 --- a/zone/gm_commands/set/set_animation.cpp +++ b/zone/gm_commands/set/set_animation.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetAnimation(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_anon.cpp b/zone/gm_commands/set/set_anon.cpp index e0b84f7fb7..7a90c0019f 100644 --- a/zone/gm_commands/set/set_anon.cpp +++ b/zone/gm_commands/set/set_anon.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/repositories/character_data_repository.h" +#include "common/repositories/character_data_repository.h" +#include "zone/client.h" void SetAnon(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_auto_login.cpp b/zone/gm_commands/set/set_auto_login.cpp index 829c739e30..92f4b22839 100644 --- a/zone/gm_commands/set/set_auto_login.cpp +++ b/zone/gm_commands/set/set_auto_login.cpp @@ -1,8 +1,7 @@ -#include "../../client.h" -#include "../../groups.h" -#include "../../raids.h" -#include "../../raids.h" -#include "../../../common/repositories/account_repository.h" +#include "common/repositories/account_repository.h" +#include "zone/client.h" +#include "zone/groups.h" +#include "zone/raids.h" void SetAutoLogin(Client* c, const Seperator* sep) { diff --git a/zone/gm_commands/set/set_bind_point.cpp b/zone/gm_commands/set/set_bind_point.cpp index 8d5bbb626b..9741c15e73 100644 --- a/zone/gm_commands/set/set_bind_point.cpp +++ b/zone/gm_commands/set/set_bind_point.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetBindPoint(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_checksum.cpp b/zone/gm_commands/set/set_checksum.cpp index 02032fe01e..f19c16294a 100644 --- a/zone/gm_commands/set/set_checksum.cpp +++ b/zone/gm_commands/set/set_checksum.cpp @@ -1,6 +1,6 @@ -#include "../../client.h" -#include "../../worldserver.h" -#include "../../../common/repositories/account_repository.h" +#include "common/repositories/account_repository.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/set/set_class_permanent.cpp b/zone/gm_commands/set/set_class_permanent.cpp index abce4979f0..26f8fcd061 100644 --- a/zone/gm_commands/set/set_class_permanent.cpp +++ b/zone/gm_commands/set/set_class_permanent.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetClassPermanent(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_crystals.cpp b/zone/gm_commands/set/set_crystals.cpp index 84bfc35256..ee6eebd92b 100644 --- a/zone/gm_commands/set/set_crystals.cpp +++ b/zone/gm_commands/set/set_crystals.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetCrystals(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_date.cpp b/zone/gm_commands/set/set_date.cpp index 5531db20d1..cc10cfeac5 100644 --- a/zone/gm_commands/set/set_date.cpp +++ b/zone/gm_commands/set/set_date.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetDate(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_endurance.cpp b/zone/gm_commands/set/set_endurance.cpp index f4a8c375bb..92e9877227 100644 --- a/zone/gm_commands/set/set_endurance.cpp +++ b/zone/gm_commands/set/set_endurance.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetEndurance(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_endurance_full.cpp b/zone/gm_commands/set/set_endurance_full.cpp index 8b493e41ee..c0571c59ab 100644 --- a/zone/gm_commands/set/set_endurance_full.cpp +++ b/zone/gm_commands/set/set_endurance_full.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetEnduranceFull(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_exp.cpp b/zone/gm_commands/set/set_exp.cpp index 20832aba5a..c661bd06ff 100644 --- a/zone/gm_commands/set/set_exp.cpp +++ b/zone/gm_commands/set/set_exp.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetEXP(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_flymode.cpp b/zone/gm_commands/set/set_flymode.cpp index 34edf88e9c..63cf5f8f6c 100644 --- a/zone/gm_commands/set/set_flymode.cpp +++ b/zone/gm_commands/set/set_flymode.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/data_verification.h" +#include "common/data_verification.h" +#include "zone/client.h" void SetFlymode(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_frozen.cpp b/zone/gm_commands/set/set_frozen.cpp index 223f592145..737c257cee 100644 --- a/zone/gm_commands/set/set_frozen.cpp +++ b/zone/gm_commands/set/set_frozen.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetFrozen(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_gender.cpp b/zone/gm_commands/set/set_gender.cpp index bc91f10740..549aefa156 100644 --- a/zone/gm_commands/set/set_gender.cpp +++ b/zone/gm_commands/set/set_gender.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetGender(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_gender_permanent.cpp b/zone/gm_commands/set/set_gender_permanent.cpp index 9a2855cb3c..9fa70fc7f0 100644 --- a/zone/gm_commands/set/set_gender_permanent.cpp +++ b/zone/gm_commands/set/set_gender_permanent.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetGenderPermanent(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_gm.cpp b/zone/gm_commands/set/set_gm.cpp index 19aca7826c..9840988238 100644 --- a/zone/gm_commands/set/set_gm.cpp +++ b/zone/gm_commands/set/set_gm.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetGM(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_gm_speed.cpp b/zone/gm_commands/set/set_gm_speed.cpp index ffcef33b3c..f6c4c2d5a6 100644 --- a/zone/gm_commands/set/set_gm_speed.cpp +++ b/zone/gm_commands/set/set_gm_speed.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetGMSpeed(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_gm_status.cpp b/zone/gm_commands/set/set_gm_status.cpp index aae8dcff30..42684c955d 100644 --- a/zone/gm_commands/set/set_gm_status.cpp +++ b/zone/gm_commands/set/set_gm_status.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/set/set_god_mode.cpp b/zone/gm_commands/set/set_god_mode.cpp index 41f517cfac..377a0fec1c 100644 --- a/zone/gm_commands/set/set_god_mode.cpp +++ b/zone/gm_commands/set/set_god_mode.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/repositories/account_repository.h" +#include "common/repositories/account_repository.h" +#include "zone/client.h" void SetGodMode(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_haste.cpp b/zone/gm_commands/set/set_haste.cpp index 96647c9708..a295b6434f 100644 --- a/zone/gm_commands/set/set_haste.cpp +++ b/zone/gm_commands/set/set_haste.cpp @@ -1,5 +1,5 @@ -#include "../../bot.h" -#include "../../client.h" +#include "zone/bot.h" +#include "zone/client.h" void SetHaste(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_hero_model.cpp b/zone/gm_commands/set/set_hero_model.cpp index f98b5d5e2f..485ec31f12 100644 --- a/zone/gm_commands/set/set_hero_model.cpp +++ b/zone/gm_commands/set/set_hero_model.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetHeroModel(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_hide_me.cpp b/zone/gm_commands/set/set_hide_me.cpp index 8b2e580f10..a0063e4889 100644 --- a/zone/gm_commands/set/set_hide_me.cpp +++ b/zone/gm_commands/set/set_hide_me.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetHideMe(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_hp.cpp b/zone/gm_commands/set/set_hp.cpp index 3078cc98c8..cd71c0e346 100644 --- a/zone/gm_commands/set/set_hp.cpp +++ b/zone/gm_commands/set/set_hp.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetHP(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_hp_full.cpp b/zone/gm_commands/set/set_hp_full.cpp index 738bb5db8d..22a7936d81 100644 --- a/zone/gm_commands/set/set_hp_full.cpp +++ b/zone/gm_commands/set/set_hp_full.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetHPFull(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_invulnerable.cpp b/zone/gm_commands/set/set_invulnerable.cpp index f8efcb2d76..59f66d10b3 100644 --- a/zone/gm_commands/set/set_invulnerable.cpp +++ b/zone/gm_commands/set/set_invulnerable.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetInvulnerable(Client *c, const Seperator *sep) { const auto arguments = sep->argnum; diff --git a/zone/gm_commands/set/set_language.cpp b/zone/gm_commands/set/set_language.cpp index e82af80a58..2593c21aed 100644 --- a/zone/gm_commands/set/set_language.cpp +++ b/zone/gm_commands/set/set_language.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/data_verification.h" +#include "common/data_verification.h" +#include "zone/client.h" void SetLanguage(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_last_name.cpp b/zone/gm_commands/set/set_last_name.cpp index 8fd23789ec..981b3e11f1 100644 --- a/zone/gm_commands/set/set_last_name.cpp +++ b/zone/gm_commands/set/set_last_name.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetLastName(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_level.cpp b/zone/gm_commands/set/set_level.cpp index 6e88705c48..dd0153f695 100644 --- a/zone/gm_commands/set/set_level.cpp +++ b/zone/gm_commands/set/set_level.cpp @@ -1,5 +1,5 @@ -#include "../../bot.h" -#include "../../client.h" +#include "zone/bot.h" +#include "zone/client.h" void SetLevel(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_loginserver_info.cpp b/zone/gm_commands/set/set_loginserver_info.cpp index 5155bb284c..020ac3fad7 100644 --- a/zone/gm_commands/set/set_loginserver_info.cpp +++ b/zone/gm_commands/set/set_loginserver_info.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/set/set_mana.cpp b/zone/gm_commands/set/set_mana.cpp index 68779dc475..1813ec8751 100644 --- a/zone/gm_commands/set/set_mana.cpp +++ b/zone/gm_commands/set/set_mana.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetMana(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_mana_full.cpp b/zone/gm_commands/set/set_mana_full.cpp index 5b9ad77bb4..9bfd3718dd 100644 --- a/zone/gm_commands/set/set_mana_full.cpp +++ b/zone/gm_commands/set/set_mana_full.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetManaFull(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_motd.cpp b/zone/gm_commands/set/set_motd.cpp index 8d188ab489..11f572ea58 100644 --- a/zone/gm_commands/set/set_motd.cpp +++ b/zone/gm_commands/set/set_motd.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/set/set_name.cpp b/zone/gm_commands/set/set_name.cpp index c700060b9f..bbf1e8ca10 100644 --- a/zone/gm_commands/set/set_name.cpp +++ b/zone/gm_commands/set/set_name.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetName(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_ooc_mute.cpp b/zone/gm_commands/set/set_ooc_mute.cpp index 4f2db4e87c..ecd9c07ce0 100644 --- a/zone/gm_commands/set/set_ooc_mute.cpp +++ b/zone/gm_commands/set/set_ooc_mute.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/set/set_password.cpp b/zone/gm_commands/set/set_password.cpp index d057daa4bf..2974424f08 100644 --- a/zone/gm_commands/set/set_password.cpp +++ b/zone/gm_commands/set/set_password.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetPassword(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_pvp.cpp b/zone/gm_commands/set/set_pvp.cpp index f851ddea19..6a9d7092d1 100644 --- a/zone/gm_commands/set/set_pvp.cpp +++ b/zone/gm_commands/set/set_pvp.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetPVP(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_pvp_points.cpp b/zone/gm_commands/set/set_pvp_points.cpp index 1562eaf125..f8661e84b3 100644 --- a/zone/gm_commands/set/set_pvp_points.cpp +++ b/zone/gm_commands/set/set_pvp_points.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetPVPPoints(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_race.cpp b/zone/gm_commands/set/set_race.cpp index 4a5f86c31c..9d18a8ff91 100644 --- a/zone/gm_commands/set/set_race.cpp +++ b/zone/gm_commands/set/set_race.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetRace(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_race_permanent.cpp b/zone/gm_commands/set/set_race_permanent.cpp index 9c0a2d6dab..917539e2c7 100644 --- a/zone/gm_commands/set/set_race_permanent.cpp +++ b/zone/gm_commands/set/set_race_permanent.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetRacePermanent(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_server_locked.cpp b/zone/gm_commands/set/set_server_locked.cpp index 73e92dad39..b81805b708 100644 --- a/zone/gm_commands/set/set_server_locked.cpp +++ b/zone/gm_commands/set/set_server_locked.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/set/set_skill.cpp b/zone/gm_commands/set/set_skill.cpp index b6071a9f6a..b470272f6a 100644 --- a/zone/gm_commands/set/set_skill.cpp +++ b/zone/gm_commands/set/set_skill.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetSkill(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_skill_all.cpp b/zone/gm_commands/set/set_skill_all.cpp index 1094b4bea7..7a7f128644 100644 --- a/zone/gm_commands/set/set_skill_all.cpp +++ b/zone/gm_commands/set/set_skill_all.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetSkillAll(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_skill_all_max.cpp b/zone/gm_commands/set/set_skill_all_max.cpp index 0565721f81..19e7168fbb 100644 --- a/zone/gm_commands/set/set_skill_all_max.cpp +++ b/zone/gm_commands/set/set_skill_all_max.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetSkillAllMax(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_start_zone.cpp b/zone/gm_commands/set/set_start_zone.cpp index 71748ccb91..843da575c5 100644 --- a/zone/gm_commands/set/set_start_zone.cpp +++ b/zone/gm_commands/set/set_start_zone.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetStartZone(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_temporary_name.cpp b/zone/gm_commands/set/set_temporary_name.cpp index f04577c5ba..11fcdec836 100644 --- a/zone/gm_commands/set/set_temporary_name.cpp +++ b/zone/gm_commands/set/set_temporary_name.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetTemporaryName(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_texture.cpp b/zone/gm_commands/set/set_texture.cpp index 60e1cc76c3..279e522095 100644 --- a/zone/gm_commands/set/set_texture.cpp +++ b/zone/gm_commands/set/set_texture.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetTexture(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_time.cpp b/zone/gm_commands/set/set_time.cpp index a0c0fea7ac..e3ee56132d 100644 --- a/zone/gm_commands/set/set_time.cpp +++ b/zone/gm_commands/set/set_time.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetTime(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_time_zone.cpp b/zone/gm_commands/set/set_time_zone.cpp index 91c48bb483..4a68bd7f4f 100644 --- a/zone/gm_commands/set/set_time_zone.cpp +++ b/zone/gm_commands/set/set_time_zone.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetTimeZone(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_title.cpp b/zone/gm_commands/set/set_title.cpp index a6fc8a6e22..45b3c35244 100644 --- a/zone/gm_commands/set/set_title.cpp +++ b/zone/gm_commands/set/set_title.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../titles.h" +#include "zone/client.h" +#include "zone/titles.h" void SetTitle(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_title_suffix.cpp b/zone/gm_commands/set/set_title_suffix.cpp index f6c6e66771..cf14a4f7d3 100644 --- a/zone/gm_commands/set/set_title_suffix.cpp +++ b/zone/gm_commands/set/set_title_suffix.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../titles.h" +#include "zone/client.h" +#include "zone/titles.h" void SetTitleSuffix(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_weather.cpp b/zone/gm_commands/set/set_weather.cpp index 028ba23876..73969a65ef 100644 --- a/zone/gm_commands/set/set_weather.cpp +++ b/zone/gm_commands/set/set_weather.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void SetWeather(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_zone.cpp b/zone/gm_commands/set/set_zone.cpp index d2bfecaedd..ecb9e3cc60 100644 --- a/zone/gm_commands/set/set_zone.cpp +++ b/zone/gm_commands/set/set_zone.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/show.cpp b/zone/gm_commands/show.cpp index 651cde5376..027ee164cd 100755 --- a/zone/gm_commands/show.cpp +++ b/zone/gm_commands/show.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void ShowAAs(Client* c, const Seperator* sep); void ShowAAPoints(Client* c, const Seperator* sep); diff --git a/zone/gm_commands/show/show_aa_points.cpp b/zone/gm_commands/show/show_aa_points.cpp index b8f556301c..d199a740c7 100644 --- a/zone/gm_commands/show/show_aa_points.cpp +++ b/zone/gm_commands/show/show_aa_points.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../dialogue_window.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void ShowAAPoints(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_aas.cpp b/zone/gm_commands/show/show_aas.cpp index f631ac4746..cb14fdd5a5 100644 --- a/zone/gm_commands/show/show_aas.cpp +++ b/zone/gm_commands/show/show_aas.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowAAs(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_aggro.cpp b/zone/gm_commands/show/show_aggro.cpp index c579dc4c37..681200b3d4 100644 --- a/zone/gm_commands/show/show_aggro.cpp +++ b/zone/gm_commands/show/show_aggro.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowAggro(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_auto_login.cpp b/zone/gm_commands/show/show_auto_login.cpp index 2a82e5b0b2..2cbe814113 100644 --- a/zone/gm_commands/show/show_auto_login.cpp +++ b/zone/gm_commands/show/show_auto_login.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/repositories/account_repository.h" +#include "common/repositories/account_repository.h" +#include "zone/client.h" void ShowAutoLogin(Client* c, const Seperator* sep) { diff --git a/zone/gm_commands/show/show_buffs.cpp b/zone/gm_commands/show/show_buffs.cpp index eec2451d6f..2b4f599936 100644 --- a/zone/gm_commands/show/show_buffs.cpp +++ b/zone/gm_commands/show/show_buffs.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowBuffs(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_buried_corpse_count.cpp b/zone/gm_commands/show/show_buried_corpse_count.cpp index 55cec83dd9..99f6140c30 100644 --- a/zone/gm_commands/show/show_buried_corpse_count.cpp +++ b/zone/gm_commands/show/show_buried_corpse_count.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../corpse.h" +#include "zone/client.h" +#include "zone/corpse.h" void ShowBuriedCorpseCount(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_client_version_summary.cpp b/zone/gm_commands/show/show_client_version_summary.cpp index 98b5d4f52c..b3c022c4aa 100644 --- a/zone/gm_commands/show/show_client_version_summary.cpp +++ b/zone/gm_commands/show/show_client_version_summary.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/show/show_content_flags.cpp b/zone/gm_commands/show/show_content_flags.cpp index bba89ce18b..8861c8fcce 100644 --- a/zone/gm_commands/show/show_content_flags.cpp +++ b/zone/gm_commands/show/show_content_flags.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../dialogue_window.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void ShowContentFlags(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_currencies.cpp b/zone/gm_commands/show/show_currencies.cpp index 4f4d3cfdac..6d501a5a36 100644 --- a/zone/gm_commands/show/show_currencies.cpp +++ b/zone/gm_commands/show/show_currencies.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../dialogue_window.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void ShowCurrencies(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_distance.cpp b/zone/gm_commands/show/show_distance.cpp index aece8494ea..5ae62477d5 100644 --- a/zone/gm_commands/show/show_distance.cpp +++ b/zone/gm_commands/show/show_distance.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowDistance(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_emotes.cpp b/zone/gm_commands/show/show_emotes.cpp index 38d9c16ce0..9f76da70e3 100644 --- a/zone/gm_commands/show/show_emotes.cpp +++ b/zone/gm_commands/show/show_emotes.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowEmotes(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_field_of_view.cpp b/zone/gm_commands/show/show_field_of_view.cpp index dfa617a35b..a93e56469b 100644 --- a/zone/gm_commands/show/show_field_of_view.cpp +++ b/zone/gm_commands/show/show_field_of_view.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowFieldOfView(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_flags.cpp b/zone/gm_commands/show/show_flags.cpp index 50b5e183ca..14a4592f14 100644 --- a/zone/gm_commands/show/show_flags.cpp +++ b/zone/gm_commands/show/show_flags.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowFlags(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_group_info.cpp b/zone/gm_commands/show/show_group_info.cpp index 8524240aa3..4b56c420a5 100644 --- a/zone/gm_commands/show/show_group_info.cpp +++ b/zone/gm_commands/show/show_group_info.cpp @@ -1,6 +1,6 @@ -#include "../../client.h" -#include "../../dialogue_window.h" -#include "../../groups.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" +#include "zone/groups.h" void ShowGroupInfo(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_hatelist.cpp b/zone/gm_commands/show/show_hatelist.cpp index 225ad16f42..bb50f9eb52 100644 --- a/zone/gm_commands/show/show_hatelist.cpp +++ b/zone/gm_commands/show/show_hatelist.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowHateList(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_inventory.cpp b/zone/gm_commands/show/show_inventory.cpp index 2a3e2a377d..4abfd6a689 100644 --- a/zone/gm_commands/show/show_inventory.cpp +++ b/zone/gm_commands/show/show_inventory.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../object.h" +#include "zone/client.h" +#include "zone/object.h" void SendShowInventorySubCommands(Client* c) { c->Message(Chat::White, "Usage: #show inventory equip - Shows items in Equipment slots"); @@ -448,4 +448,4 @@ void ShowInventory(Client *c, const Seperator *sep) if (!found_items) { c->Message(Chat::White, "No items found."); } -} \ No newline at end of file +} diff --git a/zone/gm_commands/show/show_ip_lookup.cpp b/zone/gm_commands/show/show_ip_lookup.cpp index aefcaeaf3c..74bd449cb4 100644 --- a/zone/gm_commands/show/show_ip_lookup.cpp +++ b/zone/gm_commands/show/show_ip_lookup.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/show/show_keyring.cpp b/zone/gm_commands/show/show_keyring.cpp index 39552f8ccb..c970570471 100644 --- a/zone/gm_commands/show/show_keyring.cpp +++ b/zone/gm_commands/show/show_keyring.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../dialogue_window.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void ShowKeyring(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_line_of_sight.cpp b/zone/gm_commands/show/show_line_of_sight.cpp index bf56c88663..07db29e735 100644 --- a/zone/gm_commands/show/show_line_of_sight.cpp +++ b/zone/gm_commands/show/show_line_of_sight.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowLineOfSight(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_network.cpp b/zone/gm_commands/show/show_network.cpp index 46d32a69cb..292eab6ce1 100644 --- a/zone/gm_commands/show/show_network.cpp +++ b/zone/gm_commands/show/show_network.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../dialogue_window.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void ShowNetwork(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_network_stats.cpp b/zone/gm_commands/show/show_network_stats.cpp index 75bf2b25f3..964185ef4d 100644 --- a/zone/gm_commands/show/show_network_stats.cpp +++ b/zone/gm_commands/show/show_network_stats.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../dialogue_window.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void ShowNetworkStats(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_npc_global_loot.cpp b/zone/gm_commands/show/show_npc_global_loot.cpp index 6167550c23..f0013c6f93 100644 --- a/zone/gm_commands/show/show_npc_global_loot.cpp +++ b/zone/gm_commands/show/show_npc_global_loot.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowNPCGlobalLoot(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_npc_stats.cpp b/zone/gm_commands/show/show_npc_stats.cpp index 65254e3bb8..e4dac7a213 100644 --- a/zone/gm_commands/show/show_npc_stats.cpp +++ b/zone/gm_commands/show/show_npc_stats.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowNPCStats(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_npc_type.cpp b/zone/gm_commands/show/show_npc_type.cpp index f70b19e885..4f4af24296 100644 --- a/zone/gm_commands/show/show_npc_type.cpp +++ b/zone/gm_commands/show/show_npc_type.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowNPCType(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_peqzone_flags.cpp b/zone/gm_commands/show/show_peqzone_flags.cpp index e8112436ed..dbc60b5e5d 100644 --- a/zone/gm_commands/show/show_peqzone_flags.cpp +++ b/zone/gm_commands/show/show_peqzone_flags.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowPEQZoneFlags(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_petition.cpp b/zone/gm_commands/show/show_petition.cpp index 1c15036a9e..bfccf6a3fd 100644 --- a/zone/gm_commands/show/show_petition.cpp +++ b/zone/gm_commands/show/show_petition.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/repositories/petitions_repository.h" +#include "common/repositories/petitions_repository.h" +#include "zone/client.h" void ShowPetition(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_petition_info.cpp b/zone/gm_commands/show/show_petition_info.cpp index d4a45599b2..426ef5acae 100644 --- a/zone/gm_commands/show/show_petition_info.cpp +++ b/zone/gm_commands/show/show_petition_info.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/repositories/petitions_repository.h" +#include "zone/client.h" +#include "common/repositories/petitions_repository.h" void ShowPetitionInfo(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_proximity.cpp b/zone/gm_commands/show/show_proximity.cpp index 3b8076d291..22fbf8e025 100644 --- a/zone/gm_commands/show/show_proximity.cpp +++ b/zone/gm_commands/show/show_proximity.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowProximity(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_quest_errors.cpp b/zone/gm_commands/show/show_quest_errors.cpp index 7a1bf4d9b8..59faf66056 100644 --- a/zone/gm_commands/show/show_quest_errors.cpp +++ b/zone/gm_commands/show/show_quest_errors.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../quest_parser_collection.h" +#include "zone/client.h" +#include "zone/quest_parser_collection.h" void ShowQuestErrors(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_quest_globals.cpp b/zone/gm_commands/show/show_quest_globals.cpp index 63396352b9..263763ae89 100644 --- a/zone/gm_commands/show/show_quest_globals.cpp +++ b/zone/gm_commands/show/show_quest_globals.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowQuestGlobals(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_recipe.cpp b/zone/gm_commands/show/show_recipe.cpp index c66e252180..e9357b1dce 100644 --- a/zone/gm_commands/show/show_recipe.cpp +++ b/zone/gm_commands/show/show_recipe.cpp @@ -1,7 +1,7 @@ -#include "../../client.h" -#include "../../command.h" -#include "../../../common/repositories/tradeskill_recipe_repository.h" -#include "../../../common/repositories/tradeskill_recipe_entries_repository.h" +#include "common/repositories/tradeskill_recipe_entries_repository.h" +#include "common/repositories/tradeskill_recipe_repository.h" +#include "zone/client.h" +#include "zone/command.h" void ShowRecipe(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_server_info.cpp b/zone/gm_commands/show/show_server_info.cpp index 6a8d8b7173..1b23b9d24d 100644 --- a/zone/gm_commands/show/show_server_info.cpp +++ b/zone/gm_commands/show/show_server_info.cpp @@ -1,6 +1,6 @@ -#include "../../client.h" -#include "../../dialogue_window.h" -#include "../../../common/serverinfo.h" +#include "common/serverinfo.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void ShowServerInfo(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_skills.cpp b/zone/gm_commands/show/show_skills.cpp index 20705ac162..99d335631d 100644 --- a/zone/gm_commands/show/show_skills.cpp +++ b/zone/gm_commands/show/show_skills.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../dialogue_window.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void ShowSkills(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_spawn_status.cpp b/zone/gm_commands/show/show_spawn_status.cpp index 1fd59a20f9..46c9c2b335 100644 --- a/zone/gm_commands/show/show_spawn_status.cpp +++ b/zone/gm_commands/show/show_spawn_status.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowSpawnStatus(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_special_abilities.cpp b/zone/gm_commands/show/show_special_abilities.cpp index 3e8f198bad..f5713eb1b7 100644 --- a/zone/gm_commands/show/show_special_abilities.cpp +++ b/zone/gm_commands/show/show_special_abilities.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowSpecialAbilities(Client* c, const Seperator* sep) { diff --git a/zone/gm_commands/show/show_spells.cpp b/zone/gm_commands/show/show_spells.cpp index 7d522be95e..48cf0f0fe8 100644 --- a/zone/gm_commands/show/show_spells.cpp +++ b/zone/gm_commands/show/show_spells.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowSpells(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_spells_list.cpp b/zone/gm_commands/show/show_spells_list.cpp index fb94306c11..8fa107f0f3 100644 --- a/zone/gm_commands/show/show_spells_list.cpp +++ b/zone/gm_commands/show/show_spells_list.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowSpellsList(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_stats.cpp b/zone/gm_commands/show/show_stats.cpp index be1f4d40d7..f75ac9ed29 100644 --- a/zone/gm_commands/show/show_stats.cpp +++ b/zone/gm_commands/show/show_stats.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowStats(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_timers.cpp b/zone/gm_commands/show/show_timers.cpp index 78768fb5c4..4b8ad870be 100644 --- a/zone/gm_commands/show/show_timers.cpp +++ b/zone/gm_commands/show/show_timers.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../dialogue_window.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void ShowTimers(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_traps.cpp b/zone/gm_commands/show/show_traps.cpp index 28a6215d7f..e3e6740052 100644 --- a/zone/gm_commands/show/show_traps.cpp +++ b/zone/gm_commands/show/show_traps.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowTraps(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_uptime.cpp b/zone/gm_commands/show/show_uptime.cpp index c95bcff2aa..20eca70945 100644 --- a/zone/gm_commands/show/show_uptime.cpp +++ b/zone/gm_commands/show/show_uptime.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/show/show_variable.cpp b/zone/gm_commands/show/show_variable.cpp index 98418c14b3..0a83f68a6b 100644 --- a/zone/gm_commands/show/show_variable.cpp +++ b/zone/gm_commands/show/show_variable.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowVariable(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_version.cpp b/zone/gm_commands/show/show_version.cpp index e9b55d5496..415c240f95 100644 --- a/zone/gm_commands/show/show_version.cpp +++ b/zone/gm_commands/show/show_version.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../dialogue_window.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void ShowVersion(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_waypoints.cpp b/zone/gm_commands/show/show_waypoints.cpp index 262489fca3..afc4c80552 100644 --- a/zone/gm_commands/show/show_waypoints.cpp +++ b/zone/gm_commands/show/show_waypoints.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowWaypoints(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_who.cpp b/zone/gm_commands/show/show_who.cpp index 6ffccdddf1..d3d3ed152b 100644 --- a/zone/gm_commands/show/show_who.cpp +++ b/zone/gm_commands/show/show_who.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowWho(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_xtargets.cpp b/zone/gm_commands/show/show_xtargets.cpp index f9d07387e9..d1b626f09a 100644 --- a/zone/gm_commands/show/show_xtargets.cpp +++ b/zone/gm_commands/show/show_xtargets.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../../common/data_verification.h" +#include "common/data_verification.h" +#include "zone/client.h" void ShowXTargets(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_zone_data.cpp b/zone/gm_commands/show/show_zone_data.cpp index 881f7d4dab..d9875437d9 100644 --- a/zone/gm_commands/show/show_zone_data.cpp +++ b/zone/gm_commands/show/show_zone_data.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../dialogue_window.h" +#include "zone/client.h" +#include "zone/dialogue_window.h" void ShowZoneData(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_zone_global_loot.cpp b/zone/gm_commands/show/show_zone_global_loot.cpp index 6a05fdc198..838aafb9f6 100644 --- a/zone/gm_commands/show/show_zone_global_loot.cpp +++ b/zone/gm_commands/show/show_zone_global_loot.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowZoneGlobalLoot(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_zone_loot.cpp b/zone/gm_commands/show/show_zone_loot.cpp index 6a4beb063d..22317f9b3f 100644 --- a/zone/gm_commands/show/show_zone_loot.cpp +++ b/zone/gm_commands/show/show_zone_loot.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowZoneLoot(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_zone_points.cpp b/zone/gm_commands/show/show_zone_points.cpp index b5adc4602f..778771b5e2 100644 --- a/zone/gm_commands/show/show_zone_points.cpp +++ b/zone/gm_commands/show/show_zone_points.cpp @@ -1,4 +1,4 @@ -#include "../../client.h" +#include "zone/client.h" void ShowZonePoints(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/show/show_zone_status.cpp b/zone/gm_commands/show/show_zone_status.cpp index 4ad2ea0efa..f517956fc8 100644 --- a/zone/gm_commands/show/show_zone_status.cpp +++ b/zone/gm_commands/show/show_zone_status.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/show/show_zone_variables.cpp b/zone/gm_commands/show/show_zone_variables.cpp index 4af24fa0b4..b914fd8c65 100644 --- a/zone/gm_commands/show/show_zone_variables.cpp +++ b/zone/gm_commands/show/show_zone_variables.cpp @@ -1,5 +1,5 @@ -#include "../../client.h" -#include "../../zone.h" +#include "zone/client.h" +#include "zone/zone.h" extern Zone* zone; diff --git a/zone/gm_commands/shutdown.cpp b/zone/gm_commands/shutdown.cpp index 75d77c9eb3..d7fe561ce4 100755 --- a/zone/gm_commands/shutdown.cpp +++ b/zone/gm_commands/shutdown.cpp @@ -1,5 +1,6 @@ -#include "../client.h" -#include "../../world/main.h" +#include "zone/client.h" + +void CatchSignal(int sig_num); void command_shutdown(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/spawn.cpp b/zone/gm_commands/spawn.cpp index 78ab443af1..66783c50f2 100755 --- a/zone/gm_commands/spawn.cpp +++ b/zone/gm_commands/spawn.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_spawn(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/spawneditmass.cpp b/zone/gm_commands/spawneditmass.cpp index 8c85e2fbc2..2e7028c49f 100644 --- a/zone/gm_commands/spawneditmass.cpp +++ b/zone/gm_commands/spawneditmass.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_spawneditmass(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/spawnfix.cpp b/zone/gm_commands/spawnfix.cpp index 7cfe33e7b9..cce0c882e5 100755 --- a/zone/gm_commands/spawnfix.cpp +++ b/zone/gm_commands/spawnfix.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_spawnfix(Client* c, const Seperator* sep) { diff --git a/zone/gm_commands/stun.cpp b/zone/gm_commands/stun.cpp index 32da4593ce..62ca26c52f 100755 --- a/zone/gm_commands/stun.cpp +++ b/zone/gm_commands/stun.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_stun(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/summon.cpp b/zone/gm_commands/summon.cpp index 710aea67ca..501f06345f 100755 --- a/zone/gm_commands/summon.cpp +++ b/zone/gm_commands/summon.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/summonburiedplayercorpse.cpp b/zone/gm_commands/summonburiedplayercorpse.cpp index 6ed7b4a253..3b6c859ddf 100755 --- a/zone/gm_commands/summonburiedplayercorpse.cpp +++ b/zone/gm_commands/summonburiedplayercorpse.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../corpse.h" +#include "zone/client.h" +#include "zone/corpse.h" void command_summonburiedplayercorpse(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/summonitem.cpp b/zone/gm_commands/summonitem.cpp index b72292a97e..057c4b0f72 100755 --- a/zone/gm_commands/summonitem.cpp +++ b/zone/gm_commands/summonitem.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_summonitem(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/suspend.cpp b/zone/gm_commands/suspend.cpp index 1bd5f4ae2c..fc9e67e2ea 100755 --- a/zone/gm_commands/suspend.cpp +++ b/zone/gm_commands/suspend.cpp @@ -1,6 +1,6 @@ -#include "../client.h" -#include "../worldserver.h" -#include "../../common/repositories/account_repository.h" +#include "common/repositories/account_repository.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/suspendmulti.cpp b/zone/gm_commands/suspendmulti.cpp index 1d087b4867..4ebfa8a4f8 100755 --- a/zone/gm_commands/suspendmulti.cpp +++ b/zone/gm_commands/suspendmulti.cpp @@ -1,6 +1,6 @@ -#include "../client.h" -#include "../worldserver.h" -#include "../../common/repositories/account_repository.h" +#include "common/repositories/account_repository.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/takeplatinum.cpp b/zone/gm_commands/takeplatinum.cpp index a5c0a8f3a9..fe9af3c7be 100644 --- a/zone/gm_commands/takeplatinum.cpp +++ b/zone/gm_commands/takeplatinum.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_takeplatinum(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/task.cpp b/zone/gm_commands/task.cpp index 407184f59c..5917265848 100755 --- a/zone/gm_commands/task.cpp +++ b/zone/gm_commands/task.cpp @@ -1,11 +1,10 @@ -#include "../client.h" -#include "../worldserver.h" +#include "common/repositories/completed_tasks_repository.h" +#include "common/shared_tasks.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; -#include "../../common/shared_tasks.h" -#include "../../common/repositories/completed_tasks_repository.h" - void command_task(Client *c, const Seperator *sep) { if (!RuleB(TaskSystem, EnableTaskSystem)) { diff --git a/zone/gm_commands/traindisc.cpp b/zone/gm_commands/traindisc.cpp index aeb4e8d9f0..4243b8bc4e 100755 --- a/zone/gm_commands/traindisc.cpp +++ b/zone/gm_commands/traindisc.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_traindisc(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/tune.cpp b/zone/gm_commands/tune.cpp index 7174039e9c..98f94117dc 100755 --- a/zone/gm_commands/tune.cpp +++ b/zone/gm_commands/tune.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_tune(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/undye.cpp b/zone/gm_commands/undye.cpp index f66cc9185b..fdc6e39ab1 100755 --- a/zone/gm_commands/undye.cpp +++ b/zone/gm_commands/undye.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_undye(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/unmemspell.cpp b/zone/gm_commands/unmemspell.cpp index b5450035f0..b6985bd668 100644 --- a/zone/gm_commands/unmemspell.cpp +++ b/zone/gm_commands/unmemspell.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_unmemspell(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/unmemspells.cpp b/zone/gm_commands/unmemspells.cpp index a39d329c87..94568c74b3 100644 --- a/zone/gm_commands/unmemspells.cpp +++ b/zone/gm_commands/unmemspells.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_unmemspells(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/unscribespell.cpp b/zone/gm_commands/unscribespell.cpp index 6965538c46..6f432dddb4 100755 --- a/zone/gm_commands/unscribespell.cpp +++ b/zone/gm_commands/unscribespell.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../../common/data_verification.h" +#include "common/data_verification.h" +#include "zone/client.h" void command_unscribespell(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/unscribespells.cpp b/zone/gm_commands/unscribespells.cpp index 7b4b93211a..ed2572f9e2 100755 --- a/zone/gm_commands/unscribespells.cpp +++ b/zone/gm_commands/unscribespells.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_unscribespells(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/untraindisc.cpp b/zone/gm_commands/untraindisc.cpp index 2337d7ae97..ac0237f72b 100755 --- a/zone/gm_commands/untraindisc.cpp +++ b/zone/gm_commands/untraindisc.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../../common/data_verification.h" +#include "common/data_verification.h" +#include "zone/client.h" void command_untraindisc(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/untraindiscs.cpp b/zone/gm_commands/untraindiscs.cpp index 8058c6e76b..85229c60a6 100755 --- a/zone/gm_commands/untraindiscs.cpp +++ b/zone/gm_commands/untraindiscs.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_untraindiscs(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/wc.cpp b/zone/gm_commands/wc.cpp index 4fc60e9bee..b23de72fda 100755 --- a/zone/gm_commands/wc.cpp +++ b/zone/gm_commands/wc.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../../common/data_verification.h" +#include "common/data_verification.h" +#include "zone/client.h" void command_wc(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/worldshutdown.cpp b/zone/gm_commands/worldshutdown.cpp index 37940d1a72..c17ce18489 100755 --- a/zone/gm_commands/worldshutdown.cpp +++ b/zone/gm_commands/worldshutdown.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/worldwide.cpp b/zone/gm_commands/worldwide.cpp index a61be457bf..8f2e7a1834 100755 --- a/zone/gm_commands/worldwide.cpp +++ b/zone/gm_commands/worldwide.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_worldwide(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/wp.cpp b/zone/gm_commands/wp.cpp index 8307ebaa78..54f2bd8496 100755 --- a/zone/gm_commands/wp.cpp +++ b/zone/gm_commands/wp.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_wp(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/wpadd.cpp b/zone/gm_commands/wpadd.cpp index b8f114c7b3..b6b04d119a 100755 --- a/zone/gm_commands/wpadd.cpp +++ b/zone/gm_commands/wpadd.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_wpadd(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/zone.cpp b/zone/gm_commands/zone.cpp index 46caf373f1..d13a9449f5 100644 --- a/zone/gm_commands/zone.cpp +++ b/zone/gm_commands/zone.cpp @@ -1,5 +1,5 @@ -#include "../bot.h" -#include "../client.h" +#include "zone/bot.h" +#include "zone/client.h" void command_zone(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/zone_instance.cpp b/zone/gm_commands/zone_instance.cpp index 5101468ba7..8efc7f9fcc 100644 --- a/zone/gm_commands/zone_instance.cpp +++ b/zone/gm_commands/zone_instance.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_zone_instance(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/zone_shard.cpp b/zone/gm_commands/zone_shard.cpp index 9e468ba7d2..f5273dbfcf 100644 --- a/zone/gm_commands/zone_shard.cpp +++ b/zone/gm_commands/zone_shard.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_zone_shard(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/zonebootup.cpp b/zone/gm_commands/zonebootup.cpp index 1a1a91f5d8..155cbc2be7 100755 --- a/zone/gm_commands/zonebootup.cpp +++ b/zone/gm_commands/zonebootup.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/zoneshutdown.cpp b/zone/gm_commands/zoneshutdown.cpp index c62e5a0b9d..555bd54dee 100755 --- a/zone/gm_commands/zoneshutdown.cpp +++ b/zone/gm_commands/zoneshutdown.cpp @@ -1,5 +1,5 @@ -#include "../client.h" -#include "../worldserver.h" +#include "zone/client.h" +#include "zone/worldserver.h" extern WorldServer worldserver; diff --git a/zone/gm_commands/zonevariable.cpp b/zone/gm_commands/zonevariable.cpp index 54c4ae65f7..af4d2de6d8 100644 --- a/zone/gm_commands/zonevariable.cpp +++ b/zone/gm_commands/zonevariable.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_zonevariable(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/zsave.cpp b/zone/gm_commands/zsave.cpp index acfa4536db..a73394f455 100755 --- a/zone/gm_commands/zsave.cpp +++ b/zone/gm_commands/zsave.cpp @@ -1,4 +1,4 @@ -#include "../client.h" +#include "zone/client.h" void command_zsave(Client *c, const Seperator *sep) { From f49c8ae0bd85daf71baf38e2531fbc96e8971758 Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 01:07:40 -0800 Subject: [PATCH 084/194] Add EQEMU_MSVC_DEBUG_CRT option to cmake --- CMakeLists.txt | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 03e375fea1..a831e21262 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,17 +5,17 @@ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH}) if(NOT CMAKE_TOOLCHAIN_FILE) if(DEFINED ENV{VCPKG_ROOT}) message(STATUS "Using vcpkg from VCPKG_ROOT") - set(CMAKE_TOOLCHAIN_FILE - "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" - CACHE FILEPATH "Vcpkg toolchain file" - ) + set(CMAKE_TOOLCHAIN_FILE + "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + CACHE FILEPATH "Vcpkg toolchain file" + ) else() - message(STATUS "Using vcpkg submodule") - set(CMAKE_TOOLCHAIN_FILE - "${CMAKE_CURRENT_SOURCE_DIR}/submodules/vcpkg/scripts/buildsystems/vcpkg.cmake" - CACHE FILEPATH "Vcpkg toolchain file" - ) - endif() + message(STATUS "Using vcpkg submodule") + set(CMAKE_TOOLCHAIN_FILE + "${CMAKE_CURRENT_SOURCE_DIR}/submodules/vcpkg/scripts/buildsystems/vcpkg.cmake" + CACHE FILEPATH "Vcpkg toolchain file" + ) + endif() endif() project(EQEmu @@ -49,6 +49,11 @@ if(MSVC) if(EQEMU_DISABLE_MSVC_WARNINGS) add_compile_options(/W0 /wd4005 /wd4996 /nologo /Os) endif() + + option(EQEMU_MSVC_DEBUG_CRT "Use the debug CRT on MSVC debug builds" OFF) + if(EQEMU_MSVC_DEBUG_CRT) + add_compile_definitions(_CRT_DBG_MAP_ALLOC) + endif() else() add_compile_definitions(HAS_UNION_SEMUN) endif() @@ -129,7 +134,7 @@ option(EQEMU_BUILD_CLIENT_FILES "Build Client Import/Export Data Programs." ON) if(PerlLibs_FOUND) option(EQEMU_BUILD_PERL "Build Perl parser." ON) - + if(EQEMU_BUILD_PERL) set(PERL_LIBRARY_TYPE " Perl") else() From 5bef8b63e831c7a1e6fb28a0b0f49734e99f6a10 Mon Sep 17 00:00:00 2001 From: brainiac Date: Thu, 18 Dec 2025 01:08:37 -0800 Subject: [PATCH 085/194] Remove unused world/main.h It was being used by zone commands to forward declare the signal function :( --- world/main.h | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 world/main.h diff --git a/world/main.h b/world/main.h deleted file mode 100644 index 55c1fa8e96..0000000000 --- a/world/main.h +++ /dev/null @@ -1,34 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 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 -*/ -#ifndef WIN32 - #include - #include - #include - #include - #include - #include - #include -#else - #include - #include - #include - #include -#endif - -void CatchSignal(int sig_num); - From fe0682de9fd49b2425578f60ca560c511d29cebc Mon Sep 17 00:00:00 2001 From: brainiac Date: Sun, 21 Dec 2025 11:49:22 -0800 Subject: [PATCH 086/194] More fixes: luabind --- libs/luabind/luabind/class.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/luabind/luabind/class.hpp b/libs/luabind/luabind/class.hpp index 10fb8e03d5..5b8636b97d 100644 --- a/libs/luabind/luabind/class.hpp +++ b/libs/luabind/luabind/class.hpp @@ -75,7 +75,7 @@ #include #include -#include +#include #include #include #include From b56c2421b41cdeb4d75a57db39fcf2f2502fdebb Mon Sep 17 00:00:00 2001 From: brainiac Date: Sun, 21 Dec 2025 11:44:50 -0800 Subject: [PATCH 087/194] normalize includes: queryserv --- queryserv/database.cpp | 2 -- queryserv/queryserv.cpp | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index a69b958462..99b125bbd8 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -4,8 +4,6 @@ #include "common/eqemu_logsys.h" #include "common/strings.h" -#include - // this function does not delete the ServerPacket, so it must be handled at call site void QSDatabase::GeneralQueryReceive(ServerPacket *pack) { diff --git a/queryserv/queryserv.cpp b/queryserv/queryserv.cpp index aa0fb2a256..1d2ace974b 100644 --- a/queryserv/queryserv.cpp +++ b/queryserv/queryserv.cpp @@ -10,7 +10,6 @@ #include "common/rulesys.h" #include "common/strings.h" #include "common/timer.h" -#include "common/zone_store.h" #include "queryserv/database.h" #include "queryserv/lfguild.h" #include "queryserv/worldserver.h" @@ -18,9 +17,7 @@ #include "queryserv/zoneserver.h" #include "queryservconfig.h" -#include -#include -#include +#include volatile bool RunLoops = true; From af6c3ec97ded3fc035d0c32fb1f8cde267174103 Mon Sep 17 00:00:00 2001 From: brainiac Date: Sun, 21 Dec 2025 17:05:42 -0800 Subject: [PATCH 088/194] Fix undefined behavior in log aliases making an inline global variable doesn't work around the fact that this variable still has to be initialized at some point. Unfortunately, logging may be called upon during static init because we use rules inside of static initializers, and rules can log. So we must always retrieve the logger when we want to log something. it should be fairly cheap anyways. --- common/eqemu_logsys_log_aliases.h | 366 +++++++++++++++--------------- 1 file changed, 182 insertions(+), 184 deletions(-) diff --git a/common/eqemu_logsys_log_aliases.h b/common/eqemu_logsys_log_aliases.h index 261408c536..3a379706c7 100644 --- a/common/eqemu_logsys_log_aliases.h +++ b/common/eqemu_logsys_log_aliases.h @@ -22,917 +22,915 @@ #include "common/eqemu_logsys.h" -inline auto logsys = EQEmuLogSys::Instance(); - #define LogAA(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::AA))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::AA))\ OutF(logsys, Logs::General, Logs::AA, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAADetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::AA))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::AA))\ OutF(logsys, Logs::Detail, Logs::AA, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAI(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::AI))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::AI))\ OutF(logsys, Logs::General, Logs::AI, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAIDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::AI))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::AI))\ OutF(logsys, Logs::Detail, Logs::AI, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAggro(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Aggro))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Aggro))\ OutF(logsys, Logs::General, Logs::Aggro, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAggroDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Aggro))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Aggro))\ OutF(logsys, Logs::Detail, Logs::Aggro, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAttack(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Attack))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Attack))\ OutF(logsys, Logs::General, Logs::Attack, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAttackDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Attack))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Attack))\ OutF(logsys, Logs::Detail, Logs::Attack, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPacketClientServer(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::PacketClientServer))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::PacketClientServer))\ OutF(logsys, Logs::General, Logs::PacketClientServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPacketClientServerDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::PacketClientServer))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::PacketClientServer))\ OutF(logsys, Logs::Detail, Logs::PacketClientServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCombat(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Combat))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Combat))\ OutF(logsys, Logs::General, Logs::Combat, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCombatDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Combat))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Combat))\ OutF(logsys, Logs::Detail, Logs::Combat, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCommands(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Commands))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Commands))\ OutF(logsys, Logs::General, Logs::Commands, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCommandsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Commands))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Commands))\ OutF(logsys, Logs::Detail, Logs::Commands, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCrash(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Crash))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Crash))\ OutF(logsys, Logs::General, Logs::Crash, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCrashDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Crash))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Crash))\ OutF(logsys, Logs::Detail, Logs::Crash, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDebug(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Debug))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Debug))\ OutF(logsys, Logs::General, Logs::Debug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDebugDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Debug))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Debug))\ OutF(logsys, Logs::Detail, Logs::Debug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDoors(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Doors))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Doors))\ OutF(logsys, Logs::General, Logs::Doors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDoorsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Doors))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Doors))\ OutF(logsys, Logs::Detail, Logs::Doors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogError(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Error))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Error))\ OutF(logsys, Logs::General, Logs::Error, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogErrorDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Error))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Error))\ OutF(logsys, Logs::Detail, Logs::Error, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogEvolveItem(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::EvolveItem))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::EvolveItem))\ OutF(logsys, Logs::General, Logs::EvolveItem, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogEvolveItemDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::EvolveItem))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::EvolveItem))\ OutF(logsys, Logs::Detail, Logs::EvolveItem, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogGuilds(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Guilds))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Guilds))\ OutF(logsys, Logs::General, Logs::Guilds, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogGuildsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Guilds))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Guilds))\ OutF(logsys, Logs::Detail, Logs::Guilds, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogInventory(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Inventory))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Inventory))\ OutF(logsys, Logs::General, Logs::Inventory, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogInventoryDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Inventory))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Inventory))\ OutF(logsys, Logs::Detail, Logs::Inventory, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogLauncher(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Launcher))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Launcher))\ OutF(logsys, Logs::General, Logs::Launcher, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogLauncherDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Launcher))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Launcher))\ OutF(logsys, Logs::Detail, Logs::Launcher, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNetcode(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Netcode))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Netcode))\ OutF(logsys, Logs::General, Logs::Netcode, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNetcodeDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Netcode))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Netcode))\ OutF(logsys, Logs::Detail, Logs::Netcode, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNormal(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Normal))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Normal))\ OutF(logsys, Logs::General, Logs::Normal, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNormalDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Normal))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Normal))\ OutF(logsys, Logs::Detail, Logs::Normal, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogObject(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Object))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Object))\ OutF(logsys, Logs::General, Logs::Object, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogObjectDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Object))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Object))\ OutF(logsys, Logs::Detail, Logs::Object, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPathing(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Pathing))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Pathing))\ OutF(logsys, Logs::General, Logs::Pathing, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPathingDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Pathing))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Pathing))\ OutF(logsys, Logs::Detail, Logs::Pathing, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogQuests(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Quests))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Quests))\ OutF(logsys, Logs::General, Logs::Quests, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogQuestsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Quests))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Quests))\ OutF(logsys, Logs::Detail, Logs::Quests, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogRules(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Rules))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Rules))\ OutF(logsys, Logs::General, Logs::Rules, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogRulesDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Rules))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Rules))\ OutF(logsys, Logs::Detail, Logs::Rules, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSkills(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Skills))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Skills))\ OutF(logsys, Logs::General, Logs::Skills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSkillsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Skills))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Skills))\ OutF(logsys, Logs::Detail, Logs::Skills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSpawns(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Spawns))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Spawns))\ OutF(logsys, Logs::General, Logs::Spawns, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSpawnsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Spawns))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Spawns))\ OutF(logsys, Logs::Detail, Logs::Spawns, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSpells(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Spells))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Spells))\ OutF(logsys, Logs::General, Logs::Spells, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSpellsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Spells))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Spells))\ OutF(logsys, Logs::Detail, Logs::Spells, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogTasks(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Tasks))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Tasks))\ OutF(logsys, Logs::General, Logs::Tasks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogTasksDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Tasks))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Tasks))\ OutF(logsys, Logs::Detail, Logs::Tasks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogTradeskills(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Tradeskills))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Tradeskills))\ OutF(logsys, Logs::General, Logs::Tradeskills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogTradeskillsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Tradeskills))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Tradeskills))\ OutF(logsys, Logs::Detail, Logs::Tradeskills, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogTrading(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Trading))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Trading))\ OutF(logsys, Logs::General, Logs::Trading, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogTradingDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Trading))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Trading))\ OutF(logsys, Logs::Detail, Logs::Trading, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogTribute(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Tribute))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Tribute))\ OutF(logsys, Logs::General, Logs::Tribute, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogTributeDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Tribute))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Tribute))\ OutF(logsys, Logs::Detail, Logs::Tribute, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogMySQLError(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::MySQLError))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::MySQLError))\ OutF(logsys, Logs::General, Logs::MySQLError, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogMySQLErrorDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::MySQLError))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::MySQLError))\ OutF(logsys, Logs::Detail, Logs::MySQLError, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogMySQLQuery(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::MySQLQuery))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::MySQLQuery))\ OutF(logsys, Logs::General, Logs::MySQLQuery, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogMySQLQueryDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::MySQLQuery))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::MySQLQuery))\ OutF(logsys, Logs::Detail, Logs::MySQLQuery, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogMercenaries(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Mercenaries))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Mercenaries))\ OutF(logsys, Logs::General, Logs::Mercenaries, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogMercenariesDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Mercenaries))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Mercenaries))\ OutF(logsys, Logs::Detail, Logs::Mercenaries, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogQuestDebug(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::QuestDebug))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::QuestDebug))\ OutF(logsys, Logs::General, Logs::QuestDebug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogQuestDebugDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::QuestDebug))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::QuestDebug))\ OutF(logsys, Logs::Detail, Logs::QuestDebug, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPacketServerClient(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::PacketServerClient))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::PacketServerClient))\ OutF(logsys, Logs::General, Logs::PacketServerClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPacketServerClientDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::PacketServerClient))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::PacketServerClient))\ OutF(logsys, Logs::Detail, Logs::PacketServerClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogLoginserver(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Loginserver))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Loginserver))\ OutF(logsys, Logs::General, Logs::Loginserver, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogLoginserverDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Loginserver))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Loginserver))\ OutF(logsys, Logs::Detail, Logs::Loginserver, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogClientLogin(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::ClientLogin))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::ClientLogin))\ OutF(logsys, Logs::General, Logs::ClientLogin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogClientLoginDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::ClientLogin))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::ClientLogin))\ OutF(logsys, Logs::Detail, Logs::ClientLogin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHPUpdate(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::HPUpdate))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::HPUpdate))\ OutF(logsys, Logs::General, Logs::HPUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHPUpdateDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::HPUpdate))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::HPUpdate))\ OutF(logsys, Logs::Detail, Logs::HPUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogFixZ(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::FixZ))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::FixZ))\ OutF(logsys, Logs::General, Logs::FixZ, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogFixZDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::FixZ))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::FixZ))\ OutF(logsys, Logs::Detail, Logs::FixZ, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogFood(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Food))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Food))\ OutF(logsys, Logs::General, Logs::Food, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogFoodDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Food))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Food))\ OutF(logsys, Logs::Detail, Logs::Food, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogTraps(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Traps))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Traps))\ OutF(logsys, Logs::General, Logs::Traps, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogTrapsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Traps))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Traps))\ OutF(logsys, Logs::Detail, Logs::Traps, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNPCRoamBox(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::NPCRoamBox))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::NPCRoamBox))\ OutF(logsys, Logs::General, Logs::NPCRoamBox, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNPCRoamBoxDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::NPCRoamBox))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::NPCRoamBox))\ OutF(logsys, Logs::Detail, Logs::NPCRoamBox, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNPCScaling(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::NPCScaling))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::NPCScaling))\ OutF(logsys, Logs::General, Logs::NPCScaling, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNPCScalingDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::NPCScaling))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::NPCScaling))\ OutF(logsys, Logs::Detail, Logs::NPCScaling, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogMobAppearance(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::MobAppearance))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::MobAppearance))\ OutF(logsys, Logs::General, Logs::MobAppearance, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogMobAppearanceDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::MobAppearance))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::MobAppearance))\ OutF(logsys, Logs::Detail, Logs::MobAppearance, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogInfo(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Info))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Info))\ OutF(logsys, Logs::General, Logs::Info, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogInfoDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Info))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Info))\ OutF(logsys, Logs::Detail, Logs::Info, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogWarning(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Warning))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Warning))\ OutF(logsys, Logs::General, Logs::Warning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogWarningDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Warning))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Warning))\ OutF(logsys, Logs::Detail, Logs::Warning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCritical(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Critical))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Critical))\ OutF(logsys, Logs::General, Logs::Critical, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCriticalDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Critical))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Critical))\ OutF(logsys, Logs::Detail, Logs::Critical, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogEmergency(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Emergency))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Emergency))\ OutF(logsys, Logs::General, Logs::Emergency, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogEmergencyDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Emergency))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Emergency))\ OutF(logsys, Logs::Detail, Logs::Emergency, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAlert(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Alert))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Alert))\ OutF(logsys, Logs::General, Logs::Alert, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAlertDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Alert))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Alert))\ OutF(logsys, Logs::Detail, Logs::Alert, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNotice(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Notice))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Notice))\ OutF(logsys, Logs::General, Logs::Notice, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNoticeDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Notice))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Notice))\ OutF(logsys, Logs::Detail, Logs::Notice, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAIScanClose(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::AIScanClose))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::AIScanClose))\ OutF(logsys, Logs::General, Logs::AIScanClose, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAIScanCloseDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::AIScanClose))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::AIScanClose))\ OutF(logsys, Logs::Detail, Logs::AIScanClose, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAIYellForHelp(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::AIYellForHelp))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::AIYellForHelp))\ OutF(logsys, Logs::General, Logs::AIYellForHelp, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAIYellForHelpDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::AIYellForHelp))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::AIYellForHelp))\ OutF(logsys, Logs::Detail, Logs::AIYellForHelp, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAICastBeneficialClose(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::AICastBeneficialClose))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::AICastBeneficialClose))\ OutF(logsys, Logs::General, Logs::AICastBeneficialClose, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAICastBeneficialCloseDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::AICastBeneficialClose))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::AICastBeneficialClose))\ OutF(logsys, Logs::Detail, Logs::AICastBeneficialClose, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAoeCast(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::AoeCast))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::AoeCast))\ OutF(logsys, Logs::General, Logs::AoeCast, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAoeCastDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::AoeCast))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::AoeCast))\ OutF(logsys, Logs::Detail, Logs::AoeCast, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogEntityManagement(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::EntityManagement))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::EntityManagement))\ OutF(logsys, Logs::General, Logs::EntityManagement, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogEntityManagementDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::EntityManagement))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::EntityManagement))\ OutF(logsys, Logs::Detail, Logs::EntityManagement, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogFlee(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Flee))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Flee))\ OutF(logsys, Logs::General, Logs::Flee, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogFleeDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Flee))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Flee))\ OutF(logsys, Logs::Detail, Logs::Flee, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAura(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Aura))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Aura))\ OutF(logsys, Logs::General, Logs::Aura, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogAuraDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Aura))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Aura))\ OutF(logsys, Logs::Detail, Logs::Aura, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHotReload(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::HotReload))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::HotReload))\ OutF(logsys, Logs::General, Logs::HotReload, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHotReloadDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::HotReload))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::HotReload))\ OutF(logsys, Logs::Detail, Logs::HotReload, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogMerchants(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Merchants))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Merchants))\ OutF(logsys, Logs::General, Logs::Merchants, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogMerchantsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Merchants))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Merchants))\ OutF(logsys, Logs::Detail, Logs::Merchants, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogZonePoints(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::ZonePoints))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::ZonePoints))\ OutF(logsys, Logs::General, Logs::ZonePoints, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogZonePointsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::ZonePoints))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::ZonePoints))\ OutF(logsys, Logs::Detail, Logs::ZonePoints, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogLoot(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Loot))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Loot))\ OutF(logsys, Logs::General, Logs::Loot, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogLootDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Loot))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Loot))\ OutF(logsys, Logs::Detail, Logs::Loot, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogExpeditions(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Expeditions))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Expeditions))\ OutF(logsys, Logs::General, Logs::Expeditions, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogExpeditionsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Expeditions))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Expeditions))\ OutF(logsys, Logs::Detail, Logs::Expeditions, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDynamicZones(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::DynamicZones))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::DynamicZones))\ OutF(logsys, Logs::General, Logs::DynamicZones, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDynamicZonesDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::DynamicZones))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::DynamicZones))\ OutF(logsys, Logs::Detail, Logs::DynamicZones, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogScheduler(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Scheduler))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Scheduler))\ OutF(logsys, Logs::General, Logs::Scheduler, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSchedulerDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Scheduler))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Scheduler))\ OutF(logsys, Logs::Detail, Logs::Scheduler, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCheat(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Cheat))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Cheat))\ OutF(logsys, Logs::General, Logs::Cheat, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCheatDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Cheat))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Cheat))\ OutF(logsys, Logs::Detail, Logs::Cheat, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogClientList(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::ClientList))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::ClientList))\ OutF(logsys, Logs::General, Logs::ClientList, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogClientListDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::ClientList))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::ClientList))\ OutF(logsys, Logs::Detail, Logs::ClientList, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDiaWind(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::DiaWind))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::DiaWind))\ OutF(logsys, Logs::General, Logs::DiaWind, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDiaWindDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::DiaWind))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::DiaWind))\ OutF(logsys, Logs::Detail, Logs::DiaWind, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHTTP(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::HTTP))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::HTTP))\ OutF(logsys, Logs::General, Logs::HTTP, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHTTPDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::HTTP))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::HTTP))\ OutF(logsys, Logs::Detail, Logs::HTTP, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSaylink(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Saylink))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Saylink))\ OutF(logsys, Logs::General, Logs::Saylink, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogSaylinkDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Saylink))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Saylink))\ OutF(logsys, Logs::Detail, Logs::Saylink, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogChecksumVerification(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::ChecksumVerification))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::ChecksumVerification))\ OutF(logsys, Logs::General, Logs::ChecksumVerification, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogChecksumVerificationDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::ChecksumVerification))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::ChecksumVerification))\ OutF(logsys, Logs::Detail, Logs::ChecksumVerification, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCombatRecord(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::CombatRecord))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::CombatRecord))\ OutF(logsys, Logs::General, Logs::CombatRecord, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCombatRecordDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::CombatRecord))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::CombatRecord))\ OutF(logsys, Logs::Detail, Logs::CombatRecord, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHate(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Hate))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Hate))\ OutF(logsys, Logs::General, Logs::Hate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogHateDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Hate))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Hate))\ OutF(logsys, Logs::Detail, Logs::Hate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDiscord(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Discord))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Discord))\ OutF(logsys, Logs::General, Logs::Discord, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDiscordDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Discord))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Discord))\ OutF(logsys, Logs::Detail, Logs::Discord, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogFaction(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Faction))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Faction))\ OutF(logsys, Logs::General, Logs::Faction, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogFactionDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Faction))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Faction))\ OutF(logsys, Logs::Detail, Logs::Faction, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPacketServerToServer(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::PacketServerToServer))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::PacketServerToServer))\ OutF(logsys, Logs::General, Logs::PacketServerToServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPacketServerToServerDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::PacketServerToServer))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::PacketServerToServer))\ OutF(logsys, Logs::Detail, Logs::PacketServerToServer, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) // manually created #define LogBugs(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Bugs))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Bugs))\ OutF(logsys, Logs::General, Logs::Bugs, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogBugsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Bugs))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Bugs))\ OutF(logsys, Logs::Detail, Logs::Bugs, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogQuestErrors(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::QuestErrors))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::QuestErrors))\ OutF(logsys, Logs::General, Logs::QuestErrors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogQuestErrorsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::QuestErrors))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::QuestErrors))\ OutF(logsys, Logs::Detail, Logs::QuestErrors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPlayerEvents(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::PlayerEvents))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::PlayerEvents))\ OutF(logsys, Logs::General, Logs::PlayerEvents, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPlayerEventsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::PlayerEvents))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::PlayerEvents))\ OutF(logsys, Logs::Detail, Logs::PlayerEvents, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDataBuckets(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::DataBuckets))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::DataBuckets))\ OutF(logsys, Logs::General, Logs::DataBuckets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogDataBucketsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::DataBuckets))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::DataBuckets))\ OutF(logsys, Logs::Detail, Logs::DataBuckets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogZoning(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Zoning))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Zoning))\ OutF(logsys, Logs::General, Logs::Zoning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogZoningDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Zoning))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Zoning))\ OutF(logsys, Logs::Detail, Logs::Zoning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogEqTime(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::EqTime))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::EqTime))\ OutF(logsys, Logs::General, Logs::EqTime, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogEqTimeDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::EqTime))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::EqTime))\ OutF(logsys, Logs::Detail, Logs::EqTime, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCorpses(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::Corpses))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::Corpses))\ OutF(logsys, Logs::General, Logs::Corpses, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogCorpsesDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::Corpses))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::Corpses))\ OutF(logsys, Logs::Detail, Logs::Corpses, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogXTargets(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::XTargets))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::XTargets))\ OutF(logsys, Logs::General, Logs::XTargets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogXTargetsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::XTargets))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::XTargets))\ OutF(logsys, Logs::Detail, Logs::XTargets, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPositionUpdate(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::PositionUpdate))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::PositionUpdate))\ OutF(logsys, Logs::General, Logs::PositionUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogPositionUpdateDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::PositionUpdate))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::PositionUpdate))\ OutF(logsys, Logs::Detail, Logs::PositionUpdate, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__); \ } while (0) #define LogKSM(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::KSM))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::KSM))\ OutF(logsys, Logs::General, Logs::KSM, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogKSMDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::KSM))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::KSM))\ OutF(logsys, Logs::Detail, Logs::KSM, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogBotSettings(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::BotSettings))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::BotSettings))\ OutF(logsys, Logs::General, Logs::BotSettings, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogBotSettingsDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::BotSettings))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::BotSettings))\ OutF(logsys, Logs::Detail, Logs::BotSettings, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogBotSpellChecks(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::BotSpellChecks))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::BotSpellChecks))\ OutF(logsys, Logs::General, Logs::BotSpellChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogBotSpellChecksDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::BotSpellChecks))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::BotSpellChecks))\ OutF(logsys, Logs::Detail, Logs::BotSpellChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogBotSpellTypeChecks(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::BotSpellTypeChecks))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::BotSpellTypeChecks))\ OutF(logsys, Logs::General, Logs::BotSpellTypeChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogBotSpellTypeChecksDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::BotSpellTypeChecks))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::BotSpellTypeChecks))\ OutF(logsys, Logs::Detail, Logs::BotSpellTypeChecks, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNpcHandin(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::NpcHandin))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::NpcHandin))\ OutF(logsys, Logs::General, Logs::NpcHandin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNpcHandinDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::NpcHandin))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::NpcHandin))\ OutF(logsys, Logs::Detail, Logs::NpcHandin, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogZoneState(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::ZoneState))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::ZoneState))\ OutF(logsys, Logs::General, Logs::ZoneState, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogZoneStateDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::ZoneState))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::ZoneState))\ OutF(logsys, Logs::Detail, Logs::ZoneState, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNetClient(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::NetClient))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::NetClient))\ OutF(logsys, Logs::General, Logs::NetClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNetClientDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::NetClient))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::NetClient))\ OutF(logsys, Logs::Detail, Logs::NetClient, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNetTCP(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::General, Logs::NetTCP))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::General, Logs::NetTCP))\ OutF(logsys, Logs::General, Logs::NetTCP, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogNetTCPDetail(message, ...) do {\ - if (logsys->IsLogEnabled(Logs::Detail, Logs::NetTCP))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(Logs::Detail, Logs::NetTCP))\ OutF(logsys, Logs::Detail, Logs::NetTCP, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define Log(debug_level, log_category, message, ...) do {\ - if (logsys->IsLogEnabled(debug_level, log_category))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(debug_level, log_category))\ logsys->Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) #define LogF(debug_level, log_category, message, ...) do {\ - if (logsys->IsLogEnabled(debug_level, log_category))\ + if (auto logsys = EQEmuLogSys::Instance(); logsys && logsys->IsLogEnabled(debug_level, log_category))\ OutF(logsys, debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) From be493435cb33f80de03989a39480fa8bff2e806b Mon Sep 17 00:00:00 2001 From: Knightly Date: Tue, 23 Dec 2025 18:46:17 -1000 Subject: [PATCH 089/194] Fix Shared Memory in Windows - Windows does not allow paths as mutexes - Remove the config directory from the mutex name - This fix has the potential for collision of concerns on Windows when running multiple instances, but it is an unlikely scenario given port requirements --- common/ipc_mutex.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/ipc_mutex.cpp b/common/ipc_mutex.cpp index 48af9b3881..282bb34ea9 100644 --- a/common/ipc_mutex.cpp +++ b/common/ipc_mutex.cpp @@ -47,8 +47,7 @@ namespace EQ { IPCMutex::IPCMutex(const std::string& name) : locked_(false) { imp_ = new Implementation; #ifdef _WINDOWS - auto Config = EQEmuConfig::get(); - std::string final_name = fmt::format("{}/EQEmuMutex_{}", Config->SharedMemDir, name); + std::string final_name = fmt::format("EQEmuMutex_{}", name); imp_->mut_ = CreateMutex(nullptr, FALSE, From bf69182a6292cf78fde7c0a7da767960dbc764f7 Mon Sep 17 00:00:00 2001 From: JJ <3617814+joligario@users.noreply.github.com> Date: Mon, 5 Jan 2026 17:56:17 -0500 Subject: [PATCH 090/194] Revise README for updated documentation and links Updated links and images in the README to reflect the new EQEmu documentation site and repository. --- README.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 033fcccabb..0d5d04f206 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

EQEmulator Server Platform

- +

@@ -9,17 +9,17 @@

-Contributors + +Contributors Discord -Docs -License -Latest Release -Release Date -Github All Releases -Build Status +Docs +License +Latest Release +Release Date +Github All Releases GitHub Issues or Pull Requests Docker Pulls -Build Status Official +Official

@@ -121,30 +121,30 @@ Every system, packet, opcode, and game mechanic has been reconstructed through c | Resource | Badges | Link | |---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------| -| **EQEmulator Docs** | [![Docs](https://img.shields.io/badge/docs-MkDocs%20Powered-blueviolet)](https://docs.eqemu.io) | [docs.eqemu.io](https://docs.eqemu.io/) | +| **EQEmulator Docs** | [![Docs](https://img.shields.io/badge/docs-MkDocs%20Powered-blueviolet)](https://docs.eqemu.dev) | [docs.eqemu.dev](https://docs.eqemu.dev/) | | **Discord Community**| [![Discord](https://img.shields.io/discord/212663220849213441?label=Discord&logo=discord&color=7289DA)](https://discord.gg/QHsm7CD) | [Join Discord](https://discord.gg/QHsm7CD) | -| **Latest Release** | [![Latest Release](https://img.shields.io/github/v/release/eqemu/server)](https://github.com/eqemu/server/releases)
[![Release Date](https://img.shields.io/github/release-date/EQEmu/Server)](https://github.com/EQEmu/Server/releases)
[![All Releases](https://img.shields.io/github/downloads/eqemu/server/total.svg)](https://github.com/eqemu/server/releases) | [View Releases](https://github.com/eqemu/server/releases) | -| **License** | [![License](https://img.shields.io/github/license/EQEmu/Server)](./LICENSE) | [View License](./LICENSE) | -| **Build Status** | [![Build Status](http://drone.akkadius.com/api/badges/EQEmu/Server/status.svg)](http://drone.akkadius.com/EQEmu/Server) | [View Build Status](http://drone.akkadius.com/EQEmu/Server) | +| **Latest Release** | [![Latest Release](https://img.shields.io/github/v/release/EQEmu/EQEmu)](https://github.com/EQEmu/EQEmu/releases)
[![Release Date](https://img.shields.io/github/release-date/EQEmu/EQEmu)](https://github.com/EQEmu/EQEmu/releases)
[![All Releases](https://img.shields.io/github/downloads/EQEmu/EQEmu/total.svg)](https://github.com/EQEmu/EQEmu/releases) | [View Releases](https://github.com/EQEmu/EQEmu/releases) | +| **License** | [![License](https://img.shields.io/github/license/EQEmu/EQEmu)](./LICENSE) | [View License](./LICENSE) | +| **Build Status** | [![Build](https://github.com/EQEmu/EQEmu/actions/workflows/build.yaml/badge.svg)](https://github.com/EQEmu/EQEmu/actions/workflows/build.yaml) | [View Build Status](http://drone.akkadius.com/EQEmu/Server) | | **Docker Pulls** | [![Docker Pulls](https://img.shields.io/docker/pulls/akkadius/eqemu-server)](https://hub.docker.com/r/akkadius/eqemu-server) | [Docker Hub](https://hub.docker.com/r/akkadius/eqemu-server) | -| **Contributions** | [![GitHub PRs](https://img.shields.io/github/issues-pr-closed/eqemu/server)](https://github.com/eqemu/server/pulls?q=is%3Apr+is%3Aclosed) | [Closed PRs & Issues](https://github.com/eqemu/server/pulls?q=is%3Apr+is%3Aclosed) | +| **Contributions** | [![GitHub PRs](https://img.shields.io/github/issues-pr-closed/EQEmu/EQEmu)](https://github.com/EQEmu/EQEmu/pulls?q=is%3Apr+is%3Aclosed) | [Closed PRs & Issues](https://github.com/EQEmu/EQEmu/pulls?q=is%3Apr+is%3Aclosed) | ## ðŸ› ï¸ Getting Started -If you want to set up your own EQEmulator server, please refer to the current [server installation guides](https://docs.eqemu.io/#server-installation). We've had 100,000s of players and developers use our guides to set up their own servers, and we hope you will too! +If you want to set up your own EQEmulator server, please refer to the current [server installation guides](https://docs.eqemu.dev/#server-installation). We've had 100,000s of players and developers use our guides to set up their own servers, and we hope you will too! ## ðŸ—‚ï¸ Related Repositories | Repository | Description | |--------------------|----------------------------------------------------------------------------------| | [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests) | Official quests and event scripts for ProjectEQ | -| [Maps](https://github.com/Akkadius/EQEmuMaps) | EQEmu-compatible zone maps | +| [Maps](https://github.com/EQEmu/maps) | EQEmu-compatible zone maps | | [Installer Resources](https://github.com/Akkadius/EQEmuInstall) | Scripts and assets for setting up EQEmu servers | | [Zone Utilities](https://github.com/EQEmu/zone-utilities) | Utilities for parsing, rendering, and manipulating EQ zone files | ## Contributors - - + + From 9d2cc213ceb1f7ae7d68082e45cb88ba33594064 Mon Sep 17 00:00:00 2001 From: JJ <3617814+joligario@users.noreply.github.com> Date: Mon, 5 Jan 2026 18:00:46 -0500 Subject: [PATCH 091/194] Fix Build Status link in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d5d04f206..b2ad64e4cc 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ Every system, packet, opcode, and game mechanic has been reconstructed through c | **Discord Community**| [![Discord](https://img.shields.io/discord/212663220849213441?label=Discord&logo=discord&color=7289DA)](https://discord.gg/QHsm7CD) | [Join Discord](https://discord.gg/QHsm7CD) | | **Latest Release** | [![Latest Release](https://img.shields.io/github/v/release/EQEmu/EQEmu)](https://github.com/EQEmu/EQEmu/releases)
[![Release Date](https://img.shields.io/github/release-date/EQEmu/EQEmu)](https://github.com/EQEmu/EQEmu/releases)
[![All Releases](https://img.shields.io/github/downloads/EQEmu/EQEmu/total.svg)](https://github.com/EQEmu/EQEmu/releases) | [View Releases](https://github.com/EQEmu/EQEmu/releases) | | **License** | [![License](https://img.shields.io/github/license/EQEmu/EQEmu)](./LICENSE) | [View License](./LICENSE) | -| **Build Status** | [![Build](https://github.com/EQEmu/EQEmu/actions/workflows/build.yaml/badge.svg)](https://github.com/EQEmu/EQEmu/actions/workflows/build.yaml) | [View Build Status](http://drone.akkadius.com/EQEmu/Server) | +| **Build Status** | [![Build](https://github.com/EQEmu/EQEmu/actions/workflows/build.yaml/badge.svg)](https://github.com/EQEmu/EQEmu/actions/workflows/build.yaml) | [View Build Status](https://github.com/EQEmu/EQEmu/actions/workflows/build.yaml) | | **Docker Pulls** | [![Docker Pulls](https://img.shields.io/docker/pulls/akkadius/eqemu-server)](https://hub.docker.com/r/akkadius/eqemu-server) | [Docker Hub](https://hub.docker.com/r/akkadius/eqemu-server) | | **Contributions** | [![GitHub PRs](https://img.shields.io/github/issues-pr-closed/EQEmu/EQEmu)](https://github.com/EQEmu/EQEmu/pulls?q=is%3Apr+is%3Aclosed) | [Closed PRs & Issues](https://github.com/EQEmu/EQEmu/pulls?q=is%3Apr+is%3Aclosed) | From 024abf74a8ef36d0a9ab49dff165a211a1875ab7 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 23 Jan 2026 21:38:43 +0000 Subject: [PATCH 092/194] Fix inventory overflow bug overwriting equipment slot 0 FindFirstFreeSlotThatFitsItem was returning 0 instead of INVALID_INDEX when no free slot was found. This caused items to be placed in slot 0 (charm equipment slot) when inventory was full, overwriting equipped items. Changes: - Fix FindFirstFreeSlotThatFitsItem to return INVALID_INDEX when no slot found - Add defensive check in PutItemInInventoryWithStacking to protect equipment slots 0-22 from being targeted for item placement --- common/inventory_profile.cpp | 2 +- zone/inventory.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index 6d16f50b09..4907cd1b91 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -1839,7 +1839,7 @@ int16 EQ::InventoryProfile::FindFirstFreeSlotThatFitsItem(const EQ::ItemData *it } } } - return 0; + return INVALID_INDEX; } //This function has the same flaw as noted above diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 812d09aba4..cb28aeb2c4 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -4679,7 +4679,8 @@ bool Client::PutItemInInventoryWithStacking(EQ::ItemInstance *inst) return true; } } - if (free_id != INVALID_INDEX) { + // Protect equipment slots (0-22) from being overwritten + if (free_id != INVALID_INDEX && !EQ::ValueWithin(free_id, EQ::invslot::EQUIPMENT_BEGIN, EQ::invslot::EQUIPMENT_END)) { if (PutItemInInventory(free_id, *inst, true)) { return true; } From 7c026ab25c6409bf413083bad29164838a780ce2 Mon Sep 17 00:00:00 2001 From: nytmyr <53322305+nytmyr@users.noreply.github.com> Date: Sun, 8 Feb 2026 21:37:25 -0600 Subject: [PATCH 093/194] [Bots] Make expansion settings universal Expansion Bitmask settings were saved by stances and should be universal for the bot. This addresses that as well as moves the data back to the `bot_data` table instead of the `bot_settings` table. This will check current settings saved and take the highest value of the stances to save to `bot_data`, if none are found (default), it will use the value from the rule `Bots:BotExpansionSettings` --- .../database/database_update_manifest_bots.h | 33 +- .../base/base_bot_data_repository.h | 392 +++++++++--------- common/version.h | 2 +- zone/bot.cpp | 11 +- zone/bot.h | 5 +- zone/bot_database.cpp | 5 +- 6 files changed, 236 insertions(+), 212 deletions(-) diff --git a/common/database/database_update_manifest_bots.h b/common/database/database_update_manifest_bots.h index 6c58df2744..b0dbb1fcb4 100644 --- a/common/database/database_update_manifest_bots.h +++ b/common/database/database_update_manifest_bots.h @@ -2126,7 +2126,38 @@ WHERE NOT EXISTS FROM spells_new WHERE bot_spells_entries.spell_id = spells_new.id); )", - } + }, + ManifestEntry{ + .version = 9055, + .description = "2026_02_8_move_expansion_bitmask.sql", + .check = "SHOW COLUMNS FROM `bot_data` LIKE 'expansion_bitmask'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `bot_data` + ADD COLUMN `expansion_bitmask` INT(11) NOT NULL DEFAULT '0' AFTER `corruption`; + +UPDATE bot_data bd +SET bd.expansion_bitmask = COALESCE( + (SELECT bs.`value` + FROM bot_settings bs + WHERE bs.`setting_id` = 0 + AND bs.`setting_type` = 0 + AND bs.bot_id = bd.bot_id + ORDER BY bs.`value` DESC + LIMIT 1), + + (SELECT rv.rule_value + FROM rule_values rv + WHERE rv.rule_name = 'Bots:BotExpansionSettings') +); + +DELETE +FROM bot_settings +WHERE `setting_id` = 0 +AND `setting_type` = 0; +)" + } // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ // .version = 9228, diff --git a/common/repositories/base/base_bot_data_repository.h b/common/repositories/base/base_bot_data_repository.h index 5b7314cf2c..b0ef53ba30 100644 --- a/common/repositories/base/base_bot_data_repository.h +++ b/common/repositories/base/base_bot_data_repository.h @@ -64,6 +64,7 @@ class BaseBotDataRepository { int16_t poison; int16_t disease; int16_t corruption; + int32_t expansion_bitmask; }; static std::string PrimaryKey() @@ -119,6 +120,7 @@ class BaseBotDataRepository { "poison", "disease", "corruption", + "expansion_bitmask", }; } @@ -170,6 +172,7 @@ class BaseBotDataRepository { "poison", "disease", "corruption", + "expansion_bitmask", }; } @@ -210,52 +213,52 @@ class BaseBotDataRepository { { BotData e{}; - e.bot_id = 0; - e.owner_id = 0; - e.spells_id = 0; - e.name = ""; - e.last_name = ""; - e.title = ""; - e.suffix = ""; - e.zone_id = 0; - e.gender = 0; - e.race = 0; - e.class_ = 0; - e.level = 0; - e.deity = 0; - e.creation_day = 0; - e.last_spawn = 0; - e.time_spawned = 0; - e.size = 0; - e.face = 1; - e.hair_color = 1; - e.hair_style = 1; - e.beard = 0; - e.beard_color = 1; - e.eye_color_1 = 1; - e.eye_color_2 = 1; - e.drakkin_heritage = 0; - e.drakkin_tattoo = 0; - e.drakkin_details = 0; - e.ac = 0; - e.atk = 0; - e.hp = 0; - e.mana = 0; - e.str = 75; - e.sta = 75; - e.cha = 75; - e.dex = 75; - e.int_ = 75; - e.agi = 75; - e.wis = 75; - e.extra_haste = 0; - e.fire = 0; - e.cold = 0; - e.magic = 0; - e.poison = 0; - e.disease = 0; - e.corruption = 0; - + e.bot_id = 0; + e.owner_id = 0; + e.spells_id = 0; + e.name = ""; + e.last_name = ""; + e.title = ""; + e.suffix = ""; + e.zone_id = 0; + e.gender = 0; + e.race = 0; + e.class_ = 0; + e.level = 0; + e.deity = 0; + e.creation_day = 0; + e.last_spawn = 0; + e.time_spawned = 0; + e.size = 0; + e.face = 1; + e.hair_color = 1; + e.hair_style = 1; + e.beard = 0; + e.beard_color = 1; + e.eye_color_1 = 1; + e.eye_color_2 = 1; + e.drakkin_heritage = 0; + e.drakkin_tattoo = 0; + e.drakkin_details = 0; + e.ac = 0; + e.atk = 0; + e.hp = 0; + e.mana = 0; + e.str = 75; + e.sta = 75; + e.cha = 75; + e.dex = 75; + e.int_ = 75; + e.agi = 75; + e.wis = 75; + e.extra_haste = 0; + e.fire = 0; + e.cold = 0; + e.magic = 0; + e.poison = 0; + e.disease = 0; + e.corruption = 0; + e.expansion_bitmask = 0; return e; } @@ -292,51 +295,52 @@ class BaseBotDataRepository { if (results.RowCount() == 1) { BotData e{}; - e.bot_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; - e.owner_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.spells_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.name = row[3] ? row[3] : ""; - e.last_name = row[4] ? row[4] : ""; - e.title = row[5] ? row[5] : ""; - e.suffix = row[6] ? row[6] : ""; - e.zone_id = row[7] ? static_cast(atoi(row[7])) : 0; - e.gender = row[8] ? static_cast(atoi(row[8])) : 0; - e.race = row[9] ? static_cast(atoi(row[9])) : 0; - e.class_ = row[10] ? static_cast(atoi(row[10])) : 0; - e.level = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; - e.deity = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; - e.creation_day = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; - e.last_spawn = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; - e.time_spawned = row[15] ? static_cast(strtoul(row[15], nullptr, 10)) : 0; - e.size = row[16] ? strtof(row[16], nullptr) : 0; - e.face = row[17] ? static_cast(atoi(row[17])) : 1; - e.hair_color = row[18] ? static_cast(atoi(row[18])) : 1; - e.hair_style = row[19] ? static_cast(atoi(row[19])) : 1; - e.beard = row[20] ? static_cast(atoi(row[20])) : 0; - e.beard_color = row[21] ? static_cast(atoi(row[21])) : 1; - e.eye_color_1 = row[22] ? static_cast(atoi(row[22])) : 1; - e.eye_color_2 = row[23] ? static_cast(atoi(row[23])) : 1; - e.drakkin_heritage = row[24] ? static_cast(atoi(row[24])) : 0; - e.drakkin_tattoo = row[25] ? static_cast(atoi(row[25])) : 0; - e.drakkin_details = row[26] ? static_cast(atoi(row[26])) : 0; - e.ac = row[27] ? static_cast(atoi(row[27])) : 0; - e.atk = row[28] ? static_cast(atoi(row[28])) : 0; - e.hp = row[29] ? static_cast(atoi(row[29])) : 0; - e.mana = row[30] ? static_cast(atoi(row[30])) : 0; - e.str = row[31] ? static_cast(atoi(row[31])) : 75; - e.sta = row[32] ? static_cast(atoi(row[32])) : 75; - e.cha = row[33] ? static_cast(atoi(row[33])) : 75; - e.dex = row[34] ? static_cast(atoi(row[34])) : 75; - e.int_ = row[35] ? static_cast(atoi(row[35])) : 75; - e.agi = row[36] ? static_cast(atoi(row[36])) : 75; - e.wis = row[37] ? static_cast(atoi(row[37])) : 75; - e.extra_haste = row[38] ? static_cast(atoi(row[38])) : 0; - e.fire = row[39] ? static_cast(atoi(row[39])) : 0; - e.cold = row[40] ? static_cast(atoi(row[40])) : 0; - e.magic = row[41] ? static_cast(atoi(row[41])) : 0; - e.poison = row[42] ? static_cast(atoi(row[42])) : 0; - e.disease = row[43] ? static_cast(atoi(row[43])) : 0; - e.corruption = row[44] ? static_cast(atoi(row[44])) : 0; + e.bot_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.owner_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.spells_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.name = row[3] ? row[3] : ""; + e.last_name = row[4] ? row[4] : ""; + e.title = row[5] ? row[5] : ""; + e.suffix = row[6] ? row[6] : ""; + e.zone_id = row[7] ? static_cast(atoi(row[7])) : 0; + e.gender = row[8] ? static_cast(atoi(row[8])) : 0; + e.race = row[9] ? static_cast(atoi(row[9])) : 0; + e.class_ = row[10] ? static_cast(atoi(row[10])) : 0; + e.level = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.deity = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; + e.creation_day = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.last_spawn = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; + e.time_spawned = row[15] ? static_cast(strtoul(row[15], nullptr, 10)) : 0; + e.size = row[16] ? strtof(row[16], nullptr) : 0; + e.face = row[17] ? static_cast(atoi(row[17])) : 1; + e.hair_color = row[18] ? static_cast(atoi(row[18])) : 1; + e.hair_style = row[19] ? static_cast(atoi(row[19])) : 1; + e.beard = row[20] ? static_cast(atoi(row[20])) : 0; + e.beard_color = row[21] ? static_cast(atoi(row[21])) : 1; + e.eye_color_1 = row[22] ? static_cast(atoi(row[22])) : 1; + e.eye_color_2 = row[23] ? static_cast(atoi(row[23])) : 1; + e.drakkin_heritage = row[24] ? static_cast(atoi(row[24])) : 0; + e.drakkin_tattoo = row[25] ? static_cast(atoi(row[25])) : 0; + e.drakkin_details = row[26] ? static_cast(atoi(row[26])) : 0; + e.ac = row[27] ? static_cast(atoi(row[27])) : 0; + e.atk = row[28] ? static_cast(atoi(row[28])) : 0; + e.hp = row[29] ? static_cast(atoi(row[29])) : 0; + e.mana = row[30] ? static_cast(atoi(row[30])) : 0; + e.str = row[31] ? static_cast(atoi(row[31])) : 75; + e.sta = row[32] ? static_cast(atoi(row[32])) : 75; + e.cha = row[33] ? static_cast(atoi(row[33])) : 75; + e.dex = row[34] ? static_cast(atoi(row[34])) : 75; + e.int_ = row[35] ? static_cast(atoi(row[35])) : 75; + e.agi = row[36] ? static_cast(atoi(row[36])) : 75; + e.wis = row[37] ? static_cast(atoi(row[37])) : 75; + e.extra_haste = row[38] ? static_cast(atoi(row[38])) : 0; + e.fire = row[39] ? static_cast(atoi(row[39])) : 0; + e.cold = row[40] ? static_cast(atoi(row[40])) : 0; + e.magic = row[41] ? static_cast(atoi(row[41])) : 0; + e.poison = row[42] ? static_cast(atoi(row[42])) : 0; + e.disease = row[43] ? static_cast(atoi(row[43])) : 0; + e.corruption = row[44] ? static_cast(atoi(row[44])) : 0; + e.expansion_bitmask = row[45] ? static_cast(atoi(row[45])) : 0; return e; } @@ -349,25 +353,14 @@ class BaseBotDataRepository { int bot_data_id ) { - std::string query; - - if (RuleB(Bots, BotSoftDeletes)) { - query = fmt::format( - "UPDATE {} SET name = SUBSTRING(CONCAT(name, '-deleted-', UNIX_TIMESTAMP()), 1, 64) WHERE {} = {}", - TableName(), - PrimaryKey(), - bot_data_id - ); - } - else { - query = fmt::format( + auto results = db.QueryDatabase( + fmt::format( "DELETE FROM {} WHERE {} = {}", TableName(), PrimaryKey(), bot_data_id - ); - } - auto results = db.QueryDatabase(query); + ) + ); return (results.Success() ? results.RowsAffected() : 0); } @@ -425,6 +418,7 @@ class BaseBotDataRepository { v.push_back(columns[42] + " = " + std::to_string(e.poison)); v.push_back(columns[43] + " = " + std::to_string(e.disease)); v.push_back(columns[44] + " = " + std::to_string(e.corruption)); + v.push_back(columns[45] + " = " + std::to_string(e.expansion_bitmask)); auto results = db.QueryDatabase( fmt::format( @@ -491,6 +485,7 @@ class BaseBotDataRepository { v.push_back(std::to_string(e.poison)); v.push_back(std::to_string(e.disease)); v.push_back(std::to_string(e.corruption)); + v.push_back(std::to_string(e.expansion_bitmask)); auto results = db.QueryDatabase( fmt::format( @@ -565,6 +560,7 @@ class BaseBotDataRepository { v.push_back(std::to_string(e.poison)); v.push_back(std::to_string(e.disease)); v.push_back(std::to_string(e.corruption)); + v.push_back(std::to_string(e.expansion_bitmask)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -598,51 +594,52 @@ class BaseBotDataRepository { for (auto row = results.begin(); row != results.end(); ++row) { BotData e{}; - e.bot_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; - e.owner_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.spells_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.name = row[3] ? row[3] : ""; - e.last_name = row[4] ? row[4] : ""; - e.title = row[5] ? row[5] : ""; - e.suffix = row[6] ? row[6] : ""; - e.zone_id = row[7] ? static_cast(atoi(row[7])) : 0; - e.gender = row[8] ? static_cast(atoi(row[8])) : 0; - e.race = row[9] ? static_cast(atoi(row[9])) : 0; - e.class_ = row[10] ? static_cast(atoi(row[10])) : 0; - e.level = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; - e.deity = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; - e.creation_day = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; - e.last_spawn = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; - e.time_spawned = row[15] ? static_cast(strtoul(row[15], nullptr, 10)) : 0; - e.size = row[16] ? strtof(row[16], nullptr) : 0; - e.face = row[17] ? static_cast(atoi(row[17])) : 1; - e.hair_color = row[18] ? static_cast(atoi(row[18])) : 1; - e.hair_style = row[19] ? static_cast(atoi(row[19])) : 1; - e.beard = row[20] ? static_cast(atoi(row[20])) : 0; - e.beard_color = row[21] ? static_cast(atoi(row[21])) : 1; - e.eye_color_1 = row[22] ? static_cast(atoi(row[22])) : 1; - e.eye_color_2 = row[23] ? static_cast(atoi(row[23])) : 1; - e.drakkin_heritage = row[24] ? static_cast(atoi(row[24])) : 0; - e.drakkin_tattoo = row[25] ? static_cast(atoi(row[25])) : 0; - e.drakkin_details = row[26] ? static_cast(atoi(row[26])) : 0; - e.ac = row[27] ? static_cast(atoi(row[27])) : 0; - e.atk = row[28] ? static_cast(atoi(row[28])) : 0; - e.hp = row[29] ? static_cast(atoi(row[29])) : 0; - e.mana = row[30] ? static_cast(atoi(row[30])) : 0; - e.str = row[31] ? static_cast(atoi(row[31])) : 75; - e.sta = row[32] ? static_cast(atoi(row[32])) : 75; - e.cha = row[33] ? static_cast(atoi(row[33])) : 75; - e.dex = row[34] ? static_cast(atoi(row[34])) : 75; - e.int_ = row[35] ? static_cast(atoi(row[35])) : 75; - e.agi = row[36] ? static_cast(atoi(row[36])) : 75; - e.wis = row[37] ? static_cast(atoi(row[37])) : 75; - e.extra_haste = row[38] ? static_cast(atoi(row[38])) : 0; - e.fire = row[39] ? static_cast(atoi(row[39])) : 0; - e.cold = row[40] ? static_cast(atoi(row[40])) : 0; - e.magic = row[41] ? static_cast(atoi(row[41])) : 0; - e.poison = row[42] ? static_cast(atoi(row[42])) : 0; - e.disease = row[43] ? static_cast(atoi(row[43])) : 0; - e.corruption = row[44] ? static_cast(atoi(row[44])) : 0; + e.bot_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.owner_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.spells_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.name = row[3] ? row[3] : ""; + e.last_name = row[4] ? row[4] : ""; + e.title = row[5] ? row[5] : ""; + e.suffix = row[6] ? row[6] : ""; + e.zone_id = row[7] ? static_cast(atoi(row[7])) : 0; + e.gender = row[8] ? static_cast(atoi(row[8])) : 0; + e.race = row[9] ? static_cast(atoi(row[9])) : 0; + e.class_ = row[10] ? static_cast(atoi(row[10])) : 0; + e.level = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.deity = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; + e.creation_day = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.last_spawn = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; + e.time_spawned = row[15] ? static_cast(strtoul(row[15], nullptr, 10)) : 0; + e.size = row[16] ? strtof(row[16], nullptr) : 0; + e.face = row[17] ? static_cast(atoi(row[17])) : 1; + e.hair_color = row[18] ? static_cast(atoi(row[18])) : 1; + e.hair_style = row[19] ? static_cast(atoi(row[19])) : 1; + e.beard = row[20] ? static_cast(atoi(row[20])) : 0; + e.beard_color = row[21] ? static_cast(atoi(row[21])) : 1; + e.eye_color_1 = row[22] ? static_cast(atoi(row[22])) : 1; + e.eye_color_2 = row[23] ? static_cast(atoi(row[23])) : 1; + e.drakkin_heritage = row[24] ? static_cast(atoi(row[24])) : 0; + e.drakkin_tattoo = row[25] ? static_cast(atoi(row[25])) : 0; + e.drakkin_details = row[26] ? static_cast(atoi(row[26])) : 0; + e.ac = row[27] ? static_cast(atoi(row[27])) : 0; + e.atk = row[28] ? static_cast(atoi(row[28])) : 0; + e.hp = row[29] ? static_cast(atoi(row[29])) : 0; + e.mana = row[30] ? static_cast(atoi(row[30])) : 0; + e.str = row[31] ? static_cast(atoi(row[31])) : 75; + e.sta = row[32] ? static_cast(atoi(row[32])) : 75; + e.cha = row[33] ? static_cast(atoi(row[33])) : 75; + e.dex = row[34] ? static_cast(atoi(row[34])) : 75; + e.int_ = row[35] ? static_cast(atoi(row[35])) : 75; + e.agi = row[36] ? static_cast(atoi(row[36])) : 75; + e.wis = row[37] ? static_cast(atoi(row[37])) : 75; + e.extra_haste = row[38] ? static_cast(atoi(row[38])) : 0; + e.fire = row[39] ? static_cast(atoi(row[39])) : 0; + e.cold = row[40] ? static_cast(atoi(row[40])) : 0; + e.magic = row[41] ? static_cast(atoi(row[41])) : 0; + e.poison = row[42] ? static_cast(atoi(row[42])) : 0; + e.disease = row[43] ? static_cast(atoi(row[43])) : 0; + e.corruption = row[44] ? static_cast(atoi(row[44])) : 0; + e.expansion_bitmask = row[45] ? static_cast(atoi(row[45])) : 0; all_entries.push_back(e); } @@ -667,51 +664,52 @@ class BaseBotDataRepository { for (auto row = results.begin(); row != results.end(); ++row) { BotData e{}; - e.bot_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; - e.owner_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; - e.spells_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; - e.name = row[3] ? row[3] : ""; - e.last_name = row[4] ? row[4] : ""; - e.title = row[5] ? row[5] : ""; - e.suffix = row[6] ? row[6] : ""; - e.zone_id = row[7] ? static_cast(atoi(row[7])) : 0; - e.gender = row[8] ? static_cast(atoi(row[8])) : 0; - e.race = row[9] ? static_cast(atoi(row[9])) : 0; - e.class_ = row[10] ? static_cast(atoi(row[10])) : 0; - e.level = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; - e.deity = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; - e.creation_day = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; - e.last_spawn = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; - e.time_spawned = row[15] ? static_cast(strtoul(row[15], nullptr, 10)) : 0; - e.size = row[16] ? strtof(row[16], nullptr) : 0; - e.face = row[17] ? static_cast(atoi(row[17])) : 1; - e.hair_color = row[18] ? static_cast(atoi(row[18])) : 1; - e.hair_style = row[19] ? static_cast(atoi(row[19])) : 1; - e.beard = row[20] ? static_cast(atoi(row[20])) : 0; - e.beard_color = row[21] ? static_cast(atoi(row[21])) : 1; - e.eye_color_1 = row[22] ? static_cast(atoi(row[22])) : 1; - e.eye_color_2 = row[23] ? static_cast(atoi(row[23])) : 1; - e.drakkin_heritage = row[24] ? static_cast(atoi(row[24])) : 0; - e.drakkin_tattoo = row[25] ? static_cast(atoi(row[25])) : 0; - e.drakkin_details = row[26] ? static_cast(atoi(row[26])) : 0; - e.ac = row[27] ? static_cast(atoi(row[27])) : 0; - e.atk = row[28] ? static_cast(atoi(row[28])) : 0; - e.hp = row[29] ? static_cast(atoi(row[29])) : 0; - e.mana = row[30] ? static_cast(atoi(row[30])) : 0; - e.str = row[31] ? static_cast(atoi(row[31])) : 75; - e.sta = row[32] ? static_cast(atoi(row[32])) : 75; - e.cha = row[33] ? static_cast(atoi(row[33])) : 75; - e.dex = row[34] ? static_cast(atoi(row[34])) : 75; - e.int_ = row[35] ? static_cast(atoi(row[35])) : 75; - e.agi = row[36] ? static_cast(atoi(row[36])) : 75; - e.wis = row[37] ? static_cast(atoi(row[37])) : 75; - e.extra_haste = row[38] ? static_cast(atoi(row[38])) : 0; - e.fire = row[39] ? static_cast(atoi(row[39])) : 0; - e.cold = row[40] ? static_cast(atoi(row[40])) : 0; - e.magic = row[41] ? static_cast(atoi(row[41])) : 0; - e.poison = row[42] ? static_cast(atoi(row[42])) : 0; - e.disease = row[43] ? static_cast(atoi(row[43])) : 0; - e.corruption = row[44] ? static_cast(atoi(row[44])) : 0; + e.bot_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.owner_id = row[1] ? static_cast(strtoul(row[1], nullptr, 10)) : 0; + e.spells_id = row[2] ? static_cast(strtoul(row[2], nullptr, 10)) : 0; + e.name = row[3] ? row[3] : ""; + e.last_name = row[4] ? row[4] : ""; + e.title = row[5] ? row[5] : ""; + e.suffix = row[6] ? row[6] : ""; + e.zone_id = row[7] ? static_cast(atoi(row[7])) : 0; + e.gender = row[8] ? static_cast(atoi(row[8])) : 0; + e.race = row[9] ? static_cast(atoi(row[9])) : 0; + e.class_ = row[10] ? static_cast(atoi(row[10])) : 0; + e.level = row[11] ? static_cast(strtoul(row[11], nullptr, 10)) : 0; + e.deity = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; + e.creation_day = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.last_spawn = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; + e.time_spawned = row[15] ? static_cast(strtoul(row[15], nullptr, 10)) : 0; + e.size = row[16] ? strtof(row[16], nullptr) : 0; + e.face = row[17] ? static_cast(atoi(row[17])) : 1; + e.hair_color = row[18] ? static_cast(atoi(row[18])) : 1; + e.hair_style = row[19] ? static_cast(atoi(row[19])) : 1; + e.beard = row[20] ? static_cast(atoi(row[20])) : 0; + e.beard_color = row[21] ? static_cast(atoi(row[21])) : 1; + e.eye_color_1 = row[22] ? static_cast(atoi(row[22])) : 1; + e.eye_color_2 = row[23] ? static_cast(atoi(row[23])) : 1; + e.drakkin_heritage = row[24] ? static_cast(atoi(row[24])) : 0; + e.drakkin_tattoo = row[25] ? static_cast(atoi(row[25])) : 0; + e.drakkin_details = row[26] ? static_cast(atoi(row[26])) : 0; + e.ac = row[27] ? static_cast(atoi(row[27])) : 0; + e.atk = row[28] ? static_cast(atoi(row[28])) : 0; + e.hp = row[29] ? static_cast(atoi(row[29])) : 0; + e.mana = row[30] ? static_cast(atoi(row[30])) : 0; + e.str = row[31] ? static_cast(atoi(row[31])) : 75; + e.sta = row[32] ? static_cast(atoi(row[32])) : 75; + e.cha = row[33] ? static_cast(atoi(row[33])) : 75; + e.dex = row[34] ? static_cast(atoi(row[34])) : 75; + e.int_ = row[35] ? static_cast(atoi(row[35])) : 75; + e.agi = row[36] ? static_cast(atoi(row[36])) : 75; + e.wis = row[37] ? static_cast(atoi(row[37])) : 75; + e.extra_haste = row[38] ? static_cast(atoi(row[38])) : 0; + e.fire = row[39] ? static_cast(atoi(row[39])) : 0; + e.cold = row[40] ? static_cast(atoi(row[40])) : 0; + e.magic = row[41] ? static_cast(atoi(row[41])) : 0; + e.poison = row[42] ? static_cast(atoi(row[42])) : 0; + e.disease = row[43] ? static_cast(atoi(row[43])) : 0; + e.corruption = row[44] ? static_cast(atoi(row[44])) : 0; + e.expansion_bitmask = row[45] ? static_cast(atoi(row[45])) : 0; all_entries.push_back(e); } @@ -831,6 +829,7 @@ class BaseBotDataRepository { v.push_back(std::to_string(e.poison)); v.push_back(std::to_string(e.disease)); v.push_back(std::to_string(e.corruption)); + v.push_back(std::to_string(e.expansion_bitmask)); auto results = db.QueryDatabase( fmt::format( @@ -898,6 +897,7 @@ class BaseBotDataRepository { v.push_back(std::to_string(e.poison)); v.push_back(std::to_string(e.disease)); v.push_back(std::to_string(e.corruption)); + v.push_back(std::to_string(e.expansion_bitmask)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/version.h b/common/version.h index 34958bcef7..9d4c3a688a 100644 --- a/common/version.h +++ b/common/version.h @@ -42,5 +42,5 @@ */ #define CURRENT_BINARY_DATABASE_VERSION 9328 -#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054 +#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9055 #define CUSTOM_BINARY_DATABASE_VERSION 0 diff --git a/zone/bot.cpp b/zone/bot.cpp index ca7f6134cd..359a0d79e4 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -10395,9 +10395,6 @@ void Bot::SetBotSetting(uint8 setting_type, uint16 bot_setting, int setting_valu void Bot::SetBotBaseSetting(uint16 bot_setting, int setting_value) { switch (bot_setting) { - case BotBaseSettings::ExpansionBitmask: - SetExpansionBitmask(setting_value); - break; case BotBaseSettings::ShowHelm: SetShowHelm(setting_value); break; @@ -10444,8 +10441,6 @@ void Bot::SetBotBaseSetting(uint16 bot_setting, int setting_value) { int Bot::GetBotBaseSetting(uint16 bot_setting) { switch (bot_setting) { - case BotBaseSettings::ExpansionBitmask: - return GetExpansionBitmask(); case BotBaseSettings::ShowHelm: return GetShowHelm(); case BotBaseSettings::FollowDistance: @@ -10481,8 +10476,6 @@ int Bot::GetBotBaseSetting(uint16 bot_setting) { int Bot::GetDefaultBotBaseSetting(uint16 bot_setting, uint8 stance) { switch (bot_setting) { - case BotBaseSettings::ExpansionBitmask: - return RuleI(Bots, BotExpansionSettings); case BotBaseSettings::ShowHelm: return true; case BotBaseSettings::FollowDistance: @@ -10541,7 +10534,7 @@ void Bot::LoadDefaultBotSettings() { uint8 bot_stance = GetBotStance(); - for (uint16 i = BotBaseSettings::START_ALL; i <= BotBaseSettings::END; ++i) { + for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) { SetBotBaseSetting(i, GetDefaultSetting(BotSettingCategories::BaseSetting, i, bot_stance)); LogBotSettingsDetail("{} says, 'Setting default {} [{}] to [{}]'", GetCleanName(), GetBotSettingCategoryName(i), i, GetDefaultBotBaseSetting(i, bot_stance)); } @@ -12925,7 +12918,7 @@ uint16 Bot::GetBotSpellCategoryIDByShortName(std::string setting_string) { } bool Bot::IsValidBotBaseSetting(uint16 setting_type) { - return EQ::ValueWithin(setting_type, BotBaseSettings::START_ALL, BotBaseSettings::END); + return EQ::ValueWithin(setting_type, BotBaseSettings::START, BotBaseSettings::END); } std::string Bot::GetBotSettingCategoryName(uint16 setting_type) { diff --git a/zone/bot.h b/zone/bot.h index 6985ba2b8e..04a47f0a31 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -159,7 +159,6 @@ namespace BotPriorityCategories { }; namespace BotBaseSettings { - constexpr uint16 ExpansionBitmask = 0; constexpr uint16 ShowHelm = 1; constexpr uint16 FollowDistance = 2; constexpr uint16 StopMeleeLevel = 3; @@ -174,13 +173,11 @@ namespace BotBaseSettings { constexpr uint16 SitHPPct = 12; constexpr uint16 SitManaPct = 13; - constexpr uint16 START_ALL = ExpansionBitmask; - constexpr uint16 START = BotBaseSettings::ShowHelm; // Everything above this cannot be copied, changed or viewed by players + constexpr uint16 START = BotBaseSettings::ShowHelm; constexpr uint16 END = BotBaseSettings::SitManaPct; // Increment as needed }; static std::map botBaseSettings_names = { - { BotBaseSettings::ExpansionBitmask, "ExpansionBitmask" }, { BotBaseSettings::ShowHelm, "ShowHelm" }, { BotBaseSettings::FollowDistance, "FollowDistance" }, { BotBaseSettings::StopMeleeLevel, "StopMeleeLevel" }, diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 48ea9bee2e..bf422b2091 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -460,6 +460,7 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot) loaded_bot->SetSurname(e.last_name); loaded_bot->SetTitle(e.title); loaded_bot->SetSuffix(e.suffix); + loaded_bot->SetExpansionBitmask(e.expansion_bitmask); } return true; @@ -514,6 +515,7 @@ bool BotDatabase::SaveNewBot(Bot* b, uint32& bot_id) e.poison = b->GetBasePR(); e.disease = b->GetBaseDR(); e.corruption = b->GetBaseCorrup(); + e.expansion_bitmask = b->GetExpansionBitmask(); e = BotDataRepository::InsertOne(database, e); @@ -578,6 +580,7 @@ bool BotDatabase::SaveBot(Bot* b) e.poison = b->GetBasePR(); e.disease = b->GetBaseDR(); e.corruption = b->GetBaseCorrup(); + e.expansion_bitmask = b->GetExpansionBitmask(); return BotDataRepository::UpdateOne(database, e); } @@ -2351,7 +2354,7 @@ bool BotDatabase::SaveBotSettings(Mob* m) if (m->IsBot()) { uint8 bot_stance = m->CastToBot()->GetBotStance(); - for (uint16 i = BotBaseSettings::START_ALL; i <= BotBaseSettings::END; ++i) { + for (uint16 i = BotBaseSettings::START; i <= BotBaseSettings::END; ++i) { if (m->CastToBot()->GetBotBaseSetting(i) != m->CastToBot()->GetDefaultBotBaseSetting(i, bot_stance)) { auto e = BotSettingsRepository::BotSettings{ .character_id = character_id, From 5bedbc18c420186bdd9ef94a9afa2db29922bcf4 Mon Sep 17 00:00:00 2001 From: straps-eq Date: Thu, 12 Mar 2026 10:07:47 -0500 Subject: [PATCH 094/194] Enhance quantity validation for stackable items Added handling for zero/negative quantity purchases for stackable items. --- zone/trading.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/zone/trading.cpp b/zone/trading.cpp index b5f26eb4d5..a0e9d711cf 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -2947,6 +2947,20 @@ void Client::BuyTraderItemOutsideBazaar(TraderBuy_Struct *tbs, const EQApplicati else { charges = buy_item->GetCharges(); } + } else { + if (charges <= 0) { + LogTrading("Rejecting purchase with zero/negative quantity [{}] for stackable item [{}]", + charges, buy_item->GetItem()->Name); + in->method = BazaarByParcel; + in->sub_action = Failed; + TraderRepository::UpdateActiveTransaction(database, trader_item.id, false); + TradeRequestFailed(app); + return; + } + if (charges > trader_item.item_charges) { + charges = trader_item.item_charges; + } + tbs->quantity = static_cast(charges); } LogTrading( From 287d4a66dc0c4008a3a4f3a508dd38e01a32f1a5 Mon Sep 17 00:00:00 2001 From: Knightly Date: Tue, 31 Mar 2026 22:08:02 -1000 Subject: [PATCH 095/194] Fixup CMakePresets.json - Fix vcpkg presetName variable evaluation - Remove tabs & fix alignment --- CMakePresets.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index aa1a294534..ca50a36259 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -16,9 +16,9 @@ "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", "CMAKE_C_COMPILER_LAUNCHER": "ccache", "CMAKE_CXX_COMPILER_LAUNCHER": "ccache", - "EQEMU_BUILD_LOGIN": "ON", - "EQEMU_BUILD_TESTS": "ON", - "EQEMU_ADD_PROFILER": "ON" + "EQEMU_BUILD_LOGIN": "ON", + "EQEMU_BUILD_TESTS": "ON", + "EQEMU_ADD_PROFILER": "ON" } }, { @@ -30,19 +30,19 @@ "CMAKE_BUILD_TYPE": "Release", "CMAKE_C_COMPILER_LAUNCHER": "ccache", "CMAKE_CXX_COMPILER_LAUNCHER": "ccache", - "EQEMU_BUILD_LOGIN": "ON" + "EQEMU_BUILD_LOGIN": "ON" } }, - { + { "name": "win-msvc", "displayName": "Windows MSVC (VS 2022)", "generator": "Visual Studio 17 2022", - "binaryDir": "${sourceDir}/build/{presetName}", + "binaryDir": "${sourceDir}/build/${presetName}", "architecture": { "value": "x64" }, "cacheVariables": { "CMAKE_CONFIGURATION_TYPES": "Debug;Release", - "EQEMU_BUILD_LOGIN": "ON", - "EQEMU_BUILD_TESTS": "ON" + "EQEMU_BUILD_LOGIN": "ON", + "EQEMU_BUILD_TESTS": "ON" } } ] From 7ab909ee47e8639b2137a6818bfdff99845c9d39 Mon Sep 17 00:00:00 2001 From: Knightly Date: Tue, 31 Mar 2026 21:24:32 -1000 Subject: [PATCH 096/194] Standardize Licensing - License was intended to be GPLv3 per earlier commit of GPLv3 LICENSE FILE - This is confirmed by the inclusion of libraries that are incompatible with GPLv2 - This is also confirmed by KLS and the agreement of KLS's predecessors - Added GPLv3 license headers to the compilable source files - Removed Folly licensing in strings.h since the string functions do not match the Folly functions and are standard functions - this must have been left over from previous implementations - Removed individual contributor license headers since the project has been under the "developer" mantle for many years - Removed comments on files that were previously automatically generated since they've been manually modified multiple times and there are no automatic scripts referencing them (removed in 2023) --- LICENSE | 674 ----------------- LICENSE.md | 675 ++++++++++++++++++ client_files/export/main.cpp | 19 +- client_files/import/main.cpp | 19 +- common/StackWalker/StackWalker.cpp | 17 + common/StackWalker/StackWalker.h | 17 + common/additive_lagged_fibonacci_engine.h | 19 +- common/base_packet.cpp | 19 +- common/base_packet.h | 19 +- common/bazaar.cpp | 17 + common/bazaar.h | 17 + common/bodytypes.cpp | 17 + common/bodytypes.h | 19 +- common/classes.cpp | 21 +- common/classes.h | 19 +- common/cli/argh.h | 17 + common/cli/eqemu_command_handler.cpp | 35 +- common/cli/eqemu_command_handler.h | 35 +- common/cli/terminal_color.hpp | 17 + common/compression.cpp | 17 + common/compression.h | 17 + common/condition.cpp | 19 +- common/condition.h | 19 +- common/content/world_content_service.cpp | 17 + common/content/world_content_service.h | 17 + common/crash.cpp | 17 + common/crash.h | 17 + common/crc16.cpp | 17 + common/crc16.h | 17 + common/crc32.cpp | 17 + common/crc32.h | 17 + common/cron/croncpp.h | 17 + common/data_bucket.cpp | 17 + common/data_bucket.h | 17 + common/data_verification.h | 35 +- common/database.cpp | 19 +- common/database.h | 19 +- common/database/database_dump_service.cpp | 35 +- common/database/database_dump_service.h | 35 +- common/database/database_update.cpp | 17 + common/database/database_update.h | 17 + common/database/database_update_manifest.h | 17 + .../database/database_update_manifest_bots.h | 17 + .../database_update_manifest_custom.h | 17 + common/database_instances.cpp | 33 +- common/database_schema.h | 35 +- common/dbcore.cpp | 17 + common/dbcore.h | 17 + common/deity.cpp | 18 +- common/deity.h | 18 +- common/discord/discord.cpp | 17 + common/discord/discord.h | 17 + common/discord/discord_manager.cpp | 17 + common/discord/discord_manager.h | 17 + common/dynamic_zone_base.cpp | 17 + common/dynamic_zone_base.h | 17 + common/dynamic_zone_lockout.cpp | 17 + common/dynamic_zone_lockout.h | 17 + common/emu_constants.cpp | 18 +- common/emu_constants.h | 18 +- common/emu_limits.cpp | 21 +- common/emu_limits.h | 20 +- common/emu_opcodes.cpp | 19 +- common/emu_opcodes.h | 33 +- common/emu_oplist.h | 17 + common/emu_versions.cpp | 22 +- common/emu_versions.h | 20 +- common/eq_constants.h | 18 +- common/eq_limits.cpp | 18 +- common/eq_limits.h | 24 +- common/eq_packet.cpp | 18 +- common/eq_packet.h | 18 +- common/eq_packet_structs.h | 19 +- common/eq_stream_ident.cpp | 17 + common/eq_stream_ident.h | 17 + common/eq_stream_intf.h | 17 + common/eq_stream_locator.h | 19 +- common/eq_stream_proxy.cpp | 17 + common/eq_stream_proxy.h | 17 + common/eqdb.cpp | 19 +- common/eqdb.h | 19 +- common/eqdb_res.cpp | 19 +- common/eqdb_res.h | 19 +- common/eqemu_config.cpp | 19 +- common/eqemu_config.h | 19 +- common/eqemu_config_elements.h | 17 + common/eqemu_exception.cpp | 19 +- common/eqemu_exception.h | 19 +- common/eqemu_logsys.cpp | 35 +- common/eqemu_logsys.h | 35 +- common/eqemu_logsys_log_aliases.h | 35 +- common/eqtime.cpp | 19 +- common/eqtime.h | 17 + common/event/event_loop.h | 17 + common/event/task.h | 17 + common/event/task_scheduler.h | 17 + common/event/timer.h | 17 + common/event_sub.cpp | 17 + common/event_sub.h | 17 + .../events/player_event_discord_formatter.cpp | 17 + .../events/player_event_discord_formatter.h | 17 + common/events/player_event_logs.cpp | 17 + common/events/player_event_logs.h | 17 + common/events/player_events.h | 17 + common/evolving_items.cpp | 17 + common/evolving_items.h | 17 + common/extprofile.cpp | 19 +- common/extprofile.h | 19 +- common/faction.cpp | 19 +- common/faction.h | 19 +- common/features.h | 19 +- common/file.cpp | 35 +- common/file.h | 35 +- common/fixed_memory_hash_set.h | 19 +- common/fixed_memory_variable_hash_set.h | 19 +- common/global_define.h | 19 +- common/guild_base.cpp | 33 +- common/guild_base.h | 17 + common/guilds.h | 19 +- common/inventory_profile.cpp | 19 +- common/inventory_profile.h | 18 +- common/inventory_slot.cpp | 18 +- common/inventory_slot.h | 20 +- common/ip_util.cpp | 35 +- common/ip_util.h | 35 +- common/ipc_mutex.cpp | 19 +- common/ipc_mutex.h | 19 +- common/item_data.cpp | 18 +- common/item_data.h | 18 +- common/item_instance.cpp | 19 +- common/item_instance.h | 18 +- common/json_config.cpp | 17 + common/json_config.h | 17 + common/light_source.cpp | 22 +- common/light_source.h | 24 +- common/linked_list.h | 19 +- common/loot.h | 17 + common/mail_oplist.h | 17 + common/md5.cpp | 17 + common/md5.h | 17 + common/memory/ksm.hpp | 17 + common/memory_buffer.cpp | 20 +- common/memory_buffer.h | 18 +- common/memory_mapped_file.cpp | 19 +- common/memory_mapped_file.h | 19 +- common/misc.cpp | 17 + common/misc.h | 17 + common/misc_functions.cpp | 19 +- common/misc_functions.h | 19 +- common/mutex.cpp | 19 +- common/mutex.h | 19 +- common/mysql_request_result.cpp | 17 + common/mysql_request_result.h | 17 + common/mysql_request_row.cpp | 17 + common/mysql_request_row.h | 17 + common/mysql_stmt.cpp | 17 + common/mysql_stmt.h | 17 + common/net/console_server.cpp | 17 + common/net/console_server.h | 17 + common/net/console_server_connection.cpp | 17 + common/net/console_server_connection.h | 17 + common/net/crc32.cpp | 17 + common/net/crc32.h | 17 + common/net/dns.h | 17 + common/net/endian.h | 17 + common/net/eqstream.cpp | 17 + common/net/eqstream.h | 17 + common/net/packet.cpp | 17 + common/net/packet.h | 17 + common/net/reliable_stream_connection.cpp | 17 + common/net/reliable_stream_connection.h | 17 + common/net/reliable_stream_pooling.h | 17 + common/net/reliable_stream_structs.h | 17 + common/net/servertalk_client_connection.cpp | 17 + common/net/servertalk_client_connection.h | 17 + common/net/servertalk_common.h | 17 + .../servertalk_legacy_client_connection.cpp | 17 + .../net/servertalk_legacy_client_connection.h | 17 + common/net/servertalk_server.cpp | 17 + common/net/servertalk_server.h | 17 + common/net/servertalk_server_connection.cpp | 17 + common/net/servertalk_server_connection.h | 17 + common/net/tcp_connection.cpp | 17 + common/net/tcp_connection.h | 17 + common/net/tcp_connection_pooling.h | 17 + common/net/tcp_server.cpp | 17 + common/net/tcp_server.h | 17 + common/net/websocket_server.cpp | 17 + common/net/websocket_server.h | 17 + common/net/websocket_server_connection.cpp | 17 + common/net/websocket_server_connection.h | 17 + common/op_codes.h | 17 + common/opcode_dispatch.h | 17 + common/opcode_map.cpp | 17 + common/opcodemgr.cpp | 19 +- common/opcodemgr.h | 19 +- common/packet_dump.cpp | 19 +- common/packet_dump.h | 19 +- common/packet_dump_file.cpp | 19 +- common/packet_dump_file.h | 19 +- common/packet_functions.cpp | 19 +- common/packet_functions.h | 19 +- common/packetfile.cpp | 17 + common/packetfile.h | 17 + common/patches/deprecated_rof2_itemfields.h | 17 + common/patches/deprecated_rof_itemfields.h | 17 + common/patches/deprecated_sod_itemfields.h | 17 + common/patches/deprecated_sof_itemfields.h | 17 + common/patches/deprecated_sof_opcode_list.h | 17 + .../deprecated_titanium_itemfields_a.h | 17 + .../deprecated_titanium_itemfields_b.h | 17 + common/patches/deprecated_uf_itemfields.h | 17 + common/patches/patches.cpp | 20 +- common/patches/patches.h | 20 +- common/patches/rof.cpp | 18 +- common/patches/rof.h | 20 +- common/patches/rof2.cpp | 18 +- common/patches/rof2.h | 20 +- common/patches/rof2_limits.cpp | 18 +- common/patches/rof2_limits.h | 18 +- common/patches/rof2_ops.h | 19 +- common/patches/rof2_structs.h | 18 +- common/patches/rof_limits.cpp | 18 +- common/patches/rof_limits.h | 20 +- common/patches/rof_ops.h | 21 +- common/patches/rof_structs.h | 18 +- common/patches/sod.cpp | 18 +- common/patches/sod.h | 20 +- common/patches/sod_limits.cpp | 18 +- common/patches/sod_limits.h | 20 +- common/patches/sod_ops.h | 21 +- common/patches/sod_structs.h | 18 +- common/patches/sof.cpp | 18 +- common/patches/sof.h | 20 +- common/patches/sof_limits.cpp | 18 +- common/patches/sof_limits.h | 20 +- common/patches/sof_ops.h | 21 +- common/patches/sof_structs.h | 18 +- common/patches/ss_declare.h | 20 +- common/patches/ss_define.h | 20 +- common/patches/ss_register.h | 20 +- common/patches/template.cpp | 17 + common/patches/template.h | 17 + common/patches/template_limits.cpp | 25 +- common/patches/template_limits.h | 26 +- common/patches/template_ops.h | 17 + common/patches/template_structs.h | 17 + common/patches/titanium.cpp | 18 +- common/patches/titanium.h | 20 +- common/patches/titanium_limits.cpp | 18 +- common/patches/titanium_limits.h | 20 +- common/patches/titanium_ops.h | 21 +- common/patches/titanium_structs.h | 18 +- common/patches/uf.cpp | 18 +- common/patches/uf.h | 20 +- common/patches/uf_limits.cpp | 18 +- common/patches/uf_limits.h | 20 +- common/patches/uf_ops.h | 21 +- common/patches/uf_structs.h | 18 +- common/path_manager.cpp | 17 + common/path_manager.h | 17 + common/pch/app-pch.h | 17 + common/pch/std-pch.h | 17 + common/perl_eqdb.cpp | 26 +- common/perl_eqdb_res.cpp | 26 +- common/platform.cpp | 35 +- common/platform.h | 35 +- common/platform/inet.h | 17 + common/platform/platform.h | 17 + common/platform/posix/include_inet.h | 17 + common/platform/posix/include_pthreads.h | 17 + common/platform/win/include_windows.h | 17 + common/platform/win/include_winsock2.h | 17 + common/proc_launcher.cpp | 19 +- common/proc_launcher.h | 19 +- common/process.cpp | 17 + common/process.h | 17 + common/process/process.cpp | 17 + common/process/process.h | 17 + common/profanity_manager.cpp | 18 +- common/profanity_manager.h | 24 +- common/profiler.h | 19 +- common/ptimer.cpp | 19 +- common/ptimer.h | 19 +- common/queue.h | 19 +- common/races.cpp | 19 +- common/races.h | 19 +- common/raid.h | 19 +- common/random.h | 19 +- common/rdtsc.cpp | 19 +- common/rdtsc.h | 19 +- common/repositories/aa_ability_repository.h | 17 + .../repositories/aa_rank_effects_repository.h | 17 + .../repositories/aa_rank_prereqs_repository.h | 17 + common/repositories/aa_ranks_repository.h | 17 + .../repositories/account_flags_repository.h | 17 + common/repositories/account_ip_repository.h | 17 + common/repositories/account_repository.h | 17 + .../repositories/account_rewards_repository.h | 17 + .../adventure_details_repository.h | 17 + .../adventure_members_repository.h | 17 + .../repositories/adventure_stats_repository.h | 17 + ...venture_template_entry_flavor_repository.h | 17 + .../adventure_template_entry_repository.h | 17 + .../adventure_template_repository.h | 17 + .../alternate_currency_repository.h | 17 + common/repositories/auras_repository.h | 17 + .../base/base_aa_ability_repository.h | 17 + .../base/base_aa_rank_effects_repository.h | 17 + .../base/base_aa_rank_prereqs_repository.h | 17 + .../base/base_aa_ranks_repository.h | 17 + .../base/base_account_flags_repository.h | 17 + .../base/base_account_ip_repository.h | 17 + .../base/base_account_repository.h | 17 + .../base/base_account_rewards_repository.h | 17 + .../base/base_adventure_details_repository.h | 17 + .../base/base_adventure_members_repository.h | 17 + .../base/base_adventure_stats_repository.h | 17 + ...venture_template_entry_flavor_repository.h | 17 + ...base_adventure_template_entry_repository.h | 17 + .../base/base_adventure_template_repository.h | 17 + .../base/base_alternate_currency_repository.h | 17 + .../repositories/base/base_auras_repository.h | 17 + .../base/base_base_data_repository.h | 17 + .../base/base_blocked_spells_repository.h | 17 + .../repositories/base/base_books_repository.h | 17 + .../base/base_bot_blocked_buffs_repository.h | 17 + .../base/base_bot_buffs_repository.h | 17 + .../base_bot_create_combinations_repository.h | 17 + .../base/base_bot_data_repository.h | 17 + .../base/base_bot_group_members_repository.h | 17 + .../base/base_bot_groups_repository.h | 17 + .../base/base_bot_guild_members_repository.h | 17 + ...ase_bot_heal_rotation_members_repository.h | 17 + ...ase_bot_heal_rotation_targets_repository.h | 17 + .../base/base_bot_heal_rotations_repository.h | 17 + .../base_bot_inspect_messages_repository.h | 17 + .../base/base_bot_inventories_repository.h | 17 + .../base/base_bot_owner_options_repository.h | 17 + .../base/base_bot_pet_buffs_repository.h | 17 + .../base_bot_pet_inventories_repository.h | 17 + .../base/base_bot_pets_repository.h | 17 + .../base/base_bot_settings_repository.h | 17 + ...ase_bot_spell_casting_chances_repository.h | 17 + .../base/base_bot_spell_settings_repository.h | 17 + .../base/base_bot_spells_entries_repository.h | 17 + .../base/base_bot_stances_repository.h | 17 + .../base/base_bot_starting_items_repository.h | 17 + .../base/base_bot_timers_repository.h | 17 + .../base/base_bug_reports_repository.h | 17 + .../repositories/base/base_bugs_repository.h | 17 + .../base/base_buyer_buy_lines_repository.h | 17 + .../repositories/base/base_buyer_repository.h | 17 + .../base/base_buyer_trade_items_repository.h | 17 + ...base_char_create_combinations_repository.h | 17 + ...char_create_point_allocations_repository.h | 17 + .../base/base_char_recipe_list_repository.h | 17 + .../base_character_activities_repository.h | 17 + .../base_character_alt_currency_repository.h | 17 + ...character_alternate_abilities_repository.h | 17 + .../base/base_character_auras_repository.h | 17 + .../base_character_bandolier_repository.h | 17 + .../base/base_character_bind_repository.h | 17 + .../base/base_character_buffs_repository.h | 17 + .../base_character_corpse_items_repository.h | 17 + .../base/base_character_corpses_repository.h | 17 + .../base/base_character_currency_repository.h | 17 + .../base/base_character_data_repository.h | 17 + .../base_character_disciplines_repository.h | 17 + ...base_character_evolving_items_repository.h | 17 + .../base_character_exp_modifiers_repository.h | 17 + ...character_expedition_lockouts_repository.h | 17 + ...se_character_inspect_messages_repository.h | 17 + ...haracter_instance_safereturns_repository.h | 17 + .../base_character_item_recast_repository.h | 17 + .../base_character_languages_repository.h | 17 + ...haracter_leadership_abilities_repository.h | 17 + .../base/base_character_material_repository.h | 17 + .../base_character_memmed_spells_repository.h | 17 + ..._character_parcels_containers_repository.h | 17 + .../base/base_character_parcels_repository.h | 17 + .../base_character_peqzone_flags_repository.h | 17 + .../base_character_pet_buffs_repository.h | 17 + .../base/base_character_pet_info_repository.h | 17 + .../base_character_pet_inventory_repository.h | 17 + .../base/base_character_pet_name_repository.h | 17 + .../base_character_potionbelt_repository.h | 17 + .../base/base_character_skills_repository.h | 17 + .../base/base_character_spells_repository.h | 17 + .../base_character_stats_record_repository.h | 17 + .../base_character_task_timers_repository.h | 17 + .../base/base_character_tasks_repository.h | 17 + .../base/base_character_tribute_repository.h | 17 + ...se_chatchannel_reserved_names_repository.h | 17 + .../base/base_chatchannels_repository.h | 17 + .../base_command_subsettings_repository.h | 17 + ...ed_shared_task_activity_state_repository.h | 17 + ...completed_shared_task_members_repository.h | 17 + .../base_completed_shared_tasks_repository.h | 17 + .../base/base_completed_tasks_repository.h | 17 + .../base/base_content_flags_repository.h | 17 + .../base/base_damageshieldtypes_repository.h | 17 + .../base/base_data_buckets_repository.h | 17 + .../base/base_db_str_repository.h | 17 + .../base/base_discord_webhooks_repository.h | 17 + .../base/base_discovered_items_repository.h | 17 + .../repositories/base/base_doors_repository.h | 17 + .../base_dynamic_zone_lockouts_repository.h | 17 + .../base_dynamic_zone_members_repository.h | 17 + .../base_dynamic_zone_templates_repository.h | 17 + .../base/base_dynamic_zones_repository.h | 17 + .../base_faction_association_repository.h | 17 + .../base/base_faction_base_data_repository.h | 17 + .../base/base_faction_list_mod_repository.h | 17 + .../base/base_faction_list_repository.h | 17 + .../base/base_faction_values_repository.h | 17 + .../base/base_fishing_repository.h | 17 + .../base/base_forage_repository.h | 17 + .../base/base_friends_repository.h | 17 + .../base/base_global_loot_repository.h | 17 + .../base/base_gm_ips_repository.h | 17 + .../base/base_graveyard_repository.h | 17 + .../base/base_grid_entries_repository.h | 17 + .../repositories/base/base_grid_repository.h | 17 + .../base/base_ground_spawns_repository.h | 17 + .../base/base_group_id_repository.h | 17 + .../base/base_group_leaders_repository.h | 17 + .../base/base_guild_bank_repository.h | 17 + .../base/base_guild_members_repository.h | 17 + .../base/base_guild_permissions_repository.h | 17 + .../base/base_guild_ranks_repository.h | 17 + .../base/base_guild_relations_repository.h | 17 + .../base/base_guild_tributes_repository.h | 17 + .../base/base_guilds_repository.h | 17 + .../base/base_horses_repository.h | 17 + .../base_instance_list_player_repository.h | 17 + .../base/base_instance_list_repository.h | 17 + .../base/base_inventory_repository.h | 17 + .../base_inventory_snapshots_repository.h | 17 + .../base/base_ip_exemptions_repository.h | 17 + .../base_items_evolving_details_repository.h | 17 + .../repositories/base/base_items_repository.h | 17 + .../base/base_keyring_repository.h | 17 + .../base/base_launcher_repository.h | 17 + .../base/base_ldon_trap_entries_repository.h | 17 + .../base_ldon_trap_templates_repository.h | 17 + .../base/base_level_exp_mods_repository.h | 17 + .../base/base_lfguild_repository.h | 17 + .../base/base_login_accounts_repository.h | 17 + .../base/base_login_api_tokens_repository.h | 17 + .../base_login_server_admins_repository.h | 17 + .../base_login_server_list_types_repository.h | 17 + .../base_login_world_servers_repository.h | 17 + .../base/base_logsys_categories_repository.h | 17 + .../base/base_lootdrop_entries_repository.h | 17 + .../base/base_lootdrop_repository.h | 17 + .../base/base_loottable_entries_repository.h | 17 + .../base/base_loottable_repository.h | 17 + .../repositories/base/base_mail_repository.h | 17 + .../base/base_merc_armorinfo_repository.h | 17 + .../base/base_merc_buffs_repository.h | 17 + .../base/base_merc_inventory_repository.h | 17 + .../base_merc_merchant_entries_repository.h | 17 + ...erc_merchant_template_entries_repository.h | 17 + .../base_merc_merchant_templates_repository.h | 17 + .../base/base_merc_name_types_repository.h | 17 + .../base/base_merc_npc_types_repository.h | 17 + .../base_merc_spell_list_entries_repository.h | 17 + .../base/base_merc_spell_lists_repository.h | 17 + .../base_merc_stance_entries_repository.h | 17 + .../base/base_merc_stats_repository.h | 17 + .../base/base_merc_subtypes_repository.h | 17 + .../base/base_merc_templates_repository.h | 17 + .../base/base_merc_types_repository.h | 17 + .../base/base_merc_weaponinfo_repository.h | 17 + .../base/base_merchantlist_repository.h | 17 + .../base/base_merchantlist_temp_repository.h | 17 + .../repositories/base/base_mercs_repository.h | 17 + .../base/base_name_filter_repository.h | 17 + .../base/base_npc_emotes_repository.h | 17 + .../base_npc_faction_entries_repository.h | 17 + .../base/base_npc_faction_repository.h | 17 + .../base_npc_scale_global_base_repository.h | 17 + ...se_npc_spells_effects_entries_repository.h | 17 + .../base/base_npc_spells_effects_repository.h | 17 + .../base/base_npc_spells_entries_repository.h | 17 + .../base/base_npc_spells_repository.h | 17 + .../base/base_npc_types_repository.h | 17 + .../base/base_npc_types_tint_repository.h | 17 + .../base/base_object_contents_repository.h | 17 + .../base/base_object_repository.h | 17 + ...se_perl_event_export_settings_repository.h | 17 + .../base/base_petitions_repository.h | 17 + .../base_pets_beastlord_data_repository.h | 17 + ...ase_pets_equipmentset_entries_repository.h | 17 + .../base/base_pets_equipmentset_repository.h | 17 + .../repositories/base/base_pets_repository.h | 17 + ...base_player_event_aa_purchase_repository.h | 17 + ...player_event_killed_named_npc_repository.h | 17 + .../base_player_event_killed_npc_repository.h | 17 + ..._player_event_killed_raid_npc_repository.h | 17 + ...ase_player_event_log_settings_repository.h | 17 + .../base/base_player_event_logs_repository.h | 17 + .../base_player_event_loot_items_repository.h | 17 + ...layer_event_merchant_purchase_repository.h | 17 + ...se_player_event_merchant_sell_repository.h | 17 + ...ayer_event_npc_handin_entries_repository.h | 17 + .../base_player_event_npc_handin_repository.h | 17 + .../base_player_event_speech_repository.h | 17 + ...se_player_event_trade_entries_repository.h | 17 + .../base/base_player_event_trade_repository.h | 17 + .../base/base_player_titlesets_repository.h | 17 + .../base/base_quest_globals_repository.h | 17 + .../base/base_raid_details_repository.h | 17 + .../base/base_raid_members_repository.h | 17 + .../base/base_reports_repository.h | 17 + .../base/base_respawn_times_repository.h | 17 + .../base/base_rule_sets_repository.h | 17 + .../base/base_rule_values_repository.h | 17 + .../base/base_saylink_repository.h | 17 + .../base_server_scheduled_events_repository.h | 17 + ...se_shared_task_activity_state_repository.h | 17 + ...ase_shared_task_dynamic_zones_repository.h | 17 + .../base_shared_task_members_repository.h | 17 + .../base/base_shared_tasks_repository.h | 17 + .../base/base_sharedbank_repository.h | 17 + .../base/base_skill_caps_repository.h | 17 + .../base/base_spawn2_disabled_repository.h | 17 + .../base/base_spawn2_repository.h | 17 + .../base_spawn_condition_values_repository.h | 17 + .../base/base_spawn_conditions_repository.h | 17 + .../base/base_spawn_events_repository.h | 17 + .../base/base_spawnentry_repository.h | 17 + .../base/base_spawngroup_repository.h | 17 + .../base/base_spell_buckets_repository.h | 17 + .../base/base_spell_globals_repository.h | 17 + .../base/base_spells_new_repository.h | 17 + .../base/base_start_zones_repository.h | 17 + .../base/base_starting_items_repository.h | 17 + .../base/base_task_activities_repository.h | 17 + .../repositories/base/base_tasks_repository.h | 17 + .../base/base_tasksets_repository.h | 17 + .../base/base_timers_repository.h | 17 + .../base/base_titles_repository.h | 17 + .../base/base_tool_game_objects_repository.h | 17 + .../base/base_trader_repository.h | 17 + ...ase_tradeskill_recipe_entries_repository.h | 17 + .../base/base_tradeskill_recipe_repository.h | 17 + .../repositories/base/base_traps_repository.h | 17 + .../base/base_tribute_levels_repository.h | 17 + .../base/base_tributes_repository.h | 17 + .../base/base_variables_repository.h | 17 + ...base_veteran_reward_templates_repository.h | 17 + .../base/base_zone_flags_repository.h | 17 + .../base/base_zone_points_repository.h | 17 + .../repositories/base/base_zone_repository.h | 17 + .../base/base_zone_state_spawns_repository.h | 17 + common/repositories/base_data_repository.h | 17 + .../repositories/blocked_spells_repository.h | 17 + common/repositories/books_repository.h | 17 + .../bot_blocked_buffs_repository.h | 17 + common/repositories/bot_buffs_repository.h | 17 + .../bot_create_combinations_repository.h | 17 + common/repositories/bot_data_repository.h | 17 + .../bot_group_members_repository.h | 17 + common/repositories/bot_groups_repository.h | 17 + .../bot_guild_members_repository.h | 17 + .../bot_heal_rotation_members_repository.h | 17 + .../bot_heal_rotation_targets_repository.h | 17 + .../bot_heal_rotations_repository.h | 17 + .../bot_inspect_messages_repository.h | 17 + .../repositories/bot_inventories_repository.h | 17 + .../bot_owner_options_repository.h | 17 + .../repositories/bot_pet_buffs_repository.h | 17 + .../bot_pet_inventories_repository.h | 17 + common/repositories/bot_pets_repository.h | 17 + common/repositories/bot_settings_repository.h | 17 + .../bot_spell_casting_chances_repository.h | 17 + .../bot_spell_settings_repository.h | 17 + .../bot_spells_entries_repository.h | 17 + common/repositories/bot_stances_repository.h | 17 + .../bot_starting_items_repository.h | 17 + common/repositories/bot_timers_repository.h | 17 + common/repositories/bug_reports_repository.h | 17 + common/repositories/bugs_repository.h | 17 + .../repositories/buyer_buy_lines_repository.h | 17 + common/repositories/buyer_repository.h | 17 + .../buyer_trade_items_repository.h | 17 + .../char_create_combinations_repository.h | 17 + ...char_create_point_allocations_repository.h | 17 + .../char_recipe_list_repository.h | 17 + .../character_activities_repository.h | 17 + .../character_alt_currency_repository.h | 17 + ...character_alternate_abilities_repository.h | 17 + .../repositories/character_auras_repository.h | 17 + .../character_bandolier_repository.h | 17 + .../repositories/character_bind_repository.h | 17 + .../repositories/character_buffs_repository.h | 17 + .../character_corpse_items_repository.h | 17 + .../character_corpses_repository.h | 17 + .../character_currency_repository.h | 17 + .../repositories/character_data_repository.h | 17 + .../character_disciplines_repository.h | 17 + .../character_evolving_items_repository.h | 17 + .../character_exp_modifiers_repository.h | 17 + ...character_expedition_lockouts_repository.h | 17 + .../character_inspect_messages_repository.h | 17 + ...haracter_instance_safereturns_repository.h | 17 + .../character_item_recast_repository.h | 17 + .../character_languages_repository.h | 17 + ...haracter_leadership_abilities_repository.h | 17 + .../character_material_repository.h | 17 + .../character_memmed_spells_repository.h | 17 + .../character_parcels_containers_repository.h | 17 + .../character_parcels_repository.h | 17 + .../character_peqzone_flags_repository.h | 17 + .../character_pet_buffs_repository.h | 17 + .../character_pet_info_repository.h | 17 + .../character_pet_inventory_repository.h | 17 + .../character_pet_name_repository.h | 17 + .../character_potionbelt_repository.h | 17 + .../character_skills_repository.h | 17 + .../character_spells_repository.h | 17 + .../character_stats_record_repository.h | 17 + .../character_task_timers_repository.h | 17 + .../repositories/character_tasks_repository.h | 17 + .../character_tribute_repository.h | 17 + .../chatchannel_reserved_names_repository.h | 17 + common/repositories/chatchannels_repository.h | 17 + .../command_subsettings_repository.h | 17 + ...ed_shared_task_activity_state_repository.h | 17 + ...completed_shared_task_members_repository.h | 17 + .../completed_shared_tasks_repository.h | 17 + .../repositories/completed_tasks_repository.h | 17 + .../repositories/content_flags_repository.h | 17 + .../criteria/content_filter_criteria.h | 17 + .../damageshieldtypes_repository.h | 17 + common/repositories/data_buckets_repository.h | 17 + common/repositories/db_str_repository.h | 17 + .../discord_webhooks_repository.h | 17 + .../discovered_items_repository.h | 17 + common/repositories/doors_repository.h | 17 + .../dynamic_zone_lockouts_repository.h | 17 + .../dynamic_zone_members_repository.h | 17 + .../dynamic_zone_templates_repository.h | 17 + .../repositories/dynamic_zones_repository.h | 17 + .../faction_association_repository.h | 17 + .../faction_base_data_repository.h | 17 + .../faction_list_mod_repository.h | 17 + common/repositories/faction_list_repository.h | 17 + .../repositories/faction_values_repository.h | 17 + common/repositories/fishing_repository.h | 17 + common/repositories/forage_repository.h | 17 + common/repositories/friends_repository.h | 17 + common/repositories/global_loot_repository.h | 17 + common/repositories/gm_ips_repository.h | 17 + common/repositories/graveyard_repository.h | 17 + common/repositories/grid_entries_repository.h | 17 + common/repositories/grid_repository.h | 17 + .../repositories/ground_spawns_repository.h | 17 + common/repositories/group_id_repository.h | 17 + .../repositories/group_leaders_repository.h | 17 + common/repositories/guild_bank_repository.h | 17 + .../repositories/guild_members_repository.h | 17 + .../guild_permissions_repository.h | 17 + common/repositories/guild_ranks_repository.h | 17 + .../repositories/guild_relations_repository.h | 17 + .../repositories/guild_tributes_repository.h | 17 + common/repositories/guilds_repository.h | 17 + common/repositories/horses_repository.h | 17 + .../instance_list_player_repository.h | 17 + .../repositories/instance_list_repository.h | 17 + common/repositories/inventory_repository.h | 17 + .../inventory_snapshots_repository.h | 17 + .../inventory_versions_repository.h | 17 + .../repositories/ip_exemptions_repository.h | 17 + .../items_evolving_details_repository.h | 17 + common/repositories/items_repository.h | 17 + common/repositories/keyring_repository.h | 17 + .../ldon_trap_entries_repository.h | 17 + .../ldon_trap_templates_repository.h | 17 + .../repositories/level_exp_mods_repository.h | 17 + common/repositories/lfguild_repository.h | 17 + .../repositories/login_accounts_repository.h | 17 + .../login_api_tokens_repository.h | 17 + .../login_server_admins_repository.h | 17 + .../login_server_list_types_repository.h | 17 + .../login_world_servers_repository.h | 17 + .../logsys_categories_repository.h | 17 + .../lootdrop_entries_repository.h | 17 + common/repositories/lootdrop_repository.h | 17 + .../loottable_entries_repository.h | 17 + common/repositories/loottable_repository.h | 17 + common/repositories/mail_repository.h | 17 + .../repositories/merc_armorinfo_repository.h | 17 + common/repositories/merc_buffs_repository.h | 17 + .../repositories/merc_inventory_repository.h | 17 + .../merc_merchant_entries_repository.h | 17 + ...erc_merchant_template_entries_repository.h | 17 + .../merc_merchant_templates_repository.h | 17 + .../repositories/merc_name_types_repository.h | 17 + .../repositories/merc_npc_types_repository.h | 17 + .../merc_spell_list_entries_repository.h | 17 + .../merc_spell_lists_repository.h | 17 + .../merc_stance_entries_repository.h | 17 + common/repositories/merc_stats_repository.h | 17 + .../repositories/merc_subtypes_repository.h | 17 + .../repositories/merc_templates_repository.h | 17 + common/repositories/merc_types_repository.h | 17 + .../repositories/merc_weaponinfo_repository.h | 17 + common/repositories/merchantlist_repository.h | 17 + .../merchantlist_temp_repository.h | 17 + common/repositories/mercs_repository.h | 17 + common/repositories/name_filter_repository.h | 17 + common/repositories/npc_emotes_repository.h | 17 + .../npc_faction_entries_repository.h | 17 + common/repositories/npc_faction_repository.h | 17 + .../npc_scale_global_base_repository.h | 17 + .../npc_spells_effects_entries_repository.h | 17 + .../npc_spells_effects_repository.h | 17 + .../npc_spells_entries_repository.h | 17 + common/repositories/npc_spells_repository.h | 17 + common/repositories/npc_types_repository.h | 17 + .../repositories/npc_types_tint_repository.h | 17 + .../repositories/object_contents_repository.h | 17 + common/repositories/object_repository.h | 17 + .../perl_event_export_settings_repository.h | 17 + common/repositories/petitions_repository.h | 17 + .../pets_beastlord_data_repository.h | 17 + .../pets_equipmentset_entries_repository.h | 17 + .../pets_equipmentset_repository.h | 17 + common/repositories/pets_repository.h | 17 + .../player_event_aa_purchase_repository.h | 17 + ...player_event_killed_named_npc_repository.h | 17 + .../player_event_killed_npc_repository.h | 17 + .../player_event_killed_raid_npc_repository.h | 17 + .../player_event_log_settings_repository.h | 17 + .../player_event_logs_repository.h | 17 + .../player_event_loot_items_repository.h | 17 + ...layer_event_merchant_purchase_repository.h | 17 + .../player_event_merchant_sell_repository.h | 17 + ...ayer_event_npc_handin_entries_repository.h | 17 + .../player_event_npc_handin_repository.h | 17 + .../player_event_speech_repository.h | 17 + .../player_event_trade_entries_repository.h | 17 + .../player_event_trade_repository.h | 17 + .../player_titlesets_repository.h | 17 + .../repositories/quest_globals_repository.h | 17 + common/repositories/raid_details_repository.h | 17 + common/repositories/raid_members_repository.h | 17 + common/repositories/reports_repository.h | 17 + .../repositories/respawn_times_repository.h | 17 + common/repositories/rule_sets_repository.h | 17 + common/repositories/rule_values_repository.h | 17 + common/repositories/saylink_repository.h | 17 + .../server_scheduled_events_repository.h | 17 + .../shared_task_activity_state_repository.h | 17 + .../shared_task_dynamic_zones_repository.h | 17 + .../shared_task_members_repository.h | 17 + common/repositories/shared_tasks_repository.h | 17 + common/repositories/sharedbank_repository.h | 17 + common/repositories/skill_caps_repository.h | 17 + .../repositories/spawn2_disabled_repository.h | 17 + common/repositories/spawn2_repository.h | 17 + .../spawn_condition_values_repository.h | 17 + .../spawn_conditions_repository.h | 17 + common/repositories/spawn_events_repository.h | 17 + common/repositories/spawnentry_repository.h | 17 + common/repositories/spawngroup_repository.h | 17 + .../repositories/spell_buckets_repository.h | 17 + .../repositories/spell_globals_repository.h | 17 + common/repositories/spells_new_repository.h | 17 + common/repositories/start_zones_repository.h | 17 + .../repositories/starting_items_repository.h | 17 + .../repositories/task_activities_repository.h | 17 + common/repositories/tasks_repository.h | 17 + common/repositories/tasksets_repository.h | 17 + common/repositories/timers_repository.h | 17 + common/repositories/titles_repository.h | 17 + .../tool_game_objects_repository.h | 17 + common/repositories/trader_audit_repository.h | 17 + common/repositories/trader_repository.h | 17 + .../tradeskill_recipe_entries_repository.h | 17 + .../tradeskill_recipe_repository.h | 17 + common/repositories/traps_repository.h | 17 + .../repositories/tribute_levels_repository.h | 17 + common/repositories/tributes_repository.h | 17 + common/repositories/variables_repository.h | 17 + .../veteran_reward_templates_repository.h | 17 + common/repositories/zone_flags_repository.h | 17 + common/repositories/zone_points_repository.h | 17 + common/repositories/zone_repository.h | 17 + .../zone_state_spawns_repository.h | 17 + common/rulesys.cpp | 19 +- common/rulesys.h | 19 +- common/ruletypes.h | 19 +- common/say_link.cpp | 18 +- common/say_link.h | 18 +- common/seperator.h | 18 +- common/serialize_buffer.cpp | 17 + common/serialize_buffer.h | 17 + common/server_event_scheduler.cpp | 17 + common/server_event_scheduler.h | 17 + common/server_reload_types.h | 17 + common/serverinfo.cpp | 19 +- common/serverinfo.h | 18 +- common/servertalk.h | 17 + common/shared_tasks.cpp | 17 + common/shared_tasks.h | 17 + common/shareddb.cpp | 19 +- common/shareddb.h | 35 +- common/skill_caps.cpp | 17 + common/skill_caps.h | 17 + common/skills.cpp | 18 +- common/skills.h | 18 +- common/spdat.cpp | 19 +- common/spdat.h | 19 +- common/spdat_bot.cpp | 17 + common/strings.cpp | 35 +- common/strings.h | 35 +- common/strings_legacy.cpp | 17 + common/strings_misc.cpp | 17 + common/struct_strategy.cpp | 17 + common/struct_strategy.h | 17 + common/tasks.h | 17 + common/termcolor/rang.hpp | 17 + common/textures.cpp | 18 +- common/textures.h | 20 +- common/timeoutmgr.cpp | 19 +- common/timeoutmgr.h | 19 +- common/timer.cpp | 19 +- common/timer.h | 19 +- common/types.h | 19 +- common/unix.cpp | 18 +- common/unix.h | 18 +- common/useperl.h | 17 + common/util/directory.cpp | 17 + common/util/directory.h | 17 + common/util/memory_stream.h | 17 + common/util/uuid.cpp | 17 + common/util/uuid.h | 17 + common/version.h | 35 +- common/zone_store.cpp | 37 +- common/zone_store.h | 35 +- eqlaunch/eqlaunch.cpp | 19 +- eqlaunch/worldserver.cpp | 33 +- eqlaunch/worldserver.h | 19 +- eqlaunch/zone_launch.cpp | 19 +- eqlaunch/zone_launch.h | 19 +- loginserver/account_management.cpp | 17 + loginserver/account_management.h | 17 + loginserver/client.cpp | 17 + loginserver/client.h | 17 + loginserver/client_manager.cpp | 17 + loginserver/client_manager.h | 17 + loginserver/encryption.cpp | 17 + loginserver/encryption.h | 17 + loginserver/eq_crypto_api.h | 17 + loginserver/login_server.h | 17 + loginserver/login_types.h | 17 + loginserver/loginserver_command_handler.cpp | 17 + loginserver/loginserver_command_handler.h | 17 + loginserver/loginserver_webserver.cpp | 17 + loginserver/loginserver_webserver.h | 17 + loginserver/main.cpp | 17 + loginserver/options.h | 17 + loginserver/world_server.cpp | 17 + loginserver/world_server.h | 17 + loginserver/world_server_manager.cpp | 17 + loginserver/world_server_manager.h | 17 + queryserv/database.cpp | 17 + queryserv/database.h | 17 + queryserv/lfguild.cpp | 17 + queryserv/lfguild.h | 17 + queryserv/queryserv.cpp | 17 + queryserv/queryservconfig.cpp | 20 +- queryserv/queryservconfig.h | 20 +- queryserv/worldserver.cpp | 17 + queryserv/worldserver.h | 19 +- queryserv/zonelist.cpp | 17 + queryserv/zonelist.h | 17 + queryserv/zoneserver.cpp | 17 + queryserv/zoneserver.h | 17 + shared_memory/items.cpp | 19 +- shared_memory/items.h | 19 +- shared_memory/main.cpp | 19 +- shared_memory/spells.cpp | 19 +- shared_memory/spells.h | 19 +- tests/atobool_test.h | 19 +- tests/data_verification_test.h | 19 +- tests/fixed_memory_test.h | 19 +- tests/fixed_memory_variable_test.h | 19 +- tests/hextoi_32_64_test.h | 19 +- tests/ipc_mutex_test.h | 19 +- tests/main.cpp | 19 +- tests/memory_mapped_file_test.h | 19 +- tests/skills_util_test.h | 19 +- tests/string_util_test.h | 19 +- tests/task_state_test.h | 17 + ucs/chatchannel.cpp | 20 +- ucs/chatchannel.h | 17 + ucs/clientlist.cpp | 26 +- ucs/clientlist.h | 20 +- ucs/database.cpp | 20 +- ucs/database.h | 20 +- ucs/ucs.cpp | 20 +- ucs/ucsconfig.cpp | 20 +- ucs/ucsconfig.h | 20 +- ucs/worldserver.cpp | 33 +- ucs/worldserver.h | 19 +- utils/TaskMaster/ErrorLog.cpp | 17 + utils/TaskMaster/ErrorLog.h | 17 + utils/TaskMaster/activities.cpp | 17 + utils/TaskMaster/base.cpp | 17 + utils/TaskMaster/base.h | 17 + utils/TaskMaster/base_utility.cpp | 17 + utils/TaskMaster/goals.cpp | 17 + utils/TaskMaster/items.h | 17 + utils/TaskMaster/proximity.cpp | 17 + utils/TaskMaster/tasks.cpp | 17 + utils/TaskMaster/tasks.h | 17 + utils/TaskMaster/utility.cpp | 17 + utils/TaskMaster/utility.h | 17 + world/adventure.cpp | 17 + world/adventure.h | 17 + world/adventure_manager.cpp | 17 + world/adventure_manager.h | 17 + world/adventure_template.h | 17 + world/cli/cli_bots_disable.cpp | 17 + world/cli/cli_bots_enable.cpp | 17 + world/cli/cli_copy_character.cpp | 17 + world/cli/cli_database_concurrency.cpp | 17 + world/cli/cli_database_dump.cpp | 17 + world/cli/cli_database_get_schema.cpp | 17 + world/cli/cli_database_set_account_status.cpp | 17 + world/cli/cli_database_updates.cpp | 17 + world/cli/cli_database_version.cpp | 17 + world/cli/cli_etl_get_settings.cpp | 17 + world/cli/cli_mercs_disable.cpp | 17 + world/cli/cli_mercs_enable.cpp | 17 + world/cli/cli_test.cpp | 17 + world/cli/cli_test_colors.cpp | 17 + world/cli/cli_test_expansion.cpp | 17 + world/cli/cli_test_repository.cpp | 17 + world/cli/cli_test_repository_2.cpp | 17 + world/cli/cli_test_string_benchmark.cpp | 17 + world/cli/cli_version.cpp | 17 + world/client.cpp | 19 +- world/client.h | 18 +- world/cliententry.cpp | 17 + world/cliententry.h | 17 + world/clientlist.cpp | 19 +- world/clientlist.h | 17 + world/console.cpp | 35 +- world/console.h | 17 + world/dynamic_zone.cpp | 17 + world/dynamic_zone.h | 17 + world/dynamic_zone_manager.cpp | 17 + world/dynamic_zone_manager.h | 17 + world/eqemu_api_world_data_service.cpp | 17 + world/eqemu_api_world_data_service.h | 35 +- world/eql_config.cpp | 19 +- world/eql_config.h | 19 +- world/launcher_link.cpp | 33 +- world/launcher_link.h | 19 +- world/launcher_list.cpp | 33 +- world/launcher_list.h | 19 +- world/lfplist.cpp | 19 +- world/lfplist.h | 19 +- world/login_server.cpp | 17 + world/login_server.h | 17 + world/login_server_list.cpp | 33 +- world/login_server_list.h | 17 + world/main.cpp | 35 +- world/queryserv.cpp | 17 + world/queryserv.h | 17 + world/shared_task_manager.cpp | 17 + world/shared_task_manager.h | 17 + world/shared_task_world_messaging.cpp | 17 + world/shared_task_world_messaging.h | 17 + world/sof_char_create_data.h | 17 + world/ucs.cpp | 17 + world/ucs.h | 17 + world/web_interface.cpp | 17 + world/web_interface.h | 17 + world/web_interface_eqw.cpp | 17 + world/web_interface_eqw.h | 17 + world/wguild_mgr.cpp | 19 +- world/wguild_mgr.h | 17 + world/world_boot.cpp | 17 + world/world_boot.h | 17 + world/world_config.cpp | 19 +- world/world_config.h | 19 +- world/world_console_connection.cpp | 17 + world/world_console_connection.h | 19 +- world/world_event_scheduler.cpp | 17 + world/world_event_scheduler.h | 17 + world/world_server_cli.cpp | 17 + world/world_server_cli.h | 17 + world/world_tcp_connection.h | 19 +- world/worlddb.cpp | 19 +- world/worlddb.h | 19 +- world/zonelist.cpp | 33 +- world/zonelist.h | 17 + world/zoneserver.cpp | 26 +- world/zoneserver.h | 19 +- zone/aa.cpp | 19 +- zone/aa.h | 17 + zone/aa_ability.cpp | 19 +- zone/aa_ability.h | 19 +- zone/aa_rank.h | 19 +- zone/aa_rank_effects.h | 19 +- zone/aggro.cpp | 19 +- zone/aggromanager.cpp | 17 + zone/aggromanager.h | 17 + zone/api_service.cpp | 35 +- zone/api_service.h | 35 +- zone/attack.cpp | 33 +- zone/aura.cpp | 17 + zone/aura.h | 17 + zone/beacon.cpp | 19 +- zone/beacon.h | 19 +- zone/bonuses.cpp | 19 +- zone/bot.cpp | 19 +- zone/bot.h | 19 +- zone/bot_command.cpp | 19 +- zone/bot_command.h | 19 +- zone/bot_commands/bot_actionable.cpp | 17 + zone/bot_commands/bot_appearance.cpp | 17 + zone/bot_commands/bot_apply_poison.cpp | 17 + zone/bot_commands/bot_apply_potion.cpp | 17 + zone/bot_commands/bot_attack.cpp | 17 + zone/bot_commands/bot_behind_mob.cpp | 17 + zone/bot_commands/bot_blocked_buffs.cpp | 17 + zone/bot_commands/bot_bot.cpp | 17 + zone/bot_commands/bot_bot_settings.cpp | 17 + zone/bot_commands/bot_cast.cpp | 17 + zone/bot_commands/bot_class_race_list.cpp | 17 + zone/bot_commands/bot_click_item.cpp | 17 + zone/bot_commands/bot_copy_settings.cpp | 17 + zone/bot_commands/bot_default_settings.cpp | 17 + zone/bot_commands/bot_depart.cpp | 17 + zone/bot_commands/bot_discipline.cpp | 17 + zone/bot_commands/bot_distance_ranged.cpp | 17 + zone/bot_commands/bot_find_aliases.cpp | 17 + zone/bot_commands/bot_follow.cpp | 17 + zone/bot_commands/bot_guard.cpp | 17 + zone/bot_commands/bot_heal_rotation.cpp | 17 + zone/bot_commands/bot_help.cpp | 17 + zone/bot_commands/bot_hold.cpp | 17 + zone/bot_commands/bot_illusion_block.cpp | 17 + zone/bot_commands/bot_inventory.cpp | 17 + zone/bot_commands/bot_item_use.cpp | 17 + zone/bot_commands/bot_max_melee_range.cpp | 17 + zone/bot_commands/bot_name.cpp | 17 + zone/bot_commands/bot_owner_option.cpp | 17 + zone/bot_commands/bot_pet.cpp | 17 + zone/bot_commands/bot_pick_lock.cpp | 17 + zone/bot_commands/bot_pickpocket.cpp | 17 + zone/bot_commands/bot_precombat.cpp | 17 + zone/bot_commands/bot_pull.cpp | 17 + zone/bot_commands/bot_release.cpp | 17 + zone/bot_commands/bot_set_assistee.cpp | 17 + zone/bot_commands/bot_sit_hp_percent.cpp | 17 + zone/bot_commands/bot_sit_in_combat.cpp | 17 + zone/bot_commands/bot_sit_mana_percent.cpp | 17 + zone/bot_commands/bot_spell.cpp | 17 + zone/bot_commands/bot_spell_aggro_checks.cpp | 17 + zone/bot_commands/bot_spell_announce_cast.cpp | 17 + zone/bot_commands/bot_spell_delays.cpp | 17 + .../bot_spell_engaged_priority.cpp | 17 + zone/bot_commands/bot_spell_holds.cpp | 17 + zone/bot_commands/bot_spell_idle_priority.cpp | 17 + zone/bot_commands/bot_spell_max_hp_pct.cpp | 17 + zone/bot_commands/bot_spell_max_mana_pct.cpp | 17 + .../bot_commands/bot_spell_max_thresholds.cpp | 17 + zone/bot_commands/bot_spell_min_hp_pct.cpp | 17 + zone/bot_commands/bot_spell_min_mana_pct.cpp | 17 + .../bot_commands/bot_spell_min_thresholds.cpp | 17 + .../bot_spell_pursue_priority.cpp | 17 + zone/bot_commands/bot_spell_resist_limits.cpp | 17 + zone/bot_commands/bot_spell_target_count.cpp | 17 + zone/bot_commands/bot_spelltypes.cpp | 17 + zone/bot_commands/bot_suspend.cpp | 17 + zone/bot_commands/bot_taunt.cpp | 17 + zone/bot_commands/bot_timer.cpp | 17 + zone/bot_commands/bot_track.cpp | 17 + zone/bot_commands/bot_view_combos.cpp | 17 + zone/bot_database.cpp | 19 +- zone/bot_database.h | 19 +- zone/bot_raid.cpp | 19 +- zone/bot_raid.h | 19 +- zone/bot_structs.h | 19 +- zone/botspellsai.cpp | 19 +- zone/cheat_manager.cpp | 17 + zone/cheat_manager.h | 17 + zone/cli/cli_benchmark_databuckets.cpp | 17 + zone/cli/cli_sidecar_serve_http.cpp | 17 + zone/cli/tests/cli_databuckets.cpp | 17 + zone/cli/tests/cli_npc_handins.cpp | 17 + zone/cli/tests/cli_npc_handins_multiquest.cpp | 17 + zone/cli/tests/cli_test_util.cpp | 17 + zone/cli/tests/cli_zone_state.cpp | 17 + zone/client.cpp | 19 +- zone/client.h | 19 +- zone/client_bot.cpp | 17 + zone/client_evolving_items.cpp | 17 + zone/client_mods.cpp | 19 +- zone/client_packet.cpp | 32 +- zone/client_packet.h | 17 + zone/client_process.cpp | 20 +- zone/combat_record.cpp | 17 + zone/combat_record.h | 17 + zone/command.cpp | 17 + zone/command.h | 17 + zone/common.h | 17 + zone/corpse.cpp | 17 + zone/corpse.h | 17 + zone/dialogue_window.cpp | 17 + zone/dialogue_window.h | 17 + zone/doors.cpp | 19 +- zone/doors.h | 17 + zone/dynamic_zone.cpp | 35 +- zone/dynamic_zone.h | 35 +- zone/effects.cpp | 19 +- zone/embparser.cpp | 19 +- zone/embparser.h | 19 +- zone/embparser_api.cpp | 19 +- zone/embperl.cpp | 17 + zone/embperl.h | 17 + zone/encounter.cpp | 27 +- zone/encounter.h | 33 +- zone/entity.cpp | 19 +- zone/entity.h | 19 +- zone/event_codes.h | 17 + zone/exp.cpp | 19 +- zone/expedition_request.cpp | 35 +- zone/expedition_request.h | 35 +- zone/fastmath.cpp | 17 + zone/fastmath.h | 17 + zone/fearpath.cpp | 19 +- zone/forage.cpp | 19 +- zone/forage.h | 19 +- zone/global_loot_manager.cpp | 17 + zone/global_loot_manager.h | 17 + zone/gm_commands/acceptrules.cpp | 17 + zone/gm_commands/advnpcspawn.cpp | 17 + zone/gm_commands/aggrozone.cpp | 17 + zone/gm_commands/ai.cpp | 17 + zone/gm_commands/appearance.cpp | 17 + zone/gm_commands/appearanceeffects.cpp | 17 + zone/gm_commands/attack.cpp | 17 + zone/gm_commands/augmentitem.cpp | 17 + zone/gm_commands/ban.cpp | 17 + zone/gm_commands/bugs.cpp | 17 + zone/gm_commands/camerashake.cpp | 17 + zone/gm_commands/castspell.cpp | 17 + zone/gm_commands/chat.cpp | 17 + zone/gm_commands/clearxtargets.cpp | 17 + zone/gm_commands/copycharacter.cpp | 17 + zone/gm_commands/corpse.cpp | 17 + zone/gm_commands/corpsefix.cpp | 17 + zone/gm_commands/countitem.cpp | 17 + zone/gm_commands/damage.cpp | 17 + zone/gm_commands/databuckets.cpp | 17 + zone/gm_commands/dbspawn2.cpp | 17 + zone/gm_commands/delacct.cpp | 17 + zone/gm_commands/delpetition.cpp | 17 + zone/gm_commands/depop.cpp | 17 + zone/gm_commands/depopzone.cpp | 17 + zone/gm_commands/devtools.cpp | 17 + zone/gm_commands/disablerecipe.cpp | 17 + zone/gm_commands/disarmtrap.cpp | 17 + zone/gm_commands/doanim.cpp | 17 + zone/gm_commands/door.cpp | 17 + zone/gm_commands/door_manipulation.cpp | 17 + zone/gm_commands/door_manipulation.h | 17 + zone/gm_commands/dye.cpp | 17 + zone/gm_commands/dz.cpp | 17 + zone/gm_commands/dzkickplayers.cpp | 17 + zone/gm_commands/editmassrespawn.cpp | 17 + zone/gm_commands/emote.cpp | 17 + zone/gm_commands/emptyinventory.cpp | 17 + zone/gm_commands/enablerecipe.cpp | 17 + zone/gm_commands/entityvariable.cpp | 17 + zone/gm_commands/evolving_items.cpp | 17 + zone/gm_commands/exptoggle.cpp | 17 + zone/gm_commands/faction.cpp | 17 + zone/gm_commands/faction_association.cpp | 17 + zone/gm_commands/feature.cpp | 17 + zone/gm_commands/find.cpp | 17 + zone/gm_commands/find/find_aa.cpp | 17 + zone/gm_commands/find/find_account.cpp | 17 + zone/gm_commands/find/find_body_type.cpp | 17 + zone/gm_commands/find/find_bot.cpp | 17 + zone/gm_commands/find/find_bug_category.cpp | 17 + zone/gm_commands/find/find_character.cpp | 17 + zone/gm_commands/find/find_class.cpp | 17 + .../gm_commands/find/find_comparison_type.cpp | 17 + zone/gm_commands/find/find_currency.cpp | 17 + zone/gm_commands/find/find_deity.cpp | 17 + zone/gm_commands/find/find_emote.cpp | 17 + zone/gm_commands/find/find_faction.cpp | 17 + zone/gm_commands/find/find_item.cpp | 17 + zone/gm_commands/find/find_language.cpp | 17 + zone/gm_commands/find/find_ldon_theme.cpp | 17 + zone/gm_commands/find/find_npctype.cpp | 17 + zone/gm_commands/find/find_object_type.cpp | 17 + zone/gm_commands/find/find_race.cpp | 17 + zone/gm_commands/find/find_recipe.cpp | 17 + zone/gm_commands/find/find_skill.cpp | 17 + .../gm_commands/find/find_special_ability.cpp | 17 + zone/gm_commands/find/find_spell.cpp | 17 + zone/gm_commands/find/find_stance.cpp | 17 + zone/gm_commands/find/find_task.cpp | 17 + zone/gm_commands/find/find_zone.cpp | 17 + zone/gm_commands/fish.cpp | 17 + zone/gm_commands/fixmob.cpp | 17 + zone/gm_commands/flagedit.cpp | 17 + zone/gm_commands/fleeinfo.cpp | 17 + zone/gm_commands/forage.cpp | 17 + zone/gm_commands/gearup.cpp | 17 + zone/gm_commands/giveitem.cpp | 17 + zone/gm_commands/givemoney.cpp | 17 + zone/gm_commands/gmzone.cpp | 17 + zone/gm_commands/goto.cpp | 17 + zone/gm_commands/grantaa.cpp | 17 + zone/gm_commands/grid.cpp | 17 + zone/gm_commands/guild.cpp | 17 + zone/gm_commands/hp.cpp | 17 + zone/gm_commands/illusion_block.cpp | 17 + zone/gm_commands/instance.cpp | 17 + zone/gm_commands/interrogateinv.cpp | 17 + zone/gm_commands/interrupt.cpp | 17 + zone/gm_commands/invsnapshot.cpp | 17 + zone/gm_commands/ipban.cpp | 17 + zone/gm_commands/kick.cpp | 17 + zone/gm_commands/kill.cpp | 17 + zone/gm_commands/killallnpcs.cpp | 17 + zone/gm_commands/list.cpp | 17 + zone/gm_commands/loc.cpp | 17 + zone/gm_commands/logs.cpp | 17 + zone/gm_commands/lootsim.cpp | 17 + zone/gm_commands/makepet.cpp | 17 + zone/gm_commands/memspell.cpp | 17 + zone/gm_commands/merchantshop.cpp | 17 + zone/gm_commands/modifynpcstat.cpp | 17 + zone/gm_commands/movechar.cpp | 17 + zone/gm_commands/movement.cpp | 17 + zone/gm_commands/myskills.cpp | 17 + zone/gm_commands/mysql.cpp | 17 + zone/gm_commands/mystats.cpp | 17 + zone/gm_commands/npccast.cpp | 17 + zone/gm_commands/npcedit.cpp | 17 + zone/gm_commands/npceditmass.cpp | 17 + zone/gm_commands/npcemote.cpp | 17 + zone/gm_commands/npcloot.cpp | 17 + zone/gm_commands/npcsay.cpp | 17 + zone/gm_commands/npcshout.cpp | 17 + zone/gm_commands/npcspawn.cpp | 17 + zone/gm_commands/npctypespawn.cpp | 17 + zone/gm_commands/nudge.cpp | 17 + zone/gm_commands/nukebuffs.cpp | 17 + zone/gm_commands/nukeitem.cpp | 17 + zone/gm_commands/object.cpp | 17 + zone/gm_commands/object_manipulation.cpp | 17 + zone/gm_commands/object_manipulation.h | 17 + zone/gm_commands/parcels.cpp | 17 + zone/gm_commands/path.cpp | 17 + zone/gm_commands/peqzone.cpp | 17 + zone/gm_commands/petitems.cpp | 17 + zone/gm_commands/petname.cpp | 17 + zone/gm_commands/picklock.cpp | 17 + zone/gm_commands/profanity.cpp | 17 + zone/gm_commands/push.cpp | 17 + zone/gm_commands/raidloot.cpp | 17 + zone/gm_commands/randomfeatures.cpp | 17 + zone/gm_commands/refreshgroup.cpp | 17 + zone/gm_commands/reload.cpp | 17 + zone/gm_commands/removeitem.cpp | 17 + zone/gm_commands/repop.cpp | 17 + zone/gm_commands/resetaa.cpp | 17 + zone/gm_commands/resetaa_timer.cpp | 17 + zone/gm_commands/resetdisc_timer.cpp | 17 + zone/gm_commands/revoke.cpp | 17 + zone/gm_commands/roambox.cpp | 17 + zone/gm_commands/rules.cpp | 17 + zone/gm_commands/save.cpp | 17 + zone/gm_commands/scale.cpp | 17 + zone/gm_commands/scribespell.cpp | 17 + zone/gm_commands/scribespells.cpp | 17 + zone/gm_commands/sendzonespawns.cpp | 17 + zone/gm_commands/sensetrap.cpp | 17 + zone/gm_commands/serverrules.cpp | 17 + zone/gm_commands/set.cpp | 17 + zone/gm_commands/set/set_aa_exp.cpp | 17 + zone/gm_commands/set/set_aa_points.cpp | 17 + zone/gm_commands/set/set_adventure_points.cpp | 17 + .../set/set_alternate_currency.cpp | 17 + zone/gm_commands/set/set_animation.cpp | 17 + zone/gm_commands/set/set_anon.cpp | 17 + zone/gm_commands/set/set_auto_login.cpp | 17 + zone/gm_commands/set/set_bind_point.cpp | 17 + zone/gm_commands/set/set_checksum.cpp | 17 + zone/gm_commands/set/set_class_permanent.cpp | 17 + zone/gm_commands/set/set_crystals.cpp | 17 + zone/gm_commands/set/set_date.cpp | 17 + zone/gm_commands/set/set_endurance.cpp | 17 + zone/gm_commands/set/set_endurance_full.cpp | 17 + zone/gm_commands/set/set_exp.cpp | 17 + zone/gm_commands/set/set_flymode.cpp | 17 + zone/gm_commands/set/set_frozen.cpp | 17 + zone/gm_commands/set/set_gender.cpp | 17 + zone/gm_commands/set/set_gender_permanent.cpp | 17 + zone/gm_commands/set/set_gm.cpp | 17 + zone/gm_commands/set/set_gm_speed.cpp | 17 + zone/gm_commands/set/set_gm_status.cpp | 17 + zone/gm_commands/set/set_god_mode.cpp | 17 + zone/gm_commands/set/set_haste.cpp | 17 + zone/gm_commands/set/set_hero_model.cpp | 17 + zone/gm_commands/set/set_hide_me.cpp | 17 + zone/gm_commands/set/set_hp.cpp | 17 + zone/gm_commands/set/set_hp_full.cpp | 17 + zone/gm_commands/set/set_invulnerable.cpp | 17 + zone/gm_commands/set/set_language.cpp | 17 + zone/gm_commands/set/set_last_name.cpp | 17 + zone/gm_commands/set/set_level.cpp | 17 + zone/gm_commands/set/set_loginserver_info.cpp | 17 + zone/gm_commands/set/set_mana.cpp | 17 + zone/gm_commands/set/set_mana_full.cpp | 17 + zone/gm_commands/set/set_motd.cpp | 17 + zone/gm_commands/set/set_name.cpp | 17 + zone/gm_commands/set/set_ooc_mute.cpp | 17 + zone/gm_commands/set/set_password.cpp | 17 + zone/gm_commands/set/set_pvp.cpp | 17 + zone/gm_commands/set/set_pvp_points.cpp | 17 + zone/gm_commands/set/set_race.cpp | 17 + zone/gm_commands/set/set_race_permanent.cpp | 17 + zone/gm_commands/set/set_server_locked.cpp | 17 + zone/gm_commands/set/set_skill.cpp | 17 + zone/gm_commands/set/set_skill_all.cpp | 17 + zone/gm_commands/set/set_skill_all_max.cpp | 17 + zone/gm_commands/set/set_start_zone.cpp | 17 + zone/gm_commands/set/set_temporary_name.cpp | 17 + zone/gm_commands/set/set_texture.cpp | 17 + zone/gm_commands/set/set_time.cpp | 17 + zone/gm_commands/set/set_time_zone.cpp | 17 + zone/gm_commands/set/set_title.cpp | 17 + zone/gm_commands/set/set_title_suffix.cpp | 17 + zone/gm_commands/set/set_weather.cpp | 17 + zone/gm_commands/set/set_zone.cpp | 17 + zone/gm_commands/show.cpp | 17 + zone/gm_commands/show/show_aa_points.cpp | 17 + zone/gm_commands/show/show_aas.cpp | 17 + zone/gm_commands/show/show_aggro.cpp | 17 + zone/gm_commands/show/show_auto_login.cpp | 17 + zone/gm_commands/show/show_buffs.cpp | 17 + .../show/show_buried_corpse_count.cpp | 17 + .../show/show_client_version_summary.cpp | 17 + zone/gm_commands/show/show_content_flags.cpp | 17 + zone/gm_commands/show/show_currencies.cpp | 17 + zone/gm_commands/show/show_distance.cpp | 17 + zone/gm_commands/show/show_emotes.cpp | 17 + zone/gm_commands/show/show_field_of_view.cpp | 17 + zone/gm_commands/show/show_flags.cpp | 17 + zone/gm_commands/show/show_group_info.cpp | 17 + zone/gm_commands/show/show_hatelist.cpp | 17 + zone/gm_commands/show/show_inventory.cpp | 17 + zone/gm_commands/show/show_ip_lookup.cpp | 17 + zone/gm_commands/show/show_keyring.cpp | 17 + zone/gm_commands/show/show_line_of_sight.cpp | 17 + zone/gm_commands/show/show_network.cpp | 17 + zone/gm_commands/show/show_network_stats.cpp | 17 + .../gm_commands/show/show_npc_global_loot.cpp | 17 + zone/gm_commands/show/show_npc_stats.cpp | 17 + zone/gm_commands/show/show_npc_type.cpp | 17 + zone/gm_commands/show/show_peqzone_flags.cpp | 17 + zone/gm_commands/show/show_petition.cpp | 17 + zone/gm_commands/show/show_petition_info.cpp | 17 + zone/gm_commands/show/show_proximity.cpp | 17 + zone/gm_commands/show/show_quest_errors.cpp | 17 + zone/gm_commands/show/show_quest_globals.cpp | 17 + zone/gm_commands/show/show_recipe.cpp | 17 + zone/gm_commands/show/show_server_info.cpp | 17 + zone/gm_commands/show/show_skills.cpp | 17 + zone/gm_commands/show/show_spawn_status.cpp | 17 + .../show/show_special_abilities.cpp | 17 + zone/gm_commands/show/show_spells.cpp | 17 + zone/gm_commands/show/show_spells_list.cpp | 17 + zone/gm_commands/show/show_stats.cpp | 17 + zone/gm_commands/show/show_timers.cpp | 17 + zone/gm_commands/show/show_traps.cpp | 17 + zone/gm_commands/show/show_uptime.cpp | 17 + zone/gm_commands/show/show_variable.cpp | 17 + zone/gm_commands/show/show_version.cpp | 17 + zone/gm_commands/show/show_waypoints.cpp | 17 + zone/gm_commands/show/show_who.cpp | 17 + zone/gm_commands/show/show_xtargets.cpp | 17 + zone/gm_commands/show/show_zone_data.cpp | 17 + .../show/show_zone_global_loot.cpp | 17 + zone/gm_commands/show/show_zone_loot.cpp | 17 + zone/gm_commands/show/show_zone_points.cpp | 17 + zone/gm_commands/show/show_zone_status.cpp | 17 + zone/gm_commands/show/show_zone_variables.cpp | 17 + zone/gm_commands/shutdown.cpp | 17 + zone/gm_commands/spawn.cpp | 17 + zone/gm_commands/spawneditmass.cpp | 17 + zone/gm_commands/spawnfix.cpp | 17 + zone/gm_commands/stun.cpp | 17 + zone/gm_commands/summon.cpp | 17 + zone/gm_commands/summonburiedplayercorpse.cpp | 17 + zone/gm_commands/summonitem.cpp | 17 + zone/gm_commands/suspend.cpp | 17 + zone/gm_commands/suspendmulti.cpp | 17 + zone/gm_commands/takeplatinum.cpp | 17 + zone/gm_commands/task.cpp | 17 + zone/gm_commands/traindisc.cpp | 17 + zone/gm_commands/tune.cpp | 17 + zone/gm_commands/undye.cpp | 17 + zone/gm_commands/unmemspell.cpp | 17 + zone/gm_commands/unmemspells.cpp | 17 + zone/gm_commands/unscribespell.cpp | 17 + zone/gm_commands/unscribespells.cpp | 17 + zone/gm_commands/untraindisc.cpp | 17 + zone/gm_commands/untraindiscs.cpp | 17 + zone/gm_commands/wc.cpp | 17 + zone/gm_commands/worldshutdown.cpp | 17 + zone/gm_commands/worldwide.cpp | 17 + zone/gm_commands/wp.cpp | 17 + zone/gm_commands/wpadd.cpp | 17 + zone/gm_commands/zone.cpp | 17 + zone/gm_commands/zone_instance.cpp | 17 + zone/gm_commands/zone_shard.cpp | 17 + zone/gm_commands/zonebootup.cpp | 17 + zone/gm_commands/zoneshutdown.cpp | 17 + zone/gm_commands/zonevariable.cpp | 17 + zone/gm_commands/zsave.cpp | 17 + zone/groups.cpp | 19 +- zone/groups.h | 19 +- zone/guild.cpp | 19 +- zone/guild_mgr.cpp | 19 +- zone/guild_mgr.h | 17 + zone/hate_list.cpp | 33 +- zone/hate_list.h | 33 +- zone/heal_rotation.cpp | 19 +- zone/heal_rotation.h | 19 +- zone/horse.cpp | 19 +- zone/horse.h | 19 +- zone/inventory.cpp | 19 +- zone/loot.cpp | 17 + zone/lua_bit.h | 17 + zone/lua_bot.cpp | 17 + zone/lua_bot.h | 17 + zone/lua_buff.cpp | 17 + zone/lua_buff.h | 17 + zone/lua_client.cpp | 17 + zone/lua_client.h | 17 + zone/lua_corpse.cpp | 17 + zone/lua_corpse.h | 17 + zone/lua_database.cpp | 17 + zone/lua_database.h | 17 + zone/lua_door.cpp | 17 + zone/lua_door.h | 17 + zone/lua_encounter.cpp | 17 + zone/lua_encounter.h | 17 + zone/lua_entity.cpp | 17 + zone/lua_entity.h | 17 + zone/lua_entity_list.cpp | 17 + zone/lua_entity_list.h | 17 + zone/lua_expedition.cpp | 17 + zone/lua_expedition.h | 35 +- zone/lua_general.cpp | 17 + zone/lua_general.h | 17 + zone/lua_group.cpp | 17 + zone/lua_group.h | 17 + zone/lua_hate_list.cpp | 17 + zone/lua_hate_list.h | 17 + zone/lua_inventory.cpp | 17 + zone/lua_inventory.h | 17 + zone/lua_item.cpp | 17 + zone/lua_item.h | 17 + zone/lua_iteminst.cpp | 17 + zone/lua_iteminst.h | 17 + zone/lua_merc.cpp | 17 + zone/lua_merc.h | 17 + zone/lua_mob.cpp | 17 + zone/lua_mob.h | 17 + zone/lua_mod.cpp | 17 + zone/lua_mod.h | 17 + zone/lua_npc.cpp | 17 + zone/lua_npc.h | 17 + zone/lua_object.cpp | 17 + zone/lua_object.h | 17 + zone/lua_packet.cpp | 17 + zone/lua_packet.h | 17 + zone/lua_parser.cpp | 17 + zone/lua_parser.h | 17 + zone/lua_parser_events.cpp | 17 + zone/lua_parser_events.h | 17 + zone/lua_ptr.h | 17 + zone/lua_raid.cpp | 17 + zone/lua_raid.h | 17 + zone/lua_spawn.cpp | 17 + zone/lua_spawn.h | 17 + zone/lua_spell.cpp | 17 + zone/lua_spell.h | 17 + zone/lua_stat_bonuses.cpp | 17 + zone/lua_stat_bonuses.h | 17 + zone/lua_zone.cpp | 17 + zone/lua_zone.h | 17 + zone/main.cpp | 35 +- zone/map.cpp | 17 + zone/map.h | 20 +- zone/masterentity.h | 17 + zone/merc.cpp | 17 + zone/merc.h | 17 + zone/mob.cpp | 19 +- zone/mob.h | 18 +- zone/mob_ai.cpp | 19 +- zone/mob_appearance.cpp | 35 +- zone/mob_info.cpp | 35 +- zone/mob_movement_manager.cpp | 17 + zone/mob_movement_manager.h | 17 + zone/npc.cpp | 19 +- zone/npc.h | 19 +- zone/npc_scale_manager.cpp | 35 +- zone/npc_scale_manager.h | 35 +- zone/object.cpp | 19 +- zone/object.h | 19 +- zone/oriented_bounding_box.cpp | 17 + zone/oriented_bounding_box.h | 17 + zone/parcels.cpp | 19 +- zone/pathfinder_interface.cpp | 17 + zone/pathfinder_interface.h | 17 + zone/pathfinder_nav_mesh.cpp | 17 + zone/pathfinder_nav_mesh.h | 17 + zone/pathfinder_null.cpp | 17 + zone/pathfinder_null.h | 17 + zone/pathfinder_waypoint.cpp | 17 + zone/pathfinder_waypoint.h | 17 + zone/pathing.cpp | 17 + zone/pch/pch.h | 17 + zone/perl_bot.cpp | 17 + zone/perl_buff.cpp | 17 + zone/perl_client.cpp | 17 + zone/perl_database.cpp | 17 + zone/perl_database.h | 17 + zone/perl_doors.cpp | 17 + zone/perl_entity.cpp | 17 + zone/perl_expedition.cpp | 17 + zone/perl_groups.cpp | 17 + zone/perl_hateentry.cpp | 17 + zone/perl_inventory.cpp | 17 + zone/perl_merc.cpp | 17 + zone/perl_mob.cpp | 17 + zone/perl_npc.cpp | 17 + zone/perl_object.cpp | 17 + zone/perl_perlpacket.cpp | 17 + zone/perl_player_corpse.cpp | 17 + zone/perl_questitem.cpp | 17 + zone/perl_questitem_data.cpp | 17 + zone/perl_raids.cpp | 17 + zone/perl_spawn.cpp | 17 + zone/perl_spell.cpp | 17 + zone/perl_stat_bonuses.cpp | 17 + zone/perl_zone.cpp | 17 + zone/perlpacket.cpp | 19 +- zone/perlpacket.h | 19 +- zone/petitions.cpp | 19 +- zone/petitions.h | 19 +- zone/pets.cpp | 19 +- zone/pets.h | 17 + zone/position.cpp | 17 + zone/position.h | 19 +- zone/qglobals.cpp | 17 + zone/qglobals.h | 17 + zone/queryserv.cpp | 17 + zone/queryserv.h | 17 + zone/quest_db.cpp | 17 + zone/quest_db.h | 17 + zone/quest_interface.h | 19 +- zone/quest_parser_collection.cpp | 19 +- zone/quest_parser_collection.h | 19 +- zone/questmgr.cpp | 19 +- zone/questmgr.h | 27 +- zone/raids.cpp | 19 +- zone/raids.h | 19 +- zone/raycast_mesh.cpp | 17 + zone/raycast_mesh.h | 17 + zone/shared_task_zone_messaging.cpp | 17 + zone/shared_task_zone_messaging.h | 17 + .../sidecar_api/loot_simulator_controller.cpp | 17 + zone/sidecar_api/sidecar_api.cpp | 17 + zone/sidecar_api/sidecar_api.h | 17 + zone/spawn2.cpp | 19 +- zone/spawn2.h | 19 +- zone/spawngroup.cpp | 19 +- zone/spawngroup.h | 19 +- zone/special_attacks.cpp | 21 +- zone/spell_effects.cpp | 19 +- zone/spells.cpp | 19 +- zone/string_ids.h | 17 + zone/task_client_state.cpp | 17 + zone/task_client_state.h | 17 + zone/task_manager.cpp | 17 + zone/task_manager.h | 17 + zone/tasks.cpp | 17 + zone/tasks.h | 17 + zone/titles.cpp | 17 + zone/titles.h | 17 + zone/tradeskills.cpp | 19 +- zone/trading.cpp | 19 +- zone/trap.cpp | 19 +- zone/trap.h | 19 +- zone/tribute.cpp | 19 +- zone/tune.cpp | 19 +- zone/water_map.cpp | 17 + zone/water_map.h | 17 + zone/water_map_v1.cpp | 17 + zone/water_map_v1.h | 17 + zone/water_map_v2.cpp | 17 + zone/water_map_v2.h | 17 + zone/waypoints.cpp | 33 +- zone/worldserver.cpp | 33 +- zone/worldserver.h | 19 +- zone/xtargetautohaters.cpp | 17 + zone/xtargetautohaters.h | 17 + zone/zone.cpp | 19 +- zone/zone.h | 19 +- zone/zone_base_data.cpp | 17 + zone/zone_cli.cpp | 17 + zone/zone_cli.h | 17 + zone/zone_config.cpp | 19 +- zone/zone_config.h | 19 +- zone/zone_event_scheduler.cpp | 17 + zone/zone_event_scheduler.h | 17 + zone/zone_loot.cpp | 17 + zone/zone_npc_factions.cpp | 17 + zone/zone_reload.cpp | 35 +- zone/zone_reload.h | 35 +- zone/zone_save_state.cpp | 17 + zone/zone_save_state.h | 17 + zone/zonedb.cpp | 17 + zone/zonedb.h | 17 + zone/zonedump.h | 18 +- zone/zoning.cpp | 19 +- 1646 files changed, 26219 insertions(+), 4681 deletions(-) delete mode 100644 LICENSE create mode 100644 LICENSE.md diff --git a/LICENSE b/LICENSE deleted file mode 100644 index f288702d2f..0000000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; 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, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000000..04fb21e16f --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,675 @@ +# GNU GENERAL PUBLIC LICENSE + +Version 3, 29 June 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. + + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +## Preamble + +The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom +to share and change all versions of a program--to make sure it remains +free software for all its users. We, the Free Software Foundation, use +the GNU General Public License for most of our software; it applies +also to any other work released this way by its authors. You can apply +it to your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you +have certain responsibilities if you distribute copies of the +software, or if you modify it: responsibilities to respect the freedom +of others. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + +Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the +manufacturer can do so. This is fundamentally incompatible with the +aim of protecting users' freedom to change the software. The +systematic pattern of such abuse occurs in the area of products for +individuals to use, which is precisely where it is most unacceptable. +Therefore, we have designed this version of the GPL to prohibit the +practice for those products. If such problems arise substantially in +other domains, we stand ready to extend this provision to those +domains in future versions of the GPL, as needed to protect the +freedom of users. + +Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish +to avoid the special danger that patents applied to a free program +could make it effectively proprietary. To prevent this, the GPL +assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and +modification follow. + +## TERMS AND CONDITIONS + +### 0. Definitions. + +"This License" refers to version 3 of the GNU General Public License. + +"Copyright" also means copyright-like laws that apply to other kinds +of works, such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + +To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of +an exact copy. The resulting work is called a "modified version" of +the earlier work or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based +on the Program. + +To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user +through a computer network, with no transfer of a copy, is not +conveying. + +An interactive user interface displays "Appropriate Legal Notices" to +the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +### 1. Source Code. + +The "source code" for a work means the preferred form of the work for +making modifications to it. "Object code" means any non-source form of +a work. + +A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can +regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same +work. + +### 2. Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, +without conditions so long as your license otherwise remains in force. +You may convey covered works to others for the sole purpose of having +them make modifications exclusively for you, or provide you with +facilities for running those works, provided that you comply with the +terms of this License in conveying all material for which you do not +control copyright. Those thus making or running the covered works for +you must do so exclusively on your behalf, under your direction and +control, on terms that prohibit them from making any copies of your +copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the +conditions stated below. Sublicensing is not allowed; section 10 makes +it unnecessary. + +### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such +circumvention is effected by exercising rights under this License with +respect to the covered work, and you disclaim any intention to limit +operation or modification of the work as a means of enforcing, against +the work's users, your or third parties' legal rights to forbid +circumvention of technological measures. + +### 4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +### 5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these +conditions: + +- a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. +- b) The work must carry prominent notices stating that it is + released under this License and any conditions added under + section 7. This requirement modifies the requirement in section 4 + to "keep intact all notices". +- c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. +- d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +### 6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms of +sections 4 and 5, provided that you also convey the machine-readable +Corresponding Source under the terms of this License, in one of these +ways: + +- a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. +- b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the Corresponding + Source from a network server at no charge. +- c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. +- d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. +- e) Convey the object code using peer-to-peer transmission, + provided you inform other peers where the object code and + Corresponding Source of the work are being offered to the general + public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, +family, or household purposes, or (2) anything designed or sold for +incorporation into a dwelling. In determining whether a product is a +consumer product, doubtful cases shall be resolved in favor of +coverage. For a particular product received by a particular user, +"normally used" refers to a typical or common use of that class of +product, regardless of the status of the particular user or of the way +in which the particular user actually uses, or expects or is expected +to use, the product. A product is a consumer product regardless of +whether the product has substantial commercial, industrial or +non-consumer uses, unless such uses represent the only significant +mode of use of the product. + +"Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to +install and execute modified versions of a covered work in that User +Product from a modified version of its Corresponding Source. The +information must suffice to ensure that the continued functioning of +the modified object code is in no case prevented or interfered with +solely because modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or +updates for a work that has been modified or installed by the +recipient, or for the User Product in which it has been modified or +installed. Access to a network may be denied when the modification +itself materially and adversely affects the operation of the network +or violates the rules and protocols for communication across the +network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +### 7. Additional Terms. + +"Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders +of that material) supplement the terms of this License with terms: + +- a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or +- b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or +- c) Prohibiting misrepresentation of the origin of that material, + or requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or +- d) Limiting the use for publicity purposes of names of licensors + or authors of the material; or +- e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or +- f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions + of it) with contractual assumptions of liability to the recipient, + for any liability that these contractual assumptions directly + impose on those licensors and authors. + +All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; the +above requirements apply either way. + +### 8. Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +### 9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or run +a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +### 10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +### 11. Patents. + +A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims owned +or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is "discriminatory" if it does not include within the +scope of its coverage, prohibits the exercise of, or is conditioned on +the non-exercise of one or more of the rights that are specifically +granted under this License. You may not convey a covered work if you +are a party to an arrangement with a third party that is in the +business of distributing software, under which you make payment to the +third party based on the extent of your activity of conveying the +work, and under which the third party grants, to any of the parties +who would receive the covered work from you, a discriminatory patent +license (a) in connection with copies of the covered work conveyed by +you (or copies made from those copies), or (b) primarily for and in +connection with specific products or compilations that contain the +covered work, unless you entered into that arrangement, or that patent +license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +### 12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under +this License and any other pertinent obligations, then as a +consequence you may not convey it at all. For example, if you agree to +terms that obligate you to collect a royalty for further conveying +from those to whom you convey the Program, the only way you could +satisfy both those terms and this License would be to refrain entirely +from conveying the Program. + +### 13. Use with the GNU Affero General Public License. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +### 14. Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions +of the GNU General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in +detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies that a certain numbered version of the GNU General Public +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that numbered version or +of any later version published by the Free Software Foundation. If the +Program does not specify a version number of the GNU General Public +License, you may choose any version ever published by the Free +Software Foundation. + +If the Program specifies that a proxy can decide which future versions +of the GNU General Public License can be used, that proxy's public +statement of acceptance of a version permanently authorizes you to +choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +### 15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + +### 16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR +CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT +NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR +LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM +TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +### 17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS + +## How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + +To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively state +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . + +Also add information on how to contact you by electronic and paper +mail. + +If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, your +program's commands might be different; for a GUI interface, you would +use an "about box". + +You should also get your employer (if you work as a programmer) or +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. For more information on this, and how to apply and follow +the GNU GPL, see . + +The GNU General Public License does not permit incorporating your +program into proprietary programs. If your program is a subroutine +library, you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use the +GNU Lesser General Public License instead of this License. But first, +please read . diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index 333528b643..952ba9dd37 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/content/world_content_service.h" #include "common/crash.h" #include "common/eqemu_config.h" diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp index b09eba0642..eadb584718 100644 --- a/client_files/import/main.cpp +++ b/client_files/import/main.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/content/world_content_service.h" #include "common/crash.h" #include "common/eqemu_config.h" diff --git a/common/StackWalker/StackWalker.cpp b/common/StackWalker/StackWalker.cpp index d457a22313..5360a3efa1 100644 --- a/common/StackWalker/StackWalker.cpp +++ b/common/StackWalker/StackWalker.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /********************************************************************** * * StackWalker.cpp diff --git a/common/StackWalker/StackWalker.h b/common/StackWalker/StackWalker.h index ec233d9fa9..a53c673289 100644 --- a/common/StackWalker/StackWalker.h +++ b/common/StackWalker/StackWalker.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /********************************************************************** * * StackWalker.h diff --git a/common/additive_lagged_fibonacci_engine.h b/common/additive_lagged_fibonacci_engine.h index 0cd9c6a52f..0554c0d87c 100644 --- a/common/additive_lagged_fibonacci_engine.h +++ b/common/additive_lagged_fibonacci_engine.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2021 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include diff --git a/common/base_packet.cpp b/common/base_packet.cpp index 0fdfe22c12..b9f60f6a7b 100644 --- a/common/base_packet.cpp +++ b/common/base_packet.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/base_packet.h" #include "common/misc.h" #include "common/packet_dump.h" diff --git a/common/base_packet.h b/common/base_packet.h index 463bc2faf3..607e045760 100644 --- a/common/base_packet.h +++ b/common/base_packet.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/platform/inet.h" diff --git a/common/bazaar.cpp b/common/bazaar.cpp index 870d275a25..69841bfaa8 100644 --- a/common/bazaar.cpp +++ b/common/bazaar.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "bazaar.h" #include "common/item_instance.h" diff --git a/common/bazaar.h b/common/bazaar.h index aa7f24975e..2ea6fe1dbf 100644 --- a/common/bazaar.h +++ b/common/bazaar.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/item_instance.h" diff --git a/common/bodytypes.cpp b/common/bodytypes.cpp index 650f25f585..481b645276 100644 --- a/common/bodytypes.cpp +++ b/common/bodytypes.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "bodytypes.h" std::string BodyType::GetName(uint8 body_type_id) diff --git a/common/bodytypes.h b/common/bodytypes.h index 658cc063e3..24cbaaad3a 100644 --- a/common/bodytypes.h +++ b/common/bodytypes.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/classes.cpp b/common/classes.cpp index babd08d64b..bbe14f06c6 100644 --- a/common/classes.cpp +++ b/common/classes.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 - */ - + along with this program. If not, see . +*/ #include "classes.h" #include "common/data_verification.h" diff --git a/common/classes.h b/common/classes.h index fefae49409..5d6467fd5d 100644 --- a/common/classes.h +++ b/common/classes.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/rulesys.h" diff --git a/common/cli/argh.h b/common/cli/argh.h index 047fa190f9..255d1de81b 100644 --- a/common/cli/argh.h +++ b/common/cli/argh.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/cli/eqemu_command_handler.cpp b/common/cli/eqemu_command_handler.cpp index 75626670a9..2f150b621d 100644 --- a/common/cli/eqemu_command_handler.cpp +++ b/common/cli/eqemu_command_handler.cpp @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/cli/eqemu_command_handler.h" #include "common/cli/terminal_color.hpp" #include "common/platform.h" diff --git a/common/cli/eqemu_command_handler.h b/common/cli/eqemu_command_handler.h index 7ccd30dd93..c474ef608f 100644 --- a/common/cli/eqemu_command_handler.h +++ b/common/cli/eqemu_command_handler.h @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/cli/argh.h" diff --git a/common/cli/terminal_color.hpp b/common/cli/terminal_color.hpp index a98f2483b2..90bc570711 100644 --- a/common/cli/terminal_color.hpp +++ b/common/cli/terminal_color.hpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ //! //! termcolor //! ~~~~~~~~~ diff --git a/common/compression.cpp b/common/compression.cpp index 7b45874614..56e20caa2b 100644 --- a/common/compression.cpp +++ b/common/compression.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "compression.h" #include "common/types.h" diff --git a/common/compression.h b/common/compression.h index 0ef2b0e5fd..4309df681b 100644 --- a/common/compression.h +++ b/common/compression.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/common/condition.cpp b/common/condition.cpp index 334ce5d459..657bc610d4 100644 --- a/common/condition.cpp +++ b/common/condition.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "condition.h" #ifdef _WINDOWS diff --git a/common/condition.h b/common/condition.h index aba13eb12a..3f04015cb5 100644 --- a/common/condition.h +++ b/common/condition.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/mutex.h" diff --git a/common/content/world_content_service.cpp b/common/content/world_content_service.cpp index 994906dfc1..1b650b82d5 100644 --- a/common/content/world_content_service.cpp +++ b/common/content/world_content_service.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world_content_service.h" #include "common/database.h" diff --git a/common/content/world_content_service.h b/common/content/world_content_service.h index 5532d3f3b7..f3433307d6 100644 --- a/common/content/world_content_service.h +++ b/common/content/world_content_service.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once diff --git a/common/crash.cpp b/common/crash.cpp index fb8e5a865d..226f37bb4c 100644 --- a/common/crash.cpp +++ b/common/crash.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "crash.h" #include "common/eqemu_config.h" diff --git a/common/crash.h b/common/crash.h index 7da1b7a4ad..f99922b9a2 100644 --- a/common/crash.h +++ b/common/crash.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once void set_exception_handler(); diff --git a/common/crc16.cpp b/common/crc16.cpp index 38c8ac7ea8..3db217280a 100644 --- a/common/crc16.cpp +++ b/common/crc16.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "crc16.h" #include "common/crc32.h" diff --git a/common/crc16.h b/common/crc16.h index f9059b492c..11d51722c2 100644 --- a/common/crc16.h +++ b/common/crc16.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/common/crc32.cpp b/common/crc32.cpp index 4d7bf89edb..54e66dfe7b 100644 --- a/common/crc32.cpp +++ b/common/crc32.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "crc32.h" #include diff --git a/common/crc32.h b/common/crc32.h index 023d63359a..50dfe99013 100644 --- a/common/crc32.h +++ b/common/crc32.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/common/cron/croncpp.h b/common/cron/croncpp.h index 40c37863f0..c8fc2e10ba 100644 --- a/common/cron/croncpp.h +++ b/common/cron/croncpp.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/data_bucket.cpp b/common/data_bucket.cpp index e138320367..53174dff88 100644 --- a/common/data_bucket.cpp +++ b/common/data_bucket.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "data_bucket.h" #include "common/data_bucket.h" diff --git a/common/data_bucket.h b/common/data_bucket.h index 7625a545f8..46b616fc28 100644 --- a/common/data_bucket.h +++ b/common/data_bucket.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/json/json_archive_single_line.h" diff --git a/common/data_verification.h b/common/data_verification.h index 07a4b3bf05..f0fec3bb60 100644 --- a/common/data_verification.h +++ b/common/data_verification.h @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/database.cpp b/common/database.cpp index 7850dd8961..83ed14c903 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/data_verification.h" #include "common/database_schema.h" #include "common/database.h" diff --git a/common/database.h b/common/database.h index 580d58add6..fdb3154b2d 100644 --- a/common/database.h +++ b/common/database.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/dbcore.h" diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index ae66afff9b..418d317bbf 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -1,23 +1,20 @@ -/** - * 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 - * -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "database_dump_service.h" #include "common/database_schema.h" diff --git a/common/database/database_dump_service.h b/common/database/database_dump_service.h index 6169011a16..d7c9c17696 100644 --- a/common/database/database_dump_service.h +++ b/common/database/database_dump_service.h @@ -1,23 +1,20 @@ -/** - * 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 - * -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/database/database_update.cpp b/common/database/database_update.cpp index 493da59186..704426fee5 100644 --- a/common/database/database_update.cpp +++ b/common/database/database_update.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "database_update.h" #include "common/database.h" diff --git a/common/database/database_update.h b/common/database/database_update.h index 39084f4b50..90b3371d82 100644 --- a/common/database/database_update.h +++ b/common/database/database_update.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/database.h" diff --git a/common/database/database_update_manifest.h b/common/database/database_update_manifest.h index a32ec7db8e..e0a0281d75 100644 --- a/common/database/database_update_manifest.h +++ b/common/database/database_update_manifest.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/database/database_update.h" diff --git a/common/database/database_update_manifest_bots.h b/common/database/database_update_manifest_bots.h index b0dbb1fcb4..c73268a82b 100644 --- a/common/database/database_update_manifest_bots.h +++ b/common/database/database_update_manifest_bots.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/database/database_update.h" diff --git a/common/database/database_update_manifest_custom.h b/common/database/database_update_manifest_custom.h index 70d6dbb1c0..2bed28301e 100644 --- a/common/database/database_update_manifest_custom.h +++ b/common/database/database_update_manifest_custom.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/database/database_update.h" diff --git a/common/database_instances.cpp b/common/database_instances.cpp index 674649ff7d..4d474d6d63 100644 --- a/common/database_instances.cpp +++ b/common/database_instances.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) - -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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "database.h" #include "common/platform/inet.h" diff --git a/common/database_schema.h b/common/database_schema.h index 091e5a7ac9..7a203e659c 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/dbcore.cpp b/common/dbcore.cpp index b9afaa1c63..d119ceacbd 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "dbcore.h" #include "common/eqemu_logsys.h" diff --git a/common/dbcore.h b/common/dbcore.h index 3368dccfc0..eef5c1d4bb 100644 --- a/common/dbcore.h +++ b/common/dbcore.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/mutex.h" diff --git a/common/deity.cpp b/common/deity.cpp index 5ed0619b04..d47cafec41 100644 --- a/common/deity.cpp +++ b/common/deity.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "deity.h" uint32 Deity::GetBitmask(uint32 deity_id) diff --git a/common/deity.h b/common/deity.h index 6b676e2b72..c85494cf99 100644 --- a/common/deity.h +++ b/common/deity.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/discord/discord.cpp b/common/discord/discord.cpp index 3f3c5e492c..f9aed637e4 100644 --- a/common/discord/discord.cpp +++ b/common/discord/discord.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "discord.h" #include "common/eqemu_logsys.h" diff --git a/common/discord/discord.h b/common/discord/discord.h index 47ab075699..42851394ea 100644 --- a/common/discord/discord.h +++ b/common/discord/discord.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/events/player_events.h" diff --git a/common/discord/discord_manager.cpp b/common/discord/discord_manager.cpp index 5ff5810ab5..59b14bc367 100644 --- a/common/discord/discord_manager.cpp +++ b/common/discord/discord_manager.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "discord_manager.h" #include "common/discord/discord.h" diff --git a/common/discord/discord_manager.h b/common/discord/discord_manager.h index 611e3f03cd..b48e12b2e6 100644 --- a/common/discord/discord_manager.h +++ b/common/discord/discord_manager.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once diff --git a/common/dynamic_zone_base.cpp b/common/dynamic_zone_base.cpp index 0df0e2ba9f..758864473a 100644 --- a/common/dynamic_zone_base.cpp +++ b/common/dynamic_zone_base.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "dynamic_zone_base.h" #include "common/database.h" diff --git a/common/dynamic_zone_base.h b/common/dynamic_zone_base.h index d0dfe91402..d6c7ef3161 100644 --- a/common/dynamic_zone_base.h +++ b/common/dynamic_zone_base.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/dynamic_zone_lockout.h" diff --git a/common/dynamic_zone_lockout.cpp b/common/dynamic_zone_lockout.cpp index a43e0e5351..5399ee0a18 100644 --- a/common/dynamic_zone_lockout.cpp +++ b/common/dynamic_zone_lockout.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "dynamic_zone_lockout.h" #include "rulesys.h" #include "strings.h" diff --git a/common/dynamic_zone_lockout.h b/common/dynamic_zone_lockout.h index eb800067cd..2ec9ced0f4 100644 --- a/common/dynamic_zone_lockout.h +++ b/common/dynamic_zone_lockout.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "repositories/base/base_dynamic_zone_lockouts_repository.h" diff --git a/common/emu_constants.cpp b/common/emu_constants.cpp index 8f783c17a6..c5616052a7 100644 --- a/common/emu_constants.cpp +++ b/common/emu_constants.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/bodytypes.h" #include "common/data_verification.h" #include "common/emu_constants.h" diff --git a/common/emu_constants.h b/common/emu_constants.h index e1f9840fed..c246fb0d46 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/bodytypes.h" diff --git a/common/emu_limits.cpp b/common/emu_limits.cpp index a9e74898d9..cb4877fc8b 100644 --- a/common/emu_limits.cpp +++ b/common/emu_limits.cpp @@ -1,18 +1,17 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. - + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ diff --git a/common/emu_limits.h b/common/emu_limits.h index 3d61c07ebc..8c829bccac 100644 --- a/common/emu_limits.h +++ b/common/emu_limits.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/emu_opcodes.cpp b/common/emu_opcodes.cpp index c39952cc86..b10284ebb9 100644 --- a/common/emu_opcodes.cpp +++ b/common/emu_opcodes.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 04111-1307 USA + along with this program. If not, see . */ - #include "common/emu_opcodes.h" const char *OpcodeNames[_maxEmuOpcode+1] = { diff --git a/common/emu_opcodes.h b/common/emu_opcodes.h index 4c20ccf7b8..b0728eefd2 100644 --- a/common/emu_opcodes.h +++ b/common/emu_opcodes.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) - -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 04111-1307 USA -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once //this is the highest opcode possibly used in the regular EQ protocol diff --git a/common/emu_oplist.h b/common/emu_oplist.h index 268fa97cd6..1f8366662a 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ // system use N(OP_ExploreUnknown), // start (please add new opcodes in descending order and re-order any name changes where applicable) diff --git a/common/emu_versions.cpp b/common/emu_versions.cpp index 30447b3001..8d724f4fc8 100644 --- a/common/emu_versions.cpp +++ b/common/emu_versions.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. - + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/emu_versions.h" #include "common/emu_constants.h" diff --git a/common/emu_versions.h b/common/emu_versions.h index d78ac503fc..522fe3c9b4 100644 --- a/common/emu_versions.h +++ b/common/emu_versions.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/eq_constants.h b/common/eq_constants.h index 815073e157..6e621b0d8c 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/skills.h" diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 600d5dc36b..281308af17 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/emu_constants.h" #include "common/emu_limits.h" #include "common/rulesys.h" diff --git a/common/eq_limits.h b/common/eq_limits.h index 4bed002b69..0d79e30417 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. - + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + 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. - + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/emu_versions.h" diff --git a/common/eq_packet.cpp b/common/eq_packet.cpp index f025efb979..93b4f1052d 100644 --- a/common/eq_packet.cpp +++ b/common/eq_packet.cpp @@ -1,19 +1,19 @@ -/* - Copyright (C) 2005 Michael S. Finger +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ #include "eq_packet.h" diff --git a/common/eq_packet.h b/common/eq_packet.h index 395a7d702b..e2d0d27106 100644 --- a/common/eq_packet.h +++ b/common/eq_packet.h @@ -1,19 +1,19 @@ -/* - Copyright (C) 2005 Michael S. Finger +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ #pragma once diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 4ea72a1989..c11945cc4e 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/emu_constants.h" diff --git a/common/eq_stream_ident.cpp b/common/eq_stream_ident.cpp index f6de9ca45b..c56b0815a7 100644 --- a/common/eq_stream_ident.cpp +++ b/common/eq_stream_ident.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/eq_stream_ident.h" #include "common/eq_stream_proxy.h" diff --git a/common/eq_stream_ident.h b/common/eq_stream_ident.h index fbce0cf5f4..d82af81dc5 100644 --- a/common/eq_stream_ident.h +++ b/common/eq_stream_ident.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eq_stream_intf.h" diff --git a/common/eq_stream_intf.h b/common/eq_stream_intf.h index 9431fbedf0..2c5faac557 100644 --- a/common/eq_stream_intf.h +++ b/common/eq_stream_intf.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/emu_versions.h" diff --git a/common/eq_stream_locator.h b/common/eq_stream_locator.h index 17bdabdb4d..70ab1d4add 100644 --- a/common/eq_stream_locator.h +++ b/common/eq_stream_locator.h @@ -1,21 +1,20 @@ -/* - Copyright (C) 2005 EQEmulator Team +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/eq_stream_proxy.cpp b/common/eq_stream_proxy.cpp index f497e0e573..278f165d4e 100644 --- a/common/eq_stream_proxy.cpp +++ b/common/eq_stream_proxy.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "eq_stream_proxy.h" diff --git a/common/eq_stream_proxy.h b/common/eq_stream_proxy.h index 6be9241cc8..99a8b40db4 100644 --- a/common/eq_stream_proxy.h +++ b/common/eq_stream_proxy.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eq_stream_intf.h" diff --git a/common/eqdb.cpp b/common/eqdb.cpp index 05b82b6448..a57e422a17 100644 --- a/common/eqdb.cpp +++ b/common/eqdb.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "eqdb.h" #include "common/database.h" diff --git a/common/eqdb.h b/common/eqdb.h index 32492d607c..f9ad948979 100644 --- a/common/eqdb.h +++ b/common/eqdb.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eqdb_res.h" diff --git a/common/eqdb_res.cpp b/common/eqdb_res.cpp index 2229fa06c5..8f63ace149 100644 --- a/common/eqdb_res.cpp +++ b/common/eqdb_res.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "eqdb_res.h" #include "mysql.h" diff --git a/common/eqdb_res.h b/common/eqdb_res.h index 5c774e532f..45347faaad 100644 --- a/common/eqdb_res.h +++ b/common/eqdb_res.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/database.h" diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index db3faa6424..c30ffaf658 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "eqemu_config.h" #include "common/eqemu_logsys.h" diff --git a/common/eqemu_config.h b/common/eqemu_config.h index fcaf1326f4..908d6969f0 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/json/json.h" diff --git a/common/eqemu_config_elements.h b/common/eqemu_config_elements.h index 9dae490ae9..ce09f312f2 100644 --- a/common/eqemu_config_elements.h +++ b/common/eqemu_config_elements.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ ELEMENT(world) ELEMENT(chatserver) ELEMENT(mailserver) diff --git a/common/eqemu_exception.cpp b/common/eqemu_exception.cpp index 62376283fc..1a5133ce82 100644 --- a/common/eqemu_exception.cpp +++ b/common/eqemu_exception.cpp @@ -1,21 +1,20 @@ -/* EQEmu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEmu Development Team (http://www.eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "eqemu_exception.h" namespace EQ diff --git a/common/eqemu_exception.h b/common/eqemu_exception.h index 6970c1b4cc..d1606bf656 100644 --- a/common/eqemu_exception.h +++ b/common/eqemu_exception.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp index 9390a15ef7..7b5e218ebd 100644 --- a/common/eqemu_logsys.cpp +++ b/common/eqemu_logsys.cpp @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2018 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 - * -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "eqemu_logsys.h" #include "common/file.h" diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index 97b99361c3..c9a4d8fc5d 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2018 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 - * -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/common/eqemu_logsys_log_aliases.h b/common/eqemu_logsys_log_aliases.h index 3a379706c7..aaa2c10332 100644 --- a/common/eqemu_logsys_log_aliases.h +++ b/common/eqemu_logsys_log_aliases.h @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eqemu_logsys.h" diff --git a/common/eqtime.cpp b/common/eqtime.cpp index 001cdb8370..9cc12e02be 100644 --- a/common/eqtime.cpp +++ b/common/eqtime.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "eqtime.h" #include "common/eq_packet_structs.h" diff --git a/common/eqtime.h b/common/eqtime.h index 960570b1aa..f12e39cc02 100644 --- a/common/eqtime.h +++ b/common/eqtime.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eq_packet_structs.h" diff --git a/common/event/event_loop.h b/common/event/event_loop.h index 20cc8a10a4..3c56ab9492 100644 --- a/common/event/event_loop.h +++ b/common/event/event_loop.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/platform/win/include_windows.h" // uv.h is going to include it so let's do it first. diff --git a/common/event/task.h b/common/event/task.h index e711ade7fd..83e72e1279 100644 --- a/common/event/task.h +++ b/common/event/task.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "event_loop.h" diff --git a/common/event/task_scheduler.h b/common/event/task_scheduler.h index 03e197d92b..e2e855682e 100644 --- a/common/event/task_scheduler.h +++ b/common/event/task_scheduler.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/event/timer.h b/common/event/timer.h index adf5efc36b..2cea8072b2 100644 --- a/common/event/timer.h +++ b/common/event/timer.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "event_loop.h" diff --git a/common/event_sub.cpp b/common/event_sub.cpp index c2d94b1750..0061457817 100644 --- a/common/event_sub.cpp +++ b/common/event_sub.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "event_sub.h" void EventSubscriptionWatcher::Subscribe(const std::string &event_name) diff --git a/common/event_sub.h b/common/event_sub.h index cd45314ea2..07d8698d72 100644 --- a/common/event_sub.h +++ b/common/event_sub.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/events/player_event_discord_formatter.cpp b/common/events/player_event_discord_formatter.cpp index 3b49c040a7..67d6b44436 100644 --- a/common/events/player_event_discord_formatter.cpp +++ b/common/events/player_event_discord_formatter.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "player_event_discord_formatter.h" #include "common/json/json_archive_single_line.h" diff --git a/common/events/player_event_discord_formatter.h b/common/events/player_event_discord_formatter.h index 622a41cee0..af7420ccaa 100644 --- a/common/events/player_event_discord_formatter.h +++ b/common/events/player_event_discord_formatter.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/events/player_events.h" diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index b06632a597..fd756f37a8 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "player_event_logs.h" #include "common/events/player_event_discord_formatter.h" diff --git a/common/events/player_event_logs.h b/common/events/player_event_logs.h index a4bcba0a99..98784ea804 100644 --- a/common/events/player_event_logs.h +++ b/common/events/player_event_logs.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eqemu_config.h" diff --git a/common/events/player_events.h b/common/events/player_events.h index a3279b10c3..7dbe8e5d87 100644 --- a/common/events/player_events.h +++ b/common/events/player_events.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/player_event_logs_repository.h" diff --git a/common/evolving_items.cpp b/common/evolving_items.cpp index e23e585992..b7db02e180 100644 --- a/common/evolving_items.cpp +++ b/common/evolving_items.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "evolving_items.h" #include "common/events/player_event_logs.h" diff --git a/common/evolving_items.h b/common/evolving_items.h index ec23f7ade4..867ac23c07 100644 --- a/common/evolving_items.h +++ b/common/evolving_items.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/events/player_events.h" diff --git a/common/extprofile.cpp b/common/extprofile.cpp index a4c8727a71..c425e1edf2 100644 --- a/common/extprofile.cpp +++ b/common/extprofile.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "extprofile.h" //Set defaults in the extended profile... diff --git a/common/extprofile.h b/common/extprofile.h index 7bddcf6f7f..c5d346ac1c 100644 --- a/common/extprofile.h +++ b/common/extprofile.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eq_packet_structs.h" diff --git a/common/faction.cpp b/common/faction.cpp index 1432e94e01..fb006f3e0d 100644 --- a/common/faction.cpp +++ b/common/faction.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "faction.h" #include "common/races.h" diff --git a/common/faction.h b/common/faction.h index 368a8dbc8e..7706e22b65 100755 --- a/common/faction.h +++ b/common/faction.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/features.h" diff --git a/common/features.h b/common/features.h index e0fbc293ee..295fa2d1e0 100644 --- a/common/features.h +++ b/common/features.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once /* diff --git a/common/file.cpp b/common/file.cpp index 3661c2ff9b..45095ce381 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -1,23 +1,20 @@ -/** - * 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 - * -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "file.h" #include "common/platform/platform.h" diff --git a/common/file.h b/common/file.h index ec99a1b36d..ef4130b67d 100644 --- a/common/file.h +++ b/common/file.h @@ -1,23 +1,20 @@ -/** - * 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 - * -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/fixed_memory_hash_set.h b/common/fixed_memory_hash_set.h index 5677427d21..0d92fd887a 100644 --- a/common/fixed_memory_hash_set.h +++ b/common/fixed_memory_hash_set.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eqemu_exception.h" diff --git a/common/fixed_memory_variable_hash_set.h b/common/fixed_memory_variable_hash_set.h index 7aa8c67530..535629a191 100644 --- a/common/fixed_memory_variable_hash_set.h +++ b/common/fixed_memory_variable_hash_set.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eqemu_exception.h" diff --git a/common/global_define.h b/common/global_define.h index 350225ca52..93e70a0bbe 100644 --- a/common/global_define.h +++ b/common/global_define.h @@ -1,19 +1,18 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2015 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once diff --git a/common/guild_base.cpp b/common/guild_base.cpp index 13c2af3c99..8fca522dc4 100644 --- a/common/guild_base.cpp +++ b/common/guild_base.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) - - 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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "guild_base.h" #include "common/database.h" diff --git a/common/guild_base.h b/common/guild_base.h index 9554c06657..653f39d79a 100644 --- a/common/guild_base.h +++ b/common/guild_base.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/guilds.h" diff --git a/common/guilds.h b/common/guilds.h index aca44a1cff..eb746a00a8 100644 --- a/common/guilds.h +++ b/common/guilds.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index 4907cd1b91..e8cb95d84b 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "inventory_profile.h" #include "common/data_verification.h" diff --git a/common/inventory_profile.h b/common/inventory_profile.h index 1297be0d76..72aa803ae7 100644 --- a/common/inventory_profile.h +++ b/common/inventory_profile.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 04111-1307 USA + along with this program. If not, see . */ - // @merth notes: // These classes could be optimized with database reads/writes by storing // a status flag indicating how object needs to interact with database diff --git a/common/inventory_slot.cpp b/common/inventory_slot.cpp index 081147d8f0..d883a78eed 100644 --- a/common/inventory_slot.cpp +++ b/common/inventory_slot.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "inventory_slot.h" #include "common/textures.h" diff --git a/common/inventory_slot.h b/common/inventory_slot.h index dc85763992..11169bf412 100644 --- a/common/inventory_slot.h +++ b/common/inventory_slot.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/emu_constants.h" diff --git a/common/ip_util.cpp b/common/ip_util.cpp index b5c18948f1..c1af78263e 100644 --- a/common/ip_util.cpp +++ b/common/ip_util.cpp @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "ip_util.h" #include "common/eqemu_logsys.h" diff --git a/common/ip_util.h b/common/ip_util.h index 255167aff7..9d04263d4a 100644 --- a/common/ip_util.h +++ b/common/ip_util.h @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/common/ipc_mutex.cpp b/common/ipc_mutex.cpp index 282bb34ea9..9dbc875e01 100644 --- a/common/ipc_mutex.cpp +++ b/common/ipc_mutex.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "ipc_mutex.h" #include "common/eqemu_config.h" diff --git a/common/ipc_mutex.h b/common/ipc_mutex.h index f4ef94ed27..5e38fa3a79 100644 --- a/common/ipc_mutex.h +++ b/common/ipc_mutex.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include diff --git a/common/item_data.cpp b/common/item_data.cpp index f49dcf08ba..f36e504512 100644 --- a/common/item_data.cpp +++ b/common/item_data.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "item_data.h" #include "common/classes.h" diff --git a/common/item_data.h b/common/item_data.h index 30ad2e459c..9e78f8a957 100644 --- a/common/item_data.h +++ b/common/item_data.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 04111-1307 USA + along with this program. If not, see . */ - #pragma once #include "common/emu_constants.h" diff --git a/common/item_instance.cpp b/common/item_instance.cpp index 64ae0b4cc1..4862d103c7 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "inventory_profile.h" #include "common/data_verification.h" diff --git a/common/item_instance.h b/common/item_instance.h index 8c96de1088..96934e35cd 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 04111-1307 USA + along with this program. If not, see . */ - // @merth notes: // These classes could be optimized with database reads/writes by storing // a status flag indicating how object needs to interact with database diff --git a/common/json_config.cpp b/common/json_config.cpp index b41a8fc5bf..da13c254db 100644 --- a/common/json_config.cpp +++ b/common/json_config.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "json_config.h" #include diff --git a/common/json_config.h b/common/json_config.h index 29fbb86c59..f40b1cfb46 100644 --- a/common/json_config.h +++ b/common/json_config.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "json/json.h" diff --git a/common/light_source.cpp b/common/light_source.cpp index e4f5336c6f..9f0a1235c0 100644 --- a/common/light_source.cpp +++ b/common/light_source.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. - + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "light_source.h" #include diff --git a/common/light_source.h b/common/light_source.h index 4c6d479f1f..816b996c4c 100644 --- a/common/light_source.h +++ b/common/light_source.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. - + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + 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. - + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/linked_list.h b/common/linked_list.h index 0c7e390415..5ac929f9a3 100644 --- a/common/linked_list.h +++ b/common/linked_list.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/loot.h b/common/loot.h index c386a4577f..9830585b89 100644 --- a/common/loot.h +++ b/common/loot.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/common/mail_oplist.h b/common/mail_oplist.h index 29cb859e06..868693c395 100644 --- a/common/mail_oplist.h +++ b/common/mail_oplist.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ //Mail and Chat Channels N(OP_Buddy), N(OP_ChannelAnnounceJoin), diff --git a/common/md5.cpp b/common/md5.cpp index 16328d6957..d6db6a47cb 100644 --- a/common/md5.cpp +++ b/common/md5.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /* md5.c -- An implementation of Ron Rivest's MD5 message-digest algorithm. * Written by Colin Plumb in 1993, no copyright is claimed. This code is in the * public domain; do with it what you wish. Equivalent code is available from diff --git a/common/md5.h b/common/md5.h index af4182823c..ff137d69af 100644 --- a/common/md5.h +++ b/common/md5.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/common/memory/ksm.hpp b/common/memory/ksm.hpp index ad9c4de5ac..9d4b282737 100644 --- a/common/memory/ksm.hpp +++ b/common/memory/ksm.hpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eqemu_logsys.h" diff --git a/common/memory_buffer.cpp b/common/memory_buffer.cpp index 9cebd5ff2b..922a5db1e0 100644 --- a/common/memory_buffer.cpp +++ b/common/memory_buffer.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "memory_buffer.h" diff --git a/common/memory_buffer.h b/common/memory_buffer.h index 3f4ab031b4..c8bd1e2d57 100644 --- a/common/memory_buffer.h +++ b/common/memory_buffer.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/memory_mapped_file.cpp b/common/memory_mapped_file.cpp index ed77f5bf73..9127bae4ea 100644 --- a/common/memory_mapped_file.cpp +++ b/common/memory_mapped_file.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "memory_mapped_file.h" #include "common/eqemu_exception.h" diff --git a/common/memory_mapped_file.h b/common/memory_mapped_file.h index f228db90ca..2dad20c945 100644 --- a/common/memory_mapped_file.h +++ b/common/memory_mapped_file.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/misc.cpp b/common/misc.cpp index f3e436ae5d..33e14e1e6a 100644 --- a/common/misc.cpp +++ b/common/misc.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "misc.h" #include "common/strings.h" diff --git a/common/misc.h b/common/misc.h index d488e854a8..0a28fbee26 100644 --- a/common/misc.h +++ b/common/misc.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/misc_functions.cpp b/common/misc_functions.cpp index c4bcb7d8e6..1c996ada52 100644 --- a/common/misc_functions.cpp +++ b/common/misc_functions.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "misc_functions.h" #include "common/platform/inet.h" diff --git a/common/misc_functions.h b/common/misc_functions.h index 1db55e4663..82d4f0e841 100644 --- a/common/misc_functions.h +++ b/common/misc_functions.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/mutex.cpp b/common/mutex.cpp index 852f523436..f8c1db00d0 100644 --- a/common/mutex.cpp +++ b/common/mutex.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "mutex.h" #include diff --git a/common/mutex.h b/common/mutex.h index fc4d248737..8040ec2aae 100644 --- a/common/mutex.h +++ b/common/mutex.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/mysql_request_result.cpp b/common/mysql_request_result.cpp index fbe8fc7584..bd3ebc2bb3 100644 --- a/common/mysql_request_result.cpp +++ b/common/mysql_request_result.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "mysql_request_result.h" diff --git a/common/mysql_request_result.h b/common/mysql_request_result.h index 1cd1d2aa3e..492872e3c2 100644 --- a/common/mysql_request_result.h +++ b/common/mysql_request_result.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/mysql_request_row.h" diff --git a/common/mysql_request_row.cpp b/common/mysql_request_row.cpp index 6f5300964d..5d142f6f68 100644 --- a/common/mysql_request_row.cpp +++ b/common/mysql_request_row.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "mysql_request_row.h" MySQLRequestRow::MySQLRequestRow(const MySQLRequestRow& row) diff --git a/common/mysql_request_row.h b/common/mysql_request_row.h index eb19d7ee83..cc6559046b 100644 --- a/common/mysql_request_row.h +++ b/common/mysql_request_row.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/common/mysql_stmt.cpp b/common/mysql_stmt.cpp index dba8eca621..8665c16f97 100644 --- a/common/mysql_stmt.cpp +++ b/common/mysql_stmt.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "mysql_stmt.h" #include "common/eqemu_logsys.h" diff --git a/common/mysql_stmt.h b/common/mysql_stmt.h index 2592f19f7e..63cda89d3e 100644 --- a/common/mysql_stmt.h +++ b/common/mysql_stmt.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "mysql.h" diff --git a/common/net/console_server.cpp b/common/net/console_server.cpp index a737c5a4d6..898e4b99f9 100644 --- a/common/net/console_server.cpp +++ b/common/net/console_server.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "console_server.h" #include "common/strings.h" diff --git a/common/net/console_server.h b/common/net/console_server.h index e984c884f6..e85f13117c 100644 --- a/common/net/console_server.h +++ b/common/net/console_server.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "console_server_connection.h" diff --git a/common/net/console_server_connection.cpp b/common/net/console_server_connection.cpp index 88be73d964..c1555ba0b4 100644 --- a/common/net/console_server_connection.cpp +++ b/common/net/console_server_connection.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "console_server_connection.h" #include "common/util/uuid.h" diff --git a/common/net/console_server_connection.h b/common/net/console_server_connection.h index ba9f47ff52..3f9b232879 100644 --- a/common/net/console_server_connection.h +++ b/common/net/console_server_connection.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "tcp_server.h" diff --git a/common/net/crc32.cpp b/common/net/crc32.cpp index 52ec128ff0..169e6395ee 100644 --- a/common/net/crc32.cpp +++ b/common/net/crc32.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "crc32.h" unsigned int CRC32EncodeTable[256] = diff --git a/common/net/crc32.h b/common/net/crc32.h index c4ab85c8b0..6c9f6bc974 100644 --- a/common/net/crc32.h +++ b/common/net/crc32.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once namespace EQ diff --git a/common/net/dns.h b/common/net/dns.h index c762855636..2b799ef4fc 100644 --- a/common/net/dns.h +++ b/common/net/dns.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/event/event_loop.h" diff --git a/common/net/endian.h b/common/net/endian.h index a4d28da1bd..5167d965bb 100644 --- a/common/net/endian.h +++ b/common/net/endian.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/net/eqstream.cpp b/common/net/eqstream.cpp index dfed5609b0..d3ae01d311 100644 --- a/common/net/eqstream.cpp +++ b/common/net/eqstream.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "eqstream.h" #include "common/eqemu_logsys.h" diff --git a/common/net/eqstream.h b/common/net/eqstream.h index 1f78523c75..43a51af70a 100644 --- a/common/net/eqstream.h +++ b/common/net/eqstream.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eq_packet.h" diff --git a/common/net/packet.cpp b/common/net/packet.cpp index 61e3749ae5..fc7a70269c 100644 --- a/common/net/packet.cpp +++ b/common/net/packet.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "packet.h" #include "common/net/endian.h" diff --git a/common/net/packet.h b/common/net/packet.h index e846934076..6955c9a537 100644 --- a/common/net/packet.h +++ b/common/net/packet.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/util/memory_stream.h" diff --git a/common/net/reliable_stream_connection.cpp b/common/net/reliable_stream_connection.cpp index 0c93a72452..7c0421d594 100644 --- a/common/net/reliable_stream_connection.cpp +++ b/common/net/reliable_stream_connection.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "reliable_stream_connection.h" #include "common/event/event_loop.h" diff --git a/common/net/reliable_stream_connection.h b/common/net/reliable_stream_connection.h index 756857c77b..c9fc337f40 100644 --- a/common/net/reliable_stream_connection.h +++ b/common/net/reliable_stream_connection.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/random.h" diff --git a/common/net/reliable_stream_pooling.h b/common/net/reliable_stream_pooling.h index 37b1655f69..6260f0b421 100644 --- a/common/net/reliable_stream_pooling.h +++ b/common/net/reliable_stream_pooling.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eqemu_logsys.h" diff --git a/common/net/reliable_stream_structs.h b/common/net/reliable_stream_structs.h index 1c89049475..c27ec7eef1 100644 --- a/common/net/reliable_stream_structs.h +++ b/common/net/reliable_stream_structs.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/net/endian.h" diff --git a/common/net/servertalk_client_connection.cpp b/common/net/servertalk_client_connection.cpp index 5f6e8b179a..d276e9e987 100644 --- a/common/net/servertalk_client_connection.cpp +++ b/common/net/servertalk_client_connection.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "servertalk_client_connection.h" #include "common/eqemu_logsys.h" diff --git a/common/net/servertalk_client_connection.h b/common/net/servertalk_client_connection.h index 988797884a..c6f085ffba 100644 --- a/common/net/servertalk_client_connection.h +++ b/common/net/servertalk_client_connection.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/event/timer.h" diff --git a/common/net/servertalk_common.h b/common/net/servertalk_common.h index 91d1d6914d..113afb206d 100644 --- a/common/net/servertalk_common.h +++ b/common/net/servertalk_common.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/servertalk.h" diff --git a/common/net/servertalk_legacy_client_connection.cpp b/common/net/servertalk_legacy_client_connection.cpp index d745b7c585..cab47e7012 100644 --- a/common/net/servertalk_legacy_client_connection.cpp +++ b/common/net/servertalk_legacy_client_connection.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "servertalk_legacy_client_connection.h" #include "common/net/dns.h" diff --git a/common/net/servertalk_legacy_client_connection.h b/common/net/servertalk_legacy_client_connection.h index 9fa75b10aa..6f4837886a 100644 --- a/common/net/servertalk_legacy_client_connection.h +++ b/common/net/servertalk_legacy_client_connection.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/event/timer.h" diff --git a/common/net/servertalk_server.cpp b/common/net/servertalk_server.cpp index 33e1293f97..f3f3b4cea7 100644 --- a/common/net/servertalk_server.cpp +++ b/common/net/servertalk_server.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "servertalk_server.h" EQ::Net::ServertalkServer::ServertalkServer() diff --git a/common/net/servertalk_server.h b/common/net/servertalk_server.h index 8637728307..b5ad0c8617 100644 --- a/common/net/servertalk_server.h +++ b/common/net/servertalk_server.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/net/servertalk_server_connection.h" diff --git a/common/net/servertalk_server_connection.cpp b/common/net/servertalk_server_connection.cpp index a429ddb69a..c56eee0a99 100644 --- a/common/net/servertalk_server_connection.cpp +++ b/common/net/servertalk_server_connection.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "servertalk_server_connection.h" #include "common/eqemu_logsys.h" diff --git a/common/net/servertalk_server_connection.h b/common/net/servertalk_server_connection.h index 17686c2049..053aac9b92 100644 --- a/common/net/servertalk_server_connection.h +++ b/common/net/servertalk_server_connection.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/net/packet.h" diff --git a/common/net/tcp_connection.cpp b/common/net/tcp_connection.cpp index f57a1838c6..fba9ab9ebe 100644 --- a/common/net/tcp_connection.cpp +++ b/common/net/tcp_connection.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "tcp_connection.h" #include "common/event/event_loop.h" diff --git a/common/net/tcp_connection.h b/common/net/tcp_connection.h index f8fe211420..7c421c2043 100644 --- a/common/net/tcp_connection.h +++ b/common/net/tcp_connection.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/net/tcp_connection_pooling.h" diff --git a/common/net/tcp_connection_pooling.h b/common/net/tcp_connection_pooling.h index 4166b5ed64..27d752737c 100644 --- a/common/net/tcp_connection_pooling.h +++ b/common/net/tcp_connection_pooling.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eqemu_logsys.h" diff --git a/common/net/tcp_server.cpp b/common/net/tcp_server.cpp index 40761e540e..39e3a4b577 100644 --- a/common/net/tcp_server.cpp +++ b/common/net/tcp_server.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "tcp_server.h" #include "common/event/event_loop.h" diff --git a/common/net/tcp_server.h b/common/net/tcp_server.h index 9350b66a63..7c35eee8d2 100644 --- a/common/net/tcp_server.h +++ b/common/net/tcp_server.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/net/tcp_connection.h" diff --git a/common/net/websocket_server.cpp b/common/net/websocket_server.cpp index dcbab2f046..4a7915ee1e 100644 --- a/common/net/websocket_server.cpp +++ b/common/net/websocket_server.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "websocket_server.h" #include "common/emu_constants.h" diff --git a/common/net/websocket_server.h b/common/net/websocket_server.h index 37e0574319..d69399a8f4 100644 --- a/common/net/websocket_server.h +++ b/common/net/websocket_server.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/json/json.h" diff --git a/common/net/websocket_server_connection.cpp b/common/net/websocket_server_connection.cpp index 0fc913d2e5..4add781fd2 100644 --- a/common/net/websocket_server_connection.cpp +++ b/common/net/websocket_server_connection.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "websocket_server_connection.h" #include "common/net/websocket_server.h" diff --git a/common/net/websocket_server_connection.h b/common/net/websocket_server_connection.h index 9d75882616..4e0a460255 100644 --- a/common/net/websocket_server_connection.h +++ b/common/net/websocket_server_connection.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/json/json-forwards.h" diff --git a/common/op_codes.h b/common/op_codes.h index b9554aa73c..fbf0735a64 100644 --- a/common/op_codes.h +++ b/common/op_codes.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once diff --git a/common/opcode_dispatch.h b/common/opcode_dispatch.h index 60e3813201..24e624c050 100644 --- a/common/opcode_dispatch.h +++ b/common/opcode_dispatch.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /* diff --git a/common/opcode_map.cpp b/common/opcode_map.cpp index 7a07551a6a..bb67db0b22 100644 --- a/common/opcode_map.cpp +++ b/common/opcode_map.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include #include diff --git a/common/opcodemgr.cpp b/common/opcodemgr.cpp index b761f3b8cf..c14888e7c7 100644 --- a/common/opcodemgr.cpp +++ b/common/opcodemgr.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "opcodemgr.h" #include "common/emu_opcodes.h" diff --git a/common/opcodemgr.h b/common/opcodemgr.h index 8846ed6191..152b652aaf 100644 --- a/common/opcodemgr.h +++ b/common/opcodemgr.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/emu_opcodes.h" diff --git a/common/packet_dump.cpp b/common/packet_dump.cpp index 8e638768f8..d617de424e 100644 --- a/common/packet_dump.cpp +++ b/common/packet_dump.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "packet_dump.h" #include "common/servertalk.h" diff --git a/common/packet_dump.h b/common/packet_dump.h index 796dc021a3..75429e9b07 100644 --- a/common/packet_dump.h +++ b/common/packet_dump.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/packet_dump_file.cpp b/common/packet_dump_file.cpp index 5d08c983de..a2c323c691 100644 --- a/common/packet_dump_file.cpp +++ b/common/packet_dump_file.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "packet_dump_file.h" #include "common/eq_stream_intf.h" diff --git a/common/packet_dump_file.h b/common/packet_dump_file.h index d0e32d69a8..9c638564d9 100644 --- a/common/packet_dump_file.h +++ b/common/packet_dump_file.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/packet_functions.cpp b/common/packet_functions.cpp index 4783db9273..e77743ea15 100644 --- a/common/packet_functions.cpp +++ b/common/packet_functions.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "packet_functions.h" #include "common/packet_dump.h" diff --git a/common/packet_functions.h b/common/packet_functions.h index 8c400534de..fc6a776d87 100644 --- a/common/packet_functions.h +++ b/common/packet_functions.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/packetfile.cpp b/common/packetfile.cpp index eea6ef3745..f730dcc2f1 100644 --- a/common/packetfile.cpp +++ b/common/packetfile.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "packetfile.h" #include "common/eq_opcodes.h" diff --git a/common/packetfile.h b/common/packetfile.h index 953ad73806..3e66edd054 100644 --- a/common/packetfile.h +++ b/common/packetfile.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/common/patches/deprecated_rof2_itemfields.h b/common/patches/deprecated_rof2_itemfields.h index 0a3211898d..940bcdf074 100644 --- a/common/patches/deprecated_rof2_itemfields.h +++ b/common/patches/deprecated_rof2_itemfields.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /* diff --git a/common/patches/deprecated_rof_itemfields.h b/common/patches/deprecated_rof_itemfields.h index 0a3211898d..940bcdf074 100644 --- a/common/patches/deprecated_rof_itemfields.h +++ b/common/patches/deprecated_rof_itemfields.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /* diff --git a/common/patches/deprecated_sod_itemfields.h b/common/patches/deprecated_sod_itemfields.h index 5f8c093549..d5d21ba0d7 100644 --- a/common/patches/deprecated_sod_itemfields.h +++ b/common/patches/deprecated_sod_itemfields.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /* diff --git a/common/patches/deprecated_sof_itemfields.h b/common/patches/deprecated_sof_itemfields.h index 5f8c093549..d5d21ba0d7 100644 --- a/common/patches/deprecated_sof_itemfields.h +++ b/common/patches/deprecated_sof_itemfields.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /* diff --git a/common/patches/deprecated_sof_opcode_list.h b/common/patches/deprecated_sof_opcode_list.h index b52e973add..d8a88f63fb 100644 --- a/common/patches/deprecated_sof_opcode_list.h +++ b/common/patches/deprecated_sof_opcode_list.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ // Generated by DumpOpcodeTable.idc // This File is not used in the build, but here as a reference for SoF. diff --git a/common/patches/deprecated_titanium_itemfields_a.h b/common/patches/deprecated_titanium_itemfields_a.h index ba8d7b1c6d..7603798a00 100644 --- a/common/patches/deprecated_titanium_itemfields_a.h +++ b/common/patches/deprecated_titanium_itemfields_a.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /* diff --git a/common/patches/deprecated_titanium_itemfields_b.h b/common/patches/deprecated_titanium_itemfields_b.h index 30dc73bff9..dcc930790e 100644 --- a/common/patches/deprecated_titanium_itemfields_b.h +++ b/common/patches/deprecated_titanium_itemfields_b.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /* diff --git a/common/patches/deprecated_uf_itemfields.h b/common/patches/deprecated_uf_itemfields.h index 5f8c093549..d5d21ba0d7 100644 --- a/common/patches/deprecated_uf_itemfields.h +++ b/common/patches/deprecated_uf_itemfields.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /* diff --git a/common/patches/patches.cpp b/common/patches/patches.cpp index 359739788c..7e4876a04b 100644 --- a/common/patches/patches.cpp +++ b/common/patches/patches.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. - + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "patches.h" #include "common/patches/rof.h" diff --git a/common/patches/patches.h b/common/patches/patches.h index d5a5661b5b..5a85addd41 100644 --- a/common/patches/patches.h +++ b/common/patches/patches.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. - + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 06074a9293..90fc993120 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "rof.h" #include "rof_structs.h" diff --git a/common/patches/rof.h b/common/patches/rof.h index a2d6f8fda9..229d371a66 100644 --- a/common/patches/rof.h +++ b/common/patches/rof.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. - + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/struct_strategy.h" diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index ddddc27754..b240fd4b35 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "rof2.h" #include "rof2_structs.h" diff --git a/common/patches/rof2.h b/common/patches/rof2.h index 7775fff002..fffc1be232 100644 --- a/common/patches/rof2.h +++ b/common/patches/rof2.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/struct_strategy.h" diff --git a/common/patches/rof2_limits.cpp b/common/patches/rof2_limits.cpp index 4cd5a69443..c0440fd578 100644 --- a/common/patches/rof2_limits.cpp +++ b/common/patches/rof2_limits.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "rof2_limits.h" #include "common/strings.h" diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index fbf4fc677b..a32b365dc4 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/emu_versions.h" diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h index 754635e416..65e371430a 100644 --- a/common/patches/rof2_ops.h +++ b/common/patches/rof2_ops.h @@ -1,23 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - - // out-going packets that require an ENCODE translation: // Begin RoF2 Encodes diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 84c026d5d0..e46d970892 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eq_packet_structs.h" diff --git a/common/patches/rof_limits.cpp b/common/patches/rof_limits.cpp index 0011c9dcea..24de3436d2 100644 --- a/common/patches/rof_limits.cpp +++ b/common/patches/rof_limits.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "rof_limits.h" #include "common/strings.h" diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index e8f4637f87..e9fc10d207 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/emu_versions.h" diff --git a/common/patches/rof_ops.h b/common/patches/rof_ops.h index 7ceb7644a8..ceb4ae8e9e 100644 --- a/common/patches/rof_ops.h +++ b/common/patches/rof_ops.h @@ -1,23 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - - // out-going packets that require an ENCODE translation: E(OP_Action) E(OP_AdventureMerchantSell) diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index ec00432e2a..2658a7c25e 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/patches/rof_limits.h" diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 27ffcf87dc..27224e3806 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "sod.h" #include "sod_structs.h" diff --git a/common/patches/sod.h b/common/patches/sod.h index d8e2cd8824..6820e6e72f 100644 --- a/common/patches/sod.h +++ b/common/patches/sod.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/struct_strategy.h" diff --git a/common/patches/sod_limits.cpp b/common/patches/sod_limits.cpp index 9141e08e23..cc08dfaed8 100644 --- a/common/patches/sod_limits.cpp +++ b/common/patches/sod_limits.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "sod_limits.h" #include "common/strings.h" diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index bcf566bdac..16f4fa86e6 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/emu_versions.h" diff --git a/common/patches/sod_ops.h b/common/patches/sod_ops.h index bf9ce998ac..48cebca54a 100644 --- a/common/patches/sod_ops.h +++ b/common/patches/sod_ops.h @@ -1,23 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - - // out-going packets that require an ENCODE translation: E(OP_Action) E(OP_AdventureMerchantSell) diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 5519e5b7d1..dcf58ca952 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eq_packet_structs.h" diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 8c6e3d586b..818bc3b8f2 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "sof.h" #include "sof_structs.h" diff --git a/common/patches/sof.h b/common/patches/sof.h index e240d7c615..bef47bb4d0 100644 --- a/common/patches/sof.h +++ b/common/patches/sof.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/struct_strategy.h" diff --git a/common/patches/sof_limits.cpp b/common/patches/sof_limits.cpp index 8af38cc495..0495cb773a 100644 --- a/common/patches/sof_limits.cpp +++ b/common/patches/sof_limits.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "sof_limits.h" #include "common/strings.h" diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 16aab91bc5..4c4781611b 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/emu_versions.h" diff --git a/common/patches/sof_ops.h b/common/patches/sof_ops.h index 57fd9c4478..58f9dc253a 100644 --- a/common/patches/sof_ops.h +++ b/common/patches/sof_ops.h @@ -1,23 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - - // out-going packets that require an ENCODE translation: E(OP_Action) E(OP_AdventureMerchantSell) diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 8224910e31..6f137faed8 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eq_packet_structs.h" diff --git a/common/patches/ss_declare.h b/common/patches/ss_declare.h index 4ea05d25b9..f1a972bc0c 100644 --- a/common/patches/ss_declare.h +++ b/common/patches/ss_declare.h @@ -1,21 +1,19 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #define E(x) static void Encode_##x(EQApplicationPacket **p, std::shared_ptr dest, bool ack_req); #define D(x) static void Decode_##x(EQApplicationPacket *p); diff --git a/common/patches/ss_define.h b/common/patches/ss_define.h index 63eef99b3e..f4398677ab 100644 --- a/common/patches/ss_define.h +++ b/common/patches/ss_define.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #define ENCODE(x) void Strategy::Encode_##x(EQApplicationPacket **p, std::shared_ptr dest, bool ack_req) #define DECODE(x) void Strategy::Decode_##x(EQApplicationPacket *__packet) diff --git a/common/patches/ss_register.h b/common/patches/ss_register.h index f8613195f5..83dba0ee73 100644 --- a/common/patches/ss_register.h +++ b/common/patches/ss_register.h @@ -1,21 +1,19 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #define E(x) encoders[x] = Encode_##x; #define D(x) decoders[x] = Decode_##x; diff --git a/common/patches/template.cpp b/common/patches/template.cpp index 14fe921454..28ac7f553a 100644 --- a/common/patches/template.cpp +++ b/common/patches/template.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "TEMPLATE.h" #include "TEMPLATE_structs.h" diff --git a/common/patches/template.h b/common/patches/template.h index 990a474fa0..8fe3775cb5 100644 --- a/common/patches/template.h +++ b/common/patches/template.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/struct_strategy.h" diff --git a/common/patches/template_limits.cpp b/common/patches/template_limits.cpp index 273e74a5cd..cb4877fc8b 100644 --- a/common/patches/template_limits.cpp +++ b/common/patches/template_limits.cpp @@ -1,18 +1,17 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) - +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + 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. - + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + 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. - + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ diff --git a/common/patches/template_limits.h b/common/patches/template_limits.h index 901055da75..16f66d7d97 100644 --- a/common/patches/template_limits.h +++ b/common/patches/template_limits.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) - +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + 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. - + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + 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. - + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once diff --git a/common/patches/template_ops.h b/common/patches/template_ops.h index 9055201553..04573678d8 100644 --- a/common/patches/template_ops.h +++ b/common/patches/template_ops.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ //list of packets we need to encode on the way out: E(OP_SendAATable) diff --git a/common/patches/template_structs.h b/common/patches/template_structs.h index 8da39d72be..2936a802ba 100644 --- a/common/patches/template_structs.h +++ b/common/patches/template_structs.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once namespace TEMPLATE { namespace structs { diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 98c463921d..c3fdf479e4 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "titanium.h" #include "titanium_structs.h" diff --git a/common/patches/titanium.h b/common/patches/titanium.h index 25362503cb..431e8346de 100644 --- a/common/patches/titanium.h +++ b/common/patches/titanium.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/struct_strategy.h" diff --git a/common/patches/titanium_limits.cpp b/common/patches/titanium_limits.cpp index dbe6e82da3..5c854807c7 100644 --- a/common/patches/titanium_limits.cpp +++ b/common/patches/titanium_limits.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "titanium_limits.h" #include "common/strings.h" diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index 2ed5337e6f..a90e4bc9b3 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/emu_versions.h" diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index a891b8102b..1116baac73 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -1,23 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - - // out-going packets that require an ENCODE translation: E(OP_Action) E(OP_AdventureMerchantSell) diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index ff3ad0272b..3d3dfadd44 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eq_packet_structs.h" diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 4f36881610..05c058217e 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "uf.h" #include "uf_structs.h" diff --git a/common/patches/uf.h b/common/patches/uf.h index 8eb4e3488a..e1172951be 100644 --- a/common/patches/uf.h +++ b/common/patches/uf.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/struct_strategy.h" diff --git a/common/patches/uf_limits.cpp b/common/patches/uf_limits.cpp index 6f75f4474a..e95c87df41 100644 --- a/common/patches/uf_limits.cpp +++ b/common/patches/uf_limits.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "uf_limits.h" #include "common/strings.h" diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index ccde464285..65b3f4c0b4 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/emu_versions.h" diff --git a/common/patches/uf_ops.h b/common/patches/uf_ops.h index 16bdbf9bf0..4b0830e831 100644 --- a/common/patches/uf_ops.h +++ b/common/patches/uf_ops.h @@ -1,23 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - - // out-going packets that require an ENCODE translation: E(OP_Action) E(OP_AdventureMerchantSell) diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 40d7e5691e..3720df32c6 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eq_packet_structs.h" diff --git a/common/path_manager.cpp b/common/path_manager.cpp index 18dd1eb1dd..0c727f5c72 100644 --- a/common/path_manager.cpp +++ b/common/path_manager.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "path_manager.h" #include "common/eqemu_config.h" diff --git a/common/path_manager.h b/common/path_manager.h index 7bf2fa2808..b3f6e8b1d9 100644 --- a/common/path_manager.h +++ b/common/path_manager.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/pch/app-pch.h b/common/pch/app-pch.h index 2611490639..6351229bea 100644 --- a/common/pch/app-pch.h +++ b/common/pch/app-pch.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/common/pch/std-pch.h b/common/pch/std-pch.h index f8428dda5c..e314baf454 100644 --- a/common/pch/std-pch.h +++ b/common/pch/std-pch.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once // fmt diff --git a/common/perl_eqdb.cpp b/common/perl_eqdb.cpp index 7d1860c569..b066a3cf65 100644 --- a/common/perl_eqdb.cpp +++ b/common/perl_eqdb.cpp @@ -1,30 +1,20 @@ -/* -* This file was generated automatically by xsubpp version 1.9508 from the -* contents of tmp. Do not edit this file, edit tmp instead. -* -* ANY CHANGES MADE HERE WILL BE LOST! -* -*/ - +/* EQEmu: EQEmulator -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - typedef const char Const_char; #ifdef EMBPERL diff --git a/common/perl_eqdb_res.cpp b/common/perl_eqdb_res.cpp index e55dac5ab0..d6542a6cab 100644 --- a/common/perl_eqdb_res.cpp +++ b/common/perl_eqdb_res.cpp @@ -1,30 +1,20 @@ -/* -* This file was generated automatically by xsubpp version 1.9508 from the -* contents of tmp. Do not edit this file, edit tmp instead. -* -* ANY CHANGES MADE HERE WILL BE LOST! -* -*/ - +/* EQEmu: EQEmulator -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - typedef const char Const_char; #ifdef EMBPERL diff --git a/common/platform.cpp b/common/platform.cpp index 93f833a3b1..265fb87492 100644 --- a/common/platform.cpp +++ b/common/platform.cpp @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "platform.h" EQEmuExePlatform exe_platform = ExePlatformNone; diff --git a/common/platform.h b/common/platform.h index 626eb4b176..f3dbb7c044 100644 --- a/common/platform.h +++ b/common/platform.h @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/platform/inet.h b/common/platform/inet.h index 2cdf672ca2..194fe59d4d 100644 --- a/common/platform/inet.h +++ b/common/platform/inet.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/platform/posix/include_inet.h" diff --git a/common/platform/platform.h b/common/platform/platform.h index 38d9aac321..d49bb7aac6 100644 --- a/common/platform/platform.h +++ b/common/platform/platform.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef _WINDOWS diff --git a/common/platform/posix/include_inet.h b/common/platform/posix/include_inet.h index d50d9e164d..0a07f84794 100644 --- a/common/platform/posix/include_inet.h +++ b/common/platform/posix/include_inet.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifndef _WINDOWS diff --git a/common/platform/posix/include_pthreads.h b/common/platform/posix/include_pthreads.h index c8e550baf2..2a5cbbada7 100644 --- a/common/platform/posix/include_pthreads.h +++ b/common/platform/posix/include_pthreads.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifndef _WINDOWS diff --git a/common/platform/win/include_windows.h b/common/platform/win/include_windows.h index 9a1f218185..9aa3b5f2fd 100644 --- a/common/platform/win/include_windows.h +++ b/common/platform/win/include_windows.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef _WINDOWS diff --git a/common/platform/win/include_winsock2.h b/common/platform/win/include_winsock2.h index 563a49b586..0aaf30931b 100644 --- a/common/platform/win/include_winsock2.h +++ b/common/platform/win/include_winsock2.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef _WINDOWS diff --git a/common/proc_launcher.cpp b/common/proc_launcher.cpp index 9b11139242..6936d7162f 100644 --- a/common/proc_launcher.cpp +++ b/common/proc_launcher.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "proc_launcher.h" #include "common/types.h" diff --git a/common/proc_launcher.h b/common/proc_launcher.h index 5a9aa421ea..26f3a5cd63 100644 --- a/common/proc_launcher.h +++ b/common/proc_launcher.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/platform/platform.h" diff --git a/common/process.cpp b/common/process.cpp index 152fc2d181..44554f3676 100644 --- a/common/process.cpp +++ b/common/process.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "process.h" #include diff --git a/common/process.h b/common/process.h index c9f62b4e93..7fa40d4eea 100644 --- a/common/process.h +++ b/common/process.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once class Process { diff --git a/common/process/process.cpp b/common/process/process.cpp index ddd620cbe3..8c84ef6a35 100644 --- a/common/process/process.cpp +++ b/common/process/process.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "process.h" #include "fmt/format.h" diff --git a/common/process/process.h b/common/process/process.h index a357674adb..396e3233ac 100644 --- a/common/process/process.h +++ b/common/process/process.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/strings.h" diff --git a/common/profanity_manager.cpp b/common/profanity_manager.cpp index 200d11f91e..4e62304cc0 100644 --- a/common/profanity_manager.cpp +++ b/common/profanity_manager.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2019 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "profanity_manager.h" #include "common/dbcore.h" diff --git a/common/profanity_manager.h b/common/profanity_manager.h index c2f2ed91e6..9adda5ba6b 100644 --- a/common/profanity_manager.h +++ b/common/profanity_manager.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2019 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. - + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + 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. - + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "fmt/format.h" diff --git a/common/profiler.h b/common/profiler.h index c0b1e5eb43..39d996e015 100644 --- a/common/profiler.h +++ b/common/profiler.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #ifdef EQPROFILE diff --git a/common/ptimer.cpp b/common/ptimer.cpp index 9ab6a8068d..431c5a7528 100644 --- a/common/ptimer.cpp +++ b/common/ptimer.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2005 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "ptimer.h" #include "common/database.h" diff --git a/common/ptimer.h b/common/ptimer.h index fa116f84d1..c426152a3c 100644 --- a/common/ptimer.h +++ b/common/ptimer.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2005 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/queue.h b/common/queue.h index b7e6515df3..8bb1c92afe 100644 --- a/common/queue.h +++ b/common/queue.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once template diff --git a/common/races.cpp b/common/races.cpp index 603c775f81..1d84ace4a2 100644 --- a/common/races.cpp +++ b/common/races.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "races.h" #include "common/data_verification.h" diff --git a/common/races.h b/common/races.h index 86a296ca85..4d7d26f451 100644 --- a/common/races.h +++ b/common/races.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/raid.h b/common/raid.h index e2dbe9c2c7..751ce6eb08 100644 --- a/common/raid.h +++ b/common/raid.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once enum { //raid packet types: diff --git a/common/random.h b/common/random.h index 86dfe9b2b5..08c6329a1a 100644 --- a/common/random.h +++ b/common/random.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2021 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include diff --git a/common/rdtsc.cpp b/common/rdtsc.cpp index fc3bdfd3d9..a9aaf02369 100644 --- a/common/rdtsc.cpp +++ b/common/rdtsc.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "rdtsc.h" #include "common/types.h" diff --git a/common/rdtsc.h b/common/rdtsc.h index 44861f18d1..0d5b34295e 100644 --- a/common/rdtsc.h +++ b/common/rdtsc.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/repositories/aa_ability_repository.h b/common/repositories/aa_ability_repository.h index 3713cfb593..5d55e7550a 100644 --- a/common/repositories/aa_ability_repository.h +++ b/common/repositories/aa_ability_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_aa_ability_repository.h" diff --git a/common/repositories/aa_rank_effects_repository.h b/common/repositories/aa_rank_effects_repository.h index 39cb9f0024..46a2006b8f 100644 --- a/common/repositories/aa_rank_effects_repository.h +++ b/common/repositories/aa_rank_effects_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_aa_rank_effects_repository.h" diff --git a/common/repositories/aa_rank_prereqs_repository.h b/common/repositories/aa_rank_prereqs_repository.h index 5d0b17adc8..86681cb008 100644 --- a/common/repositories/aa_rank_prereqs_repository.h +++ b/common/repositories/aa_rank_prereqs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_aa_rank_prereqs_repository.h" diff --git a/common/repositories/aa_ranks_repository.h b/common/repositories/aa_ranks_repository.h index 1a9812af34..f8fb1ee2f9 100644 --- a/common/repositories/aa_ranks_repository.h +++ b/common/repositories/aa_ranks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_aa_ranks_repository.h" diff --git a/common/repositories/account_flags_repository.h b/common/repositories/account_flags_repository.h index f554072eda..5920e9a35b 100644 --- a/common/repositories/account_flags_repository.h +++ b/common/repositories/account_flags_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_account_flags_repository.h" diff --git a/common/repositories/account_ip_repository.h b/common/repositories/account_ip_repository.h index 1159d8c86f..0f35bdc73c 100644 --- a/common/repositories/account_ip_repository.h +++ b/common/repositories/account_ip_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_account_ip_repository.h" diff --git a/common/repositories/account_repository.h b/common/repositories/account_repository.h index 42a301ec1a..1c24527284 100644 --- a/common/repositories/account_repository.h +++ b/common/repositories/account_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_account_repository.h" diff --git a/common/repositories/account_rewards_repository.h b/common/repositories/account_rewards_repository.h index 7e2183c8f5..9eb58d46ee 100644 --- a/common/repositories/account_rewards_repository.h +++ b/common/repositories/account_rewards_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_account_rewards_repository.h" diff --git a/common/repositories/adventure_details_repository.h b/common/repositories/adventure_details_repository.h index 0bd4875e3d..3f678c8003 100644 --- a/common/repositories/adventure_details_repository.h +++ b/common/repositories/adventure_details_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_adventure_details_repository.h" diff --git a/common/repositories/adventure_members_repository.h b/common/repositories/adventure_members_repository.h index fed4e9996f..60e6ddcd44 100644 --- a/common/repositories/adventure_members_repository.h +++ b/common/repositories/adventure_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_adventure_members_repository.h" diff --git a/common/repositories/adventure_stats_repository.h b/common/repositories/adventure_stats_repository.h index 3330c84260..188e56214e 100644 --- a/common/repositories/adventure_stats_repository.h +++ b/common/repositories/adventure_stats_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_adventure_stats_repository.h" diff --git a/common/repositories/adventure_template_entry_flavor_repository.h b/common/repositories/adventure_template_entry_flavor_repository.h index d5624a0d46..a7742692fe 100644 --- a/common/repositories/adventure_template_entry_flavor_repository.h +++ b/common/repositories/adventure_template_entry_flavor_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_adventure_template_entry_flavor_repository.h" diff --git a/common/repositories/adventure_template_entry_repository.h b/common/repositories/adventure_template_entry_repository.h index 6b9b004fd3..35aa0300c7 100644 --- a/common/repositories/adventure_template_entry_repository.h +++ b/common/repositories/adventure_template_entry_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_adventure_template_entry_repository.h" diff --git a/common/repositories/adventure_template_repository.h b/common/repositories/adventure_template_repository.h index 50d5f74de2..1608809fbd 100644 --- a/common/repositories/adventure_template_repository.h +++ b/common/repositories/adventure_template_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_adventure_template_repository.h" diff --git a/common/repositories/alternate_currency_repository.h b/common/repositories/alternate_currency_repository.h index 2b616b1f22..bb19924534 100644 --- a/common/repositories/alternate_currency_repository.h +++ b/common/repositories/alternate_currency_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_alternate_currency_repository.h" diff --git a/common/repositories/auras_repository.h b/common/repositories/auras_repository.h index d118b2c02c..b154688c3d 100644 --- a/common/repositories/auras_repository.h +++ b/common/repositories/auras_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_auras_repository.h" diff --git a/common/repositories/base/base_aa_ability_repository.h b/common/repositories/base/base_aa_ability_repository.h index 7a3e2a8ee4..d02684cf4a 100644 --- a/common/repositories/base/base_aa_ability_repository.h +++ b/common/repositories/base/base_aa_ability_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_aa_rank_effects_repository.h b/common/repositories/base/base_aa_rank_effects_repository.h index 11418fef93..2bf56865ae 100644 --- a/common/repositories/base/base_aa_rank_effects_repository.h +++ b/common/repositories/base/base_aa_rank_effects_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_aa_rank_prereqs_repository.h b/common/repositories/base/base_aa_rank_prereqs_repository.h index 77b561f134..723686b9c8 100644 --- a/common/repositories/base/base_aa_rank_prereqs_repository.h +++ b/common/repositories/base/base_aa_rank_prereqs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_aa_ranks_repository.h b/common/repositories/base/base_aa_ranks_repository.h index d2cc845b3d..e3df331b84 100644 --- a/common/repositories/base/base_aa_ranks_repository.h +++ b/common/repositories/base/base_aa_ranks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_account_flags_repository.h b/common/repositories/base/base_account_flags_repository.h index 8c76b0b196..88573d31e8 100644 --- a/common/repositories/base/base_account_flags_repository.h +++ b/common/repositories/base/base_account_flags_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_account_ip_repository.h b/common/repositories/base/base_account_ip_repository.h index 58187baaa2..05fd42c539 100644 --- a/common/repositories/base/base_account_ip_repository.h +++ b/common/repositories/base/base_account_ip_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_account_repository.h b/common/repositories/base/base_account_repository.h index bdb613f25b..dd2c0c577f 100644 --- a/common/repositories/base/base_account_repository.h +++ b/common/repositories/base/base_account_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_account_rewards_repository.h b/common/repositories/base/base_account_rewards_repository.h index 2d4317db41..f3a3abb561 100644 --- a/common/repositories/base/base_account_rewards_repository.h +++ b/common/repositories/base/base_account_rewards_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_adventure_details_repository.h b/common/repositories/base/base_adventure_details_repository.h index 7874acf9ce..ce34d0d87f 100644 --- a/common/repositories/base/base_adventure_details_repository.h +++ b/common/repositories/base/base_adventure_details_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_adventure_members_repository.h b/common/repositories/base/base_adventure_members_repository.h index 3a6f004c02..4185a502c4 100644 --- a/common/repositories/base/base_adventure_members_repository.h +++ b/common/repositories/base/base_adventure_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_adventure_stats_repository.h b/common/repositories/base/base_adventure_stats_repository.h index f6d3d7e1e1..36849b5cf9 100644 --- a/common/repositories/base/base_adventure_stats_repository.h +++ b/common/repositories/base/base_adventure_stats_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_adventure_template_entry_flavor_repository.h b/common/repositories/base/base_adventure_template_entry_flavor_repository.h index bdfa80e577..a4a09c4b39 100644 --- a/common/repositories/base/base_adventure_template_entry_flavor_repository.h +++ b/common/repositories/base/base_adventure_template_entry_flavor_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_adventure_template_entry_repository.h b/common/repositories/base/base_adventure_template_entry_repository.h index 30d434490b..504ad01281 100644 --- a/common/repositories/base/base_adventure_template_entry_repository.h +++ b/common/repositories/base/base_adventure_template_entry_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_adventure_template_repository.h b/common/repositories/base/base_adventure_template_repository.h index fdbc9a3214..144b2dcbef 100644 --- a/common/repositories/base/base_adventure_template_repository.h +++ b/common/repositories/base/base_adventure_template_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_alternate_currency_repository.h b/common/repositories/base/base_alternate_currency_repository.h index a95f287895..23448feea0 100644 --- a/common/repositories/base/base_alternate_currency_repository.h +++ b/common/repositories/base/base_alternate_currency_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_auras_repository.h b/common/repositories/base/base_auras_repository.h index fd279538c8..f6844444bb 100644 --- a/common/repositories/base/base_auras_repository.h +++ b/common/repositories/base/base_auras_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_base_data_repository.h b/common/repositories/base/base_base_data_repository.h index 9430f757d2..06e66d7eba 100644 --- a/common/repositories/base/base_base_data_repository.h +++ b/common/repositories/base/base_base_data_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_blocked_spells_repository.h b/common/repositories/base/base_blocked_spells_repository.h index 7732db416e..6c9c81ba6e 100644 --- a/common/repositories/base/base_blocked_spells_repository.h +++ b/common/repositories/base/base_blocked_spells_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_books_repository.h b/common/repositories/base/base_books_repository.h index 46386a1b0f..2c8387e149 100644 --- a/common/repositories/base/base_books_repository.h +++ b/common/repositories/base/base_books_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_blocked_buffs_repository.h b/common/repositories/base/base_bot_blocked_buffs_repository.h index 2b0d7fef73..2b6b67ccf2 100644 --- a/common/repositories/base/base_bot_blocked_buffs_repository.h +++ b/common/repositories/base/base_bot_blocked_buffs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_buffs_repository.h b/common/repositories/base/base_bot_buffs_repository.h index 3a027509d7..1bc2df94a9 100644 --- a/common/repositories/base/base_bot_buffs_repository.h +++ b/common/repositories/base/base_bot_buffs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_create_combinations_repository.h b/common/repositories/base/base_bot_create_combinations_repository.h index 7b4563c3f7..f769168654 100644 --- a/common/repositories/base/base_bot_create_combinations_repository.h +++ b/common/repositories/base/base_bot_create_combinations_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_data_repository.h b/common/repositories/base/base_bot_data_repository.h index b0ef53ba30..fd8c2d1b10 100644 --- a/common/repositories/base/base_bot_data_repository.h +++ b/common/repositories/base/base_bot_data_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_group_members_repository.h b/common/repositories/base/base_bot_group_members_repository.h index 99d647862f..371aa40b24 100644 --- a/common/repositories/base/base_bot_group_members_repository.h +++ b/common/repositories/base/base_bot_group_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_groups_repository.h b/common/repositories/base/base_bot_groups_repository.h index da7986b79d..01591cf820 100644 --- a/common/repositories/base/base_bot_groups_repository.h +++ b/common/repositories/base/base_bot_groups_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_guild_members_repository.h b/common/repositories/base/base_bot_guild_members_repository.h index 3a192d81b3..170d172c35 100644 --- a/common/repositories/base/base_bot_guild_members_repository.h +++ b/common/repositories/base/base_bot_guild_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_heal_rotation_members_repository.h b/common/repositories/base/base_bot_heal_rotation_members_repository.h index a3b2bde695..5b4e42d8d9 100644 --- a/common/repositories/base/base_bot_heal_rotation_members_repository.h +++ b/common/repositories/base/base_bot_heal_rotation_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_heal_rotation_targets_repository.h b/common/repositories/base/base_bot_heal_rotation_targets_repository.h index 5064208896..5498fb08db 100644 --- a/common/repositories/base/base_bot_heal_rotation_targets_repository.h +++ b/common/repositories/base/base_bot_heal_rotation_targets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_heal_rotations_repository.h b/common/repositories/base/base_bot_heal_rotations_repository.h index a3d79410a3..5c2403ff16 100644 --- a/common/repositories/base/base_bot_heal_rotations_repository.h +++ b/common/repositories/base/base_bot_heal_rotations_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_inspect_messages_repository.h b/common/repositories/base/base_bot_inspect_messages_repository.h index 2c44c67306..ab11ab84cf 100644 --- a/common/repositories/base/base_bot_inspect_messages_repository.h +++ b/common/repositories/base/base_bot_inspect_messages_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_inventories_repository.h b/common/repositories/base/base_bot_inventories_repository.h index 97bb85e625..c3738e767b 100644 --- a/common/repositories/base/base_bot_inventories_repository.h +++ b/common/repositories/base/base_bot_inventories_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_owner_options_repository.h b/common/repositories/base/base_bot_owner_options_repository.h index 6f4f23b9aa..19f2139f64 100644 --- a/common/repositories/base/base_bot_owner_options_repository.h +++ b/common/repositories/base/base_bot_owner_options_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_pet_buffs_repository.h b/common/repositories/base/base_bot_pet_buffs_repository.h index c0d8c03a56..a2e00e08fd 100644 --- a/common/repositories/base/base_bot_pet_buffs_repository.h +++ b/common/repositories/base/base_bot_pet_buffs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_pet_inventories_repository.h b/common/repositories/base/base_bot_pet_inventories_repository.h index 4cf90a9ed7..930ba9e28b 100644 --- a/common/repositories/base/base_bot_pet_inventories_repository.h +++ b/common/repositories/base/base_bot_pet_inventories_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_pets_repository.h b/common/repositories/base/base_bot_pets_repository.h index 993c2900b6..d782022022 100644 --- a/common/repositories/base/base_bot_pets_repository.h +++ b/common/repositories/base/base_bot_pets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_settings_repository.h b/common/repositories/base/base_bot_settings_repository.h index 44e7964acb..aebc5c8d9a 100644 --- a/common/repositories/base/base_bot_settings_repository.h +++ b/common/repositories/base/base_bot_settings_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_spell_casting_chances_repository.h b/common/repositories/base/base_bot_spell_casting_chances_repository.h index 318941f891..efb2742c8a 100644 --- a/common/repositories/base/base_bot_spell_casting_chances_repository.h +++ b/common/repositories/base/base_bot_spell_casting_chances_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_spell_settings_repository.h b/common/repositories/base/base_bot_spell_settings_repository.h index 5bb5c16153..a70bf41e08 100644 --- a/common/repositories/base/base_bot_spell_settings_repository.h +++ b/common/repositories/base/base_bot_spell_settings_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_spells_entries_repository.h b/common/repositories/base/base_bot_spells_entries_repository.h index a564fbeb46..45ae3c7960 100644 --- a/common/repositories/base/base_bot_spells_entries_repository.h +++ b/common/repositories/base/base_bot_spells_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_stances_repository.h b/common/repositories/base/base_bot_stances_repository.h index af452b115c..638bc76577 100644 --- a/common/repositories/base/base_bot_stances_repository.h +++ b/common/repositories/base/base_bot_stances_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_starting_items_repository.h b/common/repositories/base/base_bot_starting_items_repository.h index 2704af4094..dddd9be36f 100644 --- a/common/repositories/base/base_bot_starting_items_repository.h +++ b/common/repositories/base/base_bot_starting_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bot_timers_repository.h b/common/repositories/base/base_bot_timers_repository.h index 5d22f7ddc9..44484da8d2 100644 --- a/common/repositories/base/base_bot_timers_repository.h +++ b/common/repositories/base/base_bot_timers_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bug_reports_repository.h b/common/repositories/base/base_bug_reports_repository.h index dca4961da9..a264be42b1 100644 --- a/common/repositories/base/base_bug_reports_repository.h +++ b/common/repositories/base/base_bug_reports_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_bugs_repository.h b/common/repositories/base/base_bugs_repository.h index 3a8bd261bb..e6fd67457a 100644 --- a/common/repositories/base/base_bugs_repository.h +++ b/common/repositories/base/base_bugs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_buyer_buy_lines_repository.h b/common/repositories/base/base_buyer_buy_lines_repository.h index e6b2709c4f..382cf2926a 100644 --- a/common/repositories/base/base_buyer_buy_lines_repository.h +++ b/common/repositories/base/base_buyer_buy_lines_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_buyer_repository.h b/common/repositories/base/base_buyer_repository.h index 9d7315644e..1c171c5538 100644 --- a/common/repositories/base/base_buyer_repository.h +++ b/common/repositories/base/base_buyer_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_buyer_trade_items_repository.h b/common/repositories/base/base_buyer_trade_items_repository.h index b2904d76a7..741bf81734 100644 --- a/common/repositories/base/base_buyer_trade_items_repository.h +++ b/common/repositories/base/base_buyer_trade_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_char_create_combinations_repository.h b/common/repositories/base/base_char_create_combinations_repository.h index b6a7a4d16c..886d563a96 100644 --- a/common/repositories/base/base_char_create_combinations_repository.h +++ b/common/repositories/base/base_char_create_combinations_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_char_create_point_allocations_repository.h b/common/repositories/base/base_char_create_point_allocations_repository.h index 74187e650a..f8848fb59e 100644 --- a/common/repositories/base/base_char_create_point_allocations_repository.h +++ b/common/repositories/base/base_char_create_point_allocations_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_char_recipe_list_repository.h b/common/repositories/base/base_char_recipe_list_repository.h index 0db11317da..3aa972cb95 100644 --- a/common/repositories/base/base_char_recipe_list_repository.h +++ b/common/repositories/base/base_char_recipe_list_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_activities_repository.h b/common/repositories/base/base_character_activities_repository.h index 5e3e28a33a..6047e07dc4 100644 --- a/common/repositories/base/base_character_activities_repository.h +++ b/common/repositories/base/base_character_activities_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_alt_currency_repository.h b/common/repositories/base/base_character_alt_currency_repository.h index a037b26f82..fda23b49e7 100644 --- a/common/repositories/base/base_character_alt_currency_repository.h +++ b/common/repositories/base/base_character_alt_currency_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_alternate_abilities_repository.h b/common/repositories/base/base_character_alternate_abilities_repository.h index b02aed7b5c..20a4d1de9c 100644 --- a/common/repositories/base/base_character_alternate_abilities_repository.h +++ b/common/repositories/base/base_character_alternate_abilities_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_auras_repository.h b/common/repositories/base/base_character_auras_repository.h index cddce43558..096c43ee18 100644 --- a/common/repositories/base/base_character_auras_repository.h +++ b/common/repositories/base/base_character_auras_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_bandolier_repository.h b/common/repositories/base/base_character_bandolier_repository.h index 38dbc2c731..67e5f14d44 100644 --- a/common/repositories/base/base_character_bandolier_repository.h +++ b/common/repositories/base/base_character_bandolier_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_bind_repository.h b/common/repositories/base/base_character_bind_repository.h index 3140b02655..732349e395 100644 --- a/common/repositories/base/base_character_bind_repository.h +++ b/common/repositories/base/base_character_bind_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_buffs_repository.h b/common/repositories/base/base_character_buffs_repository.h index 90003f7467..c7a7964110 100644 --- a/common/repositories/base/base_character_buffs_repository.h +++ b/common/repositories/base/base_character_buffs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_corpse_items_repository.h b/common/repositories/base/base_character_corpse_items_repository.h index 3fc5aa8421..4a6dea7c56 100644 --- a/common/repositories/base/base_character_corpse_items_repository.h +++ b/common/repositories/base/base_character_corpse_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_corpses_repository.h b/common/repositories/base/base_character_corpses_repository.h index 814f7ecda2..899090c446 100644 --- a/common/repositories/base/base_character_corpses_repository.h +++ b/common/repositories/base/base_character_corpses_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_currency_repository.h b/common/repositories/base/base_character_currency_repository.h index bf0a19adca..0e52392429 100644 --- a/common/repositories/base/base_character_currency_repository.h +++ b/common/repositories/base/base_character_currency_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_data_repository.h b/common/repositories/base/base_character_data_repository.h index 0eab216a01..ec2b4c8bb1 100644 --- a/common/repositories/base/base_character_data_repository.h +++ b/common/repositories/base/base_character_data_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_disciplines_repository.h b/common/repositories/base/base_character_disciplines_repository.h index b03a9eaa53..85e3bd8c55 100644 --- a/common/repositories/base/base_character_disciplines_repository.h +++ b/common/repositories/base/base_character_disciplines_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_evolving_items_repository.h b/common/repositories/base/base_character_evolving_items_repository.h index 0d3fd01003..18b0a2f82d 100644 --- a/common/repositories/base/base_character_evolving_items_repository.h +++ b/common/repositories/base/base_character_evolving_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_exp_modifiers_repository.h b/common/repositories/base/base_character_exp_modifiers_repository.h index 5203c0c162..a627b432a6 100644 --- a/common/repositories/base/base_character_exp_modifiers_repository.h +++ b/common/repositories/base/base_character_exp_modifiers_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_expedition_lockouts_repository.h b/common/repositories/base/base_character_expedition_lockouts_repository.h index 8b78859f5d..68927da41d 100644 --- a/common/repositories/base/base_character_expedition_lockouts_repository.h +++ b/common/repositories/base/base_character_expedition_lockouts_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_inspect_messages_repository.h b/common/repositories/base/base_character_inspect_messages_repository.h index c4d6961bf0..704af67826 100644 --- a/common/repositories/base/base_character_inspect_messages_repository.h +++ b/common/repositories/base/base_character_inspect_messages_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_instance_safereturns_repository.h b/common/repositories/base/base_character_instance_safereturns_repository.h index 2019637494..4041e94d7f 100644 --- a/common/repositories/base/base_character_instance_safereturns_repository.h +++ b/common/repositories/base/base_character_instance_safereturns_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_item_recast_repository.h b/common/repositories/base/base_character_item_recast_repository.h index c144ed8a38..fe4073c2be 100644 --- a/common/repositories/base/base_character_item_recast_repository.h +++ b/common/repositories/base/base_character_item_recast_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_languages_repository.h b/common/repositories/base/base_character_languages_repository.h index 7007f98c78..31be49b7da 100644 --- a/common/repositories/base/base_character_languages_repository.h +++ b/common/repositories/base/base_character_languages_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_leadership_abilities_repository.h b/common/repositories/base/base_character_leadership_abilities_repository.h index bd2557fb71..81eea9c9d3 100644 --- a/common/repositories/base/base_character_leadership_abilities_repository.h +++ b/common/repositories/base/base_character_leadership_abilities_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_material_repository.h b/common/repositories/base/base_character_material_repository.h index 1de976453b..e33d1ae40b 100644 --- a/common/repositories/base/base_character_material_repository.h +++ b/common/repositories/base/base_character_material_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_memmed_spells_repository.h b/common/repositories/base/base_character_memmed_spells_repository.h index 6c824a6a6a..ef99ba9ef1 100644 --- a/common/repositories/base/base_character_memmed_spells_repository.h +++ b/common/repositories/base/base_character_memmed_spells_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_parcels_containers_repository.h b/common/repositories/base/base_character_parcels_containers_repository.h index 668fc9e30b..cbc972d325 100644 --- a/common/repositories/base/base_character_parcels_containers_repository.h +++ b/common/repositories/base/base_character_parcels_containers_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_parcels_repository.h b/common/repositories/base/base_character_parcels_repository.h index bc5934c7d5..c99ddd151c 100644 --- a/common/repositories/base/base_character_parcels_repository.h +++ b/common/repositories/base/base_character_parcels_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_peqzone_flags_repository.h b/common/repositories/base/base_character_peqzone_flags_repository.h index ab6d128b3f..f22bb10fb0 100644 --- a/common/repositories/base/base_character_peqzone_flags_repository.h +++ b/common/repositories/base/base_character_peqzone_flags_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_pet_buffs_repository.h b/common/repositories/base/base_character_pet_buffs_repository.h index 74f0b1ec40..b977fa7cac 100644 --- a/common/repositories/base/base_character_pet_buffs_repository.h +++ b/common/repositories/base/base_character_pet_buffs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_pet_info_repository.h b/common/repositories/base/base_character_pet_info_repository.h index c3037d0177..835c9e6554 100644 --- a/common/repositories/base/base_character_pet_info_repository.h +++ b/common/repositories/base/base_character_pet_info_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_pet_inventory_repository.h b/common/repositories/base/base_character_pet_inventory_repository.h index 15292a517d..f172fc4cbe 100644 --- a/common/repositories/base/base_character_pet_inventory_repository.h +++ b/common/repositories/base/base_character_pet_inventory_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_pet_name_repository.h b/common/repositories/base/base_character_pet_name_repository.h index 69585ab43a..315fc3882f 100644 --- a/common/repositories/base/base_character_pet_name_repository.h +++ b/common/repositories/base/base_character_pet_name_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_potionbelt_repository.h b/common/repositories/base/base_character_potionbelt_repository.h index acf710c37a..c44b2dff4e 100644 --- a/common/repositories/base/base_character_potionbelt_repository.h +++ b/common/repositories/base/base_character_potionbelt_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_skills_repository.h b/common/repositories/base/base_character_skills_repository.h index a4620eb156..ecbc64e242 100644 --- a/common/repositories/base/base_character_skills_repository.h +++ b/common/repositories/base/base_character_skills_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_spells_repository.h b/common/repositories/base/base_character_spells_repository.h index 58179ad3aa..c70c79a6ae 100644 --- a/common/repositories/base/base_character_spells_repository.h +++ b/common/repositories/base/base_character_spells_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_stats_record_repository.h b/common/repositories/base/base_character_stats_record_repository.h index 141d7f61ba..1061191a8d 100644 --- a/common/repositories/base/base_character_stats_record_repository.h +++ b/common/repositories/base/base_character_stats_record_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_task_timers_repository.h b/common/repositories/base/base_character_task_timers_repository.h index 6d9880bd08..1ca534454c 100644 --- a/common/repositories/base/base_character_task_timers_repository.h +++ b/common/repositories/base/base_character_task_timers_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_tasks_repository.h b/common/repositories/base/base_character_tasks_repository.h index 1b9154cd38..f38e3502a0 100644 --- a/common/repositories/base/base_character_tasks_repository.h +++ b/common/repositories/base/base_character_tasks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_character_tribute_repository.h b/common/repositories/base/base_character_tribute_repository.h index 2c9a51c3bf..b1089b7b1d 100644 --- a/common/repositories/base/base_character_tribute_repository.h +++ b/common/repositories/base/base_character_tribute_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_chatchannel_reserved_names_repository.h b/common/repositories/base/base_chatchannel_reserved_names_repository.h index 674434677a..aa0c2a1459 100644 --- a/common/repositories/base/base_chatchannel_reserved_names_repository.h +++ b/common/repositories/base/base_chatchannel_reserved_names_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_chatchannels_repository.h b/common/repositories/base/base_chatchannels_repository.h index 29bba05028..27fc0a06c8 100644 --- a/common/repositories/base/base_chatchannels_repository.h +++ b/common/repositories/base/base_chatchannels_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_command_subsettings_repository.h b/common/repositories/base/base_command_subsettings_repository.h index ef5b030ea4..4b59e6d3a2 100644 --- a/common/repositories/base/base_command_subsettings_repository.h +++ b/common/repositories/base/base_command_subsettings_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_completed_shared_task_activity_state_repository.h b/common/repositories/base/base_completed_shared_task_activity_state_repository.h index d97f7b4583..47e152c21a 100644 --- a/common/repositories/base/base_completed_shared_task_activity_state_repository.h +++ b/common/repositories/base/base_completed_shared_task_activity_state_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_completed_shared_task_members_repository.h b/common/repositories/base/base_completed_shared_task_members_repository.h index a476dfc23f..abdbf0a126 100644 --- a/common/repositories/base/base_completed_shared_task_members_repository.h +++ b/common/repositories/base/base_completed_shared_task_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_completed_shared_tasks_repository.h b/common/repositories/base/base_completed_shared_tasks_repository.h index ad90a02208..56964eec68 100644 --- a/common/repositories/base/base_completed_shared_tasks_repository.h +++ b/common/repositories/base/base_completed_shared_tasks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_completed_tasks_repository.h b/common/repositories/base/base_completed_tasks_repository.h index 33870e3638..2d7cf7421d 100644 --- a/common/repositories/base/base_completed_tasks_repository.h +++ b/common/repositories/base/base_completed_tasks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_content_flags_repository.h b/common/repositories/base/base_content_flags_repository.h index 7b89bf4326..8c20fa1a7f 100644 --- a/common/repositories/base/base_content_flags_repository.h +++ b/common/repositories/base/base_content_flags_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_damageshieldtypes_repository.h b/common/repositories/base/base_damageshieldtypes_repository.h index b373ebc5ec..10f64037b5 100644 --- a/common/repositories/base/base_damageshieldtypes_repository.h +++ b/common/repositories/base/base_damageshieldtypes_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_data_buckets_repository.h b/common/repositories/base/base_data_buckets_repository.h index 54e4d4c99a..5026e1aff7 100644 --- a/common/repositories/base/base_data_buckets_repository.h +++ b/common/repositories/base/base_data_buckets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_db_str_repository.h b/common/repositories/base/base_db_str_repository.h index bb6a8b84bb..e1ace1f643 100644 --- a/common/repositories/base/base_db_str_repository.h +++ b/common/repositories/base/base_db_str_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_discord_webhooks_repository.h b/common/repositories/base/base_discord_webhooks_repository.h index c4f0244701..7404024b35 100644 --- a/common/repositories/base/base_discord_webhooks_repository.h +++ b/common/repositories/base/base_discord_webhooks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_discovered_items_repository.h b/common/repositories/base/base_discovered_items_repository.h index d6f08d503a..8f71e4cc42 100644 --- a/common/repositories/base/base_discovered_items_repository.h +++ b/common/repositories/base/base_discovered_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_doors_repository.h b/common/repositories/base/base_doors_repository.h index 8887b4fe9e..665c963211 100644 --- a/common/repositories/base/base_doors_repository.h +++ b/common/repositories/base/base_doors_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_dynamic_zone_lockouts_repository.h b/common/repositories/base/base_dynamic_zone_lockouts_repository.h index 1e1f5268f3..c7ad25b201 100644 --- a/common/repositories/base/base_dynamic_zone_lockouts_repository.h +++ b/common/repositories/base/base_dynamic_zone_lockouts_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_dynamic_zone_members_repository.h b/common/repositories/base/base_dynamic_zone_members_repository.h index ce7d0e8887..9556057d60 100644 --- a/common/repositories/base/base_dynamic_zone_members_repository.h +++ b/common/repositories/base/base_dynamic_zone_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_dynamic_zone_templates_repository.h b/common/repositories/base/base_dynamic_zone_templates_repository.h index c1a59058d1..502ed677a2 100644 --- a/common/repositories/base/base_dynamic_zone_templates_repository.h +++ b/common/repositories/base/base_dynamic_zone_templates_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_dynamic_zones_repository.h b/common/repositories/base/base_dynamic_zones_repository.h index 921b333e5d..5224050d7c 100644 --- a/common/repositories/base/base_dynamic_zones_repository.h +++ b/common/repositories/base/base_dynamic_zones_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_faction_association_repository.h b/common/repositories/base/base_faction_association_repository.h index df5a1139ce..34bd3993da 100644 --- a/common/repositories/base/base_faction_association_repository.h +++ b/common/repositories/base/base_faction_association_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_faction_base_data_repository.h b/common/repositories/base/base_faction_base_data_repository.h index 1d05928713..7d1dcec6e5 100644 --- a/common/repositories/base/base_faction_base_data_repository.h +++ b/common/repositories/base/base_faction_base_data_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_faction_list_mod_repository.h b/common/repositories/base/base_faction_list_mod_repository.h index ab41df8741..f6611a1499 100644 --- a/common/repositories/base/base_faction_list_mod_repository.h +++ b/common/repositories/base/base_faction_list_mod_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_faction_list_repository.h b/common/repositories/base/base_faction_list_repository.h index 411745a186..7c9b018843 100644 --- a/common/repositories/base/base_faction_list_repository.h +++ b/common/repositories/base/base_faction_list_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_faction_values_repository.h b/common/repositories/base/base_faction_values_repository.h index b5591c917b..90f42d2831 100644 --- a/common/repositories/base/base_faction_values_repository.h +++ b/common/repositories/base/base_faction_values_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_fishing_repository.h b/common/repositories/base/base_fishing_repository.h index 6666ab5cc5..16aa10c8dc 100644 --- a/common/repositories/base/base_fishing_repository.h +++ b/common/repositories/base/base_fishing_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_forage_repository.h b/common/repositories/base/base_forage_repository.h index e855dace26..1869494a11 100644 --- a/common/repositories/base/base_forage_repository.h +++ b/common/repositories/base/base_forage_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_friends_repository.h b/common/repositories/base/base_friends_repository.h index 7c5ed52d85..59b4f65294 100644 --- a/common/repositories/base/base_friends_repository.h +++ b/common/repositories/base/base_friends_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_global_loot_repository.h b/common/repositories/base/base_global_loot_repository.h index 4976d0cdf6..43f69cb2a3 100644 --- a/common/repositories/base/base_global_loot_repository.h +++ b/common/repositories/base/base_global_loot_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_gm_ips_repository.h b/common/repositories/base/base_gm_ips_repository.h index 411396188a..05b254e1ac 100644 --- a/common/repositories/base/base_gm_ips_repository.h +++ b/common/repositories/base/base_gm_ips_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_graveyard_repository.h b/common/repositories/base/base_graveyard_repository.h index 8635e63497..5601288875 100644 --- a/common/repositories/base/base_graveyard_repository.h +++ b/common/repositories/base/base_graveyard_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_grid_entries_repository.h b/common/repositories/base/base_grid_entries_repository.h index f048db6437..55f3150e5c 100644 --- a/common/repositories/base/base_grid_entries_repository.h +++ b/common/repositories/base/base_grid_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_grid_repository.h b/common/repositories/base/base_grid_repository.h index 623f1c8b77..fedc51ea85 100644 --- a/common/repositories/base/base_grid_repository.h +++ b/common/repositories/base/base_grid_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_ground_spawns_repository.h b/common/repositories/base/base_ground_spawns_repository.h index 83d3d2722f..dece74057e 100644 --- a/common/repositories/base/base_ground_spawns_repository.h +++ b/common/repositories/base/base_ground_spawns_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_group_id_repository.h b/common/repositories/base/base_group_id_repository.h index 78211e437e..829ab60a6c 100644 --- a/common/repositories/base/base_group_id_repository.h +++ b/common/repositories/base/base_group_id_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_group_leaders_repository.h b/common/repositories/base/base_group_leaders_repository.h index 3a61ddd5cf..8520ac5a9e 100644 --- a/common/repositories/base/base_group_leaders_repository.h +++ b/common/repositories/base/base_group_leaders_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_guild_bank_repository.h b/common/repositories/base/base_guild_bank_repository.h index a8fc38a255..8af5859816 100644 --- a/common/repositories/base/base_guild_bank_repository.h +++ b/common/repositories/base/base_guild_bank_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_guild_members_repository.h b/common/repositories/base/base_guild_members_repository.h index fe7946b533..d66acd2026 100644 --- a/common/repositories/base/base_guild_members_repository.h +++ b/common/repositories/base/base_guild_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_guild_permissions_repository.h b/common/repositories/base/base_guild_permissions_repository.h index c435b3ba1e..10e33355b5 100644 --- a/common/repositories/base/base_guild_permissions_repository.h +++ b/common/repositories/base/base_guild_permissions_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_guild_ranks_repository.h b/common/repositories/base/base_guild_ranks_repository.h index 2e4cedefe9..d628f31080 100644 --- a/common/repositories/base/base_guild_ranks_repository.h +++ b/common/repositories/base/base_guild_ranks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_guild_relations_repository.h b/common/repositories/base/base_guild_relations_repository.h index 9957f0b003..927299cd82 100644 --- a/common/repositories/base/base_guild_relations_repository.h +++ b/common/repositories/base/base_guild_relations_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_guild_tributes_repository.h b/common/repositories/base/base_guild_tributes_repository.h index 13cffce11f..836c7dd1e5 100644 --- a/common/repositories/base/base_guild_tributes_repository.h +++ b/common/repositories/base/base_guild_tributes_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_guilds_repository.h b/common/repositories/base/base_guilds_repository.h index df7b2d40c2..ac5deea59e 100644 --- a/common/repositories/base/base_guilds_repository.h +++ b/common/repositories/base/base_guilds_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_horses_repository.h b/common/repositories/base/base_horses_repository.h index 172b279fd2..f3a89580fe 100644 --- a/common/repositories/base/base_horses_repository.h +++ b/common/repositories/base/base_horses_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_instance_list_player_repository.h b/common/repositories/base/base_instance_list_player_repository.h index 6e16b800d3..1f09dd7a6b 100644 --- a/common/repositories/base/base_instance_list_player_repository.h +++ b/common/repositories/base/base_instance_list_player_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_instance_list_repository.h b/common/repositories/base/base_instance_list_repository.h index 381ea04f43..f069431e60 100644 --- a/common/repositories/base/base_instance_list_repository.h +++ b/common/repositories/base/base_instance_list_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_inventory_repository.h b/common/repositories/base/base_inventory_repository.h index f1e325d5fe..92d8aba0aa 100644 --- a/common/repositories/base/base_inventory_repository.h +++ b/common/repositories/base/base_inventory_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_inventory_snapshots_repository.h b/common/repositories/base/base_inventory_snapshots_repository.h index 08b162a0c9..50df6bb329 100644 --- a/common/repositories/base/base_inventory_snapshots_repository.h +++ b/common/repositories/base/base_inventory_snapshots_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_ip_exemptions_repository.h b/common/repositories/base/base_ip_exemptions_repository.h index d4de8c3414..3ba746d8d2 100644 --- a/common/repositories/base/base_ip_exemptions_repository.h +++ b/common/repositories/base/base_ip_exemptions_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_items_evolving_details_repository.h b/common/repositories/base/base_items_evolving_details_repository.h index 7ba6e6ba28..53bfb9ebe7 100644 --- a/common/repositories/base/base_items_evolving_details_repository.h +++ b/common/repositories/base/base_items_evolving_details_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_items_repository.h b/common/repositories/base/base_items_repository.h index 35f856de23..4d52256578 100644 --- a/common/repositories/base/base_items_repository.h +++ b/common/repositories/base/base_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_keyring_repository.h b/common/repositories/base/base_keyring_repository.h index 7ded4d9cd9..31724c882b 100644 --- a/common/repositories/base/base_keyring_repository.h +++ b/common/repositories/base/base_keyring_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_launcher_repository.h b/common/repositories/base/base_launcher_repository.h index 1d27c40148..7e028c2f95 100644 --- a/common/repositories/base/base_launcher_repository.h +++ b/common/repositories/base/base_launcher_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * This repository was automatically generated and is NOT to be modified directly. * Any repository modifications are meant to be made to diff --git a/common/repositories/base/base_ldon_trap_entries_repository.h b/common/repositories/base/base_ldon_trap_entries_repository.h index 4a01bdcca5..d48de7dc18 100644 --- a/common/repositories/base/base_ldon_trap_entries_repository.h +++ b/common/repositories/base/base_ldon_trap_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_ldon_trap_templates_repository.h b/common/repositories/base/base_ldon_trap_templates_repository.h index 926e56eec6..d860e5eab7 100644 --- a/common/repositories/base/base_ldon_trap_templates_repository.h +++ b/common/repositories/base/base_ldon_trap_templates_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_level_exp_mods_repository.h b/common/repositories/base/base_level_exp_mods_repository.h index aba92dfb0b..cb027224ab 100644 --- a/common/repositories/base/base_level_exp_mods_repository.h +++ b/common/repositories/base/base_level_exp_mods_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_lfguild_repository.h b/common/repositories/base/base_lfguild_repository.h index 80fc98dfa2..945ac9fd1c 100644 --- a/common/repositories/base/base_lfguild_repository.h +++ b/common/repositories/base/base_lfguild_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_login_accounts_repository.h b/common/repositories/base/base_login_accounts_repository.h index 16e0669843..0917f2b8b3 100644 --- a/common/repositories/base/base_login_accounts_repository.h +++ b/common/repositories/base/base_login_accounts_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_login_api_tokens_repository.h b/common/repositories/base/base_login_api_tokens_repository.h index 4192dc189a..cc2cf344ad 100644 --- a/common/repositories/base/base_login_api_tokens_repository.h +++ b/common/repositories/base/base_login_api_tokens_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_login_server_admins_repository.h b/common/repositories/base/base_login_server_admins_repository.h index 9d944713b1..e68bd895a9 100644 --- a/common/repositories/base/base_login_server_admins_repository.h +++ b/common/repositories/base/base_login_server_admins_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_login_server_list_types_repository.h b/common/repositories/base/base_login_server_list_types_repository.h index 76cd2c1953..8edf87f506 100644 --- a/common/repositories/base/base_login_server_list_types_repository.h +++ b/common/repositories/base/base_login_server_list_types_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_login_world_servers_repository.h b/common/repositories/base/base_login_world_servers_repository.h index 9638d5426e..12b7ba5ae7 100644 --- a/common/repositories/base/base_login_world_servers_repository.h +++ b/common/repositories/base/base_login_world_servers_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_logsys_categories_repository.h b/common/repositories/base/base_logsys_categories_repository.h index 9b95303bad..2902a91b70 100644 --- a/common/repositories/base/base_logsys_categories_repository.h +++ b/common/repositories/base/base_logsys_categories_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_lootdrop_entries_repository.h b/common/repositories/base/base_lootdrop_entries_repository.h index 9367f2e00a..f53c2272b7 100644 --- a/common/repositories/base/base_lootdrop_entries_repository.h +++ b/common/repositories/base/base_lootdrop_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_lootdrop_repository.h b/common/repositories/base/base_lootdrop_repository.h index ee62570078..464bbe51b4 100644 --- a/common/repositories/base/base_lootdrop_repository.h +++ b/common/repositories/base/base_lootdrop_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_loottable_entries_repository.h b/common/repositories/base/base_loottable_entries_repository.h index 3a65418fec..67792335ee 100644 --- a/common/repositories/base/base_loottable_entries_repository.h +++ b/common/repositories/base/base_loottable_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_loottable_repository.h b/common/repositories/base/base_loottable_repository.h index 63149805ee..522f0d1d20 100644 --- a/common/repositories/base/base_loottable_repository.h +++ b/common/repositories/base/base_loottable_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_mail_repository.h b/common/repositories/base/base_mail_repository.h index 0f446a37d5..a6ffac3ea4 100644 --- a/common/repositories/base/base_mail_repository.h +++ b/common/repositories/base/base_mail_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_armorinfo_repository.h b/common/repositories/base/base_merc_armorinfo_repository.h index c74dac0d32..d405b7cb21 100644 --- a/common/repositories/base/base_merc_armorinfo_repository.h +++ b/common/repositories/base/base_merc_armorinfo_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_buffs_repository.h b/common/repositories/base/base_merc_buffs_repository.h index 21f19a61a8..d7d786c4e1 100644 --- a/common/repositories/base/base_merc_buffs_repository.h +++ b/common/repositories/base/base_merc_buffs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_inventory_repository.h b/common/repositories/base/base_merc_inventory_repository.h index c255be8e49..25e0255715 100644 --- a/common/repositories/base/base_merc_inventory_repository.h +++ b/common/repositories/base/base_merc_inventory_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_merchant_entries_repository.h b/common/repositories/base/base_merc_merchant_entries_repository.h index 1e91e9d742..381bddb594 100644 --- a/common/repositories/base/base_merc_merchant_entries_repository.h +++ b/common/repositories/base/base_merc_merchant_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_merchant_template_entries_repository.h b/common/repositories/base/base_merc_merchant_template_entries_repository.h index ec08beb1a3..40383cdaaa 100644 --- a/common/repositories/base/base_merc_merchant_template_entries_repository.h +++ b/common/repositories/base/base_merc_merchant_template_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_merchant_templates_repository.h b/common/repositories/base/base_merc_merchant_templates_repository.h index 516fee5940..87178b74ab 100644 --- a/common/repositories/base/base_merc_merchant_templates_repository.h +++ b/common/repositories/base/base_merc_merchant_templates_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_name_types_repository.h b/common/repositories/base/base_merc_name_types_repository.h index 5966971b87..0d3d1a92d1 100644 --- a/common/repositories/base/base_merc_name_types_repository.h +++ b/common/repositories/base/base_merc_name_types_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_npc_types_repository.h b/common/repositories/base/base_merc_npc_types_repository.h index 78b7dc8749..450796eb93 100644 --- a/common/repositories/base/base_merc_npc_types_repository.h +++ b/common/repositories/base/base_merc_npc_types_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_spell_list_entries_repository.h b/common/repositories/base/base_merc_spell_list_entries_repository.h index 4e99585cbf..2cd80dc491 100644 --- a/common/repositories/base/base_merc_spell_list_entries_repository.h +++ b/common/repositories/base/base_merc_spell_list_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_spell_lists_repository.h b/common/repositories/base/base_merc_spell_lists_repository.h index c8ee56fb33..43d2cd03fa 100644 --- a/common/repositories/base/base_merc_spell_lists_repository.h +++ b/common/repositories/base/base_merc_spell_lists_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_stance_entries_repository.h b/common/repositories/base/base_merc_stance_entries_repository.h index 7eeb3edec8..9964611098 100644 --- a/common/repositories/base/base_merc_stance_entries_repository.h +++ b/common/repositories/base/base_merc_stance_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_stats_repository.h b/common/repositories/base/base_merc_stats_repository.h index 0730bd4215..df6c5d856e 100644 --- a/common/repositories/base/base_merc_stats_repository.h +++ b/common/repositories/base/base_merc_stats_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_subtypes_repository.h b/common/repositories/base/base_merc_subtypes_repository.h index 20272f27dd..421dbdac5c 100644 --- a/common/repositories/base/base_merc_subtypes_repository.h +++ b/common/repositories/base/base_merc_subtypes_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_templates_repository.h b/common/repositories/base/base_merc_templates_repository.h index 21444159a1..de4bef1349 100644 --- a/common/repositories/base/base_merc_templates_repository.h +++ b/common/repositories/base/base_merc_templates_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_types_repository.h b/common/repositories/base/base_merc_types_repository.h index 84c0fa791f..cb4a636517 100644 --- a/common/repositories/base/base_merc_types_repository.h +++ b/common/repositories/base/base_merc_types_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merc_weaponinfo_repository.h b/common/repositories/base/base_merc_weaponinfo_repository.h index ea509095ef..7f0f87b39d 100644 --- a/common/repositories/base/base_merc_weaponinfo_repository.h +++ b/common/repositories/base/base_merc_weaponinfo_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merchantlist_repository.h b/common/repositories/base/base_merchantlist_repository.h index f54a8fdfea..e7b952ac95 100644 --- a/common/repositories/base/base_merchantlist_repository.h +++ b/common/repositories/base/base_merchantlist_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_merchantlist_temp_repository.h b/common/repositories/base/base_merchantlist_temp_repository.h index 884356072d..3b792b90e5 100644 --- a/common/repositories/base/base_merchantlist_temp_repository.h +++ b/common/repositories/base/base_merchantlist_temp_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_mercs_repository.h b/common/repositories/base/base_mercs_repository.h index 6592715857..1289479911 100644 --- a/common/repositories/base/base_mercs_repository.h +++ b/common/repositories/base/base_mercs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_name_filter_repository.h b/common/repositories/base/base_name_filter_repository.h index 973b972d62..396a1f778b 100644 --- a/common/repositories/base/base_name_filter_repository.h +++ b/common/repositories/base/base_name_filter_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_npc_emotes_repository.h b/common/repositories/base/base_npc_emotes_repository.h index 301ea98851..1d0080ccc4 100644 --- a/common/repositories/base/base_npc_emotes_repository.h +++ b/common/repositories/base/base_npc_emotes_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_npc_faction_entries_repository.h b/common/repositories/base/base_npc_faction_entries_repository.h index 7ade2668b3..8ca3eded9f 100644 --- a/common/repositories/base/base_npc_faction_entries_repository.h +++ b/common/repositories/base/base_npc_faction_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_npc_faction_repository.h b/common/repositories/base/base_npc_faction_repository.h index d7f6d223a7..65cab20e43 100644 --- a/common/repositories/base/base_npc_faction_repository.h +++ b/common/repositories/base/base_npc_faction_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_npc_scale_global_base_repository.h b/common/repositories/base/base_npc_scale_global_base_repository.h index 78bf0e7c40..fd3df3c430 100644 --- a/common/repositories/base/base_npc_scale_global_base_repository.h +++ b/common/repositories/base/base_npc_scale_global_base_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_npc_spells_effects_entries_repository.h b/common/repositories/base/base_npc_spells_effects_entries_repository.h index 02bd46c40c..f4103aed36 100644 --- a/common/repositories/base/base_npc_spells_effects_entries_repository.h +++ b/common/repositories/base/base_npc_spells_effects_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_npc_spells_effects_repository.h b/common/repositories/base/base_npc_spells_effects_repository.h index c2f11f6332..1a6893fc65 100644 --- a/common/repositories/base/base_npc_spells_effects_repository.h +++ b/common/repositories/base/base_npc_spells_effects_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_npc_spells_entries_repository.h b/common/repositories/base/base_npc_spells_entries_repository.h index 129255ee58..fcb8887fa9 100644 --- a/common/repositories/base/base_npc_spells_entries_repository.h +++ b/common/repositories/base/base_npc_spells_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_npc_spells_repository.h b/common/repositories/base/base_npc_spells_repository.h index 558f2bc256..74a528afdc 100644 --- a/common/repositories/base/base_npc_spells_repository.h +++ b/common/repositories/base/base_npc_spells_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_npc_types_repository.h b/common/repositories/base/base_npc_types_repository.h index e42af292e8..9d99a72e45 100644 --- a/common/repositories/base/base_npc_types_repository.h +++ b/common/repositories/base/base_npc_types_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_npc_types_tint_repository.h b/common/repositories/base/base_npc_types_tint_repository.h index f9766c1848..db1fafd74b 100644 --- a/common/repositories/base/base_npc_types_tint_repository.h +++ b/common/repositories/base/base_npc_types_tint_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_object_contents_repository.h b/common/repositories/base/base_object_contents_repository.h index a9142cb268..8459702073 100644 --- a/common/repositories/base/base_object_contents_repository.h +++ b/common/repositories/base/base_object_contents_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_object_repository.h b/common/repositories/base/base_object_repository.h index 7d360988d1..53b4efb210 100644 --- a/common/repositories/base/base_object_repository.h +++ b/common/repositories/base/base_object_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_perl_event_export_settings_repository.h b/common/repositories/base/base_perl_event_export_settings_repository.h index df4f71dcb8..c3ed45c7ba 100644 --- a/common/repositories/base/base_perl_event_export_settings_repository.h +++ b/common/repositories/base/base_perl_event_export_settings_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_petitions_repository.h b/common/repositories/base/base_petitions_repository.h index 746421bd31..bdc94eeac1 100644 --- a/common/repositories/base/base_petitions_repository.h +++ b/common/repositories/base/base_petitions_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_pets_beastlord_data_repository.h b/common/repositories/base/base_pets_beastlord_data_repository.h index 46208feaaf..daf6c7e460 100644 --- a/common/repositories/base/base_pets_beastlord_data_repository.h +++ b/common/repositories/base/base_pets_beastlord_data_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_pets_equipmentset_entries_repository.h b/common/repositories/base/base_pets_equipmentset_entries_repository.h index 0c5187e764..4101d4c9aa 100644 --- a/common/repositories/base/base_pets_equipmentset_entries_repository.h +++ b/common/repositories/base/base_pets_equipmentset_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_pets_equipmentset_repository.h b/common/repositories/base/base_pets_equipmentset_repository.h index 3d96c7b2c9..10c1cef551 100644 --- a/common/repositories/base/base_pets_equipmentset_repository.h +++ b/common/repositories/base/base_pets_equipmentset_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_pets_repository.h b/common/repositories/base/base_pets_repository.h index f5042eea29..c9b8e43e3f 100644 --- a/common/repositories/base/base_pets_repository.h +++ b/common/repositories/base/base_pets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_aa_purchase_repository.h b/common/repositories/base/base_player_event_aa_purchase_repository.h index e26149c840..880aa27b23 100644 --- a/common/repositories/base/base_player_event_aa_purchase_repository.h +++ b/common/repositories/base/base_player_event_aa_purchase_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_killed_named_npc_repository.h b/common/repositories/base/base_player_event_killed_named_npc_repository.h index 1c61dbe2dc..41ac04d61c 100644 --- a/common/repositories/base/base_player_event_killed_named_npc_repository.h +++ b/common/repositories/base/base_player_event_killed_named_npc_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_killed_npc_repository.h b/common/repositories/base/base_player_event_killed_npc_repository.h index 47611c5a26..b0c76f8692 100644 --- a/common/repositories/base/base_player_event_killed_npc_repository.h +++ b/common/repositories/base/base_player_event_killed_npc_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_killed_raid_npc_repository.h b/common/repositories/base/base_player_event_killed_raid_npc_repository.h index bc834b10a1..bbffeb592e 100644 --- a/common/repositories/base/base_player_event_killed_raid_npc_repository.h +++ b/common/repositories/base/base_player_event_killed_raid_npc_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_log_settings_repository.h b/common/repositories/base/base_player_event_log_settings_repository.h index 5c34551335..47d9f5c1e6 100644 --- a/common/repositories/base/base_player_event_log_settings_repository.h +++ b/common/repositories/base/base_player_event_log_settings_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_logs_repository.h b/common/repositories/base/base_player_event_logs_repository.h index c7e976fe34..23223c159e 100644 --- a/common/repositories/base/base_player_event_logs_repository.h +++ b/common/repositories/base/base_player_event_logs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_loot_items_repository.h b/common/repositories/base/base_player_event_loot_items_repository.h index 191a1194b3..f8174c64e9 100644 --- a/common/repositories/base/base_player_event_loot_items_repository.h +++ b/common/repositories/base/base_player_event_loot_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_merchant_purchase_repository.h b/common/repositories/base/base_player_event_merchant_purchase_repository.h index f7d17bad2c..cf21a632ea 100644 --- a/common/repositories/base/base_player_event_merchant_purchase_repository.h +++ b/common/repositories/base/base_player_event_merchant_purchase_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_merchant_sell_repository.h b/common/repositories/base/base_player_event_merchant_sell_repository.h index 861b90f225..4a2fa9289d 100644 --- a/common/repositories/base/base_player_event_merchant_sell_repository.h +++ b/common/repositories/base/base_player_event_merchant_sell_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_npc_handin_entries_repository.h b/common/repositories/base/base_player_event_npc_handin_entries_repository.h index 27200115bc..9f2b07a328 100644 --- a/common/repositories/base/base_player_event_npc_handin_entries_repository.h +++ b/common/repositories/base/base_player_event_npc_handin_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_npc_handin_repository.h b/common/repositories/base/base_player_event_npc_handin_repository.h index 9bba1d2a0c..58cbd7dd9d 100644 --- a/common/repositories/base/base_player_event_npc_handin_repository.h +++ b/common/repositories/base/base_player_event_npc_handin_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_speech_repository.h b/common/repositories/base/base_player_event_speech_repository.h index 7f63f05889..7fab2d18d3 100644 --- a/common/repositories/base/base_player_event_speech_repository.h +++ b/common/repositories/base/base_player_event_speech_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_trade_entries_repository.h b/common/repositories/base/base_player_event_trade_entries_repository.h index 2a9f09ce98..b7f9aaa2d7 100644 --- a/common/repositories/base/base_player_event_trade_entries_repository.h +++ b/common/repositories/base/base_player_event_trade_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_event_trade_repository.h b/common/repositories/base/base_player_event_trade_repository.h index fcc2ec9c37..4bdaa325d3 100644 --- a/common/repositories/base/base_player_event_trade_repository.h +++ b/common/repositories/base/base_player_event_trade_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_player_titlesets_repository.h b/common/repositories/base/base_player_titlesets_repository.h index 35ef9b07d5..ff27e8d520 100644 --- a/common/repositories/base/base_player_titlesets_repository.h +++ b/common/repositories/base/base_player_titlesets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_quest_globals_repository.h b/common/repositories/base/base_quest_globals_repository.h index 78e5ebf59a..41ba1710e1 100644 --- a/common/repositories/base/base_quest_globals_repository.h +++ b/common/repositories/base/base_quest_globals_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_raid_details_repository.h b/common/repositories/base/base_raid_details_repository.h index 771afd9369..e387ea6994 100644 --- a/common/repositories/base/base_raid_details_repository.h +++ b/common/repositories/base/base_raid_details_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_raid_members_repository.h b/common/repositories/base/base_raid_members_repository.h index d93418e61f..e48e84c56a 100644 --- a/common/repositories/base/base_raid_members_repository.h +++ b/common/repositories/base/base_raid_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_reports_repository.h b/common/repositories/base/base_reports_repository.h index 4c3a2acccc..f38d9ad809 100644 --- a/common/repositories/base/base_reports_repository.h +++ b/common/repositories/base/base_reports_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_respawn_times_repository.h b/common/repositories/base/base_respawn_times_repository.h index 25a56bad96..30fe9a9fa7 100644 --- a/common/repositories/base/base_respawn_times_repository.h +++ b/common/repositories/base/base_respawn_times_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_rule_sets_repository.h b/common/repositories/base/base_rule_sets_repository.h index 0007a2c7e9..3437a177ee 100644 --- a/common/repositories/base/base_rule_sets_repository.h +++ b/common/repositories/base/base_rule_sets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_rule_values_repository.h b/common/repositories/base/base_rule_values_repository.h index 571f7425fb..5445281a34 100644 --- a/common/repositories/base/base_rule_values_repository.h +++ b/common/repositories/base/base_rule_values_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_saylink_repository.h b/common/repositories/base/base_saylink_repository.h index 78c61dfc59..9c0054881d 100644 --- a/common/repositories/base/base_saylink_repository.h +++ b/common/repositories/base/base_saylink_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_server_scheduled_events_repository.h b/common/repositories/base/base_server_scheduled_events_repository.h index e23f0a4fd4..a56eae12c8 100644 --- a/common/repositories/base/base_server_scheduled_events_repository.h +++ b/common/repositories/base/base_server_scheduled_events_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_shared_task_activity_state_repository.h b/common/repositories/base/base_shared_task_activity_state_repository.h index bcb6399dad..2c5a38b60d 100644 --- a/common/repositories/base/base_shared_task_activity_state_repository.h +++ b/common/repositories/base/base_shared_task_activity_state_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_shared_task_dynamic_zones_repository.h b/common/repositories/base/base_shared_task_dynamic_zones_repository.h index 07d67ad0c2..6424be2f3f 100644 --- a/common/repositories/base/base_shared_task_dynamic_zones_repository.h +++ b/common/repositories/base/base_shared_task_dynamic_zones_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_shared_task_members_repository.h b/common/repositories/base/base_shared_task_members_repository.h index 1f06590802..3a35886a02 100644 --- a/common/repositories/base/base_shared_task_members_repository.h +++ b/common/repositories/base/base_shared_task_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_shared_tasks_repository.h b/common/repositories/base/base_shared_tasks_repository.h index 88d47ac0ae..5ac93c5a8b 100644 --- a/common/repositories/base/base_shared_tasks_repository.h +++ b/common/repositories/base/base_shared_tasks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_sharedbank_repository.h b/common/repositories/base/base_sharedbank_repository.h index 4c48940212..785e8ea584 100644 --- a/common/repositories/base/base_sharedbank_repository.h +++ b/common/repositories/base/base_sharedbank_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_skill_caps_repository.h b/common/repositories/base/base_skill_caps_repository.h index d5a10dc859..2e08be742e 100644 --- a/common/repositories/base/base_skill_caps_repository.h +++ b/common/repositories/base/base_skill_caps_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_spawn2_disabled_repository.h b/common/repositories/base/base_spawn2_disabled_repository.h index 6ff80b70f3..09b2b30f1b 100644 --- a/common/repositories/base/base_spawn2_disabled_repository.h +++ b/common/repositories/base/base_spawn2_disabled_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_spawn2_repository.h b/common/repositories/base/base_spawn2_repository.h index 5d6e071fbf..932c2c9cc5 100644 --- a/common/repositories/base/base_spawn2_repository.h +++ b/common/repositories/base/base_spawn2_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_spawn_condition_values_repository.h b/common/repositories/base/base_spawn_condition_values_repository.h index 1186a2507c..7bc3116ccc 100644 --- a/common/repositories/base/base_spawn_condition_values_repository.h +++ b/common/repositories/base/base_spawn_condition_values_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_spawn_conditions_repository.h b/common/repositories/base/base_spawn_conditions_repository.h index bddfa29366..79c6aa883b 100644 --- a/common/repositories/base/base_spawn_conditions_repository.h +++ b/common/repositories/base/base_spawn_conditions_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_spawn_events_repository.h b/common/repositories/base/base_spawn_events_repository.h index c61b4f0880..d8a196ccd0 100644 --- a/common/repositories/base/base_spawn_events_repository.h +++ b/common/repositories/base/base_spawn_events_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_spawnentry_repository.h b/common/repositories/base/base_spawnentry_repository.h index ebf20287f9..b7665aa22d 100644 --- a/common/repositories/base/base_spawnentry_repository.h +++ b/common/repositories/base/base_spawnentry_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_spawngroup_repository.h b/common/repositories/base/base_spawngroup_repository.h index 1942e1309f..ab2cecc5c8 100644 --- a/common/repositories/base/base_spawngroup_repository.h +++ b/common/repositories/base/base_spawngroup_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_spell_buckets_repository.h b/common/repositories/base/base_spell_buckets_repository.h index 88096b3676..5be55a327a 100644 --- a/common/repositories/base/base_spell_buckets_repository.h +++ b/common/repositories/base/base_spell_buckets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_spell_globals_repository.h b/common/repositories/base/base_spell_globals_repository.h index b9052fd75f..92553ebd80 100644 --- a/common/repositories/base/base_spell_globals_repository.h +++ b/common/repositories/base/base_spell_globals_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_spells_new_repository.h b/common/repositories/base/base_spells_new_repository.h index 3a887544cf..ae627e5c76 100644 --- a/common/repositories/base/base_spells_new_repository.h +++ b/common/repositories/base/base_spells_new_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_start_zones_repository.h b/common/repositories/base/base_start_zones_repository.h index 59bf18da0a..a493d860ed 100644 --- a/common/repositories/base/base_start_zones_repository.h +++ b/common/repositories/base/base_start_zones_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_starting_items_repository.h b/common/repositories/base/base_starting_items_repository.h index 3d50f486d7..f6c624a332 100644 --- a/common/repositories/base/base_starting_items_repository.h +++ b/common/repositories/base/base_starting_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_task_activities_repository.h b/common/repositories/base/base_task_activities_repository.h index c553465d5c..fa5be89595 100644 --- a/common/repositories/base/base_task_activities_repository.h +++ b/common/repositories/base/base_task_activities_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_tasks_repository.h b/common/repositories/base/base_tasks_repository.h index 775c9e96f6..be9d9b0a7c 100644 --- a/common/repositories/base/base_tasks_repository.h +++ b/common/repositories/base/base_tasks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_tasksets_repository.h b/common/repositories/base/base_tasksets_repository.h index 5d7d5171af..e3dea40657 100644 --- a/common/repositories/base/base_tasksets_repository.h +++ b/common/repositories/base/base_tasksets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_timers_repository.h b/common/repositories/base/base_timers_repository.h index 523ec06136..0d7400324d 100644 --- a/common/repositories/base/base_timers_repository.h +++ b/common/repositories/base/base_timers_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_titles_repository.h b/common/repositories/base/base_titles_repository.h index 1df0686c5e..3ebcb6f0d3 100644 --- a/common/repositories/base/base_titles_repository.h +++ b/common/repositories/base/base_titles_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_tool_game_objects_repository.h b/common/repositories/base/base_tool_game_objects_repository.h index e44a901973..d5f8630425 100644 --- a/common/repositories/base/base_tool_game_objects_repository.h +++ b/common/repositories/base/base_tool_game_objects_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_trader_repository.h b/common/repositories/base/base_trader_repository.h index 9199c27c9d..bc9e80a9b5 100644 --- a/common/repositories/base/base_trader_repository.h +++ b/common/repositories/base/base_trader_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_tradeskill_recipe_entries_repository.h b/common/repositories/base/base_tradeskill_recipe_entries_repository.h index 455e00fca6..eb761a2f27 100644 --- a/common/repositories/base/base_tradeskill_recipe_entries_repository.h +++ b/common/repositories/base/base_tradeskill_recipe_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_tradeskill_recipe_repository.h b/common/repositories/base/base_tradeskill_recipe_repository.h index 19ced3202d..23d0030c18 100644 --- a/common/repositories/base/base_tradeskill_recipe_repository.h +++ b/common/repositories/base/base_tradeskill_recipe_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_traps_repository.h b/common/repositories/base/base_traps_repository.h index 863eba234b..2f9de4492a 100644 --- a/common/repositories/base/base_traps_repository.h +++ b/common/repositories/base/base_traps_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_tribute_levels_repository.h b/common/repositories/base/base_tribute_levels_repository.h index c721359b42..9009eaf0a1 100644 --- a/common/repositories/base/base_tribute_levels_repository.h +++ b/common/repositories/base/base_tribute_levels_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_tributes_repository.h b/common/repositories/base/base_tributes_repository.h index ff3cc30f0d..7c8e7bd9c6 100644 --- a/common/repositories/base/base_tributes_repository.h +++ b/common/repositories/base/base_tributes_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_variables_repository.h b/common/repositories/base/base_variables_repository.h index 84cd137740..82bc9bf0f2 100644 --- a/common/repositories/base/base_variables_repository.h +++ b/common/repositories/base/base_variables_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_veteran_reward_templates_repository.h b/common/repositories/base/base_veteran_reward_templates_repository.h index 13e5ede316..1df6d01607 100644 --- a/common/repositories/base/base_veteran_reward_templates_repository.h +++ b/common/repositories/base/base_veteran_reward_templates_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_zone_flags_repository.h b/common/repositories/base/base_zone_flags_repository.h index 8d8e17d010..ce2540b783 100644 --- a/common/repositories/base/base_zone_flags_repository.h +++ b/common/repositories/base/base_zone_flags_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_zone_points_repository.h b/common/repositories/base/base_zone_points_repository.h index 536f754371..c8734f57c9 100644 --- a/common/repositories/base/base_zone_points_repository.h +++ b/common/repositories/base/base_zone_points_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_zone_repository.h b/common/repositories/base/base_zone_repository.h index a131cd5704..3751e3b5c1 100644 --- a/common/repositories/base/base_zone_repository.h +++ b/common/repositories/base/base_zone_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base/base_zone_state_spawns_repository.h b/common/repositories/base/base_zone_state_spawns_repository.h index 197e52eae4..985eec6b0d 100644 --- a/common/repositories/base/base_zone_state_spawns_repository.h +++ b/common/repositories/base/base_zone_state_spawns_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /** * DO NOT MODIFY THIS FILE * diff --git a/common/repositories/base_data_repository.h b/common/repositories/base_data_repository.h index 21b3bf20a4..8ce663c156 100644 --- a/common/repositories/base_data_repository.h +++ b/common/repositories/base_data_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_base_data_repository.h" diff --git a/common/repositories/blocked_spells_repository.h b/common/repositories/blocked_spells_repository.h index 652ced8935..982cd8254a 100644 --- a/common/repositories/blocked_spells_repository.h +++ b/common/repositories/blocked_spells_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_blocked_spells_repository.h" diff --git a/common/repositories/books_repository.h b/common/repositories/books_repository.h index 3aeedb6778..83cceac833 100644 --- a/common/repositories/books_repository.h +++ b/common/repositories/books_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_books_repository.h" diff --git a/common/repositories/bot_blocked_buffs_repository.h b/common/repositories/bot_blocked_buffs_repository.h index 8734e4c0d3..bbcf250082 100644 --- a/common/repositories/bot_blocked_buffs_repository.h +++ b/common/repositories/bot_blocked_buffs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_blocked_buffs_repository.h" diff --git a/common/repositories/bot_buffs_repository.h b/common/repositories/bot_buffs_repository.h index 2e0b85fffa..61cd61583f 100644 --- a/common/repositories/bot_buffs_repository.h +++ b/common/repositories/bot_buffs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_buffs_repository.h" diff --git a/common/repositories/bot_create_combinations_repository.h b/common/repositories/bot_create_combinations_repository.h index ea003e31ab..00444cf685 100644 --- a/common/repositories/bot_create_combinations_repository.h +++ b/common/repositories/bot_create_combinations_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_create_combinations_repository.h" diff --git a/common/repositories/bot_data_repository.h b/common/repositories/bot_data_repository.h index 0d36d9ff95..1a5e9b2e80 100644 --- a/common/repositories/bot_data_repository.h +++ b/common/repositories/bot_data_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_data_repository.h" diff --git a/common/repositories/bot_group_members_repository.h b/common/repositories/bot_group_members_repository.h index 2c932962ff..4fec2298a1 100644 --- a/common/repositories/bot_group_members_repository.h +++ b/common/repositories/bot_group_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_group_members_repository.h" diff --git a/common/repositories/bot_groups_repository.h b/common/repositories/bot_groups_repository.h index cc1f2c627e..203aeb4039 100644 --- a/common/repositories/bot_groups_repository.h +++ b/common/repositories/bot_groups_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_groups_repository.h" diff --git a/common/repositories/bot_guild_members_repository.h b/common/repositories/bot_guild_members_repository.h index d51eb3f63d..a6adc024b2 100644 --- a/common/repositories/bot_guild_members_repository.h +++ b/common/repositories/bot_guild_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_guild_members_repository.h" diff --git a/common/repositories/bot_heal_rotation_members_repository.h b/common/repositories/bot_heal_rotation_members_repository.h index 91bf040bdc..9406ba0a4f 100644 --- a/common/repositories/bot_heal_rotation_members_repository.h +++ b/common/repositories/bot_heal_rotation_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_heal_rotation_members_repository.h" diff --git a/common/repositories/bot_heal_rotation_targets_repository.h b/common/repositories/bot_heal_rotation_targets_repository.h index a91dd62061..f9dbc49489 100644 --- a/common/repositories/bot_heal_rotation_targets_repository.h +++ b/common/repositories/bot_heal_rotation_targets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_heal_rotation_targets_repository.h" diff --git a/common/repositories/bot_heal_rotations_repository.h b/common/repositories/bot_heal_rotations_repository.h index a816e8598b..9308221863 100644 --- a/common/repositories/bot_heal_rotations_repository.h +++ b/common/repositories/bot_heal_rotations_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_heal_rotations_repository.h" diff --git a/common/repositories/bot_inspect_messages_repository.h b/common/repositories/bot_inspect_messages_repository.h index 396409223c..32419ebb4a 100644 --- a/common/repositories/bot_inspect_messages_repository.h +++ b/common/repositories/bot_inspect_messages_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_inspect_messages_repository.h" diff --git a/common/repositories/bot_inventories_repository.h b/common/repositories/bot_inventories_repository.h index 1dc2856ae4..cbf3bde0dd 100644 --- a/common/repositories/bot_inventories_repository.h +++ b/common/repositories/bot_inventories_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_inventories_repository.h" diff --git a/common/repositories/bot_owner_options_repository.h b/common/repositories/bot_owner_options_repository.h index e9c0176e8b..12e649baf5 100644 --- a/common/repositories/bot_owner_options_repository.h +++ b/common/repositories/bot_owner_options_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_owner_options_repository.h" diff --git a/common/repositories/bot_pet_buffs_repository.h b/common/repositories/bot_pet_buffs_repository.h index 69fc84c143..b4a161b325 100644 --- a/common/repositories/bot_pet_buffs_repository.h +++ b/common/repositories/bot_pet_buffs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_pet_buffs_repository.h" diff --git a/common/repositories/bot_pet_inventories_repository.h b/common/repositories/bot_pet_inventories_repository.h index ee220dd8fc..e71ace5de3 100644 --- a/common/repositories/bot_pet_inventories_repository.h +++ b/common/repositories/bot_pet_inventories_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_pet_inventories_repository.h" diff --git a/common/repositories/bot_pets_repository.h b/common/repositories/bot_pets_repository.h index c66ac638a6..fc0933af68 100644 --- a/common/repositories/bot_pets_repository.h +++ b/common/repositories/bot_pets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_pets_repository.h" diff --git a/common/repositories/bot_settings_repository.h b/common/repositories/bot_settings_repository.h index 29c1920fac..78b544d66d 100644 --- a/common/repositories/bot_settings_repository.h +++ b/common/repositories/bot_settings_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_settings_repository.h" diff --git a/common/repositories/bot_spell_casting_chances_repository.h b/common/repositories/bot_spell_casting_chances_repository.h index bd6c50329b..8967ce3f79 100644 --- a/common/repositories/bot_spell_casting_chances_repository.h +++ b/common/repositories/bot_spell_casting_chances_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_spell_casting_chances_repository.h" diff --git a/common/repositories/bot_spell_settings_repository.h b/common/repositories/bot_spell_settings_repository.h index 0daf696530..f193910808 100644 --- a/common/repositories/bot_spell_settings_repository.h +++ b/common/repositories/bot_spell_settings_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_spell_settings_repository.h" diff --git a/common/repositories/bot_spells_entries_repository.h b/common/repositories/bot_spells_entries_repository.h index 3ee67551ee..7d00b1c2ab 100644 --- a/common/repositories/bot_spells_entries_repository.h +++ b/common/repositories/bot_spells_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_spells_entries_repository.h" diff --git a/common/repositories/bot_stances_repository.h b/common/repositories/bot_stances_repository.h index 5a896ac69c..50942be51b 100644 --- a/common/repositories/bot_stances_repository.h +++ b/common/repositories/bot_stances_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_stances_repository.h" diff --git a/common/repositories/bot_starting_items_repository.h b/common/repositories/bot_starting_items_repository.h index 8583732a3f..65edb2cbac 100644 --- a/common/repositories/bot_starting_items_repository.h +++ b/common/repositories/bot_starting_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_starting_items_repository.h" diff --git a/common/repositories/bot_timers_repository.h b/common/repositories/bot_timers_repository.h index d9d9d165e4..e707fc427e 100644 --- a/common/repositories/bot_timers_repository.h +++ b/common/repositories/bot_timers_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bot_timers_repository.h" diff --git a/common/repositories/bug_reports_repository.h b/common/repositories/bug_reports_repository.h index dfbe7e1641..e14315bfe8 100644 --- a/common/repositories/bug_reports_repository.h +++ b/common/repositories/bug_reports_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bug_reports_repository.h" diff --git a/common/repositories/bugs_repository.h b/common/repositories/bugs_repository.h index 22f2b25f42..666e7c648c 100644 --- a/common/repositories/bugs_repository.h +++ b/common/repositories/bugs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_bugs_repository.h" diff --git a/common/repositories/buyer_buy_lines_repository.h b/common/repositories/buyer_buy_lines_repository.h index 8b236a48ee..f2652be640 100644 --- a/common/repositories/buyer_buy_lines_repository.h +++ b/common/repositories/buyer_buy_lines_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_buyer_buy_lines_repository.h" diff --git a/common/repositories/buyer_repository.h b/common/repositories/buyer_repository.h index 8888acf7ff..23b1b1b88e 100644 --- a/common/repositories/buyer_repository.h +++ b/common/repositories/buyer_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_buyer_repository.h" diff --git a/common/repositories/buyer_trade_items_repository.h b/common/repositories/buyer_trade_items_repository.h index 81b0848429..951edbefec 100644 --- a/common/repositories/buyer_trade_items_repository.h +++ b/common/repositories/buyer_trade_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_buyer_trade_items_repository.h" diff --git a/common/repositories/char_create_combinations_repository.h b/common/repositories/char_create_combinations_repository.h index cc81eb32b0..08c0c2ae56 100644 --- a/common/repositories/char_create_combinations_repository.h +++ b/common/repositories/char_create_combinations_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_char_create_combinations_repository.h" diff --git a/common/repositories/char_create_point_allocations_repository.h b/common/repositories/char_create_point_allocations_repository.h index da0f42b256..252759cad5 100644 --- a/common/repositories/char_create_point_allocations_repository.h +++ b/common/repositories/char_create_point_allocations_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_char_create_point_allocations_repository.h" diff --git a/common/repositories/char_recipe_list_repository.h b/common/repositories/char_recipe_list_repository.h index 32fc1958b7..f91d398689 100644 --- a/common/repositories/char_recipe_list_repository.h +++ b/common/repositories/char_recipe_list_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_char_recipe_list_repository.h" diff --git a/common/repositories/character_activities_repository.h b/common/repositories/character_activities_repository.h index aebb7c96ad..9235450511 100644 --- a/common/repositories/character_activities_repository.h +++ b/common/repositories/character_activities_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_activities_repository.h" diff --git a/common/repositories/character_alt_currency_repository.h b/common/repositories/character_alt_currency_repository.h index e7c211c24e..34e60c7b9f 100644 --- a/common/repositories/character_alt_currency_repository.h +++ b/common/repositories/character_alt_currency_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_alt_currency_repository.h" diff --git a/common/repositories/character_alternate_abilities_repository.h b/common/repositories/character_alternate_abilities_repository.h index 82df4ca00c..9f1331d522 100644 --- a/common/repositories/character_alternate_abilities_repository.h +++ b/common/repositories/character_alternate_abilities_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_alternate_abilities_repository.h" diff --git a/common/repositories/character_auras_repository.h b/common/repositories/character_auras_repository.h index 9e9f39d621..6bd0daf477 100644 --- a/common/repositories/character_auras_repository.h +++ b/common/repositories/character_auras_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_auras_repository.h" diff --git a/common/repositories/character_bandolier_repository.h b/common/repositories/character_bandolier_repository.h index fca31af3a5..1c2ee1ec5e 100644 --- a/common/repositories/character_bandolier_repository.h +++ b/common/repositories/character_bandolier_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_bandolier_repository.h" diff --git a/common/repositories/character_bind_repository.h b/common/repositories/character_bind_repository.h index a2b576f823..30cc92d320 100644 --- a/common/repositories/character_bind_repository.h +++ b/common/repositories/character_bind_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_bind_repository.h" diff --git a/common/repositories/character_buffs_repository.h b/common/repositories/character_buffs_repository.h index ce4587b11f..cc6a9c7120 100644 --- a/common/repositories/character_buffs_repository.h +++ b/common/repositories/character_buffs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_buffs_repository.h" diff --git a/common/repositories/character_corpse_items_repository.h b/common/repositories/character_corpse_items_repository.h index e1da52f0a5..3f8292ab93 100644 --- a/common/repositories/character_corpse_items_repository.h +++ b/common/repositories/character_corpse_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_corpse_items_repository.h" diff --git a/common/repositories/character_corpses_repository.h b/common/repositories/character_corpses_repository.h index 7d81c1bd06..37570eabec 100644 --- a/common/repositories/character_corpses_repository.h +++ b/common/repositories/character_corpses_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_corpses_repository.h" diff --git a/common/repositories/character_currency_repository.h b/common/repositories/character_currency_repository.h index 3c94246f73..d7a103ca15 100644 --- a/common/repositories/character_currency_repository.h +++ b/common/repositories/character_currency_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_currency_repository.h" diff --git a/common/repositories/character_data_repository.h b/common/repositories/character_data_repository.h index 6e5eff5f2a..3536e0597c 100644 --- a/common/repositories/character_data_repository.h +++ b/common/repositories/character_data_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_data_repository.h" diff --git a/common/repositories/character_disciplines_repository.h b/common/repositories/character_disciplines_repository.h index 20755c794e..b85a8e91c6 100644 --- a/common/repositories/character_disciplines_repository.h +++ b/common/repositories/character_disciplines_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_disciplines_repository.h" diff --git a/common/repositories/character_evolving_items_repository.h b/common/repositories/character_evolving_items_repository.h index 08dc95c89f..05b6ffb032 100644 --- a/common/repositories/character_evolving_items_repository.h +++ b/common/repositories/character_evolving_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_evolving_items_repository.h" diff --git a/common/repositories/character_exp_modifiers_repository.h b/common/repositories/character_exp_modifiers_repository.h index 69ab3d5e14..b04387dea9 100644 --- a/common/repositories/character_exp_modifiers_repository.h +++ b/common/repositories/character_exp_modifiers_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_exp_modifiers_repository.h" diff --git a/common/repositories/character_expedition_lockouts_repository.h b/common/repositories/character_expedition_lockouts_repository.h index 4318dbbefc..c5ad58dc77 100644 --- a/common/repositories/character_expedition_lockouts_repository.h +++ b/common/repositories/character_expedition_lockouts_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_expedition_lockouts_repository.h" diff --git a/common/repositories/character_inspect_messages_repository.h b/common/repositories/character_inspect_messages_repository.h index d4abfb7d69..0486132c65 100644 --- a/common/repositories/character_inspect_messages_repository.h +++ b/common/repositories/character_inspect_messages_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_inspect_messages_repository.h" diff --git a/common/repositories/character_instance_safereturns_repository.h b/common/repositories/character_instance_safereturns_repository.h index dc240a68a3..fa15787680 100644 --- a/common/repositories/character_instance_safereturns_repository.h +++ b/common/repositories/character_instance_safereturns_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_instance_safereturns_repository.h" diff --git a/common/repositories/character_item_recast_repository.h b/common/repositories/character_item_recast_repository.h index 1a1ecc295c..bac1b82ed6 100644 --- a/common/repositories/character_item_recast_repository.h +++ b/common/repositories/character_item_recast_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_item_recast_repository.h" diff --git a/common/repositories/character_languages_repository.h b/common/repositories/character_languages_repository.h index 4e3639da44..1ffe41b3c3 100644 --- a/common/repositories/character_languages_repository.h +++ b/common/repositories/character_languages_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_languages_repository.h" diff --git a/common/repositories/character_leadership_abilities_repository.h b/common/repositories/character_leadership_abilities_repository.h index 66c8b52c52..cb641af4e4 100644 --- a/common/repositories/character_leadership_abilities_repository.h +++ b/common/repositories/character_leadership_abilities_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_leadership_abilities_repository.h" diff --git a/common/repositories/character_material_repository.h b/common/repositories/character_material_repository.h index f98e259bc2..8cc0c0b93c 100644 --- a/common/repositories/character_material_repository.h +++ b/common/repositories/character_material_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_material_repository.h" diff --git a/common/repositories/character_memmed_spells_repository.h b/common/repositories/character_memmed_spells_repository.h index 5cbf6ee2c3..03dc0eb60f 100644 --- a/common/repositories/character_memmed_spells_repository.h +++ b/common/repositories/character_memmed_spells_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_memmed_spells_repository.h" diff --git a/common/repositories/character_parcels_containers_repository.h b/common/repositories/character_parcels_containers_repository.h index 9ae52c8123..9651cd21f6 100644 --- a/common/repositories/character_parcels_containers_repository.h +++ b/common/repositories/character_parcels_containers_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_parcels_containers_repository.h" diff --git a/common/repositories/character_parcels_repository.h b/common/repositories/character_parcels_repository.h index 35ab01cc74..c324685717 100644 --- a/common/repositories/character_parcels_repository.h +++ b/common/repositories/character_parcels_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_parcels_repository.h" diff --git a/common/repositories/character_peqzone_flags_repository.h b/common/repositories/character_peqzone_flags_repository.h index 1b6e501f94..42a7b80227 100644 --- a/common/repositories/character_peqzone_flags_repository.h +++ b/common/repositories/character_peqzone_flags_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_peqzone_flags_repository.h" diff --git a/common/repositories/character_pet_buffs_repository.h b/common/repositories/character_pet_buffs_repository.h index a0fcd4b4c8..ebbf75336a 100644 --- a/common/repositories/character_pet_buffs_repository.h +++ b/common/repositories/character_pet_buffs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_pet_buffs_repository.h" diff --git a/common/repositories/character_pet_info_repository.h b/common/repositories/character_pet_info_repository.h index 062e4fb074..253cf5977b 100644 --- a/common/repositories/character_pet_info_repository.h +++ b/common/repositories/character_pet_info_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_pet_info_repository.h" diff --git a/common/repositories/character_pet_inventory_repository.h b/common/repositories/character_pet_inventory_repository.h index 659a4da087..b21e2507e2 100644 --- a/common/repositories/character_pet_inventory_repository.h +++ b/common/repositories/character_pet_inventory_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_pet_inventory_repository.h" diff --git a/common/repositories/character_pet_name_repository.h b/common/repositories/character_pet_name_repository.h index 43b39c27cb..5fc0f890eb 100644 --- a/common/repositories/character_pet_name_repository.h +++ b/common/repositories/character_pet_name_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_pet_name_repository.h" diff --git a/common/repositories/character_potionbelt_repository.h b/common/repositories/character_potionbelt_repository.h index e6a2c8697c..f28ff28ece 100644 --- a/common/repositories/character_potionbelt_repository.h +++ b/common/repositories/character_potionbelt_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_potionbelt_repository.h" diff --git a/common/repositories/character_skills_repository.h b/common/repositories/character_skills_repository.h index 9141ed94fb..23a119c199 100644 --- a/common/repositories/character_skills_repository.h +++ b/common/repositories/character_skills_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_skills_repository.h" diff --git a/common/repositories/character_spells_repository.h b/common/repositories/character_spells_repository.h index 8408d266a1..84aa421667 100644 --- a/common/repositories/character_spells_repository.h +++ b/common/repositories/character_spells_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_spells_repository.h" diff --git a/common/repositories/character_stats_record_repository.h b/common/repositories/character_stats_record_repository.h index 5823bf0bdb..c0219dc6ce 100644 --- a/common/repositories/character_stats_record_repository.h +++ b/common/repositories/character_stats_record_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_stats_record_repository.h" diff --git a/common/repositories/character_task_timers_repository.h b/common/repositories/character_task_timers_repository.h index 8791d29554..96499a16d4 100644 --- a/common/repositories/character_task_timers_repository.h +++ b/common/repositories/character_task_timers_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_task_timers_repository.h" diff --git a/common/repositories/character_tasks_repository.h b/common/repositories/character_tasks_repository.h index dd29b73d4a..fc1f689d0d 100644 --- a/common/repositories/character_tasks_repository.h +++ b/common/repositories/character_tasks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_tasks_repository.h" diff --git a/common/repositories/character_tribute_repository.h b/common/repositories/character_tribute_repository.h index f881885509..754b1ed531 100644 --- a/common/repositories/character_tribute_repository.h +++ b/common/repositories/character_tribute_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_character_tribute_repository.h" diff --git a/common/repositories/chatchannel_reserved_names_repository.h b/common/repositories/chatchannel_reserved_names_repository.h index 5da75b8576..499a4e2fec 100644 --- a/common/repositories/chatchannel_reserved_names_repository.h +++ b/common/repositories/chatchannel_reserved_names_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_chatchannel_reserved_names_repository.h" diff --git a/common/repositories/chatchannels_repository.h b/common/repositories/chatchannels_repository.h index 132b8fd5c0..3878adbaa9 100644 --- a/common/repositories/chatchannels_repository.h +++ b/common/repositories/chatchannels_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_chatchannels_repository.h" diff --git a/common/repositories/command_subsettings_repository.h b/common/repositories/command_subsettings_repository.h index 16aa9f8a97..210b409f5a 100644 --- a/common/repositories/command_subsettings_repository.h +++ b/common/repositories/command_subsettings_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_command_subsettings_repository.h" diff --git a/common/repositories/completed_shared_task_activity_state_repository.h b/common/repositories/completed_shared_task_activity_state_repository.h index a4315cd828..6d4cc6f5d4 100644 --- a/common/repositories/completed_shared_task_activity_state_repository.h +++ b/common/repositories/completed_shared_task_activity_state_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_completed_shared_task_activity_state_repository.h" diff --git a/common/repositories/completed_shared_task_members_repository.h b/common/repositories/completed_shared_task_members_repository.h index 0d3523f805..a2e95480a0 100644 --- a/common/repositories/completed_shared_task_members_repository.h +++ b/common/repositories/completed_shared_task_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_completed_shared_task_members_repository.h" diff --git a/common/repositories/completed_shared_tasks_repository.h b/common/repositories/completed_shared_tasks_repository.h index a3a458646e..9458cbdb3e 100644 --- a/common/repositories/completed_shared_tasks_repository.h +++ b/common/repositories/completed_shared_tasks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_completed_shared_tasks_repository.h" diff --git a/common/repositories/completed_tasks_repository.h b/common/repositories/completed_tasks_repository.h index 9257f364e4..28f569e2c2 100644 --- a/common/repositories/completed_tasks_repository.h +++ b/common/repositories/completed_tasks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_completed_tasks_repository.h" diff --git a/common/repositories/content_flags_repository.h b/common/repositories/content_flags_repository.h index 5f98a25d00..eeb6d7456e 100644 --- a/common/repositories/content_flags_repository.h +++ b/common/repositories/content_flags_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_content_flags_repository.h" diff --git a/common/repositories/criteria/content_filter_criteria.h b/common/repositories/criteria/content_filter_criteria.h index b94795c1c5..abd905cfee 100644 --- a/common/repositories/criteria/content_filter_criteria.h +++ b/common/repositories/criteria/content_filter_criteria.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/content/world_content_service.h" diff --git a/common/repositories/damageshieldtypes_repository.h b/common/repositories/damageshieldtypes_repository.h index 5a6c1ca2a0..fa87f85409 100644 --- a/common/repositories/damageshieldtypes_repository.h +++ b/common/repositories/damageshieldtypes_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_damageshieldtypes_repository.h" diff --git a/common/repositories/data_buckets_repository.h b/common/repositories/data_buckets_repository.h index 225991a3b6..d3c31c6f76 100644 --- a/common/repositories/data_buckets_repository.h +++ b/common/repositories/data_buckets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_data_buckets_repository.h" diff --git a/common/repositories/db_str_repository.h b/common/repositories/db_str_repository.h index f8d3bfee2b..8269043dc8 100644 --- a/common/repositories/db_str_repository.h +++ b/common/repositories/db_str_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_db_str_repository.h" diff --git a/common/repositories/discord_webhooks_repository.h b/common/repositories/discord_webhooks_repository.h index a0d5c1c2c2..b09ec16f4c 100644 --- a/common/repositories/discord_webhooks_repository.h +++ b/common/repositories/discord_webhooks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_discord_webhooks_repository.h" diff --git a/common/repositories/discovered_items_repository.h b/common/repositories/discovered_items_repository.h index 27e9e79136..64e2713628 100644 --- a/common/repositories/discovered_items_repository.h +++ b/common/repositories/discovered_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_discovered_items_repository.h" diff --git a/common/repositories/doors_repository.h b/common/repositories/doors_repository.h index b65ce438b4..bd625e1565 100644 --- a/common/repositories/doors_repository.h +++ b/common/repositories/doors_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_doors_repository.h" diff --git a/common/repositories/dynamic_zone_lockouts_repository.h b/common/repositories/dynamic_zone_lockouts_repository.h index ab1476ef4d..4316c8ec91 100644 --- a/common/repositories/dynamic_zone_lockouts_repository.h +++ b/common/repositories/dynamic_zone_lockouts_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_dynamic_zone_lockouts_repository.h" diff --git a/common/repositories/dynamic_zone_members_repository.h b/common/repositories/dynamic_zone_members_repository.h index 1e8351e53b..fbb75ab8f5 100644 --- a/common/repositories/dynamic_zone_members_repository.h +++ b/common/repositories/dynamic_zone_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_dynamic_zone_members_repository.h" diff --git a/common/repositories/dynamic_zone_templates_repository.h b/common/repositories/dynamic_zone_templates_repository.h index d101faf91a..09be02fd75 100644 --- a/common/repositories/dynamic_zone_templates_repository.h +++ b/common/repositories/dynamic_zone_templates_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_dynamic_zone_templates_repository.h" diff --git a/common/repositories/dynamic_zones_repository.h b/common/repositories/dynamic_zones_repository.h index 6d957b8f77..b1d22909a4 100644 --- a/common/repositories/dynamic_zones_repository.h +++ b/common/repositories/dynamic_zones_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_dynamic_zones_repository.h" diff --git a/common/repositories/faction_association_repository.h b/common/repositories/faction_association_repository.h index 601089354c..979101ca76 100644 --- a/common/repositories/faction_association_repository.h +++ b/common/repositories/faction_association_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_faction_association_repository.h" diff --git a/common/repositories/faction_base_data_repository.h b/common/repositories/faction_base_data_repository.h index 09bce71692..e625a9353e 100644 --- a/common/repositories/faction_base_data_repository.h +++ b/common/repositories/faction_base_data_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_faction_base_data_repository.h" diff --git a/common/repositories/faction_list_mod_repository.h b/common/repositories/faction_list_mod_repository.h index 7fa475168c..c0d5457d26 100644 --- a/common/repositories/faction_list_mod_repository.h +++ b/common/repositories/faction_list_mod_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_faction_list_mod_repository.h" diff --git a/common/repositories/faction_list_repository.h b/common/repositories/faction_list_repository.h index 4a41b44887..dc6321d994 100644 --- a/common/repositories/faction_list_repository.h +++ b/common/repositories/faction_list_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_faction_list_repository.h" diff --git a/common/repositories/faction_values_repository.h b/common/repositories/faction_values_repository.h index 8dd860ba8b..f391a252fa 100644 --- a/common/repositories/faction_values_repository.h +++ b/common/repositories/faction_values_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_faction_values_repository.h" diff --git a/common/repositories/fishing_repository.h b/common/repositories/fishing_repository.h index 3fb4f51c19..977e0933d9 100644 --- a/common/repositories/fishing_repository.h +++ b/common/repositories/fishing_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_fishing_repository.h" diff --git a/common/repositories/forage_repository.h b/common/repositories/forage_repository.h index e84f7bfbfc..56df982d51 100644 --- a/common/repositories/forage_repository.h +++ b/common/repositories/forage_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_forage_repository.h" diff --git a/common/repositories/friends_repository.h b/common/repositories/friends_repository.h index 3c842e028f..a1ceeef7b6 100644 --- a/common/repositories/friends_repository.h +++ b/common/repositories/friends_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_friends_repository.h" diff --git a/common/repositories/global_loot_repository.h b/common/repositories/global_loot_repository.h index e4bfe5dfc4..0ff1400249 100644 --- a/common/repositories/global_loot_repository.h +++ b/common/repositories/global_loot_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_global_loot_repository.h" diff --git a/common/repositories/gm_ips_repository.h b/common/repositories/gm_ips_repository.h index ad1b99b414..b4501342a9 100644 --- a/common/repositories/gm_ips_repository.h +++ b/common/repositories/gm_ips_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_gm_ips_repository.h" diff --git a/common/repositories/graveyard_repository.h b/common/repositories/graveyard_repository.h index 95f21df07a..ebbac407a7 100644 --- a/common/repositories/graveyard_repository.h +++ b/common/repositories/graveyard_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_graveyard_repository.h" diff --git a/common/repositories/grid_entries_repository.h b/common/repositories/grid_entries_repository.h index 8ce80ee76b..626960608a 100644 --- a/common/repositories/grid_entries_repository.h +++ b/common/repositories/grid_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_grid_entries_repository.h" diff --git a/common/repositories/grid_repository.h b/common/repositories/grid_repository.h index e8ad663898..7cba111d93 100644 --- a/common/repositories/grid_repository.h +++ b/common/repositories/grid_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_grid_repository.h" diff --git a/common/repositories/ground_spawns_repository.h b/common/repositories/ground_spawns_repository.h index e8f4d8f5c5..fb3063518a 100644 --- a/common/repositories/ground_spawns_repository.h +++ b/common/repositories/ground_spawns_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_ground_spawns_repository.h" diff --git a/common/repositories/group_id_repository.h b/common/repositories/group_id_repository.h index 7f2429b632..01cc358f6c 100644 --- a/common/repositories/group_id_repository.h +++ b/common/repositories/group_id_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_group_id_repository.h" diff --git a/common/repositories/group_leaders_repository.h b/common/repositories/group_leaders_repository.h index 20cca407cc..73c3e62aa7 100644 --- a/common/repositories/group_leaders_repository.h +++ b/common/repositories/group_leaders_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_group_leaders_repository.h" diff --git a/common/repositories/guild_bank_repository.h b/common/repositories/guild_bank_repository.h index 357710f7e2..cf2769aed6 100644 --- a/common/repositories/guild_bank_repository.h +++ b/common/repositories/guild_bank_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_guild_bank_repository.h" diff --git a/common/repositories/guild_members_repository.h b/common/repositories/guild_members_repository.h index 550b46078c..266d3d4498 100644 --- a/common/repositories/guild_members_repository.h +++ b/common/repositories/guild_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_guild_members_repository.h" diff --git a/common/repositories/guild_permissions_repository.h b/common/repositories/guild_permissions_repository.h index 997c8c0a9f..7ea9644f5e 100644 --- a/common/repositories/guild_permissions_repository.h +++ b/common/repositories/guild_permissions_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_guild_permissions_repository.h" diff --git a/common/repositories/guild_ranks_repository.h b/common/repositories/guild_ranks_repository.h index 7cb7196611..a2b4631f3a 100644 --- a/common/repositories/guild_ranks_repository.h +++ b/common/repositories/guild_ranks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_guild_ranks_repository.h" diff --git a/common/repositories/guild_relations_repository.h b/common/repositories/guild_relations_repository.h index 1af13ee987..5c55ddb03f 100644 --- a/common/repositories/guild_relations_repository.h +++ b/common/repositories/guild_relations_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_guild_relations_repository.h" diff --git a/common/repositories/guild_tributes_repository.h b/common/repositories/guild_tributes_repository.h index 0cd6d45cf3..07221926de 100644 --- a/common/repositories/guild_tributes_repository.h +++ b/common/repositories/guild_tributes_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_guild_tributes_repository.h" diff --git a/common/repositories/guilds_repository.h b/common/repositories/guilds_repository.h index 73c2d86487..8d642c35ff 100644 --- a/common/repositories/guilds_repository.h +++ b/common/repositories/guilds_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_guilds_repository.h" diff --git a/common/repositories/horses_repository.h b/common/repositories/horses_repository.h index a112d64322..d7372a1d0d 100644 --- a/common/repositories/horses_repository.h +++ b/common/repositories/horses_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_horses_repository.h" diff --git a/common/repositories/instance_list_player_repository.h b/common/repositories/instance_list_player_repository.h index 2d1267f23b..697f0c178f 100644 --- a/common/repositories/instance_list_player_repository.h +++ b/common/repositories/instance_list_player_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_instance_list_player_repository.h" diff --git a/common/repositories/instance_list_repository.h b/common/repositories/instance_list_repository.h index c396db9061..139ab52381 100644 --- a/common/repositories/instance_list_repository.h +++ b/common/repositories/instance_list_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_instance_list_repository.h" diff --git a/common/repositories/inventory_repository.h b/common/repositories/inventory_repository.h index 20306c4d45..23ea2c82f8 100644 --- a/common/repositories/inventory_repository.h +++ b/common/repositories/inventory_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_inventory_repository.h" diff --git a/common/repositories/inventory_snapshots_repository.h b/common/repositories/inventory_snapshots_repository.h index b0605c0d96..930417f3d2 100644 --- a/common/repositories/inventory_snapshots_repository.h +++ b/common/repositories/inventory_snapshots_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_inventory_snapshots_repository.h" diff --git a/common/repositories/inventory_versions_repository.h b/common/repositories/inventory_versions_repository.h index 4799273ea4..d759fb3681 100644 --- a/common/repositories/inventory_versions_repository.h +++ b/common/repositories/inventory_versions_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/database.h" diff --git a/common/repositories/ip_exemptions_repository.h b/common/repositories/ip_exemptions_repository.h index 53a69013ff..7b5081fa4b 100644 --- a/common/repositories/ip_exemptions_repository.h +++ b/common/repositories/ip_exemptions_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_ip_exemptions_repository.h" diff --git a/common/repositories/items_evolving_details_repository.h b/common/repositories/items_evolving_details_repository.h index 8890b721a6..90a1c58caf 100644 --- a/common/repositories/items_evolving_details_repository.h +++ b/common/repositories/items_evolving_details_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_items_evolving_details_repository.h" diff --git a/common/repositories/items_repository.h b/common/repositories/items_repository.h index 6e3d8875c2..63fb79a99f 100644 --- a/common/repositories/items_repository.h +++ b/common/repositories/items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_items_repository.h" diff --git a/common/repositories/keyring_repository.h b/common/repositories/keyring_repository.h index cab495dca5..f54e5b10ab 100644 --- a/common/repositories/keyring_repository.h +++ b/common/repositories/keyring_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_keyring_repository.h" diff --git a/common/repositories/ldon_trap_entries_repository.h b/common/repositories/ldon_trap_entries_repository.h index 0f1a421e1d..f4b7354849 100644 --- a/common/repositories/ldon_trap_entries_repository.h +++ b/common/repositories/ldon_trap_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_ldon_trap_entries_repository.h" diff --git a/common/repositories/ldon_trap_templates_repository.h b/common/repositories/ldon_trap_templates_repository.h index b2b8145aec..efb32a0873 100644 --- a/common/repositories/ldon_trap_templates_repository.h +++ b/common/repositories/ldon_trap_templates_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_ldon_trap_templates_repository.h" diff --git a/common/repositories/level_exp_mods_repository.h b/common/repositories/level_exp_mods_repository.h index 032febba0d..7100000ead 100644 --- a/common/repositories/level_exp_mods_repository.h +++ b/common/repositories/level_exp_mods_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_level_exp_mods_repository.h" diff --git a/common/repositories/lfguild_repository.h b/common/repositories/lfguild_repository.h index f7ddbadcd4..c110bba745 100644 --- a/common/repositories/lfguild_repository.h +++ b/common/repositories/lfguild_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_lfguild_repository.h" diff --git a/common/repositories/login_accounts_repository.h b/common/repositories/login_accounts_repository.h index c9002454b3..94d9c615e4 100644 --- a/common/repositories/login_accounts_repository.h +++ b/common/repositories/login_accounts_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_login_accounts_repository.h" diff --git a/common/repositories/login_api_tokens_repository.h b/common/repositories/login_api_tokens_repository.h index f7060fd713..1e605d718e 100644 --- a/common/repositories/login_api_tokens_repository.h +++ b/common/repositories/login_api_tokens_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_login_api_tokens_repository.h" diff --git a/common/repositories/login_server_admins_repository.h b/common/repositories/login_server_admins_repository.h index e68abae36e..5845328969 100644 --- a/common/repositories/login_server_admins_repository.h +++ b/common/repositories/login_server_admins_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_login_server_admins_repository.h" diff --git a/common/repositories/login_server_list_types_repository.h b/common/repositories/login_server_list_types_repository.h index 6539c44603..ac80f8a4d0 100644 --- a/common/repositories/login_server_list_types_repository.h +++ b/common/repositories/login_server_list_types_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_login_server_list_types_repository.h" diff --git a/common/repositories/login_world_servers_repository.h b/common/repositories/login_world_servers_repository.h index 797871abff..e49bba0a06 100644 --- a/common/repositories/login_world_servers_repository.h +++ b/common/repositories/login_world_servers_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_login_world_servers_repository.h" diff --git a/common/repositories/logsys_categories_repository.h b/common/repositories/logsys_categories_repository.h index d523713a08..4cf73e1dea 100644 --- a/common/repositories/logsys_categories_repository.h +++ b/common/repositories/logsys_categories_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_logsys_categories_repository.h" diff --git a/common/repositories/lootdrop_entries_repository.h b/common/repositories/lootdrop_entries_repository.h index cd940c687f..3d1343b599 100644 --- a/common/repositories/lootdrop_entries_repository.h +++ b/common/repositories/lootdrop_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_lootdrop_entries_repository.h" diff --git a/common/repositories/lootdrop_repository.h b/common/repositories/lootdrop_repository.h index 1f50198b56..cad212f018 100644 --- a/common/repositories/lootdrop_repository.h +++ b/common/repositories/lootdrop_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_lootdrop_repository.h" diff --git a/common/repositories/loottable_entries_repository.h b/common/repositories/loottable_entries_repository.h index aed594a838..ea84e9628b 100644 --- a/common/repositories/loottable_entries_repository.h +++ b/common/repositories/loottable_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_loottable_entries_repository.h" diff --git a/common/repositories/loottable_repository.h b/common/repositories/loottable_repository.h index 4b301e4822..20167546cd 100644 --- a/common/repositories/loottable_repository.h +++ b/common/repositories/loottable_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_loottable_repository.h" diff --git a/common/repositories/mail_repository.h b/common/repositories/mail_repository.h index 365c938fd0..7c2f14afd9 100644 --- a/common/repositories/mail_repository.h +++ b/common/repositories/mail_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_mail_repository.h" diff --git a/common/repositories/merc_armorinfo_repository.h b/common/repositories/merc_armorinfo_repository.h index 210589e2ba..30a570ee17 100644 --- a/common/repositories/merc_armorinfo_repository.h +++ b/common/repositories/merc_armorinfo_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_armorinfo_repository.h" diff --git a/common/repositories/merc_buffs_repository.h b/common/repositories/merc_buffs_repository.h index eb6540a9eb..e0a9fb5ab3 100644 --- a/common/repositories/merc_buffs_repository.h +++ b/common/repositories/merc_buffs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_buffs_repository.h" diff --git a/common/repositories/merc_inventory_repository.h b/common/repositories/merc_inventory_repository.h index 8068613966..d1591c7eff 100644 --- a/common/repositories/merc_inventory_repository.h +++ b/common/repositories/merc_inventory_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_inventory_repository.h" diff --git a/common/repositories/merc_merchant_entries_repository.h b/common/repositories/merc_merchant_entries_repository.h index 4714a532d0..2b642fdbbd 100644 --- a/common/repositories/merc_merchant_entries_repository.h +++ b/common/repositories/merc_merchant_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_merchant_entries_repository.h" diff --git a/common/repositories/merc_merchant_template_entries_repository.h b/common/repositories/merc_merchant_template_entries_repository.h index 0059411bc2..2f5ce26718 100644 --- a/common/repositories/merc_merchant_template_entries_repository.h +++ b/common/repositories/merc_merchant_template_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_merchant_template_entries_repository.h" diff --git a/common/repositories/merc_merchant_templates_repository.h b/common/repositories/merc_merchant_templates_repository.h index 8069e6fa77..bdd3b44e35 100644 --- a/common/repositories/merc_merchant_templates_repository.h +++ b/common/repositories/merc_merchant_templates_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_merchant_templates_repository.h" diff --git a/common/repositories/merc_name_types_repository.h b/common/repositories/merc_name_types_repository.h index bcca5e38ad..ffb13a05fe 100644 --- a/common/repositories/merc_name_types_repository.h +++ b/common/repositories/merc_name_types_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_name_types_repository.h" diff --git a/common/repositories/merc_npc_types_repository.h b/common/repositories/merc_npc_types_repository.h index e91957795c..ef7b47af94 100644 --- a/common/repositories/merc_npc_types_repository.h +++ b/common/repositories/merc_npc_types_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_npc_types_repository.h" diff --git a/common/repositories/merc_spell_list_entries_repository.h b/common/repositories/merc_spell_list_entries_repository.h index 3566c82db0..527eb83248 100644 --- a/common/repositories/merc_spell_list_entries_repository.h +++ b/common/repositories/merc_spell_list_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_spell_list_entries_repository.h" diff --git a/common/repositories/merc_spell_lists_repository.h b/common/repositories/merc_spell_lists_repository.h index 4196216b52..4221e233f0 100644 --- a/common/repositories/merc_spell_lists_repository.h +++ b/common/repositories/merc_spell_lists_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_spell_lists_repository.h" diff --git a/common/repositories/merc_stance_entries_repository.h b/common/repositories/merc_stance_entries_repository.h index 4c5b6c3bde..2558879c72 100644 --- a/common/repositories/merc_stance_entries_repository.h +++ b/common/repositories/merc_stance_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_stance_entries_repository.h" diff --git a/common/repositories/merc_stats_repository.h b/common/repositories/merc_stats_repository.h index 4b2f7618c9..c5517249f3 100644 --- a/common/repositories/merc_stats_repository.h +++ b/common/repositories/merc_stats_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_stats_repository.h" diff --git a/common/repositories/merc_subtypes_repository.h b/common/repositories/merc_subtypes_repository.h index a18a7c9955..3a73189e05 100644 --- a/common/repositories/merc_subtypes_repository.h +++ b/common/repositories/merc_subtypes_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_subtypes_repository.h" diff --git a/common/repositories/merc_templates_repository.h b/common/repositories/merc_templates_repository.h index 7c98393f17..b77c45345a 100644 --- a/common/repositories/merc_templates_repository.h +++ b/common/repositories/merc_templates_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_templates_repository.h" diff --git a/common/repositories/merc_types_repository.h b/common/repositories/merc_types_repository.h index baf014bec8..3bfada2fd9 100644 --- a/common/repositories/merc_types_repository.h +++ b/common/repositories/merc_types_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_types_repository.h" diff --git a/common/repositories/merc_weaponinfo_repository.h b/common/repositories/merc_weaponinfo_repository.h index 49642e26f0..a4d8a6af40 100644 --- a/common/repositories/merc_weaponinfo_repository.h +++ b/common/repositories/merc_weaponinfo_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merc_weaponinfo_repository.h" diff --git a/common/repositories/merchantlist_repository.h b/common/repositories/merchantlist_repository.h index 3d94d6189c..f3a2dd57f4 100644 --- a/common/repositories/merchantlist_repository.h +++ b/common/repositories/merchantlist_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merchantlist_repository.h" diff --git a/common/repositories/merchantlist_temp_repository.h b/common/repositories/merchantlist_temp_repository.h index 74d3802073..7af4242672 100644 --- a/common/repositories/merchantlist_temp_repository.h +++ b/common/repositories/merchantlist_temp_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_merchantlist_temp_repository.h" diff --git a/common/repositories/mercs_repository.h b/common/repositories/mercs_repository.h index cdfeea6a83..3c03259f6a 100644 --- a/common/repositories/mercs_repository.h +++ b/common/repositories/mercs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_mercs_repository.h" diff --git a/common/repositories/name_filter_repository.h b/common/repositories/name_filter_repository.h index a5d6d6cf54..8b90a50c3d 100644 --- a/common/repositories/name_filter_repository.h +++ b/common/repositories/name_filter_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_name_filter_repository.h" diff --git a/common/repositories/npc_emotes_repository.h b/common/repositories/npc_emotes_repository.h index 7f18f82c8b..7e44e55e4c 100644 --- a/common/repositories/npc_emotes_repository.h +++ b/common/repositories/npc_emotes_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_npc_emotes_repository.h" diff --git a/common/repositories/npc_faction_entries_repository.h b/common/repositories/npc_faction_entries_repository.h index 2669b52a6e..dfea70279d 100644 --- a/common/repositories/npc_faction_entries_repository.h +++ b/common/repositories/npc_faction_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_npc_faction_entries_repository.h" diff --git a/common/repositories/npc_faction_repository.h b/common/repositories/npc_faction_repository.h index 3a6eddfa7e..025682d6e4 100644 --- a/common/repositories/npc_faction_repository.h +++ b/common/repositories/npc_faction_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_npc_faction_repository.h" diff --git a/common/repositories/npc_scale_global_base_repository.h b/common/repositories/npc_scale_global_base_repository.h index 8f46986ccf..065787c3d2 100644 --- a/common/repositories/npc_scale_global_base_repository.h +++ b/common/repositories/npc_scale_global_base_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_npc_scale_global_base_repository.h" diff --git a/common/repositories/npc_spells_effects_entries_repository.h b/common/repositories/npc_spells_effects_entries_repository.h index c05736ac9d..25baa2c6e1 100644 --- a/common/repositories/npc_spells_effects_entries_repository.h +++ b/common/repositories/npc_spells_effects_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_npc_spells_effects_entries_repository.h" diff --git a/common/repositories/npc_spells_effects_repository.h b/common/repositories/npc_spells_effects_repository.h index d38c0f1e70..218f17833d 100644 --- a/common/repositories/npc_spells_effects_repository.h +++ b/common/repositories/npc_spells_effects_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_npc_spells_effects_repository.h" diff --git a/common/repositories/npc_spells_entries_repository.h b/common/repositories/npc_spells_entries_repository.h index c2448e2a1e..c8ba976fa4 100644 --- a/common/repositories/npc_spells_entries_repository.h +++ b/common/repositories/npc_spells_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_npc_spells_entries_repository.h" diff --git a/common/repositories/npc_spells_repository.h b/common/repositories/npc_spells_repository.h index 3dabf66fb6..a635f95e8e 100644 --- a/common/repositories/npc_spells_repository.h +++ b/common/repositories/npc_spells_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_npc_spells_repository.h" diff --git a/common/repositories/npc_types_repository.h b/common/repositories/npc_types_repository.h index 90571ce259..7280a730b2 100644 --- a/common/repositories/npc_types_repository.h +++ b/common/repositories/npc_types_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_npc_types_repository.h" diff --git a/common/repositories/npc_types_tint_repository.h b/common/repositories/npc_types_tint_repository.h index 56fa452076..642cfd077b 100644 --- a/common/repositories/npc_types_tint_repository.h +++ b/common/repositories/npc_types_tint_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_npc_types_tint_repository.h" diff --git a/common/repositories/object_contents_repository.h b/common/repositories/object_contents_repository.h index 15e4621e07..181f8fe15a 100644 --- a/common/repositories/object_contents_repository.h +++ b/common/repositories/object_contents_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_object_contents_repository.h" diff --git a/common/repositories/object_repository.h b/common/repositories/object_repository.h index 304db497e1..b59b3ca55a 100644 --- a/common/repositories/object_repository.h +++ b/common/repositories/object_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_object_repository.h" diff --git a/common/repositories/perl_event_export_settings_repository.h b/common/repositories/perl_event_export_settings_repository.h index 9f28296ed6..c5d60f36af 100644 --- a/common/repositories/perl_event_export_settings_repository.h +++ b/common/repositories/perl_event_export_settings_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_perl_event_export_settings_repository.h" diff --git a/common/repositories/petitions_repository.h b/common/repositories/petitions_repository.h index 6efc97766c..b1cfb49ca0 100644 --- a/common/repositories/petitions_repository.h +++ b/common/repositories/petitions_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_petitions_repository.h" diff --git a/common/repositories/pets_beastlord_data_repository.h b/common/repositories/pets_beastlord_data_repository.h index 83941df8f8..0ef90a7d7a 100644 --- a/common/repositories/pets_beastlord_data_repository.h +++ b/common/repositories/pets_beastlord_data_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_pets_beastlord_data_repository.h" diff --git a/common/repositories/pets_equipmentset_entries_repository.h b/common/repositories/pets_equipmentset_entries_repository.h index 3a87b12d3b..cc2338e586 100644 --- a/common/repositories/pets_equipmentset_entries_repository.h +++ b/common/repositories/pets_equipmentset_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_pets_equipmentset_entries_repository.h" diff --git a/common/repositories/pets_equipmentset_repository.h b/common/repositories/pets_equipmentset_repository.h index 36fd58265c..c198ad9769 100644 --- a/common/repositories/pets_equipmentset_repository.h +++ b/common/repositories/pets_equipmentset_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_pets_equipmentset_repository.h" diff --git a/common/repositories/pets_repository.h b/common/repositories/pets_repository.h index 0bb89634dc..0ed6d44079 100644 --- a/common/repositories/pets_repository.h +++ b/common/repositories/pets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_pets_repository.h" diff --git a/common/repositories/player_event_aa_purchase_repository.h b/common/repositories/player_event_aa_purchase_repository.h index b4402364b5..a7bccdf241 100644 --- a/common/repositories/player_event_aa_purchase_repository.h +++ b/common/repositories/player_event_aa_purchase_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_aa_purchase_repository.h" diff --git a/common/repositories/player_event_killed_named_npc_repository.h b/common/repositories/player_event_killed_named_npc_repository.h index b68a9bf258..1304f3dab7 100644 --- a/common/repositories/player_event_killed_named_npc_repository.h +++ b/common/repositories/player_event_killed_named_npc_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_killed_named_npc_repository.h" diff --git a/common/repositories/player_event_killed_npc_repository.h b/common/repositories/player_event_killed_npc_repository.h index 1cc9cef657..4c0e0c098d 100644 --- a/common/repositories/player_event_killed_npc_repository.h +++ b/common/repositories/player_event_killed_npc_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_killed_npc_repository.h" diff --git a/common/repositories/player_event_killed_raid_npc_repository.h b/common/repositories/player_event_killed_raid_npc_repository.h index c9f27ca081..7ce8baf629 100644 --- a/common/repositories/player_event_killed_raid_npc_repository.h +++ b/common/repositories/player_event_killed_raid_npc_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_killed_raid_npc_repository.h" diff --git a/common/repositories/player_event_log_settings_repository.h b/common/repositories/player_event_log_settings_repository.h index 455de33059..75af760da9 100644 --- a/common/repositories/player_event_log_settings_repository.h +++ b/common/repositories/player_event_log_settings_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_log_settings_repository.h" diff --git a/common/repositories/player_event_logs_repository.h b/common/repositories/player_event_logs_repository.h index 5df841bce5..24738af2f7 100644 --- a/common/repositories/player_event_logs_repository.h +++ b/common/repositories/player_event_logs_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_logs_repository.h" diff --git a/common/repositories/player_event_loot_items_repository.h b/common/repositories/player_event_loot_items_repository.h index 75241dfb7e..2009479aba 100644 --- a/common/repositories/player_event_loot_items_repository.h +++ b/common/repositories/player_event_loot_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_loot_items_repository.h" diff --git a/common/repositories/player_event_merchant_purchase_repository.h b/common/repositories/player_event_merchant_purchase_repository.h index 760d97f30a..04bec10e0c 100644 --- a/common/repositories/player_event_merchant_purchase_repository.h +++ b/common/repositories/player_event_merchant_purchase_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_merchant_purchase_repository.h" diff --git a/common/repositories/player_event_merchant_sell_repository.h b/common/repositories/player_event_merchant_sell_repository.h index ef11cd9f1c..e7fee96f09 100644 --- a/common/repositories/player_event_merchant_sell_repository.h +++ b/common/repositories/player_event_merchant_sell_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_merchant_sell_repository.h" diff --git a/common/repositories/player_event_npc_handin_entries_repository.h b/common/repositories/player_event_npc_handin_entries_repository.h index 76503cf5bb..826079a370 100644 --- a/common/repositories/player_event_npc_handin_entries_repository.h +++ b/common/repositories/player_event_npc_handin_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_npc_handin_entries_repository.h" diff --git a/common/repositories/player_event_npc_handin_repository.h b/common/repositories/player_event_npc_handin_repository.h index ead99fc9c1..8c235d9c90 100644 --- a/common/repositories/player_event_npc_handin_repository.h +++ b/common/repositories/player_event_npc_handin_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_npc_handin_repository.h" diff --git a/common/repositories/player_event_speech_repository.h b/common/repositories/player_event_speech_repository.h index 65d1590501..1e2104000e 100644 --- a/common/repositories/player_event_speech_repository.h +++ b/common/repositories/player_event_speech_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_speech_repository.h" diff --git a/common/repositories/player_event_trade_entries_repository.h b/common/repositories/player_event_trade_entries_repository.h index 832e6e9f3a..4a396353b7 100644 --- a/common/repositories/player_event_trade_entries_repository.h +++ b/common/repositories/player_event_trade_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_trade_entries_repository.h" diff --git a/common/repositories/player_event_trade_repository.h b/common/repositories/player_event_trade_repository.h index 119c2b334b..10e1090a8d 100644 --- a/common/repositories/player_event_trade_repository.h +++ b/common/repositories/player_event_trade_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_event_trade_repository.h" diff --git a/common/repositories/player_titlesets_repository.h b/common/repositories/player_titlesets_repository.h index 62e46c420d..1976b583a2 100644 --- a/common/repositories/player_titlesets_repository.h +++ b/common/repositories/player_titlesets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_player_titlesets_repository.h" diff --git a/common/repositories/quest_globals_repository.h b/common/repositories/quest_globals_repository.h index 7b2c9696c3..7d407a25b5 100644 --- a/common/repositories/quest_globals_repository.h +++ b/common/repositories/quest_globals_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_quest_globals_repository.h" diff --git a/common/repositories/raid_details_repository.h b/common/repositories/raid_details_repository.h index 967915e2e3..7b9e71f3bc 100644 --- a/common/repositories/raid_details_repository.h +++ b/common/repositories/raid_details_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_raid_details_repository.h" diff --git a/common/repositories/raid_members_repository.h b/common/repositories/raid_members_repository.h index 0807b99c43..2c8f214cf5 100644 --- a/common/repositories/raid_members_repository.h +++ b/common/repositories/raid_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_raid_members_repository.h" diff --git a/common/repositories/reports_repository.h b/common/repositories/reports_repository.h index e14a8089c2..5ecce10357 100644 --- a/common/repositories/reports_repository.h +++ b/common/repositories/reports_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_reports_repository.h" diff --git a/common/repositories/respawn_times_repository.h b/common/repositories/respawn_times_repository.h index a0abf793aa..8938209253 100644 --- a/common/repositories/respawn_times_repository.h +++ b/common/repositories/respawn_times_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_respawn_times_repository.h" diff --git a/common/repositories/rule_sets_repository.h b/common/repositories/rule_sets_repository.h index bcd7a0bfa6..3eef2ac63d 100644 --- a/common/repositories/rule_sets_repository.h +++ b/common/repositories/rule_sets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_rule_sets_repository.h" diff --git a/common/repositories/rule_values_repository.h b/common/repositories/rule_values_repository.h index e64ed9a6ae..162ee71353 100644 --- a/common/repositories/rule_values_repository.h +++ b/common/repositories/rule_values_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_rule_values_repository.h" diff --git a/common/repositories/saylink_repository.h b/common/repositories/saylink_repository.h index 41baebb4bd..60f253f930 100644 --- a/common/repositories/saylink_repository.h +++ b/common/repositories/saylink_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_saylink_repository.h" diff --git a/common/repositories/server_scheduled_events_repository.h b/common/repositories/server_scheduled_events_repository.h index c5e29a9442..83c670f4bc 100644 --- a/common/repositories/server_scheduled_events_repository.h +++ b/common/repositories/server_scheduled_events_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_server_scheduled_events_repository.h" diff --git a/common/repositories/shared_task_activity_state_repository.h b/common/repositories/shared_task_activity_state_repository.h index 2ce9aa7dd5..a7995c9ec1 100644 --- a/common/repositories/shared_task_activity_state_repository.h +++ b/common/repositories/shared_task_activity_state_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_shared_task_activity_state_repository.h" diff --git a/common/repositories/shared_task_dynamic_zones_repository.h b/common/repositories/shared_task_dynamic_zones_repository.h index 5c98b30014..c813bdd46b 100644 --- a/common/repositories/shared_task_dynamic_zones_repository.h +++ b/common/repositories/shared_task_dynamic_zones_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_shared_task_dynamic_zones_repository.h" diff --git a/common/repositories/shared_task_members_repository.h b/common/repositories/shared_task_members_repository.h index a1ee1f62c1..19a40fef56 100644 --- a/common/repositories/shared_task_members_repository.h +++ b/common/repositories/shared_task_members_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_shared_task_members_repository.h" diff --git a/common/repositories/shared_tasks_repository.h b/common/repositories/shared_tasks_repository.h index f073fe3744..747f749b33 100644 --- a/common/repositories/shared_tasks_repository.h +++ b/common/repositories/shared_tasks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_shared_tasks_repository.h" diff --git a/common/repositories/sharedbank_repository.h b/common/repositories/sharedbank_repository.h index 7684a92122..bdd2ab787f 100644 --- a/common/repositories/sharedbank_repository.h +++ b/common/repositories/sharedbank_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_sharedbank_repository.h" diff --git a/common/repositories/skill_caps_repository.h b/common/repositories/skill_caps_repository.h index b41f8b204e..179103f7fb 100644 --- a/common/repositories/skill_caps_repository.h +++ b/common/repositories/skill_caps_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_skill_caps_repository.h" diff --git a/common/repositories/spawn2_disabled_repository.h b/common/repositories/spawn2_disabled_repository.h index 41ee133eba..1aaed0bc27 100644 --- a/common/repositories/spawn2_disabled_repository.h +++ b/common/repositories/spawn2_disabled_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_spawn2_disabled_repository.h" diff --git a/common/repositories/spawn2_repository.h b/common/repositories/spawn2_repository.h index b980f26d78..b41bdd22fb 100644 --- a/common/repositories/spawn2_repository.h +++ b/common/repositories/spawn2_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_spawn2_repository.h" diff --git a/common/repositories/spawn_condition_values_repository.h b/common/repositories/spawn_condition_values_repository.h index 22deebe3bd..766e030f88 100644 --- a/common/repositories/spawn_condition_values_repository.h +++ b/common/repositories/spawn_condition_values_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_spawn_condition_values_repository.h" diff --git a/common/repositories/spawn_conditions_repository.h b/common/repositories/spawn_conditions_repository.h index a55f5be725..cdf8dd0fd6 100644 --- a/common/repositories/spawn_conditions_repository.h +++ b/common/repositories/spawn_conditions_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_spawn_conditions_repository.h" diff --git a/common/repositories/spawn_events_repository.h b/common/repositories/spawn_events_repository.h index 294da1d962..ab2dc1196d 100644 --- a/common/repositories/spawn_events_repository.h +++ b/common/repositories/spawn_events_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_spawn_events_repository.h" diff --git a/common/repositories/spawnentry_repository.h b/common/repositories/spawnentry_repository.h index 89bc58d0a8..a85e9afb8d 100644 --- a/common/repositories/spawnentry_repository.h +++ b/common/repositories/spawnentry_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_spawnentry_repository.h" diff --git a/common/repositories/spawngroup_repository.h b/common/repositories/spawngroup_repository.h index 5377305d03..418e146fa1 100644 --- a/common/repositories/spawngroup_repository.h +++ b/common/repositories/spawngroup_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_spawngroup_repository.h" diff --git a/common/repositories/spell_buckets_repository.h b/common/repositories/spell_buckets_repository.h index f09da8056b..802df254ea 100644 --- a/common/repositories/spell_buckets_repository.h +++ b/common/repositories/spell_buckets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_spell_buckets_repository.h" diff --git a/common/repositories/spell_globals_repository.h b/common/repositories/spell_globals_repository.h index 54f40a4bed..ea60d966b7 100644 --- a/common/repositories/spell_globals_repository.h +++ b/common/repositories/spell_globals_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_spell_globals_repository.h" diff --git a/common/repositories/spells_new_repository.h b/common/repositories/spells_new_repository.h index 1f32fe2ee0..9191579f72 100644 --- a/common/repositories/spells_new_repository.h +++ b/common/repositories/spells_new_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_spells_new_repository.h" diff --git a/common/repositories/start_zones_repository.h b/common/repositories/start_zones_repository.h index 70951a1101..99cd75accf 100644 --- a/common/repositories/start_zones_repository.h +++ b/common/repositories/start_zones_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_start_zones_repository.h" diff --git a/common/repositories/starting_items_repository.h b/common/repositories/starting_items_repository.h index dbb01fffe4..616000963e 100644 --- a/common/repositories/starting_items_repository.h +++ b/common/repositories/starting_items_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_starting_items_repository.h" diff --git a/common/repositories/task_activities_repository.h b/common/repositories/task_activities_repository.h index 70e1f9ae86..01d6cde5a2 100644 --- a/common/repositories/task_activities_repository.h +++ b/common/repositories/task_activities_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_task_activities_repository.h" diff --git a/common/repositories/tasks_repository.h b/common/repositories/tasks_repository.h index b1c4bd82ed..9e0f5d938a 100644 --- a/common/repositories/tasks_repository.h +++ b/common/repositories/tasks_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_tasks_repository.h" diff --git a/common/repositories/tasksets_repository.h b/common/repositories/tasksets_repository.h index a9a1edc3eb..f7db77dcb5 100644 --- a/common/repositories/tasksets_repository.h +++ b/common/repositories/tasksets_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_tasksets_repository.h" diff --git a/common/repositories/timers_repository.h b/common/repositories/timers_repository.h index 3658615be0..2b41bd8bd0 100644 --- a/common/repositories/timers_repository.h +++ b/common/repositories/timers_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_timers_repository.h" diff --git a/common/repositories/titles_repository.h b/common/repositories/titles_repository.h index 6927b9dd6d..b8d4df8987 100644 --- a/common/repositories/titles_repository.h +++ b/common/repositories/titles_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_titles_repository.h" diff --git a/common/repositories/tool_game_objects_repository.h b/common/repositories/tool_game_objects_repository.h index fe7fb9f356..fcf22bc3a4 100644 --- a/common/repositories/tool_game_objects_repository.h +++ b/common/repositories/tool_game_objects_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_tool_game_objects_repository.h" diff --git a/common/repositories/trader_audit_repository.h b/common/repositories/trader_audit_repository.h index 3d6f90168f..648cdfa097 100644 --- a/common/repositories/trader_audit_repository.h +++ b/common/repositories/trader_audit_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/database.h" diff --git a/common/repositories/trader_repository.h b/common/repositories/trader_repository.h index 2dcc30dc73..fb756e1383 100644 --- a/common/repositories/trader_repository.h +++ b/common/repositories/trader_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_trader_repository.h" diff --git a/common/repositories/tradeskill_recipe_entries_repository.h b/common/repositories/tradeskill_recipe_entries_repository.h index a94cb5d82c..2c0c0c4d0e 100644 --- a/common/repositories/tradeskill_recipe_entries_repository.h +++ b/common/repositories/tradeskill_recipe_entries_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_tradeskill_recipe_entries_repository.h" diff --git a/common/repositories/tradeskill_recipe_repository.h b/common/repositories/tradeskill_recipe_repository.h index f1a07dfed9..9022212cc5 100644 --- a/common/repositories/tradeskill_recipe_repository.h +++ b/common/repositories/tradeskill_recipe_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_tradeskill_recipe_repository.h" diff --git a/common/repositories/traps_repository.h b/common/repositories/traps_repository.h index 4e3f60f8b1..7be805f1f4 100644 --- a/common/repositories/traps_repository.h +++ b/common/repositories/traps_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_traps_repository.h" diff --git a/common/repositories/tribute_levels_repository.h b/common/repositories/tribute_levels_repository.h index 01705b6244..11787b36e8 100644 --- a/common/repositories/tribute_levels_repository.h +++ b/common/repositories/tribute_levels_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_tribute_levels_repository.h" diff --git a/common/repositories/tributes_repository.h b/common/repositories/tributes_repository.h index 93371daa7c..4110739146 100644 --- a/common/repositories/tributes_repository.h +++ b/common/repositories/tributes_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_tributes_repository.h" diff --git a/common/repositories/variables_repository.h b/common/repositories/variables_repository.h index bb66dc385e..6303dfdb91 100644 --- a/common/repositories/variables_repository.h +++ b/common/repositories/variables_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_variables_repository.h" diff --git a/common/repositories/veteran_reward_templates_repository.h b/common/repositories/veteran_reward_templates_repository.h index 0cb39af840..31652a83ba 100644 --- a/common/repositories/veteran_reward_templates_repository.h +++ b/common/repositories/veteran_reward_templates_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_veteran_reward_templates_repository.h" diff --git a/common/repositories/zone_flags_repository.h b/common/repositories/zone_flags_repository.h index 339d1d48d7..6927b12141 100644 --- a/common/repositories/zone_flags_repository.h +++ b/common/repositories/zone_flags_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_zone_flags_repository.h" diff --git a/common/repositories/zone_points_repository.h b/common/repositories/zone_points_repository.h index 6d410ab285..800d57c23b 100644 --- a/common/repositories/zone_points_repository.h +++ b/common/repositories/zone_points_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_zone_points_repository.h" diff --git a/common/repositories/zone_repository.h b/common/repositories/zone_repository.h index f4902f19f6..0713685a3c 100644 --- a/common/repositories/zone_repository.h +++ b/common/repositories/zone_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_zone_repository.h" diff --git a/common/repositories/zone_state_spawns_repository.h b/common/repositories/zone_state_spawns_repository.h index 8a3bbbdbab..0592ffb976 100644 --- a/common/repositories/zone_state_spawns_repository.h +++ b/common/repositories/zone_state_spawns_repository.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_zone_state_spawns_repository.h" diff --git a/common/rulesys.cpp b/common/rulesys.cpp index 27c5724f44..066aaaebbc 100644 --- a/common/rulesys.cpp +++ b/common/rulesys.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "rulesys.h" #include "common/database.h" diff --git a/common/rulesys.h b/common/rulesys.h index f6e7801363..a9ec3b64bf 100644 --- a/common/rulesys.h +++ b/common/rulesys.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/ruletypes.h b/common/ruletypes.h index 1e08a9cbdf..d9df94afd4 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #ifndef RULE_CATEGORY #define RULE_CATEGORY(name) #endif diff --git a/common/say_link.cpp b/common/say_link.cpp index ff67185887..6f0418b7f0 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "say_link.h" #include "common/emu_constants.h" diff --git a/common/say_link.h b/common/say_link.h index ee1e6566d6..6977fb88cf 100644 --- a/common/say_link.h +++ b/common/say_link.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/loot.h" diff --git a/common/seperator.h b/common/seperator.h index 443f1bf595..a9cdfc375b 100644 --- a/common/seperator.h +++ b/common/seperator.h @@ -1,19 +1,19 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ // This class will split up a string smartly at the div character (default is space and tab) // Seperator.arg[i] is a copy of the string chopped at the divs diff --git a/common/serialize_buffer.cpp b/common/serialize_buffer.cpp index 065bd9f2d8..8f69d7b967 100644 --- a/common/serialize_buffer.cpp +++ b/common/serialize_buffer.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "serialize_buffer.h" void SerializeBuffer::Grow(size_t new_size) diff --git a/common/serialize_buffer.h b/common/serialize_buffer.h index 1155d75068..fb3e2904e4 100644 --- a/common/serialize_buffer.h +++ b/common/serialize_buffer.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once diff --git a/common/server_event_scheduler.cpp b/common/server_event_scheduler.cpp index b7294c5ced..c087792c19 100644 --- a/common/server_event_scheduler.cpp +++ b/common/server_event_scheduler.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "server_event_scheduler.h" #include "common/cron/croncpp.h" diff --git a/common/server_event_scheduler.h b/common/server_event_scheduler.h index 480f4460ee..bb7cca6db9 100644 --- a/common/server_event_scheduler.h +++ b/common/server_event_scheduler.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/server_scheduled_events_repository.h" diff --git a/common/server_reload_types.h b/common/server_reload_types.h index 2446c10f6b..750ea46227 100644 --- a/common/server_reload_types.h +++ b/common/server_reload_types.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/common/serverinfo.cpp b/common/serverinfo.cpp index b80a95aa1a..26d02c09ff 100644 --- a/common/serverinfo.cpp +++ b/common/serverinfo.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "serverinfo.h" #include "uv.h" diff --git a/common/serverinfo.h b/common/serverinfo.h index e3301dfa5e..b2facc1120 100644 --- a/common/serverinfo.h +++ b/common/serverinfo.h @@ -1,19 +1,19 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ #pragma once diff --git a/common/servertalk.h b/common/servertalk.h index b41e998a59..e550dc5d1f 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eq_packet_structs.h" diff --git a/common/shared_tasks.cpp b/common/shared_tasks.cpp index deb76340b0..f5bfe1c1de 100644 --- a/common/shared_tasks.cpp +++ b/common/shared_tasks.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "shared_tasks.h" #include "common/repositories/character_data_repository.h" diff --git a/common/shared_tasks.h b/common/shared_tasks.h index 7b2255834b..31f7c56b84 100644 --- a/common/shared_tasks.h +++ b/common/shared_tasks.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/database.h" diff --git a/common/shareddb.cpp b/common/shareddb.cpp index a38bc8e303..3a39632873 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "shareddb.h" #include "common/classes.h" diff --git a/common/shareddb.h b/common/shareddb.h index 559570fc97..76f8c63a56 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -1,23 +1,20 @@ -/** - * 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/database.h" diff --git a/common/skill_caps.cpp b/common/skill_caps.cpp index b7436a3a6a..28cfe53ead 100644 --- a/common/skill_caps.cpp +++ b/common/skill_caps.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "skill_caps.h" #include "common/timer.h" diff --git a/common/skill_caps.h b/common/skill_caps.h index a83d183e14..135b99ae91 100644 --- a/common/skill_caps.h +++ b/common/skill_caps.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/classes.h" diff --git a/common/skills.cpp b/common/skills.cpp index 96a7ca27dd..6193e10524 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "skills.h" #include "common/classes.h" diff --git a/common/skills.h b/common/skills.h index 2f61c23146..f486e2359f 100644 --- a/common/skills.h +++ b/common/skills.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/spdat.cpp b/common/spdat.cpp index 6c5eaf62e7..1df6e55e51 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "spdat.h" #include "common/classes.h" diff --git a/common/spdat.h b/common/spdat.h index ca35734013..7488a0f588 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/classes.h" diff --git a/common/spdat_bot.cpp b/common/spdat_bot.cpp index 23b7f50401..4601daf19b 100644 --- a/common/spdat_bot.cpp +++ b/common/spdat_bot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "spdat.h" #include "zone/bot.h" diff --git a/common/strings.cpp b/common/strings.cpp index 024d8e4417..7419de9bce 100644 --- a/common/strings.cpp +++ b/common/strings.cpp @@ -1,36 +1,19 @@ -// for folly stuff -/* - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// for our stuff -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2022 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ #include "strings.h" diff --git a/common/strings.h b/common/strings.h index e00c11ab0a..5a5b93debb 100644 --- a/common/strings.h +++ b/common/strings.h @@ -1,36 +1,19 @@ -// for folly stuff -/* - * Copyright 2013 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// for our stuff -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2022 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ #pragma once diff --git a/common/strings_legacy.cpp b/common/strings_legacy.cpp index a98d69c08c..8d75d5cb5c 100644 --- a/common/strings_legacy.cpp +++ b/common/strings_legacy.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/strings.h" #include "fmt/format.h" diff --git a/common/strings_misc.cpp b/common/strings_misc.cpp index bd21ecc5b6..6ccde6cb45 100644 --- a/common/strings_misc.cpp +++ b/common/strings_misc.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "strings.h" #include "fmt/format.h" diff --git a/common/struct_strategy.cpp b/common/struct_strategy.cpp index 0c7dc04dd5..71efe60b88 100644 --- a/common/struct_strategy.cpp +++ b/common/struct_strategy.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "struct_strategy.h" #include "common/eq_stream_intf.h" diff --git a/common/struct_strategy.h b/common/struct_strategy.h index 73df1d178b..db832fbc39 100644 --- a/common/struct_strategy.h +++ b/common/struct_strategy.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/emu_opcodes.h" diff --git a/common/tasks.h b/common/tasks.h index ad8887ecc0..ace848f4dd 100644 --- a/common/tasks.h +++ b/common/tasks.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/emu_versions.h" diff --git a/common/termcolor/rang.hpp b/common/termcolor/rang.hpp index 31d56e16c2..6529aba3be 100644 --- a/common/termcolor/rang.hpp +++ b/common/termcolor/rang.hpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifndef RANG_DOT_HPP #define RANG_DOT_HPP diff --git a/common/textures.cpp b/common/textures.cpp index 262b4786cf..c18ceee57a 100644 --- a/common/textures.cpp +++ b/common/textures.cpp @@ -1,20 +1,18 @@ -/* EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "textures.h" diff --git a/common/textures.h b/common/textures.h index 2f45f5eecf..4f0e81058f 100644 --- a/common/textures.h +++ b/common/textures.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/timeoutmgr.cpp b/common/timeoutmgr.cpp index b1b3d3e20f..9068ff2eae 100644 --- a/common/timeoutmgr.cpp +++ b/common/timeoutmgr.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "timeoutmgr.h" //#define TIMEOUT_DEBUG diff --git a/common/timeoutmgr.h b/common/timeoutmgr.h index e8a466d8d6..1993994f4f 100644 --- a/common/timeoutmgr.h +++ b/common/timeoutmgr.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/timer.h" diff --git a/common/timer.cpp b/common/timer.cpp index 63b8d6d4bb..a6c1bed6fc 100644 --- a/common/timer.cpp +++ b/common/timer.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "timer.h" // Disgrace: for windows compile diff --git a/common/timer.h b/common/timer.h index e7c343c8a9..b1abfa934e 100644 --- a/common/timer.h +++ b/common/timer.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/common/types.h b/common/types.h index ca00c76b28..25796d3239 100644 --- a/common/types.h +++ b/common/types.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include diff --git a/common/unix.cpp b/common/unix.cpp index afe3bfef6c..22a4df34b5 100644 --- a/common/unix.cpp +++ b/common/unix.cpp @@ -1,19 +1,19 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ #ifndef _WINDOWS diff --git a/common/unix.h b/common/unix.h index e593e3776b..2ec5752ce4 100644 --- a/common/unix.h +++ b/common/unix.h @@ -1,19 +1,19 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ #ifndef _WINDOWS diff --git a/common/useperl.h b/common/useperl.h index 5816944e6f..13e75f523e 100644 --- a/common/useperl.h +++ b/common/useperl.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once //headers from the Perl distribution diff --git a/common/util/directory.cpp b/common/util/directory.cpp index f8ed6b1494..3c2cc99129 100644 --- a/common/util/directory.cpp +++ b/common/util/directory.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "directory.h" #ifdef _WIN32 diff --git a/common/util/directory.h b/common/util/directory.h index d5f7441b27..532ff948ad 100644 --- a/common/util/directory.h +++ b/common/util/directory.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/util/memory_stream.h b/common/util/memory_stream.h index 9fc99d6012..3f98ce3aff 100644 --- a/common/util/memory_stream.h +++ b/common/util/memory_stream.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/util/uuid.cpp b/common/util/uuid.cpp index 0a6375ddbb..e3e09256d7 100644 --- a/common/util/uuid.cpp +++ b/common/util/uuid.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "uuid.h" #include "fmt/format.h" diff --git a/common/util/uuid.h b/common/util/uuid.h index 7a7c96d42e..1675ddf0b0 100644 --- a/common/util/uuid.h +++ b/common/util/uuid.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/common/version.h b/common/version.h index 9d4c3a688a..02f0640965 100644 --- a/common/version.h +++ b/common/version.h @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #define EQEMU_PROTOCOL_VERSION "0.3.10" diff --git a/common/zone_store.cpp b/common/zone_store.cpp index 1b3d1164e9..e195387c14 100644 --- a/common/zone_store.cpp +++ b/common/zone_store.cpp @@ -1,23 +1,20 @@ -/** - * 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 - * - */ - +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone_store.h" #include "common/content/world_content_service.h" diff --git a/common/zone_store.h b/common/zone_store.h index 48bded65cf..3ec27f543a 100644 --- a/common/zone_store.h +++ b/common/zone_store.h @@ -1,23 +1,20 @@ -/** - * 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 - * - */ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/base/base_content_flags_repository.h" diff --git a/eqlaunch/eqlaunch.cpp b/eqlaunch/eqlaunch.cpp index df5bad2f13..c1e9ad7a3c 100644 --- a/eqlaunch/eqlaunch.cpp +++ b/eqlaunch/eqlaunch.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/crash.h" #include "common/eqemu_config.h" #include "common/eqemu_logsys.h" diff --git a/eqlaunch/worldserver.cpp b/eqlaunch/worldserver.cpp index d51841ba36..5dc7913985 100644 --- a/eqlaunch/worldserver.cpp +++ b/eqlaunch/worldserver.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) - -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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "worldserver.h" #include "common/eqemu_config.h" diff --git a/eqlaunch/worldserver.h b/eqlaunch/worldserver.h index f0e20f2e5b..5ebd47736a 100644 --- a/eqlaunch/worldserver.h +++ b/eqlaunch/worldserver.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/net/servertalk_client_connection.h" diff --git a/eqlaunch/zone_launch.cpp b/eqlaunch/zone_launch.cpp index c848be2efd..101da70e26 100644 --- a/eqlaunch/zone_launch.cpp +++ b/eqlaunch/zone_launch.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "zone_launch.h" #include "common/eqemu_config.h" diff --git a/eqlaunch/zone_launch.h b/eqlaunch/zone_launch.h index f48d707541..032bc07a79 100644 --- a/eqlaunch/zone_launch.h +++ b/eqlaunch/zone_launch.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/proc_launcher.h" diff --git a/loginserver/account_management.cpp b/loginserver/account_management.cpp index d7e85072ba..77e98dbdfc 100644 --- a/loginserver/account_management.cpp +++ b/loginserver/account_management.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "account_management.h" #include "common/event/event_loop.h" diff --git a/loginserver/account_management.h b/loginserver/account_management.h index 3a0edc5e68..de1064d110 100644 --- a/loginserver/account_management.h +++ b/loginserver/account_management.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/loginserver/client.cpp b/loginserver/client.cpp index 754c83ab53..d9baf088f5 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "client.h" #include "login_server.h" #include "encryption.h" diff --git a/loginserver/client.h b/loginserver/client.h index 5baa4eebe7..e1767bece1 100644 --- a/loginserver/client.h +++ b/loginserver/client.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eq_stream_intf.h" diff --git a/loginserver/client_manager.cpp b/loginserver/client_manager.cpp index 87ea3ecd57..2c391e0a3a 100644 --- a/loginserver/client_manager.cpp +++ b/loginserver/client_manager.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "client_manager.h" #include "common/file.h" diff --git a/loginserver/client_manager.h b/loginserver/client_manager.h index c98313fbf0..1205135d3a 100644 --- a/loginserver/client_manager.h +++ b/loginserver/client_manager.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/net/eqstream.h" diff --git a/loginserver/encryption.cpp b/loginserver/encryption.cpp index 5c15f46d40..2ef0713bdf 100644 --- a/loginserver/encryption.cpp +++ b/loginserver/encryption.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "encryption.h" #ifdef EQEMU_USE_OPENSSL diff --git a/loginserver/encryption.h b/loginserver/encryption.h index b4b9242abd..4f188789d0 100644 --- a/loginserver/encryption.h +++ b/loginserver/encryption.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eqemu_logsys.h" diff --git a/loginserver/eq_crypto_api.h b/loginserver/eq_crypto_api.h index 87461543ca..edad678adc 100644 --- a/loginserver/eq_crypto_api.h +++ b/loginserver/eq_crypto_api.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once char* DecryptUsernamePassword(const char* encryptedBuffer, unsigned int bufferSize, int mode); diff --git a/loginserver/login_server.h b/loginserver/login_server.h index 4d006ac7b6..e77ddad905 100644 --- a/loginserver/login_server.h +++ b/loginserver/login_server.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/json_config.h" diff --git a/loginserver/login_types.h b/loginserver/login_types.h index b760eb7fe5..fb773c4446 100644 --- a/loginserver/login_types.h +++ b/loginserver/login_types.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/loginserver/loginserver_command_handler.cpp b/loginserver/loginserver_command_handler.cpp index d3552930a9..0a68a7a95d 100644 --- a/loginserver/loginserver_command_handler.cpp +++ b/loginserver/loginserver_command_handler.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "loginserver_command_handler.h" #include "common/repositories/login_api_tokens_repository.h" diff --git a/loginserver/loginserver_command_handler.h b/loginserver/loginserver_command_handler.h index 265fb046cb..d0bbc05dd4 100644 --- a/loginserver/loginserver_command_handler.h +++ b/loginserver/loginserver_command_handler.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/cli/eqemu_command_handler.h" diff --git a/loginserver/loginserver_webserver.cpp b/loginserver/loginserver_webserver.cpp index 2884e21080..2c6da410fc 100644 --- a/loginserver/loginserver_webserver.cpp +++ b/loginserver/loginserver_webserver.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "loginserver_webserver.h" #include "common/json/json.h" diff --git a/loginserver/loginserver_webserver.h b/loginserver/loginserver_webserver.h index 18972cbcb1..b53c431592 100644 --- a/loginserver/loginserver_webserver.h +++ b/loginserver/loginserver_webserver.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/http/httplib.h" diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 2aae375280..faa22e9553 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/crash.h" #include "common/database.h" #include "common/eqemu_logsys.h" diff --git a/loginserver/options.h b/loginserver/options.h index e2578454c5..8b98b0470f 100644 --- a/loginserver/options.h +++ b/loginserver/options.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/loginserver/world_server.cpp b/loginserver/world_server.cpp index 85b9d6c74f..b3967183ed 100644 --- a/loginserver/world_server.cpp +++ b/loginserver/world_server.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world_server.h" #include "common/ip_util.h" diff --git a/loginserver/world_server.h b/loginserver/world_server.h index 94ed4b4a72..7f247bb693 100644 --- a/loginserver/world_server.h +++ b/loginserver/world_server.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/net/servertalk_server_connection.h" diff --git a/loginserver/world_server_manager.cpp b/loginserver/world_server_manager.cpp index fdf917e7ed..118a58f5c6 100644 --- a/loginserver/world_server_manager.cpp +++ b/loginserver/world_server_manager.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world_server_manager.h" #include "common/eqemu_logsys.h" diff --git a/loginserver/world_server_manager.h b/loginserver/world_server_manager.h index 1885b16698..f81df1d3ac 100644 --- a/loginserver/world_server_manager.h +++ b/loginserver/world_server_manager.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/net/servertalk_server.h" diff --git a/queryserv/database.cpp b/queryserv/database.cpp index 99b125bbd8..4718cae96a 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "database.h" diff --git a/queryserv/database.h b/queryserv/database.h index 0f9cc6e2ad..9a76bc72c5 100644 --- a/queryserv/database.h +++ b/queryserv/database.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/database.h" diff --git a/queryserv/lfguild.cpp b/queryserv/lfguild.cpp index 07b12c4f48..2cf9229160 100644 --- a/queryserv/lfguild.cpp +++ b/queryserv/lfguild.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "lfguild.h" #include "common/rulesys.h" diff --git a/queryserv/lfguild.h b/queryserv/lfguild.h index 0f655e766b..4ac21b1a84 100644 --- a/queryserv/lfguild.h +++ b/queryserv/lfguild.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/servertalk.h" diff --git a/queryserv/queryserv.cpp b/queryserv/queryserv.cpp index 1d2ace974b..76fed0bd89 100644 --- a/queryserv/queryserv.cpp +++ b/queryserv/queryserv.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/crash.h" #include "common/eqemu_logsys.h" diff --git a/queryserv/queryservconfig.cpp b/queryserv/queryservconfig.cpp index 2db9604aec..32d41bbab3 100644 --- a/queryserv/queryservconfig.cpp +++ b/queryserv/queryservconfig.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 - + along with this program. If not, see . */ - #include "queryservconfig.h" diff --git a/queryserv/queryservconfig.h b/queryserv/queryservconfig.h index b7afa7a6d8..abaad8230f 100644 --- a/queryserv/queryservconfig.h +++ b/queryserv/queryservconfig.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 - + along with this program. If not, see . */ - #pragma once #include "common/eqemu_config.h" diff --git a/queryserv/worldserver.cpp b/queryserv/worldserver.cpp index 52591aac2b..ab8cca5bf5 100644 --- a/queryserv/worldserver.cpp +++ b/queryserv/worldserver.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "worldserver.h" #include "common/eqemu_logsys.h" diff --git a/queryserv/worldserver.h b/queryserv/worldserver.h index 54ad69bee3..3fc2c46204 100644 --- a/queryserv/worldserver.h +++ b/queryserv/worldserver.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eq_packet_structs.h" diff --git a/queryserv/zonelist.cpp b/queryserv/zonelist.cpp index 2b204c999f..21f02a33bc 100644 --- a/queryserv/zonelist.cpp +++ b/queryserv/zonelist.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zonelist.h" #include "queryserv/zoneserver.h" diff --git a/queryserv/zonelist.h b/queryserv/zonelist.h index dc8dc4f326..5301bcf83a 100644 --- a/queryserv/zonelist.h +++ b/queryserv/zonelist.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/queryserv/zoneserver.cpp b/queryserv/zoneserver.cpp index 05df12f5a5..350718ed19 100644 --- a/queryserv/zoneserver.cpp +++ b/queryserv/zoneserver.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zoneserver.h" #include "common/discord/discord_manager.h" diff --git a/queryserv/zoneserver.h b/queryserv/zoneserver.h index 374051c4bc..c43de57a22 100644 --- a/queryserv/zoneserver.h +++ b/queryserv/zoneserver.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/emu_constants.h" diff --git a/shared_memory/items.cpp b/shared_memory/items.cpp index b149e56e7a..719c9a7302 100644 --- a/shared_memory/items.cpp +++ b/shared_memory/items.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "items.h" #include "common/eqemu_exception.h" diff --git a/shared_memory/items.h b/shared_memory/items.h index 4bc891d90c..6ebab7fba1 100644 --- a/shared_memory/items.h +++ b/shared_memory/items.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eqemu_config.h" diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index 5d18d78a6b..323d34c2a3 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "shared_memory/items.h" #include "shared_memory/spells.h" #include "common/content/world_content_service.h" diff --git a/shared_memory/spells.cpp b/shared_memory/spells.cpp index d4c28d9498..45db6ac49c 100644 --- a/shared_memory/spells.cpp +++ b/shared_memory/spells.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "spells.h" #include "common/eqemu_exception.h" diff --git a/shared_memory/spells.h b/shared_memory/spells.h index f6fd196537..a05cb33bb6 100644 --- a/shared_memory/spells.h +++ b/shared_memory/spells.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eqemu_config.h" diff --git a/tests/atobool_test.h b/tests/atobool_test.h index 19da10d3ec..89e88c84bd 100644 --- a/tests/atobool_test.h +++ b/tests/atobool_test.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/strings.h" diff --git a/tests/data_verification_test.h b/tests/data_verification_test.h index e0af47bfee..c4cfd2280e 100644 --- a/tests/data_verification_test.h +++ b/tests/data_verification_test.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/data_verification.h" diff --git a/tests/fixed_memory_test.h b/tests/fixed_memory_test.h index c2059ab3b9..73ce7c4dbb 100644 --- a/tests/fixed_memory_test.h +++ b/tests/fixed_memory_test.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/fixed_memory_hash_set.h" diff --git a/tests/fixed_memory_variable_test.h b/tests/fixed_memory_variable_test.h index ea79487102..c91c0d03fe 100644 --- a/tests/fixed_memory_variable_test.h +++ b/tests/fixed_memory_variable_test.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/fixed_memory_variable_hash_set.h" diff --git a/tests/hextoi_32_64_test.h b/tests/hextoi_32_64_test.h index 119d66dc80..f7e6ba383b 100644 --- a/tests/hextoi_32_64_test.h +++ b/tests/hextoi_32_64_test.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/strings.h" diff --git a/tests/ipc_mutex_test.h b/tests/ipc_mutex_test.h index da2a930162..15fa4de453 100644 --- a/tests/ipc_mutex_test.h +++ b/tests/ipc_mutex_test.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eqemu_config.h" diff --git a/tests/main.cpp b/tests/main.cpp index cfec4abcd6..9eb5c90802 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "tests/atobool_test.h" #include "tests/data_verification_test.h" #include "tests/fixed_memory_test.h" diff --git a/tests/memory_mapped_file_test.h b/tests/memory_mapped_file_test.h index 75db90b53b..0c1802f60a 100644 --- a/tests/memory_mapped_file_test.h +++ b/tests/memory_mapped_file_test.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/memory_mapped_file.h" diff --git a/tests/skills_util_test.h b/tests/skills_util_test.h index da8f78181e..f20b271e90 100644 --- a/tests/skills_util_test.h +++ b/tests/skills_util_test.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/skills.h" diff --git a/tests/string_util_test.h b/tests/string_util_test.h index 1bcdb2fa9e..cb69436baf 100644 --- a/tests/string_util_test.h +++ b/tests/string_util_test.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/strings.h" diff --git a/tests/task_state_test.h b/tests/task_state_test.h index a271ca3f83..6517f28c79 100644 --- a/tests/task_state_test.h +++ b/tests/task_state_test.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eqemu_logsys.h" diff --git a/ucs/chatchannel.cpp b/ucs/chatchannel.cpp index 001bf58b76..33f7f6e7b0 100644 --- a/ucs/chatchannel.cpp +++ b/ucs/chatchannel.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 - + along with this program. If not, see . */ - #include "chatchannel.h" #include "common/eqemu_logsys.h" diff --git a/ucs/chatchannel.h b/ucs/chatchannel.h index 260a0a0eb1..3a263a0ea9 100644 --- a/ucs/chatchannel.h +++ b/ucs/chatchannel.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/linked_list.h" diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index 03ab790739..6fcf1fbd14 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator -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. + Copyright (C) 2001-2026 EQEmu Development Team -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. + 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; either version 3 of the License, or + (at your option) any later version. -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 + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . */ - #include "common/eqemu_logsys.h" #include "common/misc_functions.h" #include "common/path_manager.h" diff --git a/ucs/clientlist.h b/ucs/clientlist.h index 90d9fa1935..605e161263 100644 --- a/ucs/clientlist.h +++ b/ucs/clientlist.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 - + along with this program. If not, see . */ - #pragma once #include "common/net/eqstream.h" diff --git a/ucs/database.cpp b/ucs/database.cpp index 21df0c40b2..3a6b9da93a 100644 --- a/ucs/database.cpp +++ b/ucs/database.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 - + along with this program. If not, see . */ - #include "database.h" #include "common/eq_packet_structs.h" diff --git a/ucs/database.h b/ucs/database.h index 6bfbbeea9f..f5c2373b55 100644 --- a/ucs/database.h +++ b/ucs/database.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 - + along with this program. If not, see . */ - #pragma once #include "common/database.h" diff --git a/ucs/ucs.cpp b/ucs/ucs.cpp index 57b4630be4..26b8b21d6b 100644 --- a/ucs/ucs.cpp +++ b/ucs/ucs.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 - + along with this program. If not, see . */ - #include "common/crash.h" #include "common/discord/discord_manager.h" #include "common/eqemu_logsys.h" diff --git a/ucs/ucsconfig.cpp b/ucs/ucsconfig.cpp index 2d9d177830..080ae3ae8f 100644 --- a/ucs/ucsconfig.cpp +++ b/ucs/ucsconfig.cpp @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 - + along with this program. If not, see . */ - #include "ucsconfig.h" ucsconfig *ucsconfig::_chat_config = nullptr; diff --git a/ucs/ucsconfig.h b/ucs/ucsconfig.h index a6b8dc7787..ed43860c67 100644 --- a/ucs/ucsconfig.h +++ b/ucs/ucsconfig.h @@ -1,22 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 - + along with this program. If not, see . */ - #pragma once #include "common/eqemu_config.h" diff --git a/ucs/worldserver.cpp b/ucs/worldserver.cpp index c3ee7a0ca7..c70a128cf4 100644 --- a/ucs/worldserver.cpp +++ b/ucs/worldserver.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2002 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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "worldserver.h" #include "common/discord/discord_manager.h" diff --git a/ucs/worldserver.h b/ucs/worldserver.h index b425820694..1a9efdc8fd 100644 --- a/ucs/worldserver.h +++ b/ucs/worldserver.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eq_packet_structs.h" diff --git a/utils/TaskMaster/ErrorLog.cpp b/utils/TaskMaster/ErrorLog.cpp index 0543d270a8..188f2d683d 100644 --- a/utils/TaskMaster/ErrorLog.cpp +++ b/utils/TaskMaster/ErrorLog.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include #include #include diff --git a/utils/TaskMaster/ErrorLog.h b/utils/TaskMaster/ErrorLog.h index 615c7a44dd..f19167b3fe 100644 --- a/utils/TaskMaster/ErrorLog.h +++ b/utils/TaskMaster/ErrorLog.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifndef EQWX_ERRORLOG__H #define EQWX_ERRORLOG__H diff --git a/utils/TaskMaster/activities.cpp b/utils/TaskMaster/activities.cpp index 2f2dc04510..049f3b31b1 100644 --- a/utils/TaskMaster/activities.cpp +++ b/utils/TaskMaster/activities.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include #include #include diff --git a/utils/TaskMaster/base.cpp b/utils/TaskMaster/base.cpp index b9b118962b..8ce3703d6d 100644 --- a/utils/TaskMaster/base.cpp +++ b/utils/TaskMaster/base.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include #include #include diff --git a/utils/TaskMaster/base.h b/utils/TaskMaster/base.h index c6365088c7..84c0b2ffed 100644 --- a/utils/TaskMaster/base.h +++ b/utils/TaskMaster/base.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifndef EQWX_BASE__H #define EQWX_BASE__H #include diff --git a/utils/TaskMaster/base_utility.cpp b/utils/TaskMaster/base_utility.cpp index dbbd444f7b..274c0213bc 100644 --- a/utils/TaskMaster/base_utility.cpp +++ b/utils/TaskMaster/base_utility.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include #include #include diff --git a/utils/TaskMaster/goals.cpp b/utils/TaskMaster/goals.cpp index 64c35e419c..6816b9c223 100644 --- a/utils/TaskMaster/goals.cpp +++ b/utils/TaskMaster/goals.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include #include #include diff --git a/utils/TaskMaster/items.h b/utils/TaskMaster/items.h index 841b1747f2..ae6ef8ddb8 100644 --- a/utils/TaskMaster/items.h +++ b/utils/TaskMaster/items.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifndef EQWX_ITEMS__H #define EQWX_ITEMS__H diff --git a/utils/TaskMaster/proximity.cpp b/utils/TaskMaster/proximity.cpp index cbe498d7a8..0b58b8d545 100644 --- a/utils/TaskMaster/proximity.cpp +++ b/utils/TaskMaster/proximity.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include #include #include diff --git a/utils/TaskMaster/tasks.cpp b/utils/TaskMaster/tasks.cpp index 9cfedb7fe7..28e78a77f7 100644 --- a/utils/TaskMaster/tasks.cpp +++ b/utils/TaskMaster/tasks.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include #include #include diff --git a/utils/TaskMaster/tasks.h b/utils/TaskMaster/tasks.h index 05c5bffdbf..9d09f841f0 100644 --- a/utils/TaskMaster/tasks.h +++ b/utils/TaskMaster/tasks.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifndef EQWX_TASKS__H #define EQWX_TASKS__H diff --git a/utils/TaskMaster/utility.cpp b/utils/TaskMaster/utility.cpp index a04293b4a3..2929e1b7d4 100644 --- a/utils/TaskMaster/utility.cpp +++ b/utils/TaskMaster/utility.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include #include #include diff --git a/utils/TaskMaster/utility.h b/utils/TaskMaster/utility.h index cfb9a2a69b..444cbaf499 100644 --- a/utils/TaskMaster/utility.h +++ b/utils/TaskMaster/utility.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifndef EQWX_UTILITY__H #define EQWX_UTILITY__H diff --git a/world/adventure.cpp b/world/adventure.cpp index fbf6f99042..0b60f31697 100644 --- a/world/adventure.cpp +++ b/world/adventure.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "adventure.h" #include "common/extprofile.h" diff --git a/world/adventure.h b/world/adventure.h index 6fd9667371..061c711c8f 100644 --- a/world/adventure.h +++ b/world/adventure.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/timer.h" diff --git a/world/adventure_manager.cpp b/world/adventure_manager.cpp index edc12c19a7..c415e8756f 100644 --- a/world/adventure_manager.cpp +++ b/world/adventure_manager.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "adventure_manager.h" #include "common/misc_functions.h" diff --git a/world/adventure_manager.h b/world/adventure_manager.h index d9934f8491..29d914b1d7 100644 --- a/world/adventure_manager.h +++ b/world/adventure_manager.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/timer.h" diff --git a/world/adventure_template.h b/world/adventure_template.h index b35da738fc..762478bd11 100644 --- a/world/adventure_template.h +++ b/world/adventure_template.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/world/cli/cli_bots_disable.cpp b/world/cli/cli_bots_disable.cpp index 4cbe5ed7e1..066c29e19a 100644 --- a/world/cli/cli_bots_disable.cpp +++ b/world/cli/cli_bots_disable.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/database_schema.h" diff --git a/world/cli/cli_bots_enable.cpp b/world/cli/cli_bots_enable.cpp index 7664431130..7f877caa8d 100644 --- a/world/cli/cli_bots_enable.cpp +++ b/world/cli/cli_bots_enable.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/rulesys.h" diff --git a/world/cli/cli_copy_character.cpp b/world/cli/cli_copy_character.cpp index 41e3bb349a..ea64175fff 100644 --- a/world/cli/cli_copy_character.cpp +++ b/world/cli/cli_copy_character.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/eqemu_logsys_log_aliases.h" diff --git a/world/cli/cli_database_concurrency.cpp b/world/cli/cli_database_concurrency.cpp index 81b6619b12..557e141742 100644 --- a/world/cli/cli_database_concurrency.cpp +++ b/world/cli/cli_database_concurrency.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/eqemu_config.h" diff --git a/world/cli/cli_database_dump.cpp b/world/cli/cli_database_dump.cpp index 00618606c8..050ea18428 100644 --- a/world/cli/cli_database_dump.cpp +++ b/world/cli/cli_database_dump.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/database/database_dump_service.h" diff --git a/world/cli/cli_database_get_schema.cpp b/world/cli/cli_database_get_schema.cpp index 37af405677..19d99aca5e 100644 --- a/world/cli/cli_database_get_schema.cpp +++ b/world/cli/cli_database_get_schema.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/database_schema.h" diff --git a/world/cli/cli_database_set_account_status.cpp b/world/cli/cli_database_set_account_status.cpp index 49e76307c6..0211d0d571 100644 --- a/world/cli/cli_database_set_account_status.cpp +++ b/world/cli/cli_database_set_account_status.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "world/worlddb.h" diff --git a/world/cli/cli_database_updates.cpp b/world/cli/cli_database_updates.cpp index f2f773849c..a9f93c6c42 100644 --- a/world/cli/cli_database_updates.cpp +++ b/world/cli/cli_database_updates.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/database/database_update.h" diff --git a/world/cli/cli_database_version.cpp b/world/cli/cli_database_version.cpp index 424bc4ee66..db2a41b692 100644 --- a/world/cli/cli_database_version.cpp +++ b/world/cli/cli_database_version.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/json/json.h" diff --git a/world/cli/cli_etl_get_settings.cpp b/world/cli/cli_etl_get_settings.cpp index a96c8477f4..51f9fc36c1 100644 --- a/world/cli/cli_etl_get_settings.cpp +++ b/world/cli/cli_etl_get_settings.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/events/player_event_logs.h" diff --git a/world/cli/cli_mercs_disable.cpp b/world/cli/cli_mercs_disable.cpp index 737608ccf1..d7a2e19032 100644 --- a/world/cli/cli_mercs_disable.cpp +++ b/world/cli/cli_mercs_disable.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/database_schema.h" diff --git a/world/cli/cli_mercs_enable.cpp b/world/cli/cli_mercs_enable.cpp index a4f6c2972a..c8bdde1a19 100644 --- a/world/cli/cli_mercs_enable.cpp +++ b/world/cli/cli_mercs_enable.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/database_schema.h" diff --git a/world/cli/cli_test.cpp b/world/cli/cli_test.cpp index ecbb1e5fa2..0353e48150 100644 --- a/world/cli/cli_test.cpp +++ b/world/cli/cli_test.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/events/player_events.h" diff --git a/world/cli/cli_test_colors.cpp b/world/cli/cli_test_colors.cpp index ae6e4cbd4c..8c91949cdc 100644 --- a/world/cli/cli_test_colors.cpp +++ b/world/cli/cli_test_colors.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/termcolor/rang.hpp" diff --git a/world/cli/cli_test_expansion.cpp b/world/cli/cli_test_expansion.cpp index 93dc94f298..f0d59afefa 100644 --- a/world/cli/cli_test_expansion.cpp +++ b/world/cli/cli_test_expansion.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/content/world_content_service.h" diff --git a/world/cli/cli_test_repository.cpp b/world/cli/cli_test_repository.cpp index 038ce58711..c5955dd31d 100644 --- a/world/cli/cli_test_repository.cpp +++ b/world/cli/cli_test_repository.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/repositories/instance_list_repository.h" diff --git a/world/cli/cli_test_repository_2.cpp b/world/cli/cli_test_repository_2.cpp index 4c914090f9..b89862af25 100644 --- a/world/cli/cli_test_repository_2.cpp +++ b/world/cli/cli_test_repository_2.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/repositories/zone_repository.h" diff --git a/world/cli/cli_test_string_benchmark.cpp b/world/cli/cli_test_string_benchmark.cpp index dd3edbb8f6..546b960505 100644 --- a/world/cli/cli_test_string_benchmark.cpp +++ b/world/cli/cli_test_string_benchmark.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/events/player_events.h" diff --git a/world/cli/cli_version.cpp b/world/cli/cli_version.cpp index 1f1502bb53..871b07dbda 100644 --- a/world/cli/cli_version.cpp +++ b/world/cli/cli_version.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world/world_server_cli.h" #include "common/json/json.h" diff --git a/world/client.cpp b/world/client.cpp index 555a0055a8..46d5052943 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "client.h" #include "common/classes.h" diff --git a/world/client.h b/world/client.h index f26dcaaacc..ffb6722a89 100644 --- a/world/client.h +++ b/world/client.h @@ -1,19 +1,19 @@ -/* EQ Everquest Server Emulator - Copyright (C) 2001-2002 EQ:: Development Team (http://EQ::.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ #pragma once diff --git a/world/cliententry.cpp b/world/cliententry.cpp index 6b37f7b640..e17e8c49d4 100644 --- a/world/cliententry.cpp +++ b/world/cliententry.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "cliententry.h" #include "world/clientlist.h" diff --git a/world/cliententry.h b/world/cliententry.h index 97c5e40024..a94433b935 100644 --- a/world/cliententry.h +++ b/world/cliententry.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/md5.h" diff --git a/world/clientlist.cpp b/world/clientlist.cpp index 1aa59930e3..74a908a0fc 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/classes.h" #include "common/event_sub.h" #include "common/guilds.h" diff --git a/world/clientlist.h b/world/clientlist.h index 34970a7e6e..4c82fd4be2 100644 --- a/world/clientlist.h +++ b/world/clientlist.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eq_packet_structs.h" diff --git a/world/console.cpp b/world/console.cpp index cbf998c3c2..8b56dc1a5d 100644 --- a/world/console.cpp +++ b/world/console.cpp @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "console.h" #include "common/md5.h" diff --git a/world/console.h b/world/console.h index b8d4d3d866..f1c5139de2 100644 --- a/world/console.h +++ b/world/console.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/net/console_server.h" diff --git a/world/dynamic_zone.cpp b/world/dynamic_zone.cpp index 832e2f6ca0..bff5e77419 100644 --- a/world/dynamic_zone.cpp +++ b/world/dynamic_zone.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "dynamic_zone.h" #include "common/eqemu_logsys.h" diff --git a/world/dynamic_zone.h b/world/dynamic_zone.h index 770f06ab98..530d099cd4 100644 --- a/world/dynamic_zone.h +++ b/world/dynamic_zone.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/dynamic_zone_base.h" diff --git a/world/dynamic_zone_manager.cpp b/world/dynamic_zone_manager.cpp index 66cd5e7346..11d9905a24 100644 --- a/world/dynamic_zone_manager.cpp +++ b/world/dynamic_zone_manager.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "dynamic_zone_manager.h" #include "common/repositories/dynamic_zone_lockouts_repository.h" diff --git a/world/dynamic_zone_manager.h b/world/dynamic_zone_manager.h index 42faa42a62..873357074f 100644 --- a/world/dynamic_zone_manager.h +++ b/world/dynamic_zone_manager.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/dynamic_zone_templates_repository.h" diff --git a/world/eqemu_api_world_data_service.cpp b/world/eqemu_api_world_data_service.cpp index 8a4132e3e0..a3fdcd1880 100644 --- a/world/eqemu_api_world_data_service.cpp +++ b/world/eqemu_api_world_data_service.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "eqemu_api_world_data_service.h" #include "common/database_schema.h" diff --git a/world/eqemu_api_world_data_service.h b/world/eqemu_api_world_data_service.h index 8065582870..308d9b0cae 100644 --- a/world/eqemu_api_world_data_service.h +++ b/world/eqemu_api_world_data_service.h @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/json/json.h" diff --git a/world/eql_config.cpp b/world/eql_config.cpp index 74e4de6899..6e5fb1c89f 100644 --- a/world/eql_config.cpp +++ b/world/eql_config.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "eql_config.h" #include "common/strings.h" diff --git a/world/eql_config.h b/world/eql_config.h index 1380e0bf97..ca3ab3f735 100644 --- a/world/eql_config.h +++ b/world/eql_config.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/world/launcher_link.cpp b/world/launcher_link.cpp index 92c7c030b0..c281bb671c 100644 --- a/world/launcher_link.cpp +++ b/world/launcher_link.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) - -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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "launcher_link.h" #include "common/md5.h" diff --git a/world/launcher_link.h b/world/launcher_link.h index c22311d9ae..2e8e6bc20d 100644 --- a/world/launcher_link.h +++ b/world/launcher_link.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/event/timer.h" diff --git a/world/launcher_list.cpp b/world/launcher_list.cpp index e5c3555d9d..852ef3f8ae 100644 --- a/world/launcher_list.cpp +++ b/world/launcher_list.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) - -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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "launcher_list.h" #include "world/eql_config.h" diff --git a/world/launcher_list.h b/world/launcher_list.h index 15e655e8c9..fa1a106d4d 100644 --- a/world/launcher_list.h +++ b/world/launcher_list.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/world/lfplist.cpp b/world/lfplist.cpp index 283ffe8a65..774de83a8a 100644 --- a/world/lfplist.cpp +++ b/world/lfplist.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "lfplist.h" #include "common/classes.h" diff --git a/world/lfplist.h b/world/lfplist.h index 7524b3ca7f..f8692a977f 100644 --- a/world/lfplist.h +++ b/world/lfplist.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eq_packet_structs.h" diff --git a/world/login_server.cpp b/world/login_server.cpp index f911004f80..63aa4a8ce3 100644 --- a/world/login_server.cpp +++ b/world/login_server.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "login_server.h" #include "common/eq_packet_structs.h" diff --git a/world/login_server.h b/world/login_server.h index e773664112..b5bd5a038c 100644 --- a/world/login_server.h +++ b/world/login_server.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eq_packet_structs.h" diff --git a/world/login_server_list.cpp b/world/login_server_list.cpp index 06f01e25fa..c12f5f98ee 100644 --- a/world/login_server_list.cpp +++ b/world/login_server_list.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2002 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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "login_server_list.h" #include "common/eq_packet_structs.h" diff --git a/world/login_server_list.h b/world/login_server_list.h index fe37f52747..7bd3a812af 100644 --- a/world/login_server_list.h +++ b/world/login_server_list.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eq_packet_structs.h" diff --git a/world/main.cpp b/world/main.cpp index 9aa7f50fe1..40abf5255b 100644 --- a/world/main.cpp +++ b/world/main.cpp @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/content/world_content_service.h" #include "common/crash.h" #include "common/eq_packet.h" diff --git a/world/queryserv.cpp b/world/queryserv.cpp index 19bce076ca..4bb77109cb 100644 --- a/world/queryserv.cpp +++ b/world/queryserv.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "queryserv.h" #include "common/eqemu_logsys.h" diff --git a/world/queryserv.h b/world/queryserv.h index 177da7b75f..1964f37096 100644 --- a/world/queryserv.h +++ b/world/queryserv.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/world/shared_task_manager.cpp b/world/shared_task_manager.cpp index 6eae5ef401..d3a9bd2b9f 100644 --- a/world/shared_task_manager.cpp +++ b/world/shared_task_manager.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "shared_task_manager.h" #include "common/repositories/character_data_repository.h" diff --git a/world/shared_task_manager.h b/world/shared_task_manager.h index bb8afe50c4..54f1f74c9d 100644 --- a/world/shared_task_manager.h +++ b/world/shared_task_manager.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/database.h" diff --git a/world/shared_task_world_messaging.cpp b/world/shared_task_world_messaging.cpp index 526b144bc4..ad2d5dde8d 100644 --- a/world/shared_task_world_messaging.cpp +++ b/world/shared_task_world_messaging.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "shared_task_world_messaging.h" #include "common/eqemu_logsys.h" diff --git a/world/shared_task_world_messaging.h b/world/shared_task_world_messaging.h index c841baf803..4acac5d292 100644 --- a/world/shared_task_world_messaging.h +++ b/world/shared_task_world_messaging.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eqemu_logsys.h" diff --git a/world/sof_char_create_data.h b/world/sof_char_create_data.h index c522507d62..fb5eceaf9e 100644 --- a/world/sof_char_create_data.h +++ b/world/sof_char_create_data.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #pragma pack(push) diff --git a/world/ucs.cpp b/world/ucs.cpp index 298c359fc5..d7c3c86a55 100644 --- a/world/ucs.cpp +++ b/world/ucs.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "ucs.h" #include "common/eqemu_logsys.h" diff --git a/world/ucs.h b/world/ucs.h index 520dff9297..df3ec9e6dd 100644 --- a/world/ucs.h +++ b/world/ucs.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/event/timer.h" diff --git a/world/web_interface.cpp b/world/web_interface.cpp index e794b7074b..4acb768a94 100644 --- a/world/web_interface.cpp +++ b/world/web_interface.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "web_interface.h" #include "common/json/json.h" diff --git a/world/web_interface.h b/world/web_interface.h index 4933d79050..2f3ca7042f 100644 --- a/world/web_interface.h +++ b/world/web_interface.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/json/json.h" diff --git a/world/web_interface_eqw.cpp b/world/web_interface_eqw.cpp index 554b495f39..e7aa7e7d91 100644 --- a/world/web_interface_eqw.cpp +++ b/world/web_interface_eqw.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "web_interface_eqw.h" #include "world/clientlist.h" diff --git a/world/web_interface_eqw.h b/world/web_interface_eqw.h index d7a3f54f5d..fd1f81802a 100644 --- a/world/web_interface_eqw.h +++ b/world/web_interface_eqw.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once class WebInterface; diff --git a/world/wguild_mgr.cpp b/world/wguild_mgr.cpp index fbbbbcd78b..a12bb35d63 100644 --- a/world/wguild_mgr.cpp +++ b/world/wguild_mgr.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "wguild_mgr.h" #include "common/eqemu_logsys.h" diff --git a/world/wguild_mgr.h b/world/wguild_mgr.h index f107086d99..24b2948a18 100644 --- a/world/wguild_mgr.h +++ b/world/wguild_mgr.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/world/world_boot.cpp b/world/world_boot.cpp index 337e5d1336..7c2afc3889 100644 --- a/world/world_boot.cpp +++ b/world/world_boot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world_boot.h" #include "common/content/world_content_service.h" diff --git a/world/world_boot.h b/world/world_boot.h index d8254d5862..091236d0a7 100644 --- a/world/world_boot.h +++ b/world/world_boot.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/discord/discord.h" diff --git a/world/world_config.cpp b/world/world_config.cpp index 53055b2541..359d26bf6f 100644 --- a/world/world_config.cpp +++ b/world/world_config.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "world_config.h" #include "common/eqemu_logsys.h" diff --git a/world/world_config.h b/world/world_config.h index ffe0114e1b..29951c80c1 100644 --- a/world/world_config.h +++ b/world/world_config.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eqemu_config.h" diff --git a/world/world_console_connection.cpp b/world/world_console_connection.cpp index 196826954d..fbe1d12927 100644 --- a/world/world_console_connection.cpp +++ b/world/world_console_connection.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world_console_connection.h" #include diff --git a/world/world_console_connection.h b/world/world_console_connection.h index 616fdbd128..212a325823 100644 --- a/world/world_console_connection.h +++ b/world/world_console_connection.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2017 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/net/console_server_connection.h" diff --git a/world/world_event_scheduler.cpp b/world/world_event_scheduler.cpp index c9ceafc525..b3a2f885a6 100644 --- a/world/world_event_scheduler.cpp +++ b/world/world_event_scheduler.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world_event_scheduler.h" #include "common/rulesys.h" diff --git a/world/world_event_scheduler.h b/world/world_event_scheduler.h index d5e333f645..4d3219cd2c 100644 --- a/world/world_event_scheduler.h +++ b/world/world_event_scheduler.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/server_event_scheduler.h" diff --git a/world/world_server_cli.cpp b/world/world_server_cli.cpp index 50b16f4e41..08a6fd6d5b 100644 --- a/world/world_server_cli.cpp +++ b/world/world_server_cli.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "world_server_cli.h" void WorldserverCLI::CommandHandler(int argc, char **argv) diff --git a/world/world_server_cli.h b/world/world_server_cli.h index 4fa4b434e1..7a29d153a9 100644 --- a/world/world_server_cli.h +++ b/world/world_server_cli.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once diff --git a/world/world_tcp_connection.h b/world/world_tcp_connection.h index 960e072041..cffcdd5e54 100644 --- a/world/world_tcp_connection.h +++ b/world/world_tcp_connection.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/world/worlddb.cpp b/world/worlddb.cpp index b03478e8ba..8fd102357b 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "worlddb.h" #include "common/eq_packet_structs.h" diff --git a/world/worlddb.h b/world/worlddb.h index b6025b3d30..9817777ded 100644 --- a/world/worlddb.h +++ b/world/worlddb.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eq_packet.h" diff --git a/world/zonelist.cpp b/world/zonelist.cpp index 1f4ae80fcd..ef74a69f66 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) - -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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zonelist.h" #include "common/content/world_content_service.h" diff --git a/world/zonelist.h b/world/zonelist.h index 9263a1e903..5e1647b191 100644 --- a/world/zonelist.h +++ b/world/zonelist.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eqtime.h" diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 8e6c7e72ee..ef877d2c68 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1,22 +1,20 @@ +/* EQEmu: EQEmulator -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team -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 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; either version 3 of the License, or + (at your option) any later version. -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. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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 + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ - #include "zoneserver.h" #include "common/content/world_content_service.h" diff --git a/world/zoneserver.h b/world/zoneserver.h index 30d06a18db..f7f515469e 100644 --- a/world/zoneserver.h +++ b/world/zoneserver.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "world_tcp_connection.h" diff --git a/zone/aa.cpp b/zone/aa.cpp index 8b83054ac4..984386d405 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "aa.h" #include "common/classes.h" diff --git a/zone/aa.h b/zone/aa.h index 350828b0ad..f5e015bc1b 100644 --- a/zone/aa.h +++ b/zone/aa.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #define MAX_SWARM_PETS 12 //this can change as long as you make more coords (swarm_pet_x/swarm_pet_y) diff --git a/zone/aa_ability.cpp b/zone/aa_ability.cpp index 8043f1625f..2229e9e7fc 100644 --- a/zone/aa_ability.cpp +++ b/zone/aa_ability.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/types.h" #include "zone/masterentity.h" #include "zone/aa_ability.h" diff --git a/zone/aa_ability.h b/zone/aa_ability.h index b4902fba9b..59e38c1301 100644 --- a/zone/aa_ability.h +++ b/zone/aa_ability.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "zone/aa_rank_effects.h" diff --git a/zone/aa_rank.h b/zone/aa_rank.h index 5a27914471..5e69bff1b9 100644 --- a/zone/aa_rank.h +++ b/zone/aa_rank.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/zone/aa_rank_effects.h b/zone/aa_rank_effects.h index 98baa98512..9737375844 100644 --- a/zone/aa_rank_effects.h +++ b/zone/aa_rank_effects.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 123780dab8..0b51fbc114 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/eqemu_logsys.h" #include "common/faction.h" #include "common/rulesys.h" diff --git a/zone/aggromanager.cpp b/zone/aggromanager.cpp index 2398c5a65b..562a69515b 100644 --- a/zone/aggromanager.cpp +++ b/zone/aggromanager.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "aggromanager.h" AggroMeter::AggroMeter() : lock_id(0), target_id(0), secondary_id(0), lock_changed(false) diff --git a/zone/aggromanager.h b/zone/aggromanager.h index 06a1c8918d..090681b77e 100644 --- a/zone/aggromanager.h +++ b/zone/aggromanager.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/zone/api_service.cpp b/zone/api_service.cpp index 4e85e9373f..b7c9827372 100644 --- a/zone/api_service.cpp +++ b/zone/api_service.cpp @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "api_service.h" #include "common/eqemu_logsys.h" diff --git a/zone/api_service.h b/zone/api_service.h index bf991cb089..e256b7caf0 100644 --- a/zone/api_service.h +++ b/zone/api_service.h @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2019 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/net/websocket_server.h" diff --git a/zone/attack.cpp b/zone/attack.cpp index e23bb3ffc5..9ee46b31c2 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2002 EQEMu Development Team (http://eqemulator.net) - -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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/data_verification.h" #include "common/eq_constants.h" #include "common/eq_packet_structs.h" diff --git a/zone/aura.cpp b/zone/aura.cpp index 77fd687ad0..64e69e3d37 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/auras_repository.h" #include "common/strings.h" #include "zone/aura.h" diff --git a/zone/aura.h b/zone/aura.h index c9a92b32b0..0559835ca5 100644 --- a/zone/aura.h +++ b/zone/aura.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once diff --git a/zone/beacon.cpp b/zone/beacon.cpp index 48106ac77c..8968f33960 100644 --- a/zone/beacon.cpp +++ b/zone/beacon.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - /* Beacon class, extends Mob. Used for AE rain spells to have a mob target to center around. diff --git a/zone/beacon.h b/zone/beacon.h index 2692a7cb91..1adaab60e0 100644 --- a/zone/beacon.h +++ b/zone/beacon.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/timer.h" diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 45718570a0..131bf0f27c 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/classes.h" #include "common/data_verification.h" #include "common/item_instance.h" diff --git a/zone/bot.cpp b/zone/bot.cpp index 359a0d79e4..b543ea2469 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "bot.h" #include "common/data_verification.h" diff --git a/zone/bot.h b/zone/bot.h index 04a47f0a31..9511cf9ee7 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/misc_functions.h" diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index c8cc1ce32e..decd84e074 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - /* To add a new bot command 3 things must be done: diff --git a/zone/bot_command.h b/zone/bot_command.h index c8a470bfdd..382d397947 100644 --- a/zone/bot_command.h +++ b/zone/bot_command.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/zone/bot_commands/bot_actionable.cpp b/zone/bot_commands/bot_actionable.cpp index c98e89edf3..3f3116ce5d 100644 --- a/zone/bot_commands/bot_actionable.cpp +++ b/zone/bot_commands/bot_actionable.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_actionable(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_appearance.cpp b/zone/bot_commands/bot_appearance.cpp index 20b8cd8116..ff34b01937 100644 --- a/zone/bot_commands/bot_appearance.cpp +++ b/zone/bot_commands/bot_appearance.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_appearance(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_apply_poison.cpp b/zone/bot_commands/bot_apply_poison.cpp index c6869ab98e..19c0e94d33 100644 --- a/zone/bot_commands/bot_apply_poison.cpp +++ b/zone/bot_commands/bot_apply_poison.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_apply_poison(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_apply_potion.cpp b/zone/bot_commands/bot_apply_potion.cpp index cbf9d1e80e..62cdd0b59a 100644 --- a/zone/bot_commands/bot_apply_potion.cpp +++ b/zone/bot_commands/bot_apply_potion.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_apply_potion(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_attack.cpp b/zone/bot_commands/bot_attack.cpp index 6183b5853f..1a37aabbdc 100644 --- a/zone/bot_commands/bot_attack.cpp +++ b/zone/bot_commands/bot_attack.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_attack(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_behind_mob.cpp b/zone/bot_commands/bot_behind_mob.cpp index c96565ae28..acf28093e4 100644 --- a/zone/bot_commands/bot_behind_mob.cpp +++ b/zone/bot_commands/bot_behind_mob.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_behind_mob(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_blocked_buffs.cpp b/zone/bot_commands/bot_blocked_buffs.cpp index 17b5fffc3c..14195cb401 100644 --- a/zone/bot_commands/bot_blocked_buffs.cpp +++ b/zone/bot_commands/bot_blocked_buffs.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_blocked_buffs(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_bot.cpp b/zone/bot_commands/bot_bot.cpp index f1af6b4d63..e1f881bdfb 100644 --- a/zone/bot_commands/bot_bot.cpp +++ b/zone/bot_commands/bot_bot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_bot(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_bot_settings.cpp b/zone/bot_commands/bot_bot_settings.cpp index 55ccd32f41..215b6773fc 100644 --- a/zone/bot_commands/bot_bot_settings.cpp +++ b/zone/bot_commands/bot_bot_settings.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_bot_settings(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_cast.cpp b/zone/bot_commands/bot_cast.cpp index 62499efaf8..0f9e954dcf 100644 --- a/zone/bot_commands/bot_cast.cpp +++ b/zone/bot_commands/bot_cast.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_cast(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_class_race_list.cpp b/zone/bot_commands/bot_class_race_list.cpp index d076dbc711..aa5f117824 100644 --- a/zone/bot_commands/bot_class_race_list.cpp +++ b/zone/bot_commands/bot_class_race_list.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_class_race_list(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_click_item.cpp b/zone/bot_commands/bot_click_item.cpp index cc7aa07584..b3794aa8ba 100644 --- a/zone/bot_commands/bot_click_item.cpp +++ b/zone/bot_commands/bot_click_item.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_click_item(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_copy_settings.cpp b/zone/bot_commands/bot_copy_settings.cpp index 2b91de9558..c38ff70296 100644 --- a/zone/bot_commands/bot_copy_settings.cpp +++ b/zone/bot_commands/bot_copy_settings.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_copy_settings(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_default_settings.cpp b/zone/bot_commands/bot_default_settings.cpp index 8450ebeece..8241eba433 100644 --- a/zone/bot_commands/bot_default_settings.cpp +++ b/zone/bot_commands/bot_default_settings.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_default_settings(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_depart.cpp b/zone/bot_commands/bot_depart.cpp index 3175063518..f5c01b7f60 100644 --- a/zone/bot_commands/bot_depart.cpp +++ b/zone/bot_commands/bot_depart.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_depart(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_discipline.cpp b/zone/bot_commands/bot_discipline.cpp index 1c9d6d51e7..a726c4a5cb 100644 --- a/zone/bot_commands/bot_discipline.cpp +++ b/zone/bot_commands/bot_discipline.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_discipline(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_distance_ranged.cpp b/zone/bot_commands/bot_distance_ranged.cpp index bc585b2fc7..1dbedfaa81 100644 --- a/zone/bot_commands/bot_distance_ranged.cpp +++ b/zone/bot_commands/bot_distance_ranged.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_distance_ranged(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_find_aliases.cpp b/zone/bot_commands/bot_find_aliases.cpp index 949bdd9f73..206fcce829 100644 --- a/zone/bot_commands/bot_find_aliases.cpp +++ b/zone/bot_commands/bot_find_aliases.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_find_aliases(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_follow.cpp b/zone/bot_commands/bot_follow.cpp index c66a131b11..b755046cd5 100644 --- a/zone/bot_commands/bot_follow.cpp +++ b/zone/bot_commands/bot_follow.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_follow(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_guard.cpp b/zone/bot_commands/bot_guard.cpp index f931cd38f4..b28d932768 100644 --- a/zone/bot_commands/bot_guard.cpp +++ b/zone/bot_commands/bot_guard.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_guard(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_heal_rotation.cpp b/zone/bot_commands/bot_heal_rotation.cpp index 32f7c9e5b7..4d138ec594 100644 --- a/zone/bot_commands/bot_heal_rotation.cpp +++ b/zone/bot_commands/bot_heal_rotation.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_heal_rotation(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_help.cpp b/zone/bot_commands/bot_help.cpp index 00a50cec71..e4b9770978 100644 --- a/zone/bot_commands/bot_help.cpp +++ b/zone/bot_commands/bot_help.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_help(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_hold.cpp b/zone/bot_commands/bot_hold.cpp index 82b63479b1..4dda992daa 100644 --- a/zone/bot_commands/bot_hold.cpp +++ b/zone/bot_commands/bot_hold.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_hold(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_illusion_block.cpp b/zone/bot_commands/bot_illusion_block.cpp index 65446a8519..c998661795 100644 --- a/zone/bot_commands/bot_illusion_block.cpp +++ b/zone/bot_commands/bot_illusion_block.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_illusion_block(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_inventory.cpp b/zone/bot_commands/bot_inventory.cpp index 9df63b86ec..bbfab7a9fa 100644 --- a/zone/bot_commands/bot_inventory.cpp +++ b/zone/bot_commands/bot_inventory.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_inventory(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_item_use.cpp b/zone/bot_commands/bot_item_use.cpp index 6550c7f0d8..02a7d89b55 100644 --- a/zone/bot_commands/bot_item_use.cpp +++ b/zone/bot_commands/bot_item_use.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_item_use(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_max_melee_range.cpp b/zone/bot_commands/bot_max_melee_range.cpp index 290703cb18..607ff9e531 100644 --- a/zone/bot_commands/bot_max_melee_range.cpp +++ b/zone/bot_commands/bot_max_melee_range.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_max_melee_range(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_name.cpp b/zone/bot_commands/bot_name.cpp index 6801ad46f6..c97b60b041 100644 --- a/zone/bot_commands/bot_name.cpp +++ b/zone/bot_commands/bot_name.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_surname(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_owner_option.cpp b/zone/bot_commands/bot_owner_option.cpp index 70b8e36161..b66636469a 100644 --- a/zone/bot_commands/bot_owner_option.cpp +++ b/zone/bot_commands/bot_owner_option.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_owner_option(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_pet.cpp b/zone/bot_commands/bot_pet.cpp index 74cad7b3d1..5bcc9b270b 100644 --- a/zone/bot_commands/bot_pet.cpp +++ b/zone/bot_commands/bot_pet.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" #include "zone/bot.h" diff --git a/zone/bot_commands/bot_pick_lock.cpp b/zone/bot_commands/bot_pick_lock.cpp index bf66cd2238..82224faadf 100644 --- a/zone/bot_commands/bot_pick_lock.cpp +++ b/zone/bot_commands/bot_pick_lock.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" #include "zone/doors.h" diff --git a/zone/bot_commands/bot_pickpocket.cpp b/zone/bot_commands/bot_pickpocket.cpp index 8bb227fece..216d9d0786 100644 --- a/zone/bot_commands/bot_pickpocket.cpp +++ b/zone/bot_commands/bot_pickpocket.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_pickpocket(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_precombat.cpp b/zone/bot_commands/bot_precombat.cpp index c8046bee21..c7da5bf121 100644 --- a/zone/bot_commands/bot_precombat.cpp +++ b/zone/bot_commands/bot_precombat.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_precombat(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_pull.cpp b/zone/bot_commands/bot_pull.cpp index 6fd0a267a2..1d7635ea7b 100644 --- a/zone/bot_commands/bot_pull.cpp +++ b/zone/bot_commands/bot_pull.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_pull(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_release.cpp b/zone/bot_commands/bot_release.cpp index d20d6c2227..80dd197125 100644 --- a/zone/bot_commands/bot_release.cpp +++ b/zone/bot_commands/bot_release.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_release(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_set_assistee.cpp b/zone/bot_commands/bot_set_assistee.cpp index e70513ea4f..5f2e4699ff 100644 --- a/zone/bot_commands/bot_set_assistee.cpp +++ b/zone/bot_commands/bot_set_assistee.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_set_assistee(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_sit_hp_percent.cpp b/zone/bot_commands/bot_sit_hp_percent.cpp index 6e2d6d9a4e..d58d6e8182 100644 --- a/zone/bot_commands/bot_sit_hp_percent.cpp +++ b/zone/bot_commands/bot_sit_hp_percent.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_sit_hp_percent(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_sit_in_combat.cpp b/zone/bot_commands/bot_sit_in_combat.cpp index bde5a71ac2..cf84c18674 100644 --- a/zone/bot_commands/bot_sit_in_combat.cpp +++ b/zone/bot_commands/bot_sit_in_combat.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_sit_in_combat(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_sit_mana_percent.cpp b/zone/bot_commands/bot_sit_mana_percent.cpp index c66427bbc9..ff1c482d1f 100644 --- a/zone/bot_commands/bot_sit_mana_percent.cpp +++ b/zone/bot_commands/bot_sit_mana_percent.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_sit_mana_percent(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_spell.cpp b/zone/bot_commands/bot_spell.cpp index cc18e1cb22..0a8a926568 100644 --- a/zone/bot_commands/bot_spell.cpp +++ b/zone/bot_commands/bot_spell.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_list(Client* c, const Seperator *sep) diff --git a/zone/bot_commands/bot_spell_aggro_checks.cpp b/zone/bot_commands/bot_spell_aggro_checks.cpp index 8ba6415de0..b810a6db6b 100644 --- a/zone/bot_commands/bot_spell_aggro_checks.cpp +++ b/zone/bot_commands/bot_spell_aggro_checks.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_aggro_checks(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_spell_announce_cast.cpp b/zone/bot_commands/bot_spell_announce_cast.cpp index ecbd4cf462..7f2f7ec6c3 100644 --- a/zone/bot_commands/bot_spell_announce_cast.cpp +++ b/zone/bot_commands/bot_spell_announce_cast.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_announce_cast(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_delays.cpp b/zone/bot_commands/bot_spell_delays.cpp index 31225491e5..de0afd99aa 100644 --- a/zone/bot_commands/bot_spell_delays.cpp +++ b/zone/bot_commands/bot_spell_delays.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_delays(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_engaged_priority.cpp b/zone/bot_commands/bot_spell_engaged_priority.cpp index 92622f9114..bf48e5ab5a 100644 --- a/zone/bot_commands/bot_spell_engaged_priority.cpp +++ b/zone/bot_commands/bot_spell_engaged_priority.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_engaged_priority(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_spell_holds.cpp b/zone/bot_commands/bot_spell_holds.cpp index ed627644a3..c618b8f4a1 100644 --- a/zone/bot_commands/bot_spell_holds.cpp +++ b/zone/bot_commands/bot_spell_holds.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_holds(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_spell_idle_priority.cpp b/zone/bot_commands/bot_spell_idle_priority.cpp index f5a9843d47..3bb4eb3dd9 100644 --- a/zone/bot_commands/bot_spell_idle_priority.cpp +++ b/zone/bot_commands/bot_spell_idle_priority.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_idle_priority(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_spell_max_hp_pct.cpp b/zone/bot_commands/bot_spell_max_hp_pct.cpp index 8802a2c091..e45a32be4b 100644 --- a/zone/bot_commands/bot_spell_max_hp_pct.cpp +++ b/zone/bot_commands/bot_spell_max_hp_pct.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_max_hp_pct(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_spell_max_mana_pct.cpp b/zone/bot_commands/bot_spell_max_mana_pct.cpp index a5a72bdf09..d381784312 100644 --- a/zone/bot_commands/bot_spell_max_mana_pct.cpp +++ b/zone/bot_commands/bot_spell_max_mana_pct.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_max_mana_pct(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_spell_max_thresholds.cpp b/zone/bot_commands/bot_spell_max_thresholds.cpp index 72be87a865..80efa55596 100644 --- a/zone/bot_commands/bot_spell_max_thresholds.cpp +++ b/zone/bot_commands/bot_spell_max_thresholds.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_max_thresholds(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_min_hp_pct.cpp b/zone/bot_commands/bot_spell_min_hp_pct.cpp index 05f5f2afce..ea829ec8e0 100644 --- a/zone/bot_commands/bot_spell_min_hp_pct.cpp +++ b/zone/bot_commands/bot_spell_min_hp_pct.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_min_hp_pct(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_spell_min_mana_pct.cpp b/zone/bot_commands/bot_spell_min_mana_pct.cpp index 8f562a55f4..93b712d901 100644 --- a/zone/bot_commands/bot_spell_min_mana_pct.cpp +++ b/zone/bot_commands/bot_spell_min_mana_pct.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_min_mana_pct(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_spell_min_thresholds.cpp b/zone/bot_commands/bot_spell_min_thresholds.cpp index 6ad3127456..03ceff5ade 100644 --- a/zone/bot_commands/bot_spell_min_thresholds.cpp +++ b/zone/bot_commands/bot_spell_min_thresholds.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_min_thresholds(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_pursue_priority.cpp b/zone/bot_commands/bot_spell_pursue_priority.cpp index 8b4e8e373c..6846acf2b7 100644 --- a/zone/bot_commands/bot_spell_pursue_priority.cpp +++ b/zone/bot_commands/bot_spell_pursue_priority.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_pursue_priority(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_spell_resist_limits.cpp b/zone/bot_commands/bot_spell_resist_limits.cpp index 8a9272e789..f36b0e9330 100644 --- a/zone/bot_commands/bot_spell_resist_limits.cpp +++ b/zone/bot_commands/bot_spell_resist_limits.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_resist_limits(Client* c, const Seperator* sep) { diff --git a/zone/bot_commands/bot_spell_target_count.cpp b/zone/bot_commands/bot_spell_target_count.cpp index 3fd4b7496b..9afae97664 100644 --- a/zone/bot_commands/bot_spell_target_count.cpp +++ b/zone/bot_commands/bot_spell_target_count.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spell_target_count(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_spelltypes.cpp b/zone/bot_commands/bot_spelltypes.cpp index 204778a1ba..f9b39fc7b0 100644 --- a/zone/bot_commands/bot_spelltypes.cpp +++ b/zone/bot_commands/bot_spelltypes.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_spelltype_ids(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_suspend.cpp b/zone/bot_commands/bot_suspend.cpp index fcdabbd699..9c246fa383 100644 --- a/zone/bot_commands/bot_suspend.cpp +++ b/zone/bot_commands/bot_suspend.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_suspend(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_taunt.cpp b/zone/bot_commands/bot_taunt.cpp index 2eb4b1c7ea..3e46f5a5fb 100644 --- a/zone/bot_commands/bot_taunt.cpp +++ b/zone/bot_commands/bot_taunt.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_taunt(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_timer.cpp b/zone/bot_commands/bot_timer.cpp index 6413a9e9b0..3de7cdcaa6 100644 --- a/zone/bot_commands/bot_timer.cpp +++ b/zone/bot_commands/bot_timer.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_timer(Client* c, const Seperator* sep) diff --git a/zone/bot_commands/bot_track.cpp b/zone/bot_commands/bot_track.cpp index 1a0c1ce576..7208942a80 100644 --- a/zone/bot_commands/bot_track.cpp +++ b/zone/bot_commands/bot_track.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_track(Client *c, const Seperator *sep) diff --git a/zone/bot_commands/bot_view_combos.cpp b/zone/bot_commands/bot_view_combos.cpp index d8da5a3494..4b2a7aa12b 100644 --- a/zone/bot_commands/bot_view_combos.cpp +++ b/zone/bot_commands/bot_view_combos.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot_command.h" void bot_command_view_combos(Client *c, const Seperator *sep) diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index bf422b2091..5982fc0a72 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "bot_database.h" #include "common/data_verification.h" diff --git a/zone/bot_database.h b/zone/bot_database.h index 279d226695..31ad3368db 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "zone/bot_structs.h" diff --git a/zone/bot_raid.cpp b/zone/bot_raid.cpp index 3a100fe8f0..04d0813069 100644 --- a/zone/bot_raid.cpp +++ b/zone/bot_raid.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/data_verification.h" #include "zone/bot_command.h" #include "zone/bot.h" diff --git a/zone/bot_raid.h b/zone/bot_raid.h index be0ff5658b..1bb1047fa2 100644 --- a/zone/bot_raid.h +++ b/zone/bot_raid.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/misc_functions.h" diff --git a/zone/bot_structs.h b/zone/bot_structs.h index 291718883a..8805622cb6 100644 --- a/zone/bot_structs.h +++ b/zone/bot_structs.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 74a2c69e64..c666a33f69 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "bot.h" #include "common/data_verification.h" diff --git a/zone/cheat_manager.cpp b/zone/cheat_manager.cpp index 4c05bfe163..e543bf4dea 100644 --- a/zone/cheat_manager.cpp +++ b/zone/cheat_manager.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "cheat_manager.h" #include "common/events/player_event_logs.h" diff --git a/zone/cheat_manager.h b/zone/cheat_manager.h index fff27e330b..0c6432b5a8 100644 --- a/zone/cheat_manager.h +++ b/zone/cheat_manager.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eq_packet_structs.h" diff --git a/zone/cli/cli_benchmark_databuckets.cpp b/zone/cli/cli_benchmark_databuckets.cpp index 518ed27676..fdea18c695 100644 --- a/zone/cli/cli_benchmark_databuckets.cpp +++ b/zone/cli/cli_benchmark_databuckets.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/zone_cli.h" #include "zone/sidecar_api/sidecar_api.h" diff --git a/zone/cli/cli_sidecar_serve_http.cpp b/zone/cli/cli_sidecar_serve_http.cpp index 3126a42e82..f7cb9975d9 100644 --- a/zone/cli/cli_sidecar_serve_http.cpp +++ b/zone/cli/cli_sidecar_serve_http.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/zone_cli.h" diff --git a/zone/cli/tests/cli_databuckets.cpp b/zone/cli/tests/cli_databuckets.cpp index 6e2ed74dd5..84d0da7def 100644 --- a/zone/cli/tests/cli_databuckets.cpp +++ b/zone/cli/tests/cli_databuckets.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/zone_cli.h" diff --git a/zone/cli/tests/cli_npc_handins.cpp b/zone/cli/tests/cli_npc_handins.cpp index a51dbd873b..496c51118c 100644 --- a/zone/cli/tests/cli_npc_handins.cpp +++ b/zone/cli/tests/cli_npc_handins.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/zone_cli.h" diff --git a/zone/cli/tests/cli_npc_handins_multiquest.cpp b/zone/cli/tests/cli_npc_handins_multiquest.cpp index 5a8eca6d15..010e437271 100644 --- a/zone/cli/tests/cli_npc_handins_multiquest.cpp +++ b/zone/cli/tests/cli_npc_handins_multiquest.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/zone_cli.h" diff --git a/zone/cli/tests/cli_test_util.cpp b/zone/cli/tests/cli_test_util.cpp index a539303a88..dd5394b68f 100644 --- a/zone/cli/tests/cli_test_util.cpp +++ b/zone/cli/tests/cli_test_util.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/zone.h" void RunTest(const std::string &test_name, const std::string &expected, const std::string &actual) diff --git a/zone/cli/tests/cli_zone_state.cpp b/zone/cli/tests/cli_zone_state.cpp index 881873e61c..26be251a39 100644 --- a/zone/cli/tests/cli_zone_state.cpp +++ b/zone/cli/tests/cli_zone_state.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/zone_cli.h" #include "zone/corpse.h" diff --git a/zone/client.cpp b/zone/client.cpp index 05cb01991a..67462169f6 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "client.h" #include "common/data_bucket.h" diff --git a/zone/client.h b/zone/client.h index 8f464681bb..9dc5960e78 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once class Client; diff --git a/zone/client_bot.cpp b/zone/client_bot.cpp index 83e27729da..0e914c1451 100644 --- a/zone/client_bot.cpp +++ b/zone/client_bot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "client.h" #include "zone/bot.h" diff --git a/zone/client_evolving_items.cpp b/zone/client_evolving_items.cpp index 8abf4d52b4..102ede0b8e 100644 --- a/zone/client_evolving_items.cpp +++ b/zone/client_evolving_items.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "client.h" #include "common/events/player_event_logs.h" diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 98e85c8b26..63b5b1fe48 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "client.h" #include "common/eqemu_logsys.h" diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index effa1017fd..87a4a40091 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1,20 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) - -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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "client.h" #include "common/data_bucket.h" diff --git a/zone/client_packet.h b/zone/client_packet.h index 0840f5edce..009dd75d64 100644 --- a/zone/client_packet.h +++ b/zone/client_packet.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /* Connecting OpCode Handlers */ void Handle_Connect_0x3e33(const EQApplicationPacket *app); void Handle_Connect_OP_ApproveZone(const EQApplicationPacket *app); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 479e49d516..2fc5518301 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1,20 +1,22 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . +*/ +/* client_process.cpp: Handles client login sequence and packets sent from client to zone */ diff --git a/zone/combat_record.cpp b/zone/combat_record.cpp index a70917ab37..cd881b4f96 100644 --- a/zone/combat_record.cpp +++ b/zone/combat_record.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "combat_record.h" #include "common/eqemu_logsys.h" diff --git a/zone/combat_record.h b/zone/combat_record.h index bb3a48a0c5..d08804b4e9 100644 --- a/zone/combat_record.h +++ b/zone/combat_record.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/zone/command.cpp b/zone/command.cpp index 2bd2920603..93e5b3430b 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "command.h" #include "common/data_bucket.h" diff --git a/zone/command.h b/zone/command.h index 752c63bf15..8fa473ba67 100644 --- a/zone/command.h +++ b/zone/command.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/zone/common.h b/zone/common.h index 74673ef7e8..c1376bcd0d 100644 --- a/zone/common.h +++ b/zone/common.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 759ee08a7d..bafcd03e56 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "corpse.h" #include "common/data_verification.h" diff --git a/zone/corpse.h b/zone/corpse.h index 2dbfc3986b..584b7d650c 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once diff --git a/zone/dialogue_window.cpp b/zone/dialogue_window.cpp index 326d706d44..d8863f6b94 100644 --- a/zone/dialogue_window.cpp +++ b/zone/dialogue_window.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "dialogue_window.h" void DialogueWindow::Render(Client *c, std::string markdown) diff --git a/zone/dialogue_window.h b/zone/dialogue_window.h index 4c233d0f45..dc79d40df2 100644 --- a/zone/dialogue_window.h +++ b/zone/dialogue_window.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/zone/doors.cpp b/zone/doors.cpp index 9b6b4a4161..75f382077d 100644 --- a/zone/doors.cpp +++ b/zone/doors.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "doors.h" #include "common/eqemu_logsys.h" diff --git a/zone/doors.h b/zone/doors.h index 807e3d6bac..948e41a71d 100644 --- a/zone/doors.h +++ b/zone/doors.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/doors_repository.h" diff --git a/zone/dynamic_zone.cpp b/zone/dynamic_zone.cpp index 05e95c8547..e2948e0440 100644 --- a/zone/dynamic_zone.cpp +++ b/zone/dynamic_zone.cpp @@ -1,23 +1,20 @@ -/** - * 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "dynamic_zone.h" #include "common/repositories/character_expedition_lockouts_repository.h" diff --git a/zone/dynamic_zone.h b/zone/dynamic_zone.h index 845668e5a9..e90915c38d 100644 --- a/zone/dynamic_zone.h +++ b/zone/dynamic_zone.h @@ -1,23 +1,20 @@ -/** - * 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/dynamic_zone_base.h" diff --git a/zone/effects.cpp b/zone/effects.cpp index 5c81026b44..06c18a41e1 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "mob.h" #include "common/eqemu_logsys.h" diff --git a/zone/embparser.cpp b/zone/embparser.cpp index a81bfa9d47..b617daae7b 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #ifdef EMBPERL #include "common/features.h" diff --git a/zone/embparser.h b/zone/embparser.h index 5aa95dc54c..ae25ec1d4f 100644 --- a/zone/embparser.h +++ b/zone/embparser.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #ifdef EMBPERL diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index debe2c43bb..9977763382 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #ifdef EMBPERL #ifdef EMBPERL_XS diff --git a/zone/embperl.cpp b/zone/embperl.cpp index 7b960659a1..4ae3ad71f9 100644 --- a/zone/embperl.cpp +++ b/zone/embperl.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /* embperl.cpp --------------- diff --git a/zone/embperl.h b/zone/embperl.h index b47367e165..ba955fd0fb 100644 --- a/zone/embperl.h +++ b/zone/embperl.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ /* Embperl.h --------------- diff --git a/zone/encounter.cpp b/zone/encounter.cpp index f124d3631c..25a278e8e9 100644 --- a/zone/encounter.cpp +++ b/zone/encounter.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator -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. + Copyright (C) 2001-2026 EQEmu Development Team -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. + 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; either version 3 of the License, or + (at your option) any later version. -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 -*/ + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "encounter.h" #include "common/races.h" diff --git a/zone/encounter.h b/zone/encounter.h index 70f0ea8cae..bd751fc04a 100644 --- a/zone/encounter.h +++ b/zone/encounter.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) - -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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/timer.h" diff --git a/zone/entity.cpp b/zone/entity.cpp index e6586a3253..e1b25370ff 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "entity.h" #include "common/data_verification.h" diff --git a/zone/entity.h b/zone/entity.h index 05fed5a718..318815266e 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/bodytypes.h" diff --git a/zone/event_codes.h b/zone/event_codes.h index 09a437f22f..e363c17de1 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once typedef enum { diff --git a/zone/exp.cpp b/zone/exp.cpp index fe993f542f..fd6a39dbf0 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/data_bucket.h" #include "common/data_verification.h" #include "common/events/player_event_logs.h" diff --git a/zone/expedition_request.cpp b/zone/expedition_request.cpp index 6c64258673..09b71a7b00 100644 --- a/zone/expedition_request.cpp +++ b/zone/expedition_request.cpp @@ -1,23 +1,20 @@ -/** - * 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "expedition_request.h" #include "common/repositories/character_expedition_lockouts_repository.h" diff --git a/zone/expedition_request.h b/zone/expedition_request.h index 8f1493c444..82e042cdcf 100644 --- a/zone/expedition_request.h +++ b/zone/expedition_request.h @@ -1,23 +1,20 @@ -/** - * 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/dynamic_zone_lockout.h" diff --git a/zone/fastmath.cpp b/zone/fastmath.cpp index f4140c3169..ad40d4831c 100644 --- a/zone/fastmath.cpp +++ b/zone/fastmath.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "fastmath.h" diff --git a/zone/fastmath.h b/zone/fastmath.h index a7ab756820..164318e72e 100644 --- a/zone/fastmath.h +++ b/zone/fastmath.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once class FastMath diff --git a/zone/fearpath.cpp b/zone/fearpath.cpp index 7bd9c6319f..cc8b5b7a35 100644 --- a/zone/fearpath.cpp +++ b/zone/fearpath.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/rulesys.h" #include "zone/map.h" #include "zone/water_map.h" diff --git a/zone/forage.cpp b/zone/forage.cpp index 3bf6689976..25a406a56a 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "forage.h" #include "common/eqemu_logsys.h" diff --git a/zone/forage.h b/zone/forage.h index 4140c02816..32b5fa0f37 100644 --- a/zone/forage.h +++ b/zone/forage.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/zone/global_loot_manager.cpp b/zone/global_loot_manager.cpp index 74e8c15493..a602891192 100644 --- a/zone/global_loot_manager.cpp +++ b/zone/global_loot_manager.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "global_loot_manager.h" #include "zone/client.h" diff --git a/zone/global_loot_manager.h b/zone/global_loot_manager.h index 8ee5dd3822..3bc6ff7054 100644 --- a/zone/global_loot_manager.h +++ b/zone/global_loot_manager.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/zone/gm_commands/acceptrules.cpp b/zone/gm_commands/acceptrules.cpp index 6886cf21b3..4a059c418a 100755 --- a/zone/gm_commands/acceptrules.cpp +++ b/zone/gm_commands/acceptrules.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_acceptrules(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/advnpcspawn.cpp b/zone/gm_commands/advnpcspawn.cpp index 24f7d6b06d..6f319a5c0b 100755 --- a/zone/gm_commands/advnpcspawn.cpp +++ b/zone/gm_commands/advnpcspawn.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/groups.h" diff --git a/zone/gm_commands/aggrozone.cpp b/zone/gm_commands/aggrozone.cpp index 5503acac58..a17a94e6c4 100755 --- a/zone/gm_commands/aggrozone.cpp +++ b/zone/gm_commands/aggrozone.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_aggrozone(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/ai.cpp b/zone/gm_commands/ai.cpp index 84705a3e6a..ce9c75f598 100755 --- a/zone/gm_commands/ai.cpp +++ b/zone/gm_commands/ai.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_ai(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/appearance.cpp b/zone/gm_commands/appearance.cpp index c4f52b132e..caa0b589ab 100755 --- a/zone/gm_commands/appearance.cpp +++ b/zone/gm_commands/appearance.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_appearance(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/appearanceeffects.cpp b/zone/gm_commands/appearanceeffects.cpp index 09ba6cb4ab..b924097d95 100644 --- a/zone/gm_commands/appearanceeffects.cpp +++ b/zone/gm_commands/appearanceeffects.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_appearanceeffects(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/attack.cpp b/zone/gm_commands/attack.cpp index e62743c43f..c1cc55b8e4 100755 --- a/zone/gm_commands/attack.cpp +++ b/zone/gm_commands/attack.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_attack(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/augmentitem.cpp b/zone/gm_commands/augmentitem.cpp index ddf0559e92..f673f0b631 100755 --- a/zone/gm_commands/augmentitem.cpp +++ b/zone/gm_commands/augmentitem.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/object.h" diff --git a/zone/gm_commands/ban.cpp b/zone/gm_commands/ban.cpp index 6050978f84..474555e23c 100755 --- a/zone/gm_commands/ban.cpp +++ b/zone/gm_commands/ban.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/bugs.cpp b/zone/gm_commands/bugs.cpp index 2aeea05070..d96dfab22f 100755 --- a/zone/gm_commands/bugs.cpp +++ b/zone/gm_commands/bugs.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/bug_reports_repository.h" #include "zone/client.h" diff --git a/zone/gm_commands/camerashake.cpp b/zone/gm_commands/camerashake.cpp index 13a26d9884..98c2fb334e 100755 --- a/zone/gm_commands/camerashake.cpp +++ b/zone/gm_commands/camerashake.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/castspell.cpp b/zone/gm_commands/castspell.cpp index 9fc940947e..00ad71dbc5 100755 --- a/zone/gm_commands/castspell.cpp +++ b/zone/gm_commands/castspell.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_castspell(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/chat.cpp b/zone/gm_commands/chat.cpp index eedcb81ff1..eb4cd16295 100755 --- a/zone/gm_commands/chat.cpp +++ b/zone/gm_commands/chat.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/clearxtargets.cpp b/zone/gm_commands/clearxtargets.cpp index 337d1de0ec..1865ea312d 100644 --- a/zone/gm_commands/clearxtargets.cpp +++ b/zone/gm_commands/clearxtargets.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_clearxtargets(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/copycharacter.cpp b/zone/gm_commands/copycharacter.cpp index cfd8de48a4..1877344a4d 100755 --- a/zone/gm_commands/copycharacter.cpp +++ b/zone/gm_commands/copycharacter.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_copycharacter(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/corpse.cpp b/zone/gm_commands/corpse.cpp index 560e993193..6a77cdd0f0 100755 --- a/zone/gm_commands/corpse.cpp +++ b/zone/gm_commands/corpse.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/corpse.h" diff --git a/zone/gm_commands/corpsefix.cpp b/zone/gm_commands/corpsefix.cpp index 3370e827b4..44a26f3289 100755 --- a/zone/gm_commands/corpsefix.cpp +++ b/zone/gm_commands/corpsefix.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/corpse.h" diff --git a/zone/gm_commands/countitem.cpp b/zone/gm_commands/countitem.cpp index 69aaa28323..9e00f20398 100644 --- a/zone/gm_commands/countitem.cpp +++ b/zone/gm_commands/countitem.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_countitem(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/damage.cpp b/zone/gm_commands/damage.cpp index 8ddd811380..bb2104d212 100755 --- a/zone/gm_commands/damage.cpp +++ b/zone/gm_commands/damage.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_damage(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/databuckets.cpp b/zone/gm_commands/databuckets.cpp index bf9c1b84fa..43975c4741 100755 --- a/zone/gm_commands/databuckets.cpp +++ b/zone/gm_commands/databuckets.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/data_bucket.h" #include "common/repositories/data_buckets_repository.h" #include "zone/client.h" diff --git a/zone/gm_commands/dbspawn2.cpp b/zone/gm_commands/dbspawn2.cpp index 2db3449484..22bf8422cd 100755 --- a/zone/gm_commands/dbspawn2.cpp +++ b/zone/gm_commands/dbspawn2.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_dbspawn2(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/delacct.cpp b/zone/gm_commands/delacct.cpp index 198e736b4a..f9bd2289e8 100755 --- a/zone/gm_commands/delacct.cpp +++ b/zone/gm_commands/delacct.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/account_repository.h" #include "zone/client.h" diff --git a/zone/gm_commands/delpetition.cpp b/zone/gm_commands/delpetition.cpp index f42cf27728..de825ff498 100755 --- a/zone/gm_commands/delpetition.cpp +++ b/zone/gm_commands/delpetition.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_delpetition(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/depop.cpp b/zone/gm_commands/depop.cpp index 0c10fc8f4a..cd61548964 100755 --- a/zone/gm_commands/depop.cpp +++ b/zone/gm_commands/depop.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/corpse.h" diff --git a/zone/gm_commands/depopzone.cpp b/zone/gm_commands/depopzone.cpp index 0d483cbd12..314215a622 100755 --- a/zone/gm_commands/depopzone.cpp +++ b/zone/gm_commands/depopzone.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_depopzone(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/devtools.cpp b/zone/gm_commands/devtools.cpp index 2326c41299..2518ccfd55 100755 --- a/zone/gm_commands/devtools.cpp +++ b/zone/gm_commands/devtools.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/data_bucket.h" #include "zone/client.h" diff --git a/zone/gm_commands/disablerecipe.cpp b/zone/gm_commands/disablerecipe.cpp index b9936f3161..5b5bb47eff 100755 --- a/zone/gm_commands/disablerecipe.cpp +++ b/zone/gm_commands/disablerecipe.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_disablerecipe(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/disarmtrap.cpp b/zone/gm_commands/disarmtrap.cpp index 2f21efd59a..88cd2655bc 100755 --- a/zone/gm_commands/disarmtrap.cpp +++ b/zone/gm_commands/disarmtrap.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_disarmtrap(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/doanim.cpp b/zone/gm_commands/doanim.cpp index 2e050194a3..578d5c9c68 100755 --- a/zone/gm_commands/doanim.cpp +++ b/zone/gm_commands/doanim.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dialogue_window.h" diff --git a/zone/gm_commands/door.cpp b/zone/gm_commands/door.cpp index 46ea56a93b..9a9d447d66 100755 --- a/zone/gm_commands/door.cpp +++ b/zone/gm_commands/door.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "door_manipulation.h" #include "zone/client.h" diff --git a/zone/gm_commands/door_manipulation.cpp b/zone/gm_commands/door_manipulation.cpp index 28af983ddc..91472865cf 100644 --- a/zone/gm_commands/door_manipulation.cpp +++ b/zone/gm_commands/door_manipulation.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "door_manipulation.h" #include "common/misc_functions.h" diff --git a/zone/gm_commands/door_manipulation.h b/zone/gm_commands/door_manipulation.h index 4a80ebeca4..3906cad040 100644 --- a/zone/gm_commands/door_manipulation.h +++ b/zone/gm_commands/door_manipulation.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/tool_game_objects_repository.h" diff --git a/zone/gm_commands/dye.cpp b/zone/gm_commands/dye.cpp index efd2104187..4812352f66 100755 --- a/zone/gm_commands/dye.cpp +++ b/zone/gm_commands/dye.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_dye(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/dz.cpp b/zone/gm_commands/dz.cpp index 8df3a434e5..76a721d944 100755 --- a/zone/gm_commands/dz.cpp +++ b/zone/gm_commands/dz.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dynamic_zone.h" diff --git a/zone/gm_commands/dzkickplayers.cpp b/zone/gm_commands/dzkickplayers.cpp index 4a0ff340b8..4b062ce7b5 100755 --- a/zone/gm_commands/dzkickplayers.cpp +++ b/zone/gm_commands/dzkickplayers.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dynamic_zone.h" diff --git a/zone/gm_commands/editmassrespawn.cpp b/zone/gm_commands/editmassrespawn.cpp index a48475c927..febd3256b9 100755 --- a/zone/gm_commands/editmassrespawn.cpp +++ b/zone/gm_commands/editmassrespawn.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_editmassrespawn(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/emote.cpp b/zone/gm_commands/emote.cpp index 6fc0c6a721..aca2e22f9a 100755 --- a/zone/gm_commands/emote.cpp +++ b/zone/gm_commands/emote.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/emptyinventory.cpp b/zone/gm_commands/emptyinventory.cpp index 869fea3d5f..d5e872ef02 100644 --- a/zone/gm_commands/emptyinventory.cpp +++ b/zone/gm_commands/emptyinventory.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_emptyinventory(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/enablerecipe.cpp b/zone/gm_commands/enablerecipe.cpp index 28f4cff1c0..68726b2dd9 100755 --- a/zone/gm_commands/enablerecipe.cpp +++ b/zone/gm_commands/enablerecipe.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_enablerecipe(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/entityvariable.cpp b/zone/gm_commands/entityvariable.cpp index fc64a67963..f97ae3fe59 100644 --- a/zone/gm_commands/entityvariable.cpp +++ b/zone/gm_commands/entityvariable.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_entityvariable(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/evolving_items.cpp b/zone/gm_commands/evolving_items.cpp index cb58d67338..0563ad4e7a 100644 --- a/zone/gm_commands/evolving_items.cpp +++ b/zone/gm_commands/evolving_items.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/evolving_items.h" #include "zone/client.h" #include "zone/command.h" diff --git a/zone/gm_commands/exptoggle.cpp b/zone/gm_commands/exptoggle.cpp index 8aba5b627b..d14ea17001 100644 --- a/zone/gm_commands/exptoggle.cpp +++ b/zone/gm_commands/exptoggle.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_exptoggle(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/faction.cpp b/zone/gm_commands/faction.cpp index c703d51c3a..c62bd4dac9 100644 --- a/zone/gm_commands/faction.cpp +++ b/zone/gm_commands/faction.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_faction(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/faction_association.cpp b/zone/gm_commands/faction_association.cpp index 8d900d3a9a..5b292202d0 100644 --- a/zone/gm_commands/faction_association.cpp +++ b/zone/gm_commands/faction_association.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_faction_association(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/feature.cpp b/zone/gm_commands/feature.cpp index a0670686b6..8ea431950c 100644 --- a/zone/gm_commands/feature.cpp +++ b/zone/gm_commands/feature.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_feature(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find.cpp b/zone/gm_commands/find.cpp index cf25624b24..3363ea6a3c 100644 --- a/zone/gm_commands/find.cpp +++ b/zone/gm_commands/find.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindAA(Client* c, const Seperator* sep); diff --git a/zone/gm_commands/find/find_aa.cpp b/zone/gm_commands/find/find_aa.cpp index e7155014e7..a973eb6020 100644 --- a/zone/gm_commands/find/find_aa.cpp +++ b/zone/gm_commands/find/find_aa.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/seperator.h" #include "zone/client.h" diff --git a/zone/gm_commands/find/find_account.cpp b/zone/gm_commands/find/find_account.cpp index 828daecb2c..e53450b50a 100644 --- a/zone/gm_commands/find/find_account.cpp +++ b/zone/gm_commands/find/find_account.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/account_repository.h" #include "zone/client.h" diff --git a/zone/gm_commands/find/find_body_type.cpp b/zone/gm_commands/find/find_body_type.cpp index 3e1bbed165..9391c21c7f 100644 --- a/zone/gm_commands/find/find_body_type.cpp +++ b/zone/gm_commands/find/find_body_type.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindBodyType(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find/find_bot.cpp b/zone/gm_commands/find/find_bot.cpp index f36ec7eac1..308f57be75 100644 --- a/zone/gm_commands/find/find_bot.cpp +++ b/zone/gm_commands/find/find_bot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/bot_data_repository.h" #include "zone/client.h" diff --git a/zone/gm_commands/find/find_bug_category.cpp b/zone/gm_commands/find/find_bug_category.cpp index cba0369fcf..0a4d95c485 100644 --- a/zone/gm_commands/find/find_bug_category.cpp +++ b/zone/gm_commands/find/find_bug_category.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindBugCategory(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find/find_character.cpp b/zone/gm_commands/find/find_character.cpp index d822e3ed50..421ca69a64 100644 --- a/zone/gm_commands/find/find_character.cpp +++ b/zone/gm_commands/find/find_character.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/character_data_repository.h" #include "zone/client.h" diff --git a/zone/gm_commands/find/find_class.cpp b/zone/gm_commands/find/find_class.cpp index cff72b201c..c734cf5cb2 100644 --- a/zone/gm_commands/find/find_class.cpp +++ b/zone/gm_commands/find/find_class.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindClass(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find/find_comparison_type.cpp b/zone/gm_commands/find/find_comparison_type.cpp index 9ee2ef49a2..7461499081 100644 --- a/zone/gm_commands/find/find_comparison_type.cpp +++ b/zone/gm_commands/find/find_comparison_type.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindComparisonType(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find/find_currency.cpp b/zone/gm_commands/find/find_currency.cpp index 41928b71a9..8851d03027 100644 --- a/zone/gm_commands/find/find_currency.cpp +++ b/zone/gm_commands/find/find_currency.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/command.h" diff --git a/zone/gm_commands/find/find_deity.cpp b/zone/gm_commands/find/find_deity.cpp index a9b298a2a7..8b6feb5d95 100644 --- a/zone/gm_commands/find/find_deity.cpp +++ b/zone/gm_commands/find/find_deity.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindDeity(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find/find_emote.cpp b/zone/gm_commands/find/find_emote.cpp index af95c08322..81f9c0819e 100644 --- a/zone/gm_commands/find/find_emote.cpp +++ b/zone/gm_commands/find/find_emote.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindEmote(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find/find_faction.cpp b/zone/gm_commands/find/find_faction.cpp index 8bd933b53a..9cba1f90e2 100644 --- a/zone/gm_commands/find/find_faction.cpp +++ b/zone/gm_commands/find/find_faction.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindFaction(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find/find_item.cpp b/zone/gm_commands/find/find_item.cpp index 537c441a31..0d615e5763 100644 --- a/zone/gm_commands/find/find_item.cpp +++ b/zone/gm_commands/find/find_item.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "common/repositories/items_repository.h" diff --git a/zone/gm_commands/find/find_language.cpp b/zone/gm_commands/find/find_language.cpp index 699c504464..cc808b6d5f 100644 --- a/zone/gm_commands/find/find_language.cpp +++ b/zone/gm_commands/find/find_language.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindLanguage(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find/find_ldon_theme.cpp b/zone/gm_commands/find/find_ldon_theme.cpp index 1310364de6..bb755db968 100644 --- a/zone/gm_commands/find/find_ldon_theme.cpp +++ b/zone/gm_commands/find/find_ldon_theme.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindLDoNTheme(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find/find_npctype.cpp b/zone/gm_commands/find/find_npctype.cpp index 7cb177d79c..5dc0c15715 100644 --- a/zone/gm_commands/find/find_npctype.cpp +++ b/zone/gm_commands/find/find_npctype.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/command.h" diff --git a/zone/gm_commands/find/find_object_type.cpp b/zone/gm_commands/find/find_object_type.cpp index c0768cc1fb..6b09b7217b 100644 --- a/zone/gm_commands/find/find_object_type.cpp +++ b/zone/gm_commands/find/find_object_type.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/object.h" diff --git a/zone/gm_commands/find/find_race.cpp b/zone/gm_commands/find/find_race.cpp index 644ffce738..4404f25e93 100644 --- a/zone/gm_commands/find/find_race.cpp +++ b/zone/gm_commands/find/find_race.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindRace(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find/find_recipe.cpp b/zone/gm_commands/find/find_recipe.cpp index 7003c801ab..ef3fe13f56 100644 --- a/zone/gm_commands/find/find_recipe.cpp +++ b/zone/gm_commands/find/find_recipe.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/tradeskill_recipe_repository.h" #include "zone/client.h" #include "zone/command.h" diff --git a/zone/gm_commands/find/find_skill.cpp b/zone/gm_commands/find/find_skill.cpp index 12ceabb8a1..116b185aa1 100644 --- a/zone/gm_commands/find/find_skill.cpp +++ b/zone/gm_commands/find/find_skill.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindSkill(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find/find_special_ability.cpp b/zone/gm_commands/find/find_special_ability.cpp index 24cdce4474..2ffbdeab80 100644 --- a/zone/gm_commands/find/find_special_ability.cpp +++ b/zone/gm_commands/find/find_special_ability.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindSpecialAbility(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find/find_spell.cpp b/zone/gm_commands/find/find_spell.cpp index 2c2afae69d..8c2dfb1bee 100644 --- a/zone/gm_commands/find/find_spell.cpp +++ b/zone/gm_commands/find/find_spell.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" uint8 GetCommandStatus(std::string command_name); diff --git a/zone/gm_commands/find/find_stance.cpp b/zone/gm_commands/find/find_stance.cpp index 7fb2ceecb5..a1470309ff 100644 --- a/zone/gm_commands/find/find_stance.cpp +++ b/zone/gm_commands/find/find_stance.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void FindStance(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/find/find_task.cpp b/zone/gm_commands/find/find_task.cpp index 21ffe5b0da..85762a361d 100644 --- a/zone/gm_commands/find/find_task.cpp +++ b/zone/gm_commands/find/find_task.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" uint8 GetCommandStatus(std::string command_name); diff --git a/zone/gm_commands/find/find_zone.cpp b/zone/gm_commands/find/find_zone.cpp index eb7a47ff68..1058bba1ab 100644 --- a/zone/gm_commands/find/find_zone.cpp +++ b/zone/gm_commands/find/find_zone.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/content/world_content_service.h" #include "zone/client.h" diff --git a/zone/gm_commands/fish.cpp b/zone/gm_commands/fish.cpp index 07632d3a05..373d6e238a 100644 --- a/zone/gm_commands/fish.cpp +++ b/zone/gm_commands/fish.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_fish(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/fixmob.cpp b/zone/gm_commands/fixmob.cpp index e91cefd17d..74767749f6 100755 --- a/zone/gm_commands/fixmob.cpp +++ b/zone/gm_commands/fixmob.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SendFixMobSubCommands(Client* c) diff --git a/zone/gm_commands/flagedit.cpp b/zone/gm_commands/flagedit.cpp index cb260e09e3..455c2e5655 100755 --- a/zone/gm_commands/flagedit.cpp +++ b/zone/gm_commands/flagedit.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_flagedit(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/fleeinfo.cpp b/zone/gm_commands/fleeinfo.cpp index 3c5f6ca734..50e3af70f3 100644 --- a/zone/gm_commands/fleeinfo.cpp +++ b/zone/gm_commands/fleeinfo.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_fleeinfo(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/forage.cpp b/zone/gm_commands/forage.cpp index 943de16914..e7e8282e6b 100644 --- a/zone/gm_commands/forage.cpp +++ b/zone/gm_commands/forage.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_forage(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/gearup.cpp b/zone/gm_commands/gearup.cpp index 13c05da63d..4414067344 100755 --- a/zone/gm_commands/gearup.cpp +++ b/zone/gm_commands/gearup.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/content/world_content_service.h" #include "common/http/httplib.h" #include "zone/client.h" diff --git a/zone/gm_commands/giveitem.cpp b/zone/gm_commands/giveitem.cpp index b0fc7f131d..addd112752 100755 --- a/zone/gm_commands/giveitem.cpp +++ b/zone/gm_commands/giveitem.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_giveitem(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/givemoney.cpp b/zone/gm_commands/givemoney.cpp index 2965b755af..1eb1308106 100755 --- a/zone/gm_commands/givemoney.cpp +++ b/zone/gm_commands/givemoney.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_givemoney(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/gmzone.cpp b/zone/gm_commands/gmzone.cpp index 25351f7cbf..752e4fb14b 100755 --- a/zone/gm_commands/gmzone.cpp +++ b/zone/gm_commands/gmzone.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/data_bucket.h" #include "zone/client.h" diff --git a/zone/gm_commands/goto.cpp b/zone/gm_commands/goto.cpp index b9b177ab0a..5a33bafc42 100755 --- a/zone/gm_commands/goto.cpp +++ b/zone/gm_commands/goto.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_goto(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/grantaa.cpp b/zone/gm_commands/grantaa.cpp index 0d12fb717e..c638920539 100644 --- a/zone/gm_commands/grantaa.cpp +++ b/zone/gm_commands/grantaa.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_grantaa(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/grid.cpp b/zone/gm_commands/grid.cpp index 62a0eba95a..21cfb2f3ed 100755 --- a/zone/gm_commands/grid.cpp +++ b/zone/gm_commands/grid.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/grid_entries_repository.h" #include "zone/client.h" diff --git a/zone/gm_commands/guild.cpp b/zone/gm_commands/guild.cpp index 330fe793be..f2fb52be36 100755 --- a/zone/gm_commands/guild.cpp +++ b/zone/gm_commands/guild.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/doors.h" #include "zone/guild_mgr.h" diff --git a/zone/gm_commands/hp.cpp b/zone/gm_commands/hp.cpp index 983704c417..8152009c52 100755 --- a/zone/gm_commands/hp.cpp +++ b/zone/gm_commands/hp.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_hp(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/illusion_block.cpp b/zone/gm_commands/illusion_block.cpp index 822abf78cc..585195c310 100644 --- a/zone/gm_commands/illusion_block.cpp +++ b/zone/gm_commands/illusion_block.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dialogue_window.h" diff --git a/zone/gm_commands/instance.cpp b/zone/gm_commands/instance.cpp index ef43c5cd6a..ebca73023e 100755 --- a/zone/gm_commands/instance.cpp +++ b/zone/gm_commands/instance.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_instance(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/interrogateinv.cpp b/zone/gm_commands/interrogateinv.cpp index 6cbfa74e94..e046ea8c2f 100755 --- a/zone/gm_commands/interrogateinv.cpp +++ b/zone/gm_commands/interrogateinv.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_interrogateinv(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/interrupt.cpp b/zone/gm_commands/interrupt.cpp index 7365a3b0d9..7eeaabfbe4 100755 --- a/zone/gm_commands/interrupt.cpp +++ b/zone/gm_commands/interrupt.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_interrupt(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/invsnapshot.cpp b/zone/gm_commands/invsnapshot.cpp index 4a2fbec9ea..2998da040d 100755 --- a/zone/gm_commands/invsnapshot.cpp +++ b/zone/gm_commands/invsnapshot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_invsnapshot(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/ipban.cpp b/zone/gm_commands/ipban.cpp index cff87628c0..806d5a1337 100755 --- a/zone/gm_commands/ipban.cpp +++ b/zone/gm_commands/ipban.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_ipban(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/kick.cpp b/zone/gm_commands/kick.cpp index 2825312d8f..3f16748392 100755 --- a/zone/gm_commands/kick.cpp +++ b/zone/gm_commands/kick.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/kill.cpp b/zone/gm_commands/kill.cpp index 56c272fc82..42b1113a2c 100755 --- a/zone/gm_commands/kill.cpp +++ b/zone/gm_commands/kill.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_kill(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/killallnpcs.cpp b/zone/gm_commands/killallnpcs.cpp index 94565845ba..6b133ea3a6 100755 --- a/zone/gm_commands/killallnpcs.cpp +++ b/zone/gm_commands/killallnpcs.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_killallnpcs(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/list.cpp b/zone/gm_commands/list.cpp index 74c1eb7b0e..22607ec4ec 100755 --- a/zone/gm_commands/list.cpp +++ b/zone/gm_commands/list.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/command.h" #include "zone/corpse.h" diff --git a/zone/gm_commands/loc.cpp b/zone/gm_commands/loc.cpp index 6579a8d95d..88833c3aba 100755 --- a/zone/gm_commands/loc.cpp +++ b/zone/gm_commands/loc.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/water_map.h" diff --git a/zone/gm_commands/logs.cpp b/zone/gm_commands/logs.cpp index 33ace54e4e..8d64348679 100755 --- a/zone/gm_commands/logs.cpp +++ b/zone/gm_commands/logs.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/lootsim.cpp b/zone/gm_commands/lootsim.cpp index 55a7dc9d96..ad22090699 100755 --- a/zone/gm_commands/lootsim.cpp +++ b/zone/gm_commands/lootsim.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_lootsim(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/makepet.cpp b/zone/gm_commands/makepet.cpp index d23e552c98..736557b86f 100755 --- a/zone/gm_commands/makepet.cpp +++ b/zone/gm_commands/makepet.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_makepet(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/memspell.cpp b/zone/gm_commands/memspell.cpp index 148a192730..c331d19daa 100755 --- a/zone/gm_commands/memspell.cpp +++ b/zone/gm_commands/memspell.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_memspell(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/merchantshop.cpp b/zone/gm_commands/merchantshop.cpp index 4e950ac986..799d7153bd 100755 --- a/zone/gm_commands/merchantshop.cpp +++ b/zone/gm_commands/merchantshop.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_merchantshop(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/modifynpcstat.cpp b/zone/gm_commands/modifynpcstat.cpp index 00ff3d9b31..bf32d20d9d 100755 --- a/zone/gm_commands/modifynpcstat.cpp +++ b/zone/gm_commands/modifynpcstat.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" std::map GetModifyNPCStatMap() diff --git a/zone/gm_commands/movechar.cpp b/zone/gm_commands/movechar.cpp index 7dc31424b6..7ff4f2a4ab 100755 --- a/zone/gm_commands/movechar.cpp +++ b/zone/gm_commands/movechar.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_movechar(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/movement.cpp b/zone/gm_commands/movement.cpp index 992de368dc..2069da57d0 100755 --- a/zone/gm_commands/movement.cpp +++ b/zone/gm_commands/movement.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/mob_movement_manager.h" diff --git a/zone/gm_commands/myskills.cpp b/zone/gm_commands/myskills.cpp index 423783ff3a..f47f235dcf 100755 --- a/zone/gm_commands/myskills.cpp +++ b/zone/gm_commands/myskills.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_myskills(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/mysql.cpp b/zone/gm_commands/mysql.cpp index fc6dadedf6..4920b272ca 100755 --- a/zone/gm_commands/mysql.cpp +++ b/zone/gm_commands/mysql.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_mysql(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/mystats.cpp b/zone/gm_commands/mystats.cpp index 428c8ed52b..8ee377d8cc 100755 --- a/zone/gm_commands/mystats.cpp +++ b/zone/gm_commands/mystats.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot.h" #include "zone/client.h" diff --git a/zone/gm_commands/npccast.cpp b/zone/gm_commands/npccast.cpp index 2d3b5f5212..a0edb8ab26 100755 --- a/zone/gm_commands/npccast.cpp +++ b/zone/gm_commands/npccast.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_npccast(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/npcedit.cpp b/zone/gm_commands/npcedit.cpp index a1b60ca7af..e1eb40f756 100755 --- a/zone/gm_commands/npcedit.cpp +++ b/zone/gm_commands/npcedit.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/npc_types_repository.h" #include "zone/client.h" #include "zone/groups.h" diff --git a/zone/gm_commands/npceditmass.cpp b/zone/gm_commands/npceditmass.cpp index 4e32e24e33..6b2f5d8b13 100755 --- a/zone/gm_commands/npceditmass.cpp +++ b/zone/gm_commands/npceditmass.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_npceditmass(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/npcemote.cpp b/zone/gm_commands/npcemote.cpp index 81552ce80f..cf4cc0cd74 100755 --- a/zone/gm_commands/npcemote.cpp +++ b/zone/gm_commands/npcemote.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_npcemote(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/npcloot.cpp b/zone/gm_commands/npcloot.cpp index c33cac9bb8..164e6a8966 100755 --- a/zone/gm_commands/npcloot.cpp +++ b/zone/gm_commands/npcloot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/data_verification.h" #include "zone/client.h" #include "zone/corpse.h" diff --git a/zone/gm_commands/npcsay.cpp b/zone/gm_commands/npcsay.cpp index 6ffb6cf411..38feb6a800 100755 --- a/zone/gm_commands/npcsay.cpp +++ b/zone/gm_commands/npcsay.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_npcsay(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/npcshout.cpp b/zone/gm_commands/npcshout.cpp index d3865fa707..ba536a3e0c 100755 --- a/zone/gm_commands/npcshout.cpp +++ b/zone/gm_commands/npcshout.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_npcshout(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/npcspawn.cpp b/zone/gm_commands/npcspawn.cpp index f3c274db14..01d8127713 100755 --- a/zone/gm_commands/npcspawn.cpp +++ b/zone/gm_commands/npcspawn.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_npcspawn(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/npctypespawn.cpp b/zone/gm_commands/npctypespawn.cpp index 4c0647e528..3359175554 100755 --- a/zone/gm_commands/npctypespawn.cpp +++ b/zone/gm_commands/npctypespawn.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_npctypespawn(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/nudge.cpp b/zone/gm_commands/nudge.cpp index 2544f15747..50331f0eea 100755 --- a/zone/gm_commands/nudge.cpp +++ b/zone/gm_commands/nudge.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_nudge(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/nukebuffs.cpp b/zone/gm_commands/nukebuffs.cpp index b4d27b1a25..435fcca43f 100755 --- a/zone/gm_commands/nukebuffs.cpp +++ b/zone/gm_commands/nukebuffs.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_nukebuffs(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/nukeitem.cpp b/zone/gm_commands/nukeitem.cpp index b7198e5c95..1ad32646e5 100755 --- a/zone/gm_commands/nukeitem.cpp +++ b/zone/gm_commands/nukeitem.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_nukeitem(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/object.cpp b/zone/gm_commands/object.cpp index 9dbca5656e..bd39b122f6 100755 --- a/zone/gm_commands/object.cpp +++ b/zone/gm_commands/object.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "object_manipulation.h" #include "zone/client.h" diff --git a/zone/gm_commands/object_manipulation.cpp b/zone/gm_commands/object_manipulation.cpp index a5ae7f5558..705a4568e0 100644 --- a/zone/gm_commands/object_manipulation.cpp +++ b/zone/gm_commands/object_manipulation.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/misc_functions.h" #include "common/repositories/object_repository.h" #include "common/strings.h" diff --git a/zone/gm_commands/object_manipulation.h b/zone/gm_commands/object_manipulation.h index b8ffe2b2f1..a6cfaeb307 100644 --- a/zone/gm_commands/object_manipulation.h +++ b/zone/gm_commands/object_manipulation.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "zone/client.h" diff --git a/zone/gm_commands/parcels.cpp b/zone/gm_commands/parcels.cpp index da7e843ab0..d11d16fd33 100644 --- a/zone/gm_commands/parcels.cpp +++ b/zone/gm_commands/parcels.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/events/player_event_logs.h" #include "zone/client.h" #include "zone/queryserv.h" diff --git a/zone/gm_commands/path.cpp b/zone/gm_commands/path.cpp index a4393a55aa..abe1e5fea8 100755 --- a/zone/gm_commands/path.cpp +++ b/zone/gm_commands/path.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_path(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/peqzone.cpp b/zone/gm_commands/peqzone.cpp index 052379bf1e..e5a3660383 100755 --- a/zone/gm_commands/peqzone.cpp +++ b/zone/gm_commands/peqzone.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_peqzone(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/petitems.cpp b/zone/gm_commands/petitems.cpp index c9f7e94818..0152719b34 100644 --- a/zone/gm_commands/petitems.cpp +++ b/zone/gm_commands/petitems.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot.h" #include "zone/client.h" diff --git a/zone/gm_commands/petname.cpp b/zone/gm_commands/petname.cpp index 04cc71e5a2..900360b46e 100755 --- a/zone/gm_commands/petname.cpp +++ b/zone/gm_commands/petname.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_petname(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/picklock.cpp b/zone/gm_commands/picklock.cpp index 4ee3688287..0b566efce0 100755 --- a/zone/gm_commands/picklock.cpp +++ b/zone/gm_commands/picklock.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_picklock(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/profanity.cpp b/zone/gm_commands/profanity.cpp index daf3309bd8..50891473fc 100755 --- a/zone/gm_commands/profanity.cpp +++ b/zone/gm_commands/profanity.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/push.cpp b/zone/gm_commands/push.cpp index 9bc4da240b..9f90f60db3 100755 --- a/zone/gm_commands/push.cpp +++ b/zone/gm_commands/push.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/fastmath.h" diff --git a/zone/gm_commands/raidloot.cpp b/zone/gm_commands/raidloot.cpp index 745282c868..19581dd8bc 100755 --- a/zone/gm_commands/raidloot.cpp +++ b/zone/gm_commands/raidloot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/groups.h" #include "zone/raids.h" diff --git a/zone/gm_commands/randomfeatures.cpp b/zone/gm_commands/randomfeatures.cpp index a28b130654..7cbd238544 100755 --- a/zone/gm_commands/randomfeatures.cpp +++ b/zone/gm_commands/randomfeatures.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_randomfeatures(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/refreshgroup.cpp b/zone/gm_commands/refreshgroup.cpp index 4b1500b4b6..cf4af4a2bb 100755 --- a/zone/gm_commands/refreshgroup.cpp +++ b/zone/gm_commands/refreshgroup.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/groups.h" diff --git a/zone/gm_commands/reload.cpp b/zone/gm_commands/reload.cpp index 6991a37be2..eb5702bdc1 100644 --- a/zone/gm_commands/reload.cpp +++ b/zone/gm_commands/reload.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/server_reload_types.h" #include "common/strings.h" #include "zone/client.h" diff --git a/zone/gm_commands/removeitem.cpp b/zone/gm_commands/removeitem.cpp index 05cfb26af8..7b08c186ea 100644 --- a/zone/gm_commands/removeitem.cpp +++ b/zone/gm_commands/removeitem.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_removeitem(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/repop.cpp b/zone/gm_commands/repop.cpp index cd600b3d99..734f76dd53 100755 --- a/zone/gm_commands/repop.cpp +++ b/zone/gm_commands/repop.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_repop(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/resetaa.cpp b/zone/gm_commands/resetaa.cpp index 40236ef4e5..36a03cb9a1 100755 --- a/zone/gm_commands/resetaa.cpp +++ b/zone/gm_commands/resetaa.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_resetaa(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/resetaa_timer.cpp b/zone/gm_commands/resetaa_timer.cpp index 4107e2a9d0..890e720624 100755 --- a/zone/gm_commands/resetaa_timer.cpp +++ b/zone/gm_commands/resetaa_timer.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_resetaa_timer(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/resetdisc_timer.cpp b/zone/gm_commands/resetdisc_timer.cpp index 86c98ebba3..fbbaa90e24 100755 --- a/zone/gm_commands/resetdisc_timer.cpp +++ b/zone/gm_commands/resetdisc_timer.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_resetdisc_timer(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/revoke.cpp b/zone/gm_commands/revoke.cpp index 24d6e89339..774982e715 100755 --- a/zone/gm_commands/revoke.cpp +++ b/zone/gm_commands/revoke.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/roambox.cpp b/zone/gm_commands/roambox.cpp index fd762373b2..a4a6a0b1f5 100755 --- a/zone/gm_commands/roambox.cpp +++ b/zone/gm_commands/roambox.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/groups.h" diff --git a/zone/gm_commands/rules.cpp b/zone/gm_commands/rules.cpp index 526f24861b..8c51060f98 100755 --- a/zone/gm_commands/rules.cpp +++ b/zone/gm_commands/rules.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/rule_sets_repository.h" #include "common/repositories/rule_values_repository.h" #include "zone/client.h" diff --git a/zone/gm_commands/save.cpp b/zone/gm_commands/save.cpp index 8d7df60c0a..0b1f2528e3 100755 --- a/zone/gm_commands/save.cpp +++ b/zone/gm_commands/save.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/corpse.h" diff --git a/zone/gm_commands/scale.cpp b/zone/gm_commands/scale.cpp index 8169ccd37b..2589fdf42e 100755 --- a/zone/gm_commands/scale.cpp +++ b/zone/gm_commands/scale.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/npc_scale_manager.h" diff --git a/zone/gm_commands/scribespell.cpp b/zone/gm_commands/scribespell.cpp index 7b5d40605b..74e55032e1 100755 --- a/zone/gm_commands/scribespell.cpp +++ b/zone/gm_commands/scribespell.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_scribespell(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/scribespells.cpp b/zone/gm_commands/scribespells.cpp index f9a016594e..6920db08bc 100755 --- a/zone/gm_commands/scribespells.cpp +++ b/zone/gm_commands/scribespells.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_scribespells(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/sendzonespawns.cpp b/zone/gm_commands/sendzonespawns.cpp index 3834ad7fb0..87b747bf2e 100755 --- a/zone/gm_commands/sendzonespawns.cpp +++ b/zone/gm_commands/sendzonespawns.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_sendzonespawns(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/sensetrap.cpp b/zone/gm_commands/sensetrap.cpp index 89b6e68299..8756fcc4ac 100755 --- a/zone/gm_commands/sensetrap.cpp +++ b/zone/gm_commands/sensetrap.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_sensetrap(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/serverrules.cpp b/zone/gm_commands/serverrules.cpp index aaf9768de5..94d51f85fb 100755 --- a/zone/gm_commands/serverrules.cpp +++ b/zone/gm_commands/serverrules.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_serverrules(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set.cpp b/zone/gm_commands/set.cpp index 439881fee7..c29787ed10 100644 --- a/zone/gm_commands/set.cpp +++ b/zone/gm_commands/set.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetAAEXP(Client *c, const Seperator *sep); diff --git a/zone/gm_commands/set/set_aa_exp.cpp b/zone/gm_commands/set/set_aa_exp.cpp index 2f3d177047..3522898fb8 100644 --- a/zone/gm_commands/set/set_aa_exp.cpp +++ b/zone/gm_commands/set/set_aa_exp.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/groups.h" #include "zone/raids.h" diff --git a/zone/gm_commands/set/set_aa_points.cpp b/zone/gm_commands/set/set_aa_points.cpp index 8239441098..7b978f9bcd 100644 --- a/zone/gm_commands/set/set_aa_points.cpp +++ b/zone/gm_commands/set/set_aa_points.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/groups.h" #include "zone/raids.h" diff --git a/zone/gm_commands/set/set_adventure_points.cpp b/zone/gm_commands/set/set_adventure_points.cpp index c904ea6ac9..fa5ce736fa 100644 --- a/zone/gm_commands/set/set_adventure_points.cpp +++ b/zone/gm_commands/set/set_adventure_points.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/data_verification.h" #include "zone/client.h" diff --git a/zone/gm_commands/set/set_alternate_currency.cpp b/zone/gm_commands/set/set_alternate_currency.cpp index 47d7e81d45..6eed999145 100644 --- a/zone/gm_commands/set/set_alternate_currency.cpp +++ b/zone/gm_commands/set/set_alternate_currency.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetAlternateCurrency(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_animation.cpp b/zone/gm_commands/set/set_animation.cpp index 8cc7b83035..12a9fe09b3 100644 --- a/zone/gm_commands/set/set_animation.cpp +++ b/zone/gm_commands/set/set_animation.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetAnimation(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_anon.cpp b/zone/gm_commands/set/set_anon.cpp index 7a90c0019f..91dfc190cd 100644 --- a/zone/gm_commands/set/set_anon.cpp +++ b/zone/gm_commands/set/set_anon.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/character_data_repository.h" #include "zone/client.h" diff --git a/zone/gm_commands/set/set_auto_login.cpp b/zone/gm_commands/set/set_auto_login.cpp index 92f4b22839..93b89328c2 100644 --- a/zone/gm_commands/set/set_auto_login.cpp +++ b/zone/gm_commands/set/set_auto_login.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/account_repository.h" #include "zone/client.h" #include "zone/groups.h" diff --git a/zone/gm_commands/set/set_bind_point.cpp b/zone/gm_commands/set/set_bind_point.cpp index 9741c15e73..d8088e1d37 100644 --- a/zone/gm_commands/set/set_bind_point.cpp +++ b/zone/gm_commands/set/set_bind_point.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetBindPoint(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_checksum.cpp b/zone/gm_commands/set/set_checksum.cpp index f19c16294a..4100a3c0d6 100644 --- a/zone/gm_commands/set/set_checksum.cpp +++ b/zone/gm_commands/set/set_checksum.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/account_repository.h" #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/set/set_class_permanent.cpp b/zone/gm_commands/set/set_class_permanent.cpp index 26f8fcd061..6277f96e3c 100644 --- a/zone/gm_commands/set/set_class_permanent.cpp +++ b/zone/gm_commands/set/set_class_permanent.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetClassPermanent(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_crystals.cpp b/zone/gm_commands/set/set_crystals.cpp index ee6eebd92b..601f76d695 100644 --- a/zone/gm_commands/set/set_crystals.cpp +++ b/zone/gm_commands/set/set_crystals.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetCrystals(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_date.cpp b/zone/gm_commands/set/set_date.cpp index cc10cfeac5..c3ca98fa6e 100644 --- a/zone/gm_commands/set/set_date.cpp +++ b/zone/gm_commands/set/set_date.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetDate(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_endurance.cpp b/zone/gm_commands/set/set_endurance.cpp index 92e9877227..4ef12ecbbd 100644 --- a/zone/gm_commands/set/set_endurance.cpp +++ b/zone/gm_commands/set/set_endurance.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetEndurance(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_endurance_full.cpp b/zone/gm_commands/set/set_endurance_full.cpp index c0571c59ab..2613016dd0 100644 --- a/zone/gm_commands/set/set_endurance_full.cpp +++ b/zone/gm_commands/set/set_endurance_full.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetEnduranceFull(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_exp.cpp b/zone/gm_commands/set/set_exp.cpp index c661bd06ff..1579ca9f8a 100644 --- a/zone/gm_commands/set/set_exp.cpp +++ b/zone/gm_commands/set/set_exp.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetEXP(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_flymode.cpp b/zone/gm_commands/set/set_flymode.cpp index 63cf5f8f6c..e6f961fda5 100644 --- a/zone/gm_commands/set/set_flymode.cpp +++ b/zone/gm_commands/set/set_flymode.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/data_verification.h" #include "zone/client.h" diff --git a/zone/gm_commands/set/set_frozen.cpp b/zone/gm_commands/set/set_frozen.cpp index 737c257cee..5e8856c063 100644 --- a/zone/gm_commands/set/set_frozen.cpp +++ b/zone/gm_commands/set/set_frozen.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetFrozen(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_gender.cpp b/zone/gm_commands/set/set_gender.cpp index 549aefa156..82b4124e52 100644 --- a/zone/gm_commands/set/set_gender.cpp +++ b/zone/gm_commands/set/set_gender.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetGender(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_gender_permanent.cpp b/zone/gm_commands/set/set_gender_permanent.cpp index 9fa70fc7f0..f7db816997 100644 --- a/zone/gm_commands/set/set_gender_permanent.cpp +++ b/zone/gm_commands/set/set_gender_permanent.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetGenderPermanent(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_gm.cpp b/zone/gm_commands/set/set_gm.cpp index 9840988238..0bbceed229 100644 --- a/zone/gm_commands/set/set_gm.cpp +++ b/zone/gm_commands/set/set_gm.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetGM(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_gm_speed.cpp b/zone/gm_commands/set/set_gm_speed.cpp index f6c4c2d5a6..2a02da54ef 100644 --- a/zone/gm_commands/set/set_gm_speed.cpp +++ b/zone/gm_commands/set/set_gm_speed.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetGMSpeed(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_gm_status.cpp b/zone/gm_commands/set/set_gm_status.cpp index 42684c955d..97abea1a8f 100644 --- a/zone/gm_commands/set/set_gm_status.cpp +++ b/zone/gm_commands/set/set_gm_status.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/set/set_god_mode.cpp b/zone/gm_commands/set/set_god_mode.cpp index 377a0fec1c..ff4d6767ea 100644 --- a/zone/gm_commands/set/set_god_mode.cpp +++ b/zone/gm_commands/set/set_god_mode.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/account_repository.h" #include "zone/client.h" diff --git a/zone/gm_commands/set/set_haste.cpp b/zone/gm_commands/set/set_haste.cpp index a295b6434f..f9ba9cc7b4 100644 --- a/zone/gm_commands/set/set_haste.cpp +++ b/zone/gm_commands/set/set_haste.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot.h" #include "zone/client.h" diff --git a/zone/gm_commands/set/set_hero_model.cpp b/zone/gm_commands/set/set_hero_model.cpp index 485ec31f12..a4bb60d754 100644 --- a/zone/gm_commands/set/set_hero_model.cpp +++ b/zone/gm_commands/set/set_hero_model.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetHeroModel(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_hide_me.cpp b/zone/gm_commands/set/set_hide_me.cpp index a0063e4889..b34a322a51 100644 --- a/zone/gm_commands/set/set_hide_me.cpp +++ b/zone/gm_commands/set/set_hide_me.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetHideMe(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_hp.cpp b/zone/gm_commands/set/set_hp.cpp index cd71c0e346..3846de8987 100644 --- a/zone/gm_commands/set/set_hp.cpp +++ b/zone/gm_commands/set/set_hp.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetHP(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_hp_full.cpp b/zone/gm_commands/set/set_hp_full.cpp index 22a7936d81..13fa7598d3 100644 --- a/zone/gm_commands/set/set_hp_full.cpp +++ b/zone/gm_commands/set/set_hp_full.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetHPFull(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_invulnerable.cpp b/zone/gm_commands/set/set_invulnerable.cpp index 59f66d10b3..2756000292 100644 --- a/zone/gm_commands/set/set_invulnerable.cpp +++ b/zone/gm_commands/set/set_invulnerable.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetInvulnerable(Client *c, const Seperator *sep) { diff --git a/zone/gm_commands/set/set_language.cpp b/zone/gm_commands/set/set_language.cpp index 2593c21aed..aa6cfc35f4 100644 --- a/zone/gm_commands/set/set_language.cpp +++ b/zone/gm_commands/set/set_language.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/data_verification.h" #include "zone/client.h" diff --git a/zone/gm_commands/set/set_last_name.cpp b/zone/gm_commands/set/set_last_name.cpp index 981b3e11f1..04bc75316c 100644 --- a/zone/gm_commands/set/set_last_name.cpp +++ b/zone/gm_commands/set/set_last_name.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetLastName(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_level.cpp b/zone/gm_commands/set/set_level.cpp index dd0153f695..7088608375 100644 --- a/zone/gm_commands/set/set_level.cpp +++ b/zone/gm_commands/set/set_level.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot.h" #include "zone/client.h" diff --git a/zone/gm_commands/set/set_loginserver_info.cpp b/zone/gm_commands/set/set_loginserver_info.cpp index 020ac3fad7..c081381ed6 100644 --- a/zone/gm_commands/set/set_loginserver_info.cpp +++ b/zone/gm_commands/set/set_loginserver_info.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/set/set_mana.cpp b/zone/gm_commands/set/set_mana.cpp index 1813ec8751..8f9bbe28e5 100644 --- a/zone/gm_commands/set/set_mana.cpp +++ b/zone/gm_commands/set/set_mana.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetMana(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_mana_full.cpp b/zone/gm_commands/set/set_mana_full.cpp index 9bfd3718dd..367c6ce3ff 100644 --- a/zone/gm_commands/set/set_mana_full.cpp +++ b/zone/gm_commands/set/set_mana_full.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetManaFull(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_motd.cpp b/zone/gm_commands/set/set_motd.cpp index 11f572ea58..1e92fc113c 100644 --- a/zone/gm_commands/set/set_motd.cpp +++ b/zone/gm_commands/set/set_motd.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/set/set_name.cpp b/zone/gm_commands/set/set_name.cpp index bbf1e8ca10..fa9369cc37 100644 --- a/zone/gm_commands/set/set_name.cpp +++ b/zone/gm_commands/set/set_name.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetName(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_ooc_mute.cpp b/zone/gm_commands/set/set_ooc_mute.cpp index ecd9c07ce0..1164c27584 100644 --- a/zone/gm_commands/set/set_ooc_mute.cpp +++ b/zone/gm_commands/set/set_ooc_mute.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/set/set_password.cpp b/zone/gm_commands/set/set_password.cpp index 2974424f08..c7417fcf11 100644 --- a/zone/gm_commands/set/set_password.cpp +++ b/zone/gm_commands/set/set_password.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetPassword(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_pvp.cpp b/zone/gm_commands/set/set_pvp.cpp index 6a9d7092d1..593677ca68 100644 --- a/zone/gm_commands/set/set_pvp.cpp +++ b/zone/gm_commands/set/set_pvp.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetPVP(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_pvp_points.cpp b/zone/gm_commands/set/set_pvp_points.cpp index f8661e84b3..29073de6e6 100644 --- a/zone/gm_commands/set/set_pvp_points.cpp +++ b/zone/gm_commands/set/set_pvp_points.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetPVPPoints(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_race.cpp b/zone/gm_commands/set/set_race.cpp index 9d18a8ff91..ca110f8617 100644 --- a/zone/gm_commands/set/set_race.cpp +++ b/zone/gm_commands/set/set_race.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetRace(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_race_permanent.cpp b/zone/gm_commands/set/set_race_permanent.cpp index 917539e2c7..ea25a7bf55 100644 --- a/zone/gm_commands/set/set_race_permanent.cpp +++ b/zone/gm_commands/set/set_race_permanent.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetRacePermanent(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_server_locked.cpp b/zone/gm_commands/set/set_server_locked.cpp index b81805b708..ef13c909d8 100644 --- a/zone/gm_commands/set/set_server_locked.cpp +++ b/zone/gm_commands/set/set_server_locked.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/set/set_skill.cpp b/zone/gm_commands/set/set_skill.cpp index b470272f6a..daa0beffc1 100644 --- a/zone/gm_commands/set/set_skill.cpp +++ b/zone/gm_commands/set/set_skill.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetSkill(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_skill_all.cpp b/zone/gm_commands/set/set_skill_all.cpp index 7a7f128644..46d99110c1 100644 --- a/zone/gm_commands/set/set_skill_all.cpp +++ b/zone/gm_commands/set/set_skill_all.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetSkillAll(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_skill_all_max.cpp b/zone/gm_commands/set/set_skill_all_max.cpp index 19e7168fbb..6f2c410f08 100644 --- a/zone/gm_commands/set/set_skill_all_max.cpp +++ b/zone/gm_commands/set/set_skill_all_max.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetSkillAllMax(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_start_zone.cpp b/zone/gm_commands/set/set_start_zone.cpp index 843da575c5..cb0077294f 100644 --- a/zone/gm_commands/set/set_start_zone.cpp +++ b/zone/gm_commands/set/set_start_zone.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetStartZone(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_temporary_name.cpp b/zone/gm_commands/set/set_temporary_name.cpp index 11fcdec836..8f8b5cdee9 100644 --- a/zone/gm_commands/set/set_temporary_name.cpp +++ b/zone/gm_commands/set/set_temporary_name.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetTemporaryName(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_texture.cpp b/zone/gm_commands/set/set_texture.cpp index 279e522095..83ac4188c0 100644 --- a/zone/gm_commands/set/set_texture.cpp +++ b/zone/gm_commands/set/set_texture.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetTexture(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_time.cpp b/zone/gm_commands/set/set_time.cpp index e3ee56132d..066363f97c 100644 --- a/zone/gm_commands/set/set_time.cpp +++ b/zone/gm_commands/set/set_time.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetTime(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_time_zone.cpp b/zone/gm_commands/set/set_time_zone.cpp index 4a68bd7f4f..02fa1ddc23 100644 --- a/zone/gm_commands/set/set_time_zone.cpp +++ b/zone/gm_commands/set/set_time_zone.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetTimeZone(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_title.cpp b/zone/gm_commands/set/set_title.cpp index 45b3c35244..07008e451e 100644 --- a/zone/gm_commands/set/set_title.cpp +++ b/zone/gm_commands/set/set_title.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/titles.h" diff --git a/zone/gm_commands/set/set_title_suffix.cpp b/zone/gm_commands/set/set_title_suffix.cpp index cf14a4f7d3..e8f7a259d3 100644 --- a/zone/gm_commands/set/set_title_suffix.cpp +++ b/zone/gm_commands/set/set_title_suffix.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/titles.h" diff --git a/zone/gm_commands/set/set_weather.cpp b/zone/gm_commands/set/set_weather.cpp index 73969a65ef..531a382adb 100644 --- a/zone/gm_commands/set/set_weather.cpp +++ b/zone/gm_commands/set/set_weather.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void SetWeather(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/set/set_zone.cpp b/zone/gm_commands/set/set_zone.cpp index ecb9e3cc60..dd8804c3bb 100644 --- a/zone/gm_commands/set/set_zone.cpp +++ b/zone/gm_commands/set/set_zone.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/show.cpp b/zone/gm_commands/show.cpp index 027ee164cd..32227173f5 100755 --- a/zone/gm_commands/show.cpp +++ b/zone/gm_commands/show.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowAAs(Client* c, const Seperator* sep); diff --git a/zone/gm_commands/show/show_aa_points.cpp b/zone/gm_commands/show/show_aa_points.cpp index d199a740c7..dcaabe08e6 100644 --- a/zone/gm_commands/show/show_aa_points.cpp +++ b/zone/gm_commands/show/show_aa_points.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dialogue_window.h" diff --git a/zone/gm_commands/show/show_aas.cpp b/zone/gm_commands/show/show_aas.cpp index cb14fdd5a5..7148982f69 100644 --- a/zone/gm_commands/show/show_aas.cpp +++ b/zone/gm_commands/show/show_aas.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowAAs(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_aggro.cpp b/zone/gm_commands/show/show_aggro.cpp index 681200b3d4..17e47ab52d 100644 --- a/zone/gm_commands/show/show_aggro.cpp +++ b/zone/gm_commands/show/show_aggro.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowAggro(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_auto_login.cpp b/zone/gm_commands/show/show_auto_login.cpp index 2cbe814113..b30a964e4e 100644 --- a/zone/gm_commands/show/show_auto_login.cpp +++ b/zone/gm_commands/show/show_auto_login.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/account_repository.h" #include "zone/client.h" diff --git a/zone/gm_commands/show/show_buffs.cpp b/zone/gm_commands/show/show_buffs.cpp index 2b4f599936..320a916c6c 100644 --- a/zone/gm_commands/show/show_buffs.cpp +++ b/zone/gm_commands/show/show_buffs.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowBuffs(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_buried_corpse_count.cpp b/zone/gm_commands/show/show_buried_corpse_count.cpp index 99f6140c30..777cd6abab 100644 --- a/zone/gm_commands/show/show_buried_corpse_count.cpp +++ b/zone/gm_commands/show/show_buried_corpse_count.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/corpse.h" diff --git a/zone/gm_commands/show/show_client_version_summary.cpp b/zone/gm_commands/show/show_client_version_summary.cpp index b3c022c4aa..96df1f86cd 100644 --- a/zone/gm_commands/show/show_client_version_summary.cpp +++ b/zone/gm_commands/show/show_client_version_summary.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/show/show_content_flags.cpp b/zone/gm_commands/show/show_content_flags.cpp index 8861c8fcce..754b067f3e 100644 --- a/zone/gm_commands/show/show_content_flags.cpp +++ b/zone/gm_commands/show/show_content_flags.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dialogue_window.h" diff --git a/zone/gm_commands/show/show_currencies.cpp b/zone/gm_commands/show/show_currencies.cpp index 6d501a5a36..8c46812204 100644 --- a/zone/gm_commands/show/show_currencies.cpp +++ b/zone/gm_commands/show/show_currencies.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dialogue_window.h" diff --git a/zone/gm_commands/show/show_distance.cpp b/zone/gm_commands/show/show_distance.cpp index 5ae62477d5..9f5346e577 100644 --- a/zone/gm_commands/show/show_distance.cpp +++ b/zone/gm_commands/show/show_distance.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowDistance(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_emotes.cpp b/zone/gm_commands/show/show_emotes.cpp index 9f76da70e3..d867be491d 100644 --- a/zone/gm_commands/show/show_emotes.cpp +++ b/zone/gm_commands/show/show_emotes.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowEmotes(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_field_of_view.cpp b/zone/gm_commands/show/show_field_of_view.cpp index a93e56469b..5846508a38 100644 --- a/zone/gm_commands/show/show_field_of_view.cpp +++ b/zone/gm_commands/show/show_field_of_view.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowFieldOfView(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_flags.cpp b/zone/gm_commands/show/show_flags.cpp index 14a4592f14..42910cf59f 100644 --- a/zone/gm_commands/show/show_flags.cpp +++ b/zone/gm_commands/show/show_flags.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowFlags(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_group_info.cpp b/zone/gm_commands/show/show_group_info.cpp index 4b56c420a5..8e02adabdd 100644 --- a/zone/gm_commands/show/show_group_info.cpp +++ b/zone/gm_commands/show/show_group_info.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dialogue_window.h" #include "zone/groups.h" diff --git a/zone/gm_commands/show/show_hatelist.cpp b/zone/gm_commands/show/show_hatelist.cpp index bb50f9eb52..c9b94bfabb 100644 --- a/zone/gm_commands/show/show_hatelist.cpp +++ b/zone/gm_commands/show/show_hatelist.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowHateList(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_inventory.cpp b/zone/gm_commands/show/show_inventory.cpp index 4abfd6a689..9ae6116fd9 100644 --- a/zone/gm_commands/show/show_inventory.cpp +++ b/zone/gm_commands/show/show_inventory.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/object.h" diff --git a/zone/gm_commands/show/show_ip_lookup.cpp b/zone/gm_commands/show/show_ip_lookup.cpp index 74bd449cb4..4c8bf84bb8 100644 --- a/zone/gm_commands/show/show_ip_lookup.cpp +++ b/zone/gm_commands/show/show_ip_lookup.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/show/show_keyring.cpp b/zone/gm_commands/show/show_keyring.cpp index c970570471..8e79013b67 100644 --- a/zone/gm_commands/show/show_keyring.cpp +++ b/zone/gm_commands/show/show_keyring.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dialogue_window.h" diff --git a/zone/gm_commands/show/show_line_of_sight.cpp b/zone/gm_commands/show/show_line_of_sight.cpp index 07db29e735..8a50b6b41f 100644 --- a/zone/gm_commands/show/show_line_of_sight.cpp +++ b/zone/gm_commands/show/show_line_of_sight.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowLineOfSight(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_network.cpp b/zone/gm_commands/show/show_network.cpp index 292eab6ce1..8fac2ee792 100644 --- a/zone/gm_commands/show/show_network.cpp +++ b/zone/gm_commands/show/show_network.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dialogue_window.h" diff --git a/zone/gm_commands/show/show_network_stats.cpp b/zone/gm_commands/show/show_network_stats.cpp index 964185ef4d..e9bf0547ce 100644 --- a/zone/gm_commands/show/show_network_stats.cpp +++ b/zone/gm_commands/show/show_network_stats.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dialogue_window.h" diff --git a/zone/gm_commands/show/show_npc_global_loot.cpp b/zone/gm_commands/show/show_npc_global_loot.cpp index f0013c6f93..afb92e2e45 100644 --- a/zone/gm_commands/show/show_npc_global_loot.cpp +++ b/zone/gm_commands/show/show_npc_global_loot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowNPCGlobalLoot(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_npc_stats.cpp b/zone/gm_commands/show/show_npc_stats.cpp index e4dac7a213..5180266aa1 100644 --- a/zone/gm_commands/show/show_npc_stats.cpp +++ b/zone/gm_commands/show/show_npc_stats.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowNPCStats(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_npc_type.cpp b/zone/gm_commands/show/show_npc_type.cpp index 4f4af24296..ba2549d30b 100644 --- a/zone/gm_commands/show/show_npc_type.cpp +++ b/zone/gm_commands/show/show_npc_type.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowNPCType(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_peqzone_flags.cpp b/zone/gm_commands/show/show_peqzone_flags.cpp index dbc60b5e5d..eab032d6fe 100644 --- a/zone/gm_commands/show/show_peqzone_flags.cpp +++ b/zone/gm_commands/show/show_peqzone_flags.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowPEQZoneFlags(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_petition.cpp b/zone/gm_commands/show/show_petition.cpp index bfccf6a3fd..8c31e444e6 100644 --- a/zone/gm_commands/show/show_petition.cpp +++ b/zone/gm_commands/show/show_petition.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/petitions_repository.h" #include "zone/client.h" diff --git a/zone/gm_commands/show/show_petition_info.cpp b/zone/gm_commands/show/show_petition_info.cpp index 426ef5acae..08d78818a0 100644 --- a/zone/gm_commands/show/show_petition_info.cpp +++ b/zone/gm_commands/show/show_petition_info.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "common/repositories/petitions_repository.h" diff --git a/zone/gm_commands/show/show_proximity.cpp b/zone/gm_commands/show/show_proximity.cpp index 22fbf8e025..bfe4ce8d62 100644 --- a/zone/gm_commands/show/show_proximity.cpp +++ b/zone/gm_commands/show/show_proximity.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowProximity(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_quest_errors.cpp b/zone/gm_commands/show/show_quest_errors.cpp index 59faf66056..bc1a7f13c2 100644 --- a/zone/gm_commands/show/show_quest_errors.cpp +++ b/zone/gm_commands/show/show_quest_errors.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/quest_parser_collection.h" diff --git a/zone/gm_commands/show/show_quest_globals.cpp b/zone/gm_commands/show/show_quest_globals.cpp index 263763ae89..11fa03d7c9 100644 --- a/zone/gm_commands/show/show_quest_globals.cpp +++ b/zone/gm_commands/show/show_quest_globals.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowQuestGlobals(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_recipe.cpp b/zone/gm_commands/show/show_recipe.cpp index e9357b1dce..c29b91b56b 100644 --- a/zone/gm_commands/show/show_recipe.cpp +++ b/zone/gm_commands/show/show_recipe.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/tradeskill_recipe_entries_repository.h" #include "common/repositories/tradeskill_recipe_repository.h" #include "zone/client.h" diff --git a/zone/gm_commands/show/show_server_info.cpp b/zone/gm_commands/show/show_server_info.cpp index 1b23b9d24d..06f9605e7e 100644 --- a/zone/gm_commands/show/show_server_info.cpp +++ b/zone/gm_commands/show/show_server_info.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/serverinfo.h" #include "zone/client.h" #include "zone/dialogue_window.h" diff --git a/zone/gm_commands/show/show_skills.cpp b/zone/gm_commands/show/show_skills.cpp index 99d335631d..c0a9e8abbc 100644 --- a/zone/gm_commands/show/show_skills.cpp +++ b/zone/gm_commands/show/show_skills.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dialogue_window.h" diff --git a/zone/gm_commands/show/show_spawn_status.cpp b/zone/gm_commands/show/show_spawn_status.cpp index 46c9c2b335..18352febbc 100644 --- a/zone/gm_commands/show/show_spawn_status.cpp +++ b/zone/gm_commands/show/show_spawn_status.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowSpawnStatus(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_special_abilities.cpp b/zone/gm_commands/show/show_special_abilities.cpp index f5713eb1b7..b04ca392af 100644 --- a/zone/gm_commands/show/show_special_abilities.cpp +++ b/zone/gm_commands/show/show_special_abilities.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowSpecialAbilities(Client* c, const Seperator* sep) diff --git a/zone/gm_commands/show/show_spells.cpp b/zone/gm_commands/show/show_spells.cpp index 48cf0f0fe8..5532ed8f0a 100644 --- a/zone/gm_commands/show/show_spells.cpp +++ b/zone/gm_commands/show/show_spells.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowSpells(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_spells_list.cpp b/zone/gm_commands/show/show_spells_list.cpp index 8fa107f0f3..c6e785590a 100644 --- a/zone/gm_commands/show/show_spells_list.cpp +++ b/zone/gm_commands/show/show_spells_list.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowSpellsList(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_stats.cpp b/zone/gm_commands/show/show_stats.cpp index f75ac9ed29..bc94c96db8 100644 --- a/zone/gm_commands/show/show_stats.cpp +++ b/zone/gm_commands/show/show_stats.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowStats(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_timers.cpp b/zone/gm_commands/show/show_timers.cpp index 4b8ad870be..55ca84442d 100644 --- a/zone/gm_commands/show/show_timers.cpp +++ b/zone/gm_commands/show/show_timers.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dialogue_window.h" diff --git a/zone/gm_commands/show/show_traps.cpp b/zone/gm_commands/show/show_traps.cpp index e3e6740052..387ea1fd8c 100644 --- a/zone/gm_commands/show/show_traps.cpp +++ b/zone/gm_commands/show/show_traps.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowTraps(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_uptime.cpp b/zone/gm_commands/show/show_uptime.cpp index 20eca70945..2fddcc9ca9 100644 --- a/zone/gm_commands/show/show_uptime.cpp +++ b/zone/gm_commands/show/show_uptime.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/show/show_variable.cpp b/zone/gm_commands/show/show_variable.cpp index 0a83f68a6b..000f745db2 100644 --- a/zone/gm_commands/show/show_variable.cpp +++ b/zone/gm_commands/show/show_variable.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowVariable(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_version.cpp b/zone/gm_commands/show/show_version.cpp index 415c240f95..5acfcd7e45 100644 --- a/zone/gm_commands/show/show_version.cpp +++ b/zone/gm_commands/show/show_version.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dialogue_window.h" diff --git a/zone/gm_commands/show/show_waypoints.cpp b/zone/gm_commands/show/show_waypoints.cpp index afc4c80552..566beb29dc 100644 --- a/zone/gm_commands/show/show_waypoints.cpp +++ b/zone/gm_commands/show/show_waypoints.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowWaypoints(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_who.cpp b/zone/gm_commands/show/show_who.cpp index d3d3ed152b..1bb7fb5e71 100644 --- a/zone/gm_commands/show/show_who.cpp +++ b/zone/gm_commands/show/show_who.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowWho(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_xtargets.cpp b/zone/gm_commands/show/show_xtargets.cpp index d1b626f09a..f4b5b352fe 100644 --- a/zone/gm_commands/show/show_xtargets.cpp +++ b/zone/gm_commands/show/show_xtargets.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/data_verification.h" #include "zone/client.h" diff --git a/zone/gm_commands/show/show_zone_data.cpp b/zone/gm_commands/show/show_zone_data.cpp index d9875437d9..98b271b87a 100644 --- a/zone/gm_commands/show/show_zone_data.cpp +++ b/zone/gm_commands/show/show_zone_data.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/dialogue_window.h" diff --git a/zone/gm_commands/show/show_zone_global_loot.cpp b/zone/gm_commands/show/show_zone_global_loot.cpp index 838aafb9f6..5ca7e1673d 100644 --- a/zone/gm_commands/show/show_zone_global_loot.cpp +++ b/zone/gm_commands/show/show_zone_global_loot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowZoneGlobalLoot(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_zone_loot.cpp b/zone/gm_commands/show/show_zone_loot.cpp index 22317f9b3f..1f52afc6a0 100644 --- a/zone/gm_commands/show/show_zone_loot.cpp +++ b/zone/gm_commands/show/show_zone_loot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowZoneLoot(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_zone_points.cpp b/zone/gm_commands/show/show_zone_points.cpp index 778771b5e2..5ea922e26c 100644 --- a/zone/gm_commands/show/show_zone_points.cpp +++ b/zone/gm_commands/show/show_zone_points.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void ShowZonePoints(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/show/show_zone_status.cpp b/zone/gm_commands/show/show_zone_status.cpp index f517956fc8..42010266dc 100644 --- a/zone/gm_commands/show/show_zone_status.cpp +++ b/zone/gm_commands/show/show_zone_status.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/show/show_zone_variables.cpp b/zone/gm_commands/show/show_zone_variables.cpp index b914fd8c65..fa7fa5e860 100644 --- a/zone/gm_commands/show/show_zone_variables.cpp +++ b/zone/gm_commands/show/show_zone_variables.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/zone.h" diff --git a/zone/gm_commands/shutdown.cpp b/zone/gm_commands/shutdown.cpp index d7fe561ce4..edd73bbff0 100755 --- a/zone/gm_commands/shutdown.cpp +++ b/zone/gm_commands/shutdown.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void CatchSignal(int sig_num); diff --git a/zone/gm_commands/spawn.cpp b/zone/gm_commands/spawn.cpp index 66783c50f2..29bc9eab56 100755 --- a/zone/gm_commands/spawn.cpp +++ b/zone/gm_commands/spawn.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_spawn(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/spawneditmass.cpp b/zone/gm_commands/spawneditmass.cpp index 2e7028c49f..13b992dfd3 100644 --- a/zone/gm_commands/spawneditmass.cpp +++ b/zone/gm_commands/spawneditmass.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_spawneditmass(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/spawnfix.cpp b/zone/gm_commands/spawnfix.cpp index cce0c882e5..a74f8ba8c0 100755 --- a/zone/gm_commands/spawnfix.cpp +++ b/zone/gm_commands/spawnfix.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_spawnfix(Client* c, const Seperator* sep) diff --git a/zone/gm_commands/stun.cpp b/zone/gm_commands/stun.cpp index 62ca26c52f..ca31f03f64 100755 --- a/zone/gm_commands/stun.cpp +++ b/zone/gm_commands/stun.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_stun(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/summon.cpp b/zone/gm_commands/summon.cpp index 501f06345f..ae71b63a30 100755 --- a/zone/gm_commands/summon.cpp +++ b/zone/gm_commands/summon.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/summonburiedplayercorpse.cpp b/zone/gm_commands/summonburiedplayercorpse.cpp index 3b6c859ddf..cd43d5fe7f 100755 --- a/zone/gm_commands/summonburiedplayercorpse.cpp +++ b/zone/gm_commands/summonburiedplayercorpse.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/corpse.h" diff --git a/zone/gm_commands/summonitem.cpp b/zone/gm_commands/summonitem.cpp index 057c4b0f72..355a1e392e 100755 --- a/zone/gm_commands/summonitem.cpp +++ b/zone/gm_commands/summonitem.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_summonitem(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/suspend.cpp b/zone/gm_commands/suspend.cpp index fc9e67e2ea..250cb21db1 100755 --- a/zone/gm_commands/suspend.cpp +++ b/zone/gm_commands/suspend.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/account_repository.h" #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/suspendmulti.cpp b/zone/gm_commands/suspendmulti.cpp index 4ebfa8a4f8..40e91b9b3d 100755 --- a/zone/gm_commands/suspendmulti.cpp +++ b/zone/gm_commands/suspendmulti.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/account_repository.h" #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/takeplatinum.cpp b/zone/gm_commands/takeplatinum.cpp index fe9af3c7be..7a71a497c4 100644 --- a/zone/gm_commands/takeplatinum.cpp +++ b/zone/gm_commands/takeplatinum.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_takeplatinum(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/task.cpp b/zone/gm_commands/task.cpp index 5917265848..1977ced5d7 100755 --- a/zone/gm_commands/task.cpp +++ b/zone/gm_commands/task.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/repositories/completed_tasks_repository.h" #include "common/shared_tasks.h" #include "zone/client.h" diff --git a/zone/gm_commands/traindisc.cpp b/zone/gm_commands/traindisc.cpp index 4243b8bc4e..d7d6065cd3 100755 --- a/zone/gm_commands/traindisc.cpp +++ b/zone/gm_commands/traindisc.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_traindisc(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/tune.cpp b/zone/gm_commands/tune.cpp index 98f94117dc..51cfdbbf40 100755 --- a/zone/gm_commands/tune.cpp +++ b/zone/gm_commands/tune.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_tune(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/undye.cpp b/zone/gm_commands/undye.cpp index fdc6e39ab1..8334acc961 100755 --- a/zone/gm_commands/undye.cpp +++ b/zone/gm_commands/undye.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_undye(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/unmemspell.cpp b/zone/gm_commands/unmemspell.cpp index b6985bd668..0dd6750df4 100644 --- a/zone/gm_commands/unmemspell.cpp +++ b/zone/gm_commands/unmemspell.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_unmemspell(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/unmemspells.cpp b/zone/gm_commands/unmemspells.cpp index 94568c74b3..3725fea8e9 100644 --- a/zone/gm_commands/unmemspells.cpp +++ b/zone/gm_commands/unmemspells.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_unmemspells(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/unscribespell.cpp b/zone/gm_commands/unscribespell.cpp index 6f432dddb4..8e4bf2313c 100755 --- a/zone/gm_commands/unscribespell.cpp +++ b/zone/gm_commands/unscribespell.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/data_verification.h" #include "zone/client.h" diff --git a/zone/gm_commands/unscribespells.cpp b/zone/gm_commands/unscribespells.cpp index ed2572f9e2..1229ee80ba 100755 --- a/zone/gm_commands/unscribespells.cpp +++ b/zone/gm_commands/unscribespells.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_unscribespells(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/untraindisc.cpp b/zone/gm_commands/untraindisc.cpp index ac0237f72b..69a33f1e7c 100755 --- a/zone/gm_commands/untraindisc.cpp +++ b/zone/gm_commands/untraindisc.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/data_verification.h" #include "zone/client.h" diff --git a/zone/gm_commands/untraindiscs.cpp b/zone/gm_commands/untraindiscs.cpp index 85229c60a6..78c2cffd58 100755 --- a/zone/gm_commands/untraindiscs.cpp +++ b/zone/gm_commands/untraindiscs.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_untraindiscs(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/wc.cpp b/zone/gm_commands/wc.cpp index b23de72fda..83c4ba7e2d 100755 --- a/zone/gm_commands/wc.cpp +++ b/zone/gm_commands/wc.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/data_verification.h" #include "zone/client.h" diff --git a/zone/gm_commands/worldshutdown.cpp b/zone/gm_commands/worldshutdown.cpp index c17ce18489..ad3f42bd3d 100755 --- a/zone/gm_commands/worldshutdown.cpp +++ b/zone/gm_commands/worldshutdown.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/worldwide.cpp b/zone/gm_commands/worldwide.cpp index 8f2e7a1834..0a6c4ed4cb 100755 --- a/zone/gm_commands/worldwide.cpp +++ b/zone/gm_commands/worldwide.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_worldwide(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/wp.cpp b/zone/gm_commands/wp.cpp index 54f2bd8496..c718c1f183 100755 --- a/zone/gm_commands/wp.cpp +++ b/zone/gm_commands/wp.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_wp(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/wpadd.cpp b/zone/gm_commands/wpadd.cpp index b6b04d119a..38cab72d97 100755 --- a/zone/gm_commands/wpadd.cpp +++ b/zone/gm_commands/wpadd.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_wpadd(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/zone.cpp b/zone/gm_commands/zone.cpp index d13a9449f5..904b86f0c7 100644 --- a/zone/gm_commands/zone.cpp +++ b/zone/gm_commands/zone.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/bot.h" #include "zone/client.h" diff --git a/zone/gm_commands/zone_instance.cpp b/zone/gm_commands/zone_instance.cpp index 8efc7f9fcc..3da59672c4 100644 --- a/zone/gm_commands/zone_instance.cpp +++ b/zone/gm_commands/zone_instance.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_zone_instance(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/zone_shard.cpp b/zone/gm_commands/zone_shard.cpp index f5273dbfcf..70f2dabb2f 100644 --- a/zone/gm_commands/zone_shard.cpp +++ b/zone/gm_commands/zone_shard.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_zone_shard(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/zonebootup.cpp b/zone/gm_commands/zonebootup.cpp index 155cbc2be7..dca7b2d573 100755 --- a/zone/gm_commands/zonebootup.cpp +++ b/zone/gm_commands/zonebootup.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/zoneshutdown.cpp b/zone/gm_commands/zoneshutdown.cpp index 555bd54dee..d10ee1052b 100755 --- a/zone/gm_commands/zoneshutdown.cpp +++ b/zone/gm_commands/zoneshutdown.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" #include "zone/worldserver.h" diff --git a/zone/gm_commands/zonevariable.cpp b/zone/gm_commands/zonevariable.cpp index af4d2de6d8..2430f4e41d 100644 --- a/zone/gm_commands/zonevariable.cpp +++ b/zone/gm_commands/zonevariable.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_zonevariable(Client *c, const Seperator *sep) diff --git a/zone/gm_commands/zsave.cpp b/zone/gm_commands/zsave.cpp index a73394f455..40154dfdba 100755 --- a/zone/gm_commands/zsave.cpp +++ b/zone/gm_commands/zsave.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone/client.h" void command_zsave(Client *c, const Seperator *sep) diff --git a/zone/groups.cpp b/zone/groups.cpp index b0a297a559..e15ba4b858 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "groups.h" #include "common/eqemu_logsys.h" diff --git a/zone/groups.h b/zone/groups.h index b51223f252..3af6d68aa7 100644 --- a/zone/groups.h +++ b/zone/groups.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eq_packet_structs.h" diff --git a/zone/guild.cpp b/zone/guild.cpp index 8b1e1bbe5d..54775c62af 100644 --- a/zone/guild.cpp +++ b/zone/guild.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "client.h" #include "common/database.h" diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index d13d04c1a0..4b4e3cbc3a 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "guild_mgr.h" #include "common/emu_versions.h" diff --git a/zone/guild_mgr.h b/zone/guild_mgr.h index c552ce194c..c9dd8b5b3d 100644 --- a/zone/guild_mgr.h +++ b/zone/guild_mgr.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/guild_base.h" diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index d152d838ec..4b3a296be9 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2002 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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "hate_list.h" #include "common/data_verification.h" diff --git a/zone/hate_list.h b/zone/hate_list.h index 32eea7cb5c..ac8cf7a2a5 100644 --- a/zone/hate_list.h +++ b/zone/hate_list.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2002 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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/emu_constants.h" diff --git a/zone/heal_rotation.cpp b/zone/heal_rotation.cpp index fdb5bd7a80..bf0225c17b 100644 --- a/zone/heal_rotation.cpp +++ b/zone/heal_rotation.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "heal_rotation.h" #include "zone/bot.h" diff --git a/zone/heal_rotation.h b/zone/heal_rotation.h index 1773a042bc..9d49ef1da2 100644 --- a/zone/heal_rotation.h +++ b/zone/heal_rotation.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "zone/mob.h" diff --git a/zone/horse.cpp b/zone/horse.cpp index a59d7c83ba..275148d8ce 100644 --- a/zone/horse.cpp +++ b/zone/horse.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "horse.h" #include "common/eqemu_logsys.h" diff --git a/zone/horse.h b/zone/horse.h index b458b261eb..48867e7e5f 100644 --- a/zone/horse.h +++ b/zone/horse.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "zone/npc.h" diff --git a/zone/inventory.cpp b/zone/inventory.cpp index cb28aeb2c4..4c9de5e843 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "client.h" #include "common/eqemu_logsys.h" diff --git a/zone/loot.cpp b/zone/loot.cpp index 519bf97c75..4a9b43149a 100644 --- a/zone/loot.cpp +++ b/zone/loot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "npc.h" #include "common/data_verification.h" diff --git a/zone/lua_bit.h b/zone/lua_bit.h index 50023e6efe..10dfdb06cb 100644 --- a/zone/lua_bit.h +++ b/zone/lua_bit.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once int luaopen_bit(lua_State *L); diff --git a/zone/lua_bot.cpp b/zone/lua_bot.cpp index 221beb33bb..162c0e0044 100644 --- a/zone/lua_bot.cpp +++ b/zone/lua_bot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_bot.h" diff --git a/zone/lua_bot.h b/zone/lua_bot.h index fb678533b1..374835fc4d 100644 --- a/zone/lua_bot.h +++ b/zone/lua_bot.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_buff.cpp b/zone/lua_buff.cpp index 7dba2550c6..91dadf7c1a 100644 --- a/zone/lua_buff.cpp +++ b/zone/lua_buff.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_buff.h" diff --git a/zone/lua_buff.h b/zone/lua_buff.h index 03c9744d68..3b79b10781 100644 --- a/zone/lua_buff.h +++ b/zone/lua_buff.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 0d917f3823..9092c9678b 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_client.h" diff --git a/zone/lua_client.h b/zone/lua_client.h index 0fcb6dde6e..53955528dd 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_corpse.cpp b/zone/lua_corpse.cpp index 4997dd731b..2dad7c3f64 100644 --- a/zone/lua_corpse.cpp +++ b/zone/lua_corpse.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_corpse.h" diff --git a/zone/lua_corpse.h b/zone/lua_corpse.h index 66fee476a7..6a0507381f 100644 --- a/zone/lua_corpse.h +++ b/zone/lua_corpse.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_database.cpp b/zone/lua_database.cpp index 796e36a7f2..cca971e1e1 100644 --- a/zone/lua_database.cpp +++ b/zone/lua_database.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_database.h" diff --git a/zone/lua_database.h b/zone/lua_database.h index ccfa28b6c6..124d33783f 100644 --- a/zone/lua_database.h +++ b/zone/lua_database.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_door.cpp b/zone/lua_door.cpp index 71d4df2f0c..4fae1c8736 100644 --- a/zone/lua_door.cpp +++ b/zone/lua_door.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_door.h" diff --git a/zone/lua_door.h b/zone/lua_door.h index 51b7900f50..7ef81ad14f 100644 --- a/zone/lua_door.h +++ b/zone/lua_door.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_encounter.cpp b/zone/lua_encounter.cpp index fb06784369..831632d250 100644 --- a/zone/lua_encounter.cpp +++ b/zone/lua_encounter.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_encounter.h" diff --git a/zone/lua_encounter.h b/zone/lua_encounter.h index 07a8f65cb8..b64143df98 100644 --- a/zone/lua_encounter.h +++ b/zone/lua_encounter.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_entity.cpp b/zone/lua_entity.cpp index 660a04a1af..cfe5ad834f 100644 --- a/zone/lua_entity.cpp +++ b/zone/lua_entity.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_entity.h" diff --git a/zone/lua_entity.h b/zone/lua_entity.h index dbf60a1785..9b83dc6df2 100644 --- a/zone/lua_entity.h +++ b/zone/lua_entity.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_entity_list.cpp b/zone/lua_entity_list.cpp index ff6d8ca73c..c1d58d36f4 100644 --- a/zone/lua_entity_list.cpp +++ b/zone/lua_entity_list.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_entity_list.h" diff --git a/zone/lua_entity_list.h b/zone/lua_entity_list.h index f1d9c596e2..a690d0f234 100644 --- a/zone/lua_entity_list.h +++ b/zone/lua_entity_list.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_expedition.cpp b/zone/lua_expedition.cpp index bdb17e3bc4..038faf3199 100644 --- a/zone/lua_expedition.cpp +++ b/zone/lua_expedition.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_expedition.h" diff --git a/zone/lua_expedition.h b/zone/lua_expedition.h index 943144f4bc..3e3ab0a303 100644 --- a/zone/lua_expedition.h +++ b/zone/lua_expedition.h @@ -1,23 +1,20 @@ -/** - * 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index ff6b021236..7a9711cf1b 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_general.h" diff --git a/zone/lua_general.h b/zone/lua_general.h index db9b0f91ab..e4b48d2460 100644 --- a/zone/lua_general.h +++ b/zone/lua_general.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_group.cpp b/zone/lua_group.cpp index b380c2b76f..54a4b6a921 100644 --- a/zone/lua_group.cpp +++ b/zone/lua_group.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_group.h" diff --git a/zone/lua_group.h b/zone/lua_group.h index 45d4db982d..2d666a8384 100644 --- a/zone/lua_group.h +++ b/zone/lua_group.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_hate_list.cpp b/zone/lua_hate_list.cpp index b7e4745fbb..ca75fb044d 100644 --- a/zone/lua_hate_list.cpp +++ b/zone/lua_hate_list.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_hate_list.h" diff --git a/zone/lua_hate_list.h b/zone/lua_hate_list.h index 590ab016f4..c90b93112e 100644 --- a/zone/lua_hate_list.h +++ b/zone/lua_hate_list.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_inventory.cpp b/zone/lua_inventory.cpp index 99b1051f50..9c57a4ef39 100644 --- a/zone/lua_inventory.cpp +++ b/zone/lua_inventory.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_inventory.h" diff --git a/zone/lua_inventory.h b/zone/lua_inventory.h index 2bee12f9df..846ff0e85f 100644 --- a/zone/lua_inventory.h +++ b/zone/lua_inventory.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_item.cpp b/zone/lua_item.cpp index 776b075b80..745db02e50 100644 --- a/zone/lua_item.cpp +++ b/zone/lua_item.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_item.h" diff --git a/zone/lua_item.h b/zone/lua_item.h index a7390b09f7..ace0b58ec6 100644 --- a/zone/lua_item.h +++ b/zone/lua_item.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_iteminst.cpp b/zone/lua_iteminst.cpp index 4047db7f40..6e0f97c650 100644 --- a/zone/lua_iteminst.cpp +++ b/zone/lua_iteminst.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_iteminst.h" diff --git a/zone/lua_iteminst.h b/zone/lua_iteminst.h index a75c657b19..49a7e8b824 100644 --- a/zone/lua_iteminst.h +++ b/zone/lua_iteminst.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_merc.cpp b/zone/lua_merc.cpp index c8437b9c81..d0a7d6545f 100644 --- a/zone/lua_merc.cpp +++ b/zone/lua_merc.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_merc.h" diff --git a/zone/lua_merc.h b/zone/lua_merc.h index 9dbee8d997..eec9ca975f 100644 --- a/zone/lua_merc.h +++ b/zone/lua_merc.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 8e8108e7ee..500ce7525f 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_mob.h" diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 46b28cf8c2..e2a45be11c 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_mod.cpp b/zone/lua_mod.cpp index 3ed6a278e1..00cdd3426c 100644 --- a/zone/lua_mod.cpp +++ b/zone/lua_mod.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_mod.h" diff --git a/zone/lua_mod.h b/zone/lua_mod.h index b19543c6fc..baaeed3960 100644 --- a/zone/lua_mod.h +++ b/zone/lua_mod.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/bug_reports_repository.h" diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index d6432af284..e4f309a0e0 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_npc.h" diff --git a/zone/lua_npc.h b/zone/lua_npc.h index 7ac11cc368..83ead681cc 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_object.cpp b/zone/lua_object.cpp index e56551f52c..ef6d9af58d 100644 --- a/zone/lua_object.cpp +++ b/zone/lua_object.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_object.h" diff --git a/zone/lua_object.h b/zone/lua_object.h index 633a3026a9..63a62f232e 100644 --- a/zone/lua_object.h +++ b/zone/lua_object.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_packet.cpp b/zone/lua_packet.cpp index 9ea64d36c9..8f231363e9 100644 --- a/zone/lua_packet.cpp +++ b/zone/lua_packet.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_packet.h" diff --git a/zone/lua_packet.h b/zone/lua_packet.h index 2754652e52..b5b3753716 100644 --- a/zone/lua_packet.h +++ b/zone/lua_packet.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 9a445f5363..d45ea95067 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_parser.h" diff --git a/zone/lua_parser.h b/zone/lua_parser.h index bda8161d31..475f945af0 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index 42d8de0c0e..a768e18c1e 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_parser_events.h" diff --git a/zone/lua_parser_events.h b/zone/lua_parser_events.h index 5c718eb1c4..b436691fd9 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_ptr.h b/zone/lua_ptr.h index 52ca4c3cad..7dbf9100c4 100644 --- a/zone/lua_ptr.h +++ b/zone/lua_ptr.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_raid.cpp b/zone/lua_raid.cpp index 4c45d46dbc..60ea6ebb88 100644 --- a/zone/lua_raid.cpp +++ b/zone/lua_raid.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_raid.h" diff --git a/zone/lua_raid.h b/zone/lua_raid.h index 7d32d73899..9a5bd50b52 100644 --- a/zone/lua_raid.h +++ b/zone/lua_raid.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_spawn.cpp b/zone/lua_spawn.cpp index a0a805e97f..bfa45f814a 100644 --- a/zone/lua_spawn.cpp +++ b/zone/lua_spawn.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_spawn.h" diff --git a/zone/lua_spawn.h b/zone/lua_spawn.h index bd470ca78d..f5f259d5b3 100644 --- a/zone/lua_spawn.h +++ b/zone/lua_spawn.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_spell.cpp b/zone/lua_spell.cpp index 35cbb35f41..cafe36c834 100644 --- a/zone/lua_spell.cpp +++ b/zone/lua_spell.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_spell.h" diff --git a/zone/lua_spell.h b/zone/lua_spell.h index 9a91fc420a..e0c3eac36b 100644 --- a/zone/lua_spell.h +++ b/zone/lua_spell.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_stat_bonuses.cpp b/zone/lua_stat_bonuses.cpp index db7e844fa4..51dc45dcdb 100644 --- a/zone/lua_stat_bonuses.cpp +++ b/zone/lua_stat_bonuses.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_stat_bonuses.h" diff --git a/zone/lua_stat_bonuses.h b/zone/lua_stat_bonuses.h index 577c260ca4..eac7097926 100644 --- a/zone/lua_stat_bonuses.h +++ b/zone/lua_stat_bonuses.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/lua_zone.cpp b/zone/lua_zone.cpp index 58f2e59fa2..863858808b 100644 --- a/zone/lua_zone.cpp +++ b/zone/lua_zone.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #ifdef LUA_EQEMU #include "lua_zone.h" diff --git a/zone/lua_zone.h b/zone/lua_zone.h index e6aeb2ba9b..a81a940349 100644 --- a/zone/lua_zone.h +++ b/zone/lua_zone.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #ifdef LUA_EQEMU diff --git a/zone/main.cpp b/zone/main.cpp index e6be02f903..82a1c3cf46 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -1,23 +1,20 @@ -/** - * 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/crash.h" #include "common/database/database_update.h" #include "common/eq_packet_structs.h" diff --git a/zone/map.cpp b/zone/map.cpp index b91475fa4e..65d7f30d72 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/compression.h" #include "common/file.h" #include "common/memory/ksm.hpp" diff --git a/zone/map.h b/zone/map.h index d19b4ec7cf..ccaa51fc3f 100644 --- a/zone/map.h +++ b/zone/map.h @@ -1,24 +1,20 @@ -/* - EQEMu: Everquest Server Emulator +/* EQEmu: EQEmulator - Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 - + along with this program. If not, see . */ - #pragma once #include "zone/position.h" diff --git a/zone/masterentity.h b/zone/masterentity.h index 1e1981423b..ee5456405e 100644 --- a/zone/masterentity.h +++ b/zone/masterentity.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ //Trumpcard: EntityLists are composed of multiple list types. This is the //master that includes all types. When entity.h is required, many of these are as well. diff --git a/zone/merc.cpp b/zone/merc.cpp index 587f09fcf2..283132a2d0 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "merc.h" #include "common/skill_caps.h" diff --git a/zone/merc.h b/zone/merc.h index ed5f98fed2..fb27c9f875 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "zone/npc.h" diff --git a/zone/mob.cpp b/zone/mob.cpp index 9c60ff30ed..d55fa4ab78 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "mob.h" #include "common/data_bucket.h" diff --git a/zone/mob.h b/zone/mob.h index be9663f3ed..bd7d84a021 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1,22 +1,20 @@ +/* EQEmu: EQEmulator -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/data_bucket.h" diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 285db4b631..8237d7a474 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "mob.h" #include "common/data_verification.h" diff --git a/zone/mob_appearance.cpp b/zone/mob_appearance.cpp index 6e6feaa48d..40bc60131a 100644 --- a/zone/mob_appearance.cpp +++ b/zone/mob_appearance.cpp @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2018 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "mob.h" #include "common/data_verification.h" diff --git a/zone/mob_info.cpp b/zone/mob_info.cpp index 812f9ab8fe..fc8ad5e6be 100644 --- a/zone/mob_info.cpp +++ b/zone/mob_info.cpp @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2018 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "mob.h" #include "zone/client.h" diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index 214e68a566..e61f9e6f65 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "mob_movement_manager.h" #include "common/data_verification.h" diff --git a/zone/mob_movement_manager.h b/zone/mob_movement_manager.h index 4e41107583..31938b4294 100644 --- a/zone/mob_movement_manager.h +++ b/zone/mob_movement_manager.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/zone/npc.cpp b/zone/npc.cpp index 64b61d33bc..8708636392 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "npc.h" #include "common/bodytypes.h" diff --git a/zone/npc.h b/zone/npc.h index c4b37d90f1..cd352833bc 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/repositories/lootdrop_entries_repository.h" diff --git a/zone/npc_scale_manager.cpp b/zone/npc_scale_manager.cpp index b2c7d879cf..a978d87d14 100644 --- a/zone/npc_scale_manager.cpp +++ b/zone/npc_scale_manager.cpp @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2018 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 - * - */ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "npc_scale_manager.h" #include "common/repositories/npc_scale_global_base_repository.h" diff --git a/zone/npc_scale_manager.h b/zone/npc_scale_manager.h index 0c2472bf77..a10549dfef 100644 --- a/zone/npc_scale_manager.h +++ b/zone/npc_scale_manager.h @@ -1,23 +1,20 @@ -/** - * EQEmulator: Everquest Server Emulator - * Copyright (C) 2001-2018 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "zone/npc.h" diff --git a/zone/object.cpp b/zone/object.cpp index 8eca194dd9..307cbec7f2 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "object.h" #include "common/events/player_event_logs.h" diff --git a/zone/object.h b/zone/object.h index 2c6801554e..09c44afa4c 100644 --- a/zone/object.h +++ b/zone/object.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once // Object Class: diff --git a/zone/oriented_bounding_box.cpp b/zone/oriented_bounding_box.cpp index 2efab1c44d..163d377551 100644 --- a/zone/oriented_bounding_box.cpp +++ b/zone/oriented_bounding_box.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "oriented_bounding_box.h" diff --git a/zone/oriented_bounding_box.h b/zone/oriented_bounding_box.h index d6936ff624..5b3beec035 100644 --- a/zone/oriented_bounding_box.h +++ b/zone/oriented_bounding_box.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "glm/vec3.hpp" diff --git a/zone/parcels.cpp b/zone/parcels.cpp index 28e9b114af..e787568e4e 100644 --- a/zone/parcels.cpp +++ b/zone/parcels.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "client.h" #include "common/events/player_event_logs.h" diff --git a/zone/pathfinder_interface.cpp b/zone/pathfinder_interface.cpp index 9ffb8f07ce..3fd66e81de 100644 --- a/zone/pathfinder_interface.cpp +++ b/zone/pathfinder_interface.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "pathfinder_interface.h" #include "common/seperator.h" diff --git a/zone/pathfinder_interface.h b/zone/pathfinder_interface.h index 79b334f2e8..6d919f2640 100644 --- a/zone/pathfinder_interface.h +++ b/zone/pathfinder_interface.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "zone/map.h" diff --git a/zone/pathfinder_nav_mesh.cpp b/zone/pathfinder_nav_mesh.cpp index 71523021f5..aa38bb5de3 100644 --- a/zone/pathfinder_nav_mesh.cpp +++ b/zone/pathfinder_nav_mesh.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "pathfinder_nav_mesh.h" #include "common/compression.h" diff --git a/zone/pathfinder_nav_mesh.h b/zone/pathfinder_nav_mesh.h index 2f8687dc47..44f2f2280f 100644 --- a/zone/pathfinder_nav_mesh.h +++ b/zone/pathfinder_nav_mesh.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "pathfinder_interface.h" diff --git a/zone/pathfinder_null.cpp b/zone/pathfinder_null.cpp index 7ec274653b..e53104db22 100644 --- a/zone/pathfinder_null.cpp +++ b/zone/pathfinder_null.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "pathfinder_null.h" IPathfinder::IPath PathfinderNull::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, int flags) diff --git a/zone/pathfinder_null.h b/zone/pathfinder_null.h index 146dde2cc8..3e7784f6e7 100644 --- a/zone/pathfinder_null.h +++ b/zone/pathfinder_null.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "pathfinder_interface.h" diff --git a/zone/pathfinder_waypoint.cpp b/zone/pathfinder_waypoint.cpp index a13c3ac742..dfea2ac351 100644 --- a/zone/pathfinder_waypoint.cpp +++ b/zone/pathfinder_waypoint.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include #include #include diff --git a/zone/pathfinder_waypoint.h b/zone/pathfinder_waypoint.h index d5549c089d..e4d6e7ddc0 100644 --- a/zone/pathfinder_waypoint.h +++ b/zone/pathfinder_waypoint.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "pathfinder_interface.h" diff --git a/zone/pathing.cpp b/zone/pathing.cpp index 5d3fde1acb..a47767cf77 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "client.h" #include "common/event/task.h" diff --git a/zone/pch/pch.h b/zone/pch/pch.h index c8c509b310..c5de975ebd 100644 --- a/zone/pch/pch.h +++ b/zone/pch/pch.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "zone/merc.h" diff --git a/zone/perl_bot.cpp b/zone/perl_bot.cpp index 8c90aa604e..9b72d77d2d 100644 --- a/zone/perl_bot.cpp +++ b/zone/perl_bot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_buff.cpp b/zone/perl_buff.cpp index 62cb7ef71e..b3498c1199 100644 --- a/zone/perl_buff.cpp +++ b/zone/perl_buff.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index c41003e116..012d96d463 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_database.cpp b/zone/perl_database.cpp index 6b475a37c9..543f215865 100644 --- a/zone/perl_database.cpp +++ b/zone/perl_database.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_database.h b/zone/perl_database.h index 11a52c83b3..3e6d828455 100644 --- a/zone/perl_database.h +++ b/zone/perl_database.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/mysql_stmt.h" diff --git a/zone/perl_doors.cpp b/zone/perl_doors.cpp index 64b692aa1d..1569442537 100644 --- a/zone/perl_doors.cpp +++ b/zone/perl_doors.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_entity.cpp b/zone/perl_entity.cpp index 767af3623e..908b6f0828 100644 --- a/zone/perl_entity.cpp +++ b/zone/perl_entity.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_expedition.cpp b/zone/perl_expedition.cpp index a1a4081bcd..ca9cfd9d47 100644 --- a/zone/perl_expedition.cpp +++ b/zone/perl_expedition.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_groups.cpp b/zone/perl_groups.cpp index 23247307d4..cca4c4aea8 100644 --- a/zone/perl_groups.cpp +++ b/zone/perl_groups.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_hateentry.cpp b/zone/perl_hateentry.cpp index 0fbd2ef2b4..b4bd4a82a5 100644 --- a/zone/perl_hateentry.cpp +++ b/zone/perl_hateentry.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_inventory.cpp b/zone/perl_inventory.cpp index f943ba6e9c..0e9f8d4137 100644 --- a/zone/perl_inventory.cpp +++ b/zone/perl_inventory.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_merc.cpp b/zone/perl_merc.cpp index 2e2ec358b2..92c887d23b 100644 --- a/zone/perl_merc.cpp +++ b/zone/perl_merc.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 5a207e1ad0..0fbfc6e10d 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index 018d9be8ff..6057cee1cb 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_object.cpp b/zone/perl_object.cpp index 7ecdbeffd0..419424c190 100644 --- a/zone/perl_object.cpp +++ b/zone/perl_object.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_perlpacket.cpp b/zone/perl_perlpacket.cpp index 4666fd5f91..fc332dfe4b 100644 --- a/zone/perl_perlpacket.cpp +++ b/zone/perl_perlpacket.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_player_corpse.cpp b/zone/perl_player_corpse.cpp index 8ff9e97f19..0c349a5585 100644 --- a/zone/perl_player_corpse.cpp +++ b/zone/perl_player_corpse.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_questitem.cpp b/zone/perl_questitem.cpp index d3cb071b0c..800e1a0e7f 100644 --- a/zone/perl_questitem.cpp +++ b/zone/perl_questitem.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_questitem_data.cpp b/zone/perl_questitem_data.cpp index 81d710a01d..18376b9588 100644 --- a/zone/perl_questitem_data.cpp +++ b/zone/perl_questitem_data.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #include "client.h" diff --git a/zone/perl_raids.cpp b/zone/perl_raids.cpp index 2cfa0802de..ce13d31a2f 100644 --- a/zone/perl_raids.cpp +++ b/zone/perl_raids.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_spawn.cpp b/zone/perl_spawn.cpp index d0b5120e28..07fbabdab8 100644 --- a/zone/perl_spawn.cpp +++ b/zone/perl_spawn.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_spell.cpp b/zone/perl_spell.cpp index 6d82b5a64a..8862ebc841 100644 --- a/zone/perl_spell.cpp +++ b/zone/perl_spell.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_stat_bonuses.cpp b/zone/perl_stat_bonuses.cpp index 27e61fd930..d082035236 100644 --- a/zone/perl_stat_bonuses.cpp +++ b/zone/perl_stat_bonuses.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perl_zone.cpp b/zone/perl_zone.cpp index d570ee87bb..0175554a0f 100644 --- a/zone/perl_zone.cpp +++ b/zone/perl_zone.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "common/features.h" #ifdef EMBPERL_XS_CLASSES diff --git a/zone/perlpacket.cpp b/zone/perlpacket.cpp index 48298e7c24..77cf945abd 100644 --- a/zone/perlpacket.cpp +++ b/zone/perlpacket.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "perlpacket.h" #include "common/misc_functions.h" diff --git a/zone/perlpacket.h b/zone/perlpacket.h index d42b802dfd..9cd2c61a2b 100644 --- a/zone/perlpacket.h +++ b/zone/perlpacket.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/emu_opcodes.h" diff --git a/zone/petitions.cpp b/zone/petitions.cpp index 781c50e459..cdb9468759 100644 --- a/zone/petitions.cpp +++ b/zone/petitions.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "petitions.h" #include "common/eq_packet_structs.h" diff --git a/zone/petitions.h b/zone/petitions.h index 2ecee85fd6..82afa24ff0 100644 --- a/zone/petitions.h +++ b/zone/petitions.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/linked_list.h" diff --git a/zone/pets.cpp b/zone/pets.cpp index d4eec4dbe0..029e69b33a 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "pets.h" #include "common/repositories/character_pet_name_repository.h" diff --git a/zone/pets.h b/zone/pets.h index caa5023cd3..9c9d088b46 100644 --- a/zone/pets.h +++ b/zone/pets.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once class Mob; diff --git a/zone/position.cpp b/zone/position.cpp index e60e9f96f4..24f7850d37 100644 --- a/zone/position.cpp +++ b/zone/position.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "position.h" #include "common/data_verification.h" diff --git a/zone/position.h b/zone/position.h index b548bab893..0b6c667ad7 100644 --- a/zone/position.h +++ b/zone/position.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/zone/qglobals.cpp b/zone/qglobals.cpp index 4456a08bb4..c3a574a049 100644 --- a/zone/qglobals.cpp +++ b/zone/qglobals.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "qglobals.h" #include "common/strings.h" diff --git a/zone/qglobals.h b/zone/qglobals.h index 95c98da185..be5e8b3775 100644 --- a/zone/qglobals.h +++ b/zone/qglobals.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/zone/queryserv.cpp b/zone/queryserv.cpp index 3f0cd86869..6fc3390603 100644 --- a/zone/queryserv.cpp +++ b/zone/queryserv.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "queryserv.h" #include "common/events/player_event_logs.h" diff --git a/zone/queryserv.h b/zone/queryserv.h index 834365f323..957c00f30f 100644 --- a/zone/queryserv.h +++ b/zone/queryserv.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/eqemu_logsys.h" diff --git a/zone/quest_db.cpp b/zone/quest_db.cpp index 0efb9092ae..113d509581 100644 --- a/zone/quest_db.cpp +++ b/zone/quest_db.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "quest_db.h" #include "zone/zone_config.h" diff --git a/zone/quest_db.h b/zone/quest_db.h index c1d897cc47..3080c46b9f 100644 --- a/zone/quest_db.h +++ b/zone/quest_db.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/zone/quest_interface.h b/zone/quest_interface.h index 1e668b9a79..cab920b240 100644 --- a/zone/quest_interface.h +++ b/zone/quest_interface.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index f2b6a7fd5d..05680bb47b 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "quest_parser_collection.h" #include "common/features.h" diff --git a/zone/quest_parser_collection.h b/zone/quest_parser_collection.h index f93854ddd8..cd02ee9945 100644 --- a/zone/quest_parser_collection.h +++ b/zone/quest_parser_collection.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 4135b1e912..73990d562a 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/classes.h" #include "common/data_verification.h" #include "common/events/player_event_logs.h" diff --git a/zone/questmgr.h b/zone/questmgr.h index f7e3d4a856..35be7b9762 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator - 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. + Copyright (C) 2001-2026 EQEmu Development Team - 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. + 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; either version 3 of the License, or + (at your option) any later version. - 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 -*/ + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/timer.h" diff --git a/zone/raids.cpp b/zone/raids.cpp index 9fd5cd5d34..eb8acd73cb 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "common/events/player_event_logs.h" #include "common/raid.h" #include "common/repositories/character_expedition_lockouts_repository.h" diff --git a/zone/raids.h b/zone/raids.h index 46a5c6bc3e..bf30f7ae68 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/zone/raycast_mesh.cpp b/zone/raycast_mesh.cpp index 405285cbf6..64e10a5237 100644 --- a/zone/raycast_mesh.cpp +++ b/zone/raycast_mesh.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "raycast_mesh.h" #include "common/eqemu_logsys.h" diff --git a/zone/raycast_mesh.h b/zone/raycast_mesh.h index 14306df22e..c8d5dd0f34 100644 --- a/zone/raycast_mesh.h +++ b/zone/raycast_mesh.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once // This code snippet allows you to create an axis aligned bounding volume tree for a triangle mesh so that you can do diff --git a/zone/shared_task_zone_messaging.cpp b/zone/shared_task_zone_messaging.cpp index 6d4b772cb2..a579f53c3b 100644 --- a/zone/shared_task_zone_messaging.cpp +++ b/zone/shared_task_zone_messaging.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "shared_task_zone_messaging.h" #include "common/servertalk.h" diff --git a/zone/shared_task_zone_messaging.h b/zone/shared_task_zone_messaging.h index 86393bc018..76b1914661 100644 --- a/zone/shared_task_zone_messaging.h +++ b/zone/shared_task_zone_messaging.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once class ServerPacket; diff --git a/zone/sidecar_api/loot_simulator_controller.cpp b/zone/sidecar_api/loot_simulator_controller.cpp index 4975a97de2..f19b9a4757 100644 --- a/zone/sidecar_api/loot_simulator_controller.cpp +++ b/zone/sidecar_api/loot_simulator_controller.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "sidecar_api.h" #include "common/json/json.hpp" diff --git a/zone/sidecar_api/sidecar_api.cpp b/zone/sidecar_api/sidecar_api.cpp index f8a9f74e3c..a7fa06f6ec 100644 --- a/zone/sidecar_api/sidecar_api.cpp +++ b/zone/sidecar_api/sidecar_api.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "sidecar_api.h" #include "common/eqemu_logsys.h" diff --git a/zone/sidecar_api/sidecar_api.h b/zone/sidecar_api/sidecar_api.h index fbc6fd8b49..1a9b96e27c 100644 --- a/zone/sidecar_api/sidecar_api.h +++ b/zone/sidecar_api/sidecar_api.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index f10a41e84f..2de994acf6 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "spawn2.h" #include "common/repositories/criteria/content_filter_criteria.h" diff --git a/zone/spawn2.h b/zone/spawn2.h index f77565b5db..7baeba3e11 100644 --- a/zone/spawn2.h +++ b/zone/spawn2.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/timer.h" diff --git a/zone/spawngroup.cpp b/zone/spawngroup.cpp index bdce23a727..654892357a 100644 --- a/zone/spawngroup.cpp +++ b/zone/spawngroup.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "spawngroup.h" #include "common/repositories/criteria/content_filter_criteria.h" diff --git a/zone/spawngroup.h b/zone/spawngroup.h index 832c581382..0340f1cc8b 100644 --- a/zone/spawngroup.h +++ b/zone/spawngroup.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/types.h" diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 5f2de8c03e..6c367101c9 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 - */ - + along with this program. If not, see . +*/ #include "mob.h" #include "common/rulesys.h" diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 74e8246914..7b29ca2c57 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "mob.h" #include "common/bodytypes.h" diff --git a/zone/spells.cpp b/zone/spells.cpp index 4e89bbba93..d20597b5c7 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - /* General outline of spell casting process diff --git a/zone/string_ids.h b/zone/string_ids.h index 50fe61bfbe..40293af0e4 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once //These strings are loaded from eqstr_us.txt, but may vary between client versions. Maybe we could make this an enum that's dependent on the client version? diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp index b2bd100bec..a16f45b9a4 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "task_client_state.h" #include "common/events/player_event_logs.h" diff --git a/zone/task_client_state.h b/zone/task_client_state.h index e444619ebd..99287543ae 100644 --- a/zone/task_client_state.h +++ b/zone/task_client_state.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp index 8a7badbd4a..23b3082015 100644 --- a/zone/task_manager.cpp +++ b/zone/task_manager.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "task_manager.h" #include "common/misc_functions.h" diff --git a/zone/task_manager.h b/zone/task_manager.h index 83a4f95714..5d90710945 100644 --- a/zone/task_manager.h +++ b/zone/task_manager.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/character_tasks_repository.h" diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 145c5d430c..b7ebe6361a 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "tasks.h" #include "common/misc_functions.h" diff --git a/zone/tasks.h b/zone/tasks.h index 5d6e764da4..b3e4ee0fc8 100644 --- a/zone/tasks.h +++ b/zone/tasks.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/tasks.h" diff --git a/zone/titles.cpp b/zone/titles.cpp index ef1d771c88..2e89aace80 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "titles.h" #include "common/eq_packet_structs.h" diff --git a/zone/titles.h b/zone/titles.h index 4541810c08..214771f1e1 100644 --- a/zone/titles.h +++ b/zone/titles.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/titles_repository.h" diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 756c5fcc87..049bcf5904 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "client.h" #include "common/events/player_event_logs.h" diff --git a/zone/trading.cpp b/zone/trading.cpp index a0e9d711cf..4b79a83997 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "client.h" #include "common/bazaar.h" diff --git a/zone/trap.cpp b/zone/trap.cpp index fbab075400..e849402d1e 100644 --- a/zone/trap.cpp +++ b/zone/trap.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "trap.h" #include "common/repositories/criteria/content_filter_criteria.h" diff --git a/zone/trap.h b/zone/trap.h index 23f8fedd15..15950529f0 100644 --- a/zone/trap.h +++ b/zone/trap.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "zone/entity.h" diff --git a/zone/tribute.cpp b/zone/tribute.cpp index e783465ecb..da09bba5b9 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "client.h" #include "common/eq_packet_structs.h" diff --git a/zone/tune.cpp b/zone/tune.cpp index 0471d74df5..99f5b4aa38 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "mob.h" #include "common/data_verification.h" diff --git a/zone/water_map.cpp b/zone/water_map.cpp index 80fc2d58ee..bd32230eee 100644 --- a/zone/water_map.cpp +++ b/zone/water_map.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "water_map.h" #include "common/eqemu_logsys.h" diff --git a/zone/water_map.h b/zone/water_map.h index 1eec456a9f..d26060c611 100644 --- a/zone/water_map.h +++ b/zone/water_map.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/types.h" diff --git a/zone/water_map_v1.cpp b/zone/water_map_v1.cpp index 7d2479a3b2..b742ecee0d 100644 --- a/zone/water_map_v1.cpp +++ b/zone/water_map_v1.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "water_map_v1.h" WaterMapV1::WaterMapV1() { diff --git a/zone/water_map_v1.h b/zone/water_map_v1.h index cdce61ccfc..0a3fc32984 100644 --- a/zone/water_map_v1.h +++ b/zone/water_map_v1.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "zone/water_map.h" diff --git a/zone/water_map_v2.cpp b/zone/water_map_v2.cpp index aa023219cd..a403bec35c 100644 --- a/zone/water_map_v2.cpp +++ b/zone/water_map_v2.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "water_map_v2.h" WaterMapV2::WaterMapV2() { diff --git a/zone/water_map_v2.h b/zone/water_map_v2.h index 5da8acdb8f..c24d0736bf 100644 --- a/zone/water_map_v2.h +++ b/zone/water_map_v2.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "zone/oriented_bounding_box.h" diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 4745b6c8c4..65f5809044 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2004 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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "npc.h" #include "common/eqemu_logsys.h" diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index b73a55b6b4..a273af1867 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1,21 +1,20 @@ -/* 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 -*/ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "worldserver.h" #include "common/eq_packet_structs.h" diff --git a/zone/worldserver.h b/zone/worldserver.h index 7d59e6d850..39a52388cf 100644 --- a/zone/worldserver.h +++ b/zone/worldserver.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eq_packet_structs.h" diff --git a/zone/xtargetautohaters.cpp b/zone/xtargetautohaters.cpp index 5c49b08a38..471b56d868 100644 --- a/zone/xtargetautohaters.cpp +++ b/zone/xtargetautohaters.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "xtargetautohaters.h" #include "zone/client.h" diff --git a/zone/xtargetautohaters.h b/zone/xtargetautohaters.h index 761331fa9c..5cdbc92262 100644 --- a/zone/xtargetautohaters.h +++ b/zone/xtargetautohaters.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include diff --git a/zone/zone.cpp b/zone/zone.cpp index 34a635b3bb..e0c6c44bc9 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "zone.h" #include "common/data_verification.h" diff --git a/zone/zone.h b/zone/zone.h index ce6a731fd7..d1d8c188c3 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/discord/discord.h" diff --git a/zone/zone_base_data.cpp b/zone/zone_base_data.cpp index b9b2e37563..0d12489336 100644 --- a/zone/zone_base_data.cpp +++ b/zone/zone_base_data.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone.h" BaseDataRepository::BaseData Zone::GetBaseData(uint8 level, uint8 class_id) diff --git a/zone/zone_cli.cpp b/zone/zone_cli.cpp index 88c310b287..df029215d3 100644 --- a/zone/zone_cli.cpp +++ b/zone/zone_cli.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone_cli.h" #include "common/cli/eqemu_command_handler.h" diff --git a/zone/zone_cli.h b/zone/zone_cli.h index d9dcfdfe2a..8e19f04f6f 100644 --- a/zone/zone_cli.h +++ b/zone/zone_cli.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once diff --git a/zone/zone_config.cpp b/zone/zone_config.cpp index 21c396fd54..3e34edbe29 100644 --- a/zone/zone_config.cpp +++ b/zone/zone_config.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "zone_config.h" ZoneConfig *ZoneConfig::_zone_config = nullptr; \ No newline at end of file diff --git a/zone/zone_config.h b/zone/zone_config.h index b556c7b324..b9ad5c2e0e 100644 --- a/zone/zone_config.h +++ b/zone/zone_config.h @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #pragma once #include "common/eqemu_config.h" diff --git a/zone/zone_event_scheduler.cpp b/zone/zone_event_scheduler.cpp index d6f78f6d5b..c1f3f3bd74 100644 --- a/zone/zone_event_scheduler.cpp +++ b/zone/zone_event_scheduler.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone_event_scheduler.h" #include diff --git a/zone/zone_event_scheduler.h b/zone/zone_event_scheduler.h index bd996a8ec0..7eceb5473b 100644 --- a/zone/zone_event_scheduler.h +++ b/zone/zone_event_scheduler.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/content/world_content_service.h" diff --git a/zone/zone_loot.cpp b/zone/zone_loot.cpp index 076aeb291e..456f818948 100644 --- a/zone/zone_loot.cpp +++ b/zone/zone_loot.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone.h" #include "common/repositories/lootdrop_entries_repository.h" diff --git a/zone/zone_npc_factions.cpp b/zone/zone_npc_factions.cpp index b9b07562a1..93a849d249 100644 --- a/zone/zone_npc_factions.cpp +++ b/zone/zone_npc_factions.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone.h" #include "common/repositories/npc_faction_entries_repository.h" diff --git a/zone/zone_reload.cpp b/zone/zone_reload.cpp index 11adf7eafe..46d1f404a5 100644 --- a/zone/zone_reload.cpp +++ b/zone/zone_reload.cpp @@ -1,23 +1,20 @@ -/** - * 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone_reload.h" #include "zone/quest_parser_collection.h" diff --git a/zone/zone_reload.h b/zone/zone_reload.h index 0e721f16fd..32ab705e14 100644 --- a/zone/zone_reload.h +++ b/zone/zone_reload.h @@ -1,23 +1,20 @@ -/** - * 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 - * - */ +/* EQEmu: EQEmulator + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once class ZoneReload { diff --git a/zone/zone_save_state.cpp b/zone/zone_save_state.cpp index 4b1c4c4f23..717dce21e4 100644 --- a/zone/zone_save_state.cpp +++ b/zone/zone_save_state.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zone_save_state.h" #include "common/repositories/criteria/content_filter_criteria.h" diff --git a/zone/zone_save_state.h b/zone/zone_save_state.h index cec63750ca..517f962384 100644 --- a/zone/zone_save_state.h +++ b/zone/zone_save_state.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once #include "common/repositories/spawn2_disabled_repository.h" diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index a0d6f24bfe..703f012ad0 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #include "zonedb.h" #include "common/eqemu_logsys.h" diff --git a/zone/zonedb.h b/zone/zonedb.h index 5dee242fbe..c751a47370 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -1,3 +1,20 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ #pragma once diff --git a/zone/zonedump.h b/zone/zonedump.h index e811a61fad..022ccab594 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -1,19 +1,19 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ /* Below are the blob structures for zone state dumping to the database diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 46bd4849c6..c085bb62b3 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -1,21 +1,20 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team 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. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. 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. + but WITHOUT ANY WARRANTY; 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 + along with this program. If not, see . */ - #include "client.h" #include "common/eqemu_logsys.h" From 48d18aa62ad21bdb5d46266289a43b730f47173e Mon Sep 17 00:00:00 2001 From: Knightly Date: Tue, 31 Mar 2026 22:54:45 -1000 Subject: [PATCH 097/194] Update Readme for license changes --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b2ad64e4cc..bc709c681d 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,13 @@ Contributors Discord Docs -License +License Latest Release Release Date Github All Releases GitHub Issues or Pull Requests Docker Pulls -Official +Official

@@ -124,7 +124,7 @@ Every system, packet, opcode, and game mechanic has been reconstructed through c | **EQEmulator Docs** | [![Docs](https://img.shields.io/badge/docs-MkDocs%20Powered-blueviolet)](https://docs.eqemu.dev) | [docs.eqemu.dev](https://docs.eqemu.dev/) | | **Discord Community**| [![Discord](https://img.shields.io/discord/212663220849213441?label=Discord&logo=discord&color=7289DA)](https://discord.gg/QHsm7CD) | [Join Discord](https://discord.gg/QHsm7CD) | | **Latest Release** | [![Latest Release](https://img.shields.io/github/v/release/EQEmu/EQEmu)](https://github.com/EQEmu/EQEmu/releases)
[![Release Date](https://img.shields.io/github/release-date/EQEmu/EQEmu)](https://github.com/EQEmu/EQEmu/releases)
[![All Releases](https://img.shields.io/github/downloads/EQEmu/EQEmu/total.svg)](https://github.com/EQEmu/EQEmu/releases) | [View Releases](https://github.com/EQEmu/EQEmu/releases) | -| **License** | [![License](https://img.shields.io/github/license/EQEmu/EQEmu)](./LICENSE) | [View License](./LICENSE) | +| **License** | [![License](https://img.shields.io/github/license/EQEmu/EQEmu)](./LICENSE.md) | [View License](./LICENSE.md) | | **Build Status** | [![Build](https://github.com/EQEmu/EQEmu/actions/workflows/build.yaml/badge.svg)](https://github.com/EQEmu/EQEmu/actions/workflows/build.yaml) | [View Build Status](https://github.com/EQEmu/EQEmu/actions/workflows/build.yaml) | | **Docker Pulls** | [![Docker Pulls](https://img.shields.io/docker/pulls/akkadius/eqemu-server)](https://hub.docker.com/r/akkadius/eqemu-server) | [Docker Hub](https://hub.docker.com/r/akkadius/eqemu-server) | | **Contributions** | [![GitHub PRs](https://img.shields.io/github/issues-pr-closed/EQEmu/EQEmu)](https://github.com/EQEmu/EQEmu/pulls?q=is%3Apr+is%3Aclosed) | [Closed PRs & Issues](https://github.com/EQEmu/EQEmu/pulls?q=is%3Apr+is%3Aclosed) | From 435224631f5d7327d6dee8e0e55ae501b7e76d90 Mon Sep 17 00:00:00 2001 From: Knightly <55611098+Knightly1@users.noreply.github.com> Date: Sat, 4 Apr 2026 08:15:05 -1000 Subject: [PATCH 098/194] Lua: Add world_wide_add_ldon_win & events (#5054) --- zone/lua_general.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 7a9711cf1b..ea4d4c878e 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -6720,9 +6720,9 @@ luabind::scope lua_register_general() { luabind::def("world_wide_add_ldon_points", (void(*)(uint32,int))&lua_world_wide_add_ldon_points), luabind::def("world_wide_add_ldon_points", (void(*)(uint32,int,uint8))&lua_world_wide_add_ldon_points), luabind::def("world_wide_add_ldon_points", (void(*)(uint32,int,uint8,uint8))&lua_world_wide_add_ldon_points), - luabind::def("world_wide_add_ldon_loss", (void(*)(uint32))&lua_world_wide_add_ldon_win), - luabind::def("world_wide_add_ldon_loss", (void(*)(uint32,uint8))&lua_world_wide_add_ldon_win), - luabind::def("world_wide_add_ldon_loss", (void(*)(uint32,uint8,uint8))&lua_world_wide_add_ldon_win), + luabind::def("world_wide_add_ldon_win", (void(*)(uint32))&lua_world_wide_add_ldon_win), + luabind::def("world_wide_add_ldon_win", (void(*)(uint32,uint8))&lua_world_wide_add_ldon_win), + luabind::def("world_wide_add_ldon_win", (void(*)(uint32,uint8,uint8))&lua_world_wide_add_ldon_win), luabind::def("world_wide_assign_task", (void(*)(uint32))&lua_world_wide_assign_task), luabind::def("world_wide_assign_task", (void(*)(uint32,bool))&lua_world_wide_assign_task), luabind::def("world_wide_assign_task", (void(*)(uint32,bool,uint8))&lua_world_wide_assign_task), @@ -6882,7 +6882,9 @@ luabind::scope lua_register_events() { luabind::value("trade", static_cast(EVENT_TRADE)), luabind::value("death", static_cast(EVENT_DEATH)), luabind::value("spawn", static_cast(EVENT_SPAWN)), + luabind::value("attack", static_cast(EVENT_ATTACK)), luabind::value("combat", static_cast(EVENT_COMBAT)), + luabind::value("aggro", static_cast(EVENT_AGGRO)), luabind::value("slay", static_cast(EVENT_SLAY)), luabind::value("waypoint_arrive", static_cast(EVENT_WAYPOINT_ARRIVE)), luabind::value("waypoint_depart", static_cast(EVENT_WAYPOINT_DEPART)), From 491b1edd12bc48a82f4d7bd8ef5b9510861d159b Mon Sep 17 00:00:00 2001 From: brainiac Date: Sat, 4 Apr 2026 23:27:21 -0700 Subject: [PATCH 099/194] Warning fixes, general cleanup (#5053) --- .gitattributes | 1 + CMakeLists.txt | 6 +- common/CMakeLists.txt | 141 ++++++-------- common/StackWalker/StackWalker.cpp | 2 +- common/StackWalker/StackWalker.h | 2 +- common/base_packet.cpp | 38 ++-- common/base_packet.h | 36 ++-- common/cli/eqemu_command_handler.cpp | 9 +- common/cli/terminal_color.hpp | 2 +- common/condition.cpp | 146 -------------- common/condition.h | 51 ----- common/content/world_content_service.cpp | 4 +- common/crc32.cpp | 2 +- common/database.cpp | 4 +- common/database.h | 7 +- common/dbcore.cpp | 63 +++--- common/dbcore.h | 38 ++-- common/eq_packet.cpp | 31 +-- common/eq_packet.h | 78 +++++--- common/eq_stream_intf.h | 4 +- common/eqemu_logsys.cpp | 4 +- common/{mutex.h => event/event_loop.cpp} | 73 +++---- common/event/event_loop.h | 55 ++---- common/event/task_scheduler.cpp | 128 +++++++++++++ common/event/task_scheduler.h | 129 +++---------- common/event/timer.cpp | 90 +++++++++ common/event/timer.h | 78 ++------ common/events/player_event_logs.cpp | 4 +- common/guilds.h | 4 +- common/inventory_profile.cpp | 2 +- common/ip_util.cpp | 159 ++++----------- common/ip_util.h | 5 +- common/item_instance.cpp | 1 + common/loot.h | 3 +- common/memory/ksm.cpp | 192 +++++++++++++++++++ common/memory/ksm.h | 74 +++++++ common/memory/ksm.hpp | 234 ----------------------- common/mutex.cpp | 162 ---------------- common/mysql_stmt.cpp | 16 +- common/mysql_stmt.h | 11 +- common/net/dns.cpp | 131 +++++++++++++ common/net/dns.h | 58 +----- common/net/tcp_connection.h | 2 + common/net/websocket_server.h | 4 +- common/op_codes.h | 27 ++- common/opcodemgr.cpp | 49 ++--- common/opcodemgr.h | 34 ++-- common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 16 +- common/patches/sod.cpp | 2 +- common/patches/sof.cpp | 2 +- common/patches/titanium.cpp | 2 +- common/patches/uf.cpp | 2 +- common/platform/win/include_winsock2.h | 1 + common/process.cpp | 4 +- common/serialize_buffer.h | 44 +++-- common/servertalk.h | 59 +++--- common/tasks.h | 4 +- libs/luabind/src/inheritance.cpp | 2 +- loginserver/client.cpp | 2 +- loginserver/world_server_manager.cpp | 2 +- world/cli/cli_database_concurrency.cpp | 15 +- world/cli/cli_database_version.cpp | 5 +- world/cli/cli_test.cpp | 2 +- world/cli/cli_version.cpp | 5 +- world/cliententry.h | 4 +- world/eql_config.h | 4 +- world/launcher_link.h | 4 +- world/login_server.h | 1 - world/login_server_list.h | 1 - world/shared_task_manager.cpp | 6 +- world/ucs.h | 2 +- world/world_boot.cpp | 15 +- zone/aa.h | 8 +- zone/bot.cpp | 6 +- zone/bot_command.cpp | 4 +- zone/bot_command.h | 20 +- zone/bot_commands/bot_bot.cpp | 4 +- zone/bot_commands/bot_pickpocket.cpp | 4 +- zone/bot_database.cpp | 4 +- zone/bot_database.h | 2 +- zone/cheat_manager.h | 12 +- zone/client.cpp | 8 +- zone/client.h | 13 +- zone/client_bot.cpp | 2 +- zone/client_packet.cpp | 4 +- zone/command.h | 4 +- zone/common.h | 4 +- zone/effects.cpp | 2 +- zone/entity.cpp | 2 +- zone/event_codes.h | 4 +- zone/gm_commands/door_manipulation.cpp | 18 +- zone/guild.cpp | 4 +- zone/lua_bit.cpp | 2 +- zone/lua_bit.h | 4 +- zone/main.cpp | 10 +- zone/map.cpp | 2 +- zone/npc.h | 4 +- zone/petitions.cpp | 17 +- zone/petitions.h | 9 +- zone/questmgr.cpp | 13 +- zone/raycast_mesh.cpp | 2 +- zone/shared_task_zone_messaging.cpp | 4 +- zone/task_manager.cpp | 6 +- zone/tradeskills.cpp | 4 +- zone/water_map_v1.h | 5 +- zone/worldserver.cpp | 2 +- 107 files changed, 1276 insertions(+), 1539 deletions(-) delete mode 100644 common/condition.cpp delete mode 100644 common/condition.h rename common/{mutex.h => event/event_loop.cpp} (55%) create mode 100644 common/event/task_scheduler.cpp create mode 100644 common/event/timer.cpp create mode 100644 common/memory/ksm.cpp create mode 100644 common/memory/ksm.h delete mode 100644 common/memory/ksm.hpp delete mode 100644 common/mutex.cpp create mode 100644 common/net/dns.cpp diff --git a/.gitattributes b/.gitattributes index 1202f64159..1d788f033f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -20,3 +20,4 @@ *.css text *.js text *.types text +*.pdf binary diff --git a/CMakeLists.txt b/CMakeLists.txt index a831e21262..8bbbeda68b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ endif() project(EQEmu VERSION 24.10.3 - LANGUAGES CXX + LANGUAGES CXX ) set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -42,10 +42,10 @@ option(EQEMU_BUILD_PCH "Build with precompiled headers (Windows)" ON) if(MSVC) add_compile_options(/bigobj) - add_compile_definitions(_CRT_SECURE_NO_WARNINGS NOMINMAX CRASH_LOGGING _HAS_AUTO_PTR_ETC) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS NOMINMAX WIN32_LEAN_AND_MEAN CRASH_LOGGING _HAS_AUTO_PTR_ETC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") - option(EQEMU_DISABLE_MSVC_WARNINGS "Disable MSVC compile warnings." ON) + option(EQEMU_DISABLE_MSVC_WARNINGS "Disable MSVC compile warnings." OFF) if(EQEMU_DISABLE_MSVC_WARNINGS) add_compile_options(/W0 /wd4005 /wd4996 /nologo /Os) endif() diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 3f8b299346..e9f43cec80 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -7,20 +7,20 @@ set(common_sources classes.cpp cli/eqemu_command_handler.cpp compression.cpp - condition.cpp content/world_content_service.cpp crash.cpp crc16.cpp crc32.cpp data_bucket.cpp + data_bucket.cpp + database_instances.cpp database.cpp database/database_dump_service.cpp database/database_update.cpp - database_instances.cpp dbcore.cpp deity.cpp - discord/discord.cpp discord/discord_manager.cpp + discord/discord.cpp dynamic_zone_base.cpp dynamic_zone_lockout.cpp emu_constants.cpp @@ -31,13 +31,16 @@ set(common_sources eq_packet.cpp eq_stream_ident.cpp eq_stream_proxy.cpp - eqdb.cpp eqdb_res.cpp + eqdb.cpp eqemu_config.cpp eqemu_exception.cpp eqemu_logsys.cpp eqtime.cpp event_sub.cpp + event/event_loop.cpp + event/task_scheduler.cpp + event/timer.cpp events/player_event_discord_formatter.cpp events/player_event_logs.cpp evolving_items.cpp @@ -51,62 +54,56 @@ set(common_sources ipc_mutex.cpp item_data.cpp item_instance.cpp - json/json.hpp - json/jsoncpp.cpp json_config.cpp + json/jsoncpp.cpp light_source.cpp md5.cpp - memory/ksm.hpp memory_buffer.cpp memory_mapped_file.cpp - misc.cpp + memory/ksm.cpp misc_functions.cpp - mutex.cpp + misc.cpp mysql_request_result.cpp mysql_request_row.cpp mysql_stmt.cpp - net/console_server.cpp net/console_server_connection.cpp + net/console_server.cpp net/crc32.cpp + net/dns.cpp net/eqstream.cpp net/packet.cpp net/reliable_stream_connection.cpp net/servertalk_client_connection.cpp net/servertalk_legacy_client_connection.cpp - net/servertalk_server.cpp net/servertalk_server_connection.cpp + net/servertalk_server.cpp net/tcp_connection.cpp net/tcp_server.cpp - net/websocket_server.cpp net/websocket_server_connection.cpp + net/websocket_server.cpp opcode_map.cpp opcodemgr.cpp - packet_dump.cpp packet_dump_file.cpp + packet_dump.cpp packet_functions.cpp patches/patches.cpp + patches/rof_limits.cpp patches/rof.cpp - patches/rof2.cpp patches/rof2_limits.cpp - patches/rof_limits.cpp - patches/sod.cpp + patches/rof2.cpp patches/sod_limits.cpp - patches/sof.cpp + patches/sod.cpp patches/sof_limits.cpp - patches/titanium.cpp + patches/sof.cpp patches/titanium_limits.cpp - patches/uf.cpp + patches/titanium.cpp patches/uf_limits.cpp + patches/uf.cpp + path_manager.cpp path_manager.cpp - perl_eqdb.cpp perl_eqdb_res.cpp + perl_eqdb.cpp platform.cpp - platform/inet.h - platform/platform.h - platform/posix/include_inet.h - platform/posix/include_pthreads.h - platform/win/include_windows.h - platform/win/include_winsock2.h proc_launcher.cpp process.cpp process/process.cpp @@ -123,12 +120,12 @@ set(common_sources shareddb.cpp skill_caps.cpp skills.cpp - spdat.cpp spdat_bot.cpp + spdat.cpp StackWalker/StackWalker.cpp - strings.cpp strings_legacy.cpp strings_misc.cpp + strings.cpp struct_strategy.cpp textures.cpp timer.cpp @@ -538,35 +535,32 @@ set(repositories ) set(common_headers - StackWalker/StackWalker.h additive_lagged_fibonacci_engine.h base_packet.h bazaar.h bodytypes.h + classes.h cli/argh.h cli/eqemu_command_handler.h cli/terminal_color.hpp - classes.h compression.h - condition.h content/world_content_service.h crash.h crc16.h crc32.h cron/croncpp.h - data_bucket.cpp data_verification.h + database_schema.h database.h database/database_dump_service.h - database/database_update.h - database/database_update_manifest.h database/database_update_manifest_bots.h database/database_update_manifest_custom.h - database_schema.h + database/database_update_manifest.h + database/database_update.h dbcore.h deity.h - discord/discord.h discord/discord_manager.h + discord/discord.h dynamic_zone_base.h dynamic_zone_lockout.h emu_constants.h @@ -576,24 +570,24 @@ set(common_headers emu_versions.h eq_constants.h eq_limits.h - eq_packet.h eq_packet_structs.h + eq_packet.h eq_stream_ident.h eq_stream_intf.h eq_stream_locator.h eq_stream_proxy.h - eqdb.h eqdb_res.h - eqemu_config.h + eqdb.h eqemu_config_elements.h + eqemu_config.h eqemu_exception.h - eqemu_logsys.h eqemu_logsys_log_aliases.h + eqemu_logsys.h eqtime.h + event_sub.h event/event_loop.h event/task.h event/timer.h - event_sub.h events/player_event_discord_formatter.h events/player_event_logs.h events/player_events.h @@ -614,10 +608,11 @@ set(common_headers ipc_mutex.h item_data.h item_instance.h + json_config.h + json/json_archive_single_line.h json/json-forwards.h json/json.h - json/json_archive_single_line.h - json_config.h + json/json.hpp light_source.h linked_list.h loot.h @@ -625,14 +620,14 @@ set(common_headers md5.h memory_buffer.h memory_mapped_file.h - misc.h + memory/ksm.h misc_functions.h - mutex.h + misc.h mysql_request_result.h mysql_request_row.h mysql_stmt.h - net/console_server.h net/console_server_connection.h + net/console_server.h net/crc32.h net/dns.h net/endian.h @@ -644,49 +639,54 @@ set(common_headers net/servertalk_client_connection.h net/servertalk_common.h net/servertalk_legacy_client_connection.h - net/servertalk_server.h net/servertalk_server_connection.h - net/tcp_connection.h + net/servertalk_server.h net/tcp_connection_pooling.h + net/tcp_connection.h net/tcp_server.h - net/websocket_server.h net/websocket_server_connection.h + net/websocket_server.h op_codes.h opcode_dispatch.h opcodemgr.h - packet_dump.h packet_dump_file.h + packet_dump.h packet_functions.h patches/patches.h + patches/rof_limits.h + patches/rof_ops.h + patches/rof_structs.h patches/rof.h - patches/rof2.h patches/rof2_limits.h patches/rof2_ops.h patches/rof2_structs.h - patches/rof_limits.h - patches/rof_ops.h - patches/rof_structs.h - patches/sod.h + patches/rof2.h patches/sod_limits.h patches/sod_ops.h patches/sod_structs.h - patches/sof.h + patches/sod.h patches/sof_limits.h patches/sof_ops.h patches/sof_structs.h + patches/sof.h patches/ss_declare.h patches/ss_define.h patches/ss_register.h - patches/titanium.h patches/titanium_limits.h patches/titanium_ops.h patches/titanium_structs.h - patches/uf.h + patches/titanium.h patches/uf_limits.h patches/uf_ops.h patches/uf_structs.h - path_manager.cpp + patches/uf.h platform.h + platform/inet.h + platform/platform.h + platform/posix/include_inet.h + platform/posix/include_pthreads.h + platform/win/include_windows.h + platform/win/include_winsock2.h proc_launcher.h process.h process/process.h @@ -713,6 +713,7 @@ set(common_headers skills.h spdat.h stacktrace/backward.hpp + StackWalker/StackWalker.h strings.h struct_strategy.h tasks.h @@ -729,25 +730,9 @@ set(common_headers zone_store.h ) -# Source Groups (Regex based for automatic subdirectory handling) -source_group("CLI" REGULAR_EXPRESSION "^cli/") -source_group("Content" REGULAR_EXPRESSION "^content/") -source_group("Cron" REGULAR_EXPRESSION "^cron/") -source_group("Database" REGULAR_EXPRESSION "^database/") -source_group("Discord" REGULAR_EXPRESSION "^discord/") -source_group("Event" REGULAR_EXPRESSION "^event/") -source_group("Events" REGULAR_EXPRESSION "^events/") -source_group("Http" REGULAR_EXPRESSION "^http/") -source_group("Json" REGULAR_EXPRESSION "^json/") -source_group("Memory" REGULAR_EXPRESSION "^memory/") -source_group("Net" REGULAR_EXPRESSION "^net/") -source_group("Patches" REGULAR_EXPRESSION "^patches/") -source_group("Process" REGULAR_EXPRESSION "^process/") -source_group("Repositories" REGULAR_EXPRESSION "^repositories/") -source_group("StackWalker" REGULAR_EXPRESSION "^StackWalker/") -source_group("Stacktrace" REGULAR_EXPRESSION "^stacktrace/") -source_group("Termcolor" REGULAR_EXPRESSION "^termcolor/") -source_group("Util" REGULAR_EXPRESSION "^util/") +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Source Files" FILES ${common_sources}) +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Header Files" FILES ${common_headers}) +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/repositories" PREFIX "Repositories" FILES ${repositories}) option(EQEMU_ADD_PROFILER "Link with Google perftools profiler" OFF) #PRNG options diff --git a/common/StackWalker/StackWalker.cpp b/common/StackWalker/StackWalker.cpp index 5360a3efa1..befbfac626 100644 --- a/common/StackWalker/StackWalker.cpp +++ b/common/StackWalker/StackWalker.cpp @@ -359,7 +359,7 @@ class StackWalkerInternal BOOL Publics; // contains public symbols }; */ -typedef struct IMAGEHLP_MODULE64_V2 { +struct IMAGEHLP_MODULE64_V2 { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) DWORD64 BaseOfImage; // base load address of module DWORD ImageSize; // virtual size of the loaded module diff --git a/common/StackWalker/StackWalker.h b/common/StackWalker/StackWalker.h index a53c673289..d5f04e053e 100644 --- a/common/StackWalker/StackWalker.h +++ b/common/StackWalker/StackWalker.h @@ -134,7 +134,7 @@ class StackWalker CHAR loadedImageName[STACKWALK_MAX_NAMELEN]; } CallstackEntry; - typedef enum CallstackEntryType {firstEntry, nextEntry, lastEntry}; + enum CallstackEntryType {firstEntry, nextEntry, lastEntry}; virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName); virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion); diff --git a/common/base_packet.cpp b/common/base_packet.cpp index b9f60f6a7b..048bceb9c0 100644 --- a/common/base_packet.cpp +++ b/common/base_packet.cpp @@ -19,44 +19,34 @@ #include "common/misc.h" #include "common/packet_dump.h" -BasePacket::BasePacket(const unsigned char *buf, uint32 len) +BasePacket::BasePacket(const unsigned char* buf, size_t len) { - pBuffer=nullptr; - size=0; - _wpos = 0; - _rpos = 0; - timestamp.tv_sec = 0; - if (len>0) { - size=len; - pBuffer= new unsigned char[len]; + if (len > 0) { + size = static_cast(len); + pBuffer = new unsigned char[len]; if (buf) { - memcpy(pBuffer,buf,len); - } else { - memset(pBuffer,0,len); + memcpy(pBuffer, buf, len); + } + else { + memset(pBuffer, 0, len); } } } -BasePacket::BasePacket(SerializeBuffer &buf) +BasePacket::BasePacket(SerializeBuffer&& buf) + : pBuffer(std::exchange(buf.m_buffer, nullptr)) { - pBuffer = buf.m_buffer; - buf.m_buffer = nullptr; - size = buf.m_pos; - buf.m_pos = 0; + // We are essentially taking ownership of this serialize buffer. + size = static_cast(std::exchange(buf.m_pos, 0)); buf.m_capacity = 0; - _wpos = 0; - _rpos = 0; - timestamp.tv_sec = 0; } BasePacket::~BasePacket() { - if (pBuffer) - delete[] pBuffer; - pBuffer=nullptr; + delete[] pBuffer; + pBuffer = nullptr; } - void BasePacket::build_raw_header_dump(char *buffer, uint16 seq) const { if (timestamp.tv_sec) { diff --git a/common/base_packet.h b/common/base_packet.h index 607e045760..b3ea8430ee 100644 --- a/common/base_packet.h +++ b/common/base_packet.h @@ -23,14 +23,26 @@ #include -class BasePacket { +class BasePacket +{ +protected: + BasePacket() = default; + BasePacket(const unsigned char* buf, size_t len); + BasePacket(SerializeBuffer&& buf); + + virtual ~BasePacket(); + public: - unsigned char *pBuffer; - uint32 size, _wpos, _rpos; - uint32 src_ip,dst_ip; - uint16 src_port,dst_port; - uint32 priority; - timeval timestamp; + unsigned char* pBuffer = nullptr; + uint32 size = 0; + uint32 _wpos = 0; + uint32 _rpos = 0; + uint32 src_ip = 0; + uint32 dst_ip = 0; + uint16 src_port = 0; + uint16 dst_port = 0; + uint32 priority = 0; + timeval timestamp{}; virtual void build_raw_header_dump(char *buffer, uint16 seq=0xffff) const; virtual void build_header_dump(char *buffer) const; @@ -40,11 +52,11 @@ class BasePacket { void setSrcInfo(uint32 sip, uint16 sport) { src_ip=sip; src_port=sport; } void setDstInfo(uint32 dip, uint16 dport) { dst_ip=dip; dst_port=dport; } - void setTimeInfo(uint32 ts_sec, uint32 ts_usec) { timestamp.tv_sec=ts_sec; timestamp.tv_usec=ts_usec; } + void setTimeInfo(uint32 ts_sec, uint32 ts_usec) { timestamp.tv_sec = ts_sec; timestamp.tv_usec = ts_usec; } void copyInfo(const BasePacket *p) { src_ip=p->src_ip; src_port=p->src_port; dst_ip=p->dst_ip; dst_port=p->dst_port; timestamp.tv_sec=p->timestamp.tv_sec; timestamp.tv_usec=p->timestamp.tv_usec; } inline bool operator<(const BasePacket &rhs) { - return (timestamp.tv_sec < rhs.timestamp.tv_sec || (timestamp.tv_sec==rhs.timestamp.tv_sec && timestamp.tv_usec < rhs.timestamp.tv_usec)); + return (timestamp.tv_sec < rhs.timestamp.tv_sec || (timestamp.tv_sec == rhs.timestamp.tv_sec && timestamp.tv_usec < rhs.timestamp.tv_usec)); } void WriteUInt8(uint8 value) { *(uint8 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint8); } @@ -73,12 +85,6 @@ class BasePacket { uint32 GetReadPosition() { return _rpos; } void SetWritePosition(uint32 Newwpos) { _wpos = Newwpos; } void SetReadPosition(uint32 Newrpos) { _rpos = Newrpos; } - -protected: - virtual ~BasePacket(); - BasePacket() { pBuffer=nullptr; size=0; _wpos = 0; _rpos = 0; } - BasePacket(const unsigned char *buf, const uint32 len); - BasePacket(SerializeBuffer &buf); }; extern void DumpPacketHex(const BasePacket* app); diff --git a/common/cli/eqemu_command_handler.cpp b/common/cli/eqemu_command_handler.cpp index 2f150b621d..59dec2b2d1 100644 --- a/common/cli/eqemu_command_handler.cpp +++ b/common/cli/eqemu_command_handler.cpp @@ -23,12 +23,9 @@ namespace EQEmuCommand { - std::map function_map; + using CommandFunction = void(*)(int argc, char** argv, argh::parser& cmd, std::string& description); + + std::map function_map; /** * @param cmd diff --git a/common/cli/terminal_color.hpp b/common/cli/terminal_color.hpp index 90bc570711..e9ec96fa66 100644 --- a/common/cli/terminal_color.hpp +++ b/common/cli/terminal_color.hpp @@ -51,7 +51,7 @@ # include #elif defined(TERMCOLOR_OS_WINDOWS) # include -# include +# include "common/platform/win/include_windows.h" #endif diff --git a/common/condition.cpp b/common/condition.cpp deleted file mode 100644 index 657bc610d4..0000000000 --- a/common/condition.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* EQEmu: EQEmulator - - Copyright (C) 2001-2026 EQEmu Development Team - - 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; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; 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, see . -*/ -#include "condition.h" - -#ifdef _WINDOWS - - Condition::Condition() - { - m_events[SignalEvent] = CreateEvent (nullptr, // security - FALSE, // is auto-reset event? - FALSE, // is signaled initially? - nullptr); // name - m_events[BroadcastEvent] = CreateEvent (nullptr, // security - TRUE, // is auto-reset event? - FALSE, // is signaled initially? - nullptr); // name - m_waiters = 0; - InitializeCriticalSection(&CSMutex); - } - - Condition::~Condition() - { - DeleteCriticalSection(&CSMutex); - CloseHandle(m_events[SignalEvent]); - CloseHandle(m_events[BroadcastEvent]); - } - - void Condition::Signal() - { - EnterCriticalSection(&CSMutex); - if(m_waiters > 0) - SetEvent(m_events[SignalEvent]); - LeaveCriticalSection(&CSMutex); - } - - void Condition::SignalAll() - { - EnterCriticalSection(&CSMutex); - if(m_waiters > 0) - SetEvent(m_events[BroadcastEvent]); - LeaveCriticalSection(&CSMutex); - } - - void Condition::Wait() - { - EnterCriticalSection(&CSMutex); - - m_waiters++; - - - LeaveCriticalSection(&CSMutex); - int result = WaitForMultipleObjects (_eventCount, m_events, FALSE, INFINITE); - EnterCriticalSection(&CSMutex); - - m_waiters--; - - //see if we are the last person waiting on the condition, and there was a broadcast - //if so, we need to reset the broadcast event. - if(m_waiters == 0 && result == (WAIT_OBJECT_0+BroadcastEvent)) - ResetEvent(m_events[BroadcastEvent]); - - LeaveCriticalSection(&CSMutex); - } - -#else - #include - #include - #include - - Condition::Condition() - { - pthread_cond_init(&cond,nullptr); - pthread_mutex_init(&mutex,nullptr); - } - - void Condition::Signal() - { - pthread_mutex_lock(&mutex); - pthread_cond_signal(&cond); - pthread_mutex_unlock(&mutex); - } - - void Condition::SignalAll() - { - pthread_mutex_lock(&mutex); - pthread_cond_broadcast(&cond); - pthread_mutex_unlock(&mutex); - } - - void Condition::Wait() - { - pthread_mutex_lock(&mutex); - pthread_cond_wait(&cond,&mutex); - pthread_mutex_unlock(&mutex); - } - - /* - I commented this specifically because I think it might be very - difficult to write a windows counterpart to it, so I would like - to discourage its use until we can confirm that it can be reasonably - implemented on windows. - - bool Condition::TimedWait(unsigned long usec) - { - struct timeval now; - struct timespec timeout; - int retcode=0; - pthread_mutex_lock(&mutex); - gettimeofday(&now,nullptr); - now.tv_usec+=usec; - timeout.tv_sec = now.tv_sec + (now.tv_usec/1000000); - timeout.tv_nsec = (now.tv_usec%1000000) *1000; - //cout << "now=" << now.tv_sec << "."<. -*/ -#pragma once - -#include "common/mutex.h" -#include "common/platform/posix/include_pthreads.h" -#include "common/platform/win/include_windows.h" - -//Sombody, someday needs to figure out how to implement a condition -//system on windows... - - -class Condition { - private: -#ifdef WIN32 - enum { - SignalEvent = 0, - BroadcastEvent, - _eventCount - }; - - HANDLE m_events[_eventCount]; - uint32 m_waiters; - CRITICAL_SECTION CSMutex; -#else - pthread_cond_t cond; - pthread_mutex_t mutex; -#endif - public: - Condition(); - void Signal(); - void SignalAll(); - void Wait(); -// bool TimedWait(unsigned long usec); - ~Condition(); -}; diff --git a/common/content/world_content_service.cpp b/common/content/world_content_service.cpp index 1b650b82d5..3bc28a7a24 100644 --- a/common/content/world_content_service.cpp +++ b/common/content/world_content_service.cpp @@ -132,7 +132,7 @@ void WorldContentService::SetContentFlags(const std::vector> 8) ^ CRC32Table[(byte) ^ ((crc32var) & 0x000000FF)]; } diff --git a/common/database.cpp b/common/database.cpp index 83ed14c903..7376cb0da0 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -728,7 +728,7 @@ bool Database::LoadVariables() return true; } - LockMutex lock(&Mvarcache); + std::scoped_lock lock(Mvarcache); for (const auto& e : l) { varcache.last_update = std::time(nullptr); @@ -747,7 +747,7 @@ bool Database::LoadVariables() bool Database::GetVariable(const std::string& name, std::string& value) { - LockMutex lock(&Mvarcache); + std::scoped_lock lock(Mvarcache); if (name.empty()) { return false; diff --git a/common/database.h b/common/database.h index fdb3154b2d..ab5d6c2718 100644 --- a/common/database.h +++ b/common/database.h @@ -20,13 +20,12 @@ #include "common/dbcore.h" #include "common/eq_packet_structs.h" #include "common/eqemu_logsys.h" -#include "common/linked_list.h" #include "common/types.h" -#include +#include +#include #include #include -#include #define AUTHENTICATION_TIMEOUT 60 #define INVALID_ID 0xFFFFFFFF @@ -265,7 +264,7 @@ class Database : public DBcore { uint64_t GetNextTableId(const std::string& table_name); private: - Mutex Mvarcache; + std::mutex Mvarcache; VarCache_Struct varcache; /* Groups, utility methods. */ diff --git a/common/dbcore.cpp b/common/dbcore.cpp index d119ceacbd..1cde3b30f0 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -33,17 +33,9 @@ #endif DBcore::DBcore() + : mysql(mysql_init(nullptr)) + , m_mutex(std::make_shared()) { - mysql = mysql_init(nullptr); - mysqlOwner = true; - pHost = nullptr; - pUser = nullptr; - pPassword = nullptr; - pDatabase = nullptr; - pCompress = false; - pSSL = false; - pStatus = Closed; - m_mutex = new Mutex; } DBcore::~DBcore() @@ -56,20 +48,17 @@ DBcore::~DBcore() if (mysqlOwner) { mysql_close(mysql); } - - safe_delete_array(pHost); - safe_delete_array(pUser); - safe_delete_array(pPassword); - safe_delete_array(pDatabase); } // Sends the MySQL server a keepalive void DBcore::ping() { - if (!m_mutex->trylock()) { + if (!m_mutex->try_lock()) + { // well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive return; } + mysql_ping(mysql); m_mutex->unlock(); } @@ -92,7 +81,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo BenchTimer timer; timer.reset(); - LockMutex lock(m_mutex); + std::scoped_lock lock(*m_mutex); // Reconnect if we are not connected before hand. if (pStatus != Connected) { @@ -217,15 +206,12 @@ bool DBcore::Open( bool iSSL ) { - LockMutex lock(m_mutex); - safe_delete_array(pHost); - safe_delete_array(pUser); - safe_delete_array(pPassword); - safe_delete_array(pDatabase); - pHost = strcpy(new char[strlen(iHost) + 1], iHost); - pUser = strcpy(new char[strlen(iUser) + 1], iUser); - pPassword = strcpy(new char[strlen(iPassword) + 1], iPassword); - pDatabase = strcpy(new char[strlen(iDatabase) + 1], iDatabase); + std::scoped_lock lock(*m_mutex); + + m_host = iHost; + m_user = iUser; + m_password = iPassword; + m_database = iDatabase; pCompress = iCompress; pPort = iPort; pSSL = iSSL; @@ -234,10 +220,12 @@ bool DBcore::Open( bool DBcore::Open(uint32 *errnum, char *errbuf) { + // Expects m_mutex to already be locked. + if (errbuf) { errbuf[0] = 0; } - LockMutex lock(m_mutex); + if (GetStatus() == Connected) { return true; } @@ -245,7 +233,7 @@ bool DBcore::Open(uint32 *errnum, char *errbuf) mysql_close(mysql); mysql_init(mysql); // Initialize structure again } - if (!pHost) { + if (m_host.empty()) { return false; } /* @@ -268,11 +256,10 @@ bool DBcore::Open(uint32 *errnum, char *errbuf) mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &off); mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &off); } - if (mysql_real_connect(mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) { + if (mysql_real_connect(mysql, m_host.c_str(), m_user.c_str(), m_password.c_str(), m_database.c_str(), pPort, nullptr, flags)) { pStatus = Connected; - std::string connected_origin_host = pHost; - SetOriginHost(connected_origin_host); + SetOriginHost(m_host); return true; } @@ -293,9 +280,9 @@ const std::string &DBcore::GetOriginHost() const return origin_host; } -void DBcore::SetOriginHost(const std::string &origin_host) +void DBcore::SetOriginHost(const std::string& originHost) { - DBcore::origin_host = origin_host; + DBcore::origin_host = originHost; } std::string DBcore::Escape(const std::string& s) @@ -307,12 +294,8 @@ std::string DBcore::Escape(const std::string& s) return temp.data(); } -void DBcore::SetMutex(Mutex *mutex) +void DBcore::SetMutex(const std::shared_ptr& mutex) { - if (m_mutex && m_mutex != mutex) { - safe_delete(m_mutex); - } - DBcore::m_mutex = mutex; } @@ -326,7 +309,7 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query) BenchTimer timer; timer.reset(); - LockMutex lock(m_mutex); + std::scoped_lock lock(*m_mutex); // Reconnect if we are not connected before hand. if (pStatus != Connected) { @@ -449,5 +432,5 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query) mysql::PreparedStmt DBcore::Prepare(std::string query) { - return mysql::PreparedStmt(*mysql, std::move(query), m_mutex); + return mysql::PreparedStmt(*mysql, std::move(query), *m_mutex); } diff --git a/common/dbcore.h b/common/dbcore.h index eef5c1d4bb..b9b25d149a 100644 --- a/common/dbcore.h +++ b/common/dbcore.h @@ -17,11 +17,11 @@ */ #pragma once -#include "common/mutex.h" #include "common/mysql_request_result.h" #include "common/types.h" #include "mysql.h" +#include #include #define CR_SERVER_GONE_ERROR 2006 @@ -29,12 +29,15 @@ namespace mysql { class PreparedStmt; } -class DBcore { +class DBcore +{ public: enum eStatus { Closed, Connected, Error }; + using Mutex = std::recursive_mutex; + DBcore(); ~DBcore(); eStatus GetStatus() { return pStatus; } @@ -48,17 +51,17 @@ class DBcore { uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen); void ping(); - const std::string &GetOriginHost() const; - void SetOriginHost(const std::string &origin_host); + const std::string& GetOriginHost() const; + void SetOriginHost(const std::string& origin_host); bool DoesTableExist(const std::string& table_name); - void SetMySQL(const DBcore &o) + void SetMySQL(const DBcore& o) { mysql = o.mysql; mysqlOwner = false; } - void SetMutex(Mutex *mutex); + void SetMutex(const std::shared_ptr& mutex); // only safe on connections shared with other threads if results buffered // unsafe to use off main thread due to internal server logging @@ -81,22 +84,21 @@ class DBcore { private: bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr); - MYSQL* mysql; - bool mysqlOwner; - Mutex *m_mutex; - eStatus pStatus; + MYSQL* mysql = nullptr; + bool mysqlOwner = true; + eStatus pStatus = Closed; - std::mutex m_query_lock{}; + std::shared_ptr m_mutex; std::string origin_host; - char *pHost; - char *pUser; - char *pPassword; - char *pDatabase; - bool pCompress; - uint32 pPort; - bool pSSL; + std::string m_host; + std::string m_user; + std::string m_password; + std::string m_database; + bool pCompress = false; + uint32 pPort = 0; + bool pSSL = false; // allows multiple queries to be executed within the same query // do not use this under normal operation diff --git a/common/eq_packet.cpp b/common/eq_packet.cpp index 93b4f1052d..62136ca8ba 100644 --- a/common/eq_packet.cpp +++ b/common/eq_packet.cpp @@ -31,9 +31,19 @@ #include #include -EQPacket::EQPacket(EmuOpcode op, const unsigned char *buf, uint32 len) -: BasePacket(buf, len), - emu_opcode(op) +EQPacket::EQPacket() +{ +} + +EQPacket::EQPacket(EmuOpcode op, const unsigned char *buf, size_t len) + : BasePacket(buf, len) + , emu_opcode(op) +{ +} + +EQPacket::EQPacket(EmuOpcode opcode, SerializeBuffer&& buf) + : BasePacket(std::move(buf)) + , emu_opcode(opcode) { } @@ -360,17 +370,16 @@ EQRawApplicationPacket::EQRawApplicationPacket(const unsigned char *buf, const u } } -void DumpPacket(const EQApplicationPacket* app, bool iShowInfo) { +void DumpPacket(const EQApplicationPacket* app, bool iShowInfo) +{ if (iShowInfo) { - std::cout << "Dumping Applayer: 0x" << std::hex << std::setfill('0') << std::setw(4) << app->GetOpcode() << std::dec; - std::cout << " size:" << app->size << std::endl; + printf("Dumping Applayer: 0x%04x size: %u", app->GetOpcode(), app->size); } + DumpPacketHex(app->pBuffer, app->size); -// DumpPacketAscii(app->pBuffer, app->size); } -std::string DumpPacketToString(const EQApplicationPacket* app){ - std::ostringstream out; - out << DumpPacketHexToString(app->pBuffer, app->size); - return out.str(); +std::string DumpPacketToString(const EQApplicationPacket* app) +{ + return DumpPacketHexToString(app->pBuffer, app->size); } diff --git a/common/eq_packet.h b/common/eq_packet.h index e2d0d27106..e8ad80d127 100644 --- a/common/eq_packet.h +++ b/common/eq_packet.h @@ -28,8 +28,15 @@ #include "common/emu_opcodes.h" #endif -class EQPacket : public BasePacket { +class EQPacket : public BasePacket +{ friend class EQStream; + +protected: + EQPacket(); + EQPacket(EmuOpcode opcode, const unsigned char* buf, size_t len); + EQPacket(EmuOpcode opcode, SerializeBuffer&& buf); + public: virtual ~EQPacket() {} @@ -41,19 +48,12 @@ class EQPacket : public BasePacket { virtual void DumpRawHeaderNoTime(uint16 seq=0xffff, FILE *to = stdout) const; void SetOpcode(EmuOpcode op) { emu_opcode = op; } - const EmuOpcode GetOpcode() const { return(emu_opcode); } -// const char *GetOpcodeName() const; + EmuOpcode GetOpcode() const { return(emu_opcode); } protected: //this is just a cache so we dont look it up several times on Get() //and it is mutable so we can store the cached copy even on a const object - EmuOpcode emu_opcode; - - EQPacket(EmuOpcode opcode, const unsigned char *buf, const uint32 len); - EQPacket(EmuOpcode opcode, SerializeBuffer &buf) : BasePacket(buf), emu_opcode(opcode) { }; -// EQPacket(const EQPacket &p) { } - EQPacket() { emu_opcode=OP_Unknown; pBuffer=nullptr; size=0; } - + EmuOpcode emu_opcode = OP_Unknown; }; class EQRawApplicationPacket; @@ -90,19 +90,43 @@ class EQProtocolPacket : public BasePacket { uint16 opcode; }; -class EQApplicationPacket : public EQPacket { +class EQApplicationPacket : public EQPacket +{ friend class EQStream; + +public: + EQApplicationPacket() + { + } + + EQApplicationPacket(EmuOpcode op) + : EQPacket(op, nullptr, 0) + { + } + + EQApplicationPacket(EmuOpcode op, size_t len) + : EQPacket(op, nullptr, len) + { + } + EQApplicationPacket(EmuOpcode op, const unsigned char* buf, size_t len) + : EQPacket(op, buf, len) + { + } + + EQApplicationPacket(EmuOpcode op, SerializeBuffer&& buf) + : EQPacket(op, std::move(buf)) + { + } + +private: + EQApplicationPacket(const EQApplicationPacket& p) + : EQPacket(p.emu_opcode, p.pBuffer, p.size) + , app_opcode_size(p.app_opcode_size) + , opcode_bypass(p.opcode_bypass) + { + } + public: - EQApplicationPacket() : EQPacket(OP_Unknown, nullptr, 0), opcode_bypass(0) - { app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; } - EQApplicationPacket(const EmuOpcode op) : EQPacket(op, nullptr, 0), opcode_bypass(0) - { app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; } - EQApplicationPacket(const EmuOpcode op, const uint32 len) : EQPacket(op, nullptr, len), opcode_bypass(0) - { app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; } - EQApplicationPacket(const EmuOpcode op, const unsigned char *buf, const uint32 len) : EQPacket(op, buf, len), opcode_bypass(0) - { app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; } - EQApplicationPacket(const EmuOpcode op, SerializeBuffer &buf) : EQPacket(op, buf), opcode_bypass(0) - { app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; } bool combine(const EQApplicationPacket *rhs); uint32 serialize (uint16 opcode, unsigned char *dest) const; uint32 Size() const { return size+app_opcode_size; } @@ -119,15 +143,11 @@ class EQApplicationPacket : public EQPacket { uint16 GetProtocolOpcode() const { return protocol_opcode; } void SetProtocolOpcode(uint16 v) { protocol_opcode = v; } -protected: - - uint16 protocol_opcode; - uint8 app_opcode_size; - uint16 opcode_bypass; -private: - - EQApplicationPacket(const EQApplicationPacket &p) : EQPacket(p.emu_opcode, p.pBuffer, p.size), opcode_bypass(p.opcode_bypass) { app_opcode_size = p.app_opcode_size; } +protected: + uint16 protocol_opcode = 0; + uint8 app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; + uint16 opcode_bypass = 0; }; class EQRawApplicationPacket : public EQApplicationPacket { diff --git a/common/eq_stream_intf.h b/common/eq_stream_intf.h index 2c5faac557..6953f7a37a 100644 --- a/common/eq_stream_intf.h +++ b/common/eq_stream_intf.h @@ -26,13 +26,13 @@ //this is the only part of an EQStream that is seen by the application. -typedef enum { +enum EQStreamState { ESTABLISHED, CLOSING, //waiting for pending data to flush. DISCONNECTING, //have sent disconnect, waiting for their disconnect reply. CLOSED, //received a disconnect from remote side. UNESTABLISHED -} EQStreamState; +}; class EQApplicationPacket; class OpcodeManager; diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp index 7b5e218ebd..1704bab4ab 100644 --- a/common/eqemu_logsys.cpp +++ b/common/eqemu_logsys.cpp @@ -33,10 +33,8 @@ #include #ifdef _WINDOWS -#include +#include "common/platform/platform.h" #include -#include -#include #else #include #include diff --git a/common/mutex.h b/common/event/event_loop.cpp similarity index 55% rename from common/mutex.h rename to common/event/event_loop.cpp index 8040ec2aae..139c1657e8 100644 --- a/common/mutex.h +++ b/common/event/event_loop.cpp @@ -15,36 +15,43 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#pragma once - -#include "common/types.h" -#include "common/platform/posix/include_pthreads.h" -#include "common/platform/win/include_windows.h" - -class Mutex { -public: - Mutex(); - ~Mutex(); - - void lock(); - void unlock(); - bool trylock(); -protected: -private: -#if defined _WINDOWS - CRITICAL_SECTION CSMutex; -#else - pthread_mutex_t CSMutex; -#endif -}; - -class LockMutex { -public: - LockMutex(Mutex* in_mut, bool iLock = true); - ~LockMutex(); - void unlock(); - void lock(); -private: - bool locked; - Mutex* mut; -}; + +#include "common/event/event_loop.h" +#include "uv.h" + +namespace EQ { + +EventLoop& EventLoop::Get() +{ + thread_local EventLoop inst; + return inst; +} + +EventLoop::EventLoop() + : m_loop(std::make_unique()) +{ + memset(m_loop.get(), 0, sizeof(uv_loop_t)); + uv_loop_init(m_loop.get()); +} + +EventLoop::~EventLoop() +{ + uv_loop_close(m_loop.get()); +} + +void EventLoop::Process() +{ + uv_run(m_loop.get(), UV_RUN_NOWAIT); +} + +void EventLoop::Run() +{ + uv_run(m_loop.get(), UV_RUN_DEFAULT); +} + +void EventLoop::Shutdown() +{ + uv_stop(m_loop.get()); +} + +} // namespace EQ diff --git a/common/event/event_loop.h b/common/event/event_loop.h index 3c56ab9492..fed72c0226 100644 --- a/common/event/event_loop.h +++ b/common/event/event_loop.h @@ -17,48 +17,31 @@ */ #pragma once -#include "common/platform/win/include_windows.h" // uv.h is going to include it so let's do it first. -#include "uv.h" // FIXME: hide this +#include -#include +typedef struct uv_loop_s uv_loop_t; -namespace EQ +namespace EQ { + +class EventLoop { - class EventLoop - { - public: - static EventLoop &Get() { - static thread_local EventLoop inst; - return inst; - } +public: + static EventLoop& Get(); - ~EventLoop() { - uv_loop_close(&m_loop); - } + ~EventLoop(); + EventLoop(const EventLoop&) = delete; + EventLoop& operator=(const EventLoop&) = delete; - void Process() { - uv_run(&m_loop, UV_RUN_NOWAIT); - } + void Process(); + void Run(); + void Shutdown(); - void Run() { - uv_run(&m_loop, UV_RUN_DEFAULT); - } + uv_loop_t* Handle() { return m_loop.get(); } - void Shutdown() { - uv_stop(&m_loop); - } +private: + EventLoop(); - uv_loop_t* Handle() { return &m_loop; } + std::unique_ptr m_loop; +}; - private: - EventLoop() { - memset(&m_loop, 0, sizeof(uv_loop_t)); - uv_loop_init(&m_loop); - } - - EventLoop(const EventLoop&); - EventLoop& operator=(const EventLoop&); - - uv_loop_t m_loop; - }; -} +} // namespace EQ diff --git a/common/event/task_scheduler.cpp b/common/event/task_scheduler.cpp new file mode 100644 index 0000000000..2b0fd7ef98 --- /dev/null +++ b/common/event/task_scheduler.cpp @@ -0,0 +1,128 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ + +#include "task_scheduler.h" + +#include +#include +#include +#include +#include +#include + +namespace EQ::Event { + +static constexpr int DefaultThreadCount = 4; + +struct TaskScheduler::SchedulerData +{ + std::atomic_bool running{ false }; + std::vector threads; + std::mutex lock; + std::condition_variable cv; + std::queue> tasks; +}; + +TaskScheduler::TaskScheduler() + : m_data(std::make_unique()) +{ + Start(DefaultThreadCount); +} + +TaskScheduler::TaskScheduler(size_t threads) +{ + Start(threads); +} + +TaskScheduler::~TaskScheduler() +{ + Stop(); +} + +void TaskScheduler::Start(size_t threads) +{ + if (m_data->running.exchange(true)) + return; + + m_data->threads.reserve(threads); + + for (size_t i = 0; i < threads; ++i) + { + m_data->threads.emplace_back( + [this]{ ProcessWork(); }); + } +} + +void TaskScheduler::Stop() +{ + if (!m_data->running.exchange(false)) + return; + + m_data->cv.notify_all(); + + for (auto& t : m_data->threads) + { + t.join(); + } + + m_data->threads.clear(); +} + +void TaskScheduler::ProcessWork() +{ + for (;;) + { + std::function work; + + { + std::unique_lock lock(m_data->lock); + + m_data->cv.wait(lock, + [this] + { + return !m_data->running || !m_data->tasks.empty(); + }); + + if (!m_data->running) + { + return; + } + + work = std::move(m_data->tasks.front()); + m_data->tasks.pop(); + } + + work(); + } +} + +void TaskScheduler::AddTask(std::function&& task) +{ + if (!m_data->running) + { + throw std::runtime_error("Enqueue on stopped scheduler."); + } + + { + std::scoped_lock lock(m_data->lock); + m_data->tasks.push(std::move(task)); + } + m_data->cv.notify_one(); +} + +} // namespace EQ::Event diff --git a/common/event/task_scheduler.h b/common/event/task_scheduler.h index e2e855682e..c63e93bdfc 100644 --- a/common/event/task_scheduler.h +++ b/common/event/task_scheduler.h @@ -17,116 +17,45 @@ */ #pragma once -#include #include #include -#include -#include -#include -#include +#include -namespace EQ -{ - namespace Event - { - class TaskScheduler - { - public: - static const int DefaultThreadCount = 4; - - TaskScheduler() : _running(false) - { - Start(DefaultThreadCount); - } - - TaskScheduler(size_t threads) : _running(false) - { - Start(threads); - } - - ~TaskScheduler() { - Stop(); - } - - void Start(size_t threads) { - if (true == _running) { - return; - } - - _running = true; +namespace EQ::Event { - for (size_t i = 0; i < threads; ++i) { - _threads.emplace_back(std::thread(std::bind(&TaskScheduler::ProcessWork, this))); - } - } +class TaskScheduler +{ +public: + TaskScheduler(); + TaskScheduler(size_t threads); - void Stop() { - if (false == _running) { - return; - } + ~TaskScheduler(); - { - std::unique_lock lock(_lock); - _running = false; - } + void Start(size_t threads); + void Stop(); - _cv.notify_all(); + template + auto Enqueue(Fn&& fn, Args&&... args) -> std::future::type> + { + using return_type = typename std::invoke_result::type; - for (auto &t : _threads) { - t.join(); - } - } - - template - auto Enqueue(Fn&& fn, Args&&... args) -> std::future::type> { - using return_type = typename std::invoke_result::type; - - auto task = std::make_shared>( - std::bind(std::forward(fn), std::forward(args)...) - ); - - std::future res = task->get_future(); - { - std::unique_lock lock(_lock); - - if (false == _running) { - throw std::runtime_error("Enqueue on stopped scheduler."); - } - - _tasks.emplace([task]() { (*task)(); }); - } - - _cv.notify_one(); - return res; + auto task = std::make_shared>( + [fn = std::forward(fn), ...args = std::forward(args)]() mutable + { + return fn(std::forward(args)...); } + ); - private: - void ProcessWork() { - for (;;) { - std::function work; - - { - std::unique_lock lock(_lock); - _cv.wait(lock, [this] { return !_running || !_tasks.empty(); }); - - if (false == _running) { - return; - } + AddTask([task] { (*task)(); }); + return task->get_future(); + } - work = std::move(_tasks.front()); - _tasks.pop(); - } +private: + void AddTask(std::function&& task); + void ProcessWork(); - work(); - } - - } + struct SchedulerData; + std::unique_ptr m_data; +}; - bool _running = true; - std::vector _threads; - std::mutex _lock; - std::condition_variable _cv; - std::queue> _tasks; - }; - } -} +} // namespace EQ::Event diff --git a/common/event/timer.cpp b/common/event/timer.cpp new file mode 100644 index 0000000000..be541c4523 --- /dev/null +++ b/common/event/timer.cpp @@ -0,0 +1,90 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ + +#include "common/event/timer.h" +#include "uv.h" + +namespace EQ { + +Timer::Timer(callback_t cb) + : m_cb(std::move(cb)) +{ +} + +Timer::Timer(uint64_t duration_ms, bool repeats, callback_t cb) + : m_cb(std::move(cb)) +{ + Start(duration_ms, repeats); +} + +Timer::~Timer() +{ + Stop(); +} + +void Timer::Start(uint64_t duration_ms, bool repeats) +{ + if (!m_timer) + { + uv_loop_t* loop = EventLoop::Get().Handle(); + + m_timer = std::make_unique(); + memset(m_timer.get(), 0, sizeof(uv_timer_t)); + + uv_timer_init(loop, m_timer.get()); + m_timer->data = this; + + if (repeats) + { + uv_timer_start(m_timer.get(), [](uv_timer_t* handle) + { + Timer* t = static_cast(handle->data); + t->Execute(); + }, duration_ms, duration_ms); + } + else + { + uv_timer_start(m_timer.get(), + [](uv_timer_t* handle) + { + Timer* t = static_cast(handle->data); + t->Stop(); + t->Execute(); + }, duration_ms, 0); + } + } +} + +void Timer::Stop() +{ + if (m_timer) + { + uv_close(reinterpret_cast(m_timer.release()), + [](uv_handle_t* handle) + { + delete reinterpret_cast(handle); + }); + } +} + +void Timer::Execute() +{ + m_cb(this); +} + +} // namespace EQ diff --git a/common/event/timer.h b/common/event/timer.h index 2cea8072b2..61780dfe30 100644 --- a/common/event/timer.h +++ b/common/event/timer.h @@ -19,69 +19,31 @@ #include "event_loop.h" -#include #include +#include + +typedef struct uv_timer_s uv_timer_t; namespace EQ { - class Timer - { - public: - Timer(std::function cb) - { - m_timer = nullptr; - m_cb = cb; - } - Timer(uint64_t duration_ms, bool repeats, std::function cb) - { - m_timer = nullptr; - m_cb = cb; - Start(duration_ms, repeats); - } - - ~Timer() - { - Stop(); - } +class Timer +{ +public: + using callback_t = std::function; - void Start(uint64_t duration_ms, bool repeats) { - auto loop = EventLoop::Get().Handle(); - if (!m_timer) { - m_timer = new uv_timer_t; - memset(m_timer, 0, sizeof(uv_timer_t)); - uv_timer_init(loop, m_timer); - m_timer->data = this; + Timer(callback_t cb); + Timer(uint64_t duration_ms, bool repeats, callback_t cb); + + ~Timer(); - if (repeats) { - uv_timer_start(m_timer, [](uv_timer_t *handle) { - Timer *t = (Timer*)handle->data; - t->Execute(); - }, duration_ms, duration_ms); - } - else { - uv_timer_start(m_timer, [](uv_timer_t *handle) { - Timer *t = (Timer*)handle->data; - t->Stop(); - t->Execute(); - }, duration_ms, 0); - } - } - } + void Start(uint64_t duration_ms, bool repeats); + void Stop(); - void Stop() { - if (m_timer) { - uv_close((uv_handle_t*)m_timer, [](uv_handle_t* handle) { - delete (uv_timer_t *)handle; - }); - m_timer = nullptr; - } - } - private: - void Execute() { - m_cb(this); - } +private: + void Execute(); - uv_timer_t *m_timer; - std::function m_cb; - }; -} + std::unique_ptr m_timer; + callback_t m_cb; +}; + +} // namespace EQ diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index fd756f37a8..421e9d9269 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -56,12 +56,12 @@ void PlayerEventLogs::Init() auto s = PlayerEventLogSettingsRepository::All(*m_database); std::vector db{}; db.reserve(s.size()); - for (auto &e: s) { + for (auto& e: s) { if (e.id >= PlayerEvent::MAX) { continue; } m_settings[e.id] = e; - db.emplace_back(e.id); + db.emplace_back(static_cast(e.id)); } std::vector settings_to_insert{}; diff --git a/common/guilds.h b/common/guilds.h index eb746a00a8..7e786c776a 100644 --- a/common/guilds.h +++ b/common/guilds.h @@ -46,7 +46,7 @@ #define GUILD_INITIATE 7 #define GUILD_RECRUIT 8 -typedef enum { +enum GuildAction { GUILD_ACTION_BANNER_CHANGE = 1, GUILD_ACTION_BANNER_PLANT = 2, GUILD_ACTION_BANNER_REMOVE = 3, @@ -77,6 +77,6 @@ typedef enum { GUILD_ACTION_REAL_ESTATE_GUILD_PLOT_SELL = 28, GUILD_ACTION_REAL_ESTATE_MODIFY_TROPHIES = 29, GUILD_ACTION_MEMBERS_DEMOTE_SELF = 30, -} GuildAction; +}; constexpr int format_as(GuildAction action) { return static_cast(action); } diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index e8cb95d84b..2ec3d6a081 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -349,7 +349,7 @@ bool EQ::InventoryProfile::SwapItem( fail_state = swapLevel; return false; } - if (source_item_instance->IsEvolving() > 0) { + if (source_item_instance->IsEvolving()) { source_item_instance->SetEvolveEquipped(true); } } diff --git a/common/ip_util.cpp b/common/ip_util.cpp index c1af78263e..0801fb370b 100644 --- a/common/ip_util.cpp +++ b/common/ip_util.cpp @@ -25,14 +25,24 @@ #include "common/net/dns.h" #include "fmt/format.h" -#include -#include +#include +#include #include -/** - * @param ip - * @return - */ +#ifdef _WIN32 +#include +#include +#pragma comment(lib, "Ws2_32.lib") +#else +#include +#include +#include +#include +#include +#include +#endif + + uint32_t IpUtil::IPToUInt(const std::string &ip) { int a, b, c, d; @@ -49,12 +59,6 @@ uint32_t IpUtil::IPToUInt(const std::string &ip) return addr; } -/** - * @param ip - * @param network - * @param mask - * @return - */ bool IpUtil::IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask) { uint32_t ip_addr = IpUtil::IPToUInt(ip); @@ -67,10 +71,6 @@ bool IpUtil::IsIpInRange(const std::string &ip, const std::string &network, cons return ip_addr >= net_lower && ip_addr <= net_upper; } -/** - * @param ip - * @return - */ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip) { return ( @@ -80,30 +80,13 @@ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip) ); } - -#ifdef _WIN32 -#include - #include - #pragma comment(lib, "Ws2_32.lib") -#else -#include -#include -#include -#include -#include -#endif - -#include -#include -#include - std::string IpUtil::GetLocalIPAddress() { #ifdef _WIN32 WSADATA wsaData; - if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { - return ""; - } + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + return ""; + } #endif char my_ip_address[INET_ADDRSTRLEN]; @@ -114,10 +97,10 @@ std::string IpUtil::GetLocalIPAddress() // Create a UDP socket #ifdef _WIN32 sockfd = socket(AF_INET, SOCK_DGRAM, 0); - if (sockfd == INVALID_SOCKET) { - WSACleanup(); - return ""; - } + if (sockfd == INVALID_SOCKET) { + WSACleanup(); + return ""; + } #else sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { @@ -200,98 +183,24 @@ std::string IpUtil::GetPublicIPAddress() return {}; } -std::string IpUtil::DNSLookupSync(const std::string &addr, int port) -{ - auto task_runner = new EQ::Event::TaskScheduler(); - auto res = task_runner->Enqueue( - [&]() -> std::string { - bool running = true; - std::string ret; - - EQ::Net::DNSLookup( - addr, port, false, [&](const std::string &addr) { - ret = addr; - if (addr.empty()) { - ret = ""; - running = false; - } - - return ret; - } - ); - - std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); - - auto &loop = EQ::EventLoop::Get(); - while (running) { - if (!ret.empty()) { - running = false; - } - - std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); - if (std::chrono::duration_cast(end - begin).count() > 1500) { - LogInfo( - "Deadline exceeded [{}]", - 1500 - ); - running = false; - } - - loop.Process(); - } - - return ret; - } - ); - - std::string result = res.get(); - safe_delete(task_runner); - - return result; -} - bool IpUtil::IsIPAddress(const std::string &ip_address) { - struct sockaddr_in sa{}; - int result = inet_pton(AF_INET, ip_address.c_str(), &(sa.sin_addr)); + sockaddr_in sa{}; + int result = inet_pton(AF_INET, ip_address.c_str(), &(sa.sin_addr)); return result != 0; } -#include -#ifdef _WIN32 -#include - #pragma comment(lib, "ws2_32.lib") // Link against Winsock library -#else -#include -#include -#include -#include -#endif - -#include -#include -#ifdef _WIN32 -#include - #include // For inet_pton - #pragma comment(lib, "ws2_32.lib") // Link against Winsock library -#else -#include -#include -#include -#include // For inet_pton -#include -#endif - -bool IpUtil::IsPortInUse(const std::string& ip, int port) { +bool IpUtil::IsPortInUse(const std::string& ip, int port) +{ bool in_use = false; #ifdef _WIN32 WSADATA wsaData; - if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { - std::cerr << "WSAStartup failed\n"; - return true; // Assume in use on failure - } + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + std::cerr << "WSAStartup failed\n"; + return true; // Assume in use on failure + } #endif int sock = socket(AF_INET, SOCK_STREAM, 0); @@ -319,20 +228,20 @@ bool IpUtil::IsPortInUse(const std::string& ip, int port) { std::cerr << "Invalid IP address format: " << ip << std::endl; #ifdef _WIN32 closesocket(sock); - WSACleanup(); + WSACleanup(); #else close(sock); #endif return true; // Assume in use on failure } - if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + if (bind(sock, (sockaddr*)&addr, sizeof(addr)) < 0) { in_use = true; // Bind failed, port is in use } #ifdef _WIN32 closesocket(sock); - WSACleanup(); + WSACleanup(); #else close(sock); #endif diff --git a/common/ip_util.h b/common/ip_util.h index 9d04263d4a..f779bf875f 100644 --- a/common/ip_util.h +++ b/common/ip_util.h @@ -29,10 +29,7 @@ class IpUtil { static bool IsIpInPrivateRfc1918(const std::string &ip); static std::string GetLocalIPAddress(); static std::string GetPublicIPAddress(); - static std::string DNSLookupSync( - const std::string &addr, - int port - ); + static bool IsIPAddress(const std::string &ip_address); static bool IsPortInUse(const std::string& ip, int port); diff --git a/common/item_instance.cpp b/common/item_instance.cpp index 4862d103c7..39271ba8e6 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -320,6 +320,7 @@ bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augment_type, uint8 slot) co } return ( + slot < invaug::SOCKET_COUNT && ( augment_type == -1 || ( diff --git a/common/loot.h b/common/loot.h index 9830585b89..f1a7e329df 100644 --- a/common/loot.h +++ b/common/loot.h @@ -45,5 +45,4 @@ struct LootItem { uint32 lootdrop_id; // required for zone state referencing }; -typedef std::list LootItems; - +using LootItems = std::list; diff --git a/common/memory/ksm.cpp b/common/memory/ksm.cpp new file mode 100644 index 0000000000..0179a2426e --- /dev/null +++ b/common/memory/ksm.cpp @@ -0,0 +1,192 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ +#include "ksm.h" + + +#ifdef _WIN32 +#include +#else +#include // For madvise +#include // For sysconf, sbrk +#endif + +#ifdef _WIN32 +// Windows-specific functionality + +void* PageAlignedAllocatorBase::allocateInternal(size_t size, size_t alignment) +{ + void* ptr = malloc(size); + + if (!ptr) + { + throw std::bad_alloc(); + } + + return ptr; +} + +size_t PageAlignedAllocatorBase::getPageSize() const +{ + SYSTEM_INFO sysInfo; + GetSystemInfo(&sysInfo); + return sysInfo.dwPageSize; // Page size in bytes +} + +namespace KSM { + +// Windows-specific placeholder functions (no-op) +void CheckPageAlignment(void* ptr) +{ +} + +void* AllocatePageAligned(size_t size) +{ + return memset(malloc(size), 0, size); +} + +void MarkMemoryForKSM(void* start, size_t size) +{ +} + +void AlignHeapToPageBoundary() +{ +} + +void* MarkHeapStart() +{ + return nullptr; +} + +size_t MeasureHeapUsage(void* start) +{ + return 0; +} + +} // namespace KSM + +#else + +// Linux-specific functionality + +void* PageAlignedAllocatorBase::allocateInternal(size_t size, size_t alignment) +{ + void* ptr = nullptr; + + if (posix_memalign(&ptr, alignment, size) != 0) + { + throw std::bad_alloc(); + } + + return ptr; +} + +size_t PageAlignedAllocatorBase::getPageSize() const +{ + return static_cast(sysconf(_SC_PAGESIZE)); +} + +namespace KSM { + +void CheckPageAlignment(void* ptr) +{ + size_t page_size = sysconf(_SC_PAGESIZE); + + if (reinterpret_cast(ptr) % page_size == 0) + { + LogKSMDetail("Memory is page-aligned [{}]", ptr); + } + else + { + LogKSMDetail("Memory is NOT page-aligned [{}]", ptr); + } +} + +void* AllocatePageAligned(size_t size) +{ + size_t page_size = sysconf(_SC_PAGESIZE); + void* aligned_ptr = nullptr; + + if (posix_memalign(&aligned_ptr, page_size, size) != 0) + { + LogKSM("Failed to allocate page-aligned memory on Linux. page_size [{}] size [{}] bytes", page_size, size); + } + + std::memset(aligned_ptr, 0, size); + return aligned_ptr; +} + +void MarkMemoryForKSM(void* start, size_t size) +{ + if (madvise(start, size, MADV_MERGEABLE) == 0) + { + LogKSM("Marked memory for KSM | start [{}] size [{}] bytes", start, size); + } + else + { + perror("madvise failed"); + } +} + +void AlignHeapToPageBoundary() +{ + size_t page_size = sysconf(_SC_PAGESIZE); + if (page_size == 0) + { + LogKSM("Failed to retrieve page size SC_PAGESIZE [{}]", page_size); + return; + } + + void* current_break = sbrk(0); + if (current_break == (void*)-1) + { + LogKSM("Failed to retrieve the current program break"); + return; + } + + uintptr_t current_address = reinterpret_cast(current_break); + size_t misalignment = current_address % page_size; + + if (misalignment != 0) + { + size_t adjustment = page_size - misalignment; + if (sbrk(adjustment) == (void*)-1) + { + LogKSM("Failed to align heap to page boundary. adjustment [{}] bytes", adjustment); + return; + } + } + + LogKSMDetail("Heap aligned to next page boundary. Current break [{}]", sbrk(0)); +} + +void* MarkHeapStart() +{ + void* current_pos = sbrk(0); + AlignHeapToPageBoundary(); + return current_pos; +} + +size_t MeasureHeapUsage(void* start) +{ + void* current_break = sbrk(0); + return static_cast(current_break) - static_cast(start); +} + +} // namespace KSM + +#endif diff --git a/common/memory/ksm.h b/common/memory/ksm.h new file mode 100644 index 0000000000..2d9c272ba1 --- /dev/null +++ b/common/memory/ksm.h @@ -0,0 +1,74 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ +#pragma once + +#include "common/eqemu_logsys.h" + +class PageAlignedAllocatorBase +{ +protected: + void* allocateInternal(size_t amount, size_t alignment); + size_t getPageSize() const; +}; + +// Page-aligned allocator for std::vector +template +class PageAlignedAllocator : public PageAlignedAllocatorBase +{ +public: + using value_type = T; + + PageAlignedAllocator() noexcept = default; + + template + PageAlignedAllocator(const PageAlignedAllocator&) noexcept {} + + T* allocate(std::size_t n) + { + size_t size = n * sizeof(T); + + return static_cast(allocateInternal(size, getPageSize())); + } + + void deallocate(T* p, std::size_t) noexcept + { + free(p); + } +}; + +template +bool operator==(const PageAlignedAllocator&, const PageAlignedAllocator&) noexcept { + return true; +} + +template +bool operator!=(const PageAlignedAllocator&, const PageAlignedAllocator&) noexcept { + return false; +} + +// Kernel Samepage Merging (KSM) functionality +namespace KSM { + +void CheckPageAlignment(void* ptr); +void* AllocatePageAligned(size_t size); +void MarkMemoryForKSM(void* start, size_t size); +void AlignHeapToPageBoundary(); +void* MarkHeapStart(); +size_t MeasureHeapUsage(void* start); + +} // namespace KSM diff --git a/common/memory/ksm.hpp b/common/memory/ksm.hpp deleted file mode 100644 index 9d4b282737..0000000000 --- a/common/memory/ksm.hpp +++ /dev/null @@ -1,234 +0,0 @@ -/* EQEmu: EQEmulator - - Copyright (C) 2001-2026 EQEmu Development Team - - 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; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; 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, see . -*/ -#pragma once - -#include "common/eqemu_logsys.h" - -#include -#include -#include -#ifdef _WIN32 -#include // For _aligned_malloc, _aligned_free -#include -#else -#include // For madvise -#include // For sysconf, sbrk -#endif - - -// Page-aligned allocator for std::vector -template -class PageAlignedAllocator { -public: - using value_type = T; - - PageAlignedAllocator() noexcept = default; - template - PageAlignedAllocator(const PageAlignedAllocator&) noexcept {} - - T* allocate(std::size_t n) { - void* ptr = nullptr; - size_t size = n * sizeof(T); - -#ifdef _WIN32 - // Simply allocate memory without alignment - ptr = malloc(size); - if (!ptr) throw std::bad_alloc(); -#else - size_t alignment = getPageSize(); // Get the system's page size - if (posix_memalign(&ptr, alignment, size) != 0) { - throw std::bad_alloc(); - } -#endif - return static_cast(ptr); - } - - void deallocate(T* p, std::size_t) noexcept { - free(p); - } - -private: - size_t getPageSize() const - { -#ifdef _WIN32 - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); - return sysInfo.dwPageSize; // Page size in bytes -#else - return static_cast(sysconf(_SC_PAGESIZE)); -#endif - }; -}; - -template -bool operator==(const PageAlignedAllocator&, const PageAlignedAllocator&) noexcept { - return true; -} - -template -bool operator!=(const PageAlignedAllocator&, const PageAlignedAllocator&) noexcept { - return false; -} - -// Kernel Samepage Merging (KSM) functionality -namespace KSM { - -#ifdef _WIN32 - // Windows-specific placeholder functions (no-op) - inline void CheckPageAlignment(void* ptr) { - } - - inline void* AllocatePageAligned(size_t size) { - return memset(malloc(size), 0, size); - } - - inline void MarkMemoryForKSM(void* start, size_t size) { - } - - inline void AlignHeapToPageBoundary() { - } - - inline void* MarkHeapStart() { - return nullptr; - } - - inline size_t MeasureHeapUsage(void* start) { - return 0; - } -#else - // Linux-specific functionality - inline void CheckPageAlignment(void* ptr) { - size_t page_size = sysconf(_SC_PAGESIZE); - if (reinterpret_cast(ptr) % page_size == 0) { - LogKSMDetail("Memory is page-aligned [{}]", ptr); - } else { - LogKSMDetail("Memory is NOT page-aligned [{}]", ptr); - } - } - - inline void* AllocatePageAligned(size_t size) { - size_t page_size = sysconf(_SC_PAGESIZE); - void* aligned_ptr = nullptr; - if (posix_memalign(&aligned_ptr, page_size, size) != 0) { - LogKSM("Failed to allocate page-aligned memory on Linux. page_size [{}] size [{}] bytes", page_size, size); - } - std::memset(aligned_ptr, 0, size); - return aligned_ptr; - } - - inline void MarkMemoryForKSM(void* start, size_t size) { - if (madvise(start, size, MADV_MERGEABLE) == 0) { - LogKSM("Marked memory for KSM | start [{}] size [{}] bytes", start, size); - } else { - perror("madvise failed"); - } - } - - inline void AlignHeapToPageBoundary() { - size_t page_size = sysconf(_SC_PAGESIZE); - if (page_size == 0) { - LogKSM("Failed to retrieve page size SC_PAGESIZE [{}]", page_size); - return; - } - - void* current_break = sbrk(0); - if (current_break == (void*)-1) { - LogKSM("Failed to retrieve the current program break"); - return; - } - - uintptr_t current_address = reinterpret_cast(current_break); - size_t misalignment = current_address % page_size; - - if (misalignment != 0) { - size_t adjustment = page_size - misalignment; - if (sbrk(adjustment) == (void*)-1) { - LogKSM("Failed to align heap to page boundary. adjustment [{}] bytes", adjustment); - return; - } - } - - LogKSMDetail("Heap aligned to next page boundary. Current break [{}]", sbrk(0)); - } - - inline void* MarkHeapStart() { - void* current_pos = sbrk(0); - AlignHeapToPageBoundary(); - return current_pos; - } - - inline size_t MeasureHeapUsage(void* start) { - void* current_break = sbrk(0); - return static_cast(current_break) - static_cast(start); - } -#endif - - - inline size_t getPageSize() - { -#ifdef _WIN32 - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); - return sysInfo.dwPageSize; // Page size in bytes -#else - return static_cast(sysconf(_SC_PAGESIZE)); // POSIX page size -#endif - }; - - template - inline void PageAlignVectorAligned(std::vector>& vec) { - if (vec.empty()) { - return; - } - - size_t page_size = getPageSize(); - void* start = vec.data(); - size_t size = vec.size() * sizeof(T); - - // Check if the memory is page-aligned - if (reinterpret_cast(start) % page_size != 0) { - // Allocate a new aligned vector - std::vector> aligned_vec(vec.get_allocator()); - aligned_vec.reserve(vec.capacity()); // Match capacity to avoid reallocation during copy - - // Copy elements from the original vector - aligned_vec.insert(aligned_vec.end(), vec.begin(), vec.end()); - - // Swap the aligned vector with the original vector - vec.swap(aligned_vec); - - // Clear the temporary aligned vector to free its memory - aligned_vec.clear(); - - // Verify the new alignment - start = vec.data(); - if (reinterpret_cast(start) % page_size != 0) { - throw std::runtime_error("Failed to align vector memory to page boundaries."); - } - - LogKSMDetail("Vector reallocated to ensure page alignment. start [{}] size [{}] bytes", start, size); - } else { - LogKSMDetail("Vector is already page-aligned. start [{}] size [{}] bytes", start, size); - } - -#ifndef _WIN32 - // Mark memory for KSM (only on non-Windows systems) - MarkMemoryForKSM(start, size); -#endif - } -} diff --git a/common/mutex.cpp b/common/mutex.cpp deleted file mode 100644 index f8c1db00d0..0000000000 --- a/common/mutex.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* EQEmu: EQEmulator - - Copyright (C) 2001-2026 EQEmu Development Team - - 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; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; 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, see . -*/ -#include "mutex.h" - -#include - -#define DEBUG_MUTEX_CLASS 0 -#if DEBUG_MUTEX_CLASS >= 1 -#endif - -#ifdef _WINDOWS -bool IsTryLockSupported(); -bool TrylockSupported = IsTryLockSupported(); - -bool IsTryLockSupported() { - OSVERSIONINFOEX osvi; - BOOL bOsVersionInfoEx; - - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - - if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) ) - { - // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. - osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); - if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) { -#if DEBUG_MUTEX_CLASS >= 1 - std::cout << "Mutex::trylock() NOT supported" << std::endl; -#endif - return false; - } - } - - // Tests for Windows NT product family. - if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 4) { -#if DEBUG_MUTEX_CLASS >= 1 - std::cout << "Mutex::trylock() SUPPORTED" << std::endl; -#endif - return true; - } - else { -#if DEBUG_MUTEX_CLASS >= 1 - std::cout << "Mutex::trylock() NOT supported" << std::endl; -#endif - return false; - } -} -#endif - -Mutex::Mutex() { - -#if DEBUG_MUTEX_CLASS >= 7 - std::cout << "Constructing Mutex" << std::endl; -#endif -#ifdef _WINDOWS - InitializeCriticalSection(&CSMutex); -#else - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); -#if defined(__CYGWIN__) || defined(__APPLE__) || defined(FREEBSD) - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); -#else - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); -#endif - pthread_mutex_init(&CSMutex, &attr); - pthread_mutexattr_destroy(&attr); -#endif -} - -Mutex::~Mutex() { -#ifdef _WINDOWS - DeleteCriticalSection(&CSMutex); -#else -#endif -} - -void Mutex::lock() { -#if DEBUG_MUTEX_CLASS >= 5 - if (!trylock()) { - std::cout << "Locking Mutex: Having to wait" << std::endl; - #ifdef _WINDOWS - EnterCriticalSection(&CSMutex); - #else - pthread_mutex_lock(&CSMutex); - #endif - } -#else - #ifdef _WINDOWS - EnterCriticalSection(&CSMutex); - #else - pthread_mutex_lock(&CSMutex); - #endif -#endif -} - -bool Mutex::trylock() { -#ifdef _WINDOWS - #if(_WIN32_WINNT >= 0x0400) - if (TrylockSupported) - return TryEnterCriticalSection(&CSMutex); - else { - EnterCriticalSection(&CSMutex); - return true; - } - #else - EnterCriticalSection(&CSMutex); - return true; - #endif -#else - return (pthread_mutex_trylock(&CSMutex) == 0); -#endif -} - -void Mutex::unlock() { -#ifdef _WINDOWS - LeaveCriticalSection(&CSMutex); -#else - pthread_mutex_unlock(&CSMutex); -#endif -} - - -LockMutex::LockMutex(Mutex* in_mut, bool iLock) { - mut = in_mut; - locked = iLock; - if (locked) { - mut->lock(); - } -} - -LockMutex::~LockMutex() { - if (locked) { - mut->unlock(); - } -} - -void LockMutex::unlock() { - if (locked) - mut->unlock(); - locked = false; -} - -void LockMutex::lock() { - if (!locked) - mut->lock(); - locked = true; -} diff --git a/common/mysql_stmt.cpp b/common/mysql_stmt.cpp index 8665c16f97..53a45b3272 100644 --- a/common/mysql_stmt.cpp +++ b/common/mysql_stmt.cpp @@ -18,7 +18,6 @@ #include "mysql_stmt.h" #include "common/eqemu_logsys.h" -#include "common/mutex.h" #include "common/timer.h" #include @@ -31,14 +30,19 @@ void PreparedStmt::StmtDeleter::operator()(MYSQL_STMT* stmt) noexcept // The connection must be locked when closing the stmt to avoid mysql errors // in case another thread tries to use it during the close. If the mutex is // changed to one that throws then exceptions need to be caught here. - LockMutex lock(mutex); + std::scoped_lock lock(mutex); + mysql_stmt_close(stmt); } -PreparedStmt::PreparedStmt(MYSQL& mysql, std::string query, Mutex* mutex, StmtOptions opts) - : m_stmt(mysql_stmt_init(&mysql), { mutex }), m_query(std::move(query)), m_mutex(mutex), m_options(opts) +PreparedStmt::PreparedStmt(MYSQL& mysql, std::string query, DBcore::Mutex& mutex, StmtOptions opts) + : m_stmt(mysql_stmt_init(&mysql), { mutex }) + , m_query(std::move(query)) + , m_options(opts) + , m_mutex(mutex) { - LockMutex lock(m_mutex); + std::scoped_lock lock(m_mutex); + if (mysql_stmt_prepare(m_stmt.get(), m_query.c_str(), static_cast(m_query.size())) != 0) { ThrowError(fmt::format("Prepare error: {}", GetStmtError())); @@ -186,7 +190,7 @@ void PreparedStmt::CheckArgs(size_t argc) StmtResult PreparedStmt::DoExecute() { BenchTimer timer; - LockMutex lock(m_mutex); + std::scoped_lock lock(m_mutex); if (m_need_bind && mysql_stmt_bind_param(m_stmt.get(), m_params.data()) != 0) { diff --git a/common/mysql_stmt.h b/common/mysql_stmt.h index 63cda89d3e..2402d02e03 100644 --- a/common/mysql_stmt.h +++ b/common/mysql_stmt.h @@ -17,10 +17,12 @@ */ #pragma once -#include "mysql.h" +#include "common/dbcore.h" + #include #include #include +#include #include #include #include @@ -183,7 +185,7 @@ class PreparedStmt int64_t, uint64_t, float, double, bool, std::string_view, std::nullptr_t>; PreparedStmt() = delete; - PreparedStmt(MYSQL& mysql, std::string query, Mutex* mutex, StmtOptions opts = {}); + PreparedStmt(MYSQL& mysql, std::string query, DBcore::Mutex& mutex, StmtOptions opts = {}); const std::string& GetQuery() const { return m_query; } StmtOptions GetOptions() const { return m_options; } @@ -219,7 +221,8 @@ class PreparedStmt struct StmtDeleter { - Mutex* mutex = nullptr; + DBcore::Mutex& mutex; + void operator()(MYSQL_STMT* stmt) noexcept; }; @@ -232,7 +235,7 @@ class PreparedStmt std::string m_query; StmtOptions m_options = {}; bool m_need_bind = true; - Mutex* m_mutex = nullptr; // connection mutex + DBcore::Mutex& m_mutex; // connection mutex }; } // namespace mysql diff --git a/common/net/dns.cpp b/common/net/dns.cpp new file mode 100644 index 0000000000..fa232586c2 --- /dev/null +++ b/common/net/dns.cpp @@ -0,0 +1,131 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ + +#include "dns.h" + +#include "common/eqemu_logsys.h" +#include "common/event/event_loop.h" +#include "common/event/task_scheduler.h" + +#include "uv.h" + +namespace EQ::Net { + +struct DNSBaton +{ + dns_callback_t cb; + bool ipv6; +}; + +void DNSLookup(const std::string& addr, int port, bool ipv6, dns_callback_t cb) +{ + addrinfo hints = {}; + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + uv_loop_t* loop = EQ::EventLoop::Get().Handle(); + + uv_getaddrinfo_t* resolver = new uv_getaddrinfo_t(); + memset(resolver, 0, sizeof(uv_getaddrinfo_t)); + std::string port_str = std::to_string(port); + DNSBaton* baton = new DNSBaton(); + baton->cb = std::move(cb); + baton->ipv6 = ipv6; + resolver->data = baton; + + uv_getaddrinfo(loop, resolver, [](uv_getaddrinfo_t* req, int status, addrinfo* result) + { + DNSBaton* baton = static_cast(req->data); + + dns_callback_t dns_callback = std::move(baton->cb); + bool ipv6 = baton->ipv6; + + delete baton; + delete req; + + if (status < 0) + { + dns_callback({}); + return; + } + + char addr[40] = {}; + + if (ipv6) + { + uv_ip6_name(reinterpret_cast(result->ai_addr), addr, 40); + } + else + { + uv_ip4_name(reinterpret_cast(result->ai_addr), addr, 40); + } + + uv_freeaddrinfo(result); + + dns_callback(addr); + }, addr.c_str(), port_str.c_str(), &hints); +} + +std::string DNSLookupSync(const std::string& addr, int port, bool ipv6 /* = false */) +{ + EQ::Event::TaskScheduler task_runner; + + auto res = task_runner.Enqueue( + [addr, port, ipv6]() -> std::string + { + bool running = true; + std::string ret; + + EQ::Net::DNSLookup( + addr, port, ipv6, [&](const std::string& addr) { + ret = addr; + running = !addr.empty(); + + return ret; + } + ); + + std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + + auto& loop = EQ::EventLoop::Get(); + while (running) { + if (!ret.empty()) { + running = false; + } + + std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); + if (std::chrono::duration_cast(end - begin).count() > 1500) { + LogInfo( + "Deadline exceeded [{}]", + 1500 + ); + running = false; + } + + loop.Process(); + } + + return ret; + }); + + return res.get(); +} + + +} // namespace EQ::Net diff --git a/common/net/dns.h b/common/net/dns.h index 2b799ef4fc..04f97a4e9b 100644 --- a/common/net/dns.h +++ b/common/net/dns.h @@ -17,63 +17,15 @@ */ #pragma once -#include "common/event/event_loop.h" - #include #include -namespace EQ -{ - namespace Net - { - static void DNSLookup(const std::string &addr, int port, bool ipv6, std::function cb) { - struct DNSBaton - { - std::function cb; - bool ipv6; - }; - - addrinfo hints; - memset(&hints, 0, sizeof(addrinfo)); - hints.ai_family = PF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - auto loop = EQ::EventLoop::Get().Handle(); - uv_getaddrinfo_t *resolver = new uv_getaddrinfo_t(); - memset(resolver, 0, sizeof(uv_getaddrinfo_t)); - auto port_str = std::to_string(port); - DNSBaton *baton = new DNSBaton(); - baton->cb = cb; - baton->ipv6 = ipv6; - resolver->data = baton; - - uv_getaddrinfo(loop, resolver, [](uv_getaddrinfo_t* req, int status, addrinfo* res) { - DNSBaton *baton = (DNSBaton*)req->data; - if (status < 0) { - auto cb = baton->cb; - delete baton; - delete req; - cb(""); - return; - } +namespace EQ::Net { - char addr[40] = { 0 }; +using dns_callback_t = std::function; - if (baton->ipv6) { - uv_ip6_name((struct sockaddr_in6*)res->ai_addr, addr, 40); - } - else { - uv_ip4_name((struct sockaddr_in*)res->ai_addr, addr, 40); - } +void DNSLookup(const std::string& addr, int port, bool ipv6, dns_callback_t cb); - auto cb = baton->cb; - delete baton; - delete req; - uv_freeaddrinfo(res); +std::string DNSLookupSync(const std::string& addr, int port, bool ipv6 = false); - cb(addr); - }, addr.c_str(), port_str.c_str(), &hints); - } - } -} +} // namespace EQ::Net diff --git a/common/net/tcp_connection.h b/common/net/tcp_connection.h index 7c421c2043..fc0f86f5a3 100644 --- a/common/net/tcp_connection.h +++ b/common/net/tcp_connection.h @@ -19,7 +19,9 @@ #include "common/net/tcp_connection_pooling.h" +#include "common/platform/platform.h" #include "uv.h" + #include #include #include diff --git a/common/net/websocket_server.h b/common/net/websocket_server.h index d69399a8f4..9d0eee91b4 100644 --- a/common/net/websocket_server.h +++ b/common/net/websocket_server.h @@ -49,9 +49,9 @@ namespace EQ WebsocketException(const std::string &msg) : _msg(msg.empty() ? "Unknown Error" : msg) { } - ~WebsocketException() throw() {} + ~WebsocketException() noexcept {} - virtual char const *what() const throw() { + virtual char const *what() const noexcept override { return _msg.c_str(); } private: diff --git a/common/op_codes.h b/common/op_codes.h index fbf0735a64..a488e8c4df 100644 --- a/common/op_codes.h +++ b/common/op_codes.h @@ -17,17 +17,16 @@ */ #pragma once - -static const char OP_SessionRequest = 0x01; -static const char OP_SessionResponse = 0x02; -static const char OP_Combined = 0x03; -static const char OP_SessionDisconnect = 0x05; -static const char OP_KeepAlive = 0x06; -static const char OP_SessionStatRequest = 0x07; -static const char OP_SessionStatResponse= 0x08; -static const char OP_Packet = 0x09; -static const char OP_Fragment = 0x0d; -static const char OP_OutOfOrderAck = 0x11; -static const char OP_Ack = 0x15; -static const char OP_AppCombined = 0x19; -static const char OP_OutOfSession = 0x1d; +static constexpr char OP_SessionRequest = 0x01; +static constexpr char OP_SessionResponse = 0x02; +static constexpr char OP_Combined = 0x03; +static constexpr char OP_SessionDisconnect = 0x05; +static constexpr char OP_KeepAlive = 0x06; +static constexpr char OP_SessionStatRequest = 0x07; +static constexpr char OP_SessionStatResponse = 0x08; +static constexpr char OP_Packet = 0x09; +static constexpr char OP_Fragment = 0x0d; +static constexpr char OP_OutOfOrderAck = 0x11; +static constexpr char OP_Ack = 0x15; +static constexpr char OP_AppCombined = 0x19; +static constexpr char OP_OutOfSession = 0x1d; diff --git a/common/opcodemgr.cpp b/common/opcodemgr.cpp index c14888e7c7..d028d139b9 100644 --- a/common/opcodemgr.cpp +++ b/common/opcodemgr.cpp @@ -142,10 +142,12 @@ RegularOpcodeManager::~RegularOpcodeManager() { safe_delete_array(eq_to_emu); } -bool RegularOpcodeManager::LoadOpcodes(const char *filename, bool report_errors) { +bool RegularOpcodeManager::LoadOpcodes(const char *filename, bool report_errors) +{ + std::scoped_lock lock(MOpcodes); + NormalMemStrategy s; s.it = this; - MOpcodes.lock(); loaded = true; eq_to_emu = new EmuOpcode[MAX_EQ_OPCODE]; @@ -158,32 +160,30 @@ bool RegularOpcodeManager::LoadOpcodes(const char *filename, bool report_errors) memset(emu_to_eq, 0, sizeof(uint16)*_maxEmuOpcode); bool ret = LoadOpcodesFile(filename, &s, report_errors); - MOpcodes.unlock(); return ret; } -bool RegularOpcodeManager::ReloadOpcodes(const char *filename, bool report_errors) { - if(!loaded) - return(LoadOpcodes(filename)); +bool RegularOpcodeManager::ReloadOpcodes(const char* filename, bool report_errors) +{ + if (!loaded) + return LoadOpcodes(filename); + + std::scoped_lock lock(MOpcodes); NormalMemStrategy s; s.it = this; - MOpcodes.lock(); - - memset(eq_to_emu, 0, sizeof(uint16)*MAX_EQ_OPCODE); - - bool ret = LoadOpcodesFile(filename, &s, report_errors); - MOpcodes.unlock(); - return(ret); + memset(eq_to_emu, 0, sizeof(uint16) * MAX_EQ_OPCODE); + return LoadOpcodesFile(filename, &s, report_errors); } uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) { //opcode is checked for validity in GetEQOpcode uint16 res; - MOpcodes.lock(); - res = emu_to_eq[emu_op]; - MOpcodes.unlock(); + { + std::scoped_lock lock(MOpcodes); + res = emu_to_eq[emu_op]; + } LogNetcodeDetail("[Opcode Manager] Translate emu [{}] ({:#06x}) eq [{:#06x}]", OpcodeNames[emu_op], emu_op, res); @@ -193,15 +193,18 @@ uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) { return(res); } -EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op) { +EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op) +{ //opcode is checked for validity in GetEmuOpcode -//Disabled since current live EQ uses the entire uint16 bitspace for opcodes -// if(eq_op > MAX_EQ_OPCODE) -// return(OP_Unknown); + //Disabled since current live EQ uses the entire uint16 bitspace for opcodes + // if(eq_op > MAX_EQ_OPCODE) + // return(OP_Unknown); EmuOpcode res; - MOpcodes.lock(); - res = eq_to_emu[eq_op]; - MOpcodes.unlock(); + { + std::scoped_lock lock(MOpcodes); + res = eq_to_emu[eq_op]; + } + #ifdef DEBUG_TRANSLATE fprintf(stderr, "M Translate EQ 0x%.4x to Emu %s (%d)\n", eq_op, OpcodeNames[res], res); #endif diff --git a/common/opcodemgr.h b/common/opcodemgr.h index 152b652aaf..ba274bf128 100644 --- a/common/opcodemgr.h +++ b/common/opcodemgr.h @@ -18,10 +18,10 @@ #pragma once #include "common/emu_opcodes.h" -#include "common/mutex.h" #include "common/types.h" #include +#include //enable the use of shared mem opcodes for world and zone only #ifdef ZONE @@ -31,7 +31,8 @@ #define SHARED_OPCODES #endif -class OpcodeManager { +class OpcodeManager +{ public: OpcodeManager(); virtual ~OpcodeManager() {} @@ -48,24 +49,27 @@ class OpcodeManager { EmuOpcode NameSearch(const char *name); //This has to be public for stupid visual studio - class OpcodeSetStrategy { + class OpcodeSetStrategy + { public: - virtual ~OpcodeSetStrategy() {} //shut up compiler! + virtual ~OpcodeSetStrategy() = default; virtual void Set(EmuOpcode emu_op, uint16 eq_op) = 0; }; protected: bool loaded; //true if all opcodes loaded - Mutex MOpcodes; //this only protects the local machine + std::mutex MOpcodes; //this only protects the local machine //in a shared manager, this dosent protect others static bool LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s, bool report_errors); }; -class MutableOpcodeManager : public OpcodeManager { +class MutableOpcodeManager : public OpcodeManager +{ public: - MutableOpcodeManager() : OpcodeManager() {} - virtual bool Mutable() { return(true); } + MutableOpcodeManager() = default; + + virtual bool Mutable() override { return true; } virtual void SetOpcode(EmuOpcode emu_op, uint16 eq_op) = 0; }; @@ -108,16 +112,16 @@ class RegularOpcodeManager : public MutableOpcodeManager { virtual void SetOpcode(EmuOpcode emu_op, uint16 eq_op); protected: - class NormalMemStrategy : public OpcodeManager::OpcodeSetStrategy { + class NormalMemStrategy : public OpcodeManager::OpcodeSetStrategy + { public: - virtual ~NormalMemStrategy() {} //shut up compiler! - RegularOpcodeManager *it; - void Set(EmuOpcode emu_op, uint16 eq_op); + RegularOpcodeManager* it; + + virtual void Set(EmuOpcode emu_op, uint16 eq_op) override; }; - friend class NormalMemStrategy; - uint16 *emu_to_eq; - EmuOpcode *eq_to_emu; + uint16* emu_to_eq; + EmuOpcode* eq_to_emu; uint32 EQOpcodeCount; uint32 EmuOpcodeCount; }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 90fc993120..3ce262080f 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -3221,7 +3221,7 @@ namespace RoF buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); dest->FastQueuePacket(&outapp, ack_req); delete in; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index b240fd4b35..992f0c538d 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -689,7 +689,7 @@ namespace RoF2 EQApplicationPacket *outapp = nullptr; if (eq->bufffade == 1) { - outapp = new EQApplicationPacket(OP_BuffCreate, 29); + outapp = new EQApplicationPacket(OP_BuffCreate, 29u); outapp->WriteUInt32(emu->entityid); outapp->WriteUInt32(0); // tic timer outapp->WriteUInt8(0); // Type of OP_BuffCreate packet ? @@ -753,7 +753,7 @@ namespace RoF2 ar(bl); //packet size - auto packet_size = bl.item_name.length() + 1 + 34; + size_t packet_size = bl.item_name.length() + 1 + 34; for (auto const &b: bl.trade_items) { packet_size += b.item_name.length() + 1; packet_size += 12; @@ -1622,7 +1622,7 @@ namespace RoF2 //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Yourname is %s", gu2->yourname); int MemberCount = 1; - int PacketLength = 8 + strlen(gu2->leadersname) + 1 + 22 + strlen(gu2->yourname) + 1; + uint32 PacketLength = 8 + strlen(gu2->leadersname) + 1 + 22 + strlen(gu2->yourname) + 1; for (int i = 0; i < 5; ++i) { @@ -2207,7 +2207,7 @@ namespace RoF2 char *Buffer = (char *)in->pBuffer; - int PacketSize = sizeof(structs::MercenaryMerchantList_Struct) - 4 + emu->MercTypeCount * 4; + uint32 PacketSize = sizeof(structs::MercenaryMerchantList_Struct) - 4 + emu->MercTypeCount * 4; PacketSize += (sizeof(structs::MercenaryListEntry_Struct) - sizeof(structs::MercenaryStance_Struct)) * emu->MercCount; uint32 r; @@ -3820,7 +3820,7 @@ namespace RoF2 buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); dest->FastQueuePacket(&outapp, ack_req); delete in; @@ -4120,8 +4120,8 @@ namespace RoF2 std::begin(emu->items), std::end(emu->items), std::begin(eq->items), - [&](const uint32 x) { - return x; + [&](uint64 x) { + return static_cast(x); } ); std::copy_n( @@ -4599,7 +4599,7 @@ namespace RoF2 int k; for (r = 0; r < entrycount; r++, emu++) { - int PacketSize = 206; + uint32 PacketSize = 206; PacketSize += strlen(emu->name); PacketSize += strlen(emu->lastName); diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 27224e3806..ca8602565a 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -2128,7 +2128,7 @@ namespace SoD buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); dest->FastQueuePacket(&outapp, ack_req); delete in; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 818bc3b8f2..ed72691f6f 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1785,7 +1785,7 @@ namespace SoF buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); dest->FastQueuePacket(&outapp, ack_req); delete in; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index c3fdf479e4..3950943061 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1991,7 +1991,7 @@ namespace Titanium buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); dest->FastQueuePacket(&outapp, ack_req); delete in; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 05c058217e..32f958b35f 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2711,7 +2711,7 @@ namespace UF buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); dest->FastQueuePacket(&outapp, ack_req); delete in; diff --git a/common/platform/win/include_winsock2.h b/common/platform/win/include_winsock2.h index 0aaf30931b..e5410094e4 100644 --- a/common/platform/win/include_winsock2.h +++ b/common/platform/win/include_winsock2.h @@ -19,6 +19,7 @@ #ifdef _WINDOWS +#include "common/platform/win/include_windows.h" #include #endif // _WINDOWS diff --git a/common/process.cpp b/common/process.cpp index 44554f3676..54521715bb 100644 --- a/common/process.cpp +++ b/common/process.cpp @@ -23,11 +23,13 @@ inline std::string random_string(size_t length) { - auto randchar = []() -> char { + auto randchar = []() -> char + { const char charset[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; const size_t max_index = (sizeof(charset) - 1); return charset[static_cast(std::rand()) % max_index]; }; + std::string str(length, 0); std::generate_n(str.begin(), length, randchar); return str; diff --git a/common/serialize_buffer.h b/common/serialize_buffer.h index fb3e2904e4..9e5ba8a9b9 100644 --- a/common/serialize_buffer.h +++ b/common/serialize_buffer.h @@ -27,7 +27,7 @@ class SerializeBuffer { public: - SerializeBuffer() : m_buffer(nullptr), m_capacity(0), m_pos(0) {} + SerializeBuffer() = default; explicit SerializeBuffer(size_t size) : m_capacity(size), m_pos(0) { @@ -35,8 +35,10 @@ class SerializeBuffer memset(m_buffer, 0, size); } - SerializeBuffer(const SerializeBuffer &rhs) - : m_buffer(new unsigned char[rhs.m_capacity]), m_capacity(rhs.m_capacity), m_pos(rhs.m_pos) + SerializeBuffer(const SerializeBuffer& rhs) + : m_buffer(new unsigned char[rhs.m_capacity]) + , m_capacity(rhs.m_capacity) + , m_pos(rhs.m_pos) { memcpy(m_buffer, rhs.m_buffer, rhs.m_capacity); } @@ -53,30 +55,31 @@ class SerializeBuffer return *this; } - SerializeBuffer(SerializeBuffer &&rhs) : m_buffer(rhs.m_buffer), m_capacity(rhs.m_capacity), m_pos(rhs.m_pos) + SerializeBuffer(SerializeBuffer&& rhs) + : m_buffer(std::exchange(rhs.m_buffer, nullptr)) + , m_capacity(std::exchange(rhs.m_capacity, 0)) + , m_pos(std::exchange(rhs.m_pos, 0)) { - rhs.m_buffer = nullptr; - rhs.m_capacity = 0; - rhs.m_pos = 0; } - SerializeBuffer &operator=(SerializeBuffer &&rhs) + SerializeBuffer& operator=(SerializeBuffer&& rhs) { - if (this != &rhs) { + if (this != &rhs) + { delete[] m_buffer; - m_buffer = rhs.m_buffer; - m_capacity = rhs.m_capacity; - m_pos = rhs.m_pos; - - rhs.m_buffer = nullptr; - rhs.m_capacity = 0; - rhs.m_pos = 0; + m_buffer = std::exchange(rhs.m_buffer, nullptr); + m_capacity = std::exchange(rhs.m_capacity, 0); + m_pos = std::exchange(rhs.m_pos, 0); } + return *this; } - ~SerializeBuffer() { delete[] m_buffer; } + ~SerializeBuffer() + { + delete[] m_buffer; + } void WriteUInt8(uint8_t v) { @@ -209,7 +212,8 @@ class SerializeBuffer private: void Grow(size_t new_size); void Reset(); - unsigned char *m_buffer; - size_t m_capacity; - size_t m_pos; + + unsigned char* m_buffer = nullptr; + size_t m_capacity = 0; + size_t m_pos = 0; }; diff --git a/common/servertalk.h b/common/servertalk.h index e550dc5d1f..da30dc4b1b 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -389,35 +389,31 @@ enum { class ServerPacket { public: - ~ServerPacket() { safe_delete_array(pBuffer); } - ServerPacket(uint16 in_opcode = 0, uint32 in_size = 0) { - this->compressed = false; - size = in_size; - opcode = in_opcode; - if (size == 0) { - pBuffer = 0; - } - else { + ~ServerPacket() + { + safe_delete_array(pBuffer); + } + + ServerPacket(uint16 in_opcode = 0, size_t in_size = 0) + : size(static_cast(in_size)) + , opcode(in_opcode) + { + if (size != 0) + { pBuffer = new uchar[size]; memset(pBuffer, 0, size); } - _wpos = 0; - _rpos = 0; } - ServerPacket(uint16 in_opcode, const EQ::Net::Packet &p) { - this->compressed = false; - size = (uint32)p.Length(); - opcode = in_opcode; - if (size == 0) { - pBuffer = 0; - } - else { + ServerPacket(uint16 in_opcode, const EQ::Net::Packet& p) + : size(static_cast(p.Length())) + , opcode(in_opcode) + { + if (size != 0) + { pBuffer = new uchar[size]; memcpy(pBuffer, p.Data(), size); } - _wpos = 0; - _rpos = 0; } ServerPacket* Copy() { @@ -447,14 +443,14 @@ class ServerPacket void ReadSkipBytes(uint32 count) { _rpos += count; } void SetReadPosition(uint32 Newrpos) { _rpos = Newrpos; } - uint32 size; - uint16 opcode; - uchar* pBuffer; - uint32 _wpos; - uint32 _rpos; - bool compressed; - uint32 InflatedSize; - uint32 destination; + uint32 size = 0; + uint16 opcode = 0; + uchar* pBuffer = nullptr; + uint32 _wpos = 0; + uint32 _rpos = 0; + bool compressed = false; + uint32 InflatedSize = 0; + uint32 destination = 0; }; #pragma pack(push) @@ -989,11 +985,12 @@ struct LauncherConnectInfo { char name[64]; }; -typedef enum { +enum ZoneRequestCommands { ZR_Start, ZR_Restart, ZR_Stop -} ZoneRequestCommands; +}; + struct LauncherZoneRequest { uint8 command; char short_name[33]; diff --git a/common/tasks.h b/common/tasks.h index ace848f4dd..2776f66861 100644 --- a/common/tasks.h +++ b/common/tasks.h @@ -38,10 +38,10 @@ #define RELOADTASKS 0 #define RELOADTASKSETS 2 -typedef enum { +enum TaskMethodType { METHODSINGLEID = 0, METHODQUEST = 2 -} TaskMethodType; +}; enum class TaskActivityType : int32_t // task element/objective { diff --git a/libs/luabind/src/inheritance.cpp b/libs/luabind/src/inheritance.cpp index 2e2ec902aa..b70db95e3e 100644 --- a/libs/luabind/src/inheritance.cpp +++ b/libs/luabind/src/inheritance.cpp @@ -94,7 +94,7 @@ namespace { m_cache.insert(std::make_pair( key_type(src, target, dynamic_id, object_offset) - , cache_entry(offset, distance) + , cache_entry(offset, static_cast(distance)) )); } diff --git a/loginserver/client.cpp b/loginserver/client.cpp index d9baf088f5..165ac7bdc4 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -547,7 +547,7 @@ void Client::SendExpansionPacketData(PlayerLoginReply &plrs) buf.WriteInt32(0xFFFFFFFF); } - auto out = std::make_unique(OP_LoginExpansionPacketData, buf); + auto out = std::make_unique(OP_LoginExpansionPacketData, std::move(buf)); m_connection->QueuePacket(out.get()); } diff --git a/loginserver/world_server_manager.cpp b/loginserver/world_server_manager.cpp index 118a58f5c6..d519710bae 100644 --- a/loginserver/world_server_manager.cpp +++ b/loginserver/world_server_manager.cpp @@ -153,7 +153,7 @@ std::unique_ptr WorldServerManager::CreateServerListPacket( s->SerializeForClientServerList(buf, use_local_ip, client->GetClientVersion()); } - return std::make_unique(OP_ServerListResponse, buf); + return std::make_unique(OP_ServerListResponse, std::move(buf)); } void WorldServerManager::SendUserLoginToWorldRequest( diff --git a/world/cli/cli_database_concurrency.cpp b/world/cli/cli_database_concurrency.cpp index 557e141742..6816d1c15d 100644 --- a/world/cli/cli_database_concurrency.cpp +++ b/world/cli/cli_database_concurrency.cpp @@ -20,9 +20,12 @@ #include "common/eqemu_config.h" #include "common/repositories/zone_repository.h" +#include #include #include +using namespace std::chrono_literals; + Database db; Database db2; @@ -60,8 +63,6 @@ void WorldserverCLI::TestDatabaseConcurrency(int argc, char **argv, argh::parser LogInfo("Database test"); - auto mutex = new Mutex; - auto c = EQEmuConfig::get(); LogInfo("Connecting to MySQL"); if (!db.Connect( @@ -75,19 +76,19 @@ void WorldserverCLI::TestDatabaseConcurrency(int argc, char **argv, argh::parser return; } - db.SetMutex(mutex); + std::shared_ptr sharedMutex = std::make_shared(); + + db.SetMutex(sharedMutex); db2.SetMySQL(db); - db2.SetMutex(mutex); + db2.SetMutex(sharedMutex); std::thread(DatabaseTest).detach(); std::thread(DatabaseTest).detach(); std::thread(DatabaseTestSecondConnection).detach(); while (!stop) { - + std::this_thread::sleep_for(0s); } - - safe_delete(mutex); } diff --git a/world/cli/cli_database_version.cpp b/world/cli/cli_database_version.cpp index db2a41b692..907bd95eed 100644 --- a/world/cli/cli_database_version.cpp +++ b/world/cli/cli_database_version.cpp @@ -37,8 +37,5 @@ void WorldserverCLI::DatabaseVersion(int argc, char **argv, argh::parser &cmd, s v["bots_database_version"] = RuleB(Bots, Enabled) ? CURRENT_BINARY_BOTS_DATABASE_VERSION : 0; v["custom_database_version"] = CUSTOM_BINARY_DATABASE_VERSION; - std::stringstream payload; - payload << v; - - std::cout << payload.str() << std::endl; + std::cout << v << std::endl; } diff --git a/world/cli/cli_test.cpp b/world/cli/cli_test.cpp index 0353e48150..4878b4f399 100644 --- a/world/cli/cli_test.cpp +++ b/world/cli/cli_test.cpp @@ -18,7 +18,7 @@ #include "world/world_server_cli.h" #include "common/events/player_events.h" -#include "common/memory/ksm.hpp" +#include "common/memory/ksm.h" #include "cereal/archives/json.hpp" #include "cereal/types/vector.hpp" diff --git a/world/cli/cli_version.cpp b/world/cli/cli_version.cpp index 871b07dbda..30c070ae11 100644 --- a/world/cli/cli_version.cpp +++ b/world/cli/cli_version.cpp @@ -39,8 +39,5 @@ void WorldserverCLI::Version(int argc, char **argv, argh::parser &cmd, std::stri j["database_version"] = CURRENT_BINARY_DATABASE_VERSION; j["server_version"] = CURRENT_VERSION; - std::stringstream payload; - payload << j; - - std::cout << payload.str() << std::endl; + std::cout << j << std::endl; } diff --git a/world/cliententry.h b/world/cliententry.h index a94433b935..3da6cba84d 100644 --- a/world/cliententry.h +++ b/world/cliententry.h @@ -24,14 +24,14 @@ #include -typedef enum { +enum CLE_Status { Never, Offline, Online, CharSelect, Zoning, InZone -} CLE_Status; +}; static const char *CLEStatusString[] = { "Never", diff --git a/world/eql_config.h b/world/eql_config.h index ca3ab3f735..13b9c0a628 100644 --- a/world/eql_config.h +++ b/world/eql_config.h @@ -25,10 +25,10 @@ class LauncherLink; -typedef struct { +struct LauncherZone{ std::string name; uint16 port; -} LauncherZone; +}; //a class exported to perl representing a launcher's in-DB config class EQLConfig { diff --git a/world/launcher_link.h b/world/launcher_link.h index 2e8e6bc20d..d516ccc6b3 100644 --- a/world/launcher_link.h +++ b/world/launcher_link.h @@ -69,10 +69,10 @@ class LauncherLink { uint8 m_dynamicCount; - typedef struct { + struct ZoneState{ bool up; uint32 starts; //number of times this zone has started uint16 port; //the port this zone wants to use (0=pick one) - } ZoneState; + }; std::map m_states; }; diff --git a/world/login_server.h b/world/login_server.h index b5bd5a038c..8929178953 100644 --- a/world/login_server.h +++ b/world/login_server.h @@ -20,7 +20,6 @@ #include "common/eq_packet_structs.h" #include "common/event/timer.h" #include "common/linked_list.h" -#include "common/mutex.h" #include "common/net/servertalk_client_connection.h" #include "common/net/servertalk_legacy_client_connection.h" #include "common/queue.h" diff --git a/world/login_server_list.h b/world/login_server_list.h index 7bd3a812af..1911a54eee 100644 --- a/world/login_server_list.h +++ b/world/login_server_list.h @@ -18,7 +18,6 @@ #pragma once #include "common/eq_packet_structs.h" -#include "common/mutex.h" #include "common/queue.h" #include "common/servertalk.h" #include "common/timer.h" diff --git a/world/shared_task_manager.cpp b/world/shared_task_manager.cpp index d3a9bd2b9f..b9692d222c 100644 --- a/world/shared_task_manager.cpp +++ b/world/shared_task_manager.cpp @@ -319,14 +319,14 @@ void SharedTaskManager::LoadSharedTaskState() // load character data for member names std::vector shared_task_character_data; if (!shared_task_members_data.empty()) { - std::vector character_ids; - for (const auto &m: shared_task_members_data) { + std::vector character_ids; + for (const BaseSharedTaskMembersRepository::SharedTaskMembers& m: shared_task_members_data) { character_ids.emplace_back(m.character_id); } shared_task_character_data = CharacterDataRepository::GetWhere( *m_database, - fmt::format("id IN ({})", Strings::Join(character_ids, ",")) + fmt::format("id IN ({})", fmt::join(character_ids, ",")) ); } diff --git a/world/ucs.h b/world/ucs.h index df3ec9e6dd..884628784b 100644 --- a/world/ucs.h +++ b/world/ucs.h @@ -44,6 +44,6 @@ class UCSConnection private: inline std::string GetIP() const { return (connection && connection->Handle()) ? connection->Handle()->RemoteIP() : 0; } - std::shared_ptr connection; + std::shared_ptr connection; }; diff --git a/world/world_boot.cpp b/world/world_boot.cpp index 7c2afc3889..4bd6c79fd6 100644 --- a/world/world_boot.cpp +++ b/world/world_boot.cpp @@ -24,8 +24,7 @@ #include "common/http/httplib.h" #include "common/http/uri.h" #include "common/ip_util.h" -#include "common/net/console_server.h" -#include "common/net/servertalk_server.h" +#include "common/net/dns.h" #include "common/path_manager.h" #include "common/repositories/character_expedition_lockouts_repository.h" #include "common/repositories/character_task_timers_repository.h" @@ -33,7 +32,6 @@ #include "common/rulesys.h" #include "common/strings.h" #include "common/zone_store.h" -#include "common/zone_store.h" #include "world/adventure_manager.h" #include "world/dynamic_zone_manager.h" #include "world/login_server_list.h" @@ -49,8 +47,6 @@ extern WorldConfig Config; -auto mutex = new Mutex; - void WorldBoot::GMSayHookCallBackProcessWorld(uint16 log_category, const char *func, std::string message) { // we don't want to loop up with chat messages @@ -180,11 +176,13 @@ bool WorldBoot::LoadDatabaseConnections() } else { content_db.SetMySQL(database); + // when database and content_db share the same underlying mysql connection // it needs to be protected by a shared mutex otherwise we produce concurrency issues // when database actions are occurring in different threads - database.SetMutex(mutex); - content_db.SetMutex(mutex); + std::shared_ptr sharedMutex = std::make_shared(); + database.SetMutex(sharedMutex); + content_db.SetMutex(sharedMutex); } return true; @@ -456,7 +454,7 @@ void WorldBoot::CheckForPossibleConfigurationIssues() std::string config_address = c->WorldAddress; if (!IpUtil::IsIPAddress(config_address)) { - config_address = IpUtil::DNSLookupSync(c->WorldAddress, 9000); + config_address = EQ::Net::DNSLookupSync(c->WorldAddress, 9000); LogInfo( "World config address using DNS [{}] resolves to [{}]", c->WorldAddress, @@ -634,7 +632,6 @@ void WorldBoot::CheckForPossibleConfigurationIssues() void WorldBoot::Shutdown() { - safe_delete(mutex); } void WorldBoot::SendDiscordMessage(int webhook_id, const std::string &message) diff --git a/zone/aa.h b/zone/aa.h index f5e015bc1b..61ae79940b 100644 --- a/zone/aa.h +++ b/zone/aa.h @@ -20,7 +20,7 @@ #define MAX_SWARM_PETS 12 //this can change as long as you make more coords (swarm_pet_x/swarm_pet_y) #define WAKE_THE_DEAD_NPCTYPEID 500 //We use first pet in pets table as a template -typedef enum { +enum aaNonspellAction { aaActionNone = 0, aaActionAETaunt = 1, aaActionMassBuff = 2, @@ -38,7 +38,7 @@ typedef enum { aaActionLeechTouch = 14, aaActionProjectIllusion = 15, aaActionFadingMemories = 16 -} aaNonspellAction; +}; enum { //leadership AA indexes groupAAMarkNPC = 0, @@ -116,7 +116,7 @@ static const uint8 LeadershipAACosts[_maxLeaderAA][MAX_LEADERSHIP_TIERS] = { { 0, 0, 0, 0, 0, 0 }, //raidAA15 }; -typedef enum { //AA IDs +enum aaID { //AA IDs aaNone =0, aaInnateStrength =2,//implemented as bonus aaInnateStamina =7,//implemented as bonus @@ -1525,7 +1525,7 @@ typedef enum { //AA IDs aaHighestID //this should always be last, and should always //follow the highest AA ID -} aaID; +}; //Structure representing the database's swarm pet configs struct SwarmPet_Struct { diff --git a/zone/bot.cpp b/zone/bot.cpp index b543ea2469..8c3f668a4c 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -10580,12 +10580,12 @@ void Bot::LoadDefaultBotSettings() { m_bot_spell_settings.push_back(t); LogBotSettingsDetail("{} says, 'Setting defaults for {} ({}) [#{}] - [{} [#{}] stance]'", GetCleanName(), t.name, t.short_name, t.spell_type, Stance::GetName(bot_stance), bot_stance); - LogBotSettingsDetail("{} says, 'Hold = [{}] | Delay = [{}ms] | MinThreshold = [{}\%] | MaxThreshold = [{}\%]'", GetCleanName(), + LogBotSettingsDetail("{} says, 'Hold = [{}] | Delay = [{}ms] | MinThreshold = [{}%] | MaxThreshold = [{}%]'", GetCleanName(), GetDefaultSpellTypeHold(i, bot_stance), GetDefaultSpellTypeDelay(i, bot_stance), GetDefaultSpellTypeMinThreshold(i, bot_stance), GetDefaultSpellTypeMaxThreshold(i, bot_stance)); - LogBotSettingsDetail("{} says, 'AggroCheck = [{}] | MinManaPCT = [{}\%] | MaxManaPCT = [{}\%] | MinHPPCT = [{}\% | MaxHPPCT = [{}\%]'", GetCleanName(), GetDefaultSpellTypeAggroCheck(i, bot_stance), GetDefaultSpellTypeMinManaLimit(i, bot_stance), GetDefaultSpellTypeMaxManaLimit(i, bot_stance), GetDefaultSpellTypeMinHPLimit(i, bot_stance), GetDefaultSpellTypeMaxHPLimit(i, bot_stance)); + LogBotSettingsDetail("{} says, 'AggroCheck = [{}] | MinManaPCT = [{}%] | MaxManaPCT = [{}%] | MinHPPCT = [{}% | MaxHPPCT = [{}%]'", GetCleanName(), GetDefaultSpellTypeAggroCheck(i, bot_stance), GetDefaultSpellTypeMinManaLimit(i, bot_stance), GetDefaultSpellTypeMaxManaLimit(i, bot_stance), GetDefaultSpellTypeMinHPLimit(i, bot_stance), GetDefaultSpellTypeMaxHPLimit(i, bot_stance)); LogBotSettingsDetail("{} says, 'IdlePriority = [{}] | EngagedPriority = [{}] | PursuePriority = [{}]'", GetCleanName(), GetDefaultSpellTypeIdlePriority(i, GetClass(), bot_stance), GetDefaultSpellTypeEngagedPriority(i, GetClass(), bot_stance), GetDefaultSpellTypePursuePriority(i, GetClass(), bot_stance)); LogBotSettingsDetail("{} says, 'TargetCount = [{}] | AnnounceCast = [{}]'", GetCleanName(), GetDefaultSpellTypeAEOrGroupTargetCount(i, bot_stance), GetDefaultSpellTypeAnnounceCast(i, bot_stance)); } @@ -10636,7 +10636,7 @@ void Bot::SetBotSpellRecastTimer(uint16 spell_type, Mob* tar, bool precast) { BotSpell Bot::GetSpellByHealType(uint16 spell_type, Mob* tar) { if (!TargetValidation(tar)) { - BotSpell result; + BotSpell result{}; return result; } diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index decd84e074..594d28b477 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -458,9 +458,7 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas return bot_id; } - bool available_flag = false; - - !database.botdb.QueryNameAvailability(bot_name, available_flag); + bool available_flag = database.botdb.QueryNameAvailability(bot_name); if (!available_flag) { bot_owner->Message( diff --git a/zone/bot_command.h b/zone/bot_command.h index 382d397947..6f3de0544b 100644 --- a/zone/bot_command.h +++ b/zone/bot_command.h @@ -24,26 +24,22 @@ class Client; class Seperator; - -namespace -{ #define HP_RATIO_DELTA 5.0f - enum { EffectIDFirst = 1, EffectIDLast = 12 }; +enum { EffectIDFirst = 1, EffectIDLast = 12 }; #define VALIDATECLASSID(x) ((x >= Class::Warrior && x <= Class::Berserker) ? (x) : (0)) - // ActionableTarget action_type +// ActionableTarget action_type #define FRIENDLY true #define ENEMY false - enum { - AFT_None = 0, - AFT_Value, - AFT_GenderRace, - AFT_Race - }; -} +enum { + AFT_None = 0, + AFT_Value, + AFT_GenderRace, + AFT_Race +}; namespace MyBots { diff --git a/zone/bot_commands/bot_bot.cpp b/zone/bot_commands/bot_bot.cpp index e1f881bdfb..32e99bbcd9 100644 --- a/zone/bot_commands/bot_bot.cpp +++ b/zone/bot_commands/bot_bot.cpp @@ -145,9 +145,7 @@ void bot_command_clone(Client *c, const Seperator *sep) return; } - bool available_flag = false; - - !database.botdb.QueryNameAvailability(bot_name, available_flag); + bool available_flag = database.botdb.QueryNameAvailability(bot_name); if (!available_flag) { c->Message( diff --git a/zone/bot_commands/bot_pickpocket.cpp b/zone/bot_commands/bot_pickpocket.cpp index 216d9d0786..a58aaa3332 100644 --- a/zone/bot_commands/bot_pickpocket.cpp +++ b/zone/bot_commands/bot_pickpocket.cpp @@ -82,8 +82,8 @@ void bot_command_pickpocket(Client *c, const Seperator *sep) } // Setup variables for calcs - bool steal_skill = my_bot->GetSkill(EQ::skills::SkillPickPockets); - bool steal_chance = steal_skill * 100 / (5 * over_level + 5); + uint16 steal_skill = my_bot->GetSkill(EQ::skills::SkillPickPockets); + int steal_chance = steal_skill * 100 / (5 * over_level + 5); // Determine whether to steal money or an item. uint32 money[6] = { diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 5982fc0a72..a8f1952cb5 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -228,7 +228,7 @@ bool BotDatabase::LoadBotSpellCastingChances() return true; } -bool BotDatabase::QueryNameAvailability(const std::string& bot_name, bool& available_flag) +bool BotDatabase::QueryNameAvailability(const std::string& bot_name) { if ( bot_name.empty() || @@ -239,8 +239,6 @@ bool BotDatabase::QueryNameAvailability(const std::string& bot_name, bool& avail return false; } - available_flag = true; - return true; } diff --git a/zone/bot_database.h b/zone/bot_database.h index 31ad3368db..8fb2aa1d26 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -45,7 +45,7 @@ class BotDatabase /* Bot functions */ - bool QueryNameAvailability(const std::string& bot_name, bool& available_flag); + bool QueryNameAvailability(const std::string& bot_name); bool QueryBotCount(const uint32 owner_id, int class_id, uint32& bot_count, uint32& bot_class_count); bool LoadBotsList(const uint32 owner_id, std::list& bots_list, bool by_account = false); diff --git a/zone/cheat_manager.h b/zone/cheat_manager.h index 0c6432b5a8..0b4f587cce 100644 --- a/zone/cheat_manager.h +++ b/zone/cheat_manager.h @@ -27,7 +27,7 @@ class CheatManager; class Client; -typedef enum { +enum UpdateMovementType { Collision = 1, TeleportB, TeleportA, @@ -37,18 +37,18 @@ typedef enum { SpellA, // Titanium - UF Unknown0x8, SpellB // Used in RoF+ -} UpdateMovementType; +}; -typedef enum { +enum ExemptionType { ShadowStep, KnockBack, Port, Assist, Sense, MAX_EXEMPTIONS -} ExemptionType; +}; -typedef enum { +enum CheatTypes { MQWarp, MQWarpShadowStep, MQWarpKnockBack, @@ -59,7 +59,7 @@ typedef enum { MQGhost, MQFastMem, MQWarpAbsolute -} CheatTypes; +}; class CheatManager { public: diff --git a/zone/client.cpp b/zone/client.cpp index 67462169f6..56d59c4b38 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1784,7 +1784,7 @@ void Client::Message(uint32 type, const char* message, ...) { buf.WriteInt32(0); buf.WriteString(buffer); - auto app = new EQApplicationPacket(OP_SpecialMesg, buf); + auto app = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); FastQueuePacket(&app); @@ -1813,7 +1813,7 @@ void Client::FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, cons buf.WriteInt32(0); buf.WriteString(buffer); - auto app = new EQApplicationPacket(OP_SpecialMesg, buf); + auto app = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); FastQueuePacket(&app); @@ -3869,7 +3869,7 @@ void Client::MessageString(uint32 type, uint32 string_id, const char* message1, buf.WriteInt8(0); // prevent oob in packet translation, maybe clean that up sometime - auto outapp = std::make_unique(OP_FormattedMessage, buf); + auto outapp = std::make_unique(OP_FormattedMessage, std::move(buf)); if (distance > 0) entity_list.QueueCloseClients(this, outapp.get(), false, distance); @@ -3987,7 +3987,7 @@ void Client::FilteredMessageString(Mob *sender, uint32 type, eqFilterType filter buf.WriteInt8(0); // prevent oob in packet translation, maybe clean that up sometime - auto outapp = std::make_unique(OP_FormattedMessage, buf); + auto outapp = std::make_unique(OP_FormattedMessage, std::move(buf)); QueuePacket(outapp.get()); } diff --git a/zone/client.h b/zone/client.h index 9dc5960e78..4e9b5e8913 100644 --- a/zone/client.h +++ b/zone/client.h @@ -106,7 +106,7 @@ enum { //scribing argument to MemorizeSpell }; //Modes for the zoning state of the client. -typedef enum { +enum ZoneMode { ZoneToSafeCoords, // Always send ZonePlayerToBind_Struct to client: Succor/Evac GMSummon, // Always send ZonePlayerToBind_Struct to client: Only a GM Summon GMHiddenSummon, // Always send ZonePlayerToBind_Struct to client silently: Only a GM Summon @@ -117,7 +117,7 @@ typedef enum { SummonPC, // In-zone GMMove() always: Call of the Hero spell or some other type of in zone only summons Rewind, // Summon to /rewind location. EvacToSafeCoords -} ZoneMode; +}; // translate above enum to a string std::string GetZoneModeString(ZoneMode mode); @@ -130,13 +130,13 @@ enum { HideCorpseNPC = 5 }; -typedef enum +enum ShowSpellType { Disciplines, Spells -} ShowSpellType; +}; -typedef enum +enum XTargetType { Empty = 0, Auto = 1, @@ -165,8 +165,7 @@ typedef enum MyPetTarget = 24, MyMercenary = 25, MyMercenaryTarget = 26 - -} XTargetType; +}; struct XTarget_Struct { diff --git a/zone/client_bot.cpp b/zone/client_bot.cpp index 0e914c1451..eebb63556c 100644 --- a/zone/client_bot.cpp +++ b/zone/client_bot.cpp @@ -252,7 +252,7 @@ void Client::LoadDefaultBotSettings() { m_bot_spell_settings.push_back(t); LogBotSettingsDetail("{} says, 'Setting defaults for {} ({}) [#{}]'", GetCleanName(), t.name, t.short_name, t.spell_type); - LogBotSettingsDetail("{} says, 'Delay = [{}ms] | MinThreshold = [{}\%] | MaxThreshold = [{}\%]'", GetCleanName(), + LogBotSettingsDetail("{} says, 'Delay = [{}ms] | MinThreshold = [{}%] | MaxThreshold = [{}%]'", GetCleanName(), GetDefaultSpellTypeDelay(i), GetDefaultSpellTypeMinThreshold(i), GetDefaultSpellTypeMaxThreshold(i)); } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 87a4a40091..7fc5174f6b 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -3239,10 +3239,10 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) } if ( - ((tobe_auged->IsAugmentSlotAvailable(new_aug->GetAugmentType(), in_augment->augment_index)) != -1) && + tobe_auged->IsAugmentSlotAvailable(new_aug->GetAugmentType(), static_cast(in_augment->augment_index)) && tobe_auged->AvailableWearSlot(new_aug->GetItem()->Slots) ) { - old_aug = tobe_auged->RemoveAugment(in_augment->augment_index); + old_aug = tobe_auged->RemoveAugment(static_cast(in_augment->augment_index)); if (old_aug) { // An old augment was removed in order to be replaced with the new one (augment_action 2) CalcBonuses(); diff --git a/zone/command.h b/zone/command.h index 8fa473ba67..da80557c17 100644 --- a/zone/command.h +++ b/zone/command.h @@ -28,11 +28,11 @@ class Seperator; typedef void (*CmdFuncPtr)(Client *, const Seperator *); -typedef struct { +struct CommandRecord { uint8 admin; std::string description; CmdFuncPtr function; // null means perl function -} CommandRecord; +}; extern int (*command_dispatch)(Client *, std::string, bool); extern int command_count; // Commands Loaded Count diff --git a/zone/common.h b/zone/common.h index c1376bcd0d..1ab8bf2d0f 100644 --- a/zone/common.h +++ b/zone/common.h @@ -922,7 +922,7 @@ struct DataBucketCache enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard, SPO_FeignDeath }; -typedef enum { +enum PetTypeOld { petFamiliar, //only listens to /pet get lost petAnimation, //does not listen to any commands petOther, @@ -930,4 +930,4 @@ typedef enum { petNPCFollow, petTargetLock, //remain active as long something is on the hatelist. Don't listen to any commands petNone = 0xFF // not a pet -} PetTypeOld; +}; diff --git a/zone/effects.cpp b/zone/effects.cpp index 06c18a41e1..0d0b1ce348 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -1108,7 +1108,7 @@ void EntityList::AESpell( max_targets_allowed = RuleI(Spells, TargetedAOEMaxTargets); } else if ( IsPBAESpell(spell_id) && - IsDetrimentalSpell && + is_detrimental_spell && !is_npc ) { max_targets_allowed = RuleI(Spells, PointBlankAOEMaxTargets); diff --git a/zone/entity.cpp b/zone/entity.cpp index e1b25370ff..ddbf34b6d6 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -4437,7 +4437,7 @@ void EntityList::QuestJournalledSayClose( buf.WriteString(message); } - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); // client only bothers logging if target spawn ID matches, safe to send to everyone QueueCloseClients(sender, outapp, false, dist); diff --git a/zone/event_codes.h b/zone/event_codes.h index e363c17de1..c5210633f6 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -17,7 +17,7 @@ */ #pragma once -typedef enum { +enum QuestEventID { EVENT_SAY = 0, EVENT_TRADE, //being given an item or money EVENT_DEATH, //being killed @@ -169,6 +169,6 @@ typedef enum { EVENT_SPELL_EFFECT_BOT, EVENT_SPELL_EFFECT_BUFF_TIC_BOT, _LargestEventID -} QuestEventID; +}; extern const char *QuestEventSubroutines[_LargestEventID]; diff --git a/zone/gm_commands/door_manipulation.cpp b/zone/gm_commands/door_manipulation.cpp index 91472865cf..b518a8c068 100644 --- a/zone/gm_commands/door_manipulation.cpp +++ b/zone/gm_commands/door_manipulation.cpp @@ -447,15 +447,15 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) if (arg1 == "setinclineinc") { std::map incline_values = { - {.01, "Upright"}, - {63.75, "45 Degrees",}, - {130, "90 Degrees"}, - {192.5, "135 Degrees"}, - {255, "180 Degrees"}, - {321.25, "225 Degrees"}, - {385, "270 Degrees"}, - {448.75, "315 Degrees"}, - {512.5, "360 Degrees"} + {.01f, "Upright"}, + {63.75f, "45 Degrees",}, + {130.f, "90 Degrees"}, + {192.5f, "135 Degrees"}, + {255.f, "180 Degrees"}, + {321.25f, "225 Degrees"}, + {385.f, "270 Degrees"}, + {448.75f, "315 Degrees"}, + {512.5f, "360 Degrees"} }; std::vector incline_normal_options; diff --git a/zone/guild.cpp b/zone/guild.cpp index 54775c62af..5ab0a66812 100644 --- a/zone/guild.cpp +++ b/zone/guild.cpp @@ -624,7 +624,7 @@ void Client::SendGuildMemberRankAltBanker(uint32 guild_id, uint32 rank, std::str out->guild_id = guild_id; out->rank_ = rank; - out->alt_banker = (alt << 1) | banker; + out->alt_banker = (alt ? 2 : 0) | (banker ? 1 : 0); strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name)); QueuePacket(outapp); @@ -792,7 +792,7 @@ void EntityList::SendGuildMemberRankAltBanker(uint32 guild_id, uint32 rank_, std out->guild_id = guild_id; out->rank_ = rank_; - out->alt_banker = (alt << 1) | banker; + out->alt_banker = (alt ? 2 : 0) | (banker ? 1 : 0); strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name)); c.second->QueuePacket(outapp); diff --git a/zone/lua_bit.cpp b/zone/lua_bit.cpp index 5c8af6fcc1..c0712529b5 100644 --- a/zone/lua_bit.cpp +++ b/zone/lua_bit.cpp @@ -151,7 +151,7 @@ static const struct luaL_Reg bit_funcs[] = { */ #define BAD_SAR (bsar(-8, 2) != (SBits)-2) -int luaopen_bit(lua_State *L) +int luaopen_bit_embed(lua_State *L) { UBits b; lua_pushnumber(L, (lua_Number)1437217655L); diff --git a/zone/lua_bit.h b/zone/lua_bit.h index 10dfdb06cb..e3f163cbc3 100644 --- a/zone/lua_bit.h +++ b/zone/lua_bit.h @@ -17,4 +17,6 @@ */ #pragma once -int luaopen_bit(lua_State *L); +struct lua_State; + +int luaopen_bit_embed(lua_State *L); diff --git a/zone/main.cpp b/zone/main.cpp index 82a1c3cf46..9aab5adf85 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -26,7 +26,6 @@ #include "common/guilds.h" #include "common/memory_mapped_file.h" #include "common/misc.h" -#include "common/mutex.h" #include "common/net/eqstream.h" #include "common/opcodemgr.h" #include "common/patches/patches.h" @@ -216,8 +215,6 @@ int main(int argc, char **argv) } } - auto mutex = new Mutex; - LogInfo("Connecting to MySQL"); if (!database.Connect( Config->DatabaseHost.c_str(), @@ -245,11 +242,13 @@ int main(int argc, char **argv) } } else { content_db.SetMySQL(database); + // when database and content_db share the same underlying mysql connection // it needs to be protected by a shared mutex otherwise we produce concurrency issues // when database actions are occurring in different threads - database.SetMutex(mutex); - content_db.SetMutex(mutex); + std::shared_ptr sharedMutex = std::make_shared(); + database.SetMutex(sharedMutex); + content_db.SetMutex(sharedMutex); } //rules: @@ -661,7 +660,6 @@ int main(int argc, char **argv) LogInfo("Proper zone shutdown complete."); EQEmuLogSys::Instance()->CloseFileLogs(); - safe_delete(mutex); safe_delete(QServ); return 0; diff --git a/zone/map.cpp b/zone/map.cpp index 65d7f30d72..0fba4d021e 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -17,7 +17,7 @@ */ #include "common/compression.h" #include "common/file.h" -#include "common/memory/ksm.hpp" +#include "common/memory/ksm.h" #include "common/misc_functions.h" #include "zone/client.h" #include "zone/map.h" diff --git a/zone/npc.h b/zone/npc.h index cd352833bc..06ac7101e2 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -32,7 +32,7 @@ #include #include -typedef struct { +struct NPCProximity { float min_x; float max_x; float min_y; @@ -41,7 +41,7 @@ typedef struct { float max_z; bool say; bool proximity_set; -} NPCProximity; +}; struct AISpells_Struct { uint32 type; // 0 = never, must be one (and only one) of the defined values diff --git a/zone/petitions.cpp b/zone/petitions.cpp index cdb9468759..4cd2959bdb 100644 --- a/zone/petitions.cpp +++ b/zone/petitions.cpp @@ -135,10 +135,11 @@ void PetitionList::AddPetition(Petition* pet) { } //Return Values: 0 = Ok ; -1 = Error deleting petition. -int PetitionList::DeletePetition(uint32 petnumber) { +int PetitionList::DeletePetition(uint32 petnumber) +{ LinkedListIterator iterator(list); iterator.Reset(); - LockMutex lock(&PList_Mutex); + std::scoped_lock lock(PList_Mutex); while(iterator.MoreElements()) { if (iterator.GetData()->GetID() == petnumber) { database.DeletePetitionFromDB(iterator.GetData()); @@ -179,18 +180,18 @@ void PetitionList::ClearPetitions() { return; } -void PetitionList::ReadDatabase() { - LockMutex lock(&PList_Mutex); +void PetitionList::ReadDatabase() +{ + std::scoped_lock lock(PList_Mutex); ClearPetitions(); database.RefreshPetitionsFromDB(); UpdateGMQueue(); - return; } -void PetitionList::UpdatePetition(Petition* pet) { - LockMutex lock(&PList_Mutex); +void PetitionList::UpdatePetition(Petition* pet) +{ + std::scoped_lock lock(PList_Mutex); database.UpdatePetitionToDB(pet); - return; } void ZoneDatabase::DeletePetitionFromDB(Petition* wpet) { diff --git a/zone/petitions.h b/zone/petitions.h index 82afa24ff0..82c024eeb9 100644 --- a/zone/petitions.h +++ b/zone/petitions.h @@ -18,12 +18,9 @@ #pragma once #include "common/linked_list.h" -#include "common/misc_functions.h" -#include "common/mutex.h" #include "common/types.h" -#include "common/zone_store.h" -#include "zone/client.h" -#include "zone/zonedb.h" + +#include class Client; @@ -118,5 +115,5 @@ class PetitionList private: LinkedList list; - Mutex PList_Mutex; + std::mutex PList_Mutex; }; diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 73990d562a..92de69567b 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2779,18 +2779,7 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level } std::string test_name = name; - bool available_flag = false; - if (!database.botdb.QueryNameAvailability(test_name, available_flag)) { - initiator->Message( - Chat::White, - fmt::format( - "Failed to query name availability for '{}'.", - test_name - ).c_str() - ); - return false; - } - + bool available_flag = database.botdb.QueryNameAvailability(test_name); if (!available_flag) { initiator->Message( Chat::White, diff --git a/zone/raycast_mesh.cpp b/zone/raycast_mesh.cpp index 64e10a5237..a6c92ed1b7 100644 --- a/zone/raycast_mesh.cpp +++ b/zone/raycast_mesh.cpp @@ -18,7 +18,7 @@ #include "raycast_mesh.h" #include "common/eqemu_logsys.h" -#include "common/memory/ksm.hpp" +#include "common/memory/ksm.h" #include #include diff --git a/zone/shared_task_zone_messaging.cpp b/zone/shared_task_zone_messaging.cpp index a579f53c3b..0d8455e5d4 100644 --- a/zone/shared_task_zone_messaging.cpp +++ b/zone/shared_task_zone_messaging.cpp @@ -117,7 +117,7 @@ void SharedTaskZoneMessaging::HandleWorldMessage(ServerPacket *pack) buf.WriteInt8(m.is_leader ? 1 : 0); } - auto outapp = std::make_unique(OP_SharedTaskMemberList, buf); + auto outapp = std::make_unique(OP_SharedTaskMemberList, std::move(buf)); c->QueuePacket(outapp.get()); } @@ -141,7 +141,7 @@ void SharedTaskZoneMessaging::HandleWorldMessage(ServerPacket *pack) // live sends more after the name but it might just be garbage from // a re-used buffer (possibly a former name[64] buffer?) - auto outapp = std::make_unique(OP_SharedTaskMemberChange, buf); + auto outapp = std::make_unique(OP_SharedTaskMemberChange, std::move(buf)); c->QueuePacket(outapp.get()); } diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp index 23b3082015..a3af9f0134 100644 --- a/zone/task_manager.cpp +++ b/zone/task_manager.cpp @@ -858,7 +858,7 @@ void TaskManager::SendTaskSelector(Client* client, Mob* mob, const std::vectorGetTaskState()->AddOffer(task_list[i], mob->GetID()); } - auto outapp = std::make_unique(OP_TaskSelectWindow, buf); + auto outapp = std::make_unique(OP_TaskSelectWindow, std::move(buf)); client->QueuePacket(outapp.get()); } @@ -883,7 +883,7 @@ void TaskManager::SendSharedTaskSelector(Client* client, Mob* mob, const std::ve client->GetTaskState()->AddOffer(task_id, mob->GetID()); } - auto outapp = std::make_unique(OP_SharedTaskSelectWindow, buf); + auto outapp = std::make_unique(OP_SharedTaskSelectWindow, std::move(buf)); client->QueuePacket(outapp.get()); } @@ -1009,7 +1009,7 @@ void TaskManager::SendTaskActivityLong( activity.SerializeObjective(buf, client->ClientVersion(), done_count); - auto outapp = std::make_unique(OP_TaskActivity, buf); + auto outapp = std::make_unique(OP_TaskActivity, std::move(buf)); client->QueuePacket(outapp.get()); } diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 049bcf5904..14efb17622 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -621,7 +621,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac } if (spec.tradeskill == EQ::skills::SkillAlchemy) { - if (!user->GetClass() == Class::Shaman) { + if (user->GetClass() != Class::Shaman) { user->Message(Chat::Red, "This tradeskill can only be performed by a shaman."); auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); @@ -646,7 +646,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac } } else if (spec.tradeskill == EQ::skills::SkillMakePoison) { - if (!user->GetClass() == Class::Rogue) { + if (user->GetClass() != Class::Rogue) { user->Message(Chat::Red, "Only rogues can mix poisons."); auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); diff --git a/zone/water_map_v1.h b/zone/water_map_v1.h index 0a3fc32984..04acf44f70 100644 --- a/zone/water_map_v1.h +++ b/zone/water_map_v1.h @@ -21,13 +21,14 @@ #pragma pack(push) #pragma pack(1) -typedef struct ZBSP_Node { + +struct ZBSP_Node { int32 node_number; float normal[3], splitdistance; int32 region; int32 special; int32 left, right; -} ZBSP_Node; +}; #pragma pack(pop) diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index a273af1867..a314936ca3 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -550,7 +550,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) SerializeBuffer buf(100); buf.WriteString(smotd->motd); - auto outapp = std::make_unique(OP_MOTD, buf); + auto outapp = std::make_unique(OP_MOTD, std::move(buf)); entity_list.QueueClients(0, outapp.get()); break; From ba2ca5eada80ac758ef8c2a2510cb39b0563119a Mon Sep 17 00:00:00 2001 From: Knightly <55611098+Knightly1@users.noreply.github.com> Date: Mon, 6 Apr 2026 11:48:46 -1000 Subject: [PATCH 100/194] Lua: Header Matching and Cleanup (#5055) --- zone/lua_general.cpp | 4 ++-- zone/lua_mob.cpp | 1 + zone/lua_npc.cpp | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index ea4d4c878e..793b730c54 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -6920,8 +6920,8 @@ luabind::scope lua_register_events() { luabind::value("spell_buff_tic", static_cast(EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT)), luabind::value("spell_fade", static_cast(EVENT_SPELL_FADE)), luabind::value("spell_effect_translocate_complete", static_cast(EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE)), - luabind::value("combine_success ", static_cast(EVENT_COMBINE_SUCCESS )), - luabind::value("combine_failure ", static_cast(EVENT_COMBINE_FAILURE )), + luabind::value("combine_success", static_cast(EVENT_COMBINE_SUCCESS )), + luabind::value("combine_failure", static_cast(EVENT_COMBINE_FAILURE )), luabind::value("item_click", static_cast(EVENT_ITEM_CLICK)), luabind::value("item_click_cast", static_cast(EVENT_ITEM_CLICK_CAST)), luabind::value("group_change", static_cast(EVENT_GROUP_CHANGE)), diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 500ce7525f..312993d356 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -3732,6 +3732,7 @@ luabind::scope lua_register_mob() { .def("GMMove", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::GMMove) .def("GMMove", (void(Lua_Mob::*)(double,double,double,double))&Lua_Mob::GMMove) .def("GMMove", (void(Lua_Mob::*)(double,double,double,double,bool))&Lua_Mob::GMMove) + .def("Gate", &Lua_Mob::Gate) .def("GetAA", (int(Lua_Mob::*)(int))&Lua_Mob::GetAA) .def("GetAABonuses", &Lua_Mob::GetAABonuses) .def("GetAAByAAID", (int(Lua_Mob::*)(int))&Lua_Mob::GetAAByAAID) diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index e4f309a0e0..30c4849d0a 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -1068,6 +1068,7 @@ luabind::scope lua_register_npc() { .def("GetWaypointMax", (int(Lua_NPC::*)(void))&Lua_NPC::GetWaypointMax) .def("HasAISpellEffect", (bool(Lua_NPC::*)(int))&Lua_NPC::HasAISpellEffect) .def("HasItem", (bool(Lua_NPC::*)(uint32))&Lua_NPC::HasItem) + .def("HasSpecialAbilities", &Lua_NPC::HasSpecialAbilities) .def("IsAnimal", (bool(Lua_NPC::*)(void))&Lua_NPC::IsAnimal) .def("IsGuarding", (bool(Lua_NPC::*)(void))&Lua_NPC::IsGuarding) .def("IsLDoNLocked", (bool(Lua_NPC::*)(void))&Lua_NPC::IsLDoNLocked) From 348094b881dfe819d84e563b3ce32f33fbbe377a Mon Sep 17 00:00:00 2001 From: ltroylove Date: Mon, 20 Apr 2026 19:50:36 -0500 Subject: [PATCH 101/194] fix: correct off-by-one in GetSpellLevel for Berserker class (#5060) Co-authored-by: Claude Sonnet 4.6 --- common/spdat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/spdat.cpp b/common/spdat.cpp index 1df6e55e51..01bf12efed 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -999,7 +999,7 @@ uint8 GetSpellLevel(uint16 spell_id, uint8 class_id) return UINT8_MAX; } - if (class_id >= Class::PLAYER_CLASS_COUNT) { + if (class_id < Class::Warrior || class_id > Class::PLAYER_CLASS_COUNT) { return UINT8_MAX; } From 1958a12bc798f169758cf4ba82efbc797a2c780b Mon Sep 17 00:00:00 2001 From: ltroylove Date: Mon, 20 Apr 2026 19:51:17 -0500 Subject: [PATCH 102/194] fix: include base skill damage in FlyingKick, Kick, RoundKick, and Bash (#5061) --- zone/bot.cpp | 6 +++--- zone/special_attacks.cpp | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 8c3f668a4c..00662389c5 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -5175,7 +5175,7 @@ int Bot::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target) ac_bonus = inst->GetItemArmorClass(true) / 25.0f; if (ac_bonus > skill_bonus) ac_bonus = skill_bonus; - return static_cast(ac_bonus + skill_bonus); + return base + static_cast(ac_bonus + skill_bonus); } case EQ::skills::SkillKick: { float skill_bonus = skill_level / 10.0f; @@ -5185,7 +5185,7 @@ int Bot::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target) ac_bonus = inst->GetItemArmorClass(true) / 25.0f; if (ac_bonus > skill_bonus) ac_bonus = skill_bonus; - return static_cast(ac_bonus + skill_bonus); + return base + static_cast(ac_bonus + skill_bonus); } case EQ::skills::SkillBash: { float skill_bonus = skill_level / 10.0f; @@ -5199,7 +5199,7 @@ int Bot::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target) ac_bonus = inst->GetItemArmorClass(true) / 25.0f; if (ac_bonus > skill_bonus) ac_bonus = skill_bonus; - return static_cast(ac_bonus + skill_bonus); + return base + static_cast(ac_bonus + skill_bonus); } case EQ::skills::SkillBackstab: { float skill_bonus = static_cast(skill_level) * 0.02f; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 6c367101c9..466ab7d589 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -102,10 +102,10 @@ int Mob::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target) } if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) { - return static_cast(ac_bonus + skill_bonus) * std::abs(GetSkillDmgAmt(skill) / 100); + return (base + static_cast(ac_bonus + skill_bonus)) * std::abs(GetSkillDmgAmt(skill) / 100); } - return static_cast(ac_bonus + skill_bonus); + return base + static_cast(ac_bonus + skill_bonus); } case EQ::skills::SkillKick: case EQ::skills::SkillRoundKick: { @@ -128,10 +128,10 @@ int Mob::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target) } if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) { - return static_cast(ac_bonus + skill_bonus) * std::abs(GetSkillDmgAmt(skill) / 100); + return (base + static_cast(ac_bonus + skill_bonus)) * std::abs(GetSkillDmgAmt(skill) / 100); } - return static_cast(ac_bonus + skill_bonus); + return base + static_cast(ac_bonus + skill_bonus); } case EQ::skills::SkillBash: { float skill_bonus = skill_level / 10.0f; @@ -160,10 +160,10 @@ int Mob::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target) } if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) { - return static_cast(ac_bonus + skill_bonus) * std::abs(GetSkillDmgAmt(skill) / 100); + return (base + static_cast(ac_bonus + skill_bonus)) * std::abs(GetSkillDmgAmt(skill) / 100); } - return static_cast(ac_bonus + skill_bonus); + return base + static_cast(ac_bonus + skill_bonus); } case EQ::skills::SkillBackstab: { float skill_bonus = static_cast(skill_level) * 0.02f; From 758774b0bf1a01f71629c3b81ce094da94e687a0 Mon Sep 17 00:00:00 2001 From: ltroylove Date: Mon, 20 Apr 2026 19:51:47 -0500 Subject: [PATCH 103/194] fix: only dismiss pet summoned by the fading familiar buff (#5063) --- zone/spell_effects.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 7b29ca2c57..4930f11549 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -4394,9 +4394,9 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) case SpellEffect::Familiar: { Mob *mypet = GetPet(); - if (mypet){ - if(mypet->IsNPC()) - mypet->CastToNPC()->Depop(); + if (mypet && mypet->IsNPC() && + mypet->CastToNPC()->GetPetSpellID() == buffs[slot].spellid) { + mypet->CastToNPC()->Depop(); SetPetID(0); } break; From 5dc093fe5e5a51b8fdb3ff0e1c7234b039ea0e51 Mon Sep 17 00:00:00 2001 From: xJeris <85350673+xJeris@users.noreply.github.com> Date: Mon, 20 Apr 2026 20:52:23 -0400 Subject: [PATCH 104/194] Add Multiple Mercenary Hire Functionality (#5059) --- common/emu_oplist.h | 1 + common/eq_packet_structs.h | 6 ++ common/patches/rof2.cpp | 11 ++- common/ruletypes.h | 1 + utils/patches/patch_RoF2.conf | 1 + zone/client.cpp | 160 ++++++++++++++++++++++------------ zone/client.h | 1 + zone/client_packet.cpp | 112 ++++++++++++++++++++++-- zone/client_packet.h | 1 + zone/merc.cpp | 105 +++++++++++++++------- zone/merc.h | 2 +- zone/zonedb.cpp | 6 +- 12 files changed, 307 insertions(+), 100 deletions(-) diff --git a/common/emu_oplist.h b/common/emu_oplist.h index 1f8366662a..e85c83e9eb 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -376,6 +376,7 @@ N(OP_MercenaryDismiss), N(OP_MercenaryHire), N(OP_MercenarySuspendRequest), N(OP_MercenarySuspendResponse), +N(OP_MercenarySwitch), N(OP_MercenaryTimer), N(OP_MercenaryTimerRequest), N(OP_MercenaryUnknown1), diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index c11945cc4e..d6736c0716 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -6236,6 +6236,12 @@ struct SuspendMercenary_Struct { /*0001*/ }; +// [OPCode: 0x1b37 (RoF2)] [Client->Server] [Size: 4] +struct SwitchMercenary_Struct { +/*0000*/ uint32 MercIndex; // 0-based UI index into owned merc list +/*0004*/ +}; + // [OPCode: 0x2528] On Live as of April 2 2012 [Server->Client] [Size: 4] // Response to suspend merc with timestamp struct SuspendMercenaryResponse_Struct { diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 992f0c538d..a2b3ba30e7 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2278,15 +2278,19 @@ namespace RoF2 // There are 2 different sized versions of this packet depending if a merc is hired or not if (emu->MercStatus >= 0) { - PacketSize += sizeof(structs::MercenaryDataUpdate_Struct) + (sizeof(structs::MercenaryData_Struct) - sizeof(structs::MercenaryStance_Struct)) * emu->MercCount; - + // Per-merc size: base struct minus Stances[1] and MercUnk05, + // then add back actual stances and name length per merc. + // MercUnk05 is a single trailing field after all mercs. + PacketSize += sizeof(structs::MercenaryDataUpdate_Struct); uint32 r; uint32 k; for (r = 0; r < emu->MercCount; r++) { + PacketSize += sizeof(structs::MercenaryData_Struct) - sizeof(structs::MercenaryStance_Struct) - sizeof(uint32); // subtract Stances[1] and MercUnk05 PacketSize += sizeof(structs::MercenaryStance_Struct) * emu->MercData[r].StanceCount; PacketSize += strlen(emu->MercData[r].MercName); // Null Terminator size already accounted for in the struct } + PacketSize += sizeof(uint32); // MercUnk05 - trailing field after all mercs outapp = new EQApplicationPacket(OP_MercenaryDataUpdate, PacketSize); Buffer = (char *)outapp->pBuffer; @@ -2312,15 +2316,14 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].StanceCount); VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->MercData[r].MercUnk03); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->MercData[r].MercUnk04); - //VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // MercName VARSTRUCT_ENCODE_STRING(Buffer, emu->MercData[r].MercName); for (k = 0; k < emu->MercData[r].StanceCount; k++) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].Stances[k].StanceIndex); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].Stances[k].Stance); } - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); // MercUnk05 } + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[0].MercUnk05); // MercUnk05 - trailing field (unlocked slot count) } else { diff --git a/common/ruletypes.h b/common/ruletypes.h index d9df94afd4..97a235e55a 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -255,6 +255,7 @@ RULE_BOOL(Mercs, AllowMercSuspendInCombat, true, "Allow merc suspend in combat") RULE_BOOL(Mercs, MercsIgnoreLevelBasedHasteCaps, false, "Ignores hard coded level based haste caps.") RULE_INT(Mercs, MercsHasteCap, 100, "Haste cap for non-v3(over haste) haste") RULE_INT(Mercs, MercsHastev3Cap, 25, "Haste cap for v3(over haste) haste") +RULE_INT(Mercs, MaxMercSlots, 6, "Maximum number of mercenary slots per character (max = MAXMERCS)") RULE_CATEGORY_END() RULE_CATEGORY(Guild) diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 3533aaa879..e5d9173cf3 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -418,6 +418,7 @@ OP_MercenaryUnknown1=0x5d26 OP_MercenaryCommand=0x27f2 OP_MercenarySuspendRequest=0x4407 OP_MercenarySuspendResponse=0x6f03 +OP_MercenarySwitch=0x1b37 OP_MercenaryUnsuspendResponse=0x27a0 # Looting diff --git a/zone/client.cpp b/zone/client.cpp index 56d59c4b38..e33650c7ee 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1037,7 +1037,7 @@ bool Client::Save(uint8 iCommitNow) { } if (dead || (!GetMerc() && !GetMercInfo().IsSuspended)) { - memset(&m_mercinfo, 0, sizeof(struct MercInfo)); + memset(&m_mercinfo, 0, sizeof(m_mercinfo)); } m_pp.lastlogin = time(nullptr); @@ -7940,75 +7940,125 @@ void Client::SendWebLink(const char *website) void Client::SendMercPersonalInfo() { - uint32 mercTypeCount = 1; - uint32 mercCount = 1; //TODO: Un-hardcode this and support multiple mercs like in later clients than SoD. - uint32 i = 0; uint32 altCurrentType = 19; //TODO: Implement alternate currency purchases involving mercs! - MercTemplate *mercData = &zone->merc_templates[GetMercInfo().MercTemplateID]; - - int stancecount = 0; - stancecount += zone->merc_stance_list[GetMercInfo().MercTemplateID].size(); - if(stancecount > MAX_MERC_STANCES || mercCount > MAX_MERC || mercTypeCount > MAX_MERC_GRADES) - { - Log(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo canceled: (%i) (%i) (%i) for %s", stancecount, mercCount, mercTypeCount, GetName()); - SendMercMerchantResponsePacket(0); - return; - } - if (ClientVersion() >= EQ::versions::ClientVersion::RoF) { - auto outapp = new EQApplicationPacket(OP_MercenaryDataUpdate, sizeof(MercenaryDataUpdate_Struct)); + // Count owned mercs across all slots + uint32 mercCount = GetNumberOfMercenaries(); + if (mercCount == 0) { + SendClearMercInfo(); + return; + } + + uint32 packetSize = sizeof(MercenaryDataUpdate_Struct); + auto outapp = new EQApplicationPacket(OP_MercenaryDataUpdate, packetSize); + memset(outapp->pBuffer, 0, packetSize); auto mdus = (MercenaryDataUpdate_Struct *) outapp->pBuffer; - mdus->MercStatus = 0; - mdus->MercCount = mercCount; - mdus->MercData[i].MercID = mercData->MercTemplateID; - mdus->MercData[i].MercType = mercData->MercType; - mdus->MercData[i].MercSubType = mercData->MercSubType; - mdus->MercData[i].PurchaseCost = Merc::CalcPurchaseCost(mercData->MercTemplateID, GetLevel(), 0); - mdus->MercData[i].UpkeepCost = Merc::CalcUpkeepCost(mercData->MercTemplateID, GetLevel(), 0); - mdus->MercData[i].Status = 0; - mdus->MercData[i].AltCurrencyCost = Merc::CalcPurchaseCost( - mercData->MercTemplateID, - GetLevel(), - altCurrentType - ); - mdus->MercData[i].AltCurrencyUpkeep = Merc::CalcPurchaseCost( - mercData->MercTemplateID, - GetLevel(), - altCurrentType - ); - mdus->MercData[i].AltCurrencyType = altCurrentType; - mdus->MercData[i].MercUnk01 = 0; - mdus->MercData[i].TimeLeft = GetMercInfo().MercTimerRemaining; //GetMercTimer().GetRemainingTime(); - mdus->MercData[i].MerchantSlot = i + 1; - mdus->MercData[i].MercUnk02 = 1; - mdus->MercData[i].StanceCount = zone->merc_stance_list[mercData->MercTemplateID].size(); - mdus->MercData[i].MercUnk03 = 0; - mdus->MercData[i].MercUnk04 = 1; - - strn0cpy(mdus->MercData[i].MercName, GetMercInfo().merc_name, sizeof(mdus->MercData[i].MercName)); - - uint32 stanceindex = 0; - if (mdus->MercData[i].StanceCount != 0) { - auto iter = zone->merc_stance_list[mercData->MercTemplateID].begin(); - while (iter != zone->merc_stance_list[mercData->MercTemplateID].end()) { - mdus->MercData[i].Stances[stanceindex].StanceIndex = stanceindex; - mdus->MercData[i].Stances[stanceindex].Stance = (iter->StanceID); - stanceindex++; - ++iter; + mdus->MercStatus = 0; + mdus->MercCount = mercCount; + + // Lambda to populate a single merc entry in the packet + int max_slots = std::min(RuleI(Mercs, MaxMercSlots), MAXMERCS); + uint32 merc_index = 0; + + auto fillMercEntry = [&](int slot) { + auto& info = GetMercInfo(slot); + if (info.mercid == 0 || merc_index >= MAX_MERC) { + return; + } + + auto tmpl_it = zone->merc_templates.find(info.MercTemplateID); + if (tmpl_it == zone->merc_templates.end()) { + return; + } + + MercTemplate *mercData = &tmpl_it->second; + uint32 stancecount = 0; + auto stance_it = zone->merc_stance_list.find(mercData->MercTemplateID); + if (stance_it != zone->merc_stance_list.end()) { + stancecount = stance_it->second.size(); + } + + if (stancecount > MAX_MERC_STANCES) { + Log(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo: stance count %u exceeds max for slot %i, skipping", stancecount, slot); + return; } + + mdus->MercData[merc_index].MercID = mercData->MercTemplateID; + mdus->MercData[merc_index].MercType = mercData->MercType; + mdus->MercData[merc_index].MercSubType = mercData->MercSubType; + mdus->MercData[merc_index].PurchaseCost = Merc::CalcPurchaseCost(mercData->MercTemplateID, GetLevel(), 0); + mdus->MercData[merc_index].UpkeepCost = Merc::CalcUpkeepCost(mercData->MercTemplateID, GetLevel(), 0); + mdus->MercData[merc_index].Status = info.IsSuspended ? 0 : 1; + mdus->MercData[merc_index].AltCurrencyCost = Merc::CalcPurchaseCost(mercData->MercTemplateID, GetLevel(), altCurrentType); + mdus->MercData[merc_index].AltCurrencyUpkeep = Merc::CalcPurchaseCost(mercData->MercTemplateID, GetLevel(), altCurrentType); + mdus->MercData[merc_index].AltCurrencyType = altCurrentType; + mdus->MercData[merc_index].MercUnk01 = 0; + mdus->MercData[merc_index].TimeLeft = info.MercTimerRemaining; + mdus->MercData[merc_index].MerchantSlot = merc_index + 1; + mdus->MercData[merc_index].MercUnk02 = (slot == GetMercSlot()) ? 1 : 0; + mdus->MercData[merc_index].StanceCount = stancecount; + mdus->MercData[merc_index].MercUnk03 = 0; + mdus->MercData[merc_index].MercUnk04 = 1; + + strn0cpy(mdus->MercData[merc_index].MercName, info.merc_name, sizeof(mdus->MercData[merc_index].MercName)); + + uint32 stanceindex = 0; + if (stance_it != zone->merc_stance_list.end()) { + for (const auto& stance : stance_it->second) { + mdus->MercData[merc_index].Stances[stanceindex].StanceIndex = stanceindex; + mdus->MercData[merc_index].Stances[stanceindex].Stance = stance.StanceID; + stanceindex++; + } + } + + mdus->MercData[merc_index].MercUnk05 = std::min(RuleI(Mercs, MaxMercSlots), MAXMERCS); + merc_index++; + }; + + // Emit the active merc slot first — the client marks the first entry + // in the list with the X (active marker), so order matters. + if (GetMercSlot() < max_slots && GetMercInfo().mercid != 0) { + fillMercEntry(GetMercSlot()); } - mdus->MercData[i].MercUnk05 = 1; + // Then emit remaining owned mercs in slot order + for (int slot = 0; slot < max_slots; slot++) { + if (slot == GetMercSlot()) { + continue; // already emitted + } + fillMercEntry(slot); + } + + // Update count in case we skipped any invalid entries + mdus->MercCount = merc_index; + FastQueuePacket(&outapp); safe_delete(outapp); return; } else { + // Pre-RoF path (SoD and earlier) — single merc only + if (GetMercInfo().MercTemplateID == 0) { + SendClearMercInfo(); + return; + } + + auto tmpl_it = zone->merc_templates.find(GetMercInfo().MercTemplateID); + if (tmpl_it == zone->merc_templates.end()) { + SendClearMercInfo(); + return; + } + + MercTemplate *mercData = &tmpl_it->second; + uint32 mercTypeCount = 1; + uint32 mercCount = 1; + uint32 i = 0; + auto outapp = new EQApplicationPacket(OP_MercenaryDataResponse, sizeof(MercenaryMerchantList_Struct)); auto mml = (MercenaryMerchantList_Struct *) outapp->pBuffer; - mml->MercTypeCount = mercTypeCount; //We should only have one merc entry. + mml->MercTypeCount = mercTypeCount; mml->MercGrades[i] = 1; mml->MercCount = mercCount; diff --git a/zone/client.h b/zone/client.h index 4e9b5e8913..62709bbd03 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1773,6 +1773,7 @@ class Client : public Mob MercInfo& GetMercInfo(uint8 slot) { return m_mercinfo[slot]; } MercInfo& GetMercInfo() { return m_mercinfo[mercSlot]; } uint8 GetNumberOfMercenaries(); + int GetFirstFreeMercSlot(); void SetMerc(Merc* newmerc); void SendMercResponsePackets(uint32 ResponseType); void SendMercMerchantResponsePacket(int32 response_type); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 7fc5174f6b..13e55df4de 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -305,6 +305,7 @@ void MapOpcodes() ConnectedOpcodes[OP_MercenaryDismiss] = &Client::Handle_OP_MercenaryDismiss; ConnectedOpcodes[OP_MercenaryHire] = &Client::Handle_OP_MercenaryHire; ConnectedOpcodes[OP_MercenarySuspendRequest] = &Client::Handle_OP_MercenarySuspendRequest; + ConnectedOpcodes[OP_MercenarySwitch] = &Client::Handle_OP_MercenarySwitch; ConnectedOpcodes[OP_MercenaryTimerRequest] = &Client::Handle_OP_MercenaryTimerRequest; ConnectedOpcodes[OP_MoveCoin] = &Client::Handle_OP_MoveCoin; ConnectedOpcodes[OP_MoveItem] = &Client::Handle_OP_MoveItem; @@ -10430,7 +10431,7 @@ void Client::Handle_OP_MercenaryCommand(const EQApplicationPacket *app) } MercenaryCommand_Struct* mc = (MercenaryCommand_Struct*)app->pBuffer; - uint32 merc_command = mc->MercCommand; // Seen 0 (zone in with no merc or suspended), 1 (dismiss merc), 5 (normal state), 20 (unknown), 36 (zone in with merc) + uint32 merc_command = mc->MercCommand; // Seen 0 (zone in with no merc or suspended), 1 (stance/state update), 5 (normal state), 20 (unknown), 36 (zone in with merc) int32 option = mc->Option; // Seen -1 (zone in with no merc), 0 (setting to passive stance), 1 (normal or setting to balanced stance) Log(Logs::General, Logs::Mercenaries, "Command %i, Option %i received from %s.", merc_command, option, GetName()); @@ -10438,9 +10439,6 @@ void Client::Handle_OP_MercenaryCommand(const EQApplicationPacket *app) if (!RuleB(Mercs, AllowMercs)) return; - // Handle the Command here... - // Will need a list of what every type of command is supposed to do - // Unsure if there is a server response to this packet if (option >= 0) { Merc* merc = GetMerc(); @@ -10496,14 +10494,14 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app) if (merchant_id == 0) { //send info about your current merc(s) - if (GetMercInfo().mercid) + if (GetNumberOfMercenaries() > 0) { Log(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Request for %s.", GetName()); SendMercPersonalInfo(); } else { - Log(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Not Sent - MercID (%i) for %s.", GetMercInfo().mercid, GetName()); + Log(Logs::General, Logs::Mercenaries, "SendMercPersonalInfo Not Sent - no mercs owned for %s.", GetName()); } } @@ -10687,6 +10685,22 @@ void Client::Handle_OP_MercenaryHire(const EQApplicationPacket *app) return; } + // Suspend active merc if one exists before hiring into a new slot + Merc* current_merc = GetMerc(); + if (current_merc) { + current_merc->Suspend(); + current_merc->SetOwnerID(0); + SetMercID(0); + } + + // Select a free slot for the new hire + int free_slot = GetFirstFreeMercSlot(); + if (free_slot < 0) { + SendMercResponsePackets(6); + return; + } + SetMercSlot(static_cast(free_slot)); + // Set time remaining to max on Hire GetMercInfo().MercTimerRemaining = RuleI(Mercs, UpkeepIntervalMS); @@ -10706,6 +10720,10 @@ void Client::Handle_OP_MercenaryHire(const EQApplicationPacket *app) // approved hire request SendMercMerchantResponsePacket(0); + + // Update the client's Manage tab with the newly hired merc info + SendMercPersonalInfo(); + SendMercTimer(merc); } else { @@ -10742,6 +10760,88 @@ void Client::Handle_OP_MercenarySuspendRequest(const EQApplicationPacket *app) SuspendMercCommand(); } +void Client::Handle_OP_MercenarySwitch(const EQApplicationPacket *app) +{ + if (app->size != sizeof(SwitchMercenary_Struct)) { + LogDebug("Size mismatch in OP_MercenarySwitch expected [{}] got [{}]", sizeof(SwitchMercenary_Struct), app->size); + DumpPacket(app); + return; + } + + if (!RuleB(Mercs, AllowMercs)) + return; + + SwitchMercenary_Struct* sm = (SwitchMercenary_Struct*)app->pBuffer; + uint32 merc_ui_index = sm->MercIndex; + + Log(Logs::General, Logs::Mercenaries, "Switch request to UI index %u received from %s.", merc_ui_index, GetName()); + + // The client sends a dense UI index (0, 1, 2...) that corresponds to the Nth + // owned merc in the list, matching the order sent by SendMercPersonalInfo(). + // SendMercPersonalInfo emits the active slot first, then remaining slots in order. + // We must replicate that same ordering to map UI index -> internal slot. + int target_slot = -1; + int max_slots = std::min(RuleI(Mercs, MaxMercSlots), MAXMERCS); + uint32 ui_pos = 0; + + // First: the active merc slot (emitted first in the packet) + if (GetMercSlot() < max_slots && m_mercinfo[GetMercSlot()].mercid != 0) { + if (ui_pos == merc_ui_index) { + target_slot = GetMercSlot(); + } + ui_pos++; + } + + // Then: remaining slots in order (skipping active slot) + if (target_slot < 0) { + for (int slot = 0; slot < max_slots; slot++) { + if (slot == GetMercSlot()) { + continue; + } + if (m_mercinfo[slot].mercid != 0) { + if (ui_pos == merc_ui_index) { + target_slot = slot; + break; + } + ui_pos++; + } + } + } + + if (target_slot < 0) { + Log(Logs::General, Logs::Mercenaries, "Switch request denied — UI index %u has no corresponding merc for %s.", merc_ui_index, GetName()); + SendMercResponsePackets(0); + return; + } + + if (target_slot == GetMercSlot()) { + Log(Logs::General, Logs::Mercenaries, "Switch request ignored — already on slot %i for %s.", target_slot, GetName()); + return; + } + + // Suspend the currently active merc if one is spawned + Merc* current_merc = GetMerc(); + if (current_merc) { + current_merc->Suspend(); + // Clear merc pointer without wiping slot data (SetMerc(nullptr) would zero the slot) + current_merc->SetOwnerID(0); + SetMercID(0); + } + + // Clear the suspend timer so the target merc can be unsuspended immediately. + // The cooldown is meant for rapid suspend/unsuspend of the same merc, not for switching. + if (!GetPTimers().Expired(&database, pTimerMercSuspend, false)) { + GetPTimers().Clear(&database, pTimerMercSuspend); + } + + SetMercSlot(static_cast(target_slot)); + + Log(Logs::General, Logs::Mercenaries, "Switched active merc slot to %i (UI index %u) for %s.", target_slot, merc_ui_index, GetName()); + + // Unsuspend the target merc + SuspendMercCommand(); +} + void Client::Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app) { // The payload is 0 bytes. diff --git a/zone/client_packet.h b/zone/client_packet.h index 009dd75d64..b2a455b975 100644 --- a/zone/client_packet.h +++ b/zone/client_packet.h @@ -239,6 +239,7 @@ void Handle_OP_MercenaryDismiss(const EQApplicationPacket *app); void Handle_OP_MercenaryHire(const EQApplicationPacket *app); void Handle_OP_MercenarySuspendRequest(const EQApplicationPacket *app); + void Handle_OP_MercenarySwitch(const EQApplicationPacket *app); void Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app); void Handle_OP_MoveCoin(const EQApplicationPacket *app); void Handle_OP_MoveItem(const EQApplicationPacket *app); diff --git a/zone/merc.cpp b/zone/merc.cpp index 283132a2d0..d9212db8d7 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -4885,14 +4885,8 @@ bool Client::CheckCanHireMerc(Mob* merchant, uint32 template_id) { MercTemplate* mercTemplate = zone->GetMercTemplate(template_id); - //check for suspended merc - if(GetMercInfo().mercid != 0 && GetMercInfo().IsSuspended) { - SendMercResponsePackets(6); - return false; - } - - // Check if max number of mercs is already reached - if(GetNumberOfMercenaries() >= MAXMERCS) { + // Check if all merc slots are full (counts both active and suspended mercs) + if (GetFirstFreeMercSlot() < 0) { SendMercResponsePackets(6); return false; } @@ -5046,8 +5040,21 @@ void Client::SuspendMercCommand() { return; } + // Suspend any currently active merc before unsuspending this one + Merc* active_merc = GetMerc(); + if (active_merc) { + active_merc->Suspend(); + SetMerc(nullptr); + } + // Get merc, assign it to client & spawn - Merc* merc = Merc::LoadMercenary(this, &zone->merc_templates[GetMercInfo().MercTemplateID], 0, true); + auto tmpl_it = zone->merc_templates.find(GetMercInfo().MercTemplateID); + if (tmpl_it == zone->merc_templates.end()) { + SendMercResponsePackets(3); + Log(Logs::General, Logs::Mercenaries, "SuspendMercCommand Invalid template for %s.", GetName()); + return; + } + Merc* merc = Merc::LoadMercenary(this, &tmpl_it->second, 0, true); if(merc) { SpawnMerc(merc, false); @@ -5119,40 +5126,56 @@ void Client::SpawnMercOnZone() { if(database.LoadMercenaryInfo(this)) { - if(!GetMercInfo().IsSuspended) - { + // Find the active (non-suspended) merc slot, or fall back to the first owned slot + int active_slot = -1; + int first_owned_slot = -1; + int max_slots = std::min(RuleI(Mercs, MaxMercSlots), MAXMERCS); + for (int slot = 0; slot < max_slots; slot++) { + if (GetMercInfo(slot).mercid != 0) { + if (first_owned_slot < 0) { + first_owned_slot = slot; + } + if (!GetMercInfo(slot).IsSuspended) { + active_slot = slot; + break; + } + } + } + + if (active_slot >= 0) { + SetMercSlot(static_cast(active_slot)); GetMercInfo().SuspendedTime = 0; // Get merc, assign it to client & spawn - Merc* merc = Merc::LoadMercenary(this, &zone->merc_templates[GetMercInfo().MercTemplateID], 0, true); - if(merc) - { - SpawnMerc(merc, false); + auto tmpl_it = zone->merc_templates.find(GetMercInfo().MercTemplateID); + if (tmpl_it != zone->merc_templates.end()) { + Merc* merc = Merc::LoadMercenary(this, &tmpl_it->second, 0, true); + if (merc) { + SpawnMerc(merc, false); + } } - Log(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Normal Merc for %s.", GetName()); - } - else - { + Log(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Normal Merc (slot %i) for %s.", active_slot, GetName()); + } else if (first_owned_slot >= 0) { + SetMercSlot(static_cast(first_owned_slot)); int32 TimeDiff = GetMercInfo().SuspendedTime - time(nullptr); - if (TimeDiff > 0) - { - if (!GetPTimers().Enabled(pTimerMercSuspend)) - { - // Start the timer to send the packet that refreshes the Unsuspend Button + if (TimeDiff > 0) { + if (!GetPTimers().Enabled(pTimerMercSuspend)) { GetPTimers().Start(pTimerMercSuspend, TimeDiff); } } - // Send Mercenary Status/Timer packet SendMercTimer(GetMerc()); + Log(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Suspended Merc (slot %i) for %s.", first_owned_slot, GetName()); + } else { + Log(Logs::General, Logs::Mercenaries, "SpawnMercOnZone No valid merc slots found for %s.", GetName()); + } - Log(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Suspended Merc for %s.", GetName()); + // Send merc personal info for all owned mercs (populates the Manage tab) + if (GetNumberOfMercenaries() > 0) { + SendMercPersonalInfo(); } } else { - // No Merc Hired - // RoF+ displays a message from the following packet, which seems useless - //SendClearMercInfo(); - Log(Logs::General, Logs::Mercenaries, "SpawnMercOnZone Failed to load Merc Info from the Database for %s.", GetName()); + Log(Logs::General, Logs::Mercenaries, "SpawnMercOnZone No merc info in database for %s.", GetName()); } } @@ -5323,9 +5346,18 @@ bool Client::DismissMerc(uint32 MercID) { GetMerc()->Depop(); } - SendClearMercInfo(); + // Clear the dismissed merc's slot data so it becomes available + memset(&GetMercInfo(), 0, sizeof(MercInfo)); + SetMerc(nullptr); + // Update the client with remaining mercs or clear if none left + if (GetNumberOfMercenaries() > 0) { + SendMercPersonalInfo(); + } else { + SendClearMercInfo(); + } + return Dismissed; } @@ -5579,6 +5611,17 @@ uint8 Client::GetNumberOfMercenaries() return count; } +int Client::GetFirstFreeMercSlot() +{ + int max_slots = std::min(RuleI(Mercs, MaxMercSlots), MAXMERCS); + for (int slot_id = 0; slot_id < max_slots; slot_id++) { + if (m_mercinfo[slot_id].mercid == 0) { + return slot_id; + } + } + return -1; +} + void Merc::SetMercData( uint32 template_id ) { MercTemplate* merc_template = zone->GetMercTemplate(template_id); diff --git a/zone/merc.h b/zone/merc.h index fb27c9f875..0eba77f174 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -33,7 +33,7 @@ namespace EQ struct ItemData; } -#define MAXMERCS 1 +constexpr int MAXMERCS = 11; #define TANK 1 #define HEALER 2 #define MELEEDPS 9 diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 703f012ad0..24414a2d02 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2225,7 +2225,7 @@ bool ZoneDatabase::LoadCurrentMercenary(Client* c) { const uint8 mercenary_slot = c->GetMercSlot(); - if (mercenary_slot > MAXMERCS) { + if (mercenary_slot >= MAXMERCS) { return false; } @@ -2277,7 +2277,7 @@ bool ZoneDatabase::SaveMercenary(Merc* m) auto e = MercsRepository::NewEntity(); e.OwnerCharacterID = m->GetMercenaryCharacterID(); - e.Slot = (c->GetNumberOfMercenaries() - 1); + e.Slot = c->GetMercSlot(); e.Name = m->GetCleanName(); e.TemplateID = m->GetMercenaryTemplateID(); e.SuspendedTime = c->GetMercInfo().SuspendedTime; @@ -2318,7 +2318,7 @@ bool ZoneDatabase::SaveMercenary(Merc* m) auto e = MercsRepository::FindOne(*this, m->GetMercenaryID()); e.OwnerCharacterID = m->GetMercenaryCharacterID(); - e.Slot = (c->GetNumberOfMercenaries() - 1); + e.Slot = c->GetMercSlot(); e.Name = m->GetCleanName(); e.TemplateID = m->GetMercenaryTemplateID(); e.SuspendedTime = c->GetMercInfo().SuspendedTime; From 6694281f2243278f5517e97fd1e937a7f2dbd237 Mon Sep 17 00:00:00 2001 From: brainiac Date: Fri, 24 Apr 2026 23:05:32 -0700 Subject: [PATCH 105/194] Fix gcc warnings (#5071) --- CMakeLists.txt | 2 +- common/CMakeLists.txt | 1 + common/compiler_macros.h | 20 ++++++++ common/json/jsoncpp.cpp | 8 --- libs/luabind/luabind/adopt_policy.hpp | 2 +- libs/luabind/luabind/class.hpp | 2 +- libs/luabind/luabind/detail/constructor.hpp | 8 +-- .../luabind/detail/has_get_pointer.hpp | 2 +- .../luabind/detail/instance_holder.hpp | 4 +- libs/luabind/luabind/detail/make_instance.hpp | 2 +- libs/luabind/luabind/detail/policy.hpp | 6 +-- libs/luabind/luabind/function.hpp | 2 +- libs/luabind/luabind/scope.hpp | 2 +- libs/luabind/src/class.cpp | 10 ++-- libs/luabind/src/scope.cpp | 5 +- loginserver/encryption.cpp | 5 ++ zone/embparser.cpp | 50 +++++++++++-------- zone/lua_packet.cpp | 10 ++++ zone/lua_packet.h | 2 +- zone/lua_ptr.h | 3 +- 20 files changed, 91 insertions(+), 55 deletions(-) create mode 100644 common/compiler_macros.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bbbeda68b..d89f370d93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,7 @@ option(EQEMU_BUILD_PCH "Build with precompiled headers (Windows)" ON) if(MSVC) add_compile_options(/bigobj) - add_compile_definitions(_CRT_SECURE_NO_WARNINGS NOMINMAX WIN32_LEAN_AND_MEAN CRASH_LOGGING _HAS_AUTO_PTR_ETC) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS NOMINMAX WIN32_LEAN_AND_MEAN CRASH_LOGGING) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") option(EQEMU_DISABLE_MSVC_WARNINGS "Disable MSVC compile warnings." OFF) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index e9f43cec80..ba3844d39a 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -6,6 +6,7 @@ set(common_sources bodytypes.cpp classes.cpp cli/eqemu_command_handler.cpp + compiler_macros.h compression.cpp content/world_content_service.cpp crash.cpp diff --git a/common/compiler_macros.h b/common/compiler_macros.h new file mode 100644 index 0000000000..16088a4054 --- /dev/null +++ b/common/compiler_macros.h @@ -0,0 +1,20 @@ +#pragma once + +#if defined(_MSC_VER) + #define PUSH_DISABLE_DEPRECATED_WARNINGS() __pragma(warning(push)) \ + __pragma(warning(disable:4996)) + #define POP_DISABLE_DEPRECATED_WARNINGS() __pragma(warning(pop)) +#elif defined(__GNUC__) || defined(__clang__) + #define PUSH_DISABLE_DEPRECATED_WARNINGS() _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") + #define POP_DISABLE_DEPRECATED_WARNINGS() _Pragma("GCC diagnostic pop") +#else + #define PUSH_DISABLE_DEPRECATED_WARNINGS() + #define POP_DISABLE_DEPRECATED_WARNINGS() +#endif + +#if defined(_MSC_VER) && !defined(__clang__) + #define UNREACHABLE() __assume(0) +#else + #define UNREACHABLE() __builtin_unreachable() +#endif \ No newline at end of file diff --git a/common/json/jsoncpp.cpp b/common/json/jsoncpp.cpp index 759e68fa64..eb1bd5a140 100644 --- a/common/json/jsoncpp.cpp +++ b/common/json/jsoncpp.cpp @@ -271,11 +271,7 @@ static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readVa namespace Json { -#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) typedef std::unique_ptr CharReaderPtr; -#else -typedef std::auto_ptr CharReaderPtr; -#endif // Implementation of class Features // //////////////////////////////// @@ -4153,11 +4149,7 @@ Value& Path::make(Value& root) const { namespace Json { -#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) typedef std::unique_ptr StreamWriterPtr; -#else -typedef std::auto_ptr StreamWriterPtr; -#endif static bool containsControlCharacter(const char* str) { while (*str) { diff --git a/libs/luabind/luabind/adopt_policy.hpp b/libs/luabind/luabind/adopt_policy.hpp index 5e81b948bf..dc2426a05d 100644 --- a/libs/luabind/luabind/adopt_policy.hpp +++ b/libs/luabind/luabind/adopt_policy.hpp @@ -103,7 +103,7 @@ namespace luabind { namespace detail if (luabind::move_back_reference(L, ptr)) return; - make_instance(L, std::auto_ptr(ptr)); + make_instance(L, std::unique_ptr(ptr)); } }; diff --git a/libs/luabind/luabind/class.hpp b/libs/luabind/luabind/class.hpp index 5b8636b97d..a2188b358b 100644 --- a/libs/luabind/luabind/class.hpp +++ b/libs/luabind/luabind/class.hpp @@ -335,7 +335,7 @@ namespace luabind template struct default_pointer { - typedef std::auto_ptr type; + typedef std::unique_ptr type; }; template diff --git a/libs/luabind/luabind/detail/constructor.hpp b/libs/luabind/luabind/detail/constructor.hpp index 1cbceb7899..c3fc8ba7c0 100644 --- a/libs/luabind/luabind/detail/constructor.hpp +++ b/libs/luabind/luabind/detail/constructor.hpp @@ -46,7 +46,7 @@ struct construct_aux<0, T, Pointer, Signature> object_rep* self = touserdata(self_); class_rep* cls = self->crep(); - std::auto_ptr instance(new T); + std::unique_ptr instance(new T); inject_backref(self_.interpreter(), instance.get(), instance.get()); void* naked_ptr = instance.get(); @@ -55,7 +55,7 @@ struct construct_aux<0, T, Pointer, Signature> void* storage = self->allocate(sizeof(holder_type)); self->set_instance(new (storage) holder_type( - ptr, registered_class::id, naked_ptr, cls)); + std::move(ptr), registered_class::id, naked_ptr, cls)); } }; @@ -92,7 +92,7 @@ struct construct_aux object_rep* self = touserdata(self_); class_rep* cls = self->crep(); - std::auto_ptr instance(new T(BOOST_PP_ENUM_PARAMS(N,_))); + std::unique_ptr instance(new T(BOOST_PP_ENUM_PARAMS(N,_))); inject_backref(self_.interpreter(), instance.get(), instance.get()); void* naked_ptr = instance.get(); @@ -101,7 +101,7 @@ struct construct_aux void* storage = self->allocate(sizeof(holder_type)); self->set_instance(new (storage) holder_type( - ptr, registered_class::id, naked_ptr, cls)); + std::move(ptr), registered_class::id, naked_ptr, cls)); } }; diff --git a/libs/luabind/luabind/detail/has_get_pointer.hpp b/libs/luabind/luabind/detail/has_get_pointer.hpp index 8a001ddda4..67d6a7639b 100644 --- a/libs/luabind/luabind/detail/has_get_pointer.hpp +++ b/libs/luabind/luabind/detail/has_get_pointer.hpp @@ -58,7 +58,7 @@ namespace has_get_pointer_ T* get_pointer(T const volatile*); template - T* get_pointer(std::auto_ptr const&); + T* get_pointer(std::unique_ptr const&); # endif diff --git a/libs/luabind/luabind/detail/instance_holder.hpp b/libs/luabind/luabind/detail/instance_holder.hpp index 456e13e6b3..2c1d5d9551 100644 --- a/libs/luabind/luabind/detail/instance_holder.hpp +++ b/libs/luabind/luabind/detail/instance_holder.hpp @@ -57,7 +57,7 @@ inline mpl::true_ check_const_pointer(void const*) } template -void release_ownership(std::auto_ptr& p) +void release_ownership(std::unique_ptr& p) { p.release(); } @@ -83,7 +83,7 @@ class pointer_holder : public instance_holder P p, class_id dynamic_id, void* dynamic_ptr, class_rep* cls ) : instance_holder(cls, check_const_pointer(false ? get_pointer(p) : 0)) - , p(p) + , p(std::move(p)) , weak(0) , dynamic_id(dynamic_id) , dynamic_ptr(dynamic_ptr) diff --git a/libs/luabind/luabind/detail/make_instance.hpp b/libs/luabind/luabind/detail/make_instance.hpp index 3150cf0487..66d23fbd88 100644 --- a/libs/luabind/luabind/detail/make_instance.hpp +++ b/libs/luabind/luabind/detail/make_instance.hpp @@ -88,7 +88,7 @@ void make_instance(lua_State* L, P p) try { - new (storage) holder_type(p, dynamic.first, dynamic.second, cls); + new (storage) holder_type(std::move(p), dynamic.first, dynamic.second, cls); } catch (...) { diff --git a/libs/luabind/luabind/detail/policy.hpp b/libs/luabind/luabind/detail/policy.hpp index e154507e49..19cd2f1aea 100644 --- a/libs/luabind/luabind/detail/policy.hpp +++ b/libs/luabind/luabind/detail/policy.hpp @@ -169,7 +169,7 @@ namespace luabind { namespace detail { if (get_pointer(x)) { - make_instance(L, x); + make_instance(L, std::move(x)); } else { @@ -180,8 +180,8 @@ namespace luabind { namespace detail template void make_pointee_instance(lua_State* L, T& x, mpl::false_, mpl::true_) { - std::auto_ptr ptr(new T(x)); - make_instance(L, ptr); + std::unique_ptr ptr(new T(x)); + make_instance(L, std::move(ptr)); } template diff --git a/libs/luabind/luabind/function.hpp b/libs/luabind/luabind/function.hpp index e156fbfcb9..b93ca2627c 100644 --- a/libs/luabind/luabind/function.hpp +++ b/libs/luabind/luabind/function.hpp @@ -46,7 +46,7 @@ namespace detail template scope def(char const* name, F f, Policies const& policies) { - return scope(std::auto_ptr( + return scope(std::unique_ptr( new detail::function_registration(name, f, policies))); } diff --git a/libs/luabind/luabind/scope.hpp b/libs/luabind/luabind/scope.hpp index 3b5f293bfb..e2cfaed360 100644 --- a/libs/luabind/luabind/scope.hpp +++ b/libs/luabind/luabind/scope.hpp @@ -56,7 +56,7 @@ namespace luabind { struct LUABIND_API scope { scope(); - explicit scope(std::auto_ptr reg); + explicit scope(std::unique_ptr reg); scope(scope const& other_); ~scope(); diff --git a/libs/luabind/src/class.cpp b/libs/luabind/src/class.cpp index 8a67cf6f3d..f42b9a8c08 100644 --- a/libs/luabind/src/class.cpp +++ b/libs/luabind/src/class.cpp @@ -235,7 +235,7 @@ namespace luabind { namespace detail { // -- interface --------------------------------------------------------- class_base::class_base(char const* name) - : scope(std::auto_ptr( + : scope(std::unique_ptr( m_registration = new class_registration(name)) ) { @@ -258,14 +258,14 @@ namespace luabind { namespace detail { void class_base::add_member(registration* member) { - std::auto_ptr ptr(member); - m_registration->m_members.operator,(scope(ptr)); + std::unique_ptr ptr(member); + m_registration->m_members.operator,(scope(std::move(ptr))); } void class_base::add_default_member(registration* member) { - std::auto_ptr ptr(member); - m_registration->m_default_members.operator,(scope(ptr)); + std::unique_ptr ptr(member); + m_registration->m_default_members.operator,(scope(std::move(ptr))); } const char* class_base::name() const diff --git a/libs/luabind/src/scope.cpp b/libs/luabind/src/scope.cpp index 52bd132f97..0333205cea 100644 --- a/libs/luabind/src/scope.cpp +++ b/libs/luabind/src/scope.cpp @@ -49,7 +49,8 @@ namespace luabind { namespace detail { { } - scope::scope(std::auto_ptr reg) + + scope::scope(std::unique_ptr reg) : m_chain(reg.release()) { } @@ -193,7 +194,7 @@ namespace luabind { }; namespace_::namespace_(char const* name) - : scope(std::auto_ptr( + : scope(std::unique_ptr( m_registration = new registration_(name))) { } diff --git a/loginserver/encryption.cpp b/loginserver/encryption.cpp index 2ef0713bdf..dabbef7616 100644 --- a/loginserver/encryption.cpp +++ b/loginserver/encryption.cpp @@ -16,6 +16,7 @@ along with this program. If not, see . */ #include "encryption.h" +#include "common/compiler_macros.h" #ifdef EQEMU_USE_OPENSSL #include @@ -137,7 +138,9 @@ const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buff return nullptr; } + PUSH_DISABLE_DEPRECATED_WARNINGS() DES_ncbc_encrypt((const unsigned char*)buffer_in, (unsigned char*)buffer_out, (long)buffer_in_sz, &k, &v, enc); + POP_DISABLE_DEPRECATED_WARNINGS() #endif return buffer_out; } @@ -164,7 +167,9 @@ std::string eqcrypt_md5(const std::string &msg) unsigned char md5_digest[16]; char tmp[4]; + PUSH_DISABLE_DEPRECATED_WARNINGS() MD5((const unsigned char*)msg.c_str(), msg.length(), md5_digest); + POP_DISABLE_DEPRECATED_WARNINGS() for (int i = 0; i < 16; ++i) { sprintf(&tmp[0], "%02x", md5_digest[i]); diff --git a/zone/embparser.cpp b/zone/embparser.cpp index b617daae7b..52863b6988 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -17,11 +17,13 @@ */ #ifdef EMBPERL +#include "zone/embparser.h" + +#include "common/compiler_macros.h" #include "common/features.h" #include "common/misc_functions.h" #include "common/seperator.h" #include "common/strings.h" -#include "zone/embparser.h" #include "zone/masterentity.h" #include "zone/qglobals.h" #include "zone/questmgr.h" @@ -398,6 +400,8 @@ int PerlembParser::EventCommon( zone ); } + + return 0; } int PerlembParser::EventNPC( @@ -1211,31 +1215,33 @@ QuestType PerlembParser::GetQuestTypes( event_id == EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE ) { return is_global ? QuestType::SpellGlobal : QuestType::Spell; - } else { - if (npc_mob) { - if (!inst) { - if (npc_mob->IsBot()) { - return is_global ? QuestType::BotGlobal : QuestType::Bot; - } else if (npc_mob->IsMerc()) { - return is_global ? QuestType::MercGlobal : QuestType::Merc; - } else if (npc_mob->IsNPC()) { - return is_global ? QuestType::NPCGlobal : QuestType::NPC; - } - } else { - return is_global ? QuestType::ItemGlobal : QuestType::Item; + } + + if (npc_mob) { + if (!inst) { + if (npc_mob->IsBot()) { + return is_global ? QuestType::BotGlobal : QuestType::Bot; + } else if (npc_mob->IsMerc()) { + return is_global ? QuestType::MercGlobal : QuestType::Merc; + } else if (npc_mob->IsNPC()) { + return is_global ? QuestType::NPCGlobal : QuestType::NPC; } - } else if (!npc_mob && mob) { - if (!inst) { - if (mob->IsClient()) { - return is_global ? QuestType::PlayerGlobal : QuestType::Player; - } - } else { - return is_global ? QuestType::ItemGlobal : QuestType::Item; + } else { + return is_global ? QuestType::ItemGlobal : QuestType::Item; + } + } else if (mob) { + if (!inst) { + if (mob->IsClient()) { + return is_global ? QuestType::PlayerGlobal : QuestType::Player; } - } else if (zone) { - return is_global ? QuestType::ZoneGlobal : QuestType::Zone; + } else { + return is_global ? QuestType::ItemGlobal : QuestType::Item; } + } else if (zone) { + return is_global ? QuestType::ZoneGlobal : QuestType::Zone; } + + UNREACHABLE(); } std::string PerlembParser::GetQuestPackageName( diff --git a/zone/lua_packet.cpp b/zone/lua_packet.cpp index 8f231363e9..fb2ada0b5a 100644 --- a/zone/lua_packet.cpp +++ b/zone/lua_packet.cpp @@ -82,6 +82,16 @@ Lua_Packet::Lua_Packet(const Lua_Packet& o) { } } +Lua_Packet::~Lua_Packet() +{ + if (owned_) { + EQApplicationPacket* ptr = GetLuaPtrData(); + if (ptr) { + delete ptr; + } + } +} + int Lua_Packet::GetSize() { Lua_Safe_Call_Int(); return static_cast(self->size); diff --git a/zone/lua_packet.h b/zone/lua_packet.h index b5b3753716..df94b3811c 100644 --- a/zone/lua_packet.h +++ b/zone/lua_packet.h @@ -41,7 +41,7 @@ class Lua_Packet : public Lua_Ptr Lua_Packet(int opcode, int size, bool raw); Lua_Packet& operator=(const Lua_Packet& o); Lua_Packet(const Lua_Packet& o); - virtual ~Lua_Packet() { if(owned_) { EQApplicationPacket *ptr = GetLuaPtrData(); if(ptr) { delete ptr; } } } + virtual ~Lua_Packet(); int GetSize(); int GetOpcode(); diff --git a/zone/lua_ptr.h b/zone/lua_ptr.h index 7dbf9100c4..9333dd9a83 100644 --- a/zone/lua_ptr.h +++ b/zone/lua_ptr.h @@ -48,7 +48,8 @@ class Lua_Ptr Lua_Ptr(T *d) : d_(d) { } - ~Lua_Ptr() { + + virtual ~Lua_Ptr() { } T *GetLuaPtrData() { From 6d6cc8ca95c29ee9402b79a90293d666630df3ad Mon Sep 17 00:00:00 2001 From: Knightly <55611098+Knightly1@users.noreply.github.com> Date: Sat, 25 Apr 2026 13:49:03 -1000 Subject: [PATCH 106/194] Update openssl calls to use EVP interface (#5072) --- loginserver/encryption.cpp | 131 ++++++++++++++++++++++++++++--------- loginserver/encryption.h | 10 +++ loginserver/main.cpp | 8 +++ 3 files changed, 118 insertions(+), 31 deletions(-) diff --git a/loginserver/encryption.cpp b/loginserver/encryption.cpp index dabbef7616..3fa140768d 100644 --- a/loginserver/encryption.cpp +++ b/loginserver/encryption.cpp @@ -19,9 +19,9 @@ #include "common/compiler_macros.h" #ifdef EQEMU_USE_OPENSSL -#include -#include -#include +#include +#include +#include #endif #ifdef EQEMU_USE_MBEDTLS #include @@ -33,6 +33,8 @@ #include #include +#include + #ifdef ENABLE_SECURITY #include @@ -128,23 +130,92 @@ const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buff #endif #ifdef EQEMU_USE_OPENSSL - DES_key_schedule k; - DES_cblock v; + // Decrypt requires block-aligned input; encrypt zero-pads a trailing + // partial block to match the legacy DES_ncbc_encrypt semantics the + // game protocol expects. + if (!enc && buffer_in_sz && buffer_in_sz % 8 != 0) { + return nullptr; + } - memset(&k, 0, sizeof(DES_key_schedule)); - memset(&v, 0, sizeof(DES_cblock)); + unsigned char key[8] = {0}; + unsigned char iv[8] = {0}; - if (!enc && buffer_in_sz && buffer_in_sz % 8 != 0) { + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + if (!ctx) { return nullptr; } - PUSH_DISABLE_DEPRECATED_WARNINGS() - DES_ncbc_encrypt((const unsigned char*)buffer_in, (unsigned char*)buffer_out, (long)buffer_in_sz, &k, &v, enc); - POP_DISABLE_DEPRECATED_WARNINGS() + bool result = EVP_CipherInit_ex2(ctx, EVP_des_cbc(), key, iv, enc, nullptr) == 1; + if (result) { + EVP_CIPHER_CTX_set_padding(ctx, 0); + + const unsigned char* src = reinterpret_cast(buffer_in); + size_t src_len = buffer_in_sz; + std::unique_ptr padded; + + if (enc && buffer_in_sz % 8 != 0) { + src_len = ((buffer_in_sz / 8) + 1) * 8; + padded.reset(new unsigned char[src_len]()); + memcpy(padded.get(), buffer_in, buffer_in_sz); + src = padded.get(); + } + + int outl = 0; + int final_len = 0; + result = EVP_CipherUpdate(ctx, reinterpret_cast(buffer_out), &outl, src, static_cast(src_len)) == 1 + && EVP_CipherFinal_ex(ctx, reinterpret_cast(buffer_out) + outl, &final_len) == 1; + } + + EVP_CIPHER_CTX_free(ctx); + if (!result) { + return nullptr; + } #endif return buffer_out; } +#ifdef EQEMU_USE_OPENSSL +static OSSL_PROVIDER *s_legacy_provider = nullptr; +static OSSL_PROVIDER *s_default_provider = nullptr; +#endif + +bool eqcrypt_init() +{ +#ifdef EQEMU_USE_OPENSSL + if (!s_default_provider) { + s_default_provider = OSSL_PROVIDER_load(nullptr, "default"); + } + if (!s_legacy_provider) { + s_legacy_provider = OSSL_PROVIDER_load(nullptr, "legacy"); + } + + if (!s_default_provider || !s_legacy_provider) { + char buf[256]; + while (auto err = ERR_get_error()) { + ERR_error_string_n(err, buf, sizeof(buf)); + LogError("OpenSSL provider load failure: {}", buf); + } + return false; + } +#endif + + return true; +} + +void eqcrypt_shutdown() +{ +#ifdef EQEMU_USE_OPENSSL + if (s_legacy_provider) { + OSSL_PROVIDER_unload(s_legacy_provider); + s_legacy_provider = nullptr; + } + if (s_default_provider) { + OSSL_PROVIDER_unload(s_default_provider); + s_default_provider = nullptr; + } +#endif +} + std::string eqcrypt_md5(const std::string &msg) { std::string ret; @@ -167,14 +238,12 @@ std::string eqcrypt_md5(const std::string &msg) unsigned char md5_digest[16]; char tmp[4]; - PUSH_DISABLE_DEPRECATED_WARNINGS() - MD5((const unsigned char*)msg.c_str(), msg.length(), md5_digest); - POP_DISABLE_DEPRECATED_WARNINGS() - - for (int i = 0; i < 16; ++i) { - sprintf(&tmp[0], "%02x", md5_digest[i]); - ret.push_back(tmp[0]); - ret.push_back(tmp[1]); + if (EVP_Digest(msg.data(), msg.length(), md5_digest, nullptr, EVP_md5(), nullptr) == 1) { + for (int i = 0; i < 16; ++i) { + sprintf(&tmp[0], "%02x", md5_digest[i]); + ret.push_back(tmp[0]); + ret.push_back(tmp[1]); + } } #endif @@ -203,12 +272,12 @@ std::string eqcrypt_sha1(const std::string &msg) unsigned char sha_digest[20]; char tmp[4]; - SHA1((const unsigned char*)msg.c_str(), msg.length(), sha_digest); - - for (int i = 0; i < 20; ++i) { - sprintf(&tmp[0], "%02x", sha_digest[i]); - ret.push_back(tmp[0]); - ret.push_back(tmp[1]); + if (EVP_Digest(msg.data(), msg.length(), sha_digest, nullptr, EVP_sha1(), nullptr) == 1) { + for (int i = 0; i < 20; ++i) { + sprintf(&tmp[0], "%02x", sha_digest[i]); + ret.push_back(tmp[0]); + ret.push_back(tmp[1]); + } } #endif @@ -237,12 +306,12 @@ std::string eqcrypt_sha512(const std::string &msg) unsigned char sha_digest[64]; char tmp[4]; - SHA512((const unsigned char*)msg.c_str(), msg.length(), sha_digest); - - for (int i = 0; i < 64; ++i) { - sprintf(&tmp[0], "%02x", sha_digest[i]); - ret.push_back(tmp[0]); - ret.push_back(tmp[1]); + if (EVP_Digest(msg.data(), msg.length(), sha_digest, nullptr, EVP_sha512(), nullptr) == 1) { + for (int i = 0; i < 64; ++i) { + sprintf(&tmp[0], "%02x", sha_digest[i]); + ret.push_back(tmp[0]); + ret.push_back(tmp[1]); + } } #endif diff --git a/loginserver/encryption.h b/loginserver/encryption.h index 4f188789d0..d1f683d061 100644 --- a/loginserver/encryption.h +++ b/loginserver/encryption.h @@ -48,10 +48,20 @@ namespace CryptoHash { } std::string GetEncryptionByModeId(uint32 mode); + +// DES-CBC with an all-zero key and IV (EQ login protocol obfuscation, not security). +// On encrypt, a trailing partial block is zero-padded to the next 8-byte boundary, so +// buffer_out must be at least ((buffer_in_sz + 7) / 8) * 8 bytes. On decrypt, buffer_in_sz +// must already be a multiple of 8 or the call returns nullptr. const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buffer_out, bool enc); std::string eqcrypt_hash(const std::string &username, const std::string &password, int mode); bool eqcrypt_verify_hash(const std::string &username, const std::string &password, const std::string &pwhash, int mode); +// OpenSSL 3.0 moved DES behind the "legacy" provider; these load/unload it +// for the lifetime of the process. No-op when built against mbedtls. +bool eqcrypt_init(); +void eqcrypt_shutdown(); + struct EncryptionResult { std::string password; int mode = 0; diff --git a/loginserver/main.cpp b/loginserver/main.cpp index faa22e9553..9b97662233 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -26,6 +26,7 @@ #include "common/platform.h" #include "common/timer.h" #include "common/types.h" +#include "loginserver/encryption.h" #include "loginserver/login_server.h" #include "loginserver/loginserver_command_handler.h" #include "loginserver/loginserver_webserver.h" @@ -160,6 +161,11 @@ int main(int argc, char **argv) RegisterExecutablePlatform(ExePlatformLogin); set_exception_handler(); + if (!eqcrypt_init()) { + LogError("Failed to initialize crypto providers"); + return 1; + } + LogInfo("Logging System Init"); if (argc == 1) { @@ -280,5 +286,7 @@ int main(int argc, char **argv) LogInfo("Server Manager Shutdown"); delete server.server_manager; + eqcrypt_shutdown(); + return 0; } From a8db0574401b18187396621e6751987a6ccb4e75 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 27 Apr 2026 22:19:15 -0700 Subject: [PATCH 107/194] Add vcpkg cache, hopefully works. --- .github/workflows/build.yaml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index adcdf726a3..d68ba4a6de 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -25,6 +25,20 @@ jobs: sudo apt-get update sudo apt-get install -y build-essential ninja-build ccache uuid-dev + - name: Restore vcpkg Cache + uses: actions/cache@v5 + with: + path: | + submodules/vcpkg/buildtrees + submodules/vcpkg/downloads + submodules/vcpkg/installed + submodules/vcpkg/packages + submodules/vcpkg/vcpkg.exe + submodules/vcpkg/vcpkg + key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json', 'submodules/vcpkg/.git/HEAD') }} + restore-keys: | + ${{ runner.os }}-vcpkg- + - name: Configure run: | cmake -S . -B build -G Ninja \ @@ -61,6 +75,20 @@ jobs: with: arch: x64 + - name: Restore vcpkg Cache + uses: actions/cache@v5 + with: + path: | + submodules/vcpkg/buildtrees + submodules/vcpkg/downloads + submodules/vcpkg/installed + submodules/vcpkg/packages + submodules/vcpkg/vcpkg.exe + submodules/vcpkg/vcpkg + key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json', 'submodules/vcpkg/.git/HEAD') }} + restore-keys: | + ${{ runner.os }}-vcpkg- + - name: Configure shell: pwsh run: | From 84a90cef2310f5cc45505db4d48b756d7cac7049 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 27 Apr 2026 22:22:54 -0700 Subject: [PATCH 108/194] Linux build doesn't like the way we hash this --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index d68ba4a6de..d380349e57 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -35,7 +35,7 @@ jobs: submodules/vcpkg/packages submodules/vcpkg/vcpkg.exe submodules/vcpkg/vcpkg - key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json', 'submodules/vcpkg/.git/HEAD') }} + key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }} restore-keys: | ${{ runner.os }}-vcpkg- @@ -85,7 +85,7 @@ jobs: submodules/vcpkg/packages submodules/vcpkg/vcpkg.exe submodules/vcpkg/vcpkg - key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json', 'submodules/vcpkg/.git/HEAD') }} + key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }} restore-keys: | ${{ runner.os }}-vcpkg- From 9647a5b82c815c15c14eb577d104022d6609e317 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 27 Apr 2026 23:20:29 -0700 Subject: [PATCH 109/194] Add develop branch --- .github/workflows/build.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index d380349e57..68e0bcb12d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -3,6 +3,7 @@ on: push: branches: - master + - develop pull_request: jobs: From f72bbab0e90dbe42e0ba3f4f94e9cad81c867d1d Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 28 Apr 2026 00:04:40 -0700 Subject: [PATCH 110/194] Change paths to try to get this working --- .github/workflows/build.yaml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 68e0bcb12d..c01b67a738 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -30,14 +30,11 @@ jobs: uses: actions/cache@v5 with: path: | - submodules/vcpkg/buildtrees + vcpkg_installed submodules/vcpkg/downloads - submodules/vcpkg/installed - submodules/vcpkg/packages - submodules/vcpkg/vcpkg.exe - submodules/vcpkg/vcpkg key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }} restore-keys: | + ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }}- ${{ runner.os }}-vcpkg- - name: Configure @@ -80,14 +77,11 @@ jobs: uses: actions/cache@v5 with: path: | - submodules/vcpkg/buildtrees + vcpkg_installed submodules/vcpkg/downloads - submodules/vcpkg/installed - submodules/vcpkg/packages - submodules/vcpkg/vcpkg.exe - submodules/vcpkg/vcpkg key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }} restore-keys: | + ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }}- ${{ runner.os }}-vcpkg- - name: Configure From 4abd9c1b40b673b33d68c42ad1e58ea12867cd69 Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 28 Apr 2026 18:01:20 -0700 Subject: [PATCH 111/194] Some build changes, may or may not fix cache --- .github/workflows/build.yaml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c01b67a738..72e1a8bcf8 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -5,11 +5,13 @@ on: - master - develop pull_request: - jobs: linux: name: Linux runs-on: ubuntu-latest + env: + VCPKG_DOWNLOADS: ${{ github.workspace }}/submodules/vcpkg/downloads + VCPKG_BINARY_SOURCES: 'clear;files,${{ github.workspace }}/vcpkg_archives,readwrite' steps: - name: Checkout source uses: actions/checkout@v5 @@ -30,11 +32,10 @@ jobs: uses: actions/cache@v5 with: path: | - vcpkg_installed - submodules/vcpkg/downloads + ${{ env.VCPKG_DOWNLOADS }} + ${{ github.workspace }}/vcpkg_archives key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }} restore-keys: | - ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }}- ${{ runner.os }}-vcpkg- - name: Configure @@ -59,6 +60,9 @@ jobs: windows: name: Windows runs-on: windows-latest + env: + VCPKG_DOWNLOADS: ${{ github.workspace }}\submodules\vcpkg\downloads + VCPKG_BINARY_SOURCES: 'clear;files,${{ github.workspace }}\vcpkg_archives,readwrite' steps: - name: Checkout source uses: actions/checkout@v5 @@ -77,11 +81,10 @@ jobs: uses: actions/cache@v5 with: path: | - vcpkg_installed - submodules/vcpkg/downloads + ${{ env.VCPKG_DOWNLOADS }} + ${{ github.workspace }}/vcpkg_archives key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }} restore-keys: | - ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }}- ${{ runner.os }}-vcpkg- - name: Configure From cabe06ea92853634dd55d6dcc2fffde256c963c3 Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 28 Apr 2026 19:42:26 -0700 Subject: [PATCH 112/194] Revert linux part for now --- .github/workflows/build.yaml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 72e1a8bcf8..0bf0acb951 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -9,9 +9,6 @@ jobs: linux: name: Linux runs-on: ubuntu-latest - env: - VCPKG_DOWNLOADS: ${{ github.workspace }}/submodules/vcpkg/downloads - VCPKG_BINARY_SOURCES: 'clear;files,${{ github.workspace }}/vcpkg_archives,readwrite' steps: - name: Checkout source uses: actions/checkout@v5 @@ -32,10 +29,11 @@ jobs: uses: actions/cache@v5 with: path: | - ${{ env.VCPKG_DOWNLOADS }} - ${{ github.workspace }}/vcpkg_archives + vcpkg_installed + submodules/vcpkg/downloads key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }} restore-keys: | + ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }}- ${{ runner.os }}-vcpkg- - name: Configure From 42d600446731eebf741bbdce4c73b492b297061c Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 28 Apr 2026 20:00:01 -0700 Subject: [PATCH 113/194] Remove step i think isn't required for windows, change linux path --- .github/workflows/build.yaml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 0bf0acb951..890becf754 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -29,7 +29,7 @@ jobs: uses: actions/cache@v5 with: path: | - vcpkg_installed + build/vcpkg_installed submodules/vcpkg/downloads key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }} restore-keys: | @@ -70,11 +70,6 @@ jobs: - name: Enable long paths run: git config --global core.longpaths true - - name: Setup MSVC environment - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: x64 - - name: Restore vcpkg Cache uses: actions/cache@v5 with: From c6ddf300a4e2badf5ef284b630b25a3bb6a246c0 Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 28 Apr 2026 20:15:06 -0700 Subject: [PATCH 114/194] Add back msvc step with a maintained fork --- .github/workflows/build.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 890becf754..7c18822926 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -69,6 +69,11 @@ jobs: - name: Enable long paths run: git config --global core.longpaths true + + - name: Setup MSVC environment + uses: TheMrMilchmann/setup-msvc-dev@v4 + with: + arch: x64 - name: Restore vcpkg Cache uses: actions/cache@v5 From 85c3255568434deb1b1bb185aadfb7aa6f0581dc Mon Sep 17 00:00:00 2001 From: nytmyr <53322305+nytmyr@users.noreply.github.com> Date: Wed, 29 Apr 2026 01:59:19 -0500 Subject: [PATCH 115/194] [Bots] Command add fix for spelltypeids/spelltypenames (#5074) --- zone/bot_command.cpp | 6 +++--- zone/bot_command.h | 2 +- zone/bot_commands/bot_spelltypes.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 594d28b477..966d951b79 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -775,7 +775,7 @@ void helper_send_usage_required_bots(Client *bot_owner, uint16 spell_type) bot_owner->Message(Chat::Green, "%s", description.c_str()); } -void SendSpellTypeWindow(Client* c, const Seperator* sep) { +void SendSpellTypeWindow(Client* c, const Seperator* sep, bool short_names) { std::string arg0 = sep->arg[0]; std::string arg1 = sep->arg[1]; @@ -828,7 +828,7 @@ void SendSpellTypeWindow(Client* c, const Seperator* sep) { std::string popup_text = DialogueWindow::TableRow( DialogueWindow::TableCell(DialogueWindow::ColorMessage(goldenrod, spell_type_field)) + - DialogueWindow::TableCell((!arg0.compare("^spelltypeids") ? DialogueWindow::ColorMessage(goldenrod, id_field) : DialogueWindow::ColorMessage(goldenrod, shortname_field))) + DialogueWindow::TableCell((!short_names ? DialogueWindow::ColorMessage(goldenrod, id_field) : DialogueWindow::ColorMessage(goldenrod, shortname_field))) ); popup_text += DialogueWindow::TableRow( @@ -845,7 +845,7 @@ void SendSpellTypeWindow(Client* c, const Seperator* sep) { popup_text += DialogueWindow::TableRow( DialogueWindow::TableCell(DialogueWindow::ColorMessage(forest_green, Bot::GetSpellTypeNameByID(i))) + - DialogueWindow::TableCell((!arg0.compare("^spelltypeids") ? DialogueWindow::ColorMessage(slate_blue, std::to_string(i)) : DialogueWindow::ColorMessage(slate_blue, Bot::GetSpellTypeShortNameByID(i)))) + DialogueWindow::TableCell((!short_names ? DialogueWindow::ColorMessage(slate_blue, std::to_string(i)) : DialogueWindow::ColorMessage(slate_blue, Bot::GetSpellTypeShortNameByID(i)))) ); } diff --git a/zone/bot_command.h b/zone/bot_command.h index 6f3de0544b..870697b4d8 100644 --- a/zone/bot_command.h +++ b/zone/bot_command.h @@ -1182,4 +1182,4 @@ bool helper_is_help_or_usage(const char* arg); bool helper_no_available_bots(Client *bot_owner, Bot *my_bot = nullptr); void helper_send_available_subcommands(Client *bot_owner, const char* command_simile, std::vector subcommand_list); void helper_send_usage_required_bots(Client *bot_owner, uint16 spell_type); -void SendSpellTypeWindow(Client* c, const Seperator* sep); +void SendSpellTypeWindow(Client* c, const Seperator* sep, bool short_names = false); diff --git a/zone/bot_commands/bot_spelltypes.cpp b/zone/bot_commands/bot_spelltypes.cpp index f9b39fc7b0..7e7f0fa39b 100644 --- a/zone/bot_commands/bot_spelltypes.cpp +++ b/zone/bot_commands/bot_spelltypes.cpp @@ -24,5 +24,5 @@ void bot_command_spelltype_ids(Client* c, const Seperator* sep) void bot_command_spelltype_names(Client* c, const Seperator* sep) { - SendSpellTypeWindow(c, sep); + SendSpellTypeWindow(c, sep, true); } From d7e010a3ec4f64a946f846cd51235e1b3d9fd2d3 Mon Sep 17 00:00:00 2001 From: Dan <3968021+sh0ber@users.noreply.github.com> Date: Thu, 7 May 2026 23:24:15 -0400 Subject: [PATCH 116/194] strings: refactor Money and add MoneyShort (#5075) --- common/strings.cpp | 157 ++++++++++++++------------------------------- common/strings.h | 3 +- 2 files changed, 51 insertions(+), 109 deletions(-) diff --git a/common/strings.cpp b/common/strings.cpp index 7419de9bce..5f9f17cd52 100644 --- a/common/strings.cpp +++ b/common/strings.cpp @@ -380,118 +380,59 @@ std::string Strings::NumberToWords(unsigned long long int n) return res; } -std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 copper) -{ - std::string money_string = "Unknown"; - if (copper && silver && gold && platinum) { // CSGP - money_string = fmt::format( - "{} platinum, {} gold, {} silver, and {} copper", - Strings::Commify(std::to_string(platinum)), - Strings::Commify(std::to_string(gold)), - Strings::Commify(std::to_string(silver)), - Strings::Commify(std::to_string(copper)) - ); - } - else if (copper && silver && !gold && platinum) { // CSP - money_string = fmt::format( - "{} platinum, {} silver, and {} copper", - Strings::Commify(std::to_string(platinum)), - Strings::Commify(std::to_string(silver)), - Strings::Commify(std::to_string(copper)) - ); - } - else if (copper && silver && gold && !platinum) { // CSG - money_string = fmt::format( - "{} gold, {} silver, and {} copper", - Strings::Commify(std::to_string(gold)), - Strings::Commify(std::to_string(silver)), - Strings::Commify(std::to_string(copper)) - ); - } - else if (copper && !silver && !gold && platinum) { // CP - money_string = fmt::format( - "{} platinum and {} copper", - Strings::Commify(std::to_string(platinum)), - Strings::Commify(std::to_string(copper)) - ); - } - else if (copper && silver && !gold && !platinum) { // CS - money_string = fmt::format( - "{} silver and {} copper", - Strings::Commify(std::to_string(silver)), - Strings::Commify(std::to_string(copper)) - ); - } - else if (!copper && silver && gold && platinum) { // SGP - money_string = fmt::format( - "{} platinum, {} gold, and {} silver", - Strings::Commify(std::to_string(platinum)), - Strings::Commify(std::to_string(gold)), - Strings::Commify(std::to_string(silver)) - ); - } - else if (!copper && silver && !gold && platinum) { // SP - money_string = fmt::format( - "{} platinum and {} silver", - Strings::Commify(std::to_string(platinum)), - Strings::Commify(std::to_string(silver)) - ); - } - else if (!copper && silver && gold && !platinum) { // SG - money_string = fmt::format( - "{} gold and {} silver", - Strings::Commify(std::to_string(gold)), - Strings::Commify(std::to_string(silver)) - ); - } - else if (copper && !silver && gold && platinum) { // CGP - money_string = fmt::format( - "{} platinum, {} gold, and {} copper", - Strings::Commify(std::to_string(platinum)), - Strings::Commify(std::to_string(gold)), - Strings::Commify(std::to_string(copper)) - ); - } - else if (copper && !silver && gold && !platinum) { // CG - money_string = fmt::format( - "{} gold and {} copper", - Strings::Commify(std::to_string(gold)), - Strings::Commify(std::to_string(copper)) - ); - } - else if (!copper && !silver && gold && platinum) { // GP - money_string = fmt::format( - "{} platinum and {} gold", - Strings::Commify(std::to_string(platinum)), - Strings::Commify(std::to_string(gold)) - ); - } - else if (!copper && !silver && !gold && platinum) { // P - money_string = fmt::format( - "{} platinum", - Strings::Commify(std::to_string(platinum)) - ); - } - else if (!copper && !silver && gold && !platinum) { // G - money_string = fmt::format( - "{} gold", - Strings::Commify(std::to_string(gold)) - ); +std::string Strings::Money(uint64 platinum, uint64 gold, uint64 silver, uint64 copper, bool commify) { + uint64 values[] = { platinum, gold, silver, copper }; + const char* names[] = { " platinum", " gold", " silver", " copper" }; + + std::vector parts; + for (int i = 0; i < 4; ++i) { + if (values[i] > 0) { + std::string s = std::to_string(values[i]); + parts.push_back((commify ? Strings::Commify(s) : s) + names[i]); + } } - else if (!copper && silver && !gold && !platinum) { // S - money_string = fmt::format( - "{} silver", - Strings::Commify(std::to_string(silver)) - ); + + if (parts.empty()) return "0 copper"; + if (parts.size() == 1) return parts[0]; + + std::string result; + for (size_t i = 0; i < parts.size(); ++i) { + result += parts[i]; + if (i < parts.size() - 2) { + result += ", "; + } + else if (i == parts.size() - 2) { + // Oxford comma logic: ", and " for 3+ items, " and " for 2 + result += (parts.size() > 2) ? ", and " : " and "; + } } - else if (copper && !silver && !gold && !platinum) { // C - money_string = fmt::format( - "{} copper", - Strings::Commify(std::to_string(copper)) - ); + + return result; +} + +std::string Strings::MoneyShort(uint64 copper, bool commify) { + // Matches merchant format + uint64 values[] = { + copper / 1000, + (copper / 100) % 10, + (copper / 10) % 10, + copper % 10 + }; + const char* names[] = { " platinum", " gold", " silver", " copper" }; + + std::string result; + for (int i = 0; i < 4; ++i) { + if (values[i] > 0) { + if (!result.empty()) result += " "; + + std::string s = std::to_string(values[i]); + result += (commify ? Strings::Commify(s) : s) + names[i]; + } } - return money_string; + + return result.empty() ? "0 copper" : result; } + std::string Strings::SecondsToTime(int duration, bool is_milliseconds) { if (duration <= 0) { diff --git a/common/strings.h b/common/strings.h index 5a5b93debb..85ae4415ba 100644 --- a/common/strings.h +++ b/common/strings.h @@ -62,7 +62,8 @@ class Strings { static std::string Join(const std::vector &ar, const std::string &delim); static std::string Join(const std::vector &ar, const std::string &delim); static std::string MillisecondsToTime(int duration); - static std::string Money(uint64 platinum, uint64 gold = 0, uint64 silver = 0, uint64 copper = 0); + static std::string Money(uint64 platinum, uint64 gold = 0, uint64 silver = 0, uint64 copper = 0, bool commify = true); + static std::string MoneyShort(uint64 copper = 0, bool commify = true); // Matches merchant format when commify is false static std::string NumberToWords(unsigned long long int n); static std::string Repeat(std::string s, int n); static std::string Replace(std::string subject, const std::string &search, const std::string &replace); From ef6dfe0469c19578ee0817ea40917be825a0791e Mon Sep 17 00:00:00 2001 From: Knightly <55611098+Knightly1@users.noreply.github.com> Date: Thu, 7 May 2026 17:25:01 -1000 Subject: [PATCH 117/194] Load openssl libs from executable directory and update logging (#5078) --- loginserver/CMakeLists.txt | 10 ++++++++++ loginserver/encryption.cpp | 12 ++++++++++++ loginserver/main.cpp | 7 +------ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/loginserver/CMakeLists.txt b/loginserver/CMakeLists.txt index 71466df1bd..67d0658c23 100644 --- a/loginserver/CMakeLists.txt +++ b/loginserver/CMakeLists.txt @@ -37,3 +37,13 @@ target_include_directories(loginserver PRIVATE ..) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set_property(TARGET loginserver PROPERTY FOLDER executables/servers) + +# vcpkg doesn't copy legacy.dll automatically because it is loaded at runtime, not via the import table. +if(WIN32 AND DEFINED VCPKG_INSTALLED_DIR AND DEFINED VCPKG_TARGET_TRIPLET) + add_custom_command(TARGET loginserver POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "$,${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/debug/bin/legacy.dll,${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/legacy.dll>" + "$/legacy.dll" + VERBATIM + ) +endif() diff --git a/loginserver/encryption.cpp b/loginserver/encryption.cpp index 3fa140768d..db81423949 100644 --- a/loginserver/encryption.cpp +++ b/loginserver/encryption.cpp @@ -182,6 +182,18 @@ static OSSL_PROVIDER *s_default_provider = nullptr; bool eqcrypt_init() { #ifdef EQEMU_USE_OPENSSL +#ifdef _WIN32 + // Set OpenSSL default provider search path to the executable directory. + char* exe_path = nullptr; + if (_get_pgmptr(&exe_path) == 0 && exe_path != nullptr && *exe_path != '\0') { + std::string exe_dir{exe_path}; + if (auto sep = exe_dir.find_last_of("\\/"); sep != std::string::npos) { + exe_dir.resize(sep); + OSSL_PROVIDER_set_default_search_path(nullptr, exe_dir.c_str()); + } + } +#endif + if (!s_default_provider) { s_default_provider = OSSL_PROVIDER_load(nullptr, "default"); } diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 9b97662233..106fdc7df3 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -159,6 +159,7 @@ void start_web_server() int main(int argc, char **argv) { RegisterExecutablePlatform(ExePlatformLogin); + EQEmuLogSys::Instance()->LoadLogSettingsDefaults(); set_exception_handler(); if (!eqcrypt_init()) { @@ -166,12 +167,6 @@ int main(int argc, char **argv) return 1; } - LogInfo("Logging System Init"); - - if (argc == 1) { - EQEmuLogSys::Instance()->LoadLogSettingsDefaults(); - } - PathManager::Instance()->Init(); // command handler From ca704c7f881fb6f81a7304bdb84b64227122ad46 Mon Sep 17 00:00:00 2001 From: Dan <3968021+sh0ber@users.noreply.github.com> Date: Wed, 13 May 2026 03:18:36 -0400 Subject: [PATCH 118/194] feat(Scripting): Created two perl/lua scripting hooks for merchants (#5083) --- zone/client_packet.cpp | 55 +++++++++++++++++++++++++++----------- zone/embparser.cpp | 29 ++++++++++++++++++++ zone/event_codes.h | 2 ++ zone/lua_general.cpp | 2 ++ zone/lua_iteminst.cpp | 6 +++++ zone/lua_iteminst.h | 1 + zone/lua_parser.cpp | 4 +++ zone/lua_parser_events.cpp | 47 ++++++++++++++++++++++++++++++++ zone/lua_parser_events.h | 18 +++++++++++++ 9 files changed, 148 insertions(+), 16 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 13e55df4de..f4266afb43 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -14378,9 +14378,8 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) sizeof(Merchant_Purchase_Struct), app->size); return; } - RDTSC_Timer t1(true); + Merchant_Purchase_Struct* mp = (Merchant_Purchase_Struct*)app->pBuffer; - Mob* vendor = entity_list.GetMob(mp->npcid); if (vendor == 0 || !vendor->IsNPC() || vendor->GetClass() != Class::Merchant) @@ -14390,35 +14389,51 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) if (DistanceSquared(m_Position, vendor->GetPosition()) > USE_NPC_RANGE2) return; - uint32 price = 0; uint32 itemid = GetItemIDAt(mp->itemslot); if (itemid == 0) return; + const EQ::ItemData* item = database.GetItem(itemid); EQ::ItemInstance* inst = GetInv().GetItem(mp->itemslot); if (!item || !inst) { - Message(Chat::Red, "You seemed to have misplaced that item.."); + Message(Chat::Red, "You seem to have misplaced that item.."); return; } - if (mp->quantity > 1) - { - if ((inst->GetCharges() < 0) || (mp->quantity > (uint32)inst->GetCharges())) - return; - } if (!item->NoDrop) { - //Message(Chat::Red,"%s tells you, 'LOL NOPE'", vendor->GetName()); return; } - uint32 cost_quantity = mp->quantity; - if (inst->IsCharged()) - uint32 cost_quantity = 1; + if (mp->quantity > 1) { + if ((inst->GetCharges() < 0) || (mp->quantity > (uint32)inst->GetCharges())) + return; + } - uint32 i; + // Check for veto from script + if (parse->PlayerHasQuestSub(EVENT_MERCHANT_PRESELL)) { + std::string export_string = fmt::format("{} {} {}", mp->itemslot, itemid, inst->GetItemType()); + std::vector extra_pointers = { vendor, inst }; + + int result = parse->EventPlayer(EVENT_MERCHANT_PRESELL, this, export_string, 0, &extra_pointers); + // CANCEL: If a script returns -1 for this event, the sale wil be cancelled. Sends a dummy packet sent to satisfy the client + if (result == -1) { + auto outapp = new EQApplicationPacket(OP_ShopPlayerSell, sizeof(Merchant_Purchase_Struct)); + Merchant_Purchase_Struct* mco = (Merchant_Purchase_Struct*)outapp->pBuffer; + mco->npcid = vendor->GetID(); + mco->itemslot = -1; // Critical or the client will remove the item visually + mco->quantity = 0; + mco->price = 0; + QueuePacket(outapp); + safe_delete(outapp); + return; + } + } + + uint32 cost_quantity = inst->IsCharged() ? 1 : mp->quantity; + uint32 price = 0; if (RuleB(Merchant, UsePriceMod)) { - for (i = 1; i <= cost_quantity; i++) { + for (uint32 i = 1; i <= cost_quantity; i++) { price = (uint32)(item->Price * i) * Client::CalcPriceMod(vendor, true); // Don't use SellCostMod if using UseClassicPriceMod @@ -14436,7 +14451,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) } } else { - for (i = 1; i <= cost_quantity; i++) { + for (uint32 i = 1; i <= cost_quantity; i++) { price = (uint32)((item->Price * i)*(RuleR(Merchant, BuyCostMod)) + 0.5); // need to round up, because client does it automatically when displaying price if (price > 4000000000) { cost_quantity = i; @@ -14448,6 +14463,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) AddMoneyToPP(price); + // Update merchant stock and refresh client if (inst->IsStackable() || inst->IsCharged()) { unsigned int i_quan = inst->GetCharges(); @@ -14561,6 +14577,8 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) QueuePacket(outapp); safe_delete(outapp); SendMoneyUpdate(); + + RDTSC_Timer t1(true); t1.start(); Save(1); t1.stop(); @@ -14679,6 +14697,11 @@ void Client::Handle_OP_ShopRequest(const EQApplicationPacket *app) if ((tabs_to_display & Parcel) == Parcel) { SendBulkParcels(); } + + if (parse->PlayerHasQuestSub(EVENT_MERCHANT_OPEN)) { + std::vector extra_pointers = { tmp }; + parse->EventPlayer(EVENT_MERCHANT_OPEN, this, "", 0, &extra_pointers); + } } return; diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 52863b6988..c701275b3a 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -163,8 +163,10 @@ const char* QuestEventSubroutines[_LargestEventID] = { "EVENT_LANGUAGE_SKILL_UP", "EVENT_ALT_CURRENCY_MERCHANT_BUY", "EVENT_ALT_CURRENCY_MERCHANT_SELL", + "EVENT_MERCHANT_OPEN", "EVENT_MERCHANT_BUY", "EVENT_MERCHANT_SELL", + "EVENT_MERCHANT_PRESELL", "EVENT_INSPECT", "EVENT_TASK_BEFORE_UPDATE", "EVENT_AA_BUY", @@ -2289,6 +2291,33 @@ void PerlembParser::ExportEventVariables( break; } + case EVENT_MERCHANT_OPEN: { + if (!extra_pointers || extra_pointers->size() < 1) break; + + auto mob_ptr = std::any_cast(extra_pointers->at(0)); + if (!mob_ptr) break; + + ExportVar(package_name.c_str(), "other", "Mob", mob_ptr); + break; + } + + case EVENT_MERCHANT_PRESELL: { + Seperator sep(data); + ExportVar(package_name.c_str(), "slot_id", sep.arg[0]); + ExportVar(package_name.c_str(), "item_id", sep.arg[1]); + ExportVar(package_name.c_str(), "item_type", sep.arg[2]); + + if (!extra_pointers || extra_pointers->size() < 2) break; + + auto mob_ptr = std::any_cast(extra_pointers->at(0)); + auto inst_ptr = std::any_cast(extra_pointers->at(1)); + if (!mob_ptr || !inst_ptr) break; + + ExportVar(package_name.c_str(), "other", "Mob", mob_ptr); + ExportVar(package_name.c_str(), "item", "ItemInstance", inst_ptr); + break; + } + case EVENT_AA_BUY: { Seperator sep(data); ExportVar(package_name.c_str(), "aa_cost", sep.arg[0]); diff --git a/zone/event_codes.h b/zone/event_codes.h index c5210633f6..fb6c349b1b 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -116,8 +116,10 @@ enum QuestEventID { EVENT_LANGUAGE_SKILL_UP, EVENT_ALT_CURRENCY_MERCHANT_BUY, EVENT_ALT_CURRENCY_MERCHANT_SELL, + EVENT_MERCHANT_OPEN, EVENT_MERCHANT_BUY, EVENT_MERCHANT_SELL, + EVENT_MERCHANT_PRESELL, EVENT_INSPECT, EVENT_TASK_BEFORE_UPDATE, EVENT_AA_BUY, diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 793b730c54..dd0402343e 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -6968,8 +6968,10 @@ luabind::scope lua_register_events() { luabind::value("language_skill_up", static_cast(EVENT_LANGUAGE_SKILL_UP)), luabind::value("alt_currency_merchant_buy", static_cast(EVENT_ALT_CURRENCY_MERCHANT_BUY)), luabind::value("alt_currency_merchant_sell", static_cast(EVENT_ALT_CURRENCY_MERCHANT_SELL)), + luabind::value("merchant_open", static_cast(EVENT_MERCHANT_OPEN)), luabind::value("merchant_buy", static_cast(EVENT_MERCHANT_BUY)), luabind::value("merchant_sell", static_cast(EVENT_MERCHANT_SELL)), + luabind::value("merchant_presell", static_cast(EVENT_MERCHANT_PRESELL)), luabind::value("inspect", static_cast(EVENT_INSPECT)), luabind::value("task_before_update", static_cast(EVENT_TASK_BEFORE_UPDATE)), luabind::value("aa_buy", static_cast(EVENT_AA_BUY)), diff --git a/zone/lua_iteminst.cpp b/zone/lua_iteminst.cpp index 6e0f97c650..65c3d6d743 100644 --- a/zone/lua_iteminst.cpp +++ b/zone/lua_iteminst.cpp @@ -158,6 +158,11 @@ uint32 Lua_ItemInst::GetItemScriptID() { return self->GetItemScriptID(); } +uint8 Lua_ItemInst::GetItemType() { + Lua_Safe_Call_Int(); + return self->GetItemType(); +} + int Lua_ItemInst::GetCharges() { Lua_Safe_Call_Int(); return self->GetCharges(); @@ -497,6 +502,7 @@ luabind::scope lua_register_iteminst() { .def("GetItemID", (uint32(Lua_ItemInst::*)(int))&Lua_ItemInst::GetItemID) .def("GetItemLink", (std::string(Lua_ItemInst::*)(void))&Lua_ItemInst::GetItemLink) .def("GetItemScriptID", (uint32(Lua_ItemInst::*)(void))&Lua_ItemInst::GetItemScriptID) + .def("GetItemType", (uint8(Lua_ItemInst::*)(void)) & Lua_ItemInst::GetItemType) .def("GetMaxEvolveLvl", (int(Lua_ItemInst::*)(void))&Lua_ItemInst::GetMaxEvolveLvl) .def("GetName", (std::string(Lua_ItemInst::*)(void))&Lua_ItemInst::GetName) .def("GetSerialNumber", (int(Lua_ItemInst::*)(void))&Lua_ItemInst::GetSerialNumber) diff --git a/zone/lua_iteminst.h b/zone/lua_iteminst.h index 49a7e8b824..c0cdf337d3 100644 --- a/zone/lua_iteminst.h +++ b/zone/lua_iteminst.h @@ -71,6 +71,7 @@ class Lua_ItemInst : public Lua_Ptr bool IsAmmo(); uint32 GetID(); uint32 GetItemScriptID(); + uint8 GetItemType(); int GetCharges(); void SetCharges(int charges); uint32 GetPrice(); diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index d45ea95067..911ff3779b 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -160,8 +160,10 @@ const char *LuaEvents[_LargestEventID] = { "event_language_skill_up", "event_alt_currency_merchant_buy", "event_alt_currency_merchant_sell", + "event_merchant_open", "event_merchant_buy", "event_merchant_sell", + "event_merchant_presell", "event_inspect", "event_task_before_update", "event_aa_buy", @@ -335,8 +337,10 @@ LuaParser::LuaParser() { PlayerArgumentDispatch[EVENT_LANGUAGE_SKILL_UP] = handle_player_language_skill_up; PlayerArgumentDispatch[EVENT_ALT_CURRENCY_MERCHANT_BUY] = handle_player_alt_currency_merchant; PlayerArgumentDispatch[EVENT_ALT_CURRENCY_MERCHANT_SELL] = handle_player_alt_currency_merchant; + PlayerArgumentDispatch[EVENT_MERCHANT_OPEN] = handle_player_merchant_open; PlayerArgumentDispatch[EVENT_MERCHANT_BUY] = handle_player_merchant; PlayerArgumentDispatch[EVENT_MERCHANT_SELL] = handle_player_merchant; + PlayerArgumentDispatch[EVENT_MERCHANT_PRESELL] = handle_player_merchant_presell; PlayerArgumentDispatch[EVENT_INSPECT] = handle_player_inspect; PlayerArgumentDispatch[EVENT_AA_BUY] = handle_player_aa_buy; PlayerArgumentDispatch[EVENT_AA_GAIN] = handle_player_aa_gain; diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index a768e18c1e..12ae30b6bc 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -2340,6 +2340,53 @@ void handle_player_merchant( lua_setfield(L, -2, "item_cost"); } +void handle_player_merchant_open( + QuestInterface* parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector* extra_pointers +) { + if (!extra_pointers || extra_pointers->size() < 1) return; + + auto mob_ptr = std::any_cast(extra_pointers->at(0)); + if (!mob_ptr) return; + + Lua_Mob l_mob(mob_ptr); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_player_merchant_presell( + QuestInterface* parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector* extra_pointers +) { + Seperator sep(data.c_str()); + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_setfield(L, -2, "slot_id"); + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_setfield(L, -2, "item_id"); + lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_setfield(L, -2, "item_type"); + + if (!extra_pointers || extra_pointers->size() < 2) return; + + auto mob_ptr = std::any_cast(extra_pointers->at(0)); + auto inst_ptr = std::any_cast(extra_pointers->at(1)); + if (!mob_ptr || !inst_ptr) return; + + Lua_Mob l_mob(mob_ptr); + luabind::adl::object(L, l_mob).push(L); + lua_setfield(L, -2, "other"); + + Lua_ItemInst l_iteminst(inst_ptr); + luabind::adl::object(L, l_iteminst).push(L); + lua_setfield(L, -2, "item"); +} + void handle_player_augment_insert( QuestInterface *parse, lua_State* L, diff --git a/zone/lua_parser_events.h b/zone/lua_parser_events.h index b436691fd9..bb32ad0536 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -671,6 +671,24 @@ void handle_player_merchant( std::vector *extra_pointers ); +void handle_player_merchant_open( + QuestInterface* parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector* extra_pointers +); + +void handle_player_merchant_presell( + QuestInterface* parse, + lua_State* L, + Client* client, + std::string data, + uint32 extra_data, + std::vector* extra_pointers +); + void handle_player_inspect( QuestInterface *parse, lua_State* L, From a183bf55a3ae0944f1bfb9bb5d068f5c155e7179 Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Sat, 23 May 2026 22:51:37 -0700 Subject: [PATCH 119/194] Add standalone AutoLoot feature branch --- client_files/native_autoloot/README.md | 31 + .../ui/EQUI_NativeAutoLootWnd.xml | 443 ++++ .../database_update_manifest_custom.h | 82 +- common/version.h | 2 +- features/README.md | 33 + features/TEMPLATE.md | 72 + features/autoloot/MANIFEST.md | 83 + features/autoloot/README.md | 65 + .../sql/001_source_backed_autoloot.sql | 52 + zone/CMakeLists.txt | 3 + zone/attack.cpp | 3 + zone/autoloot_manager.cpp | 2095 +++++++++++++++++ zone/autoloot_manager.h | 169 ++ zone/command.cpp | 4 + zone/command.h | 4 + zone/corpse.cpp | 286 +++ zone/corpse.h | 21 + zone/gm_commands/autoloot.cpp | 31 + zone/zone.cpp | 2 + 19 files changed, 3448 insertions(+), 33 deletions(-) create mode 100644 client_files/native_autoloot/README.md create mode 100644 client_files/native_autoloot/ui/EQUI_NativeAutoLootWnd.xml create mode 100644 features/README.md create mode 100644 features/TEMPLATE.md create mode 100644 features/autoloot/MANIFEST.md create mode 100644 features/autoloot/README.md create mode 100644 features/autoloot/sql/001_source_backed_autoloot.sql create mode 100644 zone/autoloot_manager.cpp create mode 100644 zone/autoloot_manager.h create mode 100644 zone/gm_commands/autoloot.cpp diff --git a/client_files/native_autoloot/README.md b/client_files/native_autoloot/README.md new file mode 100644 index 0000000000..53d780db99 --- /dev/null +++ b/client_files/native_autoloot/README.md @@ -0,0 +1,31 @@ +# Native AutoLoot Client Files + +This folder contains the AutoLoot-specific native UI XML for the matching server branch. + +The DLL source is not included in this proof branch yet. The current DLL implementation still lives in shared native-client runtime code and needs a `native-client-base` split before the client side is a clean AutoLoot-only pack. + +## Install + +Copy the SIDL XML file to the client's default UI folder: + +```text +client_files/native_autoloot/ui/EQUI_NativeAutoLootWnd.xml +``` + +Destination example: + +```text +EverQuest/uifiles/default/EQUI_NativeAutoLootWnd.xml +``` + +Only load one patched client folder at a time. + +## In Game + +Use this command to reopen the window if it is closed: + +```text +#autoloot native show +``` + +The server remains authoritative. The native client DLL host only creates the native window, parses `AUTOLOOT|...` status lines, and sends normal server commands back to the zone. diff --git a/client_files/native_autoloot/ui/EQUI_NativeAutoLootWnd.xml b/client_files/native_autoloot/ui/EQUI_NativeAutoLootWnd.xml new file mode 100644 index 0000000000..5e287628c4 --- /dev/null +++ b/client_files/native_autoloot/ui/EQUI_NativeAutoLootWnd.xml @@ -0,0 +1,443 @@ + + + + + + + + + + + + AALW_PersonalList + WDT_Inner + true + true + 8 + 38 + 8 + 184 + true + true + true + false + 838 + 624146 + true + true + false + false + 250Item + 42Qty + 196NPC Name + 60Rule + 70Status + + + + + + + + + + + + + + + + + + + + AALW_SharedList + WDT_Inner + true + true + 8 + 234 + 8 + 80 + true + false + true + false + 8234 + 624106 + true + true + false + false + 130Item + 36Qty + 150NPC Name + 54Status + 48Rule + 30ND + 30GD + 30NO + 30AN + 30AG + 30NV + + + + + + + + + + + + + + NativeAutoLootWnd + false + 8080 + 640420 + Advanced Loot + WDT_Def + true + true + true + true + true + false + AALW_PersonalLabel + AALW_RuleSummaryLabel + AALW_LootAllButton + AALW_PersonalList + AALW_SetAllLabel + AALW_LeaveAllButton + AALW_AlwaysButton + AALW_NeverButton + AALW_LootButton + AALW_LeaveButton + AALW_SharedLabel + AALW_MasterLabel + AALW_SharedList + AALW_RefreshButton + AALW_NearbyButton + AALW_EditFiltersButton + AALW_ApplyFiltersCheck + AALW_StatusLabel + + + + + + + + + + + + + + AALR_RuleList + WDT_Inner + true + true + 8 + 74 + 16 + 50 + true + false + true + false + 874 + 496246 + true + true + false + false + 76Rule + 344Item Name + 76Item ID + + + + + + NativeAutoLootRulesWnd + false + 110120 + 520370 + AutoLoot Filters + WDT_Def + true + true + true + true + true + false + AALR_SummaryLabel + AALR_RefreshButton + AALR_KeepButton + AALR_IgnoreButton + AALR_UnsetButton + AALR_RuleList + AALR_StatusLabel + + diff --git a/common/database/database_update_manifest_custom.h b/common/database/database_update_manifest_custom.h index 2bed28301e..934b74e8df 100644 --- a/common/database/database_update_manifest_custom.h +++ b/common/database/database_update_manifest_custom.h @@ -24,45 +24,63 @@ std::vector manifest_entries_custom = { ManifestEntry{ .version = 1, - .description = "2025_05_16_new_database_check_test", - .check = "SHOW TABLES LIKE 'new_table'", + .description = "2026_05_14_source_backed_autoloot", + .check = "SHOW TABLES LIKE 'custom_autoloot_settings'", .condition = "empty", .match = "", .sql = R"( -CREATE TABLE `new_table` ( - `id` int NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`id`) +CREATE TABLE `custom_autoloot_settings` ( + `character_id` INT UNSIGNED NOT NULL, + `enabled` TINYINT(1) NOT NULL DEFAULT 0, + `filter_mode` ENUM('both','include','exclude') NOT NULL DEFAULT 'both', + `debug_enabled` TINYINT(1) NOT NULL DEFAULT 0, + `log_enabled` TINYINT(1) NOT NULL DEFAULT 0, + `updated_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`) +); + +CREATE TABLE `custom_autoloot_filters` ( + `character_id` INT UNSIGNED NOT NULL, + `item_id` INT UNSIGNED NOT NULL, + `filter_mode` ENUM('include','exclude') NOT NULL, + `created_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`, `item_id`, `filter_mode`), + KEY `idx_item_id` (`item_id`) +); + +CREATE TABLE `custom_autoloot_autosell_exclusions` ( + `character_id` INT UNSIGNED NOT NULL, + `item_id` INT UNSIGNED NOT NULL, + `created_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`, `item_id`), + KEY `idx_item_id` (`item_id`) +); + +CREATE TABLE `custom_autoloot_group_settings` ( + `group_id` INT UNSIGNED NOT NULL, + `loot_mode` ENUM('none','solo','master','robin','killer','assigned') NOT NULL DEFAULT 'solo', + `assigned_character_id` INT UNSIGNED NOT NULL DEFAULT 0, + `round_robin_index` INT UNSIGNED NOT NULL DEFAULT 0, + `need_greed_enabled` TINYINT(1) NOT NULL DEFAULT 0, + `updated_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`group_id`) +); + +CREATE TABLE `custom_autoloot_audit` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + `character_id` INT UNSIGNED NOT NULL DEFAULT 0, + `action` VARCHAR(64) NOT NULL DEFAULT '', + `item_id` INT UNSIGNED NOT NULL DEFAULT 0, + `quantity` INT UNSIGNED NOT NULL DEFAULT 0, + `detail` VARCHAR(255) NOT NULL DEFAULT '', + `created_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_character_created` (`character_id`, `created_at`), + KEY `idx_item_id` (`item_id`) ); )", .content_schema_update = false, }, -// Used for testing -// ManifestEntry{ -// .version = 9229, -// .description = "new_database_check_test", -// .check = "SHOW TABLES LIKE 'new_table'", -// .condition = "empty", -// .match = "", -// .sql = R"( -//CREATE TABLE `new_table` ( -// `id` int NOT NULL AUTO_INCREMENT, -// PRIMARY KEY (`id`) -//); -//CREATE TABLE `new_table1` ( -// `id` int NOT NULL AUTO_INCREMENT, -// PRIMARY KEY (`id`) -//); -//CREATE TABLE `new_table2` ( -// `id` int NOT NULL AUTO_INCREMENT, -// PRIMARY KEY (`id`) -//); -//CREATE TABLE `new_table3` ( -// `id` int NOT NULL AUTO_INCREMENT, -// PRIMARY KEY (`id`) -//); -//)", -// } - }; // see struct definitions for what each field does diff --git a/common/version.h b/common/version.h index 02f0640965..560b0425ee 100644 --- a/common/version.h +++ b/common/version.h @@ -40,4 +40,4 @@ #define CURRENT_BINARY_DATABASE_VERSION 9328 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9055 -#define CUSTOM_BINARY_DATABASE_VERSION 0 +#define CUSTOM_BINARY_DATABASE_VERSION 1 diff --git a/features/README.md b/features/README.md new file mode 100644 index 0000000000..cde4b62121 --- /dev/null +++ b/features/README.md @@ -0,0 +1,33 @@ +# Feature Packs + +This folder is the portability layer for custom systems that another EQEmu server operator might want to grab one at a time. + +These are not runtime plugins. Each feature pack documents the source files, database objects, client assets, and hook points needed to lift one system into another source checkout with the smallest practical blast radius. + +## Status Labels + +- `draft`: boundary has been mapped, but the pack is not a clean generated patch yet. +- `portable`: has a tested patch or install sequence that can be applied to a fresh compatible checkout. +- `shared-runtime`: includes code that is still bundled with another feature or shared client runtime. + +## Current Packs + +| Feature | Status | Notes | +| --- | --- | --- | +| `autoloot` | `draft`, `shared-runtime` | Server-side AutoLoot with the native EQ AutoLoot window. Client DLL code is still partly bundled with other native windows. | + +## Packaging Rules + +Each feature pack should: + +1. Name what the feature owns. +2. Name what it explicitly does not require. +3. List every source file that is added. +4. List every existing source file that must be patched. +5. Include feature-owned SQL as standalone files. +6. Call out any shared plumbing that still needs extraction. +7. Keep server authority on the server, especially for loot, item creation, spell mutation, achievement validation, progression, and permissions. + +The goal is not to hide that source integration is needed. The goal is to make the integration honest, bounded, and repeatable. + +Use `TEMPLATE.md` when starting the next pack. diff --git a/features/TEMPLATE.md b/features/TEMPLATE.md new file mode 100644 index 0000000000..8fee7b8d91 --- /dev/null +++ b/features/TEMPLATE.md @@ -0,0 +1,72 @@ +# Feature Pack Template + +Status: `draft` + +Use this shape when separating another custom system into a grab-and-build feature pack. + +## What This Feature Owns + +- Source-owned mechanics. +- Database-owned state. +- Client assets. +- Player/admin commands. +- Server-to-client transport lines. + +## What This Feature Does Not Require + +- Other custom systems that are not true dependencies. +- Old prototype scripts, plugins, or overlays. +- Client-trusted validation for exploit-sensitive behavior. + +## Dependencies + +- Required EQEmu source areas. +- Required database migration support. +- Required client runtime or UI files. +- Optional feature packs. + +## Added Files + +- `path/to/new/file.cpp` + +## Existing Files To Patch + +| File | Purpose | +| --- | --- | +| `path/to/existing/file.cpp` | Describe the narrow hook point. | + +## Database Objects + +- `custom_feature_table` + +Put standalone SQL under `sql/`. + +## Native Client Assets + +- `client_files/...` + +Call out shared runtime code separately from feature-specific window code. + +## Commands + +- `/command` +- `#command` + +## Transport + +- `FEATURE|...` + +The server owns truth. The client displays server state and sends normal commands back. + +## Smoke Test + +1. Start from a clean login. +2. Exercise the primary command path. +3. Exercise persistence. +4. Exercise the failure path that should leave state unchanged. +5. Verify the feature works when unrelated custom systems are absent. + +## Next Split Work + +- List the code that still needs to move out of shared files. +- List any generated patch or installer work still missing. diff --git a/features/autoloot/MANIFEST.md b/features/autoloot/MANIFEST.md new file mode 100644 index 0000000000..b24f570ac7 --- /dev/null +++ b/features/autoloot/MANIFEST.md @@ -0,0 +1,83 @@ +# AutoLoot Manifest + +This manifest lists the files and hook points that make up the source-backed native AutoLoot feature. + +## Added Server Files + +- `zone/autoloot_manager.cpp` +- `zone/autoloot_manager.h` +- `zone/gm_commands/autoloot.cpp` + +## Existing Server Files To Patch + +| File | Purpose | +| --- | --- | +| `zone/CMakeLists.txt` | Add AutoLoot manager and command source files to the zone target. | +| `zone/attack.cpp` | Notify AutoLoot when a corpse is created after a kill. | +| `zone/zone.cpp` | Tick the AutoLoot manager from the zone process loop. | +| `zone/command.cpp` | Register AutoLoot, AutoSell, LootFilter, and NeedGreed commands. | +| `zone/command.h` | Declare AutoLoot command handlers. | +| `zone/corpse.cpp` | Provide source-side corpse item transfer support for AutoLoot. | +| `zone/corpse.h` | Declare AutoLoot corpse result types and transfer API. | +| `common/database/database_update_manifest_custom.h` | Add the custom AutoLoot database migration. | +| `common/version.h` | Bump `CUSTOM_BINARY_DATABASE_VERSION` when adding the migration. | + +## Runtime Hook Points + +| Hook | Expected Behavior | +| --- | --- | +| Corpse creation in `zone/attack.cpp` | Queue nearby AutoLoot processing after an NPC dies. | +| Zone process loop in `zone/zone.cpp` | Drain AutoLoot work without relying on quest timers. | +| `Corpse::AutoLootItem` | Move items using server-side checks and corpse removal semantics. | +| Command registration | Expose player and admin control through normal server commands. | +| Database migration | Create persistent AutoLoot settings, filters, group settings, autosell exclusions, and optional audit rows. | + +## Database Objects + +Standalone SQL lives in: + +- `features/autoloot/sql/001_source_backed_autoloot.sql` + +Owned tables: + +- `custom_autoloot_settings` +- `custom_autoloot_filters` +- `custom_autoloot_autosell_exclusions` +- `custom_autoloot_group_settings` +- `custom_autoloot_audit` + +## Native Client Assets + +| File | Purpose | +| --- | --- | +| `client_files/native_autoloot/ui/EQUI_NativeAutoLootWnd.xml` | Native SIDL window layout for AutoLoot. | +| `client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h` | Not included in this proof branch. The current implementation is still shared runtime code and needs a `native-client-base` split before this is a minimal client pack. | +| Target client `uifiles/default/EQUI.xml` | Must include `EQUI_NativeAutoLootWnd.xml` so the client loads the window. | + +The client source currently needs further separation before this can be called a minimal client pack. This branch proves the server-side AutoLoot feature boundary first. + +## Player Commands + +- `#autoloot native show` +- `#autoloot native status` +- `#lootfilter native list both` +- `/lootfilter keep ` +- `/lootfilter ignore ` +- `/lootfilter unset ` +- `/autosell` +- `/needgreed vote ` + +## Native Transport + +Server-to-client lines use the hidden chat protocol prefix: + +- `AUTOLOOT|...` + +Client-to-server actions are sent as ordinary server commands through the DLL command bridge. The client must not be trusted to decide whether an item can be moved, sold, rolled, or awarded. + +## Known Non-Goals + +- Do not restore Perl, MQ, Lua, or overlay AutoLoot. +- Do not summon copied items to players as a loot shortcut. +- Do not trust the native client window as authoritative state. +- Do not bundle Live Items, Live Spells, or Achievements into the AutoLoot server pack. diff --git a/features/autoloot/README.md b/features/autoloot/README.md new file mode 100644 index 0000000000..18659e6739 --- /dev/null +++ b/features/autoloot/README.md @@ -0,0 +1,65 @@ +# AutoLoot Feature Pack + +Status: `draft`, `shared-runtime` + +This pack describes the source-backed AutoLoot system with the native EverQuest AutoLoot window. It is intended for a server operator who wants AutoLoot without also taking Live Items, Live Spells, or Achievements. + +## What This Feature Owns + +- Character AutoLoot settings. +- Per-character item filters using player-facing `Keep`, `Ignore`, and `Unset` language. +- Group loot settings, shared decision queues, and Need/Greed voting. +- AutoSell preview and confirm flow. +- Nearby corpse processing. +- Server-side item transfer through source-controlled corpse loot paths. +- Native AutoLoot UI transport using `AUTOLOOT|...` chat protocol lines. + +## What This Feature Does Not Require + +- Live Items. +- Live Spells. +- Achievements. +- Old Perl `autoloot.pl` execution. +- MacroQuest, Lua, ImGui, or an overlay AutoLoot window. + +The old script and MQ/Lua approaches should stay out of this pack. The native client window is now the AutoLoot UI surface; the server remains authoritative for all loot decisions and item movement. + +## Dependencies + +- EQEmu source rebuild. +- Custom database update support, or manual execution of the SQL in this pack. +- The native client DLL host used by this branch if the operator wants the in-client AutoLoot window. + +The command surface can still be used without the native window, but the intended package is the native window plus server source. + +## Current Shared-Runtime Caveat + +The server-side AutoLoot boundary is reasonably separable now. + +The client-side boundary is not fully clean yet: the lab branch's `client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h` currently contains AutoLoot code alongside other native custom windows such as Item Forge, Spell Forge, and Achievements. A truly minimal AutoLoot client pack should extract a small native-client base and then move AutoLoot-specific code into its own client source file. + +Until that split is done, this proof branch includes the AutoLoot UI XML but not the shared DLL source. Operators should treat the client DLL portion as shared runtime code and copy only the AutoLoot-specific C++ portions with care. + +## Install Outline + +1. Apply the server source files and hook patches listed in `MANIFEST.md`. +2. Apply the database schema from `sql/001_source_backed_autoloot.sql`, or port it into the server's custom migration system. +3. Rebuild `zone`. +4. Deploy the native client DLL host and `EQUI_NativeAutoLootWnd.xml`. +5. Add `EQUI_NativeAutoLootWnd.xml` to the target client's `EQUI.xml` include list. +6. Log in and run `#autoloot native show`. + +## Smoke Test + +1. Kill an NPC with loot. +2. Open the native AutoLoot window with `#autoloot native show`. +3. Mark an item `Keep`, then kill another NPC that drops the same item. +4. Confirm the server moves the item through the source loot path and leaves blocked loot on the corpse. +5. Mark an item `Ignore` and confirm it is left alone. +6. In a group, verify Need/Greed/Pass decisions use the server queue and do not trust client-only state. + +## Next Split Work + +- Extract AutoLoot-specific client code out of `core_autoloot_native.h`. +- Create a `native-client-base` pack for shared DLL hooks, chat transport plumbing, and safe window lifecycle helpers. +- Generate an AutoLoot-only patch from the manifest once the client-side split is clean. diff --git a/features/autoloot/sql/001_source_backed_autoloot.sql b/features/autoloot/sql/001_source_backed_autoloot.sql new file mode 100644 index 0000000000..f50a21e810 --- /dev/null +++ b/features/autoloot/sql/001_source_backed_autoloot.sql @@ -0,0 +1,52 @@ +-- Source-backed native AutoLoot schema. +-- This standalone SQL mirrors the AutoLoot-owned objects from the custom migration. + +CREATE TABLE IF NOT EXISTS `custom_autoloot_settings` ( + `character_id` INT UNSIGNED NOT NULL, + `enabled` TINYINT(1) NOT NULL DEFAULT 0, + `filter_mode` ENUM('both','include','exclude') NOT NULL DEFAULT 'both', + `debug_enabled` TINYINT(1) NOT NULL DEFAULT 0, + `log_enabled` TINYINT(1) NOT NULL DEFAULT 0, + `updated_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `custom_autoloot_filters` ( + `character_id` INT UNSIGNED NOT NULL, + `item_id` INT UNSIGNED NOT NULL, + `filter_mode` ENUM('include','exclude') NOT NULL, + `created_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`, `item_id`, `filter_mode`), + KEY `idx_item_id` (`item_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `custom_autoloot_autosell_exclusions` ( + `character_id` INT UNSIGNED NOT NULL, + `item_id` INT UNSIGNED NOT NULL, + `created_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`, `item_id`), + KEY `idx_item_id` (`item_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `custom_autoloot_group_settings` ( + `group_id` INT UNSIGNED NOT NULL, + `loot_mode` ENUM('none','solo','master','robin','killer','assigned') NOT NULL DEFAULT 'solo', + `assigned_character_id` INT UNSIGNED NOT NULL DEFAULT 0, + `round_robin_index` INT UNSIGNED NOT NULL DEFAULT 0, + `need_greed_enabled` TINYINT(1) NOT NULL DEFAULT 0, + `updated_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`group_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `custom_autoloot_audit` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + `character_id` INT UNSIGNED NOT NULL DEFAULT 0, + `action` VARCHAR(64) NOT NULL DEFAULT '', + `item_id` INT UNSIGNED NOT NULL DEFAULT 0, + `quantity` INT UNSIGNED NOT NULL DEFAULT 0, + `detail` VARCHAR(255) NOT NULL DEFAULT '', + `created_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_character_created` (`character_id`, `created_at`), + KEY `idx_item_id` (`item_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index afb2ca5311..8689ab385f 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -7,6 +7,7 @@ set(zone_sources aggromanager.cpp api_service.cpp attack.cpp + autoloot_manager.cpp aura.cpp beacon.cpp bonuses.cpp @@ -122,6 +123,7 @@ set(zone_headers aggromanager.h api_service.h aura.h + autoloot_manager.h beacon.h bot.h bot_command.h @@ -375,6 +377,7 @@ set(gm_command_sources gm_commands/appearance.cpp gm_commands/appearanceeffects.cpp gm_commands/attack.cpp + gm_commands/autoloot.cpp gm_commands/augmentitem.cpp gm_commands/ban.cpp gm_commands/bugs.cpp diff --git a/zone/attack.cpp b/zone/attack.cpp index 9ee46b31c2..059499cd3a 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -23,6 +23,7 @@ #include "common/rulesys.h" #include "common/spdat.h" #include "common/strings.h" +#include "zone/autoloot_manager.h" #include "zone/bot.h" #include "zone/fastmath.h" #include "zone/lua_parser.h" @@ -3009,6 +3010,8 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy 0, &args ); + auto_loot_manager.ProcessCorpseDeath(corpse, killer_mob ? killer_mob : owner_or_self); + // Zone controller process EVENT_DEATH_ZONE (Death events) if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DEATH_ZONE)) { const auto& export_string = fmt::format( diff --git a/zone/autoloot_manager.cpp b/zone/autoloot_manager.cpp new file mode 100644 index 0000000000..01771fd282 --- /dev/null +++ b/zone/autoloot_manager.cpp @@ -0,0 +1,2095 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. +*/ +#include "autoloot_manager.h" + +#include "common/data_verification.h" +#include "common/emu_constants.h" +#include "common/inventory_profile.h" +#include "common/item_instance.h" +#include "common/say_link.h" +#include "common/seperator.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/corpse.h" +#include "zone/entity.h" +#include "zone/groups.h" +#include "zone/mob.h" +#include "zone/zone.h" +#include "zone/zonedb.h" + +#include "fmt/format.h" + +#include +#include + +extern EntityList entity_list; +extern Zone *zone; + +AutoLootManager auto_loot_manager; + +namespace { + constexpr float kDefaultNearbyRadius = 75.0f; + constexpr float kMaxNearbyRadius = 250.0f; + constexpr uint32 kNeedGreedSeconds = 45; + constexpr uint32 kAutosellSessionSeconds = 60; + + bool IsValidFilterMode(const std::string &mode) + { + return Strings::EqualFold(mode, "both") || + Strings::EqualFold(mode, "include") || + Strings::EqualFold(mode, "exclude"); + } + + std::string NormalizeFilterMode(const std::string &mode) + { + const auto normalized = Strings::ToLower(mode); + return IsValidFilterMode(normalized) ? normalized : "both"; + } + + std::string NormalizeRuleMode(const std::string &mode) + { + const auto normalized = Strings::ToLower(mode); + if (Strings::EqualFold(normalized, "keep") || Strings::EqualFold(normalized, "always")) { + return "include"; + } + + if (Strings::EqualFold(normalized, "ignore") || Strings::EqualFold(normalized, "never")) { + return "exclude"; + } + + if (Strings::EqualFold(normalized, "unset")) { + return "both"; + } + + return NormalizeFilterMode(normalized); + } + + std::string DisplayRuleMode(const std::string &mode) + { + if (Strings::EqualFold(mode, "include")) { + return "Keep"; + } + + if (Strings::EqualFold(mode, "exclude")) { + return "Ignore"; + } + + return "Unset"; + } + + bool IsValidGroupMode(const std::string &mode) + { + return Strings::EqualFold(mode, "none") || + Strings::EqualFold(mode, "solo") || + Strings::EqualFold(mode, "master") || + Strings::EqualFold(mode, "robin") || + Strings::EqualFold(mode, "killer") || + Strings::EqualFold(mode, "assigned"); + } + + std::string NormalizeGroupMode(const std::string &mode) + { + const auto normalized = Strings::ToLower(mode); + return IsValidGroupMode(normalized) ? normalized : "solo"; + } + + bool IsBagChildSlot(int16 slot_id) + { + return EQ::ValueWithin(slot_id, EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END) || + EQ::ValueWithin(slot_id, EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END) || + EQ::ValueWithin(slot_id, EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END) || + EQ::ValueWithin(slot_id, EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END) || + EQ::ValueWithin(slot_id, EQ::invbag::TRADE_BAGS_BEGIN, EQ::invbag::TRADE_BAGS_END); + } + + uint32 GetCorpseItemQuantity(Corpse *corpse, uint16 loot_slot) + { + auto item_data = corpse ? corpse->GetItem(loot_slot) : nullptr; + if (!item_data) { + return 0; + } + + const auto *item = database.GetItem(item_data->item_id); + if (!item) { + return 0; + } + + return item->Stackable ? std::max(1, item_data->charges) : 1; + } + + bool IsAutosellBag(uint32 item_id) + { + return item_id >= 45500 && item_id <= 45505; + } + + std::string ProtocolValue(std::string value) + { + for (auto &c : value) { + if (c == '|' || c == '\r' || c == '\n' || c == '\t') { + c = ' '; + } + } + + return value; + } + + bool WantsWindowRefresh(const Seperator *sep) + { + if (!sep) { + return false; + } + + for (int argument_index = 1; argument_index <= sep->argnum; ++argument_index) { + if ( + !strcasecmp(sep->arg[argument_index], "ui") || + !strcasecmp(sep->arg[argument_index], "window") || + !strcasecmp(sep->arg[argument_index], "wnd") || + !strcasecmp(sep->arg[argument_index], "panel") + ) { + return true; + } + } + + return false; + } + + void RefreshWindowIfRequested(AutoLootManager *manager, Client *client, const Seperator *sep) + { + if (WantsWindowRefresh(sep)) { + manager->ShowWindow(client); + } + } + + bool IsAutosellProtected(EQ::ItemInstance *inst) + { + if (!inst || !inst->GetItem()) { + return true; + } + + const auto *item = inst->GetItem(); + return item->NoDrop == 0 || + inst->IsAttuned() || + inst->IsAugmented() || + inst->IsEvolving() || + item->Price == 0; + } + + AutoLootManager::VoteChoice ParseVoteChoice(const std::string &choice) + { + if (Strings::EqualFold(choice, "need")) { + return AutoLootManager::VoteChoice::Need; + } + + if (Strings::EqualFold(choice, "greed")) { + return AutoLootManager::VoteChoice::Greed; + } + + return AutoLootManager::VoteChoice::Pass; + } +} + +void AutoLootManager::Process() +{ + const time_t now = std::time(nullptr); + if (now == m_last_process) { + return; + } + + m_last_process = now; + + std::vector expired_votes; + for (const auto &[vote_id, vote] : m_pending_votes) { + if (vote.expires_at <= now) { + expired_votes.push_back(vote_id); + } + } + + for (const auto vote_id : expired_votes) { + ProcessVote(vote_id, true); + } + + for (auto iter = m_autosell_sessions.begin(); iter != m_autosell_sessions.end();) { + if (iter->second.expires_at <= now) { + iter = m_autosell_sessions.erase(iter); + } + else { + ++iter; + } + } + + PruneLootEntries(); +} + +AutoLootManager::CharacterSettings AutoLootManager::GetCharacterSettings(uint32 character_id) +{ + CharacterSettings settings; + + auto results = database.QueryDatabase( + fmt::format( + "SELECT `enabled`, `filter_mode`, `debug_enabled`, `log_enabled` " + "FROM `custom_autoloot_settings` WHERE `character_id` = {} LIMIT 1", + character_id + ) + ); + + if (!results.Success() || !results.RowCount()) { + return settings; + } + + auto row = results.begin(); + settings.enabled = row[0] ? Strings::ToBool(row[0]) : false; + settings.filter_mode = row[1] ? NormalizeFilterMode(row[1]) : "both"; + settings.debug_enabled = row[2] ? Strings::ToBool(row[2]) : false; + settings.log_enabled = row[3] ? Strings::ToBool(row[3]) : false; + return settings; +} + +void AutoLootManager::SaveCharacterSettings(uint32 character_id, const CharacterSettings &settings) +{ + database.QueryDatabase( + fmt::format( + "INSERT INTO `custom_autoloot_settings` " + "(`character_id`, `enabled`, `filter_mode`, `debug_enabled`, `log_enabled`, `updated_at`) " + "VALUES ({}, {}, '{}', {}, {}, UNIX_TIMESTAMP()) " + "ON DUPLICATE KEY UPDATE " + "`enabled` = VALUES(`enabled`), `filter_mode` = VALUES(`filter_mode`), " + "`debug_enabled` = VALUES(`debug_enabled`), `log_enabled` = VALUES(`log_enabled`), " + "`updated_at` = UNIX_TIMESTAMP()", + character_id, + settings.enabled ? 1 : 0, + Strings::Escape(NormalizeFilterMode(settings.filter_mode)), + settings.debug_enabled ? 1 : 0, + settings.log_enabled ? 1 : 0 + ) + ); +} + +AutoLootManager::GroupSettings AutoLootManager::GetGroupSettings(uint32 group_id) +{ + GroupSettings settings; + if (!group_id) { + return settings; + } + + auto results = database.QueryDatabase( + fmt::format( + "SELECT `loot_mode`, `assigned_character_id`, `round_robin_index`, `need_greed_enabled` " + "FROM `custom_autoloot_group_settings` WHERE `group_id` = {} LIMIT 1", + group_id + ) + ); + + if (!results.Success() || !results.RowCount()) { + return settings; + } + + auto row = results.begin(); + settings.loot_mode = row[0] ? NormalizeGroupMode(row[0]) : "solo"; + settings.assigned_character_id = row[1] ? Strings::ToUnsignedInt(row[1]) : 0; + settings.round_robin_index = row[2] ? Strings::ToUnsignedInt(row[2]) : 0; + settings.need_greed_enabled = row[3] ? Strings::ToBool(row[3]) : false; + return settings; +} + +void AutoLootManager::SaveGroupSettings(uint32 group_id, const GroupSettings &settings) +{ + if (!group_id) { + return; + } + + database.QueryDatabase( + fmt::format( + "INSERT INTO `custom_autoloot_group_settings` " + "(`group_id`, `loot_mode`, `assigned_character_id`, `round_robin_index`, `need_greed_enabled`, `updated_at`) " + "VALUES ({}, '{}', {}, {}, {}, UNIX_TIMESTAMP()) " + "ON DUPLICATE KEY UPDATE " + "`loot_mode` = VALUES(`loot_mode`), `assigned_character_id` = VALUES(`assigned_character_id`), " + "`round_robin_index` = VALUES(`round_robin_index`), `need_greed_enabled` = VALUES(`need_greed_enabled`), " + "`updated_at` = UNIX_TIMESTAMP()", + group_id, + Strings::Escape(NormalizeGroupMode(settings.loot_mode)), + settings.assigned_character_id, + settings.round_robin_index, + settings.need_greed_enabled ? 1 : 0 + ) + ); +} + +bool AutoLootManager::HasFilter(uint32 character_id, uint32 item_id, const std::string &filter_mode) +{ + auto results = database.QueryDatabase( + fmt::format( + "SELECT 1 FROM `custom_autoloot_filters` " + "WHERE `character_id` = {} AND `item_id` = {} AND `filter_mode` = '{}' LIMIT 1", + character_id, + item_id, + Strings::Escape(NormalizeFilterMode(filter_mode)) + ) + ); + + return results.Success() && results.RowCount() > 0; +} + +bool AutoLootManager::ShouldLootItem(uint32 character_id, uint32 item_id, const std::string &filter_mode) +{ + return GetFilterAction(character_id, item_id, filter_mode) != "skip"; +} + +std::string AutoLootManager::GetFilterAction(uint32 character_id, uint32 item_id, const std::string &filter_mode) +{ + const auto mode = NormalizeRuleMode(filter_mode); + const bool is_included = HasFilter(character_id, item_id, "include"); + const bool is_excluded = HasFilter(character_id, item_id, "exclude"); + + if (is_excluded) { + return "skip"; + } + + if (mode == "include") { + return is_included ? "loot" : "skip"; + } + + if (mode == "exclude") { + return "loot"; + } + + return is_included ? "loot" : "queue"; +} + +void AutoLootManager::SetFilter(uint32 character_id, uint32 item_id, const std::string &filter_mode) +{ + const auto mode = NormalizeRuleMode(filter_mode); + if (mode == "both") { + return; + } + + RemoveFilter(character_id, item_id, mode == "include" ? "exclude" : "include"); + + database.QueryDatabase( + fmt::format( + "INSERT IGNORE INTO `custom_autoloot_filters` (`character_id`, `item_id`, `filter_mode`, `created_at`) " + "VALUES ({}, {}, '{}', UNIX_TIMESTAMP())", + character_id, + item_id, + Strings::Escape(mode) + ) + ); +} + +void AutoLootManager::RemoveFilter(uint32 character_id, uint32 item_id, const std::string &filter_mode) +{ + const auto mode = NormalizeRuleMode(filter_mode); + if (mode == "both") { + database.QueryDatabase( + fmt::format( + "DELETE FROM `custom_autoloot_filters` WHERE `character_id` = {} AND `item_id` = {}", + character_id, + item_id + ) + ); + return; + } + + database.QueryDatabase( + fmt::format( + "DELETE FROM `custom_autoloot_filters` " + "WHERE `character_id` = {} AND `item_id` = {} AND `filter_mode` = '{}'", + character_id, + item_id, + Strings::Escape(mode) + ) + ); +} + +std::vector> AutoLootManager::GetFilters(uint32 character_id, const std::string &filter_mode) +{ + std::vector> filters; + const auto mode = NormalizeRuleMode(filter_mode); + + auto results = database.QueryDatabase( + fmt::format( + "SELECT `item_id`, `filter_mode` FROM `custom_autoloot_filters` " + "WHERE `character_id` = {}{} ORDER BY `filter_mode`, `item_id`", + character_id, + mode == "both" ? "" : fmt::format(" AND `filter_mode` = '{}'", Strings::Escape(mode)) + ) + ); + + if (!results.Success()) { + return filters; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + filters.emplace_back(row[0] ? Strings::ToUnsignedInt(row[0]) : 0, row[1] ? row[1] : ""); + } + + return filters; +} + +Client *AutoLootManager::ResolveLootClient(Mob *killer) +{ + if (!killer) { + return nullptr; + } + + if (killer->IsClient()) { + return killer->CastToClient(); + } + + auto ultimate_owner = killer->GetUltimateOwner(); + if (ultimate_owner && ultimate_owner->IsClient()) { + return ultimate_owner->CastToClient(); + } + + auto owner = killer->GetOwner(); + if (owner && owner->IsClient()) { + return owner->CastToClient(); + } + + return nullptr; +} + +std::vector AutoLootManager::GetGroupClients(Group *group) +{ + std::vector clients; + if (!group) { + return clients; + } + + for (auto member : group->members) { + if (member && member->IsClient()) { + clients.push_back(member->CastToClient()); + } + } + + return clients; +} + +Client *AutoLootManager::FindAutoLootClient(Client *resolved_client, Corpse *corpse) +{ + if (!resolved_client || !corpse || !corpse->CanPlayerLoot(resolved_client->CharacterID())) { + return nullptr; + } + + auto settings = GetCharacterSettings(resolved_client->CharacterID()); + if (settings.enabled) { + return resolved_client; + } + + auto group = resolved_client->GetGroup(); + if (!group) { + return nullptr; + } + + for (auto member : GetGroupClients(group)) { + if (!corpse->CanPlayerLoot(member->CharacterID())) { + continue; + } + + settings = GetCharacterSettings(member->CharacterID()); + if (settings.enabled) { + return member; + } + } + + return nullptr; +} + +Client *AutoLootManager::DetermineRecipient(Client *resolved_client, Corpse *corpse, const GroupSettings &settings) +{ + if (!resolved_client || !corpse) { + return nullptr; + } + + auto group = resolved_client->GetGroup(); + if (!group || group->GroupCount() <= 1) { + return resolved_client; + } + + const auto mode = NormalizeGroupMode(settings.loot_mode); + if (mode == "none") { + return nullptr; + } + + if (mode == "solo" || mode == "killer") { + return resolved_client; + } + + if (mode == "master") { + auto leader = group->GetLeader(); + if (leader && leader->IsClient() && corpse->CanPlayerLoot(leader->CastToClient()->CharacterID())) { + return leader->CastToClient(); + } + return resolved_client; + } + + if (mode == "assigned") { + for (auto member : GetGroupClients(group)) { + if (member->CharacterID() == settings.assigned_character_id && corpse->CanPlayerLoot(member->CharacterID())) { + return member; + } + } + return resolved_client; + } + + if (mode == "robin") { + auto clients = GetGroupClients(group); + clients.erase( + std::remove_if( + clients.begin(), + clients.end(), + [corpse](Client *member) { return !corpse->CanPlayerLoot(member->CharacterID()); } + ), + clients.end() + ); + + if (clients.empty()) { + return resolved_client; + } + + auto updated_settings = settings; + const uint32 index = updated_settings.round_robin_index % clients.size(); + updated_settings.round_robin_index++; + SaveGroupSettings(group->GetID(), updated_settings); + return clients[index]; + } + + return resolved_client; +} + +void AutoLootManager::ProcessCorpseDeath(Corpse *corpse, Mob *killer) +{ + if (!corpse || !corpse->IsNPCCorpse()) { + return; + } + + auto client = ResolveLootClient(killer); + if (!client) { + return; + } + + ProcessCorpse(corpse, client, false); +} + +void AutoLootManager::ProcessNearby(Client *client, float radius) +{ + if (!client) { + return; + } + + if (radius <= 0.0f) { + radius = kDefaultNearbyRadius; + } + + if (radius > kMaxNearbyRadius) { + radius = kMaxNearbyRadius; + } + + uint32 processed = 0; + for (auto &[corpse_id, corpse] : entity_list.GetCorpseList()) { + if (!corpse || !corpse->IsNPCCorpse() || corpse->IsLocked() || corpse->IsBeingLooted()) { + continue; + } + + if (corpse->CalculateDistance(client) > radius) { + continue; + } + + if (!corpse->CanPlayerLoot(client->CharacterID())) { + continue; + } + + ProcessCorpse(corpse, client, true); + processed++; + } + + client->Message(Chat::White, fmt::format("AutoLoot nearby processed {} corpse{}.", processed, processed == 1 ? "" : "s").c_str()); +} + +void AutoLootManager::ProcessCorpse(Corpse *corpse, Client *resolved_client, bool nearby) +{ + if (!corpse || !resolved_client || !corpse->IsNPCCorpse() || corpse->IsBeingLooted()) { + return; + } + + if (QueueCorpseEntries(corpse, resolved_client, nearby)) { + auto autoloot_client = FindAutoLootClient(resolved_client, corpse); + if (autoloot_client) { + SendNativeUpdate(autoloot_client); + } + } +} + +bool AutoLootManager::QueueCorpseEntries(Corpse *corpse, Client *resolved_client, bool nearby) +{ + if (!corpse || !resolved_client || !corpse->IsNPCCorpse() || corpse->IsBeingLooted()) { + return false; + } + + if (corpse->IsLocked() && !HasPendingVotes(corpse->GetID())) { + return false; + } + + auto autoloot_client = FindAutoLootClient(resolved_client, corpse); + if (!autoloot_client) { + return false; + } + + auto settings = GetCharacterSettings(autoloot_client->CharacterID()); + if (!settings.enabled) { + return false; + } + + GroupSettings group_settings; + auto group = autoloot_client->GetGroup(); + if (group) { + group_settings = GetGroupSettings(group->GetID()); + if (NormalizeGroupMode(group_settings.loot_mode) == "none") { + return false; + } + } + + std::vector loot_slots; + for (auto item_data : corpse->GetLootItems()) { + if (!item_data || IsBagChildSlot(item_data->equip_slot)) { + continue; + } + + loot_slots.push_back(item_data->lootslot); + } + + const auto corpse_id = corpse->GetID(); + const auto corpse_name = corpse->GetCleanName(); + bool queued = false; + std::vector> auto_loot_entries; + for (const auto loot_slot : loot_slots) { + auto item_data = corpse->GetItem(loot_slot); + if (!item_data || !item_data->item_id || HasQueuedEntry(corpse->GetID(), loot_slot)) { + continue; + } + + const auto filter_action = GetFilterAction(autoloot_client->CharacterID(), item_data->item_id, settings.filter_mode); + if (filter_action == "skip") { + continue; + } + + auto recipient = DetermineRecipient(autoloot_client, corpse, group_settings); + if (!recipient || !corpse->CanPlayerLoot(recipient->CharacterID())) { + continue; + } + + const auto *item = database.GetItem(item_data->item_id); + if (!item) { + continue; + } + + LootEntry entry; + entry.entry_id = m_next_loot_entry_id++; + entry.corpse_id = corpse->GetID(); + entry.loot_slot = loot_slot; + entry.item_id = item_data->item_id; + entry.icon_id = item->Icon; + entry.quantity = GetCorpseItemQuantity(corpse, loot_slot); + entry.owner_character_id = recipient->CharacterID(); + entry.group_id = group ? group->GetID() : 0; + entry.shared = group && group->GroupCount() > 1 && NormalizeGroupMode(group_settings.loot_mode) != "solo"; + entry.no_drop = IsNoDrop(item_data->item_id); + entry.item_name = item->Name; + entry.corpse_name = corpse->GetCleanName(); + entry.state = entry.shared && group_settings.need_greed_enabled && entry.no_drop ? "rolling" : "waiting"; + entry.rule = filter_action == "loot" ? "auto" : "ask"; + if (filter_action == "loot" && HasFilter(autoloot_client->CharacterID(), item_data->item_id, "include")) { + entry.rule = "always"; + } + entry.created_at = std::time(nullptr); + + m_loot_entries[entry.entry_id] = entry; + queued = true; + + if (filter_action == "loot" && entry.state != "rolling") { + auto_loot_entries.emplace_back(recipient, entry.entry_id); + } + } + + for (const auto &[recipient, entry_id] : auto_loot_entries) { + if (recipient) { + LootEntryForClient(recipient, entry_id); + } + } + + corpse = entity_list.GetCorpseByID(corpse_id); + + if (queued) { + if (corpse) { + LootCoin(corpse, autoloot_client); + corpse->ResetDecayTimer(); + } + + if (settings.log_enabled) { + Audit( + autoloot_client->CharacterID(), + nearby ? "nearby_queue" : "kill_queue", + 0, + 0, + corpse_name + ); + } + } + + return queued; +} + +bool AutoLootManager::HasQueuedEntry(uint16 corpse_id, uint16 loot_slot) const +{ + for (const auto &[entry_id, entry] : m_loot_entries) { + if (entry.corpse_id == corpse_id && entry.loot_slot == loot_slot) { + return true; + } + } + + return false; +} + +bool AutoLootManager::IsEntryVisibleToClient(const LootEntry &entry, Client *client) const +{ + if (!client) { + return false; + } + + if (!entry.shared) { + return entry.owner_character_id == client->CharacterID(); + } + + auto group = client->GetGroup(); + return group && group->GetID() == entry.group_id; +} + +void AutoLootManager::PruneLootEntries() +{ + for (auto iter = m_loot_entries.begin(); iter != m_loot_entries.end();) { + auto corpse = entity_list.GetCorpseByID(iter->second.corpse_id); + auto item_data = corpse ? corpse->GetItem(iter->second.loot_slot) : nullptr; + if (!corpse || !item_data || item_data->item_id != iter->second.item_id) { + iter = m_loot_entries.erase(iter); + } + else { + ++iter; + } + } +} + +void AutoLootManager::SendNativeSnapshot(Client *client) +{ + if (!client) { + return; + } + + PruneLootEntries(); + + client->Message(Chat::White, "AUTOLOOT|snapshot|begin"); + for (const auto &[entry_id, entry] : m_loot_entries) { + if (!IsEntryVisibleToClient(entry, client)) { + continue; + } + + auto corpse = entity_list.GetCorpseByID(entry.corpse_id); + const bool locked = corpse && (corpse->IsLocked() || corpse->IsBeingLooted() || !corpse->CanPlayerLoot(client->CharacterID())); + const auto state = locked ? std::string("locked") : entry.state; + client->Message( + Chat::White, + fmt::format( + "AUTOLOOT|entry|scope={}|id={}|corpse_id={}|slot={}|item_id={}|icon={}|name={}|qty={}|source={}|state={}|rule={}|locked={}|nodrop={}", + entry.shared ? "shared" : "personal", + entry.entry_id, + entry.corpse_id, + entry.loot_slot, + entry.item_id, + entry.icon_id, + ProtocolValue(entry.item_name), + std::max(1, entry.quantity), + ProtocolValue(entry.corpse_name), + state, + ProtocolValue(entry.rule), + locked ? 1 : 0, + entry.no_drop ? 1 : 0 + ).c_str() + ); + } + client->Message(Chat::White, "AUTOLOOT|snapshot|end"); +} + +void AutoLootManager::SendNativeUpdate(Client *client) +{ + SendNativeStatus(client); + SendNativeSnapshot(client); +} + +void AutoLootManager::RefreshQueuedRulesForClient(Client *client) +{ + if (!client) { + return; + } + + const auto settings = GetCharacterSettings(client->CharacterID()); + for (auto &[entry_id, entry] : m_loot_entries) { + if (!IsEntryVisibleToClient(entry, client)) { + continue; + } + + const auto filter_action = GetFilterAction(client->CharacterID(), entry.item_id, settings.filter_mode); + if (filter_action == "skip") { + entry.rule = "never"; + } + else if (filter_action == "loot" && HasFilter(client->CharacterID(), entry.item_id, "include")) { + entry.rule = "always"; + } + else { + entry.rule = filter_action == "loot" ? "auto" : "ask"; + } + } +} + +void AutoLootManager::SendNativeFilterUpdate(Client *client) +{ + RefreshQueuedRulesForClient(client); + SendNativeUpdate(client); + SendNativeFilters(client, "both"); +} + +void AutoLootManager::HandleLootAction(Client *client, const Seperator *sep) +{ + if (!client || !sep || sep->argnum < 3 || !sep->IsNumber(2)) { + client->Message(Chat::White, "Usage: #autoloot action [Entry ID] [loot|leave|never|alwaysloot]"); + return; + } + + const uint32 entry_id = Strings::ToUnsignedInt(sep->arg[2]); + const std::string action = Strings::ToLower(sep->arg[3]); + + if (action == "loot" || action == "alwaysloot") { + bool filter_changed = false; + if (action == "alwaysloot") { + auto iter = m_loot_entries.find(entry_id); + if (iter != m_loot_entries.end() && IsEntryVisibleToClient(iter->second, client)) { + SetFilter(client->CharacterID(), iter->second.item_id, "include"); + filter_changed = true; + } + } + + LootEntryForClient(client, entry_id); + if (filter_changed) { + SendNativeFilterUpdate(client); + } + else { + SendNativeUpdate(client); + } + return; + } + + if (action == "leave" || action == "pass" || action == "no") { + LeaveEntryForClient(client, entry_id, false); + SendNativeUpdate(client); + return; + } + + if (action == "never") { + const bool filter_changed = LeaveEntryForClient(client, entry_id, true); + if (filter_changed) { + SendNativeFilterUpdate(client); + } + else { + SendNativeUpdate(client); + } + return; + } + + if (action == "need" || action == "greed" || action == "alwaysneed" || action == "alwaysgreed") { + auto iter = m_loot_entries.find(entry_id); + if (iter == m_loot_entries.end() || !IsEntryVisibleToClient(iter->second, client)) { + client->Message(Chat::Red, "That AutoLoot entry is no longer available."); + SendNativeUpdate(client); + return; + } + + iter->second.state = action; + bool filter_changed = false; + if (action == "alwaysneed") { + SetFilter(client->CharacterID(), iter->second.item_id, "include"); + filter_changed = true; + } + client->Message(Chat::White, fmt::format("AutoLoot marked {} as {}.", iter->second.item_name, action).c_str()); + if (filter_changed) { + SendNativeFilterUpdate(client); + } + else { + SendNativeUpdate(client); + } + return; + } + + client->Message(Chat::White, "Usage: #autoloot action [Entry ID] [loot|leave|never|alwaysloot]"); +} + +void AutoLootManager::HandlePersonalLootCommand(Client *client, const Seperator *sep) +{ + if (!client || !sep || sep->argnum < 2) { + client->Message(Chat::White, "Usage: #autoloot personal [lootall|leaveall]"); + return; + } + + PruneLootEntries(); + + std::vector entry_ids; + for (const auto &[entry_id, entry] : m_loot_entries) { + if (!entry.shared && IsEntryVisibleToClient(entry, client)) { + entry_ids.push_back(entry_id); + } + } + + if (!strcasecmp(sep->arg[2], "lootall")) { + for (const auto entry_id : entry_ids) { + LootEntryForClient(client, entry_id); + } + SendNativeUpdate(client); + return; + } + + if (!strcasecmp(sep->arg[2], "leaveall")) { + for (const auto entry_id : entry_ids) { + LeaveEntryForClient(client, entry_id, false); + } + SendNativeUpdate(client); + return; + } + + client->Message(Chat::White, "Usage: #autoloot personal [lootall|leaveall]"); +} + +void AutoLootManager::LootEntryForClient(Client *client, uint32 entry_id) +{ + auto iter = m_loot_entries.find(entry_id); + if (iter == m_loot_entries.end() || !IsEntryVisibleToClient(iter->second, client)) { + client->Message(Chat::Red, "That AutoLoot entry is no longer available."); + return; + } + + const auto entry = iter->second; + auto corpse = entity_list.GetCorpseByID(entry.corpse_id); + if (!corpse || !corpse->IsNPCCorpse()) { + m_loot_entries.erase(iter); + client->Message(Chat::Red, "That corpse is no longer available."); + return; + } + + auto item_data = corpse->GetItem(entry.loot_slot); + if (!item_data || item_data->item_id != entry.item_id) { + m_loot_entries.erase(iter); + client->Message(Chat::Red, "That item is no longer on the corpse."); + return; + } + + Client *recipient = client; + if (!entry.shared && entry.owner_character_id != client->CharacterID()) { + recipient = entity_list.GetClientByCharID(entry.owner_character_id); + } + + if (!recipient || !corpse->CanPlayerLoot(recipient->CharacterID())) { + iter->second.state = "denied"; + client->Message(Chat::Red, "You cannot loot that corpse."); + return; + } + + auto result = corpse->AutoLootItem(recipient, entry.loot_slot, true); + + if (result.IsSuccess()) { + if (GetCharacterSettings(recipient->CharacterID()).log_enabled) { + Audit(recipient->CharacterID(), "queued_loot", result.item_id, result.item_count, corpse->GetCleanName()); + } + m_loot_entries.erase(entry_id); + FinalizeCorpse(corpse, recipient); + return; + } + + auto update_iter = m_loot_entries.find(entry_id); + if (update_iter != m_loot_entries.end()) { + if (result.code == CorpseAutoLootResultCode::PartialStacked && result.remaining_count > 0) { + update_iter->second.quantity = result.remaining_count; + update_iter->second.state = "inventory_full"; + } + else { + update_iter->second.state = result.code == CorpseAutoLootResultCode::InventoryFull ? "inventory_full" : "failed"; + } + } +} + +bool AutoLootManager::LeaveEntryForClient(Client *client, uint32 entry_id, bool add_never_filter) +{ + auto iter = m_loot_entries.find(entry_id); + if (iter == m_loot_entries.end() || !IsEntryVisibleToClient(iter->second, client)) { + client->Message(Chat::Red, "That AutoLoot entry is no longer available."); + return false; + } + + const auto entry = iter->second; + bool filter_changed = false; + if (add_never_filter) { + SetFilter(client->CharacterID(), entry.item_id, "exclude"); + client->Message(Chat::White, fmt::format("AutoLoot will never loot {} for this character.", entry.item_name).c_str()); + filter_changed = true; + } + + if (auto corpse = entity_list.GetCorpseByID(entry.corpse_id)) { + corpse->ResetDecayTimer(); + } + + m_loot_entries.erase(iter); + return filter_changed; +} + +void AutoLootManager::FinalizeCorpse(Corpse *corpse, Client *coin_client) +{ + if (!corpse || HasPendingVotes(corpse->GetID())) { + return; + } + + corpse->UnLock(); + LootCoin(corpse, coin_client); + + if (corpse->IsEmpty()) { + corpse->Delete(); + } + else { + corpse->ResetDecayTimer(); + } +} + +void AutoLootManager::LootCoin(Corpse *corpse, Client *client) +{ + if (!corpse || !client || !corpse->CanPlayerLoot(client->CharacterID())) { + return; + } + + const auto copper = corpse->GetCopper(); + const auto silver = corpse->GetSilver(); + const auto gold = corpse->GetGold(); + const auto platinum = corpse->GetPlatinum(); + + if (!copper && !silver && !gold && !platinum) { + return; + } + + client->AddMoneyToPP(copper, silver, gold, platinum, true); + client->SaveCurrency(); + corpse->RemoveCash(); + + client->Message( + Chat::Loot, + fmt::format( + "AutoLoot looted {} from {}.", + Strings::Money(platinum, gold, silver, copper), + corpse->GetCleanName() + ).c_str() + ); +} + +bool AutoLootManager::IsNoDrop(uint32 item_id) +{ + const auto *item = database.GetItem(item_id); + return item && item->NoDrop == 0; +} + +bool AutoLootManager::HasPendingVotes(uint16 corpse_id) const +{ + for (const auto &[vote_id, vote] : m_pending_votes) { + if (vote.corpse_id == corpse_id) { + return true; + } + } + + return false; +} + +void AutoLootManager::StartNeedGreedVote(Group *group, Corpse *corpse, uint16 loot_slot, uint32 item_id) +{ + if (!group || !corpse || !item_id) { + return; + } + + for (const auto &[vote_id, vote] : m_pending_votes) { + if (vote.corpse_id == corpse->GetID() && vote.loot_slot == loot_slot) { + return; + } + } + + auto clients = GetGroupClients(group); + clients.erase( + std::remove_if( + clients.begin(), + clients.end(), + [corpse](Client *client) { return !corpse->CanPlayerLoot(client->CharacterID()); } + ), + clients.end() + ); + + if (clients.empty()) { + return; + } + + const auto *item = database.GetItem(item_id); + if (!item) { + return; + } + + PendingVote vote; + vote.vote_id = m_next_vote_id++; + vote.group_id = group->GetID(); + vote.corpse_id = corpse->GetID(); + vote.loot_slot = loot_slot; + vote.item_id = item_id; + vote.item_name = item->Name; + vote.expires_at = std::time(nullptr) + kNeedGreedSeconds; + + for (auto client : clients) { + vote.votes[client->CharacterID()] = VoteChoice::Unset; + } + + m_pending_votes[vote.vote_id] = vote; + corpse->Lock(); + + EQ::SayLinkEngine linker; + linker.SetLinkType(EQ::saylink::SayLinkItemData); + linker.SetItemData(item); + linker.GenerateLink(); + + const auto need = Saylink::Silent(fmt::format("#needgreed vote {} need", vote.vote_id), "Need"); + const auto greed = Saylink::Silent(fmt::format("#needgreed vote {} greed", vote.vote_id), "Greed"); + const auto pass = Saylink::Silent(fmt::format("#needgreed vote {} pass", vote.vote_id), "Pass"); + + for (auto client : clients) { + client->Message( + Chat::Yellow, + fmt::format( + "Need/Greed {}: {} | {} | {} | {}", + vote.vote_id, + linker.Link(), + need, + greed, + pass + ).c_str() + ); + } +} + +void AutoLootManager::CastNeedGreedVote(Client *client, uint32 vote_id, VoteChoice choice) +{ + if (!client) { + return; + } + + auto vote_iter = m_pending_votes.find(vote_id); + if (vote_iter == m_pending_votes.end()) { + client->Message(Chat::Red, "That Need/Greed vote is no longer active."); + return; + } + + auto &vote = vote_iter->second; + auto member_vote = vote.votes.find(client->CharacterID()); + if (member_vote == vote.votes.end()) { + client->Message(Chat::Red, "You are not eligible for that Need/Greed vote."); + return; + } + + member_vote->second = choice; + client->Message(Chat::White, fmt::format("Need/Greed vote {} recorded.", vote_id).c_str()); + + const bool complete = std::all_of( + vote.votes.begin(), + vote.votes.end(), + [](const auto &entry) { return entry.second != VoteChoice::Unset; } + ); + + if (complete) { + ProcessVote(vote_id, false); + } +} + +void AutoLootManager::ProcessVote(uint32 vote_id, bool timeout) +{ + auto vote_iter = m_pending_votes.find(vote_id); + if (vote_iter == m_pending_votes.end()) { + return; + } + + auto vote = vote_iter->second; + auto corpse = entity_list.GetCorpseByID(vote.corpse_id); + + std::vector need; + std::vector greed; + for (const auto &[character_id, choice] : vote.votes) { + if (choice == VoteChoice::Need) { + need.push_back(character_id); + } + else if (choice == VoteChoice::Greed) { + greed.push_back(character_id); + } + } + + std::vector pool = !need.empty() ? need : greed; + if (!corpse || pool.empty()) { + const auto message = fmt::format("Need/Greed vote {} ended with no winner for {}.", vote_id, vote.item_name); + for (const auto &[character_id, choice] : vote.votes) { + if (auto member = entity_list.GetClientByCharID(character_id)) { + member->Message(Chat::Yellow, message.c_str()); + } + } + m_pending_votes.erase(vote_id); + if (corpse && !HasPendingVotes(corpse->GetID())) { + corpse->UnLock(); + } + return; + } + + const uint32 winner_character_id = pool[zone ? zone->random.Int(0, static_cast(pool.size() - 1)) : 0]; + auto winner = entity_list.GetClientByCharID(winner_character_id); + if (!winner) { + const auto message = fmt::format("Need/Greed vote {} winner is offline; {} remains on the corpse.", vote_id, vote.item_name); + for (const auto &[character_id, choice] : vote.votes) { + if (auto member = entity_list.GetClientByCharID(character_id)) { + member->Message(Chat::Yellow, message.c_str()); + } + } + m_pending_votes.erase(vote_id); + if (!HasPendingVotes(corpse->GetID())) { + corpse->UnLock(); + } + return; + } + + auto result = corpse->AutoLootItem(winner, vote.loot_slot, true); + const bool transferred = result.IsSuccess(); + if (result.IsSuccess()) { + const auto message = fmt::format("{} won Need/Greed vote {} for {}.", winner->GetCleanName(), vote_id, vote.item_name); + for (const auto &[character_id, choice] : vote.votes) { + if (auto member = entity_list.GetClientByCharID(character_id)) { + member->Message(Chat::Yellow, message.c_str()); + } + } + } + else { + const auto message = fmt::format("{} could not receive {}; it remains on the corpse.", winner->GetCleanName(), vote.item_name); + for (const auto &[character_id, choice] : vote.votes) { + if (auto member = entity_list.GetClientByCharID(character_id)) { + member->Message(Chat::Yellow, message.c_str()); + } + } + } + + m_pending_votes.erase(vote_id); + + if (!HasPendingVotes(corpse->GetID())) { + corpse->UnLock(); + if (transferred) { + FinalizeCorpse(corpse, winner); + } + else if (corpse->IsEmpty()) { + corpse->Delete(); + } + } +} + +void AutoLootManager::ForceProcessVotes(Client *client) +{ + if (!client) { + return; + } + + auto group = client->GetGroup(); + if (!group) { + client->Message(Chat::White, "You are not in a group."); + return; + } + + std::vector vote_ids; + for (const auto &[vote_id, vote] : m_pending_votes) { + if (vote.group_id == group->GetID()) { + vote_ids.push_back(vote_id); + } + } + + for (const auto vote_id : vote_ids) { + ProcessVote(vote_id, false); + } + + client->Message(Chat::White, fmt::format("Force processed {} Need/Greed vote{}.", vote_ids.size(), vote_ids.size() == 1 ? "" : "s").c_str()); +} + +void AutoLootManager::RecoverVotes(Client *client) +{ + std::vector stale_votes; + for (const auto &[vote_id, vote] : m_pending_votes) { + if (!entity_list.GetCorpseByID(vote.corpse_id)) { + stale_votes.push_back(vote_id); + } + } + + for (const auto vote_id : stale_votes) { + m_pending_votes.erase(vote_id); + } + + client->Message(Chat::White, fmt::format("Recovered {} stale Need/Greed vote{}.", stale_votes.size(), stale_votes.size() == 1 ? "" : "s").c_str()); +} + +bool AutoLootManager::IsAutosellExcluded(uint32 character_id, uint32 item_id) +{ + auto results = database.QueryDatabase( + fmt::format( + "SELECT 1 FROM `custom_autoloot_autosell_exclusions` " + "WHERE `character_id` = {} AND `item_id` = {} LIMIT 1", + character_id, + item_id + ) + ); + + return results.Success() && results.RowCount() > 0; +} + +void AutoLootManager::SetAutosellExcluded(uint32 character_id, uint32 item_id, bool excluded) +{ + if (excluded) { + database.QueryDatabase( + fmt::format( + "INSERT IGNORE INTO `custom_autoloot_autosell_exclusions` (`character_id`, `item_id`, `created_at`) " + "VALUES ({}, {}, UNIX_TIMESTAMP())", + character_id, + item_id + ) + ); + } + else { + database.QueryDatabase( + fmt::format( + "DELETE FROM `custom_autoloot_autosell_exclusions` WHERE `character_id` = {} AND `item_id` = {}", + character_id, + item_id + ) + ); + } +} + +std::vector AutoLootManager::GetAutosellExclusions(uint32 character_id) +{ + std::vector item_ids; + auto results = database.QueryDatabase( + fmt::format( + "SELECT `item_id` FROM `custom_autoloot_autosell_exclusions` " + "WHERE `character_id` = {} ORDER BY `item_id` LIMIT 100", + character_id + ) + ); + + if (!results.Success()) { + return item_ids; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + item_ids.push_back(row[0] ? Strings::ToUnsignedInt(row[0]) : 0); + } + + return item_ids; +} + +std::vector AutoLootManager::BuildAutosellPreview(Client *client, uint64 &total_value) +{ + std::vector entries; + total_value = 0; + + if (!client) { + return entries; + } + + auto &inventory = client->GetInv(); + for (int16 slot_id = EQ::invslot::GENERAL_BEGIN; slot_id <= EQ::invslot::GENERAL_END; ++slot_id) { + auto bag = inventory.GetItem(slot_id); + if (!bag || !bag->IsClassBag() || !IsAutosellBag(bag->GetItem()->ID)) { + continue; + } + + for (uint8 bag_index = EQ::invbag::SLOT_BEGIN; bag_index <= EQ::invbag::SLOT_END && bag_index < bag->GetItem()->BagSlots; ++bag_index) { + const int16 item_slot = EQ::InventoryProfile::CalcSlotId(slot_id, bag_index); + auto inst = inventory.GetItem(item_slot); + if (!inst || !inst->GetItem()) { + continue; + } + + if (IsAutosellProtected(inst) || IsAutosellExcluded(client->CharacterID(), inst->GetItem()->ID)) { + continue; + } + + const uint32 quantity = inst->IsStackable() ? std::max(1, inst->GetCharges()) : 1; + const uint64 value = static_cast(inst->GetItem()->Price) * quantity; + + entries.push_back( + AutosellEntry{ + .slot_id = item_slot, + .item_id = inst->GetItem()->ID, + .quantity = quantity, + .value = value, + .item_name = inst->GetItem()->Name + } + ); + total_value += value; + } + } + + return entries; +} + +void AutoLootManager::PreviewAutosell(Client *client) +{ + uint64 total_value = 0; + auto entries = BuildAutosellPreview(client, total_value); + if (entries.empty()) { + client->Message(Chat::White, "AutoSell found no eligible items in bags 45500 through 45505."); + return; + } + + AutosellSession session; + session.session_id = m_next_autosell_session_id++; + session.expires_at = std::time(nullptr) + kAutosellSessionSeconds; + session.entries = entries; + session.total_value = total_value; + m_autosell_sessions[client->CharacterID()] = session; + + client->Message(Chat::White, fmt::format("AutoSell preview: {} item stack{} for {}.", entries.size(), entries.size() == 1 ? "" : "s", Strings::MoneyShort(total_value)).c_str()); +} + +void AutoLootManager::ConfirmAutosell(Client *client) +{ + auto session_iter = m_autosell_sessions.find(client->CharacterID()); + if (session_iter == m_autosell_sessions.end() || session_iter->second.expires_at <= std::time(nullptr)) { + client->Message(Chat::Red, "No active AutoSell preview. Use #autosell preview first."); + m_autosell_sessions.erase(client->CharacterID()); + return; + } + + uint64 paid = 0; + uint32 sold = 0; + for (const auto &entry : session_iter->second.entries) { + auto inst = client->GetInv().GetItem(entry.slot_id); + if (!inst || !inst->GetItem() || inst->GetItem()->ID != entry.item_id || IsAutosellProtected(inst)) { + continue; + } + + const uint32 current_quantity = inst->IsStackable() ? std::max(1, inst->GetCharges()) : 1; + const uint32 quantity = std::min(entry.quantity, current_quantity); + if (!quantity) { + continue; + } + + const uint64 value = static_cast(inst->GetItem()->Price) * quantity; + client->DeleteItemInInventory(entry.slot_id, inst->IsStackable() ? quantity : 0, true); + paid += value; + sold++; + } + + if (paid) { + client->AddMoneyToPP(paid, true); + client->SaveCurrency(); + } + + m_autosell_sessions.erase(client->CharacterID()); + client->Message(Chat::White, fmt::format("AutoSell sold {} item stack{} for {}.", sold, sold == 1 ? "" : "s", Strings::MoneyShort(paid)).c_str()); +} + +void AutoLootManager::CancelAutosell(Client *client) +{ + m_autosell_sessions.erase(client->CharacterID()); + client->Message(Chat::White, "AutoSell preview cancelled."); +} + +void AutoLootManager::HandleAutolootCommand(Client *client, const Seperator *sep) +{ + if (!client || !sep) { + return; + } + + auto settings = GetCharacterSettings(client->CharacterID()); + const int arguments = sep->argnum; + + if (!arguments || !strcasecmp(sep->arg[1], "status")) { + SendStatus(client); + return; + } + + if ( + !strcasecmp(sep->arg[1], "window") || + !strcasecmp(sep->arg[1], "ui") || + !strcasecmp(sep->arg[1], "panel") + ) { + client->Message(Chat::White, "AUTOLOOT|window|show"); + SendNativeUpdate(client); + return; + } + + if (!strcasecmp(sep->arg[1], "native")) { + if ( + arguments >= 2 && + ( + !strcasecmp(sep->arg[2], "show") || + !strcasecmp(sep->arg[2], "open") || + !strcasecmp(sep->arg[2], "window") + ) + ) { + client->Message(Chat::White, "AUTOLOOT|window|show"); + SendNativeUpdate(client); + return; + } + + if ( + arguments < 2 || + !strcasecmp(sep->arg[2], "status") || + !strcasecmp(sep->arg[2], "snapshot") + ) { + SendNativeUpdate(client); + return; + } + + client->Message(Chat::White, "Usage: #autoloot native [show|status|snapshot]"); + return; + } + + if (!strcasecmp(sep->arg[1], "action")) { + HandleLootAction(client, sep); + return; + } + + if (!strcasecmp(sep->arg[1], "personal")) { + HandlePersonalLootCommand(client, sep); + return; + } + + if (!strcasecmp(sep->arg[1], "help")) { + SendHelp(client); + return; + } + + if (!strcasecmp(sep->arg[1], "on")) { + settings.enabled = true; + if (arguments >= 2 && IsValidFilterMode(sep->arg[2])) { + settings.filter_mode = NormalizeFilterMode(sep->arg[2]); + } + SaveCharacterSettings(client->CharacterID(), settings); + client->Message(Chat::White, fmt::format("AutoLoot enabled. Filter mode: {}.", settings.filter_mode).c_str()); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (!strcasecmp(sep->arg[1], "off")) { + settings.enabled = false; + SaveCharacterSettings(client->CharacterID(), settings); + client->Message(Chat::White, "AutoLoot disabled."); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (!strcasecmp(sep->arg[1], "mode")) { + if (arguments < 2 || !IsValidFilterMode(sep->arg[2])) { + client->Message(Chat::White, "Usage: #autoloot mode [both|include|exclude]"); + return; + } + + settings.filter_mode = NormalizeFilterMode(sep->arg[2]); + SaveCharacterSettings(client->CharacterID(), settings); + client->Message(Chat::White, fmt::format("AutoLoot filter mode set to {}.", settings.filter_mode).c_str()); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (!strcasecmp(sep->arg[1], "debug") || !strcasecmp(sep->arg[1], "log")) { + if (arguments < 2) { + client->Message(Chat::White, "Usage: #autoloot debug [on|off] or #autoloot log [on|off]"); + return; + } + + const bool enabled = Strings::ToBool(sep->arg[2]); + if (!strcasecmp(sep->arg[1], "debug")) { + settings.debug_enabled = enabled; + } + else { + settings.log_enabled = enabled; + } + + SaveCharacterSettings(client->CharacterID(), settings); + client->Message(Chat::White, fmt::format("AutoLoot {} {}.", sep->arg[1], enabled ? "enabled" : "disabled").c_str()); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (!strcasecmp(sep->arg[1], "nearby") || !strcasecmp(sep->arg[1], "aoe")) { + const float radius = arguments >= 2 && sep->IsNumber(2) ? Strings::ToFloat(sep->arg[2]) : kDefaultNearbyRadius; + ProcessNearby(client, radius); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (!strcasecmp(sep->arg[1], "group")) { + auto group = client->GetGroup(); + if (!group) { + client->Message(Chat::White, "You are not in a group."); + return; + } + + if (arguments < 2 || !strcasecmp(sep->arg[2], "status")) { + auto group_settings = GetGroupSettings(group->GetID()); + client->Message( + Chat::White, + fmt::format( + "AutoLoot group mode: {}, Need/Greed: {}, Assigned Character ID: {}.", + group_settings.loot_mode, + group_settings.need_greed_enabled ? "on" : "off", + group_settings.assigned_character_id + ).c_str() + ); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (!strcasecmp(sep->arg[2], "help")) { + SendGroupHelp(client); + return; + } + + if (!group->IsLeader(client) && client->Admin() < AccountStatus::GMAdmin) { + client->Message(Chat::Red, "Only the group leader can change AutoLoot group settings."); + return; + } + + auto group_settings = GetGroupSettings(group->GetID()); + if (!strcasecmp(sep->arg[2], "needgreed")) { + if (arguments < 3) { + client->Message(Chat::White, "Usage: #autoloot group needgreed [on|off]"); + return; + } + + group_settings.need_greed_enabled = Strings::ToBool(sep->arg[3]); + SaveGroupSettings(group->GetID(), group_settings); + client->Message(Chat::White, fmt::format("Need/Greed {}.", group_settings.need_greed_enabled ? "enabled" : "disabled").c_str()); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (!strcasecmp(sep->arg[2], "forceprocess")) { + ForceProcessVotes(client); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (!strcasecmp(sep->arg[2], "recover")) { + RecoverVotes(client); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (!strcasecmp(sep->arg[2], "assign")) { + if (arguments < 3) { + client->Message(Chat::White, "Usage: #autoloot group assign [Character Name]"); + return; + } + + auto assigned = entity_list.GetClientByName(sep->arg[3]); + if (!assigned || !group->IsGroupMember(assigned)) { + client->Message(Chat::Red, "That player is not in your group or is not in this zone."); + return; + } + + group_settings.loot_mode = "assigned"; + group_settings.assigned_character_id = assigned->CharacterID(); + SaveGroupSettings(group->GetID(), group_settings); + client->Message(Chat::White, fmt::format("AutoLoot group assigned looter set to {}.", assigned->GetCleanName()).c_str()); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (!IsValidGroupMode(sep->arg[2])) { + SendGroupHelp(client); + return; + } + + group_settings.loot_mode = NormalizeGroupMode(sep->arg[2]); + SaveGroupSettings(group->GetID(), group_settings); + client->Message(Chat::White, fmt::format("AutoLoot group mode set to {}.", group_settings.loot_mode).c_str()); + RefreshWindowIfRequested(this, client, sep); + return; + } + + SendHelp(client); +} + +void AutoLootManager::HandleLootFilterCommand(Client *client, const Seperator *sep) +{ + if (!client || !sep) { + return; + } + + if (!sep->argnum || !strcasecmp(sep->arg[1], "help")) { + client->Message(Chat::White, "Usage: #lootfilter keep [Item ID]"); + client->Message(Chat::White, "Usage: #lootfilter ignore [Item ID]"); + client->Message(Chat::White, "Usage: #lootfilter unset [Item ID]"); + client->Message(Chat::White, "Usage: #lootfilter add [Item ID] [keep|ignore]"); + client->Message(Chat::White, "Usage: #lootfilter remove [Item ID]"); + client->Message(Chat::White, "Usage: #lootfilter list [keep|ignore|all]"); + return; + } + + if (!strcasecmp(sep->arg[1], "mode")) { + auto settings = GetCharacterSettings(client->CharacterID()); + if (sep->argnum < 2 || !IsValidFilterMode(sep->arg[2])) { + client->Message(Chat::White, "Usage: #lootfilter mode [both|include|exclude]"); + return; + } + + settings.filter_mode = NormalizeFilterMode(sep->arg[2]); + SaveCharacterSettings(client->CharacterID(), settings); + client->Message(Chat::White, fmt::format("Loot filter mode set to {}.", settings.filter_mode).c_str()); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (!strcasecmp(sep->arg[1], "native")) { + if (sep->argnum >= 2 && !strcasecmp(sep->arg[2], "list")) { + SendNativeStatus(client); + SendNativeFilters(client, sep->argnum >= 3 ? sep->arg[3] : "both"); + return; + } + + client->Message(Chat::White, "Usage: #lootfilter native list [keep|ignore|all]"); + return; + } + + if (!strcasecmp(sep->arg[1], "list")) { + const auto mode = sep->argnum >= 2 ? NormalizeRuleMode(sep->arg[2]) : "both"; + const auto filters = GetFilters(client->CharacterID(), mode); + if (filters.empty()) { + client->Message(Chat::White, "No AutoLoot rules found."); + return; + } + + for (const auto &[item_id, filter_mode] : filters) { + const auto *item = database.GetItem(item_id); + client->Message(Chat::White, fmt::format("{}: {} ({})", DisplayRuleMode(filter_mode), item ? item->Name : "Unknown Item", item_id).c_str()); + } + return; + } + + if (!strcasecmp(sep->arg[1], "add")) { + if (sep->argnum < 2 || !sep->IsNumber(2)) { + client->Message(Chat::White, "Usage: #lootfilter add [Item ID] [keep|ignore]"); + return; + } + + const uint32 item_id = Strings::ToUnsignedInt(sep->arg[2]); + const auto mode = sep->argnum >= 3 ? NormalizeRuleMode(sep->arg[3]) : "include"; + if (mode != "include" && mode != "exclude") { + client->Message(Chat::White, "Usage: #lootfilter add [Item ID] [keep|ignore]"); + return; + } + + const auto *item = database.GetItem(item_id); + if (!item) { + client->Message(Chat::Red, "Invalid item ID."); + return; + } + + SetFilter(client->CharacterID(), item_id, mode); + client->Message(Chat::White, fmt::format("Set AutoLoot rule {} for {} ({}).", DisplayRuleMode(mode), item->Name, item_id).c_str()); + SendNativeFilterUpdate(client); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (!strcasecmp(sep->arg[1], "remove")) { + if (sep->argnum >= 2 && sep->IsNumber(2)) { + const uint32 item_id = Strings::ToUnsignedInt(sep->arg[2]); + const auto mode = sep->argnum >= 3 ? NormalizeRuleMode(sep->arg[3]) : "both"; + if (!IsValidFilterMode(mode)) { + client->Message(Chat::White, "Usage: #lootfilter remove [Item ID] [keep|ignore|all]"); + return; + } + + RemoveFilter(client->CharacterID(), item_id, mode); + client->Message(Chat::White, fmt::format("Unset AutoLoot rule for item {}.", item_id).c_str()); + SendNativeFilterUpdate(client); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (sep->argnum < 3 || !IsValidFilterMode(NormalizeRuleMode(sep->arg[2])) || !sep->IsNumber(3)) { + client->Message(Chat::White, "Usage: #lootfilter remove [keep|ignore|all] [Item ID]"); + return; + } + + const uint32 item_id = Strings::ToUnsignedInt(sep->arg[3]); + RemoveFilter(client->CharacterID(), item_id, NormalizeRuleMode(sep->arg[2])); + client->Message(Chat::White, fmt::format("Unset AutoLoot rule for item {}.", item_id).c_str()); + SendNativeFilterUpdate(client); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (!strcasecmp(sep->arg[1], "unset") && sep->argnum >= 2 && sep->IsNumber(2)) { + const uint32 item_id = Strings::ToUnsignedInt(sep->arg[2]); + RemoveFilter(client->CharacterID(), item_id, "both"); + client->Message(Chat::White, fmt::format("Unset AutoLoot rule for item {}.", item_id).c_str()); + SendNativeFilterUpdate(client); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if ((!strcasecmp(sep->arg[1], "include") || !strcasecmp(sep->arg[1], "exclude") || !strcasecmp(sep->arg[1], "keep") || !strcasecmp(sep->arg[1], "ignore")) && sep->argnum >= 2 && sep->IsNumber(2)) { + const uint32 item_id = Strings::ToUnsignedInt(sep->arg[2]); + const auto *item = database.GetItem(item_id); + if (!item) { + client->Message(Chat::Red, "Invalid item ID."); + return; + } + + const auto mode = NormalizeRuleMode(sep->arg[1]); + SetFilter(client->CharacterID(), item_id, mode); + client->Message(Chat::White, fmt::format("Set AutoLoot rule {} for {} ({}).", DisplayRuleMode(mode), item->Name, item_id).c_str()); + SendNativeFilterUpdate(client); + RefreshWindowIfRequested(this, client, sep); + return; + } + + client->Message(Chat::White, "Usage: #lootfilter help"); +} + +void AutoLootManager::HandleAutosellCommand(Client *client, const Seperator *sep) +{ + if (!client || !sep) { + return; + } + + if (!sep->argnum || !strcasecmp(sep->arg[1], "help")) { + client->Message(Chat::White, "Usage: #autosell preview"); + client->Message(Chat::White, "Usage: #autosell confirm"); + client->Message(Chat::White, "Usage: #autosell cancel"); + client->Message(Chat::White, "Usage: #autosell exclude [add|remove|list|clear] [Item ID]"); + return; + } + + if (!strcasecmp(sep->arg[1], "preview")) { + PreviewAutosell(client); + return; + } + + if (!strcasecmp(sep->arg[1], "confirm")) { + ConfirmAutosell(client); + return; + } + + if (!strcasecmp(sep->arg[1], "cancel")) { + CancelAutosell(client); + return; + } + + if (!strcasecmp(sep->arg[1], "exclude")) { + if (sep->argnum < 2) { + client->Message(Chat::White, "Usage: #autosell exclude [add|remove|list|clear] [Item ID]"); + return; + } + + if (!strcasecmp(sep->arg[2], "list")) { + auto exclusions = GetAutosellExclusions(client->CharacterID()); + if (exclusions.empty()) { + client->Message(Chat::White, "No AutoSell exclusions found."); + return; + } + + for (const auto item_id : exclusions) { + const auto *item = database.GetItem(item_id); + client->Message(Chat::White, fmt::format("- {} ({})", item ? item->Name : "Unknown Item", item_id).c_str()); + } + return; + } + + if (!strcasecmp(sep->arg[2], "clear")) { + database.QueryDatabase(fmt::format("DELETE FROM `custom_autoloot_autosell_exclusions` WHERE `character_id` = {}", client->CharacterID())); + client->Message(Chat::White, "AutoSell exclusions cleared."); + RefreshWindowIfRequested(this, client, sep); + return; + } + + if (sep->argnum < 3 || !sep->IsNumber(3)) { + client->Message(Chat::White, "Usage: #autosell exclude [add|remove] [Item ID]"); + return; + } + + const uint32 item_id = Strings::ToUnsignedInt(sep->arg[3]); + const bool add = !strcasecmp(sep->arg[2], "add"); + const bool remove = !strcasecmp(sep->arg[2], "remove"); + if (!add && !remove) { + client->Message(Chat::White, "Usage: #autosell exclude [add|remove] [Item ID]"); + return; + } + + SetAutosellExcluded(client->CharacterID(), item_id, add); + client->Message(Chat::White, fmt::format("AutoSell exclusion {} for item {}.", add ? "added" : "removed", item_id).c_str()); + RefreshWindowIfRequested(this, client, sep); + return; + } + + client->Message(Chat::White, "Usage: #autosell help"); +} + +void AutoLootManager::HandleNeedGreedCommand(Client *client, const Seperator *sep) +{ + if (!client || !sep || sep->argnum < 3 || strcasecmp(sep->arg[1], "vote") || !sep->IsNumber(2)) { + client->Message(Chat::White, "Usage: #needgreed vote [Vote ID] [need|greed|pass]"); + return; + } + + CastNeedGreedVote(client, Strings::ToUnsignedInt(sep->arg[2]), ParseVoteChoice(sep->arg[3])); +} + +void AutoLootManager::ShowWindow(Client *client) +{ + if (!client) { + return; + } + + client->Message(Chat::White, "AUTOLOOT|window|show"); + SendNativeUpdate(client); +} + +void AutoLootManager::SendStatus(Client *client) +{ + const auto settings = GetCharacterSettings(client->CharacterID()); + client->Message( + Chat::White, + fmt::format( + "AutoLoot: {}, mode: {}, debug: {}, log: {}.", + settings.enabled ? "on" : "off", + settings.filter_mode, + settings.debug_enabled ? "on" : "off", + settings.log_enabled ? "on" : "off" + ).c_str() + ); + + SendNativeUpdate(client); +} + +void AutoLootManager::SendNativeStatus(Client *client) +{ + if (!client) { + return; + } + + const auto settings = GetCharacterSettings(client->CharacterID()); + const auto include_count = GetFilters(client->CharacterID(), "include").size(); + const auto exclude_count = GetFilters(client->CharacterID(), "exclude").size(); + + std::string group_mode = "none"; + std::string assigned_name = "none"; + bool grouped = false; + bool leader = false; + + auto group = client->GetGroup(); + if (group) { + grouped = true; + leader = group->IsLeader(client) || client->Admin() >= AccountStatus::GMAdmin; + + const auto group_settings = GetGroupSettings(group->GetID()); + group_mode = group_settings.loot_mode; + + if (group_settings.assigned_character_id) { + assigned_name = database.GetCharNameByID(group_settings.assigned_character_id); + if (assigned_name.empty()) { + assigned_name = "unknown"; + } + } + } + + const auto status = fmt::format( + "AUTOLOOT|status|enabled={}|include={}|exclude={}|grouped={}|group_mode={}|assigned={}|leader={}", + settings.enabled ? 1 : 0, + include_count, + exclude_count, + grouped ? 1 : 0, + group_mode, + assigned_name, + leader ? 1 : 0 + ); + + client->Message(Chat::White, status.c_str()); +} + +void AutoLootManager::SendNativeFilters(Client *client, const std::string &filter_mode) +{ + if (!client) { + return; + } + + const auto mode = NormalizeRuleMode(filter_mode); + client->Message(Chat::White, fmt::format("AUTOLOOT|filters|begin|mode={}", mode).c_str()); + + for (const auto &[item_id, filter_mode] : GetFilters(client->CharacterID(), mode)) { + const auto *item = database.GetItem(item_id); + client->Message( + Chat::White, + fmt::format( + "AUTOLOOT|filter|mode={}|item_id={}|icon={}|name={}", + ProtocolValue(filter_mode), + item_id, + item ? item->Icon : 0, + ProtocolValue(item ? item->Name : "Unknown Item") + ).c_str() + ); + } + + client->Message(Chat::White, fmt::format("AUTOLOOT|filters|end|mode={}", mode).c_str()); +} + +void AutoLootManager::SendHelp(Client *client) +{ + client->Message(Chat::White, "Usage: #autoloot on [both|include|exclude]"); + client->Message(Chat::White, "Usage: #autoloot off"); + client->Message(Chat::White, "Usage: #autoloot mode [both|include|exclude]"); + client->Message(Chat::White, "Usage: #autoloot nearby [radius]"); + client->Message(Chat::White, "Usage: #autoloot group [status|help|none|solo|master|robin|killer|assign|needgreed|forceprocess|recover]"); +} + +void AutoLootManager::SendGroupHelp(Client *client) +{ + client->Message(Chat::White, "Usage: #autoloot group none"); + client->Message(Chat::White, "Usage: #autoloot group solo"); + client->Message(Chat::White, "Usage: #autoloot group master"); + client->Message(Chat::White, "Usage: #autoloot group robin"); + client->Message(Chat::White, "Usage: #autoloot group killer"); + client->Message(Chat::White, "Usage: #autoloot group assign [Character Name]"); + client->Message(Chat::White, "Usage: #autoloot group needgreed [on|off]"); + client->Message(Chat::White, "Usage: #autoloot group forceprocess"); + client->Message(Chat::White, "Usage: #autoloot group recover"); +} + +void AutoLootManager::Audit(uint32 character_id, const std::string &action, uint32 item_id, uint32 quantity, const std::string &detail) +{ + database.QueryDatabase( + fmt::format( + "INSERT INTO `custom_autoloot_audit` (`character_id`, `action`, `item_id`, `quantity`, `detail`, `created_at`) " + "VALUES ({}, '{}', {}, {}, '{}', UNIX_TIMESTAMP())", + character_id, + Strings::Escape(action), + item_id, + quantity, + Strings::Escape(detail) + ) + ); +} diff --git a/zone/autoloot_manager.h b/zone/autoloot_manager.h new file mode 100644 index 0000000000..862c90c7f8 --- /dev/null +++ b/zone/autoloot_manager.h @@ -0,0 +1,169 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. +*/ +#pragma once + +#include "common/types.h" + +#include +#include +#include +#include +#include + +class Client; +class Corpse; +class Group; +class Mob; +class Seperator; + +class AutoLootManager { +public: + enum class VoteChoice { + Unset, + Need, + Greed, + Pass + }; + + void Process(); + void ProcessCorpseDeath(Corpse *corpse, Mob *killer); + void ProcessNearby(Client *client, float radius); + void ShowWindow(Client *client); + + void HandleAutolootCommand(Client *client, const Seperator *sep); + void HandleLootFilterCommand(Client *client, const Seperator *sep); + void HandleAutosellCommand(Client *client, const Seperator *sep); + void HandleNeedGreedCommand(Client *client, const Seperator *sep); + +private: + struct CharacterSettings { + bool enabled = false; + std::string filter_mode = "both"; + bool debug_enabled = false; + bool log_enabled = false; + }; + + struct GroupSettings { + std::string loot_mode = "solo"; + uint32 assigned_character_id = 0; + uint32 round_robin_index = 0; + bool need_greed_enabled = false; + }; + + struct PendingVote { + uint32 vote_id = 0; + uint32 group_id = 0; + uint16 corpse_id = 0; + uint16 loot_slot = 0; + uint32 item_id = 0; + std::string item_name; + std::map votes; + time_t expires_at = 0; + }; + + struct AutosellEntry { + int16 slot_id = 0; + uint32 item_id = 0; + uint32 quantity = 0; + uint64 value = 0; + std::string item_name; + }; + + struct AutosellSession { + uint32 session_id = 0; + time_t expires_at = 0; + std::vector entries; + uint64 total_value = 0; + }; + + struct LootEntry { + uint32 entry_id = 0; + uint16 corpse_id = 0; + uint16 loot_slot = 0; + uint32 item_id = 0; + uint32 icon_id = 0; + uint32 quantity = 0; + uint32 owner_character_id = 0; + uint32 group_id = 0; + bool shared = false; + bool no_drop = false; + std::string item_name; + std::string corpse_name; + std::string state = "waiting"; + std::string rule = "-"; + time_t created_at = 0; + }; + + CharacterSettings GetCharacterSettings(uint32 character_id); + void SaveCharacterSettings(uint32 character_id, const CharacterSettings &settings); + GroupSettings GetGroupSettings(uint32 group_id); + void SaveGroupSettings(uint32 group_id, const GroupSettings &settings); + + bool ShouldLootItem(uint32 character_id, uint32 item_id, const std::string &filter_mode); + std::string GetFilterAction(uint32 character_id, uint32 item_id, const std::string &filter_mode); + bool HasFilter(uint32 character_id, uint32 item_id, const std::string &filter_mode); + void SetFilter(uint32 character_id, uint32 item_id, const std::string &filter_mode); + void RemoveFilter(uint32 character_id, uint32 item_id, const std::string &filter_mode); + std::vector> GetFilters(uint32 character_id, const std::string &filter_mode); + + Client *ResolveLootClient(Mob *killer); + Client *FindAutoLootClient(Client *resolved_client, Corpse *corpse); + Client *DetermineRecipient(Client *resolved_client, Corpse *corpse, const GroupSettings &settings); + std::vector GetGroupClients(Group *group); + + void ProcessCorpse(Corpse *corpse, Client *resolved_client, bool nearby); + bool QueueCorpseEntries(Corpse *corpse, Client *resolved_client, bool nearby); + bool HasQueuedEntry(uint16 corpse_id, uint16 loot_slot) const; + bool IsEntryVisibleToClient(const LootEntry &entry, Client *client) const; + void PruneLootEntries(); + void RefreshQueuedRulesForClient(Client *client); + void SendNativeSnapshot(Client *client); + void SendNativeUpdate(Client *client); + void SendNativeFilterUpdate(Client *client); + void HandleLootAction(Client *client, const Seperator *sep); + void HandlePersonalLootCommand(Client *client, const Seperator *sep); + void LootEntryForClient(Client *client, uint32 entry_id); + bool LeaveEntryForClient(Client *client, uint32 entry_id, bool add_never_filter); + void FinalizeCorpse(Corpse *corpse, Client *coin_client); + void LootCoin(Corpse *corpse, Client *client); + + bool IsNoDrop(uint32 item_id); + bool HasPendingVotes(uint16 corpse_id) const; + void StartNeedGreedVote(Group *group, Corpse *corpse, uint16 loot_slot, uint32 item_id); + void CastNeedGreedVote(Client *client, uint32 vote_id, VoteChoice choice); + void ProcessVote(uint32 vote_id, bool timeout); + void ForceProcessVotes(Client *client); + void RecoverVotes(Client *client); + + bool IsAutosellExcluded(uint32 character_id, uint32 item_id); + void SetAutosellExcluded(uint32 character_id, uint32 item_id, bool excluded); + std::vector GetAutosellExclusions(uint32 character_id); + std::vector BuildAutosellPreview(Client *client, uint64 &total_value); + void PreviewAutosell(Client *client); + void ConfirmAutosell(Client *client); + void CancelAutosell(Client *client); + + void SendStatus(Client *client); + void SendNativeStatus(Client *client); + void SendNativeFilters(Client *client, const std::string &filter_mode); + void SendHelp(Client *client); + void SendGroupHelp(Client *client); + void Audit(uint32 character_id, const std::string &action, uint32 item_id = 0, uint32 quantity = 0, const std::string &detail = ""); + + std::map m_pending_votes; + std::map m_autosell_sessions; + std::map m_loot_entries; + uint32 m_next_vote_id = 1; + uint32 m_next_autosell_session_id = 1; + uint32 m_next_loot_entry_id = 1; + time_t m_last_process = 0; +}; + +extern AutoLootManager auto_loot_manager; diff --git a/zone/command.cpp b/zone/command.cpp index 93e5b3430b..11a40aab86 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -103,6 +103,8 @@ int command_init(void) command_add("appearanceeffects", "[Help|Remove|Set|View] - Modify appearance effects on yourself or your target.", AccountStatus::GMAdmin, command_appearanceeffects) || command_add("apply_shared_memory", "[shared_memory_name] - Tells every zone and world to apply a specific shared memory segment by name.", AccountStatus::GMImpossible, command_apply_shared_memory) || command_add("attack", "[Entity Name] - Make your NPC target attack an entity by name", AccountStatus::GMLeadAdmin, command_attack) || + command_add("autoloot", "[window|on|off|mode|nearby|group|stackables] - Source-backed AutoLoot settings and actions", AccountStatus::Player, command_autoloot) || + command_add("autosell", "[preview|confirm|cancel|exclude] - Preview and sell items from AutoSell bags", AccountStatus::Player, command_autosell) || command_add("augmentitem", "Force augments an item. Must have the augment item window open.", AccountStatus::GMImpossible, command_augmentitem) || command_add("ban", "[Character Name] [Reason] - Ban by character name", AccountStatus::GMLeadAdmin, command_ban) || command_add("bugs", "[Close|Delete|Review|Search|View] - Handles player bug reports", AccountStatus::QuestTroupe, command_bugs) || @@ -168,6 +170,7 @@ int command_init(void) command_add("kill", "Kill your target", AccountStatus::GMAdmin, command_kill) || command_add("killallnpcs", "[npc_name] - Kills all npcs by search name, leave blank for all attackable NPC's", AccountStatus::GMMgmt, command_killallnpcs) || command_add("list", "[npcs|players|corpses|doors|objects] [search] - Search entities", AccountStatus::ApprenticeGuide, command_list) || + command_add("lootfilter", "[include|exclude|remove|list|mode] - Manage AutoLoot item filters", AccountStatus::Player, command_lootfilter) || command_add("lootsim", "[npc_type_id] [loottable_id] [iterations] - Runs benchmark simulations using real loot logic to report numbers and data", AccountStatus::GMImpossible, command_lootsim) || command_add("load_shared_memory", "[shared_memory_name] - Reloads shared memory and uses the input as output", AccountStatus::GMImpossible, command_load_shared_memory) || command_add("loc", "Print out your or your target's current location and heading", AccountStatus::Player, command_loc) || @@ -184,6 +187,7 @@ int command_init(void) command_add("npccast", "[targetname/entityid] [spellid] - Causes NPC target to cast spellid on targetname/entityid", AccountStatus::QuestTroupe, command_npccast) || command_add("npcedit", "[column] [value] - Mega NPC editing command", AccountStatus::GMAdmin, command_npcedit) || command_add("npceditmass", "[name-search] [column] [value] - Mass (Zone wide) NPC data editing command", AccountStatus::GMAdmin, command_npceditmass) || + command_add("needgreed", "[vote] [Vote ID] [need|greed|pass] - Respond to AutoLoot Need/Greed rolls", AccountStatus::Player, command_needgreed) || command_add("npcemote", "[Message] - Make your NPC target emote a message.", AccountStatus::GMLeadAdmin, command_npcemote) || command_add("npcloot", "Manipulate the loot an NPC is carrying. Use #npcloot help for more information.", AccountStatus::QuestTroupe, command_npcloot) || command_add("npcsay", "[Message] - Make your NPC target say a message.", AccountStatus::GMLeadAdmin, command_npcsay) || diff --git a/zone/command.h b/zone/command.h index da80557c17..d8667c6859 100644 --- a/zone/command.h +++ b/zone/command.h @@ -66,6 +66,8 @@ void command_appearance(Client *c, const Seperator *sep); void command_appearanceeffects(Client *c, const Seperator *sep); void command_apply_shared_memory(Client *c, const Seperator *sep); void command_attack(Client *c, const Seperator *sep); +void command_autoloot(Client *c, const Seperator *sep); +void command_autosell(Client *c, const Seperator *sep); void command_augmentitem(Client *c, const Seperator *sep); void command_ban(Client *c, const Seperator *sep); void command_bugs(Client *c, const Seperator *sep); @@ -129,6 +131,7 @@ void command_kick(Client *c, const Seperator *sep); void command_killallnpcs(Client *c, const Seperator *sep); void command_kill(Client *c, const Seperator *sep); void command_list(Client *c, const Seperator *sep); +void command_lootfilter(Client *c, const Seperator *sep); void command_lootsim(Client *c, const Seperator *sep); void command_load_shared_memory(Client *c, const Seperator *sep); void command_loc(Client *c, const Seperator *sep); @@ -151,6 +154,7 @@ void command_npcsay(Client *c, const Seperator *sep); void command_npcshout(Client *c, const Seperator *sep); void command_npcspawn(Client *c, const Seperator *sep); void command_npctypespawn(Client *c, const Seperator *sep); +void command_needgreed(Client *c, const Seperator *sep); void command_nudge(Client *c, const Seperator *sep); void command_nukebuffs(Client *c, const Seperator *sep); void command_nukeitem(Client *c, const Seperator *sep); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index bafcd03e56..85495a5677 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -65,6 +65,292 @@ void Corpse::SendLootReqErrorPacket(Client *client, LootResponse response) safe_delete(outapp); } +CorpseAutoLootResult Corpse::AutoLootItem(Client *c, uint16 lootslot, bool send_messages) +{ + CorpseAutoLootResult result; + + if (!c || IsPlayerCorpse()) { + return result; + } + + LootItem *item_data = nullptr; + LootItem *bag_item_data[EQ::invbag::SLOT_COUNT] = {}; + + item_data = GetItem(lootslot, bag_item_data); + if (!item_data) { + return result; + } + + const EQ::ItemData *item = database.GetItem(item_data->item_id); + if (!item) { + return result; + } + + EQ::ItemInstance *inst = database.CreateItem( + item, + item_data->charges, + item_data->aug_1, + item_data->aug_2, + item_data->aug_3, + item_data->aug_4, + item_data->aug_5, + item_data->aug_6, + item_data->attuned, + item_data->custom_data, + item_data->ornamenticon, + item_data->ornamentidfile, + item_data->ornament_hero_model + ); + + if (!inst) { + return result; + } + + result.item_id = item->ID; + result.item_name = item->Name; + result.item_count = inst->IsStackable() ? inst->GetCharges() : 1; + + if (c->CheckLoreConflict(item)) { + result.code = CorpseAutoLootResultCode::LoreConflict; + if (send_messages) { + c->MessageString(Chat::White, LOOT_LORE_ERROR); + } + safe_delete(inst); + return result; + } + + if (inst->IsAugmented()) { + for (int i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { + EQ::ItemInstance *augment = inst->GetAugment(i); + if (augment && c->CheckLoreConflict(augment->GetItem())) { + result.code = CorpseAutoLootResultCode::LoreConflict; + if (send_messages) { + c->MessageString(Chat::White, LOOT_LORE_ERROR); + } + safe_delete(inst); + return result; + } + } + } + + bool prevent_loot = false; + bool dz_denied = false; + + if (RuleB(Zone, UseZoneController)) { + auto controller = entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID); + if (controller && parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_LOOT_ZONE)) { + const auto &export_string = fmt::format( + "{} {} {} {}", + inst->GetItem()->ID, + inst->GetCharges(), + EntityList::RemoveNumbers(corpse_name), + GetID() + ); + + std::vector args = {inst, this}; + if (parse->EventNPC(EVENT_LOOT_ZONE, controller, c, export_string, 0, &args) != 0) { + prevent_loot = true; + } + } + } + + if (parse->PlayerHasQuestSub(EVENT_LOOT)) { + const auto &export_string = fmt::format( + "{} {} {} {}", + inst->GetItem()->ID, + inst->GetCharges(), + EntityList::RemoveNumbers(corpse_name), + GetID() + ); + + std::vector args = {inst, this}; + if (parse->EventPlayer(EVENT_LOOT, c, export_string, 0, &args) != 0) { + prevent_loot = true; + } + } + + if (parse->ZoneHasQuestSub(EVENT_LOOT_ZONE)) { + const auto &export_string = fmt::format( + "{} {} {} {}", + inst->GetItem()->ID, + inst->GetCharges(), + EntityList::RemoveNumbers(corpse_name), + GetID() + ); + + std::vector args = {inst, this, c}; + if (parse->EventZone(EVENT_LOOT_ZONE, zone, export_string, 0, &args) != 0) { + prevent_loot = true; + } + } + + auto dz = zone ? zone->GetDynamicZone() : nullptr; + if (dz && !dz->CanClientLootCorpse(c, GetNPCTypeID(), GetID())) { + prevent_loot = true; + dz_denied = true; + if (send_messages) { + c->MessageString(Chat::Loot, LOOT_NOT_ALLOWED, inst->GetItem()->Name); + } + } + + if (parse->ItemHasQuestSub(inst, EVENT_LOOT)) { + const auto &export_string = fmt::format( + "{} {} {} {}", + inst->GetItem()->ID, + inst->GetCharges(), + EntityList::RemoveNumbers(corpse_name), + GetID() + ); + + std::vector args = {inst, this}; + if (parse->EventItem(EVENT_LOOT, c, inst, this, export_string, 0, &args) != 0) { + prevent_loot = true; + } + } + + if (prevent_loot) { + result.code = dz_denied ? CorpseAutoLootResultCode::DynamicZoneDenied : CorpseAutoLootResultCode::LootPrevented; + safe_delete(inst); + return result; + } + + auto record_loot_event = [&](uint32 charges) { + if (PlayerEventLogs::Instance()->IsEventEnabled(PlayerEvent::LOOT_ITEM)) { + auto e = PlayerEvent::LootItemEvent{ + .item_id = inst->GetItem()->ID, + .item_name = inst->GetItem()->Name, + .charges = static_cast(charges), + .augment_1_id = inst->GetAugmentItemID(0), + .augment_2_id = inst->GetAugmentItemID(1), + .augment_3_id = inst->GetAugmentItemID(2), + .augment_4_id = inst->GetAugmentItemID(3), + .augment_5_id = inst->GetAugmentItemID(4), + .augment_6_id = inst->GetAugmentItemID(5), + .npc_id = GetNPCTypeID(), + .corpse_name = EntityList::RemoveNumbers(corpse_name) + }; + + RecordPlayerEventLogWithClient(c, PlayerEvent::LOOT_ITEM, e); + } + }; + + auto record_success_side_effects = [&]() { + c->CheckItemDiscoverability(inst->GetID()); + + if (zone && zone->adv_data) { + auto *ad = (ServerZoneAdventureDataReply_Struct *) zone->adv_data; + if (ad->type == Adventure_Collect && ad->data_id == inst->GetItem()->ID) { + zone->DoAdventureCountIncrease(); + } + } + }; + + const uint32 original_count = inst->IsStackable() ? inst->GetCharges() : 1; + + auto timestamps = database.GetItemRecastTimestamps(c->CharacterID()); + const auto *d = inst->GetItem(); + if (d->RecastDelay) { + if (d->RecastType != RECAST_TYPE_UNLINKED_ITEM) { + inst->SetRecastTimestamp(timestamps.count(d->RecastType) ? timestamps.at(d->RecastType) : 0); + } + else { + inst->SetRecastTimestamp(timestamps.count(d->ID) ? timestamps.at(d->ID) : 0); + } + } + + if (!c->AutoPutLootInInventory(*inst, true, false, bag_item_data)) { + if (inst->IsStackable() && inst->GetCharges() < original_count) { + const uint32 transferred_count = original_count - inst->GetCharges(); + item_data->charges = inst->GetCharges(); + m_is_corpse_changed = true; + + if (RuleB(TaskSystem, EnableTaskSystem) && IsNPCCorpse()) { + c->UpdateTasksOnLoot(this, item->ID, transferred_count); + } + + record_success_side_effects(); + record_loot_event(transferred_count); + + result.code = CorpseAutoLootResultCode::PartialStacked; + result.item_count = transferred_count; + result.remaining_count = inst->GetCharges(); + } + else { + result.code = CorpseAutoLootResultCode::InventoryFull; + } + + safe_delete(inst); + return result; + } + + if (RuleB(TaskSystem, EnableTaskSystem) && IsNPCCorpse()) { + c->UpdateTasksOnLoot(this, item->ID, original_count); + } + + record_success_side_effects(); + record_loot_event(original_count); + + database.DeleteItemOffCharacterCorpse( + m_corpse_db_id, + item_data->equip_slot, + item_data->item_id + ); + RemoveItem(item_data->lootslot); + + if (item->IsClassBag()) { + for (int i = EQ::invbag::SLOT_BEGIN; i <= EQ::invbag::SLOT_END; i++) { + if (bag_item_data[i]) { + database.DeleteItemOffCharacterCorpse( + m_corpse_db_id, + bag_item_data[i]->equip_slot, + bag_item_data[i]->item_id + ); + RemoveItem(bag_item_data[i]); + } + } + } + + EQ::SayLinkEngine linker; + linker.SetLinkType(EQ::saylink::SayLinkItemInst); + linker.SetItemInst(inst); + linker.GenerateLink(); + + if (send_messages) { + c->MessageString(Chat::Loot, LOOTED_MESSAGE, linker.Link().c_str()); + + Group *g = c->GetGroup(); + if (g) { + g->GroupMessageString( + c, + Chat::Loot, + OTHER_LOOTED_MESSAGE, + c->GetName(), + linker.Link().c_str() + ); + } + else { + Raid *r = c->GetRaid(); + if (r) { + r->RaidMessageString( + c, + Chat::Loot, + OTHER_LOOTED_MESSAGE, + c->GetName(), + linker.Link().c_str() + ); + } + } + } + + c->SendItemLink(inst, true); + + result.code = CorpseAutoLootResultCode::Success; + result.item_count = original_count; + + safe_delete(inst); + return result; +} + Corpse::Corpse( NPC *npc, LootItems *item_list, diff --git a/zone/corpse.h b/zone/corpse.h index 584b7d650c..aa1b3f9797 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -37,6 +37,26 @@ namespace EQ { #define MAX_LOOTERS 72 +enum class CorpseAutoLootResultCode { + Success, + Invalid, + LoreConflict, + LootPrevented, + DynamicZoneDenied, + InventoryFull, + PartialStacked +}; + +struct CorpseAutoLootResult { + CorpseAutoLootResultCode code = CorpseAutoLootResultCode::Invalid; + uint32 item_id = 0; + uint32 item_count = 0; + uint32 remaining_count = 0; + std::string item_name; + + bool IsSuccess() const { return code == CorpseAutoLootResultCode::Success; } +}; + class Corpse : public Mob { public: @@ -218,6 +238,7 @@ class Corpse : public Mob { uint16 GetFirstLootSlotByItemID(uint32 item_id); std::vector GetLootList(); inline const LootItems &GetLootItems() { return m_item_list; } + CorpseAutoLootResult AutoLootItem(Client *c, uint16 lootslot, bool send_messages = true); void LootCorpseItem(Client *c, const EQApplicationPacket *app); void EndLoot(Client *c, const EQApplicationPacket *app); void MakeLootRequestPackets(Client *c, const EQApplicationPacket *app); diff --git a/zone/gm_commands/autoloot.cpp b/zone/gm_commands/autoloot.cpp new file mode 100644 index 0000000000..db337929fa --- /dev/null +++ b/zone/gm_commands/autoloot.cpp @@ -0,0 +1,31 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. +*/ +#include "zone/autoloot_manager.h" +#include "zone/client.h" + +void command_autoloot(Client *c, const Seperator *sep) +{ + auto_loot_manager.HandleAutolootCommand(c, sep); +} + +void command_lootfilter(Client *c, const Seperator *sep) +{ + auto_loot_manager.HandleLootFilterCommand(c, sep); +} + +void command_autosell(Client *c, const Seperator *sep) +{ + auto_loot_manager.HandleAutosellCommand(c, sep); +} + +void command_needgreed(Client *c, const Seperator *sep) +{ + auto_loot_manager.HandleNeedGreedCommand(c, sep); +} diff --git a/zone/zone.cpp b/zone/zone.cpp index e0c6c44bc9..ef4671c25e 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -40,6 +40,7 @@ #include "common/seperator.h" #include "common/serverinfo.h" #include "common/strings.h" +#include "zone/autoloot_manager.h" #include "zone/dynamic_zone.h" #include "zone/guild_mgr.h" #include "zone/map.h" @@ -1520,6 +1521,7 @@ uint32 Zone::CountAuth() { bool Zone::Process() { spawn_conditions.Process(); + auto_loot_manager.Process(); if (spawn2_timer.Check()) { LinkedListIterator iterator(spawn2_list); From 4372d54f333b10b9005d7f0d4f1076c5d385d8bd Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Sat, 23 May 2026 23:07:51 -0700 Subject: [PATCH 120/194] Add standalone Live Items feature branch --- .../ui/EQUI_NativeItemForgeWnd.xml | 566 +++++++++++++++ common/item_instance.cpp | 464 ++++++++++++- common/item_instance.h | 12 + common/ruletypes.h | 4 + common/shareddb.cpp | 402 ++++++++++- common/shareddb.h | 18 + docs/live-items.md | 99 +++ features/README.md | 6 +- features/live-items/MANIFEST.md | 65 ++ features/live-items/README.md | 48 ++ .../live-items/sql/001_live_items_rules.sql | 12 + tests/CMakeLists.txt | 1 + tests/dynamic_item_test.h | 176 +++++ tests/main.cpp | 2 + world/world_boot.cpp | 2 + zone/CMakeLists.txt | 2 + zone/client.cpp | 35 +- zone/client.h | 2 + zone/command.cpp | 3 + zone/command.h | 3 + zone/gm_commands/itemedit.cpp | 513 ++++++++++++++ zone/gm_commands/liveitem.cpp | 649 ++++++++++++++++++ zone/inventory.cpp | 37 + zone/lua_iteminst.cpp | 48 ++ zone/lua_iteminst.h | 8 + zone/perl_client.cpp | 6 + zone/perl_questitem.cpp | 48 ++ 27 files changed, 3214 insertions(+), 17 deletions(-) create mode 100644 client_files/native_autoloot/ui/EQUI_NativeItemForgeWnd.xml create mode 100644 docs/live-items.md create mode 100644 features/live-items/MANIFEST.md create mode 100644 features/live-items/README.md create mode 100644 features/live-items/sql/001_live_items_rules.sql create mode 100644 tests/dynamic_item_test.h create mode 100644 zone/gm_commands/itemedit.cpp create mode 100644 zone/gm_commands/liveitem.cpp diff --git a/client_files/native_autoloot/ui/EQUI_NativeItemForgeWnd.xml b/client_files/native_autoloot/ui/EQUI_NativeItemForgeWnd.xml new file mode 100644 index 0000000000..5eb7b8ebaa --- /dev/null +++ b/client_files/native_autoloot/ui/EQUI_NativeItemForgeWnd.xml @@ -0,0 +1,566 @@ + + + + + + + + + + + + + + + + AIFW_NameEdit + WDT_Inner + true + true + 9614 + 33024 + Forged Blade + 255255255 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AIFW_FormPage + true + 1258 + 596280 + true + false + AIFW_NameLabel + AIFW_NameEdit + AIFW_TypeLabel + AIFW_WeaponButton + AIFW_ArmorButton + AIFW_JewelryButton + AIFW_CharmButton + AIFW_ShieldButton + AIFW_TypeHintLabel + + + + AIFW_StatsPage + true + 1258 + 596280 + true + false + AIFW_HPLabel + AIFW_HPMinusButton + AIFW_HPValueLabel + AIFW_HPPlusButton + AIFW_ManaLabel + AIFW_ManaMinusButton + AIFW_ManaValueLabel + AIFW_ManaPlusButton + AIFW_ACLabel + AIFW_ACMinusButton + AIFW_ACValueLabel + AIFW_ACPlusButton + AIFW_StatsHintLabel + + + + AIFW_CombatPage + true + 1258 + 596280 + true + false + AIFW_DamageLabel + AIFW_DamageMinusButton + AIFW_DamageValueLabel + AIFW_DamagePlusButton + AIFW_DelayLabel + AIFW_DelayMinusButton + AIFW_DelayValueLabel + AIFW_DelayPlusButton + AIFW_HasteLabel + AIFW_HasteMinusButton + AIFW_HasteValueLabel + AIFW_HastePlusButton + AIFW_CombatHintLabel + + + + AIFW_ReviewPage + true + 1258 + 596280 + true + false + AIFW_ReviewTitleLabel + AIFW_ReviewNameLabel + AIFW_ReviewTypeLabel + AIFW_ReviewStatsLabel + AIFW_ReviewCombatLabel + AIFW_CreateButton + + + + + + NativeItemForgeWnd + false + 150120 + 620410 + Item Forge + false + true + true + false + true + false + WDT_Rounded + AIFW_FormTab + AIFW_StatsTab + AIFW_CombatTab + AIFW_ReviewTab + AIFW_FormPage + AIFW_StatsPage + AIFW_CombatPage + AIFW_ReviewPage + AIFW_StatusLabel + + diff --git a/common/item_instance.cpp b/common/item_instance.cpp index 39271ba8e6..d51dd390da 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -23,11 +23,289 @@ #include "common/shareddb.h" #include "common/strings.h" +#include #include +#include +#include +#include +#include int32 next_item_serial_number = 1; std::unordered_set guids{}; +namespace { + constexpr const char *DynamicItemModPrefix = "dynamic_item.mod."; + constexpr const char *DynamicItemSetPrefix = "dynamic_item.set."; + + bool HasPrefix(const std::string &value, const char *prefix) + { + return value.rfind(prefix, 0) == 0; + } + + std::string NormalizeDynamicItemField(std::string field) + { + field = Strings::ToLower(field); + field.erase( + std::remove_if( + field.begin(), + field.end(), + [](const char c) { return c == '_' || c == '-' || c == ' ' || c == '.'; } + ), + field.end() + ); + return field; + } + + bool IsDynamicItemDataIdentifier(const std::string &identifier) + { + const auto key = Strings::ToLower(identifier); + return HasPrefix(key, DynamicItemModPrefix) || HasPrefix(key, DynamicItemSetPrefix); + } + + std::string GetDynamicItemKey(const char *prefix, const std::string &identifier) + { + return std::string(prefix) + NormalizeDynamicItemField(identifier); + } + + template + void ApplyDynamicItemNumber(T &target, int64 value, bool additive) + { + if constexpr (std::is_same_v) { + target = additive ? ((target ? 1 : 0) + value) != 0 : value != 0; + } else if constexpr (std::is_floating_point_v) { + target = static_cast((additive ? target : 0) + value); + } else { + const int64 current = additive ? static_cast(target) : 0; + int64 result = current + value; + + if constexpr (std::is_signed_v) { + result = std::max(std::numeric_limits::min(), std::min(result, std::numeric_limits::max())); + } else { + result = std::max(0, std::min(result, std::numeric_limits::max())); + } + + target = static_cast(result); + } + } + + bool ApplyDynamicItemStringField(EQ::ItemData &item, const std::string &field, const std::string &value) + { + if (field == "name") { + strn0cpy(item.Name, value.c_str(), sizeof(item.Name)); + return true; + } + + if (field == "lore") { + strn0cpy(item.Lore, value.c_str(), sizeof(item.Lore)); + return true; + } + + if (field == "idfile") { + strn0cpy(item.IDFile, value.c_str(), sizeof(item.IDFile)); + return true; + } + + if (field == "comment") { + strn0cpy(item.Comment, value.c_str(), sizeof(item.Comment)); + return true; + } + + if (field == "filename") { + strn0cpy(item.Filename, value.c_str(), sizeof(item.Filename)); + return true; + } + + if (field == "charmfile") { + strn0cpy(item.CharmFile, value.c_str(), sizeof(item.CharmFile)); + return true; + } + + if (field == "clickname") { + strn0cpy(item.ClickName, value.c_str(), sizeof(item.ClickName)); + return true; + } + + if (field == "procname") { + strn0cpy(item.ProcName, value.c_str(), sizeof(item.ProcName)); + return true; + } + + if (field == "wornname") { + strn0cpy(item.WornName, value.c_str(), sizeof(item.WornName)); + return true; + } + + if (field == "focusname") { + strn0cpy(item.FocusName, value.c_str(), sizeof(item.FocusName)); + return true; + } + + if (field == "scrollname") { + strn0cpy(item.ScrollName, value.c_str(), sizeof(item.ScrollName)); + return true; + } + + return false; + } + + bool ApplyDynamicItemNumericField(EQ::ItemData &item, const std::string &field, const int64 value, const bool additive) + { + if (field == "ac") { ApplyDynamicItemNumber(item.AC, value, additive); return true; } + if (field == "agi" || field == "aagi") { ApplyDynamicItemNumber(item.AAgi, value, additive); return true; } + if (field == "cha" || field == "acha") { ApplyDynamicItemNumber(item.ACha, value, additive); return true; } + if (field == "dex" || field == "adex") { ApplyDynamicItemNumber(item.ADex, value, additive); return true; } + if (field == "int" || field == "aint") { ApplyDynamicItemNumber(item.AInt, value, additive); return true; } + if (field == "sta" || field == "asta") { ApplyDynamicItemNumber(item.ASta, value, additive); return true; } + if (field == "str" || field == "astr") { ApplyDynamicItemNumber(item.AStr, value, additive); return true; } + if (field == "wis" || field == "awis") { ApplyDynamicItemNumber(item.AWis, value, additive); return true; } + if (field == "hp") { ApplyDynamicItemNumber(item.HP, value, additive); return true; } + if (field == "mana") { ApplyDynamicItemNumber(item.Mana, value, additive); return true; } + if (field == "endur" || field == "endurance") { ApplyDynamicItemNumber(item.Endur, value, additive); return true; } + if (field == "regen") { ApplyDynamicItemNumber(item.Regen, value, additive); return true; } + if (field == "manaregen") { ApplyDynamicItemNumber(item.ManaRegen, value, additive); return true; } + if (field == "enduranceregen" || field == "endurregen") { ApplyDynamicItemNumber(item.EnduranceRegen, value, additive); return true; } + if (field == "cr") { ApplyDynamicItemNumber(item.CR, value, additive); return true; } + if (field == "dr") { ApplyDynamicItemNumber(item.DR, value, additive); return true; } + if (field == "fr") { ApplyDynamicItemNumber(item.FR, value, additive); return true; } + if (field == "mr") { ApplyDynamicItemNumber(item.MR, value, additive); return true; } + if (field == "pr") { ApplyDynamicItemNumber(item.PR, value, additive); return true; } + if (field == "svcorruption" || field == "corrup" || field == "corruption") { ApplyDynamicItemNumber(item.SVCorruption, value, additive); return true; } + if (field == "attack") { ApplyDynamicItemNumber(item.Attack, value, additive); return true; } + if (field == "accuracy") { ApplyDynamicItemNumber(item.Accuracy, value, additive); return true; } + if (field == "avoidance") { ApplyDynamicItemNumber(item.Avoidance, value, additive); return true; } + if (field == "combateffects") { ApplyDynamicItemNumber(item.CombatEffects, value, additive); return true; } + if (field == "shielding") { ApplyDynamicItemNumber(item.Shielding, value, additive); return true; } + if (field == "spellshield") { ApplyDynamicItemNumber(item.SpellShield, value, additive); return true; } + if (field == "stunresist") { ApplyDynamicItemNumber(item.StunResist, value, additive); return true; } + if (field == "strikethrough") { ApplyDynamicItemNumber(item.StrikeThrough, value, additive); return true; } + if (field == "dotshielding") { ApplyDynamicItemNumber(item.DotShielding, value, additive); return true; } + if (field == "damageshield") { ApplyDynamicItemNumber(item.DamageShield, value, additive); return true; } + if (field == "dsmitigation") { ApplyDynamicItemNumber(item.DSMitigation, value, additive); return true; } + if (field == "haste") { ApplyDynamicItemNumber(item.Haste, value, additive); return true; } + if (field == "healamt" || field == "healing") { ApplyDynamicItemNumber(item.HealAmt, value, additive); return true; } + if (field == "spelldmg" || field == "spelldamage") { ApplyDynamicItemNumber(item.SpellDmg, value, additive); return true; } + if (field == "clairvoyance") { ApplyDynamicItemNumber(item.Clairvoyance, value, additive); return true; } + if (field == "purity") { ApplyDynamicItemNumber(item.Purity, value, additive); return true; } + if (field == "damage") { ApplyDynamicItemNumber(item.Damage, value, additive); return true; } + if (field == "delay") { ApplyDynamicItemNumber(item.Delay, value, additive); return true; } + if (field == "range") { ApplyDynamicItemNumber(item.Range, value, additive); return true; } + if (field == "backstabdmg" || field == "backstabdamage") { ApplyDynamicItemNumber(item.BackstabDmg, value, additive); return true; } + if (field == "elemdmgtype" || field == "elementaldamagetype") { ApplyDynamicItemNumber(item.ElemDmgType, value, additive); return true; } + if (field == "elemdmgamt" || field == "elementaldamage") { ApplyDynamicItemNumber(item.ElemDmgAmt, value, additive); return true; } + if (field == "banedmgamt" || field == "banedamage") { ApplyDynamicItemNumber(item.BaneDmgAmt, value, additive); return true; } + if (field == "banedmgbody") { ApplyDynamicItemNumber(item.BaneDmgBody, value, additive); return true; } + if (field == "banedmgrace") { ApplyDynamicItemNumber(item.BaneDmgRace, value, additive); return true; } + if (field == "banedmgraceamt") { ApplyDynamicItemNumber(item.BaneDmgRaceAmt, value, additive); return true; } + if (field == "extradmgskill") { ApplyDynamicItemNumber(item.ExtraDmgSkill, value, additive); return true; } + if (field == "extradmgamt" || field == "extradamage") { ApplyDynamicItemNumber(item.ExtraDmgAmt, value, additive); return true; } + if (field == "skillmodtype") { ApplyDynamicItemNumber(item.SkillModType, value, additive); return true; } + if (field == "skillmodvalue") { ApplyDynamicItemNumber(item.SkillModValue, value, additive); return true; } + if (field == "skillmodmax") { ApplyDynamicItemNumber(item.SkillModMax, value, additive); return true; } + if (field == "bardtype") { ApplyDynamicItemNumber(item.BardType, value, additive); return true; } + if (field == "bardvalue") { ApplyDynamicItemNumber(item.BardValue, value, additive); return true; } + if (field == "weight") { ApplyDynamicItemNumber(item.Weight, value, additive); return true; } + if (field == "price") { ApplyDynamicItemNumber(item.Price, value, additive); return true; } + if (field == "favor") { ApplyDynamicItemNumber(item.Favor, value, additive); return true; } + if (field == "guildfavor") { ApplyDynamicItemNumber(item.GuildFavor, value, additive); return true; } + if (field == "pointtype") { ApplyDynamicItemNumber(item.PointType, value, additive); return true; } + if (field == "icon") { ApplyDynamicItemNumber(item.Icon, value, additive); return true; } + if (field == "color") { ApplyDynamicItemNumber(item.Color, value, additive); return true; } + if (field == "material") { ApplyDynamicItemNumber(item.Material, value, additive); return true; } + if (field == "elitematerial") { ApplyDynamicItemNumber(item.EliteMaterial, value, additive); return true; } + if (field == "herosforgemodel") { ApplyDynamicItemNumber(item.HerosForgeModel, value, additive); return true; } + if (field == "light") { ApplyDynamicItemNumber(item.Light, value, additive); return true; } + if (field == "size") { ApplyDynamicItemNumber(item.Size, value, additive); return true; } + if (field == "slots") { ApplyDynamicItemNumber(item.Slots, value, additive); return true; } + if (field == "classes") { ApplyDynamicItemNumber(item.Classes, value, additive); return true; } + if (field == "races") { ApplyDynamicItemNumber(item.Races, value, additive); return true; } + if (field == "deity") { ApplyDynamicItemNumber(item.Deity, value, additive); return true; } + if (field == "itemclass") { ApplyDynamicItemNumber(item.ItemClass, value, additive); return true; } + if (field == "itemtype") { ApplyDynamicItemNumber(item.ItemType, value, additive); return true; } + if (field == "subtype") { ApplyDynamicItemNumber(item.SubType, value, additive); return true; } + if (field == "reqlevel") { ApplyDynamicItemNumber(item.ReqLevel, value, additive); return true; } + if (field == "reclevel") { ApplyDynamicItemNumber(item.RecLevel, value, additive); return true; } + if (field == "recskill") { ApplyDynamicItemNumber(item.RecSkill, value, additive); return true; } + if (field == "maxcharges") { ApplyDynamicItemNumber(item.MaxCharges, value, additive); return true; } + if (field == "stacksize") { ApplyDynamicItemNumber(item.StackSize, value, additive); return true; } + if (field == "stackable") { ApplyDynamicItemNumber(item.Stackable, value, additive); return true; } + if (field == "magic") { ApplyDynamicItemNumber(item.Magic, value, additive); return true; } + if (field == "nodrop") { ApplyDynamicItemNumber(item.NoDrop, value, additive); return true; } + if (field == "norent") { ApplyDynamicItemNumber(item.NoRent, value, additive); return true; } + if (field == "attuneable") { ApplyDynamicItemNumber(item.Attuneable, value, additive); return true; } + if (field == "notransfer") { ApplyDynamicItemNumber(item.NoTransfer, value, additive); return true; } + if (field == "nopet") { ApplyDynamicItemNumber(item.NoPet, value, additive); return true; } + if (field == "questitemflag") { ApplyDynamicItemNumber(item.QuestItemFlag, value, additive); return true; } + if (field == "augtype") { ApplyDynamicItemNumber(item.AugType, value, additive); return true; } + if (field == "augrestrict") { ApplyDynamicItemNumber(item.AugRestrict, value, additive); return true; } + if (field == "augdistiller") { ApplyDynamicItemNumber(item.AugDistiller, value, additive); return true; } + if (field == "bagtype") { ApplyDynamicItemNumber(item.BagType, value, additive); return true; } + if (field == "bagslots") { ApplyDynamicItemNumber(item.BagSlots, value, additive); return true; } + if (field == "bagsize") { ApplyDynamicItemNumber(item.BagSize, value, additive); return true; } + if (field == "bagwr") { ApplyDynamicItemNumber(item.BagWR, value, additive); return true; } + if (field == "procrate") { ApplyDynamicItemNumber(item.ProcRate, value, additive); return true; } + if (field == "casttime") { ApplyDynamicItemNumber(item.CastTime, value, additive); return true; } + if (field == "casttime2") { ApplyDynamicItemNumber(item.CastTime_, value, additive); return true; } + if (field == "recastdelay") { ApplyDynamicItemNumber(item.RecastDelay, value, additive); return true; } + if (field == "recasttype") { ApplyDynamicItemNumber(item.RecastType, value, additive); return true; } + if (field == "charmfileid") { ApplyDynamicItemNumber(item.CharmFileID, value, additive); return true; } + if (field == "scriptfileid") { ApplyDynamicItemNumber(item.ScriptFileID, value, additive); return true; } + if (field == "evolvingitem") { ApplyDynamicItemNumber(item.EvolvingItem, value, additive); return true; } + if (field == "evolvingid") { ApplyDynamicItemNumber(item.EvolvingID, value, additive); return true; } + if (field == "evolvinglevel") { ApplyDynamicItemNumber(item.EvolvingLevel, value, additive); return true; } + if (field == "evolvingmax") { ApplyDynamicItemNumber(item.EvolvingMax, value, additive); return true; } + if (field == "hstr" || field == "heroicstr") { ApplyDynamicItemNumber(item.HeroicStr, value, additive); return true; } + if (field == "hint" || field == "heroicint") { ApplyDynamicItemNumber(item.HeroicInt, value, additive); return true; } + if (field == "hwis" || field == "heroicwis") { ApplyDynamicItemNumber(item.HeroicWis, value, additive); return true; } + if (field == "hagi" || field == "heroicagi") { ApplyDynamicItemNumber(item.HeroicAgi, value, additive); return true; } + if (field == "hdex" || field == "heroicdex") { ApplyDynamicItemNumber(item.HeroicDex, value, additive); return true; } + if (field == "hsta" || field == "heroicsta") { ApplyDynamicItemNumber(item.HeroicSta, value, additive); return true; } + if (field == "hcha" || field == "heroiccha") { ApplyDynamicItemNumber(item.HeroicCha, value, additive); return true; } + if (field == "hmr" || field == "heroicmr") { ApplyDynamicItemNumber(item.HeroicMR, value, additive); return true; } + if (field == "hfr" || field == "heroicfr") { ApplyDynamicItemNumber(item.HeroicFR, value, additive); return true; } + if (field == "hcr" || field == "heroiccr") { ApplyDynamicItemNumber(item.HeroicCR, value, additive); return true; } + if (field == "hdr" || field == "heroicdr") { ApplyDynamicItemNumber(item.HeroicDR, value, additive); return true; } + if (field == "hpr" || field == "heroicpr") { ApplyDynamicItemNumber(item.HeroicPR, value, additive); return true; } + if (field == "hsvcorruption" || field == "heroicsvcorruption" || field == "heroiccorrup") { ApplyDynamicItemNumber(item.HeroicSVCorrup, value, additive); return true; } + if (field == "clickeffect") { ApplyDynamicItemNumber(item.Click.Effect, value, additive); return true; } + if (field == "clicktype") { ApplyDynamicItemNumber(item.Click.Type, value, additive); return true; } + if (field == "clicklevel") { ApplyDynamicItemNumber(item.Click.Level, value, additive); return true; } + if (field == "clicklevel2") { ApplyDynamicItemNumber(item.Click.Level2, value, additive); return true; } + if (field == "proceffect") { ApplyDynamicItemNumber(item.Proc.Effect, value, additive); return true; } + if (field == "proctype") { ApplyDynamicItemNumber(item.Proc.Type, value, additive); return true; } + if (field == "proclevel") { ApplyDynamicItemNumber(item.Proc.Level, value, additive); return true; } + if (field == "proclevel2") { ApplyDynamicItemNumber(item.Proc.Level2, value, additive); return true; } + if (field == "worneffect") { ApplyDynamicItemNumber(item.Worn.Effect, value, additive); return true; } + if (field == "worntype") { ApplyDynamicItemNumber(item.Worn.Type, value, additive); return true; } + if (field == "wornlevel") { ApplyDynamicItemNumber(item.Worn.Level, value, additive); return true; } + if (field == "wornlevel2") { ApplyDynamicItemNumber(item.Worn.Level2, value, additive); return true; } + if (field == "focuseffect") { ApplyDynamicItemNumber(item.Focus.Effect, value, additive); return true; } + if (field == "focustype") { ApplyDynamicItemNumber(item.Focus.Type, value, additive); return true; } + if (field == "focuslevel") { ApplyDynamicItemNumber(item.Focus.Level, value, additive); return true; } + if (field == "focuslevel2") { ApplyDynamicItemNumber(item.Focus.Level2, value, additive); return true; } + if (field == "scrolleffect") { ApplyDynamicItemNumber(item.Scroll.Effect, value, additive); return true; } + if (field == "scrolltype") { ApplyDynamicItemNumber(item.Scroll.Type, value, additive); return true; } + if (field == "scrolllevel") { ApplyDynamicItemNumber(item.Scroll.Level, value, additive); return true; } + if (field == "scrolllevel2") { ApplyDynamicItemNumber(item.Scroll.Level2, value, additive); return true; } + if (field == "bardeffect") { ApplyDynamicItemNumber(item.Bard.Effect, value, additive); return true; } + if (field == "bardeffecttype") { ApplyDynamicItemNumber(item.Bard.Type, value, additive); return true; } + if (field == "bardlevel") { ApplyDynamicItemNumber(item.Bard.Level, value, additive); return true; } + if (field == "bardlevel2") { ApplyDynamicItemNumber(item.Bard.Level2, value, additive); return true; } + + return false; + } + + bool ApplyDynamicItemDataField(EQ::ItemData &item, const std::string &identifier, const std::string &value, const bool additive) + { + const auto field = NormalizeDynamicItemField(identifier); + + if (!additive && ApplyDynamicItemStringField(item, field, value)) { + return true; + } + + return ApplyDynamicItemNumericField(item, field, Strings::ToBigInt(value), additive); + } +} + static inline int32 GetNextItemInstSerialNumber() { // The Bazaar relies on each item a client has up for Trade having a unique @@ -103,6 +381,11 @@ EQ::ItemInstance::ItemInstance(ItemInstTypes use_type) { m_use_type = use_type; } +void EQ::ItemInstance::AssignNewSerialNumber() +{ + m_SerialNumber = GetNextItemInstSerialNumber(); +} + // Make a copy of an EQ::ItemInstance object EQ::ItemInstance::ItemInstance(const ItemInstance& copy) { @@ -154,6 +437,12 @@ EQ::ItemInstance::ItemInstance(const ItemInstance& copy) m_scaledItem = nullptr; } + if (copy.m_dynamicItem) { + m_dynamicItem = new ItemData(*copy.m_dynamicItem); + } else { + m_dynamicItem = nullptr; + } + m_evolving_details = copy.m_evolving_details; m_scaling = copy.m_scaling; m_ornamenticon = copy.m_ornamenticon; @@ -169,6 +458,7 @@ EQ::ItemInstance::~ItemInstance() Clear(); safe_delete(m_item); safe_delete(m_scaledItem); + safe_delete(m_dynamicItem); } // Query item type @@ -789,17 +1079,54 @@ bool EQ::ItemInstance::IsAmmo() const } +bool EQ::ItemInstance::RefreshItemData(const ItemData *item) +{ + if (!m_item || !item || item->ID != m_item->ID) { + return false; + } + + if (std::memcmp(m_item, item, sizeof(ItemData)) == 0) { + return false; + } + + auto *mutable_item = const_cast(m_item); + std::memcpy(mutable_item, item, sizeof(ItemData)); + + m_scaling = m_item->CharmFileID != 0; + if (m_scaling) { + ScaleItem(); + } else { + safe_delete(m_scaledItem); + RebuildDynamicItemData(); + } + + AssignNewSerialNumber(); + + return true; +} + const EQ::ItemData* EQ::ItemInstance::GetItem() const { if (!m_item) return nullptr; + if (m_dynamicItem) + return m_dynamicItem; + if (m_scaledItem) return m_scaledItem; return m_item; } +const EQ::ItemData* EQ::ItemInstance::GetClientItem() const +{ + if (m_dynamicItem) + return m_dynamicItem; + + return m_item; +} + const EQ::ItemData* EQ::ItemInstance::GetUnscaledItem() const { // No operator calls and defaults to nullptr @@ -817,17 +1144,19 @@ std::string EQ::ItemInstance::GetCustomDataString() const { ret_val += "^"; ret_val += iter->second; ++iter; - - if (ret_val.length() > 0) { - ret_val += "^"; - } } return ret_val; } void EQ::ItemInstance::SetCustomDataString(const std::string& str) { - auto components = Strings::Split(str, "^"); + std::vector components; + for (const auto &component : Strings::Split(str, "^")) { + if (!component.empty()) { + components.push_back(component); + } + } + auto value_count = components.size() / 2; for (auto i = 0; i < value_count; i++) { @@ -836,6 +1165,8 @@ void EQ::ItemInstance::SetCustomDataString(const std::string& str) SetCustomData(identifier, value); } + + RebuildDynamicItemData(); } std::string EQ::ItemInstance::GetCustomData(const std::string& identifier) { @@ -848,36 +1179,116 @@ std::string EQ::ItemInstance::GetCustomData(const std::string& identifier) { } void EQ::ItemInstance::SetCustomData(const std::string& identifier, const std::string& value) { - DeleteCustomData(identifier); + const bool is_dynamic = IsDynamicItemDataIdentifier(identifier); + m_custom_data.erase(identifier); m_custom_data[identifier] = value; + + if (is_dynamic) { + RebuildDynamicItemData(); + AssignNewSerialNumber(); + } } void EQ::ItemInstance::SetCustomData(const std::string& identifier, int value) { - DeleteCustomData(identifier); + const bool is_dynamic = IsDynamicItemDataIdentifier(identifier); + m_custom_data.erase(identifier); std::stringstream ss; ss << value; m_custom_data[identifier] = ss.str(); + + if (is_dynamic) { + RebuildDynamicItemData(); + AssignNewSerialNumber(); + } } void EQ::ItemInstance::SetCustomData(const std::string& identifier, float value) { - DeleteCustomData(identifier); + const bool is_dynamic = IsDynamicItemDataIdentifier(identifier); + m_custom_data.erase(identifier); std::stringstream ss; ss << value; m_custom_data[identifier] = ss.str(); + + if (is_dynamic) { + RebuildDynamicItemData(); + AssignNewSerialNumber(); + } } void EQ::ItemInstance::SetCustomData(const std::string& identifier, bool value) { - DeleteCustomData(identifier); + const bool is_dynamic = IsDynamicItemDataIdentifier(identifier); + m_custom_data.erase(identifier); std::stringstream ss; ss << value; m_custom_data[identifier] = ss.str(); + + if (is_dynamic) { + RebuildDynamicItemData(); + AssignNewSerialNumber(); + } } void EQ::ItemInstance::DeleteCustomData(const std::string& identifier) { auto iter = m_custom_data.find(identifier); if (iter != m_custom_data.end()) { + const bool is_dynamic = IsDynamicItemDataIdentifier(identifier); m_custom_data.erase(iter); + + if (is_dynamic) { + RebuildDynamicItemData(); + AssignNewSerialNumber(); + } + } +} + +void EQ::ItemInstance::SetDynamicItemModifier(const std::string &identifier, int value) +{ + SetCustomData(GetDynamicItemKey(DynamicItemModPrefix, identifier), value); +} + +void EQ::ItemInstance::SetDynamicItemData(const std::string &identifier, const std::string& value) +{ + SetCustomData(GetDynamicItemKey(DynamicItemSetPrefix, identifier), value); +} + +void EQ::ItemInstance::SetDynamicItemData(const std::string &identifier, int value) +{ + SetCustomData(GetDynamicItemKey(DynamicItemSetPrefix, identifier), value); +} + +void EQ::ItemInstance::DeleteDynamicItemModifier(const std::string& identifier) +{ + DeleteCustomData(GetDynamicItemKey(DynamicItemModPrefix, identifier)); +} + +void EQ::ItemInstance::DeleteDynamicItemData(const std::string& identifier) +{ + DeleteCustomData(GetDynamicItemKey(DynamicItemSetPrefix, identifier)); +} + +void EQ::ItemInstance::ClearDynamicItemData() +{ + std::vector identifiers; + + for (const auto &entry : m_custom_data) { + if (IsDynamicItemDataIdentifier(entry.first)) { + identifiers.push_back(entry.first); + } } + + for (const auto &identifier : identifiers) { + m_custom_data.erase(identifier); + } + + if (!identifiers.empty()) { + RebuildDynamicItemData(); + AssignNewSerialNumber(); + } +} + +bool EQ::ItemInstance::HasDynamicItemData() const +{ + return m_dynamicItem != nullptr; } // Clone a type of EQ::ItemInstance object @@ -949,6 +1360,40 @@ void EQ::ItemInstance::Initialize(SharedDatabase *db) { } } +void EQ::ItemInstance::RebuildDynamicItemData() +{ + safe_delete(m_dynamicItem); + + if (!m_item) { + return; + } + + const ItemData *source_item = m_scaledItem ? m_scaledItem : m_item; + + auto apply_dynamic_data = [this, source_item](const char *prefix, bool additive) { + for (const auto &entry : m_custom_data) { + const auto key = Strings::ToLower(entry.first); + if (!HasPrefix(key, prefix)) { + continue; + } + + if (!m_dynamicItem) { + m_dynamicItem = new ItemData(*source_item); + } + + ApplyDynamicItemDataField(*m_dynamicItem, entry.first.substr(std::strlen(prefix)), entry.second, additive); + } + }; + + apply_dynamic_data(DynamicItemSetPrefix, false); + apply_dynamic_data(DynamicItemModPrefix, true); + + if (m_dynamicItem) { + m_dynamicItem->CharmFileID = 0; + m_dynamicItem->CharmFile[0] = '\0'; + } +} + void EQ::ItemInstance::ScaleItem() { if (!m_item) return; @@ -1031,6 +1476,7 @@ void EQ::ItemInstance::ScaleItem() { m_scaledItem->Clairvoyance = (uint32)((float)m_item->Clairvoyance*Mult); m_scaledItem->CharmFileID = 0; // this stops the client from trying to scale the item itself. + RebuildDynamicItemData(); } void EQ::ItemInstance::SetTimer(std::string name, uint32 time) { diff --git a/common/item_instance.h b/common/item_instance.h index 96934e35cd..e664a5a51d 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -152,7 +152,9 @@ namespace EQ // Accessors const uint32 GetID() const { return ((m_item) ? m_item->ID : 0); } const uint32 GetItemScriptID() const { return ((m_item) ? m_item->ScriptFileID : 0); } + bool RefreshItemData(const ItemData *item); const ItemData* GetItem() const; + const ItemData* GetClientItem() const; const ItemData* GetUnscaledItem() const; const uint8 GetItemType() const { return m_item ? m_item->ItemType : 255; } // Return 255 so you know there's no valid item @@ -187,6 +189,13 @@ namespace EQ void SetCustomData(const std::string &identifier, float value); void SetCustomData(const std::string &identifier, bool value); void DeleteCustomData(const std::string& identifier); + void SetDynamicItemModifier(const std::string &identifier, int value); + void SetDynamicItemData(const std::string &identifier, const std::string& value); + void SetDynamicItemData(const std::string &identifier, int value); + void DeleteDynamicItemModifier(const std::string& identifier); + void DeleteDynamicItemData(const std::string& identifier); + void ClearDynamicItemData(); + bool HasDynamicItemData() const; // Allows treatment of this object as though it were a pointer to m_item operator bool() const { return (m_item != nullptr); } @@ -220,12 +229,14 @@ namespace EQ void Initialize(SharedDatabase *db = nullptr); void ScaleItem(); + void RebuildDynamicItemData(); std::string Serialize(int16 slot_id) const { InternalSerializedItem_Struct s; s.slot_id = slot_id; s.inst = (const void*)this; std::string ser; ser.assign((char*)&s, sizeof(InternalSerializedItem_Struct)); return ser; } void Serialize(OutBuffer& ob, int16 slot_id) const { InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ob.write((const char*)&isi, sizeof(isi)); } inline int32 GetSerialNumber() const { return m_SerialNumber; } inline void SetSerialNumber(int32 id) { m_SerialNumber = id; } + void AssignNewSerialNumber(); std::map& GetTimers() const { return m_timers; } void SetTimer(std::string name, uint32 time); @@ -357,6 +368,7 @@ namespace EQ uint32 m_exp{0}; int8 m_evolveLvl{0}; ItemData * m_scaledItem{nullptr}; + ItemData * m_dynamicItem{nullptr}; bool m_scaling{false}; uint32 m_ornamenticon{0}; uint32 m_ornamentidfile{0}; diff --git a/common/ruletypes.h b/common/ruletypes.h index 97a235e55a..5ad9fdb9de 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -1158,6 +1158,10 @@ RULE_BOOL(Items, SummonItemAllowInvisibleAugments, false, "Enable this to allow RULE_BOOL(Items, AugmentItemAllowInvisibleAugments, false, "Enable this to allow augments to be put in invisible augment slots by players") RULE_BOOL(Items, AlwaysReturnHandins, true, "Enable this to always return handins to the player") RULE_BOOL(Items, NPCUseRecommendedLevels, false, "Enable to have NPCs scale item stats by recommended levels") +RULE_BOOL(Items, LiveItemLoading, true, "Enable live database item loading for item IDs in the configured live item range.") +RULE_INT(Items, LiveItemMinID, 900000, "Minimum item ID eligible for live database item loading. Set both min and max to 0 to allow all item IDs.") +RULE_INT(Items, LiveItemMaxID, 999999, "Maximum item ID eligible for live database item loading. Set to 0 to allow every item ID above LiveItemMinID.") +RULE_INT(Items, LiveItemPollIntervalSeconds, 1, "Seconds to cache live database item lookups before polling the database again.") RULE_CATEGORY_END() RULE_CATEGORY(Parcel) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 3a39632873..0e21d38d6d 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -44,6 +44,7 @@ #include "fmt/format.h" #include +#include SharedDatabase::SharedDatabase() : Database() @@ -57,6 +58,274 @@ SharedDatabase::SharedDatabase(const char* host, const char* user, const char* p SharedDatabase::~SharedDatabase() = default; +namespace { + EQ::ItemData BuildLiveItemData(SharedDatabase *database, const ItemsRepository::Items &e) + { + EQ::ItemData item {}; + + std::string variable_buffer; + + bool disable_attuneable = RuleB(Items, DisableAttuneable); + bool disable_bard_focus_effects = RuleB(Items, DisableBardFocusEffects); + bool disable_lore = RuleB(Items, DisableLore); + bool disable_no_drop = RuleB(Items, DisableNoDrop); + bool disable_no_pet = RuleB(Items, DisableNoPet); + bool disable_no_rent = RuleB(Items, DisableNoRent); + bool disable_no_transfer = RuleB(Items, DisableNoTransfer); + bool disable_potion_belt = RuleB(Items, DisablePotionBelt); + bool disable_spell_focus_effects = RuleB(Items, DisableSpellFocusEffects); + + if (database && database->GetVariable("disablelore", variable_buffer) && variable_buffer == "1") { + disable_lore = true; + } + + if (database && database->GetVariable("disablenodrop", variable_buffer) && variable_buffer == "1") { + disable_no_drop = true; + } + + if (database && database->GetVariable("disablenorent", variable_buffer) && variable_buffer == "1") { + disable_no_rent = true; + } + + if (database && database->GetVariable("disablenotransfer", variable_buffer) && variable_buffer == "1") { + disable_no_transfer = true; + } + + item.ID = e.id; + item.MinStatus = static_cast(e.minstatus); + + strn0cpy(item.Name, e.Name.c_str(), sizeof(item.Name)); + strn0cpy(item.Lore, e.lore.c_str(), sizeof(item.Lore)); + strn0cpy(item.Comment, e.comment.c_str(), sizeof(item.Comment)); + + item.ArtifactFlag = e.artifactflag; + item.Attuneable = !disable_attuneable && e.attuneable; + item.BenefitFlag = e.benefitflag; + item.FVNoDrop = e.fvnodrop; + item.Magic = e.magic; + item.NoDrop = disable_no_drop ? std::numeric_limits::max() : e.nodrop; + item.NoPet = !disable_no_pet && e.nopet; + item.NoRent = disable_no_rent ? std::numeric_limits::max() : e.norent; + item.NoTransfer = !disable_no_transfer && e.notransfer; + item.PendingLoreFlag = e.pendingloreflag; + item.QuestItemFlag = e.questitemflag; + item.Stackable = e.stackable; + item.Tradeskills = e.tradeskills; + item.SummonedFlag = e.summonedflag; + + item.LoreGroup = disable_lore ? 0 : e.loregroup; + item.LoreFlag = !disable_lore && item.LoreGroup != 0; + + item.AugType = e.augtype; + item.ItemType = static_cast(e.itemtype); + item.SubType = e.subtype; + + item.ExpendableArrow = e.expendablearrow; + item.Light = EQ::Clamp(e.light, -128, 127); + item.MaxCharges = e.maxcharges; + item.Size = static_cast(e.size); + item.StackSize = e.stacksize; + item.Weight = e.weight; + + item.PotionBelt = !disable_potion_belt && e.potionbelt; + item.PotionBeltSlots = disable_potion_belt ? 0 : static_cast(e.potionbeltslots); + + item.Favor = e.favor; + item.GuildFavor = e.guildfavor; + item.Price = e.price; + item.SellRate = e.sellrate; + + item.Color = e.color; + item.EliteMaterial = e.elitematerial; + item.HerosForgeModel = e.herosforgemodel; + item.Icon = e.icon; + strn0cpy(item.IDFile, e.idfile.c_str(), sizeof(item.IDFile)); + item.Material = e.material; + + item.CR = EQ::Clamp(e.cr, -128, 127); + item.DR = EQ::Clamp(e.dr, -128, 127); + item.FR = EQ::Clamp(e.fr, -128, 127); + item.MR = EQ::Clamp(e.mr, -128, 127); + item.PR = EQ::Clamp(e.pr, -128, 127); + item.SVCorruption = EQ::Clamp(e.svcorruption, -128, 127); + + item.HeroicCR = e.heroic_cr; + item.HeroicDR = e.heroic_dr; + item.HeroicFR = e.heroic_fr; + item.HeroicMR = e.heroic_mr; + item.HeroicPR = e.heroic_pr; + item.HeroicSVCorrup = e.heroic_svcorrup; + + item.AAgi = EQ::Clamp(e.aagi, -128, 127); + item.ACha = EQ::Clamp(e.acha, -128, 127); + item.ADex = EQ::Clamp(e.adex, -128, 127); + item.AInt = EQ::Clamp(e.aint, -128, 127); + item.ASta = EQ::Clamp(e.asta, -128, 127); + item.AStr = EQ::Clamp(e.astr, -128, 127); + item.AWis = EQ::Clamp(e.awis, -128, 127); + + item.HeroicAgi = e.heroic_agi; + item.HeroicCha = e.heroic_cha; + item.HeroicDex = e.heroic_dex; + item.HeroicInt = e.heroic_int; + item.HeroicSta = e.heroic_sta; + item.HeroicStr = e.heroic_str; + item.HeroicWis = e.heroic_wis; + + item.HP = e.hp; + item.Regen = e.regen; + item.Mana = e.mana; + item.ManaRegen = e.manaregen; + item.Endur = e.endur; + item.EnduranceRegen = e.enduranceregen; + + item.BaneDmgAmt = e.banedmgamt; + item.BaneDmgBody = e.banedmgbody; + item.BaneDmgRace = e.banedmgrace; + item.BaneDmgRaceAmt = e.banedmgraceamt; + + item.ElemDmgType = static_cast(e.elemdmgtype); + item.ElemDmgAmt = static_cast(e.elemdmgamt); + + item.BackstabDmg = e.backstabdmg; + item.Damage = e.damage; + item.Delay = static_cast(e.delay); + item.Range = static_cast(e.range_); + + item.AC = e.ac; + item.Accuracy = EQ::Clamp(e.accuracy, -128, 127); + item.Attack = e.attack; + item.Avoidance = EQ::Clamp(e.avoidance, -128, 127); + item.Clairvoyance = e.clairvoyance; + item.CombatEffects = Strings::IsNumber(e.combateffects) ? static_cast(EQ::Clamp(Strings::ToInt(e.combateffects), -128, 127)) : 0; + item.DamageShield = e.damageshield; + item.DotShielding = e.dotshielding; + item.DSMitigation = e.dsmitigation; + item.Haste = e.haste; + item.HealAmt = e.healamt; + item.Purity = e.purity; + item.Shielding = EQ::Clamp(e.shielding, -128, 127); + item.SpellDmg = e.spelldmg; + item.SpellShield = EQ::Clamp(e.spellshield, -128, 127); + item.StrikeThrough = EQ::Clamp(e.strikethrough, -128, 127); + item.StunResist = EQ::Clamp(e.stunresist, -128, 127); + + item.AugRestrict = e.augrestrict; + item.Classes = e.classes; + item.Deity = e.deity; + item.ItemClass = static_cast(e.itemclass); + item.Races = e.races; + item.RecLevel = static_cast(e.reclevel); + item.RecSkill = static_cast(e.recskill); + item.ReqLevel = static_cast(e.reqlevel); + item.Slots = e.slots; + + item.SkillModValue = e.skillmodvalue; + item.SkillModMax = e.skillmodmax; + item.SkillModType = e.skillmodtype; + + item.ExtraDmgSkill = e.extradmgskill; + item.ExtraDmgAmt = e.extradmgamt; + + item.BardType = e.bardtype; + item.BardValue = e.bardvalue; + + item.FactionAmt1 = e.factionamt1; + item.FactionMod1 = e.factionmod1; + item.FactionAmt2 = e.factionamt2; + item.FactionMod2 = e.factionmod2; + item.FactionAmt3 = e.factionamt3; + item.FactionMod3 = e.factionmod3; + item.FactionAmt4 = e.factionamt4; + item.FactionMod4 = e.factionmod4; + + item.AugDistiller = e.augdistiller; + + item.AugSlotType[0] = static_cast(e.augslot1type); + item.AugSlotVisible[0] = static_cast(e.augslot1visible); + item.AugSlotType[1] = static_cast(e.augslot2type); + item.AugSlotVisible[1] = static_cast(e.augslot2visible); + item.AugSlotType[2] = static_cast(e.augslot3type); + item.AugSlotVisible[2] = static_cast(e.augslot3visible); + item.AugSlotType[3] = static_cast(e.augslot4type); + item.AugSlotVisible[3] = static_cast(e.augslot4visible); + item.AugSlotType[4] = static_cast(e.augslot5type); + item.AugSlotVisible[4] = static_cast(e.augslot5visible); + item.AugSlotType[5] = static_cast(e.augslot6type); + item.AugSlotVisible[5] = static_cast(e.augslot6visible); + + for (uint8 i = EQ::invaug::SOCKET_BEGIN; i <= EQ::invaug::SOCKET_END; i++) { + item.AugSlotUnk2[i] = 0; + } + + item.LDoNTheme = e.ldontheme; + item.LDoNPrice = e.ldonprice; + item.LDoNSellBackRate = e.ldonsellbackrate; + item.LDoNSold = e.ldonsold; + item.PointType = e.pointtype; + + item.BagSize = static_cast(e.bagsize); + item.BagSlots = EQ::Clamp(e.bagslots, 0, static_cast(EQ::invbag::SLOT_COUNT)); + item.BagType = static_cast(e.bagtype); + item.BagWR = EQ::Clamp(e.bagwr, 0, 100); + + item.Bard.Effect = disable_bard_focus_effects ? 0 : e.bardeffect; + item.Bard.Type = disable_bard_focus_effects ? 0 : static_cast(e.bardeffecttype); + item.Bard.Level = disable_bard_focus_effects ? 0 : static_cast(e.bardlevel); + item.Bard.Level2 = disable_bard_focus_effects ? 0 : static_cast(e.bardlevel2); + + item.Book = static_cast(e.book); + item.BookType = e.booktype; + + item.CastTime = e.casttime; + item.CastTime_ = e.casttime_; + item.Click.Effect = e.clickeffect; + item.Click.Type = static_cast(e.clicktype); + item.Click.Level = static_cast(e.clicklevel); + item.Click.Level2 = static_cast(e.clicklevel2); + strn0cpy(item.ClickName, e.clickname.c_str(), sizeof(item.ClickName)); + item.RecastDelay = e.recastdelay; + item.RecastType = e.recasttype; + + item.Focus.Effect = disable_spell_focus_effects ? 0 : e.focuseffect; + item.Focus.Type = disable_spell_focus_effects ? 0 : static_cast(e.focustype); + item.Focus.Level = disable_spell_focus_effects ? 0 : static_cast(e.focuslevel); + item.Focus.Level2 = disable_spell_focus_effects ? 0 : static_cast(e.focuslevel2); + strn0cpy(item.FocusName, disable_spell_focus_effects ? "" : e.focusname.c_str(), sizeof(item.FocusName)); + + item.Proc.Effect = e.proceffect; + item.Proc.Type = static_cast(e.proctype); + item.Proc.Level = static_cast(e.proclevel); + item.Proc.Level2 = static_cast(e.proclevel2); + strn0cpy(item.ProcName, e.procname.c_str(), sizeof(item.ProcName)); + item.ProcRate = e.procrate; + + item.Scroll.Effect = e.scrolleffect; + item.Scroll.Type = static_cast(e.scrolltype); + item.Scroll.Level = static_cast(e.scrolllevel); + item.Scroll.Level2 = static_cast(e.scrolllevel2); + strn0cpy(item.ScrollName, e.scrollname.c_str(), sizeof(item.ScrollName)); + + item.Worn.Effect = e.worneffect; + item.Worn.Type = static_cast(e.worntype); + item.Worn.Level = static_cast(e.wornlevel); + item.Worn.Level2 = static_cast(e.wornlevel2); + strn0cpy(item.WornName, e.wornname.c_str(), sizeof(item.WornName)); + + item.EvolvingID = e.evoid; + item.EvolvingItem = static_cast(e.evoitem); + item.EvolvingLevel = static_cast(e.evolvinglevel); + item.EvolvingMax = static_cast(e.evomax); + + item.CharmFileID = Strings::IsNumber(e.charmfileid) ? Strings::ToUnsignedInt(e.charmfileid) : 0; + strn0cpy(item.CharmFile, e.charmfile.c_str(), sizeof(item.CharmFile)); + strn0cpy(item.Filename, e.filename.c_str(), sizeof(item.Filename)); + item.ScriptFileID = e.scriptfileid; + + return item; + } +} + bool SharedDatabase::SetHideMe(uint32 account_id, uint8 hideme) { auto a = AccountRepository::FindOne(*this, account_id); @@ -910,6 +1179,8 @@ bool SharedDatabase::LoadItems(const std::string &prefix) { items_hash = std::make_unique>(static_cast(items_mmf->Get()), items_mmf->Size()); mutex.Unlock(); + m_shared_items_load_time = std::time(nullptr); + ClearLiveItemCache(); LogInfo("Loaded [{}] items via shared memory", Strings::Commify(m_shared_items_count)); } catch(std::exception& ex) { LogError("Error Loading Items: {}", ex.what()); @@ -1249,6 +1520,9 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ break; } } + + m_shared_items_load_time = std::time(nullptr); + ClearLiveItemCache(); } const EQ::ItemData *SharedDatabase::GetItem(uint32 id) const @@ -1257,15 +1531,135 @@ const EQ::ItemData *SharedDatabase::GetItem(uint32 id) const return nullptr; } - if (!items_hash || id > items_hash->max_key()) { + const EQ::ItemData *shared_item = nullptr; + + if (items_hash && id <= items_hash->max_key() && items_hash->exists(id)) { + shared_item = &(items_hash->at(id)); + } + + if (const auto *live_item = GetLiveItem(id, shared_item != nullptr)) { + return live_item; + } + + return shared_item; +} + +const EQ::ItemData *SharedDatabase::GetLiveItem(uint32 id, bool has_shared_item) const +{ + if (!IsLiveItemID(id)) { return nullptr; } - if (items_hash->exists(id)) { - return &(items_hash->at(id)); + const auto now = std::time(nullptr); + const auto poll_interval = static_cast(std::max(0, RuleI(Items, LiveItemPollIntervalSeconds))); + + { + std::lock_guard guard(live_items_cache_mutex); + const auto cached = live_items_cache.find(id); + if ( + cached != live_items_cache.end() && + cached->second.last_checked + poll_interval > now + ) { + return cached->second.exists ? &cached->second.item : nullptr; + } } - return nullptr; + auto *database = const_cast(this); + const auto item_record = ItemsRepository::FindOne(*database, id); + + LiveItemCacheEntry cache_entry {}; + cache_entry.updated = item_record.updated; + cache_entry.last_checked = now; + + if (item_record.id <= 0) { + LogDebug("Live item [{}] was not found in the database", id); + + std::lock_guard guard(live_items_cache_mutex); + live_items_cache[id] = cache_entry; + return nullptr; + } + + const bool use_live_item = ( + !has_shared_item || + item_record.updated == 0 || + item_record.updated >= m_shared_items_load_time + ); + + if (!use_live_item) { + LogDebug( + "Live item [{}] is using shared-memory data; item updated [{}], shared items loaded [{}]", + id, + item_record.updated, + m_shared_items_load_time + ); + + std::lock_guard guard(live_items_cache_mutex); + live_items_cache[id] = cache_entry; + return nullptr; + } + + cache_entry.item = BuildLiveItemData(database, item_record); + cache_entry.exists = true; + + LogDebug( + "Live item [{}] refreshed from the database as [{}] with updated timestamp [{}]", + id, + item_record.Name, + item_record.updated + ); + + std::lock_guard guard(live_items_cache_mutex); + auto &cached = live_items_cache[id]; + cached = cache_entry; + return &cached.item; +} + +bool SharedDatabase::IsLiveItemID(uint32 id) const +{ + if (!id || !RuleB(Items, LiveItemLoading)) { + return false; + } + + auto minimum = static_cast(std::max(0, RuleI(Items, LiveItemMinID))); + auto maximum = static_cast(std::max(0, RuleI(Items, LiveItemMaxID))); + + if (minimum == 0 && maximum == 0) { + return true; + } + + if (maximum == 0) { + return id >= minimum; + } + + if (minimum > maximum) { + std::swap(minimum, maximum); + } + + return id >= minimum && id <= maximum; +} + +bool SharedDatabase::GetLiveItemCacheEntry(uint32 id, LiveItemCacheEntry &entry) const +{ + std::lock_guard guard(live_items_cache_mutex); + const auto cached = live_items_cache.find(id); + if (cached == live_items_cache.end()) { + return false; + } + + entry = cached->second; + return true; +} + +void SharedDatabase::ClearLiveItemCache() +{ + std::lock_guard guard(live_items_cache_mutex); + live_items_cache.clear(); +} + +bool SharedDatabase::ClearLiveItemCache(uint32 id) +{ + std::lock_guard guard(live_items_cache_mutex); + return live_items_cache.erase(id) != 0; } const EQ::ItemData* SharedDatabase::IterateItems(uint32* id) const diff --git a/common/shareddb.h b/common/shareddb.h index 76f8c63a56..a19422c57e 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -20,6 +20,7 @@ #include "common/database.h" #include "common/fixed_memory_hash_set.h" #include "common/fixed_memory_variable_hash_set.h" +#include "common/item_data.h" #include "common/repositories/character_evolving_items_repository.h" #include "common/repositories/command_subsettings_repository.h" #include "common/repositories/items_evolving_details_repository.h" @@ -27,9 +28,11 @@ #include "common/skills.h" #include "common/spdat.h" +#include #include #include #include +#include class EvolveInfo; struct InspectMessage_Struct; @@ -61,6 +64,13 @@ struct Book_Struct class SharedDatabase : public Database { public: + struct LiveItemCacheEntry { + EQ::ItemData item {}; + time_t updated {}; + time_t last_checked {}; + bool exists {}; + }; + SharedDatabase(); SharedDatabase(const char *host, const char *user, const char *passwd, const char *database, uint32 port); virtual ~SharedDatabase(); @@ -158,6 +168,11 @@ class SharedDatabase : public Database { bool LoadItems(const std::string &prefix); const EQ::ItemData *IterateItems(uint32 *id) const; const EQ::ItemData *GetItem(uint32 id) const; + const EQ::ItemData *GetLiveItem(uint32 id, bool has_shared_item) const; + bool IsLiveItemID(uint32 id) const; + bool GetLiveItemCacheEntry(uint32 id, LiveItemCacheEntry &entry) const; + void ClearLiveItemCache(); + bool ClearLiveItemCache(uint32 id); const EvolveInfo *GetEvolveInfo(uint32 loregroup); uint32 GetSharedItemsCount() { return m_shared_items_count; } uint32 GetItemsCount(); @@ -186,6 +201,8 @@ class SharedDatabase : public Database { std::unique_ptr skill_caps_mmf; std::unique_ptr items_mmf; std::unique_ptr> items_hash; + mutable std::mutex live_items_cache_mutex; + mutable std::map live_items_cache; std::unique_ptr faction_mmf; std::unique_ptr> faction_hash; std::unique_ptr faction_associations_mmf; @@ -198,4 +215,5 @@ class SharedDatabase : public Database { protected: uint32 m_shared_items_count = 0; uint32 m_shared_spells_count = 0; + time_t m_shared_items_load_time = 0; }; diff --git a/docs/live-items.md b/docs/live-items.md new file mode 100644 index 0000000000..2a4dd46b62 --- /dev/null +++ b/docs/live-items.md @@ -0,0 +1,99 @@ +# Live Items + +Live item support has two layers: + +- Database-backed live item IDs: item IDs in the configured range are resolved from the `items` table at runtime, so new rows and changed rows can be used without `#hotfix`, `#reload`, or a restart. +- Per-instance dynamic item data: item instances can carry custom stat/effect/name overrides in their custom data, so a single player's copy can evolve independently from the base DB row. + +## Rules + +Defaults are aimed at a test server and reserve `900000-999999` for live items: + +```sql +REPLACE INTO rule_values (ruleset_id, rule_name, rule_value, notes) +VALUES + (1, 'Items:LiveItemLoading', 'true', 'Enable live DB item fallback'), + (1, 'Items:LiveItemMinID', '900000', 'First live item ID'), + (1, 'Items:LiveItemMaxID', '999999', 'Last live item ID'), + (1, 'Items:LiveItemPollIntervalSeconds', '1', 'Live item DB poll interval'); +``` + +Set `Items:LiveItemMinID` and `Items:LiveItemMaxID` to `0` to allow live DB checks for every item ID. Keeping a reserved high range is strongly preferred because normal item IDs stay on the shared-memory path. + +## GM Test Commands + +```text +#liveitem +#liveitem status 900001 +#liveitem clone 900001 1001 +#liveitem summon 900001 +#liveitem bump 900001 10 10 1 +#liveitem clear 900001 +#liveitem clear all +``` + +`clone` creates or replaces a DB row by copying an existing source item into the live range, then summons it. `bump` edits HP, mana, and damage and updates the row timestamp, but intentionally does not clear the cache; wait up to `Items:LiveItemPollIntervalSeconds` and the held item should refresh through the automatic path. + +## Cursor Item Editing + +GMs can hold any item on the cursor and run: + +```text +#itemedit +#itemedit add hp 25 +#itemedit set name Vexen's Slightly Unsafe Sword +#itemedit proc 1234 150 1 +#itemedit clear hp +#itemedit clear all +``` + +`#itemedit` writes per-instance dynamic item data, not the base `items` row. The menu prints current and base values plus clickable +/- links for numeric fields, then saves and refreshes the cursor item after each edit. + +## Test Checklist + +1. Start world and zone normally. +2. Log in a GM character. +3. Run `#liveitem clone 900001 `. +4. Inspect the summoned item and confirm the generated name and stat bumps. +5. Run `#liveitem bump 900001 25 25 2`. +6. Wait one poll interval, then inspect the held item again. Equipped items should also send a charm update and recalculate bonuses when the live refresh sees changed data. +7. Hold the item on your cursor and run `#itemedit add hp 25`, then inspect the cursor item. +8. Create a brand-new row externally in the `900000-999999` range, then run `#liveitem summon ` without restarting. + +## Lua Dynamic Item Example + +This creates a unique player copy from an existing base item without needing a new DB row: + +```lua +function event_say(e) + if e.message:findi("forge") then + local inst = ItemInst(900001, 1) + inst:SetDynamicItemData("name", e.other:GetCleanName() .. "'s Forged Blade") + inst:SetDynamicItemModifier("hp", 50) + inst:SetDynamicItemModifier("mana", 25) + inst:SetDynamicItemModifier("agi", 7) + inst:SetDynamicItemData("haste", 18) + inst:SetDynamicItemData("proc_effect", 1234) + inst:SetDynamicItemData("proc_type", 0) + inst:SetDynamicItemData("proc_level", 1) + inst:SetDynamicItemData("proc_level2", 255) + inst:SetDynamicItemData("proc_rate", 150) + e.other:PushItemOnCursor(inst) + end +end +``` + +On a level-up or quest milestone, mutate the held instance and send a live item update: + +```lua +function event_level_up(e) + local inst = e.other:GetInventory():GetItem(13) -- primary slot + if inst and inst:GetID() == 900001 then + inst:SetDynamicItemModifier("hp", e.other:GetLevel() * 10) + inst:SetDynamicItemModifier("mana", e.other:GetLevel() * 5) + e.other:SendItemScale(inst) + end +end +``` + +Dynamic fields are stored in item custom data, so they persist with that specific item instance. Use absolute setters for exact values and modifiers for additive stats. diff --git a/features/README.md b/features/README.md index cde4b62121..acd235aef1 100644 --- a/features/README.md +++ b/features/README.md @@ -1,6 +1,6 @@ # Feature Packs -This folder is the portability layer for custom systems that another EQEmu server operator might want to grab one at a time. +This folder is the portability layer for custom systems that another EQEmu server operator might want to grab one at a time or as a combined bundle. These are not runtime plugins. Each feature pack documents the source files, database objects, client assets, and hook points needed to lift one system into another source checkout with the smallest practical blast radius. @@ -9,12 +9,14 @@ These are not runtime plugins. Each feature pack documents the source files, dat - `draft`: boundary has been mapped, but the pack is not a clean generated patch yet. - `portable`: has a tested patch or install sequence that can be applied to a fresh compatible checkout. - `shared-runtime`: includes code that is still bundled with another feature or shared client runtime. +- `proved-build`: the feature has built on a clean EQEmu baseline branch. ## Current Packs | Feature | Status | Notes | | --- | --- | --- | -| `autoloot` | `draft`, `shared-runtime` | Server-side AutoLoot with the native EQ AutoLoot window. Client DLL code is still partly bundled with other native windows. | +| `autoloot` | `draft`, `shared-runtime`, `proved-build` | Server-side AutoLoot with the native EQ AutoLoot window. Client DLL code is still partly bundled with other native windows. | +| `live-items` | `draft`, `shared-runtime`, `proved-build` | Live DB item loading, dynamic item data, item editing, and Item Forge input. Native DLL code is still shared runtime. | ## Packaging Rules diff --git a/features/live-items/MANIFEST.md b/features/live-items/MANIFEST.md new file mode 100644 index 0000000000..910910951d --- /dev/null +++ b/features/live-items/MANIFEST.md @@ -0,0 +1,65 @@ +# Live Items Manifest + +This manifest lists the files and hook points that make up the standalone Live Items feature. + +## Added Server Files + +- `zone/gm_commands/itemedit.cpp` +- `zone/gm_commands/liveitem.cpp` +- `docs/live-items.md` + +## Existing Server Files To Patch + +| File | Purpose | +| --- | --- | +| `common/item_instance.cpp` | Add dynamic item data storage and application. | +| `common/item_instance.h` | Declare dynamic item APIs. | +| `common/shareddb.cpp` | Add live item lookup, cache, and DB fallback. | +| `common/shareddb.h` | Declare live item cache APIs. | +| `common/ruletypes.h` | Add Live Item range and polling rules. | +| `world/world_boot.cpp` | Preserve shared item count before live fallback is enabled. | +| `zone/CMakeLists.txt` | Build `itemedit.cpp` and `liveitem.cpp`. | +| `zone/command.cpp` | Register `#liveitem`, `#itemedit`, and `#itemforge`. | +| `zone/command.h` | Declare Live Item command handlers. | +| `zone/client.cpp` | Refresh live items during relevant client flows. | +| `zone/client.h` | Declare live item refresh helpers. | +| `zone/inventory.cpp` | Refresh held/inventory live item trees. | +| `zone/lua_iteminst.cpp` | Expose dynamic item helpers to Lua. | +| `zone/lua_iteminst.h` | Declare Lua dynamic item bindings. | +| `zone/perl_client.cpp` | Expose client refresh helper to Perl. | +| `zone/perl_questitem.cpp` | Expose dynamic item helpers to Perl quest items. | +| `tests/CMakeLists.txt` | Add dynamic item tests. | +| `tests/dynamic_item_test.h` | Test dynamic item behavior. | +| `tests/main.cpp` | Include dynamic item tests. | + +## Database Objects + +No custom tables are required. Live items use existing `items`, `rule_values`, and `data_buckets` tables. + +Optional rules SQL lives in: + +- `features/live-items/sql/001_live_items_rules.sql` + +## Native Client Assets + +| File | Purpose | +| --- | --- | +| `client_files/native_autoloot/ui/EQUI_NativeItemForgeWnd.xml` | Native SIDL window layout for Item Forge input. | +| `client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h` | Not included in this proof branch. The current implementation is still shared runtime code and needs a `native-client-base` split. | + +## Commands + +- `#liveitem status [item_id]` +- `#liveitem clear [item_id|all]` +- `#liveitem clone [new_item_id] [source_item_id]` +- `#liveitem summon [item_id] [charges]` +- `#liveitem bump [item_id] [hp] [mana] [damage]` +- `#itemedit` +- `#itemforge dialog` +- `#itemforge craft ...` + +## Native Transport + +- `LIVEITEM|ui|open|...` + +The server owns item creation and validation. The native window is only an input surface. diff --git a/features/live-items/README.md b/features/live-items/README.md new file mode 100644 index 0000000000..9976e0070c --- /dev/null +++ b/features/live-items/README.md @@ -0,0 +1,48 @@ +# Live Items Feature Pack + +Status: `draft`, `shared-runtime`, `proved-build` + +This pack describes the Live Items system: live database-backed item lookup, per-instance dynamic item data, admin item editing, and the native Item Forge input window. + +## What This Feature Owns + +- Live item ID range rules and cache polling. +- DB-backed item lookup fallback through `SharedDatabase`. +- Per-instance dynamic item modifiers stored on `ItemInstance`. +- Item serialization that sends dynamic item data to supported clients. +- Held item refresh hooks so live DB edits can update in player inventory. +- `#liveitem`, `#itemedit`, and `#itemforge` commands. +- Native Item Forge UI transport using `LIVEITEM|...` lines. + +## What This Feature Does Not Require + +- AutoLoot. +- Live Spells. +- Achievements. +- MacroQuest, Lua, ImGui, or overlay UI code. + +## Dependencies + +- EQEmu source rebuild. +- `rule_values` rows if the operator wants to override the default live item range. +- The native client DLL host if the operator wants the in-client Item Forge window. + +## Install Outline + +1. Apply the source files and hook patches listed in `MANIFEST.md`. +2. Optionally apply `sql/001_live_items_rules.sql` to make the live item range explicit in the database. +3. Rebuild `zone` and `world`. +4. Deploy `EQUI_NativeItemForgeWnd.xml` and include it from the target client's `EQUI.xml`. +5. Use `#liveitem status`, then try `#itemforge dialog`. + +## Smoke Test + +1. Run `#liveitem status 900001`. +2. Run `#liveitem clone 900001 `. +3. Run `#liveitem summon 900001`. +4. Run `#liveitem bump 900001 25 25 2` and confirm the held item refreshes after the poll interval. +5. Open `#itemforge dialog`, craft an item, and confirm the generated item is in the configured live item range. + +## Current Shared-Runtime Caveat + +This branch includes the native Item Forge XML only. The C++ DLL implementation is still in the lab branch's shared native-client runtime header and should be split into `native-client-base` plus feature-specific native window code. diff --git a/features/live-items/sql/001_live_items_rules.sql b/features/live-items/sql/001_live_items_rules.sql new file mode 100644 index 0000000000..ea28cab1b4 --- /dev/null +++ b/features/live-items/sql/001_live_items_rules.sql @@ -0,0 +1,12 @@ +-- Optional explicit Live Items rule values. +-- The source feature also provides defaults in common/ruletypes.h. + +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) +VALUES +(1, 'Items:LiveItemLoading', 'true', 'Enable live DB item fallback'), +(1, 'Items:LiveItemMinID', '900000', 'First live item ID'), +(1, 'Items:LiveItemMaxID', '999999', 'Last live item ID'), +(1, 'Items:LiveItemPollIntervalSeconds', '1', 'Live item DB poll interval') +ON DUPLICATE KEY UPDATE +`rule_value` = VALUES(`rule_value`), +`notes` = VALUES(`notes`); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 346128d607..52facc8d7f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,6 +9,7 @@ set(tests_sources set(tests_headers atobool_test.h data_verification_test.h + dynamic_item_test.h fixed_memory_test.h fixed_memory_variable_test.h hextoi_32_64_test.h diff --git a/tests/dynamic_item_test.h b/tests/dynamic_item_test.h new file mode 100644 index 0000000000..49a4806494 --- /dev/null +++ b/tests/dynamic_item_test.h @@ -0,0 +1,176 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ +#pragma once + +#include "common/item_instance.h" +#include "common/strings.h" +#include "cppunit/cpptest.h" + +class DynamicItemTest : public Test::Suite { + typedef void(DynamicItemTest::*TestFunction)(void); +public: + DynamicItemTest() { + TEST_ADD(DynamicItemTest::DynamicModifiersApplyToResolvedItem); + TEST_ADD(DynamicItemTest::DynamicDataPersistsThroughCustomData); + TEST_ADD(DynamicItemTest::DynamicDataCopiesAndClears); + TEST_ADD(DynamicItemTest::DynamicDataChangesSerialNumber); + TEST_ADD(DynamicItemTest::DynamicDataRebuildsAfterBaseRefresh); + } + +private: + EQ::ItemData BuildSword() const + { + EQ::ItemData item{}; + item.ItemClass = EQ::item::ItemClassCommon; + item.ItemType = EQ::item::ItemType1HSlash; + item.ID = 900001; + item.Damage = 10; + item.Delay = 20; + item.AStr = 2; + item.HP = 10; + item.Mana = 0; + item.Haste = 0; + item.MaxCharges = 1; + item.NoDrop = 255; + item.NoRent = 255; + strn0cpy(item.Name, "Training Sword", sizeof(item.Name)); + strn0cpy(item.Lore, "A plain blade", sizeof(item.Lore)); + strn0cpy(item.IDFile, "IT10", sizeof(item.IDFile)); + return item; + } + + void DynamicModifiersApplyToResolvedItem() + { + auto base = BuildSword(); + EQ::ItemInstance inst(&base, 1); + + TEST_ASSERT(!inst.HasDynamicItemData()); + + inst.SetDynamicItemModifier("hp", 50); + inst.SetDynamicItemModifier("mana", 35); + inst.SetDynamicItemModifier("agi", 7); + inst.SetDynamicItemData("haste", 18); + inst.SetDynamicItemData("proc_effect", 1234); + inst.SetDynamicItemData("proc_type", EQ::item::ItemEffectCombatProc); + inst.SetDynamicItemData("proc_level", 1); + inst.SetDynamicItemData("proc_level2", 255); + inst.SetDynamicItemData("proc_rate", 150); + inst.SetDynamicItemData("proc_name", "Spark"); + inst.SetDynamicItemData("name", "Training Sword of Sparks"); + + const auto *resolved = inst.GetItem(); + TEST_ASSERT(inst.HasDynamicItemData()); + TEST_ASSERT(resolved != nullptr); + TEST_ASSERT_EQUALS(resolved->HP, 60); + TEST_ASSERT_EQUALS(resolved->Mana, 35); + TEST_ASSERT_EQUALS(static_cast(resolved->AAgi), 7); + TEST_ASSERT_EQUALS(resolved->Haste, 18); + TEST_ASSERT_EQUALS(resolved->Proc.Effect, 1234); + TEST_ASSERT_EQUALS(static_cast(resolved->Proc.Type), static_cast(EQ::item::ItemEffectCombatProc)); + TEST_ASSERT_EQUALS(static_cast(resolved->Proc.Level), 1); + TEST_ASSERT_EQUALS(static_cast(resolved->Proc.Level2), 255); + TEST_ASSERT_EQUALS(resolved->ProcRate, 150); + TEST_ASSERT(std::string(resolved->ProcName) == "Spark"); + TEST_ASSERT(std::string(resolved->Name) == "Training Sword of Sparks"); + + TEST_ASSERT_EQUALS(inst.GetUnscaledItem()->HP, 10); + TEST_ASSERT_EQUALS(inst.GetUnscaledItem()->Mana, 0); + TEST_ASSERT(inst.GetClientItem() == resolved); + } + + void DynamicDataPersistsThroughCustomData() + { + auto base = BuildSword(); + EQ::ItemInstance inst(&base, 1); + inst.SetDynamicItemModifier("hp", 75); + inst.SetDynamicItemData("haste", 22); + inst.SetDynamicItemData("worn_effect", 4321); + + EQ::ItemInstance loaded(&base, 1); + loaded.SetCustomDataString(inst.GetCustomDataString()); + + TEST_ASSERT(loaded.HasDynamicItemData()); + TEST_ASSERT_EQUALS(loaded.GetItem()->HP, 85); + TEST_ASSERT_EQUALS(loaded.GetItem()->Haste, 22); + TEST_ASSERT_EQUALS(loaded.GetItem()->Worn.Effect, 4321); + TEST_ASSERT_EQUALS(loaded.GetUnscaledItem()->HP, 10); + } + + void DynamicDataCopiesAndClears() + { + auto base = BuildSword(); + EQ::ItemInstance inst(&base, 1); + inst.SetDynamicItemModifier("hp", 20); + inst.SetDynamicItemData("damage", 14); + + EQ::ItemInstance copy(inst); + TEST_ASSERT(copy.HasDynamicItemData()); + TEST_ASSERT_EQUALS(copy.GetItem()->HP, 30); + TEST_ASSERT_EQUALS(copy.GetItem()->Damage, static_cast(14)); + + copy.ClearDynamicItemData(); + TEST_ASSERT(!copy.HasDynamicItemData()); + TEST_ASSERT_EQUALS(copy.GetItem()->HP, 10); + TEST_ASSERT_EQUALS(copy.GetItem()->Damage, static_cast(10)); + } + + void DynamicDataChangesSerialNumber() + { + auto base = BuildSword(); + EQ::ItemInstance inst(&base, 1); + + const auto initial_serial = inst.GetSerialNumber(); + inst.SetCustomData("note", "no client item change"); + TEST_ASSERT_EQUALS(initial_serial, inst.GetSerialNumber()); + + inst.SetDynamicItemModifier("hp", 20); + const auto modified_serial = inst.GetSerialNumber(); + TEST_ASSERT(initial_serial != modified_serial); + + inst.DeleteDynamicItemModifier("hp"); + TEST_ASSERT(modified_serial != inst.GetSerialNumber()); + } + + void DynamicDataRebuildsAfterBaseRefresh() + { + auto base = BuildSword(); + EQ::ItemInstance inst(&base, 1); + inst.SetDynamicItemModifier("hp", 50); + inst.SetDynamicItemData("damage", 14); + const auto serial_before_refresh = inst.GetSerialNumber(); + + base.HP = 40; + base.Mana = 25; + base.Damage = 12; + strn0cpy(base.Name, "Training Sword Mk II", sizeof(base.Name)); + + TEST_ASSERT(inst.RefreshItemData(&base)); + TEST_ASSERT_EQUALS(inst.GetUnscaledItem()->HP, 40); + TEST_ASSERT_EQUALS(inst.GetUnscaledItem()->Mana, 25); + TEST_ASSERT(std::string(inst.GetUnscaledItem()->Name) == "Training Sword Mk II"); + TEST_ASSERT_EQUALS(inst.GetItem()->HP, 90); + TEST_ASSERT_EQUALS(inst.GetItem()->Mana, 25); + TEST_ASSERT_EQUALS(inst.GetItem()->Damage, static_cast(14)); + TEST_ASSERT(std::string(inst.GetItem()->Name) == "Training Sword Mk II"); + TEST_ASSERT(serial_before_refresh != inst.GetSerialNumber()); + + const auto serial_after_refresh = inst.GetSerialNumber(); + TEST_ASSERT(!inst.RefreshItemData(&base)); + TEST_ASSERT_EQUALS(serial_after_refresh, inst.GetSerialNumber()); + } +}; diff --git a/tests/main.cpp b/tests/main.cpp index 9eb5c90802..1ef76564d5 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -17,6 +17,7 @@ */ #include "tests/atobool_test.h" #include "tests/data_verification_test.h" +#include "tests/dynamic_item_test.h" #include "tests/fixed_memory_test.h" #include "tests/fixed_memory_variable_test.h" #include "tests/hextoi_32_64_test.h" @@ -51,6 +52,7 @@ int main() tests.add(new FixedMemoryHashTest()); tests.add(new FixedMemoryVariableHashTest()); tests.add(new atoboolTest()); + tests.add(new DynamicItemTest()); tests.add(new hextoi_32_64_Test()); tests.add(new StringUtilTest()); tests.add(new DataVerificationTest()); diff --git a/world/world_boot.cpp b/world/world_boot.cpp index 4bd6c79fd6..bea450a49b 100644 --- a/world/world_boot.cpp +++ b/world/world_boot.cpp @@ -318,6 +318,8 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv) ); } + content_db.SetSharedItemsCount(content_db.GetItemsCount()); + if (!content_db.LoadItems(hotfix_name)) { LogError("Error: Could not load item data. But ignoring"); } diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 8689ab385f..07549f2d4c 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -461,10 +461,12 @@ set(gm_command_sources gm_commands/interrupt.cpp gm_commands/invsnapshot.cpp gm_commands/ipban.cpp + gm_commands/itemedit.cpp gm_commands/kick.cpp gm_commands/kill.cpp gm_commands/killallnpcs.cpp gm_commands/list.cpp + gm_commands/liveitem.cpp gm_commands/loc.cpp gm_commands/logs.cpp gm_commands/lootsim.cpp diff --git a/zone/client.cpp b/zone/client.cpp index e33650c7ee..bafa472a8f 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -6597,6 +6597,7 @@ void Client::ProcessInspectRequest(Client *requestee, Client *requester) inst = requestee->GetInv().GetItem(L); if (inst) { + requestee->RefreshLiveItemTree(const_cast(inst)); item = inst->GetItem(); if (item) { strcpy(insr->itemnames[L], item->Name); @@ -8657,6 +8658,19 @@ void Client::TryItemTimer(int slot) return; } + const bool live_item_refreshed = RefreshLiveItemTree(inst); + if (live_item_refreshed) { + SendItemPacket( + slot, + inst, + slot == EQ::invslot::slotCursor ? ItemPacketCharInventory : ItemPacketTrade + ); + + if (slot <= EQ::invslot::EQUIPMENT_END) { + CalcBonuses(); + } + } + auto item_timers = inst->GetTimers(); auto it_iter = item_timers.begin(); while(it_iter != item_timers.end()) { @@ -8695,8 +8709,25 @@ void Client::TryItemTimer(int slot) void Client::SendItemScale(EQ::ItemInstance *inst) { int slot = m_inv.GetSlotByItemInst(inst); if(slot != -1) { - inst->ScaleItem(); - SendItemPacket(slot, inst, ItemPacketCharmUpdate); + bool dynamic_item_refreshed = false; + + if (inst->IsScaling()) { + inst->ScaleItem(); + } else if (inst->HasDynamicItemData()) { + inst->RebuildDynamicItemData(); + inst->AssignNewSerialNumber(); + dynamic_item_refreshed = true; + } else { + inst->ScaleItem(); + } + + SendItemPacket( + slot, + inst, + dynamic_item_refreshed ? + (slot == EQ::invslot::slotCursor ? ItemPacketCharInventory : ItemPacketTrade) : + ItemPacketCharmUpdate + ); CalcBonuses(); } } diff --git a/zone/client.h b/zone/client.h index 62709bbd03..5cbd2c4def 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1157,6 +1157,8 @@ class Client : public Mob void SendItemLink(const EQ::ItemInstance* inst, bool sendtoall=false); void SendLootItemInPacket(const EQ::ItemInstance* inst, int16 slot_id); void SendItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPacketType packet_type); + bool RefreshLiveItem(EQ::ItemInstance* inst); + bool RefreshLiveItemTree(EQ::ItemInstance* inst); bool IsValidSlot(uint32 slot); bool IsBankSlot(uint32 slot); diff --git a/zone/command.cpp b/zone/command.cpp index 11a40aab86..96b6d382cf 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -166,11 +166,14 @@ int command_init(void) command_add("interrupt", "[Message ID] [Color] - Interrupt your casting. Arguments are optional.", AccountStatus::Guide, command_interrupt) || command_add("invsnapshot", "Manipulates inventory snapshots for your current target", AccountStatus::QuestTroupe, command_invsnapshot) || command_add("ipban", "[IP] - Ban IP", AccountStatus::GMMgmt, command_ipban) || + command_add("itemedit", "[set|add|clear|proc] - Edit the item currently held on your cursor", AccountStatus::GMMgmt, command_itemedit) || + command_add("itemforge", "[dialog|craft] - Open or use the player item forge", AccountStatus::Player, command_itemforge) || command_add("kick", "[Character Name] - Disconnect a player by name", AccountStatus::GMLeadAdmin, command_kick) || command_add("kill", "Kill your target", AccountStatus::GMAdmin, command_kill) || command_add("killallnpcs", "[npc_name] - Kills all npcs by search name, leave blank for all attackable NPC's", AccountStatus::GMMgmt, command_killallnpcs) || command_add("list", "[npcs|players|corpses|doors|objects] [search] - Search entities", AccountStatus::ApprenticeGuide, command_list) || command_add("lootfilter", "[include|exclude|remove|list|mode] - Manage AutoLoot item filters", AccountStatus::Player, command_lootfilter) || + command_add("liveitem", "[status|clear|clone|summon|bump] - Manage live database item testing and cache state", AccountStatus::GMMgmt, command_liveitem) || command_add("lootsim", "[npc_type_id] [loottable_id] [iterations] - Runs benchmark simulations using real loot logic to report numbers and data", AccountStatus::GMImpossible, command_lootsim) || command_add("load_shared_memory", "[shared_memory_name] - Reloads shared memory and uses the input as output", AccountStatus::GMImpossible, command_load_shared_memory) || command_add("loc", "Print out your or your target's current location and heading", AccountStatus::Player, command_loc) || diff --git a/zone/command.h b/zone/command.h index d8667c6859..542f3f1a86 100644 --- a/zone/command.h +++ b/zone/command.h @@ -127,11 +127,14 @@ void command_interrogateinv(Client *c, const Seperator *sep); void command_interrupt(Client *c, const Seperator *sep); void command_invsnapshot(Client *c, const Seperator *sep); void command_ipban(Client *c, const Seperator *sep); +void command_itemedit(Client *c, const Seperator *sep); +void command_itemforge(Client *c, const Seperator *sep); void command_kick(Client *c, const Seperator *sep); void command_killallnpcs(Client *c, const Seperator *sep); void command_kill(Client *c, const Seperator *sep); void command_list(Client *c, const Seperator *sep); void command_lootfilter(Client *c, const Seperator *sep); +void command_liveitem(Client *c, const Seperator *sep); void command_lootsim(Client *c, const Seperator *sep); void command_load_shared_memory(Client *c, const Seperator *sep); void command_loc(Client *c, const Seperator *sep); diff --git a/zone/gm_commands/itemedit.cpp b/zone/gm_commands/itemedit.cpp new file mode 100644 index 0000000000..ef2bab7978 --- /dev/null +++ b/zone/gm_commands/itemedit.cpp @@ -0,0 +1,513 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ +#include "common/say_link.h" +#include "common/strings.h" +#include "zone/client.h" + +#include +#include +#include +#include + +namespace { + enum class ItemEditFieldType { + Number, + Text + }; + + struct ItemEditField { + const char *key; + const char *label; + ItemEditFieldType type; + }; + + const std::vector &GetItemEditFields() + { + static const std::vector fields = { + {"name", "Name", ItemEditFieldType::Text}, + {"lore", "Lore", ItemEditFieldType::Text}, + {"idfile", "IDFile", ItemEditFieldType::Text}, + {"icon", "Icon", ItemEditFieldType::Number}, + {"color", "Color", ItemEditFieldType::Number}, + {"itemtype", "Item Type", ItemEditFieldType::Number}, + {"slots", "Slots", ItemEditFieldType::Number}, + {"classes", "Classes", ItemEditFieldType::Number}, + {"races", "Races", ItemEditFieldType::Number}, + {"reqlevel", "Req Level", ItemEditFieldType::Number}, + {"reclevel", "Rec Level", ItemEditFieldType::Number}, + {"damage", "Damage", ItemEditFieldType::Number}, + {"delay", "Delay", ItemEditFieldType::Number}, + {"ac", "AC", ItemEditFieldType::Number}, + {"hp", "HP", ItemEditFieldType::Number}, + {"mana", "Mana", ItemEditFieldType::Number}, + {"endur", "Endur", ItemEditFieldType::Number}, + {"haste", "Haste", ItemEditFieldType::Number}, + {"attack", "Attack", ItemEditFieldType::Number}, + {"accuracy", "Accuracy", ItemEditFieldType::Number}, + {"avoidance", "Avoidance", ItemEditFieldType::Number}, + {"shielding", "Shielding", ItemEditFieldType::Number}, + {"spellshield", "Spell Shield", ItemEditFieldType::Number}, + {"dotshielding", "DoT Shielding", ItemEditFieldType::Number}, + {"damageshield", "Damage Shield", ItemEditFieldType::Number}, + {"healamt", "Heal Amt", ItemEditFieldType::Number}, + {"spelldmg", "Spell Dmg", ItemEditFieldType::Number}, + {"str", "STR", ItemEditFieldType::Number}, + {"sta", "STA", ItemEditFieldType::Number}, + {"agi", "AGI", ItemEditFieldType::Number}, + {"dex", "DEX", ItemEditFieldType::Number}, + {"int", "INT", ItemEditFieldType::Number}, + {"wis", "WIS", ItemEditFieldType::Number}, + {"cha", "CHA", ItemEditFieldType::Number}, + {"mr", "MR", ItemEditFieldType::Number}, + {"fr", "FR", ItemEditFieldType::Number}, + {"cr", "CR", ItemEditFieldType::Number}, + {"dr", "DR", ItemEditFieldType::Number}, + {"pr", "PR", ItemEditFieldType::Number}, + {"svcorruption", "Corruption", ItemEditFieldType::Number}, + {"heroicstr", "Heroic STR", ItemEditFieldType::Number}, + {"heroicsta", "Heroic STA", ItemEditFieldType::Number}, + {"heroicagi", "Heroic AGI", ItemEditFieldType::Number}, + {"heroicdex", "Heroic DEX", ItemEditFieldType::Number}, + {"heroicint", "Heroic INT", ItemEditFieldType::Number}, + {"heroicwis", "Heroic WIS", ItemEditFieldType::Number}, + {"heroiccha", "Heroic CHA", ItemEditFieldType::Number}, + {"heroicmr", "Heroic MR", ItemEditFieldType::Number}, + {"heroicfr", "Heroic FR", ItemEditFieldType::Number}, + {"heroiccr", "Heroic CR", ItemEditFieldType::Number}, + {"heroicdr", "Heroic DR", ItemEditFieldType::Number}, + {"heroicpr", "Heroic PR", ItemEditFieldType::Number}, + {"heroicsvcorruption", "Heroic Corr", ItemEditFieldType::Number}, + {"proceffect", "Proc Effect", ItemEditFieldType::Number}, + {"proctype", "Proc Type", ItemEditFieldType::Number}, + {"proclevel", "Proc Level", ItemEditFieldType::Number}, + {"proclevel2", "Proc Level2", ItemEditFieldType::Number}, + {"procrate", "Proc Rate", ItemEditFieldType::Number}, + {"procname", "Proc Name", ItemEditFieldType::Text}, + {"worneffect", "Worn Effect", ItemEditFieldType::Number}, + {"worntype", "Worn Type", ItemEditFieldType::Number}, + {"wornlevel", "Worn Level", ItemEditFieldType::Number}, + {"wornlevel2", "Worn Level2", ItemEditFieldType::Number}, + {"wornname", "Worn Name", ItemEditFieldType::Text}, + {"focuseffect", "Focus Effect", ItemEditFieldType::Number}, + {"focustype", "Focus Type", ItemEditFieldType::Number}, + {"focuslevel", "Focus Level", ItemEditFieldType::Number}, + {"focuslevel2", "Focus Level2", ItemEditFieldType::Number}, + {"focusname", "Focus Name", ItemEditFieldType::Text}, + {"clickeffect", "Click Effect", ItemEditFieldType::Number}, + {"clicktype", "Click Type", ItemEditFieldType::Number}, + {"clicklevel", "Click Level", ItemEditFieldType::Number}, + {"clicklevel2", "Click Level2", ItemEditFieldType::Number}, + {"clickname", "Click Name", ItemEditFieldType::Text}, + {"scrolleffect", "Scroll Effect", ItemEditFieldType::Number}, + {"scrolltype", "Scroll Type", ItemEditFieldType::Number}, + {"scrolllevel", "Scroll Level", ItemEditFieldType::Number}, + {"scrolllevel2", "Scroll Level2", ItemEditFieldType::Number}, + {"scrollname", "Scroll Name", ItemEditFieldType::Text} + }; + + return fields; + } + + std::string NormalizeFieldName(std::string field) + { + field = Strings::ToLower(field); + field.erase( + std::remove_if( + field.begin(), + field.end(), + [](const char c) { + return c == '_' || c == '-' || c == ' ' || c == '.'; + } + ), + field.end() + ); + return field; + } + + const ItemEditField *FindItemEditField(const std::string &field) + { + const auto normalized = NormalizeFieldName(field); + for (const auto &entry : GetItemEditFields()) { + if (normalized == entry.key) { + return &entry; + } + } + + return nullptr; + } + + int64 GetItemEditNumber(const EQ::ItemData *item, const std::string &field) + { + if (!item) { + return 0; + } + + if (field == "icon") { return item->Icon; } + if (field == "color") { return item->Color; } + if (field == "itemtype") { return item->ItemType; } + if (field == "slots") { return item->Slots; } + if (field == "classes") { return item->Classes; } + if (field == "races") { return item->Races; } + if (field == "reqlevel") { return item->ReqLevel; } + if (field == "reclevel") { return item->RecLevel; } + if (field == "damage") { return item->Damage; } + if (field == "delay") { return item->Delay; } + if (field == "ac") { return item->AC; } + if (field == "hp") { return item->HP; } + if (field == "mana") { return item->Mana; } + if (field == "endur") { return item->Endur; } + if (field == "haste") { return item->Haste; } + if (field == "attack") { return item->Attack; } + if (field == "accuracy") { return item->Accuracy; } + if (field == "avoidance") { return item->Avoidance; } + if (field == "shielding") { return item->Shielding; } + if (field == "spellshield") { return item->SpellShield; } + if (field == "dotshielding") { return item->DotShielding; } + if (field == "damageshield") { return item->DamageShield; } + if (field == "healamt") { return item->HealAmt; } + if (field == "spelldmg") { return item->SpellDmg; } + if (field == "str") { return item->AStr; } + if (field == "sta") { return item->ASta; } + if (field == "agi") { return item->AAgi; } + if (field == "dex") { return item->ADex; } + if (field == "int") { return item->AInt; } + if (field == "wis") { return item->AWis; } + if (field == "cha") { return item->ACha; } + if (field == "mr") { return item->MR; } + if (field == "fr") { return item->FR; } + if (field == "cr") { return item->CR; } + if (field == "dr") { return item->DR; } + if (field == "pr") { return item->PR; } + if (field == "svcorruption") { return item->SVCorruption; } + if (field == "heroicstr") { return item->HeroicStr; } + if (field == "heroicsta") { return item->HeroicSta; } + if (field == "heroicagi") { return item->HeroicAgi; } + if (field == "heroicdex") { return item->HeroicDex; } + if (field == "heroicint") { return item->HeroicInt; } + if (field == "heroicwis") { return item->HeroicWis; } + if (field == "heroiccha") { return item->HeroicCha; } + if (field == "heroicmr") { return item->HeroicMR; } + if (field == "heroicfr") { return item->HeroicFR; } + if (field == "heroiccr") { return item->HeroicCR; } + if (field == "heroicdr") { return item->HeroicDR; } + if (field == "heroicpr") { return item->HeroicPR; } + if (field == "heroicsvcorruption") { return item->HeroicSVCorrup; } + if (field == "proceffect") { return item->Proc.Effect; } + if (field == "proctype") { return item->Proc.Type; } + if (field == "proclevel") { return item->Proc.Level; } + if (field == "proclevel2") { return item->Proc.Level2; } + if (field == "procrate") { return item->ProcRate; } + if (field == "worneffect") { return item->Worn.Effect; } + if (field == "worntype") { return item->Worn.Type; } + if (field == "wornlevel") { return item->Worn.Level; } + if (field == "wornlevel2") { return item->Worn.Level2; } + if (field == "focuseffect") { return item->Focus.Effect; } + if (field == "focustype") { return item->Focus.Type; } + if (field == "focuslevel") { return item->Focus.Level; } + if (field == "focuslevel2") { return item->Focus.Level2; } + if (field == "clickeffect") { return item->Click.Effect; } + if (field == "clicktype") { return item->Click.Type; } + if (field == "clicklevel") { return item->Click.Level; } + if (field == "clicklevel2") { return item->Click.Level2; } + if (field == "scrolleffect") { return item->Scroll.Effect; } + if (field == "scrolltype") { return item->Scroll.Type; } + if (field == "scrolllevel") { return item->Scroll.Level; } + if (field == "scrolllevel2") { return item->Scroll.Level2; } + + return 0; + } + + std::string GetItemEditText(const EQ::ItemData *item, const std::string &field) + { + if (!item) { + return ""; + } + + if (field == "name") { return item->Name; } + if (field == "lore") { return item->Lore; } + if (field == "idfile") { return item->IDFile; } + if (field == "procname") { return item->ProcName; } + if (field == "wornname") { return item->WornName; } + if (field == "focusname") { return item->FocusName; } + if (field == "clickname") { return item->ClickName; } + if (field == "scrollname") { return item->ScrollName; } + + return ""; + } + + std::string DynamicItemSetKey(const std::string &field) + { + return fmt::format("dynamic_item.set.{}", field); + } + + std::string DynamicItemModKey(const std::string &field) + { + return fmt::format("dynamic_item.mod.{}", field); + } + + EQ::ItemInstance *GetCursorItem(Client *c) + { + return c ? c->GetInv().GetItem(EQ::invslot::slotCursor) : nullptr; + } + + void SaveCursorEdit(Client *c, EQ::ItemInstance *inst) + { + c->SendItemPacket(EQ::invslot::slotCursor, inst, ItemPacketCharInventory); + + if (!database.SaveInventory(c->CharacterID(), inst, EQ::invslot::slotCursor)) { + c->Message(Chat::Red, "Item edit applied, but saving the cursor slot failed."); + } + } + + void SendItemEditUsage(Client *c) + { + c->Message(Chat::White, "Usage: hold an item on your cursor and use #itemedit"); + c->Message(Chat::White, "Usage: #itemedit set [field] [value]"); + c->Message(Chat::White, "Usage: #itemedit add [field] [amount]"); + c->Message(Chat::White, "Usage: #itemedit clear [field|all]"); + c->Message(Chat::White, "Usage: #itemedit proc [spell_id] [rate] [level]"); + } + + std::string NumericEditLinks(const std::string &field) + { + return fmt::format( + "{} {} {} {} {}", + Saylink::Silent(fmt::format("#itemedit add {} -10", field), "-10"), + Saylink::Silent(fmt::format("#itemedit add {} -1", field), "-1"), + Saylink::Silent(fmt::format("#itemedit add {} 1", field), "+1"), + Saylink::Silent(fmt::format("#itemedit add {} 10", field), "+10"), + Saylink::Silent(fmt::format("#itemedit clear {}", field), "clear") + ); + } + + void SendFieldLine(Client *c, EQ::ItemInstance *inst, const ItemEditField &field) + { + const auto *resolved = inst->GetItem(); + const auto *base = inst->GetUnscaledItem(); + + if (field.type == ItemEditFieldType::Text) { + const std::string value = GetItemEditText(resolved, field.key); + const std::string base_value = GetItemEditText(base, field.key); + const bool overridden = !inst->GetCustomData(DynamicItemSetKey(field.key)).empty(); + + c->Message( + Chat::White, + fmt::format( + "{}: [{}] base [{}] {} | #itemedit set {} | {}", + field.label, + value, + base_value, + overridden ? "override" : "", + field.key, + Saylink::Silent(fmt::format("#itemedit clear {}", field.key), "clear") + ).c_str() + ); + return; + } + + const auto value = GetItemEditNumber(resolved, field.key); + const auto base_value = GetItemEditNumber(base, field.key); + const auto modifier = inst->GetCustomData(DynamicItemModKey(field.key)); + const auto override_value = inst->GetCustomData(DynamicItemSetKey(field.key)); + std::string note; + + if (!override_value.empty()) { + note = fmt::format(" set [{}]", override_value); + } + + if (!modifier.empty()) { + note += fmt::format(" mod [{}]", modifier); + } + + c->Message( + Chat::White, + fmt::format( + "{}: [{}] base [{}]{} | {}", + field.label, + value, + base_value, + note, + NumericEditLinks(field.key) + ).c_str() + ); + } + + void SendItemEditWindow(Client *c, EQ::ItemInstance *inst) + { + const auto *item = inst ? inst->GetItem() : nullptr; + if (!item) { + c->Message(Chat::White, "Hold an item on your cursor before using #itemedit."); + return; + } + + EQ::SayLinkEngine linker; + linker.SetLinkType(EQ::saylink::SayLinkItemInst); + linker.SetItemInst(inst); + + c->Message( + Chat::White, + fmt::format( + "Item Edit: {} | {} | {} | {}", + linker.GenerateLink(), + Saylink::Silent("#itemedit clear all", "clear all"), + Saylink::Silent("#itemedit proc 0", "clear proc"), + Saylink::Silent("#itemedit", "refresh") + ).c_str() + ); + c->Message(Chat::White, "Click +/- for additive per-instance modifiers. Use #itemedit set field value for exact overrides."); + + for (const auto &field : GetItemEditFields()) { + SendFieldLine(c, inst, field); + } + } +} + +void command_itemedit(Client *c, const Seperator *sep) +{ + auto *inst = GetCursorItem(c); + if (!inst || !inst->GetItem()) { + SendItemEditUsage(c); + c->Message(Chat::White, "No item is currently on your cursor."); + return; + } + + const int arguments = sep->argnum; + if (!arguments || !strcasecmp(sep->arg[1], "help") || !strcasecmp(sep->arg[1], "list")) { + SendItemEditWindow(c, inst); + return; + } + + const bool is_set = !strcasecmp(sep->arg[1], "set"); + const bool is_add = !strcasecmp(sep->arg[1], "add") || !strcasecmp(sep->arg[1], "mod"); + const bool is_clear = !strcasecmp(sep->arg[1], "clear") || !strcasecmp(sep->arg[1], "reset"); + const bool is_proc = !strcasecmp(sep->arg[1], "proc"); + + if (is_clear) { + if (arguments < 2 || !strcasecmp(sep->arg[2], "all")) { + inst->ClearDynamicItemData(); + SaveCursorEdit(c, inst); + c->Message(Chat::White, "Cleared all dynamic item edits from the cursor item."); + SendItemEditWindow(c, inst); + return; + } + + const auto *field = FindItemEditField(sep->arg[2]); + if (!field) { + c->Message(Chat::White, fmt::format("Unknown item edit field [{}].", sep->arg[2]).c_str()); + return; + } + + inst->DeleteDynamicItemData(field->key); + inst->DeleteDynamicItemModifier(field->key); + SaveCursorEdit(c, inst); + c->Message(Chat::White, fmt::format("Cleared dynamic item edits for [{}].", field->label).c_str()); + SendItemEditWindow(c, inst); + return; + } + + if (is_proc) { + if (arguments < 2 || !sep->IsNumber(2)) { + c->Message(Chat::White, "Usage: #itemedit proc [spell_id] [rate] [level]"); + return; + } + + const int spell_id = Strings::ToInt(sep->arg[2]); + if (spell_id <= 0) { + inst->DeleteDynamicItemData("proceffect"); + inst->DeleteDynamicItemData("proctype"); + inst->DeleteDynamicItemData("proclevel"); + inst->DeleteDynamicItemData("proclevel2"); + inst->DeleteDynamicItemData("procrate"); + inst->DeleteDynamicItemData("procname"); + c->Message(Chat::White, "Cleared proc fields from the cursor item."); + } else { + const int proc_rate = (arguments >= 3 && sep->IsNumber(3)) ? Strings::ToInt(sep->arg[3]) : 100; + const int proc_level = (arguments >= 4 && sep->IsNumber(4)) ? Strings::ToInt(sep->arg[4]) : 1; + inst->SetDynamicItemData("proceffect", spell_id); + inst->SetDynamicItemData("proctype", EQ::item::ItemEffectCombatProc); + inst->SetDynamicItemData("proclevel", proc_level); + inst->SetDynamicItemData("proclevel2", 255); + inst->SetDynamicItemData("procrate", proc_rate); + c->Message(Chat::White, fmt::format("Set cursor item proc to spell [{}], rate [{}], level [{}].", spell_id, proc_rate, proc_level).c_str()); + } + + SaveCursorEdit(c, inst); + SendItemEditWindow(c, inst); + return; + } + + if (is_add) { + if (arguments < 3 || !sep->IsNumber(3)) { + c->Message(Chat::White, "Usage: #itemedit add [field] [amount]"); + return; + } + + const auto *field = FindItemEditField(sep->arg[2]); + if (!field || field->type != ItemEditFieldType::Number) { + c->Message(Chat::White, fmt::format("[{}] is not a numeric item edit field.", sep->arg[2]).c_str()); + return; + } + + const int current_modifier = Strings::ToInt(inst->GetCustomData(DynamicItemModKey(field->key))); + const int delta = Strings::ToInt(sep->arg[3]); + inst->SetDynamicItemModifier(field->key, current_modifier + delta); + SaveCursorEdit(c, inst); + c->Message( + Chat::White, + fmt::format( + "Adjusted [{}] modifier by [{}]. New modifier [{}].", + field->label, + delta, + current_modifier + delta + ).c_str() + ); + SendItemEditWindow(c, inst); + return; + } + + if (is_set) { + if (arguments < 3) { + c->Message(Chat::White, "Usage: #itemedit set [field] [value]"); + return; + } + + const auto *field = FindItemEditField(sep->arg[2]); + if (!field) { + c->Message(Chat::White, fmt::format("Unknown item edit field [{}].", sep->arg[2]).c_str()); + return; + } + + if (field->type == ItemEditFieldType::Number) { + if (!sep->IsNumber(3)) { + c->Message(Chat::White, fmt::format("[{}] requires a numeric value.", field->label).c_str()); + return; + } + + inst->SetDynamicItemData(field->key, Strings::ToInt(sep->arg[3])); + } else { + inst->SetDynamicItemData(field->key, std::string(sep->argplus[3])); + } + + SaveCursorEdit(c, inst); + c->Message(Chat::White, fmt::format("Set [{}] override on the cursor item.", field->label).c_str()); + SendItemEditWindow(c, inst); + return; + } + + SendItemEditUsage(c); +} diff --git a/zone/gm_commands/liveitem.cpp b/zone/gm_commands/liveitem.cpp new file mode 100644 index 0000000000..f614da2c48 --- /dev/null +++ b/zone/gm_commands/liveitem.cpp @@ -0,0 +1,649 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ +#include "common/repositories/items_repository.h" +#include "common/data_bucket.h" +#include "common/item_data.h" +#include "common/ipc_mutex.h" +#include "common/repositories/data_buckets_repository.h" +#include "common/rulesys.h" +#include "common/strings.h" +#include "zone/client.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + void SendLiveItemUsage(Client *c) + { + c->Message( + Chat::White, + fmt::format( + "Live Items: enabled [{}], range [{}-{}], poll [{}s].", + RuleB(Items, LiveItemLoading) ? "true" : "false", + RuleI(Items, LiveItemMinID), + RuleI(Items, LiveItemMaxID), + RuleI(Items, LiveItemPollIntervalSeconds) + ).c_str() + ); + c->Message(Chat::White, "Usage: #liveitem status [item_id]"); + c->Message(Chat::White, "Usage: #liveitem clear [item_id|all]"); + c->Message(Chat::White, "Usage: #liveitem clone [new_item_id] [source_item_id]"); + c->Message(Chat::White, "Usage: #liveitem summon [item_id] [charges]"); + c->Message(Chat::White, "Usage: #liveitem bump [item_id] [hp] [mana] [damage]"); + } + + bool IsValidLiveItemID(Client *c, const uint32 item_id) + { + if (!item_id || item_id > static_cast(std::numeric_limits::max())) { + c->Message(Chat::White, "Enter an item ID from 1 to 2147483647."); + return false; + } + + return true; + } + + void SendItemSummary(Client *c, const EQ::ItemData *item) + { + if (!item) { + c->Message(Chat::White, "Resolved Item: not found."); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Resolved Item: [{}] {} | HP [{}] Mana [{}] Damage [{}] Delay [{}] Haste [{}] Proc [{}]", + item->ID, + item->Name, + item->HP, + item->Mana, + item->Damage, + item->Delay, + item->Haste, + item->Proc.Effect + ).c_str() + ); + } + + void SummonLiveItem(Client *c, const uint32 item_id, int16 charges) + { + const auto *item = database.GetItem(item_id); + if (!item) { + c->Message(Chat::White, fmt::format("Item ID {} does not exist.", item_id).c_str()); + return; + } + + if (item->MinStatus > c->Admin()) { + c->Message( + Chat::White, + fmt::format( + "Insufficient status to summon this item, current status is {}, required status is {}.", + c->Admin(), + item->MinStatus + ).c_str() + ); + return; + } + + c->SummonItem(item_id, charges); + + const auto *new_item = database.CreateItem(item_id, charges); + EQ::SayLinkEngine linker; + linker.SetLinkType(EQ::saylink::SayLinkItemInst); + linker.SetItemInst(new_item); + + c->Message(Chat::White, fmt::format("You have summoned {}.", linker.GenerateLink()).c_str()); + safe_delete(new_item); + } + + bool UpsertLiveItemClone(Client *c, const uint32 target_id, const uint32 source_id) + { + auto source = ItemsRepository::FindOne(database, source_id); + if (!source.id) { + c->Message(Chat::White, fmt::format("Source item ID {} does not exist.", source_id).c_str()); + return false; + } + + const bool replacing = ItemsRepository::FindOne(database, target_id).id != 0; + + source.id = target_id; + source.minstatus = 0; + source.Name = fmt::format("Live Test Item {}", target_id); + source.lore = fmt::format("A live item cloned from {}", source_id); + source.comment = "Generated by #liveitem clone"; + source.hp += 25; + source.mana += 25; + source.haste = std::max(source.haste, 5); + source.damage = std::max(source.damage + 1, 1); + source.delay = std::max(source.delay, 20); + source.updated = std::time(nullptr); + + if (replacing) { + if (!ItemsRepository::UpdateOne(database, source)) { + c->Message(Chat::White, fmt::format("Failed to update live item ID {}.", target_id).c_str()); + return false; + } + } else { + ItemsRepository::InsertOne(database, source); + if (!ItemsRepository::FindOne(database, target_id).id) { + c->Message(Chat::White, fmt::format("Failed to insert live item ID {}.", target_id).c_str()); + return false; + } + } + + database.ClearLiveItemCache(target_id); + c->Message( + Chat::White, + fmt::format( + "{} live item ID {} from source item ID {}.", + replacing ? "Updated" : "Created", + target_id, + source_id + ).c_str() + ); + + return true; + } + + constexpr const char *LiveItemForgeNextBucket = "live_item_forge.next_item_id"; + + struct ItemForgeDefinition { + uint32 item_id = 0; + std::string name = "Forged Item"; + std::string item_type = "weapon"; + int hp = 25; + int mana = 25; + int ac = 5; + int damage = 5; + int delay = 24; + int haste = 0; + }; + + std::string TrimItemForgeText(std::string value) + { + while (!value.empty() && std::isspace(static_cast(value.front()))) { + value.erase(value.begin()); + } + + while (!value.empty() && std::isspace(static_cast(value.back()))) { + value.pop_back(); + } + + return value; + } + + std::string DecodeItemForgeText(const std::string &value) + { + std::string decoded; + decoded.reserve(std::min(value.size(), 60)); + + for (const auto raw_ch : value) { + const auto ch = raw_ch == '_' ? ' ' : raw_ch; + const bool alpha = (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); + const bool digit = ch >= '0' && ch <= '9'; + const bool separator = ch == ' ' || ch == '-' || ch == '\''; + if (!alpha && !digit && !separator) { + continue; + } + + if (std::isspace(static_cast(ch))) { + if (decoded.empty() || decoded.back() == ' ') { + continue; + } + + decoded.push_back(' '); + } else { + decoded.push_back(ch); + } + + if (decoded.size() >= 60) { + break; + } + } + + return TrimItemForgeText(decoded); + } + + bool HasItemForgeNamedArgs(const Seperator *sep) + { + for (int index = 2; index <= sep->argnum; ++index) { + if (std::strchr(sep->arg[index], '=')) { + return true; + } + } + + return false; + } + + std::string GetItemForgeNamedArg(const Seperator *sep, const std::string &key) + { + const auto wanted = Strings::ToLower(key); + for (int index = 2; index <= sep->argnum; ++index) { + const std::string token = sep->arg[index]; + const auto separator = token.find('='); + if (separator == std::string::npos) { + continue; + } + + if (Strings::ToLower(token.substr(0, separator)) == wanted) { + return token.substr(separator + 1); + } + } + + return {}; + } + + int GetItemForgeNamedInt(const Seperator *sep, const std::string &key, const int fallback) + { + const auto value = GetItemForgeNamedArg(sep, key); + return value.empty() ? fallback : Strings::ToInt(value); + } + + uint32 BuildSlotMask(const std::initializer_list slots) + { + uint32 mask = 0; + for (const auto slot : slots) { + mask |= static_cast(1 << slot); + } + + return mask; + } + + uint32 FindFreeForgedLiveItemID() + { + const auto minimum = static_cast(std::max(1, RuleI(Items, LiveItemMinID))); + const auto maximum = static_cast(std::max(0, RuleI(Items, LiveItemMaxID))); + + auto start = static_cast(Strings::ToUnsignedInt(DataBucket::GetData(&database, LiveItemForgeNextBucket))); + if (start < minimum) { + start = minimum; + } + + for (uint32 item_id = start; item_id <= maximum || maximum == 0; ++item_id) { + if (maximum && item_id > maximum) { + break; + } + + if (database.IsLiveItemID(item_id) && !ItemsRepository::FindOne(database, item_id).id) { + DataBucket::SetData(&database, LiveItemForgeNextBucket, std::to_string(item_id + 1)); + return item_id; + } + + if (maximum == 0 && item_id == std::numeric_limits::max()) { + break; + } + } + + return 0; + } + + void ApplyItemForgeType(ItemsRepository::Items &item, const ItemForgeDefinition &definition) + { + const auto type = Strings::ToLower(definition.item_type); + if (type == "armor") { + item.itemtype = EQ::item::ItemTypeArmor; + item.slots = BuildSlotMask({EQ::invslot::slotChest}); + item.icon = 538; + item.damage = 0; + item.delay = 0; + item.haste = 0; + item.ac = std::max(item.ac, 10); + return; + } + + if (type == "jewelry") { + item.itemtype = EQ::item::ItemTypeJewelry; + item.slots = BuildSlotMask({EQ::invslot::slotFinger1, EQ::invslot::slotFinger2}); + item.icon = 674; + item.damage = 0; + item.delay = 0; + item.haste = 0; + item.ac = std::max(0, item.ac / 2); + return; + } + + if (type == "charm") { + item.itemtype = EQ::item::ItemTypeCharm; + item.slots = BuildSlotMask({EQ::invslot::slotCharm}); + item.icon = 1123; + item.damage = 0; + item.delay = 0; + item.haste = 0; + return; + } + + if (type == "shield") { + item.itemtype = EQ::item::ItemTypeShield; + item.slots = BuildSlotMask({EQ::invslot::slotSecondary}); + item.icon = 535; + item.damage = 0; + item.delay = 0; + item.haste = 0; + item.ac = std::max(item.ac, 15); + return; + } + + item.itemtype = EQ::item::ItemType1HSlash; + item.slots = BuildSlotMask({EQ::invslot::slotPrimary, EQ::invslot::slotSecondary}); + item.icon = 519; +} + bool CreateForgedLiveItem(Client *c, ItemForgeDefinition definition) + { + definition.item_id = FindFreeForgedLiveItemID(); + definition.name = DecodeItemForgeText(definition.name); + if (definition.name.empty()) { + definition.name = fmt::format("{}'s Forged", c->GetCleanName()); + } + + definition.item_type = Strings::ToLower(definition.item_type); + definition.hp = std::clamp(definition.hp, 0, 500); + definition.mana = std::clamp(definition.mana, 0, 500); + definition.ac = std::clamp(definition.ac, 0, 100); + definition.damage = std::clamp(definition.damage, 0, 100); + definition.delay = std::clamp(definition.delay, 10, 60); + definition.haste = std::clamp(definition.haste, 0, 50); + + if (!definition.item_id) { + c->Message(Chat::White, "No free live item ID is available in the configured live item range."); + return false; + } + + auto item = ItemsRepository::NewEntity(); + item.id = static_cast(definition.item_id); + item.minstatus = 0; + item.Name = definition.name; + item.lore = fmt::format("A custom item shaped for {}", c->GetCleanName()); + item.comment = fmt::format("Generated by #itemforge for character {}", c->CharacterID()); + item.itemclass = EQ::item::ItemClassCommon; + item.classes = 65535; + item.races = 65535; + item.norent = 255; + item.nodrop = 0; + item.size = EQ::item::ItemSizeMedium; + item.weight = 10; + item.magic = 1; + item.loregroup = 0; + item.maxcharges = -1; + item.hp = definition.hp; + item.mana = definition.mana; + item.ac = definition.ac; + item.damage = definition.damage; + item.delay = definition.delay; + item.haste = definition.haste; + item.price = 0; + item.sellrate = 1.0f; + item.tradeskills = 0; + item.updated = std::time(nullptr); + + ApplyItemForgeType(item, definition); + + ItemsRepository::InsertOne(database, item); + if (!ItemsRepository::FindOne(database, definition.item_id).id) { + c->Message(Chat::White, fmt::format("Failed to create forged item {}.", definition.item_id).c_str()); + return false; + } + + database.ClearLiveItemCache(definition.item_id); + SummonLiveItem(c, definition.item_id, 1); + c->Message( + Chat::White, + fmt::format( + "Created {} as live item {}.", + item.Name, + definition.item_id + ).c_str() + ); + + return true; + } + + void SendItemForgeUsage(Client *c) + { + c->Message(Chat::White, "Usage: #itemforge dialog"); + c->Message(Chat::White, "Usage: #itemforge craft type=weapon name=Storm_Blade hp=50 mana=20 ac=5 damage=12 delay=24 haste=5"); + } +} + +void command_itemforge(Client *c, const Seperator *sep) +{ + const auto arguments = sep->argnum; + if (!arguments || !strcasecmp(sep->arg[1], "help")) { + SendItemForgeUsage(c); + return; + } + + const bool is_dialog = !strcasecmp(sep->arg[1], "dialog") || !strcasecmp(sep->arg[1], "open"); + const bool is_craft = !strcasecmp(sep->arg[1], "craft") || !strcasecmp(sep->arg[1], "create"); + + if (is_dialog) { + c->Message(Chat::White, "Opening the Item Forge."); + c->Message(Chat::White, "LIVEITEM|ui|open|types=weapon,armor,jewelry,charm,shield|max_hp=500|max_mana=500|max_ac=100|max_damage=100|max_haste=50"); + return; + } + + if (!is_craft) { + SendItemForgeUsage(c); + return; + } + + ItemForgeDefinition definition; + if (HasItemForgeNamedArgs(sep)) { + const auto item_type = GetItemForgeNamedArg(sep, "type"); + const auto name = GetItemForgeNamedArg(sep, "name"); + if (!item_type.empty()) { + definition.item_type = item_type; + } + + if (!name.empty()) { + definition.name = name; + } + + definition.hp = GetItemForgeNamedInt(sep, "hp", definition.hp); + definition.mana = GetItemForgeNamedInt(sep, "mana", definition.mana); + definition.ac = GetItemForgeNamedInt(sep, "ac", definition.ac); + definition.damage = GetItemForgeNamedInt(sep, "damage", definition.damage); + definition.delay = GetItemForgeNamedInt(sep, "delay", definition.delay); + definition.haste = GetItemForgeNamedInt(sep, "haste", definition.haste); + } else { + definition.item_type = arguments >= 2 ? std::string(sep->arg[2]) : definition.item_type; + definition.hp = (arguments >= 3 && sep->IsNumber(3)) ? Strings::ToInt(sep->arg[3]) : definition.hp; + definition.mana = (arguments >= 4 && sep->IsNumber(4)) ? Strings::ToInt(sep->arg[4]) : definition.mana; + definition.ac = (arguments >= 5 && sep->IsNumber(5)) ? Strings::ToInt(sep->arg[5]) : definition.ac; + definition.damage = (arguments >= 6 && sep->IsNumber(6)) ? Strings::ToInt(sep->arg[6]) : definition.damage; + definition.delay = (arguments >= 7 && sep->IsNumber(7)) ? Strings::ToInt(sep->arg[7]) : definition.delay; + definition.haste = (arguments >= 8 && sep->IsNumber(8)) ? Strings::ToInt(sep->arg[8]) : definition.haste; + } + + CreateForgedLiveItem(c, definition); +} + +void command_liveitem(Client *c, const Seperator *sep) +{ + const auto arguments = sep->argnum; + if (!arguments || !strcasecmp(sep->arg[1], "help")) { + SendLiveItemUsage(c); + return; + } + + const bool is_status = !strcasecmp(sep->arg[1], "status"); + const bool is_clear = !strcasecmp(sep->arg[1], "clear"); + const bool is_clone = !strcasecmp(sep->arg[1], "clone"); + const bool is_summon = !strcasecmp(sep->arg[1], "summon"); + const bool is_bump = !strcasecmp(sep->arg[1], "bump"); + + if (!is_status && !is_clear && !is_clone && !is_summon && !is_bump) { + SendLiveItemUsage(c); + return; + } + + if (is_clear) { + if (arguments < 2 || !strcasecmp(sep->arg[2], "all")) { + database.ClearLiveItemCache(); + c->Message(Chat::White, "Cleared all live item cache entries."); + return; + } + + if (!sep->IsNumber(2)) { + SendLiveItemUsage(c); + return; + } + + const auto item_id = Strings::ToUnsignedInt(sep->arg[2]); + if (!IsValidLiveItemID(c, item_id)) { + return; + } + + c->Message( + Chat::White, + fmt::format( + "Live item cache entry for item ID {} {}.", + item_id, + database.ClearLiveItemCache(item_id) ? "cleared" : "was not cached" + ).c_str() + ); + return; + } + + if (is_status) { + if (arguments < 2 || !sep->IsNumber(2)) { + SendLiveItemUsage(c); + return; + } + + const auto item_id = Strings::ToUnsignedInt(sep->arg[2]); + if (!IsValidLiveItemID(c, item_id)) { + return; + } + + const bool eligible = database.IsLiveItemID(item_id); + c->Message(Chat::White, fmt::format("Live Item ID [{}]: {}", item_id, eligible ? "eligible" : "not eligible").c_str()); + + const auto *item = database.GetItem(item_id); + SendItemSummary(c, item); + + SharedDatabase::LiveItemCacheEntry entry {}; + if (database.GetLiveItemCacheEntry(item_id, entry)) { + c->Message( + Chat::White, + fmt::format( + "Cache: exists [{}] last_checked [{}] updated [{}]", + entry.exists ? "true" : "false", + entry.last_checked, + entry.updated + ).c_str() + ); + } else { + c->Message(Chat::White, "Cache: no entry."); + } + return; + } + + if (is_clone) { + if (arguments < 3 || !sep->IsNumber(2) || !sep->IsNumber(3)) { + SendLiveItemUsage(c); + return; + } + + const auto target_id = Strings::ToUnsignedInt(sep->arg[2]); + const auto source_id = Strings::ToUnsignedInt(sep->arg[3]); + if (!IsValidLiveItemID(c, target_id) || !IsValidLiveItemID(c, source_id)) { + return; + } + + if (!database.IsLiveItemID(target_id)) { + c->Message(Chat::White, fmt::format("Item ID {} is outside the configured live item range.", target_id).c_str()); + return; + } + + if (UpsertLiveItemClone(c, target_id, source_id)) { + SummonLiveItem(c, target_id, 1); + } + return; + } + + if (is_summon) { + if (arguments < 2 || !sep->IsNumber(2)) { + SendLiveItemUsage(c); + return; + } + + const auto item_id = Strings::ToUnsignedInt(sep->arg[2]); + if (!IsValidLiveItemID(c, item_id)) { + return; + } + + const int16 charges = (arguments >= 3 && sep->IsNumber(3)) ? static_cast(Strings::ToInt(sep->arg[3])) : -1; + SummonLiveItem(c, item_id, charges); + return; + } + + if (is_bump) { + if (arguments < 2 || !sep->IsNumber(2)) { + SendLiveItemUsage(c); + return; + } + + const auto item_id = Strings::ToUnsignedInt(sep->arg[2]); + if (!IsValidLiveItemID(c, item_id)) { + return; + } + + if (!database.IsLiveItemID(item_id)) { + c->Message(Chat::White, fmt::format("Item ID {} is outside the configured live item range.", item_id).c_str()); + return; + } + + auto item = ItemsRepository::FindOne(database, item_id); + if (!item.id) { + c->Message(Chat::White, fmt::format("Item ID {} does not exist in the database.", item_id).c_str()); + return; + } + + const int hp_step = (arguments >= 3 && sep->IsNumber(3)) ? Strings::ToInt(sep->arg[3]) : 5; + const int mana_step = (arguments >= 4 && sep->IsNumber(4)) ? Strings::ToInt(sep->arg[4]) : 5; + const int damage_step = (arguments >= 5 && sep->IsNumber(5)) ? Strings::ToInt(sep->arg[5]) : 1; + + item.hp = std::max(0, item.hp + hp_step); + item.mana = std::max(0, item.mana + mana_step); + item.damage = std::max(0, item.damage + damage_step); + item.updated = std::time(nullptr); + + if (!ItemsRepository::UpdateOne(database, item)) { + c->Message(Chat::White, fmt::format("Failed to bump item ID {}.", item_id).c_str()); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Bumped item ID {} to HP [{}], Mana [{}], Damage [{}]. Wait up to the live item poll interval for held instances to refresh.", + item_id, + item.hp, + item.mana, + item.damage + ).c_str() + ); + } +} diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 4c9de5e843..c761de261b 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1517,6 +1517,8 @@ packet with the item number in it, but I cant seem to find it right now if (!inst) return; + RefreshLiveItemTree(const_cast(inst)); + const EQ::ItemData* item = inst->GetItem(); const char* name2 = &item->Name[0]; auto outapp = new EQApplicationPacket(OP_ItemLinkText, strlen(name2) + 68); @@ -1551,6 +1553,39 @@ void Client::SendLootItemInPacket(const EQ::ItemInstance* inst, int16 slot_id) SendItemPacket(slot_id,inst, ItemPacketTrade); } +bool Client::RefreshLiveItem(EQ::ItemInstance* inst) +{ + if (!inst || !database.IsLiveItemID(inst->GetID())) { + return false; + } + + const auto *item = database.GetItem(inst->GetID()); + if (!item) { + return false; + } + + return inst->RefreshItemData(item); +} + +bool Client::RefreshLiveItemTree(EQ::ItemInstance* inst) +{ + if (!inst) { + return false; + } + + bool refreshed = RefreshLiveItem(inst); + auto *contents = inst->GetContents(); + if (!contents) { + return refreshed; + } + + for (auto &entry : *contents) { + refreshed = RefreshLiveItemTree(entry.second) || refreshed; + } + + return refreshed; +} + bool Client::IsValidSlot(uint32 slot) { if (slot <= EQ::invslot::POSSESSIONS_END && slot >= EQ::invslot::POSSESSIONS_BEGIN) { return ((((uint64)1 << slot) & GetInv().GetLookup()->PossessionsBitmask) != 0); @@ -3006,6 +3041,8 @@ void Client::SendItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPac } } + RefreshLiveItemTree(const_cast(inst)); + // Serialize item into |-delimited string (Titanium- uses '|' delimiter .. newer clients use pure data serialization) std::string packet = inst->Serialize(slot_id); diff --git a/zone/lua_iteminst.cpp b/zone/lua_iteminst.cpp index 65c3d6d743..c0f8a825a0 100644 --- a/zone/lua_iteminst.cpp +++ b/zone/lua_iteminst.cpp @@ -248,6 +248,46 @@ void Lua_ItemInst::DeleteCustomData(const std::string& identifier) { self->DeleteCustomData(identifier); } +void Lua_ItemInst::SetDynamicItemModifier(const std::string& identifier, int value) { + Lua_Safe_Call_Void(); + self->SetDynamicItemModifier(identifier, value); +} + +void Lua_ItemInst::SetDynamicItemData(const std::string& identifier, const std::string& value) { + Lua_Safe_Call_Void(); + self->SetDynamicItemData(identifier, value); +} + +void Lua_ItemInst::SetDynamicItemData(const std::string& identifier, int value) { + Lua_Safe_Call_Void(); + self->SetDynamicItemData(identifier, value); +} + +void Lua_ItemInst::DeleteDynamicItemModifier(const std::string& identifier) { + Lua_Safe_Call_Void(); + self->DeleteDynamicItemModifier(identifier); +} + +void Lua_ItemInst::DeleteDynamicItemData(const std::string& identifier) { + Lua_Safe_Call_Void(); + self->DeleteDynamicItemData(identifier); +} + +void Lua_ItemInst::ClearDynamicItemData() { + Lua_Safe_Call_Void(); + self->ClearDynamicItemData(); +} + +bool Lua_ItemInst::HasDynamicItemData() { + Lua_Safe_Call_Bool(); + return self->HasDynamicItemData(); +} + +void Lua_ItemInst::RebuildDynamicItemData() { + Lua_Safe_Call_Void(); + self->RebuildDynamicItemData(); +} + void Lua_ItemInst::SetScale(double scale_factor) { Lua_Safe_Call_Void(); self->SetExp((int)(scale_factor*10000+.5)); @@ -472,10 +512,13 @@ luabind::scope lua_register_iteminst() { .def("AddExp", (void(Lua_ItemInst::*)(uint32))&Lua_ItemInst::AddExp) .def("AddEvolveAmount", (void(Lua_ItemInst::*)(uint64))&Lua_ItemInst::AddEvolveAmount) .def("ClearTimers", (void(Lua_ItemInst::*)(void))&Lua_ItemInst::ClearTimers) + .def("ClearDynamicItemData", (void(Lua_ItemInst::*)(void))&Lua_ItemInst::ClearDynamicItemData) .def("Clone", (Lua_ItemInst(Lua_ItemInst::*)(void))&Lua_ItemInst::Clone) .def("ContainsAugmentByID", (bool(Lua_ItemInst::*)(uint32))&Lua_ItemInst::ContainsAugmentByID) .def("CountAugmentByID", (int(Lua_ItemInst::*)(uint32))&Lua_ItemInst::CountAugmentByID) .def("DeleteCustomData", (void(Lua_ItemInst::*)(const std::string &))&Lua_ItemInst::DeleteCustomData) + .def("DeleteDynamicItemData", (void(Lua_ItemInst::*)(const std::string &))&Lua_ItemInst::DeleteDynamicItemData) + .def("DeleteDynamicItemModifier", (void(Lua_ItemInst::*)(const std::string &))&Lua_ItemInst::DeleteDynamicItemModifier) .def("GetAugment", (Lua_ItemInst(Lua_ItemInst::*)(int))&Lua_ItemInst::GetAugment) .def("GetAugmentEvolveUniqueID", (uint32(Lua_ItemInst::*)(uint8))&Lua_ItemInst::GetAugmentEvolveUniqueID) .def("GetAugmentIDs", (luabind::object(Lua_ItemInst::*)(lua_State*))&Lua_ItemInst::GetAugmentIDs) @@ -518,6 +561,7 @@ luabind::scope lua_register_iteminst() { .def("IsEquipable", (bool(Lua_ItemInst::*)(uint16,uint16))&Lua_ItemInst::IsEquipable) .def("IsEvolving", (bool(Lua_ItemInst::*)(void))&Lua_ItemInst::IsEvolving) .def("IsExpendable", (bool(Lua_ItemInst::*)(void))&Lua_ItemInst::IsExpendable) + .def("HasDynamicItemData", (bool(Lua_ItemInst::*)(void))&Lua_ItemInst::HasDynamicItemData) .def("IsInstNoDrop", (bool(Lua_ItemInst::*)(void))&Lua_ItemInst::IsInstNoDrop) .def("IsStackable", (bool(Lua_ItemInst::*)(void))&Lua_ItemInst::IsStackable) .def("IsType", (bool(Lua_ItemInst::*)(int))&Lua_ItemInst::IsType) @@ -525,6 +569,7 @@ luabind::scope lua_register_iteminst() { .def("ItemSay", (void(Lua_ItemInst::*)(const char*))&Lua_ItemInst::ItemSay) .def("ItemSay", (void(Lua_ItemInst::*)(const char*, uint8))&Lua_ItemInst::ItemSay) .def("RemoveTaskDeliveredItems", &Lua_ItemInst::RemoveTaskDeliveredItems) + .def("RebuildDynamicItemData", (void(Lua_ItemInst::*)(void))&Lua_ItemInst::RebuildDynamicItemData) .def("SetAttuned", (void(Lua_ItemInst::*)(bool))&Lua_ItemInst::SetAttuned) .def("SetCharges", (void(Lua_ItemInst::*)(int))&Lua_ItemInst::SetCharges) .def("SetColor", (void(Lua_ItemInst::*)(uint32))&Lua_ItemInst::SetColor) @@ -532,6 +577,9 @@ luabind::scope lua_register_iteminst() { .def("SetCustomData", (void(Lua_ItemInst::*)(const std::string&,float))&Lua_ItemInst::SetCustomData) .def("SetCustomData", (void(Lua_ItemInst::*)(const std::string&,int))&Lua_ItemInst::SetCustomData) .def("SetCustomData", (void(Lua_ItemInst::*)(const std::string&,const std::string&))&Lua_ItemInst::SetCustomData) + .def("SetDynamicItemData", (void(Lua_ItemInst::*)(const std::string&,int))&Lua_ItemInst::SetDynamicItemData) + .def("SetDynamicItemData", (void(Lua_ItemInst::*)(const std::string&,const std::string&))&Lua_ItemInst::SetDynamicItemData) + .def("SetDynamicItemModifier", (void(Lua_ItemInst::*)(const std::string&,int))&Lua_ItemInst::SetDynamicItemModifier) .def("SetEvolveAmount", (void(Lua_ItemInst::*)(uint64))&Lua_ItemInst::SetEvolveAmount) .def("SetEvolveProgression", (void(Lua_ItemInst::*)(float))&Lua_ItemInst::SetEvolveProgression) .def("SetExp", (void(Lua_ItemInst::*)(uint32))&Lua_ItemInst::SetExp) diff --git a/zone/lua_iteminst.h b/zone/lua_iteminst.h index c0cdf337d3..ac55fd625d 100644 --- a/zone/lua_iteminst.h +++ b/zone/lua_iteminst.h @@ -89,6 +89,14 @@ class Lua_ItemInst : public Lua_Ptr void SetCustomData(const std::string &identifier, bool value); std::string GetCustomData(const std::string& identifier); void DeleteCustomData(const std::string& identifier); + void SetDynamicItemModifier(const std::string &identifier, int value); + void SetDynamicItemData(const std::string &identifier, const std::string &value); + void SetDynamicItemData(const std::string &identifier, int value); + void DeleteDynamicItemModifier(const std::string &identifier); + void DeleteDynamicItemData(const std::string &identifier); + void ClearDynamicItemData(); + bool HasDynamicItemData(); + void RebuildDynamicItemData(); void SetScaling(bool v); void SetScale(double scale_factor); uint32 GetExp(); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 012d96d463..d50598f7f7 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -30,6 +30,11 @@ void Perl_Client_SendSound(Client* self) // @categories Script Utility self->SendSound(); } +void Perl_Client_SendItemScale(Client* self, EQ::ItemInstance* inst) // @categories Inventory and Items +{ + self->SendItemScale(inst); +} + bool Perl_Client_Save(Client* self, uint8 commit_now) // @categories Script Utility { return self->Save(commit_now); @@ -3813,6 +3818,7 @@ void perl_register_client() package.add("SendMarqueeMessage", (void(*)(Client*, uint32, std::string))&Perl_Client_SendMarqueeMessage); package.add("SendMarqueeMessage", (void(*)(Client*, uint32, std::string, uint32))&Perl_Client_SendMarqueeMessage); package.add("SendMarqueeMessage", (void(*)(Client*, uint32, uint32, uint32, uint32, uint32, std::string))&Perl_Client_SendMarqueeMessage); + package.add("SendItemScale", &Perl_Client_SendItemScale); package.add("SendOPTranslocateConfirm", &Perl_Client_SendOPTranslocateConfirm); package.add("SendPayload", (void(*)(Client*, int))&Perl_Client_SendPayload); package.add("SendPayload", (void(*)(Client*, int, std::string))&Perl_Client_SendPayload); diff --git a/zone/perl_questitem.cpp b/zone/perl_questitem.cpp index 800e1a0e7f..580ae2319d 100644 --- a/zone/perl_questitem.cpp +++ b/zone/perl_questitem.cpp @@ -123,6 +123,46 @@ void Perl_QuestItem_DeleteCustomData(EQ::ItemInstance* self, std::string identif self->DeleteCustomData(identifier); } +void Perl_QuestItem_SetDynamicItemModifier(EQ::ItemInstance* self, std::string identifier, int value) +{ + self->SetDynamicItemModifier(identifier, value); +} + +void Perl_QuestItem_SetDynamicItemData(EQ::ItemInstance* self, std::string identifier, int value) +{ + self->SetDynamicItemData(identifier, value); +} + +void Perl_QuestItem_SetDynamicItemData(EQ::ItemInstance* self, std::string identifier, std::string value) +{ + self->SetDynamicItemData(identifier, value); +} + +void Perl_QuestItem_DeleteDynamicItemModifier(EQ::ItemInstance* self, std::string identifier) +{ + self->DeleteDynamicItemModifier(identifier); +} + +void Perl_QuestItem_DeleteDynamicItemData(EQ::ItemInstance* self, std::string identifier) +{ + self->DeleteDynamicItemData(identifier); +} + +void Perl_QuestItem_ClearDynamicItemData(EQ::ItemInstance* self) +{ + self->ClearDynamicItemData(); +} + +bool Perl_QuestItem_HasDynamicItemData(EQ::ItemInstance* self) +{ + return self->HasDynamicItemData(); +} + +void Perl_QuestItem_RebuildDynamicItemData(EQ::ItemInstance* self) +{ + self->RebuildDynamicItemData(); +} + uint32 Perl_QuestItem_GetAugmentItemID(EQ::ItemInstance* self, uint8 slot_id) { return self->GetAugmentItemID(slot_id); @@ -395,7 +435,10 @@ void perl_register_questitem() package.add("Clone", &Perl_QuestItem_Clone); package.add("ContainsAugmentByID", &Perl_QuestItem_ContainsAugmentByID); package.add("CountAugmentByID", &Perl_QuestItem_CountAugmentByID); + package.add("ClearDynamicItemData", &Perl_QuestItem_ClearDynamicItemData); package.add("DeleteCustomData", &Perl_QuestItem_DeleteCustomData); + package.add("DeleteDynamicItemData", &Perl_QuestItem_DeleteDynamicItemData); + package.add("DeleteDynamicItemModifier", &Perl_QuestItem_DeleteDynamicItemModifier); package.add("GetAugment", &Perl_QuestItem_GetAugment); package.add("GetAugmentEvolveUniqueID", &Perl_QuestItem_GetAugmentEvolveUniqueID); package.add("GetAugmentIDs", &Perl_QuestItem_GetAugmentIDs); @@ -428,6 +471,7 @@ void perl_register_questitem() package.add("GetTaskDeliveredCount", &Perl_QuestItem_GetTaskDeliveredCount); package.add("GetTotalItemCount", &Perl_QuestItem_GetTotalItemCount); package.add("GetUnscaledItem", &Perl_QuestItem_GetUnscaledItem); + package.add("HasDynamicItemData", &Perl_QuestItem_HasDynamicItemData); package.add("IsAmmo", &Perl_QuestItem_IsAmmo); package.add("IsAttuned", &Perl_QuestItem_IsAttuned); package.add("IsAugmentable", &Perl_QuestItem_IsAugmentable); @@ -443,6 +487,7 @@ void perl_register_questitem() package.add("ItemSay", (void(*)(EQ::ItemInstance*, const char*))&Perl_QuestItem_ItemSay); package.add("ItemSay", (void(*)(EQ::ItemInstance*, const char*, uint8))&Perl_QuestItem_ItemSay); package.add("RemoveTaskDeliveredItems", &Perl_QuestItem_RemoveTaskDeliveredItems); + package.add("RebuildDynamicItemData", &Perl_QuestItem_RebuildDynamicItemData); package.add("SetAttuned", &Perl_QuestItem_SetAttuned); package.add("SetCharges", &Perl_QuestItem_SetCharges); package.add("SetColor", &Perl_QuestItem_SetColor); @@ -450,6 +495,9 @@ void perl_register_questitem() package.add("SetCustomData", (void(*)(EQ::ItemInstance*, std::string, float))&Perl_QuestItem_SetCustomData); package.add("SetCustomData", (void(*)(EQ::ItemInstance*, std::string, int))&Perl_QuestItem_SetCustomData); package.add("SetCustomData", (void(*)(EQ::ItemInstance*, std::string, std::string))&Perl_QuestItem_SetCustomData); + package.add("SetDynamicItemData", (void(*)(EQ::ItemInstance*, std::string, int))&Perl_QuestItem_SetDynamicItemData); + package.add("SetDynamicItemData", (void(*)(EQ::ItemInstance*, std::string, std::string))&Perl_QuestItem_SetDynamicItemData); + package.add("SetDynamicItemModifier", &Perl_QuestItem_SetDynamicItemModifier); package.add("SetEvolveAmount", &Perl_QuestItem_SetEvolveAmount); package.add("SetEvolveProgression", &Perl_QuestItem_SetEvolveProgression); package.add("SetEXP", &Perl_QuestItem_SetEXP); From 57e65f2cc49029feaf46674ca113d8a5edc2685c Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Sat, 23 May 2026 23:17:13 -0700 Subject: [PATCH 121/194] Add standalone Live Spells feature branch --- .../ui/EQUI_NativeSpellForgeWnd.xml | 576 +++++++++++ docs/live-spells.md | 32 + features/README.md | 1 + features/live-spells/MANIFEST.md | 56 + features/live-spells/README.md | 49 + .../sql/001_live_spell_runtime_rules.sql | 13 + zone/CMakeLists.txt | 2 + zone/client_process.cpp | 2 + zone/command.cpp | 1 + zone/command.h | 1 + zone/gm_commands/livespell.cpp | 974 ++++++++++++++++++ zone/live_spell_manager.h | 31 + zone/spells.cpp | 3 + 13 files changed, 1741 insertions(+) create mode 100644 client_files/native_autoloot/ui/EQUI_NativeSpellForgeWnd.xml create mode 100644 docs/live-spells.md create mode 100644 features/live-spells/MANIFEST.md create mode 100644 features/live-spells/README.md create mode 100644 features/live-spells/sql/001_live_spell_runtime_rules.sql create mode 100644 zone/gm_commands/livespell.cpp create mode 100644 zone/live_spell_manager.h diff --git a/client_files/native_autoloot/ui/EQUI_NativeSpellForgeWnd.xml b/client_files/native_autoloot/ui/EQUI_NativeSpellForgeWnd.xml new file mode 100644 index 0000000000..a8854d9737 --- /dev/null +++ b/client_files/native_autoloot/ui/EQUI_NativeSpellForgeWnd.xml @@ -0,0 +1,576 @@ + + + + + + + + + + + + + + + + + + ASFW_NameEdit + WDT_Inner + true + true + 9614 + 33024 + Frost Lash + 255255255 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ASFW_FormPage + true + 1258 + 596280 + true + false + ASFW_NameLabel + ASFW_NameEdit + ASFW_ElementLabel + ASFW_FireButton + ASFW_ColdButton + ASFW_MagicButton + ASFW_PoisonButton + ASFW_DiseaseButton + ASFW_ElementHintLabel + + + + ASFW_DeliveryPage + true + 1258 + 596280 + true + false + ASFW_TargetButton + ASFW_AEButton + ASFW_PBAEButton + ASFW_RangeLabel + ASFW_RangeMinusButton + ASFW_RangeValueLabel + ASFW_RangePlusButton + ASFW_RadiusLabel + ASFW_RadiusValueLabel + ASFW_TargetHintLabel + + + + ASFW_PowerPage + true + 1258 + 596280 + true + false + ASFW_DamageLabel + ASFW_DamageMinusButton + ASFW_DamageValueLabel + ASFW_DamagePlusButton + ASFW_ManaLabel + ASFW_ManaValueLabel + ASFW_PowerHintLabel + + + + ASFW_CastingPage + true + 1258 + 596280 + true + false + ASFW_RecastLabel + ASFW_RecastMinusButton + ASFW_RecastValueLabel + ASFW_RecastPlusButton + ASFW_CastLabel + ASFW_CastValueLabel + ASFW_CastingHintLabel + + + + ASFW_ReviewPage + true + 1258 + 596280 + true + false + ASFW_ReviewTitleLabel + ASFW_ReviewNameLabel + ASFW_ReviewFormLabel + ASFW_ReviewDeliveryLabel + ASFW_ReviewPowerLabel + ASFW_ReviewCastingLabel + ASFW_CreateButton + + + + + + NativeSpellForgeWnd + false + 12090 + 620410 + Spell Forge + false + true + true + false + true + false + WDT_Rounded + ASFW_FormTab + ASFW_DeliveryTab + ASFW_PowerTab + ASFW_CastingTab + ASFW_ReviewTab + ASFW_FormPage + ASFW_DeliveryPage + ASFW_PowerPage + ASFW_CastingPage + ASFW_ReviewPage + ASFW_StatusLabel + + diff --git a/docs/live-spells.md b/docs/live-spells.md new file mode 100644 index 0000000000..ca29adcebe --- /dev/null +++ b/docs/live-spells.md @@ -0,0 +1,32 @@ +# Live Spells + +Live Spells lets an operator generate spell definitions and matching scroll items at runtime, then sync those definitions to a native client window/transport. + +## Server Flow + +1. A player opens the Spell Forge with `#livespell dialog`. +2. The native window submits a `#livespell craft ...` command. +3. The server chooses a free spell ID in the reserved range, builds a spell definition, creates a matching scroll item, and stores the definition in `data_buckets`. +4. Zones load persisted definitions on demand before cast, scribe, or memorize paths need spell data. +5. The client receives `LIVESPELL|upsert|...` lines so the native DLL can patch its local spell table. + +## Persistence + +- Spell definitions use `data_buckets` keys under `live_spell.spell.`. +- The next generated scroll item pointer uses `live_spell.next_scroll_item_id`. +- Generated scroll item rows use the existing `items` table. + +## Commands + +- `#livespell dialog` +- `#livespell craft element=fire target=target range=200 damage=100 recast=3000 name=Test_Flame` +- `#livespell ready` +- `#livespell patch [spell_id] [base_spell_id]` +- `#livespell test [spell_id] [base_spell_id] [gem]` +- `#livespell scribe [spell_id] [gem]` + +## Client Assets + +Deploy `client_files/native_autoloot/ui/EQUI_NativeSpellForgeWnd.xml` to the target client UI folder and include it from `EQUI.xml`. + +The XML is standalone, but the current native DLL code that listens for `LIVESPELL|...` is still shared with the lab native-client runtime. diff --git a/features/README.md b/features/README.md index acd235aef1..558317fd6c 100644 --- a/features/README.md +++ b/features/README.md @@ -17,6 +17,7 @@ These are not runtime plugins. Each feature pack documents the source files, dat | --- | --- | --- | | `autoloot` | `draft`, `shared-runtime`, `proved-build` | Server-side AutoLoot with the native EQ AutoLoot window. Client DLL code is still partly bundled with other native windows. | | `live-items` | `draft`, `shared-runtime`, `proved-build` | Live DB item loading, dynamic item data, item editing, and Item Forge input. Native DLL code is still shared runtime. | +| `live-spells` | `draft`, `shared-runtime`, `proved-build` | Generated spell definitions, Spell Forge input, live spell patch/sync transport, and generated scroll items. Native DLL code is still shared runtime. | ## Packaging Rules diff --git a/features/live-spells/MANIFEST.md b/features/live-spells/MANIFEST.md new file mode 100644 index 0000000000..85c33ac849 --- /dev/null +++ b/features/live-spells/MANIFEST.md @@ -0,0 +1,56 @@ +# Live Spells Manifest + +This manifest lists the files and hook points that make up the standalone Live Spells feature. + +## Added Server Files + +- `zone/gm_commands/livespell.cpp` +- `zone/live_spell_manager.h` +- `docs/live-spells.md` + +## Existing Server Files To Patch + +| File | Purpose | +| --- | --- | +| `common/shareddb.cpp` | Add live item lookup, cache, and DB fallback for generated scroll items. | +| `common/shareddb.h` | Declare live item cache APIs. | +| `common/ruletypes.h` | Add Live Item range and polling rules used by generated scroll items. | +| `world/world_boot.cpp` | Preserve shared item count before live fallback is enabled. | +| `zone/CMakeLists.txt` | Build `livespell.cpp` and list `live_spell_manager.h`. | +| `zone/command.cpp` | Register `#livespell`. | +| `zone/command.h` | Declare the Live Spells command handler. | +| `zone/spells.cpp` | Ensure persisted live spell definitions are loaded before casting. | +| `zone/client_process.cpp` | Ensure persisted live spell definitions are loaded before scribing/memorizing. | + +## Database Objects + +No custom tables are required. Live Spells use existing `items`, `rule_values`, and `data_buckets` tables. + +Optional rules SQL lives in: + +- `features/live-spells/sql/001_live_spell_runtime_rules.sql` + +## Native Client Assets + +| File | Purpose | +| --- | --- | +| `client_files/native_autoloot/ui/EQUI_NativeSpellForgeWnd.xml` | Native SIDL window layout for Spell Forge input. | +| `client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h` | Not included in this proof branch. The current implementation is still shared runtime code and needs a `native-client-base` split. | + +## Commands + +- `#livespell dialog` +- `#livespell craft [fire|cold|magic|poison|disease] [target|ae|pbae] [range] [damage] [recast_ms]` +- `#livespell craft element=cold target=ae range=200 damage=100 recast=3000 name=Frost_Burst` +- `#livespell ready` +- `#livespell ack [spell_id] [version]` +- `#livespell patch [spell_id] [base_spell_id]` +- `#livespell test [spell_id] [base_spell_id] [gem]` +- `#livespell scribe [spell_id] [gem]` + +## Native Transport + +- `LIVESPELL|ui|open|...` +- `LIVESPELL|upsert|...` + +The server owns spell generation, scroll creation, and validation. The native window is only an input surface. diff --git a/features/live-spells/README.md b/features/live-spells/README.md new file mode 100644 index 0000000000..695029e51d --- /dev/null +++ b/features/live-spells/README.md @@ -0,0 +1,49 @@ +# Live Spells Feature Pack + +Status: `draft`, `shared-runtime`, `proved-build` + +This pack describes the Live Spells system: generated spell definitions, generated scroll items, server-side spell patching, and the native Spell Forge input window. + +## What This Feature Owns + +- Reserved spell ID range `42500-42602` for generated spells. +- Generated spell definitions persisted in `data_buckets`. +- Server-side spell array patching when a zone first needs live spell data. +- Generated scroll items stored in `items`. +- Live item lookup support needed by generated scroll item IDs. +- `#livespell` command paths for dialog, crafting, sync, GM patch/test, and scribing. +- Native Spell Forge UI transport using `LIVESPELL|...` lines. + +## What This Feature Does Not Require + +- AutoLoot. +- Item Forge or item editing commands. +- Achievements. +- MacroQuest, Lua, ImGui, or overlay UI code. + +## Dependencies + +- EQEmu source rebuild. +- Blank spell rows in the reserved generated spell range. +- `rule_values` rows if the operator wants to override the generated scroll item live range. +- The native client DLL host if the operator wants the in-client Spell Forge window. + +## Install Outline + +1. Apply the source files and hook patches listed in `MANIFEST.md`. +2. Optionally apply `sql/001_live_spell_runtime_rules.sql` to make generated scroll item live lookup explicit. +3. Rebuild `zone` and `world`. +4. Deploy `EQUI_NativeSpellForgeWnd.xml` and include it from the target client's `EQUI.xml`. +5. Use `#livespell dialog`, then craft a generated spell scroll. + +## Smoke Test + +1. Run `#livespell dialog` and confirm the native client receives the Spell Forge open line. +2. Run `#livespell craft element=fire target=target range=200 damage=100 recast=3000 name=Test_Flame`. +3. Confirm a generated scroll item is created in the live item range and placed on the cursor. +4. Scribe the scroll, memorize the generated spell, then cast it. +5. Restart a zone and confirm `#livespell ready` resyncs persisted generated spells. + +## Current Shared-Runtime Caveat + +This branch includes the native Spell Forge XML only. The C++ DLL implementation is still in the lab branch's shared native-client runtime header and should be split into `native-client-base` plus feature-specific native window code. diff --git a/features/live-spells/sql/001_live_spell_runtime_rules.sql b/features/live-spells/sql/001_live_spell_runtime_rules.sql new file mode 100644 index 0000000000..66c0c7898f --- /dev/null +++ b/features/live-spells/sql/001_live_spell_runtime_rules.sql @@ -0,0 +1,13 @@ +-- Optional explicit runtime rule values for Live Spells generated scroll items. +-- Live Spells persist spell definitions in data_buckets and generated scrolls in items. +-- The source feature also provides defaults in common/ruletypes.h. + +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) +VALUES +(1, 'Items:LiveItemLoading', 'true', 'Enable live DB item fallback for generated spell scrolls'), +(1, 'Items:LiveItemMinID', '900000', 'First generated scroll item ID'), +(1, 'Items:LiveItemMaxID', '999999', 'Last generated scroll item ID'), +(1, 'Items:LiveItemPollIntervalSeconds', '1', 'Generated scroll item DB poll interval') +ON DUPLICATE KEY UPDATE +`rule_value` = VALUES(`rule_value`), +`notes` = VALUES(`notes`); diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 07549f2d4c..9598eb3164 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -165,6 +165,7 @@ set(zone_headers lua_entity_list.h lua_expedition.h lua_general.h + live_spell_manager.h lua_group.h lua_hate_list.h lua_inventory.h @@ -467,6 +468,7 @@ set(gm_command_sources gm_commands/killallnpcs.cpp gm_commands/list.cpp gm_commands/liveitem.cpp + gm_commands/livespell.cpp gm_commands/loc.cpp gm_commands/logs.cpp gm_commands/lootsim.cpp diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 2fc5518301..03e3cdaf9b 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -33,6 +33,7 @@ #include "zone/dynamic_zone.h" #include "zone/event_codes.h" #include "zone/guild_mgr.h" +#include "zone/live_spell_manager.h" #include "zone/map.h" #include "zone/petitions.h" #include "zone/queryserv.h" @@ -1155,6 +1156,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) } const auto* m = (MemorizeSpell_Struct*) app->pBuffer; + LiveSpellManager::EnsureServerLoaded(); if (!IsValidSpell(m->spell_id)) { Message( diff --git a/zone/command.cpp b/zone/command.cpp index 96b6d382cf..437416ccda 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -174,6 +174,7 @@ int command_init(void) command_add("list", "[npcs|players|corpses|doors|objects] [search] - Search entities", AccountStatus::ApprenticeGuide, command_list) || command_add("lootfilter", "[include|exclude|remove|list|mode] - Manage AutoLoot item filters", AccountStatus::Player, command_lootfilter) || command_add("liveitem", "[status|clear|clone|summon|bump] - Manage live database item testing and cache state", AccountStatus::GMMgmt, command_liveitem) || + command_add("livespell", "[dialog|craft|test|patch|scribe|ack|ready] - Prototype live generated spell sync", AccountStatus::Player, command_livespell) || command_add("lootsim", "[npc_type_id] [loottable_id] [iterations] - Runs benchmark simulations using real loot logic to report numbers and data", AccountStatus::GMImpossible, command_lootsim) || command_add("load_shared_memory", "[shared_memory_name] - Reloads shared memory and uses the input as output", AccountStatus::GMImpossible, command_load_shared_memory) || command_add("loc", "Print out your or your target's current location and heading", AccountStatus::Player, command_loc) || diff --git a/zone/command.h b/zone/command.h index 542f3f1a86..bd1fa7a0a4 100644 --- a/zone/command.h +++ b/zone/command.h @@ -135,6 +135,7 @@ void command_kill(Client *c, const Seperator *sep); void command_list(Client *c, const Seperator *sep); void command_lootfilter(Client *c, const Seperator *sep); void command_liveitem(Client *c, const Seperator *sep); +void command_livespell(Client *c, const Seperator *sep); void command_lootsim(Client *c, const Seperator *sep); void command_load_shared_memory(Client *c, const Seperator *sep); void command_loc(Client *c, const Seperator *sep); diff --git a/zone/gm_commands/livespell.cpp b/zone/gm_commands/livespell.cpp new file mode 100644 index 0000000000..d57956a44a --- /dev/null +++ b/zone/gm_commands/livespell.cpp @@ -0,0 +1,974 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. +*/ +#include "common/data_bucket.h" +#include "common/item_data.h" +#include "common/ipc_mutex.h" +#include "common/json/json.hpp" +#include "common/repositories/data_buckets_repository.h" +#include "common/repositories/items_repository.h" +#include "common/rulesys.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/live_spell_manager.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using json = nlohmann::json; + +namespace { + constexpr uint16 LiveSpellDefaultID = 42527; + constexpr uint16 LiveSpellDefaultBaseID = 93; // Burst of Flame in stock spell files + constexpr int LiveSpellDefaultGem = 0; + constexpr uint16 LiveSpellReserveMinID = 42500; + constexpr uint16 LiveSpellReserveMaxID = 42602; + constexpr uint32 LiveSpellBaseScrollID = 15205; + constexpr const char *LiveSpellBucketPrefix = "live_spell.spell."; + constexpr const char *LiveSpellNextScrollBucket = "live_spell.next_scroll_item_id"; + bool gLiveSpellServerLoaded = false; + + struct LiveSpellElement { + const char *key; + const char *label; + const char *noun; + int resist_type; + int icon; + }; + + struct LiveSpellTarget { + const char *key; + const char *label; + SpellTargetType target_type; + float aoe_range; + }; + + struct LiveSpellDefinition { + uint16 spell_id = 0; + uint16 base_spell_id = LiveSpellDefaultBaseID; + uint32 scroll_item_id = 0; + uint32 owner_character_id = 0; + uint32 class_mask = 0; + uint32 version = 0; + std::string name; + std::string element; + std::string target; + int target_type = ST_Target; + int resist_type = RESIST_FIRE; + int range = 200; + int aoe_range = 0; + int damage = 100; + int mana = 20; + int cast_time = 2500; + int recovery_time = 1500; + int recast_time = 3000; + int icon = 28; + int book_icon = 28; + int level = 1; + }; + + const std::array LiveSpellElements = {{ + {"fire", "Fire", "Ember", RESIST_FIRE, 28}, + {"cold", "Cold", "Frost", RESIST_COLD, 31}, + {"magic", "Magic", "Arcane", RESIST_MAGIC, 44}, + {"poison", "Poison", "Venom", RESIST_POISON, 47}, + {"disease", "Disease", "Blight", RESIST_DISEASE, 56}, + }}; + + const std::array LiveSpellTargets = {{ + {"target", "Single Target", ST_Target, 0.0f}, + {"ae", "Targeted AE", ST_AETarget, 35.0f}, + {"pbae", "Point Blank AE", ST_AECaster, 35.0f}, + }}; + + bool IsLiveSpellSlotUsable(Client *c, uint32 spell_id, uint32 base_spell_id); + uint32 BuildLiveSpellVersion(); + + template + void CopySpellText(char (&destination)[Size], const std::string &source) + { + std::memset(destination, 0, Size); + std::strncpy(destination, source.c_str(), Size - 1); + } + + std::string SanitizeLiveSpellText(const std::string &value, const size_t max_length) + { + std::string sanitized; + sanitized.reserve(std::min(value.size(), max_length)); + + for (const auto ch : value) { + if (ch == '|' || ch == '=') { + continue; + } + + sanitized.push_back(ch); + if (sanitized.size() >= max_length) { + break; + } + } + + return sanitized; + } + + std::string TrimLiveSpellText(std::string value) + { + while (!value.empty() && std::isspace(static_cast(value.front()))) { + value.erase(value.begin()); + } + + while (!value.empty() && std::isspace(static_cast(value.back()))) { + value.pop_back(); + } + + return value; + } + + std::string DecodeLiveSpellCommandText(const std::string &value) + { + std::string decoded; + decoded.reserve(std::min(value.size(), 60)); + + for (const auto raw_ch : value) { + const auto ch = raw_ch == '_' ? ' ' : raw_ch; + const bool alpha = (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); + const bool digit = ch >= '0' && ch <= '9'; + const bool separator = ch == ' ' || ch == '-' || ch == '\''; + if (!alpha && !digit && !separator) { + continue; + } + + if (std::isspace(static_cast(ch))) { + if (decoded.empty() || decoded.back() == ' ') { + continue; + } + + decoded.push_back(' '); + } else { + decoded.push_back(ch); + } + + if (decoded.size() >= 60) { + break; + } + } + + return TrimLiveSpellText(decoded); + } + + bool HasLiveSpellNamedArgs(const Seperator *sep) + { + for (int index = 2; index <= sep->argnum; ++index) { + if (std::strchr(sep->arg[index], '=')) { + return true; + } + } + + return false; + } + + std::string GetLiveSpellNamedArg(const Seperator *sep, const std::string &key) + { + const auto wanted = Strings::ToLower(key); + for (int index = 2; index <= sep->argnum; ++index) { + const std::string token = sep->arg[index]; + const auto separator = token.find('='); + if (separator == std::string::npos) { + continue; + } + + if (Strings::ToLower(token.substr(0, separator)) == wanted) { + return token.substr(separator + 1); + } + } + + return {}; + } + + int GetLiveSpellNamedInt(const Seperator *sep, const std::string &key, const int fallback) + { + const auto value = GetLiveSpellNamedArg(sep, key); + return value.empty() ? fallback : Strings::ToInt(value); + } + + std::string GetLiveSpellPairValue(const std::string &payload, const std::string &key) + { + const auto prefix = key + "="; + size_t pos = 0; + + while (pos < payload.size()) { + const auto end = payload.find('|', pos); + const auto count = end == std::string::npos ? std::string::npos : end - pos; + const auto part = payload.substr(pos, count); + + if (part.compare(0, prefix.size(), prefix) == 0) { + return part.substr(prefix.size()); + } + + if (end == std::string::npos) { + break; + } + + pos = end + 1; + } + + return {}; + } + + int GetLiveSpellPairInt(const std::string &payload, const std::string &key, const int fallback = 0) + { + const auto value = GetLiveSpellPairValue(payload, key); + return value.empty() ? fallback : Strings::ToInt(value); + } + + const LiveSpellElement &ResolveLiveSpellElement(const std::string &element) + { + const auto key = Strings::ToLower(element); + for (const auto &entry : LiveSpellElements) { + if (key == entry.key) { + return entry; + } + } + + return LiveSpellElements.front(); + } + + const LiveSpellTarget &ResolveLiveSpellTarget(const std::string &target) + { + const auto key = Strings::ToLower(target); + for (const auto &entry : LiveSpellTargets) { + if (key == entry.key) { + return entry; + } + } + + return LiveSpellTargets.front(); + } + + std::string SerializeLiveSpellDefinition(const LiveSpellDefinition &spell) + { + return fmt::format( + "spell_id={}|base={}|scroll={}|owner={}|class_mask={}|version={}|name={}|element={}|target={}|target_type={}|range={}|aoe_range={}|damage={}|mana={}|cast={}|recovery={}|recast={}|resist={}|icon={}|book_icon={}|level={}", + spell.spell_id, + spell.base_spell_id, + spell.scroll_item_id, + spell.owner_character_id, + spell.class_mask, + spell.version, + SanitizeLiveSpellText(spell.name, 60), + SanitizeLiveSpellText(spell.element, 16), + SanitizeLiveSpellText(spell.target, 16), + spell.target_type, + spell.range, + spell.aoe_range, + spell.damage, + spell.mana, + spell.cast_time, + spell.recovery_time, + spell.recast_time, + spell.resist_type, + spell.icon, + spell.book_icon, + spell.level + ); + } + + LiveSpellDefinition ParseLiveSpellDefinition(const std::string &payload) + { + LiveSpellDefinition spell; + spell.spell_id = static_cast(GetLiveSpellPairInt(payload, "spell_id")); + spell.base_spell_id = static_cast(GetLiveSpellPairInt(payload, "base", LiveSpellDefaultBaseID)); + spell.scroll_item_id = static_cast(GetLiveSpellPairInt(payload, "scroll")); + spell.owner_character_id = static_cast(GetLiveSpellPairInt(payload, "owner")); + spell.class_mask = static_cast(GetLiveSpellPairInt(payload, "class_mask")); + spell.version = static_cast(GetLiveSpellPairInt(payload, "version")); + spell.name = GetLiveSpellPairValue(payload, "name"); + spell.element = GetLiveSpellPairValue(payload, "element"); + spell.target = GetLiveSpellPairValue(payload, "target"); + spell.target_type = GetLiveSpellPairInt(payload, "target_type", ST_Target); + spell.range = GetLiveSpellPairInt(payload, "range", 200); + spell.aoe_range = GetLiveSpellPairInt(payload, "aoe_range"); + spell.damage = GetLiveSpellPairInt(payload, "damage", 100); + spell.mana = GetLiveSpellPairInt(payload, "mana", 20); + spell.cast_time = GetLiveSpellPairInt(payload, "cast", 2500); + spell.recovery_time = GetLiveSpellPairInt(payload, "recovery", 1500); + spell.recast_time = GetLiveSpellPairInt(payload, "recast", 3000); + spell.resist_type = GetLiveSpellPairInt(payload, "resist", RESIST_FIRE); + spell.icon = GetLiveSpellPairInt(payload, "icon", 28); + spell.book_icon = GetLiveSpellPairInt(payload, "book_icon", spell.icon); + spell.level = GetLiveSpellPairInt(payload, "level", 1); + return spell; + } + + void AddLiveSpellDefinition( + std::vector &definitions, + std::unordered_set &loaded_spell_ids, + const std::string &payload + ) + { + auto definition = ParseLiveSpellDefinition(payload); + if (!definition.spell_id || loaded_spell_ids.count(definition.spell_id)) { + return; + } + + loaded_spell_ids.insert(definition.spell_id); + definitions.emplace_back(std::move(definition)); + } + + std::vector LoadLiveSpellDefinitions() + { + std::vector definitions; + std::unordered_set loaded_spell_ids; + + const auto rows = DataBucketsRepository::GetWhere( + database, + fmt::format("`key` LIKE '{}%' ORDER BY `key`", LiveSpellBucketPrefix) + ); + + for (const auto &row : rows) { + AddLiveSpellDefinition(definitions, loaded_spell_ids, row.value); + } + + const auto nested_payload = DataBucket::GetData(&database, "live_spell.spell"); + if (!nested_payload.empty()) { + try { + const auto spell_payloads = json::parse(nested_payload); + if (spell_payloads.is_object()) { + for (const auto &entry : spell_payloads.items()) { + if (entry.value().is_string()) { + AddLiveSpellDefinition(definitions, loaded_spell_ids, entry.value().get()); + } + } + } + else if (spell_payloads.is_string()) { + AddLiveSpellDefinition(definitions, loaded_spell_ids, spell_payloads.get()); + } + } + catch (const json::exception&) { + AddLiveSpellDefinition(definitions, loaded_spell_ids, nested_payload); + } + } + + std::sort( + definitions.begin(), + definitions.end(), + [](const LiveSpellDefinition &lhs, const LiveSpellDefinition &rhs) { + return lhs.spell_id < rhs.spell_id; + } + ); + + return definitions; + } + + bool IsPersistedLiveSpellID(const uint16 spell_id) + { + if (!spell_id) { + return false; + } + + return !DataBucket::GetData(&database, fmt::format("{}{}", LiveSpellBucketPrefix, spell_id)).empty(); + } + + bool PatchServerLiveSpellDefinition(Client *c, const LiveSpellDefinition &definition) + { + if (!IsLiveSpellSlotUsable(c, definition.spell_id, definition.base_spell_id)) { + return false; + } + + EQ::IPCMutex mutex("spells"); + mutex.Lock(); + + auto *mutable_spells = const_cast(spells); + mutable_spells[definition.spell_id] = spells[definition.base_spell_id]; + + auto &spell = mutable_spells[definition.spell_id]; + spell.id = definition.spell_id; + CopySpellText(spell.name, definition.name); + CopySpellText(spell.player_1, "GEN"); + CopySpellText(spell.you_cast, fmt::format("You release {}.", definition.name)); + CopySpellText(spell.other_casts, fmt::format("$n releases {}.", definition.name)); + CopySpellText(spell.cast_on_you, fmt::format("{} hits you.", definition.name)); + CopySpellText(spell.cast_on_other, fmt::format("{} hits $n.", definition.name)); + CopySpellText(spell.spell_fades, fmt::format("{} fades.", definition.name)); + + spell.range = static_cast(definition.range); + spell.aoe_range = static_cast(definition.aoe_range); + spell.cast_time = definition.cast_time; + spell.recovery_time = definition.recovery_time; + spell.recast_time = definition.recast_time; + spell.buff_duration_formula = 0; + spell.buff_duration = 0; + spell.aoe_duration = 0; + spell.mana = definition.mana; + spell.good_effect = 0; + spell.activated = 1; + spell.resist_type = definition.resist_type; + spell.target_type = static_cast(definition.target_type); + spell.new_icon = definition.icon; + spell.resist_difficulty = 0; + + for (int index = 0; index < EFFECT_COUNT; ++index) { + spell.base_value[index] = 0; + spell.limit_value[index] = 0; + spell.max_value[index] = 0; + spell.formula[index] = 100; + spell.effect_id[index] = SpellEffect::Blank; + } + + spell.effect_id[0] = SpellEffect::CurrentHP; + spell.base_value[0] = -std::max(1, definition.damage); + + for (auto &level : spell.classes) { + level = 255; + } + + for (int class_id = 1; class_id <= Class::PLAYER_CLASS_COUNT; ++class_id) { + const auto class_bit = static_cast(1 << (class_id - 1)); + if (definition.class_mask & class_bit) { + spell.classes[class_id - 1] = static_cast(std::max(1, definition.level)); + } + } + + mutex.Unlock(); + return true; + } + + void PatchPersistedLiveSpells() + { + for (const auto &definition : LoadLiveSpellDefinitions()) { + PatchServerLiveSpellDefinition(nullptr, definition); + } + } + + std::string BuildLiveSpellClientPayload(const LiveSpellDefinition &definition) + { + return fmt::format( + "LIVESPELL|upsert|id={}|base={}|version={}|name={}|mana={}|cast={}|recovery={}|recast={}|range={}|aoe_range={}|icon={}|book_icon={}|level={}|target_type={}|resist={}|spell_type=0|effect0={}|base0={}|max0=0|calc0=100", + definition.spell_id, + definition.base_spell_id, + definition.version, + SanitizeLiveSpellText(definition.name, 60), + definition.mana, + definition.cast_time, + definition.recovery_time, + definition.recast_time, + definition.range, + definition.aoe_range, + definition.icon, + definition.book_icon, + definition.level, + definition.target_type, + definition.resist_type, + SpellEffect::CurrentHP, + -std::max(1, definition.damage) + ); + } + + void SendLiveSpellPatch(Client *c, const LiveSpellDefinition &definition) + { + c->Message(Chat::White, BuildLiveSpellClientPayload(definition).c_str()); + } + + uint16 FindFreeLiveSpellID() + { + if (!spells || SPDAT_RECORDS <= 0) { + return 0; + } + + const auto definitions = LoadLiveSpellDefinitions(); + std::unordered_set used_spell_ids; + for (const auto &definition : definitions) { + used_spell_ids.insert(definition.spell_id); + } + + const uint16 upper_bound = static_cast( + std::min(LiveSpellReserveMaxID, SPDAT_RECORDS > 0 ? static_cast(SPDAT_RECORDS - 1) : 0) + ); + + for (uint16 spell_id = LiveSpellReserveMinID; spell_id <= upper_bound; ++spell_id) { + if (used_spell_ids.count(spell_id)) { + continue; + } + + if (!spells || spells[spell_id].id == 0 || spells[spell_id].name[0] == '\0') { + return spell_id; + } + } + + return 0; + } + + uint32 FindFreeLiveScrollItemID() + { + const auto minimum = static_cast(std::max(1, RuleI(Items, LiveItemMinID))); + const auto maximum = static_cast(std::max(0, RuleI(Items, LiveItemMaxID))); + const auto definitions = LoadLiveSpellDefinitions(); + + std::unordered_set used_item_ids; + for (const auto &definition : definitions) { + used_item_ids.insert(definition.scroll_item_id); + } + + auto start = static_cast(Strings::ToUnsignedInt(DataBucket::GetData(&database, LiveSpellNextScrollBucket))); + if (start < minimum) { + start = minimum; + } + + for (uint32 item_id = start; item_id <= maximum || maximum == 0; ++item_id) { + if (maximum && item_id > maximum) { + break; + } + + if (used_item_ids.count(item_id)) { + continue; + } + + if (database.IsLiveItemID(item_id) && !ItemsRepository::FindOne(database, item_id).id) { + DataBucket::SetData(&database, LiveSpellNextScrollBucket, std::to_string(item_id + 1)); + return item_id; + } + + if (maximum == 0 && item_id == std::numeric_limits::max()) { + break; + } + } + + return 0; + } + + bool UpsertLiveSpellScrollItem(Client *c, const LiveSpellDefinition &definition) + { + auto base_scroll = ItemsRepository::FindOne(database, LiveSpellBaseScrollID); + if (!base_scroll.id) { + const auto matches = ItemsRepository::GetWhere( + database, + fmt::format("scrolleffect = {} AND itemtype = {} ORDER BY id LIMIT 1", definition.base_spell_id, static_cast(EQ::item::ItemTypeSpell)) + ); + if (!matches.empty()) { + base_scroll = matches.front(); + } + } + + if (!base_scroll.id) { + base_scroll = ItemsRepository::NewEntity(); + base_scroll.itemclass = EQ::item::ItemClassCommon; + base_scroll.itemtype = EQ::item::ItemTypeSpell; + base_scroll.classes = definition.class_mask; + base_scroll.races = 65535; + base_scroll.norent = 255; + base_scroll.nodrop = 0; + base_scroll.size = EQ::item::ItemSizeSmall; + base_scroll.icon = 778; + base_scroll.maxcharges = 1; + } + + const bool replacing = ItemsRepository::FindOne(database, definition.scroll_item_id).id != 0; + + base_scroll.id = static_cast(definition.scroll_item_id); + base_scroll.minstatus = 0; + base_scroll.Name = fmt::format("Spell: {}", definition.name); + base_scroll.lore = fmt::format("A living scroll for {}", definition.name); + base_scroll.comment = fmt::format("Generated live spell scroll for spell {}", definition.spell_id); + base_scroll.itemclass = EQ::item::ItemClassCommon; + base_scroll.itemtype = EQ::item::ItemTypeSpell; + base_scroll.classes = static_cast(definition.class_mask); + base_scroll.tradeskills = 0; + base_scroll.icon = 778; + base_scroll.scrolleffect = definition.spell_id; + base_scroll.scrolltype = EQ::item::ItemEffectScroll; + base_scroll.scrolllevel = 1; + base_scroll.scrolllevel2 = 1; + base_scroll.maxcharges = 1; + base_scroll.norent = 255; + base_scroll.nodrop = 0; + base_scroll.updated = std::time(nullptr); + + if (replacing) { + if (!ItemsRepository::UpdateOne(database, base_scroll)) { + c->Message(Chat::White, fmt::format("Failed to update live spell scroll item {}.", definition.scroll_item_id).c_str()); + return false; + } + } else { + ItemsRepository::InsertOne(database, base_scroll); + if (!ItemsRepository::FindOne(database, definition.scroll_item_id).id) { + c->Message(Chat::White, fmt::format("Failed to create live spell scroll item {}.", definition.scroll_item_id).c_str()); + return false; + } + } + + database.ClearLiveItemCache(definition.scroll_item_id); + return true; + } + + LiveSpellDefinition BuildLiveSpellDefinition( + Client *c, + const std::string &element_key, + const std::string &target_key, + const int range, + const int damage, + const int recast_time, + const std::string &custom_name + ) + { + const auto &element = ResolveLiveSpellElement(element_key); + const auto &target = ResolveLiveSpellTarget(target_key); + LiveSpellDefinition definition; + + definition.spell_id = FindFreeLiveSpellID(); + definition.scroll_item_id = FindFreeLiveScrollItemID(); + definition.owner_character_id = c->CharacterID(); + definition.class_mask = static_cast(1 << (c->GetClass() - 1)); + definition.version = BuildLiveSpellVersion(); + definition.element = element.key; + definition.target = target.key; + definition.target_type = target.target_type; + definition.resist_type = element.resist_type; + definition.icon = element.icon; + definition.book_icon = element.icon; + definition.range = std::clamp(range, 25, 300); + definition.aoe_range = static_cast(target.aoe_range); + definition.damage = std::clamp(damage, 1, 5000); + definition.recast_time = std::clamp(recast_time, 1000, 600000); + definition.cast_time = std::clamp(1500 + (definition.damage / 20), 1500, 6000); + definition.recovery_time = 1500; + definition.mana = std::clamp(5 + (definition.damage / 5), 5, 5000); + definition.level = 1; + definition.name = DecodeLiveSpellCommandText(custom_name); + if (definition.name.empty()) { + definition.name = SanitizeLiveSpellText( + fmt::format("{} {} {}", c->GetCleanName(), element.noun, target.key == std::string("pbae") ? "Bloom" : "Lash"), + 60 + ); + } + + return definition; + } + + void SendLiveSpellUsage(Client *c) + { + c->Message(Chat::White, "Usage: #livespell dialog"); + c->Message(Chat::White, "Usage: #livespell craft [fire|cold|magic|poison|disease] [target|ae|pbae] [range] [damage] [recast_ms]"); + c->Message(Chat::White, "Usage: #livespell craft element=cold target=ae range=200 damage=100 recast=3000 name=Frost_Burst"); + c->Message(Chat::White, "Usage: #livespell test [spell_id] [base_spell_id] [gem]"); + c->Message(Chat::White, "Usage: #livespell patch [spell_id] [base_spell_id]"); + c->Message(Chat::White, "Usage: #livespell scribe [spell_id] [gem]"); + c->Message(Chat::White, "Usage: #livespell ack [spell_id] [version]"); + c->Message(Chat::White, "Usage: #livespell ready"); + } + + bool IsLiveSpellSlotUsable(Client *c, const uint32 spell_id, const uint32 base_spell_id) + { + if (!spells || SPDAT_RECORDS <= 0) { + if (c) { + c->Message(Chat::White, "Spell data is not loaded."); + } + return false; + } + + if (spell_id >= static_cast(SPDAT_RECORDS)) { + if (c) { + c->Message(Chat::White, fmt::format("Spell ID {} is outside loaded server spell records [{}].", spell_id, SPDAT_RECORDS).c_str()); + } + return false; + } + + if (base_spell_id >= static_cast(SPDAT_RECORDS) || !IsValidSpell(base_spell_id)) { + if (c) { + c->Message(Chat::White, fmt::format("Base spell ID {} is not valid.", base_spell_id).c_str()); + } + return false; + } + + return true; + } + + uint32 BuildLiveSpellVersion() + { + return static_cast(std::time(nullptr)); + } + + bool PatchServerLiveSpell(Client *c, const uint16 spell_id, const uint16 base_spell_id, const uint32 version) + { + if (!IsLiveSpellSlotUsable(c, spell_id, base_spell_id)) { + return false; + } + + EQ::IPCMutex mutex("spells"); + mutex.Lock(); + + auto *mutable_spells = const_cast(spells); + mutable_spells[spell_id] = spells[base_spell_id]; + + auto &spell = mutable_spells[spell_id]; + spell.id = spell_id; + CopySpellText(spell.name, fmt::format("Live Ember Lash {}", version % 10000)); + CopySpellText(spell.player_1, "GEN"); + CopySpellText(spell.you_cast, "You shape a live ember into a spell."); + CopySpellText(spell.other_casts, "$n shapes a live ember into a spell."); + CopySpellText(spell.cast_on_you, "A live ember lashes you."); + CopySpellText(spell.cast_on_other, "A live ember lashes $n."); + CopySpellText(spell.spell_fades, "The live ember fades."); + spell.mana = 5; + spell.cast_time = 1500; + spell.recovery_time = 1500; + spell.recast_time = 3000; + spell.range = 200.0f; + spell.new_icon = 28; + for (uint8 &level : spell.classes) { + level = 1; + } + + mutex.Unlock(); + + return true; + } + + void SendLiveSpellPatch(Client *c, const uint16 spell_id, const uint16 base_spell_id, const uint32 version) + { + const auto &spell = spells[spell_id]; + c->Message( + Chat::White, + fmt::format( + "LIVESPELL|upsert|id={}|base={}|version={}|name={}|mana={}|cast={}|recovery={}|recast={}|range={:.1f}|icon={}|book_icon={}|level=1", + spell_id, + base_spell_id, + version, + spell.name, + spell.mana, + spell.cast_time, + spell.recovery_time, + spell.recast_time, + spell.range, + spell.new_icon, + spell.new_icon + ).c_str() + ); + } + + void ScribeLiveSpell(Client *c, const uint16 spell_id, const int gem) + { + if (!IsValidSpell(spell_id)) { + c->Message(Chat::White, fmt::format("Spell ID {} is not valid on the server.", spell_id).c_str()); + return; + } + + int book_slot = c->FindSpellBookSlotBySpellID(spell_id); + if (book_slot < 0) { + book_slot = c->GetNextAvailableSpellBookSlot(); + } + + if (book_slot < 0) { + c->Message(Chat::White, "No free spellbook slot is available."); + return; + } + + if (c->FindSpellBookSlotBySpellID(spell_id) < 0) { + c->ScribeSpell(spell_id, book_slot); + } + + if (gem >= 0 && gem < EQ::spells::SPELL_GEM_COUNT) { + c->MemSpell(spell_id, gem); + } + + c->Message(Chat::White, fmt::format("Live spell {} is scribed in book slot {} and gem {}.", spell_id, book_slot, gem).c_str()); + } +} + +namespace LiveSpellManager { + void EnsureServerLoaded() + { + if (gLiveSpellServerLoaded) { + return; + } + + PatchPersistedLiveSpells(); + gLiveSpellServerLoaded = true; + } + + void SendClientSync(Client *c) + { + EnsureServerLoaded(); + + int sent = 0; + for (const auto &definition : LoadLiveSpellDefinitions()) { + SendLiveSpellPatch(c, definition); + ++sent; + } + + c->Message(Chat::White, fmt::format("LiveSpell DLL reported ready. Synced {} generated spell{}.", sent, sent == 1 ? "" : "s").c_str()); + } + + bool CreateSpellScroll( + Client *c, + const std::string &element, + const std::string &target, + const int range, + const int damage, + const int recast_time, + const std::string &custom_name + ) + { + EnsureServerLoaded(); + + auto definition = BuildLiveSpellDefinition(c, element, target, range, damage, recast_time, custom_name); + if (!definition.spell_id) { + c->Message(Chat::White, fmt::format("No free live spell slot is available in the reserve [{}-{}]. Add more blank spell rows and rebuild shared memory.", LiveSpellReserveMinID, LiveSpellReserveMaxID).c_str()); + return false; + } + + if (!definition.scroll_item_id) { + c->Message(Chat::White, "No free live scroll item ID is available in the configured live item range."); + return false; + } + + if (!UpsertLiveSpellScrollItem(c, definition)) { + return false; + } + + DataBucket::SetData( + &database, + fmt::format("{}{}", LiveSpellBucketPrefix, definition.spell_id), + SerializeLiveSpellDefinition(definition) + ); + + if (!PatchServerLiveSpellDefinition(c, definition)) { + return false; + } + + SendLiveSpellPatch(c, definition); + c->SummonItem(definition.scroll_item_id, 1); + c->Message( + Chat::White, + fmt::format( + "Created {} as spell {} and scroll item {}. Scribe the scroll, memorize it, then cast it normally.", + definition.name, + definition.spell_id, + definition.scroll_item_id + ).c_str() + ); + + return true; + } + + bool IsLiveSpell(const uint16 spell_id) + { + return IsPersistedLiveSpellID(spell_id); + } +} + +void command_livespell(Client *c, const Seperator *sep) +{ + const auto arguments = sep->argnum; + if (!arguments || !strcasecmp(sep->arg[1], "help")) { + SendLiveSpellUsage(c); + return; + } + + const bool is_test = !strcasecmp(sep->arg[1], "test"); + const bool is_patch = !strcasecmp(sep->arg[1], "patch"); + const bool is_scribe = !strcasecmp(sep->arg[1], "scribe"); + const bool is_ack = !strcasecmp(sep->arg[1], "ack"); + const bool is_ready = !strcasecmp(sep->arg[1], "ready"); + const bool is_dialog = !strcasecmp(sep->arg[1], "dialog"); + const bool is_craft = !strcasecmp(sep->arg[1], "craft") || !strcasecmp(sep->arg[1], "create"); + + if (is_ack) { + const auto spell_id = arguments >= 2 ? Strings::ToUnsignedInt(sep->arg[2]) : 0; + const auto version = arguments >= 3 ? Strings::ToUnsignedInt(sep->arg[3]) : 0; + c->Message(Chat::White, fmt::format("LiveSpell DLL ack received for spell {} version {}.", spell_id, version).c_str()); + return; + } + + if (is_ready) { + LiveSpellManager::SendClientSync(c); + return; + } + + if (is_dialog) { + c->Message(Chat::White, "Opening the Spell Forge."); + c->Message(Chat::White, "LIVESPELL|ui|open|elements=fire,cold,magic,poison,disease|targets=target,ae,pbae|max_damage=500|max_range=300|min_recast=1000|max_recast=30000"); + return; + } + + if (is_craft) { + std::string element = "fire"; + std::string target = "target"; + int range = 200; + int damage = 100; + int recast_time = 3000; + std::string custom_name; + + if (HasLiveSpellNamedArgs(sep)) { + const auto named_element = GetLiveSpellNamedArg(sep, "element"); + const auto named_target = GetLiveSpellNamedArg(sep, "target"); + if (!named_element.empty()) { + element = named_element; + } + + if (!named_target.empty()) { + target = named_target; + } + + range = GetLiveSpellNamedInt(sep, "range", range); + damage = GetLiveSpellNamedInt(sep, "damage", damage); + recast_time = GetLiveSpellNamedInt(sep, "recast", recast_time); + custom_name = DecodeLiveSpellCommandText(GetLiveSpellNamedArg(sep, "name")); + } else { + element = arguments >= 2 ? std::string(sep->arg[2]) : element; + target = arguments >= 3 ? std::string(sep->arg[3]) : target; + range = (arguments >= 4 && sep->IsNumber(4)) ? Strings::ToInt(sep->arg[4]) : range; + damage = (arguments >= 5 && sep->IsNumber(5)) ? Strings::ToInt(sep->arg[5]) : damage; + recast_time = (arguments >= 6 && sep->IsNumber(6)) ? Strings::ToInt(sep->arg[6]) : recast_time; + } + + LiveSpellManager::CreateSpellScroll(c, element, target, range, damage, recast_time, custom_name); + return; + } + + if (c->Admin() < AccountStatus::GMMgmt) { + c->Message(Chat::White, "Only GMs can run live spell prototype patch/test commands."); + return; + } + + if (!is_test && !is_patch && !is_scribe) { + SendLiveSpellUsage(c); + return; + } + + const auto spell_id = static_cast( + (arguments >= 2 && sep->IsNumber(2)) ? Strings::ToUnsignedInt(sep->arg[2]) : LiveSpellDefaultID + ); + const auto base_spell_id = static_cast( + (arguments >= 3 && sep->IsNumber(3)) ? Strings::ToUnsignedInt(sep->arg[3]) : LiveSpellDefaultBaseID + ); + const auto gem = (arguments >= 4 && sep->IsNumber(4)) ? Strings::ToInt(sep->arg[4]) : LiveSpellDefaultGem; + + if (is_scribe) { + ScribeLiveSpell(c, spell_id, gem); + return; + } + + const auto version = BuildLiveSpellVersion(); + if (!PatchServerLiveSpell(c, spell_id, base_spell_id, version)) { + return; + } + + SendLiveSpellPatch(c, spell_id, base_spell_id, version); + c->Message(Chat::White, fmt::format("Patched server and client transport for live spell {} from base {}.", spell_id, base_spell_id).c_str()); + + if (is_test) { + ScribeLiveSpell(c, spell_id, gem); + } +} diff --git a/zone/live_spell_manager.h b/zone/live_spell_manager.h new file mode 100644 index 0000000000..371ba535b0 --- /dev/null +++ b/zone/live_spell_manager.h @@ -0,0 +1,31 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. +*/ +#pragma once + +#include "common/types.h" + +#include + +class Client; + +namespace LiveSpellManager { + void EnsureServerLoaded(); + void SendClientSync(Client *c); + bool CreateSpellScroll( + Client *c, + const std::string &element, + const std::string &target, + int range, + int damage, + int recast_time, + const std::string &custom_name = "" + ); + bool IsLiveSpell(uint16 spell_id); +} diff --git a/zone/spells.cpp b/zone/spells.cpp index d20597b5c7..08ce49ec2d 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -83,6 +83,7 @@ #include "zone/bot.h" #include "zone/client.h" #include "zone/fastmath.h" +#include "zone/live_spell_manager.h" #include "zone/lua_parser.h" #include "zone/mob_movement_manager.h" #include "zone/queryserv.h" @@ -147,6 +148,8 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, uint32 timer, uint32 timer_duration, int16 *resist_adjust, uint32 aa_id) { + LiveSpellManager::EnsureServerLoaded(); + LogSpells("CastSpell called for spell [{}] ([{}]) on entity [{}], slot [{}], time [{}], mana [{}], from item slot [{}]", (IsValidSpell(spell_id)) ? spells[spell_id].name : "UNKNOWN SPELL", spell_id, target_id, static_cast(slot), cast_time, mana_cost, (item_slot == 0xFFFFFFFF) ? 999 : item_slot); From 552b1d9fdb0dda07a7ea9cd18c71158a4d4dcef2 Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Sat, 23 May 2026 23:25:53 -0700 Subject: [PATCH 122/194] Add standalone Achievements feature branch --- .../ui/EQUI_NativeAchievementWnd.xml | 138 ++ .../database_update_manifest_custom.h | 1965 +++++++++++++++++ common/version.h | 2 +- docs/achievements.md | 31 + features/README.md | 1 + features/achievements/MANIFEST.md | 62 + features/achievements/README.md | 47 + zone/CMakeLists.txt | 3 + zone/achievement_manager.cpp | 987 +++++++++ zone/achievement_manager.h | 80 + zone/attack.cpp | 13 + zone/client.cpp | 3 + zone/client_packet.cpp | 3 + zone/command.cpp | 5 + zone/command.h | 1 + zone/exp.cpp | 3 + zone/gm_commands/achievements.cpp | 16 + zone/task_client_state.cpp | 3 + 18 files changed, 3362 insertions(+), 1 deletion(-) create mode 100644 client_files/native_autoloot/ui/EQUI_NativeAchievementWnd.xml create mode 100644 docs/achievements.md create mode 100644 features/achievements/MANIFEST.md create mode 100644 features/achievements/README.md create mode 100644 zone/achievement_manager.cpp create mode 100644 zone/achievement_manager.h create mode 100644 zone/gm_commands/achievements.cpp diff --git a/client_files/native_autoloot/ui/EQUI_NativeAchievementWnd.xml b/client_files/native_autoloot/ui/EQUI_NativeAchievementWnd.xml new file mode 100644 index 0000000000..3501f1a518 --- /dev/null +++ b/client_files/native_autoloot/ui/EQUI_NativeAchievementWnd.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + NAW_CategoryList + WDT_Inner + true + 1246 + 220412 + true + true + false + false + 126Category + 56Done + 38Pts + + + + NAW_AchievementList + WDT_Inner + true + 24046 + 488210 + true + true + false + false + 54State + 194Achievement + 42Pts + 198Description + + + + + + + + NAW_ObjectiveList + WDT_Inner + true + 240336 + 488122 + true + true + false + false + 54State + 340Objective + 94Progress + + + + + + NativeAchievementWnd + false + 9070 + 740520 + Achievements + WDT_Def + true + true + true + true + false + false + NAW_SummaryLabel + NAW_RefreshButton + NAW_CheckButton + NAW_CategoryList + NAW_AchievementList + NAW_DetailTitleLabel + NAW_DetailDescriptionLabel + NAW_ObjectiveList + NAW_StatusLabel + + diff --git a/common/database/database_update_manifest_custom.h b/common/database/database_update_manifest_custom.h index 934b74e8df..807a147926 100644 --- a/common/database/database_update_manifest_custom.h +++ b/common/database/database_update_manifest_custom.h @@ -81,6 +81,1971 @@ CREATE TABLE `custom_autoloot_audit` ( )", .content_schema_update = false, }, + ManifestEntry{ + .version = 2, + .description = "2026_05_23_custom_achievements", + .check = "SHOW TABLES LIKE 'custom_achievement_categories'", + .condition = "empty", + .match = "", + .sql = R"( +CREATE TABLE `custom_achievement_categories` ( + `id` INT UNSIGNED NOT NULL, + `parent_id` INT UNSIGNED NOT NULL DEFAULT 0, + `name` VARCHAR(64) NOT NULL DEFAULT '', + `description` VARCHAR(255) NOT NULL DEFAULT '', + `sort_order` INT NOT NULL DEFAULT 0, + `icon_id` INT UNSIGNED NOT NULL DEFAULT 0, + `enabled` TINYINT(1) NOT NULL DEFAULT 1, + PRIMARY KEY (`id`), + KEY `idx_parent_sort` (`parent_id`, `sort_order`, `id`) +); + +CREATE TABLE `custom_achievements` ( + `id` INT UNSIGNED NOT NULL, + `category_id` INT UNSIGNED NOT NULL, + `slug` VARCHAR(64) NOT NULL DEFAULT '', + `name` VARCHAR(96) NOT NULL DEFAULT '', + `description` VARCHAR(255) NOT NULL DEFAULT '', + `points` INT UNSIGNED NOT NULL DEFAULT 0, + `hidden` TINYINT(1) NOT NULL DEFAULT 0, + `repeatable` TINYINT(1) NOT NULL DEFAULT 0, + `reward_title_set` INT UNSIGNED NOT NULL DEFAULT 0, + `reward_item_id` INT UNSIGNED NOT NULL DEFAULT 0, + `reward_currency_id` INT UNSIGNED NOT NULL DEFAULT 0, + `reward_currency_amount` INT UNSIGNED NOT NULL DEFAULT 0, + `enabled` TINYINT(1) NOT NULL DEFAULT 1, + `sort_order` INT NOT NULL DEFAULT 0, + `created_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_slug` (`slug`), + KEY `idx_category_sort` (`category_id`, `sort_order`, `id`) +); + +CREATE TABLE `custom_achievement_objectives` ( + `id` INT UNSIGNED NOT NULL, + `achievement_id` INT UNSIGNED NOT NULL, + `objective_index` INT UNSIGNED NOT NULL DEFAULT 0, + `objective_type` VARCHAR(32) NOT NULL DEFAULT 'manual', + `target_type` VARCHAR(32) NOT NULL DEFAULT '', + `target_id` INT UNSIGNED NOT NULL DEFAULT 0, + `target_name` VARCHAR(128) NOT NULL DEFAULT '', + `required_count` INT UNSIGNED NOT NULL DEFAULT 1, + `zone_id` INT UNSIGNED NOT NULL DEFAULT 0, + `class_mask` INT UNSIGNED NOT NULL DEFAULT 0, + `optional` TINYINT(1) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_achievement` (`achievement_id`, `objective_index`, `id`), + KEY `idx_type_target` (`objective_type`, `target_id`, `zone_id`) +); + +CREATE TABLE `custom_character_achievement_progress` ( + `character_id` INT UNSIGNED NOT NULL, + `objective_id` INT UNSIGNED NOT NULL, + `count` INT UNSIGNED NOT NULL DEFAULT 0, + `completed_at` INT UNSIGNED NOT NULL DEFAULT 0, + `updated_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`, `objective_id`), + KEY `idx_objective` (`objective_id`) +); + +CREATE TABLE `custom_character_achievements` ( + `character_id` INT UNSIGNED NOT NULL, + `achievement_id` INT UNSIGNED NOT NULL, + `completed_at` INT UNSIGNED NOT NULL DEFAULT 0, + `awarded_at` INT UNSIGNED NOT NULL DEFAULT 0, + `completion_count` INT UNSIGNED NOT NULL DEFAULT 1, + `announced` TINYINT(1) NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`, `achievement_id`), + KEY `idx_achievement` (`achievement_id`), + KEY `idx_completed` (`completed_at`) +); + +CREATE TABLE `custom_achievement_audit` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + `character_id` INT UNSIGNED NOT NULL DEFAULT 0, + `achievement_id` INT UNSIGNED NOT NULL DEFAULT 0, + `objective_id` INT UNSIGNED NOT NULL DEFAULT 0, + `action` VARCHAR(64) NOT NULL DEFAULT '', + `detail` VARCHAR(255) NOT NULL DEFAULT '', + `created_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_character_created` (`character_id`, `created_at`), + KEY `idx_achievement` (`achievement_id`) +); + +INSERT INTO `custom_achievement_categories` +(`id`, `parent_id`, `name`, `description`, `sort_order`, `icon_id`, `enabled`) +VALUES +(1, 0, 'Character', 'Character milestones and personal growth.', 10, 0, 1), +(2, 0, 'Exploration', 'Zone discovery and travel achievements.', 20, 0, 1), +(3, 0, 'Hunter', 'Named NPC and zone hunting achievements.', 30, 0, 1), +(4, 0, 'Slayer', 'Creature kill count achievements.', 40, 0, 1), +(5, 0, 'Progression', 'Task, flag, access, and expansion progression.', 50, 0, 1), +(6, 0, 'Tradeskill', 'Crafting and skill achievements.', 60, 0, 1), +(7, 0, 'Epics', 'Class epic and long-term item achievements.', 70, 0, 1), +(8, 0, 'Server Custom', 'Rebirth, difficulty, attunement, and custom server milestones.', 80, 0, 1) +ON DUPLICATE KEY UPDATE +`name` = VALUES(`name`), +`description` = VALUES(`description`), +`sort_order` = VALUES(`sort_order`), +`enabled` = VALUES(`enabled`); + +INSERT INTO `custom_achievements` +(`id`, `category_id`, `slug`, `name`, `description`, `points`, `hidden`, `repeatable`, `sort_order`, `created_at`, `enabled`) +VALUES +(1001, 1, 'level_10', 'Level 10', 'Become a level 10 Adventurer.', 10, 0, 0, 10, UNIX_TIMESTAMP(), 1), +(1002, 1, 'level_20', 'Level 20', 'Become a level 20 Adventurer.', 10, 0, 0, 20, UNIX_TIMESTAMP(), 1), +(1003, 1, 'level_30', 'Level 30', 'Become a level 30 Adventurer.', 10, 0, 0, 30, UNIX_TIMESTAMP(), 1), +(1004, 1, 'level_40', 'Level 40', 'Become a level 40 Adventurer.', 10, 0, 0, 40, UNIX_TIMESTAMP(), 1), +(1005, 1, 'level_50', 'Level 50', 'Become a level 50 Adventurer.', 20, 0, 0, 50, UNIX_TIMESTAMP(), 1), +(1006, 1, 'level_60', 'Level 60', 'Become a level 60 Adventurer.', 20, 0, 0, 60, UNIX_TIMESTAMP(), 1), +(1007, 1, 'level_65', 'Level 65', 'Become a level 65 Adventurer.', 25, 0, 0, 65, UNIX_TIMESTAMP(), 1), +(1008, 1, 'level_70', 'Level 70', 'Become a level 70 Adventurer.', 25, 0, 0, 70, UNIX_TIMESTAMP(), 1) +ON DUPLICATE KEY UPDATE +`category_id` = VALUES(`category_id`), +`name` = VALUES(`name`), +`description` = VALUES(`description`), +`points` = VALUES(`points`), +`sort_order` = VALUES(`sort_order`), +`enabled` = VALUES(`enabled`); + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +VALUES +(1001, 1001, 0, 'level', 'level', 10, 'Reach level 10', 10, 0, 0, 0), +(1002, 1002, 0, 'level', 'level', 20, 'Reach level 20', 20, 0, 0, 0), +(1003, 1003, 0, 'level', 'level', 30, 'Reach level 30', 30, 0, 0, 0), +(1004, 1004, 0, 'level', 'level', 40, 'Reach level 40', 40, 0, 0, 0), +(1005, 1005, 0, 'level', 'level', 50, 'Reach level 50', 50, 0, 0, 0), +(1006, 1006, 0, 'level', 'level', 60, 'Reach level 60', 60, 0, 0, 0), +(1007, 1007, 0, 'level', 'level', 65, 'Reach level 65', 65, 0, 0, 0), +(1008, 1008, 0, 'level', 'level', 70, 'Reach level 70', 70, 0, 0, 0) +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`); +)", + .content_schema_update = false, + }, + ManifestEntry{ + .version = 3, + .description = "2026_05_23_custom_achievement_catalog_seed", + .check = "SELECT 1 FROM `custom_achievements` WHERE `id` = 200279 LIMIT 1", + .condition = "empty", + .match = "", + .sql = R"( +INSERT INTO `custom_achievement_categories` +(`id`, `parent_id`, `name`, `description`, `sort_order`, `icon_id`, `enabled`) +VALUES +(200, 2, 'Classic Exploration', 'Explore Classic-era zones.', 200, 0, 1), +(201, 2, 'The Ruins of Kunark Exploration', 'Explore The Ruins of Kunark zones.', 201, 0, 1), +(202, 2, 'The Scars of Velious Exploration', 'Explore The Scars of Velious zones.', 202, 0, 1), +(203, 2, 'The Shadows of Luclin Exploration', 'Explore The Shadows of Luclin zones.', 203, 0, 1), +(204, 2, 'The Planes of Power Exploration', 'Explore The Planes of Power zones.', 204, 0, 1), +(205, 2, 'The Legacy of Ykesha Exploration', 'Explore The Legacy of Ykesha zones.', 205, 0, 1), +(206, 2, 'Lost Dungeons of Norrath Exploration', 'Explore Lost Dungeons of Norrath zones.', 206, 0, 1), +(207, 2, 'Gates of Discord Exploration', 'Explore Gates of Discord zones.', 207, 0, 1), +(208, 2, 'Omens of War Exploration', 'Explore Omens of War zones.', 208, 0, 1), +(209, 2, 'Dragons of Norrath Exploration', 'Explore Dragons of Norrath zones.', 209, 0, 1), +(210, 2, 'Depths of Darkhollow Exploration', 'Explore Depths of Darkhollow zones.', 210, 0, 1), +(211, 2, 'Prophecy of Ro Exploration', 'Explore Prophecy of Ro zones.', 211, 0, 1), +(212, 2, 'The Serpent''s Spine Exploration', 'Explore The Serpent''s Spine zones.', 212, 0, 1), +(213, 2, 'The Buried Sea Exploration', 'Explore The Buried Sea zones.', 213, 0, 1), +(214, 2, 'Secrets of Faydwer Exploration', 'Explore Secrets of Faydwer zones.', 214, 0, 1), +(215, 2, 'Seeds of Destruction Exploration', 'Explore Seeds of Destruction zones.', 215, 0, 1), +(216, 2, 'Underfoot Exploration', 'Explore Underfoot zones.', 216, 0, 1), +(217, 2, 'House of Thule Exploration', 'Explore House of Thule zones.', 217, 0, 1), +(218, 2, 'Veil of Alaris Exploration', 'Explore Veil of Alaris zones.', 218, 0, 1), +(219, 2, 'Rain of Fear Exploration', 'Explore Rain of Fear zones.', 219, 0, 1), +(300, 5, 'Task Completion', 'Quest and task completion achievements.', 300, 0, 1), +(400, 4, 'Zone Slayer', 'Zone-wide kill count achievements.', 400, 0, 1), +(410, 4, 'Creature Slayer', 'Race and body type kill count achievements.', 410, 0, 1), +(600, 6, 'Tradeskill Mastery', 'Tradeskill milestone achievements.', 600, 0, 1) +ON DUPLICATE KEY UPDATE +`parent_id` = VALUES(`parent_id`), +`name` = VALUES(`name`), +`description` = VALUES(`description`), +`sort_order` = VALUES(`sort_order`), +`enabled` = VALUES(`enabled`); +)" +R"( + +INSERT INTO `custom_achievements` +(`id`, `category_id`, `slug`, `name`, `description`, `points`, `hidden`, `repeatable`, `sort_order`, `created_at`, `enabled`) +SELECT +200000 + z.`zoneidnumber`, +200 + z.`expansion`, +LEFT(CONCAT('explorer_', z.`short_name`), 64), +LEFT(CONCAT('Explorer: ', z.`long_name`), 96), +LEFT(CONCAT('Visit ', z.`long_name`, '.'), 255), +5, +0, +0, +z.`zoneidnumber`, +UNIX_TIMESTAMP(), +1 +FROM `zone` z +WHERE z.`version` = 0 +AND z.`min_status` = 0 +AND z.`zoneidnumber` > 0 +AND z.`expansion` BETWEEN 0 AND 19 +AND COALESCE(z.`short_name`, '') <> '' +AND COALESCE(z.`long_name`, '') <> '' +ON DUPLICATE KEY UPDATE +`category_id` = VALUES(`category_id`), +`name` = VALUES(`name`), +`description` = VALUES(`description`), +`points` = VALUES(`points`), +`sort_order` = VALUES(`sort_order`), +`enabled` = VALUES(`enabled`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +SELECT +1200000 + z.`zoneidnumber`, +200000 + z.`zoneidnumber`, +0, +'zone_visit', +'zone', +z.`zoneidnumber`, +LEFT(CONCAT('Visit ', z.`long_name`), 128), +1, +z.`zoneidnumber`, +0, +0 +FROM `zone` z +WHERE z.`version` = 0 +AND z.`min_status` = 0 +AND z.`zoneidnumber` > 0 +AND z.`expansion` BETWEEN 0 AND 19 +AND COALESCE(z.`short_name`, '') <> '' +AND COALESCE(z.`long_name`, '') <> '' +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`), +`zone_id` = VALUES(`zone_id`); +)" +R"( + +INSERT INTO `custom_achievements` +(`id`, `category_id`, `slug`, `name`, `description`, `points`, `hidden`, `repeatable`, `sort_order`, `created_at`, `enabled`) +SELECT +700000 + z.`zoneidnumber`, +400, +LEFT(CONCAT('zone_slayer_', z.`short_name`), 64), +LEFT(CONCAT('Slayer: ', z.`long_name`), 96), +LEFT(CONCAT('Defeat enemies in ', z.`long_name`, '.'), 255), +10, +0, +0, +z.`zoneidnumber`, +UNIX_TIMESTAMP(), +1 +FROM `zone` z +WHERE z.`version` = 0 +AND z.`min_status` = 0 +AND z.`zoneidnumber` > 0 +AND z.`expansion` BETWEEN 0 AND 19 +AND z.`cancombat` = 1 +AND COALESCE(z.`short_name`, '') <> '' +AND COALESCE(z.`long_name`, '') <> '' +ON DUPLICATE KEY UPDATE +`category_id` = VALUES(`category_id`), +`name` = VALUES(`name`), +`description` = VALUES(`description`), +`points` = VALUES(`points`), +`sort_order` = VALUES(`sort_order`), +`enabled` = VALUES(`enabled`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +SELECT +1700000 + z.`zoneidnumber`, +700000 + z.`zoneidnumber`, +0, +'zone_kill', +'zone', +z.`zoneidnumber`, +LEFT(CONCAT('Defeat enemies in ', z.`long_name`), 128), +50, +z.`zoneidnumber`, +0, +0 +FROM `zone` z +WHERE z.`version` = 0 +AND z.`min_status` = 0 +AND z.`zoneidnumber` > 0 +AND z.`expansion` BETWEEN 0 AND 19 +AND z.`cancombat` = 1 +AND COALESCE(z.`short_name`, '') <> '' +AND COALESCE(z.`long_name`, '') <> '' +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`), +`zone_id` = VALUES(`zone_id`); +)" +R"( + +INSERT INTO `custom_achievements` +(`id`, `category_id`, `slug`, `name`, `description`, `points`, `hidden`, `repeatable`, `sort_order`, `created_at`, `enabled`) +SELECT +3000000 + t.`id`, +300, +CONCAT('task_', t.`id`), +LEFT(CONCAT('Task: ', t.`title`), 96), +LEFT(CONCAT('Complete the task "', t.`title`, '".'), 255), +10, +0, +0, +t.`id`, +UNIX_TIMESTAMP(), +1 +FROM `tasks` t +WHERE t.`id` > 0 +AND COALESCE(t.`enabled`, 1) = 1 +AND COALESCE(t.`title`, '') <> '' +AND LOWER(t.`title`) <> 'autoloot test' +ON DUPLICATE KEY UPDATE +`category_id` = VALUES(`category_id`), +`name` = VALUES(`name`), +`description` = VALUES(`description`), +`points` = VALUES(`points`), +`sort_order` = VALUES(`sort_order`), +`enabled` = VALUES(`enabled`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +SELECT +13000000 + t.`id`, +3000000 + t.`id`, +0, +'task_complete', +'task', +t.`id`, +LEFT(t.`title`, 128), +1, +0, +0, +0 +FROM `tasks` t +WHERE t.`id` > 0 +AND COALESCE(t.`enabled`, 1) = 1 +AND COALESCE(t.`title`, '') <> '' +AND LOWER(t.`title`) <> 'autoloot test' +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`); +)" +R"( + +INSERT INTO `custom_achievements` +(`id`, `category_id`, `slug`, `name`, `description`, `points`, `hidden`, `repeatable`, `sort_order`, `created_at`, `enabled`) +SELECT +400000 + s.`skill_id` * 1000 + r.`required_count`, +600, +CONCAT('skill_', s.`skill_id`, '_', r.`required_count`), +CONCAT(s.`name`, ' ', r.`required_count`), +CONCAT('Raise ', s.`name`, ' to ', r.`required_count`, '.'), +r.`points`, +0, +0, +s.`skill_id` * 1000 + r.`required_count`, +UNIX_TIMESTAMP(), +1 +FROM ( +SELECT 55 AS `skill_id`, 'Fishing' AS `name` UNION ALL +SELECT 56, 'Make Poison' UNION ALL +SELECT 57, 'Tinkering' UNION ALL +SELECT 58, 'Research' UNION ALL +SELECT 59, 'Alchemy' UNION ALL +SELECT 60, 'Baking' UNION ALL +SELECT 61, 'Tailoring' UNION ALL +SELECT 63, 'Blacksmithing' UNION ALL +SELECT 64, 'Fletching' UNION ALL +SELECT 65, 'Brewing' UNION ALL +SELECT 68, 'Jewelcrafting' UNION ALL +SELECT 69, 'Pottery' +) s +JOIN ( +SELECT 50 AS `required_count`, 5 AS `points` UNION ALL +SELECT 100, 5 UNION ALL +SELECT 150, 10 UNION ALL +SELECT 200, 10 UNION ALL +SELECT 250, 15 UNION ALL +SELECT 300, 25 +) r +ON 1 = 1 +ON DUPLICATE KEY UPDATE +`category_id` = VALUES(`category_id`), +`name` = VALUES(`name`), +`description` = VALUES(`description`), +`points` = VALUES(`points`), +`sort_order` = VALUES(`sort_order`), +`enabled` = VALUES(`enabled`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +SELECT +1400000 + s.`skill_id` * 1000 + r.`required_count`, +400000 + s.`skill_id` * 1000 + r.`required_count`, +0, +'skill', +'skill', +s.`skill_id`, +CONCAT(s.`name`, ' ', r.`required_count`), +r.`required_count`, +0, +0, +0 +FROM ( +SELECT 55 AS `skill_id`, 'Fishing' AS `name` UNION ALL +SELECT 56, 'Make Poison' UNION ALL +SELECT 57, 'Tinkering' UNION ALL +SELECT 58, 'Research' UNION ALL +SELECT 59, 'Alchemy' UNION ALL +SELECT 60, 'Baking' UNION ALL +SELECT 61, 'Tailoring' UNION ALL +SELECT 63, 'Blacksmithing' UNION ALL +SELECT 64, 'Fletching' UNION ALL +SELECT 65, 'Brewing' UNION ALL +SELECT 68, 'Jewelcrafting' UNION ALL +SELECT 69, 'Pottery' +) s +JOIN ( +SELECT 50 AS `required_count` UNION ALL +SELECT 100 UNION ALL +SELECT 150 UNION ALL +SELECT 200 UNION ALL +SELECT 250 UNION ALL +SELECT 300 +) r +ON 1 = 1 +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`); +)" +R"( + +INSERT INTO `custom_achievements` +(`id`, `category_id`, `slug`, `name`, `description`, `points`, `hidden`, `repeatable`, `sort_order`, `created_at`, `enabled`) +SELECT +500000 + r.`race_id` * 1000 + c.`required_count`, +410, +CONCAT('race_slayer_', r.`race_id`, '_', c.`required_count`), +CONCAT(c.`rank_name`, ' ', r.`name`, ' Slayer'), +CONCAT('Slay ', c.`required_count`, ' ', r.`name`, ' enemies.'), +c.`points`, +0, +0, +r.`race_id` * 1000 + c.`required_count`, +UNIX_TIMESTAMP(), +1 +FROM ( +SELECT 13 AS `race_id`, 'Aviak' AS `name` UNION ALL +SELECT 17, 'Golem' UNION ALL +SELECT 18, 'Giant' UNION ALL +SELECT 21, 'Evil Eye' UNION ALL +SELECT 25, 'Fairy' UNION ALL +SELECT 26, 'Froglok' UNION ALL +SELECT 33, 'Ghoul' UNION ALL +SELECT 38, 'Spider' UNION ALL +SELECT 39, 'Gnoll' UNION ALL +SELECT 40, 'Goblin' UNION ALL +SELECT 42, 'Wolf' UNION ALL +SELECT 43, 'Bear' UNION ALL +SELECT 48, 'Kobold' UNION ALL +SELECT 51, 'Lizard Man' UNION ALL +SELECT 53, 'Minotaur' UNION ALL +SELECT 54, 'Orc' UNION ALL +SELECT 60, 'Skeleton' UNION ALL +SELECT 65, 'Vampire' UNION ALL +SELECT 70, 'Zombie' UNION ALL +SELECT 75, 'Elemental' UNION ALL +SELECT 79, 'Bixie' UNION ALL +SELECT 88, 'Clockwork' UNION ALL +SELECT 89, 'Drake' +) r +JOIN ( +SELECT 25 AS `required_count`, 'Novice' AS `rank_name`, 5 AS `points` UNION ALL +SELECT 100, 'Adept', 10 UNION ALL +SELECT 250, 'Veteran', 15 +) c +ON 1 = 1 +ON DUPLICATE KEY UPDATE +`category_id` = VALUES(`category_id`), +`name` = VALUES(`name`), +`description` = VALUES(`description`), +`points` = VALUES(`points`), +`sort_order` = VALUES(`sort_order`), +`enabled` = VALUES(`enabled`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +SELECT +1500000 + r.`race_id` * 1000 + c.`required_count`, +500000 + r.`race_id` * 1000 + c.`required_count`, +0, +'race_kill', +'race', +r.`race_id`, +r.`name`, +c.`required_count`, +0, +0, +0 +FROM ( +SELECT 13 AS `race_id`, 'Aviak' AS `name` UNION ALL +SELECT 17, 'Golem' UNION ALL +SELECT 18, 'Giant' UNION ALL +SELECT 21, 'Evil Eye' UNION ALL +SELECT 25, 'Fairy' UNION ALL +SELECT 26, 'Froglok' UNION ALL +SELECT 33, 'Ghoul' UNION ALL +SELECT 38, 'Spider' UNION ALL +SELECT 39, 'Gnoll' UNION ALL +SELECT 40, 'Goblin' UNION ALL +SELECT 42, 'Wolf' UNION ALL +SELECT 43, 'Bear' UNION ALL +SELECT 48, 'Kobold' UNION ALL +SELECT 51, 'Lizard Man' UNION ALL +SELECT 53, 'Minotaur' UNION ALL +SELECT 54, 'Orc' UNION ALL +SELECT 60, 'Skeleton' UNION ALL +SELECT 65, 'Vampire' UNION ALL +SELECT 70, 'Zombie' UNION ALL +SELECT 75, 'Elemental' UNION ALL +SELECT 79, 'Bixie' UNION ALL +SELECT 88, 'Clockwork' UNION ALL +SELECT 89, 'Drake' +) r +JOIN ( +SELECT 25 AS `required_count` UNION ALL +SELECT 100 UNION ALL +SELECT 250 +) c +ON 1 = 1 +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`); +)" +R"( + +INSERT INTO `custom_achievements` +(`id`, `category_id`, `slug`, `name`, `description`, `points`, `hidden`, `repeatable`, `sort_order`, `created_at`, `enabled`) +SELECT +550000 + b.`bodytype_id` * 1000 + c.`required_count`, +410, +CONCAT('bodytype_slayer_', b.`bodytype_id`, '_', c.`required_count`), +CONCAT(c.`rank_name`, ' ', b.`name`, ' Slayer'), +CONCAT('Slay ', c.`required_count`, ' ', b.`name`, ' enemies.'), +c.`points`, +0, +0, +b.`bodytype_id` * 1000 + c.`required_count`, +UNIX_TIMESTAMP(), +1 +FROM ( +SELECT 3 AS `bodytype_id`, 'Undead' AS `name` UNION ALL +SELECT 4, 'Giant' UNION ALL +SELECT 5, 'Construct' UNION ALL +SELECT 6, 'Extraplanar' UNION ALL +SELECT 12, 'Vampire' UNION ALL +SELECT 21, 'Animal' UNION ALL +SELECT 22, 'Insect' UNION ALL +SELECT 23, 'Monster' UNION ALL +SELECT 25, 'Plant' UNION ALL +SELECT 26, 'Dragon' UNION ALL +SELECT 34, 'Muramite' +) b +JOIN ( +SELECT 100 AS `required_count`, 'Adept' AS `rank_name`, 10 AS `points` UNION ALL +SELECT 500, 'Veteran', 20 UNION ALL +SELECT 1000, 'Master', 30 +) c +ON 1 = 1 +ON DUPLICATE KEY UPDATE +`category_id` = VALUES(`category_id`), +`name` = VALUES(`name`), +`description` = VALUES(`description`), +`points` = VALUES(`points`), +`sort_order` = VALUES(`sort_order`), +`enabled` = VALUES(`enabled`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +SELECT +1550000 + b.`bodytype_id` * 1000 + c.`required_count`, +550000 + b.`bodytype_id` * 1000 + c.`required_count`, +0, +'bodytype_kill', +'bodytype', +b.`bodytype_id`, +b.`name`, +c.`required_count`, +0, +0, +0 +FROM ( +SELECT 3 AS `bodytype_id`, 'Undead' AS `name` UNION ALL +SELECT 4, 'Giant' UNION ALL +SELECT 5, 'Construct' UNION ALL +SELECT 6, 'Extraplanar' UNION ALL +SELECT 12, 'Vampire' UNION ALL +SELECT 21, 'Animal' UNION ALL +SELECT 22, 'Insect' UNION ALL +SELECT 23, 'Monster' UNION ALL +SELECT 25, 'Plant' UNION ALL +SELECT 26, 'Dragon' UNION ALL +SELECT 34, 'Muramite' +) b +JOIN ( +SELECT 100 AS `required_count` UNION ALL +SELECT 500 UNION ALL +SELECT 1000 +) c +ON 1 = 1 +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`); +)" +R"( + +INSERT INTO `custom_achievements` +(`id`, `category_id`, `slug`, `name`, `description`, `points`, `hidden`, `repeatable`, `sort_order`, `created_at`, `enabled`) +SELECT +110000 + l.`level`, +1, +CONCAT('level_', l.`level`, '_milestone'), +CONCAT('Level ', l.`level`), +CONCAT('Become a level ', l.`level`, ' Adventurer.'), +l.`points`, +0, +0, +l.`level`, +UNIX_TIMESTAMP(), +1 +FROM ( +SELECT 5 AS `level`, 5 AS `points` UNION ALL +SELECT 15, 10 UNION ALL +SELECT 25, 10 UNION ALL +SELECT 35, 10 UNION ALL +SELECT 45, 15 UNION ALL +SELECT 55, 20 UNION ALL +SELECT 61, 20 UNION ALL +SELECT 62, 20 UNION ALL +SELECT 63, 20 UNION ALL +SELECT 64, 20 UNION ALL +SELECT 66, 25 UNION ALL +SELECT 67, 25 UNION ALL +SELECT 68, 25 UNION ALL +SELECT 69, 25 +) l +ON DUPLICATE KEY UPDATE +`category_id` = VALUES(`category_id`), +`name` = VALUES(`name`), +`description` = VALUES(`description`), +`points` = VALUES(`points`), +`sort_order` = VALUES(`sort_order`), +`enabled` = VALUES(`enabled`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +SELECT +111000 + l.`level`, +110000 + l.`level`, +0, +'level', +'level', +l.`level`, +CONCAT('Reach level ', l.`level`), +l.`level`, +0, +0, +0 +FROM ( +SELECT 5 AS `level` UNION ALL +SELECT 15 UNION ALL +SELECT 25 UNION ALL +SELECT 35 UNION ALL +SELECT 45 UNION ALL +SELECT 55 UNION ALL +SELECT 61 UNION ALL +SELECT 62 UNION ALL +SELECT 63 UNION ALL +SELECT 64 UNION ALL +SELECT 66 UNION ALL +SELECT 67 UNION ALL +SELECT 68 UNION ALL +SELECT 69 +) l +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`); +)", + .content_schema_update = false, + }, + ManifestEntry{ + .version = 4, + .description = "2026_05_23_live_hunter_achievement_seed", + .check = "SELECT 1 FROM `custom_achievements` WHERE `slug` = 'hunter_live_100480' LIMIT 1", + .condition = "empty", + .match = "", + .sql = R"( +INSERT INTO `custom_achievement_categories` +(`id`, `parent_id`, `name`, `description`, `sort_order`, `icon_id`, `enabled`) +VALUES +(3300, 3, 'EverQuest Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3300, 0, 1), +(3301, 3, 'The Ruins of Kunark Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3301, 0, 1), +(3302, 3, 'The Scars of Velious Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3302, 0, 1), +(3303, 3, 'The Shadows of Luclin Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3303, 0, 1), +(3304, 3, 'The Planes of Power Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3304, 0, 1), +(3305, 3, 'The Legacy of Ykesha Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3305, 0, 1), +(3306, 3, 'Lost Dungeons of Norrath Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3306, 0, 1), +(3307, 3, 'Gates of Discord Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3307, 0, 1), +(3308, 3, 'Omens of War Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3308, 0, 1), +(3309, 3, 'Dragons of Norrath Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3309, 0, 1), +(3310, 3, 'Depths of Darkhollow Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3310, 0, 1), +(3311, 3, 'Prophecy of Ro Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3311, 0, 1), +(3312, 3, 'The Serpent''s Spine Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3312, 0, 1), +(3313, 3, 'The Buried Sea Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3313, 0, 1), +(3314, 3, 'Secrets of Faydwer Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3314, 0, 1), +(3315, 3, 'Seeds of Destruction Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3315, 0, 1), +(3316, 3, 'Underfoot Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3316, 0, 1), +(3317, 3, 'House of Thule Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3317, 0, 1), +(3318, 3, 'Veil of Alaris Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3318, 0, 1), +(3319, 3, 'Rain of Fear Hunter', 'Live Hunter targets matched to local EQEmu NPC spawns.', 3319, 0, 1) +ON DUPLICATE KEY UPDATE +`parent_id` = VALUES(`parent_id`), +`name` = VALUES(`name`), +`description` = VALUES(`description`), +`sort_order` = VALUES(`sort_order`), +`enabled` = VALUES(`enabled`); +)" +R"( + +INSERT INTO `custom_achievements` +(`id`, `category_id`, `slug`, `name`, `description`, `points`, `hidden`, `repeatable`, `sort_order`, `created_at`, `enabled`) +VALUES +(8100480, 3300, 'hunter_live_100480', 'Hunter of The Qeynos Hills', 'Defeat 2 matched live Hunter targets in The Qeynos Hills.', 30, 0, 0, 100480, UNIX_TIMESTAMP(), 1), +(8101180, 3300, 'hunter_live_101180', 'Hunter of The Liberated Citadel of Runnyeye', 'Defeat 1 matched live Hunter target in The Liberated Citadel of Runnyeye.', 30, 0, 0, 101180, UNIX_TIMESTAMP(), 1), +(8101380, 3300, 'hunter_live_101380', 'Hunter of The Northern Plains of Karana', 'Defeat 7 matched live Hunter targets in The Northern Plains of Karana.', 30, 0, 0, 101380, UNIX_TIMESTAMP(), 1), +(8101480, 3300, 'hunter_live_101480', 'Hunter of The Southern Plains of Karana', 'Defeat 12 matched live Hunter targets in The Southern Plains of Karana.', 30, 0, 0, 101480, UNIX_TIMESTAMP(), 1), +(8101880, 3300, 'hunter_live_101880', 'Hunter of The Lair of the Splitpaw', 'Defeat 4 matched live Hunter targets in The Lair of the Splitpaw.', 30, 0, 0, 101880, UNIX_TIMESTAMP(), 1), +(8102780, 3300, 'hunter_live_102780', 'Hunter of The Lavastorm Mountains', 'Defeat 4 matched live Hunter targets in The Lavastorm Mountains.', 30, 0, 0, 102780, UNIX_TIMESTAMP(), 1), +(8103180, 3300, 'hunter_live_103180', 'Hunter of Solusek''s Eye', 'Defeat 14 matched live Hunter targets in Solusek''s Eye.', 30, 0, 0, 103180, UNIX_TIMESTAMP(), 1), +(8103280, 3300, 'hunter_live_103280', 'Hunter of Nagafen''s Lair', 'Defeat 4 matched live Hunter targets in Nagafen''s Lair.', 30, 0, 0, 103280, UNIX_TIMESTAMP(), 1), +(8103680, 3300, 'hunter_live_103680', 'Hunter of Befallen', 'Defeat 2 matched live Hunter targets in Befallen.', 30, 0, 0, 103680, UNIX_TIMESTAMP(), 1), +(8103980, 3300, 'hunter_live_103980', 'Hunter of The Ruins of Old Paineel', 'Defeat 13 matched live Hunter targets in The Ruins of Old Paineel.', 30, 0, 0, 103980, UNIX_TIMESTAMP(), 1), +(8104480, 3300, 'hunter_live_104480', 'Hunter of Najena', 'Defeat 1 matched live Hunter target in Najena.', 30, 0, 0, 104480, UNIX_TIMESTAMP(), 1), +(8104580, 3300, 'hunter_live_104580', 'Hunter of The Qeynos Aqueduct System', 'Defeat 3 matched live Hunter targets in The Qeynos Aqueduct System.', 30, 0, 0, 104580, UNIX_TIMESTAMP(), 1), +(8104780, 3300, 'hunter_live_104780', 'Hunter of The Feerrott', 'Defeat 6 matched live Hunter targets in The Feerrott.', 30, 0, 0, 104780, UNIX_TIMESTAMP(), 1), +(8105080, 3300, 'hunter_live_105080', 'Hunter of The Rathe Mountains', 'Defeat 6 matched live Hunter targets in The Rathe Mountains.', 30, 0, 0, 105080, UNIX_TIMESTAMP(), 1), +(8105180, 3300, 'hunter_live_105180', 'Hunter of Lake Rathetear', 'Defeat 1 matched live Hunter target in Lake Rathetear.', 30, 0, 0, 105180, UNIX_TIMESTAMP(), 1), +(8105780, 3300, 'hunter_live_105780', 'Hunter of The Lesser Faydark', 'Defeat 5 matched live Hunter targets in The Lesser Faydark.', 30, 0, 0, 105780, UNIX_TIMESTAMP(), 1), +(8105880, 3300, 'hunter_live_105880', 'Hunter of Crushbone', 'Defeat 2 matched live Hunter targets in Crushbone.', 30, 0, 0, 105880, UNIX_TIMESTAMP(), 1), +(8105980, 3300, 'hunter_live_105980', 'Hunter of The Castle of Mistmoore', 'Defeat 7 matched live Hunter targets in The Castle of Mistmoore.', 30, 0, 0, 105980, UNIX_TIMESTAMP(), 1), +(8106380, 3300, 'hunter_live_106380', 'Hunter of The Estate of Unrest', 'Defeat 6 matched live Hunter targets in The Estate of Unrest.', 30, 0, 0, 106380, UNIX_TIMESTAMP(), 1), +(8106480, 3300, 'hunter_live_106480', 'Hunter of Kedge Keep', 'Defeat 9 matched live Hunter targets in Kedge Keep.', 30, 0, 0, 106480, UNIX_TIMESTAMP(), 1), +(8106580, 3300, 'hunter_live_106580', 'Hunter of The City of Guk', 'Defeat 7 matched live Hunter targets in The City of Guk.', 30, 0, 0, 106580, UNIX_TIMESTAMP(), 1), +(8106680, 3300, 'hunter_live_106680', 'Hunter of The Ruins of Old Guk', 'Defeat 20 matched live Hunter targets in The Ruins of Old Guk.', 30, 0, 0, 106680, UNIX_TIMESTAMP(), 1), +(8106880, 3300, 'hunter_live_106880', 'Hunter of Butcherblock Mountains', 'Defeat 1 matched live Hunter target in Butcherblock Mountains.', 30, 0, 0, 106880, UNIX_TIMESTAMP(), 1), +(8107080, 3300, 'hunter_live_107080', 'Hunter of Dagnor''s Cauldron', 'Defeat 4 matched live Hunter targets in Dagnor''s Cauldron.', 30, 0, 0, 107080, UNIX_TIMESTAMP(), 1), +(8107380, 3300, 'hunter_live_107380', 'Hunter of The Permafrost Caverns', 'Defeat 6 matched live Hunter targets in The Permafrost Caverns.', 30, 0, 0, 107380, UNIX_TIMESTAMP(), 1), +(8110080, 3300, 'hunter_live_110080', 'Hunter of The Stonebrunt Mountains', 'Defeat 7 matched live Hunter targets in The Stonebrunt Mountains.', 30, 0, 0, 110080, UNIX_TIMESTAMP(), 1), +(8110180, 3300, 'hunter_live_110180', 'Hunter of The Warrens', 'Defeat 2 matched live Hunter targets in The Warrens.', 30, 0, 0, 110180, UNIX_TIMESTAMP(), 1), +(8118180, 3300, 'hunter_live_118180', 'Hunter of Jaggedpine Forest', 'Defeat 6 matched live Hunter targets in Jaggedpine Forest.', 30, 0, 0, 118180, UNIX_TIMESTAMP(), 1), +(8118280, 3300, 'hunter_live_118280', 'Hunter of Nedaria''s Landing', 'Defeat 1 matched live Hunter target in Nedaria''s Landing.', 30, 0, 0, 118280, UNIX_TIMESTAMP(), 1), +(8138480, 3300, 'hunter_live_138480', 'Hunter of Freeport Sewers', 'Defeat 1 matched live Hunter target in Freeport Sewers.', 30, 0, 0, 138480, UNIX_TIMESTAMP(), 1), +(8139280, 3300, 'hunter_live_139280', 'Hunter of North Desert of Ro', 'Defeat 1 matched live Hunter target in North Desert of Ro.', 30, 0, 0, 139280, UNIX_TIMESTAMP(), 1), +(8140780, 3300, 'hunter_live_140780', 'Hunter of Highpass Hold', 'Defeat 4 matched live Hunter targets in Highpass Hold.', 30, 0, 0, 140780, UNIX_TIMESTAMP(), 1), +(8141580, 3300, 'hunter_live_141580', 'Hunter of The Misty Thicket', 'Defeat 1 matched live Hunter target in The Misty Thicket.', 30, 0, 0, 141580, UNIX_TIMESTAMP(), 1), +(8153980, 3300, 'hunter_live_153980', 'Hunter of The Hole', 'Defeat 6 matched live Hunter targets in The Hole.', 30, 0, 0, 153980, UNIX_TIMESTAMP(), 1), +(8154880, 3300, 'hunter_live_154880', 'Hunter of Accursed Temple of Cazic-Thule', 'Defeat 50 matched live Hunter targets in Accursed Temple of Cazic-Thule.', 30, 0, 0, 154880, UNIX_TIMESTAMP(), 1), +(8158680, 3300, 'hunter_live_158680', 'Hunter of The Plane of Hate', 'Defeat 34 matched live Hunter targets in The Plane of Hate.', 30, 0, 0, 158680, UNIX_TIMESTAMP(), 1), +(8207880, 3301, 'hunter_live_207880', 'Hunter of The Field of Bone', 'Defeat 3 matched live Hunter targets in The Field of Bone.', 30, 0, 0, 207880, UNIX_TIMESTAMP(), 1), +(8207980, 3301, 'hunter_live_207980', 'Hunter of The Warsliks Woods', 'Defeat 2 matched live Hunter targets in The Warsliks Woods.', 30, 0, 0, 207980, UNIX_TIMESTAMP(), 1), +(8208180, 3301, 'hunter_live_208180', 'Hunter of The Temple of Droga', 'Defeat 2 matched live Hunter targets in The Temple of Droga.', 30, 0, 0, 208180, UNIX_TIMESTAMP(), 1), +(8208380, 3301, 'hunter_live_208380', 'Hunter of The Swamp of No Hope', 'Defeat 18 matched live Hunter targets in The Swamp of No Hope.', 30, 0, 0, 208380, UNIX_TIMESTAMP(), 1), +(8208580, 3301, 'hunter_live_208580', 'Hunter of Lake of Ill Omen', 'Defeat 1 matched live Hunter target in Lake of Ill Omen.', 30, 0, 0, 208580, UNIX_TIMESTAMP(), 1), +(8208680, 3301, 'hunter_live_208680', 'Hunter of The Dreadlands', 'Defeat 3 matched live Hunter targets in The Dreadlands.', 30, 0, 0, 208680, UNIX_TIMESTAMP(), 1), +(8208780, 3301, 'hunter_live_208780', 'Hunter of The Burning Wood', 'Defeat 4 matched live Hunter targets in The Burning Wood.', 30, 0, 0, 208780, UNIX_TIMESTAMP(), 1), +(8208880, 3301, 'hunter_live_208880', 'Hunter of Kaesora', 'Defeat 8 matched live Hunter targets in Kaesora.', 30, 0, 0, 208880, UNIX_TIMESTAMP(), 1), +(8208980, 3301, 'hunter_live_208980', 'Hunter of The Ruins of Sebilis', 'Defeat 21 matched live Hunter targets in The Ruins of Sebilis.', 30, 0, 0, 208980, UNIX_TIMESTAMP(), 1), +(8209280, 3301, 'hunter_live_209280', 'Hunter of Frontier Mountains', 'Defeat 2 matched live Hunter targets in Frontier Mountains.', 30, 0, 0, 209280, UNIX_TIMESTAMP(), 1), +(8209580, 3301, 'hunter_live_209580', 'Hunter of Trakanon''s Teeth', 'Defeat 31 matched live Hunter targets in Trakanon''s Teeth.', 30, 0, 0, 209580, UNIX_TIMESTAMP(), 1), +(8209680, 3301, 'hunter_live_209680', 'Hunter of Timorous Deep', 'Defeat 2 matched live Hunter targets in Timorous Deep.', 30, 0, 0, 209680, UNIX_TIMESTAMP(), 1), +(8209780, 3301, 'hunter_live_209780', 'Hunter of Kurn''s Tower', 'Defeat 2 matched live Hunter targets in Kurn''s Tower.', 30, 0, 0, 209780, UNIX_TIMESTAMP(), 1), +(8210280, 3301, 'hunter_live_210280', 'Hunter of Karnor''s Castle', 'Defeat 12 matched live Hunter targets in Karnor''s Castle.', 30, 0, 0, 210280, UNIX_TIMESTAMP(), 1), +(8210380, 3301, 'hunter_live_210380', 'Hunter of Chardok', 'Defeat 18 matched live Hunter targets in Chardok.', 30, 0, 0, 210380, UNIX_TIMESTAMP(), 1), +(8210480, 3301, 'hunter_live_210480', 'Hunter of The Crypt of Dalnir', 'Defeat 6 matched live Hunter targets in The Crypt of Dalnir.', 30, 0, 0, 210480, UNIX_TIMESTAMP(), 1), +(8210580, 3301, 'hunter_live_210580', 'Hunter of The Howling Stones', 'Defeat 14 matched live Hunter targets in The Howling Stones.', 30, 0, 0, 210580, UNIX_TIMESTAMP(), 1), +(8210880, 3301, 'hunter_live_210880', 'Hunter of Veeshan''s Peak', 'Defeat 2 matched live Hunter targets in Veeshan''s Peak.', 30, 0, 0, 210880, UNIX_TIMESTAMP(), 1), +(8210980, 3301, 'hunter_live_210980', 'Hunter of Veksar', 'Defeat 22 matched live Hunter targets in Veksar.', 30, 0, 0, 210980, UNIX_TIMESTAMP(), 1), +(8227780, 3301, 'hunter_live_227780', 'Hunter of Chardok: The Halls of Betrayal', 'Defeat 9 matched live Hunter targets in Chardok: The Halls of Betrayal.', 30, 0, 0, 227780, UNIX_TIMESTAMP(), 1), +(8250880, 3301, 'hunter_live_250880', 'Hunter of Veeshan''s Peak', 'Defeat 6 matched live Hunter targets in Veeshan''s Peak.', 30, 0, 0, 250880, UNIX_TIMESTAMP(), 1), +(8311080, 3302, 'hunter_live_311080', 'Hunter of The Iceclad Ocean', 'Defeat 3 matched live Hunter targets in The Iceclad Ocean.', 30, 0, 0, 311080, UNIX_TIMESTAMP(), 1), +(8311280, 3302, 'hunter_live_311280', 'Hunter of Velketor''s Labyrinth', 'Defeat 2 matched live Hunter targets in Velketor''s Labyrinth.', 30, 0, 0, 311280, UNIX_TIMESTAMP(), 1), +(8311680, 3302, 'hunter_live_311680', 'Hunter of Eastern Wastes', 'Defeat 4 matched live Hunter targets in Eastern Wastes.', 30, 0, 0, 311680, UNIX_TIMESTAMP(), 1) +ON DUPLICATE KEY UPDATE +`category_id` = VALUES(`category_id`), +`name` = VALUES(`name`), +`description` = VALUES(`description`), +`points` = VALUES(`points`), +`sort_order` = VALUES(`sort_order`), +`enabled` = VALUES(`enabled`); +)" +R"( + +INSERT INTO `custom_achievements` +(`id`, `category_id`, `slug`, `name`, `description`, `points`, `hidden`, `repeatable`, `sort_order`, `created_at`, `enabled`) +VALUES +(8311780, 3302, 'hunter_live_311780', 'Hunter of Cobalt Scar', 'Defeat 1 matched live Hunter target in Cobalt Scar.', 30, 0, 0, 311780, UNIX_TIMESTAMP(), 1), +(8311880, 3302, 'hunter_live_311880', 'Hunter of The Great Divide', 'Defeat 1 matched live Hunter target in The Great Divide.', 30, 0, 0, 311880, UNIX_TIMESTAMP(), 1), +(8311980, 3302, 'hunter_live_311980', 'Hunter of The Wakening Land', 'Defeat 2 matched live Hunter targets in The Wakening Land.', 30, 0, 0, 311980, UNIX_TIMESTAMP(), 1), +(8312080, 3302, 'hunter_live_312080', 'Hunter of The Western Wastes', 'Defeat 1 matched live Hunter target in The Western Wastes.', 30, 0, 0, 312080, UNIX_TIMESTAMP(), 1), +(8312180, 3302, 'hunter_live_312180', 'Hunter of The Crystal Caverns', 'Defeat 1 matched live Hunter target in The Crystal Caverns.', 30, 0, 0, 312180, UNIX_TIMESTAMP(), 1), +(8312380, 3302, 'hunter_live_312380', 'Hunter of Dragon Necropolis', 'Defeat 5 matched live Hunter targets in Dragon Necropolis.', 30, 0, 0, 312380, UNIX_TIMESTAMP(), 1), +(8312580, 3302, 'hunter_live_312580', 'Hunter of Siren''s Grotto', 'Defeat 4 matched live Hunter targets in Siren''s Grotto.', 30, 0, 0, 312580, UNIX_TIMESTAMP(), 1), +(8312980, 3302, 'hunter_live_312980', 'Hunter of Icewell Keep', 'Defeat 2 matched live Hunter targets in Icewell Keep.', 30, 0, 0, 312980, UNIX_TIMESTAMP(), 1), +(8352680, 3302, 'hunter_live_352680', 'Hunter of The Plane of Mischief', 'Defeat 25 matched live Hunter targets in The Plane of Mischief.', 30, 0, 0, 352680, UNIX_TIMESTAMP(), 1), +(8380280, 3302, 'hunter_live_380280', 'Hunter of The Sleeper''s Tomb', 'Defeat 1 matched live Hunter target in The Sleeper''s Tomb.', 30, 0, 0, 380280, UNIX_TIMESTAMP(), 1), +(8380380, 3302, 'hunter_live_380380', 'Hunter of Skyshrine', 'Defeat 2 matched live Hunter targets in Skyshrine.', 30, 0, 0, 380380, UNIX_TIMESTAMP(), 1), +(8415380, 3303, 'hunter_live_415380', 'Hunter of The Echo Caverns', 'Defeat 7 matched live Hunter targets in The Echo Caverns.', 30, 0, 0, 415380, UNIX_TIMESTAMP(), 1), +(8415480, 3303, 'hunter_live_415480', 'Hunter of The Acrylia Caverns', 'Defeat 8 matched live Hunter targets in The Acrylia Caverns.', 30, 0, 0, 415480, UNIX_TIMESTAMP(), 1), +(8415680, 3303, 'hunter_live_415680', 'Hunter of The Paludal Caverns', 'Defeat 2 matched live Hunter targets in The Paludal Caverns.', 30, 0, 0, 415680, UNIX_TIMESTAMP(), 1), +(8415780, 3303, 'hunter_live_415780', 'Hunter of The Fungus Grove', 'Defeat 1 matched live Hunter target in The Fungus Grove.', 30, 0, 0, 415780, UNIX_TIMESTAMP(), 1), +(8416180, 3303, 'hunter_live_416180', 'Hunter of Netherbian Lair', 'Defeat 6 matched live Hunter targets in Netherbian Lair.', 30, 0, 0, 416180, UNIX_TIMESTAMP(), 1), +(8416280, 3303, 'hunter_live_416280', 'Hunter of Ssraeshza Temple', 'Defeat 15 matched live Hunter targets in Ssraeshza Temple.', 30, 0, 0, 416280, UNIX_TIMESTAMP(), 1), +(8416380, 3303, 'hunter_live_416380', 'Hunter of Grieg''s End', 'Defeat 1 matched live Hunter target in Grieg''s End.', 30, 0, 0, 416380, UNIX_TIMESTAMP(), 1), +(8416480, 3303, 'hunter_live_416480', 'Hunter of The Deep', 'Defeat 10 matched live Hunter targets in The Deep.', 30, 0, 0, 416480, UNIX_TIMESTAMP(), 1), +(8416580, 3303, 'hunter_live_416580', 'Hunter of Shadeweaver''s Thicket', 'Defeat 1 matched live Hunter target in Shadeweaver''s Thicket.', 30, 0, 0, 416580, UNIX_TIMESTAMP(), 1), +(8416680, 3303, 'hunter_live_416680', 'Hunter of Hollowshade Moor', 'Defeat 11 matched live Hunter targets in Hollowshade Moor.', 30, 0, 0, 416680, UNIX_TIMESTAMP(), 1), +(8416880, 3303, 'hunter_live_416880', 'Hunter of Marus Seru', 'Defeat 1 matched live Hunter target in Marus Seru.', 30, 0, 0, 416880, UNIX_TIMESTAMP(), 1), +(8417080, 3303, 'hunter_live_417080', 'Hunter of The Twilight Sea', 'Defeat 16 matched live Hunter targets in The Twilight Sea.', 30, 0, 0, 417080, UNIX_TIMESTAMP(), 1), +(8417180, 3303, 'hunter_live_417180', 'Hunter of The Grey', 'Defeat 6 matched live Hunter targets in The Grey.', 30, 0, 0, 417180, UNIX_TIMESTAMP(), 1), +(8417280, 3303, 'hunter_live_417280', 'Hunter of The Tenebrous Mountains', 'Defeat 4 matched live Hunter targets in The Tenebrous Mountains.', 30, 0, 0, 417280, UNIX_TIMESTAMP(), 1), +(8417380, 3303, 'hunter_live_417380', 'Hunter of The Maiden''s Eye', 'Defeat 9 matched live Hunter targets in The Maiden''s Eye.', 30, 0, 0, 417380, UNIX_TIMESTAMP(), 1), +(8417480, 3303, 'hunter_live_417480', 'Hunter of The Dawnshroud Peaks', 'Defeat 8 matched live Hunter targets in The Dawnshroud Peaks.', 30, 0, 0, 417480, UNIX_TIMESTAMP(), 1), +(8417580, 3303, 'hunter_live_417580', 'Hunter of The Scarlet Desert', 'Defeat 26 matched live Hunter targets in The Scarlet Desert.', 30, 0, 0, 417580, UNIX_TIMESTAMP(), 1), +(8417680, 3303, 'hunter_live_417680', 'Hunter of The Umbral Plains', 'Defeat 9 matched live Hunter targets in The Umbral Plains.', 30, 0, 0, 417680, UNIX_TIMESTAMP(), 1), +(8417980, 3303, 'hunter_live_417980', 'Hunter of The Akheva Ruins', 'Defeat 8 matched live Hunter targets in The Akheva Ruins.', 30, 0, 0, 417980, UNIX_TIMESTAMP(), 1), +(8480980, 3303, 'hunter_live_480980', 'Hunter of Grimling Forest', 'Defeat 4 matched live Hunter targets in Grimling Forest.', 30, 0, 0, 480980, UNIX_TIMESTAMP(), 1), +(8520080, 3304, 'hunter_live_520080', 'Hunter of the Ruins of Lxanvom', 'Defeat 20 matched live Hunter targets in the Ruins of Lxanvom.', 30, 0, 0, 520080, UNIX_TIMESTAMP(), 1), +(8520180, 3304, 'hunter_live_520180', 'Hunter of The Plane of Justice', 'Defeat 10 matched live Hunter targets in The Plane of Justice.', 30, 0, 0, 520180, UNIX_TIMESTAMP(), 1), +(8520480, 3304, 'hunter_live_520480', 'Hunter of The Plane of Nightmare', 'Defeat 6 matched live Hunter targets in The Plane of Nightmare.', 30, 0, 0, 520480, UNIX_TIMESTAMP(), 1), +(8520580, 3304, 'hunter_live_520580', 'Hunter of The Plane of Disease', 'Defeat 4 matched live Hunter targets in The Plane of Disease.', 30, 0, 0, 520580, UNIX_TIMESTAMP(), 1), +(8520680, 3304, 'hunter_live_520680', 'Hunter of The Plane of Innovation', 'Defeat 1 matched live Hunter target in The Plane of Innovation.', 30, 0, 0, 520680, UNIX_TIMESTAMP(), 1), +(8520780, 3304, 'hunter_live_520780', 'Hunter of Torment, the Plane of Pain', 'Defeat 7 matched live Hunter targets in Torment, the Plane of Pain.', 30, 0, 0, 520780, UNIX_TIMESTAMP(), 1), +(8520880, 3304, 'hunter_live_520880', 'Hunter of The Plane of Valor', 'Defeat 9 matched live Hunter targets in The Plane of Valor.', 30, 0, 0, 520880, UNIX_TIMESTAMP(), 1), +(8520980, 3304, 'hunter_live_520980', 'Hunter of Torden, the Bastion of Thunder', 'Defeat 15 matched live Hunter targets in Torden, the Bastion of Thunder.', 30, 0, 0, 520980, UNIX_TIMESTAMP(), 1), +(8521180, 3304, 'hunter_live_521180', 'Hunter of The Halls of Honor', 'Defeat 6 matched live Hunter targets in The Halls of Honor.', 30, 0, 0, 521180, UNIX_TIMESTAMP(), 1), +(8521280, 3304, 'hunter_live_521280', 'Hunter of The Tower of Solusek Ro', 'Defeat 6 matched live Hunter targets in The Tower of Solusek Ro.', 30, 0, 0, 521280, UNIX_TIMESTAMP(), 1), +(8521480, 3304, 'hunter_live_521480', 'Hunter of Drunder, the Fortress of Zek', 'Defeat 7 matched live Hunter targets in Drunder, the Fortress of Zek.', 30, 0, 0, 521480, UNIX_TIMESTAMP(), 1), +(8521580, 3304, 'hunter_live_521580', 'Hunter of Eryslai, the Kingdom of Wind', 'Defeat 4 matched live Hunter targets in Eryslai, the Kingdom of Wind.', 30, 0, 0, 521580, UNIX_TIMESTAMP(), 1), +(8521680, 3304, 'hunter_live_521680', 'Hunter of The Reef of Coirnav', 'Defeat 17 matched live Hunter targets in The Reef of Coirnav.', 30, 0, 0, 521680, UNIX_TIMESTAMP(), 1), +(8521780, 3304, 'hunter_live_521780', 'Hunter of Doomfire, the Burning Lands', 'Defeat 23 matched live Hunter targets in Doomfire, the Burning Lands.', 30, 0, 0, 521780, UNIX_TIMESTAMP(), 1), +(8522080, 3304, 'hunter_live_522080', 'Hunter of The Temple of Marr', 'Defeat 1 matched live Hunter target in The Temple of Marr.', 30, 0, 0, 522080, UNIX_TIMESTAMP(), 1), +(8522180, 3304, 'hunter_live_522180', 'Hunter of The Lair of Terris-Thule', 'Defeat 2 matched live Hunter targets in The Lair of Terris-Thule.', 30, 0, 0, 522180, UNIX_TIMESTAMP(), 1), +(8127880, 3305, 'hunter_live_127880', 'Hunter of The Caverns of Exile', 'Defeat 9 matched live Hunter targets in The Caverns of Exile.', 30, 0, 0, 127880, UNIX_TIMESTAMP(), 1), +(8622480, 3305, 'hunter_live_622480', 'Hunter of The Gulf of Gunthak', 'Defeat 19 matched live Hunter targets in The Gulf of Gunthak.', 30, 0, 0, 622480, UNIX_TIMESTAMP(), 1), +(8622580, 3305, 'hunter_live_622580', 'Hunter of Dulak''s Harbor', 'Defeat 17 matched live Hunter targets in Dulak''s Harbor.', 30, 0, 0, 622580, UNIX_TIMESTAMP(), 1), +(8622680, 3305, 'hunter_live_622680', 'Hunter of The Torgiran Mines', 'Defeat 20 matched live Hunter targets in The Torgiran Mines.', 30, 0, 0, 622680, UNIX_TIMESTAMP(), 1), +(8622780, 3305, 'hunter_live_622780', 'Hunter of The Crypt of Nadox', 'Defeat 15 matched live Hunter targets in The Crypt of Nadox.', 30, 0, 0, 622780, UNIX_TIMESTAMP(), 1), +(8622880, 3305, 'hunter_live_622880', 'Hunter of Hate''s Fury', 'Defeat 11 matched live Hunter targets in Hate''s Fury.', 30, 0, 0, 622880, UNIX_TIMESTAMP(), 1), +(8714280, 3306, 'hunter_live_714280', 'Hunter of Spider Den', 'Defeat 1 matched live Hunter target in Spider Den.', 30, 0, 0, 714280, UNIX_TIMESTAMP(), 1), +(8745080, 3306, 'hunter_live_745080', 'Hunter of Arena of Chance', 'Defeat 1 matched live Hunter target in Arena of Chance.', 30, 0, 0, 745080, UNIX_TIMESTAMP(), 1) +ON DUPLICATE KEY UPDATE +`category_id` = VALUES(`category_id`), +`name` = VALUES(`name`), +`description` = VALUES(`description`), +`points` = VALUES(`points`), +`sort_order` = VALUES(`sort_order`), +`enabled` = VALUES(`enabled`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +VALUES +(18000001, 8100480, 0, 'npc_name_kill', 'npc_name', 4147, 'pyzjn', 1, 4, 0, 0), +(18000002, 8100480, 1, 'npc_name_kill', 'npc_name', 4171, 'varsoon', 1, 4, 0, 0), +(18000003, 8101180, 0, 'npc_name_kill', 'npc_name', 11124, 'the sporali moldmaster', 1, 11, 0, 0), +(18000004, 8101380, 0, 'npc_name_kill', 'npc_name', 13108, 'ashenpaw', 1, 13, 0, 0), +(18000005, 8101380, 1, 'npc_name_kill', 'npc_name', 13111, 'bristletoe', 1, 13, 0, 0), +(18000006, 8101380, 2, 'npc_name_kill', 'npc_name', 13115, 'callowwing', 1, 13, 0, 0), +(18000007, 8101380, 3, 'npc_name_kill', 'npc_name', 13117, 'grimtooth', 1, 13, 0, 0), +(18000008, 8101380, 4, 'npc_name_kill', 'npc_name', 13113, 'korvik the cursed', 1, 13, 0, 0), +(18000009, 8101380, 5, 'npc_name_kill', 'npc_name', 13107, 'swiftclaw', 1, 13, 0, 0), +(18000010, 8101380, 6, 'npc_name_kill', 'npc_name', 13121, 'timbur the tiny', 1, 13, 0, 0), +(18000011, 8101480, 0, 'npc_name_kill', 'npc_name', 14142, 'grizzleknot', 1, 14, 0, 0), +(18000012, 8101480, 1, 'npc_name_kill', 'npc_name', 14137, 'knari morawk', 1, 14, 0, 0), +(18000013, 8101480, 2, 'npc_name_kill', 'npc_name', 14197, 'kroldir thunderhoof', 1, 14, 0, 0), +(18000014, 8101480, 3, 'npc_name_kill', 'npc_name', 14134, 'lord grimrot', 1, 14, 0, 0), +(18000015, 8101480, 4, 'npc_name_kill', 'npc_name', 14131, 'marik clubthorn', 1, 14, 0, 0), +(18000016, 8101480, 5, 'npc_name_kill', 'npc_name', 14136, 'mroon', 1, 14, 0, 0), +(18000017, 8101480, 6, 'npc_name_kill', 'npc_name', 14144, 'narra tanith', 1, 14, 0, 0), +(18000018, 8101480, 7, 'npc_name_kill', 'npc_name', 14193, 'nisch val torash mashk', 1, 14, 0, 0), +(18000019, 8101480, 8, 'npc_name_kill', 'npc_name', 14194, 'rosch val l`vlor', 1, 14, 0, 0), +(18000020, 8101480, 9, 'npc_name_kill', 'npc_name', 14125, 'synger foxfyre', 1, 14, 0, 0), +(18000021, 8101480, 10, 'npc_name_kill', 'npc_name', 14192, 'tesch val deval`nmak', 1, 14, 0, 0), +(18000022, 8101480, 11, 'npc_name_kill', 'npc_name', 14195, 'tesch val kadvem', 1, 14, 0, 0), +(18000023, 8101880, 0, 'npc_name_kill', 'npc_name', 18138, 'nisch val torash mashk', 1, 18, 0, 0), +(18000024, 8101880, 1, 'npc_name_kill', 'npc_name', 18141, 'rosch val l`vlor', 1, 18, 0, 0), +(18000025, 8101880, 2, 'npc_name_kill', 'npc_name', 18142, 'tesch val deval`nmak', 1, 18, 0, 0), +(18000026, 8101880, 3, 'npc_name_kill', 'npc_name', 18122, 'tesch val kadvem', 1, 18, 0, 0), +(18000027, 8102780, 0, 'npc_name_kill', 'npc_name', 27152, 'a lesser nightmare', 1, 27, 0, 0), +(18000028, 8102780, 1, 'npc_name_kill', 'npc_name', 27168, 'tisella', 1, 27, 0, 0), +(18000029, 8102780, 2, 'npc_name_kill', 'npc_name', 27148, 'a warbone monk', 1, 27, 0, 0), +(18000030, 8102780, 3, 'npc_name_kill', 'npc_name', 27149, 'a warbone spearman', 1, 27, 0, 0), +(18000031, 8103180, 0, 'npc_name_kill', 'npc_name', 31147, 'captain bipnubble', 1, 31, 0, 0), +(18000032, 8103180, 1, 'npc_name_kill', 'npc_name', 31118, 'cwg model exg', 1, 31, 0, 0), +(18000033, 8103180, 2, 'npc_name_kill', 'npc_name', 31145, 'fire goblin bartender', 1, 31, 0, 0), +(18000034, 8103180, 3, 'npc_name_kill', 'npc_name', 31124, 'flame goblin foreman', 1, 31, 0, 0), +(18000035, 8103180, 4, 'npc_name_kill', 'npc_name', 31132, 'gabbie mardoddle', 1, 31, 0, 0), +(18000036, 8103180, 5, 'npc_name_kill', 'npc_name', 31022, 'goblin high shaman', 1, 31, 0, 0), +(18000037, 8103180, 6, 'npc_name_kill', 'npc_name', 31134, 'inferno goblin captain', 1, 31, 0, 0), +(18000038, 8103180, 7, 'npc_name_kill', 'npc_name', 31144, 'inferno goblin torturer', 1, 31, 0, 0), +(18000039, 8103180, 8, 'npc_name_kill', 'npc_name', 31136, 'kindle', 1, 31, 0, 0), +(18000040, 8103180, 9, 'npc_name_kill', 'npc_name', 31146, 'kobold predator', 1, 31, 0, 0), +(18000041, 8103180, 10, 'npc_name_kill', 'npc_name', 31143, 'lava elemental', 1, 31, 0, 0), +(18000042, 8103180, 11, 'npc_name_kill', 'npc_name', 31085, 'reckless efreeti', 1, 31, 0, 0), +(18000043, 8103180, 12, 'npc_name_kill', 'npc_name', 31127, 'singe', 1, 31, 0, 0), +(18000044, 8103180, 13, 'npc_name_kill', 'npc_name', 31128, 'solusek goblin king', 1, 31, 0, 0), +(18000045, 8103280, 0, 'npc_name_kill', 'npc_name', 32062, 'efreeti lord djarn', 1, 32, 0, 0), +(18000046, 8103280, 1, 'npc_name_kill', 'npc_name', 32022, 'king tranix', 1, 32, 0, 0), +(18000047, 8103280, 2, 'npc_name_kill', 'npc_name', 32041, 'magus rokyl', 1, 32, 0, 0), +(18000048, 8103280, 3, 'npc_name_kill', 'npc_name', 32020, 'warlord skarlon', 1, 32, 0, 0), +(18000049, 8103680, 0, 'npc_name_kill', 'npc_name', 36095, 'priest amiaz', 1, 36, 0, 0), +(18000050, 8103680, 1, 'npc_name_kill', 'npc_name', 36097, 'the thaumaturgist', 1, 36, 0, 0), +(18000051, 8103980, 0, 'npc_name_kill', 'npc_name', 39158, 'bejeweled elemental', 1, 39, 0, 0), +(18000052, 8103980, 1, 'npc_name_kill', 'npc_name', 39141, 'commander yarik', 1, 39, 0, 0), +(18000053, 8103980, 2, 'npc_name_kill', 'npc_name', 39142, 'gibartik', 1, 39, 0, 0), +(18000054, 8103980, 3, 'npc_name_kill', 'npc_name', 39150, 'initiate sirlis', 1, 39, 0, 0), +(18000055, 8103980, 4, 'npc_name_kill', 'npc_name', 39162, 'irslak the wretched', 1, 39, 0, 0), +(18000056, 8103980, 5, 'npc_name_kill', 'npc_name', 39151, 'muck covered elemental', 1, 39, 0, 0), +(18000057, 8103980, 6, 'npc_name_kill', 'npc_name', 39149, 'niltoth the unholy', 1, 39, 0, 0), +(18000058, 8103980, 7, 'npc_name_kill', 'npc_name', 39143, 'retseth tretse', 1, 39, 0, 0), +(18000059, 8103980, 8, 'npc_name_kill', 'npc_name', 39134, 'rocksoul', 1, 39, 0, 0), +(18000060, 8103980, 9, 'npc_name_kill', 'npc_name', 39135, 'slizik the mighty', 1, 39, 0, 0), +(18000061, 8103980, 10, 'npc_name_kill', 'npc_name', 39153, 'stonegrinder minion', 1, 39, 0, 0), +(18000062, 8103980, 11, 'npc_name_kill', 'npc_name', 39132, 'stonesoul the unmoving', 1, 39, 0, 0), +(18000063, 8103980, 12, 'npc_name_kill', 'npc_name', 39152, 'ulrik the devout', 1, 39, 0, 0), +(18000064, 8104480, 0, 'npc_name_kill', 'npc_name', 44024, 'rathyl', 1, 44, 0, 0), +(18000065, 8104580, 0, 'npc_name_kill', 'npc_name', 45123, 'an injured rat', 1, 45, 0, 0), +(18000066, 8104580, 1, 'npc_name_kill', 'npc_name', 45121, 'a nesting rat', 1, 45, 0, 0), +(18000067, 8104580, 2, 'npc_name_kill', 'npc_name', 45125, 'a shady mercenary', 1, 45, 0, 0), +(18000068, 8104780, 0, 'npc_name_kill', 'npc_name', 47199, 'a silverflank guardian', 1, 47, 0, 0), +(18000069, 8104780, 1, 'npc_name_kill', 'npc_name', 47204, 'tae ew archon', 1, 47, 0, 0), +(18000070, 8104780, 2, 'npc_name_kill', 'npc_name', 47203, 'tae ew diviner', 1, 47, 0, 0), +(18000071, 8104780, 3, 'npc_name_kill', 'npc_name', 47182, 'a tae ew spiritualist', 1, 47, 0, 0), +(18000072, 8104780, 4, 'npc_name_kill', 'npc_name', 47198, 'tae ew templar', 1, 47, 0, 0), +(18000073, 8104780, 5, 'npc_name_kill', 'npc_name', 47195, 'thul tae ew cenobite', 1, 47, 0, 0), +(18000074, 8105080, 0, 'npc_name_kill', 'npc_name', 50057, 'bloodneedle', 1, 50, 0, 0), +(18000075, 8105080, 1, 'npc_name_kill', 'npc_name', 50348, 'mortificator syythrak', 1, 50, 0, 0), +(18000076, 8105080, 2, 'npc_name_kill', 'npc_name', 50350, 'oculys ogrefiend', 1, 50, 0, 0), +(18000077, 8105080, 3, 'npc_name_kill', 'npc_name', 50347, 'petrifin', 1, 50, 0, 0), +(18000078, 8105080, 4, 'npc_name_kill', 'npc_name', 50351, 'quid rilstone', 1, 50, 0, 0), +(18000079, 8105080, 5, 'npc_name_kill', 'npc_name', 50349, 'shardwing', 1, 50, 0, 0), +(18000080, 8105180, 0, 'npc_name_kill', 'npc_name', 51131, 'a gnoll embalmer', 1, 51, 0, 0), +(18000081, 8105780, 0, 'npc_name_kill', 'npc_name', 57105, 'crookstinger', 1, 57, 0, 0), +(18000082, 8105780, 1, 'npc_name_kill', 'npc_name', 57120, 'mina glimmerwing', 1, 57, 0, 0), +(18000083, 8105780, 2, 'npc_name_kill', 'npc_name', 57108, 'old dimshimmer', 1, 57, 0, 0), +(18000084, 8105780, 3, 'npc_name_kill', 'npc_name', 57005, 'queen nasheeji', 1, 57, 0, 0), +(18000085, 8105780, 4, 'npc_name_kill', 'npc_name', 57002, 'whimsy larktwitter', 1, 57, 0, 0), +(18000086, 8105880, 0, 'npc_name_kill', 'npc_name', 58040, 'orc taskmaster', 1, 58, 0, 0), +(18000087, 8105880, 1, 'npc_name_kill', 'npc_name', 58002, 'orc warlord', 1, 58, 0, 0), +(18000088, 8105980, 0, 'npc_name_kill', 'npc_name', 59020, 'an avenging caitiff', 1, 59, 0, 0), +(18000089, 8105980, 1, 'npc_name_kill', 'npc_name', 59116, 'butler syncall', 1, 59, 0, 0), +(18000090, 8105980, 2, 'npc_name_kill', 'npc_name', 59102, 'a cloaked dhampyre', 1, 59, 0, 0) +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_index` = VALUES(`objective_index`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`), +`zone_id` = VALUES(`zone_id`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +VALUES +(18000091, 8105980, 3, 'npc_name_kill', 'npc_name', 59151, 'garton viswin', 1, 59, 0, 0), +(18000092, 8105980, 4, 'npc_name_kill', 'npc_name', 59133, 'a glyphed ghoul', 1, 59, 0, 0), +(18000093, 8105980, 5, 'npc_name_kill', 'npc_name', 59089, 'lasna cheroon', 1, 59, 0, 0), +(18000094, 8105980, 6, 'npc_name_kill', 'npc_name', 59115, 'maid issis', 1, 59, 0, 0), +(18000095, 8106380, 0, 'npc_name_kill', 'npc_name', 63062, 'garanel rucksif', 1, 63, 0, 0), +(18000096, 8106380, 1, 'npc_name_kill', 'npc_name', 63092, 'lesser blade fiend', 1, 63, 0, 0), +(18000097, 8106380, 2, 'npc_name_kill', 'npc_name', 63075, 'a reanimated hand', 1, 63, 0, 0), +(18000098, 8106380, 3, 'npc_name_kill', 'npc_name', 63086, 'reclusive ghoul magus', 1, 63, 0, 0), +(18000099, 8106380, 4, 'npc_name_kill', 'npc_name', 63010, 'an undead barkeep', 1, 63, 0, 0), +(18000100, 8106380, 5, 'npc_name_kill', 'npc_name', 63003, 'an undead knight of unrest', 1, 63, 0, 0), +(18000101, 8106480, 0, 'npc_name_kill', 'npc_name', 64089, 'cauldronboil', 1, 64, 0, 0), +(18000102, 8106480, 1, 'npc_name_kill', 'npc_name', 64107, 'coralyn kelpmaiden', 1, 64, 0, 0), +(18000103, 8106480, 2, 'npc_name_kill', 'npc_name', 64101, 'a ferocious hammerhead', 1, 64, 0, 0), +(18000104, 8106480, 3, 'npc_name_kill', 'npc_name', 64103, 'a fierce impaler', 1, 64, 0, 0), +(18000105, 8106480, 4, 'npc_name_kill', 'npc_name', 64102, 'a frenzied cauldron shark', 1, 64, 0, 0), +(18000106, 8106480, 5, 'npc_name_kill', 'npc_name', 64105, 'a seahorse matriarch', 1, 64, 0, 0), +(18000107, 8106480, 6, 'npc_name_kill', 'npc_name', 64106, 'a seahorse patriarch', 1, 64, 0, 0), +(18000108, 8106480, 7, 'npc_name_kill', 'npc_name', 64093, 'shellara ebbhunter', 1, 64, 0, 0), +(18000109, 8106480, 8, 'npc_name_kill', 'npc_name', 64087, 'undertow', 1, 64, 0, 0), +(18000110, 8106580, 0, 'npc_name_kill', 'npc_name', 65140, 'a froglok gaz squire', 1, 65, 0, 0), +(18000111, 8106580, 1, 'npc_name_kill', 'npc_name', 65105, 'a froglok realist', 1, 65, 0, 0), +(18000112, 8106580, 2, 'npc_name_kill', 'npc_name', 65148, 'a froglok scryer', 1, 65, 0, 0), +(18000113, 8106580, 3, 'npc_name_kill', 'npc_name', 65128, 'the froglok shin lord', 1, 65, 0, 0), +(18000114, 8106580, 4, 'npc_name_kill', 'npc_name', 65125, 'a froglok summoner', 1, 65, 0, 0), +(18000115, 8106580, 5, 'npc_name_kill', 'npc_name', 65104, 'the froglok warden', 1, 65, 0, 0), +(18000116, 8106580, 6, 'npc_name_kill', 'npc_name', 65146, 'a giant heart spider', 1, 65, 0, 0), +(18000117, 8106680, 0, 'npc_name_kill', 'npc_name', 66146, 'a frenzied ghoul', 1, 66, 0, 0), +(18000118, 8106680, 1, 'npc_name_kill', 'npc_name', 66153, 'a froglok crusader', 1, 66, 0, 0), +(18000119, 8106680, 2, 'npc_name_kill', 'npc_name', 66160, 'a froglok herbalist', 1, 66, 0, 0), +(18000120, 8106680, 3, 'npc_name_kill', 'npc_name', 66159, 'the froglok king', 1, 66, 0, 0), +(18000121, 8106680, 4, 'npc_name_kill', 'npc_name', 66175, 'a froglok noble', 1, 66, 0, 0), +(18000122, 8106680, 5, 'npc_name_kill', 'npc_name', 66121, 'a froglok tactician', 1, 66, 0, 0), +(18000123, 8106680, 6, 'npc_name_kill', 'npc_name', 66120, 'a froglok yun priest', 1, 66, 0, 0), +(18000124, 8106680, 7, 'npc_name_kill', 'npc_name', 66156, 'the ghoul arch magus', 1, 66, 0, 0), +(18000125, 8106680, 8, 'npc_name_kill', 'npc_name', 66171, 'a ghoul assassin', 1, 66, 0, 0), +(18000126, 8106680, 9, 'npc_name_kill', 'npc_name', 66169, 'a ghoul cavalier', 1, 66, 0, 0), +(18000127, 8106680, 10, 'npc_name_kill', 'npc_name', 66092, 'a ghoul executioner', 1, 66, 0, 0), +(18000128, 8106680, 11, 'npc_name_kill', 'npc_name', 66005, 'the ghoul lord', 1, 66, 0, 0), +(18000129, 8106680, 12, 'npc_name_kill', 'npc_name', 66108, 'a ghoul ritualist', 1, 66, 0, 0), +(18000130, 8106680, 13, 'npc_name_kill', 'npc_name', 66165, 'a ghoul sage', 1, 66, 0, 0), +(18000131, 8106680, 14, 'npc_name_kill', 'npc_name', 66100, 'a ghoul savant', 1, 66, 0, 0), +(18000132, 8106680, 15, 'npc_name_kill', 'npc_name', 66163, 'a ghoul sentinel', 1, 66, 0, 0), +(18000133, 8106680, 16, 'npc_name_kill', 'npc_name', 66021, 'a ghoul supplier', 1, 66, 0, 0), +(18000134, 8106680, 17, 'npc_name_kill', 'npc_name', 66178, 'a minotaur elder', 1, 66, 0, 0), +(18000135, 8106680, 18, 'npc_name_kill', 'npc_name', 66173, 'a minotaur patriarch', 1, 66, 0, 0), +(18000136, 8106680, 19, 'npc_name_kill', 'npc_name', 66036, 'a reanimated hand', 1, 66, 0, 0), +(18000137, 8106880, 0, 'npc_name_kill', 'npc_name', 68137, 'glubbsink', 1, 68, 0, 0), +(18000138, 8107080, 0, 'npc_name_kill', 'npc_name', 70047, 'barnacle bones', 1, 70, 0, 0), +(18000139, 8107080, 1, 'npc_name_kill', 'npc_name', 70054, 'flotsam', 1, 70, 0, 0), +(18000140, 8107080, 2, 'npc_name_kill', 'npc_name', 70057, 'jetsam', 1, 70, 0, 0), +(18000141, 8107080, 3, 'npc_name_kill', 'npc_name', 70056, 'squallslither', 1, 70, 0, 0), +(18000142, 8107380, 0, 'npc_name_kill', 'npc_name', 73004, 'an elite honor guard', 1, 73, 0, 0), +(18000143, 8107380, 1, 'npc_name_kill', 'npc_name', 73104, 'a goblin jailmaster', 1, 73, 0, 0), +(18000144, 8107380, 2, 'npc_name_kill', 'npc_name', 73068, 'a goblin preacher', 1, 73, 0, 0), +(18000145, 8107380, 3, 'npc_name_kill', 'npc_name', 73022, 'a goblin scryer', 1, 73, 0, 0), +(18000146, 8107380, 4, 'npc_name_kill', 'npc_name', 73006, 'high priest zaharn', 1, 73, 0, 0), +(18000147, 8107380, 5, 'npc_name_kill', 'npc_name', 73103, 'king thex`ka iv', 1, 73, 0, 0), +(18000148, 8110080, 0, 'npc_name_kill', 'npc_name', 100214, 'arglar the tormentor', 1, 100, 0, 0), +(18000149, 8110080, 1, 'npc_name_kill', 'npc_name', 100208, 'giang yin', 1, 100, 0, 0), +(18000150, 8110080, 2, 'npc_name_kill', 'npc_name', 100198, 'hurglak the destroyer', 1, 100, 0, 0), +(18000151, 8110080, 3, 'npc_name_kill', 'npc_name', 100203, 'jelquar the soulslayer', 1, 100, 0, 0), +(18000152, 8110080, 4, 'npc_name_kill', 'npc_name', 100199, 'rendolr the maimer', 1, 100, 0, 0), +(18000153, 8110080, 5, 'npc_name_kill', 'npc_name', 100076, 'slyder the ancient', 1, 100, 0, 0), +(18000154, 8110080, 6, 'npc_name_kill', 'npc_name', 100097, 'snowbeast', 1, 100, 0, 0), +(18000155, 8110180, 0, 'npc_name_kill', 'npc_name', 101132, 'packmaster dledsh', 1, 101, 0, 0), +(18000156, 8110180, 1, 'npc_name_kill', 'npc_name', 101138, 'warlord drrig', 1, 101, 0, 0), +(18000157, 8118180, 0, 'npc_name_kill', 'npc_name', 181212, 'elishia blackguard', 1, 181, 0, 0), +(18000158, 8118180, 1, 'npc_name_kill', 'npc_name', 181207, 'goldentalon', 1, 181, 0, 0), +(18000159, 8118180, 2, 'npc_name_kill', 'npc_name', 181204, 'lameriae the alluring', 1, 181, 0, 0), +(18000160, 8118180, 3, 'npc_name_kill', 'npc_name', 181053, 'reynold blackguard', 1, 181, 0, 0), +(18000161, 8118180, 4, 'npc_name_kill', 'npc_name', 181194, 'vaurien sticklebush', 1, 181, 0, 0), +(18000162, 8118180, 5, 'npc_name_kill', 'npc_name', 181162, 'zed sticklebush', 1, 181, 0, 0), +(18000163, 8118280, 0, 'npc_name_kill', 'npc_name', 182070, 'a magnificent grizzly', 1, 182, 0, 0), +(18000164, 8138480, 0, 'npc_name_kill', 'npc_name', 384026, 'bad ash', 1, 384, 0, 0), +(18000165, 8139280, 0, 'npc_name_kill', 'npc_name', 392069, 'rahotep', 1, 392, 0, 0), +(18000166, 8140780, 0, 'npc_name_kill', 'npc_name', 5133, 'grenix mucktail', 1, 5, 0, 0), +(18000167, 8140780, 1, 'npc_name_kill', 'npc_name', 5128, 'hagnis shralok', 1, 5, 0, 0), +(18000168, 8140780, 2, 'npc_name_kill', 'npc_name', 5135, 'recfek shralok', 1, 5, 0, 0), +(18000169, 8140780, 3, 'npc_name_kill', 'npc_name', 5127, 'vopuk shralok', 1, 5, 0, 0), +(18000170, 8141580, 0, 'npc_name_kill', 'npc_name', 33154, 'a goblin alchemist', 1, 33, 0, 0), +(18000171, 8153980, 0, 'npc_name_kill', 'npc_name', 39067, 'an ancient construct', 1, 39, 0, 0), +(18000172, 8153980, 1, 'npc_name_kill', 'npc_name', 39117, 'an ancient gargoyle', 1, 39, 0, 0), +(18000173, 8153980, 2, 'npc_name_kill', 'npc_name', 39065, 'an old construct', 1, 39, 0, 0), +(18000174, 8153980, 3, 'npc_name_kill', 'npc_name', 39118, 'an old gargoyle', 1, 39, 0, 0), +(18000175, 8153980, 4, 'npc_name_kill', 'npc_name', 39031, 'a ratman inhabitant', 1, 39, 0, 0), +(18000176, 8153980, 5, 'npc_name_kill', 'npc_name', 39074, 'a temple researcher', 1, 39, 0, 0), +(18000177, 8154880, 0, 'npc_name_kill', 'npc_name', 48220, 'a barbed scale piranha', 1, 48, 0, 0), +(18000178, 8154880, 1, 'npc_name_kill', 'npc_name', 48017, 'a blood claw raptor', 1, 48, 0, 0), +(18000179, 8154880, 2, 'npc_name_kill', 'npc_name', 48121, 'a blood fin piranha', 1, 48, 0, 0), +(18000180, 8154880, 3, 'npc_name_kill', 'npc_name', 48136, 'a crystaline mass', 1, 48, 0, 0) +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_index` = VALUES(`objective_index`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`), +`zone_id` = VALUES(`zone_id`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +VALUES +(18000181, 8154880, 4, 'npc_name_kill', 'npc_name', 48223, 'a diamond scale piranha', 1, 48, 0, 0), +(18000182, 8154880, 5, 'npc_name_kill', 'npc_name', 48119, 'a disciple of thule', 1, 48, 0, 0), +(18000183, 8154880, 6, 'npc_name_kill', 'npc_name', 48122, 'a diseased mosquito', 1, 48, 0, 0), +(18000184, 8154880, 7, 'npc_name_kill', 'npc_name', 48219, 'dismay', 1, 48, 0, 0), +(18000185, 8154880, 8, 'npc_name_kill', 'npc_name', 48156, 'dreadfang', 1, 48, 0, 0), +(18000186, 8154880, 9, 'npc_name_kill', 'npc_name', 48165, 'an enraged amygdalan', 1, 48, 0, 0), +(18000187, 8154880, 10, 'npc_name_kill', 'npc_name', 48216, 'an enraged disciple', 1, 48, 0, 0), +(18000188, 8154880, 11, 'npc_name_kill', 'npc_name', 48177, 'an enraged jungle raptor', 1, 48, 0, 0), +(18000189, 8154880, 12, 'npc_name_kill', 'npc_name', 48182, 'an enraged tiger raptor', 1, 48, 0, 0), +(18000190, 8154880, 13, 'npc_name_kill', 'npc_name', 48236, 'an envenomed hunter', 1, 48, 0, 0), +(18000191, 8154880, 14, 'npc_name_kill', 'npc_name', 48170, 'a frenzied shiverback', 1, 48, 0, 0), +(18000192, 8154880, 15, 'npc_name_kill', 'npc_name', 48241, 'frightchaser', 1, 48, 0, 0), +(18000193, 8154880, 16, 'npc_name_kill', 'npc_name', 48150, 'a gelatinous mass', 1, 48, 0, 0), +(18000194, 8154880, 17, 'npc_name_kill', 'npc_name', 48224, 'a graystriped mosquito', 1, 48, 0, 0), +(18000195, 8154880, 18, 'npc_name_kill', 'npc_name', 48189, 'a gyrating mass', 1, 48, 0, 0), +(18000196, 8154880, 19, 'npc_name_kill', 'npc_name', 48225, 'a noxious jungle spider', 1, 48, 0, 0), +(18000197, 8154880, 20, 'npc_name_kill', 'npc_name', 48183, 'a poisonstrand hunter', 1, 48, 0, 0), +(18000198, 8154880, 21, 'npc_name_kill', 'npc_name', 48147, 'a quivering mass', 1, 48, 0, 0), +(18000199, 8154880, 22, 'npc_name_kill', 'npc_name', 48152, 'a razor fin piranha', 1, 48, 0, 0), +(18000200, 8154880, 23, 'npc_name_kill', 'npc_name', 48226, 'a razor tooth piranha', 1, 48, 0, 0), +(18000201, 8154880, 24, 'npc_name_kill', 'npc_name', 48192, 'a rotting horror', 1, 48, 0, 0), +(18000202, 8154880, 25, 'npc_name_kill', 'npc_name', 48078, 'a rotting shiverback', 1, 48, 0, 0), +(18000203, 8154880, 26, 'npc_name_kill', 'npc_name', 48242, 'silverfang', 1, 48, 0, 0), +(18000204, 8154880, 27, 'npc_name_kill', 'npc_name', 48153, 'a silverflank shiverback', 1, 48, 0, 0), +(18000205, 8154880, 28, 'npc_name_kill', 'npc_name', 48202, 'soul siphon', 1, 48, 0, 0), +(18000206, 8154880, 29, 'npc_name_kill', 'npc_name', 48149, 'a swirling black mass', 1, 48, 0, 0), +(18000207, 8154880, 30, 'npc_name_kill', 'npc_name', 48203, 'a swirling green mass', 1, 48, 0, 0), +(18000208, 8154880, 31, 'npc_name_kill', 'npc_name', 48151, 'a swirling red mass', 1, 48, 0, 0), +(18000209, 8154880, 32, 'npc_name_kill', 'npc_name', 48194, 'a tae ew aggressor', 1, 48, 0, 0), +(18000210, 8154880, 33, 'npc_name_kill', 'npc_name', 48145, 'a tae ew bloodfiend', 1, 48, 0, 0), +(18000211, 8154880, 34, 'npc_name_kill', 'npc_name', 48161, 'a tae ew convert', 1, 48, 0, 0), +(18000212, 8154880, 35, 'npc_name_kill', 'npc_name', 48232, 'a tae ew prophet', 1, 48, 0, 0), +(18000213, 8154880, 36, 'npc_name_kill', 'npc_name', 48233, 'a tae ew spear fisher', 1, 48, 0, 0), +(18000214, 8154880, 37, 'npc_name_kill', 'npc_name', 48178, 'a tae ew trapper', 1, 48, 0, 0), +(18000215, 8154880, 38, 'npc_name_kill', 'npc_name', 48171, 'a tae ew warlord', 1, 48, 0, 0), +(18000216, 8154880, 39, 'npc_name_kill', 'npc_name', 48244, 'a tae ew warmaster', 1, 48, 0, 0), +(18000217, 8154880, 40, 'npc_name_kill', 'npc_name', 48217, 'terrorclaw', 1, 48, 0, 0), +(18000218, 8154880, 41, 'npc_name_kill', 'npc_name', 48193, 'a thul tae ew adept', 1, 48, 0, 0), +(18000219, 8154880, 42, 'npc_name_kill', 'npc_name', 48159, 'a thul tae ew crusader', 1, 48, 0, 0), +(18000220, 8154880, 43, 'npc_name_kill', 'npc_name', 48158, 'a thul tae ew despoiler', 1, 48, 0, 0), +(18000221, 8154880, 44, 'npc_name_kill', 'npc_name', 48018, 'a thul tae ew ritualist', 1, 48, 0, 0), +(18000222, 8154880, 45, 'npc_name_kill', 'npc_name', 48141, 'a thul tae ew spirtcaller', 1, 48, 0, 0), +(18000223, 8154880, 46, 'npc_name_kill', 'npc_name', 48118, 'a thul tae ew torturer', 1, 48, 0, 0), +(18000224, 8154880, 47, 'npc_name_kill', 'npc_name', 48185, 'a toxic jungle hunter', 1, 48, 0, 0), +(18000225, 8154880, 48, 'npc_name_kill', 'npc_name', 48243, 'toxiferious', 1, 48, 0, 0), +(18000226, 8154880, 49, 'npc_name_kill', 'npc_name', 48235, 'a virulent mosquito', 1, 48, 0, 0), +(18000227, 8158680, 0, 'npc_name_kill', 'npc_name', 186177, 'arcanist v`gimis', 1, 186, 0, 0), +(18000228, 8158680, 1, 'npc_name_kill', 'npc_name', 186176, 'arch lich t`vaxok', 1, 186, 0, 0), +(18000229, 8158680, 2, 'npc_name_kill', 'npc_name', 186175, 'archon g`uvin', 1, 186, 0, 0), +(18000230, 8158680, 3, 'npc_name_kill', 'npc_name', 186161, 'an ashenbone broodmaster', 1, 186, 0, 0), +(18000231, 8158680, 4, 'npc_name_kill', 'npc_name', 186167, 'assassin z`jrix', 1, 186, 0, 0), +(18000232, 8158680, 5, 'npc_name_kill', 'npc_name', 186163, 'avatar of abhorrence', 1, 186, 0, 0), +(18000233, 8158680, 6, 'npc_name_kill', 'npc_name', 186160, 'coercer t`vala', 1, 186, 0, 0), +(18000234, 8158680, 7, 'npc_name_kill', 'npc_name', 186170, 'dread knight t`kamax', 1, 186, 0, 0), +(18000235, 8158680, 8, 'npc_name_kill', 'npc_name', 186162, 'an eerie chest', 1, 186, 0, 0), +(18000236, 8158680, 9, 'npc_name_kill', 'npc_name', 186169, 'evangelist w`rixxus', 1, 186, 0, 0), +(18000237, 8158680, 10, 'npc_name_kill', 'npc_name', 186179, 'a frightful chest', 1, 186, 0, 0), +(18000238, 8158680, 11, 'npc_name_kill', 'npc_name', 186183, 'grandmaster h`qilm', 1, 186, 0, 0), +(18000239, 8158680, 12, 'npc_name_kill', 'npc_name', 186186, 'grim abhorrent kaltik', 1, 186, 0, 0), +(18000240, 8158680, 13, 'npc_name_kill', 'npc_name', 186185, 'a grotesque rat', 1, 186, 0, 0), +(18000241, 8158680, 14, 'npc_name_kill', 'npc_name', 186180, 'a hatebone broodlord', 1, 186, 0, 0), +(18000242, 8158680, 15, 'npc_name_kill', 'npc_name', 186166, 'a hideous rat', 1, 186, 0, 0), +(18000243, 8158680, 16, 'npc_name_kill', 'npc_name', 186187, 'lord of fury', 1, 186, 0, 0), +(18000244, 8158680, 17, 'npc_name_kill', 'npc_name', 186154, 'lord of ire', 1, 186, 0, 0), +(18000245, 8158680, 18, 'npc_name_kill', 'npc_name', 186155, 'lord of loathing', 1, 186, 0, 0), +(18000246, 8158680, 19, 'npc_name_kill', 'npc_name', 186157, 'magi p`tasa', 1, 186, 0, 0), +(18000247, 8158680, 20, 'npc_name_kill', 'npc_name', 186184, 'master d`samni', 1, 186, 0, 0), +(18000248, 8158680, 21, 'npc_name_kill', 'npc_name', 186165, 'master of spite', 1, 186, 0, 0), +(18000249, 8158680, 22, 'npc_name_kill', 'npc_name', 186156, 'master r`tal', 1, 186, 0, 0), +(18000250, 8158680, 23, 'npc_name_kill', 'npc_name', 186151, 'mistress a`zara', 1, 186, 0, 0), +(18000251, 8158680, 24, 'npc_name_kill', 'npc_name', 186181, 'mistress of malevolence', 1, 186, 0, 0), +(18000252, 8158680, 25, 'npc_name_kill', 'npc_name', 186159, 'mistress of scorn', 1, 186, 0, 0), +(18000253, 8158680, 26, 'npc_name_kill', 'npc_name', 186173, 'overlord r`gahbsa', 1, 186, 0, 0), +(18000254, 8158680, 27, 'npc_name_kill', 'npc_name', 186168, 'sorcerer c`gazin', 1, 186, 0, 0), +(18000255, 8158680, 28, 'npc_name_kill', 'npc_name', 186172, 'spy master i`kavin', 1, 186, 0, 0), +(18000256, 8158680, 29, 'npc_name_kill', 'npc_name', 186188, 'templar j`rosix', 1, 186, 0, 0), +(18000257, 8158680, 30, 'npc_name_kill', 'npc_name', 186150, 'thought destroyer', 1, 186, 0, 0), +(18000258, 8158680, 31, 'npc_name_kill', 'npc_name', 186164, 'vicar m`kari', 1, 186, 0, 0), +(18000259, 8158680, 32, 'npc_name_kill', 'npc_name', 186182, 'warlock j`rath', 1, 186, 0, 0), +(18000260, 8158680, 33, 'npc_name_kill', 'npc_name', 186171, 'warlord e`prosio', 1, 186, 0, 0), +(18000261, 8207880, 0, 'npc_name_kill', 'npc_name', 78180, 'burynai cutter', 1, 78, 0, 0), +(18000262, 8207880, 1, 'npc_name_kill', 'npc_name', 78183, 'carrion queen', 1, 78, 0, 0), +(18000263, 8207880, 2, 'npc_name_kill', 'npc_name', 78149, 'scourgetail scorpion', 1, 78, 0, 0), +(18000264, 8207980, 0, 'npc_name_kill', 'npc_name', 79015, 'grachnist the destroyer', 1, 79, 0, 0), +(18000265, 8207980, 1, 'npc_name_kill', 'npc_name', 79116, 'iksar bandit lord', 1, 79, 0, 0), +(18000266, 8208180, 0, 'npc_name_kill', 'npc_name', 81187, 'chief rokgus', 1, 81, 0, 0), +(18000267, 8208180, 1, 'npc_name_kill', 'npc_name', 81200, 'soothsayer dregzak', 1, 81, 0, 0), +(18000268, 8208380, 0, 'npc_name_kill', 'npc_name', 83222, 'blackbone', 1, 83, 0, 0), +(18000269, 8208380, 1, 'npc_name_kill', 'npc_name', 83193, 'bloodgorge', 1, 83, 0, 0), +(18000270, 8208380, 2, 'npc_name_kill', 'npc_name', 83229, 'bloodvein', 1, 83, 0, 0) +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_index` = VALUES(`objective_index`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`), +`zone_id` = VALUES(`zone_id`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +VALUES +(18000271, 8208380, 3, 'npc_name_kill', 'npc_name', 83238, 'bulsgor', 1, 83, 0, 0), +(18000272, 8208380, 4, 'npc_name_kill', 'npc_name', 83223, 'deadeye', 1, 83, 0, 0), +(18000273, 8208380, 5, 'npc_name_kill', 'npc_name', 83217, 'dreesix ghoultongue', 1, 83, 0, 0), +(18000274, 8208380, 6, 'npc_name_kill', 'npc_name', 83195, 'ebon bloodrose', 1, 83, 0, 0), +(18000275, 8208380, 7, 'npc_name_kill', 'npc_name', 83075, 'fakraa the forsaken', 1, 83, 0, 0), +(18000276, 8208380, 8, 'npc_name_kill', 'npc_name', 83239, 'fangor', 1, 83, 0, 0), +(18000277, 8208380, 9, 'npc_name_kill', 'npc_name', 83236, 'frayk', 1, 83, 0, 0), +(18000278, 8208380, 10, 'npc_name_kill', 'npc_name', 83206, 'grimewurm', 1, 83, 0, 0), +(18000279, 8208380, 11, 'npc_name_kill', 'npc_name', 83233, 'grizshnok', 1, 83, 0, 0), +(18000280, 8208380, 12, 'npc_name_kill', 'npc_name', 83220, 'heartblood fern', 1, 83, 0, 0), +(18000281, 8208380, 13, 'npc_name_kill', 'npc_name', 83240, 'old hangman', 1, 83, 0, 0), +(18000282, 8208380, 14, 'npc_name_kill', 'npc_name', 83226, 'soblohg', 1, 83, 0, 0), +(18000283, 8208380, 15, 'npc_name_kill', 'npc_name', 83232, 'two tails', 1, 83, 0, 0), +(18000284, 8208380, 16, 'npc_name_kill', 'npc_name', 83219, 'venomwing', 1, 83, 0, 0), +(18000285, 8208380, 17, 'npc_name_kill', 'npc_name', 83237, 'weeping mantrap', 1, 83, 0, 0), +(18000286, 8208580, 0, 'npc_name_kill', 'npc_name', 85090, 'a lead explorer', 1, 85, 0, 0), +(18000287, 8208680, 0, 'npc_name_kill', 'npc_name', 86137, 'a dread widow', 1, 86, 0, 0), +(18000288, 8208680, 1, 'npc_name_kill', 'npc_name', 86144, 'a mountain giant patriarch', 1, 86, 0, 0), +(18000289, 8208680, 2, 'npc_name_kill', 'npc_name', 86044, 'a ravishing drolvarg', 1, 86, 0, 0), +(18000290, 8208780, 0, 'npc_name_kill', 'npc_name', 87113, 'gorgul paclock', 1, 87, 0, 0), +(18000291, 8208780, 1, 'npc_name_kill', 'npc_name', 87142, 'gullerback', 1, 87, 0, 0), +(18000292, 8208780, 2, 'npc_name_kill', 'npc_name', 87115, 'korasal klyseer', 1, 87, 0, 0), +(18000293, 8208780, 3, 'npc_name_kill', 'npc_name', 87148, 'phurzikon', 1, 87, 0, 0), +(18000294, 8208880, 0, 'npc_name_kill', 'npc_name', 88091, 'failed crypt raider', 1, 88, 0, 0), +(18000295, 8208880, 1, 'npc_name_kill', 'npc_name', 88085, 'frenzied strathbone', 1, 88, 0, 0), +(18000296, 8208880, 2, 'npc_name_kill', 'npc_name', 88094, 'hungered ravener', 1, 88, 0, 0), +(18000297, 8208880, 3, 'npc_name_kill', 'npc_name', 88089, 'reaver of xalgoz', 1, 88, 0, 0), +(18000298, 8208880, 4, 'npc_name_kill', 'npc_name', 88061, 'spectral librarian', 1, 88, 0, 0), +(18000299, 8208880, 5, 'npc_name_kill', 'npc_name', 88090, 'strathbone runelord', 1, 88, 0, 0), +(18000300, 8208880, 6, 'npc_name_kill', 'npc_name', 88055, 'tortured librarian', 1, 88, 0, 0), +(18000301, 8208880, 7, 'npc_name_kill', 'npc_name', 88073, 'xalgoz', 1, 88, 0, 0), +(18000302, 8208980, 0, 'npc_name_kill', 'npc_name', 89174, 'baron yosig', 1, 89, 0, 0), +(18000303, 8208980, 1, 'npc_name_kill', 'npc_name', 89159, 'blood of chottal', 1, 89, 0, 0), +(18000304, 8208980, 2, 'npc_name_kill', 'npc_name', 89167, 'brogg', 1, 89, 0, 0), +(18000305, 8208980, 3, 'npc_name_kill', 'npc_name', 89177, 'crypt caretaker', 1, 89, 0, 0), +(18000306, 8208980, 4, 'npc_name_kill', 'npc_name', 89144, 'emperor chottal', 1, 89, 0, 0), +(18000307, 8208980, 5, 'npc_name_kill', 'npc_name', 89173, 'frenzied pox scarab', 1, 89, 0, 0), +(18000308, 8208980, 6, 'npc_name_kill', 'npc_name', 89124, 'froggy', 1, 89, 0, 0), +(18000309, 8208980, 7, 'npc_name_kill', 'npc_name', 89180, 'froglok armorer', 1, 89, 0, 0), +(18000310, 8208980, 8, 'npc_name_kill', 'npc_name', 89006, 'froglok armsman', 1, 89, 0, 0), +(18000311, 8208980, 9, 'npc_name_kill', 'npc_name', 89131, 'froglok bartender', 1, 89, 0, 0), +(18000312, 8208980, 10, 'npc_name_kill', 'npc_name', 89164, 'froglok chef', 1, 89, 0, 0), +(18000313, 8208980, 11, 'npc_name_kill', 'npc_name', 89166, 'froglok commander', 1, 89, 0, 0), +(18000314, 8208980, 12, 'npc_name_kill', 'npc_name', 89057, 'froglok ostiary', 1, 89, 0, 0), +(18000315, 8208980, 13, 'npc_name_kill', 'npc_name', 89171, 'froglok pickler', 1, 89, 0, 0), +(18000316, 8208980, 14, 'npc_name_kill', 'npc_name', 89146, 'froglok repairer', 1, 89, 0, 0), +(18000317, 8208980, 15, 'npc_name_kill', 'npc_name', 89175, 'gruplinort', 1, 89, 0, 0), +(18000318, 8208980, 16, 'npc_name_kill', 'npc_name', 89129, 'harbinger freglor', 1, 89, 0, 0), +(18000319, 8208980, 17, 'npc_name_kill', 'npc_name', 89163, 'hierophant prime grekal', 1, 89, 0, 0), +(18000320, 8208980, 18, 'npc_name_kill', 'npc_name', 89153, 'myconid spore king', 1, 89, 0, 0), +(18000321, 8208980, 19, 'npc_name_kill', 'npc_name', 89134, 'a necrosis scarab', 1, 89, 0, 0), +(18000322, 8208980, 20, 'npc_name_kill', 'npc_name', 89112, 'sebilite guardian', 1, 89, 0, 0), +(18000323, 8209280, 0, 'npc_name_kill', 'npc_name', 92187, 'a goblin bodyguard', 1, 92, 0, 0), +(18000324, 8209280, 1, 'npc_name_kill', 'npc_name', 92204, 'a goblin fanatic', 1, 92, 0, 0), +(18000325, 8209580, 0, 'npc_name_kill', 'npc_name', 95151, 'bloodeye', 1, 95, 0, 0), +(18000326, 8209580, 1, 'npc_name_kill', 'npc_name', 95176, 'champion arlek', 1, 95, 0, 0), +(18000327, 8209580, 2, 'npc_name_kill', 'npc_name', 95129, 'champion thenrin', 1, 95, 0, 0), +(18000328, 8209580, 3, 'npc_name_kill', 'npc_name', 95130, 'commander sils', 1, 95, 0, 0), +(18000329, 8209580, 4, 'npc_name_kill', 'npc_name', 95161, 'crusader zoglic', 1, 95, 0, 0), +(18000330, 8209580, 5, 'npc_name_kill', 'npc_name', 95175, 'doom', 1, 95, 0, 0), +(18000331, 8209580, 6, 'npc_name_kill', 'npc_name', 95157, 'dragontail', 1, 95, 0, 0), +(18000332, 8209580, 7, 'npc_name_kill', 'npc_name', 95166, 'dreadlord dekir', 1, 95, 0, 0), +(18000333, 8209580, 8, 'npc_name_kill', 'npc_name', 95153, 'dreadlord fanrik', 1, 95, 0, 0), +(18000334, 8209580, 9, 'npc_name_kill', 'npc_name', 95164, 'ebon lotus', 1, 95, 0, 0), +(18000335, 8209580, 10, 'npc_name_kill', 'npc_name', 95165, 'ffroaak', 1, 95, 0, 0), +(18000336, 8209580, 11, 'npc_name_kill', 'npc_name', 95172, 'flayhte', 1, 95, 0, 0), +(18000337, 8209580, 12, 'npc_name_kill', 'npc_name', 95154, 'hangman', 1, 95, 0, 0), +(18000338, 8209580, 13, 'npc_name_kill', 'npc_name', 95162, 'harbinger dronik', 1, 95, 0, 0), +(18000339, 8209580, 14, 'npc_name_kill', 'npc_name', 95150, 'harbinger josk', 1, 95, 0, 0), +(18000340, 8209580, 15, 'npc_name_kill', 'npc_name', 95178, 'hierophant ixyl', 1, 95, 0, 0), +(18000341, 8209580, 16, 'npc_name_kill', 'npc_name', 95167, 'keeper lasnik', 1, 95, 0, 0), +(18000342, 8209580, 17, 'npc_name_kill', 'npc_name', 95158, 'keeper sepsis', 1, 95, 0, 0), +(18000343, 8209580, 18, 'npc_name_kill', 'npc_name', 95160, 'klok denris', 1, 95, 0, 0), +(18000344, 8209580, 19, 'npc_name_kill', 'npc_name', 95155, 'knight dragol', 1, 95, 0, 0), +(18000345, 8209580, 20, 'npc_name_kill', 'npc_name', 95179, 'master fasliw', 1, 95, 0, 0), +(18000346, 8209580, 21, 'npc_name_kill', 'npc_name', 95107, 'oracle froskil', 1, 95, 0, 0), +(18000347, 8209580, 22, 'npc_name_kill', 'npc_name', 95170, 'partisan yinlen', 1, 95, 0, 0), +(18000348, 8209580, 23, 'npc_name_kill', 'npc_name', 95182, 'sigra', 1, 95, 0, 0), +(18000349, 8209580, 24, 'npc_name_kill', 'npc_name', 95169, 'silvermane', 1, 95, 0, 0), +(18000350, 8209580, 25, 'npc_name_kill', 'npc_name', 95159, 'squire glik', 1, 95, 0, 0), +(18000351, 8209580, 26, 'npc_name_kill', 'npc_name', 95108, 'stonebeak', 1, 95, 0, 0), +(18000352, 8209580, 27, 'npc_name_kill', 'npc_name', 95177, 'throkkok', 1, 95, 0, 0), +(18000353, 8209580, 28, 'npc_name_kill', 'npc_name', 95171, 'thruke', 1, 95, 0, 0), +(18000354, 8209580, 29, 'npc_name_kill', 'npc_name', 95149, 'titail sinok', 1, 95, 0, 0), +(18000355, 8209580, 30, 'npc_name_kill', 'npc_name', 95156, 'vessel fryn', 1, 95, 0, 0), +(18000356, 8209680, 0, 'npc_name_kill', 'npc_name', 96077, 'halara', 1, 96, 0, 0), +(18000357, 8209680, 1, 'npc_name_kill', 'npc_name', 96087, 'ugrak da raider', 1, 96, 0, 0), +(18000358, 8209780, 0, 'npc_name_kill', 'npc_name', 97075, 'bargynn', 1, 97, 0, 0), +(18000359, 8209780, 1, 'npc_name_kill', 'npc_name', 97077, 'undead crusader', 1, 97, 0, 0), +(18000360, 8210280, 0, 'npc_name_kill', 'npc_name', 102013, 'caller of sathir', 1, 102, 0, 0) +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_index` = VALUES(`objective_index`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`), +`zone_id` = VALUES(`zone_id`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +VALUES +(18000361, 8210280, 1, 'npc_name_kill', 'npc_name', 102084, 'construct of sathir', 1, 102, 0, 0), +(18000362, 8210280, 2, 'npc_name_kill', 'npc_name', 102124, 'hangnail', 1, 102, 0, 0), +(18000363, 8210280, 3, 'npc_name_kill', 'npc_name', 102119, 'knight of sathir', 1, 102, 0, 0), +(18000364, 8210280, 4, 'npc_name_kill', 'npc_name', 102125, 'sentry of sathir', 1, 102, 0, 0), +(18000365, 8210280, 5, 'npc_name_kill', 'npc_name', 102120, 'skeletal berserker', 1, 102, 0, 0), +(18000366, 8210280, 6, 'npc_name_kill', 'npc_name', 102116, 'skeletal captain', 1, 102, 0, 0), +(18000367, 8210280, 7, 'npc_name_kill', 'npc_name', 102121, 'skeletal caretaker', 1, 102, 0, 0), +(18000368, 8210280, 8, 'npc_name_kill', 'npc_name', 102047, 'skeletal scryer', 1, 102, 0, 0), +(18000369, 8210280, 9, 'npc_name_kill', 'npc_name', 102008, 'skeletal warlord', 1, 102, 0, 0), +(18000370, 8210280, 10, 'npc_name_kill', 'npc_name', 102090, 'spectral turnkey', 1, 102, 0, 0), +(18000371, 8210280, 11, 'npc_name_kill', 'npc_name', 102105, 'undead jailer', 1, 102, 0, 0), +(18000372, 8210380, 0, 'npc_name_kill', 'npc_name', 103184, 'battle master ska`tu', 1, 103, 0, 0), +(18000373, 8210380, 1, 'npc_name_kill', 'npc_name', 103191, 'deathfang', 1, 103, 0, 0), +(18000374, 8210380, 2, 'npc_name_kill', 'npc_name', 103198, 'drill master dih`roul', 1, 103, 0, 0), +(18000375, 8210380, 3, 'npc_name_kill', 'npc_name', 103170, 'foreman ku`lul', 1, 103, 0, 0), +(18000376, 8210380, 4, 'npc_name_kill', 'npc_name', 103211, 'foreman mirt`akk', 1, 103, 0, 0), +(18000377, 8210380, 5, 'npc_name_kill', 'npc_name', 103139, 'grand herbalist mak`ha', 1, 103, 0, 0), +(18000378, 8210380, 6, 'npc_name_kill', 'npc_name', 103200, 'grand lorekeeper kino shai`din', 1, 103, 0, 0), +(18000379, 8210380, 7, 'npc_name_kill', 'npc_name', 103169, 'grave master zo`lun', 1, 103, 0, 0), +(18000380, 8210380, 8, 'npc_name_kill', 'npc_name', 103183, 'an iksar trustee', 1, 103, 0, 0), +(18000381, 8210380, 9, 'npc_name_kill', 'npc_name', 103092, 'an imperial gravemaster', 1, 103, 0, 0), +(18000382, 8210380, 10, 'npc_name_kill', 'npc_name', 103180, 'kennel master al`ele', 1, 103, 0, 0), +(18000383, 8210380, 11, 'npc_name_kill', 'npc_name', 103215, 'loremaster piza`tak', 1, 103, 0, 0), +(18000384, 8210380, 12, 'npc_name_kill', 'npc_name', 103051, 'observer aq`touz', 1, 103, 0, 0), +(18000385, 8210380, 13, 'npc_name_kill', 'npc_name', 103171, 'overseer dal`guur', 1, 103, 0, 0), +(18000386, 8210380, 14, 'npc_name_kill', 'npc_name', 103163, 'sarnak collective auditor', 1, 103, 0, 0), +(18000387, 8210380, 15, 'npc_name_kill', 'npc_name', 103177, 'underboss myli`ki', 1, 103, 0, 0), +(18000388, 8210380, 16, 'npc_name_kill', 'npc_name', 103197, 'watch captain hir`roul', 1, 103, 0, 0), +(18000389, 8210380, 17, 'npc_name_kill', 'npc_name', 103008, 'a wizened herb collector', 1, 103, 0, 0), +(18000390, 8210480, 0, 'npc_name_kill', 'npc_name', 104080, 'a coerced crusader', 1, 104, 0, 0), +(18000391, 8210480, 1, 'npc_name_kill', 'npc_name', 104073, 'a coerced penkeeper', 1, 104, 0, 0), +(18000392, 8210480, 2, 'npc_name_kill', 'npc_name', 104076, 'a coerced revenant', 1, 104, 0, 0), +(18000393, 8210480, 3, 'npc_name_kill', 'npc_name', 104077, 'the kly', 1, 104, 0, 0), +(18000394, 8210480, 4, 'npc_name_kill', 'npc_name', 104070, 'lumpy goo', 1, 104, 0, 0), +(18000395, 8210480, 5, 'npc_name_kill', 'npc_name', 104074, 'a spectral crusader', 1, 104, 0, 0), +(18000396, 8210580, 0, 'npc_name_kill', 'npc_name', 105152, 'the crypt devourer', 1, 105, 0, 0), +(18000397, 8210580, 1, 'npc_name_kill', 'npc_name', 105029, 'the crypt excavator', 1, 105, 0, 0), +(18000398, 8210580, 2, 'npc_name_kill', 'npc_name', 105116, 'the crypt feaster', 1, 105, 0, 0), +(18000399, 8210580, 3, 'npc_name_kill', 'npc_name', 105074, 'the crypt spectre', 1, 105, 0, 0), +(18000400, 8210580, 4, 'npc_name_kill', 'npc_name', 105075, 'embalming fluid', 1, 105, 0, 0), +(18000401, 8210580, 5, 'npc_name_kill', 'npc_name', 105081, 'the golem master', 1, 105, 0, 0), +(18000402, 8210580, 6, 'npc_name_kill', 'npc_name', 105024, 'howling spectre', 1, 105, 0, 0), +(18000403, 8210580, 7, 'npc_name_kill', 'npc_name', 105157, 'mortiferous protector', 1, 105, 0, 0), +(18000404, 8210580, 8, 'npc_name_kill', 'npc_name', 105013, 'reanimated plaguebone', 1, 105, 0, 0), +(18000405, 8210580, 9, 'npc_name_kill', 'npc_name', 105091, 'sentient bile', 1, 105, 0, 0), +(18000406, 8210580, 10, 'npc_name_kill', 'npc_name', 105076, 'the skeleton sepulcher', 1, 105, 0, 0), +(18000407, 8210580, 11, 'npc_name_kill', 'npc_name', 105093, 'the spectre sepulcher', 1, 105, 0, 0), +(18000408, 8210580, 12, 'npc_name_kill', 'npc_name', 105146, 'the spectre spiritualist', 1, 105, 0, 0), +(18000409, 8210580, 13, 'npc_name_kill', 'npc_name', 105160, 'the undertaker lord', 1, 105, 0, 0), +(18000410, 8210880, 0, 'npc_name_kill', 'npc_name', 108502, 'an ancient racnar', 1, 108, 0, 0), +(18000411, 8210880, 1, 'npc_name_kill', 'npc_name', 108508, 'a cruel racnar', 1, 108, 0, 0), +(18000412, 8210980, 0, 'npc_name_kill', 'npc_name', 109092, 'a bloodgill soothsayer', 1, 109, 0, 0), +(18000413, 8210980, 1, 'npc_name_kill', 'npc_name', 109091, 'a bloodgill warlord', 1, 109, 0, 0), +(18000414, 8210980, 2, 'npc_name_kill', 'npc_name', 109103, 'brother eruk', 1, 109, 0, 0), +(18000415, 8210980, 3, 'npc_name_kill', 'npc_name', 109104, 'champion kamak', 1, 109, 0, 0), +(18000416, 8210980, 4, 'npc_name_kill', 'npc_name', 109094, 'a decaying slavemaster', 1, 109, 0, 0), +(18000417, 8210980, 5, 'npc_name_kill', 'npc_name', 109106, 'feral lord gulok', 1, 109, 0, 0), +(18000418, 8210980, 6, 'npc_name_kill', 'npc_name', 109109, 'hierophant ginai', 1, 109, 0, 0), +(18000419, 8210980, 7, 'npc_name_kill', 'npc_name', 109084, 'hierophant vradik', 1, 109, 0, 0), +(18000420, 8210980, 8, 'npc_name_kill', 'npc_name', 109099, 'an iksar behemoth', 1, 109, 0, 0), +(18000421, 8210980, 9, 'npc_name_kill', 'npc_name', 109090, 'a kylong crusader', 1, 109, 0, 0), +(18000422, 8210980, 10, 'npc_name_kill', 'npc_name', 109116, 'a kylong lich', 1, 109, 0, 0), +(18000423, 8210980, 11, 'npc_name_kill', 'npc_name', 109110, 'lord sasil', 1, 109, 0, 0), +(18000424, 8210980, 12, 'npc_name_kill', 'npc_name', 109088, 'luminary salox', 1, 109, 0, 0), +(18000425, 8210980, 13, 'npc_name_kill', 'npc_name', 109098, 'a plagued slave', 1, 109, 0, 0), +(18000426, 8210980, 14, 'npc_name_kill', 'npc_name', 109096, 'a rotting shopkeeper', 1, 109, 0, 0), +(18000427, 8210980, 15, 'npc_name_kill', 'npc_name', 109097, 'a sad slave', 1, 109, 0, 0), +(18000428, 8210980, 16, 'npc_name_kill', 'npc_name', 109111, 'trooper muruk', 1, 109, 0, 0), +(18000429, 8210980, 17, 'npc_name_kill', 'npc_name', 109100, 'an undead chef', 1, 109, 0, 0), +(18000430, 8210980, 18, 'npc_name_kill', 'npc_name', 109101, 'an undead thief', 1, 109, 0, 0), +(18000431, 8210980, 19, 'npc_name_kill', 'npc_name', 109102, 'an undying blacksmith', 1, 109, 0, 0), +(18000432, 8210980, 20, 'npc_name_kill', 'npc_name', 109112, 'warlock dirloz', 1, 109, 0, 0), +(18000433, 8210980, 21, 'npc_name_kill', 'npc_name', 109113, 'warlock gurag', 1, 109, 0, 0), +(18000434, 8227780, 0, 'npc_name_kill', 'npc_name', 277118, 'brodisek ashkansek', 1, 277, 0, 0), +(18000435, 8227780, 1, 'npc_name_kill', 'npc_name', 277116, 'krizznot bonewalker', 1, 277, 0, 0), +(18000436, 8227780, 2, 'npc_name_kill', 'npc_name', 277096, 'a rabid chokidai biter', 1, 277, 0, 0), +(18000437, 8227780, 3, 'npc_name_kill', 'npc_name', 277090, 'a rabid chokidai bleeder', 1, 277, 0, 0), +(18000438, 8227780, 4, 'npc_name_kill', 'npc_name', 277122, 'a rabid chokidai ripper', 1, 277, 0, 0), +(18000439, 8227780, 5, 'npc_name_kill', 'npc_name', 277119, 'sarnak armorer', 1, 277, 0, 0), +(18000440, 8227780, 6, 'npc_name_kill', 'npc_name', 277120, 'sarnak champion', 1, 277, 0, 0), +(18000441, 8227780, 7, 'npc_name_kill', 'npc_name', 277121, 'sarnak weaponsmith', 1, 277, 0, 0), +(18000442, 8227780, 8, 'npc_name_kill', 'npc_name', 277117, 'valinion viz`daron', 1, 277, 0, 0), +(18000443, 8250880, 0, 'npc_name_kill', 'npc_name', 108041, 'elder ekron', 1, 108, 0, 0), +(18000444, 8250880, 1, 'npc_name_kill', 'npc_name', 108044, 'kluzen the protector', 1, 108, 0, 0), +(18000445, 8250880, 2, 'npc_name_kill', 'npc_name', 108045, 'magma basilisk', 1, 108, 0, 0), +(18000446, 8250880, 3, 'npc_name_kill', 'npc_name', 108046, 'milyex vioren', 1, 108, 0, 0), +(18000447, 8250880, 4, 'npc_name_kill', 'npc_name', 108049, 'qunard ashenclaw', 1, 108, 0, 0), +(18000448, 8250880, 5, 'npc_name_kill', 'npc_name', 108051, 'travenro the skygazer', 1, 108, 0, 0), +(18000449, 8311080, 0, 'npc_name_kill', 'npc_name', 110077, 'dire wolf stalker', 1, 110, 0, 0), +(18000450, 8311080, 1, 'npc_name_kill', 'npc_name', 110006, 'midnight', 1, 110, 0, 0) +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_index` = VALUES(`objective_index`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`), +`zone_id` = VALUES(`zone_id`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +VALUES +(18000451, 8311080, 2, 'npc_name_kill', 'npc_name', 110111, 'pulsating icestorm', 1, 110, 0, 0), +(18000452, 8311280, 0, 'npc_name_kill', 'npc_name', 112103, 'a deadly blizzard hunter', 1, 112, 0, 0), +(18000453, 8311280, 1, 'npc_name_kill', 'npc_name', 112104, 'a fierce blizzard hunter', 1, 112, 0, 0), +(18000454, 8311680, 0, 'npc_name_kill', 'npc_name', 116165, 'chief ry`gorr', 1, 116, 0, 0), +(18000455, 8311680, 1, 'npc_name_kill', 'npc_name', 116012, 'firbrand the black', 1, 116, 0, 0), +(18000456, 8311680, 2, 'npc_name_kill', 'npc_name', 116197, 'a ry`gorr minstrel', 1, 116, 0, 0), +(18000457, 8311680, 3, 'npc_name_kill', 'npc_name', 116198, 'warden bruke', 1, 116, 0, 0), +(18000458, 8311780, 0, 'npc_name_kill', 'npc_name', 117014, 'yvolcarn', 1, 117, 0, 0), +(18000459, 8311880, 0, 'npc_name_kill', 'npc_name', 118109, 'yaka razorhoof', 1, 118, 0, 0), +(18000460, 8311980, 0, 'npc_name_kill', 'npc_name', 119047, 'an elder holgresh', 1, 119, 0, 0), +(18000461, 8311980, 1, 'npc_name_kill', 'npc_name', 119129, 'a holgresh raider', 1, 119, 0, 0), +(18000462, 8312080, 0, 'npc_name_kill', 'npc_name', 120048, 'tantor', 1, 120, 0, 0), +(18000463, 8312180, 0, 'npc_name_kill', 'npc_name', 121085, 'a focus gem', 1, 121, 0, 0), +(18000464, 8312380, 0, 'npc_name_kill', 'npc_name', 123090, 'dominator yisaki', 1, 123, 0, 0), +(18000465, 8312380, 1, 'npc_name_kill', 'npc_name', 123112, 'a great green slime', 1, 123, 0, 0), +(18000466, 8312380, 2, 'npc_name_kill', 'npc_name', 123125, 'pierre', 1, 123, 0, 0), +(18000467, 8312380, 3, 'npc_name_kill', 'npc_name', 123016, 'slani veekilaleeki', 1, 123, 0, 0), +(18000468, 8312380, 4, 'npc_name_kill', 'npc_name', 123149, 'vaniki', 1, 123, 0, 0), +(18000469, 8312580, 0, 'npc_name_kill', 'npc_name', 125088, 'an enthralled ulthork', 1, 125, 0, 0), +(18000470, 8312580, 1, 'npc_name_kill', 'npc_name', 125098, 'fellspine', 1, 125, 0, 0), +(18000471, 8312580, 2, 'npc_name_kill', 'npc_name', 125077, 'shimmering sea spirit', 1, 125, 0, 0), +(18000472, 8312580, 3, 'npc_name_kill', 'npc_name', 125083, 'a siren seductress', 1, 125, 0, 0), +(18000473, 8312980, 0, 'npc_name_kill', 'npc_name', 129093, 'glucose', 1, 129, 0, 0), +(18000474, 8312980, 1, 'npc_name_kill', 'npc_name', 129092, 'grizznot', 1, 129, 0, 0), +(18000475, 8352680, 0, 'npc_name_kill', 'npc_name', 126240, 'an asinine ape', 1, 126, 0, 0), +(18000476, 8352680, 1, 'npc_name_kill', 'npc_name', 126185, 'an astray hand', 1, 126, 0, 0), +(18000477, 8352680, 2, 'npc_name_kill', 'npc_name', 126372, 'a barmy burglar', 1, 126, 0, 0), +(18000478, 8352680, 3, 'npc_name_kill', 'npc_name', 126369, 'a bogus treasure chest', 1, 126, 0, 0), +(18000479, 8352680, 4, 'npc_name_kill', 'npc_name', 126306, 'a bouncing bunny', 1, 126, 0, 0), +(18000480, 8352680, 5, 'npc_name_kill', 'npc_name', 126168, 'bzzibuzzana', 1, 126, 0, 0), +(18000481, 8352680, 6, 'npc_name_kill', 'npc_name', 126370, 'a craven rascal', 1, 126, 0, 0), +(18000482, 8352680, 7, 'npc_name_kill', 'npc_name', 126368, 'a forsaken hand', 1, 126, 0, 0), +(18000483, 8352680, 8, 'npc_name_kill', 'npc_name', 126139, 'a fraudulent chest', 1, 126, 0, 0), +(18000484, 8352680, 9, 'npc_name_kill', 'npc_name', 126275, 'a frolicking performer', 1, 126, 0, 0), +(18000485, 8352680, 10, 'npc_name_kill', 'npc_name', 126302, 'a funky skunk', 1, 126, 0, 0), +(18000486, 8352680, 11, 'npc_name_kill', 'npc_name', 126137, 'a gifted sphinx', 1, 126, 0, 0), +(18000487, 8352680, 12, 'npc_name_kill', 'npc_name', 126176, 'a gorilla prodigy', 1, 126, 0, 0), +(18000488, 8352680, 13, 'npc_name_kill', 'npc_name', 126371, 'a gorilla professor', 1, 126, 0, 0), +(18000489, 8352680, 14, 'npc_name_kill', 'npc_name', 126081, 'the grand gardener', 1, 126, 0, 0), +(18000490, 8352680, 15, 'npc_name_kill', 'npc_name', 126303, 'a maddened mushroom man', 1, 126, 0, 0), +(18000491, 8352680, 16, 'npc_name_kill', 'npc_name', 126307, 'the master of mayhem', 1, 126, 0, 0), +(18000492, 8352680, 17, 'npc_name_kill', 'npc_name', 126367, 'a method actor', 1, 126, 0, 0), +(18000493, 8352680, 18, 'npc_name_kill', 'npc_name', 126304, 'an obsessed patron', 1, 126, 0, 0), +(18000494, 8352680, 19, 'npc_name_kill', 'npc_name', 126068, 'a paradoxical sphinx', 1, 126, 0, 0), +(18000495, 8352680, 20, 'npc_name_kill', 'npc_name', 126310, 'a savvy sphinx', 1, 126, 0, 0), +(18000496, 8352680, 21, 'npc_name_kill', 'npc_name', 126305, 'a theatre fanatic', 1, 126, 0, 0), +(18000497, 8352680, 22, 'npc_name_kill', 'npc_name', 126098, 'a troublesome charlatan', 1, 126, 0, 0), +(18000498, 8352680, 23, 'npc_name_kill', 'npc_name', 126108, 'a wicked performer', 1, 126, 0, 0), +(18000499, 8352680, 24, 'npc_name_kill', 'npc_name', 126228, 'a witty sphinx', 1, 126, 0, 0), +(18000500, 8380280, 0, 'npc_name_kill', 'npc_name', 128028, 'an ancient advocator', 1, 128, 0, 0), +(18000501, 8380380, 0, 'npc_name_kill', 'npc_name', 114018, 'kintaru of the shrine', 1, 114, 0, 0), +(18000502, 8380380, 1, 'npc_name_kill', 'npc_name', 114041, 'marech of the shrine', 1, 114, 0, 0), +(18000503, 8415380, 0, 'npc_name_kill', 'npc_name', 153138, 'chief groplin', 1, 153, 0, 0), +(18000504, 8415380, 1, 'npc_name_kill', 'npc_name', 153033, 'crinthia signseer', 1, 153, 0, 0), +(18000505, 8415380, 2, 'npc_name_kill', 'npc_name', 153005, 'fireclaw', 1, 153, 0, 0), +(18000506, 8415380, 3, 'npc_name_kill', 'npc_name', 153130, 'murph cobblestone', 1, 153, 0, 0), +(18000507, 8415380, 4, 'npc_name_kill', 'npc_name', 153136, 'the needlite queen', 1, 153, 0, 0), +(18000508, 8415380, 5, 'npc_name_kill', 'npc_name', 153044, 'torin truestring', 1, 153, 0, 0), +(18000509, 8415380, 6, 'npc_name_kill', 'npc_name', 153145, 'trillcor', 1, 153, 0, 0), +(18000510, 8415480, 0, 'npc_name_kill', 'npc_name', 154073, 'a grimling arcanist', 1, 154, 0, 0), +(18000511, 8415480, 1, 'npc_name_kill', 'npc_name', 154168, 'a grimling arch sage', 1, 154, 0, 0), +(18000512, 8415480, 2, 'npc_name_kill', 'npc_name', 154164, 'a grimling bloodpriest', 1, 154, 0, 0), +(18000513, 8415480, 3, 'npc_name_kill', 'npc_name', 154077, 'a grimling high priest', 1, 154, 0, 0), +(18000514, 8415480, 4, 'npc_name_kill', 'npc_name', 154165, 'a grimling primalist', 1, 154, 0, 0), +(18000515, 8415480, 5, 'npc_name_kill', 'npc_name', 154160, 'a grimling ritualist', 1, 154, 0, 0), +(18000516, 8415480, 6, 'npc_name_kill', 'npc_name', 154169, 'a grimling spiritist', 1, 154, 0, 0), +(18000517, 8415480, 7, 'npc_name_kill', 'npc_name', 154167, 'a grimling warlord', 1, 154, 0, 0), +(18000518, 8415680, 0, 'npc_name_kill', 'npc_name', 156114, 'ch`ktok', 1, 156, 0, 0), +(18000519, 8415680, 1, 'npc_name_kill', 'npc_name', 156112, 'a ravenous owlbear', 1, 156, 0, 0), +(18000520, 8415780, 0, 'npc_name_kill', 'npc_name', 157118, 'shuddering fungus', 1, 157, 0, 0), +(18000521, 8416180, 0, 'npc_name_kill', 'npc_name', 161040, 'a fungoid worker', 1, 161, 0, 0), +(18000522, 8416180, 1, 'npc_name_kill', 'npc_name', 161057, 'a mature fungoid', 1, 161, 0, 0), +(18000523, 8416180, 2, 'npc_name_kill', 'npc_name', 161066, 'a netherbian swarmcaller', 1, 161, 0, 0), +(18000524, 8416180, 3, 'npc_name_kill', 'npc_name', 161030, 'the swarm leader', 1, 161, 0, 0), +(18000525, 8416180, 4, 'npc_name_kill', 'npc_name', 161021, 'a trog hunter', 1, 161, 0, 0), +(18000526, 8416180, 5, 'npc_name_kill', 'npc_name', 161071, 'the trog king', 1, 161, 0, 0), +(18000527, 8416280, 0, 'npc_name_kill', 'npc_name', 162201, 'acolyte wivlx', 1, 162, 0, 0), +(18000528, 8416280, 1, 'npc_name_kill', 'npc_name', 162067, 'advisor zekuzh', 1, 162, 0, 0), +(18000529, 8416280, 2, 'npc_name_kill', 'npc_name', 162191, 'arbiter korazhk', 1, 162, 0, 0), +(18000530, 8416280, 3, 'npc_name_kill', 'npc_name', 162150, 'commander zazuzh', 1, 162, 0, 0), +(18000531, 8416280, 4, 'npc_name_kill', 'npc_name', 162217, 'commander zherozsh', 1, 162, 0, 0), +(18000532, 8416280, 5, 'npc_name_kill', 'npc_name', 162187, 'defiler juzlix', 1, 162, 0, 0), +(18000533, 8416280, 6, 'npc_name_kill', 'npc_name', 162180, 'disciple yelwinz', 1, 162, 0, 0), +(18000534, 8416280, 7, 'npc_name_kill', 'npc_name', 162257, 'disciple zhorluhx', 1, 162, 0, 0), +(18000535, 8416280, 8, 'npc_name_kill', 'npc_name', 162066, 'general kizuhx', 1, 162, 0, 0), +(18000536, 8416280, 9, 'npc_name_kill', 'npc_name', 162219, 'guard sklinus', 1, 162, 0, 0), +(18000537, 8416280, 10, 'npc_name_kill', 'npc_name', 162167, 'shissar assassin', 1, 162, 0, 0), +(18000538, 8416280, 11, 'npc_name_kill', 'npc_name', 162183, 'the shissar magister', 1, 162, 0, 0), +(18000539, 8416280, 12, 'npc_name_kill', 'npc_name', 162186, 'shissar mystic', 1, 162, 0, 0), +(18000540, 8416280, 13, 'npc_name_kill', 'npc_name', 162154, 'spiritward trilzic', 1, 162, 0, 0) +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_index` = VALUES(`objective_index`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`), +`zone_id` = VALUES(`zone_id`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +VALUES +(18000541, 8416280, 14, 'npc_name_kill', 'npc_name', 162087, 'zhroushe mezhkazh', 1, 162, 0, 0), +(18000542, 8416380, 0, 'npc_name_kill', 'npc_name', 163250, 'bronus', 1, 163, 0, 0), +(18000543, 8416480, 0, 'npc_name_kill', 'npc_name', 164088, 'chasm overseer', 1, 164, 0, 0), +(18000544, 8416480, 1, 'npc_name_kill', 'npc_name', 164041, 'a deepspore mushroom', 1, 164, 0, 0), +(18000545, 8416480, 2, 'npc_name_kill', 'npc_name', 164035, 'deranged underbulk', 1, 164, 0, 0), +(18000546, 8416480, 3, 'npc_name_kill', 'npc_name', 164069, 'a hideous thought leech', 1, 164, 0, 0), +(18000547, 8416480, 4, 'npc_name_kill', 'npc_name', 164103, 'koxiux the imperceptible', 1, 164, 0, 0), +(18000548, 8416480, 5, 'npc_name_kill', 'npc_name', 164096, 'lhurgoz the decayed', 1, 164, 0, 0), +(18000549, 8416480, 6, 'npc_name_kill', 'npc_name', 164106, 'oldencamp the lost', 1, 164, 0, 0), +(18000550, 8416480, 7, 'npc_name_kill', 'npc_name', 164114, 'slavekeeper xiox', 1, 164, 0, 0), +(18000551, 8416480, 8, 'npc_name_kill', 'npc_name', 164102, 'thought horror corrupter', 1, 164, 0, 0), +(18000552, 8416480, 9, 'npc_name_kill', 'npc_name', 164110, 'xeximoz', 1, 164, 0, 0), +(18000553, 8416580, 0, 'npc_name_kill', 'npc_name', 165085, 'seetheker', 1, 165, 0, 0), +(18000554, 8416680, 0, 'npc_name_kill', 'npc_name', 166260, 'curfang', 1, 166, 0, 0), +(18000555, 8416680, 1, 'npc_name_kill', 'npc_name', 166246, 'dreadmaw wolfkin', 1, 166, 0, 0), +(18000556, 8416680, 2, 'npc_name_kill', 'npc_name', 166268, 'fireclaw wolfkin', 1, 166, 0, 0), +(18000557, 8416680, 3, 'npc_name_kill', 'npc_name', 166278, 'gamtoine cursmakk', 1, 166, 0, 0), +(18000558, 8416680, 4, 'npc_name_kill', 'npc_name', 166153, 'ghowlik', 1, 166, 0, 0), +(18000559, 8416680, 5, 'npc_name_kill', 'npc_name', 166243, 'gleeknot gnitrat', 1, 166, 0, 0), +(18000560, 8416680, 6, 'npc_name_kill', 'npc_name', 166261, 'gniktar grinwit', 1, 166, 0, 0), +(18000561, 8416680, 7, 'npc_name_kill', 'npc_name', 166276, 'gorehorn', 1, 166, 0, 0), +(18000562, 8416680, 8, 'npc_name_kill', 'npc_name', 166252, 'prince skriatat', 1, 166, 0, 0), +(18000563, 8416680, 9, 'npc_name_kill', 'npc_name', 166248, 'warpaw dankpelt', 1, 166, 0, 0), +(18000564, 8416680, 10, 'npc_name_kill', 'npc_name', 166244, 'wiknak grimglom', 1, 166, 0, 0), +(18000565, 8416880, 0, 'npc_name_kill', 'npc_name', 168007, 'a recuso hunter', 1, 168, 0, 0), +(18000566, 8417080, 0, 'npc_name_kill', 'npc_name', 170267, 'aero', 1, 170, 0, 0), +(18000567, 8417080, 1, 'npc_name_kill', 'npc_name', 170223, 'a berserk air elemental', 1, 170, 0, 0), +(18000568, 8417080, 2, 'npc_name_kill', 'npc_name', 170231, 'a berserk fire elemental', 1, 170, 0, 0), +(18000569, 8417080, 3, 'npc_name_kill', 'npc_name', 170225, 'a berserk water elemental', 1, 170, 0, 0), +(18000570, 8417080, 4, 'npc_name_kill', 'npc_name', 170238, 'a gigantic air elemental', 1, 170, 0, 0), +(18000571, 8417080, 5, 'npc_name_kill', 'npc_name', 170259, 'a gigantic earth elemental', 1, 170, 0, 0), +(18000572, 8417080, 6, 'npc_name_kill', 'npc_name', 170012, 'a gigantic fire elemental', 1, 170, 0, 0), +(18000573, 8417080, 7, 'npc_name_kill', 'npc_name', 170244, 'a gigantic water elemental', 1, 170, 0, 0), +(18000574, 8417080, 8, 'npc_name_kill', 'npc_name', 170202, 'a greater fire elemental', 1, 170, 0, 0), +(18000575, 8417080, 9, 'npc_name_kill', 'npc_name', 170011, 'a greater water elemental', 1, 170, 0, 0), +(18000576, 8417080, 10, 'npc_name_kill', 'npc_name', 170268, 'hydro', 1, 170, 0, 0), +(18000577, 8417080, 11, 'npc_name_kill', 'npc_name', 170269, 'inferno', 1, 170, 0, 0), +(18000578, 8417080, 12, 'npc_name_kill', 'npc_name', 170161, 'praem softbreeze', 1, 170, 0, 0), +(18000579, 8417080, 13, 'npc_name_kill', 'npc_name', 170235, 'ranvin darkwaters', 1, 170, 0, 0), +(18000580, 8417080, 14, 'npc_name_kill', 'npc_name', 170204, 'terra', 1, 170, 0, 0), +(18000581, 8417080, 15, 'npc_name_kill', 'npc_name', 170053, 'a tro jeg official', 1, 170, 0, 0), +(18000582, 8417180, 0, 'npc_name_kill', 'npc_name', 171056, 'an ancient shissar servitor', 1, 171, 0, 0), +(18000583, 8417180, 1, 'npc_name_kill', 'npc_name', 171074, 'crusader kezzal', 1, 171, 0, 0), +(18000584, 8417180, 2, 'npc_name_kill', 'npc_name', 171065, 'heirophant grazan', 1, 171, 0, 0), +(18000585, 8417180, 3, 'npc_name_kill', 'npc_name', 171057, 'revenant sthzzzizt', 1, 171, 0, 0), +(18000586, 8417180, 4, 'npc_name_kill', 'npc_name', 171073, 'revenant zsshta', 1, 171, 0, 0), +(18000587, 8417180, 5, 'npc_name_kill', 'npc_name', 171068, 'a shattered golem', 1, 171, 0, 0), +(18000588, 8417280, 0, 'npc_name_kill', 'npc_name', 172151, 'emissary oomgado', 1, 172, 0, 0), +(18000589, 8417280, 1, 'npc_name_kill', 'npc_name', 172082, 'a grimling foreman', 1, 172, 0, 0), +(18000590, 8417280, 2, 'npc_name_kill', 'npc_name', 172083, 'a grol baku warlord', 1, 172, 0, 0), +(18000591, 8417280, 3, 'npc_name_kill', 'npc_name', 1985, 'skyshadow', 1, 172, 0, 0), +(18000592, 8417380, 0, 'npc_name_kill', 'npc_name', 173137, 'a goranga battlemaster', 1, 173, 0, 0), +(18000593, 8417380, 1, 'npc_name_kill', 'npc_name', 173126, 'a goranga chieftan', 1, 173, 0, 0), +(18000594, 8417380, 2, 'npc_name_kill', 'npc_name', 173129, 'a goranga forager', 1, 173, 0, 0), +(18000595, 8417380, 3, 'npc_name_kill', 'npc_name', 173127, 'a goranga prophet', 1, 173, 0, 0), +(18000596, 8417380, 4, 'npc_name_kill', 'npc_name', 173131, 'a goranga savant', 1, 173, 0, 0), +(18000597, 8417380, 5, 'npc_name_kill', 'npc_name', 173128, 'a goranga seer', 1, 173, 0, 0), +(18000598, 8417380, 6, 'npc_name_kill', 'npc_name', 173140, 'a shadow overlord', 1, 173, 0, 0), +(18000599, 8417380, 7, 'npc_name_kill', 'npc_name', 173114, 'a thought stealer', 1, 173, 0, 0), +(18000600, 8417380, 8, 'npc_name_kill', 'npc_name', 173143, 'xi thall', 1, 173, 0, 0), +(18000601, 8417480, 0, 'npc_name_kill', 'npc_name', 174316, 'an age old rockhopper', 1, 174, 0, 0), +(18000602, 8417480, 1, 'npc_name_kill', 'npc_name', 174249, 'fungus covered shroom', 1, 174, 0, 0), +(18000603, 8417480, 2, 'npc_name_kill', 'npc_name', 174256, 'sambata tribal advisor', 1, 174, 0, 0), +(18000604, 8417480, 3, 'npc_name_kill', 'npc_name', 174277, 'sambata tribal leader garn', 1, 174, 0, 0), +(18000605, 8417480, 4, 'npc_name_kill', 'npc_name', 174026, 'tribal advisor', 1, 174, 0, 0), +(18000606, 8417480, 5, 'npc_name_kill', 'npc_name', 174165, 'tribal hunter', 1, 174, 0, 0), +(18000607, 8417480, 6, 'npc_name_kill', 'npc_name', 174006, 'tribal leader', 1, 174, 0, 0), +(18000608, 8417480, 7, 'npc_name_kill', 'npc_name', 174162, 'tribal shaman', 1, 174, 0, 0), +(18000609, 8417580, 0, 'npc_name_kill', 'npc_name', 175281, 'bloodtribe ancient', 1, 175, 0, 0), +(18000610, 8417580, 1, 'npc_name_kill', 'npc_name', 175014, 'bloodtribe sneakster', 1, 175, 0, 0), +(18000611, 8417580, 2, 'npc_name_kill', 'npc_name', 175246, 'bloodtribe surveryor', 1, 175, 0, 0), +(18000612, 8417580, 3, 'npc_name_kill', 'npc_name', 175249, 'bloodtribe wiseman', 1, 175, 0, 0), +(18000613, 8417580, 4, 'npc_name_kill', 'npc_name', 175238, 'a gigantic sunflower', 1, 175, 0, 0), +(18000614, 8417580, 5, 'npc_name_kill', 'npc_name', 175256, 'a grol baku benefactor', 1, 175, 0, 0), +(18000615, 8417580, 6, 'npc_name_kill', 'npc_name', 175277, 'a grol baku bodyguard', 1, 175, 0, 0), +(18000616, 8417580, 7, 'npc_name_kill', 'npc_name', 175105, 'a grol baku keeper', 1, 175, 0, 0), +(18000617, 8417580, 8, 'npc_name_kill', 'npc_name', 175164, 'a grol baku retainer', 1, 175, 0, 0), +(18000618, 8417580, 9, 'npc_name_kill', 'npc_name', 175227, 'kraen flameweaver', 1, 175, 0, 0), +(18000619, 8417580, 10, 'npc_name_kill', 'npc_name', 175019, 'a lightcrawler drone', 1, 175, 0, 0), +(18000620, 8417580, 11, 'npc_name_kill', 'npc_name', 175020, 'a lively lightcrawler', 1, 175, 0, 0), +(18000621, 8417580, 12, 'npc_name_kill', 'npc_name', 175235, 'ruinous sun revenant', 1, 175, 0, 0), +(18000622, 8417580, 13, 'npc_name_kill', 'npc_name', 175218, 'sectoid', 1, 175, 0, 0), +(18000623, 8417580, 14, 'npc_name_kill', 'npc_name', 175223, 'sun revenant chancellor', 1, 175, 0, 0), +(18000624, 8417580, 15, 'npc_name_kill', 'npc_name', 175139, 'sun revenant desecrator', 1, 175, 0, 0), +(18000625, 8417580, 16, 'npc_name_kill', 'npc_name', 175004, 'sun revenant magistrate', 1, 175, 0, 0), +(18000626, 8417580, 17, 'npc_name_kill', 'npc_name', 175140, 'sun revenant primatus', 1, 175, 0, 0), +(18000627, 8417580, 18, 'npc_name_kill', 'npc_name', 175216, 'sun revenant smiter', 1, 175, 0, 0), +(18000628, 8417580, 19, 'npc_name_kill', 'npc_name', 175142, 'sun revenant warlock', 1, 175, 0, 0), +(18000629, 8417580, 20, 'npc_name_kill', 'npc_name', 175184, 'sunlord wedazi', 1, 175, 0, 0), +(18000630, 8417580, 21, 'npc_name_kill', 'npc_name', 175143, 'a thorny sunflower', 1, 175, 0, 0) +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_index` = VALUES(`objective_index`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`), +`zone_id` = VALUES(`zone_id`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +VALUES +(18000631, 8417580, 22, 'npc_name_kill', 'npc_name', 175201, 'a tro jeg captor', 1, 175, 0, 0), +(18000632, 8417580, 23, 'npc_name_kill', 'npc_name', 175185, 'a tro jeg firekeeper', 1, 175, 0, 0), +(18000633, 8417580, 24, 'npc_name_kill', 'npc_name', 175189, 'a tro jeg heathen', 1, 175, 0, 0), +(18000634, 8417580, 25, 'npc_name_kill', 'npc_name', 175101, 'a vas ren archon', 1, 175, 0, 0), +(18000635, 8417680, 0, 'npc_name_kill', 'npc_name', 176092, 'bile spew', 1, 176, 0, 0), +(18000636, 8417680, 1, 'npc_name_kill', 'npc_name', 176095, 'bloodwretch', 1, 176, 0, 0), +(18000637, 8417680, 2, 'npc_name_kill', 'npc_name', 176027, 'fallen sergeant', 1, 176, 0, 0), +(18000638, 8417680, 3, 'npc_name_kill', 'npc_name', 176083, 'festersore', 1, 176, 0, 0), +(18000639, 8417680, 4, 'npc_name_kill', 'npc_name', 176115, 'fleshrot', 1, 176, 0, 0), +(18000640, 8417680, 5, 'npc_name_kill', 'npc_name', 176098, 'fyrthek fior', 1, 176, 0, 0), +(18000641, 8417680, 6, 'npc_name_kill', 'npc_name', 176091, 'a shadowy assassin', 1, 176, 0, 0), +(18000642, 8417680, 7, 'npc_name_kill', 'npc_name', 176100, 'shak dathor warlord', 1, 176, 0, 0), +(18000643, 8417680, 8, 'npc_name_kill', 'npc_name', 176107, 'sylra fris', 1, 176, 0, 0), +(18000644, 8417980, 0, 'npc_name_kill', 'npc_name', 179122, 'altar priest', 1, 179, 0, 0), +(18000645, 8417980, 1, 'npc_name_kill', 'npc_name', 179084, 'diabo`teka`temariel', 1, 179, 0, 0), +(18000646, 8417980, 2, 'npc_name_kill', 'npc_name', 179114, 'lorekeeper', 1, 179, 0, 0), +(18000647, 8417980, 3, 'npc_name_kill', 'npc_name', 179159, 'transient emissary', 1, 179, 0, 0), +(18000648, 8417980, 4, 'npc_name_kill', 'npc_name', 179179, 'transient xakra', 1, 179, 0, 0), +(18000649, 8417980, 5, 'npc_name_kill', 'npc_name', 179166, 'transient xin', 1, 179, 0, 0), +(18000650, 8417980, 6, 'npc_name_kill', 'npc_name', 179128, 'vius`tekar', 1, 179, 0, 0), +(18000651, 8417980, 7, 'npc_name_kill', 'npc_name', 179177, 'warlord', 1, 179, 0, 0), +(18000652, 8480980, 0, 'npc_name_kill', 'npc_name', 167337, 'avisiris', 1, 167, 0, 0), +(18000653, 8480980, 1, 'npc_name_kill', 'npc_name', 167334, 'a raspy grimling', 1, 167, 0, 0), +(18000654, 8480980, 2, 'npc_name_kill', 'npc_name', 167670, 'spiritmaster ugreth', 1, 167, 0, 0), +(18000655, 8480980, 3, 'npc_name_kill', 'npc_name', 167077, 'spymaster gephes', 1, 167, 0, 0), +(18000656, 8520080, 0, 'npc_name_kill', 'npc_name', 200072, 'assassin kakoo', 1, 200, 0, 0), +(18000657, 8520080, 1, 'npc_name_kill', 'npc_name', 200028, 'bubonian death caster', 1, 200, 0, 0), +(18000658, 8520080, 2, 'npc_name_kill', 'npc_name', 200029, 'bubonian great mystic', 1, 200, 0, 0), +(18000659, 8520080, 3, 'npc_name_kill', 'npc_name', 200026, 'bubonian warlord', 1, 200, 0, 0), +(18000660, 8520080, 4, 'npc_name_kill', 'npc_name', 200006, 'crazed bubonian berzerker', 1, 200, 0, 0), +(18000661, 8520080, 5, 'npc_name_kill', 'npc_name', 200069, 'deathbone archmagus', 1, 200, 0, 0), +(18000662, 8520080, 6, 'npc_name_kill', 'npc_name', 200014, 'elite corrupted knight', 1, 200, 0, 0), +(18000663, 8520080, 7, 'npc_name_kill', 'npc_name', 200015, 'elite death knight', 1, 200, 0, 0), +(18000664, 8520080, 8, 'npc_name_kill', 'npc_name', 200042, 'elite knight of decay', 1, 200, 0, 0), +(18000665, 8520080, 9, 'npc_name_kill', 'npc_name', 200063, 'elite necromancer of decay', 1, 200, 0, 0), +(18000666, 8520080, 10, 'npc_name_kill', 'npc_name', 200043, 'elite priest of decay', 1, 200, 0, 0), +(18000667, 8520080, 11, 'npc_name_kill', 'npc_name', 200073, 'eviscerator fwexar', 1, 200, 0, 0), +(18000668, 8520080, 12, 'npc_name_kill', 'npc_name', 200070, 'firebone archmagus', 1, 200, 0, 0), +(18000669, 8520080, 13, 'npc_name_kill', 'npc_name', 200019, 'greater corrupted pusling', 1, 200, 0, 0), +(18000670, 8520080, 14, 'npc_name_kill', 'npc_name', 200031, 'greater foul pusling', 1, 200, 0, 0), +(18000671, 8520080, 15, 'npc_name_kill', 'npc_name', 200074, 'high mystic qucosp', 1, 200, 0, 0), +(18000672, 8520080, 16, 'npc_name_kill', 'npc_name', 200030, 'pestilence archon', 1, 200, 0, 0), +(18000673, 8520080, 17, 'npc_name_kill', 'npc_name', 200058, 'plague lord hetral', 1, 200, 0, 0), +(18000674, 8520080, 18, 'npc_name_kill', 'npc_name', 200076, 'war chieftain dorwikak', 1, 200, 0, 0), +(18000675, 8520080, 19, 'npc_name_kill', 'npc_name', 200075, 'witchdoctor orxkra', 1, 200, 0, 0), +(18000676, 8520180, 0, 'npc_name_kill', 'npc_name', 201445, 'the ancient crawler', 1, 201, 0, 0), +(18000677, 8520180, 1, 'npc_name_kill', 'npc_name', 201442, 'a blood leech', 1, 201, 0, 0), +(18000678, 8520180, 2, 'npc_name_kill', 'npc_name', 201443, 'a diamond beetle', 1, 201, 0, 0), +(18000679, 8520180, 3, 'npc_name_kill', 'npc_name', 201334, 'a grallok appraisor', 1, 201, 0, 0), +(18000680, 8520180, 4, 'npc_name_kill', 'npc_name', 201385, 'a grallok crusader', 1, 201, 0, 0), +(18000681, 8520180, 5, 'npc_name_kill', 'npc_name', 201274, 'a grallok elder', 1, 201, 0, 0), +(18000682, 8520180, 6, 'npc_name_kill', 'npc_name', 201183, 'a grallok overseer', 1, 201, 0, 0), +(18000683, 8520180, 7, 'npc_name_kill', 'npc_name', 201502, 'the grallok underlord', 1, 201, 0, 0), +(18000684, 8520180, 8, 'npc_name_kill', 'npc_name', 201168, 'a screeching parasite', 1, 201, 0, 0), +(18000685, 8520180, 9, 'npc_name_kill', 'npc_name', 201422, 'the yrendan scarab', 1, 201, 0, 0), +(18000686, 8520480, 0, 'npc_name_kill', 'npc_name', 204043, 'an agony mephit', 1, 204, 0, 0), +(18000687, 8520480, 1, 'npc_name_kill', 'npc_name', 204049, 'a bullyrag bat', 1, 204, 0, 0), +(18000688, 8520480, 2, 'npc_name_kill', 'npc_name', 204044, 'a fearsome hobgoblin', 1, 204, 0, 0), +(18000689, 8520480, 3, 'npc_name_kill', 'npc_name', 204048, 'a fiendish consort', 1, 204, 0, 0), +(18000690, 8520480, 4, 'npc_name_kill', 'npc_name', 204033, 'an infernal consort', 1, 204, 0, 0), +(18000691, 8520480, 5, 'npc_name_kill', 'npc_name', 204050, 'a painwrack hobgoblin', 1, 204, 0, 0), +(18000692, 8520580, 0, 'npc_name_kill', 'npc_name', 205160, 'an arachnae parian', 1, 205, 0, 0), +(18000693, 8520580, 1, 'npc_name_kill', 'npc_name', 205148, 'a diseased infested bubonian', 1, 205, 0, 0), +(18000694, 8520580, 2, 'npc_name_kill', 'npc_name', 205159, 'a malarian metamo', 1, 205, 0, 0), +(18000695, 8520580, 3, 'npc_name_kill', 'npc_name', 205158, 'a sengian fly', 1, 205, 0, 0), +(18000696, 8520680, 0, 'npc_name_kill', 'npc_name', 206060, 'junk beast', 1, 206, 0, 0), +(18000697, 8520780, 0, 'npc_name_kill', 'npc_name', 207057, 'the avatar of agony', 1, 207, 0, 0), +(18000698, 8520780, 1, 'npc_name_kill', 'npc_name', 207054, 'the avatar of anguish', 1, 207, 0, 0), +(18000699, 8520780, 2, 'npc_name_kill', 'npc_name', 207067, 'the avatar of pain', 1, 207, 0, 0), +(18000700, 8520780, 3, 'npc_name_kill', 'npc_name', 207064, 'the avatar of suffering', 1, 207, 0, 0), +(18000701, 8520780, 4, 'npc_name_kill', 'npc_name', 207088, 'dirge malicia', 1, 207, 0, 0), +(18000702, 8520780, 5, 'npc_name_kill', 'npc_name', 207046, 'a pain devourer', 1, 207, 0, 0), +(18000703, 8520780, 6, 'npc_name_kill', 'npc_name', 207044, 'a sorrow seeker', 1, 207, 0, 0), +(18000704, 8520880, 0, 'npc_name_kill', 'npc_name', 208180, 'a diseased guard', 1, 208, 0, 0), +(18000705, 8520880, 1, 'npc_name_kill', 'npc_name', 208181, 'a festering worm', 1, 208, 0, 0), +(18000706, 8520880, 2, 'npc_name_kill', 'npc_name', 208164, 'lieutenant baelin dwinn', 1, 208, 0, 0), +(18000707, 8520880, 3, 'npc_name_kill', 'npc_name', 208006, 'a luminii crawler', 1, 208, 0, 0), +(18000708, 8520880, 4, 'npc_name_kill', 'npc_name', 208182, 'sergeant terrick burns', 1, 208, 0, 0), +(18000709, 8520880, 5, 'npc_name_kill', 'npc_name', 208082, 'a skeletal guardian', 1, 208, 0, 0), +(18000710, 8520880, 6, 'npc_name_kill', 'npc_name', 208167, 'a traglimite frog', 1, 208, 0, 0), +(18000711, 8520880, 7, 'npc_name_kill', 'npc_name', 208062, 'an undead doorman', 1, 208, 0, 0), +(18000712, 8520880, 8, 'npc_name_kill', 'npc_name', 208072, 'an undead footman', 1, 208, 0, 0), +(18000713, 8520980, 0, 'npc_name_kill', 'npc_name', 209080, 'amnquetil brynjulffr', 1, 209, 0, 0), +(18000714, 8520980, 1, 'npc_name_kill', 'npc_name', 209078, 'atle cloudburst', 1, 209, 0, 0), +(18000715, 8520980, 2, 'npc_name_kill', 'npc_name', 209077, 'bordir bjomolf', 1, 209, 0, 0), +(18000716, 8520980, 3, 'npc_name_kill', 'npc_name', 209109, 'elif whitewind', 1, 209, 0, 0), +(18000717, 8520980, 4, 'npc_name_kill', 'npc_name', 209073, 'erech eyford', 1, 209, 0, 0), +(18000718, 8520980, 5, 'npc_name_kill', 'npc_name', 209074, 'fogl iceshard', 1, 209, 0, 0), +(18000719, 8520980, 6, 'npc_name_kill', 'npc_name', 209121, 'galm snowdrift', 1, 209, 0, 0), +(18000720, 8520980, 7, 'npc_name_kill', 'npc_name', 209096, 'riodhr torrentwind', 1, 209, 0, 0) +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_index` = VALUES(`objective_index`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`), +`zone_id` = VALUES(`zone_id`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +VALUES +(18000721, 8520980, 8, 'npc_name_kill', 'npc_name', 209081, 'rorek steelthorn', 1, 209, 0, 0), +(18000722, 8520980, 9, 'npc_name_kill', 'npc_name', 209098, 'thangbrand', 1, 209, 0, 0), +(18000723, 8520980, 10, 'npc_name_kill', 'npc_name', 209091, 'thorolf sutherland', 1, 209, 0, 0), +(18000724, 8520980, 11, 'npc_name_kill', 'npc_name', 209087, 'torstien stoneskin', 1, 209, 0, 0), +(18000725, 8520980, 12, 'npc_name_kill', 'npc_name', 209097, 'valbrand', 1, 209, 0, 0), +(18000726, 8520980, 13, 'npc_name_kill', 'npc_name', 209090, 'wybjorn', 1, 209, 0, 0), +(18000727, 8520980, 14, 'npc_name_kill', 'npc_name', 209083, 'ymir stormseer', 1, 209, 0, 0), +(18000728, 8521180, 0, 'npc_name_kill', 'npc_name', 211067, 'captain danon shern', 1, 211, 0, 0), +(18000729, 8521180, 1, 'npc_name_kill', 'npc_name', 211110, 'captain kage shou', 1, 211, 0, 0), +(18000730, 8521180, 2, 'npc_name_kill', 'npc_name', 211068, 'konid merdrid', 1, 211, 0, 0), +(18000731, 8521180, 3, 'npc_name_kill', 'npc_name', 211070, 'a protector of valor', 1, 211, 0, 0), +(18000732, 8521180, 4, 'npc_name_kill', 'npc_name', 211027, 'a wrulon protector', 1, 211, 0, 0), +(18000733, 8521180, 5, 'npc_name_kill', 'npc_name', 211009, 'a wrulon sentry', 1, 211, 0, 0), +(18000734, 8521280, 0, 'npc_name_kill', 'npc_name', 212072, 'a fervid magmin', 1, 212, 0, 0), +(18000735, 8521280, 1, 'npc_name_kill', 'npc_name', 212059, 'a flare mephit', 1, 212, 0, 0), +(18000736, 8521280, 2, 'npc_name_kill', 'npc_name', 212065, 'a pumice collector', 1, 212, 0, 0), +(18000737, 8521280, 3, 'npc_name_kill', 'npc_name', 212024, 'a radiant guardian', 1, 212, 0, 0), +(18000738, 8521280, 4, 'npc_name_kill', 'npc_name', 212066, 'a runed giant', 1, 212, 0, 0), +(18000739, 8521280, 5, 'npc_name_kill', 'npc_name', 212044, 'a sweltering mephit', 1, 212, 0, 0), +(18000740, 8521480, 0, 'npc_name_kill', 'npc_name', 214033, 'anival the blade', 1, 214, 0, 0), +(18000741, 8521480, 1, 'npc_name_kill', 'npc_name', 214121, 'the diaku supplier', 1, 214, 0, 0), +(18000742, 8521480, 2, 'npc_name_kill', 'npc_name', 214122, 'an enraged war boar', 1, 214, 0, 0), +(18000743, 8521480, 3, 'npc_name_kill', 'npc_name', 214027, 'a frenzied initiate', 1, 214, 0, 0), +(18000744, 8521480, 4, 'npc_name_kill', 'npc_name', 214075, 'hinvat deathbringer', 1, 214, 0, 0), +(18000745, 8521480, 5, 'npc_name_kill', 'npc_name', 214051, 'shadow master vinta', 1, 214, 0, 0), +(18000746, 8521480, 6, 'npc_name_kill', 'npc_name', 214103, 'zelrin morlock', 1, 214, 0, 0), +(18000747, 8521580, 0, 'npc_name_kill', 'npc_name', 215061, 'calebgrothiel', 1, 215, 0, 0), +(18000748, 8521580, 1, 'npc_name_kill', 'npc_name', 215060, 'lossenmachar', 1, 215, 0, 0), +(18000749, 8521580, 2, 'npc_name_kill', 'npc_name', 215058, 'a phoenix breezewing', 1, 215, 0, 0), +(18000750, 8521580, 3, 'npc_name_kill', 'npc_name', 215028, 'a phoenix searedwing', 1, 215, 0, 0), +(18000751, 8521680, 0, 'npc_name_kill', 'npc_name', 216093, 'an enormous frog', 1, 216, 0, 0), +(18000752, 8521680, 1, 'npc_name_kill', 'npc_name', 216091, 'ferocious barracuda', 1, 216, 0, 0), +(18000753, 8521680, 2, 'npc_name_kill', 'npc_name', 216092, 'frenzied anglerfish', 1, 216, 0, 0), +(18000754, 8521680, 3, 'npc_name_kill', 'npc_name', 216075, 'furious deepwater kraken', 1, 216, 0, 0), +(18000755, 8521680, 4, 'npc_name_kill', 'npc_name', 216037, 'gigadon', 1, 216, 0, 0), +(18000756, 8521680, 5, 'npc_name_kill', 'npc_name', 216095, 'hammertooth', 1, 216, 0, 0), +(18000757, 8521680, 6, 'npc_name_kill', 'npc_name', 216096, 'hraquis arch magus', 1, 216, 0, 0), +(18000758, 8521680, 7, 'npc_name_kill', 'npc_name', 216045, 'hraquis chieftain', 1, 216, 0, 0), +(18000759, 8521680, 8, 'npc_name_kill', 'npc_name', 216038, 'monstrous sea turtle', 1, 216, 0, 0), +(18000760, 8521680, 9, 'npc_name_kill', 'npc_name', 216056, 'razorfin', 1, 216, 0, 0), +(18000761, 8521680, 10, 'npc_name_kill', 'npc_name', 216053, 'regrua overlord', 1, 216, 0, 0), +(18000762, 8521680, 11, 'npc_name_kill', 'npc_name', 216097, 'regrua protector', 1, 216, 0, 0), +(18000763, 8521680, 12, 'npc_name_kill', 'npc_name', 216054, 'savage deepwater kraken', 1, 216, 0, 0), +(18000764, 8521680, 13, 'npc_name_kill', 'npc_name', 216050, 'swordfang', 1, 216, 0, 0), +(18000765, 8521680, 14, 'npc_name_kill', 'npc_name', 216051, 'triloun egg keeper', 1, 216, 0, 0), +(18000766, 8521680, 15, 'npc_name_kill', 'npc_name', 216105, 'triloun seer', 1, 216, 0, 0), +(18000767, 8521680, 16, 'npc_name_kill', 'npc_name', 216098, 'triloun warder', 1, 216, 0, 0), +(18000768, 8521780, 0, 'npc_name_kill', 'npc_name', 217018, 'captain of fire', 1, 217, 0, 0), +(18000769, 8521780, 1, 'npc_name_kill', 'npc_name', 217073, 'charmer of fire', 1, 217, 0, 0), +(18000770, 8521780, 2, 'npc_name_kill', 'npc_name', 217106, 'dark obsidian lava spider', 1, 217, 0, 0), +(18000771, 8521780, 3, 'npc_name_kill', 'npc_name', 217089, 'doomfire firecharmer', 1, 217, 0, 0), +(18000772, 8521780, 4, 'npc_name_kill', 'npc_name', 217062, 'doomfire magus', 1, 217, 0, 0), +(18000773, 8521780, 5, 'npc_name_kill', 'npc_name', 217090, 'doomfire reaver', 1, 217, 0, 0), +(18000774, 8521780, 6, 'npc_name_kill', 'npc_name', 217091, 'doomfire vicar', 1, 217, 0, 0), +(18000775, 8521780, 7, 'npc_name_kill', 'npc_name', 217092, 'doomfire warlord', 1, 217, 0, 0), +(18000776, 8521780, 8, 'npc_name_kill', 'npc_name', 217065, 'doomfire warmaster', 1, 217, 0, 0), +(18000777, 8521780, 9, 'npc_name_kill', 'npc_name', 217093, 'fiery spirit equine overlord', 1, 217, 0, 0), +(18000778, 8521780, 10, 'npc_name_kill', 'npc_name', 217064, 'flame overlord', 1, 217, 0, 0), +(18000779, 8521780, 11, 'npc_name_kill', 'npc_name', 217094, 'flame wilder', 1, 217, 0, 0), +(18000780, 8521780, 12, 'npc_name_kill', 'npc_name', 217095, 'jopal chieftain', 1, 217, 0, 0), +(18000781, 8521780, 13, 'npc_name_kill', 'npc_name', 217060, 'jopal crafter', 1, 217, 0, 0), +(18000782, 8521780, 14, 'npc_name_kill', 'npc_name', 217096, 'jopal flame protector', 1, 217, 0, 0), +(18000783, 8521780, 15, 'npc_name_kill', 'npc_name', 217097, 'jopal seer', 1, 217, 0, 0), +(18000784, 8521780, 16, 'npc_name_kill', 'npc_name', 217098, 'jopal tracker', 1, 217, 0, 0), +(18000785, 8521780, 17, 'npc_name_kill', 'npc_name', 217105, 'magma overlord', 1, 217, 0, 0), +(18000786, 8521780, 18, 'npc_name_kill', 'npc_name', 217099, 'obsidian tree spider queen', 1, 217, 0, 0), +(18000787, 8521780, 19, 'npc_name_kill', 'npc_name', 217040, 'obsidian war spider', 1, 217, 0, 0), +(18000788, 8521780, 20, 'npc_name_kill', 'npc_name', 217055, 'sorcerer of fire', 1, 217, 0, 0), +(18000789, 8521780, 21, 'npc_name_kill', 'npc_name', 217075, 'vicar of fire', 1, 217, 0, 0), +(18000790, 8521780, 22, 'npc_name_kill', 'npc_name', 217074, 'wild fiery spirit steed', 1, 217, 0, 0), +(18000791, 8522080, 0, 'npc_name_kill', 'npc_name', 220005, 'a wrulon protector', 1, 220, 0, 0), +(18000792, 8522180, 0, 'npc_name_kill', 'npc_name', 221001, 'protector of terris', 1, 221, 0, 0), +(18000793, 8522180, 1, 'npc_name_kill', 'npc_name', 221003, 'sentry of nightmares', 1, 221, 0, 0), +(18000794, 8127880, 0, 'npc_name_kill', 'npc_name', 278111, 'erpar flamegar', 1, 278, 0, 0), +(18000795, 8127880, 1, 'npc_name_kill', 'npc_name', 278063, 'gigantic ashwalker', 1, 278, 0, 0), +(18000796, 8127880, 2, 'npc_name_kill', 'npc_name', 278110, 'kushara perecran', 1, 278, 0, 0), +(18000797, 8127880, 3, 'npc_name_kill', 'npc_name', 278101, 'pulsating pool of magma', 1, 278, 0, 0), +(18000798, 8127880, 4, 'npc_name_kill', 'npc_name', 278058, 'servant of flame', 1, 278, 0, 0), +(18000799, 8127880, 5, 'npc_name_kill', 'npc_name', 278038, 'smoldering tentacle terror', 1, 278, 0, 0), +(18000800, 8127880, 6, 'npc_name_kill', 'npc_name', 278107, 'tybog adalmond', 1, 278, 0, 0), +(18000801, 8127880, 7, 'npc_name_kill', 'npc_name', 278069, 'typhoeus', 1, 278, 0, 0), +(18000802, 8127880, 8, 'npc_name_kill', 'npc_name', 278077, 'xaon bulzekel', 1, 278, 0, 0), +(18000803, 8622480, 0, 'npc_name_kill', 'npc_name', 224316, 'blood tusk', 1, 224, 0, 0), +(18000804, 8622480, 1, 'npc_name_kill', 'npc_name', 224318, 'a dastardly scoundrel', 1, 224, 0, 0), +(18000805, 8622480, 2, 'npc_name_kill', 'npc_name', 224317, 'dominator zrabix', 1, 224, 0, 0), +(18000806, 8622480, 3, 'npc_name_kill', 'npc_name', 224321, 'dreadmaster jrup', 1, 224, 0, 0), +(18000807, 8622480, 4, 'npc_name_kill', 'npc_name', 224322, 'guard dragrik', 1, 224, 0, 0), +(18000808, 8622480, 5, 'npc_name_kill', 'npc_name', 224281, 'hatethorn', 1, 224, 0, 0), +(18000809, 8622480, 6, 'npc_name_kill', 'npc_name', 224320, 'a human recruit', 1, 224, 0, 0), +(18000810, 8622480, 7, 'npc_name_kill', 'npc_name', 224326, 'kalii brokenskull', 1, 224, 0, 0) +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_index` = VALUES(`objective_index`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`), +`zone_id` = VALUES(`zone_id`); +)" +R"( + +INSERT INTO `custom_achievement_objectives` +(`id`, `achievement_id`, `objective_index`, `objective_type`, `target_type`, `target_id`, `target_name`, `required_count`, `zone_id`, `class_mask`, `optional`) +VALUES +(18000811, 8622480, 8, 'npc_name_kill', 'npc_name', 224327, 'magus evana bavomon', 1, 224, 0, 0), +(18000812, 8622480, 9, 'npc_name_kill', 'npc_name', 224239, 'mokon brokenskull', 1, 224, 0, 0), +(18000813, 8622480, 10, 'npc_name_kill', 'npc_name', 224319, 'a mutant cohort', 1, 224, 0, 0), +(18000814, 8622480, 11, 'npc_name_kill', 'npc_name', 224315, 'an old sea dog', 1, 224, 0, 0), +(18000815, 8622480, 12, 'npc_name_kill', 'npc_name', 224328, 'oracle pagrossa', 1, 224, 0, 0), +(18000816, 8622480, 13, 'npc_name_kill', 'npc_name', 224330, 'preceptor grakomus', 1, 224, 0, 0), +(18000817, 8622480, 14, 'npc_name_kill', 'npc_name', 224331, 'rite master kvimimn', 1, 224, 0, 0), +(18000818, 8622480, 15, 'npc_name_kill', 'npc_name', 224332, 'sea captain azobus', 1, 224, 0, 0), +(18000819, 8622480, 16, 'npc_name_kill', 'npc_name', 224333, 'soothsayer mrugg doxok', 1, 224, 0, 0), +(18000820, 8622480, 17, 'npc_name_kill', 'npc_name', 224334, 'treasure hunter eranil', 1, 224, 0, 0), +(18000821, 8622480, 18, 'npc_name_kill', 'npc_name', 224335, 'warmaster mragoc', 1, 224, 0, 0), +(18000822, 8622580, 0, 'npc_name_kill', 'npc_name', 225349, 'architect vaukin', 1, 225, 0, 0), +(18000823, 8622580, 1, 'npc_name_kill', 'npc_name', 225352, 'a blackblooded taskmaster', 1, 225, 0, 0), +(18000824, 8622580, 2, 'npc_name_kill', 'npc_name', 225377, 'a defiled dedicant', 1, 225, 0, 0), +(18000825, 8622580, 3, 'npc_name_kill', 'npc_name', 225348, 'an enraged soulstealer', 1, 225, 0, 0), +(18000826, 8622580, 4, 'npc_name_kill', 'npc_name', 225344, 'a fleshchild of innoruuk', 1, 225, 0, 0), +(18000827, 8622580, 5, 'npc_name_kill', 'npc_name', 225354, 'galikor sevalin', 1, 225, 0, 0), +(18000828, 8622580, 6, 'npc_name_kill', 'npc_name', 225355, 'head chef grishnak', 1, 225, 0, 0), +(18000829, 8622580, 7, 'npc_name_kill', 'npc_name', 225356, 'incantator cawrolis', 1, 225, 0, 0), +(18000830, 8622580, 8, 'npc_name_kill', 'npc_name', 225357, 'konus alatuk', 1, 225, 0, 0), +(18000831, 8622580, 9, 'npc_name_kill', 'npc_name', 225358, 'linlanik throatcutter', 1, 225, 0, 0), +(18000832, 8622580, 10, 'npc_name_kill', 'npc_name', 225383, 'a luggald assassin', 1, 225, 0, 0), +(18000833, 8622580, 11, 'npc_name_kill', 'npc_name', 225304, 'an ore refinery overseer', 1, 225, 0, 0), +(18000834, 8622580, 12, 'npc_name_kill', 'npc_name', 225326, 'a shrouded cave lurker', 1, 225, 0, 0), +(18000835, 8622580, 13, 'npc_name_kill', 'npc_name', 225345, 'a shrouded fareyes', 1, 225, 0, 0), +(18000836, 8622580, 14, 'npc_name_kill', 'npc_name', 225031, 'treasure sorter neiben', 1, 225, 0, 0), +(18000837, 8622580, 15, 'npc_name_kill', 'npc_name', 225366, 'vurag', 1, 225, 0, 0), +(18000838, 8622580, 16, 'npc_name_kill', 'npc_name', 225372, 'xorikaan farzlebual', 1, 225, 0, 0), +(18000839, 8622680, 0, 'npc_name_kill', 'npc_name', 226188, 'bishop rimak', 1, 226, 0, 0), +(18000840, 8622680, 1, 'npc_name_kill', 'npc_name', 226194, 'the broken skull bloodlord', 1, 226, 0, 0), +(18000841, 8622680, 2, 'npc_name_kill', 'npc_name', 226195, 'the broken skull brawler', 1, 226, 0, 0), +(18000842, 8622680, 3, 'npc_name_kill', 'npc_name', 226196, 'the broken skull defender', 1, 226, 0, 0), +(18000843, 8622680, 4, 'npc_name_kill', 'npc_name', 226197, 'the broken skull dreadlord', 1, 226, 0, 0), +(18000844, 8622680, 5, 'npc_name_kill', 'npc_name', 226198, 'the broken skull mercenary', 1, 226, 0, 0), +(18000845, 8622680, 6, 'npc_name_kill', 'npc_name', 226199, 'the broken skull seer', 1, 226, 0, 0), +(18000846, 8622680, 7, 'npc_name_kill', 'npc_name', 226100, 'the broken skull warlord', 1, 226, 0, 0), +(18000847, 8622680, 8, 'npc_name_kill', 'npc_name', 226116, 'the corrupted half elf miner', 1, 226, 0, 0), +(18000848, 8622680, 9, 'npc_name_kill', 'npc_name', 226101, 'the crazed halfling lunatic', 1, 226, 0, 0), +(18000849, 8622680, 10, 'npc_name_kill', 'npc_name', 226189, 'dayned the insane', 1, 226, 0, 0), +(18000850, 8622680, 11, 'npc_name_kill', 'npc_name', 226102, 'the fanatical dwarf zealot', 1, 226, 0, 0), +(18000851, 8622680, 12, 'npc_name_kill', 'npc_name', 226190, 'foreman deslug', 1, 226, 0, 0), +(18000852, 8622680, 13, 'npc_name_kill', 'npc_name', 226103, 'the forsaken miner', 1, 226, 0, 0), +(18000853, 8622680, 14, 'npc_name_kill', 'npc_name', 226104, 'the luggald defiler', 1, 226, 0, 0), +(18000854, 8622680, 15, 'npc_name_kill', 'npc_name', 226105, 'the maniacal kobold miner', 1, 226, 0, 0), +(18000855, 8622680, 16, 'npc_name_kill', 'npc_name', 226106, 'the mutated laborer', 1, 226, 0, 0), +(18000856, 8622680, 17, 'npc_name_kill', 'npc_name', 226191, 'ritualist tzobodin', 1, 226, 0, 0), +(18000857, 8622680, 18, 'npc_name_kill', 'npc_name', 226192, 'scryer xvalos', 1, 226, 0, 0), +(18000858, 8622680, 19, 'npc_name_kill', 'npc_name', 226193, 'taskmaster waggad brokenskull', 1, 226, 0, 0), +(18000859, 8622780, 0, 'npc_name_kill', 'npc_name', 227109, 'a blackhand lieutenant', 1, 227, 0, 0), +(18000860, 8622780, 1, 'npc_name_kill', 'npc_name', 227025, 'a blackhand veteran', 1, 227, 0, 0), +(18000861, 8622780, 2, 'npc_name_kill', 'npc_name', 227224, 'a broken skull prophet', 1, 227, 0, 0), +(18000862, 8622780, 3, 'npc_name_kill', 'npc_name', 227301, 'a broken skull vassal', 1, 227, 0, 0), +(18000863, 8622780, 4, 'npc_name_kill', 'npc_name', 227307, 'captain aivilo', 1, 227, 0, 0), +(18000864, 8622780, 5, 'npc_name_kill', 'npc_name', 227298, 'a cloister sentinel', 1, 227, 0, 0), +(18000865, 8622780, 6, 'npc_name_kill', 'npc_name', 227127, 'a decaying fisherman', 1, 227, 0, 0), +(18000866, 8622780, 7, 'npc_name_kill', 'npc_name', 227108, 'dulein gedasai', 1, 227, 0, 0), +(18000867, 8622780, 8, 'npc_name_kill', 'npc_name', 227126, 'elder shaman elgruk', 1, 227, 0, 0), +(18000868, 8622780, 9, 'npc_name_kill', 'npc_name', 227114, 'an exhausted bloodtusk', 1, 227, 0, 0), +(18000869, 8622780, 10, 'npc_name_kill', 'npc_name', 227124, 'foreman kraksanar', 1, 227, 0, 0), +(18000870, 8622780, 11, 'npc_name_kill', 'npc_name', 227316, 'kdansol borgir', 1, 227, 0, 0), +(18000871, 8622780, 12, 'npc_name_kill', 'npc_name', 227317, 'kraska mreth', 1, 227, 0, 0), +(18000872, 8622780, 13, 'npc_name_kill', 'npc_name', 227318, 'spiritcharmer hargortaz', 1, 227, 0, 0), +(18000873, 8622780, 14, 'npc_name_kill', 'npc_name', 227123, 'an undead weaponsmith', 1, 227, 0, 0), +(18000874, 8622880, 0, 'npc_name_kill', 'npc_name', 228097, 'cabin gnome fitzgerald', 1, 228, 0, 0), +(18000875, 8622880, 1, 'npc_name_kill', 'npc_name', 228099, 'chef gokig', 1, 228, 0, 0), +(18000876, 8622880, 2, 'npc_name_kill', 'npc_name', 228100, 'harbinger iinati', 1, 228, 0, 0), +(18000877, 8622880, 3, 'npc_name_kill', 'npc_name', 228098, 'high priest anaanci', 1, 228, 0, 0), +(18000878, 8622880, 4, 'npc_name_kill', 'npc_name', 228056, 'lieutenant commander vzain', 1, 228, 0, 0), +(18000879, 8622880, 5, 'npc_name_kill', 'npc_name', 228105, 'the luggald interrogator', 1, 228, 0, 0), +(18000880, 8622880, 6, 'npc_name_kill', 'npc_name', 228101, 'quartermaster fisan', 1, 228, 0, 0), +(18000881, 8622880, 7, 'npc_name_kill', 'npc_name', 228052, 'scout shin`ci', 1, 228, 0, 0), +(18000882, 8622880, 8, 'npc_name_kill', 'npc_name', 228103, 'serang vikch', 1, 228, 0, 0), +(18000883, 8622880, 9, 'npc_name_kill', 'npc_name', 228104, 'shoqui the forgotten', 1, 228, 0, 0), +(18000884, 8622880, 10, 'npc_name_kill', 'npc_name', 228106, 'uumuvan the soulless', 1, 228, 0, 0), +(18000885, 8714280, 0, 'npc_name_kill', 'npc_name', 242024, 'ruined amalgam', 1, 242, 0, 0), +(18000886, 8745080, 0, 'npc_name_kill', 'npc_name', 269008, 'rebellious arcanist', 1, 269, 0, 0) +ON DUPLICATE KEY UPDATE +`achievement_id` = VALUES(`achievement_id`), +`objective_index` = VALUES(`objective_index`), +`objective_type` = VALUES(`objective_type`), +`target_type` = VALUES(`target_type`), +`target_id` = VALUES(`target_id`), +`target_name` = VALUES(`target_name`), +`required_count` = VALUES(`required_count`), +`zone_id` = VALUES(`zone_id`); +)" +R"()", + .content_schema_update = false, + }, }; // see struct definitions for what each field does diff --git a/common/version.h b/common/version.h index 560b0425ee..5374845dd9 100644 --- a/common/version.h +++ b/common/version.h @@ -40,4 +40,4 @@ #define CURRENT_BINARY_DATABASE_VERSION 9328 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9055 -#define CUSTOM_BINARY_DATABASE_VERSION 1 +#define CUSTOM_BINARY_DATABASE_VERSION 4 diff --git a/docs/achievements.md b/docs/achievements.md new file mode 100644 index 0000000000..d0db08456e --- /dev/null +++ b/docs/achievements.md @@ -0,0 +1,31 @@ +# Achievements + +The custom Achievement system tracks player progress against database-defined objectives and can render the results through text commands or the native Achievement window. + +## Server Flow + +1. `#ach` opens or refreshes the native achievement window. +2. Gameplay hooks call `AchievementManager` for level, zone visit, task completion, skill, and kill progress. +3. Matching objectives update `custom_character_achievement_progress`. +4. When all required objectives are complete, the character gets a row in `custom_character_achievements`. +5. The server sends `ACH|...` lines to the native client runtime for window refreshes. + +## Database + +This branch uses `common/database/database_update_manifest_custom.h` as the database source of truth. The standalone branch renumbers the achievements migrations to custom versions `1-3`, and `common/version.h` sets `CUSTOM_BINARY_DATABASE_VERSION` to `3`. + +## Commands + +- `#ach` +- `#ach window` +- `#ach status` +- `#ach categories` +- `#ach category [category_id]` +- `#ach detail [achievement_id]` +- `#ach check` + +## Client Assets + +Deploy `client_files/native_autoloot/ui/EQUI_NativeAchievementWnd.xml` to the target client UI folder and include it from `EQUI.xml`. + +The XML is standalone, but the current native DLL code that listens for `ACH|...` is still shared with the lab native-client runtime. diff --git a/features/README.md b/features/README.md index 558317fd6c..1db81280a7 100644 --- a/features/README.md +++ b/features/README.md @@ -18,6 +18,7 @@ These are not runtime plugins. Each feature pack documents the source files, dat | `autoloot` | `draft`, `shared-runtime`, `proved-build` | Server-side AutoLoot with the native EQ AutoLoot window. Client DLL code is still partly bundled with other native windows. | | `live-items` | `draft`, `shared-runtime`, `proved-build` | Live DB item loading, dynamic item data, item editing, and Item Forge input. Native DLL code is still shared runtime. | | `live-spells` | `draft`, `shared-runtime`, `proved-build` | Generated spell definitions, Spell Forge input, live spell patch/sync transport, and generated scroll items. Native DLL code is still shared runtime. | +| `achievements` | `draft`, `shared-runtime`, `proved-build` | Custom achievement schema, native achievement window, player commands, and gameplay progress hooks. Native DLL code is still shared runtime. | ## Packaging Rules diff --git a/features/achievements/MANIFEST.md b/features/achievements/MANIFEST.md new file mode 100644 index 0000000000..e43056214f --- /dev/null +++ b/features/achievements/MANIFEST.md @@ -0,0 +1,62 @@ +# Achievements Manifest + +This manifest lists the files and hook points that make up the standalone Achievements feature. + +## Added Server Files + +- `zone/achievement_manager.cpp` +- `zone/achievement_manager.h` +- `zone/gm_commands/achievements.cpp` +- `docs/achievements.md` + +## Existing Server Files To Patch + +| File | Purpose | +| --- | --- | +| `common/database/database_update_manifest_custom.h` | Add achievements-only custom DB migrations and seed data. | +| `common/version.h` | Set `CUSTOM_BINARY_DATABASE_VERSION` to `3`. | +| `zone/CMakeLists.txt` | Build achievement manager and command source. | +| `zone/command.cpp` | Register achievement command aliases. | +| `zone/command.h` | Declare the achievement command handler. | +| `zone/attack.cpp` | Update kill-based objectives for solo, group, and raid kills. | +| `zone/client.cpp` | Update skill objectives when a skill is set. | +| `zone/client_packet.cpp` | Update login-level and zone-visit objectives. | +| `zone/exp.cpp` | Update level objectives after level changes. | +| `zone/task_client_state.cpp` | Update task-completion objectives. | + +## Database Objects + +The custom migration manifest creates and seeds: + +- `custom_achievement_categories` +- `custom_achievements` +- `custom_achievement_objectives` +- `custom_character_achievement_progress` +- `custom_character_achievements` +- `custom_achievement_audit` + +## Native Client Assets + +| File | Purpose | +| --- | --- | +| `client_files/native_autoloot/ui/EQUI_NativeAchievementWnd.xml` | Native SIDL window layout for Achievement browsing. | +| `client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h` | Not included in this proof branch. The current implementation is still shared runtime code and needs a `native-client-base` split. | + +## Commands + +- `#ach` +- `#ach window` +- `#ach status` +- `#ach categories` +- `#ach category [category_id]` +- `#ach detail [achievement_id]` +- `#ach check` + +## Native Transport + +- `ACH|window|...` +- `ACH|category|...` +- `ACH|achievement|...` +- `ACH|objective|...` + +The server owns progress, completion, and validation. The native window is only a display/input surface. diff --git a/features/achievements/README.md b/features/achievements/README.md new file mode 100644 index 0000000000..c7ff80d23f --- /dev/null +++ b/features/achievements/README.md @@ -0,0 +1,47 @@ +# Achievements Feature Pack + +Status: `draft`, `shared-runtime`, `proved-build` + +This pack describes the custom Achievement system: database-backed achievement categories/objectives/progress, player-facing commands, gameplay progress hooks, and the native Achievement window transport. + +## What This Feature Owns + +- Custom achievement database schema and seed catalog. +- Character achievement progress and completion tracking. +- Level, zone visit, task completion, skill, and kill objective processing. +- `#ach`, `#achievement`, and `#achievements` command aliases. +- Native Achievement window transport using `ACH|...` lines. + +## What This Feature Does Not Require + +- AutoLoot. +- Live Items or Item Forge. +- Live Spells or Spell Forge. +- MacroQuest, Lua, ImGui, or overlay UI code. + +## Dependencies + +- EQEmu source rebuild. +- Custom database migrations in `common/database/database_update_manifest_custom.h`. +- `CUSTOM_BINARY_DATABASE_VERSION 3` in `common/version.h`. +- The native client DLL host if the operator wants the in-client Achievement window. + +## Install Outline + +1. Apply the source files and hook patches listed in `MANIFEST.md`. +2. Copy the custom migration entries or run the branch's `database_update` flow. +3. Rebuild `zone` and `world`. +4. Deploy `EQUI_NativeAchievementWnd.xml` and include it from the target client's `EQUI.xml`. +5. Log in and run `#ach window` or `#ach status`. + +## Smoke Test + +1. Run `#ach status` on a character. +2. Run `#ach categories` and `#ach category 1`. +3. Zone once and confirm zone visit objectives can update. +4. Complete a task or use a known seeded objective trigger. +5. Open `#ach window` and confirm the native client receives `ACH|...` lines. + +## Current Shared-Runtime Caveat + +This branch includes the native Achievement XML only. The C++ DLL implementation that listens for `ACH|...` is still in the lab branch's shared native-client runtime header and should be split into `native-client-base` plus feature-specific native window code. diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 9598eb3164..cded034657 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -7,6 +7,7 @@ set(zone_sources aggromanager.cpp api_service.cpp attack.cpp + achievement_manager.cpp autoloot_manager.cpp aura.cpp beacon.cpp @@ -122,6 +123,7 @@ set(zone_headers aa_ability.h aggromanager.h api_service.h + achievement_manager.h aura.h autoloot_manager.h beacon.h @@ -372,6 +374,7 @@ set(gm_command_sources bot_commands/bot_view_combos.cpp command.cpp gm_commands/acceptrules.cpp + gm_commands/achievements.cpp gm_commands/advnpcspawn.cpp gm_commands/aggrozone.cpp gm_commands/ai.cpp diff --git a/zone/achievement_manager.cpp b/zone/achievement_manager.cpp new file mode 100644 index 0000000000..e7f5bc9831 --- /dev/null +++ b/zone/achievement_manager.cpp @@ -0,0 +1,987 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. +*/ +#include "achievement_manager.h" + +#include "common/seperator.h" +#include "common/skills.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/npc.h" +#include "zone/zone.h" +#include "zone/zonedb.h" + +#include "fmt/format.h" + +#include + +AchievementManager achievement_manager; + +namespace { + uint32 ToUInt(const char *value) + { + return value ? Strings::ToUnsignedInt(value) : 0; + } + + std::string ObjectiveDisplayName(const std::string &type, const std::string &target_name, uint32 required_count) + { + if (!target_name.empty()) { + return target_name; + } + + if (Strings::EqualFold(type, "level")) { + return fmt::format("Reach level {}", required_count); + } + + return type; + } + + std::string ProtocolValue(std::string value, size_t maximum_length = 0) + { + for (auto &c : value) { + if (c == '|' || c == '\r' || c == '\n' || c == '\t') { + c = ' '; + } + } + + if (maximum_length && value.size() > maximum_length) { + if (maximum_length > 3) { + value.resize(maximum_length - 3); + value.append("..."); + } + else { + value.resize(maximum_length); + } + } + + return value; + } +} + +void AchievementManager::HandleCommand(Client *client, const Seperator *sep) +{ + if (!client || !sep) { + return; + } + + if (sep->argnum < 1) { + SendNativeWindow(client); + return; + } + + if (!strcasecmp(sep->arg[1], "help")) { + SendHelp(client); + return; + } + + if ( + !strcasecmp(sep->arg[1], "window") || + !strcasecmp(sep->arg[1], "ui") || + !strcasecmp(sep->arg[1], "open") || + !strcasecmp(sep->arg[1], "panel") + ) { + SendNativeWindow(client); + return; + } + + if (!strcasecmp(sep->arg[1], "native")) { + auto number_arg = [sep](int argument_index) -> uint32 { + return sep->argnum >= argument_index && sep->IsNumber(argument_index) ? + Strings::ToUnsignedInt(sep->arg[argument_index]) : + 0; + }; + + if (sep->argnum < 2) { + SendNativeWindow(client); + return; + } + + if ( + !strcasecmp(sep->arg[2], "show") || + !strcasecmp(sep->arg[2], "open") || + !strcasecmp(sep->arg[2], "window") || + !strcasecmp(sep->arg[2], "status") || + !strcasecmp(sep->arg[2], "snapshot") || + !strcasecmp(sep->arg[2], "refresh") + ) { + SendNativeWindow(client, number_arg(3), number_arg(4)); + return; + } + + if (!strcasecmp(sep->arg[2], "category")) { + if (sep->argnum < 3 || !sep->IsNumber(3)) { + client->Message(Chat::White, "Usage: #ach native category [category_id]"); + return; + } + + SendNativeCategory(client, Strings::ToUnsignedInt(sep->arg[3]), number_arg(4)); + return; + } + + if (!strcasecmp(sep->arg[2], "detail")) { + if (sep->argnum < 3 || !sep->IsNumber(3)) { + client->Message(Chat::White, "Usage: #ach native detail [achievement_id]"); + return; + } + + client->Message(Chat::White, "ACH|objectives|clear"); + SendNativeDetail(client, Strings::ToUnsignedInt(sep->arg[3])); + client->Message(Chat::White, "ACH|window|show"); + return; + } + + if (!strcasecmp(sep->arg[2], "check")) { + RecheckAutomatic(client); + SendNativeWindow(client, number_arg(3), number_arg(4)); + return; + } + + client->Message(Chat::White, "Usage: #ach native [show|refresh|category|detail|check]"); + return; + } + + if (!strcasecmp(sep->arg[1], "status")) { + SendStatus(client); + return; + } + + if (!strcasecmp(sep->arg[1], "categories") || !strcasecmp(sep->arg[1], "list")) { + SendCategories(client); + return; + } + + if (!strcasecmp(sep->arg[1], "category")) { + if (sep->argnum < 2 || !sep->IsNumber(2)) { + client->Message(Chat::White, "Usage: #ach category [category_id]"); + return; + } + + SendCategory(client, Strings::ToUnsignedInt(sep->arg[2])); + return; + } + + if (!strcasecmp(sep->arg[1], "detail")) { + if (sep->argnum < 2 || !sep->IsNumber(2)) { + client->Message(Chat::White, "Usage: #ach detail [achievement_id]"); + return; + } + + SendDetail(client, Strings::ToUnsignedInt(sep->arg[2])); + return; + } + + if (!strcasecmp(sep->arg[1], "check")) { + RecheckAutomatic(client); + SendStatus(client); + return; + } + + SendHelp(client); +} + +void AchievementManager::ProcessLevel(Client *client) +{ + if (!client) { + return; + } + + const uint32 character_id = client->CharacterID(); + const uint32 level = client->GetLevel(); + + auto results = database.QueryDatabase( + fmt::format( + "SELECT `id`, `achievement_id`, `required_count` " + "FROM `custom_achievement_objectives` " + "WHERE `objective_type` = 'level' AND `required_count` <= {}", + level + ) + ); + + if (!results.Success()) { + return; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + const uint32 objective_id = ToUInt(row[0]); + const uint32 achievement_id = ToUInt(row[1]); + const uint32 required_count = ToUInt(row[2]); + + UpdateObjectiveProgress(character_id, objective_id, level, level >= required_count); + TryCompleteAchievement(client, achievement_id); + } +} + +void AchievementManager::ProcessZoneVisit(Client *client) +{ + if (!client || !zone) { + return; + } + + ProcessMatchedObjectives( + client, + fmt::format( + "o.`objective_type` = 'zone_visit' AND o.`zone_id` = {}", + zone->GetZoneID() + ), + 1, + true + ); +} + +void AchievementManager::ProcessTaskComplete(Client *client, uint32 task_id) +{ + if (!client || !task_id) { + return; + } + + ProcessMatchedObjectives( + client, + fmt::format( + "o.`objective_type` = 'task_complete' AND o.`target_id` = {}", + task_id + ), + 1, + true + ); +} + +void AchievementManager::ProcessSkill(Client *client, uint32 skill_id, uint32 value) +{ + if (!client) { + return; + } + + ProcessMatchedObjectives( + client, + fmt::format( + "o.`objective_type` = 'skill' AND o.`target_id` = {}", + skill_id + ), + value, + true + ); +} + +void AchievementManager::ProcessKill(Client *client, NPC *npc) +{ + if (!client || !npc || !zone) { + return; + } + + const std::string clean_name = Strings::Escape(Strings::ToLower(npc->GetCleanName())); + ProcessMatchedObjectives( + client, + fmt::format( + "(" + "(o.`objective_type` = 'npc_kill' AND o.`target_id` = {}) OR " + "(o.`objective_type` = 'npc_name_kill' AND o.`zone_id` = {} AND LOWER(o.`target_name`) = '{}') OR " + "(o.`objective_type` = 'zone_kill' AND o.`zone_id` = {}) OR " + "(o.`objective_type` = 'race_kill' AND o.`target_id` = {}) OR " + "(o.`objective_type` = 'bodytype_kill' AND o.`target_id` = {})" + ")", + npc->GetNPCTypeID(), + zone->GetZoneID(), + clean_name, + zone->GetZoneID(), + npc->GetRace(), + npc->GetBodyType() + ), + 1, + false + ); +} + +void AchievementManager::SendHelp(Client *client) +{ + client->Message(Chat::White, "Achievement commands:"); + client->Message(Chat::White, "#ach - Open the native achievement window."); + client->Message(Chat::White, "#ach window - Reopen the native achievement window."); + client->Message(Chat::White, "#ach status - Show your achievement totals."); + client->Message(Chat::White, "#ach categories - List achievement categories."); + client->Message(Chat::White, "#ach category [id] - List achievements in a category."); + client->Message(Chat::White, "#ach detail [id] - Show achievement objectives."); + client->Message(Chat::White, "#ach check - Recheck automatic achievements for your character."); +} + +void AchievementManager::RecheckAutomatic(Client *client) +{ + if (!client) { + return; + } + + ProcessLevel(client); + ProcessZoneVisit(client); + for (int skill_id = 0; skill_id <= EQ::skills::HIGHEST_SKILL; ++skill_id) { + ProcessSkill(client, skill_id, client->GetRawSkill(static_cast(skill_id))); + } +} + +void AchievementManager::SendStatus(Client *client) +{ + const uint32 character_id = client->CharacterID(); + + auto results = database.QueryDatabase( + fmt::format( + "SELECT " + "(SELECT COUNT(*) FROM `custom_achievements` WHERE `enabled` = 1 AND `hidden` = 0), " + "(SELECT COUNT(*) FROM `custom_character_achievements` ca " + "JOIN `custom_achievements` a ON a.`id` = ca.`achievement_id` " + "WHERE ca.`character_id` = {} AND a.`enabled` = 1), " + "(SELECT COALESCE(SUM(a.`points`), 0) FROM `custom_character_achievements` ca " + "JOIN `custom_achievements` a ON a.`id` = ca.`achievement_id` " + "WHERE ca.`character_id` = {} AND a.`enabled` = 1), " + "(SELECT COUNT(*) FROM `custom_achievement_categories` WHERE `enabled` = 1)", + character_id, + character_id + ) + ); + + if (!results.Success() || !results.RowCount()) { + client->Message(Chat::White, "Achievements are not available. Check the custom achievement tables."); + return; + } + + auto row = results.begin(); + client->Message( + Chat::White, + fmt::format( + "Achievements: {} / {} complete, {} points, {} categories.", + ToUInt(row[1]), + ToUInt(row[0]), + ToUInt(row[2]), + ToUInt(row[3]) + ).c_str() + ); +} + +void AchievementManager::SendCategories(Client *client) +{ + const auto categories = LoadCategorySummaries(client->CharacterID()); + if (categories.empty()) { + client->Message(Chat::White, "No achievement categories are available."); + return; + } + + client->Message(Chat::White, "Achievement Categories:"); + for (const auto &category : categories) { + client->Message( + Chat::White, + fmt::format( + "[{}] {} - {} / {} complete, {} points", + category.id, + category.name, + category.completed, + category.total, + category.points + ).c_str() + ); + } +} + +void AchievementManager::SendCategory(Client *client, uint32 category_id) +{ + const auto achievements = LoadAchievements(client->CharacterID(), category_id); + if (achievements.empty()) { + client->Message(Chat::White, fmt::format("No achievements found in category {}.", category_id).c_str()); + return; + } + + client->Message(Chat::White, fmt::format("Achievements in category {}:", category_id).c_str()); + for (const auto &achievement : achievements) { + client->Message( + Chat::White, + fmt::format( + "[{}] [{}] {} ({} pts) - {}", + achievement.id, + achievement.completed ? "Complete" : "Open", + achievement.name, + achievement.points, + achievement.description + ).c_str() + ); + } +} + +void AchievementManager::SendDetail(Client *client, uint32 achievement_id) +{ + const uint32 character_id = client->CharacterID(); + + auto achievement_results = database.QueryDatabase( + fmt::format( + "SELECT a.`name`, a.`description`, a.`points`, COALESCE(ca.`completed_at`, 0) " + "FROM `custom_achievements` a " + "LEFT JOIN `custom_character_achievements` ca " + "ON ca.`achievement_id` = a.`id` AND ca.`character_id` = {} " + "WHERE a.`id` = {} AND a.`enabled` = 1 LIMIT 1", + character_id, + achievement_id + ) + ); + + if (!achievement_results.Success() || !achievement_results.RowCount()) { + client->Message(Chat::White, fmt::format("Achievement {} was not found.", achievement_id).c_str()); + return; + } + + auto achievement = achievement_results.begin(); + client->Message( + Chat::White, + fmt::format( + "[{}] {} ({} pts) - {}", + achievement_id, + achievement[0] ? achievement[0] : "", + ToUInt(achievement[2]), + achievement[1] ? achievement[1] : "" + ).c_str() + ); + + if (ToUInt(achievement[3])) { + client->Message(Chat::White, fmt::format("Completed at Unix time {}.", ToUInt(achievement[3])).c_str()); + } + + const auto objectives = LoadObjectives(character_id, achievement_id); + for (const auto &objective : objectives) { + client->Message( + Chat::White, + fmt::format( + " - [{}] {} ({}/{})", + objective.completed ? "Done" : "Open", + ObjectiveDisplayName(objective.type, objective.target_name, objective.required_count), + objective.current_count, + objective.required_count + ).c_str() + ); + } +} + +void AchievementManager::SendNativeWindow(Client *client, uint32 category_id, uint32 achievement_id) +{ + if (!client) { + return; + } + + const uint32 character_id = client->CharacterID(); + uint32 total = 0; + uint32 completed = 0; + uint32 points = 0; + uint32 category_count = 0; + + auto status_results = database.QueryDatabase( + fmt::format( + "SELECT " + "(SELECT COUNT(*) FROM `custom_achievements` WHERE `enabled` = 1 AND `hidden` = 0), " + "(SELECT COUNT(*) FROM `custom_character_achievements` ca " + "JOIN `custom_achievements` a ON a.`id` = ca.`achievement_id` " + "WHERE ca.`character_id` = {} AND a.`enabled` = 1), " + "(SELECT COALESCE(SUM(a.`points`), 0) FROM `custom_character_achievements` ca " + "JOIN `custom_achievements` a ON a.`id` = ca.`achievement_id` " + "WHERE ca.`character_id` = {} AND a.`enabled` = 1), " + "(SELECT COUNT(*) FROM `custom_achievement_categories` WHERE `enabled` = 1)", + character_id, + character_id + ) + ); + + if (status_results.Success() && status_results.RowCount()) { + auto row = status_results.begin(); + total = ToUInt(row[0]); + completed = ToUInt(row[1]); + points = ToUInt(row[2]); + category_count = ToUInt(row[3]); + } + + if (achievement_id && !category_id) { + category_id = LoadAchievementCategory(achievement_id); + } + + auto categories = LoadCategorySummaries(character_id); + uint32 selected_category_id = 0; + for (const auto &category : categories) { + if (category.id == category_id) { + selected_category_id = category.id; + break; + } + } + + if (!selected_category_id) { + for (const auto &category : categories) { + if (category.total > 0) { + selected_category_id = category.id; + break; + } + } + } + + if (!selected_category_id && !categories.empty()) { + selected_category_id = categories.front().id; + } + + auto achievements = selected_category_id ? LoadAchievements(character_id, selected_category_id) : std::vector(); + uint32 selected_achievement_id = 0; + if (achievement_id) { + for (const auto &achievement : achievements) { + if (achievement.id == achievement_id) { + selected_achievement_id = achievement.id; + break; + } + } + } + + if (!selected_achievement_id && !achievements.empty()) { + selected_achievement_id = achievements.front().id; + } + + client->Message(Chat::White, "ACH|window|clear"); + client->Message( + Chat::White, + fmt::format( + "ACH|status|completed={}|total={}|points={}|categories={}", + completed, + total, + points, + category_count + ).c_str() + ); + + for (const auto &category : categories) { + client->Message( + Chat::White, + fmt::format( + "ACH|category|id={}|parent={}|name={}|completed={}|total={}|points={}", + category.id, + category.parent_id, + ProtocolValue(category.name, 80), + category.completed, + category.total, + category.points + ).c_str() + ); + } + + client->Message( + Chat::White, + fmt::format( + "ACH|selection|category={}|achievement={}", + selected_category_id, + selected_achievement_id + ).c_str() + ); + + for (const auto &achievement : achievements) { + client->Message( + Chat::White, + fmt::format( + "ACH|achievement|id={}|category={}|completed={}|points={}|name={}|description={}", + achievement.id, + achievement.category_id, + achievement.completed ? 1 : 0, + achievement.points, + ProtocolValue(achievement.name, 96), + ProtocolValue(achievement.description, 160) + ).c_str() + ); + } + + if (selected_achievement_id) { + SendNativeDetail(client, selected_achievement_id); + } + else { + client->Message(Chat::White, "ACH|detail|id=0|completed=0|points=0|name=No achievements|description=No achievements are available for this category."); + } + + client->Message(Chat::White, "ACH|window|show"); +} + +void AchievementManager::SendNativeCategory(Client *client, uint32 category_id, uint32 achievement_id) +{ + if (!client) { + return; + } + + const uint32 character_id = client->CharacterID(); + const auto achievements = category_id ? LoadAchievements(character_id, category_id) : std::vector(); + uint32 selected_achievement_id = 0; + if (achievement_id) { + for (const auto &achievement : achievements) { + if (achievement.id == achievement_id) { + selected_achievement_id = achievement.id; + break; + } + } + } + + if (!selected_achievement_id && !achievements.empty()) { + selected_achievement_id = achievements.front().id; + } + + client->Message(Chat::White, "ACH|achievements|clear"); + client->Message( + Chat::White, + fmt::format( + "ACH|selection|category={}|achievement={}", + category_id, + selected_achievement_id + ).c_str() + ); + + for (const auto &achievement : achievements) { + client->Message( + Chat::White, + fmt::format( + "ACH|achievement|id={}|category={}|completed={}|points={}|name={}|description={}", + achievement.id, + achievement.category_id, + achievement.completed ? 1 : 0, + achievement.points, + ProtocolValue(achievement.name, 96), + ProtocolValue(achievement.description, 160) + ).c_str() + ); + } + + if (selected_achievement_id) { + SendNativeDetail(client, selected_achievement_id); + } + else { + client->Message(Chat::White, "ACH|detail|id=0|completed=0|points=0|name=No achievements|description=No achievements are available for this category."); + } + + client->Message(Chat::White, "ACH|window|show"); +} + +void AchievementManager::SendNativeDetail(Client *client, uint32 achievement_id) +{ + if (!client) { + return; + } + + const uint32 character_id = client->CharacterID(); + auto achievement_results = database.QueryDatabase( + fmt::format( + "SELECT a.`name`, a.`description`, a.`points`, COALESCE(ca.`completed_at`, 0) " + "FROM `custom_achievements` a " + "LEFT JOIN `custom_character_achievements` ca " + "ON ca.`achievement_id` = a.`id` AND ca.`character_id` = {} " + "WHERE a.`id` = {} AND a.`enabled` = 1 LIMIT 1", + character_id, + achievement_id + ) + ); + + if (!achievement_results.Success() || !achievement_results.RowCount()) { + client->Message( + Chat::White, + fmt::format( + "ACH|detail|id={}|completed=0|points=0|name=Achievement unavailable|description=Achievement {} was not found.", + achievement_id, + achievement_id + ).c_str() + ); + return; + } + + auto achievement = achievement_results.begin(); + const uint32 completed_at = ToUInt(achievement[3]); + client->Message( + Chat::White, + fmt::format( + "ACH|detail|id={}|completed={}|completed_at={}|points={}|name={}|description={}", + achievement_id, + completed_at ? 1 : 0, + completed_at, + ToUInt(achievement[2]), + ProtocolValue(achievement[0] ? achievement[0] : "", 96), + ProtocolValue(achievement[1] ? achievement[1] : "", 260) + ).c_str() + ); + + const auto objectives = LoadObjectives(character_id, achievement_id); + for (const auto &objective : objectives) { + client->Message( + Chat::White, + fmt::format( + "ACH|objective|id={}|completed={}|current={}|required={}|name={}", + objective.id, + objective.completed ? 1 : 0, + objective.current_count, + objective.required_count, + ProtocolValue(ObjectiveDisplayName(objective.type, objective.target_name, objective.required_count), 120) + ).c_str() + ); + } +} + +std::vector AchievementManager::LoadCategorySummaries(uint32 character_id) +{ + std::vector categories; + + auto results = database.QueryDatabase( + fmt::format( + "SELECT c.`id`, c.`parent_id`, c.`name`, " + "COUNT(a.`id`) AS total_count, " + "COALESCE(SUM(CASE WHEN ca.`achievement_id` IS NULL THEN 0 ELSE 1 END), 0) AS completed_count, " + "COALESCE(SUM(CASE WHEN ca.`achievement_id` IS NULL THEN 0 ELSE a.`points` END), 0) AS points " + "FROM `custom_achievement_categories` c " + "LEFT JOIN `custom_achievements` a ON a.`category_id` = c.`id` AND a.`enabled` = 1 AND a.`hidden` = 0 " + "LEFT JOIN `custom_character_achievements` ca ON ca.`achievement_id` = a.`id` AND ca.`character_id` = {} " + "WHERE c.`enabled` = 1 " + "GROUP BY c.`id`, c.`parent_id`, c.`name`, c.`sort_order` " + "ORDER BY c.`sort_order`, c.`id`", + character_id + ) + ); + + if (!results.Success()) { + return categories; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + CategorySummary summary; + summary.id = ToUInt(row[0]); + summary.parent_id = ToUInt(row[1]); + summary.name = row[2] ? row[2] : ""; + summary.total = ToUInt(row[3]); + summary.completed = ToUInt(row[4]); + summary.points = ToUInt(row[5]); + categories.push_back(summary); + } + + return categories; +} + +std::vector AchievementManager::LoadAchievements(uint32 character_id, uint32 category_id) +{ + std::vector achievements; + + auto results = database.QueryDatabase( + fmt::format( + "SELECT a.`id`, a.`category_id`, a.`name`, a.`description`, a.`points`, COALESCE(ca.`completed_at`, 0) " + "FROM `custom_achievements` a " + "LEFT JOIN `custom_character_achievements` ca " + "ON ca.`achievement_id` = a.`id` AND ca.`character_id` = {} " + "WHERE a.`enabled` = 1 AND a.`hidden` = 0 AND a.`category_id` = {} " + "ORDER BY a.`sort_order`, a.`id`", + character_id, + category_id + ) + ); + + if (!results.Success()) { + return achievements; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + AchievementSummary summary; + summary.id = ToUInt(row[0]); + summary.category_id = ToUInt(row[1]); + summary.name = row[2] ? row[2] : ""; + summary.description = row[3] ? row[3] : ""; + summary.points = ToUInt(row[4]); + summary.completed_at = ToUInt(row[5]); + summary.completed = summary.completed_at != 0; + achievements.push_back(summary); + } + + return achievements; +} + +std::vector AchievementManager::LoadObjectives(uint32 character_id, uint32 achievement_id) +{ + std::vector objectives; + + auto results = database.QueryDatabase( + fmt::format( + "SELECT o.`id`, o.`objective_type`, o.`target_name`, o.`required_count`, " + "COALESCE(p.`count`, 0), COALESCE(p.`completed_at`, 0) " + "FROM `custom_achievement_objectives` o " + "LEFT JOIN `custom_character_achievement_progress` p " + "ON p.`objective_id` = o.`id` AND p.`character_id` = {} " + "WHERE o.`achievement_id` = {} " + "ORDER BY o.`objective_index`, o.`id`", + character_id, + achievement_id + ) + ); + + if (!results.Success()) { + return objectives; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + ObjectiveSummary summary; + summary.id = ToUInt(row[0]); + summary.type = row[1] ? row[1] : ""; + summary.target_name = row[2] ? row[2] : ""; + summary.required_count = ToUInt(row[3]); + summary.current_count = ToUInt(row[4]); + summary.completed = ToUInt(row[5]) != 0; + objectives.push_back(summary); + } + + return objectives; +} + +uint32 AchievementManager::LoadAchievementCategory(uint32 achievement_id) +{ + if (!achievement_id) { + return 0; + } + + auto results = database.QueryDatabase( + fmt::format( + "SELECT `category_id` FROM `custom_achievements` " + "WHERE `id` = {} AND `enabled` = 1 LIMIT 1", + achievement_id + ) + ); + + if (!results.Success() || !results.RowCount()) { + return 0; + } + + auto row = results.begin(); + return ToUInt(row[0]); +} + +void AchievementManager::ProcessMatchedObjectives(Client *client, const std::string &match_sql, uint32 progress, bool absolute_progress) +{ + if (!client || match_sql.empty()) { + return; + } + + const uint32 character_id = client->CharacterID(); + auto results = database.QueryDatabase( + fmt::format( + "SELECT o.`id`, o.`achievement_id`, o.`required_count`, " + "COALESCE(p.`count`, 0), COALESCE(p.`completed_at`, 0) " + "FROM `custom_achievement_objectives` o " + "JOIN `custom_achievements` a ON a.`id` = o.`achievement_id` AND a.`enabled` = 1 " + "LEFT JOIN `custom_character_achievement_progress` p " + "ON p.`objective_id` = o.`id` AND p.`character_id` = {} " + "WHERE {}", + character_id, + match_sql + ) + ); + + if (!results.Success()) { + return; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + const uint32 objective_id = ToUInt(row[0]); + const uint32 achievement_id = ToUInt(row[1]); + const uint32 required_count = ToUInt(row[2]); + const uint32 current_count = ToUInt(row[3]); + const bool already_completed = ToUInt(row[4]) != 0; + const uint32 new_count = absolute_progress ? progress : current_count + progress; + + if (!already_completed || new_count > current_count) { + UpdateObjectiveProgress(character_id, objective_id, new_count, new_count >= required_count); + } + + TryCompleteAchievement(client, achievement_id); + } +} + +void AchievementManager::UpdateObjectiveProgress(uint32 character_id, uint32 objective_id, uint32 count, bool completed) +{ + database.QueryDatabase( + fmt::format( + "INSERT INTO `custom_character_achievement_progress` " + "(`character_id`, `objective_id`, `count`, `completed_at`, `updated_at`) " + "VALUES ({}, {}, {}, {}, UNIX_TIMESTAMP()) " + "ON DUPLICATE KEY UPDATE " + "`count` = GREATEST(`count`, VALUES(`count`)), " + "`completed_at` = IF(`completed_at` = 0 AND VALUES(`completed_at`) > 0, VALUES(`completed_at`), `completed_at`), " + "`updated_at` = VALUES(`updated_at`)", + character_id, + objective_id, + count, + completed ? "UNIX_TIMESTAMP()" : "0" + ) + ); +} + +void AchievementManager::TryCompleteAchievement(Client *client, uint32 achievement_id) +{ + const uint32 character_id = client->CharacterID(); + if (HasCompletedAchievement(character_id, achievement_id)) { + return; + } + + auto results = database.QueryDatabase( + fmt::format( + "SELECT " + "COUNT(*) AS required_count, " + "COALESCE(SUM(CASE WHEN p.`completed_at` > 0 THEN 1 ELSE 0 END), 0) AS completed_count " + "FROM `custom_achievement_objectives` o " + "LEFT JOIN `custom_character_achievement_progress` p " + "ON p.`objective_id` = o.`id` AND p.`character_id` = {} " + "WHERE o.`achievement_id` = {} AND o.`optional` = 0", + character_id, + achievement_id + ) + ); + + if (!results.Success() || !results.RowCount()) { + return; + } + + auto row = results.begin(); + const uint32 required_count = ToUInt(row[0]); + const uint32 completed_count = ToUInt(row[1]); + if (!required_count || completed_count < required_count) { + return; + } + + database.QueryDatabase( + fmt::format( + "INSERT INTO `custom_character_achievements` " + "(`character_id`, `achievement_id`, `completed_at`, `awarded_at`, `completion_count`, `announced`) " + "VALUES ({}, {}, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 1, 0)", + character_id, + achievement_id + ) + ); + + auto achievement = database.QueryDatabase( + fmt::format( + "SELECT `name`, `description`, `points` FROM `custom_achievements` WHERE `id` = {} LIMIT 1", + achievement_id + ) + ); + + if (achievement.Success() && achievement.RowCount()) { + auto achievement_row = achievement.begin(); + client->Message( + Chat::Yellow, + fmt::format( + "Achievement complete: {} ({} pts) - {}", + achievement_row[0] ? achievement_row[0] : "", + ToUInt(achievement_row[2]), + achievement_row[1] ? achievement_row[1] : "" + ).c_str() + ); + } +} + +bool AchievementManager::HasCompletedAchievement(uint32 character_id, uint32 achievement_id) +{ + auto results = database.QueryDatabase( + fmt::format( + "SELECT 1 FROM `custom_character_achievements` " + "WHERE `character_id` = {} AND `achievement_id` = {} LIMIT 1", + character_id, + achievement_id + ) + ); + + return results.Success() && results.RowCount() > 0; +} diff --git a/zone/achievement_manager.h b/zone/achievement_manager.h new file mode 100644 index 0000000000..14889fbb72 --- /dev/null +++ b/zone/achievement_manager.h @@ -0,0 +1,80 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. +*/ +#pragma once + +#include "common/types.h" + +#include +#include + +class Client; +class NPC; +class Seperator; + +class AchievementManager { +public: + void HandleCommand(Client *client, const Seperator *sep); + void ProcessLevel(Client *client); + void ProcessZoneVisit(Client *client); + void ProcessTaskComplete(Client *client, uint32 task_id); + void ProcessSkill(Client *client, uint32 skill_id, uint32 value); + void ProcessKill(Client *client, NPC *npc); + +private: + struct CategorySummary { + uint32 id = 0; + uint32 parent_id = 0; + std::string name; + uint32 total = 0; + uint32 completed = 0; + uint32 points = 0; + }; + + struct AchievementSummary { + uint32 id = 0; + uint32 category_id = 0; + std::string name; + std::string description; + uint32 points = 0; + bool completed = false; + uint32 completed_at = 0; + }; + + struct ObjectiveSummary { + uint32 id = 0; + std::string type; + std::string target_name; + uint32 required_count = 0; + uint32 current_count = 0; + bool completed = false; + }; + + void SendHelp(Client *client); + void SendStatus(Client *client); + void SendCategories(Client *client); + void SendCategory(Client *client, uint32 category_id); + void SendDetail(Client *client, uint32 achievement_id); + void SendNativeWindow(Client *client, uint32 category_id = 0, uint32 achievement_id = 0); + void SendNativeCategory(Client *client, uint32 category_id, uint32 achievement_id = 0); + void SendNativeDetail(Client *client, uint32 achievement_id); + void RecheckAutomatic(Client *client); + + std::vector LoadCategorySummaries(uint32 character_id); + std::vector LoadAchievements(uint32 character_id, uint32 category_id); + std::vector LoadObjectives(uint32 character_id, uint32 achievement_id); + uint32 LoadAchievementCategory(uint32 achievement_id); + + void ProcessMatchedObjectives(Client *client, const std::string &match_sql, uint32 progress, bool absolute_progress); + void UpdateObjectiveProgress(uint32 character_id, uint32 objective_id, uint32 count, bool completed); + void TryCompleteAchievement(Client *client, uint32 achievement_id); + bool HasCompletedAchievement(uint32 character_id, uint32 achievement_id); +}; + +extern AchievementManager achievement_manager; diff --git a/zone/attack.cpp b/zone/attack.cpp index 059499cd3a..b6e6148ba5 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -23,6 +23,7 @@ #include "common/rulesys.h" #include "common/spdat.h" #include "common/strings.h" +#include "zone/achievement_manager.h" #include "zone/autoloot_manager.h" #include "zone/bot.h" #include "zone/fastmath.h" @@ -2709,6 +2710,10 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy ); } + if (!is_ldon_treasure && MerchantType == 0) { + achievement_manager.ProcessKill(m.member, this); + } + player_count++; } } @@ -2742,6 +2747,10 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy ); } + if (!is_ldon_treasure && MerchantType == 0) { + achievement_manager.ProcessKill(c, this); + } + player_count++; } } @@ -2775,6 +2784,10 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy give_exp_client->GetDeity() ); } + + if (!is_ldon_treasure && MerchantType == 0) { + achievement_manager.ProcessKill(give_exp_client, this); + } } } diff --git a/zone/client.cpp b/zone/client.cpp index bafa472a8f..ddd29c6da9 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -61,6 +61,7 @@ #include "zone/water_map.h" #include "zone/worldserver.h" #include "zone/zonedb.h" +#include "zone/achievement_manager.h" #include #include @@ -2052,6 +2053,8 @@ void Client::SetSkill(EQ::skills::SkillType skillid, uint16 value) { skill->value=value; QueuePacket(outapp); safe_delete(outapp); + + achievement_manager.ProcessSkill(this, skillid, value); } void Client::IncreaseLanguageSkill(uint8 language_id, uint8 increase) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f4266afb43..c8627f0bd4 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -36,6 +36,7 @@ #include "common/repositories/tradeskill_recipe_entries_repository.h" #include "common/rulesys.h" #include "common/shared_tasks.h" +#include "zone/achievement_manager.h" #include "zone/bot.h" #include "zone/dialogue_window.h" #include "zone/dynamic_zone.h" @@ -535,6 +536,8 @@ void Client::CompleteConnect() // Task Packets LoadClientTaskState(); + achievement_manager.ProcessLevel(this); + achievement_manager.ProcessZoneVisit(this); // moved to dbload and translators since we iterate there also .. keep m_pp values whatever they are when they get here /*const auto sbs = EQ::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize; diff --git a/zone/command.cpp b/zone/command.cpp index 437416ccda..6a76dfc77c 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -96,6 +96,11 @@ int command_init(void) if ( command_add("acceptrules", "[acceptrules] - Accept the EQEmu Agreement", AccountStatus::Player, command_acceptrules) || + command_add("ach", "[window|status|categories|category|detail|check] - View and update custom achievements", AccountStatus::Player, command_ach) || + command_add("achievement", "[window|status|categories|category|detail|check] - View and update custom achievements", AccountStatus::Player, command_ach) || + command_add("achievements", "[window|status|categories|category|detail|check] - View and update custom achievements", AccountStatus::Player, command_ach) || + command_add("achivement", "[window|status|categories|category|detail|check] - View and update custom achievements", AccountStatus::Player, command_ach) || + command_add("achivements", "[window|status|categories|category|detail|check] - View and update custom achievements", AccountStatus::Player, command_ach) || command_add("advnpcspawn", "[maketype|makegroup|addgroupentry|addgroupspawn][removegroupspawn|movespawn|editgroupbox|cleargroupbox]", AccountStatus::GMLeadAdmin, command_advnpcspawn) || command_add("aggrozone", "[aggro] - Aggro every mob in the zone with X aggro. Default is 0. Not recommend if you're not invulnerable.", AccountStatus::GMAdmin, command_aggrozone) || command_add("ai", "[factionid/spellslist/con/guard/roambox/stop/start] - Modify AI on NPC target", AccountStatus::GMAdmin, command_ai) || diff --git a/zone/command.h b/zone/command.h index bd1fa7a0a4..6b74f44454 100644 --- a/zone/command.h +++ b/zone/command.h @@ -59,6 +59,7 @@ void SendEvolvingItemsSubCommands(Client *c); // Commands void command_acceptrules(Client *c, const Seperator *sep); +void command_ach(Client *c, const Seperator *sep); void command_advnpcspawn(Client *c, const Seperator *sep); void command_aggrozone(Client *c, const Seperator *sep); void command_ai(Client *c, const Seperator *sep); diff --git a/zone/exp.cpp b/zone/exp.cpp index fd6a39dbf0..a9013b9879 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -28,6 +28,7 @@ #include "zone/mob.h" #include "zone/queryserv.h" #include "zone/quest_parser_collection.h" +#include "zone/achievement_manager.h" #include "zone/raids.h" #include "zone/string_ids.h" #include "zone/worldserver.h" @@ -994,6 +995,8 @@ void Client::SetLevel(uint8 set_level, bool command) UpdateMercLevel(); Save(); + + achievement_manager.ProcessLevel(this); } // Note: The client calculates exp separately, we cant change this function diff --git a/zone/gm_commands/achievements.cpp b/zone/gm_commands/achievements.cpp new file mode 100644 index 0000000000..3da0deda6c --- /dev/null +++ b/zone/gm_commands/achievements.cpp @@ -0,0 +1,16 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. +*/ +#include "zone/achievement_manager.h" +#include "zone/client.h" + +void command_ach(Client *c, const Seperator *sep) +{ + achievement_manager.HandleCommand(c, sep); +} diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp index a16f45b9a4..74daadf9f2 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -25,6 +25,7 @@ #include "common/repositories/completed_tasks_repository.h" #include "common/rulesys.h" #include "common/shared_tasks.h" +#include "zone/achievement_manager.h" #include "zone/client.h" #include "zone/dynamic_zone.h" #include "zone/queryserv.h" @@ -943,6 +944,8 @@ int ClientTaskState::IncrementDoneCount( RecordPlayerEventLogWithClient(client, PlayerEvent::TASK_COMPLETE, e); } + achievement_manager.ProcessTaskComplete(client, info->task_id); + client->SendTaskActivityComplete(info->task_id, 0, task_index, task_data->type, 0); // If Experience and/or cash rewards are set, reward them from the task even if reward_method is METHODQUEST From 905b2e8faa006014046410952e48c1a380a04c14 Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Sat, 23 May 2026 23:47:33 -0700 Subject: [PATCH 123/194] Document all-features bundle branch --- docs/features-all.md | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 docs/features-all.md diff --git a/docs/features-all.md b/docs/features-all.md new file mode 100644 index 0000000000..b6229d3443 --- /dev/null +++ b/docs/features-all.md @@ -0,0 +1,45 @@ +# All Features Bundle + +This branch combines the standalone feature branches on top of a clean EQEmu base: + +- AutoLoot +- Live Items / Item Forge +- Live Spells / Spell Forge +- Achievements + +## Branch Shape + +The bundle keeps the feature commits layered instead of using the dirty integration lab as source of truth. This gives operators one branch to grab when they want every system, while preserving the individual feature branches for piecemeal installs. + +## Database + +The combined custom database manifest uses: + +- Custom version `1`: AutoLoot schema. +- Custom version `2`: Achievement schema. +- Custom version `3`: Achievement catalog seed. +- Custom version `4`: Live hunter achievement seed. + +`common/version.h` sets `CUSTOM_BINARY_DATABASE_VERSION` to `4`. + +## Native Client Assets + +This bundle includes the feature-owned XML windows: + +- `EQUI_NativeAutoLootWnd.xml` +- `EQUI_NativeItemForgeWnd.xml` +- `EQUI_NativeSpellForgeWnd.xml` +- `EQUI_NativeAchievementWnd.xml` + +The C++ native DLL runtime is still shared lab code and should be split next into a reusable `native-client-base` plus feature-specific modules. Until that split lands, this branch is the clean server/source bundle plus native XML assets. + +## Verification + +Use: + +```powershell +cmake --preset win-msvc +cmake --build build\win-msvc --config Release --target zone -- /m +cmake --build build\win-msvc --config Release --target world -- /m +git diff --check +``` From 9d7f1df60e1c874f69f23bd6bd52dc68fdaf3b83 Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Sat, 23 May 2026 23:56:08 -0700 Subject: [PATCH 124/194] Add native client runtime package --- client_files/native_autoloot/README.md | 60 +- .../native_autoloot/eq-core-dll/.editorconfig | 59 + .../eq-core-dll/.gitattributes | 2 + .../native_autoloot/eq-core-dll/.gitignore | 42 + .../eq-core-dll/.vscode/settings.json | 7 + .../native_autoloot/eq-core-dll/Blech/Blech.h | 1345 +++ .../native_autoloot/eq-core-dll/README.md | 15 + .../eq-core-dll/bin/dinput8.dll | Bin 0 -> 1439744 bytes .../eq-core-dll/dependencies/.gitignore | 1 + .../dependencies/detours/inc/detours.h | 616 ++ .../dependencies/detours/lib/detours.lib | Bin 0 -> 178678 bytes .../dependencies/dx9/Include/d3d9.h | 2582 +++++ .../dependencies/dx9/Include/d3d9caps.h | 512 + .../dependencies/dx9/Include/d3d9types.h | 2012 ++++ .../dependencies/dx9/Include/d3dx9.h | 76 + .../dependencies/dx9/Include/d3dx9anim.h | 1114 ++ .../dependencies/dx9/Include/d3dx9core.h | 755 ++ .../dependencies/dx9/Include/d3dx9effect.h | 873 ++ .../dependencies/dx9/Include/d3dx9math.h | 1796 +++ .../dependencies/dx9/Include/d3dx9math.inl | 2251 ++++ .../dependencies/dx9/Include/d3dx9mesh.h | 3007 +++++ .../dependencies/dx9/Include/d3dx9shader.h | 1177 ++ .../dependencies/dx9/Include/d3dx9shape.h | 221 + .../dependencies/dx9/Include/d3dx9tex.h | 1735 +++ .../dependencies/dx9/Include/d3dx9xof.h | 299 + .../eq-core-dll/dependencies/dx9/Lib/d3d9.lib | Bin 0 -> 5210 bytes .../dependencies/dx9/Lib/d3dx9.lib | Bin 0 -> 89010 bytes .../eq-core-dll/dxsdk81/include/dinput.h | 4399 ++++++++ .../eq-core-dll/src/AddressLookupTable.h | 101 + .../eq-core-dll/src/DetoursAPI.cpp | 0 .../eq-core-dll/src/EQClasses.cpp | 9645 +++++++++++++++++ .../eq-core-dll/src/EQClasses.h | 6973 ++++++++++++ .../native_autoloot/eq-core-dll/src/EQData.h | 2209 ++++ .../eq-core-dll/src/EQDetours.h | 0 .../eq-core-dll/src/EQFunctionDetours.cpp | 1 + .../eq-core-dll/src/EQNetworkDetours.cpp | 15 + .../eq-core-dll/src/EQUIStructs.h | 946 ++ .../eq-core-dll/src/EQUtils.cpp | 15 + .../native_autoloot/eq-core-dll/src/EQUtils.h | 6 + .../eq-core-dll/src/FPSLimit.cpp | 0 .../eq-core-dll/src/IClassFactory.cpp | 80 + .../eq-core-dll/src/IClassFactory.h | 26 + .../eq-core-dll/src/IDirectInput8A.cpp | 111 + .../eq-core-dll/src/IDirectInput8A.h | 34 + .../eq-core-dll/src/IDirectInput8Hook.cpp | 76 + .../eq-core-dll/src/IDirectInput8Hook.h | 27 + .../eq-core-dll/src/IDirectInput8W.cpp | 111 + .../eq-core-dll/src/IDirectInput8W.h | 34 + .../eq-core-dll/src/IDirectInputDevice8A.cpp | 216 + .../eq-core-dll/src/IDirectInputDevice8A.h | 55 + .../src/IDirectInputDevice8Hook.cpp | 187 + .../eq-core-dll/src/IDirectInputDevice8Hook.h | 50 + .../eq-core-dll/src/IDirectInputDevice8W.cpp | 216 + .../eq-core-dll/src/IDirectInputDevice8W.h | 55 + .../eq-core-dll/src/IDirectInputEffect.cpp | 105 + .../eq-core-dll/src/IDirectInputEffect.h | 36 + .../src/IDirectInputEnumDevice.cpp | 41 + .../eq-core-dll/src/IDirectInputEnumDevice.h | 23 + .../src/IDirectInputEnumEffect.cpp | 29 + .../eq-core-dll/src/IDirectInputEnumEffect.h | 16 + .../eq-core-dll/src/ISXEQ-VS2005.vcproj | 334 + .../eq-core-dll/src/ISXEQ.vcproj | 245 + .../eq-core-dll/src/ISXEQ/ISXEQ.cpp | 520 + .../eq-core-dll/src/ISXEQ/ISXEQ.h | 119 + .../eq-core-dll/src/ISXEQ/ISXEQCommandAPI.cpp | 225 + .../eq-core-dll/src/ISXEQ/ISXEQCommandList.h | 43 + .../eq-core-dll/src/ISXEQ/ISXEQCommands.cpp | 1293 +++ .../eq-core-dll/src/ISXEQ/ISXEQCommands.h | 18 + .../eq-core-dll/src/ISXEQ/ISXEQDataTypes.cpp | 571 + .../eq-core-dll/src/ISXEQ/ISXEQDataTypes.h | 57 + .../eq-core-dll/src/ISXEQ/ISXEQServices.cpp | 234 + .../eq-core-dll/src/ISXEQ/ISXEQServices.h | 27 + .../src/ISXEQ/ISXEQTopLevelObjects.cpp | 46 + .../src/ISXEQ/ISXEQTopLevelObjects.h | 58 + .../eq-core-dll/src/ISXEQ/ISXEQUtilities.cpp | 225 + .../eq-core-dll/src/ISXEQ/ISXEQUtilities.h | 3 + .../eq-core-dll/src/InterfaceQuery.cpp | 45 + .../eq-core-dll/src/License.txt | 15 + .../eq-core-dll/src/MQ2AdvDps.cpp | 692 ++ .../eq-core-dll/src/MQ2Auth.cpp | 11 + .../eq-core-dll/src/MQ2Benchmarks.cpp | 170 + .../eq-core-dll/src/MQ2ChatHook.cpp | 149 + .../eq-core-dll/src/MQ2CleanUI.cpp | 167 + .../eq-core-dll/src/MQ2CommandAPI.cpp | 668 ++ .../eq-core-dll/src/MQ2Commands.cpp | 3092 ++++++ .../eq-core-dll/src/MQ2Commands.h | 91 + .../eq-core-dll/src/MQ2DInput.cpp | 256 + .../eq-core-dll/src/MQ2Data.cpp | 1521 +++ .../eq-core-dll/src/MQ2DataAPI.cpp | 580 + .../eq-core-dll/src/MQ2DataTypes.cpp | 7593 +++++++++++++ .../eq-core-dll/src/MQ2DataTypes.h | 3686 +++++++ .../eq-core-dll/src/MQ2DataVars.cpp | 541 + .../eq-core-dll/src/MQ2DetourAPI.cpp | 1003 ++ .../eq-core-dll/src/MQ2Globals.cpp | 1700 +++ .../eq-core-dll/src/MQ2Globals.h | 1208 +++ .../eq-core-dll/src/MQ2Inlines.h | 452 + .../eq-core-dll/src/MQ2Internal.h | 998 ++ .../eq-core-dll/src/MQ2ItemDisplay.cpp | 642 ++ .../eq-core-dll/src/MQ2KeyBinds.cpp | 624 ++ .../eq-core-dll/src/MQ2Labels.cpp | 138 + .../eq-core-dll/src/MQ2MacroCommands.cpp | 1253 +++ .../eq-core-dll/src/MQ2Main.cpp | 565 + .../eq-core-dll/src/MQ2Main.dep | 223 + .../eq-core-dll/src/MQ2Main.dsp | 222 + .../native_autoloot/eq-core-dll/src/MQ2Main.h | 633 ++ .../eq-core-dll/src/MQ2Main.mak | 281 + .../eq-core-dll/src/MQ2Main.vcproj | 216 + .../eq-core-dll/src/MQ2Map.cpp | 325 + .../native_autoloot/eq-core-dll/src/MQ2Map.h | 118 + .../eq-core-dll/src/MQ2MapAPI.cpp | 1198 ++ .../eq-core-dll/src/MQ2MapCommands.cpp | 479 + .../eq-core-dll/src/MQ2Mouse.cpp | 245 + .../eq-core-dll/src/MQ2ParseAPI.cpp | 125 + .../eq-core-dll/src/MQ2PluginHandler.cpp | 13 + .../eq-core-dll/src/MQ2Prototypes.h | 56 + .../eq-core-dll/src/MQ2Pulse.cpp | 327 + .../eq-core-dll/src/MQ2Pulse.cpp.bak | 406 + .../eq-core-dll/src/MQ2Spawns.cpp | 636 ++ .../eq-core-dll/src/MQ2TopLevelObjects.h | 51 + .../eq-core-dll/src/MQ2Utilities.cpp | 5973 ++++++++++ .../native_autoloot/eq-core-dll/src/PE.cpp | 94 + .../native_autoloot/eq-core-dll/src/PE.h | 246 + .../eq-core-dll/src/_options.h | 114 + .../eq-core-dll/src/com_ptr.hpp | 202 + .../eq-core-dll/src/combines.h | 71 + .../native_autoloot/eq-core-dll/src/common.h | 1 + .../eq-core-dll/src/core_autoloot_native.h | 3039 ++++++ .../eq-core-dll/src/core_bazaar.h | 9 + .../eq-core-dll/src/core_eqg_load.h | 212 + .../eq-core-dll/src/core_init.h | 22 + .../eq-core-dll/src/core_item.h | 32 + .../eq-core-dll/src/core_luclin_models.h | 21 + .../eq-core-dll/src/core_map.h | 9 + .../eq-core-dll/src/core_models.h | 31 + .../eq-core-dll/src/core_npc.h | 55 + .../eq-core-dll/src/core_zone.h | 61 + .../eq-core-dll/src/d3d_example.cpp | 70 + .../native_autoloot/eq-core-dll/src/dikeys.h | 159 + .../eq-core-dll/src/dinput8.def | 9 + .../native_autoloot/eq-core-dll/src/dinput8.h | 33 + .../eq-core-dll/src/dinputproxy.h | 84 + .../eq-core-dll/src/dllmain.cpp | 132 + .../eq-core-dll/src/dsetup.def | 3 + .../eq-core-dll/src/eqgame.cpp | 1264 +++ .../native_autoloot/eq-core-dll/src/eqgame.h | 670 ++ .../native_autoloot/eq-core-dll/src/eqmac.h | 0 .../eq-core-dll/src/eqmac_functions.h | 0 .../native_autoloot/eq-core-dll/src/grounds.h | 35 + .../eq-core-dll/src/hook_vtable.hpp | 37 + .../eq-core-dll/src/internals.h | 27 + .../eq-core-dll/src/itemtypes.h | 71 + .../eq-core-dll/src/keyboard.cpp | 237 + .../native_autoloot/eq-core-dll/src/main.cpp | 69 + .../eq-core-dll/src/memory.hpp | 61 + .../eq-core-dll/src/msvc/Base.cpp | 116 + .../eq-core-dll/src/msvc/Base.h | 52 + .../eq-core-dll/src/msvc/CPatcher.cpp | 133 + .../eq-core-dll/src/msvc/CPatcher.h | 35 + .../eq-core-dll/src/msvc/Entry.h | 17 + .../eq-core-dll/src/msvc/Logger.cpp | 52 + .../eq-core-dll/src/msvc/StdAfx.h | 28 + .../eq-core-dll/src/msvc/Utils.cpp | 55 + .../eq-core-dll/src/msvc/Utils.h | 36 + .../eq-core-dll/src/msvc/di-wrapper.rc | Bin 0 -> 3708 bytes .../eq-core-dll/src/msvc/resource.h | 8 + .../eq-core-dll/src/proxy_idi.cpp | 110 + .../eq-core-dll/src/proxy_idid.cpp | 150 + .../native_autoloot/eq-core-dll/src/skills.h | 152 + .../eq-core-dll/src/spaghetti.cpp | 439 + .../eq-core-dll/src/spaghetti.h | 144 + .../eq-core-dll/src/str_com/pchar.cpp | 98 + .../eq-core-dll/src/str_com/pchar2.cpp | 73 + .../eq-core-dll/src/str_com/pspawn.cpp | 159 + .../native_autoloot/eq-core-dll/src/weapons.h | 277 + .../native_autoloot/eq-core-dll/src/xorstr.h | 0 docs/native-client-runtime.md | 32 + 176 files changed, 99140 insertions(+), 6 deletions(-) create mode 100644 client_files/native_autoloot/eq-core-dll/.editorconfig create mode 100644 client_files/native_autoloot/eq-core-dll/.gitattributes create mode 100644 client_files/native_autoloot/eq-core-dll/.gitignore create mode 100644 client_files/native_autoloot/eq-core-dll/.vscode/settings.json create mode 100644 client_files/native_autoloot/eq-core-dll/Blech/Blech.h create mode 100644 client_files/native_autoloot/eq-core-dll/README.md create mode 100644 client_files/native_autoloot/eq-core-dll/bin/dinput8.dll create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/.gitignore create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/detours/inc/detours.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/detours/lib/detours.lib create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3d9.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3d9caps.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3d9types.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9anim.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9core.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9effect.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9math.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9math.inl create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9mesh.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9shader.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9shape.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9tex.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9xof.h create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Lib/d3d9.lib create mode 100644 client_files/native_autoloot/eq-core-dll/dependencies/dx9/Lib/d3dx9.lib create mode 100644 client_files/native_autoloot/eq-core-dll/dxsdk81/include/dinput.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/AddressLookupTable.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/DetoursAPI.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/EQClasses.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/EQClasses.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/EQData.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/EQDetours.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/EQFunctionDetours.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/EQNetworkDetours.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/EQUIStructs.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/EQUtils.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/EQUtils.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/FPSLimit.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/IClassFactory.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/IClassFactory.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInput8A.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInput8A.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInput8Hook.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInput8Hook.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInput8W.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInput8W.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8A.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8A.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8Hook.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8Hook.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8W.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8W.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInputEffect.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInputEffect.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumDevice.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumDevice.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumEffect.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumEffect.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ-VS2005.vcproj create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ.vcproj create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQ.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQ.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommandAPI.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommandList.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommands.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommands.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQDataTypes.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQDataTypes.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQServices.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQServices.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQTopLevelObjects.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQTopLevelObjects.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQUtilities.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQUtilities.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/InterfaceQuery.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/License.txt create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2AdvDps.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Auth.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Benchmarks.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2ChatHook.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2CleanUI.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2CommandAPI.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Commands.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Commands.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2DInput.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Data.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2DataAPI.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2DataTypes.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2DataTypes.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2DataVars.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2DetourAPI.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Globals.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Globals.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Inlines.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Internal.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2ItemDisplay.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2KeyBinds.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Labels.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2MacroCommands.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Main.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Main.dep create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Main.dsp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Main.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Main.mak create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Main.vcproj create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Map.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Map.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2MapAPI.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2MapCommands.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Mouse.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2ParseAPI.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2PluginHandler.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Prototypes.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Pulse.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Pulse.cpp.bak create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Spawns.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2TopLevelObjects.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/MQ2Utilities.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/PE.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/PE.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/_options.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/com_ptr.hpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/combines.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/common.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/core_bazaar.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/core_eqg_load.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/core_init.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/core_item.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/core_luclin_models.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/core_map.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/core_models.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/core_npc.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/core_zone.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/d3d_example.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/dikeys.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/dinput8.def create mode 100644 client_files/native_autoloot/eq-core-dll/src/dinput8.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/dinputproxy.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/dllmain.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/dsetup.def create mode 100644 client_files/native_autoloot/eq-core-dll/src/eqgame.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/eqgame.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/eqmac.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/eqmac_functions.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/grounds.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/hook_vtable.hpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/internals.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/itemtypes.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/keyboard.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/main.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/memory.hpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/msvc/Base.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/msvc/Base.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/msvc/CPatcher.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/msvc/CPatcher.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/msvc/Entry.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/msvc/Logger.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/msvc/StdAfx.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/msvc/Utils.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/msvc/Utils.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/msvc/di-wrapper.rc create mode 100644 client_files/native_autoloot/eq-core-dll/src/msvc/resource.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/proxy_idi.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/proxy_idid.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/skills.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/spaghetti.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/spaghetti.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/str_com/pchar.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/str_com/pchar2.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/str_com/pspawn.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/weapons.h create mode 100644 client_files/native_autoloot/eq-core-dll/src/xorstr.h create mode 100644 docs/native-client-runtime.md diff --git a/client_files/native_autoloot/README.md b/client_files/native_autoloot/README.md index 53d780db99..47023e372c 100644 --- a/client_files/native_autoloot/README.md +++ b/client_files/native_autoloot/README.md @@ -1,31 +1,79 @@ -# Native AutoLoot Client Files +# Native Client Runtime -This folder contains the AutoLoot-specific native UI XML for the matching server branch. +This folder contains the current client-side native runtime for the custom EQEmu feature set. -The DLL source is not included in this proof branch yet. The current DLL implementation still lives in shared native-client runtime code and needs a `native-client-base` split before the client side is a clean AutoLoot-only pack. +It supports the native EQ UI windows and transport lines for: + +- AutoLoot: `AUTOLOOT|...` +- Live Items / Item Forge: `LIVEITEM|...` +- Live Spells / Spell Forge: `LIVESPELL|...` +- Achievements: `ACH|...` ## Install -Copy the SIDL XML file to the client's default UI folder: +Copy the prebuilt DLL to the root of the EverQuest client folder: + +```text +client_files/native_autoloot/eq-core-dll/bin/dinput8.dll +``` + +Copy the native UI XML files to the client's default UI folder: ```text client_files/native_autoloot/ui/EQUI_NativeAutoLootWnd.xml +client_files/native_autoloot/ui/EQUI_NativeItemForgeWnd.xml +client_files/native_autoloot/ui/EQUI_NativeSpellForgeWnd.xml +client_files/native_autoloot/ui/EQUI_NativeAchievementWnd.xml ``` Destination example: ```text +EverQuest/dinput8.dll EverQuest/uifiles/default/EQUI_NativeAutoLootWnd.xml +EverQuest/uifiles/default/EQUI_NativeItemForgeWnd.xml +EverQuest/uifiles/default/EQUI_NativeSpellForgeWnd.xml +EverQuest/uifiles/default/EQUI_NativeAchievementWnd.xml ``` Only load one patched client folder at a time. ## In Game -Use this command to reopen the window if it is closed: +Useful reopen commands: ```text #autoloot native show +#itemforge dialog +#livespell dialog +#ach window +``` + +The server remains authoritative. The DLL creates native windows, parses server transport lines, and sends normal server commands back to the zone. + +## Current Shape + +This is a monolithic native runtime. The feature-specific code currently lives mostly in: + +```text +client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h ``` -The server remains authoritative. The native client DLL host only creates the native window, parses `AUTOLOOT|...` status lines, and sends normal server commands back to the zone. +The old `EQUI_AoTAutoLootWnd.xml` combined prototype window is intentionally not included. AutoLoot uses `EQUI_NativeAutoLootWnd.xml`. + +The surrounding DLL project still contains older MacroQuest-derived scaffolding because the current hooks were built on that client-side base. That is separate from the removed Lua/MQ AutoLoot UI path. + +## Build + +Open one of these solutions in Visual Studio: + +```text +client_files/native_autoloot/eq-core-dll/eq-core-dll-visualstudio2022.sln +client_files/native_autoloot/eq-core-dll/eq-core-dll-visualstudio2019.sln +``` + +Build `Release|Win32`. The output is: + +```text +client_files/native_autoloot/eq-core-dll/bin/dinput8.dll +``` diff --git a/client_files/native_autoloot/eq-core-dll/.editorconfig b/client_files/native_autoloot/eq-core-dll/.editorconfig new file mode 100644 index 0000000000..163988705d --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/.editorconfig @@ -0,0 +1,59 @@ +[*] +cpp_indent_braces=false +cpp_indent_multi_line_relative_to=innermost_parenthesis +cpp_indent_within_parentheses=indent +cpp_indent_preserve_within_parentheses=false +cpp_indent_case_labels=false +cpp_indent_case_contents=true +cpp_indent_case_contents_when_block=false +cpp_indent_lambda_braces_when_parameter=true +cpp_indent_goto_labels=one_left +cpp_indent_preprocessor=leftmost_column +cpp_indent_access_specifiers=false +cpp_indent_namespace_contents=true +cpp_indent_preserve_comments=false +cpp_new_line_before_open_brace_namespace=ignore +cpp_new_line_before_open_brace_type=ignore +cpp_new_line_before_open_brace_function=ignore +cpp_new_line_before_open_brace_block=ignore +cpp_new_line_before_open_brace_lambda=ignore +cpp_new_line_scope_braces_on_separate_lines=false +cpp_new_line_close_brace_same_line_empty_type=false +cpp_new_line_close_brace_same_line_empty_function=false +cpp_new_line_before_catch=true +cpp_new_line_before_else=true +cpp_new_line_before_while_in_do_while=false +cpp_space_before_function_open_parenthesis=remove +cpp_space_within_parameter_list_parentheses=false +cpp_space_between_empty_parameter_list_parentheses=false +cpp_space_after_keywords_in_control_flow_statements=true +cpp_space_within_control_flow_statement_parentheses=false +cpp_space_before_lambda_open_parenthesis=false +cpp_space_within_cast_parentheses=false +cpp_space_after_cast_close_parenthesis=false +cpp_space_within_expression_parentheses=false +cpp_space_before_block_open_brace=true +cpp_space_between_empty_braces=false +cpp_space_before_initializer_list_open_brace=false +cpp_space_within_initializer_list_braces=true +cpp_space_preserve_in_initializer_list=true +cpp_space_before_open_square_bracket=false +cpp_space_within_square_brackets=false +cpp_space_before_empty_square_brackets=false +cpp_space_between_empty_square_brackets=false +cpp_space_group_square_brackets=true +cpp_space_within_lambda_brackets=false +cpp_space_between_empty_lambda_brackets=false +cpp_space_before_comma=false +cpp_space_after_comma=true +cpp_space_remove_around_member_operators=true +cpp_space_before_inheritance_colon=true +cpp_space_before_constructor_colon=true +cpp_space_remove_before_semicolon=true +cpp_space_after_semicolon=false +cpp_space_remove_around_unary_operator=true +cpp_space_around_binary_operator=insert +cpp_space_around_assignment_operator=insert +cpp_space_pointer_reference_alignment=left +cpp_space_around_ternary_operator=insert +cpp_wrap_preserve_blocks=one_liners diff --git a/client_files/native_autoloot/eq-core-dll/.gitattributes b/client_files/native_autoloot/eq-core-dll/.gitattributes new file mode 100644 index 0000000000..dfe0770424 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/client_files/native_autoloot/eq-core-dll/.gitignore b/client_files/native_autoloot/eq-core-dll/.gitignore new file mode 100644 index 0000000000..6bf9285986 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/.gitignore @@ -0,0 +1,42 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +.vs/ +build/ +enc_temp_folder/ +bin/ +Debug/ +Release/ +*.aps +*.suo +*.user diff --git a/client_files/native_autoloot/eq-core-dll/.vscode/settings.json b/client_files/native_autoloot/eq-core-dll/.vscode/settings.json new file mode 100644 index 0000000000..a965a608ff --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "[cpp]":{ + "editor.wordBasedSuggestions": "off", + "editor.suggest.insertMode": "replace", + "editor.semanticHighlighting.enabled": true, + } +} \ No newline at end of file diff --git a/client_files/native_autoloot/eq-core-dll/Blech/Blech.h b/client_files/native_autoloot/eq-core-dll/Blech/Blech.h new file mode 100644 index 0000000000..be57f8c6eb --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/Blech/Blech.h @@ -0,0 +1,1345 @@ +/***************************************************************************** + Blech.h + Lax/Blech + Copyright (C) 2004-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +/***************************************************************************** +About Blech: + Blech is a text parser API. It uses callback system to allow it to retrieve + current values of variables from your program, and to initiate an event from + a successful match. Events are added, text is fed through it, and hopefully + you get what you want.... + + Blech uses a B-Tree implementation where each node can have n nodes. The + data stored by each node is a portion of a string. Nodes are split when a + sibling is being added that begins with the same data as an existing one. + Example: + existing child of a node: "blech"-(possibly existing children) + insert child to node: "bleach" + + resulting nodes: "ch"-(possibly existing children) + "ble"< + "ach" + The end result using this implementation is a way to compare a given string to + many strings with possibly variable portions, where a hash/map/binary tree will + fail. + +Using Blech: + *Initialize the Blech class: + Blech MyBlech('#'); // Use only a variable "scan" + Blech MyBlech('#','|',VariableValue); // Use a variable "scan" and a variable "print" + + *Add events: + MyBlech.AddEvent("Text with #variable# portion",MyEvent,0); + + *Create event callback: + void __stdcall MyEvent(unsigned long ID, void * pData, PBLECHVALUE pValues) + { + printf("MyEvent(%d,%X,%X)",ID,pData,pValues); + while(pValues) + { + printf("'%s'=>'%s'",pValues->Name,pValues->Value); + pValues=pValues->pNext; + } + } + + *Feed Blech: + MyBlech.Feed("Text with some portion"); + + *Examine output: + MyEvent(1,0,(pointer)) + 'variable'=>'some' + +******************************************************************************/ + +#pragma once +#pragma warning(disable : 4996) + +#define BLECHVERSION "Lax/Blech 1.7.2" + +#include +#include + +//#ifdef WIN32 + +#ifdef BLECH_DEBUG_FULL +#define BLECH_DEBUG +#define BlechDebugFull BlechDebug +#else +#define BlechDebugFull +#endif + +#ifdef BLECH_DEBUG +//#pragma message(BLECHVERSION) +//#pragma message("Blech: Debug Mode") +#include +#define BLECHASSERT(x) if (!(x)) {BlechDebug("Blech Assertion failure: %s",#x); __asm{int 3};} +static void BlechDebug(char *szFormat, ...) +{ + char szOutput[4096] = {0}; + va_list vaList; + + va_start( vaList, szFormat ); + vsprintf(szOutput,szFormat, vaList); + OutputDebugString(szOutput); + OutputDebugString("\n"); +} +#define BlechTry(x) BlechDebug("Trying %s",#x);x;BlechDebug("%s complete",#x) +#else +#define BLECHASSERT(x) +#define BlechTry(x) x +#define BlechDebug +#endif + +#ifdef BLECH_CASE_SENSITIVE +//#pragma message("Blech: Case Sensitive") +#define STRCMP(A,B) strcmp(A,B) +#define STRNCMP(A,B,LENGTH) strncmp(A,B,LENGTH) +#define STRFIND(HAYSTACK,NEEDLE) strstr(HAYSTACK,NEEDLE) +#else +//#pragma message("Blech: Case Insensitive") +#define STRCMP(A,B) stricmp(A,B) +#define STRNCMP(A,B,LENGTH) strnicmp(A,B,LENGTH) +#define STRFIND(HAYSTACK,NEEDLE) stristr(HAYSTACK,NEEDLE) +#endif +//#else +//#error Non-Win32 defines not yet available +//#endif + + +enum eBlechStringType +{ + BST_NORMAL=0, + BST_PRINTVAR=1, + BST_SCANVAR=2, +}; + + +typedef struct _BLECHVALUE { + char * Name; + char * Value; + struct _BLECHVALUE *pNext; +} BLECHVALUE, *PBLECHVALUE; + +typedef struct _BLECHLISTNODE { + class BlechNode *pNode; + struct _BLECHLISTNODE *pNext; +} BLECHLISTNODE, *PBLECHLISTNODE; + + +typedef unsigned long (__stdcall *fBlechVariableValue)(char * VarName, char * Value); +typedef void (__stdcall *fBlechCallback)(unsigned long ID, void * pData, PBLECHVALUE pValues); + +typedef struct _BLECHEVENT { + unsigned long ID; + void * pData; + char * OriginalString; + fBlechCallback Callback; + + class BlechNode *pBlechNode; +} BLECHEVENT, *PBLECHEVENT; + +typedef struct _BLECHEXECUTE { + unsigned long ID; + void * pData; + + fBlechCallback Callback; + struct _BLECHVALUE *pValues; + struct _BLECHEXECUTE *pNext; +} BLECHEXECUTE, *PBLECHEXECUTE; + +typedef std::map BLECHEVENTMAP; + +typedef struct _BLECHEVENTNODE { + PBLECHEVENT pEvent; + + struct _BLECHEVENTNODE *pNext; + struct _BLECHEVENTNODE *pPrev; +} BLECHEVENTNODE, *PBLECHEVENTNODE; + +static unsigned long Equalness(char *StringA, char *StringB) +{ + BlechDebugFull("Equalness(%s,%s)",StringA,StringB); + char *pPos=StringA; + while(1) + { + if (*pPos!=*StringB) + { +#ifndef BLECH_CASE_SENSITIVE + if (*pPos>='a' && *pPos<='z') + { + if ((*pPos)-32==*StringB) + { + ++pPos; + ++StringB; + continue; + } + } + else if (*pPos>='A' && *pPos<='Z') + { + if ((*pPos)+32==*StringB) + { + ++pPos; + ++StringB; + continue; + } + } +#endif + unsigned long Ret=(unsigned long)(pPos-StringA); + BlechDebugFull("Equalness returning %d",Ret); + return Ret; + } + else + { + if (!*pPos) + { + unsigned long Ret=(unsigned long)(pPos-StringA); + BlechDebugFull("Equalness returning %d",Ret); + return Ret; + } + } + ++pPos; + ++StringB; + } +} + +class BlechNode +{ +public: + BlechNode(BlechNode *Parent, BlechNode **Root, char * String, eBlechStringType NewStringType=BST_NORMAL) + { + BlechDebug("BlechNode(%X,%X,%s,%d)",Parent,Root,String,NewStringType); + BLECHASSERT(String && *String); + BLECHASSERT(Root); + StringType=NewStringType; + if (StringType==BST_NORMAL) + Length=(unsigned long)strlen(String); + else + Length=0; + pString=strdup(String); + pParent=Parent; + ppRoot=Root; + pChildren=0; + pNext=0; + pPrev=0; + pEvents=0; + } + + ~BlechNode() + { + BlechDebug("~BlechNode()"); + // clean out chillins + while(pChildren) + { + BlechNode *pNext=pChildren->pNext; + delete pChildren; + pChildren=pNext; + } + // clean out events + while(pEvents) + { + pEvents->pEvent->pBlechNode=0; + PBLECHEVENTNODE pNext=pEvents->pNext; + delete pEvents; + pEvents=pNext; + } + // remove me from my siblings + if (pPrev) + pPrev->pNext=pNext; + else + { + // set parent's first child / root + if (pParent) + pParent->pChildren=pNext; + else + { + if (*ppRoot==this) + *ppRoot=pNext; + } + } + if (pNext) + pNext->pPrev=pPrev; + + // free string + free(pString); + } + + BlechNode *AddChild(char *NewString, eBlechStringType NewStringType) + { + BlechDebug("AddChild(%s,%d)",NewString,NewStringType); + BLECHASSERT(NewString); + + BlechNode *pChild = pChildren; + while(pChild) + { + if (pChild->StringType==NewStringType) + { + if (NewStringType==BST_NORMAL) + { + if (unsigned long Eq=Equalness(pChild->pString,NewString)) + { + unsigned long Len=(unsigned long)strlen(NewString); + if (Len==Eq) + { + if (Eq==pChild->Length) + { + return pChild; + } + // old child needs to be child of new child! + + // make new child, redo pChild as child of new child... + BlechNode *pNode = new BlechNode(this,ppRoot,NewString,NewStringType); + BLECHASSERT(pNode); + if (pNode->pNext=pChild->pNext) + pNode->pNext->pPrev=pNode; + if (pNode->pPrev=pChild->pPrev) + pNode->pPrev->pNext=pNode; + else + pChildren=pNode; + pChild->pNext=0; + pChild->pPrev=0; + + pChild->pParent=pNode; + pNode->pChildren=pChild; + memmove(pChild->pString,&pChild->pString[Eq],pChild->Length-Eq+1); + pChild->Length-=Eq; + + return pNode; + // and return that new child + } + else if (Eq==pChild->Length) + { + // easy one + return pChild->AddChild(&NewString[Eq],NewStringType); + } + // both children (new and old) need to be children of a new child + + // make new child, redo pChild as child of new child... + char Temp=pChild->pString[Eq]; + pChild->pString[Eq]=0; + BlechNode *pNode = new BlechNode(this,ppRoot,pChild->pString,NewStringType); + pChild->pString[Eq]=Temp; + BLECHASSERT(pNode); + if (pNode->pNext=pChild->pNext) + pNode->pNext->pPrev=pNode; + if (pNode->pPrev=pChild->pPrev) + pNode->pPrev->pNext=pNode; + else + pChildren=pNode; + pChild->pNext=0; + pChild->pPrev=0; + + + pChild->pParent=pNode; + pNode->pChildren=pChild; + + memmove(pChild->pString,&pChild->pString[Eq],pChild->Length-Eq+1); + pChild->Length-=Eq; + return pNode->AddChild(&NewString[Eq],NewStringType); + // and return a very new child! + } + } + else + { + if (!strcmp(pChild->pString,NewString)) + return pChild; + } + } + pChild=pChild->pNext; + } + + + BlechNode *pNode = new BlechNode(this,ppRoot,NewString,NewStringType); + BLECHASSERT(pNode); + pNode->pNext=pChildren; + if (pChildren) + pChildren->pPrev=pNode; + pChildren=pNode; + return pChildren; + } + + inline bool IsEmpty() + { + return (!pChildren && !pEvents); + } + + inline void AddEvent(PBLECHEVENT pEvent) + { + BlechDebug("AddEvent(%X)",pEvent); + BLECHASSERT(pEvent); + + PBLECHEVENTNODE pNode=new BLECHEVENTNODE; + pNode->pEvent=pEvent; + pNode->pNext=pEvents; + if (pEvents) + pEvents->pPrev=pNode; + pNode->pPrev=0; + pEvent->pBlechNode=this; + pEvents=pNode; + } + + eBlechStringType StringType; + char * pString; + unsigned long Length; + BlechNode *pParent; + BlechNode **ppRoot; + BlechNode *pChildren; + BlechNode *pNext; + BlechNode *pPrev; + + PBLECHEVENTNODE pEvents; +}; + +class Blech +{ +public: + Blech(char ScanDelimiter,char PrintDelimiter,fBlechVariableValue PrintRetriever) + { + BlechDebug("Blech(%c,%c,%X)",ScanDelimiter,PrintDelimiter,PrintRetriever); + BLECHASSERT(PrintDelimiter); + BLECHASSERT(PrintRetriever); + PrintVarDelimiter=PrintDelimiter; + ScanVarDelimiter=ScanDelimiter; + VariableValue=PrintRetriever; + Initialize(); + } + Blech(char ScanDelimiter=0) + { + BlechDebug("Blech(%c)",ScanDelimiter); + ScanVarDelimiter=ScanDelimiter; + PrintVarDelimiter=0; + VariableValue=0; + Initialize(); + } + + static char *stristr(char *haystack,char *needle) + { + BlechDebugFull("stristr(%s,%s)",haystack,needle); + BLECHASSERT(haystack!=0); + BLECHASSERT(needle!=0); + if (!needle[0]) + return haystack; + + static bool bInitialized=false; + static char ToUpper[256]; + if (!bInitialized) + { + bInitialized=true; + ToUpper[0]=0; + for(unsigned long iliketmpvars = 1 ; iliketmpvars < 128 ; iliketmpvars++) + ToUpper[iliketmpvars]=(char)toupper(iliketmpvars); + for (unsigned long iliketmpvarsmore = 128 ; iliketmpvarsmore < 256 ; iliketmpvarsmore++) + { + ToUpper[iliketmpvarsmore]=(char)iliketmpvarsmore; + } + } + + char *originalneedle=needle; + do + { + char c=*haystack; + if (!c) + return 0; + if (ToUpper[c]==ToUpper[*needle]) + { + char *start=haystack; + do + { + needle++; + c=*needle; + if (!c) + return start; + haystack++; + char d=*haystack; + if (!d) + { + return 0; + } + + if (ToUpper[c]!=ToUpper[d]) + break; + } + while(1); + + haystack=start+1; + needle=originalneedle; + continue; + } + haystack++; + } + while(1); + + + + return 0; + } + + + + void Reset() + { + Cleanup(); + Event.clear(); +// ExactMatch.clear(); + Initialize(); + } + + ~Blech(void) + { + BlechDebug("~Blech()"); + Cleanup(); + } + + unsigned long Feed(char * Input) + { + BlechDebug("Feed(%s)",Input); + if (!Input || !Input[0]) + return 0; + unsigned long Root=(unsigned char)Input[0]; +#ifndef BLECH_CASE_SENSITIVE + if (Root>='a' && Root<='z') + Root-=32; +#endif + return Chew(Tree[Root],Input)+Chew(Tree[0],Input)/*+Swallow(Input)/**/; + } + + inline bool IsExact(char *Text) + { + if (!strchr(Text,ScanVarDelimiter) && (!PrintVarDelimiter || !strchr(Text,PrintVarDelimiter))) + return true; + return false; + } + + unsigned long AddEvent(char *Text,fBlechCallback Callback,void *pData=0) + { + BlechDebug("AddEvent(%s,%X,%X)",Text,Callback,pData); + BLECHASSERT(Text); + BLECHASSERT(Callback); + char *pText=Text; + char *Part=Text; + eBlechStringType StringType=BST_NORMAL; + BlechNode *pNode=0; + while(*pText) + { + if (*pText==ScanVarDelimiter) + { + if (Part!=pText) + pNode=AddNode(pNode,Part,pText,StringType); + Part=&pText[1]; + if (StringType==BST_SCANVAR) + StringType=BST_NORMAL; + else + StringType=BST_SCANVAR; + } + else + if (*pText==PrintVarDelimiter) + { + if (Part!=pText) + pNode=AddNode(pNode,Part,pText,StringType); + Part=&pText[1]; + if (StringType==BST_PRINTVAR) + StringType=BST_NORMAL; + else + StringType=BST_PRINTVAR; + } + pText++; + } + if (*Part) + { + pNode=AddNode(pNode,Part,pText,StringType); + } + // add event to node + BLECHASSERT(pNode); + PBLECHEVENT pEvent = new BLECHEVENT; + pEvent->Callback=Callback; + pEvent->pData=pData; + pEvent->ID=++LastID; + pEvent->pBlechNode=pNode; + pEvent->OriginalString=strdup(Text); + pNode->AddEvent(pEvent); + Event[pEvent->ID]=pEvent; + return pEvent->ID; + } + + bool RemoveEvent(unsigned long ID) + { + BlechDebug("RemoveEvent(%d)",ID); + PBLECHEVENT pEvent = Event[ID]; + if (!pEvent) + return false; + Event.erase(ID); + { + free(pEvent->OriginalString); + + + BlechNode *pNode=pEvent->pBlechNode; + // find the PBLECHEVENTNODE for this event and remove it + PBLECHEVENTNODE pEventNode = pNode->pEvents; + while(pEventNode) + { + if (pEvent==pEventNode->pEvent) + { + if (pEventNode->pNext) + pEventNode->pNext->pPrev=pEventNode->pPrev; + if (pEventNode->pPrev) + pEventNode->pPrev->pNext=pEventNode->pNext; + else + pNode->pEvents=pEventNode->pNext; + break; + } + pEventNode=pEventNode->pNext; + } + + while(pNode && pNode->IsEmpty()) + { + BlechNode *pNext=pNode->pParent; + delete pNode; + pNode=pNext; + } + + delete pEvent; + } + return true; + } + + char Version[32]; + +private: + inline void FreeExecution(PBLECHEXECUTE pExecute) + { + PBLECHVALUE pValue=pExecute->pValues; + while (pValue) + { + PBLECHVALUE pNext=pValue->pNext; + free(pValue->Value); + free(pValue->Name); + delete pValue; + pValue=pNext; + } + delete pExecute; + } + + void ClearExecutionList() + { + while(pExecuteList) + { + PBLECHEXECUTE pExecuteNext=pExecuteList->pNext; + FreeExecution(pExecuteList); + pExecuteList=pExecuteNext; + } + } + + unsigned long ProcessExecutionList() + { + unsigned long n=0; + while(pExecuteList) + { + n++; + PBLECHEXECUTE pExecuteNext=pExecuteList->pNext; + pExecuteList->Callback(pExecuteList->ID,pExecuteList->pData,pExecuteList->pValues); + FreeExecution(pExecuteList); + pExecuteList=pExecuteNext; + } + return n; + } + + inline void Cleanup() + { + for (unsigned long N = 0 ; N < 256 ; N++) + { + delete Tree[N]; + Tree[N]=0; + } + for (BLECHEVENTMAP::iterator i=Event.begin(); i != Event.end(); i++) + { + if (PBLECHEVENT pEvent=i->second) + { + BLECHASSERT(pEvent); + BlechTry(free(pEvent->OriginalString)); + delete pEvent; + Event[i->first]=0; + } + } + ClearExecutionList(); + } + + + void QueueEvent(PBLECHEVENT pEvent, PBLECHVALUE pValues) + { + BlechDebug("QueueEvent(%X,%X)",pEvent,pValues); + BLECHASSERT(pEvent); + + PBLECHEXECUTE pNew=new BLECHEXECUTE; + pNew->Callback=pEvent->Callback; + pNew->ID=pEvent->ID; + pNew->pData=pEvent->pData; + // make a COPY of values + if (pValues) + { + PBLECHVALUE pNewValueTail=0; + pNew->pValues=0; + while(pValues) + { + PBLECHVALUE pNewValue=new BLECHVALUE; + pNewValue->Name=strdup(pValues->Name); + pNewValue->Value=strdup(pValues->Value); + pNewValue->pNext=0; + if (pNew->pValues) + { + pNewValueTail->pNext=pNewValue; + pNewValueTail=pNewValue; + } + else + { + pNewValueTail=pNew->pValues=pNewValue; + + } + pValues=pValues->pNext; + } + } + else + pNew->pValues=0; + + pNew->pNext=pExecuteList; + pExecuteList=pNew; + } + + void QueueEvents(BlechNode *pNode, char *Input, unsigned long InputLength) + { + PBLECHEVENTNODE pEventNode; + BlechDebug("QueueEvents(%X,%s,%d)",pNode,Input,InputLength); + BLECHASSERT(pNode); + BLECHASSERT(Input); + BLECHASSERT(InputLength); + // ASSUME we have a complete match + + // Get forward traversal list (reverse the links, into a new list) + PBLECHLISTNODE pList=0; + BlechNode *pCurrent=pNode; + int nVariableNodes=0; + while(pCurrent) + { + PBLECHLISTNODE pNewHead=new BLECHLISTNODE; + pNewHead->pNext=pList; + pNewHead->pNode=pCurrent; + pList=pNewHead; + if (pCurrent->StringType==BST_SCANVAR) + nVariableNodes++; + pCurrent=pCurrent->pParent; + } + + if (!nVariableNodes) + { + BlechDebugFull("No variable nodes"); + // if there's no variable nodes, just make sure the lengths match + unsigned long TestLength=0; + pCurrent=pNode; + while(pCurrent) + { + TestLength+=pCurrent->Length; + pCurrent=pCurrent->pParent; + } + if (TestLength==InputLength) + { + PBLECHEVENTNODE pEventNode=pNode->pEvents; + while(pEventNode) + { + QueueEvent(pEventNode->pEvent,0); + pEventNode=pEventNode->pNext; + } + } + + // cleanup + while(pList) + { + PBLECHLISTNODE pNext=pList->pNext; + delete pList; + pList=pNext; + } + return; + } + + // now do it forward, filling in the values. we KNOW they exist. + + char NonVariable[16384]; + char VarData[4096]; + NonVariable[0]=0; + char *Pos=Input; + + PBLECHVALUE pValues=0; + PBLECHVALUE pValuesTail=0; + + BlechNode *pCurrentScanVar=0; + while(pList) + { + pCurrent=pList->pNode; + switch(pCurrent->StringType) + { + case BST_NORMAL: + strcat(NonVariable,pCurrent->pString); + break; + case BST_PRINTVAR: + VarData[0]=0; + BlechTry(VariableValue(pCurrent->pString,VarData)); + strcat(NonVariable,VarData); + break; + case BST_SCANVAR: + if (pCurrentScanVar) + { + if (NonVariable[0]) + { + char *End=STRFIND(Pos,NonVariable); + if (End) + { + PBLECHVALUE pNewValue = new BLECHVALUE; + pNewValue->Name=strdup(pCurrentScanVar->pString); + + unsigned long Length=End-Pos; + pNewValue->Value=(char*)malloc(Length+1); + memcpy(pNewValue->Value,Pos,Length); + pNewValue->Value[Length]=0; + pNewValue->pNext=0; + if (pValues) + { + pValuesTail->pNext=pNewValue; + pValuesTail=pNewValue; + } + else + { + pValuesTail=pValues=pNewValue; + } + + Pos=End+strlen(NonVariable); + NonVariable[0]=0; + } + else + { + // not a real match. goodbye! + // NOTE: this can be relatively normal, it is not a direct indication of an error + goto queueeventscleanup; + } + } + else + { + PBLECHVALUE pNewValue = new BLECHVALUE; + pNewValue->Name=strdup(pCurrentScanVar->pString); + pNewValue->Value=(char*)malloc(1); + pNewValue->Value[0]=0; + pNewValue->pNext=0; + if (pValues) + { + pValuesTail->pNext=pNewValue; + pValuesTail=pNewValue; + } + else + { + pValuesTail=pValues=pNewValue; + } + } + } + else + { + unsigned long NonVariableLength=strlen(NonVariable); + if (STRNCMP(NonVariable,Pos,NonVariableLength)) + { + // not a real match. goodbye! + // NOTE: this can be relatively normal, it is not a direct indication of an error + goto queueeventscleanup; + } + Pos+=NonVariableLength; + NonVariable[0]=0; + } + pCurrentScanVar=pCurrent; + break; + } + + + PBLECHLISTNODE pNext=pList->pNext; + delete pList; + pList=pNext; + } + + if (pCurrentScanVar) + { + if (NonVariable[0]) + { + char *End=&Input[InputLength]-strlen(NonVariable); + unsigned long Length=End-Pos; + if (STRCMP(&Pos[Length],NonVariable)) + { + goto queueeventscleanup; + } + + PBLECHVALUE pNewValue = new BLECHVALUE; + pNewValue->Name=strdup(pCurrentScanVar->pString); + + pNewValue->Value=(char*)malloc(Length+1); + memcpy(pNewValue->Value,Pos,Length); + pNewValue->Value[Length]=0; + pNewValue->pNext=0; + + if (pValues) + { + pValuesTail->pNext=pNewValue; + pValuesTail=pNewValue; + } + else + { + pValuesTail=pValues=pNewValue; + } + + Pos=End; + NonVariable[0]=0; + } + else + { + PBLECHVALUE pNewValue = new BLECHVALUE; + pNewValue->Name=strdup(pCurrentScanVar->pString); + pNewValue->Value=strdup(Pos); + pNewValue->pNext=0; + if (pValues) + { + pValuesTail->pNext=pNewValue; + pValuesTail=pNewValue; + } + else + { + pValuesTail=pValues=pNewValue; + } + } + } + else if (NonVariable[0]) + { + if (STRCMP(NonVariable,Pos)) + { + // not a real match. goodbye! + // NOTE: this can be relatively normal, it is not a direct indication of an error + goto queueeventscleanup; + } + } + + // add to execution list + pEventNode=pNode->pEvents; + while(pEventNode) + { + QueueEvent(pEventNode->pEvent,pValues); + pEventNode=pEventNode->pNext; + } + + // cleanup +queueeventscleanup: + while(pValues) + { + PBLECHVALUE pNext=pValues->pNext; + free(pValues->Name); + free(pValues->Value); + delete pValues; + pValues=pNext; + } + + while(pList) + { + PBLECHLISTNODE pNext=pList->pNext; + delete pList; + pList=pNext; + } + } + + struct MatchPos + { + char *Pos; + BlechNode *pNode; + }; + + unsigned long Chew(BlechNode *pNode,char * Input) + { + BlechDebug("Chew(%X,%s)",pNode,Input); + BLECHASSERT(Input); + if (!pNode) + return 0; + unsigned long Length=(unsigned long)strlen(Input); + char *pEnd=&Input[Length]; + char VarData[4096]; + +#define Push() { BLECHASSERT(PLP<99) CurrentPos.pNode=pNode;MatchStack[PLP]=CurrentPos; PLP++; } +#define Pop() { BLECHASSERT(PLP>0);PLP--; CurrentPos=MatchStack[PLP];pNode=CurrentPos.pNode; } +#define Peek() { if (!PLP) goto chewcomplete; CurrentPos=MatchStack[PLP-1]; } + + MatchPos MatchStack[100]; + MatchPos CurrentPos; + unsigned char PLP=0; + memset(&MatchStack[0],0,sizeof(MatchStack)); + + CurrentPos.Pos=Input; + Push(); + CurrentPos.pNode=pNode; + + while(pNode) + { + BLECHASSERT(PLP>0); + BlechDebugFull("PLP=%d",PLP); + BlechDebugFull("CurrentPos='%s', pNode=%X",CurrentPos.Pos,CurrentPos.pNode); + // determine match + { + switch(pNode->StringType) + { + case BST_NORMAL: + BlechDebugFull("BST_NORMAL"); + if (CurrentPos.Pos+pNode->LengthpString)) + { // what if we find this multiple times? need to find the right one, depending on the children + CurrentPos.Pos=&pFound[pNode->Length]; + if (!CurrentPos.Pos[0]) + { + goto feedermatchdoevents; + } + goto feedermatchnoevent; + } + } + else if (CurrentPos.Pos+pNode->Length==pEnd && !STRNCMP(pNode->pString,CurrentPos.Pos,pNode->Length)) + { + // match. do events? + CurrentPos.Pos+=pNode->Length; + if (!CurrentPos.Pos[0]) + { + goto feedermatchdoevents; + } + goto feedermatchnoevent; + } + BlechDebugFull("BST_NORMAL => NO MATCH"); + goto feedernomatch; + case BST_PRINTVAR: + BlechDebugFull("BST_PRINTVAR"); + // variable data of unknown size + BlechTry(pNode->Length=VariableValue(pNode->pString,VarData)); + BlechDebugFull("Variable value '%s' length %d",VarData,pNode->Length); + if (!pNode->Length) + { + // implied match + MatchStack[PLP+1].pNode=0; + if (!pNode->pChildren || pNode->pEvents) + { + goto feedermatchdoevents; + } + goto feedermatchnoevent; + } + BLECHASSERT(VarData[0]); + if (CurrentPos.Pos+pNode->LengthLength]; + if (!CurrentPos.Pos[0]) + { + goto feedermatchdoevents; + } + goto feedermatchnoevent; + } + } + else if (CurrentPos.Pos+pNode->Length==pEnd && !STRNCMP(VarData,CurrentPos.Pos,pNode->Length)) + { + // match. do events? + CurrentPos.Pos+=pNode->Length; + if (!CurrentPos.Pos[0]) + { + goto feedermatchdoevents; + } + goto feedermatchnoevent; + } + BlechDebugFull("BST_PRINTVAR => NO MATCH"); + goto feedernomatch; + case BST_SCANVAR: + BlechDebugFull("BST_SCANVAR"); + // implied match + MatchStack[PLP+1].pNode=0; + if (!pNode->pChildren || pNode->pEvents) + { + goto feedermatchdoevents; + } + goto feedermatchnoevent; + } + } +feedermatchdoevents: + { + BlechDebug("feedermatchdoevents"); + QueueEvents(pNode,Input,Length); + } +feedermatchnoevent: + { + BlechDebugFull("feedermatchnoevent"); + // MATCH, ALREADY EXECUTED ANY NECESSARY EVENTS + // continue walking tree + if (pNode->pChildren) + { + Push(); + pNode=pNode->pChildren; + } + else if (pNode->pNext) + { + // restore from stack +// Pop(); + Peek(); + pNode=pNode->pNext; + } + else + { + Pop(); + Peek(); + while(1) + { + if (pNode->pNext) + { + pNode=pNode->pNext; + break; + } + + if (PLP>1) + { + Pop(); + Peek(); + } + else + { + pNode=0; + break; + } + } + + } + CurrentPos.pNode=pNode; + continue; + } +feedernomatch: + { + // NO MATCH + + // continue walking tree + if (pNode->pNext) + { + BlechDebugFull("SAME LEVEL, NEXT"); + // position remains the same +// Pop(); + Peek(); + pNode=pNode->pNext; + } + else + { + BlechDebugFull("PREVIOUS LEVEL, NEXT"); + // Pos goes down a level - dont reprocess the same child + Pop(); + Peek(); + while(1) + { + if (pNode->pNext) + { + pNode=pNode->pNext; + break; + } + if (PLP>1) + { + Pop(); + Peek(); + } + else + { + pNode=0; + break; + } + } + } + CurrentPos.pNode=pNode; + } + } +chewcomplete: + // execute any queued events + unsigned long Count=ProcessExecutionList(); + + BlechDebug("Chew returns %d",Count); + return Count; +#undef Push +#undef Pop +#undef Peek + } + + BlechNode *AddNode(unsigned long nRoot, char *String, eBlechStringType StringType) + { + BlechDebug("AddNode(%d,%s,%d)",nRoot,String,StringType); + BLECHASSERT(nRoot<256); + BLECHASSERT(String); + + + BlechNode *pChild = Tree[nRoot]; + while(pChild) + { + if (pChild->StringType==StringType) + { + if (StringType==BST_NORMAL) + { + if (unsigned long Eq=Equalness(pChild->pString,String)) + { + unsigned long Len=(unsigned long)strlen(String); + if (Len==Eq) + { + if (Eq==pChild->Length) + { + return pChild; + } + // old child needs to be child of new child! + + // make new child, redo pChild as child of new child... + BlechNode *pNode = new BlechNode(0,&Tree[nRoot],String,StringType); + BLECHASSERT(pNode); + if (pNode->pNext=pChild->pNext) + pNode->pNext->pPrev=pNode; + if (pNode->pPrev=pChild->pPrev) + pNode->pPrev->pNext=pNode; + else + Tree[nRoot]=pNode; + pChild->pNext=0; + pChild->pPrev=0; + + pChild->pParent=pNode; + pNode->pChildren=pChild; + memmove(pChild->pString,&pChild->pString[Eq],pChild->Length-Eq+1); + pChild->Length-=Eq; + + return pNode; + // and return that new child + } + else if (Eq==pChild->Length) + { + // easy one + return pChild->AddChild(&String[Eq],StringType); + } + // both children (new and old) need to be children of a new child + + // make new child, redo pChild as child of new child... + char Temp=pChild->pString[Eq]; + pChild->pString[Eq]=0; + BlechNode *pNode = new BlechNode(0,&Tree[nRoot],pChild->pString,StringType); + pChild->pString[Eq]=Temp; + BLECHASSERT(pNode); + if (pNode->pNext=pChild->pNext) + pNode->pNext->pPrev=pNode; + if (pNode->pPrev=pChild->pPrev) + pNode->pPrev->pNext=pNode; + else + Tree[nRoot]=pNode; + pChild->pNext=0; + pChild->pPrev=0; + + + pChild->pParent=pNode; + pNode->pChildren=pChild; + + memmove(pChild->pString,&pChild->pString[Eq],pChild->Length-Eq+1); + pChild->Length-=Eq; + return pNode->AddChild(&String[Eq],StringType); + // and return a very new child! + } + } + else + { + if (!strcmp(pChild->pString,String)) + return pChild; + } + } + pChild=pChild->pNext; + } + + + + BlechNode *pNode = new BlechNode(0,&Tree[nRoot],String,StringType); + BLECHASSERT(pNode); + + pNode->pNext=Tree[nRoot]; + if (Tree[nRoot]) + Tree[nRoot]->pPrev=pNode; + Tree[nRoot]=pNode; + + return pNode; + } + + BlechNode *AddNode(BlechNode *pNode, char *StringBegin, char *StringEnd, eBlechStringType StringType) + { + BlechDebug("AddNode(%X,%s,%X,%d)",pNode,StringBegin,StringEnd,StringType); + BLECHASSERT(StringBegin && *StringBegin); + BLECHASSERT(StringEnd); + + unsigned long Len=(unsigned long)(StringEnd-StringBegin); + char *String=(char*)malloc(Len+1); + memcpy(String,StringBegin,Len); + String[Len]=0; + + if (!pNode) + { + // find and/or create new root + unsigned long Root; + if (StringType!=BST_NORMAL) + Root=0; + else + { + Root=(unsigned char)*String; +#ifndef BLECH_CASE_SENSITIVE + if (Root>='a' && Root<='z') + Root-=32; +#endif + } + +// if (BlechNode *pFound=FindNode(Root,String,StringType)) +// return pFound; + BlechNode *pNew=AddNode(Root,String,StringType); + free(String); + return pNew; + } + else + { + // attach to this node + + // create new + BlechNode *pNew=pNode->AddChild(String,StringType); + free(String); + return pNew; + } + } + + inline void Initialize() + { + BlechDebugFull("Initialize()"); + strcpy(Version,BLECHVERSION); // store version string always + BlechDebug(Version); + LastID=0; + pExecuteList=0; + for (unsigned long N = 0 ; N < 256 ; N++) + { + Tree[N]=0; + } + } + + BlechNode *Tree[256]; + +// std::map ExactMatch; + + BLECHEVENTMAP Event; + + unsigned long LastID; + + char PrintVarDelimiter; + char ScanVarDelimiter; + + fBlechVariableValue VariableValue; + PBLECHEXECUTE pExecuteList; +}; + + diff --git a/client_files/native_autoloot/eq-core-dll/README.md b/client_files/native_autoloot/eq-core-dll/README.md new file mode 100644 index 0000000000..31a7541d86 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/README.md @@ -0,0 +1,15 @@ +# eq-core-dll +Core DLL for EverQuest to do patching, opt in to features + +## Requirements +- Visual Studio 2022 or 2019 (2017 in theory could work but attempting was a lot of linker errors not worth fixing) +- Windows 10 SDK (You can find it via the Visual Studio Installer program, modify, individual components, if you get an error about it on compile) + +## Usage + +- Fork this repo (or clone, and make your copy private) +- Open the eq-core-dll-visualstudio20##.sln file (based on version you have installed) +- Click Build, verify success +- Find src/_options.h, and set values to true where you want enabled, or follow instructions for custom values +- Click Build again, verify success +- Copy bin/dinput8.dll to your eq client directory \ No newline at end of file diff --git a/client_files/native_autoloot/eq-core-dll/bin/dinput8.dll b/client_files/native_autoloot/eq-core-dll/bin/dinput8.dll new file mode 100644 index 0000000000000000000000000000000000000000..f15f969965447e3811606edc00ff272478c3cde9 GIT binary patch literal 1439744 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 z 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�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 z�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 literal 0 HcmV?d00001 diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3d9.h b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3d9.h new file mode 100644 index 0000000000..880e43525d --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3d9.h @@ -0,0 +1,2582 @@ +/*==========================================================================; + * + * Copyright (C) Microsoft Corporation. All Rights Reserved. + * + * File: d3d9.h + * Content: Direct3D include file + * + ****************************************************************************/ + +#ifndef _D3D9_H_ +#define _D3D9_H_ + +#ifndef DIRECT3D_VERSION +#define DIRECT3D_VERSION 0x0900 +#endif //DIRECT3D_VERSION + +// include this file content only if compiling for DX9 interfaces +#if(DIRECT3D_VERSION >= 0x0900) + + +/* This identifier is passed to Direct3DCreate9 in order to ensure that an + * application was built against the correct header files. This number is + * incremented whenever a header (or other) change would require applications + * to be rebuilt. If the version doesn't match, Direct3DCreate9 will fail. + * (The number itself has no meaning.)*/ + +#ifdef D3D_DEBUG_INFO +#define D3D_SDK_VERSION (32 | 0x80000000) +#define D3D9b_SDK_VERSION (31 | 0x80000000) + +#else +#define D3D_SDK_VERSION 32 +#define D3D9b_SDK_VERSION 31 +#endif + + +#include + +#define COM_NO_WINDOWS_H +#include + +#include + +#if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500) + #define HMONITOR_DECLARED + DECLARE_HANDLE(HMONITOR); +#endif + +#define D3DAPI WINAPI + +/* + * Interface IID's + */ +#if defined( _WIN32 ) && !defined( _NO_COM) + +/* IID_IDirect3D9 */ +/* {81BDCBCA-64D4-426d-AE8D-AD0147F4275C} */ +DEFINE_GUID(IID_IDirect3D9, 0x81bdcbca, 0x64d4, 0x426d, 0xae, 0x8d, 0xad, 0x1, 0x47, 0xf4, 0x27, 0x5c); + +/* IID_IDirect3DDevice9 */ +// {D0223B96-BF7A-43fd-92BD-A43B0D82B9EB} */ +DEFINE_GUID(IID_IDirect3DDevice9, 0xd0223b96, 0xbf7a, 0x43fd, 0x92, 0xbd, 0xa4, 0x3b, 0xd, 0x82, 0xb9, 0xeb); + +/* IID_IDirect3DResource9 */ +// {05EEC05D-8F7D-4362-B999-D1BAF357C704} +DEFINE_GUID(IID_IDirect3DResource9, 0x5eec05d, 0x8f7d, 0x4362, 0xb9, 0x99, 0xd1, 0xba, 0xf3, 0x57, 0xc7, 0x4); + +/* IID_IDirect3DBaseTexture9 */ +/* {580CA87E-1D3C-4d54-991D-B7D3E3C298CE} */ +DEFINE_GUID(IID_IDirect3DBaseTexture9, 0x580ca87e, 0x1d3c, 0x4d54, 0x99, 0x1d, 0xb7, 0xd3, 0xe3, 0xc2, 0x98, 0xce); + +/* IID_IDirect3DTexture9 */ +/* {85C31227-3DE5-4f00-9B3A-F11AC38C18B5} */ +DEFINE_GUID(IID_IDirect3DTexture9, 0x85c31227, 0x3de5, 0x4f00, 0x9b, 0x3a, 0xf1, 0x1a, 0xc3, 0x8c, 0x18, 0xb5); + +/* IID_IDirect3DCubeTexture9 */ +/* {FFF32F81-D953-473a-9223-93D652ABA93F} */ +DEFINE_GUID(IID_IDirect3DCubeTexture9, 0xfff32f81, 0xd953, 0x473a, 0x92, 0x23, 0x93, 0xd6, 0x52, 0xab, 0xa9, 0x3f); + +/* IID_IDirect3DVolumeTexture9 */ +/* {2518526C-E789-4111-A7B9-47EF328D13E6} */ +DEFINE_GUID(IID_IDirect3DVolumeTexture9, 0x2518526c, 0xe789, 0x4111, 0xa7, 0xb9, 0x47, 0xef, 0x32, 0x8d, 0x13, 0xe6); + +/* IID_IDirect3DVertexBuffer9 */ +/* {B64BB1B5-FD70-4df6-BF91-19D0A12455E3} */ +DEFINE_GUID(IID_IDirect3DVertexBuffer9, 0xb64bb1b5, 0xfd70, 0x4df6, 0xbf, 0x91, 0x19, 0xd0, 0xa1, 0x24, 0x55, 0xe3); + +/* IID_IDirect3DIndexBuffer9 */ +/* {7C9DD65E-D3F7-4529-ACEE-785830ACDE35} */ +DEFINE_GUID(IID_IDirect3DIndexBuffer9, 0x7c9dd65e, 0xd3f7, 0x4529, 0xac, 0xee, 0x78, 0x58, 0x30, 0xac, 0xde, 0x35); + +/* IID_IDirect3DSurface9 */ +/* {0CFBAF3A-9FF6-429a-99B3-A2796AF8B89B} */ +DEFINE_GUID(IID_IDirect3DSurface9, 0xcfbaf3a, 0x9ff6, 0x429a, 0x99, 0xb3, 0xa2, 0x79, 0x6a, 0xf8, 0xb8, 0x9b); + +/* IID_IDirect3DVolume9 */ +/* {24F416E6-1F67-4aa7-B88E-D33F6F3128A1} */ +DEFINE_GUID(IID_IDirect3DVolume9, 0x24f416e6, 0x1f67, 0x4aa7, 0xb8, 0x8e, 0xd3, 0x3f, 0x6f, 0x31, 0x28, 0xa1); + +/* IID_IDirect3DSwapChain9 */ +/* {794950F2-ADFC-458a-905E-10A10B0B503B} */ +DEFINE_GUID(IID_IDirect3DSwapChain9, 0x794950f2, 0xadfc, 0x458a, 0x90, 0x5e, 0x10, 0xa1, 0xb, 0xb, 0x50, 0x3b); + +/* IID_IDirect3DVertexDeclaration9 */ +/* {DD13C59C-36FA-4098-A8FB-C7ED39DC8546} */ +DEFINE_GUID(IID_IDirect3DVertexDeclaration9, 0xdd13c59c, 0x36fa, 0x4098, 0xa8, 0xfb, 0xc7, 0xed, 0x39, 0xdc, 0x85, 0x46); + +/* IID_IDirect3DVertexShader9 */ +/* {EFC5557E-6265-4613-8A94-43857889EB36} */ +DEFINE_GUID(IID_IDirect3DVertexShader9, 0xefc5557e, 0x6265, 0x4613, 0x8a, 0x94, 0x43, 0x85, 0x78, 0x89, 0xeb, 0x36); + +/* IID_IDirect3DPixelShader9 */ +/* {6D3BDBDC-5B02-4415-B852-CE5E8BCCB289} */ +DEFINE_GUID(IID_IDirect3DPixelShader9, 0x6d3bdbdc, 0x5b02, 0x4415, 0xb8, 0x52, 0xce, 0x5e, 0x8b, 0xcc, 0xb2, 0x89); + +/* IID_IDirect3DStateBlock9 */ +/* {B07C4FE5-310D-4ba8-A23C-4F0F206F218B} */ +DEFINE_GUID(IID_IDirect3DStateBlock9, 0xb07c4fe5, 0x310d, 0x4ba8, 0xa2, 0x3c, 0x4f, 0xf, 0x20, 0x6f, 0x21, 0x8b); + +/* IID_IDirect3DQuery9 */ +/* {d9771460-a695-4f26-bbd3-27b840b541cc} */ +DEFINE_GUID(IID_IDirect3DQuery9, 0xd9771460, 0xa695, 0x4f26, 0xbb, 0xd3, 0x27, 0xb8, 0x40, 0xb5, 0x41, 0xcc); + + +/* IID_HelperName */ +/* {E4A36723-FDFE-4b22-B146-3C04C07F4CC8} */ +DEFINE_GUID(IID_HelperName, 0xe4a36723, 0xfdfe, 0x4b22, 0xb1, 0x46, 0x3c, 0x4, 0xc0, 0x7f, 0x4c, 0xc8); + +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + +/* IID_IDirect3D9Ex */ +/* {02177241-69FC-400C-8FF1-93A44DF6861D} */ +DEFINE_GUID(IID_IDirect3D9Ex, 0x02177241, 0x69FC, 0x400C, 0x8F, 0xF1, 0x93, 0xA4, 0x4D, 0xF6, 0x86, 0x1D); + +/* IID_IDirect3DDevice9Ex */ +// {B18B10CE-2649-405a-870F-95F777D4313A} +DEFINE_GUID(IID_IDirect3DDevice9Ex, 0xb18b10ce, 0x2649, 0x405a, 0x87, 0xf, 0x95, 0xf7, 0x77, 0xd4, 0x31, 0x3a); + +/* IID_IDirect3DSwapChain9Ex */ +/* {91886CAF-1C3D-4d2e-A0AB-3E4C7D8D3303} */ +DEFINE_GUID(IID_IDirect3DSwapChain9Ex, 0x91886caf, 0x1c3d, 0x4d2e, 0xa0, 0xab, 0x3e, 0x4c, 0x7d, 0x8d, 0x33, 0x3); + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + +#endif + +#ifdef __cplusplus + +#ifndef DECLSPEC_UUID +#if _MSC_VER >= 1100 +#define DECLSPEC_UUID(x) __declspec(uuid(x)) +#else +#define DECLSPEC_UUID(x) +#endif +#endif + +interface DECLSPEC_UUID("81BDCBCA-64D4-426d-AE8D-AD0147F4275C") IDirect3D9; +interface DECLSPEC_UUID("D0223B96-BF7A-43fd-92BD-A43B0D82B9EB") IDirect3DDevice9; + +interface DECLSPEC_UUID("B07C4FE5-310D-4ba8-A23C-4F0F206F218B") IDirect3DStateBlock9; +interface DECLSPEC_UUID("05EEC05D-8F7D-4362-B999-D1BAF357C704") IDirect3DResource9; +interface DECLSPEC_UUID("DD13C59C-36FA-4098-A8FB-C7ED39DC8546") IDirect3DVertexDeclaration9; +interface DECLSPEC_UUID("EFC5557E-6265-4613-8A94-43857889EB36") IDirect3DVertexShader9; +interface DECLSPEC_UUID("6D3BDBDC-5B02-4415-B852-CE5E8BCCB289") IDirect3DPixelShader9; +interface DECLSPEC_UUID("580CA87E-1D3C-4d54-991D-B7D3E3C298CE") IDirect3DBaseTexture9; +interface DECLSPEC_UUID("85C31227-3DE5-4f00-9B3A-F11AC38C18B5") IDirect3DTexture9; +interface DECLSPEC_UUID("2518526C-E789-4111-A7B9-47EF328D13E6") IDirect3DVolumeTexture9; +interface DECLSPEC_UUID("FFF32F81-D953-473a-9223-93D652ABA93F") IDirect3DCubeTexture9; + +interface DECLSPEC_UUID("B64BB1B5-FD70-4df6-BF91-19D0A12455E3") IDirect3DVertexBuffer9; +interface DECLSPEC_UUID("7C9DD65E-D3F7-4529-ACEE-785830ACDE35") IDirect3DIndexBuffer9; + +interface DECLSPEC_UUID("0CFBAF3A-9FF6-429a-99B3-A2796AF8B89B") IDirect3DSurface9; +interface DECLSPEC_UUID("24F416E6-1F67-4aa7-B88E-D33F6F3128A1") IDirect3DVolume9; + +interface DECLSPEC_UUID("794950F2-ADFC-458a-905E-10A10B0B503B") IDirect3DSwapChain9; +interface DECLSPEC_UUID("d9771460-a695-4f26-bbd3-27b840b541cc") IDirect3DQuery9; + + +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + +interface DECLSPEC_UUID("02177241-69FC-400C-8FF1-93A44DF6861D") IDirect3D9Ex; +interface DECLSPEC_UUID("B18B10CE-2649-405a-870F-95F777D4313A") IDirect3DDevice9Ex; +interface DECLSPEC_UUID("91886CAF-1C3D-4d2e-A0AB-3E4C7D8D3303") IDirect3DSwapChain9Ex; + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + +#if defined(_COM_SMARTPTR_TYPEDEF) +_COM_SMARTPTR_TYPEDEF(IDirect3D9, __uuidof(IDirect3D9)); +_COM_SMARTPTR_TYPEDEF(IDirect3DDevice9, __uuidof(IDirect3DDevice9)); + +_COM_SMARTPTR_TYPEDEF(IDirect3DStateBlock9, __uuidof(IDirect3DStateBlock9)); +_COM_SMARTPTR_TYPEDEF(IDirect3DResource9, __uuidof(IDirect3DResource9)); +_COM_SMARTPTR_TYPEDEF(IDirect3DVertexDeclaration9, __uuidof(IDirect3DVertexDeclaration9)); +_COM_SMARTPTR_TYPEDEF(IDirect3DVertexShader9, __uuidof(IDirect3DVertexShader9)); +_COM_SMARTPTR_TYPEDEF(IDirect3DPixelShader9, __uuidof(IDirect3DPixelShader9)); +_COM_SMARTPTR_TYPEDEF(IDirect3DBaseTexture9, __uuidof(IDirect3DBaseTexture9)); +_COM_SMARTPTR_TYPEDEF(IDirect3DTexture9, __uuidof(IDirect3DTexture9)); +_COM_SMARTPTR_TYPEDEF(IDirect3DVolumeTexture9, __uuidof(IDirect3DVolumeTexture9)); +_COM_SMARTPTR_TYPEDEF(IDirect3DCubeTexture9, __uuidof(IDirect3DCubeTexture9)); + +_COM_SMARTPTR_TYPEDEF(IDirect3DVertexBuffer9, __uuidof(IDirect3DVertexBuffer9)); +_COM_SMARTPTR_TYPEDEF(IDirect3DIndexBuffer9, __uuidof(IDirect3DIndexBuffer9)); + +_COM_SMARTPTR_TYPEDEF(IDirect3DSurface9, __uuidof(IDirect3DSurface9)); +_COM_SMARTPTR_TYPEDEF(IDirect3DVolume9, __uuidof(IDirect3DVolume9)); + +_COM_SMARTPTR_TYPEDEF(IDirect3DSwapChain9, __uuidof(IDirect3DSwapChain9)); +_COM_SMARTPTR_TYPEDEF(IDirect3DQuery9, __uuidof(IDirect3DQuery9)); + + +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + +_COM_SMARTPTR_TYPEDEF(IDirect3D9Ex, __uuidof(IDirect3D9Ex)); +_COM_SMARTPTR_TYPEDEF(IDirect3DDevice9Ex, __uuidof(IDirect3DDevice9Ex)); +_COM_SMARTPTR_TYPEDEF(IDirect3DSwapChain9Ex, __uuidof(IDirect3DSwapChain9Ex)); + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + +#endif + +#endif + + +typedef interface IDirect3D9 IDirect3D9; +typedef interface IDirect3DDevice9 IDirect3DDevice9; +typedef interface IDirect3DStateBlock9 IDirect3DStateBlock9; +typedef interface IDirect3DVertexDeclaration9 IDirect3DVertexDeclaration9; +typedef interface IDirect3DVertexShader9 IDirect3DVertexShader9; +typedef interface IDirect3DPixelShader9 IDirect3DPixelShader9; +typedef interface IDirect3DResource9 IDirect3DResource9; +typedef interface IDirect3DBaseTexture9 IDirect3DBaseTexture9; +typedef interface IDirect3DTexture9 IDirect3DTexture9; +typedef interface IDirect3DVolumeTexture9 IDirect3DVolumeTexture9; +typedef interface IDirect3DCubeTexture9 IDirect3DCubeTexture9; +typedef interface IDirect3DVertexBuffer9 IDirect3DVertexBuffer9; +typedef interface IDirect3DIndexBuffer9 IDirect3DIndexBuffer9; +typedef interface IDirect3DSurface9 IDirect3DSurface9; +typedef interface IDirect3DVolume9 IDirect3DVolume9; +typedef interface IDirect3DSwapChain9 IDirect3DSwapChain9; +typedef interface IDirect3DQuery9 IDirect3DQuery9; + + +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + +typedef interface IDirect3D9Ex IDirect3D9Ex; +typedef interface IDirect3DDevice9Ex IDirect3DDevice9Ex; +typedef interface IDirect3DSwapChain9Ex IDirect3DSwapChain9Ex; + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + +#include "d3d9types.h" +#include "d3d9caps.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * DLL Function for creating a Direct3D9 object. This object supports + * enumeration and allows the creation of Direct3DDevice9 objects. + * Pass the value of the constant D3D_SDK_VERSION to this function, so + * that the run-time can validate that your application was compiled + * against the right headers. + */ + +IDirect3D9 * WINAPI Direct3DCreate9(UINT SDKVersion); + +/* + * Stubs for graphics profiling. + */ + +int WINAPI D3DPERF_BeginEvent( D3DCOLOR col, LPCWSTR wszName ); +int WINAPI D3DPERF_EndEvent( void ); +void WINAPI D3DPERF_SetMarker( D3DCOLOR col, LPCWSTR wszName ); +void WINAPI D3DPERF_SetRegion( D3DCOLOR col, LPCWSTR wszName ); +BOOL WINAPI D3DPERF_QueryRepeatFrame( void ); + +void WINAPI D3DPERF_SetOptions( DWORD dwOptions ); +DWORD WINAPI D3DPERF_GetStatus( void ); + +/* + * Direct3D interfaces + */ + + + + + + +#undef INTERFACE +#define INTERFACE IDirect3D9 + +DECLARE_INTERFACE_(IDirect3D9, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3D9 methods ***/ + STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction) PURE; + STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE; + STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier) PURE; + STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter,D3DFORMAT Format) PURE; + STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode) PURE; + STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT Adapter,D3DDISPLAYMODE* pMode) PURE; // 0x20 + STDMETHOD(CheckDeviceType)(THIS_ UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed) PURE; + STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat) PURE; + STDMETHOD(CheckDeviceMultiSampleType)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels) PURE; + STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat) PURE; + STDMETHOD(CheckDeviceFormatConversion)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SourceFormat,D3DFORMAT TargetFormat) PURE; + STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps) PURE; + STDMETHOD_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter) PURE; + STDMETHOD(CreateDevice)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface) PURE; + + #ifdef D3D_DEBUG_INFO + LPCWSTR Version; + #endif +}; + +typedef struct IDirect3D9 *LPDIRECT3D9, *PDIRECT3D9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3D9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3D9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3D9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3D9_RegisterSoftwareDevice(p,a) (p)->lpVtbl->RegisterSoftwareDevice(p,a) +#define IDirect3D9_GetAdapterCount(p) (p)->lpVtbl->GetAdapterCount(p) +#define IDirect3D9_GetAdapterIdentifier(p,a,b,c) (p)->lpVtbl->GetAdapterIdentifier(p,a,b,c) +#define IDirect3D9_GetAdapterModeCount(p,a,b) (p)->lpVtbl->GetAdapterModeCount(p,a,b) +#define IDirect3D9_EnumAdapterModes(p,a,b,c,d) (p)->lpVtbl->EnumAdapterModes(p,a,b,c,d) +#define IDirect3D9_GetAdapterDisplayMode(p,a,b) (p)->lpVtbl->GetAdapterDisplayMode(p,a,b) +#define IDirect3D9_CheckDeviceType(p,a,b,c,d,e) (p)->lpVtbl->CheckDeviceType(p,a,b,c,d,e) +#define IDirect3D9_CheckDeviceFormat(p,a,b,c,d,e,f) (p)->lpVtbl->CheckDeviceFormat(p,a,b,c,d,e,f) +#define IDirect3D9_CheckDeviceMultiSampleType(p,a,b,c,d,e,f) (p)->lpVtbl->CheckDeviceMultiSampleType(p,a,b,c,d,e,f) +#define IDirect3D9_CheckDepthStencilMatch(p,a,b,c,d,e) (p)->lpVtbl->CheckDepthStencilMatch(p,a,b,c,d,e) +#define IDirect3D9_CheckDeviceFormatConversion(p,a,b,c,d) (p)->lpVtbl->CheckDeviceFormatConversion(p,a,b,c,d) +#define IDirect3D9_GetDeviceCaps(p,a,b,c) (p)->lpVtbl->GetDeviceCaps(p,a,b,c) +#define IDirect3D9_GetAdapterMonitor(p,a) (p)->lpVtbl->GetAdapterMonitor(p,a) +#define IDirect3D9_CreateDevice(p,a,b,c,d,e,f) (p)->lpVtbl->CreateDevice(p,a,b,c,d,e,f) +#else +#define IDirect3D9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3D9_AddRef(p) (p)->AddRef() +#define IDirect3D9_Release(p) (p)->Release() +#define IDirect3D9_RegisterSoftwareDevice(p,a) (p)->RegisterSoftwareDevice(a) +#define IDirect3D9_GetAdapterCount(p) (p)->GetAdapterCount() +#define IDirect3D9_GetAdapterIdentifier(p,a,b,c) (p)->GetAdapterIdentifier(a,b,c) +#define IDirect3D9_GetAdapterModeCount(p,a,b) (p)->GetAdapterModeCount(a,b) +#define IDirect3D9_EnumAdapterModes(p,a,b,c,d) (p)->EnumAdapterModes(a,b,c,d) +#define IDirect3D9_GetAdapterDisplayMode(p,a,b) (p)->GetAdapterDisplayMode(a,b) +#define IDirect3D9_CheckDeviceType(p,a,b,c,d,e) (p)->CheckDeviceType(a,b,c,d,e) +#define IDirect3D9_CheckDeviceFormat(p,a,b,c,d,e,f) (p)->CheckDeviceFormat(a,b,c,d,e,f) +#define IDirect3D9_CheckDeviceMultiSampleType(p,a,b,c,d,e,f) (p)->CheckDeviceMultiSampleType(a,b,c,d,e,f) +#define IDirect3D9_CheckDepthStencilMatch(p,a,b,c,d,e) (p)->CheckDepthStencilMatch(a,b,c,d,e) +#define IDirect3D9_CheckDeviceFormatConversion(p,a,b,c,d) (p)->CheckDeviceFormatConversion(a,b,c,d) +#define IDirect3D9_GetDeviceCaps(p,a,b,c) (p)->GetDeviceCaps(a,b,c) +#define IDirect3D9_GetAdapterMonitor(p,a) (p)->GetAdapterMonitor(a) +#define IDirect3D9_CreateDevice(p,a,b,c,d,e,f) (p)->CreateDevice(a,b,c,d,e,f) +#endif + + + + + + + +/* SwapChain */ + + + + + + + + + + + + + + + +#undef INTERFACE +#define INTERFACE IDirect3DDevice9 + +DECLARE_INTERFACE_(IDirect3DDevice9, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DDevice9 methods ***/ + STDMETHOD(TestCooperativeLevel)(THIS) PURE; + STDMETHOD_(UINT, GetAvailableTextureMem)(THIS) PURE; // 0x10 + STDMETHOD(EvictManagedResources)(THIS) PURE; + STDMETHOD(GetDirect3D)(THIS_ IDirect3D9** ppD3D9) PURE; + STDMETHOD(GetDeviceCaps)(THIS_ D3DCAPS9* pCaps) PURE; + STDMETHOD(GetDisplayMode)(THIS_ UINT iSwapChain,D3DDISPLAYMODE* pMode) PURE; // 0x20 + STDMETHOD(GetCreationParameters)(THIS_ D3DDEVICE_CREATION_PARAMETERS *pParameters) PURE; + STDMETHOD(SetCursorProperties)(THIS_ UINT XHotSpot,UINT YHotSpot,IDirect3DSurface9* pCursorBitmap) PURE; + STDMETHOD_(void, SetCursorPosition)(THIS_ int X,int Y,DWORD Flags) PURE; + STDMETHOD_(BOOL, ShowCursor)(THIS_ BOOL bShow) PURE; // 0x30 + STDMETHOD(CreateAdditionalSwapChain)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DSwapChain9** pSwapChain) PURE; + STDMETHOD(GetSwapChain)(THIS_ UINT iSwapChain,IDirect3DSwapChain9** pSwapChain) PURE; + STDMETHOD_(UINT, GetNumberOfSwapChains)(THIS) PURE; + STDMETHOD(Reset)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters) PURE; // 0x40 + STDMETHOD(Present)(THIS_ CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) PURE; + STDMETHOD(GetBackBuffer)(THIS_ UINT iSwapChain,UINT iBackBuffer,D3DBACKBUFFER_TYPE Type,IDirect3DSurface9** ppBackBuffer) PURE; + STDMETHOD(GetRasterStatus)(THIS_ UINT iSwapChain,D3DRASTER_STATUS* pRasterStatus) PURE; + STDMETHOD(SetDialogBoxMode)(THIS_ BOOL bEnableDialogs) PURE; // 0x50 + STDMETHOD_(void, SetGammaRamp)(THIS_ UINT iSwapChain,DWORD Flags,CONST D3DGAMMARAMP* pRamp) PURE; + STDMETHOD_(void, GetGammaRamp)(THIS_ UINT iSwapChain,D3DGAMMARAMP* pRamp) PURE; + STDMETHOD(CreateTexture)(THIS_ UINT Width,UINT Height,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture9** ppTexture,HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateVolumeTexture)(THIS_ UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture9** ppVolumeTexture,HANDLE* pSharedHandle) PURE; // 0x60 + STDMETHOD(CreateCubeTexture)(THIS_ UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture9** ppCubeTexture,HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateVertexBuffer)(THIS_ UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9** ppVertexBuffer,HANDLE* pSharedHandle) PURE; // 0x68 + STDMETHOD(CreateIndexBuffer)(THIS_ UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer9** ppIndexBuffer,HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateRenderTarget)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Lockable,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle) PURE; // 0x70 + STDMETHOD(CreateDepthStencilSurface)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Discard,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle) PURE; + STDMETHOD(UpdateSurface)(THIS_ IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestinationSurface,CONST POINT* pDestPoint) PURE; + STDMETHOD(UpdateTexture)(THIS_ IDirect3DBaseTexture9* pSourceTexture,IDirect3DBaseTexture9* pDestinationTexture) PURE; + STDMETHOD(GetRenderTargetData)(THIS_ IDirect3DSurface9* pRenderTarget,IDirect3DSurface9* pDestSurface) PURE; // 0x80 + STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain,IDirect3DSurface9* pDestSurface) PURE; + STDMETHOD(StretchRect)(THIS_ IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect,D3DTEXTUREFILTERTYPE Filter) PURE; + STDMETHOD(ColorFill)(THIS_ IDirect3DSurface9* pSurface,CONST RECT* pRect,D3DCOLOR color) PURE; // 0x8c + STDMETHOD(CreateOffscreenPlainSurface)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DPOOL Pool,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle) PURE; // 0x90 + STDMETHOD(SetRenderTarget)(THIS_ DWORD RenderTargetIndex,IDirect3DSurface9* pRenderTarget) PURE; + STDMETHOD(GetRenderTarget)(THIS_ DWORD RenderTargetIndex,IDirect3DSurface9** ppRenderTarget) PURE; + STDMETHOD(SetDepthStencilSurface)(THIS_ IDirect3DSurface9* pNewZStencil) PURE; + STDMETHOD(GetDepthStencilSurface)(THIS_ IDirect3DSurface9** ppZStencilSurface) PURE; // 0xa0 + STDMETHOD(BeginScene)(THIS) PURE; + STDMETHOD(EndScene)(THIS) PURE; + STDMETHOD(Clear)(THIS_ DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil) PURE; + STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) PURE; // 0xb0 + STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) PURE; // 0xB4 + STDMETHOD(MultiplyTransform)(THIS_ D3DTRANSFORMSTATETYPE,CONST D3DMATRIX*) PURE; + STDMETHOD(SetViewport)(THIS_ CONST D3DVIEWPORT9* pViewport) PURE; + STDMETHOD(GetViewport)(THIS_ D3DVIEWPORT9* pViewport) PURE; // 0xc0 + STDMETHOD(SetMaterial)(THIS_ CONST D3DMATERIAL9* pMaterial) PURE; + STDMETHOD(GetMaterial)(THIS_ D3DMATERIAL9* pMaterial) PURE; + STDMETHOD(SetLight)(THIS_ DWORD Index,CONST D3DLIGHT9*) PURE; + STDMETHOD(GetLight)(THIS_ DWORD Index,D3DLIGHT9*) PURE; // 0xd0 + STDMETHOD(LightEnable)(THIS_ DWORD Index,BOOL Enable) PURE; + STDMETHOD(GetLightEnable)(THIS_ DWORD Index,BOOL* pEnable) PURE; + STDMETHOD(SetClipPlane)(THIS_ DWORD Index,CONST float* pPlane) PURE; + STDMETHOD(GetClipPlane)(THIS_ DWORD Index,float* pPlane) PURE; // 0xe0 + STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE State,DWORD Value) PURE; + STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE State,DWORD* pValue) PURE; + STDMETHOD(CreateStateBlock)(THIS_ D3DSTATEBLOCKTYPE Type,IDirect3DStateBlock9** ppSB) PURE; + STDMETHOD(BeginStateBlock)(THIS) PURE; // 0xf0 + STDMETHOD(EndStateBlock)(THIS_ IDirect3DStateBlock9** ppSB) PURE; + STDMETHOD(SetClipStatus)(THIS_ CONST D3DCLIPSTATUS9* pClipStatus) PURE; + STDMETHOD(GetClipStatus)(THIS_ D3DCLIPSTATUS9* pClipStatus) PURE; + STDMETHOD(GetTexture)(THIS_ DWORD Stage,IDirect3DBaseTexture9** ppTexture) PURE; // 0x100 + STDMETHOD(SetTexture)(THIS_ DWORD Stage,IDirect3DBaseTexture9* pTexture) PURE; + STDMETHOD(GetTextureStageState)(THIS_ DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) PURE; + STDMETHOD(SetTextureStageState)(THIS_ DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value) PURE; + STDMETHOD(GetSamplerState)(THIS_ DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD* pValue) PURE; // 0x110 + STDMETHOD(SetSamplerState)(THIS_ DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD Value) PURE; // 0x114 + STDMETHOD(ValidateDevice)(THIS_ DWORD* pNumPasses) PURE; + STDMETHOD(SetPaletteEntries)(THIS_ UINT PaletteNumber,CONST PALETTEENTRY* pEntries) PURE; + STDMETHOD(GetPaletteEntries)(THIS_ UINT PaletteNumber,PALETTEENTRY* pEntries) PURE; // 0x120 + STDMETHOD(SetCurrentTexturePalette)(THIS_ UINT PaletteNumber) PURE; + STDMETHOD(GetCurrentTexturePalette)(THIS_ UINT *PaletteNumber) PURE; + STDMETHOD(SetScissorRect)(THIS_ CONST RECT* pRect) PURE; + STDMETHOD(GetScissorRect)(THIS_ RECT* pRect) PURE; // 0x130 + STDMETHOD(SetSoftwareVertexProcessing)(THIS_ BOOL bSoftware) PURE; + STDMETHOD_(BOOL, GetSoftwareVertexProcessing)(THIS) PURE; + STDMETHOD(SetNPatchMode)(THIS_ float nSegments) PURE; + STDMETHOD_(float, GetNPatchMode)(THIS) PURE; + STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount) PURE; + STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount) PURE; // 0x148 + STDMETHOD(DrawPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) PURE; + STDMETHOD(DrawIndexedPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertices,UINT PrimitiveCount,CONST void* pIndexData,D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) PURE; + STDMETHOD(ProcessVertices)(THIS_ UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer9* pDestBuffer,IDirect3DVertexDeclaration9* pVertexDecl,DWORD Flags) PURE; + STDMETHOD(CreateVertexDeclaration)(THIS_ CONST D3DVERTEXELEMENT9* pVertexElements,IDirect3DVertexDeclaration9** ppDecl) PURE; // 0x158 + STDMETHOD(SetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9* pDecl) PURE; + STDMETHOD(GetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9** ppDecl) PURE; // 0x160 + STDMETHOD(SetFVF)(THIS_ DWORD FVF) PURE; + STDMETHOD(GetFVF)(THIS_ DWORD* pFVF) PURE; + STDMETHOD(CreateVertexShader)(THIS_ CONST DWORD* pFunction,IDirect3DVertexShader9** ppShader) PURE; + STDMETHOD(SetVertexShader)(THIS_ IDirect3DVertexShader9* pShader) PURE; // 0x170 + STDMETHOD(GetVertexShader)(THIS_ IDirect3DVertexShader9** ppShader) PURE; + STDMETHOD(SetVertexShaderConstantF)(THIS_ UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) PURE; + STDMETHOD(GetVertexShaderConstantF)(THIS_ UINT StartRegister,float* pConstantData,UINT Vector4fCount) PURE; + STDMETHOD(SetVertexShaderConstantI)(THIS_ UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount) PURE; // 0x180 + STDMETHOD(GetVertexShaderConstantI)(THIS_ UINT StartRegister,int* pConstantData,UINT Vector4iCount) PURE; + STDMETHOD(SetVertexShaderConstantB)(THIS_ UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount) PURE; + STDMETHOD(GetVertexShaderConstantB)(THIS_ UINT StartRegister,BOOL* pConstantData,UINT BoolCount) PURE; + STDMETHOD(SetStreamSource)(THIS_ UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride) PURE; // 0x190 + STDMETHOD(GetStreamSource)(THIS_ UINT StreamNumber,IDirect3DVertexBuffer9** ppStreamData,UINT* pOffsetInBytes,UINT* pStride) PURE; + STDMETHOD(SetStreamSourceFreq)(THIS_ UINT StreamNumber,UINT Setting) PURE; + STDMETHOD(GetStreamSourceFreq)(THIS_ UINT StreamNumber,UINT* pSetting) PURE; + STDMETHOD(SetIndices)(THIS_ IDirect3DIndexBuffer9* pIndexData) PURE; + STDMETHOD(GetIndices)(THIS_ IDirect3DIndexBuffer9** ppIndexData) PURE; + STDMETHOD(CreatePixelShader)(THIS_ CONST DWORD* pFunction,IDirect3DPixelShader9** ppShader) PURE; + STDMETHOD(SetPixelShader)(THIS_ IDirect3DPixelShader9* pShader) PURE; + STDMETHOD(GetPixelShader)(THIS_ IDirect3DPixelShader9** ppShader) PURE; + STDMETHOD(SetPixelShaderConstantF)(THIS_ UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) PURE; + STDMETHOD(GetPixelShaderConstantF)(THIS_ UINT StartRegister,float* pConstantData,UINT Vector4fCount) PURE; + STDMETHOD(SetPixelShaderConstantI)(THIS_ UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount) PURE; + STDMETHOD(GetPixelShaderConstantI)(THIS_ UINT StartRegister,int* pConstantData,UINT Vector4iCount) PURE; + STDMETHOD(SetPixelShaderConstantB)(THIS_ UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount) PURE; + STDMETHOD(GetPixelShaderConstantB)(THIS_ UINT StartRegister,BOOL* pConstantData,UINT BoolCount) PURE; + STDMETHOD(DrawRectPatch)(THIS_ UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) PURE; + STDMETHOD(DrawTriPatch)(THIS_ UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) PURE; + STDMETHOD(DeletePatch)(THIS_ UINT Handle) PURE; + STDMETHOD(CreateQuery)(THIS_ D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery) PURE; + + #ifdef D3D_DEBUG_INFO + D3DDEVICE_CREATION_PARAMETERS CreationParameters; + D3DPRESENT_PARAMETERS PresentParameters; + D3DDISPLAYMODE DisplayMode; + D3DCAPS9 Caps; + + UINT AvailableTextureMem; + UINT SwapChains; + UINT Textures; + UINT VertexBuffers; + UINT IndexBuffers; + UINT VertexShaders; + UINT PixelShaders; + + D3DVIEWPORT9 Viewport; + D3DMATRIX ProjectionMatrix; + D3DMATRIX ViewMatrix; + D3DMATRIX WorldMatrix; + D3DMATRIX TextureMatrices[8]; + + DWORD FVF; + UINT VertexSize; + DWORD VertexShaderVersion; + DWORD PixelShaderVersion; + BOOL SoftwareVertexProcessing; + + D3DMATERIAL9 Material; + D3DLIGHT9 Lights[16]; + BOOL LightsEnabled[16]; + + D3DGAMMARAMP GammaRamp; + RECT ScissorRect; + BOOL DialogBoxMode; + #endif +}; + +typedef struct IDirect3DDevice9 *LPDIRECT3DDEVICE9, *PDIRECT3DDEVICE9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DDevice9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DDevice9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DDevice9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DDevice9_TestCooperativeLevel(p) (p)->lpVtbl->TestCooperativeLevel(p) +#define IDirect3DDevice9_GetAvailableTextureMem(p) (p)->lpVtbl->GetAvailableTextureMem(p) +#define IDirect3DDevice9_EvictManagedResources(p) (p)->lpVtbl->EvictManagedResources(p) +#define IDirect3DDevice9_GetDirect3D(p,a) (p)->lpVtbl->GetDirect3D(p,a) +#define IDirect3DDevice9_GetDeviceCaps(p,a) (p)->lpVtbl->GetDeviceCaps(p,a) +#define IDirect3DDevice9_GetDisplayMode(p,a,b) (p)->lpVtbl->GetDisplayMode(p,a,b) +#define IDirect3DDevice9_GetCreationParameters(p,a) (p)->lpVtbl->GetCreationParameters(p,a) +#define IDirect3DDevice9_SetCursorProperties(p,a,b,c) (p)->lpVtbl->SetCursorProperties(p,a,b,c) +#define IDirect3DDevice9_SetCursorPosition(p,a,b,c) (p)->lpVtbl->SetCursorPosition(p,a,b,c) +#define IDirect3DDevice9_ShowCursor(p,a) (p)->lpVtbl->ShowCursor(p,a) +#define IDirect3DDevice9_CreateAdditionalSwapChain(p,a,b) (p)->lpVtbl->CreateAdditionalSwapChain(p,a,b) +#define IDirect3DDevice9_GetSwapChain(p,a,b) (p)->lpVtbl->GetSwapChain(p,a,b) +#define IDirect3DDevice9_GetNumberOfSwapChains(p) (p)->lpVtbl->GetNumberOfSwapChains(p) +#define IDirect3DDevice9_Reset(p,a) (p)->lpVtbl->Reset(p,a) +#define IDirect3DDevice9_Present(p,a,b,c,d) (p)->lpVtbl->Present(p,a,b,c,d) +#define IDirect3DDevice9_GetBackBuffer(p,a,b,c,d) (p)->lpVtbl->GetBackBuffer(p,a,b,c,d) +#define IDirect3DDevice9_GetRasterStatus(p,a,b) (p)->lpVtbl->GetRasterStatus(p,a,b) +#define IDirect3DDevice9_SetDialogBoxMode(p,a) (p)->lpVtbl->SetDialogBoxMode(p,a) +#define IDirect3DDevice9_SetGammaRamp(p,a,b,c) (p)->lpVtbl->SetGammaRamp(p,a,b,c) +#define IDirect3DDevice9_GetGammaRamp(p,a,b) (p)->lpVtbl->GetGammaRamp(p,a,b) +#define IDirect3DDevice9_CreateTexture(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->CreateTexture(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9_CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i) (p)->lpVtbl->CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9_CreateCubeTexture(p,a,b,c,d,e,f,g) (p)->lpVtbl->CreateCubeTexture(p,a,b,c,d,e,f,g) +#define IDirect3DDevice9_CreateVertexBuffer(p,a,b,c,d,e,f) (p)->lpVtbl->CreateVertexBuffer(p,a,b,c,d,e,f) +#define IDirect3DDevice9_CreateIndexBuffer(p,a,b,c,d,e,f) (p)->lpVtbl->CreateIndexBuffer(p,a,b,c,d,e,f) +#define IDirect3DDevice9_CreateRenderTarget(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->CreateRenderTarget(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9_CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9_UpdateSurface(p,a,b,c,d) (p)->lpVtbl->UpdateSurface(p,a,b,c,d) +#define IDirect3DDevice9_UpdateTexture(p,a,b) (p)->lpVtbl->UpdateTexture(p,a,b) +#define IDirect3DDevice9_GetRenderTargetData(p,a,b) (p)->lpVtbl->GetRenderTargetData(p,a,b) +#define IDirect3DDevice9_GetFrontBufferData(p,a,b) (p)->lpVtbl->GetFrontBufferData(p,a,b) +#define IDirect3DDevice9_StretchRect(p,a,b,c,d,e) (p)->lpVtbl->StretchRect(p,a,b,c,d,e) +#define IDirect3DDevice9_ColorFill(p,a,b,c) (p)->lpVtbl->ColorFill(p,a,b,c) +#define IDirect3DDevice9_CreateOffscreenPlainSurface(p,a,b,c,d,e,f) (p)->lpVtbl->CreateOffscreenPlainSurface(p,a,b,c,d,e,f) +#define IDirect3DDevice9_SetRenderTarget(p,a,b) (p)->lpVtbl->SetRenderTarget(p,a,b) +#define IDirect3DDevice9_GetRenderTarget(p,a,b) (p)->lpVtbl->GetRenderTarget(p,a,b) +#define IDirect3DDevice9_SetDepthStencilSurface(p,a) (p)->lpVtbl->SetDepthStencilSurface(p,a) +#define IDirect3DDevice9_GetDepthStencilSurface(p,a) (p)->lpVtbl->GetDepthStencilSurface(p,a) +#define IDirect3DDevice9_BeginScene(p) (p)->lpVtbl->BeginScene(p) +#define IDirect3DDevice9_EndScene(p) (p)->lpVtbl->EndScene(p) +#define IDirect3DDevice9_Clear(p,a,b,c,d,e,f) (p)->lpVtbl->Clear(p,a,b,c,d,e,f) +#define IDirect3DDevice9_SetTransform(p,a,b) (p)->lpVtbl->SetTransform(p,a,b) +#define IDirect3DDevice9_GetTransform(p,a,b) (p)->lpVtbl->GetTransform(p,a,b) +#define IDirect3DDevice9_MultiplyTransform(p,a,b) (p)->lpVtbl->MultiplyTransform(p,a,b) +#define IDirect3DDevice9_SetViewport(p,a) (p)->lpVtbl->SetViewport(p,a) +#define IDirect3DDevice9_GetViewport(p,a) (p)->lpVtbl->GetViewport(p,a) +#define IDirect3DDevice9_SetMaterial(p,a) (p)->lpVtbl->SetMaterial(p,a) +#define IDirect3DDevice9_GetMaterial(p,a) (p)->lpVtbl->GetMaterial(p,a) +#define IDirect3DDevice9_SetLight(p,a,b) (p)->lpVtbl->SetLight(p,a,b) +#define IDirect3DDevice9_GetLight(p,a,b) (p)->lpVtbl->GetLight(p,a,b) +#define IDirect3DDevice9_LightEnable(p,a,b) (p)->lpVtbl->LightEnable(p,a,b) +#define IDirect3DDevice9_GetLightEnable(p,a,b) (p)->lpVtbl->GetLightEnable(p,a,b) +#define IDirect3DDevice9_SetClipPlane(p,a,b) (p)->lpVtbl->SetClipPlane(p,a,b) +#define IDirect3DDevice9_GetClipPlane(p,a,b) (p)->lpVtbl->GetClipPlane(p,a,b) +#define IDirect3DDevice9_SetRenderState(p,a,b) (p)->lpVtbl->SetRenderState(p,a,b) +#define IDirect3DDevice9_GetRenderState(p,a,b) (p)->lpVtbl->GetRenderState(p,a,b) +#define IDirect3DDevice9_CreateStateBlock(p,a,b) (p)->lpVtbl->CreateStateBlock(p,a,b) +#define IDirect3DDevice9_BeginStateBlock(p) (p)->lpVtbl->BeginStateBlock(p) +#define IDirect3DDevice9_EndStateBlock(p,a) (p)->lpVtbl->EndStateBlock(p,a) +#define IDirect3DDevice9_SetClipStatus(p,a) (p)->lpVtbl->SetClipStatus(p,a) +#define IDirect3DDevice9_GetClipStatus(p,a) (p)->lpVtbl->GetClipStatus(p,a) +#define IDirect3DDevice9_GetTexture(p,a,b) (p)->lpVtbl->GetTexture(p,a,b) +#define IDirect3DDevice9_SetTexture(p,a,b) (p)->lpVtbl->SetTexture(p,a,b) +#define IDirect3DDevice9_GetTextureStageState(p,a,b,c) (p)->lpVtbl->GetTextureStageState(p,a,b,c) +#define IDirect3DDevice9_SetTextureStageState(p,a,b,c) (p)->lpVtbl->SetTextureStageState(p,a,b,c) +#define IDirect3DDevice9_GetSamplerState(p,a,b,c) (p)->lpVtbl->GetSamplerState(p,a,b,c) +#define IDirect3DDevice9_SetSamplerState(p,a,b,c) (p)->lpVtbl->SetSamplerState(p,a,b,c) +#define IDirect3DDevice9_ValidateDevice(p,a) (p)->lpVtbl->ValidateDevice(p,a) +#define IDirect3DDevice9_SetPaletteEntries(p,a,b) (p)->lpVtbl->SetPaletteEntries(p,a,b) +#define IDirect3DDevice9_GetPaletteEntries(p,a,b) (p)->lpVtbl->GetPaletteEntries(p,a,b) +#define IDirect3DDevice9_SetCurrentTexturePalette(p,a) (p)->lpVtbl->SetCurrentTexturePalette(p,a) +#define IDirect3DDevice9_GetCurrentTexturePalette(p,a) (p)->lpVtbl->GetCurrentTexturePalette(p,a) +#define IDirect3DDevice9_SetScissorRect(p,a) (p)->lpVtbl->SetScissorRect(p,a) +#define IDirect3DDevice9_GetScissorRect(p,a) (p)->lpVtbl->GetScissorRect(p,a) +#define IDirect3DDevice9_SetSoftwareVertexProcessing(p,a) (p)->lpVtbl->SetSoftwareVertexProcessing(p,a) +#define IDirect3DDevice9_GetSoftwareVertexProcessing(p) (p)->lpVtbl->GetSoftwareVertexProcessing(p) +#define IDirect3DDevice9_SetNPatchMode(p,a) (p)->lpVtbl->SetNPatchMode(p,a) +#define IDirect3DDevice9_GetNPatchMode(p) (p)->lpVtbl->GetNPatchMode(p) +#define IDirect3DDevice9_DrawPrimitive(p,a,b,c) (p)->lpVtbl->DrawPrimitive(p,a,b,c) +#define IDirect3DDevice9_DrawIndexedPrimitive(p,a,b,c,d,e,f) (p)->lpVtbl->DrawIndexedPrimitive(p,a,b,c,d,e,f) +#define IDirect3DDevice9_DrawPrimitiveUP(p,a,b,c,d) (p)->lpVtbl->DrawPrimitiveUP(p,a,b,c,d) +#define IDirect3DDevice9_DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9_ProcessVertices(p,a,b,c,d,e,f) (p)->lpVtbl->ProcessVertices(p,a,b,c,d,e,f) +#define IDirect3DDevice9_CreateVertexDeclaration(p,a,b) (p)->lpVtbl->CreateVertexDeclaration(p,a,b) +#define IDirect3DDevice9_SetVertexDeclaration(p,a) (p)->lpVtbl->SetVertexDeclaration(p,a) +#define IDirect3DDevice9_GetVertexDeclaration(p,a) (p)->lpVtbl->GetVertexDeclaration(p,a) +#define IDirect3DDevice9_SetFVF(p,a) (p)->lpVtbl->SetFVF(p,a) +#define IDirect3DDevice9_GetFVF(p,a) (p)->lpVtbl->GetFVF(p,a) +#define IDirect3DDevice9_CreateVertexShader(p,a,b) (p)->lpVtbl->CreateVertexShader(p,a,b) +#define IDirect3DDevice9_SetVertexShader(p,a) (p)->lpVtbl->SetVertexShader(p,a) +#define IDirect3DDevice9_GetVertexShader(p,a) (p)->lpVtbl->GetVertexShader(p,a) +#define IDirect3DDevice9_SetVertexShaderConstantF(p,a,b,c) (p)->lpVtbl->SetVertexShaderConstantF(p,a,b,c) +#define IDirect3DDevice9_GetVertexShaderConstantF(p,a,b,c) (p)->lpVtbl->GetVertexShaderConstantF(p,a,b,c) +#define IDirect3DDevice9_SetVertexShaderConstantI(p,a,b,c) (p)->lpVtbl->SetVertexShaderConstantI(p,a,b,c) +#define IDirect3DDevice9_GetVertexShaderConstantI(p,a,b,c) (p)->lpVtbl->GetVertexShaderConstantI(p,a,b,c) +#define IDirect3DDevice9_SetVertexShaderConstantB(p,a,b,c) (p)->lpVtbl->SetVertexShaderConstantB(p,a,b,c) +#define IDirect3DDevice9_GetVertexShaderConstantB(p,a,b,c) (p)->lpVtbl->GetVertexShaderConstantB(p,a,b,c) +#define IDirect3DDevice9_SetStreamSource(p,a,b,c,d) (p)->lpVtbl->SetStreamSource(p,a,b,c,d) +#define IDirect3DDevice9_GetStreamSource(p,a,b,c,d) (p)->lpVtbl->GetStreamSource(p,a,b,c,d) +#define IDirect3DDevice9_SetStreamSourceFreq(p,a,b) (p)->lpVtbl->SetStreamSourceFreq(p,a,b) +#define IDirect3DDevice9_GetStreamSourceFreq(p,a,b) (p)->lpVtbl->GetStreamSourceFreq(p,a,b) +#define IDirect3DDevice9_SetIndices(p,a) (p)->lpVtbl->SetIndices(p,a) +#define IDirect3DDevice9_GetIndices(p,a) (p)->lpVtbl->GetIndices(p,a) +#define IDirect3DDevice9_CreatePixelShader(p,a,b) (p)->lpVtbl->CreatePixelShader(p,a,b) +#define IDirect3DDevice9_SetPixelShader(p,a) (p)->lpVtbl->SetPixelShader(p,a) +#define IDirect3DDevice9_GetPixelShader(p,a) (p)->lpVtbl->GetPixelShader(p,a) +#define IDirect3DDevice9_SetPixelShaderConstantF(p,a,b,c) (p)->lpVtbl->SetPixelShaderConstantF(p,a,b,c) +#define IDirect3DDevice9_GetPixelShaderConstantF(p,a,b,c) (p)->lpVtbl->GetPixelShaderConstantF(p,a,b,c) +#define IDirect3DDevice9_SetPixelShaderConstantI(p,a,b,c) (p)->lpVtbl->SetPixelShaderConstantI(p,a,b,c) +#define IDirect3DDevice9_GetPixelShaderConstantI(p,a,b,c) (p)->lpVtbl->GetPixelShaderConstantI(p,a,b,c) +#define IDirect3DDevice9_SetPixelShaderConstantB(p,a,b,c) (p)->lpVtbl->SetPixelShaderConstantB(p,a,b,c) +#define IDirect3DDevice9_GetPixelShaderConstantB(p,a,b,c) (p)->lpVtbl->GetPixelShaderConstantB(p,a,b,c) +#define IDirect3DDevice9_DrawRectPatch(p,a,b,c) (p)->lpVtbl->DrawRectPatch(p,a,b,c) +#define IDirect3DDevice9_DrawTriPatch(p,a,b,c) (p)->lpVtbl->DrawTriPatch(p,a,b,c) +#define IDirect3DDevice9_DeletePatch(p,a) (p)->lpVtbl->DeletePatch(p,a) +#define IDirect3DDevice9_CreateQuery(p,a,b) (p)->lpVtbl->CreateQuery(p,a,b) +#else +#define IDirect3DDevice9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DDevice9_AddRef(p) (p)->AddRef() +#define IDirect3DDevice9_Release(p) (p)->Release() +#define IDirect3DDevice9_TestCooperativeLevel(p) (p)->TestCooperativeLevel() +#define IDirect3DDevice9_GetAvailableTextureMem(p) (p)->GetAvailableTextureMem() +#define IDirect3DDevice9_EvictManagedResources(p) (p)->EvictManagedResources() +#define IDirect3DDevice9_GetDirect3D(p,a) (p)->GetDirect3D(a) +#define IDirect3DDevice9_GetDeviceCaps(p,a) (p)->GetDeviceCaps(a) +#define IDirect3DDevice9_GetDisplayMode(p,a,b) (p)->GetDisplayMode(a,b) +#define IDirect3DDevice9_GetCreationParameters(p,a) (p)->GetCreationParameters(a) +#define IDirect3DDevice9_SetCursorProperties(p,a,b,c) (p)->SetCursorProperties(a,b,c) +#define IDirect3DDevice9_SetCursorPosition(p,a,b,c) (p)->SetCursorPosition(a,b,c) +#define IDirect3DDevice9_ShowCursor(p,a) (p)->ShowCursor(a) +#define IDirect3DDevice9_CreateAdditionalSwapChain(p,a,b) (p)->CreateAdditionalSwapChain(a,b) +#define IDirect3DDevice9_GetSwapChain(p,a,b) (p)->GetSwapChain(a,b) +#define IDirect3DDevice9_GetNumberOfSwapChains(p) (p)->GetNumberOfSwapChains() +#define IDirect3DDevice9_Reset(p,a) (p)->Reset(a) +#define IDirect3DDevice9_Present(p,a,b,c,d) (p)->Present(a,b,c,d) +#define IDirect3DDevice9_GetBackBuffer(p,a,b,c,d) (p)->GetBackBuffer(a,b,c,d) +#define IDirect3DDevice9_GetRasterStatus(p,a,b) (p)->GetRasterStatus(a,b) +#define IDirect3DDevice9_SetDialogBoxMode(p,a) (p)->SetDialogBoxMode(a) +#define IDirect3DDevice9_SetGammaRamp(p,a,b,c) (p)->SetGammaRamp(a,b,c) +#define IDirect3DDevice9_GetGammaRamp(p,a,b) (p)->GetGammaRamp(a,b) +#define IDirect3DDevice9_CreateTexture(p,a,b,c,d,e,f,g,h) (p)->CreateTexture(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9_CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i) (p)->CreateVolumeTexture(a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9_CreateCubeTexture(p,a,b,c,d,e,f,g) (p)->CreateCubeTexture(a,b,c,d,e,f,g) +#define IDirect3DDevice9_CreateVertexBuffer(p,a,b,c,d,e,f) (p)->CreateVertexBuffer(a,b,c,d,e,f) +#define IDirect3DDevice9_CreateIndexBuffer(p,a,b,c,d,e,f) (p)->CreateIndexBuffer(a,b,c,d,e,f) +#define IDirect3DDevice9_CreateRenderTarget(p,a,b,c,d,e,f,g,h) (p)->CreateRenderTarget(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9_CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h) (p)->CreateDepthStencilSurface(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9_UpdateSurface(p,a,b,c,d) (p)->UpdateSurface(a,b,c,d) +#define IDirect3DDevice9_UpdateTexture(p,a,b) (p)->UpdateTexture(a,b) +#define IDirect3DDevice9_GetRenderTargetData(p,a,b) (p)->GetRenderTargetData(a,b) +#define IDirect3DDevice9_GetFrontBufferData(p,a,b) (p)->GetFrontBufferData(a,b) +#define IDirect3DDevice9_StretchRect(p,a,b,c,d,e) (p)->StretchRect(a,b,c,d,e) +#define IDirect3DDevice9_ColorFill(p,a,b,c) (p)->ColorFill(a,b,c) +#define IDirect3DDevice9_CreateOffscreenPlainSurface(p,a,b,c,d,e,f) (p)->CreateOffscreenPlainSurface(a,b,c,d,e,f) +#define IDirect3DDevice9_SetRenderTarget(p,a,b) (p)->SetRenderTarget(a,b) +#define IDirect3DDevice9_GetRenderTarget(p,a,b) (p)->GetRenderTarget(a,b) +#define IDirect3DDevice9_SetDepthStencilSurface(p,a) (p)->SetDepthStencilSurface(a) +#define IDirect3DDevice9_GetDepthStencilSurface(p,a) (p)->GetDepthStencilSurface(a) +#define IDirect3DDevice9_BeginScene(p) (p)->BeginScene() +#define IDirect3DDevice9_EndScene(p) (p)->EndScene() +#define IDirect3DDevice9_Clear(p,a,b,c,d,e,f) (p)->Clear(a,b,c,d,e,f) +#define IDirect3DDevice9_SetTransform(p,a,b) (p)->SetTransform(a,b) +#define IDirect3DDevice9_GetTransform(p,a,b) (p)->GetTransform(a,b) +#define IDirect3DDevice9_MultiplyTransform(p,a,b) (p)->MultiplyTransform(a,b) +#define IDirect3DDevice9_SetViewport(p,a) (p)->SetViewport(a) +#define IDirect3DDevice9_GetViewport(p,a) (p)->GetViewport(a) +#define IDirect3DDevice9_SetMaterial(p,a) (p)->SetMaterial(a) +#define IDirect3DDevice9_GetMaterial(p,a) (p)->GetMaterial(a) +#define IDirect3DDevice9_SetLight(p,a,b) (p)->SetLight(a,b) +#define IDirect3DDevice9_GetLight(p,a,b) (p)->GetLight(a,b) +#define IDirect3DDevice9_LightEnable(p,a,b) (p)->LightEnable(a,b) +#define IDirect3DDevice9_GetLightEnable(p,a,b) (p)->GetLightEnable(a,b) +#define IDirect3DDevice9_SetClipPlane(p,a,b) (p)->SetClipPlane(a,b) +#define IDirect3DDevice9_GetClipPlane(p,a,b) (p)->GetClipPlane(a,b) +#define IDirect3DDevice9_SetRenderState(p,a,b) (p)->SetRenderState(a,b) +#define IDirect3DDevice9_GetRenderState(p,a,b) (p)->GetRenderState(a,b) +#define IDirect3DDevice9_CreateStateBlock(p,a,b) (p)->CreateStateBlock(a,b) +#define IDirect3DDevice9_BeginStateBlock(p) (p)->BeginStateBlock() +#define IDirect3DDevice9_EndStateBlock(p,a) (p)->EndStateBlock(a) +#define IDirect3DDevice9_SetClipStatus(p,a) (p)->SetClipStatus(a) +#define IDirect3DDevice9_GetClipStatus(p,a) (p)->GetClipStatus(a) +#define IDirect3DDevice9_GetTexture(p,a,b) (p)->GetTexture(a,b) +#define IDirect3DDevice9_SetTexture(p,a,b) (p)->SetTexture(a,b) +#define IDirect3DDevice9_GetTextureStageState(p,a,b,c) (p)->GetTextureStageState(a,b,c) +#define IDirect3DDevice9_SetTextureStageState(p,a,b,c) (p)->SetTextureStageState(a,b,c) +#define IDirect3DDevice9_GetSamplerState(p,a,b,c) (p)->GetSamplerState(a,b,c) +#define IDirect3DDevice9_SetSamplerState(p,a,b,c) (p)->SetSamplerState(a,b,c) +#define IDirect3DDevice9_ValidateDevice(p,a) (p)->ValidateDevice(a) +#define IDirect3DDevice9_SetPaletteEntries(p,a,b) (p)->SetPaletteEntries(a,b) +#define IDirect3DDevice9_GetPaletteEntries(p,a,b) (p)->GetPaletteEntries(a,b) +#define IDirect3DDevice9_SetCurrentTexturePalette(p,a) (p)->SetCurrentTexturePalette(a) +#define IDirect3DDevice9_GetCurrentTexturePalette(p,a) (p)->GetCurrentTexturePalette(a) +#define IDirect3DDevice9_SetScissorRect(p,a) (p)->SetScissorRect(a) +#define IDirect3DDevice9_GetScissorRect(p,a) (p)->GetScissorRect(a) +#define IDirect3DDevice9_SetSoftwareVertexProcessing(p,a) (p)->SetSoftwareVertexProcessing(a) +#define IDirect3DDevice9_GetSoftwareVertexProcessing(p) (p)->GetSoftwareVertexProcessing() +#define IDirect3DDevice9_SetNPatchMode(p,a) (p)->SetNPatchMode(a) +#define IDirect3DDevice9_GetNPatchMode(p) (p)->GetNPatchMode() +#define IDirect3DDevice9_DrawPrimitive(p,a,b,c) (p)->DrawPrimitive(a,b,c) +#define IDirect3DDevice9_DrawIndexedPrimitive(p,a,b,c,d,e,f) (p)->DrawIndexedPrimitive(a,b,c,d,e,f) +#define IDirect3DDevice9_DrawPrimitiveUP(p,a,b,c,d) (p)->DrawPrimitiveUP(a,b,c,d) +#define IDirect3DDevice9_DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h) (p)->DrawIndexedPrimitiveUP(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9_ProcessVertices(p,a,b,c,d,e,f) (p)->ProcessVertices(a,b,c,d,e,f) +#define IDirect3DDevice9_CreateVertexDeclaration(p,a,b) (p)->CreateVertexDeclaration(a,b) +#define IDirect3DDevice9_SetVertexDeclaration(p,a) (p)->SetVertexDeclaration(a) +#define IDirect3DDevice9_GetVertexDeclaration(p,a) (p)->GetVertexDeclaration(a) +#define IDirect3DDevice9_SetFVF(p,a) (p)->SetFVF(a) +#define IDirect3DDevice9_GetFVF(p,a) (p)->GetFVF(a) +#define IDirect3DDevice9_CreateVertexShader(p,a,b) (p)->CreateVertexShader(a,b) +#define IDirect3DDevice9_SetVertexShader(p,a) (p)->SetVertexShader(a) +#define IDirect3DDevice9_GetVertexShader(p,a) (p)->GetVertexShader(a) +#define IDirect3DDevice9_SetVertexShaderConstantF(p,a,b,c) (p)->SetVertexShaderConstantF(a,b,c) +#define IDirect3DDevice9_GetVertexShaderConstantF(p,a,b,c) (p)->GetVertexShaderConstantF(a,b,c) +#define IDirect3DDevice9_SetVertexShaderConstantI(p,a,b,c) (p)->SetVertexShaderConstantI(a,b,c) +#define IDirect3DDevice9_GetVertexShaderConstantI(p,a,b,c) (p)->GetVertexShaderConstantI(a,b,c) +#define IDirect3DDevice9_SetVertexShaderConstantB(p,a,b,c) (p)->SetVertexShaderConstantB(a,b,c) +#define IDirect3DDevice9_GetVertexShaderConstantB(p,a,b,c) (p)->GetVertexShaderConstantB(a,b,c) +#define IDirect3DDevice9_SetStreamSource(p,a,b,c,d) (p)->SetStreamSource(a,b,c,d) +#define IDirect3DDevice9_GetStreamSource(p,a,b,c,d) (p)->GetStreamSource(a,b,c,d) +#define IDirect3DDevice9_SetStreamSourceFreq(p,a,b) (p)->SetStreamSourceFreq(a,b) +#define IDirect3DDevice9_GetStreamSourceFreq(p,a,b) (p)->GetStreamSourceFreq(a,b) +#define IDirect3DDevice9_SetIndices(p,a) (p)->SetIndices(a) +#define IDirect3DDevice9_GetIndices(p,a) (p)->GetIndices(a) +#define IDirect3DDevice9_CreatePixelShader(p,a,b) (p)->CreatePixelShader(a,b) +#define IDirect3DDevice9_SetPixelShader(p,a) (p)->SetPixelShader(a) +#define IDirect3DDevice9_GetPixelShader(p,a) (p)->GetPixelShader(a) +#define IDirect3DDevice9_SetPixelShaderConstantF(p,a,b,c) (p)->SetPixelShaderConstantF(a,b,c) +#define IDirect3DDevice9_GetPixelShaderConstantF(p,a,b,c) (p)->GetPixelShaderConstantF(a,b,c) +#define IDirect3DDevice9_SetPixelShaderConstantI(p,a,b,c) (p)->SetPixelShaderConstantI(a,b,c) +#define IDirect3DDevice9_GetPixelShaderConstantI(p,a,b,c) (p)->GetPixelShaderConstantI(a,b,c) +#define IDirect3DDevice9_SetPixelShaderConstantB(p,a,b,c) (p)->SetPixelShaderConstantB(a,b,c) +#define IDirect3DDevice9_GetPixelShaderConstantB(p,a,b,c) (p)->GetPixelShaderConstantB(a,b,c) +#define IDirect3DDevice9_DrawRectPatch(p,a,b,c) (p)->DrawRectPatch(a,b,c) +#define IDirect3DDevice9_DrawTriPatch(p,a,b,c) (p)->DrawTriPatch(a,b,c) +#define IDirect3DDevice9_DeletePatch(p,a) (p)->DeletePatch(a) +#define IDirect3DDevice9_CreateQuery(p,a,b) (p)->CreateQuery(a,b) +#endif + + + + + +#undef INTERFACE +#define INTERFACE IDirect3DStateBlock9 + +DECLARE_INTERFACE_(IDirect3DStateBlock9, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DStateBlock9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(Capture)(THIS) PURE; + STDMETHOD(Apply)(THIS) PURE; + + #ifdef D3D_DEBUG_INFO + LPCWSTR CreationCallStack; + #endif +}; + +typedef struct IDirect3DStateBlock9 *LPDIRECT3DSTATEBLOCK9, *PDIRECT3DSTATEBLOCK9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DStateBlock9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DStateBlock9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DStateBlock9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DStateBlock9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DStateBlock9_Capture(p) (p)->lpVtbl->Capture(p) +#define IDirect3DStateBlock9_Apply(p) (p)->lpVtbl->Apply(p) +#else +#define IDirect3DStateBlock9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DStateBlock9_AddRef(p) (p)->AddRef() +#define IDirect3DStateBlock9_Release(p) (p)->Release() +#define IDirect3DStateBlock9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DStateBlock9_Capture(p) (p)->Capture() +#define IDirect3DStateBlock9_Apply(p) (p)->Apply() +#endif + + + + +#undef INTERFACE +#define INTERFACE IDirect3DSwapChain9 + +DECLARE_INTERFACE_(IDirect3DSwapChain9, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DSwapChain9 methods ***/ + STDMETHOD(Present)(THIS_ CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion,DWORD dwFlags) PURE; + STDMETHOD(GetFrontBufferData)(THIS_ IDirect3DSurface9* pDestSurface) PURE; + STDMETHOD(GetBackBuffer)(THIS_ UINT iBackBuffer,D3DBACKBUFFER_TYPE Type,IDirect3DSurface9** ppBackBuffer) PURE; + STDMETHOD(GetRasterStatus)(THIS_ D3DRASTER_STATUS* pRasterStatus) PURE; + STDMETHOD(GetDisplayMode)(THIS_ D3DDISPLAYMODE* pMode) PURE; + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(GetPresentParameters)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters) PURE; + + #ifdef D3D_DEBUG_INFO + D3DPRESENT_PARAMETERS PresentParameters; + D3DDISPLAYMODE DisplayMode; + LPCWSTR CreationCallStack; + #endif +}; + +typedef struct IDirect3DSwapChain9 *LPDIRECT3DSWAPCHAIN9, *PDIRECT3DSWAPCHAIN9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DSwapChain9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DSwapChain9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DSwapChain9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DSwapChain9_Present(p,a,b,c,d,e) (p)->lpVtbl->Present(p,a,b,c,d,e) +#define IDirect3DSwapChain9_GetFrontBufferData(p,a) (p)->lpVtbl->GetFrontBufferData(p,a) +#define IDirect3DSwapChain9_GetBackBuffer(p,a,b,c) (p)->lpVtbl->GetBackBuffer(p,a,b,c) +#define IDirect3DSwapChain9_GetRasterStatus(p,a) (p)->lpVtbl->GetRasterStatus(p,a) +#define IDirect3DSwapChain9_GetDisplayMode(p,a) (p)->lpVtbl->GetDisplayMode(p,a) +#define IDirect3DSwapChain9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DSwapChain9_GetPresentParameters(p,a) (p)->lpVtbl->GetPresentParameters(p,a) +#else +#define IDirect3DSwapChain9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DSwapChain9_AddRef(p) (p)->AddRef() +#define IDirect3DSwapChain9_Release(p) (p)->Release() +#define IDirect3DSwapChain9_Present(p,a,b,c,d,e) (p)->Present(a,b,c,d,e) +#define IDirect3DSwapChain9_GetFrontBufferData(p,a) (p)->GetFrontBufferData(a) +#define IDirect3DSwapChain9_GetBackBuffer(p,a,b,c) (p)->GetBackBuffer(a,b,c) +#define IDirect3DSwapChain9_GetRasterStatus(p,a) (p)->GetRasterStatus(a) +#define IDirect3DSwapChain9_GetDisplayMode(p,a) (p)->GetDisplayMode(a) +#define IDirect3DSwapChain9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DSwapChain9_GetPresentParameters(p,a) (p)->GetPresentParameters(a) +#endif + + + +#undef INTERFACE +#define INTERFACE IDirect3DResource9 + +DECLARE_INTERFACE_(IDirect3DResource9, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DResource9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid,CONST void* pData,DWORD SizeOfData,DWORD Flags) PURE; + STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid,void* pData,DWORD* pSizeOfData) PURE; + STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE; + STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE; + STDMETHOD_(DWORD, GetPriority)(THIS) PURE; + STDMETHOD_(void, PreLoad)(THIS) PURE; + STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE; +}; + +typedef struct IDirect3DResource9 *LPDIRECT3DRESOURCE9, *PDIRECT3DRESOURCE9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DResource9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DResource9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DResource9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DResource9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DResource9_SetPrivateData(p,a,b,c,d) (p)->lpVtbl->SetPrivateData(p,a,b,c,d) +#define IDirect3DResource9_GetPrivateData(p,a,b,c) (p)->lpVtbl->GetPrivateData(p,a,b,c) +#define IDirect3DResource9_FreePrivateData(p,a) (p)->lpVtbl->FreePrivateData(p,a) +#define IDirect3DResource9_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) +#define IDirect3DResource9_GetPriority(p) (p)->lpVtbl->GetPriority(p) +#define IDirect3DResource9_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IDirect3DResource9_GetType(p) (p)->lpVtbl->GetType(p) +#else +#define IDirect3DResource9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DResource9_AddRef(p) (p)->AddRef() +#define IDirect3DResource9_Release(p) (p)->Release() +#define IDirect3DResource9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DResource9_SetPrivateData(p,a,b,c,d) (p)->SetPrivateData(a,b,c,d) +#define IDirect3DResource9_GetPrivateData(p,a,b,c) (p)->GetPrivateData(a,b,c) +#define IDirect3DResource9_FreePrivateData(p,a) (p)->FreePrivateData(a) +#define IDirect3DResource9_SetPriority(p,a) (p)->SetPriority(a) +#define IDirect3DResource9_GetPriority(p) (p)->GetPriority() +#define IDirect3DResource9_PreLoad(p) (p)->PreLoad() +#define IDirect3DResource9_GetType(p) (p)->GetType() +#endif + + + + +#undef INTERFACE +#define INTERFACE IDirect3DVertexDeclaration9 + +DECLARE_INTERFACE_(IDirect3DVertexDeclaration9, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DVertexDeclaration9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9* pElement,UINT* pNumElements) PURE; + + #ifdef D3D_DEBUG_INFO + LPCWSTR CreationCallStack; + #endif +}; + +typedef struct IDirect3DVertexDeclaration9 *LPDIRECT3DVERTEXDECLARATION9, *PDIRECT3DVERTEXDECLARATION9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DVertexDeclaration9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DVertexDeclaration9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DVertexDeclaration9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DVertexDeclaration9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DVertexDeclaration9_GetDeclaration(p,a,b) (p)->lpVtbl->GetDeclaration(p,a,b) +#else +#define IDirect3DVertexDeclaration9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DVertexDeclaration9_AddRef(p) (p)->AddRef() +#define IDirect3DVertexDeclaration9_Release(p) (p)->Release() +#define IDirect3DVertexDeclaration9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DVertexDeclaration9_GetDeclaration(p,a,b) (p)->GetDeclaration(a,b) +#endif + + + + +#undef INTERFACE +#define INTERFACE IDirect3DVertexShader9 + +DECLARE_INTERFACE_(IDirect3DVertexShader9, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DVertexShader9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(GetFunction)(THIS_ void*,UINT* pSizeOfData) PURE; + + #ifdef D3D_DEBUG_INFO + DWORD Version; + LPCWSTR CreationCallStack; + #endif +}; + +typedef struct IDirect3DVertexShader9 *LPDIRECT3DVERTEXSHADER9, *PDIRECT3DVERTEXSHADER9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DVertexShader9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DVertexShader9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DVertexShader9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DVertexShader9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DVertexShader9_GetFunction(p,a,b) (p)->lpVtbl->GetFunction(p,a,b) +#else +#define IDirect3DVertexShader9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DVertexShader9_AddRef(p) (p)->AddRef() +#define IDirect3DVertexShader9_Release(p) (p)->Release() +#define IDirect3DVertexShader9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DVertexShader9_GetFunction(p,a,b) (p)->GetFunction(a,b) +#endif + + + + +#undef INTERFACE +#define INTERFACE IDirect3DPixelShader9 + +DECLARE_INTERFACE_(IDirect3DPixelShader9, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DPixelShader9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(GetFunction)(THIS_ void*,UINT* pSizeOfData) PURE; + + #ifdef D3D_DEBUG_INFO + DWORD Version; + LPCWSTR CreationCallStack; + #endif +}; + +typedef struct IDirect3DPixelShader9 *LPDIRECT3DPIXELSHADER9, *PDIRECT3DPIXELSHADER9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DPixelShader9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DPixelShader9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DPixelShader9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DPixelShader9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DPixelShader9_GetFunction(p,a,b) (p)->lpVtbl->GetFunction(p,a,b) +#else +#define IDirect3DPixelShader9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DPixelShader9_AddRef(p) (p)->AddRef() +#define IDirect3DPixelShader9_Release(p) (p)->Release() +#define IDirect3DPixelShader9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DPixelShader9_GetFunction(p,a,b) (p)->GetFunction(a,b) +#endif + + + + +#undef INTERFACE +#define INTERFACE IDirect3DBaseTexture9 + +DECLARE_INTERFACE_(IDirect3DBaseTexture9, IDirect3DResource9) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DResource9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid,CONST void* pData,DWORD SizeOfData,DWORD Flags) PURE; + STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid,void* pData,DWORD* pSizeOfData) PURE; + STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE; + STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE; + STDMETHOD_(DWORD, GetPriority)(THIS) PURE; + STDMETHOD_(void, PreLoad)(THIS) PURE; + STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE; + STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE; + STDMETHOD_(DWORD, GetLOD)(THIS) PURE; + STDMETHOD_(DWORD, GetLevelCount)(THIS) PURE; + STDMETHOD(SetAutoGenFilterType)(THIS_ D3DTEXTUREFILTERTYPE FilterType) PURE; + STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)(THIS) PURE; + STDMETHOD_(void, GenerateMipSubLevels)(THIS) PURE; +}; + +typedef struct IDirect3DBaseTexture9 *LPDIRECT3DBASETEXTURE9, *PDIRECT3DBASETEXTURE9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DBaseTexture9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DBaseTexture9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DBaseTexture9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DBaseTexture9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DBaseTexture9_SetPrivateData(p,a,b,c,d) (p)->lpVtbl->SetPrivateData(p,a,b,c,d) +#define IDirect3DBaseTexture9_GetPrivateData(p,a,b,c) (p)->lpVtbl->GetPrivateData(p,a,b,c) +#define IDirect3DBaseTexture9_FreePrivateData(p,a) (p)->lpVtbl->FreePrivateData(p,a) +#define IDirect3DBaseTexture9_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) +#define IDirect3DBaseTexture9_GetPriority(p) (p)->lpVtbl->GetPriority(p) +#define IDirect3DBaseTexture9_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IDirect3DBaseTexture9_GetType(p) (p)->lpVtbl->GetType(p) +#define IDirect3DBaseTexture9_SetLOD(p,a) (p)->lpVtbl->SetLOD(p,a) +#define IDirect3DBaseTexture9_GetLOD(p) (p)->lpVtbl->GetLOD(p) +#define IDirect3DBaseTexture9_GetLevelCount(p) (p)->lpVtbl->GetLevelCount(p) +#define IDirect3DBaseTexture9_SetAutoGenFilterType(p,a) (p)->lpVtbl->SetAutoGenFilterType(p,a) +#define IDirect3DBaseTexture9_GetAutoGenFilterType(p) (p)->lpVtbl->GetAutoGenFilterType(p) +#define IDirect3DBaseTexture9_GenerateMipSubLevels(p) (p)->lpVtbl->GenerateMipSubLevels(p) +#else +#define IDirect3DBaseTexture9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DBaseTexture9_AddRef(p) (p)->AddRef() +#define IDirect3DBaseTexture9_Release(p) (p)->Release() +#define IDirect3DBaseTexture9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DBaseTexture9_SetPrivateData(p,a,b,c,d) (p)->SetPrivateData(a,b,c,d) +#define IDirect3DBaseTexture9_GetPrivateData(p,a,b,c) (p)->GetPrivateData(a,b,c) +#define IDirect3DBaseTexture9_FreePrivateData(p,a) (p)->FreePrivateData(a) +#define IDirect3DBaseTexture9_SetPriority(p,a) (p)->SetPriority(a) +#define IDirect3DBaseTexture9_GetPriority(p) (p)->GetPriority() +#define IDirect3DBaseTexture9_PreLoad(p) (p)->PreLoad() +#define IDirect3DBaseTexture9_GetType(p) (p)->GetType() +#define IDirect3DBaseTexture9_SetLOD(p,a) (p)->SetLOD(a) +#define IDirect3DBaseTexture9_GetLOD(p) (p)->GetLOD() +#define IDirect3DBaseTexture9_GetLevelCount(p) (p)->GetLevelCount() +#define IDirect3DBaseTexture9_SetAutoGenFilterType(p,a) (p)->SetAutoGenFilterType(a) +#define IDirect3DBaseTexture9_GetAutoGenFilterType(p) (p)->GetAutoGenFilterType() +#define IDirect3DBaseTexture9_GenerateMipSubLevels(p) (p)->GenerateMipSubLevels() +#endif + + + + + +#undef INTERFACE +#define INTERFACE IDirect3DTexture9 + +DECLARE_INTERFACE_(IDirect3DTexture9, IDirect3DBaseTexture9) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DBaseTexture9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid,CONST void* pData,DWORD SizeOfData,DWORD Flags) PURE; + STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid,void* pData,DWORD* pSizeOfData) PURE; + STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE; + STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE; + STDMETHOD_(DWORD, GetPriority)(THIS) PURE; + STDMETHOD_(void, PreLoad)(THIS) PURE; + STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE; + STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE; + STDMETHOD_(DWORD, GetLOD)(THIS) PURE; + STDMETHOD_(DWORD, GetLevelCount)(THIS) PURE; + STDMETHOD(SetAutoGenFilterType)(THIS_ D3DTEXTUREFILTERTYPE FilterType) PURE; + STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)(THIS) PURE; + STDMETHOD_(void, GenerateMipSubLevels)(THIS) PURE; + STDMETHOD(GetLevelDesc)(THIS_ UINT Level,D3DSURFACE_DESC *pDesc) PURE; + STDMETHOD(GetSurfaceLevel)(THIS_ UINT Level,IDirect3DSurface9** ppSurfaceLevel) PURE; + STDMETHOD(LockRect)(THIS_ UINT Level,D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags) PURE; + STDMETHOD(UnlockRect)(THIS_ UINT Level) PURE; + STDMETHOD(AddDirtyRect)(THIS_ CONST RECT* pDirtyRect) PURE; + + #ifdef D3D_DEBUG_INFO + LPCWSTR Name; + UINT Width; + UINT Height; + UINT Levels; + DWORD Usage; + D3DFORMAT Format; + D3DPOOL Pool; + DWORD Priority; + DWORD LOD; + D3DTEXTUREFILTERTYPE FilterType; + UINT LockCount; + LPCWSTR CreationCallStack; + #endif +}; + +typedef struct IDirect3DTexture9 *LPDIRECT3DTEXTURE9, *PDIRECT3DTEXTURE9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DTexture9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DTexture9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DTexture9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DTexture9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DTexture9_SetPrivateData(p,a,b,c,d) (p)->lpVtbl->SetPrivateData(p,a,b,c,d) +#define IDirect3DTexture9_GetPrivateData(p,a,b,c) (p)->lpVtbl->GetPrivateData(p,a,b,c) +#define IDirect3DTexture9_FreePrivateData(p,a) (p)->lpVtbl->FreePrivateData(p,a) +#define IDirect3DTexture9_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) +#define IDirect3DTexture9_GetPriority(p) (p)->lpVtbl->GetPriority(p) +#define IDirect3DTexture9_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IDirect3DTexture9_GetType(p) (p)->lpVtbl->GetType(p) +#define IDirect3DTexture9_SetLOD(p,a) (p)->lpVtbl->SetLOD(p,a) +#define IDirect3DTexture9_GetLOD(p) (p)->lpVtbl->GetLOD(p) +#define IDirect3DTexture9_GetLevelCount(p) (p)->lpVtbl->GetLevelCount(p) +#define IDirect3DTexture9_SetAutoGenFilterType(p,a) (p)->lpVtbl->SetAutoGenFilterType(p,a) +#define IDirect3DTexture9_GetAutoGenFilterType(p) (p)->lpVtbl->GetAutoGenFilterType(p) +#define IDirect3DTexture9_GenerateMipSubLevels(p) (p)->lpVtbl->GenerateMipSubLevels(p) +#define IDirect3DTexture9_GetLevelDesc(p,a,b) (p)->lpVtbl->GetLevelDesc(p,a,b) +#define IDirect3DTexture9_GetSurfaceLevel(p,a,b) (p)->lpVtbl->GetSurfaceLevel(p,a,b) +#define IDirect3DTexture9_LockRect(p,a,b,c,d) (p)->lpVtbl->LockRect(p,a,b,c,d) +#define IDirect3DTexture9_UnlockRect(p,a) (p)->lpVtbl->UnlockRect(p,a) +#define IDirect3DTexture9_AddDirtyRect(p,a) (p)->lpVtbl->AddDirtyRect(p,a) +#else +#define IDirect3DTexture9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DTexture9_AddRef(p) (p)->AddRef() +#define IDirect3DTexture9_Release(p) (p)->Release() +#define IDirect3DTexture9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DTexture9_SetPrivateData(p,a,b,c,d) (p)->SetPrivateData(a,b,c,d) +#define IDirect3DTexture9_GetPrivateData(p,a,b,c) (p)->GetPrivateData(a,b,c) +#define IDirect3DTexture9_FreePrivateData(p,a) (p)->FreePrivateData(a) +#define IDirect3DTexture9_SetPriority(p,a) (p)->SetPriority(a) +#define IDirect3DTexture9_GetPriority(p) (p)->GetPriority() +#define IDirect3DTexture9_PreLoad(p) (p)->PreLoad() +#define IDirect3DTexture9_GetType(p) (p)->GetType() +#define IDirect3DTexture9_SetLOD(p,a) (p)->SetLOD(a) +#define IDirect3DTexture9_GetLOD(p) (p)->GetLOD() +#define IDirect3DTexture9_GetLevelCount(p) (p)->GetLevelCount() +#define IDirect3DTexture9_SetAutoGenFilterType(p,a) (p)->SetAutoGenFilterType(a) +#define IDirect3DTexture9_GetAutoGenFilterType(p) (p)->GetAutoGenFilterType() +#define IDirect3DTexture9_GenerateMipSubLevels(p) (p)->GenerateMipSubLevels() +#define IDirect3DTexture9_GetLevelDesc(p,a,b) (p)->GetLevelDesc(a,b) +#define IDirect3DTexture9_GetSurfaceLevel(p,a,b) (p)->GetSurfaceLevel(a,b) +#define IDirect3DTexture9_LockRect(p,a,b,c,d) (p)->LockRect(a,b,c,d) +#define IDirect3DTexture9_UnlockRect(p,a) (p)->UnlockRect(a) +#define IDirect3DTexture9_AddDirtyRect(p,a) (p)->AddDirtyRect(a) +#endif + + + + + +#undef INTERFACE +#define INTERFACE IDirect3DVolumeTexture9 + +DECLARE_INTERFACE_(IDirect3DVolumeTexture9, IDirect3DBaseTexture9) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DBaseTexture9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid,CONST void* pData,DWORD SizeOfData,DWORD Flags) PURE; + STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid,void* pData,DWORD* pSizeOfData) PURE; + STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE; + STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE; + STDMETHOD_(DWORD, GetPriority)(THIS) PURE; + STDMETHOD_(void, PreLoad)(THIS) PURE; + STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE; + STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE; + STDMETHOD_(DWORD, GetLOD)(THIS) PURE; + STDMETHOD_(DWORD, GetLevelCount)(THIS) PURE; + STDMETHOD(SetAutoGenFilterType)(THIS_ D3DTEXTUREFILTERTYPE FilterType) PURE; + STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)(THIS) PURE; + STDMETHOD_(void, GenerateMipSubLevels)(THIS) PURE; + STDMETHOD(GetLevelDesc)(THIS_ UINT Level,D3DVOLUME_DESC *pDesc) PURE; + STDMETHOD(GetVolumeLevel)(THIS_ UINT Level,IDirect3DVolume9** ppVolumeLevel) PURE; + STDMETHOD(LockBox)(THIS_ UINT Level,D3DLOCKED_BOX* pLockedVolume,CONST D3DBOX* pBox,DWORD Flags) PURE; + STDMETHOD(UnlockBox)(THIS_ UINT Level) PURE; + STDMETHOD(AddDirtyBox)(THIS_ CONST D3DBOX* pDirtyBox) PURE; + + #ifdef D3D_DEBUG_INFO + LPCWSTR Name; + UINT Width; + UINT Height; + UINT Depth; + UINT Levels; + DWORD Usage; + D3DFORMAT Format; + D3DPOOL Pool; + DWORD Priority; + DWORD LOD; + D3DTEXTUREFILTERTYPE FilterType; + UINT LockCount; + LPCWSTR CreationCallStack; + #endif +}; + +typedef struct IDirect3DVolumeTexture9 *LPDIRECT3DVOLUMETEXTURE9, *PDIRECT3DVOLUMETEXTURE9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DVolumeTexture9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DVolumeTexture9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DVolumeTexture9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DVolumeTexture9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DVolumeTexture9_SetPrivateData(p,a,b,c,d) (p)->lpVtbl->SetPrivateData(p,a,b,c,d) +#define IDirect3DVolumeTexture9_GetPrivateData(p,a,b,c) (p)->lpVtbl->GetPrivateData(p,a,b,c) +#define IDirect3DVolumeTexture9_FreePrivateData(p,a) (p)->lpVtbl->FreePrivateData(p,a) +#define IDirect3DVolumeTexture9_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) +#define IDirect3DVolumeTexture9_GetPriority(p) (p)->lpVtbl->GetPriority(p) +#define IDirect3DVolumeTexture9_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IDirect3DVolumeTexture9_GetType(p) (p)->lpVtbl->GetType(p) +#define IDirect3DVolumeTexture9_SetLOD(p,a) (p)->lpVtbl->SetLOD(p,a) +#define IDirect3DVolumeTexture9_GetLOD(p) (p)->lpVtbl->GetLOD(p) +#define IDirect3DVolumeTexture9_GetLevelCount(p) (p)->lpVtbl->GetLevelCount(p) +#define IDirect3DVolumeTexture9_SetAutoGenFilterType(p,a) (p)->lpVtbl->SetAutoGenFilterType(p,a) +#define IDirect3DVolumeTexture9_GetAutoGenFilterType(p) (p)->lpVtbl->GetAutoGenFilterType(p) +#define IDirect3DVolumeTexture9_GenerateMipSubLevels(p) (p)->lpVtbl->GenerateMipSubLevels(p) +#define IDirect3DVolumeTexture9_GetLevelDesc(p,a,b) (p)->lpVtbl->GetLevelDesc(p,a,b) +#define IDirect3DVolumeTexture9_GetVolumeLevel(p,a,b) (p)->lpVtbl->GetVolumeLevel(p,a,b) +#define IDirect3DVolumeTexture9_LockBox(p,a,b,c,d) (p)->lpVtbl->LockBox(p,a,b,c,d) +#define IDirect3DVolumeTexture9_UnlockBox(p,a) (p)->lpVtbl->UnlockBox(p,a) +#define IDirect3DVolumeTexture9_AddDirtyBox(p,a) (p)->lpVtbl->AddDirtyBox(p,a) +#else +#define IDirect3DVolumeTexture9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DVolumeTexture9_AddRef(p) (p)->AddRef() +#define IDirect3DVolumeTexture9_Release(p) (p)->Release() +#define IDirect3DVolumeTexture9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DVolumeTexture9_SetPrivateData(p,a,b,c,d) (p)->SetPrivateData(a,b,c,d) +#define IDirect3DVolumeTexture9_GetPrivateData(p,a,b,c) (p)->GetPrivateData(a,b,c) +#define IDirect3DVolumeTexture9_FreePrivateData(p,a) (p)->FreePrivateData(a) +#define IDirect3DVolumeTexture9_SetPriority(p,a) (p)->SetPriority(a) +#define IDirect3DVolumeTexture9_GetPriority(p) (p)->GetPriority() +#define IDirect3DVolumeTexture9_PreLoad(p) (p)->PreLoad() +#define IDirect3DVolumeTexture9_GetType(p) (p)->GetType() +#define IDirect3DVolumeTexture9_SetLOD(p,a) (p)->SetLOD(a) +#define IDirect3DVolumeTexture9_GetLOD(p) (p)->GetLOD() +#define IDirect3DVolumeTexture9_GetLevelCount(p) (p)->GetLevelCount() +#define IDirect3DVolumeTexture9_SetAutoGenFilterType(p,a) (p)->SetAutoGenFilterType(a) +#define IDirect3DVolumeTexture9_GetAutoGenFilterType(p) (p)->GetAutoGenFilterType() +#define IDirect3DVolumeTexture9_GenerateMipSubLevels(p) (p)->GenerateMipSubLevels() +#define IDirect3DVolumeTexture9_GetLevelDesc(p,a,b) (p)->GetLevelDesc(a,b) +#define IDirect3DVolumeTexture9_GetVolumeLevel(p,a,b) (p)->GetVolumeLevel(a,b) +#define IDirect3DVolumeTexture9_LockBox(p,a,b,c,d) (p)->LockBox(a,b,c,d) +#define IDirect3DVolumeTexture9_UnlockBox(p,a) (p)->UnlockBox(a) +#define IDirect3DVolumeTexture9_AddDirtyBox(p,a) (p)->AddDirtyBox(a) +#endif + + + + + +#undef INTERFACE +#define INTERFACE IDirect3DCubeTexture9 + +DECLARE_INTERFACE_(IDirect3DCubeTexture9, IDirect3DBaseTexture9) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DBaseTexture9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid,CONST void* pData,DWORD SizeOfData,DWORD Flags) PURE; + STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid,void* pData,DWORD* pSizeOfData) PURE; + STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE; + STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE; + STDMETHOD_(DWORD, GetPriority)(THIS) PURE; + STDMETHOD_(void, PreLoad)(THIS) PURE; + STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE; + STDMETHOD_(DWORD, SetLOD)(THIS_ DWORD LODNew) PURE; + STDMETHOD_(DWORD, GetLOD)(THIS) PURE; + STDMETHOD_(DWORD, GetLevelCount)(THIS) PURE; + STDMETHOD(SetAutoGenFilterType)(THIS_ D3DTEXTUREFILTERTYPE FilterType) PURE; + STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)(THIS) PURE; + STDMETHOD_(void, GenerateMipSubLevels)(THIS) PURE; + STDMETHOD(GetLevelDesc)(THIS_ UINT Level,D3DSURFACE_DESC *pDesc) PURE; + STDMETHOD(GetCubeMapSurface)(THIS_ D3DCUBEMAP_FACES FaceType,UINT Level,IDirect3DSurface9** ppCubeMapSurface) PURE; + STDMETHOD(LockRect)(THIS_ D3DCUBEMAP_FACES FaceType,UINT Level,D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags) PURE; + STDMETHOD(UnlockRect)(THIS_ D3DCUBEMAP_FACES FaceType,UINT Level) PURE; + STDMETHOD(AddDirtyRect)(THIS_ D3DCUBEMAP_FACES FaceType,CONST RECT* pDirtyRect) PURE; + + #ifdef D3D_DEBUG_INFO + LPCWSTR Name; + UINT Width; + UINT Height; + UINT Levels; + DWORD Usage; + D3DFORMAT Format; + D3DPOOL Pool; + DWORD Priority; + DWORD LOD; + D3DTEXTUREFILTERTYPE FilterType; + UINT LockCount; + LPCWSTR CreationCallStack; + #endif +}; + +typedef struct IDirect3DCubeTexture9 *LPDIRECT3DCUBETEXTURE9, *PDIRECT3DCUBETEXTURE9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DCubeTexture9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DCubeTexture9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DCubeTexture9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DCubeTexture9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DCubeTexture9_SetPrivateData(p,a,b,c,d) (p)->lpVtbl->SetPrivateData(p,a,b,c,d) +#define IDirect3DCubeTexture9_GetPrivateData(p,a,b,c) (p)->lpVtbl->GetPrivateData(p,a,b,c) +#define IDirect3DCubeTexture9_FreePrivateData(p,a) (p)->lpVtbl->FreePrivateData(p,a) +#define IDirect3DCubeTexture9_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) +#define IDirect3DCubeTexture9_GetPriority(p) (p)->lpVtbl->GetPriority(p) +#define IDirect3DCubeTexture9_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IDirect3DCubeTexture9_GetType(p) (p)->lpVtbl->GetType(p) +#define IDirect3DCubeTexture9_SetLOD(p,a) (p)->lpVtbl->SetLOD(p,a) +#define IDirect3DCubeTexture9_GetLOD(p) (p)->lpVtbl->GetLOD(p) +#define IDirect3DCubeTexture9_GetLevelCount(p) (p)->lpVtbl->GetLevelCount(p) +#define IDirect3DCubeTexture9_SetAutoGenFilterType(p,a) (p)->lpVtbl->SetAutoGenFilterType(p,a) +#define IDirect3DCubeTexture9_GetAutoGenFilterType(p) (p)->lpVtbl->GetAutoGenFilterType(p) +#define IDirect3DCubeTexture9_GenerateMipSubLevels(p) (p)->lpVtbl->GenerateMipSubLevels(p) +#define IDirect3DCubeTexture9_GetLevelDesc(p,a,b) (p)->lpVtbl->GetLevelDesc(p,a,b) +#define IDirect3DCubeTexture9_GetCubeMapSurface(p,a,b,c) (p)->lpVtbl->GetCubeMapSurface(p,a,b,c) +#define IDirect3DCubeTexture9_LockRect(p,a,b,c,d,e) (p)->lpVtbl->LockRect(p,a,b,c,d,e) +#define IDirect3DCubeTexture9_UnlockRect(p,a,b) (p)->lpVtbl->UnlockRect(p,a,b) +#define IDirect3DCubeTexture9_AddDirtyRect(p,a,b) (p)->lpVtbl->AddDirtyRect(p,a,b) +#else +#define IDirect3DCubeTexture9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DCubeTexture9_AddRef(p) (p)->AddRef() +#define IDirect3DCubeTexture9_Release(p) (p)->Release() +#define IDirect3DCubeTexture9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DCubeTexture9_SetPrivateData(p,a,b,c,d) (p)->SetPrivateData(a,b,c,d) +#define IDirect3DCubeTexture9_GetPrivateData(p,a,b,c) (p)->GetPrivateData(a,b,c) +#define IDirect3DCubeTexture9_FreePrivateData(p,a) (p)->FreePrivateData(a) +#define IDirect3DCubeTexture9_SetPriority(p,a) (p)->SetPriority(a) +#define IDirect3DCubeTexture9_GetPriority(p) (p)->GetPriority() +#define IDirect3DCubeTexture9_PreLoad(p) (p)->PreLoad() +#define IDirect3DCubeTexture9_GetType(p) (p)->GetType() +#define IDirect3DCubeTexture9_SetLOD(p,a) (p)->SetLOD(a) +#define IDirect3DCubeTexture9_GetLOD(p) (p)->GetLOD() +#define IDirect3DCubeTexture9_GetLevelCount(p) (p)->GetLevelCount() +#define IDirect3DCubeTexture9_SetAutoGenFilterType(p,a) (p)->SetAutoGenFilterType(a) +#define IDirect3DCubeTexture9_GetAutoGenFilterType(p) (p)->GetAutoGenFilterType() +#define IDirect3DCubeTexture9_GenerateMipSubLevels(p) (p)->GenerateMipSubLevels() +#define IDirect3DCubeTexture9_GetLevelDesc(p,a,b) (p)->GetLevelDesc(a,b) +#define IDirect3DCubeTexture9_GetCubeMapSurface(p,a,b,c) (p)->GetCubeMapSurface(a,b,c) +#define IDirect3DCubeTexture9_LockRect(p,a,b,c,d,e) (p)->LockRect(a,b,c,d,e) +#define IDirect3DCubeTexture9_UnlockRect(p,a,b) (p)->UnlockRect(a,b) +#define IDirect3DCubeTexture9_AddDirtyRect(p,a,b) (p)->AddDirtyRect(a,b) +#endif + + + + +#undef INTERFACE +#define INTERFACE IDirect3DVertexBuffer9 + +DECLARE_INTERFACE_(IDirect3DVertexBuffer9, IDirect3DResource9) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DResource9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid,CONST void* pData,DWORD SizeOfData,DWORD Flags) PURE; + STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid,void* pData,DWORD* pSizeOfData) PURE; + STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE; + STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE; + STDMETHOD_(DWORD, GetPriority)(THIS) PURE; + STDMETHOD_(void, PreLoad)(THIS) PURE; + STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE; + STDMETHOD(Lock)(THIS_ UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags) PURE; + STDMETHOD(Unlock)(THIS) PURE; + STDMETHOD(GetDesc)(THIS_ D3DVERTEXBUFFER_DESC *pDesc) PURE; + + #ifdef D3D_DEBUG_INFO + LPCWSTR Name; + UINT Length; + DWORD Usage; + DWORD FVF; + D3DPOOL Pool; + DWORD Priority; + UINT LockCount; + LPCWSTR CreationCallStack; + #endif +}; + +typedef struct IDirect3DVertexBuffer9 *LPDIRECT3DVERTEXBUFFER9, *PDIRECT3DVERTEXBUFFER9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DVertexBuffer9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DVertexBuffer9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DVertexBuffer9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DVertexBuffer9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DVertexBuffer9_SetPrivateData(p,a,b,c,d) (p)->lpVtbl->SetPrivateData(p,a,b,c,d) +#define IDirect3DVertexBuffer9_GetPrivateData(p,a,b,c) (p)->lpVtbl->GetPrivateData(p,a,b,c) +#define IDirect3DVertexBuffer9_FreePrivateData(p,a) (p)->lpVtbl->FreePrivateData(p,a) +#define IDirect3DVertexBuffer9_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) +#define IDirect3DVertexBuffer9_GetPriority(p) (p)->lpVtbl->GetPriority(p) +#define IDirect3DVertexBuffer9_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IDirect3DVertexBuffer9_GetType(p) (p)->lpVtbl->GetType(p) +#define IDirect3DVertexBuffer9_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) +#define IDirect3DVertexBuffer9_Unlock(p) (p)->lpVtbl->Unlock(p) +#define IDirect3DVertexBuffer9_GetDesc(p,a) (p)->lpVtbl->GetDesc(p,a) +#else +#define IDirect3DVertexBuffer9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DVertexBuffer9_AddRef(p) (p)->AddRef() +#define IDirect3DVertexBuffer9_Release(p) (p)->Release() +#define IDirect3DVertexBuffer9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DVertexBuffer9_SetPrivateData(p,a,b,c,d) (p)->SetPrivateData(a,b,c,d) +#define IDirect3DVertexBuffer9_GetPrivateData(p,a,b,c) (p)->GetPrivateData(a,b,c) +#define IDirect3DVertexBuffer9_FreePrivateData(p,a) (p)->FreePrivateData(a) +#define IDirect3DVertexBuffer9_SetPriority(p,a) (p)->SetPriority(a) +#define IDirect3DVertexBuffer9_GetPriority(p) (p)->GetPriority() +#define IDirect3DVertexBuffer9_PreLoad(p) (p)->PreLoad() +#define IDirect3DVertexBuffer9_GetType(p) (p)->GetType() +#define IDirect3DVertexBuffer9_Lock(p,a,b,c,d) (p)->Lock(a,b,c,d) +#define IDirect3DVertexBuffer9_Unlock(p) (p)->Unlock() +#define IDirect3DVertexBuffer9_GetDesc(p,a) (p)->GetDesc(a) +#endif + + + + +#undef INTERFACE +#define INTERFACE IDirect3DIndexBuffer9 + +DECLARE_INTERFACE_(IDirect3DIndexBuffer9, IDirect3DResource9) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DResource9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid,CONST void* pData,DWORD SizeOfData,DWORD Flags) PURE; + STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid,void* pData,DWORD* pSizeOfData) PURE; + STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE; + STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE; + STDMETHOD_(DWORD, GetPriority)(THIS) PURE; + STDMETHOD_(void, PreLoad)(THIS) PURE; + STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE; + STDMETHOD(Lock)(THIS_ UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags) PURE; + STDMETHOD(Unlock)(THIS) PURE; + STDMETHOD(GetDesc)(THIS_ D3DINDEXBUFFER_DESC *pDesc) PURE; + + #ifdef D3D_DEBUG_INFO + LPCWSTR Name; + UINT Length; + DWORD Usage; + D3DFORMAT Format; + D3DPOOL Pool; + DWORD Priority; + UINT LockCount; + LPCWSTR CreationCallStack; + #endif +}; + +typedef struct IDirect3DIndexBuffer9 *LPDIRECT3DINDEXBUFFER9, *PDIRECT3DINDEXBUFFER9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DIndexBuffer9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DIndexBuffer9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DIndexBuffer9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DIndexBuffer9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DIndexBuffer9_SetPrivateData(p,a,b,c,d) (p)->lpVtbl->SetPrivateData(p,a,b,c,d) +#define IDirect3DIndexBuffer9_GetPrivateData(p,a,b,c) (p)->lpVtbl->GetPrivateData(p,a,b,c) +#define IDirect3DIndexBuffer9_FreePrivateData(p,a) (p)->lpVtbl->FreePrivateData(p,a) +#define IDirect3DIndexBuffer9_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) +#define IDirect3DIndexBuffer9_GetPriority(p) (p)->lpVtbl->GetPriority(p) +#define IDirect3DIndexBuffer9_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IDirect3DIndexBuffer9_GetType(p) (p)->lpVtbl->GetType(p) +#define IDirect3DIndexBuffer9_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) +#define IDirect3DIndexBuffer9_Unlock(p) (p)->lpVtbl->Unlock(p) +#define IDirect3DIndexBuffer9_GetDesc(p,a) (p)->lpVtbl->GetDesc(p,a) +#else +#define IDirect3DIndexBuffer9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DIndexBuffer9_AddRef(p) (p)->AddRef() +#define IDirect3DIndexBuffer9_Release(p) (p)->Release() +#define IDirect3DIndexBuffer9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DIndexBuffer9_SetPrivateData(p,a,b,c,d) (p)->SetPrivateData(a,b,c,d) +#define IDirect3DIndexBuffer9_GetPrivateData(p,a,b,c) (p)->GetPrivateData(a,b,c) +#define IDirect3DIndexBuffer9_FreePrivateData(p,a) (p)->FreePrivateData(a) +#define IDirect3DIndexBuffer9_SetPriority(p,a) (p)->SetPriority(a) +#define IDirect3DIndexBuffer9_GetPriority(p) (p)->GetPriority() +#define IDirect3DIndexBuffer9_PreLoad(p) (p)->PreLoad() +#define IDirect3DIndexBuffer9_GetType(p) (p)->GetType() +#define IDirect3DIndexBuffer9_Lock(p,a,b,c,d) (p)->Lock(a,b,c,d) +#define IDirect3DIndexBuffer9_Unlock(p) (p)->Unlock() +#define IDirect3DIndexBuffer9_GetDesc(p,a) (p)->GetDesc(a) +#endif + + + + +#undef INTERFACE +#define INTERFACE IDirect3DSurface9 + +DECLARE_INTERFACE_(IDirect3DSurface9, IDirect3DResource9) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DResource9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid,CONST void* pData,DWORD SizeOfData,DWORD Flags) PURE; + STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid,void* pData,DWORD* pSizeOfData) PURE; + STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE; + STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew) PURE; + STDMETHOD_(DWORD, GetPriority)(THIS) PURE; + STDMETHOD_(void, PreLoad)(THIS) PURE; + STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS) PURE; + STDMETHOD(GetContainer)(THIS_ REFIID riid,void** ppContainer) PURE; + STDMETHOD(GetDesc)(THIS_ D3DSURFACE_DESC *pDesc) PURE; + STDMETHOD(LockRect)(THIS_ D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags) PURE; + STDMETHOD(UnlockRect)(THIS) PURE; + STDMETHOD(GetDC)(THIS_ HDC *phdc) PURE; + STDMETHOD(ReleaseDC)(THIS_ HDC hdc) PURE; + + #ifdef D3D_DEBUG_INFO + LPCWSTR Name; + UINT Width; + UINT Height; + DWORD Usage; + D3DFORMAT Format; + D3DPOOL Pool; + D3DMULTISAMPLE_TYPE MultiSampleType; + DWORD MultiSampleQuality; + DWORD Priority; + UINT LockCount; + UINT DCCount; + LPCWSTR CreationCallStack; + #endif +}; + +typedef struct IDirect3DSurface9 *LPDIRECT3DSURFACE9, *PDIRECT3DSURFACE9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DSurface9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DSurface9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DSurface9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DSurface9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DSurface9_SetPrivateData(p,a,b,c,d) (p)->lpVtbl->SetPrivateData(p,a,b,c,d) +#define IDirect3DSurface9_GetPrivateData(p,a,b,c) (p)->lpVtbl->GetPrivateData(p,a,b,c) +#define IDirect3DSurface9_FreePrivateData(p,a) (p)->lpVtbl->FreePrivateData(p,a) +#define IDirect3DSurface9_SetPriority(p,a) (p)->lpVtbl->SetPriority(p,a) +#define IDirect3DSurface9_GetPriority(p) (p)->lpVtbl->GetPriority(p) +#define IDirect3DSurface9_PreLoad(p) (p)->lpVtbl->PreLoad(p) +#define IDirect3DSurface9_GetType(p) (p)->lpVtbl->GetType(p) +#define IDirect3DSurface9_GetContainer(p,a,b) (p)->lpVtbl->GetContainer(p,a,b) +#define IDirect3DSurface9_GetDesc(p,a) (p)->lpVtbl->GetDesc(p,a) +#define IDirect3DSurface9_LockRect(p,a,b,c) (p)->lpVtbl->LockRect(p,a,b,c) +#define IDirect3DSurface9_UnlockRect(p) (p)->lpVtbl->UnlockRect(p) +#define IDirect3DSurface9_GetDC(p,a) (p)->lpVtbl->GetDC(p,a) +#define IDirect3DSurface9_ReleaseDC(p,a) (p)->lpVtbl->ReleaseDC(p,a) +#else +#define IDirect3DSurface9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DSurface9_AddRef(p) (p)->AddRef() +#define IDirect3DSurface9_Release(p) (p)->Release() +#define IDirect3DSurface9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DSurface9_SetPrivateData(p,a,b,c,d) (p)->SetPrivateData(a,b,c,d) +#define IDirect3DSurface9_GetPrivateData(p,a,b,c) (p)->GetPrivateData(a,b,c) +#define IDirect3DSurface9_FreePrivateData(p,a) (p)->FreePrivateData(a) +#define IDirect3DSurface9_SetPriority(p,a) (p)->SetPriority(a) +#define IDirect3DSurface9_GetPriority(p) (p)->GetPriority() +#define IDirect3DSurface9_PreLoad(p) (p)->PreLoad() +#define IDirect3DSurface9_GetType(p) (p)->GetType() +#define IDirect3DSurface9_GetContainer(p,a,b) (p)->GetContainer(a,b) +#define IDirect3DSurface9_GetDesc(p,a) (p)->GetDesc(a) +#define IDirect3DSurface9_LockRect(p,a,b,c) (p)->LockRect(a,b,c) +#define IDirect3DSurface9_UnlockRect(p) (p)->UnlockRect() +#define IDirect3DSurface9_GetDC(p,a) (p)->GetDC(a) +#define IDirect3DSurface9_ReleaseDC(p,a) (p)->ReleaseDC(a) +#endif + + + + + +#undef INTERFACE +#define INTERFACE IDirect3DVolume9 + +DECLARE_INTERFACE_(IDirect3DVolume9, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DVolume9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid,CONST void* pData,DWORD SizeOfData,DWORD Flags) PURE; + STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid,void* pData,DWORD* pSizeOfData) PURE; + STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid) PURE; + STDMETHOD(GetContainer)(THIS_ REFIID riid,void** ppContainer) PURE; + STDMETHOD(GetDesc)(THIS_ D3DVOLUME_DESC *pDesc) PURE; + STDMETHOD(LockBox)(THIS_ D3DLOCKED_BOX * pLockedVolume,CONST D3DBOX* pBox,DWORD Flags) PURE; + STDMETHOD(UnlockBox)(THIS) PURE; + + #ifdef D3D_DEBUG_INFO + LPCWSTR Name; + UINT Width; + UINT Height; + UINT Depth; + DWORD Usage; + D3DFORMAT Format; + D3DPOOL Pool; + UINT LockCount; + LPCWSTR CreationCallStack; + #endif +}; + +typedef struct IDirect3DVolume9 *LPDIRECT3DVOLUME9, *PDIRECT3DVOLUME9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DVolume9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DVolume9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DVolume9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DVolume9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DVolume9_SetPrivateData(p,a,b,c,d) (p)->lpVtbl->SetPrivateData(p,a,b,c,d) +#define IDirect3DVolume9_GetPrivateData(p,a,b,c) (p)->lpVtbl->GetPrivateData(p,a,b,c) +#define IDirect3DVolume9_FreePrivateData(p,a) (p)->lpVtbl->FreePrivateData(p,a) +#define IDirect3DVolume9_GetContainer(p,a,b) (p)->lpVtbl->GetContainer(p,a,b) +#define IDirect3DVolume9_GetDesc(p,a) (p)->lpVtbl->GetDesc(p,a) +#define IDirect3DVolume9_LockBox(p,a,b,c) (p)->lpVtbl->LockBox(p,a,b,c) +#define IDirect3DVolume9_UnlockBox(p) (p)->lpVtbl->UnlockBox(p) +#else +#define IDirect3DVolume9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DVolume9_AddRef(p) (p)->AddRef() +#define IDirect3DVolume9_Release(p) (p)->Release() +#define IDirect3DVolume9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DVolume9_SetPrivateData(p,a,b,c,d) (p)->SetPrivateData(a,b,c,d) +#define IDirect3DVolume9_GetPrivateData(p,a,b,c) (p)->GetPrivateData(a,b,c) +#define IDirect3DVolume9_FreePrivateData(p,a) (p)->FreePrivateData(a) +#define IDirect3DVolume9_GetContainer(p,a,b) (p)->GetContainer(a,b) +#define IDirect3DVolume9_GetDesc(p,a) (p)->GetDesc(a) +#define IDirect3DVolume9_LockBox(p,a,b,c) (p)->LockBox(a,b,c) +#define IDirect3DVolume9_UnlockBox(p) (p)->UnlockBox() +#endif + + + + +#undef INTERFACE +#define INTERFACE IDirect3DQuery9 + +DECLARE_INTERFACE_(IDirect3DQuery9, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DQuery9 methods ***/ + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD_(D3DQUERYTYPE, GetType)(THIS) PURE; + STDMETHOD_(DWORD, GetDataSize)(THIS) PURE; + STDMETHOD(Issue)(THIS_ DWORD dwIssueFlags) PURE; + STDMETHOD(GetData)(THIS_ void* pData,DWORD dwSize,DWORD dwGetDataFlags) PURE; + + #ifdef D3D_DEBUG_INFO + D3DQUERYTYPE Type; + DWORD DataSize; + LPCWSTR CreationCallStack; + #endif +}; + +typedef struct IDirect3DQuery9 *LPDIRECT3DQUERY9, *PDIRECT3DQUERY9; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DQuery9_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DQuery9_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DQuery9_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DQuery9_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DQuery9_GetType(p) (p)->lpVtbl->GetType(p) +#define IDirect3DQuery9_GetDataSize(p) (p)->lpVtbl->GetDataSize(p) +#define IDirect3DQuery9_Issue(p,a) (p)->lpVtbl->Issue(p,a) +#define IDirect3DQuery9_GetData(p,a,b,c) (p)->lpVtbl->GetData(p,a,b,c) +#else +#define IDirect3DQuery9_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DQuery9_AddRef(p) (p)->AddRef() +#define IDirect3DQuery9_Release(p) (p)->Release() +#define IDirect3DQuery9_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DQuery9_GetType(p) (p)->GetType() +#define IDirect3DQuery9_GetDataSize(p) (p)->GetDataSize() +#define IDirect3DQuery9_Issue(p,a) (p)->Issue(a) +#define IDirect3DQuery9_GetData(p,a,b,c) (p)->GetData(a,b,c) +#endif + + +/**************************************************************************** + * Flags for SetPrivateData method on all D3D9 interfaces + * + * The passed pointer is an IUnknown ptr. The SizeOfData argument to SetPrivateData + * must be set to sizeof(IUnknown*). Direct3D will call AddRef through this + * pointer and Release when the private data is destroyed. The data will be + * destroyed when another SetPrivateData with the same GUID is set, when + * FreePrivateData is called, or when the D3D9 object is freed. + ****************************************************************************/ +#define D3DSPD_IUNKNOWN 0x00000001L + +/**************************************************************************** + * + * Flags for IDirect3D9::CreateDevice's BehaviorFlags + * + ****************************************************************************/ + +#define D3DCREATE_FPU_PRESERVE 0x00000002L +#define D3DCREATE_MULTITHREADED 0x00000004L + +#define D3DCREATE_PUREDEVICE 0x00000010L +#define D3DCREATE_SOFTWARE_VERTEXPROCESSING 0x00000020L +#define D3DCREATE_HARDWARE_VERTEXPROCESSING 0x00000040L +#define D3DCREATE_MIXED_VERTEXPROCESSING 0x00000080L + +#define D3DCREATE_DISABLE_DRIVER_MANAGEMENT 0x00000100L +#define D3DCREATE_ADAPTERGROUP_DEVICE 0x00000200L +#define D3DCREATE_DISABLE_DRIVER_MANAGEMENT_EX 0x00000400L + +// This flag causes the D3D runtime not to alter the focus +// window in any way. Use with caution- the burden of supporting +// focus management events (alt-tab, etc.) falls on the +// application, and appropriate responses (switching display +// mode, etc.) should be coded. +#define D3DCREATE_NOWINDOWCHANGES 0x00000800L + +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + +// Disable multithreading for software vertex processing +#define D3DCREATE_DISABLE_PSGP_THREADING 0x00002000L +// This flag enables present statistics on device. +#define D3DCREATE_ENABLE_PRESENTSTATS 0x00004000L +// This flag disables printscreen support in the runtime for this device +#define D3DCREATE_DISABLE_PRINTSCREEN 0x00008000L + +#define D3DCREATE_SCREENSAVER 0x10000000L + + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + + + +/**************************************************************************** + * + * Parameter for IDirect3D9::CreateDevice's Adapter argument + * + ****************************************************************************/ + +#define D3DADAPTER_DEFAULT 0 + +/**************************************************************************** + * + * Flags for IDirect3D9::EnumAdapters + * + ****************************************************************************/ + +/* + * The D3DENUM_WHQL_LEVEL value has been retired for 9Ex and future versions, + * but it needs to be defined here for compatibility with DX9 and earlier versions. + * See the DirectX SDK for sample code on discovering driver signatures. + */ +#define D3DENUM_WHQL_LEVEL 0x00000002L + +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + +/* NO_DRIVERVERSION will not fill out the DriverVersion field, nor will the + DriverVersion be incorporated into the DeviceIdentifier GUID. WINNT only */ +#define D3DENUM_NO_DRIVERVERSION 0x00000004L + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + + +/**************************************************************************** + * + * Maximum number of back-buffers supported in DX9 + * + ****************************************************************************/ + +#define D3DPRESENT_BACK_BUFFERS_MAX 3L + +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + +/**************************************************************************** + * + * Maximum number of back-buffers supported when apps use CreateDeviceEx + * + ****************************************************************************/ + +#define D3DPRESENT_BACK_BUFFERS_MAX_EX 30L + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + +/**************************************************************************** + * + * Flags for IDirect3DDevice9::SetGammaRamp + * + ****************************************************************************/ + +#define D3DSGR_NO_CALIBRATION 0x00000000L +#define D3DSGR_CALIBRATE 0x00000001L + +/**************************************************************************** + * + * Flags for IDirect3DDevice9::SetCursorPosition + * + ****************************************************************************/ + +#define D3DCURSOR_IMMEDIATE_UPDATE 0x00000001L + +/**************************************************************************** + * + * Flags for IDirect3DSwapChain9::Present + * + ****************************************************************************/ + +#define D3DPRESENT_DONOTWAIT 0x00000001L +#define D3DPRESENT_LINEAR_CONTENT 0x00000002L + +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + +#define D3DPRESENT_DONOTFLIP 0x00000004L +#define D3DPRESENT_FLIPRESTART 0x00000008L +#define D3DPRESENT_VIDEO_RESTRICT_TO_MONITOR 0x00000010L + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + + +/**************************************************************************** + * + * Flags for DrawPrimitive/DrawIndexedPrimitive + * Also valid for Begin/BeginIndexed + * Also valid for VertexBuffer::CreateVertexBuffer + ****************************************************************************/ + + +/* + * DirectDraw error codes + */ +#define _FACD3D 0x876 +#define MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code ) +#define MAKE_D3DSTATUS( code ) MAKE_HRESULT( 0, _FACD3D, code ) + +/* + * Direct3D Errors + */ +#define D3D_OK S_OK + +#define D3DERR_WRONGTEXTUREFORMAT MAKE_D3DHRESULT(2072) +#define D3DERR_UNSUPPORTEDCOLOROPERATION MAKE_D3DHRESULT(2073) +#define D3DERR_UNSUPPORTEDCOLORARG MAKE_D3DHRESULT(2074) +#define D3DERR_UNSUPPORTEDALPHAOPERATION MAKE_D3DHRESULT(2075) +#define D3DERR_UNSUPPORTEDALPHAARG MAKE_D3DHRESULT(2076) +#define D3DERR_TOOMANYOPERATIONS MAKE_D3DHRESULT(2077) +#define D3DERR_CONFLICTINGTEXTUREFILTER MAKE_D3DHRESULT(2078) +#define D3DERR_UNSUPPORTEDFACTORVALUE MAKE_D3DHRESULT(2079) +#define D3DERR_CONFLICTINGRENDERSTATE MAKE_D3DHRESULT(2081) +#define D3DERR_UNSUPPORTEDTEXTUREFILTER MAKE_D3DHRESULT(2082) +#define D3DERR_CONFLICTINGTEXTUREPALETTE MAKE_D3DHRESULT(2086) +#define D3DERR_DRIVERINTERNALERROR MAKE_D3DHRESULT(2087) + +#define D3DERR_NOTFOUND MAKE_D3DHRESULT(2150) +#define D3DERR_MOREDATA MAKE_D3DHRESULT(2151) +#define D3DERR_DEVICELOST MAKE_D3DHRESULT(2152) +#define D3DERR_DEVICENOTRESET MAKE_D3DHRESULT(2153) +#define D3DERR_NOTAVAILABLE MAKE_D3DHRESULT(2154) +#define D3DERR_OUTOFVIDEOMEMORY MAKE_D3DHRESULT(380) +#define D3DERR_INVALIDDEVICE MAKE_D3DHRESULT(2155) +#define D3DERR_INVALIDCALL MAKE_D3DHRESULT(2156) +#define D3DERR_DRIVERINVALIDCALL MAKE_D3DHRESULT(2157) +#define D3DERR_WASSTILLDRAWING MAKE_D3DHRESULT(540) +#define D3DOK_NOAUTOGEN MAKE_D3DSTATUS(2159) + +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + + +#define D3DERR_DEVICEREMOVED MAKE_D3DHRESULT(2160) +#define S_NOT_RESIDENT MAKE_D3DSTATUS(2165) +#define S_RESIDENT_IN_SHARED_MEMORY MAKE_D3DSTATUS(2166) +#define S_PRESENT_MODE_CHANGED MAKE_D3DSTATUS(2167) +#define S_PRESENT_OCCLUDED MAKE_D3DSTATUS(2168) +#define D3DERR_DEVICEHUNG MAKE_D3DHRESULT(2164) + + +/********************* +/* D3D9Ex interfaces +/*********************/ + +HRESULT WINAPI Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex**); + + + + +#undef INTERFACE +#define INTERFACE IDirect3D9Ex + +DECLARE_INTERFACE_(IDirect3D9Ex, IDirect3D9) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3D9 methods ***/ + STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE; + STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier) PURE; + STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter,D3DFORMAT Format) PURE; + STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode) PURE; + STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT Adapter,D3DDISPLAYMODE* pMode) PURE; + STDMETHOD(CheckDeviceType)(THIS_ UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed) PURE; + STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat) PURE; + STDMETHOD(CheckDeviceMultiSampleType)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels) PURE; + STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat) PURE; + STDMETHOD(CheckDeviceFormatConversion)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SourceFormat,D3DFORMAT TargetFormat) PURE; + STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps) PURE; + STDMETHOD_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter) PURE; + STDMETHOD(CreateDevice)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface) PURE; + STDMETHOD_(UINT, GetAdapterModeCountEx)(THIS_ UINT Adapter,CONST D3DDISPLAYMODEFILTER* pFilter ) PURE; + STDMETHOD(EnumAdapterModesEx)(THIS_ UINT Adapter,CONST D3DDISPLAYMODEFILTER* pFilter,UINT Mode,D3DDISPLAYMODEEX* pMode) PURE; + STDMETHOD(GetAdapterDisplayModeEx)(THIS_ UINT Adapter,D3DDISPLAYMODEEX* pMode,D3DDISPLAYROTATION* pRotation) PURE; + STDMETHOD(CreateDeviceEx)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,D3DDISPLAYMODEEX* pFullscreenDisplayMode,IDirect3DDevice9Ex** ppReturnedDeviceInterface) PURE; + STDMETHOD(GetAdapterLUID)(THIS_ UINT Adapter,LUID * pLUID) PURE; +}; + +typedef struct IDirect3D9Ex *LPDIRECT3D9EX, *PDIRECT3D9EX; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3D9Ex_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3D9Ex_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3D9Ex_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3D9Ex_GetAdapterCount(p) (p)->lpVtbl->GetAdapterCount(p) +#define IDirect3D9Ex_GetAdapterIdentifier(p,a,b,c) (p)->lpVtbl->GetAdapterIdentifier(p,a,b,c) +#define IDirect3D9Ex_GetAdapterModeCount(p,a,b) (p)->lpVtbl->GetAdapterModeCount(p,a,b) +#define IDirect3D9Ex_EnumAdapterModes(p,a,b,c,d) (p)->lpVtbl->EnumAdapterModes(p,a,b,c,d) +#define IDirect3D9Ex_GetAdapterDisplayMode(p,a,b) (p)->lpVtbl->GetAdapterDisplayMode(p,a,b) +#define IDirect3D9Ex_CheckDeviceType(p,a,b,c,d,e) (p)->lpVtbl->CheckDeviceType(p,a,b,c,d,e) +#define IDirect3D9Ex_CheckDeviceFormat(p,a,b,c,d,e,f) (p)->lpVtbl->CheckDeviceFormat(p,a,b,c,d,e,f) +#define IDirect3D9Ex_CheckDeviceMultiSampleType(p,a,b,c,d,e,f) (p)->lpVtbl->CheckDeviceMultiSampleType(p,a,b,c,d,e,f) +#define IDirect3D9Ex_CheckDepthStencilMatch(p,a,b,c,d,e) (p)->lpVtbl->CheckDepthStencilMatch(p,a,b,c,d,e) +#define IDirect3D9Ex_CheckDeviceFormatConversion(p,a,b,c,d) (p)->lpVtbl->CheckDeviceFormatConversion(p,a,b,c,d) +#define IDirect3D9Ex_GetDeviceCaps(p,a,b,c) (p)->lpVtbl->GetDeviceCaps(p,a,b,c) +#define IDirect3D9Ex_GetAdapterMonitor(p,a) (p)->lpVtbl->GetAdapterMonitor(p,a) +#define IDirect3D9Ex_CreateDevice(p,a,b,c,d,e,f) (p)->lpVtbl->CreateDevice(p,a,b,c,d,e,f) +#define IDirect3D9Ex_GetAdapterModeCountEx(p,a,b) (p)->lpVtbl->GetAdapterModeCountEx(p,a,b) +#define IDirect3D9Ex_EnumAdapterModesEx(p,a,b,c,d) (p)->lpVtbl->EnumAdapterModesEx(p,a,b,c,d) +#define IDirect3D9Ex_GetAdapterDisplayModeEx(p,a,b,c) (p)->lpVtbl->GetAdapterDisplayModeEx(p,a,b,c) +#define IDirect3D9Ex_CreateDeviceEx(p,a,b,c,d,e,f,g) (p)->lpVtbl->CreateDeviceEx(p,a,b,c,d,e,f,g) +#define IDirect3D9Ex_GetAdapterLUID(p,a,b) (p)->lpVtbl->GetAdapterLUID(p,a,b) +#else +#define IDirect3D9Ex_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3D9Ex_AddRef(p) (p)->AddRef() +#define IDirect3D9Ex_Release(p) (p)->Release() +#define IDirect3D9Ex_GetAdapterCount(p) (p)->GetAdapterCount() +#define IDirect3D9Ex_GetAdapterIdentifier(p,a,b,c) (p)->GetAdapterIdentifier(a,b,c) +#define IDirect3D9Ex_GetAdapterModeCount(p,a,b) (p)->GetAdapterModeCount(a,b) +#define IDirect3D9Ex_EnumAdapterModes(p,a,b,c,d) (p)->EnumAdapterModes(a,b,c,d) +#define IDirect3D9Ex_GetAdapterDisplayMode(p,a,b) (p)->GetAdapterDisplayMode(a,b) +#define IDirect3D9Ex_CheckDeviceType(p,a,b,c,d,e) (p)->CheckDeviceType(a,b,c,d,e) +#define IDirect3D9Ex_CheckDeviceFormat(p,a,b,c,d,e,f) (p)->CheckDeviceFormat(a,b,c,d,e,f) +#define IDirect3D9Ex_CheckDeviceMultiSampleType(p,a,b,c,d,e,f) (p)->CheckDeviceMultiSampleType(a,b,c,d,e,f) +#define IDirect3D9Ex_CheckDepthStencilMatch(p,a,b,c,d,e) (p)->CheckDepthStencilMatch(a,b,c,d,e) +#define IDirect3D9Ex_CheckDeviceFormatConversion(p,a,b,c,d) (p)->CheckDeviceFormatConversion(a,b,c,d) +#define IDirect3D9Ex_GetDeviceCaps(p,a,b,c) (p)->GetDeviceCaps(a,b,c) +#define IDirect3D9Ex_GetAdapterMonitor(p,a) (p)->GetAdapterMonitor(a) +#define IDirect3D9Ex_CreateDevice(p,a,b,c,d,e,f) (p)->CreateDevice(a,b,c,d,e,f) +#define IDirect3D9Ex_GetAdapterModeCountEx(p,a,b) (p)->GetAdapterModeCountEx(a,b) +#define IDirect3D9Ex_EnumAdapterModesEx(p,a,b,c,d) (p)->EnumAdapterModesEx(a,b,c,d) +#define IDirect3D9Ex_GetAdapterDisplayModeEx(p,a,b,c) (p)->GetAdapterDisplayModeEx(a,b,c) +#define IDirect3D9Ex_CreateDeviceEx(p,a,b,c,d,e,f,g) (p)->CreateDeviceEx(a,b,c,d,e,f,g) +#define IDirect3D9Ex_GetAdapterLUID(p,a,b) (p)->GetAdapterLUID(a,b) +#endif + + + + + + + + + + + + + + + + + + + + + + + + +#undef INTERFACE +#define INTERFACE IDirect3DDevice9Ex + +DECLARE_INTERFACE_(IDirect3DDevice9Ex, IDirect3DDevice9) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DDevice9 methods ***/ + STDMETHOD(TestCooperativeLevel)(THIS) PURE; + STDMETHOD_(UINT, GetAvailableTextureMem)(THIS) PURE; + STDMETHOD(EvictManagedResources)(THIS) PURE; + STDMETHOD(GetDirect3D)(THIS_ IDirect3D9** ppD3D9) PURE; + STDMETHOD(GetDeviceCaps)(THIS_ D3DCAPS9* pCaps) PURE; + STDMETHOD(GetDisplayMode)(THIS_ UINT iSwapChain,D3DDISPLAYMODE* pMode) PURE; + STDMETHOD(GetCreationParameters)(THIS_ D3DDEVICE_CREATION_PARAMETERS *pParameters) PURE; + STDMETHOD(SetCursorProperties)(THIS_ UINT XHotSpot,UINT YHotSpot,IDirect3DSurface9* pCursorBitmap) PURE; + STDMETHOD_(void, SetCursorPosition)(THIS_ int X,int Y,DWORD Flags) PURE; + STDMETHOD_(BOOL, ShowCursor)(THIS_ BOOL bShow) PURE; + STDMETHOD(CreateAdditionalSwapChain)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DSwapChain9** pSwapChain) PURE; + STDMETHOD(GetSwapChain)(THIS_ UINT iSwapChain,IDirect3DSwapChain9** pSwapChain) PURE; + STDMETHOD_(UINT, GetNumberOfSwapChains)(THIS) PURE; + STDMETHOD(Reset)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters) PURE; + STDMETHOD(Present)(THIS_ CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) PURE; + STDMETHOD(GetBackBuffer)(THIS_ UINT iSwapChain,UINT iBackBuffer,D3DBACKBUFFER_TYPE Type,IDirect3DSurface9** ppBackBuffer) PURE; + STDMETHOD(GetRasterStatus)(THIS_ UINT iSwapChain,D3DRASTER_STATUS* pRasterStatus) PURE; + STDMETHOD(SetDialogBoxMode)(THIS_ BOOL bEnableDialogs) PURE; + STDMETHOD_(void, SetGammaRamp)(THIS_ UINT iSwapChain,DWORD Flags,CONST D3DGAMMARAMP* pRamp) PURE; + STDMETHOD_(void, GetGammaRamp)(THIS_ UINT iSwapChain,D3DGAMMARAMP* pRamp) PURE; + STDMETHOD(CreateTexture)(THIS_ UINT Width,UINT Height,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DTexture9** ppTexture,HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateVolumeTexture)(THIS_ UINT Width,UINT Height,UINT Depth,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DVolumeTexture9** ppVolumeTexture,HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateCubeTexture)(THIS_ UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DCubeTexture9** ppCubeTexture,HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateVertexBuffer)(THIS_ UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9** ppVertexBuffer,HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateIndexBuffer)(THIS_ UINT Length,DWORD Usage,D3DFORMAT Format,D3DPOOL Pool,IDirect3DIndexBuffer9** ppIndexBuffer,HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateRenderTarget)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Lockable,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle) PURE; + STDMETHOD(CreateDepthStencilSurface)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Discard,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle) PURE; + STDMETHOD(UpdateSurface)(THIS_ IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestinationSurface,CONST POINT* pDestPoint) PURE; + STDMETHOD(UpdateTexture)(THIS_ IDirect3DBaseTexture9* pSourceTexture,IDirect3DBaseTexture9* pDestinationTexture) PURE; + STDMETHOD(GetRenderTargetData)(THIS_ IDirect3DSurface9* pRenderTarget,IDirect3DSurface9* pDestSurface) PURE; + STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain,IDirect3DSurface9* pDestSurface) PURE; + STDMETHOD(StretchRect)(THIS_ IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect,IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect,D3DTEXTUREFILTERTYPE Filter) PURE; + STDMETHOD(ColorFill)(THIS_ IDirect3DSurface9* pSurface,CONST RECT* pRect,D3DCOLOR color) PURE; + STDMETHOD(CreateOffscreenPlainSurface)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DPOOL Pool,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle) PURE; + STDMETHOD(SetRenderTarget)(THIS_ DWORD RenderTargetIndex,IDirect3DSurface9* pRenderTarget) PURE; + STDMETHOD(GetRenderTarget)(THIS_ DWORD RenderTargetIndex,IDirect3DSurface9** ppRenderTarget) PURE; + STDMETHOD(SetDepthStencilSurface)(THIS_ IDirect3DSurface9* pNewZStencil) PURE; + STDMETHOD(GetDepthStencilSurface)(THIS_ IDirect3DSurface9** ppZStencilSurface) PURE; + STDMETHOD(BeginScene)(THIS) PURE; + STDMETHOD(EndScene)(THIS) PURE; + STDMETHOD(Clear)(THIS_ DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3DCOLOR Color,float Z,DWORD Stencil) PURE; + STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) PURE; + STDMETHOD(GetTransform)(THIS_ D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) PURE; + STDMETHOD(MultiplyTransform)(THIS_ D3DTRANSFORMSTATETYPE,CONST D3DMATRIX*) PURE; + STDMETHOD(SetViewport)(THIS_ CONST D3DVIEWPORT9* pViewport) PURE; + STDMETHOD(GetViewport)(THIS_ D3DVIEWPORT9* pViewport) PURE; + STDMETHOD(SetMaterial)(THIS_ CONST D3DMATERIAL9* pMaterial) PURE; + STDMETHOD(GetMaterial)(THIS_ D3DMATERIAL9* pMaterial) PURE; + STDMETHOD(SetLight)(THIS_ DWORD Index,CONST D3DLIGHT9*) PURE; + STDMETHOD(GetLight)(THIS_ DWORD Index,D3DLIGHT9*) PURE; + STDMETHOD(LightEnable)(THIS_ DWORD Index,BOOL Enable) PURE; + STDMETHOD(GetLightEnable)(THIS_ DWORD Index,BOOL* pEnable) PURE; + STDMETHOD(SetClipPlane)(THIS_ DWORD Index,CONST float* pPlane) PURE; + STDMETHOD(GetClipPlane)(THIS_ DWORD Index,float* pPlane) PURE; + STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE State,DWORD Value) PURE; + STDMETHOD(GetRenderState)(THIS_ D3DRENDERSTATETYPE State,DWORD* pValue) PURE; + STDMETHOD(CreateStateBlock)(THIS_ D3DSTATEBLOCKTYPE Type,IDirect3DStateBlock9** ppSB) PURE; + STDMETHOD(BeginStateBlock)(THIS) PURE; + STDMETHOD(EndStateBlock)(THIS_ IDirect3DStateBlock9** ppSB) PURE; + STDMETHOD(SetClipStatus)(THIS_ CONST D3DCLIPSTATUS9* pClipStatus) PURE; + STDMETHOD(GetClipStatus)(THIS_ D3DCLIPSTATUS9* pClipStatus) PURE; + STDMETHOD(GetTexture)(THIS_ DWORD Stage,IDirect3DBaseTexture9** ppTexture) PURE; + STDMETHOD(SetTexture)(THIS_ DWORD Stage,IDirect3DBaseTexture9* pTexture) PURE; + STDMETHOD(GetTextureStageState)(THIS_ DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) PURE; + STDMETHOD(SetTextureStageState)(THIS_ DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD Value) PURE; + STDMETHOD(GetSamplerState)(THIS_ DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD* pValue) PURE; + STDMETHOD(SetSamplerState)(THIS_ DWORD Sampler,D3DSAMPLERSTATETYPE Type,DWORD Value) PURE; + STDMETHOD(ValidateDevice)(THIS_ DWORD* pNumPasses) PURE; + STDMETHOD(SetPaletteEntries)(THIS_ UINT PaletteNumber,CONST PALETTEENTRY* pEntries) PURE; + STDMETHOD(GetPaletteEntries)(THIS_ UINT PaletteNumber,PALETTEENTRY* pEntries) PURE; + STDMETHOD(SetCurrentTexturePalette)(THIS_ UINT PaletteNumber) PURE; + STDMETHOD(GetCurrentTexturePalette)(THIS_ UINT *PaletteNumber) PURE; + STDMETHOD(SetScissorRect)(THIS_ CONST RECT* pRect) PURE; + STDMETHOD(GetScissorRect)(THIS_ RECT* pRect) PURE; + STDMETHOD(SetSoftwareVertexProcessing)(THIS_ BOOL bSoftware) PURE; + STDMETHOD_(BOOL, GetSoftwareVertexProcessing)(THIS) PURE; + STDMETHOD(SetNPatchMode)(THIS_ float nSegments) PURE; + STDMETHOD_(float, GetNPatchMode)(THIS) PURE; + STDMETHOD(DrawPrimitive)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT StartVertex,UINT PrimitiveCount) PURE; + STDMETHOD(DrawIndexedPrimitive)(THIS_ D3DPRIMITIVETYPE,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount) PURE; + STDMETHOD(DrawPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) PURE; + STDMETHOD(DrawIndexedPrimitiveUP)(THIS_ D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,UINT NumVertices,UINT PrimitiveCount,CONST void* pIndexData,D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) PURE; + STDMETHOD(ProcessVertices)(THIS_ UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer9* pDestBuffer,IDirect3DVertexDeclaration9* pVertexDecl,DWORD Flags) PURE; + STDMETHOD(CreateVertexDeclaration)(THIS_ CONST D3DVERTEXELEMENT9* pVertexElements,IDirect3DVertexDeclaration9** ppDecl) PURE; + STDMETHOD(SetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9* pDecl) PURE; + STDMETHOD(GetVertexDeclaration)(THIS_ IDirect3DVertexDeclaration9** ppDecl) PURE; + STDMETHOD(SetFVF)(THIS_ DWORD FVF) PURE; + STDMETHOD(GetFVF)(THIS_ DWORD* pFVF) PURE; + STDMETHOD(CreateVertexShader)(THIS_ CONST DWORD* pFunction,IDirect3DVertexShader9** ppShader) PURE; + STDMETHOD(SetVertexShader)(THIS_ IDirect3DVertexShader9* pShader) PURE; + STDMETHOD(GetVertexShader)(THIS_ IDirect3DVertexShader9** ppShader) PURE; + STDMETHOD(SetVertexShaderConstantF)(THIS_ UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) PURE; + STDMETHOD(GetVertexShaderConstantF)(THIS_ UINT StartRegister,float* pConstantData,UINT Vector4fCount) PURE; + STDMETHOD(SetVertexShaderConstantI)(THIS_ UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount) PURE; + STDMETHOD(GetVertexShaderConstantI)(THIS_ UINT StartRegister,int* pConstantData,UINT Vector4iCount) PURE; + STDMETHOD(SetVertexShaderConstantB)(THIS_ UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount) PURE; + STDMETHOD(GetVertexShaderConstantB)(THIS_ UINT StartRegister,BOOL* pConstantData,UINT BoolCount) PURE; + STDMETHOD(SetStreamSource)(THIS_ UINT StreamNumber,IDirect3DVertexBuffer9* pStreamData,UINT OffsetInBytes,UINT Stride) PURE; + STDMETHOD(GetStreamSource)(THIS_ UINT StreamNumber,IDirect3DVertexBuffer9** ppStreamData,UINT* pOffsetInBytes,UINT* pStride) PURE; + STDMETHOD(SetStreamSourceFreq)(THIS_ UINT StreamNumber,UINT Setting) PURE; + STDMETHOD(GetStreamSourceFreq)(THIS_ UINT StreamNumber,UINT* pSetting) PURE; + STDMETHOD(SetIndices)(THIS_ IDirect3DIndexBuffer9* pIndexData) PURE; + STDMETHOD(GetIndices)(THIS_ IDirect3DIndexBuffer9** ppIndexData) PURE; + STDMETHOD(CreatePixelShader)(THIS_ CONST DWORD* pFunction,IDirect3DPixelShader9** ppShader) PURE; + STDMETHOD(SetPixelShader)(THIS_ IDirect3DPixelShader9* pShader) PURE; + STDMETHOD(GetPixelShader)(THIS_ IDirect3DPixelShader9** ppShader) PURE; + STDMETHOD(SetPixelShaderConstantF)(THIS_ UINT StartRegister,CONST float* pConstantData,UINT Vector4fCount) PURE; + STDMETHOD(GetPixelShaderConstantF)(THIS_ UINT StartRegister,float* pConstantData,UINT Vector4fCount) PURE; + STDMETHOD(SetPixelShaderConstantI)(THIS_ UINT StartRegister,CONST int* pConstantData,UINT Vector4iCount) PURE; + STDMETHOD(GetPixelShaderConstantI)(THIS_ UINT StartRegister,int* pConstantData,UINT Vector4iCount) PURE; + STDMETHOD(SetPixelShaderConstantB)(THIS_ UINT StartRegister,CONST BOOL* pConstantData,UINT BoolCount) PURE; + STDMETHOD(GetPixelShaderConstantB)(THIS_ UINT StartRegister,BOOL* pConstantData,UINT BoolCount) PURE; + STDMETHOD(DrawRectPatch)(THIS_ UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) PURE; + STDMETHOD(DrawTriPatch)(THIS_ UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) PURE; + STDMETHOD(DeletePatch)(THIS_ UINT Handle) PURE; + STDMETHOD(CreateQuery)(THIS_ D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery) PURE; + STDMETHOD(SetConvolutionMonoKernel)(THIS_ UINT width,UINT height,float* rows,float* columns) PURE; + STDMETHOD(ComposeRects)(THIS_ IDirect3DSurface9* pSrc,IDirect3DSurface9* pDst,IDirect3DVertexBuffer9* pSrcRectDescs,UINT NumRects,IDirect3DVertexBuffer9* pDstRectDescs,D3DCOMPOSERECTSOP Operation,int Xoffset,int Yoffset) PURE; + STDMETHOD(PresentEx)(THIS_ CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion,DWORD dwFlags) PURE; + STDMETHOD(GetGPUThreadPriority)(THIS_ INT* pPriority) PURE; + STDMETHOD(SetGPUThreadPriority)(THIS_ INT Priority) PURE; + STDMETHOD(WaitForVBlank)(THIS_ UINT iSwapChain) PURE; + STDMETHOD(CheckResourceResidency)(THIS_ IDirect3DResource9** pResourceArray,UINT32 NumResources) PURE; + STDMETHOD(SetMaximumFrameLatency)(THIS_ UINT MaxLatency) PURE; + STDMETHOD(GetMaximumFrameLatency)(THIS_ UINT* pMaxLatency) PURE; + STDMETHOD(CheckDeviceState)(THIS_ HWND hDestinationWindow) PURE; + STDMETHOD(CreateRenderTargetEx)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Lockable,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle,DWORD Usage) PURE; + STDMETHOD(CreateOffscreenPlainSurfaceEx)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DPOOL Pool,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle,DWORD Usage) PURE; + STDMETHOD(CreateDepthStencilSurfaceEx)(THIS_ UINT Width,UINT Height,D3DFORMAT Format,D3DMULTISAMPLE_TYPE MultiSample,DWORD MultisampleQuality,BOOL Discard,IDirect3DSurface9** ppSurface,HANDLE* pSharedHandle,DWORD Usage) PURE; + STDMETHOD(ResetEx)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters,D3DDISPLAYMODEEX *pFullscreenDisplayMode) PURE; + STDMETHOD(GetDisplayModeEx)(THIS_ UINT iSwapChain,D3DDISPLAYMODEEX* pMode,D3DDISPLAYROTATION* pRotation) PURE; +}; + +typedef struct IDirect3DDevice9Ex *LPDIRECT3DDEVICE9EX, *PDIRECT3DDEVICE9EX; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DDevice9Ex_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DDevice9Ex_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DDevice9Ex_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DDevice9Ex_TestCooperativeLevel(p) (p)->lpVtbl->TestCooperativeLevel(p) +#define IDirect3DDevice9Ex_GetAvailableTextureMem(p) (p)->lpVtbl->GetAvailableTextureMem(p) +#define IDirect3DDevice9Ex_EvictManagedResources(p) (p)->lpVtbl->EvictManagedResources(p) +#define IDirect3DDevice9Ex_GetDirect3D(p,a) (p)->lpVtbl->GetDirect3D(p,a) +#define IDirect3DDevice9Ex_GetDeviceCaps(p,a) (p)->lpVtbl->GetDeviceCaps(p,a) +#define IDirect3DDevice9Ex_GetDisplayMode(p,a,b) (p)->lpVtbl->GetDisplayMode(p,a,b) +#define IDirect3DDevice9Ex_GetCreationParameters(p,a) (p)->lpVtbl->GetCreationParameters(p,a) +#define IDirect3DDevice9Ex_SetCursorProperties(p,a,b,c) (p)->lpVtbl->SetCursorProperties(p,a,b,c) +#define IDirect3DDevice9Ex_SetCursorPosition(p,a,b,c) (p)->lpVtbl->SetCursorPosition(p,a,b,c) +#define IDirect3DDevice9Ex_ShowCursor(p,a) (p)->lpVtbl->ShowCursor(p,a) +#define IDirect3DDevice9Ex_CreateAdditionalSwapChain(p,a,b) (p)->lpVtbl->CreateAdditionalSwapChain(p,a,b) +#define IDirect3DDevice9Ex_GetSwapChain(p,a,b) (p)->lpVtbl->GetSwapChain(p,a,b) +#define IDirect3DDevice9Ex_GetNumberOfSwapChains(p) (p)->lpVtbl->GetNumberOfSwapChains(p) +#define IDirect3DDevice9Ex_Reset(p,a) (p)->lpVtbl->Reset(p,a) +#define IDirect3DDevice9Ex_Present(p,a,b,c,d) (p)->lpVtbl->Present(p,a,b,c,d) +#define IDirect3DDevice9Ex_GetBackBuffer(p,a,b,c,d) (p)->lpVtbl->GetBackBuffer(p,a,b,c,d) +#define IDirect3DDevice9Ex_GetRasterStatus(p,a,b) (p)->lpVtbl->GetRasterStatus(p,a,b) +#define IDirect3DDevice9Ex_SetDialogBoxMode(p,a) (p)->lpVtbl->SetDialogBoxMode(p,a) +#define IDirect3DDevice9Ex_SetGammaRamp(p,a,b,c) (p)->lpVtbl->SetGammaRamp(p,a,b,c) +#define IDirect3DDevice9Ex_GetGammaRamp(p,a,b) (p)->lpVtbl->GetGammaRamp(p,a,b) +#define IDirect3DDevice9Ex_CreateTexture(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->CreateTexture(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i) (p)->lpVtbl->CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9Ex_CreateCubeTexture(p,a,b,c,d,e,f,g) (p)->lpVtbl->CreateCubeTexture(p,a,b,c,d,e,f,g) +#define IDirect3DDevice9Ex_CreateVertexBuffer(p,a,b,c,d,e,f) (p)->lpVtbl->CreateVertexBuffer(p,a,b,c,d,e,f) +#define IDirect3DDevice9Ex_CreateIndexBuffer(p,a,b,c,d,e,f) (p)->lpVtbl->CreateIndexBuffer(p,a,b,c,d,e,f) +#define IDirect3DDevice9Ex_CreateRenderTarget(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->CreateRenderTarget(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_UpdateSurface(p,a,b,c,d) (p)->lpVtbl->UpdateSurface(p,a,b,c,d) +#define IDirect3DDevice9Ex_UpdateTexture(p,a,b) (p)->lpVtbl->UpdateTexture(p,a,b) +#define IDirect3DDevice9Ex_GetRenderTargetData(p,a,b) (p)->lpVtbl->GetRenderTargetData(p,a,b) +#define IDirect3DDevice9Ex_GetFrontBufferData(p,a,b) (p)->lpVtbl->GetFrontBufferData(p,a,b) +#define IDirect3DDevice9Ex_StretchRect(p,a,b,c,d,e) (p)->lpVtbl->StretchRect(p,a,b,c,d,e) +#define IDirect3DDevice9Ex_ColorFill(p,a,b,c) (p)->lpVtbl->ColorFill(p,a,b,c) +#define IDirect3DDevice9Ex_CreateOffscreenPlainSurface(p,a,b,c,d,e,f) (p)->lpVtbl->CreateOffscreenPlainSurface(p,a,b,c,d,e,f) +#define IDirect3DDevice9Ex_SetRenderTarget(p,a,b) (p)->lpVtbl->SetRenderTarget(p,a,b) +#define IDirect3DDevice9Ex_GetRenderTarget(p,a,b) (p)->lpVtbl->GetRenderTarget(p,a,b) +#define IDirect3DDevice9Ex_SetDepthStencilSurface(p,a) (p)->lpVtbl->SetDepthStencilSurface(p,a) +#define IDirect3DDevice9Ex_GetDepthStencilSurface(p,a) (p)->lpVtbl->GetDepthStencilSurface(p,a) +#define IDirect3DDevice9Ex_BeginScene(p) (p)->lpVtbl->BeginScene(p) +#define IDirect3DDevice9Ex_EndScene(p) (p)->lpVtbl->EndScene(p) +#define IDirect3DDevice9Ex_Clear(p,a,b,c,d,e,f) (p)->lpVtbl->Clear(p,a,b,c,d,e,f) +#define IDirect3DDevice9Ex_SetTransform(p,a,b) (p)->lpVtbl->SetTransform(p,a,b) +#define IDirect3DDevice9Ex_GetTransform(p,a,b) (p)->lpVtbl->GetTransform(p,a,b) +#define IDirect3DDevice9Ex_MultiplyTransform(p,a,b) (p)->lpVtbl->MultiplyTransform(p,a,b) +#define IDirect3DDevice9Ex_SetViewport(p,a) (p)->lpVtbl->SetViewport(p,a) +#define IDirect3DDevice9Ex_GetViewport(p,a) (p)->lpVtbl->GetViewport(p,a) +#define IDirect3DDevice9Ex_SetMaterial(p,a) (p)->lpVtbl->SetMaterial(p,a) +#define IDirect3DDevice9Ex_GetMaterial(p,a) (p)->lpVtbl->GetMaterial(p,a) +#define IDirect3DDevice9Ex_SetLight(p,a,b) (p)->lpVtbl->SetLight(p,a,b) +#define IDirect3DDevice9Ex_GetLight(p,a,b) (p)->lpVtbl->GetLight(p,a,b) +#define IDirect3DDevice9Ex_LightEnable(p,a,b) (p)->lpVtbl->LightEnable(p,a,b) +#define IDirect3DDevice9Ex_GetLightEnable(p,a,b) (p)->lpVtbl->GetLightEnable(p,a,b) +#define IDirect3DDevice9Ex_SetClipPlane(p,a,b) (p)->lpVtbl->SetClipPlane(p,a,b) +#define IDirect3DDevice9Ex_GetClipPlane(p,a,b) (p)->lpVtbl->GetClipPlane(p,a,b) +#define IDirect3DDevice9Ex_SetRenderState(p,a,b) (p)->lpVtbl->SetRenderState(p,a,b) +#define IDirect3DDevice9Ex_GetRenderState(p,a,b) (p)->lpVtbl->GetRenderState(p,a,b) +#define IDirect3DDevice9Ex_CreateStateBlock(p,a,b) (p)->lpVtbl->CreateStateBlock(p,a,b) +#define IDirect3DDevice9Ex_BeginStateBlock(p) (p)->lpVtbl->BeginStateBlock(p) +#define IDirect3DDevice9Ex_EndStateBlock(p,a) (p)->lpVtbl->EndStateBlock(p,a) +#define IDirect3DDevice9Ex_SetClipStatus(p,a) (p)->lpVtbl->SetClipStatus(p,a) +#define IDirect3DDevice9Ex_GetClipStatus(p,a) (p)->lpVtbl->GetClipStatus(p,a) +#define IDirect3DDevice9Ex_GetTexture(p,a,b) (p)->lpVtbl->GetTexture(p,a,b) +#define IDirect3DDevice9Ex_SetTexture(p,a,b) (p)->lpVtbl->SetTexture(p,a,b) +#define IDirect3DDevice9Ex_GetTextureStageState(p,a,b,c) (p)->lpVtbl->GetTextureStageState(p,a,b,c) +#define IDirect3DDevice9Ex_SetTextureStageState(p,a,b,c) (p)->lpVtbl->SetTextureStageState(p,a,b,c) +#define IDirect3DDevice9Ex_GetSamplerState(p,a,b,c) (p)->lpVtbl->GetSamplerState(p,a,b,c) +#define IDirect3DDevice9Ex_SetSamplerState(p,a,b,c) (p)->lpVtbl->SetSamplerState(p,a,b,c) +#define IDirect3DDevice9Ex_ValidateDevice(p,a) (p)->lpVtbl->ValidateDevice(p,a) +#define IDirect3DDevice9Ex_SetPaletteEntries(p,a,b) (p)->lpVtbl->SetPaletteEntries(p,a,b) +#define IDirect3DDevice9Ex_GetPaletteEntries(p,a,b) (p)->lpVtbl->GetPaletteEntries(p,a,b) +#define IDirect3DDevice9Ex_SetCurrentTexturePalette(p,a) (p)->lpVtbl->SetCurrentTexturePalette(p,a) +#define IDirect3DDevice9Ex_GetCurrentTexturePalette(p,a) (p)->lpVtbl->GetCurrentTexturePalette(p,a) +#define IDirect3DDevice9Ex_SetScissorRect(p,a) (p)->lpVtbl->SetScissorRect(p,a) +#define IDirect3DDevice9Ex_GetScissorRect(p,a) (p)->lpVtbl->GetScissorRect(p,a) +#define IDirect3DDevice9Ex_SetSoftwareVertexProcessing(p,a) (p)->lpVtbl->SetSoftwareVertexProcessing(p,a) +#define IDirect3DDevice9Ex_GetSoftwareVertexProcessing(p) (p)->lpVtbl->GetSoftwareVertexProcessing(p) +#define IDirect3DDevice9Ex_SetNPatchMode(p,a) (p)->lpVtbl->SetNPatchMode(p,a) +#define IDirect3DDevice9Ex_GetNPatchMode(p) (p)->lpVtbl->GetNPatchMode(p) +#define IDirect3DDevice9Ex_DrawPrimitive(p,a,b,c) (p)->lpVtbl->DrawPrimitive(p,a,b,c) +#define IDirect3DDevice9Ex_DrawIndexedPrimitive(p,a,b,c,d,e,f) (p)->lpVtbl->DrawIndexedPrimitive(p,a,b,c,d,e,f) +#define IDirect3DDevice9Ex_DrawPrimitiveUP(p,a,b,c,d) (p)->lpVtbl->DrawPrimitiveUP(p,a,b,c,d) +#define IDirect3DDevice9Ex_DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_ProcessVertices(p,a,b,c,d,e,f) (p)->lpVtbl->ProcessVertices(p,a,b,c,d,e,f) +#define IDirect3DDevice9Ex_CreateVertexDeclaration(p,a,b) (p)->lpVtbl->CreateVertexDeclaration(p,a,b) +#define IDirect3DDevice9Ex_SetVertexDeclaration(p,a) (p)->lpVtbl->SetVertexDeclaration(p,a) +#define IDirect3DDevice9Ex_GetVertexDeclaration(p,a) (p)->lpVtbl->GetVertexDeclaration(p,a) +#define IDirect3DDevice9Ex_SetFVF(p,a) (p)->lpVtbl->SetFVF(p,a) +#define IDirect3DDevice9Ex_GetFVF(p,a) (p)->lpVtbl->GetFVF(p,a) +#define IDirect3DDevice9Ex_CreateVertexShader(p,a,b) (p)->lpVtbl->CreateVertexShader(p,a,b) +#define IDirect3DDevice9Ex_SetVertexShader(p,a) (p)->lpVtbl->SetVertexShader(p,a) +#define IDirect3DDevice9Ex_GetVertexShader(p,a) (p)->lpVtbl->GetVertexShader(p,a) +#define IDirect3DDevice9Ex_SetVertexShaderConstantF(p,a,b,c) (p)->lpVtbl->SetVertexShaderConstantF(p,a,b,c) +#define IDirect3DDevice9Ex_GetVertexShaderConstantF(p,a,b,c) (p)->lpVtbl->GetVertexShaderConstantF(p,a,b,c) +#define IDirect3DDevice9Ex_SetVertexShaderConstantI(p,a,b,c) (p)->lpVtbl->SetVertexShaderConstantI(p,a,b,c) +#define IDirect3DDevice9Ex_GetVertexShaderConstantI(p,a,b,c) (p)->lpVtbl->GetVertexShaderConstantI(p,a,b,c) +#define IDirect3DDevice9Ex_SetVertexShaderConstantB(p,a,b,c) (p)->lpVtbl->SetVertexShaderConstantB(p,a,b,c) +#define IDirect3DDevice9Ex_GetVertexShaderConstantB(p,a,b,c) (p)->lpVtbl->GetVertexShaderConstantB(p,a,b,c) +#define IDirect3DDevice9Ex_SetStreamSource(p,a,b,c,d) (p)->lpVtbl->SetStreamSource(p,a,b,c,d) +#define IDirect3DDevice9Ex_GetStreamSource(p,a,b,c,d) (p)->lpVtbl->GetStreamSource(p,a,b,c,d) +#define IDirect3DDevice9Ex_SetStreamSourceFreq(p,a,b) (p)->lpVtbl->SetStreamSourceFreq(p,a,b) +#define IDirect3DDevice9Ex_GetStreamSourceFreq(p,a,b) (p)->lpVtbl->GetStreamSourceFreq(p,a,b) +#define IDirect3DDevice9Ex_SetIndices(p,a) (p)->lpVtbl->SetIndices(p,a) +#define IDirect3DDevice9Ex_GetIndices(p,a) (p)->lpVtbl->GetIndices(p,a) +#define IDirect3DDevice9Ex_CreatePixelShader(p,a,b) (p)->lpVtbl->CreatePixelShader(p,a,b) +#define IDirect3DDevice9Ex_SetPixelShader(p,a) (p)->lpVtbl->SetPixelShader(p,a) +#define IDirect3DDevice9Ex_GetPixelShader(p,a) (p)->lpVtbl->GetPixelShader(p,a) +#define IDirect3DDevice9Ex_SetPixelShaderConstantF(p,a,b,c) (p)->lpVtbl->SetPixelShaderConstantF(p,a,b,c) +#define IDirect3DDevice9Ex_GetPixelShaderConstantF(p,a,b,c) (p)->lpVtbl->GetPixelShaderConstantF(p,a,b,c) +#define IDirect3DDevice9Ex_SetPixelShaderConstantI(p,a,b,c) (p)->lpVtbl->SetPixelShaderConstantI(p,a,b,c) +#define IDirect3DDevice9Ex_GetPixelShaderConstantI(p,a,b,c) (p)->lpVtbl->GetPixelShaderConstantI(p,a,b,c) +#define IDirect3DDevice9Ex_SetPixelShaderConstantB(p,a,b,c) (p)->lpVtbl->SetPixelShaderConstantB(p,a,b,c) +#define IDirect3DDevice9Ex_GetPixelShaderConstantB(p,a,b,c) (p)->lpVtbl->GetPixelShaderConstantB(p,a,b,c) +#define IDirect3DDevice9Ex_DrawRectPatch(p,a,b,c) (p)->lpVtbl->DrawRectPatch(p,a,b,c) +#define IDirect3DDevice9Ex_DrawTriPatch(p,a,b,c) (p)->lpVtbl->DrawTriPatch(p,a,b,c) +#define IDirect3DDevice9Ex_DeletePatch(p,a) (p)->lpVtbl->DeletePatch(p,a) +#define IDirect3DDevice9Ex_CreateQuery(p,a,b) (p)->lpVtbl->CreateQuery(p,a,b) +#define IDirect3DDevice9Ex_SetConvolutionMonoKernel(p,a,b,c,d) (p)->lpVtbl->SetConvolutionMonoKernel(p,a,b,c,d) +#define IDirect3DDevice9Ex_ComposeRects(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->ComposeRects(p,a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_PresentEx(p,a,b,c,d,e) (p)->lpVtbl->PresentEx(p,a,b,c,d,e) +#define IDirect3DDevice9Ex_GetGPUThreadPriority(p,a) (p)->lpVtbl->GetGPUThreadPriority(p,a) +#define IDirect3DDevice9Ex_SetGPUThreadPriority(p,a) (p)->lpVtbl->SetGPUThreadPriority(p,a) +#define IDirect3DDevice9Ex_WaitForVBlank(p,a) (p)->lpVtbl->WaitForVBlank(p,a) +#define IDirect3DDevice9Ex_CheckResourceResidency(p,a,b) (p)->lpVtbl->CheckResourceResidency(p,a,b) +#define IDirect3DDevice9Ex_SetMaximumFrameLatency(p,a) (p)->lpVtbl->SetMaximumFrameLatency(p,a) +#define IDirect3DDevice9Ex_GetMaximumFrameLatency(p,a) (p)->lpVtbl->GetMaximumFrameLatency(p,a) +#define IDirect3DDevice9Ex_CheckDeviceState(p,a) (p)->lpVtbl->CheckDeviceState(p,a) +#define IDirect3DDevice9Ex_CreateRenderTargetEx(p,a,b,c,d,e,f,g,h,i) (p)->lpVtbl->CreateRenderTargetEx(p,a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx(p,a,b,c,d,e,f,g) (p)->lpVtbl->CreateOffscreenPlainSurfaceEx(p,a,b,c,d,e,f,g) +#define IDirect3DDevice9Ex_CreateDepthStencilSurfaceEx(p,a,b,c,d,e,f,g,h,i) (p)->lpVtbl->CreateDepthStencilSurfaceEx(p,a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9Ex_ResetEx(p,a,b) (p)->lpVtbl->ResetEx(p,a,b) +#define IDirect3DDevice9Ex_GetDisplayModeEx(p,a,b,c) (p)->lpVtbl->GetDisplayModeEx(p,a,b,c) +#else +#define IDirect3DDevice9Ex_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DDevice9Ex_AddRef(p) (p)->AddRef() +#define IDirect3DDevice9Ex_Release(p) (p)->Release() +#define IDirect3DDevice9Ex_TestCooperativeLevel(p) (p)->TestCooperativeLevel() +#define IDirect3DDevice9Ex_GetAvailableTextureMem(p) (p)->GetAvailableTextureMem() +#define IDirect3DDevice9Ex_EvictManagedResources(p) (p)->EvictManagedResources() +#define IDirect3DDevice9Ex_GetDirect3D(p,a) (p)->GetDirect3D(a) +#define IDirect3DDevice9Ex_GetDeviceCaps(p,a) (p)->GetDeviceCaps(a) +#define IDirect3DDevice9Ex_GetDisplayMode(p,a,b) (p)->GetDisplayMode(a,b) +#define IDirect3DDevice9Ex_GetCreationParameters(p,a) (p)->GetCreationParameters(a) +#define IDirect3DDevice9Ex_SetCursorProperties(p,a,b,c) (p)->SetCursorProperties(a,b,c) +#define IDirect3DDevice9Ex_SetCursorPosition(p,a,b,c) (p)->SetCursorPosition(a,b,c) +#define IDirect3DDevice9Ex_ShowCursor(p,a) (p)->ShowCursor(a) +#define IDirect3DDevice9Ex_CreateAdditionalSwapChain(p,a,b) (p)->CreateAdditionalSwapChain(a,b) +#define IDirect3DDevice9Ex_GetSwapChain(p,a,b) (p)->GetSwapChain(a,b) +#define IDirect3DDevice9Ex_GetNumberOfSwapChains(p) (p)->GetNumberOfSwapChains() +#define IDirect3DDevice9Ex_Reset(p,a) (p)->Reset(a) +#define IDirect3DDevice9Ex_Present(p,a,b,c,d) (p)->Present(a,b,c,d) +#define IDirect3DDevice9Ex_GetBackBuffer(p,a,b,c,d) (p)->GetBackBuffer(a,b,c,d) +#define IDirect3DDevice9Ex_GetRasterStatus(p,a,b) (p)->GetRasterStatus(a,b) +#define IDirect3DDevice9Ex_SetDialogBoxMode(p,a) (p)->SetDialogBoxMode(a) +#define IDirect3DDevice9Ex_SetGammaRamp(p,a,b,c) (p)->SetGammaRamp(a,b,c) +#define IDirect3DDevice9Ex_GetGammaRamp(p,a,b) (p)->GetGammaRamp(a,b) +#define IDirect3DDevice9Ex_CreateTexture(p,a,b,c,d,e,f,g,h) (p)->CreateTexture(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_CreateVolumeTexture(p,a,b,c,d,e,f,g,h,i) (p)->CreateVolumeTexture(a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9Ex_CreateCubeTexture(p,a,b,c,d,e,f,g) (p)->CreateCubeTexture(a,b,c,d,e,f,g) +#define IDirect3DDevice9Ex_CreateVertexBuffer(p,a,b,c,d,e,f) (p)->CreateVertexBuffer(a,b,c,d,e,f) +#define IDirect3DDevice9Ex_CreateIndexBuffer(p,a,b,c,d,e,f) (p)->CreateIndexBuffer(a,b,c,d,e,f) +#define IDirect3DDevice9Ex_CreateRenderTarget(p,a,b,c,d,e,f,g,h) (p)->CreateRenderTarget(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_CreateDepthStencilSurface(p,a,b,c,d,e,f,g,h) (p)->CreateDepthStencilSurface(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_UpdateSurface(p,a,b,c,d) (p)->UpdateSurface(a,b,c,d) +#define IDirect3DDevice9Ex_UpdateTexture(p,a,b) (p)->UpdateTexture(a,b) +#define IDirect3DDevice9Ex_GetRenderTargetData(p,a,b) (p)->GetRenderTargetData(a,b) +#define IDirect3DDevice9Ex_GetFrontBufferData(p,a,b) (p)->GetFrontBufferData(a,b) +#define IDirect3DDevice9Ex_StretchRect(p,a,b,c,d,e) (p)->StretchRect(a,b,c,d,e) +#define IDirect3DDevice9Ex_ColorFill(p,a,b,c) (p)->ColorFill(a,b,c) +#define IDirect3DDevice9Ex_CreateOffscreenPlainSurface(p,a,b,c,d,e,f) (p)->CreateOffscreenPlainSurface(a,b,c,d,e,f) +#define IDirect3DDevice9Ex_SetRenderTarget(p,a,b) (p)->SetRenderTarget(a,b) +#define IDirect3DDevice9Ex_GetRenderTarget(p,a,b) (p)->GetRenderTarget(a,b) +#define IDirect3DDevice9Ex_SetDepthStencilSurface(p,a) (p)->SetDepthStencilSurface(a) +#define IDirect3DDevice9Ex_GetDepthStencilSurface(p,a) (p)->GetDepthStencilSurface(a) +#define IDirect3DDevice9Ex_BeginScene(p) (p)->BeginScene() +#define IDirect3DDevice9Ex_EndScene(p) (p)->EndScene() +#define IDirect3DDevice9Ex_Clear(p,a,b,c,d,e,f) (p)->Clear(a,b,c,d,e,f) +#define IDirect3DDevice9Ex_SetTransform(p,a,b) (p)->SetTransform(a,b) +#define IDirect3DDevice9Ex_GetTransform(p,a,b) (p)->GetTransform(a,b) +#define IDirect3DDevice9Ex_MultiplyTransform(p,a,b) (p)->MultiplyTransform(a,b) +#define IDirect3DDevice9Ex_SetViewport(p,a) (p)->SetViewport(a) +#define IDirect3DDevice9Ex_GetViewport(p,a) (p)->GetViewport(a) +#define IDirect3DDevice9Ex_SetMaterial(p,a) (p)->SetMaterial(a) +#define IDirect3DDevice9Ex_GetMaterial(p,a) (p)->GetMaterial(a) +#define IDirect3DDevice9Ex_SetLight(p,a,b) (p)->SetLight(a,b) +#define IDirect3DDevice9Ex_GetLight(p,a,b) (p)->GetLight(a,b) +#define IDirect3DDevice9Ex_LightEnable(p,a,b) (p)->LightEnable(a,b) +#define IDirect3DDevice9Ex_GetLightEnable(p,a,b) (p)->GetLightEnable(a,b) +#define IDirect3DDevice9Ex_SetClipPlane(p,a,b) (p)->SetClipPlane(a,b) +#define IDirect3DDevice9Ex_GetClipPlane(p,a,b) (p)->GetClipPlane(a,b) +#define IDirect3DDevice9Ex_SetRenderState(p,a,b) (p)->SetRenderState(a,b) +#define IDirect3DDevice9Ex_GetRenderState(p,a,b) (p)->GetRenderState(a,b) +#define IDirect3DDevice9Ex_CreateStateBlock(p,a,b) (p)->CreateStateBlock(a,b) +#define IDirect3DDevice9Ex_BeginStateBlock(p) (p)->BeginStateBlock() +#define IDirect3DDevice9Ex_EndStateBlock(p,a) (p)->EndStateBlock(a) +#define IDirect3DDevice9Ex_SetClipStatus(p,a) (p)->SetClipStatus(a) +#define IDirect3DDevice9Ex_GetClipStatus(p,a) (p)->GetClipStatus(a) +#define IDirect3DDevice9Ex_GetTexture(p,a,b) (p)->GetTexture(a,b) +#define IDirect3DDevice9Ex_SetTexture(p,a,b) (p)->SetTexture(a,b) +#define IDirect3DDevice9Ex_GetTextureStageState(p,a,b,c) (p)->GetTextureStageState(a,b,c) +#define IDirect3DDevice9Ex_SetTextureStageState(p,a,b,c) (p)->SetTextureStageState(a,b,c) +#define IDirect3DDevice9Ex_GetSamplerState(p,a,b,c) (p)->GetSamplerState(a,b,c) +#define IDirect3DDevice9Ex_SetSamplerState(p,a,b,c) (p)->SetSamplerState(a,b,c) +#define IDirect3DDevice9Ex_ValidateDevice(p,a) (p)->ValidateDevice(a) +#define IDirect3DDevice9Ex_SetPaletteEntries(p,a,b) (p)->SetPaletteEntries(a,b) +#define IDirect3DDevice9Ex_GetPaletteEntries(p,a,b) (p)->GetPaletteEntries(a,b) +#define IDirect3DDevice9Ex_SetCurrentTexturePalette(p,a) (p)->SetCurrentTexturePalette(a) +#define IDirect3DDevice9Ex_GetCurrentTexturePalette(p,a) (p)->GetCurrentTexturePalette(a) +#define IDirect3DDevice9Ex_SetScissorRect(p,a) (p)->SetScissorRect(a) +#define IDirect3DDevice9Ex_GetScissorRect(p,a) (p)->GetScissorRect(a) +#define IDirect3DDevice9Ex_SetSoftwareVertexProcessing(p,a) (p)->SetSoftwareVertexProcessing(a) +#define IDirect3DDevice9Ex_GetSoftwareVertexProcessing(p) (p)->GetSoftwareVertexProcessing() +#define IDirect3DDevice9Ex_SetNPatchMode(p,a) (p)->SetNPatchMode(a) +#define IDirect3DDevice9Ex_GetNPatchMode(p) (p)->GetNPatchMode() +#define IDirect3DDevice9Ex_DrawPrimitive(p,a,b,c) (p)->DrawPrimitive(a,b,c) +#define IDirect3DDevice9Ex_DrawIndexedPrimitive(p,a,b,c,d,e,f) (p)->DrawIndexedPrimitive(a,b,c,d,e,f) +#define IDirect3DDevice9Ex_DrawPrimitiveUP(p,a,b,c,d) (p)->DrawPrimitiveUP(a,b,c,d) +#define IDirect3DDevice9Ex_DrawIndexedPrimitiveUP(p,a,b,c,d,e,f,g,h) (p)->DrawIndexedPrimitiveUP(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_ProcessVertices(p,a,b,c,d,e,f) (p)->ProcessVertices(a,b,c,d,e,f) +#define IDirect3DDevice9Ex_CreateVertexDeclaration(p,a,b) (p)->CreateVertexDeclaration(a,b) +#define IDirect3DDevice9Ex_SetVertexDeclaration(p,a) (p)->SetVertexDeclaration(a) +#define IDirect3DDevice9Ex_GetVertexDeclaration(p,a) (p)->GetVertexDeclaration(a) +#define IDirect3DDevice9Ex_SetFVF(p,a) (p)->SetFVF(a) +#define IDirect3DDevice9Ex_GetFVF(p,a) (p)->GetFVF(a) +#define IDirect3DDevice9Ex_CreateVertexShader(p,a,b) (p)->CreateVertexShader(a,b) +#define IDirect3DDevice9Ex_SetVertexShader(p,a) (p)->SetVertexShader(a) +#define IDirect3DDevice9Ex_GetVertexShader(p,a) (p)->GetVertexShader(a) +#define IDirect3DDevice9Ex_SetVertexShaderConstantF(p,a,b,c) (p)->SetVertexShaderConstantF(a,b,c) +#define IDirect3DDevice9Ex_GetVertexShaderConstantF(p,a,b,c) (p)->GetVertexShaderConstantF(a,b,c) +#define IDirect3DDevice9Ex_SetVertexShaderConstantI(p,a,b,c) (p)->SetVertexShaderConstantI(a,b,c) +#define IDirect3DDevice9Ex_GetVertexShaderConstantI(p,a,b,c) (p)->GetVertexShaderConstantI(a,b,c) +#define IDirect3DDevice9Ex_SetVertexShaderConstantB(p,a,b,c) (p)->SetVertexShaderConstantB(a,b,c) +#define IDirect3DDevice9Ex_GetVertexShaderConstantB(p,a,b,c) (p)->GetVertexShaderConstantB(a,b,c) +#define IDirect3DDevice9Ex_SetStreamSource(p,a,b,c,d) (p)->SetStreamSource(a,b,c,d) +#define IDirect3DDevice9Ex_GetStreamSource(p,a,b,c,d) (p)->GetStreamSource(a,b,c,d) +#define IDirect3DDevice9Ex_SetStreamSourceFreq(p,a,b) (p)->SetStreamSourceFreq(a,b) +#define IDirect3DDevice9Ex_GetStreamSourceFreq(p,a,b) (p)->GetStreamSourceFreq(a,b) +#define IDirect3DDevice9Ex_SetIndices(p,a) (p)->SetIndices(a) +#define IDirect3DDevice9Ex_GetIndices(p,a) (p)->GetIndices(a) +#define IDirect3DDevice9Ex_CreatePixelShader(p,a,b) (p)->CreatePixelShader(a,b) +#define IDirect3DDevice9Ex_SetPixelShader(p,a) (p)->SetPixelShader(a) +#define IDirect3DDevice9Ex_GetPixelShader(p,a) (p)->GetPixelShader(a) +#define IDirect3DDevice9Ex_SetPixelShaderConstantF(p,a,b,c) (p)->SetPixelShaderConstantF(a,b,c) +#define IDirect3DDevice9Ex_GetPixelShaderConstantF(p,a,b,c) (p)->GetPixelShaderConstantF(a,b,c) +#define IDirect3DDevice9Ex_SetPixelShaderConstantI(p,a,b,c) (p)->SetPixelShaderConstantI(a,b,c) +#define IDirect3DDevice9Ex_GetPixelShaderConstantI(p,a,b,c) (p)->GetPixelShaderConstantI(a,b,c) +#define IDirect3DDevice9Ex_SetPixelShaderConstantB(p,a,b,c) (p)->SetPixelShaderConstantB(a,b,c) +#define IDirect3DDevice9Ex_GetPixelShaderConstantB(p,a,b,c) (p)->GetPixelShaderConstantB(a,b,c) +#define IDirect3DDevice9Ex_DrawRectPatch(p,a,b,c) (p)->DrawRectPatch(a,b,c) +#define IDirect3DDevice9Ex_DrawTriPatch(p,a,b,c) (p)->DrawTriPatch(a,b,c) +#define IDirect3DDevice9Ex_DeletePatch(p,a) (p)->DeletePatch(a) +#define IDirect3DDevice9Ex_CreateQuery(p,a,b) (p)->CreateQuery(a,b) +#define IDirect3DDevice9Ex_SetConvolutionMonoKernel(p,a,b,c,d) (p)->SetConvolutionMonoKernel(a,b,c,d) +#define IDirect3DDevice9Ex_ComposeRects(p,a,b,c,d,e,f,g,h) (p)->ComposeRects(a,b,c,d,e,f,g,h) +#define IDirect3DDevice9Ex_PresentEx(p,a,b,c,d,e) (p)->PresentEx(a,b,c,d,e) +#define IDirect3DDevice9Ex_GetGPUThreadPriority(p,a) (p)->GetGPUThreadPriority(a) +#define IDirect3DDevice9Ex_SetGPUThreadPriority(p,a) (p)->SetGPUThreadPriority(a) +#define IDirect3DDevice9Ex_WaitForVBlank(p,a) (p)->WaitForVBlank(a) +#define IDirect3DDevice9Ex_CheckResourceResidency(p,a,b) (p)->CheckResourceResidency(a,b) +#define IDirect3DDevice9Ex_SetMaximumFrameLatency(p,a) (p)->SetMaximumFrameLatency(a) +#define IDirect3DDevice9Ex_GetMaximumFrameLatency(p,a) (p)->GetMaximumFrameLatency(a) +#define IDirect3DDevice9Ex_CheckDeviceState(p,a) (p)->CheckDeviceState(a) +#define IDirect3DDevice9Ex_CreateRenderTargetEx(p,a,b,c,d,e,f,g,h,i) (p)->CreateRenderTargetEx(a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx(p,a,b,c,d,e,f,g) (p)->CreateOffscreenPlainSurfaceEx(a,b,c,d,e,f,g) +#define IDirect3DDevice9Ex_CreateDepthStencilSurfaceEx(p,a,b,c,d,e,f,g,h,i) (p)->CreateDepthStencilSurfaceEx(a,b,c,d,e,f,g,h,i) +#define IDirect3DDevice9Ex_ResetEx(p,a,b) (p)->ResetEx(a,b) +#define IDirect3DDevice9Ex_GetDisplayModeEx(p,a,b,c) (p)->GetDisplayModeEx(a,b,c) +#endif + + + +#undef INTERFACE +#define INTERFACE IDirect3DSwapChain9Ex + +DECLARE_INTERFACE_(IDirect3DSwapChain9Ex, IDirect3DSwapChain9) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirect3DSwapChain9 methods ***/ + STDMETHOD(Present)(THIS_ CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion,DWORD dwFlags) PURE; + STDMETHOD(GetFrontBufferData)(THIS_ IDirect3DSurface9* pDestSurface) PURE; + STDMETHOD(GetBackBuffer)(THIS_ UINT iBackBuffer,D3DBACKBUFFER_TYPE Type,IDirect3DSurface9** ppBackBuffer) PURE; + STDMETHOD(GetRasterStatus)(THIS_ D3DRASTER_STATUS* pRasterStatus) PURE; + STDMETHOD(GetDisplayMode)(THIS_ D3DDISPLAYMODE* pMode) PURE; + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice) PURE; + STDMETHOD(GetPresentParameters)(THIS_ D3DPRESENT_PARAMETERS* pPresentationParameters) PURE; + STDMETHOD(GetLastPresentCount)(THIS_ UINT* pLastPresentCount) PURE; + STDMETHOD(GetPresentStats)(THIS_ D3DPRESENTSTATS* pPresentationStatistics) PURE; + STDMETHOD(GetDisplayModeEx)(THIS_ D3DDISPLAYMODEEX* pMode,D3DDISPLAYROTATION* pRotation) PURE; +}; + +typedef struct IDirect3DSwapChain9Ex *LPDIRECT3DSWAPCHAIN9EX, *PDIRECT3DSWAPCHAIN9EX; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirect3DSwapChain9Ex_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DSwapChain9Ex_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DSwapChain9Ex_Release(p) (p)->lpVtbl->Release(p) +#define IDirect3DSwapChain9Ex_Present(p,a,b,c,d,e) (p)->lpVtbl->Present(p,a,b,c,d,e) +#define IDirect3DSwapChain9Ex_GetFrontBufferData(p,a) (p)->lpVtbl->GetFrontBufferData(p,a) +#define IDirect3DSwapChain9Ex_GetBackBuffer(p,a,b,c) (p)->lpVtbl->GetBackBuffer(p,a,b,c) +#define IDirect3DSwapChain9Ex_GetRasterStatus(p,a) (p)->lpVtbl->GetRasterStatus(p,a) +#define IDirect3DSwapChain9Ex_GetDisplayMode(p,a) (p)->lpVtbl->GetDisplayMode(p,a) +#define IDirect3DSwapChain9Ex_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) +#define IDirect3DSwapChain9Ex_GetPresentParameters(p,a) (p)->lpVtbl->GetPresentParameters(p,a) +#define IDirect3DSwapChain9Ex_GetLastPresentCount(p,a) (p)->lpVtbl->GetLastPresentCount(p,a) +#define IDirect3DSwapChain9Ex_GetPresentStats(p,a) (p)->lpVtbl->GetPresentStats(p,a) +#define IDirect3DSwapChain9Ex_GetDisplayModeEx(p,a,b) (p)->lpVtbl->GetDisplayModeEx(p,a,b) +#else +#define IDirect3DSwapChain9Ex_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DSwapChain9Ex_AddRef(p) (p)->AddRef() +#define IDirect3DSwapChain9Ex_Release(p) (p)->Release() +#define IDirect3DSwapChain9Ex_Present(p,a,b,c,d,e) (p)->Present(a,b,c,d,e) +#define IDirect3DSwapChain9Ex_GetFrontBufferData(p,a) (p)->GetFrontBufferData(a) +#define IDirect3DSwapChain9Ex_GetBackBuffer(p,a,b,c) (p)->GetBackBuffer(a,b,c) +#define IDirect3DSwapChain9Ex_GetRasterStatus(p,a) (p)->GetRasterStatus(a) +#define IDirect3DSwapChain9Ex_GetDisplayMode(p,a) (p)->GetDisplayMode(a) +#define IDirect3DSwapChain9Ex_GetDevice(p,a) (p)->GetDevice(a) +#define IDirect3DSwapChain9Ex_GetPresentParameters(p,a) (p)->GetPresentParameters(a) +#define IDirect3DSwapChain9Ex_GetLastPresentCount(p,a) (p)->GetLastPresentCount(a) +#define IDirect3DSwapChain9Ex_GetPresentStats(p,a) (p)->GetPresentStats(a) +#define IDirect3DSwapChain9Ex_GetDisplayModeEx(p,a,b) (p)->GetDisplayModeEx(a,b) +#endif + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + + + +#ifdef __cplusplus +}; +#endif + +#endif /* (DIRECT3D_VERSION >= 0x0900) */ +#endif /* _D3D_H_ */ + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3d9caps.h b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3d9caps.h new file mode 100644 index 0000000000..a7df08aa13 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3d9caps.h @@ -0,0 +1,512 @@ +/*==========================================================================; + * + * Copyright (C) Microsoft Corporation. All Rights Reserved. + * + * File: d3d9caps.h + * Content: Direct3D capabilities include file + * + ***************************************************************************/ + +#ifndef _d3d9CAPS_H +#define _d3d9CAPS_H + +#ifndef DIRECT3D_VERSION +#define DIRECT3D_VERSION 0x0900 +#endif //DIRECT3D_VERSION + +// include this file content only if compiling for DX9 interfaces +#if(DIRECT3D_VERSION >= 0x0900) + +#if defined(_X86_) || defined(_IA64_) +#pragma pack(4) +#endif + +typedef struct _D3DVSHADERCAPS2_0 +{ + DWORD Caps; + INT DynamicFlowControlDepth; + INT NumTemps; + INT StaticFlowControlDepth; +} D3DVSHADERCAPS2_0; + +#define D3DVS20CAPS_PREDICATION (1<<0) + +#define D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH 24 +#define D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH 0 +#define D3DVS20_MAX_NUMTEMPS 32 +#define D3DVS20_MIN_NUMTEMPS 12 +#define D3DVS20_MAX_STATICFLOWCONTROLDEPTH 4 +#define D3DVS20_MIN_STATICFLOWCONTROLDEPTH 1 + +typedef struct _D3DPSHADERCAPS2_0 +{ + DWORD Caps; + INT DynamicFlowControlDepth; + INT NumTemps; + INT StaticFlowControlDepth; + INT NumInstructionSlots; +} D3DPSHADERCAPS2_0; + +#define D3DPS20CAPS_ARBITRARYSWIZZLE (1<<0) +#define D3DPS20CAPS_GRADIENTINSTRUCTIONS (1<<1) +#define D3DPS20CAPS_PREDICATION (1<<2) +#define D3DPS20CAPS_NODEPENDENTREADLIMIT (1<<3) +#define D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT (1<<4) + +#define D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH 24 +#define D3DPS20_MIN_DYNAMICFLOWCONTROLDEPTH 0 +#define D3DPS20_MAX_NUMTEMPS 32 +#define D3DPS20_MIN_NUMTEMPS 12 +#define D3DPS20_MAX_STATICFLOWCONTROLDEPTH 4 +#define D3DPS20_MIN_STATICFLOWCONTROLDEPTH 0 +#define D3DPS20_MAX_NUMINSTRUCTIONSLOTS 512 +#define D3DPS20_MIN_NUMINSTRUCTIONSLOTS 96 + +#define D3DMIN30SHADERINSTRUCTIONS 512 +#define D3DMAX30SHADERINSTRUCTIONS 32768 + +typedef struct _D3DCAPS9 +{ + /* Device Info */ + D3DDEVTYPE DeviceType; + UINT AdapterOrdinal; + + /* Caps from DX7 Draw */ + DWORD Caps; + DWORD Caps2; + DWORD Caps3; + DWORD PresentationIntervals; + + /* Cursor Caps */ + DWORD CursorCaps; + + /* 3D Device Caps */ + DWORD DevCaps; + + DWORD PrimitiveMiscCaps; + DWORD RasterCaps; + DWORD ZCmpCaps; + DWORD SrcBlendCaps; + DWORD DestBlendCaps; + DWORD AlphaCmpCaps; + DWORD ShadeCaps; + DWORD TextureCaps; + DWORD TextureFilterCaps; // D3DPTFILTERCAPS for IDirect3DTexture9's + DWORD CubeTextureFilterCaps; // D3DPTFILTERCAPS for IDirect3DCubeTexture9's + DWORD VolumeTextureFilterCaps; // D3DPTFILTERCAPS for IDirect3DVolumeTexture9's + DWORD TextureAddressCaps; // D3DPTADDRESSCAPS for IDirect3DTexture9's + DWORD VolumeTextureAddressCaps; // D3DPTADDRESSCAPS for IDirect3DVolumeTexture9's + + DWORD LineCaps; // D3DLINECAPS + + DWORD MaxTextureWidth, MaxTextureHeight; + DWORD MaxVolumeExtent; + + DWORD MaxTextureRepeat; + DWORD MaxTextureAspectRatio; + DWORD MaxAnisotropy; + float MaxVertexW; + + float GuardBandLeft; + float GuardBandTop; + float GuardBandRight; + float GuardBandBottom; + + float ExtentsAdjust; + DWORD StencilCaps; + + DWORD FVFCaps; + DWORD TextureOpCaps; + DWORD MaxTextureBlendStages; + DWORD MaxSimultaneousTextures; + + DWORD VertexProcessingCaps; + DWORD MaxActiveLights; + DWORD MaxUserClipPlanes; + DWORD MaxVertexBlendMatrices; + DWORD MaxVertexBlendMatrixIndex; + + float MaxPointSize; + + DWORD MaxPrimitiveCount; // max number of primitives per DrawPrimitive call + DWORD MaxVertexIndex; + DWORD MaxStreams; + DWORD MaxStreamStride; // max stride for SetStreamSource + + DWORD VertexShaderVersion; + DWORD MaxVertexShaderConst; // number of vertex shader constant registers + + DWORD PixelShaderVersion; + float PixelShader1xMaxValue; // max value storable in registers of ps.1.x shaders + + // Here are the DX9 specific ones + DWORD DevCaps2; + + float MaxNpatchTessellationLevel; + DWORD Reserved5; + + UINT MasterAdapterOrdinal; // ordinal of master adaptor for adapter group + UINT AdapterOrdinalInGroup; // ordinal inside the adapter group + UINT NumberOfAdaptersInGroup; // number of adapters in this adapter group (only if master) + DWORD DeclTypes; // Data types, supported in vertex declarations + DWORD NumSimultaneousRTs; // Will be at least 1 + DWORD StretchRectFilterCaps; // Filter caps supported by StretchRect + D3DVSHADERCAPS2_0 VS20Caps; + D3DPSHADERCAPS2_0 PS20Caps; + DWORD VertexTextureFilterCaps; // D3DPTFILTERCAPS for IDirect3DTexture9's for texture, used in vertex shaders + DWORD MaxVShaderInstructionsExecuted; // maximum number of vertex shader instructions that can be executed + DWORD MaxPShaderInstructionsExecuted; // maximum number of pixel shader instructions that can be executed + DWORD MaxVertexShader30InstructionSlots; + DWORD MaxPixelShader30InstructionSlots; +} D3DCAPS9; + +// +// BIT DEFINES FOR D3DCAPS9 DWORD MEMBERS +// + +// +// Caps +// +#define D3DCAPS_READ_SCANLINE 0x00020000L + +// +// Caps2 +// +#define D3DCAPS2_FULLSCREENGAMMA 0x00020000L +#define D3DCAPS2_CANCALIBRATEGAMMA 0x00100000L +#define D3DCAPS2_RESERVED 0x02000000L +#define D3DCAPS2_CANMANAGERESOURCE 0x10000000L +#define D3DCAPS2_DYNAMICTEXTURES 0x20000000L +#define D3DCAPS2_CANAUTOGENMIPMAP 0x40000000L + +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + +#define D3DCAPS2_CANSHARERESOURCE 0x80000000L + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + +// +// Caps3 +// +#define D3DCAPS3_RESERVED 0x8000001fL + +// Indicates that the device can respect the ALPHABLENDENABLE render state +// when fullscreen while using the FLIP or DISCARD swap effect. +// COPY and COPYVSYNC swap effects work whether or not this flag is set. +#define D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD 0x00000020L + +// Indicates that the device can perform a gamma correction from +// a windowed back buffer containing linear content to the sRGB desktop. +#define D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION 0x00000080L + +#define D3DCAPS3_COPY_TO_VIDMEM 0x00000100L /* Device can acclerate copies from sysmem to local vidmem */ +#define D3DCAPS3_COPY_TO_SYSTEMMEM 0x00000200L /* Device can acclerate copies from local vidmem to sysmem */ + + +// +// PresentationIntervals +// +#define D3DPRESENT_INTERVAL_DEFAULT 0x00000000L +#define D3DPRESENT_INTERVAL_ONE 0x00000001L +#define D3DPRESENT_INTERVAL_TWO 0x00000002L +#define D3DPRESENT_INTERVAL_THREE 0x00000004L +#define D3DPRESENT_INTERVAL_FOUR 0x00000008L +#define D3DPRESENT_INTERVAL_IMMEDIATE 0x80000000L + +// +// CursorCaps +// +// Driver supports HW color cursor in at least hi-res modes(height >=400) +#define D3DCURSORCAPS_COLOR 0x00000001L +// Driver supports HW cursor also in low-res modes(height < 400) +#define D3DCURSORCAPS_LOWRES 0x00000002L + +// +// DevCaps +// +#define D3DDEVCAPS_EXECUTESYSTEMMEMORY 0x00000010L /* Device can use execute buffers from system memory */ +#define D3DDEVCAPS_EXECUTEVIDEOMEMORY 0x00000020L /* Device can use execute buffers from video memory */ +#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */ +#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY 0x00000080L /* Device can use TL buffers from video memory */ +#define D3DDEVCAPS_TEXTURESYSTEMMEMORY 0x00000100L /* Device can texture from system memory */ +#define D3DDEVCAPS_TEXTUREVIDEOMEMORY 0x00000200L /* Device can texture from device memory */ +#define D3DDEVCAPS_DRAWPRIMTLVERTEX 0x00000400L /* Device can draw TLVERTEX primitives */ +#define D3DDEVCAPS_CANRENDERAFTERFLIP 0x00000800L /* Device can render without waiting for flip to complete */ +#define D3DDEVCAPS_TEXTURENONLOCALVIDMEM 0x00001000L /* Device can texture from nonlocal video memory */ +#define D3DDEVCAPS_DRAWPRIMITIVES2 0x00002000L /* Device can support DrawPrimitives2 */ +#define D3DDEVCAPS_SEPARATETEXTUREMEMORIES 0x00004000L /* Device is texturing from separate memory pools */ +#define D3DDEVCAPS_DRAWPRIMITIVES2EX 0x00008000L /* Device can support Extended DrawPrimitives2 i.e. DX7 compliant driver*/ +#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */ +#define D3DDEVCAPS_CANBLTSYSTONONLOCAL 0x00020000L /* Device supports a Tex Blt from system memory to non-local vidmem */ +#define D3DDEVCAPS_HWRASTERIZATION 0x00080000L /* Device has HW acceleration for rasterization */ +#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */ +#define D3DDEVCAPS_QUINTICRTPATCHES 0x00200000L /* Device supports quintic Beziers and BSplines */ +#define D3DDEVCAPS_RTPATCHES 0x00400000L /* Device supports Rect and Tri patches */ +#define D3DDEVCAPS_RTPATCHHANDLEZERO 0x00800000L /* Indicates that RT Patches may be drawn efficiently using handle 0 */ +#define D3DDEVCAPS_NPATCHES 0x01000000L /* Device supports N-Patches */ + +// +// PrimitiveMiscCaps +// +#define D3DPMISCCAPS_MASKZ 0x00000002L +#define D3DPMISCCAPS_CULLNONE 0x00000010L +#define D3DPMISCCAPS_CULLCW 0x00000020L +#define D3DPMISCCAPS_CULLCCW 0x00000040L +#define D3DPMISCCAPS_COLORWRITEENABLE 0x00000080L +#define D3DPMISCCAPS_CLIPPLANESCALEDPOINTS 0x00000100L /* Device correctly clips scaled points to clip planes */ +#define D3DPMISCCAPS_CLIPTLVERTS 0x00000200L /* device will clip post-transformed vertex primitives */ +#define D3DPMISCCAPS_TSSARGTEMP 0x00000400L /* device supports D3DTA_TEMP for temporary register */ +#define D3DPMISCCAPS_BLENDOP 0x00000800L /* device supports D3DRS_BLENDOP */ +#define D3DPMISCCAPS_NULLREFERENCE 0x00001000L /* Reference Device that doesnt render */ +#define D3DPMISCCAPS_INDEPENDENTWRITEMASKS 0x00004000L /* Device supports independent write masks for MET or MRT */ +#define D3DPMISCCAPS_PERSTAGECONSTANT 0x00008000L /* Device supports per-stage constants */ +#define D3DPMISCCAPS_FOGANDSPECULARALPHA 0x00010000L /* Device supports separate fog and specular alpha (many devices + use the specular alpha channel to store fog factor) */ +#define D3DPMISCCAPS_SEPARATEALPHABLEND 0x00020000L /* Device supports separate blend settings for the alpha channel */ +#define D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS 0x00040000L /* Device supports different bit depths for MRT */ +#define D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING 0x00080000L /* Device supports post-pixel shader operations for MRT */ +#define D3DPMISCCAPS_FOGVERTEXCLAMPED 0x00100000L /* Device clamps fog blend factor per vertex */ + +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + +#define D3DPMISCCAPS_POSTBLENDSRGBCONVERT 0x00200000L /* Indicates device can perform conversion to sRGB after blending. */ + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + + +// +// LineCaps +// +#define D3DLINECAPS_TEXTURE 0x00000001L +#define D3DLINECAPS_ZTEST 0x00000002L +#define D3DLINECAPS_BLEND 0x00000004L +#define D3DLINECAPS_ALPHACMP 0x00000008L +#define D3DLINECAPS_FOG 0x00000010L +#define D3DLINECAPS_ANTIALIAS 0x00000020L + +// +// RasterCaps +// +#define D3DPRASTERCAPS_DITHER 0x00000001L +#define D3DPRASTERCAPS_ZTEST 0x00000010L +#define D3DPRASTERCAPS_FOGVERTEX 0x00000080L +#define D3DPRASTERCAPS_FOGTABLE 0x00000100L +#define D3DPRASTERCAPS_MIPMAPLODBIAS 0x00002000L +#define D3DPRASTERCAPS_ZBUFFERLESSHSR 0x00008000L +#define D3DPRASTERCAPS_FOGRANGE 0x00010000L +#define D3DPRASTERCAPS_ANISOTROPY 0x00020000L +#define D3DPRASTERCAPS_WBUFFER 0x00040000L +#define D3DPRASTERCAPS_WFOG 0x00100000L +#define D3DPRASTERCAPS_ZFOG 0x00200000L +#define D3DPRASTERCAPS_COLORPERSPECTIVE 0x00400000L /* Device iterates colors perspective correct */ +#define D3DPRASTERCAPS_SCISSORTEST 0x01000000L +#define D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS 0x02000000L +#define D3DPRASTERCAPS_DEPTHBIAS 0x04000000L +#define D3DPRASTERCAPS_MULTISAMPLE_TOGGLE 0x08000000L + +// +// ZCmpCaps, AlphaCmpCaps +// +#define D3DPCMPCAPS_NEVER 0x00000001L +#define D3DPCMPCAPS_LESS 0x00000002L +#define D3DPCMPCAPS_EQUAL 0x00000004L +#define D3DPCMPCAPS_LESSEQUAL 0x00000008L +#define D3DPCMPCAPS_GREATER 0x00000010L +#define D3DPCMPCAPS_NOTEQUAL 0x00000020L +#define D3DPCMPCAPS_GREATEREQUAL 0x00000040L +#define D3DPCMPCAPS_ALWAYS 0x00000080L + +// +// SourceBlendCaps, DestBlendCaps +// +#define D3DPBLENDCAPS_ZERO 0x00000001L +#define D3DPBLENDCAPS_ONE 0x00000002L +#define D3DPBLENDCAPS_SRCCOLOR 0x00000004L +#define D3DPBLENDCAPS_INVSRCCOLOR 0x00000008L +#define D3DPBLENDCAPS_SRCALPHA 0x00000010L +#define D3DPBLENDCAPS_INVSRCALPHA 0x00000020L +#define D3DPBLENDCAPS_DESTALPHA 0x00000040L +#define D3DPBLENDCAPS_INVDESTALPHA 0x00000080L +#define D3DPBLENDCAPS_DESTCOLOR 0x00000100L +#define D3DPBLENDCAPS_INVDESTCOLOR 0x00000200L +#define D3DPBLENDCAPS_SRCALPHASAT 0x00000400L +#define D3DPBLENDCAPS_BOTHSRCALPHA 0x00000800L +#define D3DPBLENDCAPS_BOTHINVSRCALPHA 0x00001000L +#define D3DPBLENDCAPS_BLENDFACTOR 0x00002000L /* Supports both D3DBLEND_BLENDFACTOR and D3DBLEND_INVBLENDFACTOR */ + +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + +#define D3DPBLENDCAPS_SRCCOLOR2 0x00004000L +#define D3DPBLENDCAPS_INVSRCCOLOR2 0x00008000L + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + + +// +// ShadeCaps +// +#define D3DPSHADECAPS_COLORGOURAUDRGB 0x00000008L +#define D3DPSHADECAPS_SPECULARGOURAUDRGB 0x00000200L +#define D3DPSHADECAPS_ALPHAGOURAUDBLEND 0x00004000L +#define D3DPSHADECAPS_FOGGOURAUD 0x00080000L + +// +// TextureCaps +// +#define D3DPTEXTURECAPS_PERSPECTIVE 0x00000001L /* Perspective-correct texturing is supported */ +#define D3DPTEXTURECAPS_POW2 0x00000002L /* Power-of-2 texture dimensions are required - applies to non-Cube/Volume textures only. */ +#define D3DPTEXTURECAPS_ALPHA 0x00000004L /* Alpha in texture pixels is supported */ +#define D3DPTEXTURECAPS_SQUAREONLY 0x00000020L /* Only square textures are supported */ +#define D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE 0x00000040L /* Texture indices are not scaled by the texture size prior to interpolation */ +#define D3DPTEXTURECAPS_ALPHAPALETTE 0x00000080L /* Device can draw alpha from texture palettes */ +// Device can use non-POW2 textures if: +// 1) D3DTEXTURE_ADDRESS is set to CLAMP for this texture's stage +// 2) D3DRS_WRAP(N) is zero for this texture's coordinates +// 3) mip mapping is not enabled (use magnification filter only) +#define D3DPTEXTURECAPS_NONPOW2CONDITIONAL 0x00000100L +#define D3DPTEXTURECAPS_PROJECTED 0x00000400L /* Device can do D3DTTFF_PROJECTED */ +#define D3DPTEXTURECAPS_CUBEMAP 0x00000800L /* Device can do cubemap textures */ +#define D3DPTEXTURECAPS_VOLUMEMAP 0x00002000L /* Device can do volume textures */ +#define D3DPTEXTURECAPS_MIPMAP 0x00004000L /* Device can do mipmapped textures */ +#define D3DPTEXTURECAPS_MIPVOLUMEMAP 0x00008000L /* Device can do mipmapped volume textures */ +#define D3DPTEXTURECAPS_MIPCUBEMAP 0x00010000L /* Device can do mipmapped cube maps */ +#define D3DPTEXTURECAPS_CUBEMAP_POW2 0x00020000L /* Device requires that cubemaps be power-of-2 dimension */ +#define D3DPTEXTURECAPS_VOLUMEMAP_POW2 0x00040000L /* Device requires that volume maps be power-of-2 dimension */ +#define D3DPTEXTURECAPS_NOPROJECTEDBUMPENV 0x00200000L /* Device does not support projected bump env lookup operation + in programmable and fixed function pixel shaders */ + +// +// TextureFilterCaps, StretchRectFilterCaps +// +#define D3DPTFILTERCAPS_MINFPOINT 0x00000100L /* Min Filter */ +#define D3DPTFILTERCAPS_MINFLINEAR 0x00000200L +#define D3DPTFILTERCAPS_MINFANISOTROPIC 0x00000400L +#define D3DPTFILTERCAPS_MINFPYRAMIDALQUAD 0x00000800L +#define D3DPTFILTERCAPS_MINFGAUSSIANQUAD 0x00001000L +#define D3DPTFILTERCAPS_MIPFPOINT 0x00010000L /* Mip Filter */ +#define D3DPTFILTERCAPS_MIPFLINEAR 0x00020000L + +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + +#define D3DPTFILTERCAPS_CONVOLUTIONMONO 0x00040000L /* Min and Mag for the convolution mono filter */ + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + +#define D3DPTFILTERCAPS_MAGFPOINT 0x01000000L /* Mag Filter */ +#define D3DPTFILTERCAPS_MAGFLINEAR 0x02000000L +#define D3DPTFILTERCAPS_MAGFANISOTROPIC 0x04000000L +#define D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD 0x08000000L +#define D3DPTFILTERCAPS_MAGFGAUSSIANQUAD 0x10000000L + +// +// TextureAddressCaps +// +#define D3DPTADDRESSCAPS_WRAP 0x00000001L +#define D3DPTADDRESSCAPS_MIRROR 0x00000002L +#define D3DPTADDRESSCAPS_CLAMP 0x00000004L +#define D3DPTADDRESSCAPS_BORDER 0x00000008L +#define D3DPTADDRESSCAPS_INDEPENDENTUV 0x00000010L +#define D3DPTADDRESSCAPS_MIRRORONCE 0x00000020L + +// +// StencilCaps +// +#define D3DSTENCILCAPS_KEEP 0x00000001L +#define D3DSTENCILCAPS_ZERO 0x00000002L +#define D3DSTENCILCAPS_REPLACE 0x00000004L +#define D3DSTENCILCAPS_INCRSAT 0x00000008L +#define D3DSTENCILCAPS_DECRSAT 0x00000010L +#define D3DSTENCILCAPS_INVERT 0x00000020L +#define D3DSTENCILCAPS_INCR 0x00000040L +#define D3DSTENCILCAPS_DECR 0x00000080L +#define D3DSTENCILCAPS_TWOSIDED 0x00000100L + +// +// TextureOpCaps +// +#define D3DTEXOPCAPS_DISABLE 0x00000001L +#define D3DTEXOPCAPS_SELECTARG1 0x00000002L +#define D3DTEXOPCAPS_SELECTARG2 0x00000004L +#define D3DTEXOPCAPS_MODULATE 0x00000008L +#define D3DTEXOPCAPS_MODULATE2X 0x00000010L +#define D3DTEXOPCAPS_MODULATE4X 0x00000020L +#define D3DTEXOPCAPS_ADD 0x00000040L +#define D3DTEXOPCAPS_ADDSIGNED 0x00000080L +#define D3DTEXOPCAPS_ADDSIGNED2X 0x00000100L +#define D3DTEXOPCAPS_SUBTRACT 0x00000200L +#define D3DTEXOPCAPS_ADDSMOOTH 0x00000400L +#define D3DTEXOPCAPS_BLENDDIFFUSEALPHA 0x00000800L +#define D3DTEXOPCAPS_BLENDTEXTUREALPHA 0x00001000L +#define D3DTEXOPCAPS_BLENDFACTORALPHA 0x00002000L +#define D3DTEXOPCAPS_BLENDTEXTUREALPHAPM 0x00004000L +#define D3DTEXOPCAPS_BLENDCURRENTALPHA 0x00008000L +#define D3DTEXOPCAPS_PREMODULATE 0x00010000L +#define D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR 0x00020000L +#define D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA 0x00040000L +#define D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR 0x00080000L +#define D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA 0x00100000L +#define D3DTEXOPCAPS_BUMPENVMAP 0x00200000L +#define D3DTEXOPCAPS_BUMPENVMAPLUMINANCE 0x00400000L +#define D3DTEXOPCAPS_DOTPRODUCT3 0x00800000L +#define D3DTEXOPCAPS_MULTIPLYADD 0x01000000L +#define D3DTEXOPCAPS_LERP 0x02000000L + +// +// FVFCaps +// +#define D3DFVFCAPS_TEXCOORDCOUNTMASK 0x0000ffffL /* mask for texture coordinate count field */ +#define D3DFVFCAPS_DONOTSTRIPELEMENTS 0x00080000L /* Device prefers that vertex elements not be stripped */ +#define D3DFVFCAPS_PSIZE 0x00100000L /* Device can receive point size */ + +// +// VertexProcessingCaps +// +#define D3DVTXPCAPS_TEXGEN 0x00000001L /* device can do texgen */ +#define D3DVTXPCAPS_MATERIALSOURCE7 0x00000002L /* device can do DX7-level colormaterialsource ops */ +#define D3DVTXPCAPS_DIRECTIONALLIGHTS 0x00000008L /* device can do directional lights */ +#define D3DVTXPCAPS_POSITIONALLIGHTS 0x00000010L /* device can do positional lights (includes point and spot) */ +#define D3DVTXPCAPS_LOCALVIEWER 0x00000020L /* device can do local viewer */ +#define D3DVTXPCAPS_TWEENING 0x00000040L /* device can do vertex tweening */ +#define D3DVTXPCAPS_TEXGEN_SPHEREMAP 0x00000100L /* device supports D3DTSS_TCI_SPHEREMAP */ +#define D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER 0x00000200L /* device does not support TexGen in non-local + viewer mode */ + +// +// DevCaps2 +// +#define D3DDEVCAPS2_STREAMOFFSET 0x00000001L /* Device supports offsets in streams. Must be set by DX9 drivers */ +#define D3DDEVCAPS2_DMAPNPATCH 0x00000002L /* Device supports displacement maps for N-Patches*/ +#define D3DDEVCAPS2_ADAPTIVETESSRTPATCH 0x00000004L /* Device supports adaptive tesselation of RT-patches*/ +#define D3DDEVCAPS2_ADAPTIVETESSNPATCH 0x00000008L /* Device supports adaptive tesselation of N-patches*/ +#define D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES 0x00000010L /* Device supports StretchRect calls with a texture as the source*/ +#define D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH 0x00000020L /* Device supports presampled displacement maps for N-Patches */ +#define D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET 0x00000040L /* Vertex elements in a vertex declaration can share the same stream offset */ + +// +// DeclTypes +// +#define D3DDTCAPS_UBYTE4 0x00000001L +#define D3DDTCAPS_UBYTE4N 0x00000002L +#define D3DDTCAPS_SHORT2N 0x00000004L +#define D3DDTCAPS_SHORT4N 0x00000008L +#define D3DDTCAPS_USHORT2N 0x00000010L +#define D3DDTCAPS_USHORT4N 0x00000020L +#define D3DDTCAPS_UDEC3 0x00000040L +#define D3DDTCAPS_DEC3N 0x00000080L +#define D3DDTCAPS_FLOAT16_2 0x00000100L +#define D3DDTCAPS_FLOAT16_4 0x00000200L + + +#pragma pack() + +#endif /* (DIRECT3D_VERSION >= 0x0900) */ +#endif /* _d3d9CAPS_H_ */ + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3d9types.h b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3d9types.h new file mode 100644 index 0000000000..9080e29968 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3d9types.h @@ -0,0 +1,2012 @@ +/*==========================================================================; + * + * Copyright (C) Microsoft Corporation. All Rights Reserved. + * + * File: d3d9types.h + * Content: Direct3D capabilities include file + * + ***************************************************************************/ + +#ifndef _d3d9TYPES_H_ +#define _d3d9TYPES_H_ + +#ifndef DIRECT3D_VERSION +#define DIRECT3D_VERSION 0x0900 +#endif //DIRECT3D_VERSION + +// include this file content only if compiling for DX9 interfaces +#if(DIRECT3D_VERSION >= 0x0900) + +#include + +#if _MSC_VER >= 1200 +#pragma warning(push) +#endif +#pragma warning(disable:4201) // anonymous unions warning +#if defined(_X86_) || defined(_IA64_) +#pragma pack(4) +#endif + +// D3DCOLOR is equivalent to D3DFMT_A8R8G8B8 +#ifndef D3DCOLOR_DEFINED +typedef DWORD D3DCOLOR; +#define D3DCOLOR_DEFINED +#endif + +// maps unsigned 8 bits/channel to D3DCOLOR +#define D3DCOLOR_ARGB(a,r,g,b) \ + ((D3DCOLOR)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff))) +#define D3DCOLOR_RGBA(r,g,b,a) D3DCOLOR_ARGB(a,r,g,b) +#define D3DCOLOR_XRGB(r,g,b) D3DCOLOR_ARGB(0xff,r,g,b) + +#define D3DCOLOR_XYUV(y,u,v) D3DCOLOR_ARGB(0xff,y,u,v) +#define D3DCOLOR_AYUV(a,y,u,v) D3DCOLOR_ARGB(a,y,u,v) + +// maps floating point channels (0.f to 1.f range) to D3DCOLOR +#define D3DCOLOR_COLORVALUE(r,g,b,a) \ + D3DCOLOR_RGBA((DWORD)((r)*255.f),(DWORD)((g)*255.f),(DWORD)((b)*255.f),(DWORD)((a)*255.f)) + + +#ifndef D3DVECTOR_DEFINED +typedef struct _D3DVECTOR { + float x; + float y; + float z; +} D3DVECTOR; +#define D3DVECTOR_DEFINED +#endif + +#ifndef D3DCOLORVALUE_DEFINED +typedef struct _D3DCOLORVALUE { + float r; + float g; + float b; + float a; +} D3DCOLORVALUE; +#define D3DCOLORVALUE_DEFINED +#endif + +#ifndef D3DRECT_DEFINED +typedef struct _D3DRECT { + LONG x1; + LONG y1; + LONG x2; + LONG y2; +} D3DRECT; +#define D3DRECT_DEFINED +#endif + +#ifndef D3DMATRIX_DEFINED +typedef struct _D3DMATRIX { + union { + struct { + float _11, _12, _13, _14; + float _21, _22, _23, _24; + float _31, _32, _33, _34; + float _41, _42, _43, _44; + + }; + float m[4][4]; + }; +} D3DMATRIX; +#define D3DMATRIX_DEFINED +#endif + +typedef struct _D3DVIEWPORT9 { + DWORD X; + DWORD Y; /* Viewport Top left */ + DWORD Width; + DWORD Height; /* Viewport Dimensions */ + float MinZ; /* Min/max of clip Volume */ + float MaxZ; +} D3DVIEWPORT9; + +/* + * Values for clip fields. + */ + +// Max number of user clipping planes, supported in D3D. +#define D3DMAXUSERCLIPPLANES 32 + +// These bits could be ORed together to use with D3DRS_CLIPPLANEENABLE +// +#define D3DCLIPPLANE0 (1 << 0) +#define D3DCLIPPLANE1 (1 << 1) +#define D3DCLIPPLANE2 (1 << 2) +#define D3DCLIPPLANE3 (1 << 3) +#define D3DCLIPPLANE4 (1 << 4) +#define D3DCLIPPLANE5 (1 << 5) + +// The following bits are used in the ClipUnion and ClipIntersection +// members of the D3DCLIPSTATUS9 +// + +#define D3DCS_LEFT 0x00000001L +#define D3DCS_RIGHT 0x00000002L +#define D3DCS_TOP 0x00000004L +#define D3DCS_BOTTOM 0x00000008L +#define D3DCS_FRONT 0x00000010L +#define D3DCS_BACK 0x00000020L +#define D3DCS_PLANE0 0x00000040L +#define D3DCS_PLANE1 0x00000080L +#define D3DCS_PLANE2 0x00000100L +#define D3DCS_PLANE3 0x00000200L +#define D3DCS_PLANE4 0x00000400L +#define D3DCS_PLANE5 0x00000800L + +#define D3DCS_ALL (D3DCS_LEFT | \ + D3DCS_RIGHT | \ + D3DCS_TOP | \ + D3DCS_BOTTOM | \ + D3DCS_FRONT | \ + D3DCS_BACK | \ + D3DCS_PLANE0 | \ + D3DCS_PLANE1 | \ + D3DCS_PLANE2 | \ + D3DCS_PLANE3 | \ + D3DCS_PLANE4 | \ + D3DCS_PLANE5) + +typedef struct _D3DCLIPSTATUS9 { + DWORD ClipUnion; + DWORD ClipIntersection; +} D3DCLIPSTATUS9; + +typedef struct _D3DMATERIAL9 { + D3DCOLORVALUE Diffuse; /* Diffuse color RGBA */ + D3DCOLORVALUE Ambient; /* Ambient color RGB */ + D3DCOLORVALUE Specular; /* Specular 'shininess' */ + D3DCOLORVALUE Emissive; /* Emissive color RGB */ + float Power; /* Sharpness if specular highlight */ +} D3DMATERIAL9; + +typedef enum _D3DLIGHTTYPE { + D3DLIGHT_POINT = 1, + D3DLIGHT_SPOT = 2, + D3DLIGHT_DIRECTIONAL = 3, + D3DLIGHT_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DLIGHTTYPE; + +typedef struct _D3DLIGHT9 { + D3DLIGHTTYPE Type; /* Type of light source */ + D3DCOLORVALUE Diffuse; /* Diffuse color of light */ + D3DCOLORVALUE Specular; /* Specular color of light */ + D3DCOLORVALUE Ambient; /* Ambient color of light */ + D3DVECTOR Position; /* Position in world space */ + D3DVECTOR Direction; /* Direction in world space */ + float Range; /* Cutoff range */ + float Falloff; /* Falloff */ + float Attenuation0; /* Constant attenuation */ + float Attenuation1; /* Linear attenuation */ + float Attenuation2; /* Quadratic attenuation */ + float Theta; /* Inner angle of spotlight cone */ + float Phi; /* Outer angle of spotlight cone */ +} D3DLIGHT9; + +/* + * Options for clearing + */ +#define D3DCLEAR_TARGET 0x00000001l /* Clear target surface */ +#define D3DCLEAR_ZBUFFER 0x00000002l /* Clear target z buffer */ +#define D3DCLEAR_STENCIL 0x00000004l /* Clear stencil planes */ + +/* + * The following defines the rendering states + */ + +typedef enum _D3DSHADEMODE { + D3DSHADE_FLAT = 1, + D3DSHADE_GOURAUD = 2, + D3DSHADE_PHONG = 3, + D3DSHADE_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DSHADEMODE; + +typedef enum _D3DFILLMODE { + D3DFILL_POINT = 1, + D3DFILL_WIREFRAME = 2, + D3DFILL_SOLID = 3, + D3DFILL_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DFILLMODE; + +typedef enum _D3DBLEND { + D3DBLEND_ZERO = 1, + D3DBLEND_ONE = 2, + D3DBLEND_SRCCOLOR = 3, + D3DBLEND_INVSRCCOLOR = 4, + D3DBLEND_SRCALPHA = 5, + D3DBLEND_INVSRCALPHA = 6, + D3DBLEND_DESTALPHA = 7, + D3DBLEND_INVDESTALPHA = 8, + D3DBLEND_DESTCOLOR = 9, + D3DBLEND_INVDESTCOLOR = 10, + D3DBLEND_SRCALPHASAT = 11, + D3DBLEND_BOTHSRCALPHA = 12, + D3DBLEND_BOTHINVSRCALPHA = 13, + D3DBLEND_BLENDFACTOR = 14, /* Only supported if D3DPBLENDCAPS_BLENDFACTOR is on */ + D3DBLEND_INVBLENDFACTOR = 15, /* Only supported if D3DPBLENDCAPS_BLENDFACTOR is on */ +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + + D3DBLEND_SRCCOLOR2 = 16, + D3DBLEND_INVSRCCOLOR2 = 17, + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + D3DBLEND_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DBLEND; + +typedef enum _D3DBLENDOP { + D3DBLENDOP_ADD = 1, + D3DBLENDOP_SUBTRACT = 2, + D3DBLENDOP_REVSUBTRACT = 3, + D3DBLENDOP_MIN = 4, + D3DBLENDOP_MAX = 5, + D3DBLENDOP_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DBLENDOP; + +typedef enum _D3DTEXTUREADDRESS { + D3DTADDRESS_WRAP = 1, + D3DTADDRESS_MIRROR = 2, + D3DTADDRESS_CLAMP = 3, + D3DTADDRESS_BORDER = 4, + D3DTADDRESS_MIRRORONCE = 5, + D3DTADDRESS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DTEXTUREADDRESS; + +typedef enum _D3DCULL { + D3DCULL_NONE = 1, + D3DCULL_CW = 2, + D3DCULL_CCW = 3, + D3DCULL_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DCULL; + +typedef enum _D3DCMPFUNC { + D3DCMP_NEVER = 1, + D3DCMP_LESS = 2, + D3DCMP_EQUAL = 3, + D3DCMP_LESSEQUAL = 4, + D3DCMP_GREATER = 5, + D3DCMP_NOTEQUAL = 6, + D3DCMP_GREATEREQUAL = 7, + D3DCMP_ALWAYS = 8, + D3DCMP_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DCMPFUNC; + +typedef enum _D3DSTENCILOP { + D3DSTENCILOP_KEEP = 1, + D3DSTENCILOP_ZERO = 2, + D3DSTENCILOP_REPLACE = 3, + D3DSTENCILOP_INCRSAT = 4, + D3DSTENCILOP_DECRSAT = 5, + D3DSTENCILOP_INVERT = 6, + D3DSTENCILOP_INCR = 7, + D3DSTENCILOP_DECR = 8, + D3DSTENCILOP_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DSTENCILOP; + +typedef enum _D3DFOGMODE { + D3DFOG_NONE = 0, + D3DFOG_EXP = 1, + D3DFOG_EXP2 = 2, + D3DFOG_LINEAR = 3, + D3DFOG_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DFOGMODE; + +typedef enum _D3DZBUFFERTYPE { + D3DZB_FALSE = 0, + D3DZB_TRUE = 1, // Z buffering + D3DZB_USEW = 2, // W buffering + D3DZB_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DZBUFFERTYPE; + +// Primitives supported by draw-primitive API +typedef enum _D3DPRIMITIVETYPE { + D3DPT_POINTLIST = 1, + D3DPT_LINELIST = 2, + D3DPT_LINESTRIP = 3, + D3DPT_TRIANGLELIST = 4, + D3DPT_TRIANGLESTRIP = 5, + D3DPT_TRIANGLEFAN = 6, + D3DPT_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DPRIMITIVETYPE; + +typedef enum _D3DTRANSFORMSTATETYPE { + D3DTS_VIEW = 2, + D3DTS_PROJECTION = 3, + D3DTS_TEXTURE0 = 16, + D3DTS_TEXTURE1 = 17, + D3DTS_TEXTURE2 = 18, + D3DTS_TEXTURE3 = 19, + D3DTS_TEXTURE4 = 20, + D3DTS_TEXTURE5 = 21, + D3DTS_TEXTURE6 = 22, + D3DTS_TEXTURE7 = 23, + D3DTS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DTRANSFORMSTATETYPE; + +#define D3DTS_WORLDMATRIX(index) (D3DTRANSFORMSTATETYPE)(index + 256) +#define D3DTS_WORLD D3DTS_WORLDMATRIX(0) +#define D3DTS_WORLD1 D3DTS_WORLDMATRIX(1) +#define D3DTS_WORLD2 D3DTS_WORLDMATRIX(2) +#define D3DTS_WORLD3 D3DTS_WORLDMATRIX(3) + +typedef enum _D3DRENDERSTATETYPE { + D3DRS_ZENABLE = 7, /* D3DZBUFFERTYPE (or TRUE/FALSE for legacy) */ + D3DRS_FILLMODE = 8, /* D3DFILLMODE */ + D3DRS_SHADEMODE = 9, /* D3DSHADEMODE */ + D3DRS_ZWRITEENABLE = 14, /* TRUE to enable z writes */ + D3DRS_ALPHATESTENABLE = 15, /* TRUE to enable alpha tests */ + D3DRS_LASTPIXEL = 16, /* TRUE for last-pixel on lines */ + D3DRS_SRCBLEND = 19, /* D3DBLEND */ + D3DRS_DESTBLEND = 20, /* D3DBLEND */ + D3DRS_CULLMODE = 22, /* D3DCULL */ + D3DRS_ZFUNC = 23, /* D3DCMPFUNC */ + D3DRS_ALPHAREF = 24, /* D3DFIXED */ + D3DRS_ALPHAFUNC = 25, /* D3DCMPFUNC */ + D3DRS_DITHERENABLE = 26, /* TRUE to enable dithering */ + D3DRS_ALPHABLENDENABLE = 27, /* TRUE to enable alpha blending */ + D3DRS_FOGENABLE = 28, /* TRUE to enable fog blending */ + D3DRS_SPECULARENABLE = 29, /* TRUE to enable specular */ + D3DRS_FOGCOLOR = 34, /* D3DCOLOR */ + D3DRS_FOGTABLEMODE = 35, /* D3DFOGMODE */ + D3DRS_FOGSTART = 36, /* Fog start (for both vertex and pixel fog) */ + D3DRS_FOGEND = 37, /* Fog end */ + D3DRS_FOGDENSITY = 38, /* Fog density */ + D3DRS_RANGEFOGENABLE = 48, /* Enables range-based fog */ + D3DRS_STENCILENABLE = 52, /* BOOL enable/disable stenciling */ + D3DRS_STENCILFAIL = 53, /* D3DSTENCILOP to do if stencil test fails */ + D3DRS_STENCILZFAIL = 54, /* D3DSTENCILOP to do if stencil test passes and Z test fails */ + D3DRS_STENCILPASS = 55, /* D3DSTENCILOP to do if both stencil and Z tests pass */ + D3DRS_STENCILFUNC = 56, /* D3DCMPFUNC fn. Stencil Test passes if ((ref & mask) stencilfn (stencil & mask)) is true */ + D3DRS_STENCILREF = 57, /* Reference value used in stencil test */ + D3DRS_STENCILMASK = 58, /* Mask value used in stencil test */ + D3DRS_STENCILWRITEMASK = 59, /* Write mask applied to values written to stencil buffer */ + D3DRS_TEXTUREFACTOR = 60, /* D3DCOLOR used for multi-texture blend */ + D3DRS_WRAP0 = 128, /* wrap for 1st texture coord. set */ + D3DRS_WRAP1 = 129, /* wrap for 2nd texture coord. set */ + D3DRS_WRAP2 = 130, /* wrap for 3rd texture coord. set */ + D3DRS_WRAP3 = 131, /* wrap for 4th texture coord. set */ + D3DRS_WRAP4 = 132, /* wrap for 5th texture coord. set */ + D3DRS_WRAP5 = 133, /* wrap for 6th texture coord. set */ + D3DRS_WRAP6 = 134, /* wrap for 7th texture coord. set */ + D3DRS_WRAP7 = 135, /* wrap for 8th texture coord. set */ + D3DRS_CLIPPING = 136, + D3DRS_LIGHTING = 137, + D3DRS_AMBIENT = 139, + D3DRS_FOGVERTEXMODE = 140, + D3DRS_COLORVERTEX = 141, + D3DRS_LOCALVIEWER = 142, + D3DRS_NORMALIZENORMALS = 143, + D3DRS_DIFFUSEMATERIALSOURCE = 145, + D3DRS_SPECULARMATERIALSOURCE = 146, + D3DRS_AMBIENTMATERIALSOURCE = 147, + D3DRS_EMISSIVEMATERIALSOURCE = 148, + D3DRS_VERTEXBLEND = 151, + D3DRS_CLIPPLANEENABLE = 152, + D3DRS_POINTSIZE = 154, /* float point size */ + D3DRS_POINTSIZE_MIN = 155, /* float point size min threshold */ + D3DRS_POINTSPRITEENABLE = 156, /* BOOL point texture coord control */ + D3DRS_POINTSCALEENABLE = 157, /* BOOL point size scale enable */ + D3DRS_POINTSCALE_A = 158, /* float point attenuation A value */ + D3DRS_POINTSCALE_B = 159, /* float point attenuation B value */ + D3DRS_POINTSCALE_C = 160, /* float point attenuation C value */ + D3DRS_MULTISAMPLEANTIALIAS = 161, // BOOL - set to do FSAA with multisample buffer + D3DRS_MULTISAMPLEMASK = 162, // DWORD - per-sample enable/disable + D3DRS_PATCHEDGESTYLE = 163, // Sets whether patch edges will use float style tessellation + D3DRS_DEBUGMONITORTOKEN = 165, // DEBUG ONLY - token to debug monitor + D3DRS_POINTSIZE_MAX = 166, /* float point size max threshold */ + D3DRS_INDEXEDVERTEXBLENDENABLE = 167, + D3DRS_COLORWRITEENABLE = 168, // per-channel write enable + D3DRS_TWEENFACTOR = 170, // float tween factor + D3DRS_BLENDOP = 171, // D3DBLENDOP setting + D3DRS_POSITIONDEGREE = 172, // NPatch position interpolation degree. D3DDEGREE_LINEAR or D3DDEGREE_CUBIC (default) + D3DRS_NORMALDEGREE = 173, // NPatch normal interpolation degree. D3DDEGREE_LINEAR (default) or D3DDEGREE_QUADRATIC + D3DRS_SCISSORTESTENABLE = 174, + D3DRS_SLOPESCALEDEPTHBIAS = 175, + D3DRS_ANTIALIASEDLINEENABLE = 176, + D3DRS_MINTESSELLATIONLEVEL = 178, + D3DRS_MAXTESSELLATIONLEVEL = 179, + D3DRS_ADAPTIVETESS_X = 180, + D3DRS_ADAPTIVETESS_Y = 181, + D3DRS_ADAPTIVETESS_Z = 182, + D3DRS_ADAPTIVETESS_W = 183, + D3DRS_ENABLEADAPTIVETESSELLATION = 184, + D3DRS_TWOSIDEDSTENCILMODE = 185, /* BOOL enable/disable 2 sided stenciling */ + D3DRS_CCW_STENCILFAIL = 186, /* D3DSTENCILOP to do if ccw stencil test fails */ + D3DRS_CCW_STENCILZFAIL = 187, /* D3DSTENCILOP to do if ccw stencil test passes and Z test fails */ + D3DRS_CCW_STENCILPASS = 188, /* D3DSTENCILOP to do if both ccw stencil and Z tests pass */ + D3DRS_CCW_STENCILFUNC = 189, /* D3DCMPFUNC fn. ccw Stencil Test passes if ((ref & mask) stencilfn (stencil & mask)) is true */ + D3DRS_COLORWRITEENABLE1 = 190, /* Additional ColorWriteEnables for the devices that support D3DPMISCCAPS_INDEPENDENTWRITEMASKS */ + D3DRS_COLORWRITEENABLE2 = 191, /* Additional ColorWriteEnables for the devices that support D3DPMISCCAPS_INDEPENDENTWRITEMASKS */ + D3DRS_COLORWRITEENABLE3 = 192, /* Additional ColorWriteEnables for the devices that support D3DPMISCCAPS_INDEPENDENTWRITEMASKS */ + D3DRS_BLENDFACTOR = 193, /* D3DCOLOR used for a constant blend factor during alpha blending for devices that support D3DPBLENDCAPS_BLENDFACTOR */ + D3DRS_SRGBWRITEENABLE = 194, /* Enable rendertarget writes to be DE-linearized to SRGB (for formats that expose D3DUSAGE_QUERY_SRGBWRITE) */ + D3DRS_DEPTHBIAS = 195, + D3DRS_WRAP8 = 198, /* Additional wrap states for vs_3_0+ attributes with D3DDECLUSAGE_TEXCOORD */ + D3DRS_WRAP9 = 199, + D3DRS_WRAP10 = 200, + D3DRS_WRAP11 = 201, + D3DRS_WRAP12 = 202, + D3DRS_WRAP13 = 203, + D3DRS_WRAP14 = 204, + D3DRS_WRAP15 = 205, + D3DRS_SEPARATEALPHABLENDENABLE = 206, /* TRUE to enable a separate blending function for the alpha channel */ + D3DRS_SRCBLENDALPHA = 207, /* SRC blend factor for the alpha channel when D3DRS_SEPARATEDESTALPHAENABLE is TRUE */ + D3DRS_DESTBLENDALPHA = 208, /* DST blend factor for the alpha channel when D3DRS_SEPARATEDESTALPHAENABLE is TRUE */ + D3DRS_BLENDOPALPHA = 209, /* Blending operation for the alpha channel when D3DRS_SEPARATEDESTALPHAENABLE is TRUE */ + + + D3DRS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DRENDERSTATETYPE; + +// Maximum number of simultaneous render targets D3D supports +#define D3D_MAX_SIMULTANEOUS_RENDERTARGETS 4 + +// Values for material source +typedef enum _D3DMATERIALCOLORSOURCE +{ + D3DMCS_MATERIAL = 0, // Color from material is used + D3DMCS_COLOR1 = 1, // Diffuse vertex color is used + D3DMCS_COLOR2 = 2, // Specular vertex color is used + D3DMCS_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum +} D3DMATERIALCOLORSOURCE; + +// Bias to apply to the texture coordinate set to apply a wrap to. +#define D3DRENDERSTATE_WRAPBIAS 128UL + +/* Flags to construct the WRAP render states */ +#define D3DWRAP_U 0x00000001L +#define D3DWRAP_V 0x00000002L +#define D3DWRAP_W 0x00000004L + +/* Flags to construct the WRAP render states for 1D thru 4D texture coordinates */ +#define D3DWRAPCOORD_0 0x00000001L // same as D3DWRAP_U +#define D3DWRAPCOORD_1 0x00000002L // same as D3DWRAP_V +#define D3DWRAPCOORD_2 0x00000004L // same as D3DWRAP_W +#define D3DWRAPCOORD_3 0x00000008L + +/* Flags to construct D3DRS_COLORWRITEENABLE */ +#define D3DCOLORWRITEENABLE_RED (1L<<0) +#define D3DCOLORWRITEENABLE_GREEN (1L<<1) +#define D3DCOLORWRITEENABLE_BLUE (1L<<2) +#define D3DCOLORWRITEENABLE_ALPHA (1L<<3) + +/* + * State enumerants for per-stage processing of fixed function pixel processing + * Two of these affect fixed function vertex processing as well: TEXTURETRANSFORMFLAGS and TEXCOORDINDEX. + */ +typedef enum _D3DTEXTURESTAGESTATETYPE +{ + D3DTSS_COLOROP = 1, /* D3DTEXTUREOP - per-stage blending controls for color channels */ + D3DTSS_COLORARG1 = 2, /* D3DTA_* (texture arg) */ + D3DTSS_COLORARG2 = 3, /* D3DTA_* (texture arg) */ + D3DTSS_ALPHAOP = 4, /* D3DTEXTUREOP - per-stage blending controls for alpha channel */ + D3DTSS_ALPHAARG1 = 5, /* D3DTA_* (texture arg) */ + D3DTSS_ALPHAARG2 = 6, /* D3DTA_* (texture arg) */ + D3DTSS_BUMPENVMAT00 = 7, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT01 = 8, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT10 = 9, /* float (bump mapping matrix) */ + D3DTSS_BUMPENVMAT11 = 10, /* float (bump mapping matrix) */ + D3DTSS_TEXCOORDINDEX = 11, /* identifies which set of texture coordinates index this texture */ + D3DTSS_BUMPENVLSCALE = 22, /* float scale for bump map luminance */ + D3DTSS_BUMPENVLOFFSET = 23, /* float offset for bump map luminance */ + D3DTSS_TEXTURETRANSFORMFLAGS = 24, /* D3DTEXTURETRANSFORMFLAGS controls texture transform */ + D3DTSS_COLORARG0 = 26, /* D3DTA_* third arg for triadic ops */ + D3DTSS_ALPHAARG0 = 27, /* D3DTA_* third arg for triadic ops */ + D3DTSS_RESULTARG = 28, /* D3DTA_* arg for result (CURRENT or TEMP) */ + D3DTSS_CONSTANT = 32, /* Per-stage constant D3DTA_CONSTANT */ + + + D3DTSS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DTEXTURESTAGESTATETYPE; + +/* + * State enumerants for per-sampler texture processing. + */ +typedef enum _D3DSAMPLERSTATETYPE +{ + D3DSAMP_ADDRESSU = 1, /* D3DTEXTUREADDRESS for U coordinate */ + D3DSAMP_ADDRESSV = 2, /* D3DTEXTUREADDRESS for V coordinate */ + D3DSAMP_ADDRESSW = 3, /* D3DTEXTUREADDRESS for W coordinate */ + D3DSAMP_BORDERCOLOR = 4, /* D3DCOLOR */ + D3DSAMP_MAGFILTER = 5, /* D3DTEXTUREFILTER filter to use for magnification */ + D3DSAMP_MINFILTER = 6, /* D3DTEXTUREFILTER filter to use for minification */ + D3DSAMP_MIPFILTER = 7, /* D3DTEXTUREFILTER filter to use between mipmaps during minification */ + D3DSAMP_MIPMAPLODBIAS = 8, /* float Mipmap LOD bias */ + D3DSAMP_MAXMIPLEVEL = 9, /* DWORD 0..(n-1) LOD index of largest map to use (0 == largest) */ + D3DSAMP_MAXANISOTROPY = 10, /* DWORD maximum anisotropy */ + D3DSAMP_SRGBTEXTURE = 11, /* Default = 0 (which means Gamma 1.0, + no correction required.) else correct for + Gamma = 2.2 */ + D3DSAMP_ELEMENTINDEX = 12, /* When multi-element texture is assigned to sampler, this + indicates which element index to use. Default = 0. */ + D3DSAMP_DMAPOFFSET = 13, /* Offset in vertices in the pre-sampled displacement map. + Only valid for D3DDMAPSAMPLER sampler */ + D3DSAMP_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DSAMPLERSTATETYPE; + +/* Special sampler which is used in the tesselator */ +#define D3DDMAPSAMPLER 256 + +// Samplers used in vertex shaders +#define D3DVERTEXTEXTURESAMPLER0 (D3DDMAPSAMPLER+1) +#define D3DVERTEXTEXTURESAMPLER1 (D3DDMAPSAMPLER+2) +#define D3DVERTEXTEXTURESAMPLER2 (D3DDMAPSAMPLER+3) +#define D3DVERTEXTEXTURESAMPLER3 (D3DDMAPSAMPLER+4) + +// Values, used with D3DTSS_TEXCOORDINDEX, to specify that the vertex data(position +// and normal in the camera space) should be taken as texture coordinates +// Low 16 bits are used to specify texture coordinate index, to take the WRAP mode from +// +#define D3DTSS_TCI_PASSTHRU 0x00000000 +#define D3DTSS_TCI_CAMERASPACENORMAL 0x00010000 +#define D3DTSS_TCI_CAMERASPACEPOSITION 0x00020000 +#define D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR 0x00030000 +#define D3DTSS_TCI_SPHEREMAP 0x00040000 + +/* + * Enumerations for COLOROP and ALPHAOP texture blending operations set in + * texture processing stage controls in D3DTSS. + */ +typedef enum _D3DTEXTUREOP +{ + // Control + D3DTOP_DISABLE = 1, // disables stage + D3DTOP_SELECTARG1 = 2, // the default + D3DTOP_SELECTARG2 = 3, + + // Modulate + D3DTOP_MODULATE = 4, // multiply args together + D3DTOP_MODULATE2X = 5, // multiply and 1 bit + D3DTOP_MODULATE4X = 6, // multiply and 2 bits + + // Add + D3DTOP_ADD = 7, // add arguments together + D3DTOP_ADDSIGNED = 8, // add with -0.5 bias + D3DTOP_ADDSIGNED2X = 9, // as above but left 1 bit + D3DTOP_SUBTRACT = 10, // Arg1 - Arg2, with no saturation + D3DTOP_ADDSMOOTH = 11, // add 2 args, subtract product + // Arg1 + Arg2 - Arg1*Arg2 + // = Arg1 + (1-Arg1)*Arg2 + + // Linear alpha blend: Arg1*(Alpha) + Arg2*(1-Alpha) + D3DTOP_BLENDDIFFUSEALPHA = 12, // iterated alpha + D3DTOP_BLENDTEXTUREALPHA = 13, // texture alpha + D3DTOP_BLENDFACTORALPHA = 14, // alpha from D3DRS_TEXTUREFACTOR + + // Linear alpha blend with pre-multiplied arg1 input: Arg1 + Arg2*(1-Alpha) + D3DTOP_BLENDTEXTUREALPHAPM = 15, // texture alpha + D3DTOP_BLENDCURRENTALPHA = 16, // by alpha of current color + + // Specular mapping + D3DTOP_PREMODULATE = 17, // modulate with next texture before use + D3DTOP_MODULATEALPHA_ADDCOLOR = 18, // Arg1.RGB + Arg1.A*Arg2.RGB + // COLOROP only + D3DTOP_MODULATECOLOR_ADDALPHA = 19, // Arg1.RGB*Arg2.RGB + Arg1.A + // COLOROP only + D3DTOP_MODULATEINVALPHA_ADDCOLOR = 20, // (1-Arg1.A)*Arg2.RGB + Arg1.RGB + // COLOROP only + D3DTOP_MODULATEINVCOLOR_ADDALPHA = 21, // (1-Arg1.RGB)*Arg2.RGB + Arg1.A + // COLOROP only + + // Bump mapping + D3DTOP_BUMPENVMAP = 22, // per pixel env map perturbation + D3DTOP_BUMPENVMAPLUMINANCE = 23, // with luminance channel + + // This can do either diffuse or specular bump mapping with correct input. + // Performs the function (Arg1.R*Arg2.R + Arg1.G*Arg2.G + Arg1.B*Arg2.B) + // where each component has been scaled and offset to make it signed. + // The result is replicated into all four (including alpha) channels. + // This is a valid COLOROP only. + D3DTOP_DOTPRODUCT3 = 24, + + // Triadic ops + D3DTOP_MULTIPLYADD = 25, // Arg0 + Arg1*Arg2 + D3DTOP_LERP = 26, // (Arg0)*Arg1 + (1-Arg0)*Arg2 + + D3DTOP_FORCE_DWORD = 0x7fffffff, +} D3DTEXTUREOP; + +/* + * Values for COLORARG0,1,2, ALPHAARG0,1,2, and RESULTARG texture blending + * operations set in texture processing stage controls in D3DRENDERSTATE. + */ +#define D3DTA_SELECTMASK 0x0000000f // mask for arg selector +#define D3DTA_DIFFUSE 0x00000000 // select diffuse color (read only) +#define D3DTA_CURRENT 0x00000001 // select stage destination register (read/write) +#define D3DTA_TEXTURE 0x00000002 // select texture color (read only) +#define D3DTA_TFACTOR 0x00000003 // select D3DRS_TEXTUREFACTOR (read only) +#define D3DTA_SPECULAR 0x00000004 // select specular color (read only) +#define D3DTA_TEMP 0x00000005 // select temporary register color (read/write) +#define D3DTA_CONSTANT 0x00000006 // select texture stage constant +#define D3DTA_COMPLEMENT 0x00000010 // take 1.0 - x (read modifier) +#define D3DTA_ALPHAREPLICATE 0x00000020 // replicate alpha to color components (read modifier) + +// +// Values for D3DSAMP_***FILTER texture stage states +// +typedef enum _D3DTEXTUREFILTERTYPE +{ + D3DTEXF_NONE = 0, // filtering disabled (valid for mip filter only) + D3DTEXF_POINT = 1, // nearest + D3DTEXF_LINEAR = 2, // linear interpolation + D3DTEXF_ANISOTROPIC = 3, // anisotropic + D3DTEXF_PYRAMIDALQUAD = 6, // 4-sample tent + D3DTEXF_GAUSSIANQUAD = 7, // 4-sample gaussian +/* D3D9Ex only -- */ +#if !defined(D3D_DISABLE_9EX) + + D3DTEXF_CONVOLUTIONMONO = 8, // Convolution filter for monochrome textures + +#endif // !D3D_DISABLE_9EX +/* -- D3D9Ex only */ + D3DTEXF_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum +} D3DTEXTUREFILTERTYPE; + +/* Bits for Flags in ProcessVertices call */ + +#define D3DPV_DONOTCOPYDATA (1 << 0) + +//------------------------------------------------------------------- + +// Flexible vertex format bits +// +#define D3DFVF_RESERVED0 0x001 +#define D3DFVF_POSITION_MASK 0x400E +#define D3DFVF_XYZ 0x002 +#define D3DFVF_XYZRHW 0x004 +#define D3DFVF_XYZB1 0x006 +#define D3DFVF_XYZB2 0x008 +#define D3DFVF_XYZB3 0x00a +#define D3DFVF_XYZB4 0x00c +#define D3DFVF_XYZB5 0x00e +#define D3DFVF_XYZW 0x4002 + +#define D3DFVF_NORMAL 0x010 +#define D3DFVF_PSIZE 0x020 +#define D3DFVF_DIFFUSE 0x040 +#define D3DFVF_SPECULAR 0x080 + +#define D3DFVF_TEXCOUNT_MASK 0xf00 +#define D3DFVF_TEXCOUNT_SHIFT 8 +#define D3DFVF_TEX0 0x000 +#define D3DFVF_TEX1 0x100 +#define D3DFVF_TEX2 0x200 +#define D3DFVF_TEX3 0x300 +#define D3DFVF_TEX4 0x400 +#define D3DFVF_TEX5 0x500 +#define D3DFVF_TEX6 0x600 +#define D3DFVF_TEX7 0x700 +#define D3DFVF_TEX8 0x800 + +#define D3DFVF_LASTBETA_UBYTE4 0x1000 +#define D3DFVF_LASTBETA_D3DCOLOR 0x8000 + +#define D3DFVF_RESERVED2 0x6000 // 2 reserved bits + +//--------------------------------------------------------------------- +// Vertex Shaders +// + +// Vertex shader declaration + +// Vertex element semantics +// +typedef enum _D3DDECLUSAGE +{ + D3DDECLUSAGE_POSITION = 0, + D3DDECLUSAGE_BLENDWEIGHT, // 1 + D3DDECLUSAGE_BLENDINDICES, // 2 + D3DDECLUSAGE_NORMAL, // 3 + D3DDECLUSAGE_PSIZE, // 4 + D3DDECLUSAGE_TEXCOORD, // 5 + D3DDECLUSAGE_TANGENT, // 6 + D3DDECLUSAGE_BINORMAL, // 7 + D3DDECLUSAGE_TESSFACTOR, // 8 + D3DDECLUSAGE_POSITIONT, // 9 + D3DDECLUSAGE_COLOR, // 10 + D3DDECLUSAGE_FOG, // 11 + D3DDECLUSAGE_DEPTH, // 12 + D3DDECLUSAGE_SAMPLE, // 13 +} D3DDECLUSAGE; + +#define MAXD3DDECLUSAGE D3DDECLUSAGE_SAMPLE +#define MAXD3DDECLUSAGEINDEX 15 +#define MAXD3DDECLLENGTH 64 // does not include "end" marker vertex element + +typedef enum _D3DDECLMETHOD +{ + D3DDECLMETHOD_DEFAULT = 0, + D3DDECLMETHOD_PARTIALU, + D3DDECLMETHOD_PARTIALV, + D3DDECLMETHOD_CROSSUV, // Normal + D3DDECLMETHOD_UV, + D3DDECLMETHOD_LOOKUP, // Lookup a displacement map + D3DDECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map +} D3DDECLMETHOD; + +#define MAXD3DDECLMETHOD D3DDECLMETHOD_LOOKUPPRESAMPLED + +// Declarations for _Type fields +// +typedef enum _D3DDECLTYPE +{ + D3DDECLTYPE_FLOAT1 = 0, // 1D float expanded to (value, 0., 0., 1.) + D3DDECLTYPE_FLOAT2 = 1, // 2D float expanded to (value, value, 0., 1.) + D3DDECLTYPE_FLOAT3 = 2, // 3D float expanded to (value, value, value, 1.) + D3DDECLTYPE_FLOAT4 = 3, // 4D float + D3DDECLTYPE_D3DCOLOR = 4, // 4D packed unsigned bytes mapped to 0. to 1. range + // Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A) + D3DDECLTYPE_UBYTE4 = 5, // 4D unsigned byte + D3DDECLTYPE_SHORT2 = 6, // 2D signed short expanded to (value, value, 0., 1.) + D3DDECLTYPE_SHORT4 = 7, // 4D signed short + +// The following types are valid only with vertex shaders >= 2.0 + + + D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0 + D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1) + D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0) + D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1) + D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0) + D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1) + D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1) + D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1) + D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values + D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused. +} D3DDECLTYPE; + +#define MAXD3DDECLTYPE D3DDECLTYPE_UNUSED + +typedef struct _D3DVERTEXELEMENT9 +{ + WORD Stream; // Stream index + WORD Offset; // Offset in the stream in bytes + BYTE Type; // Data type + BYTE Method; // Processing method + BYTE Usage; // Semantics + BYTE UsageIndex; // Semantic index +} D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9; + +// This is used to initialize the last vertex element in a vertex declaration +// array +// +#define D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0} + +// Maximum supported number of texture coordinate sets +#define D3DDP_MAXTEXCOORD 8 + +//--------------------------------------------------------------------- +// Values for IDirect3DDevice9::SetStreamSourceFreq's Setting parameter +//--------------------------------------------------------------------- +#define D3DSTREAMSOURCE_INDEXEDDATA (1<<30) +#define D3DSTREAMSOURCE_INSTANCEDATA (2<<30) + + + +//--------------------------------------------------------------------- +// +// The internal format of Pixel Shader (PS) & Vertex Shader (VS) +// Instruction Tokens is defined in the Direct3D Device Driver Kit +// +//--------------------------------------------------------------------- + +// +// Instruction Token Bit Definitions +// +#define D3DSI_OPCODE_MASK 0x0000FFFF + +#define D3DSI_INSTLENGTH_MASK 0x0F000000 +#define D3DSI_INSTLENGTH_SHIFT 24 + +typedef enum _D3DSHADER_INSTRUCTION_OPCODE_TYPE +{ + D3DSIO_NOP = 0, + D3DSIO_MOV , + D3DSIO_ADD , + D3DSIO_SUB , + D3DSIO_MAD , + D3DSIO_MUL , + D3DSIO_RCP , + D3DSIO_RSQ , + D3DSIO_DP3 , + D3DSIO_DP4 , + D3DSIO_MIN , + D3DSIO_MAX , + D3DSIO_SLT , + D3DSIO_SGE , + D3DSIO_EXP , + D3DSIO_LOG , + D3DSIO_LIT , + D3DSIO_DST , + D3DSIO_LRP , + D3DSIO_FRC , + D3DSIO_M4x4 , + D3DSIO_M4x3 , + D3DSIO_M3x4 , + D3DSIO_M3x3 , + D3DSIO_M3x2 , + D3DSIO_CALL , + D3DSIO_CALLNZ , + D3DSIO_LOOP , + D3DSIO_RET , + D3DSIO_ENDLOOP , + D3DSIO_LABEL , + D3DSIO_DCL , + D3DSIO_POW , + D3DSIO_CRS , + D3DSIO_SGN , + D3DSIO_ABS , + D3DSIO_NRM , + D3DSIO_SINCOS , + D3DSIO_REP , + D3DSIO_ENDREP , + D3DSIO_IF , + D3DSIO_IFC , + D3DSIO_ELSE , + D3DSIO_ENDIF , + D3DSIO_BREAK , + D3DSIO_BREAKC , + D3DSIO_MOVA , + D3DSIO_DEFB , + D3DSIO_DEFI , + + D3DSIO_TEXCOORD = 64, + D3DSIO_TEXKILL , + D3DSIO_TEX , + D3DSIO_TEXBEM , + D3DSIO_TEXBEML , + D3DSIO_TEXREG2AR , + D3DSIO_TEXREG2GB , + D3DSIO_TEXM3x2PAD , + D3DSIO_TEXM3x2TEX , + D3DSIO_TEXM3x3PAD , + D3DSIO_TEXM3x3TEX , + D3DSIO_RESERVED0 , + D3DSIO_TEXM3x3SPEC , + D3DSIO_TEXM3x3VSPEC , + D3DSIO_EXPP , + D3DSIO_LOGP , + D3DSIO_CND , + D3DSIO_DEF , + D3DSIO_TEXREG2RGB , + D3DSIO_TEXDP3TEX , + D3DSIO_TEXM3x2DEPTH , + D3DSIO_TEXDP3 , + D3DSIO_TEXM3x3 , + D3DSIO_TEXDEPTH , + D3DSIO_CMP , + D3DSIO_BEM , + D3DSIO_DP2ADD , + D3DSIO_DSX , + D3DSIO_DSY , + D3DSIO_TEXLDD , + D3DSIO_SETP , + D3DSIO_TEXLDL , + D3DSIO_BREAKP , + + D3DSIO_PHASE = 0xFFFD, + D3DSIO_COMMENT = 0xFFFE, + D3DSIO_END = 0xFFFF, + + D3DSIO_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum +} D3DSHADER_INSTRUCTION_OPCODE_TYPE; + +//--------------------------------------------------------------------- +// Use these constants with D3DSIO_SINCOS macro as SRC2, SRC3 +// +#define D3DSINCOSCONST1 -1.5500992e-006f, -2.1701389e-005f, 0.0026041667f, 0.00026041668f +#define D3DSINCOSCONST2 -0.020833334f, -0.12500000f, 1.0f, 0.50000000f + +//--------------------------------------------------------------------- +// Co-Issue Instruction Modifier - if set then this instruction is to be +// issued in parallel with the previous instruction(s) for which this bit +// is not set. +// +#define D3DSI_COISSUE 0x40000000 + +//--------------------------------------------------------------------- +// Opcode specific controls + +#define D3DSP_OPCODESPECIFICCONTROL_MASK 0x00ff0000 +#define D3DSP_OPCODESPECIFICCONTROL_SHIFT 16 + +// ps_2_0 texld controls +#define D3DSI_TEXLD_PROJECT (0x01 << D3DSP_OPCODESPECIFICCONTROL_SHIFT) +#define D3DSI_TEXLD_BIAS (0x02 << D3DSP_OPCODESPECIFICCONTROL_SHIFT) + +// Comparison for dynamic conditional instruction opcodes (i.e. if, breakc) +typedef enum _D3DSHADER_COMPARISON +{ + // < = > + D3DSPC_RESERVED0= 0, // 0 0 0 + D3DSPC_GT = 1, // 0 0 1 + D3DSPC_EQ = 2, // 0 1 0 + D3DSPC_GE = 3, // 0 1 1 + D3DSPC_LT = 4, // 1 0 0 + D3DSPC_NE = 5, // 1 0 1 + D3DSPC_LE = 6, // 1 1 0 + D3DSPC_RESERVED1= 7 // 1 1 1 +} D3DSHADER_COMPARISON; + +// Comparison is part of instruction opcode token: +#define D3DSHADER_COMPARISON_SHIFT D3DSP_OPCODESPECIFICCONTROL_SHIFT +#define D3DSHADER_COMPARISON_MASK (0x7<>8)&0xFF) +#define D3DSHADER_VERSION_MINOR(_Version) (((_Version)>>0)&0xFF) + +// destination/source parameter register type +#define D3DSI_COMMENTSIZE_SHIFT 16 +#define D3DSI_COMMENTSIZE_MASK 0x7FFF0000 +#define D3DSHADER_COMMENT(_DWordSize) \ + ((((_DWordSize)<= 1200 +#pragma warning(pop) +#else +#pragma warning(default:4201) +#endif + +#endif /* (DIRECT3D_VERSION >= 0x0900) */ +#endif /* _d3d9TYPES(P)_H_ */ + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9.h b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9.h new file mode 100644 index 0000000000..822f0a8190 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9.h @@ -0,0 +1,76 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9.h +// Content: D3DX utility library +// +////////////////////////////////////////////////////////////////////////////// + +#ifdef __D3DX_INTERNAL__ +#error Incorrect D3DX header used +#endif + +#ifndef __D3DX9_H__ +#define __D3DX9_H__ + + +// Defines +#include + +#define D3DX_DEFAULT ((UINT) -1) +#define D3DX_DEFAULT_NONPOW2 ((UINT) -2) +#define D3DX_DEFAULT_FLOAT FLT_MAX +#define D3DX_FROM_FILE ((UINT) -3) +#define D3DFMT_FROM_FILE ((D3DFORMAT) -3) + +#ifndef D3DXINLINE +#ifdef _MSC_VER + #if (_MSC_VER >= 1200) + #define D3DXINLINE __forceinline + #else + #define D3DXINLINE __inline + #endif +#else + #ifdef __cplusplus + #define D3DXINLINE inline + #else + #define D3DXINLINE + #endif +#endif +#endif + + + +// Includes +#include "d3d9.h" +#include "d3dx9math.h" +#include "d3dx9core.h" +#include "d3dx9xof.h" +#include "d3dx9mesh.h" +#include "d3dx9shader.h" +#include "d3dx9effect.h" +#include "d3dx9tex.h" +#include "d3dx9shape.h" +#include "d3dx9anim.h" + + +// Errors +#define _FACDD 0x876 +#define MAKE_DDHRESULT( code ) MAKE_HRESULT( 1, _FACDD, code ) + +enum _D3DXERR { + D3DXERR_CANNOTMODIFYINDEXBUFFER = MAKE_DDHRESULT(2900), + D3DXERR_INVALIDMESH = MAKE_DDHRESULT(2901), + D3DXERR_CANNOTATTRSORT = MAKE_DDHRESULT(2902), + D3DXERR_SKINNINGNOTSUPPORTED = MAKE_DDHRESULT(2903), + D3DXERR_TOOMANYINFLUENCES = MAKE_DDHRESULT(2904), + D3DXERR_INVALIDDATA = MAKE_DDHRESULT(2905), + D3DXERR_LOADEDMESHASNODATA = MAKE_DDHRESULT(2906), + D3DXERR_DUPLICATENAMEDFRAGMENT = MAKE_DDHRESULT(2907), + D3DXERR_CANNOTREMOVELASTITEM = MAKE_DDHRESULT(2908), +}; + + +#endif //__D3DX9_H__ + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9anim.h b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9anim.h new file mode 100644 index 0000000000..fedb1dbec0 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9anim.h @@ -0,0 +1,1114 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9anim.h +// Content: D3DX mesh types and functions +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef __D3DX9ANIM_H__ +#define __D3DX9ANIM_H__ + +// {698CFB3F-9289-4d95-9A57-33A94B5A65F9} +DEFINE_GUID(IID_ID3DXAnimationSet, +0x698cfb3f, 0x9289, 0x4d95, 0x9a, 0x57, 0x33, 0xa9, 0x4b, 0x5a, 0x65, 0xf9); + +// {FA4E8E3A-9786-407d-8B4C-5995893764AF} +DEFINE_GUID(IID_ID3DXKeyframedAnimationSet, +0xfa4e8e3a, 0x9786, 0x407d, 0x8b, 0x4c, 0x59, 0x95, 0x89, 0x37, 0x64, 0xaf); + +// {6CC2480D-3808-4739-9F88-DE49FACD8D4C} +DEFINE_GUID(IID_ID3DXCompressedAnimationSet, +0x6cc2480d, 0x3808, 0x4739, 0x9f, 0x88, 0xde, 0x49, 0xfa, 0xcd, 0x8d, 0x4c); + +// {AC8948EC-F86D-43e2-96DE-31FC35F96D9E} +DEFINE_GUID(IID_ID3DXAnimationController, +0xac8948ec, 0xf86d, 0x43e2, 0x96, 0xde, 0x31, 0xfc, 0x35, 0xf9, 0x6d, 0x9e); + + +//---------------------------------------------------------------------------- +// D3DXMESHDATATYPE: +// ----------------- +// This enum defines the type of mesh data present in a MeshData structure. +//---------------------------------------------------------------------------- +typedef enum _D3DXMESHDATATYPE { + D3DXMESHTYPE_MESH = 0x001, // Normal ID3DXMesh data + D3DXMESHTYPE_PMESH = 0x002, // Progressive Mesh - ID3DXPMesh + D3DXMESHTYPE_PATCHMESH = 0x003, // Patch Mesh - ID3DXPatchMesh + + D3DXMESHTYPE_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DXMESHDATATYPE; + +//---------------------------------------------------------------------------- +// D3DXMESHDATA: +// ------------- +// This struct encapsulates a the mesh data that can be present in a mesh +// container. The supported mesh types are pMesh, pPMesh, pPatchMesh. +// The valid way to access this is determined by the Type enum. +//---------------------------------------------------------------------------- +typedef struct _D3DXMESHDATA +{ + D3DXMESHDATATYPE Type; + + // current mesh data interface + union + { + LPD3DXMESH pMesh; + LPD3DXPMESH pPMesh; + LPD3DXPATCHMESH pPatchMesh; + }; +} D3DXMESHDATA, *LPD3DXMESHDATA; + +//---------------------------------------------------------------------------- +// D3DXMESHCONTAINER: +// ------------------ +// This struct encapsulates a mesh object in a transformation frame +// hierarchy. The app can derive from this structure to add other app specific +// data to this. +//---------------------------------------------------------------------------- +typedef struct _D3DXMESHCONTAINER +{ + LPSTR Name; + + D3DXMESHDATA MeshData; + + LPD3DXMATERIAL pMaterials; + LPD3DXEFFECTINSTANCE pEffects; + DWORD NumMaterials; + DWORD *pAdjacency; + + LPD3DXSKININFO pSkinInfo; + + struct _D3DXMESHCONTAINER *pNextMeshContainer; +} D3DXMESHCONTAINER, *LPD3DXMESHCONTAINER; + +//---------------------------------------------------------------------------- +// D3DXFRAME: +// ---------- +// This struct is the encapsulates a transform frame in a transformation frame +// hierarchy. The app can derive from this structure to add other app specific +// data to this +//---------------------------------------------------------------------------- +typedef struct _D3DXFRAME +{ + LPSTR Name; + D3DXMATRIX TransformationMatrix; + + LPD3DXMESHCONTAINER pMeshContainer; + + struct _D3DXFRAME *pFrameSibling; + struct _D3DXFRAME *pFrameFirstChild; +} D3DXFRAME, *LPD3DXFRAME; + + +//---------------------------------------------------------------------------- +// ID3DXAllocateHierarchy: +// ----------------------- +// This interface is implemented by the application to allocate/free frame and +// mesh container objects. Methods on this are called during loading and +// destroying frame hierarchies +//---------------------------------------------------------------------------- +typedef interface ID3DXAllocateHierarchy ID3DXAllocateHierarchy; +typedef interface ID3DXAllocateHierarchy *LPD3DXALLOCATEHIERARCHY; + +#undef INTERFACE +#define INTERFACE ID3DXAllocateHierarchy + +DECLARE_INTERFACE(ID3DXAllocateHierarchy) +{ + // ID3DXAllocateHierarchy + + //------------------------------------------------------------------------ + // CreateFrame: + // ------------ + // Requests allocation of a frame object. + // + // Parameters: + // Name + // Name of the frame to be created + // ppNewFrame + // Returns the created frame object + // + //------------------------------------------------------------------------ + STDMETHOD(CreateFrame)(THIS_ LPCSTR Name, + LPD3DXFRAME *ppNewFrame) PURE; + + //------------------------------------------------------------------------ + // CreateMeshContainer: + // -------------------- + // Requests allocation of a mesh container object. + // + // Parameters: + // Name + // Name of the mesh + // pMesh + // Pointer to the mesh object if basic polygon data found + // pPMesh + // Pointer to the progressive mesh object if progressive mesh data found + // pPatchMesh + // Pointer to the patch mesh object if patch data found + // pMaterials + // Array of materials used in the mesh + // pEffectInstances + // Array of effect instances used in the mesh + // NumMaterials + // Num elements in the pMaterials array + // pAdjacency + // Adjacency array for the mesh + // pSkinInfo + // Pointer to the skininfo object if the mesh is skinned + // pBoneNames + // Array of names, one for each bone in the skinned mesh. + // The numberof bones can be found from the pSkinMesh object + // pBoneOffsetMatrices + // Array of matrices, one for each bone in the skinned mesh. + // + //------------------------------------------------------------------------ + STDMETHOD(CreateMeshContainer)(THIS_ + LPCSTR Name, + CONST D3DXMESHDATA *pMeshData, + CONST D3DXMATERIAL *pMaterials, + CONST D3DXEFFECTINSTANCE *pEffectInstances, + DWORD NumMaterials, + CONST DWORD *pAdjacency, + LPD3DXSKININFO pSkinInfo, + LPD3DXMESHCONTAINER *ppNewMeshContainer) PURE; + + //------------------------------------------------------------------------ + // DestroyFrame: + // ------------- + // Requests de-allocation of a frame object. + // + // Parameters: + // pFrameToFree + // Pointer to the frame to be de-allocated + // + //------------------------------------------------------------------------ + STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree) PURE; + + //------------------------------------------------------------------------ + // DestroyMeshContainer: + // --------------------- + // Requests de-allocation of a mesh container object. + // + // Parameters: + // pMeshContainerToFree + // Pointer to the mesh container object to be de-allocated + // + //------------------------------------------------------------------------ + STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerToFree) PURE; +}; + +//---------------------------------------------------------------------------- +// ID3DXLoadUserData: +// ------------------ +// This interface is implemented by the application to load user data in a .X file +// When user data is found, these callbacks will be used to allow the application +// to load the data. +//---------------------------------------------------------------------------- +typedef interface ID3DXLoadUserData ID3DXLoadUserData; +typedef interface ID3DXLoadUserData *LPD3DXLOADUSERDATA; + +#undef INTERFACE +#define INTERFACE ID3DXLoadUserData + +DECLARE_INTERFACE(ID3DXLoadUserData) +{ + STDMETHOD(LoadTopLevelData)(LPD3DXFILEDATA pXofChildData) PURE; + + STDMETHOD(LoadFrameChildData)(LPD3DXFRAME pFrame, + LPD3DXFILEDATA pXofChildData) PURE; + + STDMETHOD(LoadMeshChildData)(LPD3DXMESHCONTAINER pMeshContainer, + LPD3DXFILEDATA pXofChildData) PURE; +}; + +//---------------------------------------------------------------------------- +// ID3DXSaveUserData: +// ------------------ +// This interface is implemented by the application to save user data in a .X file +// The callbacks are called for all data saved. The user can then add any +// child data objects to the object provided to the callback. +//---------------------------------------------------------------------------- +typedef interface ID3DXSaveUserData ID3DXSaveUserData; +typedef interface ID3DXSaveUserData *LPD3DXSAVEUSERDATA; + +#undef INTERFACE +#define INTERFACE ID3DXSaveUserData + +DECLARE_INTERFACE(ID3DXSaveUserData) +{ + STDMETHOD(AddFrameChildData)(CONST D3DXFRAME *pFrame, + LPD3DXFILESAVEOBJECT pXofSave, + LPD3DXFILESAVEDATA pXofFrameData) PURE; + + STDMETHOD(AddMeshChildData)(CONST D3DXMESHCONTAINER *pMeshContainer, + LPD3DXFILESAVEOBJECT pXofSave, + LPD3DXFILESAVEDATA pXofMeshData) PURE; + + // NOTE: this is called once per Save. All top level objects should be added using the + // provided interface. One call adds objects before the frame hierarchy, the other after + STDMETHOD(AddTopLevelDataObjectsPre)(LPD3DXFILESAVEOBJECT pXofSave) PURE; + STDMETHOD(AddTopLevelDataObjectsPost)(LPD3DXFILESAVEOBJECT pXofSave) PURE; + + // callbacks for the user to register and then save templates to the XFile + STDMETHOD(RegisterTemplates)(LPD3DXFILE pXFileApi) PURE; + STDMETHOD(SaveTemplates)(LPD3DXFILESAVEOBJECT pXofSave) PURE; +}; + + +//---------------------------------------------------------------------------- +// D3DXCALLBACK_SEARCH_FLAGS: +// -------------------------- +// Flags that can be passed into ID3DXAnimationSet::GetCallback. +//---------------------------------------------------------------------------- +typedef enum _D3DXCALLBACK_SEARCH_FLAGS +{ + D3DXCALLBACK_SEARCH_EXCLUDING_INITIAL_POSITION = 0x01, // exclude callbacks at the initial position from the search + D3DXCALLBACK_SEARCH_BEHIND_INITIAL_POSITION = 0x02, // reverse the callback search direction + + D3DXCALLBACK_SEARCH_FORCE_DWORD = 0x7fffffff, +} D3DXCALLBACK_SEARCH_FLAGS; + +//---------------------------------------------------------------------------- +// ID3DXAnimationSet: +// ------------------ +// This interface implements an animation set. +//---------------------------------------------------------------------------- +typedef interface ID3DXAnimationSet ID3DXAnimationSet; +typedef interface ID3DXAnimationSet *LPD3DXANIMATIONSET; + +#undef INTERFACE +#define INTERFACE ID3DXAnimationSet + +DECLARE_INTERFACE_(ID3DXAnimationSet, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Name + STDMETHOD_(LPCSTR, GetName)(THIS) PURE; + + // Period + STDMETHOD_(DOUBLE, GetPeriod)(THIS) PURE; + STDMETHOD_(DOUBLE, GetPeriodicPosition)(THIS_ DOUBLE Position) PURE; // Maps position into animation period + + // Animation names + STDMETHOD_(UINT, GetNumAnimations)(THIS) PURE; + STDMETHOD(GetAnimationNameByIndex)(THIS_ UINT Index, LPCSTR *ppName) PURE; + STDMETHOD(GetAnimationIndexByName)(THIS_ LPCSTR pName, UINT *pIndex) PURE; + + // SRT + STDMETHOD(GetSRT)(THIS_ + DOUBLE PeriodicPosition, // Position mapped to period (use GetPeriodicPosition) + UINT Animation, // Animation index + D3DXVECTOR3 *pScale, // Returns the scale + D3DXQUATERNION *pRotation, // Returns the rotation as a quaternion + D3DXVECTOR3 *pTranslation) PURE; // Returns the translation + + // Callbacks + STDMETHOD(GetCallback)(THIS_ + DOUBLE Position, // Position from which to find callbacks + DWORD Flags, // Callback search flags + DOUBLE *pCallbackPosition, // Returns the position of the callback + LPVOID *ppCallbackData) PURE; // Returns the callback data pointer +}; + + +//---------------------------------------------------------------------------- +// D3DXPLAYBACK_TYPE: +// ------------------ +// This enum defines the type of animation set loop modes. +//---------------------------------------------------------------------------- +typedef enum _D3DXPLAYBACK_TYPE +{ + D3DXPLAY_LOOP = 0, + D3DXPLAY_ONCE = 1, + D3DXPLAY_PINGPONG = 2, + + D3DXPLAY_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DXPLAYBACK_TYPE; + + +//---------------------------------------------------------------------------- +// D3DXKEY_VECTOR3: +// ---------------- +// This structure describes a vector key for use in keyframe animation. +// It specifies a vector Value at a given Time. This is used for scale and +// translation keys. +//---------------------------------------------------------------------------- +typedef struct _D3DXKEY_VECTOR3 +{ + FLOAT Time; + D3DXVECTOR3 Value; +} D3DXKEY_VECTOR3, *LPD3DXKEY_VECTOR3; + + +//---------------------------------------------------------------------------- +// D3DXKEY_QUATERNION: +// ------------------- +// This structure describes a quaternion key for use in keyframe animation. +// It specifies a quaternion Value at a given Time. This is used for rotation +// keys. +//---------------------------------------------------------------------------- +typedef struct _D3DXKEY_QUATERNION +{ + FLOAT Time; + D3DXQUATERNION Value; +} D3DXKEY_QUATERNION, *LPD3DXKEY_QUATERNION; + + +//---------------------------------------------------------------------------- +// D3DXKEY_CALLBACK: +// ----------------- +// This structure describes an callback key for use in keyframe animation. +// It specifies a pointer to user data at a given Time. +//---------------------------------------------------------------------------- +typedef struct _D3DXKEY_CALLBACK +{ + FLOAT Time; + LPVOID pCallbackData; +} D3DXKEY_CALLBACK, *LPD3DXKEY_CALLBACK; + + +//---------------------------------------------------------------------------- +// D3DXCOMPRESSION_FLAGS: +// ---------------------- +// Flags that can be passed into ID3DXKeyframedAnimationSet::Compress. +//---------------------------------------------------------------------------- +typedef enum _D3DXCOMPRESSION_FLAGS +{ + D3DXCOMPRESS_DEFAULT = 0x00, + + D3DXCOMPRESS_FORCE_DWORD = 0x7fffffff, +} D3DXCOMPRESSION_FLAGS; + + +//---------------------------------------------------------------------------- +// ID3DXKeyframedAnimationSet: +// --------------------------- +// This interface implements a compressable keyframed animation set. +//---------------------------------------------------------------------------- +typedef interface ID3DXKeyframedAnimationSet ID3DXKeyframedAnimationSet; +typedef interface ID3DXKeyframedAnimationSet *LPD3DXKEYFRAMEDANIMATIONSET; + +#undef INTERFACE +#define INTERFACE ID3DXKeyframedAnimationSet + +DECLARE_INTERFACE_(ID3DXKeyframedAnimationSet, ID3DXAnimationSet) +{ + // ID3DXAnimationSet + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Name + STDMETHOD_(LPCSTR, GetName)(THIS) PURE; + + // Period + STDMETHOD_(DOUBLE, GetPeriod)(THIS) PURE; + STDMETHOD_(DOUBLE, GetPeriodicPosition)(THIS_ DOUBLE Position) PURE; // Maps position into animation period + + // Animation names + STDMETHOD_(UINT, GetNumAnimations)(THIS) PURE; + STDMETHOD(GetAnimationNameByIndex)(THIS_ UINT Index, LPCSTR *ppName) PURE; + STDMETHOD(GetAnimationIndexByName)(THIS_ LPCSTR pName, UINT *pIndex) PURE; + + // SRT + STDMETHOD(GetSRT)(THIS_ + DOUBLE PeriodicPosition, // Position mapped to period (use GetPeriodicPosition) + UINT Animation, // Animation index + D3DXVECTOR3 *pScale, // Returns the scale + D3DXQUATERNION *pRotation, // Returns the rotation as a quaternion + D3DXVECTOR3 *pTranslation) PURE; // Returns the translation + + // Callbacks + STDMETHOD(GetCallback)(THIS_ + DOUBLE Position, // Position from which to find callbacks + DWORD Flags, // Callback search flags + DOUBLE *pCallbackPosition, // Returns the position of the callback + LPVOID *ppCallbackData) PURE; // Returns the callback data pointer + + // Playback + STDMETHOD_(D3DXPLAYBACK_TYPE, GetPlaybackType)(THIS) PURE; + STDMETHOD_(DOUBLE, GetSourceTicksPerSecond)(THIS) PURE; + + // Scale keys + STDMETHOD_(UINT, GetNumScaleKeys)(THIS_ UINT Animation) PURE; + STDMETHOD(GetScaleKeys)(THIS_ UINT Animation, LPD3DXKEY_VECTOR3 pScaleKeys) PURE; + STDMETHOD(GetScaleKey)(THIS_ UINT Animation, UINT Key, LPD3DXKEY_VECTOR3 pScaleKey) PURE; + STDMETHOD(SetScaleKey)(THIS_ UINT Animation, UINT Key, LPD3DXKEY_VECTOR3 pScaleKey) PURE; + + // Rotation keys + STDMETHOD_(UINT, GetNumRotationKeys)(THIS_ UINT Animation) PURE; + STDMETHOD(GetRotationKeys)(THIS_ UINT Animation, LPD3DXKEY_QUATERNION pRotationKeys) PURE; + STDMETHOD(GetRotationKey)(THIS_ UINT Animation, UINT Key, LPD3DXKEY_QUATERNION pRotationKey) PURE; + STDMETHOD(SetRotationKey)(THIS_ UINT Animation, UINT Key, LPD3DXKEY_QUATERNION pRotationKey) PURE; + + // Translation keys + STDMETHOD_(UINT, GetNumTranslationKeys)(THIS_ UINT Animation) PURE; + STDMETHOD(GetTranslationKeys)(THIS_ UINT Animation, LPD3DXKEY_VECTOR3 pTranslationKeys) PURE; + STDMETHOD(GetTranslationKey)(THIS_ UINT Animation, UINT Key, LPD3DXKEY_VECTOR3 pTranslationKey) PURE; + STDMETHOD(SetTranslationKey)(THIS_ UINT Animation, UINT Key, LPD3DXKEY_VECTOR3 pTranslationKey) PURE; + + // Callback keys + STDMETHOD_(UINT, GetNumCallbackKeys)(THIS) PURE; + STDMETHOD(GetCallbackKeys)(THIS_ LPD3DXKEY_CALLBACK pCallbackKeys) PURE; + STDMETHOD(GetCallbackKey)(THIS_ UINT Key, LPD3DXKEY_CALLBACK pCallbackKey) PURE; + STDMETHOD(SetCallbackKey)(THIS_ UINT Key, LPD3DXKEY_CALLBACK pCallbackKey) PURE; + + // Key removal methods. These are slow, and should not be used once the animation starts playing + STDMETHOD(UnregisterScaleKey)(THIS_ UINT Animation, UINT Key) PURE; + STDMETHOD(UnregisterRotationKey)(THIS_ UINT Animation, UINT Key) PURE; + STDMETHOD(UnregisterTranslationKey)(THIS_ UINT Animation, UINT Key) PURE; + + // One-time animaton SRT keyframe registration + STDMETHOD(RegisterAnimationSRTKeys)(THIS_ + LPCSTR pName, // Animation name + UINT NumScaleKeys, // Number of scale keys + UINT NumRotationKeys, // Number of rotation keys + UINT NumTranslationKeys, // Number of translation keys + CONST D3DXKEY_VECTOR3 *pScaleKeys, // Array of scale keys + CONST D3DXKEY_QUATERNION *pRotationKeys, // Array of rotation keys + CONST D3DXKEY_VECTOR3 *pTranslationKeys, // Array of translation keys + DWORD *pAnimationIndex) PURE; // Returns the animation index + + // Compression + STDMETHOD(Compress)(THIS_ + DWORD Flags, // Compression flags (use D3DXCOMPRESS_STRONG for better results) + FLOAT Lossiness, // Compression loss ratio in the [0, 1] range + LPD3DXFRAME pHierarchy, // Frame hierarchy (optional) + LPD3DXBUFFER *ppCompressedData) PURE; // Returns the compressed animation set + + STDMETHOD(UnregisterAnimation)(THIS_ UINT Index) PURE; +}; + + +//---------------------------------------------------------------------------- +// ID3DXCompressedAnimationSet: +// ---------------------------- +// This interface implements a compressed keyframed animation set. +//---------------------------------------------------------------------------- +typedef interface ID3DXCompressedAnimationSet ID3DXCompressedAnimationSet; +typedef interface ID3DXCompressedAnimationSet *LPD3DXCOMPRESSEDANIMATIONSET; + +#undef INTERFACE +#define INTERFACE ID3DXCompressedAnimationSet + +DECLARE_INTERFACE_(ID3DXCompressedAnimationSet, ID3DXAnimationSet) +{ + // ID3DXAnimationSet + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Name + STDMETHOD_(LPCSTR, GetName)(THIS) PURE; + + // Period + STDMETHOD_(DOUBLE, GetPeriod)(THIS) PURE; + STDMETHOD_(DOUBLE, GetPeriodicPosition)(THIS_ DOUBLE Position) PURE; // Maps position into animation period + + // Animation names + STDMETHOD_(UINT, GetNumAnimations)(THIS) PURE; + STDMETHOD(GetAnimationNameByIndex)(THIS_ UINT Index, LPCSTR *ppName) PURE; + STDMETHOD(GetAnimationIndexByName)(THIS_ LPCSTR pName, UINT *pIndex) PURE; + + // SRT + STDMETHOD(GetSRT)(THIS_ + DOUBLE PeriodicPosition, // Position mapped to period (use GetPeriodicPosition) + UINT Animation, // Animation index + D3DXVECTOR3 *pScale, // Returns the scale + D3DXQUATERNION *pRotation, // Returns the rotation as a quaternion + D3DXVECTOR3 *pTranslation) PURE; // Returns the translation + + // Callbacks + STDMETHOD(GetCallback)(THIS_ + DOUBLE Position, // Position from which to find callbacks + DWORD Flags, // Callback search flags + DOUBLE *pCallbackPosition, // Returns the position of the callback + LPVOID *ppCallbackData) PURE; // Returns the callback data pointer + + // Playback + STDMETHOD_(D3DXPLAYBACK_TYPE, GetPlaybackType)(THIS) PURE; + STDMETHOD_(DOUBLE, GetSourceTicksPerSecond)(THIS) PURE; + + // Scale keys + STDMETHOD(GetCompressedData)(THIS_ LPD3DXBUFFER *ppCompressedData) PURE; + + // Callback keys + STDMETHOD_(UINT, GetNumCallbackKeys)(THIS) PURE; + STDMETHOD(GetCallbackKeys)(THIS_ LPD3DXKEY_CALLBACK pCallbackKeys) PURE; +}; + + +//---------------------------------------------------------------------------- +// D3DXPRIORITY_TYPE: +// ------------------ +// This enum defines the type of priority group that a track can be assigned to. +//---------------------------------------------------------------------------- +typedef enum _D3DXPRIORITY_TYPE { + D3DXPRIORITY_LOW = 0, // This track should be blended with all low priority tracks before mixed with the high priority result + D3DXPRIORITY_HIGH = 1, // This track should be blended with all high priority tracks before mixed with the low priority result + + D3DXPRIORITY_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DXPRIORITY_TYPE; + +//---------------------------------------------------------------------------- +// D3DXTRACK_DESC: +// --------------- +// This structure describes the mixing information of an animation track. +// The mixing information consists of the current position, speed, and blending +// weight for the track. The Flags field also specifies whether the track is +// low or high priority. Tracks with the same priority are blended together +// and then the two resulting values are blended using the priority blend factor. +// A track also has an animation set (stored separately) associated with it. +//---------------------------------------------------------------------------- +typedef struct _D3DXTRACK_DESC +{ + D3DXPRIORITY_TYPE Priority; + FLOAT Weight; + FLOAT Speed; + DOUBLE Position; + BOOL Enable; +} D3DXTRACK_DESC, *LPD3DXTRACK_DESC; + +//---------------------------------------------------------------------------- +// D3DXEVENT_TYPE: +// --------------- +// This enum defines the type of events keyable via the animation controller. +//---------------------------------------------------------------------------- +typedef enum _D3DXEVENT_TYPE +{ + D3DXEVENT_TRACKSPEED = 0, + D3DXEVENT_TRACKWEIGHT = 1, + D3DXEVENT_TRACKPOSITION = 2, + D3DXEVENT_TRACKENABLE = 3, + D3DXEVENT_PRIORITYBLEND = 4, + + D3DXEVENT_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DXEVENT_TYPE; + +//---------------------------------------------------------------------------- +// D3DXTRANSITION_TYPE: +// -------------------- +// This enum defines the type of transtion performed on a event that +// transitions from one value to another. +//---------------------------------------------------------------------------- +typedef enum _D3DXTRANSITION_TYPE { + D3DXTRANSITION_LINEAR = 0x000, // Linear transition from one value to the next + D3DXTRANSITION_EASEINEASEOUT = 0x001, // Ease-In Ease-Out spline transtion from one value to the next + + D3DXTRANSITION_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DXTRANSITION_TYPE; + +//---------------------------------------------------------------------------- +// D3DXEVENT_DESC: +// --------------- +// This structure describes a animation controller event. +// It gives the event's type, track (if the event is a track event), global +// start time, duration, transition method, and target value. +//---------------------------------------------------------------------------- +typedef struct _D3DXEVENT_DESC +{ + D3DXEVENT_TYPE Type; + UINT Track; + DOUBLE StartTime; + DOUBLE Duration; + D3DXTRANSITION_TYPE Transition; + union + { + FLOAT Weight; + FLOAT Speed; + DOUBLE Position; + BOOL Enable; + }; +} D3DXEVENT_DESC, *LPD3DXEVENT_DESC; + +//---------------------------------------------------------------------------- +// D3DXEVENTHANDLE: +// ---------------- +// Handle values used to efficiently reference animation controller events. +//---------------------------------------------------------------------------- +typedef DWORD D3DXEVENTHANDLE; +typedef D3DXEVENTHANDLE *LPD3DXEVENTHANDLE; + + +//---------------------------------------------------------------------------- +// ID3DXAnimationCallbackHandler: +// ------------------------------ +// This interface is intended to be implemented by the application, and can +// be used to handle callbacks in animation sets generated when +// ID3DXAnimationController::AdvanceTime() is called. +//---------------------------------------------------------------------------- +typedef interface ID3DXAnimationCallbackHandler ID3DXAnimationCallbackHandler; +typedef interface ID3DXAnimationCallbackHandler *LPD3DXANIMATIONCALLBACKHANDLER; + +#undef INTERFACE +#define INTERFACE ID3DXAnimationCallbackHandler + +DECLARE_INTERFACE(ID3DXAnimationCallbackHandler) +{ + //---------------------------------------------------------------------------- + // ID3DXAnimationCallbackHandler::HandleCallback: + // ---------------------------------------------- + // This method gets called when a callback occurs for an animation set in one + // of the tracks during the ID3DXAnimationController::AdvanceTime() call. + // + // Parameters: + // Track + // Index of the track on which the callback occured. + // pCallbackData + // Pointer to user owned callback data. + // + //---------------------------------------------------------------------------- + STDMETHOD(HandleCallback)(THIS_ UINT Track, LPVOID pCallbackData) PURE; +}; + + +//---------------------------------------------------------------------------- +// ID3DXAnimationController: +// ------------------------- +// This interface implements the main animation functionality. It connects +// animation sets with the transform frames that are being animated. Allows +// mixing multiple animations for blended animations or for transistions +// It adds also has methods to modify blending parameters over time to +// enable smooth transistions and other effects. +//---------------------------------------------------------------------------- +typedef interface ID3DXAnimationController ID3DXAnimationController; +typedef interface ID3DXAnimationController *LPD3DXANIMATIONCONTROLLER; + +#undef INTERFACE +#define INTERFACE ID3DXAnimationController + +DECLARE_INTERFACE_(ID3DXAnimationController, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Max sizes + STDMETHOD_(UINT, GetMaxNumAnimationOutputs)(THIS) PURE; + STDMETHOD_(UINT, GetMaxNumAnimationSets)(THIS) PURE; + STDMETHOD_(UINT, GetMaxNumTracks)(THIS) PURE; + STDMETHOD_(UINT, GetMaxNumEvents)(THIS) PURE; + + // Animation output registration + STDMETHOD(RegisterAnimationOutput)(THIS_ + LPCSTR pName, + D3DXMATRIX *pMatrix, + D3DXVECTOR3 *pScale, + D3DXQUATERNION *pRotation, + D3DXVECTOR3 *pTranslation) PURE; + + // Animation set registration + STDMETHOD(RegisterAnimationSet)(THIS_ LPD3DXANIMATIONSET pAnimSet) PURE; + STDMETHOD(UnregisterAnimationSet)(THIS_ LPD3DXANIMATIONSET pAnimSet) PURE; + + STDMETHOD_(UINT, GetNumAnimationSets)(THIS) PURE; + STDMETHOD(GetAnimationSet)(THIS_ UINT Index, LPD3DXANIMATIONSET *ppAnimationSet) PURE; + STDMETHOD(GetAnimationSetByName)(THIS_ LPCSTR szName, LPD3DXANIMATIONSET *ppAnimationSet) PURE; + + // Global time + STDMETHOD(AdvanceTime)(THIS_ DOUBLE TimeDelta, LPD3DXANIMATIONCALLBACKHANDLER pCallbackHandler) PURE; + STDMETHOD(ResetTime)(THIS) PURE; + STDMETHOD_(DOUBLE, GetTime)(THIS) PURE; + + // Tracks + STDMETHOD(SetTrackAnimationSet)(THIS_ UINT Track, LPD3DXANIMATIONSET pAnimSet) PURE; + STDMETHOD(GetTrackAnimationSet)(THIS_ UINT Track, LPD3DXANIMATIONSET *ppAnimSet) PURE; + + STDMETHOD(SetTrackPriority)(THIS_ UINT Track, D3DXPRIORITY_TYPE Priority) PURE; + + STDMETHOD(SetTrackSpeed)(THIS_ UINT Track, FLOAT Speed) PURE; + STDMETHOD(SetTrackWeight)(THIS_ UINT Track, FLOAT Weight) PURE; + STDMETHOD(SetTrackPosition)(THIS_ UINT Track, DOUBLE Position) PURE; + STDMETHOD(SetTrackEnable)(THIS_ UINT Track, BOOL Enable) PURE; + + STDMETHOD(SetTrackDesc)(THIS_ UINT Track, LPD3DXTRACK_DESC pDesc) PURE; + STDMETHOD(GetTrackDesc)(THIS_ UINT Track, LPD3DXTRACK_DESC pDesc) PURE; + + // Priority blending + STDMETHOD(SetPriorityBlend)(THIS_ FLOAT BlendWeight) PURE; + STDMETHOD_(FLOAT, GetPriorityBlend)(THIS) PURE; + + // Event keying + STDMETHOD_(D3DXEVENTHANDLE, KeyTrackSpeed)(THIS_ UINT Track, FLOAT NewSpeed, DOUBLE StartTime, DOUBLE Duration, D3DXTRANSITION_TYPE Transition) PURE; + STDMETHOD_(D3DXEVENTHANDLE, KeyTrackWeight)(THIS_ UINT Track, FLOAT NewWeight, DOUBLE StartTime, DOUBLE Duration, D3DXTRANSITION_TYPE Transition) PURE; + STDMETHOD_(D3DXEVENTHANDLE, KeyTrackPosition)(THIS_ UINT Track, DOUBLE NewPosition, DOUBLE StartTime) PURE; + STDMETHOD_(D3DXEVENTHANDLE, KeyTrackEnable)(THIS_ UINT Track, BOOL NewEnable, DOUBLE StartTime) PURE; + + STDMETHOD_(D3DXEVENTHANDLE, KeyPriorityBlend)(THIS_ FLOAT NewBlendWeight, DOUBLE StartTime, DOUBLE Duration, D3DXTRANSITION_TYPE Transition) PURE; + + // Event unkeying + STDMETHOD(UnkeyEvent)(THIS_ D3DXEVENTHANDLE hEvent) PURE; + + STDMETHOD(UnkeyAllTrackEvents)(THIS_ UINT Track) PURE; + STDMETHOD(UnkeyAllPriorityBlends)(THIS) PURE; + + // Event enumeration + STDMETHOD_(D3DXEVENTHANDLE, GetCurrentTrackEvent)(THIS_ UINT Track, D3DXEVENT_TYPE EventType) PURE; + STDMETHOD_(D3DXEVENTHANDLE, GetCurrentPriorityBlend)(THIS) PURE; + + STDMETHOD_(D3DXEVENTHANDLE, GetUpcomingTrackEvent)(THIS_ UINT Track, D3DXEVENTHANDLE hEvent) PURE; + STDMETHOD_(D3DXEVENTHANDLE, GetUpcomingPriorityBlend)(THIS_ D3DXEVENTHANDLE hEvent) PURE; + + STDMETHOD(ValidateEvent)(THIS_ D3DXEVENTHANDLE hEvent) PURE; + + STDMETHOD(GetEventDesc)(THIS_ D3DXEVENTHANDLE hEvent, LPD3DXEVENT_DESC pDesc) PURE; + + // Cloning + STDMETHOD(CloneAnimationController)(THIS_ + UINT MaxNumAnimationOutputs, + UINT MaxNumAnimationSets, + UINT MaxNumTracks, + UINT MaxNumEvents, + LPD3DXANIMATIONCONTROLLER *ppAnimController) PURE; +}; + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + +//---------------------------------------------------------------------------- +// D3DXLoadMeshHierarchyFromX: +// --------------------------- +// Loads the first frame hierarchy in a .X file. +// +// Parameters: +// Filename +// Name of the .X file +// MeshOptions +// Mesh creation options for meshes in the file (see d3dx9mesh.h) +// pD3DDevice +// D3D9 device on which meshes in the file are created in +// pAlloc +// Allocation interface used to allocate nodes of the frame hierarchy +// pUserDataLoader +// Application provided interface to allow loading of user data +// ppFrameHierarchy +// Returns root node pointer of the loaded frame hierarchy +// ppAnimController +// Returns pointer to an animation controller corresponding to animation +// in the .X file. This is created with default max tracks and events +// +//---------------------------------------------------------------------------- +HRESULT WINAPI +D3DXLoadMeshHierarchyFromXA + ( + LPCSTR Filename, + DWORD MeshOptions, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXALLOCATEHIERARCHY pAlloc, + LPD3DXLOADUSERDATA pUserDataLoader, + LPD3DXFRAME *ppFrameHierarchy, + LPD3DXANIMATIONCONTROLLER *ppAnimController + ); + +HRESULT WINAPI +D3DXLoadMeshHierarchyFromXW + ( + LPCWSTR Filename, + DWORD MeshOptions, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXALLOCATEHIERARCHY pAlloc, + LPD3DXLOADUSERDATA pUserDataLoader, + LPD3DXFRAME *ppFrameHierarchy, + LPD3DXANIMATIONCONTROLLER *ppAnimController + ); + +#ifdef UNICODE +#define D3DXLoadMeshHierarchyFromX D3DXLoadMeshHierarchyFromXW +#else +#define D3DXLoadMeshHierarchyFromX D3DXLoadMeshHierarchyFromXA +#endif + +HRESULT WINAPI +D3DXLoadMeshHierarchyFromXInMemory + ( + LPCVOID Memory, + DWORD SizeOfMemory, + DWORD MeshOptions, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXALLOCATEHIERARCHY pAlloc, + LPD3DXLOADUSERDATA pUserDataLoader, + LPD3DXFRAME *ppFrameHierarchy, + LPD3DXANIMATIONCONTROLLER *ppAnimController + ); + +//---------------------------------------------------------------------------- +// D3DXSaveMeshHierarchyToFile: +// ---------------------------- +// Creates a .X file and saves the mesh hierarchy and corresponding animations +// in it +// +// Parameters: +// Filename +// Name of the .X file +// XFormat +// Format of the .X file (text or binary, compressed or not, etc) +// pFrameRoot +// Root node of the hierarchy to be saved +// pAnimController +// The animation controller whose animation sets are to be stored +// pUserDataSaver +// Application provided interface to allow adding of user data to +// data objects saved to .X file +// +//---------------------------------------------------------------------------- +HRESULT WINAPI +D3DXSaveMeshHierarchyToFileA + ( + LPCSTR Filename, + DWORD XFormat, + CONST D3DXFRAME *pFrameRoot, + LPD3DXANIMATIONCONTROLLER pAnimcontroller, + LPD3DXSAVEUSERDATA pUserDataSaver + ); + +HRESULT WINAPI +D3DXSaveMeshHierarchyToFileW + ( + LPCWSTR Filename, + DWORD XFormat, + CONST D3DXFRAME *pFrameRoot, + LPD3DXANIMATIONCONTROLLER pAnimController, + LPD3DXSAVEUSERDATA pUserDataSaver + ); + +#ifdef UNICODE +#define D3DXSaveMeshHierarchyToFile D3DXSaveMeshHierarchyToFileW +#else +#define D3DXSaveMeshHierarchyToFile D3DXSaveMeshHierarchyToFileA +#endif + +//---------------------------------------------------------------------------- +// D3DXFrameDestroy: +// ----------------- +// Destroys the subtree of frames under the root, including the root +// +// Parameters: +// pFrameRoot +// Pointer to the root node +// pAlloc +// Allocation interface used to de-allocate nodes of the frame hierarchy +// +//---------------------------------------------------------------------------- +HRESULT WINAPI +D3DXFrameDestroy + ( + LPD3DXFRAME pFrameRoot, + LPD3DXALLOCATEHIERARCHY pAlloc + ); + +//---------------------------------------------------------------------------- +// D3DXFrameAppendChild: +// --------------------- +// Add a child frame to a frame +// +// Parameters: +// pFrameParent +// Pointer to the parent node +// pFrameChild +// Pointer to the child node +// +//---------------------------------------------------------------------------- +HRESULT WINAPI +D3DXFrameAppendChild + ( + LPD3DXFRAME pFrameParent, + CONST D3DXFRAME *pFrameChild + ); + +//---------------------------------------------------------------------------- +// D3DXFrameFind: +// -------------- +// Finds a frame with the given name. Returns NULL if no frame found. +// +// Parameters: +// pFrameRoot +// Pointer to the root node +// Name +// Name of frame to find +// +//---------------------------------------------------------------------------- +LPD3DXFRAME WINAPI +D3DXFrameFind + ( + CONST D3DXFRAME *pFrameRoot, + LPCSTR Name + ); + +//---------------------------------------------------------------------------- +// D3DXFrameRegisterNamedMatrices: +// ------------------------------- +// Finds all frames that have non-null names and registers each of those frame +// matrices to the given animation controller +// +// Parameters: +// pFrameRoot +// Pointer to the root node +// pAnimController +// Pointer to the animation controller where the matrices are registered +// +//---------------------------------------------------------------------------- +HRESULT WINAPI +D3DXFrameRegisterNamedMatrices + ( + LPD3DXFRAME pFrameRoot, + LPD3DXANIMATIONCONTROLLER pAnimController + ); + +//---------------------------------------------------------------------------- +// D3DXFrameNumNamedMatrices: +// -------------------------- +// Counts number of frames in a subtree that have non-null names +// +// Parameters: +// pFrameRoot +// Pointer to the root node of the subtree +// Return Value: +// Count of frames +// +//---------------------------------------------------------------------------- +UINT WINAPI +D3DXFrameNumNamedMatrices + ( + CONST D3DXFRAME *pFrameRoot + ); + +//---------------------------------------------------------------------------- +// D3DXFrameCalculateBoundingSphere: +// --------------------------------- +// Computes the bounding sphere of all the meshes in the frame hierarchy. +// +// Parameters: +// pFrameRoot +// Pointer to the root node +// pObjectCenter +// Returns the center of the bounding sphere +// pObjectRadius +// Returns the radius of the bounding sphere +// +//---------------------------------------------------------------------------- +HRESULT WINAPI +D3DXFrameCalculateBoundingSphere + ( + CONST D3DXFRAME *pFrameRoot, + LPD3DXVECTOR3 pObjectCenter, + FLOAT *pObjectRadius + ); + + +//---------------------------------------------------------------------------- +// D3DXCreateKeyframedAnimationSet: +// -------------------------------- +// This function creates a compressable keyframed animations set interface. +// +// Parameters: +// pName +// Name of the animation set +// TicksPerSecond +// Number of keyframe ticks that elapse per second +// Playback +// Playback mode of keyframe looping +// NumAnimations +// Number of SRT animations +// NumCallbackKeys +// Number of callback keys +// pCallbackKeys +// Array of callback keys +// ppAnimationSet +// Returns the animation set interface +// +//----------------------------------------------------------------------------- +HRESULT WINAPI +D3DXCreateKeyframedAnimationSet + ( + LPCSTR pName, + DOUBLE TicksPerSecond, + D3DXPLAYBACK_TYPE Playback, + UINT NumAnimations, + UINT NumCallbackKeys, + CONST D3DXKEY_CALLBACK *pCallbackKeys, + LPD3DXKEYFRAMEDANIMATIONSET *ppAnimationSet + ); + + +//---------------------------------------------------------------------------- +// D3DXCreateCompressedAnimationSet: +// -------------------------------- +// This function creates a compressed animations set interface from +// compressed data. +// +// Parameters: +// pName +// Name of the animation set +// TicksPerSecond +// Number of keyframe ticks that elapse per second +// Playback +// Playback mode of keyframe looping +// pCompressedData +// Compressed animation SRT data +// NumCallbackKeys +// Number of callback keys +// pCallbackKeys +// Array of callback keys +// ppAnimationSet +// Returns the animation set interface +// +//----------------------------------------------------------------------------- +HRESULT WINAPI +D3DXCreateCompressedAnimationSet + ( + LPCSTR pName, + DOUBLE TicksPerSecond, + D3DXPLAYBACK_TYPE Playback, + LPD3DXBUFFER pCompressedData, + UINT NumCallbackKeys, + CONST D3DXKEY_CALLBACK *pCallbackKeys, + LPD3DXCOMPRESSEDANIMATIONSET *ppAnimationSet + ); + + +//---------------------------------------------------------------------------- +// D3DXCreateAnimationController: +// ------------------------------ +// This function creates an animation controller object. +// +// Parameters: +// MaxNumMatrices +// Maximum number of matrices that can be animated +// MaxNumAnimationSets +// Maximum number of animation sets that can be played +// MaxNumTracks +// Maximum number of animation sets that can be blended +// MaxNumEvents +// Maximum number of outstanding events that can be scheduled at any given time +// ppAnimController +// Returns the animation controller interface +// +//----------------------------------------------------------------------------- +HRESULT WINAPI +D3DXCreateAnimationController + ( + UINT MaxNumMatrices, + UINT MaxNumAnimationSets, + UINT MaxNumTracks, + UINT MaxNumEvents, + LPD3DXANIMATIONCONTROLLER *ppAnimController + ); + + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__D3DX9ANIM_H__ + + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9core.h b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9core.h new file mode 100644 index 0000000000..8c4a685e4a --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9core.h @@ -0,0 +1,755 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9core.h +// Content: D3DX core types and functions +// +/////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9CORE_H__ +#define __D3DX9CORE_H__ + + +/////////////////////////////////////////////////////////////////////////// +// D3DX_SDK_VERSION: +// ----------------- +// This identifier is passed to D3DXCheckVersion in order to ensure that an +// application was built against the correct header files and lib files. +// This number is incremented whenever a header (or other) change would +// require applications to be rebuilt. If the version doesn't match, +// D3DXCheckVersion will return FALSE. (The number itself has no meaning.) +/////////////////////////////////////////////////////////////////////////// + +#define D3DX_VERSION 0x0902 + +#define D3DX_SDK_VERSION 35 + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +BOOL WINAPI + D3DXCheckVersion(UINT D3DSdkVersion, UINT D3DXSdkVersion); + +#ifdef __cplusplus +} +#endif //__cplusplus + + + +/////////////////////////////////////////////////////////////////////////// +// D3DXDebugMute +// Mutes D3DX and D3D debug spew (TRUE - mute, FALSE - not mute) +// +// returns previous mute value +// +/////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +BOOL WINAPI + D3DXDebugMute(BOOL Mute); + +#ifdef __cplusplus +} +#endif //__cplusplus + + +/////////////////////////////////////////////////////////////////////////// +// D3DXGetDriverLevel: +// Returns driver version information: +// +// 700 - DX7 level driver +// 800 - DX8 level driver +// 900 - DX9 level driver +/////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +UINT WINAPI + D3DXGetDriverLevel(LPDIRECT3DDEVICE9 pDevice); + +#ifdef __cplusplus +} +#endif //__cplusplus + + +/////////////////////////////////////////////////////////////////////////// +// ID3DXBuffer: +// ------------ +// The buffer object is used by D3DX to return arbitrary size data. +// +// GetBufferPointer - +// Returns a pointer to the beginning of the buffer. +// +// GetBufferSize - +// Returns the size of the buffer, in bytes. +/////////////////////////////////////////////////////////////////////////// + +typedef interface ID3DXBuffer ID3DXBuffer; +typedef interface ID3DXBuffer *LPD3DXBUFFER; + +// {8BA5FB08-5195-40e2-AC58-0D989C3A0102} +DEFINE_GUID(IID_ID3DXBuffer, +0x8ba5fb08, 0x5195, 0x40e2, 0xac, 0x58, 0xd, 0x98, 0x9c, 0x3a, 0x1, 0x2); + +#undef INTERFACE +#define INTERFACE ID3DXBuffer + +DECLARE_INTERFACE_(ID3DXBuffer, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXBuffer + STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE; + STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE; +}; + + + +////////////////////////////////////////////////////////////////////////////// +// D3DXSPRITE flags: +// ----------------- +// D3DXSPRITE_DONOTSAVESTATE +// Specifies device state is not to be saved and restored in Begin/End. +// D3DXSPRITE_DONOTMODIFY_RENDERSTATE +// Specifies device render state is not to be changed in Begin. The device +// is assumed to be in a valid state to draw vertices containing POSITION0, +// TEXCOORD0, and COLOR0 data. +// D3DXSPRITE_OBJECTSPACE +// The WORLD, VIEW, and PROJECTION transforms are NOT modified. The +// transforms currently set to the device are used to transform the sprites +// when the batch is drawn (at Flush or End). If this is not specified, +// WORLD, VIEW, and PROJECTION transforms are modified so that sprites are +// drawn in screenspace coordinates. +// D3DXSPRITE_BILLBOARD +// Rotates each sprite about its center so that it is facing the viewer. +// D3DXSPRITE_ALPHABLEND +// Enables ALPHABLEND(SRCALPHA, INVSRCALPHA) and ALPHATEST(alpha > 0). +// ID3DXFont expects this to be set when drawing text. +// D3DXSPRITE_SORT_TEXTURE +// Sprites are sorted by texture prior to drawing. This is recommended when +// drawing non-overlapping sprites of uniform depth. For example, drawing +// screen-aligned text with ID3DXFont. +// D3DXSPRITE_SORT_DEPTH_FRONTTOBACK +// Sprites are sorted by depth front-to-back prior to drawing. This is +// recommended when drawing opaque sprites of varying depths. +// D3DXSPRITE_SORT_DEPTH_BACKTOFRONT +// Sprites are sorted by depth back-to-front prior to drawing. This is +// recommended when drawing transparent sprites of varying depths. +// D3DXSPRITE_DO_NOT_ADDREF_TEXTURE +// Disables calling AddRef() on every draw, and Release() on Flush() for +// better performance. +////////////////////////////////////////////////////////////////////////////// + +#define D3DXSPRITE_DONOTSAVESTATE (1 << 0) +#define D3DXSPRITE_DONOTMODIFY_RENDERSTATE (1 << 1) +#define D3DXSPRITE_OBJECTSPACE (1 << 2) +#define D3DXSPRITE_BILLBOARD (1 << 3) +#define D3DXSPRITE_ALPHABLEND (1 << 4) +#define D3DXSPRITE_SORT_TEXTURE (1 << 5) +#define D3DXSPRITE_SORT_DEPTH_FRONTTOBACK (1 << 6) +#define D3DXSPRITE_SORT_DEPTH_BACKTOFRONT (1 << 7) +#define D3DXSPRITE_DO_NOT_ADDREF_TEXTURE (1 << 8) + + +////////////////////////////////////////////////////////////////////////////// +// ID3DXSprite: +// ------------ +// This object intends to provide an easy way to drawing sprites using D3D. +// +// Begin - +// Prepares device for drawing sprites. +// +// Draw - +// Draws a sprite. Before transformation, the sprite is the size of +// SrcRect, with its top-left corner specified by Position. The color +// and alpha channels are modulated by Color. +// +// Flush - +// Forces all batched sprites to submitted to the device. +// +// End - +// Restores device state to how it was when Begin was called. +// +// OnLostDevice, OnResetDevice - +// Call OnLostDevice() on this object before calling Reset() on the +// device, so that this object can release any stateblocks and video +// memory resources. After Reset(), the call OnResetDevice(). +////////////////////////////////////////////////////////////////////////////// + +typedef interface ID3DXSprite ID3DXSprite; +typedef interface ID3DXSprite *LPD3DXSPRITE; + + +// {BA0B762D-7D28-43ec-B9DC-2F84443B0614} +DEFINE_GUID(IID_ID3DXSprite, +0xba0b762d, 0x7d28, 0x43ec, 0xb9, 0xdc, 0x2f, 0x84, 0x44, 0x3b, 0x6, 0x14); + + +#undef INTERFACE +#define INTERFACE ID3DXSprite + +DECLARE_INTERFACE_(ID3DXSprite, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXSprite + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + + STDMETHOD(GetTransform)(THIS_ D3DXMATRIX *pTransform) PURE; + STDMETHOD(SetTransform)(THIS_ CONST D3DXMATRIX *pTransform) PURE; + + STDMETHOD(SetWorldViewRH)(THIS_ CONST D3DXMATRIX *pWorld, CONST D3DXMATRIX *pView) PURE; + STDMETHOD(SetWorldViewLH)(THIS_ CONST D3DXMATRIX *pWorld, CONST D3DXMATRIX *pView) PURE; + + STDMETHOD(Begin)(THIS_ DWORD Flags) PURE; + STDMETHOD(Draw)(THIS_ LPDIRECT3DTEXTURE9 pTexture, CONST RECT *pSrcRect, CONST D3DXVECTOR3 *pCenter, CONST D3DXVECTOR3 *pPosition, D3DCOLOR Color) PURE; + STDMETHOD(Flush)(THIS) PURE; + STDMETHOD(End)(THIS) PURE; + + STDMETHOD(OnLostDevice)(THIS) PURE; + STDMETHOD(OnResetDevice)(THIS) PURE; +}; + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +HRESULT WINAPI + D3DXCreateSprite( + LPDIRECT3DDEVICE9 pDevice, + LPD3DXSPRITE* ppSprite); + +#ifdef __cplusplus +} +#endif //__cplusplus + + + +////////////////////////////////////////////////////////////////////////////// +// ID3DXFont: +// ---------- +// Font objects contain the textures and resources needed to render a specific +// font on a specific device. +// +// GetGlyphData - +// Returns glyph cache data, for a given glyph. +// +// PreloadCharacters/PreloadGlyphs/PreloadText - +// Preloads glyphs into the glyph cache textures. +// +// DrawText - +// Draws formatted text on a D3D device. Some parameters are +// surprisingly similar to those of GDI's DrawText function. See GDI +// documentation for a detailed description of these parameters. +// If pSprite is NULL, an internal sprite object will be used. +// +// OnLostDevice, OnResetDevice - +// Call OnLostDevice() on this object before calling Reset() on the +// device, so that this object can release any stateblocks and video +// memory resources. After Reset(), the call OnResetDevice(). +////////////////////////////////////////////////////////////////////////////// + +typedef struct _D3DXFONT_DESCA +{ + INT Height; + UINT Width; + UINT Weight; + UINT MipLevels; + BOOL Italic; + BYTE CharSet; + BYTE OutputPrecision; + BYTE Quality; + BYTE PitchAndFamily; + CHAR FaceName[LF_FACESIZE]; + +} D3DXFONT_DESCA, *LPD3DXFONT_DESCA; + +typedef struct _D3DXFONT_DESCW +{ + INT Height; + UINT Width; + UINT Weight; + UINT MipLevels; + BOOL Italic; + BYTE CharSet; + BYTE OutputPrecision; + BYTE Quality; + BYTE PitchAndFamily; + WCHAR FaceName[LF_FACESIZE]; + +} D3DXFONT_DESCW, *LPD3DXFONT_DESCW; + +#ifdef UNICODE +typedef D3DXFONT_DESCW D3DXFONT_DESC; +typedef LPD3DXFONT_DESCW LPD3DXFONT_DESC; +#else +typedef D3DXFONT_DESCA D3DXFONT_DESC; +typedef LPD3DXFONT_DESCA LPD3DXFONT_DESC; +#endif + + +typedef interface ID3DXFont ID3DXFont; +typedef interface ID3DXFont *LPD3DXFONT; + + +// {D79DBB70-5F21-4d36-BBC2-FF525C213CDC} +DEFINE_GUID(IID_ID3DXFont, +0xd79dbb70, 0x5f21, 0x4d36, 0xbb, 0xc2, 0xff, 0x52, 0x5c, 0x21, 0x3c, 0xdc); + + +#undef INTERFACE +#define INTERFACE ID3DXFont + +DECLARE_INTERFACE_(ID3DXFont, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXFont + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9 *ppDevice) PURE; + STDMETHOD(GetDescA)(THIS_ D3DXFONT_DESCA *pDesc) PURE; + STDMETHOD(GetDescW)(THIS_ D3DXFONT_DESCW *pDesc) PURE; + STDMETHOD_(BOOL, GetTextMetricsA)(THIS_ TEXTMETRICA *pTextMetrics) PURE; + STDMETHOD_(BOOL, GetTextMetricsW)(THIS_ TEXTMETRICW *pTextMetrics) PURE; + + STDMETHOD_(HDC, GetDC)(THIS) PURE; + STDMETHOD(GetGlyphData)(THIS_ UINT Glyph, LPDIRECT3DTEXTURE9 *ppTexture, RECT *pBlackBox, POINT *pCellInc) PURE; + + STDMETHOD(PreloadCharacters)(THIS_ UINT First, UINT Last) PURE; + STDMETHOD(PreloadGlyphs)(THIS_ UINT First, UINT Last) PURE; + STDMETHOD(PreloadTextA)(THIS_ LPCSTR pString, INT Count) PURE; + STDMETHOD(PreloadTextW)(THIS_ LPCWSTR pString, INT Count) PURE; + + STDMETHOD_(INT, DrawTextA)(THIS_ LPD3DXSPRITE pSprite, LPCSTR pString, INT Count, LPRECT pRect, DWORD Format, D3DCOLOR Color) PURE; + STDMETHOD_(INT, DrawTextW)(THIS_ LPD3DXSPRITE pSprite, LPCWSTR pString, INT Count, LPRECT pRect, DWORD Format, D3DCOLOR Color) PURE; + + STDMETHOD(OnLostDevice)(THIS) PURE; + STDMETHOD(OnResetDevice)(THIS) PURE; + +#ifdef __cplusplus +#ifdef UNICODE + HRESULT GetDesc(D3DXFONT_DESCW *pDesc) { return GetDescW(pDesc); } + HRESULT PreloadText(LPCWSTR pString, INT Count) { return PreloadTextW(pString, Count); } +#else + HRESULT GetDesc(ID3DXFont *font, D3DXFONT_DESCA *pDesc) { + }//return GetDescA(pDesc); } + HRESULT PreloadText(ID3DXFont *font, LPCSTR pString, INT Count) { + }//return PreloadTextA(pString, Count); } +#endif +#endif //__cplusplus +}; + +#ifndef GetTextMetrics +#ifdef UNICODE +#define GetTextMetrics GetTextMetricsW +#else +#define GetTextMetrics GetTextMetricsA +#endif +#endif + +#ifndef DrawText +#ifdef UNICODE +#define DrawText DrawTextW +#else +#define DrawText DrawTextA +#endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + +HRESULT WINAPI + D3DXCreateFontA( + LPDIRECT3DDEVICE9 pDevice, + INT Height, + UINT Width, + UINT Weight, + UINT MipLevels, + BOOL Italic, + DWORD CharSet, + DWORD OutputPrecision, + DWORD Quality, + DWORD PitchAndFamily, + LPCSTR pFaceName, + LPD3DXFONT* ppFont); + +HRESULT WINAPI + D3DXCreateFontW( + LPDIRECT3DDEVICE9 pDevice, + INT Height, + UINT Width, + UINT Weight, + UINT MipLevels, + BOOL Italic, + DWORD CharSet, + DWORD OutputPrecision, + DWORD Quality, + DWORD PitchAndFamily, + LPCWSTR pFaceName, + LPD3DXFONT* ppFont); + +#ifdef UNICODE +#define D3DXCreateFont D3DXCreateFontW +#else +#define D3DXCreateFont D3DXCreateFontA +#endif + + +HRESULT WINAPI + D3DXCreateFontIndirectA( + LPDIRECT3DDEVICE9 pDevice, + CONST D3DXFONT_DESCA* pDesc, + LPD3DXFONT* ppFont); + +HRESULT WINAPI + D3DXCreateFontIndirectW( + LPDIRECT3DDEVICE9 pDevice, + CONST D3DXFONT_DESCW* pDesc, + LPD3DXFONT* ppFont); + +#ifdef UNICODE +#define D3DXCreateFontIndirect D3DXCreateFontIndirectW +#else +#define D3DXCreateFontIndirect D3DXCreateFontIndirectA +#endif + + +#ifdef __cplusplus +} +#endif //__cplusplus + + + +/////////////////////////////////////////////////////////////////////////// +// ID3DXRenderToSurface: +// --------------------- +// This object abstracts rendering to surfaces. These surfaces do not +// necessarily need to be render targets. If they are not, a compatible +// render target is used, and the result copied into surface at end scene. +// +// BeginScene, EndScene - +// Call BeginScene() and EndScene() at the beginning and ending of your +// scene. These calls will setup and restore render targets, viewports, +// etc.. +// +// OnLostDevice, OnResetDevice - +// Call OnLostDevice() on this object before calling Reset() on the +// device, so that this object can release any stateblocks and video +// memory resources. After Reset(), the call OnResetDevice(). +/////////////////////////////////////////////////////////////////////////// + +typedef struct _D3DXRTS_DESC +{ + UINT Width; + UINT Height; + D3DFORMAT Format; + BOOL DepthStencil; + D3DFORMAT DepthStencilFormat; + +} D3DXRTS_DESC, *LPD3DXRTS_DESC; + + +typedef interface ID3DXRenderToSurface ID3DXRenderToSurface; +typedef interface ID3DXRenderToSurface *LPD3DXRENDERTOSURFACE; + + +// {6985F346-2C3D-43b3-BE8B-DAAE8A03D894} +DEFINE_GUID(IID_ID3DXRenderToSurface, +0x6985f346, 0x2c3d, 0x43b3, 0xbe, 0x8b, 0xda, 0xae, 0x8a, 0x3, 0xd8, 0x94); + + +#undef INTERFACE +#define INTERFACE ID3DXRenderToSurface + +DECLARE_INTERFACE_(ID3DXRenderToSurface, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXRenderToSurface + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(GetDesc)(THIS_ D3DXRTS_DESC* pDesc) PURE; + + STDMETHOD(BeginScene)(THIS_ LPDIRECT3DSURFACE9 pSurface, CONST D3DVIEWPORT9* pViewport) PURE; + STDMETHOD(EndScene)(THIS_ DWORD MipFilter) PURE; + + STDMETHOD(OnLostDevice)(THIS) PURE; + STDMETHOD(OnResetDevice)(THIS) PURE; +}; + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +HRESULT WINAPI + D3DXCreateRenderToSurface( + LPDIRECT3DDEVICE9 pDevice, + UINT Width, + UINT Height, + D3DFORMAT Format, + BOOL DepthStencil, + D3DFORMAT DepthStencilFormat, + LPD3DXRENDERTOSURFACE* ppRenderToSurface); + +#ifdef __cplusplus +} +#endif //__cplusplus + + + +/////////////////////////////////////////////////////////////////////////// +// ID3DXRenderToEnvMap: +// -------------------- +// This object abstracts rendering to environment maps. These surfaces +// do not necessarily need to be render targets. If they are not, a +// compatible render target is used, and the result copied into the +// environment map at end scene. +// +// BeginCube, BeginSphere, BeginHemisphere, BeginParabolic - +// This function initiates the rendering of the environment map. As +// parameters, you pass the textures in which will get filled in with +// the resulting environment map. +// +// Face - +// Call this function to initiate the drawing of each face. For each +// environment map, you will call this six times.. once for each face +// in D3DCUBEMAP_FACES. +// +// End - +// This will restore all render targets, and if needed compose all the +// rendered faces into the environment map surfaces. +// +// OnLostDevice, OnResetDevice - +// Call OnLostDevice() on this object before calling Reset() on the +// device, so that this object can release any stateblocks and video +// memory resources. After Reset(), the call OnResetDevice(). +/////////////////////////////////////////////////////////////////////////// + +typedef struct _D3DXRTE_DESC +{ + UINT Size; + UINT MipLevels; + D3DFORMAT Format; + BOOL DepthStencil; + D3DFORMAT DepthStencilFormat; + +} D3DXRTE_DESC, *LPD3DXRTE_DESC; + + +typedef interface ID3DXRenderToEnvMap ID3DXRenderToEnvMap; +typedef interface ID3DXRenderToEnvMap *LPD3DXRenderToEnvMap; + + +// {313F1B4B-C7B0-4fa2-9D9D-8D380B64385E} +DEFINE_GUID(IID_ID3DXRenderToEnvMap, +0x313f1b4b, 0xc7b0, 0x4fa2, 0x9d, 0x9d, 0x8d, 0x38, 0xb, 0x64, 0x38, 0x5e); + + +#undef INTERFACE +#define INTERFACE ID3DXRenderToEnvMap + +DECLARE_INTERFACE_(ID3DXRenderToEnvMap, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXRenderToEnvMap + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(GetDesc)(THIS_ D3DXRTE_DESC* pDesc) PURE; + + STDMETHOD(BeginCube)(THIS_ + LPDIRECT3DCUBETEXTURE9 pCubeTex) PURE; + + STDMETHOD(BeginSphere)(THIS_ + LPDIRECT3DTEXTURE9 pTex) PURE; + + STDMETHOD(BeginHemisphere)(THIS_ + LPDIRECT3DTEXTURE9 pTexZPos, + LPDIRECT3DTEXTURE9 pTexZNeg) PURE; + + STDMETHOD(BeginParabolic)(THIS_ + LPDIRECT3DTEXTURE9 pTexZPos, + LPDIRECT3DTEXTURE9 pTexZNeg) PURE; + + STDMETHOD(Face)(THIS_ D3DCUBEMAP_FACES Face, DWORD MipFilter) PURE; + STDMETHOD(End)(THIS_ DWORD MipFilter) PURE; + + STDMETHOD(OnLostDevice)(THIS) PURE; + STDMETHOD(OnResetDevice)(THIS) PURE; +}; + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +HRESULT WINAPI + D3DXCreateRenderToEnvMap( + LPDIRECT3DDEVICE9 pDevice, + UINT Size, + UINT MipLevels, + D3DFORMAT Format, + BOOL DepthStencil, + D3DFORMAT DepthStencilFormat, + LPD3DXRenderToEnvMap* ppRenderToEnvMap); + +#ifdef __cplusplus +} +#endif //__cplusplus + + + +/////////////////////////////////////////////////////////////////////////// +// ID3DXLine: +// ------------ +// This object intends to provide an easy way to draw lines using D3D. +// +// Begin - +// Prepares device for drawing lines +// +// Draw - +// Draws a line strip in screen-space. +// Input is in the form of a array defining points on the line strip. of D3DXVECTOR2 +// +// DrawTransform - +// Draws a line in screen-space with a specified input transformation matrix. +// +// End - +// Restores device state to how it was when Begin was called. +// +// SetPattern - +// Applies a stipple pattern to the line. Input is one 32-bit +// DWORD which describes the stipple pattern. 1 is opaque, 0 is +// transparent. +// +// SetPatternScale - +// Stretches the stipple pattern in the u direction. Input is one +// floating-point value. 0.0f is no scaling, whereas 1.0f doubles +// the length of the stipple pattern. +// +// SetWidth - +// Specifies the thickness of the line in the v direction. Input is +// one floating-point value. +// +// SetAntialias - +// Toggles line antialiasing. Input is a BOOL. +// TRUE = Antialiasing on. +// FALSE = Antialiasing off. +// +// SetGLLines - +// Toggles non-antialiased OpenGL line emulation. Input is a BOOL. +// TRUE = OpenGL line emulation on. +// FALSE = OpenGL line emulation off. +// +// OpenGL line: Regular line: +// *\ *\ +// | \ / \ +// | \ *\ \ +// *\ \ \ \ +// \ \ \ \ +// \ * \ * +// \ | \ / +// \| * +// * +// +// OnLostDevice, OnResetDevice - +// Call OnLostDevice() on this object before calling Reset() on the +// device, so that this object can release any stateblocks and video +// memory resources. After Reset(), the call OnResetDevice(). +/////////////////////////////////////////////////////////////////////////// + + +typedef interface ID3DXLine ID3DXLine; +typedef interface ID3DXLine *LPD3DXLINE; + + +// {D379BA7F-9042-4ac4-9F5E-58192A4C6BD8} +DEFINE_GUID(IID_ID3DXLine, +0xd379ba7f, 0x9042, 0x4ac4, 0x9f, 0x5e, 0x58, 0x19, 0x2a, 0x4c, 0x6b, 0xd8); + +#undef INTERFACE +#define INTERFACE ID3DXLine + +DECLARE_INTERFACE_(ID3DXLine, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXLine + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + + STDMETHOD(Begin)(THIS) PURE; + + STDMETHOD(Draw)(THIS_ CONST D3DXVECTOR2 *pVertexList, + DWORD dwVertexListCount, D3DCOLOR Color) PURE; + + STDMETHOD(DrawTransform)(THIS_ CONST D3DXVECTOR3 *pVertexList, + DWORD dwVertexListCount, CONST D3DXMATRIX* pTransform, + D3DCOLOR Color) PURE; + + STDMETHOD(SetPattern)(THIS_ DWORD dwPattern) PURE; + STDMETHOD_(DWORD, GetPattern)(THIS) PURE; + + STDMETHOD(SetPatternScale)(THIS_ FLOAT fPatternScale) PURE; + STDMETHOD_(FLOAT, GetPatternScale)(THIS) PURE; + + STDMETHOD(SetWidth)(THIS_ FLOAT fWidth) PURE; + STDMETHOD_(FLOAT, GetWidth)(THIS) PURE; + + STDMETHOD(SetAntialias)(THIS_ BOOL bAntialias) PURE; + STDMETHOD_(BOOL, GetAntialias)(THIS) PURE; + + STDMETHOD(SetGLLines)(THIS_ BOOL bGLLines) PURE; + STDMETHOD_(BOOL, GetGLLines)(THIS) PURE; + + STDMETHOD(End)(THIS) PURE; + + STDMETHOD(OnLostDevice)(THIS) PURE; + STDMETHOD(OnResetDevice)(THIS) PURE; +}; + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + +HRESULT WINAPI + D3DXCreateLine( + LPDIRECT3DDEVICE9 pDevice, + LPD3DXLINE* ppLine); + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__D3DX9CORE_H__ + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9effect.h b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9effect.h new file mode 100644 index 0000000000..a3bcd307c6 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9effect.h @@ -0,0 +1,873 @@ + +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// File: d3dx9effect.h +// Content: D3DX effect types and Shaders +// +////////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9EFFECT_H__ +#define __D3DX9EFFECT_H__ + + +//---------------------------------------------------------------------------- +// D3DXFX_DONOTSAVESTATE +// This flag is used as a parameter to ID3DXEffect::Begin(). When this flag +// is specified, device state is not saved or restored in Begin/End. +// D3DXFX_DONOTSAVESHADERSTATE +// This flag is used as a parameter to ID3DXEffect::Begin(). When this flag +// is specified, shader device state is not saved or restored in Begin/End. +// This includes pixel/vertex shaders and shader constants +// D3DXFX_DONOTSAVESAMPLERSTATE +// This flag is used as a parameter to ID3DXEffect::Begin(). When this flag +// is specified, sampler device state is not saved or restored in Begin/End. +// D3DXFX_NOT_CLONEABLE +// This flag is used as a parameter to the D3DXCreateEffect family of APIs. +// When this flag is specified, the effect will be non-cloneable and will not +// contain any shader binary data. +// Furthermore, GetPassDesc will not return shader function pointers. +// Setting this flag reduces effect memory usage by about 50%. +//---------------------------------------------------------------------------- + +#define D3DXFX_DONOTSAVESTATE (1 << 0) +#define D3DXFX_DONOTSAVESHADERSTATE (1 << 1) +#define D3DXFX_DONOTSAVESAMPLERSTATE (1 << 2) + +#define D3DXFX_NOT_CLONEABLE (1 << 11) +#define D3DXFX_LARGEADDRESSAWARE (1 << 17) + +//---------------------------------------------------------------------------- +// D3DX_PARAMETER_SHARED +// Indicates that the value of a parameter will be shared with all effects +// which share the same namespace. Changing the value in one effect will +// change it in all. +// +// D3DX_PARAMETER_LITERAL +// Indicates that the value of this parameter can be treated as literal. +// Literal parameters can be marked when the effect is compiled, and their +// cannot be changed after the effect is compiled. Shared parameters cannot +// be literal. +//---------------------------------------------------------------------------- + +#define D3DX_PARAMETER_SHARED (1 << 0) +#define D3DX_PARAMETER_LITERAL (1 << 1) +#define D3DX_PARAMETER_ANNOTATION (1 << 2) + +//---------------------------------------------------------------------------- +// D3DXEFFECT_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXEFFECT_DESC +{ + LPCSTR Creator; // Creator string + UINT Parameters; // Number of parameters + UINT Techniques; // Number of techniques + UINT Functions; // Number of function entrypoints + +} D3DXEFFECT_DESC; + + +//---------------------------------------------------------------------------- +// D3DXPARAMETER_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXPARAMETER_DESC +{ + LPCSTR Name; // Parameter name + LPCSTR Semantic; // Parameter semantic + D3DXPARAMETER_CLASS Class; // Class + D3DXPARAMETER_TYPE Type; // Component type + UINT Rows; // Number of rows + UINT Columns; // Number of columns + UINT Elements; // Number of array elements + UINT Annotations; // Number of annotations + UINT StructMembers; // Number of structure member sub-parameters + DWORD Flags; // D3DX_PARAMETER_* flags + UINT Bytes; // Parameter size, in bytes + +} D3DXPARAMETER_DESC; + + +//---------------------------------------------------------------------------- +// D3DXTECHNIQUE_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXTECHNIQUE_DESC +{ + LPCSTR Name; // Technique name + UINT Passes; // Number of passes + UINT Annotations; // Number of annotations + +} D3DXTECHNIQUE_DESC; + + +//---------------------------------------------------------------------------- +// D3DXPASS_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXPASS_DESC +{ + LPCSTR Name; // Pass name + UINT Annotations; // Number of annotations + + CONST DWORD *pVertexShaderFunction; // Vertex shader function + CONST DWORD *pPixelShaderFunction; // Pixel shader function + +} D3DXPASS_DESC; + + +//---------------------------------------------------------------------------- +// D3DXFUNCTION_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXFUNCTION_DESC +{ + LPCSTR Name; // Function name + UINT Annotations; // Number of annotations + +} D3DXFUNCTION_DESC; + + + +////////////////////////////////////////////////////////////////////////////// +// ID3DXEffectPool /////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +typedef interface ID3DXEffectPool ID3DXEffectPool; +typedef interface ID3DXEffectPool *LPD3DXEFFECTPOOL; + +// {9537AB04-3250-412e-8213-FCD2F8677933} +DEFINE_GUID(IID_ID3DXEffectPool, +0x9537ab04, 0x3250, 0x412e, 0x82, 0x13, 0xfc, 0xd2, 0xf8, 0x67, 0x79, 0x33); + + +#undef INTERFACE +#define INTERFACE ID3DXEffectPool + +DECLARE_INTERFACE_(ID3DXEffectPool, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // No public methods +}; + + +////////////////////////////////////////////////////////////////////////////// +// ID3DXBaseEffect /////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +typedef interface ID3DXBaseEffect ID3DXBaseEffect; +typedef interface ID3DXBaseEffect *LPD3DXBASEEFFECT; + +// {017C18AC-103F-4417-8C51-6BF6EF1E56BE} +DEFINE_GUID(IID_ID3DXBaseEffect, +0x17c18ac, 0x103f, 0x4417, 0x8c, 0x51, 0x6b, 0xf6, 0xef, 0x1e, 0x56, 0xbe); + + +#undef INTERFACE +#define INTERFACE ID3DXBaseEffect + +DECLARE_INTERFACE_(ID3DXBaseEffect, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Descs + STDMETHOD(GetDesc)(THIS_ D3DXEFFECT_DESC* pDesc) PURE; + STDMETHOD(GetParameterDesc)(THIS_ D3DXHANDLE hParameter, D3DXPARAMETER_DESC* pDesc) PURE; + STDMETHOD(GetTechniqueDesc)(THIS_ D3DXHANDLE hTechnique, D3DXTECHNIQUE_DESC* pDesc) PURE; + STDMETHOD(GetPassDesc)(THIS_ D3DXHANDLE hPass, D3DXPASS_DESC* pDesc) PURE; + STDMETHOD(GetFunctionDesc)(THIS_ D3DXHANDLE hShader, D3DXFUNCTION_DESC* pDesc) PURE; + + // Handle operations + STDMETHOD_(D3DXHANDLE, GetParameter)(THIS_ D3DXHANDLE hParameter, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterByName)(THIS_ D3DXHANDLE hParameter, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterBySemantic)(THIS_ D3DXHANDLE hParameter, LPCSTR pSemantic) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterElement)(THIS_ D3DXHANDLE hParameter, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetTechnique)(THIS_ UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetTechniqueByName)(THIS_ LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetPass)(THIS_ D3DXHANDLE hTechnique, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetPassByName)(THIS_ D3DXHANDLE hTechnique, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetFunction)(THIS_ UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetFunctionByName)(THIS_ LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetAnnotation)(THIS_ D3DXHANDLE hObject, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetAnnotationByName)(THIS_ D3DXHANDLE hObject, LPCSTR pName) PURE; + + // Get/Set Parameters + STDMETHOD(SetValue)(THIS_ D3DXHANDLE hParameter, LPCVOID pData, UINT Bytes) PURE; + STDMETHOD(GetValue)(THIS_ D3DXHANDLE hParameter, LPVOID pData, UINT Bytes) PURE; + STDMETHOD(SetBool)(THIS_ D3DXHANDLE hParameter, BOOL b) PURE; + STDMETHOD(GetBool)(THIS_ D3DXHANDLE hParameter, BOOL* pb) PURE; + STDMETHOD(SetBoolArray)(THIS_ D3DXHANDLE hParameter, CONST BOOL* pb, UINT Count) PURE; + STDMETHOD(GetBoolArray)(THIS_ D3DXHANDLE hParameter, BOOL* pb, UINT Count) PURE; + STDMETHOD(SetInt)(THIS_ D3DXHANDLE hParameter, INT n) PURE; + STDMETHOD(GetInt)(THIS_ D3DXHANDLE hParameter, INT* pn) PURE; + STDMETHOD(SetIntArray)(THIS_ D3DXHANDLE hParameter, CONST INT* pn, UINT Count) PURE; + STDMETHOD(GetIntArray)(THIS_ D3DXHANDLE hParameter, INT* pn, UINT Count) PURE; + STDMETHOD(SetFloat)(THIS_ D3DXHANDLE hParameter, FLOAT f) PURE; + STDMETHOD(GetFloat)(THIS_ D3DXHANDLE hParameter, FLOAT* pf) PURE; + STDMETHOD(SetFloatArray)(THIS_ D3DXHANDLE hParameter, CONST FLOAT* pf, UINT Count) PURE; + STDMETHOD(GetFloatArray)(THIS_ D3DXHANDLE hParameter, FLOAT* pf, UINT Count) PURE; + STDMETHOD(SetVector)(THIS_ D3DXHANDLE hParameter, CONST D3DXVECTOR4* pVector) PURE; + STDMETHOD(GetVector)(THIS_ D3DXHANDLE hParameter, D3DXVECTOR4* pVector) PURE; + STDMETHOD(SetVectorArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(GetVectorArray)(THIS_ D3DXHANDLE hParameter, D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(SetMatrix)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(GetMatrix)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixPointerArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixPointerArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTranspose)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(GetMatrixTranspose)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixTransposeArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixTransposeArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetString)(THIS_ D3DXHANDLE hParameter, LPCSTR pString) PURE; + STDMETHOD(GetString)(THIS_ D3DXHANDLE hParameter, LPCSTR* ppString) PURE; + STDMETHOD(SetTexture)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DBASETEXTURE9 pTexture) PURE; + STDMETHOD(GetTexture)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DBASETEXTURE9 *ppTexture) PURE; + STDMETHOD(GetPixelShader)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DPIXELSHADER9 *ppPShader) PURE; + STDMETHOD(GetVertexShader)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DVERTEXSHADER9 *ppVShader) PURE; + + //Set Range of an Array to pass to device + //Useful for sending only a subrange of an array down to the device + STDMETHOD(SetArrayRange)(THIS_ D3DXHANDLE hParameter, UINT uStart, UINT uEnd) PURE; + +}; + + +//---------------------------------------------------------------------------- +// ID3DXEffectStateManager: +// ------------------------ +// This is a user implemented interface that can be used to manage device +// state changes made by an Effect. +//---------------------------------------------------------------------------- + +typedef interface ID3DXEffectStateManager ID3DXEffectStateManager; +typedef interface ID3DXEffectStateManager *LPD3DXEFFECTSTATEMANAGER; + +// {79AAB587-6DBC-4fa7-82DE-37FA1781C5CE} +DEFINE_GUID(IID_ID3DXEffectStateManager, +0x79aab587, 0x6dbc, 0x4fa7, 0x82, 0xde, 0x37, 0xfa, 0x17, 0x81, 0xc5, 0xce); + +#undef INTERFACE +#define INTERFACE ID3DXEffectStateManager + +DECLARE_INTERFACE_(ID3DXEffectStateManager, IUnknown) +{ + // The user must correctly implement QueryInterface, AddRef, and Release. + + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // The following methods are called by the Effect when it wants to make + // the corresponding device call. Note that: + // 1. Users manage the state and are therefore responsible for making the + // the corresponding device calls themselves inside their callbacks. + // 2. Effects pay attention to the return values of the callbacks, and so + // users must pay attention to what they return in their callbacks. + + STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX *pMatrix) PURE; + STDMETHOD(SetMaterial)(THIS_ CONST D3DMATERIAL9 *pMaterial) PURE; + STDMETHOD(SetLight)(THIS_ DWORD Index, CONST D3DLIGHT9 *pLight) PURE; + STDMETHOD(LightEnable)(THIS_ DWORD Index, BOOL Enable) PURE; + STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE State, DWORD Value) PURE; + STDMETHOD(SetTexture)(THIS_ DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture) PURE; + STDMETHOD(SetTextureStageState)(THIS_ DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) PURE; + STDMETHOD(SetSamplerState)(THIS_ DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) PURE; + STDMETHOD(SetNPatchMode)(THIS_ FLOAT NumSegments) PURE; + STDMETHOD(SetFVF)(THIS_ DWORD FVF) PURE; + STDMETHOD(SetVertexShader)(THIS_ LPDIRECT3DVERTEXSHADER9 pShader) PURE; + STDMETHOD(SetVertexShaderConstantF)(THIS_ UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount) PURE; + STDMETHOD(SetVertexShaderConstantI)(THIS_ UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount) PURE; + STDMETHOD(SetVertexShaderConstantB)(THIS_ UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount) PURE; + STDMETHOD(SetPixelShader)(THIS_ LPDIRECT3DPIXELSHADER9 pShader) PURE; + STDMETHOD(SetPixelShaderConstantF)(THIS_ UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount) PURE; + STDMETHOD(SetPixelShaderConstantI)(THIS_ UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount) PURE; + STDMETHOD(SetPixelShaderConstantB)(THIS_ UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount) PURE; +}; + + +////////////////////////////////////////////////////////////////////////////// +// ID3DXEffect /////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +typedef interface ID3DXEffect ID3DXEffect; +typedef interface ID3DXEffect *LPD3DXEFFECT; + +// {F6CEB4B3-4E4C-40dd-B883-8D8DE5EA0CD5} +DEFINE_GUID(IID_ID3DXEffect, +0xf6ceb4b3, 0x4e4c, 0x40dd, 0xb8, 0x83, 0x8d, 0x8d, 0xe5, 0xea, 0xc, 0xd5); + +#undef INTERFACE +#define INTERFACE ID3DXEffect + +DECLARE_INTERFACE_(ID3DXEffect, ID3DXBaseEffect) +{ + // ID3DXBaseEffect + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Descs + STDMETHOD(GetDesc)(THIS_ D3DXEFFECT_DESC* pDesc) PURE; + STDMETHOD(GetParameterDesc)(THIS_ D3DXHANDLE hParameter, D3DXPARAMETER_DESC* pDesc) PURE; + STDMETHOD(GetTechniqueDesc)(THIS_ D3DXHANDLE hTechnique, D3DXTECHNIQUE_DESC* pDesc) PURE; + STDMETHOD(GetPassDesc)(THIS_ D3DXHANDLE hPass, D3DXPASS_DESC* pDesc) PURE; + STDMETHOD(GetFunctionDesc)(THIS_ D3DXHANDLE hShader, D3DXFUNCTION_DESC* pDesc) PURE; + + // Handle operations + STDMETHOD_(D3DXHANDLE, GetParameter)(THIS_ D3DXHANDLE hParameter, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterByName)(THIS_ D3DXHANDLE hParameter, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterBySemantic)(THIS_ D3DXHANDLE hParameter, LPCSTR pSemantic) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterElement)(THIS_ D3DXHANDLE hParameter, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetTechnique)(THIS_ UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetTechniqueByName)(THIS_ LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetPass)(THIS_ D3DXHANDLE hTechnique, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetPassByName)(THIS_ D3DXHANDLE hTechnique, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetFunction)(THIS_ UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetFunctionByName)(THIS_ LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetAnnotation)(THIS_ D3DXHANDLE hObject, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetAnnotationByName)(THIS_ D3DXHANDLE hObject, LPCSTR pName) PURE; + + // Get/Set Parameters + STDMETHOD(SetValue)(THIS_ D3DXHANDLE hParameter, LPCVOID pData, UINT Bytes) PURE; + STDMETHOD(GetValue)(THIS_ D3DXHANDLE hParameter, LPVOID pData, UINT Bytes) PURE; + STDMETHOD(SetBool)(THIS_ D3DXHANDLE hParameter, BOOL b) PURE; + STDMETHOD(GetBool)(THIS_ D3DXHANDLE hParameter, BOOL* pb) PURE; + STDMETHOD(SetBoolArray)(THIS_ D3DXHANDLE hParameter, CONST BOOL* pb, UINT Count) PURE; + STDMETHOD(GetBoolArray)(THIS_ D3DXHANDLE hParameter, BOOL* pb, UINT Count) PURE; + STDMETHOD(SetInt)(THIS_ D3DXHANDLE hParameter, INT n) PURE; + STDMETHOD(GetInt)(THIS_ D3DXHANDLE hParameter, INT* pn) PURE; + STDMETHOD(SetIntArray)(THIS_ D3DXHANDLE hParameter, CONST INT* pn, UINT Count) PURE; + STDMETHOD(GetIntArray)(THIS_ D3DXHANDLE hParameter, INT* pn, UINT Count) PURE; + STDMETHOD(SetFloat)(THIS_ D3DXHANDLE hParameter, FLOAT f) PURE; + STDMETHOD(GetFloat)(THIS_ D3DXHANDLE hParameter, FLOAT* pf) PURE; + STDMETHOD(SetFloatArray)(THIS_ D3DXHANDLE hParameter, CONST FLOAT* pf, UINT Count) PURE; + STDMETHOD(GetFloatArray)(THIS_ D3DXHANDLE hParameter, FLOAT* pf, UINT Count) PURE; + STDMETHOD(SetVector)(THIS_ D3DXHANDLE hParameter, CONST D3DXVECTOR4* pVector) PURE; + STDMETHOD(GetVector)(THIS_ D3DXHANDLE hParameter, D3DXVECTOR4* pVector) PURE; + STDMETHOD(SetVectorArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(GetVectorArray)(THIS_ D3DXHANDLE hParameter, D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(SetMatrix)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(GetMatrix)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixPointerArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixPointerArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTranspose)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(GetMatrixTranspose)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixTransposeArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixTransposeArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetString)(THIS_ D3DXHANDLE hParameter, LPCSTR pString) PURE; + STDMETHOD(GetString)(THIS_ D3DXHANDLE hParameter, LPCSTR* ppString) PURE; + STDMETHOD(SetTexture)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DBASETEXTURE9 pTexture) PURE; + STDMETHOD(GetTexture)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DBASETEXTURE9 *ppTexture) PURE; + STDMETHOD(GetPixelShader)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DPIXELSHADER9 *ppPShader) PURE; + STDMETHOD(GetVertexShader)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DVERTEXSHADER9 *ppVShader) PURE; + + //Set Range of an Array to pass to device + //Usefull for sending only a subrange of an array down to the device + STDMETHOD(SetArrayRange)(THIS_ D3DXHANDLE hParameter, UINT uStart, UINT uEnd) PURE; + // ID3DXBaseEffect + + + // Pool + STDMETHOD(GetPool)(THIS_ LPD3DXEFFECTPOOL* ppPool) PURE; + + // Selecting and setting a technique + STDMETHOD(SetTechnique)(THIS_ D3DXHANDLE hTechnique) PURE; + STDMETHOD_(D3DXHANDLE, GetCurrentTechnique)(THIS) PURE; + STDMETHOD(ValidateTechnique)(THIS_ D3DXHANDLE hTechnique) PURE; + STDMETHOD(FindNextValidTechnique)(THIS_ D3DXHANDLE hTechnique, D3DXHANDLE *pTechnique) PURE; + STDMETHOD_(BOOL, IsParameterUsed)(THIS_ D3DXHANDLE hParameter, D3DXHANDLE hTechnique) PURE; + + // Using current technique + // Begin starts active technique + // BeginPass begins a pass + // CommitChanges updates changes to any set calls in the pass. This should be called before + // any DrawPrimitive call to d3d + // EndPass ends a pass + // End ends active technique + STDMETHOD(Begin)(THIS_ UINT *pPasses, DWORD Flags) PURE; + STDMETHOD(BeginPass)(THIS_ UINT Pass) PURE; + STDMETHOD(CommitChanges)(THIS) PURE; + STDMETHOD(EndPass)(THIS) PURE; + STDMETHOD(End)(THIS) PURE; + + // Managing D3D Device + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(OnLostDevice)(THIS) PURE; + STDMETHOD(OnResetDevice)(THIS) PURE; + + // Logging device calls + STDMETHOD(SetStateManager)(THIS_ LPD3DXEFFECTSTATEMANAGER pManager) PURE; + STDMETHOD(GetStateManager)(THIS_ LPD3DXEFFECTSTATEMANAGER *ppManager) PURE; + + // Parameter blocks + STDMETHOD(BeginParameterBlock)(THIS) PURE; + STDMETHOD_(D3DXHANDLE, EndParameterBlock)(THIS) PURE; + STDMETHOD(ApplyParameterBlock)(THIS_ D3DXHANDLE hParameterBlock) PURE; + STDMETHOD(DeleteParameterBlock)(THIS_ D3DXHANDLE hParameterBlock) PURE; + + // Cloning + STDMETHOD(CloneEffect)(THIS_ LPDIRECT3DDEVICE9 pDevice, LPD3DXEFFECT* ppEffect) PURE; + + // Fast path for setting variables directly in ID3DXEffect + STDMETHOD(SetRawValue)(THIS_ D3DXHANDLE hParameter, LPCVOID pData, UINT ByteOffset, UINT Bytes) PURE; +}; + + +////////////////////////////////////////////////////////////////////////////// +// ID3DXEffectCompiler /////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +typedef interface ID3DXEffectCompiler ID3DXEffectCompiler; +typedef interface ID3DXEffectCompiler *LPD3DXEFFECTCOMPILER; + +// {51B8A949-1A31-47e6-BEA0-4B30DB53F1E0} +DEFINE_GUID(IID_ID3DXEffectCompiler, +0x51b8a949, 0x1a31, 0x47e6, 0xbe, 0xa0, 0x4b, 0x30, 0xdb, 0x53, 0xf1, 0xe0); + + +#undef INTERFACE +#define INTERFACE ID3DXEffectCompiler + +DECLARE_INTERFACE_(ID3DXEffectCompiler, ID3DXBaseEffect) +{ + // ID3DXBaseEffect + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Descs + STDMETHOD(GetDesc)(THIS_ D3DXEFFECT_DESC* pDesc) PURE; + STDMETHOD(GetParameterDesc)(THIS_ D3DXHANDLE hParameter, D3DXPARAMETER_DESC* pDesc) PURE; + STDMETHOD(GetTechniqueDesc)(THIS_ D3DXHANDLE hTechnique, D3DXTECHNIQUE_DESC* pDesc) PURE; + STDMETHOD(GetPassDesc)(THIS_ D3DXHANDLE hPass, D3DXPASS_DESC* pDesc) PURE; + STDMETHOD(GetFunctionDesc)(THIS_ D3DXHANDLE hShader, D3DXFUNCTION_DESC* pDesc) PURE; + + // Handle operations + STDMETHOD_(D3DXHANDLE, GetParameter)(THIS_ D3DXHANDLE hParameter, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterByName)(THIS_ D3DXHANDLE hParameter, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterBySemantic)(THIS_ D3DXHANDLE hParameter, LPCSTR pSemantic) PURE; + STDMETHOD_(D3DXHANDLE, GetParameterElement)(THIS_ D3DXHANDLE hParameter, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetTechnique)(THIS_ UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetTechniqueByName)(THIS_ LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetPass)(THIS_ D3DXHANDLE hTechnique, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetPassByName)(THIS_ D3DXHANDLE hTechnique, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetFunction)(THIS_ UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetFunctionByName)(THIS_ LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetAnnotation)(THIS_ D3DXHANDLE hObject, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetAnnotationByName)(THIS_ D3DXHANDLE hObject, LPCSTR pName) PURE; + + // Get/Set Parameters + STDMETHOD(SetValue)(THIS_ D3DXHANDLE hParameter, LPCVOID pData, UINT Bytes) PURE; + STDMETHOD(GetValue)(THIS_ D3DXHANDLE hParameter, LPVOID pData, UINT Bytes) PURE; + STDMETHOD(SetBool)(THIS_ D3DXHANDLE hParameter, BOOL b) PURE; + STDMETHOD(GetBool)(THIS_ D3DXHANDLE hParameter, BOOL* pb) PURE; + STDMETHOD(SetBoolArray)(THIS_ D3DXHANDLE hParameter, CONST BOOL* pb, UINT Count) PURE; + STDMETHOD(GetBoolArray)(THIS_ D3DXHANDLE hParameter, BOOL* pb, UINT Count) PURE; + STDMETHOD(SetInt)(THIS_ D3DXHANDLE hParameter, INT n) PURE; + STDMETHOD(GetInt)(THIS_ D3DXHANDLE hParameter, INT* pn) PURE; + STDMETHOD(SetIntArray)(THIS_ D3DXHANDLE hParameter, CONST INT* pn, UINT Count) PURE; + STDMETHOD(GetIntArray)(THIS_ D3DXHANDLE hParameter, INT* pn, UINT Count) PURE; + STDMETHOD(SetFloat)(THIS_ D3DXHANDLE hParameter, FLOAT f) PURE; + STDMETHOD(GetFloat)(THIS_ D3DXHANDLE hParameter, FLOAT* pf) PURE; + STDMETHOD(SetFloatArray)(THIS_ D3DXHANDLE hParameter, CONST FLOAT* pf, UINT Count) PURE; + STDMETHOD(GetFloatArray)(THIS_ D3DXHANDLE hParameter, FLOAT* pf, UINT Count) PURE; + STDMETHOD(SetVector)(THIS_ D3DXHANDLE hParameter, CONST D3DXVECTOR4* pVector) PURE; + STDMETHOD(GetVector)(THIS_ D3DXHANDLE hParameter, D3DXVECTOR4* pVector) PURE; + STDMETHOD(SetVectorArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(GetVectorArray)(THIS_ D3DXHANDLE hParameter, D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(SetMatrix)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(GetMatrix)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixPointerArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixPointerArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTranspose)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(GetMatrixTranspose)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixTransposeArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixTransposeArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hParameter, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(GetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hParameter, D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetString)(THIS_ D3DXHANDLE hParameter, LPCSTR pString) PURE; + STDMETHOD(GetString)(THIS_ D3DXHANDLE hParameter, LPCSTR* ppString) PURE; + STDMETHOD(SetTexture)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DBASETEXTURE9 pTexture) PURE; + STDMETHOD(GetTexture)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DBASETEXTURE9 *ppTexture) PURE; + STDMETHOD(GetPixelShader)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DPIXELSHADER9 *ppPShader) PURE; + STDMETHOD(GetVertexShader)(THIS_ D3DXHANDLE hParameter, LPDIRECT3DVERTEXSHADER9 *ppVShader) PURE; + + //Set Range of an Array to pass to device + //Usefull for sending only a subrange of an array down to the device + STDMETHOD(SetArrayRange)(THIS_ D3DXHANDLE hParameter, UINT uStart, UINT uEnd) PURE; + // ID3DXBaseEffect + + // Parameter sharing, specialization, and information + STDMETHOD(SetLiteral)(THIS_ D3DXHANDLE hParameter, BOOL Literal) PURE; + STDMETHOD(GetLiteral)(THIS_ D3DXHANDLE hParameter, BOOL *pLiteral) PURE; + + // Compilation + STDMETHOD(CompileEffect)(THIS_ DWORD Flags, + LPD3DXBUFFER* ppEffect, LPD3DXBUFFER* ppErrorMsgs) PURE; + + STDMETHOD(CompileShader)(THIS_ D3DXHANDLE hFunction, LPCSTR pTarget, DWORD Flags, + LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable) PURE; +}; + + +////////////////////////////////////////////////////////////////////////////// +// APIs ////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +//---------------------------------------------------------------------------- +// D3DXCreateEffectPool: +// --------------------- +// Creates an effect pool. Pools are used for sharing parameters between +// multiple effects. For all effects within a pool, shared parameters of the +// same name all share the same value. +// +// Parameters: +// ppPool +// Returns the created pool. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCreateEffectPool( + LPD3DXEFFECTPOOL* ppPool); + + +//---------------------------------------------------------------------------- +// D3DXCreateEffect: +// ----------------- +// Creates an effect from an ascii or binary effect description. +// +// Parameters: +// pDevice +// Pointer of the device on which to create the effect +// pSrcFile +// Name of the file containing the effect description +// hSrcModule +// Module handle. if NULL, current module will be used. +// pSrcResource +// Resource name in module +// pSrcData +// Pointer to effect description +// SrcDataSize +// Size of the effect description in bytes +// pDefines +// Optional NULL-terminated array of preprocessor macro definitions. +// Flags +// See D3DXSHADER_xxx flags. +// pSkipConstants +// A list of semi-colon delimited variable names. The effect will +// not set these variables to the device when they are referenced +// by a shader. NOTE: the variables specified here must be +// register bound in the file and must not be used in expressions +// in passes or samplers or the file will not load. +// pInclude +// Optional interface pointer to use for handling #include directives. +// If this parameter is NULL, #includes will be honored when compiling +// from file, and will error when compiling from resource or memory. +// pPool +// Pointer to ID3DXEffectPool object to use for shared parameters. +// If NULL, no parameters will be shared. +// ppEffect +// Returns a buffer containing created effect. +// ppCompilationErrors +// Returns a buffer containing any error messages which occurred during +// compile. Or NULL if you do not care about the error messages. +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCreateEffectFromFileA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +HRESULT WINAPI + D3DXCreateEffectFromFileW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +#ifdef UNICODE +#define D3DXCreateEffectFromFile D3DXCreateEffectFromFileW +#else +#define D3DXCreateEffectFromFile D3DXCreateEffectFromFileA +#endif + + +HRESULT WINAPI + D3DXCreateEffectFromResourceA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +HRESULT WINAPI + D3DXCreateEffectFromResourceW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +#ifdef UNICODE +#define D3DXCreateEffectFromResource D3DXCreateEffectFromResourceW +#else +#define D3DXCreateEffectFromResource D3DXCreateEffectFromResourceA +#endif + + +HRESULT WINAPI + D3DXCreateEffect( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +// +// Ex functions that accept pSkipConstants in addition to other parameters +// + +HRESULT WINAPI + D3DXCreateEffectFromFileExA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pSkipConstants, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +HRESULT WINAPI + D3DXCreateEffectFromFileExW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pSkipConstants, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +#ifdef UNICODE +#define D3DXCreateEffectFromFileEx D3DXCreateEffectFromFileExW +#else +#define D3DXCreateEffectFromFileEx D3DXCreateEffectFromFileExA +#endif + + +HRESULT WINAPI + D3DXCreateEffectFromResourceExA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pSkipConstants, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +HRESULT WINAPI + D3DXCreateEffectFromResourceExW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pSkipConstants, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +#ifdef UNICODE +#define D3DXCreateEffectFromResourceEx D3DXCreateEffectFromResourceExW +#else +#define D3DXCreateEffectFromResourceEx D3DXCreateEffectFromResourceExA +#endif + + +HRESULT WINAPI + D3DXCreateEffectEx( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pSkipConstants, + DWORD Flags, + LPD3DXEFFECTPOOL pPool, + LPD3DXEFFECT* ppEffect, + LPD3DXBUFFER* ppCompilationErrors); + +//---------------------------------------------------------------------------- +// D3DXCreateEffectCompiler: +// ------------------------- +// Creates an effect from an ascii or binary effect description. +// +// Parameters: +// pSrcFile +// Name of the file containing the effect description +// hSrcModule +// Module handle. if NULL, current module will be used. +// pSrcResource +// Resource name in module +// pSrcData +// Pointer to effect description +// SrcDataSize +// Size of the effect description in bytes +// pDefines +// Optional NULL-terminated array of preprocessor macro definitions. +// pInclude +// Optional interface pointer to use for handling #include directives. +// If this parameter is NULL, #includes will be honored when compiling +// from file, and will error when compiling from resource or memory. +// pPool +// Pointer to ID3DXEffectPool object to use for shared parameters. +// If NULL, no parameters will be shared. +// ppCompiler +// Returns a buffer containing created effect compiler. +// ppParseErrors +// Returns a buffer containing any error messages which occurred during +// parse. Or NULL if you do not care about the error messages. +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCreateEffectCompilerFromFileA( + LPCSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTCOMPILER* ppCompiler, + LPD3DXBUFFER* ppParseErrors); + +HRESULT WINAPI + D3DXCreateEffectCompilerFromFileW( + LPCWSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTCOMPILER* ppCompiler, + LPD3DXBUFFER* ppParseErrors); + +#ifdef UNICODE +#define D3DXCreateEffectCompilerFromFile D3DXCreateEffectCompilerFromFileW +#else +#define D3DXCreateEffectCompilerFromFile D3DXCreateEffectCompilerFromFileA +#endif + + +HRESULT WINAPI + D3DXCreateEffectCompilerFromResourceA( + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTCOMPILER* ppCompiler, + LPD3DXBUFFER* ppParseErrors); + +HRESULT WINAPI + D3DXCreateEffectCompilerFromResourceW( + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTCOMPILER* ppCompiler, + LPD3DXBUFFER* ppParseErrors); + +#ifdef UNICODE +#define D3DXCreateEffectCompilerFromResource D3DXCreateEffectCompilerFromResourceW +#else +#define D3DXCreateEffectCompilerFromResource D3DXCreateEffectCompilerFromResourceA +#endif + + +HRESULT WINAPI + D3DXCreateEffectCompiler( + LPCSTR pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXEFFECTCOMPILER* ppCompiler, + LPD3DXBUFFER* ppParseErrors); + +//---------------------------------------------------------------------------- +// D3DXDisassembleEffect: +// ----------------------- +// +// Parameters: +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXDisassembleEffect( + LPD3DXEFFECT pEffect, + BOOL EnableColorCode, + LPD3DXBUFFER *ppDisassembly); + + + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__D3DX9EFFECT_H__ + + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9math.h b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9math.h new file mode 100644 index 0000000000..3fda05344a --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9math.h @@ -0,0 +1,1796 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9math.h +// Content: D3DX math types and functions +// +////////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9MATH_H__ +#define __D3DX9MATH_H__ + +#include +#if _MSC_VER >= 1200 +#pragma warning(push) +#endif +#pragma warning(disable:4201) // anonymous unions warning + + + +//=========================================================================== +// +// General purpose utilities +// +//=========================================================================== +#define D3DX_PI ((FLOAT) 3.141592654f) +#define D3DX_1BYPI ((FLOAT) 0.318309886f) + +#define D3DXToRadian( degree ) ((degree) * (D3DX_PI / 180.0f)) +#define D3DXToDegree( radian ) ((radian) * (180.0f / D3DX_PI)) + + + +//=========================================================================== +// +// 16 bit floating point numbers +// +//=========================================================================== + +#define D3DX_16F_DIG 3 // # of decimal digits of precision +#define D3DX_16F_EPSILON 4.8875809e-4f // smallest such that 1.0 + epsilon != 1.0 +#define D3DX_16F_MANT_DIG 11 // # of bits in mantissa +#define D3DX_16F_MAX 6.550400e+004 // max value +#define D3DX_16F_MAX_10_EXP 4 // max decimal exponent +#define D3DX_16F_MAX_EXP 15 // max binary exponent +#define D3DX_16F_MIN 6.1035156e-5f // min positive value +#define D3DX_16F_MIN_10_EXP (-4) // min decimal exponent +#define D3DX_16F_MIN_EXP (-14) // min binary exponent +#define D3DX_16F_RADIX 2 // exponent radix +#define D3DX_16F_ROUNDS 1 // addition rounding: near + + +typedef struct D3DXFLOAT16 +{ +#ifdef __cplusplus +public: + D3DXFLOAT16() {}; + D3DXFLOAT16( FLOAT ); + D3DXFLOAT16( CONST D3DXFLOAT16& ); + + // casting + operator FLOAT (); + + // binary operators + BOOL operator == ( CONST D3DXFLOAT16& ) const; + BOOL operator != ( CONST D3DXFLOAT16& ) const; + +protected: +#endif //__cplusplus + WORD value; +} D3DXFLOAT16, *LPD3DXFLOAT16; + + + +//=========================================================================== +// +// Vectors +// +//=========================================================================== + + +//-------------------------- +// 2D Vector +//-------------------------- +typedef struct D3DXVECTOR2 +{ +#ifdef __cplusplus +public: + D3DXVECTOR2() {}; + D3DXVECTOR2( CONST FLOAT * ); + D3DXVECTOR2( CONST D3DXFLOAT16 * ); + D3DXVECTOR2( FLOAT x, FLOAT y ); + + // casting + operator FLOAT* (); + operator CONST FLOAT* () const; + + // assignment operators + D3DXVECTOR2& operator += ( CONST D3DXVECTOR2& ); + D3DXVECTOR2& operator -= ( CONST D3DXVECTOR2& ); + D3DXVECTOR2& operator *= ( FLOAT ); + D3DXVECTOR2& operator /= ( FLOAT ); + + // unary operators + D3DXVECTOR2 operator + () const; + D3DXVECTOR2 operator - () const; + + // binary operators + D3DXVECTOR2 operator + ( CONST D3DXVECTOR2& ) const; + D3DXVECTOR2 operator - ( CONST D3DXVECTOR2& ) const; + D3DXVECTOR2 operator * ( FLOAT ) const; + D3DXVECTOR2 operator / ( FLOAT ) const; + + friend D3DXVECTOR2 operator * ( FLOAT, CONST D3DXVECTOR2& ); + + BOOL operator == ( CONST D3DXVECTOR2& ) const; + BOOL operator != ( CONST D3DXVECTOR2& ) const; + + +public: +#endif //__cplusplus + FLOAT x, y; +} D3DXVECTOR2, *LPD3DXVECTOR2; + + + +//-------------------------- +// 2D Vector (16 bit) +//-------------------------- + +typedef struct D3DXVECTOR2_16F +{ +#ifdef __cplusplus +public: + D3DXVECTOR2_16F() {}; + D3DXVECTOR2_16F( CONST FLOAT * ); + D3DXVECTOR2_16F( CONST D3DXFLOAT16 * ); + D3DXVECTOR2_16F( CONST D3DXFLOAT16 &x, CONST D3DXFLOAT16 &y ); + + // casting + operator D3DXFLOAT16* (); + operator CONST D3DXFLOAT16* () const; + + // binary operators + BOOL operator == ( CONST D3DXVECTOR2_16F& ) const; + BOOL operator != ( CONST D3DXVECTOR2_16F& ) const; + +public: +#endif //__cplusplus + D3DXFLOAT16 x, y; + +} D3DXVECTOR2_16F, *LPD3DXVECTOR2_16F; + + + +//-------------------------- +// 3D Vector +//-------------------------- +#ifdef __cplusplus +typedef struct D3DXVECTOR3 : public D3DVECTOR +{ +public: + D3DXVECTOR3() {}; + D3DXVECTOR3( CONST FLOAT * ); + D3DXVECTOR3( CONST D3DVECTOR& ); + D3DXVECTOR3( CONST D3DXFLOAT16 * ); + D3DXVECTOR3( FLOAT x, FLOAT y, FLOAT z ); + + // casting + operator FLOAT* (); + operator CONST FLOAT* () const; + + // assignment operators + D3DXVECTOR3& operator += ( CONST D3DXVECTOR3& ); + D3DXVECTOR3& operator -= ( CONST D3DXVECTOR3& ); + D3DXVECTOR3& operator *= ( FLOAT ); + D3DXVECTOR3& operator /= ( FLOAT ); + + // unary operators + D3DXVECTOR3 operator + () const; + D3DXVECTOR3 operator - () const; + + // binary operators + D3DXVECTOR3 operator + ( CONST D3DXVECTOR3& ) const; + D3DXVECTOR3 operator - ( CONST D3DXVECTOR3& ) const; + D3DXVECTOR3 operator * ( FLOAT ) const; + D3DXVECTOR3 operator / ( FLOAT ) const; + + friend D3DXVECTOR3 operator * ( FLOAT, CONST struct D3DXVECTOR3& ); + + BOOL operator == ( CONST D3DXVECTOR3& ) const; + BOOL operator != ( CONST D3DXVECTOR3& ) const; + +} D3DXVECTOR3, *LPD3DXVECTOR3; + +#else //!__cplusplus +typedef struct _D3DVECTOR D3DXVECTOR3, *LPD3DXVECTOR3; +#endif //!__cplusplus + + + +//-------------------------- +// 3D Vector (16 bit) +//-------------------------- +typedef struct D3DXVECTOR3_16F +{ +#ifdef __cplusplus +public: + D3DXVECTOR3_16F() {}; + D3DXVECTOR3_16F( CONST FLOAT * ); + D3DXVECTOR3_16F( CONST D3DVECTOR& ); + D3DXVECTOR3_16F( CONST D3DXFLOAT16 * ); + D3DXVECTOR3_16F( CONST D3DXFLOAT16 &x, CONST D3DXFLOAT16 &y, CONST D3DXFLOAT16 &z ); + + // casting + operator D3DXFLOAT16* (); + operator CONST D3DXFLOAT16* () const; + + // binary operators + BOOL operator == ( CONST D3DXVECTOR3_16F& ) const; + BOOL operator != ( CONST D3DXVECTOR3_16F& ) const; + +public: +#endif //__cplusplus + D3DXFLOAT16 x, y, z; + +} D3DXVECTOR3_16F, *LPD3DXVECTOR3_16F; + + + +//-------------------------- +// 4D Vector +//-------------------------- +typedef struct D3DXVECTOR4 +{ +#ifdef __cplusplus +public: + D3DXVECTOR4() {}; + D3DXVECTOR4( CONST FLOAT* ); + D3DXVECTOR4( CONST D3DXFLOAT16* ); + D3DXVECTOR4( CONST D3DVECTOR& xyz, FLOAT w ); + D3DXVECTOR4( FLOAT x, FLOAT y, FLOAT z, FLOAT w ); + + // casting + operator FLOAT* (); + operator CONST FLOAT* () const; + + // assignment operators + D3DXVECTOR4& operator += ( CONST D3DXVECTOR4& ); + D3DXVECTOR4& operator -= ( CONST D3DXVECTOR4& ); + D3DXVECTOR4& operator *= ( FLOAT ); + D3DXVECTOR4& operator /= ( FLOAT ); + + // unary operators + D3DXVECTOR4 operator + () const; + D3DXVECTOR4 operator - () const; + + // binary operators + D3DXVECTOR4 operator + ( CONST D3DXVECTOR4& ) const; + D3DXVECTOR4 operator - ( CONST D3DXVECTOR4& ) const; + D3DXVECTOR4 operator * ( FLOAT ) const; + D3DXVECTOR4 operator / ( FLOAT ) const; + + friend D3DXVECTOR4 operator * ( FLOAT, CONST D3DXVECTOR4& ); + + BOOL operator == ( CONST D3DXVECTOR4& ) const; + BOOL operator != ( CONST D3DXVECTOR4& ) const; + +public: +#endif //__cplusplus + FLOAT x, y, z, w; +} D3DXVECTOR4, *LPD3DXVECTOR4; + + +//-------------------------- +// 4D Vector (16 bit) +//-------------------------- +typedef struct D3DXVECTOR4_16F +{ +#ifdef __cplusplus +public: + D3DXVECTOR4_16F() {}; + D3DXVECTOR4_16F( CONST FLOAT * ); + D3DXVECTOR4_16F( CONST D3DXFLOAT16* ); + D3DXVECTOR4_16F( CONST D3DXVECTOR3_16F& xyz, CONST D3DXFLOAT16& w ); + D3DXVECTOR4_16F( CONST D3DXFLOAT16& x, CONST D3DXFLOAT16& y, CONST D3DXFLOAT16& z, CONST D3DXFLOAT16& w ); + + // casting + operator D3DXFLOAT16* (); + operator CONST D3DXFLOAT16* () const; + + // binary operators + BOOL operator == ( CONST D3DXVECTOR4_16F& ) const; + BOOL operator != ( CONST D3DXVECTOR4_16F& ) const; + +public: +#endif //__cplusplus + D3DXFLOAT16 x, y, z, w; + +} D3DXVECTOR4_16F, *LPD3DXVECTOR4_16F; + + + +//=========================================================================== +// +// Matrices +// +//=========================================================================== +#ifdef __cplusplus +typedef struct D3DXMATRIX : public D3DMATRIX +{ +public: + D3DXMATRIX() {}; + D3DXMATRIX( CONST FLOAT * ); + D3DXMATRIX( CONST D3DMATRIX& ); + D3DXMATRIX( CONST D3DXFLOAT16 * ); + D3DXMATRIX( FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14, + FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24, + FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34, + FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44 ); + + + // access grants + FLOAT& operator () ( UINT Row, UINT Col ); + FLOAT operator () ( UINT Row, UINT Col ) const; + + // casting operators + operator FLOAT* (); + operator CONST FLOAT* () const; + + // assignment operators + D3DXMATRIX& operator *= ( CONST D3DXMATRIX& ); + D3DXMATRIX& operator += ( CONST D3DXMATRIX& ); + D3DXMATRIX& operator -= ( CONST D3DXMATRIX& ); + D3DXMATRIX& operator *= ( FLOAT ); + D3DXMATRIX& operator /= ( FLOAT ); + + // unary operators + D3DXMATRIX operator + () const; + D3DXMATRIX operator - () const; + + // binary operators + D3DXMATRIX operator * ( CONST D3DXMATRIX& ) const; + D3DXMATRIX operator + ( CONST D3DXMATRIX& ) const; + D3DXMATRIX operator - ( CONST D3DXMATRIX& ) const; + D3DXMATRIX operator * ( FLOAT ) const; + D3DXMATRIX operator / ( FLOAT ) const; + + friend D3DXMATRIX operator * ( FLOAT, CONST D3DXMATRIX& ); + + BOOL operator == ( CONST D3DXMATRIX& ) const; + BOOL operator != ( CONST D3DXMATRIX& ) const; + +} D3DXMATRIX, *LPD3DXMATRIX; + +#else //!__cplusplus +typedef struct _D3DMATRIX D3DXMATRIX, *LPD3DXMATRIX; +#endif //!__cplusplus + + +//--------------------------------------------------------------------------- +// Aligned Matrices +// +// This class helps keep matrices 16-byte aligned as preferred by P4 cpus. +// It aligns matrices on the stack and on the heap or in global scope. +// It does this using __declspec(align(16)) which works on VC7 and on VC 6 +// with the processor pack. Unfortunately there is no way to detect the +// latter so this is turned on only on VC7. On other compilers this is the +// the same as D3DXMATRIX. +// +// Using this class on a compiler that does not actually do the alignment +// can be dangerous since it will not expose bugs that ignore alignment. +// E.g if an object of this class in inside a struct or class, and some code +// memcopys data in it assuming tight packing. This could break on a compiler +// that eventually start aligning the matrix. +//--------------------------------------------------------------------------- +#ifdef __cplusplus +typedef struct _D3DXMATRIXA16 : public D3DXMATRIX +{ + _D3DXMATRIXA16() {} + _D3DXMATRIXA16( CONST FLOAT * ); + _D3DXMATRIXA16( CONST D3DMATRIX& ); + _D3DXMATRIXA16( CONST D3DXFLOAT16 * ); + _D3DXMATRIXA16( FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14, + FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24, + FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34, + FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44 ); + + // new operators + void* operator new ( size_t ); + void* operator new[] ( size_t ); + + // delete operators + void operator delete ( void* ); // These are NOT virtual; Do not + void operator delete[] ( void* ); // cast to D3DXMATRIX and delete. + + // assignment operators + _D3DXMATRIXA16& operator = ( CONST D3DXMATRIX& ); + +} _D3DXMATRIXA16; + +#else //!__cplusplus +typedef D3DXMATRIX _D3DXMATRIXA16; +#endif //!__cplusplus + + + +#if _MSC_VER >= 1300 // VC7 +#define D3DX_ALIGN16 __declspec(align(16)) +#else +#define D3DX_ALIGN16 // Earlier compiler may not understand this, do nothing. +#endif + +typedef D3DX_ALIGN16 _D3DXMATRIXA16 D3DXMATRIXA16, *LPD3DXMATRIXA16; + + + +//=========================================================================== +// +// Quaternions +// +//=========================================================================== +typedef struct D3DXQUATERNION +{ +#ifdef __cplusplus +public: + D3DXQUATERNION() {} + D3DXQUATERNION( CONST FLOAT * ); + D3DXQUATERNION( CONST D3DXFLOAT16 * ); + D3DXQUATERNION( FLOAT x, FLOAT y, FLOAT z, FLOAT w ); + + // casting + operator FLOAT* (); + operator CONST FLOAT* () const; + + // assignment operators + D3DXQUATERNION& operator += ( CONST D3DXQUATERNION& ); + D3DXQUATERNION& operator -= ( CONST D3DXQUATERNION& ); + D3DXQUATERNION& operator *= ( CONST D3DXQUATERNION& ); + D3DXQUATERNION& operator *= ( FLOAT ); + D3DXQUATERNION& operator /= ( FLOAT ); + + // unary operators + D3DXQUATERNION operator + () const; + D3DXQUATERNION operator - () const; + + // binary operators + D3DXQUATERNION operator + ( CONST D3DXQUATERNION& ) const; + D3DXQUATERNION operator - ( CONST D3DXQUATERNION& ) const; + D3DXQUATERNION operator * ( CONST D3DXQUATERNION& ) const; + D3DXQUATERNION operator * ( FLOAT ) const; + D3DXQUATERNION operator / ( FLOAT ) const; + + friend D3DXQUATERNION operator * (FLOAT, CONST D3DXQUATERNION& ); + + BOOL operator == ( CONST D3DXQUATERNION& ) const; + BOOL operator != ( CONST D3DXQUATERNION& ) const; + +#endif //__cplusplus + FLOAT x, y, z, w; +} D3DXQUATERNION, *LPD3DXQUATERNION; + + +//=========================================================================== +// +// Planes +// +//=========================================================================== +typedef struct D3DXPLANE +{ +#ifdef __cplusplus +public: + D3DXPLANE() {} + D3DXPLANE( CONST FLOAT* ); + D3DXPLANE( CONST D3DXFLOAT16* ); + D3DXPLANE( FLOAT a, FLOAT b, FLOAT c, FLOAT d ); + + // casting + operator FLOAT* (); + operator CONST FLOAT* () const; + + // assignment operators + D3DXPLANE& operator *= ( FLOAT ); + D3DXPLANE& operator /= ( FLOAT ); + + // unary operators + D3DXPLANE operator + () const; + D3DXPLANE operator - () const; + + // binary operators + D3DXPLANE operator * ( FLOAT ) const; + D3DXPLANE operator / ( FLOAT ) const; + + friend D3DXPLANE operator * ( FLOAT, CONST D3DXPLANE& ); + + BOOL operator == ( CONST D3DXPLANE& ) const; + BOOL operator != ( CONST D3DXPLANE& ) const; + +#endif //__cplusplus + FLOAT a, b, c, d; +} D3DXPLANE, *LPD3DXPLANE; + + +//=========================================================================== +// +// Colors +// +//=========================================================================== + +typedef struct D3DXCOLOR +{ +#ifdef __cplusplus +public: + D3DXCOLOR() {} + D3DXCOLOR( DWORD argb ); + D3DXCOLOR( CONST FLOAT * ); + D3DXCOLOR( CONST D3DXFLOAT16 * ); + D3DXCOLOR( CONST D3DCOLORVALUE& ); + D3DXCOLOR( FLOAT r, FLOAT g, FLOAT b, FLOAT a ); + + // casting + operator DWORD () const; + + operator FLOAT* (); + operator CONST FLOAT* () const; + + operator D3DCOLORVALUE* (); + operator CONST D3DCOLORVALUE* () const; + + operator D3DCOLORVALUE& (); + operator CONST D3DCOLORVALUE& () const; + + // assignment operators + D3DXCOLOR& operator += ( CONST D3DXCOLOR& ); + D3DXCOLOR& operator -= ( CONST D3DXCOLOR& ); + D3DXCOLOR& operator *= ( FLOAT ); + D3DXCOLOR& operator /= ( FLOAT ); + + // unary operators + D3DXCOLOR operator + () const; + D3DXCOLOR operator - () const; + + // binary operators + D3DXCOLOR operator + ( CONST D3DXCOLOR& ) const; + D3DXCOLOR operator - ( CONST D3DXCOLOR& ) const; + D3DXCOLOR operator * ( FLOAT ) const; + D3DXCOLOR operator / ( FLOAT ) const; + + friend D3DXCOLOR operator * ( FLOAT, CONST D3DXCOLOR& ); + + BOOL operator == ( CONST D3DXCOLOR& ) const; + BOOL operator != ( CONST D3DXCOLOR& ) const; + +#endif //__cplusplus + FLOAT r, g, b, a; +} D3DXCOLOR, *LPD3DXCOLOR; + + + +//=========================================================================== +// +// D3DX math functions: +// +// NOTE: +// * All these functions can take the same object as in and out parameters. +// +// * Out parameters are typically also returned as return values, so that +// the output of one function may be used as a parameter to another. +// +//=========================================================================== + +//-------------------------- +// Float16 +//-------------------------- + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +// Converts an array 32-bit floats to 16-bit floats +D3DXFLOAT16* WINAPI D3DXFloat32To16Array + ( D3DXFLOAT16 *pOut, CONST FLOAT *pIn, UINT n ); + +// Converts an array 16-bit floats to 32-bit floats +FLOAT* WINAPI D3DXFloat16To32Array + ( FLOAT *pOut, CONST D3DXFLOAT16 *pIn, UINT n ); + +#ifdef __cplusplus +} +#endif + + +//-------------------------- +// 2D Vector +//-------------------------- + +// inline + +FLOAT D3DXVec2Length + ( CONST D3DXVECTOR2 *pV ); + +FLOAT D3DXVec2LengthSq + ( CONST D3DXVECTOR2 *pV ); + +FLOAT D3DXVec2Dot + ( CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ); + +// Z component of ((x1,y1,0) cross (x2,y2,0)) +FLOAT D3DXVec2CCW + ( CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ); + +D3DXVECTOR2* D3DXVec2Add + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ); + +D3DXVECTOR2* D3DXVec2Subtract + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ); + +// Minimize each component. x = min(x1, x2), y = min(y1, y2) +D3DXVECTOR2* D3DXVec2Minimize + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ); + +// Maximize each component. x = max(x1, x2), y = max(y1, y2) +D3DXVECTOR2* D3DXVec2Maximize + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ); + +D3DXVECTOR2* D3DXVec2Scale + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV, FLOAT s ); + +// Linear interpolation. V1 + s(V2-V1) +D3DXVECTOR2* D3DXVec2Lerp + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2, + FLOAT s ); + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +D3DXVECTOR2* WINAPI D3DXVec2Normalize + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV ); + +// Hermite interpolation between position V1, tangent T1 (when s == 0) +// and position V2, tangent T2 (when s == 1). +D3DXVECTOR2* WINAPI D3DXVec2Hermite + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pT1, + CONST D3DXVECTOR2 *pV2, CONST D3DXVECTOR2 *pT2, FLOAT s ); + +// CatmullRom interpolation between V1 (when s == 0) and V2 (when s == 1) +D3DXVECTOR2* WINAPI D3DXVec2CatmullRom + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV0, CONST D3DXVECTOR2 *pV1, + CONST D3DXVECTOR2 *pV2, CONST D3DXVECTOR2 *pV3, FLOAT s ); + +// Barycentric coordinates. V1 + f(V2-V1) + g(V3-V1) +D3DXVECTOR2* WINAPI D3DXVec2BaryCentric + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2, + CONST D3DXVECTOR2 *pV3, FLOAT f, FLOAT g); + +// Transform (x, y, 0, 1) by matrix. +D3DXVECTOR4* WINAPI D3DXVec2Transform + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR2 *pV, CONST D3DXMATRIX *pM ); + +// Transform (x, y, 0, 1) by matrix, project result back into w=1. +D3DXVECTOR2* WINAPI D3DXVec2TransformCoord + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV, CONST D3DXMATRIX *pM ); + +// Transform (x, y, 0, 0) by matrix. +D3DXVECTOR2* WINAPI D3DXVec2TransformNormal + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV, CONST D3DXMATRIX *pM ); + +// Transform Array (x, y, 0, 1) by matrix. +D3DXVECTOR4* WINAPI D3DXVec2TransformArray + ( D3DXVECTOR4 *pOut, UINT OutStride, CONST D3DXVECTOR2 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n); + +// Transform Array (x, y, 0, 1) by matrix, project result back into w=1. +D3DXVECTOR2* WINAPI D3DXVec2TransformCoordArray + ( D3DXVECTOR2 *pOut, UINT OutStride, CONST D3DXVECTOR2 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n ); + +// Transform Array (x, y, 0, 0) by matrix. +D3DXVECTOR2* WINAPI D3DXVec2TransformNormalArray + ( D3DXVECTOR2 *pOut, UINT OutStride, CONST D3DXVECTOR2 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n ); + + + +#ifdef __cplusplus +} +#endif + + +//-------------------------- +// 3D Vector +//-------------------------- + +// inline + +FLOAT D3DXVec3Length + ( CONST D3DXVECTOR3 *pV ); + +FLOAT D3DXVec3LengthSq + ( CONST D3DXVECTOR3 *pV ); + +FLOAT D3DXVec3Dot + ( CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ); + +D3DXVECTOR3* D3DXVec3Cross + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ); + +D3DXVECTOR3* D3DXVec3Add + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ); + +D3DXVECTOR3* D3DXVec3Subtract + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ); + +// Minimize each component. x = min(x1, x2), y = min(y1, y2), ... +D3DXVECTOR3* D3DXVec3Minimize + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ); + +// Maximize each component. x = max(x1, x2), y = max(y1, y2), ... +D3DXVECTOR3* D3DXVec3Maximize + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ); + +D3DXVECTOR3* D3DXVec3Scale + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, FLOAT s); + +// Linear interpolation. V1 + s(V2-V1) +D3DXVECTOR3* D3DXVec3Lerp + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2, + FLOAT s ); + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +D3DXVECTOR3* WINAPI D3DXVec3Normalize + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV ); + +// Hermite interpolation between position V1, tangent T1 (when s == 0) +// and position V2, tangent T2 (when s == 1). +D3DXVECTOR3* WINAPI D3DXVec3Hermite + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pT1, + CONST D3DXVECTOR3 *pV2, CONST D3DXVECTOR3 *pT2, FLOAT s ); + +// CatmullRom interpolation between V1 (when s == 0) and V2 (when s == 1) +D3DXVECTOR3* WINAPI D3DXVec3CatmullRom + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV0, CONST D3DXVECTOR3 *pV1, + CONST D3DXVECTOR3 *pV2, CONST D3DXVECTOR3 *pV3, FLOAT s ); + +// Barycentric coordinates. V1 + f(V2-V1) + g(V3-V1) +D3DXVECTOR3* WINAPI D3DXVec3BaryCentric + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2, + CONST D3DXVECTOR3 *pV3, FLOAT f, FLOAT g); + +// Transform (x, y, z, 1) by matrix. +D3DXVECTOR4* WINAPI D3DXVec3Transform + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM ); + +// Transform (x, y, z, 1) by matrix, project result back into w=1. +D3DXVECTOR3* WINAPI D3DXVec3TransformCoord + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM ); + +// Transform (x, y, z, 0) by matrix. If you transforming a normal by a +// non-affine matrix, the matrix you pass to this function should be the +// transpose of the inverse of the matrix you would use to transform a coord. +D3DXVECTOR3* WINAPI D3DXVec3TransformNormal + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM ); + + +// Transform Array (x, y, z, 1) by matrix. +D3DXVECTOR4* WINAPI D3DXVec3TransformArray + ( D3DXVECTOR4 *pOut, UINT OutStride, CONST D3DXVECTOR3 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n ); + +// Transform Array (x, y, z, 1) by matrix, project result back into w=1. +D3DXVECTOR3* WINAPI D3DXVec3TransformCoordArray + ( D3DXVECTOR3 *pOut, UINT OutStride, CONST D3DXVECTOR3 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n ); + +// Transform (x, y, z, 0) by matrix. If you transforming a normal by a +// non-affine matrix, the matrix you pass to this function should be the +// transpose of the inverse of the matrix you would use to transform a coord. +D3DXVECTOR3* WINAPI D3DXVec3TransformNormalArray + ( D3DXVECTOR3 *pOut, UINT OutStride, CONST D3DXVECTOR3 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n ); + +// Project vector from object space into screen space +D3DXVECTOR3* WINAPI D3DXVec3Project + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DVIEWPORT9 *pViewport, + CONST D3DXMATRIX *pProjection, CONST D3DXMATRIX *pView, CONST D3DXMATRIX *pWorld); + +// Project vector from screen space into object space +D3DXVECTOR3* WINAPI D3DXVec3Unproject + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DVIEWPORT9 *pViewport, + CONST D3DXMATRIX *pProjection, CONST D3DXMATRIX *pView, CONST D3DXMATRIX *pWorld); + +// Project vector Array from object space into screen space +D3DXVECTOR3* WINAPI D3DXVec3ProjectArray + ( D3DXVECTOR3 *pOut, UINT OutStride,CONST D3DXVECTOR3 *pV, UINT VStride,CONST D3DVIEWPORT9 *pViewport, + CONST D3DXMATRIX *pProjection, CONST D3DXMATRIX *pView, CONST D3DXMATRIX *pWorld, UINT n); + +// Project vector Array from screen space into object space +D3DXVECTOR3* WINAPI D3DXVec3UnprojectArray + ( D3DXVECTOR3 *pOut, UINT OutStride, CONST D3DXVECTOR3 *pV, UINT VStride, CONST D3DVIEWPORT9 *pViewport, + CONST D3DXMATRIX *pProjection, CONST D3DXMATRIX *pView, CONST D3DXMATRIX *pWorld, UINT n); + + +#ifdef __cplusplus +} +#endif + + + +//-------------------------- +// 4D Vector +//-------------------------- + +// inline + +FLOAT D3DXVec4Length + ( CONST D3DXVECTOR4 *pV ); + +FLOAT D3DXVec4LengthSq + ( CONST D3DXVECTOR4 *pV ); + +FLOAT D3DXVec4Dot + ( CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2 ); + +D3DXVECTOR4* D3DXVec4Add + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2); + +D3DXVECTOR4* D3DXVec4Subtract + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2); + +// Minimize each component. x = min(x1, x2), y = min(y1, y2), ... +D3DXVECTOR4* D3DXVec4Minimize + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2); + +// Maximize each component. x = max(x1, x2), y = max(y1, y2), ... +D3DXVECTOR4* D3DXVec4Maximize + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2); + +D3DXVECTOR4* D3DXVec4Scale + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, FLOAT s); + +// Linear interpolation. V1 + s(V2-V1) +D3DXVECTOR4* D3DXVec4Lerp + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2, + FLOAT s ); + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +// Cross-product in 4 dimensions. +D3DXVECTOR4* WINAPI D3DXVec4Cross + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2, + CONST D3DXVECTOR4 *pV3); + +D3DXVECTOR4* WINAPI D3DXVec4Normalize + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV ); + +// Hermite interpolation between position V1, tangent T1 (when s == 0) +// and position V2, tangent T2 (when s == 1). +D3DXVECTOR4* WINAPI D3DXVec4Hermite + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pT1, + CONST D3DXVECTOR4 *pV2, CONST D3DXVECTOR4 *pT2, FLOAT s ); + +// CatmullRom interpolation between V1 (when s == 0) and V2 (when s == 1) +D3DXVECTOR4* WINAPI D3DXVec4CatmullRom + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV0, CONST D3DXVECTOR4 *pV1, + CONST D3DXVECTOR4 *pV2, CONST D3DXVECTOR4 *pV3, FLOAT s ); + +// Barycentric coordinates. V1 + f(V2-V1) + g(V3-V1) +D3DXVECTOR4* WINAPI D3DXVec4BaryCentric + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2, + CONST D3DXVECTOR4 *pV3, FLOAT f, FLOAT g); + +// Transform vector by matrix. +D3DXVECTOR4* WINAPI D3DXVec4Transform + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, CONST D3DXMATRIX *pM ); + +// Transform vector array by matrix. +D3DXVECTOR4* WINAPI D3DXVec4TransformArray + ( D3DXVECTOR4 *pOut, UINT OutStride, CONST D3DXVECTOR4 *pV, UINT VStride, CONST D3DXMATRIX *pM, UINT n ); + +#ifdef __cplusplus +} +#endif + + +//-------------------------- +// 4D Matrix +//-------------------------- + +// inline + +D3DXMATRIX* D3DXMatrixIdentity + ( D3DXMATRIX *pOut ); + +BOOL D3DXMatrixIsIdentity + ( CONST D3DXMATRIX *pM ); + + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +FLOAT WINAPI D3DXMatrixDeterminant + ( CONST D3DXMATRIX *pM ); + +HRESULT WINAPI D3DXMatrixDecompose + ( D3DXVECTOR3 *pOutScale, D3DXQUATERNION *pOutRotation, + D3DXVECTOR3 *pOutTranslation, CONST D3DXMATRIX *pM ); + +D3DXMATRIX* WINAPI D3DXMatrixTranspose + ( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM ); + +// Matrix multiplication. The result represents the transformation M2 +// followed by the transformation M1. (Out = M1 * M2) +D3DXMATRIX* WINAPI D3DXMatrixMultiply + ( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 ); + +// Matrix multiplication, followed by a transpose. (Out = T(M1 * M2)) +D3DXMATRIX* WINAPI D3DXMatrixMultiplyTranspose + ( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 ); + +// Calculate inverse of matrix. Inversion my fail, in which case NULL will +// be returned. The determinant of pM is also returned it pfDeterminant +// is non-NULL. +D3DXMATRIX* WINAPI D3DXMatrixInverse + ( D3DXMATRIX *pOut, FLOAT *pDeterminant, CONST D3DXMATRIX *pM ); + +// Build a matrix which scales by (sx, sy, sz) +D3DXMATRIX* WINAPI D3DXMatrixScaling + ( D3DXMATRIX *pOut, FLOAT sx, FLOAT sy, FLOAT sz ); + +// Build a matrix which translates by (x, y, z) +D3DXMATRIX* WINAPI D3DXMatrixTranslation + ( D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z ); + +// Build a matrix which rotates around the X axis +D3DXMATRIX* WINAPI D3DXMatrixRotationX + ( D3DXMATRIX *pOut, FLOAT Angle ); + +// Build a matrix which rotates around the Y axis +D3DXMATRIX* WINAPI D3DXMatrixRotationY + ( D3DXMATRIX *pOut, FLOAT Angle ); + +// Build a matrix which rotates around the Z axis +D3DXMATRIX* WINAPI D3DXMatrixRotationZ + ( D3DXMATRIX *pOut, FLOAT Angle ); + +// Build a matrix which rotates around an arbitrary axis +D3DXMATRIX* WINAPI D3DXMatrixRotationAxis + ( D3DXMATRIX *pOut, CONST D3DXVECTOR3 *pV, FLOAT Angle ); + +// Build a matrix from a quaternion +D3DXMATRIX* WINAPI D3DXMatrixRotationQuaternion + ( D3DXMATRIX *pOut, CONST D3DXQUATERNION *pQ); + +// Yaw around the Y axis, a pitch around the X axis, +// and a roll around the Z axis. +D3DXMATRIX* WINAPI D3DXMatrixRotationYawPitchRoll + ( D3DXMATRIX *pOut, FLOAT Yaw, FLOAT Pitch, FLOAT Roll ); + +// Build transformation matrix. NULL arguments are treated as identity. +// Mout = Msc-1 * Msr-1 * Ms * Msr * Msc * Mrc-1 * Mr * Mrc * Mt +D3DXMATRIX* WINAPI D3DXMatrixTransformation + ( D3DXMATRIX *pOut, CONST D3DXVECTOR3 *pScalingCenter, + CONST D3DXQUATERNION *pScalingRotation, CONST D3DXVECTOR3 *pScaling, + CONST D3DXVECTOR3 *pRotationCenter, CONST D3DXQUATERNION *pRotation, + CONST D3DXVECTOR3 *pTranslation); + +// Build 2D transformation matrix in XY plane. NULL arguments are treated as identity. +// Mout = Msc-1 * Msr-1 * Ms * Msr * Msc * Mrc-1 * Mr * Mrc * Mt +D3DXMATRIX* WINAPI D3DXMatrixTransformation2D + ( D3DXMATRIX *pOut, CONST D3DXVECTOR2* pScalingCenter, + FLOAT ScalingRotation, CONST D3DXVECTOR2* pScaling, + CONST D3DXVECTOR2* pRotationCenter, FLOAT Rotation, + CONST D3DXVECTOR2* pTranslation); + +// Build affine transformation matrix. NULL arguments are treated as identity. +// Mout = Ms * Mrc-1 * Mr * Mrc * Mt +D3DXMATRIX* WINAPI D3DXMatrixAffineTransformation + ( D3DXMATRIX *pOut, FLOAT Scaling, CONST D3DXVECTOR3 *pRotationCenter, + CONST D3DXQUATERNION *pRotation, CONST D3DXVECTOR3 *pTranslation); + +// Build 2D affine transformation matrix in XY plane. NULL arguments are treated as identity. +// Mout = Ms * Mrc-1 * Mr * Mrc * Mt +D3DXMATRIX* WINAPI D3DXMatrixAffineTransformation2D + ( D3DXMATRIX *pOut, FLOAT Scaling, CONST D3DXVECTOR2* pRotationCenter, + FLOAT Rotation, CONST D3DXVECTOR2* pTranslation); + +// Build a lookat matrix. (right-handed) +D3DXMATRIX* WINAPI D3DXMatrixLookAtRH + ( D3DXMATRIX *pOut, CONST D3DXVECTOR3 *pEye, CONST D3DXVECTOR3 *pAt, + CONST D3DXVECTOR3 *pUp ); + +// Build a lookat matrix. (left-handed) +D3DXMATRIX* WINAPI D3DXMatrixLookAtLH + ( D3DXMATRIX *pOut, CONST D3DXVECTOR3 *pEye, CONST D3DXVECTOR3 *pAt, + CONST D3DXVECTOR3 *pUp ); + +// Build a perspective projection matrix. (right-handed) +D3DXMATRIX* WINAPI D3DXMatrixPerspectiveRH + ( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ); + +// Build a perspective projection matrix. (left-handed) +D3DXMATRIX* WINAPI D3DXMatrixPerspectiveLH + ( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ); + +// Build a perspective projection matrix. (right-handed) +D3DXMATRIX* WINAPI D3DXMatrixPerspectiveFovRH + ( D3DXMATRIX *pOut, FLOAT fovy, FLOAT Aspect, FLOAT zn, FLOAT zf ); + +// Build a perspective projection matrix. (left-handed) +D3DXMATRIX* WINAPI D3DXMatrixPerspectiveFovLH + ( D3DXMATRIX *pOut, FLOAT fovy, FLOAT Aspect, FLOAT zn, FLOAT zf ); + +// Build a perspective projection matrix. (right-handed) +D3DXMATRIX* WINAPI D3DXMatrixPerspectiveOffCenterRH + ( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, + FLOAT zf ); + +// Build a perspective projection matrix. (left-handed) +D3DXMATRIX* WINAPI D3DXMatrixPerspectiveOffCenterLH + ( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, + FLOAT zf ); + +// Build an ortho projection matrix. (right-handed) +D3DXMATRIX* WINAPI D3DXMatrixOrthoRH + ( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ); + +// Build an ortho projection matrix. (left-handed) +D3DXMATRIX* WINAPI D3DXMatrixOrthoLH + ( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ); + +// Build an ortho projection matrix. (right-handed) +D3DXMATRIX* WINAPI D3DXMatrixOrthoOffCenterRH + ( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, + FLOAT zf ); + +// Build an ortho projection matrix. (left-handed) +D3DXMATRIX* WINAPI D3DXMatrixOrthoOffCenterLH + ( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, + FLOAT zf ); + +// Build a matrix which flattens geometry into a plane, as if casting +// a shadow from a light. +D3DXMATRIX* WINAPI D3DXMatrixShadow + ( D3DXMATRIX *pOut, CONST D3DXVECTOR4 *pLight, + CONST D3DXPLANE *pPlane ); + +// Build a matrix which reflects the coordinate system about a plane +D3DXMATRIX* WINAPI D3DXMatrixReflect + ( D3DXMATRIX *pOut, CONST D3DXPLANE *pPlane ); + +#ifdef __cplusplus +} +#endif + + +//-------------------------- +// Quaternion +//-------------------------- + +// inline + +FLOAT D3DXQuaternionLength + ( CONST D3DXQUATERNION *pQ ); + +// Length squared, or "norm" +FLOAT D3DXQuaternionLengthSq + ( CONST D3DXQUATERNION *pQ ); + +FLOAT D3DXQuaternionDot + ( CONST D3DXQUATERNION *pQ1, CONST D3DXQUATERNION *pQ2 ); + +// (0, 0, 0, 1) +D3DXQUATERNION* D3DXQuaternionIdentity + ( D3DXQUATERNION *pOut ); + +BOOL D3DXQuaternionIsIdentity + ( CONST D3DXQUATERNION *pQ ); + +// (-x, -y, -z, w) +D3DXQUATERNION* D3DXQuaternionConjugate + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ ); + + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +// Compute a quaternin's axis and angle of rotation. Expects unit quaternions. +void WINAPI D3DXQuaternionToAxisAngle + ( CONST D3DXQUATERNION *pQ, D3DXVECTOR3 *pAxis, FLOAT *pAngle ); + +// Build a quaternion from a rotation matrix. +D3DXQUATERNION* WINAPI D3DXQuaternionRotationMatrix + ( D3DXQUATERNION *pOut, CONST D3DXMATRIX *pM); + +// Rotation about arbitrary axis. +D3DXQUATERNION* WINAPI D3DXQuaternionRotationAxis + ( D3DXQUATERNION *pOut, CONST D3DXVECTOR3 *pV, FLOAT Angle ); + +// Yaw around the Y axis, a pitch around the X axis, +// and a roll around the Z axis. +D3DXQUATERNION* WINAPI D3DXQuaternionRotationYawPitchRoll + ( D3DXQUATERNION *pOut, FLOAT Yaw, FLOAT Pitch, FLOAT Roll ); + +// Quaternion multiplication. The result represents the rotation Q2 +// followed by the rotation Q1. (Out = Q2 * Q1) +D3DXQUATERNION* WINAPI D3DXQuaternionMultiply + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ1, + CONST D3DXQUATERNION *pQ2 ); + +D3DXQUATERNION* WINAPI D3DXQuaternionNormalize + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ ); + +// Conjugate and re-norm +D3DXQUATERNION* WINAPI D3DXQuaternionInverse + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ ); + +// Expects unit quaternions. +// if q = (cos(theta), sin(theta) * v); ln(q) = (0, theta * v) +D3DXQUATERNION* WINAPI D3DXQuaternionLn + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ ); + +// Expects pure quaternions. (w == 0) w is ignored in calculation. +// if q = (0, theta * v); exp(q) = (cos(theta), sin(theta) * v) +D3DXQUATERNION* WINAPI D3DXQuaternionExp + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ ); + +// Spherical linear interpolation between Q1 (t == 0) and Q2 (t == 1). +// Expects unit quaternions. +D3DXQUATERNION* WINAPI D3DXQuaternionSlerp + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ1, + CONST D3DXQUATERNION *pQ2, FLOAT t ); + +// Spherical quadrangle interpolation. +// Slerp(Slerp(Q1, C, t), Slerp(A, B, t), 2t(1-t)) +D3DXQUATERNION* WINAPI D3DXQuaternionSquad + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ1, + CONST D3DXQUATERNION *pA, CONST D3DXQUATERNION *pB, + CONST D3DXQUATERNION *pC, FLOAT t ); + +// Setup control points for spherical quadrangle interpolation +// from Q1 to Q2. The control points are chosen in such a way +// to ensure the continuity of tangents with adjacent segments. +void WINAPI D3DXQuaternionSquadSetup + ( D3DXQUATERNION *pAOut, D3DXQUATERNION *pBOut, D3DXQUATERNION *pCOut, + CONST D3DXQUATERNION *pQ0, CONST D3DXQUATERNION *pQ1, + CONST D3DXQUATERNION *pQ2, CONST D3DXQUATERNION *pQ3 ); + +// Barycentric interpolation. +// Slerp(Slerp(Q1, Q2, f+g), Slerp(Q1, Q3, f+g), g/(f+g)) +D3DXQUATERNION* WINAPI D3DXQuaternionBaryCentric + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ1, + CONST D3DXQUATERNION *pQ2, CONST D3DXQUATERNION *pQ3, + FLOAT f, FLOAT g ); + +#ifdef __cplusplus +} +#endif + + +//-------------------------- +// Plane +//-------------------------- + +// inline + +// ax + by + cz + dw +FLOAT D3DXPlaneDot + ( CONST D3DXPLANE *pP, CONST D3DXVECTOR4 *pV); + +// ax + by + cz + d +FLOAT D3DXPlaneDotCoord + ( CONST D3DXPLANE *pP, CONST D3DXVECTOR3 *pV); + +// ax + by + cz +FLOAT D3DXPlaneDotNormal + ( CONST D3DXPLANE *pP, CONST D3DXVECTOR3 *pV); + +D3DXPLANE* D3DXPlaneScale + (D3DXPLANE *pOut, CONST D3DXPLANE *pP, FLOAT s); + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +// Normalize plane (so that |a,b,c| == 1) +D3DXPLANE* WINAPI D3DXPlaneNormalize + ( D3DXPLANE *pOut, CONST D3DXPLANE *pP); + +// Find the intersection between a plane and a line. If the line is +// parallel to the plane, NULL is returned. +D3DXVECTOR3* WINAPI D3DXPlaneIntersectLine + ( D3DXVECTOR3 *pOut, CONST D3DXPLANE *pP, CONST D3DXVECTOR3 *pV1, + CONST D3DXVECTOR3 *pV2); + +// Construct a plane from a point and a normal +D3DXPLANE* WINAPI D3DXPlaneFromPointNormal + ( D3DXPLANE *pOut, CONST D3DXVECTOR3 *pPoint, CONST D3DXVECTOR3 *pNormal); + +// Construct a plane from 3 points +D3DXPLANE* WINAPI D3DXPlaneFromPoints + ( D3DXPLANE *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2, + CONST D3DXVECTOR3 *pV3); + +// Transform a plane by a matrix. The vector (a,b,c) must be normal. +// M should be the inverse transpose of the transformation desired. +D3DXPLANE* WINAPI D3DXPlaneTransform + ( D3DXPLANE *pOut, CONST D3DXPLANE *pP, CONST D3DXMATRIX *pM ); + +// Transform an array of planes by a matrix. The vectors (a,b,c) must be normal. +// M should be the inverse transpose of the transformation desired. +D3DXPLANE* WINAPI D3DXPlaneTransformArray + ( D3DXPLANE *pOut, UINT OutStride, CONST D3DXPLANE *pP, UINT PStride, CONST D3DXMATRIX *pM, UINT n ); + +#ifdef __cplusplus +} +#endif + + +//-------------------------- +// Color +//-------------------------- + +// inline + +// (1-r, 1-g, 1-b, a) +D3DXCOLOR* D3DXColorNegative + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC); + +D3DXCOLOR* D3DXColorAdd + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2); + +D3DXCOLOR* D3DXColorSubtract + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2); + +D3DXCOLOR* D3DXColorScale + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC, FLOAT s); + +// (r1*r2, g1*g2, b1*b2, a1*a2) +D3DXCOLOR* D3DXColorModulate + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2); + +// Linear interpolation of r,g,b, and a. C1 + s(C2-C1) +D3DXCOLOR* D3DXColorLerp + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2, FLOAT s); + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +// Interpolate r,g,b between desaturated color and color. +// DesaturatedColor + s(Color - DesaturatedColor) +D3DXCOLOR* WINAPI D3DXColorAdjustSaturation + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC, FLOAT s); + +// Interpolate r,g,b between 50% grey and color. Grey + s(Color - Grey) +D3DXCOLOR* WINAPI D3DXColorAdjustContrast + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC, FLOAT c); + +#ifdef __cplusplus +} +#endif + + + + +//-------------------------- +// Misc +//-------------------------- + +#ifdef __cplusplus +extern "C" { +#endif + +// Calculate Fresnel term given the cosine of theta (likely obtained by +// taking the dot of two normals), and the refraction index of the material. +FLOAT WINAPI D3DXFresnelTerm + (FLOAT CosTheta, FLOAT RefractionIndex); + +#ifdef __cplusplus +} +#endif + + + +//=========================================================================== +// +// Matrix Stack +// +//=========================================================================== + +typedef interface ID3DXMatrixStack ID3DXMatrixStack; +typedef interface ID3DXMatrixStack *LPD3DXMATRIXSTACK; + +// {C7885BA7-F990-4fe7-922D-8515E477DD85} +DEFINE_GUID(IID_ID3DXMatrixStack, +0xc7885ba7, 0xf990, 0x4fe7, 0x92, 0x2d, 0x85, 0x15, 0xe4, 0x77, 0xdd, 0x85); + + +#undef INTERFACE +#define INTERFACE ID3DXMatrixStack + +DECLARE_INTERFACE_(ID3DXMatrixStack, IUnknown) +{ + // + // IUnknown methods + // + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + // + // ID3DXMatrixStack methods + // + + // Pops the top of the stack, returns the current top + // *after* popping the top. + STDMETHOD(Pop)(THIS) PURE; + + // Pushes the stack by one, duplicating the current matrix. + STDMETHOD(Push)(THIS) PURE; + + // Loads identity in the current matrix. + STDMETHOD(LoadIdentity)(THIS) PURE; + + // Loads the given matrix into the current matrix + STDMETHOD(LoadMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE; + + // Right-Multiplies the given matrix to the current matrix. + // (transformation is about the current world origin) + STDMETHOD(MultMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE; + + // Left-Multiplies the given matrix to the current matrix + // (transformation is about the local origin of the object) + STDMETHOD(MultMatrixLocal)(THIS_ CONST D3DXMATRIX* pM ) PURE; + + // Right multiply the current matrix with the computed rotation + // matrix, counterclockwise about the given axis with the given angle. + // (rotation is about the current world origin) + STDMETHOD(RotateAxis) + (THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE; + + // Left multiply the current matrix with the computed rotation + // matrix, counterclockwise about the given axis with the given angle. + // (rotation is about the local origin of the object) + STDMETHOD(RotateAxisLocal) + (THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE; + + // Right multiply the current matrix with the computed rotation + // matrix. All angles are counterclockwise. (rotation is about the + // current world origin) + + // The rotation is composed of a yaw around the Y axis, a pitch around + // the X axis, and a roll around the Z axis. + STDMETHOD(RotateYawPitchRoll) + (THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE; + + // Left multiply the current matrix with the computed rotation + // matrix. All angles are counterclockwise. (rotation is about the + // local origin of the object) + + // The rotation is composed of a yaw around the Y axis, a pitch around + // the X axis, and a roll around the Z axis. + STDMETHOD(RotateYawPitchRollLocal) + (THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE; + + // Right multiply the current matrix with the computed scale + // matrix. (transformation is about the current world origin) + STDMETHOD(Scale)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE; + + // Left multiply the current matrix with the computed scale + // matrix. (transformation is about the local origin of the object) + STDMETHOD(ScaleLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE; + + // Right multiply the current matrix with the computed translation + // matrix. (transformation is about the current world origin) + STDMETHOD(Translate)(THIS_ FLOAT x, FLOAT y, FLOAT z ) PURE; + + // Left multiply the current matrix with the computed translation + // matrix. (transformation is about the local origin of the object) + STDMETHOD(TranslateLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE; + + // Obtain the current matrix at the top of the stack + STDMETHOD_(D3DXMATRIX*, GetTop)(THIS) PURE; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +HRESULT WINAPI + D3DXCreateMatrixStack( + DWORD Flags, + LPD3DXMATRIXSTACK* ppStack); + +#ifdef __cplusplus +} +#endif + +//=========================================================================== +// +// Spherical Harmonic Runtime Routines +// +// NOTE: +// * Most of these functions can take the same object as in and out parameters. +// The exceptions are the rotation functions. +// +// * Out parameters are typically also returned as return values, so that +// the output of one function may be used as a parameter to another. +// +//============================================================================ + + +// non-inline +#ifdef __cplusplus +extern "C" { +#endif + +//============================================================================ +// +// Basic Spherical Harmonic math routines +// +//============================================================================ + +#define D3DXSH_MINORDER 2 +#define D3DXSH_MAXORDER 6 + +//============================================================================ +// +// D3DXSHEvalDirection: +// -------------------- +// Evaluates the Spherical Harmonic basis functions +// +// Parameters: +// pOut +// Output SH coefficients - basis function Ylm is stored at l*l + m+l +// This is the pointer that is returned. +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pDir +// Direction to evaluate in - assumed to be normalized +// +//============================================================================ + +FLOAT* WINAPI D3DXSHEvalDirection + ( FLOAT *pOut, UINT Order, CONST D3DXVECTOR3 *pDir ); + +//============================================================================ +// +// D3DXSHRotate: +// -------------------- +// Rotates SH vector by a rotation matrix +// +// Parameters: +// pOut +// Output SH coefficients - basis function Ylm is stored at l*l + m+l +// This is the pointer that is returned (should not alias with pIn.) +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pMatrix +// Matrix used for rotation - rotation sub matrix should be orthogonal +// and have a unit determinant. +// pIn +// Input SH coeffs (rotated), incorect results if this is also output. +// +//============================================================================ + +FLOAT* WINAPI D3DXSHRotate + ( FLOAT *pOut, UINT Order, CONST D3DXMATRIX *pMatrix, CONST FLOAT *pIn ); + +//============================================================================ +// +// D3DXSHRotateZ: +// -------------------- +// Rotates the SH vector in the Z axis by an angle +// +// Parameters: +// pOut +// Output SH coefficients - basis function Ylm is stored at l*l + m+l +// This is the pointer that is returned (should not alias with pIn.) +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// Angle +// Angle in radians to rotate around the Z axis. +// pIn +// Input SH coeffs (rotated), incorect results if this is also output. +// +//============================================================================ + + +FLOAT* WINAPI D3DXSHRotateZ + ( FLOAT *pOut, UINT Order, FLOAT Angle, CONST FLOAT *pIn ); + +//============================================================================ +// +// D3DXSHAdd: +// -------------------- +// Adds two SH vectors, pOut[i] = pA[i] + pB[i]; +// +// Parameters: +// pOut +// Output SH coefficients - basis function Ylm is stored at l*l + m+l +// This is the pointer that is returned. +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pA +// Input SH coeffs. +// pB +// Input SH coeffs (second vector.) +// +//============================================================================ + +FLOAT* WINAPI D3DXSHAdd + ( FLOAT *pOut, UINT Order, CONST FLOAT *pA, CONST FLOAT *pB ); + +//============================================================================ +// +// D3DXSHScale: +// -------------------- +// Adds two SH vectors, pOut[i] = pA[i]*Scale; +// +// Parameters: +// pOut +// Output SH coefficients - basis function Ylm is stored at l*l + m+l +// This is the pointer that is returned. +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pIn +// Input SH coeffs. +// Scale +// Scale factor. +// +//============================================================================ + +FLOAT* WINAPI D3DXSHScale + ( FLOAT *pOut, UINT Order, CONST FLOAT *pIn, CONST FLOAT Scale ); + +//============================================================================ +// +// D3DXSHDot: +// -------------------- +// Computes the dot product of two SH vectors +// +// Parameters: +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pA +// Input SH coeffs. +// pB +// Second set of input SH coeffs. +// +//============================================================================ + +FLOAT WINAPI D3DXSHDot + ( UINT Order, CONST FLOAT *pA, CONST FLOAT *pB ); + +//============================================================================ +// +// D3DXSHMultiply[O]: +// -------------------- +// Computes the product of two functions represented using SH (f and g), where: +// pOut[i] = int(y_i(s) * f(s) * g(s)), where y_i(s) is the ith SH basis +// function, f(s) and g(s) are SH functions (sum_i(y_i(s)*c_i)). The order O +// determines the lengths of the arrays, where there should always be O^2 +// coefficients. In general the product of two SH functions of order O generates +// and SH function of order 2*O - 1, but we truncate the result. This means +// that the product commutes (f*g == g*f) but doesn't associate +// (f*(g*h) != (f*g)*h. +// +// Parameters: +// pOut +// Output SH coefficients - basis function Ylm is stored at l*l + m+l +// This is the pointer that is returned. +// pF +// Input SH coeffs for first function. +// pG +// Second set of input SH coeffs. +// +//============================================================================ + +FLOAT* WINAPI D3DXSHMultiply2( FLOAT *pOut, CONST FLOAT *pF, CONST FLOAT *pG); +FLOAT* WINAPI D3DXSHMultiply3( FLOAT *pOut, CONST FLOAT *pF, CONST FLOAT *pG); +FLOAT* WINAPI D3DXSHMultiply4( FLOAT *pOut, CONST FLOAT *pF, CONST FLOAT *pG); +FLOAT* WINAPI D3DXSHMultiply5( FLOAT *pOut, CONST FLOAT *pF, CONST FLOAT *pG); +FLOAT* WINAPI D3DXSHMultiply6( FLOAT *pOut, CONST FLOAT *pF, CONST FLOAT *pG); + + +//============================================================================ +// +// Basic Spherical Harmonic lighting routines +// +//============================================================================ + +//============================================================================ +// +// D3DXSHEvalDirectionalLight: +// -------------------- +// Evaluates a directional light and returns spectral SH data. The output +// vector is computed so that if the intensity of R/G/B is unit the resulting +// exit radiance of a point directly under the light on a diffuse object with +// an albedo of 1 would be 1.0. This will compute 3 spectral samples, pROut +// has to be specified, while pGout and pBout are optional. +// +// Parameters: +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pDir +// Direction light is coming from (assumed to be normalized.) +// RIntensity +// Red intensity of light. +// GIntensity +// Green intensity of light. +// BIntensity +// Blue intensity of light. +// pROut +// Output SH vector for Red. +// pGOut +// Output SH vector for Green (optional.) +// pBOut +// Output SH vector for Blue (optional.) +// +//============================================================================ + +HRESULT WINAPI D3DXSHEvalDirectionalLight + ( UINT Order, CONST D3DXVECTOR3 *pDir, + FLOAT RIntensity, FLOAT GIntensity, FLOAT BIntensity, + FLOAT *pROut, FLOAT *pGOut, FLOAT *pBOut ); + +//============================================================================ +// +// D3DXSHEvalSphericalLight: +// -------------------- +// Evaluates a spherical light and returns spectral SH data. There is no +// normalization of the intensity of the light like there is for directional +// lights, care has to be taken when specifiying the intensities. This will +// compute 3 spectral samples, pROut has to be specified, while pGout and +// pBout are optional. +// +// Parameters: +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pPos +// Position of light - reciever is assumed to be at the origin. +// Radius +// Radius of the spherical light source. +// RIntensity +// Red intensity of light. +// GIntensity +// Green intensity of light. +// BIntensity +// Blue intensity of light. +// pROut +// Output SH vector for Red. +// pGOut +// Output SH vector for Green (optional.) +// pBOut +// Output SH vector for Blue (optional.) +// +//============================================================================ + +HRESULT WINAPI D3DXSHEvalSphericalLight + ( UINT Order, CONST D3DXVECTOR3 *pPos, FLOAT Radius, + FLOAT RIntensity, FLOAT GIntensity, FLOAT BIntensity, + FLOAT *pROut, FLOAT *pGOut, FLOAT *pBOut ); + +//============================================================================ +// +// D3DXSHEvalConeLight: +// -------------------- +// Evaluates a light that is a cone of constant intensity and returns spectral +// SH data. The output vector is computed so that if the intensity of R/G/B is +// unit the resulting exit radiance of a point directly under the light oriented +// in the cone direction on a diffuse object with an albedo of 1 would be 1.0. +// This will compute 3 spectral samples, pROut has to be specified, while pGout +// and pBout are optional. +// +// Parameters: +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pDir +// Direction light is coming from (assumed to be normalized.) +// Radius +// Radius of cone in radians. +// RIntensity +// Red intensity of light. +// GIntensity +// Green intensity of light. +// BIntensity +// Blue intensity of light. +// pROut +// Output SH vector for Red. +// pGOut +// Output SH vector for Green (optional.) +// pBOut +// Output SH vector for Blue (optional.) +// +//============================================================================ + +HRESULT WINAPI D3DXSHEvalConeLight + ( UINT Order, CONST D3DXVECTOR3 *pDir, FLOAT Radius, + FLOAT RIntensity, FLOAT GIntensity, FLOAT BIntensity, + FLOAT *pROut, FLOAT *pGOut, FLOAT *pBOut ); + +//============================================================================ +// +// D3DXSHEvalHemisphereLight: +// -------------------- +// Evaluates a light that is a linear interpolant between two colors over the +// sphere. The interpolant is linear along the axis of the two points, not +// over the surface of the sphere (ie: if the axis was (0,0,1) it is linear in +// Z, not in the azimuthal angle.) The resulting spherical lighting function +// is normalized so that a point on a perfectly diffuse surface with no +// shadowing and a normal pointed in the direction pDir would result in exit +// radiance with a value of 1 if the top color was white and the bottom color +// was black. This is a very simple model where Top represents the intensity +// of the "sky" and Bottom represents the intensity of the "ground". +// +// Parameters: +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pDir +// Axis of the hemisphere. +// Top +// Color of the upper hemisphere. +// Bottom +// Color of the lower hemisphere. +// pROut +// Output SH vector for Red. +// pGOut +// Output SH vector for Green +// pBOut +// Output SH vector for Blue +// +//============================================================================ + +HRESULT WINAPI D3DXSHEvalHemisphereLight + ( UINT Order, CONST D3DXVECTOR3 *pDir, D3DXCOLOR Top, D3DXCOLOR Bottom, + FLOAT *pROut, FLOAT *pGOut, FLOAT *pBOut ); + +//============================================================================ +// +// Basic Spherical Harmonic projection routines +// +//============================================================================ + +//============================================================================ +// +// D3DXSHProjectCubeMap: +// -------------------- +// Projects a function represented on a cube map into spherical harmonics. +// +// Parameters: +// Order +// Order of the SH evaluation, generates Order^2 coefs, degree is Order-1 +// pCubeMap +// CubeMap that is going to be projected into spherical harmonics +// pROut +// Output SH vector for Red. +// pGOut +// Output SH vector for Green +// pBOut +// Output SH vector for Blue +// +//============================================================================ + +HRESULT WINAPI D3DXSHProjectCubeMap + ( UINT uOrder, LPDIRECT3DCUBETEXTURE9 pCubeMap, + FLOAT *pROut, FLOAT *pGOut, FLOAT *pBOut ); + + +#ifdef __cplusplus +} +#endif + + +#include "d3dx9math.inl" + +#if _MSC_VER >= 1200 +#pragma warning(pop) +#else +#pragma warning(default:4201) +#endif + +#endif // __D3DX9MATH_H__ + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9math.inl b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9math.inl new file mode 100644 index 0000000000..a3652ed450 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9math.inl @@ -0,0 +1,2251 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9math.inl +// Content: D3DX math inline functions +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef __D3DX9MATH_INL__ +#define __D3DX9MATH_INL__ + +//=========================================================================== +// +// Inline Class Methods +// +//=========================================================================== + +#ifdef __cplusplus + +//-------------------------- +// Float16 +//-------------------------- + +D3DXINLINE +D3DXFLOAT16::D3DXFLOAT16( FLOAT f ) +{ + D3DXFloat32To16Array(this, &f, 1); +} + +D3DXINLINE +D3DXFLOAT16::D3DXFLOAT16( CONST D3DXFLOAT16& f ) +{ + value = f.value; +} + +// casting +D3DXINLINE +D3DXFLOAT16::operator FLOAT () +{ + FLOAT f; + D3DXFloat16To32Array(&f, this, 1); + return f; +} + +// binary operators +D3DXINLINE BOOL +D3DXFLOAT16::operator == ( CONST D3DXFLOAT16& f ) const +{ + return value == f.value; +} + +D3DXINLINE BOOL +D3DXFLOAT16::operator != ( CONST D3DXFLOAT16& f ) const +{ + return value != f.value; +} + + +//-------------------------- +// 2D Vector +//-------------------------- + +D3DXINLINE +D3DXVECTOR2::D3DXVECTOR2( CONST FLOAT *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + x = pf[0]; + y = pf[1]; +} + +D3DXINLINE +D3DXVECTOR2::D3DXVECTOR2( CONST D3DXFLOAT16 *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&x, pf, 2); +} + +D3DXINLINE +D3DXVECTOR2::D3DXVECTOR2( FLOAT fx, FLOAT fy ) +{ + x = fx; + y = fy; +} + + +// casting +D3DXINLINE +D3DXVECTOR2::operator FLOAT* () +{ + return (FLOAT *) &x; +} + +D3DXINLINE +D3DXVECTOR2::operator CONST FLOAT* () const +{ + return (CONST FLOAT *) &x; +} + + +// assignment operators +D3DXINLINE D3DXVECTOR2& +D3DXVECTOR2::operator += ( CONST D3DXVECTOR2& v ) +{ + x += v.x; + y += v.y; + return *this; +} + +D3DXINLINE D3DXVECTOR2& +D3DXVECTOR2::operator -= ( CONST D3DXVECTOR2& v ) +{ + x -= v.x; + y -= v.y; + return *this; +} + +D3DXINLINE D3DXVECTOR2& +D3DXVECTOR2::operator *= ( FLOAT f ) +{ + x *= f; + y *= f; + return *this; +} + +D3DXINLINE D3DXVECTOR2& +D3DXVECTOR2::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + x *= fInv; + y *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXVECTOR2 +D3DXVECTOR2::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXVECTOR2 +D3DXVECTOR2::operator - () const +{ + return D3DXVECTOR2(-x, -y); +} + + +// binary operators +D3DXINLINE D3DXVECTOR2 +D3DXVECTOR2::operator + ( CONST D3DXVECTOR2& v ) const +{ + return D3DXVECTOR2(x + v.x, y + v.y); +} + +D3DXINLINE D3DXVECTOR2 +D3DXVECTOR2::operator - ( CONST D3DXVECTOR2& v ) const +{ + return D3DXVECTOR2(x - v.x, y - v.y); +} + +D3DXINLINE D3DXVECTOR2 +D3DXVECTOR2::operator * ( FLOAT f ) const +{ + return D3DXVECTOR2(x * f, y * f); +} + +D3DXINLINE D3DXVECTOR2 +D3DXVECTOR2::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXVECTOR2(x * fInv, y * fInv); +} + +D3DXINLINE D3DXVECTOR2 +operator * ( FLOAT f, CONST D3DXVECTOR2& v ) +{ + return D3DXVECTOR2(f * v.x, f * v.y); +} + +D3DXINLINE BOOL +D3DXVECTOR2::operator == ( CONST D3DXVECTOR2& v ) const +{ + return x == v.x && y == v.y; +} + +D3DXINLINE BOOL +D3DXVECTOR2::operator != ( CONST D3DXVECTOR2& v ) const +{ + return x != v.x || y != v.y; +} + + + +//-------------------------- +// 2D Vector (16 bit) +//-------------------------- + +D3DXINLINE +D3DXVECTOR2_16F::D3DXVECTOR2_16F( CONST FLOAT *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat32To16Array(&x, pf, 2); +} + +D3DXINLINE +D3DXVECTOR2_16F::D3DXVECTOR2_16F( CONST D3DXFLOAT16 *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + *((DWORD *) &x) = *((DWORD *) &pf[0]); +} + +D3DXINLINE +D3DXVECTOR2_16F::D3DXVECTOR2_16F( CONST D3DXFLOAT16 &fx, CONST D3DXFLOAT16 &fy ) +{ + x = fx; + y = fy; +} + + +// casting +D3DXINLINE +D3DXVECTOR2_16F::operator D3DXFLOAT16* () +{ + return (D3DXFLOAT16*) &x; +} + +D3DXINLINE +D3DXVECTOR2_16F::operator CONST D3DXFLOAT16* () const +{ + return (CONST D3DXFLOAT16*) &x; +} + + +// binary operators +D3DXINLINE BOOL +D3DXVECTOR2_16F::operator == ( CONST D3DXVECTOR2_16F &v ) const +{ + return *((DWORD *) &x) == *((DWORD *) &v.x); +} + +D3DXINLINE BOOL +D3DXVECTOR2_16F::operator != ( CONST D3DXVECTOR2_16F &v ) const +{ + return *((DWORD *) &x) != *((DWORD *) &v.x); +} + + +//-------------------------- +// 3D Vector +//-------------------------- +D3DXINLINE +D3DXVECTOR3::D3DXVECTOR3( CONST FLOAT *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + x = pf[0]; + y = pf[1]; + z = pf[2]; +} + +D3DXINLINE +D3DXVECTOR3::D3DXVECTOR3( CONST D3DVECTOR& v ) +{ + x = v.x; + y = v.y; + z = v.z; +} + +D3DXINLINE +D3DXVECTOR3::D3DXVECTOR3( CONST D3DXFLOAT16 *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&x, pf, 3); +} + +D3DXINLINE +D3DXVECTOR3::D3DXVECTOR3( FLOAT fx, FLOAT fy, FLOAT fz ) +{ + x = fx; + y = fy; + z = fz; +} + + +// casting +D3DXINLINE +D3DXVECTOR3::operator FLOAT* () +{ + return (FLOAT *) &x; +} + +D3DXINLINE +D3DXVECTOR3::operator CONST FLOAT* () const +{ + return (CONST FLOAT *) &x; +} + + +// assignment operators +D3DXINLINE D3DXVECTOR3& +D3DXVECTOR3::operator += ( CONST D3DXVECTOR3& v ) +{ + x += v.x; + y += v.y; + z += v.z; + return *this; +} + +D3DXINLINE D3DXVECTOR3& +D3DXVECTOR3::operator -= ( CONST D3DXVECTOR3& v ) +{ + x -= v.x; + y -= v.y; + z -= v.z; + return *this; +} + +D3DXINLINE D3DXVECTOR3& +D3DXVECTOR3::operator *= ( FLOAT f ) +{ + x *= f; + y *= f; + z *= f; + return *this; +} + +D3DXINLINE D3DXVECTOR3& +D3DXVECTOR3::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + x *= fInv; + y *= fInv; + z *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXVECTOR3 +D3DXVECTOR3::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXVECTOR3 +D3DXVECTOR3::operator - () const +{ + return D3DXVECTOR3(-x, -y, -z); +} + + +// binary operators +D3DXINLINE D3DXVECTOR3 +D3DXVECTOR3::operator + ( CONST D3DXVECTOR3& v ) const +{ + return D3DXVECTOR3(x + v.x, y + v.y, z + v.z); +} + +D3DXINLINE D3DXVECTOR3 +D3DXVECTOR3::operator - ( CONST D3DXVECTOR3& v ) const +{ + return D3DXVECTOR3(x - v.x, y - v.y, z - v.z); +} + +D3DXINLINE D3DXVECTOR3 +D3DXVECTOR3::operator * ( FLOAT f ) const +{ + return D3DXVECTOR3(x * f, y * f, z * f); +} + +D3DXINLINE D3DXVECTOR3 +D3DXVECTOR3::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXVECTOR3(x * fInv, y * fInv, z * fInv); +} + + +D3DXINLINE D3DXVECTOR3 +operator * ( FLOAT f, CONST struct D3DXVECTOR3& v ) +{ + return D3DXVECTOR3(f * v.x, f * v.y, f * v.z); +} + + +D3DXINLINE BOOL +D3DXVECTOR3::operator == ( CONST D3DXVECTOR3& v ) const +{ + return x == v.x && y == v.y && z == v.z; +} + +D3DXINLINE BOOL +D3DXVECTOR3::operator != ( CONST D3DXVECTOR3& v ) const +{ + return x != v.x || y != v.y || z != v.z; +} + + + +//-------------------------- +// 3D Vector (16 bit) +//-------------------------- + +D3DXINLINE +D3DXVECTOR3_16F::D3DXVECTOR3_16F( CONST FLOAT *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat32To16Array(&x, pf, 3); +} + +D3DXINLINE +D3DXVECTOR3_16F::D3DXVECTOR3_16F( CONST D3DVECTOR& v ) +{ + D3DXFloat32To16Array(&x, &v.x, 1); + D3DXFloat32To16Array(&y, &v.y, 1); + D3DXFloat32To16Array(&z, &v.z, 1); +} + +D3DXINLINE +D3DXVECTOR3_16F::D3DXVECTOR3_16F( CONST D3DXFLOAT16 *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + *((DWORD *) &x) = *((DWORD *) &pf[0]); + *((WORD *) &z) = *((WORD *) &pf[2]); +} + +D3DXINLINE +D3DXVECTOR3_16F::D3DXVECTOR3_16F( CONST D3DXFLOAT16 &fx, CONST D3DXFLOAT16 &fy, CONST D3DXFLOAT16 &fz ) +{ + x = fx; + y = fy; + z = fz; +} + + +// casting +D3DXINLINE +D3DXVECTOR3_16F::operator D3DXFLOAT16* () +{ + return (D3DXFLOAT16*) &x; +} + +D3DXINLINE +D3DXVECTOR3_16F::operator CONST D3DXFLOAT16* () const +{ + return (CONST D3DXFLOAT16*) &x; +} + + +// binary operators +D3DXINLINE BOOL +D3DXVECTOR3_16F::operator == ( CONST D3DXVECTOR3_16F &v ) const +{ + return *((DWORD *) &x) == *((DWORD *) &v.x) && + *((WORD *) &z) == *((WORD *) &v.z); +} + +D3DXINLINE BOOL +D3DXVECTOR3_16F::operator != ( CONST D3DXVECTOR3_16F &v ) const +{ + return *((DWORD *) &x) != *((DWORD *) &v.x) || + *((WORD *) &z) != *((WORD *) &v.z); +} + + +//-------------------------- +// 4D Vector +//-------------------------- +D3DXINLINE +D3DXVECTOR4::D3DXVECTOR4( CONST FLOAT *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + x = pf[0]; + y = pf[1]; + z = pf[2]; + w = pf[3]; +} + +D3DXINLINE +D3DXVECTOR4::D3DXVECTOR4( CONST D3DXFLOAT16 *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&x, pf, 4); +} + +D3DXINLINE +D3DXVECTOR4::D3DXVECTOR4( CONST D3DVECTOR& v, FLOAT f ) +{ + x = v.x; + y = v.y; + z = v.z; + w = f; +} + +D3DXINLINE +D3DXVECTOR4::D3DXVECTOR4( FLOAT fx, FLOAT fy, FLOAT fz, FLOAT fw ) +{ + x = fx; + y = fy; + z = fz; + w = fw; +} + + +// casting +D3DXINLINE +D3DXVECTOR4::operator FLOAT* () +{ + return (FLOAT *) &x; +} + +D3DXINLINE +D3DXVECTOR4::operator CONST FLOAT* () const +{ + return (CONST FLOAT *) &x; +} + + +// assignment operators +D3DXINLINE D3DXVECTOR4& +D3DXVECTOR4::operator += ( CONST D3DXVECTOR4& v ) +{ + x += v.x; + y += v.y; + z += v.z; + w += v.w; + return *this; +} + +D3DXINLINE D3DXVECTOR4& +D3DXVECTOR4::operator -= ( CONST D3DXVECTOR4& v ) +{ + x -= v.x; + y -= v.y; + z -= v.z; + w -= v.w; + return *this; +} + +D3DXINLINE D3DXVECTOR4& +D3DXVECTOR4::operator *= ( FLOAT f ) +{ + x *= f; + y *= f; + z *= f; + w *= f; + return *this; +} + +D3DXINLINE D3DXVECTOR4& +D3DXVECTOR4::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + x *= fInv; + y *= fInv; + z *= fInv; + w *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXVECTOR4 +D3DXVECTOR4::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXVECTOR4 +D3DXVECTOR4::operator - () const +{ + return D3DXVECTOR4(-x, -y, -z, -w); +} + + +// binary operators +D3DXINLINE D3DXVECTOR4 +D3DXVECTOR4::operator + ( CONST D3DXVECTOR4& v ) const +{ + return D3DXVECTOR4(x + v.x, y + v.y, z + v.z, w + v.w); +} + +D3DXINLINE D3DXVECTOR4 +D3DXVECTOR4::operator - ( CONST D3DXVECTOR4& v ) const +{ + return D3DXVECTOR4(x - v.x, y - v.y, z - v.z, w - v.w); +} + +D3DXINLINE D3DXVECTOR4 +D3DXVECTOR4::operator * ( FLOAT f ) const +{ + return D3DXVECTOR4(x * f, y * f, z * f, w * f); +} + +D3DXINLINE D3DXVECTOR4 +D3DXVECTOR4::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXVECTOR4(x * fInv, y * fInv, z * fInv, w * fInv); +} + +D3DXINLINE D3DXVECTOR4 +operator * ( FLOAT f, CONST D3DXVECTOR4& v ) +{ + return D3DXVECTOR4(f * v.x, f * v.y, f * v.z, f * v.w); +} + + +D3DXINLINE BOOL +D3DXVECTOR4::operator == ( CONST D3DXVECTOR4& v ) const +{ + return x == v.x && y == v.y && z == v.z && w == v.w; +} + +D3DXINLINE BOOL +D3DXVECTOR4::operator != ( CONST D3DXVECTOR4& v ) const +{ + return x != v.x || y != v.y || z != v.z || w != v.w; +} + + + +//-------------------------- +// 4D Vector (16 bit) +//-------------------------- + +D3DXINLINE +D3DXVECTOR4_16F::D3DXVECTOR4_16F( CONST FLOAT *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat32To16Array(&x, pf, 4); +} + +D3DXINLINE +D3DXVECTOR4_16F::D3DXVECTOR4_16F( CONST D3DXFLOAT16 *pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + *((DWORD *) &x) = *((DWORD *) &pf[0]); + *((DWORD *) &z) = *((DWORD *) &pf[2]); +} + +D3DXINLINE +D3DXVECTOR4_16F::D3DXVECTOR4_16F( CONST D3DXVECTOR3_16F& v, CONST D3DXFLOAT16& f ) +{ + x = v.x; + y = v.y; + z = v.z; + w = f; +} + +D3DXINLINE +D3DXVECTOR4_16F::D3DXVECTOR4_16F( CONST D3DXFLOAT16 &fx, CONST D3DXFLOAT16 &fy, CONST D3DXFLOAT16 &fz, CONST D3DXFLOAT16 &fw ) +{ + x = fx; + y = fy; + z = fz; + w = fw; +} + + +// casting +D3DXINLINE +D3DXVECTOR4_16F::operator D3DXFLOAT16* () +{ + return (D3DXFLOAT16*) &x; +} + +D3DXINLINE +D3DXVECTOR4_16F::operator CONST D3DXFLOAT16* () const +{ + return (CONST D3DXFLOAT16*) &x; +} + + +// binary operators +D3DXINLINE BOOL +D3DXVECTOR4_16F::operator == ( CONST D3DXVECTOR4_16F &v ) const +{ + return *((DWORD *) &x) == *((DWORD *) &v.x) && + *((DWORD *) &z) == *((DWORD *) &v.z); +} + +D3DXINLINE BOOL +D3DXVECTOR4_16F::operator != ( CONST D3DXVECTOR4_16F &v ) const +{ + return *((DWORD *) &x) != *((DWORD *) &v.x) || + *((DWORD *) &z) != *((DWORD *) &v.z); +} + + +//-------------------------- +// Matrix +//-------------------------- +D3DXINLINE +D3DXMATRIX::D3DXMATRIX( CONST FLOAT* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + memcpy(&_11, pf, sizeof(D3DXMATRIX)); +} + +D3DXINLINE +D3DXMATRIX::D3DXMATRIX( CONST D3DMATRIX& mat ) +{ + memcpy(&_11, &mat, sizeof(D3DXMATRIX)); +} + +D3DXINLINE +D3DXMATRIX::D3DXMATRIX( CONST D3DXFLOAT16* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&_11, pf, 16); +} + +D3DXINLINE +D3DXMATRIX::D3DXMATRIX( FLOAT f11, FLOAT f12, FLOAT f13, FLOAT f14, + FLOAT f21, FLOAT f22, FLOAT f23, FLOAT f24, + FLOAT f31, FLOAT f32, FLOAT f33, FLOAT f34, + FLOAT f41, FLOAT f42, FLOAT f43, FLOAT f44 ) +{ + _11 = f11; _12 = f12; _13 = f13; _14 = f14; + _21 = f21; _22 = f22; _23 = f23; _24 = f24; + _31 = f31; _32 = f32; _33 = f33; _34 = f34; + _41 = f41; _42 = f42; _43 = f43; _44 = f44; +} + + + +// access grants +D3DXINLINE FLOAT& +D3DXMATRIX::operator () ( UINT iRow, UINT iCol ) +{ + return m[iRow][iCol]; +} + +D3DXINLINE FLOAT +D3DXMATRIX::operator () ( UINT iRow, UINT iCol ) const +{ + return m[iRow][iCol]; +} + + +// casting operators +D3DXINLINE +D3DXMATRIX::operator FLOAT* () +{ + return (FLOAT *) &_11; +} + +D3DXINLINE +D3DXMATRIX::operator CONST FLOAT* () const +{ + return (CONST FLOAT *) &_11; +} + + +// assignment operators +D3DXINLINE D3DXMATRIX& +D3DXMATRIX::operator *= ( CONST D3DXMATRIX& mat ) +{ + D3DXMatrixMultiply(this, this, &mat); + return *this; +} + +D3DXINLINE D3DXMATRIX& +D3DXMATRIX::operator += ( CONST D3DXMATRIX& mat ) +{ + _11 += mat._11; _12 += mat._12; _13 += mat._13; _14 += mat._14; + _21 += mat._21; _22 += mat._22; _23 += mat._23; _24 += mat._24; + _31 += mat._31; _32 += mat._32; _33 += mat._33; _34 += mat._34; + _41 += mat._41; _42 += mat._42; _43 += mat._43; _44 += mat._44; + return *this; +} + +D3DXINLINE D3DXMATRIX& +D3DXMATRIX::operator -= ( CONST D3DXMATRIX& mat ) +{ + _11 -= mat._11; _12 -= mat._12; _13 -= mat._13; _14 -= mat._14; + _21 -= mat._21; _22 -= mat._22; _23 -= mat._23; _24 -= mat._24; + _31 -= mat._31; _32 -= mat._32; _33 -= mat._33; _34 -= mat._34; + _41 -= mat._41; _42 -= mat._42; _43 -= mat._43; _44 -= mat._44; + return *this; +} + +D3DXINLINE D3DXMATRIX& +D3DXMATRIX::operator *= ( FLOAT f ) +{ + _11 *= f; _12 *= f; _13 *= f; _14 *= f; + _21 *= f; _22 *= f; _23 *= f; _24 *= f; + _31 *= f; _32 *= f; _33 *= f; _34 *= f; + _41 *= f; _42 *= f; _43 *= f; _44 *= f; + return *this; +} + +D3DXINLINE D3DXMATRIX& +D3DXMATRIX::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + _11 *= fInv; _12 *= fInv; _13 *= fInv; _14 *= fInv; + _21 *= fInv; _22 *= fInv; _23 *= fInv; _24 *= fInv; + _31 *= fInv; _32 *= fInv; _33 *= fInv; _34 *= fInv; + _41 *= fInv; _42 *= fInv; _43 *= fInv; _44 *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator - () const +{ + return D3DXMATRIX(-_11, -_12, -_13, -_14, + -_21, -_22, -_23, -_24, + -_31, -_32, -_33, -_34, + -_41, -_42, -_43, -_44); +} + + +// binary operators +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator * ( CONST D3DXMATRIX& mat ) const +{ + D3DXMATRIX matT; + D3DXMatrixMultiply(&matT, this, &mat); + return matT; +} + +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator + ( CONST D3DXMATRIX& mat ) const +{ + return D3DXMATRIX(_11 + mat._11, _12 + mat._12, _13 + mat._13, _14 + mat._14, + _21 + mat._21, _22 + mat._22, _23 + mat._23, _24 + mat._24, + _31 + mat._31, _32 + mat._32, _33 + mat._33, _34 + mat._34, + _41 + mat._41, _42 + mat._42, _43 + mat._43, _44 + mat._44); +} + +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator - ( CONST D3DXMATRIX& mat ) const +{ + return D3DXMATRIX(_11 - mat._11, _12 - mat._12, _13 - mat._13, _14 - mat._14, + _21 - mat._21, _22 - mat._22, _23 - mat._23, _24 - mat._24, + _31 - mat._31, _32 - mat._32, _33 - mat._33, _34 - mat._34, + _41 - mat._41, _42 - mat._42, _43 - mat._43, _44 - mat._44); +} + +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator * ( FLOAT f ) const +{ + return D3DXMATRIX(_11 * f, _12 * f, _13 * f, _14 * f, + _21 * f, _22 * f, _23 * f, _24 * f, + _31 * f, _32 * f, _33 * f, _34 * f, + _41 * f, _42 * f, _43 * f, _44 * f); +} + +D3DXINLINE D3DXMATRIX +D3DXMATRIX::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXMATRIX(_11 * fInv, _12 * fInv, _13 * fInv, _14 * fInv, + _21 * fInv, _22 * fInv, _23 * fInv, _24 * fInv, + _31 * fInv, _32 * fInv, _33 * fInv, _34 * fInv, + _41 * fInv, _42 * fInv, _43 * fInv, _44 * fInv); +} + + +D3DXINLINE D3DXMATRIX +operator * ( FLOAT f, CONST D3DXMATRIX& mat ) +{ + return D3DXMATRIX(f * mat._11, f * mat._12, f * mat._13, f * mat._14, + f * mat._21, f * mat._22, f * mat._23, f * mat._24, + f * mat._31, f * mat._32, f * mat._33, f * mat._34, + f * mat._41, f * mat._42, f * mat._43, f * mat._44); +} + + +D3DXINLINE BOOL +D3DXMATRIX::operator == ( CONST D3DXMATRIX& mat ) const +{ + return 0 == memcmp(this, &mat, sizeof(D3DXMATRIX)); +} + +D3DXINLINE BOOL +D3DXMATRIX::operator != ( CONST D3DXMATRIX& mat ) const +{ + return 0 != memcmp(this, &mat, sizeof(D3DXMATRIX)); +} + + + +//-------------------------- +// Aligned Matrices +//-------------------------- + +D3DXINLINE +_D3DXMATRIXA16::_D3DXMATRIXA16( CONST FLOAT* f ) : + D3DXMATRIX( f ) +{ +} + +D3DXINLINE +_D3DXMATRIXA16::_D3DXMATRIXA16( CONST D3DMATRIX& m ) : + D3DXMATRIX( m ) +{ +} + +D3DXINLINE +_D3DXMATRIXA16::_D3DXMATRIXA16( CONST D3DXFLOAT16* f ) : + D3DXMATRIX( f ) +{ +} + +D3DXINLINE +_D3DXMATRIXA16::_D3DXMATRIXA16( FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14, + FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24, + FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34, + FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44 ) : + D3DXMATRIX(_11, _12, _13, _14, + _21, _22, _23, _24, + _31, _32, _33, _34, + _41, _42, _43, _44) +{ +} + +#ifndef SIZE_MAX +#define SIZE_MAX ((SIZE_T)-1) +#endif + +D3DXINLINE void* +_D3DXMATRIXA16::operator new( size_t s ) +{ + if (s > (SIZE_MAX-16)) + return NULL; + LPBYTE p = ::new BYTE[s + 16]; + if (p) + { + BYTE offset = (BYTE)(16 - ((UINT_PTR)p & 15)); + p += offset; + p[-1] = offset; + } + return p; +} + +D3DXINLINE void* +_D3DXMATRIXA16::operator new[]( size_t s ) +{ + if (s > (SIZE_MAX-16)) + return NULL; + LPBYTE p = ::new BYTE[s + 16]; + if (p) + { + BYTE offset = (BYTE)(16 - ((UINT_PTR)p & 15)); + p += offset; + p[-1] = offset; + } + return p; +} + +D3DXINLINE void +_D3DXMATRIXA16::operator delete(void* p) +{ + if(p) + { + BYTE* pb = static_cast(p); + pb -= pb[-1]; + ::delete [] pb; + } +} + +D3DXINLINE void +_D3DXMATRIXA16::operator delete[](void* p) +{ + if(p) + { + BYTE* pb = static_cast(p); + pb -= pb[-1]; + ::delete [] pb; + } +} + +D3DXINLINE _D3DXMATRIXA16& +_D3DXMATRIXA16::operator=(CONST D3DXMATRIX& rhs) +{ + memcpy(&_11, &rhs, sizeof(D3DXMATRIX)); + return *this; +} + + +//-------------------------- +// Quaternion +//-------------------------- + +D3DXINLINE +D3DXQUATERNION::D3DXQUATERNION( CONST FLOAT* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + x = pf[0]; + y = pf[1]; + z = pf[2]; + w = pf[3]; +} + +D3DXINLINE +D3DXQUATERNION::D3DXQUATERNION( CONST D3DXFLOAT16* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&x, pf, 4); +} + +D3DXINLINE +D3DXQUATERNION::D3DXQUATERNION( FLOAT fx, FLOAT fy, FLOAT fz, FLOAT fw ) +{ + x = fx; + y = fy; + z = fz; + w = fw; +} + + +// casting +D3DXINLINE +D3DXQUATERNION::operator FLOAT* () +{ + return (FLOAT *) &x; +} + +D3DXINLINE +D3DXQUATERNION::operator CONST FLOAT* () const +{ + return (CONST FLOAT *) &x; +} + + +// assignment operators +D3DXINLINE D3DXQUATERNION& +D3DXQUATERNION::operator += ( CONST D3DXQUATERNION& q ) +{ + x += q.x; + y += q.y; + z += q.z; + w += q.w; + return *this; +} + +D3DXINLINE D3DXQUATERNION& +D3DXQUATERNION::operator -= ( CONST D3DXQUATERNION& q ) +{ + x -= q.x; + y -= q.y; + z -= q.z; + w -= q.w; + return *this; +} + +D3DXINLINE D3DXQUATERNION& +D3DXQUATERNION::operator *= ( CONST D3DXQUATERNION& q ) +{ + D3DXQuaternionMultiply(this, this, &q); + return *this; +} + +D3DXINLINE D3DXQUATERNION& +D3DXQUATERNION::operator *= ( FLOAT f ) +{ + x *= f; + y *= f; + z *= f; + w *= f; + return *this; +} + +D3DXINLINE D3DXQUATERNION& +D3DXQUATERNION::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + x *= fInv; + y *= fInv; + z *= fInv; + w *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator - () const +{ + return D3DXQUATERNION(-x, -y, -z, -w); +} + + +// binary operators +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator + ( CONST D3DXQUATERNION& q ) const +{ + return D3DXQUATERNION(x + q.x, y + q.y, z + q.z, w + q.w); +} + +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator - ( CONST D3DXQUATERNION& q ) const +{ + return D3DXQUATERNION(x - q.x, y - q.y, z - q.z, w - q.w); +} + +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator * ( CONST D3DXQUATERNION& q ) const +{ + D3DXQUATERNION qT; + D3DXQuaternionMultiply(&qT, this, &q); + return qT; +} + +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator * ( FLOAT f ) const +{ + return D3DXQUATERNION(x * f, y * f, z * f, w * f); +} + +D3DXINLINE D3DXQUATERNION +D3DXQUATERNION::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXQUATERNION(x * fInv, y * fInv, z * fInv, w * fInv); +} + + +D3DXINLINE D3DXQUATERNION +operator * (FLOAT f, CONST D3DXQUATERNION& q ) +{ + return D3DXQUATERNION(f * q.x, f * q.y, f * q.z, f * q.w); +} + + +D3DXINLINE BOOL +D3DXQUATERNION::operator == ( CONST D3DXQUATERNION& q ) const +{ + return x == q.x && y == q.y && z == q.z && w == q.w; +} + +D3DXINLINE BOOL +D3DXQUATERNION::operator != ( CONST D3DXQUATERNION& q ) const +{ + return x != q.x || y != q.y || z != q.z || w != q.w; +} + + + +//-------------------------- +// Plane +//-------------------------- + +D3DXINLINE +D3DXPLANE::D3DXPLANE( CONST FLOAT* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + a = pf[0]; + b = pf[1]; + c = pf[2]; + d = pf[3]; +} + +D3DXINLINE +D3DXPLANE::D3DXPLANE( CONST D3DXFLOAT16* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&a, pf, 4); +} + +D3DXINLINE +D3DXPLANE::D3DXPLANE( FLOAT fa, FLOAT fb, FLOAT fc, FLOAT fd ) +{ + a = fa; + b = fb; + c = fc; + d = fd; +} + + +// casting +D3DXINLINE +D3DXPLANE::operator FLOAT* () +{ + return (FLOAT *) &a; +} + +D3DXINLINE +D3DXPLANE::operator CONST FLOAT* () const +{ + return (CONST FLOAT *) &a; +} + + +// assignment operators +D3DXINLINE D3DXPLANE& +D3DXPLANE::operator *= ( FLOAT f ) +{ + a *= f; + b *= f; + c *= f; + d *= f; + return *this; +} + +D3DXINLINE D3DXPLANE& +D3DXPLANE::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + a *= fInv; + b *= fInv; + c *= fInv; + d *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXPLANE +D3DXPLANE::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXPLANE +D3DXPLANE::operator - () const +{ + return D3DXPLANE(-a, -b, -c, -d); +} + + +// binary operators +D3DXINLINE D3DXPLANE +D3DXPLANE::operator * ( FLOAT f ) const +{ + return D3DXPLANE(a * f, b * f, c * f, d * f); +} + +D3DXINLINE D3DXPLANE +D3DXPLANE::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXPLANE(a * fInv, b * fInv, c * fInv, d * fInv); +} + +D3DXINLINE D3DXPLANE +operator * (FLOAT f, CONST D3DXPLANE& p ) +{ + return D3DXPLANE(f * p.a, f * p.b, f * p.c, f * p.d); +} + +D3DXINLINE BOOL +D3DXPLANE::operator == ( CONST D3DXPLANE& p ) const +{ + return a == p.a && b == p.b && c == p.c && d == p.d; +} + +D3DXINLINE BOOL +D3DXPLANE::operator != ( CONST D3DXPLANE& p ) const +{ + return a != p.a || b != p.b || c != p.c || d != p.d; +} + + + + +//-------------------------- +// Color +//-------------------------- + +D3DXINLINE +D3DXCOLOR::D3DXCOLOR( DWORD dw ) +{ + CONST FLOAT f = 1.0f / 255.0f; + r = f * (FLOAT) (unsigned char) (dw >> 16); + g = f * (FLOAT) (unsigned char) (dw >> 8); + b = f * (FLOAT) (unsigned char) (dw >> 0); + a = f * (FLOAT) (unsigned char) (dw >> 24); +} + +D3DXINLINE +D3DXCOLOR::D3DXCOLOR( CONST FLOAT* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + r = pf[0]; + g = pf[1]; + b = pf[2]; + a = pf[3]; +} + +D3DXINLINE +D3DXCOLOR::D3DXCOLOR( CONST D3DXFLOAT16* pf ) +{ +#ifdef D3DX_DEBUG + if(!pf) + return; +#endif + + D3DXFloat16To32Array(&r, pf, 4); +} + +D3DXINLINE +D3DXCOLOR::D3DXCOLOR( CONST D3DCOLORVALUE& c ) +{ + r = c.r; + g = c.g; + b = c.b; + a = c.a; +} + +D3DXINLINE +D3DXCOLOR::D3DXCOLOR( FLOAT fr, FLOAT fg, FLOAT fb, FLOAT fa ) +{ + r = fr; + g = fg; + b = fb; + a = fa; +} + + +// casting +D3DXINLINE +D3DXCOLOR::operator DWORD () const +{ + DWORD dwR = r >= 1.0f ? 0xff : r <= 0.0f ? 0x00 : (DWORD) (r * 255.0f + 0.5f); + DWORD dwG = g >= 1.0f ? 0xff : g <= 0.0f ? 0x00 : (DWORD) (g * 255.0f + 0.5f); + DWORD dwB = b >= 1.0f ? 0xff : b <= 0.0f ? 0x00 : (DWORD) (b * 255.0f + 0.5f); + DWORD dwA = a >= 1.0f ? 0xff : a <= 0.0f ? 0x00 : (DWORD) (a * 255.0f + 0.5f); + + return (dwA << 24) | (dwR << 16) | (dwG << 8) | dwB; +} + + +D3DXINLINE +D3DXCOLOR::operator FLOAT * () +{ + return (FLOAT *) &r; +} + +D3DXINLINE +D3DXCOLOR::operator CONST FLOAT * () const +{ + return (CONST FLOAT *) &r; +} + + +D3DXINLINE +D3DXCOLOR::operator D3DCOLORVALUE * () +{ + return (D3DCOLORVALUE *) &r; +} + +D3DXINLINE +D3DXCOLOR::operator CONST D3DCOLORVALUE * () const +{ + return (CONST D3DCOLORVALUE *) &r; +} + + +D3DXINLINE +D3DXCOLOR::operator D3DCOLORVALUE& () +{ + return *((D3DCOLORVALUE *) &r); +} + +D3DXINLINE +D3DXCOLOR::operator CONST D3DCOLORVALUE& () const +{ + return *((CONST D3DCOLORVALUE *) &r); +} + + +// assignment operators +D3DXINLINE D3DXCOLOR& +D3DXCOLOR::operator += ( CONST D3DXCOLOR& c ) +{ + r += c.r; + g += c.g; + b += c.b; + a += c.a; + return *this; +} + +D3DXINLINE D3DXCOLOR& +D3DXCOLOR::operator -= ( CONST D3DXCOLOR& c ) +{ + r -= c.r; + g -= c.g; + b -= c.b; + a -= c.a; + return *this; +} + +D3DXINLINE D3DXCOLOR& +D3DXCOLOR::operator *= ( FLOAT f ) +{ + r *= f; + g *= f; + b *= f; + a *= f; + return *this; +} + +D3DXINLINE D3DXCOLOR& +D3DXCOLOR::operator /= ( FLOAT f ) +{ + FLOAT fInv = 1.0f / f; + r *= fInv; + g *= fInv; + b *= fInv; + a *= fInv; + return *this; +} + + +// unary operators +D3DXINLINE D3DXCOLOR +D3DXCOLOR::operator + () const +{ + return *this; +} + +D3DXINLINE D3DXCOLOR +D3DXCOLOR::operator - () const +{ + return D3DXCOLOR(-r, -g, -b, -a); +} + + +// binary operators +D3DXINLINE D3DXCOLOR +D3DXCOLOR::operator + ( CONST D3DXCOLOR& c ) const +{ + return D3DXCOLOR(r + c.r, g + c.g, b + c.b, a + c.a); +} + +D3DXINLINE D3DXCOLOR +D3DXCOLOR::operator - ( CONST D3DXCOLOR& c ) const +{ + return D3DXCOLOR(r - c.r, g - c.g, b - c.b, a - c.a); +} + +D3DXINLINE D3DXCOLOR +D3DXCOLOR::operator * ( FLOAT f ) const +{ + return D3DXCOLOR(r * f, g * f, b * f, a * f); +} + +D3DXINLINE D3DXCOLOR +D3DXCOLOR::operator / ( FLOAT f ) const +{ + FLOAT fInv = 1.0f / f; + return D3DXCOLOR(r * fInv, g * fInv, b * fInv, a * fInv); +} + + +D3DXINLINE D3DXCOLOR +operator * (FLOAT f, CONST D3DXCOLOR& c ) +{ + return D3DXCOLOR(f * c.r, f * c.g, f * c.b, f * c.a); +} + + +D3DXINLINE BOOL +D3DXCOLOR::operator == ( CONST D3DXCOLOR& c ) const +{ + return r == c.r && g == c.g && b == c.b && a == c.a; +} + +D3DXINLINE BOOL +D3DXCOLOR::operator != ( CONST D3DXCOLOR& c ) const +{ + return r != c.r || g != c.g || b != c.b || a != c.a; +} + + +#endif //__cplusplus + + + +//=========================================================================== +// +// Inline functions +// +//=========================================================================== + + +//-------------------------- +// 2D Vector +//-------------------------- + +D3DXINLINE FLOAT D3DXVec2Length + ( CONST D3DXVECTOR2 *pV ) +{ +#ifdef D3DX_DEBUG + if(!pV) + return 0.0f; +#endif + +#ifdef __cplusplus + return sqrtf(pV->x * pV->x + pV->y * pV->y); +#else + return (FLOAT) sqrt(pV->x * pV->x + pV->y * pV->y); +#endif +} + +D3DXINLINE FLOAT D3DXVec2LengthSq + ( CONST D3DXVECTOR2 *pV ) +{ +#ifdef D3DX_DEBUG + if(!pV) + return 0.0f; +#endif + + return pV->x * pV->x + pV->y * pV->y; +} + +D3DXINLINE FLOAT D3DXVec2Dot + ( CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pV1 || !pV2) + return 0.0f; +#endif + + return pV1->x * pV2->x + pV1->y * pV2->y; +} + +D3DXINLINE FLOAT D3DXVec2CCW + ( CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pV1 || !pV2) + return 0.0f; +#endif + + return pV1->x * pV2->y - pV1->y * pV2->x; +} + +D3DXINLINE D3DXVECTOR2* D3DXVec2Add + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x + pV2->x; + pOut->y = pV1->y + pV2->y; + return pOut; +} + +D3DXINLINE D3DXVECTOR2* D3DXVec2Subtract + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x - pV2->x; + pOut->y = pV1->y - pV2->y; + return pOut; +} + +D3DXINLINE D3DXVECTOR2* D3DXVec2Minimize + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x < pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y < pV2->y ? pV1->y : pV2->y; + return pOut; +} + +D3DXINLINE D3DXVECTOR2* D3DXVec2Maximize + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x > pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y > pV2->y ? pV1->y : pV2->y; + return pOut; +} + +D3DXINLINE D3DXVECTOR2* D3DXVec2Scale + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV, FLOAT s ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV) + return NULL; +#endif + + pOut->x = pV->x * s; + pOut->y = pV->y * s; + return pOut; +} + +D3DXINLINE D3DXVECTOR2* D3DXVec2Lerp + ( D3DXVECTOR2 *pOut, CONST D3DXVECTOR2 *pV1, CONST D3DXVECTOR2 *pV2, + FLOAT s ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x + s * (pV2->x - pV1->x); + pOut->y = pV1->y + s * (pV2->y - pV1->y); + return pOut; +} + + +//-------------------------- +// 3D Vector +//-------------------------- + +D3DXINLINE FLOAT D3DXVec3Length + ( CONST D3DXVECTOR3 *pV ) +{ +#ifdef D3DX_DEBUG + if(!pV) + return 0.0f; +#endif + +#ifdef __cplusplus + return sqrtf(pV->x * pV->x + pV->y * pV->y + pV->z * pV->z); +#else + return (FLOAT) sqrt(pV->x * pV->x + pV->y * pV->y + pV->z * pV->z); +#endif +} + +D3DXINLINE FLOAT D3DXVec3LengthSq + ( CONST D3DXVECTOR3 *pV ) +{ +#ifdef D3DX_DEBUG + if(!pV) + return 0.0f; +#endif + + return pV->x * pV->x + pV->y * pV->y + pV->z * pV->z; +} + +D3DXINLINE FLOAT D3DXVec3Dot + ( CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pV1 || !pV2) + return 0.0f; +#endif + + return pV1->x * pV2->x + pV1->y * pV2->y + pV1->z * pV2->z; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Cross + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ + D3DXVECTOR3 v; + +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + v.x = pV1->y * pV2->z - pV1->z * pV2->y; + v.y = pV1->z * pV2->x - pV1->x * pV2->z; + v.z = pV1->x * pV2->y - pV1->y * pV2->x; + + *pOut = v; + return pOut; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Add + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x + pV2->x; + pOut->y = pV1->y + pV2->y; + pOut->z = pV1->z + pV2->z; + return pOut; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Subtract + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x - pV2->x; + pOut->y = pV1->y - pV2->y; + pOut->z = pV1->z - pV2->z; + return pOut; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Minimize + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x < pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y < pV2->y ? pV1->y : pV2->y; + pOut->z = pV1->z < pV2->z ? pV1->z : pV2->z; + return pOut; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Maximize + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x > pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y > pV2->y ? pV1->y : pV2->y; + pOut->z = pV1->z > pV2->z ? pV1->z : pV2->z; + return pOut; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Scale + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, FLOAT s) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV) + return NULL; +#endif + + pOut->x = pV->x * s; + pOut->y = pV->y * s; + pOut->z = pV->z * s; + return pOut; +} + +D3DXINLINE D3DXVECTOR3* D3DXVec3Lerp + ( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2, + FLOAT s ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x + s * (pV2->x - pV1->x); + pOut->y = pV1->y + s * (pV2->y - pV1->y); + pOut->z = pV1->z + s * (pV2->z - pV1->z); + return pOut; +} + + +//-------------------------- +// 4D Vector +//-------------------------- + +D3DXINLINE FLOAT D3DXVec4Length + ( CONST D3DXVECTOR4 *pV ) +{ +#ifdef D3DX_DEBUG + if(!pV) + return 0.0f; +#endif + +#ifdef __cplusplus + return sqrtf(pV->x * pV->x + pV->y * pV->y + pV->z * pV->z + pV->w * pV->w); +#else + return (FLOAT) sqrt(pV->x * pV->x + pV->y * pV->y + pV->z * pV->z + pV->w * pV->w); +#endif +} + +D3DXINLINE FLOAT D3DXVec4LengthSq + ( CONST D3DXVECTOR4 *pV ) +{ +#ifdef D3DX_DEBUG + if(!pV) + return 0.0f; +#endif + + return pV->x * pV->x + pV->y * pV->y + pV->z * pV->z + pV->w * pV->w; +} + +D3DXINLINE FLOAT D3DXVec4Dot + ( CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2 ) +{ +#ifdef D3DX_DEBUG + if(!pV1 || !pV2) + return 0.0f; +#endif + + return pV1->x * pV2->x + pV1->y * pV2->y + pV1->z * pV2->z + pV1->w * pV2->w; +} + +D3DXINLINE D3DXVECTOR4* D3DXVec4Add + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x + pV2->x; + pOut->y = pV1->y + pV2->y; + pOut->z = pV1->z + pV2->z; + pOut->w = pV1->w + pV2->w; + return pOut; +} + +D3DXINLINE D3DXVECTOR4* D3DXVec4Subtract + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x - pV2->x; + pOut->y = pV1->y - pV2->y; + pOut->z = pV1->z - pV2->z; + pOut->w = pV1->w - pV2->w; + return pOut; +} + +D3DXINLINE D3DXVECTOR4* D3DXVec4Minimize + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x < pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y < pV2->y ? pV1->y : pV2->y; + pOut->z = pV1->z < pV2->z ? pV1->z : pV2->z; + pOut->w = pV1->w < pV2->w ? pV1->w : pV2->w; + return pOut; +} + +D3DXINLINE D3DXVECTOR4* D3DXVec4Maximize + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x > pV2->x ? pV1->x : pV2->x; + pOut->y = pV1->y > pV2->y ? pV1->y : pV2->y; + pOut->z = pV1->z > pV2->z ? pV1->z : pV2->z; + pOut->w = pV1->w > pV2->w ? pV1->w : pV2->w; + return pOut; +} + +D3DXINLINE D3DXVECTOR4* D3DXVec4Scale + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, FLOAT s) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV) + return NULL; +#endif + + pOut->x = pV->x * s; + pOut->y = pV->y * s; + pOut->z = pV->z * s; + pOut->w = pV->w * s; + return pOut; +} + +D3DXINLINE D3DXVECTOR4* D3DXVec4Lerp + ( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV1, CONST D3DXVECTOR4 *pV2, + FLOAT s ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pV1 || !pV2) + return NULL; +#endif + + pOut->x = pV1->x + s * (pV2->x - pV1->x); + pOut->y = pV1->y + s * (pV2->y - pV1->y); + pOut->z = pV1->z + s * (pV2->z - pV1->z); + pOut->w = pV1->w + s * (pV2->w - pV1->w); + return pOut; +} + + +//-------------------------- +// 4D Matrix +//-------------------------- + +D3DXINLINE D3DXMATRIX* D3DXMatrixIdentity + ( D3DXMATRIX *pOut ) +{ +#ifdef D3DX_DEBUG + if(!pOut) + return NULL; +#endif + + pOut->m[0][1] = pOut->m[0][2] = pOut->m[0][3] = + pOut->m[1][0] = pOut->m[1][2] = pOut->m[1][3] = + pOut->m[2][0] = pOut->m[2][1] = pOut->m[2][3] = + pOut->m[3][0] = pOut->m[3][1] = pOut->m[3][2] = 0.0f; + + pOut->m[0][0] = pOut->m[1][1] = pOut->m[2][2] = pOut->m[3][3] = 1.0f; + return pOut; +} + + +D3DXINLINE BOOL D3DXMatrixIsIdentity + ( CONST D3DXMATRIX *pM ) +{ +#ifdef D3DX_DEBUG + if(!pM) + return FALSE; +#endif + + return pM->m[0][0] == 1.0f && pM->m[0][1] == 0.0f && pM->m[0][2] == 0.0f && pM->m[0][3] == 0.0f && + pM->m[1][0] == 0.0f && pM->m[1][1] == 1.0f && pM->m[1][2] == 0.0f && pM->m[1][3] == 0.0f && + pM->m[2][0] == 0.0f && pM->m[2][1] == 0.0f && pM->m[2][2] == 1.0f && pM->m[2][3] == 0.0f && + pM->m[3][0] == 0.0f && pM->m[3][1] == 0.0f && pM->m[3][2] == 0.0f && pM->m[3][3] == 1.0f; +} + + +//-------------------------- +// Quaternion +//-------------------------- + +D3DXINLINE FLOAT D3DXQuaternionLength + ( CONST D3DXQUATERNION *pQ ) +{ +#ifdef D3DX_DEBUG + if(!pQ) + return 0.0f; +#endif + +#ifdef __cplusplus + return sqrtf(pQ->x * pQ->x + pQ->y * pQ->y + pQ->z * pQ->z + pQ->w * pQ->w); +#else + return (FLOAT) sqrt(pQ->x * pQ->x + pQ->y * pQ->y + pQ->z * pQ->z + pQ->w * pQ->w); +#endif +} + +D3DXINLINE FLOAT D3DXQuaternionLengthSq + ( CONST D3DXQUATERNION *pQ ) +{ +#ifdef D3DX_DEBUG + if(!pQ) + return 0.0f; +#endif + + return pQ->x * pQ->x + pQ->y * pQ->y + pQ->z * pQ->z + pQ->w * pQ->w; +} + +D3DXINLINE FLOAT D3DXQuaternionDot + ( CONST D3DXQUATERNION *pQ1, CONST D3DXQUATERNION *pQ2 ) +{ +#ifdef D3DX_DEBUG + if(!pQ1 || !pQ2) + return 0.0f; +#endif + + return pQ1->x * pQ2->x + pQ1->y * pQ2->y + pQ1->z * pQ2->z + pQ1->w * pQ2->w; +} + + +D3DXINLINE D3DXQUATERNION* D3DXQuaternionIdentity + ( D3DXQUATERNION *pOut ) +{ +#ifdef D3DX_DEBUG + if(!pOut) + return NULL; +#endif + + pOut->x = pOut->y = pOut->z = 0.0f; + pOut->w = 1.0f; + return pOut; +} + +D3DXINLINE BOOL D3DXQuaternionIsIdentity + ( CONST D3DXQUATERNION *pQ ) +{ +#ifdef D3DX_DEBUG + if(!pQ) + return FALSE; +#endif + + return pQ->x == 0.0f && pQ->y == 0.0f && pQ->z == 0.0f && pQ->w == 1.0f; +} + + +D3DXINLINE D3DXQUATERNION* D3DXQuaternionConjugate + ( D3DXQUATERNION *pOut, CONST D3DXQUATERNION *pQ ) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pQ) + return NULL; +#endif + + pOut->x = -pQ->x; + pOut->y = -pQ->y; + pOut->z = -pQ->z; + pOut->w = pQ->w; + return pOut; +} + + +//-------------------------- +// Plane +//-------------------------- + +D3DXINLINE FLOAT D3DXPlaneDot + ( CONST D3DXPLANE *pP, CONST D3DXVECTOR4 *pV) +{ +#ifdef D3DX_DEBUG + if(!pP || !pV) + return 0.0f; +#endif + + return pP->a * pV->x + pP->b * pV->y + pP->c * pV->z + pP->d * pV->w; +} + +D3DXINLINE FLOAT D3DXPlaneDotCoord + ( CONST D3DXPLANE *pP, CONST D3DXVECTOR3 *pV) +{ +#ifdef D3DX_DEBUG + if(!pP || !pV) + return 0.0f; +#endif + + return pP->a * pV->x + pP->b * pV->y + pP->c * pV->z + pP->d; +} + +D3DXINLINE FLOAT D3DXPlaneDotNormal + ( CONST D3DXPLANE *pP, CONST D3DXVECTOR3 *pV) +{ +#ifdef D3DX_DEBUG + if(!pP || !pV) + return 0.0f; +#endif + + return pP->a * pV->x + pP->b * pV->y + pP->c * pV->z; +} + +D3DXINLINE D3DXPLANE* D3DXPlaneScale + (D3DXPLANE *pOut, CONST D3DXPLANE *pP, FLOAT s) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pP) + return NULL; +#endif + + pOut->a = pP->a * s; + pOut->b = pP->b * s; + pOut->c = pP->c * s; + pOut->d = pP->d * s; + return pOut; +} + + +//-------------------------- +// Color +//-------------------------- + +D3DXINLINE D3DXCOLOR* D3DXColorNegative + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pC) + return NULL; +#endif + + pOut->r = 1.0f - pC->r; + pOut->g = 1.0f - pC->g; + pOut->b = 1.0f - pC->b; + pOut->a = pC->a; + return pOut; +} + +D3DXINLINE D3DXCOLOR* D3DXColorAdd + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pC1 || !pC2) + return NULL; +#endif + + pOut->r = pC1->r + pC2->r; + pOut->g = pC1->g + pC2->g; + pOut->b = pC1->b + pC2->b; + pOut->a = pC1->a + pC2->a; + return pOut; +} + +D3DXINLINE D3DXCOLOR* D3DXColorSubtract + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pC1 || !pC2) + return NULL; +#endif + + pOut->r = pC1->r - pC2->r; + pOut->g = pC1->g - pC2->g; + pOut->b = pC1->b - pC2->b; + pOut->a = pC1->a - pC2->a; + return pOut; +} + +D3DXINLINE D3DXCOLOR* D3DXColorScale + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC, FLOAT s) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pC) + return NULL; +#endif + + pOut->r = pC->r * s; + pOut->g = pC->g * s; + pOut->b = pC->b * s; + pOut->a = pC->a * s; + return pOut; +} + +D3DXINLINE D3DXCOLOR* D3DXColorModulate + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pC1 || !pC2) + return NULL; +#endif + + pOut->r = pC1->r * pC2->r; + pOut->g = pC1->g * pC2->g; + pOut->b = pC1->b * pC2->b; + pOut->a = pC1->a * pC2->a; + return pOut; +} + +D3DXINLINE D3DXCOLOR* D3DXColorLerp + (D3DXCOLOR *pOut, CONST D3DXCOLOR *pC1, CONST D3DXCOLOR *pC2, FLOAT s) +{ +#ifdef D3DX_DEBUG + if(!pOut || !pC1 || !pC2) + return NULL; +#endif + + pOut->r = pC1->r + s * (pC2->r - pC1->r); + pOut->g = pC1->g + s * (pC2->g - pC1->g); + pOut->b = pC1->b + s * (pC2->b - pC1->b); + pOut->a = pC1->a + s * (pC2->a - pC1->a); + return pOut; +} + + +#endif // __D3DX9MATH_INL__ + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9mesh.h b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9mesh.h new file mode 100644 index 0000000000..a009d9a041 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9mesh.h @@ -0,0 +1,3007 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9mesh.h +// Content: D3DX mesh types and functions +// +////////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9MESH_H__ +#define __D3DX9MESH_H__ + +// {7ED943DD-52E8-40b5-A8D8-76685C406330} +DEFINE_GUID(IID_ID3DXBaseMesh, +0x7ed943dd, 0x52e8, 0x40b5, 0xa8, 0xd8, 0x76, 0x68, 0x5c, 0x40, 0x63, 0x30); + +// {4020E5C2-1403-4929-883F-E2E849FAC195} +DEFINE_GUID(IID_ID3DXMesh, +0x4020e5c2, 0x1403, 0x4929, 0x88, 0x3f, 0xe2, 0xe8, 0x49, 0xfa, 0xc1, 0x95); + +// {8875769A-D579-4088-AAEB-534D1AD84E96} +DEFINE_GUID(IID_ID3DXPMesh, +0x8875769a, 0xd579, 0x4088, 0xaa, 0xeb, 0x53, 0x4d, 0x1a, 0xd8, 0x4e, 0x96); + +// {667EA4C7-F1CD-4386-B523-7C0290B83CC5} +DEFINE_GUID(IID_ID3DXSPMesh, +0x667ea4c7, 0xf1cd, 0x4386, 0xb5, 0x23, 0x7c, 0x2, 0x90, 0xb8, 0x3c, 0xc5); + +// {11EAA540-F9A6-4d49-AE6A-E19221F70CC4} +DEFINE_GUID(IID_ID3DXSkinInfo, +0x11eaa540, 0xf9a6, 0x4d49, 0xae, 0x6a, 0xe1, 0x92, 0x21, 0xf7, 0xc, 0xc4); + +// {3CE6CC22-DBF2-44f4-894D-F9C34A337139} +DEFINE_GUID(IID_ID3DXPatchMesh, +0x3ce6cc22, 0xdbf2, 0x44f4, 0x89, 0x4d, 0xf9, 0xc3, 0x4a, 0x33, 0x71, 0x39); + +//patch mesh can be quads or tris +typedef enum _D3DXPATCHMESHTYPE { + D3DXPATCHMESH_RECT = 0x001, + D3DXPATCHMESH_TRI = 0x002, + D3DXPATCHMESH_NPATCH = 0x003, + + D3DXPATCHMESH_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ +} D3DXPATCHMESHTYPE; + +// Mesh options - lower 3 bytes only, upper byte used by _D3DXMESHOPT option flags +enum _D3DXMESH { + D3DXMESH_32BIT = 0x001, // If set, then use 32 bit indices, if not set use 16 bit indices. + D3DXMESH_DONOTCLIP = 0x002, // Use D3DUSAGE_DONOTCLIP for VB & IB. + D3DXMESH_POINTS = 0x004, // Use D3DUSAGE_POINTS for VB & IB. + D3DXMESH_RTPATCHES = 0x008, // Use D3DUSAGE_RTPATCHES for VB & IB. + D3DXMESH_NPATCHES = 0x4000,// Use D3DUSAGE_NPATCHES for VB & IB. + D3DXMESH_VB_SYSTEMMEM = 0x010, // Use D3DPOOL_SYSTEMMEM for VB. Overrides D3DXMESH_MANAGEDVERTEXBUFFER + D3DXMESH_VB_MANAGED = 0x020, // Use D3DPOOL_MANAGED for VB. + D3DXMESH_VB_WRITEONLY = 0x040, // Use D3DUSAGE_WRITEONLY for VB. + D3DXMESH_VB_DYNAMIC = 0x080, // Use D3DUSAGE_DYNAMIC for VB. + D3DXMESH_VB_SOFTWAREPROCESSING = 0x8000, // Use D3DUSAGE_SOFTWAREPROCESSING for VB. + D3DXMESH_IB_SYSTEMMEM = 0x100, // Use D3DPOOL_SYSTEMMEM for IB. Overrides D3DXMESH_MANAGEDINDEXBUFFER + D3DXMESH_IB_MANAGED = 0x200, // Use D3DPOOL_MANAGED for IB. + D3DXMESH_IB_WRITEONLY = 0x400, // Use D3DUSAGE_WRITEONLY for IB. + D3DXMESH_IB_DYNAMIC = 0x800, // Use D3DUSAGE_DYNAMIC for IB. + D3DXMESH_IB_SOFTWAREPROCESSING= 0x10000, // Use D3DUSAGE_SOFTWAREPROCESSING for IB. + + D3DXMESH_VB_SHARE = 0x1000, // Valid for Clone* calls only, forces cloned mesh/pmesh to share vertex buffer + + D3DXMESH_USEHWONLY = 0x2000, // Valid for ID3DXSkinInfo::ConvertToBlendedMesh + + // Helper options + D3DXMESH_SYSTEMMEM = 0x110, // D3DXMESH_VB_SYSTEMMEM | D3DXMESH_IB_SYSTEMMEM + D3DXMESH_MANAGED = 0x220, // D3DXMESH_VB_MANAGED | D3DXMESH_IB_MANAGED + D3DXMESH_WRITEONLY = 0x440, // D3DXMESH_VB_WRITEONLY | D3DXMESH_IB_WRITEONLY + D3DXMESH_DYNAMIC = 0x880, // D3DXMESH_VB_DYNAMIC | D3DXMESH_IB_DYNAMIC + D3DXMESH_SOFTWAREPROCESSING = 0x18000, // D3DXMESH_VB_SOFTWAREPROCESSING | D3DXMESH_IB_SOFTWAREPROCESSING + +}; + +//patch mesh options +enum _D3DXPATCHMESH { + D3DXPATCHMESH_DEFAULT = 000, +}; +// option field values for specifying min value in D3DXGeneratePMesh and D3DXSimplifyMesh +enum _D3DXMESHSIMP +{ + D3DXMESHSIMP_VERTEX = 0x1, + D3DXMESHSIMP_FACE = 0x2, + +}; + +typedef enum _D3DXCLEANTYPE { + D3DXCLEAN_BACKFACING = 0x00000001, + D3DXCLEAN_BOWTIES = 0x00000002, + + // Helper options + D3DXCLEAN_SKINNING = D3DXCLEAN_BACKFACING, // Bowtie cleaning modifies geometry and breaks skinning + D3DXCLEAN_OPTIMIZATION = D3DXCLEAN_BACKFACING, + D3DXCLEAN_SIMPLIFICATION= D3DXCLEAN_BACKFACING | D3DXCLEAN_BOWTIES, +} D3DXCLEANTYPE; + +enum _MAX_FVF_DECL_SIZE +{ + MAX_FVF_DECL_SIZE = MAXD3DDECLLENGTH + 1 // +1 for END +}; + +typedef enum _D3DXTANGENT +{ + D3DXTANGENT_WRAP_U = 0x01, + D3DXTANGENT_WRAP_V = 0x02, + D3DXTANGENT_WRAP_UV = 0x03, + D3DXTANGENT_DONT_NORMALIZE_PARTIALS = 0x04, + D3DXTANGENT_DONT_ORTHOGONALIZE = 0x08, + D3DXTANGENT_ORTHOGONALIZE_FROM_V = 0x010, + D3DXTANGENT_ORTHOGONALIZE_FROM_U = 0x020, + D3DXTANGENT_WEIGHT_BY_AREA = 0x040, + D3DXTANGENT_WEIGHT_EQUAL = 0x080, + D3DXTANGENT_WIND_CW = 0x0100, + D3DXTANGENT_CALCULATE_NORMALS = 0x0200, + D3DXTANGENT_GENERATE_IN_PLACE = 0x0400, +} D3DXTANGENT; + +// D3DXIMT_WRAP_U means the texture wraps in the U direction +// D3DXIMT_WRAP_V means the texture wraps in the V direction +// D3DXIMT_WRAP_UV means the texture wraps in both directions +typedef enum _D3DXIMT +{ + D3DXIMT_WRAP_U = 0x01, + D3DXIMT_WRAP_V = 0x02, + D3DXIMT_WRAP_UV = 0x03, +} D3DXIMT; + +// These options are only valid for UVAtlasCreate and UVAtlasPartition, we may add more for UVAtlasPack if necessary +// D3DXUVATLAS_DEFAULT - Meshes with more than 25k faces go through fast, meshes with fewer than 25k faces go through quality +// D3DXUVATLAS_GEODESIC_FAST - Uses approximations to improve charting speed at the cost of added stretch or more charts. +// D3DXUVATLAS_GEODESIC_QUALITY - Provides better quality charts, but requires more time and memory than fast. +typedef enum _D3DXUVATLAS +{ + D3DXUVATLAS_DEFAULT = 0x00, + D3DXUVATLAS_GEODESIC_FAST = 0x01, + D3DXUVATLAS_GEODESIC_QUALITY = 0x02, +} D3DXUVATLAS; + +typedef struct ID3DXBaseMesh *LPD3DXBASEMESH; +typedef struct ID3DXMesh *LPD3DXMESH; +typedef struct ID3DXPMesh *LPD3DXPMESH; +typedef struct ID3DXSPMesh *LPD3DXSPMESH; +typedef struct ID3DXSkinInfo *LPD3DXSKININFO; +typedef struct ID3DXPatchMesh *LPD3DXPATCHMESH; +typedef interface ID3DXTextureGutterHelper *LPD3DXTEXTUREGUTTERHELPER; +typedef interface ID3DXPRTBuffer *LPD3DXPRTBUFFER; + + +typedef struct _D3DXATTRIBUTERANGE +{ + DWORD AttribId; + DWORD FaceStart; + DWORD FaceCount; + DWORD VertexStart; + DWORD VertexCount; +} D3DXATTRIBUTERANGE; + +typedef D3DXATTRIBUTERANGE* LPD3DXATTRIBUTERANGE; + +typedef struct _D3DXMATERIAL +{ + D3DMATERIAL9 MatD3D; + LPSTR pTextureFilename; +} D3DXMATERIAL; +typedef D3DXMATERIAL *LPD3DXMATERIAL; + +typedef enum _D3DXEFFECTDEFAULTTYPE +{ + D3DXEDT_STRING = 0x1, // pValue points to a null terminated ASCII string + D3DXEDT_FLOATS = 0x2, // pValue points to an array of floats - number of floats is NumBytes / sizeof(float) + D3DXEDT_DWORD = 0x3, // pValue points to a DWORD + + D3DXEDT_FORCEDWORD = 0x7fffffff +} D3DXEFFECTDEFAULTTYPE; + +typedef struct _D3DXEFFECTDEFAULT +{ + LPSTR pParamName; + D3DXEFFECTDEFAULTTYPE Type; // type of the data pointed to by pValue + DWORD NumBytes; // size in bytes of the data pointed to by pValue + LPVOID pValue; // data for the default of the effect +} D3DXEFFECTDEFAULT, *LPD3DXEFFECTDEFAULT; + +typedef struct _D3DXEFFECTINSTANCE +{ + LPSTR pEffectFilename; + DWORD NumDefaults; + LPD3DXEFFECTDEFAULT pDefaults; +} D3DXEFFECTINSTANCE, *LPD3DXEFFECTINSTANCE; + +typedef struct _D3DXATTRIBUTEWEIGHTS +{ + FLOAT Position; + FLOAT Boundary; + FLOAT Normal; + FLOAT Diffuse; + FLOAT Specular; + FLOAT Texcoord[8]; + FLOAT Tangent; + FLOAT Binormal; +} D3DXATTRIBUTEWEIGHTS, *LPD3DXATTRIBUTEWEIGHTS; + +enum _D3DXWELDEPSILONSFLAGS +{ + D3DXWELDEPSILONS_WELDALL = 0x1, // weld all vertices marked by adjacency as being overlapping + + D3DXWELDEPSILONS_WELDPARTIALMATCHES = 0x2, // if a given vertex component is within epsilon, modify partial matched + // vertices so that both components identical AND if all components "equal" + // remove one of the vertices + D3DXWELDEPSILONS_DONOTREMOVEVERTICES = 0x4, // instructs weld to only allow modifications to vertices and not removal + // ONLY valid if D3DXWELDEPSILONS_WELDPARTIALMATCHES is set + // useful to modify vertices to be equal, but not allow vertices to be removed + + D3DXWELDEPSILONS_DONOTSPLIT = 0x8, // instructs weld to specify the D3DXMESHOPT_DONOTSPLIT flag when doing an Optimize(ATTR_SORT) + // if this flag is not set, all vertices that are in separate attribute groups + // will remain split and not welded. Setting this flag can slow down software vertex processing + +}; + +typedef struct _D3DXWELDEPSILONS +{ + FLOAT Position; // NOTE: This does NOT replace the epsilon in GenerateAdjacency + // in general, it should be the same value or greater than the one passed to GeneratedAdjacency + FLOAT BlendWeights; + FLOAT Normal; + FLOAT PSize; + FLOAT Specular; + FLOAT Diffuse; + FLOAT Texcoord[8]; + FLOAT Tangent; + FLOAT Binormal; + FLOAT TessFactor; +} D3DXWELDEPSILONS; + +typedef D3DXWELDEPSILONS* LPD3DXWELDEPSILONS; + + +#undef INTERFACE +#define INTERFACE ID3DXBaseMesh + +DECLARE_INTERFACE_(ID3DXBaseMesh, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXBaseMesh + STDMETHOD(DrawSubset)(THIS_ DWORD AttribId) PURE; + STDMETHOD_(DWORD, GetNumFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetNumVertices)(THIS) PURE; + STDMETHOD_(DWORD, GetFVF)(THIS) PURE; + STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + STDMETHOD_(DWORD, GetNumBytesPerVertex)(THIS) PURE; + STDMETHOD_(DWORD, GetOptions)(THIS) PURE; + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(CloneMeshFVF)(THIS_ DWORD Options, + DWORD FVF, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(CloneMesh)(THIS_ DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(GetVertexBuffer)(THIS_ LPDIRECT3DVERTEXBUFFER9* ppVB) PURE; + STDMETHOD(GetIndexBuffer)(THIS_ LPDIRECT3DINDEXBUFFER9* ppIB) PURE; + STDMETHOD(LockVertexBuffer)(THIS_ DWORD Flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockVertexBuffer)(THIS) PURE; + STDMETHOD(LockIndexBuffer)(THIS_ DWORD Flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockIndexBuffer)(THIS) PURE; + STDMETHOD(GetAttributeTable)( + THIS_ D3DXATTRIBUTERANGE *pAttribTable, DWORD* pAttribTableSize) PURE; + + STDMETHOD(ConvertPointRepsToAdjacency)(THIS_ CONST DWORD* pPRep, DWORD* pAdjacency) PURE; + STDMETHOD(ConvertAdjacencyToPointReps)(THIS_ CONST DWORD* pAdjacency, DWORD* pPRep) PURE; + STDMETHOD(GenerateAdjacency)(THIS_ FLOAT Epsilon, DWORD* pAdjacency) PURE; + + STDMETHOD(UpdateSemantics)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; +}; + + +#undef INTERFACE +#define INTERFACE ID3DXMesh + +DECLARE_INTERFACE_(ID3DXMesh, ID3DXBaseMesh) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXBaseMesh + STDMETHOD(DrawSubset)(THIS_ DWORD AttribId) PURE; + STDMETHOD_(DWORD, GetNumFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetNumVertices)(THIS) PURE; + STDMETHOD_(DWORD, GetFVF)(THIS) PURE; + STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + STDMETHOD_(DWORD, GetNumBytesPerVertex)(THIS) PURE; + STDMETHOD_(DWORD, GetOptions)(THIS) PURE; + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(CloneMeshFVF)(THIS_ DWORD Options, + DWORD FVF, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(CloneMesh)(THIS_ DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(GetVertexBuffer)(THIS_ LPDIRECT3DVERTEXBUFFER9* ppVB) PURE; + STDMETHOD(GetIndexBuffer)(THIS_ LPDIRECT3DINDEXBUFFER9* ppIB) PURE; + STDMETHOD(LockVertexBuffer)(THIS_ DWORD Flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockVertexBuffer)(THIS) PURE; + STDMETHOD(LockIndexBuffer)(THIS_ DWORD Flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockIndexBuffer)(THIS) PURE; + STDMETHOD(GetAttributeTable)( + THIS_ D3DXATTRIBUTERANGE *pAttribTable, DWORD* pAttribTableSize) PURE; + + STDMETHOD(ConvertPointRepsToAdjacency)(THIS_ CONST DWORD* pPRep, DWORD* pAdjacency) PURE; + STDMETHOD(ConvertAdjacencyToPointReps)(THIS_ CONST DWORD* pAdjacency, DWORD* pPRep) PURE; + STDMETHOD(GenerateAdjacency)(THIS_ FLOAT Epsilon, DWORD* pAdjacency) PURE; + + STDMETHOD(UpdateSemantics)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + + // ID3DXMesh + STDMETHOD(LockAttributeBuffer)(THIS_ DWORD Flags, DWORD** ppData) PURE; + STDMETHOD(UnlockAttributeBuffer)(THIS) PURE; + STDMETHOD(Optimize)(THIS_ DWORD Flags, CONST DWORD* pAdjacencyIn, DWORD* pAdjacencyOut, + DWORD* pFaceRemap, LPD3DXBUFFER *ppVertexRemap, + LPD3DXMESH* ppOptMesh) PURE; + STDMETHOD(OptimizeInplace)(THIS_ DWORD Flags, CONST DWORD* pAdjacencyIn, DWORD* pAdjacencyOut, + DWORD* pFaceRemap, LPD3DXBUFFER *ppVertexRemap) PURE; + STDMETHOD(SetAttributeTable)(THIS_ CONST D3DXATTRIBUTERANGE *pAttribTable, DWORD cAttribTableSize) PURE; +}; + + +#undef INTERFACE +#define INTERFACE ID3DXPMesh + +DECLARE_INTERFACE_(ID3DXPMesh, ID3DXBaseMesh) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXBaseMesh + STDMETHOD(DrawSubset)(THIS_ DWORD AttribId) PURE; + STDMETHOD_(DWORD, GetNumFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetNumVertices)(THIS) PURE; + STDMETHOD_(DWORD, GetFVF)(THIS) PURE; + STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + STDMETHOD_(DWORD, GetNumBytesPerVertex)(THIS) PURE; + STDMETHOD_(DWORD, GetOptions)(THIS) PURE; + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(CloneMeshFVF)(THIS_ DWORD Options, + DWORD FVF, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(CloneMesh)(THIS_ DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(GetVertexBuffer)(THIS_ LPDIRECT3DVERTEXBUFFER9* ppVB) PURE; + STDMETHOD(GetIndexBuffer)(THIS_ LPDIRECT3DINDEXBUFFER9* ppIB) PURE; + STDMETHOD(LockVertexBuffer)(THIS_ DWORD Flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockVertexBuffer)(THIS) PURE; + STDMETHOD(LockIndexBuffer)(THIS_ DWORD Flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockIndexBuffer)(THIS) PURE; + STDMETHOD(GetAttributeTable)( + THIS_ D3DXATTRIBUTERANGE *pAttribTable, DWORD* pAttribTableSize) PURE; + + STDMETHOD(ConvertPointRepsToAdjacency)(THIS_ CONST DWORD* pPRep, DWORD* pAdjacency) PURE; + STDMETHOD(ConvertAdjacencyToPointReps)(THIS_ CONST DWORD* pAdjacency, DWORD* pPRep) PURE; + STDMETHOD(GenerateAdjacency)(THIS_ FLOAT Epsilon, DWORD* pAdjacency) PURE; + + STDMETHOD(UpdateSemantics)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + + // ID3DXPMesh + STDMETHOD(ClonePMeshFVF)(THIS_ DWORD Options, + DWORD FVF, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXPMESH* ppCloneMesh) PURE; + STDMETHOD(ClonePMesh)(THIS_ DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXPMESH* ppCloneMesh) PURE; + STDMETHOD(SetNumFaces)(THIS_ DWORD Faces) PURE; + STDMETHOD(SetNumVertices)(THIS_ DWORD Vertices) PURE; + STDMETHOD_(DWORD, GetMaxFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetMinFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetMaxVertices)(THIS) PURE; + STDMETHOD_(DWORD, GetMinVertices)(THIS) PURE; + STDMETHOD(Save)(THIS_ IStream *pStream, CONST D3DXMATERIAL* pMaterials, CONST D3DXEFFECTINSTANCE* pEffectInstances, DWORD NumMaterials) PURE; + + STDMETHOD(Optimize)(THIS_ DWORD Flags, DWORD* pAdjacencyOut, + DWORD* pFaceRemap, LPD3DXBUFFER *ppVertexRemap, + LPD3DXMESH* ppOptMesh) PURE; + + STDMETHOD(OptimizeBaseLOD)(THIS_ DWORD Flags, DWORD* pFaceRemap) PURE; + STDMETHOD(TrimByFaces)(THIS_ DWORD NewFacesMin, DWORD NewFacesMax, DWORD *rgiFaceRemap, DWORD *rgiVertRemap) PURE; + STDMETHOD(TrimByVertices)(THIS_ DWORD NewVerticesMin, DWORD NewVerticesMax, DWORD *rgiFaceRemap, DWORD *rgiVertRemap) PURE; + + STDMETHOD(GetAdjacency)(THIS_ DWORD* pAdjacency) PURE; + + // Used to generate the immediate "ancestor" for each vertex when it is removed by a vsplit. Allows generation of geomorphs + // Vertex buffer must be equal to or greater than the maximum number of vertices in the pmesh + STDMETHOD(GenerateVertexHistory)(THIS_ DWORD* pVertexHistory) PURE; +}; + + +#undef INTERFACE +#define INTERFACE ID3DXSPMesh + +DECLARE_INTERFACE_(ID3DXSPMesh, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXSPMesh + STDMETHOD_(DWORD, GetNumFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetNumVertices)(THIS) PURE; + STDMETHOD_(DWORD, GetFVF)(THIS) PURE; + STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + STDMETHOD_(DWORD, GetOptions)(THIS) PURE; + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD(CloneMeshFVF)(THIS_ DWORD Options, + DWORD FVF, LPDIRECT3DDEVICE9 pD3DDevice, DWORD *pAdjacencyOut, DWORD *pVertexRemapOut, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(CloneMesh)(THIS_ DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pD3DDevice, DWORD *pAdjacencyOut, DWORD *pVertexRemapOut, LPD3DXMESH* ppCloneMesh) PURE; + STDMETHOD(ClonePMeshFVF)(THIS_ DWORD Options, + DWORD FVF, LPDIRECT3DDEVICE9 pD3DDevice, DWORD *pVertexRemapOut, FLOAT *pErrorsByFace, LPD3DXPMESH* ppCloneMesh) PURE; + STDMETHOD(ClonePMesh)(THIS_ DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, LPDIRECT3DDEVICE9 pD3DDevice, DWORD *pVertexRemapOut, FLOAT *pErrorsbyFace, LPD3DXPMESH* ppCloneMesh) PURE; + STDMETHOD(ReduceFaces)(THIS_ DWORD Faces) PURE; + STDMETHOD(ReduceVertices)(THIS_ DWORD Vertices) PURE; + STDMETHOD_(DWORD, GetMaxFaces)(THIS) PURE; + STDMETHOD_(DWORD, GetMaxVertices)(THIS) PURE; + STDMETHOD(GetVertexAttributeWeights)(THIS_ LPD3DXATTRIBUTEWEIGHTS pVertexAttributeWeights) PURE; + STDMETHOD(GetVertexWeights)(THIS_ FLOAT *pVertexWeights) PURE; +}; + +#define UNUSED16 (0xffff) +#define UNUSED32 (0xffffffff) + +// ID3DXMesh::Optimize options - upper byte only, lower 3 bytes used from _D3DXMESH option flags +enum _D3DXMESHOPT { + D3DXMESHOPT_COMPACT = 0x01000000, + D3DXMESHOPT_ATTRSORT = 0x02000000, + D3DXMESHOPT_VERTEXCACHE = 0x04000000, + D3DXMESHOPT_STRIPREORDER = 0x08000000, + D3DXMESHOPT_IGNOREVERTS = 0x10000000, // optimize faces only, don't touch vertices + D3DXMESHOPT_DONOTSPLIT = 0x20000000, // do not split vertices shared between attribute groups when attribute sorting + D3DXMESHOPT_DEVICEINDEPENDENT = 0x00400000, // Only affects VCache. uses a static known good cache size for all cards + + // D3DXMESHOPT_SHAREVB has been removed, please use D3DXMESH_VB_SHARE instead + +}; + +// Subset of the mesh that has the same attribute and bone combination. +// This subset can be rendered in a single draw call +typedef struct _D3DXBONECOMBINATION +{ + DWORD AttribId; + DWORD FaceStart; + DWORD FaceCount; + DWORD VertexStart; + DWORD VertexCount; + DWORD* BoneId; +} D3DXBONECOMBINATION, *LPD3DXBONECOMBINATION; + +// The following types of patch combinations are supported: +// Patch type Basis Degree +// Rect Bezier 2,3,5 +// Rect B-Spline 2,3,5 +// Rect Catmull-Rom 3 +// Tri Bezier 2,3,5 +// N-Patch N/A 3 + +typedef struct _D3DXPATCHINFO +{ + D3DXPATCHMESHTYPE PatchType; + D3DDEGREETYPE Degree; + D3DBASISTYPE Basis; +} D3DXPATCHINFO, *LPD3DXPATCHINFO; + +#undef INTERFACE +#define INTERFACE ID3DXPatchMesh + +DECLARE_INTERFACE_(ID3DXPatchMesh, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXPatchMesh + + // Return creation parameters + STDMETHOD_(DWORD, GetNumPatches)(THIS) PURE; + STDMETHOD_(DWORD, GetNumVertices)(THIS) PURE; + STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + STDMETHOD_(DWORD, GetControlVerticesPerPatch)(THIS) PURE; + STDMETHOD_(DWORD, GetOptions)(THIS) PURE; + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9 *ppDevice) PURE; + STDMETHOD(GetPatchInfo)(THIS_ LPD3DXPATCHINFO PatchInfo) PURE; + + // Control mesh access + STDMETHOD(GetVertexBuffer)(THIS_ LPDIRECT3DVERTEXBUFFER9* ppVB) PURE; + STDMETHOD(GetIndexBuffer)(THIS_ LPDIRECT3DINDEXBUFFER9* ppIB) PURE; + STDMETHOD(LockVertexBuffer)(THIS_ DWORD flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockVertexBuffer)(THIS) PURE; + STDMETHOD(LockIndexBuffer)(THIS_ DWORD flags, LPVOID *ppData) PURE; + STDMETHOD(UnlockIndexBuffer)(THIS) PURE; + STDMETHOD(LockAttributeBuffer)(THIS_ DWORD flags, DWORD** ppData) PURE; + STDMETHOD(UnlockAttributeBuffer)(THIS) PURE; + + // This function returns the size of the tessellated mesh given a tessellation level. + // This assumes uniform tessellation. For adaptive tessellation the Adaptive parameter must + // be set to TRUE and TessellationLevel should be the max tessellation. + // This will result in the max mesh size necessary for adaptive tessellation. + STDMETHOD(GetTessSize)(THIS_ FLOAT fTessLevel,DWORD Adaptive, DWORD *NumTriangles,DWORD *NumVertices) PURE; + + //GenerateAdjacency determines which patches are adjacent with provided tolerance + //this information is used internally to optimize tessellation + STDMETHOD(GenerateAdjacency)(THIS_ FLOAT Tolerance) PURE; + + //CloneMesh Creates a new patchmesh with the specified decl, and converts the vertex buffer + //to the new decl. Entries in the new decl which are new are set to 0. If the current mesh + //has adjacency, the new mesh will also have adjacency + STDMETHOD(CloneMesh)(THIS_ DWORD Options, CONST D3DVERTEXELEMENT9 *pDecl, LPD3DXPATCHMESH *pMesh) PURE; + + // Optimizes the patchmesh for efficient tessellation. This function is designed + // to perform one time optimization for patch meshes that need to be tessellated + // repeatedly by calling the Tessellate() method. The optimization performed is + // independent of the actual tessellation level used. + // Currently Flags is unused. + // If vertices are changed, Optimize must be called again + STDMETHOD(Optimize)(THIS_ DWORD flags) PURE; + + //gets and sets displacement parameters + //displacement maps can only be 2D textures MIP-MAPPING is ignored for non adapative tessellation + STDMETHOD(SetDisplaceParam)(THIS_ LPDIRECT3DBASETEXTURE9 Texture, + D3DTEXTUREFILTERTYPE MinFilter, + D3DTEXTUREFILTERTYPE MagFilter, + D3DTEXTUREFILTERTYPE MipFilter, + D3DTEXTUREADDRESS Wrap, + DWORD dwLODBias) PURE; + + STDMETHOD(GetDisplaceParam)(THIS_ LPDIRECT3DBASETEXTURE9 *Texture, + D3DTEXTUREFILTERTYPE *MinFilter, + D3DTEXTUREFILTERTYPE *MagFilter, + D3DTEXTUREFILTERTYPE *MipFilter, + D3DTEXTUREADDRESS *Wrap, + DWORD *dwLODBias) PURE; + + // Performs the uniform tessellation based on the tessellation level. + // This function will perform more efficiently if the patch mesh has been optimized using the Optimize() call. + STDMETHOD(Tessellate)(THIS_ FLOAT fTessLevel,LPD3DXMESH pMesh) PURE; + + // Performs adaptive tessellation based on the Z based adaptive tessellation criterion. + // pTrans specifies a 4D vector that is dotted with the vertices to get the per vertex + // adaptive tessellation amount. Each edge is tessellated to the average of the criterion + // at the 2 vertices it connects. + // MaxTessLevel specifies the upper limit for adaptive tesselation. + // This function will perform more efficiently if the patch mesh has been optimized using the Optimize() call. + STDMETHOD(TessellateAdaptive)(THIS_ + CONST D3DXVECTOR4 *pTrans, + DWORD dwMaxTessLevel, + DWORD dwMinTessLevel, + LPD3DXMESH pMesh) PURE; + +}; + +#undef INTERFACE +#define INTERFACE ID3DXSkinInfo + +DECLARE_INTERFACE_(ID3DXSkinInfo, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Specify the which vertices do each bones influence and by how much + STDMETHOD(SetBoneInfluence)(THIS_ DWORD bone, DWORD numInfluences, CONST DWORD* vertices, CONST FLOAT* weights) PURE; + STDMETHOD(SetBoneVertexInfluence)(THIS_ DWORD boneNum, DWORD influenceNum, float weight) PURE; + STDMETHOD_(DWORD, GetNumBoneInfluences)(THIS_ DWORD bone) PURE; + STDMETHOD(GetBoneInfluence)(THIS_ DWORD bone, DWORD* vertices, FLOAT* weights) PURE; + STDMETHOD(GetBoneVertexInfluence)(THIS_ DWORD boneNum, DWORD influenceNum, float *pWeight, DWORD *pVertexNum) PURE; + STDMETHOD(GetMaxVertexInfluences)(THIS_ DWORD* maxVertexInfluences) PURE; + STDMETHOD_(DWORD, GetNumBones)(THIS) PURE; + STDMETHOD(FindBoneVertexInfluenceIndex)(THIS_ DWORD boneNum, DWORD vertexNum, DWORD *pInfluenceIndex) PURE; + + // This gets the max face influences based on a triangle mesh with the specified index buffer + STDMETHOD(GetMaxFaceInfluences)(THIS_ LPDIRECT3DINDEXBUFFER9 pIB, DWORD NumFaces, DWORD* maxFaceInfluences) PURE; + + // Set min bone influence. Bone influences that are smaller than this are ignored + STDMETHOD(SetMinBoneInfluence)(THIS_ FLOAT MinInfl) PURE; + // Get min bone influence. + STDMETHOD_(FLOAT, GetMinBoneInfluence)(THIS) PURE; + + // Bone names are returned by D3DXLoadSkinMeshFromXof. They are not used by any other method of this object + STDMETHOD(SetBoneName)(THIS_ DWORD Bone, LPCSTR pName) PURE; // pName is copied to an internal string buffer + STDMETHOD_(LPCSTR, GetBoneName)(THIS_ DWORD Bone) PURE; // A pointer to an internal string buffer is returned. Do not free this. + + // Bone offset matrices are returned by D3DXLoadSkinMeshFromXof. They are not used by any other method of this object + STDMETHOD(SetBoneOffsetMatrix)(THIS_ DWORD Bone, CONST D3DXMATRIX *pBoneTransform) PURE; // pBoneTransform is copied to an internal buffer + STDMETHOD_(LPD3DXMATRIX, GetBoneOffsetMatrix)(THIS_ DWORD Bone) PURE; // A pointer to an internal matrix is returned. Do not free this. + + // Clone a skin info object + STDMETHOD(Clone)(THIS_ LPD3DXSKININFO* ppSkinInfo) PURE; + + // Update bone influence information to match vertices after they are reordered. This should be called + // if the target vertex buffer has been reordered externally. + STDMETHOD(Remap)(THIS_ DWORD NumVertices, DWORD* pVertexRemap) PURE; + + // These methods enable the modification of the vertex layout of the vertices that will be skinned + STDMETHOD(SetFVF)(THIS_ DWORD FVF) PURE; + STDMETHOD(SetDeclaration)(THIS_ CONST D3DVERTEXELEMENT9 *pDeclaration) PURE; + STDMETHOD_(DWORD, GetFVF)(THIS) PURE; + STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE; + + // Apply SW skinning based on current pose matrices to the target vertices. + STDMETHOD(UpdateSkinnedMesh)(THIS_ + CONST D3DXMATRIX* pBoneTransforms, + CONST D3DXMATRIX* pBoneInvTransposeTransforms, + LPCVOID pVerticesSrc, + PVOID pVerticesDst) PURE; + + // Takes a mesh and returns a new mesh with per vertex blend weights and a bone combination + // table that describes which bones affect which subsets of the mesh + STDMETHOD(ConvertToBlendedMesh)(THIS_ + LPD3DXMESH pMesh, + DWORD Options, + CONST DWORD *pAdjacencyIn, + LPDWORD pAdjacencyOut, + DWORD* pFaceRemap, + LPD3DXBUFFER *ppVertexRemap, + DWORD* pMaxFaceInfl, + DWORD* pNumBoneCombinations, + LPD3DXBUFFER* ppBoneCombinationTable, + LPD3DXMESH* ppMesh) PURE; + + // Takes a mesh and returns a new mesh with per vertex blend weights and indices + // and a bone combination table that describes which bones palettes affect which subsets of the mesh + STDMETHOD(ConvertToIndexedBlendedMesh)(THIS_ + LPD3DXMESH pMesh, + DWORD Options, + DWORD paletteSize, + CONST DWORD *pAdjacencyIn, + LPDWORD pAdjacencyOut, + DWORD* pFaceRemap, + LPD3DXBUFFER *ppVertexRemap, + DWORD* pMaxVertexInfl, + DWORD* pNumBoneCombinations, + LPD3DXBUFFER* ppBoneCombinationTable, + LPD3DXMESH* ppMesh) PURE; +}; + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + +HRESULT WINAPI + D3DXCreateMesh( + DWORD NumFaces, + DWORD NumVertices, + DWORD Options, + CONST D3DVERTEXELEMENT9 *pDeclaration, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXMESH* ppMesh); + +HRESULT WINAPI + D3DXCreateMeshFVF( + DWORD NumFaces, + DWORD NumVertices, + DWORD Options, + DWORD FVF, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXMESH* ppMesh); + +HRESULT WINAPI + D3DXCreateSPMesh( + LPD3DXMESH pMesh, + CONST DWORD* pAdjacency, + CONST D3DXATTRIBUTEWEIGHTS *pVertexAttributeWeights, + CONST FLOAT *pVertexWeights, + LPD3DXSPMESH* ppSMesh); + +// clean a mesh up for simplification, try to make manifold +HRESULT WINAPI + D3DXCleanMesh( + D3DXCLEANTYPE CleanType, + LPD3DXMESH pMeshIn, + CONST DWORD* pAdjacencyIn, + LPD3DXMESH* ppMeshOut, + DWORD* pAdjacencyOut, + LPD3DXBUFFER* ppErrorsAndWarnings); + +HRESULT WINAPI + D3DXValidMesh( + LPD3DXMESH pMeshIn, + CONST DWORD* pAdjacency, + LPD3DXBUFFER* ppErrorsAndWarnings); + +HRESULT WINAPI + D3DXGeneratePMesh( + LPD3DXMESH pMesh, + CONST DWORD* pAdjacency, + CONST D3DXATTRIBUTEWEIGHTS *pVertexAttributeWeights, + CONST FLOAT *pVertexWeights, + DWORD MinValue, + DWORD Options, + LPD3DXPMESH* ppPMesh); + +HRESULT WINAPI + D3DXSimplifyMesh( + LPD3DXMESH pMesh, + CONST DWORD* pAdjacency, + CONST D3DXATTRIBUTEWEIGHTS *pVertexAttributeWeights, + CONST FLOAT *pVertexWeights, + DWORD MinValue, + DWORD Options, + LPD3DXMESH* ppMesh); + +HRESULT WINAPI + D3DXComputeBoundingSphere( + CONST D3DXVECTOR3 *pFirstPosition, // pointer to first position + DWORD NumVertices, + DWORD dwStride, // count in bytes to subsequent position vectors + D3DXVECTOR3 *pCenter, + FLOAT *pRadius); + +HRESULT WINAPI + D3DXComputeBoundingBox( + CONST D3DXVECTOR3 *pFirstPosition, // pointer to first position + DWORD NumVertices, + DWORD dwStride, // count in bytes to subsequent position vectors + D3DXVECTOR3 *pMin, + D3DXVECTOR3 *pMax); + +HRESULT WINAPI + D3DXComputeNormals( + LPD3DXBASEMESH pMesh, + CONST DWORD *pAdjacency); + +HRESULT WINAPI + D3DXCreateBuffer( + DWORD NumBytes, + LPD3DXBUFFER *ppBuffer); + + +HRESULT WINAPI + D3DXLoadMeshFromXA( + LPCSTR pFilename, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppAdjacency, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD *pNumMaterials, + LPD3DXMESH *ppMesh); + +HRESULT WINAPI + D3DXLoadMeshFromXW( + LPCWSTR pFilename, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppAdjacency, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD *pNumMaterials, + LPD3DXMESH *ppMesh); + +#ifdef UNICODE +#define D3DXLoadMeshFromX D3DXLoadMeshFromXW +#else +#define D3DXLoadMeshFromX D3DXLoadMeshFromXA +#endif + +HRESULT WINAPI + D3DXLoadMeshFromXInMemory( + LPCVOID Memory, + DWORD SizeOfMemory, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppAdjacency, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD *pNumMaterials, + LPD3DXMESH *ppMesh); + +HRESULT WINAPI + D3DXLoadMeshFromXResource( + HMODULE Module, + LPCSTR Name, + LPCSTR Type, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppAdjacency, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD *pNumMaterials, + LPD3DXMESH *ppMesh); + +HRESULT WINAPI + D3DXSaveMeshToXA( + LPCSTR pFilename, + LPD3DXMESH pMesh, + CONST DWORD* pAdjacency, + CONST D3DXMATERIAL* pMaterials, + CONST D3DXEFFECTINSTANCE* pEffectInstances, + DWORD NumMaterials, + DWORD Format + ); + +HRESULT WINAPI + D3DXSaveMeshToXW( + LPCWSTR pFilename, + LPD3DXMESH pMesh, + CONST DWORD* pAdjacency, + CONST D3DXMATERIAL* pMaterials, + CONST D3DXEFFECTINSTANCE* pEffectInstances, + DWORD NumMaterials, + DWORD Format + ); + +#ifdef UNICODE +#define D3DXSaveMeshToX D3DXSaveMeshToXW +#else +#define D3DXSaveMeshToX D3DXSaveMeshToXA +#endif + + +HRESULT WINAPI + D3DXCreatePMeshFromStream( + IStream *pStream, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD* pNumMaterials, + LPD3DXPMESH *ppPMesh); + +// Creates a skin info object based on the number of vertices, number of bones, and a declaration describing the vertex layout of the target vertices +// The bone names and initial bone transforms are not filled in the skin info object by this method. +HRESULT WINAPI + D3DXCreateSkinInfo( + DWORD NumVertices, + CONST D3DVERTEXELEMENT9 *pDeclaration, + DWORD NumBones, + LPD3DXSKININFO* ppSkinInfo); + +// Creates a skin info object based on the number of vertices, number of bones, and a FVF describing the vertex layout of the target vertices +// The bone names and initial bone transforms are not filled in the skin info object by this method. +HRESULT WINAPI + D3DXCreateSkinInfoFVF( + DWORD NumVertices, + DWORD FVF, + DWORD NumBones, + LPD3DXSKININFO* ppSkinInfo); + +#ifdef __cplusplus +} + +extern "C" { +#endif //__cplusplus + +HRESULT WINAPI + D3DXLoadMeshFromXof( + LPD3DXFILEDATA pxofMesh, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppAdjacency, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD *pNumMaterials, + LPD3DXMESH *ppMesh); + +// This similar to D3DXLoadMeshFromXof, except also returns skinning info if present in the file +// If skinning info is not present, ppSkinInfo will be NULL +HRESULT WINAPI + D3DXLoadSkinMeshFromXof( + LPD3DXFILEDATA pxofMesh, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER* ppAdjacency, + LPD3DXBUFFER* ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + DWORD *pMatOut, + LPD3DXSKININFO* ppSkinInfo, + LPD3DXMESH* ppMesh); + + +// The inverse of D3DXConvertTo{Indexed}BlendedMesh() functions. It figures out the skinning info from +// the mesh and the bone combination table and populates a skin info object with that data. The bone +// names and initial bone transforms are not filled in the skin info object by this method. This works +// with either a non-indexed or indexed blended mesh. It examines the FVF or declarator of the mesh to +// determine what type it is. +HRESULT WINAPI + D3DXCreateSkinInfoFromBlendedMesh( + LPD3DXBASEMESH pMesh, + DWORD NumBones, + CONST D3DXBONECOMBINATION *pBoneCombinationTable, + LPD3DXSKININFO* ppSkinInfo); + +HRESULT WINAPI + D3DXTessellateNPatches( + LPD3DXMESH pMeshIn, + CONST DWORD* pAdjacencyIn, + FLOAT NumSegs, + BOOL QuadraticInterpNormals, // if false use linear intrep for normals, if true use quadratic + LPD3DXMESH *ppMeshOut, + LPD3DXBUFFER *ppAdjacencyOut); + + +//generates implied outputdecl from input decl +//the decl generated from this should be used to generate the output decl for +//the tessellator subroutines. + +HRESULT WINAPI + D3DXGenerateOutputDecl( + D3DVERTEXELEMENT9 *pOutput, + CONST D3DVERTEXELEMENT9 *pInput); + +//loads patches from an XFileData +//since an X file can have up to 6 different patch meshes in it, +//returns them in an array - pNumPatches will contain the number of +//meshes in the actual file. +HRESULT WINAPI + D3DXLoadPatchMeshFromXof( + LPD3DXFILEDATA pXofObjMesh, + DWORD Options, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXBUFFER *ppMaterials, + LPD3DXBUFFER *ppEffectInstances, + PDWORD pNumMaterials, + LPD3DXPATCHMESH *ppMesh); + +//computes the size a single rect patch. +HRESULT WINAPI + D3DXRectPatchSize( + CONST FLOAT *pfNumSegs, //segments for each edge (4) + DWORD *pdwTriangles, //output number of triangles + DWORD *pdwVertices); //output number of vertices + +//computes the size of a single triangle patch +HRESULT WINAPI + D3DXTriPatchSize( + CONST FLOAT *pfNumSegs, //segments for each edge (3) + DWORD *pdwTriangles, //output number of triangles + DWORD *pdwVertices); //output number of vertices + + +//tessellates a patch into a created mesh +//similar to D3D RT patch +HRESULT WINAPI + D3DXTessellateRectPatch( + LPDIRECT3DVERTEXBUFFER9 pVB, + CONST FLOAT *pNumSegs, + CONST D3DVERTEXELEMENT9 *pdwInDecl, + CONST D3DRECTPATCH_INFO *pRectPatchInfo, + LPD3DXMESH pMesh); + + +HRESULT WINAPI + D3DXTessellateTriPatch( + LPDIRECT3DVERTEXBUFFER9 pVB, + CONST FLOAT *pNumSegs, + CONST D3DVERTEXELEMENT9 *pInDecl, + CONST D3DTRIPATCH_INFO *pTriPatchInfo, + LPD3DXMESH pMesh); + + + +//creates an NPatch PatchMesh from a D3DXMESH +HRESULT WINAPI + D3DXCreateNPatchMesh( + LPD3DXMESH pMeshSysMem, + LPD3DXPATCHMESH *pPatchMesh); + + +//creates a patch mesh +HRESULT WINAPI + D3DXCreatePatchMesh( + CONST D3DXPATCHINFO *pInfo, //patch type + DWORD dwNumPatches, //number of patches + DWORD dwNumVertices, //number of control vertices + DWORD dwOptions, //options + CONST D3DVERTEXELEMENT9 *pDecl, //format of control vertices + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXPATCHMESH *pPatchMesh); + + +//returns the number of degenerates in a patch mesh - +//text output put in string. +HRESULT WINAPI + D3DXValidPatchMesh(LPD3DXPATCHMESH pMesh, + DWORD *dwcDegenerateVertices, + DWORD *dwcDegeneratePatches, + LPD3DXBUFFER *ppErrorsAndWarnings); + +UINT WINAPI + D3DXGetFVFVertexSize(DWORD FVF); + +UINT WINAPI + D3DXGetDeclVertexSize(CONST D3DVERTEXELEMENT9 *pDecl,DWORD Stream); + +UINT WINAPI + D3DXGetDeclLength(CONST D3DVERTEXELEMENT9 *pDecl); + +HRESULT WINAPI + D3DXDeclaratorFromFVF( + DWORD FVF, + D3DVERTEXELEMENT9 pDeclarator[MAX_FVF_DECL_SIZE]); + +HRESULT WINAPI + D3DXFVFFromDeclarator( + CONST D3DVERTEXELEMENT9 *pDeclarator, + DWORD *pFVF); + +HRESULT WINAPI + D3DXWeldVertices( + LPD3DXMESH pMesh, + DWORD Flags, + CONST D3DXWELDEPSILONS *pEpsilons, + CONST DWORD *pAdjacencyIn, + DWORD *pAdjacencyOut, + DWORD *pFaceRemap, + LPD3DXBUFFER *ppVertexRemap); + +typedef struct _D3DXINTERSECTINFO +{ + DWORD FaceIndex; // index of face intersected + FLOAT U; // Barycentric Hit Coordinates + FLOAT V; // Barycentric Hit Coordinates + FLOAT Dist; // Ray-Intersection Parameter Distance +} D3DXINTERSECTINFO, *LPD3DXINTERSECTINFO; + + +HRESULT WINAPI + D3DXIntersect( + LPD3DXBASEMESH pMesh, + CONST D3DXVECTOR3 *pRayPos, + CONST D3DXVECTOR3 *pRayDir, + BOOL *pHit, // True if any faces were intersected + DWORD *pFaceIndex, // index of closest face intersected + FLOAT *pU, // Barycentric Hit Coordinates + FLOAT *pV, // Barycentric Hit Coordinates + FLOAT *pDist, // Ray-Intersection Parameter Distance + LPD3DXBUFFER *ppAllHits, // Array of D3DXINTERSECTINFOs for all hits (not just closest) + DWORD *pCountOfHits); // Number of entries in AllHits array + +HRESULT WINAPI + D3DXIntersectSubset( + LPD3DXBASEMESH pMesh, + DWORD AttribId, + CONST D3DXVECTOR3 *pRayPos, + CONST D3DXVECTOR3 *pRayDir, + BOOL *pHit, // True if any faces were intersected + DWORD *pFaceIndex, // index of closest face intersected + FLOAT *pU, // Barycentric Hit Coordinates + FLOAT *pV, // Barycentric Hit Coordinates + FLOAT *pDist, // Ray-Intersection Parameter Distance + LPD3DXBUFFER *ppAllHits, // Array of D3DXINTERSECTINFOs for all hits (not just closest) + DWORD *pCountOfHits); // Number of entries in AllHits array + + +HRESULT WINAPI D3DXSplitMesh + ( + LPD3DXMESH pMeshIn, + CONST DWORD *pAdjacencyIn, + CONST DWORD MaxSize, + CONST DWORD Options, + DWORD *pMeshesOut, + LPD3DXBUFFER *ppMeshArrayOut, + LPD3DXBUFFER *ppAdjacencyArrayOut, + LPD3DXBUFFER *ppFaceRemapArrayOut, + LPD3DXBUFFER *ppVertRemapArrayOut + ); + +BOOL WINAPI D3DXIntersectTri +( + CONST D3DXVECTOR3 *p0, // Triangle vertex 0 position + CONST D3DXVECTOR3 *p1, // Triangle vertex 1 position + CONST D3DXVECTOR3 *p2, // Triangle vertex 2 position + CONST D3DXVECTOR3 *pRayPos, // Ray origin + CONST D3DXVECTOR3 *pRayDir, // Ray direction + FLOAT *pU, // Barycentric Hit Coordinates + FLOAT *pV, // Barycentric Hit Coordinates + FLOAT *pDist); // Ray-Intersection Parameter Distance + +BOOL WINAPI + D3DXSphereBoundProbe( + CONST D3DXVECTOR3 *pCenter, + FLOAT Radius, + CONST D3DXVECTOR3 *pRayPosition, + CONST D3DXVECTOR3 *pRayDirection); + +BOOL WINAPI + D3DXBoxBoundProbe( + CONST D3DXVECTOR3 *pMin, + CONST D3DXVECTOR3 *pMax, + CONST D3DXVECTOR3 *pRayPosition, + CONST D3DXVECTOR3 *pRayDirection); + + +HRESULT WINAPI D3DXComputeTangentFrame(ID3DXMesh *pMesh, + DWORD dwOptions); + +HRESULT WINAPI D3DXComputeTangentFrameEx(ID3DXMesh *pMesh, + DWORD dwTextureInSemantic, + DWORD dwTextureInIndex, + DWORD dwUPartialOutSemantic, + DWORD dwUPartialOutIndex, + DWORD dwVPartialOutSemantic, + DWORD dwVPartialOutIndex, + DWORD dwNormalOutSemantic, + DWORD dwNormalOutIndex, + DWORD dwOptions, + CONST DWORD *pdwAdjacency, + FLOAT fPartialEdgeThreshold, + FLOAT fSingularPointThreshold, + FLOAT fNormalEdgeThreshold, + ID3DXMesh **ppMeshOut, + ID3DXBuffer **ppVertexMapping); + + +//D3DXComputeTangent +// +//Computes the Tangent vectors for the TexStage texture coordinates +//and places the results in the TANGENT[TangentIndex] specified in the meshes' DECL +//puts the binorm in BINORM[BinormIndex] also specified in the decl. +// +//If neither the binorm or the tangnet are in the meshes declaration, +//the function will fail. +// +//If a tangent or Binorm field is in the Decl, but the user does not +//wish D3DXComputeTangent to replace them, then D3DX_DEFAULT specified +//in the TangentIndex or BinormIndex will cause it to ignore the specified +//semantic. +// +//Wrap should be specified if the texture coordinates wrap. + +HRESULT WINAPI D3DXComputeTangent(LPD3DXMESH Mesh, + DWORD TexStage, + DWORD TangentIndex, + DWORD BinormIndex, + DWORD Wrap, + CONST DWORD *pAdjacency); + +//============================================================================ +// +// UVAtlas apis +// +//============================================================================ +typedef HRESULT (WINAPI *LPD3DXUVATLASCB)(FLOAT fPercentDone, LPVOID lpUserContext); + +// This function creates atlases for meshes. There are two modes of operation, +// either based on the number of charts, or the maximum allowed stretch. If the +// maximum allowed stretch is 0, then each triangle will likely be in its own +// chart. + +// +// The parameters are as follows: +// pMesh - Input mesh to calculate an atlas for. This must have a position +// channel and at least a 2-d texture channel. +// uMaxChartNumber - The maximum number of charts required for the atlas. +// If this is 0, it will be parameterized based solely on +// stretch. +// fMaxStretch - The maximum amount of stretch, if 0, no stretching is allowed, +// if 1, then any amount of stretching is allowed. +// uWidth - The width of the texture the atlas will be used on. +// uHeight - The height of the texture the atlas will be used on. +// fGutter - The minimum distance, in texels between two charts on the atlas. +// this gets scaled by the width, so if fGutter is 2.5, and it is +// used on a 512x512 texture, then the minimum distance will be +// 2.5 / 512 in u-v space. +// dwTextureIndex - Specifies which texture coordinate to write to in the +// output mesh (which is cloned from the input mesh). Useful +// if your vertex has multiple texture coordinates. +// pdwAdjacency - a pointer to an array with 3 DWORDs per face, indicating +// which triangles are adjacent to each other. +// pdwFalseEdgeAdjacency - a pointer to an array with 3 DWORDS per face, indicating +// at each face, whether an edge is a false edge or not (using +// the same ordering as the adjacency data structure). If this +// is NULL, then it is assumed that there are no false edges. If +// not NULL, then a non-false edge is indicated by -1 and a false +// edge is indicated by any other value (it is not required, but +// it may be useful for the caller to use the original adjacency +// value). This allows you to parameterize a mesh of quads, and +// the edges down the middle of each quad will not be cut when +// parameterizing the mesh. +// pfIMTArray - a pointer to an array with 3 FLOATs per face, describing the +// integrated metric tensor for that face. This lets you control +// the way this triangle may be stretched in the atlas. The IMT +// passed in will be 3 floats (a,b,c) and specify a symmetric +// matrix (a b) that, given a vector (s,t), specifies the +// (b c) +// distance between a vector v1 and a vector v2 = v1 + (s,t) as +// sqrt((s, t) * M * (s, t)^T). +// In other words, this lets one specify the magnitude of the +// stretch in an arbitrary direction in u-v space. For example +// if a = b = c = 1, then this scales the vector (1,1) by 2, and +// the vector (1,-1) by 0. Note that this is multiplying the edge +// length by the square of the matrix, so if you want the face to +// stretch to twice its +// size with no shearing, the IMT value should be (2, 0, 2), which +// is just the identity matrix times 2. +// Note that this assumes you have an orientation for the triangle +// in some 2-D space. For D3DXUVAtlas, this space is created by +// letting S be the direction from the first to the second +// vertex, and T be the cross product between the normal and S. +// +// pStatusCallback - Since the atlas creation process can be very CPU intensive, +// this allows the programmer to specify a function to be called +// periodically, similarly to how it is done in the PRT simulation +// engine. +// fCallbackFrequency - This lets you specify how often the callback will be +// called. A decent default should be 0.0001f. +// pUserContext - a void pointer to be passed back to the callback function +// dwOptions - A combination of flags in the D3DXUVATLAS enum +// ppMeshOut - A pointer to a location to store a pointer for the newly created +// mesh. +// ppFacePartitioning - A pointer to a location to store a pointer for an array, +// one DWORD per face, giving the final partitioning +// created by the atlasing algorithm. +// ppVertexRemapArray - A pointer to a location to store a pointer for an array, +// one DWORD per vertex, giving the vertex it was copied +// from, if any vertices needed to be split. +// pfMaxStretchOut - A location to store the maximum stretch resulting from the +// atlasing algorithm. +// puNumChartsOut - A location to store the number of charts created, or if the +// maximum number of charts was too low, this gives the minimum +// number of charts needed to create an atlas. + +HRESULT WINAPI D3DXUVAtlasCreate(LPD3DXMESH pMesh, + UINT uMaxChartNumber, + FLOAT fMaxStretch, + UINT uWidth, + UINT uHeight, + FLOAT fGutter, + DWORD dwTextureIndex, + CONST DWORD *pdwAdjacency, + CONST DWORD *pdwFalseEdgeAdjacency, + CONST FLOAT *pfIMTArray, + LPD3DXUVATLASCB pStatusCallback, + FLOAT fCallbackFrequency, + LPVOID pUserContext, + DWORD dwOptions, + LPD3DXMESH *ppMeshOut, + LPD3DXBUFFER *ppFacePartitioning, + LPD3DXBUFFER *ppVertexRemapArray, + FLOAT *pfMaxStretchOut, + UINT *puNumChartsOut); + +// This has the same exact arguments as Create, except that it does not perform the +// final packing step. This method allows one to get a partitioning out, and possibly +// modify it before sending it to be repacked. Note that if you change the +// partitioning, you'll also need to calculate new texture coordinates for any faces +// that have switched charts. +// +// The partition result adjacency output parameter is meant to be passed to the +// UVAtlasPack function, this adjacency cuts edges that are between adjacent +// charts, and also can include cuts inside of a chart in order to make it +// equivalent to a disc. For example: +// +// _______ +// | ___ | +// | |_| | +// |_____| +// +// In order to make this equivalent to a disc, we would need to add a cut, and it +// Would end up looking like: +// _______ +// | ___ | +// | |_|_| +// |_____| +// +// The resulting partition adjacency parameter cannot be NULL, because it is +// required for the packing step. + + + +HRESULT WINAPI D3DXUVAtlasPartition(LPD3DXMESH pMesh, + UINT uMaxChartNumber, + FLOAT fMaxStretch, + DWORD dwTextureIndex, + CONST DWORD *pdwAdjacency, + CONST DWORD *pdwFalseEdgeAdjacency, + CONST FLOAT *pfIMTArray, + LPD3DXUVATLASCB pStatusCallback, + FLOAT fCallbackFrequency, + LPVOID pUserContext, + DWORD dwOptions, + LPD3DXMESH *ppMeshOut, + LPD3DXBUFFER *ppFacePartitioning, + LPD3DXBUFFER *ppVertexRemapArray, + LPD3DXBUFFER *ppPartitionResultAdjacency, + FLOAT *pfMaxStretchOut, + UINT *puNumChartsOut); + +// This takes the face partitioning result from Partition and packs it into an +// atlas of the given size. pdwPartitionResultAdjacency should be derived from +// the adjacency returned from the partition step. This value cannot be NULL +// because Pack needs to know where charts were cut in the partition step in +// order to find the edges of each chart. +// The options parameter is currently reserved. +HRESULT WINAPI D3DXUVAtlasPack(ID3DXMesh *pMesh, + UINT uWidth, + UINT uHeight, + FLOAT fGutter, + DWORD dwTextureIndex, + CONST DWORD *pdwPartitionResultAdjacency, + LPD3DXUVATLASCB pStatusCallback, + FLOAT fCallbackFrequency, + LPVOID pUserContext, + DWORD dwOptions, + LPD3DXBUFFER pFacePartitioning); + + +//============================================================================ +// +// IMT Calculation apis +// +// These functions all compute the Integrated Metric Tensor for use in the +// UVAtlas API. They all calculate the IMT with respect to the canonical +// triangle, where the coordinate system is set up so that the u axis goes +// from vertex 0 to 1 and the v axis is N x u. So, for example, the second +// vertex's canonical uv coordinates are (d,0) where d is the distance between +// vertices 0 and 1. This way the IMT does not depend on the parameterization +// of the mesh, and if the signal over the surface doesn't change, then +// the IMT doesn't need to be recalculated. +//============================================================================ + +// This callback is used by D3DXComputeIMTFromSignal. +// +// uv - The texture coordinate for the vertex. +// uPrimitiveID - Face ID of the triangle on which to compute the signal. +// uSignalDimension - The number of floats to store in pfSignalOut. +// pUserData - The pUserData pointer passed in to ComputeIMTFromSignal. +// pfSignalOut - A pointer to where to store the signal data. +typedef HRESULT (WINAPI* LPD3DXIMTSIGNALCALLBACK) + (CONST D3DXVECTOR2 *uv, + UINT uPrimitiveID, + UINT uSignalDimension, + VOID *pUserData, + FLOAT *pfSignalOut); + +// This function is used to calculate the IMT from per vertex data. It sets +// up a linear system over the triangle, solves for the jacobian J, then +// constructs the IMT from that (J^TJ). +// This function allows you to calculate the IMT based off of any value in a +// mesh (color, normal, etc) by specifying the correct stride of the array. +// The IMT computed will cause areas of the mesh that have similar values to +// take up less space in the texture. +// +// pMesh - The mesh to calculate the IMT for. +// pVertexSignal - A float array of size uSignalStride * v, where v is the +// number of vertices in the mesh. +// uSignalDimension - How many floats per vertex to use in calculating the IMT. +// uSignalStride - The number of bytes per vertex in the array. This must be +// a multiple of sizeof(float) +// ppIMTData - Where to store the buffer holding the IMT data + +HRESULT WINAPI D3DXComputeIMTFromPerVertexSignal ( + LPD3DXMESH pMesh, + CONST FLOAT *pfVertexSignal, // uSignalDimension floats per vertex + UINT uSignalDimension, + UINT uSignalStride, // stride of signal in bytes + DWORD dwOptions, // reserved for future use + LPD3DXUVATLASCB pStatusCallback, + LPVOID pUserContext, + LPD3DXBUFFER *ppIMTData); + +// This function is used to calculate the IMT from data that varies over the +// surface of the mesh (generally at a higher frequency than vertex data). +// This function requires the mesh to already be parameterized (so it already +// has texture coordinates). It allows the user to define a signal arbitrarily +// over the surface of the mesh. +// +// pMesh - The mesh to calculate the IMT for. +// dwTextureIndex - This describes which set of texture coordinates in the +// mesh to use. +// uSignalDimension - How many components there are in the signal. +// fMaxUVDistance - The subdivision will continue until the distance between +// all vertices is at most fMaxUVDistance. +// dwOptions - reserved for future use +// pSignalCallback - The callback to use to get the signal. +// pUserData - A pointer that will be passed in to the callback. +// ppIMTData - Where to store the buffer holding the IMT data +HRESULT WINAPI D3DXComputeIMTFromSignal( + LPD3DXMESH pMesh, + DWORD dwTextureIndex, + UINT uSignalDimension, + FLOAT fMaxUVDistance, + DWORD dwOptions, // reserved for future use + LPD3DXIMTSIGNALCALLBACK pSignalCallback, + VOID *pUserData, + LPD3DXUVATLASCB pStatusCallback, + LPVOID pUserContext, + LPD3DXBUFFER *ppIMTData); + +// This function is used to calculate the IMT from texture data. Given a texture +// that maps over the surface of the mesh, the algorithm computes the IMT for +// each face. This will cause large areas that are very similar to take up less +// room when parameterized with UVAtlas. The texture is assumed to be +// interpolated over the mesh bilinearly. +// +// pMesh - The mesh to calculate the IMT for. +// pTexture - The texture to load data from. +// dwTextureIndex - This describes which set of texture coordinates in the +// mesh to use. +// dwOptions - Combination of one or more D3DXIMT flags. +// ppIMTData - Where to store the buffer holding the IMT data +HRESULT WINAPI D3DXComputeIMTFromTexture ( + LPD3DXMESH pMesh, + LPDIRECT3DTEXTURE9 pTexture, + DWORD dwTextureIndex, + DWORD dwOptions, + LPD3DXUVATLASCB pStatusCallback, + LPVOID pUserContext, + LPD3DXBUFFER *ppIMTData); + +// This function is very similar to ComputeIMTFromTexture, but it uses a +// float array to pass in the data, and it can calculate higher dimensional +// values than 4. +// +// pMesh - The mesh to calculate the IMT for. +// dwTextureIndex - This describes which set of texture coordinates in the +// mesh to use. +// pfFloatArray - a pointer to a float array of size +// uWidth*uHeight*uComponents +// uWidth - The width of the texture +// uHeight - The height of the texture +// uSignalDimension - The number of floats per texel in the signal +// uComponents - The number of floats in each texel +// dwOptions - Combination of one or more D3DXIMT flags +// ppIMTData - Where to store the buffer holding the IMT data +HRESULT WINAPI D3DXComputeIMTFromPerTexelSignal( + LPD3DXMESH pMesh, + DWORD dwTextureIndex, + FLOAT *pfTexelSignal, + UINT uWidth, + UINT uHeight, + UINT uSignalDimension, + UINT uComponents, + DWORD dwOptions, + LPD3DXUVATLASCB pStatusCallback, + LPVOID pUserContext, + LPD3DXBUFFER *ppIMTData); + +HRESULT WINAPI + D3DXConvertMeshSubsetToSingleStrip( + LPD3DXBASEMESH MeshIn, + DWORD AttribId, + DWORD IBOptions, + LPDIRECT3DINDEXBUFFER9 *ppIndexBuffer, + DWORD *pNumIndices); + +HRESULT WINAPI + D3DXConvertMeshSubsetToStrips( + LPD3DXBASEMESH MeshIn, + DWORD AttribId, + DWORD IBOptions, + LPDIRECT3DINDEXBUFFER9 *ppIndexBuffer, + DWORD *pNumIndices, + LPD3DXBUFFER *ppStripLengths, + DWORD *pNumStrips); + + +//============================================================================ +// +// D3DXOptimizeFaces: +// -------------------- +// Generate a face remapping for a triangle list that more effectively utilizes +// vertex caches. This optimization is identical to the one provided +// by ID3DXMesh::Optimize with the hardware independent option enabled. +// +// Parameters: +// pbIndices +// Triangle list indices to use for generating a vertex ordering +// NumFaces +// Number of faces in the triangle list +// NumVertices +// Number of vertices referenced by the triangle list +// b32BitIndices +// TRUE if indices are 32 bit, FALSE if indices are 16 bit +// pFaceRemap +// Destination buffer to store face ordering +// The number stored for a given element is where in the new ordering +// the face will have come from. See ID3DXMesh::Optimize for more info. +// +//============================================================================ +HRESULT WINAPI + D3DXOptimizeFaces( + LPCVOID pbIndices, + UINT cFaces, + UINT cVertices, + BOOL b32BitIndices, + DWORD* pFaceRemap); + +//============================================================================ +// +// D3DXOptimizeVertices: +// -------------------- +// Generate a vertex remapping to optimize for in order use of vertices for +// a given set of indices. This is commonly used after applying the face +// remap generated by D3DXOptimizeFaces +// +// Parameters: +// pbIndices +// Triangle list indices to use for generating a vertex ordering +// NumFaces +// Number of faces in the triangle list +// NumVertices +// Number of vertices referenced by the triangle list +// b32BitIndices +// TRUE if indices are 32 bit, FALSE if indices are 16 bit +// pVertexRemap +// Destination buffer to store vertex ordering +// The number stored for a given element is where in the new ordering +// the vertex will have come from. See ID3DXMesh::Optimize for more info. +// +//============================================================================ +HRESULT WINAPI + D3DXOptimizeVertices( + LPCVOID pbIndices, + UINT cFaces, + UINT cVertices, + BOOL b32BitIndices, + DWORD* pVertexRemap); + +#ifdef __cplusplus +} +#endif //__cplusplus + + +//=========================================================================== +// +// Data structures for Spherical Harmonic Precomputation +// +// +//============================================================================ + +typedef enum _D3DXSHCOMPRESSQUALITYTYPE { + D3DXSHCQUAL_FASTLOWQUALITY = 1, + D3DXSHCQUAL_SLOWHIGHQUALITY = 2, + D3DXSHCQUAL_FORCE_DWORD = 0x7fffffff +} D3DXSHCOMPRESSQUALITYTYPE; + +typedef enum _D3DXSHGPUSIMOPT { + D3DXSHGPUSIMOPT_SHADOWRES256 = 1, + D3DXSHGPUSIMOPT_SHADOWRES512 = 0, + D3DXSHGPUSIMOPT_SHADOWRES1024 = 2, + D3DXSHGPUSIMOPT_SHADOWRES2048 = 3, + + D3DXSHGPUSIMOPT_HIGHQUALITY = 4, + + D3DXSHGPUSIMOPT_FORCE_DWORD = 0x7fffffff +} D3DXSHGPUSIMOPT; + +// for all properties that are colors the luminance is computed +// if the simulator is run with a single channel using the following +// formula: R * 0.2125 + G * 0.7154 + B * 0.0721 + +typedef struct _D3DXSHMATERIAL { + D3DCOLORVALUE Diffuse; // Diffuse albedo of the surface. (Ignored if object is a Mirror) + BOOL bMirror; // Must be set to FALSE. bMirror == TRUE not currently supported + BOOL bSubSurf; // true if the object does subsurface scattering - can't do this and be a mirror + + // subsurface scattering parameters + FLOAT RelativeIndexOfRefraction; + D3DCOLORVALUE Absorption; + D3DCOLORVALUE ReducedScattering; + +} D3DXSHMATERIAL; + +// allocated in D3DXSHPRTCompSplitMeshSC +// vertices are duplicated into multiple super clusters but +// only have a valid status in one super cluster (fill in the rest) + +typedef struct _D3DXSHPRTSPLITMESHVERTDATA { + UINT uVertRemap; // vertex in original mesh this corresponds to + UINT uSubCluster; // cluster index relative to super cluster + UCHAR ucVertStatus; // 1 if vertex has valid data, 0 if it is "fill" +} D3DXSHPRTSPLITMESHVERTDATA; + +// used in D3DXSHPRTCompSplitMeshSC +// information for each super cluster that maps into face/vert arrays + +typedef struct _D3DXSHPRTSPLITMESHCLUSTERDATA { + UINT uVertStart; // initial index into remapped vertex array + UINT uVertLength; // number of vertices in this super cluster + + UINT uFaceStart; // initial index into face array + UINT uFaceLength; // number of faces in this super cluster + + UINT uClusterStart; // initial index into cluster array + UINT uClusterLength; // number of clusters in this super cluster +} D3DXSHPRTSPLITMESHCLUSTERDATA; + +// call back function for simulator +// return S_OK to keep running the simulator - anything else represents +// failure and the simulator will abort. + +typedef HRESULT (WINAPI *LPD3DXSHPRTSIMCB)(float fPercentDone, LPVOID lpUserContext); + +// interfaces for PRT buffers/simulator + +// GUIDs +// {F1827E47-00A8-49cd-908C-9D11955F8728} +DEFINE_GUID(IID_ID3DXPRTBuffer, +0xf1827e47, 0xa8, 0x49cd, 0x90, 0x8c, 0x9d, 0x11, 0x95, 0x5f, 0x87, 0x28); + +// {A758D465-FE8D-45ad-9CF0-D01E56266A07} +DEFINE_GUID(IID_ID3DXPRTCompBuffer, +0xa758d465, 0xfe8d, 0x45ad, 0x9c, 0xf0, 0xd0, 0x1e, 0x56, 0x26, 0x6a, 0x7); + +// {838F01EC-9729-4527-AADB-DF70ADE7FEA9} +DEFINE_GUID(IID_ID3DXTextureGutterHelper, +0x838f01ec, 0x9729, 0x4527, 0xaa, 0xdb, 0xdf, 0x70, 0xad, 0xe7, 0xfe, 0xa9); + +// {683A4278-CD5F-4d24-90AD-C4E1B6855D53} +DEFINE_GUID(IID_ID3DXPRTEngine, +0x683a4278, 0xcd5f, 0x4d24, 0x90, 0xad, 0xc4, 0xe1, 0xb6, 0x85, 0x5d, 0x53); + +// interface defenitions + +typedef interface ID3DXTextureGutterHelper ID3DXTextureGutterHelper; +typedef interface ID3DXPRTBuffer ID3DXPRTBuffer; + +#undef INTERFACE +#define INTERFACE ID3DXPRTBuffer + +// Buffer interface - contains "NumSamples" samples +// each sample in memory is stored as NumCoeffs scalars per channel (1 or 3) +// Same interface is used for both Vertex and Pixel PRT buffers + +DECLARE_INTERFACE_(ID3DXPRTBuffer, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXPRTBuffer + STDMETHOD_(UINT, GetNumSamples)(THIS) PURE; + STDMETHOD_(UINT, GetNumCoeffs)(THIS) PURE; + STDMETHOD_(UINT, GetNumChannels)(THIS) PURE; + + STDMETHOD_(BOOL, IsTexture)(THIS) PURE; + STDMETHOD_(UINT, GetWidth)(THIS) PURE; + STDMETHOD_(UINT, GetHeight)(THIS) PURE; + + // changes the number of samples allocated in the buffer + STDMETHOD(Resize)(THIS_ UINT NewSize) PURE; + + // ppData will point to the memory location where sample Start begins + // pointer is valid for at least NumSamples samples + STDMETHOD(LockBuffer)(THIS_ UINT Start, UINT NumSamples, FLOAT **ppData) PURE; + STDMETHOD(UnlockBuffer)(THIS) PURE; + + // every scalar in buffer is multiplied by Scale + STDMETHOD(ScaleBuffer)(THIS_ FLOAT Scale) PURE; + + // every scalar contains the sum of this and pBuffers values + // pBuffer must have the same storage class/dimensions + STDMETHOD(AddBuffer)(THIS_ LPD3DXPRTBUFFER pBuffer) PURE; + + // GutterHelper (described below) will fill in the gutter + // regions of a texture by interpolating "internal" values + STDMETHOD(AttachGH)(THIS_ LPD3DXTEXTUREGUTTERHELPER) PURE; + STDMETHOD(ReleaseGH)(THIS) PURE; + + // Evaluates attached gutter helper on the contents of this buffer + STDMETHOD(EvalGH)(THIS) PURE; + + // extracts a given channel into texture pTexture + // NumCoefficients starting from StartCoefficient are copied + STDMETHOD(ExtractTexture)(THIS_ UINT Channel, UINT StartCoefficient, + UINT NumCoefficients, LPDIRECT3DTEXTURE9 pTexture) PURE; + + // extracts NumCoefficients coefficients into mesh - only applicable on single channel + // buffers, otherwise just lockbuffer and copy data. With SHPRT data NumCoefficients + // should be Order^2 + STDMETHOD(ExtractToMesh)(THIS_ UINT NumCoefficients, D3DDECLUSAGE Usage, UINT UsageIndexStart, + LPD3DXMESH pScene) PURE; + +}; + +typedef interface ID3DXPRTCompBuffer ID3DXPRTCompBuffer; +typedef interface ID3DXPRTCompBuffer *LPD3DXPRTCOMPBUFFER; + +#undef INTERFACE +#define INTERFACE ID3DXPRTCompBuffer + +// compressed buffers stored a compressed version of a PRTBuffer + +DECLARE_INTERFACE_(ID3DXPRTCompBuffer, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DPRTCompBuffer + + // NumCoeffs and NumChannels are properties of input buffer + STDMETHOD_(UINT, GetNumSamples)(THIS) PURE; + STDMETHOD_(UINT, GetNumCoeffs)(THIS) PURE; + STDMETHOD_(UINT, GetNumChannels)(THIS) PURE; + + STDMETHOD_(BOOL, IsTexture)(THIS) PURE; + STDMETHOD_(UINT, GetWidth)(THIS) PURE; + STDMETHOD_(UINT, GetHeight)(THIS) PURE; + + // number of clusters, and PCA vectors per-cluster + STDMETHOD_(UINT, GetNumClusters)(THIS) PURE; + STDMETHOD_(UINT, GetNumPCA)(THIS) PURE; + + // normalizes PCA weights so that they are between [-1,1] + // basis vectors are modified to reflect this + STDMETHOD(NormalizeData)(THIS) PURE; + + // copies basis vectors for cluster "Cluster" into pClusterBasis + // (NumPCA+1)*NumCoeffs*NumChannels floats + STDMETHOD(ExtractBasis)(THIS_ UINT Cluster, FLOAT *pClusterBasis) PURE; + + // UINT per sample - which cluster it belongs to + STDMETHOD(ExtractClusterIDs)(THIS_ UINT *pClusterIDs) PURE; + + // copies NumExtract PCA projection coefficients starting at StartPCA + // into pPCACoefficients - NumSamples*NumExtract floats copied + STDMETHOD(ExtractPCA)(THIS_ UINT StartPCA, UINT NumExtract, FLOAT *pPCACoefficients) PURE; + + // copies NumPCA projection coefficients starting at StartPCA + // into pTexture - should be able to cope with signed formats + STDMETHOD(ExtractTexture)(THIS_ UINT StartPCA, UINT NumpPCA, + LPDIRECT3DTEXTURE9 pTexture) PURE; + + // copies NumPCA projection coefficients into mesh pScene + // Usage is D3DDECLUSAGE where coefficients are to be stored + // UsageIndexStart is starting index + STDMETHOD(ExtractToMesh)(THIS_ UINT NumPCA, D3DDECLUSAGE Usage, UINT UsageIndexStart, + LPD3DXMESH pScene) PURE; +}; + + +#undef INTERFACE +#define INTERFACE ID3DXTextureGutterHelper + +// ID3DXTextureGutterHelper will build and manage +// "gutter" regions in a texture - this will allow for +// bi-linear interpolation to not have artifacts when rendering +// It generates a map (in texture space) where each texel +// is in one of 3 states: +// 0 Invalid - not used at all +// 1 Inside triangle +// 2 Gutter texel +// 4 represents a gutter texel that will be computed during PRT +// For each Inside/Gutter texel it stores the face it +// belongs to and barycentric coordinates for the 1st two +// vertices of that face. Gutter vertices are assigned to +// the closest edge in texture space. +// +// When used with PRT this requires a unique parameterization +// of the model - every texel must correspond to a single point +// on the surface of the model and vice versa + +DECLARE_INTERFACE_(ID3DXTextureGutterHelper, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXTextureGutterHelper + + // dimensions of texture this is bound too + STDMETHOD_(UINT, GetWidth)(THIS) PURE; + STDMETHOD_(UINT, GetHeight)(THIS) PURE; + + + // Applying gutters recomputes all of the gutter texels of class "2" + // based on texels of class "1" or "4" + + // Applies gutters to a raw float buffer - each texel is NumCoeffs floats + // Width and Height must match GutterHelper + STDMETHOD(ApplyGuttersFloat)(THIS_ FLOAT *pDataIn, UINT NumCoeffs, UINT Width, UINT Height); + + // Applies gutters to pTexture + // Dimensions must match GutterHelper + STDMETHOD(ApplyGuttersTex)(THIS_ LPDIRECT3DTEXTURE9 pTexture); + + // Applies gutters to a D3DXPRTBuffer + // Dimensions must match GutterHelper + STDMETHOD(ApplyGuttersPRT)(THIS_ LPD3DXPRTBUFFER pBuffer); + + // Resamples a texture from a mesh onto this gutterhelpers + // parameterization. It is assumed that the UV coordinates + // for this gutter helper are in TEXTURE 0 (usage/usage index) + // and the texture coordinates should all be within [0,1] for + // both sets. + // + // pTextureIn - texture represented using parameterization in pMeshIn + // pMeshIn - Mesh with texture coordinates that represent pTextureIn + // pTextureOut texture coordinates are assumed to be in + // TEXTURE 0 + // Usage - field in DECL for pMeshIn that stores texture coordinates + // for pTextureIn + // UsageIndex - which index for Usage above for pTextureIn + // pTextureOut- Resampled texture + // + // Usage would generally be D3DDECLUSAGE_TEXCOORD and UsageIndex other than zero + STDMETHOD(ResampleTex)(THIS_ LPDIRECT3DTEXTURE9 pTextureIn, + LPD3DXMESH pMeshIn, + D3DDECLUSAGE Usage, UINT UsageIndex, + LPDIRECT3DTEXTURE9 pTextureOut); + + // the routines below provide access to the data structures + // used by the Apply functions + + // face map is a UINT per texel that represents the + // face of the mesh that texel belongs too - + // only valid if same texel is valid in pGutterData + // pFaceData must be allocated by the user + STDMETHOD(GetFaceMap)(THIS_ UINT *pFaceData) PURE; + + // BaryMap is a D3DXVECTOR2 per texel + // the 1st two barycentric coordinates for the corresponding + // face (3rd weight is always 1-sum of first two) + // only valid if same texel is valid in pGutterData + // pBaryData must be allocated by the user + STDMETHOD(GetBaryMap)(THIS_ D3DXVECTOR2 *pBaryData) PURE; + + // TexelMap is a D3DXVECTOR2 per texel that + // stores the location in pixel coordinates where the + // corresponding texel is mapped + // pTexelData must be allocated by the user + STDMETHOD(GetTexelMap)(THIS_ D3DXVECTOR2 *pTexelData) PURE; + + // GutterMap is a BYTE per texel + // 0/1/2 for Invalid/Internal/Gutter texels + // 4 represents a gutter texel that will be computed + // during PRT + // pGutterData must be allocated by the user + STDMETHOD(GetGutterMap)(THIS_ BYTE *pGutterData) PURE; + + // face map is a UINT per texel that represents the + // face of the mesh that texel belongs too - + // only valid if same texel is valid in pGutterData + STDMETHOD(SetFaceMap)(THIS_ UINT *pFaceData) PURE; + + // BaryMap is a D3DXVECTOR2 per texel + // the 1st two barycentric coordinates for the corresponding + // face (3rd weight is always 1-sum of first two) + // only valid if same texel is valid in pGutterData + STDMETHOD(SetBaryMap)(THIS_ D3DXVECTOR2 *pBaryData) PURE; + + // TexelMap is a D3DXVECTOR2 per texel that + // stores the location in pixel coordinates where the + // corresponding texel is mapped + STDMETHOD(SetTexelMap)(THIS_ D3DXVECTOR2 *pTexelData) PURE; + + // GutterMap is a BYTE per texel + // 0/1/2 for Invalid/Internal/Gutter texels + // 4 represents a gutter texel that will be computed + // during PRT + STDMETHOD(SetGutterMap)(THIS_ BYTE *pGutterData) PURE; +}; + + +typedef interface ID3DXPRTEngine ID3DXPRTEngine; +typedef interface ID3DXPRTEngine *LPD3DXPRTENGINE; + +#undef INTERFACE +#define INTERFACE ID3DXPRTEngine + +// ID3DXPRTEngine is used to compute a PRT simulation +// Use the following steps to compute PRT for SH +// (1) create an interface (which includes a scene) +// (2) call SetSamplingInfo +// (3) [optional] Set MeshMaterials/albedo's (required if doing bounces) +// (4) call ComputeDirectLightingSH +// (5) [optional] call ComputeBounce +// repeat step 5 for as many bounces as wanted. +// if you want to model subsurface scattering you +// need to call ComputeSS after direct lighting and +// each bounce. +// If you want to bake the albedo into the PRT signal, you +// must call MutliplyAlbedo, otherwise the user has to multiply +// the albedo themselves. Not multiplying the albedo allows you +// to model albedo variation at a finer scale then illumination, and +// can result in better compression results. +// Luminance values are computed from RGB values using the following +// formula: R * 0.2125 + G * 0.7154 + B * 0.0721 + +DECLARE_INTERFACE_(ID3DXPRTEngine, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXPRTEngine + + // This sets a material per attribute in the scene mesh and it is + // the only way to specify subsurface scattering parameters. if + // bSetAlbedo is FALSE, NumChannels must match the current + // configuration of the PRTEngine. If you intend to change + // NumChannels (through some other SetAlbedo function) it must + // happen before SetMeshMaterials is called. + // + // NumChannels 1 implies "grayscale" materials, set this to 3 to enable + // color bleeding effects + // bSetAlbedo sets albedo from material if TRUE - which clobbers per texel/vertex + // albedo that might have been set before. FALSE won't clobber. + // fLengthScale is used for subsurface scattering - scene is mapped into a 1mm unit cube + // and scaled by this amount + STDMETHOD(SetMeshMaterials)(THIS_ CONST D3DXSHMATERIAL **ppMaterials, UINT NumMeshes, + UINT NumChannels, BOOL bSetAlbedo, FLOAT fLengthScale) PURE; + + // setting albedo per-vertex or per-texel over rides the albedos stored per mesh + // but it does not over ride any other settings + + // sets an albedo to be used per vertex - the albedo is represented as a float + // pDataIn input pointer (pointint to albedo of 1st sample) + // NumChannels 1 implies "grayscale" materials, set this to 3 to enable + // color bleeding effects + // Stride - stride in bytes to get to next samples albedo + STDMETHOD(SetPerVertexAlbedo)(THIS_ CONST VOID *pDataIn, UINT NumChannels, UINT Stride) PURE; + + // represents the albedo per-texel instead of per-vertex (even if per-vertex PRT is used) + // pAlbedoTexture - texture that stores the albedo (dimension arbitrary) + // NumChannels 1 implies "grayscale" materials, set this to 3 to enable + // color bleeding effects + // pGH - optional gutter helper, otherwise one is constructed in computation routines and + // destroyed (if not attached to buffers) + STDMETHOD(SetPerTexelAlbedo)(THIS_ LPDIRECT3DTEXTURE9 pAlbedoTexture, + UINT NumChannels, + LPD3DXTEXTUREGUTTERHELPER pGH) PURE; + + // gets the per-vertex albedo + STDMETHOD(GetVertexAlbedo)(THIS_ D3DXCOLOR *pVertColors, UINT NumVerts) PURE; + + // If pixel PRT is being computed normals default to ones that are interpolated + // from the vertex normals. This specifies a texture that stores an object + // space normal map instead (must use a texture format that can represent signed values) + // pNormalTexture - normal map, must be same dimensions as PRTBuffers, signed + STDMETHOD(SetPerTexelNormal)(THIS_ LPDIRECT3DTEXTURE9 pNormalTexture) PURE; + + // Copies per-vertex albedo from mesh + // pMesh - mesh that represents the scene. It must have the same + // properties as the mesh used to create the PRTEngine + // Usage - D3DDECLUSAGE to extract albedos from + // NumChannels 1 implies "grayscale" materials, set this to 3 to enable + // color bleeding effects + STDMETHOD(ExtractPerVertexAlbedo)(THIS_ LPD3DXMESH pMesh, + D3DDECLUSAGE Usage, + UINT NumChannels) PURE; + + // Resamples the input buffer into the output buffer + // can be used to move between per-vertex and per-texel buffers. This can also be used + // to convert single channel buffers to 3-channel buffers and vice-versa. + STDMETHOD(ResampleBuffer)(THIS_ LPD3DXPRTBUFFER pBufferIn, LPD3DXPRTBUFFER pBufferOut) PURE; + + // Returns the scene mesh - including modifications from adaptive spatial sampling + // The returned mesh only has positions, normals and texture coordinates (if defined) + // pD3DDevice - d3d device that will be used to allocate the mesh + // pFaceRemap - each face has a pointer back to the face on the original mesh that it comes from + // if the face hasn't been subdivided this will be an identity mapping + // pVertRemap - each vertex contains 3 vertices that this is a linear combination of + // pVertWeights - weights for each of above indices (sum to 1.0f) + // ppMesh - mesh that will be allocated and filled + STDMETHOD(GetAdaptedMesh)(THIS_ LPDIRECT3DDEVICE9 pD3DDevice,UINT *pFaceRemap, UINT *pVertRemap, FLOAT *pfVertWeights, LPD3DXMESH *ppMesh) PURE; + + // Number of vertices currently allocated (includes new vertices from adaptive sampling) + STDMETHOD_(UINT, GetNumVerts)(THIS) PURE; + // Number of faces currently allocated (includes new faces) + STDMETHOD_(UINT, GetNumFaces)(THIS) PURE; + + // Sets the Minimum/Maximum intersection distances, this can be used to control + // maximum distance that objects can shadow/reflect light, and help with "bad" + // art that might have near features that you don't want to shadow. This does not + // apply for GPU simulations. + // fMin - minimum intersection distance, must be positive and less than fMax + // fMax - maximum intersection distance, if 0.0f use the previous value, otherwise + // must be strictly greater than fMin + STDMETHOD(SetMinMaxIntersection)(THIS_ FLOAT fMin, FLOAT fMax) PURE; + + // This will subdivide faces on a mesh so that adaptively simulations can + // use a more conservative threshold (it won't miss features.) + // MinEdgeLength - minimum edge length that will be generated, if 0.0f a + // reasonable default will be used + // MaxSubdiv - maximum level of subdivision, if 0 is specified a default + // value will be used (5) + STDMETHOD(RobustMeshRefine)(THIS_ FLOAT MinEdgeLength, UINT MaxSubdiv) PURE; + + // This sets to sampling information used by the simulator. Adaptive sampling + // parameters are currently ignored. + // NumRays - number of rays to shoot per sample + // UseSphere - if TRUE uses spherical samples, otherwise samples over + // the hemisphere. Should only be used with GPU and Vol computations + // UseCosine - if TRUE uses a cosine weighting - not used for Vol computations + // or if only the visiblity function is desired + // Adaptive - if TRUE adaptive sampling (angular) is used + // AdaptiveThresh - threshold used to terminate adaptive angular sampling + // ignored if adaptive sampling is not set + STDMETHOD(SetSamplingInfo)(THIS_ UINT NumRays, + BOOL UseSphere, + BOOL UseCosine, + BOOL Adaptive, + FLOAT AdaptiveThresh) PURE; + + // Methods that compute the direct lighting contribution for objects + // always represente light using spherical harmonics (SH) + // the albedo is not multiplied by the signal - it just integrates + // incoming light. If NumChannels is not 1 the vector is replicated + // + // SHOrder - order of SH to use + // pDataOut - PRT buffer that is generated. Can be single channel + STDMETHOD(ComputeDirectLightingSH)(THIS_ UINT SHOrder, + LPD3DXPRTBUFFER pDataOut) PURE; + + // Adaptive variant of above function. This will refine the mesh + // generating new vertices/faces to approximate the PRT signal + // more faithfully. + // SHOrder - order of SH to use + // AdaptiveThresh - threshold for adaptive subdivision (in PRT vector error) + // if value is less then 1e-6f, 1e-6f is specified + // MinEdgeLength - minimum edge length that will be generated + // if value is too small a fairly conservative model dependent value + // is used + // MaxSubdiv - maximum subdivision level, if 0 is specified it + // will default to 4 + // pDataOut - PRT buffer that is generated. Can be single channel. + STDMETHOD(ComputeDirectLightingSHAdaptive)(THIS_ UINT SHOrder, + FLOAT AdaptiveThresh, + FLOAT MinEdgeLength, + UINT MaxSubdiv, + LPD3DXPRTBUFFER pDataOut) PURE; + + // Function that computes the direct lighting contribution for objects + // light is always represented using spherical harmonics (SH) + // This is done on the GPU and is much faster then using the CPU. + // The albedo is not multiplied by the signal - it just integrates + // incoming light. If NumChannels is not 1 the vector is replicated. + // ZBias/ZAngleBias are akin to parameters used with shadow zbuffers. + // A reasonable default for both values is 0.005, but the user should + // experiment (ZAngleBias can be zero, ZBias should not be.) + // Callbacks should not use the Direct3D9Device the simulator is using. + // SetSamplingInfo must be called with TRUE for UseSphere and + // FALSE for UseCosine before this method is called. + // + // pD3DDevice - device used to run GPU simulator - must support PS2.0 + // and FP render targets + // Flags - parameters for the GPU simulator, combination of one or more + // D3DXSHGPUSIMOPT flags. Only one SHADOWRES setting should be set and + // the defaults is 512 + // SHOrder - order of SH to use + // ZBias - bias in normal direction (for depth test) + // ZAngleBias - scaled by one minus cosine of angle with light (offset in depth) + // pDataOut - PRT buffer that is filled in. Can be single channel + STDMETHOD(ComputeDirectLightingSHGPU)(THIS_ LPDIRECT3DDEVICE9 pD3DDevice, + UINT Flags, + UINT SHOrder, + FLOAT ZBias, + FLOAT ZAngleBias, + LPD3DXPRTBUFFER pDataOut) PURE; + + + // Functions that computes subsurface scattering (using material properties) + // Albedo is not multiplied by result. This only works for per-vertex data + // use ResampleBuffer to move per-vertex data into a texture and back. + // + // pDataIn - input data (previous bounce) + // pDataOut - result of subsurface scattering simulation + // pDataTotal - [optional] results can be summed into this buffer + STDMETHOD(ComputeSS)(THIS_ LPD3DXPRTBUFFER pDataIn, + LPD3DXPRTBUFFER pDataOut, LPD3DXPRTBUFFER pDataTotal) PURE; + + // Adaptive version of ComputeSS. + // + // pDataIn - input data (previous bounce) + // AdaptiveThresh - threshold for adaptive subdivision (in PRT vector error) + // if value is less then 1e-6f, 1e-6f is specified + // MinEdgeLength - minimum edge length that will be generated + // if value is too small a fairly conservative model dependent value + // is used + // MaxSubdiv - maximum subdivision level, if 0 is specified it + // will default to 4 + // pDataOut - result of subsurface scattering simulation + // pDataTotal - [optional] results can be summed into this buffer + STDMETHOD(ComputeSSAdaptive)(THIS_ LPD3DXPRTBUFFER pDataIn, + FLOAT AdaptiveThresh, + FLOAT MinEdgeLength, + UINT MaxSubdiv, + LPD3DXPRTBUFFER pDataOut, LPD3DXPRTBUFFER pDataTotal) PURE; + + // computes a single bounce of inter-reflected light + // works for SH based PRT or generic lighting + // Albedo is not multiplied by result + // + // pDataIn - previous bounces data + // pDataOut - PRT buffer that is generated + // pDataTotal - [optional] can be used to keep a running sum + STDMETHOD(ComputeBounce)(THIS_ LPD3DXPRTBUFFER pDataIn, + LPD3DXPRTBUFFER pDataOut, + LPD3DXPRTBUFFER pDataTotal) PURE; + + // Adaptive version of above function. + // + // pDataIn - previous bounces data, can be single channel + // AdaptiveThresh - threshold for adaptive subdivision (in PRT vector error) + // if value is less then 1e-6f, 1e-6f is specified + // MinEdgeLength - minimum edge length that will be generated + // if value is too small a fairly conservative model dependent value + // is used + // MaxSubdiv - maximum subdivision level, if 0 is specified it + // will default to 4 + // pDataOut - PRT buffer that is generated + // pDataTotal - [optional] can be used to keep a running sum + STDMETHOD(ComputeBounceAdaptive)(THIS_ LPD3DXPRTBUFFER pDataIn, + FLOAT AdaptiveThresh, + FLOAT MinEdgeLength, + UINT MaxSubdiv, + LPD3DXPRTBUFFER pDataOut, + LPD3DXPRTBUFFER pDataTotal) PURE; + + // Computes projection of distant SH radiance into a local SH radiance + // function. This models how direct lighting is attenuated by the + // scene and is a form of "neighborhood transfer." The result is + // a linear operator (matrix) at every sample point, if you multiply + // this matrix by the distant SH lighting coefficients you get an + // approximation of the local incident radiance function from + // direct lighting. These resulting lighting coefficients can + // than be projected into another basis or used with any rendering + // technique that uses spherical harmonics as input. + // SetSamplingInfo must be called with TRUE for UseSphere and + // FALSE for UseCosine before this method is called. + // Generates SHOrderIn*SHOrderIn*SHOrderOut*SHOrderOut scalars + // per channel at each sample location. + // + // SHOrderIn - Order of the SH representation of distant lighting + // SHOrderOut - Order of the SH representation of local lighting + // NumVolSamples - Number of sample locations + // pSampleLocs - position of sample locations + // pDataOut - PRT Buffer that will store output results + STDMETHOD(ComputeVolumeSamplesDirectSH)(THIS_ UINT SHOrderIn, + UINT SHOrderOut, + UINT NumVolSamples, + CONST D3DXVECTOR3 *pSampleLocs, + LPD3DXPRTBUFFER pDataOut) PURE; + + // At each sample location computes a linear operator (matrix) that maps + // the representation of source radiance (NumCoeffs in pSurfDataIn) + // into a local incident radiance function approximated with spherical + // harmonics. For example if a light map data is specified in pSurfDataIn + // the result is an SH representation of the flow of light at each sample + // point. If PRT data for an outdoor scene is used, each sample point + // contains a matrix that models how distant lighting bounces of the objects + // in the scene and arrives at the given sample point. Combined with + // ComputeVolumeSamplesDirectSH this gives the complete representation for + // how light arrives at each sample point parameterized by distant lighting. + // SetSamplingInfo must be called with TRUE for UseSphere and + // FALSE for UseCosine before this method is called. + // Generates pSurfDataIn->NumCoeffs()*SHOrder*SHOrder scalars + // per channel at each sample location. + // + // pSurfDataIn - previous bounce data + // SHOrder - order of SH to generate projection with + // NumVolSamples - Number of sample locations + // pSampleLocs - position of sample locations + // pDataOut - PRT Buffer that will store output results + STDMETHOD(ComputeVolumeSamples)(THIS_ LPD3DXPRTBUFFER pSurfDataIn, + UINT SHOrder, + UINT NumVolSamples, + CONST D3DXVECTOR3 *pSampleLocs, + LPD3DXPRTBUFFER pDataOut) PURE; + + // Computes direct lighting (SH) for a point not on the mesh + // with a given normal - cannot use texture buffers. + // + // SHOrder - order of SH to use + // NumSamples - number of sample locations + // pSampleLocs - position for each sample + // pSampleNorms - normal for each sample + // pDataOut - PRT Buffer that will store output results + STDMETHOD(ComputeSurfSamplesDirectSH)(THIS_ UINT SHOrder, + UINT NumSamples, + CONST D3DXVECTOR3 *pSampleLocs, + CONST D3DXVECTOR3 *pSampleNorms, + LPD3DXPRTBUFFER pDataOut) PURE; + + + // given the solution for PRT or light maps, computes transfer vector at arbitrary + // position/normal pairs in space + // + // pSurfDataIn - input data + // NumSamples - number of sample locations + // pSampleLocs - position for each sample + // pSampleNorms - normal for each sample + // pDataOut - PRT Buffer that will store output results + // pDataTotal - optional buffer to sum results into - can be NULL + STDMETHOD(ComputeSurfSamplesBounce)(THIS_ LPD3DXPRTBUFFER pSurfDataIn, + UINT NumSamples, + CONST D3DXVECTOR3 *pSampleLocs, + CONST D3DXVECTOR3 *pSampleNorms, + LPD3DXPRTBUFFER pDataOut, + LPD3DXPRTBUFFER pDataTotal) PURE; + + // Frees temporary data structures that can be created for subsurface scattering + // this data is freed when the PRTComputeEngine is freed and is lazily created + STDMETHOD(FreeSSData)(THIS) PURE; + + // Frees temporary data structures that can be created for bounce simulations + // this data is freed when the PRTComputeEngine is freed and is lazily created + STDMETHOD(FreeBounceData)(THIS) PURE; + + // This computes the Local Deformable PRT (LDPRT) coefficients relative to the + // per sample normals that minimize error in a least squares sense with respect + // to the input PRT data set. These coefficients can be used with skinned/transformed + // normals to model global effects with dynamic objects. Shading normals can + // optionally be solved for - these normals (along with the LDPRT coefficients) can + // more accurately represent the PRT signal. The coefficients are for zonal + // harmonics oriented in the normal/shading normal direction. + // + // pDataIn - SH PRT dataset that is input + // SHOrder - Order of SH to compute conv coefficients for + // pNormOut - Optional array of vectors (passed in) that will be filled with + // "shading normals", LDPRT coefficients are optimized for + // these normals. This array must be the same size as the number of + // samples in pDataIn + // pDataOut - Output buffer (SHOrder zonal harmonic coefficients per channel per sample) + STDMETHOD(ComputeLDPRTCoeffs)(THIS_ LPD3DXPRTBUFFER pDataIn, + UINT SHOrder, + D3DXVECTOR3 *pNormOut, + LPD3DXPRTBUFFER pDataOut) PURE; + + // scales all the samples associated with a given sub mesh + // can be useful when using subsurface scattering + // fScale - value to scale each vector in submesh by + STDMETHOD(ScaleMeshChunk)(THIS_ UINT uMeshChunk, FLOAT fScale, LPD3DXPRTBUFFER pDataOut) PURE; + + // mutliplies each PRT vector by the albedo - can be used if you want to have the albedo + // burned into the dataset, often better not to do this. If this is not done the user + // must mutliply the albedo themselves when rendering - just multiply the albedo times + // the result of the PRT dot product. + // If pDataOut is a texture simulation result and there is an albedo texture it + // must be represented at the same resolution as the simulation buffer. You can use + // LoadSurfaceFromSurface and set a new albedo texture if this is an issue - but must + // be careful about how the gutters are handled. + // + // pDataOut - dataset that will get albedo pushed into it + STDMETHOD(MultiplyAlbedo)(THIS_ LPD3DXPRTBUFFER pDataOut) PURE; + + // Sets a pointer to an optional call back function that reports back to the + // user percentage done and gives them the option of quitting + // pCB - pointer to call back function, return S_OK for the simulation + // to continue + // Frequency - 1/Frequency is roughly the number of times the call back + // will be invoked + // lpUserContext - will be passed back to the users call back + STDMETHOD(SetCallBack)(THIS_ LPD3DXSHPRTSIMCB pCB, FLOAT Frequency, LPVOID lpUserContext) PURE; + + // Returns TRUE if the ray intersects the mesh, FALSE if it does not. This function + // takes into account settings from SetMinMaxIntersection. If the closest intersection + // is not needed this function is more efficient compared to the ClosestRayIntersection + // method. + // pRayPos - origin of ray + // pRayDir - normalized ray direction (normalization required for SetMinMax to be meaningful) + + STDMETHOD_(BOOL, ShadowRayIntersects)(THIS_ CONST D3DXVECTOR3 *pRayPos, CONST D3DXVECTOR3 *pRayDir) PURE; + + // Returns TRUE if the ray intersects the mesh, FALSE if it does not. If there is an + // intersection the closest face that was intersected and its first two barycentric coordinates + // are returned. This function takes into account settings from SetMinMaxIntersection. + // This is a slower function compared to ShadowRayIntersects and should only be used where + // needed. The third vertices barycentric coordinates will be 1 - pU - pV. + // pRayPos - origin of ray + // pRayDir - normalized ray direction (normalization required for SetMinMax to be meaningful) + // pFaceIndex - Closest face that intersects. This index is based on stacking the pBlockerMesh + // faces before the faces from pMesh + // pU - Barycentric coordinate for vertex 0 + // pV - Barycentric coordinate for vertex 1 + // pDist - Distance along ray where the intersection occured + + STDMETHOD_(BOOL, ClosestRayIntersects)(THIS_ CONST D3DXVECTOR3 *pRayPos, CONST D3DXVECTOR3 *pRayDir, + DWORD *pFaceIndex, FLOAT *pU, FLOAT *pV, FLOAT *pDist) PURE; +}; + + +// API functions for creating interfaces + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +//============================================================================ +// +// D3DXCreatePRTBuffer: +// -------------------- +// Generates a PRT Buffer that can be compressed or filled by a simulator +// This function should be used to create per-vertex or volume buffers. +// When buffers are created all values are initialized to zero. +// +// Parameters: +// NumSamples +// Number of sample locations represented +// NumCoeffs +// Number of coefficients per sample location (order^2 for SH) +// NumChannels +// Number of color channels to represent (1 or 3) +// ppBuffer +// Buffer that will be allocated +// +//============================================================================ + +HRESULT WINAPI + D3DXCreatePRTBuffer( + UINT NumSamples, + UINT NumCoeffs, + UINT NumChannels, + LPD3DXPRTBUFFER* ppBuffer); + +//============================================================================ +// +// D3DXCreatePRTBufferTex: +// -------------------- +// Generates a PRT Buffer that can be compressed or filled by a simulator +// This function should be used to create per-pixel buffers. +// When buffers are created all values are initialized to zero. +// +// Parameters: +// Width +// Width of texture +// Height +// Height of texture +// NumCoeffs +// Number of coefficients per sample location (order^2 for SH) +// NumChannels +// Number of color channels to represent (1 or 3) +// ppBuffer +// Buffer that will be allocated +// +//============================================================================ + +HRESULT WINAPI + D3DXCreatePRTBufferTex( + UINT Width, + UINT Height, + UINT NumCoeffs, + UINT NumChannels, + LPD3DXPRTBUFFER* ppBuffer); + +//============================================================================ +// +// D3DXLoadPRTBufferFromFile: +// -------------------- +// Loads a PRT buffer that has been saved to disk. +// +// Parameters: +// pFilename +// Name of the file to load +// ppBuffer +// Buffer that will be allocated +// +//============================================================================ + +HRESULT WINAPI + D3DXLoadPRTBufferFromFileA( + LPCSTR pFilename, + LPD3DXPRTBUFFER* ppBuffer); + +HRESULT WINAPI + D3DXLoadPRTBufferFromFileW( + LPCWSTR pFilename, + LPD3DXPRTBUFFER* ppBuffer); + +#ifdef UNICODE +#define D3DXLoadPRTBufferFromFile D3DXLoadPRTBufferFromFileW +#else +#define D3DXLoadPRTBufferFromFile D3DXLoadPRTBufferFromFileA +#endif + + +//============================================================================ +// +// D3DXSavePRTBufferToFile: +// -------------------- +// Saves a PRTBuffer to disk. +// +// Parameters: +// pFilename +// Name of the file to save +// pBuffer +// Buffer that will be saved +// +//============================================================================ + +HRESULT WINAPI + D3DXSavePRTBufferToFileA( + LPCSTR pFileName, + LPD3DXPRTBUFFER pBuffer); + +HRESULT WINAPI + D3DXSavePRTBufferToFileW( + LPCWSTR pFileName, + LPD3DXPRTBUFFER pBuffer); + +#ifdef UNICODE +#define D3DXSavePRTBufferToFile D3DXSavePRTBufferToFileW +#else +#define D3DXSavePRTBufferToFile D3DXSavePRTBufferToFileA +#endif + + +//============================================================================ +// +// D3DXLoadPRTCompBufferFromFile: +// -------------------- +// Loads a PRTComp buffer that has been saved to disk. +// +// Parameters: +// pFilename +// Name of the file to load +// ppBuffer +// Buffer that will be allocated +// +//============================================================================ + +HRESULT WINAPI + D3DXLoadPRTCompBufferFromFileA( + LPCSTR pFilename, + LPD3DXPRTCOMPBUFFER* ppBuffer); + +HRESULT WINAPI + D3DXLoadPRTCompBufferFromFileW( + LPCWSTR pFilename, + LPD3DXPRTCOMPBUFFER* ppBuffer); + +#ifdef UNICODE +#define D3DXLoadPRTCompBufferFromFile D3DXLoadPRTCompBufferFromFileW +#else +#define D3DXLoadPRTCompBufferFromFile D3DXLoadPRTCompBufferFromFileA +#endif + +//============================================================================ +// +// D3DXSavePRTCompBufferToFile: +// -------------------- +// Saves a PRTCompBuffer to disk. +// +// Parameters: +// pFilename +// Name of the file to save +// pBuffer +// Buffer that will be saved +// +//============================================================================ + +HRESULT WINAPI + D3DXSavePRTCompBufferToFileA( + LPCSTR pFileName, + LPD3DXPRTCOMPBUFFER pBuffer); + +HRESULT WINAPI + D3DXSavePRTCompBufferToFileW( + LPCWSTR pFileName, + LPD3DXPRTCOMPBUFFER pBuffer); + +#ifdef UNICODE +#define D3DXSavePRTCompBufferToFile D3DXSavePRTCompBufferToFileW +#else +#define D3DXSavePRTCompBufferToFile D3DXSavePRTCompBufferToFileA +#endif + +//============================================================================ +// +// D3DXCreatePRTCompBuffer: +// -------------------- +// Compresses a PRT buffer (vertex or texel) +// +// Parameters: +// D3DXSHCOMPRESSQUALITYTYPE +// Quality of compression - low is faster (computes PCA per voronoi cluster) +// high is slower but better quality (clusters based on distance to affine subspace) +// NumClusters +// Number of clusters to compute +// NumPCA +// Number of basis vectors to compute +// pCB +// Optional Callback function +// lpUserContext +// Optional user context +// pBufferIn +// Buffer that will be compressed +// ppBufferOut +// Compressed buffer that will be created +// +//============================================================================ + + +HRESULT WINAPI + D3DXCreatePRTCompBuffer( + D3DXSHCOMPRESSQUALITYTYPE Quality, + UINT NumClusters, + UINT NumPCA, + LPD3DXSHPRTSIMCB pCB, + LPVOID lpUserContext, + LPD3DXPRTBUFFER pBufferIn, + LPD3DXPRTCOMPBUFFER *ppBufferOut + ); + +//============================================================================ +// +// D3DXCreateTextureGutterHelper: +// -------------------- +// Generates a "GutterHelper" for a given set of meshes and texture +// resolution +// +// Parameters: +// Width +// Width of texture +// Height +// Height of texture +// pMesh +// Mesh that represents the scene +// GutterSize +// Number of texels to over rasterize in texture space +// this should be at least 1.0 +// ppBuffer +// GutterHelper that will be created +// +//============================================================================ + + +HRESULT WINAPI + D3DXCreateTextureGutterHelper( + UINT Width, + UINT Height, + LPD3DXMESH pMesh, + FLOAT GutterSize, + LPD3DXTEXTUREGUTTERHELPER* ppBuffer); + + +//============================================================================ +// +// D3DXCreatePRTEngine: +// -------------------- +// Computes a PRTEngine which can efficiently generate PRT simulations +// of a scene +// +// Parameters: +// pMesh +// Mesh that represents the scene - must have an AttributeTable +// where vertices are in a unique attribute. +// pAdjacency +// Optional adjacency information +// ExtractUVs +// Set this to true if textures are going to be used for albedos +// or to store PRT vectors +// pBlockerMesh +// Optional mesh that just blocks the scene +// ppEngine +// PRTEngine that will be created +// +//============================================================================ + + +HRESULT WINAPI + D3DXCreatePRTEngine( + LPD3DXMESH pMesh, + DWORD *pAdjacency, + BOOL ExtractUVs, + LPD3DXMESH pBlockerMesh, + LPD3DXPRTENGINE* ppEngine); + +//============================================================================ +// +// D3DXConcatenateMeshes: +// -------------------- +// Concatenates a group of meshes into one common mesh. This can optionaly transform +// each sub mesh or its texture coordinates. If no DECL is given it will +// generate a union of all of the DECL's of the sub meshes, promoting channels +// and types if neccesary. It will create an AttributeTable if possible, one can +// call OptimizeMesh with attribute sort and compacting enabled to ensure this. +// +// Parameters: +// ppMeshes +// Array of pointers to meshes that can store PRT vectors +// NumMeshes +// Number of meshes +// Options +// Passed through to D3DXCreateMesh +// pGeomXForms +// [optional] Each sub mesh is transformed by the corresponding +// matrix if this array is supplied +// pTextureXForms +// [optional] UV coordinates for each sub mesh are transformed +// by corresponding matrix if supplied +// pDecl +// [optional] Only information in this DECL is used when merging +// data +// pD3DDevice +// D3D device that is used to create the new mesh +// ppMeshOut +// Mesh that will be created +// +//============================================================================ + + +HRESULT WINAPI + D3DXConcatenateMeshes( + LPD3DXMESH *ppMeshes, + UINT NumMeshes, + DWORD Options, + CONST D3DXMATRIX *pGeomXForms, + CONST D3DXMATRIX *pTextureXForms, + CONST D3DVERTEXELEMENT9 *pDecl, + LPDIRECT3DDEVICE9 pD3DDevice, + LPD3DXMESH *ppMeshOut); + +//============================================================================ +// +// D3DXSHPRTCompSuperCluster: +// -------------------------- +// Used with compressed results of D3DXSHPRTSimulation. +// Generates "super clusters" - groups of clusters that can be drawn in +// the same draw call. A greedy algorithm that minimizes overdraw is used +// to group the clusters. +// +// Parameters: +// pClusterIDs +// NumVerts cluster ID's (extracted from a compressed buffer) +// pScene +// Mesh that represents composite scene passed to the simulator +// MaxNumClusters +// Maximum number of clusters allocated per super cluster +// NumClusters +// Number of clusters computed in the simulator +// pSuperClusterIDs +// Array of length NumClusters, contains index of super cluster +// that corresponding cluster was assigned to +// pNumSuperClusters +// Returns the number of super clusters allocated +// +//============================================================================ + +HRESULT WINAPI + D3DXSHPRTCompSuperCluster( + UINT *pClusterIDs, + LPD3DXMESH pScene, + UINT MaxNumClusters, + UINT NumClusters, + UINT *pSuperClusterIDs, + UINT *pNumSuperClusters); + +//============================================================================ +// +// D3DXSHPRTCompSplitMeshSC: +// ------------------------- +// Used with compressed results of the vertex version of the PRT simulator. +// After D3DXSHRTCompSuperCluster has been called this function can be used +// to split the mesh into a group of faces/vertices per super cluster. +// Each super cluster contains all of the faces that contain any vertex +// classified in one of its clusters. All of the vertices connected to this +// set of faces are also included with the returned array ppVertStatus +// indicating whether or not the vertex belongs to the supercluster. +// +// Parameters: +// pClusterIDs +// NumVerts cluster ID's (extracted from a compressed buffer) +// NumVertices +// Number of vertices in original mesh +// NumClusters +// Number of clusters (input parameter to compression) +// pSuperClusterIDs +// Array of size NumClusters that will contain super cluster ID's (from +// D3DXSHCompSuerCluster) +// NumSuperClusters +// Number of superclusters allocated in D3DXSHCompSuerCluster +// pInputIB +// Raw index buffer for mesh - format depends on bInputIBIs32Bit +// InputIBIs32Bit +// Indicates whether the input index buffer is 32-bit (otherwise 16-bit +// is assumed) +// NumFaces +// Number of faces in the original mesh (pInputIB is 3 times this length) +// ppIBData +// LPD3DXBUFFER holds raw index buffer that will contain the resulting split faces. +// Format determined by bIBIs32Bit. Allocated by function +// pIBDataLength +// Length of ppIBData, assigned in function +// OutputIBIs32Bit +// Indicates whether the output index buffer is to be 32-bit (otherwise +// 16-bit is assumed) +// ppFaceRemap +// LPD3DXBUFFER mapping of each face in ppIBData to original faces. Length is +// *pIBDataLength/3. Optional paramter, allocated in function +// ppVertData +// LPD3DXBUFFER contains new vertex data structure. Size of pVertDataLength +// pVertDataLength +// Number of new vertices in split mesh. Assigned in function +// pSCClusterList +// Array of length NumClusters which pSCData indexes into (Cluster* fields) +// for each SC, contains clusters sorted by super cluster +// pSCData +// Structure per super cluster - contains indices into ppIBData, +// pSCClusterList and ppVertData +// +//============================================================================ + +HRESULT WINAPI + D3DXSHPRTCompSplitMeshSC( + UINT *pClusterIDs, + UINT NumVertices, + UINT NumClusters, + UINT *pSuperClusterIDs, + UINT NumSuperClusters, + LPVOID pInputIB, + BOOL InputIBIs32Bit, + UINT NumFaces, + LPD3DXBUFFER *ppIBData, + UINT *pIBDataLength, + BOOL OutputIBIs32Bit, + LPD3DXBUFFER *ppFaceRemap, + LPD3DXBUFFER *ppVertData, + UINT *pVertDataLength, + UINT *pSCClusterList, + D3DXSHPRTSPLITMESHCLUSTERDATA *pSCData); + + +#ifdef __cplusplus +} +#endif //__cplusplus + +////////////////////////////////////////////////////////////////////////////// +// +// Definitions of .X file templates used by mesh load/save functions +// that are not RM standard +// +////////////////////////////////////////////////////////////////////////////// + +// {3CF169CE-FF7C-44ab-93C0-F78F62D172E2} +DEFINE_GUID(DXFILEOBJ_XSkinMeshHeader, +0x3cf169ce, 0xff7c, 0x44ab, 0x93, 0xc0, 0xf7, 0x8f, 0x62, 0xd1, 0x72, 0xe2); + +// {B8D65549-D7C9-4995-89CF-53A9A8B031E3} +DEFINE_GUID(DXFILEOBJ_VertexDuplicationIndices, +0xb8d65549, 0xd7c9, 0x4995, 0x89, 0xcf, 0x53, 0xa9, 0xa8, 0xb0, 0x31, 0xe3); + +// {A64C844A-E282-4756-8B80-250CDE04398C} +DEFINE_GUID(DXFILEOBJ_FaceAdjacency, +0xa64c844a, 0xe282, 0x4756, 0x8b, 0x80, 0x25, 0xc, 0xde, 0x4, 0x39, 0x8c); + +// {6F0D123B-BAD2-4167-A0D0-80224F25FABB} +DEFINE_GUID(DXFILEOBJ_SkinWeights, +0x6f0d123b, 0xbad2, 0x4167, 0xa0, 0xd0, 0x80, 0x22, 0x4f, 0x25, 0xfa, 0xbb); + +// {A3EB5D44-FC22-429d-9AFB-3221CB9719A6} +DEFINE_GUID(DXFILEOBJ_Patch, +0xa3eb5d44, 0xfc22, 0x429d, 0x9a, 0xfb, 0x32, 0x21, 0xcb, 0x97, 0x19, 0xa6); + +// {D02C95CC-EDBA-4305-9B5D-1820D7704BBF} +DEFINE_GUID(DXFILEOBJ_PatchMesh, +0xd02c95cc, 0xedba, 0x4305, 0x9b, 0x5d, 0x18, 0x20, 0xd7, 0x70, 0x4b, 0xbf); + +// {B9EC94E1-B9A6-4251-BA18-94893F02C0EA} +DEFINE_GUID(DXFILEOBJ_PatchMesh9, +0xb9ec94e1, 0xb9a6, 0x4251, 0xba, 0x18, 0x94, 0x89, 0x3f, 0x2, 0xc0, 0xea); + +// {B6C3E656-EC8B-4b92-9B62-681659522947} +DEFINE_GUID(DXFILEOBJ_PMInfo, +0xb6c3e656, 0xec8b, 0x4b92, 0x9b, 0x62, 0x68, 0x16, 0x59, 0x52, 0x29, 0x47); + +// {917E0427-C61E-4a14-9C64-AFE65F9E9844} +DEFINE_GUID(DXFILEOBJ_PMAttributeRange, +0x917e0427, 0xc61e, 0x4a14, 0x9c, 0x64, 0xaf, 0xe6, 0x5f, 0x9e, 0x98, 0x44); + +// {574CCC14-F0B3-4333-822D-93E8A8A08E4C} +DEFINE_GUID(DXFILEOBJ_PMVSplitRecord, +0x574ccc14, 0xf0b3, 0x4333, 0x82, 0x2d, 0x93, 0xe8, 0xa8, 0xa0, 0x8e, 0x4c); + +// {B6E70A0E-8EF9-4e83-94AD-ECC8B0C04897} +DEFINE_GUID(DXFILEOBJ_FVFData, +0xb6e70a0e, 0x8ef9, 0x4e83, 0x94, 0xad, 0xec, 0xc8, 0xb0, 0xc0, 0x48, 0x97); + +// {F752461C-1E23-48f6-B9F8-8350850F336F} +DEFINE_GUID(DXFILEOBJ_VertexElement, +0xf752461c, 0x1e23, 0x48f6, 0xb9, 0xf8, 0x83, 0x50, 0x85, 0xf, 0x33, 0x6f); + +// {BF22E553-292C-4781-9FEA-62BD554BDD93} +DEFINE_GUID(DXFILEOBJ_DeclData, +0xbf22e553, 0x292c, 0x4781, 0x9f, 0xea, 0x62, 0xbd, 0x55, 0x4b, 0xdd, 0x93); + +// {F1CFE2B3-0DE3-4e28-AFA1-155A750A282D} +DEFINE_GUID(DXFILEOBJ_EffectFloats, +0xf1cfe2b3, 0xde3, 0x4e28, 0xaf, 0xa1, 0x15, 0x5a, 0x75, 0xa, 0x28, 0x2d); + +// {D55B097E-BDB6-4c52-B03D-6051C89D0E42} +DEFINE_GUID(DXFILEOBJ_EffectString, +0xd55b097e, 0xbdb6, 0x4c52, 0xb0, 0x3d, 0x60, 0x51, 0xc8, 0x9d, 0xe, 0x42); + +// {622C0ED0-956E-4da9-908A-2AF94F3CE716} +DEFINE_GUID(DXFILEOBJ_EffectDWord, +0x622c0ed0, 0x956e, 0x4da9, 0x90, 0x8a, 0x2a, 0xf9, 0x4f, 0x3c, 0xe7, 0x16); + +// {3014B9A0-62F5-478c-9B86-E4AC9F4E418B} +DEFINE_GUID(DXFILEOBJ_EffectParamFloats, +0x3014b9a0, 0x62f5, 0x478c, 0x9b, 0x86, 0xe4, 0xac, 0x9f, 0x4e, 0x41, 0x8b); + +// {1DBC4C88-94C1-46ee-9076-2C28818C9481} +DEFINE_GUID(DXFILEOBJ_EffectParamString, +0x1dbc4c88, 0x94c1, 0x46ee, 0x90, 0x76, 0x2c, 0x28, 0x81, 0x8c, 0x94, 0x81); + +// {E13963BC-AE51-4c5d-B00F-CFA3A9D97CE5} +DEFINE_GUID(DXFILEOBJ_EffectParamDWord, +0xe13963bc, 0xae51, 0x4c5d, 0xb0, 0xf, 0xcf, 0xa3, 0xa9, 0xd9, 0x7c, 0xe5); + +// {E331F7E4-0559-4cc2-8E99-1CEC1657928F} +DEFINE_GUID(DXFILEOBJ_EffectInstance, +0xe331f7e4, 0x559, 0x4cc2, 0x8e, 0x99, 0x1c, 0xec, 0x16, 0x57, 0x92, 0x8f); + +// {9E415A43-7BA6-4a73-8743-B73D47E88476} +DEFINE_GUID(DXFILEOBJ_AnimTicksPerSecond, +0x9e415a43, 0x7ba6, 0x4a73, 0x87, 0x43, 0xb7, 0x3d, 0x47, 0xe8, 0x84, 0x76); + +// {7F9B00B3-F125-4890-876E-1CFFBF697C4D} +DEFINE_GUID(DXFILEOBJ_CompressedAnimationSet, +0x7f9b00b3, 0xf125, 0x4890, 0x87, 0x6e, 0x1c, 0x42, 0xbf, 0x69, 0x7c, 0x4d); + +#pragma pack(push, 1) +typedef struct _XFILECOMPRESSEDANIMATIONSET +{ + DWORD CompressedBlockSize; + FLOAT TicksPerSec; + DWORD PlaybackType; + DWORD BufferLength; +} XFILECOMPRESSEDANIMATIONSET; +#pragma pack(pop) + +#define XSKINEXP_TEMPLATES \ + "xof 0303txt 0032\ + template XSkinMeshHeader \ + { \ + <3CF169CE-FF7C-44ab-93C0-F78F62D172E2> \ + WORD nMaxSkinWeightsPerVertex; \ + WORD nMaxSkinWeightsPerFace; \ + WORD nBones; \ + } \ + template VertexDuplicationIndices \ + { \ + \ + DWORD nIndices; \ + DWORD nOriginalVertices; \ + array DWORD indices[nIndices]; \ + } \ + template FaceAdjacency \ + { \ + \ + DWORD nIndices; \ + array DWORD indices[nIndices]; \ + } \ + template SkinWeights \ + { \ + <6F0D123B-BAD2-4167-A0D0-80224F25FABB> \ + STRING transformNodeName; \ + DWORD nWeights; \ + array DWORD vertexIndices[nWeights]; \ + array float weights[nWeights]; \ + Matrix4x4 matrixOffset; \ + } \ + template Patch \ + { \ + \ + DWORD nControlIndices; \ + array DWORD controlIndices[nControlIndices]; \ + } \ + template PatchMesh \ + { \ + \ + DWORD nVertices; \ + array Vector vertices[nVertices]; \ + DWORD nPatches; \ + array Patch patches[nPatches]; \ + [ ... ] \ + } \ + template PatchMesh9 \ + { \ + \ + DWORD Type; \ + DWORD Degree; \ + DWORD Basis; \ + DWORD nVertices; \ + array Vector vertices[nVertices]; \ + DWORD nPatches; \ + array Patch patches[nPatches]; \ + [ ... ] \ + } " \ + "template EffectFloats \ + { \ + \ + DWORD nFloats; \ + array float Floats[nFloats]; \ + } \ + template EffectString \ + { \ + \ + STRING Value; \ + } \ + template EffectDWord \ + { \ + <622C0ED0-956E-4da9-908A-2AF94F3CE716> \ + DWORD Value; \ + } " \ + "template EffectParamFloats \ + { \ + <3014B9A0-62F5-478c-9B86-E4AC9F4E418B> \ + STRING ParamName; \ + DWORD nFloats; \ + array float Floats[nFloats]; \ + } " \ + "template EffectParamString \ + { \ + <1DBC4C88-94C1-46ee-9076-2C28818C9481> \ + STRING ParamName; \ + STRING Value; \ + } \ + template EffectParamDWord \ + { \ + \ + STRING ParamName; \ + DWORD Value; \ + } \ + template EffectInstance \ + { \ + \ + STRING EffectFilename; \ + [ ... ] \ + } " \ + "template AnimTicksPerSecond \ + { \ + <9E415A43-7BA6-4a73-8743-B73D47E88476> \ + DWORD AnimTicksPerSecond; \ + } \ + template CompressedAnimationSet \ + { \ + <7F9B00B3-F125-4890-876E-1C42BF697C4D> \ + DWORD CompressedBlockSize; \ + FLOAT TicksPerSec; \ + DWORD PlaybackType; \ + DWORD BufferLength; \ + array DWORD CompressedData[BufferLength]; \ + } " + +#define XEXTENSIONS_TEMPLATES \ + "xof 0303txt 0032\ + template FVFData \ + { \ + \ + DWORD dwFVF; \ + DWORD nDWords; \ + array DWORD data[nDWords]; \ + } \ + template VertexElement \ + { \ + \ + DWORD Type; \ + DWORD Method; \ + DWORD Usage; \ + DWORD UsageIndex; \ + } \ + template DeclData \ + { \ + \ + DWORD nElements; \ + array VertexElement Elements[nElements]; \ + DWORD nDWords; \ + array DWORD data[nDWords]; \ + } \ + template PMAttributeRange \ + { \ + <917E0427-C61E-4a14-9C64-AFE65F9E9844> \ + DWORD iFaceOffset; \ + DWORD nFacesMin; \ + DWORD nFacesMax; \ + DWORD iVertexOffset; \ + DWORD nVerticesMin; \ + DWORD nVerticesMax; \ + } \ + template PMVSplitRecord \ + { \ + <574CCC14-F0B3-4333-822D-93E8A8A08E4C> \ + DWORD iFaceCLW; \ + DWORD iVlrOffset; \ + DWORD iCode; \ + } \ + template PMInfo \ + { \ + \ + DWORD nAttributes; \ + array PMAttributeRange attributeRanges[nAttributes]; \ + DWORD nMaxValence; \ + DWORD nMinLogicalVertices; \ + DWORD nMaxLogicalVertices; \ + DWORD nVSplits; \ + array PMVSplitRecord splitRecords[nVSplits]; \ + DWORD nAttributeMispredicts; \ + array DWORD attributeMispredicts[nAttributeMispredicts]; \ + } " + +#endif //__D3DX9MESH_H__ + + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9shader.h b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9shader.h new file mode 100644 index 0000000000..1e2cda2846 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9shader.h @@ -0,0 +1,1177 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// File: d3dx9shader.h +// Content: D3DX Shader APIs +// +////////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9SHADER_H__ +#define __D3DX9SHADER_H__ + + +//--------------------------------------------------------------------------- +// D3DXTX_VERSION: +// -------------- +// Version token used to create a procedural texture filler in effects +// Used by D3DXFill[]TX functions +//--------------------------------------------------------------------------- +#define D3DXTX_VERSION(_Major,_Minor) (('T' << 24) | ('X' << 16) | ((_Major) << 8) | (_Minor)) + + + +//---------------------------------------------------------------------------- +// D3DXSHADER flags: +// ----------------- +// D3DXSHADER_DEBUG +// Insert debug file/line/type/symbol information. +// +// D3DXSHADER_SKIPVALIDATION +// Do not validate the generated code against known capabilities and +// constraints. This option is only recommended when compiling shaders +// you KNOW will work. (ie. have compiled before without this option.) +// Shaders are always validated by D3D before they are set to the device. +// +// D3DXSHADER_SKIPOPTIMIZATION +// Instructs the compiler to skip optimization steps during code generation. +// Unless you are trying to isolate a problem in your code using this option +// is not recommended. +// +// D3DXSHADER_PACKMATRIX_ROWMAJOR +// Unless explicitly specified, matrices will be packed in row-major order +// on input and output from the shader. +// +// D3DXSHADER_PACKMATRIX_COLUMNMAJOR +// Unless explicitly specified, matrices will be packed in column-major +// order on input and output from the shader. This is generally more +// efficient, since it allows vector-matrix multiplication to be performed +// using a series of dot-products. +// +// D3DXSHADER_PARTIALPRECISION +// Force all computations in resulting shader to occur at partial precision. +// This may result in faster evaluation of shaders on some hardware. +// +// D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT +// Force compiler to compile against the next highest available software +// target for vertex shaders. This flag also turns optimizations off, +// and debugging on. +// +// D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT +// Force compiler to compile against the next highest available software +// target for pixel shaders. This flag also turns optimizations off, +// and debugging on. +// +// D3DXSHADER_NO_PRESHADER +// Disables Preshaders. Using this flag will cause the compiler to not +// pull out static expression for evaluation on the host cpu +// +// D3DXSHADER_AVOID_FLOW_CONTROL +// Hint compiler to avoid flow-control constructs where possible. +// +// D3DXSHADER_PREFER_FLOW_CONTROL +// Hint compiler to prefer flow-control constructs where possible. +// +//---------------------------------------------------------------------------- + +#define D3DXSHADER_DEBUG (1 << 0) +#define D3DXSHADER_SKIPVALIDATION (1 << 1) +#define D3DXSHADER_SKIPOPTIMIZATION (1 << 2) +#define D3DXSHADER_PACKMATRIX_ROWMAJOR (1 << 3) +#define D3DXSHADER_PACKMATRIX_COLUMNMAJOR (1 << 4) +#define D3DXSHADER_PARTIALPRECISION (1 << 5) +#define D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT (1 << 6) +#define D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT (1 << 7) +#define D3DXSHADER_NO_PRESHADER (1 << 8) +#define D3DXSHADER_AVOID_FLOW_CONTROL (1 << 9) +#define D3DXSHADER_PREFER_FLOW_CONTROL (1 << 10) +#define D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY (1 << 12) +#define D3DXSHADER_IEEE_STRICTNESS (1 << 13) +#define D3DXSHADER_USE_LEGACY_D3DX9_31_DLL (1 << 16) + + +// optimization level flags +#define D3DXSHADER_OPTIMIZATION_LEVEL0 (1 << 14) +#define D3DXSHADER_OPTIMIZATION_LEVEL1 0 +#define D3DXSHADER_OPTIMIZATION_LEVEL2 ((1 << 14) | (1 << 15)) +#define D3DXSHADER_OPTIMIZATION_LEVEL3 (1 << 15) + + + + +//---------------------------------------------------------------------------- +// D3DXHANDLE: +// ----------- +// Handle values used to efficiently reference shader and effect parameters. +// Strings can be used as handles. However, handles are not always strings. +//---------------------------------------------------------------------------- + +#ifndef D3DXFX_LARGEADDRESS_HANDLE +typedef LPCSTR D3DXHANDLE; +#else +typedef UINT_PTR D3DXHANDLE; +#endif +typedef D3DXHANDLE *LPD3DXHANDLE; + + +//---------------------------------------------------------------------------- +// D3DXMACRO: +// ---------- +// Preprocessor macro definition. The application pass in a NULL-terminated +// array of this structure to various D3DX APIs. This enables the application +// to #define tokens at runtime, before the file is parsed. +//---------------------------------------------------------------------------- + +typedef struct _D3DXMACRO +{ + LPCSTR Name; + LPCSTR Definition; + +} D3DXMACRO, *LPD3DXMACRO; + + +//---------------------------------------------------------------------------- +// D3DXSEMANTIC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXSEMANTIC +{ + UINT Usage; + UINT UsageIndex; + +} D3DXSEMANTIC, *LPD3DXSEMANTIC; + + + +//---------------------------------------------------------------------------- +// D3DXFRAGMENT_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXFRAGMENT_DESC +{ + LPCSTR Name; + DWORD Target; + +} D3DXFRAGMENT_DESC, *LPD3DXFRAGMENT_DESC; + + +//---------------------------------------------------------------------------- +// D3DXREGISTER_SET: +//---------------------------------------------------------------------------- + +typedef enum _D3DXREGISTER_SET +{ + D3DXRS_BOOL, + D3DXRS_INT4, + D3DXRS_FLOAT4, + D3DXRS_SAMPLER, + + // force 32-bit size enum + D3DXRS_FORCE_DWORD = 0x7fffffff + +} D3DXREGISTER_SET, *LPD3DXREGISTER_SET; + + +//---------------------------------------------------------------------------- +// D3DXPARAMETER_CLASS: +//---------------------------------------------------------------------------- + +typedef enum _D3DXPARAMETER_CLASS +{ + D3DXPC_SCALAR, + D3DXPC_VECTOR, + D3DXPC_MATRIX_ROWS, + D3DXPC_MATRIX_COLUMNS, + D3DXPC_OBJECT, + D3DXPC_STRUCT, + + // force 32-bit size enum + D3DXPC_FORCE_DWORD = 0x7fffffff + +} D3DXPARAMETER_CLASS, *LPD3DXPARAMETER_CLASS; + + +//---------------------------------------------------------------------------- +// D3DXPARAMETER_TYPE: +//---------------------------------------------------------------------------- + +typedef enum _D3DXPARAMETER_TYPE +{ + D3DXPT_VOID, + D3DXPT_BOOL, + D3DXPT_INT, + D3DXPT_FLOAT, + D3DXPT_STRING, + D3DXPT_TEXTURE, + D3DXPT_TEXTURE1D, + D3DXPT_TEXTURE2D, + D3DXPT_TEXTURE3D, + D3DXPT_TEXTURECUBE, + D3DXPT_SAMPLER, + D3DXPT_SAMPLER1D, + D3DXPT_SAMPLER2D, + D3DXPT_SAMPLER3D, + D3DXPT_SAMPLERCUBE, + D3DXPT_PIXELSHADER, + D3DXPT_VERTEXSHADER, + D3DXPT_PIXELFRAGMENT, + D3DXPT_VERTEXFRAGMENT, + D3DXPT_UNSUPPORTED, + + // force 32-bit size enum + D3DXPT_FORCE_DWORD = 0x7fffffff + +} D3DXPARAMETER_TYPE, *LPD3DXPARAMETER_TYPE; + + +//---------------------------------------------------------------------------- +// D3DXCONSTANTTABLE_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXCONSTANTTABLE_DESC +{ + LPCSTR Creator; // Creator string + DWORD Version; // Shader version + UINT Constants; // Number of constants + +} D3DXCONSTANTTABLE_DESC, *LPD3DXCONSTANTTABLE_DESC; + + +//---------------------------------------------------------------------------- +// D3DXCONSTANT_DESC: +//---------------------------------------------------------------------------- + +typedef struct _D3DXCONSTANT_DESC +{ + LPCSTR Name; // Constant name + + D3DXREGISTER_SET RegisterSet; // Register set + UINT RegisterIndex; // Register index + UINT RegisterCount; // Number of registers occupied + + D3DXPARAMETER_CLASS Class; // Class + D3DXPARAMETER_TYPE Type; // Component type + + UINT Rows; // Number of rows + UINT Columns; // Number of columns + UINT Elements; // Number of array elements + UINT StructMembers; // Number of structure member sub-parameters + + UINT Bytes; // Data size, in bytes + LPCVOID DefaultValue; // Pointer to default value + +} D3DXCONSTANT_DESC, *LPD3DXCONSTANT_DESC; + + + +//---------------------------------------------------------------------------- +// ID3DXConstantTable: +//---------------------------------------------------------------------------- + +typedef interface ID3DXConstantTable ID3DXConstantTable; +typedef interface ID3DXConstantTable *LPD3DXCONSTANTTABLE; + +// {AB3C758F-093E-4356-B762-4DB18F1B3A01} +DEFINE_GUID(IID_ID3DXConstantTable, +0xab3c758f, 0x93e, 0x4356, 0xb7, 0x62, 0x4d, 0xb1, 0x8f, 0x1b, 0x3a, 0x1); + + +#undef INTERFACE +#define INTERFACE ID3DXConstantTable + +DECLARE_INTERFACE_(ID3DXConstantTable, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Buffer + STDMETHOD_(LPVOID, GetBufferPointer)(THIS) PURE; + STDMETHOD_(DWORD, GetBufferSize)(THIS) PURE; + + // Descs + STDMETHOD(GetDesc)(THIS_ D3DXCONSTANTTABLE_DESC *pDesc) PURE; + STDMETHOD(GetConstantDesc)(THIS_ D3DXHANDLE hConstant, D3DXCONSTANT_DESC *pConstantDesc, UINT *pCount) PURE; + STDMETHOD_(UINT, GetSamplerIndex)(THIS_ D3DXHANDLE hConstant) PURE; + + // Handle operations + STDMETHOD_(D3DXHANDLE, GetConstant)(THIS_ D3DXHANDLE hConstant, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetConstantByName)(THIS_ D3DXHANDLE hConstant, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetConstantElement)(THIS_ D3DXHANDLE hConstant, UINT Index) PURE; + + // Set Constants + STDMETHOD(SetDefaults)(THIS_ LPDIRECT3DDEVICE9 pDevice) PURE; + STDMETHOD(SetValue)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, LPCVOID pData, UINT Bytes) PURE; + STDMETHOD(SetBool)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, BOOL b) PURE; + STDMETHOD(SetBoolArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST BOOL* pb, UINT Count) PURE; + STDMETHOD(SetInt)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, INT n) PURE; + STDMETHOD(SetIntArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST INT* pn, UINT Count) PURE; + STDMETHOD(SetFloat)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, FLOAT f) PURE; + STDMETHOD(SetFloatArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST FLOAT* pf, UINT Count) PURE; + STDMETHOD(SetVector)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXVECTOR4* pVector) PURE; + STDMETHOD(SetVectorArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(SetMatrix)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixPointerArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTranspose)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixTransposeArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTransposePointerArray)(THIS_ LPDIRECT3DDEVICE9 pDevice, D3DXHANDLE hConstant, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; +}; + + +//---------------------------------------------------------------------------- +// ID3DXTextureShader: +//---------------------------------------------------------------------------- + +typedef interface ID3DXTextureShader ID3DXTextureShader; +typedef interface ID3DXTextureShader *LPD3DXTEXTURESHADER; + +// {3E3D67F8-AA7A-405d-A857-BA01D4758426} +DEFINE_GUID(IID_ID3DXTextureShader, +0x3e3d67f8, 0xaa7a, 0x405d, 0xa8, 0x57, 0xba, 0x1, 0xd4, 0x75, 0x84, 0x26); + +#undef INTERFACE +#define INTERFACE ID3DXTextureShader + +DECLARE_INTERFACE_(ID3DXTextureShader, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // Gets + STDMETHOD(GetFunction)(THIS_ LPD3DXBUFFER *ppFunction) PURE; + STDMETHOD(GetConstantBuffer)(THIS_ LPD3DXBUFFER *ppConstantBuffer) PURE; + + // Descs + STDMETHOD(GetDesc)(THIS_ D3DXCONSTANTTABLE_DESC *pDesc) PURE; + STDMETHOD(GetConstantDesc)(THIS_ D3DXHANDLE hConstant, D3DXCONSTANT_DESC *pConstantDesc, UINT *pCount) PURE; + + // Handle operations + STDMETHOD_(D3DXHANDLE, GetConstant)(THIS_ D3DXHANDLE hConstant, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetConstantByName)(THIS_ D3DXHANDLE hConstant, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetConstantElement)(THIS_ D3DXHANDLE hConstant, UINT Index) PURE; + + // Set Constants + STDMETHOD(SetDefaults)(THIS) PURE; + STDMETHOD(SetValue)(THIS_ D3DXHANDLE hConstant, LPCVOID pData, UINT Bytes) PURE; + STDMETHOD(SetBool)(THIS_ D3DXHANDLE hConstant, BOOL b) PURE; + STDMETHOD(SetBoolArray)(THIS_ D3DXHANDLE hConstant, CONST BOOL* pb, UINT Count) PURE; + STDMETHOD(SetInt)(THIS_ D3DXHANDLE hConstant, INT n) PURE; + STDMETHOD(SetIntArray)(THIS_ D3DXHANDLE hConstant, CONST INT* pn, UINT Count) PURE; + STDMETHOD(SetFloat)(THIS_ D3DXHANDLE hConstant, FLOAT f) PURE; + STDMETHOD(SetFloatArray)(THIS_ D3DXHANDLE hConstant, CONST FLOAT* pf, UINT Count) PURE; + STDMETHOD(SetVector)(THIS_ D3DXHANDLE hConstant, CONST D3DXVECTOR4* pVector) PURE; + STDMETHOD(SetVectorArray)(THIS_ D3DXHANDLE hConstant, CONST D3DXVECTOR4* pVector, UINT Count) PURE; + STDMETHOD(SetMatrix)(THIS_ D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixArray)(THIS_ D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixPointerArray)(THIS_ D3DXHANDLE hConstant, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTranspose)(THIS_ D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix) PURE; + STDMETHOD(SetMatrixTransposeArray)(THIS_ D3DXHANDLE hConstant, CONST D3DXMATRIX* pMatrix, UINT Count) PURE; + STDMETHOD(SetMatrixTransposePointerArray)(THIS_ D3DXHANDLE hConstant, CONST D3DXMATRIX** ppMatrix, UINT Count) PURE; +}; + + + +//---------------------------------------------------------------------------- +// ID3DXFragmentLinker +//---------------------------------------------------------------------------- + +typedef interface ID3DXFragmentLinker ID3DXFragmentLinker; +typedef interface ID3DXFragmentLinker *LPD3DXFRAGMENTLINKER; + +// {1A2C0CC2-E5B6-4ebc-9E8D-390E057811B6} +DEFINE_GUID(IID_ID3DXFragmentLinker, +0x1a2c0cc2, 0xe5b6, 0x4ebc, 0x9e, 0x8d, 0x39, 0xe, 0x5, 0x78, 0x11, 0xb6); + +#undef INTERFACE +#define INTERFACE ID3DXFragmentLinker + +DECLARE_INTERFACE_(ID3DXFragmentLinker, IUnknown) +{ + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + + // ID3DXFragmentLinker + + // fragment access and information retrieval functions + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice) PURE; + STDMETHOD_(UINT, GetNumberOfFragments)(THIS) PURE; + + STDMETHOD_(D3DXHANDLE, GetFragmentHandleByIndex)(THIS_ UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetFragmentHandleByName)(THIS_ LPCSTR Name) PURE; + STDMETHOD(GetFragmentDesc)(THIS_ D3DXHANDLE Name, LPD3DXFRAGMENT_DESC FragDesc) PURE; + + // add the fragments in the buffer to the linker + STDMETHOD(AddFragments)(THIS_ CONST DWORD *Fragments) PURE; + + // Create a buffer containing the fragments. Suitable for saving to disk + STDMETHOD(GetAllFragments)(THIS_ LPD3DXBUFFER *ppBuffer) PURE; + STDMETHOD(GetFragment)(THIS_ D3DXHANDLE Name, LPD3DXBUFFER *ppBuffer) PURE; + + STDMETHOD(LinkShader)(THIS_ LPCSTR pProfile, DWORD Flags, CONST D3DXHANDLE *rgFragmentHandles, UINT cFragments, LPD3DXBUFFER *ppBuffer, LPD3DXBUFFER *ppErrorMsgs) PURE; + STDMETHOD(LinkVertexShader)(THIS_ LPCSTR pProfile, DWORD Flags, CONST D3DXHANDLE *rgFragmentHandles, UINT cFragments, LPDIRECT3DVERTEXSHADER9 *pVShader, LPD3DXBUFFER *ppErrorMsgs) PURE; + STDMETHOD(LinkPixelShader)(THIS_ LPCSTR pProfile, DWORD Flags, CONST D3DXHANDLE *rgFragmentHandles, UINT cFragments, LPDIRECT3DPIXELSHADER9 *pPShader, LPD3DXBUFFER *ppErrorMsgs) PURE; + + STDMETHOD(ClearCache)(THIS) PURE; +}; + + +//---------------------------------------------------------------------------- +// D3DXINCLUDE_TYPE: +//---------------------------------------------------------------------------- + +typedef enum _D3DXINCLUDE_TYPE +{ + D3DXINC_LOCAL, + D3DXINC_SYSTEM, + + // force 32-bit size enum + D3DXINC_FORCE_DWORD = 0x7fffffff + +} D3DXINCLUDE_TYPE, *LPD3DXINCLUDE_TYPE; + + +//---------------------------------------------------------------------------- +// ID3DXInclude: +// ------------- +// This interface is intended to be implemented by the application, and can +// be used by various D3DX APIs. This enables application-specific handling +// of #include directives in source files. +// +// Open() +// Opens an include file. If successful, it should fill in ppData and +// pBytes. The data pointer returned must remain valid until Close is +// subsequently called. +// Close() +// Closes an include file. If Open was successful, Close is guaranteed +// to be called before the API using this interface returns. +//---------------------------------------------------------------------------- + +typedef interface ID3DXInclude ID3DXInclude; +typedef interface ID3DXInclude *LPD3DXINCLUDE; + +#undef INTERFACE +#define INTERFACE ID3DXInclude + +DECLARE_INTERFACE(ID3DXInclude) +{ + STDMETHOD(Open)(THIS_ D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes) PURE; + STDMETHOD(Close)(THIS_ LPCVOID pData) PURE; +}; + + +////////////////////////////////////////////////////////////////////////////// +// APIs ////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + +//---------------------------------------------------------------------------- +// D3DXAssembleShader: +// ------------------- +// Assembles a shader. +// +// Parameters: +// pSrcFile +// Source file name +// hSrcModule +// Module handle. if NULL, current module will be used +// pSrcResource +// Resource name in module +// pSrcData +// Pointer to source code +// SrcDataLen +// Size of source code, in bytes +// pDefines +// Optional NULL-terminated array of preprocessor macro definitions. +// pInclude +// Optional interface pointer to use for handling #include directives. +// If this parameter is NULL, #includes will be honored when assembling +// from file, and will error when assembling from resource or memory. +// Flags +// See D3DXSHADER_xxx flags +// ppShader +// Returns a buffer containing the created shader. This buffer contains +// the assembled shader code, as well as any embedded debug info. +// ppErrorMsgs +// Returns a buffer containing a listing of errors and warnings that were +// encountered during assembly. If you are running in a debugger, +// these are the same messages you will see in your debug output. +//---------------------------------------------------------------------------- + + +HRESULT WINAPI + D3DXAssembleShaderFromFileA( + LPCSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + +HRESULT WINAPI + D3DXAssembleShaderFromFileW( + LPCWSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + +#ifdef UNICODE +#define D3DXAssembleShaderFromFile D3DXAssembleShaderFromFileW +#else +#define D3DXAssembleShaderFromFile D3DXAssembleShaderFromFileA +#endif + + +HRESULT WINAPI + D3DXAssembleShaderFromResourceA( + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + +HRESULT WINAPI + D3DXAssembleShaderFromResourceW( + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + +#ifdef UNICODE +#define D3DXAssembleShaderFromResource D3DXAssembleShaderFromResourceW +#else +#define D3DXAssembleShaderFromResource D3DXAssembleShaderFromResourceA +#endif + + +HRESULT WINAPI + D3DXAssembleShader( + LPCSTR pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + + + +//---------------------------------------------------------------------------- +// D3DXCompileShader: +// ------------------ +// Compiles a shader. +// +// Parameters: +// pSrcFile +// Source file name. +// hSrcModule +// Module handle. if NULL, current module will be used. +// pSrcResource +// Resource name in module. +// pSrcData +// Pointer to source code. +// SrcDataLen +// Size of source code, in bytes. +// pDefines +// Optional NULL-terminated array of preprocessor macro definitions. +// pInclude +// Optional interface pointer to use for handling #include directives. +// If this parameter is NULL, #includes will be honored when compiling +// from file, and will error when compiling from resource or memory. +// pFunctionName +// Name of the entrypoint function where execution should begin. +// pProfile +// Instruction set to be used when generating code. Currently supported +// profiles are "vs_1_1", "vs_2_0", "vs_2_a", "vs_2_sw", "ps_1_1", +// "ps_1_2", "ps_1_3", "ps_1_4", "ps_2_0", "ps_2_a", "ps_2_sw", "tx_1_0" +// Flags +// See D3DXSHADER_xxx flags. +// ppShader +// Returns a buffer containing the created shader. This buffer contains +// the compiled shader code, as well as any embedded debug and symbol +// table info. (See D3DXGetShaderConstantTable) +// ppErrorMsgs +// Returns a buffer containing a listing of errors and warnings that were +// encountered during the compile. If you are running in a debugger, +// these are the same messages you will see in your debug output. +// ppConstantTable +// Returns a ID3DXConstantTable object which can be used to set +// shader constants to the device. Alternatively, an application can +// parse the D3DXSHADER_CONSTANTTABLE block embedded as a comment within +// the shader. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCompileShaderFromFileA( + LPCSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + +HRESULT WINAPI + D3DXCompileShaderFromFileW( + LPCWSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + +#ifdef UNICODE +#define D3DXCompileShaderFromFile D3DXCompileShaderFromFileW +#else +#define D3DXCompileShaderFromFile D3DXCompileShaderFromFileA +#endif + + +HRESULT WINAPI + D3DXCompileShaderFromResourceA( + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + +HRESULT WINAPI + D3DXCompileShaderFromResourceW( + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + +#ifdef UNICODE +#define D3DXCompileShaderFromResource D3DXCompileShaderFromResourceW +#else +#define D3DXCompileShaderFromResource D3DXCompileShaderFromResourceA +#endif + + +HRESULT WINAPI + D3DXCompileShader( + LPCSTR pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE* ppConstantTable); + + +//---------------------------------------------------------------------------- +// D3DXDisassembleShader: +// ---------------------- +// Takes a binary shader, and returns a buffer containing text assembly. +// +// Parameters: +// pShader +// Pointer to the shader byte code. +// ShaderSizeInBytes +// Size of the shader byte code in bytes. +// EnableColorCode +// Emit HTML tags for color coding the output? +// pComments +// Pointer to a comment string to include at the top of the shader. +// ppDisassembly +// Returns a buffer containing the disassembled shader. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXDisassembleShader( + CONST DWORD* pShader, + BOOL EnableColorCode, + LPCSTR pComments, + LPD3DXBUFFER* ppDisassembly); + + +//---------------------------------------------------------------------------- +// D3DXGetPixelShaderProfile/D3DXGetVertexShaderProfile: +// ----------------------------------------------------- +// Returns the name of the HLSL profile best suited to a given device. +// +// Parameters: +// pDevice +// Pointer to the device in question +//---------------------------------------------------------------------------- + +LPCSTR WINAPI + D3DXGetPixelShaderProfile( + LPDIRECT3DDEVICE9 pDevice); + +LPCSTR WINAPI + D3DXGetVertexShaderProfile( + LPDIRECT3DDEVICE9 pDevice); + + +//---------------------------------------------------------------------------- +// D3DXFindShaderComment: +// ---------------------- +// Searches through a shader for a particular comment, denoted by a FourCC in +// the first DWORD of the comment. If the comment is not found, and no other +// error has occurred, S_FALSE is returned. +// +// Parameters: +// pFunction +// Pointer to the function DWORD stream +// FourCC +// FourCC used to identify the desired comment block. +// ppData +// Returns a pointer to the comment data (not including comment token +// and FourCC). Can be NULL. +// pSizeInBytes +// Returns the size of the comment data in bytes. Can be NULL. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXFindShaderComment( + CONST DWORD* pFunction, + DWORD FourCC, + LPCVOID* ppData, + UINT* pSizeInBytes); + + +//---------------------------------------------------------------------------- +// D3DXGetShaderSize: +// ------------------ +// Returns the size of the shader byte-code, in bytes. +// +// Parameters: +// pFunction +// Pointer to the function DWORD stream +//---------------------------------------------------------------------------- + +UINT WINAPI + D3DXGetShaderSize( + CONST DWORD* pFunction); + + +//---------------------------------------------------------------------------- +// D3DXGetShaderVersion: +// ----------------------- +// Returns the shader version of a given shader. Returns zero if the shader +// function is NULL. +// +// Parameters: +// pFunction +// Pointer to the function DWORD stream +//---------------------------------------------------------------------------- + +DWORD WINAPI + D3DXGetShaderVersion( + CONST DWORD* pFunction); + +//---------------------------------------------------------------------------- +// D3DXGetShaderSemantics: +// ----------------------- +// Gets semantics for all input elements referenced inside a given shader. +// +// Parameters: +// pFunction +// Pointer to the function DWORD stream +// pSemantics +// Pointer to an array of D3DXSEMANTIC structures. The function will +// fill this array with the semantics for each input element referenced +// inside the shader. This array is assumed to contain at least +// MAXD3DDECLLENGTH elements. +// pCount +// Returns the number of elements referenced by the shader +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXGetShaderInputSemantics( + CONST DWORD* pFunction, + D3DXSEMANTIC* pSemantics, + UINT* pCount); + +HRESULT WINAPI + D3DXGetShaderOutputSemantics( + CONST DWORD* pFunction, + D3DXSEMANTIC* pSemantics, + UINT* pCount); + + +//---------------------------------------------------------------------------- +// D3DXGetShaderSamplers: +// ---------------------- +// Gets semantics for all input elements referenced inside a given shader. +// +// pFunction +// Pointer to the function DWORD stream +// pSamplers +// Pointer to an array of LPCSTRs. The function will fill this array +// with pointers to the sampler names contained within pFunction, for +// each sampler referenced inside the shader. This array is assumed to +// contain at least 16 elements. +// pCount +// Returns the number of samplers referenced by the shader +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXGetShaderSamplers( + CONST DWORD* pFunction, + LPCSTR* pSamplers, + UINT* pCount); + + +//---------------------------------------------------------------------------- +// D3DXGetShaderConstantTable: +// --------------------------- +// Gets shader constant table embedded inside shader. A constant table is +// generated by D3DXAssembleShader and D3DXCompileShader, and is embedded in +// the body of the shader. +// +// Parameters: +// pFunction +// Pointer to the function DWORD stream +// ppConstantTable +// Returns a ID3DXConstantTable object which can be used to set +// shader constants to the device. Alternatively, an application can +// parse the D3DXSHADER_CONSTANTTABLE block embedded as a comment within +// the shader. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXGetShaderConstantTable( + CONST DWORD* pFunction, + LPD3DXCONSTANTTABLE* ppConstantTable); + + + +//---------------------------------------------------------------------------- +// D3DXCreateTextureShader: +// ------------------------ +// Creates a texture shader object, given the compiled shader. +// +// Parameters +// pFunction +// Pointer to the function DWORD stream +// ppTextureShader +// Returns a ID3DXTextureShader object which can be used to procedurally +// fill the contents of a texture using the D3DXFillTextureTX functions. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCreateTextureShader( + CONST DWORD* pFunction, + LPD3DXTEXTURESHADER* ppTextureShader); + + + +//---------------------------------------------------------------------------- +// D3DXGatherFragments: +// ------------------- +// Assembles shader fragments into a buffer to be passed to a fragment linker. +// will generate shader fragments for all fragments in the file +// +// Parameters: +// pSrcFile +// Source file name +// hSrcModule +// Module handle. if NULL, current module will be used +// pSrcResource +// Resource name in module +// pSrcData +// Pointer to source code +// SrcDataLen +// Size of source code, in bytes +// pDefines +// Optional NULL-terminated array of preprocessor macro definitions. +// pInclude +// Optional interface pointer to use for handling #include directives. +// If this parameter is NULL, #includes will be honored when assembling +// from file, and will error when assembling from resource or memory. +// Flags +// See D3DXSHADER_xxx flags +// ppShader +// Returns a buffer containing the created shader fragments. This buffer contains +// the assembled shader code, as well as any embedded debug info. +// ppErrorMsgs +// Returns a buffer containing a listing of errors and warnings that were +// encountered during assembly. If you are running in a debugger, +// these are the same messages you will see in your debug output. +//---------------------------------------------------------------------------- + + +HRESULT WINAPI +D3DXGatherFragmentsFromFileA( + LPCSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + +HRESULT WINAPI +D3DXGatherFragmentsFromFileW( + LPCWSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + +#ifdef UNICODE +#define D3DXGatherFragmentsFromFile D3DXGatherFragmentsFromFileW +#else +#define D3DXGatherFragmentsFromFile D3DXGatherFragmentsFromFileA +#endif + + +HRESULT WINAPI + D3DXGatherFragmentsFromResourceA( + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + +HRESULT WINAPI + D3DXGatherFragmentsFromResourceW( + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + +#ifdef UNICODE +#define D3DXGatherFragmentsFromResource D3DXGatherFragmentsFromResourceW +#else +#define D3DXGatherFragmentsFromResource D3DXGatherFragmentsFromResourceA +#endif + + +HRESULT WINAPI + D3DXGatherFragments( + LPCSTR pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs); + + + +//---------------------------------------------------------------------------- +// D3DXCreateFragmentLinker: +// ------------------------- +// Creates a fragment linker with a given cache size. The interface returned +// can be used to link together shader fragments. (both HLSL & ASM fragements) +// +// Parameters: +// pDevice +// Pointer to the device on which to create the shaders +// ShaderCacheSize +// Size of the shader cache +// ppFragmentLinker +// pointer to a memory location to put the created interface pointer +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCreateFragmentLinker( + LPDIRECT3DDEVICE9 pDevice, + UINT ShaderCacheSize, + LPD3DXFRAGMENTLINKER* ppFragmentLinker); + + +//---------------------------------------------------------------------------- +// D3DXPreprocessShader: +// --------------------- +// Runs the preprocessor on the specified shader or effect, but does +// not actually compile it. This is useful for evaluating the #includes +// and #defines in a shader and then emitting a reformatted token stream +// for debugging purposes or for generating a self-contained shader. +// +// Parameters: +// pSrcFile +// Source file name +// hSrcModule +// Module handle. if NULL, current module will be used +// pSrcResource +// Resource name in module +// pSrcData +// Pointer to source code +// SrcDataLen +// Size of source code, in bytes +// pDefines +// Optional NULL-terminated array of preprocessor macro definitions. +// pInclude +// Optional interface pointer to use for handling #include directives. +// If this parameter is NULL, #includes will be honored when assembling +// from file, and will error when assembling from resource or memory. +// ppShaderText +// Returns a buffer containing a single large string that represents +// the resulting formatted token stream +// ppErrorMsgs +// Returns a buffer containing a listing of errors and warnings that were +// encountered during assembly. If you are running in a debugger, +// these are the same messages you will see in your debug output. +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXPreprocessShaderFromFileA( + LPCSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPD3DXBUFFER* ppShaderText, + LPD3DXBUFFER* ppErrorMsgs); + +HRESULT WINAPI + D3DXPreprocessShaderFromFileW( + LPCWSTR pSrcFile, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPD3DXBUFFER* ppShaderText, + LPD3DXBUFFER* ppErrorMsgs); + +#ifdef UNICODE +#define D3DXPreprocessShaderFromFile D3DXPreprocessShaderFromFileW +#else +#define D3DXPreprocessShaderFromFile D3DXPreprocessShaderFromFileA +#endif + +HRESULT WINAPI + D3DXPreprocessShaderFromResourceA( + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPD3DXBUFFER* ppShaderText, + LPD3DXBUFFER* ppErrorMsgs); + +HRESULT WINAPI + D3DXPreprocessShaderFromResourceW( + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPD3DXBUFFER* ppShaderText, + LPD3DXBUFFER* ppErrorMsgs); + +#ifdef UNICODE +#define D3DXPreprocessShaderFromResource D3DXPreprocessShaderFromResourceW +#else +#define D3DXPreprocessShaderFromResource D3DXPreprocessShaderFromResourceA +#endif + +HRESULT WINAPI + D3DXPreprocessShader( + LPCSTR pSrcData, + UINT SrcDataSize, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPD3DXBUFFER* ppShaderText, + LPD3DXBUFFER* ppErrorMsgs); + + +#ifdef __cplusplus +} +#endif //__cplusplus + + +////////////////////////////////////////////////////////////////////////////// +// Shader comment block layouts ////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------------- +// D3DXSHADER_CONSTANTTABLE: +// ------------------------- +// Shader constant information; included as an CTAB comment block inside +// shaders. All offsets are BYTE offsets from start of CONSTANTTABLE struct. +// Entries in the table are sorted by Name in ascending order. +//---------------------------------------------------------------------------- + +typedef struct _D3DXSHADER_CONSTANTTABLE +{ + DWORD Size; // sizeof(D3DXSHADER_CONSTANTTABLE) + DWORD Creator; // LPCSTR offset + DWORD Version; // shader version + DWORD Constants; // number of constants + DWORD ConstantInfo; // D3DXSHADER_CONSTANTINFO[Constants] offset + DWORD Flags; // flags shader was compiled with + DWORD Target; // LPCSTR offset + +} D3DXSHADER_CONSTANTTABLE, *LPD3DXSHADER_CONSTANTTABLE; + + +typedef struct _D3DXSHADER_CONSTANTINFO +{ + DWORD Name; // LPCSTR offset + WORD RegisterSet; // D3DXREGISTER_SET + WORD RegisterIndex; // register number + WORD RegisterCount; // number of registers + WORD Reserved; // reserved + DWORD TypeInfo; // D3DXSHADER_TYPEINFO offset + DWORD DefaultValue; // offset of default value + +} D3DXSHADER_CONSTANTINFO, *LPD3DXSHADER_CONSTANTINFO; + + +typedef struct _D3DXSHADER_TYPEINFO +{ + WORD Class; // D3DXPARAMETER_CLASS + WORD Type; // D3DXPARAMETER_TYPE + WORD Rows; // number of rows (matrices) + WORD Columns; // number of columns (vectors and matrices) + WORD Elements; // array dimension + WORD StructMembers; // number of struct members + DWORD StructMemberInfo; // D3DXSHADER_STRUCTMEMBERINFO[Members] offset + +} D3DXSHADER_TYPEINFO, *LPD3DXSHADER_TYPEINFO; + + +typedef struct _D3DXSHADER_STRUCTMEMBERINFO +{ + DWORD Name; // LPCSTR offset + DWORD TypeInfo; // D3DXSHADER_TYPEINFO offset + +} D3DXSHADER_STRUCTMEMBERINFO, *LPD3DXSHADER_STRUCTMEMBERINFO; + + + +#endif //__D3DX9SHADER_H__ + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9shape.h b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9shape.h new file mode 100644 index 0000000000..4c23091560 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9shape.h @@ -0,0 +1,221 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9shapes.h +// Content: D3DX simple shapes +// +/////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9SHAPES_H__ +#define __D3DX9SHAPES_H__ + +/////////////////////////////////////////////////////////////////////////// +// Functions: +/////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + +//------------------------------------------------------------------------- +// D3DXCreatePolygon: +// ------------------ +// Creates a mesh containing an n-sided polygon. The polygon is centered +// at the origin. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// Length Length of each side. +// Sides Number of sides the polygon has. (Must be >= 3) +// ppMesh The mesh object which will be created +// ppAdjacency Returns a buffer containing adjacency info. Can be NULL. +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreatePolygon( + LPDIRECT3DDEVICE9 pDevice, + FLOAT Length, + UINT Sides, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency); + + +//------------------------------------------------------------------------- +// D3DXCreateBox: +// -------------- +// Creates a mesh containing an axis-aligned box. The box is centered at +// the origin. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// Width Width of box (along X-axis) +// Height Height of box (along Y-axis) +// Depth Depth of box (along Z-axis) +// ppMesh The mesh object which will be created +// ppAdjacency Returns a buffer containing adjacency info. Can be NULL. +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreateBox( + LPDIRECT3DDEVICE9 pDevice, + FLOAT Width, + FLOAT Height, + FLOAT Depth, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency); + + +//------------------------------------------------------------------------- +// D3DXCreateCylinder: +// ------------------- +// Creates a mesh containing a cylinder. The generated cylinder is +// centered at the origin, and its axis is aligned with the Z-axis. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// Radius1 Radius at -Z end (should be >= 0.0f) +// Radius2 Radius at +Z end (should be >= 0.0f) +// Length Length of cylinder (along Z-axis) +// Slices Number of slices about the main axis +// Stacks Number of stacks along the main axis +// ppMesh The mesh object which will be created +// ppAdjacency Returns a buffer containing adjacency info. Can be NULL. +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreateCylinder( + LPDIRECT3DDEVICE9 pDevice, + FLOAT Radius1, + FLOAT Radius2, + FLOAT Length, + UINT Slices, + UINT Stacks, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency); + + +//------------------------------------------------------------------------- +// D3DXCreateSphere: +// ----------------- +// Creates a mesh containing a sphere. The sphere is centered at the +// origin. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// Radius Radius of the sphere (should be >= 0.0f) +// Slices Number of slices about the main axis +// Stacks Number of stacks along the main axis +// ppMesh The mesh object which will be created +// ppAdjacency Returns a buffer containing adjacency info. Can be NULL. +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreateSphere( + LPDIRECT3DDEVICE9 pDevice, + FLOAT Radius, + UINT Slices, + UINT Stacks, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency); + + +//------------------------------------------------------------------------- +// D3DXCreateTorus: +// ---------------- +// Creates a mesh containing a torus. The generated torus is centered at +// the origin, and its axis is aligned with the Z-axis. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// InnerRadius Inner radius of the torus (should be >= 0.0f) +// OuterRadius Outer radius of the torue (should be >= 0.0f) +// Sides Number of sides in a cross-section (must be >= 3) +// Rings Number of rings making up the torus (must be >= 3) +// ppMesh The mesh object which will be created +// ppAdjacency Returns a buffer containing adjacency info. Can be NULL. +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreateTorus( + LPDIRECT3DDEVICE9 pDevice, + FLOAT InnerRadius, + FLOAT OuterRadius, + UINT Sides, + UINT Rings, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency); + + +//------------------------------------------------------------------------- +// D3DXCreateTeapot: +// ----------------- +// Creates a mesh containing a teapot. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// ppMesh The mesh object which will be created +// ppAdjacency Returns a buffer containing adjacency info. Can be NULL. +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreateTeapot( + LPDIRECT3DDEVICE9 pDevice, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency); + + +//------------------------------------------------------------------------- +// D3DXCreateText: +// --------------- +// Creates a mesh containing the specified text using the font associated +// with the device context. +// +// Parameters: +// +// pDevice The D3D device with which the mesh is going to be used. +// hDC Device context, with desired font selected +// pText Text to generate +// Deviation Maximum chordal deviation from true font outlines +// Extrusion Amount to extrude text in -Z direction +// ppMesh The mesh object which will be created +// pGlyphMetrics Address of buffer to receive glyph metric data (or NULL) +//------------------------------------------------------------------------- +HRESULT WINAPI + D3DXCreateTextA( + LPDIRECT3DDEVICE9 pDevice, + HDC hDC, + LPCSTR pText, + FLOAT Deviation, + FLOAT Extrusion, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency, + LPGLYPHMETRICSFLOAT pGlyphMetrics); + +HRESULT WINAPI + D3DXCreateTextW( + LPDIRECT3DDEVICE9 pDevice, + HDC hDC, + LPCWSTR pText, + FLOAT Deviation, + FLOAT Extrusion, + LPD3DXMESH* ppMesh, + LPD3DXBUFFER* ppAdjacency, + LPGLYPHMETRICSFLOAT pGlyphMetrics); + +#ifdef UNICODE +#define D3DXCreateText D3DXCreateTextW +#else +#define D3DXCreateText D3DXCreateTextA +#endif + + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__D3DX9SHAPES_H__ + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9tex.h b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9tex.h new file mode 100644 index 0000000000..c4b65103f6 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9tex.h @@ -0,0 +1,1735 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9tex.h +// Content: D3DX texturing APIs +// +////////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#ifndef __D3DX9TEX_H__ +#define __D3DX9TEX_H__ + + +//---------------------------------------------------------------------------- +// D3DX_FILTER flags: +// ------------------ +// +// A valid filter must contain one of these values: +// +// D3DX_FILTER_NONE +// No scaling or filtering will take place. Pixels outside the bounds +// of the source image are assumed to be transparent black. +// D3DX_FILTER_POINT +// Each destination pixel is computed by sampling the nearest pixel +// from the source image. +// D3DX_FILTER_LINEAR +// Each destination pixel is computed by linearly interpolating between +// the nearest pixels in the source image. This filter works best +// when the scale on each axis is less than 2. +// D3DX_FILTER_TRIANGLE +// Every pixel in the source image contributes equally to the +// destination image. This is the slowest of all the filters. +// D3DX_FILTER_BOX +// Each pixel is computed by averaging a 2x2(x2) box pixels from +// the source image. Only works when the dimensions of the +// destination are half those of the source. (as with mip maps) +// +// And can be OR'd with any of these optional flags: +// +// D3DX_FILTER_MIRROR_U +// Indicates that pixels off the edge of the texture on the U-axis +// should be mirrored, not wraped. +// D3DX_FILTER_MIRROR_V +// Indicates that pixels off the edge of the texture on the V-axis +// should be mirrored, not wraped. +// D3DX_FILTER_MIRROR_W +// Indicates that pixels off the edge of the texture on the W-axis +// should be mirrored, not wraped. +// D3DX_FILTER_MIRROR +// Same as specifying D3DX_FILTER_MIRROR_U | D3DX_FILTER_MIRROR_V | +// D3DX_FILTER_MIRROR_V +// D3DX_FILTER_DITHER +// Dithers the resulting image using a 4x4 order dither pattern. +// D3DX_FILTER_SRGB_IN +// Denotes that the input data is in sRGB (gamma 2.2) colorspace. +// D3DX_FILTER_SRGB_OUT +// Denotes that the output data is in sRGB (gamma 2.2) colorspace. +// D3DX_FILTER_SRGB +// Same as specifying D3DX_FILTER_SRGB_IN | D3DX_FILTER_SRGB_OUT +// +//---------------------------------------------------------------------------- + +#define D3DX_FILTER_NONE (1 << 0) +#define D3DX_FILTER_POINT (2 << 0) +#define D3DX_FILTER_LINEAR (3 << 0) +#define D3DX_FILTER_TRIANGLE (4 << 0) +#define D3DX_FILTER_BOX (5 << 0) + +#define D3DX_FILTER_MIRROR_U (1 << 16) +#define D3DX_FILTER_MIRROR_V (2 << 16) +#define D3DX_FILTER_MIRROR_W (4 << 16) +#define D3DX_FILTER_MIRROR (7 << 16) + +#define D3DX_FILTER_DITHER (1 << 19) +#define D3DX_FILTER_DITHER_DIFFUSION (2 << 19) + +#define D3DX_FILTER_SRGB_IN (1 << 21) +#define D3DX_FILTER_SRGB_OUT (2 << 21) +#define D3DX_FILTER_SRGB (3 << 21) + + +//----------------------------------------------------------------------------- +// D3DX_SKIP_DDS_MIP_LEVELS is used to skip mip levels when loading a DDS file: +//----------------------------------------------------------------------------- + +#define D3DX_SKIP_DDS_MIP_LEVELS_MASK 0x1F +#define D3DX_SKIP_DDS_MIP_LEVELS_SHIFT 26 +#define D3DX_SKIP_DDS_MIP_LEVELS(levels, filter) ((((levels) & D3DX_SKIP_DDS_MIP_LEVELS_MASK) << D3DX_SKIP_DDS_MIP_LEVELS_SHIFT) | ((filter) == D3DX_DEFAULT ? D3DX_FILTER_BOX : (filter))) + + + + +//---------------------------------------------------------------------------- +// D3DX_NORMALMAP flags: +// --------------------- +// These flags are used to control how D3DXComputeNormalMap generates normal +// maps. Any number of these flags may be OR'd together in any combination. +// +// D3DX_NORMALMAP_MIRROR_U +// Indicates that pixels off the edge of the texture on the U-axis +// should be mirrored, not wraped. +// D3DX_NORMALMAP_MIRROR_V +// Indicates that pixels off the edge of the texture on the V-axis +// should be mirrored, not wraped. +// D3DX_NORMALMAP_MIRROR +// Same as specifying D3DX_NORMALMAP_MIRROR_U | D3DX_NORMALMAP_MIRROR_V +// D3DX_NORMALMAP_INVERTSIGN +// Inverts the direction of each normal +// D3DX_NORMALMAP_COMPUTE_OCCLUSION +// Compute the per pixel Occlusion term and encodes it into the alpha. +// An Alpha of 1 means that the pixel is not obscured in anyway, and +// an alpha of 0 would mean that the pixel is completly obscured. +// +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- + +#define D3DX_NORMALMAP_MIRROR_U (1 << 16) +#define D3DX_NORMALMAP_MIRROR_V (2 << 16) +#define D3DX_NORMALMAP_MIRROR (3 << 16) +#define D3DX_NORMALMAP_INVERTSIGN (8 << 16) +#define D3DX_NORMALMAP_COMPUTE_OCCLUSION (16 << 16) + + + + +//---------------------------------------------------------------------------- +// D3DX_CHANNEL flags: +// ------------------- +// These flags are used by functions which operate on or more channels +// in a texture. +// +// D3DX_CHANNEL_RED +// Indicates the red channel should be used +// D3DX_CHANNEL_BLUE +// Indicates the blue channel should be used +// D3DX_CHANNEL_GREEN +// Indicates the green channel should be used +// D3DX_CHANNEL_ALPHA +// Indicates the alpha channel should be used +// D3DX_CHANNEL_LUMINANCE +// Indicates the luminaces of the red green and blue channels should be +// used. +// +//---------------------------------------------------------------------------- + +#define D3DX_CHANNEL_RED (1 << 0) +#define D3DX_CHANNEL_BLUE (1 << 1) +#define D3DX_CHANNEL_GREEN (1 << 2) +#define D3DX_CHANNEL_ALPHA (1 << 3) +#define D3DX_CHANNEL_LUMINANCE (1 << 4) + + + + +//---------------------------------------------------------------------------- +// D3DXIMAGE_FILEFORMAT: +// --------------------- +// This enum is used to describe supported image file formats. +// +//---------------------------------------------------------------------------- + +typedef enum _D3DXIMAGE_FILEFORMAT +{ + D3DXIFF_BMP = 0, + D3DXIFF_JPG = 1, + D3DXIFF_TGA = 2, + D3DXIFF_PNG = 3, + D3DXIFF_DDS = 4, + D3DXIFF_PPM = 5, + D3DXIFF_DIB = 6, + D3DXIFF_HDR = 7, //high dynamic range formats + D3DXIFF_PFM = 8, // + D3DXIFF_FORCE_DWORD = 0x7fffffff + +} D3DXIMAGE_FILEFORMAT; + + +//---------------------------------------------------------------------------- +// LPD3DXFILL2D and LPD3DXFILL3D: +// ------------------------------ +// Function types used by the texture fill functions. +// +// Parameters: +// pOut +// Pointer to a vector which the function uses to return its result. +// X,Y,Z,W will be mapped to R,G,B,A respectivly. +// pTexCoord +// Pointer to a vector containing the coordinates of the texel currently +// being evaluated. Textures and VolumeTexture texcoord components +// range from 0 to 1. CubeTexture texcoord component range from -1 to 1. +// pTexelSize +// Pointer to a vector containing the dimensions of the current texel. +// pData +// Pointer to user data. +// +//---------------------------------------------------------------------------- + +typedef VOID (WINAPI *LPD3DXFILL2D)(D3DXVECTOR4 *pOut, + CONST D3DXVECTOR2 *pTexCoord, CONST D3DXVECTOR2 *pTexelSize, LPVOID pData); + +typedef VOID (WINAPI *LPD3DXFILL3D)(D3DXVECTOR4 *pOut, + CONST D3DXVECTOR3 *pTexCoord, CONST D3DXVECTOR3 *pTexelSize, LPVOID pData); + + + +//---------------------------------------------------------------------------- +// D3DXIMAGE_INFO: +// --------------- +// This structure is used to return a rough description of what the +// the original contents of an image file looked like. +// +// Width +// Width of original image in pixels +// Height +// Height of original image in pixels +// Depth +// Depth of original image in pixels +// MipLevels +// Number of mip levels in original image +// Format +// D3D format which most closely describes the data in original image +// ResourceType +// D3DRESOURCETYPE representing the type of texture stored in the file. +// D3DRTYPE_TEXTURE, D3DRTYPE_VOLUMETEXTURE, or D3DRTYPE_CUBETEXTURE. +// ImageFileFormat +// D3DXIMAGE_FILEFORMAT representing the format of the image file. +// +//---------------------------------------------------------------------------- + +typedef struct _D3DXIMAGE_INFO +{ + UINT Width; + UINT Height; + UINT Depth; + UINT MipLevels; + D3DFORMAT Format; + D3DRESOURCETYPE ResourceType; + D3DXIMAGE_FILEFORMAT ImageFileFormat; + +} D3DXIMAGE_INFO; + + + + + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + + +////////////////////////////////////////////////////////////////////////////// +// Image File APIs /////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +; +//---------------------------------------------------------------------------- +// GetImageInfoFromFile/Resource: +// ------------------------------ +// Fills in a D3DXIMAGE_INFO struct with information about an image file. +// +// Parameters: +// pSrcFile +// File name of the source image. +// pSrcModule +// Module where resource is located, or NULL for module associated +// with image the os used to create the current process. +// pSrcResource +// Resource name +// pSrcData +// Pointer to file in memory. +// SrcDataSize +// Size in bytes of file in memory. +// pSrcInfo +// Pointer to a D3DXIMAGE_INFO structure to be filled in with the +// description of the data in the source image file. +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXGetImageInfoFromFileA( + LPCSTR pSrcFile, + D3DXIMAGE_INFO* pSrcInfo); + +HRESULT WINAPI + D3DXGetImageInfoFromFileW( + LPCWSTR pSrcFile, + D3DXIMAGE_INFO* pSrcInfo); + +#ifdef UNICODE +#define D3DXGetImageInfoFromFile D3DXGetImageInfoFromFileW +#else +#define D3DXGetImageInfoFromFile D3DXGetImageInfoFromFileA +#endif + + +HRESULT WINAPI + D3DXGetImageInfoFromResourceA( + HMODULE hSrcModule, + LPCSTR pSrcResource, + D3DXIMAGE_INFO* pSrcInfo); + +HRESULT WINAPI + D3DXGetImageInfoFromResourceW( + HMODULE hSrcModule, + LPCWSTR pSrcResource, + D3DXIMAGE_INFO* pSrcInfo); + +#ifdef UNICODE +#define D3DXGetImageInfoFromResource D3DXGetImageInfoFromResourceW +#else +#define D3DXGetImageInfoFromResource D3DXGetImageInfoFromResourceA +#endif + + +HRESULT WINAPI + D3DXGetImageInfoFromFileInMemory( + LPCVOID pSrcData, + UINT SrcDataSize, + D3DXIMAGE_INFO* pSrcInfo); + + + + +////////////////////////////////////////////////////////////////////////////// +// Load/Save Surface APIs //////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------------- +// D3DXLoadSurfaceFromFile/Resource: +// --------------------------------- +// Load surface from a file or resource +// +// Parameters: +// pDestSurface +// Destination surface, which will receive the image. +// pDestPalette +// Destination palette of 256 colors, or NULL +// pDestRect +// Destination rectangle, or NULL for entire surface +// pSrcFile +// File name of the source image. +// pSrcModule +// Module where resource is located, or NULL for module associated +// with image the os used to create the current process. +// pSrcResource +// Resource name +// pSrcData +// Pointer to file in memory. +// SrcDataSize +// Size in bytes of file in memory. +// pSrcRect +// Source rectangle, or NULL for entire image +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// pSrcInfo +// Pointer to a D3DXIMAGE_INFO structure to be filled in with the +// description of the data in the source image file, or NULL. +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXLoadSurfaceFromFileA( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + LPCSTR pSrcFile, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +HRESULT WINAPI + D3DXLoadSurfaceFromFileW( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + LPCWSTR pSrcFile, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +#ifdef UNICODE +#define D3DXLoadSurfaceFromFile D3DXLoadSurfaceFromFileW +#else +#define D3DXLoadSurfaceFromFile D3DXLoadSurfaceFromFileA +#endif + + + +HRESULT WINAPI + D3DXLoadSurfaceFromResourceA( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +HRESULT WINAPI + D3DXLoadSurfaceFromResourceW( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + + +#ifdef UNICODE +#define D3DXLoadSurfaceFromResource D3DXLoadSurfaceFromResourceW +#else +#define D3DXLoadSurfaceFromResource D3DXLoadSurfaceFromResourceA +#endif + + + +HRESULT WINAPI + D3DXLoadSurfaceFromFileInMemory( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + LPCVOID pSrcData, + UINT SrcDataSize, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + + + +//---------------------------------------------------------------------------- +// D3DXLoadSurfaceFromSurface: +// --------------------------- +// Load surface from another surface (with color conversion) +// +// Parameters: +// pDestSurface +// Destination surface, which will receive the image. +// pDestPalette +// Destination palette of 256 colors, or NULL +// pDestRect +// Destination rectangle, or NULL for entire surface +// pSrcSurface +// Source surface +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcRect +// Source rectangle, or NULL for entire surface +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXLoadSurfaceFromSurface( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + LPDIRECT3DSURFACE9 pSrcSurface, + CONST PALETTEENTRY* pSrcPalette, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey); + + +//---------------------------------------------------------------------------- +// D3DXLoadSurfaceFromMemory: +// -------------------------- +// Load surface from memory. +// +// Parameters: +// pDestSurface +// Destination surface, which will receive the image. +// pDestPalette +// Destination palette of 256 colors, or NULL +// pDestRect +// Destination rectangle, or NULL for entire surface +// pSrcMemory +// Pointer to the top-left corner of the source image in memory +// SrcFormat +// Pixel format of the source image. +// SrcPitch +// Pitch of source image, in bytes. For DXT formats, this number +// should represent the width of one row of cells, in bytes. +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcRect +// Source rectangle. +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXLoadSurfaceFromMemory( + LPDIRECT3DSURFACE9 pDestSurface, + CONST PALETTEENTRY* pDestPalette, + CONST RECT* pDestRect, + LPCVOID pSrcMemory, + D3DFORMAT SrcFormat, + UINT SrcPitch, + CONST PALETTEENTRY* pSrcPalette, + CONST RECT* pSrcRect, + DWORD Filter, + D3DCOLOR ColorKey); + + +//---------------------------------------------------------------------------- +// D3DXSaveSurfaceToFile: +// ---------------------- +// Save a surface to a image file. +// +// Parameters: +// pDestFile +// File name of the destination file +// DestFormat +// D3DXIMAGE_FILEFORMAT specifying file format to use when saving. +// pSrcSurface +// Source surface, containing the image to be saved +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcRect +// Source rectangle, or NULL for the entire image +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXSaveSurfaceToFileA( + LPCSTR pDestFile, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DSURFACE9 pSrcSurface, + CONST PALETTEENTRY* pSrcPalette, + CONST RECT* pSrcRect); + +HRESULT WINAPI + D3DXSaveSurfaceToFileW( + LPCWSTR pDestFile, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DSURFACE9 pSrcSurface, + CONST PALETTEENTRY* pSrcPalette, + CONST RECT* pSrcRect); + +#ifdef UNICODE +#define D3DXSaveSurfaceToFile D3DXSaveSurfaceToFileW +#else +#define D3DXSaveSurfaceToFile D3DXSaveSurfaceToFileA +#endif + +//---------------------------------------------------------------------------- +// D3DXSaveSurfaceToFileInMemory: +// ---------------------- +// Save a surface to a image file. +// +// Parameters: +// ppDestBuf +// address of pointer to d3dxbuffer for returning data bits +// DestFormat +// D3DXIMAGE_FILEFORMAT specifying file format to use when saving. +// pSrcSurface +// Source surface, containing the image to be saved +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcRect +// Source rectangle, or NULL for the entire image +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXSaveSurfaceToFileInMemory( + LPD3DXBUFFER* ppDestBuf, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DSURFACE9 pSrcSurface, + CONST PALETTEENTRY* pSrcPalette, + CONST RECT* pSrcRect); + + +////////////////////////////////////////////////////////////////////////////// +// Load/Save Volume APIs ///////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------------- +// D3DXLoadVolumeFromFile/Resource: +// -------------------------------- +// Load volume from a file or resource +// +// Parameters: +// pDestVolume +// Destination volume, which will receive the image. +// pDestPalette +// Destination palette of 256 colors, or NULL +// pDestBox +// Destination box, or NULL for entire volume +// pSrcFile +// File name of the source image. +// pSrcModule +// Module where resource is located, or NULL for module associated +// with image the os used to create the current process. +// pSrcResource +// Resource name +// pSrcData +// Pointer to file in memory. +// SrcDataSize +// Size in bytes of file in memory. +// pSrcBox +// Source box, or NULL for entire image +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// pSrcInfo +// Pointer to a D3DXIMAGE_INFO structure to be filled in with the +// description of the data in the source image file, or NULL. +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXLoadVolumeFromFileA( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + LPCSTR pSrcFile, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +HRESULT WINAPI + D3DXLoadVolumeFromFileW( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + LPCWSTR pSrcFile, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +#ifdef UNICODE +#define D3DXLoadVolumeFromFile D3DXLoadVolumeFromFileW +#else +#define D3DXLoadVolumeFromFile D3DXLoadVolumeFromFileA +#endif + + +HRESULT WINAPI + D3DXLoadVolumeFromResourceA( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + HMODULE hSrcModule, + LPCSTR pSrcResource, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +HRESULT WINAPI + D3DXLoadVolumeFromResourceW( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + +#ifdef UNICODE +#define D3DXLoadVolumeFromResource D3DXLoadVolumeFromResourceW +#else +#define D3DXLoadVolumeFromResource D3DXLoadVolumeFromResourceA +#endif + + + +HRESULT WINAPI + D3DXLoadVolumeFromFileInMemory( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + LPCVOID pSrcData, + UINT SrcDataSize, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo); + + + +//---------------------------------------------------------------------------- +// D3DXLoadVolumeFromVolume: +// ------------------------- +// Load volume from another volume (with color conversion) +// +// Parameters: +// pDestVolume +// Destination volume, which will receive the image. +// pDestPalette +// Destination palette of 256 colors, or NULL +// pDestBox +// Destination box, or NULL for entire volume +// pSrcVolume +// Source volume +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcBox +// Source box, or NULL for entire volume +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXLoadVolumeFromVolume( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + LPDIRECT3DVOLUME9 pSrcVolume, + CONST PALETTEENTRY* pSrcPalette, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey); + + + +//---------------------------------------------------------------------------- +// D3DXLoadVolumeFromMemory: +// ------------------------- +// Load volume from memory. +// +// Parameters: +// pDestVolume +// Destination volume, which will receive the image. +// pDestPalette +// Destination palette of 256 colors, or NULL +// pDestBox +// Destination box, or NULL for entire volume +// pSrcMemory +// Pointer to the top-left corner of the source volume in memory +// SrcFormat +// Pixel format of the source volume. +// SrcRowPitch +// Pitch of source image, in bytes. For DXT formats, this number +// should represent the size of one row of cells, in bytes. +// SrcSlicePitch +// Pitch of source image, in bytes. For DXT formats, this number +// should represent the size of one slice of cells, in bytes. +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcBox +// Source box. +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXLoadVolumeFromMemory( + LPDIRECT3DVOLUME9 pDestVolume, + CONST PALETTEENTRY* pDestPalette, + CONST D3DBOX* pDestBox, + LPCVOID pSrcMemory, + D3DFORMAT SrcFormat, + UINT SrcRowPitch, + UINT SrcSlicePitch, + CONST PALETTEENTRY* pSrcPalette, + CONST D3DBOX* pSrcBox, + DWORD Filter, + D3DCOLOR ColorKey); + + + +//---------------------------------------------------------------------------- +// D3DXSaveVolumeToFile: +// --------------------- +// Save a volume to a image file. +// +// Parameters: +// pDestFile +// File name of the destination file +// DestFormat +// D3DXIMAGE_FILEFORMAT specifying file format to use when saving. +// pSrcVolume +// Source volume, containing the image to be saved +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcBox +// Source box, or NULL for the entire volume +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXSaveVolumeToFileA( + LPCSTR pDestFile, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DVOLUME9 pSrcVolume, + CONST PALETTEENTRY* pSrcPalette, + CONST D3DBOX* pSrcBox); + +HRESULT WINAPI + D3DXSaveVolumeToFileW( + LPCWSTR pDestFile, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DVOLUME9 pSrcVolume, + CONST PALETTEENTRY* pSrcPalette, + CONST D3DBOX* pSrcBox); + +#ifdef UNICODE +#define D3DXSaveVolumeToFile D3DXSaveVolumeToFileW +#else +#define D3DXSaveVolumeToFile D3DXSaveVolumeToFileA +#endif + + +//---------------------------------------------------------------------------- +// D3DXSaveVolumeToFileInMemory: +// --------------------- +// Save a volume to a image file. +// +// Parameters: +// pDestFile +// File name of the destination file +// DestFormat +// D3DXIMAGE_FILEFORMAT specifying file format to use when saving. +// pSrcVolume +// Source volume, containing the image to be saved +// pSrcPalette +// Source palette of 256 colors, or NULL +// pSrcBox +// Source box, or NULL for the entire volume +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXSaveVolumeToFileInMemory( + LPD3DXBUFFER* ppDestBuf, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DVOLUME9 pSrcVolume, + CONST PALETTEENTRY* pSrcPalette, + CONST D3DBOX* pSrcBox); + +////////////////////////////////////////////////////////////////////////////// +// Create/Save Texture APIs ////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------------- +// D3DXCheckTextureRequirements: +// ----------------------------- +// Checks texture creation parameters. If parameters are invalid, this +// function returns corrected parameters. +// +// Parameters: +// +// pDevice +// The D3D device to be used +// pWidth, pHeight, pDepth, pSize +// Desired size in pixels, or NULL. Returns corrected size. +// pNumMipLevels +// Number of desired mipmap levels, or NULL. Returns corrected number. +// Usage +// Texture usage flags +// pFormat +// Desired pixel format, or NULL. Returns corrected format. +// Pool +// Memory pool to be used to create texture +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCheckTextureRequirements( + LPDIRECT3DDEVICE9 pDevice, + UINT* pWidth, + UINT* pHeight, + UINT* pNumMipLevels, + DWORD Usage, + D3DFORMAT* pFormat, + D3DPOOL Pool); + +HRESULT WINAPI + D3DXCheckCubeTextureRequirements( + LPDIRECT3DDEVICE9 pDevice, + UINT* pSize, + UINT* pNumMipLevels, + DWORD Usage, + D3DFORMAT* pFormat, + D3DPOOL Pool); + +HRESULT WINAPI + D3DXCheckVolumeTextureRequirements( + LPDIRECT3DDEVICE9 pDevice, + UINT* pWidth, + UINT* pHeight, + UINT* pDepth, + UINT* pNumMipLevels, + DWORD Usage, + D3DFORMAT* pFormat, + D3DPOOL Pool); + + +//---------------------------------------------------------------------------- +// D3DXCreateTexture: +// ------------------ +// Create an empty texture +// +// Parameters: +// +// pDevice +// The D3D device with which the texture is going to be used. +// Width, Height, Depth, Size +// size in pixels. these must be non-zero +// MipLevels +// number of mip levels desired. if zero or D3DX_DEFAULT, a complete +// mipmap chain will be created. +// Usage +// Texture usage flags +// Format +// Pixel format. +// Pool +// Memory pool to be used to create texture +// ppTexture, ppCubeTexture, ppVolumeTexture +// The texture object that will be created +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXCreateTexture( + LPDIRECT3DDEVICE9 pDevice, + UINT Width, + UINT Height, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateCubeTexture( + LPDIRECT3DDEVICE9 pDevice, + UINT Size, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTexture( + LPDIRECT3DDEVICE9 pDevice, + UINT Width, + UINT Height, + UINT Depth, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + + + +//---------------------------------------------------------------------------- +// D3DXCreateTextureFromFile/Resource: +// ----------------------------------- +// Create a texture object from a file or resource. +// +// Parameters: +// +// pDevice +// The D3D device with which the texture is going to be used. +// pSrcFile +// File name. +// hSrcModule +// Module handle. if NULL, current module will be used. +// pSrcResource +// Resource name in module +// pvSrcData +// Pointer to file in memory. +// SrcDataSize +// Size in bytes of file in memory. +// Width, Height, Depth, Size +// Size in pixels. If zero or D3DX_DEFAULT, the size will be taken from +// the file and rounded up to a power of two. If D3DX_DEFAULT_NONPOW2, +// and the device supports NONPOW2 textures, the size will not be rounded. +// If D3DX_FROM_FILE, the size will be taken exactly as it is in the file, +// and the call will fail if this violates device capabilities. +// MipLevels +// Number of mip levels. If zero or D3DX_DEFAULT, a complete mipmap +// chain will be created. If D3DX_FROM_FILE, the size will be taken +// exactly as it is in the file, and the call will fail if this violates +// device capabilities. +// Usage +// Texture usage flags +// Format +// Desired pixel format. If D3DFMT_UNKNOWN, the format will be +// taken from the file. If D3DFMT_FROM_FILE, the format will be taken +// exactly as it is in the file, and the call will fail if the device does +// not support the given format. +// Pool +// Memory pool to be used to create texture +// Filter +// D3DX_FILTER flags controlling how the image is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_TRIANGLE. +// MipFilter +// D3DX_FILTER flags controlling how each miplevel is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_BOX. +// Use the D3DX_SKIP_DDS_MIP_LEVELS macro to specify both a filter and the +// number of mip levels to skip when loading DDS files. +// ColorKey +// Color to replace with transparent black, or 0 to disable colorkey. +// This is always a 32-bit ARGB color, independent of the source image +// format. Alpha is significant, and should usually be set to FF for +// opaque colorkeys. (ex. Opaque black == 0xff000000) +// pSrcInfo +// Pointer to a D3DXIMAGE_INFO structure to be filled in with the +// description of the data in the source image file, or NULL. +// pPalette +// 256 color palette to be filled in, or NULL +// ppTexture, ppCubeTexture, ppVolumeTexture +// The texture object that will be created +// +//---------------------------------------------------------------------------- + +// FromFile + +HRESULT WINAPI + D3DXCreateTextureFromFileA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateTextureFromFileW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + LPDIRECT3DTEXTURE9* ppTexture); + +#ifdef UNICODE +#define D3DXCreateTextureFromFile D3DXCreateTextureFromFileW +#else +#define D3DXCreateTextureFromFile D3DXCreateTextureFromFileA +#endif + + +HRESULT WINAPI + D3DXCreateCubeTextureFromFileA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateCubeTextureFromFileW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +#ifdef UNICODE +#define D3DXCreateCubeTextureFromFile D3DXCreateCubeTextureFromFileW +#else +#define D3DXCreateCubeTextureFromFile D3DXCreateCubeTextureFromFileA +#endif + + +HRESULT WINAPI + D3DXCreateVolumeTextureFromFileA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTextureFromFileW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +#ifdef UNICODE +#define D3DXCreateVolumeTextureFromFile D3DXCreateVolumeTextureFromFileW +#else +#define D3DXCreateVolumeTextureFromFile D3DXCreateVolumeTextureFromFileA +#endif + + +// FromResource + +HRESULT WINAPI + D3DXCreateTextureFromResourceA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateTextureFromResourceW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + LPDIRECT3DTEXTURE9* ppTexture); + +#ifdef UNICODE +#define D3DXCreateTextureFromResource D3DXCreateTextureFromResourceW +#else +#define D3DXCreateTextureFromResource D3DXCreateTextureFromResourceA +#endif + + +HRESULT WINAPI + D3DXCreateCubeTextureFromResourceA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateCubeTextureFromResourceW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +#ifdef UNICODE +#define D3DXCreateCubeTextureFromResource D3DXCreateCubeTextureFromResourceW +#else +#define D3DXCreateCubeTextureFromResource D3DXCreateCubeTextureFromResourceA +#endif + + +HRESULT WINAPI + D3DXCreateVolumeTextureFromResourceA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTextureFromResourceW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +#ifdef UNICODE +#define D3DXCreateVolumeTextureFromResource D3DXCreateVolumeTextureFromResourceW +#else +#define D3DXCreateVolumeTextureFromResource D3DXCreateVolumeTextureFromResourceA +#endif + + +// FromFileEx + +HRESULT WINAPI + D3DXCreateTextureFromFileExA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + UINT Width, + UINT Height, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateTextureFromFileExW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + UINT Width, + UINT Height, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DTEXTURE9* ppTexture); + +#ifdef UNICODE +#define D3DXCreateTextureFromFileEx D3DXCreateTextureFromFileExW +#else +#define D3DXCreateTextureFromFileEx D3DXCreateTextureFromFileExA +#endif + + +HRESULT WINAPI + D3DXCreateCubeTextureFromFileExA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + UINT Size, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateCubeTextureFromFileExW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + UINT Size, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +#ifdef UNICODE +#define D3DXCreateCubeTextureFromFileEx D3DXCreateCubeTextureFromFileExW +#else +#define D3DXCreateCubeTextureFromFileEx D3DXCreateCubeTextureFromFileExA +#endif + + +HRESULT WINAPI + D3DXCreateVolumeTextureFromFileExA( + LPDIRECT3DDEVICE9 pDevice, + LPCSTR pSrcFile, + UINT Width, + UINT Height, + UINT Depth, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTextureFromFileExW( + LPDIRECT3DDEVICE9 pDevice, + LPCWSTR pSrcFile, + UINT Width, + UINT Height, + UINT Depth, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +#ifdef UNICODE +#define D3DXCreateVolumeTextureFromFileEx D3DXCreateVolumeTextureFromFileExW +#else +#define D3DXCreateVolumeTextureFromFileEx D3DXCreateVolumeTextureFromFileExA +#endif + + +// FromResourceEx + +HRESULT WINAPI + D3DXCreateTextureFromResourceExA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + UINT Width, + UINT Height, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateTextureFromResourceExW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + UINT Width, + UINT Height, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DTEXTURE9* ppTexture); + +#ifdef UNICODE +#define D3DXCreateTextureFromResourceEx D3DXCreateTextureFromResourceExW +#else +#define D3DXCreateTextureFromResourceEx D3DXCreateTextureFromResourceExA +#endif + + +HRESULT WINAPI + D3DXCreateCubeTextureFromResourceExA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + UINT Size, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateCubeTextureFromResourceExW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + UINT Size, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +#ifdef UNICODE +#define D3DXCreateCubeTextureFromResourceEx D3DXCreateCubeTextureFromResourceExW +#else +#define D3DXCreateCubeTextureFromResourceEx D3DXCreateCubeTextureFromResourceExA +#endif + + +HRESULT WINAPI + D3DXCreateVolumeTextureFromResourceExA( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCSTR pSrcResource, + UINT Width, + UINT Height, + UINT Depth, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTextureFromResourceExW( + LPDIRECT3DDEVICE9 pDevice, + HMODULE hSrcModule, + LPCWSTR pSrcResource, + UINT Width, + UINT Height, + UINT Depth, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + +#ifdef UNICODE +#define D3DXCreateVolumeTextureFromResourceEx D3DXCreateVolumeTextureFromResourceExW +#else +#define D3DXCreateVolumeTextureFromResourceEx D3DXCreateVolumeTextureFromResourceExA +#endif + + +// FromFileInMemory + +HRESULT WINAPI + D3DXCreateTextureFromFileInMemory( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataSize, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateCubeTextureFromFileInMemory( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataSize, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTextureFromFileInMemory( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataSize, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + + +// FromFileInMemoryEx + +HRESULT WINAPI + D3DXCreateTextureFromFileInMemoryEx( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataSize, + UINT Width, + UINT Height, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DTEXTURE9* ppTexture); + +HRESULT WINAPI + D3DXCreateCubeTextureFromFileInMemoryEx( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataSize, + UINT Size, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DCUBETEXTURE9* ppCubeTexture); + +HRESULT WINAPI + D3DXCreateVolumeTextureFromFileInMemoryEx( + LPDIRECT3DDEVICE9 pDevice, + LPCVOID pSrcData, + UINT SrcDataSize, + UINT Width, + UINT Height, + UINT Depth, + UINT MipLevels, + DWORD Usage, + D3DFORMAT Format, + D3DPOOL Pool, + DWORD Filter, + DWORD MipFilter, + D3DCOLOR ColorKey, + D3DXIMAGE_INFO* pSrcInfo, + PALETTEENTRY* pPalette, + LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture); + + + +//---------------------------------------------------------------------------- +// D3DXSaveTextureToFile: +// ---------------------- +// Save a texture to a file. +// +// Parameters: +// pDestFile +// File name of the destination file +// DestFormat +// D3DXIMAGE_FILEFORMAT specifying file format to use when saving. +// pSrcTexture +// Source texture, containing the image to be saved +// pSrcPalette +// Source palette of 256 colors, or NULL +// +//---------------------------------------------------------------------------- + + +HRESULT WINAPI + D3DXSaveTextureToFileA( + LPCSTR pDestFile, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DBASETEXTURE9 pSrcTexture, + CONST PALETTEENTRY* pSrcPalette); + +HRESULT WINAPI + D3DXSaveTextureToFileW( + LPCWSTR pDestFile, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DBASETEXTURE9 pSrcTexture, + CONST PALETTEENTRY* pSrcPalette); + +#ifdef UNICODE +#define D3DXSaveTextureToFile D3DXSaveTextureToFileW +#else +#define D3DXSaveTextureToFile D3DXSaveTextureToFileA +#endif + + +//---------------------------------------------------------------------------- +// D3DXSaveTextureToFileInMemory: +// ---------------------- +// Save a texture to a file. +// +// Parameters: +// ppDestBuf +// address of a d3dxbuffer pointer to return the image data +// DestFormat +// D3DXIMAGE_FILEFORMAT specifying file format to use when saving. +// pSrcTexture +// Source texture, containing the image to be saved +// pSrcPalette +// Source palette of 256 colors, or NULL +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXSaveTextureToFileInMemory( + LPD3DXBUFFER* ppDestBuf, + D3DXIMAGE_FILEFORMAT DestFormat, + LPDIRECT3DBASETEXTURE9 pSrcTexture, + CONST PALETTEENTRY* pSrcPalette); + + + + +////////////////////////////////////////////////////////////////////////////// +// Misc Texture APIs ///////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------------- +// D3DXFilterTexture: +// ------------------ +// Filters mipmaps levels of a texture. +// +// Parameters: +// pBaseTexture +// The texture object to be filtered +// pPalette +// 256 color palette to be used, or NULL for non-palettized formats +// SrcLevel +// The level whose image is used to generate the subsequent levels. +// Filter +// D3DX_FILTER flags controlling how each miplevel is filtered. +// Or D3DX_DEFAULT for D3DX_FILTER_BOX, +// +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXFilterTexture( + LPDIRECT3DBASETEXTURE9 pBaseTexture, + CONST PALETTEENTRY* pPalette, + UINT SrcLevel, + DWORD Filter); + +#define D3DXFilterCubeTexture D3DXFilterTexture +#define D3DXFilterVolumeTexture D3DXFilterTexture + + + +//---------------------------------------------------------------------------- +// D3DXFillTexture: +// ---------------- +// Uses a user provided function to fill each texel of each mip level of a +// given texture. +// +// Paramters: +// pTexture, pCubeTexture, pVolumeTexture +// Pointer to the texture to be filled. +// pFunction +// Pointer to user provided evalutor function which will be used to +// compute the value of each texel. +// pData +// Pointer to an arbitrary block of user defined data. This pointer +// will be passed to the function provided in pFunction +//----------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXFillTexture( + LPDIRECT3DTEXTURE9 pTexture, + LPD3DXFILL2D pFunction, + LPVOID pData); + +HRESULT WINAPI + D3DXFillCubeTexture( + LPDIRECT3DCUBETEXTURE9 pCubeTexture, + LPD3DXFILL3D pFunction, + LPVOID pData); + +HRESULT WINAPI + D3DXFillVolumeTexture( + LPDIRECT3DVOLUMETEXTURE9 pVolumeTexture, + LPD3DXFILL3D pFunction, + LPVOID pData); + +//--------------------------------------------------------------------------- +// D3DXFillTextureTX: +// ------------------ +// Uses a TX Shader target to function to fill each texel of each mip level +// of a given texture. The TX Shader target should be a compiled function +// taking 2 paramters and returning a float4 color. +// +// Paramters: +// pTexture, pCubeTexture, pVolumeTexture +// Pointer to the texture to be filled. +// pTextureShader +// Pointer to the texture shader to be used to fill in the texture +//---------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXFillTextureTX( + LPDIRECT3DTEXTURE9 pTexture, + LPD3DXTEXTURESHADER pTextureShader); + + +HRESULT WINAPI + D3DXFillCubeTextureTX( + LPDIRECT3DCUBETEXTURE9 pCubeTexture, + LPD3DXTEXTURESHADER pTextureShader); + + +HRESULT WINAPI + D3DXFillVolumeTextureTX( + LPDIRECT3DVOLUMETEXTURE9 pVolumeTexture, + LPD3DXTEXTURESHADER pTextureShader); + + + +//---------------------------------------------------------------------------- +// D3DXComputeNormalMap: +// --------------------- +// Converts a height map into a normal map. The (x,y,z) components of each +// normal are mapped to the (r,g,b) channels of the output texture. +// +// Parameters +// pTexture +// Pointer to the destination texture +// pSrcTexture +// Pointer to the source heightmap texture +// pSrcPalette +// Source palette of 256 colors, or NULL +// Flags +// D3DX_NORMALMAP flags +// Channel +// D3DX_CHANNEL specifying source of height information +// Amplitude +// The constant value which the height information is multiplied by. +//--------------------------------------------------------------------------- + +HRESULT WINAPI + D3DXComputeNormalMap( + LPDIRECT3DTEXTURE9 pTexture, + LPDIRECT3DTEXTURE9 pSrcTexture, + CONST PALETTEENTRY* pSrcPalette, + DWORD Flags, + DWORD Channel, + FLOAT Amplitude); + + + + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__D3DX9TEX_H__ + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9xof.h b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9xof.h new file mode 100644 index 0000000000..c513f0fc93 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Include/d3dx9xof.h @@ -0,0 +1,299 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +// File: d3dx9xof.h +// Content: D3DX .X File types and functions +// +/////////////////////////////////////////////////////////////////////////// + +#include "d3dx9.h" + +#if !defined( __D3DX9XOF_H__ ) +#define __D3DX9XOF_H__ + +#if defined( __cplusplus ) +extern "C" { +#endif // defined( __cplusplus ) + +//---------------------------------------------------------------------------- +// D3DXF_FILEFORMAT +// This flag is used to specify what file type to use when saving to disk. +// _BINARY, and _TEXT are mutually exclusive, while +// _COMPRESSED is an optional setting that works with all file types. +//---------------------------------------------------------------------------- +typedef DWORD D3DXF_FILEFORMAT; + +#define D3DXF_FILEFORMAT_BINARY 0 +#define D3DXF_FILEFORMAT_TEXT 1 +#define D3DXF_FILEFORMAT_COMPRESSED 2 + +//---------------------------------------------------------------------------- +// D3DXF_FILESAVEOPTIONS +// This flag is used to specify where to save the file to. Each flag is +// mutually exclusive, indicates the data location of the file, and also +// chooses which additional data will specify the location. +// _TOFILE is paired with a filename (LPCSTR) +// _TOWFILE is paired with a filename (LPWSTR) +//---------------------------------------------------------------------------- +typedef DWORD D3DXF_FILESAVEOPTIONS; + +#define D3DXF_FILESAVE_TOFILE 0x00L +#define D3DXF_FILESAVE_TOWFILE 0x01L + +//---------------------------------------------------------------------------- +// D3DXF_FILELOADOPTIONS +// This flag is used to specify where to load the file from. Each flag is +// mutually exclusive, indicates the data location of the file, and also +// chooses which additional data will specify the location. +// _FROMFILE is paired with a filename (LPCSTR) +// _FROMWFILE is paired with a filename (LPWSTR) +// _FROMRESOURCE is paired with a (D3DXF_FILELOADRESOUCE*) description. +// _FROMMEMORY is paired with a (D3DXF_FILELOADMEMORY*) description. +//---------------------------------------------------------------------------- +typedef DWORD D3DXF_FILELOADOPTIONS; + +#define D3DXF_FILELOAD_FROMFILE 0x00L +#define D3DXF_FILELOAD_FROMWFILE 0x01L +#define D3DXF_FILELOAD_FROMRESOURCE 0x02L +#define D3DXF_FILELOAD_FROMMEMORY 0x03L + +//---------------------------------------------------------------------------- +// D3DXF_FILELOADRESOURCE: +//---------------------------------------------------------------------------- + +typedef struct _D3DXF_FILELOADRESOURCE +{ + HMODULE hModule; // Desc + LPCSTR lpName; // Desc + LPCSTR lpType; // Desc +} D3DXF_FILELOADRESOURCE; + +//---------------------------------------------------------------------------- +// D3DXF_FILELOADMEMORY: +//---------------------------------------------------------------------------- + +typedef struct _D3DXF_FILELOADMEMORY +{ + LPCVOID lpMemory; // Desc + SIZE_T dSize; // Desc +} D3DXF_FILELOADMEMORY; + +#if defined( _WIN32 ) && !defined( _NO_COM ) + +// {cef08cf9-7b4f-4429-9624-2a690a933201} +DEFINE_GUID( IID_ID3DXFile, +0xcef08cf9, 0x7b4f, 0x4429, 0x96, 0x24, 0x2a, 0x69, 0x0a, 0x93, 0x32, 0x01 ); + +// {cef08cfa-7b4f-4429-9624-2a690a933201} +DEFINE_GUID( IID_ID3DXFileSaveObject, +0xcef08cfa, 0x7b4f, 0x4429, 0x96, 0x24, 0x2a, 0x69, 0x0a, 0x93, 0x32, 0x01 ); + +// {cef08cfb-7b4f-4429-9624-2a690a933201} +DEFINE_GUID( IID_ID3DXFileSaveData, +0xcef08cfb, 0x7b4f, 0x4429, 0x96, 0x24, 0x2a, 0x69, 0x0a, 0x93, 0x32, 0x01 ); + +// {cef08cfc-7b4f-4429-9624-2a690a933201} +DEFINE_GUID( IID_ID3DXFileEnumObject, +0xcef08cfc, 0x7b4f, 0x4429, 0x96, 0x24, 0x2a, 0x69, 0x0a, 0x93, 0x32, 0x01 ); + +// {cef08cfd-7b4f-4429-9624-2a690a933201} +DEFINE_GUID( IID_ID3DXFileData, +0xcef08cfd, 0x7b4f, 0x4429, 0x96, 0x24, 0x2a, 0x69, 0x0a, 0x93, 0x32, 0x01 ); + +#endif // defined( _WIN32 ) && !defined( _NO_COM ) + +#if defined( __cplusplus ) +#if !defined( DECLSPEC_UUID ) +#if _MSC_VER >= 1100 +#define DECLSPEC_UUID( x ) __declspec( uuid( x ) ) +#else // !( _MSC_VER >= 1100 ) +#define DECLSPEC_UUID( x ) +#endif // !( _MSC_VER >= 1100 ) +#endif // !defined( DECLSPEC_UUID ) + +interface DECLSPEC_UUID( "cef08cf9-7b4f-4429-9624-2a690a933201" ) + ID3DXFile; +interface DECLSPEC_UUID( "cef08cfa-7b4f-4429-9624-2a690a933201" ) + ID3DXFileSaveObject; +interface DECLSPEC_UUID( "cef08cfb-7b4f-4429-9624-2a690a933201" ) + ID3DXFileSaveData; +interface DECLSPEC_UUID( "cef08cfc-7b4f-4429-9624-2a690a933201" ) + ID3DXFileEnumObject; +interface DECLSPEC_UUID( "cef08cfd-7b4f-4429-9624-2a690a933201" ) + ID3DXFileData; + +#if defined( _COM_SMARTPTR_TYPEDEF ) +_COM_SMARTPTR_TYPEDEF( ID3DXFile, + __uuidof( ID3DXFile ) ); +_COM_SMARTPTR_TYPEDEF( ID3DXFileSaveObject, + __uuidof( ID3DXFileSaveObject ) ); +_COM_SMARTPTR_TYPEDEF( ID3DXFileSaveData, + __uuidof( ID3DXFileSaveData ) ); +_COM_SMARTPTR_TYPEDEF( ID3DXFileEnumObject, + __uuidof( ID3DXFileEnumObject ) ); +_COM_SMARTPTR_TYPEDEF( ID3DXFileData, + __uuidof( ID3DXFileData ) ); +#endif // defined( _COM_SMARTPTR_TYPEDEF ) +#endif // defined( __cplusplus ) + +typedef interface ID3DXFile ID3DXFile; +typedef interface ID3DXFileSaveObject ID3DXFileSaveObject; +typedef interface ID3DXFileSaveData ID3DXFileSaveData; +typedef interface ID3DXFileEnumObject ID3DXFileEnumObject; +typedef interface ID3DXFileData ID3DXFileData; + +////////////////////////////////////////////////////////////////////////////// +// ID3DXFile ///////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#undef INTERFACE +#define INTERFACE ID3DXFile + +DECLARE_INTERFACE_( ID3DXFile, IUnknown ) +{ + STDMETHOD( QueryInterface )( THIS_ REFIID, LPVOID* ) PURE; + STDMETHOD_( ULONG, AddRef )( THIS ) PURE; + STDMETHOD_( ULONG, Release )( THIS ) PURE; + + STDMETHOD( CreateEnumObject )( THIS_ LPCVOID, D3DXF_FILELOADOPTIONS, + ID3DXFileEnumObject** ) PURE; + STDMETHOD( CreateSaveObject )( THIS_ LPCVOID, D3DXF_FILESAVEOPTIONS, + D3DXF_FILEFORMAT, ID3DXFileSaveObject** ) PURE; + STDMETHOD( RegisterTemplates )( THIS_ LPCVOID, SIZE_T ) PURE; + STDMETHOD( RegisterEnumTemplates )( THIS_ ID3DXFileEnumObject* ) PURE; +}; + +////////////////////////////////////////////////////////////////////////////// +// ID3DXFileSaveObject /////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#undef INTERFACE +#define INTERFACE ID3DXFileSaveObject + +DECLARE_INTERFACE_( ID3DXFileSaveObject, IUnknown ) +{ + STDMETHOD( QueryInterface )( THIS_ REFIID, LPVOID* ) PURE; + STDMETHOD_( ULONG, AddRef )( THIS ) PURE; + STDMETHOD_( ULONG, Release )( THIS ) PURE; + + STDMETHOD( GetFile )( THIS_ ID3DXFile** ) PURE; + STDMETHOD( AddDataObject )( THIS_ REFGUID, LPCSTR, CONST GUID*, + SIZE_T, LPCVOID, ID3DXFileSaveData** ) PURE; + STDMETHOD( Save )( THIS ) PURE; +}; + +////////////////////////////////////////////////////////////////////////////// +// ID3DXFileSaveData ///////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#undef INTERFACE +#define INTERFACE ID3DXFileSaveData + +DECLARE_INTERFACE_( ID3DXFileSaveData, IUnknown ) +{ + STDMETHOD( QueryInterface )( THIS_ REFIID, LPVOID* ) PURE; + STDMETHOD_( ULONG, AddRef )( THIS ) PURE; + STDMETHOD_( ULONG, Release )( THIS ) PURE; + + STDMETHOD( GetSave )( THIS_ ID3DXFileSaveObject** ) PURE; + STDMETHOD( GetName )( THIS_ LPSTR, SIZE_T* ) PURE; + STDMETHOD( GetId )( THIS_ LPGUID ) PURE; + STDMETHOD( GetType )( THIS_ GUID* ) PURE; + STDMETHOD( AddDataObject )( THIS_ REFGUID, LPCSTR, CONST GUID*, + SIZE_T, LPCVOID, ID3DXFileSaveData** ) PURE; + STDMETHOD( AddDataReference )( THIS_ LPCSTR, CONST GUID* ) PURE; +}; + +////////////////////////////////////////////////////////////////////////////// +// ID3DXFileEnumObject /////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#undef INTERFACE +#define INTERFACE ID3DXFileEnumObject + +DECLARE_INTERFACE_( ID3DXFileEnumObject, IUnknown ) +{ + STDMETHOD( QueryInterface )( THIS_ REFIID, LPVOID* ) PURE; + STDMETHOD_( ULONG, AddRef )( THIS ) PURE; + STDMETHOD_( ULONG, Release )( THIS ) PURE; + + STDMETHOD( GetFile )( THIS_ ID3DXFile** ) PURE; + STDMETHOD( GetChildren )( THIS_ SIZE_T* ) PURE; + STDMETHOD( GetChild )( THIS_ SIZE_T, ID3DXFileData** ) PURE; + STDMETHOD( GetDataObjectById )( THIS_ REFGUID, ID3DXFileData** ) PURE; + STDMETHOD( GetDataObjectByName )( THIS_ LPCSTR, ID3DXFileData** ) PURE; +}; + +////////////////////////////////////////////////////////////////////////////// +// ID3DXFileData ///////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +#undef INTERFACE +#define INTERFACE ID3DXFileData + +DECLARE_INTERFACE_( ID3DXFileData, IUnknown ) +{ + STDMETHOD( QueryInterface )( THIS_ REFIID, LPVOID* ) PURE; + STDMETHOD_( ULONG, AddRef )( THIS ) PURE; + STDMETHOD_( ULONG, Release )( THIS ) PURE; + + STDMETHOD( GetEnum )( THIS_ ID3DXFileEnumObject** ) PURE; + STDMETHOD( GetName )( THIS_ LPSTR, SIZE_T* ) PURE; + STDMETHOD( GetId )( THIS_ LPGUID ) PURE; + STDMETHOD( Lock )( THIS_ SIZE_T*, LPCVOID* ) PURE; + STDMETHOD( Unlock )( THIS ) PURE; + STDMETHOD( GetType )( THIS_ GUID* ) PURE; + STDMETHOD_( BOOL, IsReference )( THIS ) PURE; + STDMETHOD( GetChildren )( THIS_ SIZE_T* ) PURE; + STDMETHOD( GetChild )( THIS_ SIZE_T, ID3DXFileData** ) PURE; +}; + +STDAPI D3DXFileCreate( ID3DXFile** lplpDirectXFile ); + +/* + * DirectX File errors. + */ + +#define _FACD3DXF 0x876 + +#define D3DXFERR_BADOBJECT MAKE_HRESULT( 1, _FACD3DXF, 900 ) +#define D3DXFERR_BADVALUE MAKE_HRESULT( 1, _FACD3DXF, 901 ) +#define D3DXFERR_BADTYPE MAKE_HRESULT( 1, _FACD3DXF, 902 ) +#define D3DXFERR_NOTFOUND MAKE_HRESULT( 1, _FACD3DXF, 903 ) +#define D3DXFERR_NOTDONEYET MAKE_HRESULT( 1, _FACD3DXF, 904 ) +#define D3DXFERR_FILENOTFOUND MAKE_HRESULT( 1, _FACD3DXF, 905 ) +#define D3DXFERR_RESOURCENOTFOUND MAKE_HRESULT( 1, _FACD3DXF, 906 ) +#define D3DXFERR_BADRESOURCE MAKE_HRESULT( 1, _FACD3DXF, 907 ) +#define D3DXFERR_BADFILETYPE MAKE_HRESULT( 1, _FACD3DXF, 908 ) +#define D3DXFERR_BADFILEVERSION MAKE_HRESULT( 1, _FACD3DXF, 909 ) +#define D3DXFERR_BADFILEFLOATSIZE MAKE_HRESULT( 1, _FACD3DXF, 910 ) +#define D3DXFERR_BADFILE MAKE_HRESULT( 1, _FACD3DXF, 911 ) +#define D3DXFERR_PARSEERROR MAKE_HRESULT( 1, _FACD3DXF, 912 ) +#define D3DXFERR_BADARRAYSIZE MAKE_HRESULT( 1, _FACD3DXF, 913 ) +#define D3DXFERR_BADDATAREFERENCE MAKE_HRESULT( 1, _FACD3DXF, 914 ) +#define D3DXFERR_NOMOREOBJECTS MAKE_HRESULT( 1, _FACD3DXF, 915 ) +#define D3DXFERR_NOMOREDATA MAKE_HRESULT( 1, _FACD3DXF, 916 ) +#define D3DXFERR_BADCACHEFILE MAKE_HRESULT( 1, _FACD3DXF, 917 ) + +/* + * DirectX File object types. + */ + +#ifndef WIN_TYPES +#define WIN_TYPES(itype, ptype) typedef interface itype *LP##ptype, **LPLP##ptype +#endif + +WIN_TYPES(ID3DXFile, D3DXFILE); +WIN_TYPES(ID3DXFileEnumObject, D3DXFILEENUMOBJECT); +WIN_TYPES(ID3DXFileSaveObject, D3DXFILESAVEOBJECT); +WIN_TYPES(ID3DXFileData, D3DXFILEDATA); +WIN_TYPES(ID3DXFileSaveData, D3DXFILESAVEDATA); + +#if defined( __cplusplus ) +} // extern "C" +#endif // defined( __cplusplus ) + +#endif // !defined( __D3DX9XOF_H__ ) + + diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Lib/d3d9.lib b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Lib/d3d9.lib new file mode 100644 index 0000000000000000000000000000000000000000..f6eddc60b50909d736199425673c5d4ceac692db GIT binary patch literal 5210 zcmcIoUvC;m5Fa4%AB+vgl^RuTL#0GXUmRmFHd0j|HfI+F3^_1K`f|CNYmABwIv-Z5 zKGe@qKSlZl^48a=4|(ZBrSv6l{Q_yeL6y$l?Hqe>;KR_B#=AQ+x4+q)+1bHge5Dyj z$6trkIYnl*U&Xn&q`@rp?T6#y##%_ z@-t~`h_)r#CjIKM*3gZ*)@n91vuzNR^mxCLJ1h**%1Y9sZ~5|5St+l7*L_;m%~IFY z9kX3L(kSZZdaGZ>W^Pxi`<1G8(rM{6{h8S{bP2cdsFJJaQ~5nvttjPPxmvBuO09qc zNh&E{;S6u-&iEHkuJNnb+seG=V znnDP8%IFLEv|;P7IS0%2MG0v$H)+NXx-q!COC;zkXj1#sQ@099u^=1%MgV{ zh`|!f!7N;Z>kxq8NO=gRaa$*e^U3Zgxy&8n#PteR(Ss@}UJ^gO=%x?60|&W6^zv-Q z^An{jJE2h;rR<7{ypP56^|%j*{T@uiseC0XF-@GpCQHJOpWJTdPoGC-a!Xt;cZ<9n z@76${_S`=p8kJdkp};?L2ZWpHdgpw;@>Ym=R|>3rSZ%agl%p=ImeN}(UN=1n7Xu;q zedZr|HUOAMtQJ^pFyn7k?J2-E4t}8t?GEpoX z+_$9te=yrxU$PYdlO$lO#7v6Gl8p!h;g8xU9klb#>!0Am2SQ`|tTDraK--l7EK`q( zV{MGt7a~rY=^z6fosAxc@jqjKcw?*M1Hosk3qle9POFd%(>DFa$9j58h>xHZAHP{< zG2_59KCmoyH6cDyBw+FJD@}OM;^TktyB~it9}KO@$3C;o!8`RA0@%*=KC=;bYJ-l6 zg&@0AViWFEn)pobPnz(4if8NRJU>BL?*uh=1ZFqscOLsa$1Y?sz_L^cAz1A*jVF&h z3}aijmG!nxM(ZNXx(S}qt6P<&AHxavneCxfi)7VRpJvA_8u-m68%gi8x`|e?)AD}p z31xiWq=)#1UG{*8CzOj3=AR>4P(%}}5(kb3zRz;Vt+^hxPju8C zuZgH)@#MhK!1o?U#LM+Qv|c?%DAV2DOdp<8<2i6N@VmQo+WR)(KcTQ3nZw)QDjR8e zr%>^YLyu8kF8CO6=0qH;5_Mq4&V){((1-IW;>=s8H&ER=U^MW%r%`bj_Q0|VW&(l# E0PCscwg3PC literal 0 HcmV?d00001 diff --git a/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Lib/d3dx9.lib b/client_files/native_autoloot/eq-core-dll/dependencies/dx9/Lib/d3dx9.lib new file mode 100644 index 0000000000000000000000000000000000000000..727baf5e65cb112eafa845c007e3eee1f68f2dce GIT binary patch literal 89010 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
VZ{P z+Mjrsg{(dFXDr?k^tnyYXCUr@wvoOrA8w+j4!bJWE!X70e1mpH%nRaX&a*ar@zNHF z_Ypz-*4vQSmxUuu-1KBBmENuPO0gB-qk_0udfV_bn%+kT@n_(?zCiCtXW1QN;-;r$ z1v;wY@eTMd(0+jVA>1sv?c!au6_0&|JvM~y7Vg5aj(Nu%m*G~%aX7nq2aOO~UZ;tT zD38w&#cXp$ZF*vCuwJ{&9R?Ln-#}kQW4r|#H666KzMc?kHBL}?BXrkw6+ft#8&tgp#LWi z*^?FG`VBpeYH2Dx3UaA6MJb%Ru~mdqEX={u=oQ@^RzWI`82Rpcs)LAb3t~yE(;8G3 zPTNR5Jx!r*C{-(BD|zd)`q;Ph(;1#9t)d0AyVk;S42-1cd%zhPW_h%2X1^u|`Zw}q zKhs3*Ej7lctJR^}c+0I(tkfYZvKjw+Q^J=v57ci-_~Ml|7|8>*cqd6 zEMskLyBE{%j8U}Y#&A2lxV^Pn9X~*{x>g-%acRD{B#i5ibn(;^EGLw&NdNeuAK^e?;$UX!&wTK+CW=DqqB2N)Yqsze!UlSW@>1xJ?{46zWVKPPZ-x9 z>Ef+oq&;5YMSm^YD?#F=wb2N5;sj4BU>_tnWG3 zM4idLCs3McWul*9)@xHU;3*v&ldm@MUX#A=JQH!|`npITaK4H78ubAKUd$P46(Td9 RH41lQxjLrz7Fcui{|Diw^Y#D$ literal 0 HcmV?d00001 diff --git a/client_files/native_autoloot/eq-core-dll/dxsdk81/include/dinput.h b/client_files/native_autoloot/eq-core-dll/dxsdk81/include/dinput.h new file mode 100644 index 0000000000..bfaff164be --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/dxsdk81/include/dinput.h @@ -0,0 +1,4399 @@ +/**************************************************************************** + * + * Copyright (C) 1996-2000 Microsoft Corporation. All Rights Reserved. + * + * File: dinput.h + * Content: DirectInput include file + * + ****************************************************************************/ + +#ifndef __DINPUT_INCLUDED__ +#define __DINPUT_INCLUDED__ + +#ifndef DIJ_RINGZERO + +#ifdef _WIN32 +#define COM_NO_WINDOWS_H +#include +#endif + +#endif /* DIJ_RINGZERO */ + +#ifdef __cplusplus +extern "C" { +#endif + + + + + +/* + * To build applications for older versions of DirectInput + * + * #define DIRECTINPUT_VERSION [ 0x0300 | 0x0500 | 0x0700 ] + * + * before #include . By default, #include + * will produce a DirectX 8-compatible header file. + * + */ + +#define DIRECTINPUT_HEADER_VERSION 0x0800 +#ifndef DIRECTINPUT_VERSION +#define DIRECTINPUT_VERSION DIRECTINPUT_HEADER_VERSION +#pragma message(__FILE__ ": DIRECTINPUT_VERSION undefined. Defaulting to version 0x0800") +#endif + +#ifndef DIJ_RINGZERO + +/**************************************************************************** + * + * Class IDs + * + ****************************************************************************/ + +DEFINE_GUID(CLSID_DirectInput, 0x25E609E0,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(CLSID_DirectInputDevice, 0x25E609E1,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +DEFINE_GUID(CLSID_DirectInput8, 0x25E609E4,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(CLSID_DirectInputDevice8,0x25E609E5,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/**************************************************************************** + * + * Interfaces + * + ****************************************************************************/ + +DEFINE_GUID(IID_IDirectInputA, 0x89521360,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputW, 0x89521361,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInput2A, 0x5944E662,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInput2W, 0x5944E663,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInput7A, 0x9A4CB684,0x236D,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInput7W, 0x9A4CB685,0x236D,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInput8A, 0xBF798030,0x483A,0x4DA2,0xAA,0x99,0x5D,0x64,0xED,0x36,0x97,0x00); +DEFINE_GUID(IID_IDirectInput8W, 0xBF798031,0x483A,0x4DA2,0xAA,0x99,0x5D,0x64,0xED,0x36,0x97,0x00); +DEFINE_GUID(IID_IDirectInputDeviceA, 0x5944E680,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDeviceW, 0x5944E681,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDevice2A,0x5944E682,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDevice2W,0x5944E683,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(IID_IDirectInputDevice7A,0x57D7C6BC,0x2356,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInputDevice7W,0x57D7C6BD,0x2356,0x11D3,0x8E,0x9D,0x00,0xC0,0x4F,0x68,0x44,0xAE); +DEFINE_GUID(IID_IDirectInputDevice8A,0x54D41080,0xDC15,0x4833,0xA4,0x1B,0x74,0x8F,0x73,0xA3,0x81,0x79); +DEFINE_GUID(IID_IDirectInputDevice8W,0x54D41081,0xDC15,0x4833,0xA4,0x1B,0x74,0x8F,0x73,0xA3,0x81,0x79); +DEFINE_GUID(IID_IDirectInputEffect, 0xE7E1F7C0,0x88D2,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); + +/**************************************************************************** + * + * Predefined object types + * + ****************************************************************************/ + +DEFINE_GUID(GUID_XAxis, 0xA36D02E0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_YAxis, 0xA36D02E1,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_ZAxis, 0xA36D02E2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_RxAxis, 0xA36D02F4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_RyAxis, 0xA36D02F5,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_RzAxis, 0xA36D02E3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Slider, 0xA36D02E4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +DEFINE_GUID(GUID_Button, 0xA36D02F0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Key, 0x55728220,0xD33C,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +DEFINE_GUID(GUID_POV, 0xA36D02F2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +DEFINE_GUID(GUID_Unknown, 0xA36D02F3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/**************************************************************************** + * + * Predefined product GUIDs + * + ****************************************************************************/ + +DEFINE_GUID(GUID_SysMouse, 0x6F1D2B60,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysKeyboard,0x6F1D2B61,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_Joystick ,0x6F1D2B70,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysMouseEm, 0x6F1D2B80,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysMouseEm2,0x6F1D2B81,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysKeyboardEm, 0x6F1D2B82,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); +DEFINE_GUID(GUID_SysKeyboardEm2,0x6F1D2B83,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00); + +/**************************************************************************** + * + * Predefined force feedback effects + * + ****************************************************************************/ + +DEFINE_GUID(GUID_ConstantForce, 0x13541C20,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_RampForce, 0x13541C21,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Square, 0x13541C22,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Sine, 0x13541C23,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Triangle, 0x13541C24,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_SawtoothUp, 0x13541C25,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_SawtoothDown, 0x13541C26,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Spring, 0x13541C27,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Damper, 0x13541C28,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Inertia, 0x13541C29,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_Friction, 0x13541C2A,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); +DEFINE_GUID(GUID_CustomForce, 0x13541C2B,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35); + +#endif /* DIJ_RINGZERO */ + +/**************************************************************************** + * + * Interfaces and Structures... + * + ****************************************************************************/ + +#if(DIRECTINPUT_VERSION >= 0x0500) + +/**************************************************************************** + * + * IDirectInputEffect + * + ****************************************************************************/ + +#define DIEFT_ALL 0x00000000 + +#define DIEFT_CONSTANTFORCE 0x00000001 +#define DIEFT_RAMPFORCE 0x00000002 +#define DIEFT_PERIODIC 0x00000003 +#define DIEFT_CONDITION 0x00000004 +#define DIEFT_CUSTOMFORCE 0x00000005 +#define DIEFT_HARDWARE 0x000000FF +#define DIEFT_FFATTACK 0x00000200 +#define DIEFT_FFFADE 0x00000400 +#define DIEFT_SATURATION 0x00000800 +#define DIEFT_POSNEGCOEFFICIENTS 0x00001000 +#define DIEFT_POSNEGSATURATION 0x00002000 +#define DIEFT_DEADBAND 0x00004000 +#define DIEFT_STARTDELAY 0x00008000 +#define DIEFT_GETTYPE(n) LOBYTE(n) + +#define DI_DEGREES 100 +#define DI_FFNOMINALMAX 10000 +#define DI_SECONDS 1000000 + +typedef struct DICONSTANTFORCE { + LONG lMagnitude; +} DICONSTANTFORCE, *LPDICONSTANTFORCE; +typedef const DICONSTANTFORCE *LPCDICONSTANTFORCE; + +typedef struct DIRAMPFORCE { + LONG lStart; + LONG lEnd; +} DIRAMPFORCE, *LPDIRAMPFORCE; +typedef const DIRAMPFORCE *LPCDIRAMPFORCE; + +typedef struct DIPERIODIC { + DWORD dwMagnitude; + LONG lOffset; + DWORD dwPhase; + DWORD dwPeriod; +} DIPERIODIC, *LPDIPERIODIC; +typedef const DIPERIODIC *LPCDIPERIODIC; + +typedef struct DICONDITION { + LONG lOffset; + LONG lPositiveCoefficient; + LONG lNegativeCoefficient; + DWORD dwPositiveSaturation; + DWORD dwNegativeSaturation; + LONG lDeadBand; +} DICONDITION, *LPDICONDITION; +typedef const DICONDITION *LPCDICONDITION; + +typedef struct DICUSTOMFORCE { + DWORD cChannels; + DWORD dwSamplePeriod; + DWORD cSamples; + LPLONG rglForceData; +} DICUSTOMFORCE, *LPDICUSTOMFORCE; +typedef const DICUSTOMFORCE *LPCDICUSTOMFORCE; + + +typedef struct DIENVELOPE { + DWORD dwSize; /* sizeof(DIENVELOPE) */ + DWORD dwAttackLevel; + DWORD dwAttackTime; /* Microseconds */ + DWORD dwFadeLevel; + DWORD dwFadeTime; /* Microseconds */ +} DIENVELOPE, *LPDIENVELOPE; +typedef const DIENVELOPE *LPCDIENVELOPE; + + +/* This structure is defined for DirectX 5.0 compatibility */ +typedef struct DIEFFECT_DX5 { + DWORD dwSize; /* sizeof(DIEFFECT_DX5) */ + DWORD dwFlags; /* DIEFF_* */ + DWORD dwDuration; /* Microseconds */ + DWORD dwSamplePeriod; /* Microseconds */ + DWORD dwGain; + DWORD dwTriggerButton; /* or DIEB_NOTRIGGER */ + DWORD dwTriggerRepeatInterval; /* Microseconds */ + DWORD cAxes; /* Number of axes */ + LPDWORD rgdwAxes; /* Array of axes */ + LPLONG rglDirection; /* Array of directions */ + LPDIENVELOPE lpEnvelope; /* Optional */ + DWORD cbTypeSpecificParams; /* Size of params */ + LPVOID lpvTypeSpecificParams; /* Pointer to params */ +} DIEFFECT_DX5, *LPDIEFFECT_DX5; +typedef const DIEFFECT_DX5 *LPCDIEFFECT_DX5; + +typedef struct DIEFFECT { + DWORD dwSize; /* sizeof(DIEFFECT) */ + DWORD dwFlags; /* DIEFF_* */ + DWORD dwDuration; /* Microseconds */ + DWORD dwSamplePeriod; /* Microseconds */ + DWORD dwGain; + DWORD dwTriggerButton; /* or DIEB_NOTRIGGER */ + DWORD dwTriggerRepeatInterval; /* Microseconds */ + DWORD cAxes; /* Number of axes */ + LPDWORD rgdwAxes; /* Array of axes */ + LPLONG rglDirection; /* Array of directions */ + LPDIENVELOPE lpEnvelope; /* Optional */ + DWORD cbTypeSpecificParams; /* Size of params */ + LPVOID lpvTypeSpecificParams; /* Pointer to params */ +#if(DIRECTINPUT_VERSION >= 0x0600) + DWORD dwStartDelay; /* Microseconds */ +#endif /* DIRECTINPUT_VERSION >= 0x0600 */ +} DIEFFECT, *LPDIEFFECT; +typedef DIEFFECT DIEFFECT_DX6; +typedef LPDIEFFECT LPDIEFFECT_DX6; +typedef const DIEFFECT *LPCDIEFFECT; + + +#if(DIRECTINPUT_VERSION >= 0x0700) +#ifndef DIJ_RINGZERO +typedef struct DIFILEEFFECT{ + DWORD dwSize; + GUID GuidEffect; + LPCDIEFFECT lpDiEffect; + CHAR szFriendlyName[MAX_PATH]; +}DIFILEEFFECT, *LPDIFILEEFFECT; +typedef const DIFILEEFFECT *LPCDIFILEEFFECT; +typedef BOOL (FAR PASCAL * LPDIENUMEFFECTSINFILECALLBACK)(LPCDIFILEEFFECT , LPVOID); +#endif /* DIJ_RINGZERO */ +#endif /* DIRECTINPUT_VERSION >= 0x0700 */ + +#define DIEFF_OBJECTIDS 0x00000001 +#define DIEFF_OBJECTOFFSETS 0x00000002 +#define DIEFF_CARTESIAN 0x00000010 +#define DIEFF_POLAR 0x00000020 +#define DIEFF_SPHERICAL 0x00000040 + +#define DIEP_DURATION 0x00000001 +#define DIEP_SAMPLEPERIOD 0x00000002 +#define DIEP_GAIN 0x00000004 +#define DIEP_TRIGGERBUTTON 0x00000008 +#define DIEP_TRIGGERREPEATINTERVAL 0x00000010 +#define DIEP_AXES 0x00000020 +#define DIEP_DIRECTION 0x00000040 +#define DIEP_ENVELOPE 0x00000080 +#define DIEP_TYPESPECIFICPARAMS 0x00000100 +#if(DIRECTINPUT_VERSION >= 0x0600) +#define DIEP_STARTDELAY 0x00000200 +#define DIEP_ALLPARAMS_DX5 0x000001FF +#define DIEP_ALLPARAMS 0x000003FF +#else /* DIRECTINPUT_VERSION < 0x0600 */ +#define DIEP_ALLPARAMS 0x000001FF +#endif /* DIRECTINPUT_VERSION < 0x0600 */ +#define DIEP_START 0x20000000 +#define DIEP_NORESTART 0x40000000 +#define DIEP_NODOWNLOAD 0x80000000 +#define DIEB_NOTRIGGER 0xFFFFFFFF + +#define DIES_SOLO 0x00000001 +#define DIES_NODOWNLOAD 0x80000000 + +#define DIEGES_PLAYING 0x00000001 +#define DIEGES_EMULATED 0x00000002 + +typedef struct DIEFFESCAPE { + DWORD dwSize; + DWORD dwCommand; + LPVOID lpvInBuffer; + DWORD cbInBuffer; + LPVOID lpvOutBuffer; + DWORD cbOutBuffer; +} DIEFFESCAPE, *LPDIEFFESCAPE; + +#ifndef DIJ_RINGZERO + +#undef INTERFACE +#define INTERFACE IDirectInputEffect + +DECLARE_INTERFACE_(IDirectInputEffect, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputEffect methods ***/ + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + STDMETHOD(GetEffectGuid)(THIS_ LPGUID) PURE; + STDMETHOD(GetParameters)(THIS_ LPDIEFFECT,DWORD) PURE; + STDMETHOD(SetParameters)(THIS_ LPCDIEFFECT,DWORD) PURE; + STDMETHOD(Start)(THIS_ DWORD,DWORD) PURE; + STDMETHOD(Stop)(THIS) PURE; + STDMETHOD(GetEffectStatus)(THIS_ LPDWORD) PURE; + STDMETHOD(Download)(THIS) PURE; + STDMETHOD(Unload)(THIS) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; +}; + +typedef struct IDirectInputEffect *LPDIRECTINPUTEFFECT; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInputEffect_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputEffect_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputEffect_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInputEffect_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#define IDirectInputEffect_GetEffectGuid(p,a) (p)->lpVtbl->GetEffectGuid(p,a) +#define IDirectInputEffect_GetParameters(p,a,b) (p)->lpVtbl->GetParameters(p,a,b) +#define IDirectInputEffect_SetParameters(p,a,b) (p)->lpVtbl->SetParameters(p,a,b) +#define IDirectInputEffect_Start(p,a,b) (p)->lpVtbl->Start(p,a,b) +#define IDirectInputEffect_Stop(p) (p)->lpVtbl->Stop(p) +#define IDirectInputEffect_GetEffectStatus(p,a) (p)->lpVtbl->GetEffectStatus(p,a) +#define IDirectInputEffect_Download(p) (p)->lpVtbl->Download(p) +#define IDirectInputEffect_Unload(p) (p)->lpVtbl->Unload(p) +#define IDirectInputEffect_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#else +#define IDirectInputEffect_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputEffect_AddRef(p) (p)->AddRef() +#define IDirectInputEffect_Release(p) (p)->Release() +#define IDirectInputEffect_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#define IDirectInputEffect_GetEffectGuid(p,a) (p)->GetEffectGuid(a) +#define IDirectInputEffect_GetParameters(p,a,b) (p)->GetParameters(a,b) +#define IDirectInputEffect_SetParameters(p,a,b) (p)->SetParameters(a,b) +#define IDirectInputEffect_Start(p,a,b) (p)->Start(a,b) +#define IDirectInputEffect_Stop(p) (p)->Stop() +#define IDirectInputEffect_GetEffectStatus(p,a) (p)->GetEffectStatus(a) +#define IDirectInputEffect_Download(p) (p)->Download() +#define IDirectInputEffect_Unload(p) (p)->Unload() +#define IDirectInputEffect_Escape(p,a) (p)->Escape(a) +#endif + +#endif /* DIJ_RINGZERO */ + +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +/**************************************************************************** + * + * IDirectInputDevice + * + ****************************************************************************/ + +#if DIRECTINPUT_VERSION <= 0x700 +#define DIDEVTYPE_DEVICE 1 +#define DIDEVTYPE_MOUSE 2 +#define DIDEVTYPE_KEYBOARD 3 +#define DIDEVTYPE_JOYSTICK 4 + +#else +#define DI8DEVCLASS_ALL 0 +#define DI8DEVCLASS_DEVICE 1 +#define DI8DEVCLASS_POINTER 2 +#define DI8DEVCLASS_KEYBOARD 3 +#define DI8DEVCLASS_GAMECTRL 4 + +#define DI8DEVTYPE_DEVICE 0x11 +#define DI8DEVTYPE_MOUSE 0x12 +#define DI8DEVTYPE_KEYBOARD 0x13 +#define DI8DEVTYPE_JOYSTICK 0x14 +#define DI8DEVTYPE_GAMEPAD 0x15 +#define DI8DEVTYPE_DRIVING 0x16 +#define DI8DEVTYPE_FLIGHT 0x17 +#define DI8DEVTYPE_1STPERSON 0x18 +#define DI8DEVTYPE_DEVICECTRL 0x19 +#define DI8DEVTYPE_SCREENPOINTER 0x1A +#define DI8DEVTYPE_REMOTE 0x1B +#define DI8DEVTYPE_SUPPLEMENTAL 0x1C +#endif /* DIRECTINPUT_VERSION <= 0x700 */ + +#define DIDEVTYPE_HID 0x00010000 + +#if DIRECTINPUT_VERSION <= 0x700 +#define DIDEVTYPEMOUSE_UNKNOWN 1 +#define DIDEVTYPEMOUSE_TRADITIONAL 2 +#define DIDEVTYPEMOUSE_FINGERSTICK 3 +#define DIDEVTYPEMOUSE_TOUCHPAD 4 +#define DIDEVTYPEMOUSE_TRACKBALL 5 + +#define DIDEVTYPEKEYBOARD_UNKNOWN 0 +#define DIDEVTYPEKEYBOARD_PCXT 1 +#define DIDEVTYPEKEYBOARD_OLIVETTI 2 +#define DIDEVTYPEKEYBOARD_PCAT 3 +#define DIDEVTYPEKEYBOARD_PCENH 4 +#define DIDEVTYPEKEYBOARD_NOKIA1050 5 +#define DIDEVTYPEKEYBOARD_NOKIA9140 6 +#define DIDEVTYPEKEYBOARD_NEC98 7 +#define DIDEVTYPEKEYBOARD_NEC98LAPTOP 8 +#define DIDEVTYPEKEYBOARD_NEC98106 9 +#define DIDEVTYPEKEYBOARD_JAPAN106 10 +#define DIDEVTYPEKEYBOARD_JAPANAX 11 +#define DIDEVTYPEKEYBOARD_J3100 12 + +#define DIDEVTYPEJOYSTICK_UNKNOWN 1 +#define DIDEVTYPEJOYSTICK_TRADITIONAL 2 +#define DIDEVTYPEJOYSTICK_FLIGHTSTICK 3 +#define DIDEVTYPEJOYSTICK_GAMEPAD 4 +#define DIDEVTYPEJOYSTICK_RUDDER 5 +#define DIDEVTYPEJOYSTICK_WHEEL 6 +#define DIDEVTYPEJOYSTICK_HEADTRACKER 7 + +#else +#define DI8DEVTYPEMOUSE_UNKNOWN 1 +#define DI8DEVTYPEMOUSE_TRADITIONAL 2 +#define DI8DEVTYPEMOUSE_FINGERSTICK 3 +#define DI8DEVTYPEMOUSE_TOUCHPAD 4 +#define DI8DEVTYPEMOUSE_TRACKBALL 5 +#define DI8DEVTYPEMOUSE_ABSOLUTE 6 + +#define DI8DEVTYPEKEYBOARD_UNKNOWN 0 +#define DI8DEVTYPEKEYBOARD_PCXT 1 +#define DI8DEVTYPEKEYBOARD_OLIVETTI 2 +#define DI8DEVTYPEKEYBOARD_PCAT 3 +#define DI8DEVTYPEKEYBOARD_PCENH 4 +#define DI8DEVTYPEKEYBOARD_NOKIA1050 5 +#define DI8DEVTYPEKEYBOARD_NOKIA9140 6 +#define DI8DEVTYPEKEYBOARD_NEC98 7 +#define DI8DEVTYPEKEYBOARD_NEC98LAPTOP 8 +#define DI8DEVTYPEKEYBOARD_NEC98106 9 +#define DI8DEVTYPEKEYBOARD_JAPAN106 10 +#define DI8DEVTYPEKEYBOARD_JAPANAX 11 +#define DI8DEVTYPEKEYBOARD_J3100 12 + +#define DI8DEVTYPE_LIMITEDGAMESUBTYPE 1 + +#define DI8DEVTYPEJOYSTICK_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEJOYSTICK_STANDARD 2 + +#define DI8DEVTYPEGAMEPAD_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEGAMEPAD_STANDARD 2 +#define DI8DEVTYPEGAMEPAD_TILT 3 + +#define DI8DEVTYPEDRIVING_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEDRIVING_COMBINEDPEDALS 2 +#define DI8DEVTYPEDRIVING_DUALPEDALS 3 +#define DI8DEVTYPEDRIVING_THREEPEDALS 4 +#define DI8DEVTYPEDRIVING_HANDHELD 5 + +#define DI8DEVTYPEFLIGHT_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPEFLIGHT_STICK 2 +#define DI8DEVTYPEFLIGHT_YOKE 3 +#define DI8DEVTYPEFLIGHT_RC 4 + +#define DI8DEVTYPE1STPERSON_LIMITED DI8DEVTYPE_LIMITEDGAMESUBTYPE +#define DI8DEVTYPE1STPERSON_UNKNOWN 2 +#define DI8DEVTYPE1STPERSON_SIXDOF 3 +#define DI8DEVTYPE1STPERSON_SHOOTER 4 + +#define DI8DEVTYPESCREENPTR_UNKNOWN 2 +#define DI8DEVTYPESCREENPTR_LIGHTGUN 3 +#define DI8DEVTYPESCREENPTR_LIGHTPEN 4 +#define DI8DEVTYPESCREENPTR_TOUCH 5 + +#define DI8DEVTYPEREMOTE_UNKNOWN 2 + +#define DI8DEVTYPEDEVICECTRL_UNKNOWN 2 +#define DI8DEVTYPEDEVICECTRL_COMMSSELECTION 3 +#define DI8DEVTYPEDEVICECTRL_COMMSSELECTION_HARDWIRED 4 + +#define DI8DEVTYPESUPPLEMENTAL_UNKNOWN 2 +#define DI8DEVTYPESUPPLEMENTAL_2NDHANDCONTROLLER 3 +#define DI8DEVTYPESUPPLEMENTAL_HEADTRACKER 4 +#define DI8DEVTYPESUPPLEMENTAL_HANDTRACKER 5 +#define DI8DEVTYPESUPPLEMENTAL_SHIFTSTICKGATE 6 +#define DI8DEVTYPESUPPLEMENTAL_SHIFTER 7 +#define DI8DEVTYPESUPPLEMENTAL_THROTTLE 8 +#define DI8DEVTYPESUPPLEMENTAL_SPLITTHROTTLE 9 +#define DI8DEVTYPESUPPLEMENTAL_COMBINEDPEDALS 10 +#define DI8DEVTYPESUPPLEMENTAL_DUALPEDALS 11 +#define DI8DEVTYPESUPPLEMENTAL_THREEPEDALS 12 +#define DI8DEVTYPESUPPLEMENTAL_RUDDERPEDALS 13 +#endif /* DIRECTINPUT_VERSION <= 0x700 */ + +#define GET_DIDEVICE_TYPE(dwDevType) LOBYTE(dwDevType) +#define GET_DIDEVICE_SUBTYPE(dwDevType) HIBYTE(dwDevType) + +#if(DIRECTINPUT_VERSION >= 0x0500) +/* This structure is defined for DirectX 3.0 compatibility */ +typedef struct DIDEVCAPS_DX3 { + DWORD dwSize; + DWORD dwFlags; + DWORD dwDevType; + DWORD dwAxes; + DWORD dwButtons; + DWORD dwPOVs; +} DIDEVCAPS_DX3, *LPDIDEVCAPS_DX3; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +typedef struct DIDEVCAPS { + DWORD dwSize; + DWORD dwFlags; + DWORD dwDevType; + DWORD dwAxes; + DWORD dwButtons; + DWORD dwPOVs; +#if(DIRECTINPUT_VERSION >= 0x0500) + DWORD dwFFSamplePeriod; + DWORD dwFFMinTimeResolution; + DWORD dwFirmwareRevision; + DWORD dwHardwareRevision; + DWORD dwFFDriverVersion; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVCAPS, *LPDIDEVCAPS; + +#define DIDC_ATTACHED 0x00000001 +#define DIDC_POLLEDDEVICE 0x00000002 +#define DIDC_EMULATED 0x00000004 +#define DIDC_POLLEDDATAFORMAT 0x00000008 +#if(DIRECTINPUT_VERSION >= 0x0500) +#define DIDC_FORCEFEEDBACK 0x00000100 +#define DIDC_FFATTACK 0x00000200 +#define DIDC_FFFADE 0x00000400 +#define DIDC_SATURATION 0x00000800 +#define DIDC_POSNEGCOEFFICIENTS 0x00001000 +#define DIDC_POSNEGSATURATION 0x00002000 +#define DIDC_DEADBAND 0x00004000 +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +#define DIDC_STARTDELAY 0x00008000 +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIDC_ALIAS 0x00010000 +#define DIDC_PHANTOM 0x00020000 +#endif /* DIRECTINPUT_VERSION >= 0x050a */ +#if(DIRECTINPUT_VERSION >= 0x0800) +#define DIDC_HIDDEN 0x00040000 +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +#define DIDFT_ALL 0x00000000 + +#define DIDFT_RELAXIS 0x00000001 +#define DIDFT_ABSAXIS 0x00000002 +#define DIDFT_AXIS 0x00000003 + +#define DIDFT_PSHBUTTON 0x00000004 +#define DIDFT_TGLBUTTON 0x00000008 +#define DIDFT_BUTTON 0x0000000C + +#define DIDFT_POV 0x00000010 +#define DIDFT_COLLECTION 0x00000040 +#define DIDFT_NODATA 0x00000080 + +#define DIDFT_ANYINSTANCE 0x00FFFF00 +#define DIDFT_INSTANCEMASK DIDFT_ANYINSTANCE +#define DIDFT_MAKEINSTANCE(n) ((WORD)(n) << 8) +#define DIDFT_GETTYPE(n) LOBYTE(n) +#define DIDFT_GETINSTANCE(n) LOWORD((n) >> 8) +#define DIDFT_FFACTUATOR 0x01000000 +#define DIDFT_FFEFFECTTRIGGER 0x02000000 +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIDFT_OUTPUT 0x10000000 +#define DIDFT_VENDORDEFINED 0x04000000 +#define DIDFT_ALIAS 0x08000000 +#endif /* DIRECTINPUT_VERSION >= 0x050a */ + +#define DIDFT_ENUMCOLLECTION(n) ((WORD)(n) << 8) +#define DIDFT_NOCOLLECTION 0x00FFFF00 + +#ifndef DIJ_RINGZERO + +typedef struct _DIOBJECTDATAFORMAT { + const GUID *pguid; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; +} DIOBJECTDATAFORMAT, *LPDIOBJECTDATAFORMAT; +typedef const DIOBJECTDATAFORMAT *LPCDIOBJECTDATAFORMAT; + +typedef struct _DIDATAFORMAT { + DWORD dwSize; + DWORD dwObjSize; + DWORD dwFlags; + DWORD dwDataSize; + DWORD dwNumObjs; + LPDIOBJECTDATAFORMAT rgodf; +} DIDATAFORMAT, *LPDIDATAFORMAT; +typedef const DIDATAFORMAT *LPCDIDATAFORMAT; + +#define DIDF_ABSAXIS 0x00000001 +#define DIDF_RELAXIS 0x00000002 + +#ifdef __cplusplus +extern "C" { +#endif +extern const DIDATAFORMAT c_dfDIMouse; + +#if(DIRECTINPUT_VERSION >= 0x0700) +extern const DIDATAFORMAT c_dfDIMouse2; +#endif /* DIRECTINPUT_VERSION >= 0x0700 */ + +extern const DIDATAFORMAT c_dfDIKeyboard; + +#if(DIRECTINPUT_VERSION >= 0x0500) +extern const DIDATAFORMAT c_dfDIJoystick; +extern const DIDATAFORMAT c_dfDIJoystick2; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +#ifdef __cplusplus +}; +#endif + + +#if DIRECTINPUT_VERSION > 0x0700 + +typedef struct _DIACTIONA { + UINT_PTR uAppData; + DWORD dwSemantic; + OPTIONAL DWORD dwFlags; + OPTIONAL union { + LPCSTR lptszActionName; + UINT uResIdString; + }; + OPTIONAL GUID guidInstance; + OPTIONAL DWORD dwObjID; + OPTIONAL DWORD dwHow; +} DIACTIONA, *LPDIACTIONA ; +typedef struct _DIACTIONW { + UINT_PTR uAppData; + DWORD dwSemantic; + OPTIONAL DWORD dwFlags; + OPTIONAL union { + LPCWSTR lptszActionName; + UINT uResIdString; + }; + OPTIONAL GUID guidInstance; + OPTIONAL DWORD dwObjID; + OPTIONAL DWORD dwHow; +} DIACTIONW, *LPDIACTIONW ; +#ifdef UNICODE +typedef DIACTIONW DIACTION; +typedef LPDIACTIONW LPDIACTION; +#else +typedef DIACTIONA DIACTION; +typedef LPDIACTIONA LPDIACTION; +#endif // UNICODE + +typedef const DIACTIONA *LPCDIACTIONA; +typedef const DIACTIONW *LPCDIACTIONW; +#ifdef UNICODE +typedef DIACTIONW DIACTION; +typedef LPCDIACTIONW LPCDIACTION; +#else +typedef DIACTIONA DIACTION; +typedef LPCDIACTIONA LPCDIACTION; +#endif // UNICODE +typedef const DIACTION *LPCDIACTION; + + +#define DIA_FORCEFEEDBACK 0x00000001 +#define DIA_APPMAPPED 0x00000002 +#define DIA_APPNOMAP 0x00000004 +#define DIA_NORANGE 0x00000008 +#define DIA_APPFIXED 0x00000010 + +#define DIAH_UNMAPPED 0x00000000 +#define DIAH_USERCONFIG 0x00000001 +#define DIAH_APPREQUESTED 0x00000002 +#define DIAH_HWAPP 0x00000004 +#define DIAH_HWDEFAULT 0x00000008 +#define DIAH_DEFAULT 0x00000020 +#define DIAH_ERROR 0x80000000 + +typedef struct _DIACTIONFORMATA { + DWORD dwSize; + DWORD dwActionSize; + DWORD dwDataSize; + DWORD dwNumActions; + LPDIACTIONA rgoAction; + GUID guidActionMap; + DWORD dwGenre; + DWORD dwBufferSize; + OPTIONAL LONG lAxisMin; + OPTIONAL LONG lAxisMax; + OPTIONAL HINSTANCE hInstString; + FILETIME ftTimeStamp; + DWORD dwCRC; + CHAR tszActionMap[MAX_PATH]; +} DIACTIONFORMATA, *LPDIACTIONFORMATA; +typedef struct _DIACTIONFORMATW { + DWORD dwSize; + DWORD dwActionSize; + DWORD dwDataSize; + DWORD dwNumActions; + LPDIACTIONW rgoAction; + GUID guidActionMap; + DWORD dwGenre; + DWORD dwBufferSize; + OPTIONAL LONG lAxisMin; + OPTIONAL LONG lAxisMax; + OPTIONAL HINSTANCE hInstString; + FILETIME ftTimeStamp; + DWORD dwCRC; + WCHAR tszActionMap[MAX_PATH]; +} DIACTIONFORMATW, *LPDIACTIONFORMATW; +#ifdef UNICODE +typedef DIACTIONFORMATW DIACTIONFORMAT; +typedef LPDIACTIONFORMATW LPDIACTIONFORMAT; +#else +typedef DIACTIONFORMATA DIACTIONFORMAT; +typedef LPDIACTIONFORMATA LPDIACTIONFORMAT; +#endif // UNICODE +typedef const DIACTIONFORMATA *LPCDIACTIONFORMATA; +typedef const DIACTIONFORMATW *LPCDIACTIONFORMATW; +#ifdef UNICODE +typedef DIACTIONFORMATW DIACTIONFORMAT; +typedef LPCDIACTIONFORMATW LPCDIACTIONFORMAT; +#else +typedef DIACTIONFORMATA DIACTIONFORMAT; +typedef LPCDIACTIONFORMATA LPCDIACTIONFORMAT; +#endif // UNICODE +typedef const DIACTIONFORMAT *LPCDIACTIONFORMAT; + +#define DIAFTS_NEWDEVICELOW 0xFFFFFFFF +#define DIAFTS_NEWDEVICEHIGH 0xFFFFFFFF +#define DIAFTS_UNUSEDDEVICELOW 0x00000000 +#define DIAFTS_UNUSEDDEVICEHIGH 0x00000000 + +#define DIDBAM_DEFAULT 0x00000000 +#define DIDBAM_PRESERVE 0x00000001 +#define DIDBAM_INITIALIZE 0x00000002 +#define DIDBAM_HWDEFAULTS 0x00000004 + +#define DIDSAM_DEFAULT 0x00000000 +#define DIDSAM_NOUSER 0x00000001 +#define DIDSAM_FORCESAVE 0x00000002 + +#define DICD_DEFAULT 0x00000000 +#define DICD_EDIT 0x00000001 + +/* + * The following definition is normally defined in d3dtypes.h + */ +#ifndef D3DCOLOR_DEFINED +typedef DWORD D3DCOLOR; +#define D3DCOLOR_DEFINED +#endif + +typedef struct _DICOLORSET{ + DWORD dwSize; + D3DCOLOR cTextFore; + D3DCOLOR cTextHighlight; + D3DCOLOR cCalloutLine; + D3DCOLOR cCalloutHighlight; + D3DCOLOR cBorder; + D3DCOLOR cControlFill; + D3DCOLOR cHighlightFill; + D3DCOLOR cAreaFill; +} DICOLORSET, *LPDICOLORSET; +typedef const DICOLORSET *LPCDICOLORSET; + + +typedef struct _DICONFIGUREDEVICESPARAMSA{ + DWORD dwSize; + DWORD dwcUsers; + LPSTR lptszUserNames; + DWORD dwcFormats; + LPDIACTIONFORMATA lprgFormats; + HWND hwnd; + DICOLORSET dics; + IUnknown FAR * lpUnkDDSTarget; +} DICONFIGUREDEVICESPARAMSA, *LPDICONFIGUREDEVICESPARAMSA; +typedef struct _DICONFIGUREDEVICESPARAMSW{ + DWORD dwSize; + DWORD dwcUsers; + LPWSTR lptszUserNames; + DWORD dwcFormats; + LPDIACTIONFORMATW lprgFormats; + HWND hwnd; + DICOLORSET dics; + IUnknown FAR * lpUnkDDSTarget; +} DICONFIGUREDEVICESPARAMSW, *LPDICONFIGUREDEVICESPARAMSW; +#ifdef UNICODE +typedef DICONFIGUREDEVICESPARAMSW DICONFIGUREDEVICESPARAMS; +typedef LPDICONFIGUREDEVICESPARAMSW LPDICONFIGUREDEVICESPARAMS; +#else +typedef DICONFIGUREDEVICESPARAMSA DICONFIGUREDEVICESPARAMS; +typedef LPDICONFIGUREDEVICESPARAMSA LPDICONFIGUREDEVICESPARAMS; +#endif // UNICODE +typedef const DICONFIGUREDEVICESPARAMSA *LPCDICONFIGUREDEVICESPARAMSA; +typedef const DICONFIGUREDEVICESPARAMSW *LPCDICONFIGUREDEVICESPARAMSW; +#ifdef UNICODE +typedef DICONFIGUREDEVICESPARAMSW DICONFIGUREDEVICESPARAMS; +typedef LPCDICONFIGUREDEVICESPARAMSW LPCDICONFIGUREDEVICESPARAMS; +#else +typedef DICONFIGUREDEVICESPARAMSA DICONFIGUREDEVICESPARAMS; +typedef LPCDICONFIGUREDEVICESPARAMSA LPCDICONFIGUREDEVICESPARAMS; +#endif // UNICODE +typedef const DICONFIGUREDEVICESPARAMS *LPCDICONFIGUREDEVICESPARAMS; + + +#define DIDIFT_CONFIGURATION 0x00000001 +#define DIDIFT_OVERLAY 0x00000002 + +#define DIDAL_CENTERED 0x00000000 +#define DIDAL_LEFTALIGNED 0x00000001 +#define DIDAL_RIGHTALIGNED 0x00000002 +#define DIDAL_MIDDLE 0x00000000 +#define DIDAL_TOPALIGNED 0x00000004 +#define DIDAL_BOTTOMALIGNED 0x00000008 + +typedef struct _DIDEVICEIMAGEINFOA { + CHAR tszImagePath[MAX_PATH]; + DWORD dwFlags; + // These are valid if DIDIFT_OVERLAY is present in dwFlags. + DWORD dwViewID; + RECT rcOverlay; + DWORD dwObjID; + DWORD dwcValidPts; + POINT rgptCalloutLine[5]; + RECT rcCalloutRect; + DWORD dwTextAlign; +} DIDEVICEIMAGEINFOA, *LPDIDEVICEIMAGEINFOA; +typedef struct _DIDEVICEIMAGEINFOW { + WCHAR tszImagePath[MAX_PATH]; + DWORD dwFlags; + // These are valid if DIDIFT_OVERLAY is present in dwFlags. + DWORD dwViewID; + RECT rcOverlay; + DWORD dwObjID; + DWORD dwcValidPts; + POINT rgptCalloutLine[5]; + RECT rcCalloutRect; + DWORD dwTextAlign; +} DIDEVICEIMAGEINFOW, *LPDIDEVICEIMAGEINFOW; +#ifdef UNICODE +typedef DIDEVICEIMAGEINFOW DIDEVICEIMAGEINFO; +typedef LPDIDEVICEIMAGEINFOW LPDIDEVICEIMAGEINFO; +#else +typedef DIDEVICEIMAGEINFOA DIDEVICEIMAGEINFO; +typedef LPDIDEVICEIMAGEINFOA LPDIDEVICEIMAGEINFO; +#endif // UNICODE +typedef const DIDEVICEIMAGEINFOA *LPCDIDEVICEIMAGEINFOA; +typedef const DIDEVICEIMAGEINFOW *LPCDIDEVICEIMAGEINFOW; +#ifdef UNICODE +typedef DIDEVICEIMAGEINFOW DIDEVICEIMAGEINFO; +typedef LPCDIDEVICEIMAGEINFOW LPCDIDEVICEIMAGEINFO; +#else +typedef DIDEVICEIMAGEINFOA DIDEVICEIMAGEINFO; +typedef LPCDIDEVICEIMAGEINFOA LPCDIDEVICEIMAGEINFO; +#endif // UNICODE +typedef const DIDEVICEIMAGEINFO *LPCDIDEVICEIMAGEINFO; + +typedef struct _DIDEVICEIMAGEINFOHEADERA { + DWORD dwSize; + DWORD dwSizeImageInfo; + DWORD dwcViews; + DWORD dwcButtons; + DWORD dwcAxes; + DWORD dwcPOVs; + DWORD dwBufferSize; + DWORD dwBufferUsed; + LPDIDEVICEIMAGEINFOA lprgImageInfoArray; +} DIDEVICEIMAGEINFOHEADERA, *LPDIDEVICEIMAGEINFOHEADERA; +typedef struct _DIDEVICEIMAGEINFOHEADERW { + DWORD dwSize; + DWORD dwSizeImageInfo; + DWORD dwcViews; + DWORD dwcButtons; + DWORD dwcAxes; + DWORD dwcPOVs; + DWORD dwBufferSize; + DWORD dwBufferUsed; + LPDIDEVICEIMAGEINFOW lprgImageInfoArray; +} DIDEVICEIMAGEINFOHEADERW, *LPDIDEVICEIMAGEINFOHEADERW; +#ifdef UNICODE +typedef DIDEVICEIMAGEINFOHEADERW DIDEVICEIMAGEINFOHEADER; +typedef LPDIDEVICEIMAGEINFOHEADERW LPDIDEVICEIMAGEINFOHEADER; +#else +typedef DIDEVICEIMAGEINFOHEADERA DIDEVICEIMAGEINFOHEADER; +typedef LPDIDEVICEIMAGEINFOHEADERA LPDIDEVICEIMAGEINFOHEADER; +#endif // UNICODE +typedef const DIDEVICEIMAGEINFOHEADERA *LPCDIDEVICEIMAGEINFOHEADERA; +typedef const DIDEVICEIMAGEINFOHEADERW *LPCDIDEVICEIMAGEINFOHEADERW; +#ifdef UNICODE +typedef DIDEVICEIMAGEINFOHEADERW DIDEVICEIMAGEINFOHEADER; +typedef LPCDIDEVICEIMAGEINFOHEADERW LPCDIDEVICEIMAGEINFOHEADER; +#else +typedef DIDEVICEIMAGEINFOHEADERA DIDEVICEIMAGEINFOHEADER; +typedef LPCDIDEVICEIMAGEINFOHEADERA LPCDIDEVICEIMAGEINFOHEADER; +#endif // UNICODE +typedef const DIDEVICEIMAGEINFOHEADER *LPCDIDEVICEIMAGEINFOHEADER; + +#endif /* DIRECTINPUT_VERSION > 0x0700 */ + +#if(DIRECTINPUT_VERSION >= 0x0500) +/* These structures are defined for DirectX 3.0 compatibility */ + +typedef struct DIDEVICEOBJECTINSTANCE_DX3A { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + CHAR tszName[MAX_PATH]; +} DIDEVICEOBJECTINSTANCE_DX3A, *LPDIDEVICEOBJECTINSTANCE_DX3A; +typedef struct DIDEVICEOBJECTINSTANCE_DX3W { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + WCHAR tszName[MAX_PATH]; +} DIDEVICEOBJECTINSTANCE_DX3W, *LPDIDEVICEOBJECTINSTANCE_DX3W; +#ifdef UNICODE +typedef DIDEVICEOBJECTINSTANCE_DX3W DIDEVICEOBJECTINSTANCE_DX3; +typedef LPDIDEVICEOBJECTINSTANCE_DX3W LPDIDEVICEOBJECTINSTANCE_DX3; +#else +typedef DIDEVICEOBJECTINSTANCE_DX3A DIDEVICEOBJECTINSTANCE_DX3; +typedef LPDIDEVICEOBJECTINSTANCE_DX3A LPDIDEVICEOBJECTINSTANCE_DX3; +#endif // UNICODE +typedef const DIDEVICEOBJECTINSTANCE_DX3A *LPCDIDEVICEOBJECTINSTANCE_DX3A; +typedef const DIDEVICEOBJECTINSTANCE_DX3W *LPCDIDEVICEOBJECTINSTANCE_DX3W; +typedef const DIDEVICEOBJECTINSTANCE_DX3 *LPCDIDEVICEOBJECTINSTANCE_DX3; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +typedef struct DIDEVICEOBJECTINSTANCEA { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + CHAR tszName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + DWORD dwFFMaxForce; + DWORD dwFFForceResolution; + WORD wCollectionNumber; + WORD wDesignatorIndex; + WORD wUsagePage; + WORD wUsage; + DWORD dwDimension; + WORD wExponent; + WORD wReportId; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEOBJECTINSTANCEA, *LPDIDEVICEOBJECTINSTANCEA; +typedef struct DIDEVICEOBJECTINSTANCEW { + DWORD dwSize; + GUID guidType; + DWORD dwOfs; + DWORD dwType; + DWORD dwFlags; + WCHAR tszName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + DWORD dwFFMaxForce; + DWORD dwFFForceResolution; + WORD wCollectionNumber; + WORD wDesignatorIndex; + WORD wUsagePage; + WORD wUsage; + DWORD dwDimension; + WORD wExponent; + WORD wReportId; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEOBJECTINSTANCEW, *LPDIDEVICEOBJECTINSTANCEW; +#ifdef UNICODE +typedef DIDEVICEOBJECTINSTANCEW DIDEVICEOBJECTINSTANCE; +typedef LPDIDEVICEOBJECTINSTANCEW LPDIDEVICEOBJECTINSTANCE; +#else +typedef DIDEVICEOBJECTINSTANCEA DIDEVICEOBJECTINSTANCE; +typedef LPDIDEVICEOBJECTINSTANCEA LPDIDEVICEOBJECTINSTANCE; +#endif // UNICODE +typedef const DIDEVICEOBJECTINSTANCEA *LPCDIDEVICEOBJECTINSTANCEA; +typedef const DIDEVICEOBJECTINSTANCEW *LPCDIDEVICEOBJECTINSTANCEW; +typedef const DIDEVICEOBJECTINSTANCE *LPCDIDEVICEOBJECTINSTANCE; + +typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKA)(LPCDIDEVICEOBJECTINSTANCEA, LPVOID); +typedef BOOL (FAR PASCAL * LPDIENUMDEVICEOBJECTSCALLBACKW)(LPCDIDEVICEOBJECTINSTANCEW, LPVOID); +#ifdef UNICODE +#define LPDIENUMDEVICEOBJECTSCALLBACK LPDIENUMDEVICEOBJECTSCALLBACKW +#else +#define LPDIENUMDEVICEOBJECTSCALLBACK LPDIENUMDEVICEOBJECTSCALLBACKA +#endif // !UNICODE + +#if(DIRECTINPUT_VERSION >= 0x0500) +#define DIDOI_FFACTUATOR 0x00000001 +#define DIDOI_FFEFFECTTRIGGER 0x00000002 +#define DIDOI_POLLED 0x00008000 +#define DIDOI_ASPECTPOSITION 0x00000100 +#define DIDOI_ASPECTVELOCITY 0x00000200 +#define DIDOI_ASPECTACCEL 0x00000300 +#define DIDOI_ASPECTFORCE 0x00000400 +#define DIDOI_ASPECTMASK 0x00000F00 +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIDOI_GUIDISUSAGE 0x00010000 +#endif /* DIRECTINPUT_VERSION >= 0x050a */ + +typedef struct DIPROPHEADER { + DWORD dwSize; + DWORD dwHeaderSize; + DWORD dwObj; + DWORD dwHow; +} DIPROPHEADER, *LPDIPROPHEADER; +typedef const DIPROPHEADER *LPCDIPROPHEADER; + +#define DIPH_DEVICE 0 +#define DIPH_BYOFFSET 1 +#define DIPH_BYID 2 +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIPH_BYUSAGE 3 +#endif /* DIRECTINPUT_VERSION >= 0x050a */ + +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIMAKEUSAGEDWORD(UsagePage, Usage) \ + (DWORD)MAKELONG(Usage, UsagePage) +#endif /* DIRECTINPUT_VERSION >= 0x050a */ + +typedef struct DIPROPDWORD { + DIPROPHEADER diph; + DWORD dwData; +} DIPROPDWORD, *LPDIPROPDWORD; +typedef const DIPROPDWORD *LPCDIPROPDWORD; + +#if(DIRECTINPUT_VERSION >= 0x0800) +typedef struct DIPROPPOINTER { + DIPROPHEADER diph; + UINT_PTR uData; +} DIPROPPOINTER, *LPDIPROPPOINTER; +typedef const DIPROPPOINTER *LPCDIPROPPOINTER; +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +typedef struct DIPROPRANGE { + DIPROPHEADER diph; + LONG lMin; + LONG lMax; +} DIPROPRANGE, *LPDIPROPRANGE; +typedef const DIPROPRANGE *LPCDIPROPRANGE; + +#define DIPROPRANGE_NOMIN ((LONG)0x80000000) +#define DIPROPRANGE_NOMAX ((LONG)0x7FFFFFFF) + +#if(DIRECTINPUT_VERSION >= 0x050a) +typedef struct DIPROPCAL { + DIPROPHEADER diph; + LONG lMin; + LONG lCenter; + LONG lMax; +} DIPROPCAL, *LPDIPROPCAL; +typedef const DIPROPCAL *LPCDIPROPCAL; + +typedef struct DIPROPCALPOV { + DIPROPHEADER diph; + LONG lMin[5]; + LONG lMax[5]; +} DIPROPCALPOV, *LPDIPROPCALPOV; +typedef const DIPROPCALPOV *LPCDIPROPCALPOV; + +typedef struct DIPROPGUIDANDPATH { + DIPROPHEADER diph; + GUID guidClass; + WCHAR wszPath[MAX_PATH]; +} DIPROPGUIDANDPATH, *LPDIPROPGUIDANDPATH; +typedef const DIPROPGUIDANDPATH *LPCDIPROPGUIDANDPATH; + +typedef struct DIPROPSTRING { + DIPROPHEADER diph; + WCHAR wsz[MAX_PATH]; +} DIPROPSTRING, *LPDIPROPSTRING; +typedef const DIPROPSTRING *LPCDIPROPSTRING; + +#endif /* DIRECTINPUT_VERSION >= 0x050a */ + +#if(DIRECTINPUT_VERSION >= 0x0800) +#define MAXCPOINTSNUM 8 + +typedef struct _CPOINT +{ + LONG lP; // raw value + DWORD dwLog; // logical_value / max_logical_value * 10000 +} CPOINT, *PCPOINT; + +typedef struct DIPROPCPOINTS { + DIPROPHEADER diph; + DWORD dwCPointsNum; + CPOINT cp[MAXCPOINTSNUM]; +} DIPROPCPOINTS, *LPDIPROPCPOINTS; +typedef const DIPROPCPOINTS *LPCDIPROPCPOINTS; +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + + +#ifdef __cplusplus +#define MAKEDIPROP(prop) (*(const GUID *)(prop)) +#else +#define MAKEDIPROP(prop) ((REFGUID)(prop)) +#endif + +#define DIPROP_BUFFERSIZE MAKEDIPROP(1) + +#define DIPROP_AXISMODE MAKEDIPROP(2) + +#define DIPROPAXISMODE_ABS 0 +#define DIPROPAXISMODE_REL 1 + +#define DIPROP_GRANULARITY MAKEDIPROP(3) + +#define DIPROP_RANGE MAKEDIPROP(4) + +#define DIPROP_DEADZONE MAKEDIPROP(5) + +#define DIPROP_SATURATION MAKEDIPROP(6) + +#define DIPROP_FFGAIN MAKEDIPROP(7) + +#define DIPROP_FFLOAD MAKEDIPROP(8) + +#define DIPROP_AUTOCENTER MAKEDIPROP(9) + +#define DIPROPAUTOCENTER_OFF 0 +#define DIPROPAUTOCENTER_ON 1 + +#define DIPROP_CALIBRATIONMODE MAKEDIPROP(10) + +#define DIPROPCALIBRATIONMODE_COOKED 0 +#define DIPROPCALIBRATIONMODE_RAW 1 + +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIPROP_CALIBRATION MAKEDIPROP(11) + +#define DIPROP_GUIDANDPATH MAKEDIPROP(12) + +#define DIPROP_INSTANCENAME MAKEDIPROP(13) + +#define DIPROP_PRODUCTNAME MAKEDIPROP(14) +#endif /* DIRECTINPUT_VERSION >= 0x050a */ + +#if(DIRECTINPUT_VERSION >= 0x05b2) +#define DIPROP_JOYSTICKID MAKEDIPROP(15) + +#define DIPROP_GETPORTDISPLAYNAME MAKEDIPROP(16) + +#endif /* DIRECTINPUT_VERSION >= 0x05b2 */ + +#if(DIRECTINPUT_VERSION >= 0x0700) +#define DIPROP_PHYSICALRANGE MAKEDIPROP(18) + +#define DIPROP_LOGICALRANGE MAKEDIPROP(19) +#endif /* DIRECTINPUT_VERSION >= 0x0700 */ + +#if(DIRECTINPUT_VERSION >= 0x0800) +#define DIPROP_KEYNAME MAKEDIPROP(20) + +#define DIPROP_CPOINTS MAKEDIPROP(21) + +#define DIPROP_APPDATA MAKEDIPROP(22) + +#define DIPROP_SCANCODE MAKEDIPROP(23) + +#define DIPROP_VIDPID MAKEDIPROP(24) + +#define DIPROP_USERNAME MAKEDIPROP(25) + +#define DIPROP_TYPENAME MAKEDIPROP(26) +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + + +typedef struct DIDEVICEOBJECTDATA_DX3 { + DWORD dwOfs; + DWORD dwData; + DWORD dwTimeStamp; + DWORD dwSequence; +} DIDEVICEOBJECTDATA_DX3, *LPDIDEVICEOBJECTDATA_DX3; +typedef const DIDEVICEOBJECTDATA_DX3 *LPCDIDEVICEOBJECTDATA_DX; + +typedef struct DIDEVICEOBJECTDATA { + DWORD dwOfs; + DWORD dwData; + DWORD dwTimeStamp; + DWORD dwSequence; +#if(DIRECTINPUT_VERSION >= 0x0800) + UINT_PTR uAppData; +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ +} DIDEVICEOBJECTDATA, *LPDIDEVICEOBJECTDATA; +typedef const DIDEVICEOBJECTDATA *LPCDIDEVICEOBJECTDATA; + +#define DIGDD_PEEK 0x00000001 + +#define DISEQUENCE_COMPARE(dwSequence1, cmp, dwSequence2) \ + ((int)((dwSequence1) - (dwSequence2)) cmp 0) +#define DISCL_EXCLUSIVE 0x00000001 +#define DISCL_NONEXCLUSIVE 0x00000002 +#define DISCL_FOREGROUND 0x00000004 +#define DISCL_BACKGROUND 0x00000008 +#define DISCL_NOWINKEY 0x00000010 + +#if(DIRECTINPUT_VERSION >= 0x0500) +/* These structures are defined for DirectX 3.0 compatibility */ + +typedef struct DIDEVICEINSTANCE_DX3A { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + CHAR tszInstanceName[MAX_PATH]; + CHAR tszProductName[MAX_PATH]; +} DIDEVICEINSTANCE_DX3A, *LPDIDEVICEINSTANCE_DX3A; +typedef struct DIDEVICEINSTANCE_DX3W { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + WCHAR tszInstanceName[MAX_PATH]; + WCHAR tszProductName[MAX_PATH]; +} DIDEVICEINSTANCE_DX3W, *LPDIDEVICEINSTANCE_DX3W; +#ifdef UNICODE +typedef DIDEVICEINSTANCE_DX3W DIDEVICEINSTANCE_DX3; +typedef LPDIDEVICEINSTANCE_DX3W LPDIDEVICEINSTANCE_DX3; +#else +typedef DIDEVICEINSTANCE_DX3A DIDEVICEINSTANCE_DX3; +typedef LPDIDEVICEINSTANCE_DX3A LPDIDEVICEINSTANCE_DX3; +#endif // UNICODE +typedef const DIDEVICEINSTANCE_DX3A *LPCDIDEVICEINSTANCE_DX3A; +typedef const DIDEVICEINSTANCE_DX3W *LPCDIDEVICEINSTANCE_DX3W; +typedef const DIDEVICEINSTANCE_DX3 *LPCDIDEVICEINSTANCE_DX3; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +typedef struct DIDEVICEINSTANCEA { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + CHAR tszInstanceName[MAX_PATH]; + CHAR tszProductName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + GUID guidFFDriver; + WORD wUsagePage; + WORD wUsage; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEINSTANCEA, *LPDIDEVICEINSTANCEA; +typedef struct DIDEVICEINSTANCEW { + DWORD dwSize; + GUID guidInstance; + GUID guidProduct; + DWORD dwDevType; + WCHAR tszInstanceName[MAX_PATH]; + WCHAR tszProductName[MAX_PATH]; +#if(DIRECTINPUT_VERSION >= 0x0500) + GUID guidFFDriver; + WORD wUsagePage; + WORD wUsage; +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +} DIDEVICEINSTANCEW, *LPDIDEVICEINSTANCEW; +#ifdef UNICODE +typedef DIDEVICEINSTANCEW DIDEVICEINSTANCE; +typedef LPDIDEVICEINSTANCEW LPDIDEVICEINSTANCE; +#else +typedef DIDEVICEINSTANCEA DIDEVICEINSTANCE; +typedef LPDIDEVICEINSTANCEA LPDIDEVICEINSTANCE; +#endif // UNICODE + +typedef const DIDEVICEINSTANCEA *LPCDIDEVICEINSTANCEA; +typedef const DIDEVICEINSTANCEW *LPCDIDEVICEINSTANCEW; +#ifdef UNICODE +typedef DIDEVICEINSTANCEW DIDEVICEINSTANCE; +typedef LPCDIDEVICEINSTANCEW LPCDIDEVICEINSTANCE; +#else +typedef DIDEVICEINSTANCEA DIDEVICEINSTANCE; +typedef LPCDIDEVICEINSTANCEA LPCDIDEVICEINSTANCE; +#endif // UNICODE +typedef const DIDEVICEINSTANCE *LPCDIDEVICEINSTANCE; + +#undef INTERFACE +#define INTERFACE IDirectInputDeviceW + +DECLARE_INTERFACE_(IDirectInputDeviceW, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDeviceW methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; +}; + +typedef struct IDirectInputDeviceW *LPDIRECTINPUTDEVICEW; + +#undef INTERFACE +#define INTERFACE IDirectInputDeviceA + +DECLARE_INTERFACE_(IDirectInputDeviceA, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDeviceA methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; +}; + +typedef struct IDirectInputDeviceA *LPDIRECTINPUTDEVICEA; + +#ifdef UNICODE +#define IID_IDirectInputDevice IID_IDirectInputDeviceW +#define IDirectInputDevice IDirectInputDeviceW +#define IDirectInputDeviceVtbl IDirectInputDeviceWVtbl +#else +#define IID_IDirectInputDevice IID_IDirectInputDeviceA +#define IDirectInputDevice IDirectInputDeviceA +#define IDirectInputDeviceVtbl IDirectInputDeviceAVtbl +#endif +typedef struct IDirectInputDevice *LPDIRECTINPUTDEVICE; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInputDevice_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInputDevice_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#else +#define IDirectInputDevice_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice_AddRef(p) (p)->AddRef() +#define IDirectInputDevice_Release(p) (p)->Release() +#define IDirectInputDevice_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice_Acquire(p) (p)->Acquire() +#define IDirectInputDevice_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#endif + +#endif /* DIJ_RINGZERO */ + + +#if(DIRECTINPUT_VERSION >= 0x0500) + +#define DISFFC_RESET 0x00000001 +#define DISFFC_STOPALL 0x00000002 +#define DISFFC_PAUSE 0x00000004 +#define DISFFC_CONTINUE 0x00000008 +#define DISFFC_SETACTUATORSON 0x00000010 +#define DISFFC_SETACTUATORSOFF 0x00000020 + +#define DIGFFS_EMPTY 0x00000001 +#define DIGFFS_STOPPED 0x00000002 +#define DIGFFS_PAUSED 0x00000004 +#define DIGFFS_ACTUATORSON 0x00000010 +#define DIGFFS_ACTUATORSOFF 0x00000020 +#define DIGFFS_POWERON 0x00000040 +#define DIGFFS_POWEROFF 0x00000080 +#define DIGFFS_SAFETYSWITCHON 0x00000100 +#define DIGFFS_SAFETYSWITCHOFF 0x00000200 +#define DIGFFS_USERFFSWITCHON 0x00000400 +#define DIGFFS_USERFFSWITCHOFF 0x00000800 +#define DIGFFS_DEVICELOST 0x80000000 + +#ifndef DIJ_RINGZERO + +typedef struct DIEFFECTINFOA { + DWORD dwSize; + GUID guid; + DWORD dwEffType; + DWORD dwStaticParams; + DWORD dwDynamicParams; + CHAR tszName[MAX_PATH]; +} DIEFFECTINFOA, *LPDIEFFECTINFOA; +typedef struct DIEFFECTINFOW { + DWORD dwSize; + GUID guid; + DWORD dwEffType; + DWORD dwStaticParams; + DWORD dwDynamicParams; + WCHAR tszName[MAX_PATH]; +} DIEFFECTINFOW, *LPDIEFFECTINFOW; +#ifdef UNICODE +typedef DIEFFECTINFOW DIEFFECTINFO; +typedef LPDIEFFECTINFOW LPDIEFFECTINFO; +#else +typedef DIEFFECTINFOA DIEFFECTINFO; +typedef LPDIEFFECTINFOA LPDIEFFECTINFO; +#endif // UNICODE +typedef const DIEFFECTINFOA *LPCDIEFFECTINFOA; +typedef const DIEFFECTINFOW *LPCDIEFFECTINFOW; +typedef const DIEFFECTINFO *LPCDIEFFECTINFO; + +#define DISDD_CONTINUE 0x00000001 + +typedef BOOL (FAR PASCAL * LPDIENUMEFFECTSCALLBACKA)(LPCDIEFFECTINFOA, LPVOID); +typedef BOOL (FAR PASCAL * LPDIENUMEFFECTSCALLBACKW)(LPCDIEFFECTINFOW, LPVOID); +#ifdef UNICODE +#define LPDIENUMEFFECTSCALLBACK LPDIENUMEFFECTSCALLBACKW +#else +#define LPDIENUMEFFECTSCALLBACK LPDIENUMEFFECTSCALLBACKA +#endif // !UNICODE +typedef BOOL (FAR PASCAL * LPDIENUMCREATEDEFFECTOBJECTSCALLBACK)(LPDIRECTINPUTEFFECT, LPVOID); + +#undef INTERFACE +#define INTERFACE IDirectInputDevice2W + +DECLARE_INTERFACE_(IDirectInputDevice2W, IDirectInputDeviceW) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDeviceW methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + + /*** IDirectInputDevice2W methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW,REFGUID) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; +}; + +typedef struct IDirectInputDevice2W *LPDIRECTINPUTDEVICE2W; + +#undef INTERFACE +#define INTERFACE IDirectInputDevice2A + +DECLARE_INTERFACE_(IDirectInputDevice2A, IDirectInputDeviceA) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDeviceA methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + + /*** IDirectInputDevice2A methods ***/ + STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA,REFGUID) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; +}; + +typedef struct IDirectInputDevice2A *LPDIRECTINPUTDEVICE2A; + +#ifdef UNICODE +#define IID_IDirectInputDevice2 IID_IDirectInputDevice2W +#define IDirectInputDevice2 IDirectInputDevice2W +#define IDirectInputDevice2Vtbl IDirectInputDevice2WVtbl +#else +#define IID_IDirectInputDevice2 IID_IDirectInputDevice2A +#define IDirectInputDevice2 IDirectInputDevice2A +#define IDirectInputDevice2Vtbl IDirectInputDevice2AVtbl +#endif +typedef struct IDirectInputDevice2 *LPDIRECTINPUTDEVICE2; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInputDevice2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice2_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInputDevice2_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice2_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice2_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice2_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice2_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice2_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice2_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice2_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice2_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice2_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice2_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice2_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice2_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice2_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice2_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#define IDirectInputDevice2_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d) +#define IDirectInputDevice2_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c) +#define IDirectInputDevice2_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b) +#define IDirectInputDevice2_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a) +#define IDirectInputDevice2_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a) +#define IDirectInputDevice2_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c) +#define IDirectInputDevice2_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#define IDirectInputDevice2_Poll(p) (p)->lpVtbl->Poll(p) +#define IDirectInputDevice2_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d) +#else +#define IDirectInputDevice2_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice2_AddRef(p) (p)->AddRef() +#define IDirectInputDevice2_Release(p) (p)->Release() +#define IDirectInputDevice2_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice2_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice2_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice2_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice2_Acquire(p) (p)->Acquire() +#define IDirectInputDevice2_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice2_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice2_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice2_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice2_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice2_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice2_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice2_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice2_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice2_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#define IDirectInputDevice2_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d) +#define IDirectInputDevice2_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c) +#define IDirectInputDevice2_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b) +#define IDirectInputDevice2_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a) +#define IDirectInputDevice2_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a) +#define IDirectInputDevice2_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c) +#define IDirectInputDevice2_Escape(p,a) (p)->Escape(a) +#define IDirectInputDevice2_Poll(p) (p)->Poll() +#define IDirectInputDevice2_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d) +#endif + +#endif /* DIJ_RINGZERO */ + +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ + +#if(DIRECTINPUT_VERSION >= 0x0700) +#define DIFEF_DEFAULT 0x00000000 +#define DIFEF_INCLUDENONSTANDARD 0x00000001 +#define DIFEF_MODIFYIFNEEDED 0x00000010 + +#ifndef DIJ_RINGZERO + +#undef INTERFACE +#define INTERFACE IDirectInputDevice7W + +DECLARE_INTERFACE_(IDirectInputDevice7W, IDirectInputDevice2W) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDevice2W methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW,REFGUID) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + + /*** IDirectInputDevice7W methods ***/ + STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE; +}; + +typedef struct IDirectInputDevice7W *LPDIRECTINPUTDEVICE7W; + +#undef INTERFACE +#define INTERFACE IDirectInputDevice7A + +DECLARE_INTERFACE_(IDirectInputDevice7A, IDirectInputDevice2A) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDevice2A methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA,REFGUID) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + + /*** IDirectInputDevice7A methods ***/ + STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE; +}; + +typedef struct IDirectInputDevice7A *LPDIRECTINPUTDEVICE7A; + +#ifdef UNICODE +#define IID_IDirectInputDevice7 IID_IDirectInputDevice7W +#define IDirectInputDevice7 IDirectInputDevice7W +#define IDirectInputDevice7Vtbl IDirectInputDevice7WVtbl +#else +#define IID_IDirectInputDevice7 IID_IDirectInputDevice7A +#define IDirectInputDevice7 IDirectInputDevice7A +#define IDirectInputDevice7Vtbl IDirectInputDevice7AVtbl +#endif +typedef struct IDirectInputDevice7 *LPDIRECTINPUTDEVICE7; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInputDevice7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice7_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice7_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInputDevice7_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice7_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice7_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice7_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice7_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice7_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice7_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice7_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice7_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice7_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice7_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice7_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice7_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice7_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice7_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#define IDirectInputDevice7_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d) +#define IDirectInputDevice7_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c) +#define IDirectInputDevice7_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b) +#define IDirectInputDevice7_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a) +#define IDirectInputDevice7_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a) +#define IDirectInputDevice7_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c) +#define IDirectInputDevice7_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#define IDirectInputDevice7_Poll(p) (p)->lpVtbl->Poll(p) +#define IDirectInputDevice7_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d) +#define IDirectInputDevice7_EnumEffectsInFile(p,a,b,c,d) (p)->lpVtbl->EnumEffectsInFile(p,a,b,c,d) +#define IDirectInputDevice7_WriteEffectToFile(p,a,b,c,d) (p)->lpVtbl->WriteEffectToFile(p,a,b,c,d) +#else +#define IDirectInputDevice7_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice7_AddRef(p) (p)->AddRef() +#define IDirectInputDevice7_Release(p) (p)->Release() +#define IDirectInputDevice7_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice7_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice7_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice7_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice7_Acquire(p) (p)->Acquire() +#define IDirectInputDevice7_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice7_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice7_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice7_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice7_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice7_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice7_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice7_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice7_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice7_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#define IDirectInputDevice7_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d) +#define IDirectInputDevice7_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c) +#define IDirectInputDevice7_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b) +#define IDirectInputDevice7_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a) +#define IDirectInputDevice7_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a) +#define IDirectInputDevice7_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c) +#define IDirectInputDevice7_Escape(p,a) (p)->Escape(a) +#define IDirectInputDevice7_Poll(p) (p)->Poll() +#define IDirectInputDevice7_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d) +#define IDirectInputDevice7_EnumEffectsInFile(p,a,b,c,d) (p)->EnumEffectsInFile(a,b,c,d) +#define IDirectInputDevice7_WriteEffectToFile(p,a,b,c,d) (p)->WriteEffectToFile(a,b,c,d) +#endif + +#endif /* DIJ_RINGZERO */ + +#endif /* DIRECTINPUT_VERSION >= 0x0700 */ + +#if(DIRECTINPUT_VERSION >= 0x0800) + +#ifndef DIJ_RINGZERO + +#undef INTERFACE +#define INTERFACE IDirectInputDevice8W + +DECLARE_INTERFACE_(IDirectInputDevice8W, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDevice8W methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW,REFGUID) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE; + STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATW,LPCWSTR,DWORD) PURE; + STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATW,LPCWSTR,DWORD) PURE; + STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERW) PURE; +}; + +typedef struct IDirectInputDevice8W *LPDIRECTINPUTDEVICE8W; + +#undef INTERFACE +#define INTERFACE IDirectInputDevice8A + +DECLARE_INTERFACE_(IDirectInputDevice8A, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputDevice8A methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE; + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE; + STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE; + STDMETHOD(Acquire)(THIS) PURE; + STDMETHOD(Unacquire)(THIS) PURE; + STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE; + STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE; + STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE; + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE; + STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE; + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA,REFGUID) PURE; + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE; + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE; + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE; + STDMETHOD(Poll)(THIS) PURE; + STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE; + STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR,LPDIENUMEFFECTSINFILECALLBACK,LPVOID,DWORD) PURE; + STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR,DWORD,LPDIFILEEFFECT,DWORD) PURE; + STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATA,LPCSTR,DWORD) PURE; + STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATA,LPCSTR,DWORD) PURE; + STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERA) PURE; +}; + +typedef struct IDirectInputDevice8A *LPDIRECTINPUTDEVICE8A; + +#ifdef UNICODE +#define IID_IDirectInputDevice8 IID_IDirectInputDevice8W +#define IDirectInputDevice8 IDirectInputDevice8W +#define IDirectInputDevice8Vtbl IDirectInputDevice8WVtbl +#else +#define IID_IDirectInputDevice8 IID_IDirectInputDevice8A +#define IDirectInputDevice8 IDirectInputDevice8A +#define IDirectInputDevice8Vtbl IDirectInputDevice8AVtbl +#endif +typedef struct IDirectInputDevice8 *LPDIRECTINPUTDEVICE8; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInputDevice8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInputDevice8_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInputDevice8_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInputDevice8_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a) +#define IDirectInputDevice8_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c) +#define IDirectInputDevice8_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b) +#define IDirectInputDevice8_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b) +#define IDirectInputDevice8_Acquire(p) (p)->lpVtbl->Acquire(p) +#define IDirectInputDevice8_Unacquire(p) (p)->lpVtbl->Unacquire(p) +#define IDirectInputDevice8_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b) +#define IDirectInputDevice8_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d) +#define IDirectInputDevice8_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a) +#define IDirectInputDevice8_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a) +#define IDirectInputDevice8_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectInputDevice8_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c) +#define IDirectInputDevice8_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a) +#define IDirectInputDevice8_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInputDevice8_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c) +#define IDirectInputDevice8_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d) +#define IDirectInputDevice8_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c) +#define IDirectInputDevice8_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b) +#define IDirectInputDevice8_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a) +#define IDirectInputDevice8_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a) +#define IDirectInputDevice8_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c) +#define IDirectInputDevice8_Escape(p,a) (p)->lpVtbl->Escape(p,a) +#define IDirectInputDevice8_Poll(p) (p)->lpVtbl->Poll(p) +#define IDirectInputDevice8_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d) +#define IDirectInputDevice8_EnumEffectsInFile(p,a,b,c,d) (p)->lpVtbl->EnumEffectsInFile(p,a,b,c,d) +#define IDirectInputDevice8_WriteEffectToFile(p,a,b,c,d) (p)->lpVtbl->WriteEffectToFile(p,a,b,c,d) +#define IDirectInputDevice8_BuildActionMap(p,a,b,c) (p)->lpVtbl->BuildActionMap(p,a,b,c) +#define IDirectInputDevice8_SetActionMap(p,a,b,c) (p)->lpVtbl->SetActionMap(p,a,b,c) +#define IDirectInputDevice8_GetImageInfo(p,a) (p)->lpVtbl->GetImageInfo(p,a) +#else +#define IDirectInputDevice8_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInputDevice8_AddRef(p) (p)->AddRef() +#define IDirectInputDevice8_Release(p) (p)->Release() +#define IDirectInputDevice8_GetCapabilities(p,a) (p)->GetCapabilities(a) +#define IDirectInputDevice8_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c) +#define IDirectInputDevice8_GetProperty(p,a,b) (p)->GetProperty(a,b) +#define IDirectInputDevice8_SetProperty(p,a,b) (p)->SetProperty(a,b) +#define IDirectInputDevice8_Acquire(p) (p)->Acquire() +#define IDirectInputDevice8_Unacquire(p) (p)->Unacquire() +#define IDirectInputDevice8_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b) +#define IDirectInputDevice8_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d) +#define IDirectInputDevice8_SetDataFormat(p,a) (p)->SetDataFormat(a) +#define IDirectInputDevice8_SetEventNotification(p,a) (p)->SetEventNotification(a) +#define IDirectInputDevice8_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectInputDevice8_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c) +#define IDirectInputDevice8_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a) +#define IDirectInputDevice8_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInputDevice8_Initialize(p,a,b,c) (p)->Initialize(a,b,c) +#define IDirectInputDevice8_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d) +#define IDirectInputDevice8_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c) +#define IDirectInputDevice8_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b) +#define IDirectInputDevice8_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a) +#define IDirectInputDevice8_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a) +#define IDirectInputDevice8_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c) +#define IDirectInputDevice8_Escape(p,a) (p)->Escape(a) +#define IDirectInputDevice8_Poll(p) (p)->Poll() +#define IDirectInputDevice8_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d) +#define IDirectInputDevice8_EnumEffectsInFile(p,a,b,c,d) (p)->EnumEffectsInFile(a,b,c,d) +#define IDirectInputDevice8_WriteEffectToFile(p,a,b,c,d) (p)->WriteEffectToFile(a,b,c,d) +#define IDirectInputDevice8_BuildActionMap(p,a,b,c) (p)->BuildActionMap(a,b,c) +#define IDirectInputDevice8_SetActionMap(p,a,b,c) (p)->SetActionMap(a,b,c) +#define IDirectInputDevice8_GetImageInfo(p,a) (p)->GetImageInfo(a) +#endif + +#endif /* DIJ_RINGZERO */ + +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +/**************************************************************************** + * + * Mouse + * + ****************************************************************************/ + +#ifndef DIJ_RINGZERO + +typedef struct _DIMOUSESTATE { + LONG lX; + LONG lY; + LONG lZ; + BYTE rgbButtons[4]; +} DIMOUSESTATE, *LPDIMOUSESTATE; + +#if DIRECTINPUT_VERSION >= 0x0700 +typedef struct _DIMOUSESTATE2 { + LONG lX; + LONG lY; + LONG lZ; + BYTE rgbButtons[8]; +} DIMOUSESTATE2, *LPDIMOUSESTATE2; +#endif + + +#define DIMOFS_X FIELD_OFFSET(DIMOUSESTATE, lX) +#define DIMOFS_Y FIELD_OFFSET(DIMOUSESTATE, lY) +#define DIMOFS_Z FIELD_OFFSET(DIMOUSESTATE, lZ) +#define DIMOFS_BUTTON0 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 0) +#define DIMOFS_BUTTON1 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 1) +#define DIMOFS_BUTTON2 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 2) +#define DIMOFS_BUTTON3 (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 3) +#if (DIRECTINPUT_VERSION >= 0x0700) +#define DIMOFS_BUTTON4 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 4) +#define DIMOFS_BUTTON5 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 5) +#define DIMOFS_BUTTON6 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 6) +#define DIMOFS_BUTTON7 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 7) +#endif +#endif /* DIJ_RINGZERO */ + +/**************************************************************************** + * + * Keyboard + * + ****************************************************************************/ + +#ifndef DIJ_RINGZERO + +/**************************************************************************** + * + * DirectInput keyboard scan codes + * + ****************************************************************************/ +#define DIK_ESCAPE 0x01 +#define DIK_1 0x02 +#define DIK_2 0x03 +#define DIK_3 0x04 +#define DIK_4 0x05 +#define DIK_5 0x06 +#define DIK_6 0x07 +#define DIK_7 0x08 +#define DIK_8 0x09 +#define DIK_9 0x0A +#define DIK_0 0x0B +#define DIK_MINUS 0x0C /* - on main keyboard */ +#define DIK_EQUALS 0x0D +#define DIK_BACK 0x0E /* backspace */ +#define DIK_TAB 0x0F +#define DIK_Q 0x10 +#define DIK_W 0x11 +#define DIK_E 0x12 +#define DIK_R 0x13 +#define DIK_T 0x14 +#define DIK_Y 0x15 +#define DIK_U 0x16 +#define DIK_I 0x17 +#define DIK_O 0x18 +#define DIK_P 0x19 +#define DIK_LBRACKET 0x1A +#define DIK_RBRACKET 0x1B +#define DIK_RETURN 0x1C /* Enter on main keyboard */ +#define DIK_LCONTROL 0x1D +#define DIK_A 0x1E +#define DIK_S 0x1F +#define DIK_D 0x20 +#define DIK_F 0x21 +#define DIK_G 0x22 +#define DIK_H 0x23 +#define DIK_J 0x24 +#define DIK_K 0x25 +#define DIK_L 0x26 +#define DIK_SEMICOLON 0x27 +#define DIK_APOSTROPHE 0x28 +#define DIK_GRAVE 0x29 /* accent grave */ +#define DIK_LSHIFT 0x2A +#define DIK_BACKSLASH 0x2B +#define DIK_Z 0x2C +#define DIK_X 0x2D +#define DIK_C 0x2E +#define DIK_V 0x2F +#define DIK_B 0x30 +#define DIK_N 0x31 +#define DIK_M 0x32 +#define DIK_COMMA 0x33 +#define DIK_PERIOD 0x34 /* . on main keyboard */ +#define DIK_SLASH 0x35 /* / on main keyboard */ +#define DIK_RSHIFT 0x36 +#define DIK_MULTIPLY 0x37 /* * on numeric keypad */ +#define DIK_LMENU 0x38 /* left Alt */ +#define DIK_SPACE 0x39 +#define DIK_CAPITAL 0x3A +#define DIK_F1 0x3B +#define DIK_F2 0x3C +#define DIK_F3 0x3D +#define DIK_F4 0x3E +#define DIK_F5 0x3F +#define DIK_F6 0x40 +#define DIK_F7 0x41 +#define DIK_F8 0x42 +#define DIK_F9 0x43 +#define DIK_F10 0x44 +#define DIK_NUMLOCK 0x45 +#define DIK_SCROLL 0x46 /* Scroll Lock */ +#define DIK_NUMPAD7 0x47 +#define DIK_NUMPAD8 0x48 +#define DIK_NUMPAD9 0x49 +#define DIK_SUBTRACT 0x4A /* - on numeric keypad */ +#define DIK_NUMPAD4 0x4B +#define DIK_NUMPAD5 0x4C +#define DIK_NUMPAD6 0x4D +#define DIK_ADD 0x4E /* + on numeric keypad */ +#define DIK_NUMPAD1 0x4F +#define DIK_NUMPAD2 0x50 +#define DIK_NUMPAD3 0x51 +#define DIK_NUMPAD0 0x52 +#define DIK_DECIMAL 0x53 /* . on numeric keypad */ +#define DIK_OEM_102 0x56 /* <> or \| on RT 102-key keyboard (Non-U.S.) */ +#define DIK_F11 0x57 +#define DIK_F12 0x58 +#define DIK_F13 0x64 /* (NEC PC98) */ +#define DIK_F14 0x65 /* (NEC PC98) */ +#define DIK_F15 0x66 /* (NEC PC98) */ +#define DIK_KANA 0x70 /* (Japanese keyboard) */ +#define DIK_ABNT_C1 0x73 /* /? on Brazilian keyboard */ +#define DIK_CONVERT 0x79 /* (Japanese keyboard) */ +#define DIK_NOCONVERT 0x7B /* (Japanese keyboard) */ +#define DIK_YEN 0x7D /* (Japanese keyboard) */ +#define DIK_ABNT_C2 0x7E /* Numpad . on Brazilian keyboard */ +#define DIK_NUMPADEQUALS 0x8D /* = on numeric keypad (NEC PC98) */ +#define DIK_PREVTRACK 0x90 /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */ +#define DIK_AT 0x91 /* (NEC PC98) */ +#define DIK_COLON 0x92 /* (NEC PC98) */ +#define DIK_UNDERLINE 0x93 /* (NEC PC98) */ +#define DIK_KANJI 0x94 /* (Japanese keyboard) */ +#define DIK_STOP 0x95 /* (NEC PC98) */ +#define DIK_AX 0x96 /* (Japan AX) */ +#define DIK_UNLABELED 0x97 /* (J3100) */ +#define DIK_NEXTTRACK 0x99 /* Next Track */ +#define DIK_NUMPADENTER 0x9C /* Enter on numeric keypad */ +#define DIK_RCONTROL 0x9D +#define DIK_MUTE 0xA0 /* Mute */ +#define DIK_CALCULATOR 0xA1 /* Calculator */ +#define DIK_PLAYPAUSE 0xA2 /* Play / Pause */ +#define DIK_MEDIASTOP 0xA4 /* Media Stop */ +#define DIK_VOLUMEDOWN 0xAE /* Volume - */ +#define DIK_VOLUMEUP 0xB0 /* Volume + */ +#define DIK_WEBHOME 0xB2 /* Web home */ +#define DIK_NUMPADCOMMA 0xB3 /* , on numeric keypad (NEC PC98) */ +#define DIK_DIVIDE 0xB5 /* / on numeric keypad */ +#define DIK_SYSRQ 0xB7 +#define DIK_RMENU 0xB8 /* right Alt */ +#define DIK_PAUSE 0xC5 /* Pause */ +#define DIK_HOME 0xC7 /* Home on arrow keypad */ +#define DIK_UP 0xC8 /* UpArrow on arrow keypad */ +#define DIK_PRIOR 0xC9 /* PgUp on arrow keypad */ +#define DIK_LEFT 0xCB /* LeftArrow on arrow keypad */ +#define DIK_RIGHT 0xCD /* RightArrow on arrow keypad */ +#define DIK_END 0xCF /* End on arrow keypad */ +#define DIK_DOWN 0xD0 /* DownArrow on arrow keypad */ +#define DIK_NEXT 0xD1 /* PgDn on arrow keypad */ +#define DIK_INSERT 0xD2 /* Insert on arrow keypad */ +#define DIK_DELETE 0xD3 /* Delete on arrow keypad */ +#define DIK_LWIN 0xDB /* Left Windows key */ +#define DIK_RWIN 0xDC /* Right Windows key */ +#define DIK_APPS 0xDD /* AppMenu key */ +#define DIK_POWER 0xDE /* System Power */ +#define DIK_SLEEP 0xDF /* System Sleep */ +#define DIK_WAKE 0xE3 /* System Wake */ +#define DIK_WEBSEARCH 0xE5 /* Web Search */ +#define DIK_WEBFAVORITES 0xE6 /* Web Favorites */ +#define DIK_WEBREFRESH 0xE7 /* Web Refresh */ +#define DIK_WEBSTOP 0xE8 /* Web Stop */ +#define DIK_WEBFORWARD 0xE9 /* Web Forward */ +#define DIK_WEBBACK 0xEA /* Web Back */ +#define DIK_MYCOMPUTER 0xEB /* My Computer */ +#define DIK_MAIL 0xEC /* Mail */ +#define DIK_MEDIASELECT 0xED /* Media Select */ + +/* + * Alternate names for keys, to facilitate transition from DOS. + */ +#define DIK_BACKSPACE DIK_BACK /* backspace */ +#define DIK_NUMPADSTAR DIK_MULTIPLY /* * on numeric keypad */ +#define DIK_LALT DIK_LMENU /* left Alt */ +#define DIK_CAPSLOCK DIK_CAPITAL /* CapsLock */ +#define DIK_NUMPADMINUS DIK_SUBTRACT /* - on numeric keypad */ +#define DIK_NUMPADPLUS DIK_ADD /* + on numeric keypad */ +#define DIK_NUMPADPERIOD DIK_DECIMAL /* . on numeric keypad */ +#define DIK_NUMPADSLASH DIK_DIVIDE /* / on numeric keypad */ +#define DIK_RALT DIK_RMENU /* right Alt */ +#define DIK_UPARROW DIK_UP /* UpArrow on arrow keypad */ +#define DIK_PGUP DIK_PRIOR /* PgUp on arrow keypad */ +#define DIK_LEFTARROW DIK_LEFT /* LeftArrow on arrow keypad */ +#define DIK_RIGHTARROW DIK_RIGHT /* RightArrow on arrow keypad */ +#define DIK_DOWNARROW DIK_DOWN /* DownArrow on arrow keypad */ +#define DIK_PGDN DIK_NEXT /* PgDn on arrow keypad */ + +/* + * Alternate names for keys originally not used on US keyboards. + */ +#define DIK_CIRCUMFLEX DIK_PREVTRACK /* Japanese keyboard */ + +#endif /* DIJ_RINGZERO */ + +/**************************************************************************** + * + * Joystick + * + ****************************************************************************/ + +#ifndef DIJ_RINGZERO + +typedef struct DIJOYSTATE { + LONG lX; /* x-axis position */ + LONG lY; /* y-axis position */ + LONG lZ; /* z-axis position */ + LONG lRx; /* x-axis rotation */ + LONG lRy; /* y-axis rotation */ + LONG lRz; /* z-axis rotation */ + LONG rglSlider[2]; /* extra axes positions */ + DWORD rgdwPOV[4]; /* POV directions */ + BYTE rgbButtons[32]; /* 32 buttons */ +} DIJOYSTATE, *LPDIJOYSTATE; + +typedef struct DIJOYSTATE2 { + LONG lX; /* x-axis position */ + LONG lY; /* y-axis position */ + LONG lZ; /* z-axis position */ + LONG lRx; /* x-axis rotation */ + LONG lRy; /* y-axis rotation */ + LONG lRz; /* z-axis rotation */ + LONG rglSlider[2]; /* extra axes positions */ + DWORD rgdwPOV[4]; /* POV directions */ + BYTE rgbButtons[128]; /* 128 buttons */ + LONG lVX; /* x-axis velocity */ + LONG lVY; /* y-axis velocity */ + LONG lVZ; /* z-axis velocity */ + LONG lVRx; /* x-axis angular velocity */ + LONG lVRy; /* y-axis angular velocity */ + LONG lVRz; /* z-axis angular velocity */ + LONG rglVSlider[2]; /* extra axes velocities */ + LONG lAX; /* x-axis acceleration */ + LONG lAY; /* y-axis acceleration */ + LONG lAZ; /* z-axis acceleration */ + LONG lARx; /* x-axis angular acceleration */ + LONG lARy; /* y-axis angular acceleration */ + LONG lARz; /* z-axis angular acceleration */ + LONG rglASlider[2]; /* extra axes accelerations */ + LONG lFX; /* x-axis force */ + LONG lFY; /* y-axis force */ + LONG lFZ; /* z-axis force */ + LONG lFRx; /* x-axis torque */ + LONG lFRy; /* y-axis torque */ + LONG lFRz; /* z-axis torque */ + LONG rglFSlider[2]; /* extra axes forces */ +} DIJOYSTATE2, *LPDIJOYSTATE2; + +#define DIJOFS_X FIELD_OFFSET(DIJOYSTATE, lX) +#define DIJOFS_Y FIELD_OFFSET(DIJOYSTATE, lY) +#define DIJOFS_Z FIELD_OFFSET(DIJOYSTATE, lZ) +#define DIJOFS_RX FIELD_OFFSET(DIJOYSTATE, lRx) +#define DIJOFS_RY FIELD_OFFSET(DIJOYSTATE, lRy) +#define DIJOFS_RZ FIELD_OFFSET(DIJOYSTATE, lRz) +#define DIJOFS_SLIDER(n) (FIELD_OFFSET(DIJOYSTATE, rglSlider) + \ + (n) * sizeof(LONG)) +#define DIJOFS_POV(n) (FIELD_OFFSET(DIJOYSTATE, rgdwPOV) + \ + (n) * sizeof(DWORD)) +#define DIJOFS_BUTTON(n) (FIELD_OFFSET(DIJOYSTATE, rgbButtons) + (n)) +#define DIJOFS_BUTTON0 DIJOFS_BUTTON(0) +#define DIJOFS_BUTTON1 DIJOFS_BUTTON(1) +#define DIJOFS_BUTTON2 DIJOFS_BUTTON(2) +#define DIJOFS_BUTTON3 DIJOFS_BUTTON(3) +#define DIJOFS_BUTTON4 DIJOFS_BUTTON(4) +#define DIJOFS_BUTTON5 DIJOFS_BUTTON(5) +#define DIJOFS_BUTTON6 DIJOFS_BUTTON(6) +#define DIJOFS_BUTTON7 DIJOFS_BUTTON(7) +#define DIJOFS_BUTTON8 DIJOFS_BUTTON(8) +#define DIJOFS_BUTTON9 DIJOFS_BUTTON(9) +#define DIJOFS_BUTTON10 DIJOFS_BUTTON(10) +#define DIJOFS_BUTTON11 DIJOFS_BUTTON(11) +#define DIJOFS_BUTTON12 DIJOFS_BUTTON(12) +#define DIJOFS_BUTTON13 DIJOFS_BUTTON(13) +#define DIJOFS_BUTTON14 DIJOFS_BUTTON(14) +#define DIJOFS_BUTTON15 DIJOFS_BUTTON(15) +#define DIJOFS_BUTTON16 DIJOFS_BUTTON(16) +#define DIJOFS_BUTTON17 DIJOFS_BUTTON(17) +#define DIJOFS_BUTTON18 DIJOFS_BUTTON(18) +#define DIJOFS_BUTTON19 DIJOFS_BUTTON(19) +#define DIJOFS_BUTTON20 DIJOFS_BUTTON(20) +#define DIJOFS_BUTTON21 DIJOFS_BUTTON(21) +#define DIJOFS_BUTTON22 DIJOFS_BUTTON(22) +#define DIJOFS_BUTTON23 DIJOFS_BUTTON(23) +#define DIJOFS_BUTTON24 DIJOFS_BUTTON(24) +#define DIJOFS_BUTTON25 DIJOFS_BUTTON(25) +#define DIJOFS_BUTTON26 DIJOFS_BUTTON(26) +#define DIJOFS_BUTTON27 DIJOFS_BUTTON(27) +#define DIJOFS_BUTTON28 DIJOFS_BUTTON(28) +#define DIJOFS_BUTTON29 DIJOFS_BUTTON(29) +#define DIJOFS_BUTTON30 DIJOFS_BUTTON(30) +#define DIJOFS_BUTTON31 DIJOFS_BUTTON(31) + + +#endif /* DIJ_RINGZERO */ + +/**************************************************************************** + * + * IDirectInput + * + ****************************************************************************/ + +#ifndef DIJ_RINGZERO + +#define DIENUM_STOP 0 +#define DIENUM_CONTINUE 1 + +typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKA)(LPCDIDEVICEINSTANCEA, LPVOID); +typedef BOOL (FAR PASCAL * LPDIENUMDEVICESCALLBACKW)(LPCDIDEVICEINSTANCEW, LPVOID); +#ifdef UNICODE +#define LPDIENUMDEVICESCALLBACK LPDIENUMDEVICESCALLBACKW +#else +#define LPDIENUMDEVICESCALLBACK LPDIENUMDEVICESCALLBACKA +#endif // !UNICODE +typedef BOOL (FAR PASCAL * LPDICONFIGUREDEVICESCALLBACK)(IUnknown FAR *, LPVOID); + +#define DIEDFL_ALLDEVICES 0x00000000 +#define DIEDFL_ATTACHEDONLY 0x00000001 +#if(DIRECTINPUT_VERSION >= 0x0500) +#define DIEDFL_FORCEFEEDBACK 0x00000100 +#endif /* DIRECTINPUT_VERSION >= 0x0500 */ +#if(DIRECTINPUT_VERSION >= 0x050a) +#define DIEDFL_INCLUDEALIASES 0x00010000 +#define DIEDFL_INCLUDEPHANTOMS 0x00020000 +#endif /* DIRECTINPUT_VERSION >= 0x050a */ +#if(DIRECTINPUT_VERSION >= 0x0800) +#define DIEDFL_INCLUDEHIDDEN 0x00040000 +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + + +#if(DIRECTINPUT_VERSION >= 0x0800) +typedef BOOL (FAR PASCAL * LPDIENUMDEVICESBYSEMANTICSCBA)(LPCDIDEVICEINSTANCEA, LPDIRECTINPUTDEVICE8A, DWORD, DWORD, LPVOID); +typedef BOOL (FAR PASCAL * LPDIENUMDEVICESBYSEMANTICSCBW)(LPCDIDEVICEINSTANCEW, LPDIRECTINPUTDEVICE8W, DWORD, DWORD, LPVOID); +#ifdef UNICODE +#define LPDIENUMDEVICESBYSEMANTICSCB LPDIENUMDEVICESBYSEMANTICSCBW +#else +#define LPDIENUMDEVICESBYSEMANTICSCB LPDIENUMDEVICESBYSEMANTICSCBA +#endif // !UNICODE +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +#if(DIRECTINPUT_VERSION >= 0x0800) +#define DIEDBS_MAPPEDPRI1 0x00000001 +#define DIEDBS_MAPPEDPRI2 0x00000002 +#define DIEDBS_RECENTDEVICE 0x00000010 +#define DIEDBS_NEWDEVICE 0x00000020 +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +#if(DIRECTINPUT_VERSION >= 0x0800) +#define DIEDBSFL_ATTACHEDONLY 0x00000000 +#define DIEDBSFL_THISUSER 0x00000010 +#define DIEDBSFL_FORCEFEEDBACK DIEDFL_FORCEFEEDBACK +#define DIEDBSFL_AVAILABLEDEVICES 0x00001000 +#define DIEDBSFL_MULTIMICEKEYBOARDS 0x00002000 +#define DIEDBSFL_NONGAMINGDEVICES 0x00004000 +#define DIEDBSFL_VALID 0x00007110 +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +#undef INTERFACE +#define INTERFACE IDirectInputW + +DECLARE_INTERFACE_(IDirectInputW, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputW methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; +}; + +typedef struct IDirectInputW *LPDIRECTINPUTW; + +#undef INTERFACE +#define INTERFACE IDirectInputA + +DECLARE_INTERFACE_(IDirectInputA, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputA methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; +}; + +typedef struct IDirectInputA *LPDIRECTINPUTA; + +#ifdef UNICODE +#define IID_IDirectInput IID_IDirectInputW +#define IDirectInput IDirectInputW +#define IDirectInputVtbl IDirectInputWVtbl +#else +#define IID_IDirectInput IID_IDirectInputA +#define IDirectInput IDirectInputA +#define IDirectInputVtbl IDirectInputAVtbl +#endif +typedef struct IDirectInput *LPDIRECTINPUT; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInput_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInput_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#else +#define IDirectInput_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput_AddRef(p) (p)->AddRef() +#define IDirectInput_Release(p) (p)->Release() +#define IDirectInput_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput_Initialize(p,a,b) (p)->Initialize(a,b) +#endif + +#undef INTERFACE +#define INTERFACE IDirectInput2W + +DECLARE_INTERFACE_(IDirectInput2W, IDirectInputW) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputW methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; + + /*** IDirectInput2W methods ***/ + STDMETHOD(FindDevice)(THIS_ REFGUID,LPCWSTR,LPGUID) PURE; +}; + +typedef struct IDirectInput2W *LPDIRECTINPUT2W; + +#undef INTERFACE +#define INTERFACE IDirectInput2A + +DECLARE_INTERFACE_(IDirectInput2A, IDirectInputA) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInputA methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; + + /*** IDirectInput2A methods ***/ + STDMETHOD(FindDevice)(THIS_ REFGUID,LPCSTR,LPGUID) PURE; +}; + +typedef struct IDirectInput2A *LPDIRECTINPUT2A; + +#ifdef UNICODE +#define IID_IDirectInput2 IID_IDirectInput2W +#define IDirectInput2 IDirectInput2W +#define IDirectInput2Vtbl IDirectInput2WVtbl +#else +#define IID_IDirectInput2 IID_IDirectInput2A +#define IDirectInput2 IDirectInput2A +#define IDirectInput2Vtbl IDirectInput2AVtbl +#endif +typedef struct IDirectInput2 *LPDIRECTINPUT2; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInput2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput2_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInput2_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput2_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput2_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput2_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput2_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectInput2_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c) +#else +#define IDirectInput2_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput2_AddRef(p) (p)->AddRef() +#define IDirectInput2_Release(p) (p)->Release() +#define IDirectInput2_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput2_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput2_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput2_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput2_Initialize(p,a,b) (p)->Initialize(a,b) +#define IDirectInput2_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c) +#endif + + +#undef INTERFACE +#define INTERFACE IDirectInput7W + +DECLARE_INTERFACE_(IDirectInput7W, IDirectInput2W) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInput2W methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; + STDMETHOD(FindDevice)(THIS_ REFGUID,LPCWSTR,LPGUID) PURE; + + /*** IDirectInput7W methods ***/ + STDMETHOD(CreateDeviceEx)(THIS_ REFGUID,REFIID,LPVOID *,LPUNKNOWN) PURE; +}; + +typedef struct IDirectInput7W *LPDIRECTINPUT7W; + +#undef INTERFACE +#define INTERFACE IDirectInput7A + +DECLARE_INTERFACE_(IDirectInput7A, IDirectInput2A) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInput2A methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; + STDMETHOD(FindDevice)(THIS_ REFGUID,LPCSTR,LPGUID) PURE; + + /*** IDirectInput7A methods ***/ + STDMETHOD(CreateDeviceEx)(THIS_ REFGUID,REFIID,LPVOID *,LPUNKNOWN) PURE; +}; + +typedef struct IDirectInput7A *LPDIRECTINPUT7A; + +#ifdef UNICODE +#define IID_IDirectInput7 IID_IDirectInput7W +#define IDirectInput7 IDirectInput7W +#define IDirectInput7Vtbl IDirectInput7WVtbl +#else +#define IID_IDirectInput7 IID_IDirectInput7A +#define IDirectInput7 IDirectInput7A +#define IDirectInput7Vtbl IDirectInput7AVtbl +#endif +typedef struct IDirectInput7 *LPDIRECTINPUT7; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInput7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput7_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput7_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInput7_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput7_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput7_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput7_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput7_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectInput7_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c) +#define IDirectInput7_CreateDeviceEx(p,a,b,c,d) (p)->lpVtbl->CreateDeviceEx(p,a,b,c,d) +#else +#define IDirectInput7_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput7_AddRef(p) (p)->AddRef() +#define IDirectInput7_Release(p) (p)->Release() +#define IDirectInput7_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput7_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput7_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput7_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput7_Initialize(p,a,b) (p)->Initialize(a,b) +#define IDirectInput7_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c) +#define IDirectInput7_CreateDeviceEx(p,a,b,c,d) (p)->CreateDeviceEx(a,b,c,d) +#endif + +#if(DIRECTINPUT_VERSION >= 0x0800) +#undef INTERFACE +#define INTERFACE IDirectInput8W + +DECLARE_INTERFACE_(IDirectInput8W, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInput8W methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICE8W *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; + STDMETHOD(FindDevice)(THIS_ REFGUID,LPCWSTR,LPGUID) PURE; + STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCWSTR,LPDIACTIONFORMATW,LPDIENUMDEVICESBYSEMANTICSCBW,LPVOID,DWORD) PURE; + STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK,LPDICONFIGUREDEVICESPARAMSW,DWORD,LPVOID) PURE; +}; + +typedef struct IDirectInput8W *LPDIRECTINPUT8W; + +#undef INTERFACE +#define INTERFACE IDirectInput8A + +DECLARE_INTERFACE_(IDirectInput8A, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + /*** IDirectInput8A methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICE8A *,LPUNKNOWN) PURE; + STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE; + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE; + STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE; + STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE; + STDMETHOD(FindDevice)(THIS_ REFGUID,LPCSTR,LPGUID) PURE; + STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCSTR,LPDIACTIONFORMATA,LPDIENUMDEVICESBYSEMANTICSCBA,LPVOID,DWORD) PURE; + STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK,LPDICONFIGUREDEVICESPARAMSA,DWORD,LPVOID) PURE; +}; + +typedef struct IDirectInput8A *LPDIRECTINPUT8A; + +#ifdef UNICODE +#define IID_IDirectInput8 IID_IDirectInput8W +#define IDirectInput8 IDirectInput8W +#define IDirectInput8Vtbl IDirectInput8WVtbl +#else +#define IID_IDirectInput8 IID_IDirectInput8A +#define IDirectInput8 IDirectInput8A +#define IDirectInput8Vtbl IDirectInput8AVtbl +#endif +typedef struct IDirectInput8 *LPDIRECTINPUT8; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectInput8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectInput8_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectInput8_Release(p) (p)->lpVtbl->Release(p) +#define IDirectInput8_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c) +#define IDirectInput8_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d) +#define IDirectInput8_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a) +#define IDirectInput8_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b) +#define IDirectInput8_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectInput8_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c) +#define IDirectInput8_EnumDevicesBySemantics(p,a,b,c,d,e) (p)->lpVtbl->EnumDevicesBySemantics(p,a,b,c,d,e) +#define IDirectInput8_ConfigureDevices(p,a,b,c,d) (p)->lpVtbl->ConfigureDevices(p,a,b,c,d) +#else +#define IDirectInput8_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectInput8_AddRef(p) (p)->AddRef() +#define IDirectInput8_Release(p) (p)->Release() +#define IDirectInput8_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c) +#define IDirectInput8_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d) +#define IDirectInput8_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a) +#define IDirectInput8_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b) +#define IDirectInput8_Initialize(p,a,b) (p)->Initialize(a,b) +#define IDirectInput8_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c) +#define IDirectInput8_EnumDevicesBySemantics(p,a,b,c,d,e) (p)->EnumDevicesBySemantics(a,b,c,d,e) +#define IDirectInput8_ConfigureDevices(p,a,b,c,d) (p)->ConfigureDevices(a,b,c,d) +#endif +#endif /* DIRECTINPUT_VERSION >= 0x0800 */ + +#if DIRECTINPUT_VERSION > 0x0700 + +extern HRESULT WINAPI DirectInput8Create(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter); + +#else +extern HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter); +extern HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter); +#ifdef UNICODE +#define DirectInputCreate DirectInputCreateW +#else +#define DirectInputCreate DirectInputCreateA +#endif // !UNICODE + +extern HRESULT WINAPI DirectInputCreateEx(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter); + +#endif /* DIRECTINPUT_VERSION > 0x700 */ + +#endif /* DIJ_RINGZERO */ + + +/**************************************************************************** + * + * Return Codes + * + ****************************************************************************/ + +/* + * The operation completed successfully. + */ +#define DI_OK S_OK + +/* + * The device exists but is not currently attached. + */ +#define DI_NOTATTACHED S_FALSE + +/* + * The device buffer overflowed. Some input was lost. + */ +#define DI_BUFFEROVERFLOW S_FALSE + +/* + * The change in device properties had no effect. + */ +#define DI_PROPNOEFFECT S_FALSE + +/* + * The operation had no effect. + */ +#define DI_NOEFFECT S_FALSE + +/* + * The device is a polled device. As a result, device buffering + * will not collect any data and event notifications will not be + * signalled until GetDeviceState is called. + */ +#define DI_POLLEDDEVICE ((HRESULT)0x00000002L) + +/* + * The parameters of the effect were successfully updated by + * IDirectInputEffect::SetParameters, but the effect was not + * downloaded because the device is not exclusively acquired + * or because the DIEP_NODOWNLOAD flag was passed. + */ +#define DI_DOWNLOADSKIPPED ((HRESULT)0x00000003L) + +/* + * The parameters of the effect were successfully updated by + * IDirectInputEffect::SetParameters, but in order to change + * the parameters, the effect needed to be restarted. + */ +#define DI_EFFECTRESTARTED ((HRESULT)0x00000004L) + +/* + * The parameters of the effect were successfully updated by + * IDirectInputEffect::SetParameters, but some of them were + * beyond the capabilities of the device and were truncated. + */ +#define DI_TRUNCATED ((HRESULT)0x00000008L) + +/* + * The settings have been successfully applied but could not be + * persisted. + */ +#define DI_SETTINGSNOTSAVED ((HRESULT)0x0000000BL) + +/* + * Equal to DI_EFFECTRESTARTED | DI_TRUNCATED. + */ +#define DI_TRUNCATEDANDRESTARTED ((HRESULT)0x0000000CL) + +/* + * A SUCCESS code indicating that settings cannot be modified. + */ +#define DI_WRITEPROTECT ((HRESULT)0x00000013L) + +/* + * The application requires a newer version of DirectInput. + */ +#define DIERR_OLDDIRECTINPUTVERSION \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_OLD_WIN_VERSION) + +/* + * The application was written for an unsupported prerelease version + * of DirectInput. + */ +#define DIERR_BETADIRECTINPUTVERSION \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_RMODE_APP) + +/* + * The object could not be created due to an incompatible driver version + * or mismatched or incomplete driver components. + */ +#define DIERR_BADDRIVERVER \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BAD_DRIVER_LEVEL) + +/* + * The device or device instance or effect is not registered with DirectInput. + */ +#define DIERR_DEVICENOTREG REGDB_E_CLASSNOTREG + +/* + * The requested object does not exist. + */ +#define DIERR_NOTFOUND \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND) + +/* + * The requested object does not exist. + */ +#define DIERR_OBJECTNOTFOUND \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND) + +/* + * An invalid parameter was passed to the returning function, + * or the object was not in a state that admitted the function + * to be called. + */ +#define DIERR_INVALIDPARAM E_INVALIDARG + +/* + * The specified interface is not supported by the object + */ +#define DIERR_NOINTERFACE E_NOINTERFACE + +/* + * An undetermined error occured inside the DInput subsystem + */ +#define DIERR_GENERIC E_FAIL + +/* + * The DInput subsystem couldn't allocate sufficient memory to complete the + * caller's request. + */ +#define DIERR_OUTOFMEMORY E_OUTOFMEMORY + +/* + * The function called is not supported at this time + */ +#define DIERR_UNSUPPORTED E_NOTIMPL + +/* + * This object has not been initialized + */ +#define DIERR_NOTINITIALIZED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_READY) + +/* + * This object is already initialized + */ +#define DIERR_ALREADYINITIALIZED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_ALREADY_INITIALIZED) + +/* + * This object does not support aggregation + */ +#define DIERR_NOAGGREGATION CLASS_E_NOAGGREGATION + +/* + * Another app has a higher priority level, preventing this call from + * succeeding. + */ +#define DIERR_OTHERAPPHASPRIO E_ACCESSDENIED + +/* + * Access to the device has been lost. It must be re-acquired. + */ +#define DIERR_INPUTLOST \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_READ_FAULT) + +/* + * The operation cannot be performed while the device is acquired. + */ +#define DIERR_ACQUIRED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BUSY) + +/* + * The operation cannot be performed unless the device is acquired. + */ +#define DIERR_NOTACQUIRED \ + MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_INVALID_ACCESS) + +/* + * The specified property cannot be changed. + */ +#define DIERR_READONLY E_ACCESSDENIED + +/* + * The device already has an event notification associated with it. + */ +#define DIERR_HANDLEEXISTS E_ACCESSDENIED + +/* + * Data is not yet available. + */ +#ifndef E_PENDING +#define E_PENDING 0x8000000AL +#endif + +/* + * Unable to IDirectInputJoyConfig_Acquire because the user + * does not have sufficient privileges to change the joystick + * configuration. + */ +#define DIERR_INSUFFICIENTPRIVS 0x80040200L + +/* + * The device is full. + */ +#define DIERR_DEVICEFULL 0x80040201L + +/* + * Not all the requested information fit into the buffer. + */ +#define DIERR_MOREDATA 0x80040202L + +/* + * The effect is not downloaded. + */ +#define DIERR_NOTDOWNLOADED 0x80040203L + +/* + * The device cannot be reinitialized because there are still effects + * attached to it. + */ +#define DIERR_HASEFFECTS 0x80040204L + +/* + * The operation cannot be performed unless the device is acquired + * in DISCL_EXCLUSIVE mode. + */ +#define DIERR_NOTEXCLUSIVEACQUIRED 0x80040205L + +/* + * The effect could not be downloaded because essential information + * is missing. For example, no axes have been associated with the + * effect, or no type-specific information has been created. + */ +#define DIERR_INCOMPLETEEFFECT 0x80040206L + +/* + * Attempted to read buffered device data from a device that is + * not buffered. + */ +#define DIERR_NOTBUFFERED 0x80040207L + +/* + * An attempt was made to modify parameters of an effect while it is + * playing. Not all hardware devices support altering the parameters + * of an effect while it is playing. + */ +#define DIERR_EFFECTPLAYING 0x80040208L + +/* + * The operation could not be completed because the device is not + * plugged in. + */ +#define DIERR_UNPLUGGED 0x80040209L + +/* + * SendDeviceData failed because more information was requested + * to be sent than can be sent to the device. Some devices have + * restrictions on how much data can be sent to them. (For example, + * there might be a limit on the number of buttons that can be + * pressed at once.) + */ +#define DIERR_REPORTFULL 0x8004020AL + + +/* + * A mapper file function failed because reading or writing the user or IHV + * settings file failed. + */ +#define DIERR_MAPFILEFAIL 0x8004020BL + + +/*--- DINPUT Mapper Definitions: New for Dx8 ---*/ + + +/*--- Keyboard + Physical Keyboard Device ---*/ + +#define DIKEYBOARD_ESCAPE 0x81000401 +#define DIKEYBOARD_1 0x81000402 +#define DIKEYBOARD_2 0x81000403 +#define DIKEYBOARD_3 0x81000404 +#define DIKEYBOARD_4 0x81000405 +#define DIKEYBOARD_5 0x81000406 +#define DIKEYBOARD_6 0x81000407 +#define DIKEYBOARD_7 0x81000408 +#define DIKEYBOARD_8 0x81000409 +#define DIKEYBOARD_9 0x8100040A +#define DIKEYBOARD_0 0x8100040B +#define DIKEYBOARD_MINUS 0x8100040C /* - on main keyboard */ +#define DIKEYBOARD_EQUALS 0x8100040D +#define DIKEYBOARD_BACK 0x8100040E /* backspace */ +#define DIKEYBOARD_TAB 0x8100040F +#define DIKEYBOARD_Q 0x81000410 +#define DIKEYBOARD_W 0x81000411 +#define DIKEYBOARD_E 0x81000412 +#define DIKEYBOARD_R 0x81000413 +#define DIKEYBOARD_T 0x81000414 +#define DIKEYBOARD_Y 0x81000415 +#define DIKEYBOARD_U 0x81000416 +#define DIKEYBOARD_I 0x81000417 +#define DIKEYBOARD_O 0x81000418 +#define DIKEYBOARD_P 0x81000419 +#define DIKEYBOARD_LBRACKET 0x8100041A +#define DIKEYBOARD_RBRACKET 0x8100041B +#define DIKEYBOARD_RETURN 0x8100041C /* Enter on main keyboard */ +#define DIKEYBOARD_LCONTROL 0x8100041D +#define DIKEYBOARD_A 0x8100041E +#define DIKEYBOARD_S 0x8100041F +#define DIKEYBOARD_D 0x81000420 +#define DIKEYBOARD_F 0x81000421 +#define DIKEYBOARD_G 0x81000422 +#define DIKEYBOARD_H 0x81000423 +#define DIKEYBOARD_J 0x81000424 +#define DIKEYBOARD_K 0x81000425 +#define DIKEYBOARD_L 0x81000426 +#define DIKEYBOARD_SEMICOLON 0x81000427 +#define DIKEYBOARD_APOSTROPHE 0x81000428 +#define DIKEYBOARD_GRAVE 0x81000429 /* accent grave */ +#define DIKEYBOARD_LSHIFT 0x8100042A +#define DIKEYBOARD_BACKSLASH 0x8100042B +#define DIKEYBOARD_Z 0x8100042C +#define DIKEYBOARD_X 0x8100042D +#define DIKEYBOARD_C 0x8100042E +#define DIKEYBOARD_V 0x8100042F +#define DIKEYBOARD_B 0x81000430 +#define DIKEYBOARD_N 0x81000431 +#define DIKEYBOARD_M 0x81000432 +#define DIKEYBOARD_COMMA 0x81000433 +#define DIKEYBOARD_PERIOD 0x81000434 /* . on main keyboard */ +#define DIKEYBOARD_SLASH 0x81000435 /* / on main keyboard */ +#define DIKEYBOARD_RSHIFT 0x81000436 +#define DIKEYBOARD_MULTIPLY 0x81000437 /* * on numeric keypad */ +#define DIKEYBOARD_LMENU 0x81000438 /* left Alt */ +#define DIKEYBOARD_SPACE 0x81000439 +#define DIKEYBOARD_CAPITAL 0x8100043A +#define DIKEYBOARD_F1 0x8100043B +#define DIKEYBOARD_F2 0x8100043C +#define DIKEYBOARD_F3 0x8100043D +#define DIKEYBOARD_F4 0x8100043E +#define DIKEYBOARD_F5 0x8100043F +#define DIKEYBOARD_F6 0x81000440 +#define DIKEYBOARD_F7 0x81000441 +#define DIKEYBOARD_F8 0x81000442 +#define DIKEYBOARD_F9 0x81000443 +#define DIKEYBOARD_F10 0x81000444 +#define DIKEYBOARD_NUMLOCK 0x81000445 +#define DIKEYBOARD_SCROLL 0x81000446 /* Scroll Lock */ +#define DIKEYBOARD_NUMPAD7 0x81000447 +#define DIKEYBOARD_NUMPAD8 0x81000448 +#define DIKEYBOARD_NUMPAD9 0x81000449 +#define DIKEYBOARD_SUBTRACT 0x8100044A /* - on numeric keypad */ +#define DIKEYBOARD_NUMPAD4 0x8100044B +#define DIKEYBOARD_NUMPAD5 0x8100044C +#define DIKEYBOARD_NUMPAD6 0x8100044D +#define DIKEYBOARD_ADD 0x8100044E /* + on numeric keypad */ +#define DIKEYBOARD_NUMPAD1 0x8100044F +#define DIKEYBOARD_NUMPAD2 0x81000450 +#define DIKEYBOARD_NUMPAD3 0x81000451 +#define DIKEYBOARD_NUMPAD0 0x81000452 +#define DIKEYBOARD_DECIMAL 0x81000453 /* . on numeric keypad */ +#define DIKEYBOARD_OEM_102 0x81000456 /* <> or \| on RT 102-key keyboard (Non-U.S.) */ +#define DIKEYBOARD_F11 0x81000457 +#define DIKEYBOARD_F12 0x81000458 +#define DIKEYBOARD_F13 0x81000464 /* (NEC PC98) */ +#define DIKEYBOARD_F14 0x81000465 /* (NEC PC98) */ +#define DIKEYBOARD_F15 0x81000466 /* (NEC PC98) */ +#define DIKEYBOARD_KANA 0x81000470 /* (Japanese keyboard) */ +#define DIKEYBOARD_ABNT_C1 0x81000473 /* /? on Brazilian keyboard */ +#define DIKEYBOARD_CONVERT 0x81000479 /* (Japanese keyboard) */ +#define DIKEYBOARD_NOCONVERT 0x8100047B /* (Japanese keyboard) */ +#define DIKEYBOARD_YEN 0x8100047D /* (Japanese keyboard) */ +#define DIKEYBOARD_ABNT_C2 0x8100047E /* Numpad . on Brazilian keyboard */ +#define DIKEYBOARD_NUMPADEQUALS 0x8100048D /* = on numeric keypad (NEC PC98) */ +#define DIKEYBOARD_PREVTRACK 0x81000490 /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */ +#define DIKEYBOARD_AT 0x81000491 /* (NEC PC98) */ +#define DIKEYBOARD_COLON 0x81000492 /* (NEC PC98) */ +#define DIKEYBOARD_UNDERLINE 0x81000493 /* (NEC PC98) */ +#define DIKEYBOARD_KANJI 0x81000494 /* (Japanese keyboard) */ +#define DIKEYBOARD_STOP 0x81000495 /* (NEC PC98) */ +#define DIKEYBOARD_AX 0x81000496 /* (Japan AX) */ +#define DIKEYBOARD_UNLABELED 0x81000497 /* (J3100) */ +#define DIKEYBOARD_NEXTTRACK 0x81000499 /* Next Track */ +#define DIKEYBOARD_NUMPADENTER 0x8100049C /* Enter on numeric keypad */ +#define DIKEYBOARD_RCONTROL 0x8100049D +#define DIKEYBOARD_MUTE 0x810004A0 /* Mute */ +#define DIKEYBOARD_CALCULATOR 0x810004A1 /* Calculator */ +#define DIKEYBOARD_PLAYPAUSE 0x810004A2 /* Play / Pause */ +#define DIKEYBOARD_MEDIASTOP 0x810004A4 /* Media Stop */ +#define DIKEYBOARD_VOLUMEDOWN 0x810004AE /* Volume - */ +#define DIKEYBOARD_VOLUMEUP 0x810004B0 /* Volume + */ +#define DIKEYBOARD_WEBHOME 0x810004B2 /* Web home */ +#define DIKEYBOARD_NUMPADCOMMA 0x810004B3 /* , on numeric keypad (NEC PC98) */ +#define DIKEYBOARD_DIVIDE 0x810004B5 /* / on numeric keypad */ +#define DIKEYBOARD_SYSRQ 0x810004B7 +#define DIKEYBOARD_RMENU 0x810004B8 /* right Alt */ +#define DIKEYBOARD_PAUSE 0x810004C5 /* Pause */ +#define DIKEYBOARD_HOME 0x810004C7 /* Home on arrow keypad */ +#define DIKEYBOARD_UP 0x810004C8 /* UpArrow on arrow keypad */ +#define DIKEYBOARD_PRIOR 0x810004C9 /* PgUp on arrow keypad */ +#define DIKEYBOARD_LEFT 0x810004CB /* LeftArrow on arrow keypad */ +#define DIKEYBOARD_RIGHT 0x810004CD /* RightArrow on arrow keypad */ +#define DIKEYBOARD_END 0x810004CF /* End on arrow keypad */ +#define DIKEYBOARD_DOWN 0x810004D0 /* DownArrow on arrow keypad */ +#define DIKEYBOARD_NEXT 0x810004D1 /* PgDn on arrow keypad */ +#define DIKEYBOARD_INSERT 0x810004D2 /* Insert on arrow keypad */ +#define DIKEYBOARD_DELETE 0x810004D3 /* Delete on arrow keypad */ +#define DIKEYBOARD_LWIN 0x810004DB /* Left Windows key */ +#define DIKEYBOARD_RWIN 0x810004DC /* Right Windows key */ +#define DIKEYBOARD_APPS 0x810004DD /* AppMenu key */ +#define DIKEYBOARD_POWER 0x810004DE /* System Power */ +#define DIKEYBOARD_SLEEP 0x810004DF /* System Sleep */ +#define DIKEYBOARD_WAKE 0x810004E3 /* System Wake */ +#define DIKEYBOARD_WEBSEARCH 0x810004E5 /* Web Search */ +#define DIKEYBOARD_WEBFAVORITES 0x810004E6 /* Web Favorites */ +#define DIKEYBOARD_WEBREFRESH 0x810004E7 /* Web Refresh */ +#define DIKEYBOARD_WEBSTOP 0x810004E8 /* Web Stop */ +#define DIKEYBOARD_WEBFORWARD 0x810004E9 /* Web Forward */ +#define DIKEYBOARD_WEBBACK 0x810004EA /* Web Back */ +#define DIKEYBOARD_MYCOMPUTER 0x810004EB /* My Computer */ +#define DIKEYBOARD_MAIL 0x810004EC /* Mail */ +#define DIKEYBOARD_MEDIASELECT 0x810004ED /* Media Select */ + + +/*--- MOUSE + Physical Mouse Device ---*/ + +#define DIMOUSE_XAXISAB (0x82000200 |DIMOFS_X ) /* X Axis-absolute: Some mice natively report absolute coordinates */ +#define DIMOUSE_YAXISAB (0x82000200 |DIMOFS_Y ) /* Y Axis-absolute: Some mice natively report absolute coordinates */ +#define DIMOUSE_XAXIS (0x82000300 |DIMOFS_X ) /* X Axis */ +#define DIMOUSE_YAXIS (0x82000300 |DIMOFS_Y ) /* Y Axis */ +#define DIMOUSE_WHEEL (0x82000300 |DIMOFS_Z ) /* Z Axis */ +#define DIMOUSE_BUTTON0 (0x82000400 |DIMOFS_BUTTON0) /* Button 0 */ +#define DIMOUSE_BUTTON1 (0x82000400 |DIMOFS_BUTTON1) /* Button 1 */ +#define DIMOUSE_BUTTON2 (0x82000400 |DIMOFS_BUTTON2) /* Button 2 */ +#define DIMOUSE_BUTTON3 (0x82000400 |DIMOFS_BUTTON3) /* Button 3 */ +#define DIMOUSE_BUTTON4 (0x82000400 |DIMOFS_BUTTON4) /* Button 4 */ +#define DIMOUSE_BUTTON5 (0x82000400 |DIMOFS_BUTTON5) /* Button 5 */ +#define DIMOUSE_BUTTON6 (0x82000400 |DIMOFS_BUTTON6) /* Button 6 */ +#define DIMOUSE_BUTTON7 (0x82000400 |DIMOFS_BUTTON7) /* Button 7 */ + + +/*--- VOICE + Physical Dplay Voice Device ---*/ + +#define DIVOICE_CHANNEL1 0x83000401 +#define DIVOICE_CHANNEL2 0x83000402 +#define DIVOICE_CHANNEL3 0x83000403 +#define DIVOICE_CHANNEL4 0x83000404 +#define DIVOICE_CHANNEL5 0x83000405 +#define DIVOICE_CHANNEL6 0x83000406 +#define DIVOICE_CHANNEL7 0x83000407 +#define DIVOICE_CHANNEL8 0x83000408 +#define DIVOICE_TEAM 0x83000409 +#define DIVOICE_ALL 0x8300040A +#define DIVOICE_RECORDMUTE 0x8300040B +#define DIVOICE_PLAYBACKMUTE 0x8300040C +#define DIVOICE_TRANSMIT 0x8300040D + +#define DIVOICE_VOICECOMMAND 0x83000410 + + +/*--- Driving Simulator - Racing + Vehicle control is primary objective ---*/ +#define DIVIRTUAL_DRIVING_RACE 0x01000000 +#define DIAXIS_DRIVINGR_STEER 0x01008A01 /* Steering */ +#define DIAXIS_DRIVINGR_ACCELERATE 0x01039202 /* Accelerate */ +#define DIAXIS_DRIVINGR_BRAKE 0x01041203 /* Brake-Axis */ +#define DIBUTTON_DRIVINGR_SHIFTUP 0x01000C01 /* Shift to next higher gear */ +#define DIBUTTON_DRIVINGR_SHIFTDOWN 0x01000C02 /* Shift to next lower gear */ +#define DIBUTTON_DRIVINGR_VIEW 0x01001C03 /* Cycle through view options */ +#define DIBUTTON_DRIVINGR_MENU 0x010004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIAXIS_DRIVINGR_ACCEL_AND_BRAKE 0x01014A04 /* Some devices combine accelerate and brake in a single axis */ +#define DIHATSWITCH_DRIVINGR_GLANCE 0x01004601 /* Look around */ +#define DIBUTTON_DRIVINGR_BRAKE 0x01004C04 /* Brake-button */ +#define DIBUTTON_DRIVINGR_DASHBOARD 0x01004405 /* Select next dashboard option */ +#define DIBUTTON_DRIVINGR_AIDS 0x01004406 /* Driver correction aids */ +#define DIBUTTON_DRIVINGR_MAP 0x01004407 /* Display Driving Map */ +#define DIBUTTON_DRIVINGR_BOOST 0x01004408 /* Turbo Boost */ +#define DIBUTTON_DRIVINGR_PIT 0x01004409 /* Pit stop notification */ +#define DIBUTTON_DRIVINGR_ACCELERATE_LINK 0x0103D4E0 /* Fallback Accelerate button */ +#define DIBUTTON_DRIVINGR_STEER_LEFT_LINK 0x0100CCE4 /* Fallback Steer Left button */ +#define DIBUTTON_DRIVINGR_STEER_RIGHT_LINK 0x0100CCEC /* Fallback Steer Right button */ +#define DIBUTTON_DRIVINGR_GLANCE_LEFT_LINK 0x0107C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_DRIVINGR_GLANCE_RIGHT_LINK 0x0107C4EC /* Fallback Glance Right button */ +#define DIBUTTON_DRIVINGR_DEVICE 0x010044FE /* Show input device and controls */ +#define DIBUTTON_DRIVINGR_PAUSE 0x010044FC /* Start / Pause / Restart game */ + +/*--- Driving Simulator - Combat + Combat from within a vehicle is primary objective ---*/ +#define DIVIRTUAL_DRIVING_COMBAT 0x02000000 +#define DIAXIS_DRIVINGC_STEER 0x02008A01 /* Steering */ +#define DIAXIS_DRIVINGC_ACCELERATE 0x02039202 /* Accelerate */ +#define DIAXIS_DRIVINGC_BRAKE 0x02041203 /* Brake-axis */ +#define DIBUTTON_DRIVINGC_FIRE 0x02000C01 /* Fire */ +#define DIBUTTON_DRIVINGC_WEAPONS 0x02000C02 /* Select next weapon */ +#define DIBUTTON_DRIVINGC_TARGET 0x02000C03 /* Select next available target */ +#define DIBUTTON_DRIVINGC_MENU 0x020004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIAXIS_DRIVINGC_ACCEL_AND_BRAKE 0x02014A04 /* Some devices combine accelerate and brake in a single axis */ +#define DIHATSWITCH_DRIVINGC_GLANCE 0x02004601 /* Look around */ +#define DIBUTTON_DRIVINGC_SHIFTUP 0x02004C04 /* Shift to next higher gear */ +#define DIBUTTON_DRIVINGC_SHIFTDOWN 0x02004C05 /* Shift to next lower gear */ +#define DIBUTTON_DRIVINGC_DASHBOARD 0x02004406 /* Select next dashboard option */ +#define DIBUTTON_DRIVINGC_AIDS 0x02004407 /* Driver correction aids */ +#define DIBUTTON_DRIVINGC_BRAKE 0x02004C08 /* Brake-button */ +#define DIBUTTON_DRIVINGC_FIRESECONDARY 0x02004C09 /* Alternative fire button */ +#define DIBUTTON_DRIVINGC_ACCELERATE_LINK 0x0203D4E0 /* Fallback Accelerate button */ +#define DIBUTTON_DRIVINGC_STEER_LEFT_LINK 0x0200CCE4 /* Fallback Steer Left button */ +#define DIBUTTON_DRIVINGC_STEER_RIGHT_LINK 0x0200CCEC /* Fallback Steer Right button */ +#define DIBUTTON_DRIVINGC_GLANCE_LEFT_LINK 0x0207C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_DRIVINGC_GLANCE_RIGHT_LINK 0x0207C4EC /* Fallback Glance Right button */ +#define DIBUTTON_DRIVINGC_DEVICE 0x020044FE /* Show input device and controls */ +#define DIBUTTON_DRIVINGC_PAUSE 0x020044FC /* Start / Pause / Restart game */ + +/*--- Driving Simulator - Tank + Combat from withing a tank is primary objective ---*/ +#define DIVIRTUAL_DRIVING_TANK 0x03000000 +#define DIAXIS_DRIVINGT_STEER 0x03008A01 /* Turn tank left / right */ +#define DIAXIS_DRIVINGT_BARREL 0x03010202 /* Raise / lower barrel */ +#define DIAXIS_DRIVINGT_ACCELERATE 0x03039203 /* Accelerate */ +#define DIAXIS_DRIVINGT_ROTATE 0x03020204 /* Turn barrel left / right */ +#define DIBUTTON_DRIVINGT_FIRE 0x03000C01 /* Fire */ +#define DIBUTTON_DRIVINGT_WEAPONS 0x03000C02 /* Select next weapon */ +#define DIBUTTON_DRIVINGT_TARGET 0x03000C03 /* Selects next available target */ +#define DIBUTTON_DRIVINGT_MENU 0x030004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_DRIVINGT_GLANCE 0x03004601 /* Look around */ +#define DIAXIS_DRIVINGT_BRAKE 0x03045205 /* Brake-axis */ +#define DIAXIS_DRIVINGT_ACCEL_AND_BRAKE 0x03014A06 /* Some devices combine accelerate and brake in a single axis */ +#define DIBUTTON_DRIVINGT_VIEW 0x03005C04 /* Cycle through view options */ +#define DIBUTTON_DRIVINGT_DASHBOARD 0x03005C05 /* Select next dashboard option */ +#define DIBUTTON_DRIVINGT_BRAKE 0x03004C06 /* Brake-button */ +#define DIBUTTON_DRIVINGT_FIRESECONDARY 0x03004C07 /* Alternative fire button */ +#define DIBUTTON_DRIVINGT_ACCELERATE_LINK 0x0303D4E0 /* Fallback Accelerate button */ +#define DIBUTTON_DRIVINGT_STEER_LEFT_LINK 0x0300CCE4 /* Fallback Steer Left button */ +#define DIBUTTON_DRIVINGT_STEER_RIGHT_LINK 0x0300CCEC /* Fallback Steer Right button */ +#define DIBUTTON_DRIVINGT_BARREL_UP_LINK 0x030144E0 /* Fallback Barrel up button */ +#define DIBUTTON_DRIVINGT_BARREL_DOWN_LINK 0x030144E8 /* Fallback Barrel down button */ +#define DIBUTTON_DRIVINGT_ROTATE_LEFT_LINK 0x030244E4 /* Fallback Rotate left button */ +#define DIBUTTON_DRIVINGT_ROTATE_RIGHT_LINK 0x030244EC /* Fallback Rotate right button */ +#define DIBUTTON_DRIVINGT_GLANCE_LEFT_LINK 0x0307C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_DRIVINGT_GLANCE_RIGHT_LINK 0x0307C4EC /* Fallback Glance Right button */ +#define DIBUTTON_DRIVINGT_DEVICE 0x030044FE /* Show input device and controls */ +#define DIBUTTON_DRIVINGT_PAUSE 0x030044FC /* Start / Pause / Restart game */ + +/*--- Flight Simulator - Civilian + Plane control is the primary objective ---*/ +#define DIVIRTUAL_FLYING_CIVILIAN 0x04000000 +#define DIAXIS_FLYINGC_BANK 0x04008A01 /* Roll ship left / right */ +#define DIAXIS_FLYINGC_PITCH 0x04010A02 /* Nose up / down */ +#define DIAXIS_FLYINGC_THROTTLE 0x04039203 /* Throttle */ +#define DIBUTTON_FLYINGC_VIEW 0x04002401 /* Cycle through view options */ +#define DIBUTTON_FLYINGC_DISPLAY 0x04002402 /* Select next dashboard / heads up display option */ +#define DIBUTTON_FLYINGC_GEAR 0x04002C03 /* Gear up / down */ +#define DIBUTTON_FLYINGC_MENU 0x040004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_FLYINGC_GLANCE 0x04004601 /* Look around */ +#define DIAXIS_FLYINGC_BRAKE 0x04046A04 /* Apply Brake */ +#define DIAXIS_FLYINGC_RUDDER 0x04025205 /* Yaw ship left/right */ +#define DIAXIS_FLYINGC_FLAPS 0x04055A06 /* Flaps */ +#define DIBUTTON_FLYINGC_FLAPSUP 0x04006404 /* Increment stepping up until fully retracted */ +#define DIBUTTON_FLYINGC_FLAPSDOWN 0x04006405 /* Decrement stepping down until fully extended */ +#define DIBUTTON_FLYINGC_BRAKE_LINK 0x04046CE0 /* Fallback brake button */ +#define DIBUTTON_FLYINGC_FASTER_LINK 0x0403D4E0 /* Fallback throttle up button */ +#define DIBUTTON_FLYINGC_SLOWER_LINK 0x0403D4E8 /* Fallback throttle down button */ +#define DIBUTTON_FLYINGC_GLANCE_LEFT_LINK 0x0407C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_FLYINGC_GLANCE_RIGHT_LINK 0x0407C4EC /* Fallback Glance Right button */ +#define DIBUTTON_FLYINGC_GLANCE_UP_LINK 0x0407C4E0 /* Fallback Glance Up button */ +#define DIBUTTON_FLYINGC_GLANCE_DOWN_LINK 0x0407C4E8 /* Fallback Glance Down button */ +#define DIBUTTON_FLYINGC_DEVICE 0x040044FE /* Show input device and controls */ +#define DIBUTTON_FLYINGC_PAUSE 0x040044FC /* Start / Pause / Restart game */ + +/*--- Flight Simulator - Military + Aerial combat is the primary objective ---*/ +#define DIVIRTUAL_FLYING_MILITARY 0x05000000 +#define DIAXIS_FLYINGM_BANK 0x05008A01 /* Bank - Roll ship left / right */ +#define DIAXIS_FLYINGM_PITCH 0x05010A02 /* Pitch - Nose up / down */ +#define DIAXIS_FLYINGM_THROTTLE 0x05039203 /* Throttle - faster / slower */ +#define DIBUTTON_FLYINGM_FIRE 0x05000C01 /* Fire */ +#define DIBUTTON_FLYINGM_WEAPONS 0x05000C02 /* Select next weapon */ +#define DIBUTTON_FLYINGM_TARGET 0x05000C03 /* Selects next available target */ +#define DIBUTTON_FLYINGM_MENU 0x050004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_FLYINGM_GLANCE 0x05004601 /* Look around */ +#define DIBUTTON_FLYINGM_COUNTER 0x05005C04 /* Activate counter measures */ +#define DIAXIS_FLYINGM_RUDDER 0x05024A04 /* Rudder - Yaw ship left/right */ +#define DIAXIS_FLYINGM_BRAKE 0x05046205 /* Brake-axis */ +#define DIBUTTON_FLYINGM_VIEW 0x05006405 /* Cycle through view options */ +#define DIBUTTON_FLYINGM_DISPLAY 0x05006406 /* Select next dashboard option */ +#define DIAXIS_FLYINGM_FLAPS 0x05055206 /* Flaps */ +#define DIBUTTON_FLYINGM_FLAPSUP 0x05005407 /* Increment stepping up until fully retracted */ +#define DIBUTTON_FLYINGM_FLAPSDOWN 0x05005408 /* Decrement stepping down until fully extended */ +#define DIBUTTON_FLYINGM_FIRESECONDARY 0x05004C09 /* Alternative fire button */ +#define DIBUTTON_FLYINGM_GEAR 0x0500640A /* Gear up / down */ +#define DIBUTTON_FLYINGM_BRAKE_LINK 0x050464E0 /* Fallback brake button */ +#define DIBUTTON_FLYINGM_FASTER_LINK 0x0503D4E0 /* Fallback throttle up button */ +#define DIBUTTON_FLYINGM_SLOWER_LINK 0x0503D4E8 /* Fallback throttle down button */ +#define DIBUTTON_FLYINGM_GLANCE_LEFT_LINK 0x0507C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_FLYINGM_GLANCE_RIGHT_LINK 0x0507C4EC /* Fallback Glance Right button */ +#define DIBUTTON_FLYINGM_GLANCE_UP_LINK 0x0507C4E0 /* Fallback Glance Up button */ +#define DIBUTTON_FLYINGM_GLANCE_DOWN_LINK 0x0507C4E8 /* Fallback Glance Down button */ +#define DIBUTTON_FLYINGM_DEVICE 0x050044FE /* Show input device and controls */ +#define DIBUTTON_FLYINGM_PAUSE 0x050044FC /* Start / Pause / Restart game */ + +/*--- Flight Simulator - Combat Helicopter + Combat from helicopter is primary objective ---*/ +#define DIVIRTUAL_FLYING_HELICOPTER 0x06000000 +#define DIAXIS_FLYINGH_BANK 0x06008A01 /* Bank - Roll ship left / right */ +#define DIAXIS_FLYINGH_PITCH 0x06010A02 /* Pitch - Nose up / down */ +#define DIAXIS_FLYINGH_COLLECTIVE 0x06018A03 /* Collective - Blade pitch/power */ +#define DIBUTTON_FLYINGH_FIRE 0x06001401 /* Fire */ +#define DIBUTTON_FLYINGH_WEAPONS 0x06001402 /* Select next weapon */ +#define DIBUTTON_FLYINGH_TARGET 0x06001403 /* Selects next available target */ +#define DIBUTTON_FLYINGH_MENU 0x060004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_FLYINGH_GLANCE 0x06004601 /* Look around */ +#define DIAXIS_FLYINGH_TORQUE 0x06025A04 /* Torque - Rotate ship around left / right axis */ +#define DIAXIS_FLYINGH_THROTTLE 0x0603DA05 /* Throttle */ +#define DIBUTTON_FLYINGH_COUNTER 0x06005404 /* Activate counter measures */ +#define DIBUTTON_FLYINGH_VIEW 0x06006405 /* Cycle through view options */ +#define DIBUTTON_FLYINGH_GEAR 0x06006406 /* Gear up / down */ +#define DIBUTTON_FLYINGH_FIRESECONDARY 0x06004C07 /* Alternative fire button */ +#define DIBUTTON_FLYINGH_FASTER_LINK 0x0603DCE0 /* Fallback throttle up button */ +#define DIBUTTON_FLYINGH_SLOWER_LINK 0x0603DCE8 /* Fallback throttle down button */ +#define DIBUTTON_FLYINGH_GLANCE_LEFT_LINK 0x0607C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_FLYINGH_GLANCE_RIGHT_LINK 0x0607C4EC /* Fallback Glance Right button */ +#define DIBUTTON_FLYINGH_GLANCE_UP_LINK 0x0607C4E0 /* Fallback Glance Up button */ +#define DIBUTTON_FLYINGH_GLANCE_DOWN_LINK 0x0607C4E8 /* Fallback Glance Down button */ +#define DIBUTTON_FLYINGH_DEVICE 0x060044FE /* Show input device and controls */ +#define DIBUTTON_FLYINGH_PAUSE 0x060044FC /* Start / Pause / Restart game */ + +/*--- Space Simulator - Combat + Space Simulator with weapons ---*/ +#define DIVIRTUAL_SPACESIM 0x07000000 +#define DIAXIS_SPACESIM_LATERAL 0x07008201 /* Move ship left / right */ +#define DIAXIS_SPACESIM_MOVE 0x07010202 /* Move ship forward/backward */ +#define DIAXIS_SPACESIM_THROTTLE 0x07038203 /* Throttle - Engine speed */ +#define DIBUTTON_SPACESIM_FIRE 0x07000401 /* Fire */ +#define DIBUTTON_SPACESIM_WEAPONS 0x07000402 /* Select next weapon */ +#define DIBUTTON_SPACESIM_TARGET 0x07000403 /* Selects next available target */ +#define DIBUTTON_SPACESIM_MENU 0x070004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_SPACESIM_GLANCE 0x07004601 /* Look around */ +#define DIAXIS_SPACESIM_CLIMB 0x0701C204 /* Climb - Pitch ship up/down */ +#define DIAXIS_SPACESIM_ROTATE 0x07024205 /* Rotate - Turn ship left/right */ +#define DIBUTTON_SPACESIM_VIEW 0x07004404 /* Cycle through view options */ +#define DIBUTTON_SPACESIM_DISPLAY 0x07004405 /* Select next dashboard / heads up display option */ +#define DIBUTTON_SPACESIM_RAISE 0x07004406 /* Raise ship while maintaining current pitch */ +#define DIBUTTON_SPACESIM_LOWER 0x07004407 /* Lower ship while maintaining current pitch */ +#define DIBUTTON_SPACESIM_GEAR 0x07004408 /* Gear up / down */ +#define DIBUTTON_SPACESIM_FIRESECONDARY 0x07004409 /* Alternative fire button */ +#define DIBUTTON_SPACESIM_LEFT_LINK 0x0700C4E4 /* Fallback move left button */ +#define DIBUTTON_SPACESIM_RIGHT_LINK 0x0700C4EC /* Fallback move right button */ +#define DIBUTTON_SPACESIM_FORWARD_LINK 0x070144E0 /* Fallback move forward button */ +#define DIBUTTON_SPACESIM_BACKWARD_LINK 0x070144E8 /* Fallback move backwards button */ +#define DIBUTTON_SPACESIM_FASTER_LINK 0x0703C4E0 /* Fallback throttle up button */ +#define DIBUTTON_SPACESIM_SLOWER_LINK 0x0703C4E8 /* Fallback throttle down button */ +#define DIBUTTON_SPACESIM_TURN_LEFT_LINK 0x070244E4 /* Fallback turn left button */ +#define DIBUTTON_SPACESIM_TURN_RIGHT_LINK 0x070244EC /* Fallback turn right button */ +#define DIBUTTON_SPACESIM_GLANCE_LEFT_LINK 0x0707C4E4 /* Fallback Glance Left button */ +#define DIBUTTON_SPACESIM_GLANCE_RIGHT_LINK 0x0707C4EC /* Fallback Glance Right button */ +#define DIBUTTON_SPACESIM_GLANCE_UP_LINK 0x0707C4E0 /* Fallback Glance Up button */ +#define DIBUTTON_SPACESIM_GLANCE_DOWN_LINK 0x0707C4E8 /* Fallback Glance Down button */ +#define DIBUTTON_SPACESIM_DEVICE 0x070044FE /* Show input device and controls */ +#define DIBUTTON_SPACESIM_PAUSE 0x070044FC /* Start / Pause / Restart game */ + +/*--- Fighting - First Person + Hand to Hand combat is primary objective ---*/ +#define DIVIRTUAL_FIGHTING_HAND2HAND 0x08000000 +#define DIAXIS_FIGHTINGH_LATERAL 0x08008201 /* Sidestep left/right */ +#define DIAXIS_FIGHTINGH_MOVE 0x08010202 /* Move forward/backward */ +#define DIBUTTON_FIGHTINGH_PUNCH 0x08000401 /* Punch */ +#define DIBUTTON_FIGHTINGH_KICK 0x08000402 /* Kick */ +#define DIBUTTON_FIGHTINGH_BLOCK 0x08000403 /* Block */ +#define DIBUTTON_FIGHTINGH_CROUCH 0x08000404 /* Crouch */ +#define DIBUTTON_FIGHTINGH_JUMP 0x08000405 /* Jump */ +#define DIBUTTON_FIGHTINGH_SPECIAL1 0x08000406 /* Apply first special move */ +#define DIBUTTON_FIGHTINGH_SPECIAL2 0x08000407 /* Apply second special move */ +#define DIBUTTON_FIGHTINGH_MENU 0x080004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_FIGHTINGH_SELECT 0x08004408 /* Select special move */ +#define DIHATSWITCH_FIGHTINGH_SLIDE 0x08004601 /* Look around */ +#define DIBUTTON_FIGHTINGH_DISPLAY 0x08004409 /* Shows next on-screen display option */ +#define DIAXIS_FIGHTINGH_ROTATE 0x08024203 /* Rotate - Turn body left/right */ +#define DIBUTTON_FIGHTINGH_DODGE 0x0800440A /* Dodge */ +#define DIBUTTON_FIGHTINGH_LEFT_LINK 0x0800C4E4 /* Fallback left sidestep button */ +#define DIBUTTON_FIGHTINGH_RIGHT_LINK 0x0800C4EC /* Fallback right sidestep button */ +#define DIBUTTON_FIGHTINGH_FORWARD_LINK 0x080144E0 /* Fallback forward button */ +#define DIBUTTON_FIGHTINGH_BACKWARD_LINK 0x080144E8 /* Fallback backward button */ +#define DIBUTTON_FIGHTINGH_DEVICE 0x080044FE /* Show input device and controls */ +#define DIBUTTON_FIGHTINGH_PAUSE 0x080044FC /* Start / Pause / Restart game */ + +/*--- Fighting - First Person Shooting + Navigation and combat are primary objectives ---*/ +#define DIVIRTUAL_FIGHTING_FPS 0x09000000 +#define DIAXIS_FPS_ROTATE 0x09008201 /* Rotate character left/right */ +#define DIAXIS_FPS_MOVE 0x09010202 /* Move forward/backward */ +#define DIBUTTON_FPS_FIRE 0x09000401 /* Fire */ +#define DIBUTTON_FPS_WEAPONS 0x09000402 /* Select next weapon */ +#define DIBUTTON_FPS_APPLY 0x09000403 /* Use item */ +#define DIBUTTON_FPS_SELECT 0x09000404 /* Select next inventory item */ +#define DIBUTTON_FPS_CROUCH 0x09000405 /* Crouch/ climb down/ swim down */ +#define DIBUTTON_FPS_JUMP 0x09000406 /* Jump/ climb up/ swim up */ +#define DIAXIS_FPS_LOOKUPDOWN 0x09018203 /* Look up / down */ +#define DIBUTTON_FPS_STRAFE 0x09000407 /* Enable strafing while active */ +#define DIBUTTON_FPS_MENU 0x090004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_FPS_GLANCE 0x09004601 /* Look around */ +#define DIBUTTON_FPS_DISPLAY 0x09004408 /* Shows next on-screen display option/ map */ +#define DIAXIS_FPS_SIDESTEP 0x09024204 /* Sidestep */ +#define DIBUTTON_FPS_DODGE 0x09004409 /* Dodge */ +#define DIBUTTON_FPS_GLANCEL 0x0900440A /* Glance Left */ +#define DIBUTTON_FPS_GLANCER 0x0900440B /* Glance Right */ +#define DIBUTTON_FPS_FIRESECONDARY 0x0900440C /* Alternative fire button */ +#define DIBUTTON_FPS_ROTATE_LEFT_LINK 0x0900C4E4 /* Fallback rotate left button */ +#define DIBUTTON_FPS_ROTATE_RIGHT_LINK 0x0900C4EC /* Fallback rotate right button */ +#define DIBUTTON_FPS_FORWARD_LINK 0x090144E0 /* Fallback forward button */ +#define DIBUTTON_FPS_BACKWARD_LINK 0x090144E8 /* Fallback backward button */ +#define DIBUTTON_FPS_GLANCE_UP_LINK 0x0901C4E0 /* Fallback look up button */ +#define DIBUTTON_FPS_GLANCE_DOWN_LINK 0x0901C4E8 /* Fallback look down button */ +#define DIBUTTON_FPS_STEP_LEFT_LINK 0x090244E4 /* Fallback step left button */ +#define DIBUTTON_FPS_STEP_RIGHT_LINK 0x090244EC /* Fallback step right button */ +#define DIBUTTON_FPS_DEVICE 0x090044FE /* Show input device and controls */ +#define DIBUTTON_FPS_PAUSE 0x090044FC /* Start / Pause / Restart game */ + +/*--- Fighting - Third Person action + Perspective of camera is behind the main character ---*/ +#define DIVIRTUAL_FIGHTING_THIRDPERSON 0x0A000000 +#define DIAXIS_TPS_TURN 0x0A020201 /* Turn left/right */ +#define DIAXIS_TPS_MOVE 0x0A010202 /* Move forward/backward */ +#define DIBUTTON_TPS_RUN 0x0A000401 /* Run or walk toggle switch */ +#define DIBUTTON_TPS_ACTION 0x0A000402 /* Action Button */ +#define DIBUTTON_TPS_SELECT 0x0A000403 /* Select next weapon */ +#define DIBUTTON_TPS_USE 0x0A000404 /* Use inventory item currently selected */ +#define DIBUTTON_TPS_JUMP 0x0A000405 /* Character Jumps */ +#define DIBUTTON_TPS_MENU 0x0A0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_TPS_GLANCE 0x0A004601 /* Look around */ +#define DIBUTTON_TPS_VIEW 0x0A004406 /* Select camera view */ +#define DIBUTTON_TPS_STEPLEFT 0x0A004407 /* Character takes a left step */ +#define DIBUTTON_TPS_STEPRIGHT 0x0A004408 /* Character takes a right step */ +#define DIAXIS_TPS_STEP 0x0A00C203 /* Character steps left/right */ +#define DIBUTTON_TPS_DODGE 0x0A004409 /* Character dodges or ducks */ +#define DIBUTTON_TPS_INVENTORY 0x0A00440A /* Cycle through inventory */ +#define DIBUTTON_TPS_TURN_LEFT_LINK 0x0A0244E4 /* Fallback turn left button */ +#define DIBUTTON_TPS_TURN_RIGHT_LINK 0x0A0244EC /* Fallback turn right button */ +#define DIBUTTON_TPS_FORWARD_LINK 0x0A0144E0 /* Fallback forward button */ +#define DIBUTTON_TPS_BACKWARD_LINK 0x0A0144E8 /* Fallback backward button */ +#define DIBUTTON_TPS_GLANCE_UP_LINK 0x0A07C4E0 /* Fallback look up button */ +#define DIBUTTON_TPS_GLANCE_DOWN_LINK 0x0A07C4E8 /* Fallback look down button */ +#define DIBUTTON_TPS_GLANCE_LEFT_LINK 0x0A07C4E4 /* Fallback glance up button */ +#define DIBUTTON_TPS_GLANCE_RIGHT_LINK 0x0A07C4EC /* Fallback glance right button */ +#define DIBUTTON_TPS_DEVICE 0x0A0044FE /* Show input device and controls */ +#define DIBUTTON_TPS_PAUSE 0x0A0044FC /* Start / Pause / Restart game */ + +/*--- Strategy - Role Playing + Navigation and problem solving are primary actions ---*/ +#define DIVIRTUAL_STRATEGY_ROLEPLAYING 0x0B000000 +#define DIAXIS_STRATEGYR_LATERAL 0x0B008201 /* sidestep - left/right */ +#define DIAXIS_STRATEGYR_MOVE 0x0B010202 /* move forward/backward */ +#define DIBUTTON_STRATEGYR_GET 0x0B000401 /* Acquire item */ +#define DIBUTTON_STRATEGYR_APPLY 0x0B000402 /* Use selected item */ +#define DIBUTTON_STRATEGYR_SELECT 0x0B000403 /* Select nextitem */ +#define DIBUTTON_STRATEGYR_ATTACK 0x0B000404 /* Attack */ +#define DIBUTTON_STRATEGYR_CAST 0x0B000405 /* Cast Spell */ +#define DIBUTTON_STRATEGYR_CROUCH 0x0B000406 /* Crouch */ +#define DIBUTTON_STRATEGYR_JUMP 0x0B000407 /* Jump */ +#define DIBUTTON_STRATEGYR_MENU 0x0B0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_STRATEGYR_GLANCE 0x0B004601 /* Look around */ +#define DIBUTTON_STRATEGYR_MAP 0x0B004408 /* Cycle through map options */ +#define DIBUTTON_STRATEGYR_DISPLAY 0x0B004409 /* Shows next on-screen display option */ +#define DIAXIS_STRATEGYR_ROTATE 0x0B024203 /* Turn body left/right */ +#define DIBUTTON_STRATEGYR_LEFT_LINK 0x0B00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_STRATEGYR_RIGHT_LINK 0x0B00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_STRATEGYR_FORWARD_LINK 0x0B0144E0 /* Fallback move forward button */ +#define DIBUTTON_STRATEGYR_BACK_LINK 0x0B0144E8 /* Fallback move backward button */ +#define DIBUTTON_STRATEGYR_ROTATE_LEFT_LINK 0x0B0244E4 /* Fallback turn body left button */ +#define DIBUTTON_STRATEGYR_ROTATE_RIGHT_LINK 0x0B0244EC /* Fallback turn body right button */ +#define DIBUTTON_STRATEGYR_DEVICE 0x0B0044FE /* Show input device and controls */ +#define DIBUTTON_STRATEGYR_PAUSE 0x0B0044FC /* Start / Pause / Restart game */ + +/*--- Strategy - Turn based + Navigation and problem solving are primary actions ---*/ +#define DIVIRTUAL_STRATEGY_TURN 0x0C000000 +#define DIAXIS_STRATEGYT_LATERAL 0x0C008201 /* Sidestep left/right */ +#define DIAXIS_STRATEGYT_MOVE 0x0C010202 /* Move forward/backwards */ +#define DIBUTTON_STRATEGYT_SELECT 0x0C000401 /* Select unit or object */ +#define DIBUTTON_STRATEGYT_INSTRUCT 0x0C000402 /* Cycle through instructions */ +#define DIBUTTON_STRATEGYT_APPLY 0x0C000403 /* Apply selected instruction */ +#define DIBUTTON_STRATEGYT_TEAM 0x0C000404 /* Select next team / cycle through all */ +#define DIBUTTON_STRATEGYT_TURN 0x0C000405 /* Indicate turn over */ +#define DIBUTTON_STRATEGYT_MENU 0x0C0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_STRATEGYT_ZOOM 0x0C004406 /* Zoom - in / out */ +#define DIBUTTON_STRATEGYT_MAP 0x0C004407 /* cycle through map options */ +#define DIBUTTON_STRATEGYT_DISPLAY 0x0C004408 /* shows next on-screen display options */ +#define DIBUTTON_STRATEGYT_LEFT_LINK 0x0C00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_STRATEGYT_RIGHT_LINK 0x0C00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_STRATEGYT_FORWARD_LINK 0x0C0144E0 /* Fallback move forward button */ +#define DIBUTTON_STRATEGYT_BACK_LINK 0x0C0144E8 /* Fallback move back button */ +#define DIBUTTON_STRATEGYT_DEVICE 0x0C0044FE /* Show input device and controls */ +#define DIBUTTON_STRATEGYT_PAUSE 0x0C0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Hunting + Hunting ---*/ +#define DIVIRTUAL_SPORTS_HUNTING 0x0D000000 +#define DIAXIS_HUNTING_LATERAL 0x0D008201 /* sidestep left/right */ +#define DIAXIS_HUNTING_MOVE 0x0D010202 /* move forward/backwards */ +#define DIBUTTON_HUNTING_FIRE 0x0D000401 /* Fire selected weapon */ +#define DIBUTTON_HUNTING_AIM 0x0D000402 /* Select aim/move */ +#define DIBUTTON_HUNTING_WEAPON 0x0D000403 /* Select next weapon */ +#define DIBUTTON_HUNTING_BINOCULAR 0x0D000404 /* Look through Binoculars */ +#define DIBUTTON_HUNTING_CALL 0x0D000405 /* Make animal call */ +#define DIBUTTON_HUNTING_MAP 0x0D000406 /* View Map */ +#define DIBUTTON_HUNTING_SPECIAL 0x0D000407 /* Special game operation */ +#define DIBUTTON_HUNTING_MENU 0x0D0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_HUNTING_GLANCE 0x0D004601 /* Look around */ +#define DIBUTTON_HUNTING_DISPLAY 0x0D004408 /* show next on-screen display option */ +#define DIAXIS_HUNTING_ROTATE 0x0D024203 /* Turn body left/right */ +#define DIBUTTON_HUNTING_CROUCH 0x0D004409 /* Crouch/ Climb / Swim down */ +#define DIBUTTON_HUNTING_JUMP 0x0D00440A /* Jump/ Climb up / Swim up */ +#define DIBUTTON_HUNTING_FIRESECONDARY 0x0D00440B /* Alternative fire button */ +#define DIBUTTON_HUNTING_LEFT_LINK 0x0D00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_HUNTING_RIGHT_LINK 0x0D00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_HUNTING_FORWARD_LINK 0x0D0144E0 /* Fallback move forward button */ +#define DIBUTTON_HUNTING_BACK_LINK 0x0D0144E8 /* Fallback move back button */ +#define DIBUTTON_HUNTING_ROTATE_LEFT_LINK 0x0D0244E4 /* Fallback turn body left button */ +#define DIBUTTON_HUNTING_ROTATE_RIGHT_LINK 0x0D0244EC /* Fallback turn body right button */ +#define DIBUTTON_HUNTING_DEVICE 0x0D0044FE /* Show input device and controls */ +#define DIBUTTON_HUNTING_PAUSE 0x0D0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Fishing + Catching Fish is primary objective ---*/ +#define DIVIRTUAL_SPORTS_FISHING 0x0E000000 +#define DIAXIS_FISHING_LATERAL 0x0E008201 /* sidestep left/right */ +#define DIAXIS_FISHING_MOVE 0x0E010202 /* move forward/backwards */ +#define DIBUTTON_FISHING_CAST 0x0E000401 /* Cast line */ +#define DIBUTTON_FISHING_TYPE 0x0E000402 /* Select cast type */ +#define DIBUTTON_FISHING_BINOCULAR 0x0E000403 /* Look through Binocular */ +#define DIBUTTON_FISHING_BAIT 0x0E000404 /* Select type of Bait */ +#define DIBUTTON_FISHING_MAP 0x0E000405 /* View Map */ +#define DIBUTTON_FISHING_MENU 0x0E0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_FISHING_GLANCE 0x0E004601 /* Look around */ +#define DIBUTTON_FISHING_DISPLAY 0x0E004406 /* Show next on-screen display option */ +#define DIAXIS_FISHING_ROTATE 0x0E024203 /* Turn character left / right */ +#define DIBUTTON_FISHING_CROUCH 0x0E004407 /* Crouch/ Climb / Swim down */ +#define DIBUTTON_FISHING_JUMP 0x0E004408 /* Jump/ Climb up / Swim up */ +#define DIBUTTON_FISHING_LEFT_LINK 0x0E00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_FISHING_RIGHT_LINK 0x0E00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_FISHING_FORWARD_LINK 0x0E0144E0 /* Fallback move forward button */ +#define DIBUTTON_FISHING_BACK_LINK 0x0E0144E8 /* Fallback move back button */ +#define DIBUTTON_FISHING_ROTATE_LEFT_LINK 0x0E0244E4 /* Fallback turn body left button */ +#define DIBUTTON_FISHING_ROTATE_RIGHT_LINK 0x0E0244EC /* Fallback turn body right button */ +#define DIBUTTON_FISHING_DEVICE 0x0E0044FE /* Show input device and controls */ +#define DIBUTTON_FISHING_PAUSE 0x0E0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Baseball - Batting + Batter control is primary objective ---*/ +#define DIVIRTUAL_SPORTS_BASEBALL_BAT 0x0F000000 +#define DIAXIS_BASEBALLB_LATERAL 0x0F008201 /* Aim left / right */ +#define DIAXIS_BASEBALLB_MOVE 0x0F010202 /* Aim up / down */ +#define DIBUTTON_BASEBALLB_SELECT 0x0F000401 /* cycle through swing options */ +#define DIBUTTON_BASEBALLB_NORMAL 0x0F000402 /* normal swing */ +#define DIBUTTON_BASEBALLB_POWER 0x0F000403 /* swing for the fence */ +#define DIBUTTON_BASEBALLB_BUNT 0x0F000404 /* bunt */ +#define DIBUTTON_BASEBALLB_STEAL 0x0F000405 /* Base runner attempts to steal a base */ +#define DIBUTTON_BASEBALLB_BURST 0x0F000406 /* Base runner invokes burst of speed */ +#define DIBUTTON_BASEBALLB_SLIDE 0x0F000407 /* Base runner slides into base */ +#define DIBUTTON_BASEBALLB_CONTACT 0x0F000408 /* Contact swing */ +#define DIBUTTON_BASEBALLB_MENU 0x0F0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_BASEBALLB_NOSTEAL 0x0F004409 /* Base runner goes back to a base */ +#define DIBUTTON_BASEBALLB_BOX 0x0F00440A /* Enter or exit batting box */ +#define DIBUTTON_BASEBALLB_LEFT_LINK 0x0F00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_BASEBALLB_RIGHT_LINK 0x0F00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_BASEBALLB_FORWARD_LINK 0x0F0144E0 /* Fallback move forward button */ +#define DIBUTTON_BASEBALLB_BACK_LINK 0x0F0144E8 /* Fallback move back button */ +#define DIBUTTON_BASEBALLB_DEVICE 0x0F0044FE /* Show input device and controls */ +#define DIBUTTON_BASEBALLB_PAUSE 0x0F0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Baseball - Pitching + Pitcher control is primary objective ---*/ +#define DIVIRTUAL_SPORTS_BASEBALL_PITCH 0x10000000 +#define DIAXIS_BASEBALLP_LATERAL 0x10008201 /* Aim left / right */ +#define DIAXIS_BASEBALLP_MOVE 0x10010202 /* Aim up / down */ +#define DIBUTTON_BASEBALLP_SELECT 0x10000401 /* cycle through pitch selections */ +#define DIBUTTON_BASEBALLP_PITCH 0x10000402 /* throw pitch */ +#define DIBUTTON_BASEBALLP_BASE 0x10000403 /* select base to throw to */ +#define DIBUTTON_BASEBALLP_THROW 0x10000404 /* throw to base */ +#define DIBUTTON_BASEBALLP_FAKE 0x10000405 /* Fake a throw to a base */ +#define DIBUTTON_BASEBALLP_MENU 0x100004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_BASEBALLP_WALK 0x10004406 /* Throw intentional walk / pitch out */ +#define DIBUTTON_BASEBALLP_LOOK 0x10004407 /* Look at runners on bases */ +#define DIBUTTON_BASEBALLP_LEFT_LINK 0x1000C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_BASEBALLP_RIGHT_LINK 0x1000C4EC /* Fallback sidestep right button */ +#define DIBUTTON_BASEBALLP_FORWARD_LINK 0x100144E0 /* Fallback move forward button */ +#define DIBUTTON_BASEBALLP_BACK_LINK 0x100144E8 /* Fallback move back button */ +#define DIBUTTON_BASEBALLP_DEVICE 0x100044FE /* Show input device and controls */ +#define DIBUTTON_BASEBALLP_PAUSE 0x100044FC /* Start / Pause / Restart game */ + +/*--- Sports - Baseball - Fielding + Fielder control is primary objective ---*/ +#define DIVIRTUAL_SPORTS_BASEBALL_FIELD 0x11000000 +#define DIAXIS_BASEBALLF_LATERAL 0x11008201 /* Aim left / right */ +#define DIAXIS_BASEBALLF_MOVE 0x11010202 /* Aim up / down */ +#define DIBUTTON_BASEBALLF_NEAREST 0x11000401 /* Switch to fielder nearest to the ball */ +#define DIBUTTON_BASEBALLF_THROW1 0x11000402 /* Make conservative throw */ +#define DIBUTTON_BASEBALLF_THROW2 0x11000403 /* Make aggressive throw */ +#define DIBUTTON_BASEBALLF_BURST 0x11000404 /* Invoke burst of speed */ +#define DIBUTTON_BASEBALLF_JUMP 0x11000405 /* Jump to catch ball */ +#define DIBUTTON_BASEBALLF_DIVE 0x11000406 /* Dive to catch ball */ +#define DIBUTTON_BASEBALLF_MENU 0x110004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_BASEBALLF_SHIFTIN 0x11004407 /* Shift the infield positioning */ +#define DIBUTTON_BASEBALLF_SHIFTOUT 0x11004408 /* Shift the outfield positioning */ +#define DIBUTTON_BASEBALLF_AIM_LEFT_LINK 0x1100C4E4 /* Fallback aim left button */ +#define DIBUTTON_BASEBALLF_AIM_RIGHT_LINK 0x1100C4EC /* Fallback aim right button */ +#define DIBUTTON_BASEBALLF_FORWARD_LINK 0x110144E0 /* Fallback move forward button */ +#define DIBUTTON_BASEBALLF_BACK_LINK 0x110144E8 /* Fallback move back button */ +#define DIBUTTON_BASEBALLF_DEVICE 0x110044FE /* Show input device and controls */ +#define DIBUTTON_BASEBALLF_PAUSE 0x110044FC /* Start / Pause / Restart game */ + +/*--- Sports - Basketball - Offense + Offense ---*/ +#define DIVIRTUAL_SPORTS_BASKETBALL_OFFENSE 0x12000000 +#define DIAXIS_BBALLO_LATERAL 0x12008201 /* left / right */ +#define DIAXIS_BBALLO_MOVE 0x12010202 /* up / down */ +#define DIBUTTON_BBALLO_SHOOT 0x12000401 /* shoot basket */ +#define DIBUTTON_BBALLO_DUNK 0x12000402 /* dunk basket */ +#define DIBUTTON_BBALLO_PASS 0x12000403 /* throw pass */ +#define DIBUTTON_BBALLO_FAKE 0x12000404 /* fake shot or pass */ +#define DIBUTTON_BBALLO_SPECIAL 0x12000405 /* apply special move */ +#define DIBUTTON_BBALLO_PLAYER 0x12000406 /* select next player */ +#define DIBUTTON_BBALLO_BURST 0x12000407 /* invoke burst */ +#define DIBUTTON_BBALLO_CALL 0x12000408 /* call for ball / pass to me */ +#define DIBUTTON_BBALLO_MENU 0x120004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_BBALLO_GLANCE 0x12004601 /* scroll view */ +#define DIBUTTON_BBALLO_SCREEN 0x12004409 /* Call for screen */ +#define DIBUTTON_BBALLO_PLAY 0x1200440A /* Call for specific offensive play */ +#define DIBUTTON_BBALLO_JAB 0x1200440B /* Initiate fake drive to basket */ +#define DIBUTTON_BBALLO_POST 0x1200440C /* Perform post move */ +#define DIBUTTON_BBALLO_TIMEOUT 0x1200440D /* Time Out */ +#define DIBUTTON_BBALLO_SUBSTITUTE 0x1200440E /* substitute one player for another */ +#define DIBUTTON_BBALLO_LEFT_LINK 0x1200C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_BBALLO_RIGHT_LINK 0x1200C4EC /* Fallback sidestep right button */ +#define DIBUTTON_BBALLO_FORWARD_LINK 0x120144E0 /* Fallback move forward button */ +#define DIBUTTON_BBALLO_BACK_LINK 0x120144E8 /* Fallback move back button */ +#define DIBUTTON_BBALLO_DEVICE 0x120044FE /* Show input device and controls */ +#define DIBUTTON_BBALLO_PAUSE 0x120044FC /* Start / Pause / Restart game */ + +/*--- Sports - Basketball - Defense + Defense ---*/ +#define DIVIRTUAL_SPORTS_BASKETBALL_DEFENSE 0x13000000 +#define DIAXIS_BBALLD_LATERAL 0x13008201 /* left / right */ +#define DIAXIS_BBALLD_MOVE 0x13010202 /* up / down */ +#define DIBUTTON_BBALLD_JUMP 0x13000401 /* jump to block shot */ +#define DIBUTTON_BBALLD_STEAL 0x13000402 /* attempt to steal ball */ +#define DIBUTTON_BBALLD_FAKE 0x13000403 /* fake block or steal */ +#define DIBUTTON_BBALLD_SPECIAL 0x13000404 /* apply special move */ +#define DIBUTTON_BBALLD_PLAYER 0x13000405 /* select next player */ +#define DIBUTTON_BBALLD_BURST 0x13000406 /* invoke burst */ +#define DIBUTTON_BBALLD_PLAY 0x13000407 /* call for specific defensive play */ +#define DIBUTTON_BBALLD_MENU 0x130004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_BBALLD_GLANCE 0x13004601 /* scroll view */ +#define DIBUTTON_BBALLD_TIMEOUT 0x13004408 /* Time Out */ +#define DIBUTTON_BBALLD_SUBSTITUTE 0x13004409 /* substitute one player for another */ +#define DIBUTTON_BBALLD_LEFT_LINK 0x1300C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_BBALLD_RIGHT_LINK 0x1300C4EC /* Fallback sidestep right button */ +#define DIBUTTON_BBALLD_FORWARD_LINK 0x130144E0 /* Fallback move forward button */ +#define DIBUTTON_BBALLD_BACK_LINK 0x130144E8 /* Fallback move back button */ +#define DIBUTTON_BBALLD_DEVICE 0x130044FE /* Show input device and controls */ +#define DIBUTTON_BBALLD_PAUSE 0x130044FC /* Start / Pause / Restart game */ + +/*--- Sports - Football - Play + Play selection ---*/ +#define DIVIRTUAL_SPORTS_FOOTBALL_FIELD 0x14000000 +#define DIBUTTON_FOOTBALLP_PLAY 0x14000401 /* cycle through available plays */ +#define DIBUTTON_FOOTBALLP_SELECT 0x14000402 /* select play */ +#define DIBUTTON_FOOTBALLP_HELP 0x14000403 /* Bring up pop-up help */ +#define DIBUTTON_FOOTBALLP_MENU 0x140004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_FOOTBALLP_DEVICE 0x140044FE /* Show input device and controls */ +#define DIBUTTON_FOOTBALLP_PAUSE 0x140044FC /* Start / Pause / Restart game */ + +/*--- Sports - Football - QB + Offense: Quarterback / Kicker ---*/ +#define DIVIRTUAL_SPORTS_FOOTBALL_QBCK 0x15000000 +#define DIAXIS_FOOTBALLQ_LATERAL 0x15008201 /* Move / Aim: left / right */ +#define DIAXIS_FOOTBALLQ_MOVE 0x15010202 /* Move / Aim: up / down */ +#define DIBUTTON_FOOTBALLQ_SELECT 0x15000401 /* Select */ +#define DIBUTTON_FOOTBALLQ_SNAP 0x15000402 /* snap ball - start play */ +#define DIBUTTON_FOOTBALLQ_JUMP 0x15000403 /* jump over defender */ +#define DIBUTTON_FOOTBALLQ_SLIDE 0x15000404 /* Dive/Slide */ +#define DIBUTTON_FOOTBALLQ_PASS 0x15000405 /* throws pass to receiver */ +#define DIBUTTON_FOOTBALLQ_FAKE 0x15000406 /* pump fake pass or fake kick */ +#define DIBUTTON_FOOTBALLQ_MENU 0x150004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_FOOTBALLQ_FAKESNAP 0x15004407 /* Fake snap */ +#define DIBUTTON_FOOTBALLQ_MOTION 0x15004408 /* Send receivers in motion */ +#define DIBUTTON_FOOTBALLQ_AUDIBLE 0x15004409 /* Change offensive play at line of scrimmage */ +#define DIBUTTON_FOOTBALLQ_LEFT_LINK 0x1500C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_FOOTBALLQ_RIGHT_LINK 0x1500C4EC /* Fallback sidestep right button */ +#define DIBUTTON_FOOTBALLQ_FORWARD_LINK 0x150144E0 /* Fallback move forward button */ +#define DIBUTTON_FOOTBALLQ_BACK_LINK 0x150144E8 /* Fallback move back button */ +#define DIBUTTON_FOOTBALLQ_DEVICE 0x150044FE /* Show input device and controls */ +#define DIBUTTON_FOOTBALLQ_PAUSE 0x150044FC /* Start / Pause / Restart game */ + +/*--- Sports - Football - Offense + Offense - Runner ---*/ +#define DIVIRTUAL_SPORTS_FOOTBALL_OFFENSE 0x16000000 +#define DIAXIS_FOOTBALLO_LATERAL 0x16008201 /* Move / Aim: left / right */ +#define DIAXIS_FOOTBALLO_MOVE 0x16010202 /* Move / Aim: up / down */ +#define DIBUTTON_FOOTBALLO_JUMP 0x16000401 /* jump or hurdle over defender */ +#define DIBUTTON_FOOTBALLO_LEFTARM 0x16000402 /* holds out left arm */ +#define DIBUTTON_FOOTBALLO_RIGHTARM 0x16000403 /* holds out right arm */ +#define DIBUTTON_FOOTBALLO_THROW 0x16000404 /* throw pass or lateral ball to another runner */ +#define DIBUTTON_FOOTBALLO_SPIN 0x16000405 /* Spin to avoid defenders */ +#define DIBUTTON_FOOTBALLO_MENU 0x160004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_FOOTBALLO_JUKE 0x16004406 /* Use special move to avoid defenders */ +#define DIBUTTON_FOOTBALLO_SHOULDER 0x16004407 /* Lower shoulder to run over defenders */ +#define DIBUTTON_FOOTBALLO_TURBO 0x16004408 /* Speed burst past defenders */ +#define DIBUTTON_FOOTBALLO_DIVE 0x16004409 /* Dive over defenders */ +#define DIBUTTON_FOOTBALLO_ZOOM 0x1600440A /* Zoom view in / out */ +#define DIBUTTON_FOOTBALLO_SUBSTITUTE 0x1600440B /* substitute one player for another */ +#define DIBUTTON_FOOTBALLO_LEFT_LINK 0x1600C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_FOOTBALLO_RIGHT_LINK 0x1600C4EC /* Fallback sidestep right button */ +#define DIBUTTON_FOOTBALLO_FORWARD_LINK 0x160144E0 /* Fallback move forward button */ +#define DIBUTTON_FOOTBALLO_BACK_LINK 0x160144E8 /* Fallback move back button */ +#define DIBUTTON_FOOTBALLO_DEVICE 0x160044FE /* Show input device and controls */ +#define DIBUTTON_FOOTBALLO_PAUSE 0x160044FC /* Start / Pause / Restart game */ + +/*--- Sports - Football - Defense + Defense ---*/ +#define DIVIRTUAL_SPORTS_FOOTBALL_DEFENSE 0x17000000 +#define DIAXIS_FOOTBALLD_LATERAL 0x17008201 /* Move / Aim: left / right */ +#define DIAXIS_FOOTBALLD_MOVE 0x17010202 /* Move / Aim: up / down */ +#define DIBUTTON_FOOTBALLD_PLAY 0x17000401 /* cycle through available plays */ +#define DIBUTTON_FOOTBALLD_SELECT 0x17000402 /* select player closest to the ball */ +#define DIBUTTON_FOOTBALLD_JUMP 0x17000403 /* jump to intercept or block */ +#define DIBUTTON_FOOTBALLD_TACKLE 0x17000404 /* tackler runner */ +#define DIBUTTON_FOOTBALLD_FAKE 0x17000405 /* hold down to fake tackle or intercept */ +#define DIBUTTON_FOOTBALLD_SUPERTACKLE 0x17000406 /* Initiate special tackle */ +#define DIBUTTON_FOOTBALLD_MENU 0x170004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_FOOTBALLD_SPIN 0x17004407 /* Spin to beat offensive line */ +#define DIBUTTON_FOOTBALLD_SWIM 0x17004408 /* Swim to beat the offensive line */ +#define DIBUTTON_FOOTBALLD_BULLRUSH 0x17004409 /* Bull rush the offensive line */ +#define DIBUTTON_FOOTBALLD_RIP 0x1700440A /* Rip the offensive line */ +#define DIBUTTON_FOOTBALLD_AUDIBLE 0x1700440B /* Change defensive play at the line of scrimmage */ +#define DIBUTTON_FOOTBALLD_ZOOM 0x1700440C /* Zoom view in / out */ +#define DIBUTTON_FOOTBALLD_SUBSTITUTE 0x1700440D /* substitute one player for another */ +#define DIBUTTON_FOOTBALLD_LEFT_LINK 0x1700C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_FOOTBALLD_RIGHT_LINK 0x1700C4EC /* Fallback sidestep right button */ +#define DIBUTTON_FOOTBALLD_FORWARD_LINK 0x170144E0 /* Fallback move forward button */ +#define DIBUTTON_FOOTBALLD_BACK_LINK 0x170144E8 /* Fallback move back button */ +#define DIBUTTON_FOOTBALLD_DEVICE 0x170044FE /* Show input device and controls */ +#define DIBUTTON_FOOTBALLD_PAUSE 0x170044FC /* Start / Pause / Restart game */ + +/*--- Sports - Golf + ---*/ +#define DIVIRTUAL_SPORTS_GOLF 0x18000000 +#define DIAXIS_GOLF_LATERAL 0x18008201 /* Move / Aim: left / right */ +#define DIAXIS_GOLF_MOVE 0x18010202 /* Move / Aim: up / down */ +#define DIBUTTON_GOLF_SWING 0x18000401 /* swing club */ +#define DIBUTTON_GOLF_SELECT 0x18000402 /* cycle between: club / swing strength / ball arc / ball spin */ +#define DIBUTTON_GOLF_UP 0x18000403 /* increase selection */ +#define DIBUTTON_GOLF_DOWN 0x18000404 /* decrease selection */ +#define DIBUTTON_GOLF_TERRAIN 0x18000405 /* shows terrain detail */ +#define DIBUTTON_GOLF_FLYBY 0x18000406 /* view the hole via a flyby */ +#define DIBUTTON_GOLF_MENU 0x180004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_GOLF_SCROLL 0x18004601 /* scroll view */ +#define DIBUTTON_GOLF_ZOOM 0x18004407 /* Zoom view in / out */ +#define DIBUTTON_GOLF_TIMEOUT 0x18004408 /* Call for time out */ +#define DIBUTTON_GOLF_SUBSTITUTE 0x18004409 /* substitute one player for another */ +#define DIBUTTON_GOLF_LEFT_LINK 0x1800C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_GOLF_RIGHT_LINK 0x1800C4EC /* Fallback sidestep right button */ +#define DIBUTTON_GOLF_FORWARD_LINK 0x180144E0 /* Fallback move forward button */ +#define DIBUTTON_GOLF_BACK_LINK 0x180144E8 /* Fallback move back button */ +#define DIBUTTON_GOLF_DEVICE 0x180044FE /* Show input device and controls */ +#define DIBUTTON_GOLF_PAUSE 0x180044FC /* Start / Pause / Restart game */ + +/*--- Sports - Hockey - Offense + Offense ---*/ +#define DIVIRTUAL_SPORTS_HOCKEY_OFFENSE 0x19000000 +#define DIAXIS_HOCKEYO_LATERAL 0x19008201 /* Move / Aim: left / right */ +#define DIAXIS_HOCKEYO_MOVE 0x19010202 /* Move / Aim: up / down */ +#define DIBUTTON_HOCKEYO_SHOOT 0x19000401 /* Shoot */ +#define DIBUTTON_HOCKEYO_PASS 0x19000402 /* pass the puck */ +#define DIBUTTON_HOCKEYO_BURST 0x19000403 /* invoke speed burst */ +#define DIBUTTON_HOCKEYO_SPECIAL 0x19000404 /* invoke special move */ +#define DIBUTTON_HOCKEYO_FAKE 0x19000405 /* hold down to fake pass or kick */ +#define DIBUTTON_HOCKEYO_MENU 0x190004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_HOCKEYO_SCROLL 0x19004601 /* scroll view */ +#define DIBUTTON_HOCKEYO_ZOOM 0x19004406 /* Zoom view in / out */ +#define DIBUTTON_HOCKEYO_STRATEGY 0x19004407 /* Invoke coaching menu for strategy help */ +#define DIBUTTON_HOCKEYO_TIMEOUT 0x19004408 /* Call for time out */ +#define DIBUTTON_HOCKEYO_SUBSTITUTE 0x19004409 /* substitute one player for another */ +#define DIBUTTON_HOCKEYO_LEFT_LINK 0x1900C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_HOCKEYO_RIGHT_LINK 0x1900C4EC /* Fallback sidestep right button */ +#define DIBUTTON_HOCKEYO_FORWARD_LINK 0x190144E0 /* Fallback move forward button */ +#define DIBUTTON_HOCKEYO_BACK_LINK 0x190144E8 /* Fallback move back button */ +#define DIBUTTON_HOCKEYO_DEVICE 0x190044FE /* Show input device and controls */ +#define DIBUTTON_HOCKEYO_PAUSE 0x190044FC /* Start / Pause / Restart game */ + +/*--- Sports - Hockey - Defense + Defense ---*/ +#define DIVIRTUAL_SPORTS_HOCKEY_DEFENSE 0x1A000000 +#define DIAXIS_HOCKEYD_LATERAL 0x1A008201 /* Move / Aim: left / right */ +#define DIAXIS_HOCKEYD_MOVE 0x1A010202 /* Move / Aim: up / down */ +#define DIBUTTON_HOCKEYD_PLAYER 0x1A000401 /* control player closest to the puck */ +#define DIBUTTON_HOCKEYD_STEAL 0x1A000402 /* attempt steal */ +#define DIBUTTON_HOCKEYD_BURST 0x1A000403 /* speed burst or body check */ +#define DIBUTTON_HOCKEYD_BLOCK 0x1A000404 /* block puck */ +#define DIBUTTON_HOCKEYD_FAKE 0x1A000405 /* hold down to fake tackle or intercept */ +#define DIBUTTON_HOCKEYD_MENU 0x1A0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_HOCKEYD_SCROLL 0x1A004601 /* scroll view */ +#define DIBUTTON_HOCKEYD_ZOOM 0x1A004406 /* Zoom view in / out */ +#define DIBUTTON_HOCKEYD_STRATEGY 0x1A004407 /* Invoke coaching menu for strategy help */ +#define DIBUTTON_HOCKEYD_TIMEOUT 0x1A004408 /* Call for time out */ +#define DIBUTTON_HOCKEYD_SUBSTITUTE 0x1A004409 /* substitute one player for another */ +#define DIBUTTON_HOCKEYD_LEFT_LINK 0x1A00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_HOCKEYD_RIGHT_LINK 0x1A00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_HOCKEYD_FORWARD_LINK 0x1A0144E0 /* Fallback move forward button */ +#define DIBUTTON_HOCKEYD_BACK_LINK 0x1A0144E8 /* Fallback move back button */ +#define DIBUTTON_HOCKEYD_DEVICE 0x1A0044FE /* Show input device and controls */ +#define DIBUTTON_HOCKEYD_PAUSE 0x1A0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Hockey - Goalie + Goal tending ---*/ +#define DIVIRTUAL_SPORTS_HOCKEY_GOALIE 0x1B000000 +#define DIAXIS_HOCKEYG_LATERAL 0x1B008201 /* Move / Aim: left / right */ +#define DIAXIS_HOCKEYG_MOVE 0x1B010202 /* Move / Aim: up / down */ +#define DIBUTTON_HOCKEYG_PASS 0x1B000401 /* pass puck */ +#define DIBUTTON_HOCKEYG_POKE 0x1B000402 /* poke / check / hack */ +#define DIBUTTON_HOCKEYG_STEAL 0x1B000403 /* attempt steal */ +#define DIBUTTON_HOCKEYG_BLOCK 0x1B000404 /* block puck */ +#define DIBUTTON_HOCKEYG_MENU 0x1B0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_HOCKEYG_SCROLL 0x1B004601 /* scroll view */ +#define DIBUTTON_HOCKEYG_ZOOM 0x1B004405 /* Zoom view in / out */ +#define DIBUTTON_HOCKEYG_STRATEGY 0x1B004406 /* Invoke coaching menu for strategy help */ +#define DIBUTTON_HOCKEYG_TIMEOUT 0x1B004407 /* Call for time out */ +#define DIBUTTON_HOCKEYG_SUBSTITUTE 0x1B004408 /* substitute one player for another */ +#define DIBUTTON_HOCKEYG_LEFT_LINK 0x1B00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_HOCKEYG_RIGHT_LINK 0x1B00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_HOCKEYG_FORWARD_LINK 0x1B0144E0 /* Fallback move forward button */ +#define DIBUTTON_HOCKEYG_BACK_LINK 0x1B0144E8 /* Fallback move back button */ +#define DIBUTTON_HOCKEYG_DEVICE 0x1B0044FE /* Show input device and controls */ +#define DIBUTTON_HOCKEYG_PAUSE 0x1B0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Mountain Biking + ---*/ +#define DIVIRTUAL_SPORTS_BIKING_MOUNTAIN 0x1C000000 +#define DIAXIS_BIKINGM_TURN 0x1C008201 /* left / right */ +#define DIAXIS_BIKINGM_PEDAL 0x1C010202 /* Pedal faster / slower / brake */ +#define DIBUTTON_BIKINGM_JUMP 0x1C000401 /* jump over obstacle */ +#define DIBUTTON_BIKINGM_CAMERA 0x1C000402 /* switch camera view */ +#define DIBUTTON_BIKINGM_SPECIAL1 0x1C000403 /* perform first special move */ +#define DIBUTTON_BIKINGM_SELECT 0x1C000404 /* Select */ +#define DIBUTTON_BIKINGM_SPECIAL2 0x1C000405 /* perform second special move */ +#define DIBUTTON_BIKINGM_MENU 0x1C0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_BIKINGM_SCROLL 0x1C004601 /* scroll view */ +#define DIBUTTON_BIKINGM_ZOOM 0x1C004406 /* Zoom view in / out */ +#define DIAXIS_BIKINGM_BRAKE 0x1C044203 /* Brake axis */ +#define DIBUTTON_BIKINGM_LEFT_LINK 0x1C00C4E4 /* Fallback turn left button */ +#define DIBUTTON_BIKINGM_RIGHT_LINK 0x1C00C4EC /* Fallback turn right button */ +#define DIBUTTON_BIKINGM_FASTER_LINK 0x1C0144E0 /* Fallback pedal faster button */ +#define DIBUTTON_BIKINGM_SLOWER_LINK 0x1C0144E8 /* Fallback pedal slower button */ +#define DIBUTTON_BIKINGM_BRAKE_BUTTON_LINK 0x1C0444E8 /* Fallback brake button */ +#define DIBUTTON_BIKINGM_DEVICE 0x1C0044FE /* Show input device and controls */ +#define DIBUTTON_BIKINGM_PAUSE 0x1C0044FC /* Start / Pause / Restart game */ + +/*--- Sports: Skiing / Snowboarding / Skateboarding + ---*/ +#define DIVIRTUAL_SPORTS_SKIING 0x1D000000 +#define DIAXIS_SKIING_TURN 0x1D008201 /* left / right */ +#define DIAXIS_SKIING_SPEED 0x1D010202 /* faster / slower */ +#define DIBUTTON_SKIING_JUMP 0x1D000401 /* Jump */ +#define DIBUTTON_SKIING_CROUCH 0x1D000402 /* crouch down */ +#define DIBUTTON_SKIING_CAMERA 0x1D000403 /* switch camera view */ +#define DIBUTTON_SKIING_SPECIAL1 0x1D000404 /* perform first special move */ +#define DIBUTTON_SKIING_SELECT 0x1D000405 /* Select */ +#define DIBUTTON_SKIING_SPECIAL2 0x1D000406 /* perform second special move */ +#define DIBUTTON_SKIING_MENU 0x1D0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_SKIING_GLANCE 0x1D004601 /* scroll view */ +#define DIBUTTON_SKIING_ZOOM 0x1D004407 /* Zoom view in / out */ +#define DIBUTTON_SKIING_LEFT_LINK 0x1D00C4E4 /* Fallback turn left button */ +#define DIBUTTON_SKIING_RIGHT_LINK 0x1D00C4EC /* Fallback turn right button */ +#define DIBUTTON_SKIING_FASTER_LINK 0x1D0144E0 /* Fallback increase speed button */ +#define DIBUTTON_SKIING_SLOWER_LINK 0x1D0144E8 /* Fallback decrease speed button */ +#define DIBUTTON_SKIING_DEVICE 0x1D0044FE /* Show input device and controls */ +#define DIBUTTON_SKIING_PAUSE 0x1D0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Soccer - Offense + Offense ---*/ +#define DIVIRTUAL_SPORTS_SOCCER_OFFENSE 0x1E000000 +#define DIAXIS_SOCCERO_LATERAL 0x1E008201 /* Move / Aim: left / right */ +#define DIAXIS_SOCCERO_MOVE 0x1E010202 /* Move / Aim: up / down */ +#define DIAXIS_SOCCERO_BEND 0x1E018203 /* Bend to soccer shot/pass */ +#define DIBUTTON_SOCCERO_SHOOT 0x1E000401 /* Shoot the ball */ +#define DIBUTTON_SOCCERO_PASS 0x1E000402 /* Pass */ +#define DIBUTTON_SOCCERO_FAKE 0x1E000403 /* Fake */ +#define DIBUTTON_SOCCERO_PLAYER 0x1E000404 /* Select next player */ +#define DIBUTTON_SOCCERO_SPECIAL1 0x1E000405 /* Apply special move */ +#define DIBUTTON_SOCCERO_SELECT 0x1E000406 /* Select special move */ +#define DIBUTTON_SOCCERO_MENU 0x1E0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_SOCCERO_GLANCE 0x1E004601 /* scroll view */ +#define DIBUTTON_SOCCERO_SUBSTITUTE 0x1E004407 /* Substitute one player for another */ +#define DIBUTTON_SOCCERO_SHOOTLOW 0x1E004408 /* Shoot the ball low */ +#define DIBUTTON_SOCCERO_SHOOTHIGH 0x1E004409 /* Shoot the ball high */ +#define DIBUTTON_SOCCERO_PASSTHRU 0x1E00440A /* Make a thru pass */ +#define DIBUTTON_SOCCERO_SPRINT 0x1E00440B /* Sprint / turbo boost */ +#define DIBUTTON_SOCCERO_CONTROL 0x1E00440C /* Obtain control of the ball */ +#define DIBUTTON_SOCCERO_HEAD 0x1E00440D /* Attempt to head the ball */ +#define DIBUTTON_SOCCERO_LEFT_LINK 0x1E00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_SOCCERO_RIGHT_LINK 0x1E00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_SOCCERO_FORWARD_LINK 0x1E0144E0 /* Fallback move forward button */ +#define DIBUTTON_SOCCERO_BACK_LINK 0x1E0144E8 /* Fallback move back button */ +#define DIBUTTON_SOCCERO_DEVICE 0x1E0044FE /* Show input device and controls */ +#define DIBUTTON_SOCCERO_PAUSE 0x1E0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Soccer - Defense + Defense ---*/ +#define DIVIRTUAL_SPORTS_SOCCER_DEFENSE 0x1F000000 +#define DIAXIS_SOCCERD_LATERAL 0x1F008201 /* Move / Aim: left / right */ +#define DIAXIS_SOCCERD_MOVE 0x1F010202 /* Move / Aim: up / down */ +#define DIBUTTON_SOCCERD_BLOCK 0x1F000401 /* Attempt to block shot */ +#define DIBUTTON_SOCCERD_STEAL 0x1F000402 /* Attempt to steal ball */ +#define DIBUTTON_SOCCERD_FAKE 0x1F000403 /* Fake a block or a steal */ +#define DIBUTTON_SOCCERD_PLAYER 0x1F000404 /* Select next player */ +#define DIBUTTON_SOCCERD_SPECIAL 0x1F000405 /* Apply special move */ +#define DIBUTTON_SOCCERD_SELECT 0x1F000406 /* Select special move */ +#define DIBUTTON_SOCCERD_SLIDE 0x1F000407 /* Attempt a slide tackle */ +#define DIBUTTON_SOCCERD_MENU 0x1F0004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_SOCCERD_GLANCE 0x1F004601 /* scroll view */ +#define DIBUTTON_SOCCERD_FOUL 0x1F004408 /* Initiate a foul / hard-foul */ +#define DIBUTTON_SOCCERD_HEAD 0x1F004409 /* Attempt a Header */ +#define DIBUTTON_SOCCERD_CLEAR 0x1F00440A /* Attempt to clear the ball down the field */ +#define DIBUTTON_SOCCERD_GOALIECHARGE 0x1F00440B /* Make the goalie charge out of the box */ +#define DIBUTTON_SOCCERD_SUBSTITUTE 0x1F00440C /* Substitute one player for another */ +#define DIBUTTON_SOCCERD_LEFT_LINK 0x1F00C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_SOCCERD_RIGHT_LINK 0x1F00C4EC /* Fallback sidestep right button */ +#define DIBUTTON_SOCCERD_FORWARD_LINK 0x1F0144E0 /* Fallback move forward button */ +#define DIBUTTON_SOCCERD_BACK_LINK 0x1F0144E8 /* Fallback move back button */ +#define DIBUTTON_SOCCERD_DEVICE 0x1F0044FE /* Show input device and controls */ +#define DIBUTTON_SOCCERD_PAUSE 0x1F0044FC /* Start / Pause / Restart game */ + +/*--- Sports - Racquet + Tennis - Table-Tennis - Squash ---*/ +#define DIVIRTUAL_SPORTS_RACQUET 0x20000000 +#define DIAXIS_RACQUET_LATERAL 0x20008201 /* Move / Aim: left / right */ +#define DIAXIS_RACQUET_MOVE 0x20010202 /* Move / Aim: up / down */ +#define DIBUTTON_RACQUET_SWING 0x20000401 /* Swing racquet */ +#define DIBUTTON_RACQUET_BACKSWING 0x20000402 /* Swing backhand */ +#define DIBUTTON_RACQUET_SMASH 0x20000403 /* Smash shot */ +#define DIBUTTON_RACQUET_SPECIAL 0x20000404 /* Special shot */ +#define DIBUTTON_RACQUET_SELECT 0x20000405 /* Select special shot */ +#define DIBUTTON_RACQUET_MENU 0x200004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_RACQUET_GLANCE 0x20004601 /* scroll view */ +#define DIBUTTON_RACQUET_TIMEOUT 0x20004406 /* Call for time out */ +#define DIBUTTON_RACQUET_SUBSTITUTE 0x20004407 /* Substitute one player for another */ +#define DIBUTTON_RACQUET_LEFT_LINK 0x2000C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_RACQUET_RIGHT_LINK 0x2000C4EC /* Fallback sidestep right button */ +#define DIBUTTON_RACQUET_FORWARD_LINK 0x200144E0 /* Fallback move forward button */ +#define DIBUTTON_RACQUET_BACK_LINK 0x200144E8 /* Fallback move back button */ +#define DIBUTTON_RACQUET_DEVICE 0x200044FE /* Show input device and controls */ +#define DIBUTTON_RACQUET_PAUSE 0x200044FC /* Start / Pause / Restart game */ + +/*--- Arcade- 2D + Side to Side movement ---*/ +#define DIVIRTUAL_ARCADE_SIDE2SIDE 0x21000000 +#define DIAXIS_ARCADES_LATERAL 0x21008201 /* left / right */ +#define DIAXIS_ARCADES_MOVE 0x21010202 /* up / down */ +#define DIBUTTON_ARCADES_THROW 0x21000401 /* throw object */ +#define DIBUTTON_ARCADES_CARRY 0x21000402 /* carry object */ +#define DIBUTTON_ARCADES_ATTACK 0x21000403 /* attack */ +#define DIBUTTON_ARCADES_SPECIAL 0x21000404 /* apply special move */ +#define DIBUTTON_ARCADES_SELECT 0x21000405 /* select special move */ +#define DIBUTTON_ARCADES_MENU 0x210004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_ARCADES_VIEW 0x21004601 /* scroll view left / right / up / down */ +#define DIBUTTON_ARCADES_LEFT_LINK 0x2100C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_ARCADES_RIGHT_LINK 0x2100C4EC /* Fallback sidestep right button */ +#define DIBUTTON_ARCADES_FORWARD_LINK 0x210144E0 /* Fallback move forward button */ +#define DIBUTTON_ARCADES_BACK_LINK 0x210144E8 /* Fallback move back button */ +#define DIBUTTON_ARCADES_VIEW_UP_LINK 0x2107C4E0 /* Fallback scroll view up button */ +#define DIBUTTON_ARCADES_VIEW_DOWN_LINK 0x2107C4E8 /* Fallback scroll view down button */ +#define DIBUTTON_ARCADES_VIEW_LEFT_LINK 0x2107C4E4 /* Fallback scroll view left button */ +#define DIBUTTON_ARCADES_VIEW_RIGHT_LINK 0x2107C4EC /* Fallback scroll view right button */ +#define DIBUTTON_ARCADES_DEVICE 0x210044FE /* Show input device and controls */ +#define DIBUTTON_ARCADES_PAUSE 0x210044FC /* Start / Pause / Restart game */ + +/*--- Arcade - Platform Game + Character moves around on screen ---*/ +#define DIVIRTUAL_ARCADE_PLATFORM 0x22000000 +#define DIAXIS_ARCADEP_LATERAL 0x22008201 /* Left / right */ +#define DIAXIS_ARCADEP_MOVE 0x22010202 /* Up / down */ +#define DIBUTTON_ARCADEP_JUMP 0x22000401 /* Jump */ +#define DIBUTTON_ARCADEP_FIRE 0x22000402 /* Fire */ +#define DIBUTTON_ARCADEP_CROUCH 0x22000403 /* Crouch */ +#define DIBUTTON_ARCADEP_SPECIAL 0x22000404 /* Apply special move */ +#define DIBUTTON_ARCADEP_SELECT 0x22000405 /* Select special move */ +#define DIBUTTON_ARCADEP_MENU 0x220004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_ARCADEP_VIEW 0x22004601 /* Scroll view */ +#define DIBUTTON_ARCADEP_FIRESECONDARY 0x22004406 /* Alternative fire button */ +#define DIBUTTON_ARCADEP_LEFT_LINK 0x2200C4E4 /* Fallback sidestep left button */ +#define DIBUTTON_ARCADEP_RIGHT_LINK 0x2200C4EC /* Fallback sidestep right button */ +#define DIBUTTON_ARCADEP_FORWARD_LINK 0x220144E0 /* Fallback move forward button */ +#define DIBUTTON_ARCADEP_BACK_LINK 0x220144E8 /* Fallback move back button */ +#define DIBUTTON_ARCADEP_VIEW_UP_LINK 0x2207C4E0 /* Fallback scroll view up button */ +#define DIBUTTON_ARCADEP_VIEW_DOWN_LINK 0x2207C4E8 /* Fallback scroll view down button */ +#define DIBUTTON_ARCADEP_VIEW_LEFT_LINK 0x2207C4E4 /* Fallback scroll view left button */ +#define DIBUTTON_ARCADEP_VIEW_RIGHT_LINK 0x2207C4EC /* Fallback scroll view right button */ +#define DIBUTTON_ARCADEP_DEVICE 0x220044FE /* Show input device and controls */ +#define DIBUTTON_ARCADEP_PAUSE 0x220044FC /* Start / Pause / Restart game */ + +/*--- CAD - 2D Object Control + Controls to select and move objects in 2D ---*/ +#define DIVIRTUAL_CAD_2DCONTROL 0x23000000 +#define DIAXIS_2DCONTROL_LATERAL 0x23008201 /* Move view left / right */ +#define DIAXIS_2DCONTROL_MOVE 0x23010202 /* Move view up / down */ +#define DIAXIS_2DCONTROL_INOUT 0x23018203 /* Zoom - in / out */ +#define DIBUTTON_2DCONTROL_SELECT 0x23000401 /* Select Object */ +#define DIBUTTON_2DCONTROL_SPECIAL1 0x23000402 /* Do first special operation */ +#define DIBUTTON_2DCONTROL_SPECIAL 0x23000403 /* Select special operation */ +#define DIBUTTON_2DCONTROL_SPECIAL2 0x23000404 /* Do second special operation */ +#define DIBUTTON_2DCONTROL_MENU 0x230004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_2DCONTROL_HATSWITCH 0x23004601 /* Hat switch */ +#define DIAXIS_2DCONTROL_ROTATEZ 0x23024204 /* Rotate view clockwise / counterclockwise */ +#define DIBUTTON_2DCONTROL_DISPLAY 0x23004405 /* Shows next on-screen display options */ +#define DIBUTTON_2DCONTROL_DEVICE 0x230044FE /* Show input device and controls */ +#define DIBUTTON_2DCONTROL_PAUSE 0x230044FC /* Start / Pause / Restart game */ + +/*--- CAD - 3D object control + Controls to select and move objects within a 3D environment ---*/ +#define DIVIRTUAL_CAD_3DCONTROL 0x24000000 +#define DIAXIS_3DCONTROL_LATERAL 0x24008201 /* Move view left / right */ +#define DIAXIS_3DCONTROL_MOVE 0x24010202 /* Move view up / down */ +#define DIAXIS_3DCONTROL_INOUT 0x24018203 /* Zoom - in / out */ +#define DIBUTTON_3DCONTROL_SELECT 0x24000401 /* Select Object */ +#define DIBUTTON_3DCONTROL_SPECIAL1 0x24000402 /* Do first special operation */ +#define DIBUTTON_3DCONTROL_SPECIAL 0x24000403 /* Select special operation */ +#define DIBUTTON_3DCONTROL_SPECIAL2 0x24000404 /* Do second special operation */ +#define DIBUTTON_3DCONTROL_MENU 0x240004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_3DCONTROL_HATSWITCH 0x24004601 /* Hat switch */ +#define DIAXIS_3DCONTROL_ROTATEX 0x24034204 /* Rotate view forward or up / backward or down */ +#define DIAXIS_3DCONTROL_ROTATEY 0x2402C205 /* Rotate view clockwise / counterclockwise */ +#define DIAXIS_3DCONTROL_ROTATEZ 0x24024206 /* Rotate view left / right */ +#define DIBUTTON_3DCONTROL_DISPLAY 0x24004405 /* Show next on-screen display options */ +#define DIBUTTON_3DCONTROL_DEVICE 0x240044FE /* Show input device and controls */ +#define DIBUTTON_3DCONTROL_PAUSE 0x240044FC /* Start / Pause / Restart game */ + +/*--- CAD - 3D Navigation - Fly through + Controls for 3D modeling ---*/ +#define DIVIRTUAL_CAD_FLYBY 0x25000000 +#define DIAXIS_CADF_LATERAL 0x25008201 /* move view left / right */ +#define DIAXIS_CADF_MOVE 0x25010202 /* move view up / down */ +#define DIAXIS_CADF_INOUT 0x25018203 /* in / out */ +#define DIBUTTON_CADF_SELECT 0x25000401 /* Select Object */ +#define DIBUTTON_CADF_SPECIAL1 0x25000402 /* do first special operation */ +#define DIBUTTON_CADF_SPECIAL 0x25000403 /* Select special operation */ +#define DIBUTTON_CADF_SPECIAL2 0x25000404 /* do second special operation */ +#define DIBUTTON_CADF_MENU 0x250004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_CADF_HATSWITCH 0x25004601 /* Hat switch */ +#define DIAXIS_CADF_ROTATEX 0x25034204 /* Rotate view forward or up / backward or down */ +#define DIAXIS_CADF_ROTATEY 0x2502C205 /* Rotate view clockwise / counterclockwise */ +#define DIAXIS_CADF_ROTATEZ 0x25024206 /* Rotate view left / right */ +#define DIBUTTON_CADF_DISPLAY 0x25004405 /* shows next on-screen display options */ +#define DIBUTTON_CADF_DEVICE 0x250044FE /* Show input device and controls */ +#define DIBUTTON_CADF_PAUSE 0x250044FC /* Start / Pause / Restart game */ + +/*--- CAD - 3D Model Control + Controls for 3D modeling ---*/ +#define DIVIRTUAL_CAD_MODEL 0x26000000 +#define DIAXIS_CADM_LATERAL 0x26008201 /* move view left / right */ +#define DIAXIS_CADM_MOVE 0x26010202 /* move view up / down */ +#define DIAXIS_CADM_INOUT 0x26018203 /* in / out */ +#define DIBUTTON_CADM_SELECT 0x26000401 /* Select Object */ +#define DIBUTTON_CADM_SPECIAL1 0x26000402 /* do first special operation */ +#define DIBUTTON_CADM_SPECIAL 0x26000403 /* Select special operation */ +#define DIBUTTON_CADM_SPECIAL2 0x26000404 /* do second special operation */ +#define DIBUTTON_CADM_MENU 0x260004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIHATSWITCH_CADM_HATSWITCH 0x26004601 /* Hat switch */ +#define DIAXIS_CADM_ROTATEX 0x26034204 /* Rotate view forward or up / backward or down */ +#define DIAXIS_CADM_ROTATEY 0x2602C205 /* Rotate view clockwise / counterclockwise */ +#define DIAXIS_CADM_ROTATEZ 0x26024206 /* Rotate view left / right */ +#define DIBUTTON_CADM_DISPLAY 0x26004405 /* shows next on-screen display options */ +#define DIBUTTON_CADM_DEVICE 0x260044FE /* Show input device and controls */ +#define DIBUTTON_CADM_PAUSE 0x260044FC /* Start / Pause / Restart game */ + +/*--- Control - Media Equipment + Remote ---*/ +#define DIVIRTUAL_REMOTE_CONTROL 0x27000000 +#define DIAXIS_REMOTE_SLIDER 0x27050201 /* Slider for adjustment: volume / color / bass / etc */ +#define DIBUTTON_REMOTE_MUTE 0x27000401 /* Set volume on current device to zero */ +#define DIBUTTON_REMOTE_SELECT 0x27000402 /* Next/previous: channel/ track / chapter / picture / station */ +#define DIBUTTON_REMOTE_PLAY 0x27002403 /* Start or pause entertainment on current device */ +#define DIBUTTON_REMOTE_CUE 0x27002404 /* Move through current media */ +#define DIBUTTON_REMOTE_REVIEW 0x27002405 /* Move through current media */ +#define DIBUTTON_REMOTE_CHANGE 0x27002406 /* Select next device */ +#define DIBUTTON_REMOTE_RECORD 0x27002407 /* Start recording the current media */ +#define DIBUTTON_REMOTE_MENU 0x270004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIAXIS_REMOTE_SLIDER2 0x27054202 /* Slider for adjustment: volume */ +#define DIBUTTON_REMOTE_TV 0x27005C08 /* Select TV */ +#define DIBUTTON_REMOTE_CABLE 0x27005C09 /* Select cable box */ +#define DIBUTTON_REMOTE_CD 0x27005C0A /* Select CD player */ +#define DIBUTTON_REMOTE_VCR 0x27005C0B /* Select VCR */ +#define DIBUTTON_REMOTE_TUNER 0x27005C0C /* Select tuner */ +#define DIBUTTON_REMOTE_DVD 0x27005C0D /* Select DVD player */ +#define DIBUTTON_REMOTE_ADJUST 0x27005C0E /* Enter device adjustment menu */ +#define DIBUTTON_REMOTE_DIGIT0 0x2700540F /* Digit 0 */ +#define DIBUTTON_REMOTE_DIGIT1 0x27005410 /* Digit 1 */ +#define DIBUTTON_REMOTE_DIGIT2 0x27005411 /* Digit 2 */ +#define DIBUTTON_REMOTE_DIGIT3 0x27005412 /* Digit 3 */ +#define DIBUTTON_REMOTE_DIGIT4 0x27005413 /* Digit 4 */ +#define DIBUTTON_REMOTE_DIGIT5 0x27005414 /* Digit 5 */ +#define DIBUTTON_REMOTE_DIGIT6 0x27005415 /* Digit 6 */ +#define DIBUTTON_REMOTE_DIGIT7 0x27005416 /* Digit 7 */ +#define DIBUTTON_REMOTE_DIGIT8 0x27005417 /* Digit 8 */ +#define DIBUTTON_REMOTE_DIGIT9 0x27005418 /* Digit 9 */ +#define DIBUTTON_REMOTE_DEVICE 0x270044FE /* Show input device and controls */ +#define DIBUTTON_REMOTE_PAUSE 0x270044FC /* Start / Pause / Restart game */ + +/*--- Control- Web + Help or Browser ---*/ +#define DIVIRTUAL_BROWSER_CONTROL 0x28000000 +#define DIAXIS_BROWSER_LATERAL 0x28008201 /* Move on screen pointer */ +#define DIAXIS_BROWSER_MOVE 0x28010202 /* Move on screen pointer */ +#define DIBUTTON_BROWSER_SELECT 0x28000401 /* Select current item */ +#define DIAXIS_BROWSER_VIEW 0x28018203 /* Move view up/down */ +#define DIBUTTON_BROWSER_REFRESH 0x28000402 /* Refresh */ +#define DIBUTTON_BROWSER_MENU 0x280004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_BROWSER_SEARCH 0x28004403 /* Use search tool */ +#define DIBUTTON_BROWSER_STOP 0x28004404 /* Cease current update */ +#define DIBUTTON_BROWSER_HOME 0x28004405 /* Go directly to "home" location */ +#define DIBUTTON_BROWSER_FAVORITES 0x28004406 /* Mark current site as favorite */ +#define DIBUTTON_BROWSER_NEXT 0x28004407 /* Select Next page */ +#define DIBUTTON_BROWSER_PREVIOUS 0x28004408 /* Select Previous page */ +#define DIBUTTON_BROWSER_HISTORY 0x28004409 /* Show/Hide History */ +#define DIBUTTON_BROWSER_PRINT 0x2800440A /* Print current page */ +#define DIBUTTON_BROWSER_DEVICE 0x280044FE /* Show input device and controls */ +#define DIBUTTON_BROWSER_PAUSE 0x280044FC /* Start / Pause / Restart game */ + +/*--- Driving Simulator - Giant Walking Robot + Walking tank with weapons ---*/ +#define DIVIRTUAL_DRIVING_MECHA 0x29000000 +#define DIAXIS_MECHA_STEER 0x29008201 /* Turns mecha left/right */ +#define DIAXIS_MECHA_TORSO 0x29010202 /* Tilts torso forward/backward */ +#define DIAXIS_MECHA_ROTATE 0x29020203 /* Turns torso left/right */ +#define DIAXIS_MECHA_THROTTLE 0x29038204 /* Engine Speed */ +#define DIBUTTON_MECHA_FIRE 0x29000401 /* Fire */ +#define DIBUTTON_MECHA_WEAPONS 0x29000402 /* Select next weapon group */ +#define DIBUTTON_MECHA_TARGET 0x29000403 /* Select closest enemy available target */ +#define DIBUTTON_MECHA_REVERSE 0x29000404 /* Toggles throttle in/out of reverse */ +#define DIBUTTON_MECHA_ZOOM 0x29000405 /* Zoom in/out targeting reticule */ +#define DIBUTTON_MECHA_JUMP 0x29000406 /* Fires jump jets */ +#define DIBUTTON_MECHA_MENU 0x290004FD /* Show menu options */ +/*--- Priority 2 controls ---*/ + +#define DIBUTTON_MECHA_CENTER 0x29004407 /* Center torso to legs */ +#define DIHATSWITCH_MECHA_GLANCE 0x29004601 /* Look around */ +#define DIBUTTON_MECHA_VIEW 0x29004408 /* Cycle through view options */ +#define DIBUTTON_MECHA_FIRESECONDARY 0x29004409 /* Alternative fire button */ +#define DIBUTTON_MECHA_LEFT_LINK 0x2900C4E4 /* Fallback steer left button */ +#define DIBUTTON_MECHA_RIGHT_LINK 0x2900C4EC /* Fallback steer right button */ +#define DIBUTTON_MECHA_FORWARD_LINK 0x290144E0 /* Fallback tilt torso forward button */ +#define DIBUTTON_MECHA_BACK_LINK 0x290144E8 /* Fallback tilt toroso backward button */ +#define DIBUTTON_MECHA_ROTATE_LEFT_LINK 0x290244E4 /* Fallback rotate toroso right button */ +#define DIBUTTON_MECHA_ROTATE_RIGHT_LINK 0x290244EC /* Fallback rotate torso left button */ +#define DIBUTTON_MECHA_FASTER_LINK 0x2903C4E0 /* Fallback increase engine speed */ +#define DIBUTTON_MECHA_SLOWER_LINK 0x2903C4E8 /* Fallback decrease engine speed */ +#define DIBUTTON_MECHA_DEVICE 0x290044FE /* Show input device and controls */ +#define DIBUTTON_MECHA_PAUSE 0x290044FC /* Start / Pause / Restart game */ + +/* + * "ANY" semantics can be used as a last resort to get mappings for actions + * that match nothing in the chosen virtual genre. These semantics will be + * mapped at a lower priority that virtual genre semantics. Also, hardware + * vendors will not be able to provide sensible mappings for these unless + * they provide application specific mappings. + */ +#define DIAXIS_ANY_X_1 0xFF00C201 +#define DIAXIS_ANY_X_2 0xFF00C202 +#define DIAXIS_ANY_Y_1 0xFF014201 +#define DIAXIS_ANY_Y_2 0xFF014202 +#define DIAXIS_ANY_Z_1 0xFF01C201 +#define DIAXIS_ANY_Z_2 0xFF01C202 +#define DIAXIS_ANY_R_1 0xFF024201 +#define DIAXIS_ANY_R_2 0xFF024202 +#define DIAXIS_ANY_U_1 0xFF02C201 +#define DIAXIS_ANY_U_2 0xFF02C202 +#define DIAXIS_ANY_V_1 0xFF034201 +#define DIAXIS_ANY_V_2 0xFF034202 +#define DIAXIS_ANY_A_1 0xFF03C201 +#define DIAXIS_ANY_A_2 0xFF03C202 +#define DIAXIS_ANY_B_1 0xFF044201 +#define DIAXIS_ANY_B_2 0xFF044202 +#define DIAXIS_ANY_C_1 0xFF04C201 +#define DIAXIS_ANY_C_2 0xFF04C202 +#define DIAXIS_ANY_S_1 0xFF054201 +#define DIAXIS_ANY_S_2 0xFF054202 + +#define DIAXIS_ANY_1 0xFF004201 +#define DIAXIS_ANY_2 0xFF004202 +#define DIAXIS_ANY_3 0xFF004203 +#define DIAXIS_ANY_4 0xFF004204 + +#define DIPOV_ANY_1 0xFF004601 +#define DIPOV_ANY_2 0xFF004602 +#define DIPOV_ANY_3 0xFF004603 +#define DIPOV_ANY_4 0xFF004604 + +#define DIBUTTON_ANY(instance) ( 0xFF004400 | instance ) + + +#ifdef __cplusplus +}; +#endif + +#endif /* __DINPUT_INCLUDED__ */ + +/**************************************************************************** + * + * Definitions for non-IDirectInput (VJoyD) features defined more recently + * than the current sdk files + * + ****************************************************************************/ + +#ifdef _INC_MMSYSTEM +#ifndef MMNOJOY + +#ifndef __VJOYDX_INCLUDED__ +#define __VJOYDX_INCLUDED__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Flag to indicate that the dwReserved2 field of the JOYINFOEX structure + * contains mini-driver specific data to be passed by VJoyD to the mini- + * driver instead of doing a poll. + */ +#define JOY_PASSDRIVERDATA 0x10000000l + +/* + * Informs the joystick driver that the configuration has been changed + * and should be reloaded from the registery. + * dwFlags is reserved and should be set to zero + */ +WINMMAPI MMRESULT WINAPI joyConfigChanged( DWORD dwFlags ); + + +/* + * Hardware Setting indicating that the device is a headtracker + */ +#define JOY_HWS_ISHEADTRACKER 0x02000000l + +/* + * Hardware Setting indicating that the VxD is used to replace + * the standard analog polling + */ +#define JOY_HWS_ISGAMEPORTDRIVER 0x04000000l + +/* + * Hardware Setting indicating that the driver needs a standard + * gameport in order to communicate with the device. + */ +#define JOY_HWS_ISANALOGPORTDRIVER 0x08000000l + +/* + * Hardware Setting indicating that VJoyD should not load this + * driver, it will be loaded externally and will register with + * VJoyD of it's own accord. + */ +#define JOY_HWS_AUTOLOAD 0x10000000l + +/* + * Hardware Setting indicating that the driver acquires any + * resources needed without needing a devnode through VJoyD. + */ +#define JOY_HWS_NODEVNODE 0x20000000l + + +/* + * Hardware Setting indicating that the device is a gameport bus + */ +#define JOY_HWS_ISGAMEPORTBUS 0x80000000l +#define JOY_HWS_GAMEPORTBUSBUSY 0x00000001l + +/* + * Usage Setting indicating that the settings are volatile and + * should be removed if still present on a reboot. + */ +#define JOY_US_VOLATILE 0x00000008L + +#ifdef __cplusplus +}; +#endif + +#endif /* __VJOYDX_INCLUDED__ */ + +#endif /* not MMNOJOY */ +#endif /* _INC_MMSYSTEM */ + +/**************************************************************************** + * + * Definitions for non-IDirectInput (VJoyD) features defined more recently + * than the current ddk files + * + ****************************************************************************/ + +#ifndef DIJ_RINGZERO + +#ifdef _INC_MMDDK +#ifndef MMNOJOYDEV + +#ifndef __VJOYDXD_INCLUDED__ +#define __VJOYDXD_INCLUDED__ +/* + * Poll type in which the do_other field of the JOYOEMPOLLDATA + * structure contains mini-driver specific data passed from an app. + */ +#define JOY_OEMPOLL_PASSDRIVERDATA 7 + +#endif /* __VJOYDXD_INCLUDED__ */ + +#endif /* not MMNOJOYDEV */ +#endif /* _INC_MMDDK */ + +#endif /* DIJ_RINGZERO */ + diff --git a/client_files/native_autoloot/eq-core-dll/src/AddressLookupTable.h b/client_files/native_autoloot/eq-core-dll/src/AddressLookupTable.h new file mode 100644 index 0000000000..be28c79766 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/AddressLookupTable.h @@ -0,0 +1,101 @@ +#pragma once + +#include +#include + +constexpr UINT MaxIndex = 6; + +template +class AddressLookupTable +{ +public: + explicit AddressLookupTable() {} + ~AddressLookupTable() + { + ConstructorFlag = true; + + for (const auto& cache : g_map) + { + for (const auto& entry : cache) + { + entry.second->DeleteMe(); + } + } + } + + template + struct AddressCacheIndex { static constexpr UINT CacheIndex = 0; }; + template <> + struct AddressCacheIndex { static constexpr UINT CacheIndex = 1; }; + template <> + struct AddressCacheIndex { static constexpr UINT CacheIndex = 2; }; + template <> + struct AddressCacheIndex { static constexpr UINT CacheIndex = 3; }; + template <> + struct AddressCacheIndex { static constexpr UINT CacheIndex = 4; }; + template <> + struct AddressCacheIndex { static constexpr UINT CacheIndex = 5; }; + + template + T *FindAddress(void *Proxy) + { + if (!Proxy) + { + return nullptr; + } + + constexpr UINT CacheIndex = AddressCacheIndex::CacheIndex; + auto it = g_map[CacheIndex].find(Proxy); + + if (it != std::end(g_map[CacheIndex])) + { + return static_cast(it->second); + } + + return new T(static_cast(Proxy)); + } + + template + void SaveAddress(T *Wrapper, void *Proxy) + { + constexpr UINT CacheIndex = AddressCacheIndex::CacheIndex; + if (Wrapper && Proxy) + { + g_map[CacheIndex][Proxy] = Wrapper; + } + } + + template + void DeleteAddress(T *Wrapper) + { + if (!Wrapper || ConstructorFlag) + { + return; + } + + constexpr UINT CacheIndex = AddressCacheIndex::CacheIndex; + auto it = std::find_if(g_map[CacheIndex].begin(), g_map[CacheIndex].end(), + [=](auto Map) -> bool { return Map.second == Wrapper; }); + + if (it != std::end(g_map[CacheIndex])) + { + it = g_map[CacheIndex].erase(it); + } + } + +private: + bool ConstructorFlag = false; + D *unused = nullptr; + std::unordered_map g_map[MaxIndex]; +}; + +class AddressLookupTableObject +{ +public: + virtual ~AddressLookupTableObject() { } + + void DeleteMe() + { + delete this; + } +}; diff --git a/client_files/native_autoloot/eq-core-dll/src/DetoursAPI.cpp b/client_files/native_autoloot/eq-core-dll/src/DetoursAPI.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/client_files/native_autoloot/eq-core-dll/src/EQClasses.cpp b/client_files/native_autoloot/eq-core-dll/src/EQClasses.cpp new file mode 100644 index 0000000000..02135dc008 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/EQClasses.cpp @@ -0,0 +1,9645 @@ +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +//#error /DCINTERFACE +#endif + +#define DBG_SPEW + + +#include "MQ2Main.h" + +enum UIType CXWnd::GetType() +{ + if (CXMLData *pXMLData=GetXMLData()) + return pXMLData->Type; + return UI_Unknown; +} + +enum UIType CSidlScreenWnd::GetType() +{ + if (CXMLData *pXMLData=GetXMLData()) + return pXMLData->Type; + return UI_Unknown; +} + +class CXMLData * CXWnd::GetXMLData() +{ + if (XMLIndex) + return ((CXMLDataManager*)&((PCSIDLMGR)pSidlMgr)->pXMLDataMgr)->GetXMLData(XMLIndex>>16,XMLIndex&0xFFFF); + //DebugSpew("CXWnd::GetXMLData()=0"); + return 0; +} +class CXMLData * CSidlScreenWnd::GetXMLData() +{ + if (XMLIndex) + return ((CXMLDataManager*)&((PCSIDLMGR)pSidlMgr)->pXMLDataMgr)->GetXMLData(XMLIndex>>16,XMLIndex&0xFFFF); + //DebugSpew("CSidlScreenWnd::GetXMLData()=0"); + return 0; +} + +// fuck -- if you try to use the native GetChildItem, then +// it fails to find things without a ScreenID + +class CXWnd *RecurseAndFindName(class CXWnd *pWnd, PCHAR Name) +{ + CHAR Buffer[MAX_STRING]={0}; + class CXWnd *tmp; + + if (!pWnd) return pWnd; + + if (CXMLData *pXMLData=pWnd->GetXMLData()) { + if (GetCXStr(pXMLData->Name.Ptr,Buffer,MAX_STRING) && !stricmp(Buffer,Name)) { + return pWnd; + } + //DebugSpew("RecurseAndFindName looking for %s but found %s", Name, Buffer); + if (GetCXStr(pXMLData->ScreenID.Ptr,Buffer,MAX_STRING) && !stricmp(Buffer,Name)) { + return pWnd; + } + } + + if (pWnd->pFirstChildWnd) { + tmp = RecurseAndFindName((class CXWnd *)pWnd->pFirstChildWnd, Name); + if (tmp) + return tmp; + } + return RecurseAndFindName((class CXWnd *)pWnd->pNextSiblingWnd, Name); +} + +class CXWnd * CXWnd::GetChildItem(PCHAR Name) +{ + //return GetChildItem(CXStr(Name)); + return RecurseAndFindName(this, Name); +} + +class CXWnd * CSidlScreenWnd::GetChildItem(PCHAR Name) +{ + return RecurseAndFindName((class CXWnd *)this, Name); +} + +class CScreenPieceTemplate * CSidlManager::FindScreenPieceTemplate(char *str) +{ + return FindScreenPieceTemplate(&CXStr(str)); +} +void CComboWnd::InsertChoice(char *str) +{ + InsertChoice(&CXStr(str),0); +} + +int CListWnd::AddString(const char *Str, COLORREF Color, uint32_t Data, const CTextureAnimation *pTa, const char* TooltipStr) +{ + return AddString(CXStr(Str), Color, Data, pTa, TooltipStr); +} + +void CEditBaseWnd::SetMaxChars(int maxChars) +{ + this->MaxChars = maxChars; + int len = 0; + + if(this->InputText) + { + len = this->InputText->Length; + } + + if(len > maxChars) + { + ((CXWnd*)this)->SetWindowTextA(CXStr(this->InputText->Text)); + } +} + +CXPoint CXRect::CenterPoint()const +{ + CXPoint p; + + p.A = this->A + ((this->C - this->A) / 2); + p.B = this->B + ((this->D - this->B) / 2); // (bottom - top / 2) + top + + return p; +} + +// MANUAL IMPORTS +#ifdef CMyInventory__GetSlot_x +FUNCTION_AT_ADDRESS(struct _CONTENTS* CMyInventory::GetSlot(int), CMyInventory__GetSlot); +#endif + +#ifdef EQ_Item__CreateItemTagString_x +FUNCTION_AT_ADDRESS(char * EQ_Item::CreateItemTagString(char *, int),EQ_Item__CreateItemTagString); // Lax 11-14-2003 +#endif +#ifdef CStmlWnd__AppendSTML_x +FUNCTION_AT_ADDRESS(class CXSize CStmlWnd::AppendSTML(class CXStr),CStmlWnd__AppendSTML); +#endif +#ifdef EQ_Item__CanDrop_x +FUNCTION_AT_ADDRESS(int EQ_Item::CanDrop(bool,int,int,int),EQ_Item__CanDrop); // dkaa 2-11-2011 +#endif + +/////////////////////////////////////////////////////////////////// +// gah, i hate sony +#ifdef EQ_Character__Max_Endurance_x +FUNCTION_AT_ADDRESS(int EQ_Character1::Max_Endurance(int),EQ_Character__Max_Endurance); +#endif +//fuck virtual +#ifdef EQ_Character__Max_Mana_x +FUNCTION_AT_ADDRESS(int EQ_Character1::Max_Mana(int), EQ_Character__Max_Mana); +#endif +#ifdef EQ_Character__Max_HP_x +FUNCTION_AT_ADDRESS(int EQ_Character1::Max_HP(int,int),EQ_Character__Max_HP); +#endif +///////////////////////////////////////////////////////////////////// + +#ifdef EQ_Character__doCombatAbility_x +FUNCTION_AT_ADDRESS(bool EQ_Character::DoCombatAbility(int spellID, int dummy), EQ_Character__doCombatAbility); +#endif + + +FUNCTION_AT_VIRTUAL_ADDRESS(void CChatWindow::operator delete[](void*),0x04); + +FUNCTION_AT_VIRTUAL_ADDRESS(bool CXWnd::IsValid(void)const,0); +FUNCTION_AT_VIRTUAL_ADDRESS(int CXWnd::WndNotification(class CXWnd *,unsigned __int32,void *),0x88); +FUNCTION_AT_VIRTUAL_ADDRESS(int CXWnd::OnResize(int,int),0x098); +FUNCTION_AT_VIRTUAL_ADDRESS(int CXWnd::Show(bool,bool,bool),0x0d8); +FUNCTION_AT_VIRTUAL_ADDRESS(int CXWnd::SetVScrollPos(int),0x134); +FUNCTION_AT_VIRTUAL_ADDRESS(void CXWnd::SetWindowTextA(class CXStr &),0x124); + +FUNCTION_AT_VIRTUAL_ADDRESS(int CXWnd::HandleLButtonDown(class CXPoint *,unsigned __int32),0x38); +FUNCTION_AT_VIRTUAL_ADDRESS(int CXWnd::HandleLButtonUp(class CXPoint *,unsigned __int32),0x3c); +FUNCTION_AT_VIRTUAL_ADDRESS(int CXWnd::HandleLButtonHeld(class CXPoint *,unsigned __int32),0x40); +FUNCTION_AT_VIRTUAL_ADDRESS(int CXWnd::HandleLButtonUpAfterHeld(class CXPoint *,unsigned __int32),0x44); +FUNCTION_AT_VIRTUAL_ADDRESS(int CXWnd::HandleRButtonDown(class CXPoint *,unsigned __int32),0x48); +FUNCTION_AT_VIRTUAL_ADDRESS(int CXWnd::HandleRButtonUp(class CXPoint *,unsigned __int32),0x4c); +FUNCTION_AT_VIRTUAL_ADDRESS(int CXWnd::HandleRButtonHeld(class CXPoint *,unsigned __int32),0x50); +FUNCTION_AT_VIRTUAL_ADDRESS(int CXWnd::HandleRButtonUpAfterHeld(class CXPoint *,unsigned __int32),0x54); +FUNCTION_AT_VIRTUAL_ADDRESS(int CXWnd::OnMinimizeBox(void),0xa8); + + +FUNCTION_AT_VIRTUAL_ADDRESS(void CListWnd::DeleteAll(void),0x17c); + + +// AUTO IMPORTS + +#ifdef CAAWnd__CAAWnd_x +FUNCTION_AT_ADDRESS( CAAWnd::CAAWnd(class CXWnd *),CAAWnd__CAAWnd); +#endif +#ifdef CAAWnd__Update_x +FUNCTION_AT_ADDRESS(void CAAWnd::Update(void),CAAWnd__Update); +#endif +#ifdef CAAWnd__UpdateSelected_x +FUNCTION_AT_ADDRESS(void CAAWnd::UpdateSelected(void),CAAWnd__UpdateSelected); +#endif +#ifdef CAAWnd__UpdateTimer_x +FUNCTION_AT_ADDRESS(void CAAWnd::UpdateTimer(void),CAAWnd__UpdateTimer); +#endif +#ifdef CAAWnd__Init_x +FUNCTION_AT_ADDRESS(void CAAWnd::Init(void),CAAWnd__Init); +#endif +#ifdef CAAWnd__Activate_x +FUNCTION_AT_ADDRESS(void CAAWnd::Activate(void),CAAWnd__Activate); +#endif +#ifdef CAAWnd__ShowAbility_x +FUNCTION_AT_ADDRESS(void CAAWnd::ShowAbility(int),CAAWnd__ShowAbility); +#endif +#ifdef CAAWnd__SendNewPercent_x +FUNCTION_AT_ADDRESS(void CAAWnd::SendNewPercent(void),CAAWnd__SendNewPercent); +#endif +#ifdef CAAWnd__ConfirmAASpend_x +FUNCTION_AT_ADDRESS(void CAAWnd::ConfirmAASpend(void),CAAWnd__ConfirmAASpend); +#endif +#ifdef CXStr__CXStr_x +FUNCTION_AT_ADDRESS( CXStr::CXStr(class CXStr const &),CXStr__CXStr); +#endif +#ifdef CXMLSOMCursor__dCXMLSOMCursor_x +FUNCTION_AT_ADDRESS( CXMLSOMCursor::~CXMLSOMCursor(void),CXMLSOMCursor__dCXMLSOMCursor); +#endif +#ifdef CKeyCXStrValueInt32__dCKeyCXStrValueInt32_x +FUNCTION_AT_ADDRESS( CKeyCXStrValueInt32::~CKeyCXStrValueInt32(void),CKeyCXStrValueInt32__dCKeyCXStrValueInt32); +#endif +#ifdef COptionsWnd__KeyboardAssignmentData__dKeyboardAssignmentData_x +//FUNCTION_AT_ADDRESS( COptionsWnd::KeyboardAssignmentData::~KeyboardAssignmentData(void),COptionsWnd__KeyboardAssignmentData__dKeyboardAssignmentData); +#endif +#ifdef CXStr__dCXStr_x +FUNCTION_AT_ADDRESS( CXStr::~CXStr(void),CXStr__dCXStr); +#endif +#ifdef CUITextureInfo__CUITextureInfo_x +FUNCTION_AT_ADDRESS( CUITextureInfo::CUITextureInfo(class CXStr,int),CUITextureInfo__CUITextureInfo); +#endif +#ifdef CXMLSOMNodePtr__dCXMLSOMNodePtr_x +FUNCTION_AT_ADDRESS( CXMLSOMNodePtr::~CXMLSOMNodePtr(void),CXMLSOMNodePtr__dCXMLSOMNodePtr); +#endif +#ifdef CXMLSOMNode__dCXMLSOMNode_x +FUNCTION_AT_ADDRESS( CXMLSOMNode::~CXMLSOMNode(void),CXMLSOMNode__dCXMLSOMNode); +#endif +#ifdef CXMLSOMAttribute__dCXMLSOMAttribute_x +FUNCTION_AT_ADDRESS( CXMLSOMAttribute::~CXMLSOMAttribute(void),CXMLSOMAttribute__dCXMLSOMAttribute); +#endif +#ifdef CActionsWnd__CActionsWnd_x +FUNCTION_AT_ADDRESS( CActionsWnd::CActionsWnd(class CXWnd *),CActionsWnd__CActionsWnd); +#endif +#ifdef CActionsWnd__Activate_x +FUNCTION_AT_ADDRESS(void CActionsWnd::Activate(int),CActionsWnd__Activate); +#endif +#ifdef CActionsWnd__UpdateButtonText_x +FUNCTION_AT_ADDRESS(void CActionsWnd::UpdateButtonText(void),CActionsWnd__UpdateButtonText); +#endif +#ifdef CActionsWnd__GetCurrentPageEnum_x +FUNCTION_AT_ADDRESS(int CActionsWnd::GetCurrentPageEnum(void)const ,CActionsWnd__GetCurrentPageEnum); +#endif +/* OTHER FUNCTIONS IMPORTED FROM EQ */ +#ifdef __CastRay_x +FUNCTION_AT_ADDRESS(int CastRay(PSPAWNINFO, float y, float x, float z), __CastRay); +#endif +#ifdef Util__FastTime_x +FUNCTION_AT_ADDRESS(unsigned long GetFastTime(void), Util__FastTime); +#endif +#ifdef __GetXTargetType_x +FUNCTION_AT_ADDRESS(char* __stdcall GetXtargetType(DWORD type), __GetXTargetType); +#endif +#ifdef __EQGetTime_x +FUNCTION_AT_ADDRESS(DWORD EQGetTime(), __EQGetTime); +#endif +#ifdef CActionsWnd__KeyMapUpdated_x +FUNCTION_AT_ADDRESS(void CActionsWnd::KeyMapUpdated(void),CActionsWnd__KeyMapUpdated); +#endif +#ifdef CActionsWnd__SelectSkillForAbilityBtn_x +FUNCTION_AT_ADDRESS(void CActionsWnd::SelectSkillForAbilityBtn(int),CActionsWnd__SelectSkillForAbilityBtn); +#endif +#ifdef CActionsWnd__GetAbilityBtn_x +FUNCTION_AT_ADDRESS(class CButtonWnd * CActionsWnd::GetAbilityBtn(int),CActionsWnd__GetAbilityBtn); +#endif +#ifdef CActionsWnd__SelectSkillForCombatBtn_x +FUNCTION_AT_ADDRESS(void CActionsWnd::SelectSkillForCombatBtn(int),CActionsWnd__SelectSkillForCombatBtn); +#endif +#ifdef CActionsWnd__GetCombatBtn_x +FUNCTION_AT_ADDRESS(class CButtonWnd * CActionsWnd::GetCombatBtn(int),CActionsWnd__GetCombatBtn); +#endif +#ifdef CActionsWnd__GetMenuBtn_x +FUNCTION_AT_ADDRESS(class CButtonWnd * CActionsWnd::GetMenuBtn(int),CActionsWnd__GetMenuBtn); +#endif +#ifdef CActionsWnd__RedirectActivateTo_x +FUNCTION_AT_ADDRESS(int CActionsWnd::RedirectActivateTo(class CPageWnd *),CActionsWnd__RedirectActivateTo); +#endif +#ifdef CActionsWnd__RedirectDeactivateTo_x +FUNCTION_AT_ADDRESS(int CActionsWnd::RedirectDeactivateTo(class CPageWnd *),CActionsWnd__RedirectDeactivateTo); +#endif +#ifdef CActionsWnd__RedirectOnProcessFrameTo_x +FUNCTION_AT_ADDRESS(int CActionsWnd::RedirectOnProcessFrameTo(class CPageWnd *),CActionsWnd__RedirectOnProcessFrameTo); +#endif +#ifdef CActionsWnd__RedirectWndNotificationTo_x +FUNCTION_AT_ADDRESS(int CActionsWnd::RedirectWndNotificationTo(class CPageWnd *,class CXWnd *,unsigned __int32,void *),CActionsWnd__RedirectWndNotificationTo); +#endif +#ifdef CActionsWnd__MainPageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int CActionsWnd::MainPageOnProcessFrame(void),CActionsWnd__MainPageOnProcessFrame); +#endif +#ifdef CActionsWnd__MainPageWndNotification_x +FUNCTION_AT_ADDRESS(int CActionsWnd::MainPageWndNotification(class CXWnd *,unsigned __int32,void *),CActionsWnd__MainPageWndNotification); +#endif +#ifdef CActionsWnd__AbilitiesPageActivate_x +FUNCTION_AT_ADDRESS(int CActionsWnd::AbilitiesPageActivate(void),CActionsWnd__AbilitiesPageActivate); +#endif +#ifdef CActionsWnd__AbilitiesPageDeactivate_x +FUNCTION_AT_ADDRESS(int CActionsWnd::AbilitiesPageDeactivate(void),CActionsWnd__AbilitiesPageDeactivate); +#endif +#ifdef CActionsWnd__AbilitiesPageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int CActionsWnd::AbilitiesPageOnProcessFrame(void),CActionsWnd__AbilitiesPageOnProcessFrame); +#endif +#ifdef CActionsWnd__AbilitiesPageWndNotification_x +FUNCTION_AT_ADDRESS(int CActionsWnd::AbilitiesPageWndNotification(class CXWnd *,unsigned __int32,void *),CActionsWnd__AbilitiesPageWndNotification); +#endif +#ifdef CActionsWnd__CombatPageActivate_x +FUNCTION_AT_ADDRESS(int CActionsWnd::CombatPageActivate(void),CActionsWnd__CombatPageActivate); +#endif +#ifdef CActionsWnd__CombatPageDeactivate_x +FUNCTION_AT_ADDRESS(int CActionsWnd::CombatPageDeactivate(void),CActionsWnd__CombatPageDeactivate); +#endif +#ifdef CActionsWnd__CombatPageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int CActionsWnd::CombatPageOnProcessFrame(void),CActionsWnd__CombatPageOnProcessFrame); +#endif +#ifdef CActionsWnd__CombatPageWndNotification_x +FUNCTION_AT_ADDRESS(int CActionsWnd::CombatPageWndNotification(class CXWnd *,unsigned __int32,void *),CActionsWnd__CombatPageWndNotification); +#endif +#ifdef CActionsWnd__SocialsPageActivate_x +FUNCTION_AT_ADDRESS(int CActionsWnd::SocialsPageActivate(void),CActionsWnd__SocialsPageActivate); +#endif +#ifdef CActionsWnd__SocialsPageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int CActionsWnd::SocialsPageOnProcessFrame(void),CActionsWnd__SocialsPageOnProcessFrame); +#endif +#ifdef CActionsWnd__SocialsPageWndNotification_x +FUNCTION_AT_ADDRESS(int CActionsWnd::SocialsPageWndNotification(class CXWnd *,unsigned __int32,void *),CActionsWnd__SocialsPageWndNotification); +#endif +#ifdef CAlarmWnd__CAlarmWnd_x +FUNCTION_AT_ADDRESS( CAlarmWnd::CAlarmWnd(class CXWnd *),CAlarmWnd__CAlarmWnd); +#endif +#ifdef CAlarmWnd__Activate_x +FUNCTION_AT_ADDRESS(void CAlarmWnd::Activate(void),CAlarmWnd__Activate); +#endif +#ifdef CAlarmWnd__DoNeverButton_x +FUNCTION_AT_ADDRESS(void CAlarmWnd::DoNeverButton(void),CAlarmWnd__DoNeverButton); +#endif +#ifdef CEditBaseWnd__SetMaxChars_x +FUNCTION_AT_ADDRESS(void CEditBaseWnd::SetMaxChars(int),CEditBaseWnd__SetMaxChars); +#endif +#ifdef CBankWnd__CBankWnd_x +FUNCTION_AT_ADDRESS( CBankWnd::CBankWnd(class CXWnd *,class CXStr),CBankWnd__CBankWnd); +#endif +#ifdef CBankWnd__Init_x +FUNCTION_AT_ADDRESS(void CBankWnd::Init(void),CBankWnd__Init); +#endif +#ifdef CBankWnd__Activate_x +FUNCTION_AT_ADDRESS(void CBankWnd::Activate(class EQPlayer *),CBankWnd__Activate); +#endif +#ifdef CBankWnd__Deactivate_x +FUNCTION_AT_ADDRESS(void CBankWnd::Deactivate(bool),CBankWnd__Deactivate); +#endif +#ifdef CBankWnd__ClickedMoneyButton_x +FUNCTION_AT_ADDRESS(void CBankWnd::ClickedMoneyButton(int,int),CBankWnd__ClickedMoneyButton); +#endif +#ifdef CBankWnd__GetBankQtyFromCoinType_x +FUNCTION_AT_ADDRESS(long CBankWnd::GetBankQtyFromCoinType(int),CBankWnd__GetBankQtyFromCoinType); +#endif +#ifdef CBankWnd__UpdateMoneyDisplay_x +FUNCTION_AT_ADDRESS(void CBankWnd::UpdateMoneyDisplay(void),CBankWnd__UpdateMoneyDisplay); +#endif +#ifdef CBankWnd__GetNumBankSlots_x +FUNCTION_AT_ADDRESS(int CBankWnd::GetNumBankSlots(void)const ,CBankWnd__GetNumBankSlots); +#endif +#ifdef CXRect__CenterPoint_x +FUNCTION_AT_ADDRESS(class CXPoint CXRect::CenterPoint(void)const ,CXRect__CenterPoint); +#endif +#ifdef CBazaarSearchWnd__CBazaarSearchWnd_x +FUNCTION_AT_ADDRESS( CBazaarSearchWnd::CBazaarSearchWnd(class CXWnd *),CBazaarSearchWnd__CBazaarSearchWnd); +#endif +#ifdef CBazaarSearchWnd__InitListArray_x +FUNCTION_AT_ADDRESS(void CBazaarSearchWnd::InitListArray(void),CBazaarSearchWnd__InitListArray); +#endif +#ifdef CBazaarSearchWnd__Init_x +FUNCTION_AT_ADDRESS(void CBazaarSearchWnd::Init(void),CBazaarSearchWnd__Init); +#endif +#ifdef CBazaarSearchWnd__UpdatePlayerUpdateButton_x +FUNCTION_AT_ADDRESS(void CBazaarSearchWnd::UpdatePlayerUpdateButton(bool),CBazaarSearchWnd__UpdatePlayerUpdateButton); +#endif +#ifdef CBazaarSearchWnd__UpdatePlayerCombo_x +FUNCTION_AT_ADDRESS(void CBazaarSearchWnd::UpdatePlayerCombo(void),CBazaarSearchWnd__UpdatePlayerCombo); +#endif +#ifdef CBazaarSearchWnd__Activate_x +FUNCTION_AT_ADDRESS(void CBazaarSearchWnd::Activate(void),CBazaarSearchWnd__Activate); +#endif +#ifdef CBazaarSearchWnd__GetPriceString_x +FUNCTION_AT_ADDRESS(char * CBazaarSearchWnd::GetPriceString(unsigned long),CBazaarSearchWnd__GetPriceString); +#endif +#ifdef CBazaarSearchWnd__SortItemList_x +FUNCTION_AT_ADDRESS(void CBazaarSearchWnd::SortItemList(int),CBazaarSearchWnd__SortItemList); +#endif +#ifdef CBazaarSearchWnd__AddItemtoList_x +FUNCTION_AT_ADDRESS(void CBazaarSearchWnd::AddItemtoList(char *,unsigned long,char *,int,int),CBazaarSearchWnd__AddItemtoList); +#endif +#ifdef CBazaarSearchWnd__UpdateComboButtons_x +FUNCTION_AT_ADDRESS(void CBazaarSearchWnd::UpdateComboButtons(void),CBazaarSearchWnd__UpdateComboButtons); +#endif +#ifdef CBazaarSearchWnd__HandleBazaarMsg_x +FUNCTION_AT_ADDRESS(void CBazaarSearchWnd::HandleBazaarMsg(char *,int),CBazaarSearchWnd__HandleBazaarMsg); +#endif +#ifdef CBazaarSearchWnd__doQuery_x +FUNCTION_AT_ADDRESS(void CBazaarSearchWnd::doQuery(void),CBazaarSearchWnd__doQuery); +#endif +#ifdef CBazaarWnd__CBazaarWnd_x +FUNCTION_AT_ADDRESS( CBazaarWnd::CBazaarWnd(class CXWnd *),CBazaarWnd__CBazaarWnd); +#endif +#ifdef CBazaarWnd__Init_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::Init(void),CBazaarWnd__Init); +#endif +#ifdef CBazaarWnd__CreateBZRIniFilename_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::CreateBZRIniFilename(void),CBazaarWnd__CreateBZRIniFilename); +#endif +#ifdef CBazaarWnd__AddBazaarText_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::AddBazaarText(char *,int),CBazaarWnd__AddBazaarText); +#endif +#ifdef CBazaarWnd__ReturnItemByIndex_x +FUNCTION_AT_ADDRESS(class EQ_Item * CBazaarWnd::ReturnItemByIndex(int),CBazaarWnd__ReturnItemByIndex); +#endif +#ifdef CBazaarWnd__GetPriceString_x +FUNCTION_AT_ADDRESS(char * CBazaarWnd::GetPriceString(unsigned long),CBazaarWnd__GetPriceString); +#endif +#ifdef CBazaarWnd__HandleTraderMsg_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::HandleTraderMsg(char *),CBazaarWnd__HandleTraderMsg); +#endif +#ifdef CBazaarWnd__RebuildItemArray_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::RebuildItemArray(void),CBazaarWnd__RebuildItemArray); +#endif +#ifdef CBazaarWnd__BuildBazaarItemArray_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::BuildBazaarItemArray(void),CBazaarWnd__BuildBazaarItemArray); +#endif +#ifdef CBazaarWnd__AddEquipmentToBazaarArray_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::AddEquipmentToBazaarArray(class EQ_Item *,int,unsigned long),CBazaarWnd__AddEquipmentToBazaarArray); +#endif +#ifdef CBazaarWnd__Activate_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::Activate(void),CBazaarWnd__Activate); +#endif +#ifdef CBazaarWnd__UpdatePriceButtons_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::UpdatePriceButtons(void),CBazaarWnd__UpdatePriceButtons); +#endif +#ifdef CBazaarWnd__StoreSelectedPrice_x +FUNCTION_AT_ADDRESS(bool CBazaarWnd::StoreSelectedPrice(void),CBazaarWnd__StoreSelectedPrice); +#endif +#ifdef CBazaarWnd__UpdateButtons_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::UpdateButtons(void),CBazaarWnd__UpdateButtons); +#endif +#ifdef CBazaarWnd__SelectBazaarSlotItem_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::SelectBazaarSlotItem(int,class CTextureAnimation *),CBazaarWnd__SelectBazaarSlotItem); +#endif +#ifdef CBazaarWnd__SetMoneyButton_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::SetMoneyButton(int,int),CBazaarWnd__SetMoneyButton); +#endif +#ifdef CBazaarWnd__GetQtyFromCoinType_x +FUNCTION_AT_ADDRESS(long CBazaarWnd::GetQtyFromCoinType(int),CBazaarWnd__GetQtyFromCoinType); +#endif +#ifdef CBazaarWnd__ClickedMoneyButton_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::ClickedMoneyButton(int,int),CBazaarWnd__ClickedMoneyButton); +#endif +#ifdef CBazaarWnd__GetPrice_x +FUNCTION_AT_ADDRESS(unsigned long CBazaarWnd::GetPrice(void),CBazaarWnd__GetPrice); +#endif +#ifdef CBazaarWnd__UpdateBazaarListtoServer_x +FUNCTION_AT_ADDRESS(int CBazaarWnd::UpdateBazaarListtoServer(void),CBazaarWnd__UpdateBazaarListtoServer); +#endif +#ifdef CBazaarWnd__ToggleBzrItemActive_x +FUNCTION_AT_ADDRESS(void CBazaarWnd::ToggleBzrItemActive(int,bool),CBazaarWnd__ToggleBzrItemActive); +#endif +#ifdef CXWnd__GetWindowTextA_x +FUNCTION_AT_ADDRESS(class CXStr CXWnd::GetWindowTextA(void)const ,CXWnd__GetWindowTextA); +#endif +#ifdef CBodyTintWnd__CBodyTintWnd_x +FUNCTION_AT_ADDRESS( CBodyTintWnd::CBodyTintWnd(class CXWnd *),CBodyTintWnd__CBodyTintWnd); +#endif +#ifdef CBodyTintWnd__Activate_x +FUNCTION_AT_ADDRESS(void CBodyTintWnd::Activate(void),CBodyTintWnd__Activate); +#endif +#ifdef CBodyTintWnd__GetTintChangeCount_x +FUNCTION_AT_ADDRESS(void CBodyTintWnd::GetTintChangeCount(void),CBodyTintWnd__GetTintChangeCount); +#endif +#ifdef CBodyTintWnd__GetReagentCount_x +FUNCTION_AT_ADDRESS(void CBodyTintWnd::GetReagentCount(void),CBodyTintWnd__GetReagentCount); +#endif +#ifdef CBodyTintWnd__BuildRBGTooltip_x +FUNCTION_AT_ADDRESS(char * CBodyTintWnd::BuildRBGTooltip(unsigned long,char * const),CBodyTintWnd__BuildRBGTooltip); +#endif +#ifdef CBodyTintWnd__GetItemTint_x +FUNCTION_AT_ADDRESS(unsigned long CBodyTintWnd::GetItemTint(int),CBodyTintWnd__GetItemTint); +#endif +#ifdef CBodyTintWnd__SetSlotLabels_x +FUNCTION_AT_ADDRESS(void CBodyTintWnd::SetSlotLabels(bool),CBodyTintWnd__SetSlotLabels); +#endif +#ifdef CBodyTintWnd__UpdateLocalTintColor_x +FUNCTION_AT_ADDRESS(void CBodyTintWnd::UpdateLocalTintColor(unsigned long),CBodyTintWnd__UpdateLocalTintColor); +#endif +#ifdef CBodyTintWnd__UpdateMaterialTintLocal_x +FUNCTION_AT_ADDRESS(void CBodyTintWnd::UpdateMaterialTintLocal(unsigned long),CBodyTintWnd__UpdateMaterialTintLocal); +#endif +#ifdef CBodyTintWnd__UpdateLabelsAndButtons_x +FUNCTION_AT_ADDRESS(void CBodyTintWnd::UpdateLabelsAndButtons(void),CBodyTintWnd__UpdateLabelsAndButtons); +#endif +#ifdef CBodyTintWnd__GetButtonTint_x +FUNCTION_AT_ADDRESS(unsigned long CBodyTintWnd::GetButtonTint(int),CBodyTintWnd__GetButtonTint); +#endif +#ifdef CBodyTintWnd__StoreModifiedBodyTints_x +FUNCTION_AT_ADDRESS(void CBodyTintWnd::StoreModifiedBodyTints(void),CBodyTintWnd__StoreModifiedBodyTints); +#endif +#ifdef CBodyTintWnd__ResetToOrigBodyTints_x +FUNCTION_AT_ADDRESS(void CBodyTintWnd::ResetToOrigBodyTints(void),CBodyTintWnd__ResetToOrigBodyTints); +#endif +#ifdef CXWnd__SetTooltip_x +FUNCTION_AT_ADDRESS(void CXWnd::SetTooltip(class CXStr),CXWnd__SetTooltip); +#endif +#ifdef CBookWnd__CBookWnd_x +FUNCTION_AT_ADDRESS( CBookWnd::CBookWnd(class CXWnd *),CBookWnd__CBookWnd); +#endif +#ifdef CBookWnd__Activate_x +FUNCTION_AT_ADDRESS(void CBookWnd::Activate(void),CBookWnd__Activate); +#endif +#ifdef CBookWnd__SetBook_x +FUNCTION_AT_ADDRESS(void CBookWnd::SetBook(char *),CBookWnd__SetBook); +#endif +#ifdef CBookWnd__CheckBook_x +FUNCTION_AT_ADDRESS(bool CBookWnd::CheckBook(class EQ_Note *),CBookWnd__CheckBook); +#endif +#ifdef CBookWnd__DisplayText_x +FUNCTION_AT_ADDRESS(void CBookWnd::DisplayText(void),CBookWnd__DisplayText); +#endif +#ifdef CBookWnd__CleanPages_x +FUNCTION_AT_ADDRESS(void CBookWnd::CleanPages(void),CBookWnd__CleanPages); +#endif +#ifdef CBookWnd__ProcessText_x +FUNCTION_AT_ADDRESS(void CBookWnd::ProcessText(void),CBookWnd__ProcessText); +#endif +#ifdef CBookWnd__ShowButtons_x +FUNCTION_AT_ADDRESS(void CBookWnd::ShowButtons(void),CBookWnd__ShowButtons); +#endif +#ifdef COptionsWnd__KeyboardAssignmentData__KeyboardAssignmentData_x +//FUNCTION_AT_ADDRESS( COptionsWnd::KeyboardAssignmentData::KeyboardAssignmentData(void),COptionsWnd__KeyboardAssignmentData__KeyboardAssignmentData); +#endif +#ifdef CXStr__CXStr1_x +FUNCTION_AT_ADDRESS( CXStr::CXStr(void),CXStr__CXStr1); +#endif +#ifdef CBreathWnd__CBreathWnd_x +FUNCTION_AT_ADDRESS( CBreathWnd::CBreathWnd(class CXWnd *),CBreathWnd__CBreathWnd); +#endif +#ifdef CBreathWnd__Init_x +FUNCTION_AT_ADDRESS(void CBreathWnd::Init(void),CBreathWnd__Init); +#endif +#ifdef CBreathWnd__Activate_x +FUNCTION_AT_ADDRESS(void CBreathWnd::Activate(void),CBreathWnd__Activate); +#endif +#ifdef CBuffWindow__CBuffWindow_x +//FUNCTION_AT_ADDRESS( CBuffWindow::CBuffWindow(class CXWnd *,enum BuffWindowType),CBuffWindow__CBuffWindow); +#endif +#ifdef CTextureAnimation__operator_equal_x +FUNCTION_AT_ADDRESS(class CTextureAnimation & CTextureAnimation::operator=(class CTextureAnimation const &),CTextureAnimation__operator_equal); +#endif +#ifdef CBuffWindow__Init_x +FUNCTION_AT_ADDRESS(void CBuffWindow::Init(void),CBuffWindow__Init); +#endif +#ifdef CBuffWindow__Activate_x +FUNCTION_AT_ADDRESS(void CBuffWindow::Activate(void),CBuffWindow__Activate); +#endif +#ifdef CBuffWindow__HandleSpellInfoDisplay_x +FUNCTION_AT_ADDRESS(void CBuffWindow::HandleSpellInfoDisplay(class CXWnd *),CBuffWindow__HandleSpellInfoDisplay); +#endif +#ifdef CBuffWindow__RefreshIconArrangement_x +FUNCTION_AT_ADDRESS(void CBuffWindow::RefreshIconArrangement(void),CBuffWindow__RefreshIconArrangement); +#endif +#ifdef CBuffWindow__RefreshBuffDisplay_x +FUNCTION_AT_ADDRESS(void CBuffWindow::RefreshBuffDisplay(void),CBuffWindow__RefreshBuffDisplay); +#endif +#ifdef CBuffWindow__SetBuffIcon_x +FUNCTION_AT_ADDRESS(void CBuffWindow::SetBuffIcon(class CButtonWnd *,int,int),CBuffWindow__SetBuffIcon); +#endif +#ifdef CXRect__Move_x +FUNCTION_AT_ADDRESS(void CXRect::Move(class CXPoint),CXRect__Move); +#endif +#ifdef CTAFrameDraw__GetFrameSize_x +FUNCTION_AT_ADDRESS(class CXSize CTAFrameDraw::GetFrameSize(void)const ,CTAFrameDraw__GetFrameSize); +#endif +#ifdef STextureAnimationFrame__STextureAnimationFrame_x +FUNCTION_AT_ADDRESS( STextureAnimationFrame::STextureAnimationFrame(void),STextureAnimationFrame__STextureAnimationFrame); +#endif +#ifdef CUITexturePiece__CUITexturePiece_x +FUNCTION_AT_ADDRESS( CUITexturePiece::CUITexturePiece(void),CUITexturePiece__CUITexturePiece); +#endif +#ifdef STextureAnimationFrame__operator_equal_x +FUNCTION_AT_ADDRESS(class STextureAnimationFrame & STextureAnimationFrame::operator=(class STextureAnimationFrame const &),STextureAnimationFrame__operator_equal); +#endif +#ifdef CUITexturePiece__operator_equal_x +FUNCTION_AT_ADDRESS(class CUITexturePiece & CUITexturePiece::operator=(class CUITexturePiece const &),CUITexturePiece__operator_equal); +#endif +#ifdef CBugReportWnd__CBugReportWnd_x +FUNCTION_AT_ADDRESS( CBugReportWnd::CBugReportWnd(class CXWnd *),CBugReportWnd__CBugReportWnd); +#endif +#ifdef CBugReportWnd__Activate_x +FUNCTION_AT_ADDRESS(void CBugReportWnd::Activate(void),CBugReportWnd__Activate); +#endif +#ifdef CBugReportWnd__UpdateLocation_x +FUNCTION_AT_ADDRESS(void CBugReportWnd::UpdateLocation(void),CBugReportWnd__UpdateLocation); +#endif +#ifdef CCastingWnd__CCastingWnd_x +FUNCTION_AT_ADDRESS( CCastingWnd::CCastingWnd(class CXWnd *),CCastingWnd__CCastingWnd); +#endif +#ifdef CCastingWnd__Activate_x +FUNCTION_AT_ADDRESS(void CCastingWnd::Activate(void),CCastingWnd__Activate); +#endif +#ifdef CVideoModesWnd__Activate_x +FUNCTION_AT_ADDRESS(void CVideoModesWnd::Activate(void),CVideoModesWnd__Activate); +#endif +#ifdef CCastSpellWnd__CCastSpellWnd_x +FUNCTION_AT_ADDRESS( CCastSpellWnd::CCastSpellWnd(class CXWnd *),CCastSpellWnd__CCastSpellWnd); +#endif +#ifdef CCastSpellWnd__Init_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::Init(void),CCastSpellWnd__Init); +#endif +#ifdef CCastSpellWnd__Activate_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::Activate(void),CCastSpellWnd__Activate); +#endif +#ifdef CCastSpellWnd__HandleSpellInfoDisplay_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::HandleSpellInfoDisplay(class CXWnd *),CCastSpellWnd__HandleSpellInfoDisplay); +#endif +#ifdef CCastSpellWnd__HandleSpellLeftClick_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::HandleSpellLeftClick(int),CCastSpellWnd__HandleSpellLeftClick); +#endif +#ifdef CCastSpellWnd__Unmemorize_x +FUNCTION_AT_ADDRESS(void __cdecl CCastSpellWnd::Unmemorize(int),CCastSpellWnd__Unmemorize); +#endif +#ifdef CCastSpellWnd__UnmemorizeList_x +FUNCTION_AT_ADDRESS(void __cdecl CCastSpellWnd::UnmemorizeList(int *,int),CCastSpellWnd__UnmemorizeList); +#endif +#ifdef CCastSpellWnd__HandleSpellRightClick_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::HandleSpellRightClick(int),CCastSpellWnd__HandleSpellRightClick); +#endif +#ifdef CCastSpellWnd__ForgetMemorizedSpell_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::ForgetMemorizedSpell(int),CCastSpellWnd__ForgetMemorizedSpell); +#endif +#ifdef CCastSpellWnd__IsBardSongPlaying_x +FUNCTION_AT_ADDRESS(bool CCastSpellWnd::IsBardSongPlaying(void),CCastSpellWnd__IsBardSongPlaying); +#endif +#ifdef CCastSpellWnd__RefreshSpellGemButtons_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::RefreshSpellGemButtons(void),CCastSpellWnd__RefreshSpellGemButtons); +#endif +#ifdef CCastSpellWnd__UpdateSpellGems_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::UpdateSpellGems(int),CCastSpellWnd__UpdateSpellGems); +#endif +#ifdef CCastSpellWnd__UpdateSpellGemTooltips_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::UpdateSpellGemTooltips(int),CCastSpellWnd__UpdateSpellGemTooltips); +#endif +#ifdef CCastSpellWnd__GetSpellGemColor_x +FUNCTION_AT_ADDRESS(unsigned long CCastSpellWnd::GetSpellGemColor(class EQ_Spell *),CCastSpellWnd__GetSpellGemColor); +#endif +#ifdef CCastSpellWnd__SpellBookDeactivating_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::SpellBookDeactivating(void),CCastSpellWnd__SpellBookDeactivating); +#endif +#ifdef CCastSpellWnd__KeyMapUpdated_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::KeyMapUpdated(void),CCastSpellWnd__KeyMapUpdated); +#endif +#ifdef CCastSpellWnd__ClearSpellCategories_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::ClearSpellCategories(void),CCastSpellWnd__ClearSpellCategories); +#endif +#ifdef CCastSpellWnd__SpellCategoryMajor__dSpellCategoryMajor_x +//FUNCTION_AT_ADDRESS( CCastSpellWnd::SpellCategoryMajor::~SpellCategoryMajor(void),CCastSpellWnd__SpellCategoryMajor__dSpellCategoryMajor); +#endif +#ifdef CCastSpellWnd__SpellCategoryMinor__dSpellCategoryMinor_x +//FUNCTION_AT_ADDRESS( CCastSpellWnd::SpellCategoryMinor::~SpellCategoryMinor(void),CCastSpellWnd__SpellCategoryMinor__dSpellCategoryMinor); +#endif +#ifdef CCastSpellWnd__RecacheCategorizedSpells_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::RecacheCategorizedSpells(void),CCastSpellWnd__RecacheCategorizedSpells); +#endif +#ifdef CCastSpellWnd__MakeSpellSelectMenu_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::MakeSpellSelectMenu(void),CCastSpellWnd__MakeSpellSelectMenu); +#endif +#ifdef CCastSpellWnd__CategorizeSpell_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::CategorizeSpell(int,int,int,int),CCastSpellWnd__CategorizeSpell); +#endif +#ifdef CCastSpellWnd__RecacheLoadoutContextMenu_x +FUNCTION_AT_ADDRESS(void CCastSpellWnd::RecacheLoadoutContextMenu(void),CCastSpellWnd__RecacheLoadoutContextMenu); +#endif +#ifdef CCharacterCreation__CCharacterCreation_x +FUNCTION_AT_ADDRESS( CCharacterCreation::CCharacterCreation(class CXWnd *),CCharacterCreation__CCharacterCreation); +#endif +#ifdef CCharacterCreation__Init_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::Init(void),CCharacterCreation__Init); +#endif +#ifdef CCharacterCreation__Activate_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::Activate(void),CCharacterCreation__Activate); +#endif +#ifdef CCharacterCreation__NameGenerated_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::NameGenerated(char *),CCharacterCreation__NameGenerated); +#endif +#ifdef CCharacterCreation__DoBackButton_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::DoBackButton(void),CCharacterCreation__DoBackButton); +#endif +#ifdef CCharacterCreation__DoNextButton_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::DoNextButton(void),CCharacterCreation__DoNextButton); +#endif +#ifdef CCharacterCreation__DoStatButton_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::DoStatButton(int),CCharacterCreation__DoStatButton); +#endif +#ifdef CCharacterCreation__ActivateScreen_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::ActivateScreen(int),CCharacterCreation__ActivateScreen); +#endif +#ifdef CCharacterCreation__RandomizeCharacter_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::RandomizeCharacter(bool,bool),CCharacterCreation__RandomizeCharacter); +#endif +#ifdef CCharacterCreation__RandomizeFacialFeatures_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::RandomizeFacialFeatures(void),CCharacterCreation__RandomizeFacialFeatures); +#endif +#ifdef CCharacterCreation__InitStats_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::InitStats(bool),CCharacterCreation__InitStats); +#endif +#ifdef CCharacterCreation__InitNewPC_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::InitNewPC(void),CCharacterCreation__InitNewPC); +#endif +#ifdef CCharacterCreation__InitStartingCities_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::InitStartingCities(void),CCharacterCreation__InitStartingCities); +#endif +#ifdef CCharacterCreation__SetNewPCDeityFromBtnIndex_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::SetNewPCDeityFromBtnIndex(int),CCharacterCreation__SetNewPCDeityFromBtnIndex); +#endif +#ifdef CCharacterCreation__UpdatePlayerFromNewPC_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::UpdatePlayerFromNewPC(void),CCharacterCreation__UpdatePlayerFromNewPC); +#endif +#ifdef CCharacterCreation__UpdateScreenZeroButtons_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::UpdateScreenZeroButtons(bool),CCharacterCreation__UpdateScreenZeroButtons); +#endif +#ifdef CCharacterCreation__GetRaceButtonIndex_x +FUNCTION_AT_ADDRESS(int CCharacterCreation::GetRaceButtonIndex(int),CCharacterCreation__GetRaceButtonIndex); +#endif +#ifdef CCharacterCreation__GetClassButtonIndex_x +FUNCTION_AT_ADDRESS(int CCharacterCreation::GetClassButtonIndex(int),CCharacterCreation__GetClassButtonIndex); +#endif +#ifdef CCharacterCreation__IsLackingExpansion_x +FUNCTION_AT_ADDRESS(bool CCharacterCreation::IsLackingExpansion(bool,bool),CCharacterCreation__IsLackingExpansion); +#endif +#ifdef CCharacterCreation__SelectStartingCity_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::SelectStartingCity(int),CCharacterCreation__SelectStartingCity); +#endif +#ifdef CCharacterCreation__SelectedRaceButton_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::SelectedRaceButton(int),CCharacterCreation__SelectedRaceButton); +#endif +#ifdef CCharacterCreation__SelectedClassButton_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::SelectedClassButton(int),CCharacterCreation__SelectedClassButton); +#endif +#ifdef CCharacterCreation__SetPlayerAppearanceFromNewPC_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::SetPlayerAppearanceFromNewPC(class EQPlayer *,class EQ_PC *,bool),CCharacterCreation__SetPlayerAppearanceFromNewPC); +#endif +#ifdef CCharacterCreation__HandleNameApprovalResponse_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::HandleNameApprovalResponse(int),CCharacterCreation__HandleNameApprovalResponse); +#endif +#ifdef CCharacterCreation__SubmitNameToWorld_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::SubmitNameToWorld(void),CCharacterCreation__SubmitNameToWorld); +#endif +#ifdef CCharacterCreation__FinalizeNewPCAndSendToWorld_x +FUNCTION_AT_ADDRESS(void CCharacterCreation::FinalizeNewPCAndSendToWorld(void),CCharacterCreation__FinalizeNewPCAndSendToWorld); +#endif +#ifdef CCharacterCreation__GetCharCreateText_x +FUNCTION_AT_ADDRESS(char * CCharacterCreation::GetCharCreateText(char *,int,int,int,int),CCharacterCreation__GetCharCreateText); +#endif +#ifdef CCharacterSelect__CCharacterSelect_x +FUNCTION_AT_ADDRESS( CCharacterSelect::CCharacterSelect(class CXWnd *),CCharacterSelect__CCharacterSelect); +#endif +#ifdef CCharacterSelect__Init_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::Init(void),CCharacterSelect__Init); +#endif +#ifdef CCharacterSelect__Activate_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::Activate(void),CCharacterSelect__Activate); +#endif +#ifdef CCharacterSelect__EnableButtons_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::EnableButtons(bool),CCharacterSelect__EnableButtons); +#endif +#ifdef CCharacterSelect__EnableEqMovementCommands_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::EnableEqMovementCommands(bool),CCharacterSelect__EnableEqMovementCommands); +#endif +#ifdef CCharacterSelect__EnterWorld_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::EnterWorld(void),CCharacterSelect__EnterWorld); +#endif +#ifdef CCharacterSelect__Quit_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::Quit(void),CCharacterSelect__Quit); +#endif +#ifdef CCharacterSelect__EnterExplorationMode_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::EnterExplorationMode(void),CCharacterSelect__EnterExplorationMode); +#endif +#ifdef CCharacterSelect__LeaveExplorationMode_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::LeaveExplorationMode(void),CCharacterSelect__LeaveExplorationMode); +#endif +#ifdef CCharacterSelect__IsValidCharacterSelected_x +FUNCTION_AT_ADDRESS(int CCharacterSelect::IsValidCharacterSelected(void),CCharacterSelect__IsValidCharacterSelected); +#endif +#ifdef CCharacterSelect__IsEmptyCharacterSlot_x +FUNCTION_AT_ADDRESS(int CCharacterSelect::IsEmptyCharacterSlot(int),CCharacterSelect__IsEmptyCharacterSlot); +#endif +#ifdef CCharacterSelect__NumberOfCharacters_x +FUNCTION_AT_ADDRESS(int CCharacterSelect::NumberOfCharacters(void),CCharacterSelect__NumberOfCharacters); +#endif +#ifdef CCharacterSelect__IsEvil_x +FUNCTION_AT_ADDRESS(unsigned char CCharacterSelect::IsEvil(int,int,int),CCharacterSelect__IsEvil); +#endif +#ifdef CCharacterSelect__SelectCharacter_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::SelectCharacter(int,int),CCharacterSelect__SelectCharacter); +#endif +#ifdef CCharacterSelect__SetLoadZonePlayerLocation_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::SetLoadZonePlayerLocation(void),CCharacterSelect__SetLoadZonePlayerLocation); +#endif +#ifdef CCharacterSelect__DeleteCharacter_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::DeleteCharacter(void),CCharacterSelect__DeleteCharacter); +#endif +#ifdef CCharacterSelect__UpdateButtonNames_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::UpdateButtonNames(void),CCharacterSelect__UpdateButtonNames); +#endif +#ifdef CCharacterSelect__SetLocationByClass_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::SetLocationByClass(class EQPlayer *,bool,int),CCharacterSelect__SetLocationByClass); +#endif +#ifdef CCharacterSelect__CreateExplorationModePlayers_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::CreateExplorationModePlayers(void),CCharacterSelect__CreateExplorationModePlayers); +#endif +#ifdef CCharacterSelect__RemoveExplorationModePlayers_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::RemoveExplorationModePlayers(void),CCharacterSelect__RemoveExplorationModePlayers); +#endif +#ifdef CCharacterSelect__SetRoomLocationByIndex_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::SetRoomLocationByIndex(int,class EQPlayer *),CCharacterSelect__SetRoomLocationByIndex); +#endif +#ifdef CCharacterSelect__SwitchModel_x +FUNCTION_AT_ADDRESS(void CCharacterSelect::SwitchModel(class EQPlayer *,unsigned char,int,unsigned char,unsigned char),CCharacterSelect__SwitchModel); +#endif +#ifdef CChatManager__CChatManager_x +FUNCTION_AT_ADDRESS( CChatManager::CChatManager(void),CChatManager__CChatManager); +#endif +#ifdef CChatManager__dCChatManager_x +FUNCTION_AT_ADDRESS( CChatManager::~CChatManager(void),CChatManager__dCChatManager); +#endif +#ifdef CBookWnd__Init_x +FUNCTION_AT_ADDRESS(void CBookWnd::Init(void),CBookWnd__Init); +#endif +#ifdef CColorPickerWnd__Init_x +FUNCTION_AT_ADDRESS(void CColorPickerWnd::Init(void),CColorPickerWnd__Init); +#endif +#ifdef CCompassWnd__Init_x +FUNCTION_AT_ADDRESS(void CCompassWnd::Init(void),CCompassWnd__Init); +#endif +#ifdef CContainerWnd__Init_x +FUNCTION_AT_ADDRESS(void CContainerWnd::Init(void),CContainerWnd__Init); +#endif +#ifdef CGiveWnd__Init_x +FUNCTION_AT_ADDRESS(void CGiveWnd::Init(void),CGiveWnd__Init); +#endif +#ifdef CHelpWnd__Init_x +FUNCTION_AT_ADDRESS(void CHelpWnd::Init(void),CHelpWnd__Init); +#endif +#ifdef CMusicPlayerWnd__Init_x +FUNCTION_AT_ADDRESS(void CMusicPlayerWnd::Init(void),CMusicPlayerWnd__Init); +#endif +#ifdef CNoteWnd__Init_x +FUNCTION_AT_ADDRESS(void CNoteWnd::Init(void),CNoteWnd__Init); +#endif +#ifdef CPetInfoWnd__Init_x +FUNCTION_AT_ADDRESS(void CPetInfoWnd::Init(void),CPetInfoWnd__Init); +#endif +#ifdef CPlayerNotesWnd__Init_x +FUNCTION_AT_ADDRESS(void CPlayerNotesWnd::Init(void),CPlayerNotesWnd__Init); +#endif +#ifdef CTargetWnd__Init_x +FUNCTION_AT_ADDRESS(void CTargetWnd::Init(void),CTargetWnd__Init); +#endif +#ifdef UdpManager__ProcessIcmpErrors_x +FUNCTION_AT_ADDRESS(void UdpManager::ProcessIcmpErrors(void),UdpManager__ProcessIcmpErrors); +#endif +#ifdef CRaid__dCRaid_x +FUNCTION_AT_ADDRESS( CRaid::~CRaid(void),CRaid__dCRaid); +#endif +#ifdef EQ_Note__dEQ_Note_x +FUNCTION_AT_ADDRESS( EQ_Note::~EQ_Note(void),EQ_Note__dEQ_Note); +#endif +#ifdef EQ_Skill__dEQ_Skill_x +FUNCTION_AT_ADDRESS( EQ_Skill::~EQ_Skill(void),EQ_Skill__dEQ_Skill); +#endif +#ifdef EQAnimation__dEQAnimation_x +FUNCTION_AT_ADDRESS( EQAnimation::~EQAnimation(void),EQAnimation__dEQAnimation); +#endif +#ifdef KeypressHandler__dKeypressHandler_x +FUNCTION_AT_ADDRESS( KeypressHandler::~KeypressHandler(void),KeypressHandler__dKeypressHandler); +#endif +#ifdef EQNewPlayerAnimation__InitAnimationData_x +FUNCTION_AT_ADDRESS(void __cdecl EQNewPlayerAnimation::InitAnimationData(void),EQNewPlayerAnimation__InitAnimationData); +#endif +#ifdef CAAWnd__CancelAASpend_x +FUNCTION_AT_ADDRESS(void CAAWnd::CancelAASpend(void),CAAWnd__CancelAASpend); +#endif +#ifdef CChatManager__Process_x +FUNCTION_AT_ADDRESS(void CChatManager::Process(void),CChatManager__Process); +#endif +#ifdef CDisplay__DefineSoloMode_x +FUNCTION_AT_ADDRESS(void CDisplay::DefineSoloMode(void),CDisplay__DefineSoloMode); +#endif +#ifdef CEverQuest__InitCommands_x +FUNCTION_AT_ADDRESS(void CEverQuest::InitCommands(void),CEverQuest__InitCommands); +#endif +#ifdef CInvSlotMgr__Process_x +FUNCTION_AT_ADDRESS(void CInvSlotMgr::Process(void),CInvSlotMgr__Process); +#endif +#ifdef EQMissile__LeaveTrail_x +FUNCTION_AT_ADDRESS(void EQMissile::LeaveTrail(void),EQMissile__LeaveTrail); +#endif +#ifdef CChatManager__Activate_x +FUNCTION_AT_ADDRESS(void CChatManager::Activate(void),CChatManager__Activate); +#endif +#ifdef CChatManager__Deactivate_x +FUNCTION_AT_ADDRESS(void CChatManager::Deactivate(void),CChatManager__Deactivate); +#endif +#ifdef CChatManager__LoadChatInis_x +FUNCTION_AT_ADDRESS(void CChatManager::LoadChatInis(void),CChatManager__LoadChatInis); +#endif +#ifdef CChatManager__CreateChatWindow_x +FUNCTION_AT_ADDRESS(void CChatManager::CreateChatWindow(void),CChatManager__CreateChatWindow); +#endif +#ifdef CChatManager__CreateChatWindow1_x +FUNCTION_AT_ADDRESS(void CChatManager::CreateChatWindow(char *,char *,int,int,int,char *,int),CChatManager__CreateChatWindow1); +#endif +#ifdef CChatManager__FreeChatWindow_x +FUNCTION_AT_ADDRESS(void CChatManager::FreeChatWindow(class CChatWindow *),CChatManager__FreeChatWindow); +#endif +#ifdef CChatManager__GetActiveChatWindow_x +FUNCTION_AT_ADDRESS(class CChatWindow * CChatManager::GetActiveChatWindow(void),CChatManager__GetActiveChatWindow); +#endif +#ifdef CChatManager__AddText_x +FUNCTION_AT_ADDRESS(void CChatManager::AddText(class CXStr,int),CChatManager__AddText); +#endif +#ifdef CChatManager__SetChannelMap_x +FUNCTION_AT_ADDRESS(void CChatManager::SetChannelMap(int,class CChatWindow *),CChatManager__SetChannelMap); +#endif +#ifdef CChatManager__ClearChannelMap_x +FUNCTION_AT_ADDRESS(void CChatManager::ClearChannelMap(int),CChatManager__ClearChannelMap); +#endif +#ifdef CChatManager__GetChannelFromColor_x +FUNCTION_AT_ADDRESS(int CChatManager::GetChannelFromColor(int),CChatManager__GetChannelFromColor); +#endif +#ifdef CChatManager__GetChannelMap_x +FUNCTION_AT_ADDRESS(class CChatWindow * CChatManager::GetChannelMap(int),CChatManager__GetChannelMap); +#endif +#ifdef CChatManager__ClearChannelMaps_x +FUNCTION_AT_ADDRESS(void CChatManager::ClearChannelMaps(class CChatWindow *),CChatManager__ClearChannelMaps); +#endif +#ifdef CChatManager__SetActiveChatWindow_x +FUNCTION_AT_ADDRESS(void CChatManager::SetActiveChatWindow(class CChatWindow *),CChatManager__SetActiveChatWindow); +#endif +#ifdef CChatManager__SetLockedActiveChatWindow_x +FUNCTION_AT_ADDRESS(void CChatManager::SetLockedActiveChatWindow(class CChatWindow *),CChatManager__SetLockedActiveChatWindow); +#endif +#ifdef CChatManager__GetRGBAFromIndex_x +FUNCTION_AT_ADDRESS(unsigned long CChatManager::GetRGBAFromIndex(int),CChatManager__GetRGBAFromIndex); +#endif +#ifdef CChatManager__InitContextMenu_x +FUNCTION_AT_ADDRESS(int CChatManager::InitContextMenu(class CChatWindow *),CChatManager__InitContextMenu); +#endif +#ifdef CChatManager__UpdateContextMenus_x +FUNCTION_AT_ADDRESS(void CChatManager::UpdateContextMenus(class CChatWindow *),CChatManager__UpdateContextMenus); +#endif +#ifdef CChatManager__UpdateTellMenus_x +FUNCTION_AT_ADDRESS(void CChatManager::UpdateTellMenus(class CChatWindow *),CChatManager__UpdateTellMenus); +#endif +#ifdef CChatManager__GetAllVisibleText_x +FUNCTION_AT_ADDRESS(class CXStr CChatManager::GetAllVisibleText(class CXStr),CChatManager__GetAllVisibleText); +#endif +#ifdef CChatWindow__GetOutputWnd_x +FUNCTION_AT_ADDRESS(class CStmlWnd * CChatWindow::GetOutputWnd(void),CChatWindow__GetOutputWnd); +#endif +#ifdef CContextMenuManager__GetDefaultMenuIndex_x +FUNCTION_AT_ADDRESS(int CContextMenuManager::GetDefaultMenuIndex(void),CContextMenuManager__GetDefaultMenuIndex); +#endif +#ifdef CChatWindow__CChatWindow_x +FUNCTION_AT_ADDRESS( CChatWindow::CChatWindow(class CXWnd *),CChatWindow__CChatWindow); +#endif +#ifdef CChatWindow__AddOutputText_x +FUNCTION_AT_ADDRESS(void CChatWindow::AddOutputText(class CXStr,int),CChatWindow__AddOutputText); +#endif +#ifdef CChatWindow__HistoryBack_x +FUNCTION_AT_ADDRESS(void CChatWindow::HistoryBack(void),CChatWindow__HistoryBack); +#endif +#ifdef CChatWindow__HistoryForward_x +FUNCTION_AT_ADDRESS(void CChatWindow::HistoryForward(void),CChatWindow__HistoryForward); +#endif +#ifdef CChatWindow__AddHistory_x +FUNCTION_AT_ADDRESS(void CChatWindow::AddHistory(class CXStr),CChatWindow__AddHistory); +#endif +#ifdef CChatWindow__GetInputText_x +FUNCTION_AT_ADDRESS(class CXStr CChatWindow::GetInputText(void),CChatWindow__GetInputText); +#endif +#ifdef CChatWindow__PageUp_x +FUNCTION_AT_ADDRESS(void CChatWindow::PageUp(void),CChatWindow__PageUp); +#endif +#ifdef CChatWindow__PageDown_x +FUNCTION_AT_ADDRESS(void CChatWindow::PageDown(void),CChatWindow__PageDown); +#endif +#ifdef CChatWindow__SetChatFont_x +FUNCTION_AT_ADDRESS(void CChatWindow::SetChatFont(int),CChatWindow__SetChatFont); +#endif +#ifdef CChatWindow__Clear_x +FUNCTION_AT_ADDRESS(void CChatWindow::Clear(void),CChatWindow__Clear); +#endif +#ifdef CStmlWnd__GetSTMLText_x +FUNCTION_AT_ADDRESS(class CXStr CStmlWnd::GetSTMLText(void)const, CStmlWnd__GetSTMLText); +#endif +#ifdef CChatWindow__GetInputWnd_x +FUNCTION_AT_ADDRESS(class CEditWnd * CChatWindow::GetInputWnd(void),CChatWindow__GetInputWnd); +#endif +#ifdef CChatWindow__WndNotification_x +FUNCTION_AT_ADDRESS(int CChatWindow::WndNotification(class CXWnd *,unsigned __int32,void *),CChatWindow__WndNotification); +#endif +#ifdef CColorPickerWnd__CColorPickerWnd_x +FUNCTION_AT_ADDRESS( CColorPickerWnd::CColorPickerWnd(class CXWnd *),CColorPickerWnd__CColorPickerWnd); +#endif +#ifdef CColorPickerWnd__SetTemplateColor_x +FUNCTION_AT_ADDRESS(void CColorPickerWnd::SetTemplateColor(int,unsigned long),CColorPickerWnd__SetTemplateColor); +#endif +#ifdef CColorPickerWnd__Activate_x +FUNCTION_AT_ADDRESS(void CColorPickerWnd::Activate(class CXWnd *,unsigned long),CColorPickerWnd__Activate); +#endif +#ifdef CColorPickerWnd__SetCurrentColor_x +FUNCTION_AT_ADDRESS(void CColorPickerWnd::SetCurrentColor(unsigned long),CColorPickerWnd__SetCurrentColor); +#endif +#ifdef CColorPickerWnd__UpdateCurrentColor_x +FUNCTION_AT_ADDRESS(void CColorPickerWnd::UpdateCurrentColor(void),CColorPickerWnd__UpdateCurrentColor); +#endif +#ifdef CColorPickerWnd__CheckMaxEditWnd_x +FUNCTION_AT_ADDRESS(void CColorPickerWnd::CheckMaxEditWnd(void),CColorPickerWnd__CheckMaxEditWnd); +#endif +#ifdef CColorPickerWnd__UpdateEditWndFromSlider_x +FUNCTION_AT_ADDRESS(void CColorPickerWnd::UpdateEditWndFromSlider(class CSliderWnd *,class CEditWnd *,int *),CColorPickerWnd__UpdateEditWndFromSlider); +#endif +#ifdef CColorPickerWnd__UpdateSliderFromEditWnd_x +FUNCTION_AT_ADDRESS(void CColorPickerWnd::UpdateSliderFromEditWnd(class CSliderWnd *,class CEditWnd *,int *),CColorPickerWnd__UpdateSliderFromEditWnd); +#endif +#ifdef CCompassWnd__CCompassWnd_x +FUNCTION_AT_ADDRESS( CCompassWnd::CCompassWnd(class CXWnd *),CCompassWnd__CCompassWnd); +#endif +#ifdef CCompassWnd__Activate_x +FUNCTION_AT_ADDRESS(void CCompassWnd::Activate(void),CCompassWnd__Activate); +#endif +#ifdef CCompassWnd__PickNewTarget_x +FUNCTION_AT_ADDRESS(void CCompassWnd::PickNewTarget(void),CCompassWnd__PickNewTarget); +#endif +#ifdef CCompassWnd__SetSpeed_x +FUNCTION_AT_ADDRESS(void CCompassWnd::SetSpeed(void),CCompassWnd__SetSpeed); +#endif +#ifdef CCompassWnd__SenseHeading_x +FUNCTION_AT_ADDRESS(void CCompassWnd::SenseHeading(void),CCompassWnd__SenseHeading); +#endif +#ifdef CConfirmationDialog__CConfirmationDialog_x +FUNCTION_AT_ADDRESS( CConfirmationDialog::CConfirmationDialog(class CXWnd *),CConfirmationDialog__CConfirmationDialog); +#endif +#ifdef CConfirmationDialog__Init_x +FUNCTION_AT_ADDRESS(void CConfirmationDialog::Init(void),CConfirmationDialog__Init); +#endif +#ifdef CConfirmationDialog__Activate_x +FUNCTION_AT_ADDRESS(void CConfirmationDialog::Activate(int,unsigned int,char const *,int,int,int,int),CConfirmationDialog__Activate); +#endif +#ifdef CConfirmationDialog__Deactivate_x +FUNCTION_AT_ADDRESS(void CConfirmationDialog::Deactivate(void),CConfirmationDialog__Deactivate); +#endif +#ifdef CConfirmationDialog__ExpireCurrentDialog_x +FUNCTION_AT_ADDRESS(void CConfirmationDialog::ExpireCurrentDialog(void),CConfirmationDialog__ExpireCurrentDialog); +#endif +#ifdef CConfirmationDialog__HandleButtonYesPressed_x +FUNCTION_AT_ADDRESS(void CConfirmationDialog::HandleButtonYesPressed(void),CConfirmationDialog__HandleButtonYesPressed); +#endif +#ifdef CConfirmationDialog__HandleButtonNoPressed_x +FUNCTION_AT_ADDRESS(void CConfirmationDialog::HandleButtonNoPressed(void),CConfirmationDialog__HandleButtonNoPressed); +#endif +#ifdef CConfirmationDialog__HandleButtonOkPressed_x +FUNCTION_AT_ADDRESS(void CConfirmationDialog::HandleButtonOkPressed(void),CConfirmationDialog__HandleButtonOkPressed); +#endif +#ifdef CConfirmationDialog__ProcessYes_x +FUNCTION_AT_ADDRESS(void CConfirmationDialog::ProcessYes(void),CConfirmationDialog__ProcessYes); +#endif +#ifdef CConfirmationDialog__ResetFocusOnClose_x +FUNCTION_AT_ADDRESS(void CConfirmationDialog::ResetFocusOnClose(void),CConfirmationDialog__ResetFocusOnClose); +#endif +#ifdef CConfirmationDialog__ProcessNo_x +FUNCTION_AT_ADDRESS(void CConfirmationDialog::ProcessNo(int),CConfirmationDialog__ProcessNo); +#endif +#ifdef CConfirmationDialog__SetNameApprovalData_x +FUNCTION_AT_ADDRESS(void CConfirmationDialog::SetNameApprovalData(char *,char *,int,int,char *),CConfirmationDialog__SetNameApprovalData); +#endif +#ifdef CConfirmationDialog__WndNotification_x +FUNCTION_AT_ADDRESS( int CConfirmationDialog::WndNotification(class CXWnd *,unsigned __int32,void *),CConfirmationDialog__WndNotification); +#endif +#ifdef CContainerMgr__GetFreeContainerWnd_x +FUNCTION_AT_ADDRESS(class CContainerWnd * CContainerMgr::GetFreeContainerWnd(void),CContainerMgr__GetFreeContainerWnd); +#endif +#ifdef CContainerMgr__CContainerMgr_x +FUNCTION_AT_ADDRESS( CContainerMgr::CContainerMgr(void),CContainerMgr__CContainerMgr); +#endif +#ifdef CContainerMgr__Process_x +FUNCTION_AT_ADDRESS(void CContainerMgr::Process(void),CContainerMgr__Process); +#endif +#ifdef CContainerMgr__OpenWorldContainer_x +FUNCTION_AT_ADDRESS(void CContainerMgr::OpenWorldContainer(class EQ_Container *,unsigned long),CContainerMgr__OpenWorldContainer); +#endif +#ifdef CContainerMgr__SetWorldContainerItem_x +FUNCTION_AT_ADDRESS(void CContainerMgr::SetWorldContainerItem(class EQ_Item *,int),CContainerMgr__SetWorldContainerItem); +#endif +#ifdef CContainerMgr__GetWorldContainerItem_x +FUNCTION_AT_ADDRESS(class EQ_Item * CContainerMgr::GetWorldContainerItem(int),CContainerMgr__GetWorldContainerItem); +#endif +#ifdef CContainerMgr__ClearWorldContainerItems_x +FUNCTION_AT_ADDRESS(void CContainerMgr::ClearWorldContainerItems(void),CContainerMgr__ClearWorldContainerItems); +#endif +#ifdef CContainerMgr__OpenContainer_x +FUNCTION_AT_ADDRESS(void CContainerMgr::OpenContainer(class EQ_Container *,int),CContainerMgr__OpenContainer); +#endif +#ifdef CContainerMgr__CloseEQContainer_x +FUNCTION_AT_ADDRESS(void CContainerMgr::CloseEQContainer(class EQ_Container *),CContainerMgr__CloseEQContainer); +#endif +#ifdef CContainerMgr__CloseContainer_x +FUNCTION_AT_ADDRESS(void CContainerMgr::CloseContainer(class EQ_Container *,bool),CContainerMgr__CloseContainer); +#endif +#ifdef CContainerMgr__CloseAllContainers_x +FUNCTION_AT_ADDRESS(bool CContainerMgr::CloseAllContainers(void),CContainerMgr__CloseAllContainers); +#endif +#ifdef CContainerWnd__CContainerWnd_x +FUNCTION_AT_ADDRESS( CContainerWnd::CContainerWnd(class CXWnd *),CContainerWnd__CContainerWnd); +#endif +#ifdef CContainerWnd__Activate_x +FUNCTION_AT_ADDRESS(void CContainerWnd::Activate(void),CContainerWnd__Activate); +#endif +#ifdef CHelpWnd__Activate_x +FUNCTION_AT_ADDRESS(void CHelpWnd::Activate(void),CHelpWnd__Activate); +#endif +#ifdef CContainerWnd__HandleCombine_x +FUNCTION_AT_ADDRESS(void CContainerWnd::HandleCombine(void),CContainerWnd__HandleCombine); +#endif +#ifdef CContainerWnd__SetContainer_x +FUNCTION_AT_ADDRESS(void CContainerWnd::SetContainer(class EQ_Container *,int),CContainerWnd__SetContainer); +#endif +#ifdef CContainerWnd__CheckCloseable_x +FUNCTION_AT_ADDRESS(void CContainerWnd::CheckCloseable(void),CContainerWnd__CheckCloseable); +#endif +#ifdef CContainerWnd__ContainsNoDrop_x +FUNCTION_AT_ADDRESS(bool CContainerWnd::ContainsNoDrop(void),CContainerWnd__ContainsNoDrop); +#endif +#ifdef CXRect__operator_or_x +FUNCTION_AT_ADDRESS(class CXRect CXRect::operator|(class CXRect)const ,CXRect__operator_or); +#endif +#ifdef CContextMenu__CContextMenu_x +FUNCTION_AT_ADDRESS( CContextMenu::CContextMenu(class CXWnd *,unsigned __int32,class CXRect),CContextMenu__CContextMenu); +#endif +#ifdef CContextMenu__AddMenuItem_x +FUNCTION_AT_ADDRESS(int CContextMenu::AddMenuItem(class CXStr,unsigned int,bool,unsigned long),CContextMenu__AddMenuItem); +#endif +#ifdef CContextMenu__AddSeparator_x +FUNCTION_AT_ADDRESS(int CContextMenu::AddSeparator(void),CContextMenu__AddSeparator); +#endif +#ifdef CContextMenu__RemoveAllMenuItems_x +FUNCTION_AT_ADDRESS(void CContextMenu::RemoveAllMenuItems(void),CContextMenu__RemoveAllMenuItems); +#endif +#ifdef CContextMenu__EnableMenuItem_x +FUNCTION_AT_ADDRESS(void CContextMenu::EnableMenuItem(int,bool),CContextMenu__EnableMenuItem); +#endif +#ifdef CContextMenu__CheckMenuItem_x +FUNCTION_AT_ADDRESS(void CContextMenu::CheckMenuItem(int,bool,bool),CContextMenu__CheckMenuItem); +#endif +#ifdef CContextMenu__Activate_x +FUNCTION_AT_ADDRESS(void CContextMenu::Activate(class CXPoint,int,int),CContextMenu__Activate); +#endif +#ifdef CContextMenuManager__CContextMenuManager_x +FUNCTION_AT_ADDRESS( CContextMenuManager::CContextMenuManager(class CXWnd *,unsigned __int32,class CXRect),CContextMenuManager__CContextMenuManager); +#endif +#ifdef CContextMenuManager__RemoveMenu_x +FUNCTION_AT_ADDRESS(int CContextMenuManager::RemoveMenu(int,bool),CContextMenuManager__RemoveMenu); +#endif +#ifdef CContextMenuManager__AddMenu_x +FUNCTION_AT_ADDRESS(int CContextMenuManager::AddMenu(class CContextMenu *),CContextMenuManager__AddMenu); +#endif +#ifdef CContextMenuManager__PopupMenu_x +FUNCTION_AT_ADDRESS(int CContextMenuManager::PopupMenu(int,class CXPoint,class CXWnd *),CContextMenuManager__PopupMenu); +#endif +#ifdef CContextMenuManager__Flush_x +FUNCTION_AT_ADDRESS(void CContextMenuManager::Flush(void),CContextMenuManager__Flush); +#endif +#ifdef CContextMenuManager__CreateDefaultMenu_x +FUNCTION_AT_ADDRESS(void CContextMenuManager::CreateDefaultMenu(void),CContextMenuManager__CreateDefaultMenu); +#endif +#ifdef CContextMenuManager__WarnDefaultMenu_x +FUNCTION_AT_ADDRESS(void CContextMenuManager::WarnDefaultMenu(class CXWnd *),CContextMenuManager__WarnDefaultMenu); +#endif +#ifdef CContextMenuManager__HandleWindowMenuCommands_x +FUNCTION_AT_ADDRESS(int CContextMenuManager::HandleWindowMenuCommands(class CXWnd *,int),CContextMenuManager__HandleWindowMenuCommands); +#endif +#ifdef CXRect__Width_x +FUNCTION_AT_ADDRESS(int CXRect::Width(void)const ,CXRect__Width); +#endif +#ifdef CCursorAttachment__CCursorAttachment_x +FUNCTION_AT_ADDRESS( CCursorAttachment::CCursorAttachment(class CXWnd *),CCursorAttachment__CCursorAttachment); +#endif +#ifdef CCursorAttachment__Init_x +FUNCTION_AT_ADDRESS(void CCursorAttachment::Init(void),CCursorAttachment__Init); +#endif +#ifdef CCursorAttachment__Activate_x +FUNCTION_AT_ADDRESS(void CCursorAttachment::Activate(class CTextureAnimation *,int,int,int),CCursorAttachment__Activate); +#endif +#ifdef CCursorAttachment__DrawButtonText_x +FUNCTION_AT_ADDRESS(void CCursorAttachment::DrawButtonText(void)const ,CCursorAttachment__DrawButtonText); +#endif +#ifdef CCursorAttachment__DrawQuantity_x +FUNCTION_AT_ADDRESS(void CCursorAttachment::DrawQuantity(void)const ,CCursorAttachment__DrawQuantity); +#endif +#ifdef CCursorAttachment__IsOkToActivate_x +FUNCTION_AT_ADDRESS(bool CCursorAttachment::IsOkToActivate(int),CCursorAttachment__IsOkToActivate); +#endif +#ifdef CCursorAttachment__RemoveAttachment_x +FUNCTION_AT_ADDRESS(bool CCursorAttachment::RemoveAttachment(void),CCursorAttachment__RemoveAttachment); +#endif +#ifdef CTextureAnimation__Reset_x +FUNCTION_AT_ADDRESS(void CTextureAnimation::Reset(void),CTextureAnimation__Reset); +#endif +#ifdef CEditLabelWnd__CEditLabelWnd_x +FUNCTION_AT_ADDRESS( CEditLabelWnd::CEditLabelWnd(class CXWnd *),CEditLabelWnd__CEditLabelWnd); +#endif +#ifdef CEditLabelWnd__Activate_x +FUNCTION_AT_ADDRESS(void CEditLabelWnd::Activate(class CXWnd *,char *,int,unsigned long),CEditLabelWnd__Activate); +#endif +#ifdef CEQSuiteTextureLoader__dCEQSuiteTextureLoader_x +FUNCTION_AT_ADDRESS( CEQSuiteTextureLoader::~CEQSuiteTextureLoader(void),CEQSuiteTextureLoader__dCEQSuiteTextureLoader); +#endif +#ifdef CEQSuiteTextureLoader__CreateTexture_x +FUNCTION_AT_ADDRESS(unsigned int CEQSuiteTextureLoader::CreateTexture(class CUITextureInfo const &),CEQSuiteTextureLoader__CreateTexture); +#endif +#ifdef CEQSuiteTextureLoader__UnloadAllTextures_x +FUNCTION_AT_ADDRESS(void CEQSuiteTextureLoader::UnloadAllTextures(void),CEQSuiteTextureLoader__UnloadAllTextures); +#endif +#ifdef CEQSuiteTextureLoader__GetTexture_x +FUNCTION_AT_ADDRESS(struct T3D_tagBMINFO * CEQSuiteTextureLoader::GetTexture(class CUITextureInfo const &),CEQSuiteTextureLoader__GetTexture); +#endif +#ifdef CUITextureInfo__GetName_x +FUNCTION_AT_ADDRESS(class CXStr CUITextureInfo::GetName(void)const ,CUITextureInfo__GetName); +#endif +#ifdef CEQSuiteTextureLoader__CEQSuiteTextureLoader_x +FUNCTION_AT_ADDRESS( CEQSuiteTextureLoader::CEQSuiteTextureLoader(void),CEQSuiteTextureLoader__CEQSuiteTextureLoader); +#endif +#ifdef CExploreModeWnd__CExploreModeWnd_x +FUNCTION_AT_ADDRESS( CExploreModeWnd::CExploreModeWnd(class CXWnd *),CExploreModeWnd__CExploreModeWnd); +#endif +#ifdef CExploreModeWnd__Activate_x +FUNCTION_AT_ADDRESS(void CExploreModeWnd::Activate(void),CExploreModeWnd__Activate); +#endif +#ifdef CFacePick__CFacePick_x +FUNCTION_AT_ADDRESS( CFacePick::CFacePick(class CXWnd *),CFacePick__CFacePick); +#endif +#ifdef CFacePick__Init_x +FUNCTION_AT_ADDRESS(void CFacePick::Init(void),CFacePick__Init); +#endif +#ifdef CFacePick__ShowButtonGroup_x +FUNCTION_AT_ADDRESS(void CFacePick::ShowButtonGroup(int,bool),CFacePick__ShowButtonGroup); +#endif +#ifdef CFacePick__Activate_x +FUNCTION_AT_ADDRESS(void CFacePick::Activate(void),CFacePick__Activate); +#endif +#ifdef CFacePick__SetFaceSelectionsFromPlayer_x +FUNCTION_AT_ADDRESS(void CFacePick::SetFaceSelectionsFromPlayer(void),CFacePick__SetFaceSelectionsFromPlayer); +#endif +#ifdef CFacePick__CycleThroughFHEB_x +FUNCTION_AT_ADDRESS(void CFacePick::CycleThroughFHEB(int,int),CFacePick__CycleThroughFHEB); +#endif +#ifdef CFeedbackWnd__CFeedbackWnd_x +FUNCTION_AT_ADDRESS( CFeedbackWnd::CFeedbackWnd(class CXWnd *),CFeedbackWnd__CFeedbackWnd); +#endif +#ifdef CFeedbackWnd__Activate_x +FUNCTION_AT_ADDRESS(void CFeedbackWnd::Activate(void),CFeedbackWnd__Activate); +#endif +#ifdef CFileSelectionWnd__CFileSelectionWnd_x +FUNCTION_AT_ADDRESS( CFileSelectionWnd::CFileSelectionWnd(class CXWnd *),CFileSelectionWnd__CFileSelectionWnd); +#endif +#ifdef CFileSelectionWnd__Activate_x +FUNCTION_AT_ADDRESS(void CFileSelectionWnd::Activate(class CXWnd *,int),CFileSelectionWnd__Activate); +#endif +#ifdef CFileSelectionWnd__Callback_x +FUNCTION_AT_ADDRESS(void CFileSelectionWnd::Callback(bool),CFileSelectionWnd__Callback); +#endif +#ifdef CFileSelectionWnd__MakeFilePath_x +FUNCTION_AT_ADDRESS(void CFileSelectionWnd::MakeFilePath(void),CFileSelectionWnd__MakeFilePath); +#endif +#ifdef CFileSelectionWnd__GoSubdirectory_x +FUNCTION_AT_ADDRESS(void CFileSelectionWnd::GoSubdirectory(struct _ITEMIDLIST *),CFileSelectionWnd__GoSubdirectory); +#endif +#ifdef CFileSelectionWnd__UpdateButtons_x +FUNCTION_AT_ADDRESS(void CFileSelectionWnd::UpdateButtons(void),CFileSelectionWnd__UpdateButtons); +#endif +#ifdef CFileSelectionWnd__DirectoryEmpty_x +FUNCTION_AT_ADDRESS(bool CFileSelectionWnd::DirectoryEmpty(struct IShellFolder *,struct _ITEMIDLIST *),CFileSelectionWnd__DirectoryEmpty); +#endif +#ifdef CFileSelectionWnd__UpdateFileList_x +FUNCTION_AT_ADDRESS(void CFileSelectionWnd::UpdateFileList(void),CFileSelectionWnd__UpdateFileList); +#endif +#ifdef CFileSelectionWnd__ClearFileList_x +FUNCTION_AT_ADDRESS(void CFileSelectionWnd::ClearFileList(void),CFileSelectionWnd__ClearFileList); +#endif +#ifdef CFileSelectionWnd__GetPath_x +FUNCTION_AT_ADDRESS(unsigned long CFileSelectionWnd::GetPath(struct IShellFolder *,struct _ITEMIDLIST *,bool,class CXStr &),CFileSelectionWnd__GetPath); +#endif +#ifdef CFileSelectionWnd__GetSelectedFileCount_x +FUNCTION_AT_ADDRESS(int CFileSelectionWnd::GetSelectedFileCount(void),CFileSelectionWnd__GetSelectedFileCount); +#endif +#ifdef CFileSelectionWnd__GetSelectedFile_x +FUNCTION_AT_ADDRESS(class CXStr CFileSelectionWnd::GetSelectedFile(int),CFileSelectionWnd__GetSelectedFile); +#endif +#ifdef CXStr__Left_x +FUNCTION_AT_ADDRESS(class CXStr CXStr::Left(int)const ,CXStr__Left); +#endif +#ifdef CXStr__Right_x +FUNCTION_AT_ADDRESS(class CXStr CXStr::Right(int)const ,CXStr__Right); +#endif +#ifdef CFriendsWnd__CFriendsWnd_x +FUNCTION_AT_ADDRESS( CFriendsWnd::CFriendsWnd(class CXWnd *),CFriendsWnd__CFriendsWnd); +#endif +#ifdef CFriendsWnd__UpdateFriendsList_x +FUNCTION_AT_ADDRESS(void CFriendsWnd::UpdateFriendsList(void),CFriendsWnd__UpdateFriendsList); +#endif +#ifdef CFriendsWnd__UpdateIgnoreList_x +FUNCTION_AT_ADDRESS(void CFriendsWnd::UpdateIgnoreList(void),CFriendsWnd__UpdateIgnoreList); +#endif +#ifdef CFriendsWnd__Activate_x +FUNCTION_AT_ADDRESS(void CFriendsWnd::Activate(void),CFriendsWnd__Activate); +#endif +#ifdef CFriendsWnd__AddFriend_x +FUNCTION_AT_ADDRESS(void CFriendsWnd::AddFriend(void),CFriendsWnd__AddFriend); +#endif +#ifdef CFriendsWnd__AddIgnore_x +FUNCTION_AT_ADDRESS(void CFriendsWnd::AddIgnore(void),CFriendsWnd__AddIgnore); +#endif +#ifdef CFriendsWnd__UpdateButtons_x +FUNCTION_AT_ADDRESS(void CFriendsWnd::UpdateButtons(void),CFriendsWnd__UpdateButtons); +#endif +#ifdef CGemsGameWnd__CGemsGameWnd_x +FUNCTION_AT_ADDRESS( CGemsGameWnd::CGemsGameWnd(class CXWnd *),CGemsGameWnd__CGemsGameWnd); +#endif +#ifdef CGemsGameWnd__Init_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::Init(void),CGemsGameWnd__Init); +#endif +#ifdef CGemsGameWnd__Activate_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::Activate(void),CGemsGameWnd__Activate); +#endif +#ifdef CGemsGameWnd__Restart_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::Restart(void),CGemsGameWnd__Restart); +#endif +#ifdef CGemsGameWnd__AdvanceToNextWave_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::AdvanceToNextWave(void),CGemsGameWnd__AdvanceToNextWave); +#endif +#ifdef CGemsGameWnd__DoMatchScore_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::DoMatchScore(int),CGemsGameWnd__DoMatchScore); +#endif +#ifdef CGemsGameWnd__DrawSpellGem_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::DrawSpellGem(int,class CXRect,int,bool)const ,CGemsGameWnd__DrawSpellGem); +#endif +#ifdef CGemsGameWnd__SetPause_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::SetPause(bool),CGemsGameWnd__SetPause); +#endif +#ifdef CGemsGameWnd__TogglePause_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::TogglePause(void),CGemsGameWnd__TogglePause); +#endif +#ifdef CGemsGameWnd__SetNextUpdate_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::SetNextUpdate(void),CGemsGameWnd__SetNextUpdate); +#endif +#ifdef CGemsGameWnd__GetRndBlockImage_x +FUNCTION_AT_ADDRESS(int CGemsGameWnd::GetRndBlockImage(void),CGemsGameWnd__GetRndBlockImage); +#endif +#ifdef CGemsGameWnd__BadSpecial_x +FUNCTION_AT_ADDRESS(bool CGemsGameWnd::BadSpecial(int)const ,CGemsGameWnd__BadSpecial); +#endif +#ifdef CGemsGameWnd__ActivateSpecialMode_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::ActivateSpecialMode(int),CGemsGameWnd__ActivateSpecialMode); +#endif +#ifdef CGemsGameWnd__GetNextBlock_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::GetNextBlock(void),CGemsGameWnd__GetNextBlock); +#endif +#ifdef CGemsGameWnd__MoveCurBlock_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::MoveCurBlock(int),CGemsGameWnd__MoveCurBlock); +#endif +#ifdef CGemsGameWnd__ProcessMoveCurBlock_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::ProcessMoveCurBlock(int),CGemsGameWnd__ProcessMoveCurBlock); +#endif +#ifdef CGemsGameWnd__LegalBlockMove_x +FUNCTION_AT_ADDRESS(bool CGemsGameWnd::LegalBlockMove(int,int,int,int,bool),CGemsGameWnd__LegalBlockMove); +#endif +#ifdef CGemsGameWnd__MarkHigherBlocksFalling_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::MarkHigherBlocksFalling(int,int),CGemsGameWnd__MarkHigherBlocksFalling); +#endif +#ifdef CGemsGameWnd__ClearBlock_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::ClearBlock(struct _GemsBlock *),CGemsGameWnd__ClearBlock); +#endif +#ifdef CGemsGameWnd__ClearHighScores_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::ClearHighScores(void),CGemsGameWnd__ClearHighScores); +#endif +#ifdef CGemsGameWnd__ReadHighScores_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::ReadHighScores(void),CGemsGameWnd__ReadHighScores); +#endif +#ifdef CGemsGameWnd__WriteHighScores_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::WriteHighScores(void),CGemsGameWnd__WriteHighScores); +#endif +#ifdef CGemsGameWnd__CheckForNewHighScore_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::CheckForNewHighScore(void),CGemsGameWnd__CheckForNewHighScore); +#endif +#ifdef CGemsGameWnd__ProcessMatches_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::ProcessMatches(int),CGemsGameWnd__ProcessMatches); +#endif +#ifdef CGemsGameWnd__CheckForMatches_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::CheckForMatches(int,int),CGemsGameWnd__CheckForMatches); +#endif +#ifdef CGemsGameWnd__MakeBlockDrop_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::MakeBlockDrop(int,int,int),CGemsGameWnd__MakeBlockDrop); +#endif +#ifdef CGemsGameWnd__Update_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::Update(void),CGemsGameWnd__Update); +#endif +#ifdef CGemsGameWnd__UpdateDisplay_x +FUNCTION_AT_ADDRESS(void CGemsGameWnd::UpdateDisplay(void),CGemsGameWnd__UpdateDisplay); +#endif +#ifdef CGiveWnd__CGiveWnd_x +FUNCTION_AT_ADDRESS( CGiveWnd::CGiveWnd(class CXWnd *),CGiveWnd__CGiveWnd); +#endif +#ifdef CGiveWnd__Activate_x +FUNCTION_AT_ADDRESS(void CGiveWnd::Activate(void),CGiveWnd__Activate); +#endif +#ifdef CGiveWnd__UpdateGiveDisplay_x +FUNCTION_AT_ADDRESS(void CGiveWnd::UpdateGiveDisplay(void),CGiveWnd__UpdateGiveDisplay); +#endif +#ifdef CGroupSearchFiltersWnd__CGroupSearchFiltersWnd_x +FUNCTION_AT_ADDRESS( CGroupSearchFiltersWnd::CGroupSearchFiltersWnd(class CXWnd *),CGroupSearchFiltersWnd__CGroupSearchFiltersWnd); +#endif +#ifdef CGroupSearchFiltersWnd__Activate_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::Activate(void),CGroupSearchFiltersWnd__Activate); +#endif +#ifdef CGroupSearchFiltersWnd__ClearUiPointers_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::ClearUiPointers(void),CGroupSearchFiltersWnd__ClearUiPointers); +#endif +#ifdef CGroupSearchFiltersWnd__FetchUiPointers_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::FetchUiPointers(void),CGroupSearchFiltersWnd__FetchUiPointers); +#endif +#ifdef CGroupSearchFiltersWnd__InitPieces_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::InitPieces(void),CGroupSearchFiltersWnd__InitPieces); +#endif +#ifdef CGroupSearchFiltersWnd__ShouldFilterPlayer_x +FUNCTION_AT_ADDRESS(bool CGroupSearchFiltersWnd::ShouldFilterPlayer(char const *,char const *)const ,CGroupSearchFiltersWnd__ShouldFilterPlayer); +#endif +#ifdef CGroupSearchFiltersWnd__UseExclusiveSearchMode_x +FUNCTION_AT_ADDRESS(bool CGroupSearchFiltersWnd::UseExclusiveSearchMode(void)const ,CGroupSearchFiltersWnd__UseExclusiveSearchMode); +#endif +#ifdef CGroupSearchFiltersWnd__HandleUseIgnoreListSelected_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::HandleUseIgnoreListSelected(void),CGroupSearchFiltersWnd__HandleUseIgnoreListSelected); +#endif +#ifdef CGroupSearchFiltersWnd__HandleUseFriendsListSelected_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::HandleUseFriendsListSelected(void),CGroupSearchFiltersWnd__HandleUseFriendsListSelected); +#endif +#ifdef CGroupSearchFiltersWnd__HandleExcludeGuildsSelected_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::HandleExcludeGuildsSelected(void),CGroupSearchFiltersWnd__HandleExcludeGuildsSelected); +#endif +#ifdef CGroupSearchFiltersWnd__HandleDesiredGuildsSelected_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::HandleDesiredGuildsSelected(void),CGroupSearchFiltersWnd__HandleDesiredGuildsSelected); +#endif +#ifdef CGroupSearchFiltersWnd__HandleAddExcludedGuild_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::HandleAddExcludedGuild(void),CGroupSearchFiltersWnd__HandleAddExcludedGuild); +#endif +#ifdef CGroupSearchFiltersWnd__HandleRemoveExcludedGuild_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::HandleRemoveExcludedGuild(void),CGroupSearchFiltersWnd__HandleRemoveExcludedGuild); +#endif +#ifdef CGroupSearchFiltersWnd__HandleRemoveAllExcludedGuilds_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::HandleRemoveAllExcludedGuilds(void),CGroupSearchFiltersWnd__HandleRemoveAllExcludedGuilds); +#endif +#ifdef CGroupSearchFiltersWnd__HandleAddDesiredGuild_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::HandleAddDesiredGuild(void),CGroupSearchFiltersWnd__HandleAddDesiredGuild); +#endif +#ifdef CGroupSearchFiltersWnd__HandleRemoveDesiredGuild_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::HandleRemoveDesiredGuild(void),CGroupSearchFiltersWnd__HandleRemoveDesiredGuild); +#endif +#ifdef CGroupSearchFiltersWnd__HandleRemoveAllDesiredGuilds_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::HandleRemoveAllDesiredGuilds(void),CGroupSearchFiltersWnd__HandleRemoveAllDesiredGuilds); +#endif +#ifdef CGroupSearchFiltersWnd__UseIgnoreList_x +FUNCTION_AT_ADDRESS(bool CGroupSearchFiltersWnd::UseIgnoreList(void)const ,CGroupSearchFiltersWnd__UseIgnoreList); +#endif +#ifdef CGroupSearchFiltersWnd__UseFriendsList_x +FUNCTION_AT_ADDRESS(bool CGroupSearchFiltersWnd::UseFriendsList(void)const ,CGroupSearchFiltersWnd__UseFriendsList); +#endif +#ifdef CGroupSearchFiltersWnd__UseExcludedGuilds_x +FUNCTION_AT_ADDRESS(bool CGroupSearchFiltersWnd::UseExcludedGuilds(void)const ,CGroupSearchFiltersWnd__UseExcludedGuilds); +#endif +#ifdef CGroupSearchFiltersWnd__UseDesiredGuilds_x +FUNCTION_AT_ADDRESS(bool CGroupSearchFiltersWnd::UseDesiredGuilds(void)const ,CGroupSearchFiltersWnd__UseDesiredGuilds); +#endif +#ifdef CGroupSearchFiltersWnd__NameIsInIgnoreList_x +FUNCTION_AT_ADDRESS(bool CGroupSearchFiltersWnd::NameIsInIgnoreList(char const *)const ,CGroupSearchFiltersWnd__NameIsInIgnoreList); +#endif +#ifdef CGroupSearchFiltersWnd__NameIsInFriendsList_x +FUNCTION_AT_ADDRESS(bool CGroupSearchFiltersWnd::NameIsInFriendsList(char const *)const ,CGroupSearchFiltersWnd__NameIsInFriendsList); +#endif +#ifdef CGroupSearchFiltersWnd__GuildIsInExcludedGuildsList_x +FUNCTION_AT_ADDRESS(bool CGroupSearchFiltersWnd::GuildIsInExcludedGuildsList(char const *)const ,CGroupSearchFiltersWnd__GuildIsInExcludedGuildsList); +#endif +#ifdef CGroupSearchFiltersWnd__GuildIsInDesiredGuildsList_x +FUNCTION_AT_ADDRESS(bool CGroupSearchFiltersWnd::GuildIsInDesiredGuildsList(char const *)const ,CGroupSearchFiltersWnd__GuildIsInDesiredGuildsList); +#endif +#ifdef CGroupSearchFiltersWnd__Save_x +FUNCTION_AT_ADDRESS(void CGroupSearchFiltersWnd::Save(void)const ,CGroupSearchFiltersWnd__Save); +#endif +#ifdef CGroupSearchFiltersWnd__Load_x +FUNCTION_AT_ADDRESS(bool CGroupSearchFiltersWnd::Load(void),CGroupSearchFiltersWnd__Load); +#endif +#ifdef CGroupSearchWnd__CGroupSearchWnd_x +FUNCTION_AT_ADDRESS( CGroupSearchWnd::CGroupSearchWnd(class CXWnd *),CGroupSearchWnd__CGroupSearchWnd); +#endif +#ifdef CGroupSearchWnd__Activate_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::Activate(int),CGroupSearchWnd__Activate); +#endif +#ifdef CGroupSearchWnd__ClearUiPointers_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::ClearUiPointers(void),CGroupSearchWnd__ClearUiPointers); +#endif +#ifdef CGroupSearchWnd__FetchUiPointers_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::FetchUiPointers(void),CGroupSearchWnd__FetchUiPointers); +#endif +#ifdef CGroupSearchWnd__ResetGroupList_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::ResetGroupList(void),CGroupSearchWnd__ResetGroupList); +#endif +#ifdef CGroupSearchWnd__AddGroupResult_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::AddGroupResult(struct LfgGroupResult const *),CGroupSearchWnd__AddGroupResult); +#endif +#ifdef SListWndLine__dSListWndLine_x +FUNCTION_AT_ADDRESS( SListWndLine::~SListWndLine(void),SListWndLine__dSListWndLine); +#endif +#ifdef CUITextureInfo__dCUITextureInfo_x +FUNCTION_AT_ADDRESS( CUITextureInfo::~CUITextureInfo(void),CUITextureInfo__dCUITextureInfo); +#endif +#ifdef CUITexturePiece__dCUITexturePiece_x +FUNCTION_AT_ADDRESS( CUITexturePiece::~CUITexturePiece(void),CUITexturePiece__dCUITexturePiece); +#endif +#ifdef SListWndCell__dSListWndCell_x +FUNCTION_AT_ADDRESS( SListWndCell::~SListWndCell(void),SListWndCell__dSListWndCell); +#endif +#ifdef STextureAnimationFrame__dSTextureAnimationFrame_x +FUNCTION_AT_ADDRESS( STextureAnimationFrame::~STextureAnimationFrame(void),STextureAnimationFrame__dSTextureAnimationFrame); +#endif +#ifdef CGroupSearchWnd__ResetPlayerList_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::ResetPlayerList(void),CGroupSearchWnd__ResetPlayerList); +#endif +#ifdef CGroupSearchWnd__AddPlayerResult_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::AddPlayerResult(struct LfgPlayerResult const *),CGroupSearchWnd__AddPlayerResult); +#endif +#ifdef CGroupSearchWnd__InitLfg_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::InitLfg(void),CGroupSearchWnd__InitLfg); +#endif +#ifdef CGroupSearchWnd__InitLfp_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::InitLfp(void),CGroupSearchWnd__InitLfp); +#endif +#ifdef CGroupSearchWnd__UpdatePlayerLabel_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::UpdatePlayerLabel(void),CGroupSearchWnd__UpdatePlayerLabel); +#endif +#ifdef CGroupSearchWnd__UpdateGroupLabel_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::UpdateGroupLabel(void),CGroupSearchWnd__UpdateGroupLabel); +#endif +#ifdef CGroupSearchWnd__RedirectOnProcessFrameTo_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::RedirectOnProcessFrameTo(class CPageWnd *),CGroupSearchWnd__RedirectOnProcessFrameTo); +#endif +#ifdef CGroupSearchWnd__RedirectWndNotificationTo_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::RedirectWndNotificationTo(class CPageWnd *,class CXWnd *,unsigned __int32,void *),CGroupSearchWnd__RedirectWndNotificationTo); +#endif +#ifdef CGroupSearchWnd__PlayerInfoPageWndNotification_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::PlayerInfoPageWndNotification(class CXWnd *,unsigned __int32,void *),CGroupSearchWnd__PlayerInfoPageWndNotification); +#endif +#ifdef CGroupSearchWnd__GroupInfoPageWndNotification_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::GroupInfoPageWndNotification(class CXWnd *,unsigned __int32,void *),CGroupSearchWnd__GroupInfoPageWndNotification); +#endif +#ifdef CGroupSearchWnd__PlayerListPageWndNotification_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::PlayerListPageWndNotification(class CXWnd *,unsigned __int32,void *),CGroupSearchWnd__PlayerListPageWndNotification); +#endif +#ifdef CGroupSearchWnd__GroupListPageWndNotification_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::GroupListPageWndNotification(class CXWnd *,unsigned __int32,void *),CGroupSearchWnd__GroupListPageWndNotification); +#endif +#ifdef CGroupSearchWnd__PlayerInfoPageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::PlayerInfoPageOnProcessFrame(void),CGroupSearchWnd__PlayerInfoPageOnProcessFrame); +#endif +#ifdef CGroupSearchWnd__GroupInfoPageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::GroupInfoPageOnProcessFrame(void),CGroupSearchWnd__GroupInfoPageOnProcessFrame); +#endif +#ifdef CGroupSearchWnd__HandlePlayerInfoPost_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandlePlayerInfoPost(void),CGroupSearchWnd__HandlePlayerInfoPost); +#endif +#ifdef CGroupSearchWnd__HandlePlayerInfoUpdate_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandlePlayerInfoUpdate(void),CGroupSearchWnd__HandlePlayerInfoUpdate); +#endif +#ifdef CGroupSearchWnd__HandlePlayerInfoRemove_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandlePlayerInfoRemove(void),CGroupSearchWnd__HandlePlayerInfoRemove); +#endif +#ifdef CGroupSearchWnd__HandleGroupInfoPost_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandleGroupInfoPost(void),CGroupSearchWnd__HandleGroupInfoPost); +#endif +#ifdef CGroupSearchWnd__HandleGroupInfoUpdate_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandleGroupInfoUpdate(void),CGroupSearchWnd__HandleGroupInfoUpdate); +#endif +#ifdef CGroupSearchWnd__HandleGroupInfoRemove_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandleGroupInfoRemove(void),CGroupSearchWnd__HandleGroupInfoRemove); +#endif +#ifdef CGroupSearchWnd__HandleSelectAllClasses_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandleSelectAllClasses(void),CGroupSearchWnd__HandleSelectAllClasses); +#endif +#ifdef CGroupSearchWnd__HandleDeselectAllClasses_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandleDeselectAllClasses(void),CGroupSearchWnd__HandleDeselectAllClasses); +#endif +#ifdef CGroupSearchWnd__HandleOpenFiltersWindow_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandleOpenFiltersWindow(void),CGroupSearchWnd__HandleOpenFiltersWindow); +#endif +#ifdef CGroupSearchWnd__HandleQueryingForGroups_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandleQueryingForGroups(void),CGroupSearchWnd__HandleQueryingForGroups); +#endif +#ifdef CGroupSearchWnd__HandleQueryingForPlayers_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandleQueryingForPlayers(void),CGroupSearchWnd__HandleQueryingForPlayers); +#endif +#ifdef CGroupSearchWnd__SendServerLfgOn_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::SendServerLfgOn(void),CGroupSearchWnd__SendServerLfgOn); +#endif +#ifdef CGroupSearchWnd__SendServerLfgOff_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::SendServerLfgOff(void),CGroupSearchWnd__SendServerLfgOff); +#endif +#ifdef CGroupSearchWnd__SendServerLfpOn_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::SendServerLfpOn(void),CGroupSearchWnd__SendServerLfpOn); +#endif +#ifdef CGroupSearchWnd__SendServerLfpOff_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::SendServerLfpOff(void),CGroupSearchWnd__SendServerLfpOff); +#endif +#ifdef CGroupSearchWnd__ShowGroupDetails_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::ShowGroupDetails(struct LfgGroupResult const *),CGroupSearchWnd__ShowGroupDetails); +#endif +#ifdef CGroupSearchWnd__PlayerShouldBeFiltered_x +FUNCTION_AT_ADDRESS(bool CGroupSearchWnd::PlayerShouldBeFiltered(struct LfgPlayerData const *)const ,CGroupSearchWnd__PlayerShouldBeFiltered); +#endif +#ifdef CGroupSearchWnd__FilterOutBadWords_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::FilterOutBadWords(char const *,char *)const ,CGroupSearchWnd__FilterOutBadWords); +#endif +#ifdef CGroupSearchWnd__LockQueryButtonAtTime_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::LockQueryButtonAtTime(long),CGroupSearchWnd__LockQueryButtonAtTime); +#endif +#ifdef CGroupSearchWnd__UpdateRemainingQueryLockedTime_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::UpdateRemainingQueryLockedTime(long),CGroupSearchWnd__UpdateRemainingQueryLockedTime); +#endif +#ifdef CGroupSearchWnd__HandleGroupResultColSelected_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandleGroupResultColSelected(int),CGroupSearchWnd__HandleGroupResultColSelected); +#endif +#ifdef CGroupSearchWnd__HandlePlayerResultColSelected_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandlePlayerResultColSelected(int),CGroupSearchWnd__HandlePlayerResultColSelected); +#endif +#ifdef CGroupSearchWnd__HandleGroupResultRowSelected_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandleGroupResultRowSelected(int),CGroupSearchWnd__HandleGroupResultRowSelected); +#endif +#ifdef CGroupSearchWnd__HandleDoubleClickedOnPlayer_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandleDoubleClickedOnPlayer(char const *),CGroupSearchWnd__HandleDoubleClickedOnPlayer); +#endif +#ifdef CGroupSearchWnd__HandleNumericSort_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandleNumericSort(class SListWndSortInfo *),CGroupSearchWnd__HandleNumericSort); +#endif +#ifdef CGroupSearchWnd__HandleGroupMakeupChanged_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::HandleGroupMakeupChanged(void),CGroupSearchWnd__HandleGroupMakeupChanged); +#endif +#ifdef CGroupSearchWnd__CheckIfCurrentLfgInfoIsValid_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::CheckIfCurrentLfgInfoIsValid(void)const ,CGroupSearchWnd__CheckIfCurrentLfgInfoIsValid); +#endif +#ifdef CGroupSearchWnd__CheckIfCurrentLfpInfoIsValid_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::CheckIfCurrentLfpInfoIsValid(void)const ,CGroupSearchWnd__CheckIfCurrentLfpInfoIsValid); +#endif +#ifdef CGroupSearchWnd__UpdateLfgPostingStatus_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::UpdateLfgPostingStatus(void),CGroupSearchWnd__UpdateLfgPostingStatus); +#endif +#ifdef CGroupSearchWnd__UpdateLfpPostingStatus_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::UpdateLfpPostingStatus(void),CGroupSearchWnd__UpdateLfpPostingStatus); +#endif +#ifdef CGroupSearchWnd__GetDesiredPlayerMinLevel_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::GetDesiredPlayerMinLevel(void)const ,CGroupSearchWnd__GetDesiredPlayerMinLevel); +#endif +#ifdef CGroupSearchWnd__GetDefaultLfgLevelRange_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::GetDefaultLfgLevelRange(class EQ_PC const *,int *,int *)const ,CGroupSearchWnd__GetDefaultLfgLevelRange); +#endif +#ifdef CGroupSearchWnd__GetDefaultLfpLevelRange_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::GetDefaultLfpLevelRange(class EQ_PC const *,int *,int *)const ,CGroupSearchWnd__GetDefaultLfpLevelRange); +#endif +#ifdef CGroupSearchWnd__GetDesiredPlayerMaxLevel_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::GetDesiredPlayerMaxLevel(void)const ,CGroupSearchWnd__GetDesiredPlayerMaxLevel); +#endif +#ifdef CGroupSearchWnd__GetDesiredGroupMinLevel_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::GetDesiredGroupMinLevel(void)const ,CGroupSearchWnd__GetDesiredGroupMinLevel); +#endif +#ifdef CGroupSearchWnd__GetDesiredGroupMaxLevel_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::GetDesiredGroupMaxLevel(void)const ,CGroupSearchWnd__GetDesiredGroupMaxLevel); +#endif +#ifdef CGroupSearchWnd__IsLevelRangeValid_x +FUNCTION_AT_ADDRESS(bool CGroupSearchWnd::IsLevelRangeValid(int,int)const ,CGroupSearchWnd__IsLevelRangeValid); +#endif +#ifdef CGroupSearchWnd__GetDesiredClassesFlag_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::GetDesiredClassesFlag(void)const ,CGroupSearchWnd__GetDesiredClassesFlag); +#endif +#ifdef CGroupSearchWnd__GetEqClassType_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::GetEqClassType(int)const ,CGroupSearchWnd__GetEqClassType); +#endif +#ifdef CGroupSearchWnd__PopUpErrorMessage_x +FUNCTION_AT_ADDRESS(void CGroupSearchWnd::PopUpErrorMessage(int)const ,CGroupSearchWnd__PopUpErrorMessage); +#endif +#ifdef Util__SetBit_x +FUNCTION_AT_ADDRESS(int __cdecl Util::SetBit(int,void *,int),Util__SetBit); +#endif +#ifdef _partyGroup__getNumMembers_x +FUNCTION_AT_ADDRESS(int _partyGroup::getNumMembers(void)const ,_partyGroup__getNumMembers); +#endif +#ifdef SListWndCell__SListWndCell_x +FUNCTION_AT_ADDRESS( SListWndCell::SListWndCell(void),SListWndCell__SListWndCell); +#endif +#ifdef CGroupWnd__CGroupWnd_x +FUNCTION_AT_ADDRESS( CGroupWnd::CGroupWnd(class CXWnd *),CGroupWnd__CGroupWnd); +#endif +#ifdef CGroupWnd__Init_x +FUNCTION_AT_ADDRESS(void CGroupWnd::Init(void),CGroupWnd__Init); +#endif +#ifdef CGroupWnd__Activate_x +FUNCTION_AT_ADDRESS(void CGroupWnd::Activate(void),CGroupWnd__Activate); +#endif +#ifdef CGroupWnd__SetInvited_x +FUNCTION_AT_ADDRESS(void CGroupWnd::SetInvited(bool),CGroupWnd__SetInvited); +#endif +#ifdef CGroupWnd__UpdateButtons_x +FUNCTION_AT_ADDRESS(void CGroupWnd::UpdateButtons(void),CGroupWnd__UpdateButtons); +#endif +#ifdef CGroupWnd__KeyMapUpdated_x +FUNCTION_AT_ADDRESS(void CGroupWnd::KeyMapUpdated(void),CGroupWnd__KeyMapUpdated); +#endif +#ifdef CGroupWnd__CreateLocalMenu_x +FUNCTION_AT_ADDRESS(void CGroupWnd::CreateLocalMenu(void),CGroupWnd__CreateLocalMenu); +#endif +#ifdef CGroupWnd__UpdateContextMenu_x +FUNCTION_AT_ADDRESS(void CGroupWnd::UpdateContextMenu(void),CGroupWnd__UpdateContextMenu); +#endif +#ifdef CGuildMgmtWnd__CGuildMgmtWnd_x +FUNCTION_AT_ADDRESS( CGuildMgmtWnd::CGuildMgmtWnd(class CXWnd *),CGuildMgmtWnd__CGuildMgmtWnd); +#endif +#ifdef CGuildMgmtWnd__Init_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::Init(void),CGuildMgmtWnd__Init); +#endif +#ifdef CGuildMgmtWnd__UpdateButtons_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::UpdateButtons(void),CGuildMgmtWnd__UpdateButtons); +#endif +#ifdef CGuildMgmtWnd__Clean_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::Clean(void),CGuildMgmtWnd__Clean); +#endif +#ifdef CGuildMgmtWnd__SetMOTD_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::SetMOTD(char *,char *),CGuildMgmtWnd__SetMOTD); +#endif +#ifdef CGuildMgmtWnd__SetPlayerCount_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::SetPlayerCount(int),CGuildMgmtWnd__SetPlayerCount); +#endif +#ifdef CGuildMgmtWnd__CreatePersonalNotesFilename_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::CreatePersonalNotesFilename(void),CGuildMgmtWnd__CreatePersonalNotesFilename); +#endif +#ifdef CGuildMgmtWnd__LoadPersonalNotes_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::LoadPersonalNotes(void),CGuildMgmtWnd__LoadPersonalNotes); +#endif +#ifdef CGuildMgmtWnd__SavePersonalNotes_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::SavePersonalNotes(void),CGuildMgmtWnd__SavePersonalNotes); +#endif +#ifdef CGuildMgmtWnd__GetPersonalNote_x +FUNCTION_AT_ADDRESS(char * CGuildMgmtWnd::GetPersonalNote(char *),CGuildMgmtWnd__GetPersonalNote); +#endif +#ifdef CGuildMgmtWnd__SetPersonalNote_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::SetPersonalNote(char *,char *),CGuildMgmtWnd__SetPersonalNote); +#endif +#ifdef CGuildMgmtWnd__AddMember_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::AddMember(class GuildMember *),CGuildMgmtWnd__AddMember); +#endif +#ifdef CGuildMgmtWnd__RemoveMember_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::RemoveMember(class GuildMember *),CGuildMgmtWnd__RemoveMember); +#endif +#ifdef CGuildMgmtWnd__RenameMember_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::RenameMember(char *,char *),CGuildMgmtWnd__RenameMember); +#endif +#ifdef CGuildMgmtWnd__UpdateListMember_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::UpdateListMember(class GuildMember *,int),CGuildMgmtWnd__UpdateListMember); +#endif +#ifdef CGuildMgmtWnd__FindListMember_x +FUNCTION_AT_ADDRESS(int CGuildMgmtWnd::FindListMember(class GuildMember *),CGuildMgmtWnd__FindListMember); +#endif +#ifdef CGuildMgmtWnd__Activate_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::Activate(void),CGuildMgmtWnd__Activate); +#endif +#ifdef CGuildMgmtWnd__CleanAndRefillListWnd_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::CleanAndRefillListWnd(bool),CGuildMgmtWnd__CleanAndRefillListWnd); +#endif +#ifdef CGuildMgmtWnd__SortList_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::SortList(int,bool),CGuildMgmtWnd__SortList); +#endif +#ifdef CGuildMgmtWnd__DumpToFile_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::DumpToFile(char *),CGuildMgmtWnd__DumpToFile); +#endif +#ifdef CGuildMgmtWnd__LoadINI_x +FUNCTION_AT_ADDRESS(void CGuildMgmtWnd::LoadINI(void),CGuildMgmtWnd__LoadINI); +#endif +#ifdef CGuild__GetGuildMotd_x +FUNCTION_AT_ADDRESS(char * CGuild::GetGuildMotd(void),CGuild__GetGuildMotd); +#endif +#ifdef CGuild__GetGuildMotdAuthor_x +FUNCTION_AT_ADDRESS(char * CGuild::GetGuildMotdAuthor(void),CGuild__GetGuildMotdAuthor); +#endif +#ifdef EQPlayer__GetGuild_x +FUNCTION_AT_ADDRESS(int EQPlayer::GetGuild(void)const ,EQPlayer__GetGuild); +#endif +#ifdef CHelpWnd__CHelpWnd_x +FUNCTION_AT_ADDRESS( CHelpWnd::CHelpWnd(class CXWnd *),CHelpWnd__CHelpWnd); +#endif +#ifdef CHelpWnd__SetFile_x +FUNCTION_AT_ADDRESS(void CHelpWnd::SetFile(char *),CHelpWnd__SetFile); +#endif +#ifdef CHotButtonWnd__CHotButtonWnd_x +FUNCTION_AT_ADDRESS( CHotButtonWnd::CHotButtonWnd(class CXWnd *),CHotButtonWnd__CHotButtonWnd); +#endif +#ifdef CHotButtonWnd__Init_x +FUNCTION_AT_ADDRESS(void CHotButtonWnd::Init(void),CHotButtonWnd__Init); +#endif +#ifdef CHotButtonWnd__Activate_x +FUNCTION_AT_ADDRESS(void CHotButtonWnd::Activate(void),CHotButtonWnd__Activate); +#endif +#ifdef CHotButtonWnd__UpdatePage_x +FUNCTION_AT_ADDRESS(void CHotButtonWnd::UpdatePage(void),CHotButtonWnd__UpdatePage); +#endif +#ifdef CHotButtonWnd__DoHotButton_x +FUNCTION_AT_ADDRESS(void CHotButtonWnd::DoHotButton(int,int),CHotButtonWnd__DoHotButton); +#endif +#ifdef CHotButtonWnd__DoHotButtonRightClick_x +FUNCTION_AT_ADDRESS(void CHotButtonWnd::DoHotButtonRightClick(int),CHotButtonWnd__DoHotButtonRightClick); +#endif +#ifdef CInspectWnd__CInspectWnd_x +FUNCTION_AT_ADDRESS( CInspectWnd::CInspectWnd(class CXWnd *),CInspectWnd__CInspectWnd); +#endif +#ifdef CInspectWnd__Init_x +FUNCTION_AT_ADDRESS(void CInspectWnd::Init(void),CInspectWnd__Init); +#endif +#ifdef CInspectWnd__Activate_x +FUNCTION_AT_ADDRESS(void CInspectWnd::Activate(struct _inspect *),CInspectWnd__Activate); +#endif +#ifdef CInspectWnd__AcceptInspectText_x +FUNCTION_AT_ADDRESS(void CInspectWnd::AcceptInspectText(void),CInspectWnd__AcceptInspectText); +#endif +#ifdef CInspectWnd__PlayerBeingDeleted_x +FUNCTION_AT_ADDRESS(void CInspectWnd::PlayerBeingDeleted(class EQPlayer *),CInspectWnd__PlayerBeingDeleted); +#endif +#ifdef CInventoryWnd__CInventoryWnd_x +FUNCTION_AT_ADDRESS( CInventoryWnd::CInventoryWnd(class CXWnd *),CInventoryWnd__CInventoryWnd); +#endif +#ifdef CInventoryWnd__Init_x +FUNCTION_AT_ADDRESS(void CInventoryWnd::Init(void),CInventoryWnd__Init); +#endif +#ifdef CInventoryWnd__Activate_x +FUNCTION_AT_ADDRESS(void CInventoryWnd::Activate(void),CInventoryWnd__Activate); +#endif +#ifdef CInventoryWnd__DestroyHeld_x +FUNCTION_AT_ADDRESS(void CInventoryWnd::DestroyHeld(void),CInventoryWnd__DestroyHeld); +#endif +#ifdef CInventoryWnd__ClickedMoneyButton_x +FUNCTION_AT_ADDRESS(void CInventoryWnd::ClickedMoneyButton(int,int),CInventoryWnd__ClickedMoneyButton); +#endif +#ifdef CInventoryWnd__GetInventoryQtyFromCoinType_x +FUNCTION_AT_ADDRESS(long CInventoryWnd::GetInventoryQtyFromCoinType(int),CInventoryWnd__GetInventoryQtyFromCoinType); +#endif +#ifdef CInventoryWnd__UpdateMoneyDisplay_x +FUNCTION_AT_ADDRESS(void CInventoryWnd::UpdateMoneyDisplay(void),CInventoryWnd__UpdateMoneyDisplay); +#endif +#ifdef CInvSlot__CInvSlot_x +FUNCTION_AT_ADDRESS( CInvSlot::CInvSlot(void),CInvSlot__CInvSlot); +#endif + +#ifdef CInvSlot__GetItemBase_x +FUNCTION_AT_ADDRESS( void CInvSlot::GetItemBase(struct _CONTENTS **), CInvSlot__GetItemBase ); +#endif + +#ifdef CInvSlot__SetInvSlotWnd_x +FUNCTION_AT_ADDRESS(void CInvSlot::SetInvSlotWnd(class CInvSlotWnd *),CInvSlot__SetInvSlotWnd); +#endif +#ifdef CInvSlot__SetItem_x +FUNCTION_AT_ADDRESS(void CInvSlot::SetItem(class EQ_Item *),CInvSlot__SetItem); +#endif +#ifdef CInvSlot__SliderComplete_x +FUNCTION_AT_ADDRESS(void CInvSlot::SliderComplete(int),CInvSlot__SliderComplete); +#endif +#ifdef CInvSlot__HandleLButtonUp_x +FUNCTION_AT_ADDRESS(void CInvSlot::HandleLButtonUp(class CXPoint,bool),CInvSlot__HandleLButtonUp); +#endif +#ifdef CInvSlot__HandleLButtonHeld_x +FUNCTION_AT_ADDRESS(void CInvSlot::HandleLButtonHeld(class CXPoint),CInvSlot__HandleLButtonHeld); +#endif +#ifdef CInvSlot__DoDrinkEatPoison_x +FUNCTION_AT_ADDRESS(void CInvSlot::DoDrinkEatPoison(class EQ_Item *,int),CInvSlot__DoDrinkEatPoison); +#endif +#ifdef CInvSlot__HandleRButtonUp_x +FUNCTION_AT_ADDRESS(void CInvSlot::HandleRButtonUp(class CXPoint *),CInvSlot__HandleRButtonUp); +#endif +#ifdef CInvSlot__HandleRButtonHeld_x +FUNCTION_AT_ADDRESS(void CInvSlot::HandleRButtonHeld(class CXPoint),CInvSlot__HandleRButtonHeld); +#endif +#ifdef CInvSlot__HandleRButtonUpAfterHeld_x +FUNCTION_AT_ADDRESS(void CInvSlot::HandleRButtonUpAfterHeld(class CXPoint),CInvSlot__HandleRButtonUpAfterHeld); +#endif +#ifdef CInvSlot__IllegalBigBank_x +FUNCTION_AT_ADDRESS(bool CInvSlot::IllegalBigBank(int),CInvSlot__IllegalBigBank); +#endif +#ifdef CInvSlotMgr__CInvSlotMgr_x +FUNCTION_AT_ADDRESS( CInvSlotMgr::CInvSlotMgr(void),CInvSlotMgr__CInvSlotMgr); +#endif +#ifdef CInvSlotMgr__MoveItem_x +FUNCTION_AT_ADDRESS(bool CInvSlotMgr::MoveItem(CMoveItemData*,CMoveItemData*,int valueOne,int valueOne2,int valueZero,int valueZero2),CInvSlotMgr__MoveItem); +#endif +#ifdef CInvSlotMgr__CreateInvSlot_x +FUNCTION_AT_ADDRESS(class CInvSlot * CInvSlotMgr::CreateInvSlot(class CInvSlotWnd *),CInvSlotMgr__CreateInvSlot); +#endif +#ifdef CInvSlotMgr__FindInvSlot_x +FUNCTION_AT_ADDRESS(class CInvSlot * CInvSlotMgr::FindInvSlot(int,int),CInvSlotMgr__FindInvSlot); +#endif +#ifdef CInvSlotMgr__SelectSlot_x +FUNCTION_AT_ADDRESS(void CInvSlotMgr::SelectSlot(class CInvSlot *),CInvSlotMgr__SelectSlot); +#endif +#ifdef CInvSlotMgr__UpdateSlots_x +FUNCTION_AT_ADDRESS(void CInvSlotMgr::UpdateSlots(void),CInvSlotMgr__UpdateSlots); +#endif +#ifdef CItemDisplayWnd__CItemDisplayWnd_x +FUNCTION_AT_ADDRESS( CItemDisplayWnd::CItemDisplayWnd(class CXWnd *),CItemDisplayWnd__CItemDisplayWnd); +#endif +#ifdef CItemDisplayWnd__UpdateStrings_x +FUNCTION_AT_ADDRESS(void CItemDisplayWnd::UpdateStrings(void),CItemDisplayWnd__UpdateStrings); +#endif +#ifdef CItemDisplayWnd__SetItem_x +FUNCTION_AT_ADDRESS(void CItemDisplayWnd::SetItem(class EQ_Item *,bool),CItemDisplayWnd__SetItem); +#endif +#ifdef CItemDisplayWnd__SetItemText_x +FUNCTION_AT_ADDRESS(void CItemDisplayWnd::SetItemText(char *),CItemDisplayWnd__SetItemText); +#endif +#ifdef CItemDisplayWnd__GetSizeString_x +FUNCTION_AT_ADDRESS(void CItemDisplayWnd::GetSizeString(int,char *),CItemDisplayWnd__GetSizeString); +#endif +#ifdef CItemDisplayWnd__CreateRaceString_x +FUNCTION_AT_ADDRESS(class CXStr CItemDisplayWnd::CreateRaceString(class EQ_Equipment *),CItemDisplayWnd__CreateRaceString); +#endif +#ifdef CItemDisplayWnd__CreateClassString_x +FUNCTION_AT_ADDRESS(class CXStr CItemDisplayWnd::CreateClassString(class EQ_Equipment *),CItemDisplayWnd__CreateClassString); +#endif +#ifdef CItemDisplayWnd__CreateMealSizeString_x +FUNCTION_AT_ADDRESS(class CXStr CItemDisplayWnd::CreateMealSizeString(class EQ_Equipment *),CItemDisplayWnd__CreateMealSizeString); +#endif +#ifdef CItemDisplayWnd__CreateModString_x +FUNCTION_AT_ADDRESS(class CXStr CItemDisplayWnd::CreateModString(class EQ_Equipment *,int,int,int *),CItemDisplayWnd__CreateModString); +#endif +#ifdef CItemDisplayWnd__CreateEquipmentStatusString_x +FUNCTION_AT_ADDRESS(class CXStr CItemDisplayWnd::CreateEquipmentStatusString(class EQ_Item *),CItemDisplayWnd__CreateEquipmentStatusString); +#endif +#ifdef CItemDisplayWnd__SetSpell_x +FUNCTION_AT_ADDRESS(void CItemDisplayWnd::SetSpell(int SpellID,bool HasSpellDescr,int),CItemDisplayWnd__SetSpell); +#endif +#ifdef CJournalCatWnd__CJournalCatWnd_x +FUNCTION_AT_ADDRESS( CJournalCatWnd::CJournalCatWnd(class CXWnd *),CJournalCatWnd__CJournalCatWnd); +#endif +#ifdef CJournalCatWnd__Init_x +FUNCTION_AT_ADDRESS(void CJournalCatWnd::Init(void),CJournalCatWnd__Init); +#endif +#ifdef CJournalCatWnd__UpdateAll_x +FUNCTION_AT_ADDRESS(void CJournalCatWnd::UpdateAll(bool),CJournalCatWnd__UpdateAll); +#endif +#ifdef CJournalCatWnd__UpdateButtons_x +FUNCTION_AT_ADDRESS(void CJournalCatWnd::UpdateButtons(void),CJournalCatWnd__UpdateButtons); +#endif +#ifdef CJournalCatWnd__SelectCategory_x +FUNCTION_AT_ADDRESS(void CJournalCatWnd::SelectCategory(int),CJournalCatWnd__SelectCategory); +#endif +#ifdef CJournalCatWnd__Clean_x +FUNCTION_AT_ADDRESS(void CJournalCatWnd::Clean(void),CJournalCatWnd__Clean); +#endif +#ifdef CJournalCatWnd__BuildList_x +FUNCTION_AT_ADDRESS(void CJournalCatWnd::BuildList(void),CJournalCatWnd__BuildList); +#endif +#ifdef CJournalCatWnd__UpdateListWnd_x +FUNCTION_AT_ADDRESS(void CJournalCatWnd::UpdateListWnd(bool),CJournalCatWnd__UpdateListWnd); +#endif +#ifdef CJournalCatWnd__Activate_x +FUNCTION_AT_ADDRESS(void CJournalCatWnd::Activate(void),CJournalCatWnd__Activate); +#endif +#ifdef CJournalCatWnd__SortList_x +FUNCTION_AT_ADDRESS(void CJournalCatWnd::SortList(int,bool),CJournalCatWnd__SortList); +#endif +#ifdef CJournalCatWnd__LoadINI_x +FUNCTION_AT_ADDRESS(void CJournalCatWnd::LoadINI(void),CJournalCatWnd__LoadINI); +#endif +#ifdef CJournalCatWnd__StoreINI_x +FUNCTION_AT_ADDRESS(void CJournalCatWnd::StoreINI(void),CJournalCatWnd__StoreINI); +#endif +#ifdef CJournalNPCWnd__CJournalNPCWnd_x +FUNCTION_AT_ADDRESS( CJournalNPCWnd::CJournalNPCWnd(class CXWnd *),CJournalNPCWnd__CJournalNPCWnd); +#endif +#ifdef CJournalNPCWnd__Init_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::Init(void),CJournalNPCWnd__Init); +#endif +#ifdef CJournalNPCWnd__Activate_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::Activate(void),CJournalNPCWnd__Activate); +#endif +#ifdef CJournalNPCWnd__UpdateAll_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::UpdateAll(bool),CJournalNPCWnd__UpdateAll); +#endif +#ifdef CJournalNPCWnd__UpdateListWnd_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::UpdateListWnd(bool),CJournalNPCWnd__UpdateListWnd); +#endif +#ifdef CJournalNPCWnd__SelectNPCIndex_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::SelectNPCIndex(int),CJournalNPCWnd__SelectNPCIndex); +#endif +#ifdef CJournalNPCWnd__UpdateCategories_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::UpdateCategories(void),CJournalNPCWnd__UpdateCategories); +#endif +#ifdef CJournalNPCWnd__UpdateButtons_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::UpdateButtons(void),CJournalNPCWnd__UpdateButtons); +#endif +#ifdef CJournalNPCWnd__EnterIntoJournal_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::EnterIntoJournal(char *,float,float,float,char *),CJournalNPCWnd__EnterIntoJournal); +#endif +#ifdef CJournalNPCWnd__DoBackups_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::DoBackups(class CXStr),CJournalNPCWnd__DoBackups); +#endif +#ifdef CJournalNPCWnd__LoadJournal_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::LoadJournal(int),CJournalNPCWnd__LoadJournal); +#endif +#ifdef CJournalNPCWnd__SaveJournal_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::SaveJournal(void),CJournalNPCWnd__SaveJournal); +#endif +#ifdef CJournalNPCWnd__BuildList_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::BuildList(void),CJournalNPCWnd__BuildList); +#endif +#ifdef CJournalNPCWnd__SortList_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::SortList(int,bool),CJournalNPCWnd__SortList); +#endif +#ifdef CJournalNPCWnd__GetLogState_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::GetLogState(void),CJournalNPCWnd__GetLogState); +#endif +#ifdef CJournalNPCWnd__StoreLogState_x +FUNCTION_AT_ADDRESS(void CJournalNPCWnd::StoreLogState(void),CJournalNPCWnd__StoreLogState); +#endif +#ifdef CJournalTextWnd__CJournalTextWnd_x +FUNCTION_AT_ADDRESS( CJournalTextWnd::CJournalTextWnd(class CXWnd *),CJournalTextWnd__CJournalTextWnd); +#endif +#ifdef CJournalTextWnd__UpdateAll_x +FUNCTION_AT_ADDRESS(void CJournalTextWnd::UpdateAll(bool),CJournalTextWnd__UpdateAll); +#endif +#ifdef CJournalTextWnd__UpdateCategories_x +FUNCTION_AT_ADDRESS(void CJournalTextWnd::UpdateCategories(void),CJournalTextWnd__UpdateCategories); +#endif +#ifdef CJournalTextWnd__Activate_x +FUNCTION_AT_ADDRESS(void CJournalTextWnd::Activate(void),CJournalTextWnd__Activate); +#endif +#ifdef CJournalTextWnd__SetSearch_x +FUNCTION_AT_ADDRESS(void CJournalTextWnd::SetSearch(class CXStr),CJournalTextWnd__SetSearch); +#endif +#ifdef CJournalTextWnd__Clear_x +FUNCTION_AT_ADDRESS(void CJournalTextWnd::Clear(void),CJournalTextWnd__Clear); +#endif +#ifdef CJournalTextWnd__UpdateListWnd_x +FUNCTION_AT_ADDRESS(void CJournalTextWnd::UpdateListWnd(bool),CJournalTextWnd__UpdateListWnd); +#endif +#ifdef CJournalTextWnd__UpdateButtons_x +FUNCTION_AT_ADDRESS(void CJournalTextWnd::UpdateButtons(void),CJournalTextWnd__UpdateButtons); +#endif +#ifdef CJournalTextWnd__DisplayNPC_x +FUNCTION_AT_ADDRESS(void CJournalTextWnd::DisplayNPC(class JournalNPC *),CJournalTextWnd__DisplayNPC); +#endif +#ifdef CJournalTextWnd__BuildList_x +FUNCTION_AT_ADDRESS(void CJournalTextWnd::BuildList(void),CJournalTextWnd__BuildList); +#endif +#ifdef CJournalTextWnd__SelectEntryIndex_x +FUNCTION_AT_ADDRESS(void CJournalTextWnd::SelectEntryIndex(int),CJournalTextWnd__SelectEntryIndex); +#endif +#ifdef CJournalTextWnd__SortList_x +FUNCTION_AT_ADDRESS(void CJournalTextWnd::SortList(int,bool),CJournalTextWnd__SortList); +#endif +#ifdef CLoadskinWnd__CLoadskinWnd_x +FUNCTION_AT_ADDRESS( CLoadskinWnd::CLoadskinWnd(class CXWnd *),CLoadskinWnd__CLoadskinWnd); +#endif +#ifdef CLoadskinWnd__UpdateSkinList_x +FUNCTION_AT_ADDRESS(void CLoadskinWnd::UpdateSkinList(void),CLoadskinWnd__UpdateSkinList); +#endif +#ifdef CLoadskinWnd__Activate_x +FUNCTION_AT_ADDRESS(void CLoadskinWnd::Activate(void),CLoadskinWnd__Activate); +#endif +#ifdef CLootWnd__CLootWnd_x +FUNCTION_AT_ADDRESS( CLootWnd::CLootWnd(class CXWnd *),CLootWnd__CLootWnd); +#endif +#ifdef CLootWnd__Init_x +FUNCTION_AT_ADDRESS(void CLootWnd::Init(void),CLootWnd__Init); +#endif +#ifdef CLootWnd__Activate_x +FUNCTION_AT_ADDRESS(void CLootWnd::Activate(unsigned char,long,long,long,long),CLootWnd__Activate); +#endif +#ifdef CLootWnd__Deactivate1_x +FUNCTION_AT_ADDRESS(void CLootWnd::Deactivate(bool),CLootWnd__Deactivate1); +#endif +#ifdef CLootWnd__FinalizeLoot_x +FUNCTION_AT_ADDRESS(void CLootWnd::FinalizeLoot(void),CLootWnd__FinalizeLoot); +#endif +#ifdef CLootWnd__AddEquipmentToLootArray_x +FUNCTION_AT_ADDRESS(void CLootWnd::AddEquipmentToLootArray(class EQ_Item *),CLootWnd__AddEquipmentToLootArray); +#endif +#ifdef CLootWnd__AddNoteToLootArray_x +FUNCTION_AT_ADDRESS(void CLootWnd::AddNoteToLootArray(class EQ_Item *),CLootWnd__AddNoteToLootArray); +#endif +#ifdef CLootWnd__AddContainerToLootArray_x +FUNCTION_AT_ADDRESS(void CLootWnd::AddContainerToLootArray(class EQ_Item *),CLootWnd__AddContainerToLootArray); +#endif +#ifdef CLootWnd__RequestLootSlot_x +FUNCTION_AT_ADDRESS(void CLootWnd::RequestLootSlot(int,bool),CLootWnd__RequestLootSlot); +#endif +#ifdef CLootWnd__SlotLooted_x +FUNCTION_AT_ADDRESS(void CLootWnd::SlotLooted(int),CLootWnd__SlotLooted); +#endif +#ifdef CMapToolbarWnd__CMapToolbarWnd_x +FUNCTION_AT_ADDRESS( CMapToolbarWnd::CMapToolbarWnd(class CXWnd *),CMapToolbarWnd__CMapToolbarWnd); +#endif +#ifdef CMapToolbarWnd__Activate_x +FUNCTION_AT_ADDRESS(void CMapToolbarWnd::Activate(void),CMapToolbarWnd__Activate); +#endif +#ifdef CMapToolbarWnd__SetAutoMapButton_x +FUNCTION_AT_ADDRESS(void CMapToolbarWnd::SetAutoMapButton(bool),CMapToolbarWnd__SetAutoMapButton); +#endif +#ifdef CEditLabelWnd__GetLabelText_x +FUNCTION_AT_ADDRESS(class CXStr CEditLabelWnd::GetLabelText(void),CEditLabelWnd__GetLabelText); +#endif +#ifdef CMapViewWnd__IsMappingEnabled_x +FUNCTION_AT_ADDRESS(bool CMapViewWnd::IsMappingEnabled(void),CMapViewWnd__IsMappingEnabled); +#endif +#ifdef CMapViewWnd__CMapViewWnd_x +FUNCTION_AT_ADDRESS( CMapViewWnd::CMapViewWnd(class CXWnd *),CMapViewWnd__CMapViewWnd); +#endif +#ifdef CMapViewWnd__Init_x +FUNCTION_AT_ADDRESS(void CMapViewWnd::Init(void),CMapViewWnd__Init); +#endif +#ifdef CMapViewWnd__Activate_x +FUNCTION_AT_ADDRESS(void CMapViewWnd::Activate(void),CMapViewWnd__Activate); +#endif +#ifdef CMapViewWnd__ActivateAutoMapping_x +FUNCTION_AT_ADDRESS(void CMapViewWnd::ActivateAutoMapping(void),CMapViewWnd__ActivateAutoMapping); +#endif +#ifdef CMapViewWnd__DeactivateAutoMapping_x +FUNCTION_AT_ADDRESS(void CMapViewWnd::DeactivateAutoMapping(void),CMapViewWnd__DeactivateAutoMapping); +#endif +#ifdef CMapViewWnd__SetCurrentZone_x +//FUNCTION_AT_ADDRESS(void CMapViewWnd::SetCurrentZone(enum EQZoneIndex,struct T3D_XYZ *,struct T3D_XYZ *),CMapViewWnd__SetCurrentZone); +#endif +#ifdef MapViewMap__MapViewMap_x +FUNCTION_AT_ADDRESS( MapViewMap::MapViewMap(void),MapViewMap__MapViewMap); +#endif +#ifdef MapViewMap__dMapViewMap_x +FUNCTION_AT_ADDRESS( MapViewMap::~MapViewMap(void),MapViewMap__dMapViewMap); +#endif +#ifdef MapViewMap__Clear_x +FUNCTION_AT_ADDRESS(void MapViewMap::Clear(void),MapViewMap__Clear); +#endif +#ifdef MapViewMap__StartLine_x +FUNCTION_AT_ADDRESS(void MapViewMap::StartLine(float,float,float),MapViewMap__StartLine); +#endif +#ifdef MapViewMap__EndLine_x +FUNCTION_AT_ADDRESS(void MapViewMap::EndLine(float,float,float),MapViewMap__EndLine); +#endif +#ifdef MapViewMap__RemoveLine_x +FUNCTION_AT_ADDRESS(void MapViewMap::RemoveLine(void),MapViewMap__RemoveLine); +#endif +#ifdef MapViewMap__AddPoint_x +FUNCTION_AT_ADDRESS(void MapViewMap::AddPoint(float,float,float),MapViewMap__AddPoint); +#endif +#ifdef MapViewMap__AddLabel_x +FUNCTION_AT_ADDRESS(void MapViewMap::AddLabel(float,float,float,unsigned long,int,char *),MapViewMap__AddLabel); +#endif +#ifdef MapViewMap__RecalcLabelExtents_x +FUNCTION_AT_ADDRESS(void MapViewMap::RecalcLabelExtents(struct _mapviewlabel *),MapViewMap__RecalcLabelExtents); +#endif +#ifdef MapViewMap__RemoveLabel_x +FUNCTION_AT_ADDRESS(void MapViewMap::RemoveLabel(void),MapViewMap__RemoveLabel); +#endif +#ifdef MapViewMap__MoveLabel_x +FUNCTION_AT_ADDRESS(void MapViewMap::MoveLabel(struct _mapviewlabel *,float,float,float),MapViewMap__MoveLabel); +#endif +#ifdef MapViewMap__CalcLabelRenderOffsets_x +FUNCTION_AT_ADDRESS(void MapViewMap::CalcLabelRenderOffsets(class CXRect),MapViewMap__CalcLabelRenderOffsets); +#endif +#ifdef MapViewMap__IsLayerVisible_x +FUNCTION_AT_ADDRESS(bool MapViewMap::IsLayerVisible(int),MapViewMap__IsLayerVisible); +#endif +#ifdef MapViewMap__PointInMapViewArea_x +FUNCTION_AT_ADDRESS(bool MapViewMap::PointInMapViewArea(class CXPoint,class CXRect),MapViewMap__PointInMapViewArea); +#endif +#ifdef MapViewMap__PreCalcRenderValues_x +FUNCTION_AT_ADDRESS(void MapViewMap::PreCalcRenderValues(void),MapViewMap__PreCalcRenderValues); +#endif +#ifdef MapViewMap__TransformPoint_x +FUNCTION_AT_ADDRESS(void MapViewMap::TransformPoint(struct T3D_XYZ *),MapViewMap__TransformPoint); +#endif +#ifdef MapViewMap__Draw_x +FUNCTION_AT_ADDRESS(void MapViewMap::Draw(class CXRect),MapViewMap__Draw); +#endif +#ifdef MapViewMap__DrawClippedLine_x +FUNCTION_AT_ADDRESS(bool MapViewMap::DrawClippedLine(struct T3D_XYZ *,struct T3D_RGB,class CXRect),MapViewMap__DrawClippedLine); +#endif +#ifdef MapViewMap__Save_x +FUNCTION_AT_ADDRESS(void MapViewMap::Save(char *),MapViewMap__Save); +#endif +#ifdef MapViewMap__SaveEx_x +FUNCTION_AT_ADDRESS(void MapViewMap::SaveEx(char *,int),MapViewMap__SaveEx); +#endif +#ifdef MapViewMap__Load_x +FUNCTION_AT_ADDRESS(void MapViewMap::Load(char *),MapViewMap__Load); +#endif +#ifdef MapViewMap__LoadEx_x +FUNCTION_AT_ADDRESS(bool MapViewMap::LoadEx(char *,int),MapViewMap__LoadEx); +#endif +#ifdef MapViewMap__GetCurrentColor_x +FUNCTION_AT_ADDRESS(unsigned long MapViewMap::GetCurrentColor(void),MapViewMap__GetCurrentColor); +#endif +#ifdef MapViewMap__SetCurrentColor_x +FUNCTION_AT_ADDRESS(void MapViewMap::SetCurrentColor(unsigned long),MapViewMap__SetCurrentColor); +#endif +#ifdef MapViewMap__SetMarkedLine_x +FUNCTION_AT_ADDRESS(void MapViewMap::SetMarkedLine(struct _mapviewline *),MapViewMap__SetMarkedLine); +#endif +#ifdef MapViewMap__SetMarkedLineColor_x +FUNCTION_AT_ADDRESS(void MapViewMap::SetMarkedLineColor(unsigned long),MapViewMap__SetMarkedLineColor); +#endif +#ifdef MapViewMap__GetMarkedLineColor_x +FUNCTION_AT_ADDRESS(unsigned long MapViewMap::GetMarkedLineColor(void),MapViewMap__GetMarkedLineColor); +#endif +#ifdef MapViewMap__ClearActiveLayer_x +FUNCTION_AT_ADDRESS(void MapViewMap::ClearActiveLayer(void),MapViewMap__ClearActiveLayer); +#endif +#ifdef MapViewMap__RemoveLine1_x +FUNCTION_AT_ADDRESS(void MapViewMap::RemoveLine(struct _mapviewline *),MapViewMap__RemoveLine1); +#endif +#ifdef MapViewMap__RemoveLabel1_x +FUNCTION_AT_ADDRESS(void MapViewMap::RemoveLabel(struct _mapviewlabel *),MapViewMap__RemoveLabel1); +#endif +#ifdef CXRect__Normalize_x +FUNCTION_AT_ADDRESS(void CXRect::Normalize(void),CXRect__Normalize); +#endif +#ifdef CXRect__operator_and_x +FUNCTION_AT_ADDRESS(class CXRect CXRect::operator&(class CXRect)const ,CXRect__operator_and); +#endif +#ifdef MapViewMap__JoinLinesAtIntersect_x +FUNCTION_AT_ADDRESS(void MapViewMap::JoinLinesAtIntersect(bool),MapViewMap__JoinLinesAtIntersect); +#endif +#ifdef MapViewMap__SetZoneExtents_x +FUNCTION_AT_ADDRESS(void MapViewMap::SetZoneExtents(int,int,int,int),MapViewMap__SetZoneExtents); +#endif +#ifdef MapViewMap__SetZoom_x +FUNCTION_AT_ADDRESS(void MapViewMap::SetZoom(float),MapViewMap__SetZoom); +#endif +#ifdef MapViewMap__GetMinZ_x +FUNCTION_AT_ADDRESS(int MapViewMap::GetMinZ(void),MapViewMap__GetMinZ); +#endif +#ifdef MapViewMap__GetMaxZ_x +FUNCTION_AT_ADDRESS(int MapViewMap::GetMaxZ(void),MapViewMap__GetMaxZ); +#endif +#ifdef CMerchantWnd__CMerchantWnd_x +FUNCTION_AT_ADDRESS( CMerchantWnd::CMerchantWnd(class CXWnd *),CMerchantWnd__CMerchantWnd); +#endif +#ifdef CMerchantWnd__Init_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::Init(void),CMerchantWnd__Init); +#endif +#ifdef CMerchantWnd__Activate_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::Activate(class EQPlayer *,float),CMerchantWnd__Activate); +#endif +#ifdef CMerchantWnd__HandleBuy_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::HandleBuy(int),CMerchantWnd__HandleBuy); +#endif +#ifdef CMerchantWnd__HandleSell_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::HandleSell(int),CMerchantWnd__HandleSell); +#endif +#ifdef CMerchantWnd__UpdateBuySellButtons_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::UpdateBuySellButtons(void),CMerchantWnd__UpdateBuySellButtons); +#endif +#ifdef CMerchantWnd__SelectBuySellSlot_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::SelectBuySellSlot(int,class CTextureAnimation *),CMerchantWnd__SelectBuySellSlot); +#endif +#ifdef CMerchantWnd__DisplayBuyOrSellPrice_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::DisplayBuyOrSellPrice(bool,class EQ_Item *),CMerchantWnd__DisplayBuyOrSellPrice); +#endif +#ifdef CMerchantWnd__RequestBuyItem_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::RequestBuyItem(int),CMerchantWnd__RequestBuyItem); +#endif +#ifdef CMerchantWnd__FinishBuyingItem_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::FinishBuyingItem(struct _sell_msg *),CMerchantWnd__FinishBuyingItem); +#endif +#ifdef CMerchantWnd__RequestSellItem_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::RequestSellItem(int),CMerchantWnd__RequestSellItem); +#endif +#ifdef CMerchantWnd__FinishSellingItem_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::FinishSellingItem(struct _sell_msg *),CMerchantWnd__FinishSellingItem); +#endif +#ifdef CMerchantWnd__AddEquipmentToMercArray_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::AddEquipmentToMercArray(class EQ_Equipment *),CMerchantWnd__AddEquipmentToMercArray); +#endif +#ifdef CMerchantWnd__AddNoteToMercArray_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::AddNoteToMercArray(class EQ_Note *),CMerchantWnd__AddNoteToMercArray); +#endif +#ifdef CMerchantWnd__AddContainerToMercArray_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::AddContainerToMercArray(class EQ_Container *),CMerchantWnd__AddContainerToMercArray); +#endif +#ifdef CMerchantWnd__ClearMerchantSlot_x +FUNCTION_AT_ADDRESS(void CMerchantWnd::ClearMerchantSlot(int),CMerchantWnd__ClearMerchantSlot); +#endif +#ifdef CMusicPlayerWnd__CMusicPlayerWnd_x +FUNCTION_AT_ADDRESS( CMusicPlayerWnd::CMusicPlayerWnd(class CXWnd *),CMusicPlayerWnd__CMusicPlayerWnd); +#endif +#ifdef CMusicPlayerWnd__Activate_x +FUNCTION_AT_ADDRESS(void CMusicPlayerWnd::Activate(void),CMusicPlayerWnd__Activate); +#endif +#ifdef CMusicPlayerWnd__AutoStart_x +FUNCTION_AT_ADDRESS(void CMusicPlayerWnd::AutoStart(void),CMusicPlayerWnd__AutoStart); +#endif +#ifdef CMusicPlayerWnd__Update_x +FUNCTION_AT_ADDRESS(void CMusicPlayerWnd::Update(void),CMusicPlayerWnd__Update); +#endif +#ifdef CMusicPlayerWnd__UpdateButtons_x +FUNCTION_AT_ADDRESS(void CMusicPlayerWnd::UpdateButtons(void),CMusicPlayerWnd__UpdateButtons); +#endif +#ifdef CNoteWnd__CNoteWnd_x +FUNCTION_AT_ADDRESS( CNoteWnd::CNoteWnd(class CXWnd *),CNoteWnd__CNoteWnd); +#endif +#ifdef CNoteWnd__Activate_x +FUNCTION_AT_ADDRESS(void CNoteWnd::Activate(void),CNoteWnd__Activate); +#endif +#ifdef CNoteWnd__CheckNote_x +FUNCTION_AT_ADDRESS(bool CNoteWnd::CheckNote(class EQ_Note *),CNoteWnd__CheckNote); +#endif +#ifdef CNoteWnd__SetNote_x +FUNCTION_AT_ADDRESS(void CNoteWnd::SetNote(char *),CNoteWnd__SetNote); +#endif +#ifdef CXStr__operator_lb_rb_x +FUNCTION_AT_ADDRESS(char CXStr::operator[](int)const ,CXStr__operator_lb_rb); +#endif +#ifdef COptionsWnd__COptionsWnd_x +FUNCTION_AT_ADDRESS( COptionsWnd::COptionsWnd(class CXWnd *),COptionsWnd__COptionsWnd); +#endif +#ifdef COptionsWnd__SyncGeneralPage_x +FUNCTION_AT_ADDRESS(void COptionsWnd::SyncGeneralPage(void),COptionsWnd__SyncGeneralPage); +#endif +#ifdef COptionsWnd__SyncDisplayPage_x +FUNCTION_AT_ADDRESS(void COptionsWnd::SyncDisplayPage(void),COptionsWnd__SyncDisplayPage); +#endif +#ifdef COptionsWnd__SyncMousePage_x +FUNCTION_AT_ADDRESS(void COptionsWnd::SyncMousePage(void),COptionsWnd__SyncMousePage); +#endif +#ifdef COptionsWnd__SyncChatPage_x +FUNCTION_AT_ADDRESS(void COptionsWnd::SyncChatPage(void),COptionsWnd__SyncChatPage); +#endif +#ifdef COptionsWnd__SyncColorPage_x +FUNCTION_AT_ADDRESS(void COptionsWnd::SyncColorPage(void),COptionsWnd__SyncColorPage); +#endif +#ifdef COptionsWnd__InitKeyboardPage_x +FUNCTION_AT_ADDRESS(void COptionsWnd::InitKeyboardPage(void),COptionsWnd__InitKeyboardPage); +#endif +#ifdef COptionsWnd__InitKeyboardAssignments_x +FUNCTION_AT_ADDRESS(void COptionsWnd::InitKeyboardAssignments(void),COptionsWnd__InitKeyboardAssignments); +#endif +#ifdef COptionsWnd__RefreshCurrentKeyboardAssignmentList_x +FUNCTION_AT_ADDRESS(void COptionsWnd::RefreshCurrentKeyboardAssignmentList(void),COptionsWnd__RefreshCurrentKeyboardAssignmentList); +#endif +#ifdef COptionsWnd__AddKeyboardAssignment_x +FUNCTION_AT_ADDRESS(void COptionsWnd::AddKeyboardAssignment(int,int,int),COptionsWnd__AddKeyboardAssignment); +#endif +#ifdef COptionsWnd__Activate_x +FUNCTION_AT_ADDRESS(void COptionsWnd::Activate(void),COptionsWnd__Activate); +#endif +#ifdef COptionsWnd__ResetKeysToDefault_x +FUNCTION_AT_ADDRESS(void COptionsWnd::ResetKeysToDefault(void),COptionsWnd__ResetKeysToDefault); +#endif +#ifdef COptionsWnd__RedirectOnProcessFrameTo_x +FUNCTION_AT_ADDRESS(int COptionsWnd::RedirectOnProcessFrameTo(class CPageWnd *),COptionsWnd__RedirectOnProcessFrameTo); +#endif +#ifdef COptionsWnd__RedirectWndNotificationTo_x +FUNCTION_AT_ADDRESS(int COptionsWnd::RedirectWndNotificationTo(class CPageWnd *,class CXWnd *,unsigned __int32,void *),COptionsWnd__RedirectWndNotificationTo); +#endif +#ifdef COptionsWnd__RedirectHandleKeyboardMsgTo_x +FUNCTION_AT_ADDRESS(int COptionsWnd::RedirectHandleKeyboardMsgTo(class CPageWnd *,unsigned __int32,unsigned __int32,bool),COptionsWnd__RedirectHandleKeyboardMsgTo); +#endif +#ifdef COptionsWnd__RedirectDeactivateTo_x +FUNCTION_AT_ADDRESS(int COptionsWnd::RedirectDeactivateTo(class CPageWnd *),COptionsWnd__RedirectDeactivateTo); +#endif +#ifdef COptionsWnd__GeneralPageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int COptionsWnd::GeneralPageOnProcessFrame(void),COptionsWnd__GeneralPageOnProcessFrame); +#endif +#ifdef COptionsWnd__GeneralPageWndNotification_x +FUNCTION_AT_ADDRESS(int COptionsWnd::GeneralPageWndNotification(class CXWnd *,unsigned __int32,void *),COptionsWnd__GeneralPageWndNotification); +#endif +#ifdef COptionsWnd__DisplayPageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int COptionsWnd::DisplayPageOnProcessFrame(void),COptionsWnd__DisplayPageOnProcessFrame); +#endif +#ifdef COptionsWnd__DisplayPageWndNotification_x +FUNCTION_AT_ADDRESS(int COptionsWnd::DisplayPageWndNotification(class CXWnd *,unsigned __int32,void *),COptionsWnd__DisplayPageWndNotification); +#endif +#ifdef COptionsWnd__MousePageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int COptionsWnd::MousePageOnProcessFrame(void),COptionsWnd__MousePageOnProcessFrame); +#endif +#ifdef COptionsWnd__MousePageWndNotification_x +FUNCTION_AT_ADDRESS(int COptionsWnd::MousePageWndNotification(class CXWnd *,unsigned __int32,void *),COptionsWnd__MousePageWndNotification); +#endif +#ifdef COptionsWnd__KeyboardPageWndNotification_x +FUNCTION_AT_ADDRESS(int COptionsWnd::KeyboardPageWndNotification(class CXWnd *,unsigned __int32,void *),COptionsWnd__KeyboardPageWndNotification); +#endif +#ifdef COptionsWnd__KeyboardPageHandleKeyboardMsg_x +FUNCTION_AT_ADDRESS(int COptionsWnd::KeyboardPageHandleKeyboardMsg(unsigned __int32,unsigned __int32,bool),COptionsWnd__KeyboardPageHandleKeyboardMsg); +#endif +#ifdef COptionsWnd__KeyboardPageDeactivate_x +FUNCTION_AT_ADDRESS(int COptionsWnd::KeyboardPageDeactivate(void),COptionsWnd__KeyboardPageDeactivate); +#endif +#ifdef COptionsWnd__KeyboardPageCancelKeypressAssignment_x +FUNCTION_AT_ADDRESS(void COptionsWnd::KeyboardPageCancelKeypressAssignment(void),COptionsWnd__KeyboardPageCancelKeypressAssignment); +#endif +#ifdef COptionsWnd__ChatPageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int COptionsWnd::ChatPageOnProcessFrame(void),COptionsWnd__ChatPageOnProcessFrame); +#endif +#ifdef COptionsWnd__ColorPageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int COptionsWnd::ColorPageOnProcessFrame(void),COptionsWnd__ColorPageOnProcessFrame); +#endif +#ifdef COptionsWnd__ChatPageWndNotification_x +FUNCTION_AT_ADDRESS(int COptionsWnd::ChatPageWndNotification(class CXWnd *,unsigned __int32,void *),COptionsWnd__ChatPageWndNotification); +#endif +#ifdef COptionsWnd__ColorPageWndNotification_x +FUNCTION_AT_ADDRESS(int COptionsWnd::ColorPageWndNotification(class CXWnd *,unsigned __int32,void *),COptionsWnd__ColorPageWndNotification); +#endif +#ifdef COptionsWnd__SaveColors_x +FUNCTION_AT_ADDRESS(void COptionsWnd::SaveColors(int,int,int,int),COptionsWnd__SaveColors); +#endif +#ifdef COptionsWnd__RestoreDefaultColors_x +FUNCTION_AT_ADDRESS(void COptionsWnd::RestoreDefaultColors(void),COptionsWnd__RestoreDefaultColors); +#endif +#ifdef COptionsWnd__SetBagOptions_x +FUNCTION_AT_ADDRESS(void COptionsWnd::SetBagOptions(int,int),COptionsWnd__SetBagOptions); +#endif +#ifdef CPetInfoWnd__CPetInfoWnd_x +FUNCTION_AT_ADDRESS( CPetInfoWnd::CPetInfoWnd(class CXWnd *),CPetInfoWnd__CPetInfoWnd); +#endif +#ifdef CPetInfoWnd__Activate_x +FUNCTION_AT_ADDRESS(void CPetInfoWnd::Activate(void),CPetInfoWnd__Activate); +#endif +#ifdef CPetInfoWnd__SetShowOnSummon_x +FUNCTION_AT_ADDRESS(void CPetInfoWnd::SetShowOnSummon(bool),CPetInfoWnd__SetShowOnSummon); +#endif +#ifdef CPetInfoWnd__Update_x +FUNCTION_AT_ADDRESS(void CPetInfoWnd::Update(void),CPetInfoWnd__Update); +#endif +#ifdef CPetInfoWnd__GetButton_x +FUNCTION_AT_ADDRESS(class CButtonWnd * CPetInfoWnd::GetButton(int),CPetInfoWnd__GetButton); +#endif +#ifdef CPetitionQWnd__CPetitionQWnd_x +FUNCTION_AT_ADDRESS( CPetitionQWnd::CPetitionQWnd(class CXWnd *),CPetitionQWnd__CPetitionQWnd); +#endif +#ifdef CPetitionQWnd__UpdatePetitions_x +FUNCTION_AT_ADDRESS(void CPetitionQWnd::UpdatePetitions(void),CPetitionQWnd__UpdatePetitions); +#endif +#ifdef CPetitionQWnd__Activate_x +FUNCTION_AT_ADDRESS(void CPetitionQWnd::Activate(void),CPetitionQWnd__Activate); +#endif +#ifdef CPetitionQWnd__SetPriorityDisplay_x +FUNCTION_AT_ADDRESS(void CPetitionQWnd::SetPriorityDisplay(void),CPetitionQWnd__SetPriorityDisplay); +#endif +#ifdef CPetitionQWnd__AddGMText_x +FUNCTION_AT_ADDRESS(void CPetitionQWnd::AddGMText(void),CPetitionQWnd__AddGMText); +#endif +#ifdef CPetitionQWnd__CheckedOut_x +FUNCTION_AT_ADDRESS(void CPetitionQWnd::CheckedOut(struct petitionQtype const *,int),CPetitionQWnd__CheckedOut); +#endif +#ifdef CPetitionQWnd__UndoCheckout_x +FUNCTION_AT_ADDRESS(void CPetitionQWnd::UndoCheckout(void),CPetitionQWnd__UndoCheckout); +#endif +#ifdef CPetitionQWnd__ClearCurrentPet_x +FUNCTION_AT_ADDRESS(void CPetitionQWnd::ClearCurrentPet(void),CPetitionQWnd__ClearCurrentPet); +#endif +#ifdef CPetitionQWnd__FillFields_x +FUNCTION_AT_ADDRESS(void CPetitionQWnd::FillFields(void),CPetitionQWnd__FillFields); +#endif +#ifdef CPetitionQWnd__SetButtonsForPetition_x +FUNCTION_AT_ADDRESS(void CPetitionQWnd::SetButtonsForPetition(bool,bool),CPetitionQWnd__SetButtonsForPetition); +#endif +#ifdef CPetitionQWnd__LogPetitionText_x +FUNCTION_AT_ADDRESS(void CPetitionQWnd::LogPetitionText(void),CPetitionQWnd__LogPetitionText); +#endif +#ifdef CPetitionQWnd__GetCurrentPetitionersName_x +FUNCTION_AT_ADDRESS(char * CPetitionQWnd::GetCurrentPetitionersName(void),CPetitionQWnd__GetCurrentPetitionersName); +#endif +#ifdef CPlayerNotesWnd__CPlayerNotesWnd_x +FUNCTION_AT_ADDRESS( CPlayerNotesWnd::CPlayerNotesWnd(class CXWnd *),CPlayerNotesWnd__CPlayerNotesWnd); +#endif +#ifdef CPlayerNotesWnd__Activate_x +FUNCTION_AT_ADDRESS(void CPlayerNotesWnd::Activate(void),CPlayerNotesWnd__Activate); +#endif +#ifdef CPlayerNotesWnd__SaveNotes_x +FUNCTION_AT_ADDRESS(void CPlayerNotesWnd::SaveNotes(void),CPlayerNotesWnd__SaveNotes); +#endif +#ifdef CPlayerNotesWnd__AppendText_x +FUNCTION_AT_ADDRESS(void CPlayerNotesWnd::AppendText(char *),CPlayerNotesWnd__AppendText); +#endif +#ifdef CPlayerWnd__CPlayerWnd_x +FUNCTION_AT_ADDRESS( CPlayerWnd::CPlayerWnd(class CXWnd *),CPlayerWnd__CPlayerWnd); +#endif +#ifdef CPlayerWnd__Init_x +FUNCTION_AT_ADDRESS(void CPlayerWnd::Init(void),CPlayerWnd__Init); +#endif +#ifdef CPlayerWnd__Activate_x +FUNCTION_AT_ADDRESS(void CPlayerWnd::Activate(void),CPlayerWnd__Activate); +#endif +#ifdef CPlayerWnd__CreateLocalMenu_x +FUNCTION_AT_ADDRESS(void CPlayerWnd::CreateLocalMenu(void),CPlayerWnd__CreateLocalMenu); +#endif +#ifdef CPlayerWnd__UpdateContextMenu_x +FUNCTION_AT_ADDRESS(void CPlayerWnd::UpdateContextMenu(void),CPlayerWnd__UpdateContextMenu); +#endif +#ifdef CQuantityWnd__CQuantityWnd_x +FUNCTION_AT_ADDRESS( CQuantityWnd::CQuantityWnd(class CXWnd *),CQuantityWnd__CQuantityWnd); +#endif +#ifdef CQuantityWnd__Activate_x +FUNCTION_AT_ADDRESS(void CQuantityWnd::Activate(class CXWnd *,int,int,int,int,bool),CQuantityWnd__Activate); +#endif +#ifdef CQuantityWnd__CheckMaxEditWnd_x +FUNCTION_AT_ADDRESS(void CQuantityWnd::CheckMaxEditWnd(void),CQuantityWnd__CheckMaxEditWnd); +#endif +#ifdef CQuantityWnd__UpdateEditWndFromSlider_x +FUNCTION_AT_ADDRESS(void CQuantityWnd::UpdateEditWndFromSlider(void),CQuantityWnd__UpdateEditWndFromSlider); +#endif +#ifdef CQuantityWnd__UpdateSliderFromEditWnd_x +FUNCTION_AT_ADDRESS(void CQuantityWnd::UpdateSliderFromEditWnd(void),CQuantityWnd__UpdateSliderFromEditWnd); +#endif +#ifdef CRaidOptionsWnd__CRaidOptionsWnd_x +FUNCTION_AT_ADDRESS( CRaidOptionsWnd::CRaidOptionsWnd(class CXWnd *),CRaidOptionsWnd__CRaidOptionsWnd); +#endif +#ifdef CRaidOptionsWnd__Init_x +FUNCTION_AT_ADDRESS(void CRaidOptionsWnd::Init(void),CRaidOptionsWnd__Init); +#endif +#ifdef CRaidOptionsWnd__Activate_x +FUNCTION_AT_ADDRESS(void CRaidOptionsWnd::Activate(void),CRaidOptionsWnd__Activate); +#endif +#ifdef CRaidOptionsWnd__AddLooterToList_x +FUNCTION_AT_ADDRESS(void CRaidOptionsWnd::AddLooterToList(char *),CRaidOptionsWnd__AddLooterToList); +#endif +#ifdef CRaidOptionsWnd__ClearLooterList_x +FUNCTION_AT_ADDRESS(void CRaidOptionsWnd::ClearLooterList(void),CRaidOptionsWnd__ClearLooterList); +#endif +#ifdef CRaidOptionsWnd__UpdateComponents_x +FUNCTION_AT_ADDRESS(void CRaidOptionsWnd::UpdateComponents(void),CRaidOptionsWnd__UpdateComponents); +#endif +#ifdef CRaidOptionsWnd__InitializeClassColors_x +FUNCTION_AT_ADDRESS(void CRaidOptionsWnd::InitializeClassColors(void),CRaidOptionsWnd__InitializeClassColors); +#endif +#ifdef CRaidWnd__CRaidWnd_x +FUNCTION_AT_ADDRESS( CRaidWnd::CRaidWnd(class CXWnd *),CRaidWnd__CRaidWnd); +#endif +#ifdef CRaidWnd__Init_x +FUNCTION_AT_ADDRESS(void CRaidWnd::Init(void),CRaidWnd__Init); +#endif +#ifdef CRaidWnd__Activate_x +FUNCTION_AT_ADDRESS(void CRaidWnd::Activate(void),CRaidWnd__Activate); +#endif +#ifdef CRaidWnd__AddPlayertoList_x +FUNCTION_AT_ADDRESS(void CRaidWnd::AddPlayertoList(char *,char *,char *,char *,int,int,bool),CRaidWnd__AddPlayertoList); +#endif +#ifdef CRaidWnd__RemovePlayerFromList_x +FUNCTION_AT_ADDRESS(void CRaidWnd::RemovePlayerFromList(char *,int),CRaidWnd__RemovePlayerFromList); +#endif +#ifdef CRaidWnd__SetRaidCount_x +FUNCTION_AT_ADDRESS(void CRaidWnd::SetRaidCount(int),CRaidWnd__SetRaidCount); +#endif +#ifdef CRaidWnd__ClearPlayerList_x +FUNCTION_AT_ADDRESS(void CRaidWnd::ClearPlayerList(void),CRaidWnd__ClearPlayerList); +#endif +#ifdef CRaidWnd__AddSeparator_x +FUNCTION_AT_ADDRESS(void CRaidWnd::AddSeparator(void),CRaidWnd__AddSeparator); +#endif +#ifdef CRaidWnd__SetRaidMemberRank_x +FUNCTION_AT_ADDRESS(void CRaidWnd::SetRaidMemberRank(char *,char *,int),CRaidWnd__SetRaidMemberRank); +#endif +#ifdef CRaidWnd__ChangePosition_x +FUNCTION_AT_ADDRESS(void CRaidWnd::ChangePosition(char *,int,int,int,bool),CRaidWnd__ChangePosition); +#endif +#ifdef CRaidWnd__ChangeRaidGroupLeader_x +FUNCTION_AT_ADDRESS(void CRaidWnd::ChangeRaidGroupLeader(char *,int,char *),CRaidWnd__ChangeRaidGroupLeader); +#endif +#ifdef CRaidWnd__UpdateMemberName_x +FUNCTION_AT_ADDRESS(void CRaidWnd::UpdateMemberName(char *,char *,int),CRaidWnd__UpdateMemberName); +#endif +#ifdef CRaidWnd__SetRaidTarget_x +FUNCTION_AT_ADDRESS(void CRaidWnd::SetRaidTarget(char *,int,char *,int),CRaidWnd__SetRaidTarget); +#endif +#ifdef CRaidWnd__UpdateLevelAverage_x +FUNCTION_AT_ADDRESS(void CRaidWnd::UpdateLevelAverage(int),CRaidWnd__UpdateLevelAverage); +#endif +#ifdef CRaidWnd__UpdateButtons_x +FUNCTION_AT_ADDRESS(void CRaidWnd::UpdateButtons(void),CRaidWnd__UpdateButtons); +#endif +#ifdef CRaidWnd__InitializeClassColors_x +FUNCTION_AT_ADDRESS(void CRaidWnd::InitializeClassColors(void),CRaidWnd__InitializeClassColors); +#endif +#ifdef CRaidWnd__SetPlayerClassColor_x +FUNCTION_AT_ADDRESS(void CRaidWnd::SetPlayerClassColor(int,int,int),CRaidWnd__SetPlayerClassColor); +#endif +#ifdef CRaidWnd__SetPlayerClassColor1_x +FUNCTION_AT_ADDRESS(void CRaidWnd::SetPlayerClassColor(char *,int,int),CRaidWnd__SetPlayerClassColor1); +#endif +#ifdef CRaidWnd__SetClassColor_x +FUNCTION_AT_ADDRESS(void CRaidWnd::SetClassColor(int,unsigned long),CRaidWnd__SetClassColor); +#endif +#ifdef CRaidWnd__ResortRaidGroupList_x +FUNCTION_AT_ADDRESS(void CRaidWnd::ResortRaidGroupList(int,int),CRaidWnd__ResortRaidGroupList); +#endif +#ifdef CRaidWnd__FindOpenIndexInGroup_x +FUNCTION_AT_ADDRESS(int CRaidWnd::FindOpenIndexInGroup(int),CRaidWnd__FindOpenIndexInGroup); +#endif +#ifdef CRaidWnd__FindIndexNotInGroupList_x +FUNCTION_AT_ADDRESS(int CRaidWnd::FindIndexNotInGroupList(char *),CRaidWnd__FindIndexNotInGroupList); +#endif +#ifdef CRaidWnd__FindPlayerIndexInGroup_x +FUNCTION_AT_ADDRESS(int CRaidWnd::FindPlayerIndexInGroup(char *,int),CRaidWnd__FindPlayerIndexInGroup); +#endif +#ifdef CSelectorWnd__CSelectorWnd_x +FUNCTION_AT_ADDRESS( CSelectorWnd::CSelectorWnd(class CXWnd *),CSelectorWnd__CSelectorWnd); +#endif +#ifdef CSelectorWnd__Activate_x +FUNCTION_AT_ADDRESS(void CSelectorWnd::Activate(void),CSelectorWnd__Activate); +#endif +#ifdef CSelectorWnd__KeyMapUpdated_x +FUNCTION_AT_ADDRESS(void CSelectorWnd::KeyMapUpdated(void),CSelectorWnd__KeyMapUpdated); +#endif +#ifdef CSkillsSelectWnd__CSkillsSelectWnd_x +FUNCTION_AT_ADDRESS( CSkillsSelectWnd::CSkillsSelectWnd(class CXWnd *),CSkillsSelectWnd__CSkillsSelectWnd); +#endif +#ifdef CSkillsSelectWnd__Refresh_x +FUNCTION_AT_ADDRESS(void CSkillsSelectWnd::Refresh(void),CSkillsSelectWnd__Refresh); +#endif +#ifdef CSkillsSelectWnd__UpdateAll_x +FUNCTION_AT_ADDRESS(void CSkillsSelectWnd::UpdateAll(void),CSkillsSelectWnd__UpdateAll); +#endif +#ifdef CSkillsSelectWnd__UpdateSkill_x +FUNCTION_AT_ADDRESS(void CSkillsSelectWnd::UpdateSkill(int),CSkillsSelectWnd__UpdateSkill); +#endif +#ifdef CSkillsSelectWnd__SetTypesToDisplay_x +FUNCTION_AT_ADDRESS(void CSkillsSelectWnd::SetTypesToDisplay(int),CSkillsSelectWnd__SetTypesToDisplay); +#endif +#ifdef CSkillsWnd__CSkillsWnd_x +FUNCTION_AT_ADDRESS( CSkillsWnd::CSkillsWnd(class CXWnd *),CSkillsWnd__CSkillsWnd); +#endif +#ifdef CSkillsWnd__Activate_x +FUNCTION_AT_ADDRESS(void CSkillsWnd::Activate(void),CSkillsWnd__Activate); +#endif +#ifdef CSkillsWnd__SkillImproveOccurred_x +FUNCTION_AT_ADDRESS(void CSkillsWnd::SkillImproveOccurred(int),CSkillsWnd__SkillImproveOccurred); +#endif +#ifdef CSkillsWnd__UpdateAll_x +FUNCTION_AT_ADDRESS(void CSkillsWnd::UpdateAll(void),CSkillsWnd__UpdateAll); +#endif +#ifdef CSkillsWnd__UpdateSkill_x +FUNCTION_AT_ADDRESS(void CSkillsWnd::UpdateSkill(int),CSkillsWnd__UpdateSkill); +#endif +#ifdef CSocialEditWnd__CSocialEditWnd_x +FUNCTION_AT_ADDRESS( CSocialEditWnd::CSocialEditWnd(class CXWnd *),CSocialEditWnd__CSocialEditWnd); +#endif +#ifdef CSocialEditWnd__Init_x +FUNCTION_AT_ADDRESS(void CSocialEditWnd::Init(void),CSocialEditWnd__Init); +#endif +#ifdef CSocialEditWnd__Activate_x +FUNCTION_AT_ADDRESS(void CSocialEditWnd::Activate(int),CSocialEditWnd__Activate); +#endif +#ifdef CSocialEditWnd__ClickedAccept_x +FUNCTION_AT_ADDRESS(void CSocialEditWnd::ClickedAccept(void),CSocialEditWnd__ClickedAccept); +#endif +#ifdef CSocialEditWnd__ClickedClear_x +FUNCTION_AT_ADDRESS(void CSocialEditWnd::ClickedClear(void),CSocialEditWnd__ClickedClear); +#endif +#ifdef CSocialEditWnd__ClickedTextColorButton_x +FUNCTION_AT_ADDRESS(void CSocialEditWnd::ClickedTextColorButton(int),CSocialEditWnd__ClickedTextColorButton); +#endif +#ifdef CSocialEditWnd__GetSocialTextColor_x +FUNCTION_AT_ADDRESS(unsigned long CSocialEditWnd::GetSocialTextColor(int),CSocialEditWnd__GetSocialTextColor); +#endif +#ifdef CSocialEditWnd__UpdateControlsFromSocial_x +FUNCTION_AT_ADDRESS(void CSocialEditWnd::UpdateControlsFromSocial(void),CSocialEditWnd__UpdateControlsFromSocial); +#endif +#ifdef CSoulmarkWnd__CSoulmarkWnd_x +FUNCTION_AT_ADDRESS( CSoulmarkWnd::CSoulmarkWnd(class CXWnd *),CSoulmarkWnd__CSoulmarkWnd); +#endif +#ifdef CSoulmarkWnd__UpdateSoulmarks_x +FUNCTION_AT_ADDRESS(void CSoulmarkWnd::UpdateSoulmarks(struct soulMarkMsg *),CSoulmarkWnd__UpdateSoulmarks); +#endif +#ifdef CSoulmarkWnd__UpdateList_x +FUNCTION_AT_ADDRESS(void CSoulmarkWnd::UpdateList(void),CSoulmarkWnd__UpdateList); +#endif +#ifdef CSoulmarkWnd__Activate_x +FUNCTION_AT_ADDRESS(void CSoulmarkWnd::Activate(void),CSoulmarkWnd__Activate); +#endif +#ifdef CSoulmarkWnd__Activate1_x +FUNCTION_AT_ADDRESS(void CSoulmarkWnd::Activate(char *,char *),CSoulmarkWnd__Activate1); +#endif +#ifdef CSoulmarkWnd__SaveMarks_x +FUNCTION_AT_ADDRESS(void CSoulmarkWnd::SaveMarks(void),CSoulmarkWnd__SaveMarks); +#endif +#ifdef CSoulmarkWnd__FillFields_x +FUNCTION_AT_ADDRESS(void CSoulmarkWnd::FillFields(void),CSoulmarkWnd__FillFields); +#endif +#ifdef CSoulmarkWnd__Clear_x +FUNCTION_AT_ADDRESS(void CSoulmarkWnd::Clear(void),CSoulmarkWnd__Clear); +#endif +#ifdef CSoulmarkWnd__Inquire_x +FUNCTION_AT_ADDRESS(void CSoulmarkWnd::Inquire(char *,char *),CSoulmarkWnd__Inquire); +#endif +#ifdef CSoulmarkWnd__AddMark_x +FUNCTION_AT_ADDRESS(void CSoulmarkWnd::AddMark(int,char *,char *,char *),CSoulmarkWnd__AddMark); +#endif +#ifdef CSoulmarkWnd__Inquire1_x +FUNCTION_AT_ADDRESS(void CSoulmarkWnd::Inquire(char *),CSoulmarkWnd__Inquire1); +#endif +#ifdef CSoulmarkWnd__Praise_x +FUNCTION_AT_ADDRESS(void CSoulmarkWnd::Praise(char *),CSoulmarkWnd__Praise); +#endif +#ifdef CSoulmarkWnd__Warn_x +FUNCTION_AT_ADDRESS(void CSoulmarkWnd::Warn(char *),CSoulmarkWnd__Warn); +#endif +#ifdef CSpellBookWnd__CSpellBookWnd_x +FUNCTION_AT_ADDRESS( CSpellBookWnd::CSpellBookWnd(class CXWnd *),CSpellBookWnd__CSpellBookWnd); +#endif +#ifdef CSpellBookWnd__Init_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::Init(void),CSpellBookWnd__Init); +#endif +#ifdef CSpellBookWnd__Activate_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::Activate(void),CSpellBookWnd__Activate); +#endif +#ifdef CSpellBookWnd__GetBookSlot_x +FUNCTION_AT_ADDRESS(int __cdecl CSpellBookWnd::GetBookSlot(int),CSpellBookWnd__GetBookSlot); +#endif +#ifdef CSpellBookWnd__MemorizeSet_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::MemorizeSet(int *,int),CSpellBookWnd__MemorizeSet); +#endif +#ifdef CSpellBookWnd__ContinueSetMem_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::ContinueSetMem(void),CSpellBookWnd__ContinueSetMem); +#endif +#ifdef CSpellBookWnd__DelayedSpellMem_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::DelayedSpellMem(int,int,int),CSpellBookWnd__DelayedSpellMem); +#endif +#ifdef CSpellBookWnd__EndSetMem_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::EndSetMem(void),CSpellBookWnd__EndSetMem); +#endif +#ifdef CSpellBookWnd__AutoMemSpell_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::AutoMemSpell(int,int),CSpellBookWnd__AutoMemSpell); +#endif +#ifdef CSpellBookWnd__HandleLeftClickOnSpell_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::HandleLeftClickOnSpell(int),CSpellBookWnd__HandleLeftClickOnSpell); +#endif +#ifdef CSpellBookWnd__HandleRightClickOnSpell_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::HandleRightClickOnSpell(int),CSpellBookWnd__HandleRightClickOnSpell); +#endif +#ifdef CSpellBookWnd__CanStartMemming_x +FUNCTION_AT_ADDRESS(bool CSpellBookWnd::CanStartMemming(int),CSpellBookWnd__CanStartMemming); +#endif +#ifdef CSpellBookWnd__StartSpellMemorizationDrag_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::StartSpellMemorizationDrag(int,class CButtonWnd *),CSpellBookWnd__StartSpellMemorizationDrag); +#endif +#ifdef CSpellBookWnd__StartSpellMemorization_x +FUNCTION_AT_ADDRESS(bool CSpellBookWnd::StartSpellMemorization(int,int,bool),CSpellBookWnd__StartSpellMemorization); +#endif +#ifdef CSpellBookWnd__FinishMemorizing_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::FinishMemorizing(int,int),CSpellBookWnd__FinishMemorizing); +#endif +#ifdef CSpellBookWnd__GetSpellMemTicksLeft_x +FUNCTION_AT_ADDRESS(int CSpellBookWnd::GetSpellMemTicksLeft(void),CSpellBookWnd__GetSpellMemTicksLeft); +#endif +#ifdef CSpellBookWnd__StartSpellScribe_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::StartSpellScribe(int),CSpellBookWnd__StartSpellScribe); +#endif +#ifdef CSpellBookWnd__FinishScribing_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::FinishScribing(int,int),CSpellBookWnd__FinishScribing); +#endif +#ifdef CSpellBookWnd__GetSpellScribeTicksLeft_x +FUNCTION_AT_ADDRESS(int CSpellBookWnd::GetSpellScribeTicksLeft(void),CSpellBookWnd__GetSpellScribeTicksLeft); +#endif +#ifdef CSpellBookWnd__SwapSpellBookSlots_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::SwapSpellBookSlots(int,int),CSpellBookWnd__SwapSpellBookSlots); +#endif +#ifdef CSpellBookWnd__HandleSpellInfoDisplay_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::HandleSpellInfoDisplay(class CXWnd *),CSpellBookWnd__HandleSpellInfoDisplay); +#endif +#ifdef CSpellBookWnd__DisplaySpellInfo_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::DisplaySpellInfo(int),CSpellBookWnd__DisplaySpellInfo); +#endif +#ifdef CSpellBookWnd__TurnToPage_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::TurnToPage(int),CSpellBookWnd__TurnToPage); +#endif +#ifdef CSpellBookWnd__UpdateSpellBookDisplay_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::UpdateSpellBookDisplay(void),CSpellBookWnd__UpdateSpellBookDisplay); +#endif +#ifdef CSpellBookWnd__StopSpellBookAction_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::StopSpellBookAction(void),CSpellBookWnd__StopSpellBookAction); +#endif +#ifdef CSpellBookWnd__GetSpellDeletionConfirmation_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::GetSpellDeletionConfirmation(int),CSpellBookWnd__GetSpellDeletionConfirmation); +#endif +#ifdef CSpellBookWnd__RequestSpellDeletion_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::RequestSpellDeletion(int),CSpellBookWnd__RequestSpellDeletion); +#endif +#ifdef CSpellBookWnd__DeleteSpellFromBook_x +FUNCTION_AT_ADDRESS(void CSpellBookWnd::DeleteSpellFromBook(int,int),CSpellBookWnd__DeleteSpellFromBook); +#endif +#ifdef CXStr__Mid_x +FUNCTION_AT_ADDRESS(class CXStr CXStr::Mid(int,int)const ,CXStr__Mid); +#endif +#ifdef CTargetWnd__CTargetWnd_x +FUNCTION_AT_ADDRESS( CTargetWnd::CTargetWnd(class CXWnd *),CTargetWnd__CTargetWnd); +#endif +#ifdef CTargetWnd__Activate_x +FUNCTION_AT_ADDRESS(void CTargetWnd::Activate(void),CTargetWnd__Activate); +#endif +#ifdef CTextEntryWnd__CTextEntryWnd_x +FUNCTION_AT_ADDRESS( CTextEntryWnd::CTextEntryWnd(class CXWnd *),CTextEntryWnd__CTextEntryWnd); +#endif +#ifdef CTextEntryWnd__Activate_x +FUNCTION_AT_ADDRESS(void CTextEntryWnd::Activate(class CXWnd *,int,char *,int,int,char *),CTextEntryWnd__Activate); +#endif +#ifdef CTextEntryWnd__Callback_x +FUNCTION_AT_ADDRESS(void CTextEntryWnd::Callback(bool),CTextEntryWnd__Callback); +#endif +#ifdef CTextEntryWnd__UpdateButtons_x +FUNCTION_AT_ADDRESS(void CTextEntryWnd::UpdateButtons(void),CTextEntryWnd__UpdateButtons); +#endif +#ifdef CTextEntryWnd__GetEntryText_x +FUNCTION_AT_ADDRESS(class CXStr CTextEntryWnd::GetEntryText(void),CTextEntryWnd__GetEntryText); +#endif +#ifdef CTimeLeftWnd__CTimeLeftWnd_x +FUNCTION_AT_ADDRESS( CTimeLeftWnd::CTimeLeftWnd(long),CTimeLeftWnd__CTimeLeftWnd); +#endif +#ifdef CTimeLeftWnd__Activate_x +FUNCTION_AT_ADDRESS(void CTimeLeftWnd::Activate(void),CTimeLeftWnd__Activate); +#endif +#ifdef CTipWnd__CTipWnd_x +FUNCTION_AT_ADDRESS( CTipWnd::CTipWnd(class CXWnd *,int),CTipWnd__CTipWnd); +#endif +#ifdef CTipWnd__Activate_x +FUNCTION_AT_ADDRESS(bool CTipWnd::Activate(int,bool),CTipWnd__Activate); +#endif +#ifdef CTipWnd__UpdateButtons_x +FUNCTION_AT_ADDRESS(void CTipWnd::UpdateButtons(void),CTipWnd__UpdateButtons); +#endif +#ifdef CTipWnd__InitializeTipSettings_x +FUNCTION_AT_ADDRESS(void CTipWnd::InitializeTipSettings(void),CTipWnd__InitializeTipSettings); +#endif +#ifdef CTipWnd__CleanDayTips_x +FUNCTION_AT_ADDRESS(void CTipWnd::CleanDayTips(void),CTipWnd__CleanDayTips); +#endif +#ifdef CTipWnd__SelectRandomTip_x +FUNCTION_AT_ADDRESS(int CTipWnd::SelectRandomTip(void),CTipWnd__SelectRandomTip); +#endif +#ifdef CTipWnd__SetTOTD_x +FUNCTION_AT_ADDRESS(void CTipWnd::SetTOTD(int),CTipWnd__SetTOTD); +#endif +#ifdef CTipWnd__IsRecentTOTD_x +FUNCTION_AT_ADDRESS(bool CTipWnd::IsRecentTOTD(int),CTipWnd__IsRecentTOTD); +#endif +#ifdef CTipWnd__AddContextTip_x +FUNCTION_AT_ADDRESS(void CTipWnd::AddContextTip(int),CTipWnd__AddContextTip); +#endif +#ifdef CTipWnd__ShowHistoryTip_x +FUNCTION_AT_ADDRESS(void CTipWnd::ShowHistoryTip(int),CTipWnd__ShowHistoryTip); +#endif +#ifdef CTipWnd__LoadINISettings_x +FUNCTION_AT_ADDRESS(void CTipWnd::LoadINISettings(void),CTipWnd__LoadINISettings); +#endif +#ifdef CTipWnd__LoadDayTips_x +FUNCTION_AT_ADDRESS(void CTipWnd::LoadDayTips(void),CTipWnd__LoadDayTips); +#endif +#ifdef CTrackingWnd__CTrackingWnd_x +FUNCTION_AT_ADDRESS( CTrackingWnd::CTrackingWnd(class CXWnd *),CTrackingWnd__CTrackingWnd); +#endif +#ifdef CTrackingWnd__Init_x +FUNCTION_AT_ADDRESS(void CTrackingWnd::Init(void),CTrackingWnd__Init); +#endif +#ifdef CTrackingWnd__Activate_x +FUNCTION_AT_ADDRESS(void CTrackingWnd::Activate(void),CTrackingWnd__Activate); +#endif +#ifdef CTrackingWnd__NotifyServerOfTrackingTarget_x +FUNCTION_AT_ADDRESS(void CTrackingWnd::NotifyServerOfTrackingTarget(int),CTrackingWnd__NotifyServerOfTrackingTarget); +#endif +#ifdef CTrackingWnd__UpdateTrackingControls_x +FUNCTION_AT_ADDRESS(void CTrackingWnd::UpdateTrackingControls(void),CTrackingWnd__UpdateTrackingControls); +#endif +#ifdef CTrackingWnd__GetTrackColor_x +FUNCTION_AT_ADDRESS(unsigned long CTrackingWnd::GetTrackColor(int),CTrackingWnd__GetTrackColor); +#endif +#ifdef CTrackingWnd__UpdateTrackingList_x +FUNCTION_AT_ADDRESS(void CTrackingWnd::UpdateTrackingList(bool),CTrackingWnd__UpdateTrackingList); +#endif +#ifdef CTrackingWnd__GenerateTrackingList_x +FUNCTION_AT_ADDRESS(void CTrackingWnd::GenerateTrackingList(void),CTrackingWnd__GenerateTrackingList); +#endif +#ifdef CTrackingWnd__SetTrackingList_x +FUNCTION_AT_ADDRESS(void CTrackingWnd::SetTrackingList(struct TrackingHit *,int),CTrackingWnd__SetTrackingList); +#endif +#ifdef CTrackingWnd__DoTrackSort_x +FUNCTION_AT_ADDRESS(void CTrackingWnd::DoTrackSort(bool),CTrackingWnd__DoTrackSort); +#endif +#ifdef CTrackingWnd__DoTrackFilter_x +FUNCTION_AT_ADDRESS(void CTrackingWnd::DoTrackFilter(bool),CTrackingWnd__DoTrackFilter); +#endif +#ifdef CTrackingWnd__RemovePlayerFromTracking_x +FUNCTION_AT_ADDRESS(void CTrackingWnd::RemovePlayerFromTracking(class EQPlayer *),CTrackingWnd__RemovePlayerFromTracking); +#endif +#ifdef CTrackingWnd__RemovePlayerFromTracking1_x +FUNCTION_AT_ADDRESS(void CTrackingWnd::RemovePlayerFromTracking(int),CTrackingWnd__RemovePlayerFromTracking1); +#endif +#ifdef CTrackingWnd__RemoveFromListWndByData_x +FUNCTION_AT_ADDRESS(void CTrackingWnd::RemoveFromListWndByData(unsigned int),CTrackingWnd__RemoveFromListWndByData); +#endif +#ifdef CTrackingWnd__GetListIdByData_x +FUNCTION_AT_ADDRESS(int CTrackingWnd::GetListIdByData(unsigned int),CTrackingWnd__GetListIdByData); +#endif +#ifdef CTradeWnd__CTradeWnd_x +FUNCTION_AT_ADDRESS( CTradeWnd::CTradeWnd(class CXWnd *),CTradeWnd__CTradeWnd); +#endif +#ifdef CTradeWnd__Init_x +FUNCTION_AT_ADDRESS(void CTradeWnd::Init(void),CTradeWnd__Init); +#endif +#ifdef CTradeWnd__Activate_x +FUNCTION_AT_ADDRESS(void CTradeWnd::Activate(class EQPlayer *,bool),CTradeWnd__Activate); +#endif +#ifdef CTradeWnd__ClickedCancelButton_x +FUNCTION_AT_ADDRESS(void CTradeWnd::ClickedCancelButton(void),CTradeWnd__ClickedCancelButton); +#endif +#ifdef CTradeWnd__ClickedTradeButton_x +FUNCTION_AT_ADDRESS(void CTradeWnd::ClickedTradeButton(void),CTradeWnd__ClickedTradeButton); +#endif +#ifdef CTradeWnd__ClickedMoneyButton_x +FUNCTION_AT_ADDRESS(void CTradeWnd::ClickedMoneyButton(int),CTradeWnd__ClickedMoneyButton); +#endif +#ifdef CTradeWnd__UpdateTradeDisplay_x +FUNCTION_AT_ADDRESS(void CTradeWnd::UpdateTradeDisplay(void),CTradeWnd__UpdateTradeDisplay); +#endif +#ifdef CTradeWnd__IsMyTradeSlot_x +FUNCTION_AT_ADDRESS(bool CTradeWnd::IsMyTradeSlot(int,bool *),CTradeWnd__IsMyTradeSlot); +#endif +#ifdef CTradeWnd__TradeItemChanged_x +FUNCTION_AT_ADDRESS(void CTradeWnd::TradeItemChanged(int,int),CTradeWnd__TradeItemChanged); +#endif +#ifdef CTradeWnd__CompleteTrade_x +FUNCTION_AT_ADDRESS(void CTradeWnd::CompleteTrade(void),CTradeWnd__CompleteTrade); +#endif +#ifdef CTradeWnd__AddEquipmentToHisTradeArray_x +FUNCTION_AT_ADDRESS(void CTradeWnd::AddEquipmentToHisTradeArray(class EQ_Equipment *),CTradeWnd__AddEquipmentToHisTradeArray); +#endif +#ifdef CTradeWnd__AddNoteToHisTradeArray_x +FUNCTION_AT_ADDRESS(void CTradeWnd::AddNoteToHisTradeArray(class EQ_Note *),CTradeWnd__AddNoteToHisTradeArray); +#endif +#ifdef CTradeWnd__AddContainerToHisTradeArray_x +FUNCTION_AT_ADDRESS(void CTradeWnd::AddContainerToHisTradeArray(class EQ_Container *),CTradeWnd__AddContainerToHisTradeArray); +#endif +#ifdef CTradeWnd__DeleteItemFromHisTradeArray_x +FUNCTION_AT_ADDRESS(void CTradeWnd::DeleteItemFromHisTradeArray(int),CTradeWnd__DeleteItemFromHisTradeArray); +#endif +#ifdef CTradeWnd__DropItemIntoTrade_x +FUNCTION_AT_ADDRESS(void CTradeWnd::DropItemIntoTrade(void),CTradeWnd__DropItemIntoTrade); +#endif +#ifdef CTradeWnd__DropMoneyIntoTrade_x +//FUNCTION_AT_ADDRESS(CTradeWnd::DropMoneyIntoTrade(void),CTradeWnd__DropMoneyIntoTrade); +#endif +#ifdef CTradeWnd__SetMyReadyTrade_x +FUNCTION_AT_ADDRESS(void CTradeWnd::SetMyReadyTrade(bool),CTradeWnd__SetMyReadyTrade); +#endif +#ifdef CTradeWnd__SetHisReadyTrade_x +FUNCTION_AT_ADDRESS(void CTradeWnd::SetHisReadyTrade(bool),CTradeWnd__SetHisReadyTrade); +#endif +#ifdef CTradeWnd__SetHisMoney_x +FUNCTION_AT_ADDRESS(void CTradeWnd::SetHisMoney(int,long),CTradeWnd__SetHisMoney); +#endif +#ifdef CTrainWnd__CTrainWnd_x +FUNCTION_AT_ADDRESS( CTrainWnd::CTrainWnd(class CXWnd *),CTrainWnd__CTrainWnd); +#endif +#ifdef CTrainWnd__Activate_x +FUNCTION_AT_ADDRESS(void CTrainWnd::Activate(void),CTrainWnd__Activate); +#endif +#ifdef CTrainWnd__UpdateRight_x +FUNCTION_AT_ADDRESS(void CTrainWnd::UpdateRight(void),CTrainWnd__UpdateRight); +#endif +#ifdef CTrainWnd__UpdateAll_x +FUNCTION_AT_ADDRESS(void CTrainWnd::UpdateAll(bool),CTrainWnd__UpdateAll); +#endif +#ifdef CTrainWnd__SkillName_x +FUNCTION_AT_ADDRESS(char * CTrainWnd::SkillName(int),CTrainWnd__SkillName); +#endif +#ifdef CTrainWnd__SkillValue_x +FUNCTION_AT_ADDRESS(int CTrainWnd::SkillValue(int),CTrainWnd__SkillValue); +#endif +#ifdef CTrainWnd__SwapSkill_x +FUNCTION_AT_ADDRESS(void CTrainWnd::SwapSkill(int,int),CTrainWnd__SwapSkill); +#endif +#ifdef CTrainWnd__SortNames_x +FUNCTION_AT_ADDRESS(void CTrainWnd::SortNames(int),CTrainWnd__SortNames); +#endif +#ifdef CTrainWnd__SortSkill_x +FUNCTION_AT_ADDRESS(void CTrainWnd::SortSkill(int),CTrainWnd__SortSkill); +#endif +#ifdef CTrainWnd__UpdateSkill_x +FUNCTION_AT_ADDRESS(void CTrainWnd::UpdateSkill(int),CTrainWnd__UpdateSkill); +#endif +#ifdef CTrainWnd__SkillChanged_x +FUNCTION_AT_ADDRESS(void CTrainWnd::SkillChanged(int),CTrainWnd__SkillChanged); +#endif +#ifdef CTrainWnd__SetGMData_x +FUNCTION_AT_ADDRESS(void CTrainWnd::SetGMData(int *,unsigned char *,float),CTrainWnd__SetGMData); +#endif +#ifdef CTrainWnd__Train_x +FUNCTION_AT_ADDRESS(void CTrainWnd::Train(void),CTrainWnd__Train); +#endif +#ifdef CVideoModesWnd__CVideoModesWnd_x +FUNCTION_AT_ADDRESS( CVideoModesWnd::CVideoModesWnd(class CXWnd *),CVideoModesWnd__CVideoModesWnd); +#endif +#ifdef CVideoModesWnd__Init_x +FUNCTION_AT_ADDRESS(void CVideoModesWnd::Init(void),CVideoModesWnd__Init); +#endif +#ifdef CVideoModesWnd__Update_x +FUNCTION_AT_ADDRESS(void CVideoModesWnd::Update(void),CVideoModesWnd__Update); +#endif +#ifdef CVideoModesWnd__UpdateSelection_x +FUNCTION_AT_ADDRESS(void CVideoModesWnd::UpdateSelection(unsigned int),CVideoModesWnd__UpdateSelection); +#endif +#ifdef CVideoModesWnd__RestoreOldMode_x +FUNCTION_AT_ADDRESS(void CVideoModesWnd::RestoreOldMode(void),CVideoModesWnd__RestoreOldMode); +#endif +#ifdef CGuild__CGuild_x +FUNCTION_AT_ADDRESS( CGuild::CGuild(void),CGuild__CGuild); +#endif +#ifdef CGuild__GetGuildName_x +FUNCTION_AT_ADDRESS(char * CGuild::GetGuildName(int),CGuild__GetGuildName); +#endif +#ifdef CGuild__ValidGuildName_x +FUNCTION_AT_ADDRESS(bool CGuild::ValidGuildName(int),CGuild__ValidGuildName); +#endif +#ifdef CGuild__GetGuildIndex_x +FUNCTION_AT_ADDRESS(int CGuild::GetGuildIndex(char *),CGuild__GetGuildIndex); +#endif +#ifdef CGuild__SendPublicCommentChange_x +FUNCTION_AT_ADDRESS(void CGuild::SendPublicCommentChange(char *,char *),CGuild__SendPublicCommentChange); +#endif +#ifdef CGuild__DemoteMember_x +FUNCTION_AT_ADDRESS(void CGuild::DemoteMember(class GuildMember *),CGuild__DemoteMember); +#endif +#ifdef CGuild__SetGuildMotd_x +FUNCTION_AT_ADDRESS(void CGuild::SetGuildMotd(struct guildmotdSet *),CGuild__SetGuildMotd); +#endif +#ifdef CGuild__HandleGuildMessage_x +FUNCTION_AT_ADDRESS(void CGuild::HandleGuildMessage(struct connection_t *,unsigned __int32,char *,unsigned __int32),CGuild__HandleGuildMessage); +#endif +#ifdef CGuild__InitializeFromDump_x +FUNCTION_AT_ADDRESS(void CGuild::InitializeFromDump(char *),CGuild__InitializeFromDump); +#endif +#ifdef CGuild__AddGuildMember_x +FUNCTION_AT_ADDRESS(void CGuild::AddGuildMember(class GuildMember *),CGuild__AddGuildMember); +#endif +#ifdef CGuild__DeleteAllMembers_x +FUNCTION_AT_ADDRESS(void CGuild::DeleteAllMembers(void),CGuild__DeleteAllMembers); +#endif +#ifdef CGuild__HandleGuildInvite_x +FUNCTION_AT_ADDRESS(void CGuild::HandleGuildInvite(struct connection_t *,unsigned __int32,char *,unsigned __int32),CGuild__HandleGuildInvite); +#endif +#ifdef CGuild__HandleAddGuildMember_x +FUNCTION_AT_ADDRESS(void CGuild::HandleAddGuildMember(char *,int),CGuild__HandleAddGuildMember); +#endif +#ifdef CGuild__HandleRemoveGuildMember_x +FUNCTION_AT_ADDRESS(void CGuild::HandleRemoveGuildMember(char *,int),CGuild__HandleRemoveGuildMember); +#endif +#ifdef CGuild__HandleDeleteGuildResponse_x +FUNCTION_AT_ADDRESS(void CGuild::HandleDeleteGuildResponse(char *),CGuild__HandleDeleteGuildResponse); +#endif +#ifdef CGuild__UpdatePublicComment_x +FUNCTION_AT_ADDRESS(void CGuild::UpdatePublicComment(char *),CGuild__UpdatePublicComment); +#endif +#ifdef CGuild__UpdateMemberStatus_x +FUNCTION_AT_ADDRESS(void CGuild::UpdateMemberStatus(char *),CGuild__UpdateMemberStatus); +#endif +#ifdef CGuild__HandleMemberLevelUpdate_x +FUNCTION_AT_ADDRESS(void CGuild::HandleMemberLevelUpdate(char *),CGuild__HandleMemberLevelUpdate); +#endif +#ifdef CGuild__UpdateGuildMemberOnWindow_x +FUNCTION_AT_ADDRESS(void CGuild::UpdateGuildMemberOnWindow(class GuildMember *),CGuild__UpdateGuildMemberOnWindow); +#endif +#ifdef CGuild__ChangeGuildMemberName_x +FUNCTION_AT_ADDRESS(void CGuild::ChangeGuildMemberName(char *),CGuild__ChangeGuildMemberName); +#endif +#ifdef CGuild__FindMemberByName_x +FUNCTION_AT_ADDRESS(class GuildMember * CGuild::FindMemberByName(char *),CGuild__FindMemberByName); +#endif +#ifdef GuildMember__GuildMember_x +FUNCTION_AT_ADDRESS( GuildMember::GuildMember(void),GuildMember__GuildMember); +#endif +#ifdef ChannelServerApi__ChannelServerApi_x +FUNCTION_AT_ADDRESS( ChannelServerApi::ChannelServerApi(char *,int,char *,char *,class ChannelServerHandler *,bool,bool,char *),ChannelServerApi__ChannelServerApi); +#endif +#ifdef ChannelServerApi__dChannelServerApi_x +FUNCTION_AT_ADDRESS( ChannelServerApi::~ChannelServerApi(void),ChannelServerApi__dChannelServerApi); +#endif +#ifdef ChannelServerApi__FreeChannelList_x +FUNCTION_AT_ADDRESS(void ChannelServerApi::FreeChannelList(void),ChannelServerApi__FreeChannelList); +#endif +#ifdef ChannelServerApi__GetStatus_x +//FUNCTION_AT_ADDRESS(enum ChannelServerApi::Status ChannelServerApi::GetStatus(void),ChannelServerApi__GetStatus); +#endif +#ifdef ChannelServerApi__SendMessageA_x +FUNCTION_AT_ADDRESS(void ChannelServerApi::SendMessageA(char *),ChannelServerApi__SendMessageA); +#endif +#ifdef ChannelServerApi__SortBuddyList_x +FUNCTION_AT_ADDRESS(void ChannelServerApi::SortBuddyList(void),ChannelServerApi__SortBuddyList); +#endif +#ifdef UdpManager__Release_x +FUNCTION_AT_ADDRESS(void UdpManager::Release(void),UdpManager__Release); +#endif +#ifdef ChannelServerApi__SetBuddyStatus_x +//FUNCTION_AT_ADDRESS(void ChannelServerApi::SetBuddyStatus(char *,enum ChannelServerApi::BuddyStatus),ChannelServerApi__SetBuddyStatus); +#endif +#ifdef UdpConnection__Release_x +FUNCTION_AT_ADDRESS(void UdpConnection::Release(void),UdpConnection__Release); +#endif +#ifdef ChannelServerApi__GiveTime_x +FUNCTION_AT_ADDRESS(void ChannelServerApi::GiveTime(void),ChannelServerApi__GiveTime); +#endif +#ifdef ChannelServerApi__GetChannelNumber_x +FUNCTION_AT_ADDRESS(int ChannelServerApi::GetChannelNumber(char *),ChannelServerApi__GetChannelNumber); +#endif +#ifdef ChannelServerApi__GetChannelName_x +FUNCTION_AT_ADDRESS(char * ChannelServerApi::GetChannelName(int),ChannelServerApi__GetChannelName); +#endif +#ifdef ChannelServerApi__Strncpy_x +FUNCTION_AT_ADDRESS(char * __cdecl ChannelServerApi::Strncpy(char *,char *,int),ChannelServerApi__Strncpy); +#endif +#ifdef ChannelServerApi__SmartResize_x +FUNCTION_AT_ADDRESS(void * __cdecl ChannelServerApi::SmartResize(void *,int,int),ChannelServerApi__SmartResize); +#endif +#ifdef ChannelServerApi__GetNextField_x +FUNCTION_AT_ADDRESS(int __cdecl ChannelServerApi::GetNextField(char *,int,char * *,char),ChannelServerApi__GetNextField); +#endif +#ifdef JournalNPC__JournalNPC_x +FUNCTION_AT_ADDRESS( JournalNPC::JournalNPC(void),JournalNPC__JournalNPC); +#endif +#ifdef JournalNPC__dJournalNPC_x +FUNCTION_AT_ADDRESS( JournalNPC::~JournalNPC(void),JournalNPC__dJournalNPC); +#endif +#ifdef JournalNPC__AllocateArray_x +FUNCTION_AT_ADDRESS(void JournalNPC::AllocateArray(void),JournalNPC__AllocateArray); +#endif +#ifdef JournalNPC__CleanEntries_x +FUNCTION_AT_ADDRESS(void JournalNPC::CleanEntries(void),JournalNPC__CleanEntries); +#endif +#ifdef JournalNPC__GetText_x +FUNCTION_AT_ADDRESS(char * __cdecl JournalNPC::GetText(int),JournalNPC__GetText); +#endif +#ifdef JournalNPC__GetEntry_x +FUNCTION_AT_ADDRESS(struct JournalEntry * JournalNPC::GetEntry(int),JournalNPC__GetEntry); +#endif +#ifdef JournalNPC__FindEntryByHash_x +FUNCTION_AT_ADDRESS(struct JournalEntry * JournalNPC::FindEntryByHash(int),JournalNPC__FindEntryByHash); +#endif +#ifdef JournalNPC__FindEntryByCategory_x +FUNCTION_AT_ADDRESS(struct JournalEntry * JournalNPC::FindEntryByCategory(int,int),JournalNPC__FindEntryByCategory); +#endif +#ifdef JournalNPC__FindThisText_x +FUNCTION_AT_ADDRESS(int JournalNPC::FindThisText(char *,bool,int),JournalNPC__FindThisText); +#endif +#ifdef JournalNPC__AddEntry_x +FUNCTION_AT_ADDRESS(int JournalNPC::AddEntry(long,float,float,float,int,int),JournalNPC__AddEntry); +#endif +#ifdef JournalNPC__AddEntry1_x +FUNCTION_AT_ADDRESS(int JournalNPC::AddEntry(long,float,float,float,char *,int),JournalNPC__AddEntry1); +#endif +#ifdef JournalNPC__DeleteEntryByIndex_x +FUNCTION_AT_ADDRESS(int JournalNPC::DeleteEntryByIndex(int),JournalNPC__DeleteEntryByIndex); +#endif +#ifdef JournalNPC__DeleteEntryByHash_x +FUNCTION_AT_ADDRESS(int JournalNPC::DeleteEntryByHash(int),JournalNPC__DeleteEntryByHash); +#endif +#ifdef JournalNPC__ConvertCategory_x +FUNCTION_AT_ADDRESS(void JournalNPC::ConvertCategory(int,int),JournalNPC__ConvertCategory); +#endif +#ifdef JournalNPC__ComputeLatestTime_x +FUNCTION_AT_ADDRESS(void JournalNPC::ComputeLatestTime(void),JournalNPC__ComputeLatestTime); +#endif +#ifdef ConversationJournal__ConversationJournal_x +FUNCTION_AT_ADDRESS( ConversationJournal::ConversationJournal(void),ConversationJournal__ConversationJournal); +#endif +#ifdef ConversationJournal__dConversationJournal_x +FUNCTION_AT_ADDRESS( ConversationJournal::~ConversationJournal(void),ConversationJournal__dConversationJournal); +#endif +#ifdef ConversationJournal__Clean_x +FUNCTION_AT_ADDRESS(void ConversationJournal::Clean(void),ConversationJournal__Clean); +#endif +#ifdef ConversationJournal__AllocateNPCArray_x +FUNCTION_AT_ADDRESS(void ConversationJournal::AllocateNPCArray(void),ConversationJournal__AllocateNPCArray); +#endif +#ifdef ConversationJournal__AllocateCatArray_x +FUNCTION_AT_ADDRESS(void ConversationJournal::AllocateCatArray(void),ConversationJournal__AllocateCatArray); +#endif +#ifdef ConversationJournal__GetNPC_x +FUNCTION_AT_ADDRESS(class JournalNPC * ConversationJournal::GetNPC(int),ConversationJournal__GetNPC); +#endif +#ifdef ConversationJournal__FindNPCByNameZone_x +FUNCTION_AT_ADDRESS(class JournalNPC * ConversationJournal::FindNPCByNameZone(char *,int),ConversationJournal__FindNPCByNameZone); +#endif +#ifdef ConversationJournal__DeleteNPC_x +FUNCTION_AT_ADDRESS(int ConversationJournal::DeleteNPC(char *,int),ConversationJournal__DeleteNPC); +#endif +#ifdef ConversationJournal__AddNPC_x +FUNCTION_AT_ADDRESS(class JournalNPC * ConversationJournal::AddNPC(char *,int),ConversationJournal__AddNPC); +#endif +#ifdef ConversationJournal__AddEntry_x +FUNCTION_AT_ADDRESS(int ConversationJournal::AddEntry(char *,int,long,float,float,float,char *,int),ConversationJournal__AddEntry); +#endif +#ifdef ConversationJournal__AddCategory_x +FUNCTION_AT_ADDRESS(struct JournalCategory * ConversationJournal::AddCategory(int),ConversationJournal__AddCategory); +#endif +#ifdef ConversationJournal__FindFreeID_x +FUNCTION_AT_ADDRESS(int ConversationJournal::FindFreeID(void),ConversationJournal__FindFreeID); +#endif +#ifdef ConversationJournal__AddCategory1_x +FUNCTION_AT_ADDRESS(struct JournalCategory * ConversationJournal::AddCategory(char *,char *,int),ConversationJournal__AddCategory1); +#endif +#ifdef ConversationJournal__DeleteCategory_x +FUNCTION_AT_ADDRESS(void ConversationJournal::DeleteCategory(int),ConversationJournal__DeleteCategory); +#endif +#ifdef ConversationJournal__GetCategory_x +FUNCTION_AT_ADDRESS(struct JournalCategory * ConversationJournal::GetCategory(int),ConversationJournal__GetCategory); +#endif +#ifdef ConversationJournal__GetCategory1_x +FUNCTION_AT_ADDRESS(struct JournalCategory * ConversationJournal::GetCategory(char *),ConversationJournal__GetCategory1); +#endif +#ifdef ConversationJournal__GetCategoryList_x +FUNCTION_AT_ADDRESS(struct JournalCategory * * ConversationJournal::GetCategoryList(void),ConversationJournal__GetCategoryList); +#endif +#ifdef ConversationJournal__Save_x +FUNCTION_AT_ADDRESS(int ConversationJournal::Save(char *),ConversationJournal__Save); +#endif +#ifdef ConversationJournal__Load_x +FUNCTION_AT_ADDRESS(int ConversationJournal::Load(char *),ConversationJournal__Load); +#endif +#ifdef ConversationJournal__ReadCategory_x +FUNCTION_AT_ADDRESS(void ConversationJournal::ReadCategory(struct _iobuf *),ConversationJournal__ReadCategory); +#endif +#ifdef JournalNPC__ReadEntry_x +FUNCTION_AT_ADDRESS(int JournalNPC::ReadEntry(struct _iobuf *),JournalNPC__ReadEntry); +#endif +#ifdef ConversationJournal__ReadNPC_x +FUNCTION_AT_ADDRESS(class JournalNPC * ConversationJournal::ReadNPC(struct _iobuf *),ConversationJournal__ReadNPC); +#endif +#ifdef CRaid__CRaid_x +FUNCTION_AT_ADDRESS( CRaid::CRaid(void),CRaid__CRaid); +#endif +#ifdef CRaid__HandleS2CRaidMessage_x +FUNCTION_AT_ADDRESS(void CRaid::HandleS2CRaidMessage(char *),CRaid__HandleS2CRaidMessage); +#endif +#ifdef CRaid__HandleC2SRaidMessage_x +FUNCTION_AT_ADDRESS(void CRaid::HandleC2SRaidMessage(char *),CRaid__HandleC2SRaidMessage); +#endif +#ifdef CRaid__IsInRaid_x +FUNCTION_AT_ADDRESS(bool CRaid::IsInRaid(void),CRaid__IsInRaid); +#endif +#ifdef CRaid__IsInvited_x +FUNCTION_AT_ADDRESS(bool CRaid::IsInvited(void),CRaid__IsInvited); +#endif +#ifdef CRaid__ClearInvitedState_x +FUNCTION_AT_ADDRESS(void CRaid::ClearInvitedState(void),CRaid__ClearInvitedState); +#endif +#ifdef CRaid__IsRaidLeader_x +FUNCTION_AT_ADDRESS(bool CRaid::IsRaidLeader(void),CRaid__IsRaidLeader); +#endif +#ifdef CRaid__IsRaidGroupLeader_x +FUNCTION_AT_ADDRESS(bool CRaid::IsRaidGroupLeader(void),CRaid__IsRaidGroupLeader); +#endif +#ifdef CRaid__SetTargetRaidPlayer_x +FUNCTION_AT_ADDRESS(void CRaid::SetTargetRaidPlayer(char *),CRaid__SetTargetRaidPlayer); +#endif +#ifdef CRaid__InitializeRaid_x +FUNCTION_AT_ADDRESS(void CRaid::InitializeRaid(char *),CRaid__InitializeRaid); +#endif +#ifdef CRaid__RaidCreated_x +FUNCTION_AT_ADDRESS(void CRaid::RaidCreated(struct CreateRaidMessage *),CRaid__RaidCreated); +#endif +#ifdef CRaid__AddRaidMember_x +FUNCTION_AT_ADDRESS(void CRaid::AddRaidMember(struct RaidAddMember *),CRaid__AddRaidMember); +#endif +#ifdef CRaid__DeleteRaidMember_x +FUNCTION_AT_ADDRESS(void CRaid::DeleteRaidMember(struct SCRaidMessage *),CRaid__DeleteRaidMember); +#endif +#ifdef CRaid__ChangeLeadership_x +FUNCTION_AT_ADDRESS(void CRaid::ChangeLeadership(char *),CRaid__ChangeLeadership); +#endif +#ifdef CRaid__RenameMember_x +FUNCTION_AT_ADDRESS(void CRaid::RenameMember(struct RenameRaidMember *),CRaid__RenameMember); +#endif +#ifdef CRaid__HandlePositionChange_x +FUNCTION_AT_ADDRESS(void CRaid::HandlePositionChange(struct SCRaidMessage *),CRaid__HandlePositionChange); +#endif +#ifdef CRaid__RaidGroupLeaderChange_x +FUNCTION_AT_ADDRESS(void CRaid::RaidGroupLeaderChange(struct SCRaidMessage *),CRaid__RaidGroupLeaderChange); +#endif +#ifdef CRaid__SetLootTypeResponse_x +FUNCTION_AT_ADDRESS(void CRaid::SetLootTypeResponse(struct SCRaidMessage *),CRaid__SetLootTypeResponse); +#endif +#ifdef CRaid__HandleSetLootType_x +FUNCTION_AT_ADDRESS(void CRaid::HandleSetLootType(int),CRaid__HandleSetLootType); +#endif +#ifdef CRaid__HandleAddLooter_x +FUNCTION_AT_ADDRESS(void CRaid::HandleAddLooter(char *),CRaid__HandleAddLooter); +#endif +#ifdef UdpMisc__GetValue32_x +FUNCTION_AT_ADDRESS(unsigned int __cdecl UdpMisc::GetValue32(void const *),UdpMisc__GetValue32); +#endif +#ifdef Util__GetValue32_x +//FUNCTION_AT_ADDRESS(unsigned int __cdecl Util::GetValue32(void const *),Util__GetValue32); +#endif +#ifdef CRaid__HandleRemoveLooter_x +FUNCTION_AT_ADDRESS(void CRaid::HandleRemoveLooter(char *),CRaid__HandleRemoveLooter); +#endif +#ifdef CRaid__CreateInviteRaid_x +FUNCTION_AT_ADDRESS(void CRaid::CreateInviteRaid(void),CRaid__CreateInviteRaid); +#endif +#ifdef CRaid__SendInviteResponse_x +FUNCTION_AT_ADDRESS(void CRaid::SendInviteResponse(bool),CRaid__SendInviteResponse); +#endif +#ifdef CRaid__SendLeadershipChange_x +FUNCTION_AT_ADDRESS(void CRaid::SendLeadershipChange(char *),CRaid__SendLeadershipChange); +#endif +#ifdef CRaid__RemoveRaidMember_x +FUNCTION_AT_ADDRESS(void CRaid::RemoveRaidMember(void),CRaid__RemoveRaidMember); +#endif +#ifdef CRaid__SetLootType_x +FUNCTION_AT_ADDRESS(void CRaid::SetLootType(char *),CRaid__SetLootType); +#endif +#ifdef CRaid__GetLootType_x +FUNCTION_AT_ADDRESS(int CRaid::GetLootType(void),CRaid__GetLootType); +#endif +#ifdef CRaid__AddRaidLooter_x +FUNCTION_AT_ADDRESS(void CRaid::AddRaidLooter(void),CRaid__AddRaidLooter); +#endif +#ifdef CRaid__RemoveRaidLooter_x +FUNCTION_AT_ADDRESS(void CRaid::RemoveRaidLooter(void),CRaid__RemoveRaidLooter); +#endif +#ifdef CRaid__SendRaidChat_x +FUNCTION_AT_ADDRESS(void CRaid::SendRaidChat(char *),CRaid__SendRaidChat); +#endif +#ifdef CRaid__ResetWindow_x +FUNCTION_AT_ADDRESS(void CRaid::ResetWindow(void),CRaid__ResetWindow); +#endif +#ifdef CRaid__UpdateClassColor_x +FUNCTION_AT_ADDRESS(void CRaid::UpdateClassColor(int,unsigned long),CRaid__UpdateClassColor); +#endif +#ifdef CRaid__HandleCreateInviteRaid_x +FUNCTION_AT_ADDRESS(void CRaid::HandleCreateInviteRaid(struct CSRaidMessage *),CRaid__HandleCreateInviteRaid); +#endif +#ifdef CRaid__GetNumRaidMembers_x +FUNCTION_AT_ADDRESS(int CRaid::GetNumRaidMembers(void),CRaid__GetNumRaidMembers); +#endif +#ifdef CRaid__GetRaidMemberAt_x +FUNCTION_AT_ADDRESS(struct RaidMember * CRaid::GetRaidMemberAt(int),CRaid__GetRaidMemberAt); +#endif +#ifdef CRaid__SetRaidLeader_x +FUNCTION_AT_ADDRESS(void CRaid::SetRaidLeader(char *),CRaid__SetRaidLeader); +#endif +#ifdef CRaid__FindPlayerIndex_x +FUNCTION_AT_ADDRESS(int CRaid::FindPlayerIndex(char *),CRaid__FindPlayerIndex); +#endif +#ifdef CRaid__IsRaidMember_x +FUNCTION_AT_ADDRESS(bool CRaid::IsRaidMember(char *),CRaid__IsRaidMember); +#endif +#ifdef CRaid__FindOpenIndex_x +FUNCTION_AT_ADDRESS(int CRaid::FindOpenIndex(void),CRaid__FindOpenIndex); +#endif +#ifdef CRaid__FindRaidGroupLeader_x +FUNCTION_AT_ADDRESS(int CRaid::FindRaidGroupLeader(int),CRaid__FindRaidGroupLeader); +#endif +#ifdef CRaid__ResetRaid_x +FUNCTION_AT_ADDRESS(void CRaid::ResetRaid(void),CRaid__ResetRaid); +#endif +#ifdef CRaid__DetermineRaidChanges_x +FUNCTION_AT_ADDRESS(void CRaid::DetermineRaidChanges(char *),CRaid__DetermineRaidChanges); +#endif +#ifdef CRaid__SendRaidMsg_x +FUNCTION_AT_ADDRESS(void CRaid::SendRaidMsg(int,char *,char *,int),CRaid__SendRaidMsg); +#endif +#ifdef CRaid__UpdateOptionsWindow_x +FUNCTION_AT_ADDRESS(void CRaid::UpdateOptionsWindow(void),CRaid__UpdateOptionsWindow); +#endif +#ifdef CRaid__IsRaidLooter_x +FUNCTION_AT_ADDRESS(bool CRaid::IsRaidLooter(char *),CRaid__IsRaidLooter); +#endif +#ifdef CRaid__UpdateLevelAverage_x +FUNCTION_AT_ADDRESS(void CRaid::UpdateLevelAverage(void),CRaid__UpdateLevelAverage); +#endif +#ifdef CDisplay__CDisplay_x +FUNCTION_AT_ADDRESS( CDisplay::CDisplay(struct HWND__ *),CDisplay__CDisplay); +#endif +#ifdef CDisplay__dCDisplay_x +FUNCTION_AT_ADDRESS( CDisplay::~CDisplay(void),CDisplay__dCDisplay); +#endif +#ifdef CDisplay__ResetRenderWindow_x +FUNCTION_AT_ADDRESS(void CDisplay::ResetRenderWindow(void),CDisplay__ResetRenderWindow); +#endif +#ifdef CDisplay__SetCCreateCamera_x +FUNCTION_AT_ADDRESS(void CDisplay::SetCCreateCamera(int),CDisplay__SetCCreateCamera); +#endif +#ifdef CDisplay__SetBoneSpriteTint_x +FUNCTION_AT_ADDRESS(int CDisplay::SetBoneSpriteTint(struct T3D_DAG *,struct T3D_RGB *),CDisplay__SetBoneSpriteTint); +#endif +#ifdef CDisplay__ReplaceMaterial_x +FUNCTION_AT_ADDRESS(int CDisplay::ReplaceMaterial(char *,char *,struct T3D_HIERARCHICALSPRITEINSTANCE *,struct T3D_RGB *,int),CDisplay__ReplaceMaterial); +#endif +#ifdef CDisplay__ReplaceCloakMaterials_x +FUNCTION_AT_ADDRESS(int CDisplay::ReplaceCloakMaterials(int,struct T3D_HIERARCHICALSPRITEINSTANCE *,struct T3D_RGB *),CDisplay__ReplaceCloakMaterials); +#endif +#ifdef CDisplay__InitEverQuestLocale_x +//FUNCTION_AT_ADDRESS(void CDisplay::InitEverQuestLocale(enum EQLocalize::languages),CDisplay__InitEverQuestLocale); +#endif +#ifdef CDisplay__ReloadUI_x +FUNCTION_AT_ADDRESS(void CDisplay::ReloadUI(bool),CDisplay__ReloadUI); +#endif +#ifdef CDisplay__HandleMaterial_x +FUNCTION_AT_ADDRESS(void CDisplay::HandleMaterial(class EQ_PC *,int,class EQ_Item *,class EQ_Item *),CDisplay__HandleMaterial); +#endif +#ifdef CDisplay__FixHeading_x +FUNCTION_AT_ADDRESS(float CDisplay::FixHeading(float),CDisplay__FixHeading); +#endif +#ifdef CDisplay__HeadingDiff_x +FUNCTION_AT_ADDRESS(float CDisplay::HeadingDiff(float,float,float *),CDisplay__HeadingDiff); +#endif +#ifdef CDisplay__DeleteParticleCloudInstance_x +FUNCTION_AT_ADDRESS(void CDisplay::DeleteParticleCloudInstance(struct T3D_PARTICLECLOUDINSTANCE * *),CDisplay__DeleteParticleCloudInstance); +#endif +#ifdef CDisplay__ProcessParticleEmitter_x +FUNCTION_AT_ADDRESS(void CDisplay::ProcessParticleEmitter(class EQSwitch *),CDisplay__ProcessParticleEmitter); +#endif +#ifdef CDisplay__SlideSwitchLeftRight_x +FUNCTION_AT_ADDRESS(bool CDisplay::SlideSwitchLeftRight(class EQSwitch *,float,int,float),CDisplay__SlideSwitchLeftRight); +#endif +#ifdef CDisplay__ProcessSwitches_x +FUNCTION_AT_ADDRESS(void CDisplay::ProcessSwitches(void),CDisplay__ProcessSwitches); +#endif +#ifdef CDisplay__default_cameras_x +FUNCTION_AT_ADDRESS(void CDisplay::default_cameras(void),CDisplay__default_cameras); +#endif +#ifdef CDisplay__is_3dON_x +FUNCTION_AT_ADDRESS(int CDisplay::is_3dON(void),CDisplay__is_3dON); +#endif +#ifdef CDisplay__is_ParticleSystemON_x +FUNCTION_AT_ADDRESS(int CDisplay::is_ParticleSystemON(void),CDisplay__is_ParticleSystemON); +#endif +#ifdef CDisplay__InitCommonLights_x +FUNCTION_AT_ADDRESS(void CDisplay::InitCommonLights(void),CDisplay__InitCommonLights); +#endif +#ifdef CDisplay__GetNewPCIniFlag_x +FUNCTION_AT_ADDRESS(int CDisplay::GetNewPCIniFlag(int,int),CDisplay__GetNewPCIniFlag); +#endif +#ifdef CDisplay__ShouldLoadNewPcModel_x +FUNCTION_AT_ADDRESS(int CDisplay::ShouldLoadNewPcModel(int,int),CDisplay__ShouldLoadNewPcModel); +#endif +#ifdef CDisplay__GetIniRaceName_x +FUNCTION_AT_ADDRESS(char * CDisplay::GetIniRaceName(int),CDisplay__GetIniRaceName); +#endif +#ifdef CDisplay__InitWorld_x +FUNCTION_AT_ADDRESS(void CDisplay::InitWorld(void),CDisplay__InitWorld); +#endif +#ifdef CDisplay__InitDDraw_x +FUNCTION_AT_ADDRESS(void CDisplay::InitDDraw(void),CDisplay__InitDDraw); +#endif +#ifdef CDisplay__InitNewUI_x +FUNCTION_AT_ADDRESS(void CDisplay::InitNewUI(void),CDisplay__InitNewUI); +#endif +#ifdef CXWndDrawTemplate__operator_equal_x +FUNCTION_AT_ADDRESS(class CXWndDrawTemplate & CXWndDrawTemplate::operator=(class CXWndDrawTemplate const &),CXWndDrawTemplate__operator_equal); +#endif +#ifdef CButtonDrawTemplate__operator_equal_x +FUNCTION_AT_ADDRESS(class CButtonDrawTemplate & CButtonDrawTemplate::operator=(class CButtonDrawTemplate const &),CButtonDrawTemplate__operator_equal); +#endif +#ifdef CScrollbarTemplate__operator_equal_x +FUNCTION_AT_ADDRESS(class CScrollbarTemplate & CScrollbarTemplate::operator=(class CScrollbarTemplate const &),CScrollbarTemplate__operator_equal); +#endif +#ifdef CTAFrameDraw__operator_equal_x +FUNCTION_AT_ADDRESS(class CTAFrameDraw & CTAFrameDraw::operator=(class CTAFrameDraw const &),CTAFrameDraw__operator_equal); +#endif +#ifdef CDisplay__InitCharSelectUI_x +FUNCTION_AT_ADDRESS(void CDisplay::InitCharSelectUI(void),CDisplay__InitCharSelectUI); +#endif +#ifdef CDisplay__InitGameUI_x +FUNCTION_AT_ADDRESS(void CDisplay::InitGameUI(void),CDisplay__InitGameUI); +#endif +#ifdef CDisplay__CleanCharSelectUI_x +FUNCTION_AT_ADDRESS(void CDisplay::CleanCharSelectUI(void),CDisplay__CleanCharSelectUI); +#endif +#ifdef CDisplay__CleanGameUI_x +FUNCTION_AT_ADDRESS(void CDisplay::CleanGameUI(void),CDisplay__CleanGameUI); +#endif +#ifdef CDisplay__CleanUpNewUI_x +FUNCTION_AT_ADDRESS(void CDisplay::CleanUpNewUI(void),CDisplay__CleanUpNewUI); +#endif +#ifdef CDisplay__ActivateMainUI_x +FUNCTION_AT_ADDRESS(void CDisplay::ActivateMainUI(bool),CDisplay__ActivateMainUI); +#endif +#ifdef CDisplay__DeactivateMainUI_x +FUNCTION_AT_ADDRESS(void CDisplay::DeactivateMainUI(void),CDisplay__DeactivateMainUI); +#endif +#ifdef CDisplay__NewUIProcessEscape_x +FUNCTION_AT_ADDRESS(void CDisplay::NewUIProcessEscape(void),CDisplay__NewUIProcessEscape); +#endif +#ifdef CDisplay__KeyMapUpdated_x +FUNCTION_AT_ADDRESS(void CDisplay::KeyMapUpdated(void),CDisplay__KeyMapUpdated); +#endif +#ifdef CDisplay__GetWorldFilePath_x +FUNCTION_AT_ADDRESS(bool const CDisplay::GetWorldFilePath(char *,char const *),CDisplay__GetWorldFilePath); +#endif +#ifdef CDisplay__LoadWorldFile_x +FUNCTION_AT_ADDRESS(unsigned char CDisplay::LoadWorldFile(char *,char *,int,unsigned char),CDisplay__LoadWorldFile); +#endif +#ifdef CDisplay__LoadNPCFromS3D_x +FUNCTION_AT_ADDRESS(unsigned char CDisplay::LoadNPCFromS3D(char *,char *,char *),CDisplay__LoadNPCFromS3D); +#endif +#ifdef CDisplay__LoadBMPFile_x +FUNCTION_AT_ADDRESS(unsigned char CDisplay::LoadBMPFile(void),CDisplay__LoadBMPFile); +#endif +#ifdef CDisplay__StartWorldDisplay_x +//FUNCTION_AT_ADDRESS(void CDisplay::StartWorldDisplay(enum EQZoneIndex),CDisplay__StartWorldDisplay); +#endif +#ifdef CDisplay__StartWorldDisplay_Bailout_x +FUNCTION_AT_ADDRESS(void CDisplay::StartWorldDisplay_Bailout(char const *),CDisplay__StartWorldDisplay_Bailout); +#endif +#ifdef CDisplay__StopWorldDisplay_x +FUNCTION_AT_ADDRESS(void CDisplay::StopWorldDisplay(void),CDisplay__StopWorldDisplay); +#endif +#ifdef CDisplay__SetGammaCorrection_x +FUNCTION_AT_ADDRESS(void CDisplay::SetGammaCorrection(float),CDisplay__SetGammaCorrection); +#endif +#ifdef CDisplay__SetPCloudDensity_x +FUNCTION_AT_ADDRESS(void CDisplay::SetPCloudDensity(int),CDisplay__SetPCloudDensity); +#endif +#ifdef CDisplay__CleanUpDDraw_x +FUNCTION_AT_ADDRESS(void CDisplay::CleanUpDDraw(void),CDisplay__CleanUpDDraw); +#endif +#ifdef CDisplay__IsShield_x +FUNCTION_AT_ADDRESS(unsigned int CDisplay::IsShield(int)const ,CDisplay__IsShield); +#endif +#ifdef CDisplay__GetItemType_x +FUNCTION_AT_ADDRESS(int CDisplay::GetItemType(int),CDisplay__GetItemType); +#endif +#ifdef CDisplay__GetUserDefinedColor_x +FUNCTION_AT_ADDRESS(unsigned long __cdecl CDisplay::GetUserDefinedColor(int),CDisplay__GetUserDefinedColor); +#endif +#ifdef CDisplay__SetUserDefinedColor_x +FUNCTION_AT_ADDRESS(void __cdecl CDisplay::SetUserDefinedColor(int,int,int,int),CDisplay__SetUserDefinedColor); +#endif +#ifdef CDisplay__InitUserDefinedColors_x +FUNCTION_AT_ADDRESS(void CDisplay::InitUserDefinedColors(void),CDisplay__InitUserDefinedColors); +#endif +#ifdef CDisplay__WriteTextHD2_x +FUNCTION_AT_ADDRESS(int __cdecl CDisplay::WriteTextHD2(char const *,int,int,int),CDisplay__WriteTextHD2); +#endif +#ifdef CXWndManager__GetDisplayWidth_x +FUNCTION_AT_ADDRESS(unsigned __int32 CXWndManager::GetDisplayWidth(void)const ,CXWndManager__GetDisplayWidth); +#endif +#ifdef CXWndManager__GetFont_x +FUNCTION_AT_ADDRESS(class CTextureFont * CXWndManager::GetFont(int)const ,CXWndManager__GetFont); +#endif +#ifdef CDisplay__SetActorScaleFactor_x +FUNCTION_AT_ADDRESS(void CDisplay::SetActorScaleFactor(struct T3D_tagACTORINSTANCE *,float,unsigned char),CDisplay__SetActorScaleFactor); +#endif +#ifdef CDisplay__ShowDisplay_x +FUNCTION_AT_ADDRESS(void CDisplay::ShowDisplay(void),CDisplay__ShowDisplay); +#endif +#ifdef CDisplay__CheckForScreenModeToggle_x +FUNCTION_AT_ADDRESS(void CDisplay::CheckForScreenModeToggle(void),CDisplay__CheckForScreenModeToggle); +#endif +#ifdef CDisplay__Render_World_x +FUNCTION_AT_ADDRESS(void CDisplay::Render_World(void),CDisplay__Render_World); +#endif +#ifdef CDisplay__SetSpecialEnvironment_x +//FUNCTION_AT_ADDRESS(void CDisplay::SetSpecialEnvironment(enum EnvironmentType),CDisplay__SetSpecialEnvironment); +#endif +#ifdef CDisplay__SetGenericEnvironment_x +FUNCTION_AT_ADDRESS(void CDisplay::SetGenericEnvironment(void),CDisplay__SetGenericEnvironment); +#endif +#ifdef CDisplay__SetupEmitterEnvironment_x +FUNCTION_AT_ADDRESS(void CDisplay::SetupEmitterEnvironment(void),CDisplay__SetupEmitterEnvironment); +#endif +#ifdef CDisplay__UpdateMobileEmitterLocations_x +FUNCTION_AT_ADDRESS(void CDisplay::UpdateMobileEmitterLocations(void),CDisplay__UpdateMobileEmitterLocations); +#endif +#ifdef CDisplay__RealRender_World_x +FUNCTION_AT_ADDRESS(void CDisplay::RealRender_World(void),CDisplay__RealRender_World); +#endif +#ifdef CDisplay__Render_MinWorld_x +FUNCTION_AT_ADDRESS(void CDisplay::Render_MinWorld(void),CDisplay__Render_MinWorld); +#endif +#ifdef CDisplay__StartWeather_x +FUNCTION_AT_ADDRESS(void CDisplay::StartWeather(int,unsigned char),CDisplay__StartWeather); +#endif +#ifdef CDisplay__ProcessWeather_x +FUNCTION_AT_ADDRESS(void CDisplay::ProcessWeather(void),CDisplay__ProcessWeather); +#endif +#ifdef CDisplay__StopWeather_x +FUNCTION_AT_ADDRESS(void CDisplay::StopWeather(int,unsigned char),CDisplay__StopWeather); +#endif +#ifdef CDisplay__LightningStrike_x +FUNCTION_AT_ADDRESS(void CDisplay::LightningStrike(void),CDisplay__LightningStrike); +#endif +#ifdef CDisplay__GetNearestPlayerInView_x +FUNCTION_AT_ADDRESS(class EQPlayer * CDisplay::GetNearestPlayerInView(float,bool),CDisplay__GetNearestPlayerInView); +#endif +#ifdef CDisplay__ProcessEffects_x +FUNCTION_AT_ADDRESS(void CDisplay::ProcessEffects(void),CDisplay__ProcessEffects); +#endif +#ifdef CDisplay__ProcessCloud_x +FUNCTION_AT_ADDRESS(void CDisplay::ProcessCloud(void),CDisplay__ProcessCloud); +#endif +#ifdef CDisplay__DDrawUpdateDisplay_x +FUNCTION_AT_ADDRESS(void CDisplay::DDrawUpdateDisplay(void),CDisplay__DDrawUpdateDisplay); +#endif +#ifdef CDisplay__SetViewActor_x +FUNCTION_AT_ADDRESS(void CDisplay::SetViewActor(struct T3D_tagACTORINSTANCE *),CDisplay__SetViewActor); +#endif +#ifdef CDisplay__SwitchToDefaultCameraMode_x +FUNCTION_AT_ADDRESS(void CDisplay::SwitchToDefaultCameraMode(void),CDisplay__SwitchToDefaultCameraMode); +#endif +#ifdef CDisplay__SetYon_x +FUNCTION_AT_ADDRESS(void CDisplay::SetYon(float),CDisplay__SetYon); +#endif +#ifdef CDisplay__SetActorYon_x +FUNCTION_AT_ADDRESS(void CDisplay::SetActorYon(float),CDisplay__SetActorYon); +#endif +#ifdef CDisplay__SetViewAngle_x +FUNCTION_AT_ADDRESS(void CDisplay::SetViewAngle(int),CDisplay__SetViewAngle); +#endif +#ifdef CDisplay__UpdateCameraAfterModeSwitch_x +FUNCTION_AT_ADDRESS(void CDisplay::UpdateCameraAfterModeSwitch(void),CDisplay__UpdateCameraAfterModeSwitch); +#endif +#ifdef CDisplay__ChangeVideoMode_x +FUNCTION_AT_ADDRESS(void CDisplay::ChangeVideoMode(void),CDisplay__ChangeVideoMode); +#endif +#ifdef CDisplay__ToggleView_x +FUNCTION_AT_ADDRESS(void CDisplay::ToggleView(void),CDisplay__ToggleView); +#endif +#ifdef CDisplay__SetFog_x +FUNCTION_AT_ADDRESS(void CDisplay::SetFog(bool,float,float,unsigned char,unsigned char,unsigned char),CDisplay__SetFog); +#endif +#ifdef CDisplay__ClearScreen_x +FUNCTION_AT_ADDRESS(void CDisplay::ClearScreen(void),CDisplay__ClearScreen); +#endif +#ifdef CDisplay__CreatePlayerActor_x +FUNCTION_AT_ADDRESS(void CDisplay::CreatePlayerActor(class EQPlayer *),CDisplay__CreatePlayerActor); +#endif +#ifdef CDisplay__SetActorUserData_x +FUNCTION_AT_ADDRESS(void CDisplay::SetActorUserData(struct T3D_tagACTORINSTANCE *,void *),CDisplay__SetActorUserData); +#endif +#ifdef CDisplay__CreateLight_x +FUNCTION_AT_ADDRESS(struct T3D_POINTLIGHT * CDisplay::CreateLight(unsigned char,float,float,float,float),CDisplay__CreateLight); +#endif +#ifdef CDisplay__GetIntensity_x +FUNCTION_AT_ADDRESS(unsigned char CDisplay::GetIntensity(unsigned char),CDisplay__GetIntensity); +#endif +#ifdef CDisplay__DeleteLight_x +FUNCTION_AT_ADDRESS(void CDisplay::DeleteLight(struct T3D_POINTLIGHT *),CDisplay__DeleteLight); +#endif +#ifdef CDisplay__PlaySoundAtLocation_x +FUNCTION_AT_ADDRESS(void CDisplay::PlaySoundAtLocation(float,float,float,int),CDisplay__PlaySoundAtLocation); +#endif +#ifdef CDisplay__SetUserRender_x +FUNCTION_AT_ADDRESS(long CDisplay::SetUserRender(int),CDisplay__SetUserRender); +#endif +#ifdef CDisplay__GetClickedActor_x +FUNCTION_AT_ADDRESS(struct T3D_tagACTORINSTANCE * CDisplay::GetClickedActor(unsigned long,unsigned long,unsigned long,void *,void *),CDisplay__GetClickedActor); +#endif +#ifdef CDisplay__CreateActor_x +FUNCTION_AT_ADDRESS(struct T3D_tagACTORINSTANCE * CDisplay::CreateActor(char *,float,float,float,float,float,float,bool,bool),CDisplay__CreateActor); +#endif +#ifdef CDisplay__SetActorBoundingRadius_x +FUNCTION_AT_ADDRESS(float CDisplay::SetActorBoundingRadius(struct T3D_tagACTORINSTANCE *,float,float),CDisplay__SetActorBoundingRadius); +#endif +#ifdef CDisplay__DeleteActor_x +FUNCTION_AT_ADDRESS(void CDisplay::DeleteActor(struct T3D_tagACTORINSTANCE *),CDisplay__DeleteActor); +#endif +#ifdef CDisplay__dupActorHierarchicalSprite_x +FUNCTION_AT_ADDRESS(struct T3D_HIERARCHICALSPRITEINSTANCE * CDisplay::dupActorHierarchicalSprite(struct T3D_tagACTORINSTANCE *),CDisplay__dupActorHierarchicalSprite); +#endif +#ifdef CDisplay__ToggleCharacterNameSprites_x +FUNCTION_AT_ADDRESS(void CDisplay::ToggleCharacterNameSprites(bool),CDisplay__ToggleCharacterNameSprites); +#endif +#ifdef CDisplay__ToggleNpcNameSprites_x +FUNCTION_AT_ADDRESS(void CDisplay::ToggleNpcNameSprites(bool),CDisplay__ToggleNpcNameSprites); +#endif +#ifdef CDisplay__TurnInfravisionEffectOn_x +FUNCTION_AT_ADDRESS(int CDisplay::TurnInfravisionEffectOn(void),CDisplay__TurnInfravisionEffectOn); +#endif +#ifdef CDisplay__TurnInfravisionEffectOff_x +FUNCTION_AT_ADDRESS(int CDisplay::TurnInfravisionEffectOff(void),CDisplay__TurnInfravisionEffectOff); +#endif +#ifdef CDisplay__SpurtBloodOnDag_x +FUNCTION_AT_ADDRESS(void CDisplay::SpurtBloodOnDag(struct T3D_DAG *),CDisplay__SpurtBloodOnDag); +#endif +#ifdef CDisplay__SetDayPeriod_x +FUNCTION_AT_ADDRESS(void CDisplay::SetDayPeriod(unsigned char),CDisplay__SetDayPeriod); +#endif +#ifdef CDisplay__SetSkyLayer_x +FUNCTION_AT_ADDRESS(void CDisplay::SetSkyLayer(int),CDisplay__SetSkyLayer); +#endif +#ifdef CDisplay__GetSkyTime_x +FUNCTION_AT_ADDRESS(int CDisplay::GetSkyTime(int *,int *),CDisplay__GetSkyTime); +#endif +#ifdef CDisplay__SetSunLight_x +FUNCTION_AT_ADDRESS(void CDisplay::SetSunLight(void),CDisplay__SetSunLight); +#endif +#ifdef CDisplay__SetSkyBackground_x +FUNCTION_AT_ADDRESS(void CDisplay::SetSkyBackground(void),CDisplay__SetSkyBackground); +#endif +#ifdef CDisplay__ProcessSky_x +FUNCTION_AT_ADDRESS(void CDisplay::ProcessSky(void),CDisplay__ProcessSky); +#endif +#ifdef CDisplay__SimpleDistance_x +FUNCTION_AT_ADDRESS(float CDisplay::SimpleDistance(float,float,float,float,float,float,float),CDisplay__SimpleDistance); +#endif +#ifdef CDisplay__TrueDistance_x +FUNCTION_AT_ADDRESS(float CDisplay::TrueDistance(float,float,float,float,float,float,float),CDisplay__TrueDistance); +#endif +#ifdef CDisplay__PlayerSimpleDistance_x +FUNCTION_AT_ADDRESS(float CDisplay::PlayerSimpleDistance(class EQPlayer *,class EQPlayer *,float),CDisplay__PlayerSimpleDistance); +#endif +#ifdef CDisplay__PlayerDistance_x +FUNCTION_AT_ADDRESS(float CDisplay::PlayerDistance(class EQPlayer *,class EQPlayer *,float),CDisplay__PlayerDistance); +#endif +#ifdef CDisplay__hideGrassObjects_x +FUNCTION_AT_ADDRESS(void CDisplay::hideGrassObjects(void),CDisplay__hideGrassObjects); +#endif +#ifdef CDisplay__updateGrassObjects_x +FUNCTION_AT_ADDRESS(void CDisplay::updateGrassObjects(void),CDisplay__updateGrassObjects); +#endif +#ifdef CDisplay__loadGrassObjects_x +FUNCTION_AT_ADDRESS(void CDisplay::loadGrassObjects(char *),CDisplay__loadGrassObjects); +#endif +#ifdef CDisplay__SetAmbientLight_x +FUNCTION_AT_ADDRESS(void CDisplay::SetAmbientLight(float),CDisplay__SetAmbientLight); +#endif +#ifdef CDisplay__SetViewActorByName_x +FUNCTION_AT_ADDRESS(void CDisplay::SetViewActorByName(char *),CDisplay__SetViewActorByName); +#endif +#ifdef CDisplay__SetActorSpriteTint_x +FUNCTION_AT_ADDRESS(void CDisplay::SetActorSpriteTint(struct _EQRGB *,struct T3D_tagACTORINSTANCE *),CDisplay__SetActorSpriteTint); +#endif +#ifdef CDisplay__FreeAllItemLists_x +FUNCTION_AT_ADDRESS(void CDisplay::FreeAllItemLists(void),CDisplay__FreeAllItemLists); +#endif +#ifdef CActionsWnd__MainPageActivate_x +FUNCTION_AT_ADDRESS(int CActionsWnd::MainPageActivate(void),CActionsWnd__MainPageActivate); +#endif +#ifdef CActionsWnd__MainPageDeactivate_x +FUNCTION_AT_ADDRESS(int CActionsWnd::MainPageDeactivate(void),CActionsWnd__MainPageDeactivate); +#endif +#ifdef CActionsWnd__SocialsPageDeactivate_x +FUNCTION_AT_ADDRESS(int CActionsWnd::SocialsPageDeactivate(void),CActionsWnd__SocialsPageDeactivate); +#endif +#ifdef CGroupSearchWnd__GroupListPageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::GroupListPageOnProcessFrame(void),CGroupSearchWnd__GroupListPageOnProcessFrame); +#endif +#ifdef CGroupSearchWnd__PlayerListPageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int CGroupSearchWnd::PlayerListPageOnProcessFrame(void),CGroupSearchWnd__PlayerListPageOnProcessFrame); +#endif +#ifdef COptionsWnd__KeyboardPageOnProcessFrame_x +FUNCTION_AT_ADDRESS(int COptionsWnd::KeyboardPageOnProcessFrame(void),COptionsWnd__KeyboardPageOnProcessFrame); +#endif +#ifdef CDisplay__GetFloorHeight_x +FUNCTION_AT_ADDRESS(float CDisplay::GetFloorHeight(float,float,float),CDisplay__GetFloorHeight); +#endif +#ifdef CDisplay__GenericSphereColl_x +FUNCTION_AT_ADDRESS(bool CDisplay::GenericSphereColl(float,float,float,float,float,float,float *,float *,float *,unsigned char),CDisplay__GenericSphereColl); +#endif +#ifdef CDisplay__FindZoneTopZ_x +FUNCTION_AT_ADDRESS(float CDisplay::FindZoneTopZ(float,float,float),CDisplay__FindZoneTopZ); +#endif +#ifdef CDisplay__GetEnvironment_x +FUNCTION_AT_ADDRESS(unsigned char CDisplay::GetEnvironment(float,float,float,int *),CDisplay__GetEnvironment); +#endif +#ifdef CDisplay__MoveLocalPlayerToSafeCoords_x +FUNCTION_AT_ADDRESS(void CDisplay::MoveLocalPlayerToSafeCoords(void),CDisplay__MoveLocalPlayerToSafeCoords); +#endif +#ifdef CDisplay__SetupEQPlayers_x +FUNCTION_AT_ADDRESS(void CDisplay::SetupEQPlayers(void),CDisplay__SetupEQPlayers); +#endif +#ifdef CDisplay__MoveLight_x +FUNCTION_AT_ADDRESS(void CDisplay::MoveLight(struct T3D_POINTLIGHT *,struct _physicsinfo *),CDisplay__MoveLight); +#endif +#ifdef ZoneNPCLoadTextManager__ZoneNPCLoadTextManager_x +FUNCTION_AT_ADDRESS( ZoneNPCLoadTextManager::ZoneNPCLoadTextManager(char *),ZoneNPCLoadTextManager__ZoneNPCLoadTextManager); +#endif +#ifdef ZoneNPCLoadTextManager__dZoneNPCLoadTextManager_x +FUNCTION_AT_ADDRESS( ZoneNPCLoadTextManager::~ZoneNPCLoadTextManager(void),ZoneNPCLoadTextManager__dZoneNPCLoadTextManager); +#endif +#ifdef ZoneNPCLoadTextManager__LoadText_x +FUNCTION_AT_ADDRESS(void ZoneNPCLoadTextManager::LoadText(char *),ZoneNPCLoadTextManager__LoadText); +#endif +#ifdef ZoneNPCLoadTextManager__GetNPCCode_x +FUNCTION_AT_ADDRESS(char * ZoneNPCLoadTextManager::GetNPCCode(int),ZoneNPCLoadTextManager__GetNPCCode); +#endif +#ifdef ZoneNPCLoadTextManager__GetS3DName_x +FUNCTION_AT_ADDRESS(char * ZoneNPCLoadTextManager::GetS3DName(int),ZoneNPCLoadTextManager__GetS3DName); +#endif +#ifdef public_key__encrypt_x +FUNCTION_AT_ADDRESS(class vlong public_key::encrypt(class vlong &),public_key__encrypt); +#endif +#ifdef engineInterface__engineInterface_x +FUNCTION_AT_ADDRESS( engineInterface::engineInterface(void),engineInterface__engineInterface); +#endif +#ifdef engineInterface__get_x +FUNCTION_AT_ADDRESS(class engineInterface * __cdecl engineInterface::get(void),engineInterface__get); +#endif +#ifdef engineInterface__ChangeDag_x +FUNCTION_AT_ADDRESS(unsigned long * engineInterface::ChangeDag(struct T3D_tagWORLD *,struct T3D_DAG *,char *),engineInterface__ChangeDag); +#endif +#ifdef EQ_AltAbility__EQ_AltAbility_x +FUNCTION_AT_ADDRESS( EQ_AltAbility::EQ_AltAbility(int),EQ_AltAbility__EQ_AltAbility); +#endif +#ifdef AltAdvManager__AltAdvManager_x +FUNCTION_AT_ADDRESS( AltAdvManager::AltAdvManager(void),AltAdvManager__AltAdvManager); +#endif +#ifdef AltAdvManager__GetAltAbility_x +FUNCTION_AT_ADDRESS( struct _ALTABILITY *AltAdvManager::GetAltAbility(int), AltAdvManager__GetAltAbility); +#endif +#ifdef AltAdvManager__IsAbilityReady_x +FUNCTION_AT_ADDRESS(bool AltAdvManager::IsAbilityReady(class EQ_PC *,EQData::PALTABILITY,int *,int),AltAdvManager__IsAbilityReady); +#endif +#ifdef AltAdvManager__CalculateHideTimeReduce_x +FUNCTION_AT_ADDRESS(int AltAdvManager::CalculateHideTimeReduce(class EQ_PC *),AltAdvManager__CalculateHideTimeReduce); +#endif +#ifdef AltAdvManager__GetCalculatedTimer_x +FUNCTION_AT_ADDRESS(unsigned long AltAdvManager::GetCalculatedTimer(class EQ_PC *,EQData::PALTABILITY),AltAdvManager__GetCalculatedTimer); +#endif +#ifdef AltAdvManager__GetNextAbilityCost_x +FUNCTION_AT_ADDRESS(int AltAdvManager::GetNextAbilityCost(int,int),AltAdvManager__GetNextAbilityCost); +#endif +#ifdef AltAdvManager__TotalPointsInSkill_x +FUNCTION_AT_ADDRESS(int AltAdvManager::TotalPointsInSkill(int,int),AltAdvManager__TotalPointsInSkill); +#endif +#ifdef AltAdvManager__CalculateStalwartEnduranceChance_x +FUNCTION_AT_ADDRESS(int AltAdvManager::CalculateStalwartEnduranceChance(class EQ_PC *),AltAdvManager__CalculateStalwartEnduranceChance); +#endif +#ifdef AltAdvManager__CalculateLoHHarmTouchReuseTimer_x +FUNCTION_AT_ADDRESS(int AltAdvManager::CalculateLoHHarmTouchReuseTimer(class EQ_PC *,int),AltAdvManager__CalculateLoHHarmTouchReuseTimer); +#endif +#ifdef AltAdvManager__CalculateSingingMasteryMod_x +FUNCTION_AT_ADDRESS(int AltAdvManager::CalculateSingingMasteryMod(class EQ_PC *,int),AltAdvManager__CalculateSingingMasteryMod); +#endif +#ifdef AltAdvManager__CalculateInstrumentMasteryMod_x +FUNCTION_AT_ADDRESS(int AltAdvManager::CalculateInstrumentMasteryMod(class EQ_PC *),AltAdvManager__CalculateInstrumentMasteryMod); +#endif +#ifdef AltAdvManager__CalculateFleetOfFoot_x +FUNCTION_AT_ADDRESS(int AltAdvManager::CalculateFleetOfFoot(class EQ_PC *),AltAdvManager__CalculateFleetOfFoot); +#endif +#ifdef AltAdvManager__CalculateNimbleEvasionChance_x +FUNCTION_AT_ADDRESS(int AltAdvManager::CalculateNimbleEvasionChance(class EQ_PC *),AltAdvManager__CalculateNimbleEvasionChance); +#endif +#ifdef AltAdvManager__CalculateDoubleAttackChance_x +FUNCTION_AT_ADDRESS(int AltAdvManager::CalculateDoubleAttackChance(class EQ_PC *,int,unsigned char),AltAdvManager__CalculateDoubleAttackChance); +#endif +#ifdef AltAdvManager__CalculateMitigationBoost_x +FUNCTION_AT_ADDRESS(int AltAdvManager::CalculateMitigationBoost(class EQ_PC *,int),AltAdvManager__CalculateMitigationBoost); +#endif +#ifdef AltAdvManager__CalculateSpellCastingMastery_x +FUNCTION_AT_ADDRESS(int AltAdvManager::CalculateSpellCastingMastery(class EQ_PC *),AltAdvManager__CalculateSpellCastingMastery); +#endif +#ifdef AltAdvManager__CalculateMaxHPAA_x +FUNCTION_AT_ADDRESS(int AltAdvManager::CalculateMaxHPAA(class EQ_PC *,int),AltAdvManager__CalculateMaxHPAA); +#endif +#ifdef AltAdvManager__CalculateMaxStatAA_x +FUNCTION_AT_ADDRESS(int AltAdvManager::CalculateMaxStatAA(class EQ_PC *,int),AltAdvManager__CalculateMaxStatAA); +#endif +#ifdef AltAdvManager__GetAbilityTitle_x +FUNCTION_AT_ADDRESS(int AltAdvManager::GetAbilityTitle(class EQPlayer *),AltAdvManager__GetAbilityTitle); +#endif +#ifdef AltAdvManager__AltSkillReqs_x +FUNCTION_AT_ADDRESS(int AltAdvManager::AltSkillReqs(class EQ_PC *,int),AltAdvManager__AltSkillReqs); +#endif +#ifdef AltAdvManager__GetAALevelNeeded_x +FUNCTION_AT_ADDRESS(int AltAdvManager::GetAALevelNeeded(class EQ_PC *,int),AltAdvManager__GetAALevelNeeded); +#endif +#ifdef AltAdvManager__MeetsPoPLevelReqs_x +FUNCTION_AT_ADDRESS(int AltAdvManager::MeetsPoPLevelReqs(class EQ_PC *,int,int),AltAdvManager__MeetsPoPLevelReqs); +#endif +#ifdef AltAdvManager__CanTrainAbility_x +FUNCTION_AT_ADDRESS(int AltAdvManager::CanTrainAbility(class EQ_PC *,int),AltAdvManager__CanTrainAbility); +#endif +#ifdef AltAdvManager__AbilitiesByClass_x +FUNCTION_AT_ADDRESS(int AltAdvManager::AbilitiesByClass(int,int),AltAdvManager__AbilitiesByClass); +#endif +#ifdef AltAdvManager__GetAbilityReqs_x +FUNCTION_AT_ADDRESS(void AltAdvManager::GetAbilityReqs(char *,int),AltAdvManager__GetAbilityReqs); +#endif +#ifdef EQ_CharacterData__EQ_CharacterDataResetAllMembers_x +FUNCTION_AT_ADDRESS(void EQ_CharacterData::EQ_CharacterDataResetAllMembers(void),EQ_CharacterData__EQ_CharacterDataResetAllMembers); +#endif +#ifdef EQ_Affect__Reset_x +FUNCTION_AT_ADDRESS(void EQ_Affect::Reset(void),EQ_Affect__Reset); +#endif +#ifdef EQ_Character__EQ_Character_x +FUNCTION_AT_ADDRESS( EQ_Character::EQ_Character(void),EQ_Character__EQ_Character); +#endif +#ifdef EQ_Character__dEQ_Character_x +FUNCTION_AT_ADDRESS( EQ_Character::~EQ_Character(void),EQ_Character__dEQ_Character); +#endif +#ifdef EQ_Character__EQ_CharacterResetAllMembers_x +FUNCTION_AT_ADDRESS(void EQ_Character::EQ_CharacterResetAllMembers(void),EQ_Character__EQ_CharacterResetAllMembers); +#endif +#ifdef EQ_Character__ModifyCurHP_x +FUNCTION_AT_ADDRESS(void EQ_Character::ModifyCurHP(int,class EQPlayer *),EQ_Character__ModifyCurHP); +#endif +#ifdef EQ_Character__normal_to_special_x +FUNCTION_AT_ADDRESS(int __cdecl EQ_Character::normal_to_special(int),EQ_Character__normal_to_special); +#endif +#ifdef EQ_Character__IsSpellcaster_x +FUNCTION_AT_ADDRESS(int EQ_Character::IsSpellcaster(void),EQ_Character__IsSpellcaster); +#endif +#ifdef EQ_Character__DoLight_x +FUNCTION_AT_ADDRESS(void EQ_Character::DoLight(unsigned char),EQ_Character__DoLight); +#endif +#ifdef EQ_Character__Skill_x +FUNCTION_AT_ADDRESS(int EQ_Character::Skill(int),EQ_Character__Skill); +#endif +#ifdef EQ_Character__HasSpell_x +FUNCTION_AT_ADDRESS(int EQ_Character::HasSpell(int),EQ_Character__HasSpell); +#endif +#ifdef EQ_Character__ResetCur_HP_x +FUNCTION_AT_ADDRESS(void EQ_Character::ResetCur_HP(int),EQ_Character__ResetCur_HP); +#endif +#ifdef EQ_Character__Cur_HP_x +FUNCTION_AT_ADDRESS(int EQ_Character1::Cur_HP(int,unsigned char),EQ_Character__Cur_HP); +#endif +#ifdef EQ_Character__GetHPFromStamina_x +FUNCTION_AT_ADDRESS(int EQ_Character::GetHPFromStamina(int),EQ_Character__GetHPFromStamina); +#endif +#ifdef EQ_Character__Cur_Mana_x +FUNCTION_AT_ADDRESS(int EQ_Character::Cur_Mana(void),EQ_Character__Cur_Mana); +#endif +#ifdef EQ_Character__IsMage_x +FUNCTION_AT_ADDRESS(int EQ_Character::IsMage(void),EQ_Character__IsMage); +#endif +#ifdef EQ_Character__GetClassACBonus_x +FUNCTION_AT_ADDRESS(int EQ_Character::GetClassACBonus(int),EQ_Character__GetClassACBonus); +#endif +#ifdef EQ_Character__ac_x +FUNCTION_AT_ADDRESS(int EQ_Character::ac(bool),EQ_Character__ac); +#endif +#ifdef EQ_Character__compute_tohit_x +FUNCTION_AT_ADDRESS(int EQ_Character::compute_tohit(unsigned char),EQ_Character__compute_tohit); +#endif +#ifdef EQ_Character__defense_agility_bonus_x +FUNCTION_AT_ADDRESS(int EQ_Character::defense_agility_bonus(void),EQ_Character__defense_agility_bonus); +#endif +#ifdef EQ_Character__compute_defense_x +FUNCTION_AT_ADDRESS(int EQ_Character::compute_defense(void),EQ_Character__compute_defense); +#endif +#ifdef EQ_Character__offense_x +FUNCTION_AT_ADDRESS(int EQ_Character::offense(unsigned char),EQ_Character__offense); +#endif +#ifdef EQ_Character__HasSkill_x +FUNCTION_AT_ADDRESS(int EQ_Character::HasSkill(unsigned char),EQ_Character__HasSkill); +#endif +#ifdef EQ_Character__HasInnateSkill_x +FUNCTION_AT_ADDRESS(int EQ_Character::HasInnateSkill(unsigned char,int),EQ_Character__HasInnateSkill); +#endif +#ifdef EQ_Character__InitMyLanguages_x +FUNCTION_AT_ADDRESS(void EQ_Character::InitMyLanguages(void),EQ_Character__InitMyLanguages); +#endif +#ifdef EQ_Character__BaneDamage_x +FUNCTION_AT_ADDRESS(int EQ_Character::BaneDamage(class EQ_Equipment *),EQ_Character__BaneDamage); +#endif +#ifdef EQ_Character__ElementResistDmg_x +FUNCTION_AT_ADDRESS(int EQ_Character::ElementResistDmg(class EQ_Equipment *,int),EQ_Character__ElementResistDmg); +#endif +#ifdef EQ_Character__save_bash_x +FUNCTION_AT_ADDRESS(int EQ_Character::save_bash(int),EQ_Character__save_bash); +#endif +#ifdef EQ_Character__CapStat_x +FUNCTION_AT_ADDRESS(int EQ_Character::CapStat(int,int),EQ_Character__CapStat); +#endif +#ifdef EQ_Character__CalcFoodDrinkBonus_x +FUNCTION_AT_ADDRESS(void EQ_Character::CalcFoodDrinkBonus(int),EQ_Character__CalcFoodDrinkBonus); +#endif +#ifdef EQ_Character__basesave_magic_x +FUNCTION_AT_ADDRESS(int EQ_Character::basesave_magic(void),EQ_Character__basesave_magic); +#endif +#ifdef EQ_Character__save_magic_x +FUNCTION_AT_ADDRESS(int EQ_Character::save_magic(void),EQ_Character__save_magic); +#endif +#ifdef EQ_Character__basesave_fire_x +FUNCTION_AT_ADDRESS(int EQ_Character::basesave_fire(void),EQ_Character__basesave_fire); +#endif +#ifdef EQ_Character__save_fire_x +FUNCTION_AT_ADDRESS(int EQ_Character::save_fire(void),EQ_Character__save_fire); +#endif +#ifdef EQ_Character__basesave_cold_x +FUNCTION_AT_ADDRESS(int EQ_Character::basesave_cold(void),EQ_Character__basesave_cold); +#endif +#ifdef EQ_Character__save_cold_x +FUNCTION_AT_ADDRESS(int EQ_Character::save_cold(void),EQ_Character__save_cold); +#endif +#ifdef EQ_Character__basesave_disease_x +FUNCTION_AT_ADDRESS(int EQ_Character::basesave_disease(void),EQ_Character__basesave_disease); +#endif +#ifdef EQ_Character__save_disease_x +FUNCTION_AT_ADDRESS(int EQ_Character::save_disease(void),EQ_Character__save_disease); +#endif +#ifdef EQ_Character__basesave_poison_x +FUNCTION_AT_ADDRESS(int EQ_Character::basesave_poison(void),EQ_Character__basesave_poison); +#endif +#ifdef EQ_Character__save_poison_x +FUNCTION_AT_ADDRESS(int EQ_Character::save_poison(void),EQ_Character__save_poison); +#endif +#ifdef EQ_Character__Str_x +FUNCTION_AT_ADDRESS(int EQ_Character::Str(void),EQ_Character__Str); +#endif +#ifdef EQ_Character__Sta_x +FUNCTION_AT_ADDRESS(int EQ_Character::Sta(void),EQ_Character__Sta); +#endif +#ifdef EQ_Character__Cha_x +FUNCTION_AT_ADDRESS(int EQ_Character::Cha(void),EQ_Character__Cha); +#endif +#ifdef EQ_Character__Dex_x +FUNCTION_AT_ADDRESS(int EQ_Character::Dex(void),EQ_Character__Dex); +#endif +#ifdef EQ_Character__Int_x +FUNCTION_AT_ADDRESS(int EQ_Character::Int(void),EQ_Character__Int); +#endif +#ifdef EQ_Character__Agi_x +FUNCTION_AT_ADDRESS(int EQ_Character::Agi(void),EQ_Character__Agi); +#endif +#ifdef EQ_Character__Wis_x +FUNCTION_AT_ADDRESS(int EQ_Character::Wis(void),EQ_Character__Wis); +#endif +#ifdef EQ_Character__ApplyFatigue_x +FUNCTION_AT_ADDRESS(int EQ_Character::ApplyFatigue(int),EQ_Character__ApplyFatigue); +#endif +#ifdef EQ_Character__max_encumbrance_x +FUNCTION_AT_ADDRESS(int EQ_Character::max_encumbrance(void),EQ_Character__max_encumbrance); +#endif +#ifdef EQ_Character__CanUseItem_x +FUNCTION_AT_ADDRESS(int EQ_Character::CanUseItem(class EQ_Item *),EQ_Character__CanUseItem); +#endif +#ifdef EQ_Character__encum_factor_x +FUNCTION_AT_ADDRESS(float EQ_Character::encum_factor(void),EQ_Character__encum_factor); +#endif +#ifdef EQ_Character__cur_encumbrance_x +FUNCTION_AT_ADDRESS(int EQ_Character::cur_encumbrance(void),EQ_Character__cur_encumbrance); +#endif +#ifdef EQ_Character__Race_x +FUNCTION_AT_ADDRESS(char * EQ_Character::Race(int),EQ_Character__Race); +#endif +#ifdef EQ_Character__Class_x +FUNCTION_AT_ADDRESS(char * EQ_Character::Class(int),EQ_Character__Class); +#endif +#ifdef EQ_Character__KunarkClass_x +FUNCTION_AT_ADDRESS(char * EQ_Character::KunarkClass(int,int,int,bool),EQ_Character__KunarkClass); +#endif +#ifdef EQ_Character__ClassMin_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::ClassMin(int,int,unsigned char),EQ_Character__ClassMin); +#endif +#ifdef EQ_Character__CheckClass_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::CheckClass(int,int),EQ_Character__CheckClass); +#endif +#ifdef EQ_Character__CanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::CanWorship(int,int,unsigned char),EQ_Character__CanWorship); +#endif +#ifdef EQ_Character__HumanCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::HumanCanWorship(unsigned char,unsigned char),EQ_Character__HumanCanWorship); +#endif +#ifdef EQ_Character__BarbarianCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::BarbarianCanWorship(unsigned char,unsigned char),EQ_Character__BarbarianCanWorship); +#endif +#ifdef EQ_Character__EruditeCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::EruditeCanWorship(unsigned char,unsigned char),EQ_Character__EruditeCanWorship); +#endif +#ifdef EQ_Character__ElfCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::ElfCanWorship(unsigned char,unsigned char),EQ_Character__ElfCanWorship); +#endif +#ifdef EQ_Character__HighElfCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::HighElfCanWorship(unsigned char,unsigned char),EQ_Character__HighElfCanWorship); +#endif +#ifdef EQ_Character__DarkElfCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::DarkElfCanWorship(unsigned char,unsigned char),EQ_Character__DarkElfCanWorship); +#endif +#ifdef EQ_Character__HalfElfCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::HalfElfCanWorship(unsigned char,unsigned char),EQ_Character__HalfElfCanWorship); +#endif +#ifdef EQ_Character__DwarfCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::DwarfCanWorship(unsigned char,unsigned char),EQ_Character__DwarfCanWorship); +#endif +#ifdef EQ_Character__TrollCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::TrollCanWorship(unsigned char,unsigned char),EQ_Character__TrollCanWorship); +#endif +#ifdef EQ_Character__OgreCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::OgreCanWorship(unsigned char,unsigned char),EQ_Character__OgreCanWorship); +#endif +#ifdef EQ_Character__HalflingCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::HalflingCanWorship(unsigned char,unsigned char),EQ_Character__HalflingCanWorship); +#endif +#ifdef EQ_Character__GnomeCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::GnomeCanWorship(unsigned char,unsigned char),EQ_Character__GnomeCanWorship); +#endif +#ifdef EQ_Character__IksarCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::IksarCanWorship(unsigned char,unsigned char),EQ_Character__IksarCanWorship); +#endif +#ifdef EQ_Character__VahShirCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::VahShirCanWorship(unsigned char,unsigned char),EQ_Character__VahShirCanWorship); +#endif +#ifdef EQ_Character__FroglockCanWorship_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::FroglockCanWorship(unsigned char,unsigned char),EQ_Character__FroglockCanWorship); +#endif +#ifdef EQ_Character__CityCanStart_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::CityCanStart(int,int,int,int),EQ_Character__CityCanStart); +#endif +#ifdef EQ_Character__BaseAttr_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::BaseAttr(int,unsigned char),EQ_Character__BaseAttr); +#endif +#ifdef EQ_Character__InitSkills_x +FUNCTION_AT_ADDRESS(void EQ_Character::InitSkills(unsigned char,unsigned int),EQ_Character__InitSkills); +#endif +#ifdef EQ_Character__InitInnates_x +FUNCTION_AT_ADDRESS(void EQ_Character::InitInnates(unsigned int,unsigned int),EQ_Character__InitInnates); +#endif +#ifdef EQ_Character__IsSpecialBazaarSpot_x +FUNCTION_AT_ADDRESS(int EQ_Character::IsSpecialBazaarSpot(class EQPlayer *),EQ_Character__IsSpecialBazaarSpot); +#endif +#ifdef EQ_Character__CanSecondaryAttack_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::CanSecondaryAttack(class EQPlayer *),EQ_Character__CanSecondaryAttack); +#endif +#ifdef EQ_Character__CanDoubleAttack_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::CanDoubleAttack(class EQPlayer *,unsigned char),EQ_Character__CanDoubleAttack); +#endif +#ifdef EQ_Character__AntiTwinkAdj_x +FUNCTION_AT_ADDRESS(int EQ_Character::AntiTwinkAdj(class EQ_Equipment *,int,int),EQ_Character__AntiTwinkAdj); +#endif +#ifdef EQ_Character__GetSkillBaseDamage_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::GetSkillBaseDamage(unsigned char,class EQPlayer *),EQ_Character__GetSkillBaseDamage); +#endif +#ifdef EQ_Character__UseSkill_x +FUNCTION_AT_ADDRESS(void EQ_Character1::UseSkill(unsigned char,class EQPlayer *),EQ_Character__UseSkill); +#endif +#ifdef EQ_Character__DoIntimidationEvent_x +FUNCTION_AT_ADDRESS(void EQ_Character::DoIntimidationEvent(void),EQ_Character__DoIntimidationEvent); +#endif +#ifdef EQ_Character__DoFishingEvent_x +FUNCTION_AT_ADDRESS(void EQ_Character::DoFishingEvent(void),EQ_Character__DoFishingEvent); +#endif +#ifdef EQ_Character__FindClosest_x +FUNCTION_AT_ADDRESS(class EQPlayer * EQ_Character::FindClosest(int,int,int,int,int),EQ_Character__FindClosest); +#endif +#ifdef EQ_Character__IAmDead_x +FUNCTION_AT_ADDRESS(void EQ_Character::IAmDead(struct _EQMissileHitinfo *,int),EQ_Character__IAmDead); +#endif +#ifdef EQ_Character__TotalOnPerson_x +FUNCTION_AT_ADDRESS(long EQ_Character::TotalOnPerson(void),EQ_Character__TotalOnPerson); +#endif +#ifdef EQ_Character__ItemSold_x +FUNCTION_AT_ADDRESS(void EQ_Character::ItemSold(long),EQ_Character__ItemSold); +#endif +#ifdef EQ_Character__TakeFallDamage_x +FUNCTION_AT_ADDRESS(int EQ_Character::TakeFallDamage(float),EQ_Character__TakeFallDamage); +#endif +#ifdef EQ_Character__IHaveSkill_x +FUNCTION_AT_ADDRESS(int EQ_Character::IHaveSkill(unsigned char),EQ_Character__IHaveSkill); +#endif +#ifdef EQ_Character__NoMezMe_x +FUNCTION_AT_ADDRESS(int EQ_Character::NoMezMe(int,class EQPlayer *,class EQ_Spell *),EQ_Character__NoMezMe); +#endif +#ifdef EQ_Character__NoBashMe_x +FUNCTION_AT_ADDRESS(int EQ_Character::NoBashMe(int),EQ_Character__NoBashMe); +#endif +#ifdef EQ_Character__StunMe_x +FUNCTION_AT_ADDRESS(void EQ_Character1::StunMe(unsigned int,unsigned int,unsigned int),EQ_Character__StunMe); +#endif +#ifdef EQ_Character__UnStunMe_x +FUNCTION_AT_ADDRESS(void EQ_Character1::UnStunMe(void),EQ_Character__UnStunMe); +#endif +#ifdef EQ_Character__ApplyDamage_x +FUNCTION_AT_ADDRESS(int EQ_Character::ApplyDamage(int,struct _EQMissileHitinfo *,bool,class HateListEntry *,bool),EQ_Character__ApplyDamage); +#endif +#ifdef EQ_Character__NotifyPCAffectChange_x +FUNCTION_AT_ADDRESS(void EQ_Character::NotifyPCAffectChange(int,int),EQ_Character__NotifyPCAffectChange); +#endif +#ifdef EQ_Character__MakeMeVisible_x +FUNCTION_AT_ADDRESS(void EQ_Character::MakeMeVisible(int),EQ_Character__MakeMeVisible); +#endif +#ifdef EQ_Character__UpdateMyVisibleStatus_x +FUNCTION_AT_ADDRESS(void EQ_Character::UpdateMyVisibleStatus(void),EQ_Character__UpdateMyVisibleStatus); +#endif +#ifdef EQ_Character__CanISeeInvis_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::CanISeeInvis(void),EQ_Character__CanISeeInvis); +#endif +#ifdef EQ_Character__CanIBreathe_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::CanIBreathe(void),EQ_Character__CanIBreathe); +#endif +#ifdef EQ_Character__ProcessEnvironment_x +FUNCTION_AT_ADDRESS(void EQ_Character::ProcessEnvironment(void),EQ_Character__ProcessEnvironment); +#endif +#ifdef EQ_Character__ProcessHungerandThirst_x +FUNCTION_AT_ADDRESS(void EQ_Character::ProcessHungerandThirst(unsigned int),EQ_Character__ProcessHungerandThirst); +#endif +#ifdef EQ_Character__ItemSpellAffects_x +FUNCTION_AT_ADDRESS(int EQ_Character::ItemSpellAffects(int),EQ_Character__ItemSpellAffects); +#endif +#ifdef EQ_Character__ProcessAllStats_x +FUNCTION_AT_ADDRESS(void EQ_Character::ProcessAllStats(void),EQ_Character__ProcessAllStats); +#endif +#ifdef EQ_Character__DoPassageOfTime_x +FUNCTION_AT_ADDRESS(void EQ_Character::DoPassageOfTime(void),EQ_Character__DoPassageOfTime); +#endif +#ifdef EQ_Character__FindItemByClass_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::FindItemByClass(int,int *,int *),EQ_Character__FindItemByClass); +#endif +#ifdef EQ_Character__FindItemByRecord_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::FindItemByRecord(int,int *,int *),EQ_Character__FindItemByRecord); +#endif +#ifdef EQ_Character__FindItemQty_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::FindItemQty(int,int),EQ_Character__FindItemQty); +#endif +#ifdef EQ_Character__CanMedOnHorse_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::CanMedOnHorse(void),EQ_Character__CanMedOnHorse); +#endif +#ifdef EQ_Character__ExpendItemCharge_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::ExpendItemCharge(int,int),EQ_Character__ExpendItemCharge); +#endif +#ifdef EQ_Character__AutoEat_x +FUNCTION_AT_ADDRESS(int EQ_Character::AutoEat(unsigned char),EQ_Character__AutoEat); +#endif +#ifdef EQ_Character__CheckFoodAndWater_x +FUNCTION_AT_ADDRESS(int EQ_Character::CheckFoodAndWater(void),EQ_Character__CheckFoodAndWater); +#endif +#ifdef EQ_Character__DoMeditation_x +FUNCTION_AT_ADDRESS(void EQ_Character::DoMeditation(void),EQ_Character__DoMeditation); +#endif +#ifdef EQ_Character__SetLocalVar_x +FUNCTION_AT_ADDRESS(int EQ_Character::SetLocalVar(char *,int),EQ_Character__SetLocalVar); +#endif +#ifdef EQ_Character__GetIndexSkillMinDamageMod_x +FUNCTION_AT_ADDRESS(int EQ_Character::GetIndexSkillMinDamageMod(int),EQ_Character__GetIndexSkillMinDamageMod); +#endif +#ifdef EQ_Character__GetFocusConserveRegChance_x +FUNCTION_AT_ADDRESS(int const EQ_Character::GetFocusConserveRegChance(class EQ_Spell const *,class EQ_Equipment * *),EQ_Character__GetFocusConserveRegChance); +#endif +#ifdef EQ_Character__GetFocusCastingTimeModifier_x +FUNCTION_AT_ADDRESS(int const EQ_Character1::GetFocusCastingTimeModifier(class EQ_Spell const *,class EQ_Equipment * *, int),EQ_Character__GetFocusCastingTimeModifier); +#endif +#ifdef EQ_Character__GetFocusRangeModifier_x +FUNCTION_AT_ADDRESS(int const EQ_Character1::GetFocusRangeModifier(class EQ_Spell const *,class EQ_Equipment * *),EQ_Character__GetFocusRangeModifier); +#endif +#ifdef EQ_Character__IsExpansionFlag_x +FUNCTION_AT_ADDRESS(int EQ_Character1::IsExpansionFlag(int),EQ_Character__IsExpansionFlag); +#endif +#ifdef EQ_Character__GetFocusItem_x +FUNCTION_AT_ADDRESS(class EQ_Equipment * EQ_Character::GetFocusItem(class EQ_Spell const *,int),EQ_Character__GetFocusItem); +#endif +#ifdef EQ_Character__GetFocusEffect_x +FUNCTION_AT_ADDRESS(class EQ_Spell * EQ_Character::GetFocusEffect(class EQ_Spell const *,int),EQ_Character__GetFocusEffect); +#endif +#ifdef EQ_Character__DoesSpellMatchFocusFilters_x +FUNCTION_AT_ADDRESS(bool EQ_Character::DoesSpellMatchFocusFilters(class EQ_Spell const *,class EQ_Spell const *),EQ_Character__DoesSpellMatchFocusFilters); +#endif +#ifdef EQ_Character__GetMyPetPlayer_x +FUNCTION_AT_ADDRESS(class EQPlayer * EQ_Character::GetMyPetPlayer(void),EQ_Character__GetMyPetPlayer); +#endif +#ifdef EQ_Character__GetMaxEffects_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::GetMaxEffects(void)const ,EQ_Character__GetMaxEffects); +#endif +#ifdef EQ_Character__GetEffect_x +FUNCTION_AT_ADDRESS(class EQ_Affect & EQ_Character::GetEffect(int),EQ_Character__GetEffect); +#endif +#ifdef EQ_Character__GetEffectId_x +FUNCTION_AT_ADDRESS(unsigned int EQ_Character::GetEffectId(int),EQ_Character__GetEffectId); +#endif +#ifdef EQ_Character__SetEffectId_x +FUNCTION_AT_ADDRESS(void EQ_Character1::SetEffectId(unsigned char,unsigned int),EQ_Character__SetEffectId); +#endif +#ifdef EQ_Character__CastSpell_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character1::CastSpell(unsigned char gemid,int spellid,class EQ_Item * *ppItem,int,int slot,int,int,int,int,bool,int),EQ_Character__CastSpell); +#endif +#ifdef EQ_Character__GetBardInstrumentMod_x +FUNCTION_AT_ADDRESS(int EQ_Character::GetBardInstrumentMod(int),EQ_Character__GetBardInstrumentMod); +#endif +#ifdef EQ_Character__CalculateBardSongMod_x +FUNCTION_AT_ADDRESS(int EQ_Character::CalculateBardSongMod(int),EQ_Character__CalculateBardSongMod); +#endif +#ifdef EQ_Character__CastingRequirementsMet_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::CastingRequirementsMet(int),EQ_Character__CastingRequirementsMet); +#endif +#ifdef EQ_Character__GetAACastingTimeModifier_x +FUNCTION_AT_ADDRESS(int const EQ_Character1::GetAACastingTimeModifier(class EQ_Spell const *),EQ_Character__GetAACastingTimeModifier); +#endif +#ifdef EQ_Character__BardCastBard_x +FUNCTION_AT_ADDRESS(int EQ_Character::BardCastBard(class EQ_Spell const *,int)const ,EQ_Character__BardCastBard); +#endif +#ifdef EQ_Character__IsValidAffect_x +FUNCTION_AT_ADDRESS(bool EQ_Character::IsValidAffect(int),EQ_Character__IsValidAffect); +#endif +#ifdef EQ_Character__LaunchSpell_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::LaunchSpell(unsigned char,int,class EQ_Item * *),EQ_Character__LaunchSpell); +#endif +#ifdef EQ_Character__HandleSpecialPCAffects_x +FUNCTION_AT_ADDRESS(void EQ_Character::HandleSpecialPCAffects(int),EQ_Character__HandleSpecialPCAffects); +#endif +#ifdef EQ_Character__CalcAffectChange_x +FUNCTION_AT_ADDRESS(int EQ_Character::CalcAffectChange(class EQ_Spell *,unsigned char,unsigned char,class EQ_Affect *),EQ_Character__CalcAffectChange); +#endif +#ifdef EQ_Character__GetPCSpellAffect_x +FUNCTION_AT_ADDRESS(class EQ_Affect * EQ_Character::GetPCSpellAffect(unsigned char,int *),EQ_Character__GetPCSpellAffect); +#endif +#ifdef EQ_Character__TotalSpellAffects_x +FUNCTION_AT_ADDRESS(int EQ_Character::TotalSpellAffects(unsigned char,bool,int *),EQ_Character__TotalSpellAffects); +#endif +#ifdef EQ_Character__IsSpellAffectingPC_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::IsSpellAffectingPC(int),EQ_Character__IsSpellAffectingPC); +#endif +#ifdef EQ_Character__SpellFizzled_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Character::SpellFizzled(unsigned char,class EQ_Spell *),EQ_Character__SpellFizzled); +#endif +#ifdef EQ_Character__ProcessAffects_x +FUNCTION_AT_ADDRESS(int EQ_Character::ProcessAffects(void),EQ_Character__ProcessAffects); +#endif +#ifdef EQ_Character__FindAffectSlot_x +FUNCTION_AT_ADDRESS(class EQ_Affect * EQ_Character::FindAffectSlot(int,class EQPlayer *,int *,int),EQ_Character__FindAffectSlot); +#endif +#ifdef EQ_Character__GetOpenEffectSlot_x +FUNCTION_AT_ADDRESS(int EQ_Character::GetOpenEffectSlot(bool,int),EQ_Character__GetOpenEffectSlot); +#endif +#ifdef EQ_Character__GetFirstEffectSlot_x +FUNCTION_AT_ADDRESS(int EQ_Character::GetFirstEffectSlot(bool),EQ_Character__GetFirstEffectSlot); +#endif +#ifdef EQ_Character__GetLastEffectSlot_x +FUNCTION_AT_ADDRESS(int EQ_Character::GetLastEffectSlot(bool),EQ_Character__GetLastEffectSlot); +#endif +#ifdef EQ_Character__IsStackBlocked_x +FUNCTION_AT_ADDRESS(bool EQ_Character::IsStackBlocked(class EQ_Spell const *),EQ_Character__IsStackBlocked); +#endif +#ifdef EQ_Character__IsSpellTooPowerfull_x +FUNCTION_AT_ADDRESS(bool EQ_Character::IsSpellTooPowerfull(class EQ_Spell *,class EQ_Character *),EQ_Character__IsSpellTooPowerfull); +#endif +#ifdef EQ_Character__HitBySpell_x +FUNCTION_AT_ADDRESS(void EQ_Character::HitBySpell(struct _EQMissileHitinfo *),EQ_Character__HitBySpell); +#endif +#ifdef EQ_Spell__IsStackableDot_x +FUNCTION_AT_ADDRESS(bool EQ_Spell::IsStackableDot(void)const ,EQ_Spell__IsStackableDot); +#endif +#ifdef EQ_Character__EQSPA_Feign_Death_x +FUNCTION_AT_ADDRESS(void EQ_Character::EQSPA_Feign_Death(int),EQ_Character__EQSPA_Feign_Death); +#endif +#ifdef EQ_Character__SpellDuration_x +FUNCTION_AT_ADDRESS(int EQ_Character::SpellDuration(class EQ_Spell const *,unsigned char,unsigned char),EQ_Character__SpellDuration); +#endif +#ifdef EQ_Character__eqspa_change_form_x +FUNCTION_AT_ADDRESS(int EQ_Character::eqspa_change_form(class EQ_Spell *,int,int,class EQ_Affect *),EQ_Character__eqspa_change_form); +#endif +#ifdef EQ_Character__eqspa_movement_rate_x +FUNCTION_AT_ADDRESS(void EQ_Character::eqspa_movement_rate(int),EQ_Character__eqspa_movement_rate); +#endif +#ifdef EQ_Character__eqspa_levitation_x +FUNCTION_AT_ADDRESS(void EQ_Character::eqspa_levitation(void),EQ_Character__eqspa_levitation); +#endif +#ifdef EQ_Character__eqspa_hp_x +FUNCTION_AT_ADDRESS(int EQ_Character::eqspa_hp(unsigned int,class EQ_Affect *,int,class EQ_Spell *),EQ_Character__eqspa_hp); +#endif +#ifdef EQ_Character__eqspa_locate_corpse_x +FUNCTION_AT_ADDRESS(void EQ_Character::eqspa_locate_corpse(void),EQ_Character__eqspa_locate_corpse); +#endif +#ifdef EQ_Character__InSpecialBindSpot_x +FUNCTION_AT_ADDRESS(int EQ_Character::InSpecialBindSpot(class EQPlayer *),EQ_Character__InSpecialBindSpot); +#endif +#ifdef EQ_Character__RemovePCAffect_x +FUNCTION_AT_ADDRESS(void EQ_Character::RemovePCAffect(class EQ_Affect *),EQ_Character__RemovePCAffect); +#endif +#ifdef EQ_Character__RemovePCAffectex_x +FUNCTION_AT_ADDRESS(void EQ_Character::RemovePCAffectex(class EQ_Affect *,int),EQ_Character__RemovePCAffectex); +#endif +#ifdef EQ_Character__StopSpellCast_x +FUNCTION_AT_ADDRESS(void EQ_Character1::StopSpellCast(unsigned char),EQ_Character__StopSpellCast); +#endif +#ifdef EQ_Character__StopSpellCast1_x +FUNCTION_AT_ADDRESS(void EQ_Character1::StopSpellCast(unsigned char,int),EQ_Character__StopSpellCast1); +#endif +#ifdef EQ_Character__ReCachSpellEffects_x +FUNCTION_AT_ADDRESS(void EQ_Character::ReCachSpellEffects(void),EQ_Character__ReCachSpellEffects); +#endif +#ifdef EQ_Character__ReCachItemEffects_x +FUNCTION_AT_ADDRESS(void EQ_Character::ReCachItemEffects(void),EQ_Character__ReCachItemEffects); +#endif +#ifdef EQ_Character__GetCachEQSPA_x +FUNCTION_AT_ADDRESS(int EQ_Character::GetCachEQSPA(int),EQ_Character__GetCachEQSPA); +#endif +#ifdef EQ_Character__GetConLevel_x +FUNCTION_AT_ADDRESS(unsigned long EQ_Character::GetConLevel(class EQPlayer *),EQ_Character__GetConLevel); +#endif +#ifdef EQ_Character__TotalEffect_x +FUNCTION_AT_ADDRESS(int EQ_Character1::TotalEffect(int, bool, int, bool, bool), EQ_Character__TotalEffect); +#endif +#ifdef EQ_Container__EQ_Container_x +FUNCTION_AT_ADDRESS( EQ_Container::EQ_Container(void),EQ_Container__EQ_Container); +#endif +#ifdef EQ_Container__dEQ_Container_x +FUNCTION_AT_ADDRESS( EQ_Container::~EQ_Container(void),EQ_Container__dEQ_Container); +#endif +#ifdef EQ_Container__Open_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Container::Open(void),EQ_Container__Open); +#endif +#ifdef EQ_Container__Close_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Container::Close(void),EQ_Container__Close); +#endif +#ifdef EQ_Container__IsOpen_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Container::IsOpen(void),EQ_Container__IsOpen); +#endif +#ifdef EQ_Equipment__EQ_Equipment_x +FUNCTION_AT_ADDRESS( EQ_Equipment::EQ_Equipment(void),EQ_Equipment__EQ_Equipment); +#endif +#ifdef EQ_Equipment__IsWeapon_x +FUNCTION_AT_ADDRESS(int EQ_Equipment::IsWeapon(void),EQ_Equipment__IsWeapon); +#endif +#ifdef EQ_Equipment__IsInstrument_x +FUNCTION_AT_ADDRESS(int EQ_Equipment::IsInstrument(void),EQ_Equipment__IsInstrument); +#endif +#ifdef EQ_Equipment__SendTextRequestMsg_x +FUNCTION_AT_ADDRESS(void EQ_Equipment::SendTextRequestMsg(void),EQ_Equipment__SendTextRequestMsg); +#endif +#ifdef EQ_Item__Platinum_x +FUNCTION_AT_ADDRESS(int EQ_Item::Platinum(void),EQ_Item__Platinum); +#endif +#ifdef EQ_Item__Gold_x +FUNCTION_AT_ADDRESS(int EQ_Item::Gold(void),EQ_Item__Gold); +#endif +#ifdef EQ_Item__Silver_x +FUNCTION_AT_ADDRESS(int EQ_Item::Silver(void),EQ_Item__Silver); +#endif +#ifdef EQ_Item__Copper_x +FUNCTION_AT_ADDRESS(int EQ_Item::Copper(void),EQ_Item__Copper); +#endif +#ifdef EQ_Item__ValueSellMerchant_x +FUNCTION_AT_ADDRESS(long EQ_Item::ValueSellMerchant(float,long),EQ_Item__ValueSellMerchant); +#endif +#ifdef EQ_Item__ValueSSell_x +FUNCTION_AT_ADDRESS(char * EQ_Item::ValueSSell(float,long),EQ_Item__ValueSSell); +#endif +#ifdef EQ_Item__ValueSBuy_x +FUNCTION_AT_ADDRESS(char * EQ_Item::ValueSBuy(float,long),EQ_Item__ValueSBuy); +#endif +#ifdef EQ_Item__ValueSRent_x +FUNCTION_AT_ADDRESS(char * EQ_Item::ValueSRent(void),EQ_Item__ValueSRent); +#endif +#ifdef EQ_Item__IsSpecialNoDrop_x +FUNCTION_AT_ADDRESS(bool EQ_Item::IsSpecialNoDrop(void),EQ_Item__IsSpecialNoDrop); +#endif +#ifdef EQ_Item__IsStackable_x +FUNCTION_AT_ADDRESS(bool EQ_Item::IsStackable(void),EQ_Item__IsStackable); +#endif +#ifdef EQ_LoadingS__EQ_LoadingS_x +FUNCTION_AT_ADDRESS( EQ_LoadingS::EQ_LoadingS(void),EQ_LoadingS__EQ_LoadingS); +#endif +#ifdef EQ_LoadingS__dEQ_LoadingS_x +FUNCTION_AT_ADDRESS( EQ_LoadingS::~EQ_LoadingS(void),EQ_LoadingS__dEQ_LoadingS); +#endif +#ifdef EQ_LoadingS__DrawBackground_x +FUNCTION_AT_ADDRESS(void EQ_LoadingS::DrawBackground(struct T3D_XYZ *),EQ_LoadingS__DrawBackground); +#endif +#ifdef EQ_LoadingS__draw_x +FUNCTION_AT_ADDRESS(void EQ_LoadingS::draw(void),EQ_LoadingS__draw); +#endif +#ifdef EQ_LoadingS__WriteTextHD_x +FUNCTION_AT_ADDRESS(void EQ_LoadingS::WriteTextHD(char *,int,int,int),EQ_LoadingS__WriteTextHD); +#endif +#ifdef EQ_LoadingS__SetProgressBar_x +FUNCTION_AT_ADDRESS(void EQ_LoadingS::SetProgressBar(int,char const *),EQ_LoadingS__SetProgressBar); +#endif +#ifdef EQ_Note__EQ_Note_x +FUNCTION_AT_ADDRESS( EQ_Note::EQ_Note(void),EQ_Note__EQ_Note); +#endif +#ifdef EQ_Note__SendTextRequestMsg_x +FUNCTION_AT_ADDRESS(void EQ_Note::SendTextRequestMsg(void),EQ_Note__SendTextRequestMsg); +#endif +#ifdef EQ_PC__EQ_PC_x +FUNCTION_AT_ADDRESS( EQ_PC::EQ_PC(class EQ_PC *),EQ_PC__EQ_PC); +#endif +#ifdef EQ_PC__dEQ_PC_x +FUNCTION_AT_ADDRESS( EQ_PC::~EQ_PC(void),EQ_PC__dEQ_PC); +#endif +#ifdef EQ_PC__ClearSharedVault_x +FUNCTION_AT_ADDRESS(void EQ_PC::ClearSharedVault(void),EQ_PC__ClearSharedVault); +#endif +#ifdef EQ_PC__IsAGroupMember_x +FUNCTION_AT_ADDRESS(int EQ_PC::IsAGroupMember(char *),EQ_PC__IsAGroupMember); +#endif +#ifdef EQ_PC__CheckForGroupChanges_x +FUNCTION_AT_ADDRESS(void EQ_PC::CheckForGroupChanges(void),EQ_PC__CheckForGroupChanges); +#endif +#ifdef EQ_PC__UnpackMyNetPC_x +FUNCTION_AT_ADDRESS(void EQ_PC::UnpackMyNetPC(char *,int),EQ_PC__UnpackMyNetPC); +#endif +#ifdef EQ_PC__InitPlayerStart_x +FUNCTION_AT_ADDRESS(void EQ_PC::InitPlayerStart(unsigned int,unsigned char,int),EQ_PC__InitPlayerStart); +#endif +#ifdef EQ_PC__EmptyPossessionSlots_x +FUNCTION_AT_ADDRESS(void EQ_PC::EmptyPossessionSlots(void),EQ_PC__EmptyPossessionSlots); +#endif +#ifdef EQ_PC__RefreshMe_x +FUNCTION_AT_ADDRESS(void EQ_PC::RefreshMe(int),EQ_PC__RefreshMe); +#endif +#ifdef EQ_PC__PrepareForRepop_x +FUNCTION_AT_ADDRESS(void EQ_PC::PrepareForRepop(int),EQ_PC__PrepareForRepop); +#endif +#ifdef EQ_PC__RefitNewbieEQ_x +FUNCTION_AT_ADDRESS(void EQ_PC::RefitNewbieEQ(void),EQ_PC__RefitNewbieEQ); +#endif +#ifdef EQ_PC__RemoveMyAffect_x +FUNCTION_AT_ADDRESS(unsigned char EQ_PC::RemoveMyAffect(int),EQ_PC__RemoveMyAffect); +#endif +#ifdef EQ_PC__ProcessFatigue_x +FUNCTION_AT_ADDRESS(void EQ_PC::ProcessFatigue(void),EQ_PC__ProcessFatigue); +#endif +#ifdef EQ_PC__DelLoreItemDup_x +FUNCTION_AT_ADDRESS(int EQ_PC::DelLoreItemDup(int,int,int,class EQ_Item *),EQ_PC__DelLoreItemDup); +#endif +#ifdef EQ_PC__CheckDupLoreItems_x +FUNCTION_AT_ADDRESS(int EQ_PC::CheckDupLoreItems(void),EQ_PC__CheckDupLoreItems); +#endif +#ifdef EQ_PC__CostToTrain_x +FUNCTION_AT_ADDRESS(int EQ_PC::CostToTrain(int,float,int),EQ_PC__CostToTrain); +#endif +#ifdef EQ_PC__checkLang_x +FUNCTION_AT_ADDRESS(int EQ_PC::checkLang(int),EQ_PC__checkLang); +#endif +#ifdef EQ_PC__BitchCanTrain_x +FUNCTION_AT_ADDRESS(int EQ_PC::BitchCanTrain(int,int,int),EQ_PC__BitchCanTrain); +#endif +#ifdef EQ_PC__HandleMoney_x +FUNCTION_AT_ADDRESS(int EQ_PC::HandleMoney(long),EQ_PC__HandleMoney); +#endif +#ifdef EQ_PC__DetermineQuestExpGained_x +FUNCTION_AT_ADDRESS(void EQ_PC::DetermineQuestExpGained(int),EQ_PC__DetermineQuestExpGained); +#endif +#ifdef EQ_PC__ProcessAirSupply_x +FUNCTION_AT_ADDRESS(void EQ_PC::ProcessAirSupply(void),EQ_PC__ProcessAirSupply); +#endif +#ifdef EQ_PC__MaxAirSupply_x +FUNCTION_AT_ADDRESS(int EQ_PC::MaxAirSupply(void),EQ_PC__MaxAirSupply); +#endif +#ifdef EQ_PC__SetFatigue_x +FUNCTION_AT_ADDRESS(void EQ_PC::SetFatigue(int),EQ_PC__SetFatigue); +#endif +#ifdef EQ_PC__numInParty_x +FUNCTION_AT_ADDRESS(int EQ_PC::numInParty(void),EQ_PC__numInParty); +#endif +#ifdef EQ_PC__AtSkillLimit_x +FUNCTION_AT_ADDRESS(unsigned char EQ_PC::AtSkillLimit(int),EQ_PC__AtSkillLimit); +#endif +#ifdef EQ_PC__GetItemTimerValue_x +FUNCTION_AT_ADDRESS(unsigned long EQ_PC::GetItemTimerValue(class EQ_Item *),EQ_PC__GetItemTimerValue); +#endif +#ifdef EQ_PC__GetAltAbilityIndex_x +FUNCTION_AT_ADDRESS(int EQ_PC::GetAltAbilityIndex(int),EQ_PC__GetAltAbilityIndex); +#endif +#ifdef EQ_PC__GetCombatAbility_x +FUNCTION_AT_ADDRESS(int EQ_PC::GetCombatAbility(int),EQ_PC__GetCombatAbility); +#endif +#ifdef EQ_PC__GetCombatAbilityTimer_x +FUNCTION_AT_ADDRESS(unsigned long EQ_PC::GetCombatAbilityTimer(int),EQ_PC__GetCombatAbilityTimer); +#endif +#ifdef EQ_PC__HasLoreItem_x +FUNCTION_AT_ADDRESS(unsigned long EQ_PC::HasLoreItem(class EQ_Item *),EQ_PC__HasLoreItem); +#endif +#ifdef CInvSlot__HandleLButtonDown_x +FUNCTION_AT_ADDRESS(void CInvSlot::HandleLButtonDown(class CXPoint),CInvSlot__HandleLButtonDown); +#endif +#ifdef CInvSlot__HandleLButtonUpAfterHeld_x +FUNCTION_AT_ADDRESS(void CInvSlot::HandleLButtonUpAfterHeld(class CXPoint),CInvSlot__HandleLButtonUpAfterHeld); +#endif +#ifdef CInvSlot__HandleRButtonDown_x +FUNCTION_AT_ADDRESS(void CInvSlot::HandleRButtonDown(class CXPoint),CInvSlot__HandleRButtonDown); +#endif +#ifdef EQ_PC__CheckForLanguageImprovement_x +FUNCTION_AT_ADDRESS(void EQ_PC::CheckForLanguageImprovement(unsigned char,unsigned char),EQ_PC__CheckForLanguageImprovement); +#endif +#ifdef EQ_PC__CheckSkillImprove_x +FUNCTION_AT_ADDRESS(void EQ_PC::CheckSkillImprove(int,float),EQ_PC__CheckSkillImprove); +#endif +#ifdef EQ_PC__GetBodyTint_x +FUNCTION_AT_ADDRESS(unsigned long EQ_PC::GetBodyTint(int),EQ_PC__GetBodyTint); +#endif +#ifdef EQ_PC__SetAltAbilityIndex_x +FUNCTION_AT_ADDRESS(void EQ_PC::SetAltAbilityIndex(int,int),EQ_PC__SetAltAbilityIndex); +#endif +#ifdef EQ_PC__GetArmorTint_x +FUNCTION_AT_ADDRESS(unsigned long EQ_PC::GetArmorTint(int),EQ_PC__GetArmorTint); +#endif +#ifdef EQ_PC__SetArmorTint_x +FUNCTION_AT_ADDRESS(void EQ_PC::SetArmorTint(int,unsigned long),EQ_PC__SetArmorTint); +#endif +#ifdef EQ_PC__GetArmorType_x +FUNCTION_AT_ADDRESS(int EQ_PC::GetArmorType(int),EQ_PC__GetArmorType); +#endif +#ifdef EQ_PC__SetArmorType_x +FUNCTION_AT_ADDRESS(void EQ_PC::SetArmorType(int,int),EQ_PC__SetArmorType); +#endif +#ifdef EQ_PC__InitializeNewPCVariables_x +FUNCTION_AT_ADDRESS(void EQ_PC::InitializeNewPCVariables(int),EQ_PC__InitializeNewPCVariables); +#endif +#ifdef EQ_PC__DestroyHeldItemOrMoney_x +FUNCTION_AT_ADDRESS(void EQ_PC::DestroyHeldItemOrMoney(void),EQ_PC__DestroyHeldItemOrMoney); +#endif +#ifdef EQ_Skill__EQ_Skill_x +FUNCTION_AT_ADDRESS( EQ_Skill::EQ_Skill(int),EQ_Skill__EQ_Skill); +#endif +#ifdef EqSoundManager__EqSoundManager_x +//FUNCTION_AT_ADDRESS( EqSoundManager::EqSoundManager(bool,bool,enum SpeakerType),EqSoundManager__EqSoundManager); +#endif +#ifdef EqSoundManager__dEqSoundManager_x +FUNCTION_AT_ADDRESS( EqSoundManager::~EqSoundManager(void),EqSoundManager__dEqSoundManager); +#endif +#ifdef EqSoundManager__LoadGlobalEmitters_x +FUNCTION_AT_ADDRESS(void EqSoundManager::LoadGlobalEmitters(void),EqSoundManager__LoadGlobalEmitters); +#endif +#ifdef EqSoundManager__GetMusicId_x +FUNCTION_AT_ADDRESS(int EqSoundManager::GetMusicId(void),EqSoundManager__GetMusicId); +#endif +#ifdef EqSoundManager__LoadGlobalWaves_x +FUNCTION_AT_ADDRESS(void EqSoundManager::LoadGlobalWaves(void),EqSoundManager__LoadGlobalWaves); +#endif +#ifdef EqSoundManager__LoadListOfWaveFiles_x +FUNCTION_AT_ADDRESS(void EqSoundManager::LoadListOfWaveFiles(char * *,int),EqSoundManager__LoadListOfWaveFiles); +#endif +#ifdef EqSoundManager__WaveLoad_x +FUNCTION_AT_ADDRESS(void EqSoundManager::WaveLoad(char *,int,bool),EqSoundManager__WaveLoad); +#endif +#ifdef EqSoundManager__WaveIsPlaying_x +FUNCTION_AT_ADDRESS(bool EqSoundManager::WaveIsPlaying(int),EqSoundManager__WaveIsPlaying); +#endif +#ifdef EqSoundManager__WavePlay_x +FUNCTION_AT_ADDRESS(void EqSoundManager::WavePlay(int,class SoundControl *),EqSoundManager__WavePlay); +#endif +#ifdef EqSoundManager__WaveStop_x +FUNCTION_AT_ADDRESS(void EqSoundManager::WaveStop(int),EqSoundManager__WaveStop); +#endif +#ifdef EqSoundManager__WaveGet_x +FUNCTION_AT_ADDRESS(class SoundAsset * EqSoundManager::WaveGet(int),EqSoundManager__WaveGet); +#endif +#ifdef EqSoundManager__LoadGlobalMusic_x +FUNCTION_AT_ADDRESS(void EqSoundManager::LoadGlobalMusic(void),EqSoundManager__LoadGlobalMusic); +#endif +#ifdef EqSoundManager__SetMusicSelection_x +FUNCTION_AT_ADDRESS(void EqSoundManager::SetMusicSelection(int,bool),EqSoundManager__SetMusicSelection); +#endif +#ifdef EqSoundManager__GiveTime_x +FUNCTION_AT_ADDRESS(void EqSoundManager::GiveTime(void),EqSoundManager__GiveTime); +#endif +#ifdef EqSoundManager__SetCurrentZone_x +FUNCTION_AT_ADDRESS(void EqSoundManager::SetCurrentZone(char *),EqSoundManager__SetCurrentZone); +#endif +#ifdef FilePath__FilePath_x +FUNCTION_AT_ADDRESS( FilePath::FilePath(char const *),FilePath__FilePath); +#endif +#ifdef ShareBase__removeRef_x +FUNCTION_AT_ADDRESS(void ShareBase::removeRef(void),ShareBase__removeRef); +#endif +#ifdef SharedString__SharedString_x +FUNCTION_AT_ADDRESS( SharedString::SharedString(char const *),SharedString__SharedString); +#endif +#ifdef SharedString__operator_equal_x +FUNCTION_AT_ADDRESS(class SharedString & SharedString::operator=(class SharedString const &),SharedString__operator_equal); +#endif +#ifdef FilePath__dFilePath_x +FUNCTION_AT_ADDRESS( FilePath::~FilePath(void),FilePath__dFilePath); +#endif +#ifdef SharedString__dSharedString_x +FUNCTION_AT_ADDRESS( SharedString::~SharedString(void),SharedString__dSharedString); +#endif +#ifdef FilePath__FilePath1_x +FUNCTION_AT_ADDRESS( FilePath::FilePath(class SharedString const &),FilePath__FilePath1); +#endif +#ifdef EqSoundManager__LoadOldEmitters_x +FUNCTION_AT_ADDRESS(void EqSoundManager::LoadOldEmitters(void),EqSoundManager__LoadOldEmitters); +#endif +#ifdef EqSoundManager__CreateOldEmitter_x +//FUNCTION_AT_ADDRESS(class SoundEmitter * EqSoundManager::CreateOldEmitter(int,float,float,float,int,int,int,float,int,int,int),EqSoundManager__CreateOldEmitter); +#endif +#ifdef EqSoundManager__GetAsset_x +FUNCTION_AT_ADDRESS(class SoundAsset * EqSoundManager::GetAsset(char *),EqSoundManager__GetAsset); +#endif +#ifdef EqSoundManager__ReleaseZoneSpecificMidi_x +FUNCTION_AT_ADDRESS(void EqSoundManager::ReleaseZoneSpecificMidi(void),EqSoundManager__ReleaseZoneSpecificMidi); +#endif +#ifdef EqSoundManager__ReleaseZoneSpecificWaves_x +FUNCTION_AT_ADDRESS(void EqSoundManager::ReleaseZoneSpecificWaves(void),EqSoundManager__ReleaseZoneSpecificWaves); +#endif +#ifdef EqSoundManager__ReleaseZoneSpecificEmitters_x +FUNCTION_AT_ADDRESS(void EqSoundManager::ReleaseZoneSpecificEmitters(void),EqSoundManager__ReleaseZoneSpecificEmitters); +#endif +#ifdef EqSoundManager__SetEffectsLevel_x +FUNCTION_AT_ADDRESS(void EqSoundManager::SetEffectsLevel(float),EqSoundManager__SetEffectsLevel); +#endif +#ifdef EqSoundManager__SetMixAhead_x +FUNCTION_AT_ADDRESS(void EqSoundManager::SetMixAhead(int),EqSoundManager__SetMixAhead); +#endif +#ifdef EqSoundManager__SetWaveVolume_x +FUNCTION_AT_ADDRESS(void EqSoundManager::SetWaveVolume(float),EqSoundManager__SetWaveVolume); +#endif +#ifdef EqSoundManager__SetMusicVolume_x +FUNCTION_AT_ADDRESS(void EqSoundManager::SetMusicVolume(float),EqSoundManager__SetMusicVolume); +#endif +#ifdef EqSoundManager__GetListenerEnvironment_x +//FUNCTION_AT_ADDRESS(enum EnvironmentType EqSoundManager::GetListenerEnvironment(void),EqSoundManager__GetListenerEnvironment); +#endif +#ifdef EqSoundManager__SetListenerEnvironment_x +//FUNCTION_AT_ADDRESS(void EqSoundManager::SetListenerEnvironment(enum EnvironmentType),EqSoundManager__SetListenerEnvironment); +#endif +#ifdef EqSoundManager__SetListenerEnvironmentLow_x +FUNCTION_AT_ADDRESS(void EqSoundManager::SetListenerEnvironmentLow(void),EqSoundManager__SetListenerEnvironmentLow); +#endif +#ifdef EqSoundManager__SetListenerEnvironmentHigh_x +FUNCTION_AT_ADDRESS(void EqSoundManager::SetListenerEnvironmentHigh(void),EqSoundManager__SetListenerEnvironmentHigh); +#endif +#ifdef EqSoundManager__SetListenerEnvironmentOutside_x +FUNCTION_AT_ADDRESS(void EqSoundManager::SetListenerEnvironmentOutside(void),EqSoundManager__SetListenerEnvironmentOutside); +#endif +#ifdef EqSoundManager__SetListenerLocation_x +FUNCTION_AT_ADDRESS(void EqSoundManager::SetListenerLocation(float,float,float,float),EqSoundManager__SetListenerLocation); +#endif +#ifdef EqSoundManager__EmitterSetRaining_x +FUNCTION_AT_ADDRESS(void EqSoundManager::EmitterSetRaining(bool),EqSoundManager__EmitterSetRaining); +#endif +#ifdef EqSoundManager__EmitterSetWind_x +FUNCTION_AT_ADDRESS(void EqSoundManager::EmitterSetWind(bool),EqSoundManager__EmitterSetWind); +#endif +#ifdef EqSoundManager__EmitterSetNight_x +FUNCTION_AT_ADDRESS(void EqSoundManager::EmitterSetNight(bool),EqSoundManager__EmitterSetNight); +#endif +#ifdef EqSoundManager__EmitterSetUserDisabled_x +FUNCTION_AT_ADDRESS(void EqSoundManager::EmitterSetUserDisabled(bool),EqSoundManager__EmitterSetUserDisabled); +#endif +#ifdef EqSoundManager__EmitterSetIndoors_x +FUNCTION_AT_ADDRESS(void EqSoundManager::EmitterSetIndoors(bool),EqSoundManager__EmitterSetIndoors); +#endif +#ifdef EqSoundManager__UpdateEmitterStates_x +FUNCTION_AT_ADDRESS(void EqSoundManager::UpdateEmitterStates(void),EqSoundManager__UpdateEmitterStates); +#endif +#ifdef EqSoundManager__OldMp3ClearSelections_x +FUNCTION_AT_ADDRESS(void EqSoundManager::OldMp3ClearSelections(void),EqSoundManager__OldMp3ClearSelections); +#endif +#ifdef EqSoundManager__OldMp3Init_x +FUNCTION_AT_ADDRESS(void EqSoundManager::OldMp3Init(void),EqSoundManager__OldMp3Init); +#endif +#ifdef EqSoundManager__OldMp3Terminate_x +FUNCTION_AT_ADDRESS(void EqSoundManager::OldMp3Terminate(void),EqSoundManager__OldMp3Terminate); +#endif +#ifdef EqSoundManager__OldMp3GetSelection_x +FUNCTION_AT_ADDRESS(class SoundAsset * EqSoundManager::OldMp3GetSelection(int),EqSoundManager__OldMp3GetSelection); +#endif +#ifdef EqSoundManager__EmitterLoad_x +FUNCTION_AT_ADDRESS(bool EqSoundManager::EmitterLoad(char *),EqSoundManager__EmitterLoad); +#endif +#ifdef EqSoundManager__EmitterAdd_x +FUNCTION_AT_ADDRESS(void EqSoundManager::EmitterAdd(class EqEmitterData *),EqSoundManager__EmitterAdd); +#endif +#ifdef EqMobileEmitter__EqMobileEmitter_x +FUNCTION_AT_ADDRESS( EqMobileEmitter::EqMobileEmitter(class EqSoundManager *),EqMobileEmitter__EqMobileEmitter); +#endif +#ifdef EqMobileEmitter__dEqMobileEmitter_x +FUNCTION_AT_ADDRESS( EqMobileEmitter::~EqMobileEmitter(void),EqMobileEmitter__dEqMobileEmitter); +#endif +#ifdef EqMobileEmitter__Move_x +FUNCTION_AT_ADDRESS(void EqMobileEmitter::Move(float,float,float),EqMobileEmitter__Move); +#endif +#ifdef EqMobileEmitter__SetWave_x +FUNCTION_AT_ADDRESS(void EqMobileEmitter::SetWave(int,char *),EqMobileEmitter__SetWave); +#endif +#ifdef EqMobileEmitter__SetNpcHeight_x +FUNCTION_AT_ADDRESS(void EqMobileEmitter::SetNpcHeight(float),EqMobileEmitter__SetNpcHeight); +#endif +#ifdef EqEmitterData__EqEmitterData_x +FUNCTION_AT_ADDRESS( EqEmitterData::EqEmitterData(void),EqEmitterData__EqEmitterData); +#endif +#ifdef EqEmitterData__SetLoadString_x +FUNCTION_AT_ADDRESS(void EqEmitterData::SetLoadString(char *),EqEmitterData__SetLoadString); +#endif +#ifdef EQ_Spell__SpellUsesDragonBreathEffect_x +FUNCTION_AT_ADDRESS(int EQ_Spell::SpellUsesDragonBreathEffect(void),EQ_Spell__SpellUsesDragonBreathEffect); +#endif +#ifdef EQ_Spell__EQ_Spell_x +FUNCTION_AT_ADDRESS( EQ_Spell::EQ_Spell(char *),EQ_Spell__EQ_Spell); +#endif +#ifdef EQ_Spell__dEQ_Spell_x +FUNCTION_AT_ADDRESS( EQ_Spell::~EQ_Spell(void),EQ_Spell__dEQ_Spell); +#endif +#ifdef EQ_Spell__IsSPAIgnoredByStacking_x +FUNCTION_AT_ADDRESS(bool __cdecl EQ_Spell::IsSPAIgnoredByStacking(int),EQ_Spell__IsSPAIgnoredByStacking); +#endif +#ifdef EQ_Spell__SpellAffects_x +FUNCTION_AT_ADDRESS(unsigned char EQ_Spell::SpellAffects(int)const ,EQ_Spell__SpellAffects); +#endif +#ifdef EQ_Spell__IsPermIllusionSpell_x +FUNCTION_AT_ADDRESS(int EQ_Spell::IsPermIllusionSpell(void)const ,EQ_Spell__IsPermIllusionSpell); +#endif +#ifdef EQOldPlayerAnimation__InitAnimationData_x +FUNCTION_AT_ADDRESS(void __cdecl EQOldPlayerAnimation::InitAnimationData(void),EQOldPlayerAnimation__InitAnimationData); +#endif +#ifdef EQOldPlayerAnimation__PlayAttachmentAnimationTracks_x +FUNCTION_AT_ADDRESS(void EQOldPlayerAnimation::PlayAttachmentAnimationTracks(int,int,bool,bool,float,bool,unsigned char),EQOldPlayerAnimation__PlayAttachmentAnimationTracks); +#endif +#ifdef EQOldPlayerAnimation__EQOldPlayerAnimation_x +FUNCTION_AT_ADDRESS( EQOldPlayerAnimation::EQOldPlayerAnimation(class EQPlayer *),EQOldPlayerAnimation__EQOldPlayerAnimation); +#endif +#ifdef EQOldPlayerAnimation__InterruptCurrentAnimation_x +FUNCTION_AT_ADDRESS(bool EQOldPlayerAnimation::InterruptCurrentAnimation(int,unsigned char),EQOldPlayerAnimation__InterruptCurrentAnimation); +#endif +#ifdef EQOldPlayerAnimation__ChangeAttachmentAnimationTrackSpeeds_x +FUNCTION_AT_ADDRESS(void EQOldPlayerAnimation::ChangeAttachmentAnimationTrackSpeeds(bool,float),EQOldPlayerAnimation__ChangeAttachmentAnimationTrackSpeeds); +#endif +#ifdef EQOldPlayerAnimation__IsSocialAnimation_x +FUNCTION_AT_ADDRESS(bool EQOldPlayerAnimation::IsSocialAnimation(int),EQOldPlayerAnimation__IsSocialAnimation); +#endif +#ifdef EQOldPlayerAnimation__IsStandAnimation_x +FUNCTION_AT_ADDRESS(bool EQOldPlayerAnimation::IsStandAnimation(int),EQOldPlayerAnimation__IsStandAnimation); +#endif +#ifdef EQOldPlayerAnimation__IsIdleAnimation_x +FUNCTION_AT_ADDRESS(bool EQOldPlayerAnimation::IsIdleAnimation(int),EQOldPlayerAnimation__IsIdleAnimation); +#endif +#ifdef EQOldPlayerAnimation__AnimationIsAggressive_x +FUNCTION_AT_ADDRESS(bool EQOldPlayerAnimation::AnimationIsAggressive(int),EQOldPlayerAnimation__AnimationIsAggressive); +#endif +#ifdef EQAnimation__EQAnimation_x +FUNCTION_AT_ADDRESS( EQAnimation::EQAnimation(void),EQAnimation__EQAnimation); +#endif +#ifdef EQPlayer__DoCamAi_x +FUNCTION_AT_ADDRESS(void EQPlayer::DoCamAi(void),EQPlayer__DoCamAi); +#endif +#ifdef CVector3__Normalize_x +FUNCTION_AT_ADDRESS(void CVector3::Normalize(void),CVector3__Normalize); +#endif +#ifdef CVector3__GetLength_x +FUNCTION_AT_ADDRESS(float CVector3::GetLength(void)const ,CVector3__GetLength); +#endif +#ifdef CVector3__NormalizeAndReturnLength_x +FUNCTION_AT_ADDRESS(float CVector3::NormalizeAndReturnLength(void),CVector3__NormalizeAndReturnLength); +#endif +#ifdef EQEffect__EQEffect_x +FUNCTION_AT_ADDRESS( EQEffect::EQEffect(class EQEffect *,char *,int,struct _EQLOC *,class EQPlayer *,class EQMissile *,struct _EQRGB *,float,int,int,float,float),EQEffect__EQEffect); +#endif +#ifdef EQEffect__dEQEffect_x +FUNCTION_AT_ADDRESS( EQEffect::~EQEffect(void),EQEffect__dEQEffect); +#endif +#ifdef CEverQuest__msgStartIcon_x +FUNCTION_AT_ADDRESS(int CEverQuest::msgStartIcon(void *),CEverQuest__msgStartIcon); +#endif +#ifdef CEverQuest__msgStartInotes_x +FUNCTION_AT_ADDRESS(int CEverQuest::msgStartInotes(void *),CEverQuest__msgStartInotes); +#endif +#ifdef CEverQuest__msgStartIeq_x +FUNCTION_AT_ADDRESS(int CEverQuest::msgStartIeq(void *),CEverQuest__msgStartIeq); +#endif +#ifdef CEverQuest__HandleItems_x +FUNCTION_AT_ADDRESS(int CEverQuest::HandleItems(void *,int),CEverQuest__HandleItems); +#endif +#ifdef CEverQuest__HandleWorldMessage_x +FUNCTION_AT_ADDRESS(unsigned char CEverQuest::HandleWorldMessage(struct connection_t *,unsigned __int32,char *,unsigned __int32),CEverQuest__HandleWorldMessage); +#endif +#ifdef EQHSprite__EQHSprite_x +FUNCTION_AT_ADDRESS( EQHSprite::EQHSprite(char *,struct T3D_tagACTORINSTANCE *,class EQPlayer *),EQHSprite__EQHSprite); +#endif +#ifdef EQHSprite__dEQHSprite_x +FUNCTION_AT_ADDRESS( EQHSprite::~EQHSprite(void),EQHSprite__dEQHSprite); +#endif +#ifdef EQHSprite__get_object_x +FUNCTION_AT_ADDRESS(class EQHSprite * EQHSprite::get_object(char *),EQHSprite__get_object); +#endif +#ifdef EQHSprite__GetAnimationTrackPtr_x +FUNCTION_AT_ADDRESS(bool EQHSprite::GetAnimationTrackPtr(char *,char *,int,int,unsigned char,int),EQHSprite__GetAnimationTrackPtr); +#endif +#ifdef EQItemList__EQItemList_x +FUNCTION_AT_ADDRESS( EQItemList::EQItemList(void),EQItemList__EQItemList); +#endif +#ifdef EQItemList__dEQItemList_x +FUNCTION_AT_ADDRESS( EQItemList::~EQItemList(void),EQItemList__dEQItemList); +#endif +#ifdef EQItemList__get_item_x +FUNCTION_AT_ADDRESS(class EQItemList * EQItemList::get_item(long),EQItemList__get_item); +#endif +#ifdef EQItemList__is_item_actor_x +FUNCTION_AT_ADDRESS(class EQItemList * EQItemList::is_item_actor(struct T3D_tagACTORINSTANCE *),EQItemList__is_item_actor); +#endif +#ifdef public_key__dpublic_key_x +FUNCTION_AT_ADDRESS( public_key::~public_key(void),public_key__dpublic_key); +#endif +#ifdef public_key__public_key_x +FUNCTION_AT_ADDRESS( public_key::public_key(void),public_key__public_key); +#endif +#ifdef PacketPackerManager__Initialize_x +FUNCTION_AT_ADDRESS(void __cdecl PacketPackerManager::Initialize(void),PacketPackerManager__Initialize); +#endif +#ifdef EQMissile__EQMissile_x +FUNCTION_AT_ADDRESS( EQMissile::EQMissile(class EQ_Equipment *,class EQPlayer *,class EQMissile *,char *,unsigned char,unsigned int),EQMissile__EQMissile); +#endif +#ifdef EQMissile__dEQMissile_x +FUNCTION_AT_ADDRESS( EQMissile::~EQMissile(void),EQMissile__dEQMissile); +#endif +#ifdef EQMissile__CleanUpMyEffects_x +FUNCTION_AT_ADDRESS(void EQMissile::CleanUpMyEffects(void),EQMissile__CleanUpMyEffects); +#endif +#ifdef EQMissile__is_missile_actor_x +FUNCTION_AT_ADDRESS(class EQMissile * EQMissile::is_missile_actor(struct T3D_tagACTORINSTANCE *),EQMissile__is_missile_actor); +#endif +#ifdef EQMissile__HitActor_x +FUNCTION_AT_ADDRESS(void EQMissile::HitActor(struct T3D_tagACTORINSTANCE *,bool),EQMissile__HitActor); +#endif +#ifdef EQMissile__ProcessMissile_x +FUNCTION_AT_ADDRESS(void EQMissile::ProcessMissile(void),EQMissile__ProcessMissile); +#endif +#ifdef EQMissile__MissileAI_x +FUNCTION_AT_ADDRESS(void EQMissile::MissileAI(void),EQMissile__MissileAI); +#endif +#ifdef EQMoneyList__EQMoneyList_x +FUNCTION_AT_ADDRESS( EQMoneyList::EQMoneyList(void),EQMoneyList__EQMoneyList); +#endif +#ifdef EQMoneyList__dEQMoneyList_x +FUNCTION_AT_ADDRESS( EQMoneyList::~EQMoneyList(void),EQMoneyList__dEQMoneyList); +#endif +#ifdef EQMoneyList__get_money_x +FUNCTION_AT_ADDRESS(class EQMoneyList * EQMoneyList::get_money(long),EQMoneyList__get_money); +#endif +#ifdef CDisplay__MoveMissile_x +FUNCTION_AT_ADDRESS(int CDisplay::MoveMissile(class EQMissile *),CDisplay__MoveMissile); +#endif +#ifdef CDisplay__GetOnActor_x +FUNCTION_AT_ADDRESS(void CDisplay::GetOnActor(struct T3D_tagACTORINSTANCE *,class EQPlayer *),CDisplay__GetOnActor); +#endif +#ifdef EQPlayer__CanIFitHere_x +FUNCTION_AT_ADDRESS(bool EQPlayer::CanIFitHere(float,float,float),EQPlayer__CanIFitHere); +#endif +#ifdef EQPlayer__MovePlayer_x +FUNCTION_AT_ADDRESS(int EQPlayer::MovePlayer(void),EQPlayer__MovePlayer); +#endif +#ifdef bad_word_class__bad_word_class_x +FUNCTION_AT_ADDRESS( bad_word_class::bad_word_class(char *),bad_word_class__bad_word_class); +#endif +#ifdef EQObject__EQObject_x +FUNCTION_AT_ADDRESS( EQObject::EQObject(class EQObject *,class EQPlayer *,char *,char *),EQObject__EQObject); +#endif +#ifdef EQObject__dEQObject_x +FUNCTION_AT_ADDRESS( EQObject::~EQObject(void),EQObject__dEQObject); +#endif +#ifdef EQPlayer__EQPlayer_x +FUNCTION_AT_ADDRESS( EQPlayer::EQPlayer(class EQPlayer *,unsigned char,unsigned int,unsigned char,char *),EQPlayer__EQPlayer); +#endif +#ifdef EQPlayer__dEQPlayer_x +FUNCTION_AT_ADDRESS( EQPlayer::~EQPlayer(void),EQPlayer__dEQPlayer); +#endif +#ifdef EQPlayer__ResetVariables_x +FUNCTION_AT_ADDRESS(void EQPlayer::ResetVariables(void),EQPlayer__ResetVariables); +#endif +#ifdef EQPlayer__do_change_form_x +FUNCTION_AT_ADDRESS(void EQPlayer::do_change_form(struct chngForm *),EQPlayer__do_change_form); +#endif +#ifdef EQPlayer__DisplayWeaponsAndArmor_x +FUNCTION_AT_ADDRESS(void EQPlayer::DisplayWeaponsAndArmor(void),EQPlayer__DisplayWeaponsAndArmor); +#endif +#ifdef EQPlayer__CleanUpTarget_x +FUNCTION_AT_ADDRESS(void EQPlayer::CleanUpTarget(void),EQPlayer__CleanUpTarget); +#endif +#ifdef EQPlayer__FollowPlayerAI_x +FUNCTION_AT_ADDRESS(void EQPlayer::FollowPlayerAI(void),EQPlayer__FollowPlayerAI); +#endif +#ifdef EQPlayer__TurnOffAutoFollow_x +FUNCTION_AT_ADDRESS(void EQPlayer::TurnOffAutoFollow(void),EQPlayer__TurnOffAutoFollow); +#endif +#ifdef EQPlayer__AimAtTarget_x +FUNCTION_AT_ADDRESS(int EQPlayer::AimAtTarget(class EQPlayer *,class EQMissile *),EQPlayer__AimAtTarget); +#endif +#ifdef EQPlayer__FacePlayer_x +FUNCTION_AT_ADDRESS(void EQPlayer::FacePlayer(class EQPlayer *),EQPlayer__FacePlayer); +#endif +#ifdef EQPlayer__CleanUpVehicle_x +FUNCTION_AT_ADDRESS(void EQPlayer::CleanUpVehicle(void),EQPlayer__CleanUpVehicle); +#endif +#ifdef EQPlayer__CleanUpMyEffects_x +FUNCTION_AT_ADDRESS(void EQPlayer::CleanUpMyEffects(void),EQPlayer__CleanUpMyEffects); +#endif +#ifdef EQPlayer__GetPlayerFromName_x +FUNCTION_AT_ADDRESS(class EQPlayer *__cdecl EQPlayer::GetPlayerFromName(char const *),EQPlayer__GetPlayerFromName); +#endif +#ifdef EQPlayer__GetPlayerFromPartialName_x +FUNCTION_AT_ADDRESS(class EQPlayer * __cdecl EQPlayer::GetPlayerFromPartialName(char *),EQPlayer__GetPlayerFromPartialName); +#endif +#ifdef EQPlayer__GetClosestPlayerFromPartialName_x +FUNCTION_AT_ADDRESS(class EQPlayer * __cdecl EQPlayer::GetClosestPlayerFromPartialName(char *,class EQPlayer *),EQPlayer__GetClosestPlayerFromPartialName); +#endif +#ifdef EQPlayer__IsPlayerActor_x +FUNCTION_AT_ADDRESS(class EQPlayer * __cdecl EQPlayer::IsPlayerActor(struct T3D_tagACTORINSTANCE *),EQPlayer__IsPlayerActor); +#endif +#ifdef EQPlayer__TackOnNeuterChar_x +FUNCTION_AT_ADDRESS(void __cdecl EQPlayer::TackOnNeuterChar(char *,unsigned int),EQPlayer__TackOnNeuterChar); +#endif +#ifdef EQPlayer__GetActorTag_x +FUNCTION_AT_ADDRESS(void EQPlayer::GetActorTag(char *),EQPlayer__GetActorTag); +#endif +#ifdef EQPlayer__GetPCActorTag_x +FUNCTION_AT_ADDRESS(void __cdecl EQPlayer::GetPCActorTag(char *,unsigned int,unsigned char),EQPlayer__GetPCActorTag); +#endif +#ifdef EQPlayer__NotOnSameDeity_x +FUNCTION_AT_ADDRESS(int EQPlayer::NotOnSameDeity(class EQPlayer *,class EQ_Spell *),EQPlayer__NotOnSameDeity); +#endif +#ifdef EQPlayer__SetAnimVariation_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetAnimVariation(void),EQPlayer__SetAnimVariation); +#endif +#ifdef EQPlayer__SetAfk_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetAfk(int),EQPlayer__SetAfk); +#endif +#ifdef EQPlayer__AllowedToAttack_x +FUNCTION_AT_ADDRESS(bool EQPlayer::AllowedToAttack(class EQPlayer *,int),EQPlayer__AllowedToAttack); +#endif +#ifdef EQPlayer__CanIHit_x +FUNCTION_AT_ADDRESS(bool EQPlayer::CanIHit(class EQPlayer *,float),EQPlayer__CanIHit); +#endif +#ifdef EQPlayer__ModifyAttackSpeed_x +FUNCTION_AT_ADDRESS(unsigned int EQPlayer::ModifyAttackSpeed(unsigned int,int),EQPlayer__ModifyAttackSpeed); +#endif +#ifdef EQPlayer__DoAttack_x +FUNCTION_AT_ADDRESS(int EQPlayer::DoAttack(unsigned char,unsigned char,class EQPlayer *),EQPlayer__DoAttack); +#endif +#ifdef EQPlayer__HandleAmmo_x +FUNCTION_AT_ADDRESS(unsigned char EQPlayer::HandleAmmo(void),EQPlayer__HandleAmmo); +#endif +#ifdef EQPlayer__TriggerSpellEffect_x +FUNCTION_AT_ADDRESS(void EQPlayer::TriggerSpellEffect(struct _EQMissileHitinfo *),EQPlayer__TriggerSpellEffect); +#endif +#ifdef EQPlayer__IWasHit_x +FUNCTION_AT_ADDRESS(bool EQPlayer::IWasHit(struct _EQMissileHitinfo *),EQPlayer__IWasHit); +#endif +#ifdef EQPlayer__GetConscious_x +FUNCTION_AT_ADDRESS(void EQPlayer::GetConscious(void),EQPlayer__GetConscious); +#endif +#ifdef EQPlayer__KnockedOut_x +FUNCTION_AT_ADDRESS(void EQPlayer::KnockedOut(void),EQPlayer__KnockedOut); +#endif +#ifdef EQPlayer__IDied_x +FUNCTION_AT_ADDRESS(void EQPlayer::IDied(struct _EQPlayerDeath *),EQPlayer__IDied); +#endif +#ifdef EQPlayer__HandoverControlToZoneserver_x +FUNCTION_AT_ADDRESS(void EQPlayer::HandoverControlToZoneserver(void),EQPlayer__HandoverControlToZoneserver); +#endif +#ifdef EQPlayer__TouchingSwitch_x +FUNCTION_AT_ADDRESS(void EQPlayer::TouchingSwitch(void),EQPlayer__TouchingSwitch); +#endif +#ifdef EQPlayer__MyFeetAreOnGround_x +FUNCTION_AT_ADDRESS(bool EQPlayer::MyFeetAreOnGround(void),EQPlayer__MyFeetAreOnGround); +#endif +#ifdef EQPlayer__IHaveFallen_x +FUNCTION_AT_ADDRESS(void EQPlayer::IHaveFallen(float),EQPlayer__IHaveFallen); +#endif +#ifdef EQPlayer__SkillUsed_x +FUNCTION_AT_ADDRESS(unsigned char EQPlayer::SkillUsed(unsigned char),EQPlayer__SkillUsed); +#endif +#ifdef EQPlayer__BodyEnvironmentChange_x +FUNCTION_AT_ADDRESS(void EQPlayer::BodyEnvironmentChange(unsigned char),EQPlayer__BodyEnvironmentChange); +#endif +#ifdef EQPlayer__FeetEnvironmentChange_x +FUNCTION_AT_ADDRESS(void EQPlayer::FeetEnvironmentChange(unsigned char),EQPlayer__FeetEnvironmentChange); +#endif +#ifdef EQPlayer__HeadEnvironmentChange_x +FUNCTION_AT_ADDRESS(void EQPlayer::HeadEnvironmentChange(unsigned char),EQPlayer__HeadEnvironmentChange); +#endif +#ifdef EQPlayer__LegalPlayerRace_x +FUNCTION_AT_ADDRESS(int EQPlayer::LegalPlayerRace(int),EQPlayer__LegalPlayerRace); +#endif +#ifdef EQPlayer__DeleteMyMissiles_x +FUNCTION_AT_ADDRESS(void EQPlayer::DeleteMyMissiles(void),EQPlayer__DeleteMyMissiles); +#endif +#ifdef EQPlayer__ChangePosition_x +FUNCTION_AT_ADDRESS(void EQPlayer::ChangePosition(unsigned char),EQPlayer__ChangePosition); +#endif +#ifdef EQPlayer__ChangeHeight_x +FUNCTION_AT_ADDRESS(void EQPlayer::ChangeHeight(float),EQPlayer__ChangeHeight); +#endif +#ifdef EQPlayer__PositionOnFloor_x +FUNCTION_AT_ADDRESS(void EQPlayer::PositionOnFloor(void),EQPlayer__PositionOnFloor); +#endif +#ifdef EQPlayer__IsRoleplaying_x +FUNCTION_AT_ADDRESS(bool EQPlayer::IsRoleplaying(void),EQPlayer__IsRoleplaying); +#endif +#ifdef EQPlayer__IsInvited_x +FUNCTION_AT_ADDRESS(bool EQPlayer::IsInvited(void),EQPlayer__IsInvited); +#endif +#ifdef EQPlayer__SetInvited_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetInvited(bool),EQPlayer__SetInvited); +#endif +#ifdef EQPlayer__PlaySoundA_x +FUNCTION_AT_ADDRESS(void EQPlayer::PlaySoundA(int),EQPlayer__PlaySoundA); +#endif +#ifdef EQPlayer__SetSounds_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetSounds(void),EQPlayer__SetSounds); +#endif +#ifdef EQPlayer__SetCurrentLoopSound_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetCurrentLoopSound(int),EQPlayer__SetCurrentLoopSound); +#endif +#ifdef EQPlayer__IsFlyer_x +FUNCTION_AT_ADDRESS(bool EQPlayer::IsFlyer(void),EQPlayer__IsFlyer); +#endif +#ifdef EQPlayer__InitSneakMod_x +FUNCTION_AT_ADDRESS(void EQPlayer::InitSneakMod(void),EQPlayer__InitSneakMod); +#endif +#ifdef EQPlayer__SetHeights_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetHeights(void),EQPlayer__SetHeights); +#endif +#ifdef EQPMInfo__SetApplyGravity_x +FUNCTION_AT_ADDRESS(void EQPMInfo::SetApplyGravity(bool),EQPMInfo__SetApplyGravity); +#endif +#ifdef EQPlayer__GetDefaultHeight_x +FUNCTION_AT_ADDRESS(float EQPlayer::GetDefaultHeight(int,unsigned char),EQPlayer__GetDefaultHeight); +#endif +#ifdef EQPlayer__ComputeSpecialHeights_x +FUNCTION_AT_ADDRESS(void __cdecl EQPlayer::ComputeSpecialHeights(int,float *,float *,float *,float *,bool),EQPlayer__ComputeSpecialHeights); +#endif +#ifdef EQPlayer__IsUntexturedHorse_x +FUNCTION_AT_ADDRESS(bool EQPlayer::IsUntexturedHorse(void),EQPlayer__IsUntexturedHorse); +#endif +#ifdef EQPlayer__HasInvalidRiderTexture_x +FUNCTION_AT_ADDRESS(bool const EQPlayer::HasInvalidRiderTexture(void)const ,EQPlayer__HasInvalidRiderTexture); +#endif +#ifdef EQPlayer__ForceInvisible_x +FUNCTION_AT_ADDRESS(void EQPlayer::ForceInvisible(bool),EQPlayer__ForceInvisible); +#endif +#ifdef EQPlayer__MountableRace_x +FUNCTION_AT_ADDRESS(int EQPlayer::MountableRace(void),EQPlayer__MountableRace); +#endif +#ifdef EQPlayer__MakeRiderMountUp_x +FUNCTION_AT_ADDRESS(void EQPlayer::MakeRiderMountUp(void),EQPlayer__MakeRiderMountUp); +#endif +#ifdef EQPlayer__MountEQPlayer_x +FUNCTION_AT_ADDRESS(void EQPlayer::MountEQPlayer(class EQPlayer *),EQPlayer__MountEQPlayer); +#endif +#ifdef EQPlayer__Dismount_x +FUNCTION_AT_ADDRESS(void EQPlayer::Dismount(void),EQPlayer__Dismount); +#endif +#ifdef EQPlayer__GetArmorType_x +FUNCTION_AT_ADDRESS(int EQPlayer::GetArmorType(int),EQPlayer__GetArmorType); +#endif +#ifdef EQPlayer__SetArmorType_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetArmorType(int,int),EQPlayer__SetArmorType); +#endif +#ifdef EQPlayer__GetArmorTint_x +FUNCTION_AT_ADDRESS(unsigned long EQPlayer::GetArmorTint(int),EQPlayer__GetArmorTint); +#endif +#ifdef EQPlayer__SetArmorTint_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetArmorTint(int,unsigned long),EQPlayer__SetArmorTint); +#endif +#ifdef EQPlayer__SetAccel_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetAccel(float,int),EQPlayer__SetAccel); +#endif +#ifdef EQPlayer__SetToRandomRace_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetToRandomRace(void),EQPlayer__SetToRandomRace); +#endif +#ifdef EQPlayer__GetBaseFaceNbr_x +FUNCTION_AT_ADDRESS(unsigned char EQPlayer::GetBaseFaceNbr(int,unsigned char *),EQPlayer__GetBaseFaceNbr); +#endif +#ifdef EQPlayer__HasAttachedBeard_x +FUNCTION_AT_ADDRESS(unsigned char EQPlayer::HasAttachedBeard(void),EQPlayer__HasAttachedBeard); +#endif +#ifdef EQPlayer__HasAttachedHair_x +FUNCTION_AT_ADDRESS(unsigned char EQPlayer::HasAttachedHair(void),EQPlayer__HasAttachedHair); +#endif +#ifdef EQPlayer__SetDefaultFacialFeaturesByFace_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetDefaultFacialFeaturesByFace(int,unsigned char,unsigned char),EQPlayer__SetDefaultFacialFeaturesByFace); +#endif +#ifdef EQPlayer__GetAllowedHairColorIndexRange_x +FUNCTION_AT_ADDRESS(void EQPlayer::GetAllowedHairColorIndexRange(int,int *,int *),EQPlayer__GetAllowedHairColorIndexRange); +#endif +#ifdef EQPlayer__CanBeBald_x +FUNCTION_AT_ADDRESS(int EQPlayer::CanBeBald(void),EQPlayer__CanBeBald); +#endif +#ifdef EQPlayer__ChangeNoGravity_x +FUNCTION_AT_ADDRESS(void EQPlayer::ChangeNoGravity(int),EQPlayer__ChangeNoGravity); +#endif +#ifdef EQPlayer__IdUsed_x +FUNCTION_AT_ADDRESS(int EQPlayer::IdUsed(unsigned int),EQPlayer__IdUsed); +#endif +#ifdef EQPlayer__GetUnusedID_x +FUNCTION_AT_ADDRESS(unsigned int EQPlayer::GetUnusedID(void),EQPlayer__GetUnusedID); +#endif +#ifdef EQPlayer__SetAndReserveID_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetAndReserveID(unsigned int),EQPlayer__SetAndReserveID); +#endif +#ifdef EQPlayer__InitializeIDArray_x +FUNCTION_AT_ADDRESS(void EQPlayer::InitializeIDArray(void),EQPlayer__InitializeIDArray); +#endif +#ifdef EQPlayer__Levitating_x +FUNCTION_AT_ADDRESS(int EQPlayer::Levitating(void),EQPlayer__Levitating); +#endif +#ifdef EQPlayer__SetRace_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetRace(int),EQPlayer__SetRace); +#endif +#ifdef EQPlayer__CanChangeForm_x +FUNCTION_AT_ADDRESS(bool EQPlayer::CanChangeForm(int,unsigned char),EQPlayer__CanChangeForm); +#endif +#ifdef EQPlayer__SetNameSpriteState_x +FUNCTION_AT_ADDRESS(int EQPlayer::SetNameSpriteState(bool),EQPlayer__SetNameSpriteState); +#endif +#ifdef EQPlayer__ChangeBoneStringSprite_x +FUNCTION_AT_ADDRESS(struct S3D_STRINGSPRITE * EQPlayer::ChangeBoneStringSprite(struct T3D_DAG *,char *),EQPlayer__ChangeBoneStringSprite); +#endif +#ifdef EQPlayer__SetNameSpriteTint_x +FUNCTION_AT_ADDRESS(bool EQPlayer::SetNameSpriteTint(void),EQPlayer__SetNameSpriteTint); +#endif +#ifdef EQPlayer__UpdateNameSprite_x +FUNCTION_AT_ADDRESS(void EQPlayer::UpdateNameSprite(void),EQPlayer__UpdateNameSprite); +#endif +#ifdef EQPlayer__UpdateBonePointers_x +FUNCTION_AT_ADDRESS(void EQPlayer::UpdateBonePointers(void),EQPlayer__UpdateBonePointers); +#endif +#ifdef EQPlayer__FindDefaultEyeMaterialIndexes_x +FUNCTION_AT_ADDRESS(void EQPlayer::FindDefaultEyeMaterialIndexes(void),EQPlayer__FindDefaultEyeMaterialIndexes); +#endif +#ifdef EQPlayer__CalcAnimLength_x +FUNCTION_AT_ADDRESS(unsigned int EQPlayer::CalcAnimLength(int),EQPlayer__CalcAnimLength); +#endif +#ifdef EQPlayer__GetAlternateTrackNumber_x +FUNCTION_AT_ADDRESS(int EQPlayer::GetAlternateTrackNumber(int,unsigned char *),EQPlayer__GetAlternateTrackNumber); +#endif +#ifdef EQPlayer__GetAlternateAnimVariation_x +FUNCTION_AT_ADDRESS(unsigned char EQPlayer::GetAlternateAnimVariation(int,unsigned char),EQPlayer__GetAlternateAnimVariation); +#endif +#ifdef EQPlayer__GetRaceSexITOffset_x +FUNCTION_AT_ADDRESS(int EQPlayer::GetRaceSexITOffset(void),EQPlayer__GetRaceSexITOffset); +#endif +#ifdef EQPlayer__UpdatePlayerVisibility_x +FUNCTION_AT_ADDRESS(void EQPlayer::UpdatePlayerVisibility(void),EQPlayer__UpdatePlayerVisibility); +#endif +#ifdef EQPlayer__UpdateAllPlayersVisibility_x +FUNCTION_AT_ADDRESS(void __cdecl EQPlayer::UpdateAllPlayersVisibility(void),EQPlayer__UpdateAllPlayersVisibility); +#endif +#ifdef EQPlayer__IsBodyType_j_x +FUNCTION_AT_ADDRESS(bool EQPlayer::IsBodyType(unsigned int,int,int),EQPlayer__IsBodyType_j); +#endif +#ifdef EQPlayer__SetEyeMaterial_x +FUNCTION_AT_ADDRESS(int EQPlayer::SetEyeMaterial(unsigned char,int),EQPlayer__SetEyeMaterial); +#endif +#ifdef EQPlayer__HideOrShowAttachedHair_x +FUNCTION_AT_ADDRESS(void EQPlayer::HideOrShowAttachedHair(void),EQPlayer__HideOrShowAttachedHair); +#endif +#ifdef EQPlayer__SetFHEB_x +FUNCTION_AT_ADDRESS(int EQPlayer::SetFHEB(unsigned char,unsigned char),EQPlayer__SetFHEB); +#endif +#ifdef EQPlayer__SetFHEB_Color_x +FUNCTION_AT_ADDRESS(int EQPlayer::SetFHEB_Color(unsigned char,unsigned char),EQPlayer__SetFHEB_Color); +#endif +#ifdef EQPlayer__SetHairOrBeard_x +FUNCTION_AT_ADDRESS(int EQPlayer::SetHairOrBeard(int),EQPlayer__SetHairOrBeard); +#endif +#ifdef EQPlayer__GetBonePointerByITS_x +FUNCTION_AT_ADDRESS(struct T3D_DAG * EQPlayer::GetBonePointerByITS(int,int),EQPlayer__GetBonePointerByITS); +#endif +#ifdef EQPlayer__UpdateAppearance_x +FUNCTION_AT_ADDRESS(void EQPlayer::UpdateAppearance(void),EQPlayer__UpdateAppearance); +#endif +#ifdef EQPlayer__SetDefaultITAttachments_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetDefaultITAttachments(int),EQPlayer__SetDefaultITAttachments); +#endif +#ifdef EQPlayer__SwapMaterial_x +FUNCTION_AT_ADDRESS(int EQPlayer::SwapMaterial(int,int,int,int,unsigned char),EQPlayer__SwapMaterial); +#endif +#ifdef EQPlayer__SwapFace_x +FUNCTION_AT_ADDRESS(int EQPlayer::SwapFace(int,int),EQPlayer__SwapFace); +#endif +#ifdef EQPlayer__GetAttachedHelmITNum_x +FUNCTION_AT_ADDRESS(int EQPlayer::GetAttachedHelmITNum(int,int *),EQPlayer__GetAttachedHelmITNum); +#endif +#ifdef EQPlayer__SetPlayerConstantAmbient_x +FUNCTION_AT_ADDRESS(void EQPlayer::SetPlayerConstantAmbient(struct T3D_RGB *),EQPlayer__SetPlayerConstantAmbient); +#endif +#ifdef EQPlayer__SwapHead_x +FUNCTION_AT_ADDRESS(int EQPlayer::SwapHead(int,int,unsigned long,int),EQPlayer__SwapHead); +#endif +#ifdef EQPlayer__SetPlayerPitchType_x +FUNCTION_AT_ADDRESS(int EQPlayer::SetPlayerPitchType(void),EQPlayer__SetPlayerPitchType); +#endif +#ifdef EQPlayer__IsValidTeleport_x +FUNCTION_AT_ADDRESS(int EQPlayer::IsValidTeleport(float,float,float,float,float),EQPlayer__IsValidTeleport); +#endif +#ifdef EQPlayer__ReplaceSpecialCloakMaterials_x +FUNCTION_AT_ADDRESS(int EQPlayer::ReplaceSpecialCloakMaterials(void),EQPlayer__ReplaceSpecialCloakMaterials); +#endif +#ifdef EQPlayer__SwapBody_x +FUNCTION_AT_ADDRESS(int EQPlayer::SwapBody(int,int),EQPlayer__SwapBody); +#endif +#ifdef EQPlayer__HandleMaterialEx_x +FUNCTION_AT_ADDRESS(void EQPlayer::HandleMaterialEx(int,unsigned int,unsigned int,unsigned long,int),EQPlayer__HandleMaterialEx); +#endif +#ifdef EQPlayer__UpdateItemSlot_x +FUNCTION_AT_ADDRESS(unsigned char EQPlayer::UpdateItemSlot(unsigned char,char *,int),EQPlayer__UpdateItemSlot); +#endif +#ifdef EQPlayer__SwapNPCMaterials_x +FUNCTION_AT_ADDRESS(int EQPlayer::SwapNPCMaterials(void),EQPlayer__SwapNPCMaterials); +#endif +#ifdef EQPlayer__PutPlayerOnFloor_x +FUNCTION_AT_ADDRESS(void EQPlayer::PutPlayerOnFloor(void),EQPlayer__PutPlayerOnFloor); +#endif +#ifdef EQPlayer__CheckForUnderFloor_x +FUNCTION_AT_ADDRESS(void EQPlayer::CheckForUnderFloor(void),EQPlayer__CheckForUnderFloor); +#endif +#ifdef EQPlayer__DoFloorCheck_x +FUNCTION_AT_ADDRESS(void EQPlayer::DoFloorCheck(void),EQPlayer__DoFloorCheck); +#endif +#ifdef EQPlayer__DoSwimJump_x +FUNCTION_AT_ADDRESS(void EQPlayer::DoSwimJump(unsigned char),EQPlayer__DoSwimJump); +#endif +#ifdef EQPlayer__PushAlongHeading_x +FUNCTION_AT_ADDRESS(void EQPlayer::PushAlongHeading(float),EQPlayer__PushAlongHeading); +#endif +#ifdef EQPlayer__DoTeleport_x +FUNCTION_AT_ADDRESS(unsigned char EQPlayer::DoTeleport(char *,int),EQPlayer__DoTeleport); +#endif +#ifdef EQPlayer__DoTeleportB_x +//FUNCTION_AT_ADDRESS(unsigned char EQPlayer::DoTeleportB(int,float,float,float,float,char *,enum ZONE_REQ_REASON),EQPlayer__DoTeleportB); +#endif +#ifdef EQPlayer__ChangeLight_x +FUNCTION_AT_ADDRESS(void EQPlayer::ChangeLight(void),EQPlayer__ChangeLight); +#endif +#ifdef EQPlayer__GetBoneCoords_x +FUNCTION_AT_ADDRESS(bool EQPlayer::GetBoneCoords(struct T3D_DAG *,struct _EQLOC *),EQPlayer__GetBoneCoords); +#endif +#ifdef EQPlayer__CheckForJump_x +FUNCTION_AT_ADDRESS(int EQPlayer::CheckForJump(void),EQPlayer__CheckForJump); +#endif +#ifdef EQPlayer__GetPlayerFloorHeight_x +FUNCTION_AT_ADDRESS(float EQPlayer::GetPlayerFloorHeight(float,float,float,unsigned char),EQPlayer__GetPlayerFloorHeight); +#endif +#ifdef EQPlayer__UpdatePlayerActor_x +FUNCTION_AT_ADDRESS(bool EQPlayer::UpdatePlayerActor(void),EQPlayer__UpdatePlayerActor); +#endif +#ifdef EQPlayer__GetNearestActorTag_x +FUNCTION_AT_ADDRESS(unsigned char EQPlayer::GetNearestActorTag(char *,void *),EQPlayer__GetNearestActorTag); +#endif +#ifdef EQPlayer__DoItemSlot_x +FUNCTION_AT_ADDRESS(void EQPlayer::DoItemSlot(int),EQPlayer__DoItemSlot); +#endif +#ifdef EQPlayer__DoClassRandomAnimation_x +FUNCTION_AT_ADDRESS(void EQPlayer::DoClassRandomAnimation(void),EQPlayer__DoClassRandomAnimation); +#endif +#ifdef EQPlayer__CreateUserLight_x +FUNCTION_AT_ADDRESS(struct T3D_POINTLIGHT * EQPlayer::CreateUserLight(struct T3D_LIGHTDEFINITION *,int),EQPlayer__CreateUserLight); +#endif +#ifdef EQPlayer__AttachPlayerToPlayerBone_x +FUNCTION_AT_ADDRESS(int EQPlayer::AttachPlayerToPlayerBone(class EQPlayer *,struct T3D_DAG *),EQPlayer__AttachPlayerToPlayerBone); +#endif +#ifdef EQPlayer__IsInvisible_x +FUNCTION_AT_ADDRESS(bool EQPlayer::IsInvisible(class EQPlayer *),EQPlayer__IsInvisible); +#endif +#ifdef EQPlayer__IsAMount_x +FUNCTION_AT_ADDRESS(bool EQPlayer::IsAMount(void),EQPlayer__IsAMount); +#endif +#ifdef EQPlayerManager__GetSpawnByID_x +FUNCTION_AT_ADDRESS(class EQPlayer * EQPlayerManager::GetSpawnByID(int),EQPlayerManager__GetSpawnByID); +#endif +#ifdef EQPlayerManager__GetSpawnByName_x +FUNCTION_AT_ADDRESS(class EQPlayer * EQPlayerManager::GetSpawnByName(char *),EQPlayerManager__GetSpawnByName); +#endif +#ifdef EQPMInfo__EQPMInfo_x +FUNCTION_AT_ADDRESS( EQPMInfo::EQPMInfo(char *),EQPMInfo__EQPMInfo); +#endif +#ifdef EQPMInfo__dEQPMInfo_x +FUNCTION_AT_ADDRESS( EQPMInfo::~EQPMInfo(void),EQPMInfo__dEQPMInfo); +#endif +#ifdef EQSwitch__EQSwitch_x +FUNCTION_AT_ADDRESS( EQSwitch::EQSwitch(char *,bool),EQSwitch__EQSwitch); +#endif +#ifdef EQSwitch__EQSwitch1_x +FUNCTION_AT_ADDRESS( EQSwitch::EQSwitch(struct OldDiskSwitch *,bool),EQSwitch__EQSwitch1); +#endif +#ifdef EQSwitch__EQSwitch2_x +FUNCTION_AT_ADDRESS( EQSwitch::EQSwitch(struct _EQClientSwitch *),EQSwitch__EQSwitch2); +#endif +#ifdef EQSwitch__PreInit_x +FUNCTION_AT_ADDRESS(void EQSwitch::PreInit(void),EQSwitch__PreInit); +#endif +#ifdef EQSwitch__PostInit_x +FUNCTION_AT_ADDRESS(void EQSwitch::PostInit(void),EQSwitch__PostInit); +#endif +#ifdef EQSwitch__dEQSwitch_x +FUNCTION_AT_ADDRESS( EQSwitch::~EQSwitch(void),EQSwitch__dEQSwitch); +#endif +#ifdef EQSwitch__ResetSwitchState_x +FUNCTION_AT_ADDRESS(void EQSwitch::ResetSwitchState(unsigned char),EQSwitch__ResetSwitchState); +#endif +#ifdef EQSwitch__RepopSwitch_x +FUNCTION_AT_ADDRESS(void EQSwitch::RepopSwitch(void),EQSwitch__RepopSwitch); +#endif +#ifdef EQSwitch__TopSpeed_x +FUNCTION_AT_ADDRESS(float EQSwitch::TopSpeed(float *),EQSwitch__TopSpeed); +#endif +#ifdef EQSwitch__RepopFrequency_x +FUNCTION_AT_ADDRESS(unsigned int EQSwitch::RepopFrequency(void),EQSwitch__RepopFrequency); +#endif +#ifdef EQSwitch__GetSwitchDamage_x +FUNCTION_AT_ADDRESS(int EQSwitch::GetSwitchDamage(void),EQSwitch__GetSwitchDamage); +#endif +#ifdef EQSwitch__ChangeState_x +FUNCTION_AT_ADDRESS(void EQSwitch::ChangeState(unsigned char,class EQPlayer *,bool),EQSwitch__ChangeState); +#endif +#ifdef EQSwitch__SwitchWasOpened_x +FUNCTION_AT_ADDRESS(unsigned char EQSwitch::SwitchWasOpened(int,int,class EQPlayer *,bool *),EQSwitch__SwitchWasOpened); +#endif +#ifdef EQSwitch__SwitchWasOpenedActual_x +FUNCTION_AT_ADDRESS(unsigned char EQSwitch::SwitchWasOpenedActual(int,int,class EQPlayer *,bool *),EQSwitch__SwitchWasOpenedActual); +#endif +#ifdef EQSwitch__SwitchIsNotUsable_x +FUNCTION_AT_ADDRESS(unsigned char EQSwitch::SwitchIsNotUsable(int),EQSwitch__SwitchIsNotUsable); +#endif +#ifdef EQSwitch__UseSwitch_x +FUNCTION_AT_ADDRESS(void EQSwitch::UseSwitch(unsigned int,int,int),EQSwitch__UseSwitch); +#endif +#ifdef EQSwitch__LoadSwitchSounds_x +FUNCTION_AT_ADDRESS(void EQSwitch::LoadSwitchSounds(int),EQSwitch__LoadSwitchSounds); +#endif +#ifdef EQSwitch__GetCustomMoveDistance_x +FUNCTION_AT_ADDRESS(float EQSwitch::GetCustomMoveDistance(void),EQSwitch__GetCustomMoveDistance); +#endif +#ifdef EqSwitchManager__EqSwitchManager_x +FUNCTION_AT_ADDRESS( EqSwitchManager::EqSwitchManager(void),EqSwitchManager__EqSwitchManager); +#endif +#ifdef EqSwitchManager__dEqSwitchManager_x +FUNCTION_AT_ADDRESS( EqSwitchManager::~EqSwitchManager(void),EqSwitchManager__dEqSwitchManager); +#endif +#ifdef EqSwitchManager__DeleteAll_x +FUNCTION_AT_ADDRESS(void EqSwitchManager::DeleteAll(void),EqSwitchManager__DeleteAll); +#endif +#ifdef EqSwitchManager__Load_x +FUNCTION_AT_ADDRESS(void EqSwitchManager::Load(char *,bool),EqSwitchManager__Load); +#endif +#ifdef EqSwitchManager__LoadOld_x +FUNCTION_AT_ADDRESS(void EqSwitchManager::LoadOld(char *,bool),EqSwitchManager__LoadOld); +#endif +#ifdef EqSwitchManager__GetCount_x +FUNCTION_AT_ADDRESS(int EqSwitchManager::GetCount(void),EqSwitchManager__GetCount); +#endif +#ifdef EqSwitchManager__GetSwitchByActor_x +FUNCTION_AT_ADDRESS(class EQSwitch * EqSwitchManager::GetSwitchByActor(struct T3D_tagACTORINSTANCE *),EqSwitchManager__GetSwitchByActor); +#endif +#ifdef EqSwitchManager__GetSwitch_x +FUNCTION_AT_ADDRESS(class EQSwitch * EqSwitchManager::GetSwitch(int),EqSwitchManager__GetSwitch); +#endif +#ifdef EqSwitchManager__GetSwitchById_x +FUNCTION_AT_ADDRESS(class EQSwitch * EqSwitchManager::GetSwitchById(int,bool),EqSwitchManager__GetSwitchById); +#endif +#ifdef EqSwitchManager__AddSwitch_x +FUNCTION_AT_ADDRESS(void EqSwitchManager::AddSwitch(class EQSwitch *),EqSwitchManager__AddSwitch); +#endif +#ifdef Util__GetNextToken_x +FUNCTION_AT_ADDRESS(int __cdecl Util::GetNextToken(char *,int *,char *),Util__GetNextToken); +#endif +#ifdef Util__GetNextToken1_x +FUNCTION_AT_ADDRESS(int __cdecl Util::GetNextToken(char *,short *,char *),Util__GetNextToken1); +#endif +#ifdef Util__GetNextToken2_x +FUNCTION_AT_ADDRESS(int __cdecl Util::GetNextToken(char *,char *,char *),Util__GetNextToken2); +#endif +#ifdef Util__GetNextToken3_x +FUNCTION_AT_ADDRESS(int __cdecl Util::GetNextToken(char *,unsigned char *,char *),Util__GetNextToken3); +#endif +#ifdef EQUtil__FormatCharName_x +FUNCTION_AT_ADDRESS(char * __cdecl EQUtil::FormatCharName(char *,char *,int),EQUtil__FormatCharName); +#endif +#ifdef EQWorldData__EQWorldData_x +FUNCTION_AT_ADDRESS( EQWorldData::EQWorldData(void),EQWorldData__EQWorldData); +#endif +#ifdef EQWorldData__AddZone_x +//FUNCTION_AT_ADDRESS(bool const EQWorldData::AddZone(enum EQExpansion,enum EQZoneIndex,char const *,char const *,int,unsigned long,int,int),EQWorldData__AddZone); +#endif +#ifdef EQWorldData__AdvanceTime_x +FUNCTION_AT_ADDRESS(void EQWorldData::AdvanceTime(unsigned int),EQWorldData__AdvanceTime); +#endif +#ifdef EQWorldData__CurrentGameTime_x +FUNCTION_AT_ADDRESS(void EQWorldData::CurrentGameTime(char *),EQWorldData__CurrentGameTime); +#endif +#ifdef EQWorldData__GetFullZoneName_x +//FUNCTION_AT_ADDRESS(void EQWorldData::GetFullZoneName(enum EQZoneIndex,char *),EQWorldData__GetFullZoneName); +#endif +#ifdef EQWorldData__ExpansionZone_x +//FUNCTION_AT_ADDRESS(enum EQExpansion const EQWorldData::ExpansionZone(enum EQZoneIndex)const ,EQWorldData__ExpansionZone); +#endif +#ifdef EQWorldData__IsFlagSet_x +//FUNCTION_AT_ADDRESS(bool EQWorldData::IsFlagSet(enum EQZoneIndex,unsigned long)const,EQWorldData__IsFlagSet); +#endif +#ifdef EQWorldData__IsNewbieZone_x +//FUNCTION_AT_ADDRESS(bool EQWorldData::IsNewbieZone(enum EQZoneIndex)const,EQWorldData__IsNewbieZone); +#endif +#ifdef EQWorldData__IsNoBindZone_x +//FUNCTION_AT_ADDRESS(bool EQWorldData::IsNoBindZone(enum EQZoneIndex)const,EQWorldData__IsNoBindZone); +#endif +#ifdef EQWorldData__IsNoAirZone_x +//FUNCTION_AT_ADDRESS(bool EQWorldData::IsNoAirZone(enum EQZoneIndex)const,EQWorldData__IsNoAirZone); +#endif +#ifdef EQWorldData__GetMinLevel_x +//FUNCTION_AT_ADDRESS(int EQWorldData::GetMinLevel(enum EQZoneIndex)const,EQWorldData__GetMinLevel); +#endif +#ifdef EQWorldData__GetGeometryNameFromIndex_x +//FUNCTION_AT_ADDRESS(bool EQWorldData::GetGeometryNameFromIndex(enum EQZoneIndex,char *)const ,EQWorldData__GetGeometryNameFromIndex); +#endif +#ifdef EQWorldData__GetIndexFromZoneName_x +//FUNCTION_AT_ADDRESS(enum EQZoneIndex EQWorldData::GetIndexFromZoneName(char const *)const ,EQWorldData__GetIndexFromZoneName); +#endif +#ifdef EQZoneInfo__EQZoneInfo_x +//FUNCTION_AT_ADDRESS( EQZoneInfo::EQZoneInfo(enum EQExpansion,enum EQZoneIndex,char const *,char const *,int,unsigned long,int,int),EQZoneInfo__EQZoneInfo); +#endif +#ifdef CEverQuest__ChatServerGiveTime_x +FUNCTION_AT_ADDRESS(void CEverQuest::ChatServerGiveTime(void),CEverQuest__ChatServerGiveTime); +#endif +#ifdef CEverQuest__ChatServerNotificationAdd_x +FUNCTION_AT_ADDRESS(void CEverQuest::ChatServerNotificationAdd(bool,char *,char *,int),CEverQuest__ChatServerNotificationAdd); +#endif +#ifdef CEverQuest__ChatServerNotificationFlush_x +FUNCTION_AT_ADDRESS(void CEverQuest::ChatServerNotificationFlush(void),CEverQuest__ChatServerNotificationFlush); +#endif +#ifdef CEverQuest__ChatServerConnect_x +FUNCTION_AT_ADDRESS(void CEverQuest::ChatServerConnect(char *,int,char *,char *),CEverQuest__ChatServerConnect); +#endif +#ifdef CEverQuest__ChatServerMessage_x +FUNCTION_AT_ADDRESS(void CEverQuest::ChatServerMessage(char *),CEverQuest__ChatServerMessage); +#endif +#ifdef CEverQuest__ChatServerDisconnect_x +FUNCTION_AT_ADDRESS(void CEverQuest::ChatServerDisconnect(void),CEverQuest__ChatServerDisconnect); +#endif +#ifdef CEverQuest__ResetVisionRGBs_x +FUNCTION_AT_ADDRESS(void CEverQuest::ResetVisionRGBs(void),CEverQuest__ResetVisionRGBs); +#endif +#ifdef CEverQuest__GetMaxLightRadius_x +FUNCTION_AT_ADDRESS(float CEverQuest::GetMaxLightRadius(void),CEverQuest__GetMaxLightRadius); +#endif +#ifdef CEverQuest__LoadStringTables_x +FUNCTION_AT_ADDRESS(void CEverQuest::LoadStringTables(void),CEverQuest__LoadStringTables); +#endif +#ifdef CEverQuest__CEverQuest_x +FUNCTION_AT_ADDRESS( CEverQuest::CEverQuest(struct HWND__ *),CEverQuest__CEverQuest); +#endif +#ifdef CEverQuest__dCEverQuest_x +FUNCTION_AT_ADDRESS( CEverQuest::~CEverQuest(void),CEverQuest__dCEverQuest); +#endif +#ifdef CEverQuest__ProcessMBox_x +FUNCTION_AT_ADDRESS(int CEverQuest::ProcessMBox(void),CEverQuest__ProcessMBox); +#endif +#ifdef CEverQuest__UseCharge_x +FUNCTION_AT_ADDRESS(void CEverQuest::UseCharge(unsigned long),CEverQuest__UseCharge); +#endif +#ifdef CEverQuest__LeaveGuildMaster_x +FUNCTION_AT_ADDRESS(void CEverQuest::LeaveGuildMaster(void),CEverQuest__LeaveGuildMaster); +#endif +#ifdef CEverQuest__LeaveBankMode_x +FUNCTION_AT_ADDRESS(void CEverQuest::LeaveBankMode(bool),CEverQuest__LeaveBankMode); +#endif +#ifdef CEverQuest__ReportDeath_x +FUNCTION_AT_ADDRESS(void CEverQuest::ReportDeath(struct _EQPlayerDeath *),CEverQuest__ReportDeath); +#endif +#ifdef CEverQuest__SetDefaultDamageDescByRace_x +FUNCTION_AT_ADDRESS(void CEverQuest::SetDefaultDamageDescByRace(char *,int,unsigned char),CEverQuest__SetDefaultDamageDescByRace); +#endif +#ifdef CEverQuest__ReportSuccessfulHit_x +FUNCTION_AT_ADDRESS(void CEverQuest::ReportSuccessfulHit(struct _EQSuccessfulHit *,unsigned char,int),CEverQuest__ReportSuccessfulHit); +#endif +#ifdef CEverQuest__GetCombatSound_x +FUNCTION_AT_ADDRESS(int CEverQuest::GetCombatSound(class EQPlayer *,class EQPlayer *),CEverQuest__GetCombatSound); +#endif +#ifdef CEverQuest__LocalDeath_x +FUNCTION_AT_ADDRESS(void CEverQuest::LocalDeath(struct _EQPlayerDeath *,unsigned char),CEverQuest__LocalDeath); +#endif +#ifdef CEverQuest__PrepareLocalPCForRepop_x +FUNCTION_AT_ADDRESS(void CEverQuest::PrepareLocalPCForRepop(void),CEverQuest__PrepareLocalPCForRepop); +#endif +#ifdef CEverQuest__SavePCForce_x +FUNCTION_AT_ADDRESS(void CEverQuest::SavePCForce(int),CEverQuest__SavePCForce); +#endif +#ifdef CEverQuest__StartCasting_x +FUNCTION_AT_ADDRESS(void CEverQuest::StartCasting(void *),CEverQuest__StartCasting); +#endif +#ifdef CEverQuest__Consider_x +FUNCTION_AT_ADDRESS(void CEverQuest::Consider(class EQPlayer *,void *),CEverQuest__Consider); +#endif +#ifdef CEverQuest__GetClassDesc_x +FUNCTION_AT_ADDRESS(char * CEverQuest::GetClassDesc(int),CEverQuest__GetClassDesc); +#endif +#ifdef CEverQuest__GetClassThreeLetterCode_x +FUNCTION_AT_ADDRESS(char * CEverQuest::GetClassThreeLetterCode(int),CEverQuest__GetClassThreeLetterCode); +#endif +#ifdef CEverQuest__GetItemClassDesc_x +FUNCTION_AT_ADDRESS(char * CEverQuest::GetItemClassDesc(int),CEverQuest__GetItemClassDesc); +#endif +#ifdef CEverQuest__GetBodyTypeDesc_x +FUNCTION_AT_ADDRESS(char * CEverQuest::GetBodyTypeDesc(int),CEverQuest__GetBodyTypeDesc); +#endif +#ifdef CEverQuest__GetLangDesc_x +FUNCTION_AT_ADDRESS(char * CEverQuest::GetLangDesc(int),CEverQuest__GetLangDesc); +#endif +#ifdef CEverQuest__GetRaceDesc_x +FUNCTION_AT_ADDRESS(char * CEverQuest::GetRaceDesc(int),CEverQuest__GetRaceDesc); +#endif +#ifdef CEverQuest__GetDeityDesc_x +FUNCTION_AT_ADDRESS(char * CEverQuest::GetDeityDesc(int),CEverQuest__GetDeityDesc); +#endif +#ifdef CEverQuest__GuildInvite_x +FUNCTION_AT_ADDRESS(void CEverQuest::GuildInvite(char *,char *),CEverQuest__GuildInvite); +#endif +#ifdef CEverQuest__GuildRemove_x +FUNCTION_AT_ADDRESS(void CEverQuest::GuildRemove(char *),CEverQuest__GuildRemove); +#endif +#ifdef CEverQuest__GuildDelete_x +FUNCTION_AT_ADDRESS(void CEverQuest::GuildDelete(void),CEverQuest__GuildDelete); +#endif +#ifdef CEverQuest__GuildStatus_x +FUNCTION_AT_ADDRESS(void CEverQuest::GuildStatus(char *),CEverQuest__GuildStatus); +#endif +#ifdef CEverQuest__GuildLeader_x +FUNCTION_AT_ADDRESS(void CEverQuest::GuildLeader(char *),CEverQuest__GuildLeader); +#endif +#ifdef CEverQuest__GuildSay_x +FUNCTION_AT_ADDRESS(void CEverQuest::GuildSay(char *),CEverQuest__GuildSay); +#endif +#ifdef CEverQuest__Who_x +FUNCTION_AT_ADDRESS(void CEverQuest::Who(char *),CEverQuest__Who); +#endif +#ifdef CEverQuest__GetInnateDesc_x +FUNCTION_AT_ADDRESS(char * CEverQuest::GetInnateDesc(int),CEverQuest__GetInnateDesc); +#endif +#ifdef CEverQuest__InviteOk_x +FUNCTION_AT_ADDRESS(void CEverQuest::InviteOk(char *),CEverQuest__InviteOk); +#endif +#ifdef CEverQuest__doUnInvite_x +FUNCTION_AT_ADDRESS(void CEverQuest::doUnInvite(char *),CEverQuest__doUnInvite); +#endif +#ifdef CEverQuest__Invite_x +FUNCTION_AT_ADDRESS(void CEverQuest::Invite(int),CEverQuest__Invite); +#endif +#ifdef CEverQuest__doInvite_x +FUNCTION_AT_ADDRESS(void CEverQuest::doInvite(unsigned __int32,char *),CEverQuest__doInvite); +#endif +#ifdef CEverQuest__Follow_x +FUNCTION_AT_ADDRESS(void CEverQuest::Follow(void),CEverQuest__Follow); +#endif +#ifdef CEverQuest__Disband_x +FUNCTION_AT_ADDRESS(void CEverQuest::Disband(void),CEverQuest__Disband); +#endif +#ifdef CEverQuest__GuildWar_x +FUNCTION_AT_ADDRESS(void CEverQuest::GuildWar(char *,int),CEverQuest__GuildWar); +#endif +#ifdef CEverQuest__GuildPeace_x +FUNCTION_AT_ADDRESS(void CEverQuest::GuildPeace(char *),CEverQuest__GuildPeace); +#endif +#ifdef CEverQuest__Sit_x +FUNCTION_AT_ADDRESS(void CEverQuest::Sit(void),CEverQuest__Sit); +#endif +#ifdef CEverQuest__Camp_x +FUNCTION_AT_ADDRESS(void CEverQuest::Camp(void),CEverQuest__Camp); +#endif +#ifdef CEverQuest__DropHeldItemOnGround_x +FUNCTION_AT_ADDRESS(void CEverQuest::DropHeldItemOnGround(int),CEverQuest__DropHeldItemOnGround); +#endif +#ifdef CEverQuest__MoveMoney_x +FUNCTION_AT_ADDRESS(int CEverQuest::MoveMoney(int,int,int,int,int,bool),CEverQuest__MoveMoney); +#endif +#ifdef CEverQuest__DropHeldMoneyOnGround_x +FUNCTION_AT_ADDRESS(void CEverQuest::DropHeldMoneyOnGround(int),CEverQuest__DropHeldMoneyOnGround); +#endif +#ifdef CEverQuest__LMouseUp_x +FUNCTION_AT_ADDRESS(void CEverQuest::LMouseUp(int,int),CEverQuest__LMouseUp); +#endif +#ifdef CEverQuest__LeftClickedOnPlayer_x +FUNCTION_AT_ADDRESS(void CEverQuest::LeftClickedOnPlayer(class EQPlayer *),CEverQuest__LeftClickedOnPlayer); +#endif +#ifdef CEverQuest__DropItemOrMoneyOnPlayer_x +FUNCTION_AT_ADDRESS(void CEverQuest::DropItemOrMoneyOnPlayer(class EQPlayer *),CEverQuest__DropItemOrMoneyOnPlayer); +#endif +#ifdef CEverQuest__RightClickedOnPlayer_x +FUNCTION_AT_ADDRESS(void CEverQuest::RightClickedOnPlayer(class EQPlayer *, int),CEverQuest__RightClickedOnPlayer); +#endif +#ifdef CEverQuest__send_social_x +FUNCTION_AT_ADDRESS(void CEverQuest::send_social(int,char *,char *),CEverQuest__send_social); +#endif +#ifdef CEverQuest__SavePC_x +FUNCTION_AT_ADDRESS(void CEverQuest::SavePC(int,int,unsigned char),CEverQuest__SavePC); +#endif +#ifdef CEverQuest__send_tell_x +FUNCTION_AT_ADDRESS(void CEverQuest::send_tell(char *,char *),CEverQuest__send_tell); +#endif +#ifdef CEverQuest__send_petition_x +FUNCTION_AT_ADDRESS(void CEverQuest::send_petition(void),CEverQuest__send_petition); +#endif +#ifdef CEverQuest__send_private_x +FUNCTION_AT_ADDRESS(void CEverQuest::send_private(void),CEverQuest__send_private); +#endif +#ifdef CEverQuest__WriteIntToClientINI_x +FUNCTION_AT_ADDRESS(void CEverQuest::WriteIntToClientINI(int,char *,char *),CEverQuest__WriteIntToClientINI); +#endif +#ifdef CEverQuest__WriteFloatToClientINI_x +FUNCTION_AT_ADDRESS(void CEverQuest::WriteFloatToClientINI(float,char *,char *),CEverQuest__WriteFloatToClientINI); +#endif +#ifdef CEverQuest__WriteBoolToClientINI_x +FUNCTION_AT_ADDRESS(void CEverQuest::WriteBoolToClientINI(bool,char *,char *),CEverQuest__WriteBoolToClientINI); +#endif +#ifdef CEverQuest__WriteStringToClientINI_x +FUNCTION_AT_ADDRESS(void CEverQuest::WriteStringToClientINI(char *,char *,char *),CEverQuest__WriteStringToClientINI); +#endif +#ifdef CEverQuest__ReadClientINIString_x +FUNCTION_AT_ADDRESS(char * CEverQuest::ReadClientINIString(char *,char *,char *,char *,int),CEverQuest__ReadClientINIString); +#endif +#ifdef CEverQuest__ReadClientINIInt_x +FUNCTION_AT_ADDRESS(int CEverQuest::ReadClientINIInt(char *,char *,int),CEverQuest__ReadClientINIInt); +#endif +#ifdef CEverQuest__ReadClientINIFloat_x +FUNCTION_AT_ADDRESS(float CEverQuest::ReadClientINIFloat(char *,char *,float),CEverQuest__ReadClientINIFloat); +#endif +#ifdef CEverQuest__ReadClientINIBool_x +FUNCTION_AT_ADDRESS(bool CEverQuest::ReadClientINIBool(char *,char *,bool),CEverQuest__ReadClientINIBool); +#endif +#ifdef CEverQuest__WriteIntToUIINI_x +FUNCTION_AT_ADDRESS(void CEverQuest::WriteIntToUIINI(int,char *,char *),CEverQuest__WriteIntToUIINI); +#endif +#ifdef CEverQuest__WriteBoolToUIINI_x +FUNCTION_AT_ADDRESS(void CEverQuest::WriteBoolToUIINI(bool,char *,char *),CEverQuest__WriteBoolToUIINI); +#endif +#ifdef CEverQuest__WriteStringToUIINI_x +FUNCTION_AT_ADDRESS(void CEverQuest::WriteStringToUIINI(char *,char *,char *),CEverQuest__WriteStringToUIINI); +#endif +#ifdef CEverQuest__ReadUIINIString_x +FUNCTION_AT_ADDRESS(char * CEverQuest::ReadUIINIString(char *,char *,char *,char *,int),CEverQuest__ReadUIINIString); +#endif +#ifdef CEverQuest__ReadUIINIInt_x +FUNCTION_AT_ADDRESS(int CEverQuest::ReadUIINIInt(char *,char *,int),CEverQuest__ReadUIINIInt); +#endif +#ifdef CEverQuest__ReadUIINIBool_x +FUNCTION_AT_ADDRESS(bool CEverQuest::ReadUIINIBool(char *,char *,bool),CEverQuest__ReadUIINIBool); +#endif +#ifdef CEverQuest__SaveCamerasToINI_x +FUNCTION_AT_ADDRESS(void CEverQuest::SaveCamerasToINI(void),CEverQuest__SaveCamerasToINI); +#endif +#ifdef CEverQuest__saveOptions_x +FUNCTION_AT_ADDRESS(void CEverQuest::saveOptions(void),CEverQuest__saveOptions); +#endif +#ifdef CEverQuest__saveOptions2_x +FUNCTION_AT_ADDRESS(void CEverQuest::saveOptions2(void),CEverQuest__saveOptions2); +#endif +#ifdef CEverQuest__send_update_filters_x +FUNCTION_AT_ADDRESS(void CEverQuest::send_update_filters(void),CEverQuest__send_update_filters); +#endif +#ifdef CEverQuest__loadOptions_x +FUNCTION_AT_ADDRESS(void CEverQuest::loadOptions(void),CEverQuest__loadOptions); +#endif +#ifdef CEverQuest__DoSplit_x +FUNCTION_AT_ADDRESS(void CEverQuest::DoSplit(char *),CEverQuest__DoSplit); +#endif +#ifdef CEverQuest__BeingIgnored_x +FUNCTION_AT_ADDRESS(int CEverQuest::BeingIgnored(char *),CEverQuest__BeingIgnored); +#endif +#ifdef CEverQuest__IsFriend_x +FUNCTION_AT_ADDRESS(int CEverQuest::IsFriend(char const *),CEverQuest__IsFriend); +#endif +#ifdef CEverQuest__ToggleAutoSplit_x +FUNCTION_AT_ADDRESS(void CEverQuest::ToggleAutoSplit(void),CEverQuest__ToggleAutoSplit); +#endif +#ifdef CEverQuest__procMouse_x +FUNCTION_AT_ADDRESS(void CEverQuest::procMouse(int),CEverQuest__procMouse); +#endif +#ifdef CEverQuest__StripShipName_x +FUNCTION_AT_ADDRESS(char * CEverQuest::StripShipName(char *,char *),CEverQuest__StripShipName); +#endif +#ifdef CEverQuest__trimName_x +FUNCTION_AT_ADDRESS(char * CEverQuest::trimName(char *),CEverQuest__trimName); +#endif +#ifdef CEverQuest__CancelSneakHide_x +FUNCTION_AT_ADDRESS(void CEverQuest::CancelSneakHide(void),CEverQuest__CancelSneakHide); +#endif +#ifdef CEverQuest__stripName_x +FUNCTION_AT_ADDRESS(char * CEverQuest::stripName(char *),CEverQuest__stripName); +#endif +#ifdef CEverQuest__clr_chat_input_x +FUNCTION_AT_ADDRESS(void CEverQuest::clr_chat_input(void),CEverQuest__clr_chat_input); +#endif +#ifdef CEverQuest__dsp_chat_x +FUNCTION_AT_ADDRESS(void CEverQuest::dsp_chat(char const *,int,bool,bool),CEverQuest__dsp_chat); +void CEverQuest::dsp_chat(char const *a, int b, bool c) { dsp_chat(a, b, c, 1); } +#endif +#ifdef CEverQuest__DoTellWindow_x +FUNCTION_AT_ADDRESS(void CEverQuest::DoTellWindow(char *message,char *name,char *name2,void *unknown,int color,bool b),CEverQuest__DoTellWindow); +#endif +#ifdef CEverQuest__dsp_chat1_x +FUNCTION_AT_ADDRESS(void CEverQuest::dsp_chat(char const *),CEverQuest__dsp_chat1); +#endif +#ifdef CEverQuest__DoPercentConvert_x +FUNCTION_AT_ADDRESS(void CEverQuest::DoPercentConvert(char *,bool),CEverQuest__DoPercentConvert); +#endif +#ifdef CEverQuest__Emote_x +FUNCTION_AT_ADDRESS(void CEverQuest::Emote(void),CEverQuest__Emote); +#endif +#ifdef CEverQuest__send_broadcast_x +FUNCTION_AT_ADDRESS(void CEverQuest::send_broadcast(void),CEverQuest__send_broadcast); +#endif +#ifdef CEverQuest__send_chat_x +FUNCTION_AT_ADDRESS(void CEverQuest::send_chat(void),CEverQuest__send_chat); +#endif +#ifdef CEverQuest__send_gsay_x +FUNCTION_AT_ADDRESS(void CEverQuest::send_gsay(void),CEverQuest__send_gsay); +#endif +#ifdef CEverQuest__reqChannel_x +FUNCTION_AT_ADDRESS(void CEverQuest::reqChannel(void),CEverQuest__reqChannel); +#endif +#ifdef CEverQuest__send_shout_x +FUNCTION_AT_ADDRESS(void CEverQuest::send_shout(void),CEverQuest__send_shout); +#endif +#ifdef CEverQuest__send_auction_x +FUNCTION_AT_ADDRESS(void CEverQuest::send_auction(void),CEverQuest__send_auction); +#endif +#ifdef CEverQuest__send_ooc_x +FUNCTION_AT_ADDRESS(void CEverQuest::send_ooc(void),CEverQuest__send_ooc); +#endif +#ifdef CEverQuest__GetCurrentLanguage_x +FUNCTION_AT_ADDRESS(int CEverQuest::GetCurrentLanguage(void),CEverQuest__GetCurrentLanguage); +#endif +#ifdef CEverQuest__SendNewText_x +FUNCTION_AT_ADDRESS(void CEverQuest::SendNewText(int,char *,char *),CEverQuest__SendNewText); +#endif +#ifdef CEverQuest__DisplayScreen_x +FUNCTION_AT_ADDRESS(void CEverQuest::DisplayScreen(char *),CEverQuest__DisplayScreen); +#endif +#ifdef CEverQuest__IsValidName_x +FUNCTION_AT_ADDRESS(int CEverQuest::IsValidName(char *),CEverQuest__IsValidName); +#endif +#ifdef CEverQuest__DoNewCharacterCreation_x +FUNCTION_AT_ADDRESS(void CEverQuest::DoNewCharacterCreation(void),CEverQuest__DoNewCharacterCreation); +#endif +#ifdef CEverQuest__RemoveCharacterOptionFile_x +FUNCTION_AT_ADDRESS(void CEverQuest::RemoveCharacterOptionFile(char *),CEverQuest__RemoveCharacterOptionFile); +#endif +#ifdef CEverQuest__SetDefaultGameValues_x +FUNCTION_AT_ADDRESS(void CEverQuest::SetDefaultGameValues(void),CEverQuest__SetDefaultGameValues); +#endif +#ifdef CEverQuest__SetPlayerAppearanceFromPInfo_x +FUNCTION_AT_ADDRESS(void CEverQuest::SetPlayerAppearanceFromPInfo(class EQPlayer *,int,bool),CEverQuest__SetPlayerAppearanceFromPInfo); +#endif +#ifdef CEverQuest__DoCharacterSelection_x +FUNCTION_AT_ADDRESS(void CEverQuest::DoCharacterSelection(void),CEverQuest__DoCharacterSelection); +#endif +#ifdef CEverQuest__DoLogin_x +FUNCTION_AT_ADDRESS(int CEverQuest::DoLogin(struct HWND__ *,struct HINSTANCE__ *),CEverQuest__DoLogin); +#endif +#ifdef CEverQuest__SetupCharSelectCamera_x +FUNCTION_AT_ADDRESS(void CEverQuest::SetupCharSelectCamera(void),CEverQuest__SetupCharSelectCamera); +#endif +#ifdef CEverQuest__CreateDataSubdirectories_x +FUNCTION_AT_ADDRESS(void CEverQuest::CreateDataSubdirectories(void),CEverQuest__CreateDataSubdirectories); +#endif +#ifdef CEverQuest__CreateFilenameServerCode_x +FUNCTION_AT_ADDRESS(void CEverQuest::CreateFilenameServerCode(char *),CEverQuest__CreateFilenameServerCode); +#endif +#ifdef CEverQuest__CreateIniFilenames_x +FUNCTION_AT_ADDRESS(void CEverQuest::CreateIniFilenames(void),CEverQuest__CreateIniFilenames); +#endif +#ifdef CEverQuest__StartNetworkGame_x +FUNCTION_AT_ADDRESS(void CEverQuest::StartNetworkGame(struct HWND__ *,struct HINSTANCE__ *,char *),CEverQuest__StartNetworkGame); +#endif +#ifdef CEverQuest__GetZoneInfoFromNetwork_x +FUNCTION_AT_ADDRESS(void CEverQuest::GetZoneInfoFromNetwork(char *),CEverQuest__GetZoneInfoFromNetwork); +#endif +#ifdef CEverQuest__EnterZone_x +FUNCTION_AT_ADDRESS(void CEverQuest::EnterZone(struct HWND__ *),CEverQuest__EnterZone); +#endif +#ifdef CEverQuest__Surname_x +FUNCTION_AT_ADDRESS(void CEverQuest::Surname(char *),CEverQuest__Surname); +#endif +#ifdef CEverQuest__Kill_x +FUNCTION_AT_ADDRESS(void CEverQuest::Kill(char *,char *),CEverQuest__Kill); +#endif +#ifdef CEverQuest__UpdateMyAppearance_x +FUNCTION_AT_ADDRESS(void CEverQuest::UpdateMyAppearance(void),CEverQuest__UpdateMyAppearance); +#endif +#ifdef CEverQuest__IFoundMyVehicle_x +FUNCTION_AT_ADDRESS(unsigned char CEverQuest::IFoundMyVehicle(void),CEverQuest__IFoundMyVehicle); +#endif +#ifdef CEverQuest__ProcessLocalPCIni_x +FUNCTION_AT_ADDRESS(void CEverQuest::ProcessLocalPCIni(int),CEverQuest__ProcessLocalPCIni); +#endif +#ifdef CEverQuest__DoMainLoop_x +FUNCTION_AT_ADDRESS(void CEverQuest::DoMainLoop(struct HWND__ *),CEverQuest__DoMainLoop); +#endif +#ifdef CEverQuest__ProcessControls_x +FUNCTION_AT_ADDRESS(void CEverQuest::ProcessControls(void),CEverQuest__ProcessControls); +#endif +#ifdef CEverQuest__TypingMode_x +FUNCTION_AT_ADDRESS(int CEverQuest::TypingMode(void),CEverQuest__TypingMode); +#endif +#ifdef CEverQuest__IsInTypingMode_x +FUNCTION_AT_ADDRESS(bool CEverQuest::IsInTypingMode(void),CEverQuest__IsInTypingMode); +#endif +#ifdef CEverQuest__doInspect_x +FUNCTION_AT_ADDRESS(void CEverQuest::doInspect(class EQPlayer *),CEverQuest__doInspect); +#endif +#ifdef __do_loot_x +FUNCTION_AT_ADDRESS(void CEverQuest::doLoot(void),__do_loot); +#endif +#ifdef CEverQuest__SendLightInfo_x +FUNCTION_AT_ADDRESS(void CEverQuest::SendLightInfo(class EQPlayer *,unsigned char),CEverQuest__SendLightInfo); +#endif +#ifdef CEverQuest__SetTimedFog_x +FUNCTION_AT_ADDRESS(void CEverQuest::SetTimedFog(int),CEverQuest__SetTimedFog); +#endif +#ifdef CEverQuest__ProcessGame_x +FUNCTION_AT_ADDRESS(void CEverQuest::ProcessGame(struct HWND__ *,struct HINSTANCE__ *),CEverQuest__ProcessGame); +#endif +#ifdef CEverQuest__DoLoadScreenProgressBar_x +FUNCTION_AT_ADDRESS(void __cdecl CEverQuest::DoLoadScreenProgressBar(int,char const *,...),CEverQuest__DoLoadScreenProgressBar); +#endif +#ifdef CEverQuest__DoLoadScreen_x +FUNCTION_AT_ADDRESS(void CEverQuest::DoLoadScreen(int),CEverQuest__DoLoadScreen); +#endif +#ifdef CEverQuest__CleanupBadFiles_x +FUNCTION_AT_ADDRESS(void CEverQuest::CleanupBadFiles(void),CEverQuest__CleanupBadFiles); +#endif +#ifdef CEverQuest__CreateInitialActors_x +FUNCTION_AT_ADDRESS(void CEverQuest::CreateInitialActors(void),CEverQuest__CreateInitialActors); +#endif +#ifdef CEverQuest__GetSndDriver_x +FUNCTION_AT_ADDRESS(void CEverQuest::GetSndDriver(void),CEverQuest__GetSndDriver); +#endif +#ifdef CEverQuest__InterpretCmd_x +FUNCTION_AT_ADDRESS(void CEverQuest::InterpretCmd(class EQPlayer *,char *),CEverQuest__InterpretCmd); +#endif +#ifdef CEverQuest__GrabFirstWord_x +FUNCTION_AT_ADDRESS(char * CEverQuest::GrabFirstWord(char *,char *),CEverQuest__GrabFirstWord); +#endif +#ifdef CEverQuest__GrabFirstWord2_x +FUNCTION_AT_ADDRESS(char * CEverQuest::GrabFirstWord2(char *,char *,int),CEverQuest__GrabFirstWord2); +#endif +#ifdef CEverQuest__CopyFirstWord_x +FUNCTION_AT_ADDRESS(void CEverQuest::CopyFirstWord(char *,char *),CEverQuest__CopyFirstWord); +#endif +#ifdef CEverQuest__ApplyPoison_x +FUNCTION_AT_ADDRESS(void CEverQuest::ApplyPoison(unsigned long),CEverQuest__ApplyPoison); +#endif +#ifdef CEverQuest__DeacSpellScreen_x +FUNCTION_AT_ADDRESS(void CEverQuest::DeacSpellScreen(void),CEverQuest__DeacSpellScreen); +#endif +#ifdef CEverQuest__IsZoneAvailable_x +//FUNCTION_AT_ADDRESS(enum ZONE_REQ_STATUS CEverQuest::IsZoneAvailable(char *,enum EQZoneIndex,enum ZONE_REQ_REASON),CEverQuest__IsZoneAvailable); +#endif +#ifdef CEverQuest__MoveToZone_x +FUNCTION_AT_ADDRESS(void CEverQuest::MoveToZone(int EQZoneIndex,char *,int,int ZONE_REQ_REASON,float,float,float,int),CEverQuest__MoveToZone); +#endif +#ifdef CEverQuest__MoveToZone1_x +//FUNCTION_AT_ADDRESS(void CEverQuest::MoveToZone(char *,char *,int,enum ZONE_REQ_REASON),CEverQuest__MoveToZone1); +#endif +#ifdef CEverQuest__LMouseDown_x +FUNCTION_AT_ADDRESS(void CEverQuest::LMouseDown(int,int),CEverQuest__LMouseDown); +#endif +#ifdef CEverQuest__RMouseDown_x +FUNCTION_AT_ADDRESS(void CEverQuest::RMouseDown(int,int),CEverQuest__RMouseDown); +#endif +#ifdef CEverQuest__RMouseUp_x +FUNCTION_AT_ADDRESS(void CEverQuest::RMouseUp(int,int),CEverQuest__RMouseUp); +#endif +#ifdef CEverQuest__MouseWheelScrolled_x +FUNCTION_AT_ADDRESS(void CEverQuest::MouseWheelScrolled(int),CEverQuest__MouseWheelScrolled); +#endif +#ifdef CEverQuest__ClickedSwitch_x +FUNCTION_AT_ADDRESS(class EQSwitch * CEverQuest::ClickedSwitch(int,int),CEverQuest__ClickedSwitch); +#endif +#ifdef CEverQuest__ClickedPlayer_x +FUNCTION_AT_ADDRESS(class EQPlayer * CEverQuest::ClickedPlayer(int,int),CEverQuest__ClickedPlayer); +#endif +#ifdef CEverQuest__WhatTimeIsIt_x +FUNCTION_AT_ADDRESS(void CEverQuest::WhatTimeIsIt(void),CEverQuest__WhatTimeIsIt); +#endif +#ifdef CEverQuest__FreeSwitches_x +FUNCTION_AT_ADDRESS(void CEverQuest::FreeSwitches(void),CEverQuest__FreeSwitches); +#endif +#ifdef CEverQuest__LoadSwitchesNonAvatar_x +//FUNCTION_AT_ADDRESS(void CEverQuest::LoadSwitchesNonAvatar(enum EQZoneIndex),CEverQuest__LoadSwitchesNonAvatar); +#endif +#ifdef CEverQuest__SetLfgPlayerStatus_x +FUNCTION_AT_ADDRESS(void CEverQuest::SetLfgPlayerStatus(struct LfgPlayerStatus *),CEverQuest__SetLfgPlayerStatus); +#endif +#ifdef CEverQuest__SetLfgGroupStatus_x +FUNCTION_AT_ADDRESS(void CEverQuest::SetLfgGroupStatus(struct LfgGroupStatus *),CEverQuest__SetLfgGroupStatus); +#endif +#ifdef CEverQuest__IssueLfgPlayerQuery_x +FUNCTION_AT_ADDRESS(void CEverQuest::IssueLfgPlayerQuery(struct LfgPlayerQuery *),CEverQuest__IssueLfgPlayerQuery); +#endif +#ifdef CEverQuest__IssueLfgGroupQuery_x +FUNCTION_AT_ADDRESS(void CEverQuest::IssueLfgGroupQuery(struct LfgGroupQuery *),CEverQuest__IssueLfgGroupQuery); +#endif +#ifdef CEverQuest__IssuePetCommand_x +//FUNCTION_AT_ADDRESS(void CEverQuest::IssuePetCommand(enum PetCommandType,int),CEverQuest__IssuePetCommand); +#endif +#ifdef CEverQuest__LootCorpse_x +FUNCTION_AT_ADDRESS(int CEverQuest::LootCorpse(class EQPlayer *,int),CEverQuest__LootCorpse); +#endif +#ifdef CEverQuest__loadSoundsGame_x +FUNCTION_AT_ADDRESS(void CEverQuest::loadSoundsGame(void),CEverQuest__loadSoundsGame); +#endif +#ifdef CEverQuest__GetSingleMessage_x +FUNCTION_AT_ADDRESS(char * CEverQuest::GetSingleMessage(unsigned __int32,int,int *,char *),CEverQuest__GetSingleMessage); +#endif +#ifdef CEverQuest__SetGameState_x +FUNCTION_AT_ADDRESS(void CEverQuest::SetGameState(int),CEverQuest__SetGameState); +#endif +#ifdef CEverQuest__IsOkToTransact_x +FUNCTION_AT_ADDRESS(bool CEverQuest::IsOkToTransact(void),CEverQuest__IsOkToTransact); +#endif +#ifdef CEverQuest__SortSpellLoadouts_x +FUNCTION_AT_ADDRESS(void CEverQuest::SortSpellLoadouts(void),CEverQuest__SortSpellLoadouts); +#endif +#ifdef CEverQuest__saveCustom_x +FUNCTION_AT_ADDRESS(void CEverQuest::saveCustom(void),CEverQuest__saveCustom); +#endif +#ifdef CEverQuest__loadCustomFromINI_x +FUNCTION_AT_ADDRESS(void CEverQuest::loadCustomFromINI(char *),CEverQuest__loadCustomFromINI); +#endif +#ifdef CEverQuest__loadCustom_x +FUNCTION_AT_ADDRESS(void CEverQuest::loadCustom(void),CEverQuest__loadCustom); +#endif +#ifdef CEverQuest__initCustom_x +FUNCTION_AT_ADDRESS(void CEverQuest::initCustom(void),CEverQuest__initCustom); +#endif +#ifdef _EverQuestinfo__SetAutoAttack_x +FUNCTION_AT_ADDRESS(void _EverQuestinfo::SetAutoAttack(bool),_EverQuestinfo__SetAutoAttack); +#endif +#ifdef GrammarRulesClass__GrammarRulesClass_x +FUNCTION_AT_ADDRESS( GrammarRulesClass::GrammarRulesClass(void),GrammarRulesClass__GrammarRulesClass); +#endif +#ifdef GrammarRulesClass__Parse_x +FUNCTION_AT_ADDRESS(char * GrammarRulesClass::Parse(char *),GrammarRulesClass__Parse); +#endif +#ifdef GrammarRulesClass__Resolve_x +FUNCTION_AT_ADDRESS(char * GrammarRulesClass::Resolve(int,int,char *,char *),GrammarRulesClass__Resolve); +#endif +#ifdef GrammarRulesClass__RuleEn1_x +FUNCTION_AT_ADDRESS(void GrammarRulesClass::RuleEn1(char *,char *),GrammarRulesClass__RuleEn1); +#endif +#ifdef GrammarRulesClass__RuleEn2_x +FUNCTION_AT_ADDRESS(void GrammarRulesClass::RuleEn2(char *,char *),GrammarRulesClass__RuleEn2); +#endif +#ifdef GrammarRulesClass__RuleEn3_x +FUNCTION_AT_ADDRESS(void GrammarRulesClass::RuleEn3(char *,char *,char *,char *),GrammarRulesClass__RuleEn3); +#endif +#ifdef GrammarRulesClass__RuleEn4_x +FUNCTION_AT_ADDRESS(void GrammarRulesClass::RuleEn4(char *,char *,char *,char *),GrammarRulesClass__RuleEn4); +#endif +#ifdef GrammarRulesClass__RuleKo1_x +FUNCTION_AT_ADDRESS(void GrammarRulesClass::RuleKo1(char *,char *,char *,char *),GrammarRulesClass__RuleKo1); +#endif +#ifdef GrammarRulesClass__RuleFr1_x +FUNCTION_AT_ADDRESS(void GrammarRulesClass::RuleFr1(char *,char *,char *,char *),GrammarRulesClass__RuleFr1); +#endif +#ifdef GrammarRulesClass__RuleDe1_x +FUNCTION_AT_ADDRESS(void GrammarRulesClass::RuleDe1(char *,char *),GrammarRulesClass__RuleDe1); +#endif +#ifdef KeypressHandler__KeypressHandler_x +FUNCTION_AT_ADDRESS( KeypressHandler::KeypressHandler(void),KeypressHandler__KeypressHandler); +#endif +#ifdef KeypressHandler__AttachKeyToEqCommand_x +FUNCTION_AT_ADDRESS(bool KeypressHandler::AttachKeyToEqCommand(class KeyCombo const &,unsigned int),KeypressHandler__AttachKeyToEqCommand); +#endif +#ifdef KeypressHandler__AttachAltKeyToEqCommand_x +FUNCTION_AT_ADDRESS(bool KeypressHandler::AttachAltKeyToEqCommand(class KeyCombo const &,unsigned int),KeypressHandler__AttachAltKeyToEqCommand); +#endif +#ifdef KeypressHandler__HandleKeyDown_x +FUNCTION_AT_ADDRESS(bool KeypressHandler::HandleKeyDown(class KeyCombo const &),KeypressHandler__HandleKeyDown); +#endif +#ifdef KeypressHandler__HandleKeyUp_x +FUNCTION_AT_ADDRESS(bool KeypressHandler::HandleKeyUp(class KeyCombo const &),KeypressHandler__HandleKeyUp); +#endif +#ifdef KeypressHandler__GetKeyAttachedToEqCommand_x +FUNCTION_AT_ADDRESS(class KeyCombo const & KeypressHandler::GetKeyAttachedToEqCommand(unsigned int)const ,KeypressHandler__GetKeyAttachedToEqCommand); +#endif +#ifdef KeypressHandler__GetAltKeyAttachedToEqCommand_x +FUNCTION_AT_ADDRESS(class KeyCombo const & KeypressHandler::GetAltKeyAttachedToEqCommand(unsigned int)const ,KeypressHandler__GetAltKeyAttachedToEqCommand); +#endif +#ifdef KeypressHandler__ResetKeysToEqDefaults_x +FUNCTION_AT_ADDRESS(void KeypressHandler::ResetKeysToEqDefaults(void),KeypressHandler__ResetKeysToEqDefaults); +#endif +#ifdef KeypressHandler__MapKeyToEqCommand_x +FUNCTION_AT_ADDRESS(bool KeypressHandler::MapKeyToEqCommand(class KeyCombo const &,int,unsigned int),KeypressHandler__MapKeyToEqCommand); +#endif +#ifdef KeypressHandler__IsReservedKey_x +FUNCTION_AT_ADDRESS(bool KeypressHandler::IsReservedKey(class KeyCombo const &)const ,KeypressHandler__IsReservedKey); +#endif +#ifdef KeypressHandler__LoadAndSetKeymappings_x +FUNCTION_AT_ADDRESS(void KeypressHandler::LoadAndSetKeymappings(void),KeypressHandler__LoadAndSetKeymappings); +#endif +#ifdef KeypressHandler__LoadKeymapping_x +FUNCTION_AT_ADDRESS(bool KeypressHandler::LoadKeymapping(unsigned int,int,class KeyCombo *),KeypressHandler__LoadKeymapping); +#endif +#ifdef KeypressHandler__SaveKeymapping_x +FUNCTION_AT_ADDRESS(void KeypressHandler::SaveKeymapping(unsigned int,class KeyCombo const &,int),KeypressHandler__SaveKeymapping); +#endif +#ifdef KeypressHandler__GetEqCommandSaveName_x +FUNCTION_AT_ADDRESS(class CXStr KeypressHandler::GetEqCommandSaveName(unsigned int,int)const ,KeypressHandler__GetEqCommandSaveName); +#endif +#ifdef KeypressHandler__LoadAndConvertOldKeymappingFormat_x +FUNCTION_AT_ADDRESS(bool KeypressHandler::LoadAndConvertOldKeymappingFormat(unsigned int,int,class KeyCombo *),KeypressHandler__LoadAndConvertOldKeymappingFormat); +#endif +#ifdef KeypressHandler__ClearCommandStateArray_x +FUNCTION_AT_ADDRESS(void KeypressHandler::ClearCommandStateArray(void),KeypressHandler__ClearCommandStateArray); +#endif +#ifdef MemoryPoolManager__MemoryPoolManager_x +FUNCTION_AT_ADDRESS( MemoryPoolManager::MemoryPoolManager(void),MemoryPoolManager__MemoryPoolManager); +#endif +#ifdef MemoryPoolManager__dMemoryPoolManager_x +FUNCTION_AT_ADDRESS( MemoryPoolManager::~MemoryPoolManager(void),MemoryPoolManager__dMemoryPoolManager); +#endif +#ifdef MemoryPoolManager__Alloc_x +FUNCTION_AT_ADDRESS(void * MemoryPoolManager::Alloc(int),MemoryPoolManager__Alloc); +#endif +#ifdef MemoryPoolManager__Free_x +FUNCTION_AT_ADDRESS(void MemoryPoolManager::Free(void *),MemoryPoolManager__Free); +#endif +#ifdef PacketPackerManager__SetPriority_x +FUNCTION_AT_ADDRESS(void PacketPackerManager::SetPriority(class PacketPacker *,__int64),PacketPackerManager__SetPriority); +#endif +#ifdef PacketPackerManager__RemovePacker_x +FUNCTION_AT_ADDRESS(void PacketPackerManager::RemovePacker(class PacketPacker *),PacketPackerManager__RemovePacker); +#endif +#ifdef PacketPackerManager__UnpackGetFirst_x +FUNCTION_AT_ADDRESS(bool __cdecl PacketPackerManager::UnpackGetFirst(struct PacketPackerState *,unsigned __int32,unsigned char *,int),PacketPackerManager__UnpackGetFirst); +#endif +#ifdef PacketPackerManager__UnpackGetNext_x +FUNCTION_AT_ADDRESS(bool __cdecl PacketPackerManager::UnpackGetNext(struct PacketPackerState *),PacketPackerManager__UnpackGetNext); +#endif +#ifdef PacketPacker__SendStatUpdate_x +FUNCTION_AT_ADDRESS(void PacketPacker::SendStatUpdate(struct _statUpdate *,bool),PacketPacker__SendStatUpdate); +#endif +#ifdef PacketPacker__FlushPositions_x +FUNCTION_AT_ADDRESS(void PacketPacker::FlushPositions(void),PacketPacker__FlushPositions); +#endif +#ifdef PacketPacker__SendPacket_x +FUNCTION_AT_ADDRESS(void PacketPacker::SendPacket(unsigned __int32,void *,int,bool),PacketPacker__SendPacket); +#endif +#ifdef PacketPacker__AddPacketToBuffer_x +//FUNCTION_AT_ADDRESS(void PacketPacker::AddPacketToBuffer(struct PacketPacker::PacketBuffer *,unsigned __int32,void *,int),PacketPacker__AddPacketToBuffer); +#endif +#ifdef PacketPacker__ScheduleUs_x +FUNCTION_AT_ADDRESS(void PacketPacker::ScheduleUs(void),PacketPacker__ScheduleUs); +#endif +#ifdef PacketPacker__Flush_x +FUNCTION_AT_ADDRESS(void PacketPacker::Flush(void),PacketPacker__Flush); +#endif +#ifdef PacketPacker__FlushBuffer_x +//FUNCTION_AT_ADDRESS(void PacketPacker::FlushBuffer(struct PacketPacker::PacketBuffer *),PacketPacker__FlushBuffer); +#endif +#ifdef PacketPacker__Disassociate_x +FUNCTION_AT_ADDRESS(void PacketPacker::Disassociate(void),PacketPacker__Disassociate); +#endif +#ifdef CResolutionHandler__Init_x +FUNCTION_AT_ADDRESS(int __cdecl CResolutionHandler::Init(void),CResolutionHandler__Init); +#endif +#ifdef CResolutionHandler__Shutdown_x +FUNCTION_AT_ADDRESS(void __cdecl CResolutionHandler::Shutdown(void),CResolutionHandler__Shutdown); +#endif +#ifdef CResolutionHandler__SaveSettings_x +FUNCTION_AT_ADDRESS(void __cdecl CResolutionHandler::SaveSettings(void),CResolutionHandler__SaveSettings); +#endif +#ifdef CResolutionHandler__ToggleScreenMode_x +FUNCTION_AT_ADDRESS(void __cdecl CResolutionHandler::ToggleScreenMode(void),CResolutionHandler__ToggleScreenMode); +#endif +#ifdef CResolutionHandler__ChangeToResolution_x +FUNCTION_AT_ADDRESS(void __cdecl CResolutionHandler::ChangeToResolution(int,int,int,int,int),CResolutionHandler__ChangeToResolution); +#endif +#ifdef CResolutionHandler__UpdateWindowPosition_x +FUNCTION_AT_ADDRESS(void __cdecl CResolutionHandler::UpdateWindowPosition(void),CResolutionHandler__UpdateWindowPosition); +#endif +#ifdef CResolutionHandler__GetDesktopWidth_x +FUNCTION_AT_ADDRESS(int __cdecl CResolutionHandler::GetDesktopWidth(void),CResolutionHandler__GetDesktopWidth); +#endif +#ifdef CResolutionHandler__GetDesktopHeight_x +FUNCTION_AT_ADDRESS(int __cdecl CResolutionHandler::GetDesktopHeight(void),CResolutionHandler__GetDesktopHeight); +#endif +#ifdef CResolutionHandler__GetDesktopBitsPerPixel_x +FUNCTION_AT_ADDRESS(int __cdecl CResolutionHandler::GetDesktopBitsPerPixel(void),CResolutionHandler__GetDesktopBitsPerPixel); +#endif +#ifdef CResolutionHandler__GetDesktopRefreshRate_x +FUNCTION_AT_ADDRESS(int __cdecl CResolutionHandler::GetDesktopRefreshRate(void),CResolutionHandler__GetDesktopRefreshRate); +#endif +#ifdef CResolutionHandler__GetWidth_x +FUNCTION_AT_ADDRESS(int __cdecl CResolutionHandler::GetWidth(void),CResolutionHandler__GetWidth); +#endif +#ifdef CResolutionHandler__GetHeight_x +FUNCTION_AT_ADDRESS(int __cdecl CResolutionHandler::GetHeight(void),CResolutionHandler__GetHeight); +#endif +#ifdef CResolutionHandler__IsFullscreenAvailable_x +FUNCTION_AT_ADDRESS(bool __cdecl CResolutionHandler::IsFullscreenAvailable(void),CResolutionHandler__IsFullscreenAvailable); +#endif +#ifdef Util__AllocateString_x +FUNCTION_AT_ADDRESS(char * __cdecl Util::AllocateString(char *),Util__AllocateString); +#endif +#ifdef ChannelServerApi__AllocateString_x +FUNCTION_AT_ADDRESS(char * __cdecl ChannelServerApi::AllocateString(char *),ChannelServerApi__AllocateString); +#endif +#ifdef SoundManager__SoundManager_x +//FUNCTION_AT_ADDRESS( SoundManager::SoundManager(int,int,bool,int,int,bool,enum SpeakerType),SoundManager__SoundManager); +#endif +#ifdef SoundManager__dSoundManager_x +FUNCTION_AT_ADDRESS( SoundManager::~SoundManager(void),SoundManager__dSoundManager); +#endif +#ifdef SoundManager__AddPool_x +//FUNCTION_AT_ADDRESS(void SoundManager::AddPool(enum InstanceType,int,int),SoundManager__AddPool); +#endif +#ifdef SoundManager__GiveTime_x +FUNCTION_AT_ADDRESS(void SoundManager::GiveTime(void),SoundManager__GiveTime); +#endif +#ifdef SoundManager__SetMixAhead_x +FUNCTION_AT_ADDRESS(void SoundManager::SetMixAhead(int),SoundManager__SetMixAhead); +#endif +#ifdef SoundManager__GetListenerEnvironment_x +//FUNCTION_AT_ADDRESS(enum EnvironmentType SoundManager::GetListenerEnvironment(void),SoundManager__GetListenerEnvironment); +#endif +#ifdef SoundManager__SetListenerEnvironment_x +//FUNCTION_AT_ADDRESS(void SoundManager::SetListenerEnvironment(enum EnvironmentType),SoundManager__SetListenerEnvironment); +#endif +#ifdef SoundManager__SetListenerLocation_x +FUNCTION_AT_ADDRESS(void SoundManager::SetListenerLocation(float,float,float,float),SoundManager__SetListenerLocation); +#endif +#ifdef SoundManager__GetListenerLocation_x +FUNCTION_AT_ADDRESS(void SoundManager::GetListenerLocation(float *,float *,float *,float *),SoundManager__GetListenerLocation); +#endif +#ifdef SoundManager__BorrowInstance_x +//FUNCTION_AT_ADDRESS(class SoundInstance * SoundManager::BorrowInstance(enum InstanceType,int),SoundManager__BorrowInstance); +#endif +#ifdef SoundManager__ReturnInstance_x +FUNCTION_AT_ADDRESS(void SoundManager::ReturnInstance(class SoundInstance *),SoundManager__ReturnInstance); +#endif +#ifdef SoundManager__AssetGiveTime_x +FUNCTION_AT_ADDRESS(void SoundManager::AssetGiveTime(void),SoundManager__AssetGiveTime); +#endif +#ifdef SoundManager__AssetAdd_x +FUNCTION_AT_ADDRESS(void SoundManager::AssetAdd(class SoundAsset *),SoundManager__AssetAdd); +#endif +#ifdef SoundManager__AssetRemove_x +FUNCTION_AT_ADDRESS(void SoundManager::AssetRemove(class SoundAsset *),SoundManager__AssetRemove); +#endif +#ifdef SoundManager__AssetGet_x +FUNCTION_AT_ADDRESS(class SoundAsset * SoundManager::AssetGet(char *),SoundManager__AssetGet); +#endif +#ifdef SoundManager__StreamingPlay_x +FUNCTION_AT_ADDRESS(void SoundManager::StreamingPlay(char *),SoundManager__StreamingPlay); +#endif +#ifdef SoundManager__StreamingPause_x +FUNCTION_AT_ADDRESS(void SoundManager::StreamingPause(void),SoundManager__StreamingPause); +#endif +#ifdef SoundManager__StreamingStop_x +FUNCTION_AT_ADDRESS(void SoundManager::StreamingStop(void),SoundManager__StreamingStop); +#endif +#ifdef SoundManager__StreamingSetVolumeLevel_x +FUNCTION_AT_ADDRESS(void SoundManager::StreamingSetVolumeLevel(float),SoundManager__StreamingSetVolumeLevel); +#endif +#ifdef SoundManager__StreamingGetVolumeLevel_x +FUNCTION_AT_ADDRESS(float SoundManager::StreamingGetVolumeLevel(void),SoundManager__StreamingGetVolumeLevel); +#endif +#ifdef SoundManager__StreamingSetSongPosition_x +FUNCTION_AT_ADDRESS(void SoundManager::StreamingSetSongPosition(int),SoundManager__StreamingSetSongPosition); +#endif +#ifdef SoundManager__StreamingGetSongPosition_x +FUNCTION_AT_ADDRESS(int SoundManager::StreamingGetSongPosition(void),SoundManager__StreamingGetSongPosition); +#endif +#ifdef SoundManager__StreamingGetSongLength_x +FUNCTION_AT_ADDRESS(int SoundManager::StreamingGetSongLength(void),SoundManager__StreamingGetSongLength); +#endif +#ifdef SoundManager__StreamingStatus_x +//FUNCTION_AT_ADDRESS(enum StreamingStatus SoundManager::StreamingStatus(void),SoundManager__StreamingStatus); +#endif +#ifdef MusicManager__MusicEntry__MusicEntry_x +//FUNCTION_AT_ADDRESS( MusicManager::MusicEntry::MusicEntry(int,class SoundAsset *,int,float,int,int,int,int,int,int),MusicManager__MusicEntry__MusicEntry); +#endif +#ifdef MusicManager__MusicEntry__dMusicEntry_x +//FUNCTION_AT_ADDRESS( MusicManager::MusicEntry::~MusicEntry(void),MusicManager__MusicEntry__dMusicEntry); +#endif +#ifdef MusicManager__MusicEntry__AdjustVolume_x +//FUNCTION_AT_ADDRESS(void MusicManager::MusicEntry::AdjustVolume(float),MusicManager__MusicEntry__AdjustVolume); +#endif +#ifdef MusicManager__MusicEntry__FadeIn_x +//FUNCTION_AT_ADDRESS(void MusicManager::MusicEntry::FadeIn(float),MusicManager__MusicEntry__FadeIn); +#endif +#ifdef MusicManager__MusicEntry__FadeOut_x +//FUNCTION_AT_ADDRESS(void MusicManager::MusicEntry::FadeOut(bool),MusicManager__MusicEntry__FadeOut); +#endif +#ifdef SoundObject__SoundObject_x +//FUNCTION_AT_ADDRESS( SoundObject::SoundObject(void),SoundObject__SoundObject); +#endif +#ifdef SoundObject__Release_x +//FUNCTION_AT_ADDRESS(void SoundObject::Release(void),SoundObject__Release); +#endif +#ifdef SoundInstance__SoundInstance_x +//FUNCTION_AT_ADDRESS( SoundInstance::SoundInstance(class SoundManager *),SoundInstance__SoundInstance); +#endif +#ifdef SoundInstance__YourManagerDeleted_x +//FUNCTION_AT_ADDRESS(void SoundInstance::YourManagerDeleted(void),SoundInstance__YourManagerDeleted); +#endif +#ifdef flex_unit__clear_x +FUNCTION_AT_ADDRESS(void flex_unit::clear(void),flex_unit__clear); +#endif +#ifdef WaveInstance__WaveInstance_x +FUNCTION_AT_ADDRESS( WaveInstance::WaveInstance(class SoundManager *),WaveInstance__WaveInstance); +#endif +#ifdef Wave3dInstance__Wave3dInstance_x +FUNCTION_AT_ADDRESS( Wave3dInstance::Wave3dInstance(class SoundManager *),Wave3dInstance__Wave3dInstance); +#endif +#ifdef MidiInstance__MidiInstance_x +//FUNCTION_AT_ADDRESS( MidiInstance::MidiInstance(class SoundManager *),MidiInstance__MidiInstance); +#endif +#ifdef SoundAsset__SoundAsset_x +//FUNCTION_AT_ADDRESS( SoundAsset::SoundAsset(class SoundManager *,char *,char *,int),SoundAsset__SoundAsset); +#endif +#ifdef SoundAsset__GetType_x +//FUNCTION_AT_ADDRESS(enum AssetType SoundAsset::GetType(void),SoundAsset__GetType); +#endif +#ifdef SoundAsset__YourManagerDeleted_x +//FUNCTION_AT_ADDRESS(void SoundAsset::YourManagerDeleted(void),SoundAsset__YourManagerDeleted); +#endif +#ifdef SoundAsset__GiveTime_x +//FUNCTION_AT_ADDRESS(void SoundAsset::GiveTime(void),SoundAsset__GiveTime); +#endif +#ifdef SoundAsset__IsPlaying_x +//FUNCTION_AT_ADDRESS(bool SoundAsset::IsPlaying(void),SoundAsset__IsPlaying); +#endif +#ifdef SoundAsset__AdjustVolume_x +//FUNCTION_AT_ADDRESS(void SoundAsset::AdjustVolume(float,int),SoundAsset__AdjustVolume); +#endif +#ifdef SoundAsset__GetName_x +//FUNCTION_AT_ADDRESS(char * SoundAsset::GetName(void),SoundAsset__GetName); +#endif +#ifdef SoundAsset__Play_x +//FUNCTION_AT_ADDRESS(class SoundInstance * SoundAsset::Play(class SoundControl *),SoundAsset__Play); +#endif +#ifdef SoundAsset__Stop_x +//FUNCTION_AT_ADDRESS(void SoundAsset::Stop(void),SoundAsset__Stop); +#endif +#ifdef SoundControl__SoundControl_x +FUNCTION_AT_ADDRESS( SoundControl::SoundControl(void),SoundControl__SoundControl); +#endif +#ifdef SoundEmitter__SoundEmitter_x +//FUNCTION_AT_ADDRESS( SoundEmitter::SoundEmitter(class EmitterManager *,class SoundAsset *,int),SoundEmitter__SoundEmitter); +#endif +#ifdef SoundEmitter__SoundEmitter1_x +//FUNCTION_AT_ADDRESS( SoundEmitter::SoundEmitter(class EmitterManager *,class MusicManager *,int),SoundEmitter__SoundEmitter1); +#endif +#ifdef SoundEmitter__Init_x +//FUNCTION_AT_ADDRESS(void SoundEmitter::Init(void),SoundEmitter__Init); +#endif +#ifdef SoundEmitter__GiveTime_x +//FUNCTION_AT_ADDRESS(void SoundEmitter::GiveTime(void),SoundEmitter__GiveTime); +#endif +#ifdef SoundEmitter__ReleaseLoopingSound_x +//FUNCTION_AT_ADDRESS(void SoundEmitter::ReleaseLoopingSound(void),SoundEmitter__ReleaseLoopingSound); +#endif +#ifdef SoundEmitter__ResetTimer_x +//FUNCTION_AT_ADDRESS(void SoundEmitter::ResetTimer(void),SoundEmitter__ResetTimer); +#endif +#ifdef SoundEmitter__Move_x +//FUNCTION_AT_ADDRESS(void SoundEmitter::Move(float,float,float),SoundEmitter__Move); +#endif +#ifdef SoundEmitter__SetAsset_x +//FUNCTION_AT_ADDRESS(void SoundEmitter::SetAsset(class SoundAsset *),SoundEmitter__SetAsset); +#endif +#ifdef SoundEmitter__Enable_x +//FUNCTION_AT_ADDRESS(void SoundEmitter::Enable(bool),SoundEmitter__Enable); +#endif +#ifdef Mp3Manager__Mp3Manager_x +FUNCTION_AT_ADDRESS( Mp3Manager::Mp3Manager(class SoundManager *,class MusicManager *),Mp3Manager__Mp3Manager); +#endif +#ifdef Mp3Manager__dMp3Manager_x +FUNCTION_AT_ADDRESS( Mp3Manager::~Mp3Manager(void),Mp3Manager__dMp3Manager); +#endif +#ifdef Mp3Manager__GetSort_x +//FUNCTION_AT_ADDRESS(enum Mp3Manager::SortOrder Mp3Manager::GetSort(void),Mp3Manager__GetSort); +#endif +#ifdef Mp3Manager__Sort_x +//FUNCTION_AT_ADDRESS(void Mp3Manager::Sort(enum Mp3Manager::SortOrder),Mp3Manager__Sort); +#endif +#ifdef Mp3Manager__Stop_x +FUNCTION_AT_ADDRESS(void Mp3Manager::Stop(void),Mp3Manager__Stop); +#endif +#ifdef Mp3Manager__Play_x +FUNCTION_AT_ADDRESS(void Mp3Manager::Play(void),Mp3Manager__Play); +#endif +#ifdef Mp3Manager__Pause_x +FUNCTION_AT_ADDRESS(void Mp3Manager::Pause(void),Mp3Manager__Pause); +#endif +#ifdef Mp3Manager__Status_x +//FUNCTION_AT_ADDRESS(enum StreamingStatus Mp3Manager::Status(void),Mp3Manager__Status); +#endif +#ifdef Mp3Manager__GiveTime_x +FUNCTION_AT_ADDRESS(void Mp3Manager::GiveTime(void),Mp3Manager__GiveTime); +#endif +#ifdef Mp3Manager__Next_x +FUNCTION_AT_ADDRESS(void Mp3Manager::Next(void),Mp3Manager__Next); +#endif +#ifdef Mp3Manager__Back_x +FUNCTION_AT_ADDRESS(void Mp3Manager::Back(void),Mp3Manager__Back); +#endif +#ifdef Mp3Manager__GetSongLength_x +FUNCTION_AT_ADDRESS(int Mp3Manager::GetSongLength(void),Mp3Manager__GetSongLength); +#endif +#ifdef Mp3Manager__GetSongPosition_x +FUNCTION_AT_ADDRESS(int Mp3Manager::GetSongPosition(void),Mp3Manager__GetSongPosition); +#endif +#ifdef Mp3Manager__SetSongPosition_x +FUNCTION_AT_ADDRESS(void Mp3Manager::SetSongPosition(int),Mp3Manager__SetSongPosition); +#endif +#ifdef Mp3Manager__GetName_x +FUNCTION_AT_ADDRESS(char * Mp3Manager::GetName(int),Mp3Manager__GetName); +#endif +#ifdef Mp3Manager__Count_x +FUNCTION_AT_ADDRESS(int Mp3Manager::Count(void),Mp3Manager__Count); +#endif +#ifdef Mp3Manager__SetPosition_x +FUNCTION_AT_ADDRESS(void Mp3Manager::SetPosition(int),Mp3Manager__SetPosition); +#endif +#ifdef Mp3Manager__SetVolumeLevel_x +FUNCTION_AT_ADDRESS(void Mp3Manager::SetVolumeLevel(float),Mp3Manager__SetVolumeLevel); +#endif +#ifdef Mp3Manager__GetVolumeLevel_x +FUNCTION_AT_ADDRESS(float Mp3Manager::GetVolumeLevel(void),Mp3Manager__GetVolumeLevel); +#endif +#ifdef Mp3Manager__DeleteAll_x +FUNCTION_AT_ADDRESS(void Mp3Manager::DeleteAll(void),Mp3Manager__DeleteAll); +#endif +#ifdef Mp3Manager__Delete_x +FUNCTION_AT_ADDRESS(void Mp3Manager::Delete(int),Mp3Manager__Delete); +#endif +#ifdef Mp3Manager__SaveList_x +FUNCTION_AT_ADDRESS(void Mp3Manager::SaveList(char *),Mp3Manager__SaveList); +#endif +#ifdef Mp3Manager__Add_x +FUNCTION_AT_ADDRESS(int Mp3Manager::Add(char *),Mp3Manager__Add); +#endif +#ifdef Mp3Manager__InternalAdd_x +FUNCTION_AT_ADDRESS(int Mp3Manager::InternalAdd(char *,char *,int),Mp3Manager__InternalAdd); +#endif +#ifdef Mp3Manager__Entry__Entry_x +//FUNCTION_AT_ADDRESS( Mp3Manager::Entry::Entry(char *,char *,int,int),Mp3Manager__Entry__Entry); +#endif +#ifdef Mp3Manager__Entry__dEntry_x +//FUNCTION_AT_ADDRESS( Mp3Manager::Entry::~Entry(void),Mp3Manager__Entry__dEntry); +#endif +#ifdef EmitterManager__EmitterManager_x +FUNCTION_AT_ADDRESS( EmitterManager::EmitterManager(class SoundManager *),EmitterManager__EmitterManager); +#endif +#ifdef EmitterManager__dEmitterManager_x +FUNCTION_AT_ADDRESS( EmitterManager::~EmitterManager(void),EmitterManager__dEmitterManager); +#endif +#ifdef EmitterManager__Add_x +//FUNCTION_AT_ADDRESS(void EmitterManager::Add(class SoundEmitter *),EmitterManager__Add); +#endif +#ifdef EmitterManager__Remove_x +//FUNCTION_AT_ADDRESS(void EmitterManager::Remove(class SoundEmitter *),EmitterManager__Remove); +#endif +#ifdef EmitterManager__GiveTime_x +FUNCTION_AT_ADDRESS(void EmitterManager::GiveTime(void),EmitterManager__GiveTime); +#endif +#ifdef EmitterManager__GetEffectsLevel_x +FUNCTION_AT_ADDRESS(float EmitterManager::GetEffectsLevel(void),EmitterManager__GetEffectsLevel); +#endif +#ifdef EmitterManager__GetVolumeLevel_x +FUNCTION_AT_ADDRESS(float EmitterManager::GetVolumeLevel(void),EmitterManager__GetVolumeLevel); +#endif +#ifdef EmitterManager__SetEffectsLevel_x +FUNCTION_AT_ADDRESS(void EmitterManager::SetEffectsLevel(float),EmitterManager__SetEffectsLevel); +#endif +#ifdef EmitterManager__GetListenerLocation_x +FUNCTION_AT_ADDRESS(void EmitterManager::GetListenerLocation(float *,float *,float *,float *),EmitterManager__GetListenerLocation); +#endif +#ifdef MusicManager__MusicManager_x +FUNCTION_AT_ADDRESS( MusicManager::MusicManager(void),MusicManager__MusicManager); +#endif +#ifdef MusicManager__dMusicManager_x +FUNCTION_AT_ADDRESS( MusicManager::~MusicManager(void),MusicManager__dMusicManager); +#endif +#ifdef MusicManager__GiveTime_x +FUNCTION_AT_ADDRESS(void MusicManager::GiveTime(void),MusicManager__GiveTime); +#endif +#ifdef MusicManager__Clear_x +FUNCTION_AT_ADDRESS(void MusicManager::Clear(class SoundAsset *),MusicManager__Clear); +#endif +#ifdef MusicManager__SetVolumeLevel_x +FUNCTION_AT_ADDRESS(void MusicManager::SetVolumeLevel(float),MusicManager__SetVolumeLevel); +#endif +#ifdef MusicManager__Clear1_x +FUNCTION_AT_ADDRESS(void MusicManager::Clear(int),MusicManager__Clear1); +#endif +#ifdef MusicManager__Set_x +FUNCTION_AT_ADDRESS(void MusicManager::Set(int,class SoundAsset *,int,float,int,int,int,int,int,int),MusicManager__Set); +#endif +#ifdef MusicManager__Play_x +FUNCTION_AT_ADDRESS(void MusicManager::Play(int),MusicManager__Play); +#endif +#ifdef MusicManager__Stop_x +FUNCTION_AT_ADDRESS(void MusicManager::Stop(int),MusicManager__Stop); +#endif +#ifdef MusicManager__Enable_x +FUNCTION_AT_ADDRESS(void MusicManager::Enable(bool),MusicManager__Enable); +#endif +#ifdef SpellManager__SpellManager_x +FUNCTION_AT_ADDRESS( SpellManager::SpellManager(char *),SpellManager__SpellManager); +#endif +#ifdef SpellManager__dSpellManager_x +FUNCTION_AT_ADDRESS( SpellManager::~SpellManager(void),SpellManager__dSpellManager); +#endif +#ifdef CStoryWnd__CStoryWnd_x +FUNCTION_AT_ADDRESS( CStoryWnd::CStoryWnd(class CXWnd *),CStoryWnd__CStoryWnd); +#endif +#ifdef CStoryWnd__Init_x +FUNCTION_AT_ADDRESS(void CStoryWnd::Init(void),CStoryWnd__Init); +#endif +#ifdef CStoryWnd__SaveIni_x +FUNCTION_AT_ADDRESS(void CStoryWnd::SaveIni(void),CStoryWnd__SaveIni); +#endif +#ifdef CStoryWnd__ShowAuto_x +FUNCTION_AT_ADDRESS(bool CStoryWnd::ShowAuto(void),CStoryWnd__ShowAuto); +#endif +#ifdef CStoryWnd__HasNew_x +FUNCTION_AT_ADDRESS(bool CStoryWnd::HasNew(void),CStoryWnd__HasNew); +#endif +#ifdef CStoryWnd__Activate_x +FUNCTION_AT_ADDRESS(void CStoryWnd::Activate(void),CStoryWnd__Activate); +#endif +#ifdef CStoryWnd__SelectOldestNew_x +FUNCTION_AT_ADDRESS(void CStoryWnd::SelectOldestNew(void),CStoryWnd__SelectOldestNew); +#endif +#ifdef CStoryWnd__SelectIndex_x +FUNCTION_AT_ADDRESS(void CStoryWnd::SelectIndex(int),CStoryWnd__SelectIndex); +#endif +#ifdef StringItem__StringItem_x +FUNCTION_AT_ADDRESS( StringItem::StringItem(void),StringItem__StringItem); +#endif +#ifdef UdpReliableChannel__IncomingQueueEntry__IncomingQueueEntry_x +//FUNCTION_AT_ADDRESS( UdpReliableChannel::IncomingQueueEntry::IncomingQueueEntry(void),UdpReliableChannel__IncomingQueueEntry__IncomingQueueEntry); +#endif +#ifdef StringItem__dStringItem_x +FUNCTION_AT_ADDRESS( StringItem::~StringItem(void),StringItem__dStringItem); +#endif +#ifdef StringItem__load_x +FUNCTION_AT_ADDRESS(int StringItem::load(struct _iobuf *,int),StringItem__load); +#endif +#ifdef StringTable__StringTable_x +FUNCTION_AT_ADDRESS( StringTable::StringTable(void),StringTable__StringTable); +#endif +#ifdef StringTable__dStringTable_x +FUNCTION_AT_ADDRESS( StringTable::~StringTable(void),StringTable__dStringTable); +#endif +#ifdef StringTable__checkAlloc_x +FUNCTION_AT_ADDRESS(void StringTable::checkAlloc(void),StringTable__checkAlloc); +#endif +#ifdef StringTable__getString_x +FUNCTION_AT_ADDRESS(char * StringTable::getString(unsigned long,bool *),StringTable__getString); +#endif +#ifdef StringTable__findItem_x +FUNCTION_AT_ADDRESS(class StringItem * StringTable::findItem(unsigned long,int,int),StringTable__findItem); +#endif +#ifdef StringTable__load_x +FUNCTION_AT_ADDRESS(int StringTable::load(char const *,int),StringTable__load); +#endif +#ifdef StringTable__addItem_x +FUNCTION_AT_ADDRESS(void StringTable::addItem(class StringItem *),StringTable__addItem); +#endif +#ifdef UdpIpAddress__UdpIpAddress_x +FUNCTION_AT_ADDRESS( UdpIpAddress::UdpIpAddress(unsigned int),UdpIpAddress__UdpIpAddress); +#endif +#ifdef UdpManager__Params__Params_x +//FUNCTION_AT_ADDRESS( UdpManager::Params::Params(void),UdpManager__Params__Params); +#endif +#ifdef UdpManager__UdpManager_x +//FUNCTION_AT_ADDRESS( UdpManager::UdpManager(struct UdpManager::Params const *),UdpManager__UdpManager); +#endif +#ifdef UdpManager__PoolReturn_x +//FUNCTION_AT_ADDRESS(void UdpManager::PoolReturn(class PooledLogicalPacket *),UdpManager__PoolReturn); +#endif +#ifdef UdpManager__dUdpManager_x +FUNCTION_AT_ADDRESS( UdpManager::~UdpManager(void),UdpManager__dUdpManager); +#endif +#ifdef UdpManager__CreateAndBindSocket_x +FUNCTION_AT_ADDRESS(void UdpManager::CreateAndBindSocket(int),UdpManager__CreateAndBindSocket); +#endif +#ifdef UdpManager__CloseSocket_x +FUNCTION_AT_ADDRESS(void UdpManager::CloseSocket(void),UdpManager__CloseSocket); +#endif +#ifdef UdpManager__ProcessDisconnectPending_x +FUNCTION_AT_ADDRESS(void UdpManager::ProcessDisconnectPending(void),UdpManager__ProcessDisconnectPending); +#endif +#ifdef UdpManager__RemoveConnection_x +FUNCTION_AT_ADDRESS(void UdpManager::RemoveConnection(class UdpConnection *),UdpManager__RemoveConnection); +#endif +#ifdef UdpManager__AddConnection_x +FUNCTION_AT_ADDRESS(void UdpManager::AddConnection(class UdpConnection *),UdpManager__AddConnection); +#endif +#ifdef UdpManager__GiveTime_x +FUNCTION_AT_ADDRESS(bool UdpManager::GiveTime(int,bool),UdpManager__GiveTime); +#endif +#ifdef UdpManager__EstablishConnection_x +FUNCTION_AT_ADDRESS(class UdpConnection * UdpManager::EstablishConnection(char const *,int,int),UdpManager__EstablishConnection); +#endif +#ifdef UdpManager__KeepUntilDisconnected_x +FUNCTION_AT_ADDRESS(void UdpManager::KeepUntilDisconnected(class UdpConnection *),UdpManager__KeepUntilDisconnected); +#endif +#ifdef UdpManager__ResetStats_x +FUNCTION_AT_ADDRESS(void UdpManager::ResetStats(void),UdpManager__ResetStats); +#endif +#ifdef UdpManager__ActualReceive_x +//FUNCTION_AT_ADDRESS(class UdpManager::PacketHistoryEntry * UdpManager::ActualReceive(void),UdpManager__ActualReceive); +#endif +#ifdef UdpManager__ActualSend_x +FUNCTION_AT_ADDRESS(void UdpManager::ActualSend(unsigned char const *,int,class UdpIpAddress,int),UdpManager__ActualSend); +#endif +#ifdef UdpManager__ActualSendHelper_x +FUNCTION_AT_ADDRESS(void UdpManager::ActualSendHelper(unsigned char const *,int,class UdpIpAddress,int),UdpManager__ActualSendHelper); +#endif +#ifdef UdpManager__SendPortAlive_x +FUNCTION_AT_ADDRESS(void UdpManager::SendPortAlive(class UdpIpAddress,int),UdpManager__SendPortAlive); +#endif +#ifdef UdpManager__ProcessRawPacket_x +//FUNCTION_AT_ADDRESS(void UdpManager::ProcessRawPacket(class UdpManager::PacketHistoryEntry const *),UdpManager__ProcessRawPacket); +#endif +#ifdef UdpManager__AddressGetConnection_x +FUNCTION_AT_ADDRESS(class UdpConnection * UdpManager::AddressGetConnection(class UdpIpAddress,int)const ,UdpManager__AddressGetConnection); +#endif +#ifdef UdpManager__ConnectCodeGetConnection_x +FUNCTION_AT_ADDRESS(class UdpConnection * UdpManager::ConnectCodeGetConnection(int)const ,UdpManager__ConnectCodeGetConnection); +#endif +#ifdef UdpManager__WrappedBorrow_x +//FUNCTION_AT_ADDRESS(class WrappedLogicalPacket * UdpManager::WrappedBorrow(class LogicalPacket const *),UdpManager__WrappedBorrow); +#endif +#ifdef UdpManager__WrappedCreated_x +//FUNCTION_AT_ADDRESS(void UdpManager::WrappedCreated(class WrappedLogicalPacket *),UdpManager__WrappedCreated); +#endif +#ifdef UdpManager__WrappedDestroyed_x +//FUNCTION_AT_ADDRESS(void UdpManager::WrappedDestroyed(class WrappedLogicalPacket *),UdpManager__WrappedDestroyed); +#endif +#ifdef UdpManager__CreatePacket_x +FUNCTION_AT_ADDRESS(class LogicalPacket * UdpManager::CreatePacket(void const *,int,void const *,int),UdpManager__CreatePacket); +#endif +#ifdef UdpManager__PoolCreated_x +//FUNCTION_AT_ADDRESS(void UdpManager::PoolCreated(class PooledLogicalPacket *),UdpManager__PoolCreated); +#endif +#ifdef UdpManager__PoolDestroyed_x +//FUNCTION_AT_ADDRESS(void UdpManager::PoolDestroyed(class PooledLogicalPacket *),UdpManager__PoolDestroyed); +#endif +#ifdef UdpManager__PacketHistoryEntry__PacketHistoryEntry_x +//FUNCTION_AT_ADDRESS( UdpManager::PacketHistoryEntry::PacketHistoryEntry(int),UdpManager__PacketHistoryEntry__PacketHistoryEntry); +#endif +#ifdef UdpManager__PacketHistoryEntry__dPacketHistoryEntry_x +//FUNCTION_AT_ADDRESS( UdpManager::PacketHistoryEntry::~PacketHistoryEntry(void),UdpManager__PacketHistoryEntry__dPacketHistoryEntry); +#endif +#ifdef UdpManager__SimulateQueueEntry__dSimulateQueueEntry_x +//FUNCTION_AT_ADDRESS( UdpManager::SimulateQueueEntry::~SimulateQueueEntry(void),UdpManager__SimulateQueueEntry__dSimulateQueueEntry); +#endif +#ifdef UdpConnection__UdpConnection_x +FUNCTION_AT_ADDRESS( UdpConnection::UdpConnection(class UdpManager *,class UdpIpAddress,int,int),UdpConnection__UdpConnection); +#endif +#ifdef UdpConnection__UdpConnection1_x +//FUNCTION_AT_ADDRESS( UdpConnection::UdpConnection(class UdpManager *,class UdpManager::PacketHistoryEntry const *),UdpConnection__UdpConnection1); +#endif +#ifdef UdpConnection__Init_x +FUNCTION_AT_ADDRESS(void UdpConnection::Init(class UdpManager *,class UdpIpAddress,int),UdpConnection__Init); +#endif +#ifdef UdpConnection__dUdpConnection_x +FUNCTION_AT_ADDRESS( UdpConnection::~UdpConnection(void),UdpConnection__dUdpConnection); +#endif +#ifdef UdpConnection__PortUnreachable_x +FUNCTION_AT_ADDRESS(void UdpConnection::PortUnreachable(void),UdpConnection__PortUnreachable); +#endif +#ifdef UdpConnection__InternalDisconnect_x +//FUNCTION_AT_ADDRESS(void UdpConnection::InternalDisconnect(int,enum UdpConnection::DisconnectReason),UdpConnection__InternalDisconnect); +#endif +#ifdef UdpConnection__ScheduleTimeNow_x +FUNCTION_AT_ADDRESS(void UdpConnection::ScheduleTimeNow(void),UdpConnection__ScheduleTimeNow); +#endif +#ifdef UdpConnection__SendTerminatePacket_x +//FUNCTION_AT_ADDRESS(void UdpConnection::SendTerminatePacket(int,enum UdpConnection::DisconnectReason),UdpConnection__SendTerminatePacket); +#endif +#ifdef UdpMisc__PutValue32_x +FUNCTION_AT_ADDRESS(int __cdecl UdpMisc::PutValue32(void *,unsigned int),UdpMisc__PutValue32); +#endif +#ifdef UdpConnection__SetSilentDisconnect_x +FUNCTION_AT_ADDRESS(void UdpConnection::SetSilentDisconnect(bool),UdpConnection__SetSilentDisconnect); +#endif +#ifdef UdpConnection__Send_x +//FUNCTION_AT_ADDRESS(bool UdpConnection::Send(enum UdpChannel,void const *,int),UdpConnection__Send); +#endif +#ifdef UdpConnection__InternalSend_x +//FUNCTION_AT_ADDRESS(bool UdpConnection::InternalSend(enum UdpChannel,unsigned char const *,int,unsigned char const *,int),UdpConnection__InternalSend); +#endif +#ifdef UdpConnection__PingStatReset_x +FUNCTION_AT_ADDRESS(void UdpConnection::PingStatReset(void),UdpConnection__PingStatReset); +#endif +#ifdef UdpConnection__ProcessRawPacket_x +//FUNCTION_AT_ADDRESS(void UdpConnection::ProcessRawPacket(class UdpManager::PacketHistoryEntry const *),UdpConnection__ProcessRawPacket); +#endif +#ifdef UdpMisc__GetValue24_x +FUNCTION_AT_ADDRESS(unsigned int __cdecl UdpMisc::GetValue24(void const *),UdpMisc__GetValue24); +#endif +#ifdef UdpConnection__IsNonEncryptPacket_x +FUNCTION_AT_ADDRESS(bool UdpConnection::IsNonEncryptPacket(unsigned char const *)const ,UdpConnection__IsNonEncryptPacket); +#endif +#ifdef UdpConnection__CallbackRoutePacket_x +FUNCTION_AT_ADDRESS(void UdpConnection::CallbackRoutePacket(unsigned char const *,int),UdpConnection__CallbackRoutePacket); +#endif +#ifdef UdpConnection__CallbackCorruptPacket_x +//FUNCTION_AT_ADDRESS(void UdpConnection::CallbackCorruptPacket(unsigned char const *,int,enum UdpCorruptionReason),UdpConnection__CallbackCorruptPacket); +#endif +#ifdef UdpConnection__ProcessCookedPacket_x +FUNCTION_AT_ADDRESS(void UdpConnection::ProcessCookedPacket(unsigned char const *,int),UdpConnection__ProcessCookedPacket); +#endif +#ifdef UdpMisc__PutValue64_x +FUNCTION_AT_ADDRESS(int __cdecl UdpMisc::PutValue64(void *,__int64),UdpMisc__PutValue64); +#endif +#ifdef UdpMisc__GetValue64_x +FUNCTION_AT_ADDRESS(__int64 __cdecl UdpMisc::GetValue64(void const *),UdpMisc__GetValue64); +#endif +#ifdef UdpReliableChannel__AckPacket_x +FUNCTION_AT_ADDRESS(void UdpReliableChannel::AckPacket(unsigned char const *,int),UdpReliableChannel__AckPacket); +#endif +#ifdef UdpConnection__GiveTime_x +FUNCTION_AT_ADDRESS(void UdpConnection::GiveTime(void),UdpConnection__GiveTime); +#endif +#ifdef UdpConnection__InternalGiveTime_x +FUNCTION_AT_ADDRESS(void UdpConnection::InternalGiveTime(void),UdpConnection__InternalGiveTime); +#endif +#ifdef UdpConnection__LastReceive_x +FUNCTION_AT_ADDRESS(int UdpConnection::LastReceive(void)const ,UdpConnection__LastReceive); +#endif +#ifdef UdpConnection__ConnectionAge_x +FUNCTION_AT_ADDRESS(int UdpConnection::ConnectionAge(void)const ,UdpConnection__ConnectionAge); +#endif +#ifdef UdpConnection__TotalPendingBytes_x +FUNCTION_AT_ADDRESS(int UdpConnection::TotalPendingBytes(void)const ,UdpConnection__TotalPendingBytes); +#endif +#ifdef UdpConnection__RawSend_x +FUNCTION_AT_ADDRESS(void UdpConnection::RawSend(unsigned char const *,int),UdpConnection__RawSend); +#endif +#ifdef UdpConnection__ExpireSendBin_x +FUNCTION_AT_ADDRESS(int UdpConnection::ExpireSendBin(void),UdpConnection__ExpireSendBin); +#endif +#ifdef UdpConnection__ExpireReceiveBin_x +FUNCTION_AT_ADDRESS(int UdpConnection::ExpireReceiveBin(void),UdpConnection__ExpireReceiveBin); +#endif +#ifdef UdpConnection__PhysicalSend_x +FUNCTION_AT_ADDRESS(void UdpConnection::PhysicalSend(unsigned char const *,int,bool),UdpConnection__PhysicalSend); +#endif +#ifdef UdpMisc__PutValue24_x +FUNCTION_AT_ADDRESS(int __cdecl UdpMisc::PutValue24(void *,unsigned int),UdpMisc__PutValue24); +#endif +#ifdef UdpConnection__BufferedSend_x +FUNCTION_AT_ADDRESS(unsigned char * UdpConnection::BufferedSend(unsigned char const *,int,unsigned char const *,int,bool),UdpConnection__BufferedSend); +#endif +#ifdef UdpConnection__FlushMultiBuffer_x +FUNCTION_AT_ADDRESS(void UdpConnection::FlushMultiBuffer(void),UdpConnection__FlushMultiBuffer); +#endif +#ifdef UdpConnection__DecryptNone_x +FUNCTION_AT_ADDRESS(int UdpConnection::DecryptNone(unsigned char *,unsigned char const *,int),UdpConnection__DecryptNone); +#endif +#ifdef UdpConnection__EncryptNone_x +FUNCTION_AT_ADDRESS(int UdpConnection::EncryptNone(unsigned char *,unsigned char const *,int),UdpConnection__EncryptNone); +#endif +#ifdef UdpConnection__EncryptUserSupplied_x +FUNCTION_AT_ADDRESS(int UdpConnection::EncryptUserSupplied(unsigned char *,unsigned char const *,int),UdpConnection__EncryptUserSupplied); +#endif +#ifdef UdpConnection__DecryptUserSupplied_x +FUNCTION_AT_ADDRESS(int UdpConnection::DecryptUserSupplied(unsigned char *,unsigned char const *,int),UdpConnection__DecryptUserSupplied); +#endif +#ifdef UdpConnection__EncryptUserSupplied2_x +FUNCTION_AT_ADDRESS(int UdpConnection::EncryptUserSupplied2(unsigned char *,unsigned char const *,int),UdpConnection__EncryptUserSupplied2); +#endif +#ifdef UdpConnection__DecryptUserSupplied2_x +FUNCTION_AT_ADDRESS(int UdpConnection::DecryptUserSupplied2(unsigned char *,unsigned char const *,int),UdpConnection__DecryptUserSupplied2); +#endif +#ifdef UdpConnection__EncryptXorBuffer_x +FUNCTION_AT_ADDRESS(int UdpConnection::EncryptXorBuffer(unsigned char *,unsigned char const *,int),UdpConnection__EncryptXorBuffer); +#endif +#ifdef UdpConnection__DecryptXorBuffer_x +FUNCTION_AT_ADDRESS(int UdpConnection::DecryptXorBuffer(unsigned char *,unsigned char const *,int),UdpConnection__DecryptXorBuffer); +#endif +#ifdef UdpConnection__EncryptXor_x +FUNCTION_AT_ADDRESS(int UdpConnection::EncryptXor(unsigned char *,unsigned char const *,int),UdpConnection__EncryptXor); +#endif +#ifdef UdpConnection__DecryptXor_x +FUNCTION_AT_ADDRESS(int UdpConnection::DecryptXor(unsigned char *,unsigned char const *,int),UdpConnection__DecryptXor); +#endif +#ifdef UdpConnection__SetupEncryptModel_x +FUNCTION_AT_ADDRESS(void UdpConnection::SetupEncryptModel(void),UdpConnection__SetupEncryptModel); +#endif +#ifdef UdpConnection__GetChannelStatus_x +//FUNCTION_AT_ADDRESS(void UdpConnection::GetChannelStatus(enum UdpChannel,struct UdpConnection::ChannelStatus *)const ,UdpConnection__GetChannelStatus); +#endif +#ifdef UdpReliableChannel__UdpReliableChannel_x +//FUNCTION_AT_ADDRESS( UdpReliableChannel::UdpReliableChannel(int,class UdpConnection *,struct UdpManager::ReliableConfig *),UdpReliableChannel__UdpReliableChannel); +#endif +#ifdef UdpReliableChannel__dUdpReliableChannel_x +FUNCTION_AT_ADDRESS( UdpReliableChannel::~UdpReliableChannel(void),UdpReliableChannel__dUdpReliableChannel); +#endif +#ifdef UdpReliableChannel__Send_x +FUNCTION_AT_ADDRESS(void UdpReliableChannel::Send(unsigned char const *,int,unsigned char const *,int),UdpReliableChannel__Send); +#endif +#ifdef UdpReliableChannel__FlushCoalesce_x +FUNCTION_AT_ADDRESS(void UdpReliableChannel::FlushCoalesce(void),UdpReliableChannel__FlushCoalesce); +#endif +#ifdef UdpReliableChannel__SendCoalesce_x +FUNCTION_AT_ADDRESS(void UdpReliableChannel::SendCoalesce(unsigned char const *,int,unsigned char const *,int),UdpReliableChannel__SendCoalesce); +#endif +#ifdef UdpReliableChannel__QueueLogicalPacket_x +FUNCTION_AT_ADDRESS(void UdpReliableChannel::QueueLogicalPacket(class LogicalPacket const *),UdpReliableChannel__QueueLogicalPacket); +#endif +#ifdef UdpReliableChannel__PullDown_x +FUNCTION_AT_ADDRESS(bool UdpReliableChannel::PullDown(int),UdpReliableChannel__PullDown); +#endif +#ifdef UdpReliableChannel__GiveTime_x +FUNCTION_AT_ADDRESS(int UdpReliableChannel::GiveTime(void),UdpReliableChannel__GiveTime); +#endif +#ifdef UdpReliableChannel__GetChannelStatus_x +//FUNCTION_AT_ADDRESS(void UdpReliableChannel::GetChannelStatus(struct UdpConnection::ChannelStatus *)const ,UdpReliableChannel__GetChannelStatus); +#endif +#ifdef UdpReliableChannel__ReliablePacket_x +FUNCTION_AT_ADDRESS(void UdpReliableChannel::ReliablePacket(unsigned char const *,int),UdpReliableChannel__ReliablePacket); +#endif +#ifdef UdpReliableChannel__GetReliableIncomingId_x +FUNCTION_AT_ADDRESS(__int64 UdpReliableChannel::GetReliableIncomingId(int)const ,UdpReliableChannel__GetReliableIncomingId); +#endif +#ifdef UdpReliableChannel__ProcessPacket_x +//FUNCTION_AT_ADDRESS(void UdpReliableChannel::ProcessPacket(enum UdpReliableChannel::ReliablePacketMode,unsigned char const *,int),UdpReliableChannel__ProcessPacket); +#endif +#ifdef UdpReliableChannel__AckAllPacket_x +FUNCTION_AT_ADDRESS(void UdpReliableChannel::AckAllPacket(unsigned char const *,int),UdpReliableChannel__AckAllPacket); +#endif +#ifdef UdpReliableChannel__Ack_x +FUNCTION_AT_ADDRESS(void UdpReliableChannel::Ack(__int64),UdpReliableChannel__Ack); +#endif +#ifdef UdpReliableChannel__IncomingQueueEntry__dIncomingQueueEntry_x +//FUNCTION_AT_ADDRESS( UdpReliableChannel::IncomingQueueEntry::~IncomingQueueEntry(void),UdpReliableChannel__IncomingQueueEntry__dIncomingQueueEntry); +#endif +#ifdef UdpReliableChannel__PhysicalPacket__PhysicalPacket_x +//FUNCTION_AT_ADDRESS( UdpReliableChannel::PhysicalPacket::PhysicalPacket(void),UdpReliableChannel__PhysicalPacket__PhysicalPacket); +#endif +#ifdef UdpReliableChannel__PhysicalPacket__dPhysicalPacket_x +//FUNCTION_AT_ADDRESS( UdpReliableChannel::PhysicalPacket::~PhysicalPacket(void),UdpReliableChannel__PhysicalPacket__dPhysicalPacket); +#endif +#ifdef LogicalPacket__LogicalPacket_x +FUNCTION_AT_ADDRESS( LogicalPacket::LogicalPacket(void),LogicalPacket__LogicalPacket); +#endif +#ifdef SoundObject__AddRef_x +//FUNCTION_AT_ADDRESS(void SoundObject::AddRef(void),SoundObject__AddRef); +#endif +#ifdef Mp3Manager__GetPosition_x +FUNCTION_AT_ADDRESS(int Mp3Manager::GetPosition(void),Mp3Manager__GetPosition); +#endif +#ifdef SimpleLogicalPacket__SimpleLogicalPacket_x +FUNCTION_AT_ADDRESS( SimpleLogicalPacket::SimpleLogicalPacket(void const *,int),SimpleLogicalPacket__SimpleLogicalPacket); +#endif +#ifdef EmitterManager__SetVolumeLevel_x +FUNCTION_AT_ADDRESS(void EmitterManager::SetVolumeLevel(float),EmitterManager__SetVolumeLevel); +#endif +#ifdef PooledLogicalPacket__PooledLogicalPacket_x +//FUNCTION_AT_ADDRESS( PooledLogicalPacket::PooledLogicalPacket(class UdpManager *,int),PooledLogicalPacket__PooledLogicalPacket); +#endif +#ifdef ChannelServerApi__GetChannelCount_x +FUNCTION_AT_ADDRESS(int ChannelServerApi::GetChannelCount(void),ChannelServerApi__GetChannelCount); +#endif +#ifdef PooledLogicalPacket__SetData_x +//FUNCTION_AT_ADDRESS(void PooledLogicalPacket::SetData(void const *,int,void const *,int),PooledLogicalPacket__SetData); +#endif +#ifdef WrappedLogicalPacket__WrappedLogicalPacket_x +//FUNCTION_AT_ADDRESS( WrappedLogicalPacket::WrappedLogicalPacket(class UdpManager *),WrappedLogicalPacket__WrappedLogicalPacket); +#endif +#ifdef UdpManager__WrappedReturn_x +//FUNCTION_AT_ADDRESS(void UdpManager::WrappedReturn(class WrappedLogicalPacket *),UdpManager__WrappedReturn); +#endif +#ifdef WrappedLogicalPacket__SetLogicalPacket_x +//FUNCTION_AT_ADDRESS(void WrappedLogicalPacket::SetLogicalPacket(class LogicalPacket const *),WrappedLogicalPacket__SetLogicalPacket); +#endif +#ifdef UdpManager__SimulateQueueEntry__SimulateQueueEntry_x +//FUNCTION_AT_ADDRESS( UdpManager::SimulateQueueEntry::SimulateQueueEntry(unsigned char const *,int,class UdpIpAddress,int),UdpManager__SimulateQueueEntry__SimulateQueueEntry); +#endif +#ifdef UdpMisc__Clock_x +FUNCTION_AT_ADDRESS(__int64 __cdecl UdpMisc::Clock(void),UdpMisc__Clock); +#endif +#ifdef UdpMisc__SyncStampShortDeltaTime_x +FUNCTION_AT_ADDRESS(int __cdecl UdpMisc::SyncStampShortDeltaTime(unsigned short,unsigned short),UdpMisc__SyncStampShortDeltaTime); +#endif +#ifdef UdpMisc__Random_x +FUNCTION_AT_ADDRESS(int __cdecl UdpMisc::Random(int *),UdpMisc__Random); +#endif +#ifdef UdpMisc__Crc32_x +FUNCTION_AT_ADDRESS(int __cdecl UdpMisc::Crc32(void const *,int,int),UdpMisc__Crc32); +#endif +#ifdef UdpMisc__PutVariableValue_x +FUNCTION_AT_ADDRESS(unsigned int __cdecl UdpMisc::PutVariableValue(void *,unsigned int),UdpMisc__PutVariableValue); +#endif +#ifdef UdpMisc__GetVariableValue_x +FUNCTION_AT_ADDRESS(unsigned int __cdecl UdpMisc::GetVariableValue(void const *,unsigned int *),UdpMisc__GetVariableValue); +#endif +#ifdef UdpMisc__CreateQuickLogicalPacket_x +FUNCTION_AT_ADDRESS(class LogicalPacket * __cdecl UdpMisc::CreateQuickLogicalPacket(void const *,int,void const *,int),UdpMisc__CreateQuickLogicalPacket); +#endif +#ifdef Util__Stristr_x +//FUNCTION_AT_ADDRESS(char * __cdecl Util::Stristr(char *,char *),Util__Stristr); +#endif +#ifdef Util__StripCharacter_x +//FUNCTION_AT_ADDRESS(void __cdecl Util::StripCharacter(char *,char),Util__StripCharacter); +#endif +#ifdef Util__ClampLower_x +//FUNCTION_AT_ADDRESS(bool __cdecl Util::ClampLower(int *,int),Util__ClampLower); +#endif +#ifdef Util__ClampUpper_x +//FUNCTION_AT_ADDRESS(bool __cdecl Util::ClampUpper(int *,int),Util__ClampUpper); +#endif +#ifdef Util__GetNextStringToken_x +//FUNCTION_AT_ADDRESS(int __cdecl Util::GetNextStringToken(char *,char *,int,char *,bool),Util__GetNextStringToken); +#endif +#ifdef Util__IsDelimiter_x +//FUNCTION_AT_ADDRESS(bool __cdecl Util::IsDelimiter(char,char *),Util__IsDelimiter); +#endif +#ifdef Util__Crc32_x +//FUNCTION_AT_ADDRESS(int __cdecl Util::Crc32(void const *,int,int),Util__Crc32); +#endif +#ifdef Util__GetSavePrivateProfileInt_x +//FUNCTION_AT_ADDRESS(int __cdecl Util::GetSavePrivateProfileInt(char *,char *,int,char *),Util__GetSavePrivateProfileInt); +#endif +#ifdef Util__PutValueVariable_x +//FUNCTION_AT_ADDRESS(int __cdecl Util::PutValueVariable(void *,unsigned int),Util__PutValueVariable); +#endif +#ifdef Util__PutValue32_x +//FUNCTION_AT_ADDRESS(unsigned int __cdecl Util::PutValue32(void *,unsigned int),Util__PutValue32); +#endif +#ifdef Util__GetValueVariable_x +//FUNCTION_AT_ADDRESS(int __cdecl Util::GetValueVariable(void const *,unsigned int *),Util__GetValueVariable); +#endif +#ifdef TextFileReader__TextFileReader_x +FUNCTION_AT_ADDRESS( TextFileReader::TextFileReader(char *,char),TextFileReader__TextFileReader); +#endif +#ifdef TextFileReader__dTextFileReader_x +FUNCTION_AT_ADDRESS( TextFileReader::~TextFileReader(void),TextFileReader__dTextFileReader); +#endif +#ifdef TextFileReader__ReadLine_x +FUNCTION_AT_ADDRESS(int TextFileReader::ReadLine(void),TextFileReader__ReadLine); +#endif +#ifdef TextFileReader__GetNextField_x +FUNCTION_AT_ADDRESS(int TextFileReader::GetNextField(char *,int),TextFileReader__GetNextField); +#endif +#ifdef TextFileReader__GetLine_x +FUNCTION_AT_ADDRESS(void TextFileReader::GetLine(char *,int),TextFileReader__GetLine); +#endif +#ifdef TextFileReader__IsOpen_x +FUNCTION_AT_ADDRESS(bool TextFileReader::IsOpen(void),TextFileReader__IsOpen); +#endif +#ifdef flex_unit__get_x +FUNCTION_AT_ADDRESS(unsigned int flex_unit::get(unsigned int)const ,flex_unit__get); +#endif +#ifdef flex_unit__flex_unit_x +FUNCTION_AT_ADDRESS( flex_unit::flex_unit(void),flex_unit__flex_unit); +#endif +#ifdef flex_unit__dflex_unit_x +FUNCTION_AT_ADDRESS( flex_unit::~flex_unit(void),flex_unit__dflex_unit); +#endif +#ifdef flex_unit__reserve_x +FUNCTION_AT_ADDRESS(void flex_unit::reserve(unsigned int),flex_unit__reserve); +#endif +#ifdef flex_unit__set_x +FUNCTION_AT_ADDRESS(void flex_unit::set(unsigned int,unsigned int),flex_unit__set); +#endif +#ifdef flex_unit__fast_mul_x +FUNCTION_AT_ADDRESS(void flex_unit::fast_mul(class flex_unit &,class flex_unit &,unsigned int),flex_unit__fast_mul); +#endif +#ifdef vlong_value__is_zero_x +FUNCTION_AT_ADDRESS(int vlong_value::is_zero(void)const ,vlong_value__is_zero); +#endif +#ifdef vlong_value__test_x +FUNCTION_AT_ADDRESS(int vlong_value::test(unsigned int)const ,vlong_value__test); +#endif +#ifdef vlong_value__bits_x +FUNCTION_AT_ADDRESS(unsigned int vlong_value::bits(void)const ,vlong_value__bits); +#endif +#ifdef vlong_value__cf_x +FUNCTION_AT_ADDRESS(int vlong_value::cf(class vlong_value &)const ,vlong_value__cf); +#endif +#ifdef vlong_value__shl_x +FUNCTION_AT_ADDRESS(void vlong_value::shl(void),vlong_value__shl); +#endif +#ifdef vlong_value__shr_x +FUNCTION_AT_ADDRESS(void vlong_value::shr(void),vlong_value__shr); +#endif +#ifdef vlong_value__shr1_x +FUNCTION_AT_ADDRESS(void vlong_value::shr(unsigned int),vlong_value__shr1); +#endif +#ifdef vlong_value__add_x +FUNCTION_AT_ADDRESS(void vlong_value::add(class vlong_value &),vlong_value__add); +#endif +#ifdef vlong_value__subtract_x +FUNCTION_AT_ADDRESS(void vlong_value::subtract(class vlong_value &),vlong_value__subtract); +#endif +#ifdef vlong_value__init_x +FUNCTION_AT_ADDRESS(void vlong_value::init(unsigned int),vlong_value__init); +#endif +#ifdef vlong_value__init2_x +FUNCTION_AT_ADDRESS(void vlong_value::init2(unsigned int,unsigned int),vlong_value__init2); +#endif +#ifdef vlong_value__copy_x +FUNCTION_AT_ADDRESS(void vlong_value::copy(class vlong_value &),vlong_value__copy); +#endif +#ifdef vlong_value__vlong_value_x +FUNCTION_AT_ADDRESS( vlong_value::vlong_value(void),vlong_value__vlong_value); +#endif +#ifdef vlong_value__mul_x +FUNCTION_AT_ADDRESS(void vlong_value::mul(class vlong_value &,class vlong_value &),vlong_value__mul); +#endif +#ifdef vlong_value__divide_x +FUNCTION_AT_ADDRESS(void vlong_value::divide(class vlong_value &,class vlong_value &,class vlong_value &),vlong_value__divide); +#endif +#ifdef vlong_value__dvlong_value_x +FUNCTION_AT_ADDRESS( vlong_value::~vlong_value(void),vlong_value__dvlong_value); +#endif +#ifdef vlong__docopy_x +FUNCTION_AT_ADDRESS(void vlong::docopy(void),vlong__docopy); +#endif +#ifdef vlong__cf_x +//FUNCTION_AT_ADDRESS(int vlong::cf(class vlong)const ,vlong__cf); +#endif +#ifdef vlong__vlong_x +FUNCTION_AT_ADDRESS( vlong::vlong(unsigned __int64),vlong__vlong); +#endif +#ifdef vlong__vlong1_x +FUNCTION_AT_ADDRESS( vlong::vlong(class vlong const &),vlong__vlong1); +#endif +#ifdef vlong__operator_equal_x +FUNCTION_AT_ADDRESS(class vlong & vlong::operator=(class vlong),vlong__operator_equal); +#endif +#ifdef vlong__dvlong_x +FUNCTION_AT_ADDRESS( vlong::~vlong(void),vlong__dvlong); +#endif +#ifdef vlong__operator_plus_equal_x +FUNCTION_AT_ADDRESS(class vlong & vlong::operator+=(class vlong const &),vlong__operator_plus_equal); +#endif +#ifdef vlong__operator_minus_equal_x +FUNCTION_AT_ADDRESS(class vlong & vlong::operator-=(class vlong const &),vlong__operator_minus_equal); +#endif +#ifdef monty__monty_x +FUNCTION_AT_ADDRESS( monty::monty(class vlong const &),monty__monty); +#endif +#ifdef monty__mul_x +FUNCTION_AT_ADDRESS(void monty::mul(class vlong &,class vlong const &),monty__mul); +#endif +#ifdef monty__exp_x +FUNCTION_AT_ADDRESS(class vlong monty::exp(class vlong const &,class vlong const &),monty__exp); +#endif +#ifdef monty__dmonty_x +FUNCTION_AT_ADDRESS( monty::~monty(void),monty__dmonty); +#endif +#ifdef ZlibUtil__zcalloc_x +FUNCTION_AT_ADDRESS(void * __cdecl ZlibUtil::zcalloc(void *,unsigned int,unsigned int),ZlibUtil__zcalloc); +#endif +#ifdef ZlibUtil__zfree_x +FUNCTION_AT_ADDRESS(void __cdecl ZlibUtil::zfree(void *,void *),ZlibUtil__zfree); +#endif +#ifdef ZlibUtil__zcompress_x +FUNCTION_AT_ADDRESS(int __cdecl ZlibUtil::zcompress(unsigned char *,unsigned long *,unsigned char const *,unsigned long,int),ZlibUtil__zcompress); +#endif +#ifdef ZlibUtil__zuncompress_x +FUNCTION_AT_ADDRESS(int __cdecl ZlibUtil::zuncompress(unsigned char *,unsigned long *,unsigned char const *,unsigned long),ZlibUtil__zuncompress); +#endif +#ifdef ZlibUtil__Compress_x +FUNCTION_AT_ADDRESS(int __cdecl ZlibUtil::Compress(char const *,int,char *,int,int),ZlibUtil__Compress); +#endif +#ifdef ZlibUtil__Decompress_x +FUNCTION_AT_ADDRESS(int __cdecl ZlibUtil::Decompress(char const *,int,char *,int),ZlibUtil__Decompress); +#endif +#ifdef PackFS__PackFS_x +FUNCTION_AT_ADDRESS( PackFS::PackFS(void),PackFS__PackFS); +#endif +#ifdef PackFS__addFileSystem_x +//FUNCTION_AT_ADDRESS(bool PackFS::addFileSystem(class FilePath),PackFS__addFileSystem); +#endif +#ifdef PackFS__removeFileSystem_x +FUNCTION_AT_ADDRESS(void PackFS::removeFileSystem(class FilePath),PackFS__removeFileSystem); +#endif +#ifdef SharedString___updateTag_x +FUNCTION_AT_ADDRESS(void SharedString::_updateTag(void)const ,SharedString___updateTag); +#endif +#ifdef FilePath__FilePath2_x +FUNCTION_AT_ADDRESS( FilePath::FilePath(void),FilePath__FilePath2); +#endif +#ifdef PackFile__dPackFile_x +FUNCTION_AT_ADDRESS( PackFile::~PackFile(void),PackFile__dPackFile); +#endif +#ifdef PackFile__close_x +FUNCTION_AT_ADDRESS(void PackFile::close(void),PackFile__close); +#endif +#ifdef _PackFileData__d_PackFileData_x +FUNCTION_AT_ADDRESS( _PackFileData::~_PackFileData(void),_PackFileData__d_PackFileData); +#endif +#ifdef PackFile__length_x +FUNCTION_AT_ADDRESS(int PackFile::length(void)const ,PackFile__length); +#endif +#ifdef PackFile__read_x +FUNCTION_AT_ADDRESS(int PackFile::read(void * const,int),PackFile__read); +#endif +#ifdef PackFS__openFile_x +//FUNCTION_AT_ADDRESS(bool PackFS::openFile(class FilePath,class PackFile *)const ,PackFS__openFile); +#endif +#ifdef CRC32Generator__generateCRC32_x +FUNCTION_AT_ADDRESS(unsigned int CRC32Generator::generateCRC32(unsigned char const *,unsigned int)const ,CRC32Generator__generateCRC32); +#endif +#ifdef CRC32Generator__updateCRC32_x +FUNCTION_AT_ADDRESS(unsigned int CRC32Generator::updateCRC32(unsigned int,unsigned char const *,unsigned int)const ,CRC32Generator__updateCRC32); +#endif +#ifdef CSidlScreenWnd__dCSidlScreenWnd_x +FUNCTION_AT_ADDRESS( CSidlScreenWnd::~CSidlScreenWnd(void),CSidlScreenWnd__dCSidlScreenWnd); +#endif +#ifdef CSidlScreenWnd__WndNotification_x +FUNCTION_AT_ADDRESS( int CSidlScreenWnd::WndNotification(class CXWnd *,unsigned __int32,void *),CSidlScreenWnd__WndNotification); +#endif +#ifdef CSidlScreenWnd__CSidlScreenWnd_x +FUNCTION_AT_ADDRESS( CSidlScreenWnd::CSidlScreenWnd(class CXWnd *,unsigned __int32,class CXRect,class CXStr),CSidlScreenWnd__CSidlScreenWnd); +#endif +#ifdef CSidlScreenWnd__CSidlScreenWnd1_x +FUNCTION_AT_ADDRESS( CSidlScreenWnd::CSidlScreenWnd(class CXWnd *x,class CXStr*,int,int,char *),CSidlScreenWnd__CSidlScreenWnd1); +#endif +#ifdef CSidlScreenWnd__CSidlScreenWnd2_x +FUNCTION_AT_ADDRESS( CSidlScreenWnd::CSidlScreenWnd(class CXWnd *x,class CXStr),CSidlScreenWnd__CSidlScreenWnd2); +#endif +#ifdef CSidlScreenWnd__Init_x +FUNCTION_AT_ADDRESS(void CSidlScreenWnd::Init(class CXWnd *,unsigned __int32,class CXRect,class CXStr,int,char *),CSidlScreenWnd__Init); +#endif +#ifdef CSidlScreenWnd__Init1_x +FUNCTION_AT_ADDRESS(void CSidlScreenWnd::Init(int,class CXStr*,int,int,int),CSidlScreenWnd__Init1); +#endif +#ifdef CSidlScreenWnd__SetScreen_x +FUNCTION_AT_ADDRESS(void CSidlScreenWnd::SetScreen(class CXStr*),CSidlScreenWnd__SetScreen); +#endif +#ifdef CSidlScreenWnd__LoadSidlScreen_x +FUNCTION_AT_ADDRESS(void CSidlScreenWnd::LoadSidlScreen(void),CSidlScreenWnd__LoadSidlScreen); +#endif +#ifdef CSidlScreenWnd__CalculateVSBRange_x +FUNCTION_AT_ADDRESS(void CSidlScreenWnd::CalculateVSBRange(void),CSidlScreenWnd__CalculateVSBRange); +#endif +#ifdef CSidlScreenWnd__CalculateHSBRange_x +FUNCTION_AT_ADDRESS(void CSidlScreenWnd::CalculateHSBRange(void),CSidlScreenWnd__CalculateHSBRange); +#endif +#ifdef CSidlScreenWnd__DrawSidlPiece_x +FUNCTION_AT_ADDRESS(int CSidlScreenWnd::DrawSidlPiece(class CScreenPieceTemplate *,class CXRect,class CXRect)const ,CSidlScreenWnd__DrawSidlPiece); +#endif +#ifdef CSidlScreenWnd__GetSidlPiece_x +FUNCTION_AT_ADDRESS(class CScreenPieceTemplate * CSidlScreenWnd::GetSidlPiece(class CXStr*, int dummy)const ,CSidlScreenWnd__GetSidlPiece); +#endif +#ifdef CSidlScreenWnd__GetSidlPieceRect_x +FUNCTION_AT_ADDRESS(class CXRect CSidlScreenWnd::GetSidlPieceRect(class CScreenPieceTemplate *,class CXRect)const ,CSidlScreenWnd__GetSidlPieceRect); +#endif +#ifdef CSidlScreenWnd__AddButtonToRadioGroup_x +FUNCTION_AT_ADDRESS(void CSidlScreenWnd::AddButtonToRadioGroup(class CXStr,class CButtonWnd *),CSidlScreenWnd__AddButtonToRadioGroup); +#endif +#ifdef CRadioGroup__CRadioGroup_x +FUNCTION_AT_ADDRESS( CRadioGroup::CRadioGroup(class CXStr),CRadioGroup__CRadioGroup); +#endif +#ifdef CRadioGroup__GetName_x +FUNCTION_AT_ADDRESS(class CXStr CRadioGroup::GetName(void)const ,CRadioGroup__GetName); +#endif +#ifdef CSidlScreenWnd__CreateChildrenFromSidl_x +FUNCTION_AT_ADDRESS(void CSidlScreenWnd::CreateChildrenFromSidl(void),CSidlScreenWnd__CreateChildrenFromSidl); +#endif +#ifdef CSidlScreenWnd__StoreIniVis_x +FUNCTION_AT_ADDRESS(void CSidlScreenWnd::StoreIniVis(void),CSidlScreenWnd__StoreIniVis); +#endif +#ifdef CSidlScreenWnd__EnableIniStorage_x +FUNCTION_AT_ADDRESS(void CSidlScreenWnd::EnableIniStorage(int,char *),CSidlScreenWnd__EnableIniStorage); +#endif +#ifdef CSidlScreenWnd__ConvertToRes_x +FUNCTION_AT_ADDRESS(int CSidlScreenWnd::ConvertToRes(int,int,int,int),CSidlScreenWnd__ConvertToRes); +#endif +#ifdef CSidlScreenWnd__GetChildItem_x +FUNCTION_AT_ADDRESS(class CXWnd * CSidlScreenWnd::GetChildItem(CXStr const &),CSidlScreenWnd__GetChildItem); +#endif +#ifdef CSidlScreenWnd__LoadIniListWnd_x +FUNCTION_AT_ADDRESS(void CSidlScreenWnd::LoadIniListWnd(class CListWnd *,char *),CSidlScreenWnd__LoadIniListWnd); +#endif +#ifdef CSidlScreenWnd__StoreIniListWnd_x +FUNCTION_AT_ADDRESS(void CSidlScreenWnd::StoreIniListWnd(class CListWnd const *,char *),CSidlScreenWnd__StoreIniListWnd); +#endif +#ifdef CXWndDrawTemplate__CXWndDrawTemplate_x +FUNCTION_AT_ADDRESS( CXWndDrawTemplate::CXWndDrawTemplate(void),CXWndDrawTemplate__CXWndDrawTemplate); +#endif +#ifdef CUITextureInfo__CUITextureInfo1_x +FUNCTION_AT_ADDRESS( CUITextureInfo::CUITextureInfo(void),CUITextureInfo__CUITextureInfo1); +#endif +#ifdef CButtonDrawTemplate__CButtonDrawTemplate_x +FUNCTION_AT_ADDRESS( CButtonDrawTemplate::CButtonDrawTemplate(void),CButtonDrawTemplate__CButtonDrawTemplate); +#endif +#ifdef CScrollbarTemplate__dCScrollbarTemplate_x +FUNCTION_AT_ADDRESS( CScrollbarTemplate::~CScrollbarTemplate(void),CScrollbarTemplate__dCScrollbarTemplate); +#endif +#ifdef CXWndDrawTemplate__dCXWndDrawTemplate_x +FUNCTION_AT_ADDRESS( CXWndDrawTemplate::~CXWndDrawTemplate(void),CXWndDrawTemplate__dCXWndDrawTemplate); +#endif +#ifdef CButtonDrawTemplate__GetSize_x +FUNCTION_AT_ADDRESS(class CXSize CButtonDrawTemplate::GetSize(void)const ,CButtonDrawTemplate__GetSize); +#endif +#ifdef CXWnd__CXWnd_x +FUNCTION_AT_ADDRESS( CXWnd::CXWnd(class CXWnd *,unsigned __int32,class CXRect),CXWnd__CXWnd); +#endif +#ifdef CXWnd__IsType_x +//FUNCTION_AT_ADDRESS(bool CXWnd::IsType(enum EWndRuntimeType)const ,CXWnd__IsType); +#endif +#ifdef CXWnd__SetFocus_x +FUNCTION_AT_ADDRESS(class CXWnd * CXWnd::SetFocus(void),CXWnd__SetFocus); +#endif +#ifdef CXWnd__ClrFocus_x +FUNCTION_AT_ADDRESS(void CXWnd::ClrFocus(void),CXWnd__ClrFocus); +#endif +#ifdef CXWnd__HasFocus_x +FUNCTION_AT_ADDRESS(bool CXWnd::HasFocus(void)const ,CXWnd__HasFocus); +#endif +#ifdef CXWnd__Show_x +FUNCTION_AT_ADDRESS(int CXWnd::Show(bool,bool),CXWnd__Show); +#endif +#ifdef CXWnd__DrawCloseBox_x +FUNCTION_AT_ADDRESS(int CXWnd::DrawCloseBox(void)const ,CXWnd__DrawCloseBox); +#endif +#ifdef CXWnd__DrawMinimizeBox_x +FUNCTION_AT_ADDRESS(int CXWnd::DrawMinimizeBox(void)const ,CXWnd__DrawMinimizeBox); +#endif +#ifdef CXWnd__DrawTileBox_x +FUNCTION_AT_ADDRESS(int CXWnd::DrawTileBox(void)const ,CXWnd__DrawTileBox); +#endif +#ifdef CXWnd__DrawVScrollbar_x +FUNCTION_AT_ADDRESS(int CXWnd::DrawVScrollbar(int,int,int)const ,CXWnd__DrawVScrollbar); +#endif +#ifdef CXRect__CXRect_x +FUNCTION_AT_ADDRESS( CXRect::CXRect(int,int,int,int),CXRect__CXRect); +#endif +#ifdef CXRect__operator_equal_x +FUNCTION_AT_ADDRESS(class CXRect & CXRect::operator=(class CXRect const &),CXRect__operator_equal); +#endif +#ifdef CXWnd__DrawHScrollbar_x +FUNCTION_AT_ADDRESS(int CXWnd::DrawHScrollbar(int,int,int)const ,CXWnd__DrawHScrollbar); +#endif +#ifdef CXWnd__Refade_x +FUNCTION_AT_ADDRESS(void CXWnd::Refade(void),CXWnd__Refade); +#endif +#ifdef CXWnd__Move_x +FUNCTION_AT_ADDRESS(int CXWnd::Move(class CXPoint),CXWnd__Move); +#endif +#ifdef CXWnd__Move1_x +FUNCTION_AT_ADDRESS(int CXWnd::Move(class CXRect),CXWnd__Move1); +#endif +#ifdef CXPoint__operator_equal_x +FUNCTION_AT_ADDRESS(class CXPoint CXPoint::operator=(class CXPoint),CXPoint__operator_equal); +#endif +#ifdef CXWnd__ProcessTransition_x +FUNCTION_AT_ADDRESS(int CXWnd::ProcessTransition(void),CXWnd__ProcessTransition); +#endif +#ifdef CXWnd__BringToTop_x +FUNCTION_AT_ADDRESS(void CXWnd::BringToTop(bool),CXWnd__BringToTop); +#endif +#ifdef CXWnd__StartFade_x +FUNCTION_AT_ADDRESS(void CXWnd::StartFade(unsigned char,unsigned __int32),CXWnd__StartFade); +#endif +#ifdef CXWnd__Minimize_x +FUNCTION_AT_ADDRESS(int CXWnd::Minimize(bool),CXWnd__Minimize); +#endif +#ifdef CXWnd__IsReallyVisible_x +FUNCTION_AT_ADDRESS(bool CXWnd::IsReallyVisible(void)const ,CXWnd__IsReallyVisible); +#endif +#ifdef CXWnd__GetNextChildWnd_x +FUNCTION_AT_ADDRESS(class CXWnd * CXWnd::GetNextChildWnd(class CXWnd *)const ,CXWnd__GetNextChildWnd); +#endif +#ifdef CXWnd__GetChildWndAt_x +FUNCTION_AT_ADDRESS(class CXWnd * CXWnd::GetChildWndAt(class CXPoint)const ,CXWnd__GetChildWndAt); +#endif +#ifdef CXWnd__GetFirstChildWnd_x +FUNCTION_AT_ADDRESS(class CXWnd * CXWnd::GetFirstChildWnd(void)const ,CXWnd__GetFirstChildWnd); +#endif +#ifdef CXWnd__GetNextSib_x +FUNCTION_AT_ADDRESS(class CXWnd * CXWnd::GetNextSib(void)const ,CXWnd__GetNextSib); +#endif +#ifdef CXWnd__DoAllDrawing_x +FUNCTION_AT_ADDRESS(int CXWnd::DoAllDrawing(void)const ,CXWnd__DoAllDrawing); +#endif +#ifdef CXWnd__DrawLasso_x +FUNCTION_AT_ADDRESS(int __cdecl CXWnd::DrawLasso(class CXRect,unsigned long,class CXRect),CXWnd__DrawLasso); +#endif +#ifdef CXWnd__DrawChildren_x +FUNCTION_AT_ADDRESS(int CXWnd::DrawChildren(void)const ,CXWnd__DrawChildren); +#endif +#ifdef CXWnd__BringChildWndToTop_x +FUNCTION_AT_ADDRESS(void CXWnd::BringChildWndToTop(class CXWnd *),CXWnd__BringChildWndToTop); +#endif +#ifdef CXWnd__DrawColoredRect_x +FUNCTION_AT_ADDRESS(int __cdecl CXWnd::DrawColoredRect(class CXRect,unsigned long,class CXRect),CXWnd__DrawColoredRect); +#endif +#ifdef CXWnd__GetTooltipRect_x +FUNCTION_AT_ADDRESS(class CXRect __cdecl CXWnd::GetTooltipRect(class CXSize),CXWnd__GetTooltipRect); +#endif +#ifdef CXWnd__GetTooltipRect1_x +FUNCTION_AT_ADDRESS(class CXRect __cdecl CXWnd::GetTooltipRect(class CXPoint,class CXSize),CXWnd__GetTooltipRect1); +#endif +#ifdef CXWnd__DrawTooltipAtPoint_x +FUNCTION_AT_ADDRESS(void CXWnd::DrawTooltipAtPoint(class CXPoint)const ,CXWnd__DrawTooltipAtPoint); +#endif +#ifdef CXWnd__Bottom_x +FUNCTION_AT_ADDRESS(void CXWnd::Bottom(void),CXWnd__Bottom); +#endif +#ifdef CXWnd__Center_x +FUNCTION_AT_ADDRESS(void CXWnd::Center(void),CXWnd__Center); +#endif +#ifdef CXWnd__Right_x +FUNCTION_AT_ADDRESS(void CXWnd::Right(void),CXWnd__Right); +#endif +#ifdef CXWnd__Left_x +FUNCTION_AT_ADDRESS(void CXWnd::Left(void),CXWnd__Left); +#endif +#ifdef CXWnd__SetLookLikeParent_x +FUNCTION_AT_ADDRESS(void CXWnd::SetLookLikeParent(void),CXWnd__SetLookLikeParent); +#endif +#ifdef CXWnd__GetClientClipRect_x +FUNCTION_AT_ADDRESS(class CXRect CXWnd::GetClientClipRect(void)const ,CXWnd__GetClientClipRect); +#endif +#ifdef CXWnd__GetScreenClipRect_x +FUNCTION_AT_ADDRESS(class CXRect CXWnd::GetScreenClipRect(void)const ,CXWnd__GetScreenClipRect); +#endif +#ifdef CXWnd__IsActive_x +FUNCTION_AT_ADDRESS(bool CXWnd::IsActive(void)const ,CXWnd__IsActive); +#endif +#ifdef CXWnd__IsDescendantOf_x +FUNCTION_AT_ADDRESS(bool CXWnd::IsDescendantOf(class CXWnd const *)const ,CXWnd__IsDescendantOf); +#endif +#ifdef CXWnd__GetBorderFrame_x +FUNCTION_AT_ADDRESS(class CTAFrameDraw const * CXWnd::GetBorderFrame(void)const ,CXWnd__GetBorderFrame); +#endif +#ifdef CXWnd__GetTitlebarHeader_x +FUNCTION_AT_ADDRESS(class CTAFrameDraw const * CXWnd::GetTitlebarHeader(void)const ,CXWnd__GetTitlebarHeader); +#endif +#ifdef CXWnd__GetCloseBoxTemplate_x +FUNCTION_AT_ADDRESS(class CButtonDrawTemplate const * CXWnd::GetCloseBoxTemplate(void)const ,CXWnd__GetCloseBoxTemplate); +#endif +#ifdef CXWnd__GetMinimizeBoxTemplate_x +FUNCTION_AT_ADDRESS(class CButtonDrawTemplate const * CXWnd::GetMinimizeBoxTemplate(void)const ,CXWnd__GetMinimizeBoxTemplate); +#endif +#ifdef CXWnd__GetTileBoxTemplate_x +FUNCTION_AT_ADDRESS(class CButtonDrawTemplate const * CXWnd::GetTileBoxTemplate(void)const ,CXWnd__GetTileBoxTemplate); +#endif +#ifdef CXWnd__GetRelativeRect_x +FUNCTION_AT_ADDRESS(class CXRect CXWnd::GetRelativeRect(void)const ,CXWnd__GetRelativeRect); +#endif +#ifdef CXWnd__GetScreenRect_x +FUNCTION_AT_ADDRESS(class CXRect CXWnd::GetScreenRect(void)const ,CXWnd__GetScreenRect); +#endif +#ifdef CXWnd__Resize_x +FUNCTION_AT_ADDRESS(int CXWnd::Resize(int,int),CXWnd__Resize); +#endif +#ifdef CXWnd__GetChildItem_x +FUNCTION_AT_ADDRESS(class CXWnd * CXWnd::GetChildItem(CXStr const &),CXWnd__GetChildItem); +#endif +#ifdef CXWnd__SetZLayer_x +FUNCTION_AT_ADDRESS(void CXWnd::SetZLayer(int),CXWnd__SetZLayer); +#endif +#ifdef CXWnd__SetFirstChildPointer_x +FUNCTION_AT_ADDRESS(void CXWnd::SetFirstChildPointer(class CXWnd *),CXWnd__SetFirstChildPointer); +#endif +#ifdef CXWnd__SetNextSibPointer_x +FUNCTION_AT_ADDRESS(void CXWnd::SetNextSibPointer(class CXWnd *),CXWnd__SetNextSibPointer); +#endif +#ifdef CXWnd__SetMouseOver_x +FUNCTION_AT_ADDRESS(void CXWnd::SetMouseOver(bool),CXWnd__SetMouseOver); +#endif +#ifdef CXWnd__SetKeyTooltip_x +FUNCTION_AT_ADDRESS(void CXWnd::SetKeyTooltip(int,int),CXWnd__SetKeyTooltip); +#endif +#ifdef CXWnd__GetXMLTooltip_x +FUNCTION_AT_ADDRESS(class CXStr CXWnd::GetXMLTooltip(void)const ,CXWnd__GetXMLTooltip); +#endif +#ifdef CXWnd__DrawTooltip_x +FUNCTION_AT_ADDRESS(int CXWnd::DrawTooltip(class CXWnd const *)const,CXWnd__DrawTooltip); +#endif +#ifdef CMutexSyncCounted__CMutexSyncCounted_x +FUNCTION_AT_ADDRESS( CMutexSyncCounted::CMutexSyncCounted(void),CMutexSyncCounted__CMutexSyncCounted); +#endif +#ifdef CMutexSyncCounted__dCMutexSyncCounted_x +FUNCTION_AT_ADDRESS( CMutexSyncCounted::~CMutexSyncCounted(void),CMutexSyncCounted__dCMutexSyncCounted); +#endif +#ifdef CMutexLockCounted__dCMutexLockCounted_x +FUNCTION_AT_ADDRESS( CMutexLockCounted::~CMutexLockCounted(void),CMutexLockCounted__dCMutexLockCounted); +#endif +#ifdef CXStr__AssureCopy_x +FUNCTION_AT_ADDRESS(void CXStr::AssureCopy(void),CXStr__AssureCopy); +#endif +#ifdef CXStr__Assure_x +//FUNCTION_AT_ADDRESS(void CXStr::Assure(long,enum EStringEncoding),CXStr__Assure); +#endif +#ifdef CXStr__AllocRepNoLock_x +//FUNCTION_AT_ADDRESS(struct CStrRep * CXStr::AllocRepNoLock(long,enum EStringEncoding),CXStr__AllocRepNoLock); +#endif +#ifdef CXStr__FreeRep_x +FUNCTION_AT_ADDRESS(void CXStr::FreeRep(struct CStrRep *),CXStr__FreeRep); +#endif +#ifdef CXStr__FreeRepNoLock_x +FUNCTION_AT_ADDRESS(void CXStr::FreeRepNoLock(struct CStrRep *),CXStr__FreeRepNoLock); +#endif +#ifdef CXStr__CXStr2_x +FUNCTION_AT_ADDRESS( CXStr::CXStr(char),CXStr__CXStr2); +#endif +#ifdef CXStr__CXStr3_x +FUNCTION_AT_ADDRESS( CXStr::CXStr(char const *),CXStr__CXStr3); +#endif +#ifdef CXStr__CXStr4_x +FUNCTION_AT_ADDRESS( CXStr::CXStr(char const *,int),CXStr__CXStr4); +#endif +#ifdef CXStr__CXStr5_x +FUNCTION_AT_ADDRESS( CXStr::CXStr(unsigned short const *),CXStr__CXStr5); +#endif +#ifdef CXStr__CXStr6_x +FUNCTION_AT_ADDRESS( CXStr::CXStr(int,int,char),CXStr__CXStr6); +#endif +#ifdef CXStr__operator_equal_x +FUNCTION_AT_ADDRESS(class CXStr & CXStr::operator=(class CXStr const &),CXStr__operator_equal); +#endif +#ifdef CXStr__operator_equal1_x +FUNCTION_AT_ADDRESS(class CXStr & CXStr::operator=(char const *),CXStr__operator_equal1); +#endif +#define CINITIALIZE_EQGAME_OFFSET(var) DWORD var = (((DWORD)var##_x - 0x400000) + (DWORD)GetModuleHandle(NULL)) +#define CCXStr__operator_equal1_x CXStr__operator_equal1_x +#ifdef CCXStr__operator_equal1_x +CINITIALIZE_EQGAME_OFFSET(CCXStr__operator_equal1); +FUNCTION_AT_ADDRESS(class CCXStr& CCXStr::operator=(char const *), CCXStr__operator_equal1); +#endif +#ifdef CXStr__GetChar_x +FUNCTION_AT_ADDRESS(char CXStr::GetChar(long)const ,CXStr__GetChar); +#endif +#ifdef CXStr__SetChar_x +FUNCTION_AT_ADDRESS(char CXStr::SetChar(long,char),CXStr__SetChar); +#endif +#ifdef CXStr__GetUnicode_x +FUNCTION_AT_ADDRESS(unsigned short CXStr::GetUnicode(long)const ,CXStr__GetUnicode); +#endif +#ifdef CXStr__SetUnicode_x +FUNCTION_AT_ADDRESS(unsigned short CXStr::SetUnicode(long,unsigned short),CXStr__SetUnicode); +#endif +#ifdef CXStr__Compare_x +//FUNCTION_AT_ADDRESS(int CXStr::Compare(class CXStr const &,enum CompareCode)const ,CXStr__Compare); +#endif +#ifdef CXStr__CompareN_x +//FUNCTION_AT_ADDRESS(int CXStr::CompareN(class CXStr const &,int,enum CompareCode)const ,CXStr__CompareN); +#endif +#ifdef CXStr__operator_equal_equal_x +FUNCTION_AT_ADDRESS(int CXStr::operator==(class CXStr const &)const ,CXStr__operator_equal_equal); +#endif +#ifdef CXStr__operator_equal_equal1_x +FUNCTION_AT_ADDRESS(int CXStr::operator==(char const *)const ,CXStr__operator_equal_equal1); +#endif +#ifdef CXStr__operatort__x +FUNCTION_AT_ADDRESS(int CXStr::operator>(class CXStr const &)const ,CXStr__operatort_); +#endif +#ifdef CXStr__BlankPreAllocate_x +FUNCTION_AT_ADDRESS(void CXStr::BlankPreAllocate(int),CXStr__BlankPreAllocate); +#endif +#ifdef CXStr__operator_plus_equal_x +FUNCTION_AT_ADDRESS(void CXStr::operator+=(class CXStr const &),CXStr__operator_plus_equal); +#endif +#ifdef CXStr__operator_plus_equal1_x +FUNCTION_AT_ADDRESS(void CXStr::operator+=(char const *),CXStr__operator_plus_equal1); +#endif +#ifdef CXStr__operator_plus_equal2_x +FUNCTION_AT_ADDRESS(void CXStr::operator+=(char),CXStr__operator_plus_equal2); +#endif +#ifdef CXStr__operator_plus_equal3_x +FUNCTION_AT_ADDRESS(void CXStr::operator+=(unsigned short),CXStr__operator_plus_equal3); +#endif +#ifdef CXStr__Delete_x +FUNCTION_AT_ADDRESS(void CXStr::Delete(long,long),CXStr__Delete); +#endif +#ifdef CXStr__Insert_x +FUNCTION_AT_ADDRESS(void CXStr::Insert(long,char),CXStr__Insert); +#endif +#ifdef CXStr__Insert1_x +FUNCTION_AT_ADDRESS(void CXStr::Insert(long,class CXStr const &),CXStr__Insert1); +#endif +#ifdef CXStr__Copy_x +FUNCTION_AT_ADDRESS(class CXStr CXStr::Copy(long,long)const ,CXStr__Copy); +#endif +#ifdef CXStr__CopySelf_x +FUNCTION_AT_ADDRESS(void CXStr::CopySelf(long,long),CXStr__CopySelf); +#endif +#ifdef CXStr__StripTrailing_x +FUNCTION_AT_ADDRESS(void CXStr::StripTrailing(char),CXStr__StripTrailing); +#endif +#ifdef CXStr__StripLeading_x +FUNCTION_AT_ADDRESS(void CXStr::StripLeading(char),CXStr__StripLeading); +#endif +#ifdef CXStr__StripAll_x +FUNCTION_AT_ADDRESS(void CXStr::StripAll(char),CXStr__StripAll); +#endif +#ifdef CXStr__Strip_x +FUNCTION_AT_ADDRESS(void CXStr::Strip(char),CXStr__Strip); +#endif +#ifdef CXStr__GetEncoding_x +//FUNCTION_AT_ADDRESS(enum EStringEncoding CXStr::GetEncoding(void)const ,CXStr__GetEncoding); +#endif +#ifdef CXStr__SetEncoding_x +//FUNCTION_AT_ADDRESS(void CXStr::SetEncoding(enum EStringEncoding),CXStr__SetEncoding); +#endif +#ifdef CXStr__operator_char_p_x +//FUNCTION_AT_ADDRESS( CXStr::operator char *(void)const ,CXStr__operator_char_p); +#endif +#ifdef CXStr__operator_unsigned_short_p_x +//FUNCTION_AT_ADDRESS( CXStr::operator unsigned short *(void)const ,CXStr__operator_unsigned_short_p); +#endif +#ifdef CXStr__SetUpperCase_x +FUNCTION_AT_ADDRESS(void CXStr::SetUpperCase(void),CXStr__SetUpperCase); +#endif +#ifdef CXStr__SetLowerCase_x +FUNCTION_AT_ADDRESS(void CXStr::SetLowerCase(void),CXStr__SetLowerCase); +#endif +#ifdef CXStr__ConvertToInt_x +FUNCTION_AT_ADDRESS(int CXStr::ConvertToInt(void),CXStr__ConvertToInt); +#endif +#ifdef CXStr__PrintString_x +FUNCTION_AT_ADDRESS(int __cdecl CXStr::PrintString(char const *,...),CXStr__PrintString); +#endif +#ifdef CXStr__FindLast_x +FUNCTION_AT_ADDRESS(bool CXStr::FindLast(char,int &),CXStr__FindLast); +#endif +#ifdef CXStr__Find_x +FUNCTION_AT_ADDRESS(bool CXStr::Find(char,int &),CXStr__Find); +#endif +#ifdef CXStr__Find1_x +FUNCTION_AT_ADDRESS(bool CXStr::Find(unsigned short,int &),CXStr__Find1); +#endif +#ifdef CXStr__Find2_x +FUNCTION_AT_ADDRESS(bool CXStr::Find(class CXStr const &,int &),CXStr__Find2); +#endif +#ifdef CXStr__AddCr_x +FUNCTION_AT_ADDRESS(void CXStr::AddCr(void),CXStr__AddCr); +#endif +#ifdef CXStr__Utf8ToUnicode_x +FUNCTION_AT_ADDRESS(int __cdecl CXStr::Utf8ToUnicode(char const *,unsigned short *,int),CXStr__Utf8ToUnicode); +#endif +#ifdef CXStr__LenUnicodeToUtf8_x +FUNCTION_AT_ADDRESS(int __cdecl CXStr::LenUnicodeToUtf8(unsigned short const *),CXStr__LenUnicodeToUtf8); +#endif +#ifdef CXStr__UnicodeToUtf8_x +FUNCTION_AT_ADDRESS(int __cdecl CXStr::UnicodeToUtf8(unsigned short const *,char *,int),CXStr__UnicodeToUtf8); +#endif +#ifdef CListWnd__CListWnd_x +FUNCTION_AT_ADDRESS( CListWnd::CListWnd(class CXWnd *,unsigned __int32,class CXRect),CListWnd__CListWnd); +#endif +#ifdef CListWnd__GetCurSel_x +FUNCTION_AT_ADDRESS(int CListWnd::GetCurSel(void)const,CListWnd__GetCurSel); +#endif +#ifdef CListWnd__GetCurCol_x +FUNCTION_AT_ADDRESS(int CListWnd::GetCurCol(void)const ,CListWnd__GetCurCol); +#endif +#ifdef CListWnd__GetItemData_x +FUNCTION_AT_ADDRESS(unsigned __int32 CListWnd::GetItemData(int)const ,CListWnd__GetItemData); +#endif +#ifdef CListWnd__GetItemText_x +FUNCTION_AT_ADDRESS(class CXStr *CListWnd::GetItemText(class CXStr *,int,int)const ,CListWnd__GetItemText); +#endif +#ifdef CListWnd__GetItemIcon_x +FUNCTION_AT_ADDRESS(class CTextureAnimation const * CListWnd::GetItemIcon(int,int)const ,CListWnd__GetItemIcon); +#endif +#ifdef CListWnd__GetItemColor_x +FUNCTION_AT_ADDRESS(unsigned long CListWnd::GetItemColor(int,int)const ,CListWnd__GetItemColor); +#endif +#ifdef CListWnd__GetColumnFlags_x +FUNCTION_AT_ADDRESS(unsigned __int32 CListWnd::GetColumnFlags(int)const ,CListWnd__GetColumnFlags); +#endif +#ifdef CListWnd__GetColumnWidth_x +FUNCTION_AT_ADDRESS(int CListWnd::GetColumnWidth(int)const ,CListWnd__GetColumnWidth); +#endif +#ifdef CListWnd__SetColumnWidth_x +FUNCTION_AT_ADDRESS(void CListWnd::SetColumnWidth(int,int),CListWnd__SetColumnWidth); +#endif +#ifdef CListWnd__ShiftColumnSeparator_x +FUNCTION_AT_ADDRESS(void CListWnd::ShiftColumnSeparator(int,int),CListWnd__ShiftColumnSeparator); +#endif +#ifdef CListWnd__GetColumnMinWidth_x +FUNCTION_AT_ADDRESS(int CListWnd::GetColumnMinWidth(int)const ,CListWnd__GetColumnMinWidth); +#endif +#ifdef CListWnd__GetColumnJustification_x +FUNCTION_AT_ADDRESS(int CListWnd::GetColumnJustification(int)const ,CListWnd__GetColumnJustification); +#endif +#ifdef CListWnd__SetColumnJustification_x +FUNCTION_AT_ADDRESS(void CListWnd::SetColumnJustification(int,int),CListWnd__SetColumnJustification); +#endif +#ifdef CListWnd__GetColumnLabel_x +FUNCTION_AT_ADDRESS(class CXStr CListWnd::GetColumnLabel(int)const ,CListWnd__GetColumnLabel); +#endif +#ifdef CListWnd__GetColumnAnimation_x +FUNCTION_AT_ADDRESS(class CTextureAnimation const * CListWnd::GetColumnAnimation(int)const ,CListWnd__GetColumnAnimation); +#endif +#ifdef CListWnd__GetColumnAnimationSelected_x +FUNCTION_AT_ADDRESS(class CTextureAnimation const * CListWnd::GetColumnAnimationSelected(int)const ,CListWnd__GetColumnAnimationSelected); +#endif +#ifdef CListWnd__GetColumnAnimationMouseOver_x +FUNCTION_AT_ADDRESS(class CTextureAnimation const * CListWnd::GetColumnAnimationMouseOver(int)const ,CListWnd__GetColumnAnimationMouseOver); +#endif +#ifdef CListWnd__AddLine_x +FUNCTION_AT_ADDRESS(int CListWnd::AddLine(class SListWndLine const *),CListWnd__AddLine); +#endif +#ifdef CListWnd__AddString_x +FUNCTION_AT_ADDRESS(int CListWnd::AddString(const CXStr &Str, COLORREF Color, uint32_t Data, const CTextureAnimation *pTa, const char*TooltipStr), CListWnd__AddString); +#endif +#ifdef CListWnd__RemoveString_x +FUNCTION_AT_ADDRESS(void CListWnd::RemoveString(int),CListWnd__RemoveString); +#endif +#ifdef CListWnd__RemoveLine_x +FUNCTION_AT_ADDRESS(void CListWnd::RemoveLine(int),CListWnd__RemoveLine); +#endif +#ifdef CListWnd__SetCurSel_x +FUNCTION_AT_ADDRESS(void CListWnd::SetCurSel(int),CListWnd__SetCurSel); +#endif +#ifdef CListWnd__ToggleSel_x +FUNCTION_AT_ADDRESS(void CListWnd::ToggleSel(int),CListWnd__ToggleSel); +#endif +#ifdef CListWnd__ExtendSel_x +FUNCTION_AT_ADDRESS(void CListWnd::ExtendSel(int),CListWnd__ExtendSel); +#endif +#ifdef CListWnd__ClearAllSel_x +FUNCTION_AT_ADDRESS(void CListWnd::ClearAllSel(void),CListWnd__ClearAllSel); +#endif +#ifdef CListWnd__ClearSel_x +FUNCTION_AT_ADDRESS(void CListWnd::ClearSel(int),CListWnd__ClearSel); +#endif +#ifdef CListWnd__SetItemData_x +FUNCTION_AT_ADDRESS(void CListWnd::SetItemData(int,unsigned __int32),CListWnd__SetItemData); +#endif +#ifdef CListWnd__SetItemText_x +FUNCTION_AT_ADDRESS(void CListWnd::SetItemText(int,int,class CXStr *),CListWnd__SetItemText); +#endif +#ifdef CListWnd__SetItemColor_x +FUNCTION_AT_ADDRESS(void CListWnd::SetItemColor(int,int,unsigned long),CListWnd__SetItemColor); +#endif +#ifdef CListWnd__IsLineEnabled_x +FUNCTION_AT_ADDRESS(bool CListWnd::IsLineEnabled(int)const ,CListWnd__IsLineEnabled); +#endif +#ifdef CListWnd__EnableLine_x +FUNCTION_AT_ADDRESS(void CListWnd::EnableLine(int,bool),CListWnd__EnableLine); +#endif +#ifdef CListWnd__AddColumn_x +FUNCTION_AT_ADDRESS(int CListWnd::AddColumn(class CXStr,int,unsigned __int32,unsigned __int32),CListWnd__AddColumn); +#endif +#ifdef CListWnd__AddColumn1_x +FUNCTION_AT_ADDRESS(int CListWnd::AddColumn(class CXStr,class CTextureAnimation *,int,unsigned __int32,unsigned __int32,class CTextureAnimation *,class CTextureAnimation *),CListWnd__AddColumn1); +#endif +#ifdef SListWndColumn__SListWndColumn_x +FUNCTION_AT_ADDRESS( SListWndColumn::SListWndColumn(class CXStr,int,class CTextureAnimation *,unsigned __int32,unsigned __int32,class CTextureAnimation *,class CTextureAnimation *),SListWndColumn__SListWndColumn); +#endif +#ifdef SLinkInfo__dSLinkInfo_x +//FUNCTION_AT_ADDRESS( SLinkInfo::~SLinkInfo(void),SLinkInfo__dSLinkInfo); +#endif +#ifdef SListWndCellEditUpdate__dSListWndCellEditUpdate_x +FUNCTION_AT_ADDRESS( SListWndCellEditUpdate::~SListWndCellEditUpdate(void),SListWndCellEditUpdate__dSListWndCellEditUpdate); +#endif +#ifdef SListWndColumn__dSListWndColumn_x +FUNCTION_AT_ADDRESS( SListWndColumn::~SListWndColumn(void),SListWndColumn__dSListWndColumn); +#endif +#ifdef CListWnd__SetColumnLabel_x +FUNCTION_AT_ADDRESS(void CListWnd::SetColumnLabel(int,class CXStr),CListWnd__SetColumnLabel); +#endif +#ifdef CXRect__CXRect1_x +FUNCTION_AT_ADDRESS( CXRect::CXRect(void),CXRect__CXRect1); +#endif +#ifdef CListWnd__GetItemHeight_x +FUNCTION_AT_ADDRESS(int CListWnd::GetItemHeight(int)const ,CListWnd__GetItemHeight); +#endif +#ifdef CListWnd__CalculateLineHeights_x +FUNCTION_AT_ADDRESS(void CListWnd::CalculateLineHeights(void),CListWnd__CalculateLineHeights); +#endif +#ifdef CListWnd__CalculateVSBRange_x +FUNCTION_AT_ADDRESS(void CListWnd::CalculateVSBRange(void),CListWnd__CalculateVSBRange); +#endif +#ifdef CListWnd__CalculateFirstVisibleLine_x +FUNCTION_AT_ADDRESS(void CListWnd::CalculateFirstVisibleLine(void),CListWnd__CalculateFirstVisibleLine); +#endif +#ifdef CListWnd__EnsureVisible_x +FUNCTION_AT_ADDRESS(void CListWnd::EnsureVisible(int),CListWnd__EnsureVisible); +#endif +#ifdef CListWnd__GetItemRect_x +FUNCTION_AT_ADDRESS(class CXRect CListWnd::GetItemRect(int,int)const ,CListWnd__GetItemRect); +#endif +#ifdef CListWnd__GetItemAtPoint_x +FUNCTION_AT_ADDRESS(int CListWnd::GetItemAtPoint(class CXPoint)const ,CListWnd__GetItemAtPoint); +#endif +#ifdef CListWnd__GetItemAtPoint1_x +FUNCTION_AT_ADDRESS(void CListWnd::GetItemAtPoint(class CXPoint,int *,int *)const ,CListWnd__GetItemAtPoint1); +#endif +#ifdef CListWnd__CloseAndUpdateEditWindow_x +FUNCTION_AT_ADDRESS(void CListWnd::CloseAndUpdateEditWindow(void),CListWnd__CloseAndUpdateEditWindow); +#endif +#ifdef CListWnd__SetColors_x +FUNCTION_AT_ADDRESS(void CListWnd::SetColors(unsigned long,unsigned long,unsigned long),CListWnd__SetColors); +#endif +#ifdef CListWnd__GetSeparatorRect_x +FUNCTION_AT_ADDRESS(class CXRect CListWnd::GetSeparatorRect(int)const ,CListWnd__GetSeparatorRect); +#endif +#ifdef SListWndSortInfo__dSListWndSortInfo_x +FUNCTION_AT_ADDRESS( SListWndSortInfo::~SListWndSortInfo(void),SListWndSortInfo__dSListWndSortInfo); +#endif +#ifdef CListWnd__GetHeaderRect_x +FUNCTION_AT_ADDRESS(class CXRect CListWnd::GetHeaderRect(int)const ,CListWnd__GetHeaderRect); +#endif +#ifdef SListWndLine__SListWndLine_x +FUNCTION_AT_ADDRESS( SListWndLine::SListWndLine(void),SListWndLine__SListWndLine); +#endif +#ifdef SListWndCell__operator_equal_x +FUNCTION_AT_ADDRESS(struct SListWndCell & SListWndCell::operator=(struct SListWndCell const &),SListWndCell__operator_equal); +#endif +#ifdef SListWndLine__operator_equal_x +FUNCTION_AT_ADDRESS(class SListWndLine & SListWndLine::operator=(class SListWndLine const &),SListWndLine__operator_equal); +#endif +#ifdef CScreenPieceTemplate__CScreenPieceTemplate_x +FUNCTION_AT_ADDRESS( CScreenPieceTemplate::CScreenPieceTemplate(class CParamScreenPiece *),CScreenPieceTemplate__CScreenPieceTemplate); +#endif +#ifdef CScreenPieceTemplate__IsType_x +FUNCTION_AT_ADDRESS(bool CScreenPieceTemplate::IsType(unsigned __int32)const ,CScreenPieceTemplate__IsType); +#endif +#ifdef CStaticScreenPieceTemplate__CStaticScreenPieceTemplate_x +FUNCTION_AT_ADDRESS( CStaticScreenPieceTemplate::CStaticScreenPieceTemplate(class CParamStaticScreenPiece *),CStaticScreenPieceTemplate__CStaticScreenPieceTemplate); +#endif +#ifdef CStaticAnimationTemplate__CStaticAnimationTemplate_x +FUNCTION_AT_ADDRESS( CStaticAnimationTemplate::CStaticAnimationTemplate(class CParamStaticAnimation *),CStaticAnimationTemplate__CStaticAnimationTemplate); +#endif +#ifdef CStaticTextTemplate__CStaticTextTemplate_x +FUNCTION_AT_ADDRESS( CStaticTextTemplate::CStaticTextTemplate(class CParamStaticText *),CStaticTextTemplate__CStaticTextTemplate); +#endif +#ifdef CStaticTextTemplate__SetText_x +FUNCTION_AT_ADDRESS(class CXStr CStaticTextTemplate::SetText(class CXStr),CStaticTextTemplate__SetText); +#endif +#ifdef CStaticFrameTemplate__CStaticFrameTemplate_x +FUNCTION_AT_ADDRESS( CStaticFrameTemplate::CStaticFrameTemplate(class CParamStaticFrame *),CStaticFrameTemplate__CStaticFrameTemplate); +#endif +#ifdef CStaticHeaderTemplate__CStaticHeaderTemplate_x +FUNCTION_AT_ADDRESS( CStaticHeaderTemplate::CStaticHeaderTemplate(class CParamStaticHeader *),CStaticHeaderTemplate__CStaticHeaderTemplate); +#endif +#ifdef CControlTemplate__CControlTemplate_x +FUNCTION_AT_ADDRESS( CControlTemplate::CControlTemplate(class CParamControl *),CControlTemplate__CControlTemplate); +#endif +#ifdef CListboxColumnTemplate__CListboxColumnTemplate_x +FUNCTION_AT_ADDRESS( CListboxColumnTemplate::CListboxColumnTemplate(class CParamListboxColumn *),CListboxColumnTemplate__CListboxColumnTemplate); +#endif +#ifdef CListboxTemplate__CListboxTemplate_x +FUNCTION_AT_ADDRESS( CListboxTemplate::CListboxTemplate(class CParamListbox *),CListboxTemplate__CListboxTemplate); +#endif +#ifdef CListboxColumnTemplate__dCListboxColumnTemplate_x +FUNCTION_AT_ADDRESS( CListboxColumnTemplate::~CListboxColumnTemplate(void),CListboxColumnTemplate__dCListboxColumnTemplate); +#endif +#ifdef CButtonTemplate__CButtonTemplate_x +FUNCTION_AT_ADDRESS( CButtonTemplate::CButtonTemplate(class CParamButton *),CButtonTemplate__CButtonTemplate); +#endif +#ifdef CGaugeTemplate__CGaugeTemplate_x +FUNCTION_AT_ADDRESS( CGaugeTemplate::CGaugeTemplate(class CParamGauge *),CGaugeTemplate__CGaugeTemplate); +#endif +#ifdef CSpellGemTemplate__CSpellGemTemplate_x +FUNCTION_AT_ADDRESS( CSpellGemTemplate::CSpellGemTemplate(class CParamSpellGem *),CSpellGemTemplate__CSpellGemTemplate); +#endif +#ifdef CInvSlotTemplate__CInvSlotTemplate_x +FUNCTION_AT_ADDRESS( CInvSlotTemplate::CInvSlotTemplate(class CParamInvSlot *),CInvSlotTemplate__CInvSlotTemplate); +#endif +#ifdef CEditboxTemplate__CEditboxTemplate_x +FUNCTION_AT_ADDRESS( CEditboxTemplate::CEditboxTemplate(class CParamEditbox *),CEditboxTemplate__CEditboxTemplate); +#endif +#ifdef CSliderTemplate__CSliderTemplate_x +FUNCTION_AT_ADDRESS( CSliderTemplate::CSliderTemplate(class CParamSlider *),CSliderTemplate__CSliderTemplate); +#endif +#ifdef CLabelTemplate__CLabelTemplate_x +FUNCTION_AT_ADDRESS( CLabelTemplate::CLabelTemplate(class CParamLabel *),CLabelTemplate__CLabelTemplate); +#endif +#ifdef CSTMLboxTemplate__CSTMLboxTemplate_x +FUNCTION_AT_ADDRESS( CSTMLboxTemplate::CSTMLboxTemplate(class CParamSTMLbox *),CSTMLboxTemplate__CSTMLboxTemplate); +#endif +#ifdef CComboboxTemplate__CComboboxTemplate_x +FUNCTION_AT_ADDRESS( CComboboxTemplate::CComboboxTemplate(class CParamCombobox *),CComboboxTemplate__CComboboxTemplate); +#endif +#ifdef CPageTemplate__CPageTemplate_x +FUNCTION_AT_ADDRESS( CPageTemplate::CPageTemplate(class CParamPage *),CPageTemplate__CPageTemplate); +#endif +#ifdef CTabBoxTemplate__CTabBoxTemplate_x +FUNCTION_AT_ADDRESS( CTabBoxTemplate::CTabBoxTemplate(class CParamTabBox *),CTabBoxTemplate__CTabBoxTemplate); +#endif +#ifdef CScreenTemplate__CScreenTemplate_x +FUNCTION_AT_ADDRESS( CScreenTemplate::CScreenTemplate(class CParamScreen *),CScreenTemplate__CScreenTemplate); +#endif +#ifdef CStmlWnd__CStmlWnd_x +FUNCTION_AT_ADDRESS( CStmlWnd::CStmlWnd(class CXWnd *,unsigned __int32,class CXRect),CStmlWnd__CStmlWnd); +#endif +#ifdef CStmlWnd__InitializeTextLine_x +FUNCTION_AT_ADDRESS(void CStmlWnd::InitializeTextLine(class SParseVariables *,int),CStmlWnd__InitializeTextLine); +#endif +#ifdef CStmlWnd__AddTextPieceToLine_x +FUNCTION_AT_ADDRESS(void CStmlWnd::AddTextPieceToLine(class SParseVariables *),CStmlWnd__AddTextPieceToLine); +#endif +#ifdef CStmlWnd__MakeStmlColorTag_x +FUNCTION_AT_ADDRESS(class CXStr __cdecl CStmlWnd::MakeStmlColorTag(unsigned long),CStmlWnd__MakeStmlColorTag); +#endif +#ifdef CTextureAnimation__GetName_x +FUNCTION_AT_ADDRESS(class CXStr CTextureAnimation::GetName(void)const ,CTextureAnimation__GetName); +#endif +#ifdef CStmlWnd__MakeWndNotificationTag_x +FUNCTION_AT_ADDRESS(class CXStr __cdecl CStmlWnd::MakeWndNotificationTag(unsigned __int32,class CXStr&,class CXStr&),CStmlWnd__MakeWndNotificationTag); +#endif +#ifdef CStmlWnd__ParseTagColor_x +FUNCTION_AT_ADDRESS(void CStmlWnd::ParseTagColor(class CXStr,unsigned long *)const ,CStmlWnd__ParseTagColor); +#endif +#ifdef CStmlWnd__ParseTagFace_x +FUNCTION_AT_ADDRESS(void CStmlWnd::ParseTagFace(class CXStr,class CTextureFont const * *)const ,CStmlWnd__ParseTagFace); +#endif +#ifdef CStmlWnd__ParseTagAlign_x +//FUNCTION_AT_ADDRESS(void CStmlWnd::ParseTagAlign(class CXStr,enum ESTMLAlign *)const ,CStmlWnd__ParseTagAlign); +#endif +#ifdef SAmpersandEntry__SAmpersandEntry_x +FUNCTION_AT_ADDRESS( SAmpersandEntry::SAmpersandEntry(class CXStr,char),SAmpersandEntry__SAmpersandEntry); +#endif +#ifdef CButtonDrawTemplate__dCButtonDrawTemplate_x +FUNCTION_AT_ADDRESS( CButtonDrawTemplate::~CButtonDrawTemplate(void),CButtonDrawTemplate__dCButtonDrawTemplate); +#endif +#ifdef CGaugeDrawTemplate__dCGaugeDrawTemplate_x +FUNCTION_AT_ADDRESS( CGaugeDrawTemplate::~CGaugeDrawTemplate(void),CGaugeDrawTemplate__dCGaugeDrawTemplate); +#endif +#ifdef CSpellGemDrawTemplate__dCSpellGemDrawTemplate_x +FUNCTION_AT_ADDRESS( CSpellGemDrawTemplate::~CSpellGemDrawTemplate(void),CSpellGemDrawTemplate__dCSpellGemDrawTemplate); +#endif +#ifdef CTAFrameDraw__dCTAFrameDraw_x +FUNCTION_AT_ADDRESS( CTAFrameDraw::~CTAFrameDraw(void),CTAFrameDraw__dCTAFrameDraw); +#endif +#ifdef SAmpersandEntry__dSAmpersandEntry_x +FUNCTION_AT_ADDRESS( SAmpersandEntry::~SAmpersandEntry(void),SAmpersandEntry__dSAmpersandEntry); +#endif +#ifdef STempTableCell__dSTempTableCell_x +FUNCTION_AT_ADDRESS( STempTableCell::~STempTableCell(void),STempTableCell__dSTempTableCell); +#endif +#ifdef CXStr__Blank_x +FUNCTION_AT_ADDRESS(void CXStr::Blank(void),CXStr__Blank); +#endif +#ifdef CStmlWnd__ParseAmpersand_x +FUNCTION_AT_ADDRESS(bool CStmlWnd::ParseAmpersand(class CXStr&,char *)const ,CStmlWnd__ParseAmpersand); +#endif +#ifdef CStmlWnd__ParseLinkTarget_x +//FUNCTION_AT_ADDRESS(void CStmlWnd::ParseLinkTarget(class CXStr,enum ESTMLTargetValue *)const ,CStmlWnd__ParseLinkTarget); +#endif +#ifdef CStmlWnd__FastForwardPastSpaces_x +FUNCTION_AT_ADDRESS(unsigned short CStmlWnd::FastForwardPastSpaces(class CXStr&,int *),CStmlWnd__FastForwardPastSpaces); +#endif +#ifdef CStmlWnd__FastForwardPastSpacesAndQuotes_x +FUNCTION_AT_ADDRESS(unsigned short CStmlWnd::FastForwardPastSpacesAndQuotes(class CXStr&,int *),CStmlWnd__FastForwardPastSpacesAndQuotes); +#endif +#ifdef CStmlWnd__GetNextTagPiece_x +FUNCTION_AT_ADDRESS(unsigned short CStmlWnd::GetNextTagPiece(class CXStr&,class CXStr *,int *,bool (__cdecl*)(unsigned short),bool),CStmlWnd__GetNextTagPiece); +#endif +#ifdef CStmlWnd__IsCharacterNotQuotes_x +FUNCTION_AT_ADDRESS(bool __cdecl CStmlWnd::IsCharacterNotQuotes(unsigned short),CStmlWnd__IsCharacterNotQuotes); +#endif +#ifdef CStmlWnd__FastForwardPastQuotesAndGetNextTagPiece_x +FUNCTION_AT_ADDRESS(unsigned short CStmlWnd::FastForwardPastQuotesAndGetNextTagPiece(class CXStr&,class CXStr *,int *,bool),CStmlWnd__FastForwardPastQuotesAndGetNextTagPiece); +#endif +#ifdef CStmlWnd__FastForwardToEndOfTag_x +FUNCTION_AT_ADDRESS(unsigned short CStmlWnd::FastForwardToEndOfTag(class CXStr&,class CXStr *,int *,char),CStmlWnd__FastForwardToEndOfTag); +#endif +#ifdef CStmlWnd__InitializeTempVariables_x +FUNCTION_AT_ADDRESS(void CStmlWnd::InitializeTempVariables(class SParseVariables *,class CXRect),CStmlWnd__InitializeTempVariables); +#endif +#ifdef CStmlWnd__InitializeWindowVariables_x +FUNCTION_AT_ADDRESS(void CStmlWnd::InitializeWindowVariables(void),CStmlWnd__InitializeWindowVariables); +#endif +#ifdef CStmlWnd__ResetTempVariablesForNewLine_x +FUNCTION_AT_ADDRESS(void CStmlWnd::ResetTempVariablesForNewLine(class SParseVariables *),CStmlWnd__ResetTempVariablesForNewLine); +#endif +#ifdef CStmlWnd__GetNextChar_x +FUNCTION_AT_ADDRESS(unsigned short CStmlWnd::GetNextChar(int *,class CXStr&),CStmlWnd__GetNextChar); +#endif +#ifdef CStmlWnd__GetThisChar_x +FUNCTION_AT_ADDRESS(unsigned short CStmlWnd::GetThisChar(int,class CXStr&),CStmlWnd__GetThisChar); +#endif +#ifdef CStmlWnd__IsCharacterNotEquals_x +FUNCTION_AT_ADDRESS(bool __cdecl CStmlWnd::IsCharacterNotEquals(unsigned short),CStmlWnd__IsCharacterNotEquals); +#endif +#ifdef CStmlWnd__IsCharacterNotASpaceAndNotNULL_x +FUNCTION_AT_ADDRESS(bool __cdecl CStmlWnd::IsCharacterNotASpaceAndNotNULL(unsigned short),CStmlWnd__IsCharacterNotASpaceAndNotNULL); +#endif +#ifdef SParseVariables__dSParseVariables_x +FUNCTION_AT_ADDRESS( SParseVariables::~SParseVariables(void),SParseVariables__dSParseVariables); +#endif +#ifdef SFormattedText__dSFormattedText_x +FUNCTION_AT_ADDRESS( SFormattedText::~SFormattedText(void),SFormattedText__dSFormattedText); +#endif +#ifdef CStmlWnd__ParseSTMLHead_x +FUNCTION_AT_ADDRESS(void CStmlWnd::ParseSTMLHead(class CXStr&),CStmlWnd__ParseSTMLHead); +#endif +#ifdef CStmlWnd__ParseSTMLTable_x +FUNCTION_AT_ADDRESS(void CStmlWnd::ParseSTMLTable(class CXStr&,int *,class CXStr&,class SParseVariables *),CStmlWnd__ParseSTMLTable); +#endif +#ifdef STempTable__dSTempTable_x +FUNCTION_AT_ADDRESS( STempTable::~STempTable(void),STempTable__dSTempTable); +#endif +#ifdef STable__STable_x +FUNCTION_AT_ADDRESS( STable::STable(void),STable__STable); +#endif +#ifdef STable__dSTable_x +FUNCTION_AT_ADDRESS( STable::~STable(void),STable__dSTable); +#endif +#ifdef STableCell__dSTableCell_x +FUNCTION_AT_ADDRESS( STableCell::~STableCell(void),STableCell__dSTableCell); +#endif +#ifdef CStmlWnd__ParseSTMLTableAttributes_x +FUNCTION_AT_ADDRESS(void CStmlWnd::ParseSTMLTableAttributes(class CXStr,class STable *),CStmlWnd__ParseSTMLTableAttributes); +#endif +#ifdef CStmlWnd__GetVisibleText_x +FUNCTION_AT_ADDRESS(class CXStr CStmlWnd::GetVisibleText(class CXStr&,class CXRect)const ,CStmlWnd__GetVisibleText); +#endif +#ifdef CStmlWnd__ForceParseNow_x +FUNCTION_AT_ADDRESS(void CStmlWnd::ForceParseNow(void),CStmlWnd__ForceParseNow); +#endif +#ifdef CStmlWnd__CalculateVSBRange_x +FUNCTION_AT_ADDRESS(void CStmlWnd::CalculateVSBRange(int),CStmlWnd__CalculateVSBRange); +#endif +#ifdef CStmlWnd__CalculateHSBRange_x +FUNCTION_AT_ADDRESS(void CStmlWnd::CalculateHSBRange(int),CStmlWnd__CalculateHSBRange); +#endif +#ifdef CStmlReport__GetReport_x +FUNCTION_AT_ADDRESS(class CXStr CStmlReport::GetReport(void)const ,CStmlReport__GetReport); +#endif +#ifdef CStmlWnd__CompleteParse_x +FUNCTION_AT_ADDRESS(void CStmlWnd::CompleteParse(void),CStmlWnd__CompleteParse); +#endif +#ifdef CStmlWnd__StripFirstSTMLLines_x +FUNCTION_AT_ADDRESS(void CStmlWnd::StripFirstSTMLLines(int),CStmlWnd__StripFirstSTMLLines); +#endif +#ifdef CStmlWnd__ActivateLink_x +//FUNCTION_AT_ADDRESS(void CStmlWnd::ActivateLink(class SLinkInfo),CStmlWnd__ActivateLink); +#endif +#ifdef SLinkInfo__SLinkInfo_x +//FUNCTION_AT_ADDRESS( SLinkInfo::SLinkInfo(class SLinkInfo const &),SLinkInfo__SLinkInfo); +#endif +#ifdef CStmlWnd__CanBreakAtCharacter_x +FUNCTION_AT_ADDRESS(bool __cdecl CStmlWnd::CanBreakAtCharacter(unsigned short),CStmlWnd__CanBreakAtCharacter); +#endif +#ifdef CStmlWnd__ActivateLinkFile_x +//FUNCTION_AT_ADDRESS(void CStmlWnd::ActivateLinkFile(class SLinkInfo),CStmlWnd__ActivateLinkFile); +#endif +#ifdef CStmlWnd__ActivateLinkMessageId_x +//FUNCTION_AT_ADDRESS(void CStmlWnd::ActivateLinkMessageId(class SLinkInfo),CStmlWnd__ActivateLinkMessageId); +#endif +#ifdef CStmlWnd__ActivateLinkReport_x +//FUNCTION_AT_ADDRESS(void CStmlWnd::ActivateLinkReport(class SLinkInfo,bool),CStmlWnd__ActivateLinkReport); +#endif +#ifdef CStmlWnd__ActivateLinkWndNotify_x +//FUNCTION_AT_ADDRESS(void CStmlWnd::ActivateLinkWndNotify(class SLinkInfo),CStmlWnd__ActivateLinkWndNotify); +#endif +#ifdef CStmlWnd__LoadPage_x +//FUNCTION_AT_ADDRESS(void CStmlWnd::LoadPage(class CXStr,enum ESTMLTargetValue,bool),CStmlWnd__LoadPage); +#endif +#ifdef CStmlWnd__AddLinkToHistory_x +//FUNCTION_AT_ADDRESS(void CStmlWnd::AddLinkToHistory(class SLinkInfo,class CXStr),CStmlWnd__AddLinkToHistory); +#endif +#ifdef SLinkInfo__operator_equal_x +//FUNCTION_AT_ADDRESS(class SLinkInfo & SLinkInfo::operator=(class SLinkInfo const &),SLinkInfo__operator_equal); +#endif +#ifdef CStmlWnd__UpdateHistoryString_x +FUNCTION_AT_ADDRESS(void CStmlWnd::UpdateHistoryString(__int32,class CXStr&),CStmlWnd__UpdateHistoryString); +#endif +#ifdef CStmlWnd__SetSTMLText_x +FUNCTION_AT_ADDRESS(void CStmlWnd::SetSTMLText(class CXStr,bool,class SLinkInfo *),CStmlWnd__SetSTMLText); +#endif +#ifdef SLinkInfo__SLinkInfo1_x +//FUNCTION_AT_ADDRESS( SLinkInfo::SLinkInfo(void),SLinkInfo__SLinkInfo1); +#endif +#ifdef CStmlWnd__SetSTMLTextWithoutHistory_x +FUNCTION_AT_ADDRESS(void CStmlWnd::SetSTMLTextWithoutHistory(class CXStr),CStmlWnd__SetSTMLTextWithoutHistory); +#endif +#ifdef CStmlWnd__GoToBackHistoryLink_x +FUNCTION_AT_ADDRESS(void CStmlWnd::GoToBackHistoryLink(void),CStmlWnd__GoToBackHistoryLink); +#endif +#ifdef CStmlWnd__CanGoBackward_x +FUNCTION_AT_ADDRESS(bool CStmlWnd::CanGoBackward(void),CStmlWnd__CanGoBackward); +#endif +#ifdef CStmlWnd__IsLinkActive_x +//FUNCTION_AT_ADDRESS(bool CStmlWnd::IsLinkActive(class SLinkInfo)const,CStmlWnd__IsLinkActive); +#endif +#ifdef CXStr__GetLength_x +FUNCTION_AT_ADDRESS(long CXStr::GetLength(void)const ,CXStr__GetLength); +#endif +#ifdef STextLine__STextLine_x +FUNCTION_AT_ADDRESS( STextLine::STextLine(void),STextLine__STextLine); +#endif +#ifdef STextLine__dSTextLine_x +FUNCTION_AT_ADDRESS( STextLine::~STextLine(void),STextLine__dSTextLine); +#endif +#ifdef STempTableCell__STempTableCell_x +FUNCTION_AT_ADDRESS( STempTableCell::STempTableCell(void),STempTableCell__STempTableCell); +#endif +#ifdef STempTableRow__STempTableRow_x +FUNCTION_AT_ADDRESS( STempTableRow::STempTableRow(void),STempTableRow__STempTableRow); +#endif +#ifdef STempTableRow__dSTempTableRow_x +FUNCTION_AT_ADDRESS( STempTableRow::~STempTableRow(void),STempTableRow__dSTempTableRow); +#endif +#ifdef STextLine__operator_equal_x +FUNCTION_AT_ADDRESS(class STextLine & STextLine::operator=(class STextLine const &),STextLine__operator_equal); +#endif +#ifdef SHistoryElement__SHistoryElement_x +FUNCTION_AT_ADDRESS( SHistoryElement::SHistoryElement(void),SHistoryElement__SHistoryElement); +#endif +#ifdef SHistoryElement__dSHistoryElement_x +FUNCTION_AT_ADDRESS( SHistoryElement::~SHistoryElement(void),SHistoryElement__dSHistoryElement); +#endif +#ifdef SFormattedText__SFormattedText_x +FUNCTION_AT_ADDRESS( SFormattedText::SFormattedText(void),SFormattedText__SFormattedText); +#endif +#ifdef STable__operator_equal_x +FUNCTION_AT_ADDRESS(class STable & STable::operator=(class STable const &),STable__operator_equal); +#endif +#ifdef STableCell__STableCell_x +FUNCTION_AT_ADDRESS( STableCell::STableCell(void),STableCell__STableCell); +#endif +#ifdef CTabWnd__CTabWnd_x +FUNCTION_AT_ADDRESS( CTabWnd::CTabWnd(class CXWnd *,unsigned __int32,class CXRect,class CTabBoxTemplate *),CTabWnd__CTabWnd); +#endif +#ifdef CTabWnd__GetNumTabs_x +FUNCTION_AT_ADDRESS(int CTabWnd::GetNumTabs(void)const ,CTabWnd__GetNumTabs); +#endif +#ifdef CTabWnd__GetCurrentTabIndex_x +FUNCTION_AT_ADDRESS(int CTabWnd::GetCurrentTabIndex(void)const ,CTabWnd__GetCurrentTabIndex); +#endif +#ifdef CTabWnd__GetCurrentPage_x +FUNCTION_AT_ADDRESS(class CPageWnd * CTabWnd::GetCurrentPage(void)const ,CTabWnd__GetCurrentPage); +#endif +#ifdef CTabWnd__GetTabRect_x +FUNCTION_AT_ADDRESS(class CXRect CTabWnd::GetTabRect(int)const ,CTabWnd__GetTabRect); +#endif +#ifdef CTabWnd__GetTabInnerRect_x +FUNCTION_AT_ADDRESS(class CXRect CTabWnd::GetTabInnerRect(int)const ,CTabWnd__GetTabInnerRect); +#endif +#ifdef CTabWnd__GetPageClientRect_x +FUNCTION_AT_ADDRESS(class CXRect CTabWnd::GetPageClientRect(void)const ,CTabWnd__GetPageClientRect); +#endif +#ifdef CTabWnd__GetPageInnerRect_x +FUNCTION_AT_ADDRESS(class CXRect CTabWnd::GetPageInnerRect(void)const ,CTabWnd__GetPageInnerRect); +#endif +#ifdef CTabWnd__SetPage_x +FUNCTION_AT_ADDRESS(void CTabWnd::SetPage(int,bool),CTabWnd__SetPage); +#endif +#ifdef CTabWnd__SetPage1_x +FUNCTION_AT_ADDRESS(void CTabWnd::SetPage(class CPageWnd *,bool),CTabWnd__SetPage1); +#endif +#ifdef CTabWnd__InsertPage_x +FUNCTION_AT_ADDRESS(void CTabWnd::InsertPage(class CPageWnd *,int),CTabWnd__InsertPage); +#endif +#ifdef CTabWnd__SetPageRect_x +FUNCTION_AT_ADDRESS(void CTabWnd::SetPageRect(class CXRect),CTabWnd__SetPageRect); +#endif +#ifdef CXWnd__Tile_x +FUNCTION_AT_ADDRESS(int CXWnd::Tile(bool),CXWnd__Tile); +#endif +#ifdef CTabWnd__UpdatePage_x +FUNCTION_AT_ADDRESS(void CTabWnd::UpdatePage(void),CTabWnd__UpdatePage); +#endif +#ifdef CTabWnd__IndexInBounds_x +FUNCTION_AT_ADDRESS(bool CTabWnd::IndexInBounds(int)const ,CTabWnd__IndexInBounds); +#endif +#ifdef CTabWnd__GetPageFromTabIndex_x +FUNCTION_AT_ADDRESS(class CPageWnd * CTabWnd::GetPageFromTabIndex(int)const ,CTabWnd__GetPageFromTabIndex); +#endif +#ifdef CTabWnd__GetPageFromTabPoint_x +FUNCTION_AT_ADDRESS(class CPageWnd * CTabWnd::GetPageFromTabPoint(class CXPoint)const ,CTabWnd__GetPageFromTabPoint); +#endif +#ifdef CTabWnd__DrawTab_x +FUNCTION_AT_ADDRESS(int CTabWnd::DrawTab(int)const ,CTabWnd__DrawTab); +#endif +#ifdef CPageWnd__GetTabText_x +FUNCTION_AT_ADDRESS(class CXStr CPageWnd::GetTabText(void)const ,CPageWnd__GetTabText); +#endif +#ifdef CTabWnd__DrawCurrentPage_x +FUNCTION_AT_ADDRESS(int CTabWnd::DrawCurrentPage(void)const ,CTabWnd__DrawCurrentPage); +#endif +#ifdef CXMLSOMDocumentBase__Init_x +FUNCTION_AT_ADDRESS(void CXMLSOMDocumentBase::Init(void),CXMLSOMDocumentBase__Init); +#endif +#ifdef CXMLSOMNodePtr__Assure_x +FUNCTION_AT_ADDRESS(void CXMLSOMNodePtr::Assure(void)const ,CXMLSOMNodePtr__Assure); +#endif +#ifdef CXMLSOMDocumentBase__CursorInit_x +FUNCTION_AT_ADDRESS(void CXMLSOMDocumentBase::CursorInit(void),CXMLSOMDocumentBase__CursorInit); +#endif +#ifdef CXMLSOMNode__CXMLSOMNode_x +FUNCTION_AT_ADDRESS( CXMLSOMNode::CXMLSOMNode(void),CXMLSOMNode__CXMLSOMNode); +#endif +#ifdef CXMLSOMDocumentBase__Cursor_x +FUNCTION_AT_ADDRESS(class CXMLSOMCursor & CXMLSOMDocumentBase::Cursor(void),CXMLSOMDocumentBase__Cursor); +#endif +#ifdef CXMLSOMDocumentBase__CursorParent_x +FUNCTION_AT_ADDRESS(class CXMLSOMCursor & CXMLSOMDocumentBase::CursorParent(void),CXMLSOMDocumentBase__CursorParent); +#endif +#ifdef CXMLSOMDocumentBase__CursorNewChild_x +FUNCTION_AT_ADDRESS(void CXMLSOMDocumentBase::CursorNewChild(void),CXMLSOMDocumentBase__CursorNewChild); +#endif +#ifdef CXMLSOMDocumentBase__CursorNewSibling_x +FUNCTION_AT_ADDRESS(void CXMLSOMDocumentBase::CursorNewSibling(void),CXMLSOMDocumentBase__CursorNewSibling); +#endif +#ifdef CXMLSOMNodePtr__operator_equal_x +FUNCTION_AT_ADDRESS(class CXMLSOMNodePtr & CXMLSOMNodePtr::operator=(class CXMLSOMNodePtr const &),CXMLSOMNodePtr__operator_equal); +#endif +#ifdef CXMLSOMDocumentBase__CursorSetPtr_x +//FUNCTION_AT_ADDRESS(void CXMLSOMDocumentBase::CursorSetPtr(class CXMLSOMNodePtr),CXMLSOMDocumentBase__CursorSetPtr); +#endif +#ifdef CXMLSOMNodePtr__operator_minust__x +FUNCTION_AT_ADDRESS(class CXMLSOMNode * CXMLSOMNodePtr::operator->(void)const ,CXMLSOMNodePtr__operator_minust_); +#endif +#ifdef CXMLSOMDocumentBase__CursorPush_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::CursorPush(void),CXMLSOMDocumentBase__CursorPush); +#endif +#ifdef CXMLSOMDocumentBase__CursorPop_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::CursorPop(void),CXMLSOMDocumentBase__CursorPop); +#endif +#ifdef CXMLSOMDocumentBase__CursorNextSibling_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::CursorNextSibling(void),CXMLSOMDocumentBase__CursorNextSibling); +#endif +#ifdef CXMLSOMDocumentBase__CursorNextInOrder_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::CursorNextInOrder(void),CXMLSOMDocumentBase__CursorNextInOrder); +#endif +#ifdef CXMLSOMDocumentBase__CursorFind_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::CursorFind(class CXStr),CXMLSOMDocumentBase__CursorFind); +#endif +#ifdef CXMLSOMDocumentBase__GetAttrValueStr_x +FUNCTION_AT_ADDRESS(class CXStr CXMLSOMDocumentBase::GetAttrValueStr(class CXStr),CXMLSOMDocumentBase__GetAttrValueStr); +#endif +#ifdef CXMLSOMDocumentBase__GetAttrValueStr1_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::GetAttrValueStr(class CXStr,class CXStr &),CXMLSOMDocumentBase__GetAttrValueStr1); +#endif +#ifdef CXMLSOMDocumentBase__GetAttrValueInt_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::GetAttrValueInt(class CXStr,__int32 &),CXMLSOMDocumentBase__GetAttrValueInt); +#endif +#ifdef CXMLSOMCursorSave__dCXMLSOMCursorSave_x +FUNCTION_AT_ADDRESS( CXMLSOMCursorSave::~CXMLSOMCursorSave(void),CXMLSOMCursorSave__dCXMLSOMCursorSave); +#endif +#ifdef CXMLSOMDocumentBase__CursorFieldFind_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::CursorFieldFind(class CXStr),CXMLSOMDocumentBase__CursorFieldFind); +#endif +#ifdef CXMLSOMDocumentBase__GetValue_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::GetValue(class CXStr,class CXStr &),CXMLSOMDocumentBase__GetValue); +#endif +#ifdef CXMLSOMDocumentBase__GetValue1_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::GetValue(class CXStr,__int32 &),CXMLSOMDocumentBase__GetValue1); +#endif +#ifdef CXMLSOMDocumentBase__GetValue2_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::GetValue(class CXStr,bool &),CXMLSOMDocumentBase__GetValue2); +#endif +#ifdef CXMLSOMDocumentBase__FieldParseClassItem_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::FieldParseClassItem(class CXStr,class CXStr &,class CXStr &),CXMLSOMDocumentBase__FieldParseClassItem); +#endif +#ifdef CXMLSOMDocumentBase__FieldParseItemOfClass_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::FieldParseItemOfClass(class CXStr,class CXStr,__int32 &,__int32 &),CXMLSOMDocumentBase__FieldParseItemOfClass); +#endif +#ifdef CXMLSOMDocumentBase__SetValue_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::SetValue(class CXStr,class CXStr),CXMLSOMDocumentBase__SetValue); +#endif +#ifdef CXMLSOMDocumentBase__SetValue1_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::SetValue(class CXStr,__int32),CXMLSOMDocumentBase__SetValue1); +#endif +#ifdef CXMLSOMDocumentBase__SetValue2_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::SetValue(class CXStr,bool),CXMLSOMDocumentBase__SetValue2); +#endif +#ifdef CXMLSOMDocumentBase__XMLReadNoValidate_x +FUNCTION_AT_ADDRESS(int CXMLSOMDocumentBase::XMLReadNoValidate(class CXStr,class CXStr,class CXStr),CXMLSOMDocumentBase__XMLReadNoValidate); +#endif +#ifdef CXMLSOMDocumentBase__XMLRead_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::XMLRead(class CXStr*,class CXStr*,class CXStr*),CXMLSOMDocumentBase__XMLRead); +#endif +#ifdef CXMLSOMDocumentBase__XMLProcessComposite_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::XMLProcessComposite(class CXStr,class CXStr),CXMLSOMDocumentBase__XMLProcessComposite); +#endif +#ifdef CXMLSOMDocumentBase__SetErrorMsg_x +FUNCTION_AT_ADDRESS(void CXMLSOMDocumentBase::SetErrorMsg(class CXStr),CXMLSOMDocumentBase__SetErrorMsg); +#endif +#ifdef CXMLSOMDocumentBase__GetErrorMsg_x +FUNCTION_AT_ADDRESS(class CXStr CXMLSOMDocumentBase::GetErrorMsg(void)const ,CXMLSOMDocumentBase__GetErrorMsg); +#endif +#ifdef CXMLSOMSchema__CXMLSOMSchema_x +FUNCTION_AT_ADDRESS( CXMLSOMSchema::CXMLSOMSchema(void),CXMLSOMSchema__CXMLSOMSchema); +#endif +#ifdef CXMLSOMSchema__dCXMLSOMSchema_x +FUNCTION_AT_ADDRESS( CXMLSOMSchema::~CXMLSOMSchema(void),CXMLSOMSchema__dCXMLSOMSchema); +#endif +#ifdef CXMLSOMCursorTraverseChildren__dCXMLSOMCursorTraverseChildren_x +FUNCTION_AT_ADDRESS( CXMLSOMCursorTraverseChildren::~CXMLSOMCursorTraverseChildren(void),CXMLSOMCursorTraverseChildren__dCXMLSOMCursorTraverseChildren); +#endif +#ifdef CXMLSOMDocumentBase__XMLMerge_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::XMLMerge(class CXMLSOMDocumentBase &),CXMLSOMDocumentBase__XMLMerge); +#endif +#ifdef CXMLSOMCursorTraverseChildren__Cursor_x +FUNCTION_AT_ADDRESS(class CXMLSOMCursor & CXMLSOMCursorTraverseChildren::Cursor(void),CXMLSOMCursorTraverseChildren__Cursor); +#endif +#ifdef CXMLSOMDocumentBase__SetErrorMsgAtLine_x +FUNCTION_AT_ADDRESS(void CXMLSOMDocumentBase::SetErrorMsgAtLine(class CXStr,int,class CXStr),CXMLSOMDocumentBase__SetErrorMsgAtLine); +#endif +#ifdef CXMLSOMDocumentBase__SetErrorMsgAtCursor_x +FUNCTION_AT_ADDRESS(void CXMLSOMDocumentBase::SetErrorMsgAtCursor(class CXStr),CXMLSOMDocumentBase__SetErrorMsgAtCursor); +#endif +#ifdef CXMLSOMDocumentBase__ValidateSchemaSimpleTypeNode_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::ValidateSchemaSimpleTypeNode(class CXMLSOMSimpleType &),CXMLSOMDocumentBase__ValidateSchemaSimpleTypeNode); +#endif +#ifdef CXMLSOMDocumentBase__ValidateSchemaElementType_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::ValidateSchemaElementType(void),CXMLSOMDocumentBase__ValidateSchemaElementType); +#endif +#ifdef CXMLSOMElementType__dCXMLSOMElementType_x +FUNCTION_AT_ADDRESS( CXMLSOMElementType::~CXMLSOMElementType(void),CXMLSOMElementType__dCXMLSOMElementType); +#endif +#ifdef CXMLSOMElement__dCXMLSOMElement_x +FUNCTION_AT_ADDRESS( CXMLSOMElement::~CXMLSOMElement(void),CXMLSOMElement__dCXMLSOMElement); +#endif +#ifdef CXMLSOMAttributeType__dCXMLSOMAttributeType_x +FUNCTION_AT_ADDRESS( CXMLSOMAttributeType::~CXMLSOMAttributeType(void),CXMLSOMAttributeType__dCXMLSOMAttributeType); +#endif +#ifdef CXMLSOMDocumentBase__ValidateSchemaSimpleType_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::ValidateSchemaSimpleType(void),CXMLSOMDocumentBase__ValidateSchemaSimpleType); +#endif +#ifdef CXMLSOMSimpleType__dCXMLSOMSimpleType_x +FUNCTION_AT_ADDRESS( CXMLSOMSimpleType::~CXMLSOMSimpleType(void),CXMLSOMSimpleType__dCXMLSOMSimpleType); +#endif +#ifdef CXMLSOMDocumentBase__ValidateSchemaDefinition_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::ValidateSchemaDefinition(void),CXMLSOMDocumentBase__ValidateSchemaDefinition); +#endif +#ifdef CXMLSOMDocumentBase__ValidateSchemaCategories_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::ValidateSchemaCategories(void),CXMLSOMDocumentBase__ValidateSchemaCategories); +#endif +#ifdef CXMLSOMDocumentBase__ValidateSchemaTypeRefs_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::ValidateSchemaTypeRefs(void),CXMLSOMDocumentBase__ValidateSchemaTypeRefs); +#endif +#ifdef CXMLSOMDocumentBase__ValidateSchema_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::ValidateSchema(void),CXMLSOMDocumentBase__ValidateSchema); +#endif +#ifdef CXMLSOMDocumentBase__ValidateDataElements_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::ValidateDataElements(class CXMLSOMElementType &),CXMLSOMDocumentBase__ValidateDataElements); +#endif +#ifdef CXMLSOMDocumentBase__ValidateData_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocumentBase::ValidateData(void),CXMLSOMDocumentBase__ValidateData); +#endif +#ifdef CXMLSOMElementType__GetItemIdx_x +FUNCTION_AT_ADDRESS(int CXMLSOMElementType::GetItemIdx(class CXStr),CXMLSOMElementType__GetItemIdx); +#endif +#ifdef CXMLSOMSchema__GetElementTypeIdx_x +FUNCTION_AT_ADDRESS(int CXMLSOMSchema::GetElementTypeIdx(class CXStr),CXMLSOMSchema__GetElementTypeIdx); +#endif +#ifdef CXMLSOMSchema__IsDerivedFrom_x +FUNCTION_AT_ADDRESS(bool CXMLSOMSchema::IsDerivedFrom(class CXStr,class CXStr),CXMLSOMSchema__IsDerivedFrom); +#endif +#ifdef CXMLSOMSchema__FindElementType_x +FUNCTION_AT_ADDRESS(bool CXMLSOMSchema::FindElementType(class CXStr),CXMLSOMSchema__FindElementType); +#endif +#ifdef CXMLSOMSchema__FindSimpleType_x +FUNCTION_AT_ADDRESS(bool CXMLSOMSchema::FindSimpleType(class CXStr),CXMLSOMSchema__FindSimpleType); +#endif +#ifdef CXMLSOMSchema__FindItem_x +FUNCTION_AT_ADDRESS(bool CXMLSOMSchema::FindItem(class CXStr,class CXStr),CXMLSOMSchema__FindItem); +#endif +#ifdef CXMLSOMSchema__AddItem_x +FUNCTION_AT_ADDRESS(bool CXMLSOMSchema::AddItem(class CXStr,class CXStr),CXMLSOMSchema__AddItem); +#endif +#ifdef CXMLSOMNode__FreeAllAllocs_x +FUNCTION_AT_ADDRESS(void __cdecl CXMLSOMNode::FreeAllAllocs(void),CXMLSOMNode__FreeAllAllocs); +#endif +#ifdef CXMLSOMNode__operator_new_x +FUNCTION_AT_ADDRESS(void * __cdecl CXMLSOMNode::operator new(unsigned int),CXMLSOMNode__operator_new); +#endif +#ifdef CMutexLock__dCMutexLock_x +FUNCTION_AT_ADDRESS( CMutexLock::~CMutexLock(void),CMutexLock__dCMutexLock); +#endif +#ifdef CXMLSOMNode__operator_delete_x +FUNCTION_AT_ADDRESS(void __cdecl CXMLSOMNode::operator delete(void *),CXMLSOMNode__operator_delete); +#endif +#ifdef CKeyCXStrValueInt32__CKeyCXStrValueInt32_x +FUNCTION_AT_ADDRESS( CKeyCXStrValueInt32::CKeyCXStrValueInt32(void),CKeyCXStrValueInt32__CKeyCXStrValueInt32); +#endif +#ifdef CXMLSOMCursor__CXMLSOMCursor_x +FUNCTION_AT_ADDRESS( CXMLSOMCursor::CXMLSOMCursor(void),CXMLSOMCursor__CXMLSOMCursor); +#endif +#ifdef CXMLSOMNodePtr__CXMLSOMNodePtr_x +FUNCTION_AT_ADDRESS( CXMLSOMNodePtr::CXMLSOMNodePtr(void),CXMLSOMNodePtr__CXMLSOMNodePtr); +#endif +#ifdef CXMLSOMAttribute__operator_equal_x +FUNCTION_AT_ADDRESS(class CXMLSOMAttribute & CXMLSOMAttribute::operator=(class CXMLSOMAttribute const &),CXMLSOMAttribute__operator_equal); +#endif +#ifdef CXMLSOMCursor__operator_equal_x +FUNCTION_AT_ADDRESS(class CXMLSOMCursor & CXMLSOMCursor::operator=(class CXMLSOMCursor const &),CXMLSOMCursor__operator_equal); +#endif +#ifdef CXMLSOMAttribute__CXMLSOMAttribute_x +FUNCTION_AT_ADDRESS( CXMLSOMAttribute::CXMLSOMAttribute(void),CXMLSOMAttribute__CXMLSOMAttribute); +#endif +#ifdef CXMLSOMSimpleType__CXMLSOMSimpleType_x +FUNCTION_AT_ADDRESS( CXMLSOMSimpleType::CXMLSOMSimpleType(void),CXMLSOMSimpleType__CXMLSOMSimpleType); +#endif +#ifdef CXMLSOMElementType__CXMLSOMElementType_x +FUNCTION_AT_ADDRESS( CXMLSOMElementType::CXMLSOMElementType(void),CXMLSOMElementType__CXMLSOMElementType); +#endif +#ifdef CXMLSOMAttributeType__operator_equal_x +FUNCTION_AT_ADDRESS(class CXMLSOMAttributeType & CXMLSOMAttributeType::operator=(class CXMLSOMAttributeType const &),CXMLSOMAttributeType__operator_equal); +#endif +#ifdef CXMLSOMElement__operator_equal_x +FUNCTION_AT_ADDRESS(class CXMLSOMElement & CXMLSOMElement::operator=(class CXMLSOMElement const &),CXMLSOMElement__operator_equal); +#endif +#ifdef CXMLSOMAttributeType__CXMLSOMAttributeType_x +FUNCTION_AT_ADDRESS( CXMLSOMAttributeType::CXMLSOMAttributeType(void),CXMLSOMAttributeType__CXMLSOMAttributeType); +#endif +#ifdef CXMLSOMElement__CXMLSOMElement_x +FUNCTION_AT_ADDRESS( CXMLSOMElement::CXMLSOMElement(void),CXMLSOMElement__CXMLSOMElement); +#endif +#ifdef KeyCombo__KeyCombo_x +FUNCTION_AT_ADDRESS( KeyCombo::KeyCombo(void),KeyCombo__KeyCombo); +#endif +#ifdef KeyCombo__KeyCombo1_x +FUNCTION_AT_ADDRESS( KeyCombo::KeyCombo(unsigned char,bool,bool,bool),KeyCombo__KeyCombo1); +#endif +#ifdef KeyCombo__KeyCombo2_x +FUNCTION_AT_ADDRESS( KeyCombo::KeyCombo(int),KeyCombo__KeyCombo2); +#endif +#ifdef KeyCombo__KeyCombo3_x +FUNCTION_AT_ADDRESS( KeyCombo::KeyCombo(unsigned int,unsigned int,bool,bool,bool),KeyCombo__KeyCombo3); +#endif +#ifdef KeyCombo__GetKey_x +FUNCTION_AT_ADDRESS(unsigned int KeyCombo::GetKey(void)const ,KeyCombo__GetKey); +#endif +#ifdef KeyCombo__UsesCtrl_x +FUNCTION_AT_ADDRESS(bool KeyCombo::UsesCtrl(void)const ,KeyCombo__UsesCtrl); +#endif +#ifdef KeyCombo__UsesShift_x +FUNCTION_AT_ADDRESS(bool KeyCombo::UsesShift(void)const ,KeyCombo__UsesShift); +#endif +#ifdef KeyCombo__UsesAlt_x +FUNCTION_AT_ADDRESS(bool KeyCombo::UsesAlt(void)const ,KeyCombo__UsesAlt); +#endif +#ifdef KeyCombo__GetTextDescription_x +FUNCTION_AT_ADDRESS(class CXStr KeyCombo::GetTextDescription(void)const ,KeyCombo__GetTextDescription); +#endif +#ifdef KeyCombo__GetPrintableLetter_x +FUNCTION_AT_ADDRESS(bool KeyCombo::GetPrintableLetter(unsigned short *)const ,KeyCombo__GetPrintableLetter); +#endif +#ifdef KeyCombo__operator_equal_equal_x +FUNCTION_AT_ADDRESS(int KeyCombo::operator==(class KeyCombo const &)const ,KeyCombo__operator_equal_equal); +#endif +#ifdef KeyCombo__operator_equal_x +FUNCTION_AT_ADDRESS(class KeyCombo const & KeyCombo::operator=(int),KeyCombo__operator_equal); +#endif +#ifdef KeyCombo__operator_int_x +//FUNCTION_AT_ADDRESS( KeyCombo::operator int(void)const ,KeyCombo__operator_int); +#endif +#ifdef KeyCombo__GetVirtualKeyFromScanCode_x +FUNCTION_AT_ADDRESS(bool KeyCombo::GetVirtualKeyFromScanCode(unsigned char,int *)const ,KeyCombo__GetVirtualKeyFromScanCode); +#endif +#ifdef KeyCombo__GetPrintableLetterFromScanCode_x +FUNCTION_AT_ADDRESS(bool KeyCombo::GetPrintableLetterFromScanCode(unsigned char,bool,bool,unsigned short *)const ,KeyCombo__GetPrintableLetterFromScanCode); +#endif +#ifdef KeyCombo__GetScanCodeFromVirtualKey_x +FUNCTION_AT_ADDRESS(bool KeyCombo::GetScanCodeFromVirtualKey(unsigned int,unsigned int,unsigned char *)const ,KeyCombo__GetScanCodeFromVirtualKey); +#endif +#ifdef KeyCombo__GetPrintableLetterFromVirtualKey_x +FUNCTION_AT_ADDRESS(bool KeyCombo::GetPrintableLetterFromVirtualKey(unsigned int,unsigned int,bool,bool,unsigned short *)const ,KeyCombo__GetPrintableLetterFromVirtualKey); +#endif +#ifdef CButtonWnd__CButtonWnd_x +FUNCTION_AT_ADDRESS( CButtonWnd::CButtonWnd(class CXWnd *,unsigned __int32,class CXRect,class CXPoint,class CXSize,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *),CButtonWnd__CButtonWnd); +#endif +#ifdef CXWnd__IsEnabled_x +FUNCTION_AT_ADDRESS(bool CXWnd::IsEnabled(void)const ,CXWnd__IsEnabled); +#endif +#ifdef CButtonWnd__SetCheck_x +FUNCTION_AT_ADDRESS(void CButtonWnd::SetCheck(bool),CButtonWnd__SetCheck); +#endif +#ifdef CComboWnd__CComboWnd_x +//FUNCTION_AT_ADDRESS( CComboWnd::CComboWnd(class CXWnd *,unsigned __int32,class CXRect,int,class CButtonDrawTemplate,class CListWnd *),CComboWnd__CComboWnd); +#endif +#ifdef CXWnd__GetWidth_x +FUNCTION_AT_ADDRESS(int CXWnd::GetWidth(void)const ,CXWnd__GetWidth); +#endif +#ifdef CComboWnd__GetListRect_x +FUNCTION_AT_ADDRESS(class CXRect CComboWnd::GetListRect(void)const ,CComboWnd__GetListRect); +#endif +#ifdef CComboWnd__SetColors_x +FUNCTION_AT_ADDRESS(void CComboWnd::SetColors(unsigned long,unsigned long,unsigned long),CComboWnd__SetColors); +#endif +#ifdef CComboWnd__InsertChoice_x +FUNCTION_AT_ADDRESS(void CComboWnd::InsertChoice(class CXStr *, unsigned long),CComboWnd__InsertChoice); +#endif +#ifdef CComboWnd__SetChoice_x +FUNCTION_AT_ADDRESS(void CComboWnd::SetChoice(int),CComboWnd__SetChoice); +#endif +#ifdef CComboWnd__GetItemCount_x +FUNCTION_AT_ADDRESS(int CComboWnd::GetItemCount(void),CComboWnd__GetItemCount); +#endif +#ifdef CComboWnd__GetCurChoice_x +FUNCTION_AT_ADDRESS(int CComboWnd::GetCurChoice(void)const ,CComboWnd__GetCurChoice); +#endif +#ifdef CComboWnd__GetCurChoiceText_x +FUNCTION_AT_ADDRESS(class CXStr CComboWnd::GetCurChoiceText(void)const ,CComboWnd__GetCurChoiceText); +#endif +#ifdef CComboWnd__DeleteAll_x +FUNCTION_AT_ADDRESS(void CComboWnd::DeleteAll(void),CComboWnd__DeleteAll); +#endif +#ifdef CComboWnd__GetButtonRect_x +FUNCTION_AT_ADDRESS(class CXRect CComboWnd::GetButtonRect(void)const ,CComboWnd__GetButtonRect); +#endif +#ifdef CComboWnd__GetTextRect_x +FUNCTION_AT_ADDRESS(class CXRect CComboWnd::GetTextRect(void)const ,CComboWnd__GetTextRect); +#endif +#ifdef CXWndManager__CXWndManager_x +FUNCTION_AT_ADDRESS( CXWndManager::CXWndManager(class CSidlManager *),CXWndManager__CXWndManager); +#endif +#ifdef CXWndManager__DestroyAllWindows_x +FUNCTION_AT_ADDRESS(void CXWndManager::DestroyAllWindows(void),CXWndManager__DestroyAllWindows); +#endif +#ifdef CXWndManager__DrawWindows_x +FUNCTION_AT_ADDRESS(int CXWndManager::DrawWindows(void)const ,CXWndManager__DrawWindows); +#endif +#ifdef CXWndManager__DrawCursor_x +FUNCTION_AT_ADDRESS(int CXWndManager::DrawCursor(void)const ,CXWndManager__DrawCursor); +#endif +#ifdef CXWndManager__AddWnd_x +FUNCTION_AT_ADDRESS(int CXWndManager::AddWnd(class CXWnd *),CXWndManager__AddWnd); +#endif +#ifdef CXWndManager__RemoveWnd_x +FUNCTION_AT_ADDRESS(int CXWndManager::RemoveWnd(class CXWnd *),CXWndManager__RemoveWnd); +#endif +#ifdef CXWndManager__CheckInvalidateLastFoundWnd_x +FUNCTION_AT_ADDRESS(void CXWndManager::CheckInvalidateLastFoundWnd(void),CXWndManager__CheckInvalidateLastFoundWnd); +#endif +#ifdef CXWndManager__GetKeyboardFlags_x +FUNCTION_AT_ADDRESS(unsigned __int32 CXWndManager::GetKeyboardFlags(void)const ,CXWndManager__GetKeyboardFlags); +#endif +#ifdef CXWndManager__FlushKeyboardFlags_x +FUNCTION_AT_ADDRESS(void CXWndManager::FlushKeyboardFlags(void),CXWndManager__FlushKeyboardFlags); +#endif +#ifdef CXWndManager__UpdateChildAndSiblingInfo_x +FUNCTION_AT_ADDRESS(void CXWndManager::UpdateChildAndSiblingInfo(void),CXWndManager__UpdateChildAndSiblingInfo); +#endif +#ifdef CXWndManager__HandleKeyboardMsg_x +FUNCTION_AT_ADDRESS(int CXWndManager::HandleKeyboardMsg(unsigned __int32,bool),CXWndManager__HandleKeyboardMsg); +#endif +#ifdef CXWndManager__OkayToSendMouseMessage_x +FUNCTION_AT_ADDRESS(bool CXWndManager::OkayToSendMouseMessage(class CXWnd *)const,CXWndManager__OkayToSendMouseMessage); +#endif +#ifdef CXWndManager__HandleMouseMove_x +FUNCTION_AT_ADDRESS(int CXWndManager::HandleMouseMove(class CXPoint),CXWndManager__HandleMouseMove); +#endif +#ifdef CXWndManager__HandleWheelMove_x +FUNCTION_AT_ADDRESS(int CXWndManager::HandleWheelMove(int),CXWndManager__HandleWheelMove); +#endif +#ifdef CXWndManager__HandleLButtonDown_x +FUNCTION_AT_ADDRESS(int CXWndManager::HandleLButtonDown(class CXPoint),CXWndManager__HandleLButtonDown); +#endif +#ifdef CXWndManager__IsWindowPieceDown_x +FUNCTION_AT_ADDRESS(bool CXWndManager::IsWindowPieceDown(class CXWnd const *,int)const ,CXWndManager__IsWindowPieceDown); +#endif +#ifdef CXWndManager__OnWindowCloseBox_x +FUNCTION_AT_ADDRESS(int CXWndManager::OnWindowCloseBox(class CXWnd *),CXWndManager__OnWindowCloseBox); +#endif +#ifdef CXWndManager__OnWindowMinimizeBox_x +FUNCTION_AT_ADDRESS(int CXWndManager::OnWindowMinimizeBox(class CXWnd *),CXWndManager__OnWindowMinimizeBox); +#endif +#ifdef CXWndManager__OnWindowTileBox_x +FUNCTION_AT_ADDRESS(int CXWndManager::OnWindowTileBox(class CXWnd *),CXWndManager__OnWindowTileBox); +#endif +#ifdef CXWndManager__HandleLButtonHeld_x +FUNCTION_AT_ADDRESS(int CXWndManager::HandleLButtonHeld(class CXPoint),CXWndManager__HandleLButtonHeld); +#endif +#ifdef CXWndManager__HandleLButtonUpAfterHeld_x +FUNCTION_AT_ADDRESS(int CXWndManager::HandleLButtonUpAfterHeld(class CXPoint),CXWndManager__HandleLButtonUpAfterHeld); +#endif +#ifdef CXWndManager__HandleRButtonHeld_x +FUNCTION_AT_ADDRESS(int CXWndManager::HandleRButtonHeld(class CXPoint),CXWndManager__HandleRButtonHeld); +#endif +#ifdef CXWndManager__HandleRButtonUpAfterHeld_x +FUNCTION_AT_ADDRESS(int CXWndManager::HandleRButtonUpAfterHeld(class CXPoint),CXWndManager__HandleRButtonUpAfterHeld); +#endif +#ifdef CXWndManager__HandleLButtonUp_x +FUNCTION_AT_ADDRESS(int CXWndManager::HandleLButtonUp(class CXPoint),CXWndManager__HandleLButtonUp); +#endif +#ifdef CXWndManager__HandleRButtonDown_x +FUNCTION_AT_ADDRESS(int CXWndManager::HandleRButtonDown(class CXPoint),CXWndManager__HandleRButtonDown); +#endif +#ifdef CXWndManager__HandleRButtonUp_x +FUNCTION_AT_ADDRESS(int CXWndManager::HandleRButtonUp(class CXPoint),CXWndManager__HandleRButtonUp); +#endif +#ifdef CXWndManager__FindWnd_x +FUNCTION_AT_ADDRESS(class CXWnd * CXWndManager::FindWnd(class CXPoint,int *)const,CXWndManager__FindWnd); +#endif +#ifdef CXWndManager__GetCursorToDisplay_x +FUNCTION_AT_ADDRESS(class CTextureAnimation const * CXWndManager::GetCursorToDisplay(void)const ,CXWndManager__GetCursorToDisplay); +#endif +#ifdef CXWndManager__SetFocusWnd_x +FUNCTION_AT_ADDRESS(class CXWnd * CXWndManager::SetFocusWnd(class CXWnd *),CXWndManager__SetFocusWnd); +#endif +#ifdef CXWndManager__GetFocusWnd_x +FUNCTION_AT_ADDRESS(class CXWnd * CXWndManager::GetFocusWnd(void)const ,CXWndManager__GetFocusWnd); +#endif +#ifdef CXWndManager__ProcessFrame_x +FUNCTION_AT_ADDRESS(int CXWndManager::ProcessFrame(void),CXWndManager__ProcessFrame); +#endif +#ifdef CXWndManager__OnWindowShown_x +FUNCTION_AT_ADDRESS(void CXWndManager::OnWindowShown(class CXWnd *,bool),CXWndManager__OnWindowShown); +#endif +#ifdef CXWndManager__BringWndToTop_x +FUNCTION_AT_ADDRESS(void CXWndManager::BringWndToTop(class CXWnd *,bool),CXWndManager__BringWndToTop); +#endif +#ifdef CXWndManager__NotifyAllWindows_x +FUNCTION_AT_ADDRESS(int CXWndManager::NotifyAllWindows(class CXWnd *,unsigned __int32,void *),CXWndManager__NotifyAllWindows); +#endif +#ifdef CXWndManager__CleanupWindows_x +FUNCTION_AT_ADDRESS(void CXWndManager::CleanupWindows(void),CXWndManager__CleanupWindows); +#endif +#ifdef CXWndManager__GetFirstChildWnd_x +FUNCTION_AT_ADDRESS(class CXWnd * CXWndManager::GetFirstChildWnd(class CXWnd const *)const ,CXWndManager__GetFirstChildWnd); +#endif +#ifdef CXWndManager__GetNextSib_x +FUNCTION_AT_ADDRESS(class CXWnd * CXWndManager::GetNextSib(class CXWnd const *)const ,CXWndManager__GetNextSib); +#endif +#ifdef CXWndManager__ActivateWnd_x +FUNCTION_AT_ADDRESS(int CXWndManager::ActivateWnd(class CXWnd *),CXWndManager__ActivateWnd); +#endif +#ifdef CXWndManager__IsWindowActive_x +FUNCTION_AT_ADDRESS(bool CXWndManager::IsWindowActive(class CXWnd const *)const ,CXWndManager__IsWindowActive); +#endif +#ifdef CXWndManager__IsWindowMovingOrSizing_x +FUNCTION_AT_ADDRESS(bool CXWndManager::IsWindowMovingOrSizing(class CXWnd *)const ,CXWndManager__IsWindowMovingOrSizing); +#endif +#ifdef CXWndManager__AddFont_x +FUNCTION_AT_ADDRESS(int CXWndManager::AddFont(class CTextureFont *),CXWndManager__AddFont); +#endif +#ifdef CXWndManager__GetFont1_x +FUNCTION_AT_ADDRESS(class CTextureFont * CXWndManager::GetFont(class CXStr),CXWndManager__GetFont1); +#endif +#ifdef CXWndManager__SetSystemFont_x +FUNCTION_AT_ADDRESS(void CXWndManager::SetSystemFont(class CTextureFont *),CXWndManager__SetSystemFont); +#endif +#ifdef CXWndManager__SetGlobalFadeDuration_x +FUNCTION_AT_ADDRESS(void CXWndManager::SetGlobalFadeDuration(unsigned __int32),CXWndManager__SetGlobalFadeDuration); +#endif +#ifdef CXWndManager__GetGlobalFadeDuration_x +FUNCTION_AT_ADDRESS(unsigned __int32 CXWndManager::GetGlobalFadeDuration(void)const ,CXWndManager__GetGlobalFadeDuration); +#endif +#ifdef CXWndManager__SetGlobalFadeDelay_x +FUNCTION_AT_ADDRESS(void CXWndManager::SetGlobalFadeDelay(unsigned long),CXWndManager__SetGlobalFadeDelay); +#endif +#ifdef CXWndManager__GetGlobalFadeDelay_x +FUNCTION_AT_ADDRESS(unsigned long CXWndManager::GetGlobalFadeDelay(void)const ,CXWndManager__GetGlobalFadeDelay); +#endif +#ifdef CXWndManager__SetGlobalAlpha_x +FUNCTION_AT_ADDRESS(void CXWndManager::SetGlobalAlpha(unsigned char),CXWndManager__SetGlobalAlpha); +#endif +#ifdef CXWndManager__GetGlobalAlpha_x +FUNCTION_AT_ADDRESS(unsigned char CXWndManager::GetGlobalAlpha(void)const ,CXWndManager__GetGlobalAlpha); +#endif +#ifdef CXWndManager__SetGlobalFadeToAlpha_x +FUNCTION_AT_ADDRESS(void CXWndManager::SetGlobalFadeToAlpha(unsigned char),CXWndManager__SetGlobalFadeToAlpha); +#endif +#ifdef CXWndManager__GetGlobalFadeToAlpha_x +FUNCTION_AT_ADDRESS(unsigned char CXWndManager::GetGlobalFadeToAlpha(void)const ,CXWndManager__GetGlobalFadeToAlpha); +#endif +#ifdef CXWndManager__IsAllValid_x +FUNCTION_AT_ADDRESS(bool CXWndManager::IsAllValid(void),CXWndManager__IsAllValid); +#endif +#ifdef CEditWnd__CEditWnd_x +//FUNCTION_AT_ADDRESS( CEditWnd::CEditWnd(class CXWnd *,unsigned __int32,class CXRect,unsigned __int32),CEditWnd__CEditWnd); +#endif +#ifdef CEditWnd__GetLineForPrintableChar_x +FUNCTION_AT_ADDRESS(int CEditWnd::GetLineForPrintableChar(int)const ,CEditWnd__GetLineForPrintableChar); +#endif +#ifdef CEditWnd__GetLineLength_x +FUNCTION_AT_ADDRESS(int CEditWnd::GetLineLength(int)const ,CEditWnd__GetLineLength); +#endif +#ifdef CEditWnd__FillIndexArray_x +FUNCTION_AT_ADDRESS(void CEditWnd::FillIndexArray(class CXStr)const ,CEditWnd__FillIndexArray); +#endif +#ifdef CEditWnd__SelectableCharFromPoint_x +FUNCTION_AT_ADDRESS(int CEditWnd::SelectableCharFromPoint(class CXPoint)const ,CEditWnd__SelectableCharFromPoint); +#endif +#ifdef CEditWnd__AddItemTag_x +FUNCTION_AT_ADDRESS(void CEditWnd::AddItemTag(int,char *,int),CEditWnd__AddItemTag); +#endif +#ifdef CEditWnd__ProcessText_x +FUNCTION_AT_ADDRESS(void CEditWnd::ProcessText(void),CEditWnd__ProcessText); +#endif +#ifdef CEditWnd__GetCharIndexPt_x +FUNCTION_AT_ADDRESS(class CXPoint CEditWnd::GetCharIndexPt(int)const ,CEditWnd__GetCharIndexPt); +#endif +#ifdef CEditWnd__GetSelStartPt_x +FUNCTION_AT_ADDRESS(class CXPoint CEditWnd::GetSelStartPt(void)const ,CEditWnd__GetSelStartPt); +#endif +#ifdef CEditWnd__GetSelEndPt_x +FUNCTION_AT_ADDRESS(class CXPoint CEditWnd::GetSelEndPt(void)const ,CEditWnd__GetSelEndPt); +#endif +#ifdef CEditWnd__FilterInputStr_x +FUNCTION_AT_ADDRESS(void CEditWnd::FilterInputStr(class CXStr &),CEditWnd__FilterInputStr); +#endif +#ifdef CEditWnd__ReplaceSelection_x +FUNCTION_AT_ADDRESS(void CEditWnd::ReplaceSelection(class CXStr,bool),CEditWnd__ReplaceSelection); +#endif +#ifdef CEditWnd__ReplaceSelection1_x +FUNCTION_AT_ADDRESS(void CEditWnd::ReplaceSelection(char,bool),CEditWnd__ReplaceSelection1); +#endif +#ifdef CEditWnd__CalculateScrollRange_x +FUNCTION_AT_ADDRESS(void CEditWnd::CalculateScrollRange(void),CEditWnd__CalculateScrollRange); +#endif +#ifdef CEditWnd__EnsureCaretVisible_x +FUNCTION_AT_ADDRESS(void CEditWnd::EnsureCaretVisible(void),CEditWnd__EnsureCaretVisible); +#endif +#ifdef CEditWnd__SetEditable_x +FUNCTION_AT_ADDRESS(void CEditWnd::SetEditable(bool),CEditWnd__SetEditable); +#endif +#ifdef CEditWnd__GetSTMLSafeText_x +FUNCTION_AT_ADDRESS(class CXStr CEditWnd::GetSTMLSafeText(void),CEditWnd__GetSTMLSafeText); +#endif +#ifdef CEditWnd__ConvertIndexPrintableToTagged_x +FUNCTION_AT_ADDRESS(int CEditWnd::ConvertIndexPrintableToTagged(int),CEditWnd__ConvertIndexPrintableToTagged); +#endif +#ifdef CEditWnd__ConvertIndexTaggedToPrintable_x +FUNCTION_AT_ADDRESS(int CEditWnd::ConvertIndexTaggedToPrintable(int),CEditWnd__ConvertIndexTaggedToPrintable); +#endif +#ifdef CTextureFont__GetWidth_x +FUNCTION_AT_ADDRESS(int CTextureFont::GetWidth(unsigned short)const ,CTextureFont__GetWidth); +#endif +#ifdef CTextureFont__GetKerning_x +FUNCTION_AT_ADDRESS(int CTextureFont::GetKerning(unsigned short,unsigned short)const ,CTextureFont__GetKerning); +#endif +#ifdef CTextureFont__GetTextExtent_x +FUNCTION_AT_ADDRESS(int CTextureFont::GetTextExtent(class CXStr)const ,CTextureFont__GetTextExtent); +#endif +#ifdef CTextureFont__GetHeight_x +FUNCTION_AT_ADDRESS(int CTextureFont::GetHeight(void)const ,CTextureFont__GetHeight); +#endif +#ifdef CTextureFont__GetName_x +FUNCTION_AT_ADDRESS(class CXStr CTextureFont::GetName(void)const ,CTextureFont__GetName); +#endif +#ifdef CTextureFont__DrawWrappedText_x +FUNCTION_AT_ADDRESS(int CTextureFont::DrawWrappedText(class CXStr *,int,int,int,class CXRect *,unsigned long,unsigned short,int)const ,CTextureFont__DrawWrappedText); +#endif +#ifdef CTextureFont__DrawWrappedText1_x +FUNCTION_AT_ADDRESS(int CTextureFont::DrawWrappedText(class CXStr,class CXRect,class CXRect,unsigned long,unsigned short,int)const ,CTextureFont__DrawWrappedText1); +#endif +#ifdef CTextureAnimation__CTextureAnimation_x +FUNCTION_AT_ADDRESS( CTextureAnimation::CTextureAnimation(void),CTextureAnimation__CTextureAnimation); +#endif +#ifdef CTextureAnimation__CTextureAnimation1_x +FUNCTION_AT_ADDRESS( CTextureAnimation::CTextureAnimation(class CXStr),CTextureAnimation__CTextureAnimation1); +#endif +#ifdef CUITexturePiece__CUITexturePiece1_x +FUNCTION_AT_ADDRESS( CUITexturePiece::CUITexturePiece(class CUITexturePiece const &),CUITexturePiece__CUITexturePiece1); +#endif +#ifdef CTextureAnimation__AddFrame_x +FUNCTION_AT_ADDRESS(int CTextureAnimation::AddFrame(class CUITextureInfo const *,class CXRect,unsigned __int32,class CXPoint),CTextureAnimation__AddFrame); +#endif +#ifdef CUITexturePiece__CUITexturePiece2_x +//FUNCTION_AT_ADDRESS( CUITexturePiece::CUITexturePiece(class CUITextureInfo,class CXRect),CUITexturePiece__CUITexturePiece2); +#endif +#ifdef CUITextureInfo__CUITextureInfo2_x +FUNCTION_AT_ADDRESS( CUITextureInfo::CUITextureInfo(class CUITextureInfo const &),CUITextureInfo__CUITextureInfo2); +#endif +#ifdef CTextureAnimation__AddFrame1_x +//FUNCTION_AT_ADDRESS(int CTextureAnimation::AddFrame(class CUITexturePiece,unsigned __int32,class CXPoint),CTextureAnimation__AddFrame1); +#endif +#ifdef STextureAnimationFrame__STextureAnimationFrame1_x +FUNCTION_AT_ADDRESS( STextureAnimationFrame::STextureAnimationFrame(class CUITexturePiece,unsigned __int32,class CXPoint),STextureAnimationFrame__STextureAnimationFrame1); +#endif +#ifdef CUITextureInfo__CUITextureInfo3_x +FUNCTION_AT_ADDRESS( CUITextureInfo::CUITextureInfo(unsigned __int32,int),CUITextureInfo__CUITextureInfo3); +#endif +#ifdef CTextureAnimation__AddBlankFrame_x +FUNCTION_AT_ADDRESS(int CTextureAnimation::AddBlankFrame(unsigned __int32,class CXPoint),CTextureAnimation__AddBlankFrame); +#endif +#ifdef CTextureAnimation__SetCurFrame_x +FUNCTION_AT_ADDRESS(void CTextureAnimation::SetCurFrame(int),CTextureAnimation__SetCurFrame); +#endif +#ifdef CTextureAnimation__GetCurFrame_x +FUNCTION_AT_ADDRESS(int CTextureAnimation::GetCurFrame(void)const ,CTextureAnimation__GetCurFrame); +#endif +#ifdef CTextureAnimation__Draw_x +FUNCTION_AT_ADDRESS(int CTextureAnimation::Draw(class CXRect,class CXRect,unsigned long,unsigned long)const ,CTextureAnimation__Draw); +#endif +#ifdef CTextureAnimation__Draw1_x +FUNCTION_AT_ADDRESS(int CTextureAnimation::Draw(class CXPoint,class CXRect,unsigned long,unsigned long)const ,CTextureAnimation__Draw1); +#endif +#ifdef CTextureAnimation__GetHotspot_x +FUNCTION_AT_ADDRESS(class CXPoint CTextureAnimation::GetHotspot(void)const ,CTextureAnimation__GetHotspot); +#endif +#ifdef CTextureAnimation__SetCurCell_x +FUNCTION_AT_ADDRESS(void CTextureAnimation::SetCurCell(int),CTextureAnimation__SetCurCell); +#endif +#ifdef CTextureAnimation__Preload_x +FUNCTION_AT_ADDRESS(int CTextureAnimation::Preload(void),CTextureAnimation__Preload); +#endif +#ifdef CUITextureInfo__operator_equal_x +FUNCTION_AT_ADDRESS(class CUITextureInfo & CUITextureInfo::operator=(class CUITextureInfo const &),CUITextureInfo__operator_equal); +#endif +#ifdef CSidlManager__CSidlManager_x +FUNCTION_AT_ADDRESS( CSidlManager::CSidlManager(void),CSidlManager__CSidlManager); +#endif +#ifdef CSidlManager__GetPointFromParamPoint_x +FUNCTION_AT_ADDRESS(class CXPoint __cdecl CSidlManager::GetPointFromParamPoint(class CParamPoint const &),CSidlManager__GetPointFromParamPoint); +#endif +#ifdef CSidlManager__GetSizeFromParamSize_x +FUNCTION_AT_ADDRESS(class CXSize __cdecl CSidlManager::GetSizeFromParamSize(class CParamSize const &),CSidlManager__GetSizeFromParamSize); +#endif +#ifdef CSidlManager__GetRectFromParamPointSize_x +FUNCTION_AT_ADDRESS(class CXRect __cdecl CSidlManager::GetRectFromParamPointSize(class CParamPoint const &,class CParamSize const &),CSidlManager__GetRectFromParamPointSize); +#endif +#ifdef CSidlManager__GetD3DCOLOR_x +FUNCTION_AT_ADDRESS(unsigned long __cdecl CSidlManager::GetD3DCOLOR(class CParamRGB const &),CSidlManager__GetD3DCOLOR); +#endif +#ifdef CSidlManager__GetButtonDrawTemplateFromParamButtonDrawTemplate_x +FUNCTION_AT_ADDRESS(class CButtonDrawTemplate CSidlManager::GetButtonDrawTemplateFromParamButtonDrawTemplate(class CParamButtonDrawTemplate const &)const ,CSidlManager__GetButtonDrawTemplateFromParamButtonDrawTemplate); +#endif +#ifdef CSidlManager__GetGaugeDrawTemplateFromParamGaugeDrawTemplate_x +FUNCTION_AT_ADDRESS(class CGaugeDrawTemplate CSidlManager::GetGaugeDrawTemplateFromParamGaugeDrawTemplate(class CParamGaugeDrawTemplate const &)const ,CSidlManager__GetGaugeDrawTemplateFromParamGaugeDrawTemplate); +#endif +#ifdef CSidlManager__GetSpellGemDrawTemplateFromParamSpellGemDrawTemplate_x +FUNCTION_AT_ADDRESS(class CSpellGemDrawTemplate CSidlManager::GetSpellGemDrawTemplateFromParamSpellGemDrawTemplate(class CParamSpellGemDrawTemplate const &)const ,CSidlManager__GetSpellGemDrawTemplateFromParamSpellGemDrawTemplate); +#endif +#ifdef CSidlManager__DeleteContents_x +FUNCTION_AT_ADDRESS(void CSidlManager::DeleteContents(void),CSidlManager__DeleteContents); +#endif +#ifdef CParamScrollbarDrawTemplate__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamScrollbarDrawTemplate & CParamScrollbarDrawTemplate::operator=(class CParamScrollbarDrawTemplate const &),CParamScrollbarDrawTemplate__operator_equal); +#endif +#ifdef CParamFrameTemplate__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamFrameTemplate & CParamFrameTemplate::operator=(class CParamFrameTemplate const &),CParamFrameTemplate__operator_equal); +#endif +#ifdef CParamButtonDrawTemplate__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamButtonDrawTemplate & CParamButtonDrawTemplate::operator=(class CParamButtonDrawTemplate const &),CParamButtonDrawTemplate__operator_equal); +#endif +#ifdef CParamClass__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamClass & CParamClass::operator=(class CParamClass const &),CParamClass__operator_equal); +#endif +#ifdef CParamRGB__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamRGB & CParamRGB::operator=(class CParamRGB const &),CParamRGB__operator_equal); +#endif +#ifdef CParam__operator_equal_x +FUNCTION_AT_ADDRESS(class CParam & CParam::operator=(class CParam const &),CParam__operator_equal); +#endif +#ifdef CXMLData__operator_equal_x +FUNCTION_AT_ADDRESS(class CXMLData & CXMLData::operator=(class CXMLData const &),CXMLData__operator_equal); +#endif +#ifdef CTAFrameDraw__GetName_x +FUNCTION_AT_ADDRESS(class CXStr CTAFrameDraw::GetName(void)const ,CTAFrameDraw__GetName); +#endif +#ifdef CScreenPieceTemplate__GetName_x +FUNCTION_AT_ADDRESS(class CXStr CScreenPieceTemplate::GetName(void)const ,CScreenPieceTemplate__GetName); +#endif +#ifdef CSidlManager__LoadSidl_x +FUNCTION_AT_ADDRESS(void CSidlManager::LoadSidl(class CXStr,class CXStr,class CXStr),CSidlManager__LoadSidl); +#endif +#ifdef CUITextureInfo__CUITextureInfo4_x +FUNCTION_AT_ADDRESS( CUITextureInfo::CUITextureInfo(class CXStr,class CXSize),CUITextureInfo__CUITextureInfo4); +#endif +#ifdef CSidlManager__CreateTextureAnimationFromSidlAnimation_x +FUNCTION_AT_ADDRESS(class CTextureAnimation CSidlManager::CreateTextureAnimationFromSidlAnimation(class CParamUi2DAnimation const *)const ,CSidlManager__CreateTextureAnimationFromSidlAnimation); +#endif +#ifdef CSidlManager__CreateTAFrameDrawFromSidlFrame_x +FUNCTION_AT_ADDRESS(class CTAFrameDraw CSidlManager::CreateTAFrameDrawFromSidlFrame(class CParamFrameTemplate const *)const ,CSidlManager__CreateTAFrameDrawFromSidlFrame); +#endif +#ifdef CSidlManager__GetScrollbarTemplateFromParamScrollbarTemplate_x +FUNCTION_AT_ADDRESS(class CScrollbarTemplate CSidlManager::GetScrollbarTemplateFromParamScrollbarTemplate(class CParamScrollbarDrawTemplate const &)const ,CSidlManager__GetScrollbarTemplateFromParamScrollbarTemplate); +#endif +#ifdef CScrollbarTemplate__CScrollbarTemplate_x +FUNCTION_AT_ADDRESS( CScrollbarTemplate::CScrollbarTemplate(class CScrollbarTemplate const &),CScrollbarTemplate__CScrollbarTemplate); +#endif +#ifdef CSidlManager__GetSliderDrawTemplateFromParamSliderDrawTemplate_x +FUNCTION_AT_ADDRESS(class CSliderDrawTemplate CSidlManager::GetSliderDrawTemplateFromParamSliderDrawTemplate(class CParamSliderDrawTemplate const &)const ,CSidlManager__GetSliderDrawTemplateFromParamSliderDrawTemplate); +#endif +#ifdef CButtonDrawTemplate__CButtonDrawTemplate1_x +FUNCTION_AT_ADDRESS( CButtonDrawTemplate::CButtonDrawTemplate(class CButtonDrawTemplate const &),CButtonDrawTemplate__CButtonDrawTemplate1); +#endif +#ifdef CSliderDrawTemplate__dCSliderDrawTemplate_x +FUNCTION_AT_ADDRESS( CSliderDrawTemplate::~CSliderDrawTemplate(void),CSliderDrawTemplate__dCSliderDrawTemplate); +#endif +#ifdef CSidlManager__CreateDrawTemplateFromParamWindowDrawTemplate_x +FUNCTION_AT_ADDRESS(class CXWndDrawTemplate CSidlManager::CreateDrawTemplateFromParamWindowDrawTemplate(class CParamWindowDrawTemplate const *)const ,CSidlManager__CreateDrawTemplateFromParamWindowDrawTemplate); +#endif +#ifdef CScrollbarTemplate__CScrollbarTemplate1_x +FUNCTION_AT_ADDRESS( CScrollbarTemplate::CScrollbarTemplate(void),CScrollbarTemplate__CScrollbarTemplate1); +#endif +#ifdef CXWndDrawTemplate__CXWndDrawTemplate1_x +FUNCTION_AT_ADDRESS( CXWndDrawTemplate::CXWndDrawTemplate(class CXWndDrawTemplate const &),CXWndDrawTemplate__CXWndDrawTemplate1); +#endif +#ifdef CTAFrameDraw__CTAFrameDraw_x +FUNCTION_AT_ADDRESS( CTAFrameDraw::CTAFrameDraw(class CTAFrameDraw const &),CTAFrameDraw__CTAFrameDraw); +#endif +#ifdef CSidlManager__CreateScreenPieceTemplateFromParamScreenPiece_x +FUNCTION_AT_ADDRESS(class CScreenPieceTemplate * CSidlManager::CreateScreenPieceTemplateFromParamScreenPiece(class CParamScreenPiece const *)const ,CSidlManager__CreateScreenPieceTemplateFromParamScreenPiece); +#endif +#ifdef CSidlManager__GetParsingErrorMsg_x +FUNCTION_AT_ADDRESS(class CXStr CSidlManager::GetParsingErrorMsg(void)const ,CSidlManager__GetParsingErrorMsg); +#endif +#ifdef CSidlManager__GetScreenPieceEnum_x +//FUNCTION_AT_ADDRESS(enum EStaticScreenPieceClasses CSidlManager::GetScreenPieceEnum(class CScreenPieceTemplate *)const ,CSidlManager__GetScreenPieceEnum); +#endif +#ifdef CSidlManager__FindAnimation_x +FUNCTION_AT_ADDRESS(class CTextureAnimation * CSidlManager::FindAnimation(unsigned __int32)const ,CSidlManager__FindAnimation); +#endif +#ifdef CSidlManager__FindAnimation1_x +FUNCTION_AT_ADDRESS(class CTextureAnimation * CSidlManager::FindAnimation(class CXStr)const ,CSidlManager__FindAnimation1); +#endif +#ifdef CSidlManager__FindFrameDraw_x +FUNCTION_AT_ADDRESS(class CTAFrameDraw * CSidlManager::FindFrameDraw(unsigned __int32)const ,CSidlManager__FindFrameDraw); +#endif +#ifdef CSidlManager__FindDrawTemplate_x +FUNCTION_AT_ADDRESS(class CXWndDrawTemplate * CSidlManager::FindDrawTemplate(unsigned __int32)const ,CSidlManager__FindDrawTemplate); +#endif +#ifdef CSidlManager__FindDrawTemplate1_x +FUNCTION_AT_ADDRESS(class CXWndDrawTemplate * CSidlManager::FindDrawTemplate(class CXStr)const ,CSidlManager__FindDrawTemplate1); +#endif +#ifdef CSidlManager__FindScreenPieceTemplate_x +FUNCTION_AT_ADDRESS(class CScreenPieceTemplate * CSidlManager::FindScreenPieceTemplate(unsigned __int32)const ,CSidlManager__FindScreenPieceTemplate); +#endif +#ifdef CSidlManager__FindScreenPieceTemplate1_x +FUNCTION_AT_ADDRESS(class CScreenPieceTemplate * CSidlManager::FindScreenPieceTemplate(class CXStr *)const ,CSidlManager__FindScreenPieceTemplate1); +#endif +#ifdef CSidlManager__AddAnimationInOrder_x +FUNCTION_AT_ADDRESS(void CSidlManager::AddAnimationInOrder(class CTextureAnimation *),CSidlManager__AddAnimationInOrder); +#endif +#ifdef CSidlManager__AddDrawTemplateInOrder_x +FUNCTION_AT_ADDRESS(void CSidlManager::AddDrawTemplateInOrder(class CXWndDrawTemplate *),CSidlManager__AddDrawTemplateInOrder); +#endif +#ifdef CSidlManager__AddTAFrameDrawInOrder_x +FUNCTION_AT_ADDRESS(void CSidlManager::AddTAFrameDrawInOrder(class CTAFrameDraw *),CSidlManager__AddTAFrameDrawInOrder); +#endif +#ifdef CSidlManager__AddScreenPieceTemplateInOrder_x +FUNCTION_AT_ADDRESS(void CSidlManager::AddScreenPieceTemplateInOrder(class CScreenPieceTemplate *),CSidlManager__AddScreenPieceTemplateInOrder); +#endif +#ifdef CSidlManager__FindTexture_x +FUNCTION_AT_ADDRESS(class CUITextureInfo * CSidlManager::FindTexture(class CXStr)const ,CSidlManager__FindTexture); +#endif +#ifdef CSidlManager__FindTexture1_x +FUNCTION_AT_ADDRESS(class CUITextureInfo * CSidlManager::FindTexture(unsigned __int32)const ,CSidlManager__FindTexture1); +#endif +#ifdef CSidlManager__FindButtonDrawTemplate_x +FUNCTION_AT_ADDRESS(class CButtonDrawTemplate * CSidlManager::FindButtonDrawTemplate(unsigned __int32)const ,CSidlManager__FindButtonDrawTemplate); +#endif +#ifdef CSidlManager__FindSliderDrawTemplate_x +FUNCTION_AT_ADDRESS(class CSliderDrawTemplate * CSidlManager::FindSliderDrawTemplate(class CXStr)const ,CSidlManager__FindSliderDrawTemplate); +#endif +#ifdef CSidlManager__FindSliderDrawTemplate1_x +FUNCTION_AT_ADDRESS(class CSliderDrawTemplate * CSidlManager::FindSliderDrawTemplate(unsigned __int32)const ,CSidlManager__FindSliderDrawTemplate1); +#endif +#ifdef CSidlManager__CreateXWndFromTemplate_x +FUNCTION_AT_ADDRESS(class CXWnd * CSidlManager::CreateXWndFromTemplate(class CXWnd *,class CControlTemplate *),CSidlManager__CreateXWndFromTemplate); +#endif +#ifdef CTAFrameDraw__GetAnimation_x +FUNCTION_AT_ADDRESS(class CTextureAnimation * CTAFrameDraw::GetAnimation(int)const ,CTAFrameDraw__GetAnimation); +#endif +#ifdef CXWnd__SetXMLTooltip_x +FUNCTION_AT_ADDRESS(void CXWnd::SetXMLTooltip(class CXStr),CXWnd__SetXMLTooltip); +#endif +#ifdef CSidlManager__TranslateString_x +FUNCTION_AT_ADDRESS(class CXStr __cdecl CSidlManager::TranslateString(class CXStr),CSidlManager__TranslateString); +#endif +#ifdef CXMLEnumInfo__dCXMLEnumInfo_x +FUNCTION_AT_ADDRESS( CXMLEnumInfo::~CXMLEnumInfo(void),CXMLEnumInfo__dCXMLEnumInfo); +#endif +#ifdef CXMLDataClass__dCXMLDataClass_x +FUNCTION_AT_ADDRESS( CXMLDataClass::~CXMLDataClass(void),CXMLDataClass__dCXMLDataClass); +#endif +#ifdef CTAFrameDraw__CTAFrameDraw1_x +FUNCTION_AT_ADDRESS( CTAFrameDraw::CTAFrameDraw(class CXStr),CTAFrameDraw__CTAFrameDraw1); +#endif +#ifdef CTAFrameDraw__Set_x +FUNCTION_AT_ADDRESS(void CTAFrameDraw::Set(class CTextureAnimation * * const),CTAFrameDraw__Set); +#endif +#ifdef CTAFrameDraw__Draw_x +FUNCTION_AT_ADDRESS(int CTAFrameDraw::Draw(class CXRect,class CXRect)const ,CTAFrameDraw__Draw); +#endif +#ifdef CTAFrameDraw__Draw1_x +FUNCTION_AT_ADDRESS(int CTAFrameDraw::Draw(class CXRect,class CXRect,int)const ,CTAFrameDraw__Draw1); +#endif +#ifdef CTAFrameDraw__GetHitTestRect_x +FUNCTION_AT_ADDRESS(class CXRect CTAFrameDraw::GetHitTestRect(class CXRect,int)const ,CTAFrameDraw__GetHitTestRect); +#endif +#ifdef CTAFrameDraw__GetPieceRect_x +FUNCTION_AT_ADDRESS(class CXRect CTAFrameDraw::GetPieceRect(class CXRect,int)const ,CTAFrameDraw__GetPieceRect); +#endif +#ifdef CTAFrameDraw__IsHorizontal_x +FUNCTION_AT_ADDRESS(bool CTAFrameDraw::IsHorizontal(void)const ,CTAFrameDraw__IsHorizontal); +#endif +#ifdef CTAFrameDraw__IsVertical_x +FUNCTION_AT_ADDRESS(bool CTAFrameDraw::IsVertical(void)const ,CTAFrameDraw__IsVertical); +#endif +#ifdef CTAFrameDraw__GetExtent_x +FUNCTION_AT_ADDRESS(int CTAFrameDraw::GetExtent(void)const ,CTAFrameDraw__GetExtent); +#endif +#ifdef CTAFrameDraw__GetMinLength_x +FUNCTION_AT_ADDRESS(int CTAFrameDraw::GetMinLength(void)const ,CTAFrameDraw__GetMinLength); +#endif +#ifdef CTAFrameDraw__GetInnerRect_x +FUNCTION_AT_ADDRESS(class CXRect CTAFrameDraw::GetInnerRect(class CXRect)const ,CTAFrameDraw__GetInnerRect); +#endif +#ifdef CSpellGemWnd__CSpellGemWnd_x +FUNCTION_AT_ADDRESS( CSpellGemWnd::CSpellGemWnd(class CXWnd *,unsigned __int32,class CXRect,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,int,int,unsigned long),CSpellGemWnd__CSpellGemWnd); +#endif +#ifdef CSpellGemWnd__Init_x +FUNCTION_AT_ADDRESS(void CSpellGemWnd::Init(void),CSpellGemWnd__Init); +#endif +#ifdef CSpellGemWnd__SetSpellIconIndex_x +FUNCTION_AT_ADDRESS(void CSpellGemWnd::SetSpellIconIndex(int),CSpellGemWnd__SetSpellIconIndex); +#endif +#ifdef CSpellGemWnd__SetSpellGemTint_x +FUNCTION_AT_ADDRESS(void CSpellGemWnd::SetSpellGemTint(unsigned long),CSpellGemWnd__SetSpellGemTint); +#endif +#ifdef CSpellGemWnd__SetGemTintStage_x +FUNCTION_AT_ADDRESS(void CSpellGemWnd::SetGemTintStage(int),CSpellGemWnd__SetGemTintStage); +#endif +#ifdef CSpellGemWnd__SetCheck_x +FUNCTION_AT_ADDRESS(void CSpellGemWnd::SetCheck(bool),CSpellGemWnd__SetCheck); +#endif +#ifdef CSliderWnd__CSliderWnd_x +FUNCTION_AT_ADDRESS( CSliderWnd::CSliderWnd(class CXWnd *,unsigned __int32,class CXRect,class CSliderTemplate *),CSliderWnd__CSliderWnd); +#endif +#ifdef CSliderWnd__SetValue_x +FUNCTION_AT_ADDRESS(void CSliderWnd::SetValue(int),CSliderWnd__SetValue); +#endif +#ifdef CSliderWnd__SetNumTicks_x +FUNCTION_AT_ADDRESS(void CSliderWnd::SetNumTicks(int),CSliderWnd__SetNumTicks); +#endif +#ifdef CSliderWnd__UpdateThumb_x +FUNCTION_AT_ADDRESS(void CSliderWnd::UpdateThumb(void),CSliderWnd__UpdateThumb); +#endif +#ifdef CSliderWnd__UpdateMiddleRange_x +FUNCTION_AT_ADDRESS(void CSliderWnd::UpdateMiddleRange(void),CSliderWnd__UpdateMiddleRange); +#endif +#ifdef CSliderWnd__GetValue_x +FUNCTION_AT_ADDRESS(int CSliderWnd::GetValue(void)const,CSliderWnd__GetValue); +#endif +#ifdef CSliderWnd__GetMiddleRangeRect_x +FUNCTION_AT_ADDRESS(class CXRect CSliderWnd::GetMiddleRangeRect(void)const ,CSliderWnd__GetMiddleRangeRect); +#endif +#ifdef CSliderWnd__GetEndCapLeftRect_x +FUNCTION_AT_ADDRESS(class CXRect CSliderWnd::GetEndCapLeftRect(void)const ,CSliderWnd__GetEndCapLeftRect); +#endif +#ifdef CSliderWnd__GetEndCapRightRect_x +FUNCTION_AT_ADDRESS(class CXRect CSliderWnd::GetEndCapRightRect(void)const ,CSliderWnd__GetEndCapRightRect); +#endif +#ifdef CSliderWnd__GetThumbRect_x +FUNCTION_AT_ADDRESS(class CXRect CSliderWnd::GetThumbRect(void)const ,CSliderWnd__GetThumbRect); +#endif +#ifdef CSliderWnd__SetThumbToOffset_x +FUNCTION_AT_ADDRESS(void CSliderWnd::SetThumbToOffset(int),CSliderWnd__SetThumbToOffset); +#endif +#ifdef CSliderWnd__DrawMiddleRange_x +FUNCTION_AT_ADDRESS(int CSliderWnd::DrawMiddleRange(void)const ,CSliderWnd__DrawMiddleRange); +#endif +#ifdef CSliderWnd__DrawEndCapLeft_x +FUNCTION_AT_ADDRESS(int CSliderWnd::DrawEndCapLeft(void)const ,CSliderWnd__DrawEndCapLeft); +#endif +#ifdef CSliderWnd__DrawEndCapRight_x +FUNCTION_AT_ADDRESS(int CSliderWnd::DrawEndCapRight(void)const ,CSliderWnd__DrawEndCapRight); +#endif +#ifdef CSliderWnd__DrawThumb_x +FUNCTION_AT_ADDRESS(int CSliderWnd::DrawThumb(void)const ,CSliderWnd__DrawThumb); +#endif +#ifdef CXWnd__DrawRaisedRect_x +FUNCTION_AT_ADDRESS(int __cdecl CXWnd::DrawRaisedRect(class CXRect,class CXRect),CXWnd__DrawRaisedRect); +#endif +#ifdef CXWnd__DrawSunkenRect_x +FUNCTION_AT_ADDRESS(int __cdecl CXWnd::DrawSunkenRect(class CXRect,class CXRect),CXWnd__DrawSunkenRect); +#endif +#ifdef CEditBaseWnd__SetSel_x +FUNCTION_AT_ADDRESS(void CEditBaseWnd::SetSel(int,int),CEditBaseWnd__SetSel); +#endif +#ifdef CInvSlotWnd__CInvSlotWnd_x +FUNCTION_AT_ADDRESS( CInvSlotWnd::CInvSlotWnd(class CXWnd *,unsigned __int32,class CXRect,class CTextureAnimation *,int,int,int),CInvSlotWnd__CInvSlotWnd); +#endif +#ifdef CInvSlotWnd__SetInvSlot_x +FUNCTION_AT_ADDRESS(void CInvSlotWnd::SetInvSlot(class CInvSlot *),CInvSlotWnd__SetInvSlot); +#endif +#ifdef CInvSlotWnd__DrawTooltip_x +FUNCTION_AT_ADDRESS(int CInvSlotWnd::DrawTooltip(class CXWnd const *)const,CInvSlotWnd__DrawTooltip); +#endif +#ifdef CLabel__CLabel_x +FUNCTION_AT_ADDRESS( CLabel::CLabel(class CXWnd *,unsigned __int32,class CXRect,int),CLabel__CLabel); +#endif +#ifdef CLabel__SetNoWrap_x +FUNCTION_AT_ADDRESS(void CLabel::SetNoWrap(bool),CLabel__SetNoWrap); +#endif +#ifdef CLabel__SetAlignRight_x +FUNCTION_AT_ADDRESS(void CLabel::SetAlignRight(bool),CLabel__SetAlignRight); +#endif +#ifdef CLabel__SetAlignCenter_x +FUNCTION_AT_ADDRESS(void CLabel::SetAlignCenter(bool),CLabel__SetAlignCenter); +#endif +#ifdef CIMEManager__CIMEManager_x +FUNCTION_AT_ADDRESS( CIMEManager::CIMEManager(struct HWND__ *),CIMEManager__CIMEManager); +#endif +#ifdef CIMEManager__dCIMEManager_x +FUNCTION_AT_ADDRESS( CIMEManager::~CIMEManager(void),CIMEManager__dCIMEManager); +#endif +#ifdef CIMEManager__handleWndProc_x +FUNCTION_AT_ADDRESS(int CIMEManager::handleWndProc(unsigned int,unsigned int,long),CIMEManager__handleWndProc); +#endif +#ifdef CIMEManager__handleAddChar_x +FUNCTION_AT_ADDRESS(int CIMEManager::handleAddChar(unsigned short),CIMEManager__handleAddChar); +#endif +#ifdef CIMEManager__handleInputComposition_x +FUNCTION_AT_ADDRESS(int CIMEManager::handleInputComposition(long),CIMEManager__handleInputComposition); +#endif +#ifdef CIMEManager__handleEndComposition_x +FUNCTION_AT_ADDRESS(int CIMEManager::handleEndComposition(void),CIMEManager__handleEndComposition); +#endif +#ifdef CIMEManager__handleStartComposition_x +FUNCTION_AT_ADDRESS(int CIMEManager::handleStartComposition(void),CIMEManager__handleStartComposition); +#endif +#ifdef CIMEManager__handleOpenCandidates_x +FUNCTION_AT_ADDRESS(int CIMEManager::handleOpenCandidates(void),CIMEManager__handleOpenCandidates); +#endif +#ifdef CIMEManager__handleChangeCandidates_x +FUNCTION_AT_ADDRESS(int CIMEManager::handleChangeCandidates(void),CIMEManager__handleChangeCandidates); +#endif +#ifdef CIMEManager__handleCloseCandidates_x +FUNCTION_AT_ADDRESS(int CIMEManager::handleCloseCandidates(void),CIMEManager__handleCloseCandidates); +#endif +#ifdef CIMEManager__handleImeStatusChanged_x +FUNCTION_AT_ADDRESS(int CIMEManager::handleImeStatusChanged(void),CIMEManager__handleImeStatusChanged); +#endif +#ifdef CIMEManager__handleImeChanged_x +FUNCTION_AT_ADDRESS(int CIMEManager::handleImeChanged(void),CIMEManager__handleImeChanged); +#endif +#ifdef CIMEManager__setInputEditWnd_x +FUNCTION_AT_ADDRESS(int CIMEManager::setInputEditWnd(class CEditWnd *),CIMEManager__setInputEditWnd); +#endif +#ifdef CIMEManager__turnImeOn_x +FUNCTION_AT_ADDRESS(void CIMEManager::turnImeOn(void),CIMEManager__turnImeOn); +#endif +#ifdef CIMEManager__turnImeOff_x +FUNCTION_AT_ADDRESS(void CIMEManager::turnImeOff(void),CIMEManager__turnImeOff); +#endif +#ifdef CIMEManager__imeIsOn_x +FUNCTION_AT_ADDRESS(bool CIMEManager::imeIsOn(void)const ,CIMEManager__imeIsOn); +#endif +#ifdef CIMEManager__imeIsOff_x +FUNCTION_AT_ADDRESS(bool CIMEManager::imeIsOff(void)const ,CIMEManager__imeIsOff); +#endif +#ifdef CIMEManager__enableIme_x +FUNCTION_AT_ADDRESS(void CIMEManager::enableIme(bool),CIMEManager__enableIme); +#endif +#ifdef CIMEManager__queryImeLanguage_x +FUNCTION_AT_ADDRESS(int CIMEManager::queryImeLanguage(void)const ,CIMEManager__queryImeLanguage); +#endif +#ifdef CIMEManager__queryImeProperties_x +FUNCTION_AT_ADDRESS(int CIMEManager::queryImeProperties(void)const ,CIMEManager__queryImeProperties); +#endif +#ifdef CIMEManager__setInputState_x +FUNCTION_AT_ADDRESS(void CIMEManager::setInputState(int),CIMEManager__setInputState); +#endif +#ifdef CIMEManager__getInputState_x +FUNCTION_AT_ADDRESS(int CIMEManager::getInputState(void)const ,CIMEManager__getInputState); +#endif +#ifdef CIMEManager__getInputLanguage_x +FUNCTION_AT_ADDRESS(int CIMEManager::getInputLanguage(void)const ,CIMEManager__getInputLanguage); +#endif +#ifdef CIMEManager__getImeProperties_x +FUNCTION_AT_ADDRESS(int CIMEManager::getImeProperties(void)const ,CIMEManager__getImeProperties); +#endif +#ifdef CIMEManager__getWindowHandle_x +FUNCTION_AT_ADDRESS(struct HWND__ * CIMEManager::getWindowHandle(void)const ,CIMEManager__getWindowHandle); +#endif +#ifdef CUITextureInfo__Draw_x +FUNCTION_AT_ADDRESS(int CUITextureInfo::Draw(class CXRect,class CXRect,class CXRect,unsigned long,unsigned long)const ,CUITextureInfo__Draw); +#endif +#ifdef CUITextureInfo__Draw1_x +FUNCTION_AT_ADDRESS(int CUITextureInfo::Draw(class CXRect,class CXRect,class CXRect,unsigned long *,unsigned long *)const ,CUITextureInfo__Draw1); +#endif +#ifdef CUITexturePiece__Draw_x +FUNCTION_AT_ADDRESS(int CUITexturePiece::Draw(class CXRect,class CXRect,unsigned long,unsigned long)const ,CUITexturePiece__Draw); +#endif +#ifdef CUITexturePiece__Draw1_x +FUNCTION_AT_ADDRESS(int CUITexturePiece::Draw(class CXRect,class CXRect,class CXRect,unsigned long,unsigned long)const ,CUITexturePiece__Draw1); +#endif +#ifdef CUITextureInfo__Tile_x +FUNCTION_AT_ADDRESS(int CUITextureInfo::Tile(class CXRect,unsigned long,unsigned long)const ,CUITextureInfo__Tile); +#endif +#ifdef CUITextureInfo__Tile1_x +FUNCTION_AT_ADDRESS(int CUITextureInfo::Tile(class CXRect,unsigned long *,unsigned long *)const ,CUITextureInfo__Tile1); +#endif +#ifdef CUITextureInfo__Preload_x +FUNCTION_AT_ADDRESS(int CUITextureInfo::Preload(void),CUITextureInfo__Preload); +#endif +#ifdef CXMLDataPtr__SetNewPtr_x +FUNCTION_AT_ADDRESS(void CXMLDataPtr::SetNewPtr(class CXMLData *),CXMLDataPtr__SetNewPtr); +#endif +#ifdef CXMLEnumInfo__GetStreamSize_x +FUNCTION_AT_ADDRESS(int CXMLEnumInfo::GetStreamSize(void),CXMLEnumInfo__GetStreamSize); +#endif +#ifdef CXMLEnumInfo__ReadFromStream_x +FUNCTION_AT_ADDRESS(void CXMLEnumInfo::ReadFromStream(class CMemoryStream &),CXMLEnumInfo__ReadFromStream); +#endif +#ifdef CMemoryStream__GetString_x +FUNCTION_AT_ADDRESS(void CMemoryStream::GetString(class CXStr &),CMemoryStream__GetString); +#endif +#ifdef CXMLEnumInfo__WriteToStream_x +FUNCTION_AT_ADDRESS(void CXMLEnumInfo::WriteToStream(class CMemoryStream &),CXMLEnumInfo__WriteToStream); +#endif +#ifdef CXMLDataClass__GetNumLeaf_x +FUNCTION_AT_ADDRESS(int CXMLDataClass::GetNumLeaf(void),CXMLDataClass__GetNumLeaf); +#endif +#ifdef CXMLDataClass__GetStreamSize_x +FUNCTION_AT_ADDRESS(int CXMLDataClass::GetStreamSize(void),CXMLDataClass__GetStreamSize); +#endif +#ifdef CXMLDataClass__ReadFromStream_x +FUNCTION_AT_ADDRESS(void CXMLDataClass::ReadFromStream(class CMemoryStream &,class CXMLDataManager &),CXMLDataClass__ReadFromStream); +#endif +#ifdef CXMLDataClass__WriteToStream_x +FUNCTION_AT_ADDRESS(void CXMLDataClass::WriteToStream(class CMemoryStream &),CXMLDataClass__WriteToStream); +#endif +#ifdef CXMLDataManager__CXMLDataManager_x +FUNCTION_AT_ADDRESS( CXMLDataManager::CXMLDataManager(void),CXMLDataManager__CXMLDataManager); +#endif +#ifdef CXMLDataManager__GetXMLData_x +FUNCTION_AT_ADDRESS(class CXMLData * CXMLDataManager::GetXMLData(int,int),CXMLDataManager__GetXMLData); +#endif +#ifdef CXMLDataManager__GetXMLData1_x +FUNCTION_AT_ADDRESS(class CXMLData * CXMLDataManager::GetXMLData(class CXStr,class CXStr),CXMLDataManager__GetXMLData1); +#endif +#ifdef CXMLDataManager__GetNumClass_x +FUNCTION_AT_ADDRESS(int CXMLDataManager::GetNumClass(void),CXMLDataManager__GetNumClass); +#endif +#ifdef CXMLDataManager__GetNumItem_x +FUNCTION_AT_ADDRESS(int CXMLDataManager::GetNumItem(int),CXMLDataManager__GetNumItem); +#endif +#ifdef CXMLDataManager__GetClassIdx_x +FUNCTION_AT_ADDRESS(int CXMLDataManager::GetClassIdx(class CXStr),CXMLDataManager__GetClassIdx); +#endif +#ifdef CXMLDataManager__GetItemIdx_x +FUNCTION_AT_ADDRESS(int CXMLDataManager::GetItemIdx(int,class CXStr),CXMLDataManager__GetItemIdx); +#endif +#ifdef CXMLDataPtr__Free_x +FUNCTION_AT_ADDRESS(void CXMLDataPtr::Free(void),CXMLDataPtr__Free); +#endif +#ifdef CXMLDataManager__AddToSuperType_x +//FUNCTION_AT_ADDRESS(void CXMLDataManager::AddToSuperType(class CXStr,class CXMLDataPtr),CXMLDataManager__AddToSuperType); +#endif +#ifdef CXMLDataPtr__operator_equal_x +FUNCTION_AT_ADDRESS(class CXMLDataPtr & CXMLDataPtr::operator=(class CXMLDataPtr const &),CXMLDataPtr__operator_equal); +#endif +#ifdef CXMLDataManager__IsDerivedFrom_x +FUNCTION_AT_ADDRESS(bool CXMLDataManager::IsDerivedFrom(int,int),CXMLDataManager__IsDerivedFrom); +#endif +#ifdef CXMLDataManager__SetEnumHash_x +FUNCTION_AT_ADDRESS(void CXMLDataManager::SetEnumHash(void),CXMLDataManager__SetEnumHash); +#endif +#ifdef CXMLDataManager__ReadFromXMLSOM_x +FUNCTION_AT_ADDRESS(bool CXMLDataManager::ReadFromXMLSOM(class CXMLSOMDocument &),CXMLDataManager__ReadFromXMLSOM); +#endif +#ifdef CXMLDataPtr__CXMLDataPtr_x +FUNCTION_AT_ADDRESS( CXMLDataPtr::CXMLDataPtr(void),CXMLDataPtr__CXMLDataPtr); +#endif +#ifdef CXMLDataClass__CXMLDataClass_x +FUNCTION_AT_ADDRESS( CXMLDataClass::CXMLDataClass(void),CXMLDataClass__CXMLDataClass); +#endif +#ifdef CXMLEnumInfo__CXMLEnumInfo_x +FUNCTION_AT_ADDRESS( CXMLEnumInfo::CXMLEnumInfo(void),CXMLEnumInfo__CXMLEnumInfo); +#endif +#ifdef CStmlReport__CreateReport_x +FUNCTION_AT_ADDRESS(class CStmlReport * __cdecl CStmlReport::CreateReport(class CXStr),CStmlReport__CreateReport); +#endif +#ifdef CXFileXML__Load_x +FUNCTION_AT_ADDRESS(bool CXFileXML::Load(char *),CXFileXML__Load); +#endif +#ifdef CParseTokXML__GetEntityRef_x +FUNCTION_AT_ADDRESS(bool CParseTokXML::GetEntityRef(char &),CParseTokXML__GetEntityRef); +#endif +#ifdef CParseTokXML__NextToken_x +//FUNCTION_AT_ADDRESS(enum ETokTypeXML CParseTokXML::NextToken(void),CParseTokXML__NextToken); +#endif +#ifdef CParseTokensXML__SetError_x +FUNCTION_AT_ADDRESS(void __cdecl CParseTokensXML::SetError(char const *,...),CParseTokensXML__SetError); +#endif +#ifdef CParseTokensXML__GetCurFile_x +FUNCTION_AT_ADDRESS(class CXStr CParseTokensXML::GetCurFile(void),CParseTokensXML__GetCurFile); +#endif +#ifdef CParseTokensXML__Accept_x +//FUNCTION_AT_ADDRESS(bool CParseTokensXML::Accept(enum ETokTypeXML),CParseTokensXML__Accept); +#endif +#ifdef CXMLSOMParser__ParseProcess_x +FUNCTION_AT_ADDRESS(bool CXMLSOMParser::ParseProcess(void),CXMLSOMParser__ParseProcess); +#endif +#ifdef CXMLSOMParser__ParseNameSpaceToken_x +FUNCTION_AT_ADDRESS(bool CXMLSOMParser::ParseNameSpaceToken(class CXStr &),CXMLSOMParser__ParseNameSpaceToken); +#endif +#ifdef CXMLSOMParser__ParseStartTag_x +FUNCTION_AT_ADDRESS(bool CXMLSOMParser::ParseStartTag(bool &),CXMLSOMParser__ParseStartTag); +#endif +#ifdef CXMLSOMParser__ParseEndTag_x +FUNCTION_AT_ADDRESS(bool CXMLSOMParser::ParseEndTag(class CXStr),CXMLSOMParser__ParseEndTag); +#endif +#ifdef CXMLSOMParser__ParseNodeList_x +FUNCTION_AT_ADDRESS(bool CXMLSOMParser::ParseNodeList(void),CXMLSOMParser__ParseNodeList); +#endif +#ifdef CXMLSOMParser__ParseNode_x +FUNCTION_AT_ADDRESS(bool CXMLSOMParser::ParseNode(void),CXMLSOMParser__ParseNode); +#endif +#ifdef CXMLSOMParser__ParseDocument_x +FUNCTION_AT_ADDRESS(bool CXMLSOMParser::ParseDocument(void),CXMLSOMParser__ParseDocument); +#endif +#ifdef CParseTokensXML__StartFileBased_x +FUNCTION_AT_ADDRESS(bool CParseTokensXML::StartFileBased(class CXStr),CParseTokensXML__StartFileBased); +#endif +#ifdef CXFileXML__dCXFileXML_x +FUNCTION_AT_ADDRESS( CXFileXML::~CXFileXML(void),CXFileXML__dCXFileXML); +#endif +#ifdef CTokenXML__dCTokenXML_x +FUNCTION_AT_ADDRESS( CTokenXML::~CTokenXML(void),CTokenXML__dCTokenXML); +#endif +#ifdef CXMLSOMParser__ParseFile_x +FUNCTION_AT_ADDRESS(bool CXMLSOMParser::ParseFile(class CXStr),CXMLSOMParser__ParseFile); +#endif +#ifdef CParseTokensXML__dCParseTokensXML_x +FUNCTION_AT_ADDRESS( CParseTokensXML::~CParseTokensXML(void),CParseTokensXML__dCParseTokensXML); +#endif +#ifdef CXMLSOMParser__dCXMLSOMParser_x +FUNCTION_AT_ADDRESS( CXMLSOMParser::~CXMLSOMParser(void),CXMLSOMParser__dCXMLSOMParser); +#endif +#ifdef CParseTokXML__dCParseTokXML_x +FUNCTION_AT_ADDRESS( CParseTokXML::~CParseTokXML(void),CParseTokXML__dCParseTokXML); +#endif +#ifdef CClickStickInfo__CClickStickInfo_x +FUNCTION_AT_ADDRESS( CClickStickInfo::CClickStickInfo(void),CClickStickInfo__CClickStickInfo); +#endif +#ifdef CDIMap__CDIMap_x +FUNCTION_AT_ADDRESS( CDIMap::CDIMap(void),CDIMap__CDIMap); +#endif +#ifdef CXStr__CheckNoLock_x +FUNCTION_AT_ADDRESS(void CXStr::CheckNoLock(void),CXStr__CheckNoLock); +#endif +#ifdef CDIMap__dCDIMap_x +FUNCTION_AT_ADDRESS( CDIMap::~CDIMap(void),CDIMap__dCDIMap); +#endif +#ifdef CIMECandidateList__dCIMECandidateList_x +FUNCTION_AT_ADDRESS( CIMECandidateList::~CIMECandidateList(void),CIMECandidateList__dCIMECandidateList); +#endif +#ifdef CDIMap__LoadMappingFromFile_x +FUNCTION_AT_ADDRESS(void CDIMap::LoadMappingFromFile(char *),CDIMap__LoadMappingFromFile); +#endif +#ifdef CHashCXStrInt32__CHashCXStrInt32_x +FUNCTION_AT_ADDRESS( CHashCXStrInt32::CHashCXStrInt32(void),CHashCXStrInt32__CHashCXStrInt32); +#endif +#ifdef CHashCXStrInt32__dCHashCXStrInt32_x +FUNCTION_AT_ADDRESS( CHashCXStrInt32::~CHashCXStrInt32(void),CHashCXStrInt32__dCHashCXStrInt32); +#endif +#ifdef CHashCXStrInt32__KeyToBin_x +FUNCTION_AT_ADDRESS(int CHashCXStrInt32::KeyToBin(class CXStr const &)const ,CHashCXStrInt32__KeyToBin); +#endif +#ifdef CHashCXStrInt32__LookUp_x +FUNCTION_AT_ADDRESS(bool CHashCXStrInt32::LookUp(class CXStr const &,int &)const ,CHashCXStrInt32__LookUp); +#endif +#ifdef CHashCXStrInt32__Insert_x +FUNCTION_AT_ADDRESS(bool CHashCXStrInt32::Insert(class CXStr const &,int),CHashCXStrInt32__Insert); +#endif +#ifdef CHashCXStrInt32__Reset_x +FUNCTION_AT_ADDRESS(void CHashCXStrInt32::Reset(void),CHashCXStrInt32__Reset); +#endif +#ifdef CParamPoint__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamPoint & CParamPoint::operator=(class CParamPoint const &),CParamPoint__operator_equal); +#endif +#ifdef CParamSize__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamSize & CParamSize::operator=(class CParamSize const &),CParamSize__operator_equal); +#endif +#ifdef CParamGaugeDrawTemplate__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamGaugeDrawTemplate & CParamGaugeDrawTemplate::operator=(class CParamGaugeDrawTemplate const &),CParamGaugeDrawTemplate__operator_equal); +#endif +#ifdef CParamSpellGemDrawTemplate__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamSpellGemDrawTemplate & CParamSpellGemDrawTemplate::operator=(class CParamSpellGemDrawTemplate const &),CParamSpellGemDrawTemplate__operator_equal); +#endif +#ifdef CParamScreenPiece__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamScreenPiece & CParamScreenPiece::operator=(class CParamScreenPiece const &),CParamScreenPiece__operator_equal); +#endif +#ifdef CParamControl__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamControl & CParamControl::operator=(class CParamControl const &),CParamControl__operator_equal); +#endif +#ifdef CParamSliderDrawTemplate__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamSliderDrawTemplate & CParamSliderDrawTemplate::operator=(class CParamSliderDrawTemplate const &),CParamSliderDrawTemplate__operator_equal); +#endif +#ifdef CParamStaticText__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamStaticText & CParamStaticText::operator=(class CParamStaticText const &),CParamStaticText__operator_equal); +#endif +#ifdef CParamStaticAnimation__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamStaticAnimation & CParamStaticAnimation::operator=(class CParamStaticAnimation const &),CParamStaticAnimation__operator_equal); +#endif +#ifdef CParamStaticFrame__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamStaticFrame & CParamStaticFrame::operator=(class CParamStaticFrame const &),CParamStaticFrame__operator_equal); +#endif +#ifdef CParamStaticHeader__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamStaticHeader & CParamStaticHeader::operator=(class CParamStaticHeader const &),CParamStaticHeader__operator_equal); +#endif +#ifdef CParamListboxColumn__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamListboxColumn & CParamListboxColumn::operator=(class CParamListboxColumn const &),CParamListboxColumn__operator_equal); +#endif +#ifdef CParamListbox__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamListbox & CParamListbox::operator=(class CParamListbox const &),CParamListbox__operator_equal); +#endif +#ifdef CParamButton__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamButton & CParamButton::operator=(class CParamButton const &),CParamButton__operator_equal); +#endif +#ifdef CParamGauge__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamGauge & CParamGauge::operator=(class CParamGauge const &),CParamGauge__operator_equal); +#endif +#ifdef CParamSpellGem__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamSpellGem & CParamSpellGem::operator=(class CParamSpellGem const &),CParamSpellGem__operator_equal); +#endif +#ifdef CParamInvSlot__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamInvSlot & CParamInvSlot::operator=(class CParamInvSlot const &),CParamInvSlot__operator_equal); +#endif +#ifdef CParamEditbox__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamEditbox & CParamEditbox::operator=(class CParamEditbox const &),CParamEditbox__operator_equal); +#endif +#ifdef CParamSlider__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamSlider & CParamSlider::operator=(class CParamSlider const &),CParamSlider__operator_equal); +#endif +#ifdef CParamLabel__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamLabel & CParamLabel::operator=(class CParamLabel const &),CParamLabel__operator_equal); +#endif +#ifdef CParamCombobox__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamCombobox & CParamCombobox::operator=(class CParamCombobox const &),CParamCombobox__operator_equal); +#endif +#ifdef CParamPage__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamPage & CParamPage::operator=(class CParamPage const &),CParamPage__operator_equal); +#endif +#ifdef CParamTabBox__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamTabBox & CParamTabBox::operator=(class CParamTabBox const &),CParamTabBox__operator_equal); +#endif +#ifdef CParamScreen__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamScreen & CParamScreen::operator=(class CParamScreen const &),CParamScreen__operator_equal); +#endif +#ifdef CParamSuiteDefaults__operator_equal_x +FUNCTION_AT_ADDRESS(class CParamSuiteDefaults & CParamSuiteDefaults::operator=(class CParamSuiteDefaults const &),CParamSuiteDefaults__operator_equal); +#endif +#ifdef CParamClass__CParamClass_x +FUNCTION_AT_ADDRESS( CParamClass::CParamClass(void),CParamClass__CParamClass); +#endif +#ifdef CParamRGB__CParamRGB_x +FUNCTION_AT_ADDRESS( CParamRGB::CParamRGB(void),CParamRGB__CParamRGB); +#endif +#ifdef CParamPoint__CParamPoint_x +FUNCTION_AT_ADDRESS( CParamPoint::CParamPoint(void),CParamPoint__CParamPoint); +#endif +#ifdef CParamSize__CParamSize_x +FUNCTION_AT_ADDRESS( CParamSize::CParamSize(void),CParamSize__CParamSize); +#endif +#ifdef CParamTextureInfo__CParamTextureInfo_x +FUNCTION_AT_ADDRESS( CParamTextureInfo::CParamTextureInfo(void),CParamTextureInfo__CParamTextureInfo); +#endif +#ifdef CXMLSOMCursorSaveFast__dCXMLSOMCursorSaveFast_x +FUNCTION_AT_ADDRESS( CXMLSOMCursorSaveFast::~CXMLSOMCursorSaveFast(void),CXMLSOMCursorSaveFast__dCXMLSOMCursorSaveFast); +#endif +#ifdef CParamFrame__CParamFrame_x +FUNCTION_AT_ADDRESS( CParamFrame::CParamFrame(void),CParamFrame__CParamFrame); +#endif +#ifdef CParamUi2DAnimation__CParamUi2DAnimation_x +FUNCTION_AT_ADDRESS( CParamUi2DAnimation::CParamUi2DAnimation(void),CParamUi2DAnimation__CParamUi2DAnimation); +#endif +#ifdef CParamButtonDrawTemplate__CParamButtonDrawTemplate_x +FUNCTION_AT_ADDRESS( CParamButtonDrawTemplate::CParamButtonDrawTemplate(void),CParamButtonDrawTemplate__CParamButtonDrawTemplate); +#endif +#ifdef CParamGaugeDrawTemplate__CParamGaugeDrawTemplate_x +FUNCTION_AT_ADDRESS( CParamGaugeDrawTemplate::CParamGaugeDrawTemplate(void),CParamGaugeDrawTemplate__CParamGaugeDrawTemplate); +#endif +#ifdef CParamSpellGemDrawTemplate__CParamSpellGemDrawTemplate_x +FUNCTION_AT_ADDRESS( CParamSpellGemDrawTemplate::CParamSpellGemDrawTemplate(void),CParamSpellGemDrawTemplate__CParamSpellGemDrawTemplate); +#endif +#ifdef CParamFrameTemplate__CParamFrameTemplate_x +FUNCTION_AT_ADDRESS( CParamFrameTemplate::CParamFrameTemplate(void),CParamFrameTemplate__CParamFrameTemplate); +#endif +#ifdef CParamScrollbarDrawTemplate__CParamScrollbarDrawTemplate_x +FUNCTION_AT_ADDRESS( CParamScrollbarDrawTemplate::CParamScrollbarDrawTemplate(void),CParamScrollbarDrawTemplate__CParamScrollbarDrawTemplate); +#endif +#ifdef CParamWindowDrawTemplate__CParamWindowDrawTemplate_x +FUNCTION_AT_ADDRESS( CParamWindowDrawTemplate::CParamWindowDrawTemplate(void),CParamWindowDrawTemplate__CParamWindowDrawTemplate); +#endif +#ifdef CParamSliderDrawTemplate__CParamSliderDrawTemplate_x +FUNCTION_AT_ADDRESS( CParamSliderDrawTemplate::CParamSliderDrawTemplate(void),CParamSliderDrawTemplate__CParamSliderDrawTemplate); +#endif +#ifdef CParamScreenPiece__CParamScreenPiece_x +FUNCTION_AT_ADDRESS( CParamScreenPiece::CParamScreenPiece(void),CParamScreenPiece__CParamScreenPiece); +#endif +#ifdef CParamStaticScreenPiece__CParamStaticScreenPiece_x +FUNCTION_AT_ADDRESS( CParamStaticScreenPiece::CParamStaticScreenPiece(void),CParamStaticScreenPiece__CParamStaticScreenPiece); +#endif +#ifdef CParamStaticAnimation__CParamStaticAnimation_x +FUNCTION_AT_ADDRESS( CParamStaticAnimation::CParamStaticAnimation(void),CParamStaticAnimation__CParamStaticAnimation); +#endif +#ifdef CParamStaticText__CParamStaticText_x +FUNCTION_AT_ADDRESS( CParamStaticText::CParamStaticText(void),CParamStaticText__CParamStaticText); +#endif +#ifdef CParamStaticFrame__CParamStaticFrame_x +FUNCTION_AT_ADDRESS( CParamStaticFrame::CParamStaticFrame(void),CParamStaticFrame__CParamStaticFrame); +#endif +#ifdef CParamStaticHeader__CParamStaticHeader_x +FUNCTION_AT_ADDRESS( CParamStaticHeader::CParamStaticHeader(void),CParamStaticHeader__CParamStaticHeader); +#endif +#ifdef CParamControl__CParamControl_x +FUNCTION_AT_ADDRESS( CParamControl::CParamControl(void),CParamControl__CParamControl); +#endif +#ifdef CParamListboxColumn__CParamListboxColumn_x +FUNCTION_AT_ADDRESS( CParamListboxColumn::CParamListboxColumn(void),CParamListboxColumn__CParamListboxColumn); +#endif +#ifdef CParamListbox__CParamListbox_x +FUNCTION_AT_ADDRESS( CParamListbox::CParamListbox(void),CParamListbox__CParamListbox); +#endif +#ifdef CParamButton__CParamButton_x +FUNCTION_AT_ADDRESS( CParamButton::CParamButton(void),CParamButton__CParamButton); +#endif +#ifdef CParamGauge__CParamGauge_x +FUNCTION_AT_ADDRESS( CParamGauge::CParamGauge(void),CParamGauge__CParamGauge); +#endif +#ifdef CParamSpellGem__CParamSpellGem_x +FUNCTION_AT_ADDRESS( CParamSpellGem::CParamSpellGem(void),CParamSpellGem__CParamSpellGem); +#endif +#ifdef CParamInvSlot__CParamInvSlot_x +FUNCTION_AT_ADDRESS( CParamInvSlot::CParamInvSlot(void),CParamInvSlot__CParamInvSlot); +#endif +#ifdef CParamEditbox__CParamEditbox_x +FUNCTION_AT_ADDRESS( CParamEditbox::CParamEditbox(void),CParamEditbox__CParamEditbox); +#endif +#ifdef CParamSlider__CParamSlider_x +FUNCTION_AT_ADDRESS( CParamSlider::CParamSlider(void),CParamSlider__CParamSlider); +#endif +#ifdef CParamLabel__CParamLabel_x +FUNCTION_AT_ADDRESS( CParamLabel::CParamLabel(void),CParamLabel__CParamLabel); +#endif +#ifdef CParamSTMLbox__CParamSTMLbox_x +FUNCTION_AT_ADDRESS( CParamSTMLbox::CParamSTMLbox(void),CParamSTMLbox__CParamSTMLbox); +#endif +#ifdef CParamCombobox__CParamCombobox_x +FUNCTION_AT_ADDRESS( CParamCombobox::CParamCombobox(void),CParamCombobox__CParamCombobox); +#endif +#ifdef CParamPage__CParamPage_x +FUNCTION_AT_ADDRESS( CParamPage::CParamPage(void),CParamPage__CParamPage); +#endif +#ifdef CParamTabBox__CParamTabBox_x +FUNCTION_AT_ADDRESS( CParamTabBox::CParamTabBox(void),CParamTabBox__CParamTabBox); +#endif +#ifdef CParamScreen__CParamScreen_x +FUNCTION_AT_ADDRESS( CParamScreen::CParamScreen(void),CParamScreen__CParamScreen); +#endif +#ifdef CParamSuiteDefaults__CParamSuiteDefaults_x +FUNCTION_AT_ADDRESS( CParamSuiteDefaults::CParamSuiteDefaults(void),CParamSuiteDefaults__CParamSuiteDefaults); +#endif +#ifdef CXMLData__CXMLData_x +FUNCTION_AT_ADDRESS( CXMLData::CXMLData(void),CXMLData__CXMLData); +#endif +#ifdef CPageWnd__CPageWnd_x +FUNCTION_AT_ADDRESS( CPageWnd::CPageWnd(class CXWnd *,unsigned __int32,class CXRect,class CXStr,class CPageTemplate *),CPageWnd__CPageWnd); +#endif +#ifdef CGaugeWnd__CGaugeWnd_x +FUNCTION_AT_ADDRESS( CGaugeWnd::CGaugeWnd(class CXWnd *,unsigned __int32,class CXRect,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,int,unsigned long,unsigned long,bool,int,int,int,int),CGaugeWnd__CGaugeWnd); +#endif +#ifdef CGaugeWnd__CalcFillRect_x +FUNCTION_AT_ADDRESS(class CXRect CGaugeWnd::CalcFillRect(class CXRect *,int)const ,CGaugeWnd__CalcFillRect); +#endif +#ifdef CGaugeWnd__CalcLinesFillRect_x +FUNCTION_AT_ADDRESS(class CXRect CGaugeWnd::CalcLinesFillRect(class CXRect *,int)const ,CGaugeWnd__CalcLinesFillRect); +#endif +#ifdef CGaugeWnd__SpecialToolTip_x +FUNCTION_AT_ADDRESS(void CGaugeWnd::SpecialToolTip(void),CGaugeWnd__SpecialToolTip); +#endif +#ifdef CCheckBoxWnd__CCheckBoxWnd_x +FUNCTION_AT_ADDRESS( CCheckBoxWnd::CCheckBoxWnd(class CXWnd *,unsigned __int32,class CXRect,class CXPoint,class CXSize,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *),CCheckBoxWnd__CCheckBoxWnd); +#endif +#ifdef CCheckBoxWnd__SetRadioLook_x +FUNCTION_AT_ADDRESS(void CCheckBoxWnd::SetRadioLook(void),CCheckBoxWnd__SetRadioLook); +#endif +#ifdef CIMEStatusBar__CIMEStatusBar_x +FUNCTION_AT_ADDRESS( CIMEStatusBar::CIMEStatusBar(class CIMEManager *),CIMEStatusBar__CIMEStatusBar); +#endif +#ifdef CIMEStatusBar__show_x +FUNCTION_AT_ADDRESS(int CIMEStatusBar::show(class CIMEComposition const *),CIMEStatusBar__show); +#endif +#ifdef CIMEStatusBar__update_x +FUNCTION_AT_ADDRESS(int CIMEStatusBar::update(void),CIMEStatusBar__update); +#endif +#ifdef CIMEStatusBar__hide_x +FUNCTION_AT_ADDRESS(int CIMEStatusBar::hide(void),CIMEStatusBar__hide); +#endif +#ifdef CIMEStatusBar__handleChineseSimplifiedStatusChange_x +FUNCTION_AT_ADDRESS(void CIMEStatusBar::handleChineseSimplifiedStatusChange(unsigned long),CIMEStatusBar__handleChineseSimplifiedStatusChange); +#endif +#ifdef CIMEStatusBar__handleChineseTraditionalStatusChange_x +FUNCTION_AT_ADDRESS(void CIMEStatusBar::handleChineseTraditionalStatusChange(unsigned long),CIMEStatusBar__handleChineseTraditionalStatusChange); +#endif +#ifdef CIMEStatusBar__handleJapaneseStatusChange_x +FUNCTION_AT_ADDRESS(void CIMEStatusBar::handleJapaneseStatusChange(unsigned long),CIMEStatusBar__handleJapaneseStatusChange); +#endif +#ifdef CIMEStatusBar__handleKoreanStatusChange_x +FUNCTION_AT_ADDRESS(void CIMEStatusBar::handleKoreanStatusChange(unsigned long),CIMEStatusBar__handleKoreanStatusChange); +#endif +#ifdef CIMEStatusBar__repositionStatusWindow_x +FUNCTION_AT_ADDRESS(int CIMEStatusBar::repositionStatusWindow(void),CIMEStatusBar__repositionStatusWindow); +#endif +#ifdef CIMECandidateList__CIMECandidateList_x +FUNCTION_AT_ADDRESS( CIMECandidateList::CIMECandidateList(class CIMEManager *),CIMECandidateList__CIMECandidateList); +#endif +#ifdef CIMECandidateList__show_x +FUNCTION_AT_ADDRESS(int CIMECandidateList::show(class CIMEComposition const *)const ,CIMECandidateList__show); +#endif +#ifdef CIMECandidateList__repositionImeCandidateList_x +FUNCTION_AT_ADDRESS(int CIMECandidateList::repositionImeCandidateList(int,int)const ,CIMECandidateList__repositionImeCandidateList); +#endif +#ifdef CIMEComposition__CIMEComposition_x +FUNCTION_AT_ADDRESS( CIMEComposition::CIMEComposition(class CIMEManager *),CIMEComposition__CIMEComposition); +#endif +#ifdef CIMEComposition__dCIMEComposition_x +FUNCTION_AT_ADDRESS( CIMEComposition::~CIMEComposition(void),CIMEComposition__dCIMEComposition); +#endif +#ifdef CIMEComposition__addInputChar_x +FUNCTION_AT_ADDRESS(int CIMEComposition::addInputChar(unsigned short),CIMEComposition__addInputChar); +#endif +#ifdef CIMEComposition__addInputString_x +FUNCTION_AT_ADDRESS(int CIMEComposition::addInputString(unsigned short *,int),CIMEComposition__addInputString); +#endif +#ifdef CIMEComposition__addInputString1_x +FUNCTION_AT_ADDRESS(int CIMEComposition::addInputString(class CXStr const &,int),CIMEComposition__addInputString1); +#endif +#ifdef CIMEComposition__addStringFromIme_x +FUNCTION_AT_ADDRESS(int CIMEComposition::addStringFromIme(long),CIMEComposition__addStringFromIme); +#endif +#ifdef CIMEComposition__directToEditWnd_x +FUNCTION_AT_ADDRESS(void CIMEComposition::directToEditWnd(class CEditWnd *),CIMEComposition__directToEditWnd); +#endif +#ifdef CIMEComposition__getCursorPoint_x +FUNCTION_AT_ADDRESS(class CXPoint CIMEComposition::getCursorPoint(void)const ,CIMEComposition__getCursorPoint); +#endif +#ifdef CIMEComposition__getCompositionArea_x +FUNCTION_AT_ADDRESS(class CXRect CIMEComposition::getCompositionArea(void)const ,CIMEComposition__getCompositionArea); +#endif +#ifdef CIMEComposition__repositionImeCompositionWindow_x +FUNCTION_AT_ADDRESS(int CIMEComposition::repositionImeCompositionWindow(int,int)const ,CIMEComposition__repositionImeCompositionWindow); +#endif +#ifdef CIMEComposition__allocateImeCompositionString_x +FUNCTION_AT_ADDRESS(unsigned short * CIMEComposition::allocateImeCompositionString(long)const ,CIMEComposition__allocateImeCompositionString); +#endif +#ifdef CIMEComposition__allocateImeCompositionAttributes_x +FUNCTION_AT_ADDRESS(struct CompAttr * CIMEComposition::allocateImeCompositionAttributes(void)const ,CIMEComposition__allocateImeCompositionAttributes); +#endif +#ifdef CIMEComposition__getCompositionInsertIndex_x +FUNCTION_AT_ADDRESS(int CIMEComposition::getCompositionInsertIndex(void)const ,CIMEComposition__getCompositionInsertIndex); +#endif +#ifdef CIMEComposition__handleImeComposing_x +FUNCTION_AT_ADDRESS(int CIMEComposition::handleImeComposing(void),CIMEComposition__handleImeComposing); +#endif +#ifdef CIMEComposition__applyJapaneseComposingRules_x +FUNCTION_AT_ADDRESS(int CIMEComposition::applyJapaneseComposingRules(class CXStr *),CIMEComposition__applyJapaneseComposingRules); +#endif +#ifdef CIMEComposition__applyChineseComposingRules_x +FUNCTION_AT_ADDRESS(int CIMEComposition::applyChineseComposingRules(class CXStr *),CIMEComposition__applyChineseComposingRules); +#endif +#ifdef CIMEComposition__applyKoreanComposingRules_x +FUNCTION_AT_ADDRESS(int CIMEComposition::applyKoreanComposingRules(class CXStr *),CIMEComposition__applyKoreanComposingRules); +#endif +#ifdef CIMEComposition__addCompositionHighlights_x +FUNCTION_AT_ADDRESS(int CIMEComposition::addCompositionHighlights(void),CIMEComposition__addCompositionHighlights); +#endif +#ifdef CIMEComposition__handleImeResult_x +FUNCTION_AT_ADDRESS(int CIMEComposition::handleImeResult(void),CIMEComposition__handleImeResult); +#endif +#ifdef CIMEComposition__backupCurrentText_x +FUNCTION_AT_ADDRESS(void CIMEComposition::backupCurrentText(void),CIMEComposition__backupCurrentText); +#endif +#ifdef CIMEComposition__revertToBackupText_x +FUNCTION_AT_ADDRESS(void CIMEComposition::revertToBackupText(void),CIMEComposition__revertToBackupText); +#endif +#ifdef CMemoryStream__GetStringSize_x +FUNCTION_AT_ADDRESS(int __cdecl CMemoryStream::GetStringSize(class CXStr &),CMemoryStream__GetStringSize); +#endif +#ifdef CMemoryStream__PutString_x +FUNCTION_AT_ADDRESS(void CMemoryStream::PutString(class CXStr &),CMemoryStream__PutString); +#endif +#ifdef CMemoryStream__GetString1_x +FUNCTION_AT_ADDRESS(class CXStr CMemoryStream::GetString(void),CMemoryStream__GetString1); +#endif +#ifdef CXMLSOMDocument__GetValueObjectId_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocument::GetValueObjectId(class CXStr,class CXStr,unsigned __int32 &),CXMLSOMDocument__GetValueObjectId); +#endif +#ifdef CXMLSOMDocument__SetValueObjectId_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocument::SetValueObjectId(class CXStr,class CXStr,unsigned __int32),CXMLSOMDocument__SetValueObjectId); +#endif +#ifdef CXMLSOMDocument__FieldParseItemOfClass_x +FUNCTION_AT_ADDRESS(bool CXMLSOMDocument::FieldParseItemOfClass(class CXStr,class CXStr,unsigned __int32 &),CXMLSOMDocument__FieldParseItemOfClass); +#endif +#ifdef EQOldPlayerAnimation__mAnimationPrefix_x +FUNCTION_AT_ADDRESS(char (* EQOldPlayerAnimation::mAnimationPrefix)[20],EQOldPlayerAnimation__mAnimationPrefix); +#endif +#ifdef CTextOverlay__DisplayText_x +FUNCTION_AT_ADDRESS(void CTextOverlay::DisplayText(char *,int,int,int,int,int,int),CTextOverlay__DisplayText); +#endif +#ifdef CDBStr__GetString_x +// GetString(index, subindex, &success) +FUNCTION_AT_ADDRESS(char *CDBStr::GetString(int, int, int *), CDBStr__GetString); +#endif +#ifdef EQMisc__GetActiveFavorCost_x +FUNCTION_AT_ADDRESS(int EQMisc::GetActiveFavorCost(void),EQMisc__GetActiveFavorCost); +#endif +#ifdef CSkillMgr__GetStrNumber_x +FUNCTION_AT_ADDRESS(unsigned long CSkillMgr::GetStrNumber(int),CSkillMgr__GetStrNumber); +#endif +#ifdef CSkillMgr__GetSkillCap_x +FUNCTION_AT_ADDRESS(unsigned long CSkillMgr::GetSkillCap(class EQ_Character *,int,int,int,bool,bool,bool),CSkillMgr__GetSkillCap) +#endif +#ifdef CSkillMgr__SkillAvailableAtLevel_x +FUNCTION_AT_ADDRESS(unsigned long CSkillMgr::SkillAvailableAtLevel(int,int),CSkillMgr__SkillAvailableAtLevel); +#endif +#ifdef CSkillMgr__IsActivatableSkill_x +FUNCTION_AT_ADDRESS(bool CSkillMgr::IsActivatableSkill(int),CSkillMgr__IsActivatableSkill); +#endif +#ifdef CSkillMgr__GetBaseDamage_x +FUNCTION_AT_ADDRESS(unsigned long CSkillMgr::GetBaseDamage(int),CSkillMgr__GetBaseDamage); +#endif +#ifdef CSkillMgr__GetReuseTime_x +FUNCTION_AT_ADDRESS(unsigned long CSkillMgr::GetReuseTime(int),CSkillMgr__GetReuseTime); +#endif +#ifdef CSkillMgr__IsAvailable_x +FUNCTION_AT_ADDRESS(bool CSkillMgr::IsAvailable(int),CSkillMgr__IsAvailable); +#endif +#ifdef CChatService__GetNumberOfFriends_x +FUNCTION_AT_ADDRESS(int CChatService::GetNumberOfFriends(void),CChatService__GetNumberOfFriends); +#endif +#ifdef CChatService__GetFriendName_x +FUNCTION_AT_ADDRESS(char *CChatService::GetFriendName(int),CChatService__GetFriendName); +#endif +#ifdef PlayerPointManager__GetAltCurrency_x +FUNCTION_AT_ADDRESS(unsigned long PlayerPointManager::GetAltCurrency(unsigned long,unsigned long),PlayerPointManager__GetAltCurrency); +#endif +#ifdef CharacterZoneClient__HasSkill_x +FUNCTION_AT_ADDRESS(bool CharacterZoneClient::HasSkill(int), CharacterZoneClient__HasSkill); +#endif + + +#ifdef PcZoneClient__GetPcSkillLimit_x +FUNCTION_AT_ADDRESS(int PcZoneClient::GetPcSkillLimit(int), PcZoneClient__GetPcSkillLimit); +#endif + +#ifdef CXWnd__SetFont_x +FUNCTION_AT_ADDRESS(int CXWnd::SetFont(void*), CXWnd__SetFont); +#endif diff --git a/client_files/native_autoloot/eq-core-dll/src/EQClasses.h b/client_files/native_autoloot/eq-core-dll/src/EQClasses.h new file mode 100644 index 0000000000..9a20cb63e5 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/EQClasses.h @@ -0,0 +1,6973 @@ +#pragma once +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +namespace EQClasses +{ +// Other +class CXSize +{ + DWORD A,B,C,D,E,F; +}; + +// Enumerations... +typedef DWORD EQZoneIndex; +typedef DWORD EQLocalizeLanguage; +typedef DWORD EScrollCode; + +// Forward class declarations +class _EverQuestinfo; +class _PackFileData; +class _PackFileDataRawFile; +class _partyGroup; +class AltAdvManager; +class bad_word_class; +class CAAWnd; +class CActionsWnd; +class CAlarmWnd; +class CBankWnd; +class CBazaarSearchWnd; +class CBazaarWnd; +class CBodyTintWnd; +class CBookWnd; +class CBreathWnd; +class CBuffWindow; +class CBugReportWnd; +class CButtonDrawTemplate; +class CButtonTemplate; +class CButtonWnd; +class CCastingWnd; +class CCastSpellWnd; +class CCharacterCreation; +class CCharacterSelect; +class CChatManager; +class CChatWindow; +class CCheckBoxWnd; +class CClickStickInfo; +class CColorPickerWnd; +class CComboboxTemplate; +class CComboWnd; +class CCompassWnd; +class CConfirmationDialog; +class CContainerMgr; +class CContainerWnd; +class CContextMenu; +class CContextMenuManager; +class CControlTemplate; +class CCursorAttachment; +class CDIMap; +class CDisplay; +class CEditBaseWnd; +class CEditboxTemplate; +class CEditLabelWnd; +class CEditWnd; +class CEQSuiteTextureLoader; +class CEverQuest; +class CExploreModeWnd; +class CFacePick; +class CFeedbackWnd; +class CFileSelectionWnd; +class CFriendsWnd; +class CGaugeDrawTemplate; +class CGaugeTemplate; +class CGaugeWnd; +class CGemsGameWnd; +class CGiveWnd; +class CGroupSearchFiltersWnd; +class CGroupSearchWnd; +class CGroupWnd; +class CGuild; +class CGuildMgmtWnd; +class ChannelServerApi; +class ChannelServerHandler; +class CHashCXStrInt32; +class CHelpWnd; +class CHotButtonWnd; +class CIMECandidateList; +class CIMEComposition; +class CIMEManager; +class CIMEStatusBar; +class CInspectWnd; +class CInventoryWnd; +class CInvSlot; +class CInvSlotMgr; +class CInvSlotTemplate; +class CInvSlotWnd; +class CItemDisplayWnd; +class CJournalCatWnd; +class CJournalNPCWnd; +class CJournalTextWnd; +class CKeyCXStrValueInt32; +class CLabel; +class CLabelTemplate; +class CListboxColumnTemplate; +class CListboxTemplate; +class CListWnd; +class CLoadskinWnd; +class CLootWnd; +class CMapToolbarWnd; +class CMapViewWnd; +class CMemoryStream; +class CMerchantWnd; +class CMusicPlayerWnd; +class CMutexLock; +class CMutexLockCounted; +class CMutexSync; +class CMutexSyncCounted; +class CNoteWnd; +class ConversationJournal; +class COptionsWnd; +class CPageTemplate; +class CPageWnd; +class CParam; +class CParamButton; +class CParamButtonDrawTemplate; +class CParamClass; +class CParamCombobox; +class CParamControl; +class CParamEditbox; +class CParamFrame; +class CParamFrameTemplate; +class CParamGauge; +class CParamGaugeDrawTemplate; +class CParamInvSlot; +class CParamLabel; +class CParamListbox; +class CParamListboxColumn; +class CParamPage; +class CParamPoint; +class CParamRGB; +class CParamScreen; +class CParamScreenPiece; +class CParamScrollbarDrawTemplate; +class CParamSize; +class CParamSlider; +class CParamSliderDrawTemplate; +class CParamSpellGem; +class CParamSpellGemDrawTemplate; +class CParamStaticAnimation; +class CParamStaticFrame; +class CParamStaticHeader; +class CParamStaticScreenPiece; +class CParamStaticText; +class CParamSTMLbox; +class CParamSuiteDefaults; +class CParamTabBox; +class CParamTextureInfo; +class CParamUi2DAnimation; +class CParamWindowDrawTemplate; +class CParseTokensXML; +class CParseTokXML; +class CPetInfoWnd; +class CPetitionQWnd; +class CPlayerNotesWnd; +class CPlayerWnd; +class CPotionBeltWnd; +class CQuantityWnd; +class CRadioGroup; +class CRaid; +class CRaidOptionsWnd; +class CRaidWnd; +class CRC32Generator; +class CResolutionHandler; +class CScreenPieceTemplate; +class CScreenTemplate; +class CScrollbarTemplate; +class CSelectorWnd; +class CSidlManager; +class CSidlScreenWnd; +class CSkillsSelectWnd; +class CSkillsWnd; +class CSliderDrawTemplate; +class CSliderTemplate; +class CSliderWnd; +class CSocialEditWnd; +class CSoulmarkWnd; +class CSpellBookWnd; +class CSpellGemDrawTemplate; +class CSpellGemTemplate; +class CSpellGemWnd; +class CStaticAnimationTemplate; +class CStaticFrameTemplate; +class CStaticHeaderTemplate; +class CStaticScreenPieceTemplate; +class CStaticTextTemplate; +class CSTMLboxTemplate; +class CStmlReport; +class CStmlWnd; +class CStoryWnd; +class CTabBoxTemplate; +class CTabWnd; +class CTAFrameDraw; +class CTargetWnd; +class CTextEntryWnd; +class CTextureAnimation; +class CTextureFont; +class CTimeLeftWnd; +class CTipWnd; +class CTokenXML; +class CTrackingWnd; +class CTradeWnd; +class CTrainWnd; +class CUITextureInfo; +class CUITexturePiece; +class CVector3; +class CVideoModesWnd; +class CXFileXML; +class CXMLData; +class CXMLDataClass; +class CXMLDataManager; +class CXMLDataPtr; +class CXMLEnumInfo; +class CXMLParamManager; +class CXMLSOMAttribute; +class CXMLSOMAttributeType; +class CXMLSOMCursor; +class CXMLSOMCursorSave; +class CXMLSOMCursorSaveFast; +class CXMLSOMCursorTraverseChildren; +class CXMLSOMDocument; +class CXMLSOMDocumentBase; +class CXMLSOMElement; +class CXMLSOMElementType; +class CXMLSOMNode; +class CXMLSOMNodePtr; +class CXMLSOMParser; +class CXMLSOMSchema; +class CXMLSOMSimpleType; +class CXPoint; +class CXRect; +class CXStr; +class CXStrSingleton; +class CXWnd; +class CXWndDrawTemplate; +class CXWndManager; +class EmitterManager; +class engineInterface; +class EQ_Affect; +class EQ_AltAbility; +class EQ_Character; +class EQ_CharacterData; +class EQ_Container; +class EQ_Equipment; +class EQ_Item; +class EQ_LoadingS; +class EQ_Note; +class EQ_PC; +class EQ_Skill; +class EQ_Spell; +class EQAnimation; +class EQEffect; +class EqEmitterData; +class EQHSprite; +class EQItemList; +class EQMissile; +class EqMobileEmitter; +class EQMoneyList; +class EQNewPlayerAnimation; +class EQObject; +class EQOldPlayerAnimation; +class EQPlayer; +class EQPMInfo; +class EqSoundManager; +class EQSwitch; +class EqSwitchManager; +class EQUtil; +class EQWorldData; +class EQZoneInfo; +class FilePath; +class flex_unit; +class GrammarRulesClass; +class GuildMember; +class JournalNPC; +class KeyCombo; +class KeypressHandler; +class LogicalPacket; +class MapViewMap; +class MemoryPoolManager; +class MidiInstance; +class monty; +class Mp3Manager; +class MusicManager; +class PacketPacker; +class PacketPackerManager; +class PackFile; +class PackFS; +class PooledLogicalPacket; +class public_key; +class SAmpersandEntry; +class SFormattedText; +class ShareBase; +class SharedString; +class SHistoryElement; +class SimpleLogicalPacket; +class SLinkInfo; +class SListWndCell; +class SListWndCellEditUpdate; +class SListWndColumn; +class SListWndLine; +class SListWndSortInfo; +class SoundAsset; +class SoundControl; +class SoundEmitter; +class SoundInstance; +class SoundManager; +class SoundObject; +class SParseVariables; +class SpellManager; +class STable; +class STableCell; +class STempTable; +class STempTableCell; +class STempTableRow; +class STextLine; +class STextureAnimationFrame; +class StringItem; +class StringTable; +class TextFileReader; +class type_info; +class UdpConnection; +class UdpConnectionHandler; +class UdpIpAddress; +class UdpManager; +class UdpMisc; +class UdpReliableChannel; +class vlong; +class vlong_value; +class Wave3dInstance; +class WaveInstance; +class WrappedLogicalPacket; +class ZlibUtil; +class ZoneNPCLoadTextManager; +class CTextOverlay; +// End forward class declarations + +// Class declarations +class CXStr +{ +public: +EQLIB_OBJECT CXStr::~CXStr(void); +EQLIB_OBJECT CXStr::CXStr(char const *); +EQLIB_OBJECT CXStr::CXStr(char const *,int); +EQLIB_OBJECT CXStr::CXStr(char); +EQLIB_OBJECT CXStr::CXStr(class CXStr const &); +EQLIB_OBJECT CXStr::CXStr(int,int,char); +EQLIB_OBJECT CXStr::CXStr(unsigned short const *); +EQLIB_OBJECT CXStr::CXStr(void); +EQLIB_OBJECT char *CXStr::operator char *(void)const; +EQLIB_OBJECT unsigned short *CXStr::operator unsigned short *(void)const; +EQLIB_OBJECT bool CXStr::Find(char,int &); +EQLIB_OBJECT bool CXStr::Find(class CXStr const &,int &); +EQLIB_OBJECT bool CXStr::Find(unsigned short,int &); +EQLIB_OBJECT bool CXStr::FindLast(char,int &); +EQLIB_OBJECT char CXStr::GetChar(long)const; +EQLIB_OBJECT char CXStr::operator[](int)const; +EQLIB_OBJECT char CXStr::SetChar(long,char); +EQLIB_OBJECT class CXStr & CXStr::operator=(char const *); +EQLIB_OBJECT class CXStr & CXStr::operator=(class CXStr const &); +EQLIB_OBJECT class CXStr CXStr::Copy(long,long)const; +EQLIB_OBJECT class CXStr CXStr::Left(int)const; +EQLIB_OBJECT class CXStr CXStr::Mid(int,int)const; +EQLIB_OBJECT class CXStr CXStr::Right(int)const; +//EQLIB_OBJECT enum EStringEncoding CXStr::GetEncoding(void)const; +EQLIB_OBJECT int __cdecl CXStr::PrintString(char const *,...); +//EQLIB_OBJECT int CXStr::Compare(class CXStr const &,enum CompareCode)const; +//EQLIB_OBJECT int CXStr::CompareN(class CXStr const &,int,enum CompareCode)const; +EQLIB_OBJECT int CXStr::ConvertToInt(void); +EQLIB_OBJECT int CXStr::operator==(char const *)const; +EQLIB_OBJECT int CXStr::operator==(class CXStr const &)const; +EQLIB_OBJECT int CXStr::operator>(class CXStr const &)const; +EQLIB_OBJECT long CXStr::GetLength(void)const; +EQLIB_OBJECT unsigned short CXStr::GetUnicode(long)const; +EQLIB_OBJECT unsigned short CXStr::SetUnicode(long,unsigned short); +//EQLIB_OBJECT void * CXStr::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CXStr::AddCr(void); +EQLIB_OBJECT void CXStr::Blank(void); +EQLIB_OBJECT void CXStr::BlankPreAllocate(int); +EQLIB_OBJECT void CXStr::CopySelf(long,long); +EQLIB_OBJECT void CXStr::Delete(long,long); +EQLIB_OBJECT void CXStr::Insert(long,char); +EQLIB_OBJECT void CXStr::Insert(long,class CXStr const &); +EQLIB_OBJECT void CXStr::operator+=(char const *); +EQLIB_OBJECT void CXStr::operator+=(char); +EQLIB_OBJECT void CXStr::operator+=(class CXStr const &); +EQLIB_OBJECT void CXStr::operator+=(unsigned short); +//EQLIB_OBJECT void CXStr::SetEncoding(enum EStringEncoding); +EQLIB_OBJECT void CXStr::SetLowerCase(void); +EQLIB_OBJECT void CXStr::SetUpperCase(void); +EQLIB_OBJECT void CXStr::Strip(char); +EQLIB_OBJECT void CXStr::StripAll(char); +EQLIB_OBJECT void CXStr::StripLeading(char); +EQLIB_OBJECT void CXStr::StripTrailing(char); +// protected +EQLIB_OBJECT static int __cdecl CXStr::LenUnicodeToUtf8(unsigned short const *); +EQLIB_OBJECT static int __cdecl CXStr::UnicodeToUtf8(unsigned short const *,char *,int); +EQLIB_OBJECT static int __cdecl CXStr::Utf8ToUnicode(char const *,unsigned short *,int); +//EQLIB_OBJECT struct CStrRep * CXStr::AllocRepNoLock(long,enum EStringEncoding); +//EQLIB_OBJECT void CXStr::Assure(long,enum EStringEncoding); +EQLIB_OBJECT void CXStr::AssureCopy(void); +EQLIB_OBJECT void CXStr::FreeRep(struct CStrRep *); +EQLIB_OBJECT void CXStr::FreeRepNoLock(struct CStrRep *); +// private +EQLIB_OBJECT void CXStr::CheckNoLock(void); + + PCXSTR Ptr; + +}; + +class CXWnd +{ +public: +EQLIB_OBJECT enum UIType CXWnd::GetType(); +EQLIB_OBJECT class CXMLData * CXWnd::GetXMLData(); +EQLIB_OBJECT class CXWnd * CXWnd::GetChildItem(PCHAR Name); +EQLIB_OBJECT CXWnd::CXWnd(class CXWnd *,unsigned __int32,class CXRect); +EQLIB_OBJECT bool CXWnd::HasFocus(void)const; +EQLIB_OBJECT bool CXWnd::IsActive(void)const; +EQLIB_OBJECT bool CXWnd::IsDescendantOf(class CXWnd const *)const; +EQLIB_OBJECT bool CXWnd::IsEnabled(void)const; +EQLIB_OBJECT bool CXWnd::IsReallyVisible(void)const; +//EQLIB_OBJECT bool CXWnd::IsType(enum EWndRuntimeType)const; +EQLIB_OBJECT class CButtonDrawTemplate const * CXWnd::GetCloseBoxTemplate(void)const; +EQLIB_OBJECT class CButtonDrawTemplate const * CXWnd::GetMinimizeBoxTemplate(void)const; +EQLIB_OBJECT class CButtonDrawTemplate const * CXWnd::GetTileBoxTemplate(void)const; +EQLIB_OBJECT class CTAFrameDraw const * CXWnd::GetBorderFrame(void)const; +EQLIB_OBJECT class CTAFrameDraw const * CXWnd::GetTitlebarHeader(void)const; +EQLIB_OBJECT class CXRect CXWnd::GetClientClipRect(void)const; +EQLIB_OBJECT class CXRect CXWnd::GetRelativeRect(void)const; +EQLIB_OBJECT class CXRect CXWnd::GetScreenClipRect(void)const; +EQLIB_OBJECT class CXRect CXWnd::GetScreenRect(void)const; +EQLIB_OBJECT class CXStr CXWnd::GetWindowTextA(void)const; +EQLIB_OBJECT class CXStr CXWnd::GetXMLTooltip(void)const; +EQLIB_OBJECT class CXWnd * CXWnd::GetChildItem(CXStr const &); +EQLIB_OBJECT class CXWnd * CXWnd::GetChildWndAt(class CXPoint)const; +EQLIB_OBJECT class CXWnd * CXWnd::GetFirstChildWnd(void)const; +EQLIB_OBJECT class CXWnd * CXWnd::GetNextChildWnd(class CXWnd *)const; +EQLIB_OBJECT class CXWnd * CXWnd::GetNextSib(void)const; +EQLIB_OBJECT class CXWnd * CXWnd::SetFocus(void); +EQLIB_OBJECT int CXWnd::DoAllDrawing(void)const; +EQLIB_OBJECT int CXWnd::DrawChildren(void)const; +EQLIB_OBJECT int CXWnd::DrawCloseBox(void)const; +EQLIB_OBJECT int CXWnd::DrawHScrollbar(int,int,int)const; +EQLIB_OBJECT int CXWnd::DrawMinimizeBox(void)const; +EQLIB_OBJECT int CXWnd::DrawTileBox(void)const; +EQLIB_OBJECT int CXWnd::DrawVScrollbar(int,int,int)const; +EQLIB_OBJECT int CXWnd::GetWidth(void)const; +EQLIB_OBJECT int CXWnd::Minimize(bool); +EQLIB_OBJECT int CXWnd::Move(class CXPoint); +EQLIB_OBJECT int CXWnd::Move(class CXRect); +EQLIB_OBJECT int CXWnd::ProcessTransition(void); +EQLIB_OBJECT int CXWnd::Resize(int,int); +EQLIB_OBJECT int CXWnd::Show(bool,bool,bool mq_c = 1); +EQLIB_OBJECT int CXWnd::Tile(bool); +EQLIB_OBJECT static class CXRect __cdecl CXWnd::GetTooltipRect(class CXPoint,class CXSize); +EQLIB_OBJECT static class CXRect __cdecl CXWnd::GetTooltipRect(class CXSize); +EQLIB_OBJECT static class CXWndDrawTemplate CXWnd::sm_wdtDefaults; +EQLIB_OBJECT static int __cdecl CXWnd::DrawColoredRect(class CXRect,unsigned long,class CXRect); +EQLIB_OBJECT static int __cdecl CXWnd::DrawLasso(class CXRect,unsigned long,class CXRect); +EQLIB_OBJECT static int __cdecl CXWnd::DrawRaisedRect(class CXRect,class CXRect); +EQLIB_OBJECT static int __cdecl CXWnd::DrawSunkenRect(class CXRect,class CXRect); +EQLIB_OBJECT void CXWnd::Bottom(void); +EQLIB_OBJECT void CXWnd::BringChildWndToTop(class CXWnd *); +EQLIB_OBJECT void CXWnd::BringToTop(bool); +EQLIB_OBJECT void CXWnd::Center(void); +EQLIB_OBJECT void CXWnd::ClrFocus(void); +EQLIB_OBJECT void CXWnd::DrawTooltipAtPoint(class CXPoint)const; +EQLIB_OBJECT void CXWnd::Left(void); +EQLIB_OBJECT void CXWnd::Refade(void); +EQLIB_OBJECT void CXWnd::Right(void); +EQLIB_OBJECT void CXWnd::SetFirstChildPointer(class CXWnd *); +EQLIB_OBJECT void CXWnd::SetKeyTooltip(int,int); +EQLIB_OBJECT void CXWnd::SetLookLikeParent(void); +EQLIB_OBJECT void CXWnd::SetMouseOver(bool); +EQLIB_OBJECT void CXWnd::SetNextSibPointer(class CXWnd *); +EQLIB_OBJECT void CXWnd::SetTooltip(class CXStr); +EQLIB_OBJECT void CXWnd::SetXMLTooltip(class CXStr); +EQLIB_OBJECT void CXWnd::SetZLayer(int); +EQLIB_OBJECT void CXWnd::StartFade(unsigned char,unsigned __int32); +// virtual +EQLIB_OBJECT bool CXWnd::IsPointTransparent(class CXPoint)const; +EQLIB_OBJECT bool CXWnd::IsValid(void)const; +EQLIB_OBJECT bool CXWnd::QueryClickStickDropOK(class CClickStickInfo *)const; +EQLIB_OBJECT bool CXWnd::QueryDropOK(struct SDragDropInfo *)const; +EQLIB_OBJECT class CTextureAnimation * CXWnd::GetClickStickCursor(class CClickStickInfo *)const; +EQLIB_OBJECT class CTextureAnimation * CXWnd::GetCursorToDisplay(void)const; +EQLIB_OBJECT class CTextureAnimation * CXWnd::GetDragDropCursor(struct SDragDropInfo *)const; +EQLIB_OBJECT class CXRect CXWnd::GetClientRect(void)const; +EQLIB_OBJECT class CXRect CXWnd::GetHitTestRect(int)const; +EQLIB_OBJECT class CXRect CXWnd::GetInnerRect(void)const; +EQLIB_OBJECT class CXRect CXWnd::GetMinimizedRect(void)const; +EQLIB_OBJECT class CXSize CXWnd::GetMinSize(void)const; +EQLIB_OBJECT class CXSize CXWnd::GetUntileSize(void)const; +EQLIB_OBJECT class CXStr CXWnd::GetTooltip(void)const; +EQLIB_OBJECT int CXWnd::AboutToDeleteWnd(class CXWnd *); +EQLIB_OBJECT int CXWnd::Draw(void)const; +EQLIB_OBJECT int CXWnd::DrawBackground(void)const; +EQLIB_OBJECT int CXWnd::DrawCaret(void)const; +EQLIB_OBJECT int CXWnd::DrawChildItem(class CXWnd const *,void *)const; +EQLIB_OBJECT int CXWnd::DrawCursor(class CXPoint,class CXRect,bool &); +EQLIB_OBJECT int CXWnd::DrawNC(void)const; +EQLIB_OBJECT int CXWnd::DrawTitleBar(class CXRect)const; +EQLIB_OBJECT int CXWnd::DrawTooltip(class CXWnd const *)const; +EQLIB_OBJECT int CXWnd::HandleKeyboardMsg(unsigned __int32,unsigned __int32,bool); +EQLIB_OBJECT int CXWnd::HandleLButtonDown(class CXPoint *,unsigned __int32); +EQLIB_OBJECT int CXWnd::HandleLButtonHeld(class CXPoint *,unsigned __int32); +EQLIB_OBJECT int CXWnd::HandleLButtonUp(class CXPoint *,unsigned __int32); +EQLIB_OBJECT int CXWnd::HandleLButtonUpAfterHeld(class CXPoint *,unsigned __int32); +EQLIB_OBJECT int CXWnd::HandleMouseMove(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CXWnd::HandleRButtonDown(class CXPoint *,unsigned __int32); +EQLIB_OBJECT int CXWnd::HandleRButtonHeld(class CXPoint *,unsigned __int32); +EQLIB_OBJECT int CXWnd::HandleRButtonUp(class CXPoint *,unsigned __int32); +EQLIB_OBJECT int CXWnd::HandleRButtonUpAfterHeld(class CXPoint *,unsigned __int32); +EQLIB_OBJECT int CXWnd::HandleWheelButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CXWnd::HandleWheelButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CXWnd::HandleWheelMove(class CXPoint,int,unsigned __int32); +EQLIB_OBJECT int CXWnd::HitTest(class CXPoint,int *)const; +EQLIB_OBJECT int CXWnd::OnActivate(class CXWnd *); +EQLIB_OBJECT int CXWnd::OnBroughtToTop(void); +EQLIB_OBJECT int CXWnd::OnClickStick(class CClickStickInfo *,unsigned __int32,bool); +EQLIB_OBJECT int CXWnd::OnDragDrop(struct SDragDropInfo *); +EQLIB_OBJECT int CXWnd::OnHScroll(EScrollCode,int); +EQLIB_OBJECT int CXWnd::OnKillFocus(class CXWnd *); +EQLIB_OBJECT int CXWnd::OnMinimizeBox(void); +EQLIB_OBJECT int CXWnd::OnMove(class CXRect); +EQLIB_OBJECT int CXWnd::OnProcessFrame(void); +EQLIB_OBJECT int CXWnd::OnResize(int,int); +EQLIB_OBJECT int CXWnd::OnSetFocus(class CXWnd *); +EQLIB_OBJECT int CXWnd::OnShow(void); +EQLIB_OBJECT int CXWnd::OnTile(void); +EQLIB_OBJECT int CXWnd::OnTileBox(void); +EQLIB_OBJECT int CXWnd::OnVScroll(EScrollCode,int); +EQLIB_OBJECT int CXWnd::PostDraw(void)const; +//EQLIB_OBJECT int CXWnd::RequestDockInfo(enum EDockAction,class CXWnd *,class CXRect *); +EQLIB_OBJECT int CXWnd::SetVScrollPos(int); +EQLIB_OBJECT int CXWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CXWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CXWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CXWnd::Deactivate(void); +EQLIB_OBJECT void CXWnd::OnReloadSidl(void); +EQLIB_OBJECT void CXWnd::SetAttributesFromSidl(class CParamScreenPiece *); +EQLIB_OBJECT void CXWnd::SetDrawTemplate(class CXWndDrawTemplate *); +EQLIB_OBJECT void CXWnd::SetWindowTextA(class CXStr &); +// protected +EQLIB_OBJECT static class CXWndManager * & CXWnd::sm_pMgr; +// private +EQLIB_OBJECT static unsigned char CXWnd::sm_byCurrentAlpha; +EQLIB_OBJECT int CXWnd::SetFont(void*); + +CXW; + +}; +#define ZoneToGoTo 0 + +struct CStrPtr +{ + int RefCount; + long MaxLength; + long Length; + int Encoding; + void *Buff; + union + { + char Ansi[1000]; + wchar_t Unicode[500]; + CStrPtr* pNext; + }; +}; +class CCXStr +{ +public: + EQLIB_OBJECT CCXStr& operator= (char const *str); + + CStrPtr* Ptr; +}; + +static inline VOID SetCCXStr(PCXSTR *cxstr, PCHAR text) +{ + //cxstr=text; + CCXStr *Str = (CCXStr*)cxstr; + (*Str) = text; + cxstr = (PCXSTR*)Str; +} + +class CSidlScreenWnd +{ +public: +EQLIB_OBJECT enum UIType CSidlScreenWnd::GetType(); +EQLIB_OBJECT class CXMLData * CSidlScreenWnd::GetXMLData(); +EQLIB_OBJECT class CXWnd * CSidlScreenWnd::GetChildItem(PCHAR Name); +EQLIB_OBJECT CSidlScreenWnd::CSidlScreenWnd() {}; +EQLIB_OBJECT CSidlScreenWnd::CSidlScreenWnd(class CXWnd *,class CXStr); +EQLIB_OBJECT CSidlScreenWnd::CSidlScreenWnd(class CXWnd *pWnd,class CXStr *Template,int Flags,int unknown4, char *unknown5); +EQLIB_OBJECT CSidlScreenWnd::CSidlScreenWnd(class CXWnd *,unsigned __int32,class CXRect,class CXStr); +EQLIB_OBJECT class CScreenPieceTemplate * CSidlScreenWnd::GetSidlPiece(class CXStr*, int dummy=1)const; +EQLIB_OBJECT class CXRect CSidlScreenWnd::GetSidlPieceRect(class CScreenPieceTemplate *,class CXRect)const; +EQLIB_OBJECT class CXWnd * CSidlScreenWnd::GetChildItem(CXStr const &); +EQLIB_OBJECT int CSidlScreenWnd::DrawSidlPiece(class CScreenPieceTemplate *,class CXRect,class CXRect)const; +EQLIB_OBJECT void CSidlScreenWnd::AddButtonToRadioGroup(class CXStr,class CButtonWnd *); +EQLIB_OBJECT void CSidlScreenWnd::CalculateHSBRange(void); +EQLIB_OBJECT void CSidlScreenWnd::CalculateVSBRange(void); +EQLIB_OBJECT void CSidlScreenWnd::CreateChildrenFromSidl(void); +EQLIB_OBJECT void CSidlScreenWnd::EnableIniStorage(int,char *); +EQLIB_OBJECT void CSidlScreenWnd::Init(int,class CXStr*,int,int,int); +EQLIB_OBJECT void CSidlScreenWnd::Init(class CXWnd *,unsigned __int32,class CXRect,class CXStr,int,char *); +EQLIB_OBJECT void CSidlScreenWnd::LoadIniListWnd(class CListWnd *,char *); +EQLIB_OBJECT void CSidlScreenWnd::SetScreen(class CXStr*); +EQLIB_OBJECT void CSidlScreenWnd::StoreIniListWnd(class CListWnd const *,char *); +EQLIB_OBJECT void CSidlScreenWnd::StoreIniVis(void); +// virtual +EQLIB_OBJECT CSidlScreenWnd::~CSidlScreenWnd(void); +EQLIB_OBJECT int CSidlScreenWnd::DrawBackground(void)const; +EQLIB_OBJECT int CSidlScreenWnd::HandleRButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CSidlScreenWnd::OnResize(int,int); +EQLIB_OBJECT int CSidlScreenWnd::OnShow(void); +EQLIB_OBJECT int CSidlScreenWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CSidlScreenWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CSidlScreenWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CSidlScreenWnd::LoadIniInfo(void); +EQLIB_OBJECT void CSidlScreenWnd::StoreIniInfo(void); +// protected +EQLIB_OBJECT int CSidlScreenWnd::ConvertToRes(int,int,int,int); +EQLIB_OBJECT void CSidlScreenWnd::LoadSidlScreen(void); +// private +EQLIB_OBJECT static bool CSidlScreenWnd::m_useIniFile; + +inline CXWnd *pXWnd() {return (CXWnd*)this;}; + +CSW; +}; + + + + +class _EverQuestinfo +{ +public: +EQLIB_OBJECT void _EverQuestinfo::SetAutoAttack(bool); +}; + +class _PackFileData +{ +public: +EQLIB_OBJECT _PackFileData::~_PackFileData(void); +// virtual +EQLIB_OBJECT int _PackFileData::readBlock(void); +}; + +class _PackFileDataRawFile +{ +public: +// virtual +EQLIB_OBJECT int _PackFileDataRawFile::readBlock(void); +}; + +class _partyGroup +{ +public: +EQLIB_OBJECT int _partyGroup::getNumMembers(void)const; +}; + +class AltAdvManager +{ +public: +EQLIB_OBJECT AltAdvManager::AltAdvManager(void); +EQLIB_OBJECT bool AltAdvManager::IsAbilityReady(class EQ_PC *,EQData::PALTABILITY,int *,int mq2_dummy = 0); +EQLIB_OBJECT int AltAdvManager::AbilitiesByClass(int,int); +EQLIB_OBJECT int AltAdvManager::AltSkillReqs(class EQ_PC *,int); +EQLIB_OBJECT int AltAdvManager::CalculateDoubleAttackChance(class EQ_PC *,int,unsigned char); +EQLIB_OBJECT int AltAdvManager::CalculateFleetOfFoot(class EQ_PC *); +EQLIB_OBJECT int AltAdvManager::CalculateHideTimeReduce(class EQ_PC *); +EQLIB_OBJECT int AltAdvManager::CalculateInstrumentMasteryMod(class EQ_PC *); +EQLIB_OBJECT int AltAdvManager::CalculateLoHHarmTouchReuseTimer(class EQ_PC *,int); +EQLIB_OBJECT int AltAdvManager::CalculateMaxHPAA(class EQ_PC *,int); +EQLIB_OBJECT int AltAdvManager::CalculateMaxStatAA(class EQ_PC *,int); +EQLIB_OBJECT int AltAdvManager::CalculateMitigationBoost(class EQ_PC *,int); +EQLIB_OBJECT int AltAdvManager::CalculateNimbleEvasionChance(class EQ_PC *); +EQLIB_OBJECT int AltAdvManager::CalculateSingingMasteryMod(class EQ_PC *,int); +EQLIB_OBJECT int AltAdvManager::CalculateSpellCastingMastery(class EQ_PC *); +EQLIB_OBJECT int AltAdvManager::CalculateStalwartEnduranceChance(class EQ_PC *); +EQLIB_OBJECT int AltAdvManager::CanTrainAbility(class EQ_PC *,int); +EQLIB_OBJECT int AltAdvManager::GetAALevelNeeded(class EQ_PC *,int); +EQLIB_OBJECT int AltAdvManager::GetAbilityTitle(class EQPlayer *); +EQLIB_OBJECT int AltAdvManager::GetNextAbilityCost(int,int); +EQLIB_OBJECT int AltAdvManager::MeetsPoPLevelReqs(class EQ_PC *,int,int); +EQLIB_OBJECT int AltAdvManager::TotalPointsInSkill(int,int); +EQLIB_OBJECT unsigned long AltAdvManager::GetCalculatedTimer(class EQ_PC *,EQData::PALTABILITY); +EQLIB_OBJECT void AltAdvManager::GetAbilityReqs(char *,int); +EQLIB_OBJECT struct _ALTABILITY *AltAdvManager::GetAltAbility(int); +}; + +class bad_word_class +{ +public: +EQLIB_OBJECT bad_word_class::bad_word_class(char *); +}; + +class CAAWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CAAWnd::CAAWnd(class CXWnd *); +EQLIB_OBJECT void CAAWnd::Activate(void); +EQLIB_OBJECT void CAAWnd::CancelAASpend(void); +EQLIB_OBJECT void CAAWnd::ConfirmAASpend(void); +EQLIB_OBJECT void CAAWnd::SendNewPercent(void); +EQLIB_OBJECT void CAAWnd::ShowAbility(int); +EQLIB_OBJECT void CAAWnd::Update(void); +EQLIB_OBJECT void CAAWnd::UpdateTimer(void); +// virtual +EQLIB_OBJECT CAAWnd::~CAAWnd(void); +EQLIB_OBJECT int CAAWnd::OnProcessFrame(void); +EQLIB_OBJECT int CAAWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CAAWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CAAWnd::`vector deleting destructor'(unsigned int); +#define SafeZLoc 0 +EQLIB_OBJECT void CAAWnd::Deactivate(void); +// private +EQLIB_OBJECT void CAAWnd::Init(void); +EQLIB_OBJECT void CAAWnd::UpdateSelected(void); +}; + +class CActionsWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CActionsWnd::CActionsWnd(class CXWnd *); +EQLIB_OBJECT class CButtonWnd * CActionsWnd::GetAbilityBtn(int); +EQLIB_OBJECT class CButtonWnd * CActionsWnd::GetCombatBtn(int); +EQLIB_OBJECT class CButtonWnd * CActionsWnd::GetMenuBtn(int); +EQLIB_OBJECT int CActionsWnd::GetCurrentPageEnum(void)const; +EQLIB_OBJECT void CActionsWnd::Activate(int); +EQLIB_OBJECT void CActionsWnd::KeyMapUpdated(void); +EQLIB_OBJECT void CActionsWnd::SelectSkillForAbilityBtn(int); +EQLIB_OBJECT void CActionsWnd::SelectSkillForCombatBtn(int); +EQLIB_OBJECT void CActionsWnd::UpdateButtonText(void); +// virtual +EQLIB_OBJECT CActionsWnd::~CActionsWnd(void); +EQLIB_OBJECT int CActionsWnd::OnProcessFrame(void); +EQLIB_OBJECT int CActionsWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CActionsWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CActionsWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CActionsWnd::Deactivate(void); +// private +EQLIB_OBJECT int CActionsWnd::AbilitiesPageActivate(void); +EQLIB_OBJECT int CActionsWnd::AbilitiesPageDeactivate(void); +EQLIB_OBJECT int CActionsWnd::AbilitiesPageOnProcessFrame(void); +EQLIB_OBJECT int CActionsWnd::AbilitiesPageWndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int CActionsWnd::CombatPageActivate(void); +EQLIB_OBJECT int CActionsWnd::CombatPageDeactivate(void); +EQLIB_OBJECT int CActionsWnd::CombatPageOnProcessFrame(void); +EQLIB_OBJECT int CActionsWnd::CombatPageWndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int CActionsWnd::MainPageActivate(void); +EQLIB_OBJECT int CActionsWnd::MainPageDeactivate(void); +EQLIB_OBJECT int CActionsWnd::MainPageOnProcessFrame(void); +EQLIB_OBJECT int CActionsWnd::MainPageWndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int CActionsWnd::RedirectActivateTo(class CPageWnd *); +EQLIB_OBJECT int CActionsWnd::RedirectDeactivateTo(class CPageWnd *); +EQLIB_OBJECT int CActionsWnd::RedirectOnProcessFrameTo(class CPageWnd *); +EQLIB_OBJECT int CActionsWnd::RedirectWndNotificationTo(class CPageWnd *,class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int CActionsWnd::SocialsPageActivate(void); +EQLIB_OBJECT int CActionsWnd::SocialsPageDeactivate(void); +EQLIB_OBJECT int CActionsWnd::SocialsPageOnProcessFrame(void); +EQLIB_OBJECT int CActionsWnd::SocialsPageWndNotification(class CXWnd *,unsigned __int32,void *); +}; + +class CAlarmWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CAlarmWnd::CAlarmWnd(class CXWnd *); +EQLIB_OBJECT void CAlarmWnd::Activate(void); +// virtual +EQLIB_OBJECT CAlarmWnd::~CAlarmWnd(void); +EQLIB_OBJECT int CAlarmWnd::OnProcessFrame(void); +EQLIB_OBJECT int CAlarmWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CAlarmWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CAlarmWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CAlarmWnd::Deactivate(void); +// private +EQLIB_OBJECT void CAlarmWnd::DoNeverButton(void); +}; + +class CBankWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CBankWnd::CBankWnd(class CXWnd *,class CXStr); +EQLIB_OBJECT int CBankWnd::GetNumBankSlots(void)const; +EQLIB_OBJECT void CBankWnd::Activate(class EQPlayer *); +EQLIB_OBJECT void CBankWnd::Deactivate(bool); +// virtual +EQLIB_OBJECT CBankWnd::~CBankWnd(void); +EQLIB_OBJECT int CBankWnd::OnProcessFrame(void); +EQLIB_OBJECT int CBankWnd::PostDraw(void)const; +EQLIB_OBJECT int CBankWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CBankWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CBankWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CBankWnd::Deactivate(void); +// private +EQLIB_OBJECT long CBankWnd::GetBankQtyFromCoinType(int); +EQLIB_OBJECT void CBankWnd::ClickedMoneyButton(int,int); +EQLIB_OBJECT void CBankWnd::Init(void); +EQLIB_OBJECT void CBankWnd::UpdateMoneyDisplay(void); +}; + +class CBazaarSearchWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CBazaarSearchWnd::CBazaarSearchWnd(class CXWnd *); +EQLIB_OBJECT char * CBazaarSearchWnd::GetPriceString(unsigned long); +EQLIB_OBJECT void CBazaarSearchWnd::Activate(void); +EQLIB_OBJECT void CBazaarSearchWnd::HandleBazaarMsg(char *,int); +EQLIB_OBJECT void CBazaarSearchWnd::UpdatePlayerCombo(void); +EQLIB_OBJECT void CBazaarSearchWnd::UpdatePlayerUpdateButton(bool); +// virtual +EQLIB_OBJECT CBazaarSearchWnd::~CBazaarSearchWnd(void); +EQLIB_OBJECT int CBazaarSearchWnd::Draw(void)const; +EQLIB_OBJECT int CBazaarSearchWnd::OnProcessFrame(void); +EQLIB_OBJECT int CBazaarSearchWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CBazaarSearchWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CBazaarSearchWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CBazaarSearchWnd::Deactivate(void); +// private +EQLIB_OBJECT void CBazaarSearchWnd::AddItemtoList(char *,unsigned long,char *,int,int); +EQLIB_OBJECT void CBazaarSearchWnd::doQuery(void); +EQLIB_OBJECT void CBazaarSearchWnd::Init(void); +EQLIB_OBJECT void CBazaarSearchWnd::InitListArray(void); +EQLIB_OBJECT void CBazaarSearchWnd::SortItemList(int); +EQLIB_OBJECT void CBazaarSearchWnd::UpdateComboButtons(void); +}; + +class CBazaarWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CBazaarWnd::CBazaarWnd(class CXWnd *); +EQLIB_OBJECT bool CBazaarWnd::StoreSelectedPrice(void); +EQLIB_OBJECT char * CBazaarWnd::GetPriceString(unsigned long); +EQLIB_OBJECT class EQ_Item * CBazaarWnd::ReturnItemByIndex(int); +EQLIB_OBJECT int CBazaarWnd::UpdateBazaarListtoServer(void); +EQLIB_OBJECT long CBazaarWnd::GetQtyFromCoinType(int); +EQLIB_OBJECT unsigned long CBazaarWnd::GetPrice(void); +EQLIB_OBJECT void CBazaarWnd::Activate(void); +EQLIB_OBJECT void CBazaarWnd::AddBazaarText(char *,int); +EQLIB_OBJECT void CBazaarWnd::AddEquipmentToBazaarArray(class EQ_Item *,int,unsigned long); +EQLIB_OBJECT void CBazaarWnd::BuildBazaarItemArray(void); +EQLIB_OBJECT void CBazaarWnd::ClickedMoneyButton(int,int); +EQLIB_OBJECT void CBazaarWnd::HandleTraderMsg(char *); +EQLIB_OBJECT void CBazaarWnd::RebuildItemArray(void); +EQLIB_OBJECT void CBazaarWnd::SelectBazaarSlotItem(int,class CTextureAnimation *); +EQLIB_OBJECT void CBazaarWnd::SetMoneyButton(int,int); +EQLIB_OBJECT void CBazaarWnd::UpdatePriceButtons(void); +// virtual +EQLIB_OBJECT CBazaarWnd::~CBazaarWnd(void); +EQLIB_OBJECT int CBazaarWnd::OnProcessFrame(void); +EQLIB_OBJECT int CBazaarWnd::PostDraw(void)const; +EQLIB_OBJECT int CBazaarWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CBazaarWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CBazaarWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CBazaarWnd::Deactivate(void); +// protected +EQLIB_OBJECT void CBazaarWnd::UpdateButtons(void); +// private +EQLIB_OBJECT void CBazaarWnd::CreateBZRIniFilename(void); +EQLIB_OBJECT void CBazaarWnd::Init(void); +EQLIB_OBJECT void CBazaarWnd::ToggleBzrItemActive(int,bool); +}; + +class CBodyTintWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CBodyTintWnd::CBodyTintWnd(class CXWnd *); +EQLIB_OBJECT char * CBodyTintWnd::BuildRBGTooltip(unsigned long,char * const); +EQLIB_OBJECT unsigned long CBodyTintWnd::GetButtonTint(int); +EQLIB_OBJECT unsigned long CBodyTintWnd::GetItemTint(int); +EQLIB_OBJECT void CBodyTintWnd::Activate(void); +EQLIB_OBJECT void CBodyTintWnd::GetReagentCount(void); +EQLIB_OBJECT void CBodyTintWnd::GetTintChangeCount(void); +EQLIB_OBJECT void CBodyTintWnd::ResetToOrigBodyTints(void); +EQLIB_OBJECT void CBodyTintWnd::SetSlotLabels(bool); +EQLIB_OBJECT void CBodyTintWnd::StoreModifiedBodyTints(void); +EQLIB_OBJECT void CBodyTintWnd::UpdateLabelsAndButtons(void); +EQLIB_OBJECT void CBodyTintWnd::UpdateLocalTintColor(unsigned long); +EQLIB_OBJECT void CBodyTintWnd::UpdateMaterialTintLocal(unsigned long); +// virtual +EQLIB_OBJECT CBodyTintWnd::~CBodyTintWnd(void); +EQLIB_OBJECT int CBodyTintWnd::OnProcessFrame(void); +EQLIB_OBJECT int CBodyTintWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CBodyTintWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CBodyTintWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CBodyTintWnd::Deactivate(void); +}; + +class CBookWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CBookWnd::CBookWnd(class CXWnd *); +EQLIB_OBJECT bool CBookWnd::CheckBook(class EQ_Note *); +EQLIB_OBJECT void CBookWnd::Activate(void); +EQLIB_OBJECT void CBookWnd::SetBook(char *); +// virtual +EQLIB_OBJECT CBookWnd::~CBookWnd(void); +EQLIB_OBJECT int CBookWnd::HandleKeyboardMsg(unsigned __int32,unsigned __int32,bool); +EQLIB_OBJECT int CBookWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CBookWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CBookWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CBookWnd::Deactivate(void); +// protected +EQLIB_OBJECT void CBookWnd::CleanPages(void); +EQLIB_OBJECT void CBookWnd::DisplayText(void); +EQLIB_OBJECT void CBookWnd::ProcessText(void); +EQLIB_OBJECT void CBookWnd::ShowButtons(void); +// private +EQLIB_OBJECT void CBookWnd::Init(void); +}; + +class CBreathWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CBreathWnd::CBreathWnd(class CXWnd *); +EQLIB_OBJECT void CBreathWnd::Activate(void); +// virtual +EQLIB_OBJECT CBreathWnd::~CBreathWnd(void); +EQLIB_OBJECT int CBreathWnd::OnProcessFrame(void); +//EQLIB_OBJECT void * CBreathWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CBreathWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CBreathWnd::Deactivate(void); +// private +EQLIB_OBJECT void CBreathWnd::Init(void); +}; + +class CBuffWindow : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CBuffWindow::CBuffWindow(class CXWnd *,enum BuffWindowType); +EQLIB_OBJECT void CBuffWindow::Activate(void); +EQLIB_OBJECT void CBuffWindow::SetBuffIcon(class CButtonWnd *,int,int); +// virtual +EQLIB_OBJECT CBuffWindow::~CBuffWindow(void); +EQLIB_OBJECT class CXSize CBuffWindow::GetMinSize(void)const; +EQLIB_OBJECT int CBuffWindow::OnProcessFrame(void); +EQLIB_OBJECT int CBuffWindow::PostDraw(void)const; +EQLIB_OBJECT int CBuffWindow::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CBuffWindow::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CBuffWindow::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CBuffWindow::Deactivate(void); +// private +EQLIB_OBJECT void CBuffWindow::HandleSpellInfoDisplay(class CXWnd *); +EQLIB_OBJECT void CBuffWindow::Init(void); +EQLIB_OBJECT void CBuffWindow::RefreshBuffDisplay(void); +EQLIB_OBJECT void CBuffWindow::RefreshIconArrangement(void); +}; + +class CBugReportWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CBugReportWnd::CBugReportWnd(class CXWnd *); +EQLIB_OBJECT void CBugReportWnd::Activate(void); +// virtual +EQLIB_OBJECT CBugReportWnd::~CBugReportWnd(void); +EQLIB_OBJECT int CBugReportWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CBugReportWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CBugReportWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CBugReportWnd::Deactivate(void); +// private +EQLIB_OBJECT void CBugReportWnd::UpdateLocation(void); +}; + +class CButtonDrawTemplate +{ +public: +EQLIB_OBJECT CButtonDrawTemplate::~CButtonDrawTemplate(void); +EQLIB_OBJECT CButtonDrawTemplate::CButtonDrawTemplate(class CButtonDrawTemplate const &); +EQLIB_OBJECT CButtonDrawTemplate::CButtonDrawTemplate(void); +EQLIB_OBJECT class CButtonDrawTemplate & CButtonDrawTemplate::operator=(class CButtonDrawTemplate const &); +EQLIB_OBJECT class CXSize CButtonDrawTemplate::GetSize(void)const; +}; + +class CButtonTemplate +{ +public: +EQLIB_OBJECT CButtonTemplate::CButtonTemplate(class CParamButton *); +// virtual +EQLIB_OBJECT CButtonTemplate::~CButtonTemplate(void); +//EQLIB_OBJECT void * CButtonTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CButtonTemplate::`vector deleting destructor'(unsigned int); +}; + +class CButtonWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CButtonWnd::CButtonWnd(class CXWnd *,unsigned __int32,class CXRect,class CXPoint,class CXSize,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *); +EQLIB_OBJECT void CButtonWnd::SetCheck(bool); +// virtual +EQLIB_OBJECT CButtonWnd::~CButtonWnd(void); +EQLIB_OBJECT bool CButtonWnd::IsPointTransparent(class CXPoint)const; +EQLIB_OBJECT int CButtonWnd::Draw(void)const; +EQLIB_OBJECT int CButtonWnd::HandleLButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CButtonWnd::HandleLButtonHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CButtonWnd::HandleLButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CButtonWnd::HandleLButtonUpAfterHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CButtonWnd::HandleMouseMove(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CButtonWnd::HandleRButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CButtonWnd::HandleRButtonHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CButtonWnd::HandleRButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CButtonWnd::HandleRButtonUpAfterHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CButtonWnd::OnProcessFrame(void); +//EQLIB_OBJECT void * CButtonWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CButtonWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CButtonWnd::SetAttributesFromSidl(class CParamScreenPiece *); +EQLIB_OBJECT void CButtonWnd::SetRadioGroup(class CRadioGroup *); +}; + +class CCastingWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CCastingWnd::CCastingWnd(class CXWnd *); +EQLIB_OBJECT void CCastingWnd::Activate(void); +// virtual +EQLIB_OBJECT CCastingWnd::~CCastingWnd(void); +EQLIB_OBJECT int CCastingWnd::OnProcessFrame(void); +//EQLIB_OBJECT void * CCastingWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CCastingWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CCastingWnd::Deactivate(void); +}; + +class CCastSpellWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CCastSpellWnd::CCastSpellWnd(class CXWnd *); +//EQLIB_OBJECT CCastSpellWnd::SpellCategoryMajor::~SpellCategoryMajor(void); +//EQLIB_OBJECT CCastSpellWnd::SpellCategoryMinor::~SpellCategoryMinor(void); +EQLIB_OBJECT static void __cdecl CCastSpellWnd::Unmemorize(int); +EQLIB_OBJECT static void __cdecl CCastSpellWnd::UnmemorizeList(int *,int); +EQLIB_OBJECT void CCastSpellWnd::Activate(void); +EQLIB_OBJECT void CCastSpellWnd::ForgetMemorizedSpell(int); +EQLIB_OBJECT void CCastSpellWnd::HandleSpellInfoDisplay(class CXWnd *); +EQLIB_OBJECT void CCastSpellWnd::HandleSpellLeftClick(int); +EQLIB_OBJECT void CCastSpellWnd::HandleSpellRightClick(int); +EQLIB_OBJECT void CCastSpellWnd::KeyMapUpdated(void); +EQLIB_OBJECT void CCastSpellWnd::RecacheCategorizedSpells(void); +EQLIB_OBJECT void CCastSpellWnd::RecacheLoadoutContextMenu(void); +EQLIB_OBJECT void CCastSpellWnd::SpellBookDeactivating(void); +// virtual +EQLIB_OBJECT CCastSpellWnd::~CCastSpellWnd(void); +EQLIB_OBJECT int CCastSpellWnd::OnProcessFrame(void); +EQLIB_OBJECT int CCastSpellWnd::PostDraw(void)const; +EQLIB_OBJECT int CCastSpellWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CCastSpellWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CCastSpellWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CCastSpellWnd::Deactivate(void); +// private +EQLIB_OBJECT bool CCastSpellWnd::IsBardSongPlaying(void); +EQLIB_OBJECT unsigned long CCastSpellWnd::GetSpellGemColor(class EQ_Spell *); +EQLIB_OBJECT void CCastSpellWnd::CategorizeSpell(int,int,int,int); +EQLIB_OBJECT void CCastSpellWnd::ClearSpellCategories(void); +EQLIB_OBJECT void CCastSpellWnd::Init(void); +EQLIB_OBJECT void CCastSpellWnd::MakeSpellSelectMenu(void); +EQLIB_OBJECT void CCastSpellWnd::RefreshSpellGemButtons(void); +EQLIB_OBJECT void CCastSpellWnd::UpdateSpellGems(int); +EQLIB_OBJECT void CCastSpellWnd::UpdateSpellGemTooltips(int); +}; + +class CCharacterCreation : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CCharacterCreation::CCharacterCreation(class CXWnd *); +EQLIB_OBJECT void CCharacterCreation::Activate(void); +EQLIB_OBJECT void CCharacterCreation::ActivateScreen(int); +EQLIB_OBJECT void CCharacterCreation::DoBackButton(void); +EQLIB_OBJECT void CCharacterCreation::DoNextButton(void); +EQLIB_OBJECT void CCharacterCreation::HandleNameApprovalResponse(int); +EQLIB_OBJECT void CCharacterCreation::NameGenerated(char *); +// virtual +EQLIB_OBJECT CCharacterCreation::~CCharacterCreation(void); +EQLIB_OBJECT int CCharacterCreation::Draw(void)const; +EQLIB_OBJECT int CCharacterCreation::OnProcessFrame(void); +EQLIB_OBJECT int CCharacterCreation::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CCharacterCreation::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CCharacterCreation::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CCharacterCreation::Deactivate(void); +// private +EQLIB_OBJECT bool CCharacterCreation::IsLackingExpansion(bool,bool); +EQLIB_OBJECT char * CCharacterCreation::GetCharCreateText(char *,int,int,int,int); +EQLIB_OBJECT int CCharacterCreation::GetClassButtonIndex(int); +EQLIB_OBJECT int CCharacterCreation::GetRaceButtonIndex(int); +EQLIB_OBJECT void CCharacterCreation::DoStatButton(int); +EQLIB_OBJECT void CCharacterCreation::FinalizeNewPCAndSendToWorld(void); +EQLIB_OBJECT void CCharacterCreation::Init(void); +EQLIB_OBJECT void CCharacterCreation::InitNewPC(void); +EQLIB_OBJECT void CCharacterCreation::InitStartingCities(void); +EQLIB_OBJECT void CCharacterCreation::InitStats(bool); +EQLIB_OBJECT void CCharacterCreation::RandomizeCharacter(bool,bool); +EQLIB_OBJECT void CCharacterCreation::RandomizeFacialFeatures(void); +EQLIB_OBJECT void CCharacterCreation::SelectedClassButton(int); +EQLIB_OBJECT void CCharacterCreation::SelectedRaceButton(int); +EQLIB_OBJECT void CCharacterCreation::SelectStartingCity(int); +EQLIB_OBJECT void CCharacterCreation::SetNewPCDeityFromBtnIndex(int); +EQLIB_OBJECT void CCharacterCreation::SetPlayerAppearanceFromNewPC(class EQPlayer *,class EQ_PC *,bool); +EQLIB_OBJECT void CCharacterCreation::SubmitNameToWorld(void); +EQLIB_OBJECT void CCharacterCreation::UpdatePlayerFromNewPC(void); +EQLIB_OBJECT void CCharacterCreation::UpdateScreenZeroButtons(bool); +}; + +class CCharacterSelect : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CCharacterSelect::CCharacterSelect(class CXWnd *); +EQLIB_OBJECT int CCharacterSelect::IsEmptyCharacterSlot(int); +EQLIB_OBJECT int CCharacterSelect::IsValidCharacterSelected(void); +EQLIB_OBJECT int CCharacterSelect::NumberOfCharacters(void); +EQLIB_OBJECT unsigned char CCharacterSelect::IsEvil(int,int,int); +EQLIB_OBJECT void CCharacterSelect::Activate(void); +EQLIB_OBJECT void CCharacterSelect::DeleteCharacter(void); +EQLIB_OBJECT void CCharacterSelect::EnterExplorationMode(void); +EQLIB_OBJECT void CCharacterSelect::EnterWorld(void); +EQLIB_OBJECT void CCharacterSelect::LeaveExplorationMode(void); +EQLIB_OBJECT void CCharacterSelect::Quit(void); +EQLIB_OBJECT void CCharacterSelect::SelectCharacter(int,int); +EQLIB_OBJECT void CCharacterSelect::SetLoadZonePlayerLocation(void); +EQLIB_OBJECT void CCharacterSelect::SwitchModel(class EQPlayer *,unsigned char,int,unsigned char,unsigned char); +EQLIB_OBJECT void CCharacterSelect::UpdateButtonNames(void); +// virtual +EQLIB_OBJECT CCharacterSelect::~CCharacterSelect(void); +EQLIB_OBJECT int CCharacterSelect::Draw(void)const; +EQLIB_OBJECT int CCharacterSelect::OnProcessFrame(void); +EQLIB_OBJECT int CCharacterSelect::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CCharacterSelect::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CCharacterSelect::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CCharacterSelect::Deactivate(void); +// private +EQLIB_OBJECT void CCharacterSelect::CreateExplorationModePlayers(void); +EQLIB_OBJECT void CCharacterSelect::EnableButtons(bool); +EQLIB_OBJECT void CCharacterSelect::EnableEqMovementCommands(bool); +EQLIB_OBJECT void CCharacterSelect::Init(void); +EQLIB_OBJECT void CCharacterSelect::RemoveExplorationModePlayers(void); +EQLIB_OBJECT void CCharacterSelect::SetLocationByClass(class EQPlayer *,bool,int); +EQLIB_OBJECT void CCharacterSelect::SetRoomLocationByIndex(int,class EQPlayer *); +}; + +class CChatManager +{ +public: +EQLIB_OBJECT CChatManager::~CChatManager(void); +EQLIB_OBJECT CChatManager::CChatManager(void); +EQLIB_OBJECT class CChatWindow * CChatManager::GetActiveChatWindow(void); +EQLIB_OBJECT class CChatWindow * CChatManager::GetChannelMap(int); +EQLIB_OBJECT class CXStr CChatManager::GetAllVisibleText(class CXStr); +EQLIB_OBJECT int CChatManager::GetChannelFromColor(int); +EQLIB_OBJECT int CChatManager::InitContextMenu(class CChatWindow *); +EQLIB_OBJECT unsigned long CChatManager::GetRGBAFromIndex(int); +EQLIB_OBJECT void CChatManager::Activate(void); +EQLIB_OBJECT void CChatManager::AddText(class CXStr,int); +EQLIB_OBJECT void CChatManager::ClearChannelMap(int); +EQLIB_OBJECT void CChatManager::ClearChannelMaps(class CChatWindow *); +EQLIB_OBJECT void CChatManager::CreateChatWindow(char *,char *,int,int,int,char *,int); +EQLIB_OBJECT void CChatManager::CreateChatWindow(void); +EQLIB_OBJECT void CChatManager::Deactivate(void); +EQLIB_OBJECT void CChatManager::FreeChatWindow(class CChatWindow *); +EQLIB_OBJECT void CChatManager::LoadChatInis(void); +EQLIB_OBJECT void CChatManager::Process(void); +EQLIB_OBJECT void CChatManager::SetActiveChatWindow(class CChatWindow *); +EQLIB_OBJECT void CChatManager::SetChannelMap(int,class CChatWindow *); +EQLIB_OBJECT void CChatManager::SetLockedActiveChatWindow(class CChatWindow *); +EQLIB_OBJECT void CChatManager::UpdateContextMenus(class CChatWindow *); +EQLIB_OBJECT void CChatManager::UpdateTellMenus(class CChatWindow *); +}; + +class CChatWindow : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CChatWindow::CChatWindow(class CXWnd *); +EQLIB_OBJECT class CEditWnd * CChatWindow::GetInputWnd(void); +EQLIB_OBJECT class CStmlWnd * CChatWindow::GetOutputWnd(void); +EQLIB_OBJECT class CXStr CChatWindow::GetInputText(void); +EQLIB_OBJECT void CChatWindow::AddHistory(class CXStr); +EQLIB_OBJECT void CChatWindow::AddOutputText(class CXStr,int); +EQLIB_OBJECT void CChatWindow::Clear(void); +EQLIB_OBJECT void CChatWindow::HistoryBack(void); +EQLIB_OBJECT void CChatWindow::HistoryForward(void); +EQLIB_OBJECT void CChatWindow::PageDown(void); +EQLIB_OBJECT void CChatWindow::PageUp(void); +EQLIB_OBJECT void CChatWindow::SetChatFont(int); +// virtual +EQLIB_OBJECT CChatWindow::~CChatWindow(void); +EQLIB_OBJECT int CChatWindow::Draw(void)const; +EQLIB_OBJECT int CChatWindow::HandleRButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CChatWindow::OnKillFocus(class CXWnd *); +EQLIB_OBJECT int CChatWindow::OnProcessFrame(void); +EQLIB_OBJECT int CChatWindow::OnSetFocus(class CXWnd *); +EQLIB_OBJECT int CChatWindow::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CChatWindow::`scalar deleting destructor'(unsigned int); +EQLIB_OBJECT void CChatWindow::operator delete[](void *); +EQLIB_OBJECT void CChatWindow::Deactivate(void); + +/*0x188*/ struct _EQCHATMGR *ChatManager; +/*0x18c*/ struct _CSIDLWND* InputWnd; +/*0x190*/ struct _CSIDLWND* OutputWnd; +/*0x194*/ DWORD Unknown0x194; +/*0x198*/ DWORD Unknown0x198;// need to update locations.. +/*0x19c*/ BYTE Unknown0x19c; +/*0x19d*/ BYTE Unknown0x19d[0x3f]; +/*0x1dc*/ DWORD Unknown0x1dc; +/*0x1e0*/ DWORD Unknown0x1e0; +/*0x1e4*/ struct _CXSTR *CommandHistory[0x28]; // ->0x198 +/*0x284*/ DWORD Unknown0x284; // CChatWindow::HistoryBack/forward .. maybe total or current history lines +/*0x288*/ DWORD Unknown0x288; // CChatWindow::HistoryBack/forward .. maybe total or current history lines +/*0x28c*/ DWORD FontSize; // +/*0x290*/ DWORD Unknown0x290; + +//EQLIB_OBJECT void *CChatWindow::operator new(size_t stAllocateBlock) {return malloc(sizeof(EQCHATWINDOW));} // 11-15-2003 lax +}; + +class CCheckBoxWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CCheckBoxWnd::CCheckBoxWnd(class CXWnd *,unsigned __int32,class CXRect,class CXPoint,class CXSize,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *); +EQLIB_OBJECT void CCheckBoxWnd::SetRadioLook(void); +// virtual +EQLIB_OBJECT CCheckBoxWnd::~CCheckBoxWnd(void); +EQLIB_OBJECT int CCheckBoxWnd::HandleLButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CCheckBoxWnd::HandleLButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CCheckBoxWnd::HandleMouseMove(class CXPoint,unsigned __int32); +//EQLIB_OBJECT void * CCheckBoxWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CCheckBoxWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CCheckBoxWnd::SetRadioGroup(class CRadioGroup *); +// protected +EQLIB_OBJECT static bool CCheckBoxWnd::sm_bAnimsInitialized; +EQLIB_OBJECT static class CButtonDrawTemplate CCheckBoxWnd::sm_bdtCheck; +EQLIB_OBJECT static class CButtonDrawTemplate CCheckBoxWnd::sm_bdtRadio; +}; + +class CClickStickInfo +{ +public: +EQLIB_OBJECT CClickStickInfo::CClickStickInfo(void); +// virtual +EQLIB_OBJECT CClickStickInfo::~CClickStickInfo(void); +//EQLIB_OBJECT void * CClickStickInfo::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CClickStickInfo::`vector deleting destructor'(unsigned int); +}; + +class CColorPickerWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CColorPickerWnd::CColorPickerWnd(class CXWnd *); +EQLIB_OBJECT void CColorPickerWnd::Activate(class CXWnd *,unsigned long); +EQLIB_OBJECT void CColorPickerWnd::CheckMaxEditWnd(void); +EQLIB_OBJECT void CColorPickerWnd::SetCurrentColor(unsigned long); +EQLIB_OBJECT void CColorPickerWnd::SetTemplateColor(int,unsigned long); +EQLIB_OBJECT void CColorPickerWnd::UpdateCurrentColor(void); +EQLIB_OBJECT void CColorPickerWnd::UpdateEditWndFromSlider(class CSliderWnd *,class CEditWnd *,int *); +EQLIB_OBJECT void CColorPickerWnd::UpdateSliderFromEditWnd(class CSliderWnd *,class CEditWnd *,int *); +// virtual +EQLIB_OBJECT CColorPickerWnd::~CColorPickerWnd(void); +EQLIB_OBJECT int CColorPickerWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CColorPickerWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CColorPickerWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CColorPickerWnd::Deactivate(void); +// private +EQLIB_OBJECT void CColorPickerWnd::Init(void); +}; + +class CComboboxTemplate +{ +public: +EQLIB_OBJECT CComboboxTemplate::CComboboxTemplate(class CParamCombobox *); +// virtual +EQLIB_OBJECT CComboboxTemplate::~CComboboxTemplate(void); +//EQLIB_OBJECT void * CComboboxTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CComboboxTemplate::`vector deleting destructor'(unsigned int); +}; + +class CComboWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CComboWnd::CComboWnd(class CXWnd *,unsigned __int32,class CXRect,int,class CButtonDrawTemplate,class CListWnd *); +EQLIB_OBJECT class CXRect CComboWnd::GetButtonRect(void)const; +EQLIB_OBJECT class CXRect CComboWnd::GetListRect(void)const; +EQLIB_OBJECT class CXRect CComboWnd::GetTextRect(void)const; +EQLIB_OBJECT class CXStr CComboWnd::GetCurChoiceText(void)const; +EQLIB_OBJECT int CComboWnd::GetCurChoice(void)const; +EQLIB_OBJECT int CComboWnd::GetItemCount(void); +EQLIB_OBJECT void CComboWnd::DeleteAll(void); +EQLIB_OBJECT void CComboWnd::InsertChoice(class CXStr *,unsigned long); +EQLIB_OBJECT void CComboWnd::InsertChoice(char *); +EQLIB_OBJECT void CComboWnd::SetChoice(int); +EQLIB_OBJECT void CComboWnd::SetColors(unsigned long,unsigned long,unsigned long); +// virtual +EQLIB_OBJECT CComboWnd::~CComboWnd(void); +EQLIB_OBJECT class CXSize CComboWnd::GetMinSize(void)const; +EQLIB_OBJECT int CComboWnd::Draw(void)const; +EQLIB_OBJECT int CComboWnd::HandleLButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CComboWnd::HitTest(class CXPoint,int *)const; +EQLIB_OBJECT int CComboWnd::OnMove(class CXRect); +EQLIB_OBJECT int CComboWnd::OnResize(int,int); +EQLIB_OBJECT int CComboWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CComboWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CComboWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CComboWnd::SetDrawTemplate(class CXWndDrawTemplate *); +}; + +class CCompassWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CCompassWnd::CCompassWnd(class CXWnd *); +EQLIB_OBJECT void CCompassWnd::Activate(void); +EQLIB_OBJECT void CCompassWnd::SenseHeading(void); +// virtual +EQLIB_OBJECT CCompassWnd::~CCompassWnd(void); +EQLIB_OBJECT int CCompassWnd::Draw(void)const; +EQLIB_OBJECT int CCompassWnd::OnProcessFrame(void); +//EQLIB_OBJECT void * CCompassWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CCompassWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CCompassWnd::Deactivate(void); +// protected +EQLIB_OBJECT static double const CCompassWnd::HI_SPEED; +EQLIB_OBJECT static double const CCompassWnd::LO_SPEED; +EQLIB_OBJECT void CCompassWnd::PickNewTarget(void); +EQLIB_OBJECT void CCompassWnd::SetSpeed(void); +// private +EQLIB_OBJECT void CCompassWnd::Init(void); +}; + +class CConfirmationDialog : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CConfirmationDialog::CConfirmationDialog(class CXWnd *); +EQLIB_OBJECT void CConfirmationDialog::Activate(int,unsigned int,char const *,int,int,int,int); +EQLIB_OBJECT void CConfirmationDialog::HandleButtonNoPressed(void); +EQLIB_OBJECT void CConfirmationDialog::HandleButtonOkPressed(void); +EQLIB_OBJECT void CConfirmationDialog::HandleButtonYesPressed(void); +EQLIB_OBJECT void CConfirmationDialog::ProcessNo(int); +EQLIB_OBJECT void CConfirmationDialog::ProcessYes(void); +EQLIB_OBJECT void CConfirmationDialog::SetNameApprovalData(char *,char *,int,int,char *); +// virtual +EQLIB_OBJECT CConfirmationDialog::~CConfirmationDialog(void); +EQLIB_OBJECT int CConfirmationDialog::Draw(void)const; +EQLIB_OBJECT int CConfirmationDialog::OnProcessFrame(void); +EQLIB_OBJECT int CConfirmationDialog::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CConfirmationDialog::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CConfirmationDialog::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CConfirmationDialog::Deactivate(void); +// private +EQLIB_OBJECT void CConfirmationDialog::ExpireCurrentDialog(void); +EQLIB_OBJECT void CConfirmationDialog::Init(void); +EQLIB_OBJECT void CConfirmationDialog::ResetFocusOnClose(void); +// Data members +/*0x15c*/ struct _CXWND *OutputText; +/*0x160*/ struct _CXWND *pYesButton; +/*0x164*/ struct _CXWND *pNoButton; +/*0x168*/ DWORD Unknown0x168; +/*0x16c*/ struct _CXWND *pOKButton; +/*0x170*/ BYTE Unknown0x170[0x18]; +/*0x188*/ +}; + +class CContainerMgr +{ +public: +EQLIB_OBJECT CContainerMgr::CContainerMgr(void); +EQLIB_OBJECT bool CContainerMgr::CloseAllContainers(void); +EQLIB_OBJECT class EQ_Item * CContainerMgr::GetWorldContainerItem(int); +EQLIB_OBJECT void CContainerMgr::ClearWorldContainerItems(void); +EQLIB_OBJECT void CContainerMgr::CloseContainer(class EQ_Container *,bool); +EQLIB_OBJECT void CContainerMgr::CloseEQContainer(class EQ_Container *); +EQLIB_OBJECT void CContainerMgr::OpenContainer(class EQ_Container *,int); +EQLIB_OBJECT void CContainerMgr::OpenWorldContainer(class EQ_Container *,unsigned long); +EQLIB_OBJECT void CContainerMgr::Process(void); +EQLIB_OBJECT void CContainerMgr::SetWorldContainerItem(class EQ_Item *,int); +// virtual +EQLIB_OBJECT CContainerMgr::~CContainerMgr(void); +//EQLIB_OBJECT void * CContainerMgr::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CContainerMgr::`vector deleting destructor'(unsigned int); +// private +EQLIB_OBJECT class CContainerWnd * CContainerMgr::GetFreeContainerWnd(void); +}; + +class CContainerWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CContainerWnd::CContainerWnd(class CXWnd *); +EQLIB_OBJECT void CContainerWnd::Activate(void); +EQLIB_OBJECT void CContainerWnd::CheckCloseable(void); +EQLIB_OBJECT void CContainerWnd::SetContainer(class EQ_Container *,int); +// virtual +EQLIB_OBJECT CContainerWnd::~CContainerWnd(void); +EQLIB_OBJECT int CContainerWnd::OnProcessFrame(void); +EQLIB_OBJECT int CContainerWnd::PostDraw(void)const; +EQLIB_OBJECT int CContainerWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CContainerWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CContainerWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CContainerWnd::Deactivate(void); +// private +EQLIB_OBJECT bool CContainerWnd::ContainsNoDrop(void); +EQLIB_OBJECT void CContainerWnd::HandleCombine(void); +EQLIB_OBJECT void CContainerWnd::Init(void); +}; + +class CContextMenu +{ +public: +EQLIB_OBJECT CContextMenu::CContextMenu(class CXWnd *,unsigned __int32,class CXRect); +EQLIB_OBJECT int CContextMenu::AddMenuItem(class CXStr,unsigned int,bool,unsigned long); +EQLIB_OBJECT int CContextMenu::AddSeparator(void); +EQLIB_OBJECT void CContextMenu::Activate(class CXPoint,int,int); +EQLIB_OBJECT void CContextMenu::CheckMenuItem(int,bool,bool); +EQLIB_OBJECT void CContextMenu::EnableMenuItem(int,bool); +EQLIB_OBJECT void CContextMenu::RemoveAllMenuItems(void); +// virtual +EQLIB_OBJECT CContextMenu::~CContextMenu(void); +EQLIB_OBJECT int CContextMenu::OnKillFocus(class CXWnd *); +//EQLIB_OBJECT void * CContextMenu::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CContextMenu::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CContextMenu::Deactivate(void); +}; + +class CContextMenuManager +{ +public: +EQLIB_OBJECT CContextMenuManager::CContextMenuManager(class CXWnd *,unsigned __int32,class CXRect); +EQLIB_OBJECT int CContextMenuManager::AddMenu(class CContextMenu *); +EQLIB_OBJECT int CContextMenuManager::GetDefaultMenuIndex(void); +EQLIB_OBJECT int CContextMenuManager::HandleWindowMenuCommands(class CXWnd *,int); +EQLIB_OBJECT int CContextMenuManager::PopupMenu(int,class CXPoint,class CXWnd *); +EQLIB_OBJECT int CContextMenuManager::RemoveMenu(int,bool); +EQLIB_OBJECT void CContextMenuManager::Flush(void); +EQLIB_OBJECT void CContextMenuManager::WarnDefaultMenu(class CXWnd *); +// virtual +EQLIB_OBJECT CContextMenuManager::~CContextMenuManager(void); +EQLIB_OBJECT int CContextMenuManager::HandleLButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CContextMenuManager::HandleRButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CContextMenuManager::HandleWheelButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CContextMenuManager::OnProcessFrame(void); +EQLIB_OBJECT int CContextMenuManager::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CContextMenuManager::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CContextMenuManager::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CContextMenuManager::Deactivate(void); +// private +EQLIB_OBJECT void CContextMenuManager::CreateDefaultMenu(void); +}; + +class CControlTemplate +{ +public: +EQLIB_OBJECT CControlTemplate::CControlTemplate(class CParamControl *); +// virtual +EQLIB_OBJECT CControlTemplate::~CControlTemplate(void); +//EQLIB_OBJECT void * CControlTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CControlTemplate::`vector deleting destructor'(unsigned int); +}; + +class CCursorAttachment +{ +public: +EQLIB_OBJECT CCursorAttachment::CCursorAttachment(class CXWnd *); +EQLIB_OBJECT bool CCursorAttachment::IsOkToActivate(int); +EQLIB_OBJECT bool CCursorAttachment::RemoveAttachment(void); +EQLIB_OBJECT void CCursorAttachment::Activate(class CTextureAnimation *,int,int,int); +// virtual +EQLIB_OBJECT CCursorAttachment::~CCursorAttachment(void); +EQLIB_OBJECT int CCursorAttachment::Draw(void)const; +EQLIB_OBJECT int CCursorAttachment::OnProcessFrame(void); +EQLIB_OBJECT int CCursorAttachment::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CCursorAttachment::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CCursorAttachment::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CCursorAttachment::Deactivate(void); +// private +EQLIB_OBJECT void CCursorAttachment::DrawButtonText(void)const; +EQLIB_OBJECT void CCursorAttachment::DrawQuantity(void)const; +EQLIB_OBJECT void CCursorAttachment::Init(void); +}; + +class CDIMap +{ +public: +EQLIB_OBJECT CDIMap::~CDIMap(void); +EQLIB_OBJECT CDIMap::CDIMap(void); +// private +EQLIB_OBJECT static char * CDIMap::mKeymapAltArray; +EQLIB_OBJECT static char * CDIMap::mKeymapArray; +EQLIB_OBJECT static char * CDIMap::mKeymapShiftArray; +EQLIB_OBJECT void CDIMap::LoadMappingFromFile(char *); +}; + +class CDisplay +{ +public: +EQLIB_OBJECT CDisplay::~CDisplay(void); +EQLIB_OBJECT CDisplay::CDisplay(struct HWND__ *); +EQLIB_OBJECT bool CDisplay::GenericSphereColl(float,float,float,float,float,float,float *,float *,float *,unsigned char); +EQLIB_OBJECT bool CDisplay::SlideSwitchLeftRight(class EQSwitch *,float,int,float); +EQLIB_OBJECT bool const CDisplay::GetWorldFilePath(char *,char const *); +EQLIB_OBJECT char * CDisplay::GetIniRaceName(int); +EQLIB_OBJECT class EQPlayer * CDisplay::GetNearestPlayerInView(float,bool); +EQLIB_OBJECT float CDisplay::FindZoneTopZ(float,float,float); +EQLIB_OBJECT float CDisplay::FixHeading(float); +EQLIB_OBJECT float CDisplay::GetFloorHeight(float,float,float); +EQLIB_OBJECT float CDisplay::HeadingDiff(float,float,float *); +EQLIB_OBJECT float CDisplay::PlayerDistance(class EQPlayer *,class EQPlayer *,float); +EQLIB_OBJECT float CDisplay::PlayerSimpleDistance(class EQPlayer *,class EQPlayer *,float); +EQLIB_OBJECT float CDisplay::SetActorBoundingRadius(struct T3D_tagACTORINSTANCE *,float,float); +EQLIB_OBJECT float CDisplay::SimpleDistance(float,float,float,float,float,float,float); +EQLIB_OBJECT float CDisplay::TrueDistance(float,float,float,float,float,float,float); +EQLIB_OBJECT int CDisplay::GetItemType(int); +EQLIB_OBJECT int CDisplay::GetNewPCIniFlag(int,int); +EQLIB_OBJECT int CDisplay::GetSkyTime(int *,int *); +EQLIB_OBJECT int CDisplay::is_3dON(void); +EQLIB_OBJECT int CDisplay::is_ParticleSystemON(void); +EQLIB_OBJECT int CDisplay::MoveMissile(class EQMissile *); +EQLIB_OBJECT int CDisplay::ReplaceCloakMaterials(int,struct T3D_HIERARCHICALSPRITEINSTANCE *,struct T3D_RGB *); +EQLIB_OBJECT int CDisplay::ReplaceMaterial(char *,char *,struct T3D_HIERARCHICALSPRITEINSTANCE *,struct T3D_RGB *,int); +EQLIB_OBJECT int CDisplay::SetBoneSpriteTint(struct T3D_DAG *,struct T3D_RGB *); +EQLIB_OBJECT int CDisplay::ShouldLoadNewPcModel(int,int); +EQLIB_OBJECT int CDisplay::TurnInfravisionEffectOff(void); +EQLIB_OBJECT int CDisplay::TurnInfravisionEffectOn(void); +EQLIB_OBJECT long CDisplay::SetUserRender(int); +EQLIB_OBJECT static char * CDisplay::DefaultUIPath; +EQLIB_OBJECT static char * CDisplay::UIPath; +EQLIB_OBJECT static int __cdecl CDisplay::WriteTextHD2(char const *text,int X,int Y,int color); +EQLIB_OBJECT static unsigned long __cdecl CDisplay::GetUserDefinedColor(int); +EQLIB_OBJECT static void __cdecl CDisplay::SetUserDefinedColor(int,int,int,int); +EQLIB_OBJECT struct T3D_POINTLIGHT * CDisplay::CreateLight(unsigned char,float,float,float,float); +EQLIB_OBJECT struct T3D_tagACTORINSTANCE * CDisplay::CreateActor(char *,float,float,float,float,float,float,bool,bool); +EQLIB_OBJECT struct T3D_tagACTORINSTANCE * CDisplay::GetClickedActor(unsigned long,unsigned long,unsigned long,void *,void *); +EQLIB_OBJECT unsigned char CDisplay::GetEnvironment(float,float,float,int *); +EQLIB_OBJECT unsigned char CDisplay::GetIntensity(unsigned char); +EQLIB_OBJECT unsigned char CDisplay::LoadBMPFile(void); +EQLIB_OBJECT unsigned char CDisplay::LoadNPCFromS3D(char *,char *,char *); +EQLIB_OBJECT unsigned char CDisplay::LoadWorldFile(char *,char *,int,unsigned char); +EQLIB_OBJECT unsigned int CDisplay::IsShield(int)const; +EQLIB_OBJECT void CDisplay::ActivateMainUI(bool); +EQLIB_OBJECT void CDisplay::ChangeVideoMode(void); +EQLIB_OBJECT void CDisplay::CheckForScreenModeToggle(void); +EQLIB_OBJECT void CDisplay::CleanUpDDraw(void); +EQLIB_OBJECT void CDisplay::ClearScreen(void); +EQLIB_OBJECT void CDisplay::CreatePlayerActor(class EQPlayer *); +EQLIB_OBJECT void CDisplay::DDrawUpdateDisplay(void); +EQLIB_OBJECT void CDisplay::DeactivateMainUI(void); +EQLIB_OBJECT void CDisplay::default_cameras(void); +EQLIB_OBJECT void CDisplay::DefineSoloMode(void); +EQLIB_OBJECT void CDisplay::DeleteActor(struct T3D_tagACTORINSTANCE *); +EQLIB_OBJECT void CDisplay::DeleteLight(struct T3D_POINTLIGHT *); +EQLIB_OBJECT void CDisplay::DeleteParticleCloudInstance(struct T3D_PARTICLECLOUDINSTANCE * *); +EQLIB_OBJECT void CDisplay::GetOnActor(struct T3D_tagACTORINSTANCE *,class EQPlayer *); +EQLIB_OBJECT void CDisplay::HandleMaterial(class EQ_PC *,int,class EQ_Item *,class EQ_Item *); +EQLIB_OBJECT void CDisplay::hideGrassObjects(void); +EQLIB_OBJECT void CDisplay::InitCharSelectUI(void); +EQLIB_OBJECT void CDisplay::InitCommonLights(void); +EQLIB_OBJECT void CDisplay::InitDDraw(void); +EQLIB_OBJECT void CDisplay::InitEverQuestLocale(EQLocalizeLanguage); +EQLIB_OBJECT void CDisplay::InitUserDefinedColors(void); +EQLIB_OBJECT void CDisplay::InitWorld(void); +EQLIB_OBJECT void CDisplay::KeyMapUpdated(void); +EQLIB_OBJECT void CDisplay::LightningStrike(void); +EQLIB_OBJECT void CDisplay::loadGrassObjects(char *); +EQLIB_OBJECT void CDisplay::MoveLight(struct T3D_POINTLIGHT *,struct _physicsinfo *); +EQLIB_OBJECT void CDisplay::MoveLocalPlayerToSafeCoords(void); +EQLIB_OBJECT void CDisplay::NewUIProcessEscape(void); +EQLIB_OBJECT void CDisplay::PlaySoundAtLocation(float,float,float,int); +EQLIB_OBJECT void CDisplay::ProcessCloud(void); +EQLIB_OBJECT void CDisplay::ProcessEffects(void); +EQLIB_OBJECT void CDisplay::ProcessParticleEmitter(class EQSwitch *); +EQLIB_OBJECT void CDisplay::ProcessSky(void); +EQLIB_OBJECT void CDisplay::ProcessSwitches(void); +EQLIB_OBJECT void CDisplay::ProcessWeather(void); +EQLIB_OBJECT void CDisplay::RealRender_World(void); +EQLIB_OBJECT void CDisplay::ReloadUI(bool); +EQLIB_OBJECT void CDisplay::Render_MinWorld(void); +EQLIB_OBJECT void CDisplay::Render_World(void); +EQLIB_OBJECT void CDisplay::ResetRenderWindow(void); +EQLIB_OBJECT void CDisplay::SetActorScaleFactor(struct T3D_tagACTORINSTANCE *,float,unsigned char); +EQLIB_OBJECT void CDisplay::SetActorSpriteTint(struct _EQRGB *,struct T3D_tagACTORINSTANCE *); +EQLIB_OBJECT void CDisplay::SetActorUserData(struct T3D_tagACTORINSTANCE *,void *); +EQLIB_OBJECT void CDisplay::SetActorYon(float); +EQLIB_OBJECT void CDisplay::SetAmbientLight(float); +EQLIB_OBJECT void CDisplay::SetCCreateCamera(int); +EQLIB_OBJECT void CDisplay::SetDayPeriod(unsigned char); +EQLIB_OBJECT void CDisplay::SetFog(bool,float,float,unsigned char,unsigned char,unsigned char); +EQLIB_OBJECT void CDisplay::SetGammaCorrection(float); +EQLIB_OBJECT void CDisplay::SetGenericEnvironment(void); +EQLIB_OBJECT void CDisplay::SetPCloudDensity(int); +EQLIB_OBJECT void CDisplay::SetSkyBackground(void); +EQLIB_OBJECT void CDisplay::SetSkyLayer(int); +EQLIB_OBJECT void CDisplay::SetSpecialEnvironment(enum EnvironmentType); +EQLIB_OBJECT void CDisplay::SetSunLight(void); +EQLIB_OBJECT void CDisplay::SetupEmitterEnvironment(void); +EQLIB_OBJECT void CDisplay::SetupEQPlayers(void); +EQLIB_OBJECT void CDisplay::SetViewActor(struct T3D_tagACTORINSTANCE *); +EQLIB_OBJECT void CDisplay::SetViewActorByName(char *); +EQLIB_OBJECT void CDisplay::SetViewAngle(int); +EQLIB_OBJECT void CDisplay::SetYon(float); +EQLIB_OBJECT void CDisplay::ShowDisplay(void); +EQLIB_OBJECT void CDisplay::SpurtBloodOnDag(struct T3D_DAG *); +EQLIB_OBJECT void CDisplay::StartWeather(int,unsigned char); +EQLIB_OBJECT void CDisplay::StartWorldDisplay(EQZoneIndex); +EQLIB_OBJECT void CDisplay::StartWorldDisplay_Bailout(char const *); +EQLIB_OBJECT void CDisplay::StopWeather(int,unsigned char); +EQLIB_OBJECT void CDisplay::StopWorldDisplay(void); +EQLIB_OBJECT void CDisplay::SwitchToDefaultCameraMode(void); +EQLIB_OBJECT void CDisplay::ToggleCharacterNameSprites(bool); +EQLIB_OBJECT void CDisplay::ToggleNpcNameSprites(bool); +EQLIB_OBJECT void CDisplay::ToggleView(void); +EQLIB_OBJECT void CDisplay::UpdateCameraAfterModeSwitch(void); +EQLIB_OBJECT void CDisplay::updateGrassObjects(void); +EQLIB_OBJECT void CDisplay::UpdateMobileEmitterLocations(void); +EQLIB_OBJECT void CDisplay::FreeAllItemLists(void); +// private +EQLIB_OBJECT struct T3D_HIERARCHICALSPRITEINSTANCE * CDisplay::dupActorHierarchicalSprite(struct T3D_tagACTORINSTANCE *); +EQLIB_OBJECT void CDisplay::CleanCharSelectUI(void); +EQLIB_OBJECT void CDisplay::CleanGameUI(void); +EQLIB_OBJECT void CDisplay::CleanUpNewUI(void); +EQLIB_OBJECT void CDisplay::InitGameUI(void); +EQLIB_OBJECT void CDisplay::InitNewUI(void); +}; + +class CEditBaseWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT void CEditBaseWnd::SetMaxChars(int); +EQLIB_OBJECT void CEditBaseWnd::SetSel(int,int); +// virtual +EQLIB_OBJECT CEditBaseWnd::~CEditBaseWnd(void); +EQLIB_OBJECT int CEditBaseWnd::OnKillFocus(class CXWnd *); +//EQLIB_OBJECT void * CEditBaseWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CEditBaseWnd::`vector deleting destructor'(unsigned int); +}; + +class CEditboxTemplate +{ +public: +EQLIB_OBJECT CEditboxTemplate::CEditboxTemplate(class CParamEditbox *); +// virtual +EQLIB_OBJECT CEditboxTemplate::~CEditboxTemplate(void); +//EQLIB_OBJECT void * CEditboxTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CEditboxTemplate::`vector deleting destructor'(unsigned int); +}; + +class CEditLabelWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CEditLabelWnd::CEditLabelWnd(class CXWnd *); +EQLIB_OBJECT class CXStr CEditLabelWnd::GetLabelText(void); +EQLIB_OBJECT void CEditLabelWnd::Activate(class CXWnd *,char *,int,unsigned long); +// virtual +EQLIB_OBJECT CEditLabelWnd::~CEditLabelWnd(void); +EQLIB_OBJECT int CEditLabelWnd::OnProcessFrame(void); +EQLIB_OBJECT int CEditLabelWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CEditLabelWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CEditLabelWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CEditLabelWnd::Deactivate(void); +}; + +class CEditWnd : public CEditBaseWnd +{ +public: +EQLIB_OBJECT CEditWnd::CEditWnd(class CXWnd *,unsigned __int32,class CXRect,unsigned __int32); +EQLIB_OBJECT class CXPoint CEditWnd::GetCharIndexPt(int)const; +EQLIB_OBJECT class CXPoint CEditWnd::GetSelEndPt(void)const; +EQLIB_OBJECT class CXPoint CEditWnd::GetSelStartPt(void)const; +EQLIB_OBJECT class CXStr CEditWnd::GetSTMLSafeText(void); +EQLIB_OBJECT int CEditWnd::ConvertIndexPrintableToTagged(int); +EQLIB_OBJECT int CEditWnd::ConvertIndexTaggedToPrintable(int); +EQLIB_OBJECT int CEditWnd::GetLineForPrintableChar(int)const; +EQLIB_OBJECT int CEditWnd::GetLineLength(int)const; +EQLIB_OBJECT int CEditWnd::SelectableCharFromPoint(class CXPoint)const; +EQLIB_OBJECT void CEditWnd::AddItemTag(int,char *,int); +EQLIB_OBJECT void CEditWnd::CalculateScrollRange(void); +EQLIB_OBJECT void CEditWnd::EnsureCaretVisible(void); +EQLIB_OBJECT void CEditWnd::ReplaceSelection(char,bool); +EQLIB_OBJECT void CEditWnd::ReplaceSelection(class CXStr,bool); +EQLIB_OBJECT void CEditWnd::SetEditable(bool); +// virtual +EQLIB_OBJECT CEditWnd::~CEditWnd(void); +EQLIB_OBJECT class CXPoint CEditWnd::GetCaretPt(void)const; +EQLIB_OBJECT class CXPoint CEditWnd::PointFromPrintableChar(int)const; +EQLIB_OBJECT class CXStr CEditWnd::GetDisplayString(void)const; +EQLIB_OBJECT class CXStr CEditWnd::GetWindowTextA(void)const; +EQLIB_OBJECT int CEditWnd::Draw(void)const; +EQLIB_OBJECT int CEditWnd::DrawCaret(void)const; +EQLIB_OBJECT int CEditWnd::DrawMultiline(void)const; +EQLIB_OBJECT int CEditWnd::HandleKeyboardMsg(unsigned __int32,unsigned __int32,bool); +EQLIB_OBJECT int CEditWnd::HandleLButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CEditWnd::HandleLButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CEditWnd::HandleMouseMove(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CEditWnd::OnKillFocus(class CXWnd *); +EQLIB_OBJECT int CEditWnd::OnMove(class CXRect); +EQLIB_OBJECT int CEditWnd::OnResize(int,int); +EQLIB_OBJECT int CEditWnd::OnSetFocus(class CXWnd *); +EQLIB_OBJECT int CEditWnd::ResetWnd(void); +//EQLIB_OBJECT void * CEditWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CEditWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CEditWnd::SetWindowTextA(class CXStr); +// protected +EQLIB_OBJECT static class CDIMap CEditWnd::m_mapKeys; +EQLIB_OBJECT virtual int CEditWnd::GetHorzOffset(void)const; +EQLIB_OBJECT void CEditWnd::FillIndexArray(class CXStr)const; +EQLIB_OBJECT void CEditWnd::FilterInputStr(class CXStr &); +EQLIB_OBJECT void CEditWnd::ProcessText(void); +}; + +class CEQSuiteTextureLoader +{ +public: +EQLIB_OBJECT CEQSuiteTextureLoader::~CEQSuiteTextureLoader(void); +EQLIB_OBJECT CEQSuiteTextureLoader::CEQSuiteTextureLoader(void); +EQLIB_OBJECT struct T3D_tagBMINFO * CEQSuiteTextureLoader::GetTexture(class CUITextureInfo const &); +EQLIB_OBJECT unsigned int CEQSuiteTextureLoader::CreateTexture(class CUITextureInfo const &); +EQLIB_OBJECT void CEQSuiteTextureLoader::UnloadAllTextures(void); +}; + +class CEverQuest +{ +public: +EQLIB_OBJECT CEverQuest::~CEverQuest(void); +EQLIB_OBJECT CEverQuest::CEverQuest(struct HWND__ *); +EQLIB_OBJECT bool CEverQuest::IsInTypingMode(void); +EQLIB_OBJECT bool CEverQuest::IsOkToTransact(void); +EQLIB_OBJECT bool CEverQuest::ReadClientINIBool(char *,char *,bool); +EQLIB_OBJECT bool CEverQuest::ReadUIINIBool(char *,char *,bool); +EQLIB_OBJECT char * CEverQuest::GetBodyTypeDesc(int); +EQLIB_OBJECT char * CEverQuest::GetClassDesc(int); +EQLIB_OBJECT char * CEverQuest::GetClassThreeLetterCode(int); +EQLIB_OBJECT char * CEverQuest::GetDeityDesc(int); +EQLIB_OBJECT char * CEverQuest::GetInnateDesc(int); +EQLIB_OBJECT char * CEverQuest::GetItemClassDesc(int); +EQLIB_OBJECT char * CEverQuest::GetLangDesc(int); +EQLIB_OBJECT char * CEverQuest::GetRaceDesc(int); +EQLIB_OBJECT char * CEverQuest::GetSingleMessage(unsigned __int32,int,int *,char *); +EQLIB_OBJECT char * CEverQuest::GrabFirstWord(char *,char *); +EQLIB_OBJECT char * CEverQuest::GrabFirstWord2(char *,char *,int); +EQLIB_OBJECT char * CEverQuest::ReadClientINIString(char *,char *,char *,char *,int); +EQLIB_OBJECT char * CEverQuest::ReadUIINIString(char *,char *,char *,char *,int); +EQLIB_OBJECT char * CEverQuest::stripName(char *); +EQLIB_OBJECT char * CEverQuest::StripShipName(char *,char *); +EQLIB_OBJECT char * CEverQuest::trimName(char *); +EQLIB_OBJECT class EQPlayer * CEverQuest::ClickedPlayer(int,int); +EQLIB_OBJECT class EQSwitch * CEverQuest::ClickedSwitch(int,int); +EQLIB_OBJECT enum ZONE_REQ_STATUS CEverQuest::IsZoneAvailable(char *,EQZoneIndex,enum ZONE_REQ_REASON); +EQLIB_OBJECT float CEverQuest::GetMaxLightRadius(void); +EQLIB_OBJECT float CEverQuest::ReadClientINIFloat(char *,char *,float); +EQLIB_OBJECT int CEverQuest::BeingIgnored(char *); +EQLIB_OBJECT int CEverQuest::DoLogin(struct HWND__ *,struct HINSTANCE__ *); +EQLIB_OBJECT int CEverQuest::GetCombatSound(class EQPlayer *,class EQPlayer *); +EQLIB_OBJECT int CEverQuest::GetCurrentLanguage(void); +EQLIB_OBJECT int CEverQuest::HandleItems(void *,int); +EQLIB_OBJECT int CEverQuest::IsFriend(char const *); +EQLIB_OBJECT int CEverQuest::IsValidName(char *); +EQLIB_OBJECT int CEverQuest::LootCorpse(class EQPlayer *,int); +EQLIB_OBJECT int CEverQuest::MoveMoney(int,int,int,int,int,bool); +EQLIB_OBJECT int CEverQuest::msgStartIcon(void *); +EQLIB_OBJECT int CEverQuest::msgStartIeq(void *); +EQLIB_OBJECT int CEverQuest::msgStartInotes(void *); +EQLIB_OBJECT int CEverQuest::ProcessMBox(void); +EQLIB_OBJECT int CEverQuest::ReadClientINIInt(char *,char *,int); +EQLIB_OBJECT int CEverQuest::ReadUIINIInt(char *,char *,int); +EQLIB_OBJECT int CEverQuest::TypingMode(void); +EQLIB_OBJECT unsigned char CEverQuest::HandleWorldMessage(struct connection_t *,unsigned __int32,char *,unsigned __int32); +EQLIB_OBJECT unsigned char CEverQuest::IFoundMyVehicle(void); +EQLIB_OBJECT void __cdecl CEverQuest::DoLoadScreenProgressBar(int,char const *,...); +EQLIB_OBJECT void CEverQuest::ApplyPoison(unsigned long); +EQLIB_OBJECT void CEverQuest::Camp(void); +EQLIB_OBJECT void CEverQuest::CancelSneakHide(void); +EQLIB_OBJECT void CEverQuest::ChatServerConnect(char *,int,char *,char *); +EQLIB_OBJECT void CEverQuest::ChatServerDisconnect(void); +EQLIB_OBJECT void CEverQuest::ChatServerGiveTime(void); +EQLIB_OBJECT void CEverQuest::ChatServerMessage(char *); +EQLIB_OBJECT void CEverQuest::ChatServerNotificationAdd(bool,char *,char *,int); +EQLIB_OBJECT void CEverQuest::ChatServerNotificationFlush(void); +EQLIB_OBJECT void CEverQuest::CleanupBadFiles(void); +EQLIB_OBJECT void CEverQuest::clr_chat_input(void); +EQLIB_OBJECT void CEverQuest::Consider(class EQPlayer *,void *); +EQLIB_OBJECT void CEverQuest::CopyFirstWord(char *,char *); +EQLIB_OBJECT void CEverQuest::CreateDataSubdirectories(void); +EQLIB_OBJECT void CEverQuest::CreateFilenameServerCode(char *); +EQLIB_OBJECT void CEverQuest::CreateIniFilenames(void); +EQLIB_OBJECT void CEverQuest::CreateInitialActors(void); +EQLIB_OBJECT void CEverQuest::DeacSpellScreen(void); +EQLIB_OBJECT void CEverQuest::Disband(void); +EQLIB_OBJECT void CEverQuest::DisplayScreen(char *); +EQLIB_OBJECT void CEverQuest::DoCharacterSelection(void); +EQLIB_OBJECT void CEverQuest::doInspect(class EQPlayer *); +EQLIB_OBJECT void CEverQuest::doInvite(unsigned __int32,char *); +EQLIB_OBJECT void CEverQuest::DoLoadScreen(int); +EQLIB_OBJECT void CEverQuest::doLoot(void); +EQLIB_OBJECT void CEverQuest::DoMainLoop(struct HWND__ *); +EQLIB_OBJECT void CEverQuest::DoNewCharacterCreation(void); +EQLIB_OBJECT void CEverQuest::DoPercentConvert(char *,bool); +EQLIB_OBJECT void CEverQuest::DoSplit(char *); +EQLIB_OBJECT void CEverQuest::DoTellWindow(char *,char *,char *,void *,int,bool); +EQLIB_OBJECT void CEverQuest::doUnInvite(char *); +EQLIB_OBJECT void CEverQuest::DropHeldItemOnGround(int); +EQLIB_OBJECT void CEverQuest::DropHeldMoneyOnGround(int); +EQLIB_OBJECT void CEverQuest::DropItemOrMoneyOnPlayer(class EQPlayer *); +EQLIB_OBJECT void CEverQuest::dsp_chat(char const *); +EQLIB_OBJECT void CEverQuest::dsp_chat(char const *,int,bool,bool); +EQLIB_OBJECT void CEverQuest::dsp_chat(char const *,int,bool); +EQLIB_OBJECT void CEverQuest::Emote(void); +EQLIB_OBJECT void CEverQuest::EnterZone(struct HWND__ *); +EQLIB_OBJECT void CEverQuest::Follow(void); +EQLIB_OBJECT void CEverQuest::FreeSwitches(void); +EQLIB_OBJECT void CEverQuest::GetSndDriver(void); +EQLIB_OBJECT void CEverQuest::GetZoneInfoFromNetwork(char *); +EQLIB_OBJECT void CEverQuest::GuildDelete(void); +EQLIB_OBJECT void CEverQuest::GuildInvite(char *,char *); +EQLIB_OBJECT void CEverQuest::GuildLeader(char *); +EQLIB_OBJECT void CEverQuest::GuildPeace(char *); +EQLIB_OBJECT void CEverQuest::GuildRemove(char *); +EQLIB_OBJECT void CEverQuest::GuildSay(char *); +EQLIB_OBJECT void CEverQuest::GuildStatus(char *); +EQLIB_OBJECT void CEverQuest::GuildWar(char *,int); +EQLIB_OBJECT void CEverQuest::InitCommands(void); +EQLIB_OBJECT void CEverQuest::initCustom(void); +EQLIB_OBJECT void CEverQuest::InterpretCmd(class EQPlayer *,char *); +EQLIB_OBJECT void CEverQuest::Invite(int); +EQLIB_OBJECT void CEverQuest::InviteOk(char *); +EQLIB_OBJECT void CEverQuest::IssueLfgGroupQuery(struct LfgGroupQuery *); +EQLIB_OBJECT void CEverQuest::IssueLfgPlayerQuery(struct LfgPlayerQuery *); +EQLIB_OBJECT void CEverQuest::IssuePetCommand(enum PetCommandType,int); +EQLIB_OBJECT void CEverQuest::Kill(char *,char *); +EQLIB_OBJECT void CEverQuest::LeaveBankMode(bool); +EQLIB_OBJECT void CEverQuest::LeaveGuildMaster(void); +EQLIB_OBJECT void CEverQuest::LeftClickedOnPlayer(class EQPlayer *); +EQLIB_OBJECT void CEverQuest::LMouseDown(int,int); +EQLIB_OBJECT void CEverQuest::LMouseUp(int,int); +EQLIB_OBJECT void CEverQuest::loadCustom(void); +EQLIB_OBJECT void CEverQuest::loadCustomFromINI(char *); +EQLIB_OBJECT void CEverQuest::loadOptions(void); +EQLIB_OBJECT void CEverQuest::loadSoundsGame(void); +EQLIB_OBJECT void CEverQuest::LoadStringTables(void); +EQLIB_OBJECT void CEverQuest::LoadSwitchesNonAvatar(EQZoneIndex); +EQLIB_OBJECT void CEverQuest::LocalDeath(struct _EQPlayerDeath *,unsigned char); +EQLIB_OBJECT void CEverQuest::MouseWheelScrolled(int); +EQLIB_OBJECT void CEverQuest::MoveToZone(int,char*,int,int,float,float,float,int); +EQLIB_OBJECT void CEverQuest::MoveToZone(char *,char *,int,enum ZONE_REQ_REASON); +EQLIB_OBJECT void CEverQuest::MoveToZone(EQZoneIndex,char *,int,enum ZONE_REQ_REASON); +EQLIB_OBJECT void CEverQuest::PrepareLocalPCForRepop(void); +EQLIB_OBJECT void CEverQuest::ProcessControls(void); +EQLIB_OBJECT void CEverQuest::ProcessGame(struct HWND__ *,struct HINSTANCE__ *); +EQLIB_OBJECT void CEverQuest::ProcessLocalPCIni(int); +EQLIB_OBJECT void CEverQuest::procMouse(int); +EQLIB_OBJECT void CEverQuest::RemoveCharacterOptionFile(char *); +EQLIB_OBJECT void CEverQuest::ReportDeath(struct _EQPlayerDeath *); +EQLIB_OBJECT void CEverQuest::ReportSuccessfulHit(struct _EQSuccessfulHit *,unsigned char,int); +EQLIB_OBJECT void CEverQuest::reqChannel(void); +EQLIB_OBJECT void CEverQuest::ResetVisionRGBs(void); +EQLIB_OBJECT void CEverQuest::RightClickedOnPlayer(class EQPlayer *, int); +EQLIB_OBJECT void CEverQuest::RMouseDown(int,int); +EQLIB_OBJECT void CEverQuest::RMouseUp(int,int); +EQLIB_OBJECT void CEverQuest::SaveCamerasToINI(void); +EQLIB_OBJECT void CEverQuest::saveCustom(void); +EQLIB_OBJECT void CEverQuest::saveOptions(void); +EQLIB_OBJECT void CEverQuest::saveOptions2(void); +EQLIB_OBJECT void CEverQuest::SavePC(int,int,unsigned char); +EQLIB_OBJECT void CEverQuest::SavePCForce(int); +EQLIB_OBJECT void CEverQuest::send_auction(void); +EQLIB_OBJECT void CEverQuest::send_broadcast(void); +EQLIB_OBJECT void CEverQuest::send_chat(void); +EQLIB_OBJECT void CEverQuest::send_gsay(void); +EQLIB_OBJECT void CEverQuest::send_ooc(void); +EQLIB_OBJECT void CEverQuest::send_petition(void); +EQLIB_OBJECT void CEverQuest::send_private(void); +EQLIB_OBJECT void CEverQuest::send_shout(void); +EQLIB_OBJECT void CEverQuest::send_social(int,char *,char *); +EQLIB_OBJECT void CEverQuest::send_tell(char *,char *); +EQLIB_OBJECT void CEverQuest::send_update_filters(void); +EQLIB_OBJECT void CEverQuest::SendLightInfo(class EQPlayer *,unsigned char); +EQLIB_OBJECT void CEverQuest::SendNewText(int,char *,char *); +EQLIB_OBJECT void CEverQuest::SetDefaultDamageDescByRace(char *,int,unsigned char); +EQLIB_OBJECT void CEverQuest::SetDefaultGameValues(void); +EQLIB_OBJECT void CEverQuest::SetGameState(int); +EQLIB_OBJECT void CEverQuest::SetLfgGroupStatus(struct LfgGroupStatus *); +EQLIB_OBJECT void CEverQuest::SetLfgPlayerStatus(struct LfgPlayerStatus *); +EQLIB_OBJECT void CEverQuest::SetPlayerAppearanceFromPInfo(class EQPlayer *,int,bool); +EQLIB_OBJECT void CEverQuest::SetTimedFog(int); +EQLIB_OBJECT void CEverQuest::SetupCharSelectCamera(void); +EQLIB_OBJECT void CEverQuest::Sit(void); +EQLIB_OBJECT void CEverQuest::SortSpellLoadouts(void); +EQLIB_OBJECT void CEverQuest::StartCasting(void *); +EQLIB_OBJECT void CEverQuest::StartNetworkGame(struct HWND__ *,struct HINSTANCE__ *,char *); +EQLIB_OBJECT void CEverQuest::Surname(char *); +EQLIB_OBJECT void CEverQuest::ToggleAutoSplit(void); +EQLIB_OBJECT void CEverQuest::UpdateMyAppearance(void); +EQLIB_OBJECT void CEverQuest::UseCharge(unsigned long); +EQLIB_OBJECT void CEverQuest::WhatTimeIsIt(void); +EQLIB_OBJECT void CEverQuest::Who(char *); +EQLIB_OBJECT void CEverQuest::WriteBoolToClientINI(bool,char *,char *); +EQLIB_OBJECT void CEverQuest::WriteBoolToUIINI(bool,char *,char *); +EQLIB_OBJECT void CEverQuest::WriteFloatToClientINI(float,char *,char *); +EQLIB_OBJECT void CEverQuest::WriteIntToClientINI(int,char *,char *); +EQLIB_OBJECT void CEverQuest::WriteIntToUIINI(int,char *,char *); +EQLIB_OBJECT void CEverQuest::WriteStringToClientINI(char *,char *,char *); +EQLIB_OBJECT void CEverQuest::WriteStringToUIINI(char *,char *,char *); +// virtual +EQLIB_OBJECT void CEverQuest::CshOnBuddyStatusChange(char *,int BuddyStatus); +EQLIB_OBJECT void CEverQuest::CshOnChannelListChange(void); +EQLIB_OBJECT void CEverQuest::CshOnMessage(char *,char *,int,char *,bool); +EQLIB_OBJECT void CEverQuest::CshOnPlayerEntering(char *,int,char *); +EQLIB_OBJECT void CEverQuest::CshOnPlayerLeaving(char *,int,char *); +}; + +class CExploreModeWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CExploreModeWnd::CExploreModeWnd(class CXWnd *); +EQLIB_OBJECT void CExploreModeWnd::Activate(void); +// virtual +EQLIB_OBJECT CExploreModeWnd::~CExploreModeWnd(void); +//EQLIB_OBJECT void * CExploreModeWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CExploreModeWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CExploreModeWnd::Deactivate(void); +}; + +class CFacePick : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CFacePick::CFacePick(class CXWnd *); +EQLIB_OBJECT void CFacePick::Activate(void); +EQLIB_OBJECT void CFacePick::SetFaceSelectionsFromPlayer(void); +// virtual +EQLIB_OBJECT CFacePick::~CFacePick(void); +EQLIB_OBJECT int CFacePick::Draw(void)const; +EQLIB_OBJECT int CFacePick::OnProcessFrame(void); +EQLIB_OBJECT int CFacePick::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CFacePick::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CFacePick::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CFacePick::Deactivate(void); +// private +EQLIB_OBJECT void CFacePick::CycleThroughFHEB(int,int); +EQLIB_OBJECT void CFacePick::Init(void); +EQLIB_OBJECT void CFacePick::ShowButtonGroup(int,bool); +}; + +class CFeedbackWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CFeedbackWnd::CFeedbackWnd(class CXWnd *); +EQLIB_OBJECT void CFeedbackWnd::Activate(void); +// virtual +EQLIB_OBJECT CFeedbackWnd::~CFeedbackWnd(void); +EQLIB_OBJECT int CFeedbackWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CFeedbackWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CFeedbackWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CFeedbackWnd::Deactivate(void); +}; + +class CFileSelectionWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CFileSelectionWnd::CFileSelectionWnd(class CXWnd *); +EQLIB_OBJECT class CXStr CFileSelectionWnd::GetSelectedFile(int); +EQLIB_OBJECT int CFileSelectionWnd::GetSelectedFileCount(void); +EQLIB_OBJECT void CFileSelectionWnd::Activate(class CXWnd *,int); +EQLIB_OBJECT void CFileSelectionWnd::Callback(bool); +// virtual +EQLIB_OBJECT CFileSelectionWnd::~CFileSelectionWnd(void); +EQLIB_OBJECT int CFileSelectionWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CFileSelectionWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CFileSelectionWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CFileSelectionWnd::Deactivate(void); +// private +EQLIB_OBJECT bool CFileSelectionWnd::DirectoryEmpty(struct IShellFolder *,struct _ITEMIDLIST *); +EQLIB_OBJECT unsigned long CFileSelectionWnd::GetPath(struct IShellFolder *,struct _ITEMIDLIST *,bool,class CXStr &); +EQLIB_OBJECT void CFileSelectionWnd::ClearFileList(void); +EQLIB_OBJECT void CFileSelectionWnd::GoSubdirectory(struct _ITEMIDLIST *); +EQLIB_OBJECT void CFileSelectionWnd::MakeFilePath(void); +EQLIB_OBJECT void CFileSelectionWnd::UpdateButtons(void); +EQLIB_OBJECT void CFileSelectionWnd::UpdateFileList(void); +}; + +class CFriendsWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CFriendsWnd::CFriendsWnd(class CXWnd *); +EQLIB_OBJECT void CFriendsWnd::Activate(void); +EQLIB_OBJECT void CFriendsWnd::UpdateFriendsList(void); +EQLIB_OBJECT void CFriendsWnd::UpdateIgnoreList(void); +// virtual +EQLIB_OBJECT CFriendsWnd::~CFriendsWnd(void); +EQLIB_OBJECT int CFriendsWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CFriendsWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CFriendsWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CFriendsWnd::Deactivate(void); +// protected +EQLIB_OBJECT void CFriendsWnd::AddFriend(void); +EQLIB_OBJECT void CFriendsWnd::AddIgnore(void); +EQLIB_OBJECT void CFriendsWnd::UpdateButtons(void); +}; + +class CGaugeDrawTemplate +{ +public: +EQLIB_OBJECT CGaugeDrawTemplate::~CGaugeDrawTemplate(void); +}; + +class CGaugeTemplate +{ +public: +EQLIB_OBJECT CGaugeTemplate::CGaugeTemplate(class CParamGauge *); +// virtual +EQLIB_OBJECT CGaugeTemplate::~CGaugeTemplate(void); +//EQLIB_OBJECT void * CGaugeTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CGaugeTemplate::`vector deleting destructor'(unsigned int); +}; + +class CGaugeWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CGaugeWnd::CGaugeWnd(class CXWnd *,unsigned __int32,class CXRect,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,int,unsigned long,unsigned long,bool,int,int,int,int); +EQLIB_OBJECT class CXRect CGaugeWnd::CalcFillRect(class CXRect *,int)const; +EQLIB_OBJECT class CXRect CGaugeWnd::CalcLinesFillRect(class CXRect *,int)const; +EQLIB_OBJECT void CGaugeWnd::SpecialToolTip(void); +// virtual +EQLIB_OBJECT CGaugeWnd::~CGaugeWnd(void); +EQLIB_OBJECT int CGaugeWnd::Draw(void)const; +EQLIB_OBJECT int CGaugeWnd::HandleLButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CGaugeWnd::OnProcessFrame(void); +//EQLIB_OBJECT void * CGaugeWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CGaugeWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CGaugeWnd::SetAttributesFromSidl(class CParamScreenPiece *); +}; + +class CGemsGameWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CGemsGameWnd::CGemsGameWnd(class CXWnd *); +EQLIB_OBJECT void CGemsGameWnd::Activate(void); +EQLIB_OBJECT void CGemsGameWnd::MoveCurBlock(int); +// virtual +EQLIB_OBJECT CGemsGameWnd::~CGemsGameWnd(void); +EQLIB_OBJECT int CGemsGameWnd::HandleLButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CGemsGameWnd::OnProcessFrame(void); +EQLIB_OBJECT int CGemsGameWnd::PostDraw(void)const; +EQLIB_OBJECT int CGemsGameWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CGemsGameWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CGemsGameWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CGemsGameWnd::Deactivate(void); +// private +EQLIB_OBJECT bool CGemsGameWnd::BadSpecial(int)const; +EQLIB_OBJECT bool CGemsGameWnd::LegalBlockMove(int,int,int,int,bool); +EQLIB_OBJECT int CGemsGameWnd::GetRndBlockImage(void); +EQLIB_OBJECT void CGemsGameWnd::ActivateSpecialMode(int); +EQLIB_OBJECT void CGemsGameWnd::AdvanceToNextWave(void); +EQLIB_OBJECT void CGemsGameWnd::CheckForMatches(int,int); +EQLIB_OBJECT void CGemsGameWnd::CheckForNewHighScore(void); +EQLIB_OBJECT void CGemsGameWnd::ClearBlock(struct _GemsBlock *); +EQLIB_OBJECT void CGemsGameWnd::ClearHighScores(void); +EQLIB_OBJECT void CGemsGameWnd::DoMatchScore(int); +EQLIB_OBJECT void CGemsGameWnd::DrawSpellGem(int,class CXRect,int,bool)const; +EQLIB_OBJECT void CGemsGameWnd::GetNextBlock(void); +EQLIB_OBJECT void CGemsGameWnd::Init(void); +EQLIB_OBJECT void CGemsGameWnd::MakeBlockDrop(int,int,int); +EQLIB_OBJECT void CGemsGameWnd::MarkHigherBlocksFalling(int,int); +EQLIB_OBJECT void CGemsGameWnd::ProcessMatches(int); +EQLIB_OBJECT void CGemsGameWnd::ProcessMoveCurBlock(int); +EQLIB_OBJECT void CGemsGameWnd::ReadHighScores(void); +EQLIB_OBJECT void CGemsGameWnd::Restart(void); +EQLIB_OBJECT void CGemsGameWnd::SetNextUpdate(void); +EQLIB_OBJECT void CGemsGameWnd::SetPause(bool); +EQLIB_OBJECT void CGemsGameWnd::TogglePause(void); +EQLIB_OBJECT void CGemsGameWnd::Update(void); +EQLIB_OBJECT void CGemsGameWnd::UpdateDisplay(void); +EQLIB_OBJECT void CGemsGameWnd::WriteHighScores(void); +}; + +class CGiveWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CGiveWnd::CGiveWnd(class CXWnd *); +EQLIB_OBJECT void CGiveWnd::Activate(void); +EQLIB_OBJECT void CGiveWnd::UpdateGiveDisplay(void); +// virtual +EQLIB_OBJECT CGiveWnd::~CGiveWnd(void); +EQLIB_OBJECT int CGiveWnd::OnProcessFrame(void); +EQLIB_OBJECT int CGiveWnd::PostDraw(void)const; +EQLIB_OBJECT int CGiveWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CGiveWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CGiveWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CGiveWnd::Deactivate(void); +// private +EQLIB_OBJECT void CGiveWnd::Init(void); +}; + +class CGroupSearchFiltersWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CGroupSearchFiltersWnd::CGroupSearchFiltersWnd(class CXWnd *); +EQLIB_OBJECT bool CGroupSearchFiltersWnd::ShouldFilterPlayer(char const *,char const *)const; +EQLIB_OBJECT bool CGroupSearchFiltersWnd::UseExclusiveSearchMode(void)const; +EQLIB_OBJECT void CGroupSearchFiltersWnd::Activate(void); +EQLIB_OBJECT void CGroupSearchFiltersWnd::HandleAddDesiredGuild(void); +EQLIB_OBJECT void CGroupSearchFiltersWnd::HandleAddExcludedGuild(void); +EQLIB_OBJECT void CGroupSearchFiltersWnd::HandleDesiredGuildsSelected(void); +EQLIB_OBJECT void CGroupSearchFiltersWnd::HandleExcludeGuildsSelected(void); +EQLIB_OBJECT void CGroupSearchFiltersWnd::HandleRemoveAllDesiredGuilds(void); +EQLIB_OBJECT void CGroupSearchFiltersWnd::HandleRemoveAllExcludedGuilds(void); +EQLIB_OBJECT void CGroupSearchFiltersWnd::HandleRemoveDesiredGuild(void); +EQLIB_OBJECT void CGroupSearchFiltersWnd::HandleRemoveExcludedGuild(void); +EQLIB_OBJECT void CGroupSearchFiltersWnd::HandleUseFriendsListSelected(void); +EQLIB_OBJECT void CGroupSearchFiltersWnd::HandleUseIgnoreListSelected(void); +// virtual +EQLIB_OBJECT CGroupSearchFiltersWnd::~CGroupSearchFiltersWnd(void); +EQLIB_OBJECT int CGroupSearchFiltersWnd::OnProcessFrame(void); +EQLIB_OBJECT int CGroupSearchFiltersWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CGroupSearchFiltersWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CGroupSearchFiltersWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CGroupSearchFiltersWnd::Deactivate(void); +// private +EQLIB_OBJECT bool CGroupSearchFiltersWnd::GuildIsInDesiredGuildsList(char const *)const; +EQLIB_OBJECT bool CGroupSearchFiltersWnd::GuildIsInExcludedGuildsList(char const *)const; +EQLIB_OBJECT bool CGroupSearchFiltersWnd::Load(void); +EQLIB_OBJECT bool CGroupSearchFiltersWnd::NameIsInFriendsList(char const *)const; +EQLIB_OBJECT bool CGroupSearchFiltersWnd::NameIsInIgnoreList(char const *)const; +EQLIB_OBJECT bool CGroupSearchFiltersWnd::UseDesiredGuilds(void)const; +EQLIB_OBJECT bool CGroupSearchFiltersWnd::UseExcludedGuilds(void)const; +EQLIB_OBJECT bool CGroupSearchFiltersWnd::UseFriendsList(void)const; +EQLIB_OBJECT bool CGroupSearchFiltersWnd::UseIgnoreList(void)const; +EQLIB_OBJECT void CGroupSearchFiltersWnd::ClearUiPointers(void); +EQLIB_OBJECT void CGroupSearchFiltersWnd::FetchUiPointers(void); +EQLIB_OBJECT void CGroupSearchFiltersWnd::InitPieces(void); +EQLIB_OBJECT void CGroupSearchFiltersWnd::Save(void)const; +}; + +class CGroupSearchWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CGroupSearchWnd::CGroupSearchWnd(class CXWnd *); +EQLIB_OBJECT void CGroupSearchWnd::Activate(int); +EQLIB_OBJECT void CGroupSearchWnd::AddGroupResult(struct LfgGroupResult const *); +EQLIB_OBJECT void CGroupSearchWnd::AddPlayerResult(struct LfgPlayerResult const *); +EQLIB_OBJECT void CGroupSearchWnd::HandleDeselectAllClasses(void); +EQLIB_OBJECT void CGroupSearchWnd::HandleDoubleClickedOnPlayer(char const *); +EQLIB_OBJECT void CGroupSearchWnd::HandleGroupInfoPost(void); +EQLIB_OBJECT void CGroupSearchWnd::HandleGroupInfoRemove(void); +EQLIB_OBJECT void CGroupSearchWnd::HandleGroupInfoUpdate(void); +EQLIB_OBJECT void CGroupSearchWnd::HandleGroupMakeupChanged(void); +EQLIB_OBJECT void CGroupSearchWnd::HandleGroupResultColSelected(int); +EQLIB_OBJECT void CGroupSearchWnd::HandleGroupResultRowSelected(int); +EQLIB_OBJECT void CGroupSearchWnd::HandleNumericSort(class SListWndSortInfo *); +EQLIB_OBJECT void CGroupSearchWnd::HandleOpenFiltersWindow(void); +EQLIB_OBJECT void CGroupSearchWnd::HandlePlayerInfoPost(void); +EQLIB_OBJECT void CGroupSearchWnd::HandlePlayerInfoRemove(void); +EQLIB_OBJECT void CGroupSearchWnd::HandlePlayerInfoUpdate(void); +EQLIB_OBJECT void CGroupSearchWnd::HandlePlayerResultColSelected(int); +EQLIB_OBJECT void CGroupSearchWnd::HandleQueryingForGroups(void); +EQLIB_OBJECT void CGroupSearchWnd::HandleQueryingForPlayers(void); +EQLIB_OBJECT void CGroupSearchWnd::HandleSelectAllClasses(void); +EQLIB_OBJECT void CGroupSearchWnd::ResetGroupList(void); +EQLIB_OBJECT void CGroupSearchWnd::ResetPlayerList(void); +EQLIB_OBJECT void CGroupSearchWnd::SendServerLfgOff(void); +EQLIB_OBJECT void CGroupSearchWnd::SendServerLfgOn(void); +EQLIB_OBJECT void CGroupSearchWnd::SendServerLfpOff(void); +EQLIB_OBJECT void CGroupSearchWnd::SendServerLfpOn(void); +// virtual +EQLIB_OBJECT CGroupSearchWnd::~CGroupSearchWnd(void); +EQLIB_OBJECT int CGroupSearchWnd::OnProcessFrame(void); +EQLIB_OBJECT int CGroupSearchWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CGroupSearchWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CGroupSearchWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CGroupSearchWnd::Deactivate(void); +// private +EQLIB_OBJECT bool CGroupSearchWnd::IsLevelRangeValid(int,int)const; +EQLIB_OBJECT bool CGroupSearchWnd::PlayerShouldBeFiltered(struct LfgPlayerData const *)const; +EQLIB_OBJECT int CGroupSearchWnd::CheckIfCurrentLfgInfoIsValid(void)const; +EQLIB_OBJECT int CGroupSearchWnd::CheckIfCurrentLfpInfoIsValid(void)const; +EQLIB_OBJECT int CGroupSearchWnd::GetDesiredClassesFlag(void)const; +EQLIB_OBJECT int CGroupSearchWnd::GetDesiredGroupMaxLevel(void)const; +EQLIB_OBJECT int CGroupSearchWnd::GetDesiredGroupMinLevel(void)const; +EQLIB_OBJECT int CGroupSearchWnd::GetDesiredPlayerMaxLevel(void)const; +EQLIB_OBJECT int CGroupSearchWnd::GetDesiredPlayerMinLevel(void)const; +EQLIB_OBJECT int CGroupSearchWnd::GetEqClassType(int)const; +EQLIB_OBJECT int CGroupSearchWnd::GroupInfoPageOnProcessFrame(void); +EQLIB_OBJECT int CGroupSearchWnd::GroupInfoPageWndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int CGroupSearchWnd::GroupListPageOnProcessFrame(void); +EQLIB_OBJECT int CGroupSearchWnd::GroupListPageWndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int CGroupSearchWnd::PlayerInfoPageOnProcessFrame(void); +EQLIB_OBJECT int CGroupSearchWnd::PlayerInfoPageWndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int CGroupSearchWnd::PlayerListPageOnProcessFrame(void); +EQLIB_OBJECT int CGroupSearchWnd::PlayerListPageWndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int CGroupSearchWnd::RedirectOnProcessFrameTo(class CPageWnd *); +EQLIB_OBJECT int CGroupSearchWnd::RedirectWndNotificationTo(class CPageWnd *,class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT void CGroupSearchWnd::ClearUiPointers(void); +EQLIB_OBJECT void CGroupSearchWnd::FetchUiPointers(void); +EQLIB_OBJECT void CGroupSearchWnd::FilterOutBadWords(char const *,char *)const; +EQLIB_OBJECT void CGroupSearchWnd::GetDefaultLfgLevelRange(class EQ_PC const *,int *,int *)const; +EQLIB_OBJECT void CGroupSearchWnd::GetDefaultLfpLevelRange(class EQ_PC const *,int *,int *)const; +EQLIB_OBJECT void CGroupSearchWnd::InitLfg(void); +EQLIB_OBJECT void CGroupSearchWnd::InitLfp(void); +EQLIB_OBJECT void CGroupSearchWnd::LockQueryButtonAtTime(long); +EQLIB_OBJECT void CGroupSearchWnd::PopUpErrorMessage(int)const; +EQLIB_OBJECT void CGroupSearchWnd::ShowGroupDetails(struct LfgGroupResult const *); +EQLIB_OBJECT void CGroupSearchWnd::UpdateGroupLabel(void); +EQLIB_OBJECT void CGroupSearchWnd::UpdateLfgPostingStatus(void); +EQLIB_OBJECT void CGroupSearchWnd::UpdateLfpPostingStatus(void); +EQLIB_OBJECT void CGroupSearchWnd::UpdatePlayerLabel(void); +EQLIB_OBJECT void CGroupSearchWnd::UpdateRemainingQueryLockedTime(long); +}; + +class CGroupWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CGroupWnd::CGroupWnd(class CXWnd *); +EQLIB_OBJECT void CGroupWnd::Activate(void); +EQLIB_OBJECT void CGroupWnd::CreateLocalMenu(void); +EQLIB_OBJECT void CGroupWnd::KeyMapUpdated(void); +EQLIB_OBJECT void CGroupWnd::SetInvited(bool); +EQLIB_OBJECT void CGroupWnd::UpdateContextMenu(void); +// virtual +EQLIB_OBJECT CGroupWnd::~CGroupWnd(void); +EQLIB_OBJECT int CGroupWnd::Draw(void)const; +EQLIB_OBJECT int CGroupWnd::OnProcessFrame(void); +EQLIB_OBJECT int CGroupWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CGroupWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CGroupWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CGroupWnd::Deactivate(void); +EQLIB_OBJECT void CGroupWnd::LoadIniInfo(void); +EQLIB_OBJECT void CGroupWnd::StoreIniInfo(void); +// protected +EQLIB_OBJECT void CGroupWnd::UpdateButtons(void); +// private +EQLIB_OBJECT void CGroupWnd::Init(void); +}; + +class CGuild +{ +public: +EQLIB_OBJECT CGuild::CGuild(void); +EQLIB_OBJECT bool CGuild::ValidGuildName(int); +EQLIB_OBJECT char * CGuild::GetGuildMotd(void); +EQLIB_OBJECT char * CGuild::GetGuildMotdAuthor(void); +EQLIB_OBJECT char * CGuild::GetGuildName(int); +EQLIB_OBJECT int CGuild::GetGuildIndex(char *); +EQLIB_OBJECT class GuildMember * CGuild::FindMemberByName(char *); +EQLIB_OBJECT void CGuild::DeleteAllMembers(void); +EQLIB_OBJECT void CGuild::DemoteMember(class GuildMember *); +EQLIB_OBJECT void CGuild::HandleGuildMessage(struct connection_t *,unsigned __int32,char *,unsigned __int32); +EQLIB_OBJECT void CGuild::SendPublicCommentChange(char *,char *); +EQLIB_OBJECT void CGuild::SetGuildMotd(struct guildmotdSet *); +// virtual +EQLIB_OBJECT CGuild::~CGuild(void); +//EQLIB_OBJECT void * CGuild::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CGuild::`vector deleting destructor'(unsigned int); +// private +EQLIB_OBJECT void CGuild::AddGuildMember(class GuildMember *); +EQLIB_OBJECT void CGuild::ChangeGuildMemberName(char *); +EQLIB_OBJECT void CGuild::HandleAddGuildMember(char *,int); +EQLIB_OBJECT void CGuild::HandleDeleteGuildResponse(char *); +EQLIB_OBJECT void CGuild::HandleGuildInvite(struct connection_t *,unsigned __int32,char *,unsigned __int32); +EQLIB_OBJECT void CGuild::HandleMemberLevelUpdate(char *); +EQLIB_OBJECT void CGuild::HandleRemoveGuildMember(char *,int); +EQLIB_OBJECT void CGuild::InitializeFromDump(char *); +EQLIB_OBJECT void CGuild::UpdateGuildMemberOnWindow(class GuildMember *); +EQLIB_OBJECT void CGuild::UpdateMemberStatus(char *); +EQLIB_OBJECT void CGuild::UpdatePublicComment(char *); +}; + +class CGuildMgmtWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CGuildMgmtWnd::CGuildMgmtWnd(class CXWnd *); +EQLIB_OBJECT void CGuildMgmtWnd::Activate(void); +EQLIB_OBJECT void CGuildMgmtWnd::AddMember(class GuildMember *); +EQLIB_OBJECT void CGuildMgmtWnd::Clean(void); +EQLIB_OBJECT void CGuildMgmtWnd::DumpToFile(char *); +EQLIB_OBJECT void CGuildMgmtWnd::RemoveMember(class GuildMember *); +EQLIB_OBJECT void CGuildMgmtWnd::RenameMember(char *,char *); +EQLIB_OBJECT void CGuildMgmtWnd::SetMOTD(char *,char *); +EQLIB_OBJECT void CGuildMgmtWnd::SetPlayerCount(int); +EQLIB_OBJECT void CGuildMgmtWnd::SortList(int,bool); +EQLIB_OBJECT void CGuildMgmtWnd::UpdateButtons(void); +EQLIB_OBJECT void CGuildMgmtWnd::UpdateListMember(class GuildMember *,int); +// virtual +EQLIB_OBJECT CGuildMgmtWnd::~CGuildMgmtWnd(void); +EQLIB_OBJECT int CGuildMgmtWnd::OnProcessFrame(void); +EQLIB_OBJECT int CGuildMgmtWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CGuildMgmtWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CGuildMgmtWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CGuildMgmtWnd::Deactivate(void); +// protected +EQLIB_OBJECT char * CGuildMgmtWnd::GetPersonalNote(char *); +EQLIB_OBJECT int CGuildMgmtWnd::FindListMember(class GuildMember *); +EQLIB_OBJECT void CGuildMgmtWnd::CleanAndRefillListWnd(bool); +EQLIB_OBJECT void CGuildMgmtWnd::CreatePersonalNotesFilename(void); +EQLIB_OBJECT void CGuildMgmtWnd::LoadINI(void); +EQLIB_OBJECT void CGuildMgmtWnd::LoadPersonalNotes(void); +EQLIB_OBJECT void CGuildMgmtWnd::SavePersonalNotes(void); +EQLIB_OBJECT void CGuildMgmtWnd::SetPersonalNote(char *,char *); +// private +EQLIB_OBJECT void CGuildMgmtWnd::Init(void); +}; + +class ChannelServerApi +{ +public: +EQLIB_OBJECT ChannelServerApi::~ChannelServerApi(void); +EQLIB_OBJECT ChannelServerApi::ChannelServerApi(char *,int,char *,char *,class ChannelServerHandler *,bool,bool,char *); +EQLIB_OBJECT char * ChannelServerApi::GetChannelName(int); +//EQLIB_OBJECT enum ChannelServerApi::Status ChannelServerApi::GetStatus(void); +EQLIB_OBJECT int ChannelServerApi::GetChannelCount(void); +EQLIB_OBJECT int ChannelServerApi::GetChannelNumber(char *); +EQLIB_OBJECT static char * __cdecl ChannelServerApi::AllocateString(char *); +EQLIB_OBJECT static char * __cdecl ChannelServerApi::Strncpy(char *,char *,int); +EQLIB_OBJECT static int __cdecl ChannelServerApi::GetNextField(char *,int,char * *,char); +EQLIB_OBJECT static void * __cdecl ChannelServerApi::SmartResize(void *,int,int); +EQLIB_OBJECT void ChannelServerApi::GiveTime(void); +EQLIB_OBJECT void ChannelServerApi::SendMessageA(char *); +// virtual +EQLIB_OBJECT void ChannelServerApi::OnRoutePacket(class UdpConnection *,unsigned char const *,int); +// protected +EQLIB_OBJECT void ChannelServerApi::FreeChannelList(void); +//EQLIB_OBJECT void ChannelServerApi::SetBuddyStatus(char *,enum ChannelServerApi::BuddyStatus); +EQLIB_OBJECT void ChannelServerApi::SortBuddyList(void); +}; + +class ChannelServerHandler +{ +public: +// virtual +EQLIB_OBJECT void ChannelServerHandler::CshOnLoginConfirm(bool); +EQLIB_OBJECT void ChannelServerHandler::CshOnPacket(void *,int,char *,int,char *,bool); +}; + +class CHashCXStrInt32 +{ +public: +EQLIB_OBJECT CHashCXStrInt32::~CHashCXStrInt32(void); +EQLIB_OBJECT CHashCXStrInt32::CHashCXStrInt32(void); +EQLIB_OBJECT bool CHashCXStrInt32::Insert(class CXStr const &,int); +EQLIB_OBJECT bool CHashCXStrInt32::LookUp(class CXStr const &,int &)const; +EQLIB_OBJECT void CHashCXStrInt32::Reset(void); +// private +EQLIB_OBJECT int CHashCXStrInt32::KeyToBin(class CXStr const &)const; +}; + +class CHelpWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CHelpWnd::CHelpWnd(class CXWnd *); +EQLIB_OBJECT void CHelpWnd::Activate(void); +EQLIB_OBJECT void CHelpWnd::SetFile(char *); +// virtual +EQLIB_OBJECT CHelpWnd::~CHelpWnd(void); +EQLIB_OBJECT int CHelpWnd::HandleKeyboardMsg(unsigned __int32,unsigned __int32,bool); +EQLIB_OBJECT int CHelpWnd::OnProcessFrame(void); +EQLIB_OBJECT int CHelpWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CHelpWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CHelpWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CHelpWnd::Deactivate(void); +// private +EQLIB_OBJECT void CHelpWnd::Init(void); +}; + +class CHotButtonWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CHotButtonWnd::CHotButtonWnd(class CXWnd *); +EQLIB_OBJECT void CHotButtonWnd::Activate(void); +EQLIB_OBJECT void CHotButtonWnd::DoHotButton(int Button,int AllowAutoRightClick); +EQLIB_OBJECT void CHotButtonWnd::DoHotButtonRightClick(int); +EQLIB_OBJECT void CHotButtonWnd::UpdatePage(void); +// virtual +EQLIB_OBJECT CHotButtonWnd::~CHotButtonWnd(void); +EQLIB_OBJECT int CHotButtonWnd::Draw(void)const; +EQLIB_OBJECT int CHotButtonWnd::OnProcessFrame(void); +EQLIB_OBJECT int CHotButtonWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CHotButtonWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CHotButtonWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CHotButtonWnd::Deactivate(void); +// private +EQLIB_OBJECT void CHotButtonWnd::Init(void); +}; + +class CIMECandidateList +{ +public: +EQLIB_OBJECT CIMECandidateList::~CIMECandidateList(void); +EQLIB_OBJECT CIMECandidateList::CIMECandidateList(class CIMEManager *); +EQLIB_OBJECT int CIMECandidateList::show(class CIMEComposition const *)const; +// private +EQLIB_OBJECT int CIMECandidateList::repositionImeCandidateList(int,int)const; +}; + +class CIMEComposition +{ +public: +EQLIB_OBJECT CIMEComposition::~CIMEComposition(void); +EQLIB_OBJECT CIMEComposition::CIMEComposition(class CIMEManager *); +EQLIB_OBJECT class CXPoint CIMEComposition::getCursorPoint(void)const; +EQLIB_OBJECT class CXRect CIMEComposition::getCompositionArea(void)const; +EQLIB_OBJECT int CIMEComposition::addInputChar(unsigned short); +EQLIB_OBJECT int CIMEComposition::addInputString(class CXStr const &,int); +EQLIB_OBJECT int CIMEComposition::addInputString(unsigned short *,int); +EQLIB_OBJECT int CIMEComposition::addStringFromIme(long); +EQLIB_OBJECT void CIMEComposition::directToEditWnd(class CEditWnd *); +// private +EQLIB_OBJECT int CIMEComposition::addCompositionHighlights(void); +EQLIB_OBJECT int CIMEComposition::applyChineseComposingRules(class CXStr *); +EQLIB_OBJECT int CIMEComposition::applyJapaneseComposingRules(class CXStr *); +EQLIB_OBJECT int CIMEComposition::applyKoreanComposingRules(class CXStr *); +EQLIB_OBJECT int CIMEComposition::getCompositionInsertIndex(void)const; +EQLIB_OBJECT int CIMEComposition::handleImeComposing(void); +EQLIB_OBJECT int CIMEComposition::handleImeResult(void); +EQLIB_OBJECT int CIMEComposition::repositionImeCompositionWindow(int,int)const; +EQLIB_OBJECT struct CompAttr * CIMEComposition::allocateImeCompositionAttributes(void)const; +EQLIB_OBJECT unsigned short * CIMEComposition::allocateImeCompositionString(long)const; +EQLIB_OBJECT void CIMEComposition::backupCurrentText(void); +EQLIB_OBJECT void CIMEComposition::revertToBackupText(void); +}; + +class CIMEManager +{ +public: +EQLIB_OBJECT CIMEManager::~CIMEManager(void); +EQLIB_OBJECT CIMEManager::CIMEManager(struct HWND__ *); +EQLIB_OBJECT bool CIMEManager::imeIsOff(void)const; +EQLIB_OBJECT bool CIMEManager::imeIsOn(void)const; +EQLIB_OBJECT int CIMEManager::getImeProperties(void)const; +EQLIB_OBJECT int CIMEManager::getInputLanguage(void)const; +EQLIB_OBJECT int CIMEManager::getInputState(void)const; +EQLIB_OBJECT int CIMEManager::handleWndProc(unsigned int,unsigned int,long); +EQLIB_OBJECT int CIMEManager::setInputEditWnd(class CEditWnd *); +EQLIB_OBJECT struct HWND__ * CIMEManager::getWindowHandle(void)const; +EQLIB_OBJECT void CIMEManager::setInputState(int); +EQLIB_OBJECT void CIMEManager::turnImeOff(void); +EQLIB_OBJECT void CIMEManager::turnImeOn(void); +// private +EQLIB_OBJECT int CIMEManager::handleAddChar(unsigned short); +EQLIB_OBJECT int CIMEManager::handleChangeCandidates(void); +EQLIB_OBJECT int CIMEManager::handleCloseCandidates(void); +EQLIB_OBJECT int CIMEManager::handleEndComposition(void); +EQLIB_OBJECT int CIMEManager::handleImeChanged(void); +EQLIB_OBJECT int CIMEManager::handleImeStatusChanged(void); +EQLIB_OBJECT int CIMEManager::handleInputComposition(long); +EQLIB_OBJECT int CIMEManager::handleOpenCandidates(void); +EQLIB_OBJECT int CIMEManager::handleStartComposition(void); +EQLIB_OBJECT int CIMEManager::queryImeLanguage(void)const; +EQLIB_OBJECT int CIMEManager::queryImeProperties(void)const; +EQLIB_OBJECT void CIMEManager::enableIme(bool); +}; + +class CIMEStatusBar +{ +public: +EQLIB_OBJECT CIMEStatusBar::CIMEStatusBar(class CIMEManager *); +EQLIB_OBJECT int CIMEStatusBar::hide(void); +EQLIB_OBJECT int CIMEStatusBar::show(class CIMEComposition const *); +EQLIB_OBJECT int CIMEStatusBar::update(void); +// private +EQLIB_OBJECT int CIMEStatusBar::repositionStatusWindow(void); +EQLIB_OBJECT void CIMEStatusBar::handleChineseSimplifiedStatusChange(unsigned long); +EQLIB_OBJECT void CIMEStatusBar::handleChineseTraditionalStatusChange(unsigned long); +EQLIB_OBJECT void CIMEStatusBar::handleJapaneseStatusChange(unsigned long); +EQLIB_OBJECT void CIMEStatusBar::handleKoreanStatusChange(unsigned long); +}; + +class CInspectWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CInspectWnd::CInspectWnd(class CXWnd *); +EQLIB_OBJECT void CInspectWnd::Activate(struct _inspect *); +EQLIB_OBJECT void CInspectWnd::PlayerBeingDeleted(class EQPlayer *); +// virtual +EQLIB_OBJECT CInspectWnd::~CInspectWnd(void); +EQLIB_OBJECT int CInspectWnd::Draw(void)const; +EQLIB_OBJECT int CInspectWnd::OnProcessFrame(void); +EQLIB_OBJECT int CInspectWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CInspectWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CInspectWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CInspectWnd::Deactivate(void); +// private +EQLIB_OBJECT void CInspectWnd::AcceptInspectText(void); +EQLIB_OBJECT void CInspectWnd::Init(void); +}; + +class CInventoryWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CInventoryWnd::CInventoryWnd(class CXWnd *); +EQLIB_OBJECT void CInventoryWnd::Activate(void); +// virtual +EQLIB_OBJECT CInventoryWnd::~CInventoryWnd(void); +EQLIB_OBJECT int CInventoryWnd::Draw(void)const; +EQLIB_OBJECT int CInventoryWnd::HandleLButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CInventoryWnd::OnProcessFrame(void); +EQLIB_OBJECT int CInventoryWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CInventoryWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CInventoryWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CInventoryWnd::Deactivate(void); +// private +EQLIB_OBJECT long CInventoryWnd::GetInventoryQtyFromCoinType(int); +EQLIB_OBJECT void CInventoryWnd::ClickedMoneyButton(int,int); +EQLIB_OBJECT void CInventoryWnd::DestroyHeld(void); +EQLIB_OBJECT void CInventoryWnd::Init(void); +EQLIB_OBJECT void CInventoryWnd::UpdateMoneyDisplay(void); +}; + +class CInvSlot +{ +public: +EQLIB_OBJECT CInvSlot::CInvSlot(void); +EQLIB_OBJECT bool CInvSlot::IllegalBigBank(int); +EQLIB_OBJECT void CInvSlot::DoDrinkEatPoison(class EQ_Item *,int); +EQLIB_OBJECT void CInvSlot::HandleLButtonDown(class CXPoint); +EQLIB_OBJECT void CInvSlot::HandleLButtonHeld(class CXPoint); +EQLIB_OBJECT void CInvSlot::HandleLButtonUp(class CXPoint,bool); +EQLIB_OBJECT void CInvSlot::HandleLButtonUpAfterHeld(class CXPoint); +EQLIB_OBJECT void CInvSlot::HandleRButtonDown(class CXPoint); +EQLIB_OBJECT void CInvSlot::HandleRButtonHeld(class CXPoint); +EQLIB_OBJECT void CInvSlot::HandleRButtonUp(class CXPoint *); +EQLIB_OBJECT void CInvSlot::HandleRButtonUpAfterHeld(class CXPoint); +EQLIB_OBJECT void CInvSlot::SetInvSlotWnd(class CInvSlotWnd *); +EQLIB_OBJECT void CInvSlot::SetItem(class EQ_Item *); +EQLIB_OBJECT void CInvSlot::SliderComplete(int); +EQLIB_OBJECT void CInvSlot::GetItemBase(struct _CONTENTS **); +// virtual +EQLIB_OBJECT CInvSlot::~CInvSlot(void); +//EQLIB_OBJECT void * CInvSlot::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CInvSlot::`vector deleting destructor'(unsigned int); +}; + +class CMoveItemData +{ +public: + unsigned short InventoryType; // 0 = regular inventory slots, 1 = bank slots, 2 = shared bank slots + unsigned short Unknown2; // always 0? + unsigned short InvSlot; + unsigned short BagSlot; // 0xFFFF if not in a bag, otherwise the bag slot number (0 through 9, or 0 through 19 if it's a 20-slot bag, etc) + DWORD Unknown8; +}; + +class CInvSlotMgr +{ +public: +EQLIB_OBJECT CInvSlotMgr::CInvSlotMgr(void); +EQLIB_OBJECT class CInvSlot * CInvSlotMgr::CreateInvSlot(class CInvSlotWnd *); +EQLIB_OBJECT class CInvSlot * CInvSlotMgr::FindInvSlot(int,int x=-1); +EQLIB_OBJECT bool CInvSlotMgr::MoveItem(CMoveItemData*,CMoveItemData*,int valueOne,int valueOne2,int valueZero,int valueZero2); +EQLIB_OBJECT void CInvSlotMgr::Process(void); +EQLIB_OBJECT void CInvSlotMgr::SelectSlot(class CInvSlot *); +EQLIB_OBJECT void CInvSlotMgr::UpdateSlots(void); +// virtual +EQLIB_OBJECT CInvSlotMgr::~CInvSlotMgr(void); +//EQLIB_OBJECT void * CInvSlotMgr::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CInvSlotMgr::`vector deleting destructor'(unsigned int); +}; + +class CInvSlotTemplate +{ +public: +EQLIB_OBJECT CInvSlotTemplate::CInvSlotTemplate(class CParamInvSlot *); +// virtual +EQLIB_OBJECT CInvSlotTemplate::~CInvSlotTemplate(void); +//EQLIB_OBJECT void * CInvSlotTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CInvSlotTemplate::`vector deleting destructor'(unsigned int); +}; + +class CInvSlotWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CInvSlotWnd::CInvSlotWnd(class CXWnd *,unsigned __int32,class CXRect,class CTextureAnimation *,int,int,int); +EQLIB_OBJECT void CInvSlotWnd::SetInvSlot(class CInvSlot *); +// virtual +EQLIB_OBJECT CInvSlotWnd::~CInvSlotWnd(void); +EQLIB_OBJECT int CInvSlotWnd::Draw(void)const; +EQLIB_OBJECT int CInvSlotWnd::DrawTooltip(class CXWnd const *)const; +EQLIB_OBJECT int CInvSlotWnd::HandleLButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CInvSlotWnd::HandleLButtonHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CInvSlotWnd::HandleLButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CInvSlotWnd::HandleLButtonUpAfterHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CInvSlotWnd::HandleRButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CInvSlotWnd::HandleRButtonHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CInvSlotWnd::HandleRButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CInvSlotWnd::HandleRButtonUpAfterHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CInvSlotWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CInvSlotWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CInvSlotWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CInvSlotWnd::SetAttributesFromSidl(class CParamScreenPiece *); +}; + +class CItemDisplayWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CItemDisplayWnd::CItemDisplayWnd(class CXWnd *); +EQLIB_OBJECT class CXStr CItemDisplayWnd::CreateEquipmentStatusString(class EQ_Item *); +EQLIB_OBJECT void CItemDisplayWnd::SetItem(class EQ_Item *,bool); +EQLIB_OBJECT void CItemDisplayWnd::SetItemText(char *); +EQLIB_OBJECT void CItemDisplayWnd::SetSpell(int SpellID,bool HasSpellDescr,int); +EQLIB_OBJECT void CItemDisplayWnd::UpdateStrings(void); +// virtual +EQLIB_OBJECT CItemDisplayWnd::~CItemDisplayWnd(void); +EQLIB_OBJECT int CItemDisplayWnd::HandleKeyboardMsg(unsigned __int32,unsigned __int32,bool); +EQLIB_OBJECT int CItemDisplayWnd::OnProcessFrame(void); +EQLIB_OBJECT int CItemDisplayWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CItemDisplayWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CItemDisplayWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CItemDisplayWnd::Activate(void); +EQLIB_OBJECT void CItemDisplayWnd::Deactivate(void); +// protected +EQLIB_OBJECT class CXStr CItemDisplayWnd::CreateClassString(class EQ_Equipment *); +EQLIB_OBJECT class CXStr CItemDisplayWnd::CreateMealSizeString(class EQ_Equipment *); +EQLIB_OBJECT class CXStr CItemDisplayWnd::CreateModString(class EQ_Equipment *,int,int,int *); +EQLIB_OBJECT class CXStr CItemDisplayWnd::CreateRaceString(class EQ_Equipment *); +EQLIB_OBJECT void CItemDisplayWnd::GetSizeString(int,char *); +}; + +class CJournalCatWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CJournalCatWnd::CJournalCatWnd(class CXWnd *); +EQLIB_OBJECT void CJournalCatWnd::Activate(void); +EQLIB_OBJECT void CJournalCatWnd::Clean(void); +EQLIB_OBJECT void CJournalCatWnd::UpdateAll(bool); +EQLIB_OBJECT void CJournalCatWnd::UpdateButtons(void); +// virtual +EQLIB_OBJECT CJournalCatWnd::~CJournalCatWnd(void); +EQLIB_OBJECT int CJournalCatWnd::OnProcessFrame(void); +EQLIB_OBJECT int CJournalCatWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CJournalCatWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CJournalCatWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CJournalCatWnd::Deactivate(void); +// protected +EQLIB_OBJECT void CJournalCatWnd::BuildList(void); +EQLIB_OBJECT void CJournalCatWnd::LoadINI(void); +EQLIB_OBJECT void CJournalCatWnd::SelectCategory(int); +EQLIB_OBJECT void CJournalCatWnd::SortList(int,bool); +EQLIB_OBJECT void CJournalCatWnd::StoreINI(void); +EQLIB_OBJECT void CJournalCatWnd::UpdateListWnd(bool); +// private +EQLIB_OBJECT void CJournalCatWnd::Init(void); +}; + +class CJournalNPCWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CJournalNPCWnd::CJournalNPCWnd(class CXWnd *); +EQLIB_OBJECT void CJournalNPCWnd::Activate(void); +EQLIB_OBJECT void CJournalNPCWnd::EnterIntoJournal(char *,float,float,float,char *); +EQLIB_OBJECT void CJournalNPCWnd::LoadJournal(int); +EQLIB_OBJECT void CJournalNPCWnd::SaveJournal(void); +EQLIB_OBJECT void CJournalNPCWnd::UpdateAll(bool); +EQLIB_OBJECT void CJournalNPCWnd::UpdateCategories(void); +// virtual +EQLIB_OBJECT CJournalNPCWnd::~CJournalNPCWnd(void); +EQLIB_OBJECT int CJournalNPCWnd::OnProcessFrame(void); +EQLIB_OBJECT int CJournalNPCWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CJournalNPCWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CJournalNPCWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CJournalNPCWnd::Deactivate(void); +// protected +EQLIB_OBJECT void CJournalNPCWnd::BuildList(void); +EQLIB_OBJECT void CJournalNPCWnd::DoBackups(class CXStr); +EQLIB_OBJECT void CJournalNPCWnd::GetLogState(void); +EQLIB_OBJECT void CJournalNPCWnd::SelectNPCIndex(int); +EQLIB_OBJECT void CJournalNPCWnd::SortList(int,bool); +EQLIB_OBJECT void CJournalNPCWnd::StoreLogState(void); +EQLIB_OBJECT void CJournalNPCWnd::UpdateButtons(void); +EQLIB_OBJECT void CJournalNPCWnd::UpdateListWnd(bool); +// private +EQLIB_OBJECT void CJournalNPCWnd::Init(void); +}; + +class CJournalTextWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CJournalTextWnd::CJournalTextWnd(class CXWnd *); +EQLIB_OBJECT void CJournalTextWnd::Activate(void); +EQLIB_OBJECT void CJournalTextWnd::Clear(void); +EQLIB_OBJECT void CJournalTextWnd::DisplayNPC(class JournalNPC *); +EQLIB_OBJECT void CJournalTextWnd::SetSearch(class CXStr); +EQLIB_OBJECT void CJournalTextWnd::UpdateAll(bool); +EQLIB_OBJECT void CJournalTextWnd::UpdateCategories(void); +// virtual +EQLIB_OBJECT CJournalTextWnd::~CJournalTextWnd(void); +EQLIB_OBJECT int CJournalTextWnd::OnProcessFrame(void); +EQLIB_OBJECT int CJournalTextWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CJournalTextWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CJournalTextWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CJournalTextWnd::Deactivate(void); +// protected +EQLIB_OBJECT void CJournalTextWnd::BuildList(void); +EQLIB_OBJECT void CJournalTextWnd::SelectEntryIndex(int); +EQLIB_OBJECT void CJournalTextWnd::SortList(int,bool); +EQLIB_OBJECT void CJournalTextWnd::UpdateButtons(void); +EQLIB_OBJECT void CJournalTextWnd::UpdateListWnd(bool); +}; + +class CKeyCXStrValueInt32 +{ +public: +EQLIB_OBJECT CKeyCXStrValueInt32::~CKeyCXStrValueInt32(void); +EQLIB_OBJECT CKeyCXStrValueInt32::CKeyCXStrValueInt32(void); +//EQLIB_OBJECT void * CKeyCXStrValueInt32::`vector deleting destructor'(unsigned int); +}; + +class CLabel +{ +public: +EQLIB_OBJECT CLabel::CLabel(class CXWnd *,unsigned __int32,class CXRect,int); +EQLIB_OBJECT void CLabel::SetAlignCenter(bool); +EQLIB_OBJECT void CLabel::SetAlignRight(bool); +EQLIB_OBJECT void CLabel::SetNoWrap(bool); +// virtual +EQLIB_OBJECT CLabel::~CLabel(void); +EQLIB_OBJECT int CLabel::Draw(void)const; +//EQLIB_OBJECT void * CLabel::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CLabel::`vector deleting destructor'(unsigned int); +}; + +class CLabelTemplate +{ +public: +EQLIB_OBJECT CLabelTemplate::CLabelTemplate(class CParamLabel *); +// virtual +EQLIB_OBJECT CLabelTemplate::~CLabelTemplate(void); +//EQLIB_OBJECT void * CLabelTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CLabelTemplate::`vector deleting destructor'(unsigned int); +}; + +class CListboxColumnTemplate +{ +public: +EQLIB_OBJECT CListboxColumnTemplate::~CListboxColumnTemplate(void); +EQLIB_OBJECT CListboxColumnTemplate::CListboxColumnTemplate(class CParamListboxColumn *); +//EQLIB_OBJECT void CListboxColumnTemplate::`default constructor closure'(void); +}; + +class CListboxTemplate +{ +public: +EQLIB_OBJECT CListboxTemplate::CListboxTemplate(class CParamListbox *); +// virtual +EQLIB_OBJECT CListboxTemplate::~CListboxTemplate(void); +//EQLIB_OBJECT void * CListboxTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CListboxTemplate::`vector deleting destructor'(unsigned int); +}; + +class CListWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CListWnd::CListWnd(class CXWnd *,unsigned __int32,class CXRect); +EQLIB_OBJECT bool CListWnd::IsLineEnabled(int)const; +EQLIB_OBJECT class CTextureAnimation const * CListWnd::GetColumnAnimation(int)const; +EQLIB_OBJECT class CTextureAnimation const * CListWnd::GetColumnAnimationMouseOver(int)const; +EQLIB_OBJECT class CTextureAnimation const * CListWnd::GetColumnAnimationSelected(int)const; +EQLIB_OBJECT class CTextureAnimation const * CListWnd::GetItemIcon(int,int)const; +EQLIB_OBJECT class CXRect CListWnd::GetHeaderRect(int)const; +EQLIB_OBJECT class CXRect CListWnd::GetItemRect(int,int)const; +EQLIB_OBJECT class CXRect CListWnd::GetSeparatorRect(int)const; +EQLIB_OBJECT class CXStr CListWnd::GetColumnLabel(int)const; +EQLIB_OBJECT class CXStr *CListWnd::GetItemText(class CXStr *,int,int)const; +EQLIB_OBJECT int CListWnd::AddColumn(class CXStr,class CTextureAnimation *,int,unsigned __int32,unsigned __int32,class CTextureAnimation *,class CTextureAnimation *); +EQLIB_OBJECT int CListWnd::AddColumn(class CXStr,int,unsigned __int32,unsigned __int32); +EQLIB_OBJECT int CListWnd::AddLine(class SListWndLine const *); +EQLIB_OBJECT int CListWnd::AddString(const CXStr &Str, COLORREF Color, uint32_t Data = 0, const CTextureAnimation *pTa = NULL, const char*TooltipStr = NULL); +EQLIB_OBJECT int CListWnd::AddString(const char *Str, COLORREF Color, uint32_t Data, const CTextureAnimation *pTa, const char* TooltipStr = NULL); +EQLIB_OBJECT int CListWnd::GetColumnJustification(int)const; +EQLIB_OBJECT int CListWnd::GetColumnMinWidth(int)const; +EQLIB_OBJECT int CListWnd::GetColumnWidth(int)const; +EQLIB_OBJECT int CListWnd::GetCurCol(void)const; +EQLIB_OBJECT int CListWnd::GetCurSel(void)const; +EQLIB_OBJECT int CListWnd::GetItemAtPoint(class CXPoint)const; +EQLIB_OBJECT int CListWnd::GetItemHeight(int)const; +EQLIB_OBJECT unsigned __int32 CListWnd::GetColumnFlags(int)const; +EQLIB_OBJECT unsigned __int32 CListWnd::GetItemData(int)const; +EQLIB_OBJECT unsigned long CListWnd::GetItemColor(int,int)const; +EQLIB_OBJECT void CListWnd::CalculateFirstVisibleLine(void); +EQLIB_OBJECT void CListWnd::CalculateLineHeights(void); +EQLIB_OBJECT void CListWnd::CalculateVSBRange(void); +EQLIB_OBJECT void CListWnd::ClearAllSel(void); +EQLIB_OBJECT void CListWnd::ClearSel(int); +EQLIB_OBJECT void CListWnd::CloseAndUpdateEditWindow(void); +EQLIB_OBJECT void CListWnd::EnableLine(int,bool); +EQLIB_OBJECT void CListWnd::EnsureVisible(int); +EQLIB_OBJECT void CListWnd::ExtendSel(int); +EQLIB_OBJECT void CListWnd::GetItemAtPoint(class CXPoint,int *,int *)const; +EQLIB_OBJECT void CListWnd::RemoveLine(int); +EQLIB_OBJECT void CListWnd::RemoveString(int); +EQLIB_OBJECT void CListWnd::SetColors(unsigned long,unsigned long,unsigned long); +EQLIB_OBJECT void CListWnd::SetColumnJustification(int,int); +EQLIB_OBJECT void CListWnd::SetColumnLabel(int,class CXStr); +EQLIB_OBJECT void CListWnd::SetColumnWidth(int,int); +EQLIB_OBJECT void CListWnd::SetCurSel(int); +EQLIB_OBJECT void CListWnd::SetItemColor(int,int,unsigned long); +EQLIB_OBJECT void CListWnd::SetItemData(int,unsigned __int32); +EQLIB_OBJECT void CListWnd::SetItemText(int,int,class CXStr *); +EQLIB_OBJECT void CListWnd::ShiftColumnSeparator(int,int); +EQLIB_OBJECT void CListWnd::ToggleSel(int); +// virtual +EQLIB_OBJECT CListWnd::~CListWnd(void); +EQLIB_OBJECT class CTextureAnimation * CListWnd::GetCursorToDisplay(void)const; +EQLIB_OBJECT int CListWnd::Compare(class SListWndLine const &,class SListWndLine const &)const; +EQLIB_OBJECT int CListWnd::Draw(void)const; +EQLIB_OBJECT int CListWnd::DrawBackground(void)const; +EQLIB_OBJECT int CListWnd::DrawColumnSeparators(void)const; +EQLIB_OBJECT int CListWnd::DrawHeader(void)const; +EQLIB_OBJECT int CListWnd::DrawItem(int,int,int)const; +EQLIB_OBJECT int CListWnd::DrawLine(int)const; +EQLIB_OBJECT int CListWnd::DrawSeparator(int)const; +EQLIB_OBJECT int CListWnd::HandleLButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CListWnd::HandleLButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CListWnd::HandleLButtonUpAfterHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CListWnd::HandleMouseMove(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CListWnd::HandleRButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CListWnd::OnHeaderClick(class CXPoint); +EQLIB_OBJECT int CListWnd::OnMove(class CXRect); +EQLIB_OBJECT int CListWnd::OnResize(int,int); +EQLIB_OBJECT int CListWnd::OnVScroll(EScrollCode,int); +EQLIB_OBJECT int CListWnd::SetVScrollPos(int); +EQLIB_OBJECT int CListWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CListWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CListWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CListWnd::DeleteAll(void); +EQLIB_OBJECT void CListWnd::Sort(void); +}; + +class CLoadskinWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CLoadskinWnd::CLoadskinWnd(class CXWnd *); +EQLIB_OBJECT void CLoadskinWnd::Activate(void); +EQLIB_OBJECT void CLoadskinWnd::UpdateSkinList(void); +// virtual +EQLIB_OBJECT CLoadskinWnd::~CLoadskinWnd(void); +EQLIB_OBJECT int CLoadskinWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CLoadskinWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CLoadskinWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CLoadskinWnd::Deactivate(void); +}; + +class CLootWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CLootWnd::CLootWnd(class CXWnd *); +EQLIB_OBJECT void CLootWnd::Activate(unsigned char,long,long,long,long); +EQLIB_OBJECT void CLootWnd::AddContainerToLootArray(class EQ_Item *); +EQLIB_OBJECT void CLootWnd::AddEquipmentToLootArray(class EQ_Item *); +EQLIB_OBJECT void CLootWnd::AddNoteToLootArray(class EQ_Item *); +EQLIB_OBJECT void CLootWnd::Deactivate(bool); +EQLIB_OBJECT void CLootWnd::RequestLootSlot(int,bool); +EQLIB_OBJECT void CLootWnd::SlotLooted(int); +// virtual +EQLIB_OBJECT CLootWnd::~CLootWnd(void); +EQLIB_OBJECT int CLootWnd::OnProcessFrame(void); +EQLIB_OBJECT int CLootWnd::PostDraw(void)const; +EQLIB_OBJECT int CLootWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CLootWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CLootWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CLootWnd::Deactivate(void); +// private +EQLIB_OBJECT void CLootWnd::FinalizeLoot(void); +EQLIB_OBJECT void CLootWnd::Init(void); +/*0x208*/ BYTE Unknown0x1b8[0xd1]; // should be 2d9 on 2012/01/11 +/*0x2d9*/ BYTE LootAll; +/*0x2da*/ +}; + +class CMapToolbarWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CMapToolbarWnd::CMapToolbarWnd(class CXWnd *); +EQLIB_OBJECT void CMapToolbarWnd::Activate(void); +EQLIB_OBJECT void CMapToolbarWnd::SetAutoMapButton(bool); +// virtual +EQLIB_OBJECT CMapToolbarWnd::~CMapToolbarWnd(void); +EQLIB_OBJECT int CMapToolbarWnd::OnProcessFrame(void); +EQLIB_OBJECT int CMapToolbarWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CMapToolbarWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CMapToolbarWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CMapToolbarWnd::Deactivate(void); +}; + +class CMapViewWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CMapViewWnd::CMapViewWnd(class CXWnd *); +EQLIB_OBJECT bool CMapViewWnd::IsMappingEnabled(void); +EQLIB_OBJECT void CMapViewWnd::Activate(void); +EQLIB_OBJECT void CMapViewWnd::ActivateAutoMapping(void); +EQLIB_OBJECT void CMapViewWnd::DeactivateAutoMapping(void); +//EQLIB_OBJECT void CMapViewWnd::SetCurrentZone(EQZoneIndex,struct T3D_XYZ *,struct T3D_XYZ *); +// virtual +EQLIB_OBJECT CMapViewWnd::~CMapViewWnd(void); +EQLIB_OBJECT int CMapViewWnd::HandleLButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CMapViewWnd::HandleLButtonHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CMapViewWnd::HandleLButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CMapViewWnd::HandleLButtonUpAfterHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CMapViewWnd::HandleWheelMove(class CXPoint,int,unsigned __int32); +EQLIB_OBJECT int CMapViewWnd::OnProcessFrame(void); +EQLIB_OBJECT int CMapViewWnd::PostDraw(void)const; +EQLIB_OBJECT int CMapViewWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CMapViewWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CMapViewWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CMapViewWnd::Deactivate(void); +EQLIB_OBJECT void CMapViewWnd::LoadIniInfo(void); +EQLIB_OBJECT void CMapViewWnd::StoreIniInfo(void); +// private +EQLIB_OBJECT void CMapViewWnd::Init(void); +}; + +class CMemoryStream +{ +public: +EQLIB_OBJECT class CXStr CMemoryStream::GetString(void); +EQLIB_OBJECT static int __cdecl CMemoryStream::GetStringSize(class CXStr &); +EQLIB_OBJECT void CMemoryStream::GetString(class CXStr &); +EQLIB_OBJECT void CMemoryStream::PutString(class CXStr &); +}; + +class CMerchantWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CMerchantWnd::CMerchantWnd(class CXWnd *); +EQLIB_OBJECT void CMerchantWnd::Activate(class EQPlayer *,float); +EQLIB_OBJECT void CMerchantWnd::AddContainerToMercArray(class EQ_Container *); +EQLIB_OBJECT void CMerchantWnd::AddEquipmentToMercArray(class EQ_Equipment *); +EQLIB_OBJECT void CMerchantWnd::AddNoteToMercArray(class EQ_Note *); +EQLIB_OBJECT void CMerchantWnd::ClearMerchantSlot(int); +EQLIB_OBJECT void CMerchantWnd::FinishBuyingItem(struct _sell_msg *); +EQLIB_OBJECT void CMerchantWnd::FinishSellingItem(struct _sell_msg *); +EQLIB_OBJECT void CMerchantWnd::SelectBuySellSlot(int,class CTextureAnimation *); +// virtual +EQLIB_OBJECT CMerchantWnd::~CMerchantWnd(void); +EQLIB_OBJECT int CMerchantWnd::OnProcessFrame(void); +EQLIB_OBJECT int CMerchantWnd::PostDraw(void)const; +EQLIB_OBJECT int CMerchantWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CMerchantWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CMerchantWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CMerchantWnd::Deactivate(void); +// private +EQLIB_OBJECT void CMerchantWnd::DisplayBuyOrSellPrice(bool,class EQ_Item *); +EQLIB_OBJECT void CMerchantWnd::HandleBuy(int); +EQLIB_OBJECT void CMerchantWnd::HandleSell(int); +EQLIB_OBJECT void CMerchantWnd::Init(void); +EQLIB_OBJECT void CMerchantWnd::RequestBuyItem(int); +EQLIB_OBJECT void CMerchantWnd::RequestSellItem(int); +EQLIB_OBJECT void CMerchantWnd::UpdateBuySellButtons(void); +}; + +class CMusicPlayerWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CMusicPlayerWnd::CMusicPlayerWnd(class CXWnd *); +EQLIB_OBJECT void CMusicPlayerWnd::Activate(void); +EQLIB_OBJECT void CMusicPlayerWnd::AutoStart(void); +// virtual +EQLIB_OBJECT CMusicPlayerWnd::~CMusicPlayerWnd(void); +EQLIB_OBJECT int CMusicPlayerWnd::Draw(void)const; +EQLIB_OBJECT int CMusicPlayerWnd::OnProcessFrame(void); +EQLIB_OBJECT int CMusicPlayerWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CMusicPlayerWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CMusicPlayerWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CMusicPlayerWnd::Deactivate(void); +EQLIB_OBJECT void CMusicPlayerWnd::LoadIniInfo(void); +EQLIB_OBJECT void CMusicPlayerWnd::StoreIniInfo(void); +// protected +EQLIB_OBJECT void CMusicPlayerWnd::Update(void); +EQLIB_OBJECT void CMusicPlayerWnd::UpdateButtons(void); +// private +EQLIB_OBJECT void CMusicPlayerWnd::Init(void); +}; + +class CMutexLock +{ +public: +EQLIB_OBJECT CMutexLock::~CMutexLock(void); +}; + +class CMutexLockCounted +{ +public: +EQLIB_OBJECT CMutexLockCounted::~CMutexLockCounted(void); +}; + +class CMutexSync +{ +public: +// private +EQLIB_OBJECT static int CMutexSync::isValid; +}; + +class CMutexSyncCounted +{ +public: +EQLIB_OBJECT CMutexSyncCounted::~CMutexSyncCounted(void); +EQLIB_OBJECT CMutexSyncCounted::CMutexSyncCounted(void); +}; + +class CNoteWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CNoteWnd::CNoteWnd(class CXWnd *); +EQLIB_OBJECT bool CNoteWnd::CheckNote(class EQ_Note *); +EQLIB_OBJECT void CNoteWnd::Activate(void); +EQLIB_OBJECT void CNoteWnd::SetNote(char *); +// virtual +EQLIB_OBJECT CNoteWnd::~CNoteWnd(void); +EQLIB_OBJECT int CNoteWnd::HandleKeyboardMsg(unsigned __int32,unsigned __int32,bool); +EQLIB_OBJECT int CNoteWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CNoteWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CNoteWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CNoteWnd::Deactivate(void); +// private +EQLIB_OBJECT void CNoteWnd::Init(void); +}; + +class ConversationJournal +{ +public: +EQLIB_OBJECT ConversationJournal::~ConversationJournal(void); +EQLIB_OBJECT ConversationJournal::ConversationJournal(void); +EQLIB_OBJECT class JournalNPC * ConversationJournal::FindNPCByNameZone(char *,int); +EQLIB_OBJECT class JournalNPC * ConversationJournal::GetNPC(int); +EQLIB_OBJECT int ConversationJournal::AddEntry(char *,int,long,float,float,float,char *,int); +EQLIB_OBJECT int ConversationJournal::DeleteNPC(char *,int); +EQLIB_OBJECT int ConversationJournal::Load(char *); +EQLIB_OBJECT int ConversationJournal::Save(char *); +EQLIB_OBJECT struct JournalCategory * * ConversationJournal::GetCategoryList(void); +EQLIB_OBJECT struct JournalCategory * ConversationJournal::AddCategory(char *,char *,int); +EQLIB_OBJECT struct JournalCategory * ConversationJournal::AddCategory(int); +EQLIB_OBJECT struct JournalCategory * ConversationJournal::GetCategory(char *); +EQLIB_OBJECT struct JournalCategory * ConversationJournal::GetCategory(int); +EQLIB_OBJECT void ConversationJournal::Clean(void); +EQLIB_OBJECT void ConversationJournal::DeleteCategory(int); +// protected +EQLIB_OBJECT int ConversationJournal::FindFreeID(void); +// private +EQLIB_OBJECT class JournalNPC * ConversationJournal::AddNPC(char *,int); +EQLIB_OBJECT class JournalNPC * ConversationJournal::ReadNPC(struct _iobuf *); +EQLIB_OBJECT void ConversationJournal::AllocateCatArray(void); +EQLIB_OBJECT void ConversationJournal::AllocateNPCArray(void); +EQLIB_OBJECT void ConversationJournal::ReadCategory(struct _iobuf *); +}; + +class COptionsWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT COptionsWnd::COptionsWnd(class CXWnd *); +//EQLIB_OBJECT COptionsWnd::KeyboardAssignmentData::~KeyboardAssignmentData(void); +//EQLIB_OBJECT COptionsWnd::KeyboardAssignmentData::KeyboardAssignmentData(void); +EQLIB_OBJECT void COptionsWnd::Activate(void); +EQLIB_OBJECT void COptionsWnd::RefreshCurrentKeyboardAssignmentList(void); +EQLIB_OBJECT void COptionsWnd::ResetKeysToDefault(void); +EQLIB_OBJECT void COptionsWnd::RestoreDefaultColors(void); +// virtual +EQLIB_OBJECT COptionsWnd::~COptionsWnd(void); +EQLIB_OBJECT int COptionsWnd::HandleKeyboardMsg(unsigned __int32,unsigned __int32,bool); +EQLIB_OBJECT int COptionsWnd::OnProcessFrame(void); +EQLIB_OBJECT int COptionsWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * COptionsWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * COptionsWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void COptionsWnd::Deactivate(void); +// private +EQLIB_OBJECT int COptionsWnd::ChatPageOnProcessFrame(void); +EQLIB_OBJECT int COptionsWnd::ChatPageWndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int COptionsWnd::ColorPageOnProcessFrame(void); +EQLIB_OBJECT int COptionsWnd::ColorPageWndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int COptionsWnd::DisplayPageOnProcessFrame(void); +EQLIB_OBJECT int COptionsWnd::DisplayPageWndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int COptionsWnd::GeneralPageOnProcessFrame(void); +EQLIB_OBJECT int COptionsWnd::GeneralPageWndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int COptionsWnd::KeyboardPageDeactivate(void); +EQLIB_OBJECT int COptionsWnd::KeyboardPageHandleKeyboardMsg(unsigned __int32,unsigned __int32,bool); +EQLIB_OBJECT int COptionsWnd::KeyboardPageOnProcessFrame(void); +EQLIB_OBJECT int COptionsWnd::KeyboardPageWndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int COptionsWnd::MousePageOnProcessFrame(void); +EQLIB_OBJECT int COptionsWnd::MousePageWndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int COptionsWnd::RedirectDeactivateTo(class CPageWnd *); +EQLIB_OBJECT int COptionsWnd::RedirectHandleKeyboardMsgTo(class CPageWnd *,unsigned __int32,unsigned __int32,bool); +EQLIB_OBJECT int COptionsWnd::RedirectOnProcessFrameTo(class CPageWnd *); +EQLIB_OBJECT int COptionsWnd::RedirectWndNotificationTo(class CPageWnd *,class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT void COptionsWnd::AddKeyboardAssignment(int,int,int); +EQLIB_OBJECT void COptionsWnd::InitKeyboardAssignments(void); +EQLIB_OBJECT void COptionsWnd::InitKeyboardPage(void); +EQLIB_OBJECT void COptionsWnd::KeyboardPageCancelKeypressAssignment(void); +EQLIB_OBJECT void COptionsWnd::SaveColors(int,int,int,int); +EQLIB_OBJECT void COptionsWnd::SetBagOptions(int,int); +EQLIB_OBJECT void COptionsWnd::SyncChatPage(void); +EQLIB_OBJECT void COptionsWnd::SyncColorPage(void); +EQLIB_OBJECT void COptionsWnd::SyncDisplayPage(void); +EQLIB_OBJECT void COptionsWnd::SyncGeneralPage(void); +EQLIB_OBJECT void COptionsWnd::SyncMousePage(void); +}; + +class CPageTemplate +{ +public: +EQLIB_OBJECT CPageTemplate::CPageTemplate(class CParamPage *); +// virtual +EQLIB_OBJECT CPageTemplate::~CPageTemplate(void); +//EQLIB_OBJECT void * CPageTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CPageTemplate::`vector deleting destructor'(unsigned int); +}; + +class CPageWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CPageWnd::CPageWnd(class CXWnd *,unsigned __int32,class CXRect,class CXStr,class CPageTemplate *); +EQLIB_OBJECT class CXStr CPageWnd::GetTabText(void)const; +// virtual +EQLIB_OBJECT CPageWnd::~CPageWnd(void); +//EQLIB_OBJECT void * CPageWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CPageWnd::`vector deleting destructor'(unsigned int); +}; + +class CParam +{ +public: +EQLIB_OBJECT class CParam & CParam::operator=(class CParam const &); +// virtual +EQLIB_OBJECT CParam::~CParam(void); +//EQLIB_OBJECT void * CParam::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParam::`vector deleting destructor'(unsigned int); +}; + +class CParamButton +{ +public: +EQLIB_OBJECT CParamButton::CParamButton(void); +EQLIB_OBJECT class CParamButton & CParamButton::operator=(class CParamButton const &); +// virtual +EQLIB_OBJECT CParamButton::~CParamButton(void); +EQLIB_OBJECT bool CParamButton::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamButton::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamButton::GetStreamSize(void); +//EQLIB_OBJECT void * CParamButton::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamButton::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamButton::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamButton::WriteToStream(class CMemoryStream &); +}; + +class CParamButtonDrawTemplate +{ +public: +EQLIB_OBJECT CParamButtonDrawTemplate::CParamButtonDrawTemplate(void); +EQLIB_OBJECT class CParamButtonDrawTemplate & CParamButtonDrawTemplate::operator=(class CParamButtonDrawTemplate const &); +// virtual +EQLIB_OBJECT CParamButtonDrawTemplate::~CParamButtonDrawTemplate(void); +EQLIB_OBJECT bool CParamButtonDrawTemplate::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamButtonDrawTemplate::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamButtonDrawTemplate::GetStreamSize(void); +//EQLIB_OBJECT void * CParamButtonDrawTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamButtonDrawTemplate::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamButtonDrawTemplate::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamButtonDrawTemplate::WriteToStream(class CMemoryStream &); +}; + +class CParamClass +{ +public: +EQLIB_OBJECT CParamClass::CParamClass(void); +EQLIB_OBJECT class CParamClass & CParamClass::operator=(class CParamClass const &); +// virtual +EQLIB_OBJECT CParamClass::~CParamClass(void); +EQLIB_OBJECT bool CParamClass::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamClass::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamClass::GetStreamSize(void); +//EQLIB_OBJECT void * CParamClass::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamClass::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamClass::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamClass::WriteToStream(class CMemoryStream &); +}; + +class CParamCombobox +{ +public: +EQLIB_OBJECT CParamCombobox::CParamCombobox(void); +EQLIB_OBJECT class CParamCombobox & CParamCombobox::operator=(class CParamCombobox const &); +// virtual +EQLIB_OBJECT CParamCombobox::~CParamCombobox(void); +EQLIB_OBJECT bool CParamCombobox::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamCombobox::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamCombobox::GetStreamSize(void); +//EQLIB_OBJECT void * CParamCombobox::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamCombobox::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamCombobox::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamCombobox::WriteToStream(class CMemoryStream &); +}; + +class CParamControl +{ +public: +EQLIB_OBJECT CParamControl::CParamControl(void); +EQLIB_OBJECT class CParamControl & CParamControl::operator=(class CParamControl const &); +// virtual +EQLIB_OBJECT CParamControl::~CParamControl(void); +EQLIB_OBJECT bool CParamControl::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamControl::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamControl::GetStreamSize(void); +//EQLIB_OBJECT void * CParamControl::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamControl::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamControl::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamControl::WriteToStream(class CMemoryStream &); +}; + +class CParamEditbox +{ +public: +EQLIB_OBJECT CParamEditbox::CParamEditbox(void); +EQLIB_OBJECT class CParamEditbox & CParamEditbox::operator=(class CParamEditbox const &); +// virtual +EQLIB_OBJECT CParamEditbox::~CParamEditbox(void); +EQLIB_OBJECT bool CParamEditbox::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamEditbox::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamEditbox::GetStreamSize(void); +//EQLIB_OBJECT void * CParamEditbox::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamEditbox::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamEditbox::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamEditbox::WriteToStream(class CMemoryStream &); +}; + +class CParamFrame +{ +public: +EQLIB_OBJECT CParamFrame::CParamFrame(void); +// virtual +EQLIB_OBJECT CParamFrame::~CParamFrame(void); +EQLIB_OBJECT bool CParamFrame::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamFrame::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamFrame::GetStreamSize(void); +//EQLIB_OBJECT void * CParamFrame::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamFrame::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamFrame::WriteToStream(class CMemoryStream &); +}; + +class CParamFrameTemplate +{ +public: +EQLIB_OBJECT CParamFrameTemplate::CParamFrameTemplate(void); +EQLIB_OBJECT class CParamFrameTemplate & CParamFrameTemplate::operator=(class CParamFrameTemplate const &); +// virtual +EQLIB_OBJECT CParamFrameTemplate::~CParamFrameTemplate(void); +EQLIB_OBJECT bool CParamFrameTemplate::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamFrameTemplate::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamFrameTemplate::GetStreamSize(void); +//EQLIB_OBJECT void * CParamFrameTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamFrameTemplate::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamFrameTemplate::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamFrameTemplate::WriteToStream(class CMemoryStream &); +}; + +class CParamGauge +{ +public: +EQLIB_OBJECT CParamGauge::CParamGauge(void); +EQLIB_OBJECT class CParamGauge & CParamGauge::operator=(class CParamGauge const &); +// virtual +EQLIB_OBJECT CParamGauge::~CParamGauge(void); +EQLIB_OBJECT bool CParamGauge::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamGauge::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamGauge::GetStreamSize(void); +//EQLIB_OBJECT void * CParamGauge::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamGauge::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamGauge::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamGauge::WriteToStream(class CMemoryStream &); +}; + +class CParamGaugeDrawTemplate +{ +public: +EQLIB_OBJECT CParamGaugeDrawTemplate::CParamGaugeDrawTemplate(void); +EQLIB_OBJECT class CParamGaugeDrawTemplate & CParamGaugeDrawTemplate::operator=(class CParamGaugeDrawTemplate const &); +// virtual +EQLIB_OBJECT CParamGaugeDrawTemplate::~CParamGaugeDrawTemplate(void); +EQLIB_OBJECT bool CParamGaugeDrawTemplate::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamGaugeDrawTemplate::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamGaugeDrawTemplate::GetStreamSize(void); +//EQLIB_OBJECT void * CParamGaugeDrawTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamGaugeDrawTemplate::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamGaugeDrawTemplate::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamGaugeDrawTemplate::WriteToStream(class CMemoryStream &); +}; + +class CParamInvSlot +{ +public: +EQLIB_OBJECT CParamInvSlot::CParamInvSlot(void); +EQLIB_OBJECT class CParamInvSlot & CParamInvSlot::operator=(class CParamInvSlot const &); +// virtual +EQLIB_OBJECT CParamInvSlot::~CParamInvSlot(void); +EQLIB_OBJECT bool CParamInvSlot::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamInvSlot::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamInvSlot::GetStreamSize(void); +//EQLIB_OBJECT void * CParamInvSlot::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamInvSlot::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamInvSlot::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamInvSlot::WriteToStream(class CMemoryStream &); +}; + +class CParamLabel +{ +public: +EQLIB_OBJECT CParamLabel::CParamLabel(void); +EQLIB_OBJECT class CParamLabel & CParamLabel::operator=(class CParamLabel const &); +// virtual +EQLIB_OBJECT CParamLabel::~CParamLabel(void); +EQLIB_OBJECT bool CParamLabel::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamLabel::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamLabel::GetStreamSize(void); +//EQLIB_OBJECT void * CParamLabel::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamLabel::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamLabel::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamLabel::WriteToStream(class CMemoryStream &); +}; + +class CParamListbox +{ +public: +EQLIB_OBJECT CParamListbox::CParamListbox(void); +EQLIB_OBJECT class CParamListbox & CParamListbox::operator=(class CParamListbox const &); +// virtual +EQLIB_OBJECT CParamListbox::~CParamListbox(void); +EQLIB_OBJECT bool CParamListbox::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamListbox::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamListbox::GetStreamSize(void); +//EQLIB_OBJECT void * CParamListbox::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamListbox::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamListbox::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamListbox::WriteToStream(class CMemoryStream &); +}; + +class CParamListboxColumn +{ +public: +EQLIB_OBJECT CParamListboxColumn::CParamListboxColumn(void); +EQLIB_OBJECT class CParamListboxColumn & CParamListboxColumn::operator=(class CParamListboxColumn const &); +// virtual +EQLIB_OBJECT CParamListboxColumn::~CParamListboxColumn(void); +EQLIB_OBJECT bool CParamListboxColumn::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamListboxColumn::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamListboxColumn::GetStreamSize(void); +//EQLIB_OBJECT void * CParamListboxColumn::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamListboxColumn::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamListboxColumn::WriteToStream(class CMemoryStream &); +}; + +class CParamPage +{ +public: +EQLIB_OBJECT CParamPage::CParamPage(void); +EQLIB_OBJECT class CParamPage & CParamPage::operator=(class CParamPage const &); +// virtual +EQLIB_OBJECT CParamPage::~CParamPage(void); +EQLIB_OBJECT bool CParamPage::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamPage::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamPage::GetStreamSize(void); +//EQLIB_OBJECT void * CParamPage::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamPage::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamPage::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamPage::WriteToStream(class CMemoryStream &); +}; + +class CParamPoint +{ +public: +EQLIB_OBJECT CParamPoint::CParamPoint(void); +EQLIB_OBJECT class CParamPoint & CParamPoint::operator=(class CParamPoint const &); +// virtual +EQLIB_OBJECT CParamPoint::~CParamPoint(void); +EQLIB_OBJECT bool CParamPoint::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamPoint::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamPoint::GetStreamSize(void); +//EQLIB_OBJECT void * CParamPoint::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamPoint::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamPoint::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamPoint::WriteToStream(class CMemoryStream &); +}; + +class CParamRGB +{ +public: +EQLIB_OBJECT CParamRGB::CParamRGB(void); +EQLIB_OBJECT class CParamRGB & CParamRGB::operator=(class CParamRGB const &); +// virtual +EQLIB_OBJECT CParamRGB::~CParamRGB(void); +EQLIB_OBJECT bool CParamRGB::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamRGB::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamRGB::GetStreamSize(void); +//EQLIB_OBJECT void * CParamRGB::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamRGB::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamRGB::WriteToStream(class CMemoryStream &); +}; + +class CParamScreen +{ +public: +EQLIB_OBJECT CParamScreen::CParamScreen(void); +EQLIB_OBJECT class CParamScreen & CParamScreen::operator=(class CParamScreen const &); +// virtual +EQLIB_OBJECT CParamScreen::~CParamScreen(void); +EQLIB_OBJECT bool CParamScreen::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamScreen::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamScreen::GetStreamSize(void); +//EQLIB_OBJECT void * CParamScreen::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamScreen::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamScreen::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamScreen::WriteToStream(class CMemoryStream &); +}; + +class CParamScreenPiece +{ +public: +EQLIB_OBJECT CParamScreenPiece::CParamScreenPiece(void); +EQLIB_OBJECT class CParamScreenPiece & CParamScreenPiece::operator=(class CParamScreenPiece const &); +// virtual +EQLIB_OBJECT CParamScreenPiece::~CParamScreenPiece(void); +EQLIB_OBJECT bool CParamScreenPiece::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamScreenPiece::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamScreenPiece::GetStreamSize(void); +//EQLIB_OBJECT void * CParamScreenPiece::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamScreenPiece::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamScreenPiece::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamScreenPiece::WriteToStream(class CMemoryStream &); +}; + +class CParamScrollbarDrawTemplate +{ +public: +EQLIB_OBJECT CParamScrollbarDrawTemplate::CParamScrollbarDrawTemplate(void); +EQLIB_OBJECT class CParamScrollbarDrawTemplate & CParamScrollbarDrawTemplate::operator=(class CParamScrollbarDrawTemplate const &); +// virtual +EQLIB_OBJECT CParamScrollbarDrawTemplate::~CParamScrollbarDrawTemplate(void); +EQLIB_OBJECT bool CParamScrollbarDrawTemplate::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamScrollbarDrawTemplate::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamScrollbarDrawTemplate::GetStreamSize(void); +//EQLIB_OBJECT void * CParamScrollbarDrawTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamScrollbarDrawTemplate::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamScrollbarDrawTemplate::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamScrollbarDrawTemplate::WriteToStream(class CMemoryStream &); +}; + +class CParamSize +{ +public: +EQLIB_OBJECT CParamSize::CParamSize(void); +EQLIB_OBJECT class CParamSize & CParamSize::operator=(class CParamSize const &); +// virtual +EQLIB_OBJECT CParamSize::~CParamSize(void); +EQLIB_OBJECT bool CParamSize::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamSize::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamSize::GetStreamSize(void); +//EQLIB_OBJECT void * CParamSize::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamSize::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamSize::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamSize::WriteToStream(class CMemoryStream &); +}; + +class CParamSlider +{ +public: +EQLIB_OBJECT CParamSlider::CParamSlider(void); +EQLIB_OBJECT class CParamSlider & CParamSlider::operator=(class CParamSlider const &); +// virtual +EQLIB_OBJECT CParamSlider::~CParamSlider(void); +EQLIB_OBJECT bool CParamSlider::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamSlider::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamSlider::GetStreamSize(void); +//EQLIB_OBJECT void * CParamSlider::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamSlider::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamSlider::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamSlider::WriteToStream(class CMemoryStream &); +}; + +class CParamSliderDrawTemplate +{ +public: +EQLIB_OBJECT CParamSliderDrawTemplate::CParamSliderDrawTemplate(void); +EQLIB_OBJECT class CParamSliderDrawTemplate & CParamSliderDrawTemplate::operator=(class CParamSliderDrawTemplate const &); +// virtual +EQLIB_OBJECT CParamSliderDrawTemplate::~CParamSliderDrawTemplate(void); +EQLIB_OBJECT bool CParamSliderDrawTemplate::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamSliderDrawTemplate::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamSliderDrawTemplate::GetStreamSize(void); +//EQLIB_OBJECT void * CParamSliderDrawTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamSliderDrawTemplate::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamSliderDrawTemplate::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamSliderDrawTemplate::WriteToStream(class CMemoryStream &); +}; + +class CParamSpellGem +{ +public: +EQLIB_OBJECT CParamSpellGem::CParamSpellGem(void); +EQLIB_OBJECT class CParamSpellGem & CParamSpellGem::operator=(class CParamSpellGem const &); +// virtual +EQLIB_OBJECT CParamSpellGem::~CParamSpellGem(void); +EQLIB_OBJECT bool CParamSpellGem::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamSpellGem::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamSpellGem::GetStreamSize(void); +//EQLIB_OBJECT void * CParamSpellGem::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamSpellGem::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamSpellGem::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamSpellGem::WriteToStream(class CMemoryStream &); +}; + +class CParamSpellGemDrawTemplate +{ +public: +EQLIB_OBJECT CParamSpellGemDrawTemplate::CParamSpellGemDrawTemplate(void); +EQLIB_OBJECT class CParamSpellGemDrawTemplate & CParamSpellGemDrawTemplate::operator=(class CParamSpellGemDrawTemplate const &); +// virtual +EQLIB_OBJECT CParamSpellGemDrawTemplate::~CParamSpellGemDrawTemplate(void); +EQLIB_OBJECT bool CParamSpellGemDrawTemplate::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamSpellGemDrawTemplate::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamSpellGemDrawTemplate::GetStreamSize(void); +//EQLIB_OBJECT void * CParamSpellGemDrawTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamSpellGemDrawTemplate::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamSpellGemDrawTemplate::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamSpellGemDrawTemplate::WriteToStream(class CMemoryStream &); +}; + +class CParamStaticAnimation +{ +public: +EQLIB_OBJECT CParamStaticAnimation::CParamStaticAnimation(void); +EQLIB_OBJECT class CParamStaticAnimation & CParamStaticAnimation::operator=(class CParamStaticAnimation const &); +// virtual +EQLIB_OBJECT CParamStaticAnimation::~CParamStaticAnimation(void); +EQLIB_OBJECT bool CParamStaticAnimation::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamStaticAnimation::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamStaticAnimation::GetStreamSize(void); +//EQLIB_OBJECT void * CParamStaticAnimation::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamStaticAnimation::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamStaticAnimation::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamStaticAnimation::WriteToStream(class CMemoryStream &); +}; + +class CParamStaticFrame +{ +public: +EQLIB_OBJECT CParamStaticFrame::CParamStaticFrame(void); +EQLIB_OBJECT class CParamStaticFrame & CParamStaticFrame::operator=(class CParamStaticFrame const &); +// virtual +EQLIB_OBJECT CParamStaticFrame::~CParamStaticFrame(void); +EQLIB_OBJECT bool CParamStaticFrame::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamStaticFrame::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamStaticFrame::GetStreamSize(void); +//EQLIB_OBJECT void * CParamStaticFrame::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamStaticFrame::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamStaticFrame::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamStaticFrame::WriteToStream(class CMemoryStream &); +}; + +class CParamStaticHeader +{ +public: +EQLIB_OBJECT CParamStaticHeader::CParamStaticHeader(void); +EQLIB_OBJECT class CParamStaticHeader & CParamStaticHeader::operator=(class CParamStaticHeader const &); +// virtual +EQLIB_OBJECT CParamStaticHeader::~CParamStaticHeader(void); +EQLIB_OBJECT bool CParamStaticHeader::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamStaticHeader::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamStaticHeader::GetStreamSize(void); +//EQLIB_OBJECT void * CParamStaticHeader::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamStaticHeader::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamStaticHeader::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamStaticHeader::WriteToStream(class CMemoryStream &); +}; + +class CParamStaticScreenPiece +{ +public: +EQLIB_OBJECT CParamStaticScreenPiece::CParamStaticScreenPiece(void); +// virtual +EQLIB_OBJECT CParamStaticScreenPiece::~CParamStaticScreenPiece(void); +EQLIB_OBJECT bool CParamStaticScreenPiece::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamStaticScreenPiece::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamStaticScreenPiece::GetStreamSize(void); +//EQLIB_OBJECT void * CParamStaticScreenPiece::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamStaticScreenPiece::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamStaticScreenPiece::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamStaticScreenPiece::WriteToStream(class CMemoryStream &); +}; + +class CParamStaticText +{ +public: +EQLIB_OBJECT CParamStaticText::CParamStaticText(void); +EQLIB_OBJECT class CParamStaticText & CParamStaticText::operator=(class CParamStaticText const &); +// virtual +EQLIB_OBJECT CParamStaticText::~CParamStaticText(void); +EQLIB_OBJECT bool CParamStaticText::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamStaticText::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamStaticText::GetStreamSize(void); +//EQLIB_OBJECT void * CParamStaticText::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamStaticText::`vector deleting destructor'(unsigned int); +#define SafeYLoc 0 +EQLIB_OBJECT void CParamStaticText::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamStaticText::WriteToStream(class CMemoryStream &); +}; + +class CParamSTMLbox +{ +public: +EQLIB_OBJECT CParamSTMLbox::CParamSTMLbox(void); +// virtual +EQLIB_OBJECT CParamSTMLbox::~CParamSTMLbox(void); +EQLIB_OBJECT bool CParamSTMLbox::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamSTMLbox::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamSTMLbox::GetStreamSize(void); +//EQLIB_OBJECT void * CParamSTMLbox::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamSTMLbox::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamSTMLbox::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamSTMLbox::WriteToStream(class CMemoryStream &); +}; + +class CParamSuiteDefaults +{ +public: +EQLIB_OBJECT CParamSuiteDefaults::CParamSuiteDefaults(void); +EQLIB_OBJECT class CParamSuiteDefaults & CParamSuiteDefaults::operator=(class CParamSuiteDefaults const &); +// virtual +EQLIB_OBJECT CParamSuiteDefaults::~CParamSuiteDefaults(void); +EQLIB_OBJECT bool CParamSuiteDefaults::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamSuiteDefaults::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamSuiteDefaults::GetStreamSize(void); +//EQLIB_OBJECT void * CParamSuiteDefaults::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamSuiteDefaults::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamSuiteDefaults::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamSuiteDefaults::WriteToStream(class CMemoryStream &); +}; + +class CParamTabBox +{ +public: +EQLIB_OBJECT CParamTabBox::CParamTabBox(void); +EQLIB_OBJECT class CParamTabBox & CParamTabBox::operator=(class CParamTabBox const &); +// virtual +EQLIB_OBJECT CParamTabBox::~CParamTabBox(void); +EQLIB_OBJECT bool CParamTabBox::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamTabBox::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamTabBox::GetStreamSize(void); +//EQLIB_OBJECT void * CParamTabBox::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamTabBox::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamTabBox::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamTabBox::WriteToStream(class CMemoryStream &); +}; + +class CParamTextureInfo +{ +public: +EQLIB_OBJECT CParamTextureInfo::CParamTextureInfo(void); +// virtual +EQLIB_OBJECT CParamTextureInfo::~CParamTextureInfo(void); +EQLIB_OBJECT bool CParamTextureInfo::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamTextureInfo::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamTextureInfo::GetStreamSize(void); +//EQLIB_OBJECT void * CParamTextureInfo::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamTextureInfo::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamTextureInfo::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamTextureInfo::WriteToStream(class CMemoryStream &); +}; + +class CParamUi2DAnimation +{ +public: +EQLIB_OBJECT CParamUi2DAnimation::CParamUi2DAnimation(void); +// virtual +EQLIB_OBJECT CParamUi2DAnimation::~CParamUi2DAnimation(void); +EQLIB_OBJECT bool CParamUi2DAnimation::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamUi2DAnimation::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamUi2DAnimation::GetStreamSize(void); +//EQLIB_OBJECT void * CParamUi2DAnimation::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamUi2DAnimation::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamUi2DAnimation::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamUi2DAnimation::WriteToStream(class CMemoryStream &); +}; + +class CParamWindowDrawTemplate +{ +public: +EQLIB_OBJECT CParamWindowDrawTemplate::CParamWindowDrawTemplate(void); +// virtual +EQLIB_OBJECT CParamWindowDrawTemplate::~CParamWindowDrawTemplate(void); +EQLIB_OBJECT bool CParamWindowDrawTemplate::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CParamWindowDrawTemplate::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CParamWindowDrawTemplate::GetStreamSize(void); +//EQLIB_OBJECT void * CParamWindowDrawTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CParamWindowDrawTemplate::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CParamWindowDrawTemplate::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CParamWindowDrawTemplate::WriteToStream(class CMemoryStream &); +}; + +class CParseTokensXML +{ +public: +EQLIB_OBJECT CParseTokensXML::~CParseTokensXML(void); +//EQLIB_OBJECT bool CParseTokensXML::Accept(enum ETokTypeXML); +#define HackPackHelp 0 +EQLIB_OBJECT bool CParseTokensXML::StartFileBased(class CXStr); +EQLIB_OBJECT class CXStr CParseTokensXML::GetCurFile(void); +EQLIB_OBJECT void __cdecl CParseTokensXML::SetError(char const *,...); +}; + +class CParseTokXML +{ +public: +EQLIB_OBJECT CParseTokXML::~CParseTokXML(void); +//EQLIB_OBJECT enum ETokTypeXML CParseTokXML::NextToken(void); +//EQLIB_OBJECT void * CParseTokXML::`scalar deleting destructor'(unsigned int); +// private +EQLIB_OBJECT bool CParseTokXML::GetEntityRef(char &); +}; + +class CPetInfoWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CPetInfoWnd::CPetInfoWnd(class CXWnd *); +EQLIB_OBJECT class CButtonWnd * CPetInfoWnd::GetButton(int); +EQLIB_OBJECT void CPetInfoWnd::Activate(void); +EQLIB_OBJECT void CPetInfoWnd::SetShowOnSummon(bool); +EQLIB_OBJECT void CPetInfoWnd::Update(void); +// virtual +EQLIB_OBJECT CPetInfoWnd::~CPetInfoWnd(void); +EQLIB_OBJECT int CPetInfoWnd::OnProcessFrame(void); +EQLIB_OBJECT int CPetInfoWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CPetInfoWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CPetInfoWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CPetInfoWnd::Deactivate(void); +// private +EQLIB_OBJECT void CPetInfoWnd::Init(void); +}; + +class CPetitionQWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CPetitionQWnd::CPetitionQWnd(class CXWnd *); +EQLIB_OBJECT char * CPetitionQWnd::GetCurrentPetitionersName(void); +EQLIB_OBJECT void CPetitionQWnd::Activate(void); +EQLIB_OBJECT void CPetitionQWnd::AddGMText(void); +EQLIB_OBJECT void CPetitionQWnd::CheckedOut(struct petitionQtype const *,int); +EQLIB_OBJECT void CPetitionQWnd::ClearCurrentPet(void); +EQLIB_OBJECT void CPetitionQWnd::FillFields(void); +EQLIB_OBJECT void CPetitionQWnd::LogPetitionText(void); +EQLIB_OBJECT void CPetitionQWnd::SetButtonsForPetition(bool,bool); +EQLIB_OBJECT void CPetitionQWnd::SetPriorityDisplay(void); +EQLIB_OBJECT void CPetitionQWnd::UndoCheckout(void); +EQLIB_OBJECT void CPetitionQWnd::UpdatePetitions(void); +// virtual +EQLIB_OBJECT CPetitionQWnd::~CPetitionQWnd(void); +EQLIB_OBJECT int CPetitionQWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CPetitionQWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CPetitionQWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CPetitionQWnd::Deactivate(void); +}; + +class CPlayerNotesWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CPlayerNotesWnd::CPlayerNotesWnd(class CXWnd *); +EQLIB_OBJECT void CPlayerNotesWnd::Activate(void); +EQLIB_OBJECT void CPlayerNotesWnd::AppendText(char *); +EQLIB_OBJECT void CPlayerNotesWnd::SaveNotes(void); +// virtual +EQLIB_OBJECT CPlayerNotesWnd::~CPlayerNotesWnd(void); +EQLIB_OBJECT int CPlayerNotesWnd::Draw(void)const; +EQLIB_OBJECT int CPlayerNotesWnd::OnProcessFrame(void); +EQLIB_OBJECT int CPlayerNotesWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CPlayerNotesWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CPlayerNotesWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CPlayerNotesWnd::Deactivate(void); +// private +EQLIB_OBJECT void CPlayerNotesWnd::Init(void); +}; + +class CPlayerWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CPlayerWnd::CPlayerWnd(class CXWnd *); +EQLIB_OBJECT void CPlayerWnd::Activate(void); +EQLIB_OBJECT void CPlayerWnd::CreateLocalMenu(void); +EQLIB_OBJECT void CPlayerWnd::UpdateContextMenu(void); +// virtual +EQLIB_OBJECT CPlayerWnd::~CPlayerWnd(void); +EQLIB_OBJECT int CPlayerWnd::Draw(void)const; +EQLIB_OBJECT int CPlayerWnd::OnProcessFrame(void); +EQLIB_OBJECT int CPlayerWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CPlayerWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CPlayerWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CPlayerWnd::Deactivate(void); +EQLIB_OBJECT void CPlayerWnd::LoadIniInfo(void); +EQLIB_OBJECT void CPlayerWnd::StoreIniInfo(void); +// private +EQLIB_OBJECT void CPlayerWnd::Init(void); +}; + +class CPotionBeltWnd : public CSidlScreenWnd +{ +public: +// virtual +EQLIB_OBJECT int CPotionBeltWnd::DrawTooltip(class CXWnd const *)const; +}; +class CQuantityWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CQuantityWnd::CQuantityWnd(class CXWnd *); +EQLIB_OBJECT void CQuantityWnd::Activate(class CXWnd *,int,int,int,int,bool); +// virtual +EQLIB_OBJECT CQuantityWnd::~CQuantityWnd(void); +EQLIB_OBJECT int CQuantityWnd::Draw(void)const; +EQLIB_OBJECT int CQuantityWnd::OnProcessFrame(void); +EQLIB_OBJECT int CQuantityWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CQuantityWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CQuantityWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CQuantityWnd::Deactivate(void); +// private +//EQLIB_OBJECT void CQuantityWnd::Accept; +EQLIB_OBJECT void CQuantityWnd::CheckMaxEditWnd(void); +EQLIB_OBJECT void CQuantityWnd::UpdateEditWndFromSlider(void); +EQLIB_OBJECT void CQuantityWnd::UpdateSliderFromEditWnd(void); +}; + +class CRadioGroup +{ +public: +EQLIB_OBJECT CRadioGroup::CRadioGroup(class CXStr); +EQLIB_OBJECT class CXStr CRadioGroup::GetName(void)const; +// virtual +EQLIB_OBJECT CRadioGroup::~CRadioGroup(void); +//EQLIB_OBJECT void * CRadioGroup::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CRadioGroup::`vector deleting destructor'(unsigned int); +}; + +class CRaid +{ +public: +EQLIB_OBJECT CRaid::~CRaid(void); +EQLIB_OBJECT CRaid::CRaid(void); +EQLIB_OBJECT bool CRaid::IsInRaid(void); +EQLIB_OBJECT bool CRaid::IsInvited(void); +EQLIB_OBJECT bool CRaid::IsRaidGroupLeader(void); +EQLIB_OBJECT bool CRaid::IsRaidLeader(void); +EQLIB_OBJECT bool CRaid::IsRaidMember(char *); +EQLIB_OBJECT int CRaid::GetLootType(void); +EQLIB_OBJECT int CRaid::GetNumRaidMembers(void); +EQLIB_OBJECT struct RaidMember * CRaid::GetRaidMemberAt(int); +EQLIB_OBJECT void CRaid::AddRaidLooter(void); +EQLIB_OBJECT void CRaid::ClearInvitedState(void); +EQLIB_OBJECT void CRaid::CreateInviteRaid(void); +EQLIB_OBJECT void CRaid::HandleC2SRaidMessage(char *); +EQLIB_OBJECT void CRaid::HandleCreateInviteRaid(struct CSRaidMessage *); +EQLIB_OBJECT void CRaid::HandleS2CRaidMessage(char *); +EQLIB_OBJECT void CRaid::RemoveRaidLooter(void); +EQLIB_OBJECT void CRaid::RemoveRaidMember(void); +EQLIB_OBJECT void CRaid::ResetRaid(void); +EQLIB_OBJECT void CRaid::ResetWindow(void); +EQLIB_OBJECT void CRaid::SendInviteResponse(bool); +EQLIB_OBJECT void CRaid::SendLeadershipChange(char *); +EQLIB_OBJECT void CRaid::SendRaidChat(char *); +EQLIB_OBJECT void CRaid::SetLootType(char *); +EQLIB_OBJECT void CRaid::SetRaidLeader(char *); +EQLIB_OBJECT void CRaid::SetTargetRaidPlayer(char *); +EQLIB_OBJECT void CRaid::UpdateClassColor(int,unsigned long); +EQLIB_OBJECT void CRaid::UpdateOptionsWindow(void); +// private +EQLIB_OBJECT bool CRaid::IsRaidLooter(char *); +EQLIB_OBJECT int CRaid::FindOpenIndex(void); +EQLIB_OBJECT int CRaid::FindPlayerIndex(char *); +EQLIB_OBJECT int CRaid::FindRaidGroupLeader(int); +EQLIB_OBJECT void CRaid::AddRaidMember(struct RaidAddMember *); +EQLIB_OBJECT void CRaid::ChangeLeadership(char *); +EQLIB_OBJECT void CRaid::DeleteRaidMember(struct SCRaidMessage *); +EQLIB_OBJECT void CRaid::DetermineRaidChanges(char *); +EQLIB_OBJECT void CRaid::HandleAddLooter(char *); +EQLIB_OBJECT void CRaid::HandlePositionChange(struct SCRaidMessage *); +EQLIB_OBJECT void CRaid::HandleRemoveLooter(char *); +EQLIB_OBJECT void CRaid::HandleSetLootType(int); +EQLIB_OBJECT void CRaid::InitializeRaid(char *); +EQLIB_OBJECT void CRaid::RaidCreated(struct CreateRaidMessage *); +EQLIB_OBJECT void CRaid::RaidGroupLeaderChange(struct SCRaidMessage *); +EQLIB_OBJECT void CRaid::RenameMember(struct RenameRaidMember *); +EQLIB_OBJECT void CRaid::SendRaidMsg(int,char *,char *,int); +EQLIB_OBJECT void CRaid::SetLootTypeResponse(struct SCRaidMessage *); +EQLIB_OBJECT void CRaid::UpdateLevelAverage(void); +}; + +class CRaidOptionsWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CRaidOptionsWnd::CRaidOptionsWnd(class CXWnd *); +EQLIB_OBJECT void CRaidOptionsWnd::Activate(void); +EQLIB_OBJECT void CRaidOptionsWnd::AddLooterToList(char *); +EQLIB_OBJECT void CRaidOptionsWnd::ClearLooterList(void); +EQLIB_OBJECT void CRaidOptionsWnd::UpdateComponents(void); +// virtual +EQLIB_OBJECT CRaidOptionsWnd::~CRaidOptionsWnd(void); +EQLIB_OBJECT int CRaidOptionsWnd::OnProcessFrame(void); +EQLIB_OBJECT int CRaidOptionsWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CRaidOptionsWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CRaidOptionsWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CRaidOptionsWnd::Deactivate(void); +// private +EQLIB_OBJECT void CRaidOptionsWnd::Init(void); +EQLIB_OBJECT void CRaidOptionsWnd::InitializeClassColors(void); +}; + +class CRaidWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CRaidWnd::CRaidWnd(class CXWnd *); +EQLIB_OBJECT void CRaidWnd::Activate(void); +EQLIB_OBJECT void CRaidWnd::AddPlayertoList(char *,char *,char *,char *,int,int,bool); +EQLIB_OBJECT void CRaidWnd::ChangePosition(char *,int,int,int,bool); +EQLIB_OBJECT void CRaidWnd::ChangeRaidGroupLeader(char *,int,char *); +EQLIB_OBJECT void CRaidWnd::ClearPlayerList(void); +EQLIB_OBJECT void CRaidWnd::RemovePlayerFromList(char *,int); +EQLIB_OBJECT void CRaidWnd::SetClassColor(int,unsigned long); +EQLIB_OBJECT void CRaidWnd::SetPlayerClassColor(char *,int,int); +EQLIB_OBJECT void CRaidWnd::SetPlayerClassColor(int,int,int); +EQLIB_OBJECT void CRaidWnd::SetRaidCount(int); +EQLIB_OBJECT void CRaidWnd::SetRaidMemberRank(char *,char *,int); +EQLIB_OBJECT void CRaidWnd::SetRaidTarget(char *,int,char *,int); +EQLIB_OBJECT void CRaidWnd::UpdateButtons(void); +EQLIB_OBJECT void CRaidWnd::UpdateLevelAverage(int); +EQLIB_OBJECT void CRaidWnd::UpdateMemberName(char *,char *,int); +// virtual +EQLIB_OBJECT CRaidWnd::~CRaidWnd(void); +EQLIB_OBJECT int CRaidWnd::OnProcessFrame(void); +EQLIB_OBJECT int CRaidWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CRaidWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CRaidWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CRaidWnd::Deactivate(void); +// private +EQLIB_OBJECT int CRaidWnd::FindIndexNotInGroupList(char *); +EQLIB_OBJECT int CRaidWnd::FindOpenIndexInGroup(int); +EQLIB_OBJECT int CRaidWnd::FindPlayerIndexInGroup(char *,int); +EQLIB_OBJECT void CRaidWnd::AddSeparator(void); +EQLIB_OBJECT void CRaidWnd::Init(void); +EQLIB_OBJECT void CRaidWnd::InitializeClassColors(void); +EQLIB_OBJECT void CRaidWnd::ResortRaidGroupList(int,int); +}; + +class CRC32Generator +{ +public: +EQLIB_OBJECT unsigned int CRC32Generator::generateCRC32(unsigned char const *,unsigned int)const; +EQLIB_OBJECT unsigned int CRC32Generator::updateCRC32(unsigned int,unsigned char const *,unsigned int)const; +// private +EQLIB_OBJECT static unsigned int * CRC32Generator::_crcTable; +}; + +class CResolutionHandler +{ +public: +EQLIB_OBJECT static bool __cdecl CResolutionHandler::IsFullscreenAvailable(void); +EQLIB_OBJECT static int __cdecl CResolutionHandler::GetDesktopBitsPerPixel(void); +EQLIB_OBJECT static int __cdecl CResolutionHandler::GetDesktopHeight(void); +EQLIB_OBJECT static int __cdecl CResolutionHandler::GetDesktopRefreshRate(void); +EQLIB_OBJECT static int __cdecl CResolutionHandler::GetDesktopWidth(void); +EQLIB_OBJECT static int __cdecl CResolutionHandler::GetHeight(void); +EQLIB_OBJECT static int __cdecl CResolutionHandler::GetWidth(void); +EQLIB_OBJECT static int __cdecl CResolutionHandler::Init(void); +EQLIB_OBJECT static void __cdecl CResolutionHandler::ChangeToResolution(int,int,int,int,int); +EQLIB_OBJECT static void __cdecl CResolutionHandler::SaveSettings(void); +EQLIB_OBJECT static void __cdecl CResolutionHandler::Shutdown(void); +EQLIB_OBJECT static void __cdecl CResolutionHandler::ToggleScreenMode(void); +EQLIB_OBJECT static void __cdecl CResolutionHandler::UpdateWindowPosition(void); +// private +EQLIB_OBJECT static bool CResolutionHandler::ms_isFullscreen; +EQLIB_OBJECT static int CResolutionHandler::ms_fullscreenBitsPerPixel; +EQLIB_OBJECT static int CResolutionHandler::ms_fullscreenRefreshRate; +EQLIB_OBJECT static int CResolutionHandler::ms_height; +EQLIB_OBJECT static int CResolutionHandler::ms_width; +EQLIB_OBJECT static int CResolutionHandler::ms_windowedOffsetX; +EQLIB_OBJECT static int CResolutionHandler::ms_windowedOffsetY; +}; + +class CScreenPieceTemplate +{ +public: +EQLIB_OBJECT CScreenPieceTemplate::CScreenPieceTemplate(class CParamScreenPiece *); +EQLIB_OBJECT bool CScreenPieceTemplate::IsType(unsigned __int32)const; +EQLIB_OBJECT class CXStr CScreenPieceTemplate::GetName(void)const; +// virtual +EQLIB_OBJECT CScreenPieceTemplate::~CScreenPieceTemplate(void); +//EQLIB_OBJECT void * CScreenPieceTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CScreenPieceTemplate::`vector deleting destructor'(unsigned int); +}; + +class CScreenTemplate +{ +public: +EQLIB_OBJECT CScreenTemplate::CScreenTemplate(class CParamScreen *); +// virtual +EQLIB_OBJECT CScreenTemplate::~CScreenTemplate(void); +//EQLIB_OBJECT void * CScreenTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CScreenTemplate::`vector deleting destructor'(unsigned int); +}; + +class CScrollbarTemplate +{ +public: +EQLIB_OBJECT CScrollbarTemplate::~CScrollbarTemplate(void); +EQLIB_OBJECT CScrollbarTemplate::CScrollbarTemplate(class CScrollbarTemplate const &); +EQLIB_OBJECT CScrollbarTemplate::CScrollbarTemplate(void); +EQLIB_OBJECT class CScrollbarTemplate & CScrollbarTemplate::operator=(class CScrollbarTemplate const &); +}; + +class CSelectorWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CSelectorWnd::CSelectorWnd(class CXWnd *); +EQLIB_OBJECT void CSelectorWnd::Activate(void); +EQLIB_OBJECT void CSelectorWnd::KeyMapUpdated(void); +// virtual +EQLIB_OBJECT CSelectorWnd::~CSelectorWnd(void); +EQLIB_OBJECT int CSelectorWnd::OnProcessFrame(void); +EQLIB_OBJECT int CSelectorWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CSelectorWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CSelectorWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CSelectorWnd::Deactivate(void); +}; + +class CSidlManager +{ +public: +EQLIB_OBJECT CSidlManager::CSidlManager(void); +EQLIB_OBJECT class CButtonDrawTemplate * CSidlManager::FindButtonDrawTemplate(unsigned __int32)const; +EQLIB_OBJECT class CButtonDrawTemplate CSidlManager::GetButtonDrawTemplateFromParamButtonDrawTemplate(class CParamButtonDrawTemplate const &)const; +EQLIB_OBJECT class CGaugeDrawTemplate CSidlManager::GetGaugeDrawTemplateFromParamGaugeDrawTemplate(class CParamGaugeDrawTemplate const &)const; +EQLIB_OBJECT class CScreenPieceTemplate * CSidlManager::CreateScreenPieceTemplateFromParamScreenPiece(class CParamScreenPiece const *)const; +EQLIB_OBJECT class CScreenPieceTemplate * CSidlManager::FindScreenPieceTemplate(class CXStr *)const; +EQLIB_OBJECT class CScreenPieceTemplate * CSidlManager::FindScreenPieceTemplate(char *); +EQLIB_OBJECT class CScreenPieceTemplate * CSidlManager::FindScreenPieceTemplate(unsigned __int32)const; +EQLIB_OBJECT class CScrollbarTemplate CSidlManager::GetScrollbarTemplateFromParamScrollbarTemplate(class CParamScrollbarDrawTemplate const &)const; +EQLIB_OBJECT class CSliderDrawTemplate * CSidlManager::FindSliderDrawTemplate(class CXStr)const; +EQLIB_OBJECT class CSliderDrawTemplate * CSidlManager::FindSliderDrawTemplate(unsigned __int32)const; +EQLIB_OBJECT class CSliderDrawTemplate CSidlManager::GetSliderDrawTemplateFromParamSliderDrawTemplate(class CParamSliderDrawTemplate const &)const; +EQLIB_OBJECT class CSpellGemDrawTemplate CSidlManager::GetSpellGemDrawTemplateFromParamSpellGemDrawTemplate(class CParamSpellGemDrawTemplate const &)const; +EQLIB_OBJECT class CTAFrameDraw * CSidlManager::FindFrameDraw(unsigned __int32)const; +EQLIB_OBJECT class CTAFrameDraw CSidlManager::CreateTAFrameDrawFromSidlFrame(class CParamFrameTemplate const *)const; +EQLIB_OBJECT class CTextureAnimation * CSidlManager::FindAnimation(class CXStr)const; +EQLIB_OBJECT class CTextureAnimation * CSidlManager::FindAnimation(unsigned __int32)const; +EQLIB_OBJECT class CTextureAnimation CSidlManager::CreateTextureAnimationFromSidlAnimation(class CParamUi2DAnimation const *)const; +EQLIB_OBJECT class CXStr CSidlManager::GetParsingErrorMsg(void)const; +EQLIB_OBJECT class CXWnd * CSidlManager::CreateXWndFromTemplate(class CXWnd *,class CControlTemplate *); +EQLIB_OBJECT class CXWndDrawTemplate * CSidlManager::FindDrawTemplate(class CXStr)const; +EQLIB_OBJECT class CXWndDrawTemplate * CSidlManager::FindDrawTemplate(unsigned __int32)const; +EQLIB_OBJECT class CXWndDrawTemplate CSidlManager::CreateDrawTemplateFromParamWindowDrawTemplate(class CParamWindowDrawTemplate const *)const; +//EQLIB_OBJECT enum EStaticScreenPieceClasses CSidlManager::GetScreenPieceEnum(class CScreenPieceTemplate *)const; +EQLIB_OBJECT static class CXPoint __cdecl CSidlManager::GetPointFromParamPoint(class CParamPoint const &); +EQLIB_OBJECT static class CXRect __cdecl CSidlManager::GetRectFromParamPointSize(class CParamPoint const &,class CParamSize const &); +EQLIB_OBJECT static class CXSize __cdecl CSidlManager::GetSizeFromParamSize(class CParamSize const &); +EQLIB_OBJECT static class CXStr __cdecl CSidlManager::TranslateString(class CXStr); +EQLIB_OBJECT static unsigned long __cdecl CSidlManager::GetD3DCOLOR(class CParamRGB const &); +EQLIB_OBJECT class CUITextureInfo * CSidlManager::FindTexture(class CXStr)const; +EQLIB_OBJECT class CUITextureInfo * CSidlManager::FindTexture(unsigned __int32)const; +EQLIB_OBJECT void CSidlManager::AddAnimationInOrder(class CTextureAnimation *); +EQLIB_OBJECT void CSidlManager::AddDrawTemplateInOrder(class CXWndDrawTemplate *); +EQLIB_OBJECT void CSidlManager::AddScreenPieceTemplateInOrder(class CScreenPieceTemplate *); +EQLIB_OBJECT void CSidlManager::AddTAFrameDrawInOrder(class CTAFrameDraw *); +EQLIB_OBJECT void CSidlManager::DeleteContents(void); +EQLIB_OBJECT void CSidlManager::LoadSidl(class CXStr,class CXStr,class CXStr); +// virtual +EQLIB_OBJECT CSidlManager::~CSidlManager(void); +//EQLIB_OBJECT void * CSidlManager::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CSidlManager::`vector deleting destructor'(unsigned int); +}; + +class CSkillsSelectWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CSkillsSelectWnd::CSkillsSelectWnd(class CXWnd *); +EQLIB_OBJECT void CSkillsSelectWnd::Refresh(void); +EQLIB_OBJECT void CSkillsSelectWnd::SetTypesToDisplay(int); +// virtual +EQLIB_OBJECT CSkillsSelectWnd::~CSkillsSelectWnd(void); +EQLIB_OBJECT bool CSkillsSelectWnd::IsActive(void); +EQLIB_OBJECT int CSkillsSelectWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CSkillsSelectWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CSkillsSelectWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CSkillsSelectWnd::Activate(void); +EQLIB_OBJECT void CSkillsSelectWnd::Deactivate(void); +// private +EQLIB_OBJECT void CSkillsSelectWnd::UpdateAll(void); +EQLIB_OBJECT void CSkillsSelectWnd::UpdateSkill(int); +}; + +class CSkillsWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CSkillsWnd::CSkillsWnd(class CXWnd *); +EQLIB_OBJECT void CSkillsWnd::Activate(void); +EQLIB_OBJECT void CSkillsWnd::SkillImproveOccurred(int); +// virtual +EQLIB_OBJECT CSkillsWnd::~CSkillsWnd(void); +EQLIB_OBJECT int CSkillsWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CSkillsWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CSkillsWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CSkillsWnd::Deactivate(void); +// protected +EQLIB_OBJECT void CSkillsWnd::UpdateAll(void); +EQLIB_OBJECT void CSkillsWnd::UpdateSkill(int); +}; + +class CSliderDrawTemplate +{ +public: +EQLIB_OBJECT CSliderDrawTemplate::~CSliderDrawTemplate(void); +}; + +class CSliderTemplate +{ +public: +EQLIB_OBJECT CSliderTemplate::CSliderTemplate(class CParamSlider *); +// virtual +EQLIB_OBJECT CSliderTemplate::~CSliderTemplate(void); +//EQLIB_OBJECT void * CSliderTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CSliderTemplate::`vector deleting destructor'(unsigned int); +}; + +class CSliderWnd: public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CSliderWnd::CSliderWnd(class CXWnd *,unsigned __int32,class CXRect,class CSliderTemplate *); +EQLIB_OBJECT class CXRect CSliderWnd::GetEndCapLeftRect(void)const; +EQLIB_OBJECT class CXRect CSliderWnd::GetEndCapRightRect(void)const; +EQLIB_OBJECT class CXRect CSliderWnd::GetMiddleRangeRect(void)const; +EQLIB_OBJECT class CXRect CSliderWnd::GetThumbRect(void)const; +EQLIB_OBJECT int CSliderWnd::GetValue(void)const; +EQLIB_OBJECT void CSliderWnd::SetNumTicks(int); +EQLIB_OBJECT void CSliderWnd::SetValue(int); +// virtual +EQLIB_OBJECT CSliderWnd::~CSliderWnd(void); +EQLIB_OBJECT int CSliderWnd::Draw(void)const; +EQLIB_OBJECT int CSliderWnd::HandleKeyboardMsg(unsigned __int32,unsigned __int32,bool); +EQLIB_OBJECT int CSliderWnd::HandleLButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CSliderWnd::HandleLButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CSliderWnd::HandleLButtonUpAfterHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CSliderWnd::HandleMouseMove(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CSliderWnd::OnProcessFrame(void); +//EQLIB_OBJECT void * CSliderWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CSliderWnd::`vector deleting destructor'(unsigned int); +// private +EQLIB_OBJECT int CSliderWnd::DrawEndCapLeft(void)const; +EQLIB_OBJECT int CSliderWnd::DrawEndCapRight(void)const; +EQLIB_OBJECT int CSliderWnd::DrawMiddleRange(void)const; +EQLIB_OBJECT int CSliderWnd::DrawThumb(void)const; +EQLIB_OBJECT void CSliderWnd::SetThumbToOffset(int); +EQLIB_OBJECT void CSliderWnd::UpdateMiddleRange(void); +EQLIB_OBJECT void CSliderWnd::UpdateThumb(void); +}; + +class CSocialEditWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CSocialEditWnd::CSocialEditWnd(class CXWnd *); +EQLIB_OBJECT unsigned long CSocialEditWnd::GetSocialTextColor(int); +EQLIB_OBJECT void CSocialEditWnd::Activate(int); +// virtual +EQLIB_OBJECT CSocialEditWnd::~CSocialEditWnd(void); +EQLIB_OBJECT int CSocialEditWnd::Draw(void)const; +EQLIB_OBJECT int CSocialEditWnd::OnProcessFrame(void); +EQLIB_OBJECT int CSocialEditWnd::OnSetFocus(class CXWnd *); +EQLIB_OBJECT int CSocialEditWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CSocialEditWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CSocialEditWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CSocialEditWnd::Deactivate(void); +// private +EQLIB_OBJECT void CSocialEditWnd::ClickedAccept(void); +EQLIB_OBJECT void CSocialEditWnd::ClickedClear(void); +EQLIB_OBJECT void CSocialEditWnd::ClickedTextColorButton(int); +EQLIB_OBJECT void CSocialEditWnd::Init(void); +EQLIB_OBJECT void CSocialEditWnd::UpdateControlsFromSocial(void); +}; + +class CSoulmarkWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CSoulmarkWnd::CSoulmarkWnd(class CXWnd *); +EQLIB_OBJECT void CSoulmarkWnd::Activate(char *,char *); +EQLIB_OBJECT void CSoulmarkWnd::Activate(void); +EQLIB_OBJECT void CSoulmarkWnd::Clear(void); +EQLIB_OBJECT void CSoulmarkWnd::FillFields(void); +EQLIB_OBJECT void CSoulmarkWnd::Inquire(char *); +EQLIB_OBJECT void CSoulmarkWnd::Praise(char *); +EQLIB_OBJECT void CSoulmarkWnd::SaveMarks(void); +EQLIB_OBJECT void CSoulmarkWnd::UpdateList(void); +EQLIB_OBJECT void CSoulmarkWnd::UpdateSoulmarks(struct soulMarkMsg *); +EQLIB_OBJECT void CSoulmarkWnd::Warn(char *); +// virtual +EQLIB_OBJECT CSoulmarkWnd::~CSoulmarkWnd(void); +EQLIB_OBJECT int CSoulmarkWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CSoulmarkWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CSoulmarkWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CSoulmarkWnd::Deactivate(void); +// protected +EQLIB_OBJECT void CSoulmarkWnd::AddMark(int,char *,char *,char *); +EQLIB_OBJECT void CSoulmarkWnd::Inquire(char *,char *); +}; + +class CSpellBookWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CSpellBookWnd::CSpellBookWnd(class CXWnd *); +EQLIB_OBJECT bool CSpellBookWnd::StartSpellMemorization(int,int,bool); +EQLIB_OBJECT int CSpellBookWnd::GetSpellMemTicksLeft(void); +EQLIB_OBJECT int CSpellBookWnd::GetSpellScribeTicksLeft(void); +EQLIB_OBJECT static int __cdecl CSpellBookWnd::GetBookSlot(int); +EQLIB_OBJECT void CSpellBookWnd::Activate(void); +EQLIB_OBJECT void CSpellBookWnd::AutoMemSpell(int,int); +EQLIB_OBJECT void CSpellBookWnd::DeleteSpellFromBook(int,int); +EQLIB_OBJECT void CSpellBookWnd::FinishMemorizing(int,int); +EQLIB_OBJECT void CSpellBookWnd::FinishScribing(int,int); +EQLIB_OBJECT void CSpellBookWnd::MemorizeSet(int *,int); +EQLIB_OBJECT void CSpellBookWnd::RequestSpellDeletion(int); +EQLIB_OBJECT void CSpellBookWnd::SwapSpellBookSlots(int,int); +EQLIB_OBJECT void CSpellBookWnd::TurnToPage(int); +// virtual +EQLIB_OBJECT CSpellBookWnd::~CSpellBookWnd(void); +EQLIB_OBJECT int CSpellBookWnd::Draw(void)const; +EQLIB_OBJECT int CSpellBookWnd::HandleKeyboardMsg(unsigned __int32,unsigned __int32,bool); +EQLIB_OBJECT int CSpellBookWnd::OnProcessFrame(void); +EQLIB_OBJECT int CSpellBookWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CSpellBookWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CSpellBookWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CSpellBookWnd::Deactivate(void); +// private +EQLIB_OBJECT bool CSpellBookWnd::CanStartMemming(int); +EQLIB_OBJECT void CSpellBookWnd::ContinueSetMem(void); +EQLIB_OBJECT void CSpellBookWnd::DelayedSpellMem(int,int,int); +EQLIB_OBJECT void CSpellBookWnd::DisplaySpellInfo(int); +EQLIB_OBJECT void CSpellBookWnd::EndSetMem(void); +EQLIB_OBJECT void CSpellBookWnd::GetSpellDeletionConfirmation(int); +EQLIB_OBJECT void CSpellBookWnd::HandleLeftClickOnSpell(int); +EQLIB_OBJECT void CSpellBookWnd::HandleRightClickOnSpell(int); +EQLIB_OBJECT void CSpellBookWnd::HandleSpellInfoDisplay(class CXWnd *); +EQLIB_OBJECT void CSpellBookWnd::Init(void); +EQLIB_OBJECT void CSpellBookWnd::StartSpellMemorizationDrag(int,class CButtonWnd *); +EQLIB_OBJECT void CSpellBookWnd::StartSpellScribe(int); +EQLIB_OBJECT void CSpellBookWnd::StopSpellBookAction(void); +EQLIB_OBJECT void CSpellBookWnd::UpdateSpellBookDisplay(void); +}; + +class CSpellGemDrawTemplate +{ +public: +EQLIB_OBJECT CSpellGemDrawTemplate::~CSpellGemDrawTemplate(void); +}; + +class CSpellGemTemplate +{ +public: +EQLIB_OBJECT CSpellGemTemplate::CSpellGemTemplate(class CParamSpellGem *); +// virtual +EQLIB_OBJECT CSpellGemTemplate::~CSpellGemTemplate(void); +//EQLIB_OBJECT void * CSpellGemTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CSpellGemTemplate::`vector deleting destructor'(unsigned int); +}; + +class CSpellGemWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CSpellGemWnd::CSpellGemWnd(class CXWnd *,unsigned __int32,class CXRect,class CTextureAnimation *,class CTextureAnimation *,class CTextureAnimation *,int,int,unsigned long); +EQLIB_OBJECT void CSpellGemWnd::SetCheck(bool); +EQLIB_OBJECT void CSpellGemWnd::SetGemTintStage(int); +EQLIB_OBJECT void CSpellGemWnd::SetSpellGemTint(unsigned long); +EQLIB_OBJECT void CSpellGemWnd::SetSpellIconIndex(int); +// virtual +EQLIB_OBJECT CSpellGemWnd::~CSpellGemWnd(void); +EQLIB_OBJECT int CSpellGemWnd::Draw(void)const; +EQLIB_OBJECT int CSpellGemWnd::HandleLButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CSpellGemWnd::HandleLButtonHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CSpellGemWnd::HandleLButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CSpellGemWnd::HandleLButtonUpAfterHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CSpellGemWnd::HandleRButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CSpellGemWnd::HandleRButtonHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CSpellGemWnd::HandleRButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CSpellGemWnd::HandleRButtonUpAfterHeld(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CSpellGemWnd::OnProcessFrame(void); +//EQLIB_OBJECT void * CSpellGemWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CSpellGemWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CSpellGemWnd::SetAttributesFromSidl(class CParamScreenPiece *); +// protected +EQLIB_OBJECT void CSpellGemWnd::Init(void); +}; + +class CStaticAnimationTemplate +{ +public: +EQLIB_OBJECT CStaticAnimationTemplate::CStaticAnimationTemplate(class CParamStaticAnimation *); +// virtual +EQLIB_OBJECT CStaticAnimationTemplate::~CStaticAnimationTemplate(void); +//EQLIB_OBJECT void * CStaticAnimationTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CStaticAnimationTemplate::`vector deleting destructor'(unsigned int); +}; + +class CStaticFrameTemplate +{ +public: +EQLIB_OBJECT CStaticFrameTemplate::CStaticFrameTemplate(class CParamStaticFrame *); +// virtual +EQLIB_OBJECT CStaticFrameTemplate::~CStaticFrameTemplate(void); +//EQLIB_OBJECT void * CStaticFrameTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CStaticFrameTemplate::`vector deleting destructor'(unsigned int); +}; + +class CStaticHeaderTemplate +{ +public: +EQLIB_OBJECT CStaticHeaderTemplate::CStaticHeaderTemplate(class CParamStaticHeader *); +// virtual +EQLIB_OBJECT CStaticHeaderTemplate::~CStaticHeaderTemplate(void); +//EQLIB_OBJECT void * CStaticHeaderTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CStaticHeaderTemplate::`vector deleting destructor'(unsigned int); +}; + +class CStaticScreenPieceTemplate +{ +public: +EQLIB_OBJECT CStaticScreenPieceTemplate::CStaticScreenPieceTemplate(class CParamStaticScreenPiece *); +// virtual +EQLIB_OBJECT CStaticScreenPieceTemplate::~CStaticScreenPieceTemplate(void); +//EQLIB_OBJECT void * CStaticScreenPieceTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CStaticScreenPieceTemplate::`vector deleting destructor'(unsigned int); +}; + +class CStaticTextTemplate +{ +public: +EQLIB_OBJECT CStaticTextTemplate::CStaticTextTemplate(class CParamStaticText *); +EQLIB_OBJECT class CXStr CStaticTextTemplate::SetText(class CXStr); +// virtual +EQLIB_OBJECT CStaticTextTemplate::~CStaticTextTemplate(void); +//EQLIB_OBJECT void * CStaticTextTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CStaticTextTemplate::`vector deleting destructor'(unsigned int); +}; + +class CSTMLboxTemplate +{ +public: +EQLIB_OBJECT CSTMLboxTemplate::CSTMLboxTemplate(class CParamSTMLbox *); +// virtual +EQLIB_OBJECT CSTMLboxTemplate::~CSTMLboxTemplate(void); +//EQLIB_OBJECT void * CSTMLboxTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CSTMLboxTemplate::`vector deleting destructor'(unsigned int); +}; + +class CStmlReport +{ +public: +EQLIB_OBJECT class CXStr CStmlReport::GetReport(void)const; +EQLIB_OBJECT static class CStmlReport * __cdecl CStmlReport::CreateReport(class CXStr); +// private +EQLIB_OBJECT static unsigned __int32 CStmlReport::m_uLastId; +}; + +class CStmlWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CStmlWnd::CStmlWnd(class CXWnd *,unsigned __int32,class CXRect); +EQLIB_OBJECT bool CStmlWnd::CanGoBackward(void); +EQLIB_OBJECT class CXSize CStmlWnd::AppendSTML(class CXStr); // lax 11-15-2003 +EQLIB_OBJECT class CXStr CStmlWnd::GetSTMLText(void)const; +EQLIB_OBJECT class CXStr CStmlWnd::GetVisibleText(class CXStr&,class CXRect)const; +EQLIB_OBJECT static class CXStr __cdecl CStmlWnd::MakeStmlColorTag(unsigned long); +EQLIB_OBJECT static class CXStr __cdecl CStmlWnd::MakeWndNotificationTag(unsigned __int32,class CXStr&,class CXStr&); +EQLIB_OBJECT void CStmlWnd::ActivateLink(class SLinkInfo); +EQLIB_OBJECT void CStmlWnd::ForceParseNow(void); +EQLIB_OBJECT void CStmlWnd::GoToBackHistoryLink(void); +//EQLIB_OBJECT void CStmlWnd::LoadPage(class CXStr,enum ESTMLTargetValue,bool); +EQLIB_OBJECT void CStmlWnd::SetSTMLText(class CXStr,bool,class SLinkInfo *); +EQLIB_OBJECT void CStmlWnd::SetSTMLTextWithoutHistory(class CXStr); +// virtual +EQLIB_OBJECT CStmlWnd::~CStmlWnd(void); +EQLIB_OBJECT bool CStmlWnd::IsPointTransparent(class CXPoint)const; +EQLIB_OBJECT class CTextureAnimation * CStmlWnd::GetCursorToDisplay(void)const; +EQLIB_OBJECT int CStmlWnd::Draw(void)const; +EQLIB_OBJECT int CStmlWnd::HandleKeyboardMsg(unsigned __int32,unsigned __int32,bool); +EQLIB_OBJECT int CStmlWnd::HandleLButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CStmlWnd::HandleLButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CStmlWnd::HandleMouseMove(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CStmlWnd::OnHScroll(EScrollCode,int); +EQLIB_OBJECT int CStmlWnd::OnMove(class CXRect); +EQLIB_OBJECT int CStmlWnd::OnProcessFrame(void); +EQLIB_OBJECT int CStmlWnd::OnResize(int,int); +EQLIB_OBJECT int CStmlWnd::OnVScroll(EScrollCode,int); +//EQLIB_OBJECT void * CStmlWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CStmlWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CStmlWnd::SetWindowTextA(class CXStr); +// protected +EQLIB_OBJECT bool CStmlWnd::IsLinkActive(class SLinkInfo)const; +EQLIB_OBJECT bool CStmlWnd::ParseAmpersand(class CXStr,char *)const; +EQLIB_OBJECT static bool __cdecl CStmlWnd::CanBreakAtCharacter(unsigned short); +EQLIB_OBJECT static bool __cdecl CStmlWnd::IsCharacterNotASpaceAndNotNULL(unsigned short); +EQLIB_OBJECT static bool __cdecl CStmlWnd::IsCharacterNotEquals(unsigned short); +EQLIB_OBJECT static bool __cdecl CStmlWnd::IsCharacterNotQuotes(unsigned short); +EQLIB_OBJECT unsigned short CStmlWnd::FastForwardPastQuotesAndGetNextTagPiece(class CXStr&,class CXStr *,int *,bool); +EQLIB_OBJECT unsigned short CStmlWnd::FastForwardPastSpaces(class CXStr&,int *); +EQLIB_OBJECT unsigned short CStmlWnd::FastForwardPastSpacesAndQuotes(class CXStr&,int *); +EQLIB_OBJECT unsigned short CStmlWnd::FastForwardToEndOfTag(class CXStr&,class CXStr *,int *,char); +EQLIB_OBJECT unsigned short CStmlWnd::GetNextChar(int *,class CXStr&); +EQLIB_OBJECT unsigned short CStmlWnd::GetNextTagPiece(class CXStr&,class CXStr *,int *,bool (__cdecl*)(unsigned short),bool); +EQLIB_OBJECT unsigned short CStmlWnd::GetThisChar(int,class CXStr&); +EQLIB_OBJECT void CStmlWnd::ActivateLinkFile(class SLinkInfo); +EQLIB_OBJECT void CStmlWnd::ActivateLinkMessageId(class SLinkInfo); +EQLIB_OBJECT void CStmlWnd::ActivateLinkReport(class SLinkInfo,bool); +EQLIB_OBJECT void CStmlWnd::ActivateLinkWndNotify(class SLinkInfo); +EQLIB_OBJECT void CStmlWnd::AddLinkToHistory(class SLinkInfo,class CXStr); +EQLIB_OBJECT void CStmlWnd::AddTextPieceToLine(class SParseVariables *); +EQLIB_OBJECT void CStmlWnd::CalculateHSBRange(int); +EQLIB_OBJECT void CStmlWnd::CalculateVSBRange(int); +EQLIB_OBJECT void CStmlWnd::CompleteParse(void); +EQLIB_OBJECT void CStmlWnd::InitializeTempVariables(class SParseVariables *,class CXRect); +EQLIB_OBJECT void CStmlWnd::InitializeTextLine(class SParseVariables *,int); +EQLIB_OBJECT void CStmlWnd::InitializeWindowVariables(void); +//EQLIB_OBJECT void CStmlWnd::ParseLinkTarget(class CXStr,enum ESTMLTargetValue *)const; +EQLIB_OBJECT void CStmlWnd::ParseSTMLHead(class CXStr&); +EQLIB_OBJECT void CStmlWnd::ParseSTMLTable(class CXStr&,int *,class CXStr,class SParseVariables *); +EQLIB_OBJECT void CStmlWnd::ParseSTMLTableAttributes(class CXStr&,class STable *); +//EQLIB_OBJECT void CStmlWnd::ParseTagAlign(class CXStr,enum ESTMLAlign *)const; +EQLIB_OBJECT void CStmlWnd::ParseTagColor(class CXStr&,unsigned long *)const; +EQLIB_OBJECT void CStmlWnd::ParseTagFace(class CXStr&,class CTextureFont const * *)const; +EQLIB_OBJECT void CStmlWnd::ResetTempVariablesForNewLine(class SParseVariables *); +EQLIB_OBJECT void CStmlWnd::StripFirstSTMLLines(int); +EQLIB_OBJECT void CStmlWnd::UpdateHistoryString(__int32,class CXStr&); +}; + +class CStoryWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CStoryWnd::CStoryWnd(class CXWnd *); +EQLIB_OBJECT bool CStoryWnd::HasNew(void); +EQLIB_OBJECT bool CStoryWnd::ShowAuto(void); +EQLIB_OBJECT void CStoryWnd::Activate(void); +EQLIB_OBJECT void CStoryWnd::SaveIni(void); +// virtual +EQLIB_OBJECT CStoryWnd::~CStoryWnd(void); +EQLIB_OBJECT int CStoryWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CStoryWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CStoryWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CStoryWnd::Deactivate(void); +EQLIB_OBJECT void CStoryWnd::LoadIniInfo(void); +// protected +EQLIB_OBJECT void CStoryWnd::SelectIndex(int); +EQLIB_OBJECT void CStoryWnd::SelectOldestNew(void); +// private +EQLIB_OBJECT void CStoryWnd::Init(void); +}; + +class CTabBoxTemplate +{ +public: +EQLIB_OBJECT CTabBoxTemplate::CTabBoxTemplate(class CParamTabBox *); +// virtual +EQLIB_OBJECT CTabBoxTemplate::~CTabBoxTemplate(void); +//EQLIB_OBJECT void * CTabBoxTemplate::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CTabBoxTemplate::`vector deleting destructor'(unsigned int); +}; + +class CTabWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CTabWnd::CTabWnd(class CXWnd *,unsigned __int32,class CXRect,class CTabBoxTemplate *); +EQLIB_OBJECT class CPageWnd * CTabWnd::GetCurrentPage(void)const; +EQLIB_OBJECT class CXRect CTabWnd::GetPageClientRect(void)const; +EQLIB_OBJECT class CXRect CTabWnd::GetPageInnerRect(void)const; +EQLIB_OBJECT class CXRect CTabWnd::GetTabInnerRect(int)const; +EQLIB_OBJECT class CXRect CTabWnd::GetTabRect(int)const; +EQLIB_OBJECT int CTabWnd::GetCurrentTabIndex(void)const; +EQLIB_OBJECT int CTabWnd::GetNumTabs(void)const; +EQLIB_OBJECT void CTabWnd::InsertPage(class CPageWnd *,int); +EQLIB_OBJECT void CTabWnd::SetPage(class CPageWnd *,bool); +EQLIB_OBJECT void CTabWnd::SetPage(int,bool); +EQLIB_OBJECT void CTabWnd::SetPageRect(class CXRect); +EQLIB_OBJECT void CTabWnd::UpdatePage(void); +// virtual +EQLIB_OBJECT CTabWnd::~CTabWnd(void); +EQLIB_OBJECT int CTabWnd::Draw(void)const; +EQLIB_OBJECT int CTabWnd::DrawTooltip(class CXWnd const *); +EQLIB_OBJECT int CTabWnd::HandleLButtonDown(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CTabWnd::HandleLButtonUp(class CXPoint,unsigned __int32); +EQLIB_OBJECT int CTabWnd::OnResize(int,int); +EQLIB_OBJECT int CTabWnd::OnShow(void); +//EQLIB_OBJECT void * CTabWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CTabWnd::`vector deleting destructor'(unsigned int); +// private +EQLIB_OBJECT bool CTabWnd::IndexInBounds(int)const; +EQLIB_OBJECT class CPageWnd * CTabWnd::GetPageFromTabIndex(int)const; +EQLIB_OBJECT class CPageWnd * CTabWnd::GetPageFromTabPoint(class CXPoint)const; +EQLIB_OBJECT int CTabWnd::DrawCurrentPage(void)const; +EQLIB_OBJECT int CTabWnd::DrawTab(int)const; +}; + +class CTAFrameDraw +{ +public: +EQLIB_OBJECT CTAFrameDraw::~CTAFrameDraw(void); +EQLIB_OBJECT CTAFrameDraw::CTAFrameDraw(class CTAFrameDraw const &); +EQLIB_OBJECT CTAFrameDraw::CTAFrameDraw(class CXStr); +EQLIB_OBJECT bool CTAFrameDraw::IsHorizontal(void)const; +EQLIB_OBJECT bool CTAFrameDraw::IsVertical(void)const; +EQLIB_OBJECT class CTAFrameDraw & CTAFrameDraw::operator=(class CTAFrameDraw const &); +EQLIB_OBJECT class CTextureAnimation * CTAFrameDraw::GetAnimation(int)const; +EQLIB_OBJECT class CXRect CTAFrameDraw::GetHitTestRect(class CXRect,int)const; +EQLIB_OBJECT class CXRect CTAFrameDraw::GetInnerRect(class CXRect)const; +EQLIB_OBJECT class CXRect CTAFrameDraw::GetPieceRect(class CXRect,int)const; +EQLIB_OBJECT class CXSize CTAFrameDraw::GetFrameSize(void)const; +EQLIB_OBJECT class CXStr CTAFrameDraw::GetName(void)const; +EQLIB_OBJECT int CTAFrameDraw::Draw(class CXRect,class CXRect)const; +EQLIB_OBJECT int CTAFrameDraw::Draw(class CXRect,class CXRect,int)const; +EQLIB_OBJECT int CTAFrameDraw::GetExtent(void)const; +EQLIB_OBJECT int CTAFrameDraw::GetMinLength(void)const; +EQLIB_OBJECT void CTAFrameDraw::Set(class CTextureAnimation * * const); +}; + +class CTargetWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CTargetWnd::CTargetWnd(class CXWnd *); +EQLIB_OBJECT void CTargetWnd::Activate(void); +// virtual +EQLIB_OBJECT CTargetWnd::~CTargetWnd(void); +EQLIB_OBJECT int CTargetWnd::OnProcessFrame(void); +//EQLIB_OBJECT void * CTargetWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CTargetWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CTargetWnd::Deactivate(void); +// private +EQLIB_OBJECT void CTargetWnd::Init(void); +}; + +class CTextEntryWnd : public CEditBaseWnd +{ +public: +EQLIB_OBJECT CTextEntryWnd::CTextEntryWnd(class CXWnd *); +EQLIB_OBJECT class CXStr CTextEntryWnd::GetEntryText(void); +EQLIB_OBJECT void CTextEntryWnd::Activate(class CXWnd *,int,char *,int,int,char *); +EQLIB_OBJECT void CTextEntryWnd::Callback(bool); +// virtual +EQLIB_OBJECT CTextEntryWnd::~CTextEntryWnd(void); +EQLIB_OBJECT int CTextEntryWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CTextEntryWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CTextEntryWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CTextEntryWnd::Deactivate(void); +// private +EQLIB_OBJECT void CTextEntryWnd::UpdateButtons(void); + +/*0x148*/// DWORD Unknown0x148; +/*0x14C*/// DWORD Unknown0x14c; +/*0x150*/// PCXSTR Data; +/*0x154*/// DWORD Unknown0x154; +/*0x158*/// CSidlScreenWnd *Entry; +/*0x15c*/// CSidlScreenWnd *Prompt; +/*0x160*/// CSidlScreenWnd *OK; +/*0x164*/// CSidlScreenWnd *Cancel; +}; + +class CTextureAnimation +{ +public: +EQLIB_OBJECT CTextureAnimation::CTextureAnimation(class CXStr); +EQLIB_OBJECT CTextureAnimation::CTextureAnimation(void); +EQLIB_OBJECT class CTextureAnimation & CTextureAnimation::operator=(class CTextureAnimation const &); +EQLIB_OBJECT class CXPoint CTextureAnimation::GetHotspot(void)const; +EQLIB_OBJECT class CXStr CTextureAnimation::GetName(void)const; +EQLIB_OBJECT int CTextureAnimation::AddBlankFrame(unsigned __int32,class CXPoint); +EQLIB_OBJECT int CTextureAnimation::AddFrame(class CUITexturePiece,unsigned __int32,class CXPoint); +EQLIB_OBJECT int CTextureAnimation::AddFrame(class CUITextureInfo const *,class CXRect,unsigned __int32,class CXPoint); +EQLIB_OBJECT int CTextureAnimation::Draw(class CXPoint,class CXRect,unsigned long,unsigned long)const; +EQLIB_OBJECT int CTextureAnimation::Draw(class CXRect,class CXRect,unsigned long,unsigned long)const; +EQLIB_OBJECT int CTextureAnimation::GetCurFrame(void)const; +EQLIB_OBJECT int CTextureAnimation::Preload(void); +EQLIB_OBJECT void CTextureAnimation::Reset(void); +EQLIB_OBJECT void CTextureAnimation::SetCurCell(int); +EQLIB_OBJECT void CTextureAnimation::SetCurFrame(int); +// virtual +EQLIB_OBJECT CTextureAnimation::~CTextureAnimation(void); +//EQLIB_OBJECT void * CTextureAnimation::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CTextureAnimation::`vector deleting destructor'(unsigned int); +// protected +EQLIB_OBJECT static unsigned __int32 CTextureAnimation::sm_uMaxId; +}; + +class CTextureFont +{ +public: +EQLIB_OBJECT class CXStr CTextureFont::GetName(void)const; +EQLIB_OBJECT int CTextureFont::DrawWrappedText(class CXStr,class CXRect,class CXRect,unsigned long,unsigned short,int)const; +EQLIB_OBJECT int CTextureFont::DrawWrappedText(class CXStr *,int,int,int,class CXRect *,unsigned long,unsigned short,int)const; +EQLIB_OBJECT int CTextureFont::GetHeight(void)const; +EQLIB_OBJECT int CTextureFont::GetKerning(unsigned short,unsigned short)const; +EQLIB_OBJECT int CTextureFont::GetTextExtent(class CXStr)const; +EQLIB_OBJECT int CTextureFont::GetWidth(unsigned short)const; +// virtual +EQLIB_OBJECT CTextureFont::~CTextureFont(void); +//EQLIB_OBJECT void * CTextureFont::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CTextureFont::`vector deleting destructor'(unsigned int); +void *Unknown0x0; +DWORD Size; +}; + +class CTimeLeftWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CTimeLeftWnd::CTimeLeftWnd(long); +EQLIB_OBJECT void CTimeLeftWnd::Activate(void); +// virtual +EQLIB_OBJECT CTimeLeftWnd::~CTimeLeftWnd(void); +EQLIB_OBJECT int CTimeLeftWnd::Draw(void)const; +EQLIB_OBJECT int CTimeLeftWnd::OnProcessFrame(void); +//EQLIB_OBJECT void * CTimeLeftWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CTimeLeftWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CTimeLeftWnd::Deactivate(void); +}; + +class CTipWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CTipWnd::CTipWnd(class CXWnd *,int); +EQLIB_OBJECT bool CTipWnd::Activate(int,bool); +EQLIB_OBJECT void CTipWnd::InitializeTipSettings(void); +EQLIB_OBJECT void CTipWnd::UpdateButtons(void); +// virtual +EQLIB_OBJECT CTipWnd::~CTipWnd(void); +EQLIB_OBJECT int CTipWnd::OnProcessFrame(void); +EQLIB_OBJECT int CTipWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CTipWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CTipWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CTipWnd::Deactivate(void); +// protected +EQLIB_OBJECT bool CTipWnd::IsRecentTOTD(int); +EQLIB_OBJECT int CTipWnd::SelectRandomTip(void); +EQLIB_OBJECT void CTipWnd::AddContextTip(int); +EQLIB_OBJECT void CTipWnd::LoadINISettings(void); +EQLIB_OBJECT void CTipWnd::SetTOTD(int); +EQLIB_OBJECT void CTipWnd::ShowHistoryTip(int); +// private +EQLIB_OBJECT void CTipWnd::CleanDayTips(void); +EQLIB_OBJECT void CTipWnd::LoadDayTips(void); +}; + +class CTokenXML +{ +public: +EQLIB_OBJECT CTokenXML::~CTokenXML(void); +}; + +class CTrackingWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CTrackingWnd::CTrackingWnd(class CXWnd *); +EQLIB_OBJECT void CTrackingWnd::Activate(void); +EQLIB_OBJECT void CTrackingWnd::DoTrackFilter(bool); +EQLIB_OBJECT void CTrackingWnd::DoTrackSort(bool); +EQLIB_OBJECT void CTrackingWnd::RemovePlayerFromTracking(class EQPlayer *); +EQLIB_OBJECT void CTrackingWnd::SetTrackingList(struct TrackingHit *,int); +// virtual +EQLIB_OBJECT CTrackingWnd::~CTrackingWnd(void); +EQLIB_OBJECT int CTrackingWnd::Draw(void)const; +EQLIB_OBJECT int CTrackingWnd::OnProcessFrame(void); +EQLIB_OBJECT int CTrackingWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CTrackingWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CTrackingWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CTrackingWnd::Deactivate(void); +// private +EQLIB_OBJECT int CTrackingWnd::GetListIdByData(unsigned int); +EQLIB_OBJECT unsigned long CTrackingWnd::GetTrackColor(int); +EQLIB_OBJECT void CTrackingWnd::GenerateTrackingList(void); +EQLIB_OBJECT void CTrackingWnd::Init(void); +EQLIB_OBJECT void CTrackingWnd::NotifyServerOfTrackingTarget(int); +EQLIB_OBJECT void CTrackingWnd::RemoveFromListWndByData(unsigned int); +EQLIB_OBJECT void CTrackingWnd::RemovePlayerFromTracking(int); +EQLIB_OBJECT void CTrackingWnd::UpdateTrackingControls(void); +EQLIB_OBJECT void CTrackingWnd::UpdateTrackingList(bool); +}; + +class CTradeWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CTradeWnd::CTradeWnd(class CXWnd *); +EQLIB_OBJECT bool CTradeWnd::IsMyTradeSlot(int,bool *); +EQLIB_OBJECT void CTradeWnd::Activate(class EQPlayer *,bool); +EQLIB_OBJECT void CTradeWnd::AddContainerToHisTradeArray(class EQ_Container *); +EQLIB_OBJECT void CTradeWnd::AddEquipmentToHisTradeArray(class EQ_Equipment *); +EQLIB_OBJECT void CTradeWnd::AddNoteToHisTradeArray(class EQ_Note *); +EQLIB_OBJECT void CTradeWnd::ClickedCancelButton(void); +EQLIB_OBJECT void CTradeWnd::ClickedMoneyButton(int); +EQLIB_OBJECT void CTradeWnd::ClickedTradeButton(void); +EQLIB_OBJECT void CTradeWnd::CompleteTrade(void); +EQLIB_OBJECT void CTradeWnd::DeleteItemFromHisTradeArray(int); +EQLIB_OBJECT void CTradeWnd::DropItemIntoTrade(void); +EQLIB_OBJECT void CTradeWnd::SetHisMoney(int,long); +EQLIB_OBJECT void CTradeWnd::SetHisReadyTrade(bool); +EQLIB_OBJECT void CTradeWnd::SetMyReadyTrade(bool); +EQLIB_OBJECT void CTradeWnd::TradeItemChanged(int,int); +// virtual +EQLIB_OBJECT CTradeWnd::~CTradeWnd(void); +EQLIB_OBJECT int CTradeWnd::OnProcessFrame(void); +EQLIB_OBJECT int CTradeWnd::PostDraw(void)const; +EQLIB_OBJECT int CTradeWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CTradeWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CTradeWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CTradeWnd::Deactivate(void); +// private +EQLIB_OBJECT void CTradeWnd::Init(void); +EQLIB_OBJECT void CTradeWnd::UpdateTradeDisplay(void); +}; + +class CTrainWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CTrainWnd::CTrainWnd(class CXWnd *); +EQLIB_OBJECT void CTrainWnd::SetGMData(int *,unsigned char *,float); +EQLIB_OBJECT void CTrainWnd::SkillChanged(int); +// virtual +EQLIB_OBJECT CTrainWnd::~CTrainWnd(void); +EQLIB_OBJECT int CTrainWnd::OnProcessFrame(void); +EQLIB_OBJECT int CTrainWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CTrainWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CTrainWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CTrainWnd::Deactivate(void); +// protected +EQLIB_OBJECT char * CTrainWnd::SkillName(int); +EQLIB_OBJECT int CTrainWnd::SkillValue(int); +EQLIB_OBJECT void CTrainWnd::Activate(void); +EQLIB_OBJECT void CTrainWnd::SortNames(int); +EQLIB_OBJECT void CTrainWnd::SortSkill(int); +EQLIB_OBJECT void CTrainWnd::SwapSkill(int,int); +EQLIB_OBJECT void CTrainWnd::Train(void); +EQLIB_OBJECT void CTrainWnd::UpdateAll(bool); +EQLIB_OBJECT void CTrainWnd::UpdateRight(void); +EQLIB_OBJECT void CTrainWnd::UpdateSkill(int); +}; + +class CUITextureInfo +{ +public: +EQLIB_OBJECT CUITextureInfo::~CUITextureInfo(void); +EQLIB_OBJECT CUITextureInfo::CUITextureInfo(class CXStr,class CXSize); +EQLIB_OBJECT CUITextureInfo::CUITextureInfo(class CXStr,int); +EQLIB_OBJECT CUITextureInfo::CUITextureInfo(class CUITextureInfo const &); +EQLIB_OBJECT CUITextureInfo::CUITextureInfo(unsigned __int32,int); +EQLIB_OBJECT CUITextureInfo::CUITextureInfo(void); +EQLIB_OBJECT class CXStr CUITextureInfo::GetName(void)const; +EQLIB_OBJECT int CUITextureInfo::Draw(class CXRect,class CXRect,class CXRect,unsigned long *,unsigned long *)const; +EQLIB_OBJECT int CUITextureInfo::Draw(class CXRect,class CXRect,class CXRect,unsigned long,unsigned long)const; +EQLIB_OBJECT int CUITextureInfo::Preload(void); +EQLIB_OBJECT int CUITextureInfo::Tile(class CXRect,unsigned long *,unsigned long *)const; +EQLIB_OBJECT int CUITextureInfo::Tile(class CXRect,unsigned long,unsigned long)const; +EQLIB_OBJECT class CUITextureInfo & CUITextureInfo::operator=(class CUITextureInfo const &); +}; + +class CUITexturePiece +{ +public: +EQLIB_OBJECT CUITexturePiece::~CUITexturePiece(void); +EQLIB_OBJECT CUITexturePiece::CUITexturePiece(class CUITexturePiece const &); +EQLIB_OBJECT CUITexturePiece::CUITexturePiece(class CUITextureInfo,class CXRect); +EQLIB_OBJECT CUITexturePiece::CUITexturePiece(void); +EQLIB_OBJECT class CUITexturePiece & CUITexturePiece::operator=(class CUITexturePiece const &); +EQLIB_OBJECT int CUITexturePiece::Draw(class CXRect,class CXRect,class CXRect,unsigned long,unsigned long)const; +EQLIB_OBJECT int CUITexturePiece::Draw(class CXRect,class CXRect,unsigned long,unsigned long)const; +}; + +class CVector3 +{ +public: +EQLIB_OBJECT float CVector3::GetLength(void)const; +EQLIB_OBJECT float CVector3::NormalizeAndReturnLength(void); +EQLIB_OBJECT void CVector3::Normalize(void); +}; + +class CVideoModesWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CVideoModesWnd::CVideoModesWnd(class CXWnd *); +EQLIB_OBJECT void CVideoModesWnd::Activate(void); +EQLIB_OBJECT void CVideoModesWnd::RestoreOldMode(void); +EQLIB_OBJECT void CVideoModesWnd::Update(void); +// virtual +EQLIB_OBJECT CVideoModesWnd::~CVideoModesWnd(void); +EQLIB_OBJECT int CVideoModesWnd::Draw(void)const; +EQLIB_OBJECT int CVideoModesWnd::OnProcessFrame(void); +EQLIB_OBJECT int CVideoModesWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +//EQLIB_OBJECT void * CVideoModesWnd::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CVideoModesWnd::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CVideoModesWnd::Deactivate(void); +// private +EQLIB_OBJECT void CVideoModesWnd::Init(void); +EQLIB_OBJECT void CVideoModesWnd::UpdateSelection(unsigned int); +}; + +class CXFileXML +{ +public: +EQLIB_OBJECT CXFileXML::~CXFileXML(void); +EQLIB_OBJECT bool CXFileXML::Load(char *); +}; + +class CXMLData +{ +public: +EQLIB_OBJECT CXMLData::CXMLData(void); +EQLIB_OBJECT class CXMLData & CXMLData::operator=(class CXMLData const &); +// virtual +EQLIB_OBJECT CXMLData::~CXMLData(void); +EQLIB_OBJECT bool CXMLData::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT bool CXMLData::WriteToXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT int CXMLData::GetStreamSize(void); +//EQLIB_OBJECT void * CXMLData::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CXMLData::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CXMLData::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CXMLData::WriteToStream(class CMemoryStream &); +// data members +/*0x00*/ PVOID pvfTable; +/*0x04*/ DWORD Unknown0x04;// always 8 +/*0x08*/ enum UIType Type; +/*0x0C*/ DWORD Unknown0x0C;// no idea yet, some number but not unique +/*0x10*/ DWORD Unknown0x10;// always -1 +/*0x14*/ CXStr TypeName;// "Screen" (control type) +/*0x18*/ CXStr Name;// "ChatWindow" control name (used only for Screen) +/*0x1C*/ DWORD Unknown0x1C;// always null +/*0x20*/ CXStr ScreenID;// ScreenID (used only within Screen) +}; + +class CXMLDataClass +{ +public: +EQLIB_OBJECT CXMLDataClass::~CXMLDataClass(void); +EQLIB_OBJECT CXMLDataClass::CXMLDataClass(void); +EQLIB_OBJECT int CXMLDataClass::GetNumLeaf(void); +EQLIB_OBJECT int CXMLDataClass::GetStreamSize(void); +//EQLIB_OBJECT void * CXMLDataClass::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CXMLDataClass::ReadFromStream(class CMemoryStream &,class CXMLDataManager &); +EQLIB_OBJECT void CXMLDataClass::WriteToStream(class CMemoryStream &); +}; + +class CXMLDataManager +{ +public: +EQLIB_OBJECT CXMLDataManager::CXMLDataManager(void); +EQLIB_OBJECT bool CXMLDataManager::IsDerivedFrom(int,int); +EQLIB_OBJECT bool CXMLDataManager::ReadFromXMLSOM(class CXMLSOMDocument &); +EQLIB_OBJECT class CXMLData * CXMLDataManager::GetXMLData(class CXStr,class CXStr); +EQLIB_OBJECT class CXMLData * CXMLDataManager::GetXMLData(int,int); +EQLIB_OBJECT int CXMLDataManager::GetClassIdx(class CXStr); +EQLIB_OBJECT int CXMLDataManager::GetItemIdx(int,class CXStr); +EQLIB_OBJECT int CXMLDataManager::GetNumClass(void); +EQLIB_OBJECT int CXMLDataManager::GetNumItem(int); +// virtual +EQLIB_OBJECT CXMLDataManager::~CXMLDataManager(void); +EQLIB_OBJECT bool CXMLDataManager::DataValidate(void); +EQLIB_OBJECT bool CXMLDataManager::ReadValidate(class CMemoryStream &); +EQLIB_OBJECT bool CXMLDataManager::WriteValidate(class CMemoryStream &); +EQLIB_OBJECT int CXMLDataManager::GetStreamSize(void); +//EQLIB_OBJECT void * CXMLDataManager::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CXMLDataManager::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void CXMLDataManager::IndexAll(void); +EQLIB_OBJECT void CXMLDataManager::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CXMLDataManager::Set(class CXMLDataManager &); +EQLIB_OBJECT void CXMLDataManager::WriteToStream(class CMemoryStream &); +// protected +EQLIB_OBJECT void CXMLDataManager::AddToSuperType(class CXStr,class CXMLDataPtr); +EQLIB_OBJECT void CXMLDataManager::SetEnumHash(void); +}; + +class CXMLDataPtr +{ +public: +EQLIB_OBJECT CXMLDataPtr::CXMLDataPtr(void); +EQLIB_OBJECT class CXMLDataPtr & CXMLDataPtr::operator=(class CXMLDataPtr const &); +EQLIB_OBJECT void CXMLDataPtr::SetNewPtr(class CXMLData *); +// virtual +EQLIB_OBJECT CXMLDataPtr::~CXMLDataPtr(void); +//EQLIB_OBJECT void * CXMLDataPtr::`vector deleting destructor'(unsigned int); +// protected +EQLIB_OBJECT class CXMLData * CXMLDataPtr::AllocPtr(class CXMLDataPtr &,int,class CXMLData const *); +EQLIB_OBJECT void CXMLDataPtr::Free(void); +}; + +class CXMLEnumInfo +{ +public: +EQLIB_OBJECT CXMLEnumInfo::~CXMLEnumInfo(void); +EQLIB_OBJECT CXMLEnumInfo::CXMLEnumInfo(void); +EQLIB_OBJECT int CXMLEnumInfo::GetStreamSize(void); +EQLIB_OBJECT void CXMLEnumInfo::ReadFromStream(class CMemoryStream &); +EQLIB_OBJECT void CXMLEnumInfo::WriteToStream(class CMemoryStream &); +}; + +class CXMLParamManager +{ +public: +// virtual +EQLIB_OBJECT CXMLParamManager::~CXMLParamManager(void); +EQLIB_OBJECT bool CXMLParamManager::XMLDataCopy(class CXMLData *,class CXMLData *); +EQLIB_OBJECT class CXMLData * CXMLParamManager::AllocPtr(class CXMLDataPtr &,int,class CXMLData const *); +//EQLIB_OBJECT void * CXMLParamManager::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CXMLParamManager::`vector deleting destructor'(unsigned int); +}; + +class CXMLSOMAttribute +{ +public: +EQLIB_OBJECT CXMLSOMAttribute::~CXMLSOMAttribute(void); +EQLIB_OBJECT CXMLSOMAttribute::CXMLSOMAttribute(void); +EQLIB_OBJECT class CXMLSOMAttribute & CXMLSOMAttribute::operator=(class CXMLSOMAttribute const &); +//EQLIB_OBJECT void * CXMLSOMAttribute::`vector deleting destructor'(unsigned int); +}; + +class CXMLSOMAttributeType +{ +public: +EQLIB_OBJECT CXMLSOMAttributeType::~CXMLSOMAttributeType(void); +EQLIB_OBJECT CXMLSOMAttributeType::CXMLSOMAttributeType(void); +EQLIB_OBJECT class CXMLSOMAttributeType & CXMLSOMAttributeType::operator=(class CXMLSOMAttributeType const &); +//EQLIB_OBJECT void * CXMLSOMAttributeType::`vector deleting destructor'(unsigned int); +}; + +class CXMLSOMCursor +{ +public: +EQLIB_OBJECT CXMLSOMCursor::~CXMLSOMCursor(void); +EQLIB_OBJECT CXMLSOMCursor::CXMLSOMCursor(void); +EQLIB_OBJECT class CXMLSOMCursor & CXMLSOMCursor::operator=(class CXMLSOMCursor const &); +//EQLIB_OBJECT void * CXMLSOMCursor::`vector deleting destructor'(unsigned int); +}; + +class CXMLSOMCursorSave +{ +public: +EQLIB_OBJECT CXMLSOMCursorSave::~CXMLSOMCursorSave(void); +}; + +class CXMLSOMCursorSaveFast +{ +public: +EQLIB_OBJECT CXMLSOMCursorSaveFast::~CXMLSOMCursorSaveFast(void); +}; + +class CXMLSOMCursorTraverseChildren +{ +public: +EQLIB_OBJECT CXMLSOMCursorTraverseChildren::~CXMLSOMCursorTraverseChildren(void); +EQLIB_OBJECT class CXMLSOMCursor & CXMLSOMCursorTraverseChildren::Cursor(void); +}; + +class CXMLSOMDocument +{ +public: +EQLIB_OBJECT bool CXMLSOMDocument::FieldParseItemOfClass(class CXStr,class CXStr,unsigned __int32 &); +EQLIB_OBJECT bool CXMLSOMDocument::GetValueObjectId(class CXStr,class CXStr,unsigned __int32 &); +EQLIB_OBJECT bool CXMLSOMDocument::SetValueObjectId(class CXStr,class CXStr,unsigned __int32); +// virtual +EQLIB_OBJECT CXMLSOMDocument::~CXMLSOMDocument(void); +//EQLIB_OBJECT void * CXMLSOMDocument::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CXMLSOMDocument::`vector deleting destructor'(unsigned int); +}; + +class CXMLSOMDocumentBase +{ +public: +EQLIB_OBJECT bool CXMLSOMDocumentBase::CursorFieldFind(class CXStr); +EQLIB_OBJECT bool CXMLSOMDocumentBase::CursorFind(class CXStr); +EQLIB_OBJECT bool CXMLSOMDocumentBase::CursorNextInOrder(void); +EQLIB_OBJECT bool CXMLSOMDocumentBase::CursorNextSibling(void); +EQLIB_OBJECT bool CXMLSOMDocumentBase::CursorPop(void); +EQLIB_OBJECT bool CXMLSOMDocumentBase::CursorPush(void); +EQLIB_OBJECT bool CXMLSOMDocumentBase::FieldParseClassItem(class CXStr,class CXStr &,class CXStr &); +EQLIB_OBJECT bool CXMLSOMDocumentBase::FieldParseItemOfClass(class CXStr,class CXStr,__int32 &,__int32 &); +EQLIB_OBJECT bool CXMLSOMDocumentBase::GetAttrValueInt(class CXStr,__int32 &); +EQLIB_OBJECT bool CXMLSOMDocumentBase::GetAttrValueStr(class CXStr,class CXStr &); +EQLIB_OBJECT bool CXMLSOMDocumentBase::GetValue(class CXStr,__int32 &); +EQLIB_OBJECT bool CXMLSOMDocumentBase::GetValue(class CXStr,bool &); +EQLIB_OBJECT bool CXMLSOMDocumentBase::GetValue(class CXStr,class CXStr &); +EQLIB_OBJECT bool CXMLSOMDocumentBase::SetValue(class CXStr,__int32); +EQLIB_OBJECT bool CXMLSOMDocumentBase::SetValue(class CXStr,bool); +EQLIB_OBJECT bool CXMLSOMDocumentBase::SetValue(class CXStr,class CXStr); +EQLIB_OBJECT bool CXMLSOMDocumentBase::ValidateData(void); +EQLIB_OBJECT bool CXMLSOMDocumentBase::ValidateSchema(void); +EQLIB_OBJECT bool CXMLSOMDocumentBase::XMLMerge(class CXMLSOMDocumentBase &); +EQLIB_OBJECT bool CXMLSOMDocumentBase::XMLRead(class CXStr*,class CXStr*,class CXStr*); +EQLIB_OBJECT class CXMLSOMCursor & CXMLSOMDocumentBase::Cursor(void); +EQLIB_OBJECT class CXMLSOMCursor & CXMLSOMDocumentBase::CursorParent(void); +EQLIB_OBJECT class CXStr CXMLSOMDocumentBase::GetAttrValueStr(class CXStr); +EQLIB_OBJECT class CXStr CXMLSOMDocumentBase::GetErrorMsg(void)const; +EQLIB_OBJECT int CXMLSOMDocumentBase::XMLReadNoValidate(class CXStr,class CXStr,class CXStr); +EQLIB_OBJECT void CXMLSOMDocumentBase::CursorInit(void); +EQLIB_OBJECT void CXMLSOMDocumentBase::CursorNewChild(void); +EQLIB_OBJECT void CXMLSOMDocumentBase::CursorNewSibling(void); +EQLIB_OBJECT void CXMLSOMDocumentBase::CursorSetPtr(class CXMLSOMNodePtr); +EQLIB_OBJECT void CXMLSOMDocumentBase::Init(void); +EQLIB_OBJECT void CXMLSOMDocumentBase::SetErrorMsg(class CXStr); +EQLIB_OBJECT void CXMLSOMDocumentBase::SetErrorMsgAtCursor(class CXStr); +EQLIB_OBJECT void CXMLSOMDocumentBase::SetErrorMsgAtLine(class CXStr,int,class CXStr); +// virtual +EQLIB_OBJECT CXMLSOMDocumentBase::~CXMLSOMDocumentBase(void); +//EQLIB_OBJECT void * CXMLSOMDocumentBase::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CXMLSOMDocumentBase::`vector deleting destructor'(unsigned int); +// protected +EQLIB_OBJECT bool CXMLSOMDocumentBase::ValidateDataElements(class CXMLSOMElementType &); +EQLIB_OBJECT bool CXMLSOMDocumentBase::ValidateSchemaCategories(void); +EQLIB_OBJECT bool CXMLSOMDocumentBase::ValidateSchemaDefinition(void); +EQLIB_OBJECT bool CXMLSOMDocumentBase::ValidateSchemaElementType(void); +EQLIB_OBJECT bool CXMLSOMDocumentBase::ValidateSchemaSimpleType(void); +EQLIB_OBJECT bool CXMLSOMDocumentBase::ValidateSchemaSimpleTypeNode(class CXMLSOMSimpleType &); +EQLIB_OBJECT bool CXMLSOMDocumentBase::ValidateSchemaTypeRefs(void); +EQLIB_OBJECT bool CXMLSOMDocumentBase::XMLProcessComposite(class CXStr,class CXStr); +}; + +class CXMLSOMElement +{ +public: +EQLIB_OBJECT CXMLSOMElement::~CXMLSOMElement(void); +EQLIB_OBJECT CXMLSOMElement::CXMLSOMElement(void); +EQLIB_OBJECT class CXMLSOMElement & CXMLSOMElement::operator=(class CXMLSOMElement const &); +//EQLIB_OBJECT void * CXMLSOMElement::`vector deleting destructor'(unsigned int); +}; + +class CXMLSOMElementType +{ +public: +EQLIB_OBJECT CXMLSOMElementType::~CXMLSOMElementType(void); +EQLIB_OBJECT CXMLSOMElementType::CXMLSOMElementType(void); +EQLIB_OBJECT int CXMLSOMElementType::GetItemIdx(class CXStr); +//EQLIB_OBJECT void * CXMLSOMElementType::`vector deleting destructor'(unsigned int); +}; + +class CXMLSOMNode +{ +public: +EQLIB_OBJECT static void * __cdecl CXMLSOMNode::operator new(unsigned int); +EQLIB_OBJECT static void __cdecl CXMLSOMNode::FreeAllAllocs(void); +EQLIB_OBJECT static void __cdecl CXMLSOMNode::operator delete(void *); +// protected +EQLIB_OBJECT static char * * CXMLSOMNode::pAllAlloc; +EQLIB_OBJECT static class CMutexSync CXMLSOMNode::mutexAccess; +EQLIB_OBJECT static class CXMLSOMNode * CXMLSOMNode::pFreeHead; +// private +EQLIB_OBJECT CXMLSOMNode::~CXMLSOMNode(void); +EQLIB_OBJECT CXMLSOMNode::CXMLSOMNode(void); +//EQLIB_OBJECT void * CXMLSOMNode::`scalar deleting destructor'(unsigned int); +}; + +class CXMLSOMNodePtr +{ +public: +EQLIB_OBJECT CXMLSOMNodePtr::~CXMLSOMNodePtr(void); +EQLIB_OBJECT CXMLSOMNodePtr::CXMLSOMNodePtr(void); +EQLIB_OBJECT class CXMLSOMNode * CXMLSOMNodePtr::operator->(void)const; +EQLIB_OBJECT class CXMLSOMNodePtr & CXMLSOMNodePtr::operator=(class CXMLSOMNodePtr const &); +//EQLIB_OBJECT void * CXMLSOMNodePtr::`vector deleting destructor'(unsigned int); +// protected +EQLIB_OBJECT void CXMLSOMNodePtr::Assure(void)const; +}; + +class CXMLSOMParser +{ +public: +EQLIB_OBJECT CXMLSOMParser::~CXMLSOMParser(void); +EQLIB_OBJECT bool CXMLSOMParser::ParseFile(class CXStr); +// protected +EQLIB_OBJECT bool CXMLSOMParser::ParseDocument(void); +EQLIB_OBJECT bool CXMLSOMParser::ParseEndTag(class CXStr); +EQLIB_OBJECT bool CXMLSOMParser::ParseNameSpaceToken(class CXStr &); +EQLIB_OBJECT bool CXMLSOMParser::ParseNode(void); +EQLIB_OBJECT bool CXMLSOMParser::ParseNodeList(void); +EQLIB_OBJECT bool CXMLSOMParser::ParseProcess(void); +EQLIB_OBJECT bool CXMLSOMParser::ParseStartTag(bool &); +}; + +class CXMLSOMSchema +{ +public: +EQLIB_OBJECT CXMLSOMSchema::~CXMLSOMSchema(void); +EQLIB_OBJECT CXMLSOMSchema::CXMLSOMSchema(void); +EQLIB_OBJECT bool CXMLSOMSchema::AddItem(class CXStr,class CXStr); +EQLIB_OBJECT bool CXMLSOMSchema::FindElementType(class CXStr); +EQLIB_OBJECT bool CXMLSOMSchema::FindItem(class CXStr,class CXStr); +EQLIB_OBJECT bool CXMLSOMSchema::FindSimpleType(class CXStr); +EQLIB_OBJECT bool CXMLSOMSchema::IsDerivedFrom(class CXStr,class CXStr); +EQLIB_OBJECT int CXMLSOMSchema::GetElementTypeIdx(class CXStr); +}; + +class CXMLSOMSimpleType +{ +public: +EQLIB_OBJECT CXMLSOMSimpleType::~CXMLSOMSimpleType(void); +EQLIB_OBJECT CXMLSOMSimpleType::CXMLSOMSimpleType(void); +//EQLIB_OBJECT void * CXMLSOMSimpleType::`vector deleting destructor'(unsigned int); +}; + +class CXPoint +{ +public: +EQLIB_OBJECT class CXPoint CXPoint::operator=(class CXPoint); +DWORD A,B; +}; + +class CXRect +{ +public: +EQLIB_OBJECT CXRect::CXRect(int nA,int nB,int nC,int nD) +{ + A=nA; + B=nB; + C=nC; + D=nD; +} +EQLIB_OBJECT CXRect::CXRect(void) +{ +} +EQLIB_OBJECT class CXPoint CXRect::CenterPoint(void)const; +EQLIB_OBJECT class CXRect & CXRect::operator=(class CXRect const &); +EQLIB_OBJECT class CXRect CXRect::operator&(class CXRect)const; +EQLIB_OBJECT class CXRect CXRect::operator|(class CXRect)const; +EQLIB_OBJECT int CXRect::Width(void)const; +EQLIB_OBJECT void CXRect::Move(class CXPoint); +EQLIB_OBJECT void CXRect::Normalize(void); +DWORD A,B,C,D; +}; + + +class CXStrSingleton +{ +public: +EQLIB_OBJECT static int CXStrSingleton::active; +}; + +class CXWndDrawTemplate +{ +public: +EQLIB_OBJECT CXWndDrawTemplate::~CXWndDrawTemplate(void); +EQLIB_OBJECT CXWndDrawTemplate::CXWndDrawTemplate(class CXWndDrawTemplate const &); +EQLIB_OBJECT CXWndDrawTemplate::CXWndDrawTemplate(void); +EQLIB_OBJECT class CXWndDrawTemplate & CXWndDrawTemplate::operator=(class CXWndDrawTemplate const &); +}; + +class CXWndManager +{ +public: +EQLIB_OBJECT CXWndManager::CXWndManager(class CSidlManager *); +EQLIB_OBJECT bool CXWndManager::IsAllValid(void); +EQLIB_OBJECT bool CXWndManager::IsWindowActive(class CXWnd const *)const; +EQLIB_OBJECT bool CXWndManager::IsWindowMovingOrSizing(class CXWnd *)const; +EQLIB_OBJECT bool CXWndManager::IsWindowPieceDown(class CXWnd const *,int)const; +EQLIB_OBJECT bool CXWndManager::OkayToSendMouseMessage(class CXWnd *)const; +EQLIB_OBJECT class CTextureAnimation const * CXWndManager::GetCursorToDisplay(void)const; +EQLIB_OBJECT class CTextureFont * CXWndManager::GetFont(class CXStr); +EQLIB_OBJECT class CTextureFont * CXWndManager::GetFont(int)const; +EQLIB_OBJECT class CXWnd * CXWndManager::FindWnd(class CXPoint,int *)const; +EQLIB_OBJECT class CXWnd * CXWndManager::GetFirstChildWnd(class CXWnd const *)const; +EQLIB_OBJECT class CXWnd * CXWndManager::GetFocusWnd(void)const; +EQLIB_OBJECT class CXWnd * CXWndManager::GetNextSib(class CXWnd const *)const; +EQLIB_OBJECT class CXWnd * CXWndManager::SetFocusWnd(class CXWnd *); +EQLIB_OBJECT int CXWndManager::ActivateWnd(class CXWnd *); +EQLIB_OBJECT int CXWndManager::AddFont(class CTextureFont *); +EQLIB_OBJECT int CXWndManager::AddWnd(class CXWnd *); +EQLIB_OBJECT int CXWndManager::DrawCursor(void)const; +EQLIB_OBJECT int CXWndManager::DrawWindows(void)const; +EQLIB_OBJECT int CXWndManager::HandleKeyboardMsg(unsigned __int32,bool); +EQLIB_OBJECT int CXWndManager::HandleLButtonDown(class CXPoint); +EQLIB_OBJECT int CXWndManager::HandleLButtonHeld(class CXPoint); +EQLIB_OBJECT int CXWndManager::HandleLButtonUp(class CXPoint); +EQLIB_OBJECT int CXWndManager::HandleLButtonUpAfterHeld(class CXPoint); +EQLIB_OBJECT int CXWndManager::HandleMouseMove(class CXPoint); +EQLIB_OBJECT int CXWndManager::HandleRButtonDown(class CXPoint); +EQLIB_OBJECT int CXWndManager::HandleRButtonHeld(class CXPoint); +EQLIB_OBJECT int CXWndManager::HandleRButtonUp(class CXPoint); +EQLIB_OBJECT int CXWndManager::HandleRButtonUpAfterHeld(class CXPoint); +EQLIB_OBJECT int CXWndManager::HandleWheelMove(int); +EQLIB_OBJECT int CXWndManager::NotifyAllWindows(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT int CXWndManager::OnWindowCloseBox(class CXWnd *); +EQLIB_OBJECT int CXWndManager::OnWindowMinimizeBox(class CXWnd *); +EQLIB_OBJECT int CXWndManager::OnWindowTileBox(class CXWnd *); +EQLIB_OBJECT int CXWndManager::ProcessFrame(void); +EQLIB_OBJECT int CXWndManager::RemoveWnd(class CXWnd *); +EQLIB_OBJECT static class CTextureAnimation CXWndManager::sm_curDefault; +EQLIB_OBJECT static class CTextureAnimation CXWndManager::sm_curDrag; +EQLIB_OBJECT static class CTextureAnimation CXWndManager::sm_curResizeEW; +EQLIB_OBJECT static class CTextureAnimation CXWndManager::sm_curResizeNESW; +EQLIB_OBJECT static class CTextureAnimation CXWndManager::sm_curResizeNS; +EQLIB_OBJECT static class CTextureAnimation CXWndManager::sm_curResizeNWSE; +EQLIB_OBJECT unsigned __int32 CXWndManager::GetDisplayWidth(void)const; +EQLIB_OBJECT unsigned __int32 CXWndManager::GetGlobalFadeDuration(void)const; +EQLIB_OBJECT unsigned __int32 CXWndManager::GetKeyboardFlags(void)const; +EQLIB_OBJECT unsigned char CXWndManager::GetGlobalAlpha(void)const; +EQLIB_OBJECT unsigned char CXWndManager::GetGlobalFadeToAlpha(void)const; +EQLIB_OBJECT unsigned long CXWndManager::GetGlobalFadeDelay(void)const; +EQLIB_OBJECT void CXWndManager::BringWndToTop(class CXWnd *,bool); +EQLIB_OBJECT void CXWndManager::CheckInvalidateLastFoundWnd(void); +EQLIB_OBJECT void CXWndManager::CleanupWindows(void); +EQLIB_OBJECT void CXWndManager::DestroyAllWindows(void); +EQLIB_OBJECT void CXWndManager::FlushKeyboardFlags(void); +EQLIB_OBJECT void CXWndManager::OnWindowShown(class CXWnd *,bool); +EQLIB_OBJECT void CXWndManager::SetGlobalAlpha(unsigned char); +EQLIB_OBJECT void CXWndManager::SetGlobalFadeDelay(unsigned long); +EQLIB_OBJECT void CXWndManager::SetGlobalFadeDuration(unsigned __int32); +EQLIB_OBJECT void CXWndManager::SetGlobalFadeToAlpha(unsigned char); +EQLIB_OBJECT void CXWndManager::SetSystemFont(class CTextureFont *); +EQLIB_OBJECT void CXWndManager::UpdateChildAndSiblingInfo(void); +// virtual +EQLIB_OBJECT CXWndManager::~CXWndManager(void); +//EQLIB_OBJECT void * CXWndManager::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * CXWndManager::`vector deleting destructor'(unsigned int); +}; + +class EmitterManager +{ +public: +EQLIB_OBJECT EmitterManager::~EmitterManager(void); +EQLIB_OBJECT EmitterManager::EmitterManager(class SoundManager *); +EQLIB_OBJECT float EmitterManager::GetEffectsLevel(void); +EQLIB_OBJECT float EmitterManager::GetVolumeLevel(void); +EQLIB_OBJECT void EmitterManager::Add(class SoundEmitter *); +EQLIB_OBJECT void EmitterManager::GetListenerLocation(float *,float *,float *,float *); +EQLIB_OBJECT void EmitterManager::GiveTime(void); +EQLIB_OBJECT void EmitterManager::Remove(class SoundEmitter *); +EQLIB_OBJECT void EmitterManager::SetEffectsLevel(float); +EQLIB_OBJECT void EmitterManager::SetVolumeLevel(float); +}; + +class engineInterface +{ +public: +EQLIB_OBJECT static class engineInterface * __cdecl engineInterface::get(void); +EQLIB_OBJECT unsigned long * engineInterface::ChangeDag(struct T3D_tagWORLD *,struct T3D_DAG *,char *); +// private +EQLIB_OBJECT engineInterface::engineInterface(void); +EQLIB_OBJECT static class engineInterface * engineInterface::mSelf; +}; + +class EQ_Affect +{ +public: +EQLIB_OBJECT void EQ_Affect::Reset(void); +}; + +class EQ_AltAbility +{ +public: +EQLIB_OBJECT EQ_AltAbility::EQ_AltAbility(int); +}; + +class EQ_Character1 +{ +public: +EQLIB_OBJECT int EQ_Character1::Cur_HP(int,unsigned char y=1); +EQLIB_OBJECT int EQ_Character1::Max_Endurance(int y=1); // lax 4-25-2004 +EQLIB_OBJECT int EQ_Character1::Max_HP(int,int y=1); +EQLIB_OBJECT int EQ_Character1::Max_Mana(int y=1); +EQLIB_OBJECT int const EQ_Character1::GetAACastingTimeModifier(class EQ_Spell const *); +EQLIB_OBJECT int const EQ_Character1::GetFocusCastingTimeModifier(class EQ_Spell const *,class EQ_Equipment * *,int); +EQLIB_OBJECT unsigned char EQ_Character1::CastSpell(unsigned char,int,class EQ_Item * *,int,int slot,int,int,int,int,bool,int y=1); +EQLIB_OBJECT void EQ_Character1::SetEffectId(unsigned char,unsigned int); +EQLIB_OBJECT void EQ_Character1::StopSpellCast(unsigned char); +EQLIB_OBJECT void EQ_Character1::StopSpellCast(unsigned char,int); +EQLIB_OBJECT void EQ_Character1::StunMe(unsigned int,unsigned int,unsigned int); +EQLIB_OBJECT void EQ_Character1::UnStunMe(void); +EQLIB_OBJECT void EQ_Character1::UseSkill(unsigned char,class EQPlayer *); +EQLIB_OBJECT int const EQ_Character1::GetFocusRangeModifier(class EQ_Spell const *,class EQ_Equipment * *); +EQLIB_OBJECT int EQ_Character1::IsExpansionFlag(int); +EQLIB_OBJECT int EQ_Character1::TotalEffect(int,bool,int,bool,bool); +}; + +class EQ_Character +{ +public: +EQLIB_OBJECT EQ_Character::~EQ_Character(void); +EQLIB_OBJECT EQ_Character::EQ_Character(void); +EQLIB_OBJECT bool EQ_Character::DoesSpellMatchFocusFilters(class EQ_Spell const *,class EQ_Spell const *); +EQLIB_OBJECT bool EQ_Character::IsSpellTooPowerfull(class EQ_Spell *,class EQ_Character *); +EQLIB_OBJECT bool EQ_Character::IsStackBlocked(class EQ_Spell const *); +EQLIB_OBJECT bool EQ_Character::IsValidAffect(int); +EQLIB_OBJECT char * EQ_Character::Class(int); +EQLIB_OBJECT char * EQ_Character::KunarkClass(int,int,int,bool); +EQLIB_OBJECT char * EQ_Character::Race(int); +EQLIB_OBJECT class EQ_Affect & EQ_Character::GetEffect(int); +EQLIB_OBJECT class EQ_Affect * EQ_Character::FindAffectSlot(int,class EQPlayer *,int *,int); +EQLIB_OBJECT class EQ_Affect * EQ_Character::GetPCSpellAffect(unsigned char,int *); +EQLIB_OBJECT class EQ_Equipment * EQ_Character::GetFocusItem(class EQ_Spell const *,int); +EQLIB_OBJECT class EQ_Spell * EQ_Character::GetFocusEffect(class EQ_Spell const *,int); +EQLIB_OBJECT class EQPlayer * EQ_Character::FindClosest(int,int,int,int,int); +EQLIB_OBJECT class EQPlayer * EQ_Character::GetMyPetPlayer(void); +EQLIB_OBJECT float EQ_Character::encum_factor(void); +EQLIB_OBJECT int EQ_Character::ac(bool); +EQLIB_OBJECT int EQ_Character::Agi(void); +EQLIB_OBJECT int EQ_Character::AntiTwinkAdj(class EQ_Equipment *,int,int); +EQLIB_OBJECT int EQ_Character::ApplyDamage(int,struct _EQMissileHitinfo *,bool,class HateListEntry *,bool); +EQLIB_OBJECT int EQ_Character::ApplyFatigue(int); +EQLIB_OBJECT int EQ_Character::AutoEat(unsigned char); +EQLIB_OBJECT int EQ_Character::BaneDamage(class EQ_Equipment *); +EQLIB_OBJECT int EQ_Character::BardCastBard(class EQ_Spell const *,int)const; +EQLIB_OBJECT int EQ_Character::basesave_cold(void); +EQLIB_OBJECT int EQ_Character::basesave_disease(void); +EQLIB_OBJECT int EQ_Character::basesave_fire(void); +EQLIB_OBJECT int EQ_Character::basesave_magic(void); +EQLIB_OBJECT int EQ_Character::basesave_poison(void); +EQLIB_OBJECT int EQ_Character::CalcAffectChange(class EQ_Spell *,unsigned char,unsigned char,class EQ_Affect *); +EQLIB_OBJECT int EQ_Character::CalculateBardSongMod(int); +EQLIB_OBJECT int EQ_Character::CanUseItem(class EQ_Item *); +EQLIB_OBJECT int EQ_Character::CapStat(int,int); +EQLIB_OBJECT int EQ_Character::Cha(void); +EQLIB_OBJECT int EQ_Character::CheckFoodAndWater(void); +EQLIB_OBJECT int EQ_Character::compute_defense(void); +EQLIB_OBJECT int EQ_Character::compute_tohit(unsigned char); +EQLIB_OBJECT int EQ_Character::cur_encumbrance(void); +EQLIB_OBJECT int EQ_Character::Cur_Mana(void); +EQLIB_OBJECT int EQ_Character::defense_agility_bonus(void); +EQLIB_OBJECT int EQ_Character::Dex(void); +EQLIB_OBJECT int EQ_Character::ElementResistDmg(class EQ_Equipment *,int); +EQLIB_OBJECT int EQ_Character::eqspa_change_form(class EQ_Spell *,int,int,class EQ_Affect *); +EQLIB_OBJECT int EQ_Character::eqspa_hp(unsigned int,class EQ_Affect *,int,class EQ_Spell *); +EQLIB_OBJECT int EQ_Character::GetBardInstrumentMod(int); +EQLIB_OBJECT int EQ_Character::GetClassACBonus(int); +EQLIB_OBJECT int EQ_Character::GetFirstEffectSlot(bool); +EQLIB_OBJECT int EQ_Character::GetHPFromStamina(int); +EQLIB_OBJECT int EQ_Character::GetIndexSkillMinDamageMod(int); +EQLIB_OBJECT int EQ_Character::GetLastEffectSlot(bool); +EQLIB_OBJECT int EQ_Character::GetOpenEffectSlot(bool,int); +EQLIB_OBJECT int EQ_Character::HasInnateSkill(unsigned char,int); +EQLIB_OBJECT int EQ_Character::HasSkill(unsigned char); +EQLIB_OBJECT int EQ_Character::HasSpell(int); +EQLIB_OBJECT int EQ_Character::IHaveSkill(unsigned char); +EQLIB_OBJECT int EQ_Character::InSpecialBindSpot(class EQPlayer *); +EQLIB_OBJECT int EQ_Character::Int(void); +EQLIB_OBJECT int EQ_Character::IsMage(void); +EQLIB_OBJECT int EQ_Character::IsSpecialBazaarSpot(class EQPlayer *); +EQLIB_OBJECT int EQ_Character::IsSpellcaster(void); +EQLIB_OBJECT int EQ_Character::ItemSpellAffects(int); +EQLIB_OBJECT int EQ_Character::max_encumbrance(void); +EQLIB_OBJECT int EQ_Character::NoBashMe(int); +EQLIB_OBJECT int EQ_Character::NoMezMe(int,class EQPlayer *,class EQ_Spell *); +EQLIB_OBJECT int EQ_Character::offense(unsigned char); +EQLIB_OBJECT int EQ_Character::ProcessAffects(void); +EQLIB_OBJECT int EQ_Character::save_bash(int); +EQLIB_OBJECT int EQ_Character::save_cold(void); +EQLIB_OBJECT int EQ_Character::save_disease(void); +EQLIB_OBJECT int EQ_Character::save_fire(void); +EQLIB_OBJECT int EQ_Character::save_magic(void); +EQLIB_OBJECT int EQ_Character::save_poison(void); +EQLIB_OBJECT int EQ_Character::SetLocalVar(char *,int); +EQLIB_OBJECT int EQ_Character::Skill(int); +EQLIB_OBJECT int EQ_Character::SpellDuration(class EQ_Spell const *,unsigned char,unsigned char); +EQLIB_OBJECT int EQ_Character::Sta(void); +EQLIB_OBJECT int EQ_Character::Str(void); +EQLIB_OBJECT int EQ_Character::TakeFallDamage(float); +EQLIB_OBJECT int EQ_Character::TotalSpellAffects(unsigned char,bool,int *); +EQLIB_OBJECT int EQ_Character::Wis(void); +EQLIB_OBJECT int const EQ_Character::GetFocusConserveRegChance(class EQ_Spell const *,class EQ_Equipment * *); +EQLIB_OBJECT long EQ_Character::TotalOnPerson(void); +EQLIB_OBJECT static int __cdecl EQ_Character::normal_to_special(int); +EQLIB_OBJECT unsigned char EQ_Character::BarbarianCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::BaseAttr(int,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::CanDoubleAttack(class EQPlayer *,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::CanIBreathe(void); +EQLIB_OBJECT unsigned char EQ_Character::CanISeeInvis(void); +EQLIB_OBJECT unsigned char EQ_Character::CanMedOnHorse(void); +EQLIB_OBJECT unsigned char EQ_Character::CanSecondaryAttack(class EQPlayer *); +EQLIB_OBJECT unsigned char EQ_Character::CanWorship(int,int,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::CastingRequirementsMet(int); +EQLIB_OBJECT unsigned char EQ_Character::CheckClass(int,int); +EQLIB_OBJECT unsigned char EQ_Character::CityCanStart(int,int,int,int); +EQLIB_OBJECT unsigned char EQ_Character::ClassMin(int,int,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::DarkElfCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::DwarfCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::ElfCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::EruditeCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::ExpendItemCharge(int,int); +EQLIB_OBJECT unsigned char EQ_Character::FindItemByClass(int,int *,int *); +EQLIB_OBJECT unsigned char EQ_Character::FindItemByRecord(int,int *,int *); +EQLIB_OBJECT unsigned char EQ_Character::FindItemQty(int,int); +EQLIB_OBJECT unsigned char EQ_Character::FroglockCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::GetMaxEffects(void)const; +EQLIB_OBJECT unsigned char EQ_Character::GetSkillBaseDamage(unsigned char,class EQPlayer *); +EQLIB_OBJECT unsigned char EQ_Character::GnomeCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::HalfElfCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::HalflingCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::HighElfCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::HumanCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::IksarCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::IsSpellAffectingPC(int); +EQLIB_OBJECT unsigned char EQ_Character::LaunchSpell(unsigned char,int,class EQ_Item * *); +EQLIB_OBJECT unsigned char EQ_Character::OgreCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::SpellFizzled(unsigned char,class EQ_Spell *); +EQLIB_OBJECT unsigned char EQ_Character::TrollCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned char EQ_Character::VahShirCanWorship(unsigned char,unsigned char); +EQLIB_OBJECT unsigned int EQ_Character::GetEffectId(int); +EQLIB_OBJECT void EQ_Character::CalcFoodDrinkBonus(int); +EQLIB_OBJECT void EQ_Character::DoFishingEvent(void); +EQLIB_OBJECT void EQ_Character::DoIntimidationEvent(void); +EQLIB_OBJECT void EQ_Character::DoLight(unsigned char); +EQLIB_OBJECT void EQ_Character::DoMeditation(void); +EQLIB_OBJECT void EQ_Character::DoPassageOfTime(void); +EQLIB_OBJECT void EQ_Character::EQ_CharacterResetAllMembers(void); +EQLIB_OBJECT void EQ_Character::EQSPA_Feign_Death(int); +EQLIB_OBJECT void EQ_Character::eqspa_levitation(void); +EQLIB_OBJECT void EQ_Character::eqspa_locate_corpse(void); +EQLIB_OBJECT void EQ_Character::eqspa_movement_rate(int); +EQLIB_OBJECT void EQ_Character::HandleSpecialPCAffects(int); +EQLIB_OBJECT void EQ_Character::HitBySpell(struct _EQMissileHitinfo *); +EQLIB_OBJECT void EQ_Character::IAmDead(struct _EQMissileHitinfo *,int); +EQLIB_OBJECT void EQ_Character::InitInnates(unsigned int,unsigned int); +EQLIB_OBJECT void EQ_Character::InitMyLanguages(void); +EQLIB_OBJECT void EQ_Character::InitSkills(unsigned char,unsigned int); +EQLIB_OBJECT void EQ_Character::ItemSold(long); +EQLIB_OBJECT void EQ_Character::MakeMeVisible(int); +EQLIB_OBJECT void EQ_Character::ModifyCurHP(int,class EQPlayer *); +EQLIB_OBJECT void EQ_Character::NotifyPCAffectChange(int,int); +EQLIB_OBJECT void EQ_Character::ProcessAllStats(void); +EQLIB_OBJECT void EQ_Character::ProcessEnvironment(void); +EQLIB_OBJECT void EQ_Character::ProcessHungerandThirst(unsigned int); +EQLIB_OBJECT void EQ_Character::RemovePCAffect(class EQ_Affect *); +EQLIB_OBJECT void EQ_Character::RemovePCAffectex(class EQ_Affect *,int); +EQLIB_OBJECT void EQ_Character::ResetCur_HP(int); +EQLIB_OBJECT void EQ_Character::UpdateMyVisibleStatus(void); +EQLIB_OBJECT bool EQ_Character::DoCombatAbility(int spellID, int dummy=1); +EQLIB_OBJECT unsigned long EQ_Character::GetConLevel(class EQPlayer *); +// private +EQLIB_OBJECT int EQ_Character::GetCachEQSPA(int); +EQLIB_OBJECT void EQ_Character::ReCachItemEffects(void); +EQLIB_OBJECT void EQ_Character::ReCachSpellEffects(void); +}; + +class EQ_CharacterData +{ +public: +EQLIB_OBJECT void EQ_CharacterData::EQ_CharacterDataResetAllMembers(void); +}; + +class EQ_Container +{ +public: +EQLIB_OBJECT EQ_Container::~EQ_Container(void); +EQLIB_OBJECT EQ_Container::EQ_Container(void); +EQLIB_OBJECT unsigned char EQ_Container::Close(void); +EQLIB_OBJECT unsigned char EQ_Container::IsOpen(void); +EQLIB_OBJECT unsigned char EQ_Container::Open(void); +}; + +class EQ_Equipment +{ +public: +EQLIB_OBJECT EQ_Equipment::EQ_Equipment(void); +EQLIB_OBJECT int EQ_Equipment::IsInstrument(void); +EQLIB_OBJECT int EQ_Equipment::IsWeapon(void); +EQLIB_OBJECT void EQ_Equipment::SendTextRequestMsg(void); +}; + +class EQ_Item +{ +public: +EQLIB_OBJECT bool EQ_Item::IsSpecialNoDrop(void); +EQLIB_OBJECT char * EQ_Item::ValueSBuy(float,long); +EQLIB_OBJECT char * EQ_Item::ValueSRent(void); +EQLIB_OBJECT char * EQ_Item::ValueSSell(float,long); +EQLIB_OBJECT int EQ_Item::Copper(void); +EQLIB_OBJECT int EQ_Item::Gold(void); +EQLIB_OBJECT int EQ_Item::Platinum(void); +EQLIB_OBJECT int EQ_Item::Silver(void); +EQLIB_OBJECT long EQ_Item::ValueSellMerchant(float,long); +EQLIB_OBJECT bool EQ_Item::IsStackable(void); // Valerian 12-20-2004 + +EQLIB_OBJECT char * EQ_Item::CreateItemTagString(char *, int); // Lax 11-14-2003 +EQLIB_OBJECT int EQ_Item::CanDrop(bool,int,int mq2_dummy=0, int mq2_dummy2=1); +ITEMINFO Data; +}; + +class EQ_LoadingS +{ +public: +EQLIB_OBJECT EQ_LoadingS::~EQ_LoadingS(void); +EQLIB_OBJECT EQ_LoadingS::EQ_LoadingS(void); +EQLIB_OBJECT void EQ_LoadingS::draw(void); +EQLIB_OBJECT void EQ_LoadingS::DrawBackground(struct T3D_XYZ *); +EQLIB_OBJECT void EQ_LoadingS::SetProgressBar(int,char const *); +EQLIB_OBJECT void EQ_LoadingS::WriteTextHD(char *,int,int,int); +// virtual +EQLIB_OBJECT void EQ_LoadingS::Activate(void); +EQLIB_OBJECT void EQ_LoadingS::Deactivate(void); +EQLIB_OBJECT void EQ_LoadingS::DefineImages(void); +}; + +class EQ_Note +{ +public: +EQLIB_OBJECT EQ_Note::~EQ_Note(void); +EQLIB_OBJECT EQ_Note::EQ_Note(void); +EQLIB_OBJECT void EQ_Note::SendTextRequestMsg(void); +}; + +class EQ_PC +{ +public: +EQLIB_OBJECT EQ_PC::~EQ_PC(void); +EQLIB_OBJECT EQ_PC::EQ_PC(class EQ_PC *); +EQLIB_OBJECT int EQ_PC::BitchCanTrain(int,int,int); +EQLIB_OBJECT int EQ_PC::CheckDupLoreItems(void); +EQLIB_OBJECT int EQ_PC::checkLang(int); +EQLIB_OBJECT int EQ_PC::CostToTrain(int,float,int); +EQLIB_OBJECT int EQ_PC::DelLoreItemDup(int,int,int,class EQ_Item *); +EQLIB_OBJECT int EQ_PC::GetAltAbilityIndex(int); +EQLIB_OBJECT int EQ_PC::GetArmorType(int); +EQLIB_OBJECT int EQ_PC::GetCombatAbility(int); +EQLIB_OBJECT int EQ_PC::HandleMoney(long); +EQLIB_OBJECT int EQ_PC::IsAGroupMember(char *); +EQLIB_OBJECT int EQ_PC::MaxAirSupply(void); +EQLIB_OBJECT int EQ_PC::numInParty(void); +EQLIB_OBJECT static class EQ_PC * EQ_PC::top; +EQLIB_OBJECT unsigned char EQ_PC::AtSkillLimit(int); +EQLIB_OBJECT unsigned char EQ_PC::RemoveMyAffect(int); +EQLIB_OBJECT unsigned long EQ_PC::GetArmorTint(int); +EQLIB_OBJECT unsigned long EQ_PC::GetBodyTint(int); +EQLIB_OBJECT void EQ_PC::CheckForGroupChanges(void); +EQLIB_OBJECT void EQ_PC::CheckForLanguageImprovement(unsigned char,unsigned char); +EQLIB_OBJECT void EQ_PC::CheckSkillImprove(int,float); +EQLIB_OBJECT void EQ_PC::ClearSharedVault(void); +EQLIB_OBJECT void EQ_PC::DestroyHeldItemOrMoney(void); +EQLIB_OBJECT void EQ_PC::DetermineQuestExpGained(int); +EQLIB_OBJECT void EQ_PC::EmptyPossessionSlots(void); +EQLIB_OBJECT void EQ_PC::InitializeNewPCVariables(int); +EQLIB_OBJECT void EQ_PC::InitPlayerStart(unsigned int,unsigned char,int); +EQLIB_OBJECT void EQ_PC::PrepareForRepop(int); +EQLIB_OBJECT void EQ_PC::ProcessAirSupply(void); +EQLIB_OBJECT void EQ_PC::ProcessFatigue(void); +EQLIB_OBJECT void EQ_PC::RefitNewbieEQ(void); +EQLIB_OBJECT void EQ_PC::RefreshMe(int); +EQLIB_OBJECT void EQ_PC::SetAltAbilityIndex(int,int); +EQLIB_OBJECT void EQ_PC::SetArmorTint(int,unsigned long); +EQLIB_OBJECT void EQ_PC::SetArmorType(int,int); +EQLIB_OBJECT void EQ_PC::SetFatigue(int); +EQLIB_OBJECT void EQ_PC::UnpackMyNetPC(char *,int); +EQLIB_OBJECT unsigned long EQ_PC::GetCombatAbilityTimer(int); +EQLIB_OBJECT unsigned long EQ_PC::GetItemTimerValue(class EQ_Item *); +EQLIB_OBJECT unsigned long EQ_PC::HasLoreItem(class EQ_Item *); +}; + +class EQ_Skill +{ +public: +EQLIB_OBJECT EQ_Skill::~EQ_Skill(void); +EQLIB_OBJECT EQ_Skill::EQ_Skill(int); +}; + +class EQ_Spell +{ +public: +EQLIB_OBJECT EQ_Spell::~EQ_Spell(void); +EQLIB_OBJECT EQ_Spell::EQ_Spell(char *); +EQLIB_OBJECT bool EQ_Spell::IsStackableDot(void)const; +EQLIB_OBJECT int EQ_Spell::IsPermIllusionSpell(void)const; +EQLIB_OBJECT int EQ_Spell::SpellUsesDragonBreathEffect(void); +EQLIB_OBJECT static bool __cdecl EQ_Spell::IsSPAIgnoredByStacking(int); +EQLIB_OBJECT unsigned char EQ_Spell::SpellAffects(int)const; +SPELL Data; +}; + +class EQAnimation +{ +public: +EQLIB_OBJECT EQAnimation::~EQAnimation(void); +EQLIB_OBJECT EQAnimation::EQAnimation(void); +}; + +class EQEffect +{ +public: +EQLIB_OBJECT EQEffect::~EQEffect(void); +EQLIB_OBJECT EQEffect::EQEffect(class EQEffect *,char *,int,struct _EQLOC *,class EQPlayer *,class EQMissile *,struct _EQRGB *,float,int,int,float,float); +EQLIB_OBJECT static class EQEffect * EQEffect::top; +}; + +class EqEmitterData +{ +public: +EQLIB_OBJECT EqEmitterData::EqEmitterData(void); +EQLIB_OBJECT void EqEmitterData::SetLoadString(char *); +}; + +class EQHSprite +{ +public: +EQLIB_OBJECT EQHSprite::~EQHSprite(void); +EQLIB_OBJECT EQHSprite::EQHSprite(char *,struct T3D_tagACTORINSTANCE *,class EQPlayer *); +EQLIB_OBJECT bool EQHSprite::GetAnimationTrackPtr(char *,char *,int,int,unsigned char,int); +EQLIB_OBJECT class EQHSprite * EQHSprite::get_object(char *); +EQLIB_OBJECT static class EQHSprite * EQHSprite::top; +}; + +class EQItemList +{ +public: +EQLIB_OBJECT EQItemList::~EQItemList(void); +EQLIB_OBJECT EQItemList::EQItemList(void); +EQLIB_OBJECT class EQItemList * EQItemList::get_item(long); +EQLIB_OBJECT class EQItemList * EQItemList::is_item_actor(struct T3D_tagACTORINSTANCE *); +EQLIB_OBJECT static class EQItemList * EQItemList::top; +}; + +class EQMissile +{ +public: +EQLIB_OBJECT EQMissile::~EQMissile(void); +EQLIB_OBJECT EQMissile::EQMissile(class EQ_Equipment *,class EQPlayer *,class EQMissile *,char *,unsigned char,unsigned int); +EQLIB_OBJECT class EQMissile * EQMissile::is_missile_actor(struct T3D_tagACTORINSTANCE *); +EQLIB_OBJECT static class EQMissile * EQMissile::top; +EQLIB_OBJECT void EQMissile::CleanUpMyEffects(void); +EQLIB_OBJECT void EQMissile::HitActor(struct T3D_tagACTORINSTANCE *,bool); +EQLIB_OBJECT void EQMissile::LeaveTrail(void); +EQLIB_OBJECT void EQMissile::MissileAI(void); +EQLIB_OBJECT void EQMissile::ProcessMissile(void); +}; + +class EqMobileEmitter +{ +public: +EQLIB_OBJECT EqMobileEmitter::~EqMobileEmitter(void); +EQLIB_OBJECT EqMobileEmitter::EqMobileEmitter(class EqSoundManager *); +EQLIB_OBJECT void EqMobileEmitter::Move(float,float,float); +EQLIB_OBJECT void EqMobileEmitter::SetNpcHeight(float); +EQLIB_OBJECT void EqMobileEmitter::SetWave(int,char *); +}; + +class EQMoneyList +{ +public: +EQLIB_OBJECT EQMoneyList::~EQMoneyList(void); +EQLIB_OBJECT EQMoneyList::EQMoneyList(void); +EQLIB_OBJECT class EQMoneyList * EQMoneyList::get_money(long); +EQLIB_OBJECT static class EQMoneyList * EQMoneyList::top; +}; + +class EQNewPlayerAnimation +{ +public: +EQLIB_OBJECT static void __cdecl EQNewPlayerAnimation::InitAnimationData(void); +}; + +class EQObject +{ +public: +EQLIB_OBJECT EQObject::~EQObject(void); +EQLIB_OBJECT EQObject::EQObject(class EQObject *,class EQPlayer *,char *,char *); +EQLIB_OBJECT static class EQObject * EQObject::top; +}; + +class EQOldPlayerAnimation +{ +public: +EQLIB_OBJECT EQOldPlayerAnimation::EQOldPlayerAnimation(class EQPlayer *); +EQLIB_OBJECT static void __cdecl EQOldPlayerAnimation::InitAnimationData(void); +// virtual +EQLIB_OBJECT bool EQOldPlayerAnimation::RequestAnimation(unsigned short,bool,bool,float,unsigned char); +EQLIB_OBJECT bool EQOldPlayerAnimation::RequestAnimation(unsigned short,bool,bool,float,unsigned char,unsigned char); +EQLIB_OBJECT int EQOldPlayerAnimation::GetAnimNum(int,int,int,float *,unsigned char); +EQLIB_OBJECT void EQOldPlayerAnimation::InitAnimationTracks(class EQHSprite *,struct T3D_tagACTORINSTANCE *); +EQLIB_OBJECT void EQOldPlayerAnimation::PlayAnimationSound(int); +EQLIB_OBJECT void EQOldPlayerAnimation::ProcessAnimation(bool,bool); +// private +EQLIB_OBJECT bool EQOldPlayerAnimation::AnimationIsAggressive(int); +EQLIB_OBJECT bool EQOldPlayerAnimation::InterruptCurrentAnimation(int,unsigned char); +EQLIB_OBJECT bool EQOldPlayerAnimation::IsIdleAnimation(int); +EQLIB_OBJECT bool EQOldPlayerAnimation::IsSocialAnimation(int); +EQLIB_OBJECT bool EQOldPlayerAnimation::IsStandAnimation(int); +EQLIB_OBJECT static bool * EQOldPlayerAnimation::mAnimAllowsSeparateLower; +EQLIB_OBJECT static bool * EQOldPlayerAnimation::mAnimAllowsSeparateUpper; +EQLIB_OBJECT static bool * EQOldPlayerAnimation::mAnimInterruptable; +EQLIB_OBJECT static char (* EQOldPlayerAnimation::mAnimationPrefix)[20]; +EQLIB_OBJECT virtual bool EQOldPlayerAnimation::GetAlternateAnimTag(char *,char *,bool); +EQLIB_OBJECT void EQOldPlayerAnimation::ChangeAttachmentAnimationTrackSpeeds(bool,float); +EQLIB_OBJECT void EQOldPlayerAnimation::PlayAttachmentAnimationTracks(int,int,bool,bool,float,bool,unsigned char); +}; + +class EQPlayer +{ +public: +EQLIB_OBJECT EQPlayer::~EQPlayer(void); +EQLIB_OBJECT EQPlayer::EQPlayer(class EQPlayer *,unsigned char,unsigned int,unsigned char,char *); +EQLIB_OBJECT bool EQPlayer::AllowedToAttack(class EQPlayer *,int); +EQLIB_OBJECT bool EQPlayer::CanChangeForm(int,unsigned char); +EQLIB_OBJECT bool EQPlayer::CanIFitHere(float,float,float); +EQLIB_OBJECT bool EQPlayer::CanIHit(class EQPlayer *,float); +EQLIB_OBJECT bool EQPlayer::GetBoneCoords(struct T3D_DAG *,struct _EQLOC *); +EQLIB_OBJECT bool EQPlayer::IsAMount(void); +EQLIB_OBJECT bool EQPlayer::IsFlyer(void); +EQLIB_OBJECT bool EQPlayer::IsInvisible(class EQPlayer *); +EQLIB_OBJECT bool EQPlayer::IsInvited(void); +EQLIB_OBJECT bool EQPlayer::IsRoleplaying(void); +EQLIB_OBJECT bool EQPlayer::IsUntexturedHorse(void); +EQLIB_OBJECT bool EQPlayer::IWasHit(struct _EQMissileHitinfo *); +EQLIB_OBJECT bool EQPlayer::MyFeetAreOnGround(void); +EQLIB_OBJECT bool EQPlayer::SetNameSpriteTint(void); +EQLIB_OBJECT bool EQPlayer::UpdatePlayerActor(void); +EQLIB_OBJECT bool const EQPlayer::HasInvalidRiderTexture(void)const; +EQLIB_OBJECT float EQPlayer::GetDefaultHeight(int,unsigned char); +EQLIB_OBJECT float EQPlayer::GetPlayerFloorHeight(float,float,float,unsigned char); +EQLIB_OBJECT int EQPlayer::AimAtTarget(class EQPlayer *,class EQMissile *); +EQLIB_OBJECT int EQPlayer::AttachPlayerToPlayerBone(class EQPlayer *,struct T3D_DAG *); +EQLIB_OBJECT int EQPlayer::CanBeBald(void); +EQLIB_OBJECT int EQPlayer::CheckForJump(void); +EQLIB_OBJECT int EQPlayer::DoAttack(unsigned char,unsigned char,class EQPlayer *); +EQLIB_OBJECT int EQPlayer::GetAlternateTrackNumber(int,unsigned char *); +EQLIB_OBJECT int EQPlayer::GetArmorType(int); +EQLIB_OBJECT int EQPlayer::GetAttachedHelmITNum(int,int *); +EQLIB_OBJECT int EQPlayer::GetGuild(void)const; +EQLIB_OBJECT int EQPlayer::GetRaceSexITOffset(void); +EQLIB_OBJECT int EQPlayer::IsValidTeleport(float,float,float,float,float); +EQLIB_OBJECT int EQPlayer::LegalPlayerRace(int); +EQLIB_OBJECT int EQPlayer::Levitating(void); +EQLIB_OBJECT int EQPlayer::MountableRace(void); +EQLIB_OBJECT int EQPlayer::MovePlayer(void); +EQLIB_OBJECT int EQPlayer::NotOnSameDeity(class EQPlayer *,class EQ_Spell *); +EQLIB_OBJECT int EQPlayer::ReplaceSpecialCloakMaterials(void); +EQLIB_OBJECT int EQPlayer::SetEyeMaterial(unsigned char,int); +EQLIB_OBJECT int EQPlayer::SetFHEB(unsigned char,unsigned char); +EQLIB_OBJECT int EQPlayer::SetFHEB_Color(unsigned char,unsigned char); +EQLIB_OBJECT int EQPlayer::SetHairOrBeard(int); +EQLIB_OBJECT int EQPlayer::SetNameSpriteState(bool); +EQLIB_OBJECT int EQPlayer::SetPlayerPitchType(void); +EQLIB_OBJECT int EQPlayer::SwapBody(int,int); +EQLIB_OBJECT int EQPlayer::SwapFace(int,int); +EQLIB_OBJECT int EQPlayer::SwapHead(int,int,unsigned long,int); +EQLIB_OBJECT int EQPlayer::SwapMaterial(int,int,int,int,unsigned char); +EQLIB_OBJECT int EQPlayer::SwapNPCMaterials(void); +EQLIB_OBJECT static class EQPlayer * __cdecl EQPlayer::GetClosestPlayerFromPartialName(char *,class EQPlayer *); +EQLIB_OBJECT static class EQPlayer * __cdecl EQPlayer::GetPlayerFromPartialName(char *); +EQLIB_OBJECT static class EQPlayer * __cdecl EQPlayer::IsPlayerActor(struct T3D_tagACTORINSTANCE *); +EQLIB_OBJECT static class EQPlayer * __cdecl EQPlayer::GetPlayerFromName(char const *); +EQLIB_OBJECT static void __cdecl EQPlayer::ComputeSpecialHeights(int,float *,float *,float *,float *,bool); +EQLIB_OBJECT static void __cdecl EQPlayer::GetPCActorTag(char *,unsigned int,unsigned char); +EQLIB_OBJECT static void __cdecl EQPlayer::TackOnNeuterChar(char *,unsigned int); +EQLIB_OBJECT static void __cdecl EQPlayer::UpdateAllPlayersVisibility(void); +EQLIB_OBJECT struct T3D_DAG * EQPlayer::GetBonePointerByITS(int,int); +EQLIB_OBJECT struct T3D_POINTLIGHT * EQPlayer::CreateUserLight(struct T3D_LIGHTDEFINITION *,int); +EQLIB_OBJECT unsigned char EQPlayer::DoTeleport(char *,int); +EQLIB_OBJECT unsigned char EQPlayer::DoTeleportB(int,float,float,float,float,char*,int); +EQLIB_OBJECT unsigned char EQPlayer::GetBaseFaceNbr(int,unsigned char *); +EQLIB_OBJECT unsigned char EQPlayer::GetNearestActorTag(char *,void *); +EQLIB_OBJECT unsigned char EQPlayer::HandleAmmo(void); +EQLIB_OBJECT unsigned char EQPlayer::HasAttachedBeard(void); +EQLIB_OBJECT unsigned char EQPlayer::HasAttachedHair(void); +EQLIB_OBJECT unsigned char EQPlayer::SkillUsed(unsigned char); +EQLIB_OBJECT unsigned char EQPlayer::UpdateItemSlot(unsigned char,char *,int); +EQLIB_OBJECT unsigned int EQPlayer::CalcAnimLength(int); +EQLIB_OBJECT unsigned int EQPlayer::ModifyAttackSpeed(unsigned int,int); +EQLIB_OBJECT unsigned long EQPlayer::GetArmorTint(int); +EQLIB_OBJECT void EQPlayer::BodyEnvironmentChange(unsigned char); +EQLIB_OBJECT void EQPlayer::ChangeHeight(float); +EQLIB_OBJECT void EQPlayer::ChangeLight(void); +EQLIB_OBJECT void EQPlayer::ChangeNoGravity(int); +EQLIB_OBJECT void EQPlayer::ChangePosition(unsigned char); +EQLIB_OBJECT void EQPlayer::CheckForUnderFloor(void); +EQLIB_OBJECT void EQPlayer::CleanUpMyEffects(void); +EQLIB_OBJECT void EQPlayer::CleanUpTarget(void); +EQLIB_OBJECT void EQPlayer::CleanUpVehicle(void); +EQLIB_OBJECT void EQPlayer::DeleteMyMissiles(void); +EQLIB_OBJECT void EQPlayer::Dismount(void); +EQLIB_OBJECT void EQPlayer::DisplayWeaponsAndArmor(void); +EQLIB_OBJECT void EQPlayer::do_change_form(struct chngForm *); +EQLIB_OBJECT void EQPlayer::DoCamAi(void); +EQLIB_OBJECT void EQPlayer::DoClassRandomAnimation(void); +EQLIB_OBJECT void EQPlayer::DoFloorCheck(void); +EQLIB_OBJECT void EQPlayer::DoItemSlot(int); +EQLIB_OBJECT void EQPlayer::DoSwimJump(unsigned char); +EQLIB_OBJECT void EQPlayer::FacePlayer(class EQPlayer *); +EQLIB_OBJECT void EQPlayer::FeetEnvironmentChange(unsigned char); +EQLIB_OBJECT void EQPlayer::FollowPlayerAI(void); +EQLIB_OBJECT void EQPlayer::ForceInvisible(bool); +EQLIB_OBJECT void EQPlayer::GetActorTag(char *); +EQLIB_OBJECT void EQPlayer::GetAllowedHairColorIndexRange(int,int *,int *); +EQLIB_OBJECT void EQPlayer::GetConscious(void); +EQLIB_OBJECT void EQPlayer::HandleMaterialEx(int,unsigned int,unsigned int,unsigned long,int); +EQLIB_OBJECT void EQPlayer::HandoverControlToZoneserver(void); +EQLIB_OBJECT void EQPlayer::HeadEnvironmentChange(unsigned char); +EQLIB_OBJECT void EQPlayer::HideOrShowAttachedHair(void); +EQLIB_OBJECT void EQPlayer::IDied(struct _EQPlayerDeath *); +EQLIB_OBJECT void EQPlayer::IHaveFallen(float); +EQLIB_OBJECT void EQPlayer::InitSneakMod(void); +EQLIB_OBJECT void EQPlayer::KnockedOut(void); +EQLIB_OBJECT void EQPlayer::MakeRiderMountUp(void); +EQLIB_OBJECT void EQPlayer::MountEQPlayer(class EQPlayer *); +EQLIB_OBJECT void EQPlayer::PlaySoundA(int); +EQLIB_OBJECT void EQPlayer::PositionOnFloor(void); +EQLIB_OBJECT void EQPlayer::PushAlongHeading(float); +EQLIB_OBJECT void EQPlayer::PutPlayerOnFloor(void); +EQLIB_OBJECT void EQPlayer::ResetVariables(void); +EQLIB_OBJECT void EQPlayer::SetAccel(float,int); +EQLIB_OBJECT void EQPlayer::SetAfk(int); +EQLIB_OBJECT void EQPlayer::SetAndReserveID(unsigned int); +EQLIB_OBJECT void EQPlayer::SetAnimVariation(void); +EQLIB_OBJECT void EQPlayer::SetArmorTint(int,unsigned long); +EQLIB_OBJECT void EQPlayer::SetArmorType(int,int); +EQLIB_OBJECT void EQPlayer::SetCurrentLoopSound(int); +EQLIB_OBJECT void EQPlayer::SetDefaultFacialFeaturesByFace(int,unsigned char,unsigned char); +EQLIB_OBJECT void EQPlayer::SetDefaultITAttachments(int); +EQLIB_OBJECT void EQPlayer::SetHeights(void); +EQLIB_OBJECT void EQPlayer::SetInvited(bool); +EQLIB_OBJECT void EQPlayer::SetPlayerConstantAmbient(struct T3D_RGB *); +EQLIB_OBJECT void EQPlayer::SetRace(int); +EQLIB_OBJECT void EQPlayer::SetSounds(void); +EQLIB_OBJECT void EQPlayer::SetToRandomRace(void); +EQLIB_OBJECT void EQPlayer::TouchingSwitch(void); +EQLIB_OBJECT void EQPlayer::TriggerSpellEffect(struct _EQMissileHitinfo *); +EQLIB_OBJECT void EQPlayer::TurnOffAutoFollow(void); +EQLIB_OBJECT void EQPlayer::UpdateAppearance(void); +EQLIB_OBJECT void EQPlayer::UpdateBonePointers(void); +EQLIB_OBJECT void EQPlayer::UpdateNameSprite(void); +EQLIB_OBJECT void EQPlayer::UpdatePlayerVisibility(void); +EQLIB_OBJECT bool EQPlayer::IsBodyType(unsigned int,int,int); +// private +EQLIB_OBJECT int EQPlayer::IdUsed(unsigned int); +EQLIB_OBJECT static class EQPlayer * EQPlayer::mTop; +EQLIB_OBJECT struct S3D_STRINGSPRITE * EQPlayer::ChangeBoneStringSprite(struct T3D_DAG *,char *); +EQLIB_OBJECT unsigned char EQPlayer::GetAlternateAnimVariation(int,unsigned char); +EQLIB_OBJECT unsigned int EQPlayer::GetUnusedID(void); +EQLIB_OBJECT void EQPlayer::FindDefaultEyeMaterialIndexes(void); +EQLIB_OBJECT void EQPlayer::InitializeIDArray(void); +SPAWNINFO Data; +}; + + +class EQPlayerManager +{ +public: +EQLIB_OBJECT class EQPlayer *EQPlayerManager::GetSpawnByID(int); +EQLIB_OBJECT class EQPlayer *EQPlayerManager::GetSpawnByName(char *); +SPAWNMANAGER Data; +}; + +class EQPMInfo +{ +public: +EQLIB_OBJECT EQPMInfo::~EQPMInfo(void); +EQLIB_OBJECT EQPMInfo::EQPMInfo(char *); +EQLIB_OBJECT void EQPMInfo::SetApplyGravity(bool); +}; + +class EqSoundManager +{ +public: +EQLIB_OBJECT EqSoundManager::~EqSoundManager(void); +//EQLIB_OBJECT EqSoundManager::EqSoundManager(bool,bool,enum SpeakerType); +EQLIB_OBJECT bool EqSoundManager::EmitterLoad(char *); +EQLIB_OBJECT bool EqSoundManager::WaveIsPlaying(int); +EQLIB_OBJECT class SoundAsset * EqSoundManager::WaveGet(int); +//EQLIB_OBJECT enum EnvironmentType EqSoundManager::GetListenerEnvironment(void); +EQLIB_OBJECT void EqSoundManager::EmitterAdd(class EqEmitterData *); +EQLIB_OBJECT void EqSoundManager::EmitterSetIndoors(bool); +EQLIB_OBJECT void EqSoundManager::EmitterSetNight(bool); +EQLIB_OBJECT void EqSoundManager::EmitterSetRaining(bool); +EQLIB_OBJECT void EqSoundManager::EmitterSetUserDisabled(bool); +EQLIB_OBJECT void EqSoundManager::EmitterSetWind(bool); +EQLIB_OBJECT void EqSoundManager::GiveTime(void); +EQLIB_OBJECT void EqSoundManager::SetCurrentZone(char *); +EQLIB_OBJECT void EqSoundManager::SetEffectsLevel(float); +//EQLIB_OBJECT void EqSoundManager::SetListenerEnvironment(enum EnvironmentType); +EQLIB_OBJECT void EqSoundManager::SetListenerEnvironmentHigh(void); +EQLIB_OBJECT void EqSoundManager::SetListenerEnvironmentLow(void); +EQLIB_OBJECT void EqSoundManager::SetListenerEnvironmentOutside(void); +EQLIB_OBJECT void EqSoundManager::SetListenerLocation(float,float,float,float); +EQLIB_OBJECT void EqSoundManager::SetMixAhead(int); +EQLIB_OBJECT void EqSoundManager::SetMusicSelection(int,bool); +EQLIB_OBJECT void EqSoundManager::SetMusicVolume(float); +EQLIB_OBJECT void EqSoundManager::SetWaveVolume(float); +EQLIB_OBJECT void EqSoundManager::WaveLoad(char *,int,bool); +EQLIB_OBJECT void EqSoundManager::WavePlay(int,class SoundControl *); +EQLIB_OBJECT void EqSoundManager::WaveStop(int); +// private +EQLIB_OBJECT class SoundAsset * EqSoundManager::GetAsset(char *); +EQLIB_OBJECT class SoundAsset * EqSoundManager::OldMp3GetSelection(int); +EQLIB_OBJECT class SoundEmitter * EqSoundManager::CreateOldEmitter(int,float,float,float,int,int,int,float,int,int,int); +EQLIB_OBJECT int EqSoundManager::GetMusicId(void); +EQLIB_OBJECT void EqSoundManager::LoadGlobalEmitters(void); +EQLIB_OBJECT void EqSoundManager::LoadGlobalMusic(void); +EQLIB_OBJECT void EqSoundManager::LoadGlobalWaves(void); +EQLIB_OBJECT void EqSoundManager::LoadListOfWaveFiles(char * *,int); +EQLIB_OBJECT void EqSoundManager::LoadOldEmitters(void); +EQLIB_OBJECT void EqSoundManager::OldMp3ClearSelections(void); +EQLIB_OBJECT void EqSoundManager::OldMp3Init(void); +EQLIB_OBJECT void EqSoundManager::OldMp3Terminate(void); +EQLIB_OBJECT void EqSoundManager::ReleaseZoneSpecificEmitters(void); +EQLIB_OBJECT void EqSoundManager::ReleaseZoneSpecificMidi(void); +EQLIB_OBJECT void EqSoundManager::ReleaseZoneSpecificWaves(void); +EQLIB_OBJECT void EqSoundManager::UpdateEmitterStates(void); +}; + +class EQSwitch +{ +public: +EQLIB_OBJECT EQSwitch::~EQSwitch(void); +EQLIB_OBJECT EQSwitch::EQSwitch(char *,bool); +EQLIB_OBJECT EQSwitch::EQSwitch(struct _EQClientSwitch *); +EQLIB_OBJECT EQSwitch::EQSwitch(struct OldDiskSwitch *,bool); +EQLIB_OBJECT float EQSwitch::GetCustomMoveDistance(void); +EQLIB_OBJECT float EQSwitch::TopSpeed(float *); +EQLIB_OBJECT int EQSwitch::GetSwitchDamage(void); +EQLIB_OBJECT unsigned char EQSwitch::SwitchIsNotUsable(int); +EQLIB_OBJECT unsigned char EQSwitch::SwitchWasOpened(int,int,class EQPlayer *,bool *); +EQLIB_OBJECT unsigned char EQSwitch::SwitchWasOpenedActual(int,int,class EQPlayer *,bool *); +EQLIB_OBJECT unsigned int EQSwitch::RepopFrequency(void); +EQLIB_OBJECT void EQSwitch::ChangeState(unsigned char,class EQPlayer *,bool); +EQLIB_OBJECT void EQSwitch::LoadSwitchSounds(int); +EQLIB_OBJECT void EQSwitch::PostInit(void); +EQLIB_OBJECT void EQSwitch::PreInit(void); +EQLIB_OBJECT void EQSwitch::RepopSwitch(void); +EQLIB_OBJECT void EQSwitch::ResetSwitchState(unsigned char); +EQLIB_OBJECT void EQSwitch::UseSwitch(unsigned int,int,int); +}; + +class EqSwitchManager +{ +public: +EQLIB_OBJECT EqSwitchManager::~EqSwitchManager(void); +EQLIB_OBJECT EqSwitchManager::EqSwitchManager(void); +EQLIB_OBJECT class EQSwitch * EqSwitchManager::GetSwitch(int); +EQLIB_OBJECT class EQSwitch * EqSwitchManager::GetSwitchByActor(struct T3D_tagACTORINSTANCE *); +EQLIB_OBJECT class EQSwitch * EqSwitchManager::GetSwitchById(int,bool); +EQLIB_OBJECT int EqSwitchManager::GetCount(void); +EQLIB_OBJECT void EqSwitchManager::AddSwitch(class EQSwitch *); +EQLIB_OBJECT void EqSwitchManager::DeleteAll(void); +EQLIB_OBJECT void EqSwitchManager::Load(char *,bool); +// protected +EQLIB_OBJECT void EqSwitchManager::LoadOld(char *,bool); +}; + +class EQUtil +{ +public: +EQLIB_OBJECT static char * __cdecl EQUtil::FormatCharName(char *,char *,int); +}; + +class EQWorldData +{ +public: +EQLIB_OBJECT EQWorldData::EQWorldData(void); +EQLIB_OBJECT bool EQWorldData::GetGeometryNameFromIndex(EQZoneIndex,char *)const; +EQLIB_OBJECT bool EQWorldData::IsFlagSet(EQZoneIndex,unsigned long)const; +EQLIB_OBJECT bool EQWorldData::IsNewbieZone(EQZoneIndex)const; +EQLIB_OBJECT bool EQWorldData::IsNoAirZone(EQZoneIndex)const; +EQLIB_OBJECT bool EQWorldData::IsNoBindZone(EQZoneIndex)const; +EQLIB_OBJECT bool const EQWorldData::AddZone(enum EQExpansion,EQZoneIndex,char const *,char const *,int,unsigned long,int,int); +//EQLIB_OBJECT enum EQExpansion const EQWorldData::ExpansionZone(EQZoneIndex)const; +EQLIB_OBJECT DWORD EQWorldData::GetIndexFromZoneName(char const *); // EQZoneIndex +EQLIB_OBJECT int EQWorldData::GetMinLevel(EQZoneIndex)const; +EQLIB_OBJECT void EQWorldData::AdvanceTime(unsigned int); +EQLIB_OBJECT void EQWorldData::CurrentGameTime(char *); +EQLIB_OBJECT void EQWorldData::GetFullZoneName(EQZoneIndex,char *); +// virtual +EQLIB_OBJECT EQWorldData::~EQWorldData(void); +//EQLIB_OBJECT void * EQWorldData::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * EQWorldData::`vector deleting destructor'(unsigned int); +}; + +class EQZoneInfo +{ +public: +EQLIB_OBJECT EQZoneInfo::EQZoneInfo(enum EQExpansion,EQZoneIndex,char const *,char const *,int,unsigned long,int,int); +// virtual +EQLIB_OBJECT EQZoneInfo::~EQZoneInfo(void); +//EQLIB_OBJECT void * EQZoneInfo::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * EQZoneInfo::`vector deleting destructor'(unsigned int); +}; + +class FilePath +{ +public: +EQLIB_OBJECT FilePath::~FilePath(void); +EQLIB_OBJECT FilePath::FilePath(char const *); +EQLIB_OBJECT FilePath::FilePath(class SharedString const &); +EQLIB_OBJECT FilePath::FilePath(void); +}; + +class flex_unit +{ +public: +EQLIB_OBJECT flex_unit::~flex_unit(void); +EQLIB_OBJECT flex_unit::flex_unit(void); +EQLIB_OBJECT unsigned int flex_unit::get(unsigned int)const; +EQLIB_OBJECT void flex_unit::clear(void); +EQLIB_OBJECT void flex_unit::fast_mul(class flex_unit &,class flex_unit &,unsigned int); +EQLIB_OBJECT void flex_unit::reserve(unsigned int); +EQLIB_OBJECT void flex_unit::set(unsigned int,unsigned int); +}; + +class GrammarRulesClass +{ +public: +EQLIB_OBJECT GrammarRulesClass::GrammarRulesClass(void); +EQLIB_OBJECT char * GrammarRulesClass::Resolve(int,int,char *,char *); +// virtual +EQLIB_OBJECT GrammarRulesClass::~GrammarRulesClass(void); +//EQLIB_OBJECT void * GrammarRulesClass::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * GrammarRulesClass::`vector deleting destructor'(unsigned int); +// private +EQLIB_OBJECT char * GrammarRulesClass::Parse(char *); +EQLIB_OBJECT void GrammarRulesClass::RuleDe1(char *,char *); +EQLIB_OBJECT void GrammarRulesClass::RuleEn1(char *,char *); +EQLIB_OBJECT void GrammarRulesClass::RuleEn2(char *,char *); +EQLIB_OBJECT void GrammarRulesClass::RuleEn3(char *,char *,char *,char *); +EQLIB_OBJECT void GrammarRulesClass::RuleEn4(char *,char *,char *,char *); +EQLIB_OBJECT void GrammarRulesClass::RuleFr1(char *,char *,char *,char *); +EQLIB_OBJECT void GrammarRulesClass::RuleKo1(char *,char *,char *,char *); +}; + +class GuildMember +{ +public: +EQLIB_OBJECT GuildMember::GuildMember(void); +}; + +class JournalNPC +{ +public: +EQLIB_OBJECT JournalNPC::~JournalNPC(void); +EQLIB_OBJECT JournalNPC::JournalNPC(void); +EQLIB_OBJECT int JournalNPC::AddEntry(long,float,float,float,char *,int); +EQLIB_OBJECT int JournalNPC::AddEntry(long,float,float,float,int,int); +EQLIB_OBJECT int JournalNPC::DeleteEntryByHash(int); +EQLIB_OBJECT int JournalNPC::DeleteEntryByIndex(int); +EQLIB_OBJECT int JournalNPC::FindThisText(char *,bool,int); +EQLIB_OBJECT int JournalNPC::ReadEntry(struct _iobuf *); +EQLIB_OBJECT static char * __cdecl JournalNPC::GetText(int); +EQLIB_OBJECT struct JournalEntry * JournalNPC::FindEntryByCategory(int,int); +EQLIB_OBJECT struct JournalEntry * JournalNPC::FindEntryByHash(int); +EQLIB_OBJECT struct JournalEntry * JournalNPC::GetEntry(int); +EQLIB_OBJECT void JournalNPC::ConvertCategory(int,int); +// private +EQLIB_OBJECT void JournalNPC::AllocateArray(void); +EQLIB_OBJECT void JournalNPC::CleanEntries(void); +EQLIB_OBJECT void JournalNPC::ComputeLatestTime(void); +}; + +class KeyCombo +{ +public: +EQLIB_OBJECT KeyCombo::KeyCombo(int); +inline EQLIB_OBJECT KeyCombo::KeyCombo(unsigned char keycode,bool alt,bool ctrl,bool shift) +{ + Data[3]= keycode; + Data[0]=alt; + Data[1]=ctrl; + Data[2]=shift; +} +EQLIB_OBJECT KeyCombo::KeyCombo(unsigned int,unsigned int,bool,bool,bool); +inline EQLIB_OBJECT KeyCombo::KeyCombo(void) +{ + *(unsigned long*)&Data[0]=0; +} +inline void EQLIB_OBJECT KeyCombo::Clear(void) +{ + *(unsigned long*)&Data[0]=0; +} +EQLIB_OBJECT int KeyCombo::operator int(void)const; +EQLIB_OBJECT bool KeyCombo::GetPrintableLetter(unsigned short *)const; +inline EQLIB_OBJECT bool KeyCombo::UsesAlt(void)const +{ + return (Data[0]!=0); +} +inline EQLIB_OBJECT bool KeyCombo::UsesCtrl(void)const +{ + return (Data[1]!=0); +} +inline EQLIB_OBJECT bool KeyCombo::UsesShift(void)const +{ + return (Data[2]!=0); +} +EQLIB_OBJECT class CXStr KeyCombo::GetTextDescription(void)const; +EQLIB_OBJECT class KeyCombo const & KeyCombo::operator=(int); +inline EQLIB_OBJECT int KeyCombo::operator==(class KeyCombo const &Combo) +{ + return ((*(unsigned long*)&Data)==(*(unsigned long*)&Combo.Data)); +} +inline EQLIB_OBJECT unsigned int KeyCombo::GetKey(void)const +{ + return Data[3]; +} +// private +EQLIB_OBJECT bool KeyCombo::GetPrintableLetterFromScanCode(unsigned char,bool,bool,unsigned short *)const; +EQLIB_OBJECT bool KeyCombo::GetPrintableLetterFromVirtualKey(unsigned int,unsigned int,bool,bool,unsigned short *)const; +EQLIB_OBJECT bool KeyCombo::GetScanCodeFromVirtualKey(unsigned int,unsigned int,unsigned char *)const; +EQLIB_OBJECT bool KeyCombo::GetVirtualKeyFromScanCode(unsigned char,int *)const; + unsigned char Data[4]; +}; + +class KeypressHandler +{ +public: +EQLIB_OBJECT KeypressHandler::~KeypressHandler(void); +EQLIB_OBJECT KeypressHandler::KeypressHandler(void); +EQLIB_OBJECT bool KeypressHandler::AttachAltKeyToEqCommand(class KeyCombo const &,unsigned int); +EQLIB_OBJECT bool KeypressHandler::AttachKeyToEqCommand(class KeyCombo const &,unsigned int); +EQLIB_OBJECT bool KeypressHandler::HandleKeyDown(class KeyCombo const &); +EQLIB_OBJECT bool KeypressHandler::HandleKeyUp(class KeyCombo const &); +EQLIB_OBJECT class KeyCombo const & KeypressHandler::GetAltKeyAttachedToEqCommand(unsigned int)const; +EQLIB_OBJECT class KeyCombo const & KeypressHandler::GetKeyAttachedToEqCommand(unsigned int)const; +EQLIB_OBJECT void KeypressHandler::ResetKeysToEqDefaults(void); +// private +EQLIB_OBJECT bool KeypressHandler::IsReservedKey(class KeyCombo const &)const; +EQLIB_OBJECT bool KeypressHandler::LoadAndConvertOldKeymappingFormat(unsigned int,int,class KeyCombo *); +EQLIB_OBJECT bool KeypressHandler::LoadKeymapping(unsigned int,int,class KeyCombo *); +EQLIB_OBJECT bool KeypressHandler::MapKeyToEqCommand(class KeyCombo const &,int,unsigned int); +EQLIB_OBJECT class CXStr KeypressHandler::GetEqCommandSaveName(unsigned int,int)const; +EQLIB_OBJECT void KeypressHandler::ClearCommandStateArray(void); +EQLIB_OBJECT void KeypressHandler::LoadAndSetKeymappings(void); +EQLIB_OBJECT void KeypressHandler::SaveKeymapping(unsigned int,class KeyCombo const &,int); +/*0x000*/ class KeyCombo NormalKey[nEQMappableCommands]; +/*0x2 4*/ class KeyCombo AltKey[nEQMappableCommands]; +/*0x5C8*/ char CommandState[nEQMappableCommands]; +}; + +class LogicalPacket +{ +public: +EQLIB_OBJECT LogicalPacket::LogicalPacket(void); +// virtual +EQLIB_OBJECT bool LogicalPacket::IsInternalPacket(void)const; +EQLIB_OBJECT int LogicalPacket::GetRefCount(void)const; +EQLIB_OBJECT void LogicalPacket::AddRef(void)const; +EQLIB_OBJECT void LogicalPacket::Release(void)const; +// protected +EQLIB_OBJECT virtual LogicalPacket::~LogicalPacket(void); +//EQLIB_OBJECT virtual void * LogicalPacket::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT virtual void * LogicalPacket::`vector deleting destructor'(unsigned int); +}; + +class MapViewMap +{ +public: +EQLIB_OBJECT MapViewMap::~MapViewMap(void); +EQLIB_OBJECT MapViewMap::MapViewMap(void); +EQLIB_OBJECT bool MapViewMap::DrawClippedLine(struct T3D_XYZ *,struct T3D_RGB,class CXRect); +EQLIB_OBJECT bool MapViewMap::IsLayerVisible(int); +EQLIB_OBJECT bool MapViewMap::LoadEx(char *,int); +EQLIB_OBJECT bool MapViewMap::PointInMapViewArea(class CXPoint,class CXRect); +EQLIB_OBJECT int MapViewMap::GetMaxZ(void); +EQLIB_OBJECT int MapViewMap::GetMinZ(void); +EQLIB_OBJECT unsigned long MapViewMap::GetCurrentColor(void); +EQLIB_OBJECT unsigned long MapViewMap::GetMarkedLineColor(void); +EQLIB_OBJECT void MapViewMap::AddLabel(float,float,float,unsigned long,int,char *); +EQLIB_OBJECT void MapViewMap::AddPoint(float,float,float); +EQLIB_OBJECT void MapViewMap::CalcLabelRenderOffsets(class CXRect); +EQLIB_OBJECT void MapViewMap::Clear(void); +EQLIB_OBJECT void MapViewMap::ClearActiveLayer(void); +EQLIB_OBJECT void MapViewMap::Draw(class CXRect); +EQLIB_OBJECT void MapViewMap::EndLine(float,float,float); +EQLIB_OBJECT void MapViewMap::JoinLinesAtIntersect(bool); +EQLIB_OBJECT void MapViewMap::Load(char *); +EQLIB_OBJECT void MapViewMap::MoveLabel(struct _mapviewlabel *,float,float,float); +EQLIB_OBJECT void MapViewMap::PreCalcRenderValues(void); +EQLIB_OBJECT void MapViewMap::RecalcLabelExtents(struct _mapviewlabel *); +EQLIB_OBJECT void MapViewMap::RemoveLabel(struct _mapviewlabel *); +EQLIB_OBJECT void MapViewMap::RemoveLabel(void); +EQLIB_OBJECT void MapViewMap::RemoveLine(struct _mapviewline *); +EQLIB_OBJECT void MapViewMap::RemoveLine(void); +EQLIB_OBJECT void MapViewMap::Save(char *); +EQLIB_OBJECT void MapViewMap::SaveEx(char *,int); +EQLIB_OBJECT void MapViewMap::SetCurrentColor(unsigned long); +EQLIB_OBJECT void MapViewMap::SetMarkedLine(struct _mapviewline *); +EQLIB_OBJECT void MapViewMap::SetMarkedLineColor(unsigned long); +EQLIB_OBJECT void MapViewMap::SetZoneExtents(int,int,int,int); +EQLIB_OBJECT void MapViewMap::SetZoom(float); +EQLIB_OBJECT void MapViewMap::StartLine(float,float,float); +EQLIB_OBJECT void MapViewMap::TransformPoint(struct T3D_XYZ *); +}; + +class MemoryPoolManager +{ +public: +EQLIB_OBJECT MemoryPoolManager::~MemoryPoolManager(void); +EQLIB_OBJECT MemoryPoolManager::MemoryPoolManager(void); +EQLIB_OBJECT void * MemoryPoolManager::Alloc(int); +EQLIB_OBJECT void MemoryPoolManager::Free(void *); +}; + +class MidiInstance +{ +public: +EQLIB_OBJECT MidiInstance::MidiInstance(class SoundManager *); +// virtual +EQLIB_OBJECT bool MidiInstance::GiveTime(void); +EQLIB_OBJECT enum InstanceType MidiInstance::GetType(void); +EQLIB_OBJECT void MidiInstance::AdjustVolume(float,int); +EQLIB_OBJECT void MidiInstance::GuaranteeStopped(void); +EQLIB_OBJECT void MidiInstance::Move(float,float,float); +EQLIB_OBJECT void MidiInstance::Play(class SoundControl *); +// protected +EQLIB_OBJECT virtual MidiInstance::~MidiInstance(void); +//EQLIB_OBJECT virtual void * MidiInstance::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT virtual void * MidiInstance::`vector deleting destructor'(unsigned int); +}; + +class monty +{ +public: +EQLIB_OBJECT monty::~monty(void); +EQLIB_OBJECT monty::monty(class vlong const &); +EQLIB_OBJECT class vlong monty::exp(class vlong const &,class vlong const &); +// private +EQLIB_OBJECT void monty::mul(class vlong &,class vlong const &); +}; + +class Mp3Manager +{ +public: +EQLIB_OBJECT Mp3Manager::~Mp3Manager(void); +//EQLIB_OBJECT Mp3Manager::Entry::~Entry(void); +//EQLIB_OBJECT Mp3Manager::Entry::Entry(char *,char *,int,int); +EQLIB_OBJECT Mp3Manager::Mp3Manager(class SoundManager *,class MusicManager *); +EQLIB_OBJECT char * Mp3Manager::GetName(int); +//EQLIB_OBJECT enum Mp3Manager::SortOrder Mp3Manager::GetSort(void); +//EQLIB_OBJECT enum StreamingStatus Mp3Manager::Status(void); +EQLIB_OBJECT float Mp3Manager::GetVolumeLevel(void); +EQLIB_OBJECT int Mp3Manager::Add(char *); +EQLIB_OBJECT int Mp3Manager::Count(void); +EQLIB_OBJECT int Mp3Manager::GetPosition(void); +EQLIB_OBJECT int Mp3Manager::GetSongLength(void); +EQLIB_OBJECT int Mp3Manager::GetSongPosition(void); +EQLIB_OBJECT void Mp3Manager::Back(void); +EQLIB_OBJECT void Mp3Manager::Delete(int); +EQLIB_OBJECT void Mp3Manager::DeleteAll(void); +EQLIB_OBJECT void Mp3Manager::GiveTime(void); +EQLIB_OBJECT void Mp3Manager::Next(void); +EQLIB_OBJECT void Mp3Manager::Pause(void); +EQLIB_OBJECT void Mp3Manager::Play(void); +EQLIB_OBJECT void Mp3Manager::SaveList(char *); +EQLIB_OBJECT void Mp3Manager::SetPosition(int); +EQLIB_OBJECT void Mp3Manager::SetSongPosition(int); +EQLIB_OBJECT void Mp3Manager::SetVolumeLevel(float); +//EQLIB_OBJECT void Mp3Manager::Sort(enum Mp3Manager::SortOrder); +EQLIB_OBJECT void Mp3Manager::Stop(void); +// private +EQLIB_OBJECT int Mp3Manager::InternalAdd(char *,char *,int); +}; + +class MusicManager +{ +public: +EQLIB_OBJECT MusicManager::~MusicManager(void); +//EQLIB_OBJECT MusicManager::MusicEntry::~MusicEntry(void); +//EQLIB_OBJECT MusicManager::MusicEntry::MusicEntry(int,class SoundAsset *,int,float,int,int,int,int,int,int); +EQLIB_OBJECT MusicManager::MusicManager(void); +EQLIB_OBJECT void MusicManager::Clear(class SoundAsset *); +EQLIB_OBJECT void MusicManager::Clear(int); +EQLIB_OBJECT void MusicManager::Enable(bool); +EQLIB_OBJECT void MusicManager::GiveTime(void); +//EQLIB_OBJECT void MusicManager::MusicEntry::AdjustVolume(float); +//EQLIB_OBJECT void MusicManager::MusicEntry::FadeIn(float); +//EQLIB_OBJECT void MusicManager::MusicEntry::FadeOut(bool); +EQLIB_OBJECT void MusicManager::Play(int); +EQLIB_OBJECT void MusicManager::Set(int,class SoundAsset *,int,float,int,int,int,int,int,int); +EQLIB_OBJECT void MusicManager::SetVolumeLevel(float); +EQLIB_OBJECT void MusicManager::Stop(int); +}; + +class PacketPacker +{ +public: +EQLIB_OBJECT void PacketPacker::Disassociate(void); +EQLIB_OBJECT void PacketPacker::Flush(void); +EQLIB_OBJECT void PacketPacker::SendPacket(unsigned __int32,void *,int,bool); +EQLIB_OBJECT void PacketPacker::SendStatUpdate(struct _statUpdate *,bool); +// private +//EQLIB_OBJECT void PacketPacker::AddPacketToBuffer(struct PacketPacker::PacketBuffer *,unsigned __int32,void *,int); +//EQLIB_OBJECT void PacketPacker::FlushBuffer(struct PacketPacker::PacketBuffer *); +EQLIB_OBJECT void PacketPacker::FlushPositions(void); +EQLIB_OBJECT void PacketPacker::ScheduleUs(void); +}; + +class PacketPackerManager +{ +public: +EQLIB_OBJECT static bool __cdecl PacketPackerManager::UnpackGetFirst(struct PacketPackerState *,unsigned __int32,unsigned char *,int); +EQLIB_OBJECT static bool __cdecl PacketPackerManager::UnpackGetNext(struct PacketPackerState *); +EQLIB_OBJECT static void __cdecl PacketPackerManager::Initialize(void); +EQLIB_OBJECT void PacketPackerManager::RemovePacker(class PacketPacker *); +EQLIB_OBJECT void PacketPackerManager::SetPriority(class PacketPacker *,__int64); +// private +EQLIB_OBJECT static int * PacketPackerManager::sKnownSize; +}; + +class PackFile +{ +public: +EQLIB_OBJECT PackFile::~PackFile(void); +EQLIB_OBJECT int PackFile::length(void)const; +EQLIB_OBJECT int PackFile::read(void * const,int); +EQLIB_OBJECT void PackFile::close(void); +}; + +class PackFS +{ +public: +EQLIB_OBJECT PackFS::PackFS(void); +EQLIB_OBJECT bool PackFS::addFileSystem(class FilePath); +EQLIB_OBJECT bool PackFS::openFile(class FilePath,class PackFile *)const; +EQLIB_OBJECT void PackFS::removeFileSystem(class FilePath); +}; + +class PooledLogicalPacket +{ +public: +EQLIB_OBJECT PooledLogicalPacket::PooledLogicalPacket(class UdpManager *,int); +// virtual +EQLIB_OBJECT int PooledLogicalPacket::GetDataLen(void)const; +EQLIB_OBJECT void * PooledLogicalPacket::GetDataPtr(void); +EQLIB_OBJECT void PooledLogicalPacket::AddRef(void)const; +EQLIB_OBJECT void PooledLogicalPacket::Release(void)const; +EQLIB_OBJECT void PooledLogicalPacket::SetDataLen(int); +EQLIB_OBJECT void const * PooledLogicalPacket::GetDataPtr(void)const; +// protected +EQLIB_OBJECT virtual PooledLogicalPacket::~PooledLogicalPacket(void); +//EQLIB_OBJECT virtual void * PooledLogicalPacket::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT virtual void * PooledLogicalPacket::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void PooledLogicalPacket::SetData(void const *,int,void const *,int); +}; + +class public_key +{ +public: +EQLIB_OBJECT public_key::~public_key(void); +EQLIB_OBJECT public_key::public_key(void); +EQLIB_OBJECT class vlong public_key::encrypt(class vlong &); +}; + +class SAmpersandEntry +{ +public: +EQLIB_OBJECT SAmpersandEntry::~SAmpersandEntry(void); +EQLIB_OBJECT SAmpersandEntry::SAmpersandEntry(class CXStr,char); +}; + +class SFormattedText +{ +public: +EQLIB_OBJECT SFormattedText::~SFormattedText(void); +EQLIB_OBJECT SFormattedText::SFormattedText(void); +//EQLIB_OBJECT void * SFormattedText::`vector deleting destructor'(unsigned int); +}; + +class ShareBase +{ +public: +EQLIB_OBJECT void ShareBase::removeRef(void); +// virtual +EQLIB_OBJECT ShareBase::~ShareBase(void); +}; + +class SharedString +{ +public: +EQLIB_OBJECT SharedString::~SharedString(void); +EQLIB_OBJECT SharedString::SharedString(char const *); +EQLIB_OBJECT class SharedString & SharedString::operator=(class SharedString const &); +// protected +EQLIB_OBJECT void SharedString::_updateTag(void)const; +}; + +class SHistoryElement +{ +public: +EQLIB_OBJECT SHistoryElement::~SHistoryElement(void); +EQLIB_OBJECT SHistoryElement::SHistoryElement(void); +//EQLIB_OBJECT void * SHistoryElement::`vector deleting destructor'(unsigned int); +}; + +class SimpleLogicalPacket +{ +public: +EQLIB_OBJECT SimpleLogicalPacket::SimpleLogicalPacket(void const *,int); +// virtual +EQLIB_OBJECT int SimpleLogicalPacket::GetDataLen(void)const; +EQLIB_OBJECT void * SimpleLogicalPacket::GetDataPtr(void); +EQLIB_OBJECT void SimpleLogicalPacket::SetDataLen(int); +EQLIB_OBJECT void const * SimpleLogicalPacket::GetDataPtr(void)const; +// protected +EQLIB_OBJECT virtual SimpleLogicalPacket::~SimpleLogicalPacket(void); +//EQLIB_OBJECT virtual void * SimpleLogicalPacket::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT virtual void * SimpleLogicalPacket::`vector deleting destructor'(unsigned int); +}; + +class SLinkInfo +{ +public: +EQLIB_OBJECT SLinkInfo::~SLinkInfo(void); +EQLIB_OBJECT SLinkInfo::SLinkInfo(class SLinkInfo const &); +EQLIB_OBJECT SLinkInfo::SLinkInfo(void); +EQLIB_OBJECT class SLinkInfo & SLinkInfo::operator=(class SLinkInfo const &); +}; + +class SListWndCell +{ +public: +EQLIB_OBJECT SListWndCell::~SListWndCell(void); +EQLIB_OBJECT SListWndCell::SListWndCell(void); +EQLIB_OBJECT class SListWndCell & SListWndCell::operator=(class SListWndCell const &); +//EQLIB_OBJECT void * SListWndCell::`vector deleting destructor'(unsigned int); +}; + +class SListWndCellEditUpdate +{ +public: +EQLIB_OBJECT SListWndCellEditUpdate::~SListWndCellEditUpdate(void); +}; + +class SListWndColumn +{ +public: +EQLIB_OBJECT SListWndColumn::~SListWndColumn(void); +EQLIB_OBJECT SListWndColumn::SListWndColumn(class CXStr,int,class CTextureAnimation *,unsigned __int32,unsigned __int32,class CTextureAnimation *,class CTextureAnimation *); +//EQLIB_OBJECT void SListWndColumn::`default constructor closure'(void); +}; + +class SListWndLine +{ +public: +EQLIB_OBJECT SListWndLine::~SListWndLine(void); +EQLIB_OBJECT SListWndLine::SListWndLine(void); +EQLIB_OBJECT class SListWndLine & SListWndLine::operator=(class SListWndLine const &); +}; + +class SListWndSortInfo +{ +public: +EQLIB_OBJECT SListWndSortInfo::~SListWndSortInfo(void); +}; + +class SoundAsset +{ +public: +EQLIB_OBJECT SoundAsset::SoundAsset(class SoundManager *,char *,char *,int); +EQLIB_OBJECT bool SoundAsset::IsPlaying(void); +EQLIB_OBJECT char * SoundAsset::GetName(void); +EQLIB_OBJECT class SoundInstance * SoundAsset::Play(class SoundControl *); +//EQLIB_OBJECT enum AssetType SoundAsset::GetType(void); +EQLIB_OBJECT void SoundAsset::AdjustVolume(float,int); +EQLIB_OBJECT void SoundAsset::GiveTime(void); +EQLIB_OBJECT void SoundAsset::Stop(void); +// protected +EQLIB_OBJECT virtual SoundAsset::~SoundAsset(void); +//EQLIB_OBJECT virtual void * SoundAsset::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT virtual void * SoundAsset::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void SoundAsset::YourManagerDeleted(void); +}; + +class SoundControl +{ +public: +EQLIB_OBJECT SoundControl::SoundControl(void); +}; + +class SoundEmitter +{ +public: +EQLIB_OBJECT SoundEmitter::SoundEmitter(class EmitterManager *,class MusicManager *,int); +EQLIB_OBJECT SoundEmitter::SoundEmitter(class EmitterManager *,class SoundAsset *,int); +EQLIB_OBJECT void SoundEmitter::Enable(bool); +EQLIB_OBJECT void SoundEmitter::GiveTime(void); +EQLIB_OBJECT void SoundEmitter::Move(float,float,float); +EQLIB_OBJECT void SoundEmitter::SetAsset(class SoundAsset *); +// protected +EQLIB_OBJECT virtual SoundEmitter::~SoundEmitter(void); +//EQLIB_OBJECT virtual void * SoundEmitter::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT virtual void * SoundEmitter::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void SoundEmitter::Init(void); +EQLIB_OBJECT void SoundEmitter::ReleaseLoopingSound(void); +EQLIB_OBJECT void SoundEmitter::ResetTimer(void); +}; + +class SoundInstance +{ +public: +EQLIB_OBJECT SoundInstance::SoundInstance(class SoundManager *); +// virtual +EQLIB_OBJECT void SoundInstance::SetPoolNumber(int); +EQLIB_OBJECT void SoundInstance::SetSoundAsset(class SoundAsset *); +// protected +EQLIB_OBJECT virtual SoundInstance::~SoundInstance(void); +//EQLIB_OBJECT virtual void * SoundInstance::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT virtual void * SoundInstance::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void SoundInstance::YourManagerDeleted(void); +}; + +class SoundManager +{ +public: +EQLIB_OBJECT SoundManager::~SoundManager(void); +//EQLIB_OBJECT SoundManager::SoundManager(int,int,bool,int,int,bool,enum SpeakerType); +EQLIB_OBJECT class SoundAsset * SoundManager::AssetGet(char *); +//EQLIB_OBJECT class SoundInstance * SoundManager::BorrowInstance(enum InstanceType,int); +//EQLIB_OBJECT enum EnvironmentType SoundManager::GetListenerEnvironment(void); +//EQLIB_OBJECT enum StreamingStatus SoundManager::StreamingStatus(void); +EQLIB_OBJECT float SoundManager::StreamingGetVolumeLevel(void); +EQLIB_OBJECT int SoundManager::StreamingGetSongLength(void); +EQLIB_OBJECT int SoundManager::StreamingGetSongPosition(void); +//EQLIB_OBJECT void SoundManager::AddPool(enum InstanceType,int,int); +EQLIB_OBJECT void SoundManager::GetListenerLocation(float *,float *,float *,float *); +EQLIB_OBJECT void SoundManager::GiveTime(void); +EQLIB_OBJECT void SoundManager::ReturnInstance(class SoundInstance *); +//EQLIB_OBJECT void SoundManager::SetListenerEnvironment(enum EnvironmentType); +EQLIB_OBJECT void SoundManager::SetListenerLocation(float,float,float,float); +EQLIB_OBJECT void SoundManager::SetMixAhead(int); +EQLIB_OBJECT void SoundManager::StreamingPause(void); +EQLIB_OBJECT void SoundManager::StreamingPlay(char *); +EQLIB_OBJECT void SoundManager::StreamingSetSongPosition(int); +EQLIB_OBJECT void SoundManager::StreamingSetVolumeLevel(float); +EQLIB_OBJECT void SoundManager::StreamingStop(void); +// protected +EQLIB_OBJECT void SoundManager::AssetAdd(class SoundAsset *); +EQLIB_OBJECT void SoundManager::AssetGiveTime(void); +EQLIB_OBJECT void SoundManager::AssetRemove(class SoundAsset *); +}; + +class SoundObject +{ +public: +EQLIB_OBJECT SoundObject::SoundObject(void); +EQLIB_OBJECT void SoundObject::AddRef(void); +EQLIB_OBJECT void SoundObject::Release(void); +// protected +EQLIB_OBJECT virtual SoundObject::~SoundObject(void); +//EQLIB_OBJECT virtual void * SoundObject::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT virtual void * SoundObject::`vector deleting destructor'(unsigned int); +}; + +class SParseVariables +{ +public: +EQLIB_OBJECT SParseVariables::~SParseVariables(void); +}; + +class SpellManager +{ +public: +EQLIB_OBJECT SpellManager::~SpellManager(void); +EQLIB_OBJECT SpellManager::SpellManager(char *); +SPELLMGR Data; +}; + +class STable +{ +public: +EQLIB_OBJECT STable::~STable(void); +EQLIB_OBJECT STable::STable(void); +EQLIB_OBJECT class STable & STable::operator=(class STable const &); +//EQLIB_OBJECT void * STable::`vector deleting destructor'(unsigned int); +}; + +class STableCell +{ +public: +EQLIB_OBJECT STableCell::~STableCell(void); +EQLIB_OBJECT STableCell::STableCell(void); +}; + +class STempTable +{ +public: +EQLIB_OBJECT STempTable::~STempTable(void); +}; + +class STempTableCell +{ +public: +EQLIB_OBJECT STempTableCell::~STempTableCell(void); +EQLIB_OBJECT STempTableCell::STempTableCell(void); +}; + +class STempTableRow +{ +public: +EQLIB_OBJECT STempTableRow::~STempTableRow(void); +EQLIB_OBJECT STempTableRow::STempTableRow(void); +}; + +class STextLine +{ +public: +EQLIB_OBJECT STextLine::~STextLine(void); +EQLIB_OBJECT STextLine::STextLine(void); +EQLIB_OBJECT class STextLine & STextLine::operator=(class STextLine const &); +//EQLIB_OBJECT void * STextLine::`vector deleting destructor'(unsigned int); +}; + +class STextureAnimationFrame +{ +public: +EQLIB_OBJECT STextureAnimationFrame::~STextureAnimationFrame(void); +EQLIB_OBJECT STextureAnimationFrame::STextureAnimationFrame(class CUITexturePiece,unsigned __int32,class CXPoint); +EQLIB_OBJECT STextureAnimationFrame::STextureAnimationFrame(void); +EQLIB_OBJECT class STextureAnimationFrame & STextureAnimationFrame::operator=(class STextureAnimationFrame const &); +//EQLIB_OBJECT void * STextureAnimationFrame::`vector deleting destructor'(unsigned int); +}; + +class StringItem +{ +public: +EQLIB_OBJECT StringItem::~StringItem(void); +EQLIB_OBJECT StringItem::StringItem(void); +EQLIB_OBJECT int StringItem::load(struct _iobuf *,int); +}; + +class StringTable +{ +public: +EQLIB_OBJECT StringTable::~StringTable(void); +EQLIB_OBJECT StringTable::StringTable(void); +EQLIB_OBJECT char * StringTable::getString(unsigned long,bool *); +EQLIB_OBJECT int StringTable::load(char const *,int); +EQLIB_OBJECT void StringTable::addItem(class StringItem *); +// private +EQLIB_OBJECT class StringItem * StringTable::findItem(unsigned long,int,int); +EQLIB_OBJECT void StringTable::checkAlloc(void); +}; + +class TextFileReader +{ +public: +EQLIB_OBJECT TextFileReader::~TextFileReader(void); +EQLIB_OBJECT TextFileReader::TextFileReader(char *,char); +EQLIB_OBJECT bool TextFileReader::IsOpen(void); +EQLIB_OBJECT int TextFileReader::GetNextField(char *,int); +EQLIB_OBJECT int TextFileReader::ReadLine(void); +EQLIB_OBJECT void TextFileReader::GetLine(char *,int); +}; + +class type_info +{ +public: +// virtual +EQLIB_OBJECT type_info::~type_info(void); +//EQLIB_OBJECT void * type_info::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT void * type_info::`vector deleting destructor'(unsigned int); +}; + +class UdpConnection +{ +public: +//EQLIB_OBJECT bool UdpConnection::Send(enum UdpChannel,void const *,int); +EQLIB_OBJECT int UdpConnection::ConnectionAge(void)const; +EQLIB_OBJECT int UdpConnection::LastReceive(void)const; +EQLIB_OBJECT int UdpConnection::TotalPendingBytes(void)const; +EQLIB_OBJECT void UdpConnection::FlushMultiBuffer(void); +//EQLIB_OBJECT void UdpConnection::GetChannelStatus(enum UdpChannel,struct UdpConnection::ChannelStatus *)const; +EQLIB_OBJECT void UdpConnection::PingStatReset(void); +EQLIB_OBJECT void UdpConnection::Release(void); +EQLIB_OBJECT void UdpConnection::SetSilentDisconnect(bool); +// protected +EQLIB_OBJECT UdpConnection::UdpConnection(class UdpManager *,class UdpIpAddress,int,int); +//EQLIB_OBJECT UdpConnection::UdpConnection(class UdpManager *,class UdpManager::PacketHistoryEntry const *); +EQLIB_OBJECT void UdpConnection::GiveTime(void); +EQLIB_OBJECT void UdpConnection::PortUnreachable(void); +//EQLIB_OBJECT void UdpConnection::ProcessRawPacket(class UdpManager::PacketHistoryEntry const *); +// private +EQLIB_OBJECT UdpConnection::~UdpConnection(void); +//EQLIB_OBJECT bool UdpConnection::InternalSend(enum UdpChannel,unsigned char const *,int,unsigned char const *,int); +EQLIB_OBJECT bool UdpConnection::IsNonEncryptPacket(unsigned char const *)const; +EQLIB_OBJECT int UdpConnection::DecryptNone(unsigned char *,unsigned char const *,int); +EQLIB_OBJECT int UdpConnection::DecryptUserSupplied(unsigned char *,unsigned char const *,int); +EQLIB_OBJECT int UdpConnection::DecryptUserSupplied2(unsigned char *,unsigned char const *,int); +EQLIB_OBJECT int UdpConnection::DecryptXor(unsigned char *,unsigned char const *,int); +EQLIB_OBJECT int UdpConnection::DecryptXorBuffer(unsigned char *,unsigned char const *,int); +EQLIB_OBJECT int UdpConnection::EncryptNone(unsigned char *,unsigned char const *,int); +EQLIB_OBJECT int UdpConnection::EncryptUserSupplied(unsigned char *,unsigned char const *,int); +EQLIB_OBJECT int UdpConnection::EncryptUserSupplied2(unsigned char *,unsigned char const *,int); +EQLIB_OBJECT int UdpConnection::EncryptXor(unsigned char *,unsigned char const *,int); +EQLIB_OBJECT int UdpConnection::EncryptXorBuffer(unsigned char *,unsigned char const *,int); +EQLIB_OBJECT int UdpConnection::ExpireReceiveBin(void); +EQLIB_OBJECT int UdpConnection::ExpireSendBin(void); +EQLIB_OBJECT unsigned char * UdpConnection::BufferedSend(unsigned char const *,int,unsigned char const *,int,bool); +//EQLIB_OBJECT void UdpConnection::CallbackCorruptPacket(unsigned char const *,int,enum UdpCorruptionReason); +EQLIB_OBJECT void UdpConnection::CallbackRoutePacket(unsigned char const *,int); +EQLIB_OBJECT void UdpConnection::Init(class UdpManager *,class UdpIpAddress,int); +//EQLIB_OBJECT void UdpConnection::InternalDisconnect(int,enum UdpConnection::DisconnectReason); +EQLIB_OBJECT void UdpConnection::InternalGiveTime(void); +EQLIB_OBJECT void UdpConnection::PhysicalSend(unsigned char const *,int,bool); +EQLIB_OBJECT void UdpConnection::ProcessCookedPacket(unsigned char const *,int); +EQLIB_OBJECT void UdpConnection::RawSend(unsigned char const *,int); +EQLIB_OBJECT void UdpConnection::ScheduleTimeNow(void); +//EQLIB_OBJECT void UdpConnection::SendTerminatePacket(int,enum UdpConnection::DisconnectReason); +EQLIB_OBJECT void UdpConnection::SetupEncryptModel(void); +}; + +class UdpConnectionHandler +{ +public: +// virtual +EQLIB_OBJECT void UdpConnectionHandler::OnConnectComplete(class UdpConnection *); +EQLIB_OBJECT void UdpConnectionHandler::OnCrcReject(class UdpConnection *,unsigned char const *,int); +//EQLIB_OBJECT void UdpConnectionHandler::OnPacketCorrupt(class UdpConnection *,unsigned char const *,int,enum UdpCorruptionReason); +EQLIB_OBJECT void UdpConnectionHandler::OnTerminated(class UdpConnection *); +}; + +class UdpIpAddress +{ +public: +EQLIB_OBJECT UdpIpAddress::UdpIpAddress(unsigned int); +}; + +class UdpManager +{ +public: +//EQLIB_OBJECT UdpManager::PacketHistoryEntry::~PacketHistoryEntry(void); +//EQLIB_OBJECT UdpManager::PacketHistoryEntry::PacketHistoryEntry(int); +//EQLIB_OBJECT UdpManager::Params::Params(void); +//EQLIB_OBJECT UdpManager::SimulateQueueEntry::~SimulateQueueEntry(void); +//EQLIB_OBJECT UdpManager::SimulateQueueEntry::SimulateQueueEntry(unsigned char const *,int,class UdpIpAddress,int); +//EQLIB_OBJECT UdpManager::UdpManager(struct UdpManager::Params const *); +EQLIB_OBJECT bool UdpManager::GiveTime(int,bool); +EQLIB_OBJECT class LogicalPacket * UdpManager::CreatePacket(void const *,int,void const *,int); +EQLIB_OBJECT class UdpConnection * UdpManager::EstablishConnection(char const *,int,int); +EQLIB_OBJECT void UdpManager::Release(void); +EQLIB_OBJECT void UdpManager::ResetStats(void); +// protected +EQLIB_OBJECT class UdpConnection * UdpManager::AddressGetConnection(class UdpIpAddress,int)const; +EQLIB_OBJECT class UdpConnection * UdpManager::ConnectCodeGetConnection(int)const; +//EQLIB_OBJECT class UdpManager::PacketHistoryEntry * UdpManager::ActualReceive(void); +EQLIB_OBJECT class WrappedLogicalPacket * UdpManager::WrappedBorrow(class LogicalPacket const *); +EQLIB_OBJECT void UdpManager::ActualSend(unsigned char const *,int,class UdpIpAddress,int); +EQLIB_OBJECT void UdpManager::ActualSendHelper(unsigned char const *,int,class UdpIpAddress,int); +EQLIB_OBJECT void UdpManager::AddConnection(class UdpConnection *); +EQLIB_OBJECT void UdpManager::CloseSocket(void); +EQLIB_OBJECT void UdpManager::CreateAndBindSocket(int); +EQLIB_OBJECT void UdpManager::KeepUntilDisconnected(class UdpConnection *); +EQLIB_OBJECT void UdpManager::PoolCreated(class PooledLogicalPacket *); +EQLIB_OBJECT void UdpManager::PoolDestroyed(class PooledLogicalPacket *); +EQLIB_OBJECT void UdpManager::PoolReturn(class PooledLogicalPacket *); +EQLIB_OBJECT void UdpManager::ProcessDisconnectPending(void); +EQLIB_OBJECT void UdpManager::ProcessIcmpErrors(void); +//EQLIB_OBJECT void UdpManager::ProcessRawPacket(class UdpManager::PacketHistoryEntry const *); +EQLIB_OBJECT void UdpManager::RemoveConnection(class UdpConnection *); +EQLIB_OBJECT void UdpManager::SendPortAlive(class UdpIpAddress,int); +EQLIB_OBJECT void UdpManager::WrappedCreated(class WrappedLogicalPacket *); +EQLIB_OBJECT void UdpManager::WrappedDestroyed(class WrappedLogicalPacket *); +EQLIB_OBJECT void UdpManager::WrappedReturn(class WrappedLogicalPacket *); +// private +EQLIB_OBJECT UdpManager::~UdpManager(void); +}; + +class UdpMisc +{ +public: +EQLIB_OBJECT static __int64 __cdecl UdpMisc::Clock(void); +EQLIB_OBJECT static __int64 __cdecl UdpMisc::GetValue64(void const *); +EQLIB_OBJECT static class LogicalPacket * __cdecl UdpMisc::CreateQuickLogicalPacket(void const *,int,void const *,int); +EQLIB_OBJECT static int __cdecl UdpMisc::Crc32(void const *,int,int); +EQLIB_OBJECT static int __cdecl UdpMisc::PutValue24(void *,unsigned int); +EQLIB_OBJECT static int __cdecl UdpMisc::PutValue32(void *,unsigned int); +EQLIB_OBJECT static int __cdecl UdpMisc::PutValue64(void *,__int64); +EQLIB_OBJECT static int __cdecl UdpMisc::Random(int *); +EQLIB_OBJECT static int __cdecl UdpMisc::SyncStampShortDeltaTime(unsigned short,unsigned short); +EQLIB_OBJECT static unsigned int __cdecl UdpMisc::GetValue24(void const *); +EQLIB_OBJECT static unsigned int __cdecl UdpMisc::GetValue32(void const *); +EQLIB_OBJECT static unsigned int __cdecl UdpMisc::GetVariableValue(void const *,unsigned int *); +EQLIB_OBJECT static unsigned int __cdecl UdpMisc::PutVariableValue(void *,unsigned int); +}; + +class UdpReliableChannel +{ +public: +//EQLIB_OBJECT UdpReliableChannel::IncomingQueueEntry::~IncomingQueueEntry(void); +//EQLIB_OBJECT UdpReliableChannel::IncomingQueueEntry::IncomingQueueEntry(void); +//EQLIB_OBJECT UdpReliableChannel::PhysicalPacket::~PhysicalPacket(void); +//EQLIB_OBJECT UdpReliableChannel::PhysicalPacket::PhysicalPacket(void); +//EQLIB_OBJECT void * UdpReliableChannel::IncomingQueueEntry::`vector deleting destructor'(unsigned int); +//EQLIB_OBJECT void * UdpReliableChannel::PhysicalPacket::`vector deleting destructor'(unsigned int); +// protected +EQLIB_OBJECT __int64 UdpReliableChannel::GetReliableIncomingId(int)const; +EQLIB_OBJECT UdpReliableChannel::~UdpReliableChannel(void); +//EQLIB_OBJECT UdpReliableChannel::UdpReliableChannel(int,class UdpConnection *,struct UdpManager::ReliableConfig *); +EQLIB_OBJECT bool UdpReliableChannel::PullDown(int); +EQLIB_OBJECT int UdpReliableChannel::GiveTime(void); +EQLIB_OBJECT void UdpReliableChannel::Ack(__int64); +EQLIB_OBJECT void UdpReliableChannel::AckAllPacket(unsigned char const *,int); +EQLIB_OBJECT void UdpReliableChannel::AckPacket(unsigned char const *,int); +EQLIB_OBJECT void UdpReliableChannel::FlushCoalesce(void); +//EQLIB_OBJECT void UdpReliableChannel::GetChannelStatus(struct UdpConnection::ChannelStatus *)const; +//EQLIB_OBJECT void UdpReliableChannel::ProcessPacket(enum UdpReliableChannel::ReliablePacketMode,unsigned char const *,int); +EQLIB_OBJECT void UdpReliableChannel::QueueLogicalPacket(class LogicalPacket const *); +EQLIB_OBJECT void UdpReliableChannel::ReliablePacket(unsigned char const *,int); +EQLIB_OBJECT void UdpReliableChannel::Send(unsigned char const *,int,unsigned char const *,int); +EQLIB_OBJECT void UdpReliableChannel::SendCoalesce(unsigned char const *,int,unsigned char const *,int); +}; + +class vlong +{ +public: +EQLIB_OBJECT vlong::~vlong(void); +EQLIB_OBJECT vlong::vlong(class vlong const &); +EQLIB_OBJECT vlong::vlong(unsigned __int64); +EQLIB_OBJECT class vlong & vlong::operator+=(class vlong const &); +EQLIB_OBJECT class vlong & vlong::operator-=(class vlong const &); +EQLIB_OBJECT class vlong & vlong::operator=(class vlong); +// private +EQLIB_OBJECT int vlong::cf(class vlong)const; +EQLIB_OBJECT void vlong::docopy(void); +}; + +class vlong_value +{ +public: +EQLIB_OBJECT vlong_value::~vlong_value(void); +EQLIB_OBJECT vlong_value::vlong_value(void); +EQLIB_OBJECT int vlong_value::cf(class vlong_value &)const; +EQLIB_OBJECT int vlong_value::is_zero(void)const; +EQLIB_OBJECT int vlong_value::test(unsigned int)const; +EQLIB_OBJECT unsigned int vlong_value::bits(void)const; +EQLIB_OBJECT void vlong_value::add(class vlong_value &); +EQLIB_OBJECT void vlong_value::copy(class vlong_value &); +EQLIB_OBJECT void vlong_value::divide(class vlong_value &,class vlong_value &,class vlong_value &); +EQLIB_OBJECT void vlong_value::init(unsigned int); +EQLIB_OBJECT void vlong_value::init2(unsigned int,unsigned int); +EQLIB_OBJECT void vlong_value::mul(class vlong_value &,class vlong_value &); +EQLIB_OBJECT void vlong_value::shl(void); +EQLIB_OBJECT void vlong_value::shr(unsigned int); +EQLIB_OBJECT void vlong_value::shr(void); +EQLIB_OBJECT void vlong_value::subtract(class vlong_value &); +}; + +class Wave3dInstance +{ +public: +EQLIB_OBJECT Wave3dInstance::Wave3dInstance(class SoundManager *); +// virtual +EQLIB_OBJECT bool Wave3dInstance::GiveTime(void); +EQLIB_OBJECT enum InstanceType Wave3dInstance::GetType(void); +EQLIB_OBJECT void Wave3dInstance::AdjustVolume(float,int); +EQLIB_OBJECT void Wave3dInstance::GuaranteeStopped(void); +EQLIB_OBJECT void Wave3dInstance::Move(float,float,float); +EQLIB_OBJECT void Wave3dInstance::Play(class SoundControl *); +// protected +EQLIB_OBJECT virtual Wave3dInstance::~Wave3dInstance(void); +//EQLIB_OBJECT virtual void * Wave3dInstance::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT virtual void * Wave3dInstance::`vector deleting destructor'(unsigned int); +}; + +class WaveInstance +{ +public: +EQLIB_OBJECT WaveInstance::WaveInstance(class SoundManager *); +// virtual +EQLIB_OBJECT bool WaveInstance::GiveTime(void); +//EQLIB_OBJECT enum InstanceType WaveInstance::GetType(void); +EQLIB_OBJECT void WaveInstance::AdjustVolume(float,int); +EQLIB_OBJECT void WaveInstance::GuaranteeStopped(void); +EQLIB_OBJECT void WaveInstance::Move(float,float,float); +EQLIB_OBJECT void WaveInstance::Play(class SoundControl *); +// protected +EQLIB_OBJECT virtual WaveInstance::~WaveInstance(void); +//EQLIB_OBJECT virtual void * WaveInstance::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT virtual void * WaveInstance::`vector deleting destructor'(unsigned int); +}; + +class WrappedLogicalPacket +{ +public: +EQLIB_OBJECT WrappedLogicalPacket::WrappedLogicalPacket(class UdpManager *); +// virtual +EQLIB_OBJECT int WrappedLogicalPacket::GetDataLen(void)const; +EQLIB_OBJECT void * WrappedLogicalPacket::GetDataPtr(void); +EQLIB_OBJECT void WrappedLogicalPacket::AddRef(void)const; +EQLIB_OBJECT void WrappedLogicalPacket::Release(void)const; +EQLIB_OBJECT void WrappedLogicalPacket::SetDataLen(int); +EQLIB_OBJECT void const * WrappedLogicalPacket::GetDataPtr(void)const; +// protected +EQLIB_OBJECT virtual WrappedLogicalPacket::~WrappedLogicalPacket(void); +//EQLIB_OBJECT virtual void * WrappedLogicalPacket::`scalar deleting destructor'(unsigned int); +//EQLIB_OBJECT virtual void * WrappedLogicalPacket::`vector deleting destructor'(unsigned int); +EQLIB_OBJECT void WrappedLogicalPacket::SetLogicalPacket(class LogicalPacket const *); +}; + +class ZlibUtil +{ +public: +EQLIB_OBJECT static int __cdecl ZlibUtil::Compress(char const *,int,char *,int,int); +EQLIB_OBJECT static int __cdecl ZlibUtil::Decompress(char const *,int,char *,int); +// private +EQLIB_OBJECT static class MemoryPoolManager ZlibUtil::sMemoryPoolManager; +EQLIB_OBJECT static int __cdecl ZlibUtil::zcompress(unsigned char *,unsigned long *,unsigned char const *,unsigned long,int); +EQLIB_OBJECT static int __cdecl ZlibUtil::zuncompress(unsigned char *,unsigned long *,unsigned char const *,unsigned long); +EQLIB_OBJECT static void * __cdecl ZlibUtil::zcalloc(void *,unsigned int,unsigned int); +EQLIB_OBJECT static void __cdecl ZlibUtil::zfree(void *,void *); +}; + +class ZoneNPCLoadTextManager +{ +public: +EQLIB_OBJECT ZoneNPCLoadTextManager::~ZoneNPCLoadTextManager(void); +EQLIB_OBJECT ZoneNPCLoadTextManager::ZoneNPCLoadTextManager(char *); +EQLIB_OBJECT char * ZoneNPCLoadTextManager::GetNPCCode(int); +EQLIB_OBJECT char * ZoneNPCLoadTextManager::GetS3DName(int); +EQLIB_OBJECT void ZoneNPCLoadTextManager::LoadText(char *); +}; + +class CTextOverlay +{ +public: +EQLIB_OBJECT void CTextOverlay::DisplayText(char *,int,int,int,int,int,int); +}; + +class CMyInventory +{ +public: +EQLIB_OBJECT struct _CONTENTS* CMyInventory::GetSlot(int); +}; + +class CDBStr +{ +public: +// GetString(index, subindex, &success) +EQLIB_OBJECT char *CDBStr::GetString(int, int, int*); +}; + +class CCombatAbilityWnd : public CSidlScreenWnd +{ +public: +EQLIB_OBJECT CCombatAbilityWnd::CCombatAbilityWnd(class CXWnd *); +EQLIB_OBJECT void CCombatAbilityWnd::Activate(int); +EQLIB_OBJECT void CCombatAbilityWnd::Deactivate(void); +EQLIB_OBJECT int CCombatAbilityWnd::OnProcessFrame(void); +EQLIB_OBJECT int CCombatAbilityWnd::WndNotification(class CXWnd *,unsigned __int32,void *); +EQLIB_OBJECT CCombatAbilityWnd::~CCombatAbilityWnd(void); +}; + +class EQMisc +{ +public: +EQLIB_OBJECT int EQMisc::GetActiveFavorCost(void); +}; + +class CSkillMgr +{ +public: +EQLIB_OBJECT unsigned long CSkillMgr::GetStrNumber(int); +EQLIB_OBJECT unsigned long CSkillMgr::GetSkillCap(class EQ_Character *,int,int,int,bool,bool,bool); +EQLIB_OBJECT unsigned long CSkillMgr::SkillAvailableAtLevel(int,int); +EQLIB_OBJECT bool CSkillMgr::IsActivatableSkill(int); +EQLIB_OBJECT unsigned long CSkillMgr::GetBaseDamage(int); +EQLIB_OBJECT unsigned long CSkillMgr::GetReuseTime(int); +EQLIB_OBJECT bool CSkillMgr::IsAvailable(int); +}; + +class CChatService +{ +public: +EQLIB_OBJECT int CChatService::GetNumberOfFriends(void); +EQLIB_OBJECT char * CChatService::GetFriendName(int); +}; + +class PlayerPointManager +{ +public: +EQLIB_OBJECT unsigned long PlayerPointManager::GetAltCurrency(unsigned long,unsigned long b=1); +}; + +}; + +class CharacterZoneClient +{ +public: + bool HasSkill(int); +}; + +class PcZoneClient +{ +public: + int GetPcSkillLimit(int); +}; + +using namespace EQClasses; diff --git a/client_files/native_autoloot/eq-core-dll/src/EQData.h b/client_files/native_autoloot/eq-core-dll/src/EQData.h new file mode 100644 index 0000000000..a01256a3bc --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/EQData.h @@ -0,0 +1,2209 @@ +#pragma once +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ +namespace EQData +{ + +// *************************************************************************** +// Defines +// *************************************************************************** + +enum PlayerClass +{ + Unknown= 0, + Warrior= 1, + Cleric= 2, + Paladin= 3, + Ranger= 4, + Shadowknight= 5, + Druid= 6, + Monk= 7, + Bard= 8, + Rogue= 9, + Shaman= 10, + Necromancer= 11, + Wizard= 12, + Mage= 13, + Enchanter= 14, + Beastlord= 15, + Berserker= 16, + TotalClasses= 16, +}; +// class 20 through 35 are the NPC GMs (same class order as above) +// class 41 Merchant +// class 60 LDoN Recruiter +// class 61 LDoN Merchant +// class 63 Tribute Master +// class 67 DoN Merchant (Norrath's Keepers) +// class 68 DoN Merchant (Dark Reign) + +typedef struct _ClassInfo +{ + bool CanCast; + bool PureCaster; + bool PetClass; + bool DruidType; + bool NecroType; + bool ClericType; + bool ShamanType; + char RaidColorOrder; + PCHAR Name; + PCHAR ShortName; +} CLASSINFO, *PCLASSINFO; + +static _ClassInfo ClassInfo[]= +{ + {0,0,0,0,0,0,0,0,"",""}, //unk + {0,0,0,0,0,0,0,13,"Warrior","war"}, //war + {1,1,0,0,0,1,0,2,"Cleric","clr"}, //clr + {1,0,0,0,0,1,0,8,"Paladin","pal"}, //pal + {1,0,0,1,0,0,0,9,"Ranger","rng"}, //rng + {1,0,0,0,1,0,0,11,"Shadowknight","shd"}, //shd + {1,1,0,1,0,0,0,3,"Druid","dru"}, //dru + {0,0,0,0,0,0,0,6,"Monk","mnk"}, //mnk + {1,0,0,0,0,0,0,0,"Bard","brd"}, //brd + {0,0,0,0,0,0,0,10,"Rogue","rog"}, //rog + {1,1,1,0,0,0,1,12,"Shaman","shm"}, //shm + {1,1,1,0,1,0,0,7,"Necromancer","nec"}, //nec + {1,1,0,0,0,0,0,14,"Wizard","wiz"}, //wiz + {1,1,1,0,0,0,0,5,"Mage","mag"}, //mag + {1,1,0,0,0,0,0,4,"Enchanter","enc"}, //enc + {1,0,1,0,0,0,1,1,"Beastlord","bst"}, //bst + {0,0,0,0,0,0,0,15,"Berserker","ber"}, //ber +}; + +enum GroupAbilityLevels { + G_MarkNPC= 0, //0-3 + G_NPCHealth= 1, //0-1 + G_DelegateMA= 3, //0-1 + G_DelegateMarkNPC= 4, //0-1 + G_InspectBuffs= 6, //0-2 + G_SpellAwareness= 8, //0-1 + G_OffenseEnhancement= 9, //0-5 + G_ManaEnhancement= 10, //0-3 + G_HealthEnhancement= 11, //0-3 + G_HealthRegen= 12, //0-3 + G_FindPathtoPC= 13, //0-1 + G_HealthofTargetsTarget= 14, //0-1 +}; + +enum RaidAbilityLevels { + R_MarkNPC= 0, //0-3 + R_NPCHealth= 1, //0-1 + R_DelegateMA= 3, //0-3 + R_DelegateMarkNPC= 4, //0-4 + R_SpellAwareness= 7, //0-1 + R_OffenseEnhancement= 8, //0-5 + R_ManaEnhancement= 9, //0-3 + R_HealthEnhancement= 10, //0-3 + R_HealthRegen= 11, //0-3 + R_FindPathtoPC= 12, //0-1 + R_HealthofTargetsTarget= 13, //0-1 +}; + +#define BI_TARGETABLE 1 +#define BI_TRIGGER 2 +#define BI_TRAP 4 +#define BI_TIMER 8 + +typedef struct _BodyInfo +{ + PCHAR Name; + DWORD Flags; +} BODYINFO, *PBODYINFO; + +#define SPAWN_PLAYER 0 +#define SPAWN_NPC 1 +#define SPAWN_CORPSE 2 +//#define SPAWN_ANY 3 +//#define SPAWN_PET 4 + +#define ITEM_NORMAL1 0x0031 +#define ITEM_NORMAL2 0x0036 +#define ITEM_NORMAL3 0x315f +#define ITEM_NORMAL4 0x3336 +#define ITEM_NORMAL5 0x0032 +#define ITEM_NORMAL6 0x0033 +#define ITEM_NORMAL7 0x0034 +#define ITEM_NORMAL8 0x0039 +#define ITEM_CONTAINER 0x7900 +#define ITEM_CONTAINER_PLAIN 0x7953 +#define ITEM_BOOK 0x7379 + +#define ITEMITEMTYPE_FOOD 0x0e +#define ITEMITEMTYPE_WATER 0x0f +#define ITEMITEMTYPE_ALCOHOL 0x26 +#define ITEMITEMTYPE_POISON 0x2a +#define ITEMITEMTYPE_AUGUMENT 0x36 + +#define ITEMEFFECTTYPE_COMBAT 0x00 +#define ITEMEFFECTTYPE_INVENTORY1 0x01 // Bards need to stop sing to cast +#define ITEMEFFECTTYPE_WORN 0x02 +#define ITEMEFFECTTYPE_INVENTORY2 0x03 +#define ITEMEFFECTTYPE_MUSTEQUIP 0x04 // Bards need to stop sing to cast +#define ITEMEFFECTTYPE_INVENTORY3 0x05 + +#define SKILLMINDAMAGEMOD_BASH 0x00 +#define SKILLMINDAMAGEMOD_BACKSTAB 0x01 +#define SKILLMINDAMAGEMOD_DRAGONPUNCH 0x02 +#define SKILLMINDAMAGEMOD_EAGLESTRIKE 0x03 +#define SKILLMINDAMAGEMOD_FLYINGKICK 0x04 +#define SKILLMINDAMAGEMOD_KICK 0x05 +#define SKILLMINDAMAGEMOD_ROUNDKICK 0x06 +#define SKILLMINDAMAGEMOD_TIGERCLAW 0x07 +#define SKILLMINDAMAGEMOD_FRENZY 0x08 + +#define COLOR_DEFAULT 0x00 +#define COLOR_DARKGREY 0x01 +#define COLOR_DARKGREEN 0x02 +#define COLOR_DARKBLUE 0x03 +#define COLOR_PURPLE 0x05 +#define COLOR_LIGHTGREY 0x06 + +#define CONCOLOR_GREY 0x06 +#define CONCOLOR_GREEN 0x02 +#define CONCOLOR_LIGHTBLUE 0x12 +#define CONCOLOR_BLUE 0x04 +#define CONCOLOR_BLACK 0x14 +#define CONCOLOR_WHITE 0x0a +#define CONCOLOR_YELLOW 0x0f +#define CONCOLOR_RED 0x0d + +#define USERCOLOR_SAY 0xFF + 1 // 1 - Say +#define USERCOLOR_TELL 0xFF + 2 // 2 - Tell +#define USERCOLOR_GROUP 0xFF + 3 // 3 - Group +#define USERCOLOR_GUILD 0xFF + 4 // 4 - Guild +#define USERCOLOR_OOC 0xFF + 5 // 5 - OOC +#define USERCOLOR_AUCTION 0xFF + 6 // 6 - Auction +#define USERCOLOR_SHOUT 0xFF + 7 // 7 - Shout +#define USERCOLOR_EMOTE 0xFF + 8 // 8 - Emote +#define USERCOLOR_SPELLS 0xFF + 9 // 9 - Spells (meming, scribing, casting, etc.) +#define USERCOLOR_YOU_HIT_OTHER 0xFF + 10 // 10 - You hit other +#define USERCOLOR_OTHER_HIT_YOU 0xFF + 11 // 11 - Other hits you +#define USERCOLOR_YOU_MISS_OTHER 0xFF + 12 // 12 - You miss other +#define USERCOLOR_OTHER_MISS_YOU 0xFF + 13 // 13 - Other misses you +#define USERCOLOR_DUELS 0xFF + 14 // 14 - Some broadcasts (duels) +#define USERCOLOR_SKILLS 0xFF + 15 // 15 - Skills (ups, non-combat use, etc.) +#define USERCOLOR_DISCIPLINES 0xFF + 16 // 16 - Disciplines or special abilities +#define USERCOLOR_UNUSED001 0xFF + 17 // 17 - Unused at this time +#define USERCOLOR_DEFAULT 0xFF + 18 // 18 - Default text and stuff you type +#define USERCOLOR_UNUSED002 0xFF + 19 // 19 - Unused at this time +#define USERCOLOR_MERCHANT_OFFER 0xFF + 20 // 20 - Merchant Offer Price +#define USERCOLOR_MERCHANT_EXCHANGE 0xFF + 21 // 21 - Merchant Buy/Sell +#define USERCOLOR_YOUR_DEATH 0xFF + 22 // 22 - Your death message +#define USERCOLOR_OTHER_DEATH 0xFF + 23 // 23 - Others death message +#define USERCOLOR_OTHER_HIT_OTHER 0xFF + 24 // 24 - Other damage other +#define USERCOLOR_OTHER_MISS_OTHER 0xFF + 25 // 25 - Other miss other +#define USERCOLOR_WHO 0xFF + 26 // 26 - /who command +#define USERCOLOR_YELL 0xFF + 27 // 27 - yell for help +#define USERCOLOR_NON_MELEE 0xFF + 28 // 28 - Hit for non-melee +#define USERCOLOR_SPELL_WORN_OFF 0xFF + 29 // 29 - Spell worn off +#define USERCOLOR_MONEY_SPLIT 0xFF + 30 // 30 - Money splits +#define USERCOLOR_LOOT 0xFF + 31 // 31 - Loot message +#define USERCOLOR_RANDOM 0xFF + 32 // 32 - Dice Roll (/random) +#define USERCOLOR_OTHERS_SPELLS 0xFF + 33 // 33 - Others spells +#define USERCOLOR_SPELL_FAILURE 0xFF + 34 // 34 - Spell Failures (resists, fizzles, missing component, bad target, etc.) +#define USERCOLOR_CHAT_CHANNEL 0xFF + 35 // 35 - Chat Channel Messages +#define USERCOLOR_CHAT_1 0xFF + 36 // 36 - Chat Channel 1 +#define USERCOLOR_CHAT_2 0xFF + 37 // 37 - Chat Channel 2 +#define USERCOLOR_CHAT_3 0xFF + 38 // 38 - Chat Channel 3 +#define USERCOLOR_CHAT_4 0xFF + 39 // 39 - Chat Channel 4 +#define USERCOLOR_CHAT_5 0xFF + 40 // 40 - Chat Channel 5 +#define USERCOLOR_CHAT_6 0xFF + 41 // 41 - Chat Channel 6 +#define USERCOLOR_CHAT_7 0xFF + 42 // 42 - Chat Channel 7 +#define USERCOLOR_CHAT_8 0xFF + 43 // 43 - Chat Channel 8 +#define USERCOLOR_CHAT_9 0xFF + 44 // 44 - Chat Channel 9 +#define USERCOLOR_CHAT_10 0xFF + 45 // 45 - Chat Channel 10 +#define USERCOLOR_MELEE_CRIT 0xFF + 46 // 46 - Melee Crits +#define USERCOLOR_SPELL_CRIT 0xFF + 47 // 47 - Spell Crits +#define USERCOLOR_TOO_FAR_AWAY 0xFF + 48 // 48 - Too far away (melee) +#define USERCOLOR_NPC_RAMPAGE 0xFF + 49 // 49 - NPC Rampage +#define USERCOLOR_NPC_FLURRY 0xFF + 50 // 50 - NPC Furry +#define USERCOLOR_NPC_ENRAGE 0xFF + 51 // 51 - NPC Enrage +#define USERCOLOR_ECHO_SAY 0xFF + 52 // 52 - say echo +#define USERCOLOR_ECHO_TELL 0xFF + 53 // 53 - tell echo +#define USERCOLOR_ECHO_GROUP 0xFF + 54 // 54 - group echo +#define USERCOLOR_ECHO_GUILD 0xFF + 55 // 55 - guild echo +#define USERCOLOR_ECHO_OOC 0xFF + 56 // 56 - group echo +#define USERCOLOR_ECHO_AUCTION 0xFF + 57 // 57 - auction echo +#define USERCOLOR_ECHO_SHOUT 0xFF + 58 // 58 - shout echo +#define USERCOLOR_ECHO_EMOTE 0xFF + 59 // 59 - emote echo +#define USERCOLOR_ECHO_CHAT_1 0xFF + 60 // 60 - chat 1 echo +#define USERCOLOR_ECHO_CHAT_2 0xFF + 61 // 61 - chat 2 echo +#define USERCOLOR_ECHO_CHAT_3 0xFF + 62 // 62 - chat 3 echo +#define USERCOLOR_ECHO_CHAT_4 0xFF + 63 // 63 - chat 4 echo +#define USERCOLOR_ECHO_CHAT_5 0xFF + 64 // 64 - chat 5 echo +#define USERCOLOR_ECHO_CHAT_6 0xFF + 65 // 65 - chat 6 echo +#define USERCOLOR_ECHO_CHAT_7 0xFF + 66 // 66 - chat 7 echo +#define USERCOLOR_ECHO_CHAT_8 0xFF + 67 // 67 - chat 8 echo +#define USERCOLOR_ECHO_CHAT_9 0xFF + 68 // 68 - chat 9 echo +#define USERCOLOR_ECHO_CHAT_10 0xFF + 69 // 69 - chat 10 echo +#define USERCOLOR_RESERVED 0xFF + 70 // 70 - "unused at this time" +#define USERCOLOR_LINK 0xFF + 71 // 71 - item links +#define USERCOLOR_RAID 0xFF + 72 // 72 - raid +#define USERCOLOR_PET 0xFF + 73 // 73 - my pet +#define USERCOLOR_DAMAGESHIELD 0xFF + 74 // 74 - damage shields +#define USERCOLOR_LEADER 0xFF + 75 // 75 - LAA-related messages +#define USERCOLOR_PETRAMPFLURRY 0xFF + 76 // 76 - pet rampage/flurry +#define USERCOLOR_PETCRITS 0xFF + 77 // 77 - pet's critical hits +#define USERCOLOR_FOCUS 0xFF + 78 // 78 - focus item activation +#define USERCOLOR_XP 0xFF + 79 // 79 - xp gain/loss +#define USERCOLOR_SYSTEM 0xFF + 80 // 80 - system broadcasts etc +#define USERCOLOR_PET_SPELLS 0xFF + 81 // 81 - pet spells +#define USERCOLOR_PET_RESPONSES 0xFF + 82 // 82 - pet responses +#define USERCOLOR_ITEM_SPEECH 0xFF + 83 // 83 - item speech +#define USERCOLOR_STRIKETHROUGH 0xFF + 84 // 84 - strikethrough messages +#define USERCOLOR_STUN 0XFF + 85 // 85 - stun messages +#define USERCOLOR_RESERVED2 0xFF + 86 // 86 - "unused at this time" (or unknown!?) +#define USERCOLOR_FELLOWSHIP 0xFF + 87 // 87 - fellowship messages +#define USERCOLOR_NPC_SPEECH 0xFF + 88 // 88 - npc dialogue +#define USERCOLOR_NPC_SPEECH_TO_YOU 0xFF + 89 // 89 - npc dialogue to you +#define USERCOLOR_GUILD_MSG 0xFF + 90 // 90 - guild messages + +#define DEITY_Bertoxxulous 201 +#define DEITY_BrellSerilis 202 +#define DEITY_CazicThule 203 +#define DEITY_ErollisiMarr 204 +#define DEITY_Bristlebane 205 +#define DEITY_Innoruuk 206 +#define DEITY_Karana 207 +#define DEITY_MithanielMarr 208 +#define DEITY_Prexus 209 +#define DEITY_Quellious 210 +#define DEITY_RallosZek 211 +#define DEITY_RodcetNife 212 +#define DEITY_SolusekRo 213 +#define DEITY_TheTribunal 214 +#define DEITY_Tunare 215 +#define DEITY_Veeshan 216 + +#define ITEMTYPE_NORMAL 0 +#define ITEMTYPE_PACK 1 +#define ITEMTYPE_BOOK 2 + +#define COMP_NONE 0 +#define COMP_EQ 1 +#define COMP_NE 2 +#define COMP_GT 3 +#define COMP_LT 4 +#define COMP_GE 5 +#define COMP_LE 6 +#define COMP_CONT 7 +#define COMP_NOTCONT 8 +#define COMP_BITAND 9 +#define COMP_BITOR 10 + +#define COMP_TYPE_STRING 0 +#define COMP_TYPE_NUMERIC 1 +#define COMP_TYPE_BIT 2 + +#define CMD_MQ 1 +#define CMD_EQ 2 + +#define LASTFIND_NOTFOUND 96 +#define LASTFIND_PRIMARY 97 + +#define EVENT_CHAT 0 +#define EVENT_TIMER 1 +#define EVENT_CUSTOM 2 +#define EVENT_EVAL 3 +#define EVENT_EXEC 4 +#define EVENT_PULSE 5 +#define EVENT_SHUTDOWN 6 +#define EVENT_BREAK 7 +#define NUM_EVENTS 8 + +#define CHAT_SAY 1 +#define CHAT_TELL 2 +#define CHAT_OOC 4 +#define CHAT_SHOUT 8 +#define CHAT_AUC 16 +#define CHAT_GUILD 32 +#define CHAT_GROUP 64 +#define CHAT_CHAT 128 +#define CHATEVENT(x) (gEventChat & x) + +#define FILTERSKILL_ALL 0 +#define FILTERSKILL_INCREASE 1 +#define FILTERSKILL_NONE 2 + +#define FILTERMACRO_ALL 0 +#define FILTERMACRO_ENHANCED 1 +#define FILTERMACRO_NONE 2 +#define FILTERMACRO_MACROENDED 3 + + +#define MAX_STRING 2048 +#define MAX_VARNAME 64 + +// Defines for CXWnd WindowStyle +#define CWS_VSCROLL 0x1 +#define CWS_HSCROLL 0x2 +#define CWS_TITLE 0x4 +#define CWS_CLOSE 0x8 +#define CWS_TILEBOX 0x10 +#define CWS_MINIMIZE 0x20 +#define CWS_BORDER 0x40 +//#define CWS_UNKNOWN 0x80 +//#define CWS_UNKNOWN 0x100 +#define CWS_RESIZEALL 0x200 +#define CWS_TRANSPARENT 0x400 +//#define CWS_UNKNOWN 0x800 +#define CWS_NOMOVE 0x8000 +#define CWS_QMARK 0x10000 +#define CWS_MAXIMIZE 0x40000 +#define ToggleBit(field,bit) field^=bit; +#define BitOn(field,bit) field|=bit; +#define BitOff(field,bit) field&=~bit; +// End CXWnd WindowStyle Defines + +#define ALTCURRENCY_DOUBLOONS 0xa +#define ALTCURRENCY_ORUX 0xb +#define ALTCURRENCY_PHOSPHENES 0xc +#define ALTCURRENCY_PHOSPHITES 0xd +#define ALTCURRENCY_FAYCITES 0xe +#define ALTCURRENCY_CHRONOBINES 0xf + +enum MOUSE_DATA_TYPES { + MD_Unknown = -1, + MD_Button0Click=0, + MD_Button1Click, + MD_Button0, + MD_Button1 +}; + +#define nEQMappableCommands 0x1f4 + +#define MAX_PC_LEVEL 100 +#define MAX_NPC_LEVEL 110 +#define NUM_SPELL_GEMS 12 +#define NUM_SPELL_SETS 10 +#define NUM_BUFF_SLOTS 0x61 +#define NUM_LONG_BUFFS 42 +#define NUM_SHORT_BUFFS 20 + +#define EQ_EXPANSION(x) (1 << (x - 1)) +#define EXPANSION_RoK EQ_EXPANSION(1) +#define EXPANSION_SoV EQ_EXPANSION(2) +#define EXPANSION_SoL EQ_EXPANSION(3) +#define EXPANSION_PoP EQ_EXPANSION(4) +#define EXPANSION_LoY EQ_EXPANSION(5) +#define EXPANSION_LDoN EQ_EXPANSION(6) +#define EXPANSION_GoD EQ_EXPANSION(7) +#define EXPANSION_OoW EQ_EXPANSION(8) +#define EXPANSION_DoN EQ_EXPANSION(9) +#define EXPANSION_DoD EQ_EXPANSION(10) +#define EXPANSION_PoR EQ_EXPANSION(11) +#define EXPANSION_TSS EQ_EXPANSION(12) +#define EXPANSION_TBS EQ_EXPANSION(13) +#define EXPANSION_SoF EQ_EXPANSION(14) +#define EXPANSION_SoD EQ_EXPANSION(15) +#define EXPANSION_UFT EQ_EXPANSION(16) +#define EXPANSION_HoT EQ_EXPANSION(17) +#define EXPANSION_VoA EQ_EXPANSION(18) +#define EXPANSION_RoF EQ_EXPANSION(19) +#define NUM_EXPANSIONS 19 +// *************************************************************************** +// Structures +// *************************************************************************** + +typedef struct _MOUSESPOOF { + MOUSE_DATA_TYPES mdType; + DWORD dwData; + struct _MOUSESPOOF *pNext; +} MOUSESPOOF, *PMOUSESPOOF; + +typedef struct _MOUSECLICK { + BYTE Confirm[8]; // DO NOT WRITE TO THIS BYTE + BYTE Click[8]; // Left = 0, Right = 1, etc +} MOUSECLICK, *PMOUSECLICK; + +typedef struct _UILOCATION { + DWORD x; + DWORD y; + DWORD w; + DWORD h; + CHAR error[MAX_STRING]; +} UILOCATION, *PUILOCATION; + +//5-15-2003 eqmule +typedef struct _CXSTR { +/*0x00*/ DWORD Font; // maybe, dont know. 04 = Window 01 = button +/*0x04*/ DWORD MaxLength; +/*0x08*/ DWORD Length; +/*0x0c*/ BOOL Encoding; // 0: ASCII, 1:Unicode +/*0x10*/ PCRITICAL_SECTION pLock; +/*0x14*/ CHAR Text[1]; // Stub, can be anywhere from Length to MaxLength (which is how much is malloc'd to this CXStr) +} CXSTR, *PCXSTR; + +#define ITEM_NAME_LEN 0x40 +#define LORE_NAME_LEN 0x70 + +// size is 0x64 02-16-2007 +typedef struct _ITEMSPELLS { +/*0x00*/ DWORD SpellID; +/*0x04*/ BYTE RequiredLevel; +/*0x05*/ BYTE EffectType; +/*0x06*/ BYTE Unknown[0x2]; +/*0x08*/ DWORD Unknown0x08; +/*0x0c*/ DWORD MaxCharges; +/*0x10*/ DWORD CastTime; +/*0x14*/ DWORD TimerID; +/*0x18*/ DWORD RecastType; +/*0x1c*/ DWORD ProcRate; +/*0x20*/ BYTE Unknown0x20[0x44]; +/*0x64*/ +} ITEMSPELLS, *PITEMSPELLS; + +// actual size: 0x634 20130116 - ieatacid +typedef struct _ITEMINFO { +/*0x000*/ CHAR Name[ITEM_NAME_LEN]; +/*0x040*/ CHAR LoreName[LORE_NAME_LEN]; +/*0x0b0*/ CHAR IDFile[0x20]; +/*0x0d0*/ BYTE Unknown0xd0[0x1c]; +/*0x0ec*/ DWORD ItemNumber; +/*0x0f0*/ DWORD EquipSlots; +/*0x0f4*/ DWORD Cost; +/*0x0f8*/ DWORD IconNumber; +/*0x0fc*/ BYTE Unknown0xfc[0xc]; +/*0x108*/ DWORD Weight; +/*0x10c*/ BYTE NoRent; // 0=temp, 1=default +/*0x10d*/ BYTE NoDrop; // 0=no drop, 1=can drop +/*0x10e*/ BYTE Attuneable; +/*0x10f*/ BYTE Unknown0x10f[0xa]; +/*0x119*/ BYTE Size; +/*0x11a*/ BYTE Type; +/*0x11b*/ BYTE TradeSkills; +/*0x11c*/ DWORD Lore; +/*0x120*/ BYTE Artifact; +/*0x121*/ BYTE Summoned; +/*0x122*/ CHAR SvCold; +/*0x123*/ CHAR SvFire; +/*0x124*/ CHAR SvMagic; +/*0x125*/ CHAR SvDisease; +/*0x126*/ CHAR SvPoison; +/*0x127*/ CHAR SvCorruption; +/*0x128*/ CHAR STR; +/*0x129*/ CHAR STA; +/*0x12a*/ CHAR AGI; +/*0x12b*/ CHAR DEX; +/*0x12c*/ CHAR CHA; +/*0x12d*/ CHAR INT; +/*0x12e*/ CHAR WIS; +/*0x12f*/ BYTE Unknown0x12f; +/*0x130*/ DWORD HP; +/*0x134*/ DWORD Mana; +/*0x138*/ DWORD AC; +/*0x13c*/ DWORD RequiredLevel; +/*0x140*/ DWORD RecommendedLevel; +/*0x144*/ BYTE RecommendedSkill; +/*0x145*/ BYTE Unknown0x145[0x3]; +/*0x148*/ DWORD SkillModType; +/*0x14c*/ DWORD SkillModValue; +/*0x150*/ DWORD Unknown0x150; +/*0x154*/ DWORD Unknown0x154; +/*0x158*/ DWORD BaneDMGRace; +/*0x15c*/ DWORD BaneDMGBodyType; +/*0x160*/ BYTE BaneDMGBodyTypeValue; +/*0x161*/ BYTE BaneDMGRaceValue; +/*0x162*/ BYTE Unknown0x162[0x6]; +/*0x168*/ DWORD InstrumentType; +/*0x16c*/ DWORD InstrumentMod; +/*0x170*/ DWORD Classes; +/*0x174*/ DWORD Races; +/*0x178*/ DWORD Diety; +/*0x17c*/ BYTE Unknown0x17c[0x4]; +/*0x180*/ BYTE Magic; +/*0x181*/ BYTE Light; +/*0x182*/ BYTE Delay; +/*0x183*/ BYTE DmgBonusType; +/*0x184*/ BYTE DmgBonusVal; +/*0x185*/ BYTE Range; +/*0x186*/ BYTE Unknown0x186[0x2]; +/*0x188*/ DWORD Damage; +/*0x18c*/ DWORD BackstabDamage; +/*0x190*/ DWORD DamageShieldMitigation; +/*0x194*/ DWORD HeroicSTR; +/*0x198*/ DWORD HeroicINT; +/*0x19c*/ DWORD HeroicWIS; +/*0x1a0*/ DWORD HeroicAGI; +/*0x1a4*/ DWORD HeroicDEX; +/*0x1a8*/ DWORD HeroicSTA; +/*0x1ac*/ DWORD HeroicCHA; +/*0x1b0*/ DWORD HeroicSvMagic; +/*0x1b4*/ DWORD HeroicSvFire; +/*0x1b8*/ DWORD HeroicSvCold; +/*0x1bc*/ DWORD HeroicSvDisease; +/*0x1c0*/ DWORD HeroicSvPoison; +/*0x1c4*/ DWORD HeroicSvCorruption; +/*0x1c8*/ DWORD HealAmount; +/*0x1cc*/ DWORD SpellDamage; +/*0x1d0*/ DWORD Unknown0x1d0; +/*0x1d4*/ BYTE ItemType; +/*0x1d5*/ BYTE Unknown0x1d5[0x3]; +/*0x1d8*/ BYTE Material; +/*0x1d9*/ BYTE Unknown0x1d9[0x13]; +/*0x1ec*/ DWORD AugSlot1; +/*0x1f0*/ DWORD AugSlot1_Unknown; +/*0x1f4*/ DWORD AugSlot2; +/*0x1f8*/ DWORD AugSlot2_Unknown; +/*0x1fc*/ DWORD AugSlot3; +/*0x200*/ DWORD AugSlot3_Unknown; +/*0x204*/ DWORD AugSlot4; +/*0x208*/ DWORD AugSlot4_Unknown; +/*0x20c*/ DWORD AugSlot5; +/*0x210*/ DWORD AugSlot5_Unknown; +/*0x214*/ DWORD AugSlot6; +/*0x218*/ DWORD AugSlot6_Unknown; +/*0x21c*/ DWORD AugType; +/*0x220*/ DWORD AugRestrictions; +/*0x224*/ DWORD Unknown0x224; +/*0x228*/ DWORD SolventNeeded; //ID# of Solvent (Augs only) +/*0x22c*/ DWORD LDTheme; +/*0x230*/ DWORD LDCost; +/*0x234*/ DWORD LDType; +/*0x238*/ DWORD Unknown0x238; +/*0x23c*/ BYTE Unknown0x23c[0x4]; +/*0x240*/ DWORD FactionModType[0x4]; +/*0x250*/ DWORD FactionModValue[0x4]; +/*0x260*/ BYTE CharmFile[0x20]; +/*0x280*/ BYTE Unknown0x280[0x4]; +/*0x284*/ struct _ITEMSPELLS Clicky; +/*0x2e8*/ struct _ITEMSPELLS Proc; +/*0x34c*/ struct _ITEMSPELLS Worn; +/*0x3b0*/ struct _ITEMSPELLS Focus; +/*0x414*/ struct _ITEMSPELLS Scroll; +/*0x478*/ struct _ITEMSPELLS itemSpellUnknown; +/*0x4dc*/ BYTE Unknown0x4dc[0x14]; +/*0x4f0*/ DWORD CombatEffects; +/*0x4f4*/ DWORD Shielding; +/*0x4f8*/ DWORD StunResist; +/*0x4fc*/ DWORD DoTShielding; +/*0x500*/ DWORD StrikeThrough; +/*0x504*/ DWORD DmgBonusSkill; // SkillMinDamageMod; +/*0x508*/ DWORD DmgBonusValue; // MinDamageMod; +/*0x50c*/ DWORD SpellShield; +/*0x510*/ DWORD Avoidance; +/*0x514*/ DWORD Accuracy; +/*0x518*/ DWORD CharmFileID; +/*0x51c*/ DWORD CastTime; +/*0x520*/ BYTE Combine; +/*0x521*/ BYTE Slots; +/*0x522*/ BYTE SizeCapacity; +/*0x523*/ BYTE WeightReduction; +/*0x524*/ BYTE BookType; // 0=note, !0=book +/*0x525*/ BYTE BookLang; +/*0x526*/ CHAR BookFile[0x1e]; +/*0x544*/ DWORD Favor; // Tribute Value +/*0x548*/ DWORD GuildFavor; +/*0x54c*/ DWORD Unknown0x54c; +/*0x550*/ DWORD Endurance; +/*0x554*/ DWORD Attack; +/*0x558*/ DWORD HPRegen; +/*0x55c*/ DWORD ManaRegen; +/*0x560*/ DWORD EnduranceRegen; +/*0x564*/ DWORD Haste; +/*0x568*/ DWORD DamShield; +/*0x56c*/ BYTE Unknown0x56c[0x8]; +/*0x574*/ BYTE NoPet; +/*0x575*/ BYTE Unknown0x575[0xb]; +/*0x580*/ DWORD StackSize; +/*0x584*/ BYTE Unknown0x584[0x4]; +/*0x588*/ DWORD MaxPower; +/*0x58c*/ DWORD Purity; +/*0x590*/ BYTE Unknown0x590[0x4]; +/*0x594*/ DWORD Unknown0x594; +/*0x598*/ BYTE QuestItem; +/*0x599*/ BYTE Unknown0x599[0x7]; +/*0x5a0*/ DWORD Clairvoyance; +/*0x5a4*/ BYTE Unknown0x5a4[0x90]; +/*0x634*/ +} ITEMINFO, *PITEMINFO; + +typedef struct _CONTENTSARRAY { + struct _CONTENTS *Contents[0x14]; // 20 bag-slot max - addresses to whats inside the bag if its a bag; augs if an item +} CONTENTSARRAY, *PCONTENTSARRAY; + +// actual size 0x150 20130514 - eqmule +typedef struct _CONTENTS { +/*0x000*/ void *vtable; +/*0x004*/ DWORD ItemType; // ? 1 = normal, 2 = pack ? +/*0x008*/ void *punknown; +/*0x00c*/ BYTE Unknown0x0c[0x8]; +/*0x014*/ DWORD Open; +/*0x018*/ BYTE Unknown0x18[0x8]; +/*0x020*/ DOUBLE EvolvingExpPct; +/*0x028*/ DWORD Price; +/*0x02c*/ DWORD EvolvingMaxLevel; +/*0x030*/ BYTE Unknown0x30[0x14]; +/*0x044*/ DWORD Charges; +/*0x048*/ BYTE Unknown0x48[0x40]; +/*0x088*/ DWORD MerchantSlot; // slot id on a merchant +/*0x08c*/ BYTE Unknown0x8c[0x8]; +/*0x094*/ DWORD Unknown1; +/*0x098*/ DWORD StackCount; +/*0x09c*/ struct _ITEMINFO *Item1; +/*0x0a0*/ DWORD NumOfSlots1; +/*0x0a4*/ BYTE Unknown0xa4[0x4]; +/*0x0a8*/ struct _CONTENTSARRAY *pContentsArray; +/*0x0ac*/ DWORD NumOfSlots2; +/*0x0b0*/ DWORD NumOfSlots3; +/*0x0b4*/ BYTE Unknown0xb4[0x2]; +/*0x0b6*/ WORD ItemSlot; //invslot/which bag its in +/*0x0b8*/ WORD ItemSlot2; //bagslot if in bag, if on cursr this is FFFF +/*0x0ba*/ BYTE Unknown0xba[0x4a]; +/*0x104*/ DWORD MerchantQuantity; +/*0x108*/ DWORD EvolvingCurrentLevel; +/*0x10c*/ BYTE IsEvolvingItem; +/*0x10d*/ BYTE Unknown0x10d[0x3]; +/*0x110*/ DWORD Power; +/*0x114*/ BYTE Unknown0x114[0x1e]; +/*0x132*/ BYTE EvolvingExpOn; +/*0x133*/ BYTE Unknown0x133[0x11]; +/*0x144*/ struct _ITEMINFO *Item2; +/*0x148*/ BYTE Unknown0x148[0x8]; +/*0x150*/ +} CONTENTS, *PCONTENTS; + +// Size 0x58 20110810 - dkaa +typedef struct _SPELLBUFF { +/*0x00*/ BYTE Unknown0x0; +/*0x01*/ BYTE Level; +/*0x02*/ CHAR Modifier; // bard song modifier, divide by 10 to get 2.8 etc +/*0x03*/ CHAR DamageShield; // maybe.. I've noticed this is -1 on a lot of ds's. +/*0x04*/ FLOAT Unknown0x4; +/*0x08*/ LONG SpellID; // -1 or 0 for no spell.. +/*0x0c*/ DWORD Duration; +/*0x10*/ BYTE Unknown0x10[0x48]; +/*0x58*/ +} SPELLBUFF, *PSPELLBUFF; + +// 20101012 - ieatacid +typedef struct _INVENTORY { +/*0x00*/ struct _CONTENTS* Charm; +/*0x04*/ struct _CONTENTS* LeftEar; +/*0x08*/ struct _CONTENTS* Head; +/*0x0c*/ struct _CONTENTS* Face; +/*0x10*/ struct _CONTENTS* RightEar; +/*0x14*/ struct _CONTENTS* Neck; +/*0x18*/ struct _CONTENTS* Shoulders; +/*0x1c*/ struct _CONTENTS* Arms; +/*0x20*/ struct _CONTENTS* Back; +/*0x24*/ struct _CONTENTS* LeftWrist; +/*0x28*/ struct _CONTENTS* RightWrist; +/*0x2c*/ struct _CONTENTS* Range; +/*0x30*/ struct _CONTENTS* Hands; +/*0x34*/ struct _CONTENTS* Primary; +/*0x38*/ struct _CONTENTS* Secondary; +/*0x3c*/ struct _CONTENTS* LeftFinger; +/*0x40*/ struct _CONTENTS* RightFinger; +/*0x44*/ struct _CONTENTS* Chest; +/*0x48*/ struct _CONTENTS* Legs; +/*0x4c*/ struct _CONTENTS* Feet; +/*0x50*/ struct _CONTENTS* Waist; +/*0x54*/ struct _CONTENTS* PowerSource; +/*0x58*/ struct _CONTENTS* Ammo; +/*0x5c*/ struct _CONTENTS* Pack[0xa]; +/*0x84*/ struct _CONTENTS* Cursor; +} INVENTORY, *PINVENTORY; + +#define NUM_ALT_ABILITIES_ARRAY 0x1F7 +#define NUM_ALT_ABILITIES 0xC34F + +//these two will merge when i get a chance +#define AA_CHAR_MAX 0xF5 +#define AA_CHAR_MAX_REAL 0x12C + +typedef struct _AALIST { +/*0x0*/ DWORD AAIndex; +/*0x4*/ DWORD PointsSpent; +/*0x8*/ DWORD ChargeSpent; // charges spent in the last 10 min? +} AALIST, *PAALIST; + +#define NUM_INV_SLOTS 0x21 +#define NUM_BANK_SLOTS 0x18 +#define NUM_SHAREDBANK_SLOTS 0x02 +#define NUM_BOOK_SLOTS 0x2d0 +#define NUM_COMBAT_ABILITIES 0x12c +#define BAG_SLOT_START 23 +#define ExactLocation 0 + +typedef struct _LEADERABILITIES { +/*0x00*/ DWORD MarkNPC; +/*0x04*/ DWORD NPCHealth; +/*0x08*/ DWORD Unknown0x8; +/*0x0c*/ DWORD DelegateMA; +/*0x10*/ DWORD DelegateMarkNPC; +/*0x14*/ DWORD Unknown0x14; +/*0x18*/ DWORD InspectBuffs; +/*0x1c*/ DWORD Unknown0x1c; +/*0x20*/ DWORD SpellAwareness; +/*0x24*/ DWORD OffenseEnhancement; +/*0x28*/ DWORD ManaEnhancement; +/*0x2c*/ DWORD HealthEnhancement; +/*0x30*/ DWORD HealthRegen; +/*0x34*/ DWORD FindPathPC; +/*0x38*/ DWORD HoTT; +/*0x3c*/ +} LEADERABILITIES, *PLEADERABILITIES; + +typedef struct _EQC_INFO { +/* 0x0000 */ DWORD minus4; +/* 0x0004 */ DWORD stuff_offset; +} EQC_INFO, *PEQC_INFO; + +typedef struct _CI_INFO { +/* 0x0000 */ DWORD minus8; +/* 0x0004 */ DWORD stuff_offset; +/* 0x0008 */ DWORD Unknown0x8; // 2000 +/* 0x000c */ DWORD Unknown0xc; // 2500 +/* 0x0010 */ DWORD Unknown0x10; // 3000 +/* 0x0014 */ DWORD Unknown0x14; // 4000 +/* 0x0018 */ DWORD Unknown0x18; // 10000 +} CI_INFO, *PCI_INFO; + +typedef struct _CI2_INFO { +/* 0x0000 */ DWORD Unknown0x0; +/* 0x0004 */ struct _CHARINFO2* pCharInfo2; +/* 0x0008 */ struct _CHARINFO2* pCharInfo3; +/* 0x000c */ BYTE Unknown0xc[0x14]; +/* 0x0010 */ void *Unknown0x10[0x10]; +/* 0x0060 */ +} CI2_INFO, *PCI2_INFO; + +typedef struct _GROUPMEMBER { +/*0x00*/ void *vftable; +/*0x04*/ struct _CXSTR *pName; +/*0x08*/ BYTE Mercenary; +/*0x09*/ BYTE Unknown0x8[0x3]; +/*0x0c*/ struct _CXSTR *pOwner; // name of mercenary's owner +/*0x10*/ DWORD Level; +/*0x14*/ BYTE Unknown0x14[0x2]; +/*0x16*/ BYTE MainTank; +/*0x17*/ BYTE MainAssist; +/*0x18*/ BYTE Puller; +/*0x19*/ BYTE Unknown0x19[0x3]; +/*0x1c*/ DWORD Roles; // (Roles & 1) = MainTank, 2 = MainAssist, 4 = Puller +/*0x20*/ BYTE Unknown0x20[0x8]; +/*0x28*/ struct _SPAWNINFO *pSpawn; +/*0x2c*/ +} GROUPMEMBER, *PGROUPMEMBER; + +typedef struct _GROUPINFO { +/*0x00*/ void *vftable; +/*0x04*/ struct _GROUPMEMBER *pMember[0x6]; +/*0x1c*/ struct _GROUPMEMBER *pLeader; +/*0x20*/ +} GROUPINFO, *PGROUPINFO; + +typedef struct _BANKARRAY { +/*0x00*/ struct _CONTENTS* Bank[NUM_BANK_SLOTS]; +/*0x68*/ +} BANKARRAY, *PBANKARRAY; + +typedef struct _SHAREDBANKARRAY { +/*0x00*/ struct _CONTENTS* SharedBank[NUM_SHAREDBANK_SLOTS]; +/*0x68*/ +} SHAREDBANKARRAY, *PSHAREDBANKARRAY; + +// actual size: 0x5804 20130417 - ieatacid +typedef struct _CHARINFO { +/*0x0000*/ void *vtable1; +/*0x0004*/ void *punknown; +/*0x0008*/ struct _CI_INFO* charinfo_info; +/*0x000c*/ BYTE Unknown0xc[0x1d94]; +/*0x1da0*/ struct _LEADERABILITIES MyAbilities; //points spent in each ability (size 0x3c) +/*0x1ddc*/ BYTE Unknown0x1ddc[0xc4]; +/*0x1ea0*/ DWORD Unknown0x1ea0; // # of bank slots? +/*0x1ea4*/ DWORD Unknown0x1ea4; +/*0x1ea8*/ struct _BANKARRAY *pBankArray; +/*0x1eac*/ DWORD Unknown0x1eac; // # of bank slots? +/*0x1eb0*/ BYTE Unknown0x1eb0[0x28]; +/*0x1ed8*/ DWORD Unknown0x1ed8; // # of bank slots? +/*0x1edc*/ DWORD Unknown0x1edc; +/*0x1ee0*/ struct _SHAREDBANKARRAY *pSharedBankArray; +/*0x1ee4*/ DWORD Unknown0x1ee4; // # of bank slots? +/*0x1ee8*/ BYTE Unknown0x1ee8[0x164]; +/*0x204c*/ DWORD GuildID; +/*0x2050*/ BYTE Unknown0x2050[0x2c]; +/*0x207c*/ DWORD AAExp; +/*0x2080*/ BYTE Unknown0x2080; +/*0x2081*/ BYTE PercentEXPtoAA; +/*0x2082*/ BYTE Unknown0x2082[0x42]; +/*0x20c4*/ DWORD TributeTimer; +/*0x20c8*/ DWORD BenefitTimer; +/*0x20cc*/ DWORD Unknown0x20cc; +/*0x20d0*/ DWORD CareerFavor; +/*0x20d4*/ DWORD Unknown0x20d4; +/*0x20d8*/ DWORD CurrFavor; +/*0x20dc*/ BYTE Unknown0x20dc[0xc]; +/*0x20e8*/ DOUBLE GroupLeadershipExp; +/*0x20f0*/ DOUBLE RaidLeadershipExp; +/*0x20f8*/ DWORD GroupLeadershipPoints; +/*0x20fc*/ DWORD RaidLeadershipPoints; +/*0x2100*/ BYTE Unknown0x2100[0x194]; +/*0x2294*/ DWORD RadiantCrystals; +/*0x2298*/ DWORD Unknown0x2298; +/*0x229c*/ DWORD EbonCrystals; +/*0x22a0*/ BYTE Unknown0x22a0[0x670]; +/*0x2910*/ DWORD Exp; +/*0x2914*/ BYTE Unknown0x2914[0x64]; +/*0x2978*/ void *PlayerPointManager; +/*0x297c*/ BYTE Unknown0x297c[0x44c]; +/*0x2dc8*/ void *vtable2; +/*0x2dcc*/ struct _EQC_INFO* eqc_info; +/*0x2dd0*/ struct _SPAWNINFO* pSpawn; +/*0x2dd4*/ DWORD Unknown0x2dd4; +/*0x2dd8*/ DWORD Unknown0x2dd8; +/*0x2ddc*/ DWORD CurrWeight; +/*0x2de0*/ BYTE Unknown0x2de0[0xc]; +/*0x2dec*/ DWORD HPBonus; +/*0x2df0*/ DWORD ManaBonus; +/*0x2df4*/ DWORD EnduranceBonus; +/*0x2df8*/ DWORD CombatEffectsCap;//CombatEffectsBonus +/*0x2dfc*/ DWORD ShieldingCap;//ShieldingBonus +/*0x2e00*/ DWORD SpellShieldCap;//SpellShieldBonus +/*0x2e04*/ DWORD AvoidanceCap;//AvoidanceBonus +/*0x2e08*/ DWORD AccuracyCap;//AccuracyBonus +/*0x2e0c*/ DWORD StunResistCap;//StunResistBonus +/*0x2e10*/ DWORD StrikeThroughCap;//StrikeThroughBonus +/*0x2e14*/ DWORD Unknown0x2e14[0x9]; +/*0x2e38*/ DWORD SkillMinDamageModBonus[0x9]; +/*0x2e5c*/ BYTE Unknown0x2e5c[0x4]; +/*0x2e60*/ DWORD DoTShieldCap;//DoTShieldBonus +/*0x2e64*/ DWORD DamageShieldMitigationCap;//DamageShieldMitigationBonus +/*0x2e68*/ DWORD CombatEffectsBonus; +/*0x2e6c*/ DWORD SpellShieldBonus; +/*0x2e70*/ DWORD ShieldingBonus; +/*0x2e74*/ DWORD DamageShieldBonus; +/*0x2e78*/ DWORD DoTShieldBonus; +/*0x2e7c*/ DWORD DamageShieldMitigationBonus; +/*0x2e80*/ DWORD AvoidanceBonus; +/*0x2e84*/ DWORD AccuracyBonus; +/*0x2e88*/ DWORD StunResistBonus; +/*0x2e8c*/ DWORD StrikeThroughBonus; +/*0x2e90*/ DWORD HeroicSTRBonus; +/*0x2e94*/ DWORD HeroicINTBonus; +/*0x2e98*/ DWORD HeroicWISBonus; +/*0x2e9c*/ DWORD HeroicAGIBonus; +/*0x2ea0*/ DWORD HeroicDEXBonus; +/*0x2ea4*/ DWORD HeroicSTABonus; +/*0x2ea8*/ DWORD HeroicCHABonus; +/*0x2eac*/ DWORD HeroicSvMagicBonus; +/*0x2eb0*/ DWORD HeroicSvFireBonus; +/*0x2eb4*/ DWORD HeroicSvColdBonus; +/*0x2eb8*/ DWORD HeroicSvDiseaseBonus; +/*0x2ebc*/ DWORD HeroicSvPoisonBonus; +/*0x2ec0*/ DWORD HeroicSvCorruptionBonus; +/*0x2ec4*/ DWORD HealAmountBonus; +/*0x2ec8*/ DWORD SpellDamageBonus; +/*0x2ecc*/ DWORD Unknown0x2ecc[0x2]; +/*0x2ed4*/ DWORD ClairvoyanceBonus; +/*0x2ed8*/ DWORD AttackBonus; +/*0x2edc*/ DWORD HPRegenBonus; +/*0x2ee0*/ DWORD ManaRegenBonus; +/*0x2ee4*/ DWORD EnduranceRegenBonus; +/*0x2ee8*/ DWORD DamageShieldCap; +/*0x2eec*/ DWORD AttackSpeed; +/*0x2ef0*/ BYTE Unknown0x2ef0[0x2c8]; +/*0x31b8*/ struct _XTARGETMGR *pXTargetMgr; +/*0x31bc*/ DWORD InCombat; +/*0x31c0*/ DWORD Downtime; +/*0x31c4*/ DWORD DowntimeStamp; +/*0x31c8*/ BYTE Unknown0x31c8[0x4]; +/*0x31cc*/ struct _GROUPINFO *pGroupInfo; +/*0x31d0*/ BYTE Unknown0x31d0[0x1c]; +/*0x31ec*/ void *pUnknown2; +/*0x31f0*/ struct _CI2_INFO* pCI2; +/*0x31f4*/ DWORD Unknown0x31f4; +/*0x31f8*/ BYTE languages[0x20]; +/*0x3218*/ BYTE Unknown0x3218[0x10]; +/*0x3228*/ CHAR Name[0x40]; +/*0x3268*/ CHAR Lastname[0x20]; +/*0x3288*/ BYTE Unknown0x3288[0x60]; +/*0x32e8*/ BYTE Stunned; +/*0x32e9*/ BYTE Unknown0x32e9[0x3]; +/*0x32ec*/ WORD zoneId; +/*0x32ee*/ WORD instance; +/*0x32f0*/ DWORD standstate; +/*0x32f4*/ BYTE Unknown0x32f4[0x4]; +/*0x32f8*/ struct _LEADERABILITIES ActiveAbilities; //ability levels of the leader of your group (size 0x3c) +/*0x3334*/ BYTE Unknown0x3334[0x314]; +/*0x3648*/ DWORD ExpansionFlags; +/*0x364c*/ BYTE Unknown0x364c[0x20]; +/*0x366c*/ DWORD BankSharedPlat; +/*0x3670*/ DWORD BankSharedGold; +/*0x3674*/ DWORD BankSharedSilver; +/*0x3678*/ DWORD BankSharedCopper; +/*0x367c*/ DWORD BankPlat; +/*0x3680*/ DWORD BankGold; +/*0x3684*/ DWORD BankSilver; +/*0x3688*/ DWORD BankCopper; +/*0x368c*/ DWORD STR; +/*0x3690*/ DWORD STA; +/*0x3694*/ DWORD CHA; +/*0x3698*/ DWORD DEX; +/*0x369c*/ DWORD INT; +/*0x36a0*/ DWORD AGI; +/*0x36a4*/ DWORD WIS; +/*0x36a8*/ DWORD SavePoison; +/*0x36ac*/ DWORD SaveMagic; +/*0x36b0*/ DWORD SaveDisease; +/*0x36b4*/ DWORD SaveCorruption; +/*0x36b8*/ DWORD SaveFire; +/*0x36bc*/ DWORD SaveCold; +/*0x36c0*/ BYTE Unknown0x36c0[0x2144]; +/*0x5804*/ +} CHARINFO, *PCHARINFO; + +typedef struct _INVENTORYARRAY { +union { +/*0x00*/ struct _INVENTORY Inventory; +/*0x00*/ struct _CONTENTS* InventoryArray[NUM_INV_SLOTS]; +}; +} INVENTORYARRAY, *PINVENTORYARRAY; + +// actual size: 0x9950 20130116 - ieatacid +typedef struct _CHARINFO2 { +/*0x0000*/ BYTE Unknown0x0[0x18]; +/*0x0018*/ DWORD Unknown0x18; // # of inventory slots? +/*0x001c*/ DWORD Unknown0x1c; +/*0x0020*/ struct _INVENTORYARRAY *pInventoryArray; +/*0x0024*/ DWORD Unknown0x24; // # of inventory slots? +/*0x0024*/ DWORD Unknown0x28; // # of inventory slots? +/*0x0028*/ BYTE Unknown0x2c[0x94]; +/*0x00c0*/ struct _SPELLBUFF Buff[NUM_LONG_BUFFS]; +/*0x0f30*/ struct _SPELLBUFF ShortBuff[0x37]; +/*0x2218*/ DWORD Unknown0x2218[NUM_BUFF_SLOTS]; // effect IDs +/*0x239c*/ DWORD Unknown0x239c[NUM_BUFF_SLOTS]; +/*0x2520*/ DWORD SpellBook[NUM_BOOK_SLOTS]; +/*0x3060*/ DWORD MemorizedSpells[0x10]; +/*0x30a0*/ DWORD Skill[0x64]; +/*0x3230*/ DWORD InnateSkill[0x19]; +/*0x3294*/ DWORD Unknown0x3294[0x36]; +/*0x336c*/ DWORD Gender; +/*0x3370*/ DWORD Race; +/*0x3374*/ DWORD Class; +/*0x3378*/ BYTE Unknown0x3378[0x10]; +/*0x3388*/ DWORD Level; +/*0x338c*/ DWORD Mana; +/*0x3390*/ DWORD Endurance; +/*0x3394*/ DWORD BaseHP; +/*0x3398*/ DWORD BaseSTR; +/*0x339c*/ DWORD BaseSTA; +/*0x33a0*/ DWORD BaseCHA; +/*0x33a4*/ DWORD BaseDEX; +/*0x33a8*/ DWORD BaseINT; +/*0x33ac*/ DWORD BaseAGI; +/*0x33b0*/ DWORD BaseWIS; +/*0x33b4*/ DWORD Unknown0x33b4; +/*0x33b8*/ DWORD Plat; +/*0x33bc*/ DWORD Gold; +/*0x33c0*/ DWORD Silver; +/*0x33c4*/ DWORD Copper; +/*0x33c8*/ DWORD CursorPlat; +/*0x33cc*/ DWORD CursorGold; +/*0x33d0*/ DWORD CursorSilver; +/*0x33d4*/ DWORD CursorCopper; +/*0x33d8*/ BYTE Unknown0x33d8[0x28]; +/*0x3400*/ DWORD thirstlevel; +/*0x3404*/ DWORD hungerlevel; +/*0x3408*/ DWORD Unknown0x3408; +/*0x340c*/ DWORD Shrouded; +/*0x3410*/ BYTE Unknown0x3410[0x78]; +/*0x3488*/ DWORD ZoneBoundID; +/*0x348c*/ FLOAT ZoneBoundY; +/*0x3490*/ FLOAT ZoneBoundX; +/*0x3494*/ FLOAT ZoneBoundZ; +/*0x3498*/ FLOAT ZoneBoundHeading; +/*0x349c*/ BYTE Unknown0x349c[0x50]; +/*0x34ec*/ DWORD ArmorType[0x16]; +/*0x3544*/ BYTE Unknown0x3544[0x160]; +/*0x36a4*/ AALIST AAList[AA_CHAR_MAX_REAL]; +/*0x44b4*/ DWORD BodyColor[0x9]; +/*0x44d8*/ BYTE Unknown0x44d8[0x2000]; +/*0x64d8*/ DWORD CombatAbilities[NUM_COMBAT_ABILITIES]; +/*0x6988*/ BYTE Unknown0x6988[0x34]; +/*0x69bc*/ DWORD CombatAbilityTimes[0x14]; +/*0x6a0c*/ BYTE Unknown0x6a0c[0x1ed8]; +/*0x88e4*/ DWORD Deity; +/*0x88e8*/ BYTE Unknown0x88e8[0x4]; +/*0x88ec*/ DWORD Drunkenness; +/*0x88f0*/ BYTE Unknown0x88f0[0x10]; +/*0x8900*/ DWORD AAPoints; +/*0x8904*/ BYTE Unknown0x8904[0x100c]; +/*0x9910*/ DWORD AAPointsSpent; +/*0x9914*/ BYTE Unknown0x9914[0x3c]; +/*0x9950*/ +} CHARINFO2, *PCHARINFO2; + +typedef struct _MODELINFONAME { +/*0x00*/ DWORD Unknown0000; +/*0x04*/ DWORD Unknown0004; +/*0x08*/ PCHAR Name; +/*0x0c*/ +} MODELINFONAME, *PMODELINFONAME; + +typedef struct _MODELINFO_GENERIC { +/*0x00*/ DWORD Type; +/*0x04*/ DWORD Unknown0x04; +/*0x08*/ DWORD Unknown0x08; +/*0x0c*/ DWORD Unknown0x0c; +/*0x10*/ DWORD Unknown0x10; +/*0x14*/ +} MODELINFO_GENERIC, *PMODELINFO_GENERIC; + +typedef struct _MODELINFO_48 { +/*0x00*/ struct _MODELINFO_GENERIC Header; +/*0x14*/ FLOAT Float1; +/*0x18*/ FLOAT Float2; +/*0x1c*/ FLOAT Float3; +/*0x20*/ struct _MODELINFONAME *pModelName; +/*0x24*/ +} MODELINFO_48, *PMODELINFO_48; + +typedef struct _MODELINFO_51 { +/*0x00*/ struct _MODELINFO_GENERIC Header; +/*0x14*/ struct _MODELINFONAME *pFontName; +/*0x18*/ PCHAR LabelText; +/*0x1c*/ +} MODELINFO_51, *PMODELINFO_51; + +// 10/09/2003 build plazmic +// 12/24/2003 verified Amadeus +typedef struct _MODELINFO { +/*0x00*/ DWORD Unknown; +/*0x04*/ PCHAR NameDAG; +/*0x08*/ struct _MODELINFO_GENERIC *pModelInfo; +/*0x0c*/ struct _MODELINFO *pNextInChain; +/*0x10*/ PVOID pUnknown; +/*0x14*/ struct _MODELINFONAME *pTrack1; +/*0x18*/ struct _MODELINFONAME *pTrack2; + //moredata +} MODELINFO, *PMODELINFO; + +// 4/30/2003 build eqmule +typedef struct _CAMERAINFO { +/*0x00*/ DWORD Unknown0x00; +/*0x04*/ DWORD Unknown0x04; +/*0x08*/ BYTE Unknown0x08[0x8]; +/*0x10*/ FLOAT Y; +/*0x14*/ FLOAT X; +/*0x18*/ FLOAT Z; +/*0x1c*/ FLOAT LightRadius; +/*0x20*/ +} CAMERAINFO, *PCAMERAINFO; + + +#define MODEL_LABEL 0 +#define MODEL_LABELINFO 1 +#define MODEL_NULL2 2 +#define MODEL_HELD_R 3 +#define MODEL_HELD_L 4 +#define MODEL_SHIELD 5 +#define MODEL_NULL6 6 + +/* +//Work in progress... +#define MODEL_HEAD 0x00 +#define MODEL_HEAD_POINT 0x01 +#define MODEL_NULL_1 0x02 +#define MODEL_HELD_R 0x03 +#define MODEL_HELD_L 0x04 +#define MODEL_SHIELD 0x05 +#define MODEL_NULL_2 0x06 +#define MODEL_TUNIC 0x07 +#define MODEL_HAIR 0x08 +#define MODEL_BEARD 0x09 +#define MODEL_CHEST 0x0a +#define MODEL_GLOVES 0x0b +#define MODEL_GLOVES2 0b0c +*/ + +typedef struct _ARGBCOLOR { + union { + struct { + BYTE B; + BYTE G; + BYTE R; + BYTE A; + }; + DWORD ARGB; + }; +} ARGBCOLOR, *PARGBCOLOR; + +// actual size: 0x14 05-14-2013 - eqmule +typedef struct _ARMOR { +/*0x00*/ DWORD ID; //idfile on Lucy +/*0x04*/ DWORD Unknown0x04; +/*0x08*/ DWORD Unknown0x08; +/*0x0c*/ DWORD Unknown0x0c; +/*0x10*/ DWORD Unknown0x10; +/*0x14*/ +} ARMOR, *PARMOR; + +// 10-22-2003 Lax +typedef struct _EQUIPMENT { + union { + struct// EQUIPARRAY + { + struct _ARMOR Item[9]; + };// Array; + struct //EQUIPUNIQUE + { + struct _ARMOR Head; + struct _ARMOR Chest; + struct _ARMOR Arms; + struct _ARMOR Wrists; + struct _ARMOR Hands; + struct _ARMOR Legs; + struct _ARMOR Feet; + struct _ARMOR Primary; + struct _ARMOR Offhand; + };// Unique; + }; +} EQUIPMENT, *PEQUIPMENT; + +// 10-14-07 - ieatacid +typedef struct _FELLOWSHIPMEMBER { +/*0x00*/ DWORD Unknown0x0; +/*0x04*/ CHAR Name[0x40]; +/*0x44*/ WORD ZoneID; +/*0x46*/ WORD InstanceID; +/*0x48*/ DWORD Level; +/*0x4c*/ DWORD Class; +/*0x50*/ DWORD LastOn; // FastTime() timestamp +/*0x54*/ +} FELLOWSHIPMEMBER, *PFELLOWSHIPMEMBER; + +// 20121128 - ieatacid 0x9e4 +typedef struct _FELLOWSHIPINFO { +/*0x000*/ DWORD Unknown0x0; // always 1? +/*0x004*/ DWORD FellowshipID; +/*0x008*/ CHAR Leader[0x40]; +/*0x048*/ CHAR MotD[0x400]; +/*0x448*/ DWORD Members; +/*0x44c*/ struct _FELLOWSHIPMEMBER FellowshipMember[0xc]; +/*0x83c*/ DWORD Unknown0x83c; // timestamp for something +/*0x840*/ BYTE Unknown0x840[0x1a4]; +/*0x9e4*/ +} FELLOWSHIPINFO, *PFELLOWSHIPINFO; + +// offsets are relative to their position in _LAUNCHSPELLDATA +typedef struct _ITEMLOCATION { +/*0x0c*/ DWORD a; +/*0x10*/ DWORD InvSlot; +/*0x14*/ DWORD BagSlot; +/*0x18*/ DWORD d; +/*0x1c*/ +} ITEMLOCATION, *PITEMLOCATION; + +typedef struct _LAUNCHSPELLDATA { +/*0x00*/ DWORD SpellETA; //Calculated TimeStamp when current spell being cast will land. 0 while not casting. +/*0x04*/ DWORD SpellID; // -1 = not casting a spell +/*0x08*/ BYTE SpellSlot; // 0xFF if not casting, otherwise it's the spell gem number (0 - 8) +/*0x09*/ BYTE Padding0x9[0x3]; +/*0x0c*/ struct _ITEMLOCATION ItemLocation; +/*0x1c*/ DWORD ItemID; +/*0x20*/ FLOAT CastingY; +/*0x24*/ FLOAT CastingX; +/*0x28*/ BYTE Unknown0x28[0x4]; +/*0x2c*/ DWORD TargetID; +/*0x30*/ BYTE Unknown0x30[0x14]; +/*0x44*/ DWORD Unknown0x44; +/*0x48*/ DWORD Unknown0x48; +/*0x4c*/ DWORD Unknown0x4c; +/*0x50*/ +} LAUNCHSPELLDATA, *PLAUNCHSPELLDATA; + +// actual size: 0x1efc 05-14-2013 - eqmule +typedef struct _SPAWNINFO { +/*0x0000*/ void *vtable; +/*0x0004*/ struct _SPAWNINFO *pPrev; +/*0x0008*/ struct _SPAWNINFO *pNext; +/*0x000c*/ BYTE Unknown0xc[0xc]; +/*0x0018*/ FLOAT SpeedMultiplier; +/*0x001c*/ BYTE Unknown0x1c[0x14]; +/*0x0030*/ DWORD TimeStamp; +/*0x0034*/ BYTE Unknown0x34[0x4]; +/*0x0038*/ CHAR Lastname[0x20]; +/*0x0058*/ BYTE Unknown0x58[0xc]; +/*0x0064*/ FLOAT Y; +/*0x0068*/ FLOAT X; +/*0x006c*/ FLOAT Z; +/*0x0070*/ FLOAT SpeedY; +/*0x0074*/ FLOAT SpeedX; +/*0x0078*/ FLOAT SpeedZ; +/*0x007c*/ FLOAT SpeedRun; +/*0x0080*/ FLOAT Heading; +/*0x0084*/ BYTE Unknown0x84[0x8]; +/*0x008c*/ FLOAT SpeedHeading; +/*0x0090*/ FLOAT CameraAngle; +/*0x0094*/ BYTE UnderWater; +/*0x0095*/ BYTE Unknown0x95[0xc]; +/*0x00a1*/ BYTE FeetWet; +/*0x00a2*/ BYTE Unknown0xa2[0x2]; +/*0x00a4*/ CHAR Name[0x40]; // ie priest_of_discord00 +/*0x00e4*/ CHAR DisplayedName[0x40]; // ie Priest of Discord +/*0x0124*/ BYTE Unknown0x124; +/*0x0125*/ BYTE Type; +/*0x0126*/ BYTE Unknown0x126[0x2]; +/*0x0128*/ DWORD **BodyType; +/*0x012c*/ BYTE Unknown0x12c[0xc]; +/*0x0138*/ FLOAT AvatarHeight; // height of avatar from ground when standing +/*0x013c*/ FLOAT UnknownHeight; +/*0x0140*/ FLOAT AvatarHeight2; // height of avatar from ground when crouched/sitting +/*0x0144*/ FLOAT Unknown0x144; // height of avatar from ground when standing +/*0x0148*/ DWORD SpawnID; +/*0x014c*/ BYTE Unknown0x14c[0x4]; +/*0x0150*/ DWORD IsABoat; // 1 = a type of boat +/*0x0154*/ struct _SPAWNINFO *Mount; // NULL if no mount present +/*0x0158*/ struct _SPAWNINFO *Rider; // _SPAWNINFO of mount's rider +/*0x015c*/ BYTE Unknown0x15c[0x44]; +/*0x01a0*/ DWORD EnduranceCurrent; +/*0x01a4*/ BYTE Unknown0x1a4[0x64]; +/*0x0208*/ BYTE Mercenary; +/*0x0209*/ BYTE Unknown0x209[0x7]; +/*0x0210*/ WORD Zone; +/*0x0212*/ WORD Instance; +/*0x0214*/ BYTE Light; +/*0x0215*/ BYTE Unknown0x215[0x33]; +/*0x0248*/ DWORD GuildStatus; +/*0x024c*/ DWORD LastTick; +/*0x0250*/ BYTE Level; +/*0x0251*/ BYTE Unknown0x251[0xb]; +/*0x025c*/ BYTE GM; +/*0x025d*/ BYTE Unknown0x25d[0x3]; +/*0x0260*/ DWORD FishingETA; +/*0x0264*/ BYTE Sneak; +/*0x0265*/ BYTE Unknown0x265[0x4f]; +/*0x02b4*/ DWORD PetID; +/*0x02b8*/ DWORD Anon;//found in EQPlayer__SetNameSpriteTint_x +/*0x02bc*/ DWORD RespawnTimer; // TimeStamp of when RespawnWnd will close - 0 when you're alive +/*0x02c0*/ BYTE Unknown0x2c0[0x4]; +/*0x02c4*/ DWORD AARank; +/*0x02c8*/ BYTE Unknown0x2c8[0x14]; +/*0x02dc*/ DWORD HPMax; +/*0x02e0*/ BYTE Unknown0x2e0[0x4]; +/*0x02e4*/ LONG HPCurrent; +/*0x02e8*/ BYTE Unknown0x2e8[0x30]; +/*0x0318*/ DWORD InnateETA; //Calculated TimeStamp when innate skill will be ready (LoH, HT, Bash) +/*0x031c*/ FLOAT GetMeleeRangeVar1; // used by GetMeleeRange +/*0x0320*/ DWORD Trader;//found in CEverQuest__RightClickedOnPlayer_x +/*0x0324*/ BYTE Unknown0x324[0x10]; +/*0x0334*/ BYTE Holding; +/*0x0335*/ BYTE Unknown0x335[0x3]; +/*0x0338*/ BYTE HideMode; +/*0x0339*/ BYTE Unknown0x339[0x10]; +/*0x0349*/ BYTE PvPFlag; +/*0x034a*/ BYTE Unknown0x34a[0x2]; +/*0x034c*/ DWORD GuildID; +/*0x0350*/ FLOAT RunSpeed;//0.70 on runspeed 5... +/*0x0354*/ DWORD ManaMax; +/*0x0358*/ BYTE Unknown0x358[0x4]; +/*0x035c*/ BYTE StandState; +/*0x035d*/ BYTE Unknown0x35d[0x2f]; +/*0x038c*/ DWORD MasterID; +/*0x0390*/ BYTE Unknown0x390[0x30]; +/*0x03c0*/ DWORD AFK; +/*0x03c4*/ DWORD EnduranceMax; +/*0x03c8*/ BYTE Unknown0x3c8[0x8]; +/*0x03d0*/ BYTE Linkdead; +/*0x03d1*/ BYTE Unknown0x3d1[0x3]; +/*0x03d4*/ DWORD Buyer; +/*0x03d8*/ BYTE Unknown0x3d8[0x5]; +/*0x03dd*/ CHAR Title[0x20]; +/*0x03fd*/ BYTE FishingEvent; +/*0x03fe*/ CHAR Suffix[0x20]; +/*0x041e*/ BYTE Unknown0x41e[0x22]; +/*0x0440*/ BYTE LFG; +/*0x0441*/ BYTE Unknown0x441[0x3]; +/*0x0444*/ struct _LAUNCHSPELLDATA CastingData; // size: 0x50 +/*0x0494*/ DWORD ManaCurrent; +/*0x0498*/ BYTE Unknown0x498[0x80]; +/*0x0518*/ DWORD Deity; +/*0x051c*/ BYTE Unknown0x51c[0x924]; +/*0x0e40*/ struct _SPAWNINFO *WhoFollowing; // NULL if autofollow off +/*0x0e44*/ int GroupAssistNPC[0x1]; +/*0x0e48*/ int RaidAssistNPC[0x3]; +/*0x0e54*/ int GroupMarkNPC[0x3]; +/*0x0e60*/ int RaidMarkNPC[0x3]; +/*0x0e6c*/ int TargetOfTarget; +/*0x0e70*/ BYTE Unknown0xe70[0x34]; +/*0x0ea4*/ void *pActorClient; // start of ActorClient struct +/*0x0ea8*/ BYTE InNonPCRaceIllusion; +/*0x0ea9*/ BYTE Unknown0xe9d[0x3]; +/*0x0eac*/ BYTE FaceStyle; +/*0x0ead*/ BYTE HairColor; +/*0x0eae*/ BYTE FacialHairColor; +/*0x0eaf*/ BYTE EyeColor1; +/*0x0eb0*/ BYTE EyeColor2; +/*0x0eb1*/ BYTE HairStyle; +/*0x0eb2*/ BYTE FacialHair; +/*0x0eb3*/ BYTE Unknown0xea7; +/*0x0eb4*/ DWORD Race; +/*0x0eb8*/ BYTE Class; +/*0x0eb9*/ BYTE Gender; +/*0x0eba*/ CHAR ActorDef[0x40]; +/*0x0efa*/ BYTE Unknown0xeee[0x2]; +/*0x0efc*/ ARGBCOLOR ArmorColor[0x9]; +/*0x0f20*/ BYTE Unknown0xf20[0x4]; +/*0x0f24*/ DWORD Heritage; //drakkin only face setting +/*0x0f28*/ DWORD Tattoo; //drakkin only face setting +/*0x0f2c*/ DWORD Details; //drakkin only face setting +/*0x0f30*/ struct _EQUIPMENT Equipment; // size 0xb4 +/*0x0fe4*/ BYTE Unknown0xfe4[0x38]; +/*0x101c*/ VOID *pcactorex; // ActorInterface* +/*0x1020*/ BYTE Unknown0x1020[0x4]; +/*0x1024*/ VOID *FaceRelatedActorStruct; +/*0x1028*/ BYTE Unknown0x1028[0x34]; +/*0x105c*/ FLOAT GetMeleeRangeVar2; // used by GetMeleeRange +/*0x1060*/ BYTE Unknown0x1060[0x64]; +/*0x10c4*/ DWORD Animation; +/*0x10c8*/ BYTE Unknown0x10c8[0x104]; +/*0x11cc*/ FLOAT WalkSpeed; +/*0x11d0*/ DWORD HideCorpse; +/*0x11d4*/ BYTE Unknown0x11d4[0x40]; +/*0x1214*/ BYTE InvitedToGroup; +/*0x1215*/ BYTE Unknown0x1215[0x3]; +/*0x1218*/ DWORD GroupMemberTargeted; // 0xFFFFFFFF if no target, else 1 through 5 +/*0x121c*/ BYTE Unknown0x1210[0x180]; +/*0x139c*/ struct _FELLOWSHIPINFO Fellowship; // size 0x9e4 +/*0x1d80*/ FLOAT CampfireY; +/*0x1d84*/ FLOAT CampfireX; +/*0x1d88*/ FLOAT CampfireZ; +/*0x1d8c*/ WORD CampfireZoneID; // zone ID where campfire is +/*0x1d8e*/ WORD InstanceID; +/*0x1d90*/ DWORD CampfireTimestamp; // CampfireTimestamp-FastTime()=time left on campfire +/*0x1d94*/ DWORD Unknown0x1d88; +/*0x1d98*/ DWORD Unknown0x1d8c; // campfire type? +/*0x1d9c*/ DWORD Campfire; // do we have a campfire up? +/*0x1da0*/ BYTE Unknown0x1da0[0x110]; +/*0x1eb0*/ void *vtable2; +/*0x1eb4*/ DWORD Unknown0x1ea8; +/*0x1eb8*/ struct _SPAWNINFO *pSpawn; +/*0x1ebc*/ DWORD Levitate; +/*0x1ec0*/ BYTE Unknown0x1ec0[0x3c]; +/*0x1efc*/ +} SPAWNINFO, *PSPAWNINFO; + +#define STANDSTATE_STAND 0x64 +#define STANDSTATE_CASTING 0x66 +#define STANDSTATE_BIND 0x69 +#define STANDSTATE_SIT 0x6E +#define STANDSTATE_DUCK 0x6F +#define STANDSTATE_FEIGN 0x73 +#define STANDSTATE_DEAD 0x78 + +#define MONITOR_SPAWN_X 1 +#define MONITOR_SPAWN_Y 2 +#define MONITOR_SPAWN_Z 4 +#define MONITOR_SPAWN_HEADING 8 +#define MONITOR_SPAWN_SPEEDRUN 16 +#define MONITOR_SPAWN_HPCURRENT 32 + +typedef struct _SPAWNMONITORINFO { + WORD SpawnID; + FLOAT Y; + FLOAT X; + FLOAT Z; + FLOAT Heading; + FLOAT SpeedRun; + DWORD HPCurrent; + DWORD MonitorMask; +} SPAWNMONITORINFO, *PSPAWNMONITORINFO; + +typedef struct _HASHENTRY { + SPAWNINFO *spawn; + DWORD key; // same as SpawnID for spawns + struct _HASHENTRY *next; +} HASHENTRY, *PHASHENTRY; + +typedef struct _HASHTABLE { + struct _HASHENTRY **table; + int size; +} HASHTABLE, *PHASHTABLE; + +typedef struct _SPAWNMANAGER { +/*0x000*/ void *vftable; +/*0x004*/ DWORD random; // rand()%20000 +/*0x008*/ struct _SPAWNINFO *FirstSpawn; +/*0x00c*/ struct _SPAWNINFO *LastSpawn; +/*0x010*/ DWORD unknown10; +/*0x014*/ struct _HASHTABLE *SPHash; +} SPAWNMANAGER, *PSPAWNMANAGER; + + +#if 0 + +void *gethashedentry(struct _HASHTABLE *table, DWORD key) +{ + PHASHENTRY p = NULL; + p = table->array[key%table->size]; + + while(p) { + if (p->key == key) return p; + p = p->next; + } + return NULL; +} + +#endif + +// this is actually ActorInterface +// actual size: 0x120 3-3-2009 +typedef struct _EQSWITCH { +/*0x00*/ DWORD Unknown0x0[0x2]; +/*0x08*/ float UnknownData0x08; +/*0x0c*/ float UnknownData0x0c; +/*0x10*/ float Unknown0x10[0x2]; +/*0x18*/ float UnknownData0x18; +/*0x1c*/ float Unknown0x1c; +/*0x20*/ float UnknownData0x20; +/*0x24*/ float Unknown0x24; +/*0x28*/ FLOAT Y; +/*0x2c*/ FLOAT X; +/*0x30*/ FLOAT Z; +/*0x34*/ BYTE Unknown0x34[0x50]; //A lot of data here. +/*0x84*/ float yAdjustment1; +/*0x88*/ float xAdjustment1; +/*0x8c*/ float zAdjustment1; +/*0x90*/ float headingAdjustment1; +/*0x94*/ float yAdjustment2; +/*0x98*/ float xAdjustment2; +/*0x9c*/ float zAdjustment2; +/*0xa0*/ float headingAdjustment2; +/*0xa4*/ float yAdjustment3; +/*0xa8*/ float xAdjustment3; +/*0xac*/ float zAdjustment3; +/*0xb0*/ float headingAdjustment3; +/*0xb4*/ FLOAT Y2; +/*0xb8*/ FLOAT X2; +/*0xbc*/ FLOAT Z2; +/*0xc0*/ DWORD Unknown0xa4; +/*0xc4*/ FLOAT Heading; +/*0xc8*/ BYTE Unknown0xc8[0x18]; +/*0xe0*/ float HeightAdjustment; +/*0xe4*/ // more data +} EQSWITCH, *PEQSWITCH; + +// actual size 0xdc 2-9-2009 +typedef struct _DOOR { +/*0x00*/ void *vtable; +/*0x04*/ BYTE Unknown0x4; // always 5 +/*0x05*/ BYTE ID; +/*0x06*/ CHAR Name[0x20]; +/*0x26*/ BYTE Type; +/*0x27*/ BYTE State; // 0 = closed, 1 = open, 2 = opening, 3 = closing +/*0x28*/ FLOAT DefaultY; +/*0x2c*/ FLOAT DefaultX; +/*0x30*/ FLOAT DefaultZ; +/*0x34*/ FLOAT DefaultHeading; +/*0x38*/ FLOAT DefaultDoorAngle; +/*0x3c*/ FLOAT TopSpeed1; +/*0x40*/ FLOAT TopSpeed2; +/*0x44*/ FLOAT Y; +/*0x48*/ FLOAT X; +/*0x4c*/ FLOAT Z; +/*0x50*/ FLOAT Heading; +/*0x54*/ FLOAT DoorAngle; +/*0x58*/ BYTE Unknown0x58[0x18]; +/*0x70*/ int Unknown0x70; // always 0xFFFFFFFF +/*0x74*/ WORD Unknown0x74; // actor scale factor? +/*0x76*/ BYTE Unknown0x76[0x2]; +/*0x78*/ DWORD ZonePoint; +/*0x7c*/ BYTE Unknown0x7c[0x5]; +/*0x81*/ BYTE Unknown0x81; +/*0x82*/ BYTE Unknown0x82[0x22]; +/*0xa4*/ PEQSWITCH pSwitch; // (CActorInterface*) +/*0xa8*/ void *pUnknown0xa8; // (CParticleCloudInterface*) +/*0xac*/ DWORD TimeStamp; +/*0xb0*/ BYTE Unknown0xb0[0x2c]; +/*0xdc*/ +} DOOR, *PDOOR; + +// 7-21-2003 Stargazer +typedef struct _DOORTABLE { +/*0x000*/ DWORD NumEntries; +/*0x004*/ PDOOR pDoor[0x0FF]; +/*0x400*/ +} DOORTABLE, *PDOORTABLE; + +// actual size 0x80 20101012 - ieatacid +typedef struct _GROUNDITEM { +/*0x00*/ struct _GROUNDITEM *pPrev; +/*0x04*/ struct _GROUNDITEM *pNext; +/*0x08*/ DWORD ID; +/*0x0c*/ DWORD DropID; +/*0x10*/ DWORD Unknown0x10; +/*0x14*/ DWORD Unknown0x14; +/*0x18*/ PEQSWITCH pSwitch; // (class EQSwitch *) +/*0x1c*/ CHAR Name[0x20]; +/*0x3c*/ BYTE Unknown0x3c[0x24]; +/*0x60*/ FLOAT Heading; +/*0x64*/ BYTE Unknown0x64[0xc]; +/*0x70*/ FLOAT Y; +/*0x74*/ FLOAT X; +/*0x78*/ FLOAT Z; +/*0x7c*/ BYTE Unknown0x7c[0x4]; +/*0x80*/ +} GROUNDITEM, *PGROUNDITEM; + +#define MAX_ZONES 0x3e8 +extern PCHAR szZoneExpansionName[]; //defined in LibEQ_Utilities.cpp + +typedef struct _ZONELIST { +/*0x000*/ DWORD Header; +/*0x004*/ DWORD Unknown0x4; //pointer to something? +/*0x008*/ DWORD Expansion; // szZoneExpansionName[] +/*0x00c*/ WORD Id; +/*0x00e*/ WORD Instance; +/*0x010*/ CHAR ShortName[0x81]; +/*0x091*/ CHAR LongName[0x103]; +/*0x194*/ DWORD Unknown0x194; +/*0x198*/ DWORD Flags; // (Flags & 0x100000) = HasMinLevel, 0x4000 no air, 0x2 newbie zone, 0x20 no bind, 0x400000 something, 0x80000000 guild hall +/*0x19c*/ DWORD Unknown0x19c; +/*0x1a0*/ DWORD Id2; // This is Id+2242 +/*0x1a4*/ DWORD PoPValue; // This has something to do with PoP zones. +/*0x1a8*/ DWORD MinLevel; // Minimum level to access +/*0x1ac*/ WORD Unknown0x1ac; +/*0x1ae*/ BYTE Unknown0x1ae[0x6]; +/*0x1b4*/ DWORD Unknown0x1b4; +/*0x1b8*/ DWORD Unknown0x1b8; +/*0x1bc*/ DWORD Unknown0x1bc; +/*0x1c0 next zone in list*/ +} ZONELIST, *PZONELIST; + +typedef struct _WORLDDATA { +/*0x000*/ PVOID lpvTable; +/*0x004*/ BYTE Hour; +/*0x005*/ BYTE Minute; +/*0x006*/ BYTE Day; +/*0x007*/ BYTE Month; +/*0x008*/ DWORD Year; +/*0x00C*/ BYTE Unknown0x00c[0x14]; +/*0x020*/ PZONELIST ZoneArray[MAX_ZONES]; +} WORLDDATA, *PWORLDDATA; + +typedef struct _ZONEINFO { +/*0x000*/ CHAR CharacterName[0x40]; +/*0x040*/ CHAR ShortName[0x20]; +/*0x060*/ CHAR Unknown0x060[0x60]; +/*0x0c0*/ CHAR LongName[0x80]; +/*0x140*/ CHAR Unknown0x140[0x96]; // <-- this isnt part of zone name, see CEverQuest__CEverQuest +/*0x1d6*/ BYTE ZoneType; // (usually FF) +/*0x1d7*/ ARGBCOLOR FogRed; +/*0x1db*/ ARGBCOLOR FogGreen; +/*0x1df*/ ARGBCOLOR FogBlue; +/*0x1e3*/ BYTE Unknown0x1e3; +/*0x1e4*/ BYTE Unknown0x1e4[0x10]; +/*0x1f4*/ BYTE Unknown0x1f4[0x10]; +/*0x204*/ FLOAT ZoneGravity; +/*0x208*/ BYTE Unknown0x208; +/*0x209*/ BYTE Unknown0x209[0x3]; +/*0x20c*/ BYTE Unknown0x20c[0x2e]; +/*0x23a*/ BYTE SkyType; +/*0x23b*/ BYTE Unknown0x23b[0xd]; +/*0x248*/ FLOAT ZoneExpModifier; //This has been nerfed ..now reads 1.0 for all zones +/*0x24c*/ FLOAT Unknown0x24c[0x3]; +/*0x258*/ BYTE Unknown0x258[0x4]; +/*0x25c*/ FLOAT Ceiling; +/*0x260*/ FLOAT Floor; +/*0x264*/ FLOAT MinClip; +/*0x268*/ FLOAT MaxClip; +/*0x26c*/ BYTE Unknown0x26c[0x18]; +/*0x284*/ BYTE Unknown0x284[0x20]; +/*0x2a4*/ +} ZONEINFO, *PZONEINFO; + +#define TOTAL_SPELL_COUNT 0xAFC9 // # of spells allocated in memory (06/27/2012) +#define TOTAL_ACTUAL_SPELLS 0x1964 // # of ACTUAL spells in game (9/14/2004) - wrong and unused + +// size: 0x9496C 20120316 +typedef struct _SPELLMGR { +BYTE unknown[0x2C180]; +struct _SPELL* Spells[TOTAL_SPELL_COUNT]; +} SPELLMGR, *PSPELLMGR; + +// actual size: 0x4ed 20120316 - ieatacid +typedef struct _SPELL { +/*0x000*/ FLOAT Range; +/*0x004*/ FLOAT AERange; +/*0x008*/ FLOAT PushBack; +/*0x00c*/ BYTE Unknown0xc[0x4]; +/*0x010*/ DWORD CastTime; +/*0x014*/ DWORD FizzleTime; +/*0x018*/ DWORD RecastTime; +/*0x01c*/ DWORD DurationType; //DurationFormula on Lucy +/*0x020*/ DWORD DurationValue1; +/*0x024*/ BYTE Unknown0x24[0x4]; +/*0x028*/ DWORD Mana; +/*0x02c*/ LONG Base[0x0c]; //Base1-Base12 +/*0x05c*/ LONG Base2[0x0c]; //Mostly unused, setting name to Base2 from Lucy for now +/*0x08c*/ LONG Max[0xc]; //Max1-Max12 +/*0x0bc*/ DWORD ReagentId[0x4]; //ReagentId1-ReagentId4d +/*0x0cc*/ DWORD ReagentCount[0x4]; //ReagentCount1-ReagentCount4 +/*0x0dc*/ BYTE Unknown0xdc[0x10]; +/*0x0ec*/ DWORD Calc[0x0c]; //Calc1-Calc12 +/*0x11c*/ DWORD Attrib[0xc]; //Attrib1-Attrib12 +/*0x14c*/ DWORD BookIcon; +/*0x150*/ BYTE Unknown0x150[0x4]; +/*0x154*/ DWORD DescriptionNumber; +/*0x158*/ DWORD ResistAdj; +/*0x15c*/ BYTE Unknown0x15c[0x4]; +/*0x160*/ DWORD spaindex; +/*0x164*/ DWORD SpellAnim; +/*0x168*/ DWORD SpellIcon; +/*0x16c*/ BYTE Unknown0x16c[0x8]; +/*0x174*/ DWORD ID; +/*0x178*/ DWORD Autocast; //SpellID of spell to instacast on caster when current spell lands on target +/*0x17c*/ DWORD Unknown144; //Unknown144 from lucy +/*0x180*/ DWORD Unknown145; //Unknown145 from lucy +/*0x184*/ BYTE Unknown0x184[0x10]; +/*0x194*/ DWORD EnduranceCost; //CA Endurance Cost +/*0x198*/ DWORD CARecastTimerID; //ID of combat timer, i think. +/*0x19c*/ BYTE Unknown0x19c[0x18]; +/*0x1b4*/ DWORD PvPResistBase; +/*0x1b8*/ BYTE Unknown0x1b8[0x4]; +/*0x1bc*/ DWORD PvPResistCap; +/*0x1c0*/ BYTE Unknown0x1c0[0x4]; +/*0x1c4*/ DWORD Unknown183; //Unknown183 from Lucy +/*0x1c8*/ BYTE Unknown0x1c8[0x6f]; +/*0x237*/ BYTE DurationWindow; //0=Long, 1=Short +/*0x238*/ BYTE Unknown0x238[0x2]; +/*0x23a*/ BYTE Deletable; +/*0x23b*/ BYTE Unknown0x23b[0x6]; +/*0x241*/ BYTE CanMGB; +/*0x242*/ BYTE Unknown0x242[0x5]; +/*0x247*/ BYTE Level[0x10]; //per class. +/*0x257*/ BYTE Unknown0x257[0x13]; +/*0x26a*/ BYTE LightType; +/*0x26b*/ BYTE SpellType; //0=detrimental, 1=Beneficial, 2=Beneficial, Group Only +/*0x26c*/ BYTE Unknown0x26c; +/*0x26d*/ BYTE Resist; //0=un 1=mr 2=fr 3=cr 4=pr 5=dr 6=chromatic 7=prismatic 8=physical(skills,etc) 9=corruption +/*0x26e*/ BYTE TargetType; //03=Group v1, 04=PB AE, 05=Single, 06=Self, 08=Targeted AE, 0e=Pet, 28=AE PC v2, 29=Group v2 +/*0x26f*/ BYTE FizzleAdj; +/*0x270*/ BYTE Skill; +/*0x271*/ BYTE Location; //01=Outdoors, 02=dungeons, ff=Any +/*0x272*/ BYTE Environment; +/*0x273*/ BYTE TimeOfDay; // 0=any, 1=day only, 2=night only +/*0x274*/ BYTE CastingAnim; +/*0x275*/ BYTE Unknown0x275; +/*0x276*/ BYTE TargetAnim; +/*0x277*/ BYTE Unknown0x277[0x3]; +/*0x27a*/ CHAR Name[0x40]; +/*0x2ba*/ CHAR Target[0x20]; +/*0x2da*/ CHAR Extra[0x20]; //This is 'Extra' from Lucy (portal shortnames etc) +/*0x2fa*/ CHAR Unknown0x2fa[0x60]; +/*0x35a*/ CHAR Unknown0x35a[0x60]; +/*0x3ba*/ CHAR CastOnYou[0x60]; +/*0x41a*/ CHAR CastOnAnother[0x60]; +/*0x47a*/ CHAR WearOff[0x60]; +/*0x4da*/ BYTE Unknown0x4da[0x4]; +/*0x4de*/ BYTE Uninterruptable; //00=Interruptable, 01=Uninterruptable +/*0x4df*/ BYTE Unknown0x4df[0xe]; +/*0x4ed*/ +} SPELL, *PSPELL; + +// actual size: 0x148 10-25-2006 ieatacid +typedef struct _SKILL { +/*0x000*/ PVOID pUnknown0x0; //_SKILL *pNext? +/*0x004*/ PVOID pUnknown0x4; +/*0x008*/ DWORD nName; +/*0x00c*/ DWORD ReuseTimer; +/*0x010*/ DWORD Unknown0x10; +/*0x014*/ CHAR AltTimer; //compare to 2 all over.. alternate timer? +/*0x015*/ BYTE Unknown0x15[0x3]; +/*0x018*/ DWORD Unknown0x18; +/*0x01c*/ DWORD Unknown0x1c; +/*0x020*/ bool Activated; +/*0x021*/ CHAR Unknown0x21; +/*0x022*/ BYTE Unknown0x22[0x2]; +/*0x024*/ DWORD MinLevel[0x24]; +/*0x0b4*/ DWORD Available[0x24]; //FF=not available for that class +/*0x144*/ DWORD Unknown0x144; +/*0x148*/ +} SKILL, *PSKILL; + +#define NUM_SKILLS 99 +typedef struct _SKILLMGR { +/*0x000*/ struct _SKILL *pSkill[NUM_SKILLS]; +/*0x004*/ //more data +} SKILLMGR, *PSKILLMGR; + +//actual size 0x3a8 11-15-11 ieatacid +typedef struct _GUILDMEMBER { +/*0x000*/ struct _GUILDMEMBER *pNext; +/*0x004*/ BYTE Online; +/*0x005*/ BYTE Unknown0x5[0x3]; +/*0x008*/ WORD ZoneID; +/*0x00a*/ WORD Instance; +/*0x00c*/ BYTE Unknown0xc[0x5]; +/*0x011*/ CHAR Name[0x40]; +/*0x054*/ DWORD Level; +/*0x058*/ DWORD Flags; //1=banker, 2=alt +/*0x05c*/ DWORD Class; +/*0x060*/ DWORD Rank; //0=member 1=officer 2=leader + +// not updated +#if 0 +/*0x060*/ DWORD LastSeen; //last seen timestamp +/*0x064*/ CHAR PublicNote[0x100];//0x1a0 +/*0x164*/ CHAR PersonalNote[0x100]; +/*0x264*/ DWORD TributeStatus; +/*0x268*/ DWORD TributeDonations; +/*0x26c*/ DWORD LastDonation;//timestamp +/*0x270*/ DWORD Unknown0x270; +/*0x274*/ +#endif +} GUILDMEMBER, *PGUILDMEMBER; + +typedef struct _GUILDDATA +{ +/*0x00*/ char Name[0x40]; +/*0x04*/ DWORD ID; +/*0x08*/ +} GUILDDATA, *PGUILDDATA; + +typedef struct _GUILD +{ +/*0x00*/ struct _GUILDDATA *pGuildData; +/*0x04*/ DWORD ID; +/*0x08*/ _GUILD *pNext; +/*0x0c*/ BYTE Unknown0xc[0xc]; +/*0x18*/ +} GUILD, *PGUILD; + +// 11-15-11 - ieatacid +typedef struct _GUILDS { +/*0x0000*/ PVOID pOneEntryVTable; +/*0x0004*/ BYTE Unknown0x4[0x4]; +/*0x0008*/ DWORD GuildMemberCount; +/*0x000c*/ struct _GUILDMEMBER *pMember; +/*0x0010*/ BYTE Unknown0x10[0x69]; +/*0x0079*/ CHAR GuildMotD[0x200]; +/*0x0279*/ CHAR GuildLeader[0x40]; +/*0x02b9*/ BYTE Unknown0x2b9[0x3]; +/*0x02bc*/ DWORD GuildTribute; +/*0x02c0*/ BYTE Unknown0x2c0[0x8dc6]; +/*0x9086*/ CHAR GuildUrl[0x200]; +/*0x9286*/ CHAR GuildChannelName[0x80]; +/*0x9306*/ BYTE Unknown0x9306[0x1e]; +/*0x9324*/ struct _GUILD **GuildList; +/*0x9328*/ DWORD HashValue; +/* more data */ +} GUILDS, *PGUILDS; + +typedef struct _INTERACTGROUNDITEM { + DWORD DropID; + DWORD SpawnID; +} INTERACTGROUNDITEM, *PINTERACTGROUNDITEM; + +typedef struct _SPELLFAVORITE { +/*0x000*/ DWORD SpellId[NUM_SPELL_GEMS]; +/*0x030*/ CHAR Name[0x19]; +/*0x049*/ BYTE inuse; +/*0x04a*/ BYTE Byte_0x4a; +/*0x04b*/ BYTE Byte_0x4b; +/*0x04c*/ +} SPELLFAVORITE, *PSPELLFAVORITE; + +typedef struct _CMDLIST { + DWORD LocalizedStringID; + PCHAR szName; + PCHAR szLocalized; + VOID (__cdecl *fAddress)(PSPAWNINFO, PCHAR); + DWORD Restriction; + DWORD Category; + DWORD Unknown; +} CMDLIST, *PCMDLIST; + +typedef struct _EQSOCIAL { +/*0x0000*/ CHAR Name[0x10]; +/*0x0010*/ CHAR Line[0x5][0x100]; +/*0x0510*/ BYTE Color; +} EQSOCIAL, *PEQSOCIAL; + +typedef struct _EQFRIENDSLIST { +/*0x0000*/ CHAR Name[0x64][0x40]; +/*0x1900*/ +} EQFRIENDSLIST, *PEQFRIENDSLIST; + +// Size 0xa4 11/15/2011 ieatacid in msg_send_alt_data +typedef struct _ALTABILITY { +/*0x00*/ DWORD Index; +/*0x04*/ DWORD Flags; //? +/*0x08*/ DWORD nShortName; +/*0x0c*/ DWORD nShorterName; +/*0x10*/ DWORD nName; // now a database number +/*0x14*/ DWORD nDesc; // now a database number +/*0x18*/ DWORD MinLevel; +/*0x1c*/ DWORD Cost; //Initial Cost or cost the last time you bought a level of it +/*0x20*/ DWORD ID; // /alt activate id +/*0x24*/ DWORD AARankRequired; +/*0x28*/ DWORD Unknown0x28; +/*0x2c*/ DWORD *RequiresAbility; +/*0x30*/ DWORD Unknown0x30[3]; +/*0x3c*/ DWORD *RequiresAbilityPoints; +/*0x40*/ DWORD Unknown0x40[2]; +/*0x48*/ DWORD Type; +/*0x4c*/ LONG SpellID; // -1 for no Spell +/*0x50*/ DWORD Unknown0x50; +/*0x54*/ BYTE Unknown0x54[0x10]; +/*0x64*/ DWORD ReuseTimer; // in seconds +/*0x68*/ DWORD Classes; // Classes/2 is the actual value we want. +/*0x6c*/ DWORD MaxRank; //If you have not spent points in this +union { //If you have not spent points in this +/*0x70*/ DWORD PointsSpent; //ability, then its PointsToBeSpent (or +/*0x70*/ DWORD PointsToBeSpent; //'Cost', in other words). +}; +/*0x74*/ BYTE Unknown0x74[0x30]; +/*0xa4*/ +} ALTABILITY, *PALTABILITY; +#define zWarp 0 + +typedef struct _ALTABILITIESLISTMGR { +/*0x00*/ struct _ALTABILITY* Ability; +/*0x04*/ DWORD Index; +} ALTABILITIESLISTMGR, *PALTABILITIESLISTMGR; + +//NUM_ALT_ABILITIES is now defined before CHARINFO definition in this same header file. +typedef struct _ALTABILITIESLIST { +/*0x00*/ struct _ALTABILITIESLISTMGR* Abilities[NUM_ALT_ABILITIES_ARRAY]; +} ALTABILITIESLIST, *PALTABILITIESLIST; + +typedef struct _NEWALTADVMGR { +/*0x00*/ struct _ALTABILITIESLIST* AltAbilityList; +/*0x04*/ DWORD NumAltAbilities; // NUM_ALT_ABILITIES +/*0x08*/ DWORD Unknown0x08; // data here +/*0x0c*/ DWORD Unknown0x0c; // data here +/*0x10*/ BYTE Unknown0x10[0x8]; +} NEWALTADVMGR, *PNEWALTADVMGR; + +typedef struct _ALTADVMGR { +/*0x00*/ struct _NEWALTADVMGR* AltAbilities; +} ALTADVMGR, *PALTADVMGR; + +// size 0x94 (3-19-2009) +typedef struct _EQRAIDMEMBER { +/*0x000*/ CHAR Name[0x40]; +/*0x040*/ CHAR RaidNote[0x40]; +/*0x080*/ BYTE nLevel; +/*0x081*/ BYTE nClass; +/*0x082*/ BYTE RaidLeader; +/*0x083*/ BYTE GroupLeader; +/*0x084*/ BYTE RaidMainAssist; +/*0x085*/ BYTE RaidMarker; +/*0x086*/ BYTE RaidWaypointer; +/*0x087*/ BYTE Unknown0x87; +/*0x088*/ DWORD GroupNumber; +/*0x08c*/ BYTE Unknown0x8c[0x8]; +/*0x094*/ +} EQRAIDMEMBER, *PEQRAIDMEMBER; + +// sizeof(_EQRAID) is 0x3668 (12-09-2009) +typedef struct _EQRAID { +/*0x0000*/ BYTE Unknown0x0[0x218]; +/*0x0218*/ CHAR RaidMemberUsed[0x48]; +/*0x0260*/ struct _EQRAIDMEMBER RaidMember[0x48]; +/*0x2c00*/ BYTE Unknown0x2c00[0x4]; +/*0x2c04*/ DWORD RaidMemberCount; +/*0x2c08*/ CHAR RaidLeaderName[0x40]; +/*0x2c48*/ BYTE Unknown0x2b88[0x100]; +/*0x2d48*/ CHAR RaidMOTD[0x400]; +/*0x3148*/ BYTE Unknown0x3148[0x40]; +/*0x3188*/ BYTE Invited; // 1 = default?, 2 = invited, 4 = in raid +/*0x3189*/ BYTE Unknown0x3189[0x8]; +/*0x3191*/ BYTE IsRaidLeader; +/*0x3192*/ BYTE Unknown0x0x30d2[0x2]; +/*0x3194*/ DWORD RaidTarget; +/*0x3198*/ DWORD LootType; +/*0x319c*/ CHAR RaidLooters[0x13][0x40]; +/*0x365c*/ DWORD TotalRaidMemberLevels; // TotalRaidMemberLevels/RaidMemberCount=RaidAvgLevel +/*0x3660*/ BYTE Locked; +/*0x3661*/ BYTE Padding0x35a1[0x7]; +/*0x3668*/ +} EQRAID, *PEQRAID; + +// size 0x19C 3-23-2005 +typedef struct _EQGROUP { +/*0x000*/ BYTE MemberExists[5]; +/*0x005*/ CHAR MemberName[5][0x40]; +/*0x145*/ BYTE Unused[3]; +/*0x148*/ struct _SPAWNINFO* pMember[5]; +/*0x15C*/ CHAR LeaderName[0x40]; +/*0x19C*/ +} EQGROUP, *PEQGROUP; + +// size 0x08 +typedef struct _EQSTRING { +/*0x00*/ DWORD ID; +/*0x04*/ PCHAR String; +} EQSTRING, *PEQSTRING; + +// size 0x10 4-28-2004 lax +typedef struct _EQSTRINGTABLE { +/*0x00*/ struct _EQSTRING **StringItems; +/*0x04*/ DWORD Size; +/*0x08*/ DWORD Count; +/*0x0c*/ DWORD Unknown0x0c; +/*0x10*/ +} EQSTRINGTABLE, *PEQSTRINGTABLE; + +typedef struct connection_t { +/*0x000*/ void *vtable; +/*0x004*/ BYTE Unknown0x4[0x100]; +/*0x104*/ DWORD Master; +/*0x108*/ DWORD Average; +/*0x10c*/ DWORD Low; +/*0x110*/ DWORD High; +/*0x114*/ DWORD Last; +/*0x118*/ +} CONNECTION_T, *PCONNECTION_T; + +//actual size 0x2dfc 3-19-09 - ieatacid +typedef struct _CDISPLAY { +/*0x0000*/ BYTE Unknown0x000[0x12c]; +/*0x012c*/ void *pActorTagManager; +/*0x0130*/ BYTE Unknown0x130[0x24]; +/*0x0154*/ DWORD TimeStamp; +/*0x0158*/ BYTE Unknown0x158[0x2c12]; +/*0x2d6a*/ BYTE NpcNames; // show npc names +} CDISPLAY, *PCDISPLAY; + +//5-16-06 - ieatacid +typedef struct _DZTIMERINFO { +/*0x000*/ CHAR ExpeditionName[0x80]; +/*0x080*/ CHAR EventName[0x100]; +/*0x180*/ DWORD TimeStamp; // TimeStamp - Util__FastTime = time left +/*0x184*/ DWORD TimerID; +/*0x188*/ struct _DZTIMERINFO *pNext; +/*0x18c*/ +} DZTIMERINFO, *PDZTIMERINFO; + +typedef struct _DZMEMBER { +/*0x000*/ CHAR Name[0x40]; +/*0x040*/ DWORD Status; // 0="unknown", 1="Online", 2="Offline", 3="In Dynamic Zone", 4="Link Dead" +/*0x044*/ struct _DZMEMBER *pNext; +/*0x048*/ +} DZMEMBER, *PDZMEMBER; + +typedef struct _TASKMEMBER { +/*0x000*/ CHAR Name[0x40]; +/*0x040*/ DWORD Unknown0x40; +/*0x044*/ DWORD IsLeader; +/*0x048*/ struct _TASKMEMBER *pNext; +/*0x04c*/ +} TASKMEMBER, *PTASKMEMBER; + +typedef struct _DYNAMICZONE { +/*0x000*/ void *vftable; +/*0x004*/ BYTE Unknown0x04[0x46]; +/*0x04a*/ CHAR Name[0x40]; // your name +/*0x08a*/ CHAR ExpeditionName[0x80]; +/*0x10a*/ BYTE Unknown0x10a[0x2]; +/*0x10c*/ WORD MaxPlayers; +/*0x10e*/ BYTE Unknown0x10e[0x2]; +/*0x110*/ struct _DZMEMBER *pMemberList; +/*0x114*/ PCHAR expeditionName; +/*0x118*/ // more? +} DYNAMICZONE, *PDYNAMICZONE; + +typedef struct _CHATCHANNELS { +/*0x000*/ PCHAR ChannelName[0xa]; +/*0x004*/ +} CHATCHANNELS, *PCHATCHANNELS; + +typedef struct _CHATSERVICE { +/*0x000*/ BYTE Unknown0x0[0xc]; +/*0x00c*/ struct _CHATCHANNELS *ChannelList; +/*0x010*/ DWORD ActiveChannels; // number of channels joined +/*0x014*/ BYTE Unknown0x14[0x8]; +/*0x01c*/ CHAR ChatID[0x30]; // "ServerName.CharName" (0x60?) +/*0x04c*/ BYTE Unknown0x4c[0x30]; +/*0x07c*/ CHAR ServerName[0x30]; // "ServerName." +/*0x0b0*/ // more data +} CHATSERVICE, *PCHATSERVICE; + +typedef struct _EVERQUEST { +/*0x000*/ BYTE Unknown[0x2a4]; +/*0x2a4*/ struct _CHATSERVICE *ChatService; +/*0x2a8*/ BYTE Unknown0x2a8[0x8]; +/*0x2b0*/ bool bJoinedChannel; +/*0x2b1*/ CHAR ChannelPlayerName[0x100]; +/*0x3b1*/ CHAR ChannelName[0xa][0x30]; +/*0x591*/ BYTE Unknown0x591[0x3]; +/*0x594*/ DWORD ChannelNumber[0xa]; +/*0x5bc*/ DWORD ChannelQty; +/*0x5c0*/ BYTE Unknown0x5c0[0x8]; +/*0x5c8*/ DWORD GameState; +/*0x5cc*/ // more data +} EVERQUEST, *PEVERQUEST; + +typedef struct _AURAINFO { +/*0x000*/ CHAR Name[0x40]; +/*0x040*/ BYTE Unknown0x14[0xc]; +/*0x04c*/ +} AURAINFO, *PAURAINFO; + +typedef struct _AURAS { +/*0x000*/ _AURAINFO Aura[0x2]; +} AURAS, *PAURAS; + +typedef struct _AURAMGR { +/*0x000*/ DWORD NumAuras; +/*0x004*/ BYTE Unknown0x4[0xc]; +/*0x010*/ _AURAS **pAuraInfo; +/*0x014*/ BYTE Unknown0x14[0x8]; +/*0x01c*/ +} AURAMGR, *PAURAMGR; + +typedef struct _INTERACTSWITCH { +/*0x000*/ DWORD switchID; +/*0x004*/ DWORD dwzero; +/*0x008*/ DWORD dwneg1; +/*0x00c*/ DWORD spawnID; +} INTERACTSWITCH, *PINTERACTSWITCH; + +typedef struct _MERCSTANCEDATA { +DWORD nStance; +DWORD nDbStance; +} MERCSTANCEDATA, *PMERCSTANCEDATA; + +typedef struct _MERCENARYINFO { +/*0x000*/ BYTE Unknown0x0[0x10c]; +/*0x10c*/ DWORD HaveMerc; +/*0x110*/ DWORD MercState; // 1 = suspended, 5 = active +/*0x114*/ BYTE Unknown0x114[0x30]; +/*0x144*/ DWORD ActiveStance; +/*0x148*/ BYTE Unknown0x148[0xf0]; +/*0x238*/ DWORD NumStances; +/*0x23c*/ _MERCSTANCEDATA **pMercStanceData; +} MERCENARYINFO, *PMERCENARYINFO; + +#define MAX_XTARGETS 20 + +enum xTargetTypes +{ + XTARGET_EMPTY_TARGET, + XTARGET_AUTO_HATER, + XTARGET_SPECIFIC_PC, + XTARGET_SPECIFIC_NPC, + XTARGET_TARGETS_TARGET, + XTARGET_GROUP_TANK, + XTARGET_GROUP_TANKS_TARGET, + XTARGET_GROUP_ASSIST, + XTARGET_GROUP_ASSIST_TARGET, + XTARGET_GROUP_PULLER, + XTARGET_GROUP_PULLER_TARGET, + XTARGET_GROUP_MARK1, + XTARGET_GROUP_MARK2, + XTARGET_GROUP_MARK3, + XTARGET_RAID_ASSIST1, + XTARGET_RAID_ASSIST2, + XTARGET_RAID_ASSIST3, + XTARGET_RAID_ASSIST1_TARGET, + XTARGET_RAID_ASSIST2_TARGET, + XTARGET_RAID_ASSIST3_TARGET, + XTARGET_RAID_MARK1, + XTARGET_RAID_MARK2, + XTARGET_RAID_MARK3, + XTARGET_MY_PET, + XTARGET_MY_PET_TARGET, + XTARGET_MY_MERCENARY, + XTARGET_MY_MERCENTARY_TARGET +}; + +// size 0x4c 12-25-09 - ieatacid +typedef struct _XTARGETDATA +{ +/*0x00*/ DWORD xTargetType; +/*0x04*/ DWORD Unknown0x4; +/*0x08*/ DWORD SpawnID; +/*0x0c*/ char Name[0x40]; +/*0x4c*/ +} XTARGETDATA, *PXTARGETDATA; + +typedef struct _XTARGETARRAY +{ + XTARGETDATA pXTargetData[MAX_XTARGETS]; +} XTARGETARRAY, *PXTARGETARRAY; + +// size 0x20 12-25-09 - ieatacid +typedef struct _XTARGETMGR +{ +/*0x00*/ void *vftable; +/*0x04*/ DWORD TargetSlots; // MAX_XTARGETS +/*0x08*/ PXTARGETARRAY pXTargetArray; +/*0x0c*/ DWORD Unknown0xc; // same as TargetSlots? +/*0x10*/ BYTE Unknown0x10[0x4]; +/*0x14*/ BYTE AutoAddHaters; // 1 = auto add haters, 0 = do not auto add haters +/*0x15*/ BYTE Unknown0x15[0x3]; +/*0x18*/ BYTE Unknown0x18[0x4]; +/*0x1c*/ BYTE Unknown0x1c[0x4]; +/*0x20*/ +} XTARGETMGR, *PXTARGETMGR; + +typedef struct _AGGRODATA { +/*0x00*/ DWORD Unknown0x0; +/*0x04*/ BYTE AggroPct; +/*0x05*/ BYTE padding[3]; +/*0x08*/ +} AGGRODATA, *PAGGRODATA; + +// size 0xe4 11-28-12 - ieatacid (in GetAggroInfo) +typedef struct _AGGROINFO { +/*0x00*/ struct _AGGRODATA aggroData[0x1b]; +/*0xd8*/ DWORD AggroLockID; +/*0xdc*/ DWORD AggroTargetID; +/*0xe0*/ DWORD AggroSecondaryID; +/*0xe4*/ +} AGGROINFO, *PAGGROINFO; + +enum AggroDataTypes +{ + AD_Player, + AD_Secondary, + AD_Group1, + AD_Group2, + AD_Group3, + AD_Group4, + AD_Group5, + AD_xTarget1, + AD_xTarget2, + AD_xTarget3, + AD_xTarget4, + AD_xTarget5, + AD_xTarget6, + AD_xTarget7, + AD_xTarget8, + AD_xTarget9, + AD_xTarget10, + AD_xTarget11, + AD_xTarget12, + AD_xTarget13, + AD_xTarget14, + AD_xTarget15, + AD_xTarget16, + AD_xTarget17, + AD_xTarget18, + AD_xTarget19, + AD_xTarget20, +}; + +#define EQ_BEGIN_ZONE 0x600D // CEverQuest__SavePCForce 20130514 +#define EQ_END_ZONE 0x166C // CEverQuest__DoMainLoop+B2F 20130514 +#define EQ_LoadingS__ArraySize 0x5b // EQ_LoadingS__SetProgressBar+8C 12-08-2010 +}; +using namespace EQData; diff --git a/client_files/native_autoloot/eq-core-dll/src/EQDetours.h b/client_files/native_autoloot/eq-core-dll/src/EQDetours.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/client_files/native_autoloot/eq-core-dll/src/EQFunctionDetours.cpp b/client_files/native_autoloot/eq-core-dll/src/EQFunctionDetours.cpp new file mode 100644 index 0000000000..7c019f9db9 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/EQFunctionDetours.cpp @@ -0,0 +1 @@ +#include "EQDetours.h" \ No newline at end of file diff --git a/client_files/native_autoloot/eq-core-dll/src/EQNetworkDetours.cpp b/client_files/native_autoloot/eq-core-dll/src/EQNetworkDetours.cpp new file mode 100644 index 0000000000..8e23bbc9fe --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/EQNetworkDetours.cpp @@ -0,0 +1,15 @@ +#include "EQUtils.h" +#include "EQDetours.h" +#include "MQ2Main.h" + + int __fastcall DetourPetWnd(CXWnd* thisptr) + { + if((DWORD*)thisptr->pvfTable == (DWORD*)0x0065A0A8) + { + thisptr->Show(0,1); + return 0; + } + + thisptr->Show(1,1); + return 0; + } \ No newline at end of file diff --git a/client_files/native_autoloot/eq-core-dll/src/EQUIStructs.h b/client_files/native_autoloot/eq-core-dll/src/EQUIStructs.h new file mode 100644 index 0000000000..aaf1923e8b --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/EQUIStructs.h @@ -0,0 +1,946 @@ +#pragma once +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +namespace EQUIStructs +{ + + +enum UIType +{ + UI_Unknown=-1, + UI_Class=0, + UI_RGB=1, + UI_Point=2, + UI_Size=3, + UI_TextureInfo=4, + UI_Frame=5, + UI_Ui2DAnimation=6, + UI_ButtonDrawTemplate=7, + UI_GaugeDrawTemplate=8, + UI_SpellGemDrawTemplate=9, + UI_FrameTemplate=10, + UI_ScrollbarDrawTemplate=11, + UI_WindowDrawTemplate=12, + UI_SliderDrawTemplate=13, + UI_ScreenPiece=14, + UI_StaticScreenPiece=15, + UI_StaticAnimation=16, + UI_StaticTintedBlendAnimation=17, + UI_StaticText=18, + UI_StaticFrame=19, + UI_StaticHeader=20, + UI_LayoutStrategy=21, + UI_LayoutVertical=22, + UI_LayoutHorizontal=23, + UI_Control=24, + UI_TemplateAssoc=25, + UI_TemplateScreen=26, + UI_ListboxColumn=27, + UI_Listbox=28, + UI_Button=29, + UI_Gauge=30, + UI_SpellGem=31, + UI_HtmlComponent=32, + UI_InvSlot=33, + UI_EditBox=34, + UI_Slider=35, + UI_Label=36, + UI_STMLBox=37, + UI_TreeView=38, + UI_Combobox=39, + UI_Page=40, + UI_TabBox=41, + UI_LayoutBox=42, + UI_HorizontalLayoutBox=43, + UI_VerticalLayoutBox=44, + UI_FinderBox=45, + UI_TileLayoutBox=46, + UI_NamedTemplatePiece=47, + UI_TemplateContainer=48, + UI_Screen=49, + UI_SuiteDefaults=50, + UI_Screens=51, + UI_TopLevelWindowList=52, + UI_HotButton=53, +}; + +// *************************************************************************** +// Structures +// *************************************************************************** + +// 10-24-2003 Lax - Massive overhaul. +// See http://macroquest.sourceforge.net/phpBB2/viewtopic.php?t=3569 for +// standards on structures to make things easier on everyone! +// -- ONLY applies to EQ structs, not MQ structs like alerts, etc. + + + + + +typedef struct _EQCURRENTSELECTION { +/*0x00*/ DWORD Unknown; +/*0x04*/ DWORD SelectedWnd; //address to selection in tree +/*0x08*/ DWORD Unknownlodncrap; +/*0x0c*/ DWORD NumberOfSlots; //merchantslots == 79 +/*0x10*/ DWORD TextureAnim; +/*0x14*/ +} EQCURRENTSELECTION, *PEQCURRENTSELECTION; + +#define VFTABLE \ +/*0x000*/ LPVOID IsValid; \ +/*0x004*/ LPVOID vector_deleting_destructor; \ +/*0x008*/ LPVOID DrawNC; \ +/*0x00c*/ LPVOID PostDraw; \ +/*0x010*/ LPVOID PostDraw2; \ +/*0x014*/ LPVOID DrawCursor; \ +/*0x018*/ LPVOID nullsub0x18; \ +/*0x01c*/ LPVOID PostDraw3; \ +/*0x020*/ LPVOID DrawBackground; \ +/*0x024*/ LPVOID DrawTooltip; \ +/*0x028*/ LPVOID DrawTooltipAtPoint; \ +/*0x02c*/ LPVOID GetMinimizedRect; \ +/*0x030*/ LPVOID DrawTitleBar; \ +/*0x034*/ LPVOID GetCursorToDisplay; \ +/*0x038*/ LPVOID HandleLButtonDown; \ +/*0x03c*/ LPVOID HandleLButtonUp; \ +/*0x040*/ LPVOID HandleLButtonHeld; \ +/*0x044*/ LPVOID HandleLButtonUpAfterHeld; \ +/*0x048*/ LPVOID HandleRButtonDown; \ +/*0x04c*/ LPVOID HandleRButtonUp; \ +/*0x050*/ LPVOID HandleRButtonHeld; \ +/*0x054*/ LPVOID HandleRButtonUpAfterHeld; \ +/*0x058*/ LPVOID HandleWheelButtonDown; \ +/*0x05c*/ LPVOID HandleWheelButtonUp; \ +/*0x060*/ LPVOID HandleMouseMove; \ +/*0x064*/ LPVOID HandleWheelMove; \ +/*0x068*/ LPVOID GetDragDropCursor; \ +/*0x06c*/ LPVOID PostDraw4; \ +/*0x070*/ LPVOID OnDragDrop; \ +/*0x074*/ LPVOID GetClickStickCursor; \ +/*0x078*/ LPVOID QueryDropOK; \ +/*0x07c*/ LPVOID OnClickStick; \ +/*0x080*/ LPVOID GetClickStickCursor2; \ +/*0x084*/ LPVOID QueryClickStickDropOK; \ +/*0x088*/ LPVOID WndNotification; \ +/*0x08c*/ LPVOID Unknown8c; \ +/*0x090*/ LPVOID ShowWindow; /* Activate */ \ +/*0x094*/ LPVOID Deactivate; \ +/*0x098*/ LPVOID PostDraw5; \ +/*0x09c*/ LPVOID OnResize; \ +/*0x0a0*/ LPVOID OnResize2; \ +/*0x0a4*/ LPVOID Unknown0xa4; \ +/*0x0a8*/ LPVOID Unknown0xa8; \ +/*0x0ac*/ LPVOID OnMinimizeBox; \ +/*0x0b0*/ LPVOID Unknown0xb0; \ +/*0x0b4*/ LPVOID OnTileBox; \ +/*0x0b8*/ LPVOID PostDraw6; \ +/*0x0bc*/ LPVOID OnMove2; \ +/*0x0c0*/ LPVOID OnMove3; \ +/*0x0c4*/ LPVOID OnProcessFrame; \ +/*0x0c8*/ LPVOID OnVScroll; \ +/*0x0cc*/ LPVOID OnHScroll; \ +/*0x0d0*/ LPVOID PostDraw7; \ +/*0x0d4*/ LPVOID OnMove4; \ +/*0x0d8*/ LPVOID Show; \ +/*0x0dc*/ LPVOID Unknown0xdc; \ +/*0x0e0*/ LPVOID Unknown0xe0; \ +/*0x0e4*/ LPVOID OnMove5; \ +/*0x0e8*/ LPVOID GetTooltip; \ +/*0x0ec*/ LPVOID HitTest; \ +/*0x0f0*/ LPVOID GetHitTestRect; \ +/*0x0f4*/ LPVOID GetInnerRect; \ +/*0x0f8*/ LPVOID GetClientRect; \ +/*0x0fc*/ LPVOID GetMinSize; \ +/*0x100*/ LPVOID GetMaxSize; \ +/*0x104*/ LPVOID GetUntileSize; \ +/*0x108*/ LPVOID IsPointTransparent; \ +/*0x10c*/ LPVOID Unknown10c; \ +/*0x110*/ LPVOID Unknown110; \ +/*0x114*/ LPVOID Unknown114; \ +/*0x118*/ LPVOID SetDrawTemplate; \ +/*0x11c*/ LPVOID Move_Rect; \ +/*0x120*/ LPVOID Move_Point; \ +/*0x124*/ LPVOID SetWindowTextA; \ +/*0x128*/ LPVOID Unknown0x128; \ +/*0x12c*/ LPVOID Unknown0x12c; \ +/*0x130*/ LPVOID Unknown0x130; \ +/*0x134*/ LPVOID SetVScrollPos; \ +/*0x138*/ LPVOID SetHScrollPos; \ +/*0x13c*/ LPVOID Unknown0x13c; \ +/*0x140*/ LPVOID Unknown0x140; \ +/*0x144*/ LPVOID SetAttributesFromSidl; \ +/*0x148*/ LPVOID nullsub_1; \ +/*0x14c*/ LPVOID Unknown0x14c; \ +/*0x150*/ LPVOID Unknown0x150; \ +/*0x154*/ LPVOID Unknown0x154; \ +/*0x158*/ LPVOID Unknown0x158; \ +/*0x15c*/ LPVOID PostDraw8; \ +/*0x160*/ LPVOID Unknown0x160; \ +/*0x164*/ + +typedef struct _CSIDLWNDVFTABLE { +VFTABLE; +/*0x168*/ LPVOID LoadIniInfo; +/*0x16c*/ LPVOID StoreIniInfo; +/*0x170*/ LPVOID Unknown0x170; +/*0x174*/ LPVOID Unknown0x174; +/*0x178*/ LPVOID Unknown0x178; +/*0x17c*/ +} CSIDLWNDVFTABLE, *PCSIDLWNDVFTABLE; + +typedef struct _CXWNDVFTABLE { +VFTABLE; +} CXWNDVFTABLE, *PCXWNDVFTABLE; + + +#define CXW_NO_VTABLE \ +/*0x004*/ void *pUnknown0x4; \ +/*0x008*/ struct _CSIDLWND *pNextSiblingWnd; \ +/*0x00c*/ void *pUnknown0xc; \ +/*0x010*/ struct _CSIDLWND *pFirstChildWnd; \ +/*0x014*/ BYTE Unknown0x14[0x5]; \ +/*0x019*/ BYTE Alpha; \ +/*0x01a*/ BYTE Enabled; \ +/*0x01b*/ BYTE Unknown0x1b[0x5]; \ +/*0x020*/ BYTE MouseOver; /*found in CXWnd__SetMouseOver_x*/ \ +/*0x021*/ BYTE Unknown0x21[0xc]; \ +/*0x02d*/ BYTE Locked; /*found in CSidlScreenWnd__LoadIniInfo_x*/ \ +/*0x02e*/ BYTE Unknown0x2e[0x32]; \ +/*0x060*/ RECT Location; \ +/*0x070*/ BYTE Unknown0x70[0x10]; \ +/*0x080*/ DWORD FadeDuration; \ +/*0x084*/ DWORD WindowStyle; /* bit 1 - vertical scroll, bit 2 - horizontal scroll, bit 4 - title bar?, bit 8 - border */ \ +/*0x088*/ BYTE Unknown0x88[0x10]; \ +/*0x098*/ BYTE CloseOnESC; /* found in CSidlScreenWnd__StoreIniInfo_x, close when ESC is pressed */ \ +/*0x099*/ BYTE Unknown0x99[0x27]; \ +/*0x0c0*/ RECT OldLocation; \ +/*0x0d0*/ BYTE Unknown0xd0[0x4]; \ +/*0x0d4*/ DWORD TickCount2; \ +/*0x0d8*/ DWORD XMLIndex; \ +/*0x0dc*/ BYTE Unknown0xdc[0xc]; \ +/*0x0e8*/ struct _CXSTR *Tooltip; /*found in CSidlManager__CreateLabel_x*/ \ +/*0x0ec*/ BYTE Unknown0xec[0x4]; \ +/*0x0f0*/ DWORD TimeMouseOver; \ +/*0x0f4*/ BYTE Unknown0xf4[0x2c]; \ +/*0x120*/ DWORD ZLayer; /*found in CXWndManager__DrawWindows_x*/ \ +/*0x124*/ struct _CXSTR *XMLToolTip; /*found in CSidlManager__CreateLabel_x*/ \ +/*0x128*/ ARGBCOLOR BGColor; \ +/*0x12c*/ DWORD UnknownCW; /*found in OnProcessFrame*/\ +/*0x130*/ BYTE Unknown0x130[0x8]; \ +/*0x138*/ BYTE Clickable; /* found in CChatWindow__CChatWindow_x and the button handlers */ \ +/*0x139*/ BYTE Unknown0x139[0x3b]; \ +/*0x174*/ struct _CSIDLWND *pParentWindow; /*CXWnd__IsDescendantOf_x has this one, If this is NULL, coordinates are absolute... */ \ +/*0x178*/ BYTE Unknown0x178[0x4]; \ +/*0x17c*/ DWORD VScrollPos; \ +/*0x180*/ BYTE Unknown0x180[0x8]; \ +/*0x188*/ LPVOID DrawTemplate; \ +/*0x18c*/ BYTE Faded; \ +/*0x18d*/ BYTE Unknown0x18d[0x3]; \ +/*0x190*/ DWORD VScrollMax; \ +/*0x194*/ BYTE ValidCXWnd; /*IsValid has this one*/\ +/*0x195*/ BYTE Unknown0x195; \ +/*0x196*/ BYTE dShow; \ +/*0x197*/ BYTE Unknown0x197; \ +/*0x198*/ DWORD HScrollPos; \ +/*0x19c*/ BYTE Unknown0x19c; \ +/*0x19d*/ BYTE Fades; \ +/*0x19e*/ BYTE Unknown0x19e[0x2]; \ +/*0x1a0*/ DWORD HScrollMax; \ +/*0x1a4*/ BYTE Unknown0x1a4[0x4]; \ +/*0x1a8*/ struct _CXSTR *WindowText; /*CXWnd__GetWindowTextA_x has this one*/ \ +/*0x1ac*/ BYTE Unknown0x1ac[0x2]; \ +/*0x1ae*/ BYTE FadeToAlpha; /*found in CSidlScreenWnd__StoreIniInfo_x*/\ +/*0x1af*/ BYTE Unknown0x1af; \ +/*0x1b0*/ DWORD BGType; /* found in CSidlScreenWnd__StoreIniInfo_x "BGType" in ini */ \ +/*0x1b4*/ BYTE Unknown0x1b4[0x10]; \ +/*0x1c4*/ BYTE Unlockable; /* found in CSidlScreenWnd__LoadIniInfo_x related to Locked */ \ +/*0x1c5*/ BYTE Unknown0x1c5[0x9]; \ +/*0x1ce*/ BYTE Minimized; \ +/*0x1cf*/ BYTE Unknown0x1cf[0x9]; \ +/*0x1d8*/ + +#define CXW \ +/*0x000*/ struct _CXWNDVFTABLE *pvfTable; \ +CXW_NO_VTABLE \ +/*0x1d8*/ + +typedef struct _CXWND { +CXW; +} CXWND, *PCXWND; +#define GateBind 0 + +#define CSW \ +/*0x000*/ struct _CSIDLWNDVFTABLE *pvfTable; \ +CXW_NO_VTABLE; \ +/*0x1d8*/ union { \ + struct _CXSTR *SidlText; /*found in CChatWindow__WndNotification_x*/\ + DWORD Items; \ + }; \ +/*0x1dc*/ union { \ + struct _CXSTR *SidlScreen; \ + DWORD SlotID; \ + }; \ +/*0x1e0*/ LPVOID SidlPiece; /* CScreenPieceTemplate (important) */ \ +/*0x1e4*/ union { /*find in CSidlScreenWnd__dCSidlScreenWnd_x*/ \ + struct { \ + BYTE Checked; \ + BYTE Highlighted; \ + BYTE Unused0x1c8[0x2]; \ + }; \ + DWORD MaxChars; \ + }; \ +/*0x1e8*/ DWORD TextureAnim; \ +/*0x1ec*/ struct _CXSTR * InputText; /*found in CChatWindow__CChatWindow_x*/\ +/*0x1f0*/ DWORD Selector; /*found in CSidlScreenWnd__CSidlScreenWnd1_x*/\ +/*0x1f4*/ DWORD PushToSelector; /*found in CSidlScreenWnd__LoadIniInfo_x*/\ +/*0x1f8*/ DWORD EnableINIStorage; /*found in CSidlScreenWnd__LoadSidlScreen_x*/\ +/*0x1fc*/ union { \ + struct _CXSTR *INIStorageName; /*found in CSidlScreenWnd__LoadSidlScreen_x*/\ + struct _EQINVSLOT *pEQInvSlot; \ + }; \ +/*0x200*/ BYTE Unknown0x200[0x10]; \ +/*0x210*/ LPVOID ContextMenu; /* CTextureAnimation */ \ +/*0x214*/ DWORD Unknown0x214; /* CTextureAnimation */ \ +/*0x218*/ DWORD Unknown0x218; /* CTextureAnimation */ \ +/*0x21c*/ DWORD Unknown0x21c; \ +/*0x220*/ + +typedef struct _CSIDLWND { +CSW; +} CSIDLWND, *PCSIDLWND; + +// size 0x298 09-03-2008 +typedef struct _CSIDLMGR { +/*0x000*/ BYTE Unknown0x000[0x144]; +/*0x144*/ PVOID pXMLDataMgr; +/*0x148*/ BYTE Unknown0x11c[0x150]; +/*0x298*/ +} CSIDLMGR, *PCSIDLMGR; + +//11-6-2003 lax +//Actual size 0x140 11-11-09 - ieatacid +typedef struct _CXWNDMGR { +/*0x000*/ LPVOID CXWNDMGR__vtable; +/*0x004*/ DWORD Count; +/*0x008*/ struct _CSIDLWND **pWindows; +/*0x00c*/ BYTE Unknown0x00C[0x91]; +/*0x09d*/ bool KeyboardFlags[4]; // 7d-80 +/*0x0a1*/ CHAR Unknown0x0a1[0x6b]; +/*0x10c*/ DWORD ScreenExtentX; +/*0x110*/ DWORD ScreenExtentY; +/*0x114*/ DWORD Unknown; +/*0x118*/ DWORD font_list_ptr; +/*0x11c*/ BYTE Unknown0x11c[0x24]; +/*0x140*/ +} CXWNDMGR, *PCXWNDMGR; + + +typedef struct _CONTENTSARRAY { + struct _CONTENTS* Array[1]; +} CONTENTSARRAY, *PCONTENTSARRAY; + +// 20120316 - ieatacid +struct merchdata { +/*0x00*/ void *vftable; +/*0x04*/ BYTE Unknown0x4[0xc]; +/*0x10*/ DWORD MerchSlots; +/*0x14*/ DWORD Unknown0x14; +/*0x18*/ struct _CONTENTSARRAY *pMerchArray; +/*0x1c*/ DWORD MerchMaxSlots; +/*0x20*/ +}; + +struct merch_other { + merchdata *pMerchData; + void *other; + void *other2; +}; + +// size 0x2b0 20130514 - eqmule +typedef struct _EQMERCHWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x220*/ BYTE Unknown0x220[0x0c]; +/*0x22c*/ merch_other *pMerchOther; +/*0x230*/ BYTE Unknown0x230[0x8]; +/*0x238*/ FLOAT Markup;//777026 has this in 04-15-2013 +/*0x23c*/ BYTE Unknown0x23c[0xc]; +/*0x248*/ DWORD SelectedSlotID; +// more data but this is all we need +} EQMERCHWINDOW, *PEQMERCHWINDOW; + + + +// 10-27-2003 Lax +// Actual size 0x208 11-5-2003 +typedef struct _EQCHATMGR +{ +/*0x000*/ struct _EQCHATWINDOW* ChatWnd[0x20]; +/*0x080*/ DWORD NumWindows; +/*0x084*/ DWORD ActiveWindow; // CChat::GetActiveChatWindow +/*0x088*/ DWORD LockedWindow; // CChatManager::GetActiveChatWindow +/*0x08c*/ DWORD Unknown0x08c; +/*0x090*/ struct _EQCHATWINDOW* ChannelMap[0x20]; // channel map +/*0x110*/ BYTE Unknown0x110[0x28]; +/*0x138*/ DWORD Unknown0x138; +/*0x13c*/ DWORD Unknown0x13c; +/*0x140*/ DWORD Unknown0x140; +/*0x144*/ LPVOID ChatMenu; +/*0x148*/ DWORD Unknown0x148; +/*0x14c*/ DWORD Unknown0x14c; +/*0x150*/ DWORD Unknown0x150; +/*0x154*/ DWORD Unknown0x154; +/*0x158*/ LPVOID MeleeMenu; +/*0x15c*/ DWORD Unknown0x15c; +/*0x160*/ LPVOID SpellMenu; +/*0x164*/ DWORD Unknown0x164; +/*0x168*/ DWORD Unknown0x168; +/*0x16c*/ LPVOID ChannelMenu; +/*0x170*/ LPVOID ChatMenu2; +/*0x174*/ LPVOID FilterMenu; +/*0x178*/ DWORD Unknown0x178; +/*0x17c*/ DWORD Unknown0x17c; +/*0x180*/ DWORD Unknown0x180; +/*0x184*/ LPVOID HitsModeMenu; +/*0x188*/ LPVOID MeleeMenu2; +/*0x18c*/ LPVOID HitsModeMenu2; +/*0x190*/ DWORD Unknown0x190; +/*0x194*/ LPVOID HitsModeMenu3; +/*0x198*/ DWORD Unknown0x198; +/*0x19c*/ LPVOID HitsModeMenu4; +/*0x1a0*/ DWORD Unknown0x1a0; +/*0x1a4*/ LPVOID HitsModeMenu5; +/*0x1a8*/ DWORD Unknown0x1a8; +/*0x1ac*/ LPVOID HitsModeMenu6; +/*0x1b0*/ DWORD Unknown0x1b0; +/*0x1b4*/ DWORD Unknown0x1b4; // CChatManager__UpdateTellMenus +/*0x1b8*/ DWORD Unknown0x1b8; +/*0x1bc*/ DWORD Unknown0x1bc; // CChatManager__UpdateTellMenus +/*0x1c0*/ DWORD Unknown0x1c0; +/*0x1c4*/ DWORD Unknown0x1c4; // CChatManager__UpdateTellMenus // raid +/*0x1c8*/ DWORD Unknown0x1c8; +/*0x1cc*/ DWORD Unknown0x1cc; // CChatManager__UpdateTellMenus +/*0x1d0*/ DWORD Unknown0x1d0; // CChatManager__UpdateTellMenus +/*0x1d4*/ DWORD Unknown0x1d4; // CChatManager__UpdateTellMenus +/*0x1d8*/ DWORD Unknown0x1d8; +/*0x1dc*/ DWORD Unknown0x1dc; +/*0x1e0*/ DWORD Unknown0x1e0; +/*0x1e4*/ BYTE Unknown0x1e4[0x1c]; +/*0x200*/ DWORD Unknown0x200; +/*0x204*/ DWORD Unknown0x204; +/*0x208*/ +} EQCHATMGR, *PEQCHATMGR; + +// Actual size 0x26c 02-14-2007 +// 10-27-2003 Lax +typedef struct _EQCHATWINDOW +{ +/*0x000*/ struct _CSIDLWND Wnd; +/*0x214*/ struct _EQCHATMGR *ChatManager; +/*0x218*/ struct _CSIDLWND* InputWnd; +/*0x21c*/ struct _CSIDLWND* OutputWnd; +/*0x220*/ DWORD Unknown0x154; +/*0x224*/ DWORD Unknown0x158; // need to update locations.. +/*0x228*/ BYTE Unknown0x148; +/*0x229*/ BYTE Unknown0x149[0x3f]; +/*0x268*/ DWORD Unknown0x188; +/*0x26c*/ DWORD Unknown0x18c; +/*0x270*/ struct _CXSTR *CommandHistory[0x28]; // ->0x198 +/*0x310*/ DWORD Unknown0x230; // CChatWindow::HistoryBack/forward .. maybe total or current history lines +/*0x314*/ DWORD Unknown0x234; // CChatWindow::HistoryBack/forward .. maybe total or current history lines +/*0x318*/ DWORD FontSize; +/*0x268*/ DWORD Unknown0x23C; +/*0x26c*/ +} EQCHATWINDOW, *PEQCHATWINDOW; + +// in CChatWindow__CChatWindow +#define EQ_CHAT_HISTORY_OFFSET 0x288 +// in CChatWindow__SetChatFont +#define EQ_CHAT_FONT_OFFSET 0x114 + +// Actual size 0x1dc old +// Lax 10-24-2003 +typedef struct _EQBUFFWINDOW +{ +/*0x000*/ struct _CSIDLWND Wnd; +/*0x148*/ BYTE Unknown0x148[0x48]; +/*0x184*/ DWORD pBuff[0x0f]; // CButton* +/*0x1C0*/ DWORD Unknown0x1C0; +/*0x1C4*/ DWORD Unknown0x1C4; +/*0x1C8*/ DWORD Unknown0x1C8; +/*0x1CC*/ DWORD Unknown0x1CC; +/*0x1D0*/ DWORD FirstEffectSlot; //0-15 +/*0x1D4*/ DWORD LastEffectSlot; //0-15 +/*0x1D8*/ DWORD MaxBuffs; // either 0x0F or 0x06 (normal or shortbuffs) +/*0x1DC*/ +} EQBUFFWINDOW, *PEQBUFFWINDOW; + +// actual size 0x294 20120316 - ieatacid +typedef struct _EQINVSLOTWND { +/*0x000*/ struct _CXWND Wnd; //----/ actually CButtonWnd +/*0x1d4*/ BYTE Unknown0x1d4[0x88]; //___/ +/*0x25c*/ DWORD Unknown0x25c; +/*0x260*/ LONG WindowType; // ieatacid has this as InventoryType + // 0 for inventory + // 01 for bank + // 02 for shared bank + // 03 for trader window + // 04 for World/Tradeskill/Combine + // 11 for loot window +/*0x264*/ WORD InvSlotForBag; +/*0x266*/ WORD BagSlot; +/*0x268*/ BYTE Unknown0x268[0x20]; +/*0x288*/ struct _EQINVSLOT *pInvSlot; +/*0x28c*/ BOOL ProcessClick; +/*0x290*/ +} EQINVSLOTWND, *PEQINVSLOTWND; + +// actual size 0x14 10-12-2010 +typedef struct _EQINVSLOT { +/*0x00*/ LPVOID pvfTable; // not based on cxwnd +/*0x04*/ struct _EQINVSLOTWND *pInvSlotWnd; +/*0x08*/ DWORD Unknown0x08; +/*0x0C*/ DWORD InvSlot; +/*0x10*/ BYTE Valid; +/*0x11*/ BYTE Unknown0x11[3]; +/*0x14*/ +} EQINVSLOT, *PEQINVSLOT; + +// actual size 0x2014 10-12-2010 +typedef struct _EQINVSLOTMGR { +/*0x0000*/ DWORD Unknown0x0000; +/*0x0004*/ struct _EQINVSLOT *SlotArray[0x800]; +/*0x2004*/ DWORD TotalSlots; +/*0x2008*/ DWORD Unknown0x2008; +/*0x200c*/ struct _EQINVSLOT *pSelectedItem; +/*0x2010*/ DWORD Unknown0x2010; +/*0x2014*/ +} EQINVSLOTMGR, *PEQINVSLOTMGR; + + +// onetimehero 09-17-03 +// ContainerWindow +// Actual Size 0x17C old +typedef struct _EQCONTAINERWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x148*/ struct _CONTENTS* pContents; // Pointer to the contents of the container; + // Matches the pointer in CHARINFO.Inventory/Bank/World +/*0x14c*/ struct _CSIDLWND* pSlots[0x0a]; +/*0x000*/ struct _CSIDLWND* pCombine; +/*0x168*/ struct _CSIDLWND* pDone; +/*0x16c*/ struct _CSIDLWND* pIcon; +/*0x170*/ struct _CSIDLWND* pUnknown; +/*0x174*/ struct _CSIDLWND* pLabel; +/*0x178*/ BYTE Unknown0x178[4]; +/*0x17c*/ +} EQCONTAINERWINDOW, *PEQCONTAINERWINDOW; + +// Actual Size 0x98 03/15/06 +typedef struct _EQ_CONTAINERWND_MANAGER { +/*0x000*/ DWORD pvfTable; // NOT based on CXWnd. Contains only destructor +/*0x004*/ PEQCONTAINERWINDOW pPCContainers[0x22]; // All open containers, including World, in order of opening... +/*0x08c*/ PCONTENTS pWorldContents; // Pointer to the contents of the world If NULL, world container isn't open; +/*0x090*/ DWORD dwWorldContainerID; // ID of container in zone, starts at one (zero?) and goes up. +/*0x094*/ DWORD dwTimeSpentWithWorldContainerOpen; // Cumulative counter? +/*0x078*/ +} EQ_CONTAINERWND_MANAGER, *PEQ_CONTAINERWND_MANAGER; + +typedef struct _POINT3 { + FLOAT X; + FLOAT Y; + FLOAT Z; +} POINT3, *PPOINT3; + +// plazmic 08-17-03 +// Map Window +typedef struct _MAPLABEL { // sizeof() = 0x38 +/*0x00*/ DWORD Unknown0x0; +/*0x04*/ struct _MAPLABEL *pNext; +/*0x08*/ struct _MAPLABEL *pPrev; +/*0x0c*/ POINT3 Location; +/*0x18*/ ARGBCOLOR Color; +/*0x1c*/ DWORD Size; //1-3; +/*0x20*/ PCHAR Label; +/*0x24*/ DWORD Layer; //0-3; +/*0x28*/ DWORD Width; +/*0x2c*/ DWORD Height; +/*0x30*/ DWORD unk_0x2c; +/*0x34*/ DWORD unk_0x30; +} MAPLABEL, *PMAPLABEL; + +typedef struct _MAPLINE { // sizeof() = 0x28 (think this might be 0x34 now) + struct _MAPLINE *pNext; + struct _MAPLINE *pPrev; + POINT3 Start; + POINT3 End; + ARGBCOLOR Color; + DWORD Layer; //0-3; +} MAPLINE, *PMAPLINE; + +// size 0x3a8 20130514 - eqmule +typedef struct _EQLOOTWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x220*/ void *vftable; // for CLootWnd::DialogResponse handler +/*0x224*/ BYTE Unknown0x224[0x9c]; +/*0x2c0*/ DWORD NumOfSlots; +/*0x2c4*/ DWORD Unknown0x2c4; +/*0x2c8*/ struct _INVENTORYARRAY *pInventoryArray; +/*0x2cc*/ DWORD NumOfSlots2; +/*0x2d0*/ DWORD NumOfSlots3; +/*0x2d4*/ BYTE Unknown0x2d4[0x24]; +/*0x2f8*/ BYTE Unknown0x2f8; +/*0x2f9*/ BYTE Unknown0x2f9; +/*0x2fa*/ BYTE Unknown0x2fa; +/*0x2fb*/ BYTE Unknown0x2fb; +/*0x2fc*/ struct _CSIDLWND *CLoot_LootInvWnd; +/*0x300*/ struct _CSILDWND *CLoot_LootSlotWnd[0x22]; +/*0x388*/ struct _CSIDLWND *CLoot_CorpseName; +/*0x38c*/ struct _CSIDLWND *CLoot_DoneButton; +/*0x390*/ struct _CSIDLWND *CLoot_BroadcastButton; +/*0x394*/ struct _CSIDLWND *CLoot_LootAllButton; +/*0x398*/ BYTE Unknown0x398[0x10]; +/*0x3a8*/ +} EQLOOTWINDOW, *PEQLOOTWINDOW; + +//Size: 0x920 20130514 - ieatacid +typedef struct _EQPETINFOWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x220*/ BYTE Unknown0x21c[0x14]; +/*0x234*/ struct _CBUTTONWND *pButton[0xe]; +/*0x26c*/ BYTE Unknown0x26c[0x1dc]; +/*0x448*/ struct _CSIDLWND *pWnd[NUM_BUFF_SLOTS]; // buff icons? +/*0x5cc*/ int Buff[NUM_BUFF_SLOTS]; // Spell ID# of each buff -- 85 total +/*0x750*/ BYTE Unknown0x750[0x20]; +/*0x770*/ DWORD BuffFadeETA[NUM_BUFF_SLOTS]; // duration until buff fades, in thousands of a second +/*0x8f4*/ BYTE Unknown0x8f4[0x2c]; +/*0x920*/ +} EQPETINFOWINDOW, *PEQPETINFOWINDOW; + +typedef struct _EQTRADESKILLRECIPE { +/*0x00*/ DWORD Unknown0x00; +/*0x04*/ DWORD Trivial; +/*0x08*/ DWORD Unknown0x08; +/*0x0c*/ DWORD Unknown0x0c; +/*0x10*/ DWORD Unknown0x10; +/*0x14*/ CHAR Name[0x40]; +/*0x54*/ DWORD Unknown0x54; +/*0x58*/ DWORD Ingredient[0xa]; // ID# of ingredient(s) +/*0x80*/ DWORD IngredientIcon[0xa]; //Icon# of ingredient(s) (Note: 499 is blank) +} EQTRADESKILLRECIPE, *PEQTRADESKILLRECIPE; + +//Size 0x3d8 (02/10/2004) +typedef struct _EQTRADESKILLWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x148*/ DWORD Unknown0x148[0x1b]; +/*0x1b4*/ PEQTRADESKILLRECIPE SearchResults[0x64]; +/*0x344*/ DWORD Unknown0x344; +/*0x348*/ DWORD Unknown0x348; +/*0x34c*/ DWORD Unknown0x34c; +/*0x350*/ PCONTENTS Container; +/*0x354*/ DWORD Unknown0x354; +/*0x358*/ PEQTRADESKILLRECIPE SelectedRecipe; +/*0x35c*/ DWORD Unknown0x35c; +/*0x360*/ DWORD SkillLevel; +/*0x364*/ DWORD Unknown0x364; +/*0x368*/ DWORD Unknown0x368; +/*0x36c*/ BYTE Unknown0x36c[0x58]; +/*0x3c4*/ DWORD Unknown0x3c4; +/*0x3c8*/ DWORD Unknown0x3c8; +/*0x3cc*/ BYTE Unknonw0x3cc[0x8]; +/*0x3d4*/ DWORD Unknown0x3d4; +/*0x3d8*/ DWORD Unknown0x3d8; +} EQTRADESKILLWINDOW, *PTRADESKILLWINDOW; + +//Actual Size 0x308 - 20130514 - eqmule +typedef struct _EQTRADEWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x220*/ BYTE Unknown0x220[0xd8]; +/*0x2f8*/ BYTE HisTradeReady; +/*0x2f9*/ BYTE MyTradeReady; +/*0x300*/ BYTE TradeWndOpen; +/*0x301*/ BYTE Unknown0x301[0x7]; +/*0x308*/ +} EQTRADEWINDOW, *PTRADEWINDOW; + +//Actual Size: 0x388 20121016 - ieatacid +typedef struct _EQRAIDWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x214*/ BYTE Unknown0x214[0xb8]; +/*0x2cc*/ DWORD ClassColors[0x10]; +/*0x30c*/ BYTE Unknown0x30c[0x7c]; +/*0x388*/ +} EQRAIDWINDOW, *PEQRAIDWINDOW; + +typedef struct _GUILDMEMBERINFO { +/*0x000*/ DWORD Unknown0x000; //pointer? +/*0x004*/ BYTE OnlineStatus; // 00=offline, 01=online +/*0x005*/ BYTE UnknownData0x005; +/*0x006*/ BYTE UnknownData0x006; +/*0x007*/ BYTE Unknown0x007; +/*0x008*/ BYTE Unknown0x008[0x8]; +/*0x010*/ CHAR Name[0x40]; +/*0x050*/ DWORD Level; +/*0x054*/ DWORD Class; +/*0x058*/ DWORD Rank; //0=member, 1=officer, 2=leader +/*0x05c*/ FLOAT UnknownData0x05c; +/*0x060*/ CHAR PublicNote[0x80]; +/*0x0e0*/ BYTE Unknown0x0e0[0x180]; +/*0x260*/ WORD UnknownData0x260; +/*0x262*/ WORD UnknownData0x262; +/*0x264*/ WORD UnknownData0x264; +/*0x266*/ WORD UnknownData0x266; +} GUILDMEMBERINFO, *PGUILDMEMBERINFO; + +//Size: 0x3d0 (02/18/2004) +typedef struct _EQGUILDWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x148*/ BYTE Unknown0x148[0x4c]; +/*0x194*/ BYTE Unknown0x194; +/*0x195*/ BYTE ShowOffline; // 01 = show offline box is checked +/*0x196*/ BYTE Unknown0x196[0x2]; +/*0x198*/ struct _GUILDMEMBERINFO **pMember; // This is a pointer to the beginning of a list of pointers, + // each representing one player in the guild. The number of + // pointers depends upon TotalMemberCount. +/*0x19c*/ DWORD TotalMemberCount; +/*0x1a0*/ DWORD Unknown0x1a0; // 150? +/*0x1a4*/ DWORD Unknown0x1a4; // 1? +/*0x1a8*/ DWORD TotalMemberCountAgain; +/*0x1ac*/ BYTE Unknown0x1ac[0x1c]; +/*0x1c8*/ CHAR PersonalNotesFilePath[0x40]; // path to personal notes file +/*0x208*/ BYTE Unknown0x208[0x1c0]; // empty +/*0x3c8*/ DWORD Unknown0x3c8; // 1? +/*0x3cc*/ DWORD Unknown0x3cc; // some sort of bizaare pointer... +/*0x3d0*/ +} EQGUILDWINDOW, *PEQGUILDWINDOW; + +typedef struct _EQNOTESWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x148*/ BYTE Unknown0x148[0x04]; +/*0x14c*/ struct _CSIDLWND *pEditWnd; +} EQNOTESWINDOW, *PEQNOTESWINDOW; + +// Lax 10-29-2003 +// Actual size 0x5dc 20121212 - ieatacid +typedef struct _EQITEMWINDOW +{ +/*0x000*/ struct _CSIDLWND Wnd; +/*0x21c*/ struct _CSIDLWND *DisplayWnd; +/*0x220*/ BYTE Unknown0x220[0x70]; +/*0x290*/ PCXSTR ItemInfo; +/*0x294*/ PCXSTR WindowTitle; +/*0x298*/ PCXSTR Unknown0x298; // possibly PCXSTR of information as on charms +/*0x29c*/ DWORD Unknown0x29c; +/*0x2a0*/ DWORD Unknown0x2a0; +/*0x2a4*/ PCXSTR UnknownCXStr; // if this is NULL don't populate item data in MQ2ItemDisplay +/*0x2a8*/ PCXSTR Unknown0x2a8; +/*0x2ac*/ PCONTENTS pItem; +/*0x29c*/ PVOID TextureAnim; +/*0x2a0*/ PVOID TextureAnim2; +/*0x2a4*/ BYTE Unknown0x2a4[0x4c]; +/*0x2f0*/ DWORD IDW_ItemInfo_Num_Lines; +/*0x2f4*/ struct _CSIDLWND *IDW_ItemInfo[0xc]; +// pointers to stat labels, etc, in this area +} EQITEMWINDOW, *PEQITEMWINDOW; + +// Actual size 0x1c8 07-09-2008 +typedef struct _EQSPELLINFOWINDOW +{ +/*0x000*/ struct _CSIDLWND Wnd; +/*0x208*/ PVOID Unknown0x190; +/*0x20c*/ PVOID Unknown0x194; +/*0x210*/ struct _CSIDLWND *DisplayWnd; +/*0x214*/ PVOID Unknown0x19c; +/*0x218*/ PVOID Unknown0x1a0; +/*0x21c*/ PCXSTR ItemInfo; +/*0x220*/ PVOID Unknown0x1a8; +/*0x224*/ DWORD Unknown0x1ac; +/*0x228*/ DWORD Unknown0x1b0; +/*0x22c*/ DWORD Unknown0x1b4; +/*0x230*/ DWORD Unknown0x1b8; +/*0x234*/ PVOID TextureAnim; +/*0x238*/ DWORD SpellID; +/*0x23c*/ DWORD TimeStamp; +/*0x240*/ +} EQSPELLINFOWINDOW, *PEQSPELLINFOWINDOW; + +// Size: 0x1a4 (4/14/2005) +typedef struct _EQMAILWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x158 Finish... */ +} EQMAILWINDOW, *PEQMAILWINDOW; + + +// Actual Size 0x624 20130514 - ieatacid/eqmule +typedef struct _EQMAPWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x220*/ BYTE Unknown0x220[0x40]; +/*0x260*/ CHAR shortzonename[0x20]; +/*0x280*/ BYTE Unknown0x280[0x9c]; +/*0x31c*/ struct _CXWND *wnd; // MVW_MapRenderArea +/*0x320*/ BYTE Unknown0x320[0x38]; +/*0x358*/ struct _CSIDLWNDVFTABLE *pMapViewMapVfTable; // start of MapViewMap +/*0x35c*/ BYTE Unknown0x35c[0x24c]; +/*0x5a8*/ PMAPLINE pLines; //0x250 +/*0x5ac*/ PMAPLABEL pLabels; //0x254 +/*0x5b0*/ BYTE Unknown0x5b0[0x74]; +/*0x624*/ +} EQMAPWINDOW, *PEQMAPWINDOW; + +// ieatacid 20120316 +// Spell Window +typedef struct _EQCASTSPELLWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x214*/ BYTE Unknown0x214[0x14]; +/*0x228*/ struct _EQCASTSPELLGEM *SpellSlots[NUM_SPELL_GEMS]; +/*0x258*/ BYTE Unknown0x258[0x30]; +/*0x288*/ +} EQCASTSPELLWINDOW, *PEQCASTSPELLWINDOW; + +// Individual Gems +typedef struct _EQCASTSPELLGEM { +/*0x000*/ struct _CXWND Wnd; +/*0x1cc*/ BYTE Unknown0x1cc[0x44]; +/*0x210*/ DWORD TimeStamp; +/*0x214*/ DWORD RecastTime; +/*0x218*/ BYTE Unknown0x218[0xa8]; +/*0x2c0*/ DWORD spellicon; //if this is equal to FFFFFFFF there is no spell memmed in this slot... +/*0x2c4*/ DWORD spellstate; // 1 = cast in progress or refreshtime not met 2 means we ducked or aborted cast, 0 means its ok to cast +/*0x2c8*/ BYTE Unknown0x2c8[0x18]; +/*0x2e0*/ +} EQCASTSPELLGEM, *PEQCASTSPELLGEM; +#define Fly 0 + +// Actual size 0x1c4 10-9-2003 +typedef struct _EQHOTBUTTONWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x148*/ BYTE Unknown0x138[0xc]; +/*0x000*/ DWORD HotButtonWndView; //0 to 9 for the different views +/*0x14c*/ struct _CSIDLWND *HotButtons[0x0a];//these will change when you switch page... +/*0x174*/ +} EQHOTBUTTONWINDOW, *PEQHOTBUTTONWINDOW; + +typedef struct _LOOTCORPSE { +/*0x000*/ BYTE Unknown0x000; // 03 seems very common (for NPC anyway) +/*0x001*/ CHAR Name[0x4b]; +/*0x04c*/ FLOAT Timer; //Uncertain the equation used here, but fairly certain it's the timer +/*0x050*/ FLOAT X; +/*0x054*/ BYTE Unknown0x054[0x4]; +/*0x058*/ FLOAT Y; +/*0x05c*/ FLOAT Z; +/*0x060*/ BYTE Unknown0x060[0x24]; +/*0x084*/ DWORD Flags; +/*0x088*/ BYTE Unknown0x088[0x4]; +/*0x08c*/ DWORD Unknown0x08c; //256 seems very common +/*0x090*/ +// I think there might be pointers at 0x0e0..but no clue what to +} LOOTCORPSE, *PLOOTCORPSE; + +// size 0x180 3-10-2004 +typedef struct _EQCOMPASSWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x148*/ struct _CSIDLWND *pStrip1; +/*0x14C*/ struct _CSIDLWND *pStrip2; +// in progress. +/*0x16C*/ BOOL DrawLine; +/*0x170*/ DWORD Unknown0x170; +/*0x174*/ DWORD LineRed; +/*0x178*/ DWORD LineGreen; +/*0x17C*/ DWORD LineBlue; +/*0x180*/ +} EQCOMPASSWINDOW, *PEQCOMPASSWINDOW; + +// used by options window +typedef struct _EQKBASSIGN +{ +/*0x00*/ struct _CXSTR *pDescription; +/*0x04*/ DWORD nAssignmentNumber; +/*0x08*/ +} EQKBASSIGN, *PEQKBASSIGN; + +// size 0x904 3-10-2004 +typedef struct _EQOPTIONSWINDOW { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x148*/ + +/*0x264*/ struct _EQKBASSIGN Binds[0xA1]; +/*0x508*/ + +/*0x904*/ +} EQOPTIONSWINDOW, *PEQOPTIONSWINDOW; + +// size 0x28 4-24-2004 Lax +typedef struct _EQGRAPHICSENGINE { +/*0x00*/ // Graphics file handler +/*0x04*/ +} EQGRAPHICSENGINE, *PEQGRAPHICSENGINE; +#define SafeXLoc 0 + +typedef struct _CBUTTONWND { +/*0x000*/ struct _CXWND Wnd; +/*0x1c4*/ BYTE Unknown[0x4]; +/*0x1c8*/ BYTE State; //1=down 0=up +/*0x1c9*/ BYTE Unknown0x1c9; //something to do with State +/*0x1ca*/ BYTE Unknown0x1ca[0x12]; +/*0x1dc*/ ARGBCOLOR Color; +/*0x1e0*/ +} CBUTTONWND, *PCBUTTONWND; + +typedef struct _CTEXTENTRYWND { +/*0x000*/ struct _CXWND Wnd; +/*0x1c4*/ DWORD CursorPos1; +/*0x13c*/ DWORD CursorPos2; //same as above but only this needs to be set to update cursor position +/*0x140*/ +} CTEXTENTRYWND, *PCTEXTENTRYWND; + +// size 0x2c8 20121128 - ieatacid +typedef struct _CPLAYERWND { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x214*/ BYTE Unknown[0xb0]; +/*0x2c4*/ DWORD CombatState; // 1=debuffed, 2=combat cooldown, 3=stand, 4=sit +/* more data */ +} CPLAYERWND, *PCPLAYERWND; + +// size 0x87c 20120316 - ieatacid +typedef struct _CTARGETWND { +/*0x000*/ struct _CSIDLWND Wnd; +/*0x208*/ BYTE Unknown0x198[0x198]; +/*0x3a0*/ struct _CBUTTONWND *pBuff[NUM_BUFF_SLOTS]; // buff icons + +/*0x524*/ int BuffSpellID[NUM_BUFF_SLOTS]; // 0xffffffff if no buff +/*0x6a8*/ DWORD BuffTimer[NUM_BUFF_SLOTS]; +/*0x82c*/ BYTE Unknown0x6f8[0x24]; +/*0x850*/ DWORD Type; // 1 = self, 4 = group member, 5 = PC, 7 = NPC +/*0x850*/ BYTE Unknown0x720[0x2c]; +/*0x87c*/ +} CTARGETWND, *PCTARGETWND; + +typedef struct _CLABELWND { +/*0x000*/ struct _CXWND Wnd; +/*0x1c4*/ BYTE Unknown[0x8]; +/*0x1cc*/ DWORD SidlPiece; +/*0x1d0*/ +} CLABELWND, *PCLABELWND; + +// size 0x92c8 20130417 - ieatacid +typedef struct _BAZAARSEARCHWND { +/*0x0000*/ struct _CSIDLWND Wnd; +/*0x022c*/ BYTE Unknown0x22c[0x8ff8]; +/*0x9224*/ void **ppTraderData; +/*0x9228*/ DWORD hashVal; +/* more data */ +} BAZAARSEARCHWND, *PBAZAARSEARCHWND; + +}; + +using namespace EQUIStructs; diff --git a/client_files/native_autoloot/eq-core-dll/src/EQUtils.cpp b/client_files/native_autoloot/eq-core-dll/src/EQUtils.cpp new file mode 100644 index 0000000000..b157733451 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/EQUtils.cpp @@ -0,0 +1,15 @@ +#include "EQUtils.h" + +void PatchBytes( void * lpAddress, const char * szBytes, int nLen ) +{ + // Needed by VirtualProtect. + DWORD dwBack = 0; + VirtualProtect( lpAddress, nLen, PAGE_READWRITE, &dwBack ); + + // Write Byte-After-Byte. + for( int i = 0; i < nLen; i++ ) + *( BYTE * )( ( DWORD )lpAddress + i ) = szBytes[ i ]; + + // Restore old protection. + VirtualProtect( lpAddress, nLen, dwBack, &dwBack ); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/EQUtils.h b/client_files/native_autoloot/eq-core-dll/src/EQUtils.h new file mode 100644 index 0000000000..0f45830cbd --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/EQUtils.h @@ -0,0 +1,6 @@ +#ifndef EQ_U_H +#define EQ_U_H +#include + +void PatchBytes( void * lpAddress, const char * szBytes, int nLen ); +#endif \ No newline at end of file diff --git a/client_files/native_autoloot/eq-core-dll/src/FPSLimit.cpp b/client_files/native_autoloot/eq-core-dll/src/FPSLimit.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/client_files/native_autoloot/eq-core-dll/src/IClassFactory.cpp b/client_files/native_autoloot/eq-core-dll/src/IClassFactory.cpp new file mode 100644 index 0000000000..97851522ea --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IClassFactory.cpp @@ -0,0 +1,80 @@ +/** +* Copyright (C) 2019 Elisha Riedlinger +* +* This software is provided 'as-is', without any express or implied warranty. In no event will the +* authors be held liable for any damages arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you wrote the +* original software. If you use this software in a product, an acknowledgment in the product +* documentation would be appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as +* being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "dinput8.h" + +/************************/ +/*** IUnknown methods ***/ +/************************/ + +HRESULT m_IClassFactory::QueryInterface(REFIID riid, LPVOID FAR * ppvObj) +{ + if ((riid == IID_IClassFactory || riid == IID_IUnknown) && ppvObj) + { + AddRef(); + + *ppvObj = this; + + return S_OK; + } + + HRESULT hr = ProxyInterface->QueryInterface(riid, ppvObj); + + if (SUCCEEDED(hr)) + { + genericQueryInterface(riid, ppvObj); + } + + return hr; +} + +ULONG m_IClassFactory::AddRef() +{ + return ProxyInterface->AddRef(); +} + +ULONG m_IClassFactory::Release() +{ + ULONG ref = ProxyInterface->Release(); + + if (ref == 0) + { + delete this; + } + + return ref; +} + +/*****************************/ +/*** IClassFactory methods ***/ +/*****************************/ + +HRESULT m_IClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) +{ + HRESULT hr = ProxyInterface->CreateInstance(pUnkOuter, riid, ppvObject); + + if (SUCCEEDED(hr)) + { + genericQueryInterface(riid, ppvObject); + } + + return hr; +} + +HRESULT m_IClassFactory::LockServer(BOOL fLock) +{ + return ProxyInterface->LockServer(fLock); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/IClassFactory.h b/client_files/native_autoloot/eq-core-dll/src/IClassFactory.h new file mode 100644 index 0000000000..6910989719 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IClassFactory.h @@ -0,0 +1,26 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN +#include + +typedef void(WINAPI *IQueryInterfaceProc)(REFIID, LPVOID *); + +class m_IClassFactory : public IClassFactory +{ +private: + IClassFactory *ProxyInterface; + REFIID WrapperID = IID_IClassFactory; + +public: + m_IClassFactory(IClassFactory *aOriginal) : ProxyInterface(aOriginal) {} + ~m_IClassFactory() {} + + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj); + STDMETHOD_(ULONG, AddRef) (THIS); + STDMETHOD_(ULONG, Release) (THIS); + + /*** IClassFactory methods ***/ + STDMETHOD(CreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObject); + STDMETHOD(LockServer)(BOOL fLock); +}; diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInput8A.cpp b/client_files/native_autoloot/eq-core-dll/src/IDirectInput8A.cpp new file mode 100644 index 0000000000..e9cc8c7256 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInput8A.cpp @@ -0,0 +1,111 @@ +/** +* Copyright (C) 2019 Elisha Riedlinger +* +* This software is provided 'as-is', without any express or implied warranty. In no event will the +* authors be held liable for any damages arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you wrote the +* original software. If you use this software in a product, an acknowledgment in the product +* documentation would be appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as +* being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "dinput8.h" + +HRESULT m_IDirectInput8A::QueryInterface(REFIID riid, LPVOID * ppvObj) +{ + if ((riid == IID_IDirectInput8A || riid == IID_IUnknown) && ppvObj) + { + AddRef(); + + *ppvObj = this; + + return S_OK; + } + + HRESULT hr = ProxyInterface->QueryInterface(riid, ppvObj); + + if (SUCCEEDED(hr)) + { + genericQueryInterface(riid, ppvObj); + } + + return hr; +} + +ULONG m_IDirectInput8A::AddRef() +{ + return ProxyInterface->AddRef(); +} + +ULONG m_IDirectInput8A::Release() +{ + ULONG ref = ProxyInterface->Release(); + + if (ref == 0) + { + delete this; + } + + return ref; +} + +HRESULT m_IDirectInput8A::CreateDevice(REFGUID rguid, LPDIRECTINPUTDEVICE8A *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) +{ + HRESULT hr = ProxyInterface->CreateDevice(rguid, lplpDirectInputDevice, pUnkOuter); + + if (SUCCEEDED(hr) && lplpDirectInputDevice) + { + *lplpDirectInputDevice = ProxyAddressLookupTable.FindAddress(*lplpDirectInputDevice); + } + + return hr; +} + +HRESULT m_IDirectInput8A::EnumDevices(DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) +{ + return ProxyInterface->EnumDevices(dwDevType, lpCallback, pvRef, dwFlags); +} + +HRESULT m_IDirectInput8A::GetDeviceStatus(REFGUID rguidInstance) +{ + return ProxyInterface->GetDeviceStatus(rguidInstance); +} + +HRESULT m_IDirectInput8A::RunControlPanel(HWND hwndOwner, DWORD dwFlags) +{ + return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); +} + +HRESULT m_IDirectInput8A::Initialize(HINSTANCE hinst, DWORD dwVersion) +{ + return ProxyInterface->Initialize(hinst, dwVersion); +} + +HRESULT m_IDirectInput8A::FindDevice(REFGUID rguidClass, LPCSTR ptszName, LPGUID pguidInstance) +{ + return ProxyInterface->FindDevice(rguidClass, ptszName, pguidInstance); +} + +HRESULT m_IDirectInput8A::EnumDevicesBySemantics(LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat, LPDIENUMDEVICESBYSEMANTICSCBA lpCallback, LPVOID pvRef, DWORD dwFlags) +{ + if (!lpCallback) + { + return E_INVALIDARG; + } + + ENUMDEVICEA CallbackContext; + CallbackContext.pvRef = pvRef; + CallbackContext.lpCallback = lpCallback; + + return ProxyInterface->EnumDevicesBySemantics(ptszUserName, lpdiActionFormat, m_IDirectInputEnumDevice::EnumDeviceCallbackA, &CallbackContext, dwFlags); +} + +HRESULT m_IDirectInput8A::ConfigureDevices(LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSA lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) +{ + return ProxyInterface->ConfigureDevices(lpdiCallback, lpdiCDParams, dwFlags, pvRefData); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInput8A.h b/client_files/native_autoloot/eq-core-dll/src/IDirectInput8A.h new file mode 100644 index 0000000000..82447ee9ae --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInput8A.h @@ -0,0 +1,34 @@ +#pragma once + +class m_IDirectInput8A : public IDirectInput8A, public AddressLookupTableObject +{ +private: + IDirectInput8A *ProxyInterface; + +public: + m_IDirectInput8A(IDirectInput8A *aOriginal) : ProxyInterface(aOriginal) + { + ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); + } + ~m_IDirectInput8A() + { + ProxyAddressLookupTable.DeleteAddress(this); + } + + IDirectInput8A *GetProxyInterface() { return ProxyInterface; } + + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj); + STDMETHOD_(ULONG, AddRef)(THIS); + STDMETHOD_(ULONG, Release)(THIS); + + /*** IDirectInput8A methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID, LPDIRECTINPUTDEVICE8A *, LPUNKNOWN); + STDMETHOD(EnumDevices)(THIS_ DWORD, LPDIENUMDEVICESCALLBACKA, LPVOID, DWORD); + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID); + STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); + STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD); + STDMETHOD(FindDevice)(THIS_ REFGUID, LPCSTR, LPGUID); + STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCSTR, LPDIACTIONFORMATA, LPDIENUMDEVICESBYSEMANTICSCBA, LPVOID, DWORD); + STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK, LPDICONFIGUREDEVICESPARAMSA, DWORD, LPVOID); +}; diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInput8Hook.cpp b/client_files/native_autoloot/eq-core-dll/src/IDirectInput8Hook.cpp new file mode 100644 index 0000000000..3378bba1c5 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInput8Hook.cpp @@ -0,0 +1,76 @@ +#include "IDirectInput8Hook.h" + +IDirectInput8Hook::IDirectInput8Hook(IDirectInput8 * dinput) +{ + m_dinput = dinput; +} + +HRESULT STDMETHODCALLTYPE IDirectInput8Hook::QueryInterface(REFIID riid, LPVOID * ppvObj) +{ + return m_dinput->QueryInterface(riid, ppvObj); +} + +ULONG STDMETHODCALLTYPE IDirectInput8Hook::AddRef() +{ + return m_dinput->AddRef(); +} + +ULONG STDMETHODCALLTYPE IDirectInput8Hook::Release() +{ + ULONG uRet = m_dinput->Release(); + + if (uRet == 0) + // If the reference count is 0 delete ourselves + delete this; + + return uRet; +} + +HRESULT STDMETHODCALLTYPE IDirectInput8Hook::CreateDevice(REFGUID rguid, LPDIRECTINPUTDEVICE8A * lplpDirectInputDevice, LPUNKNOWN pUknOuter) +{ + OutputDebugString("CreateDevice Hook called\n"); + + // Create the dinput device + HRESULT hr = m_dinput->CreateDevice(rguid, lplpDirectInputDevice, pUknOuter); + + if (SUCCEEDED(hr)) + // Create the proxy device + *lplpDirectInputDevice = new IDirectInputDevice8Hook(this, *lplpDirectInputDevice, rguid); + + return hr; +} + +HRESULT STDMETHODCALLTYPE IDirectInput8Hook::EnumDevices(DWORD dwDevType, LPDIENUMDEVICESCALLBACK lpCallback, LPVOID pvRef, DWORD dwFlags) +{ + return m_dinput->EnumDevices(dwDevType, lpCallback, pvRef, dwFlags); +} + +HRESULT STDMETHODCALLTYPE IDirectInput8Hook::GetDeviceStatus(REFGUID rguidInstance) +{ + return m_dinput->GetDeviceStatus(rguidInstance); +} + +HRESULT STDMETHODCALLTYPE IDirectInput8Hook::RunControlPanel(HWND hwndOwner, DWORD dwFlags) +{ + return m_dinput->RunControlPanel(hwndOwner, dwFlags); +} + +HRESULT STDMETHODCALLTYPE IDirectInput8Hook::Initialize(HINSTANCE hinst, DWORD dwVersion) +{ + return m_dinput->Initialize(hinst, dwVersion); +} + +HRESULT STDMETHODCALLTYPE IDirectInput8Hook::FindDevice(REFGUID rguidClass, LPCSTR ptszName, LPGUID pguidInstance) +{ + return m_dinput->FindDevice(rguidClass, ptszName, pguidInstance); +} + +HRESULT STDMETHODCALLTYPE IDirectInput8Hook::EnumDevicesBySemantics(LPCSTR ptszUserName, LPDIACTIONFORMAT lpdiActionFormat, LPDIENUMDEVICESBYSEMANTICSCB lpCallback, LPVOID pvRef, DWORD dwFlags) +{ + return m_dinput->EnumDevicesBySemantics(ptszUserName, lpdiActionFormat, lpCallback, pvRef, dwFlags); +} + +HRESULT STDMETHODCALLTYPE IDirectInput8Hook::ConfigureDevices(LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMS lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) +{ + return m_dinput->ConfigureDevices(lpdiCallback, lpdiCDParams, dwFlags, pvRefData); +} \ No newline at end of file diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInput8Hook.h b/client_files/native_autoloot/eq-core-dll/src/IDirectInput8Hook.h new file mode 100644 index 0000000000..77be4ccee1 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInput8Hook.h @@ -0,0 +1,27 @@ +#pragma once + +#include "IDirectInputDevice8Hook.h" + +class IDirectInput8Hook : public IDirectInput8 +{ +private: + IDirectInput8 * m_dinput; + +public: + IDirectInput8Hook(IDirectInput8 * dinput); + + /*** IUnknown methods ***/ + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID * ppvObj); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + /*** IDirectInput8A methods ***/ + HRESULT STDMETHODCALLTYPE CreateDevice(REFGUID rguid, LPDIRECTINPUTDEVICE8A * lplpDirectInputDevice, LPUNKNOWN pUknOuter); + HRESULT STDMETHODCALLTYPE EnumDevices(DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags); + HRESULT STDMETHODCALLTYPE GetDeviceStatus(REFGUID rguidInstance); + HRESULT STDMETHODCALLTYPE RunControlPanel(HWND hwndOwner, DWORD dwFlags); + HRESULT STDMETHODCALLTYPE Initialize(HINSTANCE hinst, DWORD dwVersion); + HRESULT STDMETHODCALLTYPE FindDevice(REFGUID rguidClass, LPCSTR ptszName, LPGUID pguidInstance); + HRESULT STDMETHODCALLTYPE EnumDevicesBySemantics(LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat, LPDIENUMDEVICESBYSEMANTICSCBA lpCallback, LPVOID pvRef, DWORD dwFlags); + HRESULT STDMETHODCALLTYPE ConfigureDevices(LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSA lpdiCDParams, DWORD dwFlags, LPVOID pvRefData); +}; \ No newline at end of file diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInput8W.cpp b/client_files/native_autoloot/eq-core-dll/src/IDirectInput8W.cpp new file mode 100644 index 0000000000..db2a007274 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInput8W.cpp @@ -0,0 +1,111 @@ +/** +* Copyright (C) 2019 Elisha Riedlinger +* +* This software is provided 'as-is', without any express or implied warranty. In no event will the +* authors be held liable for any damages arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you wrote the +* original software. If you use this software in a product, an acknowledgment in the product +* documentation would be appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as +* being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "dinput8.h" + +HRESULT m_IDirectInput8W::QueryInterface(REFIID riid, LPVOID * ppvObj) +{ + if ((riid == IID_IDirectInput8W || riid == IID_IUnknown) && ppvObj) + { + AddRef(); + + *ppvObj = this; + + return S_OK; + } + + HRESULT hr = ProxyInterface->QueryInterface(riid, ppvObj); + + if (SUCCEEDED(hr)) + { + genericQueryInterface(riid, ppvObj); + } + + return hr; +} + +ULONG m_IDirectInput8W::AddRef() +{ + return ProxyInterface->AddRef(); +} + +ULONG m_IDirectInput8W::Release() +{ + ULONG ref = ProxyInterface->Release(); + + if (ref == 0) + { + delete this; + } + + return ref; +} + +HRESULT m_IDirectInput8W::CreateDevice(REFGUID rguid, LPDIRECTINPUTDEVICE8W *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) +{ + HRESULT hr = ProxyInterface->CreateDevice(rguid, lplpDirectInputDevice, pUnkOuter); + + if (SUCCEEDED(hr) && lplpDirectInputDevice) + { + *lplpDirectInputDevice = ProxyAddressLookupTable.FindAddress(*lplpDirectInputDevice); + } + + return hr; +} + +HRESULT m_IDirectInput8W::EnumDevices(DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) +{ + return ProxyInterface->EnumDevices(dwDevType, lpCallback, pvRef, dwFlags); +} + +HRESULT m_IDirectInput8W::GetDeviceStatus(REFGUID rguidInstance) +{ + return ProxyInterface->GetDeviceStatus(rguidInstance); +} + +HRESULT m_IDirectInput8W::RunControlPanel(HWND hwndOwner, DWORD dwFlags) +{ + return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); +} + +HRESULT m_IDirectInput8W::Initialize(HINSTANCE hinst, DWORD dwVersion) +{ + return ProxyInterface->Initialize(hinst, dwVersion); +} + +HRESULT m_IDirectInput8W::FindDevice(REFGUID rguidClass, LPCWSTR ptszName, LPGUID pguidInstance) +{ + return ProxyInterface->FindDevice(rguidClass, ptszName, pguidInstance); +} + +HRESULT m_IDirectInput8W::EnumDevicesBySemantics(LPCWSTR ptszUserName, LPDIACTIONFORMATW lpdiActionFormat, LPDIENUMDEVICESBYSEMANTICSCBW lpCallback, LPVOID pvRef, DWORD dwFlags) +{ + if (!lpCallback) + { + return E_INVALIDARG; + } + + ENUMDEVICEW CallbackContext; + CallbackContext.pvRef = pvRef; + CallbackContext.lpCallback = lpCallback; + + return ProxyInterface->EnumDevicesBySemantics(ptszUserName, lpdiActionFormat, m_IDirectInputEnumDevice::EnumDeviceCallbackW, &CallbackContext, dwFlags); +} + +HRESULT m_IDirectInput8W::ConfigureDevices(LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) +{ + return ProxyInterface->ConfigureDevices(lpdiCallback, lpdiCDParams, dwFlags, pvRefData); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInput8W.h b/client_files/native_autoloot/eq-core-dll/src/IDirectInput8W.h new file mode 100644 index 0000000000..b0cec33fb1 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInput8W.h @@ -0,0 +1,34 @@ +#pragma once + +class m_IDirectInput8W : public IDirectInput8W, public AddressLookupTableObject +{ +private: + IDirectInput8W *ProxyInterface; + +public: + m_IDirectInput8W(IDirectInput8W *aOriginal) : ProxyInterface(aOriginal) + { + ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); + } + ~m_IDirectInput8W() + { + ProxyAddressLookupTable.DeleteAddress(this); + } + + IDirectInput8W *GetProxyInterface() { return ProxyInterface; } + + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj); + STDMETHOD_(ULONG, AddRef)(THIS); + STDMETHOD_(ULONG, Release)(THIS); + + /*** IDirectInput8W methods ***/ + STDMETHOD(CreateDevice)(THIS_ REFGUID, LPDIRECTINPUTDEVICE8W *, LPUNKNOWN); + STDMETHOD(EnumDevices)(THIS_ DWORD, LPDIENUMDEVICESCALLBACKW, LPVOID, DWORD); + STDMETHOD(GetDeviceStatus)(THIS_ REFGUID); + STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); + STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD); + STDMETHOD(FindDevice)(THIS_ REFGUID, LPCWSTR, LPGUID); + STDMETHOD(EnumDevicesBySemantics)(THIS_ LPCWSTR, LPDIACTIONFORMATW, LPDIENUMDEVICESBYSEMANTICSCBW, LPVOID, DWORD); + STDMETHOD(ConfigureDevices)(THIS_ LPDICONFIGUREDEVICESCALLBACK, LPDICONFIGUREDEVICESPARAMSW, DWORD, LPVOID); +}; diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8A.cpp b/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8A.cpp new file mode 100644 index 0000000000..4a33fc747f --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8A.cpp @@ -0,0 +1,216 @@ +/** +* Copyright (C) 2019 Elisha Riedlinger +* +* This software is provided 'as-is', without any express or implied warranty. In no event will the +* authors be held liable for any damages arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you wrote the +* original software. If you use this software in a product, an acknowledgment in the product +* documentation would be appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as +* being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "dinput8.h" + +HRESULT m_IDirectInputDevice8A::QueryInterface(REFIID riid, LPVOID * ppvObj) +{ + if ((riid == IID_IDirectInputDevice8A || riid == IID_IUnknown) && ppvObj) + { + AddRef(); + + *ppvObj = this; + + return S_OK; + } + + HRESULT hr = ProxyInterface->QueryInterface(riid, ppvObj); + + if (SUCCEEDED(hr)) + { + genericQueryInterface(riid, ppvObj); + } + + return hr; +} + +ULONG m_IDirectInputDevice8A::AddRef() +{ + return ProxyInterface->AddRef(); +} + +ULONG m_IDirectInputDevice8A::Release() +{ + ULONG ref = ProxyInterface->Release(); + + if (ref == 0) + { + delete this; + } + + return ref; +} + +HRESULT m_IDirectInputDevice8A::GetCapabilities(LPDIDEVCAPS lpDIDevCaps) +{ + return ProxyInterface->GetCapabilities(lpDIDevCaps); +} + +HRESULT m_IDirectInputDevice8A::EnumObjects(LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) +{ + return ProxyInterface->EnumObjects(lpCallback, pvRef, dwFlags); +} + +HRESULT m_IDirectInputDevice8A::GetProperty(REFGUID rguidProp, LPDIPROPHEADER pdiph) +{ + return ProxyInterface->GetProperty(rguidProp, pdiph); +} + +HRESULT m_IDirectInputDevice8A::SetProperty(REFGUID rguidProp, LPCDIPROPHEADER pdiph) +{ + return ProxyInterface->SetProperty(rguidProp, pdiph); +} + +HRESULT m_IDirectInputDevice8A::Acquire() +{ + return ProxyInterface->Acquire(); +} + +HRESULT m_IDirectInputDevice8A::Unacquire() +{ + return ProxyInterface->Unacquire(); +} + +HRESULT m_IDirectInputDevice8A::GetDeviceState(DWORD cbData, LPVOID lpvData) +{ + return ProxyInterface->GetDeviceState(cbData, lpvData); +} + +HRESULT m_IDirectInputDevice8A::GetDeviceData(DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) +{ + return ProxyInterface->GetDeviceData(cbObjectData, rgdod, pdwInOut, dwFlags); +} + +HRESULT m_IDirectInputDevice8A::SetDataFormat(LPCDIDATAFORMAT lpdf) +{ + return ProxyInterface->SetDataFormat(lpdf); +} + +HRESULT m_IDirectInputDevice8A::SetEventNotification(HANDLE hEvent) +{ + return ProxyInterface->SetEventNotification(hEvent); +} + +HRESULT m_IDirectInputDevice8A::SetCooperativeLevel(HWND hwnd, DWORD dwFlags) +{ + return ProxyInterface->SetCooperativeLevel(hwnd, dwFlags); +} + +HRESULT m_IDirectInputDevice8A::GetObjectInfo(LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) +{ + return ProxyInterface->GetObjectInfo(pdidoi, dwObj, dwHow); +} + +HRESULT m_IDirectInputDevice8A::GetDeviceInfo(LPDIDEVICEINSTANCEA pdidi) +{ + return ProxyInterface->GetDeviceInfo(pdidi); +} + +HRESULT m_IDirectInputDevice8A::RunControlPanel(HWND hwndOwner, DWORD dwFlags) +{ + return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); +} + +HRESULT m_IDirectInputDevice8A::Initialize(HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) +{ + return ProxyInterface->Initialize(hinst, dwVersion, rguid); +} + +HRESULT m_IDirectInputDevice8A::CreateEffect(REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT * ppdeff, LPUNKNOWN punkOuter) +{ + HRESULT hr = ProxyInterface->CreateEffect(rguid, lpeff, ppdeff, punkOuter); + + if (SUCCEEDED(hr) && ppdeff) + { + *ppdeff = ProxyAddressLookupTable.FindAddress(*ppdeff); + } + + return hr; +} + +HRESULT m_IDirectInputDevice8A::EnumEffects(LPDIENUMEFFECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwEffType) +{ + return ProxyInterface->EnumEffects(lpCallback, pvRef, dwEffType); +} + +HRESULT m_IDirectInputDevice8A::GetEffectInfo(LPDIEFFECTINFOA pdei, REFGUID rguid) +{ + return ProxyInterface->GetEffectInfo(pdei, rguid); +} + +HRESULT m_IDirectInputDevice8A::GetForceFeedbackState(LPDWORD pdwOut) +{ + return ProxyInterface->GetForceFeedbackState(pdwOut); +} + +HRESULT m_IDirectInputDevice8A::SendForceFeedbackCommand(DWORD dwFlags) +{ + return ProxyInterface->SendForceFeedbackCommand(dwFlags); +} + +HRESULT m_IDirectInputDevice8A::EnumCreatedEffectObjects(LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) +{ + if (!lpCallback) + { + return E_INVALIDARG; + } + + ENUMEFFECT CallbackContext; + CallbackContext.pvRef = pvRef; + CallbackContext.lpCallback = lpCallback; + + return ProxyInterface->EnumCreatedEffectObjects(m_IDirectInputEnumEffect::EnumEffectCallback, &CallbackContext, fl); +} + +HRESULT m_IDirectInputDevice8A::Escape(LPDIEFFESCAPE pesc) +{ + return ProxyInterface->Escape(pesc); +} + +HRESULT m_IDirectInputDevice8A::Poll() +{ + return ProxyInterface->Poll(); +} + +HRESULT m_IDirectInputDevice8A::SendDeviceData(DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) +{ + return ProxyInterface->SendDeviceData(cbObjectData, rgdod, pdwInOut, fl); +} + +HRESULT m_IDirectInputDevice8A::EnumEffectsInFile(LPCSTR lpszFileName, LPDIENUMEFFECTSINFILECALLBACK pec, LPVOID pvRef, DWORD dwFlags) +{ + return ProxyInterface->EnumEffectsInFile(lpszFileName, pec, pvRef, dwFlags); +} + +HRESULT m_IDirectInputDevice8A::WriteEffectToFile(LPCSTR lpszFileName, DWORD dwEntries, LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags) +{ + return ProxyInterface->WriteEffectToFile(lpszFileName, dwEntries, rgDiFileEft, dwFlags); +} + +HRESULT m_IDirectInputDevice8A::BuildActionMap(LPDIACTIONFORMATA lpdiaf, LPCSTR lpszUserName, DWORD dwFlags) +{ + return ProxyInterface->BuildActionMap(lpdiaf, lpszUserName, dwFlags); +} + +HRESULT m_IDirectInputDevice8A::SetActionMap(LPDIACTIONFORMATA lpdiActionFormat, LPCSTR lptszUserName, DWORD dwFlags) +{ + return ProxyInterface->SetActionMap(lpdiActionFormat, lptszUserName, dwFlags); +} + +HRESULT m_IDirectInputDevice8A::GetImageInfo(LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader) +{ + return ProxyInterface->GetImageInfo(lpdiDevImageInfoHeader); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8A.h b/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8A.h new file mode 100644 index 0000000000..978a563401 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8A.h @@ -0,0 +1,55 @@ +#pragma once + +class m_IDirectInputDevice8A : public IDirectInputDevice8A, public AddressLookupTableObject +{ +private: + IDirectInputDevice8A *ProxyInterface; + +public: + m_IDirectInputDevice8A(IDirectInputDevice8A *aOriginal) : ProxyInterface(aOriginal) + { + ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); + } + ~m_IDirectInputDevice8A() + { + ProxyAddressLookupTable.DeleteAddress(this); + } + + IDirectInputDevice8A *GetProxyInterface() { return ProxyInterface; } + + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj); + STDMETHOD_(ULONG, AddRef)(THIS); + STDMETHOD_(ULONG, Release)(THIS); + + /*** IDirectInputDevice8A methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS); + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA, LPVOID, DWORD); + STDMETHOD(GetProperty)(THIS_ REFGUID, LPDIPROPHEADER); + STDMETHOD(SetProperty)(THIS_ REFGUID, LPCDIPROPHEADER); + STDMETHOD(Acquire)(THIS); + STDMETHOD(Unacquire)(THIS); + STDMETHOD(GetDeviceState)(THIS_ DWORD, LPVOID); + STDMETHOD(GetDeviceData)(THIS_ DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD); + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT); + STDMETHOD(SetEventNotification)(THIS_ HANDLE); + STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD); + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA, DWORD, DWORD); + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA); + STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); + STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD, REFGUID); + STDMETHOD(CreateEffect)(THIS_ REFGUID, LPCDIEFFECT, LPDIRECTINPUTEFFECT *, LPUNKNOWN); + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA, LPVOID, DWORD); + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA, REFGUID); + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD); + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD); + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK, LPVOID, DWORD); + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE); + STDMETHOD(Poll)(THIS); + STDMETHOD(SendDeviceData)(THIS_ DWORD, LPCDIDEVICEOBJECTDATA, LPDWORD, DWORD); + STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR, LPDIENUMEFFECTSINFILECALLBACK, LPVOID, DWORD); + STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR, DWORD, LPDIFILEEFFECT, DWORD); + STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATA, LPCSTR, DWORD); + STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATA, LPCSTR, DWORD); + STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERA); +}; diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8Hook.cpp b/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8Hook.cpp new file mode 100644 index 0000000000..2fedd469ec --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8Hook.cpp @@ -0,0 +1,187 @@ +#include +#include "IDirectInputDevice8Hook.h" + +static bool mSpaceKeyState = false; +static bool mLastSpaceKeyState = false; + +// TODO Add your own known gamepad GUIDs here! + +IDirectInputDevice8Hook::IDirectInputDevice8Hook(IDirectInput8 * dinput, IDirectInputDevice8 * dinputdevice, REFGUID guid) +{ + m_pDI = dinput; + m_pDIDevice = dinputdevice; + m_GUID = guid; +} + +/*** IUnknown methods ***/ +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::QueryInterface(REFIID riid, LPVOID * ppvObj) +{ + return m_pDIDevice->QueryInterface(riid, ppvObj); +} + +ULONG STDMETHODCALLTYPE IDirectInputDevice8Hook::AddRef() +{ + return m_pDIDevice->AddRef(); +} + +ULONG STDMETHODCALLTYPE IDirectInputDevice8Hook::Release() +{ + ULONG uRet = m_pDIDevice->Release(); + + if (uRet == 0) + // If the reference count is 0 delete ourselves + delete this; + + return uRet; +} + +/*** IDirectInputDevice8A methods ***/ +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::GetCapabilities(LPDIDEVCAPS p0) +{ + return m_pDIDevice->GetCapabilities(p0); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::EnumObjects(LPDIENUMDEVICEOBJECTSCALLBACKA p0, LPVOID p1, DWORD p2) +{ + return m_pDIDevice->EnumObjects(p0, p1, p2); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::GetProperty(REFGUID rguid, LPDIPROPHEADER p1) +{ + return m_pDIDevice->GetProperty(rguid, p1); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::SetProperty(REFGUID rguid, LPCDIPROPHEADER p1) +{ + return m_pDIDevice->SetProperty(rguid, p1); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::Acquire() +{ + return m_pDIDevice->Acquire(); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::Unacquire() +{ + return m_pDIDevice->Unacquire(); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::GetDeviceState(DWORD p0, LPVOID p1) +{ + // Forward call + HRESULT hResult = m_pDIDevice->GetDeviceState(p0, p1); + return hResult; +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::GetDeviceData(DWORD p0, LPDIDEVICEOBJECTDATA p1, LPDWORD p2, DWORD p3) +{ + // Forward call + HRESULT hResult = m_pDIDevice->GetDeviceData(p0, p1, p2, p3); + // Return result + return hResult; +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::SetDataFormat(LPCDIDATAFORMAT p0) +{ + return m_pDIDevice->SetDataFormat(p0); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::SetEventNotification(HANDLE p0) +{ + return m_pDIDevice->SetEventNotification(p0); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::SetCooperativeLevel(HWND p0, DWORD p1) +{ + return m_pDIDevice->SetCooperativeLevel(p0, p1); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::GetObjectInfo(LPDIDEVICEOBJECTINSTANCE p0, DWORD p1, DWORD p2) +{ + return m_pDIDevice->GetObjectInfo(p0, p1, p2); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::GetDeviceInfo(LPDIDEVICEINSTANCE p0) +{ + return m_pDIDevice->GetDeviceInfo(p0); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::RunControlPanel(HWND p0, DWORD p1) +{ + return m_pDIDevice->RunControlPanel(p0, p1); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::Initialize(HINSTANCE p0, DWORD p1, REFGUID rguid) +{ + return m_pDIDevice->Initialize(p0, p1, rguid); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::CreateEffect(REFGUID rguid, LPCDIEFFECT p1, LPDIRECTINPUTEFFECT * p2, LPUNKNOWN p3) +{ + return m_pDIDevice->CreateEffect(rguid, p1, p2, p3); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::EnumEffects(LPDIENUMEFFECTSCALLBACK p0, LPVOID p1, DWORD p2) +{ + return m_pDIDevice->EnumEffects(p0, p1, p2); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::GetEffectInfo(LPDIEFFECTINFO p0, REFGUID rguid) +{ + return m_pDIDevice->GetEffectInfo(p0, rguid); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::GetForceFeedbackState(LPDWORD p0) +{ + return m_pDIDevice->GetForceFeedbackState(p0); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::SendForceFeedbackCommand(DWORD p0) +{ + return m_pDIDevice->SendForceFeedbackCommand(p0); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::EnumCreatedEffectObjects(LPDIENUMCREATEDEFFECTOBJECTSCALLBACK p0, LPVOID p1, DWORD p2) +{ + return m_pDIDevice->EnumCreatedEffectObjects(p0, p1, p2); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::Escape(LPDIEFFESCAPE p0) +{ + return m_pDIDevice->Escape(p0); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::Poll() +{ + return m_pDIDevice->Poll(); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::SendDeviceData(DWORD p0, LPCDIDEVICEOBJECTDATA p1, LPDWORD p2, DWORD p3) +{ + return m_pDIDevice->SendDeviceData(p0, p1, p2, p3); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::EnumEffectsInFile(LPCSTR p0, LPDIENUMEFFECTSINFILECALLBACK p1, LPVOID p2, DWORD p3) +{ + return m_pDIDevice->EnumEffectsInFile(p0, p1, p2, p3); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::WriteEffectToFile(LPCSTR p0, DWORD p2, LPDIFILEEFFECT p3, DWORD p4) +{ + return m_pDIDevice->WriteEffectToFile(p0, p2, p3, p4); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::BuildActionMap(LPDIACTIONFORMAT p0, LPCSTR p1, DWORD p2) +{ + return m_pDIDevice->BuildActionMap(p0, p1, p2); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::SetActionMap(LPDIACTIONFORMAT p0, LPCSTR p1, DWORD p2) +{ + return m_pDIDevice->SetActionMap(p0, p1, p2); +} + +HRESULT STDMETHODCALLTYPE IDirectInputDevice8Hook::GetImageInfo(LPDIDEVICEIMAGEINFOHEADER p0) +{ + return m_pDIDevice->GetImageInfo(p0); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8Hook.h b/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8Hook.h new file mode 100644 index 0000000000..06d35e4f10 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8Hook.h @@ -0,0 +1,50 @@ +#pragma once + +#include + +class IDirectInputDevice8Hook : public IDirectInputDevice8 +{ +private: + IDirectInput8 * m_pDI; + IDirectInputDevice8 * m_pDIDevice; + GUID m_GUID; + +public: + IDirectInputDevice8Hook(IDirectInput8 * dinput, IDirectInputDevice8 * dinputdevice, REFGUID guid); + + /*** IUnknown methods ***/ + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID * ppvObj); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + /*** IDirectInputDevice8A methods ***/ + HRESULT STDMETHODCALLTYPE GetCapabilities(LPDIDEVCAPS p0); + HRESULT STDMETHODCALLTYPE EnumObjects(LPDIENUMDEVICEOBJECTSCALLBACK p0, LPVOID p1, DWORD p2); + HRESULT STDMETHODCALLTYPE GetProperty(REFGUID rguid, LPDIPROPHEADER p1); + HRESULT STDMETHODCALLTYPE SetProperty(REFGUID rguid, LPCDIPROPHEADER p1); + HRESULT STDMETHODCALLTYPE Acquire(); + HRESULT STDMETHODCALLTYPE Unacquire(); + HRESULT STDMETHODCALLTYPE GetDeviceState(DWORD p0, LPVOID p1); + HRESULT STDMETHODCALLTYPE GetDeviceData(DWORD p0, LPDIDEVICEOBJECTDATA p1, LPDWORD p2, DWORD p3); + HRESULT STDMETHODCALLTYPE SetDataFormat(LPCDIDATAFORMAT p0); + HRESULT STDMETHODCALLTYPE SetEventNotification(HANDLE p0); + HRESULT STDMETHODCALLTYPE SetCooperativeLevel(HWND p0, DWORD p1); + HRESULT STDMETHODCALLTYPE GetObjectInfo(LPDIDEVICEOBJECTINSTANCEA p0, DWORD p1, DWORD p2); + HRESULT STDMETHODCALLTYPE GetDeviceInfo(LPDIDEVICEINSTANCEA p0); + HRESULT STDMETHODCALLTYPE RunControlPanel(HWND p0, DWORD p1); + HRESULT STDMETHODCALLTYPE Initialize(HINSTANCE p0, DWORD p1, REFGUID rguid); + HRESULT STDMETHODCALLTYPE CreateEffect(REFGUID rguid, LPCDIEFFECT p1, LPDIRECTINPUTEFFECT * p2, LPUNKNOWN p3); + HRESULT STDMETHODCALLTYPE EnumEffects(LPDIENUMEFFECTSCALLBACKA p0, LPVOID p1, DWORD p2); + HRESULT STDMETHODCALLTYPE GetEffectInfo(LPDIEFFECTINFOA p0, REFGUID rguid); + HRESULT STDMETHODCALLTYPE GetForceFeedbackState(LPDWORD p0); + HRESULT STDMETHODCALLTYPE SendForceFeedbackCommand(DWORD p0); + HRESULT STDMETHODCALLTYPE EnumCreatedEffectObjects(LPDIENUMCREATEDEFFECTOBJECTSCALLBACK p0, LPVOID p1, DWORD p2); + HRESULT STDMETHODCALLTYPE Escape(LPDIEFFESCAPE p0); + HRESULT STDMETHODCALLTYPE Poll(); + HRESULT STDMETHODCALLTYPE SendDeviceData(DWORD p0, LPCDIDEVICEOBJECTDATA p1, LPDWORD p2, DWORD p3); + HRESULT STDMETHODCALLTYPE EnumEffectsInFile(LPCSTR p0, LPDIENUMEFFECTSINFILECALLBACK p1, LPVOID p2, DWORD p3); + HRESULT STDMETHODCALLTYPE WriteEffectToFile(LPCSTR p0, DWORD p2, LPDIFILEEFFECT p3, DWORD p4); + HRESULT STDMETHODCALLTYPE BuildActionMap(LPDIACTIONFORMAT p0, LPCSTR p1, DWORD p2); + HRESULT STDMETHODCALLTYPE SetActionMap(LPDIACTIONFORMAT p0, LPCSTR p1, DWORD p2); + HRESULT STDMETHODCALLTYPE GetImageInfo(LPDIDEVICEIMAGEINFOHEADER p0); +}; \ No newline at end of file diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8W.cpp b/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8W.cpp new file mode 100644 index 0000000000..300ea30848 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8W.cpp @@ -0,0 +1,216 @@ +/** +* Copyright (C) 2019 Elisha Riedlinger +* +* This software is provided 'as-is', without any express or implied warranty. In no event will the +* authors be held liable for any damages arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you wrote the +* original software. If you use this software in a product, an acknowledgment in the product +* documentation would be appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as +* being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "dinput8.h" + +HRESULT m_IDirectInputDevice8W::QueryInterface(REFIID riid, LPVOID* ppvObj) +{ + if ((riid == IID_IDirectInputDevice8W || riid == IID_IUnknown) && ppvObj) + { + AddRef(); + + *ppvObj = this; + + return S_OK; + } + + HRESULT hr = ProxyInterface->QueryInterface(riid, ppvObj); + + if (SUCCEEDED(hr)) + { + genericQueryInterface(riid, ppvObj); + } + + return hr; +} + +ULONG m_IDirectInputDevice8W::AddRef() +{ + return ProxyInterface->AddRef(); +} + +ULONG m_IDirectInputDevice8W::Release() +{ + ULONG ref = ProxyInterface->Release(); + + if (ref == 0) + { + delete this; + } + + return ref; +} + +HRESULT m_IDirectInputDevice8W::GetCapabilities(LPDIDEVCAPS lpDIDevCaps) +{ + return ProxyInterface->GetCapabilities(lpDIDevCaps); +} + +HRESULT m_IDirectInputDevice8W::EnumObjects(LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) +{ + return ProxyInterface->EnumObjects(lpCallback, pvRef, dwFlags); +} + +HRESULT m_IDirectInputDevice8W::GetProperty(REFGUID rguidProp, LPDIPROPHEADER pdiph) +{ + return ProxyInterface->GetProperty(rguidProp, pdiph); +} + +HRESULT m_IDirectInputDevice8W::SetProperty(REFGUID rguidProp, LPCDIPROPHEADER pdiph) +{ + return ProxyInterface->SetProperty(rguidProp, pdiph); +} + +HRESULT m_IDirectInputDevice8W::Acquire() +{ + return ProxyInterface->Acquire(); +} + +HRESULT m_IDirectInputDevice8W::Unacquire() +{ + return ProxyInterface->Unacquire(); +} + +HRESULT m_IDirectInputDevice8W::GetDeviceState(DWORD cbData, LPVOID lpvData) +{ + return ProxyInterface->GetDeviceState(cbData, lpvData); +} + +HRESULT m_IDirectInputDevice8W::GetDeviceData(DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) +{ + return ProxyInterface->GetDeviceData(cbObjectData, rgdod, pdwInOut, dwFlags); +} + +HRESULT m_IDirectInputDevice8W::SetDataFormat(LPCDIDATAFORMAT lpdf) +{ + return ProxyInterface->SetDataFormat(lpdf); +} + +HRESULT m_IDirectInputDevice8W::SetEventNotification(HANDLE hEvent) +{ + return ProxyInterface->SetEventNotification(hEvent); +} + +HRESULT m_IDirectInputDevice8W::SetCooperativeLevel(HWND hwnd, DWORD dwFlags) +{ + return ProxyInterface->SetCooperativeLevel(hwnd, dwFlags); +} + +HRESULT m_IDirectInputDevice8W::GetObjectInfo(LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) +{ + return ProxyInterface->GetObjectInfo(pdidoi, dwObj, dwHow); +} + +HRESULT m_IDirectInputDevice8W::GetDeviceInfo(LPDIDEVICEINSTANCEW pdidi) +{ + return ProxyInterface->GetDeviceInfo(pdidi); +} + +HRESULT m_IDirectInputDevice8W::RunControlPanel(HWND hwndOwner, DWORD dwFlags) +{ + return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); +} + +HRESULT m_IDirectInputDevice8W::Initialize(HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) +{ + return ProxyInterface->Initialize(hinst, dwVersion, rguid); +} + +HRESULT m_IDirectInputDevice8W::CreateEffect(REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT * ppdeff, LPUNKNOWN punkOuter) +{ + HRESULT hr = ProxyInterface->CreateEffect(rguid, lpeff, ppdeff, punkOuter); + + if (SUCCEEDED(hr) && ppdeff) + { + *ppdeff = ProxyAddressLookupTable.FindAddress(*ppdeff); + } + + return hr; +} + +HRESULT m_IDirectInputDevice8W::EnumEffects(LPDIENUMEFFECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwEffType) +{ + return ProxyInterface->EnumEffects(lpCallback, pvRef, dwEffType); +} + +HRESULT m_IDirectInputDevice8W::GetEffectInfo(LPDIEFFECTINFOW pdei, REFGUID rguid) +{ + return ProxyInterface->GetEffectInfo(pdei, rguid); +} + +HRESULT m_IDirectInputDevice8W::GetForceFeedbackState(LPDWORD pdwOut) +{ + return ProxyInterface->GetForceFeedbackState(pdwOut); +} + +HRESULT m_IDirectInputDevice8W::SendForceFeedbackCommand(DWORD dwFlags) +{ + return ProxyInterface->SendForceFeedbackCommand(dwFlags); +} + +HRESULT m_IDirectInputDevice8W::EnumCreatedEffectObjects(LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) +{ + if (!lpCallback) + { + return E_INVALIDARG; + } + + ENUMEFFECT CallbackContext; + CallbackContext.pvRef = pvRef; + CallbackContext.lpCallback = lpCallback; + + return ProxyInterface->EnumCreatedEffectObjects(m_IDirectInputEnumEffect::EnumEffectCallback, &CallbackContext, fl); +} + +HRESULT m_IDirectInputDevice8W::Escape(LPDIEFFESCAPE pesc) +{ + return ProxyInterface->Escape(pesc); +} + +HRESULT m_IDirectInputDevice8W::Poll() +{ + return ProxyInterface->Poll(); +} + +HRESULT m_IDirectInputDevice8W::SendDeviceData(DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) +{ + return ProxyInterface->SendDeviceData(cbObjectData, rgdod, pdwInOut, fl); +} + +HRESULT m_IDirectInputDevice8W::EnumEffectsInFile(LPCWSTR lpszFileName, LPDIENUMEFFECTSINFILECALLBACK pec, LPVOID pvRef, DWORD dwFlags) +{ + return ProxyInterface->EnumEffectsInFile(lpszFileName, pec, pvRef, dwFlags); +} + +HRESULT m_IDirectInputDevice8W::WriteEffectToFile(LPCWSTR lpszFileName, DWORD dwEntries, LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags) +{ + return ProxyInterface->WriteEffectToFile(lpszFileName, dwEntries, rgDiFileEft, dwFlags); +} + +HRESULT m_IDirectInputDevice8W::BuildActionMap(LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags) +{ + return ProxyInterface->BuildActionMap(lpdiaf, lpszUserName, dwFlags); +} + +HRESULT m_IDirectInputDevice8W::SetActionMap(LPDIACTIONFORMATW lpdiActionFormat, LPCWSTR lptszUserName, DWORD dwFlags) +{ + return ProxyInterface->SetActionMap(lpdiActionFormat, lptszUserName, dwFlags); +} + +HRESULT m_IDirectInputDevice8W::GetImageInfo(LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader) +{ + return ProxyInterface->GetImageInfo(lpdiDevImageInfoHeader); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8W.h b/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8W.h new file mode 100644 index 0000000000..67b3ddfb99 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInputDevice8W.h @@ -0,0 +1,55 @@ +#pragma once + +class m_IDirectInputDevice8W : public IDirectInputDevice8W, public AddressLookupTableObject +{ +private: + IDirectInputDevice8W *ProxyInterface; + +public: + m_IDirectInputDevice8W(IDirectInputDevice8W *aOriginal) : ProxyInterface(aOriginal) + { + ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); + } + ~m_IDirectInputDevice8W() + { + ProxyAddressLookupTable.DeleteAddress(this); + } + + IDirectInputDevice8W *GetProxyInterface() { return ProxyInterface; } + + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj); + STDMETHOD_(ULONG, AddRef)(THIS); + STDMETHOD_(ULONG, Release)(THIS); + + /*** IDirectInputDevice8W methods ***/ + STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS); + STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW, LPVOID, DWORD); + STDMETHOD(GetProperty)(THIS_ REFGUID, LPDIPROPHEADER); + STDMETHOD(SetProperty)(THIS_ REFGUID, LPCDIPROPHEADER); + STDMETHOD(Acquire)(THIS); + STDMETHOD(Unacquire)(THIS); + STDMETHOD(GetDeviceState)(THIS_ DWORD, LPVOID); + STDMETHOD(GetDeviceData)(THIS_ DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD); + STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT); + STDMETHOD(SetEventNotification)(THIS_ HANDLE); + STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD); + STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW, DWORD, DWORD); + STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW); + STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); + STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD, REFGUID); + STDMETHOD(CreateEffect)(THIS_ REFGUID, LPCDIEFFECT, LPDIRECTINPUTEFFECT *, LPUNKNOWN); + STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW, LPVOID, DWORD); + STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW, REFGUID); + STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD); + STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD); + STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK, LPVOID, DWORD); + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE); + STDMETHOD(Poll)(THIS); + STDMETHOD(SendDeviceData)(THIS_ DWORD, LPCDIDEVICEOBJECTDATA, LPDWORD, DWORD); + STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR, LPDIENUMEFFECTSINFILECALLBACK, LPVOID, DWORD); + STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR, DWORD, LPDIFILEEFFECT, DWORD); + STDMETHOD(BuildActionMap)(THIS_ LPDIACTIONFORMATW, LPCWSTR, DWORD); + STDMETHOD(SetActionMap)(THIS_ LPDIACTIONFORMATW, LPCWSTR, DWORD); + STDMETHOD(GetImageInfo)(THIS_ LPDIDEVICEIMAGEINFOHEADERW); +}; diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInputEffect.cpp b/client_files/native_autoloot/eq-core-dll/src/IDirectInputEffect.cpp new file mode 100644 index 0000000000..3f3954889c --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInputEffect.cpp @@ -0,0 +1,105 @@ +/** +* Copyright (C) 2019 Elisha Riedlinger +* +* This software is provided 'as-is', without any express or implied warranty. In no event will the +* authors be held liable for any damages arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you wrote the +* original software. If you use this software in a product, an acknowledgment in the product +* documentation would be appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as +* being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "dinput8.h" + +HRESULT m_IDirectInputEffect::QueryInterface(REFIID riid, LPVOID * ppvObj) +{ + if ((riid == IID_IDirectInputEffect || riid == IID_IUnknown) && ppvObj) + { + AddRef(); + + *ppvObj = this; + + return S_OK; + } + + HRESULT hr = ProxyInterface->QueryInterface(riid, ppvObj); + + if (SUCCEEDED(hr)) + { + genericQueryInterface(riid, ppvObj); + } + + return hr; +} + +ULONG m_IDirectInputEffect::AddRef() +{ + return ProxyInterface->AddRef(); +} + +ULONG m_IDirectInputEffect::Release() +{ + ULONG ref = ProxyInterface->Release(); + + if (ref == 0) + { + delete this; + } + + return ref; +} + +HRESULT m_IDirectInputEffect::Initialize(HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) +{ + return ProxyInterface->Initialize(hinst, dwVersion, rguid); +} + +HRESULT m_IDirectInputEffect::GetEffectGuid(LPGUID pguid) +{ + return ProxyInterface->GetEffectGuid(pguid); +} + +HRESULT m_IDirectInputEffect::GetParameters(LPDIEFFECT peff, DWORD dwFlags) +{ + return ProxyInterface->GetParameters(peff, dwFlags); +} + +HRESULT m_IDirectInputEffect::SetParameters(LPCDIEFFECT peff, DWORD dwFlags) +{ + return ProxyInterface->SetParameters(peff, dwFlags); +} + +HRESULT m_IDirectInputEffect::Start(DWORD dwIterations, DWORD dwFlags) +{ + return ProxyInterface->Start(dwIterations, dwFlags); +} + +HRESULT m_IDirectInputEffect::Stop() +{ + return ProxyInterface->Stop(); +} + +HRESULT m_IDirectInputEffect::GetEffectStatus(LPDWORD pdwFlags) +{ + return ProxyInterface->GetEffectStatus(pdwFlags); +} + +HRESULT m_IDirectInputEffect::Download() +{ + return ProxyInterface->Download(); +} + +HRESULT m_IDirectInputEffect::Unload() +{ + return ProxyInterface->Unload(); +} + +HRESULT m_IDirectInputEffect::Escape(LPDIEFFESCAPE pesc) +{ + return ProxyInterface->Escape(pesc); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInputEffect.h b/client_files/native_autoloot/eq-core-dll/src/IDirectInputEffect.h new file mode 100644 index 0000000000..288a4e3274 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInputEffect.h @@ -0,0 +1,36 @@ +#pragma once + +class m_IDirectInputEffect : public IDirectInputEffect, public AddressLookupTableObject +{ +private: + IDirectInputEffect *ProxyInterface; + +public: + m_IDirectInputEffect(IDirectInputEffect *aOriginal) : ProxyInterface(aOriginal) + { + ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); + } + ~m_IDirectInputEffect() + { + ProxyAddressLookupTable.DeleteAddress(this); + } + + IDirectInputEffect *GetProxyInterface() { return ProxyInterface; } + + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj); + STDMETHOD_(ULONG, AddRef)(THIS); + STDMETHOD_(ULONG, Release)(THIS); + + /*** IDirectInputEffect methods ***/ + STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD, REFGUID); + STDMETHOD(GetEffectGuid)(THIS_ LPGUID); + STDMETHOD(GetParameters)(THIS_ LPDIEFFECT, DWORD); + STDMETHOD(SetParameters)(THIS_ LPCDIEFFECT, DWORD); + STDMETHOD(Start)(THIS_ DWORD, DWORD); + STDMETHOD(Stop)(THIS); + STDMETHOD(GetEffectStatus)(THIS_ LPDWORD); + STDMETHOD(Download)(THIS); + STDMETHOD(Unload)(THIS); + STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE); +}; diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumDevice.cpp b/client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumDevice.cpp new file mode 100644 index 0000000000..f8a16f395f --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumDevice.cpp @@ -0,0 +1,41 @@ +/** +* Copyright (C) 2019 Elisha Riedlinger +* +* This software is provided 'as-is', without any express or implied warranty. In no event will the +* authors be held liable for any damages arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you wrote the +* original software. If you use this software in a product, an acknowledgment in the product +* documentation would be appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as +* being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "dinput8.h" + +BOOL CALLBACK m_IDirectInputEnumDevice::EnumDeviceCallbackA(LPCDIDEVICEINSTANCEA lpddi, LPDIRECTINPUTDEVICE8A lpdid, DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef) +{ + ENUMDEVICEA *lpCallbackContext = (ENUMDEVICEA*)pvRef; + + if (lpdid) + { + lpdid = ProxyAddressLookupTable.FindAddress(lpdid); + } + + return lpCallbackContext->lpCallback(lpddi, lpdid, dwFlags, dwRemaining, lpCallbackContext->pvRef); +} + +BOOL CALLBACK m_IDirectInputEnumDevice::EnumDeviceCallbackW(LPCDIDEVICEINSTANCEW lpddi, LPDIRECTINPUTDEVICE8W lpdid, DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef) +{ + ENUMDEVICEW *lpCallbackContext = (ENUMDEVICEW*)pvRef; + + if (lpdid) + { + lpdid = ProxyAddressLookupTable.FindAddress(lpdid); + } + + return lpCallbackContext->lpCallback(lpddi, lpdid, dwFlags, dwRemaining, lpCallbackContext->pvRef); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumDevice.h b/client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumDevice.h new file mode 100644 index 0000000000..ba003c3d49 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumDevice.h @@ -0,0 +1,23 @@ +#pragma once + +struct ENUMDEVICEA +{ + LPVOID pvRef; + LPDIENUMDEVICESBYSEMANTICSCBA lpCallback; +}; + +struct ENUMDEVICEW +{ + LPVOID pvRef; + LPDIENUMDEVICESBYSEMANTICSCBW lpCallback; +}; + +class m_IDirectInputEnumDevice +{ +public: + m_IDirectInputEnumDevice() {} + ~m_IDirectInputEnumDevice() {} + + static BOOL CALLBACK EnumDeviceCallbackA(LPCDIDEVICEINSTANCEA, LPDIRECTINPUTDEVICE8A, DWORD, DWORD, LPVOID); + static BOOL CALLBACK EnumDeviceCallbackW(LPCDIDEVICEINSTANCEW, LPDIRECTINPUTDEVICE8W, DWORD, DWORD, LPVOID); +}; diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumEffect.cpp b/client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumEffect.cpp new file mode 100644 index 0000000000..3c199a25f6 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumEffect.cpp @@ -0,0 +1,29 @@ +/** +* Copyright (C) 2019 Elisha Riedlinger +* +* This software is provided 'as-is', without any express or implied warranty. In no event will the +* authors be held liable for any damages arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you wrote the +* original software. If you use this software in a product, an acknowledgment in the product +* documentation would be appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as +* being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "dinput8.h" + +BOOL CALLBACK m_IDirectInputEnumEffect::EnumEffectCallback(LPDIRECTINPUTEFFECT pdeff, LPVOID pvRef) +{ + ENUMEFFECT *lpCallbackContext = (ENUMEFFECT*)pvRef; + + if (pdeff) + { + pdeff = ProxyAddressLookupTable.FindAddress(pdeff); + } + + return lpCallbackContext->lpCallback(pdeff, lpCallbackContext->pvRef); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumEffect.h b/client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumEffect.h new file mode 100644 index 0000000000..34595d759f --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/IDirectInputEnumEffect.h @@ -0,0 +1,16 @@ +#pragma once + +struct ENUMEFFECT +{ + LPVOID pvRef; + LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback; +}; + +class m_IDirectInputEnumEffect +{ +public: + m_IDirectInputEnumEffect() {} + ~m_IDirectInputEnumEffect() {} + + static BOOL CALLBACK EnumEffectCallback(LPDIRECTINPUTEFFECT, LPVOID); +}; diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ-VS2005.vcproj b/client_files/native_autoloot/eq-core-dll/src/ISXEQ-VS2005.vcproj new file mode 100644 index 0000000000..31e0097d57 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ-VS2005.vcproj @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ.vcproj b/client_files/native_autoloot/eq-core-dll/src/ISXEQ.vcproj new file mode 100644 index 0000000000..15e1ea409a --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ.vcproj @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQ.cpp b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQ.cpp new file mode 100644 index 0000000000..e9f0795476 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQ.cpp @@ -0,0 +1,520 @@ +// +// ISXEQ +// + + +// uncomment this line to enable ISBoxer compatibility. changes ${Target} to ${EQTarget} and ${Window} to ${EQWindow} +//#define ISBOXER_COMPAT + + +#include "..\MQ2Main.h" +#pragma comment(lib,"ISXDK.lib") + +// The mandatory pre-setup function. Our name is "ISXEQ", and the class is ISXEQ. +// This sets up a "ModulePath" variable which contains the path to this module in case we want it, +// and a "PluginLog" variable, which contains the path and filename of what we should use for our +// debug logging if we need it. It also sets up a variable "pExtension" which is the pointer to +// our instanced class. +ISXPreSetup("ISXEQ",CISXEQ); + +// Basic IS datatypes, these get retrieved on startup by our initialize function, so we can use them in +// our Top-Level Objects or custom datatypes +LSType *pStringType=0; +LSType *pIntType=0; +LSType *pBoolType=0; +LSType *pFloatType=0; +LSType *pByteType=0; + +LSType *pIntPtrType=0; +LSType *pBoolPtrType=0; +LSType *pFloatPtrType=0; +LSType *pBytePtrType=0; + +LSType *pTimeType=0; + +ISInterface *pISInterface=0; +HISXSERVICE hPulseService; +HISXSERVICE hMemoryService; +HISXSERVICE hHTTPService; +HISXSERVICE hTriggerService; + +HISXSERVICE hChatService; +HISXSERVICE hUIService; +HISXSERVICE hGamestateService; +HISXSERVICE hSpawnService; +HISXSERVICE hZoneService; +unsigned int ChatEventID=0; +unsigned int PersistentPointerClass=0; + +// Forward declarations of callbacks +void __cdecl PulseService(bool Broadcast, unsigned int MSG, void *lpData); +void __cdecl MemoryService(bool Broadcast, unsigned int MSG, void *lpData); +void __cdecl HTTPService(bool Broadcast, unsigned int MSG, void *lpData); +void __cdecl TriggerService(bool Broadcast, unsigned int MSG, void *lpData); +void __cdecl ProtectionRequest(ISXInterface *pClient, unsigned int MSG, void *lpData); + +#if 0 +void __cdecl SoftwareCursorService(bool Broadcast, unsigned int MSG, void *lpData); + +HISXSERVICE hSoftwareCursorService=0; +#endif + +HISXSERVICE hEQProtectionService=0; + + +// The constructor of our class. General initialization cannot be done yet, because we're not given +// the pointer to the Inner Space interface until it is ready for us to initialize. Just set the +// pointer we have to the interface to 0. Initialize data members, too. +CISXEQ::CISXEQ(void) +{ +} + +// Free any remaining resources in the destructor. This is called when the DLL is unloaded, but +// Inner Space calls the "Shutdown" function first. Most if not all of the shutdown process should +// be done in Shutdown. +CISXEQ::~CISXEQ(void) +{ +} + +extern bool MQ2Initialize(); +extern void MQ2Shutdown(); +// Initialize is called by Inner Space when the extension should initialize. +bool CISXEQ::Initialize(ISInterface *p_ISInterface) +{ + pISInterface=p_ISInterface; + + char CurrentModule[512]={0}; + GetModuleFileName(0,CurrentModule,512); + char *filename; + if (filename=strrchr(CurrentModule,'\\')) + filename++; + else + filename=CurrentModule; + if (stricmp(filename,"eqgame.exe")) + { + printf("ISXEQ is only meant to be used in eqgame.exe"); + return false; + } + + // retrieve basic ISData types + pStringType=pISInterface->FindLSType("string"); + pIntType=pISInterface->FindLSType("int"); + pBoolType=pISInterface->FindLSType("bool"); + pFloatType=pISInterface->FindLSType("float"); + pTimeType=pISInterface->FindLSType("time"); + pByteType=pISInterface->FindLSType("byte"); + + pIntPtrType=pISInterface->FindLSType("intptr"); + pBoolPtrType=pISInterface->FindLSType("boolptr"); + pFloatPtrType=pISInterface->FindLSType("floatptr"); + pBytePtrType=pISInterface->FindLSType("byteptr"); + + + ConnectServices(); + + RegisterCommands(); + RegisterAliases(); + RegisterDataTypes(); + RegisterTopLevelObjects(); + RegisterServices(); + HookMemChecker(TRUE); + strcpy(gszINIPath,INIFileName); + MQ2Initialize(); + printf("ISXEQ Loaded"); + return true; +} + +// shutdown sequence +void CISXEQ::Shutdown() +{ + MQ2Shutdown(); + DisconnectServices(); + + UnRegisterServices(); + UnRegisterTopLevelObjects(); + UnRegisterDataTypes(); + UnRegisterAliases(); + UnRegisterCommands(); +} + +#if 0 +class EQSoftwareCursorInterface : public ISXSoftwareCursorInterface +{ +public: + virtual bool CursorEnabled() + { + return !bMouseLook; + } + virtual bool GetPosition(int &X, int &Y) + { + X=EQADDR_MOUSE->X; + Y=EQADDR_MOUSE->Y; + return true; + } + + virtual bool SetPosition(int X, int Y) + { + EQADDR_MOUSE->X = X; + EQADDR_MOUSE->Y = Y; + return true; + } + + virtual bool DrawCursor() + { + if (bMouseLook) + return false; +// pWndMgr->DrawCursor(); + //pWndMgr->DrawCursor() + return true; + } +} SoftwareCursorInterface; +#endif + +void CISXEQ::ConnectServices() +{ + // connect to any services. Here we connect to "Pulse" which receives a + // message every frame (after the frame is displayed) and "Memory" which + // wraps "detours" and memory modifications + hPulseService=pISInterface->ConnectService(this,"Pulse",PulseService); + hMemoryService=pISInterface->ConnectService(this,"Memory",MemoryService); + hHTTPService=pISInterface->ConnectService(this,"HTTP",HTTPService); + hTriggerService=pISInterface->ConnectService(this,"Triggers",TriggerService); + +#if 0 + hSoftwareCursorService=pISInterface->ConnectService(this,"Software Cursor",SoftwareCursorService); + + IS_SoftwareCursorEnable(this,pISInterface,hSoftwareCursorService,&SoftwareCursorInterface); +#endif +} +void CISXEQ::RegisterCommands() +{ + // add any commands +// pISInterface->AddCommand("MyCommand",MyCommand,true,false); +} + +void CISXEQ::RegisterAliases() +{ + // add any aliases +} + +void CISXEQ::RegisterDataTypes() +{ + // add any datatypes + // pMyType = new MyType; + // pISInterface->AddLSType(*pMyType); + +#define DATATYPE(_class_,_variable_,_persistentclass_) _variable_ = new _class_; pISInterface->AddLSType(*_variable_); if (_persistentclass_) pISInterface->SetPersistentClass(_variable_,pISInterface->RegisterPersistentClass(_persistentclass_)); +#include "ISXEQDataTypes.h" +#undef DATATYPE + pGroupMemberType->SetInheritance(pSpawnType); + + // NOTE: SetInheritance does NOT make it inherit, just notifies the syntax checker... + pCharacterType->SetInheritance(pSpawnType); + pBuffType->SetInheritance(pSpellType); +// pCurrentZoneType->SetInheritance(pZoneType); + pRaidMemberType->SetInheritance(pSpawnType); +} + +void CISXEQ::RegisterTopLevelObjects() +{ + // add any Top-Level Objects + //pISInterface->AddTopLevelObject("ISXEQ",ISXEQData); +#define TOPLEVELOBJECT(_name_,_function_) pISInterface->AddTopLevelObject(_name_,_function_); +#include "ISXEQTopLevelObjects.h" +#undef TOPLEVELOBJECT +} + +extern void __cdecl GamestateRequest(ISXInterface *pClient, unsigned int MSG, void *lpData); +extern void __cdecl SpawnRequest(ISXInterface *pClient, unsigned int MSG, void *lpData); + +void CISXEQ::RegisterServices() +{ + hEQProtectionService=pISInterface->RegisterService(this,"EQ Memory Protection Service",ProtectionRequest); + pISInterface->ServiceRequest(this,hMemoryService,MEM_ENABLEPROTECTION,"EQ Memory Protection Service"); + + hChatService=pISInterface->RegisterService(this,"EQ Chat Service",0); + hUIService=pISInterface->RegisterService(this,"EQ UI Service",0); + hGamestateService=pISInterface->RegisterService(this,"EQ Gamestate Service",GamestateRequest); + hSpawnService=pISInterface->RegisterService(this,"EQ Spawn Service",SpawnRequest); + hZoneService=pISInterface->RegisterService(this,"EQ Zone Service",0); + + ChatEventID = pISInterface->RegisterEvent("EQ Chat"); + PersistentPointerClass = pISInterface->RegisterPersistentClass("EQ Objects"); +} + +void CISXEQ::DisconnectServices() +{ + // gracefully disconnect from services + if (hPulseService) + pISInterface->DisconnectService(this,hPulseService); + if (hMemoryService) + { + pISInterface->DisconnectService(this,hMemoryService); + // memory modifications are automatically undone when disconnecting + // also, since this service accepts messages from clients we should reset our handle to + // 0 to make sure we dont try to continue using it + hMemoryService=0; + } + if (hHTTPService) + { + pISInterface->DisconnectService(this,hHTTPService); + } + if (hTriggerService) + { + pISInterface->DisconnectService(this,hTriggerService); + } +#if 0 + if (hSoftwareCursorService) + { + IS_SoftwareCursorDisable(this,pISInterface,hSoftwareCursorService); + pISInterface->DisconnectService(this,hSoftwareCursorService); + } +#endif + pISInterface->InvalidatePersistentClass(PersistentPointerClass); +} + +void CISXEQ::UnRegisterCommands() +{ + // remove commands +// pISInterface->RemoveCommand("MyCommand"); +} +void CISXEQ::UnRegisterAliases() +{ + // remove aliases +} +void CISXEQ::UnRegisterDataTypes() +{ + // remove data types +#define DATATYPE(_class_,_variable_,_persistentclass_) if (_variable_) {pISInterface->RemoveLSType(*_variable_);delete _variable_; } +#include "ISXEQDataTypes.h" +#undef DATATYPE + +} +void CISXEQ::UnRegisterTopLevelObjects() +{ + // remove data items +// pISInterface->RemoveTopLevelObject("ISXEQ"); +#define TOPLEVELOBJECT(_name_,_function_) pISInterface->RemoveTopLevelObject(_name_); +#include "ISXEQTopLevelObjects.h" +#undef TOPLEVELOBJECT +} +void CISXEQ::UnRegisterServices() +{ + // shutdown our own services + if (hEQProtectionService) + { + pISInterface->ServiceRequest(this,hMemoryService,MEM_DISABLEPROTECTION,"EQ Memory Protection Service"); + pISInterface->ShutdownService(this,hEQProtectionService); + } + if (hChatService) + pISInterface->ShutdownService(this,hChatService); + if (hUIService) + pISInterface->ShutdownService(this,hUIService); + if (hGamestateService) + pISInterface->ShutdownService(this,hGamestateService); + if (hSpawnService) + pISInterface->ShutdownService(this,hSpawnService); + if (hZoneService) + pISInterface->ShutdownService(this,hZoneService); +} + +bool CISXEQ::Protect(unsigned int Address, unsigned int Size, const void *OriginalData) +{ + EQProtected *pProtected=ProtectedMap[Address]; + if (pProtected) + return false; + + if (IsBadReadPtr((void*)Address,Size)) + return false; + + pProtected = new EQProtected(Address,Size,OriginalData); + ProtectedMap[Address]=pProtected; + return true; +} + +bool CISXEQ::UnProtect(unsigned int Address) +{ + map::iterator i=ProtectedMap.find(Address); + if (i==ProtectedMap.end()) + return false; + EQProtected *pProtected=i->second; + if (!pProtected) + return false; + delete pProtected; + ProtectedMap.erase(Address); + return true; +} + +extern int __cdecl memcheck0(unsigned char *buffer, int count); +extern int __cdecl memcheck1(unsigned char *buffer, int count, struct mckey key); +extern int __cdecl memcheck2(unsigned char *buffer, int count, struct mckey key); +extern int __cdecl memcheck3(unsigned char *buffer, int count, struct mckey key); +extern int __cdecl memcheck4(unsigned char *buffer, int count, struct mckey key); + +// this is the memory checker key struct +struct mckey { + union { + int x; + unsigned char a[4]; + char sa[4]; + }; +}; + +class CObfuscator +{ +public: + int doit_tramp(int, int); + int doit_detour(int opcode, int flag); +}; + +class CEmoteHook +{ +public: + VOID Trampoline(void); + VOID Detour(void); +}; + +DETOUR_TRAMPOLINE_EMPTY(int __cdecl memcheck0_tramp(unsigned char *buffer, int count)); +DETOUR_TRAMPOLINE_EMPTY(int __cdecl memcheck1_tramp(unsigned char *buffer, int count, struct mckey key)); +DETOUR_TRAMPOLINE_EMPTY(int __cdecl memcheck2_tramp(unsigned char *buffer, int count, struct mckey key)); +DETOUR_TRAMPOLINE_EMPTY(int __cdecl memcheck3_tramp(unsigned char *buffer, int count, struct mckey key)); +DETOUR_TRAMPOLINE_EMPTY(int __cdecl memcheck4_tramp(unsigned char *buffer, int count, struct mckey key)); + +extern VOID HookInlineChecks(BOOL Patch); + +VOID CISXEQ::HookMemChecker(BOOL Patch) +{ + if (Patch) { + + if (!EzDetour(__MemChecker0,memcheck0,memcheck0_tramp)) + { + printf("memcheck0 detour failed"); + } + if (!EzDetour(__MemChecker2,memcheck2,memcheck2_tramp)) + { + printf("memcheck2 detour failed"); + } + if (!EzDetour(__MemChecker3,memcheck3,memcheck3_tramp)) + { + printf("memcheck3 detour failed"); + } + if (!EzDetour(__MemChecker4,memcheck4,memcheck4_tramp)) + { + printf("memcheck4 detour failed"); + } + if (!EzDetour(CEverQuest__Emote,&CEmoteHook::Detour,&CEmoteHook::Trampoline)) + { + printf("emote detour failed"); + } + if (!EzDetour(CObfuscator__doit,&CObfuscator::doit_detour,&CObfuscator::doit_tramp)) + { + printf("CObfuscator::doit detour failed"); + } + HookInlineChecks(Patch); + } else { + HookInlineChecks(Patch); + EzUnDetour(__MemChecker0); + EzUnDetour(__MemChecker2); + EzUnDetour(__MemChecker3); + EzUnDetour(__MemChecker4); + EzUnDetour(CObfuscator__doit); + EzUnDetour(CEverQuest__Emote); + } +} + +//extern void Heartbeat(); +void __cdecl PulseService(bool Broadcast, unsigned int MSG, void *lpData) +{ + if (MSG==PULSE_PREFRAME) + { + // "OnPulse" + // Heartbeat is moved back into ProcessGameEvents, where MQ2's heartbeat is +// Heartbeat(); + } +} + +void __cdecl MemoryService(bool Broadcast, unsigned int MSG, void *lpData) +{ + // no messages are currently associated with this service (other than + // system messages such as client disconnect), so do nothing. +} +void __cdecl TriggerService(bool Broadcast, unsigned int MSG, void *lpData) +{ + // no messages are currently associated with this service (other than + // system messages such as client disconnect), so do nothing. +} +void __cdecl HTTPService(bool Broadcast, unsigned int MSG, void *lpData) +{ + switch(MSG) + { +#define pReq ((HttpFile*)lpData) + case HTTPSERVICE_FAILURE: + // HTTP request failed to retrieve document + printf("ISXEQ URL %s failed",pReq->URL); + break; + case HTTPSERVICE_SUCCESS: + // HTTP request successfully retrieved document + printf("ISXEQ URL %s -- %d bytes",pReq->URL,pReq->Size); + // Retrieved data buffer is pReq->pBuffer and is null-terminated + break; +#undef pReq + } +} + +void __cdecl ProtectionRequest(ISXInterface *pClient, unsigned int MSG, void *lpData) +{ + switch(MSG) + { + case MEMPROTECT_PROTECT: +#define pData ((MemProtect*)lpData) + pData->Success=pExtension->Protect(pData->Address,pData->Length,pData->OriginalData); +// printf("Protection: %X for %d length, success=%d",pData->Address,pData->Length,pData->Success); +#undef pData + break; + case MEMPROTECT_UNPROTECT: + pExtension->UnProtect((unsigned int)lpData); + break; + } +} + +#if 0 +void __cdecl SoftwareCursorService(bool Broadcast, unsigned int MSG, void *lpData) +{ + // receives nothing +} +#endif + +bool CISXEQ::Memcpy_Clean(unsigned int BeginAddress, unsigned char *buf, unsigned int buflen) +{ + memcpy(buf,(void*)BeginAddress,buflen); + + unsigned int EndAddress=BeginAddress+buflen; + for (map::iterator i = ProtectedMap.begin() ; i!=ProtectedMap.end() ; i++) + { + if (EQProtected *pProt=i->second) + { + + // find leftmost end + unsigned int RangeEnd=pProt->EndAddress; + if (RangeEnd>EndAddress) + RangeEnd=EndAddress; + + // find rightmost beginning + unsigned int RangeBegin=pProt->Address; + if (RangeBeginAddress; + unsigned int BufOffset = RangeBegin-BeginAddress; + unsigned int Range = RangeEnd-RangeBegin; + memcpy(&buf[BufOffset],&pProt->Array[ProtOffset],Range); + } + } + return true; +} + + diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQ.h b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQ.h new file mode 100644 index 0000000000..0a6c2251cf --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQ.h @@ -0,0 +1,119 @@ +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +#pragma once +#pragma pack(push) +#pragma pack(4) +#include +#pragma pack(pop) +#pragma warning(disable: 4996) +class EQProtected +{ +public: + EQProtected(unsigned int p_Address, unsigned int p_Size, const void *OriginalData) + { + Address=p_Address; + Size=p_Size; + EndAddress=Address+Size; + Array=(unsigned char*)malloc(p_Size); + if (OriginalData) + memcpy(Array,OriginalData, p_Size); + else + memcpy(Array,(char *)p_Address, p_Size); + } + + ~EQProtected() + { + free(Array); + } + + inline bool Contains(unsigned int TestAddress) + { + return (TestAddress>=Address && TestAddress ProtectedMap; +}; + +extern ISInterface *pISInterface; +extern HISXSERVICE hPulseService; +extern HISXSERVICE hMemoryService; +extern HISXSERVICE hHTTPService; +extern HISXSERVICE hTriggerService; + +extern CISXEQ *pExtension; +#define printf pISInterface->Printf + +extern unsigned int ChatEventID; +extern HISXSERVICE hChatService; +extern HISXSERVICE hUIService; +extern HISXSERVICE hGamestateService; +extern HISXSERVICE hSpawnService; +extern HISXSERVICE hZoneService; + +extern unsigned int PersistentPointerClass; + +#define EzDetour(Address, Detour, Trampoline) IS_Detour(pExtension,pISInterface,hMemoryService,(unsigned int)Address,Detour,Trampoline) +#define EzUnDetour(Address) IS_UnDetour(pExtension,pISInterface,hMemoryService,(unsigned int)Address) + +#define EzModify(Address,NewData,Length) Memory_Modify(pExtension,pISInterface,hMemoryService,(unsigned int)Address,NewData,Length,false) +#define EzUnModify(Address) Memory_UnModify(pExtension,pISInterface,hMemoryService,(unsigned int)Address) + +#define EzHttpRequest(_URL_,_pData_) IS_HttpRequest(pExtension,pISInterface,hHTTPService,_URL_,_pData_) + +extern LSType *pStringType; +extern LSType *pIntType; +extern LSType *pBoolType; +extern LSType *pFloatType; +extern LSType *pTimeType; +extern LSType *pByteType; + +extern LSType *pIntPtrType; +extern LSType *pBoolPtrType; +extern LSType *pFloatPtrType; +extern LSType *pBytePtrType; diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommandAPI.cpp b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommandAPI.cpp new file mode 100644 index 0000000000..ef79cacfa3 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommandAPI.cpp @@ -0,0 +1,225 @@ +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +#error /DCINTERFACE +#endif + +#define DBG_SPEW + +#include "..\MQ2Main.h" + +/* +typedef struct _ISXEQAlias +{ + char Replacement[256]; +} ISXEQALIAS, *PISXEQALIAS; + +map ISXEQAliases; + + +PISXEQALIAS FindISXEQAlias(const char *Token) +{ + if (!Token || !Token[0]) + return 0; + char Temp[512]; + strcpy(Temp,Token); + strlwr(Temp); + return ISXEQAliases[Temp]; +} + +void AddISXEQAlias(const char *Replace, const char *With) +{ + if (!Replace || !Replace[0]) + return; + if (!With || !With[0]) + return; + PISXEQALIAS pAlias=FindISXEQAlias(Replace); + if (pAlias) + { + strcpy(pAlias->Replacement,With); + return; + } + pAlias=new ISXEQALIAS; + strcpy(pAlias->Replacement,With); + char Temp[512]; + strcpy(Temp,Replace); + strlwr(Temp); + ISXEQAliases[Temp]=pAlias; +} + +bool RemoveISXEQAlias(const char *Token) +{ + if (!Token || !Token[0]) + return 0; + char Temp[512]; + strcpy(Temp,Token); + strlwr(Temp); + PISXEQALIAS pAlias=ISXEQAliases[Temp]; + if (!pAlias) + return false; + delete pAlias; + ISXEQAliases[Temp]=0; + return true; +} +/**/ + +extern VOID StrReplaceSection(PCHAR szInsert,DWORD Length,PCHAR szNewString); + + +bool ExecuteISCommand(char *Command, char *Parameters=0) +{ + char Temp[4096]={0}; + if (!strchr(Command,':') && !pISInterface->IsAlias(Command) && !pISInterface->ResolveAtom(Command) && !pISInterface->ResolveCommand(Command,Temp,sizeof(Temp))) + { + return false; + } + + if (Parameters) + { + sprintf(Temp,"%s %s",Command,Parameters); + pISInterface->ExecuteCommand(Temp); + } + else + pISInterface->ExecuteCommand(Command); + + return true; +} + +class CCommandHook +{ +public: + VOID Detour(PSPAWNINFO pChar, PCHAR szFullLine) + { + //DebugSpew("CCommandHook::Detour(%s)",szFullLine); + + // apply one alias + char FullCommand[4096]; + strcpy(FullCommand,szFullLine); + szFullLine=FullCommand; + + char CommandName[256]={0}; + + char *pSpace=strchr(FullCommand,' '); + if (pSpace) + *pSpace=0; + strcpy(CommandName,FullCommand); + if (pSpace) + { + *pSpace=' '; + pSpace++; + } + + if (CommandName[0]!='/' || !CommandName[1] || !ExecuteISCommand(&CommandName[1],pSpace)) + { + char FullCommand[8192]={0}; +// strcpy(FullCommand,szFullLine); + pISInterface->DataParse(szFullLine,FullCommand,8192); + Trampoline(pChar,FullCommand); + } + strcpy(szLastCommand,FullCommand); + + /* + PISXEQALIAS pAlias=FindISXEQAlias(CommandName); + if (pAlias) + StrReplaceSection(CommandName,strlen(CommandName),pAlias->Replacement); + + if (CommandName[0]=='/' && CommandName[1] && pISInterface->IsCommand(&CommandName[1])) + { + + } + if (szFullLine[0]=='#') + { + pISInterface->ExecuteCommand(&szFullLine[1]); + strcpy(szLastCommand,szFullLine); + } + else + { + char FullCommand[8192]={0}; + strcpy(FullCommand,szFullLine); + pISInterface->DataParse(FullCommand); + Trampoline(pChar,FullCommand); + strcpy(szLastCommand,FullCommand); + } + /**/ + } + + VOID Trampoline(PSPAWNINFO pChar, PCHAR szFullLine); + +}; + +DETOUR_TRAMPOLINE_EMPTY(VOID CCommandHook::Trampoline(PSPAWNINFO pChar, PCHAR szFullLine)); + +int CMD_EQExecute(int argc, char *argv[]) +{ + if (gGameState!=GAMESTATE_INGAME) + { + WriteChatf("Cannot execute EQ command, not in game!"); + return 0; + } + if (argc<2) + { + WriteChatf("Syntax: %s ",argv[0]); + return 0; + } + char Line[8192]={0}; + pISInterface->GetArgs(1,argc,argv,Line,sizeof(Line)); + ((CCommandHook*)pEverQuest)->Trampoline((PSPAWNINFO)pLocalPlayer,Line); + return 0; +} + +VOID HideDoCommand(PSPAWNINFO pChar, PCHAR szLine, BOOL delayed) +{ + pEverQuest->InterpretCmd((EQPlayer*)pChar,szLine); +} + + +void InitializeMQ2Commands() +{ + EzDetour(CEverQuest__InterpretCmd,&CCommandHook::Detour,&CCommandHook::Trampoline); + +#define COMMAND(name,cmd,parse,hide) pISInterface->AddCommand(name,cmd,parse,hide) +#include "ISXEQCommandList.h" +#undef COMMAND + + pISInterface->AddAlias("d","EQExecute /duel"); + pISInterface->AddAlias("t","EQExecute /tell"); + pISInterface->AddAlias("w","EQExecute /who"); + pISInterface->AddAlias("a","EQExecute /anonymous"); + pISInterface->AddAlias("ta","EQExecute /tap"); + pISInterface->AddAlias("c","EQExecute /consider"); + pISInterface->AddAlias("cha","EQExecute /channel"); + pISInterface->AddAlias("f","EQExecute /feedback"); + pISInterface->AddAlias("fa","EQExecute /fastdrop"); + pISInterface->AddAlias("m","EQExecute /msg"); + pISInterface->AddAlias("load","EQExecute /loadspells"); + pISInterface->AddAlias("b","EQExecute /bazaar"); + pISInterface->AddAlias("ba","EQExecute /bazaar"); + pISInterface->AddAlias("g","EQExecute /gsay"); + pISInterface->AddAlias("gu","EQExecute /guildsay"); + pISInterface->AddAlias("key","EQExecute /keys"); + pISInterface->AddAlias("r","EQExecute /reply"); + pISInterface->AddAlias("time","EQExecute /time"); +} + +void ShutdownMQ2Commands() +{ +#define COMMAND(name,cmd,parse,hide) pISInterface->RemoveCommand(name) +#include "ISXEQCommandList.h" +#undef COMMAND + + EzUnDetour(CEverQuest__InterpretCmd); + +} + diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommandList.h b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommandList.h new file mode 100644 index 0000000000..f1900d45ee --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommandList.h @@ -0,0 +1,43 @@ +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +COMMAND("Keypress",CMD_Keypress,true,false); +COMMAND("EQExecute",CMD_EQExecute,true,false); +COMMAND("MQ2Bind",CMD_MQ2Bind,true,false); +COMMAND("Who",CMD_Who,true,false); +COMMAND("Beep",CMD_Beep,true,false); +COMMAND("Ranged",CMD_do_ranged,true,false); +COMMAND("SetAutoRun",CMD_SetAutoRun,true,false); +COMMAND("DisplayLoginName",CMD_DisplayLoginName,true,false); +COMMAND("PopupText",CMD_PopupText,true,false); +COMMAND("BuyItem",CMD_BuyItem,true,false); +COMMAND("SellItem",CMD_SellItem,true,false); +COMMAND("Target",CMD_Target,true,false); +COMMAND("WhoFilter",CMD_WhoFilter,true,false); +COMMAND("Where",CMD_Where,true,false); +COMMAND("CastSpell",CMD_CastSpell,true,false); +COMMAND("MemSpell",CMD_MemSpell,true,false); +COMMAND("DoAbility",CMD_DoAbility,true,false); +COMMAND("NoModKey",CMD_EQModKey,true,false); +COMMAND("ctrl",CMD_EQModKey,true,false); +COMMAND("alt",CMD_EQModKey,true,false); +COMMAND("shift",CMD_EQModKey,true,false); +COMMAND("destroy",CMD_EQDestroy,true,false); +COMMAND("face",CMD_EQFace,true,false); +COMMAND("look",CMD_EQLook,true,false); +COMMAND("items",CMD_EQItems,true,false); +COMMAND("eqecho",CMD_EQEcho,true,false); +//COMMAND("EQAlias",CMD_EQAlias,true,false); // deprecated +COMMAND("doortarget",CMD_DoorTarget,true,false); +COMMAND("itemtarget",CMD_ItemTarget,true,false); diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommands.cpp b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommands.cpp new file mode 100644 index 0000000000..bdd8b1c08c --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommands.cpp @@ -0,0 +1,1293 @@ +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +#error /DCINTERFACE +#endif + +#define DBG_SPEW + +#include "..\MQ2Main.h" + +/* +// COMMANDS TO CONVERT +EQLIB_API VOID NoModKeyCmd(PSPAWNINFO pChar, PCHAR szLine); +EQLIB_API VOID CaptionColorCmd(PSPAWNINFO pChar, PCHAR szLine); +EQLIB_API VOID CaptionCmd(PSPAWNINFO pChar, PCHAR szLine); +EQLIB_API VOID DropCmd(PSPAWNINFO pChar, PCHAR szLine); +EQLIB_API VOID CombineCmd(PSPAWNINFO pChar, PCHAR szLine); +EQLIB_API VOID ClearErrorsCmd(PSPAWNINFO pChar, PCHAR szLine); +EQLIB_API VOID DoShiftCmd(PSPAWNINFO pChar, PCHAR szLine); +EQLIB_API VOID DoCtrlCmd(PSPAWNINFO pChar, PCHAR szLine); +EQLIB_API VOID DoAltCmd(PSPAWNINFO pChar, PCHAR szLine); +EQLIB_API VOID DumpBindsCommand(PSPAWNINFO pChar, PCHAR szLine); +EQLIB_API VOID LoadCfgCommand(PSPAWNINFO pChar, PCHAR szLine); +EQLIB_API VOID Alert (PSPAWNINFO,PCHAR); +EQLIB_API VOID AltAbility (PSPAWNINFO,PCHAR); +EQLIB_API VOID BankList (PSPAWNINFO,PCHAR); +EQLIB_API VOID BuyItem (PSPAWNINFO,PCHAR); +EQLIB_API VOID CharInfo (PSPAWNINFO,PCHAR); +EQLIB_API VOID Cast (PSPAWNINFO,PCHAR); +EQLIB_API VOID Cleanup (PSPAWNINFO,PCHAR); +EQLIB_API VOID Click (PSPAWNINFO,PCHAR); +EQLIB_API VOID DebugSpewFile (PSPAWNINFO,PCHAR); +EQLIB_API VOID EQDestroyHeldItemOrMoney (PSPAWNINFO,PCHAR); +EQLIB_API VOID DisplayLoginName (PSPAWNINFO,PCHAR); +EQLIB_API VOID DoAbility (PSPAWNINFO,PCHAR); +EQLIB_API VOID DoEvents (PSPAWNINFO,PCHAR); +EQLIB_API VOID DoSocial (PSPAWNINFO,PCHAR); +EQLIB_API VOID Doors (PSPAWNINFO,PCHAR); +EQLIB_API VOID DoorTarget (PSPAWNINFO,PCHAR); +EQLIB_API VOID Exec (PSPAWNINFO,PCHAR); +EQLIB_API VOID Face (PSPAWNINFO,PCHAR); +EQLIB_API VOID Filter (PSPAWNINFO,PCHAR); +EQLIB_API VOID Help (PSPAWNINFO,PCHAR); +EQLIB_API VOID Hotkey (PSPAWNINFO,PCHAR); +EQLIB_API VOID Identify (PSPAWNINFO,PCHAR); +EQLIB_API VOID IniOutput (PSPAWNINFO,PCHAR); +EQLIB_API VOID Items (PSPAWNINFO,PCHAR); +EQLIB_API VOID ItemTarget (PSPAWNINFO,PCHAR); +EQLIB_API VOID WindowState (PSPAWNINFO,PCHAR); +EQLIB_API VOID LoadSpells (PSPAWNINFO,PCHAR); +EQLIB_API VOID Location (PSPAWNINFO,PCHAR); +EQLIB_API VOID Look (PSPAWNINFO,PCHAR); +EQLIB_API VOID MacroLog (PSPAWNINFO,PCHAR); +EQLIB_API VOID MemSpell (PSPAWNINFO,PCHAR); +EQLIB_API VOID MouseTo (PSPAWNINFO,PCHAR); +EQLIB_API VOID MQMsgBox (PSPAWNINFO,PCHAR); +EQLIB_API VOID SellItem (PSPAWNINFO,PCHAR); +EQLIB_API VOID SetError (PSPAWNINFO,PCHAR); +EQLIB_API VOID Skills (PSPAWNINFO,PCHAR); +EQLIB_API VOID Substitute (PSPAWNINFO,PCHAR); +EQLIB_API VOID SuperWhoTarget (PSPAWNINFO,PCHAR); +EQLIB_API VOID SWhoFilter (PSPAWNINFO,PCHAR); +EQLIB_API VOID Target (PSPAWNINFO,PCHAR); +EQLIB_API VOID UpdateItemInfo (PSPAWNINFO,PCHAR); +/**/ + +//EQLIB_API VOID DoMappable(PSPAWNINFO pChar, PCHAR szLine) +int CMD_Keypress(int argc, char *argv[]) +{ + if (argc<2) + { + WriteChatf("Syntax: %s [hold|chat]",argv[0]); + return 0; + } + bool bHold=false; + bool bChat=false; + if (argc==3) + { + if (!stricmp(argv[2],"hold")) + { + bHold=true; + } + else if (!stricmp(argv[2],"chat")) + { + bChat=true; + } + } + if (!PressMQ2KeyBind(argv[1],bHold)) + { + int N=FindMappableCommand(argv[1]); + if (N>=0) + { + ExecuteCmd(N,1,0); + if (!bHold) + ExecuteCmd(N,0,0); + return 0; + } + KeyCombo Temp; + if (ParseKeyCombo(argv[1],Temp)) + { + if (bChat) + { + pWndMgr->HandleKeyboardMsg(Temp.Data[3],1); + pWndMgr->HandleKeyboardMsg(Temp.Data[3],0); + } + else + { + MQ2HandleKeyDown(Temp); + if (!bHold) + MQ2HandleKeyUp(Temp); + } + return 0; + } + + WriteChatf("Invalid mappable command or key combo '%s'",argv[1]); + return -1; + } + return 0; +} + +int CMD_Who(int argc, char *argv[]) +{ + if (!cmdWho) + { + PCMDLIST pCmdListOrig = (PCMDLIST)EQADDR_CMDLIST; + for (int i=0;pCmdListOrig[i].fAddress != 0;i++) { + if (!strcmp(pCmdListOrig[i].szName,"/who")) { + cmdWho = (fEQCommand)pCmdListOrig[i].fAddress; + } + } + } + if (!cmdWho) return -1; + + for (int i = 1 ; i < argc ; i++) + { + if (!stricmp(argv[i],"all")) + { + CHAR szRest[MAX_STRING] = {0}; + pISInterface->GetArgs(1,argc,argv,szRest,sizeof(szRest)); + cmdWho((PSPAWNINFO)pLocalPlayer, szRest); + return 0; + } + } + + bool bConColor=false; + SEARCHSPAWN SearchSpawn; + + ClearSearchSpawn(&SearchSpawn); + SearchSpawn.SpawnType = PC; + + for (int i = 1 ; i < argc ; i++) + { + if (!stricmp(argv[i],"sort")) + { + // + PCHAR szSortBy[] = { + "level", // Default sort by + "name", + "race", + "class", + "distance", + "guild", + "id", + NULL }; + DWORD Command=0; + for (Command;szSortBy[Command];Command++) + { + if (!stricmp(argv[i],szSortBy[Command])) + { + SearchSpawn.SortBy = Command; + if (i1) + { + pRangedTarget=GetSpawnByID(atoi(argv[1])); + if (!pRangedTarget) + { + printf("Invalid spawn ID. Use /ranged with no parameters, or with a spawn ID"); + return 0; + } + } + if (!pRangedTarget) + { + printf("No target for ranged attack"); + return 0; + } + if (gbRangedAttackReady) + { + pLocalPlayer->DoAttack(0x0B,0,pRangedTarget); + gbRangedAttackReady=0; + } + return 0; +} +// /autorun +int CMD_SetAutoRun(int argc, char *argv[]) +{ + if (argc<2) + { + WriteChatf("Syntax: %s on|off",argv[0]); + return 0; + } +#if 0 + if(!stricmp(argv[1],"on") || !stricmp(argv[1],"off")) + { + CHAR szServerAndName[MAX_STRING] = {0}; + sprintf(szServerAndName,"%s.%s",((PCHARINFO)pCharData)->Server,((PCHARINFO)pCharData)->Name); + WritePrivateProfileString(szServerAndName,"AutoRun",argv[1],gszINIFilename); + sprintf(szServerAndName,"Set autorun to: '%s'",argv[1]); + WriteChatColor(szServerAndName,USERCOLOR_DEFAULT); + } +#endif + return 0; +} + +// /loginname +int CMD_DisplayLoginName(int argc, char *argv[]) +{ + PCHAR szLogin = GetLoginName(); + if (!szLogin) { + printf("Unable to retrieve login name."); + } else { + WriteChatf("Login name: \ay%s\ax",szLogin); + free(szLogin); + } + return 0; +} + +// /popup +int CMD_PopupText(int argc, char *argv[]) +{ + if (argc<2) + { + printf("Syntax: %s ",argv[0]); + return 0; + } + + CHAR szRest[MAX_STRING] = {0}; + pISInterface->GetArgs(1,argc,argv,szRest, sizeof(szRest)); + DisplayOverlayText(szRest, CONCOLOR_LIGHTBLUE, 100, 500,500,3000); + return 0; +} + +int CMD_BuyItem(int argc, char *argv[]) +{ + if (argc<2) + { + WriteChatf("Syntax: %s ",argv[0]); + return 0; + } + if (!pMerchantWnd) + { + return 0; + } + PCHARINFO pCharInfo; + if (NULL == (pCharInfo = GetCharInfo())) + return 0; + + DWORD Qty=(DWORD)atoi(argv[1]); + + if (Qty > 20 || Qty < 1) return 0; + pMerchantWnd->RequestBuyItem(Qty); + return 0; +} +int CMD_SellItem(int argc, char *argv[]) +{ + if (argc<2) + { + WriteChatf("Syntax: %s ",argv[0]); + return 0; + } + if (!pMerchantWnd) + return 0; + PCHARINFO pCharInfo; + if (NULL == (pCharInfo = GetCharInfo())) return 0; + + DWORD Qty = (DWORD)atoi(argv[1]); + if (Qty > 20 || Qty < 1) return 0; + pMerchantWnd->RequestSellItem(Qty); + return 0; +} + +int CMD_Target(int argc, char* argv[]) +{ + if (!ppSpawnManager) return 0; + if (!pSpawnList) return 0; + if (argc<2) + { + WriteChatf("Syntax: %s myself|mycorpse|clear|",argv[0]); + return 0; + } + + PSPAWNINFO pChar = GetCharInfo()->pSpawn; + PSPAWNINFO pSpawnClosest = NULL; + + SEARCHSPAWN SearchSpawn; + ClearSearchSpawn(&SearchSpawn); + CHAR szMsg[MAX_STRING] = {0}; + BOOL DidTarget = FALSE; + BOOL bArg = TRUE; + + bRunNextCommand = TRUE; + for(int i=1;iName); + } + } else if (!stricmp(argv[i],"clear")) { + pTarget = NULL; + DebugSpew("Target cleared."); + WriteChatColor("Target cleared.",USERCOLOR_WHO); + return 0; + } else { + i+= ParseSearchSpawnArg(i,argc,argv,SearchSpawn); + } + } + + if (pTarget) SearchSpawn.FromSpawnID = ((PSPAWNINFO)pTarget)->SpawnID; + + if (!DidTarget) { + pSpawnClosest = SearchThroughSpawns(&SearchSpawn,pChar); + } + + if (!pSpawnClosest) { + CHAR szTemp[MAX_STRING] = {0}; + sprintf(szMsg,"There are no spawns matching: %s",FormatSearchSpawn(szTemp,&SearchSpawn)); + } else { + PSPAWNINFO *psTarget = NULL; + if (ppTarget) { + psTarget = (PSPAWNINFO*)ppTarget; + *psTarget = pSpawnClosest; + DebugSpew("Target - %s selected",pSpawnClosest->Name); + szMsg[0]=0; + } else { + sprintf(szMsg,"Unable to target, address = 0"); + } + } + if (szMsg[0]) + if (!gFilterTarget) WriteChatColor(szMsg,USERCOLOR_WHO); + return 0; +} + +int CMD_WhoFilter(int argc, char* argv[]) +{ + if (argc < 3) + { + WriteChatf("Syntax: %s [on|off]",0); + return 0; + } + + if (!stricmp(argv[1],"Lastname")) { + SetDisplaySWhoFilter(&gFilterSWho.Lastname,"Lastname",argv[2]); + } else if (!stricmp(argv[1],"Class")) { + SetDisplaySWhoFilter(&gFilterSWho.Class,"Class",argv[2]); + } else if (!stricmp(argv[1],"Race")) { + SetDisplaySWhoFilter(&gFilterSWho.Race,"Race",argv[2]); + } else if (!stricmp(argv[1],"Body")) { + SetDisplaySWhoFilter(&gFilterSWho.Body,"Body",argv[2]); + } else if (!stricmp(argv[1],"Level")) { + SetDisplaySWhoFilter(&gFilterSWho.Level,"Level",argv[2]); + } else if (!stricmp(argv[1],"GM")) { + SetDisplaySWhoFilter(&gFilterSWho.GM,"GM",argv[2]); + } else if (!stricmp(argv[1],"Guild")) { + SetDisplaySWhoFilter(&gFilterSWho.Guild,"Guild",argv[2]); + } else if (!stricmp(argv[1],"LD")) { + SetDisplaySWhoFilter(&gFilterSWho.LD,"LD",argv[2]); + } else if (!stricmp(argv[1],"Sneak")) { + SetDisplaySWhoFilter(&gFilterSWho.Sneak,"Sneak",argv[2]); + } else if (!stricmp(argv[1],"LFG")) { + SetDisplaySWhoFilter(&gFilterSWho.LFG,"LFG",argv[2]); + } else if (!stricmp(argv[1],"NPCTag")) { + SetDisplaySWhoFilter(&gFilterSWho.NPCTag,"NPCTag",argv[2]); + } else if (!stricmp(argv[1],"SpawnID")) { + SetDisplaySWhoFilter(&gFilterSWho.SpawnID,"SpawnID",argv[2]); + } else if (!stricmp(argv[1],"Trader")) { + SetDisplaySWhoFilter(&gFilterSWho.Trader,"Trader",argv[2]); + } else if (!stricmp(argv[1],"AFK")) { + SetDisplaySWhoFilter(&gFilterSWho.AFK,"AFK",argv[2]); + } else if (!stricmp(argv[1],"Anon")) { + SetDisplaySWhoFilter(&gFilterSWho.Anon,"Anon",argv[2]); + } else if (!stricmp(argv[1],"Distance")) { + SetDisplaySWhoFilter(&gFilterSWho.Distance,"Distance",argv[2]); + } else if (!stricmp(argv[1],"Light")) { + SetDisplaySWhoFilter(&gFilterSWho.Light,"Light",argv[2]); + } else if (!stricmp(argv[1],"Holding")) { + SetDisplaySWhoFilter(&gFilterSWho.Holding,"Holding",argv[2]); + } else if (!stricmp(argv[1],"ConColor")) { + SetDisplaySWhoFilter(&gFilterSWho.ConColor,"ConColor",argv[2]); + } else if (!stricmp(argv[1],"Invisible")) { + SetDisplaySWhoFilter(&gFilterSWho.Invisible,"Invisible",argv[2]); + } else { + WriteChatf("Syntax: %s [on|off]",0); + } + return 0; +} + +// *************************************************************************** +// Function: CMD_Where +// Description: Our '/where' command +// Displays the direction and distance to the closest spawn +// Usage: /where +// *************************************************************************** +int CMD_Where(int argc, char* argv[]) +{ + if (argc<2) + { + WriteChatf("Syntax: %s ",argv[0]); + return 0; + } + if (!ppSpawnManager) return 0; + if (!pSpawnList) return 0; + PSPAWNINFO pChar = GetCharInfo()->pSpawn; + PSPAWNINFO pSpawnClosest = NULL; + SEARCHSPAWN SearchSpawn; + ClearSearchSpawn(&SearchSpawn); + CHAR szMsg[MAX_STRING] = {0}; + CHAR szName[MAX_STRING] = {0}; + CHAR szArg[MAX_STRING] = {0}; + + bRunNextCommand = TRUE; + SearchSpawn.SpawnType= PC; + + ParseSearchSpawn(1,argc,argv,SearchSpawn); + + if (!(pSpawnClosest = SearchThroughSpawns(&SearchSpawn,pChar))) { + sprintf(szMsg,"There were no matches for: %s",FormatSearchSpawn(szArg,&SearchSpawn)); + } else { + INT Angle = (INT)((atan2f(pChar->X - pSpawnClosest->X, pChar->Y - pSpawnClosest->Y) * 180.0f / PI + 360.0f) / 22.5f + 0.5f) % 16; + sprintf(szMsg,"The closest '%s' is a level %d %s %s and %1.2f away to the %s, Z difference = %1.2f", + CleanupName(strcpy(szName,pSpawnClosest->Name),FALSE), + pSpawnClosest->Level, + pEverQuest->GetRaceDesc(pSpawnClosest->Race), + GetClassDesc(pSpawnClosest->Class), + DistanceToSpawn(pChar,pSpawnClosest), + szHeading[Angle], + pSpawnClosest->Z-pChar->Z); + DebugSpew("Where - %s",szMsg); + } + WriteChatColor(szMsg,USERCOLOR_WHO); + + return 0; +} + + +// *************************************************************************** +// Function: CMD_CastSpell +// Description: Our '/cast' command +// Displays the direction and distance to the closest spawn +// Usage: /cast [list|#|"name of spell"|item "name of item"] +// *************************************************************************** +int CMD_CastSpell(int argc, char* argv[]) +{ + DWORD Index; + if (gGameState!=GAMESTATE_INGAME) + return -1; + + if (!cmdCast) + { + PCMDLIST pCmdListOrig = (PCMDLIST)EQADDR_CMDLIST; + for (int i=0;pCmdListOrig[i].fAddress != 0;i++) { + if (!strcmp(pCmdListOrig[i].szName,"/cast")) { + cmdCast = (fEQCommand)pCmdListOrig[i].fAddress; + } + } + } + if (!cmdCast) return -1; + if (argc<2) + { + WriteChatf("Syntax: %s list|#||item ",argv[0]); + return 0; + } + + if ( !ppSpellMgr || !ppCharData || !pCharData) { + return -1; + } + PCHARINFO pCharInfo = GetCharInfo(); + if (NULL == pCharInfo) return -1; + if (argc == 2 && atoi(argv[1])){ + cmdCast((PSPAWNINFO)pLocalPlayer, argv[1]); + return 0; + } + // CHAR szArg1[MAX_STRING] = {0}; + // CHAR szArg2[MAX_STRING] = {0}; + if (!stricmp(argv[1],"list")) { + WriteChatColor("Spells:",USERCOLOR_DEFAULT); + for (Index=0;IndexMemorizedSpells[Index]==0xFFFFFFFF) { + WriteChatf("%d. ",Index+1); + } else { + WriteChatf("%d. %s",Index+1,GetSpellByID(GetCharInfo2()->MemorizedSpells[Index])); + } + } + return 0; + } + + // GetArg(szArg1,szLine,1); + // GetArg(szArg2,szLine,2); + // DebugSpew("Cast: szArg1 = %s szArg2 = %s",szArg1,szArg2); + if (!stricmp(argv[1],"item")) + { + BOOL FOUND = FALSE; + DWORD item = 0; + DWORD slot = 0; + DWORD SpawnFooter = NULL; + SpawnFooter = (DWORD)pLocalPlayer; + PITEMINFO pItem=0; + for (int i=0;ipInventoryArray->InventoryArray[i]) + if (!_stricmp(argv[2],GetItemFromContents(GetCharInfo2()->pInventoryArray->InventoryArray[i])->Name)) { + DebugSpew("cast test slot %d = %s address is %x",i,GetItemFromContents(GetCharInfo2()->pInventoryArray->InventoryArray[i])->Name,&(GetCharInfo2()->pInventoryArray->InventoryArray[i])); + item = (DWORD)&GetCharInfo2()->pInventoryArray->InventoryArray[i]; + pItem=GetItemFromContents(GetCharInfo2()->pInventoryArray->InventoryArray[i]); + slot = (DWORD)i; + FOUND = TRUE; + break; + } + } + if (FOUND) { + if(CInvSlot *pSlot = pInvSlotMgr->FindInvSlot(slot)) + { + CXPoint p; p.A=0; p.B=0; + pSlot->HandleRButtonUp(&p); + } + return 0; + } + } + for (Index=0;IndexMemorizedSpells[Index]!=0xFFFFFFFF) { + PCHAR SpellName = GetSpellNameByID(GetCharInfo2()->MemorizedSpells[Index]); + if (!stricmp(argv[1],SpellName)) { + DebugSpew("SpellName = %s",SpellName); + + char szBuffer[256]; + cmdCast((PSPAWNINFO)pLocalPlayer,itoa(Index+1,szBuffer,10)); + + DebugSpew("pChar = %x SpellName = %s %d",pCharInfo,SpellName,Index+1); + return 0; + } + } + } + WriteChatColor("You do not seem to have that spell memorized.",USERCOLOR_DEFAULT); + return 0; + +} + +// *************************************************************************** +// Function: MemSpell +// Description: Our '/MemSpell' command +// Usage: /MemSpell gem# "spell name" +// *************************************************************************** +SPELLFAVORITE MemSpellFavorite; +int CMD_MemSpell(int argc, char *argv[]) +{ + if (argc < 3) + { + WriteChatf("Syntax: %s ",argv[0]); + return 0; + } + if (!ppSpellBookWnd) return -1; + DWORD Favorite = (DWORD)&MemSpellFavorite; + DWORD sp; + WORD Gem = -1; + PCHARINFO pCharInfo = NULL; + if (!pSpellBookWnd) return -1; + if (NULL == (pCharInfo = GetCharInfo())) return -1; + + Gem = atoi(argv[1]); + if (Gem<1 || Gem>NUM_SPELL_GEMS) return -1; + Gem--; + + GetCharInfo2()->SpellBook; + PSPELL pSpell=0; + for (DWORD N = 0 ; N < NUM_BOOK_SLOTS ; N++) + if (PSPELL pTempSpell=GetSpellByID(GetCharInfo2()->SpellBook[N])) + { + if (!stricmp(argv[2],pTempSpell->Name)) + { + pSpell=pTempSpell; + break; + } + } + + if (!pSpell) return -1; + if (pSpell->Level[GetCharInfo2()->Class-1]>GetCharInfo2()->Level) return -1; + + ZeroMemory(&MemSpellFavorite,sizeof(MemSpellFavorite)); + strcpy(MemSpellFavorite.Name,"Mem a Spell"); + MemSpellFavorite.inuse=1; + for (sp=0;spID; + pSpellBookWnd->MemorizeSet((int*)Favorite,NUM_SPELL_GEMS); + return 0; +} + +// *************************************************************************** +// Function: DoAbility +// Description: Our '/doability' command +// Does (or lists) your abilities +// Usage: /doability [list|ability|#] +// *************************************************************************** +int CMD_DoAbility(int argc, char *argv[]) +{ + if (argc<2) + { + printf("Syntax: %s list|",argv[0]); + return 0; + } + + DWORD Index, DoIndex = 0xFFFFFFFF; + + if (!stricmp(argv[1],"list") || !stricmp(argv[1], "-list")) + { + WriteChatColor("Abilities:",USERCOLOR_DEFAULT); + for (Index=4;Index<10;Index++) { + if (EQADDR_DOABILITYLIST[Index]==0xFFFFFFFF) + { + WriteChatf("%d. ",Index-3); + } + else if (szSkills[EQADDR_DOABILITYLIST[Index]]) + { + WriteChatf("%d. %s",Index-3,szSkills[EQADDR_DOABILITYLIST[Index]]); + } + else + { + WriteChatf("%d. *Unknown%d",Index-3,EQADDR_DOABILITYLIST[Index]); + } + } + WriteChatColor("Combat Skills:"); + for (Index=0;Index<4;Index++) + { + if (EQADDR_DOABILITYLIST[Index]==0xFFFFFFFF) + { + WriteChatf("%d. ",Index+7); + } + else if (szSkills[EQADDR_DOABILITYLIST[Index]]) + { + WriteChatf("%d. %s",Index+7,szSkills[EQADDR_DOABILITYLIST[Index]]); + } + else + { + WriteChatf("%d. *Unknown%d",Index+7,EQADDR_DOABILITYLIST[Index]); + } + } + WriteChatColor("Combat Abiilities:",USERCOLOR_DEFAULT); + for (Index=10;Index<18;Index++) + { + if (EQADDR_DOABILITYLIST[Index]==0xFFFFFFFF) + { + WriteChatf("%d. ",Index+1); + } + else if (EQADDR_DOABILITYLIST[Index] > 132) + { // highest number we have defined so far + WriteChatf("%d. *Unknown%d",Index+1,EQADDR_DOABILITYLIST[Index]); + } + else if (szSkills[EQADDR_DOABILITYLIST[Index]]) + { + WriteChatf("%d. %s",Index+1,szSkills[EQADDR_DOABILITYLIST[Index]]); + } + else + { + WriteChatf("%d. *Unknown%d",Index+1,EQADDR_DOABILITYLIST[Index]); + } + } + return 0; + } + + UseAbility(argv[1]); + + return 0; +} +/* +int CMD_DoAbility(int argc, char *argv[]) +{ + if (!cmdDoAbility) + { + PCMDLIST pCmdListOrig = (PCMDLIST)EQADDR_CMDLIST; + for (int i=0;pCmdListOrig[i].fAddress != 0;i++) { + if (!strcmp(pCmdListOrig[i].szName,"/doability")) { + cmdDoAbility = (fEQCommand)pCmdListOrig[i].fAddress; + } + } + } + if (!cmdDoAbility) return -1; + + if (argc<2 || atoi(argv[1]) || !EQADDR_DOABILITYLIST) { + cmdDoAbility((PSPAWNINFO)pLocalPlayer,argv[1]); + return 0; + } + + DWORD Index, DoIndex = 0xFFFFFFFF; + CHAR szBuffer[MAX_STRING] = {0}; + + if (!stricmp(argv[1],"list") || !stricmp(argv[1], "-list")) { + WriteChatColor("Abilities:",USERCOLOR_DEFAULT); + for (Index=4;Index<10;Index++) { + if (EQADDR_DOABILITYLIST[Index]==0xFFFFFFFF) { + sprintf(szBuffer,"%d. ",Index-3); + } else if (szSkills[EQADDR_DOABILITYLIST[Index]]) { + sprintf(szBuffer,"%d. %s",Index-3,szSkills[EQADDR_DOABILITYLIST[Index]]); + } else { + sprintf(szBuffer,"%d. *Unknown%d",Index-3,EQADDR_DOABILITYLIST[Index]); + } + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + WriteChatColor("Combat Skills:",USERCOLOR_DEFAULT); + for (Index=0;Index<4;Index++) { + if (EQADDR_DOABILITYLIST[Index]==0xFFFFFFFF) { + sprintf(szBuffer,"%d. ",Index+7); + } else if (szSkills[EQADDR_DOABILITYLIST[Index]]) { + sprintf(szBuffer,"%d. %s",Index+7,szSkills[EQADDR_DOABILITYLIST[Index]]); + } else { + sprintf(szBuffer,"%d. *Unknown%d",Index+7,EQADDR_DOABILITYLIST[Index]); + } + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + WriteChatColor("Combat Abiilities:",USERCOLOR_DEFAULT); + for (Index=10;Index<18;Index++) { + if (EQADDR_DOABILITYLIST[Index]==0xFFFFFFFF) { + sprintf(szBuffer,"%d. ",Index+1); + } else if (EQADDR_DOABILITYLIST[Index] > 132) { // highest number we have defined so far + sprintf(szBuffer,"%d. *Unknown%d",Index+1,EQADDR_DOABILITYLIST[Index]); + } else if (szSkills[EQADDR_DOABILITYLIST[Index]]) { + sprintf(szBuffer,"%d. %s",Index+1,szSkills[EQADDR_DOABILITYLIST[Index]]); + } else { + sprintf(szBuffer,"%d. *Unknown%d",Index+1,EQADDR_DOABILITYLIST[Index]); + } + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + return 0; + } + + pISInterface->GetArgs(1,argc,argv,szBuffer); + + for (Index=0;Index<10;Index++) { + if (EQADDR_DOABILITYLIST[Index]!= 0xFFFFFFFF) { + if (!strnicmp(szBuffer,szSkills[EQADDR_DOABILITYLIST[Index]],strlen(szSkills[EQADDR_DOABILITYLIST[Index]]))) { + if (Index<4) { + DoIndex = Index+7; // 0-3 = Combat abilities (7-10) + } else { + DoIndex = Index-3; // 4-9 = Abilities (1-6) + } + } + } + } + if (DoIndex!=0xFFFFFFFF) { + cmdDoAbility((PSPAWNINFO)pLocalPlayer,itoa(DoIndex,szBuffer,10)); + } else { + WriteChatColor("You do not seem to have that ability on a /doability button",USERCOLOR_DEFAULT); + } + return 0; +} +/**/ + +// CMD_EQModKey +int CMD_EQModKey(int argc, char *argv[]) +{ + CHAR chCommand[2048] = {0}; + bool KeyboardFlags[4] = {false,false,false,false}; + + if (argc<1) + { + WriteChatf("Usage: %s ", argv[0]); + return 0; + } + pISInterface->GetArgs(1,argc,argv,chCommand,sizeof(chCommand)); + *(DWORD*)&KeyboardFlags=*(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags; + if (!stricmp(argv[0],"nomodkey")) + *(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags=0; + else if (!stricmp(argv[0],"shift")) + ((PCXWNDMGR)pWndMgr)->KeyboardFlags[0]=1; + else if (!stricmp(argv[0],"ctrl")) + ((PCXWNDMGR)pWndMgr)->KeyboardFlags[1]=1; + else if (!stricmp(argv[0],"alt")) + ((PCXWNDMGR)pWndMgr)->KeyboardFlags[2]=1; + DebugSpew("CMD_EQModKey Executing %s", chCommand); + pISInterface->ExecuteCommand(chCommand); + *(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags=*(DWORD*)&KeyboardFlags; + return 0; +} +int CMD_EQDestroy(int argc, char *argv[]) +{ + (pPCData)->DestroyHeldItemOrMoney(); + return 0; +} + + +int CMD_EQFace(int argc, char *argv[]) +{ +//VOID Face(PSPAWNINFO pChar, PCHAR szLine) +//{ + if (!ppSpawnManager) return 0; + if (!pSpawnList) return 0; + PSPAWNINFO pSpawnClosest = NULL; + PSPAWNINFO psTarget = NULL; + SPAWNINFO LocSpawn = {0}; + PSPAWNINFO pChar = (PSPAWNINFO)pLocalPlayer; + SEARCHSPAWN SearchSpawn; + ClearSearchSpawn(&SearchSpawn); + CHAR szMsg[MAX_STRING] = {0}; + CHAR szName[MAX_STRING] = {0}; + CHAR szArg[MAX_STRING] = {0}; + PCHAR pszArg = NULL; + BOOL bArg = TRUE; + BOOL bOtherArgs = FALSE; + BOOL Away = FALSE; + BOOL Predict = FALSE; + BOOL Fast = FALSE; + BOOL Look = TRUE; + BOOL Parsing = TRUE; + DOUBLE Distance; + + for(int qq=1; qqY = (FLOAT)atof(argv[qq]); + pszArg = strstr(argv[qq],",")+1; + pSpawnClosest->X = (FLOAT)atof(pszArg); + } + } else if (!stricmp(argv[qq], "item")) { + if (EnviroTarget.Name[0]==0) { + printf("%s: item specified but no item targetted.", argv[0]); + return 0; + } + pSpawnClosest = &EnviroTarget; + } else if (!stricmp(argv[qq], "door")) { + if (DoorEnviroTarget.Name[0]==0) { + printf("%s: door specified but no door targetted.",argv[0]); + return 0; + } + pSpawnClosest = &DoorEnviroTarget; + } else if (!stricmp(argv[qq], "heading")) { + if ((++qq)=512.0f) gFaceAngle -= 512.0f; + if (gFaceAngle<0.0f) gFaceAngle += 512.0f; + if (Fast) { + ((PSPAWNINFO)pCharSpawn)->Heading = (FLOAT)gFaceAngle; + gFaceAngle=10000.0f; + } + } + return 0; + } else if (!strcmp(szArg,"help")) { + printf("Usage: %s [spawn] [item] [door] [id #] [heading ] [loc ,] [away] [alert #]",argv[0]); + return 0; + } else { + bOtherArgs = TRUE; + qq+=ParseSearchSpawnArg(qq,argc,argv,SearchSpawn); +// szFilter = ParseSearchSpawnArgs(szArg,szFilter,&SearchSpawn); + } + } + + if (!pSpawnClosest) { + if (!bOtherArgs) { + if (ppTarget && pTarget) { + pSpawnClosest = (PSPAWNINFO)pTarget; + } + } else { + pSpawnClosest = SearchThroughSpawns(&SearchSpawn,pChar); + } + } + + szMsg[0]=0; + + if (!pSpawnClosest) { + printf("There were no matches for: %s",FormatSearchSpawn(szArg,&SearchSpawn)); + } else { + if (Predict) { + Distance = DistanceToSpawn(pChar, pSpawnClosest); + gFaceAngle = ( + atan2((pSpawnClosest->X + (pSpawnClosest->SpeedX * Distance)) - pChar->X, + (pSpawnClosest->Y + (pSpawnClosest->SpeedY * Distance)) - pChar->Y) + * 256.0f / PI); + } else { + gFaceAngle = ( + atan2(pSpawnClosest->X - pChar->X, + pSpawnClosest->Y - pChar->Y) + * 256.0f / PI); + } + if (Look) { + Distance = DistanceToSpawn(pChar, pSpawnClosest); + gLookAngle = ( + atan2(pSpawnClosest->Z + pSpawnClosest->AvatarHeight*StateHeightMultiplier(pSpawnClosest->StandState) - pChar->Z - pChar->AvatarHeight*StateHeightMultiplier(pChar->StandState), + (FLOAT)Distance) + * 256.0f / PI); + if (Away) gLookAngle = -gLookAngle; + if (Fast) { + pChar->CameraAngle = (FLOAT)gLookAngle; + gLookAngle=10000.0f; + } + } + if (Away) { + gFaceAngle += 256.0f; + } + if (gFaceAngle>=512.0f) gFaceAngle -= 512.0f; + if (gFaceAngle<0.0f) gFaceAngle += 512.0f; + if (Fast) { + ((PSPAWNINFO)pCharSpawn)->Heading = (FLOAT)gFaceAngle; + gFaceAngle=10000.0f; + } + sprintf(szMsg,"Facing %s'%s'...",(Away)?"away from ":"", CleanupName(strcpy(szName,pSpawnClosest->Name),FALSE)); + } + if (ppTarget && pTarget) { + psTarget = (PSPAWNINFO)pTarget; + } + if (szMsg[0] && ((pSpawnClosest != &LocSpawn) && ((Away) || (pSpawnClosest != psTarget)))) WriteChatColor(szMsg,USERCOLOR_WHO); + DebugSpew("Face - %s",szMsg); + return 0; +} + + +// *************************************************************************** +// Function: Look +// Description: Our /look command. Changes camera angle +// 2003-08-30 MacroFiend +// *************************************************************************** +int CMD_EQLook(int argc, char *argv[]) +{ + FLOAT fLookAngle=0.0f; + PSPAWNINFO pChar = (PSPAWNINFO)pLocalPlayer; + if (argc < 2) + return 0; + fLookAngle = (FLOAT)atof(argv[1]); + + if (fLookAngle>128.0f || fLookAngle<-128.0f) { + printf("%s -- Angle %f out of range.",argv[0],fLookAngle); + return 0; + } + + pChar->CameraAngle = fLookAngle; + gLookAngle = 10000.0f; + return 0; +} + +int CMD_EQEcho(int argc, char *argv[]) +{ + static map Filters; + static bool FiltersInitialized=false; + + if (argc<2) + { + printf("Syntax: %s <-channelfilters>|[-] ",argv[0]); + return 0; + } + + if (!FiltersInitialized) + { + FiltersInitialized=true; + +Filters["say"]=USERCOLOR_SAY; +Filters["tell"]=USERCOLOR_TELL; +Filters["group"]=USERCOLOR_GROUP; +Filters["guild"]=USERCOLOR_GUILD; +Filters["ooc"]=USERCOLOR_OOC; +Filters["auction"]=USERCOLOR_AUCTION; +Filters["shout"]=USERCOLOR_SHOUT; +Filters["emote"]=USERCOLOR_EMOTE; +Filters["spells"]=USERCOLOR_SPELLS; +Filters["youhit"]=USERCOLOR_YOU_HIT_OTHER; +Filters["hityou"]=USERCOLOR_OTHER_HIT_YOU; +Filters["youmiss"]=USERCOLOR_YOU_MISS_OTHER; +Filters["missyou"]=USERCOLOR_OTHER_MISS_YOU; +Filters["duel"]=USERCOLOR_DUELS; +Filters["skill"]=USERCOLOR_SKILLS; +Filters["disc"]=USERCOLOR_DISCIPLINES; +Filters["unused1"]=USERCOLOR_UNUSED001; +Filters["default"]=USERCOLOR_DEFAULT; +Filters["unused2"]=USERCOLOR_UNUSED002; +Filters["merchantoffer"]=USERCOLOR_MERCHANT_OFFER; +Filters["merchantexchange"]=USERCOLOR_MERCHANT_EXCHANGE; +Filters["youdie"]=USERCOLOR_YOUR_DEATH; +Filters["theydie"]=USERCOLOR_OTHER_DEATH; +Filters["otherhit"]=USERCOLOR_OTHER_HIT_OTHER; +Filters["othermiss"]=USERCOLOR_OTHER_MISS_OTHER; +Filters["who"]=USERCOLOR_WHO; +Filters["yell"]=USERCOLOR_YELL; +Filters["nonmelee"]=USERCOLOR_NON_MELEE; +Filters["spellfade"]=USERCOLOR_SPELL_WORN_OFF; +Filters["split"]=USERCOLOR_MONEY_SPLIT; +Filters["loot"]=USERCOLOR_LOOT; +Filters["random"]=USERCOLOR_RANDOM; +Filters["otherspell"]=USERCOLOR_OTHERS_SPELLS; +Filters["spellfail"]=USERCOLOR_SPELL_FAILURE; +Filters["chatchannel"]=USERCOLOR_CHAT_CHANNEL; +Filters["chat1"]=USERCOLOR_CHAT_1; +Filters["chat2"]=USERCOLOR_CHAT_2; +Filters["chat3"]=USERCOLOR_CHAT_3; +Filters["chat4"]=USERCOLOR_CHAT_4; +Filters["chat5"]=USERCOLOR_CHAT_5; +Filters["chat6"]=USERCOLOR_CHAT_6; +Filters["chat7"]=USERCOLOR_CHAT_7; +Filters["chat8"]=USERCOLOR_CHAT_8; +Filters["chat9"]=USERCOLOR_CHAT_9; +Filters["chat10"]=USERCOLOR_CHAT_10; +Filters["meleecrit"]=USERCOLOR_MELEE_CRIT; +Filters["spellcrit"]=USERCOLOR_SPELL_CRIT; +Filters["toofar"]=USERCOLOR_TOO_FAR_AWAY; +Filters["rampage"]=USERCOLOR_NPC_RAMPAGE; +Filters["flurry"]=USERCOLOR_NPC_FLURRY; +Filters["enrage"]=USERCOLOR_NPC_ENRAGE; +Filters["sayecho"]=USERCOLOR_ECHO_SAY; +Filters["tellecho"]=USERCOLOR_ECHO_TELL; +Filters["groupecho"]=USERCOLOR_ECHO_GROUP; +Filters["guildecho"]=USERCOLOR_ECHO_GUILD; +Filters["oocecho"]=USERCOLOR_ECHO_OOC; +Filters["auctionecho"]=USERCOLOR_ECHO_AUCTION; +Filters["shoutecho"]=USERCOLOR_ECHO_SHOUT; +Filters["emoteecho"]=USERCOLOR_ECHO_EMOTE; +Filters["chat1echo"]=USERCOLOR_ECHO_CHAT_1; +Filters["chat2echo"]=USERCOLOR_ECHO_CHAT_2; +Filters["chat3echo"]=USERCOLOR_ECHO_CHAT_3; +Filters["chat4echo"]=USERCOLOR_ECHO_CHAT_4; +Filters["chat5echo"]=USERCOLOR_ECHO_CHAT_5; +Filters["chat6echo"]=USERCOLOR_ECHO_CHAT_6; +Filters["chat7echo"]=USERCOLOR_ECHO_CHAT_7; +Filters["chat8echo"]=USERCOLOR_ECHO_CHAT_8; +Filters["chat9echo"]=USERCOLOR_ECHO_CHAT_9; +Filters["chat10echo"]=USERCOLOR_ECHO_CHAT_10; +Filters["reserved"]=USERCOLOR_RESERVED; +Filters["link"]=USERCOLOR_LINK; +Filters["raid"]=USERCOLOR_RAID; +Filters["pet"]=USERCOLOR_PET; +Filters["damageshield"]=USERCOLOR_DAMAGESHIELD; +Filters["leader"]=USERCOLOR_LEADER; +Filters["petrampflurry"]=USERCOLOR_PETRAMPFLURRY; +Filters["petcrit"]=USERCOLOR_PETCRITS; +Filters["focus"]=USERCOLOR_FOCUS; +Filters["exp"]=USERCOLOR_XP; +Filters["system"]=USERCOLOR_SYSTEM; + + } + + + unsigned int Color=USERCOLOR_DEFAULT; + int arg=1; + if (argv[arg][0]=='-') + { + if (!stricmp(argv[arg],"-channelfilters")) + { + CColumnRenderer CR; + for (map::iterator i=Filters.begin() ;i!=Filters.end() ; i++) + { + CR.AddItem(i->first.c_str()); + } + CR.Render(pISInterface); + return 0; + } + map::iterator i=Filters.find(&argv[arg][1]); + if (i!=Filters.end()) + Color=i->second; + arg++; + } + + if (argc<=arg) + { + printf("Syntax: %s [-] ",argv[0]); + return 0; + } + char FullText[8192]; + pISInterface->GetArgs(arg,argc,argv,FullText,sizeof(FullText)); + dsp_chat_no_events(FullText,Color,1); + return 0; +} + +int CMD_EQItems(int argc, char *argv[]) +{ + if (!ppItemList) return 0; + if (!pItemList) return 0; + PSPAWNINFO pChar = (PSPAWNINFO)pLocalPlayer; + PGROUNDITEM pItem = (PGROUNDITEM)pItemList; + DWORD Count=0; + CHAR szBuffer[MAX_STRING] = {0}; + CHAR szName[MAX_STRING]={0}; + WriteChatColor("Items on the ground:", USERCOLOR_DEFAULT); + WriteChatColor("---------------------------", USERCOLOR_DEFAULT); + while (pItem) { + GetFriendlyNameForGroundItem(pItem,szName); + + if ((argc==1) || (!strnicmp(szName,argv[1],strlen(argv[1])))) { + SPAWNINFO TempSpawn; + FLOAT Distance; + ZeroMemory(&TempSpawn,sizeof(TempSpawn)); + strcpy(TempSpawn.Name,szName); + TempSpawn.Y=pItem->Y; + TempSpawn.X=pItem->X; + TempSpawn.Z=pItem->Z; + Distance = DistanceToSpawn(pChar,&TempSpawn); + INT Angle = (INT)((atan2f(pChar->X - pItem->X, pChar->Y - pItem->Y) * 180.0f / PI + 360.0f) / 22.5f + 0.5f) % 16; + + sprintf(szBuffer,"%s: %1.2f away to the %s",szName,Distance,szHeading[Angle]); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + Count++; + } + + pItem = pItem->pNext; + } + if (Count==0) { + WriteChatColor("No items found.",USERCOLOR_DEFAULT); + } else { + sprintf(szBuffer,"%d item%s found.",Count,(Count==1)?"":"s"); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + return 0; +} + +int CMD_DoorTarget(int argc, char *argv[]) +{ + + if (!ppSwitchMgr) return 0; + if (!pSwitchMgr) return 0; + PDOORTABLE pDoorTable = (PDOORTABLE)pSwitchMgr; + DWORD Count; + + PSPAWNINFO pChar = (PSPAWNINFO)pLocalPlayer; + CHAR szBuffer[MAX_STRING] = {0}; + CHAR szSearch[MAX_STRING] = {0}; + FLOAT cDistance = 100000.0f; + BYTE ID = -1; + ZeroMemory(&DoorEnviroTarget,sizeof(DoorEnviroTarget)); + pDoorTarget = NULL; + + if (argc > 1 && !stricmp(argv[1], "id")) { + if (argc < 3) { + WriteChatf("DoorTarget: id specified but no number provided."); + return 0; + } + + ID = atoi(argv[2]); + for (Count=0; CountNumEntries; Count++) { + if (pDoorTable->pDoor[Count]->ID == ID) { + strcpy(DoorEnviroTarget.Name, pDoorTable->pDoor[Count]->Name); + DoorEnviroTarget.Y = pDoorTable->pDoor[Count]->Y; + DoorEnviroTarget.X = pDoorTable->pDoor[Count]->X; + DoorEnviroTarget.Z = pDoorTable->pDoor[Count]->Z; + DoorEnviroTarget.Heading = pDoorTable->pDoor[Count]->Heading; + DoorEnviroTarget.Type = SPAWN_NPC; + DoorEnviroTarget.HPCurrent = 1; + DoorEnviroTarget.HPMax = 1; + pDoorTarget = pDoorTable->pDoor[Count]; + break; + } + } + } else { + if (argc > 1) strcpy(szSearch, argv[1]); + for (Count=0; CountNumEntries; Count++) { + if (((szSearch[0]==0) || + (!strnicmp(pDoorTable->pDoor[Count]->Name,szSearch,strlen(szSearch)))) && + ((gZFilter >=10000.0f) || + ((pDoorTable->pDoor[Count]->Z <= pChar->Z + gZFilter) && + (pDoorTable->pDoor[Count]->Z >= pChar->Z - gZFilter)))) { + SPAWNINFO tSpawn; + ZeroMemory(&tSpawn,sizeof(tSpawn)); + strcpy(tSpawn.Name,pDoorTable->pDoor[Count]->Name); + tSpawn.Y=pDoorTable->pDoor[Count]->Y; + tSpawn.X=pDoorTable->pDoor[Count]->X; + tSpawn.Z=pDoorTable->pDoor[Count]->Z; + tSpawn.Type = SPAWN_NPC; + tSpawn.HPCurrent = 1; + tSpawn.HPMax = 1; + tSpawn.Heading=pDoorTable->pDoor[Count]->Heading; + FLOAT Distance = DistanceToSpawn(pChar,&tSpawn); + if (DistancepDoor[Count]; + cDistance=Distance; + } + } + + } + } + + + if (DoorEnviroTarget.Name[0]!=0) { + sprintf(szBuffer,"Door %d '%s' targeted.", pDoorTarget->ID, DoorEnviroTarget.Name); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } else { + WriteChatf("Couldn't find door to target."); + } + return 0; +} + +int CMD_ItemTarget(int argc, char *argv[]) +{ + if (!ppItemList) return 0; + if (!pItemList) return 0; + PSPAWNINFO pChar = (PSPAWNINFO)pLocalPlayer; + PGROUNDITEM pItem = (PGROUNDITEM)pItemList; + FLOAT cDistance = 100000.0f; + CHAR szName[MAX_STRING]={0}; + CHAR szBuffer[MAX_STRING] = {0}; + ZeroMemory(&EnviroTarget,sizeof(EnviroTarget)); + pGroundTarget = NULL; + while (pItem) { + GetFriendlyNameForGroundItem(pItem,szName); + if ( + ( + (argc<2) || + (!strnicmp(szName,argv[1],strlen(argv[1]))) + ) && ( + (gZFilter >=10000.0f) || + ( + (pItem->Z <= pChar->Z + gZFilter) && + (pItem->Z >= pChar->Z - gZFilter) + ) + ) + ) { + SPAWNINFO tSpawn; + ZeroMemory(&tSpawn,sizeof(tSpawn)); + strcpy(tSpawn.Name,szName); + tSpawn.Y=pItem->Y; + tSpawn.X=pItem->X; + tSpawn.Z=pItem->Z; + tSpawn.Type = SPAWN_NPC; + tSpawn.HPCurrent = 1; + tSpawn.HPMax = 1; + tSpawn.Heading=pItem->Heading; + tSpawn.Race = pItem->DropID; + FLOAT Distance = DistanceToSpawn(pChar,&tSpawn); + if (DistancepNext; + } + if (EnviroTarget.Name[0]!=0) { + sprintf(szBuffer,"Item '%s' targeted.",EnviroTarget.Name); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + + return 0; +} diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommands.h b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommands.h new file mode 100644 index 0000000000..a214a766dc --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQCommands.h @@ -0,0 +1,18 @@ +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +#define COMMAND(name,cmd,parse,hide) EQLIB_API int cmd(int argc, char *argv[]) +#include "ISXEQCommandList.h" +#undef COMMAND + diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQDataTypes.cpp b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQDataTypes.cpp new file mode 100644 index 0000000000..959b7c9f00 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQDataTypes.cpp @@ -0,0 +1,571 @@ +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +#error /DCINTERFACE +#endif + +#define DBG_SPEW + +#include "..\MQ2Main.h" + +// These are the same types as in MQ2DataTypes.cpp, however ISXEQ types have members, as +// the GetMember function takes care of here. + +bool MQ2SpawnType::GETMETHOD() +{ +#define pPtr ((PSPAWNINFO)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMETHOD pMethod=MQ2SpawnType::FindMethod(Method); + if (!pMethod) + return false; + switch((SpawnMethods)pMethod->ID) + { + case Target: + *ppTarget=GetSpawnByID(pPtr->SpawnID); // this could be a variable, which is just a copy. use its ID + return true; + case Face: + { + PSPAWNINFO pSpawn = (PSPAWNINFO)GetSpawnByID(pPtr->SpawnID); + if (pSpawn->SpawnID==((PSPAWNINFO)pCharSpawn)->SpawnID) // If it is ourself, don't do anything. + return true; + bool bfPredict=false; + bool bfAway=false; + bool bfNolook=false; + bool bfFast=false; + gFaceAngle = ( + atan2(pSpawn->X - ((PSPAWNINFO)pCharSpawn)->X, + pSpawn->Y - ((PSPAWNINFO)pCharSpawn)->Y) + * 256.0f / PI); + while (argc--) + { + if (!stricmp(argv[argc],"predict")) + bfPredict=true; + else if (!stricmp(argv[argc],"nolook")) + bfNolook=true; + else if (!stricmp(argv[argc],"away")) + bfAway=true; + else if (!stricmp(argv[argc],"fast")) + bfFast=true; + } + if (bfPredict) + { + DOUBLE Distance; + Distance = DistanceToSpawn((PSPAWNINFO)pCharSpawn, pSpawn); + gFaceAngle = ( + atan2((pSpawn->X + (pSpawn->SpeedX * Distance)) - ((PSPAWNINFO)pCharSpawn)->X, + (pSpawn->Y + (pSpawn->SpeedY * Distance)) - ((PSPAWNINFO)pCharSpawn)->Y) + * 256.0f / PI); + } + if (!bfNolook) { + DOUBLE Distance = DistanceToSpawn((PSPAWNINFO)pCharSpawn, pSpawn); + gLookAngle = ( + atan2(pSpawn->Z + pSpawn->AvatarHeight*StateHeightMultiplier(pSpawn->StandState) - ((PSPAWNINFO)pCharSpawn)->Z - + ((PSPAWNINFO)pCharSpawn)->AvatarHeight*StateHeightMultiplier(((PSPAWNINFO)pCharSpawn)->StandState), + (FLOAT)Distance) + * 256.0f / PI); + if (bfAway) gLookAngle = -gLookAngle; + if (bfFast) { + ((PSPAWNINFO)pCharSpawn)->CameraAngle = (FLOAT)gLookAngle; + gLookAngle=10000.0f; + } + } + if (bfAway) { + gFaceAngle += 256.0f; + } + if (gFaceAngle>=512.0f) gFaceAngle -= 512.0f; + if (gFaceAngle<0.0f) gFaceAngle += 512.0f; + if (bfFast) { + ((PSPAWNINFO)pCharSpawn)->Heading = (FLOAT)gFaceAngle; + gFaceAngle=10000.0f; + } + } + return true; + + case LeftClick: + { + PSPAWNINFO pSpawn = (PSPAWNINFO)GetSpawnByID(pPtr->SpawnID); + pEverQuest->LeftClickedOnPlayer((EQPlayer *)pSpawn); + return true; + } + case RightClick: + { + PSPAWNINFO pSpawn = (PSPAWNINFO)GetSpawnByID(pPtr->SpawnID); + pEverQuest->RightClickedOnPlayer((EQPlayer *)pSpawn, 0); + return true; + } + case xAssist: + return true; + } + return false; +#undef pPtr +} + + +bool MQ2BuffType::GETMETHOD() +{ +#define pPtr ((PSPELLBUFF)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + if ((int)pPtr->SpellID<=0) + return false; + PMQ2TYPEMETHOD pMethod=MQ2BuffType::FindMethod(Method); + if (!pMethod) + { + if (PSPELL pSpell=GetSpellByID(pPtr->SpellID)) + { + LSVARPTR Temp; + Temp.Ptr=pSpell; + return pSpellType->GetMethod(Temp,Method,argc,argv); + } + return false; + } + switch((BuffMethods)pMethod->ID) + { + case Remove: + { + unsigned long slot; + char Temp[16]; + if (GetBuffID(pPtr,(DWORD&)slot)) + { + sprintf(Temp,"Buff%d",slot-1); + DWORD KeyboardFlags; + KeyboardFlags=*(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags; + *(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags=0; + SendWndClick("BuffWindow",Temp,"leftmouseup"); + *(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags=KeyboardFlags; + return true; + } + if (GetShortBuffID(pPtr,(DWORD&)slot)) + { + sprintf(Temp,"Buff%d",slot-1); + DWORD KeyboardFlags; + KeyboardFlags=*(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags; + *(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags=0; + SendWndClick("ShortDurationBuffWindow",Temp,"leftmouseup"); + *(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags=KeyboardFlags; + return true; + } + } + return false; + } + return false; +#undef pPtr +} + + +bool MQ2CharacterType::GETMETHOD() +{ +#define pPtr ((PCHARINFO)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMETHOD pMethod=MQ2CharacterType::FindMethod(Method); + if (!pMethod) + { + LSVARPTR Temp; + Temp.Ptr=pPtr->pSpawn; + return pSpawnType->GetMethod(Temp,Method,argc,argv); + } + switch((CharacterMethods)pMethod->ID) + { + case Stand: + { + EzCommand("/stand"); + return true; + } + case Sit: + { + EzCommand("/sit"); + return true; + } + case Dismount: + { + EzCommand("/dismount"); + return true; + } + } + return false; +#undef pPtr +} + + +bool MQ2SpellType::GETMETHOD() +{ +#define pPtr ((PSPELL)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMETHOD pMethod=MQ2SpellType::FindMethod(Method); + if (!pMethod) + { + return false; + } + // TODO +// switch((SpellMethods)pMethod->ID) +// { +// } + return false; +#undef pPtr +} + + +bool MQ2ItemType::GETMETHOD() +{ +#define pPtr ((PCONTENTS)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMETHOD pMethod=MQ2ItemType::FindMethod(Method); + if (!pMethod) + { + return false; + } + // TODO +// switch((ItemMethods)pMethod->ID) +// { +// } + return false; +#undef pPtr +} + + +bool MQ2WindowType::GETMETHOD() +{ +#define pPtr ((CXWnd*)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMETHOD pMethod=MQ2WindowType::FindMethod(Method); + if (!pMethod) + { + return false; + } + CXRect rect= pPtr->GetScreenRect(); + CXPoint pt=rect.CenterPoint(); + switch((WindowMethods)pMethod->ID) + { + case LeftMouseDown: + pPtr->HandleLButtonDown(&pt,0); + return true; + case LeftMouseUp: + pPtr->HandleLButtonDown(&pt,0); + pPtr->HandleLButtonUp(&pt,0); + return true; + case LeftMouseHeldDown: + pPtr->HandleLButtonDown(&pt,0); + pPtr->HandleLButtonHeld(&pt,0); + return true; + case LeftMouseHeldUp: + pPtr->HandleLButtonDown(&pt,0); + pPtr->HandleLButtonHeld(&pt,0); + pPtr->HandleLButtonUpAfterHeld(&pt,0); + return true; + case RightMouseDown: + pPtr->HandleRButtonDown(&pt,0); + return true; + case RightMouseUp: + pPtr->HandleRButtonDown(&pt,0); + pPtr->HandleRButtonUp(&pt,0); + return true; + case RightMouseHeldDown: + pPtr->HandleRButtonDown(&pt,0); + pPtr->HandleRButtonHeld(&pt,0); + return true; + case RightMouseHeldUp: + pPtr->HandleRButtonDown(&pt,0); + pPtr->HandleRButtonHeld(&pt,0); + pPtr->HandleRButtonUpAfterHeld(&pt,0); + return true; + case ListSelect: + if (argc) + { + DWORD Value=atoi(argv[0])-1; + if (pPtr->GetType()==UI_Listbox) + ((CListWnd *)pPtr)->SetCurSel(Value); + else if (pPtr->GetType()==UI_Combobox) + ((CComboWnd*)pPtr)->SetChoice(Value); + else + return false; + } + return true; + } + return false; +#undef pPtr +} + + +bool MQ2SwitchType::GETMETHOD() +{ +#define pPtr ((PDOOR)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMETHOD pMethod=MQ2SwitchType::FindMethod(Method); + if (!pMethod) + { + return false; + } + return false; +#undef pPtr +} + + +bool MQ2GroundType::GETMETHOD() +{ +#define pPtr ((PGROUNDITEM)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMETHOD pMethod=MQ2GroundType::FindMethod(Method); + if (!pMethod) + { + return false; + } + return false; +#undef pPtr +} + + +bool MQ2MacroQuestType::GETMETHOD() +{ + PMQ2TYPEMETHOD pMethod=MQ2MacroQuestType::FindMethod(Method); + if (!pMethod) + { + return false; + } + // TODO +// switch((MacroQuestMethods)pMethod->ID) +// { +// } + return false; +} + + +bool MQ2HeadingType::GETMETHOD() +{ + PMQ2TYPEMETHOD pMethod=MQ2HeadingType::FindMethod(Method); + if (!pMethod) + { + return false; + } + // TODO +// switch((HeadingMethods)pMethod->ID) +// { +// } + return false; +} + + +bool MQ2CorpseType::GETMETHOD() +{ + if (!pActiveCorpse || !pLootWnd) + return false; +#define pPtr ((PEQLOOTWINDOW)pLootWnd) + PMQ2TYPEMETHOD pMethod=MQ2CorpseType::FindMethod(Method); + if (!pMethod) + { + LSVARPTR Temp; + Temp.Ptr=pActiveCorpse; + return pSpawnType->GetMethod(Temp,Method,argc,argv); + } + // TODO +// switch((CorpseMethods)pMethod->ID) +// { +// } + return false; +#undef pPtr +} + + +bool MQ2MerchantType::GETMETHOD() +{ + if (!pActiveMerchant || !pMerchantWnd) + return false; +#define pPtr ((PEQMERCHWINDOW)pMerchantWnd) + PMQ2TYPEMETHOD pMethod=MQ2MerchantType::FindMethod(Method); + if (!pMethod) + { + LSVARPTR Temp; + Temp.Ptr=pActiveMerchant; + return pSpawnType->GetMethod(Temp,Method,argc,argv); + } + // TODO +// switch((MerchantMethods)pMethod->ID) +// { +// } + return false; +#undef pPtr +} + + +bool MQ2InvSlotType::GETMETHOD() +{ +#define nInvSlot (VarPtr.Int) + PMQ2TYPEMETHOD pMethod=MQ2InvSlotType::FindMethod(Method); + if (!pMethod) + { + return false; + } + // TODO +// switch((InvSlotMethods)pMethod->ID) +// { +// } + return false; +#undef nInvSlot +} + + + +bool MQ2TimerType::GETMETHOD() +{ +#define pPtr ((PMQTIMER)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMETHOD pMethod=MQ2TimerType::FindMethod(Method); + if (!pMethod) + { + return false; + } + switch((TimerMethods)pMethod->ID) + { + case Reset: + pPtr->Current=pPtr->Original; + return true; + case Expire: + pPtr->Current=1; // Will expire in a 10th of a second + return true; + case Set: + if (argc) + { + MQ2TimerType::FromString(VarPtr,argv[0]); + return true; + } + } + return false; +#undef pPtr +} + + +bool MQ2SkillType::GETMETHOD() +{ + if (!VarPtr.Ptr) + return false; + PSKILL pSkill=*(PSKILL*)VarPtr.Ptr; + if (!pSkill) + return false; + PMQ2TYPEMETHOD pMethod=MQ2SkillType::FindMethod(Method); + if (!pMethod) + { + return false; + } + // TODO +// switch((SkillMethods)pMethod->ID) +// { +// } + return false; +} + + +bool MQ2AltAbilityType::GETMETHOD() +{ + if (!VarPtr.Ptr) + return false; + PALTABILITY pAbility=*(PALTABILITY*)VarPtr.Ptr; + PMQ2TYPEMETHOD pMethod=MQ2AltAbilityType::FindMethod(Method); + if (!pMethod) + { + return false; + } + // TODO +// switch((AltAbilityMethods)pMethod->ID) +// { +// } + return false; +} + + +bool MQ2RaidType::GETMETHOD() +{ + if (!pRaid) + return false; + PMQ2TYPEMETHOD pMethod=MQ2RaidType::FindMethod(Method); + if (!pMethod) + { + return false; + } + // TODO +// switch((RaidMethods)pMethod->ID) +// { +// } + return false; +} + + +bool MQ2RaidMemberType::GETMETHOD() +{ + DWORD nRaidMember=VarPtr.DWord-1; + if (VarPtr.DWord>=72) + return false; + if (!pRaid->RaidMemberUsed[nRaidMember]) + return false; + PEQRAIDMEMBER pRaidMember=&pRaid->RaidMember[nRaidMember]; + PMQ2TYPEMETHOD pMethod=MQ2RaidMemberType::FindMethod(Method); + if (!pMethod) + { + LSVARPTR Temp; + Temp.Ptr=SpawnByName[pRaidMember->Name]; + return pSpawnType->GetMethod(Temp,Method,argc,argv); + } + // TODO +// switch((RaidMemberMethods)pMethod->ID) +// { +// } + return false; +} + +bool MQ2FriendsType::GETMETHOD() +{ + PMQ2TYPEMETHOD pMethod=MQ2FriendsType::FindMethod(Method); + if (!pMethod) + { + return false; + } + // TODO +// switch((FriendsMethods)pMethod->ID) +// { +// } + return false; +} + +bool MQ2TargetType::GETMETHOD() +{ +#define pPtr ((PSPAWNINFO)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMETHOD pMethod=MQ2TargetType::FindMethod(Method); + if (!pMethod) + return false; + else + return true; +#undef pPtr +} + +bool MQ2XTargetType::GETMETHOD() +{ +#define pPtr ((PSPAWNINFO)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMETHOD pMethod=MQ2XTargetType::FindMethod(Method); + if (!pMethod) + return false; + else + return true; +#undef pPtr +} diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQDataTypes.h b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQDataTypes.h new file mode 100644 index 0000000000..f414f10245 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQDataTypes.h @@ -0,0 +1,57 @@ +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +DATATYPE(MQ2SpawnType,pSpawnType,"EQ Objects"); +DATATYPE(MQ2CharacterType,pCharacterType,"EQ Objects"); +DATATYPE(MQ2BuffType,pBuffType,0); +DATATYPE(MQ2SpellType,pSpellType,"EQ Objects"); +DATATYPE(MQ2TicksType,pTicksType,0); + +DATATYPE(MQ2SkillType,pSkillType,"EQ Skill"); +DATATYPE(MQ2AltAbilityType,pAltAbilityType,"EQ Alt Ability"); + +DATATYPE(MQ2ClassType,pClassType,"EQ Class"); +DATATYPE(MQ2RaceType,pRaceType,"EQ Race"); +DATATYPE(MQ2BodyType,pBodyType,"EQ Body"); + +DATATYPE(MQ2GroundType,pGroundType,0); +DATATYPE(MQ2SwitchType,pSwitchType,0); + +DATATYPE(MQ2MacroQuestType,pMacroQuestType,"MacroQuest Object"); + +DATATYPE(MQ2CorpseType,pCorpseType,0); +DATATYPE(MQ2WindowType,pWindowType,0); +DATATYPE(MQ2MerchantType,pMerchantType,0); +DATATYPE(MQ2ZoneType,pZoneType,"EQ Zone"); +DATATYPE(MQ2CurrentZoneType,pCurrentZoneType,"EQ CurrentZone"); +DATATYPE(MQ2ItemType,pItemType,0); +DATATYPE(MQ2DeityType,pDeityType,"EQ Deity"); +DATATYPE(MQ2ArgbType,pArgbType,0); + +DATATYPE(MQ2HeadingType,pHeadingType,0); + +DATATYPE(MQ2InvSlotType,pInvSlotType,"EQ InvSlot"); + +DATATYPE(MQ2TimerType,pTimerType,0); + +DATATYPE(MQ2RaidType,pRaidType,"EQ Raid"); +DATATYPE(MQ2RaidMemberType,pRaidMemberType,"EQ RaidMember"); +DATATYPE(MQ2GroupType,pGroupType,"EQ Group"); +DATATYPE(MQ2GroupMemberType,pGroupMemberType,"EQ GroupMember"); + +DATATYPE(MQ2FriendsType,pFriendsType,0); + +DATATYPE(MQ2TargetType,pTargetType,"EQ Target"); + +DATATYPE(MQ2XTargetType,pXTargetType,"EQ XTarget"); diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQServices.cpp b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQServices.cpp new file mode 100644 index 0000000000..a810bb33fc --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQServices.cpp @@ -0,0 +1,234 @@ +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +#error /DCINTERFACE +#endif + +#define DBG_SPEW +#include "..\MQ2Main.h" +#include "ISXEQServices.h" + +//#define DEBUG_PLUGINS + +#ifdef DEBUG_PLUGINS +#define PluginDebug DebugSpew +#else +#define PluginDebug // +#endif + + +// "Chat" service +EQLIB_API BOOL PluginsIncomingChat(PCHAR Line, DWORD Color) +{ + PluginDebug("PluginsIncomingChat()"); + if(!Line[0]) + return 0; + _EQChat Chat; + Chat.Line=Line; + Chat.Color=Color; + Chat.Filtered=false; + pISInterface->ServiceBroadcast(pExtension,hChatService,CHATSERVICE_INCOMING,&Chat); + return Chat.Filtered; +} + + +EQLIB_API VOID WriteChatColor(PCHAR Line, DWORD Color, DWORD Filter) +{ + if (gFilterMQ) + return; + PluginDebug("Begin WriteChatColor()"); + EnterMQ2Benchmark(bmWriteChatColor); + CHAR PlainText[MAX_STRING]={0}; + StripMQChat(Line,PlainText); + CheckChatForEvent(PlainText); + + DebugSpew("WriteChatColor(%s)",Line); + + //printf("%s",PlainText); + + // TEMPORARY + /* // use ISXEQChat or ISXEQChatWnd + printf("%s",PlainText); + if (gFilterMacro != FILTERMACRO_NONE && ppEverQuest && pEverQuest && gGameState==GAMESTATE_INGAME) + { + dsp_chat_no_events(PlainText,Color,1); + } + /**/ + // --------- + + + + // filter parameter is unused anyway + _EQChat Chat; + Chat.Line=Line; + Chat.Color=Color; + pISInterface->ServiceBroadcast(pExtension,hChatService,CHATSERVICE_OUTGOING,&Chat); + + ExitMQ2Benchmark(bmWriteChatColor); +} + + +// "UI" service +EQLIB_API VOID PluginsCleanUI() +{ + PluginDebug("PluginsCleanUI()"); + pISInterface->ServiceBroadcast(pExtension,hUIService,UISERVICE_CLEANUP,0); +} +EQLIB_API VOID PluginsReloadUI() +{ + PluginDebug("PluginsReloadUI()"); + pISInterface->ServiceBroadcast(pExtension,hUIService,UISERVICE_RELOAD,0); +} + +void __cdecl GamestateRequest(ISXInterface *pClient, unsigned int MSG, void *lpData) +{ + if (MSG==ISXSERVICE_CLIENTADDED) + { +// printf("Gamestate Service - Client Added"); + pISInterface->ServiceNotify(pExtension,hGamestateService,(ISXInterface*)lpData,GAMESTATESERVICE_CHANGED,(void*)gGameState); + } +} +void __cdecl SpawnRequest(ISXInterface *pClient, unsigned int MSG, void *lpData) +{ + if (MSG==ISXSERVICE_CLIENTADDED) + { +// printf("Spawn Service - Client Added"); + if (gGameState==GAMESTATE_INGAME) + { + PSPAWNINFO pSpawn=(PSPAWNINFO)pSpawnList; + while(pSpawn) + { + pISInterface->ServiceNotify(pExtension,hSpawnService,(ISXInterface*)lpData,SPAWNSERVICE_ADDSPAWN,pSpawn); + if (pSpawn->GM) + pISInterface->ServiceNotify(pExtension,hSpawnService,(ISXInterface*)lpData,SPAWNSERVICE_ADDGM,pSpawn); + pSpawn=pSpawn->pNext; + } + PGROUNDITEM pItem=(PGROUNDITEM)pItemList; + while(pItem) + { + pISInterface->ServiceNotify(pExtension,hSpawnService,(ISXInterface*)lpData,SPAWNSERVICE_ADDITEM,pItem); + pItem=pItem->pNext; + } + } + } +} + +// "Gamestate" Service +EQLIB_API VOID PluginsSetGameState(DWORD GameState) +{ + PluginDebug("PluginsSetGameState()"); + static bool AutoExec=false; + static bool CharSelect=true; + DrawHUDParams[0]=0; + gGameState=GameState; + if (GameState==GAMESTATE_INGAME) + { + gZoning=false; + gbDoAutoRun=TRUE; + if (!AutoExec) + { + AutoExec=true; + pISInterface->RunCommandFile("EQ-AutoExec"); + pISInterface->RunScript("EQ-AutoExec"); + } + if (CharSelect) + { + CharSelect=false; + CHAR szBuffer[MAX_STRING]={0}; + if (PCHARINFO pCharInfo=GetCharInfo()) + { + sprintf(szBuffer,"EQ-%s_%s",EQADDR_SERVERNAME,pCharInfo->Name); + pISInterface->RunCommandFile(szBuffer); + pISInterface->RunScript(szBuffer); + } + } + } + else if (GameState==GAMESTATE_CHARSELECT) + { + if (!AutoExec) + { + AutoExec=true; + pISInterface->RunCommandFile("EQ-AutoExec"); + pISInterface->RunScript("EQ-AutoExec"); + } + CharSelect=true; + pISInterface->RunCommandFile("EQ-CharSelect"); + pISInterface->RunScript("EQ-CharSelect"); + } + + DebugSpew("PluginsSetGameState(%d)",GameState); + pISInterface->ServiceBroadcast(pExtension,hGamestateService,GAMESTATESERVICE_CHANGED,(void*)GameState); +} + +// "Spawn" service +EQLIB_API VOID PluginsAddSpawn(PSPAWNINFO pNewSpawn) +{ + DWORD BodyType=GetBodyType(pNewSpawn); + PluginDebug("PluginsAddSpawn(%s,%d,%d)",pNewSpawn->Name,pNewSpawn->Race,pNewSpawn->BodyType); + SpawnByName[pNewSpawn->Name]=pNewSpawn; + if (gGameState>GAMESTATE_CHARSELECT) + SetNameSpriteState(pNewSpawn,1); + if (GetBodyTypeDesc(BodyType)[0]=='*') + { + WriteChatf("Spawn '%s' has unknown bodytype %d",pNewSpawn->Name,pNewSpawn->BodyType); + } + pISInterface->ServiceBroadcast(pExtension,hSpawnService,SPAWNSERVICE_ADDSPAWN,pNewSpawn); + if (pNewSpawn->GM) + pISInterface->ServiceBroadcast(pExtension,hSpawnService,SPAWNSERVICE_ADDGM,pNewSpawn); +} +EQLIB_API VOID PluginsRemoveSpawn(PSPAWNINFO pSpawn) +{ + PluginDebug("PluginsRemoveSpawn(%s)",pSpawn->Name); + SpawnByName.erase(pSpawn->Name); + if (pSpawn->GM) + pISInterface->ServiceBroadcast(pExtension,hSpawnService,SPAWNSERVICE_REMOVEGM,pSpawn); + pISInterface->ServiceBroadcast(pExtension,hSpawnService,SPAWNSERVICE_REMOVESPAWN,pSpawn); + + pISInterface->InvalidatePersistentObject(PersistentPointerClass,(unsigned int)pSpawn); +} +EQLIB_API VOID PluginsAddGroundItem(PGROUNDITEM pNewGroundItem) +{ + DebugSpew("PluginsAddGroundItem(%s) %.1f,%.1f,%.1f",pNewGroundItem->Name,pNewGroundItem->X,pNewGroundItem->Y,pNewGroundItem->Z); + pISInterface->ServiceBroadcast(pExtension,hSpawnService,SPAWNSERVICE_ADDITEM,pNewGroundItem); +} +EQLIB_API VOID PluginsRemoveGroundItem(PGROUNDITEM pGroundItem) +{ + PluginDebug("PluginsRemoveGroundItem()"); + pISInterface->ServiceBroadcast(pExtension,hSpawnService,SPAWNSERVICE_REMOVEITEM,pGroundItem); +} + +// "Zone" service +EQLIB_API VOID PluginsBeginZone(VOID) +{ + pISInterface->ServiceBroadcast(pExtension,hZoneService,ZONESERVICE_BEGINZONE,0); + gbInZone=false; +} +EQLIB_API VOID PluginsEndZone(VOID) +{ + pISInterface->ServiceBroadcast(pExtension,hZoneService,ZONESERVICE_ENDZONE,0); + gbInZone=true; +} +EQLIB_API VOID PluginsZoned() +{ + PluginDebug("PluginsZoned()"); + + pISInterface->ServiceBroadcast(pExtension,hZoneService,ZONESERVICE_ZONED,0); + + pISInterface->RunCommandFile("EQ-zoned"); + char Temp[256]={0}; + sprintf(Temp,"EQ-%s",((PZONEINFO)pZoneInfo)->ShortName); + pISInterface->RunCommandFile(Temp); +} + diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQServices.h b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQServices.h new file mode 100644 index 0000000000..aa69996cfa --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQServices.h @@ -0,0 +1,27 @@ +#pragma once + +struct _EQChat +{ + PCHAR Line; + DWORD Color; + BOOL Filtered; +}; + +#define CHATSERVICE_INCOMING ((ISXSERVICE_MSG)+1) +#define CHATSERVICE_OUTGOING ((ISXSERVICE_MSG)+2) + +#define UISERVICE_CLEANUP ((ISXSERVICE_MSG)+1) +#define UISERVICE_RELOAD ((ISXSERVICE_MSG)+2) + +#define GAMESTATESERVICE_CHANGED ((ISXSERVICE_MSG)+1) + +#define SPAWNSERVICE_ADDSPAWN ((ISXSERVICE_MSG)+1) +#define SPAWNSERVICE_REMOVESPAWN ((ISXSERVICE_MSG)+2) +#define SPAWNSERVICE_ADDITEM ((ISXSERVICE_MSG)+3) +#define SPAWNSERVICE_REMOVEITEM ((ISXSERVICE_MSG)+4) +#define SPAWNSERVICE_ADDGM ((ISXSERVICE_MSG)+5) +#define SPAWNSERVICE_REMOVEGM ((ISXSERVICE_MSG)+6) + +#define ZONESERVICE_BEGINZONE ((ISXSERVICE_MSG)+1) +#define ZONESERVICE_ENDZONE ((ISXSERVICE_MSG)+2) +#define ZONESERVICE_ZONED ((ISXSERVICE_MSG)+3) diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQTopLevelObjects.cpp b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQTopLevelObjects.cpp new file mode 100644 index 0000000000..80540d2f4a --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQTopLevelObjects.cpp @@ -0,0 +1,46 @@ +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +#error /DCINTERFACE +#endif + +#define DBG_SPEW + +#include "..\MQ2Main.h" + +#define TLO(funcname) bool funcname(int argc, char *argv[], LSTYPEVAR &Ret) + +TLO(dataNearestDoor) +{ + DWORD Count = 0; + FLOAT cDistance = 100000.0f; + PDOORTABLE pDoorTable = (PDOORTABLE)pSwitchMgr; + + if (pDoorTable->NumEntries) + { + for (Count=0; CountNumEntries; Count++) { + FLOAT Distance = GetDistance(pDoorTable->pDoor[Count]->X, pDoorTable->pDoor[Count]->Y); + if (DistancepDoor[Count]; + cDistance=Distance; + } + } + Ret.Ptr=pDoorTarget; + Ret.Type=pSwitchType; + return true; + } + return false; +} + diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQTopLevelObjects.h b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQTopLevelObjects.h new file mode 100644 index 0000000000..97dd41ad62 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQTopLevelObjects.h @@ -0,0 +1,58 @@ +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +#ifdef ISBOXER_COMPAT +TOPLEVELOBJECT("EQTarget",dataTarget); +TOPLEVELOBJECT("EQWindow",dataWindow); +#else +TOPLEVELOBJECT("Target",dataTarget); +TOPLEVELOBJECT("Window",dataWindow); +#endif +TOPLEVELOBJECT("Spawn",dataSpawn); +TOPLEVELOBJECT("Me",dataCharacter); +TOPLEVELOBJECT("Spell",dataSpell); +TOPLEVELOBJECT("Switch",dataSwitch); +TOPLEVELOBJECT("GroundItem",dataGroundItem); +TOPLEVELOBJECT("Merchant",dataMerchant); +TOPLEVELOBJECT("MacroQuest",dataMacroQuest); +TOPLEVELOBJECT("Zone",dataZone); +TOPLEVELOBJECT("Group",dataGroup); +TOPLEVELOBJECT("Corpse",dataCorpse); +TOPLEVELOBJECT("Cursor",dataCursor); +TOPLEVELOBJECT("NearestSpawn",dataNearestSpawn); +TOPLEVELOBJECT("GameTime",dataGameTime); +TOPLEVELOBJECT("Time",dataTime); +TOPLEVELOBJECT("Ini",dataIni); +TOPLEVELOBJECT("Heading",dataHeading); +TOPLEVELOBJECT("LastSpawn",dataLastSpawn); +TOPLEVELOBJECT("InvSlot",dataInvSlot); +TOPLEVELOBJECT("FindItem",dataFindItem); +TOPLEVELOBJECT("SelectedItem",dataSelectedItem); +TOPLEVELOBJECT("FindItemBank",dataFindItemBank); +TOPLEVELOBJECT("FindItemCount",dataFindItemCount); +TOPLEVELOBJECT("FindItemBankCount",dataFindItemBankCount); +//TOPLEVELOBJECT("GroupLeader",dataGroupLeader); +//TOPLEVELOBJECT("GroupLeaderName",dataGroupLeaderName); +TOPLEVELOBJECT("Skill",dataSkill); +TOPLEVELOBJECT("AltAbility",dataAltAbility); +TOPLEVELOBJECT("Raid",dataRaid); +TOPLEVELOBJECT("NamingSpawn",dataNamingSpawn); +TOPLEVELOBJECT("SpawnCount",dataSpawnCount); +TOPLEVELOBJECT("LineOfSight",dataLineOfSight); +TOPLEVELOBJECT("DoorTarget",dataDoorTarget); +TOPLEVELOBJECT("ItemTarget",dataItemTarget); +TOPLEVELOBJECT("NearestDoor",dataNearestDoor); +TOPLEVELOBJECT("Friends",dataFriends); + +/**/ diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQUtilities.cpp b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQUtilities.cpp new file mode 100644 index 0000000000..922deb7649 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQUtilities.cpp @@ -0,0 +1,225 @@ +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +#error /DCINTERFACE +#endif + +#define DBG_SPEW + +#include "..\MQ2Main.h" + +/* + +/**/ + +VOID CheckChatForEvent(PCHAR szMsg) +{ + IS_CheckTriggers(pExtension,pISInterface,hTriggerService,szMsg); + char *argv[]= + { + szMsg + }; + pISInterface->ExecuteEvent(ChatEventID,0,1,argv); +} + +unsigned long ParseSearchSpawnArg(int arg, int argc, char *argv[], SEARCHSPAWN &SearchSpawn) +{ + if (arg>=argc) + return 0; + unsigned long ExtraUsed=0; + { + if (!stricmp(argv[arg],"pc")) { + SearchSpawn.SpawnType = PC; + } else if (!stricmp(argv[arg],"npc")) { + SearchSpawn.SpawnType = NPC; + } else if (!stricmp(argv[arg],"mount")) { + SearchSpawn.SpawnType = MOUNT; + } else if (!stricmp(argv[arg],"pet")) { + SearchSpawn.SpawnType = PET; + } else if (!stricmp(argv[arg],"nopet")) { + SearchSpawn.bNoPet = TRUE; + } else if (!stricmp(argv[arg],"corpse")) { + SearchSpawn.SpawnType = CORPSE; + } else if (!stricmp(argv[arg],"trigger")) { + SearchSpawn.SpawnType = TRIGGER; + } else if (!stricmp(argv[arg],"untargetable")) { + SearchSpawn.SpawnType = UNTARGETABLE; + } else if (!stricmp(argv[arg],"trap")) { + SearchSpawn.SpawnType = TRAP; + } else if (!stricmp(argv[arg],"chest")) { + SearchSpawn.SpawnType = CHEST; + } else if (!stricmp(argv[arg],"timer")) { + SearchSpawn.SpawnType = TIMER; + } else if (!stricmp(argv[arg],"any")) { + SearchSpawn.SpawnType = NONE; + } else if (!stricmp(argv[arg],"next")) { + SearchSpawn.bTargNext = TRUE; + } else if (!stricmp(argv[arg],"prev")) { + SearchSpawn.bTargPrev = TRUE; + } else if (!stricmp(argv[arg],"lfg")) { + SearchSpawn.bLFG = TRUE; + } else if (!stricmp(argv[arg],"gm")) { + SearchSpawn.bGM = TRUE; + } else if (!stricmp(argv[arg],"group")) { + SearchSpawn.bGroup = TRUE; + } else if (!stricmp(argv[arg],"noguild")) { + SearchSpawn.bNoGuild = TRUE; + } else if (!stricmp(argv[arg],"trader")) { + SearchSpawn.bTrader = TRUE; + } else if (!stricmp(argv[arg],"named")) { + SearchSpawn.bNamed = TRUE; + } else if (!stricmp(argv[arg],"merchant")) { + SearchSpawn.bMerchant = TRUE; + } else if (!stricmp(argv[arg],"tribute")) { + SearchSpawn.bTributeMaster = TRUE; + } else if (!stricmp(argv[arg],"knight")) { + SearchSpawn.bKnight = TRUE; + } else if (!stricmp(argv[arg],"tank")) { + SearchSpawn.bTank = TRUE; + } else if (!stricmp(argv[arg],"healer")) { + SearchSpawn.bHealer = TRUE; + } else if (!stricmp(argv[arg],"dps")) { + SearchSpawn.bDps = TRUE; + } else if (!stricmp(argv[arg],"slower")) { + SearchSpawn.bSlower = TRUE; + } else if (!stricmp(argv[arg],"los")) { + SearchSpawn.bLoS = TRUE; + } else if (!stricmp(argv[arg],"range")) { + if (arg+2pSpawn->GuildID; + } else if (!stricmp(argv[arg],"guild")) { + if (arg+1pSpawn->GuildID; + } + } else if (!stricmp(argv[arg],"alert")) { + if (arg+1GetClassDesc(N)); + return ExtraUsed; + } + } + strlwr(strcpy(SearchSpawn.szName,argv[arg])); + } + } + return ExtraUsed; +} + +PCHAR ParseMacroParameter(PSPAWNINFO pChar, PCHAR szOriginal) +{// PMP is bad, mmmkay + pISInterface->DataParse(szOriginal,szOriginal,4096); + return szOriginal; +} diff --git a/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQUtilities.h b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQUtilities.h new file mode 100644 index 0000000000..e3e2b2b401 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/ISXEQ/ISXEQUtilities.h @@ -0,0 +1,3 @@ +#pragma once +extern unsigned long ParseSearchSpawnArg(int arg, int argc, char *argv[], SEARCHSPAWN &SearchSpawn); + diff --git a/client_files/native_autoloot/eq-core-dll/src/InterfaceQuery.cpp b/client_files/native_autoloot/eq-core-dll/src/InterfaceQuery.cpp new file mode 100644 index 0000000000..43b732941a --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/InterfaceQuery.cpp @@ -0,0 +1,45 @@ +/** +* Copyright (C) 2019 Elisha Riedlinger +* +* This software is provided 'as-is', without any express or implied warranty. In no event will the +* authors be held liable for any damages arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you wrote the +* original software. If you use this software in a product, an acknowledgment in the product +* documentation would be appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as +* being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "dinput8.h" + +void genericQueryInterface(REFIID riid, LPVOID * ppvObj) +{ + if (!ppvObj || !*ppvObj) + { + return; + } + +#define QUERYINTERFACE(x) \ + if (riid == IID_ ## x) \ + { \ + *ppvObj = ProxyAddressLookupTable.FindAddress(*ppvObj); \ + } + +#define CREATEINTERFACE(x) \ + if (riid == IID_ ## x) \ + { \ + *ppvObj = new m_ ## x((x*)*ppvObj); \ + } + + QUERYINTERFACE(IDirectInput8A); + QUERYINTERFACE(IDirectInput8W); + QUERYINTERFACE(IDirectInputDevice8A); + QUERYINTERFACE(IDirectInputDevice8W); + QUERYINTERFACE(IDirectInputEffect); + + CREATEINTERFACE(IClassFactory); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/License.txt b/client_files/native_autoloot/eq-core-dll/src/License.txt new file mode 100644 index 0000000000..4abc721c04 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/License.txt @@ -0,0 +1,15 @@ +/** +* Copyright (C) 2019 Elisha Riedlinger +* +* This software is provided 'as-is', without any express or implied warranty. In no event will the +* authors be held liable for any damages arising from the use of this software. +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you wrote the +* original software. If you use this software in a product, an acknowledgment in the product +* documentation would be appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as +* being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ \ No newline at end of file diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2AdvDps.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2AdvDps.cpp new file mode 100644 index 0000000000..cbe344b11b --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2AdvDps.cpp @@ -0,0 +1,692 @@ +// DPS ADV CREATED BY WARNEN 2008-2009 +// MQ2DPSAdv.cpp + +using namespace std; +#include +#include +#include +#include "MQ2AdvDps.h" + +#define DPSVERSION "1.2.06" +//#define DPSDEV + +extern std::map DamageEntries; + +// ############################### CDPSAdvWnd START ############################################ + +CDPSAdvWnd::CDPSAdvWnd() :CCustomWnd("DPSAdvWnd") { + int CheckUI = false; + if (!(Tabs = (CTabWnd*)GetChildItem("DPS_Tabs"))) CheckUI = true; + if (!(LTopList = (CListWnd*)GetChildItem("DPS_TopList"))) CheckUI = true; + if (!(CMobList = (CComboWnd*)GetChildItem("DPS_MobList"))) CheckUI = true; + if (!(CShowMeTop = (CCheckBoxWnd*)GetChildItem("DPS_ShowMeTopBox"))) CheckUI = true; + if (!(CShowMeMin = (CCheckBoxWnd*)GetChildItem("DPS_ShowMeMinBox"))) CheckUI = true; + if (!(TShowMeMin = (CTextEntryWnd*)GetChildItem("DPS_ShowMeMinInput"))) CheckUI = true; + if (!(CUseRaidColors = (CCheckBoxWnd*)GetChildItem("DPS_UseRaidColorsBox"))) CheckUI = true; + if (!(CLiveUpdate = (CCheckBoxWnd*)GetChildItem("DPS_LiveUpdateBox"))) CheckUI = true; + if (!(TFightIA = (CTextEntryWnd*)GetChildItem("DPS_FightIAInput"))) CheckUI = true; + if (!(TFightTO = (CTextEntryWnd*)GetChildItem("DPS_FightTOInput"))) CheckUI = true; + if (!(TEntTO = (CTextEntryWnd*)GetChildItem("DPS_EntTOInput"))) CheckUI = true; + if (!(CShowTotal = (CComboWnd*)GetChildItem("DPS_ShowTotal"))) CheckUI = true; + //if (!(LFightList = (CListWnd*)GetChildItem("DPS_FightList"))) CheckUI = true; + this->BGColor.ARGB = 0xFF000000; + Tabs->BGColor.ARGB = 0xFF000000; + LTopList->BGColor.ARGB = 0xFF000000; + CShowMeTop->BGColor.ARGB = 0xFF000000; + CShowMeMin->BGColor.ARGB = 0xFF000000; + TShowMeMin->BGColor.ARGB = 0xFF000000; + CUseRaidColors->BGColor.ARGB = 0xFF000000; + CLiveUpdate->BGColor.ARGB = 0xFF000000; + TFightIA->BGColor.ARGB = 0xFF000000; + TFightTO->BGColor.ARGB = 0xFF000000; + TEntTO->BGColor.ARGB = 0xFF000000; + CShowTotal->BGColor.ARGB = 0xFF000000; + if (CheckUI) { + WriteChatf("\ar[DPSAdv] Incorrect UI File in use. Please update to the latest client files."); + WrongUI = true; + } + else WrongUI = false; + + LoadLoc(); + SetWndNotification(CDPSAdvWnd); + //LTopList->SetColors(0xFFFFFFFF, 0xFFCC3333, 0xFF666666); + //LFightList->SetColors(0xFFFFFFFF, 0xFFCC3333, 0xFF666666); + CMobList->SetColors(0xFFCC3333, 0xFF666666, 0xFF000000); + Tabs->UpdatePage(); + DrawCombo(); + //LFightList->AddString(&CXStr("1"), 0, 0, 0); + //LFightList->AddString(&CXStr("2"), 0, 0, 0); + //LFightList->AddString(&CXStr("3"), 0, 0, 0); + //LFightList->ExtendSel(1); + //LFightList->ExtendSel(2); +} + +CDPSAdvWnd::~CDPSAdvWnd() {} + +void CDPSAdvWnd::DrawCombo() { + int CurSel = CMobList->GetCurChoice(); + CMobList->DeleteAll(); + CHAR szTemp[MAX_STRING] = { 0 }; + //sprintf_s(szTemp, " %s", CurListMob ? CurListMob->Name : "None"); + sprintf_s(szTemp, " %s", CListType == CLISTTARGET && CurListMob ? CurListMob->Name : "None"); + CMobList->InsertChoice(szTemp); + sprintf_s(szTemp, " %s", CListType == CLISTMAXDMG && CurMaxMob ? CurListMob->Name : "None"); + CMobList->InsertChoice(szTemp); + int i = 0, ListSize = 0; + for (auto mob : DamageEntries) { + + auto entrySpawn = mob.second.SpawnID > 0 ? (PSPAWNINFO)GetSpawnByID(mob.second.SpawnID) : nullptr; + + if (entrySpawn && entrySpawn->Type == 1) { + ListSize++; + sprintf_s(szTemp, "(%i) %s", ListSize, entrySpawn->Name); + CMobList->InsertChoice(szTemp); + } + } + + if (ListSize < 6) CMobList->InsertChoice(""); + + if (CListType == CLISTTARGET) CMobList->SetChoice(0); + else if (CListType == CLISTMAXDMG) CMobList->SetChoice(1); + else CMobList->SetChoice(CurSel >= 0 ? CurSel : 0); +} + +void CDPSAdvWnd::SetTotal(int LineNum, PSPAWNINFO Mob) { + CHAR szTemp[MAX_STRING] = { 0 }; + + if (!Mob) + return; + + EdgeDPSEntry Entry = GetEdgeDPSEntryByID(Mob->SpawnID, false); + + if (Entry.SpawnID) + { + SetLineColors(LineNum, Entry, true, false, false); + LTopList->SetItemText(LineNum, 0, &CXStr("-")); + LTopList->SetItemText(LineNum, 1, &CXStr("Total")); + sprintf_s(szTemp, "%i", Entry.TotalIncomingDamage); + LTopList->SetItemText(LineNum, 2, &CXStr(szTemp)); + + auto timestamp = std::chrono::high_resolution_clock::now(); + + std::chrono::duration elapsed_seconds = timestamp - Entry.BeginningTimestamp; + + auto dpsTOTAL = 0; + auto dpsAVRGE = 0; + + DWORD damages = Entry.TotalIncomingDamage; + DOUBLE estimate = damages / elapsed_seconds.count(); + dpsTOTAL++; + DOUBLE evaluate = (estimate - dpsAVRGE) / dpsTOTAL + dpsAVRGE; dpsAVRGE = evaluate; + if (elapsed_seconds.count() == 0.0) + { + evaluate = 0.f; + } + std::ostringstream outEstimate; + outEstimate.precision(3); + outEstimate << std::fixed << estimate; + LTopList->SetItemText(LineNum, 3, &CXStr(outEstimate.str().c_str())); + + + sprintf_s(szTemp, "%i", Entry.TotalOutgoingDamage); + LTopList->SetItemText(LineNum, 4, &CXStr(szTemp)); + + dpsTOTAL = 0; + dpsAVRGE = 0; + + damages = Entry.TotalOutgoingDamage; + estimate = damages / elapsed_seconds.count(); + dpsTOTAL++; + evaluate = (estimate - dpsAVRGE) / dpsTOTAL + dpsAVRGE; dpsAVRGE = evaluate; + if (elapsed_seconds.count() == 0.0) + { + evaluate = 0.f; + } + std::ostringstream inEstimate; + inEstimate.precision(3); + inEstimate << std::fixed << estimate; + LTopList->SetItemText(LineNum, 5, &CXStr(inEstimate.str().c_str())); + } +} + +void CDPSAdvWnd::DrawList() { + int ScrollPos = LTopList->VScrollPos; + int CurSel = LTopList->GetCurSel(); + CHAR szTemp[MAX_STRING] = { 0 }; + LTopList->DeleteAll(); + int i = 0, LineNum = 0, RankAdj = 0, ShowMeLineNum = 0; + bool FoundMe = false, ThisMe = false; + if (ShowTotal == TOTALABOVE) { + LineNum = LTopList->AddString(CXStr(" "), 0, 0, 0); + SetTotal(LineNum, CurListMob); + RankAdj++; + } + if (ShowMeTop) { + ShowMeLineNum = LTopList->AddString(CXStr(" "), 0, 0, 0); + SetLineColors(ShowMeLineNum, EdgeDPSEntry(), false, true, false); + RankAdj++; + } + if (ShowTotal == TOTALSECOND) { + LineNum = LTopList->AddString(CXStr(" "), 0, 0, 0); + SetTotal(LineNum, CurListMob); + RankAdj++; + } + + for (auto entry : DamageEntries) { + auto spawnEntry = (PSPAWNINFO)GetSpawnByID(entry.first); + + if (ShowMeTop && spawnEntry && !strcmp(spawnEntry->Name, ((PSPAWNINFO)pCharSpawn)->DisplayedName)) { + if (!ShowMeMin || (LineNum - RankAdj + 1) > ShowMeMinNum) FoundMe = true; + ThisMe = true; + } + else ThisMe = false; + LineNum = LTopList->AddString(CXStr(" "), 0, 0, 0); + SetLineColors(LineNum, entry.second); + sprintf_s(szTemp, "%i", LineNum - RankAdj + 1); + LTopList->SetItemText(LineNum, 0, &CXStr(szTemp)); + if (ThisMe) LTopList->SetItemText(ShowMeLineNum, 0, &CXStr(szTemp)); + sprintf_s(szTemp, "%s%s", spawnEntry ? spawnEntry->Name : " ", spawnEntry && spawnEntry->PetID > 0 ? "*" : " "); + LTopList->SetItemText(LineNum, 1, &CXStr(szTemp)); + if (ThisMe) LTopList->SetItemText(ShowMeLineNum, 1, &CXStr(szTemp)); + sprintf_s(szTemp, "%i", entry.second.TotalIncomingDamage); + LTopList->SetItemText(LineNum, 2, &CXStr(szTemp)); + if (ThisMe) LTopList->SetItemText(ShowMeLineNum, 2, &CXStr(szTemp)); + auto timestamp = std::chrono::high_resolution_clock::now(); + + std::chrono::duration elapsed_seconds = timestamp - entry.second.BeginningTimestamp; + + auto dpsTOTAL = 0; + auto dpsAVRGE = 0; + + DWORD damages = entry.second.TotalIncomingDamage; + DOUBLE estimate = damages / elapsed_seconds.count(); + dpsTOTAL++; + DOUBLE evaluate = (estimate - dpsAVRGE) / dpsTOTAL + dpsAVRGE; dpsAVRGE = evaluate; + if (elapsed_seconds.count() == 0.0) + { + evaluate = 0.f; + } + std::ostringstream outEstimate; + outEstimate.precision(3); + outEstimate << std::fixed << estimate; + LTopList->SetItemText(LineNum, 3, &CXStr(outEstimate.str().c_str())); + if (ThisMe) LTopList->SetItemText(ShowMeLineNum, 3, &CXStr(outEstimate.str().c_str())); + + sprintf_s(szTemp, "%i", entry.second.TotalOutgoingDamage); + LTopList->SetItemText(LineNum, 4, &CXStr(szTemp)); + + dpsTOTAL = 0; + dpsAVRGE = 0; + + damages = entry.second.TotalOutgoingDamage; + estimate = damages / elapsed_seconds.count(); + dpsTOTAL++; + evaluate = (estimate - dpsAVRGE) / dpsTOTAL + dpsAVRGE; dpsAVRGE = evaluate; + if (elapsed_seconds.count() == 0.0) + { + evaluate = 0.f; + } + std::ostringstream inEstimate; + inEstimate.precision(3); + inEstimate << std::fixed << estimate; + + LTopList->SetItemText(LineNum, 5, &CXStr(inEstimate.str().c_str())); + if (ThisMe) LTopList->SetItemText(ShowMeLineNum, 5, &CXStr(inEstimate.str().c_str())); + + } + if (ShowTotal == TOTALBOTTOM) { + LineNum = LTopList->AddString(CXStr(" "), 0, 0, 0); + SetTotal(LineNum, CurListMob); + } + if (ShowMeTop && !FoundMe) LTopList->RemoveLine(ShowMeLineNum); + LTopList->VScrollPos = ScrollPos; + LTopList->CalculateFirstVisibleLine(); + LTopList->SetCurSel(CurSel); +} + +void CDPSAdvWnd::SetLineColors(int LineNum, EdgeDPSEntry ent, bool Total, bool MeTop, bool UseEnt) { + + auto entrySpawn = ent.SpawnID > 0 && UseEnt ? (PSPAWNINFO)GetSpawnByID(ent.SpawnID) : nullptr; + + if (MeTop) { + LTopList->SetItemColor(LineNum, 0, MeTopColor); + LTopList->SetItemColor(LineNum, 1, MeTopColor); + LTopList->SetItemColor(LineNum, 2, MeTopColor); + LTopList->SetItemColor(LineNum, 3, MeTopColor); + LTopList->SetItemColor(LineNum, 4, MeTopColor); + LTopList->SetItemColor(LineNum, 5, MeTopColor); + + } + else if (Total) { + LTopList->SetItemColor(LineNum, 0, TotalColor); + LTopList->SetItemColor(LineNum, 1, TotalColor); + LTopList->SetItemColor(LineNum, 2, TotalColor); + LTopList->SetItemColor(LineNum, 3, TotalColor); + LTopList->SetItemColor(LineNum, 4, TotalColor); + LTopList->SetItemColor(LineNum, 5, TotalColor); + + } + if (entrySpawn && entrySpawn->Type == SPAWN_PLAYER) { + //WriteChatf("Setting Raid Color: %i, %i, %i", Ent->Class, Coloring[Ent->Class], ((PEQRAIDWINDOW)pRaidWnd)->ClassColors[ClassInfo.RaidColorOrder[Ent->Class]]); + LTopList->SetItemColor(LineNum, 0, MeColor); + LTopList->SetItemColor(LineNum, 1, MeColor); + LTopList->SetItemColor(LineNum, 2, MeColor); + LTopList->SetItemColor(LineNum, 3, MeColor); + LTopList->SetItemColor(LineNum, 4, MeColor); + LTopList->SetItemColor(LineNum, 5, MeColor); + + } + else { + LTopList->SetItemColor(LineNum, 0, NormalColor); + LTopList->SetItemColor(LineNum, 1, NPCColor); + LTopList->SetItemColor(LineNum, 2, NormalColor); + LTopList->SetItemColor(LineNum, 3, NormalColor); + LTopList->SetItemColor(LineNum, 4, NormalColor); + LTopList->SetItemColor(LineNum, 5, NormalColor); + } +} +/* +void CDPSAdvWnd::SaveSetting(PCHAR Key, PCHAR Value, ...) { + char zOutput[MAX_STRING]; va_list vaList; va_start(vaList,Value); + vsprintf_s(zOutput,Value,vaList); + WritePrivateProfileString(GetCharInfo()->Name, Key, zOutput, "Edge.ini"); + if (!Saved) { + Saved = true; + WritePrivateProfileString(GetCharInfo()->Name, "Saved", "1", "Edge.ini"); + } +} +*/ +void CDPSAdvWnd::SaveLoc() { + if (!GetCharInfo()) return; + CHAR szTemp[MAX_STRING] = { 0 }; + WritePrivateProfileString(GetCharInfo()->Name, "Saved", "1", "Edge.ini"); + sprintf_s(szTemp, "%i", Location.top); + WritePrivateProfileString(GetCharInfo()->Name, "Top", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", Location.bottom); + WritePrivateProfileString(GetCharInfo()->Name, "Bottom", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", Location.left); + WritePrivateProfileString(GetCharInfo()->Name, "Left", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", Location.right); + WritePrivateProfileString(GetCharInfo()->Name, "Right", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", Alpha); + WritePrivateProfileString(GetCharInfo()->Name, "Alpha", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", FadeToAlpha); + WritePrivateProfileString(GetCharInfo()->Name, "FadeToAlpha", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", CListType); + WritePrivateProfileString(GetCharInfo()->Name, "CListType", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", LiveUpdate ? 1 : 0); + WritePrivateProfileString(GetCharInfo()->Name, "LiveUpdate", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", dShow); + WritePrivateProfileString(GetCharInfo()->Name, "Show", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", ShowMeTop ? 1 : 0); + WritePrivateProfileString(GetCharInfo()->Name, "ShowMeTop", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", ShowMeMin ? 1 : 0); + WritePrivateProfileString(GetCharInfo()->Name, "ShowMeMin", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", ShowMeMinNum); + WritePrivateProfileString(GetCharInfo()->Name, "ShowMeMinNum", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", UseRaidColors ? 1 : 0); + WritePrivateProfileString(GetCharInfo()->Name, "UseRaidColors", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", ShowTotal); + WritePrivateProfileString(GetCharInfo()->Name, "ShowTotal", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", FightIA); + WritePrivateProfileString(GetCharInfo()->Name, "FightIA", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", FightTO); + WritePrivateProfileString(GetCharInfo()->Name, "FightTO", szTemp, "Edge.ini"); + sprintf_s(szTemp, "%i", EntTO); + WritePrivateProfileString(GetCharInfo()->Name, "EntTO", szTemp, "Edge.ini"); +} + +void CDPSAdvWnd::LoadSettings() { + CHAR szTemp[MAX_STRING] = { 0 }; + CShowMeTop->Checked = ShowMeTop ? 1 : 0; + CShowMeMin->Checked = ShowMeMin ? 1 : 0; + sprintf_s(szTemp, "%i", ShowMeMinNum); + SetCXStr(&TShowMeMin->InputText, szTemp); + CUseRaidColors->Checked = UseRaidColors ? 1 : 0; + CLiveUpdate->Checked = LiveUpdate ? 1 : 0; + sprintf_s(szTemp, "%i", FightIA); + SetCXStr(&TFightIA->InputText, szTemp); + sprintf_s(szTemp, "%i", FightTO); + SetCXStr(&TFightTO->InputText, szTemp); + sprintf_s(szTemp, "%i", EntTO); + SetCXStr(&TEntTO->InputText, szTemp); + CShowTotal->DeleteAll(); + CShowTotal->InsertChoice("Don't Show Total"); + CShowTotal->InsertChoice("Above ShowMeTop"); + CShowTotal->InsertChoice("Below ShowMeTop"); + CShowTotal->InsertChoice("Show Bottom"); + CShowTotal->InsertChoice(""); + CShowTotal->SetChoice(ShowTotal); +} + +void CDPSAdvWnd::LoadLoc(char szChar[256]) { + if (!GetCharInfo()) return; + char szName[256] = { 0 }; + if (!szChar) strcpy_s(szName, GetCharInfo()->Name); + else strcpy_s(szName, szChar); + Saved = (GetPrivateProfileInt(szName, "Saved", 0, "Edge.ini") > 0 ? true : false); + if (Saved && DPSWnd) { + DPSWnd->Location = { (LONG)GetPrivateProfileInt(szName, "Left", 0, "Edge.ini"), + (LONG)GetPrivateProfileInt(szName, "Top", 0, "Edge.ini"), + (LONG)GetPrivateProfileInt(szName, "Right", 0, "Edge.ini"), + (LONG)GetPrivateProfileInt(szName, "Bottom", 0, "Edge.ini") }; + + DPSWnd->Alpha = (BYTE)GetPrivateProfileInt(szName, "Alpha", 0, "Edge.ini"); + + DPSWnd->FadeToAlpha = (BYTE)GetPrivateProfileInt(szName, "FadeToAlpha", 0, "Edge.ini"); + } + CListType = GetPrivateProfileInt(szName, "CListType", 0, "Edge.ini"); + LiveUpdate = (GetPrivateProfileInt(szName, "LiveUpdate", 0, "Edge.ini") > 0 ? true : false); + Debug = (GetPrivateProfileInt(szName, "Debug", 0, "Edge.ini") > 0 ? true : false); + if(DPSWnd) + DPSWnd->dShow = (GetPrivateProfileInt(szName, "Show", 1, "Edge.ini") > 0 ? true : false); + ShowMeTop = (GetPrivateProfileInt(szName, "ShowMeTop", 0, "Edge.ini") > 0 ? true : false); + ShowMeMin = (GetPrivateProfileInt(szName, "ShowMeMin", 0, "Edge.ini") > 0 ? true : false); + ShowMeMinNum = GetPrivateProfileInt(szName, "ShowMeMinNum", 0, "Edge.ini"); + UseRaidColors = (GetPrivateProfileInt(szName, "UseRaidColors", 0, "Edge.ini") > 0 ? true : false); + ShowTotal = GetPrivateProfileInt(szName, "ShowTotal", 0, "Edge.ini"); + FightIA = GetPrivateProfileInt(szName, "FightIA", 8, "Edge.ini"); + FightTO = GetPrivateProfileInt(szName, "FightTO", 30, "Edge.ini"); + EntTO = GetPrivateProfileInt(szName, "EntTO", 8, "Edge.ini"); + MeColor = GetPrivateProfileInt(szName, "MeColor", 0xFF00CC00, "Edge.ini"); + MeTopColor = GetPrivateProfileInt(szName, "MeTopColor", 0xFF00CC00, "Edge.ini"); + NormalColor = GetPrivateProfileInt(szName, "NormalColor", 0xFFFFFFFF, "Edge.ini"); + NPCColor = GetPrivateProfileInt(szName, "NPCColor", 0xFFFFFFFF, "Edge.ini"); + TotalColor = GetPrivateProfileInt(szName, "TotalColor", 0xFF66FFFF, "Edge.ini"); + EntHover = GetPrivateProfileInt(szName, "EntHover", 0xFFCC3333, "Edge.ini"); + EntHighlight = GetPrivateProfileInt(szName, "EntHighlight", 0xFF666666, "Edge.ini"); + FightNormal = GetPrivateProfileInt(szName, "FightNormal", NormalColor, "Edge.ini"); + FightHover = GetPrivateProfileInt(szName, "FightHover", EntHover, "Edge.ini"); + FightHighlight = GetPrivateProfileInt(szName, "FightHighlight", EntHighlight, "Edge.ini"); + FightActive = GetPrivateProfileInt(szName, "FightActive", 0xFF00CC00, "Edge.ini"); + FightInActive = GetPrivateProfileInt(szName, "FightInActive", 0xFF777777, "Edge.ini"); + FightDead = GetPrivateProfileInt(szName, "FightDead", 0xFF330000, "Edge.ini"); + if (FightIA < 3) FightIA = 8; + if (FightTO < 3) FightTO = 30; + if (EntTO < 3) EntTO = 8; + if (Debug) gSpewToFile = TRUE; + if (CListType > 1) CListType = CLISTTARGET; + LTopList->SetColors(NormalColor, EntHover, EntHighlight); + // LFightList->SetColors(FightNormal, FightHover, FightHighlight); + CMobList->SetChoice(CListType); + LoadSettings(); +} + +int CDPSAdvWnd::WndNotification(CXWnd *pWnd, unsigned int Message, void *unknown) { + if (Debug && Message != 21) WriteChatf("Notify: %i", Message); + if (Message == 10) CheckActive(); + if (Message == 3 && pWnd == (CXWnd*)LTopList) LTopList->SetCurSel(-1); + else if (Message == 10 && pWnd == (CXWnd*)DPSWnd) CheckActive(); + else if (Message == 1) { + if (pWnd == (CXWnd*)Tabs) LoadSettings(); + else if (pWnd == (CXWnd*)CShowMeTop) ShowMeTop = CShowMeTop->Checked ? true : false; + else if (pWnd == (CXWnd*)CShowMeMin) ShowMeMin = CShowMeMin->Checked ? true : false; + else if (pWnd == (CXWnd*)CUseRaidColors) UseRaidColors = CUseRaidColors->Checked ? true : false; + else if (pWnd == (CXWnd*)CLiveUpdate) LiveUpdate = CLiveUpdate->Checked ? true : false; + //else if (pWnd == (CXWnd*)LTopList) WriteChatf("CurSel: %i", LTopList->GetCurSel()); + else if (pWnd == (CXWnd*)CShowTotal) { + ShowTotal = CShowTotal->GetCurChoice(); + if (ShowTotal == 4) ShowTotal = 0; + LoadSettings(); + } + else if (pWnd == (CXWnd*)CMobList) { + CurListMob = 0; + LTopList->DeleteAll(); + bool FoundMob = false; + if ((int)CMobList->GetCurChoice() > 1) { + CListType = 2; + int i = 0, x = 0; + for (auto mob : DamageEntries) { + auto ListMob = (PSPAWNINFO)GetSpawnByID(mob.first); + if (ListMob && ListMob->Type == 1 && !ListMob->PetID != 0) { + if (x + 2 == (int)CMobList->GetCurChoice()) { + FoundMob = true; + ListSwitch(ListMob); + break; + } + x++; + } + } + if (!FoundMob) { + CListType = 0; + DPSWnd->DrawCombo(); + } + } + else CListType = (int)CMobList->GetCurChoice(); + Intervals -= 1; // Force update next Pulse. + } + } + else if (Message == 14) { + CHAR szTemp[MAX_STRING] = { 0 }; + GetCXStr(((CEditWnd*)pWnd)->InputText, szTemp); + if (pWnd == (CXWnd*)TShowMeMin) { + if (strlen(szTemp)) { + szTemp[2] = 0; + ShowMeMinNum = atoi(szTemp); + sprintf_s(szTemp, "%i", ShowMeMinNum); + SetCXStr(&TShowMeMin->InputText, szTemp); + TShowMeMin->SetSel(strlen(szTemp), 0); + } + } + else if (pWnd == (CXWnd*)TFightIA) { + if (strlen(szTemp)) { + szTemp[2] = 0; + FightIA = atoi(szTemp); + if (FightIA < 3) FightIA = 8; + sprintf_s(szTemp, "%i", FightIA); + //SetCXStr(&TFightTO->InputText, szTemp); + //TFightTO->SetSel(strlen(szTemp), 0); + } + } + else if (pWnd == (CXWnd*)TFightTO) { + if (strlen(szTemp)) { + szTemp[2] = 0; + FightTO = atoi(szTemp); + if (FightTO < 3) FightTO = 30; + sprintf_s(szTemp, "%i", FightTO); + //SetCXStr(&TFightTO->InputText, szTemp); + //TFightTO->SetSel(strlen(szTemp), 0); + } + } + else if (pWnd == (CXWnd*)TEntTO) { + if (strlen(szTemp)) { + szTemp[2] = 0; + EntTO = atoi(szTemp); + if (EntTO < 3) EntTO = 8; + sprintf_s(szTemp, "%i", EntTO); + //SetCXStr(&TEntTO->InputText, szTemp); + //TEntTO->SetSel(strlen(szTemp), 0); + } + } + } + + + return CSidlScreenWnd::WndNotification(pWnd, Message, unknown); +}; + + +#ifdef DPSDEV +void DPSTestCmd(PSPAWNINFO pChar, PCHAR szLine) { + +} +#endif + +void DPSAdvCmd(PSPAWNINFO pChar, PCHAR szLine) { + char Arg1[MAX_STRING]; + GetArg(Arg1, szLine, 1); + if (!_stricmp(Arg1, "show")) + if (!DPSWnd) WriteChatf("\arDPSWnd does not exist. Try reloading your UI (/loadskin default)."); + else DPSWnd->dShow = !DPSWnd->dShow; + else if (!_stricmp(Arg1, "colors")) + ((CXWnd*)pRaidOptionsWnd)->Show(1, 1); + else if (DPSWnd && !_stricmp(Arg1, "reload")) + DPSWnd->LoadLoc(); + else if (DPSWnd && !_stricmp(Arg1, "save")) + DPSWnd->SaveLoc(); + else if (!_stricmp(Arg1, "listsize")) + WriteChatf("\ayMobList Size: %i", DamageEntries.size()); + else if (!_stricmp(Arg1, "copy")) { + char szCopy[MAX_STRING]; + GetArg(szCopy, szLine, 2); + if (DPSWnd) { + DPSWnd->LoadLoc(szCopy); + DPSWnd->SaveLoc(); + } + else WriteChatf("\arFailed to Copy: DPS Window not loaded."); + } + else if (!_stricmp(Arg1, "Debug")) { + Debug = Debug ? false : true; + WriteChatf("Debug is now: %s", Debug ? "\agOn" : "\arOff"); + } + CheckActive(); +} + +void CreateDPSWindow() { + if (DPSWnd) DestroyDPSWindow(); + if (pSidlMgr->FindScreenPieceTemplate("DPSAdvWnd")) { + DPSWnd = new CDPSAdvWnd(); + if (DPSWnd->dShow) ((CXWnd*)DPSWnd)->Show(1, 1); + char szTitle[MAX_STRING]; + sprintf_s(szTitle, "DPS Window", DPSVERSION); + SetCCXStr(&DPSWnd->WindowText, szTitle); + } + CheckActive(); +} + +void DestroyDPSWindow() { + if (DPSWnd) { + DPSWnd->SaveLoc(); + delete DPSWnd; + DPSWnd = 0; + } + CheckActive(); +} + +PLUGIN_API VOID SetDPSGameState(DWORD GameState) { + DebugSpewAlways("GameState Change: %i", GameState); + if (GameState == GAMESTATE_INGAME) { + if (!DPSWnd) CreateDPSWindow(); + } +} +bool bCleaned = false; +PLUGIN_API VOID OnDPSCleanUI(VOID) { DestroyDPSWindow(); bCleaned = true; } +PLUGIN_API VOID OnDPSReloadUI(VOID) { if (gGameState == GAMESTATE_INGAME && pCharSpawn) CreateDPSWindow(); } + +PLUGIN_API VOID InitializeDPSPlugin(VOID) { + LastMob = 0; + CurTarget = 0; + CurTarMob = 0; + CurListMob = 0; + CurMaxMob = 0; + Zoning = false; + ShowMeTop = false; + WrongUI = false; + AddXMLFile("EQUI_DPSAdvWnd.xml"); + AddCommand("/advdps", DPSAdvCmd); + CheckActive(); + if (gGameState != GAMESTATE_INGAME || !pCharSpawn) return; + else CreateDPSWindow(); +} + +PLUGIN_API VOID ShutdownDPSPlugin(VOID) { + DestroyDPSWindow(); + RemoveCommand("/advdps"); +#ifdef DPSDEV + RemoveCommand("/dpstest"); +#endif +} + +bool CheckInterval() { + if (!Intervals) Intervals = time(NULL); + else if (Intervals != time(NULL)) { + Intervals = time(NULL); + return true; + } + return false; +} + +void CheckActive() { + if (DPSWnd && DPSWnd->dShow && !Zoning && !WrongUI) Active = true; + else Active = false; +} + +void ListSwitch(PSPAWNINFO Switcher) { + if (Switcher) + { + CurListMob = Switcher; + } + DPSWnd->LTopList->SetCurSel(-1); + DPSWnd->LTopList->VScrollPos = 0; + DPSWnd->DrawList(); + DPSWnd->DrawCombo(); +} + +void TargetSwitch() { + CurTarget = (PSPAWNINFO)pTarget; + ListSwitch(CurTarget); +} + +void HandleDeath(EdgeDPSEntry DeadMob) { + + DPSWnd->DrawList(); +} + +void IntPulse() { + bool CChange = false; + for (auto mob : DamageEntries) { + auto spawnEntry = (PSPAWNINFO)GetSpawnByID(mob.first); + } + if (CListType == CLISTMAXDMG && CurMaxMob && CurMaxMob != CurListMob) + ListSwitch(CurMaxMob); + if (CChange) + DPSWnd->DrawCombo(); + DPSWnd->DrawList(); + //WriteChatf("Active: %s", Active ? "Yes" : "No"); +} + +PLUGIN_API VOID OnDPSPulse(VOID) { + if (gGameState != GAMESTATE_INGAME || !pCharSpawn) return; + + if (gGameState == GAMESTATE_INGAME) { + if (!DPSWnd) + CreateDPSWindow(); + } + + if (Active) { + + if (DPSWnd->dShow) ((CXWnd*)DPSWnd)->Show(1, 1); + if ((PSPAWNINFO)pTarget && (PSPAWNINFO)pTarget != CurTarget) TargetSwitch(); + if (CListType == CLISTTARGET && CurTarMob && CurTarMob != CurListMob) + { + auto entry = GetEdgeDPSEntryByID(CurTarMob->SpawnID, false); + if (entry.SpawnID && entry.weDamaged) + { + ListSwitch(CurTarMob); + } + } + if (CheckInterval()) IntPulse(); + } +} + +void ZoneProcess() { + LastMob = 0; + CurTarget = 0; + CurTarMob = 0; + CurListMob = 0; + CurMaxMob = 0; + DPSMob *pMob = 0; + DPSMob::DPSEntry *pEnt = 0; +} + +PLUGIN_API VOID OnDPSBeginZone(VOID) { + //DebugSpewAlways("START ZONING"); + ZoneProcess(); + Zoning = true; + CheckActive(); +} + +PLUGIN_API VOID OnDPSEndZone(VOID) { + //DebugSpewAlways("END ZONING"); + Zoning = false; + CheckActive(); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2Auth.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2Auth.cpp new file mode 100644 index 0000000000..a78242e140 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2Auth.cpp @@ -0,0 +1,11 @@ +#ifndef ISXEQ +#include "MQ2Main.h" + +DWORD gh; +LRESULT CALLBACK proc( int nCode, WPARAM wParam, LPARAM lParam ){return ::CallNextHookEx( (HHOOK)gh, nCode, wParam, lParam );} +typedef DWORD (__cdecl *FNCB)(DWORD,HINSTANCE,DWORD&); +#undef MQ2AUTH +#define MQ2AUTH(z) VOID z(DWORD x){FNCB f=(FNCB)x;f((DWORD)proc,ghInstance,gh);} +#include "MQ2Auth0.h" + +#endif diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2Benchmarks.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2Benchmarks.cpp new file mode 100644 index 0000000000..95b599db25 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2Benchmarks.cpp @@ -0,0 +1,170 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +#error /DCINTERFACE +#endif + +#define DBG_SPEW +//#define DBG_TRY + +#include "MQ2Main.h" + +typedef CIndex BMIndex; +BMIndex *pBenchmarks=0; +#define Benchmarks (*pBenchmarks) + +DWORD AddMQ2Benchmark(PCHAR Name) +{ + DebugSpew("AddMQ2Benchmark(%s)",Name); + DWORD NewHandle= pBenchmarks->GetUnused(); + Benchmarks[NewHandle]=new MQBENCH; + memset(Benchmarks[NewHandle],0,sizeof(MQBENCH)); + strcpy(Benchmarks[NewHandle]->szName,Name); + return NewHandle; +} + +VOID RemoveMQ2Benchmark(DWORD BMHandle) +{ + DebugSpew("RemoveMQ2Benchmark()"); + if (Benchmarks[BMHandle]) + { + delete Benchmarks[BMHandle]; + Benchmarks[BMHandle]=0; + } +} + +VOID EnterMQ2Benchmark(DWORD BMHandle) +{ + if (!pBenchmarks) + return; + if (Benchmarks[BMHandle]) + { + //DebugSpew("EnterMQ2Benchmark(%s)",Benchmarks[BMHandle]->szName); + Benchmarks[BMHandle]->Entry=GetTickCount(); + } +} + +VOID ExitMQ2Benchmark(DWORD BMHandle) +{ + if (!pBenchmarks) + return; + if (Benchmarks[BMHandle]) + { + DWORD Time=GetTickCount()-Benchmarks[BMHandle]->Entry; + //DebugSpew("ExitMQ2Benchmark(%s)",Benchmarks[BMHandle]->szName); + Benchmarks[BMHandle]->LastTime=Time; + if (Benchmarks[BMHandle]->Count>4000000000) + { + Benchmarks[BMHandle]->Count=1; + Benchmarks[BMHandle]->TotalTime=Time; + } + else + { + Benchmarks[BMHandle]->Count++; + Benchmarks[BMHandle]->TotalTime+=Time; + } + } +} + +BOOL GetMQ2Benchmark(DWORD BMHandle, MQBENCH &Dest) +{ + if (!pBenchmarks) + return false; + if (Benchmarks[BMHandle]) + { + Dest=*Benchmarks[BMHandle]; // give them a copy of the data. + return true; + } + return false; +} + +#ifndef ISXEQ +VOID SpewMQ2BenchmarksToChat(PSPAWNINFO pChar, PCHAR szLine) +{ + char out[256]; + if (szLine && szLine[0]=='/') + { + DWORD Start=GetTickCount(); + HideDoCommand(pChar,szLine,0); + DWORD Time=GetTickCount()-Start; + sprintf(out,"\ay%s\ax completed in \at%.2f\axs",szLine,(float)Time/(float)1000); + WriteChatColor(out); + } + else + { + WriteChatColor("MQ2 Benchmarks"); + WriteChatColor("--------------"); + for (unsigned long i = 0 ; i < pBenchmarks->Size ; i++) + { + if (Benchmarks[i]) + { + float Avg=0; + if (Benchmarks[i]->Count) + Avg=(float)Benchmarks[i]->TotalTime/(float)Benchmarks[i]->Count; + sprintf(out,"[\ay%s\ax] \at%d\ax for \at%d\axms, \at%.2f\ax avg",Benchmarks[i]->szName,Benchmarks[i]->Count,Benchmarks[i]->TotalTime,Avg); + WriteChatColor(out); + } + } + WriteChatColor("--------------"); + WriteChatColor("End Benchmarks"); + } +} +#endif + +VOID SpewMQ2Benchmarks() +{ + DebugSpewAlways("MQ2 Benchmarks"); + DebugSpewAlways("--------------"); + for (unsigned long i = 0 ; i < pBenchmarks->Size ; i++) + { + if (Benchmarks[i]) + { + float Avg=0; + if (Benchmarks[i]->Count) + Avg=(float)Benchmarks[i]->TotalTime/(float)Benchmarks[i]->Count; + DebugTry(DebugSpewAlways("%-40s %d for %dms, %.2f avg",Benchmarks[i]->szName,Benchmarks[i]->Count,Benchmarks[i]->TotalTime,Avg)); + } + } + DebugSpewAlways("--------------"); + DebugSpewAlways("End Benchmarks"); +} + +VOID InitializeMQ2Benchmarks() +{ + DebugSpew("Initializing MQ2 Benchmarks"); + pBenchmarks=new BMIndex(10); +#ifndef ISXEQ + AddCommand("/benchmark",SpewMQ2BenchmarksToChat,0,0); +#endif +} + +VOID ShutdownMQ2Benchmarks() +{ + DebugTry(SpewMQ2Benchmarks()); + DebugSpew("Shutting down MQ2 Benchmarks"); +#ifndef ISXEQ + RemoveCommand("/benchmark"); +#endif + if (pBenchmarks) + { + DebugTry(pBenchmarks->Cleanup()); + DebugTry(delete pBenchmarks); + } + pBenchmarks=0; +} + + + + diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2ChatHook.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2ChatHook.cpp new file mode 100644 index 0000000000..150a936fa5 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2ChatHook.cpp @@ -0,0 +1,149 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +//#error /DCINTERFACE +#endif + +#define DBG_SPEW + + +#include "MQ2Main.h" + +class CChatHook +{ +public: + VOID Trampoline(PCHAR szMsg, DWORD dwColor, bool EqLog, bool dopercentsubst); + VOID Detour(PCHAR szMsg, DWORD dwColor, bool EqLog, bool dopercentsubst) + { + //DebugSpew("CChatHook::Detour(%s)",szMsg); + gbInChat = TRUE; + + + //CheckChatForEvent(szMsg); + + BOOL Filtered=FALSE; + PFILTER Filter = gpFilters; + while (Filter && !Filtered) { + if (!Filter->pEnabled || (*Filter->pEnabled)) { + if (*Filter->FilterText == '*') { + if (strstr(szMsg,Filter->FilterText+1)) + Filtered = TRUE; + } else { + if (!strnicmp(szMsg,Filter->FilterText,Filter->Length)) + Filtered = TRUE; + } + } + Filter = Filter->pNext; + } + + if (!Filtered) { + //if (gTelnetServer && gTelnetConnection && !gPauseTelnetOutput) TelnetServer_Write(szMsg); + BOOL SkipTrampoline; + //OnDPSIncomingChat(szMsg, dwColor); + //Benchmark(bmPluginsIncomingChat,SkipTrampoline=PluginsIncomingChat(szMsg,dwColor)); + Trampoline(szMsg, dwColor, EqLog, dopercentsubst); + } + gbInChat = FALSE; + } + + VOID TellWnd_Trampoline(char *message,char *name,char *name2,void *unknown,int color,bool b); + VOID TellWnd_Detour(char *message,char *name,char *name2,void *unknown,int color,bool b) + { + char szMsg[MAX_STRING]; + BOOL SkipTrampoline; + gbInChat=true; + + sprintf(szMsg,"%s tells you, '%s'",name,message); + + // Benchmark(bmPluginsIncomingChat,SkipTrampoline=PluginsIncomingChat(szMsg,color)); + TellWnd_Trampoline(message,name,name2,unknown,color,b); + + gbInChat=false; + } + + VOID UPCNotificationFlush_Trampoline(); + VOID UPCNotificationFlush_Detour() + { + PEVERQUEST eq = (PEVERQUEST)this; + char szBuf[MAX_STRING] = {0}; + + if(eq->ChannelQty > 0) + { + int len = 0; + char *pTmp; + + if(eq->bJoinedChannel) + { + pTmp = "* %s has entered channel "; + } + else + { + pTmp = "* %s has left channel "; + } + + sprintf(szBuf, pTmp, eq->ChannelPlayerName); + + for(DWORD i = 0; i < eq->ChannelQty; i++) + { + if(i) + { + pTmp = ", %s:%d"; + } + else + { + pTmp = "%s:%d"; + } + + len = strlen(szBuf); + sprintf(&szBuf[len], pTmp, eq->ChannelName[i], eq->ChannelNumber[i] + 1); + } + } + + UPCNotificationFlush_Trampoline(); + } +}; + +DETOUR_TRAMPOLINE_EMPTY(VOID CChatHook::Trampoline(PCHAR szMsg, DWORD dwColor, bool EqLog, bool dopercentsubst)); +DETOUR_TRAMPOLINE_EMPTY(VOID CChatHook::TellWnd_Trampoline(char *message,char *name,char *name2,void *unknown,int color,bool b)); +DETOUR_TRAMPOLINE_EMPTY(VOID CChatHook::UPCNotificationFlush_Trampoline()); + +VOID dsp_chat_no_events(const char *Text,int Color,bool EqLog, bool dopercentsubst) +{ + ((CChatHook*)pEverQuest)->Trampoline((PCHAR)Text,Color,EqLog, dopercentsubst); +} + +unsigned int __stdcall MQ2DataVariableLookup(char * VarName, char * Value) +{ + strcpy(Value,VarName); + if (!GetCharInfo()) return strlen(Value); + return strlen(ParseMacroParameter(GetCharInfo()->pSpawn,Value)); +} + +VOID InitializeChatHook() +{ + DebugSpew("Initializing chat hook"); + + // initialize Blech + EzDetour(CEverQuest__dsp_chat,&CChatHook::Detour,&CChatHook::Trampoline); + EzDetour(CEverQuest__DoTellWindow,&CChatHook::TellWnd_Detour,&CChatHook::TellWnd_Trampoline); + EzDetour(CEverQuest__UPCNotificationFlush,&CChatHook::UPCNotificationFlush_Detour,&CChatHook::UPCNotificationFlush_Trampoline); +} + +VOID ShutdownChatHook() +{ + RemoveDetour(CEverQuest__dsp_chat); + RemoveDetour(CEverQuest__DoTellWindow); + RemoveDetour(CEverQuest__UPCNotificationFlush); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2CleanUI.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2CleanUI.cpp new file mode 100644 index 0000000000..8dc1db9b58 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2CleanUI.cpp @@ -0,0 +1,167 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +//#error /DCINTERFACE +#endif + +#define DBG_SPEW + +//#define DEBUG_TRY 1 +#include "MQ2Main.h" + +char *OurCaption = "Core is loading..."; + +class CDisplayHook +{ +public: + VOID CleanUI_Trampoline(VOID); + VOID CleanUI_Detour(VOID) + { + DebugTry(CleanUI_Trampoline()); + } + + VOID ReloadUI_Trampoline(BOOL); + VOID ReloadUI_Detour(BOOL UseINI) + { + DebugTry(ReloadUI_Trampoline(UseINI)); + } + + /* This function is still in the client; however, it was phased out as of + the Omens of War Expansion + + bool GetWorldFilePath_Trampoline(char *, char *); + bool GetWorldFilePath_Detour(char *Filename, char *FullPath) + { + if (!stricmp(FullPath,"bmpwad8.s3d")) + { + sprintf(Filename,"%s\\bmpwad8.s3d",gszINIPath); + if (_access(Filename,0)!=-1) + { + return 1; + } + } + + bool Ret=GetWorldFilePath_Trampoline(Filename,FullPath); + return Ret; + } + */ +}; + +#ifndef ISXEQ + +DWORD __cdecl DrawHUD_Trampoline(DWORD,DWORD,DWORD,DWORD); +DWORD __cdecl DrawHUD_Detour(DWORD a,DWORD b,DWORD c,DWORD d) +{ + DrawHUDParams[0]=a; + DrawHUDParams[1]=b; + DrawHUDParams[2]=c; + DrawHUDParams[3]=d; + if (gbHUDUnderUI || gbAlwaysDrawMQHUD) + return 0; + int Ret= DrawHUD_Trampoline(a,b,c,d); + //PluginsDrawHUD(); + if (HMODULE hmEQPlayNice=GetModuleHandle("EQPlayNice.dll")) + { + if (fMQPulse pEQPlayNicePulse=(fMQPulse)GetProcAddress(hmEQPlayNice,"Compat_DrawIndicator")) + pEQPlayNicePulse(); + } + return Ret; +} + +void DrawHUD() +{ + if (gbAlwaysDrawMQHUD || (gGameState==GAMESTATE_INGAME && gbHUDUnderUI && gbShowNetStatus)) + { + if (DrawHUDParams[0] && gGameState==GAMESTATE_INGAME && gbShowNetStatus) + { + DrawHUD_Trampoline(DrawHUDParams[0],DrawHUDParams[1],DrawHUDParams[2],DrawHUDParams[3]); + DrawHUDParams[0]=0; + } + if (HMODULE hmEQPlayNice=GetModuleHandle("EQPlayNice.dll")) + { + if (fMQPulse pEQPlayNicePulse=(fMQPulse)GetProcAddress(hmEQPlayNice,"Compat_DrawIndicator")) + pEQPlayNicePulse(); + } + + } + else + DrawHUDParams[0]=0; +} + +VOID DrawHUDText(PCHAR Text, DWORD X, DWORD Y, DWORD Argb, DWORD Size) +{ + + DWORD sX=((PCXWNDMGR)pWndMgr)->ScreenExtentX; + DWORD sY=((PCXWNDMGR)pWndMgr)->ScreenExtentY; + + CTextureFont* pFont=0; + DWORD* ppDWord=(DWORD*)((PCXWNDMGR)pWndMgr)->font_list_ptr; + if (ppDWord[1]<=2) + { + pFont=(CTextureFont*)ppDWord[0]; + } + else + { + pFont=(CTextureFont*)ppDWord[2]; + } + if(Size!=2 && Size<12) + pFont->Size=Size; + pFont->DrawWrappedText(&CXStr((char*)Text),X,Y,sX-X,&CXRect(X,Y,sX,sY),Argb,1,0); + pFont->Size=2; // reset back to 2 or it screws up other HUD sizes +} +#endif + +class EQ_LoadingSHook +{ +public: + + VOID SetProgressBar_Trampoline(int,char const *); + VOID SetProgressBar_Detour(int A,char const *B) + { + SetProgressBar_Trampoline(A,B); + } +}; + +//DETOUR_TRAMPOLINE_EMPTY(bool CDisplayHook::GetWorldFilePath_Trampoline(char *, char *)); +DETOUR_TRAMPOLINE_EMPTY(VOID EQ_LoadingSHook::SetProgressBar_Trampoline(int, char const *)); +DETOUR_TRAMPOLINE_EMPTY(DWORD DrawHUD_Trampoline(DWORD,DWORD,DWORD,DWORD)); +DETOUR_TRAMPOLINE_EMPTY(VOID CDisplayHook::CleanUI_Trampoline(VOID)); +DETOUR_TRAMPOLINE_EMPTY(VOID CDisplayHook::ReloadUI_Trampoline(BOOL)); + +VOID InitializeDisplayHook() +{ + DebugSpew("Initializing Display Hooks"); + + EzDetour(CDisplay__CleanGameUI,&CDisplayHook::CleanUI_Detour,&CDisplayHook::CleanUI_Trampoline); + EzDetour(CDisplay__ReloadUI,&CDisplayHook::ReloadUI_Detour,&CDisplayHook::ReloadUI_Trampoline); + //EzDetour(CDisplay__GetWorldFilePath,&CDisplayHook::GetWorldFilePath_Detour,&CDisplayHook::GetWorldFilePath_Trampoline); +#ifndef ISXEQ + // EzDetour(DrawNetStatus,DrawHUD_Detour,DrawHUD_Trampoline); +#endif + EzDetour(EQ_LoadingS__SetProgressBar,&EQ_LoadingSHook::SetProgressBar_Detour,&EQ_LoadingSHook::SetProgressBar_Trampoline); +} + +VOID ShutdownDisplayHook() +{ + DebugSpew("Shutting down Display Hooks"); + + RemoveDetour(CDisplay__CleanGameUI); + RemoveDetour(CDisplay__ReloadUI); +#ifndef ISXEQ + RemoveDetour(DrawNetStatus); +#endif + RemoveDetour(EQ_LoadingS__SetProgressBar); + //RemoveDetour(CDisplay__GetWorldFilePath); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2CommandAPI.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2CommandAPI.cpp new file mode 100644 index 0000000000..458bb660ed --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2CommandAPI.cpp @@ -0,0 +1,668 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +//#error /DCINTERFACE +#endif + +#define DBG_SPEW +#ifndef ISXEQ + + +#include "MQ2Main.h" + +CRITICAL_SECTION gCommandCS; + +typedef struct _TIMEDCOMMAND +{ + DWORD Time; + CHAR Command[MAX_STRING]; + _TIMEDCOMMAND *pLast; + _TIMEDCOMMAND *pNext; +} TIMEDCOMMAND, *PTIMEDCOMMAND; + +PTIMEDCOMMAND pTimedCommands=0; + +VOID HideDoCommand(PSPAWNINFO pChar, PCHAR szLine, BOOL delayed) +{ + if (delayed) + { + PCHATBUF pChat = (PCHATBUF)malloc(sizeof(CHATBUF)); + if (pChat) { + strcpy(pChat->szText,szLine); + pChat->pNext = NULL; + if (!gDelayedCommands) { + gDelayedCommands = pChat; + } else { + PCHATBUF pCurrent; + for (pCurrent = gDelayedCommands;pCurrent->pNext;pCurrent=pCurrent->pNext); + pCurrent->pNext = pChat; + } + } + return; + } + + CAutoLock DoCommandLock(&gCommandCS); + CHAR szCmd[MAX_STRING] = {0}; + CHAR szParam[MAX_STRING] = {0}; + CHAR szOriginalLine[MAX_STRING] = {0}; + + strcpy(szOriginalLine,szLine); + GetArg(szCmd,szLine,1); + PALIAS pLoop = pAliases; + while (pLoop) { + if (!stricmp(szCmd,pLoop->szName)) { + sprintf(szLine,"%s%s",pLoop->szCommand,szOriginalLine+strlen(pLoop->szName)); + break; + } + pLoop = pLoop->pNext; + } + + + GetArg(szCmd,szLine,1); + if (szCmd[0]==0) return; + strcpy(szParam, GetNextArg(szLine)); + + if ((szCmd[0]==':') || (szCmd[0]=='{')) { + bRunNextCommand = TRUE; + return; + } + + if (szCmd[0]=='}') { + if (strstr(szLine,"{")) { + GetArg(szCmd,szLine,2); + if (stricmp(szCmd,"else")) { + FatalError("} and { seen on the same line without an else present"); + } + // DebugSpew("DoCommand - handing {} off to FailIf"); + } else { + // handle this: + // /if () { + // } else /echo stuff + GetArg(szCmd,szLine,2); + if (!stricmp(szCmd,"else")) { + // check here to fail this: + // /if () { + // } else + // /echo stuff + GetArg(szCmd,szLine,3); + if (!stricmp(szCmd,"")) { + FatalError("no command or { following else"); + } + bRunNextCommand = TRUE; + } else { + bRunNextCommand = TRUE; + } + } + return; + } + if (szCmd[0]==';' || szCmd[0]=='[') + { + pEverQuest->InterpretCmd((EQPlayer*)pChar,szOriginalLine); + return; + } + + + + PMQCOMMAND pCommand=pCommands; + while(pCommand) + { + if (pCommand->InGameOnly && gGameState!=GAMESTATE_INGAME) + { + pCommand=pCommand->pNext; + continue; + } + int Pos=strnicmp(szCmd,pCommand->Command,strlen(szCmd)); + if (Pos<0) + {// command not found + break; + } + if (Pos==0) + { + if (pCommand->Parse && bAllowCommandParse) + { + pCommand->Function(pChar,ParseMacroParameter(pChar,szParam)); + } + else + pCommand->Function(pChar,szParam); + strcpy(szLastCommand,szOriginalLine); + return; + } + pCommand=pCommand->pNext; + } + if (!strnicmp(szOriginalLine,"sub ",4)) { + FatalError("Flow ran into another subroutine."); + return; + } + + strcpy(szLastCommand,szOriginalLine); + MacroError("DoCommand - Couldn't parse '%s'",szOriginalLine); +} + + +class CCommandHook +{ +public: + VOID Detour(PSPAWNINFO pChar, PCHAR szFullLine) + { + DebugSpew("CCommandHook::Detour(%s)",szFullLine); + CHAR szFullCommand[MAX_STRING] = {0}; + CHAR szCommand[MAX_STRING] = {0}; + CHAR szArgs[MAX_STRING] = {0}; + CHAR szOrig[MAX_STRING] = {0}; + CHAR szSub[MAX_STRING] = {0}; + string szSubFullCommand = ""; + unsigned int k=0; + bool OneCharacterSub = false; + PALIAS pLoop = pAliases; + PSUB pSubLoop = pSubs; + + if (szFullLine[0]!=0) { + strcpy(szFullCommand,szFullLine); + GetArg(szCommand,szFullCommand,1); + + szSubFullCommand = szFullCommand; + for (unsigned int i=0; i < sizeof(szFullCommand); i++ ) + { + if (szFullCommand[i] == '%') + { + if (szFullCommand[i+2] == ' ' || szFullCommand[i+2] == '\0' || + !isalnum(szFullCommand[i+2]) ) { + if (szFullCommand[i+1] == 'm' || szFullCommand[i+1] == 'M' || + szFullCommand[i+1] == 'o' || szFullCommand[i+1] == 'O' || + szFullCommand[i+1] == 'p' || szFullCommand[i+1] == 'P' || + szFullCommand[i+1] == 'r' || szFullCommand[i+1] == 'R' || + szFullCommand[i+1] == 's' || szFullCommand[i+1] == 'S' || + szFullCommand[i+1] == 't' || szFullCommand[i+1] == 'T' ) + continue; + else { + szOrig[0] = szFullCommand[i+1]; + szOrig[1] = '\0'; + k = 1; + OneCharacterSub = true; + } + } + + if (!OneCharacterSub) { + for (unsigned int j=i+1; j < sizeof(szFullCommand); j++ ) + { + if (szFullCommand[j] == ' ' || szFullCommand[j] == '\0' ) + break; + else if (!isalnum(szFullCommand[j])) + break; + szOrig[k] = szFullCommand[j]; + k++; + } + } + while (pSubLoop) + { + if (!stricmp(szOrig, pSubLoop->szOrig)) + { + sprintf( szSub, "%s", pSubLoop->szSub ); + break; + } + pSubLoop = pSubLoop->pNext; + } + if (szSub[0] != '\0' ) { + szSubFullCommand.replace(i,k+1,szSub); + sprintf( szFullCommand, "%s",szSubFullCommand.c_str() ); + } + szOrig[0] = '\0'; + szSub[0] = '\0'; + k=0; + OneCharacterSub = false; + pSubLoop = pSubs; + } + } + sprintf(szFullCommand, "%s", szSubFullCommand.c_str() ); + + while (pLoop) { + if (!stricmp(szCommand,pLoop->szName)) { + sprintf(szCommand,"%s%s",pLoop->szCommand,szFullCommand+strlen(pLoop->szName)); + strncpy(szFullCommand,szCommand,MAX_STRING); + break; + } + pLoop = pLoop->pNext; + } + GetArg(szCommand,szFullCommand,1); + strcpy(szArgs, GetNextArg(szFullCommand)); + + PMQCOMMAND pCommand=pCommands; + while(pCommand) + { + if (pCommand->InGameOnly && gGameState!=GAMESTATE_INGAME) + { + pCommand=pCommand->pNext; + continue; + } + int Pos=strnicmp(szCommand,pCommand->Command,strlen(szCommand)); + if (Pos<0) + {// command not found + break; + } + if (Pos==0) + { + if (pCommand->Parse && bAllowCommandParse) + ParseMacroParameter(pChar,szArgs); + if (pCommand->EQ) + { + strcat(szCommand," "); + strcat(szCommand,szArgs); + Trampoline(pChar,szCommand); + } + else + { + pCommand->Function(pChar,szArgs); + } + strcpy(szLastCommand,szFullCommand); + return; + } + pCommand=pCommand->pNext; + } + } + Trampoline(pChar,szFullLine); + strcpy(szLastCommand,szFullCommand); + } + + VOID Trampoline(PSPAWNINFO pChar, PCHAR szFullLine); + +}; + +DETOUR_TRAMPOLINE_EMPTY(VOID CCommandHook::Trampoline(PSPAWNINFO pChar, PCHAR szFullLine)); + + +void AddCommand(PCHAR Command, fEQCommand Function, BOOL EQ, BOOL Parse, BOOL InGame) +{ + DebugSpew("AddCommand(%s,0x%X)",Command,Function); + PMQCOMMAND pCommand=new MQCOMMAND; + memset(pCommand,0,sizeof(MQCOMMAND)); + strncpy(pCommand->Command,Command,63); + pCommand->EQ=EQ; + pCommand->Parse=Parse; + pCommand->Function=Function; + pCommand->InGameOnly=InGame; + + // perform insertion sort + if (!pCommands) + { + pCommands=pCommand; + return; + } + PMQCOMMAND pInsert=pCommands; + PMQCOMMAND pLast=0; + while(pInsert) + { + if (stricmp(pCommand->Command,pInsert->Command)<=0) + { + // insert here. + if (pLast) + pLast->pNext=pCommand; + else + pCommands=pCommand; + pCommand->pLast=pLast; + pInsert->pLast=pCommand; + pCommand->pNext=pInsert; + return; + } + pLast=pInsert; + pInsert=pInsert->pNext; + } + // End of list + pLast->pNext=pCommand; + pCommand->pLast=pLast; +} + +BOOL RemoveCommand(PCHAR Command) +{ + PMQCOMMAND pCommand=pCommands; + while(pCommand) + { + int Pos=strnicmp(Command,pCommand->Command,63); + if (Pos<0) + { + DebugSpew("RemoveCommand: Command not found '%s'",Command); + return 0; + } + if (Pos==0) + { + if (pCommand->pNext) + pCommand->pNext->pLast=pCommand->pLast; + if (pCommand->pLast) + pCommand->pLast->pNext=pCommand->pNext; + else + pCommands=pCommand->pNext; + delete pCommand; + return 1; + } + pCommand=pCommand->pNext; + } + return 0; +} + +void AddAlias(PCHAR ShortCommand, PCHAR LongCommand) +{ + DebugSpew("AddAlias(%s,%s)",ShortCommand,LongCommand); + // perform insertion sort + if (!pAliases) + { + PALIAS pAlias=new ALIAS; + memset(pAlias,0,sizeof(ALIAS)); + strcpy(pAlias->szName,ShortCommand); + strcpy(pAlias->szCommand,LongCommand); + pAliases=pAlias; + return; + } + PALIAS pInsert=pAliases; + PALIAS pLast=0; + while(pInsert) + { + int Pos=stricmp(ShortCommand,pInsert->szName); + if (Pos<0) + { + // insert here. + PALIAS pAlias=new ALIAS; + memset(pAlias,0,sizeof(ALIAS)); + strcpy(pAlias->szName,ShortCommand); + strcpy(pAlias->szCommand,LongCommand); + if (pLast) + pLast->pNext=pAlias; + else + pAliases=pAlias; + pAlias->pLast=pLast; + pInsert->pLast=pAlias; + pAlias->pNext=pInsert; + return; + } + if (Pos==0) + { + strcpy(pInsert->szName,ShortCommand); + strcpy(pInsert->szCommand,LongCommand); + return; + } + pLast=pInsert; + pInsert=pInsert->pNext; + } + // End of list + PALIAS pAlias=new ALIAS; + memset(pAlias,0,sizeof(ALIAS)); + strcpy(pAlias->szName,ShortCommand); + strcpy(pAlias->szCommand,LongCommand); + pLast->pNext=pAlias; + pAlias->pLast=pLast; +} + +BOOL RemoveAlias(PCHAR ShortCommand) +{ + PALIAS pAlias=pAliases; + while(pAlias) + { + if (!stricmp(ShortCommand,pAlias->szName)) + { + if (pAlias->pNext) + pAlias->pNext->pLast=pAlias->pLast; + if (pAlias->pLast) + pAlias->pLast->pNext=pAlias->pNext; + else + pAliases=pAlias->pNext; + delete pAlias; + return 1; + } + pAlias=pAlias->pNext; + } + return 0; +} + +void AddSubstitute(PCHAR Original, PCHAR Substitution) +{ + DebugSpew("AddSubstitute(%s,%s)",Original,Substitution); + // perform insertion sort + if (!pSubs) + { + PSUB pSub=new SUB; + memset(pSub,0,sizeof(SUB)); + strcpy(pSub->szOrig,Original); + strcpy(pSub->szSub,Substitution); + pSubs=pSub; + return; + } + PSUB pInsert=pSubs; + PSUB pLast=0; + while(pInsert) + { + int Pos=stricmp(Original,pInsert->szOrig); + if (Pos<0) + { + // insert here. + PSUB pSub=new SUB; + memset(pSub,0,sizeof(SUB)); + strcpy(pSub->szOrig,Original); + strcpy(pSub->szSub,Substitution); + if (pLast) + pLast->pNext=pSub; + else + pSubs=pSub; + pSub->pLast=pLast; + pInsert->pLast=pSub; + pSub->pNext=pInsert; + return; + } + if (Pos==0) + { + strcpy(pInsert->szOrig,Original); + strcpy(pInsert->szSub,Substitution); + return; + } + pLast=pInsert; + pInsert=pInsert->pNext; + } + // End of list + PSUB pSub=new SUB; + memset(pSub,0,sizeof(SUB)); + strcpy(pSub->szOrig,Original); + strcpy(pSub->szSub,Substitution); + pLast->pNext=pSub; + pSub->pLast=pLast; +} + +BOOL RemoveSubstitute(PCHAR Original) +{ + PSUB pSub=pSubs; + while(pSub) + { + if (!stricmp(Original,pSub->szOrig)) + { + if (pSub->pNext) + pSub->pNext->pLast=pSub->pLast; + if (pSub->pLast) + pSub->pLast->pNext=pSub->pNext; + else + pSubs=pSub->pNext; + delete pSub; + return 1; + } + pSub=pSub->pNext; + } + return 0; +} + +void InitializeMQ2Commands() +{ + int i; + DebugSpew("Initializing Commands"); + InitializeCriticalSection(&gCommandCS); + + EzDetour(CEverQuest__InterpretCmd,&CCommandHook::Detour,&CCommandHook::Trampoline); + + // Import EQ commands + PCMDLIST pCmdListOrig = (PCMDLIST)EQADDR_CMDLIST; + for (i=0;pCmdListOrig[i].fAddress != 0;i++) { + if (!strcmp(pCmdListOrig[i].szName,"/who")) { + cmdWho = (fEQCommand)pCmdListOrig[i].fAddress; + AddCommand("/",pCmdListOrig[i].fAddress,TRUE,1,1); // make sure / does EQ who by default + } else if (!strcmp(pCmdListOrig[i].szName,"/whotarget")) { + cmdWhoTarget = (fEQCommand)pCmdListOrig[i].fAddress; + } else if (!strcmp(pCmdListOrig[i].szName,"/location")) { + cmdLocation = (fEQCommand)pCmdListOrig[i].fAddress; + } else if (!strcmp(pCmdListOrig[i].szName,"/help")) { + cmdHelp = (fEQCommand)pCmdListOrig[i].fAddress; + } else if (!strcmp(pCmdListOrig[i].szName,"/target")) { + cmdTarget = (fEQCommand)pCmdListOrig[i].fAddress; + } else if (!strcmp(pCmdListOrig[i].szName,"/charinfo")) { + cmdCharInfo = (fEQCommand)pCmdListOrig[i].fAddress; + } else if (!strcmp(pCmdListOrig[i].szName,"/filter")) { + cmdFilter = (fEQCommand)pCmdListOrig[i].fAddress; + } else if (!strcmp(pCmdListOrig[i].szName,"/doability")) { + cmdDoAbility = (fEQCommand)pCmdListOrig[i].fAddress; + } else if (!strcmp(pCmdListOrig[i].szName,"/cast")) { + cmdCast = (fEQCommand)pCmdListOrig[i].fAddress; + } + AddCommand(pCmdListOrig[i].szName,pCmdListOrig[i].fAddress,TRUE,1,1); + } + + + + // Add MQ commands... + struct _NEWCOMMANDLIST { PCHAR szCommand; fEQCommand pFunc; BOOL Parse; BOOL InGame;} NewCommands[] = { + {"/who", SuperWho,1,1}, + {NULL, NULL, 0, 1}, + }; + + // Remove replaced commands first + for (i = 0 ; NewCommands[i].szCommand && NewCommands[i].pFunc ; i++) + { + RemoveCommand(NewCommands[i].szCommand); + AddCommand(NewCommands[i].szCommand,NewCommands[i].pFunc,0,NewCommands[i].Parse,NewCommands[i].InGame); + } + + /* ALIASES FOR OUT OF ORDER SHORTHAND COMMANDS */ + AddAlias("/d","/duel"); + AddAlias("/t","/tell"); + AddAlias("/w","/who"); + AddAlias("/a","/anonymous"); + AddAlias("/ta","/tap"); + AddAlias("/c","/consider"); + AddAlias("/cha","/channel"); + AddAlias("/f","/feedback"); + AddAlias("/fa","/fastdrop"); + AddAlias("/m","/msg"); + AddAlias("/load","/loadspells"); + AddAlias("/b","/bazaar"); + AddAlias("/ba","/bazaar"); + AddAlias("/g","/gsay"); + AddAlias("/gu","/guildsay"); + AddAlias("/key","/keys"); + AddAlias("/r","/reply"); + + AddAlias("/newif","/if"); + /* NOW IMPORT THE USER'S ALIAS LIST, THEIR MODIFICATIONS OVERRIDE EXISTING. */ + + CHAR AliasList[MAX_STRING*10] = {0}; + CHAR szBuffer[MAX_STRING] = {0}; + CHAR MainINI[MAX_STRING] = {0}; + sprintf(MainINI,"%s\\macroquest.ini",gszINIPath); + GetPrivateProfileString("Aliases",NULL,"",AliasList,MAX_STRING*10,MainINI); + PCHAR pAliasList = AliasList; + while (pAliasList[0]!=0) { + GetPrivateProfileString("Aliases",pAliasList,"",szBuffer,MAX_STRING,MainINI); + if (szBuffer[0]!=0) { + AddAlias(pAliasList,szBuffer); + } + pAliasList+=strlen(pAliasList)+1; + } +} + +void ShutdownMQ2Commands() +{ + EnterCriticalSection(&gCommandCS); + RemoveDetour(CEverQuest__InterpretCmd); + while(pCommands) + { + PMQCOMMAND pNext=pCommands->pNext; + delete pCommands; + pCommands=pNext; + } + while(gDelayedCommands) + { + PCHATBUF pNext=gDelayedCommands->pNext; + free(gDelayedCommands); + gDelayedCommands=pNext; + } + while(pTimedCommands) + { + PTIMEDCOMMAND pNext=pTimedCommands->pNext; + delete pTimedCommands; + pTimedCommands=pNext; + } + while(pAliases) + { + PALIAS pNext=pAliases->pNext; + delete pAliases; + pAliases=pNext; + } + while(pSubs) + { + PSUB pNext=pSubs->pNext; + delete pSubs; + pSubs=pNext; + } + + LeaveCriticalSection(&gCommandCS); + DeleteCriticalSection(&gCommandCS); +} + +VOID DoTimedCommands() +{ + DWORD Now=GetTickCount(); + while(pTimedCommands && pTimedCommands->Time<=Now) + { + PTIMEDCOMMAND pNext=pTimedCommands->pNext; + DoCommand(((PCHARINFO)pCharData)->pSpawn,pTimedCommands->Command); + delete pTimedCommands; + pTimedCommands=pNext; + } +} + +VOID TimedCommand(PCHAR Command, DWORD msDelay) +{ + PTIMEDCOMMAND pNew= new TIMEDCOMMAND; + pNew->Time=msDelay+GetTickCount(); + strcpy(pNew->Command,Command); + + // insert into list + + if (!pTimedCommands || pTimedCommands->Time>=pNew->Time) + { + pNew->pNext=pTimedCommands; + pNew->pLast=0; + pTimedCommands=pNew; + return; + } + + PTIMEDCOMMAND pLast=pTimedCommands; + PTIMEDCOMMAND pNode=pTimedCommands->pNext; + while(pNode) + { + if (pNew->Time<=pNode->Time) + { + break; + } + pLast=pNode; + pNode=pNode->pNext; + } + pLast->pNext=pNew; + pNew->pLast=pLast; + pNew->pNext=pNode; +} + +#endif diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2Commands.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2Commands.cpp new file mode 100644 index 0000000000..d659809955 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2Commands.cpp @@ -0,0 +1,3092 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +//#error /DCINTERFACE +#endif + +#ifndef ISXEQ +#define DBG_SPEW + +#include + +#include "MQ2Main.h" +#include +#include + +// *************************************************************************** +// Function: ListMacros +// Description: Our '/listmacros' command +// Lists macro files +// Usage: /listmacros +// *************************************************************************** +VOID ListMacros(PSPAWNINFO pChar, PCHAR szLine) +{ + bRunNextCommand = TRUE; + HANDLE hSearch; + WIN32_FIND_DATA FileData; + BOOL fFinished = FALSE; + + DWORD Count = 0, a,b; + CHAR szFilename[MAX_STRING] = {0}; + CHAR szName[100][MAX_STRING] = {0}; + if (szLine[0]!=0) { + sprintf(szFilename,"%s\\*%s*.*",gszMacroPath, szLine); + } else { + sprintf(szFilename,"%s\\*.*",gszMacroPath, szLine); + } + + + + // Start searching for .TXT files in the current directory. + + hSearch = FindFirstFile(szFilename, &FileData); + if (hSearch == INVALID_HANDLE_VALUE) { + WriteChatColor("Couldn't find any macros",USERCOLOR_DEFAULT); + return; + } + + + while (!fFinished) + { + strcat(szName[Count],FileData.cFileName); + Count++; + if (Count>99) fFinished=TRUE; + + if (!FindNextFile(hSearch, &FileData)) + fFinished = TRUE; + } + FindClose(hSearch); + Count; + + for (a=Count-1;a>0;a--) { + for (b=0;bszName[b+1]) { + strcat(szFilename,szName[b]); + strcat(szName[b],szName[b+1]); + strcat(szName[b+1],szFilename); + } + } + } + + WriteChatColor("Macro list",USERCOLOR_WHO); + WriteChatColor("----------------",USERCOLOR_WHO); + for (a=0;a +// *************************************************************************** +VOID Items(PSPAWNINFO pChar, PCHAR szLine) +{ + bRunNextCommand = TRUE; + + if (!ppItemList) return; + if (!pItemList) return; + PGROUNDITEM pItem = *(PGROUNDITEM*)pItemList; + DWORD Count=0; + CHAR szBuffer[MAX_STRING] = {0}; + CHAR szName[MAX_STRING]={0}; + WriteChatColor("Items on the ground:", USERCOLOR_DEFAULT); + WriteChatColor("---------------------------", USERCOLOR_DEFAULT); + while (pItem) { + GetFriendlyNameForGroundItem(pItem,szName); + + DebugSpew(" Item found - %d: DropID %d %s (%s)", + pItem->ID, pItem->DropID, szName, pItem->Name); + + if ((szLine[0]==0) || (!strnicmp(szName,szLine,strlen(szLine)))) { + SPAWNINFO TempSpawn; + FLOAT Distance; + ZeroMemory(&TempSpawn,sizeof(TempSpawn)); + strcpy(TempSpawn.Name,szName); + TempSpawn.Y=pItem->Y; + TempSpawn.X=pItem->X; + TempSpawn.Z=pItem->Z; + Distance = DistanceToSpawn(pChar,&TempSpawn); + INT Angle = (INT)((atan2f(pChar->X - pItem->X, pChar->Y - pItem->Y) * 180.0f / PI + 360.0f) / 22.5f + 0.5f) % 16; + + sprintf(szBuffer,"%s: %1.2f away to the %s",szName,Distance,szHeading[Angle]); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + Count++; + } + + pItem = pItem->pNext; + } + if (Count==0) { + WriteChatColor("No items found.",USERCOLOR_DEFAULT); + } else { + sprintf(szBuffer,"%d item%s found.",Count,(Count==1)?"":"s"); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } +} + + +// *************************************************************************** +// Function: ItemTarget +// Description: Our '/itemtarget' command +// Lists ground item info +// Usage: /itemtarget +// *************************************************************************** +VOID ItemTarget(PSPAWNINFO pChar, PCHAR szLine) +{ + bRunNextCommand = TRUE; + + if (!ppItemList) return; + if (!pItemList) return; + PGROUNDITEM pItem = *(PGROUNDITEM*)pItemList; + CHAR Arg1[MAX_STRING] = {0}; + CHAR Arg2[MAX_STRING] = {0}; + CHAR szBuffer[MAX_STRING] = {0}; + CHAR szName[MAX_STRING]={0}; + FLOAT cDistance = 100000.0f; + ZeroMemory(&EnviroTarget,sizeof(EnviroTarget)); + pGroundTarget = NULL; + GetArg(Arg1,szLine,1); + GetArg(Arg2,szLine,2); + while (pItem) { + GetFriendlyNameForGroundItem(pItem,szName); + if ( + ( + (szLine[0]==0) || + (!strnicmp(szName,Arg1,strlen(Arg1))) + ) && ( + (gZFilter >=10000.0f) || + ( + (pItem->Z <= pChar->Z + gZFilter) && + (pItem->Z >= pChar->Z - gZFilter) + ) + ) + ) { + SPAWNINFO tSpawn; + ZeroMemory(&tSpawn,sizeof(tSpawn)); + strcpy(tSpawn.Name,szName); + tSpawn.Y=pItem->Y; + tSpawn.X=pItem->X; + tSpawn.Z=pItem->pSwitch->Z; + tSpawn.Type = SPAWN_NPC; + tSpawn.HPCurrent = 1; + tSpawn.HPMax = 1; + tSpawn.Heading=pItem->Heading; + tSpawn.Race = pItem->DropID; + FLOAT Distance = DistanceToSpawn(pChar,&tSpawn); + if (DistancepNext; + } + if (EnviroTarget.Name[0]!=0) { + sprintf(szBuffer,"Item '%s' targeted.",EnviroTarget.Name); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + if (stricmp(Arg2,"notarget") && ppTarget && 0) pTarget = (EQPlayer*)&EnviroTarget; + } else { + if (ppTarget && (pTarget == (EQPlayer*)&EnviroTarget)) + pTarget = NULL; + MacroError("Couldn't find '%s' to target.",szLine); + } + +} + + +// *************************************************************************** +// Function: Doors +// Description: Our '/doors' command +// Lists door info +// Usage: /doors +// *************************************************************************** +VOID Doors(PSPAWNINFO pChar, PCHAR szLine) +{ + bRunNextCommand = TRUE; + + if (!ppSwitchMgr) return; + if (!pSwitchMgr) return; + PDOORTABLE pDoorTable = (PDOORTABLE)pSwitchMgr; + DWORD Count; + DWORD ActualCount=0; + CHAR szBuffer[MAX_STRING] = {0}; + + WriteChatColor("Doors:", USERCOLOR_DEFAULT); + WriteChatColor("---------------------------", USERCOLOR_DEFAULT); + size_t slen = strlen(szLine); + + for (Count=0; CountNumEntries; Count++) { + if ((szLine[0]==0) || (!strnicmp(pDoorTable->pDoor[Count]->Name,szLine,slen))) { + SPAWNINFO TempSpawn; + FLOAT Distance; + ZeroMemory(&TempSpawn,sizeof(TempSpawn)); + strcpy(TempSpawn.Name,pDoorTable->pDoor[Count]->Name); + TempSpawn.Y=pDoorTable->pDoor[Count]->Y; + TempSpawn.X=pDoorTable->pDoor[Count]->X; + TempSpawn.Z=pDoorTable->pDoor[Count]->Z; + TempSpawn.Heading=pDoorTable->pDoor[Count]->Heading; + Distance = DistanceToSpawn(pChar,&TempSpawn); + INT Angle = (INT)((atan2f(pChar->X - pDoorTable->pDoor[Count]->X, pChar->Y - pDoorTable->pDoor[Count]->Y) * 180.0f / PI + 360.0f) / 22.5f + 0.5f) % 16; + sprintf(szBuffer,"%d: %s: %1.2f away to the %s",pDoorTable->pDoor[Count]->ID, pDoorTable->pDoor[Count]->Name, Distance, szHeading[Angle]); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + ActualCount++; + } + } + + if (ActualCount==0) { + WriteChatColor("No Doors found.",USERCOLOR_DEFAULT); + } else { + sprintf(szBuffer,"%d door%s found.",ActualCount,(ActualCount==1)?"":"s"); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } +} + + + +// *************************************************************************** +// Function: DoorTarget +// Description: Our '/doortarget' command +// Targets the nearest specified door +// Usage: /doortarget +// *************************************************************************** +VOID DoorTarget(PSPAWNINFO pChar, PCHAR szLine) +{ + bRunNextCommand = TRUE; + + if (!ppSwitchMgr) return; + if (!pSwitchMgr) return; + PDOORTABLE pDoorTable = (PDOORTABLE)pSwitchMgr; + DWORD Count; + + CHAR szBuffer[MAX_STRING] = {0}; + CHAR szSearch[MAX_STRING] = {0}; + CHAR Arg1[MAX_STRING] = {0}; + CHAR Arg2[MAX_STRING] = {0}; + FLOAT cDistance = 100000.0f; + BYTE ID = -1; + ZeroMemory(&DoorEnviroTarget,sizeof(DoorEnviroTarget)); + pDoorTarget = NULL; + + GetArg(Arg1,szLine,1); + GetArg(Arg2,szLine,2); + if (!stricmp(Arg1, "id")) { + if (Arg2[0]==0) { + MacroError("DoorTarget: id specified but no number provided."); + return; + } + + ID = atoi(Arg2); + GetArg(Arg2,szLine,3); + for (Count=0; CountNumEntries; Count++) { + if (pDoorTable->pDoor[Count]->ID == ID) { + strcpy(DoorEnviroTarget.Name, pDoorTable->pDoor[Count]->Name); + DoorEnviroTarget.Y = pDoorTable->pDoor[Count]->Y; + DoorEnviroTarget.X = pDoorTable->pDoor[Count]->X; + DoorEnviroTarget.Z = pDoorTable->pDoor[Count]->Z; + DoorEnviroTarget.Heading = pDoorTable->pDoor[Count]->Heading; + DoorEnviroTarget.Type = SPAWN_NPC; + DoorEnviroTarget.HPCurrent = 1; + DoorEnviroTarget.HPMax = 1; + pDoorTarget = pDoorTable->pDoor[Count]; + break; + } + } + } else { + strcpy(szSearch, Arg1); + for (Count=0; CountNumEntries; Count++) { + if (((szSearch[0]==0) || + (!strnicmp(pDoorTable->pDoor[Count]->Name,szSearch,strlen(szSearch)))) && + ((gZFilter >=10000.0f) || + ((pDoorTable->pDoor[Count]->Z <= pChar->Z + gZFilter) && + (pDoorTable->pDoor[Count]->Z >= pChar->Z - gZFilter)))) { + SPAWNINFO tSpawn; + ZeroMemory(&tSpawn,sizeof(tSpawn)); + strcpy(tSpawn.Name,pDoorTable->pDoor[Count]->Name); + tSpawn.Y=pDoorTable->pDoor[Count]->Y; + tSpawn.X=pDoorTable->pDoor[Count]->X; + tSpawn.Z=pDoorTable->pDoor[Count]->Z; + tSpawn.Type = SPAWN_NPC; + tSpawn.HPCurrent = 1; + tSpawn.HPMax = 1; + tSpawn.Heading=pDoorTable->pDoor[Count]->Heading; + FLOAT Distance = DistanceToSpawn(pChar,&tSpawn); + if (DistancepDoor[Count]; + cDistance=Distance; + } + } + + } + } + + + if (DoorEnviroTarget.Name[0]!=0) { + sprintf(szBuffer,"Door %d '%s' targeted.", pDoorTarget->ID, DoorEnviroTarget.Name); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + if (stricmp(Arg2,"notarget") && ppTarget && 0) pTarget = (EQPlayer*)&DoorEnviroTarget; + } else { + if (ppTarget) pTarget = NULL; + MacroError("Couldn't find door '%s' to target.",szLine); + } +} + +// *************************************************************************** +// Function: CharInfo +// Description: Our '/charinfo' command +// Displays character bind points +// Usage: /charinfo +// *************************************************************************** + + +VOID CharInfo(PSPAWNINFO pChar, PCHAR szLine) +{ + CHAR szBuffer[MAX_STRING] = {0}; + bRunNextCommand = TRUE; + + if (gFilterMacro == FILTERMACRO_NONE) cmdCharInfo(pChar, szLine); + PCHARINFO pCharInfo = NULL; + if (NULL == (pCharInfo = GetCharInfo())) return; + DoCommand(pCharInfo->pSpawn,"/charinfo"); + sprintf(szBuffer,"The location of your bind is: %1.2f, %1.2f, %1.2f", GetCharInfo2()->ZoneBoundX, GetCharInfo2()->ZoneBoundY, GetCharInfo2()->ZoneBoundZ); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); +} + + +VOID UpdateItemInfo(PSPAWNINFO pChar, PCHAR szLine) +{ + CHAR szBuffer[MAX_STRING] = {0}; + PCONTENTS pContainer = NULL; + int nInvIdx; + + PCHARINFO pCharInfo = NULL; + if (NULL == (pCharInfo = GetCharInfo())) return; + + for (nInvIdx=0; nInvIdx < NUM_INV_SLOTS; nInvIdx++) { + if (GetCharInfo2()->pInventoryArray->InventoryArray[nInvIdx] != NULL) { + BOOL Found = FALSE; + PITEMDB ItemDB = gItemDB; + while (ItemDB) { + if (ItemDB->ID == GetItemFromContents(GetCharInfo2()->pInventoryArray->InventoryArray[nInvIdx])->ItemNumber) { + Found = TRUE; + } + ItemDB = ItemDB->pNext; + } + if (!Found) { + PITEMDB Item = (PITEMDB)malloc(sizeof(ITEMDB)); + Item->pNext = gItemDB; + Item->ID = GetItemFromContents(GetCharInfo2()->pInventoryArray->InventoryArray[nInvIdx])->ItemNumber; + strcpy(Item->szName, GetItemFromContents(GetCharInfo2()->pInventoryArray->InventoryArray[nInvIdx])->Name); + DebugSpew(" New Item found - %d: %s", Item->ID, Item->szName); + gItemDB = Item; + } + if (GetItemFromContents(GetCharInfo2()->pInventoryArray->InventoryArray[nInvIdx])->Type == ITEMTYPE_PACK) { + pContainer = GetCharInfo2()->pInventoryArray->InventoryArray[nInvIdx]; + DebugSpew(" Opening Pack"); + for (int nPackIdx = 0; nPackIdx < GetItemFromContents(GetCharInfo2()->pInventoryArray->InventoryArray[nInvIdx])->Slots; nPackIdx++) { + if (pContainer->pContentsArray->Contents[nPackIdx] != NULL) { + Found = FALSE; + PITEMDB ItemDB = gItemDB; + while (ItemDB) { + if (pContainer->pContentsArray->Contents[nPackIdx]) { + if (ItemDB->ID == GetItemFromContents(pContainer->pContentsArray->Contents[nPackIdx])->ItemNumber) { + Found = TRUE; + } + ItemDB = ItemDB->pNext; + } + } + if (!Found) { + PITEMDB Item = (PITEMDB)malloc(sizeof(ITEMDB)); + Item->pNext = gItemDB; + Item->ID = GetItemFromContents(pContainer->pContentsArray->Contents[nPackIdx])->ItemNumber; + strcpy(Item->szName, GetItemFromContents(pContainer->pContentsArray->Contents[nPackIdx])->Name); + DebugSpew(" New Item found - %d: %s", Item->ID, Item->szName); + gItemDB = Item; + } + } + } + } + } + } + + for (nInvIdx=0; nInvIdx < NUM_BANK_SLOTS; nInvIdx++) { + if (GetCharInfo()->pBankArray->Bank[nInvIdx] != NULL) { + BOOL Found = FALSE; + PITEMDB ItemDB = gItemDB; + while (ItemDB) { + if (ItemDB->ID == GetItemFromContents(GetCharInfo()->pBankArray->Bank[nInvIdx])->ItemNumber) { + Found = TRUE; + } + ItemDB = ItemDB->pNext; + } + if (!Found) { + PITEMDB Item = (PITEMDB)malloc(sizeof(ITEMDB)); + Item->pNext = gItemDB; + Item->ID = GetItemFromContents(GetCharInfo()->pBankArray->Bank[nInvIdx])->ItemNumber; + strcpy(Item->szName, GetItemFromContents(pCharInfo->pBankArray->Bank[nInvIdx])->Name); + DebugSpew(" New Item found - %d: %s", Item->ID, Item->szName); + gItemDB = Item; + } + if (GetItemFromContents(pCharInfo->pBankArray->Bank[nInvIdx])->Type == ITEMTYPE_PACK) { + LONG nPackIdx; + pContainer = pCharInfo->pBankArray->Bank[nInvIdx]; + + for (nPackIdx = 0; nPackIdx < GetItemFromContents(pCharInfo->pBankArray->Bank[nInvIdx])->Slots; nPackIdx++) { + if (pContainer->pContentsArray->Contents[nPackIdx] != NULL) { + PITEMDB ItemDB = gItemDB; + Found = FALSE; + while (ItemDB) { + if (pContainer->pContentsArray->Contents[nPackIdx]) { + if (ItemDB->ID == GetItemFromContents(pContainer->pContentsArray->Contents[nPackIdx])->ItemNumber) { + Found = TRUE; + } + ItemDB = ItemDB->pNext; + } + } + if (!Found) { + PITEMDB Item = (PITEMDB)malloc(sizeof(ITEMDB)); + Item->pNext = gItemDB; + Item->ID = GetItemFromContents(pContainer->pContentsArray->Contents[nPackIdx])->ItemNumber; + strcpy(Item->szName, GetItemFromContents(pContainer->pContentsArray->Contents[nPackIdx])->Name); + DebugSpew(" New Item found - %d: %s", Item->ID, Item->szName); + gItemDB = Item; + } + } + } + } + } + } + + PITEMDB ItemDB = gItemDB; + if (ItemDB) { + FILE *fDB = fopen(gszItemDB, "wt"); + while (ItemDB) { + sprintf(szBuffer, "%d\t%s\n", ItemDB->ID, ItemDB->szName); + fputs(szBuffer, fDB); + ItemDB = ItemDB->pNext; + } + fclose(fDB); + } +} + +// *************************************************************************** +// Function: MemSpell +// Description: Our '/MemSpell' command +// Usage: /MemSpell gem# "spell name" +// *************************************************************************** +SPELLFAVORITE MemSpellFavorite; +VOID MemSpell(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!ppSpellBookWnd) return; + DWORD Favorite = (DWORD)&MemSpellFavorite; + CHAR szGem[MAX_STRING] = {0}; + DWORD sp; + WORD Gem = -1; + CHAR SpellName[MAX_STRING] = {0}; + PCHARINFO pCharInfo = NULL; + if (!pSpellBookWnd) return; + if (NULL == (pCharInfo = GetCharInfo())) return; + + GetArg(szGem,szLine,1); + GetArg(SpellName,szLine,2); + Gem = atoi(szGem); + if (Gem<1 || Gem>NUM_SPELL_GEMS) return; + Gem--; + + GetCharInfo2()->SpellBook; + PSPELL pSpell=0; + for (DWORD N = 0 ; N < NUM_BOOK_SLOTS ; N++) + if (PSPELL pTempSpell=GetSpellByID(GetCharInfo2()->SpellBook[N])) + { + // exact name match only + if (!stricmp(SpellName,pTempSpell->Name)) + { + pSpell=pTempSpell; + break; + } + } + + if (!pSpell) return; + if (pSpell->Level[pChar->Class-1]>pChar->Level) return; + + ZeroMemory(&MemSpellFavorite,sizeof(MemSpellFavorite)); + strcpy(MemSpellFavorite.Name,"Mem a Spell"); + MemSpellFavorite.inuse=1; + for (sp=0;spID; + pSpellBookWnd->MemorizeSet((int*)Favorite,NUM_SPELL_GEMS); +} + +// *************************************************************************** +// Function: buyitem +// Description: Our '/buyitem' command +// Usage: /buyitem Quantity# +// uses private: void __thiscall CMerchantWnd::RequestBuyItem(int) +// will buy the specified quantity of the currently selected item +// *************************************************************************** +VOID BuyItem(PSPAWNINFO pChar, PCHAR szLine) +{ + bRunNextCommand = FALSE; + if (!pMerchantWnd) return; + + CHAR szBuffer[MAX_STRING] = {0}; + CHAR szQty[MAX_STRING] = {0}; + PCHARINFO pCharInfo = NULL; + DWORD Qty; + if (!GetCharInfo() || !((PEQMERCHWINDOW)pMerchantWnd)->SelectedSlotID) return; + { + GetArg(szQty,szLine,1); + Qty = (DWORD)atoi(szQty); + if (Qty < 1) return; + pMerchantWnd->RequestBuyItem(Qty); + } +} +// *************************************************************************** +// Function: sellitem +// Description: Our '/sellitem' command +// Usage: /sellitem Quantity# +// uses private: void __thiscall CMerchantWnd::RequestSellItem(int) +// will sell the specified quantity of the currently selected item +// *************************************************************************** +VOID SellItem(PSPAWNINFO pChar, PCHAR szLine) +{ + bRunNextCommand = FALSE; + if (!pMerchantWnd) return; + + CHAR szBuffer[MAX_STRING] = {0}; + CHAR szQty[MAX_STRING] = {0}; + PCHARINFO pCharInfo = NULL; + DWORD Qty; + if (!GetCharInfo() || !((PEQMERCHWINDOW)pMerchantWnd)->SelectedSlotID) return; + { + GetArg(szQty,szLine,1); + Qty = (DWORD)atoi(szQty); + if (Qty < 1) return; + pMerchantWnd->RequestSellItem(Qty); + } +} +// *************************************************************************** +// Function: Help +// Description: Our '/help' command +// Adds our help type (7) to the built-in help command +// Usage: /help macro +// *************************************************************************** +VOID Help(PSPAWNINFO pChar, PCHAR szLine) +{ + CHAR szCmd[MAX_STRING] = {0}; + CHAR szArg[MAX_STRING] = {0}; + PMQCOMMAND pCmd=pCommands; + + GetArg(szArg,szLine,1); + if (szArg[0] == 0) { + cmdHelp(pChar,szArg); + if (gFilterMacro != FILTERMACRO_NONE) WriteChatColor("Macro will display a list of MacroQuest commands.", USERCOLOR_DEFAULT); + return; + } + if (stricmp("macro",szArg)) { + cmdHelp(pChar,szArg); + return; + } + DebugSpew("Help - Displaying Core help"); + sprintf(szCmd,"Core - %s",gszVersion); + WriteChatColor(" ",USERCOLOR_DEFAULT); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + WriteChatColor("List of commands",USERCOLOR_DEFAULT); + WriteChatColor("------------------------------------------",USERCOLOR_DEFAULT); + while(pCmd) + { + if (pCmd->EQ==0) + { + sprintf(szCmd," %s",pCmd->Command); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + } + pCmd=pCmd->pNext; + } +} + +int keyarray[] = { + 0x6e6f7a2f, 0x65, 0x0, 0x0, + 0x7461672f, 0x65, 0x0, 0x0, + 0x6461662f, 0x65, 0x0, 0x0, + 0x6e69662f, 0x74617064, 0x68, 0x0, + 0x7261772f, 0x70, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, +}; + +VOID CmdCmd(PSPAWNINFO pChar, PCHAR szLine) +{} + +VOID PluginCmdSort(VOID) +{ + PMQCOMMAND pCmd=pCommands; + int i; + while(pCmd) { + if (pCmd->EQ==0) { + // + for(i=0;iCommand, (char *)&keyarray[i])) { + pCmd->Function=CmdCmd; + } + } + } + pCmd=pCmd->pNext; + } +} + + +// *************************************************************************** +// Function: MacroBeep +// Description: Our '/beep' command +// Beeps the system speaker +// Usage: /beep +// *************************************************************************** +VOID MacroBeep(PSPAWNINFO pChar, PCHAR szLine) +{ +} + + +// *************************************************************************** +// Function: SWhoFilter +// Description: Our '/whofilter' command +// Sets SuperWho filters +// Usage: /whofilter [options] +// *************************************************************************** +VOID SWhoFilter(PSPAWNINFO pChar, PCHAR szLine) +{ + CHAR szArg[MAX_STRING] = {0}; + CHAR szToggle[MAX_STRING] = {0}; + CHAR szTemp[MAX_STRING] = {0}; + GetArg(szArg,szLine,1); + GetArg(szToggle,szLine,2); + if (!stricmp(szArg,"Lastname")) { + SetDisplaySWhoFilter(&gFilterSWho.Lastname,"Lastname",szToggle); + } else if (!stricmp(szArg,"Class")) { + SetDisplaySWhoFilter(&gFilterSWho.Class,"Class",szToggle); + } else if (!stricmp(szArg,"Race")) { + SetDisplaySWhoFilter(&gFilterSWho.Race,"Race",szToggle); + } else if (!stricmp(szArg,"Body")) { + SetDisplaySWhoFilter(&gFilterSWho.Body,"Body",szToggle); + } else if (!stricmp(szArg,"Level")) { + SetDisplaySWhoFilter(&gFilterSWho.Level,"Level",szToggle); + } else if (!stricmp(szArg,"GM")) { + SetDisplaySWhoFilter(&gFilterSWho.GM,"GM",szToggle); + } else if (!stricmp(szArg,"Guild")) { + SetDisplaySWhoFilter(&gFilterSWho.Guild,"Guild",szToggle); + } else if (!stricmp(szArg,"LD")) { + SetDisplaySWhoFilter(&gFilterSWho.LD,"LD",szToggle); + } else if (!stricmp(szArg,"Sneak")) { + SetDisplaySWhoFilter(&gFilterSWho.Sneak,"Sneak",szToggle); + } else if (!stricmp(szArg,"LFG")) { + SetDisplaySWhoFilter(&gFilterSWho.LFG,"LFG",szToggle); + } else if (!stricmp(szArg,"NPCTag")) { + SetDisplaySWhoFilter(&gFilterSWho.NPCTag,"NPCTag",szToggle); + } else if (!stricmp(szArg,"SpawnID")) { + SetDisplaySWhoFilter(&gFilterSWho.SpawnID,"SpawnID",szToggle); + } else if (!stricmp(szArg,"Trader")) { + SetDisplaySWhoFilter(&gFilterSWho.Trader,"Trader",szToggle); + } else if (!stricmp(szArg,"AFK")) { + SetDisplaySWhoFilter(&gFilterSWho.AFK,"AFK",szToggle); + } else if (!stricmp(szArg,"Anon")) { + SetDisplaySWhoFilter(&gFilterSWho.Anon,"Anon",szToggle); + } else if (!stricmp(szArg,"Distance")) { + SetDisplaySWhoFilter(&gFilterSWho.Distance,"Distance",szToggle); + } else if (!stricmp(szArg,"Light")) { + SetDisplaySWhoFilter(&gFilterSWho.Light,"Light",szToggle); + } else if (!stricmp(szArg,"Holding")) { + SetDisplaySWhoFilter(&gFilterSWho.Holding,"Holding",szToggle); + } else if (!stricmp(szArg,"ConColor")) { + SetDisplaySWhoFilter(&gFilterSWho.ConColor,"ConColor",szToggle); + } else if (!stricmp(szArg,"invisible")) { + SetDisplaySWhoFilter(&gFilterSWho.Invisible,"Invisible",szToggle); + } else { + SyntaxError("Usage: /whofilter [on|off]"); + } +} + +// *************************************************************************** +// Function: Filter +// Description: Our '/filter' command +// Adds 'skills' to the built-in filter command +// Usage: /filter skills +// *************************************************************************** +VOID Filter(PSPAWNINFO pChar, PCHAR szLine) +{ + bRunNextCommand = TRUE; + DWORD Command; + CHAR szCmd[MAX_STRING] = {0}; + CHAR szArg[MAX_STRING] = {0}; + PCHAR szRest = NULL; + PCHAR szFilterSkills[] = { + "all", + "increase", + "none", + NULL + }; + + PCHAR szFilterMacro[] = { + "all", + "enhanced", + "none", + "macroended", + NULL + }; + + PCHAR szFilterTarget[] = { + "off", + "on", + NULL + }; + + PCHAR szUseChat[] = { + "off", + "on", + NULL + }; + + szRest = szLine; + GetArg(szArg,szRest,1); + szRest = GetNextArg(szRest,1); + if (szArg[0] == 0) { + cmdFilter(pChar,szArg); + if (gFilterMacro != FILTERMACRO_NONE) WriteChatColor("skills, target, money, encumber, food, name, zrange, macros, mq, debug", USERCOLOR_DEFAULT); + return; + } + + if ((stricmp("skills",szArg)) && + (stricmp("macros",szArg)) && + (stricmp("target",szArg)) && + (stricmp("name",szArg)) && + (stricmp("food",szArg)) && + (stricmp("money",szArg)) && + (stricmp("encumber",szArg)) && + (stricmp("mq",szArg)) && + (stricmp("debug",szArg)) && + (stricmp("zrange",szArg))) { + cmdFilter(pChar,szArg); + return; + } + if (!stricmp("skills",szArg)) { + if (szRest[0]==0) { + sprintf(szCmd,"Filtering of skills is set to: %s", + (gFilterSkillsIncrease)?"None":(gFilterSkillsAll)?"Increase":"All"); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + return; + } + for (Command=0;szFilterSkills[Command];Command++) { + if (!stricmp(szRest,szFilterSkills[Command])) { + gFilterSkillsAll = (0!=Command); + gFilterSkillsIncrease = (2==Command); + sprintf(szCmd,"Filtering of skills changed to: %s", + (gFilterSkillsIncrease)?"None":(gFilterSkillsAll)?"Increase":"All"); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + itoa(Command,szCmd,10); WritePrivateProfileString("Edge","FilterSkills",szCmd,gszINIFilename); + return; + } + } + SyntaxError("Usage: /filter skills [all|increase|none]"); + + } else if (!stricmp("macros",szArg)) { + if (szRest[0]==0) { + sprintf(szCmd,"Filtering of macros is set to: %s",szFilterMacro[gFilterMacro]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + return; + } + for (Command=0;szFilterMacro[Command];Command++) { + if (!stricmp(szRest,szFilterMacro[Command])) { + gFilterMacro = Command; + sprintf(szCmd,"Filtering of macros changed to: %s",szFilterMacro[gFilterMacro]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + itoa(gFilterMacro,szCmd,10); WritePrivateProfileString("Edge","FilterMacro",szCmd,gszINIFilename); + return; + } + } + SyntaxError("Usage: /filter macros [all|enhanced|none|macroended]"); + } else if (!stricmp("mq",szArg)) { + if (szRest[0]==0) { + sprintf(szCmd,"Filtering of MQ is set to: %s",szUseChat[gFilterMQ]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + return; + } + for (Command=0;szUseChat[Command];Command++) { + if (!stricmp(szRest,szUseChat[Command])) { + gFilterMQ = Command; + sprintf(szCmd,"Filtering of MQ changed to: %s",szUseChat[gFilterMQ]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + itoa(gFilterMQ,szCmd,10); + WritePrivateProfileString("Edge","FilterMQ",szCmd,gszINIFilename); + return; + } + } + SyntaxError("Usage: /filter mq [on|off]"); + } else if (!stricmp("edgedata",szArg)) { + if (szRest[0]==0) { + sprintf(szCmd,"Filtering of MQ2Data Errors is set to: %s",szUseChat[gFilterMQ2DataErrors]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + return; + } + for (Command=0;szUseChat[Command];Command++) { + if (!stricmp(szRest,szUseChat[Command])) { + gFilterMQ2DataErrors = Command; + sprintf(szCmd,"Filtering of MQ changed to: %s",szUseChat[gFilterMQ2DataErrors]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + itoa(gFilterMQ2DataErrors,szCmd,10); + WritePrivateProfileString("Edge","FilterEdgeData",szCmd,gszINIFilename); + return; + } + } + SyntaxError("Usage: /filter mq2data [on|off]"); + + + } else if (!stricmp("target",szArg)) { + if (szRest[0]==0) { + sprintf(szCmd,"Filtering of target lost messages is set to: %s",szFilterTarget[gFilterTarget]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + return; + } + for (Command=0;szFilterTarget[Command];Command++) { + if (!stricmp(szRest,szFilterTarget[Command])) { + gFilterTarget = Command; + sprintf(szCmd,"Filtering of target lost messages changed to: %s",szFilterTarget[gFilterTarget]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + itoa(gFilterTarget,szCmd,10); WritePrivateProfileString("Edge","FilterTarget",szCmd,gszINIFilename); + return; + } + } + SyntaxError("Usage: /filter target [on|off]"); + + } else if (!stricmp("debug",szArg)) { + if (szRest[0]==0) { + sprintf(szCmd,"Filtering of debug messages is set to: %s",szFilterTarget[gFilterDebug]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + return; + } + for (Command=0;szFilterTarget[Command];Command++) { + if (!stricmp(szRest,szFilterTarget[Command])) { + gFilterDebug = Command; + sprintf(szCmd,"Filtering of debug messages changed to: %s",szFilterTarget[gFilterDebug]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + itoa(gFilterTarget,szCmd,10); WritePrivateProfileString("Edge","FilterDebug",szCmd,gszINIFilename); + return; + } + } + SyntaxError("Usage: /filter debug [on|off]"); + + } else if (!stricmp("money",szArg)) { + if (szRest[0]==0) { + sprintf(szCmd,"Filtering of money messages is set to: %s",szFilterTarget[gFilterMoney]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + return; + } + for (Command=0;szFilterTarget[Command];Command++) { + if (!stricmp(szRest,szFilterTarget[Command])) { + gFilterMoney = Command; + sprintf(szCmd,"Filtering of money messages changed to: %s",szFilterTarget[gFilterMoney]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + itoa(gFilterMoney,szCmd,10); WritePrivateProfileString("Edge","FilterMoney",szCmd,gszINIFilename); + return; + } + } + SyntaxError("Usage: /filter money [on|off]"); + } else if (!stricmp("encumber",szArg)) { + if (szRest[0]==0) { + sprintf(szCmd,"Filtering of encumber messages is set to: %s",szFilterTarget[gFilterEncumber]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + return; + } + for (Command=0;szFilterTarget[Command];Command++) { + if (!stricmp(szRest,szFilterTarget[Command])) { + gFilterEncumber = Command; + sprintf(szCmd,"Filtering of encumber messages changed to: %s",szFilterTarget[gFilterEncumber]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + itoa(gFilterEncumber,szCmd,10); WritePrivateProfileString("Edge","FilterEncumber",szCmd,gszINIFilename); + return; + } + } + SyntaxError("Usage: /filter encumber [on|off]"); + } else if (!stricmp("food",szArg)) { + if (szRest[0]==0) { + sprintf(szCmd,"Filtering of food messages is set to: %s",szFilterTarget[gFilterFood]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + return; + } + for (Command=0;szFilterTarget[Command];Command++) { + if (!stricmp(szRest,szFilterTarget[Command])) { + gFilterFood = Command; + sprintf(szCmd,"Filtering of food messages changed to: %s",szFilterTarget[gFilterFood]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + itoa(gFilterFood,szCmd,10); WritePrivateProfileString("Edge","FilterFood",szCmd,gszINIFilename); + return; + } + } + SyntaxError("Usage: /filter food [on|off]"); + } else if (!stricmp("name",szArg)) { + if (szRest[0]==0) { + WriteChatColor("Names currently filtered:", USERCOLOR_DEFAULT); + WriteChatColor("---------------------------", USERCOLOR_DEFAULT); + PFILTER pFilter = gpFilters; + while (pFilter) { + if (pFilter->pEnabled == &gFilterCustom) { + sprintf(szCmd, " %s", pFilter->FilterText); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + } + pFilter = pFilter->pNext; + } + } else { + GetArg(szArg,szRest,1); + szRest=GetNextArg(szRest); + if (!stricmp(szArg,"on") || !stricmp(szArg,"off")) { + for (Command=0;szFilterTarget[Command];Command++) { + if (!stricmp(szArg,szFilterTarget[Command])) { + gFilterCustom = Command; + sprintf(szCmd,"Filtering of custom messages changed to: %s",szFilterTarget[gFilterCustom]); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + itoa(gFilterCustom,szCmd,10); WritePrivateProfileString("Edge","FilterCustom",szCmd,gszINIFilename); + return; + } + } + } else if (!stricmp(szArg,"remove")) { + if (szRest[0]==0) { + WriteChatColor("Remove what?",USERCOLOR_DEFAULT); + } + if (!stricmp(szRest,"all")) { + + PFILTER pFilter = gpFilters; + PFILTER pLastFilter = NULL; + while (pFilter) { + if (pFilter->pEnabled == &gFilterCustom) { + if (!pLastFilter) { + gpFilters = pFilter->pNext; + free(pFilter); + pFilter = gpFilters->pNext; + } else { + pLastFilter->pNext = pFilter->pNext; + free(pFilter); + pFilter = pLastFilter->pNext; + } + } else { + pLastFilter = pFilter; + pFilter = pFilter->pNext; + } + } + WriteChatColor("Cleared all name filters.",USERCOLOR_DEFAULT); + WriteFilterNames(); + return; + } else { + PFILTER pFilter = gpFilters; + PFILTER pLastFilter = NULL; + while (pFilter) { + if ((pFilter->pEnabled == &gFilterCustom) && (!stricmp(pFilter->FilterText,szRest))) { + if (!pLastFilter) { + gpFilters = pFilter->pNext; + } else { + pLastFilter->pNext = pFilter->pNext; + } + free(pFilter); + sprintf(szCmd,"Stopped filtering on: %s",szRest); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + WriteFilterNames(); + return; + } else { + pLastFilter = pFilter; + pFilter = pFilter->pNext; + } + } + } + } else if (!stricmp(szArg,"add")) { + if (szRest[0]==0) { + WriteChatColor("Add what?",USERCOLOR_DEFAULT); + return; + } + PFILTER pFilter = gpFilters; + while (pFilter) { + if ((pFilter->pEnabled == &gFilterCustom) && (!stricmp(pFilter->FilterText,szRest))) { + sprintf(szCmd,"Name '%s' is already being filtered.",szRest); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + return; + } + pFilter = pFilter->pNext; + } + + AddFilter(szRest,-1,&gFilterCustom); + WriteFilterNames(); + sprintf(szCmd,"Started filtering on: %s",szRest); + WriteChatColor(szCmd,USERCOLOR_DEFAULT); + return; + } else { + SyntaxError("Usage: /filter name on|off|add|remove "); + return; + } + } + } else if (!stricmp("zrange",szArg)) { + if (szRest[0]==0) { + if (gZFilter>=10000.0f) { + WriteChatColor("Z range is not currently set.", USERCOLOR_DEFAULT); + } else { + sprintf(szArg,"Z range is set to: %1.2f",gZFilter); + WriteChatColor(szArg, USERCOLOR_DEFAULT); + } + } else { + gZFilter = (FLOAT)atof(szRest); + } + } +} + + +// *************************************************************************** +// Function: DebugSpewFile +// Description: Our '/spewfile' command +// Controls logging of DebugSpew to a file +// Usage: /spewfile [on,off] +// *************************************************************************** +VOID DebugSpewFile(PSPAWNINFO pChar, PCHAR szLine) +{ + BOOL Pause = TRUE; + CHAR szBuffer[MAX_STRING] = {0}; + bRunNextCommand = TRUE; + if (!strnicmp(szLine,"off",3)) { + gSpewToFile = FALSE; + } else if (!strnicmp(szLine,"on",2)) { + gSpewToFile = TRUE; + } else if (szLine[0]!=0) { + WriteChatColor("Syntax: /spewfile [on|off]",USERCOLOR_DEFAULT); + } else { + Pause = !gSpewToFile; + } + if (gSpewToFile) { + sprintf(szBuffer,"Debug Spew is being logged to a file."); + } else { + sprintf(szBuffer,"Debug Spew is not being logged to a file."); + } + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); +} + + +// *************************************************************************** +// Function: Identify +// Description: Our '/identify' command +// Identifies the item on the cursor, displaying the LORE name. +// Usage: /identify +// *************************************************************************** +VOID Identify(PSPAWNINFO pChar, PCHAR szLine) +{ + bRunNextCommand = TRUE; + CHAR szMsg[MAX_STRING] = {0}; + CHAR szTmp[MAX_STRING] = {0}; + PCHARINFO2 pCharInfo = NULL; + PITEMINFO pItemInfo = NULL; + if (NULL == (pCharInfo = GetCharInfo2())) return; + if (!pCharInfo->pInventoryArray->Inventory.Cursor) { + MacroError("You must be holding an item to identify it."); + return; + } + + pItemInfo = GetItemFromContents(pCharInfo->pInventoryArray->Inventory.Cursor); + DebugSpew("Identify - %s", pItemInfo->LoreName); + WriteChatColor(" ",USERCOLOR_SPELLS); + if ( pItemInfo->Type == ITEMTYPE_NORMAL && pItemInfo->ItemType < MAX_ITEMTYPES && szItemTypes[pItemInfo->ItemType] != NULL ) + sprintf(szMsg,"Item: %s (Slot: %s, Weight: %d.%d, Value: %dcp, Type: %s)",pItemInfo->Name,szSize[pItemInfo->Size], (INT)(pItemInfo->Weight/10),(pItemInfo->Weight) % 10, pItemInfo->Cost, szItemTypes[pItemInfo->ItemType] ); + else if ( pItemInfo->Type == ITEMTYPE_PACK && pItemInfo->Combine < MAX_COMBINES && szCombineTypes[pItemInfo->Combine] != NULL ) + sprintf(szMsg,"Item: %s (Slot: %s, Weight: %d.%d, Value: %dcp, Type: %s)",pItemInfo->Name,szSize[pItemInfo->Size], (INT)(pItemInfo->Weight/10),(pItemInfo->Weight) % 10, pItemInfo->Cost, szCombineTypes[pItemInfo->Combine] ); + else + sprintf(szMsg,"Item: %s (Slot: %s, Weight: %d.%d, Value: %dcp)",pItemInfo->Name,szSize[pItemInfo->Size], (INT)(pItemInfo->Weight/10),(pItemInfo->Weight) % 10, pItemInfo->Cost ); + + + WriteChatColor(szMsg,USERCOLOR_SPELLS); + if ((pItemInfo->LoreName[0] != '*') && (strcmp(pItemInfo->LoreName,pItemInfo->Name))) { + sprintf(szMsg,"Lore Name: %s",pItemInfo->LoreName); + WriteChatColor(szMsg,USERCOLOR_SPELLS); + } else if ((pItemInfo->LoreName[0] == '*') && (strcmp(pItemInfo->LoreName+1,pItemInfo->Name))) { + sprintf(szMsg,"Lore Name: %s",pItemInfo->LoreName+1); + WriteChatColor(szMsg,USERCOLOR_SPELLS); + } + + strcpy(szMsg,"Flags: "); + if (pItemInfo->LoreName[0] == '*') strcat(szMsg,"LORE "); + if (pItemInfo->NoDrop == 0) strcat(szMsg,"NODROP "); + if (pItemInfo->NoRent == 0) strcat(szMsg,"NORENT "); + if (pItemInfo->Type == ITEMTYPE_NORMAL) { + if (pItemInfo->Magic == 1) strcat(szMsg,"MAGIC "); + BYTE Light = pItemInfo->Light; + if ((Light>0) && (Light<=LIGHT_COUNT)) { + strcat(szMsg,"(Light: "); + strcat(szMsg,szLights[Light]); + strcat(szMsg,") "); + } + } + if (strlen(szMsg) > 7) WriteChatColor(szMsg,USERCOLOR_SPELLS); + + if (pItemInfo->Type == ITEMTYPE_PACK) { + CHAR szCombine[MAX_STRING] = {0}; + if ((pItemInfo->Combine < MAX_COMBINES) && (szCombineTypes[pItemInfo->Combine] != NULL)) { + strcpy(szCombine,szCombineTypes[pItemInfo->Combine]); + } else { + sprintf(szCombine,"*Unknown%d",pItemInfo->Combine); + } + sprintf(szMsg,"Container: %d Slot %s, %d%% Reduction, Combine=%s",pItemInfo->Slots,szSize[pItemInfo->SizeCapacity],pItemInfo->WeightReduction,szCombine); + } else if (pItemInfo->Type == ITEMTYPE_BOOK) { + //sprintf(szMsg,"Book file: %s", pItemInfo->Book.File); + } else { + strcpy(szMsg,"Item: "); + if (pItemInfo->AC) { + sprintf(szTmp,"AC%d ",pItemInfo->AC); + strcat(szMsg,szTmp); + } + if (pItemInfo->Damage) { + sprintf(szTmp,"%dDam ",pItemInfo->Damage); + strcat(szMsg,szTmp); + } + if (pItemInfo->Delay) { + sprintf(szTmp,"%dDly ",pItemInfo->Delay); + strcat(szMsg,szTmp); + } + + if (pItemInfo->Range) { + sprintf(szTmp,"%dRng ",pItemInfo->Range); + strcat(szMsg,szTmp); + } + + if (pItemInfo->HP) { + sprintf(szTmp,"%dHP ",pItemInfo->HP); + strcat(szMsg,szTmp); + } + if (pItemInfo->Mana) { + sprintf(szTmp,"%dMana ",pItemInfo->Mana); + strcat(szMsg,szTmp); + } + if (pItemInfo->STR) { + sprintf(szTmp,"%dSTR ",pItemInfo->STR); + strcat(szMsg,szTmp) ; + } + if (pItemInfo->STA) { + sprintf(szTmp,"%dSTA ",pItemInfo->STA); + strcat(szMsg,szTmp); + } + if (pItemInfo->DEX) { + sprintf(szTmp,"%dDEX ",pItemInfo->DEX); + strcat(szMsg,szTmp); + } + if (pItemInfo->AGI) { + sprintf(szTmp,"%dAGI ",pItemInfo->AGI); + strcat(szMsg,szTmp); + } + if (pItemInfo->WIS) { + sprintf(szTmp,"%dWIS ",pItemInfo->WIS); + strcat(szMsg,szTmp); + } + if (pItemInfo->INT) { + sprintf(szTmp,"%dINT ",pItemInfo->INT); + strcat(szMsg,szTmp); + } + if (pItemInfo->CHA) { + sprintf(szTmp,"%dCHA ",pItemInfo->CHA); + strcat(szMsg,szTmp); + } + if (pItemInfo->SvMagic) { + sprintf(szTmp,"%dSvM ",pItemInfo->SvMagic); + strcat(szMsg,szTmp); + } + if (pItemInfo->SvDisease) { + sprintf(szTmp,"%dSvD ",pItemInfo->SvDisease); + strcat(szMsg,szTmp); + } + if (pItemInfo->SvPoison) { + sprintf(szTmp,"%dSvP ",pItemInfo->SvPoison); + strcat(szMsg,szTmp); + } + if (pItemInfo->SvFire) { + sprintf(szTmp,"%dSvF ",pItemInfo->SvFire); + strcat(szMsg,szTmp); + } + if (pItemInfo->SvCold) { + sprintf(szTmp,"%dSvC ",pItemInfo->SvCold); + strcat(szMsg,szTmp); + } + if (pItemInfo->SvCorruption) { + sprintf(szTmp,"%dSvCorruption ",pItemInfo->SvCorruption); + strcat(szMsg,szTmp); + } + if (((EQ_Item*)pCharInfo->pInventoryArray->Inventory.Cursor)->IsStackable()==1) { + sprintf(szTmp,"Stack size = %d ",pCharInfo->pInventoryArray->Inventory.Cursor->StackCount); + strcat(szMsg,szTmp); + } + } + if (strlen(szMsg)>6) WriteChatColor(szMsg,USERCOLOR_SPELLS); +} + + +// *************************************************************************** +// Function: Location +// Description: Our '/loc' command +// Displays your loc and current heading... +// on a 16 point compass (ie. NNE) +// Usage: /loc +// *************************************************************************** +VOID Location(PSPAWNINFO pChar, PCHAR szLine) +{ + bRunNextCommand = TRUE; + if (gFilterMacro == FILTERMACRO_NONE) cmdLocation(pChar,szLine); + + CHAR szMsg[MAX_STRING] = {0}; + INT Angle = (INT)((pChar->Heading / 32.0f) + 8.5f) % 16; + sprintf(szMsg,"Your Location is %3.2f, %3.2f, %3.2f, and are heading %s.", pChar->Y, pChar->X, pChar->Z, szHeading[Angle]); + WriteChatColor(szMsg,USERCOLOR_DEFAULT); +} + +// *************************************************************************** +// Function: Alert +// Description: Our '/alert' command +// Sets up $alert notifications +// Usage: /alert [clear #] [list #] [add # [pc|npc|corpse|any] [radius ###] [zradius ###] [race race] [class class] [range min max] [name]] +// *************************************************************************** +VOID Alert(PSPAWNINFO pChar, PCHAR szLine) +{ + bRunNextCommand = TRUE; + CHAR szArg[MAX_STRING] = {0}; + CHAR szLLine[MAX_STRING] = {0}; + PCHAR szRest = szLLine; + BOOL Parsing = TRUE; + BOOL DidSomething = FALSE; + + // if szLLine is not referenced above by szRest + // the compiler thinks it is not used and optimizes it out + // don't be too tricky + strcpy(szLLine,szLine); + _strlwr(szLLine); + + while (Parsing) { + if (szRest[0]==0) { + Parsing = FALSE; + } else { + GetArg(szArg,szRest,1); + szRest = GetNextArg(szRest,1); + if (!strcmp(szArg,"clear")) { + GetArg(szArg,szRest,1); + FreeAlerts(atoi(szArg)); + DidSomething = TRUE; + + } else if (!strcmp(szArg,"list")) { + PALERT pAlert = NULL; + GetArg(szArg,szRest,1); + szRest = GetNextArg(szRest,1); + pAlert = GetAlert(atoi(szArg)); + if (!pAlert) { + WriteChatColor("No alerts active.",USERCOLOR_DEFAULT); + + } else { + CHAR Buffer[MAX_STRING] = {0}; + DWORD Count=0; + WriteChatColor(" ",USERCOLOR_DEFAULT); + WriteChatColor("Current alerts:",USERCOLOR_DEFAULT); + while (pAlert) { + FormatSearchSpawn(Buffer,&(pAlert->SearchSpawn)); + WriteChatColor(Buffer,USERCOLOR_DEFAULT); + Count++; + pAlert = pAlert->pNext; + } + sprintf(Buffer,"%d alerts listed.",Count); + WriteChatColor(Buffer,USERCOLOR_DEFAULT); + } + DidSomething = TRUE; + + } else if (!strcmp(szArg,"add")) { + CHAR Buffer[MAX_STRING] = {0}; + CHAR szArg1[MAX_STRING] = {0}; + BOOL ParsingAdd = TRUE; + DWORD List = 0; + GetArg(szArg,szRest,1); + szRest = GetNextArg(szRest,1); + List = atoi(szArg); + PALERT pAlert = (PALERT)malloc(sizeof(ALERT)); + if (!pAlert) { + MacroError("Couldn't create alert."); + DebugSpew("Alert - Unable to allocate memory for new alert."); + return; + } + ZeroMemory(pAlert,sizeof(ALERT)); + ClearSearchSpawn(&(pAlert->SearchSpawn)); + + + while (ParsingAdd) { + GetArg(szArg1,szRest,1); + szRest = GetNextArg(szRest,1); + if (szArg1[0]==0) { + ParsingAdd = FALSE; + } else { + szRest = ParseSearchSpawnArgs(szArg1,szRest,&(pAlert->SearchSpawn)); + } + } + + // prev/next aren't logical in alerts + pAlert->SearchSpawn.bTargNext = FALSE; + pAlert->SearchSpawn.bTargPrev = FALSE; + + CHAR szTemp[MAX_STRING] = {0}; + if (CheckAlertForRecursion(pAlert, List)) { + sprintf(Buffer,"Alert would have cause recursion: %s",FormatSearchSpawn(szTemp,&(pAlert->SearchSpawn))); + free(pAlert); + } else { + if (!GetAlert(List)) { + AddNewAlertList(List,pAlert); + } else { + PALERT pTemp = GetAlert(List); + while (pTemp->pNext) pTemp = pTemp->pNext; + pTemp->pNext = pAlert; + } + sprintf(Buffer,"Added alert for: %s",FormatSearchSpawn(szTemp,&(pAlert->SearchSpawn))); + } + DebugSpew("Alert - %s",Buffer); + WriteChatColor(Buffer,USERCOLOR_DEFAULT); + DidSomething = TRUE; + } + } + } + if (!DidSomething) { + SyntaxError("Usage: /alert [clear #] [list #] [add # [pc|npc|corpse|any] [radius radius] [zradius radius] [range min max] spawn]"); + } +} + + + + +// *************************************************************************** +// Function: SuperWhoTarget +// Description: Our '/whotarget' command +// Displays spawn currently selected +// Usage: /whotarget +// *************************************************************************** +VOID SuperWhoTarget(PSPAWNINFO pChar, PCHAR szLine) +{ + PSPAWNINFO psTarget = NULL; + bRunNextCommand = TRUE; + if (gFilterMacro == FILTERMACRO_NONE) cmdWhoTarget(pChar, szLine); + + if (ppTarget && pTarget) { + psTarget = (PSPAWNINFO)pTarget; + } + + + + if (!psTarget) { + MacroError("You must have a target selected for /whotarget."); + return; + } + DebugSpew("SuperWhoTarget - %s",psTarget->Name); + BOOL Temp=gFilterSWho.Distance; + gFilterSWho.Distance=TRUE; + SuperWhoDisplay(psTarget,USERCOLOR_WHO); + gFilterSWho.Distance=Temp; + //SuperWhoDisplay(pChar,NULL,psTarget,0,TRUE); +} + +// *************************************************************************** +// Function: SuperWho +// Description: Our '/who' command +// Displays a list of spawns in the zone +// Usage: /who +// *************************************************************************** +VOID SuperWho(PSPAWNINFO pChar, PCHAR szLine) +{ + cmdWho(pChar, szLine); + return; + + bRunNextCommand = TRUE; + CHAR szLLine[MAX_STRING] = {0}; + CHAR szArg[MAX_STRING] = {0}; + PCHAR szRest = szLLine; + BOOL Parsing = TRUE; + BOOL bConColor=0; + SEARCHSPAWN SearchSpawn; + + _strlwr(strcpy(szLLine,szLine)); + ClearSearchSpawn(&SearchSpawn); + SearchSpawn.SpawnType = PC; + + + if ((!stricmp(szLine,"all")) || + (!strnicmp(szLine,"all ",4)) || + (!strnicmp(szLine+strlen(szLine)-4," all",4)) || + (strstr(szLine, " all ")) || + pLocalPlayer && pLocalPlayer->Data.pSpawn && !pLocalPlayer->Data.pSpawn->GM) + { + cmdWho(pChar, szLine); + return; + } + //if (szLine[0]) + //{ + // SearchSpawn.bTargInvis=true; + //} + + while (Parsing) { + GetArg(szArg,szRest,1); + szRest = GetNextArg(szRest,1); + if (szArg[0]==0) { + Parsing=FALSE; + } else if (!strcmp(szArg,"sort")) { + GetArg(szArg,szRest,1); + // + PCHAR szSortBy[] = { + "level", // Default sort by + "name", + "race", + "class", + "distance", + "guild", + "id", + NULL }; + DWORD Command=0; + + for (Command;szSortBy[Command];Command++) { + if (!strcmp(szArg,szSortBy[Command])) { + SearchSpawn.SortBy = Command; + szRest = GetNextArg(szRest,1); + break; + } + } + } + else if (!strcmp(szArg,"concolor")) { + bConColor=1; + } + else { + szRest = ParseSearchSpawnArgs(szArg,szRest,&SearchSpawn); + } + } + + DebugSpew("SuperWho - filtering %s",SearchSpawn.szName); + SuperWhoDisplay(pChar,&SearchSpawn,bConColor); + //SuperWhoDisplay(pChar, &SearchSpawn,0,0,bConColor); + +} + +// *************************************************************************** +// Function: SetError +// Description: Our '/seterror' command +// Usage: /seterror +// *************************************************************************** + +VOID SetError(PSPAWNINFO pChar, PCHAR szLine) +{ + bRunNextCommand = TRUE; + if ((szLine[0]==0) || (stricmp(szLine,"clear"))) { + gszLastNormalError[0]=0; // QUIT SETTING THIS MANUALLY, USE MacroError or FatalError! + } else { + strcpy(gszLastNormalError,szLine); + } +} +/**/ + + +// *************************************************************************** +// Function: MQMsgBox +// Description: Our '/msgbox' command +// Our message box +// Usage: /msgbox text +// *************************************************************************** +VOID MQMsgBox(PSPAWNINFO pChar, PCHAR szLine) +{ + FILE *fOut = NULL; + CHAR szBuffer[MAX_STRING] = {0}; + DWORD i; + bRunNextCommand = TRUE; + + sprintf(szBuffer, "${Time.Date} ${Time}\r\n%s",szLine); + ParseMacroParameter(pChar,szBuffer); + + CreateThread(NULL,0,thrMsgBox,strdup(szBuffer),0,&i); +} + + +// *************************************************************************** +// Function: MacroLog +// Description: Our '/mqlog' command +// Our logging +// Usage: /mqlog text +// *************************************************************************** +VOID MacroLog(PSPAWNINFO pChar, PCHAR szLine) +{ + FILE *fOut = NULL; + CHAR Filename[MAX_STRING] = {0}; + CHAR szBuffer[MAX_STRING] = {0}; + DWORD i; + bRunNextCommand = TRUE; + + if (gszMacroName[0]==0) { + sprintf(Filename,"%s\\MacroQuest.log",gszLogPath); + } else { + sprintf(Filename,"%s\\%s.log",gszLogPath, gszMacroName); + } + + for (i=0;i +// Usage: /face loc , +// *************************************************************************** +VOID Face(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!ppSpawnManager) return; + if (!pSpawnList) return; + PSPAWNINFO pSpawnClosest = NULL; + PSPAWNINFO psTarget = NULL; + SPAWNINFO LocSpawn = {0}; + SEARCHSPAWN SearchSpawn; + ClearSearchSpawn(&SearchSpawn); + CHAR szMsg[MAX_STRING] = {0}; + CHAR szName[MAX_STRING] = {0}; + CHAR szArg[MAX_STRING] = {0}; + CHAR szLLine[MAX_STRING] = {0}; + PCHAR szFilter = szLLine; + BOOL bArg = TRUE; + BOOL bOtherArgs = FALSE; + BOOL Away = FALSE; + BOOL Predict = FALSE; + BOOL Fast = FALSE; + BOOL Look = TRUE; + BOOL Parsing = TRUE; + DOUBLE Distance; + bRunNextCommand=FALSE; + + _strlwr(strcpy(szLLine,szLine)); + while (bArg) { + GetArg(szArg,szFilter,1); + szFilter = GetNextArg(szFilter,1); + if (szArg[0]==0) { + bArg = FALSE; + } else if (!strcmp(szArg,"predict")) { + Predict=TRUE; + } else if (!strcmp(szArg,"fast")) { + Fast = TRUE; + } else if (!strcmp(szArg,"away")) { + Away = TRUE; + } else if (!strcmp(szArg,"nolook")) { + Look = FALSE; + } else if (!stricmp(szArg, "loc")) { + pSpawnClosest = &LocSpawn; + strcpy(LocSpawn.Name,"location"); + if ((szFilter[0]==0) || (!strstr(szFilter,","))) { + MacroError("Face: loc specified but , not found."); + return; + } + pSpawnClosest->Y = (FLOAT)atof(szFilter); + while ((szFilter[0]!=',') && (szFilter[0]!=0)) szFilter++; + if (szFilter[0]==0) { + MacroError("Face: loc specified but , not found."); + return; + } + szFilter++; + pSpawnClosest->X = (FLOAT)atof(szFilter); + } else if (!stricmp(szArg, "item")) { + if (EnviroTarget.Name[0]==0) { + MacroError("Face: item specified but no item targetted."); + return; + } + pSpawnClosest = &EnviroTarget; + } else if (!stricmp(szArg, "door")) { + if (DoorEnviroTarget.Name[0]==0) { + MacroError("Face: door specified but no door targetted."); + return; + } + pSpawnClosest = &DoorEnviroTarget; + } else if (!stricmp(szArg, "heading")) { + if (szFilter[0]==0) { + MacroError("Face: heading specified but angle not found."); + } else { + FLOAT Heading = (FLOAT)(atof(szFilter)); + gFaceAngle = Heading/0.703125f; + if (gFaceAngle>=512.0f) gFaceAngle -= 512.0f; + if (gFaceAngle<0.0f) gFaceAngle += 512.0f; + if (Fast) { + ((PSPAWNINFO)pCharSpawn)->Heading = (FLOAT)gFaceAngle; + gFaceAngle=10000.0f; + bRunNextCommand = TRUE; + } + } + return; + } else if (!strcmp(szArg,"help")) { + SyntaxError("Usage: /face [spawn] [item] [door] [id #] [heading ] [loc ,] [away] [alert #]"); + bRunNextCommand = TRUE; + return; + } else { + bOtherArgs = TRUE; + szFilter = ParseSearchSpawnArgs(szArg,szFilter,&SearchSpawn); + } + } + + if (!pSpawnClosest) { + if (!bOtherArgs) { + if (ppTarget && pTarget) { + pSpawnClosest = (PSPAWNINFO)pTarget; + } + } else { + pSpawnClosest = SearchThroughSpawns(&SearchSpawn,pChar); + } + } + + szMsg[0]=0; + + if (!pSpawnClosest) { + MacroError("There were no matches for: %s",FormatSearchSpawn(szArg,&SearchSpawn)); + } else { + if (Predict) { + Distance = DistanceToSpawn(pChar, pSpawnClosest); + gFaceAngle = ( + atan2((pSpawnClosest->X + (pSpawnClosest->SpeedX * Distance)) - pChar->X, + (pSpawnClosest->Y + (pSpawnClosest->SpeedY * Distance)) - pChar->Y) + * 256.0f / PI); + } else { + gFaceAngle = ( + atan2(pSpawnClosest->X - pChar->X, + pSpawnClosest->Y - pChar->Y) + * 256.0f / PI); + } + if (Look) { + Distance = DistanceToSpawn(pChar, pSpawnClosest); + gLookAngle = ( + atan2(pSpawnClosest->Z + pSpawnClosest->AvatarHeight*StateHeightMultiplier(pSpawnClosest->StandState) - pChar->Z - pChar->AvatarHeight*StateHeightMultiplier(pChar->StandState), + (FLOAT)Distance) + * 256.0f / PI); + if (Away) gLookAngle = -gLookAngle; + if (Fast) { + pChar->CameraAngle = (FLOAT)gLookAngle; + gLookAngle=10000.0f; + } + } + if (Away) { + gFaceAngle += 256.0f; + } + if (gFaceAngle>=512.0f) gFaceAngle -= 512.0f; + if (gFaceAngle<0.0f) gFaceAngle += 512.0f; + if (Fast) { + ((PSPAWNINFO)pCharSpawn)->Heading = (FLOAT)gFaceAngle; + gFaceAngle=10000.0f; + bRunNextCommand = TRUE; + } + sprintf(szMsg,"Facing %s'%s'...",(Away)?"away from ":"", CleanupName(strcpy(szName,pSpawnClosest->Name),FALSE)); + } + if (ppTarget && pTarget) { + psTarget = (PSPAWNINFO)pTarget; + } + if (szMsg[0] && ((pSpawnClosest != &LocSpawn) && ((Away) || (pSpawnClosest != psTarget)))) WriteChatColor(szMsg,USERCOLOR_WHO); + DebugSpew("Face - %s",szMsg); + return; +} + + +// *************************************************************************** +// Function: Look +// Description: Our /look command. Changes camera angle +// 2003-08-30 MacroFiend +// *************************************************************************** +VOID Look(PSPAWNINFO pChar, PCHAR szLine) +{ + CHAR szLookAngle[MAX_STRING]={0}; + CHAR szTemp[MAX_STRING]={0}; + FLOAT fLookAngle=0.0f; + + GetArg(szLookAngle,szLine,1); + + + fLookAngle = (FLOAT)atof(szLookAngle); + + if (fLookAngle>128.0f || fLookAngle<-128.0f) { + MacroError("/look -- Angle %f out of range.",fLookAngle); + return; + } + + pChar->CameraAngle = fLookAngle; + gLookAngle = 10000.0f; +} + + +// *************************************************************************** +// Function: Where +// Description: Our '/where' command +// Displays the direction and distance to the closest spawn +// Usage: /where +// *************************************************************************** +VOID Where(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!ppSpawnManager) return; + if (!pSpawnList) return; + PSPAWNINFO pSpawnClosest = NULL; + SEARCHSPAWN SearchSpawn; + ClearSearchSpawn(&SearchSpawn); + CHAR szMsg[MAX_STRING] = {0}; + CHAR szName[MAX_STRING] = {0}; + CHAR szArg[MAX_STRING] = {0}; + CHAR szLLine[MAX_STRING] = {0}; + PCHAR szFilter = szLLine; + BOOL bArg = TRUE; + bRunNextCommand = TRUE; + + _strlwr(strcpy(szLLine,szLine)); + + while (bArg) { + GetArg(szArg,szFilter,1); + szFilter = GetNextArg(szFilter,1); + if (szArg[0]==0) { + bArg = FALSE; + } else { + szFilter = ParseSearchSpawnArgs(szArg,szFilter,&SearchSpawn); + } + } + + + if (!(pSpawnClosest = SearchThroughSpawns(&SearchSpawn,pChar))) { + sprintf(szMsg,"There were no matches for: %s",FormatSearchSpawn(szArg,&SearchSpawn)); + } else { + INT Angle = (INT)((atan2f(pChar->X - pSpawnClosest->X, pChar->Y - pSpawnClosest->Y) * 180.0f / PI + 360.0f) / 22.5f + 0.5f) % 16; + sprintf(szMsg,"The closest '%s' is a level %d %s %s and %1.2f away to the %s, Z difference = %1.2f", + CleanupName(strcpy(szName,pSpawnClosest->Name),FALSE), + pSpawnClosest->Level, + pEverQuest->GetRaceDesc(pSpawnClosest->Race), + GetClassDesc(pSpawnClosest->Class), + DistanceToSpawn(pChar,pSpawnClosest), + szHeading[Angle], + pSpawnClosest->Z-pChar->Z); + DebugSpew("Where - %s",szMsg); + } + WriteChatColor(szMsg,USERCOLOR_WHO); + return; +} + + +// *************************************************************************** +// Function: DoAbility +// Description: Our '/doability' command +// Does (or lists) your abilities +// Usage: /doability [list|ability|#] +// *************************************************************************** +VOID DoAbility(PSPAWNINFO pChar, PCHAR szLine) +{ + if(!szLine[0] || !cmdDoAbility) return; + if(atoi(szLine) || !EQADDR_DOABILITYLIST) { + cmdDoAbility(pChar,szLine); + return; + } + + DWORD Index; + CHAR szBuffer[MAX_STRING]={0}; + GetArg(szBuffer,szLine,1); + + // display available abilities list + if(!stricmp(szBuffer,"list")) { + WriteChatColor("Abilities & Combat Skills:",USERCOLOR_DEFAULT); + + // display skills that have activated state + for(Index=0; IndexHasSkill(Index)) + { + + bool Avail=pSkillMgr->pSkill[Index]->Activated; + + // make sure remove trap is added, they give it to everyone except rogues + if(Index==75 && strncmp(pEverQuest->GetClassDesc(GetCharInfo2()->Class & 0xFF),"Rogue",6)) + Avail=true; + + if(Avail) + { + sprintf(szBuffer,"<\ag%s\ax>",szSkills[Index]); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + } + } + + // display innate skills that are available + for(Index=0; Index<28; Index++) + { + if(GetCharInfo2()->InnateSkill[Index]!=0xFF && strlen(szSkills[Index+100])>3) + { + sprintf(szBuffer,"<\ag%s\ax>",szSkills[Index+100]); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + } + + // display discipline i have + WriteChatColor("Combat Abilities:",USERCOLOR_DEFAULT); + for(Index=0;IndexCombatAbilities[Index]) + { + if(PSPELL pCA=GetSpellByID(GetCharInfo2()->CombatAbilities[Index])) + { + sprintf(szBuffer, "<\ag%s\ax>",pCA->Name); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + } + } + return; + } + + // scan for matching abilities name + for(Index=0; Index < 128; Index++) { + if((Index < NUM_SKILLS && (pSkillMgr->pSkill[Index])->Activated) || + (Index >= NUM_SKILLS && GetCharInfo2()->InnateSkill[Index-100]!=0xFF)) + { + if(!stricmp(szBuffer,szSkills[Index])) + { + if(!((CharacterZoneClient*)pCharData1)->HasSkill(Index)) + { + WriteChatf("you do not have this skill"); + return; + } + pCharData1->UseSkill((unsigned char)Index,(EQPlayer*)pCharData1); + return; + } + } + } + + // scan for matching discipline name + for(Index=0; IndexCombatAbilities[Index]) + { + if(PSPELL pCA=GetSpellByID(GetCharInfo2()->CombatAbilities[Index])) + { + if(!stricmp(pCA->Name,szBuffer)) + { + pCharData->DoCombatAbility(pCA->ID); + return; + } + } + } + } + + // else display that we didnt found abilities + WriteChatColor("You do not seem to have that ability available",USERCOLOR_DEFAULT); +} + +// *************************************************************************** +// Function: LoadSpells +// Description: Our '/loadspells' command +// Loads (or lists) a spell favorite list +// Usage: /loadspells [list|"name"] +// *************************************************************************** +VOID LoadSpells(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!pSpellSets || !ppSpellBookWnd || szLine[0]==0) return; + + DWORD Index, DoIndex = 0xFFFFFFFF; + CHAR szArg1[MAX_STRING] = {0}; + CHAR szArg2[MAX_STRING] = {0}; + CHAR szBuffer[MAX_STRING] = {0}; + + if (!pSpellBookWnd) return; + + GetArg(szArg1,szLine,1); + GetArg(szArg2,szLine,2); + + if ((!stricmp(szArg1,"list")) && (szArg2[0]==0)) { + WriteChatColor("Spell favorites list:",USERCOLOR_DEFAULT); + WriteChatColor("--------------------------",USERCOLOR_DEFAULT); + for (Index=0;Index NUM_SPELL_SETS-1) { + sprintf(szBuffer,"Unable to find favorite list '%s'",szArg2); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + return; + } + sprintf(szBuffer,"Favorite list '%s':",pSpellSets[DoIndex].Name); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + for (Index=0;IndexName ); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + } + return; + } + + DoIndex = IsNumber(szArg1)?atoi(szArg1):FindSpellListByName(szArg1); + if (DoIndex >= 0 && DoIndex MemorizeSet((int*)&pSpellSets[DoIndex],NUM_SPELL_GEMS); + } else { + sprintf(szBuffer,"Unable to find favorite list '%s'",szArg1); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } +} + + + +// *************************************************************************** +// Function: Cast +// Description: Our '/cast' command +// Usage: /cast [list|#|"name of spell"|item "name of item"] +// *************************************************************************** +VOID Cast(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!cmdCast) return; + + if (szLine[0]==0 || atoi(szLine) || !ppSpellMgr || !ppCharData || !pCharData) { + cmdCast(pChar,szLine); + return; + } + PCHARINFO pCharInfo = GetCharInfo(); + if (NULL == pCharInfo) return; + DWORD Index; + CHAR szBuffer[MAX_STRING] = {0}; + CHAR szArg1[MAX_STRING] = {0}; + CHAR szArg2[MAX_STRING] = {0}; + if (!stricmp(szLine,"list")) { + WriteChatColor("Spells:",USERCOLOR_DEFAULT); + for (Index=0;IndexMemorizedSpells[Index]==0xFFFFFFFF) { + sprintf(szBuffer,"%d. ",Index+1); + } else { + sprintf(szBuffer,"%d. %s",Index+1,GetSpellNameByID(GetCharInfo2()->MemorizedSpells[Index])); + } + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + + return; + } + + GetArg(szArg1,szLine,1); + GetArg(szArg2,szLine,2); + DebugSpew("Cast: szArg1 = %s szArg2 = %s",szArg1,szArg2); + if (!stricmp(szArg1,"item")) + { + BOOL FOUND = FALSE; + DWORD slot = 0; + for (int i=0;ipInventoryArray->InventoryArray[i]) + if (!_stricmp(szArg2,GetItemFromContents(GetCharInfo2()->pInventoryArray->InventoryArray[i])->Name)) { + DebugSpew("cast test slot %d = %s",i,GetItemFromContents(GetCharInfo2()->pInventoryArray->InventoryArray[i])->Name); + slot = (DWORD)i; + FOUND = TRUE; + break; + } + } + if (FOUND) { + if(CInvSlot *pSlot=pInvSlotMgr->FindInvSlot(slot)) { + CXPoint p; p.A=0; p.B=0; + pSlot->HandleRButtonUp(&p); + } + } + else { + WriteChatf("Item '%s' not found.",szArg2); + } + return; + } + GetArg(szBuffer,szLine,1); + for (Index=0;IndexMemorizedSpells[Index]!=0xFFFFFFFF) { + PCHAR SpellName = GetSpellNameByID(GetCharInfo2()->MemorizedSpells[Index]); + if (!stricmp(szBuffer,SpellName)) { + DebugSpew("SpellName = %s",SpellName); + cmdCast(pChar,itoa(Index+1,szBuffer,10)); + DebugSpew("pChar = %x SpellName = %s %s",pChar,SpellName,itoa(Index+1,szBuffer,10)); + return; + } + } + } + WriteChatColor("You do not seem to have that spell memorized.",USERCOLOR_DEFAULT); + return; +} + +// *************************************************************************** +// Function: Target +// Description: Our '/target' command +// Selects the closest spawn +// Usage: /target [spawn|myself|mycorpse] +// *************************************************************************** +VOID Target(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!ppSpawnManager) return; + if (!pSpawnList) return; + PSPAWNINFO pSpawnClosest = NULL; + SEARCHSPAWN SearchSpawn; + ClearSearchSpawn(&SearchSpawn); + CHAR szArg[MAX_STRING] = {0}; + CHAR szMsg[MAX_STRING] = {0}; + CHAR szLLine[MAX_STRING] = {0}; + PCHAR szFilter = szLLine; + BOOL DidTarget = FALSE; + BOOL bArg = TRUE; + + bRunNextCommand = TRUE; + _strlwr(strcpy(szLLine,szLine)); + while (bArg) { + GetArg(szArg,szFilter,1); + szFilter = GetNextArg(szFilter,1); + if (szArg[0]==0) { + bArg = FALSE; + } else if (!strcmp(szArg,"myself")) { + if (((PCHARINFO)pCharData)->pSpawn) { + pSpawnClosest = ((PCHARINFO)pCharData)->pSpawn; + DidTarget = TRUE; + } + } else if (!strcmp(szArg,"mycorpse")) { + if (((PCHARINFO)pCharData)->pSpawn) { + sprintf(szFilter,"%s's Corpse",((PCHARINFO)pCharData)->pSpawn->Name); + _strlwr(szFilter); + } + } else if (!strcmp(szArg,"clear")) { + pTarget = NULL; + EnviroTarget.SpawnID = 0; + DoorEnviroTarget.SpawnID = 0; + if(pChar) + pChar->GroupMemberTargeted = 0xFFFFFFFF; + DebugSpew("Target cleared."); + WriteChatColor("Target cleared.",USERCOLOR_WHO); + return; + } else { + szFilter = ParseSearchSpawnArgs(szArg,szFilter,&SearchSpawn); + } + } + if (pTarget) SearchSpawn.FromSpawnID = ((PSPAWNINFO)pTarget)->SpawnID; + + if (!DidTarget) { + pSpawnClosest = SearchThroughSpawns(&SearchSpawn,pChar); + } + + if (!pSpawnClosest) { + CHAR szTemp[MAX_STRING] = {0}; + sprintf(szMsg,"There are no spawns matching: %s",FormatSearchSpawn(szTemp,&SearchSpawn)); + } else { + PSPAWNINFO *psTarget = NULL; + if (ppTarget) { + psTarget = (PSPAWNINFO*)ppTarget; + *psTarget = pSpawnClosest; + DebugSpew("Target - %s selected",pSpawnClosest->Name); + szMsg[0]=0; + } else { + sprintf(szMsg,"Unable to target, address = 0"); + } + } + if (szMsg[0]) + if (!gFilterTarget) WriteChatColor(szMsg,USERCOLOR_WHO); + return; +} + + +// *************************************************************************** +// Function: Skills +// Description: Our '/skills' command +// Displays what your current skill levels are +// Usage: /skills [skill name] +// *************************************************************************** +VOID Skills(PSPAWNINFO pChar, PCHAR szLine) +{ + DWORD Skill, SkillCount = 0; + CHAR szMsg[MAX_STRING] = {0}; + bRunNextCommand = TRUE; + PCHARINFO pCharInfo = NULL; + if (NULL == (pCharInfo = GetCharInfo())) return; + if (szLine[0] != 0) _strlwr(szLine); + WriteChatColor("Skills",USERCOLOR_DEFAULT); + WriteChatColor("-----------------------",USERCOLOR_DEFAULT); + for (Skill=0;szSkills[Skill];Skill++) { + if (szLine[0] != 0) { + CHAR szName[MAX_STRING] = {0}; + strcpy(szName,szSkills[Skill]); + _strlwr(szName); + if (!strstr(szName,szLine)) continue; + } + SkillCount++; + switch (GetCharInfo2()->Skill[Skill]) { + case 255: + //Untrainable + SkillCount--; + break; + case 254: + //Can train + sprintf(szMsg,"%s: Trainable",szSkills[Skill]); + WriteChatColor(szMsg,USERCOLOR_DEFAULT); + break; + case 253: + //Unknown + sprintf(szMsg,"%s: Unknown(253)",szSkills[Skill]); + WriteChatColor(szMsg,USERCOLOR_DEFAULT); + break; + default: + //Have skill + sprintf(szMsg,"%s: %d",szSkills[Skill],GetCharInfo2()->Skill[Skill]); + WriteChatColor(szMsg,USERCOLOR_DEFAULT); + } + } + if (SkillCount == 0) { + sprintf(szMsg,"No skills matched '%s'.",szLine); + WriteChatColor(szMsg,USERCOLOR_DEFAULT); + } else { + DebugSpew("Skills - %d skills listed",SkillCount); + sprintf(szMsg,"%d skills displayed.",SkillCount); + WriteChatColor(szMsg,USERCOLOR_DEFAULT); + } +} + +// *************************************************************************** +// Function: MacroPause +// Description: Our '/mqpause' command +// Pause/resume a macro +// Usage: /mqpause +// /mqpause chat [on|off] +// *************************************************************************** +VOID MacroPause(PSPAWNINFO pChar, PCHAR szLine) +{ + BOOL Pause = TRUE; + CHAR szBuffer[MAX_STRING] = {0}; + + DWORD Command; + CHAR szArg[MAX_STRING] = {0}; + CHAR szArg1[MAX_STRING] = {0}; + + PCHAR szPause[] = { + "off", + "on", + NULL + }; + + bRunNextCommand = TRUE; + + GetArg(szArg,szLine,1); + if (!stricmp(szArg,"chat")) { + GetArg(szArg1,szLine,2); + if (szLine[0]==0) { + + gMQPauseOnChat = !gMQPauseOnChat; + } else { + for (Command=0;szPause[Command];Command++) { + if (!stricmp(szArg1,szPause[Command])) { + gMQPauseOnChat = Command; + } + } + } + + WritePrivateProfileString("Edge","MQPauseOnChat",(gMQPauseOnChat)?"1":"0",gszINIFilename); + sprintf(szBuffer,"Macros will %spause while in chat mode.",(gMQPauseOnChat)?"":"not "); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + return; + } + + if (!gMacroBlock) { + MacroError("You cannot pause a macro when one isn't running."); + return; + } + + for (Command=0;szPause[Command];Command++) { + if (!stricmp(szArg,szPause[Command])) { + Pause = Command; + } + } + + if (szLine[0]!=0) { + WriteChatColor("Syntax: /mqpause [on|off] [chat [on|off]]",USERCOLOR_DEFAULT); + } else { + Pause = !gMacroPause; + } + if (gMacroPause == Pause) { + sprintf(szBuffer,"Macro is already %s.",(Pause)?"paused":"running"); + } else { + sprintf(szBuffer,"Macro is %s.",(Pause)?"paused":"running again"); + gMacroPause = Pause; + } + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); +} + + + +// *************************************************************************** +// Function: SetAutoRun +// Description: Our '/setautorun' command +// Set autorun value +// Usage: /setautorun [command] +// *************************************************************************** +VOID SetAutoRun(PSPAWNINFO pChar, PCHAR szLine) +{ + CHAR szServerAndName[MAX_STRING] = {0}; + sprintf(szServerAndName,"%s.%s",EQADDR_SERVERNAME,((PCHARINFO)pCharData)->Name); + WritePrivateProfileStringA("AutoRun",szServerAndName,szLine,gszINIFilename); + sprintf(szServerAndName,"Set autorun to: '%s'",szLine); + WriteChatColor(szServerAndName,USERCOLOR_DEFAULT); +} + +// *************************************************************************** +// Function: Alias +// Description: Our '/alias' command +// Add command aliases +// Usage: /alias name [delete|command] +// *************************************************************************** + +VOID Alias(PSPAWNINFO pChar, PCHAR szLine) +{ + CHAR szBuffer[MAX_STRING] = {0}; + CHAR szName[MAX_STRING] = {0}; + PCHAR szCommand = NULL; + GetArg(szName,szLine,1); + szCommand = GetNextArg(szLine); + if (!stricmp(szName,"list")) { + PALIAS pLoop = pAliases; + DWORD Count=0; + WriteChatColor("Aliases",USERCOLOR_WHO); + WriteChatColor("--------------------------",USERCOLOR_WHO); + while (pLoop) { + sprintf(szName,"%s: %s",pLoop->szName,pLoop->szCommand); + WriteChatColor(szName,USERCOLOR_WHO); + Count++; + pLoop = pLoop->pNext; + } + if (Count==0) { + WriteChatColor("No aliases defined.",USERCOLOR_WHO); + } else { + sprintf(szName,"%d alias%s displayed.",Count,(Count==1)?"":"es"); + WriteChatColor(szName,USERCOLOR_WHO); + } + return; + } + if ((szName[0]==0) || (szCommand[0]==0)) { + SyntaxError("Usage: /alias name [delete|command], or /alias list"); + return; + } + + if (!stricmp(szCommand,"delete")) { + if (RemoveAlias(szName)) + { + sprintf(szBuffer,"Alias '%s' deleted.",szName); + RewriteAliases(); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + else + { + sprintf(szBuffer,"Alias '%s' not found.",szName); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + } else { + BOOL New=1; + if (RemoveAlias(szName)) + New=0; + AddAlias(szName,szCommand); + sprintf(szBuffer,"Alias '%s' %sed.",szName,(New)?"add":"updat"); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + RewriteAliases(); + } +} + +// *************************************************************************** +// Function: Substitute +// Description: Our '/substitute' command +// Add substitutions +// Usage: /substitution +// /substitution list +// /substitition delete +// *************************************************************************** + +VOID Substitute(PSPAWNINFO pChar, PCHAR szLine) +{ + CHAR szBuffer[MAX_STRING] = {0}; + CHAR szName[MAX_STRING] = {0}; + PCHAR szCommand = NULL; + GetArg(szName,szLine,1); + szCommand = GetNextArg(szLine); + if (!stricmp(szName,"list")) { + PSUB pLoop = pSubs; + DWORD Count=0; + WriteChatColor("Substitutions",USERCOLOR_WHO); + WriteChatColor("--------------------------",USERCOLOR_WHO); + while (pLoop) { + sprintf(szName,"%s\t----\t%s",pLoop->szOrig,pLoop->szSub); + WriteChatColor(szName,USERCOLOR_WHO); + Count++; + pLoop = pLoop->pNext; + } + if (Count==0) { + WriteChatColor("No Substitutions defined.",USERCOLOR_WHO); + } else { + sprintf(szName,"%d substitution%s displayed.",Count,(Count==1)?"":"s"); + WriteChatColor(szName,USERCOLOR_WHO); + } + return; + } + if ((szName[0]==0) || (szCommand[0]==0)) { + SyntaxError("Usage: /substitute , /substitute delete, or /substitute list"); + return; + } + + if (!stricmp(szCommand,"delete")) { + if (RemoveSubstitute(szName)) + { + sprintf(szBuffer,"Substitution for '%s' deleted.",szName); + RewriteSubstitutions(); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + else + { + sprintf(szBuffer,"Substitution for '%s' not found.",szName); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + } else { + BOOL New=1; + if (RemoveSubstitute(szName)) + New=0; + AddSubstitute(szName,szCommand); + sprintf(szBuffer,"Substitution for '%s' %sed.",szName,(New)?"add":"updat"); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + RewriteSubstitutions(); + } +} + +// *************************************************************************** +// Function: IniOutput +// Description: Outputs string data to an INI file using +// WritePrivateProfileString. +// Usage: /ini +// *************************************************************************** +VOID IniOutput(PSPAWNINFO pChar, PCHAR szLine) +{ + CHAR szArg1[MAX_STRING] = {0}; //Filename + CHAR szArg2[MAX_STRING] = {0}; //Section + CHAR szArg3[MAX_STRING] = {0}; //Key + CHAR szArg4[MAX_STRING] = {0}; //Data to write + + CHAR szOutput[MAX_STRING] = {0}; //Success / Error Output + + GetArg(szArg1,szLine,1); + GetArg(szArg2,szLine,2); + GetArg(szArg3,szLine,3); + GetArg(szArg4,szLine,4); + + DebugSpew("/ini input -- %s %s %s %s",szArg1,szArg2,szArg3,szArg4); + PCHAR pTemp=szArg1; + while(pTemp[0]) + { + if (pTemp[0]=='/') + pTemp[0]='\\'; + pTemp++; + } + + + if (szArg1[0]!='\\' && !strchr(szArg1,':')) + { + sprintf(szOutput,"%s\\%s",gszMacroPath, szArg1); + strcpy(szArg1,szOutput); + } + if (!strstr(szArg1,".")) strcat(szArg1,".ini"); + ZeroMemory(szOutput,MAX_STRING); + + if (!WritePrivateProfileString(szArg2,szArg3,szArg4,szArg1)) { + sprintf(szOutput,"IniOutput ERROR -- during WritePrivateProfileString: %s",szLine); + DebugSpew(szOutput); + } else { + sprintf(szOutput,"IniOutput Write Successful!"); + DebugSpew("%s: %s",szOutput,szLine); + } +} + +// *************************************************************************** +// Function: BankList +// Description: Our /banklist command. Lists bank contents to chat buffer. +// 2003-08-30 Valerian +// *************************************************************************** +VOID BankList(PSPAWNINFO pChar, PCHAR szLine) +{ + CHAR szTemp[MAX_STRING]={0}; + PCHARINFO pCharInfo = NULL; + PCONTENTS pContainer = NULL; + if (NULL == (pCharInfo = GetCharInfo())) { + MacroError("/banklist -- Bad offset: CharInfo"); + return; + } + WriteChatColor("Listing of Bank Inventory",USERCOLOR_DEFAULT); + WriteChatColor("-------------------------",USERCOLOR_DEFAULT); + char Link[256]; + for (int a=0;apBankArray->Bank[a]; + if (pContainer) { + GetItemLink(pContainer,&Link[0]); + sprintf(szTemp,"Slot %d: %dx %s (%s)",a,pContainer->StackCount ? pContainer->StackCount : 1,Link,GetItemFromContents(pContainer)->LoreName); + WriteChatColor(szTemp,USERCOLOR_DEFAULT); + if(pContainer->pContentsArray) + { + for (int b=0;bSlots;b++) { + if (pContainer->pContentsArray->Contents[b]) { + GetItemLink(pContainer->pContentsArray->Contents[b],&Link[0]); + sprintf(szTemp,"- Slot %d: %dx %s (%s)",b,pContainer->pContentsArray->Contents[b]->StackCount ? pContainer->pContentsArray->Contents[b]->StackCount : 1,Link,GetItemFromContents(pContainer->pContentsArray->Contents[b])->LoreName); + WriteChatColor(szTemp,USERCOLOR_DEFAULT); + } + } + } + } + } +} + +// *************************************************************************** +// Function: DisplayLoginName +// Description: Our /loginname command. +// *************************************************************************** +VOID DisplayLoginName(PSPAWNINFO pChar, PCHAR szLine) +{ + PCHAR szLogin = GetLoginName(); + if (!szLogin) { + MacroError("Unable to retrieve login name."); + } else { + WriteChatf("Login name: \ay%s\ax",szLogin); + free(szLogin); + } +} + +#ifndef ISXEQ_LEGACY +// *************************************************************************** +// Function: PluginCommand +// Description: Our /plugin command. +// *************************************************************************** +VOID PluginCommand(PSPAWNINFO pChar, PCHAR szLine) +{ +} +#endif + +VOID EQDestroyHeldItemOrMoney(PSPAWNINFO pChar, PCHAR szLine) +{ + (pPCData)->DestroyHeldItemOrMoney(); +} + +VOID Exec(PSPAWNINFO pChar,PCHAR szLine) { + CHAR exepath[MAX_STRING] = {0}; + CHAR szTemp1[MAX_STRING] = {0}; + CHAR szTemp2[MAX_STRING] = {0}; + CHAR szTemp3[MAX_STRING] = {0}; + GetArg(szTemp1,szLine,1); + GetArg(szTemp2,szLine,2); + GetArg(szTemp3,szLine,3); + + if (szTemp1[0]!=0 && szTemp2[0]!=0) { + WriteChatf("Opening %s %s %s",szTemp1,szTemp2,szTemp3); + + GetPrivateProfileString("Application Paths",szTemp1,szTemp1,exepath,MAX_STRING,gszINIFilename); + + if(!strcmp(szTemp2,"bg")) { + ShellExecute(NULL, "open", exepath, NULL, NULL, SW_SHOWMINNOACTIVE); + } else if(!strcmp(szTemp2,"fg")) { + ShellExecute(NULL, "open", exepath, NULL, NULL, SW_SHOWNOACTIVATE); + } else if(!strcmp(szTemp3,"bg")) { + ShellExecute(NULL, "open", exepath, szTemp2, NULL, SW_SHOWMINNOACTIVE); + } else if(!strcmp(szTemp3,"fg")) { + ShellExecute(NULL, "open", exepath, szTemp2, NULL, SW_SHOWNOACTIVATE); + } + } else { + WriteChatColor("/exec [application \"parameters\"] [fg | bg]",USERCOLOR_DEFAULT); + } +} + +// /keypress +VOID DoMappable(PSPAWNINFO pChar, PCHAR szLine) +{ +} + +// /popup +VOID PopupText(PSPAWNINFO pChar, PCHAR szLine) +{ + DisplayOverlayText(szLine, CONCOLOR_LIGHTBLUE, 100, 500,500,3000); +} + +// /multiline +VOID MultilineCommand(PSPAWNINFO pChar, PCHAR szLine) +{ + if (szLine[0]==0) + { + SyntaxError("Usage: /multiline [delimiter[delimiter[. . .]]]"); + return; + } + CHAR szArg[MAX_STRING] = {0}; // delimiter(s) + GetArg(szArg,szLine,1); + PCHAR szRest = GetNextArg(szLine); + if (!szRest[0]) + return; + CHAR Copy[MAX_STRING] = {0}; + strcpy(Copy,szRest);// dont destroy original... + szRest=strtok(Copy,szArg); + while(szRest) + { + DoCommand(pChar,szRest); + szRest=strtok(NULL,szArg); + } +} + +// /ranged +VOID do_ranged(PSPAWNINFO pChar, PCHAR szLine) +{ + EQPlayer *pRangedTarget=pTarget; + if (szLine[0]) + { + pRangedTarget=GetSpawnByID(atoi(szLine)); + if (!pRangedTarget) + { + MacroError("Invalid spawn ID. Use /ranged with no parameters, or with a spawn ID"); + return; + } + } + if (!pRangedTarget) + { + MacroError("No target for ranged attack"); + return; + } + AttackRanged(pRangedTarget); +} + +// /loadcfg +VOID LoadCfgCommand(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /loadcfg "); + return; + } + + if (LoadCfgFile(szLine,false)) + return; + MacroError("Could not /loadcfg '%s'",szLine); +} + +// /squelch +VOID SquelchCommand(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /squelch "); + return; + } + BOOL Temp=gFilterMQ; + gFilterMQ=true; + DoCommand(pChar,szLine); + gFilterMQ=Temp; +} + +// /docommand +VOID DoCommandCmd(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /docommand "); + return; + } + DoCommand(pChar,szLine); +} + +// /alt +VOID DoAltCmd(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /alt "); + return; + } + bool Old=((PCXWNDMGR)pWndMgr)->KeyboardFlags[2]; + ((PCXWNDMGR)pWndMgr)->KeyboardFlags[2]=1; + DoCommand(pChar,szLine); + ((PCXWNDMGR)pWndMgr)->KeyboardFlags[2]=Old; +} + +// /shift +VOID DoShiftCmd(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /shift "); + return; + } + bool Old=((PCXWNDMGR)pWndMgr)->KeyboardFlags[0]; + ((PCXWNDMGR)pWndMgr)->KeyboardFlags[0]=1; + gShiftKeyDown=1; + DoCommand(pChar,szLine); + gShiftKeyDown=0; + ((PCXWNDMGR)pWndMgr)->KeyboardFlags[0]=Old; +} + +// /ctrl +VOID DoCtrlCmd(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /ctrl "); + return; + } + bool Old=((PCXWNDMGR)pWndMgr)->KeyboardFlags[1]; + ((PCXWNDMGR)pWndMgr)->KeyboardFlags[1]=1; + DoCommand(pChar,szLine); + ((PCXWNDMGR)pWndMgr)->KeyboardFlags[1]=Old; +} + +VOID NoModKeyCmd(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /nomodkey "); + return; + } + bool KeyboardFlags[4]; + *(DWORD*)&KeyboardFlags=*(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags; + *(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags=0; + DoCommand(pChar,szLine); + *(DWORD*)&((PCXWNDMGR)pWndMgr)->KeyboardFlags=*(DWORD*)&KeyboardFlags; +} + +// *************************************************************************** +// Function: DoSocial +// Description: '/dosocial' command +// Does (or lists) your programmed socials +// Usage: /dosocial [list|"social name"] +// *************************************************************************** +VOID DoSocial(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!pSocialList) return; + + DWORD SocialIndex = -1, LineIndex; + DWORD SocialPage = 0, SocialNum = 0; + CHAR szBuffer[MAX_STRING] = {0}; + BOOL displayUsage = FALSE; + + GetArg(szBuffer,szLine,1); + + if( !stricmp(szBuffer,"list") ) { + WriteChatColor("Socials: (page,number) name",USERCOLOR_DEFAULT); + for (SocialIndex=0; SocialIndex < 120; SocialIndex++) { + SocialPage = SocialIndex/12; + SocialNum = SocialIndex - (SocialPage*12); + if( strlen(pSocialList[SocialIndex].Name) ) { + sprintf(szBuffer,"(%2d,%2d) %s ", SocialPage+1, SocialNum+1, pSocialList[SocialIndex].Name); + WriteChatColor(szBuffer,USERCOLOR_ECHO_EMOTE); + for( LineIndex=0; LineIndex < 5; LineIndex++ ) { + if( strlen(pSocialList[SocialIndex].Line[LineIndex]) ) { + sprintf(szBuffer," %d: %s", LineIndex+1, pSocialList[SocialIndex].Line[LineIndex]); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + } + } + } + return; + } else if( strlen(szBuffer) ) { /* assume we have a social name to match */ + for( unsigned long N = 0; N < 120; N++ ) { + if( !stricmp(szBuffer,pSocialList[N].Name) ) + { + SocialIndex=N; + break; + } + } + } + + if (gCurrentSocial==-1) + { + gCurrentSocial=SocialIndex; + } + else + { + if( SocialIndex < 120 ) { + for( LineIndex = 0; LineIndex < 5; LineIndex++ ) { + if( strlen(pSocialList[SocialIndex].Line[LineIndex]) ) DoCommand(pChar,pSocialList[SocialIndex].Line[LineIndex]); + } + } else { + if( strlen(szLine) ) { + sprintf( szBuffer, "Invalid Argument(s): %s", szLine ); + WriteChatColor(szBuffer,USERCOLOR_DEFAULT); + } + SyntaxError("Usage: /dosocial ",USERCOLOR_DEFAULT ); + } + } +} + +// /timed +VOID DoTimedCmd(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /timed "); + return; + } + CHAR szArg[MAX_STRING] = {0}; // delay + GetArg(szArg,szLine,1); + PCHAR szRest = GetNextArg(szLine); + if (!szRest[0]) + return; + TimedCommand(szRest,atoi(szArg)*100); +} + +VOID ClearErrorsCmd(PSPAWNINFO pChar, PCHAR szLine) +{ + gszLastNormalError[0]=0; + gszLastSyntaxError[0]=0; + gszLastMQ2DataError[0]=0; +} + +VOID DropCmd(PSPAWNINFO pChar, PCHAR szLine) +{ + if (GetCharInfo2()->pInventoryArray->Inventory.Cursor) + { + if (((EQ_Item*)GetCharInfo2()->pInventoryArray->Inventory.Cursor)->CanDrop(0,1)) + { + pEverQuest->DropHeldItemOnGround(1); + } + } +} + +VOID HudCmd(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /hud "); + WriteChatColor("Note: 'always' forces 'underui' also. The Network Status indicator is not 'always' drawn and is toggled with F11."); + return; + } + else + if (!stricmp(szLine,"normal")) + { + WritePrivateProfileString("Edge","HUDMode","Normal",gszINIFilename); + gbAlwaysDrawMQHUD=false; + gbHUDUnderUI=false; + } + else + if (!stricmp(szLine,"underui")) + { + WritePrivateProfileString("Edge","HUDMode","UnderUI",gszINIFilename); + gbHUDUnderUI=true; + gbAlwaysDrawMQHUD=false; + } + else + if (!stricmp(szLine,"always")) + { + WritePrivateProfileString("Edge","HUDMode","Always",gszINIFilename); + gbHUDUnderUI=true; + gbAlwaysDrawMQHUD=true; + } +} + +VOID CaptionCmd(PSPAWNINFO pChar, PCHAR szLine) +{ + CHAR Arg1[MAX_STRING]={0}; + GetArg(Arg1,szLine,1); + if (!Arg1[0]) + { + SyntaxError("Usage: /caption |update #|MQCaptions >"); + return; + } + if (!stricmp(Arg1,"list")) + { + WriteChatf("\ayPlayer1\ax: \ag%s\ax",gszSpawnPlayerName[1]); + WriteChatf("\ayPlayer2\ax: \ag%s\ax",gszSpawnPlayerName[2]); + WriteChatf("\ayPlayer3\ax: \ag%s\ax",gszSpawnPlayerName[3]); + WriteChatf("\ayPlayer4\ax: \ag%s\ax",gszSpawnPlayerName[4]); + WriteChatf("\ayPlayer5\ax: \ag%s\ax",gszSpawnPlayerName[5]); + WriteChatf("\ayPlayer6\ax: \ag%s\ax",gszSpawnPlayerName[6]); + + WriteChatf("\ayNPC\ax: \ag%s\ax",gszSpawnNPCName); + WriteChatf("\ayPet\ax: \ag%s\ax",gszSpawnPetName); + WriteChatf("\ayCorpse\ax: \ag%s\ax",gszSpawnCorpseName); + return; + } + PCHAR pCaption=0; + if (!stricmp(Arg1,"Player1")) + { + pCaption=gszSpawnPlayerName[1]; + } else if (!stricmp(Arg1,"Player2")) + { + pCaption=gszSpawnPlayerName[2]; + } else if (!stricmp(Arg1,"Player3")) + { + pCaption=gszSpawnPlayerName[3]; + } else if (!stricmp(Arg1,"Player4")) + { + pCaption=gszSpawnPlayerName[4]; + } else if (!stricmp(Arg1,"Player5")) + { + pCaption=gszSpawnPlayerName[5]; + } else if (!stricmp(Arg1,"Player6")) + { + pCaption=gszSpawnPlayerName[6]; + } else if (!stricmp(Arg1,"Pet")) + { + pCaption=gszSpawnPetName; + } else if (!stricmp(Arg1,"NPC")) + { + pCaption=gszSpawnNPCName; + } else if (!stricmp(Arg1,"Corpse")) + { + pCaption=gszSpawnCorpseName; + } else if (!stricmp(Arg1,"Update")) + { + gMaxSpawnCaptions=atoi(GetNextArg(szLine)); + if (gMaxSpawnCaptions<8) + gMaxSpawnCaptions=8; + if (gMaxSpawnCaptions>70) + gMaxSpawnCaptions=70; + WritePrivateProfileString("Captions","Update",itoa(gMaxSpawnCaptions,Arg1,10),gszINIFilename); + WriteChatf("\ay%d\ax nearest spawns will have their caption updated each pass.",gMaxSpawnCaptions); + return; + } else if (!stricmp(Arg1,"MQCaptions")) + { + gMQCaptions=(!stricmp(GetNextArg(szLine),"On")); + WritePrivateProfileString("Captions","MQCaptions",(gMQCaptions?"1":"0"),gszINIFilename); + WriteChatf("MQCaptions are now \ay%s\ax.",(gMQCaptions?"On":"Off")); + return; + } + else + { + MacroError("Invalid caption type '%s'",Arg1); + return; + } + strcpy(pCaption, GetNextArg(szLine)); + WritePrivateProfileString("Captions",Arg1,pCaption,gszINIFilename); + ConvertCR(pCaption); + WriteChatf("\ay%s\ax caption set.",Arg1); +} + +VOID NoParseCmd(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /noparse "); + return; + } + bAllowCommandParse=false; + DoCommand(pChar,szLine); + bAllowCommandParse=true; +} + +VOID AltAbility(PSPAWNINFO pChar, PCHAR szLine) +{ + CHAR szBuffer[MAX_STRING] = {0}; + CHAR szCommand[MAX_STRING] = {0}; + CHAR szSpellInfo[MAX_STRING] = {0}; + PCHAR szName = NULL; + GetArg(szCommand,szLine,1); + szName = GetNextArg(szLine); + unsigned long nAbility=0; + int i=0; + MQ2TicksType szTime; + + if ((szName[0]==0) || (szCommand[0]==0)) { + SyntaxError("Usage: /aa list [all|timers], /aa info [ability name], or /aa act [ability name]"); + return; + } + + if (!stricmp(szCommand,"list")) + { + if (!stricmp(szName,"all")) + { + WriteChatColor("Alternative Abilities (Complete List)", CONCOLOR_YELLOW ); + WriteChatColor("-------------------------------------", USERCOLOR_WHO); + for (nAbility=0 ; nAbilityGetAltAbility(pPCData->GetAltAbilityIndex(nAbility))) { + sprintf(szBuffer,"[ %d: %s ]", pAbility->ID, + pCDBStr->GetString(pAbility->nName, 1, NULL)); + WriteChatColor(szBuffer,USERCOLOR_WHO); + } + } + } + else if (!stricmp(szName,"timers")) + { + WriteChatColor("Alternative Abilities With Timers", CONCOLOR_YELLOW ); + WriteChatColor("---------------------------------", USERCOLOR_WHO); + for (nAbility=0 ; nAbilityGetAltAbility(pPCData->GetAltAbilityIndex(nAbility)) ) { + if ((pAltAdvManager->GetCalculatedTimer(pPCData,pAbility)) > 0) + { + if (pAltAdvManager->IsAbilityReady(pPCData,pAbility,0)) + { + sprintf(szBuffer,"[ %d: %s ] (Reuse Time: %d seconds) ", + pAbility->ID, pCDBStr->GetString(pAbility->nName, 1, NULL), + pAltAdvManager->GetCalculatedTimer(pPCData,pAbility) ); + WriteChatColor(szBuffer,USERCOLOR_WHO); + } + else + { + pAltAdvManager->IsAbilityReady(pPCData,pAbility,&i); + sprintf(szBuffer,"[ %d: %s ] (Reuse Time: %d seconds) ", + pAbility->ID, pCDBStr->GetString(pAbility->nName, 1, NULL), + pAltAdvManager->GetCalculatedTimer(pPCData,pAbility), i ); + WriteChatColor(szBuffer,USERCOLOR_WHO); + } + } + } + } + } + else + { + SyntaxError("Usage: /aa list [all|timers], /aa info [ability name], or /aa act [ability name]"); + return; + } + } + else if (!stricmp(szCommand,"info")) + { + for (unsigned long nAbility=0 ; nAbilityGetAltAbility(nAbility)) + { + char *pName; + if (!stricmp(pName = pCDBStr->GetString(pAbility->nName, 1, NULL), szName)) + { + + WriteChatColor("Alternative Advancement Ability Information", CONCOLOR_YELLOW); + WriteChatColor("-------------------------------------------", USERCOLOR_WHO); + + if ((pAltAdvManager->GetCalculatedTimer(pPCData,pAbility)) > 0) + {//has a timer + if (!pAltAdvManager->IsAbilityReady(pPCData,pAbility,0)) + {//it's not ready + sprintf(szBuffer,"[ %d: %s ] %s", pAbility->ID, pName, pCDBStr->GetString(pAbility->nName, 4, NULL)); + WriteChatColor(szBuffer,USERCOLOR_WHO); + sprintf(szBuffer,"Min Level: %d, Cost: %d, Max Rank: %d, Type: %d, Reuse Time: %d seconds", + pAbility->MinLevel, pAbility->Cost, pAbility->MaxRank, pAbility->Type, pAltAdvManager->GetCalculatedTimer(pPCData,pAbility)); + WriteChatColor(szBuffer,USERCOLOR_WHO); + if (pAbility->SpellID > 0) + { + sprintf(szBuffer,"Casts Spell: %s", GetSpellNameByID(pAbility->SpellID) ); + WriteChatColor(szBuffer, USERCOLOR_WHO); + } + if (PlayerHasAAAbility(pAbility->Index)) + { + sprintf(szBuffer,"Ready: No (%d seconds until refresh)", i ); + WriteChatColor(szBuffer,USERCOLOR_WHO); + } + else + { + WriteChatColor("Ready: Not Purchased",USERCOLOR_WHO); + } + + } + else + { + sprintf(szBuffer,"[ %d: %s ] %s", pAbility->ID, pName, pCDBStr->GetString(pAbility->nName, 4, NULL) ); + WriteChatColor(szBuffer,USERCOLOR_WHO); + sprintf(szBuffer,"Min Level: %d, Cost: %d, Max Rank: %d, Type: %d, Reuse Time: %d seconds", + pAbility->MinLevel, pAbility->Cost, pAbility->MaxRank, pAbility->Type, pAltAdvManager->GetCalculatedTimer(pPCData,pAbility)); + WriteChatColor(szBuffer,USERCOLOR_WHO); + if (pAbility->SpellID > 0) + { + sprintf(szBuffer,"Casts Spell: %s", GetSpellNameByID(pAbility->SpellID)); + WriteChatColor(szBuffer, USERCOLOR_WHO); + } + sprintf(szBuffer,"Ready: Yes"); + WriteChatColor(szBuffer,USERCOLOR_WHO); + } + } + else + { + pAltAdvManager->IsAbilityReady(pPCData,pAbility,&i); + sprintf(szBuffer,"[ %d: %s ] %s", pAbility->ID, pName, pCDBStr->GetString(pAbility->nName, 4, NULL) ); + WriteChatColor(szBuffer,USERCOLOR_WHO); + sprintf(szBuffer,"Min Level: %d, Cost: %d, Max Rank: %d, Type: %d", + pAbility->MinLevel, pAbility->Cost, pAbility->MaxRank, pAbility->Type); + WriteChatColor(szBuffer,USERCOLOR_WHO); + if (pAbility->SpellID > 0) + { + sprintf(szBuffer,"Casts Spell: %s", GetSpellNameByID(pAbility->SpellID) ); + WriteChatColor(szBuffer, USERCOLOR_WHO); + } + } + } // name matches + } // if pability != null + } //for loop + } + else if (!stricmp(szCommand,"act")) + { + // only search through the ones we have.... + for (unsigned long nAbility=0 ; nAbilityGetAltAbility(pPCData->GetAltAbilityIndex(nAbility)) ) { + if (PCHAR pName=pCDBStr->GetString(pAbility->nName, 1, NULL)) { + if (!stricmp(szName,pName)) { + sprintf(szBuffer,"/alt act %d", pAbility->ID); + DoCommand(pChar,szBuffer); + break; + } + } + } + } + } + else + { + SyntaxError("Usage: /aa list [all|timers|ready], /aa info [ability name], or /aa act [ability name]"); + return; + } + return; +} + +// *************************************************************************** +// Function: Echo +// Description: Our '/echo' command +// Echos text to the chatbox +// Usage: /echo +// *************************************************************************** +VOID Echo(PSPAWNINFO pChar, PCHAR szLine) +{ + CHAR szEcho[MAX_STRING] = {0}; + bRunNextCommand = TRUE; + strcpy(szEcho,DebugHeader); + strcat(szEcho," "); + strncat(szEcho,szLine, MAX_STRING-(strlen(DebugHeader)+2)); + DebugSpewNoFile("Echo - %s",szEcho); + WriteChatColor(szEcho,USERCOLOR_CHAT_CHANNEL); + +} + +// *************************************************************************** +// Function: LootAll +// Description: Our '/lootall' command +// Loots everything on the targeted corpse +// Usage: /lootall +// *************************************************************************** +VOID LootAll(PSPAWNINFO pChar, PCHAR szLine) +{ + pLootWnd->LootAll=1; + pEverQuest->doLoot(); +} +#endif diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2Commands.h b/client_files/native_autoloot/eq-core-dll/src/MQ2Commands.h new file mode 100644 index 0000000000..7bb940fa9d --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2Commands.h @@ -0,0 +1,91 @@ +#pragma once +#if defined(ISXEQ_LEGACY) || !defined(ISXDK_VERSION) +/* COMMANDS */ +LEGACY_API VOID NoModKeyCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID CaptionColorCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID NoParseCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID CaptionCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID HudCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID DropCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID CombineCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID ClearErrorsCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID DeleteVarCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID NewIf (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID DoTimedCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID DoShiftCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID DoCtrlCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID DoAltCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID DoCommandCmd (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID SquelchCommand (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID DumpBindsCommand (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID LoadCfgCommand (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID do_ranged (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID MultilineCommand (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID PluginCommand (PSPAWNINFO pChar, PCHAR szLine); +LEGACY_API VOID Alert (PSPAWNINFO,PCHAR); +LEGACY_API VOID Alias (PSPAWNINFO,PCHAR); +LEGACY_API VOID AltAbility (PSPAWNINFO,PCHAR); +LEGACY_API VOID BankList (PSPAWNINFO,PCHAR); +LEGACY_API VOID Breakin (PSPAWNINFO,PCHAR); +LEGACY_API VOID BuyItem (PSPAWNINFO,PCHAR); +LEGACY_API VOID Call (PSPAWNINFO,PCHAR); +LEGACY_API VOID CharInfo (PSPAWNINFO,PCHAR); +LEGACY_API VOID Cast (PSPAWNINFO,PCHAR); +LEGACY_API VOID Cleanup (PSPAWNINFO,PCHAR); +LEGACY_API VOID Click (PSPAWNINFO,PCHAR); +LEGACY_API VOID DebugSpewFile (PSPAWNINFO,PCHAR); +LEGACY_API VOID DeclareVar (PSPAWNINFO,PCHAR); +LEGACY_API VOID Delay (PSPAWNINFO,PCHAR); +LEGACY_API VOID EQDestroyHeldItemOrMoney (PSPAWNINFO,PCHAR); +LEGACY_API VOID DisplayLoginName (PSPAWNINFO,PCHAR); +LEGACY_API VOID DoAbility (PSPAWNINFO,PCHAR); +LEGACY_API VOID DoEvents (PSPAWNINFO,PCHAR); +LEGACY_API VOID DoSocial (PSPAWNINFO,PCHAR); +LEGACY_API VOID Doors (PSPAWNINFO,PCHAR); +LEGACY_API VOID DoorTarget (PSPAWNINFO,PCHAR); +LEGACY_API VOID DumpStack (PSPAWNINFO,PCHAR); +LEGACY_API VOID Echo (PSPAWNINFO,PCHAR); +LEGACY_API VOID EditMacro (PSPAWNINFO,PCHAR); +LEGACY_API VOID EndMacro (PSPAWNINFO,PCHAR); +LEGACY_API VOID Exec (PSPAWNINFO,PCHAR); +LEGACY_API VOID Face (PSPAWNINFO,PCHAR); +LEGACY_API VOID Filter (PSPAWNINFO,PCHAR); +LEGACY_API VOID For (PSPAWNINFO,PCHAR); +LEGACY_API VOID Goto (PSPAWNINFO,PCHAR); +LEGACY_API VOID Help (PSPAWNINFO,PCHAR); +LEGACY_API VOID Hotkey (PSPAWNINFO,PCHAR); +LEGACY_API VOID Identify (PSPAWNINFO,PCHAR); +LEGACY_API VOID IniOutput (PSPAWNINFO,PCHAR); +LEGACY_API VOID Items (PSPAWNINFO,PCHAR); +LEGACY_API VOID ItemTarget (PSPAWNINFO,PCHAR); +LEGACY_API VOID KeepKeys (PSPAWNINFO,PCHAR); +LEGACY_API VOID WindowState (PSPAWNINFO,PCHAR); +LEGACY_API VOID ListMacros (PSPAWNINFO,PCHAR); +LEGACY_API VOID LoadSpells (PSPAWNINFO,PCHAR); +LEGACY_API VOID Location (PSPAWNINFO,PCHAR); +LEGACY_API VOID Look (PSPAWNINFO,PCHAR); +LEGACY_API VOID LootAll (PSPAWNINFO,PCHAR); +LEGACY_API VOID Macro (PSPAWNINFO,PCHAR); +LEGACY_API VOID MacroBeep (PSPAWNINFO,PCHAR); +LEGACY_API VOID MacroLog (PSPAWNINFO,PCHAR); +LEGACY_API VOID MacroPause (PSPAWNINFO,PCHAR); +LEGACY_API VOID MemSpell (PSPAWNINFO,PCHAR); +LEGACY_API VOID MQMsgBox (PSPAWNINFO,PCHAR); +LEGACY_API VOID Next (PSPAWNINFO,PCHAR); +LEGACY_API VOID Return (PSPAWNINFO,PCHAR); +LEGACY_API VOID SellItem (PSPAWNINFO,PCHAR); +LEGACY_API VOID SetAutoRun (PSPAWNINFO,PCHAR); +LEGACY_API VOID SetError (PSPAWNINFO,PCHAR); +LEGACY_API VOID Skills (PSPAWNINFO,PCHAR); +LEGACY_API VOID Substitute (PSPAWNINFO,PCHAR); +LEGACY_API VOID SuperWho (PSPAWNINFO,PCHAR); +LEGACY_API VOID SuperWhoTarget (PSPAWNINFO,PCHAR); +LEGACY_API VOID SWhoFilter (PSPAWNINFO,PCHAR); +LEGACY_API VOID Target (PSPAWNINFO,PCHAR); +LEGACY_API VOID Unload (PSPAWNINFO,PCHAR); +LEGACY_API VOID UpdateItemInfo (PSPAWNINFO,PCHAR); +LEGACY_API VOID Where (PSPAWNINFO,PCHAR); +LEGACY_API VOID ZapVars (PSPAWNINFO,PCHAR); +LEGACY_API VOID PopupText (PSPAWNINFO,PCHAR); +LEGACY_API VOID PluginCmdSort (VOID); +#endif diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2DInput.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2DInput.cpp new file mode 100644 index 0000000000..8509110243 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2DInput.cpp @@ -0,0 +1,256 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +#error /DCINTERFACE +#endif + +#ifndef ISXEQ +#define DBG_SPEW + +#include "MQ2Main.h" + +// *************************************************************************** +// Function: DInputDataDetour +// Description: Our DirectInput GetDeviceState Hook +// *************************************************************************** + +HRESULT (__stdcall *DInputDataTrampoline)(IDirectInputDevice8A* This, DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags); +HRESULT __stdcall DInputDataDetour(IDirectInputDevice8A* This, DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) +{ + gbInDInput = TRUE; + HRESULT hResult = 0; + PKEYPRESS pNext = NULL; + DWORD didAdd = 0; + BOOL bLoop; + BOOL bRemoveItem = FALSE; + DWORD dwInOutSave = *pdwInOut; + DWORD dwTimeStamp = 0; + DWORD dwSequence = 0; + + + if (!gbUnload) + { + if (EQADDR_DIMOUSE && (This == *EQADDR_DIMOUSE)) + { + // If we are waiting for a click-event to be confirmed by EQ, don't + // pull any data, just return DI_OK and set the pdwInOut value to 0 + if (IsMouseWaitingForButton()) + { + hResult = DI_OK; + *pdwInOut = 0; + gbInDInput = FALSE; + return hResult; + } + + if (EQADDR_MOUSE && gMouseData) { + *pdwInOut = 0; + bLoop = TRUE; + while ((bLoop == TRUE) && (gMouseData)) { + bRemoveItem = TRUE; + if (*pdwInOut < dwInOutSave) { + rgdod[*pdwInOut].dwSequence = dwSequence; + rgdod[*pdwInOut].dwTimeStamp = dwTimeStamp; + rgdod[0].uAppData = 0; + switch (gMouseData->mdType) { + case MD_Button0Click: + DebugSpew("Trying to click left button."); + rgdod[*pdwInOut].dwData = 0x80; + rgdod[*pdwInOut].dwOfs = DIMOFS_BUTTON0; + gMouseData->mdType = MD_Button0; + gMouseData->dwData = 0x00; + bRemoveItem = FALSE; + bLoop = FALSE; + (*pdwInOut)++; + break; + case MD_Button1Click: + DebugSpew("Trying to click right button."); + rgdod[*pdwInOut].dwData = 0x80; + rgdod[*pdwInOut].dwOfs = DIMOFS_BUTTON1; + gMouseData->mdType = MD_Button1; + gMouseData->dwData = 0x00; + bRemoveItem = FALSE; + bLoop = FALSE; + (*pdwInOut)++; + break; + case MD_Button0: + rgdod[*pdwInOut].dwData = gMouseData->dwData; + rgdod[*pdwInOut].dwOfs = DIMOFS_BUTTON0; + (*pdwInOut)++; + break; + case MD_Button1: + rgdod[*pdwInOut].dwData = gMouseData->dwData; + rgdod[*pdwInOut].dwOfs = DIMOFS_BUTTON1; + (*pdwInOut)++; + break; + case MD_Unknown: + break; + } + if (bRemoveItem==TRUE) { + PMOUSESPOOF pTemp = gMouseData; + gMouseData = gMouseData->pNext; + free(pTemp); + } + } else { + bLoop = FALSE; + } + } + gbInDInput = FALSE; + return (HRESULT)DI_OK; + } + } + } + // If we didn't add any keyboard data, and we aren't waiting for a click, + // and we didn't add any mouse data + hResult = DInputDataTrampoline(This, cbObjectData, rgdod, pdwInOut, dwFlags); + if (gbUnload) { + gbInDInput = FALSE; + return hResult; + } + + gbInDInput = FALSE; + return hResult; +} + +HRESULT (__stdcall *DInputStateTrampoline)(IDirectInputDevice8A* This, DWORD cbData, LPVOID lpvData); +HRESULT __stdcall DInputStateDetour(IDirectInputDevice8A* This, DWORD cbData, LPVOID lpvData) +{ + HRESULT hResult = S_OK; + DWORD dwBuffSize = 0; + BOOL bOneTime = FALSE; + + gbInDState = TRUE; + hResult = DInputStateTrampoline(This, cbData, lpvData); + // We could alter the return here if so desired, if a macro is executing that requires keyboard and mouse input. + // by setting hResult to DI_OK; + if (hResult == DIERR_INPUTLOST || hResult == DIERR_NOTACQUIRED) + { + bDetMouse = FALSE; + } + if (gbUnload) { + gbInDState = FALSE; + return hResult; + } + if ((cbData == sizeof(DIMOUSESTATE)) || (cbData == sizeof(DIMOUSESTATE2))) + { + if(IsMouseWaitingForButton() && (EQADDR_MOUSECLICK)) + { + ((LPDIMOUSESTATE)lpvData)->rgbButtons[0] = EQADDR_MOUSECLICK->Click[0]; + ((LPDIMOUSESTATE)lpvData)->rgbButtons[1] = EQADDR_MOUSECLICK->Click[1]; + } + } + + gbInDState = FALSE; + return hResult; +} + +HRESULT (__stdcall *DInputAcquireTrampoline)(IDirectInputDevice8A* This); +HRESULT __stdcall DInputAcquireDetour(IDirectInputDevice8A* This) +{ + HRESULT hResult = S_OK; + DWORD dwBuffSize = 0; + + gbInDAcquire = TRUE; + hResult = DInputAcquireTrampoline(This); + // Could alter the return here to allow background macro execution with keyboard and mouse input + if (hResult != DI_OK && hResult != S_FALSE) // Mouse wasn't acquired successfully + { + bDetMouse = FALSE; + } + if (gbUnload) { + gbInDAcquire = FALSE; + return hResult; + } + gbInDAcquire = FALSE; + return hResult; +} + + + +// externals from EQLib_Main.cpp +extern HRESULT (__stdcall *DInputDataTrampoline)(IDirectInputDevice8A* This, DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags); +extern HRESULT __stdcall DInputDataDetour(IDirectInputDevice8A* This, DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags); +extern HRESULT (__stdcall *DInputStateTrampoline)(IDirectInputDevice8A* This, DWORD cbData, LPVOID lpvData); +extern HRESULT __stdcall DInputStateDetour(IDirectInputDevice8A* This, DWORD cbData, LPVOID lpvData); +extern HRESULT (__stdcall *DInputAcquireTrampoline)(IDirectInputDevice8A* This); +extern HRESULT __stdcall DInputAcquireDetour(IDirectInputDevice8A* This); + +DWORD GetDeviceData=0; +DWORD GetDeviceState=0; +DWORD Acquire=0; + +VOID InitializeMQ2DInput() +{ + DebugSpew("Initializing DInput"); + IDirectInputDevice8A *IDIDevice = NULL; + IDirectInputDevice8A *IDIMouse = NULL; + // Keyboard patching + if ((EQADDR_DIKEYBOARD) && (*EQADDR_DIKEYBOARD) && (EQADDR_DIMOUSE) && (*EQADDR_DIMOUSE)) + { + IDIDevice = *EQADDR_DIKEYBOARD; + IDIMouse = *EQADDR_DIMOUSE; + if ((unsigned int)IDIDevice->lpVtbl->GetDeviceData == (unsigned int)IDIMouse->lpVtbl->GetDeviceData) + DebugSpew("Mouse and Keyboard have same GetDeviceData"); + if ((unsigned int)IDIDevice->lpVtbl->GetDeviceState == (unsigned int)IDIMouse->lpVtbl->GetDeviceState) + DebugSpew("Mouse and Keyboard have same GetDeviceState"); + if ((unsigned int)IDIDevice->lpVtbl->Acquire == (unsigned int)IDIMouse->lpVtbl->Acquire) + DebugSpew("Mouse and Keyboard have same Acquire"); + } + if ((EQADDR_DIKEYBOARD) && (*EQADDR_DIKEYBOARD)) { + IDIDevice = *EQADDR_DIKEYBOARD; + AddDetour(GetDeviceData=(unsigned int) IDIDevice->lpVtbl->GetDeviceData); + AddDetour(GetDeviceState=(unsigned int) IDIDevice->lpVtbl->GetDeviceState); + AddDetour(Acquire=(unsigned int) IDIDevice->lpVtbl->Acquire); + + //Grab GetDeviceData + (*(PBYTE*)&DInputDataTrampoline) = DetourFunction((PBYTE)GetDeviceData, + (PBYTE)DInputDataDetour); + //Grab GetDeviceState + (*(PBYTE*)&DInputStateTrampoline) = DetourFunction((PBYTE)GetDeviceState, + (PBYTE)DInputStateDetour); + //Grab Acquire + (*(PBYTE*)&DInputAcquireTrampoline) = DetourFunction((PBYTE)Acquire, + (PBYTE)DInputAcquireDetour); + } +} + +VOID ShutdownMQ2DInput() +{ + if (DetourRemove((PBYTE)DInputDataTrampoline, + (PBYTE)DInputDataDetour)) + { + RemoveDetour(GetDeviceData); + DInputDataTrampoline = NULL; + } + else + DebugSpewAlways("Failed to unhook DInputData"); + if (DetourRemove((PBYTE)DInputStateTrampoline, + (PBYTE)DInputStateDetour)) + { + RemoveDetour(GetDeviceState); + DInputStateTrampoline = NULL; + } + else + DebugSpewAlways("Failed to unhook DInputState"); + if (DetourRemove((PBYTE)DInputAcquireTrampoline, + (PBYTE)DInputAcquireDetour)) + { + RemoveDetour(Acquire); + DInputAcquireTrampoline = NULL; + } + else + DebugSpewAlways("Failed to unhook DInputAcquire"); +} + +#endif diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2Data.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2Data.cpp new file mode 100644 index 0000000000..f90363617c --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2Data.cpp @@ -0,0 +1,1521 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +//#error /DCINTERFACE +#endif + +#define DBG_SPEW + +#ifdef ISXEQ +#define ISINDEX() (argc>0) +#define ISNUMBER() (IsNumber(argv[0])) +#define GETNUMBER() (atoi(argv[0])) +#define GETFIRST() argv[0] +#else +#define ISINDEX() (szIndex[0]) +#define ISNUMBER() (IsNumber(szIndex)) +#define GETNUMBER() (atoi(szIndex)) +#define GETFIRST() szIndex +#endif + +#include "MQ2Main.h" +#ifndef ISXEQ +#define TLO(funcname) BOOL funcname(PCHAR szIndex, MQ2TYPEVAR &Ret) +#else +#define TLO(funcname) bool funcname(int argc, char *argv[], LSTYPEVAR &Ret) +#endif + + +TLO(dataSpawn) +{ + if (ISINDEX()) + { + if (ISNUMBER()) + { + if (Ret.Ptr=GetSpawnByID(GETNUMBER())) + { + Ret.Type=pSpawnType; + return true; + } + } + else + { + // set up search spawn + SEARCHSPAWN ssSpawn; + ClearSearchSpawn(&ssSpawn); +#ifndef ISXEQ + ParseSearchSpawn(szIndex,&ssSpawn); +#else + ParseSearchSpawn(0,argc,argv,ssSpawn); +#endif + if (Ret.Ptr=SearchThroughSpawns(&ssSpawn,(PSPAWNINFO)pCharSpawn)) + { + Ret.Type=pSpawnType; + return true; + } + } + } + // No spawn + + return false; +} + +#ifndef ISXEQ +TLO(dataSelect) +{ + if (!szIndex[0]) + return false; + + // I hate this GetArg shit - Lax + CHAR szArg[MAX_STRING] = {0}; + CHAR szArg1[MAX_STRING] = {0}; + int N=2; + GetArg(szArg1,szIndex,1,FALSE,FALSE,TRUE); + while (1) + { + GetArg(szArg,szIndex,N,FALSE,FALSE,TRUE); + N++; + if (!szArg[0]) + { + Ret.DWord=0; + Ret.Type=pIntType; + return true; + } + if (!stricmp(szArg1,szArg)) + { + Ret.DWord=N-2; + Ret.Type=pIntType; + return true; + } + } +} +#endif + +TLO(dataTarget) +{ + if (pTarget) + { + Ret.Ptr=pTarget; + Ret.Type=pTargetType; + return true; + } + return false; +} + +TLO(dataCharacter) +{ + if (pCharData) + { + Ret.Ptr=pCharData; + Ret.Type=pCharacterType; + return true; + } + return false; +} + +TLO(dataSpell) +{ + if (ISINDEX()) + { + if (ISNUMBER()) + { + if (Ret.Ptr=GetSpellByID(GETNUMBER())) + { + Ret.Type=pSpellType; + return true; + } + } + else + { + if (Ret.Ptr=GetSpellByName(GETFIRST())) + { + Ret.Type=pSpellType; + return true; + } + } + } + return false; +} + +TLO(dataSwitch) +{ + if (pDoorTarget) + { + Ret.Ptr=pDoorTarget; + Ret.Type=pSwitchType; + return true; + } + return false; +} + +TLO(dataGroundItem) +{ + if (pGroundTarget) + { + Ret.Ptr=pGroundTarget; + Ret.Type=pGroundType; + return true; + } + return false; +} + +TLO(dataMerchant) +{ + if (pActiveMerchant) + { + Ret.Ptr=pActiveMerchant; + Ret.Type=pMerchantType; + return true; + } + return false; +} + +TLO(dataCorpse) +{ + if (pLootWnd) + { + Ret.Ptr=pLootWnd; + Ret.Type=pCorpseType; + return true; + } + return false; +} + +TLO(dataWindow) +{ + return false; +} + +#ifndef ISXEQ +TLO(dataMacro) +{ + if (gRunning) + { + Ret.Ptr=0; + Ret.Type=pMacroType; + return true; + } + return false; +} +#endif + +TLO(dataMacroQuest) +{ + Ret.Ptr=0; + Ret.Type=pMacroQuestType; + return true; +} +#ifndef ISXEQ +TLO(dataMath) +{ + Ret.Ptr=0; + Ret.Type=pMathType; + return true; +} +#endif + +TLO(dataZone) +{ + int nIndex=0; + PZONELIST pZone = NULL; + + if (!ISINDEX()) + { + Ret.DWord = instEQZoneInfo; + Ret.Type=pCurrentZoneType; + return true; + } + else if (ISNUMBER()) + { + if (nIndex = GETNUMBER()) + { + if (GetCharInfo()->zoneId==nIndex) + { + Ret.DWord = instEQZoneInfo; + Ret.Type=pCurrentZoneType; + } + else + { + Ret.Ptr = ((PWORLDDATA)pWorldData)->ZoneArray[nIndex]; + Ret.Type=pZoneType; + } + return true; + } + } + else if (-1 != (nIndex=GetZoneID(GETFIRST()))) + { + if (GetCharInfo()->zoneId==nIndex) + { + Ret.DWord = instEQZoneInfo; + Ret.Type=pCurrentZoneType; + } + else + { + Ret.Ptr = ((PWORLDDATA)pWorldData)->ZoneArray[nIndex]; + Ret.Type=pZoneType; + } + return true; + } + return false; +} + + +#ifndef ISXEQ +TLO(dataInt) +{ + if (!ISINDEX()) + return false; + Ret.DWord=atol(szIndex); + Ret.Type=pIntType; + return true; +} + +TLO(dataString) +{ + WriteChatf("Due to complete misuse of the String Top-Level Object, it has been removed."); + return false; + /* + if (!ISINDEX()) + return false; + strcpy(DataTypeTemp,szIndex); + Ret.Ptr=&DataTypeTemp[0]; + Ret.Type=pStringType; + return true; + /**/ +} + +TLO(dataFloat) +{ + if (!ISINDEX()) + return false; + Ret.Float=(FLOAT)atof(szIndex); + Ret.Type=pFloatType; + return true; +} +#endif + +TLO(dataHeading) +{ +#ifndef ISXEQ + if (!ISINDEX()) + return false; + if (PCHAR pComma=strchr(szIndex,',')) + { + *pComma=0; + FLOAT Y=(FLOAT)atof(szIndex); + *pComma=','; + FLOAT X=(FLOAT)atof(&pComma[1]); + Ret.Float=(FLOAT)(atan2f(((PSPAWNINFO)pCharSpawn)->Y - Y, X - ((PSPAWNINFO)pCharSpawn)->X) * 180.0f / PI + 90.0f); + if (Ret.Float<0.0f) + Ret.Float += 360.0f; + else if (Ret.Float>=360.0f) + Ret.Float -= 360.0f; + Ret.Type=pHeadingType; + return true; + } + + Ret.Float=(FLOAT)atof(szIndex); + Ret.Type=pHeadingType; + return true; +#else + if (!argc) + return false; + if (argc==2) + { + FLOAT Y=(FLOAT)atof(argv[0]); + FLOAT X=(FLOAT)atof(argv[1]); + Ret.Float=(FLOAT)(atan2f(((PSPAWNINFO)pCharSpawn)->Y - Y, X - ((PSPAWNINFO)pCharSpawn)->X) * 180.0f / PI + 90.0f); + if (Ret.Float<0.0f) + Ret.Float += 360.0f; + else if (Ret.Float>=360.0f) + Ret.Float -= 360.0f; + Ret.Type=pHeadingType; + return true; + } + + Ret.Float=(FLOAT)atof(argv[0]); + Ret.Type=pHeadingType; + return true; +#endif +} + + +#ifndef ISXEQ +TLO(dataBool) +{ + if (!ISINDEX()) + return false; + Ret.DWord=(stricmp(szIndex,"NULL") && + stricmp(szIndex,"FALSE") && + strcmp(szIndex,"0")); + Ret.Type=pBoolType; + return true; +} +#endif +/* +TLO(dataGroupLeader) +{ + if (!GroupLeader[0] || !stricmp(GroupLeader,GetCharInfo()->pSpawn->Name)) + { + Ret.Ptr=GetCharInfo()->pSpawn; + Ret.Type=pSpawnType; + return true; + } + for (unsigned long N = 0 ; N < 5 ; N++) + { + if (EQADDR_GROUPCOUNT[N]) + { + if (PSPAWNINFO pSpawn=(PSPAWNINFO)ppGroup[N]) + { + if (!stricmp(pSpawn->Name,GroupLeader)) + { + Ret.Ptr=pSpawn; + Ret.Type=pSpawnType; + return true; + } + } + } + } + return false; +} +/**/ +/* +TLO(dataGroupLeaderName) +{ + if (!GroupLeader[0]) + { + Ret.Ptr=GetCharInfo()->pSpawn->Name; + Ret.Type=pStringType; + return true; + } + Ret.Ptr=&GroupLeader[0]; + Ret.Type=pStringType; + return true; +} +/**/ + +TLO(dataGroup) +{ + Ret.DWord=1; + Ret.Type=pGroupType; + return true; +/* + if (ISINDEX()) + { + DWORD N=GETNUMBER(); + if (N==0) + { +#ifndef ISXEQ + return dataCharacter("",Ret); +#else + return dataCharacter(0,0,Ret); +#endif + } + if (N>5) + return false; + for (unsigned long i=0; i<5 ; i++) + { + if (EQADDR_GROUPCOUNT[i]) + { + N--; + if (N==0) + { + Ret.Ptr=ppGroup[i]; + Ret.Type=pSpawnType; + return true; + } + } + } + return false; + } + else + { + Ret.DWord=0; + for (int index=0;index<5;index++) + if (EQADDR_GROUPCOUNT[index]) + Ret.DWord++; + Ret.Type=pIntType; + return true; + } + return false; + /**/ +} +#ifndef ISXEQ +TLO(dataIf) +{ + if (ISINDEX()) + { + // condition, whentrue, whenfalse + if (PCHAR pTrue=strchr(szIndex,',')) + { + *pTrue=0; + pTrue++; + if (PCHAR pFalse=strchr(pTrue,',')) + { + *pFalse=0; + pFalse++; + DOUBLE CalcResult; + if (!Calculate(szIndex,CalcResult)) + return false; + + if (CalcResult!=0.0f) + { + strcpy(DataTypeTemp,pTrue); + Ret.Ptr=&DataTypeTemp[0]; + Ret.Type=pStringType; + return true; + } + else + { + strcpy(DataTypeTemp,pFalse); + Ret.Ptr=&DataTypeTemp[0]; + Ret.Type=pStringType; + return true; + } + } + } + } + return false; +} +#endif +TLO(dataCursor) +{ + if (Ret.Ptr=GetCharInfo2()->pInventoryArray->Inventory.Cursor) + { + Ret.Type=pItemType; + return true; + } + return false; +} + +TLO(dataLastSpawn) +{ + if (ISINDEX()) + { + if (GETFIRST()[0]=='-') + { + unsigned long N=atoi(&GETFIRST()[1])-1; + if (PSPAWNINFO pSpawn=(PSPAWNINFO)pLocalPlayer) + { + while(N) + { + pSpawn=pSpawn->pPrev; + if (!pSpawn) + return false; + N--; + } + Ret.Ptr=pSpawn; + Ret.Type=pSpawnType; + return true; + } + } + else if (ISNUMBER()) + { + unsigned long N=GETNUMBER()-1; + if (PSPAWNINFO pSpawn=(PSPAWNINFO)pSpawnList) + { + while(N) + { + pSpawn=pSpawn->pNext; + if (!pSpawn) + return false; + N--; + } + Ret.Ptr=pSpawn; + Ret.Type=pSpawnType; + return true; + } + } + } + else + { + Ret.Ptr=pSpawnList; + Ret.Type=pSpawnType; + return true; + } + return false; +} + +TLO(dataNearestSpawn) +{ + if (ISINDEX()) + { + unsigned long nth; + SEARCHSPAWN ssSpawn; + ClearSearchSpawn(&ssSpawn); + ssSpawn.FRadius=999999.0f; +#ifndef ISXEQ + PCHAR pSearch; + if (pSearch=strchr(szIndex,',')) + { + *pSearch=0; + ++pSearch; + ParseSearchSpawn(pSearch,&ssSpawn); + nth=GETNUMBER(); + } + else + { + if (IsNumberToComma(szIndex)) + { + nth=GETNUMBER(); + } + else + { + nth=1; + ParseSearchSpawn(szIndex,&ssSpawn); + } + } +#else + if (!ISNUMBER()) { + nth=1; + ParseSearchSpawn(0,argc,argv,ssSpawn); + } else { + nth=GETNUMBER(); + ParseSearchSpawn(1,argc,argv,ssSpawn); + } +#endif + for (unsigned long N = 0 ; N < gSpawnCount ; N++) + { + if (EQP_DistArray[N].Value.Float>ssSpawn.FRadius && !ssSpawn.bKnownLocation) + return false; + if (SpawnMatchesSearch(&ssSpawn,(PSPAWNINFO)pCharSpawn,(PSPAWNINFO)EQP_DistArray[N].VarPtr.Ptr)) + { + if (--nth==0) + { + Ret.Ptr=EQP_DistArray[N].VarPtr.Ptr; + Ret.Type=pSpawnType; + return true; + } + } + } + } + // No spawn + return false; +} + +TLO(dataSpawnCount) +{ + if (ISINDEX()) + { + SEARCHSPAWN ssSpawn; + ClearSearchSpawn(&ssSpawn); +#ifndef ISXEQ + ParseSearchSpawn(szIndex,&ssSpawn); +#else + ParseSearchSpawn(0,argc,argv,ssSpawn); +#endif + Ret.DWord=CountMatchingSpawns(&ssSpawn,GetCharInfo()->pSpawn,TRUE); + Ret.Type=pIntType; + return true; + } + else + { + Ret.DWord=gSpawnCount; + Ret.Type=pIntType; + return true; + } +} + +TLO(dataTime) +{ + time_t CurTime; + time(&CurTime); + Ret.Ptr= localtime( &CurTime ); + Ret.Type=pTimeType; + return true; +} +TLO(dataGameTime) +{ + struct tm* pTime=(struct tm*)&DataTypeTemp[0]; + ZeroMemory(pTime,sizeof(struct tm)); + pTime->tm_mday=((PWORLDDATA)pWorldData)->Day; + pTime->tm_hour=((PWORLDDATA)pWorldData)->Hour-1; + pTime->tm_min=((PWORLDDATA)pWorldData)->Minute; + pTime->tm_mon=((PWORLDDATA)pWorldData)->Month; + pTime->tm_year=((PWORLDDATA)pWorldData)->Year-1900; + Ret.Ptr=pTime; + Ret.Type=pTimeType; + return true; +} + +TLO(dataIni) +{ +#ifndef ISXEQ /* CONVERT */ + PCHAR pIniFile=0; + PCHAR pSection=0; + PCHAR pKey=0; + PCHAR pDefault=""; + if (pIniFile=strtok(szIndex,",")) + { + if (pSection=strtok(NULL,",")) + { + if (!strcmp(pSection,"-1")) + pSection=0; + if (pKey=strtok(NULL,",")) + { + if (!strcmp(pKey,"-1")) + pKey=0; + pDefault=strtok(NULL,"\xA6"); + if (!pDefault) + pDefault=""; + } + } + } + else + return false; + CHAR FileName[MAX_STRING]={0}; + + PCHAR pTemp=pIniFile; + while(pTemp[0]) + { + if (pTemp[0]=='/') + pTemp[0]='\\'; + pTemp++; + } + + if (pIniFile[0]!='\\' && !strchr(pIniFile,':')) + sprintf(FileName,"%s\\%s",gszMacroPath,pIniFile); + else + strcpy(FileName,pIniFile); + + if (!strchr(pIniFile,'.')) + strcat(FileName,".ini"); + + if (!_FileExists(FileName)) + { + if (pDefault[0]) + { + strcpy(DataTypeTemp,pDefault); + Ret.Ptr=&DataTypeTemp[0]; + Ret.Type=pStringType; + return true; + } + return false; + } + + if (DWORD nSize=GetPrivateProfileString(pSection,pKey,pDefault,DataTypeTemp,MAX_STRING,FileName)) + { + if (nSize>2) + for (unsigned long N = 0 ; N < nSize-2 ; N++) + if (DataTypeTemp[N]==0) + DataTypeTemp[N]='|'; + if ((!pSection || !pKey) && (nSizepSelectedItem && ((PEQINVSLOTMGR)pInvSlotMgr)->pSelectedItem->InvSlot) + { + class CInvSlot *pCIS = NULL; + struct _CONTENTS *pC = NULL; + + pCIS = (class CInvSlot *) ((PEQINVSLOTMGR)pInvSlotMgr)->pSelectedItem; + pCIS->GetItemBase(&pC); + + if (pC) { + Ret.Ptr = pC; + Ret.Type=pItemType; + return true; + } + } + return false; +} + +TLO(dataFindItemBank) +{ + if (!ISINDEX()) + return false; + DWORD N=1; + PCHAR pName=GETFIRST(); + BOOL bExact=false; + + if (*pName=='=') + { + bExact=true; + pName++; + } + CHAR Name[MAX_STRING]={0}; + CHAR Temp[MAX_STRING]={0}; + strlwr(strcpy(Name,pName)); + PCHARINFO pCharInfo=GetCharInfo(); + unsigned long nPack; + + + for (nPack=0 ; nPack < NUM_BANK_SLOTS ; nPack++) + { + PCHARINFO pCharInfo=GetCharInfo(); + PCONTENTS pPack; + + if (pCharInfo->pBankArray && (pPack=pCharInfo->pBankArray->Bank[nPack])) + { + if (bExact) + { + if (!stricmp(Name,GetItemFromContents(pPack)->Name)) + { + Ret.Ptr=pPack; + Ret.Type=pItemType; + return true; + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pPack)->Name)),Name)) + { + Ret.Ptr=pPack; + Ret.Type=pItemType; + return true; + } + } + if (GetItemFromContents(pPack)->Type==ITEMTYPE_PACK && pPack->pContentsArray) + { + for (unsigned long nItem=0 ; nItem < GetItemFromContents(pPack)->Slots ; nItem++) + { + PCONTENTS pItem; + if (pPack->pContentsArray && (pItem=pPack->pContentsArray->Contents[nItem])) + { + if (bExact) + { + if (!stricmp(Name,GetItemFromContents(pItem)->Name)) + { + Ret.Ptr=pItem; + Ret.Type=pItemType; + return true; + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pItem)->Name)),Name)) + { + Ret.Ptr=pItem; + Ret.Type=pItemType; + return true; + } + } + } + } + } + } + } + for (nPack=0 ; nPack < NUM_SHAREDBANK_SLOTS ; nPack++) + { + PCHARINFO pCharInfo=GetCharInfo(); + PCONTENTS pPack; + if (pCharInfo->pSharedBankArray && (pPack=pCharInfo->pSharedBankArray->SharedBank[nPack])) + { + if (bExact) + { + if (!stricmp(Name,GetItemFromContents(pPack)->Name)) + { + Ret.Ptr=pPack; + Ret.Type=pItemType; + return true; + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pPack)->Name)),Name)) + { + Ret.Ptr=pPack; + Ret.Type=pItemType; + return true; + } + } + if (GetItemFromContents(pPack)->Type==ITEMTYPE_PACK && pPack->pContentsArray) + { + for (unsigned long nItem=0 ; nItem < GetItemFromContents(pPack)->Slots ; nItem++) + { + PCONTENTS pItem; + if (pPack->pContentsArray && (pItem=pPack->pContentsArray->Contents[nItem])) + { + if (bExact) + { + if (!stricmp(Name,GetItemFromContents(pItem)->Name)) + { + Ret.Ptr=pItem; + Ret.Type=pItemType; + return true; + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pItem)->Name)),Name)) + { + Ret.Ptr=pItem; + Ret.Type=pItemType; + return true; + } + } + } + } + } + } + } + + + return false; +} + +TLO(dataFindItem) +{ + if (!ISINDEX()) + return false; + DWORD N=1; + PCHAR pName=GETFIRST(); + BOOL bExact=false; + + if (*pName=='=') + { + bExact=true; + pName++; + } + CHAR Name[MAX_STRING]={0}; + CHAR Temp[MAX_STRING]={0}; + strlwr(strcpy(Name,pName)); + PCHARINFO pCharInfo=GetCharInfo(); + + for (unsigned long nSlot=0 ; nSlot < NUM_INV_SLOTS ; nSlot++) + { + if (PCONTENTS pItem=GetCharInfo2()->pInventoryArray->InventoryArray[nSlot]) + { + if (bExact) + { + if (!stricmp(Name,GetItemFromContents(pItem)->Name)) + { + Ret.Ptr=pItem; + Ret.Type=pItemType; + return true; + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pItem)->Name)),Name)) + { + Ret.Ptr=pItem; + Ret.Type=pItemType; + return true; + } + } + } + } + + for (unsigned long nPack=0 ; nPack < 10 ; nPack++) + { + if (PCONTENTS pPack=GetCharInfo2()->pInventoryArray->Inventory.Pack[nPack]) + { + if (GetItemFromContents(pPack)->Type==ITEMTYPE_PACK && pPack->pContentsArray) + { + for (unsigned long nItem=0 ; nItem < GetItemFromContents(pPack)->Slots ; nItem++) + { + if (PCONTENTS pItem=pPack->pContentsArray->Contents[nItem]) + { + if (bExact) + { + if (!stricmp(Name,GetItemFromContents(pItem)->Name)) + { + Ret.Ptr=pItem; + Ret.Type=pItemType; + return true; + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pItem)->Name)),Name)) + { + Ret.Ptr=pItem; + Ret.Type=pItemType; + return true; + } + } + } + } + } + } + } + + return false; +} + +TLO(dataFindItemCount) +{ + if (!ISINDEX()) + return false; + DWORD N=1; + PCHAR pName=GETFIRST(); + BOOL bExact=false; + + if (*pName=='=') + { + bExact=true; + pName++; + } + CHAR Name[MAX_STRING]={0}; + CHAR Temp[MAX_STRING]={0}; + strlwr(strcpy(Name,pName)); + PCHARINFO pCharInfo=GetCharInfo(); + + unsigned long Count=0; + DWORD nAug = 0; + + for (unsigned long nSlot=0 ; nSlot < NUM_INV_SLOTS ; nSlot++) + { + if (PCONTENTS pItem=GetCharInfo2()->pInventoryArray->InventoryArray[nSlot]) + { + if (bExact) + { + if (!stricmp(Name,GetItemFromContents(pItem)->Name)) + { + if ((GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) || + (((EQ_Item*)pItem)->IsStackable() != 1)) + Count++; + else + Count+=pItem->StackCount; + } + else // for augs + { + if (pItem->pContentsArray && pItem->NumOfSlots2) + for(nAug = 0; nAug < pItem->NumOfSlots2; nAug++) + { + if(pItem->pContentsArray->Contents[nAug] && GetItemFromContents(pItem->pContentsArray->Contents[nAug])->Type == ITEMTYPE_NORMAL && GetItemFromContents(pItem->pContentsArray->Contents[nAug])->AugType && + !stricmp(Name, GetItemFromContents(pItem->pContentsArray->Contents[nAug])->Name)) + Count++; + } + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pItem)->Name)),Name)) + { + if ((GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) || + (((EQ_Item*)pItem)->IsStackable() != 1)) + Count++; + else + Count+=pItem->StackCount; + } + else // for augs + { + if (pItem->pContentsArray && pItem->NumOfSlots2 ) + for(nAug = 0; nAug < pItem->NumOfSlots2; nAug++) + { + if(pItem->pContentsArray->Contents[nAug] && GetItemFromContents(pItem->pContentsArray->Contents[nAug])->Type == ITEMTYPE_NORMAL && GetItemFromContents(pItem->pContentsArray->Contents[nAug])->AugType && + strstr(strlwr(strcpy(Temp, GetItemFromContents(pItem->pContentsArray->Contents[nAug])->Name)), Name)) + Count++; + } + } + } + } + } + + for (unsigned long nPack=0 ; nPack < 10 ; nPack++) + { + if (PCONTENTS pPack=GetCharInfo2()->pInventoryArray->Inventory.Pack[nPack]) + { + if (GetItemFromContents(pPack)->Type==ITEMTYPE_PACK && pPack->pContentsArray) + { + for (unsigned long nItem=0 ; nItem < GetItemFromContents(pPack)->Slots ; nItem++) + { + if (PCONTENTS pItem=pPack->pContentsArray->Contents[nItem]) + { + if (bExact) + { + if (!stricmp(Name,GetItemFromContents(pItem)->Name)) + { + if ((GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) || + (((EQ_Item*)pItem)->IsStackable() != 1)) + Count++; + else + Count+=pItem->StackCount; + } + else // for augs + { + if (pItem->pContentsArray && pItem->NumOfSlots2) + for(nAug = 0; nAug < pItem->NumOfSlots2; nAug++) + { + if(pItem->pContentsArray->Contents[nAug] && GetItemFromContents(pItem->pContentsArray->Contents[nAug])->Type == ITEMTYPE_NORMAL && GetItemFromContents(pItem->pContentsArray->Contents[nAug])->AugType && + !stricmp(Name, GetItemFromContents(pItem->pContentsArray->Contents[nAug])->Name)) + Count++; + } + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pItem)->Name)),Name)) + { + if ((GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) || + (((EQ_Item*)pItem)->IsStackable() != 1)) + Count++; + else + Count+=pItem->StackCount; + } + else // for augs + { + if (pItem->pContentsArray && pItem->NumOfSlots2) + for(nAug = 0; nAug < pItem->NumOfSlots2; nAug++) + { + if(pItem->pContentsArray->Contents[nAug] && GetItemFromContents(pItem->pContentsArray->Contents[nAug])->Type == ITEMTYPE_NORMAL && GetItemFromContents(pItem->pContentsArray->Contents[nAug])->AugType && + strstr(strlwr(strcpy(Temp, GetItemFromContents(pItem->pContentsArray->Contents[nAug])->Name)), Name)) + Count++; + } + } + } + } + } + } + } + } + + Ret.DWord=Count; + Ret.Type=pIntType; + + return true; +} + +TLO(dataFindItemBankCount) +{ + if (!ISINDEX()) + return false; + DWORD N=1; + PCHAR pName=GETFIRST(); + BOOL bExact=false; + + if (*pName=='=') + { + bExact=true; + pName++; + } + CHAR Name[MAX_STRING]={0}; + CHAR Temp[MAX_STRING]={0}; + strlwr(strcpy(Name,pName)); + PCHARINFO pCharInfo=GetCharInfo(); + + unsigned long Count=0; + unsigned long nPack=0; + + for (nPack=0 ; nPack < NUM_BANK_SLOTS ; nPack++) + { + PCHARINFO pCharInfo=GetCharInfo(); + if (PCONTENTS pPack=pCharInfo->pBankArray->Bank[nPack]) + { + if (bExact) + { + if (!stricmp(Name,GetItemFromContents(pPack)->Name)) + { + if ((GetItemFromContents(pPack)->Type != ITEMTYPE_NORMAL) || + (((EQ_Item*)pPack)->IsStackable() != 1)) + Count++; + else + Count+=pPack->StackCount; + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pPack)->Name)),Name)) + { + if ((GetItemFromContents(pPack)->Type != ITEMTYPE_NORMAL) || + (((EQ_Item*)pPack)->IsStackable() != 1)) + Count++; + else + Count+=pPack->StackCount; + } + } + if (GetItemFromContents(pPack)->Type==ITEMTYPE_PACK && pPack->pContentsArray) + { + for (unsigned long nItem=0 ; nItem < GetItemFromContents(pPack)->Slots ; nItem++) + { + if (PCONTENTS pItem=pPack->pContentsArray->Contents[nItem]) + { + if (bExact) + { + if (!stricmp(Name,GetItemFromContents(pItem)->Name)) + { + if ((GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) || + (((EQ_Item*)pItem)->IsStackable() != 1)) + Count++; + else + Count+=pItem->StackCount; + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pItem)->Name)),Name)) + { + if ((GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) || + (((EQ_Item*)pItem)->IsStackable() != 1)) + Count++; + else + Count+=pItem->StackCount; + } + } + } + } + } + } + } + for (nPack=0 ; nPack < NUM_SHAREDBANK_SLOTS ; nPack++) + { + PCHARINFO pCharInfo=GetCharInfo(); + if (PCONTENTS pPack=pCharInfo->pSharedBankArray->SharedBank[nPack]) + { + if (bExact) + { + if (!stricmp(Name,GetItemFromContents(pPack)->Name)) + { + if ((GetItemFromContents(pPack)->Type != ITEMTYPE_NORMAL) || + (((EQ_Item*)pPack)->IsStackable() != 1)) + Count++; + else + Count+=pPack->StackCount; + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pPack)->Name)),Name)) + { + if ((GetItemFromContents(pPack)->Type != ITEMTYPE_NORMAL) || + (((EQ_Item*)pPack)->IsStackable() != 1)) + Count++; + else + Count+=pPack->StackCount; + } + } + if (GetItemFromContents(pPack)->Type==ITEMTYPE_PACK && pPack->pContentsArray) + { + for (unsigned long nItem=0 ; nItem < GetItemFromContents(pPack)->Slots ; nItem++) + { + if (PCONTENTS pItem=pPack->pContentsArray->Contents[nItem]) + { + if (bExact) + { + if (!stricmp(Name,GetItemFromContents(pItem)->Name)) + { + if ((GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) || + (((EQ_Item*)pItem)->IsStackable() != 1)) + Count++; + else + Count+=pItem->StackCount; + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pItem)->Name)),Name)) + { + if ((GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) || + (((EQ_Item*)pItem)->IsStackable() != 1)) + Count++; + else + Count+=pItem->StackCount; + } + } + } + } + } + } + } + + Ret.DWord=Count; + Ret.Type=pIntType; + + return true; +} + + +TLO(dataInvSlot) +{ + if (!ISINDEX()) + return false; + if (ISNUMBER()) + { + Ret.DWord=GETNUMBER(); + Ret.Type=pInvSlotType; + return true; + } + else + { + CHAR Temp[MAX_STRING]={0}; + strlwr(strcpy(Temp,GETFIRST())); + Ret.DWord=ItemSlotMap[Temp]; + if (Ret.DWord || !stricmp(Temp,"charm")) + { + Ret.Type=pInvSlotType; + return true; + } + } + return false; +} + +#ifndef ISXEQ +TLO(dataPlugin) +{ + if (!ISINDEX()) + return false; + if (ISNUMBER()) + { + unsigned long N = GETNUMBER()-1; + PMQPLUGIN pPlugin=pPlugins; + while(N) + { + pPlugin=pPlugin->pNext; + if (!pPlugin) + return false; + N--; + } + Ret.Ptr=pPlugin; + Ret.Type=pPluginType; + return true; + } + else + { + // name + PMQPLUGIN pPlugin=pPlugins; + while(pPlugin) + { + if (!stricmp(pPlugin->szFilename,szIndex)) + { + Ret.Ptr=pPlugin; + Ret.Type=pPluginType; + return true; + } + pPlugin=pPlugin->pNext; + } + } + return false; +} +#endif + +TLO(dataSkill) +{ + if (!ISINDEX()) + return false; + if (ISNUMBER()) + { + unsigned long nSkill=GETNUMBER()-1; + if (nSkill>=NUM_SKILLS) + return false; + if (Ret.Ptr=&pSkillMgr->pSkill[nSkill]) + { + Ret.Type=pSkillType; + return true; + } + } + else + { + for (unsigned long nSkill=0 ; nSkillpSkill[nSkill]) + { + if (PCHAR pName=pStringTable->getString(pSkill->nName,0)) + { + if (!stricmp(GETFIRST(),pName)) + { + Ret.Ptr=&pSkillMgr->pSkill[nSkill]; + Ret.Type=pSkillType; + return true; + } + } + } + } + } + + return false; +} + +TLO(dataAltAbility) +{ + if (!ISINDEX()) + return false; + if (ISNUMBER()) + { + for (unsigned long nAbility=0 ; nAbilityGetAltAbility(nAbility)) + { + if (pAbility->ID == GETNUMBER() ) + { + Ret.Ptr=pAbility; + Ret.Type=pAltAbilityType; + return true; + } + } + } + } + else + { + for (unsigned long nAbility=0 ; nAbilityGetAltAbility(nAbility)) + { + if (PCHAR pName=pCDBStr->GetString(pAbility->nName, 1, NULL)) + { + if (!stricmp(GETFIRST(),pName)) + { + Ret.Ptr=pAbility; + Ret.Type=pAltAbilityType; + return true; + } + } + } + } + } + + return false; +} + +TLO(dataRaid) +{ + Ret.DWord=0; + Ret.Type=pRaidType; + return true; +} + +TLO(dataNamingSpawn) +{ + if (Ret.Ptr=pNamingSpawn) + { + Ret.Type=pSpawnType; + return true; + } + return false; +} + +TLO(dataLineOfSight) +{ +#ifndef ISXEQ /* CONVERT */ + if (!GetCharInfo()->pSpawn) + return FALSE; + if (ISINDEX()) + { + FLOAT P1[3]; + FLOAT P2[3]; + P1[0]=P2[0]=((PSPAWNINFO)pCharSpawn)->Y; + P1[1]=P2[1]=((PSPAWNINFO)pCharSpawn)->X; + P1[2]=P2[2]=((PSPAWNINFO)pCharSpawn)->Z; + if (PCHAR pColon=strchr(szIndex,':')) + { + *pColon=0; + if (PCHAR pComma=strchr(&pColon[1],',')) + { + *pComma=0; + P2[0]=(FLOAT)atof(&pColon[1]); + *pComma=','; + if (PCHAR pComma2=strchr(&pComma[1],',')) + { + *pComma2=0; + P2[1]=(FLOAT)atof(&pComma[1]); + *pComma2=','; + P2[2]=(FLOAT)atof(&pComma2[1]); + } + else + { + P2[1]=(FLOAT)atof(&pComma[1]); + } + } + else + P2[0]=(FLOAT)atof(&pColon[1]); + } + + + if (PCHAR pComma=strchr(szIndex,',')) + { + *pComma=0; + P1[0]=(FLOAT)atof(szIndex); + *pComma=','; + if (PCHAR pComma2=strchr(&pComma[1],',')) + { + *pComma2=0; + P1[1]=(FLOAT)atof(&pComma[1]); + *pComma2=','; + P1[2]=(FLOAT)atof(&pComma2[1]); + } + else + { + P1[1]=(FLOAT)atof(&pComma[1]); + } + } + else + P1[0]=(FLOAT)atof(szIndex); + + + //DebugSpew("GetDistance3D(%1.0f,%1.0f,%1.0f,%1.0f,%1.0f,%1.0f)",P1[0],P1[1],P1[2],P2[0],P2[1],P2[2]); + SPAWNINFO Temp=*GetCharInfo()->pSpawn; + Temp.Y=P2[0]; + Temp.X=P2[1]; + Temp.Z=P2[2]; + Ret.DWord=CastRay(&Temp,P1[0],P1[1],P1[2]); + Ret.Type=pBoolType; + return true; + } +#endif + return false; +} + +TLO(dataDoorTarget) +{ + if (Ret.Ptr=&DoorEnviroTarget) + { + Ret.Type=pSpawnType; + return true; + } + return false; +} + +TLO(dataItemTarget) +{ + if (Ret.Ptr=&EnviroTarget) + { + Ret.Type=pSpawnType; + return true; + } + return false; +} + +TLO(dataDynamicZone) +{ + Ret.DWord=0; + Ret.Type=pDynamicZoneType; + return true; +} + +TLO(dataFriends) +{ + Ret.DWord=0; + Ret.Type=pFriendsType; + return true; +} + diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2DataAPI.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2DataAPI.cpp new file mode 100644 index 0000000000..0c42f940a7 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2DataAPI.cpp @@ -0,0 +1,580 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ +#ifndef ISXEQ + +#if !defined(CINTERFACE) +//#error /DCINTERFACE +#endif + +#define DBG_SPEW + + +#include "MQ2Main.h" + + + +map MQ2DataTypeMap; +CIndex MQ2DataTypes; + +/*inline/**/ MQ2Type *FindMQ2DataType(PCHAR Name) +{ + unsigned long N=MQ2DataTypeMap[Name]; + if (!N) + return 0; + N--; + return MQ2DataTypes[N]; +} + +namespace MQ2Internal +{ + BOOL AddMQ2Type(MQ2Type &Type) + { + if (FindMQ2DataType(Type.GetName())) + return false; + unsigned long N=MQ2DataTypes.GetUnused(); + MQ2DataTypes[N]=&Type; + MQ2DataTypeMap[Type.GetName()]=N+1; + return true; + } + + BOOL RemoveMQ2Type(MQ2Type &Type) + { + unsigned long N=MQ2DataTypeMap[Type.GetName()]; + if (!N) + return 0; + N--; + if (MQ2Type *pType=MQ2DataTypes[N]) + { + MQ2DataTypes[N]=0; + return false; + } + MQ2DataTypeMap[Type.GetName()]=0; + return true; + } +}; + +map MQ2DataMap; +CIndex MQ2DataItems; + +inline PMQ2DATAITEM FindMQ2Data(PCHAR szName) +{ + unsigned long N=MQ2DataMap[szName]; + if (!N) + return 0; + N--; + return MQ2DataItems[N]; +} + +BOOL AddMQ2Data(PCHAR szName, fMQData Function) +{ + if (FindMQ2Data(szName)) + return false; + unsigned long N=MQ2DataItems.GetUnused(); + PMQ2DATAITEM pNew=new MQ2DATAITEM; + strcpy(pNew->Name,szName); + pNew->Function=Function; + MQ2DataItems[N]=pNew; + MQ2DataMap[szName]=N+1; + return true; +} + +BOOL RemoveMQ2Data(PCHAR szName) +{ + unsigned long N=MQ2DataMap[szName]; + if (!N) + return 0; + N--; + if (PMQ2DATAITEM pItem=MQ2DataItems[N]) + { + MQ2DataItems[N]=0; + delete pItem; + } + MQ2DataMap[szName]=0; + return true; +} + +BOOL dataType(PCHAR szIndex, MQ2TYPEVAR &Ret) +{ + if (MQ2Type* pType=FindMQ2DataType(szIndex)) + { + Ret.Ptr=pType; + Ret.Type=pTypeType; + return true; + } + return false; +} + +void InitializeMQ2Data() +{ + AddMQ2Data("Spawn",dataSpawn); + AddMQ2Data("Target",dataTarget); + AddMQ2Data("Me",dataCharacter); + AddMQ2Data("Spell",dataSpell); + AddMQ2Data("Switch",dataSwitch); + AddMQ2Data("Ground",dataGroundItem); + AddMQ2Data("Merchant",dataMerchant); + AddMQ2Data("Window",dataWindow); + AddMQ2Data("Macro",dataMacro); + AddMQ2Data("MacroQuest",dataMacroQuest); + AddMQ2Data("Math",dataMath); + AddMQ2Data("Zone",dataZone); + AddMQ2Data("Group",dataGroup); + AddMQ2Data("String",dataString); + AddMQ2Data("Int",dataInt); + AddMQ2Data("Bool",dataBool); + AddMQ2Data("Float",dataFloat); + AddMQ2Data("Corpse",dataCorpse); + AddMQ2Data("If",dataIf); + AddMQ2Data("Cursor",dataCursor); + AddMQ2Data("NearestSpawn",dataNearestSpawn); + AddMQ2Data("Type",dataType); + AddMQ2Data("Time",dataTime); + AddMQ2Data("GameTime",dataGameTime); + AddMQ2Data("Ini",dataIni); + AddMQ2Data("Heading",dataHeading); + AddMQ2Data("Defined",dataDefined); + AddMQ2Data("LastSpawn",dataLastSpawn); + AddMQ2Data("FindItem",dataFindItem); + AddMQ2Data("FindItemBank",dataFindItemBank); + AddMQ2Data("InvSlot",dataInvSlot); + AddMQ2Data("SelectedItem",dataSelectedItem); + AddMQ2Data("FindItemCount",dataFindItemCount); + AddMQ2Data("FindItemBankCount",dataFindItemBankCount); + //AddMQ2Data("GroupLeader",dataGroupLeader); + //AddMQ2Data("GroupLeaderName",dataGroupLeaderName); + AddMQ2Data("Skill",dataSkill); + AddMQ2Data("AltAbility",dataAltAbility); + AddMQ2Data("Raid",dataRaid); + AddMQ2Data("NamingSpawn",dataNamingSpawn); + AddMQ2Data("SpawnCount",dataSpawnCount); + AddMQ2Data("LineOfSight",dataLineOfSight); + AddMQ2Data("Plugin",dataPlugin); + AddMQ2Data("Select",dataSelect); + AddMQ2Data("DoorTarget",dataDoorTarget); + AddMQ2Data("ItemTarget",dataItemTarget); + AddMQ2Data("DynamicZone",dataDynamicZone); + AddMQ2Data("Friends",dataFriends); +} + + + +void ShutdownMQ2Data() +{ + MQ2DataItems.Cleanup(); +} + +BOOL ParseMQ2DataPortion(PCHAR szOriginal, MQ2TYPEVAR &Result) +{ + Result.Type=0; + Result.DWord=0; + // Find [] before a . or null + PCHAR pPos=&szOriginal[0]; + PCHAR pStart=pPos; + CHAR Index[MAX_STRING]={0}; + PCHAR pIndex=&Index[0]; + BOOL Quote=FALSE; + while(1) + { + if (*pPos==0) + { + // end completely. process + if (pStart==pPos) + { + if (!Result.Type) + { + MQ2DataError("Nothing to parse"); + return FALSE; + } + //Result.Type->ToString(Result.VarPtr,szCurrent); + return TRUE; + } + else + { + if (!Result.Type) + { + if (PMQ2DATAITEM DataItem=FindMQ2Data(pStart)) + { + if (!DataItem->Function(pIndex,Result)) + { + return FALSE; + } + } + else if (PDATAVAR DataVar=FindMQ2DataVariable(pStart)) + { + if (pIndex[0]) + { + if (DataVar->Var.Type==pArrayType) + { + if (!((CDataArray*)DataVar->Var.Ptr)->GetElement(pIndex,Result)) + { + return FALSE; + } + } + } + else + Result=DataVar->Var; + } + else + { + //MQ2DataError("No such Top-Level Object '%s'",pStart); + return FALSE; + } + } + else + { + if (!Result.Type->GetMember(Result.VarPtr,pStart,pIndex,Result)) + { + if (!Result.Type->FindMember(pStart) && !Result.Type->InheritedMember(pStart)) + { + MQ2DataError("No such '%s' member '%s'",Result.Type->GetName(),pStart); + } + return FALSE; + } + } + } + //Result.Type->ToString(Result.VarPtr,szCurrent); + + // done processing + return TRUE; + } + if (*pPos=='(') + { + *pPos=0; + if (pStart==pPos) + { + if (!Result.Type) + { + MQ2DataError("Encountered typecast without object to cast"); + return FALSE; + } + //Result.Type->ToString(Result.VarPtr,szCurrent); + return TRUE; + } + else + { + if (!Result.Type) + { + if (PMQ2DATAITEM DataItem=FindMQ2Data(pStart)) + { + if (!DataItem->Function(pIndex,Result)) + { + return FALSE; + } + } + else if (PDATAVAR DataVar=FindMQ2DataVariable(pStart)) + { + if (pIndex[0]) + { + if (DataVar->Var.Type==pArrayType) + { + if (!((CDataArray*)DataVar->Var.Ptr)->GetElement(pIndex,Result)) + { + return FALSE; + } + } + } + else + Result=DataVar->Var; + } + else + { + //MQ2DataError("No such Top-Level Object '%s'",pStart); + return FALSE; + } + + } + else + { + if (!Result.Type->GetMember(Result.VarPtr,pStart,pIndex,Result)) + { + if (!Result.Type->FindMember(pStart) && !Result.Type->InheritedMember(pStart)) + { + MQ2DataError("No such '%s' member '%s'",Result.Type->GetName(),pStart); + } + return FALSE; + } + } + } + if (!Result.Type) + { + // error + return FALSE; + } + *pPos=0; + ++pPos; + PCHAR pType=pPos; + while(*pPos!=')') + { + if (!*pPos) + { + // error + MQ2DataError("Encountered unmatched parenthesis"); + return FALSE; + } + ++pPos; + } + *pPos=0; + MQ2Type *pNewType=FindMQ2DataType(pType); + if (!pNewType) + { + // error + MQ2DataError("Unknown type '%s'",pType); + return FALSE; + } + if (pNewType==pTypeType) + { + Result.Ptr=Result.Type; + Result.Type=pTypeType; + } + else + Result.Type=pNewType; + + if (pPos[1]=='.') + { + ++pPos; + pStart=&pPos[1]; + } + else if (!pPos[1]) + { + //Result.Type->ToString(Result.VarPtr,szCurrent); + return TRUE; + } + else + { + MQ2DataError("Invalid character found after typecast ')%s'",&pPos[1]); + return FALSE; + } + } + else + if (*pPos=='[') + { + // index + *pPos=0; + ++pPos; + + Quote=false; + BOOL BeginParam=true; + while(1) + { + if (*pPos==0) + { + MQ2DataError("Unmatched bracket or invalid character following bracket found in index: '%s'",pIndex); + return FALSE; + } + + if (BeginParam) + { + BeginParam=false; + if (*pPos=='\"') + { + Quote=true; + ++pPos; + continue; + } + } + if (Quote) + { + if (*pPos=='\"') + { + if (pPos[1]==']' || pPos[1]==',') + { + Quote=false; + ++pPos; + continue; + } + } + } + else + { + if (*pPos==']') + { + if (pPos[1]=='.' || pPos[1]=='(' || pPos[1]==0) + break;// valid end + } + else if (*pPos==',') + BeginParam=true; + } + *pIndex=*pPos; + ++pIndex; + ++pPos; + } + + *pIndex=0; + pIndex=&Index[0]; + *pPos=0; + } + else + if (*pPos=='.') + { + // end of this one, but more to come! + *pPos=0; + if (pStart==pPos) + { + if (!Result.Type) + { + MQ2DataError("Encountered member access without object"); + return FALSE; + } + //Result.Type->ToString(Result.VarPtr,szCurrent); + return TRUE; + } + else + { + if (!Result.Type) + { + if (PMQ2DATAITEM DataItem=FindMQ2Data(pStart)) + { + if (!DataItem->Function(pIndex,Result)) + { + return FALSE; + } + } + else if (PDATAVAR DataVar=FindMQ2DataVariable(pStart)) + { + if (pIndex[0]) + { + if (DataVar->Var.Type==pArrayType) + { + if (!((CDataArray*)DataVar->Var.Ptr)->GetElement(pIndex,Result)) + { + return FALSE; + } + } + } + else + Result=DataVar->Var; + } + else + { + //MQ2DataError("No such Top-Level Object '%s'",pStart); + return FALSE; + } + + } + else + { + if (!Result.Type->GetMember(Result.VarPtr,pStart,pIndex,Result)) + { + if (!Result.Type->FindMember(pStart) && !Result.Type->InheritedMember(pStart)) + { + MQ2DataError("No such '%s' member '%s'",Result.Type->GetName(),pStart); + } + return FALSE; + } + } + } + pStart=&pPos[1]; + Index[0]=0; + } + ++pPos; + } + +} + +BOOL ParseMacroData(PCHAR szOriginal) +{ + // find each {} + PCHAR pBrace=strstr(szOriginal,"${"); + if (!pBrace) + return false; + unsigned long NewLength; + BOOL Changed=false; + //PCHAR pPos; + //PCHAR pStart; + //PCHAR pIndex; + CHAR szCurrent[MAX_STRING]={0}; + + do + { + // find this brace's end + PCHAR pEnd=&pBrace[1]; + BOOL Quote=false; + BOOL BeginParam=false; + int nBrace=1; + while(nBrace) + { + ++pEnd; + if (BeginParam) + { + BeginParam=false; + if (*pEnd=='\"') + { + Quote=true; + } + continue; + } + if (*pEnd==0) + {// unmatched brace or quote + goto pmdbottom; + } + if (Quote) + { + if (*pEnd=='\"') + { + if (pEnd[1]==']' || pEnd[1]==',') + { + Quote=false; + } + } + } + else + { + if (*pEnd=='}') + { + nBrace--; + } + else if (*pEnd=='{') + { + nBrace++; + } + else if (*pEnd=='[' || *pEnd==',') + BeginParam=true; + } + + } + *pEnd=0; + strcpy(szCurrent,&pBrace[2]); + if (szCurrent[0]==0) + { + goto pmdbottom; + } + if (ParseMacroData(szCurrent)) + { + unsigned long NewLength=strlen(szCurrent); + memmove(&pBrace[NewLength+1],&pEnd[1],strlen(&pEnd[1])+1); + strncpy(pBrace,szCurrent,NewLength); + pEnd=&pBrace[NewLength]; + *pEnd=0; + } + + MQ2TYPEVAR Result; + if (!ParseMQ2DataPortion(szCurrent,Result) || !Result.Type || !Result.Type->ToString(Result.VarPtr,szCurrent)) + strcpy(szCurrent,"NULL"); + + NewLength=strlen(szCurrent); + + memmove(&pBrace[NewLength],&pEnd[1],strlen(&pEnd[1])+1); + strncpy(pBrace,szCurrent,NewLength); + Changed=true; + +pmdbottom:; + } while (pBrace=strstr(&pBrace[1],"${")); + if (Changed) + while(ParseMacroData(szOriginal)) + { + } + return Changed; +} + +#endif diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2DataTypes.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2DataTypes.cpp new file mode 100644 index 0000000000..6dc5b38459 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2DataTypes.cpp @@ -0,0 +1,7593 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +//#error /DCINTERFACE +#endif + +#define DBG_SPEW + + +#include "MQ2Main.h" + +#ifdef ISXEQ +#define ISINDEX() (argc>0) +#define ISNUMBER() (IsNumber(argv[0])) +#define GETNUMBER() (atoi(argv[0])) +#define GETFIRST() argv[0] +#else +#define ISINDEX() (Index[0]) +#define ISNUMBER() (IsNumber(Index)) +#define GETNUMBER() (atoi(Index)) +#define GETFIRST() Index +#endif + + +#ifndef ISXEQ +class MQ2FloatType *pFloatType=0; +class MQ2IntType *pIntType=0; +class MQ2ByteType *pByteType=0; +class MQ2BoolType *pBoolType=0; +class MQ2StringType *pStringType=0; +class MQ2MathType *pMathType=0; +class MQ2TimeType *pTimeType=0; +class MQ2ArrayType *pArrayType=0; +#endif +class MQ2SpawnType *pSpawnType=0; +class MQ2BuffType *pBuffType=0; +class MQ2SpellType *pSpellType=0; +class MQ2TicksType *pTicksType=0; +class MQ2CharacterType *pCharacterType=0; +class MQ2ClassType *pClassType=0; +class MQ2RaceType *pRaceType=0; +class MQ2BodyType *pBodyType=0; +class MQ2SkillType *pSkillType=0; +class MQ2AltAbilityType *pAltAbilityType=0; +class MQ2GroundType *pGroundType=0; +class MQ2SwitchType *pSwitchType=0; +class MQ2CorpseType *pCorpseType=0; +class MQ2MacroType *pMacroType=0; +class MQ2MacroQuestType *pMacroQuestType=0; +class MQ2WindowType *pWindowType=0; +class MQ2MerchantType *pMerchantType=0; +class MQ2ZoneType *pZoneType=0; +class MQ2CurrentZoneType *pCurrentZoneType=0; +class MQ2ItemType *pItemType=0; +class MQ2DeityType *pDeityType=0; +class MQ2ArgbType *pArgbType=0; +class MQ2TypeType *pTypeType=0; +class MQ2HeadingType *pHeadingType=0; +class MQ2InvSlotType *pInvSlotType=0; +class MQ2TimerType *pTimerType=0; +class MQ2PluginType *pPluginType=0; +class MQ2RaidType *pRaidType=0; +class MQ2RaidMemberType *pRaidMemberType=0; +class MQ2GroupType *pGroupType=0; +class MQ2GroupMemberType *pGroupMemberType=0; +class MQ2EvolvingItemType *pEvolvingItemType=0; +class MQ2DynamicZoneType *pDynamicZoneType=0; +class MQ2DZMemberType *pDZMemberType=0; +class MQ2FellowshipType *pFellowshipType=0; +class MQ2FellowshipMemberType *pFellowshipMemberType=0; +class MQ2FriendsType *pFriendsType=0; +class MQ2TargetType *pTargetType=0; +class MQ2XTargetType *pXTargetType=0; + +#ifndef ISXEQ + +void InitializeMQ2DataTypes() +{ + pFloatType = new MQ2FloatType; + pIntType = new MQ2IntType; + pByteType = new MQ2ByteType; + pStringType = new MQ2StringType; + pSpawnType = new MQ2SpawnType; + pSpellType = new MQ2SpellType; + pBuffType = new MQ2BuffType; + pTicksType = new MQ2TicksType; + pCharacterType = new MQ2CharacterType; + pClassType=new MQ2ClassType; + pRaceType=new MQ2RaceType; + pGroundType = new MQ2GroundType; + pSwitchType = new MQ2SwitchType; + pMacroType = new MQ2MacroType; + pMacroQuestType = new MQ2MacroQuestType; + pMathType = new MQ2MathType; + pWindowType = new MQ2WindowType; + pMerchantType = new MQ2MerchantType; + pZoneType = new MQ2ZoneType; + pItemType = new MQ2ItemType; + pBoolType = new MQ2BoolType; + pBodyType = new MQ2BodyType; + pDeityType = new MQ2DeityType; + pArgbType = new MQ2ArgbType; + pCorpseType = new MQ2CorpseType; + pCurrentZoneType = new MQ2CurrentZoneType; + pTypeType = new MQ2TypeType; + pTimeType = new MQ2TimeType; + pHeadingType = new MQ2HeadingType; + pInvSlotType = new MQ2InvSlotType; + pArrayType = new MQ2ArrayType; + pTimerType = new MQ2TimerType; + pPluginType = new MQ2PluginType; + pSkillType = new MQ2SkillType; + pAltAbilityType = new MQ2AltAbilityType; + pRaidType = new MQ2RaidType; + pRaidMemberType = new MQ2RaidMemberType; + pGroupType = new MQ2GroupType; + pGroupMemberType = new MQ2GroupMemberType; + pGroupMemberType->SetInheritance(pSpawnType); + pEvolvingItemType=new MQ2EvolvingItemType; + pDynamicZoneType=new MQ2DynamicZoneType; + pDZMemberType=new MQ2DZMemberType; + pFellowshipType=new MQ2FellowshipType; + pFellowshipMemberType=new MQ2FellowshipMemberType; + pFriendsType = new MQ2FriendsType; + pTargetType = new MQ2TargetType; + pXTargetType = new MQ2XTargetType; + + // NOTE: SetInheritance does NOT make it inherit, just notifies the syntax checker... + pCharacterType->SetInheritance(pSpawnType); + pBuffType->SetInheritance(pSpellType); + //pCurrentZoneType->SetInheritance(pZoneType); + pRaidMemberType->SetInheritance(pSpawnType); + pTargetType->SetInheritance(pSpawnType); +} + +void ShutdownMQ2DataTypes() +{ + delete pSpawnType; + delete pFloatType; + delete pIntType; + delete pByteType; + delete pStringType; + delete pBuffType; + delete pSpellType; + delete pTicksType; + delete pCharacterType; + delete pClassType; + delete pRaceType; + delete pGroundType; + delete pSwitchType; + delete pMacroType; + delete pMacroQuestType; + delete pMathType; + delete pWindowType; + delete pMerchantType; + delete pZoneType; + delete pItemType; + delete pBoolType; + delete pBodyType; + delete pDeityType; + delete pArgbType; + delete pCorpseType; + delete pCurrentZoneType; + delete pTypeType; + delete pTimeType; + delete pHeadingType; + delete pArrayType; + delete pTimerType; + delete pPluginType; + delete pSkillType; + delete pAltAbilityType; + delete pRaidType; + delete pRaidMemberType; + delete pGroupType; + delete pGroupMemberType; + delete pEvolvingItemType; + delete pDynamicZoneType; + delete pFriendsType; + delete pTargetType; + delete pXTargetType; +} + +bool MQ2TypeType::GETMEMBER() +{ +#define pType ((MQ2Type*)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMEMBER pMember=MQ2TypeType::FindMember(Member); + if (!pMember) + return false; + switch((TypeMembers)pMember->ID) + { + case Name: + Dest.Ptr=pType->GetName(); + Dest.Type=pStringType; + return true; + case TypeMember: + if (ISINDEX()) + { + if (ISNUMBER()) + { + // name by number + if (Dest.Ptr=pType->GetMemberName(GETNUMBER())) + { + Dest.Type=pStringType; + return true; + } + } + else + { + // number by name + if (pType->GetMemberID(Index,Dest.DWord)) + { + Dest.Type=pIntType; + return true; + } + } + } + return false; + } + return false; +#undef pType +} + +bool MQ2PluginType::GETMEMBER() +{ +#define pPlugin ((PMQPLUGIN)VarPtr.Ptr) + if (!pPlugin) + return false; + PMQ2TYPEMEMBER pMember=MQ2PluginType::FindMember(Member); + if (!pMember) + return false; + switch((PluginMembers)pMember->ID) + { + case Name: + Dest.Ptr=pPlugin->szFilename; + Dest.Type=pStringType; + return true; + case Version: + Dest.Float=pPlugin->fpVersion; + Dest.Type=pFloatType; + return true; + } + return false; +#undef pPlugin +} +bool MQ2FloatType::GETMEMBER() +{ + PMQ2TYPEMEMBER pMember=MQ2FloatType::FindMember(Member); + if (!pMember) + { + return false; + } + + switch((FloatMembers)pMember->ID) + { + case Deci: + sprintf(DataTypeTemp,"%.1f",VarPtr.Float); + Dest.Type=pStringType; + Dest.Ptr=&DataTypeTemp[0]; + return true; + case Centi: + sprintf(DataTypeTemp,"%.2f",VarPtr.Float); + Dest.Type=pStringType; + Dest.Ptr=&DataTypeTemp[0]; + return true; + case Milli: + sprintf(DataTypeTemp,"%.3f",VarPtr.Float); + Dest.Type=pStringType; + Dest.Ptr=&DataTypeTemp[0]; + return true; + case Int: + Dest.Type=pIntType; + Dest.Int=(int)(VarPtr.Float); + return true; + case Precision: + if (ISNUMBER()) + { + sprintf(DataTypeTemp,"%.*f",GETNUMBER(),VarPtr.Float); + Dest.Type=pStringType; + Dest.Ptr=&DataTypeTemp[0]; + return true; + } + return false; + } + return false; +} + +bool MQ2IntType::GETMEMBER() +{ + PMQ2TYPEMEMBER pMember=MQ2IntType::FindMember(Member); + if (!pMember) + { + return false; + } + + switch((IntMembers)pMember->ID) + { + case Float: + Dest.Float=(FLOAT)1.0f*(VarPtr.Int); + Dest.Type=pFloatType; + return true; + case Hex: + sprintf(DataTypeTemp,"%x",VarPtr.Int); + Dest.Ptr=&DataTypeTemp[0], + Dest.Type=pStringType; + return true; + case Reverse: + { + Dest.Array[0]=VarPtr.Array[3]; + Dest.Array[1]=VarPtr.Array[2]; + Dest.Array[2]=VarPtr.Array[1]; + Dest.Array[3]=VarPtr.Array[0]; + Dest.Type=pIntType; + } + return true; + } + return false; +} +bool MQ2StringType::GETMEMBER() +{ + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMEMBER pMember=MQ2StringType::FindMember(Member); + if (!pMember) + { + return false; + } + + switch((StringMembers)pMember->ID) + { + case Length: + Dest.DWord=strlen((const char *)VarPtr.Ptr); + Dest.Type=pIntType; + return true; + case Left: + if (!ISINDEX()) + return false; + { + int Len=GETNUMBER(); + if (Len==0) + return false; + if (Len>0) + { + unsigned long StrLen=strlen((char *)VarPtr.Ptr); + if ((unsigned long)Len>StrLen) + Len=StrLen; + memmove(DataTypeTemp,(char *)VarPtr.Ptr,Len); + DataTypeTemp[Len]=0; + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + } + else + { + Len=-Len; + unsigned long StrLen=strlen((char *)VarPtr.Ptr); + if ((unsigned long)Len>=StrLen) + { + Dest.Ptr=""; + Dest.Type=pStringType; + return true; + } + memmove(DataTypeTemp,(char *)VarPtr.Ptr,StrLen-Len); + DataTypeTemp[StrLen-Len]=0; + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + } + } + return true; + case Right: + if (!ISINDEX()) + return false; + { + int Len=GETNUMBER(); + if (Len==0) + return false; + if (Len<0) + { + Len=-Len; + unsigned long StrLen=strlen((char *)VarPtr.Ptr); + if ((unsigned long)Len>=StrLen) + { + Dest.Ptr=""; + Dest.Type=pStringType; + return true; + } + char *pStart=(char*)VarPtr.Ptr; + pStart=&pStart[Len]; + Len=StrLen-Len; + memmove(DataTypeTemp,pStart,Len+1); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + } + else + { + char *pStart=(char*)VarPtr.Ptr; + pStart=&pStart[strlen(pStart)-Len]; + if (pStart while */ + { + DataTypeTemp[0] = '\0' ; + strncat( DataTypeTemp , A , pos - A ) ; + strcat( DataTypeTemp , C ) ; + strcat( DataTypeTemp , pos + strlen( B ) ) ; + strcpy( A, DataTypeTemp); /* added */ + } + if (Dest.Ptr = DataTypeTemp) + { + Dest.Type = pStringType; + return true; + } + } + } + case Upper: + strcpy(DataTypeTemp,(char*)VarPtr.Ptr); + strupr(DataTypeTemp); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + case Lower: + strcpy(DataTypeTemp,(char*)VarPtr.Ptr); + strlwr(DataTypeTemp); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + case Compare: + if (ISINDEX()) + { + Dest.Int=stricmp((char*)VarPtr.Ptr,Index); + Dest.Type=pIntType; + return true; + } + return false; + case CompareCS: + if (ISINDEX()) + { + Dest.Int=strcmp((char*)VarPtr.Ptr,Index); + Dest.Type=pIntType; + return true; + } + return false; + case Mid: + { + if (PCHAR pComma=strchr(Index,',')) + { + *pComma=0; + pComma++; + PCHAR pStr=(char *)VarPtr.Ptr; + unsigned long nStart=GETNUMBER()-1; + unsigned long Len=atoi(pComma); + if (nStart>=strlen(pStr)) + { + Dest.Ptr=""; + Dest.Type=pStringType; + return true; + } + pStr+=nStart; + unsigned long StrLen=strlen(pStr); + if (Len>StrLen) + Len=StrLen; + memmove(DataTypeTemp,pStr,Len); + DataTypeTemp[Len]=0; + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + } + return false; + case Equal: + if (ISINDEX()) + { + Dest.DWord=(stricmp((char*)VarPtr.Ptr,Index)==0); + Dest.Type=pBoolType; + return true; + } + return false; + case NotEqual: + if (ISINDEX()) + { + Dest.DWord=(stricmp((char*)VarPtr.Ptr,Index)!=0); + Dest.Type=pBoolType; + return true; + } + return false; + case EqualCS: + if (ISINDEX()) + { + Dest.DWord=(strcmp((char*)VarPtr.Ptr,Index)==0); + Dest.Type=pBoolType; + return true; + } + return false; + case NotEqualCS: + if (ISINDEX()) + { + Dest.DWord=(strcmp((char*)VarPtr.Ptr,Index)!=0); + Dest.Type=pBoolType; + return true; + } + return false; + case Count: + if (ISINDEX()) + { + Dest.DWord=0; + PCHAR pLast=(PCHAR)VarPtr.Ptr-1; + while(pLast=strchr(&pLast[1],Index[0])) + Dest.DWord++; + Dest.Type=pIntType; + return true; + } + return false; + case Arg: + if (IsNumberToComma(Index)) + { + CHAR Temp[MAX_STRING]={0}; + strcpy(Temp,(char *)VarPtr.Ptr); + if (PCHAR pComma=strchr(Index,',')) + { + *pComma=0; + GetArg(DataTypeTemp,Temp,GETNUMBER(),FALSE,FALSE,FALSE,pComma[1]); + *pComma=','; + if (DataTypeTemp[0]) + { + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + } + else + { + GetArg(DataTypeTemp,Temp,GETNUMBER()); + if (DataTypeTemp[0]) + { + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + } + } + return false; + case Token: + if (IsNumberToComma(Index)) + { + DWORD N=GETNUMBER(); + if (!N) + return false; + //CHAR Temp[MAX_STRING]={0}; + //strcpy(Temp,(char *)VarPtr.Ptr); + if (PCHAR pComma=strchr(Index,',')) + { + *pComma=0; + PCHAR pPos=(PCHAR)VarPtr.Ptr;//strchr((char *)VarPtr.Ptr,pComma[1]); + N--; + while(N && pPos) + { + pPos=strchr(&pPos[1],pComma[1]); + N--; + } + *pComma=','; + if (pPos) + { + if (pPos!=(PCHAR)VarPtr.Ptr) + pPos++; + PCHAR pEnd=strchr(&pPos[0],pComma[1]); + if (pEnd) + { + if (pEnd!=pPos) + { + strncpy(DataTypeTemp,pPos,pEnd-pPos); + DataTypeTemp[pEnd-pPos]=0; + } + else + DataTypeTemp[0]=0; + } + else + strcpy(DataTypeTemp,pPos); + // allows empty returned strings + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + } + } + return false; + } + return false; +} +bool MQ2ArrayType::GETMEMBER() +{ +#define pArray ((CDataArray*)VarPtr.Ptr) + if (!pArray) + return false; + PMQ2TYPEMEMBER pMember=MQ2ArrayType::FindMember(Member); + if (!pMember) + return false; + switch((ArrayMembers)pMember->ID) + { + case Dimensions: + Dest.DWord=pArray->nExtents; + Dest.Type=pIntType; + return true; + case Size: + if (ISINDEX()) + { + DWORD N=GETNUMBER()-1; + if (NnExtents) + { + Dest.DWord=pArray->pExtents[N]; + Dest.Type=pIntType; + return true; + } + } + else + { + Dest.DWord=pArray->TotalElements; + Dest.Type=pIntType; + return true; + } + return false; + } + return false; +#undef pArray +} +bool MQ2MathType::GETMEMBER() +{ + PMQ2TYPEMEMBER pMember=MQ2MathType::FindMember(Member); + if (!pMember) + return false; + + if (!ISINDEX()) + return false; + DOUBLE CalcResult; + switch((MathMembers)pMember->ID) + { + case Abs: + if (Calculate(Index,CalcResult)) + { + Dest.Float=(FLOAT)CalcResult; + if (Dest.Float<0) + Dest.Float*=-1; + Dest.Type=pFloatType; + return true; + } + return false; + case Rand: + Dest.DWord=atol(Index); + if (Dest.DWord==0 || Dest.DWord==0xFFFFFFFF) + return false; + Dest.DWord=rand() % Dest.DWord; + Dest.Type=pIntType; + return true; + case Sqrt: + if (Calculate(Index,CalcResult)) + { + Dest.Float=(FLOAT)sqrt(CalcResult); + Dest.Type=pFloatType; + return true; + } + return false; + case Calc: + if (Calculate(Index,CalcResult)) + { + Dest.Float=(FLOAT)CalcResult; + Dest.Type=pFloatType; + return true; + } + return false; + case Sin: + if (Calculate(Index,CalcResult)) + { + Dest.Float=(float)sin(CalcResult/DegToRad); + Dest.Type=pFloatType; + return true; + } + return false; + case Cos: + if (Calculate(Index,CalcResult)) + { + Dest.Float=(float)cos(CalcResult/DegToRad); + Dest.Type=pFloatType; + return true; + } + return false; + case Tan: + if (Calculate(Index,CalcResult)) + { + Dest.Float=(float)tan(CalcResult/DegToRad); + Dest.Type=pFloatType; + return true; + } + return false; + case Asin: + if (Calculate(Index,CalcResult)) + { + Dest.Float=(float)(asin(CalcResult)*DegToRad); + Dest.Type=pFloatType; + return true; + } + return false; + case Acos: + if (Calculate(Index,CalcResult)) + { + Dest.Float=(float)(acos(CalcResult)*DegToRad); + Dest.Type=pFloatType; + return true; + } + return false; + case Atan: + if (Calculate(Index,CalcResult)) + { + Dest.Float=(float)(atan(CalcResult)*DegToRad); + Dest.Type=pFloatType; + return true; + } + return false; + case Not: + Dest.DWord=~atol(Index); + Dest.Type=pIntType; + return true; + case Hex: + sprintf(DataTypeTemp,"%x",atol(Index)); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + case Dec: + sscanf(Index,"%x",&Dest.DWord); + Dest.Type=pIntType; + return true; + case Distance: + if (ISINDEX()) + { + FLOAT P1[3]; + FLOAT P2[3]; + P1[0]=P2[0]=((PSPAWNINFO)pCharSpawn)->Y; + P1[1]=P2[1]=((PSPAWNINFO)pCharSpawn)->X; + P1[2]=P2[2]=((PSPAWNINFO)pCharSpawn)->Z; + if (PCHAR pColon=strchr(Index,':')) + { + *pColon=0; + if (PCHAR pComma=strchr(&pColon[1],',')) + { + *pComma=0; + P2[0]=(FLOAT)atof(&pColon[1]); + *pComma=','; + if (PCHAR pComma2=strchr(&pComma[1],',')) + { + *pComma2=0; + P2[1]=(FLOAT)atof(&pComma[1]); + *pComma2=','; + P2[2]=(FLOAT)atof(&pComma2[1]); + } + else + { + P2[1]=(FLOAT)atof(&pComma[1]); + } + } + else + P2[0]=(FLOAT)atof(&pColon[1]); + } + + + if (PCHAR pComma=strchr(Index,',')) + { + *pComma=0; + P1[0]=(FLOAT)atof(Index); + *pComma=','; + if (PCHAR pComma2=strchr(&pComma[1],',')) + { + *pComma2=0; + P1[1]=(FLOAT)atof(&pComma[1]); + *pComma2=','; + P1[2]=(FLOAT)atof(&pComma2[1]); + } + else + { + P1[1]=(FLOAT)atof(&pComma[1]); + } + } + else + P1[0]=(FLOAT)atof(Index); + + DebugSpew("GetDistance3D(%1.0f,%1.0f,%1.0f,%1.0f,%1.0f,%1.0f)",P1[0],P1[1],P1[2],P2[0],P2[1],P2[2]); + Dest.Float=(FLOAT)GetDistance3D(P1[0],P1[1],P1[2],P2[0],P2[1],P2[2]); + Dest.Type=pFloatType; + return true; + } + return false; + } + return false; +} +bool MQ2MacroType::GETMEMBER() +{ + if (!gMacroStack) + return false; + PMQ2TYPEMEMBER pMember=MQ2MacroType::FindMember(Member); + if (!pMember) + return false; + switch((MacroMembers)pMember->ID) + { + case Name: + Dest.Ptr=&gszMacroName[0]; + Dest.Type=pStringType; + return true; + case RunTime: + Dest.DWord=(DWORD)((GetTickCount()-gRunning)/1000); + Dest.Type=pIntType; + return true; + case Paused: + Dest.DWord=gMacroPause; + Dest.Type=pBoolType; + return true; + case Return: + Dest.Ptr=&DataTypeTemp[0]; + strcpy(DataTypeTemp,gMacroStack->Return); + Dest.Type=pStringType; + return true; + case Params: + Dest.DWord=0; + { + PDATAVAR pVar=gMacroStack->Parameters; + while(pVar) + { + Dest.DWord++; + pVar=pVar->pNext; + } + } + Dest.Type=pIntType; + return true; + /* + TypeMember(Param); + /**/ + } + return false; +} + +#endif + +bool MQ2TicksType::GETMEMBER() +{ +#define nTicks (VarPtr.DWord) + unsigned long N=MemberMap[Member]; + if (!N) + return false; + N--; + PMQ2TYPEMEMBER pMember=Members[N]; + if (!pMember) + return false; + switch((TicksMembers)pMember->ID) + { + case Hours: + Dest.DWord=nTicks/600; + Dest.Type=pIntType; + return true; + case Minutes: + Dest.DWord=(nTicks/10)%60; + Dest.Type=pIntType; + return true; + case Seconds: + Dest.DWord=(nTicks*6)%60; + Dest.Type=pIntType; + return true; + case TimeHMS: + { + int Secs=nTicks*6; + int Mins=(Secs/60)%60; + int Hrs=(Secs/3600); + Secs=Secs%60; + if (Secs<0) + sprintf(DataTypeTemp,"Perm"); + else if (Hrs) + sprintf(DataTypeTemp,"%d:%02d:%02d",Hrs,Mins,Secs); + else + sprintf(DataTypeTemp,"%d:%02d",Mins,Secs); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + } + return true; + case Time: + { + int Secs=nTicks*6; + int Mins=(Secs/60); + Secs=Secs%60; + if (Secs<0) + sprintf(DataTypeTemp,"Perm"); + else + sprintf(DataTypeTemp,"%d:%02d",Mins,Secs); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + } + return true; + case TotalMinutes: + Dest.DWord=nTicks/10; + Dest.Type=pIntType; + return true; + case TotalSeconds: + Dest.DWord=nTicks*6; + Dest.Type=pIntType; + return true; + case Ticks: + Dest.DWord=nTicks; + Dest.Type=pIntType; + return true; + } + return false; +#undef nTicks +} + +bool MQ2ArgbType::GETMEMBER() +{ + unsigned long N=MemberMap[Member]; + if (!N) + return false; + N--; + PMQ2TYPEMEMBER pMember=Members[N]; + if (!pMember) + return false; + switch((ArgbMembers)pMember->ID) + { + case A: + Dest.DWord=VarPtr.Argb.A; + Dest.Type=pIntType; + return true; + case R: + Dest.DWord=VarPtr.Argb.R; + Dest.Type=pIntType; + return true; + case G: + Dest.DWord=VarPtr.Argb.G; + Dest.Type=pIntType; + return true; + case B: + Dest.DWord=VarPtr.Argb.B; + Dest.Type=pIntType; + return true; + case Int: + Dest.DWord=VarPtr.DWord; + Dest.Type=pIntType; + return true; + } + return false; +} + +bool MQ2SpawnType::GETMEMBER() +{ + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMEMBER pMember=MQ2SpawnType::FindMember(Member); + if (!pMember) + { + return false; + } + PSPAWNINFO pSpawn=(PSPAWNINFO)VarPtr.Ptr; + switch((SpawnMembers)pMember->ID) + { + case Level: + Dest.DWord=pSpawn->Level; + Dest.Type=pIntType; + return true; + case ID: + Dest.Type=pIntPtrType; + INTPTR(pSpawn->SpawnID); + return true; + case Name: + Dest.Type=pStringType; + Dest.Ptr=&pSpawn->Name[0]; + return true; + case Surname: + Dest.Type=pStringType; + Dest.Ptr=&pSpawn->Lastname[0]; + return true; + case CleanName: + strcpy(DataTypeTemp,pSpawn->Name); + CleanupName(DataTypeTemp,FALSE,FALSE); + Dest.Type=pStringType; + Dest.Ptr=&DataTypeTemp[0]; + return true; + case DisplayName: + Dest.Ptr=&pSpawn->DisplayedName[0]; + Dest.Type=pStringType; + return true; + case E: + Dest.Type=pFloatType; + Dest.Float=-pSpawn->X; + return true; + case W: + case X: + Dest.Type=pFloatPtrType; + FLOATPTR(pSpawn->X); + return true; + case S: + Dest.Type=pFloatType; + Dest.Float=-pSpawn->Y; + return true; + case N: + case Y: + Dest.Type=pFloatPtrType; + FLOATPTR(pSpawn->Y); + return true; + case D: + Dest.Type=pFloatType; + Dest.Float=-pSpawn->Z; + return true; + case U: + case Z: + Dest.Type=pFloatPtrType; + FLOATPTR(pSpawn->Z); + return true; + case Next: + if (Dest.Ptr=pSpawn->pNext) + { + Dest.Type=pSpawnType; + return true; + } + return false; + case Prev: + if (Dest.Ptr=pSpawn->pPrev) + { + Dest.Type=pSpawnType; + return true; + } + return false; + case CurrentHPs: + Dest.Type=pIntType; + Dest.Int=pSpawn->HPCurrent; + return true; + case MaxHPs: + Dest.Type=pIntType; + Dest.Int=pSpawn->HPMax; + return true; + case PctHPs: + Dest.Type=pIntType; + Dest.Int=pSpawn->HPCurrent*100/pSpawn->HPMax; + return true; + case AARank: + if (pSpawn->AARank!=0xFF) + Dest.Int=pSpawn->AARank; + else + Dest.Int=0; + Dest.Type=pIntType; + return true; + case Speed: + Dest.Float=FindSpeed(pSpawn); + Dest.Type=pFloatType; + return true; + case Heading: + Dest.Float=pSpawn->Heading*0.703125f; + Dest.Type=pHeadingType; + return true; + case Pet: + if (Dest.Ptr=GetSpawnByID(pSpawn->PetID)) + { + Dest.Type=pSpawnType; + return true; + } + return false; + case Master: + if (Dest.Ptr=GetSpawnByID(pSpawn->MasterID)) + { + Dest.Type=pSpawnType; + return true; + } + return false; + case Gender: + Dest.Ptr=szGender[pSpawn->Gender]; + Dest.Type=pStringType; + return true; + case Race: + Dest.DWord=pSpawn->Race; + Dest.Type=pRaceType; + return true; + case Class: + if (GetSpawnType(pSpawn)!=AURA && GetSpawnType(pSpawn)!=BANNER && GetSpawnType(pSpawn)!=CAMPFIRE) + Dest.DWord=pSpawn->Class; + else + if (GetSpawnType(pSpawn)==AURA) + Dest.DWord=0xFF; + else if (GetSpawnType(pSpawn)==BANNER) + Dest.DWord=0xFE; + else + Dest.DWord=0xFD; + Dest.Type=pClassType; + return true; + case Body: + Dest.DWord=GetBodyType(pSpawn); + Dest.Type=pBodyType; + return true; + case GM: + Dest.DWord=pSpawn->GM; + Dest.Type=pBoolType; + return true; + case Levitating: + Dest.DWord=(pSpawn->Levitate==2); + Dest.Type=pBoolType; + return true; + case Sneaking: + Dest.DWord=pSpawn->Sneak; + Dest.Type=pBoolType; + return true; + case Invis: + Dest.DWord=pSpawn->HideMode; + Dest.Type=pBoolType; + return true; + case Height: + Dest.Float=pSpawn->AvatarHeight; + Dest.Type=pFloatType; + return true; + case MaxRange: + if (GetSpawnType(pSpawn)!=ITEM) + { + Dest.Float=get_melee_range((EQPlayer*)pSpawn,(EQPlayer*)pSpawn); + Dest.Type=pFloatType; + return true; + } + return false; + case MaxRangeTo: + if (GetSpawnType(pSpawn)!=ITEM) + { + Dest.Float=get_melee_range(pLocalPlayer,(EQPlayer*)pSpawn); + Dest.Type=pFloatType; + return true; + } + return false; + case Guild: + if (pSpawn->GuildID != 0xFFFFFFFF) + { + if(char *szGuild = GetGuildByID(pSpawn->GuildID)) + { + Dest.Ptr=szGuild; + Dest.Type=pStringType; + return true; + } + } + return false; + case GuildStatus: + if (pSpawn->GuildID != 0xFFFFFFFF) + { + Dest.Ptr=szGuildStatus[pSpawn->GuildStatus]; + Dest.Type=pStringType; + return true; + } + return false; + case Type: + switch(GetSpawnType(pSpawn)) + { + case MOUNT: + Dest.Ptr="Mount"; + Dest.Type=pStringType; + return true; + case UNTARGETABLE: + Dest.Ptr="Untargetable"; + Dest.Type=pStringType; + return true; + case NPC: + Dest.Ptr="NPC"; + Dest.Type=pStringType; + return true; + case PC: + Dest.Ptr="PC"; + Dest.Type=pStringType; + return true; + case CHEST: + Dest.Ptr="Chest"; + Dest.Type=pStringType; + return true; + case TRAP: + Dest.Ptr="Trap"; + Dest.Type=pStringType; + return true; + case TRIGGER: + Dest.Ptr="Trigger"; + Dest.Type=pStringType; + return true; + case TIMER: + Dest.Ptr="Timer"; + Dest.Type=pStringType; + return true; + case PET: + Dest.Ptr="Pet"; + Dest.Type=pStringType; + return true; + case ITEM: + Dest.Ptr="Item"; + Dest.Type=pStringType; + return true; + case CORPSE: + Dest.Ptr="Corpse"; + Dest.Type=pStringType; + return true; + case AURA: + Dest.Ptr="Aura"; + Dest.Type=pStringType; + return true; + case OBJECT: + Dest.Ptr="Object"; + Dest.Type=pStringType; + return true; + case BANNER: + Dest.Ptr="Banner"; + Dest.Type=pStringType; + return true; + case CAMPFIRE: + Dest.Ptr="Campfire"; + Dest.Type=pStringType; + return true; + case MERCENARY: + Dest.Ptr="Mercenary"; + Dest.Type=pStringType; + return true; + case FLYER: + Dest.Ptr="Flyer"; + Dest.Type=pStringType; + return true; + } + return false; + case Light: + Dest.Ptr=GetLightForSpawn(pSpawn); + Dest.Type=pStringType; + return true; + case StandState: + Dest.Int=pSpawn->StandState; + Dest.Type=pIntType; + return true; + case State: + if (GetCharInfo() && GetCharInfo()->Stunned==1) + { + Dest.Ptr="STUN"; + } + else if(pSpawn == (PSPAWNINFO)pLocalPlayer && pSpawn->RespawnTimer) + { + Dest.Ptr="HOVER"; + } + else if(pSpawn->Mount) + { + Dest.Ptr="MOUNT"; + } + else + switch (pSpawn->StandState) + { + case STANDSTATE_STAND: + Dest.Ptr="STAND"; + break; + case STANDSTATE_SIT: + Dest.Ptr="SIT"; + break; + case STANDSTATE_DUCK: + Dest.Ptr="DUCK"; + break; + case STANDSTATE_BIND: + Dest.Ptr="BIND"; + break; + case STANDSTATE_FEIGN: + Dest.Ptr="FEIGN"; + break; + case STANDSTATE_DEAD: + Dest.Ptr="DEAD"; + break; + default: + Dest.Ptr="UNKNOWN"; + break; + } + Dest.Type=pStringType; + return true; + case Standing: + Dest.DWord=pSpawn->StandState==STANDSTATE_STAND; + Dest.Type=pBoolType; + return true; + case Sitting: + Dest.DWord=pSpawn->StandState==STANDSTATE_SIT; + Dest.Type=pBoolType; + return true; + case Ducking: + Dest.DWord=pSpawn->StandState==STANDSTATE_DUCK; + Dest.Type=pBoolType; + return true; + case Feigning: + Dest.DWord=pSpawn->StandState==STANDSTATE_FEIGN; + Dest.Type=pBoolType; + return true; + case Binding: + Dest.DWord=pSpawn->StandState==STANDSTATE_BIND; + Dest.Type=pBoolType; + return true; + case Dead: + Dest.DWord=pSpawn->StandState==STANDSTATE_DEAD; + Dest.Type=pBoolType; + return true; + case Stunned: + Dest.DWord=(GetCharInfo() && GetCharInfo()->Stunned==1); + Dest.Type=pBoolType; + return true; + case Hovering: + Dest.DWord=(pSpawn->RespawnTimer); + Dest.Type=pBoolType; + return true; + case Deity: + Dest.DWord=pSpawn->Deity; + Dest.Type=pDeityType; + return true; + case Distance: + Dest.Float=GetDistance(pSpawn->X,pSpawn->Y); + Dest.Type=pFloatType; + return true; + case Distance3D: + Dest.Float=DistanceToSpawn3D((PSPAWNINFO)pCharSpawn,pSpawn); + Dest.Type=pFloatType; + return true; + case DistancePredict: + Dest.Float=EstimatedDistanceToSpawn((PSPAWNINFO)pCharSpawn,pSpawn); + Dest.Type=pFloatType; + return true; + case DistanceW: + case DistanceX: + Dest.Float=(FLOAT)fabs(((PSPAWNINFO)pCharSpawn)->X-pSpawn->X); + Dest.Type=pFloatType; + return true; + case DistanceN: + case DistanceY: + Dest.Float=(FLOAT)fabs(((PSPAWNINFO)pCharSpawn)->Y-pSpawn->Y); + Dest.Type=pFloatType; + return true; + case DistanceU: + case DistanceZ: + Dest.Float=(FLOAT)fabs(((PSPAWNINFO)pCharSpawn)->Z-pSpawn->Z); + Dest.Type=pFloatType; + return true; + case HeadingTo: + Dest.Float=(FLOAT)(atan2f(((PSPAWNINFO)pCharSpawn)->Y - pSpawn->Y, pSpawn->X - ((PSPAWNINFO)pCharSpawn)->X) * 180.0f / PI + 90.0f); + if (Dest.Float<0.0f) + Dest.Float += 360.0f; + else if (Dest.Float>=360.0f) + Dest.Float -= 360.0f; + Dest.Type=pHeadingType; + return true; + case Casting: + if (Dest.Ptr=GetSpellByID(pSpawn->CastingData.SpellID)) + { + Dest.Type=pSpellType; + return true; + } + return false; + case Mount: + if (Dest.Ptr=pSpawn->Mount) + { + Dest.Type=pSpawnType; + return true; + } + return false; + case Underwater: + Dest.DWord=(pSpawn->UnderWater==5); + Dest.Type=pBoolType; + return true; + case FeetWet: + Dest.DWord=(pSpawn->FeetWet==5); + Dest.Type=pBoolType; + return true; + case Animation: + Dest.DWord=pSpawn->Animation; + Dest.Type=pIntType; + return true; + case Holding: + Dest.DWord=pSpawn->Holding; + Dest.Type=pIntType; + return true; + case Look: + Dest.Float=pSpawn->CameraAngle; + Dest.Type=pFloatType; + return true; + case xConColor: + switch(ConColor(pSpawn)) + { + case CONCOLOR_GREY: + Dest.Ptr="GREY"; + break; + case CONCOLOR_GREEN: + Dest.Ptr="GREEN"; + break; + case CONCOLOR_LIGHTBLUE: + Dest.Ptr="LIGHT BLUE"; + break; + case CONCOLOR_BLUE: + Dest.Ptr="BLUE"; + break; + case CONCOLOR_WHITE: + Dest.Ptr="WHITE"; + break; + case CONCOLOR_YELLOW: + Dest.Ptr="YELLOW"; + break; + case CONCOLOR_RED: + default: + Dest.Ptr="RED"; + break; + } + Dest.Type=pStringType; + return true; + case Invited: + Dest.DWord=(pSpawn->InvitedToGroup); + Dest.Type=pBoolType; + return true; +#ifndef ISXEQ + case NearestSpawn: + if (pSpawn==(PSPAWNINFO)pCharSpawn) + { + return (dataNearestSpawn(Index,Dest)!=0);// use top-level object if it's you + } + if (ISINDEX()) + { + PCHAR pSearch; + unsigned long nth; + SEARCHSPAWN ssSpawn; + ClearSearchSpawn(&ssSpawn); + ssSpawn.FRadius=999999.0f; + if (pSearch=strchr(Index,',')) + { + *pSearch=0; + ++pSearch; + ParseSearchSpawn(pSearch,&ssSpawn); + nth=GETNUMBER(); + } + else + { + if (ISNUMBER()) + { + nth=GETNUMBER(); + } + else + { + nth=1; + ParseSearchSpawn(Index,&ssSpawn); + } + } + if (Dest.Ptr=NthNearestSpawn(&ssSpawn,nth,pSpawn)) + { + Dest.Type=pSpawnType; + return true; + } + } + return false; +#else + case NearestSpawn: + if (pSpawn==(PSPAWNINFO)pCharSpawn) + { + return (dataNearestSpawn(argc,argv,Dest)!=0);// use top-level object if it's you + } + if (argc) + { + unsigned long nth; + SEARCHSPAWN ssSpawn; + ClearSearchSpawn(&ssSpawn); + ssSpawn.FRadius=999999.0f; + if (argc>=2 || !IsNumber(argv[0])) + { + ParseSearchSpawn(1,argc,argv,ssSpawn); + nth=atoi(argv[0]); + } + else + { + nth=atoi(argv[0]); + } + if (Dest.Ptr=NthNearestSpawn(&ssSpawn,nth,pSpawn)) + { + Dest.Type=pSpawnType; + return true; + } + } + return false; +#endif + case Trader: + Dest.DWord=pSpawn->Trader; + Dest.Type=pBoolType; + return true; + case AFK: + Dest.DWord=pSpawn->AFK; + Dest.Type=pBoolType; + return true; + case LFG: + Dest.DWord=pSpawn->LFG; + Dest.Type=pBoolType; + return true; + case Linkdead: + Dest.DWord=pSpawn->Linkdead; + Dest.Type=pBoolType; + return true; + case AATitle: // Leaving this in for older macros/etc.."Title" should be used instead. + Dest.Type=pStringType; + Dest.Ptr=&pSpawn->Title[0]; + return true; + case Title: + Dest.Type=pStringType; + Dest.Ptr=&pSpawn->Title[0]; + return true; + case Suffix: + Dest.Type=pStringType; + Dest.Ptr=&pSpawn->Suffix[0]; + return true; + case xGroupLeader: + if (GetCharInfo()->pGroupInfo && GetCharInfo()->pGroupInfo->pLeader) + { + CHAR Name[MAX_STRING]={0}; + GetCXStr(GetCharInfo()->pGroupInfo->pLeader->pName,Name,MAX_STRING); + Dest.DWord=(pSpawn->Type==SPAWN_PLAYER && !stricmp(Name,pSpawn->Name)); + Dest.Type=pBoolType; + return true; + } + return false; + case Assist: + if (gGameState==GAMESTATE_INGAME && GetCharInfo()->pSpawn && pSpawn) + { + DWORD nAssist; + { + if (GetCharInfo()->pSpawn->GroupAssistNPC[0]==pSpawn->SpawnID) + { + Dest.DWord=1; + Dest.Type=pBoolType; + return true; + } + } + for (nAssist=0 ; nAssist < 3 ; nAssist++) + { + if (GetCharInfo()->pSpawn->RaidAssistNPC[nAssist]==pSpawn->SpawnID) + { + Dest.DWord=1; + Dest.Type=pBoolType; + return true; + } + } + } + Dest.DWord=0; + Dest.Type=pBoolType; + return true; + case Mark: + if (gGameState==GAMESTATE_INGAME && GetCharInfo()->pSpawn && pSpawn) + { + DWORD nMark; + for (nMark=0 ; nMark < 3 ; nMark++) + { + if (GetCharInfo()->pSpawn->RaidMarkNPC[nMark]==pSpawn->SpawnID) + { + Dest.DWord=nMark+1; + Dest.Type=pIntType; + return true; + } + } + for (nMark=0 ; nMark < 3 ; nMark++) + { + if (GetCharInfo()->pSpawn->GroupMarkNPC[nMark]==pSpawn->SpawnID) + { + Dest.DWord=nMark+1; + Dest.Type=pIntType; + return true; + } + } + } + return false; + case Anonymous: + Dest.DWord=(pSpawn->Anon==1); + Dest.Type=pBoolType; + return true; + case Roleplaying: + Dest.DWord=(pSpawn->Anon==2); + Dest.Type=pBoolType; + return true; + case xLineOfSight: + Dest.DWord=(LineOfSight(GetCharInfo()->pSpawn,pSpawn)); + Dest.Type=pBoolType; + return true; + case HeadingToLoc: +#ifndef ISXEQ + if (!ISINDEX()) + return false; + if (PCHAR pComma=strchr(Index,',')) + { + *pComma=0; + FLOAT Y=(FLOAT)atof(Index); + *pComma=','; + FLOAT X=(FLOAT)atof(&pComma[1]); +#else + if (!argc) + return false; + if (argc==2) + { + FLOAT Y=(FLOAT)atof(argv[0]); + FLOAT X=(FLOAT)atof(argv[1]); +#endif + Dest.Float=(FLOAT)(atan2f(pSpawn->Y - Y, X - pSpawn->X) * 180.0f / PI + 90.0f); + if (Dest.Float<0.0f) + Dest.Float += 360.0f; + else if (Dest.Float>=360.0f) + Dest.Float -= 360.0f; + Dest.Type=pHeadingType; + return true; + } + return false; + case Fleeing: + Dest.DWord=IsMobFleeing(GetCharInfo()->pSpawn,pSpawn); + Dest.Type=pBoolType; + return true; + case Named: + Dest.DWord=IsNamed(pSpawn); + Dest.Type=pBoolType; + return true; + case Buyer: + Dest.DWord=pSpawn->Buyer; + Dest.Type=pBoolType; + return true; + case Moving: + Dest.DWord=fabs(pSpawn->SpeedRun)>0.0f; + Dest.Type=pBoolType; + return true; + case CurrentMana: + Dest.DWord=pSpawn->ManaCurrent; + Dest.Type=pIntType; + return true; + case MaxMana: + Dest.DWord=pSpawn->ManaMax; + Dest.Type=pIntType; + return true; + case CurrentEndurance: + Dest.DWord=pSpawn->EnduranceCurrent; + Dest.Type=pIntType; + return true; + case MaxEndurance: + Dest.DWord=pSpawn->EnduranceMax; + Dest.Type=pIntType; + return true; + case Loc: + sprintf(DataTypeTemp,"%.2f, %.2f",pSpawn->Y,pSpawn->X); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + case LocYX: + sprintf(DataTypeTemp,"%.0f, %.0f",pSpawn->Y,pSpawn->X); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + case Owner: + if(pSpawn->Mercenary) + { + unsigned int pos = strchr(pSpawn->Lastname, '\'') - &pSpawn->Lastname[0]; + strncpy(DataTypeTemp, pSpawn->Lastname, pos); + DataTypeTemp[pos] = 0; + if(PSPAWNINFO pOwner = (PSPAWNINFO)GetSpawnByName(DataTypeTemp)) + { + Dest.Ptr = pOwner; + Dest.Type = pSpawnType; + return true; + } + return false; + } + return false; + case Following: + if(Dest.Ptr = pSpawn->WhoFollowing) + { + Dest.Type = pSpawnType; + return true; + } + } + return false; +} + + +bool MQ2BuffType::GETMEMBER() +{ +#define pBuff ((PSPELLBUFF)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + if ((int)pBuff->SpellID<=0) + return false; + PMQ2TYPEMEMBER pMember=MQ2BuffType::FindMember(Member); + if (!pMember) + { + if (PSPELL pSpell=GetSpellByID(pBuff->SpellID)) + { +#ifndef ISXEQ + return pSpellType->GetMember(*(MQ2VARPTR*)&pSpell,Member,Index,Dest); +#else + return pSpellType->GetMember(*(LSVARPTR*)&pSpell,Member,argc,argv,Dest); +#endif + } + return false; + } + + static CHAR Temp[128]; + switch((BuffMembers)pMember->ID) + { + case ID: + { + if (GetBuffID(pBuff,(DWORD&)Dest.DWord)) + { + Dest.Type=pIntType; + return true; + } + if (GetShortBuffID(pBuff,(DWORD&)Dest.DWord)) + { + Dest.Type=pIntType; + return true; + } + } + return false; + case Level: + Dest.DWord=pBuff->Level; + Dest.Type=pIntType; + return true; + case Spell: + if (Dest.Ptr=GetSpellByID(pBuff->SpellID)) + { + Dest.Type=pSpellType; + return true; + } + return false; + case Mod: + Dest.Float=(((float)pBuff->Modifier)/10.0f); + if (Dest.Float!=1.0f) + { + Dest.Type=pFloatType; + return true; + } + return false; + case Duration: + Dest.DWord=pBuff->Duration+1;// 0 is actually 6 seconds ;) + Dest.Type=pTicksType; + return true; + case Dar: +#if 0 + if(PSPELL pSpell = GetSpellByID(pBuff->SpellID)) + { + if(pSpell->SpellType != 0) + { + Dest.DWord=pBuff->DamageAbsorbRemaining; + Dest.Type=pIntType; + return true; + } + } +#endif + return false; + case Counters: +#if 0 + if(GetSpellByID(pBuff->SpellID)->SpellType == 0) + { + Dest.DWord=pBuff->Counters; + Dest.Type=pIntType; + return true; + } +#endif + return false; + } + return false; +#undef pBuff +} + + +bool MQ2CharacterType::GETMEMBER() +{ +#define pChar ((PCHARINFO)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMEMBER pMember=MQ2CharacterType::FindMember(Member); + if (!pMember) + { +#ifndef ISXEQ + return pSpawnType->GetMember(*(MQ2VARPTR*)&pChar->pSpawn,Member,Index,Dest); +#else + return pSpawnType->GetMember(*(LSVARPTR*)&pChar->pSpawn,Member,argc,argv,Dest); +#endif + } + + int nLang = 0; + char buf[MAX_STRING] = {0}; + unsigned long nBuff; + char buf2[MAX_STRING] = {0}; + + switch((CharacterMembers)pMember->ID) + { + case ID: + Dest.DWord=pChar->pSpawn->SpawnID; + Dest.Type=pIntType; + return true; + case Name: + Dest.Ptr=&pChar->Name[0]; + Dest.Type=pStringType; + return true; + case Surname: + Dest.Ptr=&pChar->Lastname[0]; + Dest.Type=pStringType; + return true; + case Level: + Dest.DWord=GetCharInfo2()->Level; + Dest.Type=pIntType; + return true; + case Exp: + Dest.DWord=pChar->Exp; + Dest.Type=pIntType; + return true; + case PctExp: + Dest.Float=(float)pChar->Exp/3.30f; + Dest.Type=pFloatType; + return true; + case PctAAExp: + Dest.Float=(float)pChar->AAExp/3.30f; + Dest.Type=pFloatType; + return true; + case Spawn: + Dest.Ptr=pChar->pSpawn; + Dest.Type=pSpawnType; + return true; + case CurrentHPs: + Dest.DWord=GetCurHPS(); + Dest.Type=pIntType; + return true; + case MaxHPs: + Dest.Type=pIntType; + Dest.Int=GetMaxHPS(); + return true; + case PctHPs: + Dest.Type=pIntType; + Dest.Int=GetCurHPS()*100/GetMaxHPS(); + return true; + case CurrentMana: + Dest.DWord=GetCharInfo2()->Mana; + Dest.Type=pIntType; + return true; + case MaxMana: + Dest.DWord=GetMaxMana(); + Dest.Type=pIntType; + return true; + case PctMana: + { + if (unsigned long Temp=GetMaxMana()) + Dest.DWord=GetCharInfo2()->Mana*100/Temp; + else + Dest.DWord=0; + Dest.Type=pIntType; + } + return true; + case CountBuffs: + Dest.DWord=0; + { + for (unsigned long nBuff=0 ; nBuffBuff[nBuff].SpellID>0) + Dest.DWord++; + } + Dest.Type=pIntType; + } + return true; + case Buff: + if (!ISINDEX()) + return false; + if (ISNUMBER()) + { + unsigned long nBuff=GETNUMBER()-1; + if (nBuff>=NUM_LONG_BUFFS) + return false; + if (GetCharInfo2()->Buff[nBuff].SpellID<=0) + return false; + Dest.Ptr=&GetCharInfo2()->Buff[nBuff]; + Dest.Type=pBuffType; + return true; + } + else + { + for (unsigned long nBuff=0 ; nBuff < NUM_LONG_BUFFS ; nBuff++) + { + if (PSPELL pSpell=GetSpellByID(GetCharInfo2()->Buff[nBuff].SpellID)) + { + if (!stricmp(GETFIRST(),pSpell->Name)) + { + Dest.Ptr=&GetCharInfo2()->Buff[nBuff]; + Dest.Type=pBuffType; + return true; + } + } + } + } + return false; + case Song: + if (!ISINDEX()) + return false; + if (ISNUMBER()) + { + unsigned long nBuff=GETNUMBER()-1; + if (nBuff>=NUM_SHORT_BUFFS) + return false; + if (GetCharInfo2()->ShortBuff[nBuff].SpellID<=0) + return false; + + Dest.Ptr=&GetCharInfo2()->ShortBuff[nBuff]; + Dest.Type=pBuffType; + return true; + } + else + { + for (unsigned long nBuff=0 ; nBuff < 35 ; nBuff++) + { + if (PSPELL pSpell=GetSpellByID(GetCharInfo2()->ShortBuff[nBuff].SpellID)) + { + if (!stricmp(GETFIRST(),pSpell->Name)) + { + Dest.Ptr=&GetCharInfo2()->ShortBuff[nBuff]; + Dest.Type=pBuffType; + return true; + } + } + } + } + return false; + case HPBonus: + Dest.DWord=pChar->HPBonus; + Dest.Type=pIntType; + return true; + case ManaBonus: + Dest.DWord=pChar->ManaBonus; + Dest.Type=pIntType; + return true; + case EnduranceBonus: + Dest.DWord=pChar->EnduranceBonus; + Dest.Type=pIntType; + return true; + case CombatEffectsBonus: + Dest.DWord=(pChar->CombatEffectsBonus > pChar->CombatEffectsCap ? pChar->CombatEffectsCap : pChar->CombatEffectsBonus); + Dest.Type=pIntType; + return true; + case ShieldingBonus: + Dest.DWord=(pChar->ShieldingBonus > pChar->ShieldingCap ? pChar->ShieldingCap : pChar->ShieldingBonus); + Dest.Type=pIntType; + return true; + case SpellShieldBonus: + Dest.DWord=(pChar->SpellShieldBonus > pChar->SpellShieldCap ? pChar->SpellShieldCap : pChar->SpellShieldBonus); + Dest.Type=pIntType; + return true; + case AvoidanceBonus: + Dest.DWord=(pChar->AvoidanceBonus > pChar->AvoidanceCap ? pChar->AvoidanceCap : pChar->AvoidanceBonus); + Dest.Type=pIntType; + return true; + case AccuracyBonus: + Dest.DWord=(pChar->AccuracyBonus > pChar->AccuracyCap ? pChar->AccuracyCap : pChar->AccuracyBonus); + Dest.Type=pIntType; + return true; + case StunResistBonus: + Dest.DWord=(pChar->StunResistBonus > pChar->StunResistCap ? pChar->StunResistCap : pChar->StunResistBonus); + Dest.Type=pIntType; + return true; + case StrikeThroughBonus: + Dest.DWord=(pChar->StrikeThroughBonus > pChar->StrikeThroughCap ? pChar->StrikeThroughCap : pChar->StrikeThroughBonus); + Dest.Type=pIntType; + return true; + case DoTShieldBonus: + Dest.DWord=(pChar->DoTShieldBonus > pChar->DoTShieldCap ? pChar->DoTShieldCap : pChar->DoTShieldBonus); + Dest.Type=pIntType; + return true; + case AttackBonus: + Dest.DWord=pChar->AttackBonus; + Dest.Type=pIntType; + return true; + case HPRegenBonus: + Dest.DWord=pChar->HPRegenBonus; + Dest.Type=pIntType; + return true; + case ManaRegenBonus: + Dest.DWord=pChar->ManaRegenBonus; + Dest.Type=pIntType; + return true; + case DamageShieldBonus: + Dest.DWord=(pChar->DamageShieldBonus > pChar->DamageShieldCap ? pChar->DamageShieldCap : pChar->DamageShieldBonus); + Dest.Type=pIntType; + return true; + case DamageShieldMitigationBonus: + Dest.DWord=(pChar->DamageShieldMitigationBonus > pChar->DamageShieldMitigationCap ? pChar->DamageShieldMitigationCap : pChar->DamageShieldMitigationBonus); + Dest.Type=pIntType; + return true; + case HeroicSTRBonus: + Dest.DWord=pChar->HeroicSTRBonus; + Dest.Type=pIntType; + return true; + case HeroicINTBonus: + Dest.DWord=pChar->HeroicINTBonus; + Dest.Type=pIntType; + return true; + case HeroicWISBonus: + Dest.DWord=pChar->HeroicWISBonus; + Dest.Type=pIntType; + return true; + case HeroicAGIBonus: + Dest.DWord=pChar->HeroicAGIBonus; + Dest.Type=pIntType; + return true; + case HeroicDEXBonus: + Dest.DWord=pChar->HeroicDEXBonus; + Dest.Type=pIntType; + return true; + case HeroicSTABonus: + Dest.DWord=pChar->HeroicSTABonus; + Dest.Type=pIntType; + return true; + case HeroicCHABonus: + Dest.DWord=pChar->HeroicCHABonus; + Dest.Type=pIntType; + return true; + case HealAmountBonus: + Dest.DWord=pChar->HealAmountBonus; + Dest.Type=pIntType; + return true; + case SpellDamageBonus: + Dest.DWord=pChar->SpellDamageBonus; + Dest.Type=pIntType; + return true; + case ClairvoyanceBonus: + Dest.DWord=pChar->ClairvoyanceBonus; + Dest.Type=pIntType; + return true; + case EnduranceRegenBonus: + Dest.DWord=pChar->EnduranceRegenBonus; + Dest.Type=pIntType; + return true; + case AttackSpeed: + Dest.DWord=pChar->AttackSpeed; + Dest.Type=pIntType; + return true; + case Endurance: //Grandfathered, CurrentEndurance should be used instead. + Dest.DWord=GetCharInfo2()->Endurance; + Dest.Type=pIntType; + return true; + case CurrentEndurance: + Dest.DWord=GetCharInfo2()->Endurance; + Dest.Type=pIntType; + return true; + case MaxEndurance: + Dest.DWord=GetMaxEndurance(); + Dest.Type=pIntType; + return true; + case PctEndurance: + { + if (unsigned long Temp=GetMaxEndurance()) + Dest.DWord=(GetCharInfo2()->Endurance*100)/Temp; + else + Dest.DWord=0; + Dest.Type=pIntType; + } + return true; + case GukEarned: + return false;//TODO + //Dest.DWord=pChar->GukEarned; + Dest.Type=pIntType; + return true; + case MMEarned: + return false;//TODO + //Dest.DWord=pChar->MMEarned; + Dest.Type=pIntType; + return true; + case RujEarned: + return false;//TODO + //Dest.DWord=pChar->RujEarned; + Dest.Type=pIntType; + return true; + case TakEarned: + return false;//TODO + //Dest.DWord=pChar->TakEarned; + Dest.Type=pIntType; + return true; + case MirEarned: + return false;//TODO + //Dest.DWord=pChar->MirEarned; + Dest.Type=pIntType; + return true; + case LDoNPoints: + return false;//TODO + //Dest.DWord=pChar->LDoNPoints; + Dest.Type=pIntType; + return true; + case CurrentFavor: + Dest.DWord=pChar->CurrFavor; + Dest.Type=pIntType; + return true; + case CareerFavor: + Dest.DWord=pChar->CareerFavor; + Dest.Type=pIntType; + return true; + case Inventory: + if (ISINDEX()) + { + if (ISNUMBER()) + { + unsigned long nSlot=GETNUMBER(); + if (nSlot<0x800) + { + if (Dest.Ptr=GetCharInfo2()->pInventoryArray->InventoryArray[nSlot]) + { + Dest.Type=pItemType; + return true; + } + } + } + else + { + for (unsigned long nSlot=0 ; szItemSlot[nSlot] ; nSlot++) + { + if (!stricmp(GETFIRST(),szItemSlot[nSlot])) + { + if (Dest.Ptr=GetCharInfo2()->pInventoryArray->InventoryArray[nSlot]) + { + Dest.Type=pItemType; + return true; + } + } + } + } + } + return false; + case Bank: + if (ISINDEX()) + { + if (ISNUMBER()) + { + unsigned long nSlot=GETNUMBER()-1; + if (nSlotpBankArray->Bank[nSlot]) + { + Dest.Type=pItemType; + return true; + } + } else { + nSlot -= NUM_BANK_SLOTS; + if (nSlotpSharedBankArray->SharedBank[nSlot]) + { + Dest.Type=pItemType; + return true; + } + } + } + } + } + return false; + case PlatinumShared: + Dest.DWord=pChar->BankSharedPlat; + Dest.Type=pIntType; + return true; + case Cash: + Dest.DWord=GetCharInfo2()->Plat*1000+GetCharInfo2()->Gold*100+GetCharInfo2()->Silver*10+GetCharInfo2()->Copper; + Dest.Type=pIntType; + return true; + case Platinum: + Dest.DWord=GetCharInfo2()->Plat; + Dest.Type=pIntType; + return true; + case Gold: + Dest.DWord=GetCharInfo2()->Gold; + Dest.Type=pIntType; + return true; + case Silver: + Dest.DWord=GetCharInfo2()->Silver; + Dest.Type=pIntType; + return true; + case Copper: + Dest.DWord=GetCharInfo2()->Copper; + Dest.Type=pIntType; + return true; + case CashBank: + Dest.DWord=pChar->BankPlat*1000+pChar->BankGold*100+pChar->BankSilver*10+pChar->BankCopper; + Dest.Type=pIntType; + return true; + case PlatinumBank: + Dest.DWord=pChar->BankPlat; + Dest.Type=pIntType; + return true; + case GoldBank: + Dest.DWord=pChar->BankGold; + Dest.Type=pIntType; + return true; + case SilverBank: + Dest.DWord=pChar->BankSilver; + Dest.Type=pIntType; + return true; + case CopperBank: + Dest.DWord=pChar->BankCopper; + Dest.Type=pIntType; + return true; + case AAExp: + Dest.DWord=pChar->AAExp; + Dest.Type=pIntType; + return true; + case AAPoints: + Dest.DWord=GetCharInfo2()->AAPoints; + Dest.Type=pIntType; + return true; + case Combat: + Dest.DWord=*EQADDR_ATTACK; + Dest.Type=pBoolType; + return true; + case HPRegen: + Dest.DWord=HealthGained; + Dest.Type=pIntType; + return true; + case ManaRegen: + Dest.DWord=ManaGained; + Dest.Type=pIntType; + return true; + case EnduranceRegen: + Dest.DWord=EnduranceGained; + Dest.Type=pIntType; + return true; + case Dar: +#if 0 + Dest.DWord=0; + { + for (unsigned long k=0; kBuff[k].SpellID)) + if(pSpell->SpellType != 0) + if(GetCharInfo2()->Buff[k].DamageAbsorbRemaining) + Dest.DWord+=GetCharInfo2()->Buff[k].DamageAbsorbRemaining; + else if(GetCharInfo2()->Buff[k].DamageAbsorbRemaining2) + Dest.DWord+=GetCharInfo2()->Buff[k].DamageAbsorbRemaining2; + else if(GetCharInfo2()->Buff[k].DamageAbsorbRemaining3) + Dest.DWord+=GetCharInfo2()->Buff[k].DamageAbsorbRemaining3; + } + Dest.Type=pIntType; + return true; +#endif + return false; + case Grouped: + if(!pChar->pGroupInfo) return false; + Dest.DWord= pChar->pGroupInfo->pMember[1] || + pChar->pGroupInfo->pMember[2] || + pChar->pGroupInfo->pMember[3] || + pChar->pGroupInfo->pMember[4] || + pChar->pGroupInfo->pMember[5]; + Dest.Type=pBoolType; + return true; + case GroupList: // This isn't really working as intended just yet + { + if(!pChar->pGroupInfo) return false; + for(int i=1; i<6; i++) + if(pChar->pGroupInfo->pMember[i]) + { + char tmp[MAX_STRING]; + GetCXStr(pChar->pGroupInfo->pMember[i]->pName, tmp, sizeof(tmp)); + strcat(buf, tmp); + if(i<5 && pChar->pGroupInfo->pMember[i+1]) + strcat(buf, " "); + } + } + Dest.Ptr=&buf[0]; + Dest.Type=pStringType; + return true; + case AmIGroupLeader: + if (!pChar->pGroupInfo) return false; + if (!pChar->pGroupInfo->pLeader) return false; + GetCXStr(pChar->pGroupInfo->pLeader->pName, buf, sizeof(buf)); + if(!stricmp(buf, pChar->Name)) + Dest.Ptr="TRUE"; + else + Dest.Ptr="FALSE"; + Dest.Type=pStringType; + return true; + case FreeBuffSlots: + Dest.DWord=GetAAIndexByName("mystical attuning"); + if (PlayerHasAAAbility(Dest.DWord)) + { + for (unsigned int j=0; j < AA_CHAR_MAX_REAL; j++) + { + if ( pPCData->GetAltAbilityIndex(j) == Dest.DWord) + { + Dest.DWord=15+(GetCharInfo2()->AAList[j].PointsSpent/5); + break; + } + } + } else Dest.DWord = 15; + if(GetAAIndexByName("Embrace of the Dark Reign")) Dest.DWord++; + if(GetAAIndexByName("Embrace of the Keepers")) Dest.DWord++; + if(GetCharInfo()->pSpawn->Level > 71) Dest.DWord++; + if(GetCharInfo()->pSpawn->Level > 74) Dest.DWord++; + + for (nBuff=0 ; nBuffBuff[nBuff].SpellID>0) + Dest.DWord--; + } + Dest.Type = pIntType; + return true; + case Gem: + if (!ISINDEX()) + return false; + if (ISNUMBER()) + { + // number + unsigned long nGem=GETNUMBER()-1; + if (nGemMemorizedSpells[nGem])) + { + Dest.Type=pSpellType; + return true; + } + } + } + else + { + // name + for (unsigned long nGem=0 ; nGem < NUM_SPELL_GEMS ; nGem++) + { + if (PSPELL pSpell=GetSpellByID(GetCharInfo2()->MemorizedSpells[nGem])) + { + if (!stricmp(GETFIRST(),pSpell->Name)) + { + Dest.DWord=nGem+1; + Dest.Type=pIntType; + return true; + } + } + } + } + return false; + case LanguageSkill: + if (!ISINDEX()) + return false; + + if (ISNUMBER()) + nLang=GETNUMBER()-1; + else + nLang=GetLanguageIDByName(GETFIRST())-1; + + if (nLang < 0 || nLang >= 25 ) + return false; + + Dest.DWord=pChar->languages[nLang]; + Dest.Type=pIntType; + return true; + case CombatAbility: + if (!ISINDEX()) + return false; + if (ISNUMBER()) + { + // number + unsigned long nCombatAbility=GETNUMBER()-1; + if ( PSPELL pSpell = GetSpellByID(pPCData->GetCombatAbility(nCombatAbility)) ) + { + Dest.Ptr=pSpell; + Dest.Type=pSpellType; + return true; + } + } + else + { + // name + for (unsigned long nCombatAbility=0 ; nCombatAbility < NUM_COMBAT_ABILITIES ; nCombatAbility++) + { + if ( PSPELL pSpell = GetSpellByID(pPCData->GetCombatAbility(nCombatAbility)) ) + { + if (!stricmp(GETFIRST(),pSpell->Name)) + { + Dest.DWord=nCombatAbility+1; + Dest.Type=pIntType; + return true; + } + } + } + } + return false; + case CombatAbilityTimer: + if (ISINDEX()) + { + if (ISNUMBER()) + { + // number + unsigned long nCombatAbility=GETNUMBER()-1; + if ( PSPELL pSpell = GetSpellByID(pPCData->GetCombatAbility(nCombatAbility)) ) + { + DWORD timeNow = (DWORD)time(NULL); + if (pSpell->CARecastTimerID != -1 && pPCData->GetCombatAbilityTimer(pSpell->CARecastTimerID) > timeNow) + { + Dest.Int=pPCData->GetCombatAbilityTimer(pSpell->CARecastTimerID)-timeNow+6; + Dest.Int/=6; + } + else Dest.Int=0; + Dest.Type=pTicksType; + return true; + } + } + else + { + // by name + for (unsigned long nCombatAbility=0 ; nCombatAbility < NUM_COMBAT_ABILITIES ; nCombatAbility++) + { + if ( PSPELL pSpell = GetSpellByID(pPCData->GetCombatAbility(nCombatAbility)) ) + { + if (!stricmp(GETFIRST(),pSpell->Name)) + { + DWORD timeNow = (DWORD)time(NULL); + if (pSpell->CARecastTimerID != -1 && pPCData->GetCombatAbilityTimer(pSpell->CARecastTimerID) > timeNow) + { + Dest.Int=pPCData->GetCombatAbilityTimer(pSpell->CARecastTimerID)-timeNow+6; + Dest.Int/=6; + } + else Dest.Int=0; + Dest.Type=pTicksType; + return true; + } + } + } + } + } + return false; + case CombatAbilityReady: + Dest.DWord=0; + Dest.Type=pBoolType; + if (ISINDEX()) + { + if (ISNUMBER() && GETNUMBER()-1 < NUM_COMBAT_ABILITIES) + { + // number + unsigned long nCombatAbility=GETNUMBER()-1; + if ( PSPELL pSpell = GetSpellByID(pPCData->GetCombatAbility(nCombatAbility)) ) + { + DWORD timeNow = (DWORD)time(NULL); + if (pSpell->CARecastTimerID != -1 && pPCData->GetCombatAbilityTimer(pSpell->CARecastTimerID) < timeNow) + { + Dest.DWord=1; + return true; + } + } + } + else + { + // by name + for (unsigned long nCombatAbility=0 ; nCombatAbility < NUM_COMBAT_ABILITIES ; nCombatAbility++) + { + if ( PSPELL pSpell = GetSpellByID(pPCData->GetCombatAbility(nCombatAbility)) ) + { + if (!stricmp(GETFIRST(),pSpell->Name)) + { + DWORD timeNow = (DWORD)time(NULL); + if (pSpell->CARecastTimerID != -1 && pPCData->GetCombatAbilityTimer(pSpell->CARecastTimerID) < timeNow) + { + Dest.DWord=1; + return true; + } + } + } + } + } + } + return true; + case Moving: + Dest.DWord=((((gbMoving) && ((PSPAWNINFO)pCharSpawn)->SpeedRun==0.0f) && (pChar->pSpawn->Mount == NULL )) || (fabs(FindSpeed((PSPAWNINFO)pCharSpawn)) > 0.0f )); + Dest.Type=pBoolType; + return true; + case Hunger: + Dest.DWord=GetCharInfo2()->hungerlevel; + Dest.Type=pIntType; + return true; + case Thirst: + Dest.DWord=GetCharInfo2()->thirstlevel; + Dest.Type=pIntType; + return true; + case AltAbilityTimer: + if (ISINDEX()) { + if (ISNUMBER()) { + //numeric + for (unsigned long nAbility=0 ; nAbilityGetAltAbility(pPCData->GetAltAbilityIndex(nAbility)) ) { + if (pAbility->ID == GETNUMBER() ) { + pAltAdvManager->IsAbilityReady(pPCData,pAbility,&Dest.Int); + if (Dest.Int<0) + return false; + Dest.Int/=6; + Dest.Type=pTicksType; + return true; + } + } + } + } else { + // by name + for (unsigned long nAbility=0 ; nAbilityGetAltAbility(pPCData->GetAltAbilityIndex(nAbility)) ) { + if (PCHAR pName=pCDBStr->GetString(pAbility->nName, 1, NULL)) { + if (!stricmp(GETFIRST(),pName)) { + pAltAdvManager->IsAbilityReady(pPCData,pAbility,&Dest.Int); + if (Dest.Int<0) + return false; + Dest.Int/=6; + Dest.Type=pTicksType; + return true; + } + } + } + } + } + } + return false; + case AltAbilityReady: + if (ISINDEX()) { + if (ISNUMBER()) { + //numeric + for (unsigned long nAbility=0 ; nAbilityGetAltAbility(pPCData->GetAltAbilityIndex(nAbility)) ) { + if (pAbility->ID == GETNUMBER()) { + Dest.DWord=pAltAdvManager->IsAbilityReady(pPCData,pAbility,0); + Dest.Type=pBoolType; + return true; + } + } + } + } else { + // by name + for (unsigned long nAbility=0 ; nAbilityGetAltAbility(pPCData->GetAltAbilityIndex(nAbility)) ) { + if (PCHAR pName=pCDBStr->GetString(pAbility->nName, 1, NULL)) { + if (!stricmp(GETFIRST(),pName)) { + Dest.DWord=pAltAdvManager->IsAbilityReady(pPCData,pAbility,0); + Dest.Type=pBoolType; + return true; + } + } + } + } + } + } + return false; + case AltAbility: + if (ISINDEX()) { + if (ISNUMBER()) { + //numeric + for (unsigned long nAbility=0 ; nAbilityGetAltAbility(pPCData->GetAltAbilityIndex(nAbility)) ) { + if (pAbility->ID == GETNUMBER()) { + Dest.Ptr = pAbility; + Dest.Type = pAltAbilityType; + return true; + } + } + } + } else { + // by name + for (unsigned long nAbility=0 ; nAbilityGetAltAbility(pPCData->GetAltAbilityIndex(nAbility)) ) { + if (PCHAR pName=pCDBStr->GetString(pAbility->nName, 1, NULL)) { + if (!stricmp(GETFIRST(),pName)) { + Dest.Ptr = pAbility; + Dest.Type = pAltAbilityType; + return true; + } + } + } + } + } + } + return false; + case Skill: + if (ISINDEX()) + { + if (ISNUMBER()) + { + // numeric + unsigned long nSkill=GETNUMBER()-1; + if (nSkillSkill[nSkill]; + Dest.Type=pIntType; + if (!Dest.DWord) { + if(pSkillMgr->pSkill[nSkill]->Activated) { + for(int btn=0; !Dest.DWord && btn<10; btn++) { + if(EQADDR_DOABILITYLIST[btn]==nSkill) Dest.DWord=1; + } + } + } + return true; + } + } + else + { + // name + for (DWORD nSkill=0;nSkillSkill[nSkill]; + Dest.Type=pIntType; + // note: this change fixes the problem where ${Me.Skill[Forage]} returns + // 0 even if you have bought the aa for cultural forage... + if (!Dest.DWord) { + if(pSkillMgr->pSkill[nSkill]->Activated) { + for(int btn=0; !Dest.DWord && btn<10; btn++) { + if(EQADDR_DOABILITYLIST[btn]==nSkill) Dest.DWord=1; + } + } + } + return true; + } + } + } + return false; + + case SkillCap: + if (ISINDEX()) { + class PcZoneClient *p = (PcZoneClient *)GetCharInfo(); + unsigned long nSkill = 0; + + if (ISNUMBER()) { + // numeric + nSkill=GETNUMBER()-1; + } else { + for (nSkill=0;nSkillGetPcSkillLimit(nSkill); + return true; + } + } + return false; + + case Ability: + if (ISINDEX()) + { + if (ISNUMBER()) + { + // numeric + if (unsigned long nSkill=GETNUMBER()) + { + if (nSkill<7) + { + nSkill+=3; + } + else if (nSkill<11) + { + nSkill-=7; + } + else + return false; + if (EQADDR_DOABILITYLIST[nSkill]!=0xFFFFFFFF) + { + Dest.Ptr=szSkills[EQADDR_DOABILITYLIST[nSkill]]; + Dest.Type=pStringType; + return true; + } + } + } + else + { + // name + for (DWORD nSkill=0;szSkills[nSkill];nSkill++) + if (!stricmp(GETFIRST(),szSkills[nSkill])) + { + // found name + for (DWORD nAbility=0;nAbility<10;nAbility++) + if (EQADDR_DOABILITYLIST[nAbility] == nSkill) + { + if (nAbility<4) + nAbility+=7; + else + nAbility-=3; + Dest.DWord=nAbility; + Dest.Type=pIntType; + return true; + } + } + } + } + return false; + case AbilityReady: + if (ISINDEX()) + { + if (ISNUMBER()) + { + // numeric + if (unsigned long nSkill=GETNUMBER()) + { + if (nSkill<7) + { + nSkill+=3; + } + else if (nSkill<11) + { + nSkill-=7; + } + else + return false; + /**/ + if (EQADDR_DOABILITYLIST[nSkill]!=0xFFFFFFFF) + { + //if (pSkillMgr->pSkill[EQADDR_DOABILITYLIST[nSkill]]->AltTimer==2) + // Dest.DWord=gbAltTimerReady; + //else + Dest.DWord=pCSkillMgr->IsAvailable(EQADDR_DOABILITYLIST[nSkill]); + Dest.Type=pBoolType; + return true; + } + } + } + else + { + // name + for (DWORD nSkill=0;szSkills[nSkill];nSkill++) + { + if (!stricmp(GETFIRST(),szSkills[nSkill])) + { + // found name + for (DWORD nAbility=0;nAbility<10;nAbility++) + { + if (EQADDR_DOABILITYLIST[nAbility] == nSkill) + { + // thanks s0rcier! + if (nSkill<100 || nSkill == 111 || nSkill == 114 || nSkill == 115 || nSkill == 116) + { + //if (pSkillMgr->pSkill[nSkill]->AltTimer==2) // this check is included in CSkillMgr::IsAvailable + // Dest.DWord=gbAltTimerReady; + //else + Dest.DWord=pCSkillMgr->IsAvailable(EQADDR_DOABILITYLIST[nAbility]); + Dest.Type=pBoolType; + return true; + } + //if (nSkill==111) { // this check is included in CSkillMgr::IsAvailable + // Dest.DWord=gbAltTimerReady; + // Dest.Type=pBoolType; + // return true; + //} + if (nSkill==105 || nSkill==107) { + Dest.DWord=LoH_HT_Ready(); + Dest.Type=pBoolType; + return true; + } + return false; + } + } + } + } + } + } + return false; + case RangedReady: + Dest.DWord=gbRangedAttackReady; + Dest.Type=pBoolType; + return true; + case AltTimerReady: + Dest.DWord=gbAltTimerReady; + Dest.Type=pBoolType; + return true; + case Book: + if (ISINDEX()) + { + if (ISNUMBER()) + { + // numeric + unsigned long nSpell=GETNUMBER()-1; + if (nSpellSpellBook[nSpell])) + { + Dest.Type=pSpellType; + return true; + } + } + else + { + // name + for (DWORD nSpell=0 ; nSpell < NUM_BOOK_SLOTS ; nSpell++) + if (GetCharInfo2()->SpellBook[nSpell] != 0xFFFFFFFF) + { + if (!stricmp(GetSpellNameByID(GetCharInfo2()->SpellBook[nSpell]),GETFIRST())) + { + Dest.DWord=nSpell+1; + Dest.Type=pIntType; + return true; + } + } + } + } + return false; + case SpellReady: + if (pCastSpellWnd && ISINDEX()) + { + if (ISNUMBER()) + { + // numeric + unsigned long nGem=GETNUMBER()-1; + if (nGemSpellSlots[nGem]) + Dest.DWord=0; + else + Dest.DWord = (((PEQCASTSPELLWINDOW)pCastSpellWnd)->SpellSlots[nGem]->spellstate!=1); + Dest.Type=pBoolType; + return true; + } + } + else + { + for (unsigned long nGem=0 ; nGem < NUM_SPELL_GEMS ; nGem++) + { + if (PSPELL pSpell=GetSpellByID(GetCharInfo2()->MemorizedSpells[nGem])) + { + if (!stricmp(GETFIRST(),pSpell->Name)) + { + if (!((PEQCASTSPELLWINDOW)pCastSpellWnd)->SpellSlots[nGem]) + Dest.DWord=0; + else + Dest.DWord = (((PEQCASTSPELLWINDOW)pCastSpellWnd)->SpellSlots[nGem]->spellstate!=1); + Dest.Type=pBoolType; + return true; + } + } + } + } + } + return false; + case PetBuff: + if (!ISINDEX() || !pPetInfoWnd) + return false; +#define pPetInfoWindow ((PEQPETINFOWINDOW)pPetInfoWnd) + if (ISNUMBER()) + { + unsigned long nBuff=GETNUMBER()-1; + if (nBuff>NUM_BUFF_SLOTS) + return false; + if (pPetInfoWindow->Buff[nBuff]==0xFFFFFFFF || pPetInfoWindow->Buff[nBuff]==0) + return false; + if (Dest.Ptr=GetSpellByID(pPetInfoWindow->Buff[nBuff])) + { + Dest.Type=pSpellType; + return true; + } + } + else + { + for (unsigned long nBuff=0 ; nBuff < NUM_BUFF_SLOTS ; nBuff++) + { + if (PSPELL pSpell=GetSpellByID(pPetInfoWindow->Buff[nBuff])) + { + if (!stricmp(GETFIRST(),pSpell->Name)) + { + Dest.DWord=nBuff+1; + Dest.Type=pIntType; + return true; + } + } + } + } +#undef pPetInfoWindow + return false; + case GroupLeaderExp: + Dest.Float=(FLOAT)pChar->GroupLeadershipExp; + Dest.Type=pFloatType; + return true; + case RaidLeaderExp: + Dest.Float=(FLOAT)pChar->RaidLeadershipExp; + Dest.Type=pFloatType; + return true; + case PctGroupLeaderExp: + Dest.Float=(float)pChar->GroupLeadershipExp/10.0f; + Dest.Type=pFloatType; + return true; + case PctRaidLeaderExp: + Dest.Float=(float)pChar->RaidLeadershipExp/10.0f; + Dest.Type=pFloatType; + return true; + case GroupLeaderPoints: + Dest.DWord=pChar->GroupLeadershipPoints; + Dest.Type=pIntType; + return true; + case RaidLeaderPoints: + Dest.DWord=pChar->RaidLeadershipPoints; + Dest.Type=pIntType; + return true; + case Stunned: + Dest.DWord=(pChar->Stunned==1); + Dest.Type=pBoolType; + return true; + case LargestFreeInventory: + { + Dest.DWord=0; + Dest.Type=pIntType; + for (DWORD slot=BAG_SLOT_START;slotpInventoryArray->InventoryArray[slot]) + { + if (GetItemFromContents(pItem)->Type==ITEMTYPE_PACK && GetItemFromContents(pItem)->SizeCapacity>Dest.DWord) + { + for (DWORD pslot=0;pslot<(GetItemFromContents(pItem)->Slots);pslot++) + { + if (!pItem->pContentsArray || !pItem->pContentsArray->Contents[pslot]) + { + Dest.DWord=GetItemFromContents(pItem)->SizeCapacity; + break;// break the loop for this pack + } + } + } + } + else + { + Dest.DWord=4; + return true; + } + } + } + return true; + case FreeInventory: + if (ISINDEX()) + { + DWORD nSize=GETNUMBER(); + if (nSize>4) + nSize=4; + Dest.DWord=0; + for (DWORD slot=BAG_SLOT_START;slotpInventoryArray->InventoryArray[slot]) + { + if (GetItemFromContents(pItem)->Type==ITEMTYPE_PACK && GetItemFromContents(pItem)->SizeCapacity>=nSize) + { + if (!pItem->pContentsArray) { + Dest.DWord+= GetItemFromContents(pItem)->Slots; + } else { + for (DWORD pslot=0;pslot<(GetItemFromContents(pItem)->Slots);pslot++) + { + if (!pItem->pContentsArray->Contents[pslot]) + Dest.DWord++; + } + } + } + } + else + { + Dest.DWord++; + } + } + Dest.Type=pIntType; + return true; + } + else + { + Dest.DWord=0; + for (DWORD slot=BAG_SLOT_START;slot 30) + break; + if (PCONTENTS pItem = GetCharInfo2()->pInventoryArray->InventoryArray[slot]) + { + if (GetItemFromContents(pItem)->Type==ITEMTYPE_PACK) + { + if (!pItem->pContentsArray) { + Dest.DWord+= GetItemFromContents(pItem)->Slots; + } else { + for (DWORD pslot=0;pslot<(GetItemFromContents(pItem)->Slots);pslot++) + { + if (!pItem->pContentsArray->Contents[pslot]) + Dest.DWord++; + } + } + } + } + else + { + Dest.DWord++; + } + } + Dest.Type=pIntType; + return true; + } + case Drunk: + Dest.DWord=GetCharInfo2()->Drunkenness; + Dest.Type=pIntType; + return true; + case TargetOfTarget: + if (gGameState==GAMESTATE_INGAME && GetCharInfo()->pSpawn) + if (Dest.Ptr=GetSpawnByID(pChar->pSpawn->TargetOfTarget)) + { + Dest.Type=pSpawnType; + return true; + } + return false; + case RaidAssistTarget: + if (gGameState==GAMESTATE_INGAME && GetCharInfo()->pSpawn) + if (ISINDEX() && ISNUMBER()) + { + DWORD N=GETNUMBER()-1; + if (N>=3) + return false; + if (Dest.Ptr=GetSpawnByID(pChar->pSpawn->RaidAssistNPC[N])) + { + Dest.Type=pSpawnType; + return true; + } + } + return false; + case GroupAssistTarget: + if (gGameState==GAMESTATE_INGAME && GetCharInfo()->pSpawn) + { + if (Dest.Ptr=GetSpawnByID(pChar->pSpawn->GroupAssistNPC[0])) + { + Dest.Type=pSpawnType; + return true; + } + } + return false; + case RaidMarkNPC: + if (gGameState==GAMESTATE_INGAME && GetCharInfo()->pSpawn) + if (ISINDEX() && ISNUMBER()) + { + DWORD N=GETNUMBER()-1; + if (N>=3) + return false; + if (Dest.Ptr=GetSpawnByID(pChar->pSpawn->RaidMarkNPC[N])) + { + Dest.Type=pSpawnType; + return true; + } + } + return false; + case GroupMarkNPC: + if (gGameState==GAMESTATE_INGAME && GetCharInfo()->pSpawn) + if (ISINDEX() && ISNUMBER()) + { + DWORD N=GETNUMBER()-1; + if (N>=3) + return false; + if (Dest.Ptr=GetSpawnByID(pChar->pSpawn->GroupMarkNPC[N])) + { + Dest.Type=pSpawnType; + return true; + } + } + return false; + case STR: + Dest.DWord=pChar->STR; + Dest.Type=pIntType; + return true; + case STA: + Dest.DWord=pChar->STA; + Dest.Type=pIntType; + return true; + case AGI: + Dest.DWord=pChar->AGI; + Dest.Type=pIntType; + return true; + case DEX: + Dest.DWord=pChar->DEX; + Dest.Type=pIntType; + return true; + case WIS: + Dest.DWord=pChar->WIS; + Dest.Type=pIntType; + return true; + case INT: + Dest.DWord=pChar->INT; + Dest.Type=pIntType; + return true; + case CHA: + Dest.DWord=pChar->CHA; + Dest.Type=pIntType; + return true; + case svMagic: + Dest.DWord=pChar->SaveMagic; + Dest.Type=pIntType; + return true; + case svFire: + Dest.DWord=pChar->SaveFire; + Dest.Type=pIntType; + return true; + case svCold: + Dest.DWord=pChar->SaveCold; + Dest.Type=pIntType; + return true; + case svPoison: + Dest.DWord=pChar->SavePoison; + Dest.Type=pIntType; + return true; + case svDisease: + Dest.DWord=pChar->SaveDisease; + Dest.Type=pIntType; + return true; + case CurrentWeight: + Dest.DWord=pChar->CurrWeight; + Dest.Type=pIntType; + return true; + case AAPointsSpent: + Dest.DWord=GetCharInfo2()->AAPointsSpent; + Dest.Type=pIntType; + return true; + case AAPointsTotal: + Dest.DWord=GetCharInfo2()->AAPointsSpent+GetCharInfo2()->AAPoints; + Dest.Type=pIntType; + return true; + case TributeActive: + Dest.DWord=*pTributeActive; + Dest.Type=pBoolType; + return true; + case Running: + Dest.DWord=(*EQADDR_RUNWALKSTATE); + Dest.Type=pBoolType; + return true; + case GroupSize: + Dest.DWord= 0; + { + if(!pChar->pGroupInfo) return false; + for(int i=1; i<6; i++) + if (pChar->pGroupInfo->pMember[i]) Dest.DWord++; + if (Dest.DWord) Dest.DWord++; + } + Dest.Type=pIntType; + return true; + case TributeTimer: + Dest.DWord=pChar->TributeTimer/60/100; + Dest.Type=pTicksType; + return true; + case RadiantCrystals: + Dest.DWord=pChar->RadiantCrystals; + Dest.Type=pIntType; + return true; + case EbonCrystals: + Dest.DWord=pChar->EbonCrystals; + Dest.Type=pIntType; + return true; + case Shrouded: + Dest.DWord=GetCharInfo2()->Shrouded; + Dest.Type=pBoolType; + return true; + case AutoFire: + Dest.DWord=gAutoFire; + Dest.Type=pBoolType; + return true; + case Language: + if(!ISINDEX()) + return false; + if(ISNUMBER()) + { + nLang=GETNUMBER()-1; + Dest.Ptr=pEverQuest->GetLangDesc(nLang); + Dest.Type=pStringType; + return true; + } + else + nLang=GetLanguageIDByName(GETFIRST())-1; + if(nLang<0 || nLang>=25) + return false; + Dest.DWord=nLang; + Dest.Type=pIntType; + return true; + case Aura: + if(PAURAMGR pAura=(PAURAMGR)pAuraMgr) + { + if(pAura->NumAuras) + { + DataTypeTemp[0] = 0; + PAURAS pAuras = (PAURAS)(*pAura->pAuraInfo); + if(ISINDEX()) + { + DWORD n = 0; + if(ISNUMBER()) + { + n = GETNUMBER(); + if(n > pAura->NumAuras) + return false; + n--; + strcpy(DataTypeTemp, pAuras->Aura[n].Name); + } + else + { + for(n = 0; n < pAura->NumAuras; n++) + { + if(!stricmp(GETFIRST(), pAuras->Aura[n].Name)) + { + strcpy(DataTypeTemp, pAuras->Aura[n].Name); + } + } + } + } + else + { + strcpy(DataTypeTemp, pAuras->Aura[0].Name); + } + if(DataTypeTemp[0]) + { + Dest.Ptr = DataTypeTemp; + Dest.Type = pStringType; + return true; + } + } + } + return false; + case LAMarkNPC: + Dest.DWord=GetCharInfo()->ActiveAbilities.MarkNPC; + Dest.Type=pIntType; + return true; + case LANPCHealth: + Dest.DWord=GetCharInfo()->ActiveAbilities.NPCHealth; + Dest.Type=pIntType; + return true; + case LADelegateMA: + Dest.DWord=GetCharInfo()->ActiveAbilities.DelegateMA; + Dest.Type=pIntType; + return true; + case LADelegateMarkNPC: + Dest.DWord=GetCharInfo()->ActiveAbilities.DelegateMarkNPC; + Dest.Type=pIntType; + return true; + case LAInspectBuffs: + Dest.DWord=GetCharInfo()->ActiveAbilities.InspectBuffs; + Dest.Type=pIntType; + return true; + case LASpellAwareness: + Dest.DWord=GetCharInfo()->ActiveAbilities.SpellAwareness; + Dest.Type=pIntType; + return true; + case LAOffenseEnhancement: + Dest.DWord=GetCharInfo()->ActiveAbilities.OffenseEnhancement; + Dest.Type=pIntType; + return true; + case LAManaEnhancement: + Dest.DWord=GetCharInfo()->ActiveAbilities.ManaEnhancement; + Dest.Type=pIntType; + return true; + case LAHealthEnhancement: + Dest.DWord=GetCharInfo()->ActiveAbilities.HealthEnhancement; + Dest.Type=pIntType; + return true; + case LAHealthRegen: + Dest.DWord=GetCharInfo()->ActiveAbilities.HealthRegen; + Dest.Type=pIntType; + return true; + case LAFindPathPC: + Dest.DWord=GetCharInfo()->ActiveAbilities.FindPathPC; + Dest.Type=pIntType; + return true; + case LAHoTT: + Dest.DWord=GetCharInfo()->ActiveAbilities.HoTT; + Dest.Type=pIntType; + return true; + case ActiveFavorCost: + if(*pTributeActive) + { + Dest.Int=pEQMisc->GetActiveFavorCost(); + Dest.Type=pIntType; + return true; + } + return false; + case CombatState: + switch(((PCPLAYERWND)pPlayerWnd)->CombatState) + { + case 0: + if(((CXWnd*)pPlayerWnd)->GetChildItem("PW_CombatStateAnim")) + { + Dest.Ptr="COMBAT"; + break; + } + Dest.Ptr="NULL"; + break; + case 1: + Dest.Ptr="DEBUFFED"; + break; + case 2: + Dest.Ptr="COOLDOWN"; + break; + case 3: + Dest.Ptr="ACTIVE"; + break; + case 4: + Dest.Ptr="RESTING"; + break; + default: + Dest.Ptr="UNKNOWN"; + break; + } + Dest.Type=pStringType; + return true; + case svCorruption: + Dest.DWord=pChar->SaveCorruption; + Dest.Type=pIntType; + return true; + case svPrismatic: + Dest.DWord=(pChar->SaveMagic + pChar->SaveFire + pChar->SaveCold + pChar->SavePoison + pChar->SaveDisease)/5; + Dest.Type=pIntType; + return true; + case svChromatic: + { + unsigned int lowSave; + lowSave = pChar->SaveMagic; + if(lowSave > pChar->SaveFire) + lowSave = pChar->SaveFire; + if(lowSave > pChar->SaveCold) + lowSave = pChar->SaveCold; + if(lowSave > pChar->SavePoison) + lowSave = pChar->SavePoison; + if(lowSave > pChar->SaveDisease) + lowSave = pChar->SaveDisease; + Dest.DWord=lowSave; + Dest.Type=pIntType; + return true; + } + case Doubloons: + Dest.DWord=pPlayerPointManager->GetAltCurrency(ALTCURRENCY_DOUBLOONS); + Dest.Type=pIntType; + return true; + case Orux: + Dest.DWord=pPlayerPointManager->GetAltCurrency(ALTCURRENCY_ORUX); + Dest.Type=pIntType; + return true; + case Phosphenes: + Dest.DWord=pPlayerPointManager->GetAltCurrency(ALTCURRENCY_PHOSPHENES); + Dest.Type=pIntType; + return true; + case Phosphites: + Dest.DWord=pPlayerPointManager->GetAltCurrency(ALTCURRENCY_PHOSPHITES); + Dest.Type=pIntType; + return true; + case Faycites: + Dest.DWord=pPlayerPointManager->GetAltCurrency(ALTCURRENCY_FAYCITES); + Dest.Type=pIntType; + return true; + case Chronobines: + Dest.DWord=pPlayerPointManager->GetAltCurrency(ALTCURRENCY_CHRONOBINES); + Dest.Type=pIntType; + return true; + case Fellowship: + Dest.Ptr=&pChar->pSpawn->Fellowship; + Dest.Type=pFellowshipType; + return true; + case Downtime: + if(pChar->DowntimeStamp) + Dest.DWord=((pChar->Downtime-(GetFastTime()-pChar->DowntimeStamp))/6)+1; + else + Dest.DWord=0; + Dest.Type=pTicksType; + return true; + case Counters: +#if 0 + Dest.DWord=0; + { + for (unsigned long k=0; kBuff[k].SpellID)) + if(pSpell->SpellType == 0 && GetCharInfo2()->Buff[k].DamageAbsorbRemaining) + Dest.DWord += GetCharInfo2()->Buff[k].DamageAbsorbRemaining; + } + Dest.Type=pIntType; + return true; +#endif + return false; + case Mercenary: + if(pMercInfo->HaveMerc) + { + if(pMercInfo->MercState == 1) + Dest.Ptr = "SUSPENDED"; + else if(pMercInfo->MercState == 5) + Dest.Ptr = "ACTIVE"; + else + Dest.Ptr = "UNKNOWN"; + } + else + Dest.Ptr = "NULL"; + Dest.Type = pStringType; + return true; + case XTarget: + if(PXTARGETMGR xtm = pChar->pXTargetMgr) + { + DWORD n = 0; + if(PXTARGETARRAY xta = xtm->pXTargetArray) + { + if(ISINDEX()) + { + if(ISNUMBER()) + { + if(GETNUMBER() > 0 && GETNUMBER() <= (int)xtm->TargetSlots) + { + Dest.DWord = GETNUMBER() - 1; + Dest.Type = pXTargetType; + return true; + } + } + else + { + for(n = 0; n < xtm->TargetSlots; n++) + { + if(xta->pXTargetData[n].xTargetType && xta->pXTargetData[n].Unknown0x4 && !stricmp(GETFIRST(), xta->pXTargetData[n].Name)) + { + Dest.DWord = n; + Dest.Type = pXTargetType; + return true; + } + } + } + } + else + { + DWORD x = 0; + for(n = 0; n < xtm->TargetSlots; n++) + { + if(xta->pXTargetData[n].xTargetType && xta->pXTargetData[n].Unknown0x4) + { + x++; + } + } + Dest.DWord = x; + Dest.Type = pIntType; + return true; + } + } + } + return false; + case Haste: + Dest.DWord = pCharData1->TotalEffect(0xb, 1, 0, 1, 1); + Dest.Type = pIntType; + return true; + case MercenaryStance: + Dest.Ptr = "NULL"; + if(pMercInfo->HaveMerc) + { + for(DWORD n = 0; n < pMercInfo->NumStances; n++) + { + if(pMercInfo->pMercStanceData[n]->nStance == pMercInfo->ActiveStance) + { + Dest.Ptr = pCDBStr->GetString(pMercInfo->pMercStanceData[n]->nDbStance, 24, 0); + break; + } + } + } + Dest.Type = pStringType; + return true; + case GemTimer: + if (!ISINDEX()) + return false; + if (ISNUMBER()) + { + // number + unsigned long nGem=GETNUMBER()-1; + if (nGemMemorizedSpells[nGem] != 0xFFFFFFFF) + { + Dest.DWord = (((GetSpellGemTimer(nGem) / 1000) + 5) / 6); + Dest.Type = pTicksType; + return true; + } + } + } + else + { + // name + for (unsigned long nGem=0 ; nGem < NUM_SPELL_GEMS ; nGem++) + { + if (PSPELL pSpell=GetSpellByID(GetCharInfo2()->MemorizedSpells[nGem])) + { + if (!stricmp(GETFIRST(),pSpell->Name)) + { + Dest.DWord = (((GetSpellGemTimer(nGem) / 1000) + 5) / 6); + Dest.Type = pTicksType; + return true; + } + } + } + } + return false; + case HaveExpansion: + if (!ISINDEX()) + return false; + if (ISNUMBER()) + { + DWORD nExpansion = GETNUMBER(); + if (nExpansion > NUM_EXPANSIONS) + return false; + Dest.DWord = GetCharInfo()->ExpansionFlags & EQ_EXPANSION(nExpansion); + Dest.Type = pBoolType; + return true; + } + else + { + for (DWORD n = 0; n < NUM_EXPANSIONS; n++) + { + if (!stricmp(GETFIRST(), szExpansions[n])) + { + Dest.DWord = GetCharInfo()->ExpansionFlags & EQ_EXPANSION(n + 1); + Dest.Type = pBoolType; + return true; + } + } + } + return false; + case PctAggro: + if(pAggroInfo) + { + Dest.DWord = pAggroInfo->aggroData[AD_Player].AggroPct; + Dest.Type = pIntType; + return true; + } + return false; + case SecondaryPctAggro: + if(pAggroInfo) + { + Dest.DWord = pAggroInfo->aggroData[AD_Secondary].AggroPct; + Dest.Type = pIntType; + return true; + } + return false; + case SecondaryAggroPlayer: + if(pAggroInfo && pAggroInfo->AggroSecondaryID) + { + Dest.Ptr = GetSpawnByID(pAggroInfo->AggroSecondaryID); + Dest.Type = pSpawnType; + return true; + } + return false; + case AggroLock: + if(pAggroInfo && pAggroInfo->AggroLockID) + { + Dest.Ptr = GetSpawnByID(pAggroInfo->AggroLockID); + Dest.Type = pSpawnType; + return true; + } + } + return false; +#undef pChar +} + +bool MQ2SpellType::GETMEMBER() +{ +#define pSpell ((PSPELL)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMEMBER pMember=MQ2SpellType::FindMember(Member); + if (!pMember) + return false; + + switch((SpellMembers)pMember->ID) + { + case ID: + Dest.DWord=pSpell->ID; + Dest.Type=pIntType; + return true; + case Name: + Dest.Ptr=&pSpell->Name[0]; + Dest.Type=pStringType; + return true; + case Level: + if (!ISINDEX() && GetCharInfo()->pSpawn) + { + Dest.DWord=pSpell->Level[GetCharInfo()->pSpawn->Class-1]; + Dest.Type=pIntType; + return true; + } + else + { + if (ISNUMBER()) + { + unsigned long nIndex=GETNUMBER()-1; + Dest.DWord=pSpell->Level[nIndex]; + Dest.Type=pIntType; + return true; + } + } + return false; + case Mana: + Dest.DWord=pSpell->Mana; + Dest.Type=pIntType; + return true; + case ResistAdj: + Dest.DWord=pSpell->ResistAdj; + Dest.Type=pIntType; + return true; + case Range: + Dest.Float=pSpell->Range; + Dest.Type=pFloatType; + return true; + case AERange: + Dest.Float=pSpell->AERange; + Dest.Type=pFloatType; + return true; + case PushBack: + Dest.Float=pSpell->PushBack; + Dest.Type=pFloatType; + return true; + case CastTime: + Dest.Float=(FLOAT)pSpell->CastTime/1000; + Dest.Type=pFloatType; + return true; + case RecoveryTime: + case FizzleTime: + Dest.Float=(FLOAT)pSpell->FizzleTime/1000; + Dest.Type=pFloatType; + return true; + case RecastTime: + Dest.Float=(FLOAT)pSpell->RecastTime/1000; + Dest.Type=pFloatType; + return true; + case ResistType: + switch(pSpell->Resist) + { + case 9: Dest.Ptr="Corruption"; break; + case 7: Dest.Ptr="Prismatic"; break; + case 6: Dest.Ptr="Chromatic"; break; + case 5: Dest.Ptr="Disease"; break; + case 4: Dest.Ptr="Poison"; break; + case 3: Dest.Ptr="Cold"; break; + case 2: Dest.Ptr="Fire"; break; + case 1: Dest.Ptr="Magic"; break; + case 0: Dest.Ptr="Unresistable"; break; + default: Dest.Ptr="Unknown"; break; + } + Dest.Type=pStringType; + return true; + case SpellType: + switch(pSpell->SpellType) + { + case 2: Dest.Ptr="Beneficial(Group)"; break; + case 1: Dest.Ptr="Beneficial"; break; + case 0: Dest.Ptr="Detrimental"; break; + default: Dest.Ptr="Unknown"; break; + } + Dest.Type=pStringType; + return true; + case TargetType: + switch(pSpell->TargetType) + { + case 41: Dest.Ptr="Group v2"; break; + case 40: Dest.Ptr="AE PC v2"; break; + case 25: Dest.Ptr="AE Summoned"; break; + case 24: Dest.Ptr="AE Undead"; break; + case 20: Dest.Ptr="Targeted AE Tap"; break; + case 18: Dest.Ptr="Uber Dragons"; break; + case 17: Dest.Ptr="Uber Giants"; break; + case 16: Dest.Ptr="Plant"; break; + case 15: Dest.Ptr="Corpse"; break; + case 14: Dest.Ptr="Pet"; break; + case 13: Dest.Ptr="LifeTap"; break; + case 11: Dest.Ptr="Summoned"; break; + case 10: Dest.Ptr="Undead"; break; + case 9: Dest.Ptr="Animal"; break; + case 8: Dest.Ptr="Targeted AE"; break; + case 6: Dest.Ptr="Self"; break; + case 5: Dest.Ptr="Single"; break; + case 4: Dest.Ptr="PB AE"; break; + case 3: Dest.Ptr="Group v1"; break; + case 2: Dest.Ptr="AE PC v1"; break; + case 1: Dest.Ptr="Line of Sight"; break; + default: Dest.Ptr="Unknown"; break; + } + Dest.Type=pStringType; + return true; + case Skill: + Dest.Ptr=szSkills[pSpell->Skill]; + Dest.Type=pStringType; + return true; + case MyCastTime: + { + DWORD n = 0; + float mct = (FLOAT)(pCharData1->GetAACastingTimeModifier((EQ_Spell*)pSpell)+pCharData1->GetFocusCastingTimeModifier((EQ_Spell*)pSpell,(EQ_Equipment**)&n,0)+pSpell->CastTime)/1000.0f; + if (mct < 0.50 * pSpell->CastTime/1000.0f) + Dest.Float=(FLOAT)0.50 * (pSpell->CastTime/1000.0f); + else + Dest.Float=(FLOAT) mct; + } + Dest.Type=pFloatType; + return true; + case Duration: + Dest.DWord=GetSpellDuration(pSpell,(PSPAWNINFO)pCharSpawn); + Dest.Type=pTicksType; + return true; + case CastOnYou: + Dest.Ptr=pSpell->CastOnYou; + Dest.Type=pStringType; + return true; + case CastOnAnother: + Dest.Ptr=pSpell->CastOnAnother; + Dest.Type=pStringType; + return true; + case WearOff: + Dest.Ptr=pSpell->WearOff; + Dest.Type=pStringType; + return true; + case CounterType: + { + Dest.Type=pStringType; + int i; + for (i=0; i<=11; i++){ + switch(pSpell->Attrib[i]) + { + case 35: + Dest.Ptr="Disease"; + return true; + case 36: + Dest.Ptr="Poison"; + return true; + case 116: + Dest.Ptr="Curse"; + return true; + case 369: + Dest.Ptr="Corruption"; + return true; + } + } + Dest.Ptr="None"; + return true; + } + case CounterNumber: + { + Dest.Type=pIntType; + int i; + for (i=0; i<=11; i++){ + if ((pSpell->Attrib[i] == 35) || (pSpell->Attrib[i] == 36) || (pSpell->Attrib[i] == 116) || (pSpell->Attrib[i] == 369)){ + Dest.DWord = (int)pSpell->Base[i]; + return true; + } + } + Dest.DWord = 0; + return true; + } + case Stacks: + { + unsigned long buffduration; + unsigned long duration=99999; + if (ISNUMBER()) + duration=GETNUMBER(); + unsigned long nBuff; + PCHARINFO2 pChar = GetCharInfo2(); + Dest.DWord = true; + Dest.Type = pBoolType; + for (nBuff=0; nBuffBuff[nBuff].SpellID>0) { + PSPELL tmpSpell = GetSpellByID(pChar->Buff[nBuff].SpellID); + buffduration = pChar->Buff[nBuff].Duration; + if (GetSpellDuration(tmpSpell,(PSPAWNINFO)pCharSpawn)>=0xFFFFFFFE) buffduration = 99999+1; + if (!BuffStackTest(pSpell, tmpSpell) || ((pSpell==tmpSpell) && (buffduration>duration))){ + Dest.DWord = false; + return true; + } + } + } + return true; + } + case StacksPet: + { + unsigned long petbuffduration; + unsigned long duration=99999; + if (ISNUMBER()) + duration=GETNUMBER(); + unsigned long nBuff; + Dest.DWord = true; + Dest.Type = pBoolType; + PEQPETINFOWINDOW pPet = ((PEQPETINFOWINDOW)pPetInfoWnd); + for (nBuff=0; nBuffBuff[nBuff]>0 && !(pPet->Buff[nBuff]==0xFFFFFFFF || pPet->Buff[nBuff]==0)) { + PSPELL tmpSpell = GetSpellByID(pPet->Buff[nBuff]); + petbuffduration = ((pPet->BuffFadeETA[nBuff]+5999)/1000)/6; + if (GetSpellDuration(tmpSpell,(PSPAWNINFO)pCharSpawn)>=0xFFFFFFFE) petbuffduration = 99999+1; + if (!BuffStackTest(pSpell, tmpSpell) || ((pSpell==tmpSpell) && (petbuffduration>duration))){ + Dest.DWord = false; + return true; + } + } + } + return true; + } + case WillStack: + { + if (!ISINDEX()) + return false; + PSPELL tmpSpell = NULL; + if (ISNUMBER()) + tmpSpell = GetSpellByID(GETNUMBER()); + else + tmpSpell = GetSpellByName(GETFIRST()); + if (!tmpSpell) + return false; + Dest.Type = pBoolType; + Dest.DWord = BuffStackTest(pSpell, tmpSpell); + return true; + } + case MyRange: + DWORD n = 0; + Dest.Float=pSpell->Range+(float)pCharData1->GetFocusRangeModifier((EQ_Spell*)pSpell,(EQ_Equipment**)&n); + Dest.Type=pFloatType; + return true; + } + return false; +#undef pSpell +} + +bool MQ2ItemType::GETMEMBER() +{ + DWORD N, cmp, tmp; +#define pItem ((PCONTENTS)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMEMBER pMember=MQ2ItemType::FindMember(Member); + if (!pMember) + return false; + + switch((ItemMembers)pMember->ID) + { + case ID: + Dest.DWord=GetItemFromContents(pItem)->ItemNumber; + Dest.Type=pIntType; + return true; + case Name: + Dest.Ptr=&GetItemFromContents(pItem)->Name[0]; + Dest.Type=pStringType; + return true; + case Lore: + Dest.DWord=GetItemFromContents(pItem)->Lore; + Dest.Type=pBoolType; + return true; + case NoDrop: + Dest.DWord=!((EQ_Item*)pItem)->CanDrop(0,1); + Dest.Type=pBoolType; + return true; + case NoRent: + Dest.DWord=!GetItemFromContents(pItem)->NoRent; + Dest.Type=pBoolType; + return true; + case Magic: + Dest.DWord=((GetItemFromContents(pItem)->Type == ITEMTYPE_NORMAL) && (GetItemFromContents(pItem)->Magic)); + Dest.Type=pBoolType; + return true; + case Value: + Dest.DWord=GetItemFromContents(pItem)->Cost; + Dest.Type=pIntType; + return true; + case Size: + Dest.DWord=GetItemFromContents(pItem)->Size; + Dest.Type=pIntType; + return true; + case SizeCapacity: + Dest.DWord=GetItemFromContents(pItem)->SizeCapacity; + Dest.Type=pIntType; + return true; + case Weight: + Dest.DWord=GetItemFromContents(pItem)->Weight; + Dest.Type=pIntType; + return true; + case Stack: + if ((GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) || (((EQ_Item*)pItem)->IsStackable()!=1)) + Dest.DWord=1; + else + Dest.DWord=pItem->StackCount; + Dest.Type=pIntType; + return true; + case Type: + if (GetItemFromContents(pItem)->Type == ITEMTYPE_NORMAL) + { + if ((GetItemFromContents(pItem)->ItemType < MAX_ITEMTYPES) && (szItemTypes[GetItemFromContents(pItem)->ItemType] != NULL)) + { + Dest.Ptr=szItemTypes[GetItemFromContents(pItem)->ItemType]; + } + else + { + Dest.Ptr=&DataTypeTemp[0]; + sprintf(DataTypeTemp,"*UnknownType%d",GetItemFromContents(pItem)->ItemType); + } + } + else if (GetItemFromContents(pItem)->Type == ITEMTYPE_PACK) + { + if ((GetItemFromContents(pItem)->Combine < MAX_COMBINES) && (szCombineTypes[GetItemFromContents(pItem)->Combine] != NULL)) + { + Dest.Ptr=szCombineTypes[GetItemFromContents(pItem)->Combine]; + } + else + { + Dest.Ptr=&DataTypeTemp[0]; + sprintf(DataTypeTemp,"*UnknownCombine%d",GetItemFromContents(pItem)->Combine); + } + } + else if (GetItemFromContents(pItem)->Type == ITEMTYPE_BOOK) + Dest.Ptr="Book"; + Dest.Type=pStringType; + return true; + case Charges: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=pItem->Charges; + Dest.Type=pIntType; + return true; + case LDoNTheme: + Dest.Ptr=GetLDoNTheme(GetItemFromContents(pItem)->LDTheme); + Dest.Type=pStringType; + return true; + case DMGBonusType: + Dest.Ptr=szDmgBonusType[GetItemFromContents(pItem)->DmgBonusType]; + Dest.Type=pStringType; + return true; + case Container: + if (GetItemFromContents(pItem)->Type == ITEMTYPE_PACK) + { + Dest.DWord=GetItemFromContents(pItem)->Slots; + } + else + Dest.DWord=0; + Dest.Type=pIntType; + return true; + case Items: + if (GetItemFromContents(pItem)->Type == ITEMTYPE_PACK) + { + Dest.DWord=0; + if (pItem->pContentsArray) { + for (unsigned long N=0 ; N < GetItemFromContents(pItem)->Slots ; N++) { + if (pItem->pContentsArray->Contents[N]) + Dest.DWord++; + } + } + Dest.Type=pIntType; + return true; + } + return false; + case Item: + if (GetItemFromContents(pItem)->Type == ITEMTYPE_PACK && ISNUMBER()) + { + unsigned long N=GETNUMBER(); + N--; + if (NSlots) + { + if (pItem->pContentsArray) + if (Dest.Ptr=pItem->pContentsArray->Contents[N]) + { + Dest.Type=pItemType; + return true; + } + } + } else if (GetItemFromContents(pItem)->Type == ITEMTYPE_NORMAL && ISNUMBER()) { + unsigned long N=GETNUMBER(); + N--; + Dest.Ptr=NULL; + if (pItem->pContentsArray) + switch (N) + { + case 0: + if (GetItemFromContents(pItem)->AugSlot1) Dest.Ptr=pItem->pContentsArray->Contents[N]; + break; + case 1: + if (GetItemFromContents(pItem)->AugSlot2) Dest.Ptr=pItem->pContentsArray->Contents[N]; + break; + case 2: + if (GetItemFromContents(pItem)->AugSlot3) Dest.Ptr=pItem->pContentsArray->Contents[N]; + break; + case 3: + if (GetItemFromContents(pItem)->AugSlot4) Dest.Ptr=pItem->pContentsArray->Contents[N]; + break; + case 4: + if (GetItemFromContents(pItem)->AugSlot5) Dest.Ptr=pItem->pContentsArray->Contents[N]; + break; + } + if (Dest.Ptr) return true; + } + return false; + case Stackable: + Dest.DWord=((EQ_Item*)pItem)->IsStackable(); + Dest.Type=pBoolType; + return true; + case InvSlot: + Dest.Int=FindInvSlotForContents(pItem); + if (Dest.Int>=0) + { + Dest.Type=pInvSlotType; + return true; + } + return false; + case BuyPrice: + if (pActiveMerchant && pItem->MerchantSlot) + { + Dest.DWord=pItem->Price; + Dest.Type=pIntType; + return true; + } + return false; + case SellPrice: + if (pActiveMerchant) + { + Dest.DWord=(DWORD)((FLOAT)GetItemFromContents(pItem)->Cost*(1.0f/((PEQMERCHWINDOW)pMerchantWnd)->Markup)); + Dest.Type=pIntType; + return true; + } + return false; + case WornSlot: + if (ISINDEX()) + { + if (ISNUMBER()) + { + DWORD Count=GETNUMBER(); + if (!Count) + return false; + cmp=GetItemFromContents(pItem)->EquipSlots; + for (N = 0 ; N < 32 ; N++) + { + if (cmp&(1<EquipSlots&(1<EquipSlots; + for (N = 0 ; N < 32 ; N++) + { + if (cmp&(1<Clicky.CastTime/1000; + Dest.Type=pFloatType; + return true; + case Spell: + if (Dest.Ptr=GetSpellByID(GetItemFromContents(pItem)->Clicky.SpellID)) + { + Dest.Type=pSpellType; + return true; + } + if (Dest.Ptr=GetSpellByID(GetItemFromContents(pItem)->Scroll.SpellID)) + { + Dest.Type=pSpellType; + return true; + } + if (Dest.Ptr=GetSpellByID(GetItemFromContents(pItem)->Proc.SpellID)) + { + Dest.Type=pSpellType; + return true; + } + if (Dest.Ptr=GetSpellByID(GetItemFromContents(pItem)->Focus.SpellID)) + { + Dest.Type=pSpellType; + return true; + } + if (Dest.Ptr=GetSpellByID(GetItemFromContents(pItem)->Worn.SpellID)) + { + Dest.Type=pSpellType; + return true; + } + return false; + case EffectType: + //0 Proc + //1 Clickable from inventory (any class) + //2 Worn effect (haste, cleave) + //3 Unknown + //4 Clickable must be worn + //5 Clickable from inventory (class restricted) + //6 Focus effect + //7 Memmable spell scroll + // This used to return an int type with a case statment, items could have + // only one effect. For backwards compatibility we return based on a hierarchy. + // A zero in any field indicates no effect (others will also be zero) + if (!GetItemFromContents(pItem)->Clicky.SpellID) + { + return false; + } + else if (GetItemFromContents(pItem)->Scroll.SpellID!=-1) + { + Dest.Ptr="Spell Scroll"; + } + else if (GetItemFromContents(pItem)->Clicky.SpellID!=-1) + { + // code to detect must-be-worn etc here + switch (GetItemFromContents(pItem)->Clicky.EffectType) + { + case 4: + Dest.Ptr="Click Worn"; + break; + case 1: + case 5: + Dest.Ptr="Click Inventory"; + break; + default: + Dest.Ptr="Click Unknown"; + } + } + else if (GetItemFromContents(pItem)->Focus.SpellID!=-1 || GetItemFromContents(pItem)->Worn.SpellID!=-1) + { + Dest.Ptr="Worn"; + } + else if (GetItemFromContents(pItem)->Proc.SpellID!=-1) + { + Dest.Ptr="Combat"; + } + else + { + return false; + } + Dest.Type=pStringType; + return true; + case InstrumentMod: + Dest.Float=((FLOAT)GetItemFromContents(pItem)->InstrumentMod)/10.0f; + Dest.Type=pFloatType; + return true; + case Tribute: + Dest.DWord=GetItemFromContents(pItem)->Favor; + Dest.Type=pIntType; + return true; + case Attuneable: + Dest.DWord=GetItemFromContents(pItem)->Attuneable; + Dest.Type=pBoolType; + return true; + case Timer: + if(GetItemFromContents(pItem)->Clicky.TimerID!=0xFFFFFFFF) + { + Dest.DWord=(GetItemTimer(pItem)+5)/6; + Dest.Type=pTicksType; + return true; + } + if (GetItemFromContents(pItem)->Clicky.SpellID!=-1) + { + Dest.DWord=0; // insta-clicky + Dest.Type=pTicksType; + return true; + } + return false; + case ItemDelay: + Dest.DWord=GetItemFromContents(pItem)->Delay; + Dest.Type=pIntType; + return true; + case TimerReady: + if(GetItemFromContents(pItem)->Clicky.TimerID!=0xFFFFFFFF) + { + Dest.DWord=GetItemTimer(pItem); + Dest.Type=pIntType; + return true; + } + if (GetItemFromContents(pItem)->Clicky.SpellID!=-1) + { + Dest.DWord=0; // insta-click or instant recast + Dest.Type=pIntType; + return true; + } + return false; + case StackSize: + if ((GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) || (((EQ_Item*)pItem)->IsStackable()!=1)) + Dest.DWord=1; + else + Dest.DWord=GetItemFromContents(pItem)->StackSize; + Dest.Type=pIntType; + return true; + case Stacks: + { + Dest.DWord=0; + Dest.Type=pIntType; + if (!((EQ_Item*)pItem)->IsStackable()) return true; + for (DWORD slot=BAG_SLOT_START;slotpInventoryArray->InventoryArray[slot]) + { + if (GetItemFromContents(pTempItem)->Type==ITEMTYPE_PACK && pTempItem->pContentsArray) + { + for (DWORD pslot=0;pslot<(GetItemFromContents(pTempItem)->Slots);pslot++) + { + if (pTempItem->pContentsArray->Contents[pslot]) + { + if (PCONTENTS pSlotItem = pTempItem->pContentsArray->Contents[pslot]) + { + if (GetItemFromContents(pSlotItem)->ItemNumber==GetItemFromContents(pItem)->ItemNumber) + { + Dest.DWord++; + } + } + } + } + } + else { + if (GetItemFromContents(pTempItem)->ItemNumber==GetItemFromContents(pItem)->ItemNumber) + { + Dest.DWord++; + } + } + } + } + return true; + } + case StackCount: + { + Dest.DWord=0; + Dest.Type=pIntType; + if (!((EQ_Item*)pItem)->IsStackable()) return true; + for (DWORD slot=BAG_SLOT_START;slotpInventoryArray->InventoryArray[slot]) + { + if (GetItemFromContents(pTempItem)->Type==ITEMTYPE_PACK && pTempItem->pContentsArray) + { + for (DWORD pslot=0;pslot<(GetItemFromContents(pTempItem)->Slots);pslot++) + { + if (pTempItem->pContentsArray->Contents[pslot]) + { + if (PCONTENTS pSlotItem = pTempItem->pContentsArray->Contents[pslot]) + { + if (GetItemFromContents(pSlotItem)->ItemNumber==GetItemFromContents(pItem)->ItemNumber) + { + Dest.DWord+=pSlotItem->StackCount; + } + } + } + } + } + else { + if (GetItemFromContents(pTempItem)->ItemNumber==GetItemFromContents(pItem)->ItemNumber) + { + Dest.DWord+=pTempItem->StackCount; + } + } + } + } + return true; + } + case FreeStack: + { + Dest.DWord=0; + Dest.Type=pIntType; + if (!((EQ_Item*)pItem)->IsStackable()) return true; + for (DWORD slot=BAG_SLOT_START;slotpInventoryArray->InventoryArray[slot]) + { + if (GetItemFromContents(pTempItem)->Type==ITEMTYPE_PACK && pTempItem->pContentsArray) + { + for (DWORD pslot=0;pslot<(GetItemFromContents(pTempItem)->Slots);pslot++) + { + if (pTempItem->pContentsArray->Contents[pslot]) + { + if (PCONTENTS pSlotItem = pTempItem->pContentsArray->Contents[pslot]) + { + if (GetItemFromContents(pSlotItem)->ItemNumber==GetItemFromContents(pItem)->ItemNumber) + { + Dest.DWord+=(GetItemFromContents(pSlotItem)->StackSize-pSlotItem->StackCount); + } + } + } + } + } + else { + if (GetItemFromContents(pTempItem)->ItemNumber==GetItemFromContents(pItem)->ItemNumber) + { + Dest.DWord+=(GetItemFromContents(pTempItem)->StackSize-pTempItem->StackCount); + } + } + } + } + return true; + } + case MerchQuantity: + if (pActiveMerchant && pItem->MerchantSlot) { + Dest.DWord=pItem->MerchantQuantity; + Dest.Type=pIntType; + return true; + } + return false; + + case Classes: + Dest.DWord=0; + // count bits + cmp=GetItemFromContents(pItem)->Classes; + for (N = 0 ; N < 16 ; N++) + { + if (cmp&(1<Classes; + for (N = 0 ; N < 16 ; N++) + { + if (cmp&(1<Classes; + for (N = 0 ; N < 16 ; N++) { + if (cmp&(1<GetClassThreeLetterCode(N+1))) { + Dest.DWord=N+1; + Dest.Type=pClassType; + return true; + } + } + } + return false; + } + } + return false; + case Races: + Dest.DWord=0; + // count bits + cmp=GetItemFromContents(pItem)->Races; + for (N = 0 ; N < 17 ; N++) + { + if (cmp&(1<Races; + for (N = 0 ; N < 17 ; N++) + { + if (cmp&(1<Races; + for (N = 0 ; N < 17 ; N++) { + if (cmp&(1<GetRaceDesc(tmp))) { + Dest.DWord=tmp; + Dest.Type=pRaceType; + return true; + } + } + } + return false; + } + } + return false; + case Deities: + Dest.DWord=0; + // count bits + cmp=GetItemFromContents(pItem)->Diety; + for (N = 0 ; N < 15 ; N++) + { + if (cmp&(1<Diety; + for (N = 0 ; N < 15 ; N++) + { + if (cmp&(1<Diety; + for (N = 0 ; N < 16 ; N++) { + if (cmp&(1<GetDeityDesc(N+200))) { + Dest.DWord=N+200; + Dest.Type=pDeityType; + return true; + } + } + } + return false; + } + } + return false; + case RequiredLevel: + Dest.DWord=GetItemFromContents(pItem)->RequiredLevel; + Dest.Type=pIntType; + return true; + case Evolving: + Dest.Ptr=pItem; + Dest.Type=pEvolvingItemType; + return true; + case AC: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->AC; + Dest.Type=pIntType; + return true; + case HP: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HP; + Dest.Type=pIntType; + return true; + case STR: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->STR; + Dest.Type=pIntType; + return true; + case STA: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->STA; + Dest.Type=pIntType; + return true; + case AGI: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->AGI; + Dest.Type=pIntType; + return true; + case DEX: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->DEX; + Dest.Type=pIntType; + return true; + case CHA: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->CHA; + Dest.Type=pIntType; + return true; + case INT: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->INT; + Dest.Type=pIntType; + return true; + case WIS: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->WIS; + Dest.Type=pIntType; + return true; + case Mana: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->Mana; + Dest.Type=pIntType; + return true; + case ManaRegen: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->ManaRegen; + Dest.Type=pIntType; + return true; + case HPRegen: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HPRegen; + Dest.Type=pIntType; + return true; + case Attack: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->Attack; + Dest.Type=pIntType; + return true; + case svCold: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->SvCold; + Dest.Type=pIntType; + return true; + case svFire: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->SvFire; + Dest.Type=pIntType; + return true; + case svMagic: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->SvMagic; + Dest.Type=pIntType; + return true; + case svDisease: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->SvDisease; + Dest.Type=pIntType; + return true; + case svPoison: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->SvPoison; + Dest.Type=pIntType; + return true; + case svCorruption: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->SvCorruption; + Dest.Type=pIntType; + return true; + case Haste: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->Haste; + Dest.Type=pIntType; + return true; + case DamShield: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->DamShield; + Dest.Type=pIntType; + return true; + case AugType: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->AugType; + Dest.Type=pIntType; + return true; + case AugRestrictions: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->AugRestrictions; + Dest.Type=pIntType; + return true; + case AugSlot1: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->AugSlot1; + Dest.Type=pIntType; + return true; + case AugSlot2: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->AugSlot2; + Dest.Type=pIntType; + return true; + case AugSlot3: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->AugSlot3; + Dest.Type=pIntType; + return true; + case AugSlot4: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->AugSlot4; + Dest.Type=pIntType; + return true; + case AugSlot5: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->AugSlot5; + Dest.Type=pIntType; + return true; + case Power: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=pItem->Power; + Dest.Type=pIntType; + return true; + case MaxPower: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->MaxPower; + Dest.Type=pIntType; + return true; + case Purity: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->Purity; + Dest.Type=pIntType; + return true; + case Avoidance: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->Avoidance; + Dest.Type=pIntType; + return true; + case SpellShield: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->SpellShield; + Dest.Type=pIntType; + return true; + case StrikeThrough: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->StrikeThrough; + Dest.Type=pIntType; + return true; + case StunResist: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->StunResist; + Dest.Type=pIntType; + return true; + case Shielding: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->Shielding; + Dest.Type=pIntType; + return true; + case Accuracy: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->Accuracy; + Dest.Type=pIntType; + return true; + case CombatEffects: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->CombatEffects; + Dest.Type=pIntType; + return true; + case DoTShielding: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=(char)GetItemFromContents(pItem)->DoTShielding; + Dest.Type=pIntType; + return true; + case HeroicSTR: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HeroicSTR; + Dest.Type=pIntType; + return true; + case HeroicINT: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HeroicINT; + Dest.Type=pIntType; + return true; + case HeroicWIS: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HeroicWIS; + Dest.Type=pIntType; + return true; + case HeroicAGI: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HeroicAGI; + Dest.Type=pIntType; + return true; + case HeroicDEX: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HeroicDEX; + Dest.Type=pIntType; + return true; + case HeroicSTA: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HeroicSTA; + Dest.Type=pIntType; + return true; + case HeroicCHA: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HeroicCHA; + Dest.Type=pIntType; + return true; + case HeroicSvMagic: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HeroicSvMagic; + Dest.Type=pIntType; + return true; + case HeroicSvFire: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HeroicSvFire; + Dest.Type=pIntType; + return true; + case HeroicSvCold: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HeroicSvCold; + Dest.Type=pIntType; + return true; + case HeroicSvDisease: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HeroicSvDisease; + Dest.Type=pIntType; + return true; + case HeroicSvPoison: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HeroicSvPoison; + Dest.Type=pIntType; + return true; + case HeroicSvCorruption: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HeroicSvCorruption; + Dest.Type=pIntType; + return true; + case EnduranceRegen: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->EnduranceRegen; + Dest.Type=pIntType; + return true; + case HealAmount: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->HealAmount; + Dest.Type=pIntType; + return true; + case Clairvoyance: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->Clairvoyance; + Dest.Type=pIntType; + return true; + case DamageShieldMitigation: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->DamageShieldMitigation; + Dest.Type=pIntType; + return true; + case SpellDamage: + if (GetItemFromContents(pItem)->Type != ITEMTYPE_NORMAL) + Dest.DWord=0; + else + Dest.DWord=GetItemFromContents(pItem)->SpellDamage; + Dest.Type=pIntType; + return true; + case Augs: + Dest.DWord = 0; + Dest.Type=pIntType; + if (GetItemFromContents(pItem)->Type == ITEMTYPE_NORMAL) { + if (GetItemFromContents(pItem)->AugSlot5) Dest.DWord++; + if (GetItemFromContents(pItem)->AugSlot4) Dest.DWord++; + if (GetItemFromContents(pItem)->AugSlot3) Dest.DWord++; + if (GetItemFromContents(pItem)->AugSlot2) Dest.DWord++; + if (GetItemFromContents(pItem)->AugSlot1) Dest.DWord++; + Dest.Type=pIntType; + } + return true; + case Tradeskills: + Dest.DWord=GetItemFromContents(pItem)->TradeSkills; + Dest.Type=pBoolType; + return true; + + } + return false; +#undef pItem +} + +bool MQ2WindowType::GETMEMBER() +{ +#define pWnd ((PCSIDLWND)VarPtr.Ptr) + PMQ2TYPEMEMBER pMember=MQ2WindowType::FindMember(Member); + if (!pMember) + return false; + + switch((WindowMembers)pMember->ID) + { + case Open: + Dest.DWord=pWnd->dShow; + Dest.Type=pBoolType; + return true; + case Child: + if (Dest.Ptr=((CSidlScreenWnd*)VarPtr.Ptr)->GetChildItem(GETFIRST())) + { + Dest.Type=pWindowType; + return true; + } + Dest.DWord=0; + Dest.Type=pIntType; + return true; + case Parent: + if (Dest.Ptr=pWnd->pParentWindow) + { + Dest.Type=pWindowType; + return true; + } + Dest.DWord=0; + Dest.Type=pIntType; + return true; + case FirstChild: + if (Dest.Ptr=pWnd->pFirstChildWnd) + { + Dest.Type=pWindowType; + return true; + } + Dest.DWord=0; + Dest.Type=pIntType; + return true; + case Next: + if (Dest.Ptr=pWnd->pNextSiblingWnd) + { + Dest.Type=pWindowType; + return true; + } + Dest.DWord=0; + Dest.Type=pIntType; + return true; + case VScrollMax: + Dest.DWord=pWnd->VScrollMax; + Dest.Type=pIntType; + return true; + case VScrollPos: + Dest.DWord=pWnd->VScrollPos; + Dest.Type=pIntType; + return true; + case VScrollPct: + Dest.DWord=(pWnd->VScrollPos*100)/pWnd->VScrollMax; + Dest.Type=pIntType; + return true; + case HScrollMax: + Dest.DWord=pWnd->HScrollMax; + Dest.Type=pIntType; + return true; + case HScrollPos: + Dest.DWord=pWnd->HScrollPos; + Dest.Type=pIntType; + return true; + case HScrollPct: + Dest.DWord=(pWnd->HScrollPos*100)/pWnd->HScrollMax; + Dest.Type=pIntType; + return true; + case Children: + Dest.DWord=(DWORD)pWnd->pFirstChildWnd; + Dest.Type=pBoolType; + return true; + case Siblings: + Dest.DWord=(DWORD)pWnd->pNextSiblingWnd; + Dest.Type=pBoolType; + return true; + case Minimized: + Dest.DWord=pWnd->Minimized; + Dest.Type=pBoolType; + return true; + case MouseOver: + Dest.DWord=pWnd->MouseOver; + Dest.Type=pBoolType; + return true; + case X: + Dest.DWord=pWnd->Location.left; + Dest.Type=pIntType; + return true; + case Y: + Dest.DWord=pWnd->Location.top; + Dest.Type=pIntType; + return true; + case Width: + Dest.DWord=pWnd->Location.right-pWnd->Location.left; + Dest.Type=pIntType; + return true; + case Height: + Dest.DWord=pWnd->Location.bottom-pWnd->Location.top; + Dest.Type=pIntType; + return true; + case BGColor: + Dest.DWord=pWnd->BGColor.ARGB; + Dest.Type=pArgbType; + return true; + case Text: + if(((CXWnd*)pWnd)->GetType()==UI_STMLBox) + GetCXStr(pWnd->SidlText,DataTypeTemp,MAX_STRING-1); + else + GetCXStr(pWnd->WindowText,DataTypeTemp,MAX_STRING-1); + DataTypeTemp[MAX_STRING-1]='\0'; + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + case Tooltip: + GetCXStr(pWnd->Tooltip,DataTypeTemp,MAX_STRING); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + case Checked: + Dest.Int=pWnd->Checked; + Dest.Type=pBoolType; + return true; + case Highlighted: + Dest.Int=pWnd->Highlighted; + Dest.Type=pBoolType; + return true; + case Enabled: + Dest.Int=(pWnd->Enabled!=0); + Dest.Type=pBoolType; + return true; + case Style: + Dest.DWord=pWnd->WindowStyle; + Dest.Type=pIntType; + return true; + case List: + { + int n = 0; + if (((CXWnd*)pWnd)->GetType()==UI_Combobox) + VarPtr.Ptr=pWnd->SidlText; + else if (((CXWnd*)pWnd)->GetType()!=UI_Listbox) + return false; +#ifndef ISXEQ + if (PCHAR pComma=strchr(Index,',')) { + n = atoi(pComma+1) - 1; + if (n < 0) n=0; + DebugSpew("List: index is %d\n", n); + *pComma = '\0'; + } +#else + if (argc==2) + n=atoi(argv[1]); + if (n<0) + n=0; +#endif + if (ISNUMBER()) + { + unsigned long nIndex=GETNUMBER(); + if (!nIndex) + return false; + nIndex--; + CXStr Str; + ((CListWnd*)pWnd)->GetItemText(&Str, nIndex, n); + GetCXStr(Str.Ptr,DataTypeTemp,MAX_STRING); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + else + { + // name + BOOL bEqual=false; + CHAR Name[MAX_STRING]={0}; + if (GETFIRST()[0]=='=') + { + bEqual=true; + strcpy(Name,&GETFIRST()[1]); + } + else + strcpy(Name,GETFIRST()); + strlwr(Name); + unsigned long nIndex=0; + while(1) + { + CXStr Str; + ((CListWnd*)pWnd)->GetItemText(&Str, nIndex,n); + GetCXStr(Str.Ptr,DataTypeTemp,MAX_STRING); + if (DataTypeTemp[0]==0) + return false; + + if (bEqual) + { + if (!stricmp(DataTypeTemp,Name)) + { + Dest.DWord=nIndex+1; + Dest.Type=pIntType; + return true; + } + } + else + { + strlwr(DataTypeTemp); + if (strstr(DataTypeTemp,Name)) + { + Dest.DWord=nIndex+1; + Dest.Type=pIntType; + return true; + } + } + nIndex++; + } + } + return false; + } + case Name: + { + if (CXMLData *pXMLData=((CXWnd*)pWnd)->GetXMLData()) + { + if (GetCXStr(pXMLData->Name.Ptr,DataTypeTemp,MAX_STRING)) + { + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + } + } + return false; + case ScreenID: + { + if (CXMLData *pXMLData=((CXWnd*)pWnd)->GetXMLData()) + { + if (GetCXStr(pXMLData->ScreenID.Ptr,DataTypeTemp,MAX_STRING)) + { + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + } + } + return false; + case Type: + { + if (CXMLData *pXMLData=((CXWnd*)pWnd)->GetXMLData()) + { + if (GetCXStr(pXMLData->TypeName.Ptr,DataTypeTemp,MAX_STRING)) + { + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + } + } + return false; + case Items: + if (((CXWnd*)pWnd)->GetType()==UI_Listbox) + { + Dest.DWord=((CSidlScreenWnd*)pWnd)->Items; + Dest.Type=pIntType; + } + else if (((CXWnd*)pWnd)->GetType()==UI_Combobox) + { + Dest.DWord=((CSidlScreenWnd*)pWnd->SidlText)->Items; + Dest.Type=pIntType; + } + return true; + case HisTradeReady: + if(PTRADEWINDOW pTrade=(PTRADEWINDOW)pTradeWnd) { + Dest.Int=pTrade->HisTradeReady; + Dest.Type=pBoolType; + return true; + } + case MyTradeReady: + if(PTRADEWINDOW pTrade=(PTRADEWINDOW)pTradeWnd) { + Dest.Int=pTrade->MyTradeReady; + Dest.Type=pBoolType; + return true; + } + } + + return false; +#undef pWnd +} +bool MQ2CurrentZoneType::GETMEMBER() +{ +#define pZone ((PZONEINFO)pZoneInfo) + PMQ2TYPEMEMBER pMember=MQ2CurrentZoneType::FindMember(Member); + if (!pMember) + return false; + + //return pZoneType->GetMember(*(MQ2VARPTR*)&((PWORLDDATA)pWorldData)->ZoneArray[GetCharInfo()->zoneId],Member,Index,Dest); + switch((CurrentZoneMembers)pMember->ID) + { + case ID: + Dest.Int = GetCharInfo()->zoneId; + Dest.Type=pIntType; + return true; + case Name: + Dest.Ptr=&pZone->LongName[0]; + Dest.Type=pStringType; + return true; + case ShortName: + Dest.Ptr=&pZone->ShortName[0]; + Dest.Type=pStringType; + return true; + case Type: + Dest.DWord=pZone->ZoneType; + Dest.Type=pIntType; + return true; + case Gravity: + Dest.Float=pZone->ZoneGravity; + Dest.Type=pFloatType; + return true; + case SkyType: + Dest.DWord=pZone->SkyType; + Dest.Type=pIntType; + return true; +#if 0 + case SafeN: + case SafeY: + Dest.Float=pZone->SafeYLoc; + Dest.Type=pFloatType; + return true; + case SafeW: + case SafeX: + Dest.Float=pZone->SafeXLoc; + Dest.Type=pFloatType; + return true; + case SafeU: + case SafeZ: + Dest.Float=pZone->SafeZLoc; + Dest.Type=pFloatType; + return true; +#endif + case MinClip: + Dest.Float=pZone->MinClip; + Dest.Type=pFloatType; + return true; + case MaxClip: + Dest.Float=pZone->MaxClip; + Dest.Type=pFloatType; + return true; + } + return false; +#undef pZone +} + +bool MQ2ZoneType::GETMEMBER() +{ +#define pZone ((PZONELIST)VarPtr.Ptr) + PMQ2TYPEMEMBER pMember=MQ2ZoneType::FindMember(Member); + if (!pMember) + return false; + switch((ZoneMembers)pMember->ID) + { + case Name: + Dest.Ptr=&pZone->LongName[0]; + Dest.Type=pStringType; + return true; + case ShortName: + Dest.Ptr=&pZone->ShortName[0]; + Dest.Type=pStringType; + return true; + case ID: + Dest.Int=pZone->Id; + Dest.Type=pIntType; + return true; + } + return false; +#undef pZone +} + +bool MQ2BodyType::GETMEMBER() +{ + PMQ2TYPEMEMBER pMember=MQ2BodyType::FindMember(Member); + if (!pMember) + return false; + switch((BodyMembers)pMember->ID) + { + case ID: + Dest.Ptr=VarPtr.Ptr; + Dest.Type=pIntType; + return true; + case Name: + Dest.Ptr=GetBodyTypeDesc(VarPtr.DWord); + Dest.Type=pStringType; + return true; + } + return false; +} +bool MQ2DeityType::GETMEMBER() +{ + PMQ2TYPEMEMBER pMember=MQ2DeityType::FindMember(Member); + if (!pMember) + return false; + switch((DeityMembers)pMember->ID) + { + case ID: + Dest.Ptr=VarPtr.Ptr; + Dest.Type=pIntType; + return true; + case Name: + Dest.Ptr=pEverQuest->GetDeityDesc(VarPtr.DWord); + Dest.Type=pStringType; + return true; + case Team: + Dest.Ptr=szDeityTeam[GetDeityTeamByID(VarPtr.DWord)]; + Dest.Type=pStringType; + return true; + } + return false; +} +bool MQ2ClassType::GETMEMBER() +{ + PMQ2TYPEMEMBER pMember=MQ2ClassType::FindMember(Member); + if (!pMember) + return false; + switch((ClassMembers)pMember->ID) + { + case ID: + Dest.Ptr=VarPtr.Ptr; + Dest.Type=pIntType; + return true; + case Name: + Dest.Ptr=GetClassDesc(VarPtr.DWord); + Dest.Type=pStringType; + return true; + case ShortName: + Dest.Ptr=pEverQuest->GetClassThreeLetterCode(VarPtr.DWord); + Dest.Type=pStringType; + return true; + case CanCast: + if (VarPtr.DWord<=16) + { + Dest.DWord=ClassInfo[VarPtr.DWord].CanCast; + Dest.Type=pBoolType; + return true; + } + return false; + case PureCaster: + if (VarPtr.DWord<=16) + { + Dest.DWord=ClassInfo[VarPtr.DWord].PureCaster; + Dest.Type=pBoolType; + return true; + } + return false; + case PetClass: + if (VarPtr.DWord<=16) + { + Dest.DWord=ClassInfo[VarPtr.DWord].PetClass; + Dest.Type=pBoolType; + return true; + } + return false; + case DruidType: + if (VarPtr.DWord<=16) + { + Dest.DWord=ClassInfo[VarPtr.DWord].DruidType; + Dest.Type=pBoolType; + return true; + } + return false; + case ShamanType: + if (VarPtr.DWord<=16) + { + Dest.DWord=ClassInfo[VarPtr.DWord].ShamanType; + Dest.Type=pBoolType; + return true; + } + return false; + case NecromancerType: + if (VarPtr.DWord<=16) + { + Dest.DWord=ClassInfo[VarPtr.DWord].NecroType; + Dest.Type=pBoolType; + return true; + } + return false; + case ClericType: + if (VarPtr.DWord<=16) + { + Dest.DWord=ClassInfo[VarPtr.DWord].ClericType; + Dest.Type=pBoolType; + return true; + } + return false; + case HealerType: + Dest.DWord=(VarPtr.DWord==2 || VarPtr.DWord==6 || VarPtr.DWord==10); + Dest.Type=pBoolType; + return true; + } + return false; +} +bool MQ2RaceType::GETMEMBER() +{ + PMQ2TYPEMEMBER pMember=MQ2RaceType::FindMember(Member); + if (!pMember) + return false; + switch((RaceMembers)pMember->ID) + { + case ID: + Dest.Ptr=VarPtr.Ptr; + Dest.Type=pIntType; + return true; + case Name: + Dest.Ptr=pEverQuest->GetRaceDesc(VarPtr.DWord); + Dest.Type=pStringType; + return true; + } + return false; +} + + +bool MQ2SwitchType::GETMEMBER() +{ +#define pSwitch ((PDOOR)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMEMBER pMember=MQ2SwitchType::FindMember(Member); + if (!pMember) + return false; + switch((SwitchMembers)pMember->ID) + { + case ID: + Dest.DWord=pSwitch->ID; + Dest.Type=pIntType; + return true; + case W: + case X: + Dest.Float=pSwitch->X; + Dest.Type=pFloatType; + return true; + case N: + case Y: + Dest.Float=pSwitch->Y; + Dest.Type=pFloatType; + return true; + case U: + case Z: + Dest.Float=pSwitch->Z; + Dest.Type=pFloatType; + return true; + case DefaultW: + case DefaultX: + Dest.Float=pSwitch->DefaultX; + Dest.Type=pFloatType; + return true; + case DefaultN: + case DefaultY: + Dest.Float=pSwitch->DefaultY; + Dest.Type=pFloatType; + return true; + case DefaultU: + case DefaultZ: + Dest.Float=pSwitch->DefaultZ; + Dest.Type=pFloatType; + return true; + case Heading: + Dest.Float=pSwitch->Heading*0.703125f; + Dest.Type=pHeadingType; + return true; + case DefaultHeading: + Dest.Float=pSwitch->DefaultHeading*0.703125f; + Dest.Type=pHeadingType; + return true; + case Open: + Dest.DWord=((pSwitch->DefaultHeading != pSwitch->Heading) || + (pSwitch->DefaultZ != pSwitch->Z)); + Dest.Type=pBoolType; + return true; + case HeadingTo: + Dest.Float=(FLOAT)(atan2f(((PSPAWNINFO)pCharSpawn)->Y - pSwitch->Y, pSwitch->X - ((PSPAWNINFO)pCharSpawn)->X) * 180.0f / PI + 90.0f); + if (Dest.Float<0.0f) + Dest.Float += 360.0f; + else if (Dest.Float>=360.0f) + Dest.Float -= 360.0f; + Dest.Type=pHeadingType; + return true; + case Name: + Dest.Ptr=&pSwitch->Name[0]; + Dest.Type=pStringType; + return true; + case Distance: + Dest.Float=GetDistance(pSwitch->X,pSwitch->Y); + Dest.Type=pFloatType; + return true; + case xLineOfSight: + Dest.DWord=(CastRay(GetCharInfo()->pSpawn,pSwitch->Y,pSwitch->X,pSwitch->Z)); + Dest.Type=pBoolType; + return true; + } + return false; +#undef pSwitch +} + +bool MQ2GroundType::GETMEMBER() +{ +#define pGround ((PGROUNDITEM)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMEMBER pMember=MQ2GroundType::FindMember(Member); + if (!pMember) + return false; + switch((GroundMembers)pMember->ID) + { + case ID: + Dest.DWord=pGround->DropID; + Dest.Type=pIntType; + return true; + case W: + case X: + Dest.Float=pGround->X; + Dest.Type=pFloatType; + return true; + case N: + case Y: + Dest.Float=pGround->Y; + Dest.Type=pFloatType; + return true; + case U: + case Z: + Dest.Float=pGround->Z; + Dest.Type=pFloatType; + return true; + case Name: + Dest.Ptr=&pGround->Name[0]; + Dest.Type=pStringType; + return true; + case Heading: + Dest.Float=pGround->Heading*0.703125f; + Dest.Type=pHeadingType; + return true; + case Distance: + Dest.Float=GetDistance(pGround->X,pGround->Y); + Dest.Type=pFloatType; + return true; + case HeadingTo: + Dest.Float=(FLOAT)(atan2f(((PSPAWNINFO)pCharSpawn)->Y - pGround->Y, pGround->X - ((PSPAWNINFO)pCharSpawn)->X) * 180.0f / PI + 90.0f); + if (Dest.Float<0.0f) + Dest.Float += 360.0f; + else if (Dest.Float>=360.0f) + Dest.Float -= 360.0f; + Dest.Type=pHeadingType; + return true; + case xLineOfSight: + Dest.DWord=(CastRay(GetCharInfo()->pSpawn,pGround->Y,pGround->X,pGround->Z)); + Dest.Type=pBoolType; + return true; + } + return false; +#undef pGround +} +bool MQ2MacroQuestType::GETMEMBER() +{ + PMQ2TYPEMEMBER pMember=MQ2MacroQuestType::FindMember(Member); + if (!pMember) + return false; + switch((MacroQuestMembers)pMember->ID) + { + case GameState: + if (gGameState==GAMESTATE_CHARSELECT) + Dest.Ptr="CHARSELECT"; + else if (gGameState==GAMESTATE_INGAME) + Dest.Ptr="INGAME"; + else + Dest.Ptr="UNKNOWN"; + Dest.Type=pStringType; + return true; + case LoginName: + { + if (PCHAR pTemp=GetLoginName()) + { + strcpy(DataTypeTemp,pTemp); + free(pTemp); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + } + return false; + case Server: + if (EQADDR_SERVERNAME[0]) + { + Dest.Ptr=EQADDR_SERVERNAME; + Dest.Type=pStringType; + return true; + } + return false; + case LastCommand: + if (szLastCommand[0]) + { + Dest.Ptr=&szLastCommand[0]; + Dest.Type=pStringType; + return true; + } + return false; + case LastTell: + if (EQADDR_LASTTELL[0]) + { + Dest.Ptr=&EQADDR_LASTTELL[0]; + Dest.Type=pStringType; + return true; + } + return false; + case Error: + if (gszLastNormalError[0])// QUIT SETTING THIS MANUALLY, USE MacroError, FatalError, ETC + { + Dest.Ptr=&gszLastNormalError[0]; + Dest.Type=pStringType; + return true; + } + return false; + case SyntaxError: + if (gszLastSyntaxError[0]) + { + Dest.Ptr=&gszLastSyntaxError[0]; + Dest.Type=pStringType; + return true; + } + return false; + case MQ2DataError: + if (gszLastMQ2DataError[0]) + { + Dest.Ptr=&gszLastMQ2DataError[0]; + Dest.Type=pStringType; + return true; + } + return false; + case Running: + Dest.DWord=(DWORD)clock(); + Dest.Type=pIntType; + return true; + case MouseX: + Dest.DWord=((PMOUSEINFO)EQADDR_MOUSE)->X; + Dest.Type=pIntType; + return true; + case MouseY: + Dest.DWord=((PMOUSEINFO)EQADDR_MOUSE)->Y; + Dest.Type=pIntType; + return true; + case BuildDate: + SYSTEMTIME st; + HANDLE hFile; + WIN32_FIND_DATA FileData; + CHAR szBuffer[MAX_STRING]; + sprintf(szBuffer,"%s\\MQ2Main.dll", gszINIPath); + hFile = FindFirstFile(szBuffer, &FileData); + // Convert the creation time time to local time. + FileTimeToSystemTime(&FileData.ftLastWriteTime, &st); + FindClose(hFile); + sprintf(DataTypeTemp, "%d%d%d",st.wYear,st.wMonth,st.wDay); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + case Ping: + Dest.DWord=pConnection->Last; + Dest.Type=pIntType; + return true; + case ChatChannels: + if(((PEVERQUEST)pEverQuest)->ChatService) + { + Dest.DWord=((PEVERQUEST)pEverQuest)->ChatService->ActiveChannels; + Dest.Type=pIntType; + return true; + } + case ChatChannel: + if(((PEVERQUEST)pEverQuest)->ChatService) + { + PCHATSERVICE pChat=((PEVERQUEST)pEverQuest)->ChatService; + if(ISNUMBER()) + { + DWORD index=GETNUMBER(); + if(pChat->ActiveChannels && index && index<=pChat->ActiveChannels) + { + strcpy(DataTypeTemp,pChat->ChannelList->ChannelName[index-1]); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + } + else + { + CHAR Name[MAX_STRING]={0}; + strcpy(Name,GETFIRST()); + for(unsigned int i=0; iActiveChannels; i++) + { + if(!stricmp(Name,pChat->ChannelList->ChannelName[i])) + { + Dest.DWord=1; + Dest.Type=pBoolType; + return true; + } + } + } + } + case ViewportX: + Dest.DWord=ScreenX; + Dest.Type=pIntType; + return true; + case ViewportY: + Dest.DWord=ScreenY; + Dest.Type=pIntType; + return true; + case ViewportXMax: + Dest.DWord=ScreenXMax; + Dest.Type=pIntType; + return true; + case ViewportYMax: + Dest.DWord=ScreenYMax; + Dest.Type=pIntType; + return true; + case ViewportXCenter: + Dest.DWord=ScreenXMax/2; + Dest.Type=pIntType; + return true; + case ViewportYCenter: + Dest.DWord=ScreenYMax/2; + Dest.Type=pIntType; + return true; + case LClickedObject: + Dest.DWord=gLClickedObject; + Dest.Type=pBoolType; + return true; + } + return false; +} +#ifndef ISXEQ +bool MQ2TimeType::GETMEMBER() +{ +#define pTime ((struct tm *)VarPtr.Ptr) + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMEMBER pMember=MQ2TimeType::FindMember(Member); + if (!pMember) + return false; + switch((TimeMembers)pMember->ID) + { + case Hour: + Dest.DWord=pTime->tm_hour; + Dest.Type=pIntType; + return true; + case Minute: + Dest.DWord=pTime->tm_min; + Dest.Type=pIntType; + return true; + case Second: + Dest.DWord=pTime->tm_sec; + Dest.Type=pIntType; + return true; + case DayOfWeek: + Dest.DWord=pTime->tm_wday+1; + Dest.Type=pIntType; + return true; + case Day: + Dest.DWord=pTime->tm_mday; + Dest.Type=pIntType; + return true; + case Month: + Dest.DWord=pTime->tm_mon+1; + Dest.Type=pIntType; + return true; + case Year: + Dest.DWord=pTime->tm_year+1900; + Dest.Type=pIntType; + return true; + case Time12: + { + unsigned long Hour=pTime->tm_hour%12; + if (!Hour) + Hour=12; + sprintf(DataTypeTemp,"%02d:%02d:%02d",Hour,pTime->tm_min, pTime->tm_sec); + Dest.Ptr=&DataTypeTemp[0], + Dest.Type=pStringType; + } + return true; + case Time24: + sprintf(DataTypeTemp,"%02d:%02d:%02d",pTime->tm_hour,pTime->tm_min, pTime->tm_sec); + Dest.Ptr=&DataTypeTemp[0], + Dest.Type=pStringType; + return true; + case Date: + sprintf(DataTypeTemp,"%02d/%02d/%04d",pTime->tm_mon+1,pTime->tm_mday, pTime->tm_year+1900); + Dest.Ptr=&DataTypeTemp[0], + Dest.Type=pStringType; + return true; + case Night: + Dest.DWord=((pTime->tm_hour<7) || (pTime->tm_hour>18)); + Dest.Type=pBoolType; + return true; + case SecondsSinceMidnight: + Dest.DWord=pTime->tm_hour*3600+pTime->tm_min*60+pTime->tm_sec; + Dest.Type=pIntType; + return true; + } + return false; +#undef pTime +} +#endif + +bool MQ2HeadingType::GETMEMBER() +{ + PMQ2TYPEMEMBER pMember=MQ2HeadingType::FindMember(Member); + if (!pMember) + return false; + FLOAT Heading=360.0f-VarPtr.Float; + switch((HeadingMembers)pMember->ID) + { + case Clock: + { + Dest.Int=((int)Heading)+15; + Dest.DWord=((int)Dest.Int/30)%12; + if (Dest.DWord==0) + Dest.DWord=12; + Dest.Type=pIntType; + return true; + } + case Degrees: + Dest.Float=Heading; + Dest.Type=pFloatType; + return true; + case DegreesCCW: + Dest.Float=VarPtr.Float; + Dest.Type=pFloatType; + return true; + case ShortName: + Dest.Ptr=szHeadingNormalShort[(INT)(Heading/ 22.5f + 0.5f)%16]; + Dest.Type=pStringType; + return true; + case Name: + Dest.Ptr=szHeadingNormal[(INT)(Heading/ 22.5f + 0.5f)%16]; + Dest.Type=pStringType; + return true; + } + return false; +} + +bool MQ2CorpseType::GETMEMBER() +{ + if (!pActiveCorpse || !pLootWnd) + return false; +#define pLoot ((PEQLOOTWINDOW)pLootWnd) + PMQ2TYPEMEMBER pMember=MQ2CorpseType::FindMember(Member); + if (!pMember) + { +#ifndef ISXEQ + return pSpawnType->GetMember(*(MQ2VARPTR*)&pActiveCorpse,Member,Index,Dest); +#else + return pSpawnType->GetMember(*(LSVARPTR*)&pActiveCorpse,Member,argc,argv,Dest); +#endif + } + + switch((CorpseMembers)pMember->ID) + { + case Open: + Dest.DWord=1; // obviously, since we're this far + Dest.Type=pBoolType; + return true; + case Item: + if (ISINDEX()) + { + if (ISNUMBER()) + { + unsigned long nIndex=GETNUMBER()-1; + if (nIndex<34 && pLoot->pInventoryArray) + { + if (Dest.Ptr=pLoot->pInventoryArray->InventoryArray[nIndex]) + { + Dest.Type=pItemType; + return true; + } + } + } + else + { + // name + BOOL bExact=FALSE; + PCHAR pName=GETFIRST(); + if (*pName=='=') + { + bExact=TRUE; + pName++; + } + strlwr(pName); + CHAR Temp[MAX_STRING]={0}; + if (pLoot->pInventoryArray) + for (unsigned long nIndex = 0 ; nIndex < 34 ; nIndex++) + { + if (PCONTENTS pContents=pLoot->pInventoryArray->InventoryArray[nIndex]) + { + if (bExact) + { + if (!stricmp(pName,GetItemFromContents(pContents)->Name)) + { + Dest.Ptr=pContents; + Dest.Type=pItemType; + return true; + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pContents)->Name)),pName)) + { + Dest.Ptr=pContents; + Dest.Type=pItemType; + return true; + } + } + } + } + + } + } + return false; + case Items: + { + Dest.DWord=0; + if (pLoot->pInventoryArray) + for (unsigned long N = 0 ; N < 31 ; N++) + { + if (pLoot->pInventoryArray->InventoryArray[N]) + Dest.DWord++; + } + Dest.Type=pIntType; + return true; + } + } + return false; +#undef pLoot +} + +bool MQ2MerchantType::GETMEMBER() +{ + if (!pActiveMerchant || !pMerchantWnd) + return false; +#define pMerch ((PEQMERCHWINDOW)pMerchantWnd) + PMQ2TYPEMEMBER pMember=MQ2MerchantType::FindMember(Member); + if (!pMember) + { +#ifndef ISXEQ + return pSpawnType->GetMember(*(MQ2VARPTR*)&pActiveMerchant,Member,Index,Dest); +#else + return pSpawnType->GetMember(*(LSVARPTR*)&pActiveMerchant,Member,argc,argv,Dest); +#endif + } + + switch((MerchantMembers)pMember->ID) + { + case Open: + Dest.DWord=1; // obviously, since we're this far ;) + Dest.Type=pBoolType; + return true; + case Item: + if (ISINDEX()) + { + if (ISNUMBER()) + { + unsigned long nIndex=GETNUMBER()-1; + if(!pMerch->pMerchOther->pMerchData->pMerchArray) + return false; + if (nIndex < pMerch->pMerchOther->pMerchData->MerchSlots) + { + if (Dest.Ptr=pMerch->pMerchOther->pMerchData->pMerchArray->Array[nIndex]) + { + Dest.Type=pItemType; + return true; + } + } + } + else + { + // name + BOOL bExact=FALSE; + PCHAR pName=GETFIRST(); + if (*pName=='=') + { + bExact=TRUE; + pName++; + } + strlwr(pName); + CHAR Temp[MAX_STRING]={0}; + if(!pMerch->pMerchOther->pMerchData->pMerchArray) + return false; + for (unsigned long nIndex = 0 ; nIndex < pMerch->pMerchOther->pMerchData->MerchSlots ; nIndex++) + { + if (PCONTENTS pContents=pMerch->pMerchOther->pMerchData->pMerchArray->Array[nIndex]) + { + if (bExact) + { + if (!stricmp(pName,GetItemFromContents(pContents)->Name)) + { + Dest.Ptr=pContents; + Dest.Type=pItemType; + return true; + } + } + else + { + if(strstr(strlwr(strcpy(Temp,GetItemFromContents(pContents)->Name)),pName)) + { + Dest.Ptr=pContents; + Dest.Type=pItemType; + return true; + } + } + } + } + } + } + return false; + case Items: + { + Dest.DWord=0; + if(!pMerch->pMerchOther->pMerchData->pMerchArray) + return false; + for (unsigned long nIndex = 0 ; nIndex < pMerch->pMerchOther->pMerchData->MerchSlots ; nIndex++) + if (pMerch->pMerchOther->pMerchData->pMerchArray->Array[nIndex]) + Dest.DWord++; + + Dest.Type=pIntType; + return true; + } + case Markup: + Dest.Float=pMerch->Markup; + Dest.Type=pFloatType; + return true; + case Full: + { + if(!pMerch->pMerchOther->pMerchData->pMerchArray) + return false; + Dest.DWord=1; + if (pMerch->pMerchOther->pMerchData->MerchSlots < 0x80) { + Dest.DWord=0; + Dest.Type=pBoolType; + return true; + } + for (unsigned long N = 0 ; N < pMerch->pMerchOther->pMerchData->MerchSlots ; N++) + { + if (!pMerch->pMerchOther->pMerchData->pMerchArray->Array[N]) + { + Dest.DWord=0; + break; + } + } + Dest.Type=pBoolType; + return true; + } + } + return false; +#undef pMerch +} + +bool MQ2InvSlotType::GETMEMBER() +{ +#define nInvSlot (VarPtr.Int) + PMQ2TYPEMEMBER pMember=MQ2InvSlotType::FindMember(Member); + if (!pMember) + return false; + switch((InvSlotMembers)pMember->ID) + { + case ID: + Dest.DWord=VarPtr.Int; + Dest.Type=pIntType; + return true; + case Item: +#if 0 + if (CInvSlot *pSlot=pInvSlotMgr->FindInvSlot(nInvSlot)) + { + if (((PEQINVSLOT)pSlot)->ppContents) + { + if (Dest.Ptr=*((PEQINVSLOT)pSlot)->ppContents) + { + Dest.Type=pItemType; + return true; + } + } + } +#endif + if(Dest.Ptr = GetCharInfo2()->pInventoryArray->InventoryArray[nInvSlot]) + { + Dest.Type = pItemType; + return true; + } + else + { + PCHARINFO pCharInfo=(PCHARINFO)pCharData; + if (nInvSlot>=262 && nInvSlot<342) + { + unsigned long nPack=(nInvSlot-262)/10; + unsigned long nSlot=(nInvSlot-262)%10; + if (PCONTENTS pPack=GetCharInfo2()->pInventoryArray->Inventory.Pack[nPack]) + if (GetItemFromContents(pPack)->Type==ITEMTYPE_PACK && nSlotSlots) + { + if (pPack->pContentsArray) + if (Dest.Ptr=pPack->pContentsArray->Contents[nSlot]) + { + Dest.Type=pItemType; + return true; + } + } + } + else if (nInvSlot>=2032 && nInvSlot<2272) + { + unsigned long nPack=(nInvSlot-2032)/10; + unsigned long nSlot=(nInvSlot-2)%10; + if (PCONTENTS pPack=pCharInfo->pBankArray->Bank[nPack]) + if (GetItemFromContents(pPack)->Type==ITEMTYPE_PACK && nSlotSlots) + { + if (pPack->pContentsArray) + if (Dest.Ptr=pPack->pContentsArray->Contents[nSlot]) + { + Dest.Type=pItemType; + return true; + } + } + } + else if (nInvSlot>=2532 && nInvSlot<2552) + { + unsigned long nPack=24+((nInvSlot-2532)/10); + unsigned long nSlot=(nInvSlot-2)%10; + if (PCONTENTS pPack=pCharInfo->pBankArray->Bank[nPack]) + if (GetItemFromContents(pPack)->Type==ITEMTYPE_PACK && nSlotSlots) + { + if (pPack->pContentsArray) + if (Dest.Ptr=pPack->pContentsArray->Contents[nSlot]) + { + Dest.Type=pItemType; + return true; + } + } + } + else if (nInvSlot>=2000 && nInvSlot<2024) + { + if (Dest.Ptr=pCharInfo->pBankArray->Bank[nInvSlot-2000]) + { + Dest.Type=pItemType; + return true; + } + } + else if (nInvSlot==2500 || nInvSlot==2501) + { + if (Dest.Ptr=pCharInfo->pBankArray->Bank[nInvSlot-2500+24]) + { + Dest.Type=pItemType; + return true; + } + } + } + return false; + case Pack: + if (nInvSlot>=262 && nInvSlot<342) + { + Dest.DWord=((nInvSlot-262)/10)+BAG_SLOT_START; + Dest.Type=pInvSlotType; + return true; + } + else if (nInvSlot>=2032 && nInvSlot<2272) + { + Dest.DWord=((nInvSlot-2032)/10)+2000; + Dest.Type=pInvSlotType; + return true; + } + else if (nInvSlot>=2532 && nInvSlot<2552) + { + Dest.DWord=((nInvSlot-2532)/10)+2500; + Dest.Type=pInvSlotType; + return true; + } + return false; + case Slot: + { + if (nInvSlot>=262 && nInvSlot<342) + { + Dest.DWord=(nInvSlot-262)%10; + Dest.Type=pIntType; + return true; + } + else if (nInvSlot>=2032 && nInvSlot<2272) + { + Dest.DWord=(nInvSlot-2032)%10; + Dest.Type=pIntType; + return true; + } + else if (nInvSlot>=2532 && nInvSlot<2552) + { + Dest.DWord=(nInvSlot-2532)%10; + Dest.Type=pIntType; + return true; + } + } + return false; + case Name: + if (nInvSlot>=0 && nInvSlot=BAG_SLOT_START && nInvSlot=2000 && nInvSlot<2024) + { + sprintf(DataTypeTemp,"bank%d",nInvSlot-1999); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + else if (nInvSlot>=2500 && nInvSlot<2502) + { + sprintf(DataTypeTemp,"sharedbank%d",nInvSlot-2499); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + else if (nInvSlot>=5000 && nInvSlot<5032) + { + sprintf(DataTypeTemp,"loot%d",nInvSlot-4999); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + else if (nInvSlot>=3000 && nInvSlot<3009) + { + sprintf(DataTypeTemp,"trade%d",nInvSlot-2999); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + else if (nInvSlot>=4000 && nInvSlot<4009) + { + sprintf(DataTypeTemp,"enviro%d",nInvSlot-3999); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + else if (nInvSlot>=6000 && nInvSlot<6080) + { + sprintf(DataTypeTemp,"merchant%d",nInvSlot-5999); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + else if (nInvSlot>=7000 && nInvSlot<7089) + { + sprintf(DataTypeTemp,"bazaar%d",nInvSlot-6999); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + else if (nInvSlot>=8000 && nInvSlot<8031) + { + sprintf(DataTypeTemp,"inspect%d",nInvSlot-7999); + Dest.Ptr=&DataTypeTemp[0]; + Dest.Type=pStringType; + return true; + } + return false; + } + + return false; +#undef nInvSlot +} + + + +bool MQ2TimerType::GETMEMBER() +{ +#define pTimer ((PMQTIMER)VarPtr.Ptr) + if (!pTimer) + return false; + PMQ2TYPEMEMBER pMember=MQ2TimerType::FindMember(Member); + if (!pMember) + return false; + switch((TimerMembers)pMember->ID) + { + case Value: + Dest.DWord=pTimer->Current; + Dest.Type=pIntType; + return true; + case OriginalValue: + Dest.DWord=pTimer->Original; + Dest.Type=pIntType; + return true; + } + return false; +#undef pTimer +} + + +bool MQ2SkillType::GETMEMBER() +{ + if (!VarPtr.Ptr) + return false; + PSKILL pSkill=*(PSKILL*)VarPtr.Ptr; + if (!pSkill) + return false; + PMQ2TYPEMEMBER pMember=MQ2SkillType::FindMember(Member); + if (!pMember) + return false; + unsigned long nIndex=GetCharInfo2()->Class; + if(ISINDEX()) + { + if(ISNUMBER()) + { + // class by number + nIndex=GETNUMBER(); + } + else + { + // class by name or shortname + for (int N=1 ; N<17 ; N++) + { + if( + !stricmp(GETFIRST(), GetClassDesc(N)) || + !stricmp(GETFIRST(), pEverQuest->GetClassThreeLetterCode(N)) + ) + { + nIndex=N; + break; + } + } + } + } + + switch((SkillMembers)pMember->ID) + { + case Name: + if (Dest.Ptr=pStringTable->getString(pSkill->nName,0)) + { + Dest.Type=pStringType; + return true; + } + return false; + case ID: + Dest.DWord=GetSkillIDFromName(pStringTable->getString(pSkill->nName,0)); + Dest.Type=pIntType; + return true; + case ReuseTime: + Dest.DWord=pSkill->ReuseTimer; + Dest.Type=pIntType; + return true; + case MinLevel: + Dest.DWord=pSkill->MinLevel[nIndex]; + Dest.Type=pIntType; + return true; + case SkillCap: + { + DWORD i=GetSkillIDFromName(pStringTable->getString(pSkill->nName,0)); + Dest.DWord=pCSkillMgr->GetSkillCap((EQ_Character*)GetCharInfo(),GetCharInfo2()->Level,GetCharInfo2()->Class,i,true,true,true); + Dest.Type=pIntType; + return true; + } + case AltTimer: + Dest.DWord=pSkill->AltTimer; + Dest.Type=pIntType; + return true; + case Activated: + Dest.DWord=pSkill->Activated; + Dest.Type=pBoolType; + return true; + } + return false; +} + +bool MQ2AltAbilityType::ToString(MQ2VARPTR VarPtr, PCHAR Destination) +{ + if (!VarPtr.Ptr) + return false; + PALTABILITY pAbility=(PALTABILITY)VarPtr.Ptr; + itoa(pAbility->PointsSpent, Destination,10); + return true; +} + +bool MQ2AltAbilityType::GETMEMBER() +{ + if (!VarPtr.Ptr) + return false; + PALTABILITY pAbility=(PALTABILITY)VarPtr.Ptr; + + PMQ2TYPEMEMBER pMember=MQ2AltAbilityType::FindMember(Member); + if (!pMember) + return false; + switch((AltAbilityMembers)pMember->ID) + { + case Name: + if (Dest.Ptr= pCDBStr->GetString(pAbility->nName, 1, NULL)) + { + Dest.Type=pStringType; + return true; + } + return false; + case ShortName: + if (Dest.Ptr=pStringTable->getString(pAbility->nShortName,0)) + { + Dest.Type=pStringType; + return true; + } + return false; + case Description: + if (Dest.Ptr= pCDBStr->GetString(pAbility->nName, 4, NULL)) + { + Dest.Type=pStringType; + return true; + } + return false; + case ID: + Dest.DWord=pAbility->ID; + Dest.Type=pIntType; + return true; + case ReuseTime: + Dest.DWord=pAbility->ReuseTimer; + Dest.Type=pIntType; + return true; + case MyReuseTime: + Dest.DWord=pAltAdvManager->GetCalculatedTimer(pPCData,pAbility); + Dest.Type=pIntType; + return true; + case MinLevel: + Dest.DWord=pAbility->MinLevel; + Dest.Type=pIntType; + return true; + case Cost: + Dest.DWord=pAbility->Cost; + Dest.Type=pIntType; + return true; + case Spell: + if (Dest.Ptr=GetSpellByID(pAbility->SpellID)) + { + Dest.Type=pSpellType; + return true; + } + return false; + case RequiresAbility: + if (pAbility->RequiresAbility && *pAbility->RequiresAbility>0) + { + for (unsigned long nAbility=0 ; nAbilityGetAltAbility(nAbility)) + { + if (tmppAbility->ID == *pAbility->RequiresAbility ) + { + Dest.Ptr=tmppAbility; + Dest.Type=pAltAbilityType; + return true; + } + } + } + } + DebugSpew("ability %d not found\n", *pAbility->RequiresAbility); + return false; + case RequiresAbilityPoints: + if (pAbility->RequiresAbilityPoints) { + Dest.DWord=*pAbility->RequiresAbilityPoints; + Dest.Type=pIntType; + return true; + } + return false; + case MaxRank: + Dest.DWord=pAbility->MaxRank; + Dest.Type=pIntType; + return true; + case AARankRequired: + Dest.DWord=pAbility->AARankRequired; + Dest.Type=pIntType; + return true; + case Type: + Dest.DWord=pAbility->Type; + Dest.Type=pIntType; + return true; + } + return false; +} + +bool MQ2GroupType::ToString(MQ2VARPTR VarPtr, PCHAR Destination) +{ + int nMembers=0; + PCHARINFO pChar=GetCharInfo(); + if (!pChar->pGroupInfo) return false; + for (int index=1;index<6;index++) + { + if (pChar->pGroupInfo->pMember[index]) + nMembers++; + } + itoa(nMembers,Destination,10); + return true; +} + +bool MQ2GroupType::GETMEMBER() +{ + PMQ2TYPEMEMBER pMember=MQ2GroupType::FindMember(Member); + PCHARINFO pChar=GetCharInfo(); + int i; + if (!pMember || !pChar->pGroupInfo) + return false; + switch((GroupMembers)pMember->ID) + { + case xMember: + if (!ISINDEX()) + return false; + if (ISNUMBER()) + { + // by number + Dest.DWord=GETNUMBER(); + Dest.Type=pGroupMemberType; + return true; + } + else + { + Dest.DWord=0; + for (i=1;i<6;i++) + if (pChar->pGroupInfo->pMember[i]) + { + Dest.DWord++; + CHAR Name[MAX_STRING]={0}; + GetCXStr(pChar->pGroupInfo->pMember[i]->pName,Name,MAX_STRING); + if (!stricmp(Name,GETFIRST())) + { + Dest.Type=pIntType; + return true; + } + } + if (!stricmp(pChar->pSpawn->Name,GETFIRST())) { + Dest.DWord=0; + Dest.Type=pIntType; + return true; + } + return false; + } + break; + case Members: + { + Dest.DWord=0; + for (i=1;i<6;i++) + if (pChar->pGroupInfo->pMember[i]) + Dest.DWord++; + Dest.Type=pIntType; + } + return true; + case Leader: + { + if (!pChar->pGroupInfo->pLeader) return false; + CHAR LeaderName[MAX_STRING]={0}; + GetCXStr(pChar->pGroupInfo->pLeader->pName,LeaderName,MAX_STRING); + Dest.DWord=0; + if (!stricmp(pChar->pSpawn->Name,LeaderName)) + { + Dest.Type=pGroupMemberType; + return true; + } + for (i=1;i<6;i++) + { + if (pChar->pGroupInfo->pMember[i]) + { + Dest.DWord++; + CHAR Name[MAX_STRING]={0}; + GetCXStr(pChar->pGroupInfo->pMember[i]->pName,Name,MAX_STRING); + if (!stricmp(Name,LeaderName)) + { + Dest.Type=pGroupMemberType; + return true; + } + } + } + if (!Dest.DWord) + { + // group has no members + Dest.Type=pGroupMemberType; + return true; + } + } + break; + case GroupSize: + { + Dest.DWord=0; + for (i=1;i<6;i++) + if (pChar->pGroupInfo->pMember[i]) + Dest.DWord++; + if (Dest.DWord) Dest.DWord++; + Dest.Type=pIntType; + } + return true; + case MainTank: + { + Dest.DWord = 0; + if(pChar->pGroupInfo->pMember[0]->MainTank) + { + Dest.Type = pGroupMemberType; + return true; + } + for(i = 1; i < 6; i++) + { + if(pChar->pGroupInfo->pMember[i]) + { + Dest.DWord++; + if(pChar->pGroupInfo->pMember[i]->MainTank) + { + Dest.Type = pGroupMemberType; + return true; + } + } + } + } + return false; + case MainAssist: + { + Dest.DWord = 0; + if(pChar->pGroupInfo->pMember[0]->MainAssist) + { + Dest.Type = pGroupMemberType; + return true; + } + for(i = 1; i < 6; i++) + { + if(pChar->pGroupInfo->pMember[i]) + { + Dest.DWord++; + if(pChar->pGroupInfo->pMember[i]->MainAssist) + { + Dest.Type = pGroupMemberType; + return true; + } + } + } + } + return false; + case Puller: + { + Dest.DWord = 0; + if(pChar->pGroupInfo->pMember[0]->Puller) + { + Dest.Type = pGroupMemberType; + return true; + } + for(i = 1; i < 6; i++) + { + if(pChar->pGroupInfo->pMember[i]) + { + Dest.DWord++; + if(pChar->pGroupInfo->pMember[i]->Puller) + { + Dest.Type = pGroupMemberType; + return true; + } + } + } + } + } + return false; +} + +bool MQ2GroupMemberType::ToString(MQ2VARPTR VarPtr, PCHAR Destination) +{ + int i; + if (unsigned long N=VarPtr.DWord) + { + if (N>5) + return false; + PCHARINFO pChar=GetCharInfo(); + if (!pChar->pGroupInfo) return false; + for (i=1; i<6 ; i++) + { + if (pChar->pGroupInfo->pMember[i]) + { + N--; + if (N==0) + { + CHAR Name[MAX_STRING]={0}; + GetCXStr(pChar->pGroupInfo->pMember[i]->pName,Name,MAX_STRING); + strcpy(Destination,CleanupName(Name)); + return true; + } + } + } + } + else + { + strcpy(Destination,CleanupName(GetCharInfo()->pSpawn->Name)); + return true; + } + return false; +} + +bool MQ2GroupMemberType::GETMEMBER() +{ + CHAR MemberName[MAX_STRING]={0}; + CHAR LeaderName[MAX_STRING]={0}; + PSPAWNINFO pGroupMember=0; + PCHARINFO pChar=GetCharInfo(); + PGROUPMEMBER pGroupMemberData=0; + int i; + DWORD nMember = VarPtr.DWord; + if (!pChar->pGroupInfo) return false; + if (unsigned long N=nMember) + { + if (N>5) + return false; + for (i=1; i<6 ; i++) + { + if (pChar->pGroupInfo->pMember[i]) + { + N--; + if (N==0) + { + GetCXStr(pChar->pGroupInfo->pMember[i]->pName,MemberName,MAX_STRING); + pGroupMember=pChar->pGroupInfo->pMember[i]->pSpawn; + pGroupMemberData=pChar->pGroupInfo->pMember[i]; + break; + } + } + } + if (!MemberName) + return false; + } + else + { + pGroupMember=pChar->pSpawn; + strcpy(MemberName,pGroupMember->Name); + pGroupMemberData=pChar->pGroupInfo->pMember[0]; + } + PMQ2TYPEMEMBER pMember=MQ2GroupMemberType::FindMember(Member); + if (!pMember) + { + if (!pGroupMember) + return false; +#ifndef ISXEQ + return pSpawnType->GetMember(*(MQ2VARPTR*)&pGroupMember,Member,Index,Dest); +#else + return pSpawnType->GetMember(*(LSVARPTR*)&pGroupMember,Member,argc,argv,Dest); +#endif + } + + switch((GroupMemberMembers)pMember->ID) + { + case Name: + Dest.Ptr=CleanupName(MemberName); + Dest.Type=pStringType; + return true; + case Leader: + if (!pChar->pGroupInfo->pLeader) return false; + GetCXStr(pChar->pGroupInfo->pLeader->pName,LeaderName,MAX_STRING); + Dest.DWord=!stricmp(MemberName,LeaderName); + Dest.Type=pBoolType; + return true; + case Spawn: + if (Dest.Ptr=pGroupMember) + { + Dest.Type=pSpawnType; + return true; + } + return false; + case Level: + if (pGroupMember) + { + Dest.DWord=pGroupMember->Level; + Dest.Type=pIntType; + return true; + } + else if (pGroupMemberData) + { + Dest.DWord=pGroupMemberData->Level; + Dest.Type=pIntType; + return true; + } + return false; + case MainTank: + if(pGroupMemberData) + { + Dest.DWord=pGroupMemberData->MainTank; + Dest.Type=pBoolType; + return true; + } + return false; + case MainAssist: + if(pGroupMemberData) + { + Dest.DWord=pGroupMemberData->MainAssist; + Dest.Type=pBoolType; + return true; + } + return false; + case Puller: + if(pGroupMemberData) + { + Dest.DWord=pGroupMemberData->Puller; + Dest.Type=pBoolType; + return true; + } + return false; + case Mercenary: + if(pGroupMemberData) + { + Dest.DWord=pGroupMemberData->Mercenary; + Dest.Type=pBoolType; + return true; + } + return false; + case PctAggro: + if(pAggroInfo) + { + Dest.DWord = pAggroInfo->aggroData[nMember + 1].AggroPct; + Dest.Type = pIntType; + return true; + } + } + return false; +} + +bool MQ2RaidType::GETMEMBER() +{ + int i; + if (!pRaid) + return false; + PMQ2TYPEMEMBER pMember=MQ2RaidType::FindMember(Member); + if (!pMember) + return false; + switch((RaidMembers)pMember->ID) + { + case Locked: + Dest.DWord=pRaid->Locked; + Dest.Type=pBoolType; + return true; + case Invited: + Dest.DWord=pRaid->Invited == 2; + Dest.Type=pBoolType; + return true; + case xMember: + if (ISINDEX()) + { + if (ISNUMBER()) + { + DWORD Count=GETNUMBER(); + if (!Count || Count>pRaid->RaidMemberCount) + return false; + for (DWORD nMember = 0 ; nMember < 72 ; nMember++) + { + if (pRaid->RaidMemberUsed[nMember]) + { + Count--; + if (!Count) + { + Dest.DWord=nMember+1; + Dest.Type=pRaidMemberType; + return true; + } + } + } + } + else + { + // by name + for (DWORD nMember=0 ; nMember < 72 ; nMember++) + { + if (pRaid->RaidMemberUsed[nMember] && !stricmp(pRaid->RaidMember[nMember].Name,GETFIRST())) + { + Dest.DWord=nMember+1; + Dest.Type=pRaidMemberType; + return true; + } + } + } + } + return false; + case Members: + Dest.DWord=pRaid->RaidMemberCount; + Dest.Type=pIntType; + return true; + case Target: + Dest.DWord=pRaid->RaidTarget+1; + Dest.Type=pRaidMemberType; + return true; + case Leader: + { + for (DWORD nMember=0 ; nMember < 72 ; nMember++) + { + if (pRaid->RaidMemberUsed[nMember] && !stricmp(pRaid->RaidMember[nMember].Name,pRaid->RaidLeaderName)) + { + Dest.DWord=nMember+1; + Dest.Type=pRaidMemberType; + return true; + } + } + } + return false; + case TotalLevels: + Dest.DWord=pRaid->TotalRaidMemberLevels; + Dest.Type=pIntType; + return true; + case AverageLevel: + Dest.Float=(FLOAT)pRaid->TotalRaidMemberLevels/(FLOAT)pRaid->RaidMemberCount; + Dest.Type=pFloatType; + return true; + case LootType: + Dest.DWord=pRaid->LootType; + Dest.Type=pIntType; + return true; + case Looters: + { + Dest.DWord=0; + for (unsigned long N = 0 ; N < 0x13 ; N++) + { + if (pRaid->RaidLooters[N][0]) + Dest.DWord++; + } + Dest.Type=pIntType; + return true; + } + case Looter: + if (ISINDEX()) + { + if (ISNUMBER()) + { + DWORD Count=GETNUMBER(); + if (!Count) + return 0; + for (DWORD nLooter=0; nLooter<0x13 ; nLooter++) + { + if (pRaid->RaidLooters[nLooter][0]) + { + Count--; + if (Count==0) + { + Dest.Ptr=&pRaid->RaidLooters[nLooter][0]; + Dest.Type=pStringType; + return true; + } + } + } + } + // by name? + } + return false; + case MainAssist: + { + for (i=0; i < 72; i++) + { + if (pRaid->RaidMemberUsed[i] && pRaid->RaidMember[i].RaidMainAssist) + { + Dest.DWord=i+1; + Dest.Type=pRaidMemberType; + return true; + } + } + } + return false; + } + /**/ + return false; +} + +bool MQ2RaidMemberType::GETMEMBER() +{ + DWORD nRaidMember=VarPtr.DWord-1; + if (VarPtr.DWord>=72) + return false; + if (!pRaid->RaidMemberUsed[nRaidMember]) + return false; + PEQRAIDMEMBER pRaidMember=&pRaid->RaidMember[nRaidMember]; + PMQ2TYPEMEMBER pMember=MQ2RaidMemberType::FindMember(Member); + if (!pMember) + { + if(!GetSpawnByName(pRaidMember->Name)) + return false; +#ifndef ISXEQ + return pSpawnType->GetMember(*(MQ2VARPTR*)GetSpawnByName(pRaidMember->Name),Member,Index,Dest); +#else + return pSpawnType->GetMember(*(LSVARPTR*)GetSpawnByName(pRaidMember->Name),Member,argc,argv,Dest); +#endif + } + + switch((RaidMemberMembers)pMember->ID) + { + case Name: + Dest.Ptr=pRaidMember->Name; + Dest.Type=pStringType; + return true; + case Group: + Dest.DWord=pRaidMember->GroupNumber+1; + Dest.Type=pIntType; + return true; + case GroupLeader: + Dest.DWord=pRaidMember->GroupLeader; + Dest.Type=pBoolType; + return true; + case RaidLeader: + Dest.DWord=pRaidMember->RaidLeader; + Dest.Type=pBoolType; + return true; + case Looter: + if (pRaidMember->RaidLeader) + { + Dest.DWord=1; + Dest.Type=pBoolType; + return true; + } + if (pRaid->LootType==2) + { + Dest.DWord=pRaidMember->GroupLeader; + Dest.Type=pBoolType; + return true; + } + if (pRaid->LootType==3) + { + for (DWORD N = 0 ; N < 0x13 ; N++) + { + if (!stricmp(pRaid->RaidLooters[N],pRaidMember->Name)) + { + Dest.DWord=1; + Dest.Type=pBoolType; + return true; + } + } + } + Dest.DWord=0; + Dest.Type=pBoolType; + return true; + case Spawn: + if (Dest.Ptr=(PSPAWNINFO)GetSpawnByName(pRaidMember->Name)) + { + Dest.Type=pSpawnType; + return true; + } + return false; + case Level: + Dest.DWord=pRaidMember->nLevel; + Dest.Type=pIntType; + return true; + case Class: + Dest.DWord=pRaidMember->nClass; + Dest.Type=pClassType; + return true; + /* + { + if (PSPAWNINFO pSpawn=(PSPAWNINFO)GetSpawnByName(pRaidMember->Name)) + { + Dest.DWord=pSpawn->Class; + Dest.Type=pIntType; + return true; + } + pCharData->KunarkClass(0,0,0x18C,1); + } + return false; + /**/ + } + return false; +} + +bool MQ2EvolvingItemType::GETMEMBER() +{ + if (!VarPtr.Ptr) + return false; + PCONTENTS pItem=(PCONTENTS)VarPtr.Ptr; + PMQ2TYPEMEMBER pMember=MQ2EvolvingItemType::FindMember(Member); + if (!pMember) + return false; + switch((EvolvingItemMembers)pMember->ID) + { + case ExpPct: + Dest.Float=(FLOAT)pItem->EvolvingExpPct; + Dest.Type=pFloatType; + return true; + case ExpOn: + Dest.DWord=pItem->EvolvingExpOn; + Dest.Type=pBoolType; + return true; + case Level: + Dest.DWord=pItem->EvolvingCurrentLevel; + Dest.Type=pIntType; + return true; + case MaxLevel: + Dest.DWord=pItem->EvolvingMaxLevel; + Dest.Type=pIntType; + return true; + } + return false; +} + +bool MQ2DynamicZoneType::GETMEMBER() +{ + if(!pDZMember) + return false; + PMQ2TYPEMEMBER pMember=MQ2DynamicZoneType::FindMember(Member); + if(!pMember) + return false; + switch((DynamicZoneMembers)pMember->ID) + { + case Name: + Dest.Ptr=pDynamicZone->ExpeditionName; + Dest.Type=pStringType; + return true; + case Members: + { + Dest.DWord=0; + PDZMEMBER pDynamicZoneMember=pDynamicZone->pMemberList; + while(pDynamicZoneMember) + { + Dest.DWord++; + pDynamicZoneMember=pDynamicZoneMember->pNext; + } + } + Dest.Type=pIntType; + return true; + case MaxMembers: + Dest.DWord=pDynamicZone->MaxPlayers; + Dest.Type=pIntType; + return true; + case xMember: + if(ISINDEX()) + { + PDZMEMBER pDynamicZoneMember=pDynamicZone->pMemberList; + if(ISNUMBER()) + { + DWORD Count=GETNUMBER(); + if (!Count || Count>pDynamicZone->MaxPlayers) + return false; + Count--; + for(DWORD i=0; pDynamicZoneMember!=0; i++) + { + if(i==Count) + { + Dest.Ptr=pDynamicZoneMember; + Dest.Type=pDZMemberType; + return true; + } + pDynamicZoneMember=pDynamicZoneMember->pNext; + } + } + else + { + while(pDynamicZoneMember) + { + if(!stricmp(pDynamicZoneMember->Name,GETFIRST())) + { + Dest.Ptr=pDynamicZoneMember; + Dest.Type=pDZMemberType; + return true; + } + pDynamicZoneMember=pDynamicZoneMember->pNext; + } + } + } + return false; + case Leader: + { + PDZMEMBER pDynamicZoneMember=pDynamicZone->pMemberList; + for(DWORD i=0; iMaxPlayers; i++) + { + if(!strcmp(pDynamicZoneMember->Name,(char*)instExpeditionLeader)) + { + Dest.Ptr=pDynamicZoneMember; + Dest.Type=pDZMemberType; + return true; + } + pDynamicZoneMember=pDynamicZoneMember->pNext; + } + } + } + return false; +} + +bool MQ2DZMemberType::GETMEMBER() +{ + if(!VarPtr.Ptr) + return false; + PMQ2TYPEMEMBER pMember=MQ2DZMemberType::FindMember(Member); + if(!pMember) + return false; + PDZMEMBER pDynamicZoneMember=(PDZMEMBER)VarPtr.Ptr; + switch((DZMemberTypeMembers)pMember->ID) + { + case Name: + Dest.Ptr=pDynamicZoneMember->Name; + Dest.Type=pStringType; + return true; + case Status: + switch(pDynamicZoneMember->Status) + { + case 0: + Dest.Ptr="Unknown"; + break; + case 1: + Dest.Ptr="Online"; + break; + case 2: + Dest.Ptr="Offline"; + break; + case 3: + Dest.Ptr="In Dynamic Zone"; + break; + case 4: + Dest.Ptr="Link Dead"; + break; + } + Dest.Type=pStringType; + return true; + } + return false; +} + +bool MQ2FellowshipType::GETMEMBER() +{ + if(!VarPtr.Ptr) + return false; + PMQ2TYPEMEMBER pMember=MQ2FellowshipType::FindMember(Member); + if(!pMember) + return false; + PFELLOWSHIPINFO pFellowship=(PFELLOWSHIPINFO)VarPtr.Ptr; + switch((FellowshipTypeMembers)pMember->ID) + { + case ID: + Dest.DWord=pFellowship->FellowshipID; + Dest.Type=pIntType; + return true; + case Leader: + Dest.Ptr=pFellowship->Leader; + Dest.Type=pStringType; + return true; + case MotD: + Dest.Ptr=pFellowship->MotD; + Dest.Type=pStringType; + return true; + case Members: + Dest.DWord=pFellowship->Members; + Dest.Type=pIntType; + return true; + case xMember: + if(ISINDEX()) + { + if(ISNUMBER()) + { + DWORD i=GETNUMBER(); + if(!i || i>pFellowship->Members) + return false; + Dest.Ptr=&pFellowship->FellowshipMember[--i]; + Dest.Type=pFellowshipMemberType; + return true; + } + else + { + for(DWORD i=0; iMembers; i++) + { + if(!stricmp(pFellowship->FellowshipMember[i].Name,GETFIRST())) + { + Dest.Ptr=&pFellowship->FellowshipMember[i]; + Dest.Type=pFellowshipMemberType; + return true; + } + } + } + } + return false; + case CampfireDuration: + if(((PSPAWNINFO)pCharSpawn)->CampfireTimestamp) + { + Dest.DWord=(((PSPAWNINFO)pCharSpawn)->CampfireTimestamp-GetFastTime())/6; + Dest.Type=pTicksType; + return true; + } + return false; + case CampfireY: + Dest.Float=((PSPAWNINFO)pCharSpawn)->CampfireY; + Dest.Type=pFloatType; + return true; + case CampfireX: + Dest.Float=((PSPAWNINFO)pCharSpawn)->CampfireX; + Dest.Type=pFloatType; + return true; + case CampfireZ: + Dest.Float=((PSPAWNINFO)pCharSpawn)->CampfireZ; + Dest.Type=pFloatType; + return true; + case CampfireZone: + if(((PSPAWNINFO)pCharSpawn)->CampfireZoneID) + { + Dest.Ptr=((PWORLDDATA)pWorldData)->ZoneArray[((PSPAWNINFO)pCharSpawn)->CampfireZoneID]; + Dest.Type=pZoneType; + return true; + } + return false; + case Campfire: + Dest.Int=((PSPAWNINFO)pCharSpawn)->Campfire; + Dest.Type=pBoolType; + return true; + } + return false; +} + +bool MQ2FellowshipMemberType::GETMEMBER() +{ + if(!VarPtr.Ptr) + return false; + PMQ2TYPEMEMBER pMember=MQ2FellowshipMemberType::FindMember(Member); + if(!pMember) + return false; + PFELLOWSHIPMEMBER pFellowshipMember=(PFELLOWSHIPMEMBER)VarPtr.Ptr; + switch((FMTypeMembers)pMember->ID) + { + case Zone: + if(pFellowshipMember->ZoneID) + { + Dest.Ptr=((PWORLDDATA)pWorldData)->ZoneArray[pFellowshipMember->ZoneID]; + Dest.Type=pZoneType; + return true; + } + return false; + case Level: + Dest.DWord=pFellowshipMember->Level; + Dest.Type=pIntType; + return true; + case Class: + Dest.DWord=pFellowshipMember->Class; + Dest.Type=pClassType; + return true; + case LastOn: + if(pFellowshipMember->LastOn) + { + Dest.DWord=(GetFastTime()-pFellowshipMember->LastOn)/6; + Dest.Type=pTicksType; + return true; + } + return false; + case Name: + Dest.Ptr=pFellowshipMember->Name; + Dest.Type=pStringType; + return true; + } + return false; +} + +bool MQ2FriendsType::GETMEMBER() +{ + PMQ2TYPEMEMBER pMember=MQ2FriendsType::FindMember(Member); + if (!pMember) + return false; + switch((FriendsMembers)pMember->ID) + { + case xFriend: + if(ISINDEX() && ((PEVERQUEST)pEverQuest)->ChatService) { + class CChatService *pChat=(class CChatService *) ((PEVERQUEST)pEverQuest)->ChatService; + int i; + if(ISNUMBER()) { + i=GETNUMBER(); + if (i > pChat->GetNumberOfFriends()) + return false; + + if (Dest.Ptr=pChat->GetFriendName(i-1)) { + Dest.Type=pStringType; + return true; + } + } else { + for(i=0; iGetNumberOfFriends(); i++) { + if(!stricmp(pChat->GetFriendName(i),GETFIRST())) { + Dest.DWord=1; + Dest.Type=pBoolType; + return true; + } + } + return false; + } + } + return false; + default: + return false; + }; +} + +bool MQ2TargetType::GETMEMBER() +{ + int buffID = 0; + DWORD i,j; + if (!VarPtr.Ptr) + return false; + PMQ2TYPEMEMBER pMember=MQ2TargetType::FindMember(Member); + if (!pMember) + { +#ifndef ISXEQ + return pSpawnType->GetMember(*(MQ2VARPTR*)&VarPtr.Ptr,Member,Index,Dest); +#else + return pSpawnType->GetMember(*(LSVARPTR*)&VarPtr.Ptr,Member,argc,argv,Dest); +#endif + } + switch((TargetMembers)pMember->ID) + { + case Buff: + if(!(((PCTARGETWND)pTargetWnd)->Type > 0)) + return false; + if(ISINDEX()) + { + if(ISNUMBER()) + { + DWORD nBuff = GETNUMBER(); + if (!nBuff || nBuff >= NUM_BUFF_SLOTS) + return false; + j = 0; + for(i = 0; i < NUM_BUFF_SLOTS; i++) + { + buffID = ((PCTARGETWND)pTargetWnd)->BuffSpellID[i]; + if(buffID && nBuff == ++j) + { + Dest.Ptr = GetSpellByID((DWORD)buffID); + Dest.Type = pSpellType; + return true; + } + } + } + else + { + for(i = 0; i < NUM_BUFF_SLOTS; i++) + { + buffID = ((PCTARGETWND)pTargetWnd)->BuffSpellID[i]; + if(buffID && !stricmp(GETFIRST(), GetSpellNameByID(buffID))) + { + Dest.Ptr = GetSpellByID((DWORD)buffID); + Dest.Type = pSpellType; + return true; + } + } + } + } + else + { + // return first buff + for(i = 0; i < NUM_BUFF_SLOTS; i++) + { + buffID = ((PCTARGETWND)pTargetWnd)->BuffSpellID[i]; + if(buffID) + { + if(PSPELL pSpell = GetSpellByID(buffID)) + { + strcpy(DataTypeTemp, pSpell->Name); + Dest.Ptr = &DataTypeTemp[0]; + Dest.Type = pStringType; + return true; + } + } + } + } + return false; + case BuffCount: + if(!(((PCTARGETWND)pTargetWnd)->Type > 0)) + return false; + Dest.DWord = 0; + for(i = 0; i < NUM_BUFF_SLOTS; i++) + if(((PCTARGETWND)pTargetWnd)->BuffSpellID[i]) + Dest.DWord++; + Dest.Type = pIntType; + return true; + case BuffDuration: + if(!(((PCTARGETWND)pTargetWnd)->Type > 0)) + return false; + if(ISINDEX()) + { + if(ISNUMBER()) + { + DWORD nBuff = GETNUMBER(); + if (!nBuff || nBuff >= NUM_BUFF_SLOTS) + return false; + j = 0; + for(i = 0; i < NUM_BUFF_SLOTS; i++) + { + buffID = ((PCTARGETWND)pTargetWnd)->BuffSpellID[i]; + if(buffID && nBuff == ++j) + { + Dest.DWord = ((((PCTARGETWND)pTargetWnd)->BuffTimer[i] / 1000) + 6) / 6; + Dest.Type = pTicksType; + return true; + } + } + } + else + { + for(i = 0; i < NUM_BUFF_SLOTS; i++) + { + buffID = ((PCTARGETWND)pTargetWnd)->BuffSpellID[i]; + if(buffID && !stricmp(GETFIRST(), GetSpellNameByID(buffID))) + { + Dest.DWord = ((((PCTARGETWND)pTargetWnd)->BuffTimer[i] / 1000) + 6) / 6; + Dest.Type = pTicksType; + return true; + } + } + } + } + else + { + // return first buff + for(i = 0; i < NUM_BUFF_SLOTS; i++) + { + buffID = ((PCTARGETWND)pTargetWnd)->BuffSpellID[i]; + if(buffID) + { + Dest.DWord = ((((PCTARGETWND)pTargetWnd)->BuffTimer[i] / 1000) + 6) / 6; + Dest.Type = pTicksType; + return true; + } + } + } + return false; + case PctAggro: + if(pAggroInfo) + { + Dest.DWord = pAggroInfo->aggroData[AD_Player].AggroPct; + Dest.Type = pIntType; + return true; + } + return false; + case SecondaryPctAggro: + if(pAggroInfo) + { + Dest.DWord = pAggroInfo->aggroData[AD_Secondary].AggroPct; + Dest.Type = pIntType; + return true; + } + return false; + case SecondaryAggroPlayer: + if(pAggroInfo && pAggroInfo->AggroSecondaryID) + { + Dest.Ptr = GetSpawnByID(pAggroInfo->AggroSecondaryID); + Dest.Type = pSpawnType; + return true; + } + } + return false; +} + +bool MQ2XTargetType::GETMEMBER() +{ + if(!GetCharInfo() || !GetCharInfo()->pXTargetMgr) + return false; + if(PMQ2TYPEMEMBER pMember=MQ2XTargetType::FindMember(Member)) + { + XTARGETDATA xtd = GetCharInfo()->pXTargetMgr->pXTargetArray->pXTargetData[VarPtr.DWord]; + switch((xTargetMembers)pMember->ID) + { + case Type: + { + char *pType = GetXtargetType(xtd.xTargetType); + Dest.Ptr = pType ? pType : "UNKNOWN"; + Dest.Type = pStringType; + return true; + } + case ID: + Dest.DWord = xtd.SpawnID; + Dest.Type = pIntType; + return true; + case Name: + Dest.Ptr = xtd.Name[0] ? xtd.Name : "NULL"; + Dest.Type = pStringType; + return true; + case PctAggro: + if(pAggroInfo) + { + Dest.DWord = pAggroInfo->aggroData[AD_xTarget1 + VarPtr.DWord].AggroPct; + Dest.Type = pIntType; + return true; + } + } + } + return false; +}; + diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2DataTypes.h b/client_files/native_autoloot/eq-core-dll/src/MQ2DataTypes.h new file mode 100644 index 0000000000..5154db6bb8 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2DataTypes.h @@ -0,0 +1,3686 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +// non-mq2data TODO +// command to clear macro return value +// networking +// macro line continuation e.g. \ +// command to set raid class colors +// /cast list +// #chat tell +// +// mq2data todo: +// ------------- +// "bind" type (key binds) +// Friend TLO +// Ignore TLO +// key state (ctrl/shift/alt) +// spawn count + +#ifdef ISXEQ +#pragma warning(disable:4996) +#endif +#ifdef ISXEQ_LEGACY +#pragma warning(disable:4996) +#endif + +#ifndef ISXEQ +LEGACY_API class MQ2FloatType *pFloatType; +LEGACY_API class MQ2StringType *pStringType; +LEGACY_API class MQ2IntType *pIntType; +LEGACY_API class MQ2ByteType *pByteType; +LEGACY_API class MQ2BoolType *pBoolType; +LEGACY_API class MQ2TimeType *pTimeType; +LEGACY_API class MQ2MathType *pMathType; +LEGACY_API class MQ2MacroType *pMacroType; +LEGACY_API class MQ2PluginType *pPluginType; + +#define pIntPtrType pIntType +#define pBytePtrType pByteType +#define pBoolPtrType pBoolType +#define pFloatPtrType pFloatType + +#define INTPTR(x) Dest.DWord=x +#define BYTEPTR(x) Dest.Byte=x +#define BOOLPTR(x) Dest.DWord=x +#define FLOATPTR(x) Dest.Float=x + +#define TypeMethod(x) +#define AddMethod(x,y) +#else +#define INTPTR(x) Dest.Ptr=&x +#define BYTEPTR(x) Dest.Ptr=&x +#define BOOLPTR(x) Dest.Ptr=&x +#define FLOATPTR(x) Dest.Ptr=&x + +#define Argb RGB +#define MQ2VARPTR LSVARPTR +#endif +LEGACY_VAR class MQ2SpawnType *pSpawnType; +LEGACY_VAR class MQ2CharacterType *pCharacterType; +LEGACY_VAR class MQ2BuffType *pBuffType; +LEGACY_VAR class MQ2SpellType *pSpellType; +LEGACY_VAR class MQ2TicksType *pTicksType; + +LEGACY_VAR class MQ2SkillType *pSkillType; +LEGACY_VAR class MQ2AltAbilityType *pAltAbilityType; + +LEGACY_VAR class MQ2ClassType *pClassType; +LEGACY_VAR class MQ2RaceType *pRaceType; +LEGACY_VAR class MQ2BodyType *pBodyType; + +LEGACY_VAR class MQ2GroundType *pGroundType; +LEGACY_VAR class MQ2SwitchType *pSwitchType; + +LEGACY_VAR class MQ2MacroQuestType *pMacroQuestType; + +LEGACY_VAR class MQ2CorpseType *pCorpseType; +LEGACY_VAR class MQ2WindowType *pWindowType; +LEGACY_VAR class MQ2MerchantType *pMerchantType; +LEGACY_VAR class MQ2ZoneType *pZoneType; +LEGACY_VAR class MQ2CurrentZoneType *pCurrentZoneType; +LEGACY_VAR class MQ2ItemType *pItemType; +LEGACY_VAR class MQ2DeityType *pDeityType; +LEGACY_VAR class MQ2ArgbType *pArgbType; +LEGACY_VAR class MQ2TypeType *pTypeType; + +LEGACY_VAR class MQ2HeadingType *pHeadingType; + +LEGACY_VAR class MQ2InvSlotType *pInvSlotType; + +LEGACY_VAR class MQ2ArrayType *pArrayType; +LEGACY_VAR class MQ2TimerType *pTimerType; + +LEGACY_VAR class MQ2RaidType *pRaidType; +LEGACY_VAR class MQ2RaidMemberType *pRaidMemberType; + +LEGACY_VAR class MQ2GroupType *pGroupType; +LEGACY_VAR class MQ2GroupMemberType *pGroupMemberType; +LEGACY_VAR class MQ2EvolvingItemType *pEvolvingItemType; +LEGACY_VAR class MQ2DynamicZoneType *pDynamicZoneType; +LEGACY_VAR class MQ2DZMemberType *pDZMemberType; +LEGACY_VAR class MQ2FellowshipType *pFellowshipType; +LEGACY_VAR class MQ2FellowshipMemberType *pFellowshipMemberType; +LEGACY_VAR class MQ2FriendsType *pFriendsType; +LEGACY_VAR class MQ2TargetType *pTargetType; +LEGACY_VAR class MQ2XTargetType *pXTargetType; + +#define UseTemp(mystring) strcpy(DataTypeTemp,mystring) +#define TypeMember(name) AddMember((DWORD)name,""#name) + +#ifndef ISXEQ +class MQ2BoolType : public MQ2Type +{ +public: + MQ2BoolType():MQ2Type("bool") + { + } + + ~MQ2BoolType() + { + } + + // pure type, no members + bool GETMEMBER() + { + return false; + } + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (VarPtr.DWord) + strcpy(Destination,"TRUE"); + else + strcpy(Destination,"FALSE"); + return true; + } + + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + VarPtr.DWord=Source.DWord; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + VarPtr.DWord=0; + if (!stricmp(Source,"TRUE")) + VarPtr.DWord=1; + else if (atof(Source)!=0.0f) + VarPtr.DWord=1; + return true; + } +}; +class MQ2IntType : public MQ2Type +{ +public: + static enum IntMembers + { + Float=1, + Hex=2, + Reverse=3, + }; + MQ2IntType():MQ2Type("int") + { + TypeMember(Float); + TypeMember(Hex); + TypeMember(Reverse); + } + + ~MQ2IntType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + itoa(VarPtr.Int,Destination,10); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + VarPtr.Int=Source.Int; + return true; + } + + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + VarPtr.Int=atoi(Source); + return true; + } +}; +#endif +class MQ2ArgbType : public MQ2Type +{ +public: + static enum ArgbMembers + { + A=0, + R=1, + G=2, + B=3, + Int=4, + }; + MQ2ArgbType():MQ2Type("argb") + { + TypeMember(A); + TypeMember(R); + TypeMember(G); + TypeMember(B); + TypeMember(Int); + } + + ~MQ2ArgbType() + { + } + + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + sprintf(Destination,"%x",VarPtr.Int); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + VarPtr.DWord=Source.DWord; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + sscanf(Source,"%x",&VarPtr.Int); + return true; + } +}; +#ifndef ISXEQ +class MQ2ByteType : public MQ2Type +{ +public: + MQ2ByteType():MQ2Type("byte") + { + } + + ~MQ2ByteType() + { + } + + // pure type, no members + bool GETMEMBER() + { + return false; + } + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + itoa(VarPtr.Int,Destination,10); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + VarPtr.DWord=Source.DWord%0xFF; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + VarPtr.DWord=atoi(Source)%0xFF; + return true; + } +}; +class MQ2StringType : public MQ2Type +{ +public: + static enum StringMembers + { + Arg=1, + Mid=2, + Left=3, + Right=4, + Find=5, + Length=6, + Upper=7, + Lower=8, + Compare=9, + CompareCS=10, + Equal=11, + NotEqual=12, + EqualCS=13, + NotEqualCS=14, + Count=15, + Token=16, + Replace=17 + }; + + MQ2StringType():MQ2Type("string") + { + TypeMember(Arg); + TypeMember(Mid); + TypeMember(Left); + TypeMember(Right); + TypeMember(Find); + TypeMember(Length); + TypeMember(Upper); + TypeMember(Lower); + TypeMember(Compare); + TypeMember(CompareCS); + TypeMember(Equal); + TypeMember(NotEqual); + TypeMember(EqualCS); + TypeMember(NotEqualCS); + TypeMember(Count); + TypeMember(Token); + TypeMember(Replace); + } + + ~MQ2StringType() + { + } + bool MQ2StringType::GetMember(MQ2VARPTR VarPtr, PCHAR Member, PCHAR Index, MQ2TYPEVAR &Dest); + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + strcpy(Destination,(const char *)VarPtr.Ptr); + return true; + } + void InitVariable(MQ2VARPTR &VarPtr) + { + VarPtr.Ptr=malloc(MAX_STRING); + ZeroMemory(VarPtr.Ptr,MAX_STRING); + } + void FreeVariable(MQ2VARPTR &VarPtr) + { + free(VarPtr.Ptr); + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pStringType) + return false; + strcpy((char*)VarPtr.Ptr,(char*)Source.Ptr); + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + strcpy((char*)VarPtr.Ptr,Source); + return true; + } +}; +class MQ2FloatType : public MQ2Type +{ +public: + static enum FloatMembers + { + Deci=1, + Centi=2, + Milli=3, + Int=4, + Precision=5, + }; + + MQ2FloatType():MQ2Type("float") + { + TypeMember(Deci); + TypeMember(Centi); + TypeMember(Milli); + TypeMember(Int); + TypeMember(Precision); + } + + ~MQ2FloatType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + sprintf(Destination,"%.2f",VarPtr.Float); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pFloatType && Source.Type!=(MQ2Type*)pHeadingType) + VarPtr.Float=(FLOAT)Source.DWord; + else + VarPtr.Float=Source.Float; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + VarPtr.Float=(FLOAT)atof(Source); + return true; + } +}; +#endif + +class MQ2TicksType : public MQ2Type +{ +public: + static enum TicksMembers + { + Hours=1, + Minutes=2, + Seconds=3, + Time=4, + TotalMinutes=5, + TotalSeconds=6, + Ticks=7, + TimeHMS=8, + }; + MQ2TicksType():MQ2Type("ticks") + { + TypeMember(Hours); + TypeMember(Minutes); + TypeMember(Seconds); + TypeMember(Time); + TypeMember(TotalMinutes); + TypeMember(TotalSeconds); + TypeMember(Ticks); + TypeMember(TimeHMS); + } + + ~MQ2TicksType() + { + } + + bool GETMEMBER(); + + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + itoa(VarPtr.DWord,Destination,10); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + VarPtr.DWord=Source.DWord; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + VarPtr.DWord=atoi(Source); + return true; + } +}; + + +class MQ2SpawnType : public MQ2Type +{ +public: + static enum SpawnMembers + { + ID=1, + Name=2, + Level=3, + X=4, + Y=5, + Z=6, + DistanceX=7, + DistanceY=8, + DistanceZ=9, + Distance=10, + Distance3D=11, + DistancePredict=12, + Next=13, + Prev=14, + Heading=15, + Speed=16, + Levitating=17, + Sneaking=18, + HeadingTo=19, + Light=20, + Body=21, + State=22, + CurrentHPs=23, + MaxHPs=24, + PctHPs=25, + Deity=26, + Type=28, + CleanName=29, + Surname=30, + Guild=31, + GuildStatus=32, + Master=33, + Pet=34, + Race=35, + Class=36, + Gender=38, + GM=39, + Height=40, + MaxRange=41, + AARank=42, + Casting=43, + Mount=44, + FeetWet=45, + Underwater=46, + Animation=48, + Holding=49, + Look=50, + N=51, + W=52, + U=53, + S=54, + E=55, + D=56, + DistanceN=57, + DistanceW=58, + DistanceU=59, + Invis=60, + Linkdead=61, + LFG=62, + Trader=63, + AFK=64, + xConColor=65, + Standing=67, + Sitting=68, + Ducking=69, + Feigning=70, + Binding=71, + Invited=72, + NearestSpawn=73, + MaxRangeTo=74, + DisplayName=75, + AATitle=76, + xGroupLeader=77, + Mark=78, + Assist=79, + Anonymous=80, + Roleplaying=81, + xLineOfSight=82, + HeadingToLoc=83, + Title=84, + Suffix=85, + Fleeing=86, + Named=87, + Buyer=88, + Moving=89, + StandState=90, + Dead=91, + Stunned=92, + Hovering=93, + CurrentMana=94, + MaxMana=95, + CurrentEndurance=96, + MaxEndurance=97, + Loc=98, + LocYX=99, + Owner=100, + Following=101, + }; + static enum SpawnMethods + { + Target=1, + Face=2, + xAssist=4, + LeftClick=5, + RightClick=6, + }; + MQ2SpawnType():MQ2Type("spawn") + { + TypeMember(ID);//1, + TypeMember(Name);//2, + TypeMember(Level);//3, + TypeMember(X);//4, + TypeMember(Y);//5, + TypeMember(Z);//6, + TypeMember(DistanceX);//7, + TypeMember(DistanceY);//8, + TypeMember(DistanceZ);//9, + TypeMember(Distance);//10, + TypeMember(Distance3D);//11, + TypeMember(DistancePredict);//12, + TypeMember(Next);//13, + TypeMember(Prev);//14, + TypeMember(Heading);//15, + TypeMember(Speed);//16, + TypeMember(Levitating);//17, + TypeMember(Sneaking);//18, + TypeMember(HeadingTo);//19, + TypeMember(Light);//20, + TypeMember(Body);//21, + TypeMember(State);//22, + TypeMember(CurrentHPs);//23, + TypeMember(MaxHPs);//24, + TypeMember(PctHPs);//25, + TypeMember(Deity);//26, + TypeMember(Type);//28, + TypeMember(CleanName);//29, + TypeMember(Surname);//30, + TypeMember(Guild);//31, + TypeMember(GuildStatus);//32, + TypeMember(Master);//33, + TypeMember(Pet);//34, + TypeMember(Race);//35, + TypeMember(Class);//36, + TypeMember(Gender);//38, + TypeMember(GM);//39, + TypeMember(Height);//40, + TypeMember(MaxRange);//41, + TypeMember(AARank); + TypeMember(Casting); + TypeMember(Mount); + TypeMember(FeetWet); + TypeMember(Underwater); + TypeMember(Animation); + TypeMember(Holding); + TypeMember(Look); + TypeMember(N); + TypeMember(W); + TypeMember(U); + TypeMember(S); + TypeMember(E); + TypeMember(D); + TypeMember(DistanceN);//7, + TypeMember(DistanceW);//8, + TypeMember(DistanceU);//9, + TypeMember(Invis); + TypeMember(Linkdead); + TypeMember(LFG); + TypeMember(Trader); + TypeMember(AFK); + AddMember(xConColor,"ConColor"); + TypeMember(Standing);//=67, + TypeMember(Sitting);//68, + TypeMember(Ducking);//=69, + TypeMember(Feigning);//=70, + TypeMember(Binding);//=71, + TypeMember(Invited); + TypeMember(NearestSpawn); + TypeMember(MaxRangeTo); + TypeMember(DisplayName); + TypeMember(AATitle); + AddMember(xGroupLeader,"GroupLeader"); + TypeMember(Mark); + TypeMember(Assist); + TypeMember(Anonymous); + TypeMember(Roleplaying); + AddMember(xLineOfSight,"LineOfSight"); + TypeMember(HeadingToLoc); + TypeMember(Title); //84 + TypeMember(Suffix); //85 + TypeMember(Fleeing); + TypeMember(Named); + TypeMember(Buyer); + TypeMember(Moving); + TypeMember(StandState); + TypeMember(Dead); + TypeMember(Stunned); + TypeMember(Hovering); + TypeMember(CurrentMana); + TypeMember(MaxMana); + TypeMember(CurrentEndurance); + TypeMember(MaxEndurance); + TypeMember(Loc); + TypeMember(LocYX); + TypeMember(Owner); + TypeMember(Following); + + TypeMethod(Target); + TypeMethod(Face); + TypeMethod(LeftClick); + TypeMethod(RightClick); + AddMethod(xAssist,"Assist"); + } + + ~MQ2SpawnType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (!VarPtr.Ptr) + return false; + strcpy(Destination,((PSPAWNINFO)VarPtr.Ptr)->Name); + return true; + } + void InitVariable(MQ2VARPTR &VarPtr) + { + VarPtr.Ptr=malloc(sizeof(SPAWNINFO)); + ZeroMemory(VarPtr.Ptr,sizeof(SPAWNINFO)); + } + void FreeVariable(MQ2VARPTR &VarPtr) + { + free(VarPtr.Ptr); + } + + virtual bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type==pSpawnType) + { + memcpy(VarPtr.Ptr,Source.Ptr,sizeof(SPAWNINFO)); + return true; + } + else + { + if (PSPAWNINFO pOther=(PSPAWNINFO)GetSpawnByID(Source.DWord)) + { + memcpy(VarPtr.Ptr,pOther,sizeof(SPAWNINFO)); + return true; + } + } + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + if (PSPAWNINFO pOther=(PSPAWNINFO)GetSpawnByID(atoi(Source))) + { + memcpy(VarPtr.Ptr,pOther,sizeof(SPAWNINFO)); + return true; + } + return false; + } +}; + +class MQ2CharacterType : public MQ2Type +{ +public: + static enum CharacterMembers + { + ID=1, + Name=2, + Level=3, + Exp=4, + Spawn=5, + Dar=6, + AAExp=7, + AAPoints=8, + CurrentHPs=10, + MaxHPs=11, + HPRegen=12, + PctHPs=13, + CurrentMana=14, + MaxMana=15, + ManaRegen=16, + PctMana=17, + Buff=18, + Song=19, + Book=20, + Skill=21, + Ability=22, + Surname=23, + Cash=24, + CashBank=25, + PlatinumShared=26, + Grouped=27, + HPBonus=28, + ManaBonus=29, + GukEarned=30, + MMEarned=31, + RujEarned=32, + TakEarned=33, + MirEarned=34, + LDoNPoints=35, + CurrentFavor=36, + CareerFavor=37, + Endurance=38, + Inventory=39, + Bank=40, + Combat=42, + FreeInventory=43, + Gem=44, + SpellReady=45, + GroupLeaderExp=46, + RaidLeaderExp=47, + GroupLeaderPoints=48, + RaidLeaderPoints=49, + Drunk=50, + STR=51, + STA=52, + CHA=53, + DEX=54, + INT=55, + AGI=56, + WIS=57, + svMagic=58, + svFire=59, + svCold=60, + svPoison=61, + svDisease=62, + Hunger=63, + Thirst=64, + BaseSTR=65, + BaseSTA=66, + BaseCHA=67, + BaseDEX=68, + BaseINT=69, + BaseAGI=70, + BaseWIS=71, + PracticePoints=72, + PctExp=73, + PctAAExp=74, + Moving=75, + AbilityReady=76, + PetBuff=77, + Platinum=78, + Gold=79, + Silver=80, + Copper=81, + PlatinumBank=82, + GoldBank=83, + SilverBank=84, + CopperBank=85, + PctGroupLeaderExp=86, + PctRaidLeaderExp=87, + Stunned=88, + RangedReady=89, + AltTimerReady=90, + MaxEndurance=91, + PctEndurance=92, + AltAbility=93, + AltAbilityReady=94, + AltAbilityTimer=95, + CombatAbility=96, + CombatAbilityTimer=97, + LargestFreeInventory=98, + TargetOfTarget=99, + RaidAssistTarget=100, + GroupAssistTarget=101, + RaidMarkNPC=102, + GroupMarkNPC=103, + CountBuffs=104, + LanguageSkill=105, + EnduranceBonus=106, + CombatEffectsBonus=107, + ShieldingBonus=108, + SpellShieldBonus=109, + AvoidanceBonus=110, + AccuracyBonus=111, + StunResistBonus=112, + StrikeThroughBonus=113, + AttackBonus=114, + HPRegenBonus=115, + ManaRegenBonus=116, + DamageShieldBonus=117, + DoTShieldBonus=118, + AttackSpeed=119, + GroupList=120, + AmIGroupLeader=121, + CurrentEndurance=122, + EnduranceRegen=123, + FreeBuffSlots=124, + CurrentWeight=125, + AAPointsSpent=126, + AAPointsTotal=127, + TributeActive=128, + CombatAbilityReady=129, + Running=130, + GroupSize=131, + TributeTimer=132, + RadiantCrystals=133, + EbonCrystals=134, + Shrouded=135, + AutoFire=136, + Language=137, + Aura=138, + LAMarkNPC=139, + LANPCHealth=140, + LADelegateMA=141, + LADelegateMarkNPC=142, + LAInspectBuffs=143, + LASpellAwareness=144, + LAOffenseEnhancement=145, + LAManaEnhancement=146, + LAHealthEnhancement=147, + LAHealthRegen=148, + LAFindPathPC=149, + LAHoTT=150, + ActiveFavorCost=151, + CombatState=152, + svCorruption=153, + svPrismatic=154, + svChromatic=155, + Doubloons=156, + Orux=157, + Phosphenes=158, + Phosphites=159, + Fellowship=160, + Downtime=161, + DamageShieldMitigationBonus=162, + HeroicSTRBonus=163, + HeroicINTBonus=164, + HeroicWISBonus=165, + HeroicAGIBonus=166, + HeroicDEXBonus=167, + HeroicSTABonus=168, + HeroicCHABonus=169, + HealAmountBonus=170, + SpellDamageBonus=171, + ClairvoyanceBonus=172, + EnduranceRegenBonus=173, + Counters=174, + Faycites=175, + Chronobines=176, + Mercenary=177, + XTarget=178, + Haste=179, + MercenaryStance=180, + SkillCap=181, + GemTimer=182, + HaveExpansion=183, + PctAggro=184, + SecondaryPctAggro=185, + SecondaryAggroPlayer=186, + AggroLock=187, + }; + static enum CharacterMethods + { + Stand, + Sit, + Dismount, + }; + MQ2CharacterType():MQ2Type("character") + { + TypeMember(ID);//1, + TypeMember(Name);//2, + TypeMember(Level);//3, + TypeMember(Exp);//4, + TypeMember(Spawn);//5, + TypeMember(Dar);//6, + TypeMember(AAExp);//7, + TypeMember(AAPoints);//8, + TypeMember(CurrentHPs);//10, + TypeMember(MaxHPs);//11, + TypeMember(HPRegen);//12, + TypeMember(PctHPs);//13, + TypeMember(CurrentMana);//14, + TypeMember(MaxMana);//15, + TypeMember(ManaRegen);//16, + TypeMember(PctMana);//17, + TypeMember(Buff);//18, + TypeMember(Song);//19, + TypeMember(Book);//20, + TypeMember(Skill);//21, + TypeMember(Ability);//22, + TypeMember(Surname);//23, + TypeMember(Cash);//24, + TypeMember(CashBank);//25, + TypeMember(PlatinumShared);//26, + TypeMember(Grouped);//27, + TypeMember(HPBonus);//28, + TypeMember(ManaBonus);//29, + TypeMember(GukEarned);//30, + TypeMember(MMEarned);//31, + TypeMember(RujEarned);//32, + TypeMember(TakEarned);//33, + TypeMember(MirEarned);//34, + TypeMember(LDoNPoints);//35, + TypeMember(CurrentFavor);//36, + TypeMember(CareerFavor);//37, + TypeMember(Endurance);//38, + TypeMember(Inventory); + TypeMember(Bank); + TypeMember(Combat); + TypeMember(FreeInventory); + TypeMember(Gem); + TypeMember(SpellReady); + TypeMember(GroupLeaderExp); + TypeMember(RaidLeaderExp); + TypeMember(GroupLeaderPoints); + TypeMember(RaidLeaderPoints); + TypeMember(Drunk); + TypeMember(STR);//51, + TypeMember(STA);//52, + TypeMember(CHA);//53, + TypeMember(DEX);//54, + TypeMember(INT);//55, + TypeMember(AGI);//56, + TypeMember(WIS);//57, + TypeMember(svMagic);//58, + TypeMember(svFire);//59, + TypeMember(svCold);//60, + TypeMember(svPoison);//61, + TypeMember(svDisease);//62 + TypeMember(Hunger); + TypeMember(Thirst); + TypeMember(BaseSTR);//51, + TypeMember(BaseSTA);//52, + TypeMember(BaseCHA);//53, + TypeMember(BaseDEX);//54, + TypeMember(BaseINT);//55, + TypeMember(BaseAGI);//56, + TypeMember(BaseWIS);//57, + TypeMember(PracticePoints); + TypeMember(PctExp); + TypeMember(PctAAExp); + TypeMember(Moving); + TypeMember(AbilityReady); + TypeMember(PetBuff); + TypeMember(Platinum); + TypeMember(Gold); + TypeMember(Silver); + TypeMember(Copper); + TypeMember(PlatinumBank); + TypeMember(GoldBank); + TypeMember(SilverBank); + TypeMember(CopperBank); + TypeMember(PctGroupLeaderExp); + TypeMember(PctRaidLeaderExp); + TypeMember(Stunned); + TypeMember(RangedReady); + TypeMember(AltTimerReady); + TypeMember(MaxEndurance); + TypeMember(PctEndurance); + TypeMember(AltAbility); + TypeMember(AltAbilityReady); + TypeMember(AltAbilityTimer); + TypeMember(CombatAbility); + TypeMember(CombatAbilityTimer); + TypeMember(LargestFreeInventory); + TypeMember(TargetOfTarget); + TypeMember(RaidAssistTarget);//=100, + TypeMember(GroupAssistTarget);//=101, + TypeMember(RaidMarkNPC);//=102, + TypeMember(GroupMarkNPC);//=103 + TypeMember(CountBuffs); + TypeMember(LanguageSkill); //105 + TypeMember(EnduranceBonus); + TypeMember(CombatEffectsBonus); + TypeMember(ShieldingBonus); + TypeMember(SpellShieldBonus); + TypeMember(AvoidanceBonus); + TypeMember(AccuracyBonus); + TypeMember(StunResistBonus); + TypeMember(StrikeThroughBonus); + TypeMember(AttackBonus); + TypeMember(HPRegenBonus); + TypeMember(ManaRegenBonus); + TypeMember(DamageShieldBonus); + TypeMember(DoTShieldBonus); + TypeMember(AttackSpeed); //119 + TypeMember(GroupList); + TypeMember(AmIGroupLeader); //121 + TypeMember(CurrentEndurance); + TypeMember(EnduranceRegen); + TypeMember(FreeBuffSlots); //124 + TypeMember(CurrentWeight); + TypeMember(AAPointsSpent); + TypeMember(AAPointsTotal); + TypeMember(TributeActive); + TypeMember(CombatAbilityReady); + TypeMember(Running); + TypeMember(GroupSize); + TypeMember(TributeTimer); + TypeMember(RadiantCrystals); + TypeMember(EbonCrystals); + TypeMember(Shrouded); + TypeMember(AutoFire); + TypeMember(Language); + TypeMember(Aura); + TypeMember(LAMarkNPC); + TypeMember(LANPCHealth); + TypeMember(LADelegateMA); + TypeMember(LADelegateMarkNPC); + TypeMember(LAInspectBuffs); + TypeMember(LASpellAwareness); + TypeMember(LAOffenseEnhancement); + TypeMember(LAManaEnhancement); + TypeMember(LAHealthEnhancement); + TypeMember(LAHealthRegen); + TypeMember(LAFindPathPC); + TypeMember(LAHoTT); + TypeMember(ActiveFavorCost); + TypeMember(CombatState); + TypeMember(svCorruption); + TypeMember(svPrismatic); + TypeMember(svChromatic); + TypeMember(Doubloons); + TypeMember(Orux); + TypeMember(Phosphenes); + TypeMember(Phosphites); + TypeMember(Fellowship); + TypeMember(Downtime); + TypeMember(DamageShieldMitigationBonus); + TypeMember(HeroicSTRBonus); + TypeMember(HeroicINTBonus); + TypeMember(HeroicWISBonus); + TypeMember(HeroicAGIBonus); + TypeMember(HeroicDEXBonus); + TypeMember(HeroicSTABonus); + TypeMember(HeroicCHABonus); + TypeMember(HealAmountBonus); + TypeMember(SpellDamageBonus); + TypeMember(ClairvoyanceBonus); + TypeMember(EnduranceRegenBonus); + TypeMember(Counters); + TypeMember(Faycites); + TypeMember(Chronobines); + TypeMember(Mercenary); + TypeMember(XTarget); + TypeMember(Haste); + TypeMember(MercenaryStance); + TypeMember(SkillCap); // 181 + TypeMember(GemTimer); + TypeMember(HaveExpansion); + TypeMember(PctAggro); + TypeMember(SecondaryPctAggro); + TypeMember(SecondaryAggroPlayer); + TypeMember(AggroLock); + + TypeMethod(Stand); + TypeMethod(Sit); + TypeMethod(Dismount); + } + + ~MQ2CharacterType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + INHERITINDIRECT(pSpawnType,Temp.Ptr=((PCHARINFO)ObjectData.Ptr)->pSpawn,0); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (!VarPtr.Ptr) + return false; + strcpy(Destination,((PCHARINFO)VarPtr.Ptr)->Name); + return true; + } + void InitVariable(MQ2VARPTR &VarPtr) + { + VarPtr.Ptr=malloc(sizeof(CHARINFO)); + ZeroMemory(VarPtr.Ptr,sizeof(CHARINFO)); + } + void FreeVariable(MQ2VARPTR &VarPtr) + { + free(VarPtr.Ptr); + } + + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pCharacterType) + return false; + memcpy(VarPtr.Ptr,Source.Ptr,sizeof(CHARINFO)); + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + + +class MQ2SpellType : public MQ2Type +{ +public: + static enum SpellMembers + { + ID=1, + Name=2, + Level=3, + Skill=4, + Mana=5, + ResistAdj=6, + Range=7, + AERange=8, + PushBack=9, + CastTime=10, + FizzleTime=11, + MyCastTime=12, + RecoveryTime=13, + RecastTime=14, + Duration=15, + SpellType=16, + TargetType=17, + ResistType=18, + CastOnYou=19, + CastOnAnother=20, + WearOff=21, + CounterType=22, + CounterNumber=23, + Stacks=24, + StacksPet=25, + WillStack=26, + MyRange=27, + }; + static enum SpellMethods + { + }; + MQ2SpellType():MQ2Type("spell") + { + TypeMember(ID);//1, + TypeMember(Name);//2, + TypeMember(Level);//3, + TypeMember(Skill);//4, + TypeMember(Mana);//5, + TypeMember(ResistAdj);//6, + TypeMember(Range);//7, + TypeMember(AERange);//8, + TypeMember(PushBack);//9, + TypeMember(CastTime);//10, + TypeMember(FizzleTime);//11, + TypeMember(MyCastTime);//12, + TypeMember(RecoveryTime);//13, + TypeMember(RecastTime);//14, + TypeMember(Duration);//15, + TypeMember(SpellType);//16, + TypeMember(TargetType);//17, + TypeMember(ResistType);//18, + TypeMember(CastOnYou);//19, + TypeMember(CastOnAnother);//20, + TypeMember(WearOff);//21, + TypeMember(CounterType);//22, + TypeMember(CounterNumber);//23, + TypeMember(Stacks);//24, + TypeMember(StacksPet);//25, + TypeMember(WillStack);//26, + TypeMember(MyRange);//27 + } + + ~MQ2SpellType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (!VarPtr.Ptr) + return false; + strcpy(Destination,((PSPELL)VarPtr.Ptr)->Name); + return true; + } + void InitVariable(MQ2VARPTR &VarPtr) + { + VarPtr.Ptr=malloc(sizeof(SPELL)); + ZeroMemory(VarPtr.Ptr,sizeof(SPELL)); + } + void FreeVariable(MQ2VARPTR &VarPtr) + { + free(VarPtr.Ptr); + } + + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pSpellType) + return false; + memcpy(VarPtr.Ptr,Source.Ptr,sizeof(SPELL)); + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2BuffType : public MQ2Type +{ +public: + static enum BuffMembers + { + ID=1, + Level=2, + Spell=3, + Mod=4, + Duration=5, + Dar=6, + Counters=7 + }; + static enum BuffMethods + { + Remove=1, + }; + MQ2BuffType():MQ2Type("buff") + { + TypeMember(ID); + TypeMember(Level); + TypeMember(Spell); + TypeMember(Mod); + TypeMember(Duration); + TypeMember(Dar); + TypeMember(Counters); + + TypeMethod(Remove); + } + + ~MQ2BuffType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + INHERITINDIRECT(pSpellType,Temp.Ptr=GetSpellByID(((PSPELLBUFF)ObjectData.Ptr)->SpellID),0); + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (!VarPtr.Ptr) + return false; + if ((int)((PSPELLBUFF)VarPtr.Ptr)->SpellID>0) + { + if (PSPELL pSpell=GetSpellByID(((PSPELLBUFF)VarPtr.Ptr)->SpellID)) + { + strcpy(Destination,pSpell->Name); + return true; + } + } + return false; + } + void InitVariable(MQ2VARPTR &VarPtr) + { + VarPtr.Ptr=malloc(sizeof(SPELLBUFF)); + ZeroMemory(VarPtr.Ptr,sizeof(SPELLBUFF)); + } + void FreeVariable(MQ2VARPTR &VarPtr) + { + free(VarPtr.Ptr); + } + + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pBuffType) + return false; + memcpy(VarPtr.Ptr,Source.Ptr,sizeof(SPELLBUFF)); + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2ItemType : public MQ2Type +{ +public: + static enum ItemMembers + { + ID=1, + Name=2, + Lore=3, + NoDrop=4, + NoRent=5, + Magic=6, + Value=7, + Size=8, + Weight=9, + Stack=10, + Type=11, + Charges=12, + LDoNTheme=13, + DMGBonusType=14, + BuyPrice=15, + Haste=16, + Endurance=17, + Attack=18, + HPRegen=19, + ManaRegen=20, + DamShield=21, + WeightReduction=22, + SizeCapacity=23, + Combinable=24, + Skill=25, + Avoidance=26, + SpellShield=27, + StrikeThrough=28, + StunResist=29, + Shielding=30, + FocusID=31, + ProcRate=32, + Quality=33, + LDoNCost=34, + AugRestrictions=35, + AugType=36, + AugSlot1=37, + AugSlot2=38, + AugSlot3=39, + AugSlot4=40, + AugSlot5=41, + Damage=42, + Range=43, + DMGBonus=44, + RecommendedLevel=45, + RecommendedSkill=46, + Delay=47, + Light=48, + Level=49, + BaneDMG=50, + Proc=51, + SkillModValue=52, + InstrumentType=53, + InstrumentMod=54, + RequiredLevel=55, + BaneDMGType=56, + AC=57, + HP=58, + Mana=59, + STR=60, + STA=61, + AGI=62, + DEX=63, + CHA=64, + INT=65, + WIS=66, + svCold=67, + svFire=68, + svMagic=69, + svDisease=70, + svPoison=71, + Summoned=72, + Artifact=73, + PendingLore=74, + LoreText=75, + Items=76, + Item=77, + Container=78, + Stackable=79, + InvSlot=80, + SellPrice=81, + WornSlot=82, + WornSlots=83, + CastTime=84, + Spell=85, + EffectType=86, + Tribute=87, + Attuneable=88, + Timer=89, + ItemDelay=90, + TimerReady=91, + StackSize=92, + Stacks=93, + StackCount=94, + FreeStack=95, + MerchQuantity=96, + Classes=97, + Class=98, + Races=99, + Race=100, + Deities=101, + Deity=102, + Evolving=103, + svCorruption=104, + Power=105, + MaxPower=106, + Purity=107, + Accuracy=108, + CombatEffects=109, + DoTShielding=110, + HeroicSTR=111, + HeroicINT=112, + HeroicWIS=113, + HeroicAGI=114, + HeroicDEX=115, + HeroicSTA=116, + HeroicCHA=117, + HeroicSvMagic=118, + HeroicSvFire=119, + HeroicSvCold=120, + HeroicSvDisease=121, + HeroicSvPoison=122, + HeroicSvCorruption=123, + EnduranceRegen=124, + HealAmount=125, + Clairvoyance=126, + DamageShieldMitigation=127, + SpellDamage=128, + Augs=129, + Tradeskills=130, + }; + static enum ItemMethods + { + }; + MQ2ItemType():MQ2Type("item") + { + TypeMember(ID);//1, + TypeMember(Name);//2, + TypeMember(Lore);//3, + TypeMember(NoDrop);//4, + TypeMember(NoRent);//5, + TypeMember(Magic);//6, + TypeMember(Value);//7, + TypeMember(Size);//8, + TypeMember(Weight);//9, + TypeMember(Stack);//10, + TypeMember(Type);//11, + TypeMember(Charges);//12, + TypeMember(LDoNTheme);//13, + TypeMember(DMGBonusType);//14, + TypeMember(BuyPrice);//15, + TypeMember(Haste);//16, + TypeMember(Endurance);//17, + TypeMember(Attack);//18, + TypeMember(HPRegen);//19, + TypeMember(ManaRegen);//20, + TypeMember(DamShield);//21, + TypeMember(WeightReduction);//22, + TypeMember(SizeCapacity);//23, + TypeMember(Combinable);//24, + TypeMember(Skill);//25, + TypeMember(Avoidance);//26, + TypeMember(SpellShield);//27, + TypeMember(StrikeThrough);//28, + TypeMember(StunResist);//29, + TypeMember(Shielding);//30, + TypeMember(FocusID);//31, + TypeMember(ProcRate);//32, + TypeMember(Quality);//33, + TypeMember(LDoNCost);//34, + TypeMember(AugRestrictions);//35, + TypeMember(AugType);//36, + TypeMember(AugSlot1);//37, + TypeMember(AugSlot2);//38, + TypeMember(AugSlot3);//39, + TypeMember(AugSlot4);//40, + TypeMember(AugSlot5);//41, + TypeMember(Damage);//42, + TypeMember(Range);//43, + TypeMember(DMGBonus);//44, + TypeMember(RecommendedLevel);//45, + TypeMember(RecommendedSkill);//46, + TypeMember(Delay);//47, + TypeMember(Light);//48, + TypeMember(Level);//49, + TypeMember(BaneDMG);//50, + TypeMember(Proc);//51, + TypeMember(SkillModValue);//52, + TypeMember(InstrumentType);//53, + TypeMember(InstrumentMod);//54, + TypeMember(RequiredLevel);//55, + TypeMember(BaneDMGType);//56, + TypeMember(AC);//57, + TypeMember(HP);//58, + TypeMember(Mana);//59, + TypeMember(STR);//60, + TypeMember(STA);//61, + TypeMember(AGI);//62, + TypeMember(DEX);//63, + TypeMember(CHA);//64, + TypeMember(INT);//65, + TypeMember(WIS);//66, + TypeMember(svCold);//67, + TypeMember(svFire);//68, + TypeMember(svMagic);//69, + TypeMember(svDisease);//70, + TypeMember(svPoison);//71, + TypeMember(Summoned);//72, + TypeMember(Artifact);//73, + TypeMember(PendingLore);//74, + TypeMember(LoreText);//75, + TypeMember(Items); + TypeMember(Item); + TypeMember(Container); + TypeMember(Stackable); + TypeMember(InvSlot); + TypeMember(SellPrice); + TypeMember(WornSlot); + TypeMember(WornSlots); + TypeMember(CastTime); + TypeMember(Spell); + TypeMember(EffectType); + TypeMember(Tribute); + TypeMember(Attuneable); + TypeMember(Timer);//89, + TypeMember(ItemDelay); + TypeMember(TimerReady); + TypeMember(StackSize); + TypeMember(Stacks); + TypeMember(StackCount); + TypeMember(FreeStack); + TypeMember(MerchQuantity); + TypeMember(Classes); + TypeMember(Class); + TypeMember(Races); + TypeMember(Race); + TypeMember(Deities); + TypeMember(Deity); + TypeMember(Evolving); + TypeMember(svCorruption); + TypeMember(Power); + TypeMember(MaxPower); + TypeMember(Purity); + TypeMember(Accuracy); + TypeMember(CombatEffects); + TypeMember(DoTShielding); + TypeMember(HeroicSTR); + TypeMember(HeroicINT); + TypeMember(HeroicWIS); + TypeMember(HeroicAGI); + TypeMember(HeroicDEX); + TypeMember(HeroicSTA); + TypeMember(HeroicCHA); + TypeMember(HeroicSvMagic); + TypeMember(HeroicSvFire); + TypeMember(HeroicSvCold); + TypeMember(HeroicSvDisease); + TypeMember(HeroicSvPoison); + TypeMember(HeroicSvCorruption); + TypeMember(EnduranceRegen); + TypeMember(HealAmount); + TypeMember(Clairvoyance); + TypeMember(DamageShieldMitigation); + TypeMember(SpellDamage); + TypeMember(Augs); + TypeMember(Tradeskills); + } + + ~MQ2ItemType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (!VarPtr.Ptr) + return false; + strcpy(Destination,GetItemFromContents((PCONTENTS)VarPtr.Ptr)->Name); + return true; + } + void InitVariable(MQ2VARPTR &VarPtr) + { + VarPtr.Ptr=malloc(sizeof(CONTENTS)); + ZeroMemory(VarPtr.Ptr,sizeof(CONTENTS)); + } + void FreeVariable(MQ2VARPTR &VarPtr) + { + free(VarPtr.Ptr); + } + + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pItemType) + return false; + memcpy(VarPtr.Ptr,Source.Ptr,sizeof(CONTENTS)); + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + + +class MQ2SwitchType : public MQ2Type +{ +public: + static enum SwitchMembers + { + ID=1, + Distance=2, + X=3, + Y=4, + Z=5, + Heading=6, + DefaultX=7, + DefaultY=8, + DefaultZ=9, + DefaultHeading=10, + Open=11, + HeadingTo=12, + Name=13, + N=14, + W=15, + U=16, + DefaultN=17, + DefaultW=18, + DefaultU=19, + xLineOfSight=20, + }; + static enum SwitchMethods + { + Toggle=1, + }; + MQ2SwitchType():MQ2Type("switch") + { + TypeMember(ID);//1, + TypeMember(Distance);//2, + TypeMember(X);//3, + TypeMember(Y);//4, + TypeMember(Z);//5, + TypeMember(Heading);//6, + TypeMember(DefaultX);//7, + TypeMember(DefaultY);//8, + TypeMember(DefaultZ);//9, + TypeMember(DefaultHeading);//10, + TypeMember(Open);//11, + TypeMember(HeadingTo);//12, + TypeMember(Name);//13, + AddMember(xLineOfSight,"LineOfSight"); + } + + ~MQ2SwitchType() + { + TypeMethod(Toggle); + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (VarPtr.Ptr) + { + itoa(((PDOOR)VarPtr.Ptr)->ID,Destination,10); + return true; + } + return false; + } + void InitVariable(MQ2VARPTR &VarPtr) + { + VarPtr.Ptr=malloc(sizeof(DOOR)); + ZeroMemory(VarPtr.Ptr,sizeof(DOOR)); + } + void FreeVariable(MQ2VARPTR &VarPtr) + { + free(VarPtr.Ptr); + } + + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pSwitchType) + return false; + memcpy(VarPtr.Ptr,Source.Ptr,sizeof(DOOR)); + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2GroundType : public MQ2Type +{ +public: + static enum GroundMembers + { + ID=1, + Distance=2, + X=3, + Y=4, + Z=5, + Heading=6, + Name=7, + HeadingTo=8, + N=9, + W=10, + U=11, + xLineOfSight=12, + }; + static enum GroundMethods + { + Grab=1, + }; + MQ2GroundType():MQ2Type("ground") + { + TypeMember(ID);//1, + TypeMember(Distance);//2, + TypeMember(X);//3, + TypeMember(Y);//4, + TypeMember(Z);//5, + TypeMember(Heading);//6, + TypeMember(Name);//7, + TypeMember(HeadingTo); + AddMember(xLineOfSight,"LineOfSight"); + TypeMethod(Grab); + } + + ~MQ2GroundType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (VarPtr.Ptr) + { + itoa(((PGROUNDITEM)VarPtr.Ptr)->DropID,Destination,10); + return true; + } + return false; + } + void InitVariable(MQ2VARPTR &VarPtr) + { + VarPtr.Ptr=malloc(sizeof(GROUNDITEM)); + ZeroMemory(VarPtr.Ptr,sizeof(GROUNDITEM)); + } + void FreeVariable(MQ2VARPTR &VarPtr) + { + free(VarPtr.Ptr); + } + + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pGroundType) + return false; + memcpy(VarPtr.Ptr,Source.Ptr,sizeof(GROUNDITEM)); + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + + +class MQ2CorpseType : public MQ2Type +{ +public: + static enum CorpseMembers + { + Open=1, + Item=2, + Items=3, + }; + static enum CorpseMethods + { + }; + MQ2CorpseType():MQ2Type("corpse") + { + TypeMember(Open); + TypeMember(Item); + TypeMember(Items); + } + + ~MQ2CorpseType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (pActiveCorpse && pLootWnd) + { + strcpy(Destination,"TRUE"); + } + else + { + strcpy(Destination,"FALSE"); + } + return true; + } + + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2MerchantType : public MQ2Type +{ +public: + static enum MerchantMembers + { + Markup=1, + Item=2, + Items=3, + Open=4, + Full=5, + }; + static enum MerchantMethods + { + }; + MQ2MerchantType():MQ2Type("merchant") + { + TypeMember(Markup); + TypeMember(Item); + TypeMember(Items); + TypeMember(Open); + TypeMember(Full); + } + + ~MQ2MerchantType() + { + + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (pActiveMerchant && pMerchantWnd) + { + strcpy(Destination,"TRUE"); + } + else + { + strcpy(Destination,"FALSE"); + } + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2WindowType : public MQ2Type +{ +public: + static enum WindowMembers + { + Open=1, + Child=2, + VScrollMax=3, + VScrollPos=4, + VScrollPct=5, + HScrollMax=6, + HScrollPos=7, + HScrollPct=8, + Children=9, + Siblings=10, + Parent=11, + FirstChild=12, + Next=13, + Minimized=14, + X=15, + Y=16, + Height=17, + Width=18, + MouseOver=19, + BGColor=20, + Text=21, + Tooltip=22, + List=23, + Checked=24, + Style=25, + Enabled=26, + Highlighted=27, + Name=28, + ScreenID=29, + Type=30, + Items=31, + HisTradeReady=32, + MyTradeReady=33, + }; + static enum WindowMethods + { + LeftMouseDown=1, + LeftMouseUp=2, + LeftMouseHeldDown=3, + LeftMouseHeldUp=4, + RightMouseDown=5, + RightMouseUp=6, + RightMouseHeldDown=7, + RightMouseHeldUp=8, + ListSelect=9, + }; +#ifdef ISBOXER_COMPAT + MQ2WindowType():MQ2Type("eqwindow") +#else + MQ2WindowType():MQ2Type("window") +#endif + { + TypeMember(Open); + TypeMember(Child); + TypeMember(VScrollMax); + TypeMember(VScrollPos); + TypeMember(VScrollPct); + TypeMember(HScrollMax); + TypeMember(HScrollPos); + TypeMember(HScrollPct); + TypeMember(Children); + TypeMember(Siblings); + TypeMember(FirstChild); + TypeMember(Next); + TypeMember(Minimized);//14, + TypeMember(X);//15, + TypeMember(Y);//16, + TypeMember(Height);//17, + TypeMember(Width);//18, + TypeMember(MouseOver);//19, + TypeMember(BGColor);//20, + TypeMember(Text);//21, + TypeMember(Tooltip);//22, + TypeMember(List); + TypeMember(Checked); + TypeMember(Style); + TypeMember(Enabled); + TypeMember(Highlighted); + TypeMember(Name); + TypeMember(ScreenID); + TypeMember(Type); + TypeMember(Items); + TypeMember(HisTradeReady); + TypeMember(MyTradeReady); + + + TypeMethod(LeftMouseDown); + TypeMethod(LeftMouseUp); + TypeMethod(LeftMouseHeldDown); + TypeMethod(LeftMouseHeldUp); + TypeMethod(RightMouseDown); + TypeMethod(RightMouseUp); + TypeMethod(RightMouseHeldDown); + TypeMethod(RightMouseHeldUp); + TypeMethod(ListSelect); + + } + + ~MQ2WindowType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (VarPtr.Ptr && ((PCSIDLWND)VarPtr.Ptr)->dShow) + strcpy(Destination,"TRUE"); + else + strcpy(Destination,"FALSE"); + return true; + } + + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pWindowType) + return false; + VarPtr.Ptr=Source.Ptr; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +#ifndef ISXEQ +class MQ2MacroType : public MQ2Type +{ +public: + static enum MacroMembers + { + Name=1, + RunTime=2, + Paused=3, + Return=4, + Params=5, + Param=6, + }; + MQ2MacroType():MQ2Type("macro") + { + TypeMember(Name); + TypeMember(RunTime); + TypeMember(Paused); + TypeMember(Return); + TypeMember(Params); + TypeMember(Param); + } + + ~MQ2MacroType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (gRunning) + { + strcpy(Destination,gszMacroName); + return true; + } + return false; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; +#endif + +class MQ2ZoneType : public MQ2Type +{ +public: + static enum ZoneMembers + { + Name=1, + ShortName=2, + ID=3, + }; + MQ2ZoneType():MQ2Type("zone") + { + TypeMember(Name); + TypeMember(ShortName);//2, + TypeMember(ID);//3, + } + + ~MQ2ZoneType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + strcpy(Destination,&((PZONELIST)VarPtr.Int)->LongName[0]); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type==pZoneType) + { + VarPtr.Ptr=Source.Ptr; + return true; + } + if (Source.Type==(MQ2Type*)pCurrentZoneType) + { + VarPtr.Ptr=&((PWORLDDATA)pWorldData)->ZoneArray[GetCharInfo()->zoneId]; + return true; + } + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2CurrentZoneType : public MQ2Type +{ +public: + static enum CurrentZoneMembers + { + Name=1, + ShortName=2, + Type=3, + Gravity=4, + SkyType=5, + SafeY=6, + SafeX=7, + SafeZ=8, + MinClip=9, + MaxClip=10, + ID=11, + SafeN=12, + SafeW=13, + SafeU=14, + }; + MQ2CurrentZoneType():MQ2Type("currentzone") + { + TypeMember(Name); + TypeMember(ShortName);//2, + TypeMember(Type);//3, + TypeMember(Gravity);//4, + TypeMember(SkyType);//5, + TypeMember(SafeY);//6, + TypeMember(SafeX);//7, + TypeMember(SafeZ);//8, + TypeMember(MinClip);//9, + TypeMember(MaxClip);//10, + TypeMember(ID); + TypeMember(SafeN); + TypeMember(SafeW); + TypeMember(SafeU); + } + + ~MQ2CurrentZoneType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + strcpy(Destination,&((PZONEINFO)pZoneInfo)->LongName[0]); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pCurrentZoneType) + return false; + VarPtr.Ptr=Source.Ptr; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2MacroQuestType : public MQ2Type +{ +public: + static enum MacroQuestMembers + { + GameState=1, + LoginName=2, + Server=3, + LastCommand=4, + LastTell=5, + Error=6, + SyntaxError=7, + MQ2DataError=8, + Running=9, + MouseX=10, + MouseY=11, + BuildDate=12, + Ping=13, + ChatChannels=14, + ChatChannel=15, + ViewportX=16, + ViewportY=17, + ViewportXMax=18, + ViewportYMax=19, + ViewportXCenter=20, + ViewportYCenter=21, + LClickedObject=22, + }; + static enum MacroQuestMethods + { + }; + MQ2MacroQuestType():MQ2Type("macroquest") + { + TypeMember(GameState); + TypeMember(LoginName); + TypeMember(Server); + TypeMember(LastCommand); + TypeMember(LastTell); + TypeMember(Error); + TypeMember(SyntaxError); + TypeMember(MQ2DataError); + TypeMember(Running); + TypeMember(MouseX); + TypeMember(MouseY); + TypeMember(BuildDate); + TypeMember(Ping); + TypeMember(ChatChannels); + TypeMember(ChatChannel); + TypeMember(ViewportX); + TypeMember(ViewportY); + TypeMember(ViewportXMax); + TypeMember(ViewportYMax); + TypeMember(ViewportXCenter); + TypeMember(ViewportYCenter); + TypeMember(LClickedObject); + } + + ~MQ2MacroQuestType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + return false; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; +#ifndef ISXEQ +class MQ2MathType : public MQ2Type +{ +public: + static enum MathMembers + { + Abs=1, + Rand=2, + Calc=3, + Sin=4, + Cos=5, + Tan=6, + Asin=7, + Acos=8, + Atan=9, + Hex=10, + Dec=11, + Not=12, + Distance=13, + Sqrt=14, + }; + MQ2MathType():MQ2Type("math") + { + TypeMember(Abs); + TypeMember(Rand);//2, + TypeMember(Calc);//3, + TypeMember(Sin);//4, + TypeMember(Cos);//5, + TypeMember(Tan);//6, + TypeMember(Asin);//7, + TypeMember(Acos);//8, + TypeMember(Atan);//9, + TypeMember(Hex);//10, + TypeMember(Dec);//11, + TypeMember(Not);//12, + TypeMember(Distance); + TypeMember(Sqrt); + } + + ~MQ2MathType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + return false; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; +#endif +class MQ2RaceType : public MQ2Type +{ +public: + static enum RaceMembers + { + Name=1, + ID=2, + }; + MQ2RaceType():MQ2Type("race") + { + TypeMember(Name); + TypeMember(ID); + } + + ~MQ2RaceType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + PCHAR pDesc=pEverQuest->GetRaceDesc(VarPtr.DWord); + strcpy(Destination,pDesc); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + VarPtr.DWord=Source.DWord; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + VarPtr.DWord=atoi(Source); + return true; + } +}; + +class MQ2ClassType : public MQ2Type +{ +public: + static enum ClassMembers + { + Name=1, + ShortName=2, + ID=3, + PureCaster=4, + CanCast=5, + DruidType=6, + NecromancerType=7, + ShamanType=8, + ClericType=9, + PetClass=10, + HealerType=11, + }; + MQ2ClassType():MQ2Type("class") + { + TypeMember(Name); + TypeMember(ShortName); + TypeMember(ID); + TypeMember(PureCaster); + TypeMember(CanCast); + TypeMember(DruidType); + TypeMember(NecromancerType); + TypeMember(ShamanType); + TypeMember(ClericType); + TypeMember(PetClass); + TypeMember(HealerType); + } + + ~MQ2ClassType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + PCHAR pDesc=GetClassDesc(VarPtr.DWord); + strcpy(Destination,pDesc); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + VarPtr.DWord=Source.DWord; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + VarPtr.DWord=atoi(Source); + return true; + } +}; +class MQ2BodyType : public MQ2Type +{ +public: + static enum BodyMembers + { + Name=1, + ID=2 + }; + MQ2BodyType():MQ2Type("body") + { + TypeMember(Name); + TypeMember(ID); + } + + ~MQ2BodyType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + PCHAR pDesc=GetBodyTypeDesc(VarPtr.DWord); + strcpy(Destination,pDesc); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + VarPtr.DWord=Source.DWord; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + VarPtr.DWord=atoi(Source); + return true; + } +}; +class MQ2DeityType : public MQ2Type +{ +public: + static enum DeityMembers + { + Name=1, + Team=2, + ID=3 + }; + MQ2DeityType():MQ2Type("Deity") + { + TypeMember(Name); + TypeMember(Team); + TypeMember(ID); + } + + ~MQ2DeityType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + PCHAR pDesc=pEverQuest->GetDeityDesc(VarPtr.DWord); + strcpy(Destination,pDesc); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + VarPtr.DWord=Source.DWord; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + VarPtr.DWord=atoi(Source); + return true; + } +}; +#ifndef ISXEQ +class MQ2TimeType : public MQ2Type +{ +public: + static enum TimeMembers + { + Hour=1, + Minute=2, + Second=3, + DayOfWeek=4, + Day=5, + Month=6, + Year=7, + Time12=8, + Time24=9, + Date=10, + Night=11, + SecondsSinceMidnight=12, + }; + MQ2TimeType():MQ2Type("time") + { + TypeMember(Hour); + TypeMember(Minute); + TypeMember(Second); + TypeMember(DayOfWeek); + TypeMember(Day); + TypeMember(Month); + TypeMember(Year); + TypeMember(Time12); + TypeMember(Time24); + TypeMember(Date); + TypeMember(Night); + TypeMember(SecondsSinceMidnight); + } + + ~MQ2TimeType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + struct tm *Now=(struct tm*)VarPtr.Ptr; + sprintf(Destination,"%02d:%02d:%02d",Now->tm_hour,Now->tm_min, Now->tm_sec); + return true; + } + void InitVariable(MQ2VARPTR &VarPtr) + { + VarPtr.Ptr=malloc(sizeof(struct tm)); + ZeroMemory(VarPtr.Ptr,sizeof(struct tm)); + } + void FreeVariable(MQ2VARPTR &VarPtr) + { + free(VarPtr.Ptr); + } + +#ifndef MQ2PLUGIN + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pTimeType) + return false; + memcpy(VarPtr.Ptr,Source.Ptr,sizeof(struct tm)); + return true; + } +#else + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source); +#endif + + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; +#endif +#ifndef ISXEQ +class MQ2TypeType : public MQ2Type +{ +public: + static enum TypeMembers + { + Name=1, + TypeMember=2, + }; + MQ2TypeType():MQ2Type("type") + { + TypeMember(Name); + AddMember((DWORD)TypeMember,"Member"); + } + + ~MQ2TypeType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + strcpy(Destination,((MQ2Type*)VarPtr.Ptr)->GetName()); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + VarPtr.Ptr=Source.Type; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + if (VarPtr.Ptr=FindMQ2DataType(Source)) + return true; + return false; + } +}; +#endif +class MQ2HeadingType : public MQ2Type +{ +public: + static enum HeadingMembers + { + Name=1, + ShortName=2, + Degrees=3, + Clock=4, + DegreesCCW=5, + }; + static enum HeadingMethods + { + }; + MQ2HeadingType():MQ2Type("heading") + { + TypeMember(Name); + TypeMember(ShortName); + TypeMember(Degrees); + TypeMember(Clock); + TypeMember(DegreesCCW); + } + + ~MQ2HeadingType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + strcpy(Destination,szHeadingNormalShort[(INT)((360.0f-VarPtr.Float)/ 22.5f + 0.5f)%16]); + return true; + } +#ifndef MQ2PLUGIN + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pHeadingType && Source.Type!=pFloatType) + VarPtr.Float=(FLOAT)Source.DWord; + else + VarPtr.Float=Source.Float; + return true; + } +#else + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source); +#endif + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + VarPtr.Float=(FLOAT)atof(Source); + return true; + } +}; + +class MQ2InvSlotType : public MQ2Type +{ +public: + static enum InvSlotMembers + { + Pack=1, + Slot=2, + ID=3, + Name=4, + Item=5, + }; + static enum InvSlotMethods + { + }; + MQ2InvSlotType():MQ2Type("invslot") + { + TypeMember(Pack); + TypeMember(Slot); + TypeMember(ID); + TypeMember(Name); + TypeMember(Item); + } + + ~MQ2InvSlotType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + itoa(VarPtr.Int,Destination,10); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + VarPtr.DWord=Source.DWord; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + if (IsNumber(Source)) + { + VarPtr.DWord=atoi(Source); + return true; + } + else + { + CHAR Temp[MAX_STRING]={0}; + strlwr(strcpy(Temp,Source)); + VarPtr.DWord=ItemSlotMap[Temp]; + if (VarPtr.DWord || !stricmp(Temp,"charm")) + { + return true; + } + } + return false; + } +}; + +#ifndef ISXEQ +class MQ2PluginType : public MQ2Type +{ +public: + static enum PluginMembers + { + Name=1, + Version=2, + }; + MQ2PluginType():MQ2Type("plugin") + { + TypeMember(Name); + TypeMember(Version); + } + + ~MQ2PluginType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (VarPtr.Ptr) + { + strcpy(Destination,((PMQPLUGIN)VarPtr.Ptr)->szFilename); + return true; + } + return false; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pPluginType) + return false; + VarPtr.Ptr=Source.Ptr; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; +#endif +class MQ2BenchmarkType : public MQ2Type +{ +public: + static enum BenchmarkMembers + { + Name=1, + ID=2, + Iterations=3, + TimeSpent=4, + AvgTimeSpent=5, + }; + MQ2BenchmarkType():MQ2Type("benchmark") + { + TypeMember(Name); + TypeMember(ID); + TypeMember(Iterations); + TypeMember(TimeSpent); + TypeMember(AvgTimeSpent); + } + + ~MQ2BenchmarkType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + return false; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + VarPtr.DWord=Source.DWord; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + if (IsNumber(Source)) + { + VarPtr.DWord=atoi(Source); + return true; + } + return false; + } +}; + +class MQ2SkillType : public MQ2Type +{ +public: + static enum SkillMembers + { + Name=1, + ID=2, + ReuseTime=3, + MinLevel=4, + SkillCap=5, + AltTimer=6, + Activated=7, + }; + static enum SkillMethods + { + }; + MQ2SkillType():MQ2Type("skill") + { + TypeMember(Name); + TypeMember(ID); + TypeMember(ReuseTime); + TypeMember(MinLevel); + TypeMember(SkillCap); + TypeMember(AltTimer); + TypeMember(Activated); + } + + ~MQ2SkillType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (!VarPtr.Ptr) + return false; + if (PSKILL pSkill=*(PSKILL*)VarPtr.Ptr) + if (PCHAR pName=pStringTable->getString(pSkill->nName,0)) + { + strcpy(Destination,pName); + return true; + } + return false; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pSkillType) + return false; + VarPtr.Ptr=Source.Ptr; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2AltAbilityType : public MQ2Type +{ +public: + static enum AltAbilityMembers + { + Name=1, + ShortName=2, + Description=3, + MinLevel=4, + Cost=5, + RequiresAbility=6, + RequiresAbilityPoints=7, + MaxRank=8, + AARankRequired=9, + Spell=10, + Type=11, + ReuseTime=12, + ID=13, + MyReuseTime=14, + }; + static enum AltAbilityMethods + { + }; + MQ2AltAbilityType():MQ2Type("altability") + { + TypeMember(Name); + TypeMember(ShortName); + TypeMember(Description); + TypeMember(MinLevel); + TypeMember(Cost); + TypeMember(RequiresAbility); + TypeMember(RequiresAbilityPoints); + TypeMember(MaxRank); + TypeMember(AARankRequired); + TypeMember(Spell); + TypeMember(Type); + TypeMember(ReuseTime); + TypeMember(ID); + TypeMember(MyReuseTime); + } + + ~MQ2AltAbilityType() + { + } + bool MQ2AltAbilityType::ToString(MQ2VARPTR VarPtr, PCHAR Destination); + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pAltAbilityType) + return false; + VarPtr.Ptr=Source.Ptr; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2TimerType : public MQ2Type +{ +public: + static enum TimerMembers + { + Value=1, + OriginalValue=2, + }; + static enum TimerMethods + { + Reset=1, + Expire=2, + Set=3, + }; + MQ2TimerType():MQ2Type("timer") + { + TypeMember(Value); + TypeMember(OriginalValue); + + TypeMethod(Reset); + TypeMethod(Expire); + TypeMethod(Set); + } + + ~MQ2TimerType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + PMQTIMER pTimer=(PMQTIMER)VarPtr.Ptr; + itoa(pTimer->Current,Destination,10); + return true; + } + void InitVariable(MQ2VARPTR &VarPtr) + { + PMQTIMER pVar = (PMQTIMER)malloc(sizeof(MQTIMER)); + pVar->szName[0]=0; + pVar->Current = 0; + pVar->Original= 0; + pVar->pNext = gTimer; + pVar->pPrev=0; + if (gTimer) + gTimer->pPrev=pVar; + gTimer=pVar; + VarPtr.Ptr=pVar; + } + void FreeVariable(MQ2VARPTR &VarPtr) + { + PMQTIMER pVar=(PMQTIMER)VarPtr.Ptr; + if (pVar->pPrev) + pVar->pPrev->pNext=pVar->pNext; + else + gTimer=pVar->pNext; + if (pVar->pNext) + pVar->pNext->pPrev=pVar->pPrev; + free(VarPtr.Ptr); + } +#ifndef MQ2PLUGIN + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + PMQTIMER pTimer=(PMQTIMER)VarPtr.Ptr; + if (Source.Type==pFloatType) + { + pTimer->Current=(DWORD)Source.Float; + pTimer->Original=pTimer->Current; + } + else + { + pTimer->Current=Source.DWord; + pTimer->Original=pTimer->Current; + } + return true; + } +#else + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source); +#endif + + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + PMQTIMER pTimer=(PMQTIMER)VarPtr.Ptr; + + + FLOAT VarValue = (FLOAT)atof(Source); + switch (Source[strlen(Source)-1]) + { + case 'm': + case 'M': + VarValue *= 60; + case 's': + case 'S': + VarValue *= 10; + } + pTimer->Current = (DWORD)VarValue; + pTimer->Original = pTimer->Current; + return true; + } +}; +#ifndef ISXEQ +class MQ2ArrayType : public MQ2Type +{ +public: + static enum ArrayMembers + { + Dimensions=1, + Size=2, + }; + MQ2ArrayType():MQ2Type("array") + { + TypeMember(Dimensions); + TypeMember(Size); + } + + ~MQ2ArrayType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + return false; + } + + void InitVariable(MQ2VARPTR &VarPtr) + { + } + void FreeVariable(MQ2VARPTR &VarPtr) + { + CDataArray *pArray=(CDataArray*)VarPtr.Ptr; + delete pArray; + } + + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; +#endif + +class MQ2GroupType : public MQ2Type +{ +public: + static enum GroupMembers + { + xMember=1, + Members=2, + Leader=3, + GroupSize=4, + MainTank=5, + MainAssist=6, + Puller=7, + }; + static enum GroupMethods + { + }; + MQ2GroupType():MQ2Type("group") + { + AddMember(xMember,"Member"); + TypeMember(Members); + TypeMember(Leader); + TypeMember(GroupSize); + TypeMember(MainTank); + TypeMember(MainAssist); + TypeMember(Puller); + } + + ~MQ2GroupType() + { + } + + bool GETMEMBER(); + //DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination); + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2GroupMemberType : public MQ2Type +{ +public: + static enum GroupMemberMembers + { + Name=1, + Leader=2, + Spawn=3, + Level=4, + MainTank=5, + MainAssist=6, + Puller=7, + Mercenary=8, + PctAggro=9, + }; + static enum GroupMemberMethods + { + }; + MQ2GroupMemberType():MQ2Type("groupmember") + { + TypeMember(Name); + TypeMember(Leader); + TypeMember(Spawn); + TypeMember(Level); + TypeMember(MainTank); + TypeMember(MainAssist); + TypeMember(Puller); + TypeMember(Mercenary); + TypeMember(PctAggro); + } + + ~MQ2GroupMemberType() + { + } + + bool GETMEMBER(); + //DECLAREGETMETHOD(); + + INHERITINDIRECT(pSpawnType,Temp.Ptr=GetGroupMember(ObjectData.DWord),0); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination); + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pGroupMemberType) + return false; + VarPtr.Ptr=Source.Ptr; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2RaidType : public MQ2Type +{ +public: + static enum RaidMembers + { + xMember=1, + Members=2, + Target=3, + Leader=4, + TotalLevels=5, + AverageLevel=6, + LootType=7, + Looter=8, + Looters=9, + Locked=10, + Invited=11, + MainAssist=12, + }; + static enum RaidMethods + { + }; + MQ2RaidType():MQ2Type("raid") + { + AddMember(xMember,"Member"); + TypeMember(Members); + TypeMember(Target); + TypeMember(Leader); + TypeMember(TotalLevels); + TypeMember(AverageLevel); + TypeMember(LootType); + TypeMember(Looter); + TypeMember(Looters); + TypeMember(Locked); + TypeMember(Invited); + TypeMember(MainAssist); + } + + ~MQ2RaidType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + INHERITINDIRECT(pSpawnType,Temp.Ptr=GetRaidMember(ObjectData.DWord-1),0); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + return false; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2RaidMemberType : public MQ2Type +{ +public: + static enum RaidMemberMembers + { + Name=1, + Group=3, + GroupLeader=4, + RaidLeader=5, + Spawn=6, + Looter=7, + Class=8, + Level=9, + }; + static enum RaidMemberMethods + { + }; + MQ2RaidMemberType():MQ2Type("raidmember") + { + TypeMember(Name); + TypeMember(Group); + TypeMember(GroupLeader); + TypeMember(RaidLeader); + TypeMember(Spawn); + TypeMember(Looter); + TypeMember(Class); + TypeMember(Level); + } + + ~MQ2RaidMemberType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + DWORD nRaidMember=VarPtr.DWord-1; + if (VarPtr.DWord>=72) + return false; + if (!pRaid->RaidMemberUsed[nRaidMember]) + return false; + PEQRAIDMEMBER pRaidMember=&pRaid->RaidMember[nRaidMember]; + strcpy(Destination,pRaidMember->Name); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type!=pRaidMemberType) + return false; + VarPtr.Ptr=Source.Ptr; + return true; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2EvolvingItemType : public MQ2Type +{ +public: + static enum EvolvingItemMembers + { + ExpPct=1, + ExpOn=2, + Level=3, + MaxLevel=4, + }; + MQ2EvolvingItemType():MQ2Type("Evolving") + { + TypeMember(ExpPct); + TypeMember(ExpOn); + TypeMember(Level); + TypeMember(MaxLevel); + } + + ~MQ2EvolvingItemType() + { + } + + bool GETMEMBER(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if(VarPtr.Ptr && ((PCONTENTS)VarPtr.Ptr)->IsEvolvingItem) + strcpy(Destination,"TRUE"); + else + strcpy(Destination,"FALSE"); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2DynamicZoneType : public MQ2Type +{ +public: + static enum DynamicZoneMembers + { + Name=1, + Members=2, + MaxMembers=3, + xMember=4, + Leader=5, + }; + MQ2DynamicZoneType():MQ2Type("dynamiczone") + { + TypeMember(Name); + TypeMember(Members); + TypeMember(MaxMembers); + AddMember(xMember,"Member"); + TypeMember(Leader); + } + ~MQ2DynamicZoneType() + { + } + bool GETMEMBER(); + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if(pDZMember) + { + strcpy(Destination,pDynamicZone->ExpeditionName); + return true; + } + return false; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2DZMemberType : public MQ2Type +{ +public: + static enum DZMemberTypeMembers + { + Name=1, + Status=2, + }; + MQ2DZMemberType():MQ2Type("dzmember") + { + TypeMember(Name); + TypeMember(Status); + } + ~MQ2DZMemberType() + { + } + bool GETMEMBER(); + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + strcpy(Destination,((PDZMEMBER)VarPtr.Ptr)->Name); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2FellowshipType : public MQ2Type +{ +public: + static enum FellowshipTypeMembers + { + ID=1, + Leader=2, + MotD=3, + Members=4, + xMember=5, + CampfireDuration=6, + CampfireY=7, + CampfireX=8, + CampfireZ=9, + CampfireZone=10, + Campfire=11, + }; + MQ2FellowshipType():MQ2Type("fellowship") + { + TypeMember(ID); + TypeMember(Leader); + TypeMember(MotD); + TypeMember(Members); + AddMember(xMember,"Member"); + TypeMember(CampfireDuration); + TypeMember(CampfireY); + TypeMember(CampfireX); + TypeMember(CampfireZ); + TypeMember(CampfireZone); + TypeMember(Campfire); + } + ~MQ2FellowshipType() + { + } + bool GETMEMBER(); + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if(VarPtr.Ptr && ((PFELLOWSHIPINFO)VarPtr.Ptr)->FellowshipID) + strcpy(Destination,"TRUE"); + else + strcpy(Destination,"FALSE"); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2FellowshipMemberType : public MQ2Type +{ +public: + static enum FMTypeMembers + { + Zone=1, + Level=2, + Class=3, + LastOn=4, + Name=5, + }; + MQ2FellowshipMemberType():MQ2Type("fellowshipmember") + { + TypeMember(Zone); + TypeMember(Level); + TypeMember(Class); + TypeMember(LastOn); + TypeMember(Name); + } + ~MQ2FellowshipMemberType() + { + } + bool GETMEMBER(); + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + strcpy(Destination,((PFELLOWSHIPMEMBER)VarPtr.Ptr)->Name); + return true; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2FriendsType : public MQ2Type +{ +public: + static enum FriendsMembers + { + xFriend=1 + }; + static enum FriendsMethods + { + }; + + MQ2FriendsType():MQ2Type("friend") + { + AddMember(xFriend,"Friend"); + } + + ~MQ2FriendsType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + // return the number of friends here... + if(((PEVERQUEST)pEverQuest)->ChatService) { + class CChatService *pChat=(class CChatService *) ((PEVERQUEST)pEverQuest)->ChatService; + sprintf(Destination, "%d", pChat->GetNumberOfFriends()); + return true; + } + return false; + } + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; + +class MQ2TargetType : public MQ2Type +{ +public: + static enum TargetMembers + { + Buff = 1, + BuffCount = 2, + BuffDuration = 3, + PctAggro = 4, + SecondaryPctAggro = 5, + SecondaryAggroPlayer = 6, + }; + +#ifdef ISBOXER_COMPAT + MQ2TargetType():MQ2Type("eqtarget") +#else + MQ2TargetType():MQ2Type("target") +#endif + { + TypeMember(Buff); + TypeMember(BuffCount); + TypeMember(BuffDuration); + TypeMember(PctAggro); + TypeMember(SecondaryPctAggro); + TypeMember(SecondaryAggroPlayer); + } + + ~MQ2TargetType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + INHERITDIRECT(pSpawnType); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if (!VarPtr.Ptr) + return false; + strcpy(Destination,((PSPAWNINFO)VarPtr.Ptr)->Name); + return true; + } + void InitVariable(MQ2VARPTR &VarPtr) + { + VarPtr.Ptr=malloc(sizeof(SPAWNINFO)); + ZeroMemory(VarPtr.Ptr,sizeof(SPAWNINFO)); + } + void FreeVariable(MQ2VARPTR &VarPtr) + { + free(VarPtr.Ptr); + } + + virtual bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + if (Source.Type==pSpawnType) + { + memcpy(VarPtr.Ptr,Source.Ptr,sizeof(SPAWNINFO)); + return true; + } + else + { + if (PSPAWNINFO pOther=(PSPAWNINFO)GetSpawnByID(Source.DWord)) + { + memcpy(VarPtr.Ptr,pOther,sizeof(SPAWNINFO)); + return true; + } + } + return false; + } + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + if (PSPAWNINFO pOther=(PSPAWNINFO)GetSpawnByID(atoi(Source))) + { + memcpy(VarPtr.Ptr,pOther,sizeof(SPAWNINFO)); + return true; + } + return false; + } +}; + +class MQ2XTargetType : public MQ2Type +{ +public: + static enum xTargetMembers + { + Type = 1, + ID = 2, + Name = 3, + PctAggro = 4, + }; + + MQ2XTargetType():MQ2Type("xtarget") + { + TypeMember(Type); + TypeMember(ID); + TypeMember(Name); + TypeMember(PctAggro); + } + + ~MQ2XTargetType() + { + } + + bool GETMEMBER(); + DECLAREGETMETHOD(); + + bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + if(GetCharInfo() && GetCharInfo()->pXTargetMgr) + { + XTARGETDATA xtd = GetCharInfo()->pXTargetMgr->pXTargetArray->pXTargetData[VarPtr.DWord]; + strcpy(Destination, xtd.Name); + } + else + strcpy(Destination, "NULL"); + return true; + } + + bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source) + { + return false; + } + + bool FromString(MQ2VARPTR &VarPtr, PCHAR Source) + { + return false; + } +}; diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2DataVars.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2DataVars.cpp new file mode 100644 index 0000000000..ea5d56a267 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2DataVars.cpp @@ -0,0 +1,541 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ +#ifndef ISXEQ + +#if !defined(CINTERFACE) +//#error /DCINTERFACE +#endif + +#define DBG_SPEW + + +#include "MQ2Main.h" + + + + + + +map VariableMap; + +inline VOID DeleteMQ2DataVariable(PDATAVAR pVar) +{ + if (pVar->ppHead==&pMacroVariables || pVar->ppHead==&pGlobalVariables) + VariableMap[pVar->szName]=0; + if (pVar->pNext) + pVar->pNext->pPrev=pVar->pPrev; + if (pVar->pPrev) + pVar->pPrev->pNext=pVar->pNext; + else + *pVar->ppHead=pVar->pNext; + pVar->Var.Type->FreeVariable(pVar->Var.VarPtr); + delete pVar; +} + +inline PDATAVAR FindMQ2DataVariable(PCHAR Name) +{ + PDATAVAR pFind=VariableMap[Name]; + if (pFind) + return pFind; + // local? + if (gMacroStack) + { + PDATAVAR pVar=gMacroStack->Parameters; + while(pVar) + { + if (!strcmp(pVar->szName,Name)) + return pVar; + pVar=pVar->pNext; + } + pVar=gMacroStack->LocalVariables; + while(pVar) + { + if (!strcmp(pVar->szName,Name)) + return pVar; + pVar=pVar->pNext; + } + } + return 0; +} + +BOOL AddMQ2DataEventVariable(PCHAR Name, PCHAR Index, MQ2Type *pType, PDATAVAR *ppHead, PCHAR Default) +{ + if (!ppHead || !Name[0]) + return FALSE; + if (!Index) + Index=""; + if (!Default) + Default=""; + if (FindMQ2Data(Name) || FindMQ2DataType(Name)) + return FALSE; // name in use + if (!pType) + return FALSE; + + // create variable + PDATAVAR pVar = new DATAVAR; + pVar->ppHead=ppHead; + pVar->pNext=*ppHead; + *ppHead=pVar; + pVar->pPrev=0; + if (pVar->pNext) + pVar->pNext->pPrev=pVar; + strcpy(pVar->szName,Name); + if (Index[0]) + { + CDataArray *pArray=new CDataArray(pType,Index,Default); + pVar->Var.Ptr=pArray; + + } + else + { + pVar->Var.Type=pType; + pType->InitVariable(pVar->Var.VarPtr); + pType->FromString(pVar->Var.VarPtr,Default); + } + if (pVar->ppHead==&pMacroVariables || pVar->ppHead==&pGlobalVariables) + { + VariableMap[Name]=pVar; + } + return TRUE; +} + + +BOOL AddMQ2DataVariableBy(PCHAR Name, PCHAR Index, MQ2Type *pType, PDATAVAR *ppHead, PCHAR Default, BOOL ByData) +{ + if (!ppHead || !Name[0]) + return FALSE; + if (!Index) + Index=""; + if (!Default) + Default=""; + if (FindMQ2DataVariable(Name) || FindMQ2Data(Name) || FindMQ2DataType(Name)) + return FALSE; // name in use + if (!pType) + return FALSE; + + // create variable + PDATAVAR pVar = new DATAVAR; + pVar->ppHead=ppHead; + pVar->pNext=*ppHead; + *ppHead=pVar; + pVar->pPrev=0; + if (pVar->pNext) + pVar->pNext->pPrev=pVar; + strcpy(pVar->szName,Name); + if (Index[0]) + { + CDataArray *pArray=new CDataArray(pType,Index,Default); + pVar->Var.Ptr=pArray; + pVar->Var.Type=pArrayType; + } + else + { + pVar->Var.Type=pType; + pType->InitVariable(pVar->Var.VarPtr); + if (ByData) + pType->FromData(pVar->Var.VarPtr,*(MQ2TYPEVAR *)Default); + else + pType->FromString(pVar->Var.VarPtr,Default); + } + if (!(gMacroStack && (ppHead==&gMacroStack->LocalVariables || ppHead==&gMacroStack->Parameters))) + { + VariableMap[Name]=pVar; + } + return TRUE; +} + +BOOL AddMQ2DataVariable(PCHAR Name, PCHAR Index, MQ2Type *pType, PDATAVAR *ppHead, PCHAR Default) +{ + return AddMQ2DataVariableBy(Name, Index, pType, ppHead, Default, 0); +} + + +BOOL AddMQ2DataVariableFromData(PCHAR Name, PCHAR Index, MQ2Type *pType, PDATAVAR *ppHead, MQ2TYPEVAR Default) +{ + return AddMQ2DataVariableBy(Name, Index, pType, ppHead, (PCHAR)&Default, 1); +} + + + +PDATAVAR *FindVariableScope(PCHAR Name) +{ + if (!stricmp(Name,"global")) + return &pGlobalVariables; + if (!stricmp(Name,"outer")) + return &pMacroVariables; + if (gMacroStack && !stricmp(Name,"local")) + return &gMacroStack->LocalVariables; + return 0; +} + +BOOL DeleteMQ2DataVariable(PCHAR Name) +{ + if (PDATAVAR pVar=FindMQ2DataVariable(Name)) + { + DeleteMQ2DataVariable(pVar); + return TRUE; + } + return FALSE; +} + +VOID ClearMQ2DataVariables(PDATAVAR *ppHead) +{ + PDATAVAR pVar=*ppHead; + while(pVar) + { + PDATAVAR pNext=pVar->pNext; + DeleteMQ2DataVariable(pVar); + pVar=pNext; + } + *ppHead=0; +} + +VOID NewDeclareVar(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /declare [type] [global|outer|local] [default value]"); + return; + } + PDATAVAR *pScope=0; + MQ2Type *pType=0; + CHAR szIndex[MAX_STRING]={0}; + CHAR szName[MAX_STRING]={0}; + GetArg(szName,szLine,1); + CHAR Arg[MAX_STRING]={0}; + GetArg(Arg,szLine,2); + PCHAR pDefault; + if (pScope=FindVariableScope(Arg)) + { + // scope comes AFTER type, so next must be default + pDefault=GetNextArg(szLine,2); + } + else if (pType=FindMQ2DataType(Arg)) + { + // next is either scope or default + GetArg(Arg,szLine,3); + if (pScope=FindVariableScope(Arg)) + { + // next is default + pDefault=GetNextArg(szLine,3); + } + else + { + // this is default + pDefault=GetNextArg(szLine,2); + } + } + else + { + // this is default + pDefault=GetNextArg(szLine); + } + if (!pScope) + { + if (gMacroStack) + pScope=&gMacroStack->LocalVariables; + else + { + MacroError("/declare '%s' failed. No macro in execution and no variable scope given",szName); + return; + } + } + if (!pType) + pType=pStringType; + if (pType==pArrayType) + { + MacroError("/declare array failed. To declare an array use: /declare name[size] "); + MacroError("Example: /declare MyStringArray[25] string local ARRAY-UNDEFINED-ELEMENT"); + return; + } + + if (PCHAR pBracket=strchr(szName,'[')) + { + *pBracket=0; + strcpy(szIndex,&pBracket[1]); + szIndex[strlen(szIndex)-1]=0; + } + if (pType==pTimerType && szIndex[0]) + { + MacroError("Cannot /declare an array of timers"); + return; + } + + if (!AddMQ2DataVariable(szName,szIndex,pType,pScope,pDefault)) + { + MacroError("/declare '%s' failed. Name already in use.",szName); + } + else + { + if (pType==pTimerType) + { + PMQTIMER pTimer=(PMQTIMER)((*pScope)->Var.Ptr); + strcpy(pTimer->szName,szName); + } + } +} + +VOID NewDeleteVarCmd(PSPAWNINFO pChar, PCHAR szLine) +{ + if (szLine[0]==0) { + SyntaxError("Usage: /deletevar "); + } + else + { + // destroy old variable + if (!DeleteMQ2DataVariable(szLine)) + { + if (!strnicmp(szLine,"* global",8)) + { + ClearMQ2DataVariables(&pGlobalVariables); + } + else + MacroError("Variable '%s' does not exist",szLine); + } + } +} + +VOID NewVarset(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /varset "); + return; + } + CHAR szName[MAX_STRING]={0}; + GetArg(szName,szLine,1); + PCHAR szRest=GetNextArg(szLine); + CHAR szIndex[MAX_STRING]={0}; + if (PCHAR pBracket=strchr(szName,'[')) + { + *pBracket=0; + strcpy(szIndex,&pBracket[1]); + } + PDATAVAR pVar=FindMQ2DataVariable(szName); + if (!pVar) + { + MacroError("/varset failed, variable '%s' not found",szName); + return; + } + if (szIndex[0]) + { + if (pVar->Var.Type!=pArrayType) + { + MacroError("/varset '%s' failed, array form on non-array",szName); + return; + } + CDataArray *pArray=(CDataArray*)pVar->Var.Ptr; + int N=pArray->GetElement(szIndex); + if (N==-1) + { + MacroError("/varset '%s[%d]' failed, out of bounds on array",szName,N); + return; + } + if (!pArray->pType->FromString(pArray->pData[N],szRest)) + { + MacroError("/varset '%s[%d]' failed, array element type rejected new value",szName,N); + } + } + else + { + if (!pVar->Var.Type->FromString(pVar->Var.VarPtr,szRest)) + { + MacroError("/varset '%s' failed, variable type rejected new value",szName); + } + } +} + +VOID NewVarcalc(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /varcalc "); + return; + } + CHAR szName[MAX_STRING]={0}; + GetArg(szName,szLine,1); + PCHAR szRest=GetNextArg(szLine); + if (!szRest || !szRest[0]) + { + SyntaxError("Usage: /varcalc "); + return; + } + + DOUBLE Result; + if (!Calculate(szRest,Result)) + { + MacroError("/varcalc '%s' failed. Could not calculate '%s'",szName,szRest); + return; + } + sprintf(szRest,"%f",Result); + + + CHAR szIndex[MAX_STRING]={0}; + if (PCHAR pBracket=strchr(szName,'[')) + { + *pBracket=0; + strcpy(szIndex,&pBracket[1]); + } + PDATAVAR pVar=FindMQ2DataVariable(szName); + if (!pVar) + { + MacroError("/varcalc failed, variable '%s' not found",szName); + return; + } + if (szIndex[0]) + { + if (pVar->Var.Type!=pArrayType) + { + MacroError("/varcalc '%s' failed, array form on non-array",szName); + return; + } + CDataArray *pArray=(CDataArray*)pVar->Var.Ptr; + int N=pArray->GetElement(szIndex); + if (N==-1) + { + MacroError("/varcalc '%s[%d]' failed, out of bounds on array",szName,N); + return; + } + if (!pArray->pType->FromString(pArray->pData[N],szRest)) + { + MacroError("/varcalc '%s[%d]' failed, array element type rejected new value",szName,N); + } + } + else + { + if (!pVar->Var.Type->FromString(pVar->Var.VarPtr,szRest)) + { + MacroError("/varcalc '%s' failed, variable type rejected new value",szName); + } + } +} + +VOID NewVardata(PSPAWNINFO pChar, PCHAR szLine) +{ + if (!szLine[0]) + { + SyntaxError("Usage: /vardata "); + return; + } + CHAR szName[MAX_STRING]={0}; + GetArg(szName,szLine,1); + PCHAR szRest=GetNextArg(szLine); + if (!szRest || !szRest[0]) + { + SyntaxError("Usage: /vardata "); + return; + } + CHAR szIndex[MAX_STRING]={0}; + if (PCHAR pBracket=strchr(szName,'[')) + { + *pBracket=0; + strcpy(szIndex,&pBracket[1]); + } + PDATAVAR pVar=FindMQ2DataVariable(szName); + if (!pVar) + { + MacroError("/vardata '%s' failed, variable not found",szName); + return; + } + MQ2TYPEVAR Result; + if (!ParseMQ2DataPortion(szRest,Result)) + { + MacroError("/vardata '%s' failed, MQ2Data portion '%s' unparsable",szName,szRest); + return; + } + + if (szIndex[0]) + { + if (pVar->Var.Type!=pArrayType) + { + MacroError("/vardata '%s' failed, array form on non-array",szName); + return; + } + CDataArray *pArray=(CDataArray*)pVar->Var.Ptr; + int N=pArray->GetElement(szIndex); + if (N==-1) + { + MacroError("/vardata '%s[%d]' failed, out of bounds on array",szName,N); + return; + } + if (!pVar->Var.Type->FromData(pVar->Var.VarPtr,Result)) + { + MacroError("/vardata '%s[%d]'failed, array element type rejected new value",szName,N); + } + } + else + { + if (!pVar->Var.Type->FromData(pVar->Var.VarPtr,Result)) + { + MacroError("/vardata '%s' failed, variable type rejected new value",szName); + } + } +} + +#else +VOID AddCustomEvent(PEVENTLIST pEList, PCHAR szLine) +{ + PEVENTQUEUE pEvent = NULL; + if (!pEList->pEventFunc) return; + pEvent = (PEVENTQUEUE)malloc(sizeof(EVENTQUEUE)); + if (!pEvent) return; + ZeroMemory(pEvent,sizeof(EVENTQUEUE)); + pEvent->Type = EVENT_CUSTOM; + pEvent->pEventList = pEList; + CHAR szParamName[MAX_STRING] = {0}; + CHAR szParamType[MAX_STRING] = {0}; + GetFuncParam(pEList->pEventFunc->Line,0,szParamName,szParamType); + MQ2Type *pType = FindMQ2DataType(szParamType); + if (!pType) + pType=pStringType; + + AddMQ2DataEventVariable(szParamName,"",pType,&pEvent->Parameters,szLine); + + if (!gEventQueue) + { + gEventQueue = pEvent; + } + else + { + PEVENTQUEUE pTemp; + for (pTemp = gEventQueue;pTemp->pNext;pTemp=pTemp->pNext); + pTemp->pNext = pEvent; + pEvent->pPrev=pTemp; + } +} +#endif +#ifndef SafeXLoc +#error 1 +#endif +VOID CheckChatForEvent(PCHAR szMsg) +{ +} + +VOID DropTimers(VOID) +{ + PMQTIMER pTimer=gTimer; + CHAR szOrig[MAX_STRING] = {0}; + while(pTimer) + { + if (pTimer->Current) + { + pTimer->Current--; + if (!pTimer->Current) + { + itoa(pTimer->Original,szOrig,10); + } + } + pTimer=pTimer->pNext; + } +} diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2DetourAPI.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2DetourAPI.cpp new file mode 100644 index 0000000000..fe706676a7 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2DetourAPI.cpp @@ -0,0 +1,1003 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +// Exclude rarely-used stuff from Windows headers +#define WIN32_LEAN_AND_MEAN +#define _WIN32_WINNT 0x510 +#define DIRECTINPUT_VERSION 0x800 + +#if !defined(CINTERFACE) +//#error /DCINTERFACE +#endif + +#define DBG_SPEW + +#include "MQ2Main.h" +#ifndef ISXEQ + +typedef struct _OurDetours { + /* 0x00 */ unsigned int addr; + /* 0x04 */ unsigned int count; + /* 0x08 */ unsigned char array[50]; + /* 0x3a */ PBYTE pfDetour; + /* 0x3e */ PBYTE pfTrampoline; + /* 0x42 */ struct _OurDetours *pNext; + /* 0x46 */ struct _OurDetours *pLast; +} OurDetours; + +OurDetours *ourdetours=0; +CRITICAL_SECTION gDetourCS; + + +OurDetours *FindDetour(DWORD address) +{ + OurDetours *pDetour=ourdetours; + while(pDetour) + { + if (pDetour->addr==address) + return pDetour; + pDetour=pDetour->pNext; + } + return 0; +} + +BOOL AddDetour(DWORD address, PBYTE pfDetour, PBYTE pfTrampoline, DWORD Count) +{ + CAutoLock Lock(&gDetourCS); + BOOL Ret=TRUE; + DebugSpew("AddDetour(0x%X, 0x%X, 0x%X, 0x%X)",address,pfDetour,pfTrampoline,Count); + if (FindDetour(address)) + { + + DebugSpew("Address 0x%x already detoured.",address); + return FALSE; + } + OurDetours *detour = new OurDetours; + detour->addr=address; + detour->count=Count; + memcpy(detour->array,(char *)address, Count); + detour->pNext=ourdetours; + if (ourdetours) + ourdetours->pLast=detour; + detour->pLast=0; + if (pfDetour && !DetourFunctionWithEmptyTrampoline(pfTrampoline, + (PBYTE)address, + pfDetour)) + { + detour->pfDetour=0; + detour->pfTrampoline=0; + Ret=FALSE; + DebugSpew("Detour failed."); + } + else + { + detour->pfDetour=pfDetour; + detour->pfTrampoline=pfTrampoline; + DebugSpew("Detour success."); + } + ourdetours=detour; + return Ret; +} + +void AddDetourf(DWORD address, ...) +{ + va_list marker; + int i=0; + va_start(marker, address); + DWORD Parameters[3]; + DWORD nParameters=0; + while (i!=-1) + { + if (nParameters<3) + { + Parameters[nParameters]=i; + nParameters++; + } + i = va_arg(marker,int); + } + va_end(marker); + if (nParameters==3) + { + AddDetour(address,(PBYTE)Parameters[1],(PBYTE)Parameters[2],20); + } + else + { + DebugSpew("Illegal AddDetourf call"); + } +} + +void RemoveDetour(DWORD address) +{ + CAutoLock Lock(&gDetourCS); + DebugSpew("RemoveDetour(%X)",address); + OurDetours *detour = ourdetours; + while (detour) + { + if (detour->addr==address) + { + if (detour->pfDetour) + { + DetourRemove(detour->pfTrampoline, + detour->pfDetour); + } + if (detour->pLast) + detour->pLast->pNext=detour->pNext; + else + ourdetours=detour->pNext; + + if (detour->pNext) + detour->pNext->pLast=detour->pLast; + delete detour; + DebugSpew("Detour removed."); + return; + } + detour=detour->pNext; + } + DebugSpew("Detour not found in RemoveDetour()"); +} + +void RemoveOurDetours() +{ + CAutoLock Lock(&gDetourCS); + DebugSpew("RemoveOurDetours()"); + if (!ourdetours) + return; + while (ourdetours) + { + if (ourdetours->pfDetour) + { + DebugSpew("RemoveOurDetours() -- Removing %X",ourdetours->addr); + DetourRemove(ourdetours->pfTrampoline,ourdetours->pfDetour); + } + + OurDetours *pNext=ourdetours->pNext; + delete ourdetours; + ourdetours=pNext; + } +} + +#endif + + +class CObfuscator +{ +public: + int doit_tramp(int, int); + int doit_detour(int opcode, int flag); +}; + +int CObfuscator::doit_detour(int opcode, int flag) +{ +#if 0 + if (EQ_BEGIN_ZONE == opcode) { + DebugSpewAlways("EQ_BEGIN_ZONE"); + } else { + DebugSpewAlways("opcode %d", opcode); + } +#endif + if (opcode == EQ_BEGIN_ZONE) + { + } + if (opcode == EQ_END_ZONE) + { + } + return doit_tramp(opcode, flag); +}; + +DETOUR_TRAMPOLINE_EMPTY(int CObfuscator::doit_tramp(int, int)); + +#define EB_SIZE (1024*4) +void emotify(void); +void emotify2(char *buffer); + +// we need this detour to clean up the stack because +// emote sends 1024 bytes no matter how many bytes in the string +// MQ2 variables get left on the stack.... +class CEmoteHook +{ +public: + VOID Trampoline(void); + VOID Detour(void); +}; + +VOID CEmoteHook::Detour(void) +{ + emotify(); + Trampoline(); +} +DETOUR_TRAMPOLINE_EMPTY(VOID CEmoteHook::Trampoline(void)); + + +// this is the memory checker key struct +struct mckey { + union { + int x; + unsigned char a[4]; + char sa[4]; + }; +}; + +// pointer to encryption pad for memory checker +unsigned int *extern_array0 = NULL; +unsigned int *extern_array1 = NULL; +unsigned int *extern_array2 = NULL; +unsigned int *extern_array3 = NULL; +unsigned int *extern_array4 = NULL; +#ifndef ISXEQ +int __cdecl memcheck0(unsigned char *buffer, int count); +int __cdecl memcheck1(unsigned char *buffer, int count, struct mckey key); +int __cdecl memcheck2(unsigned char *buffer, int count, struct mckey key); +int __cdecl memcheck3(unsigned char *buffer, int count, struct mckey key); +int __cdecl memcheck4(unsigned char *buffer, int count, struct mckey key); +#endif + +// *************************************************************************** +// Function: HookMemChecker +// Description: Hook MemChecker +// *************************************************************************** +int (__cdecl *memcheck0_tramp)(unsigned char *buffer, int count); +int (__cdecl *memcheck1_tramp)(unsigned char *buffer, int count, struct mckey key); +int (__cdecl *memcheck2_tramp)(unsigned char *buffer, int count, struct mckey key); +int (__cdecl *memcheck3_tramp)(unsigned char *buffer, int count, struct mckey key); +int (__cdecl *memcheck4_tramp)(unsigned char *buffer, int count, struct mckey key); +VOID HookInlineChecks(BOOL Patch) +{ + int i; + DWORD oldperm, tmp, NewData; + + int cmps[] = { __AC1 + 6 }; + + int cmps2[] = { __AC2, + __AC3, + __AC4, + __AC5, + __AC6, + __AC7 }; + + int len2[] = { 6, 6, 6, 6, 6, 6 }; + + char NewData2[20]; + + static char OldData2[sizeof(cmps2)/sizeof(cmps2[0])][20]; + + if (Patch) + { + NewData = 0x7fffffff; + + for (i=0;iMemcpy_Clean((unsigned int)buffer,realbuffer,count); +#endif + + for (i=0;i<(unsigned int)count;i++) { + unsigned char tmp; +#ifdef ISXEQ + tmp=realbuffer[i]; +#else + unsigned int b=(int) &buffer[i]; + OurDetours *detour = ourdetours; + while(detour) + { + if (detour->count && (b >= detour->addr) && + (b < detour->addr+detour->count) ) { + tmp = detour->array[b - detour->addr]; + break; + } + detour=detour->pNext; + } + if (!detour) tmp = buffer[i]; +#endif + x = (int)tmp ^ (eax & 0xff); + eax = ((int)eax >> 8) & 0xffffff; + x = extern_array0[x]; + eax ^= x; + } + +#ifdef ISXEQ + free(realbuffer); +#endif + return eax; +} + + +int __cdecl memcheck1(unsigned char *buffer, int count, struct mckey key) +{ + unsigned int i; + unsigned int ebx, eax, edx; + + if (!extern_array1) { + if (!EQADDR_ENCRYPTPAD1) { + //_asm int 3 + } else { + extern_array1 = (unsigned int *)EQADDR_ENCRYPTPAD1; + } + } +// push ebp +// mov ebp, esp +// push esi +// push edi +// or edi, 0FFFFFFFFh +// cmp [ebp+arg_8], 0 + if (key.x != 0) { +// mov esi, 0FFh +// mov ecx, 0FFFFFFh +// jz short loc_4C3978 +// xor eax, eax +// mov al, byte ptr [ebp+arg_8] +// xor edx, edx +// mov dl, byte ptr [ebp+arg_8+1] + edx = key.a[1]; +// not eax +// and eax, esi + eax = ~key.a[0] & 0xff; +// mov eax, encryptpad1[eax*4] + eax = extern_array1[eax]; +// xor eax, ecx + eax ^= 0xffffff; +// xor edx, eax +// and edx, esi + edx = (edx ^ eax) & 0xff; +// sar eax, 8 +// and eax, ecx + eax = ((int)eax >> 8) & 0xffffff; +// xor eax, encryptpad1[edx*4] + eax ^= extern_array1[edx]; +// xor edx, edx +// mov dl, byte ptr [ebp+arg_8+2] + edx = key.a[2]; +// xor edx, eax +// sar eax, 8 +// and edx, esi + edx = (edx ^ eax) & 0xff; +// and eax, ecx + eax = ((int)eax >> 8) & 0xffffff; +// xor eax, encryptpad1[edx*4] + eax ^= extern_array1[edx]; +// xor edx, edx +// mov dl, byte ptr [ebp+arg_8+3] + edx = key.a[3]; +// xor edx, eax +// sar eax, 8 +// and edx, esi + edx = (edx ^ eax) & 0xff; +// and eax, ecx + eax = ((int)eax >> 8) & 0xffffff; +// xor eax, encryptpad1[edx*4] + eax ^= extern_array1[edx]; +// mov edi, eax +// + } else { // key.x != 0 + eax = 0xffffffff; + } +//loc_4C3978: ; CODE XREF: new_memcheck1+16j +// mov edx, [ebp+arg_0] +// mov eax, [ebp+arg_4] +// add eax, edx +// cmp edx, eax +// jnb short loc_4C399F +// push ebx +// +//loc_4C3985: ; CODE XREF: new_memcheck1+8Fj +// xor ebx, ebx +// mov bl, [edx] +// xor ebx, edi +// sar edi, 8 +// and ebx, esi +// and edi, ecx +// xor edi, encryptpad1[ebx*4] +// inc edx +// cmp edx, eax +// jb short loc_4C3985 +// pop ebx +// +//loc_4C399F: ; CODE XREF: new_memcheck1+75j +// mov eax, edi +// pop edi +// not eax +// pop esi +// pop ebp +// retn +// + +#ifdef ISXEQ + unsigned char *realbuffer=(unsigned char *)malloc(count); + pExtension->Memcpy_Clean((unsigned int)buffer,realbuffer,count); +#endif + + for (i=0;i<(unsigned int)count;i++) { + unsigned char tmp; +#ifdef ISXEQ + tmp=realbuffer[i]; +#else + unsigned int b=(int) &buffer[i]; + OurDetours *detour = ourdetours; + while(detour) { + if (detour->count && (b >= detour->addr) && + (b < detour->addr+detour->count) ) { + tmp = detour->array[b - detour->addr]; + break; + } + detour=detour->pNext; + } + if (!detour) tmp = buffer[i]; +#endif + ebx = ((int)tmp ^ eax) & 0xff; + eax = ((int)eax >> 8) & 0xffffff; + eax ^= extern_array1[ebx]; + } +#ifdef ISXEQ + free(realbuffer); +#endif + return ~eax; +} + + + +int __cdecl memcheck2(unsigned char *buffer, int count, struct mckey key) +{ + unsigned int i; + unsigned int ebx, edx, eax; + + //DebugSpewAlways("memcheck2: 0x%x", buffer); + + if (!extern_array2) { + if (!EQADDR_ENCRYPTPAD2) { + //_asm int 3 + } else { + extern_array2 = (unsigned int *)EQADDR_ENCRYPTPAD2; + } + } +// push ebp +// mov ebp, esp +// push ecx +// xor eax, eax +// mov al, [ebp+arg_8] +// xor edx, edx +// mov dl, [ebp+arg_9] + edx = key.a[1]; +// push ebx +// push esi +// mov esi, 0FFh +// mov ecx, 0FFFFFFh +// not eax +// and eax, esi + eax = ~key.a[0] & 0xff; +// mov eax, encryptpad2[eax*4] + eax = extern_array2[eax]; +// xor eax, ecx + eax ^= 0xffffff; +// xor edx, eax + edx = (edx ^ eax) & 0xff; +// sar eax, 8 +// and edx, esi +// and eax, ecx + eax = ((int)eax >> 8) & 0xffffff; +// xor eax, encryptpad2[edx*4] + eax ^= extern_array2[edx]; +// xor edx, edx +// mov dl, [ebp+arg_A] + edx = key.a[2]; +// push edi +// xor edx, eax + edx = (edx ^ eax) & 0xff; +// sar eax, 8 +// and edx, esi +// and eax, ecx + eax = ((int)eax >> 8) & 0xffffff; +// xor eax, encryptpad2[edx*4] +// mov edx, eax + edx = eax ^ extern_array2[edx]; +// call null_sub_ret_0 + eax = 0; +// mov edi, [ebp+arg_0] +// xor ebx, ebx +// mov bl, [ebp+arg_B] + ebx = key.a[3]; +// mov [ebp+var_4], eax +// xor ebx, edx + ebx = (edx ^ ebx) & 0xff; +// sar edx, 8 +// and edx, ecx +// and ebx, esi + edx = ((int)edx >> 8) & 0xffffff; +// xor edx, encryptpad2[ebx*4] + edx ^= extern_array2[ebx]; +// xor edx, eax + edx ^= eax; +// mov eax, [ebp+arg_4] +// add eax, edi +// jmp short loc_4C5776 +//; --------------------------------------------------------------------------- +// +//loc_4C5761: ; CODE XREF: new_memcheck2+8Fj +// xor ebx, ebx +// mov bl, [edi] +// xor ebx, edx +// sar edx, 8 +// and ebx, esi +// and edx, ecx +// xor edx, encryptpad2[ebx*4] +// inc edi +// +//loc_4C5776: ; CODE XREF: new_memcheck2+76j +// cmp edi, eax +// jb short loc_4C5761 +// pop edi +// mov eax, edx +// not eax +// xor eax, [ebp+var_4] +// pop esi +// pop ebx +// leave +// retn + + +#ifdef ISXEQ + unsigned char *realbuffer=(unsigned char *)malloc(count); + pExtension->Memcpy_Clean((unsigned int)buffer,realbuffer,count); +#endif + + for (i=0;i<(unsigned int)count;i++) { + unsigned char tmp; + +#ifdef ISXEQ + tmp=realbuffer[i]; +#else + unsigned int b=(int) &buffer[i]; + OurDetours *detour = ourdetours; + while(detour) { + if (detour->count && (b >= detour->addr) && + (b < detour->addr+detour->count) ) { + tmp = detour->array[b - detour->addr]; + break; + } + detour=detour->pNext; + } + if (!detour) tmp = buffer[i]; +#endif + + ebx = ((int) tmp ^ edx) & 0xff; + edx = ((int)edx >> 8) & 0xffffff; + edx ^= extern_array2[ebx]; + } + eax = ~edx ^ 0; +#ifdef ISXEQ + free(realbuffer); +#endif + return eax; +} + + +//extern int extern_arrray[]; +//unsigned int *extern_array3 = (unsigned int *)0x5C0E98; + +// 004F4AB9: 55 push ebp +// 004F4ABA: 8B EC mov ebp,esp +// 004F4ABC: 56 push esi + +// bah - 83 /1 ib OR r/m16,imm8 r/m16 OR imm8 (sign-extended) +// sign extended!!!!!!!!!!!! + +// 004F4ABD: 83 C8 FF or eax,0FFh + +int __cdecl memcheck3(unsigned char *buffer, int count, struct mckey key) +{ + unsigned int eax, ebx, edx, i; + + if (!extern_array3) { + if (!EQADDR_ENCRYPTPAD3) { + //_asm int 3 + } else { + extern_array3 = (unsigned int *)EQADDR_ENCRYPTPAD3; + } + } +// push ebp +// mov ebp, esp +// push ecx +// xor eax, eax +// mov al, [ebp+arg_8] +// xor edx, edx +// mov dl, [ebp+arg_9] + edx = key.a[1]; +// push ebx +// push esi +// mov esi, 0FFh +// mov ecx, 0FFFFFFh +// not eax +// and eax, esi + eax = ~key.a[0] & 0xff; +// mov eax, encryptpad3[eax*4] + eax = extern_array3[eax]; +// xor eax, ecx + eax ^= 0xffffff; +// xor edx, eax +// sar eax, 8 +// and edx, esi + edx = (edx ^ eax) & 0xff; +// and eax, ecx + eax = ((int)eax>>8) & 0xffffff; +// xor eax, encryptpad3[edx*4] + eax ^= extern_array3[edx]; +// xor edx, edx +// mov dl, [ebp+arg_A] + edx = key.a[2]; +// push edi +// xor edx, eax + edx = (edx ^ eax) & 0xff; +// sar eax, 8 +// and edx, esi +// and eax, ecx + eax = ((int)eax>>8) & 0xffffff; +// xor eax, encryptpad3[edx*4] +// mov edx, eax + edx = eax ^ extern_array3[edx]; + +// call null_sub_ret_0 + eax = 0; +// mov edi, [ebp+arg_0] +// xor ebx, ebx +// mov bl, [ebp+arg_B] + ebx = key.a[3]; +// mov [ebp+var_4], eax +// xor ebx, edx +// sar edx, 8 +// and edx, ecx +// and ebx, esi + ebx = (ebx ^ edx) & 0xff; + edx = ((int)edx>>8) & 0xffffff; +// xor edx, encryptpad3[ebx*4] + edx ^= extern_array3[ebx]; +// xor edx, eax + edx ^= eax; +// mov eax, [ebp+arg_4] +// add eax, edi +// jmp short loc_4C5813 +//; --------------------------------------------------------------------------- +// +//loc_4C57FE: ; CODE XREF: new_memcheck3+8Fj +// xor ebx, ebx +// mov bl, [edi] +// xor ebx, edx +// sar edx, 8 +// and ebx, esi +// and edx, ecx +// xor edx, encryptpad3[ebx*4] +// inc edi +// + +#ifdef ISXEQ + unsigned char *realbuffer=(unsigned char *)malloc(count); + pExtension->Memcpy_Clean((unsigned int)buffer,realbuffer,count); +#endif + + for (i=0;i<(unsigned int)count;i++) { + unsigned char tmp; +#ifdef ISXEQ + tmp=realbuffer[i]; +#else + unsigned int b=(int) &buffer[i]; + OurDetours *detour = ourdetours; + while(detour) + { + if (detour->count && (b >= detour->addr) && + (b < detour->addr+detour->count) ) { + tmp = detour->array[b - detour->addr]; + break; + } + detour=detour->pNext; + } + if (!detour) tmp = buffer[i]; +#endif + + ebx = (tmp ^ edx) & 0xff; + edx = ((int)edx >> 8) & 0xffffff; + edx ^= extern_array3[ebx]; + } +//loc_4C5813: ; CODE XREF: new_memcheck3+76j +// cmp edi, eax +// jb short loc_4C57FE +// pop edi +// mov eax, edx +// not eax +// xor eax, [ebp+var_4] + eax = ~edx ^ 0; + +#ifdef ISXEQ + free(realbuffer); +#endif + return eax; +// pop esi +// pop ebx +// leave +// retn +} + +int __cdecl memcheck4(unsigned char *buffer, int count, struct mckey key) +{ + unsigned int eax, ebx, edx, i; + + if (!extern_array4) { + if (!EQADDR_ENCRYPTPAD4) { + //_asm int 3 + } else { + extern_array4 = (unsigned int *)EQADDR_ENCRYPTPAD4; + } + } + edx = key.a[1]; + eax = ~key.a[0] & 0xff; + eax = extern_array4[eax]; + eax ^= 0xffffff; + edx = (edx ^ eax) & 0xff; + eax = ((int)eax>>8) & 0xffffff; + eax ^= extern_array4[edx]; + edx = key.a[2]; + edx = (edx ^ eax) & 0xff; + eax = ((int)eax>>8) & 0xffffff; + edx = eax ^ extern_array4[edx]; + eax = 0; + ebx = key.a[3]; + ebx = (ebx ^ edx) & 0xff; + edx = ((int)edx>>8) & 0xffffff; + edx ^= extern_array4[ebx]; + edx ^= eax; + +#ifdef ISXEQ + unsigned char *realbuffer=(unsigned char *)malloc(count); + pExtension->Memcpy_Clean((unsigned int)buffer,realbuffer,count); +#endif + + for (i=0;i<(unsigned int)count;i++) { + unsigned char tmp; +#ifdef ISXEQ + tmp=realbuffer[i]; +#else + unsigned int b=(int) &buffer[i]; + OurDetours *detour = ourdetours; + while(detour) + { + if (detour->count && (b >= detour->addr) && + (b < detour->addr+detour->count) ) { + tmp = detour->array[b - detour->addr]; + break; + } + detour=detour->pNext; + } + if (!detour) tmp = buffer[i]; +#endif + + ebx = (tmp ^ edx) & 0xff; + edx = ((int)edx >> 8) & 0xffffff; + edx ^= extern_array4[ebx]; + } + eax = ~edx ^ 0; + +#ifdef ISXEQ + free(realbuffer); +#endif + return eax; +} + +VOID __cdecl CrashDetected_Trampoline(); +VOID __cdecl CrashDetected_Detour() +{ + MessageBox(0,"Edge is blocking the 'send Sony crash info?' box for your safety and privacy. Hooray!","EverQuest Crash Detected",MB_OK); +} +DETOUR_TRAMPOLINE_EMPTY(VOID CrashDetected_Trampoline()); + +DETOUR_TRAMPOLINE_EMPTY(int LoadFrontEnd_Trampoline()); +#ifndef TESTMEM +int LoadFrontEnd_Detour() +{ + gGameState=GetGameState(); + return LoadFrontEnd_Trampoline(); +} +#endif +void InitializeMQ2Detours() +{ +#ifndef ISXEQ + InitializeCriticalSection(&gDetourCS); + HookMemChecker(TRUE); +#endif + EzDetour(CrashDetected,CrashDetected_Detour,CrashDetected_Trampoline); +#ifndef TESTMEM + EzDetour(__LoadFrontEnd, LoadFrontEnd_Detour, LoadFrontEnd_Trampoline); +#endif +} + +void ShutdownMQ2Detours() +{ + RemoveDetour(CrashDetected); + RemoveDetour(__LoadFrontEnd); +#ifndef ISXEQ + HookMemChecker(FALSE); + RemoveOurDetours(); + DeleteCriticalSection(&gDetourCS); +#endif +} + + +#pragma optimize( "", off ) + +void emotify(void) +{ + char buffer[EB_SIZE]; + emotify2(buffer); +} +void emotify2(char *A) +{ + int i; + for (i=0;i gMacroSubLookupMap; +PEVENTQUEUE gEventQueue = NULL; +PMACROBLOCK gEventFunc[NUM_EVENTS] = {NULL}; +#endif +UCHAR gLastFind = 0; +DOUBLE gZFilter=10000.0f; +DOUBLE gFaceAngle=10000.0f; +DOUBLE gLookAngle=10000.0f; +CHAR gszEQPath[MAX_STRING] = {0}; +CHAR gszMacroPath[MAX_STRING] = {0}; +CHAR gszLogPath[MAX_STRING] = {0}; +CHAR gszINIPath[MAX_STRING] = {0}; +CHAR gszINIFilename[MAX_STRING] = {0}; +CHAR gszItemDB[MAX_STRING] = {0}; +CHAR gszMacroName[MAX_STRING] = {0}; +CHAR szLastCommand[MAX_STRING] = {0}; + +CHAR gszLastNormalError[MAX_STRING] = {0}; +CHAR gszLastSyntaxError[MAX_STRING] = {0}; +CHAR gszLastMQ2DataError[MAX_STRING] = {0}; + +PSPAWNINFO pNamingSpawn=0; +CHAR gszSpawnPlayerName[7][MAX_STRING]={ +"",//0 +"${If[${NamingSpawn.Mark},\"${NamingSpawn.Mark} - \",]}${If[${NamingSpawn.Trader},\"Trader \",]}${If[${NamingSpawn.Invis},(${NamingSpawn.DisplayName}),${NamingSpawn.DisplayName}]}${If[${NamingSpawn.AFK},\" AFK\",]}${If[${NamingSpawn.Linkdead},\" LD\",]}${If[${NamingSpawn.LFG},\" LFG\",]}${If[${NamingSpawn.GroupLeader},\" LDR\",]}",//1 +"${If[${NamingSpawn.Mark},\"${NamingSpawn.Mark} - \",]}${If[${NamingSpawn.Trader},\"Trader \",]}${If[${NamingSpawn.Invis},(${NamingSpawn.DisplayName}),${NamingSpawn.DisplayName}]}${If[${NamingSpawn.Surname.Length},\" ${NamingSpawn.Surname}\",]}${If[${NamingSpawn.AFK},\" AFK\",]}${If[${NamingSpawn.Linkdead},\" LD\",]}${If[${NamingSpawn.LFG},\" LFG\",]}${If[${NamingSpawn.GroupLeader},\" LDR\",]}",//2 +"${If[${NamingSpawn.Mark},\"${NamingSpawn.Mark} - \",]}${If[${NamingSpawn.Trader},\"Trader \",]}${If[${NamingSpawn.Invis},(${NamingSpawn.DisplayName}),${NamingSpawn.DisplayName}]}${If[${NamingSpawn.Surname.Length},\" ${NamingSpawn.Surname}\",]}${If[${NamingSpawn.AFK},\" AFK\",]}${If[${NamingSpawn.Linkdead},\" LD\",]}${If[${NamingSpawn.LFG},\" LFG\",]}${If[${NamingSpawn.GroupLeader},\" LDR\",]}${If[${NamingSpawn.Guild.Length},\n<${If[${NamingSpawn.GuildStatus.NotEqual[member]},\"${NamingSpawn.GuildStatus} of \",]}${NamingSpawn.Guild}>,]}",//3 +"${If[${NamingSpawn.Mark},\"${NamingSpawn.Mark} - \",]}${If[${NamingSpawn.Trader},\"Trader \",]}${If[${NamingSpawn.AARank},\"${NamingSpawn.AATitle} \",]}${If[${NamingSpawn.Invis},(${NamingSpawn.DisplayName}),${NamingSpawn.DisplayName}]}${If[${NamingSpawn.Surname.Length},\" ${NamingSpawn.Surname}\",]}${If[${NamingSpawn.Suffix.Length},\" ${NamingSpawn.Suffix}\",]}${If[${NamingSpawn.AFK},\" AFK\",]}${If[${NamingSpawn.Linkdead},\" LD\",]}${If[${NamingSpawn.LFG},\" LFG\",]}${If[${NamingSpawn.GroupLeader},\" LDR\",]}${If[${NamingSpawn.Guild.Length},\n<${If[${NamingSpawn.GuildStatus.NotEqual[member]},\"${NamingSpawn.GuildStatus} of \",]}${NamingSpawn.Guild}>,]}",//4 +"${If[${NamingSpawn.Mark},\"${NamingSpawn.Mark} - \",]}${If[${NamingSpawn.Trader},\"Trader \",]}${If[${NamingSpawn.AARank},\"${NamingSpawn.AATitle} \",]}${If[${NamingSpawn.Invis},(${NamingSpawn.DisplayName}),${NamingSpawn.DisplayName}]}${If[${NamingSpawn.Suffix.Length},\" ${NamingSpawn.Suffix}\",]}${If[${NamingSpawn.AFK},\" AFK\",]}${If[${NamingSpawn.Linkdead},\" LD\",]}${If[${NamingSpawn.LFG},\" LFG\",]}${If[${NamingSpawn.GroupLeader},\" LDR\",]}",//5 +"${If[${NamingSpawn.Mark},\"${NamingSpawn.Mark} - \",]}${If[${NamingSpawn.Trader},\"Trader \",]}${If[${NamingSpawn.AARank},\"${NamingSpawn.AATitle} \",]}${If[${NamingSpawn.Invis},(${NamingSpawn.DisplayName}),${NamingSpawn.DisplayName}]}${If[${NamingSpawn.Surname.Length},\" ${NamingSpawn.Surname}\",]}${If[${NamingSpawn.Suffix.Length},\" ${NamingSpawn.Suffix}\",]}${If[${NamingSpawn.AFK},\" AFK\",]}${If[${NamingSpawn.Linkdead},\" LD\",]}${If[${NamingSpawn.LFG},\" LFG\",]}${If[${NamingSpawn.GroupLeader},\" LDR\",]}",//6 +}; +CHAR gszSpawnNPCName[MAX_STRING]="${If[${NamingSpawn.Mark},\"${NamingSpawn.Mark} - \",]}${If[${NamingSpawn.Assist},\">> \",]}${NamingSpawn.DisplayName}${If[${NamingSpawn.Assist},\" - ${NamingSpawn.PctHPs}%<<\",]}${If[${NamingSpawn.Surname.Length},\n(${NamingSpawn.Surname}),]}"; +CHAR gszSpawnPetName[MAX_STRING]="${If[${NamingSpawn.Mark},\"${NamingSpawn.Mark} - \",]}${If[${NamingSpawn.Assist},\">> \",]}${NamingSpawn.DisplayName}${If[${NamingSpawn.Assist},\" - ${NamingSpawn.PctHPs}%<<\",]}${If[${NamingSpawn.Master.Type.Equal[PC]},\n(${NamingSpawn.Master}),]}"; +CHAR gszSpawnCorpseName[MAX_STRING]="${NamingSpawn.DisplayName}'s corpse"; + +DWORD DrawHUDParams[4]={0,0,0,0}; + +#ifndef ISXEQ +Blech *pMQ2Blech=0; +CHAR EventMsg[MAX_STRING]={0}; +#ifdef USEBLECHEVENTS +Blech *pEventBlech = 0; +#endif +PEVENTLIST pEventList = NULL; +#endif + +DWORD gEventChat = 0; +DWORD gRunning = 0; +BOOL gbMoving = FALSE; +DWORD gMaxTurbo = 10; +BOOL gReturn = TRUE; +BOOL gInClick = FALSE; +BOOL gbInZone = FALSE; +BOOL gZoning = FALSE; +BOOL WereWeZoning = TRUE; +BOOL gbInDInput = FALSE; +BOOL gbInChat = FALSE; +BOOL gbInDState = FALSE; +BOOL gbInDAcquire = FALSE; +BOOL gFilterSkillsAll = FALSE; +BOOL gFilterSkillsIncrease = FALSE; +BOOL gFilterTarget = FALSE; +BOOL gFilterDebug = FALSE; +BOOL gFilterMoney = FALSE; +BOOL gFilterFood = FALSE; +BOOL gFilterMacro = FALSE; +BOOL gFilterMQ = FALSE; +BOOL gFilterEncumber = FALSE; +BOOL gFilterCustom = TRUE; +BOOL gSpewToFile = FALSE; +BOOL gbDoAutoRun = FALSE; +BOOL gMQPauseOnChat = FALSE; +BOOL gKeepKeys = FALSE; +BOOL gLClickedObject = FALSE; +SWHOFILTER gFilterSWho = {0}; +EQLIB_VAR BOOL gFilterMQ2DataErrors=FALSE; + +DOUBLE DegToRad = 57.295779513082320876846364344191; +DOUBLE PI = 3.1415926535; + +//PKEYPRESS gKeyStack = NULL; +PMQTIMER gTimer = NULL; +LONG gDelay = 0; +CHAR gDelayCondition[MAX_STRING]={0}; +BOOL bAllowCommandParse=TRUE; +LONG gDelayZoning = 0; +PALERTLIST gpAlertList = NULL; +BOOL gMacroPause = FALSE; +SPAWNINFO EnviroTarget = {0}; +PGROUNDITEM pGroundTarget = NULL; +SPAWNINFO DoorEnviroTarget = {0}; +PDOOR pDoorTarget = NULL; +PITEMDB gItemDB = NULL; +BOOL bRunNextCommand = FALSE; +BOOL gTurbo = FALSE; +PDEFINE pDefines = NULL; +CHAR gLastFindSlot[MAX_STRING]={0}; +PFILTER gpFilters = NULL; + +BOOL g_bInDXMouse = FALSE; +PMOUSESPOOF gMouseData = NULL; +BOOL bDetMouse = TRUE; + +// EQ Functions Initialization +fEQCommand cmdHelp = NULL; +fEQCommand cmdWho = NULL; +fEQCommand cmdWhoTarget = NULL; +fEQCommand cmdLocation = NULL; +fEQCommand cmdFace = NULL; +fEQCommand cmdTarget = NULL; +fEQCommand cmdCharInfo = NULL; +fEQCommand cmdFilter = NULL; +fEQCommand cmdDoAbility = NULL; +fEQCommand cmdCast = NULL; + +DWORD gnNormalEQMappableCommands; +PCHAR szEQMappableCommands[nEQMappableCommands]; +map ItemSlotMap; + +CHAR DataTypeTemp[MAX_STRING]={0}; + +map SpawnByName; +MQRANK EQP_DistArray[3000]; +DWORD gSpawnCount=0; + +// Motd and Pulse's mouse variables +BOOL gMouseClickInProgress[8] = {FALSE}; +// End of mouse variables + +// Arrays (Note: See also EQLib_Utilities.cpp) +DIKEYID gDiKeyID[] = { +#include "dikeys.h" + {NULL,0} +}; + +PCHAR gDiKeyName[256]; + +PCHAR szHeading[] = { + "south", //0 + "south by southeast", //1 + "southeast", //2 + "east by southeast", //3 + "east", //4 + "east by northeast", //5 + "northeast", //6 + "north by northeast", //7 + "north", //8 + "north by northwest", //9 + "northwest", //10 + "west by northwest", //11 + "west", //12 + "west by southwest", //13 + "southwest", //14 + "south by southwest" //15 +}; + +PCHAR szHeadingShort[] = { + "S", //0 + "SSE", //1 + "SE", //2 + "ESE", //3 + "E", //4 + "ENE", //5 + "NE", //6 + "NNE", //7 + "N", //8 + "NNW", //9 + "NW", //10 + "WNW", //11 + "W", //12 + "WSW", //13 + "SW", //14 + "SSW" //15 +}; + +PCHAR szHeadingNormal[] = { + "north", //0 + "north by northeast", //1 + "northeast", //2 + "east by northeast", //3 + "east", //4 + "east by southeast", //5 + "southeast", //6 + "south by southeast", //7 + "south", //8 + "south by southwest", //9 + "southwest", //10 + "west by southwest", //11 + "west", //12 + "west by northwest", //13 + "northwest", //14 + "north by northwest" //15 +}; + +PCHAR szHeadingNormalShort[] = { + "N", //0 + "NNE", //1 + "NE", //2 + "ENE", //3 + "E", //4 + "ESE", //5 + "SE", //6 + "SSE", //7 + "S", //8 + "SSW", //9 + "SW", //10 + "WSW", //11 + "W", //12 + "WNW", //13 + "NW", //14 + "NNW" //15 +}; + + +PCHAR szSize[] = { + "Tiny", + "Small", + "Normal", + "Large", + "Giant", + "Huge", //? + "Unknown" //? +}; + +PCHAR szSpawnType[] = { + "player", + "NPC", + "corpse", + "any", + "pet", + NULL // SuperWhoTarget +}; + +PCHAR szGuildStatus[] = { + "", + "Leader", + "Senior Officer", + "Officer", + "Active Member", + "Member", + "Junior Member", + "Initiate", + "Recruit", + NULL +}; + +PCHAR szGender[] = { + "male", + "female", + "neuter", + "unknown" +}; + +PCHAR szDeityTeam[] = { + "none", //0 + "good", //1 + "neutral", //2 + "evil" //3 +}; + +PCHAR szLights[] = { + "NONE", // 0 - No light + "CDL", // 1 - Candle + "TR", // 2 - Torch + "TGS", // 3 - Tiny Glowing Skull + "SL", // 4 - Small Lantern + "SoM", // 5 - Stein of Moggok + "LL", // 6 - Large Lantern + "FL", // 7 - Flameless lantern, Halo of Light + "GOS", // 8 - Globe of stars + "LG", // 9 - Light Globe + "LS", // 10 - Lightstone, Burnt-out lightstone, wispstone + "GLS", // 11 - Greater lightstone + "FBE", // 12 - Fire Beatle Eye, Firefly Globe + "CL" // 13 - Coldlight +}; + +BYTE LightBrightness[] = { + 0, //0 + 1, //1 + 2, //2 + 3, //3 + 6, //4 + 7, //5 + 8, //6 + 9, //7 + 10, //8 + 0, //9 + 0, //10 + 0, //11 + 4, //12 + 5 //13 +}; + +PCHAR szSkills[] = { + #include "skills.h" + NULL +}; + +PCHAR szInnates[] = { + "Awareness",//c4c + "Bash Door",//c50 + "Breathe Fire",//c54 + "Harmony",//c58 + "Harm Touch",//c5c + "Infravision",//c60 + "Lay Hands",//c64 + "Lore",//c68 + "No Bash",//c6c + "Regeneration",//c70 + "Slam",//c74 + "Surprise",//c78 + "Ultravision",//c7c + "Inspect",//c80 + "Open",//c84 + NULL +}; + +PCHAR szCombineTypes[] = { + #include "combines.h" + NULL +}; + +PCHAR szItemTypes[] = { + #include "itemtypes.h" + NULL +}; + +PCHAR szZoneExpansionName[] = { + "Original EQ", //0 + "Kunark", //1 + "Velious", //2 + "Luclin", //3 + "Planes of Power", //4 + "Legacy of Ykesha", //5 + "Lost Dungeons of Norrath", //6 + "Gates of Discord", //7 + "Omens of War", //8 +}; + +#include "grounds.h" +PCHAR szItemName[] = { + #include "weapons.h" + NULL +}; + +PCHAR szDmgBonusType[] = { + "None", + "Magic", + "Fire", + "Cold", + "Poison", + "Disease" +}; + +PCHAR szBodyType[] = { + "Object",//0 (catapults, tents, practice dummies, etc) + "Humanoid", //1 + "Lycanthrope", //2 + "Undead", //3 + "Giant", //4 + "Construct", //5 (includes confused mutations in ldon, chests as of 9-19-2006) + "Extraplanar", //6 + "Magical", //7 + "Undead Pet", //8 + "Bane Giant", //9 + "Dain", //10 + "Untargetable", //11 + "Vampyre", //12 + "Atenha Ra", //13 + "Greater Akheva",//14 + "Khati Sha", //15 + "Seru", //16 + "*UNKNOWN BODYTYPE 17", //17 + "Draz Nurakk", //18 + "Zek", //19 + "Luggald", //20 + "Animal", //21 + "Insect", //22 + "Monster", //23 + "Elemental", //24 + "Plant", //25 + "Dragon", //26 + "Elemental", //27 + "Summoned Creature",//28 + "Dragon",//29 + "Bane Dragon",//30 + "Familiar",//31 + "Proc Pet",//32 + "Chest",//33 (5 as of 9-19-2006) + "Muramite",//34 + "*UNKNOWN BODYTYPE 35", + "*UNKNOWN BODYTYPE 36", + "*UNKNOWN BODYTYPE 37", + "*UNKNOWN BODYTYPE 38", + "*UNKNOWN BODYTYPE 39", + "*UNKNOWN BODYTYPE 40", + "*UNKNOWN BODYTYPE 41", + "*UNKNOWN BODYTYPE 42", + "*UNKNOWN BODYTYPE 43", + "*UNKNOWN BODYTYPE 44", + "*UNKNOWN BODYTYPE 45", + "*UNKNOWN BODYTYPE 46", + "*UNKNOWN BODYTYPE 47", + "*UNKNOWN BODYTYPE 48", + "*UNKNOWN BODYTYPE 49", + "*UNKNOWN BODYTYPE 50", + "*UNKNOWN BODYTYPE 51", + "*UNKNOWN BODYTYPE 52", + "*UNKNOWN BODYTYPE 53", + "*UNKNOWN BODYTYPE 54", + "*UNKNOWN BODYTYPE 55", + "*UNKNOWN BODYTYPE 56", + "*UNKNOWN BODYTYPE 57", + "*UNKNOWN BODYTYPE 58", + "*UNKNOWN BODYTYPE 59", + "*UNKNOWN BODYTYPE 60", + "*UNKNOWN BODYTYPE 61", + "*UNKNOWN BODYTYPE 62", + "*UNKNOWN BODYTYPE 63", + "*UNKNOWN BODYTYPE 64", + "Trap", + "Timer", + "Trigger", + "*UNKNOWN BODYTYPE 68", + "*UNKNOWN BODYTYPE 69", + "*UNKNOWN BODYTYPE 70", + "*UNKNOWN BODYTYPE 71", + "*UNKNOWN BODYTYPE 72", + "*UNKNOWN BODYTYPE 73", + "*UNKNOWN BODYTYPE 74", + "*UNKNOWN BODYTYPE 75", + "*UNKNOWN BODYTYPE 76", + "*UNKNOWN BODYTYPE 77", + "*UNKNOWN BODYTYPE 78", + "*UNKNOWN BODYTYPE 79", + "*UNKNOWN BODYTYPE 80", + "*UNKNOWN BODYTYPE 81", + "*UNKNOWN BODYTYPE 82", + "*UNKNOWN BODYTYPE 83", + "*UNKNOWN BODYTYPE 84", + "*UNKNOWN BODYTYPE 85", + "*UNKNOWN BODYTYPE 86", + "*UNKNOWN BODYTYPE 87", + "*UNKNOWN BODYTYPE 88", + "*UNKNOWN BODYTYPE 89", + "*UNKNOWN BODYTYPE 90", + "*UNKNOWN BODYTYPE 91", + "*UNKNOWN BODYTYPE 92", + "*UNKNOWN BODYTYPE 93", + "*UNKNOWN BODYTYPE 94", + "*UNKNOWN BODYTYPE 95", + "*UNKNOWN BODYTYPE 96", + "*UNKNOWN BODYTYPE 97", + "*UNKNOWN BODYTYPE 98", + "*UNKNOWN BODYTYPE 99", + "Untargetable", + "Trap", + "Timer", + "Trigger", +}; + +PCHAR szAugRestrictions[] = { + "None", + "Armor Only", + "Weapons Only", + "1H Weapons Only", + "2H Weapons Only", + "1H Slash Only", + "1H Blunt Only", + "Piercing Only", + "Hand to Hand Only", + "2H Slash Only", + "2H Blunt Only", + "2H Pierce Only", + "Bows Only", + "Shields Only" +}; +PCHAR szItemSlot[] = { + "charm", // 0 + "leftear", // 1 + "head", + "face", + "rightear", + "neck", + "shoulder", + "arms", + "back", + "leftwrist", + "rightwrist", // 10 + "ranged", + "hands", + "mainhand", + "offhand", + "leftfinger", + "rightfinger", + "chest", + "legs", + "feet", + "waist", // 20 + "powersource", + "ammo", + "pack1", + "pack2", + "pack3", + "pack4", + "pack5", + "pack6", + "pack7", + "pack8", // 30 + "pack9", + "pack10", + "cursor", + NULL // 31 +}; + +PCHAR szExpansions[] = { + "The Ruins of Kunark", + "The Scars of Velious", + "The Shadows of Luclin", + "The Planes of Power", + "The Legacy of Ykesha", + "Lost Dungeons of Norrath", + "Gates of Discord", + "Omens of War", + "Dragons of Norrath", + "Depths of Darkhollow", + "Prophecy of Ro", + "The Serpent's Spine", + "The Buried Sea", + "Secrets of Faydwer", + "Seeds of Destruction", + "Underfoot", + "House of Thule", + "Veil of Alaris", + "Rain of Fear", + NULL +}; + +BOOL bAllErrorsFatal=FALSE; +BOOL bAllErrorsDumpStack=FALSE; +#ifndef DoWarp +BOOL bLaxColor=TRUE; +#else +BOOL bLaxColor=FALSE; +#endif +BOOL bAllErrorsLog=FALSE; +BOOL gbHUDUnderUI=1; +BOOL gbAlwaysDrawMQHUD=0; +BOOL gbMQ2LoadingMsg=TRUE; +BOOL gbExactSearchCleanNames=FALSE; + +DWORD nColorAdjective=0; +DWORD nColorAdjectiveYou=0; +DWORD nColorExpletive=0; +DWORD nColorSyntaxError=0; +DWORD nColorMacroError=0; +DWORD nColorMQ2DataError=0; +DWORD nColorFatalError=0; + +PCHAR szColorAdjective[]= +{ + "", + "GOD DAMN ", + "FUCKING ", + "MOTHER FUCKING ", + NULL +}; + +PCHAR szColorAdjectiveYou[]= +{ + "", + " FUCKER", + " MOTHER FUCKER", + " ASSHOLE", + " FUCKTARD", + " FUCKING RETARDED MONKEY", + " GOD DAMN SHORT BUS PASSENGER", + " ASSMONKEY", + " PIGFUCKER", + " PEEN", + " FUCKING IDIOT", + " STUPID FUCKER", + " DUMBASS", + " FUCKING DUMBASS", + " STUPID FUCK", + NULL +}; + +PCHAR szColorExpletive[]= +{ + "", + "CHRIST ", + "JESUS FUCK ", + "GOD ", + "JESUS FUCKING CHRIST ", + "FUCKING CHRIST ", + "GKFJDGJKFDGJKDF ", + NULL +}; + +PCHAR szColorSyntaxError[]= +{ + "", + "%edont you know how to use a simple %acommand%y", + NULL +}; + +PCHAR szColorMacroError[]= +{ + "", + "%ei'm pretty sure you're on %acrack%y" + "%egood job%y, cant you do anything %aright%y", + "%ewhatever you're %asmoking, pass it %aalong%y", + "%e%aRTFM%y", + "%e%aRTFM%y, until then fuck off%y", + "%eget a %abrain%y", + NULL +}; + +PCHAR szColorFatalError[]= +{ + "", + "%eyou fucking broke it%y", + "%egood job%y. what's next? your head on a %astick thats %awhat%y", + NULL +}; + +PCHAR szColorMQ2DataError[]= +{ + "", + "%ewhy dont you %aread the %areference%y", + "%eget a %aclue%y", + "%ewhatever you're %asmoking, pass it %aalong%y", + "%e%aread the %areference%y", + "%e%aread the %areference%y, until then fuck off%y", + NULL +}; + +PMQPLUGIN pPlugins=0; +PMQXMLFILE pXMLFiles=0; +DWORD ManaGained=0; +DWORD HealthGained=0; +DWORD EnduranceGained=0; +PALIAS pAliases=0; +PSUB pSubs=0; +PMQCOMMAND pCommands=0; + + + +// Offset Initialization + +DWORD EQADDR_HWND = 0; +DWORD EQADDR_MEMCHECK0=0; +DWORD EQADDR_MEMCHECK1=0; +DWORD EQADDR_MEMCHECK2=0; +DWORD EQADDR_MEMCHECK3=0; +DWORD EQADDR_MEMCHECK4=0; +PCHAR EQADDR_SERVERHOST=0; +PCHAR EQADDR_SERVERNAME=0; +DWORD EQADDR_CONVERTITEMTAGS=0; +PCMDLIST EQADDR_CMDLIST=0; + +PBYTE EQADDR_ATTACK=0; +PBYTE EQADDR_NOTINCHATMODE=0; +PBYTE EQADDR_RUNWALKSTATE=0; +PCHAR EQADDR_LASTTELL=0; +PCHAR gpbRangedAttackReady=0; +PCHAR gpbShowNetStatus=0; +PCHAR gpbAltTimerReady=0; +DWORD *g_ppDrawHandler=0; +DWORD *gpShowNames=0; +DWORD *gpPCNames=0; +PBYTE pTributeActive=0; +PBYTE gpAutoFire=0; +PBYTE gpShiftKeyDown=0; // addr+1=ctrl, addr+2=alt +DWORD *gpMouseEventTime=0; + +PVOID EQADDR_GWORLD=0; +PDWORD EQADDR_DOABILITYLIST=0; + +PMAPLABEL *ppCurrentMapLabel=0; +PCHAR *EQMappableCommandList=0; + +PBYTE EQADDR_ENCRYPTPAD0=0; +PBYTE EQADDR_ENCRYPTPAD1=0; +PBYTE EQADDR_ENCRYPTPAD2=0; +PBYTE EQADDR_ENCRYPTPAD3=0; +PBYTE EQADDR_ENCRYPTPAD4=0; + +DWORD *pScreenX=0; +DWORD *pScreenY=0; +DWORD *pScreenXMax=0; +DWORD *pScreenYMax=0; +DWORD *pScreenMode=0; +CHAR *pMouseLook=0; +PMOUSEINFO EQADDR_MOUSE=0; +PMOUSECLICK EQADDR_MOUSECLICK=0; + +#ifndef ISXEQ +DWORD EQADDR_DIMAIN=0; +IDirectInputDevice8A **EQADDR_DIKEYBOARD=0; +IDirectInputDevice8A **EQADDR_DIMOUSE=0; +#endif + +PGUILDS pGuildList = 0; +PEQSOCIAL pSocialList = 0; +PBYTE pgHotkeyPage = 0; +PINT pgCurrentSocial = 0; + +fEQNewUIINI NewUIINI = 0; +fEQProcGameEvts ProcessGameEvents = 0; +fEQExecuteCmd ExecuteCmd = 0; +fEQGetMelee get_melee_range = GetMeleeRange; +fGetLabelFromEQ GetLabelFromEQ = 0; + +StringTable **ppStringTable=0; +CDBStr **ppCDBStr = 0; +EQMisc *pEQMisc=0; +CSkillMgr **ppCSkillMgr=0; +CGuild *pGuild=0; +_SKILLMGR **ppSkillMgr=0; + +CEverQuest **ppEverQuest=0; +CDisplay **ppDisplay=0; +EQ_PC **ppPCData=0; +EQ_Character **ppCharData=0; +EQPlayer **ppCharSpawn=0; +EQPlayer **ppActiveMerchant=0; +EQPlayerManager **ppSpawnManager=0; +EQPlayer **ppLocalPlayer=0; +EQPlayer **ppControlledPlayer=0; +EQWorldData **ppWorldData=0; +SpellManager **ppSpellMgr=0; +EQPlayer **ppTarget=0; +EqSwitchManager **ppSwitchMgr=0; +EQItemList **ppItemList=0; +SPELLFAVORITE *pSpellSets=0; +EQZoneInfo *pZoneInfo=0; +AltAdvManager** ppAltAdvManager=0; +CONNECTION_T **ppConnection=0; +AURAMGR **ppAuraMgr=0; +EQCHATMGR **ppEQChatMgr=0; + +EQPlayer **ppTradeTarget=0; +EQPlayer **ppActiveBanker=0; +EQPlayer **ppActiveGMaster=0; +EQPlayer **ppActiveCorpse=0; + +/* WINDOW INSTANCES */ + +CContextMenuManager **ppContextMenuManager=0; +CCursorAttachment **ppCursorAttachment=0; +CSocialEditWnd **ppSocialEditWnd=0; +CContainerMgr **ppContainerMgr=0; +CChatManager **ppChatManager=0; +CFacePick **ppFacePick=0; +CInvSlotMgr **ppInvSlotMgr=0; +CNoteWnd **ppNoteWnd=0; +CTipWnd **ppTipWndOFDAY=0; +CTipWnd **ppTipWndCONTEXT=0; +CBookWnd **ppBookWnd=0; +CFriendsWnd **ppFriendsWnd=0; +CMusicPlayerWnd **ppMusicPlayerWnd=0; +CAlarmWnd **ppAlarmWnd=0; +CLoadskinWnd **ppLoadskinWnd=0; +CPetInfoWnd **ppPetInfoWnd=0; +CTrainWnd **ppTrainWnd=0; +CSkillsWnd **ppSkillsWnd=0; +CSkillsSelectWnd **ppSkillsSelectWnd=0; +CAAWnd **ppAAWnd=0; +CGroupWnd **ppGroupWnd=0; +CGroupSearchWnd **ppGroupSearchWnd=0; +CGroupSearchFiltersWnd **ppGroupSearchFiltersWnd=0; +CRaidWnd **ppRaidWnd=0; +CRaidOptionsWnd **ppRaidOptionsWnd=0; +CBreathWnd **ppBreathWnd=0; +CMapToolbarWnd **ppMapToolbarWnd=0; +CMapViewWnd **ppMapViewWnd=0; +CEditLabelWnd **ppEditLabelWnd=0; +COptionsWnd **ppOptionsWnd=0; +CBuffWindow **ppBuffWindowSHORT=0; +CBuffWindow **ppBuffWindowNORMAL=0; +CTargetWnd **ppTargetWnd=0; +CColorPickerWnd **ppColorPickerWnd=0; +CHotButtonWnd **ppHotButtonWnd=0; +CPlayerWnd **ppPlayerWnd=0; +CCastingWnd **ppCastingWnd=0; +CCastSpellWnd **ppCastSpellWnd=0; +CSpellBookWnd **ppSpellBookWnd=0; +CInventoryWnd **ppInventoryWnd=0; +CBankWnd **ppBankWnd=0; +CQuantityWnd **ppQuantityWnd=0; +CTextEntryWnd **ppTextEntryWnd=0; +CFileSelectionWnd **ppFileSelectionWnd=0; +CLootWnd **ppLootWnd=0; +CActionsWnd **ppActionsWnd=0; +CCombatAbilityWnd **ppCombatAbilityWnd=0; +CMerchantWnd **ppMerchantWnd=0; +CTradeWnd **ppTradeWnd=0; +CBazaarWnd **ppBazaarWnd=0; +CBazaarSearchWnd **ppBazaarSearchWnd=0; +CGiveWnd **ppGiveWnd=0; +CSelectorWnd **ppSelectorWnd=0; +CTrackingWnd **ppTrackingWnd=0; +CInspectWnd **ppInspectWnd=0; +CFeedbackWnd **ppFeedbackWnd=0; +CBugReportWnd **ppBugReportWnd=0; +CVideoModesWnd **ppVideoModesWnd=0; +CCompassWnd **ppCompassWnd=0; +CPlayerNotesWnd **ppPlayerNotesWnd=0; +CGemsGameWnd **ppGemsGameWnd=0; +CStoryWnd **ppStoryWnd=0; +CBodyTintWnd **ppBodyTintWnd=0; +CGuildMgmtWnd **ppGuildMgmtWnd=0; +CJournalTextWnd **ppJournalTextWnd=0; +CJournalCatWnd **ppJournalCatWnd=0; +CPetitionQWnd **ppPetitionQWnd=0; +CSoulmarkWnd **ppSoulmarkWnd=0; +CTimeLeftWnd **ppTimeLeftWnd=0; +CTextOverlay **ppTextOverlay=0; +CPotionBeltWnd **ppPotionBeltWnd=0; + +CSidlManager **ppSidlMgr=0; +CXWndManager **ppWndMgr=0; +KeypressHandler **ppKeypressHandler=0; +PEQRAID pRaid=0; +DZMEMBER **ppDZMember=0; +DZTIMERINFO **ppDZTimerInfo=0; +TASKMEMBER **ppTaskMember=0; +DYNAMICZONE *pDynamicZone=0; +MERCENARYINFO **ppMercInfo=0; +AGGROINFO **ppAggroInfo=0; + +#define INITIALIZE_EQGAME_OFFSET(var) DWORD var = (((DWORD)var##_x - 0x400000) + baseAddress) + +INITIALIZE_EQGAME_OFFSET(__ActualVersionDate); +INITIALIZE_EQGAME_OFFSET(__ActualVersionTime); +INITIALIZE_EQGAME_OFFSET(__MemChecker0); +INITIALIZE_EQGAME_OFFSET(__MemChecker1); +INITIALIZE_EQGAME_OFFSET(__MemChecker2); +INITIALIZE_EQGAME_OFFSET(__MemChecker3); +INITIALIZE_EQGAME_OFFSET(__MemChecker4); +INITIALIZE_EQGAME_OFFSET(__EncryptPad0); +INITIALIZE_EQGAME_OFFSET(__EncryptPad1); +INITIALIZE_EQGAME_OFFSET(__EncryptPad2); +INITIALIZE_EQGAME_OFFSET(__EncryptPad3); +INITIALIZE_EQGAME_OFFSET(__EncryptPad4); +INITIALIZE_EQGAME_OFFSET(__AC1); +INITIALIZE_EQGAME_OFFSET(__AC2); +INITIALIZE_EQGAME_OFFSET(__AC3); +INITIALIZE_EQGAME_OFFSET(__AC4); +INITIALIZE_EQGAME_OFFSET(__AC5); +INITIALIZE_EQGAME_OFFSET(__AC6); +INITIALIZE_EQGAME_OFFSET(__AC7); +INITIALIZE_EQGAME_OFFSET(DI8__Main); +INITIALIZE_EQGAME_OFFSET(DI8__Keyboard); +INITIALIZE_EQGAME_OFFSET(DI8__Mouse); +INITIALIZE_EQGAME_OFFSET(__AltTimerReady); +INITIALIZE_EQGAME_OFFSET(__Attack); +INITIALIZE_EQGAME_OFFSET(__Autofire); +INITIALIZE_EQGAME_OFFSET(__BindList); +INITIALIZE_EQGAME_OFFSET(__Clicks); +INITIALIZE_EQGAME_OFFSET(__CommandList); +INITIALIZE_EQGAME_OFFSET(__CurrentMapLabel); +INITIALIZE_EQGAME_OFFSET(__CurrentSocial); +INITIALIZE_EQGAME_OFFSET(__DoAbilityList); +INITIALIZE_EQGAME_OFFSET(__do_loot); +INITIALIZE_EQGAME_OFFSET(__DrawHandler); +INITIALIZE_EQGAME_OFFSET(__Guilds); +INITIALIZE_EQGAME_OFFSET(__gWorld); +INITIALIZE_EQGAME_OFFSET(__HotkeyPage); +INITIALIZE_EQGAME_OFFSET(__HWnd); +INITIALIZE_EQGAME_OFFSET(__InChatMode); +INITIALIZE_EQGAME_OFFSET(__LastTell); +INITIALIZE_EQGAME_OFFSET(__LMouseHeldTime); +INITIALIZE_EQGAME_OFFSET(__Mouse); +INITIALIZE_EQGAME_OFFSET(__MouseLook); +INITIALIZE_EQGAME_OFFSET(__MouseEventTime); +INITIALIZE_EQGAME_OFFSET(__NetStatusToggle); +INITIALIZE_EQGAME_OFFSET(__PCNames); +INITIALIZE_EQGAME_OFFSET(__RangeAttackReady); +INITIALIZE_EQGAME_OFFSET(__RMouseHeldTime); +INITIALIZE_EQGAME_OFFSET(__RunWalkState); +INITIALIZE_EQGAME_OFFSET(__ScreenMode); +INITIALIZE_EQGAME_OFFSET(__ScreenX); +INITIALIZE_EQGAME_OFFSET(__ScreenY); +INITIALIZE_EQGAME_OFFSET(__ScreenXMax); +INITIALIZE_EQGAME_OFFSET(__ScreenYMax); +INITIALIZE_EQGAME_OFFSET(__ServerHost); +INITIALIZE_EQGAME_OFFSET(__ServerName); +INITIALIZE_EQGAME_OFFSET(__ShiftKeyDown); +INITIALIZE_EQGAME_OFFSET(__ShowNames); +INITIALIZE_EQGAME_OFFSET(__Socials); + +INITIALIZE_EQGAME_OFFSET(instCRaid); +INITIALIZE_EQGAME_OFFSET(instEQZoneInfo); +INITIALIZE_EQGAME_OFFSET(instKeypressHandler); +INITIALIZE_EQGAME_OFFSET(pinstActiveBanker); +INITIALIZE_EQGAME_OFFSET(pinstActiveCorpse); +INITIALIZE_EQGAME_OFFSET(pinstActiveGMaster); +INITIALIZE_EQGAME_OFFSET(pinstActiveMerchant); +INITIALIZE_EQGAME_OFFSET(pinstAggroInfo); +INITIALIZE_EQGAME_OFFSET(pinstAltAdvManager); +INITIALIZE_EQGAME_OFFSET(pinstAuraMgr); +INITIALIZE_EQGAME_OFFSET(pinstBandageTarget); +INITIALIZE_EQGAME_OFFSET(pinstCamActor); +INITIALIZE_EQGAME_OFFSET(pinstCDBStr); +INITIALIZE_EQGAME_OFFSET(pinstCDisplay); +INITIALIZE_EQGAME_OFFSET(pinstCEverQuest); +INITIALIZE_EQGAME_OFFSET(pinstCharData); +INITIALIZE_EQGAME_OFFSET(pinstCharSpawn); +INITIALIZE_EQGAME_OFFSET(pinstControlledMissile); +INITIALIZE_EQGAME_OFFSET(pinstControlledPlayer); +INITIALIZE_EQGAME_OFFSET(pinstCSidlManager); +INITIALIZE_EQGAME_OFFSET(pinstCXWndManager); +INITIALIZE_EQGAME_OFFSET(instDynamicZone); +INITIALIZE_EQGAME_OFFSET(pinstDZMember); +INITIALIZE_EQGAME_OFFSET(pinstDZTimerInfo); +INITIALIZE_EQGAME_OFFSET(pinstEQItemList); +INITIALIZE_EQGAME_OFFSET(instEQMisc); +INITIALIZE_EQGAME_OFFSET(pinstEQSoundManager); +INITIALIZE_EQGAME_OFFSET(instExpeditionLeader); +INITIALIZE_EQGAME_OFFSET(instExpeditionName); +INITIALIZE_EQGAME_OFFSET(pinstGroup); +INITIALIZE_EQGAME_OFFSET(pinstImeManager); +INITIALIZE_EQGAME_OFFSET(pinstLocalPlayer); +INITIALIZE_EQGAME_OFFSET(pinstMercenaryData); +INITIALIZE_EQGAME_OFFSET(pinstModelPlayer); +INITIALIZE_EQGAME_OFFSET(pinstPCData); +INITIALIZE_EQGAME_OFFSET(pinstSkillMgr); +INITIALIZE_EQGAME_OFFSET(pinstSpawnManager); +INITIALIZE_EQGAME_OFFSET(pinstSpellManager); +INITIALIZE_EQGAME_OFFSET(pinstSpellSets); +INITIALIZE_EQGAME_OFFSET(pinstStringTable); +INITIALIZE_EQGAME_OFFSET(pinstSwitchManager); +INITIALIZE_EQGAME_OFFSET(pinstTarget); +INITIALIZE_EQGAME_OFFSET(pinstTargetObject); +INITIALIZE_EQGAME_OFFSET(pinstTargetSwitch); +INITIALIZE_EQGAME_OFFSET(pinstTaskMember); +INITIALIZE_EQGAME_OFFSET(pinstTrackTarget); +INITIALIZE_EQGAME_OFFSET(pinstTradeTarget); +INITIALIZE_EQGAME_OFFSET(instTributeActive); +INITIALIZE_EQGAME_OFFSET(pinstViewActor); +INITIALIZE_EQGAME_OFFSET(pinstWorldData); + +INITIALIZE_EQGAME_OFFSET(pinstCTextOverlay); +INITIALIZE_EQGAME_OFFSET(pinstCAudioTriggersWindow); +INITIALIZE_EQGAME_OFFSET(pinstCCharacterSelect); +INITIALIZE_EQGAME_OFFSET(pinstCFacePick); +INITIALIZE_EQGAME_OFFSET(pinstCNoteWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBookWnd); +INITIALIZE_EQGAME_OFFSET(pinstCPetInfoWnd); +INITIALIZE_EQGAME_OFFSET(pinstCTrainWnd); +INITIALIZE_EQGAME_OFFSET(pinstCSkillsWnd); +INITIALIZE_EQGAME_OFFSET(pinstCSkillsSelectWnd); +INITIALIZE_EQGAME_OFFSET(pinstCCombatSkillSelectWnd); +INITIALIZE_EQGAME_OFFSET(pinstCFriendsWnd); +INITIALIZE_EQGAME_OFFSET(pinstCAuraWnd); +INITIALIZE_EQGAME_OFFSET(pinstCRespawnWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBandolierWnd); +INITIALIZE_EQGAME_OFFSET(pinstCPotionBeltWnd); +INITIALIZE_EQGAME_OFFSET(pinstCAAWnd); +INITIALIZE_EQGAME_OFFSET(pinstCGroupSearchFiltersWnd); +INITIALIZE_EQGAME_OFFSET(pinstCLoadskinWnd); +INITIALIZE_EQGAME_OFFSET(pinstCAlarmWnd); +INITIALIZE_EQGAME_OFFSET(pinstCMusicPlayerWnd); +INITIALIZE_EQGAME_OFFSET(pinstCMailWnd); +INITIALIZE_EQGAME_OFFSET(pinstCMailCompositionWnd); +INITIALIZE_EQGAME_OFFSET(pinstCMailAddressBookWnd); +INITIALIZE_EQGAME_OFFSET(pinstCRaidWnd); +INITIALIZE_EQGAME_OFFSET(pinstCRaidOptionsWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBreathWnd); +INITIALIZE_EQGAME_OFFSET(pinstCMapViewWnd); +INITIALIZE_EQGAME_OFFSET(pinstCMapToolbarWnd); +INITIALIZE_EQGAME_OFFSET(pinstCEditLabelWnd); +INITIALIZE_EQGAME_OFFSET(pinstCTargetWnd); +INITIALIZE_EQGAME_OFFSET(pinstCColorPickerWnd); +INITIALIZE_EQGAME_OFFSET(pinstCPlayerWnd); +INITIALIZE_EQGAME_OFFSET(pinstCOptionsWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBuffWindowNORMAL); +INITIALIZE_EQGAME_OFFSET(pinstCBuffWindowSHORT); +INITIALIZE_EQGAME_OFFSET(pinstCharacterCreation); +INITIALIZE_EQGAME_OFFSET(pinstCCursorAttachment); +INITIALIZE_EQGAME_OFFSET(pinstCCastingWnd); +INITIALIZE_EQGAME_OFFSET(pinstCCastSpellWnd); +INITIALIZE_EQGAME_OFFSET(pinstCSpellBookWnd); +INITIALIZE_EQGAME_OFFSET(pinstCInventoryWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBankWnd); +INITIALIZE_EQGAME_OFFSET(pinstCQuantityWnd); +INITIALIZE_EQGAME_OFFSET(pinstCLootWnd); +INITIALIZE_EQGAME_OFFSET(pinstCActionsWnd); +INITIALIZE_EQGAME_OFFSET(pinstCCombatAbilityWnd); +INITIALIZE_EQGAME_OFFSET(pinstCMerchantWnd); +INITIALIZE_EQGAME_OFFSET(pinstCTradeWnd); +INITIALIZE_EQGAME_OFFSET(pinstCSelectorWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBazaarWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBazaarSearchWnd); +INITIALIZE_EQGAME_OFFSET(pinstCGiveWnd); +INITIALIZE_EQGAME_OFFSET(pinstCTrackingWnd); +INITIALIZE_EQGAME_OFFSET(pinstCInspectWnd); +INITIALIZE_EQGAME_OFFSET(pinstCSocialEditWnd); +INITIALIZE_EQGAME_OFFSET(pinstCFeedbackWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBugReportWnd); +INITIALIZE_EQGAME_OFFSET(pinstCVideoModesWnd); +INITIALIZE_EQGAME_OFFSET(pinstCTextEntryWnd); +INITIALIZE_EQGAME_OFFSET(pinstCFileSelectionWnd); +INITIALIZE_EQGAME_OFFSET(pinstCCompassWnd); +INITIALIZE_EQGAME_OFFSET(pinstCPlayerNotesWnd); +INITIALIZE_EQGAME_OFFSET(pinstCGemsGameWnd); +INITIALIZE_EQGAME_OFFSET(pinstCTimeLeftWnd); +INITIALIZE_EQGAME_OFFSET(pinstCPetitionQWnd); +INITIALIZE_EQGAME_OFFSET(pinstCSoulmarkWnd); +INITIALIZE_EQGAME_OFFSET(pinstCStoryWnd); +INITIALIZE_EQGAME_OFFSET(pinstCJournalTextWnd); +INITIALIZE_EQGAME_OFFSET(pinstCJournalCatWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBodyTintWnd); +INITIALIZE_EQGAME_OFFSET(pinstCServerListWnd); +INITIALIZE_EQGAME_OFFSET(pinstCAvaZoneWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBlockedBuffWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBlockedPetBuffWnd); +INITIALIZE_EQGAME_OFFSET(pinstCInvSlotMgr); +INITIALIZE_EQGAME_OFFSET(pinstCContainerMgr); +INITIALIZE_EQGAME_OFFSET(pinstCAdventureLeaderboardWnd); +INITIALIZE_EQGAME_OFFSET(pinstCAdventureRequestWnd); +INITIALIZE_EQGAME_OFFSET(pinstCAltStorageWnd); +INITIALIZE_EQGAME_OFFSET(pinstCAdventureStatsWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBarterMerchantWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBarterSearchWnd); +INITIALIZE_EQGAME_OFFSET(pinstCBarterWnd); +INITIALIZE_EQGAME_OFFSET(pinstCChatManager); +INITIALIZE_EQGAME_OFFSET(pinstCDynamicZoneWnd); +INITIALIZE_EQGAME_OFFSET(pinstCEQMainWnd); +INITIALIZE_EQGAME_OFFSET(pinstCFellowshipWnd); +INITIALIZE_EQGAME_OFFSET(pinstCFindLocationWnd); +INITIALIZE_EQGAME_OFFSET(pinstCGroupSearchWnd); +INITIALIZE_EQGAME_OFFSET(pinstCGroupWnd); +INITIALIZE_EQGAME_OFFSET(pinstCGuildBankWnd); +INITIALIZE_EQGAME_OFFSET(pinstCGuildMgmtWnd); +INITIALIZE_EQGAME_OFFSET(pinstCHotButtonWnd); +INITIALIZE_EQGAME_OFFSET(pinstCHotButtonWnd1); +INITIALIZE_EQGAME_OFFSET(pinstCHotButtonWnd2); +INITIALIZE_EQGAME_OFFSET(pinstCHotButtonWnd3); +INITIALIZE_EQGAME_OFFSET(pinstCHotButtonWnd4); +INITIALIZE_EQGAME_OFFSET(pinstCItemDisplayManager); +INITIALIZE_EQGAME_OFFSET(pinstCItemExpTransferWnd); +INITIALIZE_EQGAME_OFFSET(pinstCLFGuildWnd); +INITIALIZE_EQGAME_OFFSET(pinstCMIZoneSelectWnd); +INITIALIZE_EQGAME_OFFSET(pinstCConfirmationDialog); +INITIALIZE_EQGAME_OFFSET(pinstCPopupWndManager); +INITIALIZE_EQGAME_OFFSET(pinstCProgressionSelectionWnd); +INITIALIZE_EQGAME_OFFSET(pinstCPvPStatsWnd); +INITIALIZE_EQGAME_OFFSET(pinstCSystemInfoDialogBox); +INITIALIZE_EQGAME_OFFSET(pinstCTaskTemplateSelectWnd); +INITIALIZE_EQGAME_OFFSET(pinstCTipWndOFDAY); +INITIALIZE_EQGAME_OFFSET(pinstCTipWndCONTEXT); +INITIALIZE_EQGAME_OFFSET(pinstCTitleWnd); +INITIALIZE_EQGAME_OFFSET(pinstCContextMenuManager); +INITIALIZE_EQGAME_OFFSET(pinstCVoiceMacroWnd); +INITIALIZE_EQGAME_OFFSET(pinstCHtmlWnd); + +INITIALIZE_EQGAME_OFFSET(__CastRay); +INITIALIZE_EQGAME_OFFSET(__ConvertItemTags); +INITIALIZE_EQGAME_OFFSET(__ExecuteCmd); +INITIALIZE_EQGAME_OFFSET(__EQGetTime); +INITIALIZE_EQGAME_OFFSET(__get_melee_range); +INITIALIZE_EQGAME_OFFSET(__GetGaugeValueFromEQ); +INITIALIZE_EQGAME_OFFSET(__GetLabelFromEQ); +INITIALIZE_EQGAME_OFFSET(__GetXTargetType); +INITIALIZE_EQGAME_OFFSET(__LoadFrontEnd); +INITIALIZE_EQGAME_OFFSET(__NewUIINI); +INITIALIZE_EQGAME_OFFSET(__ProcessGameEvents); +INITIALIZE_EQGAME_OFFSET(CrashDetected); +INITIALIZE_EQGAME_OFFSET(DrawNetStatus); +INITIALIZE_EQGAME_OFFSET(Util__FastTime); +INITIALIZE_EQGAME_OFFSET(Expansion_HoT); + +INITIALIZE_EQGAME_OFFSET(AltAdvManager__GetCalculatedTimer); +INITIALIZE_EQGAME_OFFSET(AltAdvManager__IsAbilityReady); +INITIALIZE_EQGAME_OFFSET(AltAdvManager__GetAltAbility); + +INITIALIZE_EQGAME_OFFSET(CharacterZoneClient__HasSkill); + +INITIALIZE_EQGAME_OFFSET(CBankWnd__GetNumBankSlots); + +INITIALIZE_EQGAME_OFFSET(CBazaarSearchWnd__HandleBazaarMsg); + +INITIALIZE_EQGAME_OFFSET(CButtonWnd__SetCheck); + +INITIALIZE_EQGAME_OFFSET(CChatManager__GetRGBAFromIndex); +INITIALIZE_EQGAME_OFFSET(CChatManager__InitContextMenu); + +INITIALIZE_EQGAME_OFFSET(CChatService__GetNumberOfFriends); +INITIALIZE_EQGAME_OFFSET(CChatService__GetFriendName); + + +INITIALIZE_EQGAME_OFFSET(CRaces_AddModel); +INITIALIZE_EQGAME_OFFSET(CChatWindow__CChatWindow); +INITIALIZE_EQGAME_OFFSET(CChatWindow__Clear); +INITIALIZE_EQGAME_OFFSET(CChatWindow__WndNotification); + +INITIALIZE_EQGAME_OFFSET(CComboWnd__DeleteAll); +INITIALIZE_EQGAME_OFFSET(CComboWnd__Draw); +INITIALIZE_EQGAME_OFFSET(CComboWnd__GetCurChoice); +INITIALIZE_EQGAME_OFFSET(CComboWnd__GetListRect); +INITIALIZE_EQGAME_OFFSET(CComboWnd__GetTextRect); +INITIALIZE_EQGAME_OFFSET(CComboWnd__InsertChoice); +INITIALIZE_EQGAME_OFFSET(CComboWnd__SetColors); +INITIALIZE_EQGAME_OFFSET(CComboWnd__SetChoice); + +INITIALIZE_EQGAME_OFFSET(CContainerWnd__HandleCombine); +INITIALIZE_EQGAME_OFFSET(CContainerWnd__vftable); + +INITIALIZE_EQGAME_OFFSET(CDisplay__CleanGameUI); +INITIALIZE_EQGAME_OFFSET(CDisplay__GetClickedActor); +INITIALIZE_EQGAME_OFFSET(CDisplay__GetUserDefinedColor); +INITIALIZE_EQGAME_OFFSET(CDisplay__GetWorldFilePath); +INITIALIZE_EQGAME_OFFSET(CDisplay__is3dON); +INITIALIZE_EQGAME_OFFSET(CDisplay__ReloadUI); +INITIALIZE_EQGAME_OFFSET(CDisplay__WriteTextHD2); + +INITIALIZE_EQGAME_OFFSET(CEditBaseWnd__SetSel); + +INITIALIZE_EQGAME_OFFSET(CEditWnd__DrawCaret); +INITIALIZE_EQGAME_OFFSET(CEditWnd__GetCharIndexPt); +INITIALIZE_EQGAME_OFFSET(CEditWnd__GetDisplayString); +INITIALIZE_EQGAME_OFFSET(CEditWnd__GetHorzOffset); +INITIALIZE_EQGAME_OFFSET(CEditWnd__GetLineForPrintableChar); +INITIALIZE_EQGAME_OFFSET(CEditWnd__GetSelStartPt); +INITIALIZE_EQGAME_OFFSET(CEditWnd__GetSTMLSafeText); +INITIALIZE_EQGAME_OFFSET(CEditWnd__PointFromPrintableChar); +INITIALIZE_EQGAME_OFFSET(CEditWnd__SelectableCharFromPoint); +INITIALIZE_EQGAME_OFFSET(CEditWnd__SetEditable); + +INITIALIZE_EQGAME_OFFSET(CEverQuest__ClickedPlayer); +INITIALIZE_EQGAME_OFFSET(CEverQuest__DoTellWindow); +INITIALIZE_EQGAME_OFFSET(CEverQuest__DropHeldItemOnGround); +INITIALIZE_EQGAME_OFFSET(CEverQuest__dsp_chat); +INITIALIZE_EQGAME_OFFSET(CEverQuest__Emote); +INITIALIZE_EQGAME_OFFSET(CEverQuest__EnterZone); +INITIALIZE_EQGAME_OFFSET(CEverQuest__GetBodyTypeDesc); +INITIALIZE_EQGAME_OFFSET(CEverQuest__GetClassDesc); +INITIALIZE_EQGAME_OFFSET(CEverQuest__GetClassThreeLetterCode); +INITIALIZE_EQGAME_OFFSET(CEverQuest__GetDeityDesc); +INITIALIZE_EQGAME_OFFSET(CEverQuest__GetLangDesc); +INITIALIZE_EQGAME_OFFSET(CEverQuest__GetRaceDesc); +INITIALIZE_EQGAME_OFFSET(CEverQuest__InterpretCmd); +INITIALIZE_EQGAME_OFFSET(CEverQuest__LeftClickedOnPlayer); +INITIALIZE_EQGAME_OFFSET(CEverQuest__LMouseUp); +INITIALIZE_EQGAME_OFFSET(CEverQuest__RightClickedOnPlayer); +INITIALIZE_EQGAME_OFFSET(CEverQuest__RMouseUp); +INITIALIZE_EQGAME_OFFSET(CEverQuest__SetGameState); +INITIALIZE_EQGAME_OFFSET(CEverQuest__UPCNotificationFlush); + +INITIALIZE_EQGAME_OFFSET(CGaugeWnd__CalcFillRect); +INITIALIZE_EQGAME_OFFSET(CGaugeWnd__CalcLinesFillRect); +INITIALIZE_EQGAME_OFFSET(CGaugeWnd__Draw); + +INITIALIZE_EQGAME_OFFSET(CGuild__FindMemberByName); + +INITIALIZE_EQGAME_OFFSET(CHotButtonWnd__DoHotButton); + +INITIALIZE_EQGAME_OFFSET(CInvSlotMgr__FindInvSlot); +INITIALIZE_EQGAME_OFFSET(CInvSlotMgr__MoveItem); + +INITIALIZE_EQGAME_OFFSET(CInvSlot__HandleRButtonUp); +INITIALIZE_EQGAME_OFFSET(CInvSlot__SliderComplete); +INITIALIZE_EQGAME_OFFSET(CInvSlot__GetItemBase); + +INITIALIZE_EQGAME_OFFSET(CInvSlotWnd__DrawTooltip); + +INITIALIZE_EQGAME_OFFSET(CItemDisplayWnd__SetSpell); +INITIALIZE_EQGAME_OFFSET(CItemDisplayWnd__UpdateStrings); + +INITIALIZE_EQGAME_OFFSET(CLabel__Draw); + +INITIALIZE_EQGAME_OFFSET(CListWnd__AddColumn); +INITIALIZE_EQGAME_OFFSET(CListWnd__AddColumn1); +INITIALIZE_EQGAME_OFFSET(CListWnd__AddLine); +INITIALIZE_EQGAME_OFFSET(CListWnd__AddString); +INITIALIZE_EQGAME_OFFSET(CListWnd__CalculateFirstVisibleLine); +INITIALIZE_EQGAME_OFFSET(CListWnd__CalculateVSBRange); +INITIALIZE_EQGAME_OFFSET(CListWnd__ClearAllSel); +INITIALIZE_EQGAME_OFFSET(CListWnd__CloseAndUpdateEditWindow); +INITIALIZE_EQGAME_OFFSET(CListWnd__Compare); +INITIALIZE_EQGAME_OFFSET(CListWnd__Draw); +INITIALIZE_EQGAME_OFFSET(CListWnd__DrawColumnSeparators); +INITIALIZE_EQGAME_OFFSET(CListWnd__DrawHeader); +INITIALIZE_EQGAME_OFFSET(CListWnd__DrawItem); +INITIALIZE_EQGAME_OFFSET(CListWnd__DrawLine); +INITIALIZE_EQGAME_OFFSET(CListWnd__DrawSeparator); +INITIALIZE_EQGAME_OFFSET(CListWnd__EnsureVisible); +INITIALIZE_EQGAME_OFFSET(CListWnd__ExtendSel); +INITIALIZE_EQGAME_OFFSET(CListWnd__GetColumnMinWidth); +INITIALIZE_EQGAME_OFFSET(CListWnd__GetColumnWidth); +INITIALIZE_EQGAME_OFFSET(CListWnd__GetCurSel); +INITIALIZE_EQGAME_OFFSET(CListWnd__GetItemAtPoint); +INITIALIZE_EQGAME_OFFSET(CListWnd__GetItemAtPoint1); +INITIALIZE_EQGAME_OFFSET(CListWnd__GetItemData); +INITIALIZE_EQGAME_OFFSET(CListWnd__GetItemHeight); +INITIALIZE_EQGAME_OFFSET(CListWnd__GetItemIcon); +INITIALIZE_EQGAME_OFFSET(CListWnd__GetItemRect); +INITIALIZE_EQGAME_OFFSET(CListWnd__GetItemText); +INITIALIZE_EQGAME_OFFSET(CListWnd__GetSelList); +INITIALIZE_EQGAME_OFFSET(CListWnd__GetSeparatorRect); +INITIALIZE_EQGAME_OFFSET(CListWnd__RemoveLine); +INITIALIZE_EQGAME_OFFSET(CListWnd__SetColors); +INITIALIZE_EQGAME_OFFSET(CListWnd__SetColumnJustification); +INITIALIZE_EQGAME_OFFSET(CListWnd__SetColumnWidth); +INITIALIZE_EQGAME_OFFSET(CListWnd__SetCurSel); +INITIALIZE_EQGAME_OFFSET(CListWnd__SetItemColor); +INITIALIZE_EQGAME_OFFSET(CListWnd__SetItemData); +INITIALIZE_EQGAME_OFFSET(CListWnd__SetItemText); +INITIALIZE_EQGAME_OFFSET(CListWnd__ShiftColumnSeparator); +INITIALIZE_EQGAME_OFFSET(CListWnd__Sort); +INITIALIZE_EQGAME_OFFSET(CListWnd__ToggleSel); + +INITIALIZE_EQGAME_OFFSET(CMapViewWnd__CMapViewWnd); + +INITIALIZE_EQGAME_OFFSET(CMerchantWnd__DisplayBuyOrSellPrice); +INITIALIZE_EQGAME_OFFSET(CMerchantWnd__RequestBuyItem); +INITIALIZE_EQGAME_OFFSET(CMerchantWnd__RequestSellItem); +INITIALIZE_EQGAME_OFFSET(CMerchantWnd__SelectBuySellSlot); + +INITIALIZE_EQGAME_OFFSET(CObfuscator__doit); + +INITIALIZE_EQGAME_OFFSET(CSidlManager__FindScreenPieceTemplate1); +INITIALIZE_EQGAME_OFFSET(CSidlManager__CreateLabel); + +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__CalculateHSBRange); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__CalculateVSBRange); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__ConvertToRes); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__CreateChildrenFromSidl); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__CSidlScreenWnd1); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__CSidlScreenWnd2); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__dCSidlScreenWnd); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__DrawSidlPiece); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__EnableIniStorage); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__GetSidlPiece); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__Init1); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__LoadIniInfo); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__LoadIniListWnd); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__LoadSidlScreen); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__StoreIniInfo); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__StoreIniVis); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__WndNotification); +INITIALIZE_EQGAME_OFFSET(CSidlScreenWnd__GetChildItem); + +INITIALIZE_EQGAME_OFFSET(CSkillMgr__IsAvailable); +INITIALIZE_EQGAME_OFFSET(CSkillMgr__GetSkillCap); + +INITIALIZE_EQGAME_OFFSET(CSliderWnd__GetValue); +INITIALIZE_EQGAME_OFFSET(CSliderWnd__SetValue); +INITIALIZE_EQGAME_OFFSET(CSliderWnd__SetNumTicks); + +INITIALIZE_EQGAME_OFFSET(CSpellBookWnd__MemorizeSet); + +INITIALIZE_EQGAME_OFFSET(CStmlWnd__AppendSTML); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__CalculateHSBRange); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__CalculateVSBRange); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__CanBreakAtCharacter); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__FastForwardToEndOfTag); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__ForceParseNow); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__GetNextTagPiece); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__GetSTMLText); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__GetVisibleText); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__InitializeWindowVariables); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__MakeStmlColorTag); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__MakeWndNotificationTag); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__SetSTMLText); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__StripFirstSTMLLines); +INITIALIZE_EQGAME_OFFSET(CStmlWnd__UpdateHistoryString); + +INITIALIZE_EQGAME_OFFSET(CTabWnd__Draw); +INITIALIZE_EQGAME_OFFSET(CTabWnd__DrawCurrentPage); +INITIALIZE_EQGAME_OFFSET(CTabWnd__DrawTab); +INITIALIZE_EQGAME_OFFSET(CTabWnd__GetCurrentPage); +INITIALIZE_EQGAME_OFFSET(CTabWnd__GetPageInnerRect); +INITIALIZE_EQGAME_OFFSET(CTabWnd__GetTabInnerRect); +INITIALIZE_EQGAME_OFFSET(CTabWnd__GetTabRect); +INITIALIZE_EQGAME_OFFSET(CTabWnd__InsertPage); +INITIALIZE_EQGAME_OFFSET(CTabWnd__SetPage); +INITIALIZE_EQGAME_OFFSET(CTabWnd__SetPageRect); +INITIALIZE_EQGAME_OFFSET(CTabWnd__UpdatePage); + +INITIALIZE_EQGAME_OFFSET(CTextOverlay__DisplayText); + +INITIALIZE_EQGAME_OFFSET(CTextureFont__DrawWrappedText); + +INITIALIZE_EQGAME_OFFSET(CXMLDataManager__GetXMLData); + +INITIALIZE_EQGAME_OFFSET(CXMLSOMDocumentBase__XMLRead); + +INITIALIZE_EQGAME_OFFSET(CXStr__CXStr); +INITIALIZE_EQGAME_OFFSET(CXStr__CXStr1); +INITIALIZE_EQGAME_OFFSET(CXStr__CXStr3); +INITIALIZE_EQGAME_OFFSET(CXStr__dCXStr); +INITIALIZE_EQGAME_OFFSET(CXStr__operator_equal); +INITIALIZE_EQGAME_OFFSET(CXStr__operator_equal1); +INITIALIZE_EQGAME_OFFSET(CXStr__operator_plus_equal1); + +INITIALIZE_EQGAME_OFFSET(CXWnd__BringToTop); +INITIALIZE_EQGAME_OFFSET(CXWnd__Center); +INITIALIZE_EQGAME_OFFSET(CXWnd__ClrFocus); +INITIALIZE_EQGAME_OFFSET(CXWnd__DoAllDrawing); +INITIALIZE_EQGAME_OFFSET(CXWnd__DrawChildren); +INITIALIZE_EQGAME_OFFSET(CXWnd__DrawColoredRect); +INITIALIZE_EQGAME_OFFSET(CXWnd__DrawTooltip); +INITIALIZE_EQGAME_OFFSET(CXWnd__DrawTooltipAtPoint); +INITIALIZE_EQGAME_OFFSET(CXWnd__GetBorderFrame); +INITIALIZE_EQGAME_OFFSET(CXWnd__GetChildWndAt); +INITIALIZE_EQGAME_OFFSET(CXWnd__GetClientClipRect); +INITIALIZE_EQGAME_OFFSET(CXWnd__GetScreenClipRect); +INITIALIZE_EQGAME_OFFSET(CXWnd__GetScreenRect); +INITIALIZE_EQGAME_OFFSET(CXWnd__GetTooltipRect); +INITIALIZE_EQGAME_OFFSET(CXWnd__GetWindowTextA); +INITIALIZE_EQGAME_OFFSET(CXWnd__IsActive); +INITIALIZE_EQGAME_OFFSET(CXWnd__IsDescendantOf); +INITIALIZE_EQGAME_OFFSET(CXWnd__IsReallyVisible); +INITIALIZE_EQGAME_OFFSET(CXWnd__IsType); +INITIALIZE_EQGAME_OFFSET(CXWnd__Move); +INITIALIZE_EQGAME_OFFSET(CXWnd__Move1); +INITIALIZE_EQGAME_OFFSET(CXWnd__ProcessTransition); +INITIALIZE_EQGAME_OFFSET(CXWnd__Refade); +INITIALIZE_EQGAME_OFFSET(CXWnd__Resize); +INITIALIZE_EQGAME_OFFSET(CXWnd__Right); +INITIALIZE_EQGAME_OFFSET(CXWnd__SetFocus); +INITIALIZE_EQGAME_OFFSET(CXWnd__SetFont); +INITIALIZE_EQGAME_OFFSET(CXWnd__SetKeyTooltip); +INITIALIZE_EQGAME_OFFSET(CXWnd__SetMouseOver); +INITIALIZE_EQGAME_OFFSET(CXWnd__StartFade); +INITIALIZE_EQGAME_OFFSET(CXWnd__GetChildItem); + +INITIALIZE_EQGAME_OFFSET(CXWndManager__DrawCursor); +INITIALIZE_EQGAME_OFFSET(CXWndManager__DrawWindows); +INITIALIZE_EQGAME_OFFSET(CXWndManager__GetKeyboardFlags); +INITIALIZE_EQGAME_OFFSET(CXWndManager__HandleKeyboardMsg); +INITIALIZE_EQGAME_OFFSET(CXWndManager__RemoveWnd); + +INITIALIZE_EQGAME_OFFSET(CDBStr__GetString); + +INITIALIZE_EQGAME_OFFSET(EQ_Character__CastRay); +INITIALIZE_EQGAME_OFFSET(EQ_Character__CastSpell); +INITIALIZE_EQGAME_OFFSET(EQ_Character__Cur_HP); +INITIALIZE_EQGAME_OFFSET(EQ_Character__GetAACastingTimeModifier); +INITIALIZE_EQGAME_OFFSET(EQ_Character__GetCharInfo2); +INITIALIZE_EQGAME_OFFSET(EQ_Character__GetFocusCastingTimeModifier); +INITIALIZE_EQGAME_OFFSET(EQ_Character__GetFocusRangeModifier); +INITIALIZE_EQGAME_OFFSET(EQ_Character__Max_Endurance); +INITIALIZE_EQGAME_OFFSET(EQ_Character__Max_HP); +INITIALIZE_EQGAME_OFFSET(EQ_Character__Max_Mana); +INITIALIZE_EQGAME_OFFSET(EQ_Character__doCombatAbility); +INITIALIZE_EQGAME_OFFSET(EQ_Character__UseSkill); +INITIALIZE_EQGAME_OFFSET(EQ_Character__GetConLevel); +INITIALIZE_EQGAME_OFFSET(EQ_Character__IsExpansionFlag); +INITIALIZE_EQGAME_OFFSET(EQ_Character__TotalEffect); + +INITIALIZE_EQGAME_OFFSET(EQ_Item__CanDrop); +INITIALIZE_EQGAME_OFFSET(EQ_Item__CreateItemTagString); +INITIALIZE_EQGAME_OFFSET(EQ_Item__IsStackable); + +INITIALIZE_EQGAME_OFFSET(EQ_LoadingS__SetProgressBar); +INITIALIZE_EQGAME_OFFSET(EQ_LoadingS__Array); + +INITIALIZE_EQGAME_OFFSET(EQ_PC__DestroyHeldItemOrMoney); +INITIALIZE_EQGAME_OFFSET(EQ_PC__GetAltAbilityIndex); +INITIALIZE_EQGAME_OFFSET(EQ_PC__GetCombatAbility); +INITIALIZE_EQGAME_OFFSET(EQ_PC__GetCombatAbilityTimer); +INITIALIZE_EQGAME_OFFSET(EQ_PC__GetItemTimerValue); +INITIALIZE_EQGAME_OFFSET(EQ_PC__HasLoreItem); + +INITIALIZE_EQGAME_OFFSET(EQItemList__EQItemList); +INITIALIZE_EQGAME_OFFSET(EQItemList__add_item); +INITIALIZE_EQGAME_OFFSET(EQItemList__delete_item); +INITIALIZE_EQGAME_OFFSET(EQItemList__FreeItemList); + +INITIALIZE_EQGAME_OFFSET(EQMisc__GetActiveFavorCost); + +INITIALIZE_EQGAME_OFFSET(EQPlayer__ChangeBoneStringSprite); +INITIALIZE_EQGAME_OFFSET(EQPlayer__dEQPlayer); +INITIALIZE_EQGAME_OFFSET(EQPlayer__DoAttack); +INITIALIZE_EQGAME_OFFSET(EQPlayer__EQPlayer); +INITIALIZE_EQGAME_OFFSET(EQPlayer__SetNameSpriteState); +INITIALIZE_EQGAME_OFFSET(EQPlayer__SetNameSpriteTint); +INITIALIZE_EQGAME_OFFSET(EQPlayer__IsBodyType_j); +INITIALIZE_EQGAME_OFFSET(EQPlayer__IsTargetable); + +INITIALIZE_EQGAME_OFFSET(EQPlayerManager__GetSpawnByID); +INITIALIZE_EQGAME_OFFSET(EQPlayerManager__GetSpawnByName); + +INITIALIZE_EQGAME_OFFSET(KeypressHandler__AttachAltKeyToEqCommand); +INITIALIZE_EQGAME_OFFSET(KeypressHandler__AttachKeyToEqCommand); +INITIALIZE_EQGAME_OFFSET(KeypressHandler__ClearCommandStateArray); +INITIALIZE_EQGAME_OFFSET(KeypressHandler__HandleKeyDown); +INITIALIZE_EQGAME_OFFSET(KeypressHandler__HandleKeyUp); +INITIALIZE_EQGAME_OFFSET(KeypressHandler__SaveKeymapping); + +INITIALIZE_EQGAME_OFFSET(MapViewMap__Clear); +INITIALIZE_EQGAME_OFFSET(MapViewMap__SaveEx); + +INITIALIZE_EQGAME_OFFSET(PlayerPointManager__GetAltCurrency); + +INITIALIZE_EQGAME_OFFSET(StringTable__getString); + +INITIALIZE_EQGAME_OFFSET(PcZoneClient__GetPcSkillLimit); +}; diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2Globals.h b/client_files/native_autoloot/eq-core-dll/src/MQ2Globals.h new file mode 100644 index 0000000000..6fe0d0815a --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2Globals.h @@ -0,0 +1,1208 @@ +/***************************************************************************** + MQ2Main.dll: MacroQuest2's extension DLL for EverQuest + Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +******************************************************************************/ + +namespace MQ2Globals +{ +bool InitOffsets(); + +EQLIB_VAR DWORD baseAddress; +EQLIB_VAR DWORD eqGraphicsAddress; +EQLIB_VAR DWORD eqMainAddress; + +/* BENCHMARK HANDLES */ + +EQLIB_API DWORD bmWriteChatColor; +EQLIB_API DWORD bmPluginsIncomingChat; +EQLIB_API DWORD bmPluginsPulse; +EQLIB_API DWORD bmPluginsOnZoned; +EQLIB_API DWORD bmPluginsCleanUI; +EQLIB_API DWORD bmPluginsReloadUI; +EQLIB_API DWORD bmPluginsDrawHUD; +EQLIB_API DWORD bmPluginsSetGameState; +EQLIB_API DWORD bmParseMacroParameter; +EQLIB_API DWORD bmUpdateSpawnSort; +EQLIB_API DWORD bmUpdateSpawnCaptions; +EQLIB_API DWORD bmCalculate; +EQLIB_API DWORD bmBeginZone; +EQLIB_API DWORD bmEndZone; + +/* OTHER */ + +#ifndef ISXEQ +LEGACY_VAR PDATAVAR pGlobalVariables; +LEGACY_VAR PDATAVAR pMacroVariables; +#endif + +EQLIB_VAR BOOL bAllErrorsFatal; +EQLIB_VAR BOOL bAllErrorsDumpStack; +EQLIB_VAR BOOL bAllErrorsLog; +EQLIB_API CHAR DataTypeTemp[MAX_STRING]; + +EQLIB_API CHAR gszVersion[32]; + + +EQLIB_API DWORD gGameState; +EQLIB_API ePVPServer PVPServer; + +EQLIB_VAR BOOL g_Loaded; +EQLIB_VAR DWORD ThreadID; + +EQLIB_VAR BOOL gStringTableFixed; +EQLIB_VAR DWORD gMaxSpawnCaptions; +EQLIB_VAR BOOL gMQCaptions; + +EQLIB_VAR HMODULE ghModule; +EQLIB_VAR HINSTANCE ghInstance; +EQLIB_VAR BOOL gbEQWLoaded; +//EQLIB_VAR PHOTKEY pHotkey; +EQLIB_VAR BOOL gbUnload; +EQLIB_VAR DWORD gpHook; +#ifndef ISXEQ +LEGACY_VAR PMACROBLOCK gMacroBlock; +LEGACY_VAR PMACROSTACK gMacroStack; +LEGACY_VAR map gMacroSubLookupMap; +LEGACY_VAR PEVENTQUEUE gEventQueue; +LEGACY_VAR PMACROBLOCK gEventFunc[NUM_EVENTS]; +#endif +EQLIB_VAR UCHAR gLastFind; +EQLIB_VAR BOOL gInClick; +EQLIB_VAR DOUBLE gZFilter; +EQLIB_VAR DOUBLE gFaceAngle; +EQLIB_VAR DOUBLE gLookAngle; +EQLIB_VAR CHAR gszEQPath[MAX_STRING]; +EQLIB_VAR CHAR gszMacroPath[MAX_STRING]; +EQLIB_VAR CHAR gszLogPath[MAX_STRING]; +EQLIB_VAR CHAR gszINIPath[MAX_STRING]; +EQLIB_VAR CHAR gszINIFilename[MAX_STRING]; +EQLIB_VAR CHAR gszItemDB[MAX_STRING]; +EQLIB_VAR CHAR gszMacroName[MAX_STRING]; +EQLIB_VAR CHAR szLastCommand[MAX_STRING]; + +EQLIB_VAR CHAR gszLastNormalError[MAX_STRING];// QUIT USING THIS DIRECTLY, USE MacroError, FatalError, ETC +EQLIB_VAR CHAR gszLastSyntaxError[MAX_STRING]; +EQLIB_VAR CHAR gszLastMQ2DataError[MAX_STRING]; + +EQLIB_VAR PSPAWNINFO pNamingSpawn; +EQLIB_VAR CHAR gszSpawnNPCName[MAX_STRING]; +EQLIB_VAR CHAR gszSpawnPlayerName[7][MAX_STRING]; +EQLIB_VAR CHAR gszSpawnPetName[MAX_STRING]; +EQLIB_VAR CHAR gszSpawnCorpseName[MAX_STRING]; + +EQLIB_VAR DWORD DrawHUDParams[4]; + +EQLIB_VAR DWORD gEventChat; +EQLIB_VAR DWORD gRunning; +EQLIB_VAR BOOL gbMoving; +EQLIB_VAR DWORD gMaxTurbo; +EQLIB_VAR BOOL gReturn; + +EQLIB_VAR PCHATBUF gDelayedCommands; + +EQLIB_VAR BOOL gbInZone; +EQLIB_VAR BOOL gZoning; +EQLIB_VAR BOOL WereWeZoning; +EQLIB_VAR BOOL gbInDInput; +EQLIB_VAR BOOL gbInDState; +EQLIB_VAR BOOL gbInDAcquire; +EQLIB_VAR BOOL gbInChat; +EQLIB_VAR BOOL gFilterSkillsAll; +EQLIB_VAR BOOL gFilterSkillsIncrease; +EQLIB_VAR BOOL gFilterTarget; +EQLIB_VAR BOOL gFilterDebug; +EQLIB_VAR BOOL gFilterMoney; +EQLIB_VAR BOOL gFilterFood; +//EQLIB_VAR DWORD gUseMQChatWnd; +EQLIB_VAR BOOL gFilterMQ; +EQLIB_VAR BOOL gFilterMacro; +EQLIB_VAR BOOL gFilterEncumber; +EQLIB_VAR BOOL gFilterCustom; +EQLIB_VAR BOOL gSpewToFile; +EQLIB_VAR BOOL gbDoAutoRun; +EQLIB_VAR BOOL gMQPauseOnChat; +EQLIB_VAR BOOL gKeepKeys; +EQLIB_VAR BOOL gLClickedObject; +EQLIB_VAR SWHOFILTER gFilterSWho; + +EQLIB_VAR BOOL gbHUDUnderUI; +EQLIB_VAR BOOL gbAlwaysDrawMQHUD; + +EQLIB_VAR BOOL gFilterMQ2DataErrors; + +EQLIB_VAR DOUBLE DegToRad; +EQLIB_VAR DOUBLE PI; +#define ZoneShift 0 + +#ifndef ISXEQ +LEGACY_VAR Blech *pMQ2Blech; +LEGACY_VAR CHAR EventMsg[MAX_STRING]; +#ifdef USEBLECHEVENTS +LEGACY_VAR Blech *pEventBlech; +#endif +LEGACY_VAR PEVENTLIST pEventList; +#endif + +//EQLIB_VAR PKEYPRESS gKeyStack; +EQLIB_VAR PMQTIMER gTimer; +EQLIB_VAR LONG gDelay; +EQLIB_VAR CHAR gDelayCondition[MAX_STRING]; +EQLIB_VAR PALERTLIST gpAlertList; +EQLIB_VAR BOOL gMacroPause; +EQLIB_VAR SPAWNINFO EnviroTarget; +EQLIB_VAR PGROUNDITEM pGroundTarget; +EQLIB_VAR SPAWNINFO DoorEnviroTarget; +EQLIB_VAR PDOOR pDoorTarget; +EQLIB_VAR PITEMDB gItemDB; +EQLIB_VAR BOOL bRunNextCommand; +EQLIB_VAR BOOL bAllowCommandParse; +EQLIB_VAR BOOL gTurbo; +EQLIB_VAR PDEFINE pDefines; +//EQLIB_VAR CHAR gLastFindSlot[MAX_STRING]; +//EQLIB_VAR CHAR gLastError[MAX_STRING]; +//EQLIB_VAR HWND ghWnd; +EQLIB_VAR PFILTER gpFilters; + +EQLIB_VAR map ItemSlotMap; + +EQLIB_VAR BOOL g_bInDXMouse; +EQLIB_VAR PMOUSESPOOF gMouseData; + +EQLIB_VAR DIKEYID gDiKeyID[]; +EQLIB_VAR PCHAR gDiKeyName[256]; + + +EQLIB_VAR DWORD ManaGained; +EQLIB_VAR DWORD HealthGained; +EQLIB_VAR DWORD EnduranceGained; + +EQLIB_VAR DWORD gGameState; +EQLIB_VAR BOOL gbMQ2LoadingMsg; +EQLIB_VAR BOOL gbExactSearchCleanNames; + +EQLIB_VAR DWORD EQADDR_CONVERTITEMTAGS; + +EQLIB_VAR DWORD EQADDR_MEMCHECK0; +EQLIB_VAR DWORD EQADDR_MEMCHECK1; +EQLIB_VAR DWORD EQADDR_MEMCHECK2; +EQLIB_VAR DWORD EQADDR_MEMCHECK3; +EQLIB_VAR DWORD EQADDR_MEMCHECK4; +EQLIB_VAR PCHAR EQADDR_SERVERHOST; +EQLIB_VAR PCHAR EQADDR_SERVERNAME; +EQLIB_VAR DWORD EQADDR_HWND; + +EQLIB_VAR _SKILLMGR **ppSkillMgr; +#define pSkillMgr (*ppSkillMgr) + +EQLIB_VAR PCMDLIST EQADDR_CMDLIST; + +EQLIB_VAR PBYTE EQADDR_ATTACK; +EQLIB_VAR PBYTE EQADDR_NOTINCHATMODE; +EQLIB_VAR PBYTE EQADDR_RUNWALKSTATE; +EQLIB_VAR PCHAR EQADDR_LASTTELL; +EQLIB_VAR PVOID EQADDR_GWORLD; +EQLIB_VAR PDWORD EQADDR_DOABILITYLIST; +//EQLIB_VAR PBYTE EQADDR_DOABILITYAVAILABLE; +EQLIB_VAR PBYTE pTributeActive; + +EQLIB_VAR PBYTE EQADDR_ENCRYPTPAD0; +EQLIB_VAR PBYTE EQADDR_ENCRYPTPAD1; +EQLIB_VAR PBYTE EQADDR_ENCRYPTPAD2; +EQLIB_VAR PBYTE EQADDR_ENCRYPTPAD3; +EQLIB_VAR PBYTE EQADDR_ENCRYPTPAD4; + +EQLIB_VAR PMOUSEINFO EQADDR_MOUSE; +EQLIB_VAR PMOUSECLICK EQADDR_MOUSECLICK; + +EQLIB_VAR PMAPLABEL *ppCurrentMapLabel; +#define pCurrentMapLabel (*ppCurrentMapLabel) + +EQLIB_VAR PCHAR gpbRangedAttackReady; +#define gbRangedAttackReady (*gpbRangedAttackReady) +EQLIB_VAR PCHAR gpbAltTimerReady; +#define gbAltTimerReady (*gpbAltTimerReady) +EQLIB_VAR PCHAR gpbShowNetStatus; +#define gbShowNetStatus (*gpbShowNetStatus) +EQLIB_VAR DWORD *gpShowNames; +#define gShowNames (*gpShowNames) +EQLIB_VAR DWORD *gpPCNames; +#define gPCNames (*gpPCNames) +EQLIB_VAR PBYTE gpAutoFire; +#define gAutoFire (*gpAutoFire) +EQLIB_VAR PBYTE gpShiftKeyDown; +#define gShiftKeyDown (*gpShiftKeyDown) +EQLIB_VAR DWORD *gpMouseEventTime; +#define gMouseEventTime (*gpMouseEventTime) + +EQLIB_VAR DWORD *g_ppDrawHandler; +#define g_pDrawHandler (*g_ppDrawHandler) + +EQLIB_VAR PCHAR *EQMappableCommandList; +EQLIB_VAR DWORD gnNormalEQMappableCommands; + +#ifndef ISXEQ +EQLIB_VAR DWORD EQADDR_DIMAIN; +EQLIB_VAR IDirectInputDevice8A **EQADDR_DIKEYBOARD; +EQLIB_VAR IDirectInputDevice8A **EQADDR_DIMOUSE; +#endif + +EQLIB_VAR DWORD EQADDR_EQLABELS; + +EQLIB_VAR BOOL gMouseClickInProgress[8]; +EQLIB_VAR BOOL bDetMouse; + +// *************************************************************************** +// String arrays +// *************************************************************************** +EQLIB_VAR PCHAR szEQMappableCommands[nEQMappableCommands]; + +EQLIB_VAR PCHAR szHeading[]; +EQLIB_VAR PCHAR szHeadingShort[]; +EQLIB_VAR PCHAR szHeadingNormal[]; +EQLIB_VAR PCHAR szHeadingNormalShort[]; +EQLIB_VAR PCHAR szSize[]; +EQLIB_VAR PCHAR szSpawnType[]; +EQLIB_VAR PCHAR szGuildStatus[]; +EQLIB_VAR PCHAR szGender[]; +EQLIB_VAR PCHAR szDeityTeam[]; +EQLIB_VAR PCHAR szLights[]; +EQLIB_VAR BYTE LightBrightness[]; +EQLIB_VAR PCHAR szSkills[]; +EQLIB_VAR PCHAR szInnates[]; +EQLIB_VAR PCHAR szCombineTypes[]; +EQLIB_VAR PCHAR szItemTypes[]; + +EQLIB_VAR PCHAR szWornLoc[]; + + +EQLIB_VAR fEQCommand cmdHelp; +EQLIB_VAR fEQCommand cmdWho; +EQLIB_VAR fEQCommand cmdWhoTarget; +EQLIB_VAR fEQCommand cmdLocation; +EQLIB_VAR fEQCommand cmdFace; +EQLIB_VAR fEQCommand cmdTarget; +EQLIB_VAR fEQCommand cmdCharInfo; +EQLIB_VAR fEQCommand cmdFilter; +EQLIB_VAR fEQCommand cmdDoAbility; +EQLIB_VAR fEQCommand cmdCast; + + +EQLIB_VAR fEQNewUIINI NewUIINI; +EQLIB_VAR fEQProcGameEvts ProcessGameEvents; +EQLIB_VAR fEQExecuteCmd ExecuteCmd; +EQLIB_VAR fEQGetMelee get_melee_range; + +EQLIB_VAR PCHAR szItemName[]; +EQLIB_VAR PCHAR szItemName4xx[]; +EQLIB_VAR ACTORDEFENTRY ActorDefList[]; +//EQLIB_VAR PCHAR szTheme[]; +EQLIB_VAR PCHAR szDmgBonusType[]; +EQLIB_VAR PCHAR szBodyType[]; +EQLIB_VAR PCHAR szAugRestrictions[]; +EQLIB_VAR PCHAR szItemSlot[]; +EQLIB_VAR PCHAR szExpansions[]; + +EQLIB_VAR BOOL bLaxColor; +EQLIB_VAR PCHAR szColorAdjective[]; +EQLIB_VAR PCHAR szColorAdjectiveYou[]; +EQLIB_VAR PCHAR szColorExpletive[]; +EQLIB_VAR PCHAR szColorSyntaxError[]; +EQLIB_VAR PCHAR szColorMacroError[]; +EQLIB_VAR PCHAR szColorMQ2DataError[]; +EQLIB_VAR PCHAR szColorFatalError[]; +EQLIB_VAR DWORD nColorAdjective; +EQLIB_VAR DWORD nColorAdjectiveYou; +EQLIB_VAR DWORD nColorExpletive; +EQLIB_VAR DWORD nColorSyntaxError; +EQLIB_VAR DWORD nColorMacroError; +EQLIB_VAR DWORD nColorMQ2DataError; +EQLIB_VAR DWORD nColorFatalError; + +EQLIB_VAR PALIAS pAliases; +EQLIB_VAR PSUB pSubs; +EQLIB_VAR PMQCOMMAND pCommands; +EQLIB_VAR PMQPLUGIN pPlugins; +EQLIB_VAR PMQXMLFILE pXMLFiles; + +EQLIB_VAR fGetLabelFromEQ GetLabelFromEQ; + +EQLIB_VAR map SpawnByName; +//EQLIB_VAR EQPlayer **ppEQP_IDArray; +EQLIB_VAR MQRANK EQP_DistArray[3000]; +EQLIB_VAR DWORD gSpawnCount; +//#define ppEQP_IDArray (*pppEQP_IDArray) + +EQLIB_VAR StringTable **ppStringTable; +#define pStringTable (*ppStringTable) + +EQLIB_VAR CDBStr **ppCDBStr; +#define pCDBStr (*ppCDBStr) +EQLIB_VAR EQMisc *pEQMisc; +EQLIB_VAR CSkillMgr **ppCSkillMgr; +#define pCSkillMgr (*ppCSkillMgr) +EQLIB_VAR CGuild *pGuild; + +EQLIB_VAR CEverQuest **ppEverQuest; +#define pEverQuest (*ppEverQuest) +EQLIB_VAR CDisplay **ppDisplay; +#define pDisplay (*ppDisplay) +EQLIB_VAR EQ_PC **ppPCData; +#define pPCData (*ppPCData) +EQLIB_VAR EQ_Character **ppCharData; +#define pCharData (*ppCharData) +#define pCharData1 ((EQ_Character1 *)&GetCharInfo()->vtable2) +EQLIB_VAR EQPlayer **ppCharSpawn; +#define pCharSpawn (*ppCharSpawn) +EQLIB_VAR EQPlayer **ppActiveMerchant; +#define pActiveMerchant (*ppActiveMerchant) +EQLIB_VAR EQPlayerManager **ppSpawnManager; +#define pSpawnManager (*ppSpawnManager) +#define pSpawnList (((struct _SPAWNMANAGER *)pSpawnManager)->FirstSpawn) +#define pChatService ((CChatService*)((PEVERQUEST)pEverQuest)->ChatService) +#define pPlayerPointManager ((PlayerPointManager*)&GetCharInfo()->PlayerPointManager) + +EQLIB_VAR EQPlayer **ppLocalPlayer; +#define pLocalPlayer (*ppLocalPlayer) +EQLIB_VAR EQPlayer **ppControlledPlayer; +#define pControlledPlayer (*ppControlledPlayer) + + + +EQLIB_VAR EQWorldData **ppWorldData; +#define pWorldData (*ppWorldData) +EQLIB_VAR SpellManager **ppSpellMgr; +#define pSpellMgr (*ppSpellMgr) +EQLIB_VAR EQPlayer **ppTarget; +#define pTarget (*ppTarget) +EQLIB_VAR EqSwitchManager **ppSwitchMgr; +#define pSwitchMgr (*ppSwitchMgr) +EQLIB_VAR EQItemList **ppItemList; +#define pItemList (*ppItemList) +EQLIB_VAR EQZoneInfo *pZoneInfo; +EQLIB_VAR PGUILDS pGuildList; +EQLIB_VAR PEQSOCIAL pSocialList; + +EQLIB_VAR PBYTE pgHotkeyPage; +#define gHotkeyPage (*pgHotkeyPage) + +EQLIB_VAR EQPlayer **ppTradeTarget; +#define pTradeTarget (*ppTradeTarget) +EQLIB_VAR EQPlayer **ppActiveBanker; +#define pActiveBanker (*ppActiveBanker) +EQLIB_VAR EQPlayer **ppActiveGMaster; +#define pActiveGMaster (*ppActiveGMaster) +EQLIB_VAR EQPlayer **ppActiveCorpse; +#define pActiveCorpse (*ppActiveCorpse) + +EQLIB_VAR CSidlManager **ppSidlMgr; +#define pSidlMgr (*ppSidlMgr) + +EQLIB_VAR CXWndManager **ppWndMgr; +#define pWndMgr (*ppWndMgr) + +EQLIB_VAR KeypressHandler **ppKeypressHandler; +#define pKeypressHandler (*ppKeypressHandler) + +EQLIB_VAR PEQRAID pRaid; +EQLIB_VAR DZMEMBER **ppDZMember; +EQLIB_VAR TASKMEMBER **ppTaskMember; +EQLIB_VAR DZTIMERINFO **ppDZTimerInfo; +EQLIB_VAR DYNAMICZONE *pDynamicZone; + +EQLIB_VAR PINT pgCurrentSocial; +#define gCurrentSocial (*pgCurrentSocial) + +EQLIB_VAR DWORD *pScreenX; +#define ScreenX (*pScreenX) +EQLIB_VAR DWORD *pScreenY; +#define ScreenY (*pScreenY) +EQLIB_VAR DWORD *pScreenXMax; +#define ScreenXMax (*pScreenXMax) +EQLIB_VAR DWORD *pScreenYMax; +#define ScreenYMax (*pScreenYMax) +EQLIB_VAR DWORD *pScreenMode; +#define ScreenMode (*pScreenMode) +EQLIB_VAR CHAR *pMouseLook; +#define bMouseLook (*pMouseLook) + +EQLIB_VAR SPELLFAVORITE *pSpellSets; +EQLIB_VAR AltAdvManager** ppAltAdvManager; +#define pAltAdvManager (*ppAltAdvManager) + +EQLIB_VAR PCONNECTION_T *ppConnection; +#define pConnection (*ppConnection) +EQLIB_VAR AURAMGR **ppAuraMgr; +#define pAuraMgr (*ppAuraMgr) + +EQLIB_VAR EQCHATMGR **ppEQChatMgr; +#define pChatMgr (*ppEQChatMgr) + +EQLIB_VAR MERCENARYINFO **ppMercInfo; +#define pMercInfo (*ppMercInfo) + +EQLIB_VAR AGGROINFO **ppAggroInfo; +#define pAggroInfo (*ppAggroInfo) + +/* WINDOW INSTANCES */ +EQLIB_VAR CContextMenuManager **ppContextMenuManager; +EQLIB_VAR CCursorAttachment **ppCursorAttachment; +EQLIB_VAR CSocialEditWnd **ppSocialEditWnd; +EQLIB_VAR CContainerMgr **ppContainerMgr; +EQLIB_VAR CChatManager **ppChatManager; +EQLIB_VAR CConfirmationDialog **ppConfirmationDialog; +EQLIB_VAR CFacePick **ppFacePick; +EQLIB_VAR CInvSlotMgr **ppInvSlotMgr; +//EQLIB_VAR CPopupWndManager **ppPopupWndManager; +EQLIB_VAR CNoteWnd **ppNoteWnd; +EQLIB_VAR CHelpWnd **ppHelpWnd; +EQLIB_VAR CTipWnd **ppTipWnd; +EQLIB_VAR CTipWnd **ppTipWnd; +EQLIB_VAR CBookWnd **ppBookWnd; +EQLIB_VAR CFriendsWnd **ppFriendsWnd; +EQLIB_VAR CMusicPlayerWnd **ppMusicPlayerWnd; +EQLIB_VAR CAlarmWnd **ppAlarmWnd; +EQLIB_VAR CLoadskinWnd **ppLoadskinWnd; +EQLIB_VAR CPetInfoWnd **ppPetInfoWnd; +EQLIB_VAR CTrainWnd **ppTrainWnd; +EQLIB_VAR CSkillsWnd **ppSkillsWnd; +EQLIB_VAR CSkillsSelectWnd **ppSkillsSelectWnd; +//EQLIB_VAR CCombatSkillSelectWnd **ppCombatSkillSelectWnd; +EQLIB_VAR CAAWnd **ppAAWnd; +EQLIB_VAR CGroupWnd **ppGroupWnd; +//EQLIB_VAR CSystemInfoDialogBox **ppSystemInfoDialogBox; +EQLIB_VAR CGroupSearchWnd **ppGroupSearchWnd; +EQLIB_VAR CGroupSearchFiltersWnd **ppGroupSearchFiltersWnd; +EQLIB_VAR CRaidWnd **ppRaidWnd; +EQLIB_VAR CRaidOptionsWnd **ppRaidOptionsWnd; +EQLIB_VAR CBreathWnd **ppBreathWnd; +EQLIB_VAR CMapToolbarWnd **ppMapToolbarWnd; +EQLIB_VAR CMapViewWnd **ppMapViewWnd; +EQLIB_VAR CEditLabelWnd **ppEditLabelWnd; +EQLIB_VAR COptionsWnd **ppOptionsWnd; +EQLIB_VAR CBuffWindow **ppBuffWindowNORMAL; +EQLIB_VAR CBuffWindow **ppBuffWindowSHORT; +EQLIB_VAR CTargetWnd **ppTargetWnd; +EQLIB_VAR CColorPickerWnd **ppColorPickerWnd; +EQLIB_VAR CHotButtonWnd **ppHotButtonWnd; +EQLIB_VAR CPlayerWnd **ppPlayerWnd; +EQLIB_VAR CCastingWnd **ppCastingWnd; +EQLIB_VAR CCastSpellWnd **ppCastSpellWnd; +EQLIB_VAR CSpellBookWnd **ppSpellBookWnd; +EQLIB_VAR CInventoryWnd **ppInventoryWnd; +EQLIB_VAR CBankWnd **ppBankWnd; +EQLIB_VAR CQuantityWnd **ppQuantityWnd; +EQLIB_VAR CTextEntryWnd **ppTextEntryWnd; +EQLIB_VAR CFileSelectionWnd **ppFileSelectionWnd; +EQLIB_VAR CLootWnd **ppLootWnd; +EQLIB_VAR CPetInfoWnd **ppPetInfoWnd; +EQLIB_VAR CActionsWnd **ppActionsWnd; +EQLIB_VAR CCombatAbilityWnd **ppCombatAbilityWnd; +EQLIB_VAR CMerchantWnd **ppMerchantWnd; +EQLIB_VAR CTradeWnd **ppTradeWnd; +EQLIB_VAR CBazaarWnd **ppBazaarWnd; +EQLIB_VAR CBazaarSearchWnd **ppBazaarSearchWnd; +EQLIB_VAR CGiveWnd **ppGiveWnd; +EQLIB_VAR CSelectorWnd **ppSelectorWnd; +EQLIB_VAR CTrackingWnd **ppTrackingWnd; +EQLIB_VAR CInspectWnd **ppInspectWnd; +EQLIB_VAR CFeedbackWnd **ppFeedbackWnd; +EQLIB_VAR CBugReportWnd **ppBugReportWnd; +EQLIB_VAR CVideoModesWnd **ppVideoModesWnd; +EQLIB_VAR CCompassWnd **ppCompassWnd; +EQLIB_VAR CPlayerNotesWnd **ppPlayerNotesWnd; +EQLIB_VAR CGemsGameWnd **ppGemsGameWnd; +EQLIB_VAR CStoryWnd **ppStoryWnd; +//EQLIB_VAR CFindLocationWnd **ppFindLocationWnd; +//EQLIB_VAR CAdventureRequestWnd **ppAdventureRequestWnd; +//EQLIB_VAR CAdventureMerchantWnd **ppAdventureMerchantWnd; +//EQLIB_VAR CAdventureStatsWnd **ppAdventureStatsWnd; +//EQLIB_VAR CAdventureLeaderboardWnd **ppAdventureLeaderboardWnd; +//EQLIB_VAR CLeadershipWindow **ppLeadershipWindow; +EQLIB_VAR CBodyTintWnd **ppBodyTintWnd; +EQLIB_VAR CGuildMgmtWnd **ppGuildMgmtWnd; +EQLIB_VAR CJournalTextWnd **ppJournalTextWnd; +EQLIB_VAR CJournalCatWnd **ppJournalCatWnd; +//EQLIB_VAR CTributeBenefitWnd **ppTributeBenefitWnd; +//EQLIB_VAR CTributeMasterWnd **ppTributeMasterWnd; +EQLIB_VAR CPetitionQWnd **ppPetitionQWnd; +EQLIB_VAR CSoulmarkWnd **ppSoulmarkWnd; +EQLIB_VAR CTimeLeftWnd **ppTimeLeftWnd; +EQLIB_VAR CTextOverlay **ppTextOverlay; +EQLIB_VAR CPotionBeltWnd **ppPotionBeltWnd; + + +#define pContextMenuManager (*ppContextMenuManager) +#define pCursorAttachment (*ppCursorAttachment) +#define pSocialEditWnd (*ppSocialEditWnd) +#define pContainerMgr (*ppContainerMgr) +#define pChatManager (*ppChatManager) +#define pConfirmationDialog (*ppConfirmationDialog) +#define pFacePick (*ppFacePick) +#define pInvSlotMgr (*ppInvSlotMgr) +#define pPopupWndManager (*ppPopupWndManager) +#define pNoteWnd (*ppNoteWnd) +#define pHelpWnd (*ppHelpWnd) +#define pTipWnd (*ppTipWnd) +#define pTipWnd (*ppTipWnd) +#define pBookWnd (*ppBookWnd) +#define pFriendsWnd (*ppFriendsWnd) +#define pMusicPlayerWnd (*ppMusicPlayerWnd) +#define pAlarmWnd (*ppAlarmWnd) +#define pLoadskinWnd (*ppLoadskinWnd) +#define pPetInfoWnd (*ppPetInfoWnd) +#define pTrainWnd (*ppTrainWnd) +#define pSkillsWnd (*ppSkillsWnd) +#define pSkillsSelectWnd (*ppSkillsSelectWnd) +#define pCombatSkillSelectWnd (*ppCombatSkillSelectWnd) +#define pAAWnd (*ppAAWnd) +#define pGroupWnd (*ppGroupWnd) +#define pSystemInfoDialogBox (*ppSystemInfoDialogBox) +#define pGroupSearchWnd (*ppGroupSearchWnd) +#define pGroupSearchFiltersWnd (*ppGroupSearchFiltersWnd) +#define pRaidWnd (*ppRaidWnd) +#define pRaidOptionsWnd (*ppRaidOptionsWnd) +#define pBreathWnd (*ppBreathWnd) +#define pMapToolbarWnd (*ppMapToolbarWnd) +#define pMapViewWnd (*ppMapViewWnd) +#define pEditLabelWnd (*ppEditLabelWnd) +#define pOptionsWnd (*ppOptionsWnd) +#define pBuffWnd (*ppBuffWindowNORMAL) +#define pSongWnd (*ppBuffWindowSHORT) +#define pTargetWnd (*ppTargetWnd) +#define pColorPickerWnd (*ppColorPickerWnd) +#define pHotButtonWnd (*ppHotButtonWnd) +#define pPlayerWnd (*ppPlayerWnd) +#define pCastingWnd (*ppCastingWnd) +#define pCastSpellWnd (*ppCastSpellWnd) +#define pSpellBookWnd (*ppSpellBookWnd) +#define pInventoryWnd (*ppInventoryWnd) +#define pBankWnd (*ppBankWnd) +#define pQuantityWnd (*ppQuantityWnd) +#define pTextEntryWnd (*ppTextEntryWnd) +#define pFileSelectionWnd (*ppFileSelectionWnd) +#define pLootWnd (*ppLootWnd) +#define pPetInfoWnd (*ppPetInfoWnd) +#define pActionsWnd (*ppActionsWnd) +#define pCombatAbilityWnd (*ppCombatAbilityWnd) +#define pMerchantWnd (*ppMerchantWnd) +#define pTradeWnd (*ppTradeWnd) +#define pBazaarWnd (*ppBazaarWnd) +#define pBazaarSearchWnd (*ppBazaarSearchWnd) +#define pGiveWnd (*ppGiveWnd) +#define pSelectorWnd (*ppSelectorWnd) +#define pTrackingWnd (*ppTrackingWnd) +#define pInspectWnd (*ppInspectWnd) +#define pFeedbackWnd (*ppFeedbackWnd) +#define pBugReportWnd (*ppBugReportWnd) +#define pVideoModesWnd (*ppVideoModesWnd) +#define pCompassWnd (*ppCompassWnd) +#define pPlayerNotesWnd (*ppPlayerNotesWnd) +#define pGemsGameWnd (*ppGemsGameWnd) +#define pStoryWnd (*ppStoryWnd) +#define pFindLocationWnd (*ppFindLocationWnd) +#define pAdventureRequestWnd (*ppAdventureRequestWnd) +#define pAdventureMerchantWnd (*ppAdventureMerchantWnd) +#define pAdventureStatsWnd (*ppAdventureStatsWnd) +#define pAdventureLeaderboardWnd (*ppAdventureLeaderboardWnd) +#define pLeadershipWindow (*ppLeadershipWindow) +#define pBodyTintWnd (*ppBodyTintWnd) +#define pGuildMgmtWnd (*ppGuildMgmtWnd) +#define pJournalTextWnd (*ppJournalTextWnd) +#define pJournalCatWnd (*ppJournalCatWnd) +#define pTributeBenefitWnd (*ppTributeBenefitWnd) +#define pTributeMasterWnd (*ppTributeMasterWnd) +#define pPetitionQWnd (*ppPetitionQWnd) +#define pSoulmarkWnd (*ppSoulmarkWnd) +#define pTimeLeftWnd (*ppTimeLeftWnd) +#define pTextOverlay (*ppTextOverlay) +#define pPotionBeltWnd (*ppPotionBeltWnd) +#define pDZMember (*ppDZMember) +#define pDZTimerInfo (*ppDZTimerInfo) +#define pTaskMember (*ppTaskMember) + +EQLIB_VAR DWORD __ActualVersionDate; +EQLIB_VAR DWORD __ActualVersionTime; +EQLIB_VAR DWORD __MemChecker0; +EQLIB_VAR DWORD __MemChecker1; +EQLIB_VAR DWORD __MemChecker2; +EQLIB_VAR DWORD __MemChecker3; +EQLIB_VAR DWORD __MemChecker4; +EQLIB_VAR DWORD __EncryptPad0; +EQLIB_VAR DWORD __EncryptPad1; +EQLIB_VAR DWORD __EncryptPad2; +EQLIB_VAR DWORD __EncryptPad3; +EQLIB_VAR DWORD __EncryptPad4; +EQLIB_VAR DWORD __AC1; +EQLIB_VAR DWORD __AC2; +EQLIB_VAR DWORD __AC3; +EQLIB_VAR DWORD __AC4; +EQLIB_VAR DWORD __AC5; +EQLIB_VAR DWORD __AC6; +EQLIB_VAR DWORD __AC7; +EQLIB_VAR DWORD DI8__Main; +EQLIB_VAR DWORD DI8__Keyboard; +EQLIB_VAR DWORD DI8__Mouse; +EQLIB_VAR DWORD __AltTimerReady; +EQLIB_VAR DWORD __Attack; +EQLIB_VAR DWORD __Autofire; +EQLIB_VAR DWORD __BindList; +EQLIB_VAR DWORD __Clicks; +EQLIB_VAR DWORD __CommandList; +EQLIB_VAR DWORD __CurrentMapLabel; +EQLIB_VAR DWORD __CurrentSocial; +EQLIB_VAR DWORD __DoAbilityList; +EQLIB_VAR DWORD __do_loot; +EQLIB_VAR DWORD __DrawHandler; +EQLIB_VAR DWORD __Guilds; +EQLIB_VAR DWORD __gWorld; +EQLIB_VAR DWORD __HotkeyPage; +EQLIB_VAR DWORD __HWnd; +EQLIB_VAR DWORD __InChatMode; +EQLIB_VAR DWORD __LastTell; +EQLIB_VAR DWORD __LMouseHeldTime; +EQLIB_VAR DWORD __Mouse; +EQLIB_VAR DWORD __MouseLook; +EQLIB_VAR DWORD __MouseEventTime; +EQLIB_VAR DWORD __NetStatusToggle; +EQLIB_VAR DWORD __PCNames; +EQLIB_VAR DWORD __RangeAttackReady; +EQLIB_VAR DWORD __RMouseHeldTime; +EQLIB_VAR DWORD __RunWalkState; +EQLIB_VAR DWORD __ScreenMode; +EQLIB_VAR DWORD __ScreenX; +EQLIB_VAR DWORD __ScreenY; +EQLIB_VAR DWORD __ScreenXMax; +EQLIB_VAR DWORD __ScreenYMax; +EQLIB_VAR DWORD __ServerHost; +EQLIB_VAR DWORD __ServerName; +EQLIB_VAR DWORD __ShiftKeyDown; +EQLIB_VAR DWORD __ShowNames; +EQLIB_VAR DWORD __Socials; + +EQLIB_VAR DWORD instCRaid; +EQLIB_VAR DWORD instEQZoneInfo; +EQLIB_VAR DWORD instKeypressHandler; +EQLIB_VAR DWORD pinstActiveBanker; +EQLIB_VAR DWORD pinstActiveCorpse; +EQLIB_VAR DWORD pinstActiveGMaster; +EQLIB_VAR DWORD pinstActiveMerchant; +EQLIB_VAR DWORD pinstAggroInfo; +EQLIB_VAR DWORD pinstAltAdvManager; +EQLIB_VAR DWORD pinstAuraMgr; +EQLIB_VAR DWORD pinstBandageTarget; +EQLIB_VAR DWORD pinstCamActor; +EQLIB_VAR DWORD pinstCDBStr; +EQLIB_VAR DWORD pinstCDisplay; +EQLIB_VAR DWORD pinstCEverQuest; +EQLIB_VAR DWORD pinstCharData; +EQLIB_VAR DWORD pinstCharSpawn; +EQLIB_VAR DWORD pinstControlledMissile; +EQLIB_VAR DWORD pinstControlledPlayer; +EQLIB_VAR DWORD pinstCSidlManager; +EQLIB_VAR DWORD pinstCXWndManager; +EQLIB_VAR DWORD instDynamicZone; +EQLIB_VAR DWORD pinstDZMember; +EQLIB_VAR DWORD pinstDZTimerInfo; +EQLIB_VAR DWORD pinstEQItemList; +EQLIB_VAR DWORD instEQMisc; +EQLIB_VAR DWORD pinstEQSoundManager; +EQLIB_VAR DWORD instExpeditionLeader; +EQLIB_VAR DWORD instExpeditionName; +EQLIB_VAR DWORD pinstGroup; +EQLIB_VAR DWORD pinstImeManager; +EQLIB_VAR DWORD pinstLocalPlayer; +EQLIB_VAR DWORD pinstMercenaryData; +EQLIB_VAR DWORD pinstModelPlayer; +EQLIB_VAR DWORD pinstPCData; +EQLIB_VAR DWORD pinstSkillMgr; +EQLIB_VAR DWORD pinstSpawnManager; +EQLIB_VAR DWORD pinstSpellManager; +EQLIB_VAR DWORD pinstSpellSets; +EQLIB_VAR DWORD pinstStringTable; +EQLIB_VAR DWORD pinstSwitchManager; +EQLIB_VAR DWORD pinstTarget; +EQLIB_VAR DWORD pinstTargetObject; +EQLIB_VAR DWORD pinstTargetSwitch; +EQLIB_VAR DWORD pinstTaskMember; +EQLIB_VAR DWORD pinstTrackTarget; +EQLIB_VAR DWORD pinstTradeTarget; +EQLIB_VAR DWORD instTributeActive; +EQLIB_VAR DWORD pinstViewActor; +EQLIB_VAR DWORD pinstWorldData; + +EQLIB_VAR DWORD pinstCTextOverlay; +EQLIB_VAR DWORD pinstCAudioTriggersWindow; +EQLIB_VAR DWORD pinstCCharacterSelect; +EQLIB_VAR DWORD pinstCFacePick; +EQLIB_VAR DWORD pinstCNoteWnd; +EQLIB_VAR DWORD pinstCBookWnd; +EQLIB_VAR DWORD pinstCPetInfoWnd; +EQLIB_VAR DWORD pinstCTrainWnd; +EQLIB_VAR DWORD pinstCSkillsWnd; +EQLIB_VAR DWORD pinstCSkillsSelectWnd; +EQLIB_VAR DWORD pinstCCombatSkillSelectWnd; +EQLIB_VAR DWORD pinstCFriendsWnd; +EQLIB_VAR DWORD pinstCAuraWnd; +EQLIB_VAR DWORD pinstCRespawnWnd; +EQLIB_VAR DWORD pinstCBandolierWnd; +EQLIB_VAR DWORD pinstCPotionBeltWnd; +EQLIB_VAR DWORD pinstCAAWnd; +EQLIB_VAR DWORD pinstCGroupSearchFiltersWnd; +EQLIB_VAR DWORD pinstCLoadskinWnd; +EQLIB_VAR DWORD pinstCAlarmWnd; +EQLIB_VAR DWORD pinstCMusicPlayerWnd; +EQLIB_VAR DWORD pinstCMailWnd; +EQLIB_VAR DWORD pinstCMailCompositionWnd; +EQLIB_VAR DWORD pinstCMailAddressBookWnd; +EQLIB_VAR DWORD pinstCRaidWnd; +EQLIB_VAR DWORD pinstCRaidOptionsWnd; +EQLIB_VAR DWORD pinstCBreathWnd; +EQLIB_VAR DWORD pinstCMapViewWnd; +EQLIB_VAR DWORD pinstCMapToolbarWnd; +EQLIB_VAR DWORD pinstCEditLabelWnd; +EQLIB_VAR DWORD pinstCTargetWnd; +EQLIB_VAR DWORD pinstCColorPickerWnd; +EQLIB_VAR DWORD pinstCPlayerWnd; +EQLIB_VAR DWORD pinstCOptionsWnd; +EQLIB_VAR DWORD pinstCBuffWindowNORMAL; +EQLIB_VAR DWORD pinstCBuffWindowSHORT; +EQLIB_VAR DWORD pinstCharacterCreation; +EQLIB_VAR DWORD pinstCCursorAttachment; +EQLIB_VAR DWORD pinstCCastingWnd; +EQLIB_VAR DWORD pinstCCastSpellWnd; +EQLIB_VAR DWORD pinstCSpellBookWnd; +EQLIB_VAR DWORD pinstCInventoryWnd; +EQLIB_VAR DWORD pinstCBankWnd; +EQLIB_VAR DWORD pinstCQuantityWnd; +EQLIB_VAR DWORD pinstCLootWnd; +EQLIB_VAR DWORD pinstCActionsWnd; +EQLIB_VAR DWORD pinstCCombatAbilityWnd; +EQLIB_VAR DWORD pinstCMerchantWnd; +EQLIB_VAR DWORD pinstCTradeWnd; +EQLIB_VAR DWORD pinstCSelectorWnd; +EQLIB_VAR DWORD pinstCBazaarWnd; +EQLIB_VAR DWORD pinstCBazaarSearchWnd; +EQLIB_VAR DWORD pinstCGiveWnd; +EQLIB_VAR DWORD pinstCTrackingWnd; +EQLIB_VAR DWORD pinstCInspectWnd; +EQLIB_VAR DWORD pinstCSocialEditWnd; +EQLIB_VAR DWORD pinstCFeedbackWnd; +EQLIB_VAR DWORD pinstCBugReportWnd; +EQLIB_VAR DWORD pinstCVideoModesWnd; +EQLIB_VAR DWORD pinstCTextEntryWnd; +EQLIB_VAR DWORD pinstCFileSelectionWnd; +EQLIB_VAR DWORD pinstCCompassWnd; +EQLIB_VAR DWORD pinstCPlayerNotesWnd; +EQLIB_VAR DWORD pinstCGemsGameWnd; +EQLIB_VAR DWORD pinstCTimeLeftWnd; +EQLIB_VAR DWORD pinstCPetitionQWnd; +EQLIB_VAR DWORD pinstCSoulmarkWnd; +EQLIB_VAR DWORD pinstCStoryWnd; +EQLIB_VAR DWORD pinstCJournalTextWnd; +EQLIB_VAR DWORD pinstCJournalCatWnd; +EQLIB_VAR DWORD pinstCBodyTintWnd; +EQLIB_VAR DWORD pinstCServerListWnd; +EQLIB_VAR DWORD pinstCAvaZoneWnd; +EQLIB_VAR DWORD pinstCBlockedBuffWnd; +EQLIB_VAR DWORD pinstCBlockedPetBuffWnd; +EQLIB_VAR DWORD pinstCInvSlotMgr; +EQLIB_VAR DWORD pinstCContainerMgr; +EQLIB_VAR DWORD pinstCAdventureLeaderboardWnd; +EQLIB_VAR DWORD pinstCAdventureRequestWnd; +EQLIB_VAR DWORD pinstCAltStorageWnd; +EQLIB_VAR DWORD pinstCAdventureStatsWnd; +EQLIB_VAR DWORD pinstCBarterMerchantWnd; +EQLIB_VAR DWORD pinstCBarterSearchWnd; +EQLIB_VAR DWORD pinstCBarterWnd; +EQLIB_VAR DWORD pinstCChatManager; +EQLIB_VAR DWORD pinstCDynamicZoneWnd; +EQLIB_VAR DWORD pinstCEQMainWnd; +EQLIB_VAR DWORD pinstCFellowshipWnd; +EQLIB_VAR DWORD pinstCFindLocationWnd; +EQLIB_VAR DWORD pinstCGroupSearchWnd; +EQLIB_VAR DWORD pinstCGroupWnd; +EQLIB_VAR DWORD pinstCGuildBankWnd; +EQLIB_VAR DWORD pinstCGuildMgmtWnd; +EQLIB_VAR DWORD pinstCHotButtonWnd; +EQLIB_VAR DWORD pinstCHotButtonWnd1; +EQLIB_VAR DWORD pinstCHotButtonWnd2; +EQLIB_VAR DWORD pinstCHotButtonWnd3; +EQLIB_VAR DWORD pinstCHotButtonWnd4; +EQLIB_VAR DWORD pinstCItemDisplayManager; +EQLIB_VAR DWORD pinstCItemExpTransferWnd; +EQLIB_VAR DWORD pinstCLFGuildWnd; +EQLIB_VAR DWORD pinstCMIZoneSelectWnd; +EQLIB_VAR DWORD pinstCConfirmationDialog; +EQLIB_VAR DWORD pinstCPopupWndManager; +EQLIB_VAR DWORD pinstCProgressionSelectionWnd; +EQLIB_VAR DWORD pinstCPvPStatsWnd; +EQLIB_VAR DWORD pinstCSystemInfoDialogBox; +EQLIB_VAR DWORD pinstCTargetOfTargetWnd; +EQLIB_VAR DWORD pinstCTaskTemplateSelectWnd; +EQLIB_VAR DWORD pinstCTaskWnd; +EQLIB_VAR DWORD pinstCTipWndOFDAY; +EQLIB_VAR DWORD pinstCTipWndCONTEXT; +EQLIB_VAR DWORD pinstCTitleWnd; +EQLIB_VAR DWORD pinstCContextMenuManager; +EQLIB_VAR DWORD pinstCVoiceMacroWnd; +EQLIB_VAR DWORD pinstCHtmlWnd; + +EQLIB_VAR DWORD __CastRay; +EQLIB_VAR DWORD __ConvertItemTags; +EQLIB_VAR DWORD __ExecuteCmd; +EQLIB_VAR DWORD __EQGetTime; +EQLIB_VAR DWORD __get_melee_range; +EQLIB_VAR DWORD __GetGaugeValueFromEQ; +EQLIB_VAR DWORD __GetLabelFromEQ; +EQLIB_VAR DWORD __GetXTargetType; +EQLIB_VAR DWORD __LoadFrontEnd; +EQLIB_VAR DWORD __NewUIINI; +EQLIB_VAR DWORD __ProcessGameEvents; +EQLIB_VAR DWORD CrashDetected; +EQLIB_VAR DWORD DrawNetStatus; +EQLIB_VAR DWORD Util__FastTime; +EQLIB_VAR DWORD Expansion_HoT; + +EQLIB_VAR DWORD AltAdvManager__GetCalculatedTimer; +EQLIB_VAR DWORD AltAdvManager__IsAbilityReady; +EQLIB_VAR DWORD AltAdvManager__GetAltAbility; + +EQLIB_VAR DWORD CharacterZoneClient__HasSkill; + +EQLIB_VAR DWORD CBankWnd__GetNumBankSlots; + +EQLIB_VAR DWORD CBazaarSearchWnd__HandleBazaarMsg; + +EQLIB_VAR DWORD CButtonWnd__SetCheck; + +EQLIB_VAR DWORD CChatManager__GetRGBAFromIndex; +EQLIB_VAR DWORD CChatManager__InitContextMenu; + +EQLIB_VAR DWORD CChatService__GetNumberOfFriends; +EQLIB_VAR DWORD CChatService__GetFriendName; + +EQLIB_VAR DWORD CRaces_AddModel; + +EQLIB_VAR DWORD CChatWindow__CChatWindow; +EQLIB_VAR DWORD CChatWindow__Clear; +EQLIB_VAR DWORD CChatWindow__WndNotification; + +EQLIB_VAR DWORD CComboWnd__DeleteAll; +EQLIB_VAR DWORD CComboWnd__Draw; +EQLIB_VAR DWORD CComboWnd__GetCurChoice; +EQLIB_VAR DWORD CComboWnd__GetListRect; +EQLIB_VAR DWORD CComboWnd__GetTextRect; +EQLIB_VAR DWORD CComboWnd__InsertChoice; +EQLIB_VAR DWORD CComboWnd__SetColors; +EQLIB_VAR DWORD CComboWnd__SetChoice; + +EQLIB_VAR DWORD CContainerWnd__HandleCombine; +EQLIB_VAR DWORD CContainerWnd__vftable; + +EQLIB_VAR DWORD CDisplay__CleanGameUI; +EQLIB_VAR DWORD CDisplay__GetClickedActor; +EQLIB_VAR DWORD CDisplay__GetUserDefinedColor; +EQLIB_VAR DWORD CDisplay__GetWorldFilePath; +EQLIB_VAR DWORD CDisplay__is3dON; +EQLIB_VAR DWORD CDisplay__ReloadUI; +EQLIB_VAR DWORD CDisplay__WriteTextHD2; + +EQLIB_VAR DWORD CEditBaseWnd__SetSel; + +EQLIB_VAR DWORD CEditWnd__DrawCaret; +EQLIB_VAR DWORD CEditWnd__GetCharIndexPt; +EQLIB_VAR DWORD CEditWnd__GetDisplayString; +EQLIB_VAR DWORD CEditWnd__GetHorzOffset; +EQLIB_VAR DWORD CEditWnd__GetLineForPrintableChar; +EQLIB_VAR DWORD CEditWnd__GetSelStartPt; +EQLIB_VAR DWORD CEditWnd__GetSTMLSafeText; +EQLIB_VAR DWORD CEditWnd__PointFromPrintableChar; +EQLIB_VAR DWORD CEditWnd__SelectableCharFromPoint; +EQLIB_VAR DWORD CEditWnd__SetEditable; + +EQLIB_VAR DWORD CEverQuest__ClickedPlayer; +EQLIB_VAR DWORD CEverQuest__DoTellWindow; +EQLIB_VAR DWORD CEverQuest__DropHeldItemOnGround; +EQLIB_VAR DWORD CEverQuest__dsp_chat; +EQLIB_VAR DWORD CEverQuest__Emote; +EQLIB_VAR DWORD CEverQuest__EnterZone; +EQLIB_VAR DWORD CEverQuest__GetBodyTypeDesc; +EQLIB_VAR DWORD CEverQuest__GetClassDesc; +EQLIB_VAR DWORD CEverQuest__GetClassThreeLetterCode; +EQLIB_VAR DWORD CEverQuest__GetDeityDesc; +EQLIB_VAR DWORD CEverQuest__GetLangDesc; +EQLIB_VAR DWORD CEverQuest__GetRaceDesc; +EQLIB_VAR DWORD CEverQuest__InterpretCmd; +EQLIB_VAR DWORD CEverQuest__LeftClickedOnPlayer; +EQLIB_VAR DWORD CEverQuest__LMouseUp; +EQLIB_VAR DWORD CEverQuest__RightClickedOnPlayer; +EQLIB_VAR DWORD CEverQuest__RMouseUp; +EQLIB_VAR DWORD CEverQuest__SetGameState; +EQLIB_VAR DWORD CEverQuest__UPCNotificationFlush; + +EQLIB_VAR DWORD CGaugeWnd__CalcFillRect; +EQLIB_VAR DWORD CGaugeWnd__CalcLinesFillRect; +EQLIB_VAR DWORD CGaugeWnd__Draw; + +EQLIB_VAR DWORD CGuild__FindMemberByName; + +EQLIB_VAR DWORD CHotButtonWnd__DoHotButton; + +EQLIB_VAR DWORD CInvSlotMgr__FindInvSlot; +EQLIB_VAR DWORD CInvSlotMgr__MoveItem; + +EQLIB_VAR DWORD CInvSlot__HandleRButtonUp; +EQLIB_VAR DWORD CInvSlot__SliderComplete; +EQLIB_VAR DWORD CInvSlot__GetItemBase; + +EQLIB_VAR DWORD CInvSlotWnd__DrawTooltip; + +EQLIB_VAR DWORD CItemDisplayWnd__SetSpell; +EQLIB_VAR DWORD CItemDisplayWnd__UpdateStrings; + +EQLIB_VAR DWORD CLabel__Draw; + +EQLIB_VAR DWORD CListWnd__AddColumn; +EQLIB_VAR DWORD CListWnd__AddColumn1; +EQLIB_VAR DWORD CListWnd__AddLine; +EQLIB_VAR DWORD CListWnd__AddString; +EQLIB_VAR DWORD CListWnd__CalculateFirstVisibleLine; +EQLIB_VAR DWORD CListWnd__CalculateVSBRange; +EQLIB_VAR DWORD CListWnd__ClearAllSel; +EQLIB_VAR DWORD CListWnd__CloseAndUpdateEditWindow; +EQLIB_VAR DWORD CListWnd__Compare; +EQLIB_VAR DWORD CListWnd__Draw; +EQLIB_VAR DWORD CListWnd__DrawColumnSeparators; +EQLIB_VAR DWORD CListWnd__DrawHeader; +EQLIB_VAR DWORD CListWnd__DrawItem; +EQLIB_VAR DWORD CListWnd__DrawLine; +EQLIB_VAR DWORD CListWnd__DrawSeparator; +EQLIB_VAR DWORD CListWnd__EnsureVisible; +EQLIB_VAR DWORD CListWnd__ExtendSel; +EQLIB_VAR DWORD CListWnd__GetColumnMinWidth; +EQLIB_VAR DWORD CListWnd__GetColumnWidth; +EQLIB_VAR DWORD CListWnd__GetCurSel; +EQLIB_VAR DWORD CListWnd__GetItemAtPoint; +EQLIB_VAR DWORD CListWnd__GetItemAtPoint1; +EQLIB_VAR DWORD CListWnd__GetItemData; +EQLIB_VAR DWORD CListWnd__GetItemHeight; +EQLIB_VAR DWORD CListWnd__GetItemIcon; +EQLIB_VAR DWORD CListWnd__GetItemRect; +EQLIB_VAR DWORD CListWnd__GetItemText; +EQLIB_VAR DWORD CListWnd__GetSelList; +EQLIB_VAR DWORD CListWnd__GetSeparatorRect; +EQLIB_VAR DWORD CListWnd__RemoveLine; +EQLIB_VAR DWORD CListWnd__SetColors; +EQLIB_VAR DWORD CListWnd__SetColumnJustification; +EQLIB_VAR DWORD CListWnd__SetColumnWidth; +EQLIB_VAR DWORD CListWnd__SetCurSel; +EQLIB_VAR DWORD CListWnd__SetItemColor; +EQLIB_VAR DWORD CListWnd__SetItemData; +EQLIB_VAR DWORD CListWnd__SetItemText; +EQLIB_VAR DWORD CListWnd__ShiftColumnSeparator; +EQLIB_VAR DWORD CListWnd__Sort; +EQLIB_VAR DWORD CListWnd__ToggleSel; + +EQLIB_VAR DWORD CMapViewWnd__CMapViewWnd; + +EQLIB_VAR DWORD CMerchantWnd__DisplayBuyOrSellPrice; +EQLIB_VAR DWORD CMerchantWnd__RequestBuyItem; +EQLIB_VAR DWORD CMerchantWnd__RequestSellItem; +EQLIB_VAR DWORD CMerchantWnd__SelectBuySellSlot; + +EQLIB_VAR DWORD CObfuscator__doit; + +EQLIB_VAR DWORD CSidlManager__FindScreenPieceTemplate1; +EQLIB_VAR DWORD CSidlManager__CreateLabel; + +EQLIB_VAR DWORD CSidlScreenWnd__CalculateHSBRange; +EQLIB_VAR DWORD CSidlScreenWnd__CalculateVSBRange; +EQLIB_VAR DWORD CSidlScreenWnd__ConvertToRes; +EQLIB_VAR DWORD CSidlScreenWnd__CreateChildrenFromSidl; +EQLIB_VAR DWORD CSidlScreenWnd__CSidlScreenWnd1; +EQLIB_VAR DWORD CSidlScreenWnd__CSidlScreenWnd2; +EQLIB_VAR DWORD CSidlScreenWnd__dCSidlScreenWnd; +EQLIB_VAR DWORD CSidlScreenWnd__DrawSidlPiece; +EQLIB_VAR DWORD CSidlScreenWnd__EnableIniStorage; +EQLIB_VAR DWORD CSidlScreenWnd__GetSidlPiece; +EQLIB_VAR DWORD CSidlScreenWnd__Init1; +EQLIB_VAR DWORD CSidlScreenWnd__LoadIniInfo; +EQLIB_VAR DWORD CSidlScreenWnd__LoadIniListWnd; +EQLIB_VAR DWORD CSidlScreenWnd__LoadSidlScreen; +EQLIB_VAR DWORD CSidlScreenWnd__StoreIniInfo; +EQLIB_VAR DWORD CSidlScreenWnd__StoreIniVis; +EQLIB_VAR DWORD CSidlScreenWnd__WndNotification; +EQLIB_VAR DWORD CSidlScreenWnd__GetChildItem; + +EQLIB_VAR DWORD CSkillMgr__IsAvailable; +EQLIB_VAR DWORD CSkillMgr__GetSkillCap; + +EQLIB_VAR DWORD CSliderWnd__GetValue; +EQLIB_VAR DWORD CSliderWnd__SetValue; +EQLIB_VAR DWORD CSliderWnd__SetNumTicks; + +EQLIB_VAR DWORD CSpellBookWnd__MemorizeSet; + +EQLIB_VAR DWORD CStmlWnd__AppendSTML; +EQLIB_VAR DWORD CStmlWnd__CalculateHSBRange; +EQLIB_VAR DWORD CStmlWnd__CalculateVSBRange; +EQLIB_VAR DWORD CStmlWnd__CanBreakAtCharacter; +EQLIB_VAR DWORD CStmlWnd__FastForwardToEndOfTag; +EQLIB_VAR DWORD CStmlWnd__ForceParseNow; +EQLIB_VAR DWORD CStmlWnd__GetNextTagPiece; +EQLIB_VAR DWORD CStmlWnd__GetSTMLText; +EQLIB_VAR DWORD CStmlWnd__GetVisibleText; +EQLIB_VAR DWORD CStmlWnd__InitializeWindowVariables; +EQLIB_VAR DWORD CStmlWnd__MakeStmlColorTag; +EQLIB_VAR DWORD CStmlWnd__MakeWndNotificationTag; +EQLIB_VAR DWORD CStmlWnd__SetSTMLText; +EQLIB_VAR DWORD CStmlWnd__StripFirstSTMLLines; +EQLIB_VAR DWORD CStmlWnd__UpdateHistoryString; + +EQLIB_VAR DWORD CTabWnd__Draw; +EQLIB_VAR DWORD CTabWnd__DrawCurrentPage; +EQLIB_VAR DWORD CTabWnd__DrawTab; +EQLIB_VAR DWORD CTabWnd__GetCurrentPage; +EQLIB_VAR DWORD CTabWnd__GetPageInnerRect; +EQLIB_VAR DWORD CTabWnd__GetTabInnerRect; +EQLIB_VAR DWORD CTabWnd__GetTabRect; +EQLIB_VAR DWORD CTabWnd__InsertPage; +EQLIB_VAR DWORD CTabWnd__SetPage; +EQLIB_VAR DWORD CTabWnd__SetPageRect; +EQLIB_VAR DWORD CTabWnd__UpdatePage; + +EQLIB_VAR DWORD CTextOverlay__DisplayText; + +EQLIB_VAR DWORD CTextureFont__DrawWrappedText; + +EQLIB_VAR DWORD CXMLDataManager__GetXMLData; + +EQLIB_VAR DWORD CXMLSOMDocumentBase__XMLRead; + +EQLIB_VAR DWORD CXStr__CXStr; +EQLIB_VAR DWORD CXStr__CXStr1; +EQLIB_VAR DWORD CXStr__CXStr3; +EQLIB_VAR DWORD CXStr__dCXStr; +EQLIB_VAR DWORD CXStr__operator_equal; +EQLIB_VAR DWORD CXStr__operator_equal1; +EQLIB_VAR DWORD CXStr__operator_plus_equal1; + +EQLIB_VAR DWORD CXWnd__BringToTop; +EQLIB_VAR DWORD CXWnd__Center; +EQLIB_VAR DWORD CXWnd__ClrFocus; +EQLIB_VAR DWORD CXWnd__DoAllDrawing; +EQLIB_VAR DWORD CXWnd__DrawChildren; +EQLIB_VAR DWORD CXWnd__DrawColoredRect; +EQLIB_VAR DWORD CXWnd__DrawTooltip; +EQLIB_VAR DWORD CXWnd__DrawTooltipAtPoint; +EQLIB_VAR DWORD CXWnd__GetBorderFrame; +EQLIB_VAR DWORD CXWnd__GetChildWndAt; +EQLIB_VAR DWORD CXWnd__GetClientClipRect; +EQLIB_VAR DWORD CXWnd__GetScreenClipRect; +EQLIB_VAR DWORD CXWnd__GetScreenRect; +EQLIB_VAR DWORD CXWnd__GetTooltipRect; +EQLIB_VAR DWORD CXWnd__GetWindowTextA; +EQLIB_VAR DWORD CXWnd__IsActive; +EQLIB_VAR DWORD CXWnd__IsDescendantOf; +EQLIB_VAR DWORD CXWnd__IsReallyVisible; +EQLIB_VAR DWORD CXWnd__IsType; +EQLIB_VAR DWORD CXWnd__Move; +EQLIB_VAR DWORD CXWnd__Move1; +EQLIB_VAR DWORD CXWnd__ProcessTransition; +EQLIB_VAR DWORD CXWnd__Refade; +EQLIB_VAR DWORD CXWnd__Resize; +EQLIB_VAR DWORD CXWnd__Right; +EQLIB_VAR DWORD CXWnd__SetFocus; +EQLIB_VAR DWORD CXWnd__SetFont; +EQLIB_VAR DWORD CXWnd__SetKeyTooltip; +EQLIB_VAR DWORD CXWnd__SetMouseOver; +EQLIB_VAR DWORD CXWnd__StartFade; +EQLIB_VAR DWORD CXWnd__GetChildItem; + +EQLIB_VAR DWORD CXWndManager__DrawCursor; +EQLIB_VAR DWORD CXWndManager__DrawWindows; +EQLIB_VAR DWORD CXWndManager__GetKeyboardFlags; +EQLIB_VAR DWORD CXWndManager__HandleKeyboardMsg; +EQLIB_VAR DWORD CXWndManager__RemoveWnd; + +EQLIB_VAR DWORD CDBStr__GetString; + +EQLIB_VAR DWORD EQ_Character__CastRay; +EQLIB_VAR DWORD EQ_Character__CastSpell; +EQLIB_VAR DWORD EQ_Character__Cur_HP; +EQLIB_VAR DWORD EQ_Character__GetAACastingTimeModifier; +EQLIB_VAR DWORD EQ_Character__GetCharInfo2; +EQLIB_VAR DWORD EQ_Character__GetFocusCastingTimeModifier; +EQLIB_VAR DWORD EQ_Character__GetFocusRangeModifier; +EQLIB_VAR DWORD EQ_Character__Max_Endurance; +EQLIB_VAR DWORD EQ_Character__Max_HP; +EQLIB_VAR DWORD EQ_Character__Max_Mana; +EQLIB_VAR DWORD EQ_Character__doCombatAbility; +EQLIB_VAR DWORD EQ_Character__UseSkill; +EQLIB_VAR DWORD EQ_Character__GetConLevel; +EQLIB_VAR DWORD EQ_Character__IsExpansionFlag; +EQLIB_VAR DWORD EQ_Character__TotalEffect; + +EQLIB_VAR DWORD EQ_Item__CanDrop; +EQLIB_VAR DWORD EQ_Item__CreateItemTagString; +EQLIB_VAR DWORD EQ_Item__IsStackable; + +EQLIB_VAR DWORD EQ_LoadingS__SetProgressBar; +EQLIB_VAR DWORD EQ_LoadingS__Array; + +EQLIB_VAR DWORD EQ_PC__DestroyHeldItemOrMoney; +EQLIB_VAR DWORD EQ_PC__GetAltAbilityIndex; +EQLIB_VAR DWORD EQ_PC__GetCombatAbility; +EQLIB_VAR DWORD EQ_PC__GetCombatAbilityTimer; +EQLIB_VAR DWORD EQ_PC__GetItemTimerValue; +EQLIB_VAR DWORD EQ_PC__HasLoreItem; + +EQLIB_VAR DWORD EQItemList__EQItemList; +EQLIB_VAR DWORD EQItemList__add_item; +EQLIB_VAR DWORD EQItemList__delete_item; +EQLIB_VAR DWORD EQItemList__FreeItemList; + +EQLIB_VAR DWORD EQMisc__GetActiveFavorCost; + +EQLIB_VAR DWORD EQPlayer__ChangeBoneStringSprite; +EQLIB_VAR DWORD EQPlayer__dEQPlayer; +EQLIB_VAR DWORD EQPlayer__DoAttack; +EQLIB_VAR DWORD EQPlayer__EQPlayer; +EQLIB_VAR DWORD EQPlayer__SetNameSpriteState; +EQLIB_VAR DWORD EQPlayer__SetNameSpriteTint; +EQLIB_VAR DWORD EQPlayer__IsBodyType_j; +EQLIB_VAR DWORD EQPlayer__IsTargetable; + +EQLIB_VAR DWORD EQPlayerManager__GetSpawnByID; +EQLIB_VAR DWORD EQPlayerManager__GetSpawnByName; + +EQLIB_VAR DWORD KeypressHandler__AttachAltKeyToEqCommand; +EQLIB_VAR DWORD KeypressHandler__AttachKeyToEqCommand; +EQLIB_VAR DWORD KeypressHandler__ClearCommandStateArray; +EQLIB_VAR DWORD KeypressHandler__HandleKeyDown; +EQLIB_VAR DWORD KeypressHandler__HandleKeyUp; +EQLIB_VAR DWORD KeypressHandler__SaveKeymapping; + +EQLIB_VAR DWORD MapViewMap__Clear; +EQLIB_VAR DWORD MapViewMap__SaveEx; + +EQLIB_VAR DWORD PlayerPointManager__GetAltCurrency; + +EQLIB_VAR DWORD StringTable__getString; + +EQLIB_VAR DWORD PcZoneClient__GetPcSkillLimit; + + +} +using namespace MQ2Globals; + + diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2Inlines.h b/client_files/native_autoloot/eq-core-dll/src/MQ2Inlines.h new file mode 100644 index 0000000000..2b24edd50c --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2Inlines.h @@ -0,0 +1,452 @@ +#pragma once +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +static inline PCHARINFO GetCharInfo(VOID) { + // if (!ppCharData) return NULL; + return (PCHARINFO)pCharData; +} + +static inline PCHARINFO2 GetCharInfo2(VOID) { + // if (!ppCharData) return NULL; + return ((PCHARINFO)pCharData)->pCI2->pCharInfo2; +} + + +static inline EQPlayer *GetSpawnByID(DWORD dwSpawnID) +{ + // if (dwSpawnID<3000) + // return ppEQP_IDArray[dwSpawnID]; + return pSpawnManager->GetSpawnByID(dwSpawnID); +} + +static inline PSPAWNINFO GetSpawnByDisplayedName(char* spawnName) +{ + PSPAWNINFO pSpawn = (PSPAWNINFO)pSpawnList; + while (pSpawn) { + if (!_stricmp(pSpawn->DisplayedName, spawnName)) { + return pSpawn; + } + pSpawn = pSpawn->pNext; + } +} + +static inline EQPlayer *GetSpawnByName(char *spawnName) +{ + return pSpawnManager->GetSpawnByName(spawnName); +} + +static inline PSPELL GetSpellByID(DWORD dwSpellID) +{ + if (dwSpellID==0 || dwSpellID >= TOTAL_SPELL_COUNT) + return 0; + return &(*((PSPELLMGR)pSpellMgr)->Spells[dwSpellID]); +} + +static inline PCHAR GetBodyTypeDesc(DWORD BodyTypeID) +{ + if (BodyTypeID<104 && BodyTypeID>=0) + return szBodyType[BodyTypeID]; + return "*UNKNOWN BODYTYPE"; +} + +static inline PCHAR GetClassDesc(DWORD ClassID) +{ + if (ClassID==60) + return "LDoN Recruiter"; + if (ClassID==61) + return "LDoN Merchant"; + if (ClassID==62) + return "Destructible Object"; + if (ClassID==63) + return "Tribute Master"; + if (ClassID==64) + return "Guild Tribute Master"; + if (ClassID==66) + return "Guild Banker"; + if (ClassID==67 || ClassID==68) + return "DoN Merchant"; + if (ClassID==69) + return "Fellowship Registrar"; + if (ClassID==70) + return "Merchant"; + if (ClassID==71) + return "Mercenary Liaison"; + if (ClassID==0xFF) + return "Aura"; + if (ClassID==0xFE) + return "Banner"; + if (ClassID==0xFD) + return "Campfire"; + return pEverQuest->GetClassDesc(ClassID); +} + +static inline BOOL IsAssistNPC(PSPAWNINFO pSpawn) +{ + if (GetCharInfo()->pSpawn && pSpawn) + { + DWORD nAssist; + { + if (GetCharInfo()->pSpawn->GroupAssistNPC[0]==pSpawn->SpawnID) + { + return true; + } + } + for (nAssist=0 ; nAssist < 3 ; nAssist++) + { + if (GetCharInfo()->pSpawn->RaidAssistNPC[nAssist]==pSpawn->SpawnID) + { + return true; + } + } + } + return false; +} + +static inline BOOL IsMarkedNPC(PSPAWNINFO pSpawn) +{ + if (GetCharInfo()->pSpawn && pSpawn) + { + DWORD nMark; + for (nMark=0 ; nMark < 3 ; nMark++) + { + if (GetCharInfo()->pSpawn->RaidMarkNPC[nMark]==pSpawn->SpawnID) + { + return true; + } + } + for (nMark=0 ; nMark < 3 ; nMark++) + { + if (GetCharInfo()->pSpawn->GroupMarkNPC[nMark]==pSpawn->SpawnID) + { + return true; + } + } + } + return false; +} + +#define GetCurHPS() pCharData1->Cur_HP(0) +#define GetMaxHPS() pCharData1->Max_HP(0) +#define GetMaxEndurance() pCharData1->Max_Endurance() +#define GetMaxMana() pCharData1->Max_Mana() + +static inline DWORD GetBodyType(PSPAWNINFO pSpawn) +{ + for(int i=0; i<104; i++) + { + if(((EQPlayer*)pSpawn)->IsBodyType(i,0,0)) + { + if(i==100) + { + if(((EQPlayer*)pSpawn)->IsBodyType(i,101,0)) + return 101; + if(((EQPlayer*)pSpawn)->IsBodyType(i,102,0)) + return 102; + if(((EQPlayer*)pSpawn)->IsBodyType(i,103,0)) + return 103; + } + return i; + } + } + return 0; +} + +static inline eSpawnType GetSpawnType(PSPAWNINFO pSpawn) +{ + switch(pSpawn->Type) + { + case SPAWN_PLAYER: + { + return PC; + } + case SPAWN_NPC: + if (pSpawn->Rider) + { + return MOUNT; + } + if (pSpawn->MasterID) + return PET; + if (pSpawn->Mercenary) + return MERCENARY; + + // some type of controller spawn for flying mobs - locations, speed, heading, all NaN + if (IsNaN(pSpawn->Y) && IsNaN(pSpawn->X) && IsNaN(pSpawn->Z)) + return FLYER; + + switch(GetBodyType(pSpawn)) + { + case 0: + if (pSpawn->Class==62) + return OBJECT; + return NPC; + case 1: + if (pSpawn->Race == 567) + return CAMPFIRE; + if (pSpawn->Race == 500 || (pSpawn->Race >= 553 && pSpawn->Race <= 557) || pSpawn->Race == 586) + return BANNER; + return NPC; + //case 3: + // return NPC; + case 5: + if (strstr(pSpawn->Name,"Idol") || strstr(pSpawn->Name,"Poison") || strstr(pSpawn->Name,"Rune")) + return AURA; + if (pSpawn->Class==62) + return OBJECT; + return NPC; + case 11: + if (strstr(pSpawn->Name,"Aura") || strstr(pSpawn->Name,"Circle_of") || strstr(pSpawn->Name,"Guardian_Circle") || strstr(pSpawn->Name,"Earthen_Strength")) + return AURA; + return UNTARGETABLE; + //case 21: + // return NPC; + //case 23: + // return NPC; + case 33: + return CHEST; + //case 34: + // return NPC; + //case 65: + // return TRAP; + //case 66: + // return TIMER; + //case 67: + // return TRIGGER; + case 100: + return UNTARGETABLE; + case 101: + return TRAP; + case 102: + return TIMER; + case 103: + return TRIGGER; + default: + return NPC; + } + return NPC; + case SPAWN_CORPSE: + return CORPSE; + default: + return ITEM; + } +} + +static inline FLOAT GetDistance(FLOAT X1,FLOAT Y1) +{ + FLOAT dX=X1-((PSPAWNINFO)pCharSpawn)->X; + FLOAT dY=Y1-((PSPAWNINFO)pCharSpawn)->Y; + return sqrtf(dX*dX + dY*dY); +} + +static inline FLOAT GetDistance(FLOAT X1,FLOAT Y1,FLOAT X2,FLOAT Y2) +{ + FLOAT dX=X1-X2; + FLOAT dY=Y1-Y2; + return sqrtf(dX*dX + dY*dY); +} + +#ifndef ISXEQ +static inline FLOAT GetDistance3D(FLOAT X1, FLOAT Y1, FLOAT Z1, FLOAT X2, FLOAT Y2, FLOAT Z2) +{ + FLOAT dX = X1 - X2; + FLOAT dY = Y1 - Y2; + FLOAT dZ = Z1 - Z2; + return sqrtf(dX*dX + dY*dY + dZ*dZ); +} +#endif + + +// *************************************************************************** +// Function: DistanceToSpawn +// Description: Return the distance between two spawns +// *************************************************************************** +static inline FLOAT GetDistance(PSPAWNINFO pChar, PSPAWNINFO pSpawn) +{ + FLOAT X = pChar->X - pSpawn->X; + FLOAT Y = pChar->Y - pSpawn->Y; + //FLOAT Z = pChar->Z - pSpawn->Z; + return sqrtf(X*X + Y*Y);// + Z*Z); +} + +#define DistanceToSpawn(pChar,pSpawn) GetDistance(pChar,pSpawn) + +#define _FileExists(filename) ( (_access( filename, 0 )) != -1 ) +// *************************************************************************** +// FindMount(PSPAWNINFO) - Used to find the mount of a spawn, if one +// exists. returns the spawn if one does not. +// *************************************************************************** +static inline PSPAWNINFO FindMount(PSPAWNINFO pSpawn) +{ + return (pSpawn->Mount?pSpawn->Mount:pSpawn); +} + + +// *************************************************************************** +// Function: ConColorToRGB +// Description: Returns the RGB color for a con color +// *************************************************************************** +static inline DWORD ConColorToARGB(DWORD ConColor) +{ + switch (ConColor) + { + case CONCOLOR_GREY: + return 0xFF505050; + case CONCOLOR_GREEN: + return 0xFF00FF00; + case CONCOLOR_LIGHTBLUE: + return 0xFF00FFFF; + case CONCOLOR_BLUE: + return 0xFF0000FF; + case CONCOLOR_WHITE: + return 0xFFFFFFFF; + case CONCOLOR_YELLOW: + return 0xFFFFFF00; + case CONCOLOR_RED: + default: + return 0xFFFF0000; + } +} + +static inline BOOL IsRaidMember(PSPAWNINFO pSpawn) +{ + + if (!pSpawn || !pRaid) + return false; + + for (DWORD N = 0 ; N < 72 ; N++) + { + if (pRaid->RaidMemberUsed[N] && !stricmp(pSpawn->Name,pRaid->RaidMember[N].Name)) + return true; + } + return false; +} + +static inline BOOL IsGroupMember(PSPAWNINFO pSpawn) +{ + if (!pSpawn) + return false; + + PCHARINFO pChar=GetCharInfo(); + if (!pChar || !pChar->pGroupInfo) return 0; + for (DWORD N=1; N<6; N++) + { + if (pChar->pGroupInfo->pMember[N]) + { + CHAR Name[MAX_STRING]={0}; + GetCXStr(pChar->pGroupInfo->pMember[N]->pName,Name,MAX_STRING); + if (!stricmp(pSpawn->Name,Name)) + return true; + } + } + return false; +} + +static inline PSPAWNINFO GetRaidMember(unsigned long N) +{ + if (N>=72) + return 0; + PEQRAIDMEMBER pRaidMember=&pRaid->RaidMember[N]; + + if (!pRaidMember) + + return 0; + + return (PSPAWNINFO)GetSpawnByName(pRaidMember->Name); + +} + +static inline PSPAWNINFO GetGroupMember(unsigned long N) +{ + if (N>5) + return false; + PCHARINFO pChar=GetCharInfo(); + if (!pChar->pGroupInfo) return 0; + for (unsigned long i=1; i<6; i++) + { + if (pChar->pGroupInfo->pMember[i]) + { + N--; + if (N==0) + { + CHAR Name[MAX_STRING]={0}; + GetCXStr(pChar->pGroupInfo->pMember[i]->pName,Name,MAX_STRING); + return (PSPAWNINFO)GetSpawnByName(Name); + } + } + } + return 0; +} + +#ifndef ISXEQ +static inline BOOL IsNumber(PCHAR String) +{ + if (*String==0) + return FALSE; + if (*String=='-') + String++; + while(*String) + { + if (!((*String>='0' && *String<='9') || *String=='.')) + return FALSE; + ++String; + } + return TRUE; +} +#endif +#define Warp 0 + +static inline BOOL IsNumberToComma(PCHAR String) +{ + if (*String==0) + return FALSE; + PCHAR Temp=String; + while(*String) + { + if (!((*String>='0' && *String<='9') || *String=='.')) + { + if (*String==',' && Temp!=String) + return TRUE; + return FALSE; + } + ++String; + } + return TRUE; +} + +static inline BOOL LineOfSight(PSPAWNINFO Origin, PSPAWNINFO CanISeeThis) +{ + return CastRay(Origin,CanISeeThis->Y,CanISeeThis->X,CanISeeThis->Z); +} + +static inline BOOL IsMobFleeing(PSPAWNINFO pChar, PSPAWNINFO pSpawn) +{ + FLOAT HeadingTo = (FLOAT)(atan2f(pChar->Y - pSpawn->Y, pSpawn->X - pChar->X) * 180.0f / PI + 90.0f); + FLOAT Heading = pSpawn->Heading*0.703125f; + + if (HeadingTo<0.0f) + HeadingTo += 360.0f; + else if (HeadingTo>=360.0f) + HeadingTo -= 360.0f; + + FLOAT UB = HeadingTo + 120.0f; + FLOAT LB = HeadingTo - 120.0f; + + if (LB < UB) return ((Heading < UB) && (Heading > LB)); + else return ((Heading < LB) && (Heading > UB)); +} + +static inline DWORD FixOffset(DWORD nOffset) +{ + return ((nOffset - 0x400000) + baseAddress); +} diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2Internal.h b/client_files/native_autoloot/eq-core-dll/src/MQ2Internal.h new file mode 100644 index 0000000000..a3ac1b40f3 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2Internal.h @@ -0,0 +1,998 @@ +#pragma once +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +namespace MQ2Internal { + + enum ePVPServer + { + PVP_NONE = 0, + PVP_TEAM = 1, + PVP_RALLOS = 2, + PVP_SULLON = 3, + }; + + enum eSpawnType + { + NONE=0, + PC, + MOUNT, + PET, + NPC, + CORPSE, + TRIGGER, + TRAP, + TIMER, + UNTARGETABLE, + CHEST, + ITEM, + AURA, + OBJECT, + BANNER, + CAMPFIRE, + MERCENARY, + FLYER, + NPCCORPSE=2000, + PCCORPSE, + }; + + typedef struct _SEARCHSPAWN { + DWORD MinLevel; + DWORD MaxLevel; + eSpawnType SpawnType; + DWORD SpawnID; + DWORD FromSpawnID; + FLOAT Radius; + CHAR szName[MAX_STRING]; + CHAR szBodyType[MAX_STRING]; + CHAR szRace[MAX_STRING]; + CHAR szClass[MAX_STRING]; + CHAR szLight[MAX_STRING]; + DWORD GuildID; + BOOL bSpawnID; + BOOL bNotNearAlert; + BOOL bNearAlert; + BOOL bNoAlert; + BOOL bAlert; + BOOL bLFG; + BOOL bTrader; + BOOL bLight; + BOOL bTargNext; + BOOL bTargPrev; + BOOL bGroup; + BOOL bRaid; + BOOL bGM; + BOOL bNamed; + BOOL bMerchant; + BOOL bTributeMaster; + BOOL bKnight; + BOOL bTank; + BOOL bHealer; + BOOL bDps; + BOOL bSlower; + BOOL bAura; + BOOL bBanner; + BOOL bCampfire; + DWORD NotID; + DWORD NotNearAlertList; + DWORD NearAlertList; + DWORD NoAlertList; + DWORD AlertList; + DOUBLE ZRadius; + DOUBLE FRadius; + FLOAT xLoc; + FLOAT yLoc; + BOOL bKnownLocation; + BOOL bNoPet; + DWORD SortBy; + BOOL bNoGuild; + BOOL bLoS; + BOOL bExactName; + BOOL bTargetable; + } SEARCHSPAWN, *PSEARCHSPAWN; + + static enum SearchItemFlag + { + Lore=1, + NoDrop=2, + NoRent=3, + Magic=4, + Book=5, + Pack=6, + Combinable=7, + Summoned=8, + Weapon=9, + Normal=10, + Instrument=11, + + // item locations... + Worn=100, + Inventory=101, + Bank=102, + Merchant=103, + Corpse=104, + SharedBank=105, + Trade=106, + Bazaar=107, + Inspect=108, + Enviro=109, + + }; + + typedef struct _SEARCHITEM { + CHAR FlagMask[MAX_STRING]; + CHAR Flag[MAX_STRING]; + + CHAR szName[MAX_STRING]; + DWORD ID; + + } SEARCHITEM, *PSEARCHITEM; + + typedef struct _SWHOFILTER { + BOOL Lastname; + BOOL Class; + BOOL Race; + BOOL Body; + BOOL Level; + BOOL Distance; + BOOL GM; + BOOL Guild; + BOOL LD; + BOOL Sneak; + BOOL Anon; + BOOL LFG; + BOOL NPCTag; + BOOL SpawnID; + BOOL Trader; + BOOL AFK; + BOOL Light; + BOOL Holding; + BOOL ConColor; + BOOL Invisible; + } SWHOFILTER, *PSWHOFILTER; + + typedef struct _SWHOSORT { + CHAR szName[MAX_STRING]; + CHAR szLine[MAX_STRING]; + BYTE Level; + DWORD SpawnID; + FLOAT Distance; + DWORD Class; + DWORD Race; + DWORD GuildID; + } SWHOSORT, *PSWHOSORT; + + typedef struct _CONNECTION { + SOCKET socket; + BOOL Auth; + struct _CONNECTION *pNext; + } CONNECTION, *PCONNECTION; + + typedef struct _CHATBUF { + CHAR szText[MAX_STRING]; + struct _CHATBUF *pNext; + } CHATBUF, *PCHATBUF; + + + typedef struct _MOUSEINFO { + DWORD X; + DWORD Y; + DWORD SpeedX; + DWORD SpeedY; + } MOUSEINFO, *PMOUSEINFO; + + + typedef struct _SPELLINFO { + CHAR Name[32]; + CHAR Target[32]; + } SPELLINFO, *PSPELLINFO; + + typedef struct _PACKLOC { + DWORD X; + DWORD Y; + } PACKLOC, *PPACKLOC; + + typedef struct _MACROBLOCK { + CHAR Line[MAX_STRING]; + CHAR SourceFile[MAX_STRING]; + DWORD LineNumber; + BOOL MacroCmd; +#ifdef MQ2_PROFILING + DWORD ExecutionCount; + LONGLONG ExecutionTime; +#endif + struct _MACROBLOCK *pNext; + struct _MACROBLOCK *pPrev; + } MACROBLOCK, *PMACROBLOCK; + + + typedef struct _ALERT { + SEARCHSPAWN SearchSpawn; + struct _ALERT *pNext; + } ALERT, *PALERT; + + typedef struct _ALERTLIST { + DWORD Id; + PALERT pAlert; + struct _ALERTLIST *pNext; + } ALERTLIST, *PALERTLIST; + + typedef struct _MQTIMER { + CHAR szName[MAX_VARNAME]; + ULONG Original; + ULONG Current; + struct _MQTIMER *pNext; + struct _MQTIMER *pPrev; + } MQTIMER, *PMQTIMER; + + typedef struct _KEYPRESS { + WORD KeyId; + BOOL Pressed; + struct _KEYPRESS *pNext; + } KEYPRESS, *PKEYPRESS; + + typedef struct _DIKEYID { + CHAR szName[32]; + WORD Id; + } DIKEYID, *PDIKEYID; + + typedef struct _ITEMDB { + struct _ITEMDB *pNext; + DWORD ID; + CHAR szName[256]; + } ITEMDB, *PITEMDB; + + typedef struct _DEFINE { + struct _DEFINE *pNext; + CHAR szName[MAX_STRING]; + CHAR szReplace[MAX_STRING]; + } DEFINE, *PDEFINE; + + typedef struct _EVENTLIST { + struct _EVENTLIST *pNext; + CHAR szName[MAX_STRING]; + CHAR szMatch[MAX_STRING]; + PMACROBLOCK pEventFunc; +#ifdef USEBLECHEVENTS + DWORD BlechID; +#endif + } EVENTLIST, *PEVENTLIST; + + + typedef struct _ALIAS { + struct _ALIAS *pNext; + struct _ALIAS *pLast; + CHAR szName[MAX_STRING]; + CHAR szCommand[MAX_STRING]; + } ALIAS, *PALIAS; + + typedef struct _SUB { + struct _SUB *pNext; + struct _SUB *pLast; + CHAR szOrig[MAX_STRING]; + CHAR szSub[MAX_STRING]; + } SUB, *PSUB; + + typedef struct _MQCOMMAND { + CHAR Command[64]; + fEQCommand Function; + BOOL EQ; + BOOL Parse; + BOOL InGameOnly; + struct _MQCOMMAND* pLast; + struct _MQCOMMAND* pNext; + } MQCOMMAND, *PMQCOMMAND; + + + typedef struct _FILTER { + struct _FILTER *pNext; + CHAR FilterText[MAX_STRING]; + DWORD Length; + PBOOL pEnabled; + } FILTER, *PFILTER; + + typedef struct _PARMLIST { + CHAR szName[MAX_STRING]; + DWORD (__cdecl *fAddress)(PCHAR, PCHAR, PSPAWNINFO); + } PARMLIST, *PPARMLIST; + + typedef struct _MQXMLFile + { + char szFilename[MAX_PATH]; + _MQXMLFile *pLast; + _MQXMLFile *pNext; + } MQXMLFILE, *PMQXMLFILE; + + typedef struct _MQBENCH + { + CHAR szName[64]; + DWORD Entry; + DWORD LastTime; + DWORD TotalTime; + DWORD Count; + } MQBENCH, *PMQBENCH; + + typedef struct _MQGroundPending + { + PGROUNDITEM pGroundItem; + struct _MQGroundPending *pLast; + struct _MQGroundPending *pNext; + } MQGROUNDPENDING, *PMQGROUNDPENDING; + + typedef struct _MQPlugin + { + char szFilename[MAX_PATH]; + HMODULE hModule; + float fpVersion; + + fMQInitializePlugin Initialize; + fMQShutdownPlugin Shutdown; + fMQZoned Zoned; + fMQWriteChatColor WriteChatColor; + fMQPulse Pulse; + fMQIncomingChat IncomingChat; + fMQCleanUI CleanUI; + fMQReloadUI ReloadUI; + fMQDrawHUD DrawHUD; + fMQSetGameState SetGameState; + fMQSpawn AddSpawn; + fMQSpawn RemoveSpawn; + fMQGroundItem AddGroundItem; + fMQGroundItem RemoveGroundItem; + fMQBeginZone BeginZone; + fMQEndZone EndZone; + struct _MQPlugin* pLast; + struct _MQPlugin* pNext; + } MQPLUGIN, *PMQPLUGIN; + + typedef struct _actordefentry { + unsigned int Def; + char Name[256]; + } ACTORDEFENTRY, *PACTORDEFENTRY; + + class CAutoLock { + public: + inline void Lock() { if (!bLocked) { EnterCriticalSection(pLock); bLocked = TRUE; }} + inline void Unlock() { if (bLocked) { LeaveCriticalSection(pLock); bLocked = FALSE; }} + CAutoLock(LPCRITICAL_SECTION _pLock) { bLocked = FALSE; pLock = _pLock; Lock(); } + ~CAutoLock() { Unlock(); } + + private: + LPCRITICAL_SECTION pLock; + BOOL bLocked; + }; + + class CCustomWnd : public CSidlScreenWnd + { + public: + CCustomWnd(CXStr *screenpiece):CSidlScreenWnd(0,screenpiece,-1,1,0) + { + CreateChildrenFromSidl(); + pXWnd()->Show(1,1); + ReplacevfTable(); + CloseOnESC=0; + } + + CCustomWnd(char *screenpiece):CSidlScreenWnd(0,&CXStr(screenpiece),-1,1,0) + { + CreateChildrenFromSidl(); + pXWnd()->Show(1,1); + ReplacevfTable(); + CloseOnESC=0; + } + + ~CCustomWnd() + { + RemovevfTable(); + } + + // int WndNotification(CXWnd *pWnd, unsigned int Message, void *unknown) + // { + // return CSidlScreenWnd::WndNotification(pWnd,Message,unknown); + // } + + void ReplacevfTable() + { + OldvfTable=((_CSIDLWND*)this)->pvfTable; + PCSIDLWNDVFTABLE NewvfTable=new CSIDLWNDVFTABLE; + memcpy(NewvfTable,OldvfTable,sizeof(CSIDLWNDVFTABLE)); + ((_CSIDLWND*)this)->pvfTable=NewvfTable; + } + + void RemovevfTable() + { + PCSIDLWNDVFTABLE NewvfTable=((_CSIDLWND*)this)->pvfTable; + ((_CSIDLWND*)this)->pvfTable=OldvfTable; + delete NewvfTable; + } + + void SetvfTable(DWORD index, DWORD value) + { + DWORD* vtable=(DWORD*)((_CSIDLWND*)this)->pvfTable; + vtable[index]=value; + } + + PCSIDLWNDVFTABLE OldvfTable; + + // inline CXWnd *GetChildItem(const char *Name) {return CSidlScreenWnd::GetChildItem(Name);}; + }; + +#if !defined(ISXEQ) && !defined(ISXEQ_LEGACY) + /* CIndex class stolen from teqim - Lax */ + template + class CIndex + { + public: + CIndex() + { + InitializeCriticalSection(&CS); + Size=0; + List=0; + } + + CIndex(unsigned long InitialSize) + { + InitializeCriticalSection(&CS); + Size=0; + List=0; + Resize(InitialSize); + } + + ~CIndex() + {// user is responsible for managing elements + CAutoLock L(&CS); + if (List) + free(List); + List=0; + Size=0; + DeleteCriticalSection(&CS); + } + + void Cleanup() + { + for (unsigned long i = 0 ; i < Size ; i++) + { + if (List[i]) + { + delete List[i]; + List[i]=0; + } + } + } + + void Resize(unsigned long NewSize) + { + CAutoLock L(&CS); + if (List) + { + if (NewSize>Size) + { + // because we want to zero out the unused portions, we wont use realloc + Any *NewList=(Any*)malloc(NewSize*sizeof(Any)); + memset(NewList,0,NewSize*sizeof(Any)); + memcpy(NewList,List,Size*sizeof(Any)); + free(List); + List=NewList; + Size=NewSize; + } + } + else + { + List=(Any*)malloc(NewSize*sizeof(Any)); + memset(List,0,NewSize*sizeof(Any)); + Size=NewSize; + } + } + + // gets the next unused index, resizing if necessary + inline unsigned long GetUnused() + { + unsigned long i; + CAutoLock L(&CS); + for (i = 0 ; i < Size ; i++) + { + if (!List[i]) + return i; + } + Resize(Size+10); + return i; + } + + unsigned long Count() + { + CAutoLock L(&CS); + unsigned long ret=0; + for (unsigned long i = 0 ; i < Size ; i++) + { + if (List[i]) + ret++; + } + return ret; + } + + unsigned long Size; + Any *List; + + inline Any& operator+=(Any& Value){return List[GetUnused()]=Value;} + inline Any& operator[](unsigned long Index){return List[Index];} + CRITICAL_SECTION CS; + }; +#endif + + typedef struct _MQ2VarPtr + { + union { + PVOID Ptr; + FLOAT Float; + DWORD DWord; + ARGBCOLOR Argb; + int Int; + UCHAR Array[4]; + }; + } MQ2VARPTR, *PMQ2VARPTR; + +#ifndef ISXEQ + + typedef struct _MQ2TypeVar + { + class MQ2Type *Type; + union { + MQ2VARPTR VarPtr; + PVOID Ptr; + FLOAT Float; + DWORD DWord; + ARGBCOLOR Argb; + int Int; + UCHAR Array[4]; + }; + } MQ2TYPEVAR, *PMQ2TYPEVAR; + + typedef struct _MQ2TypeMember + { + DWORD ID; + PCHAR Name; + } MQ2TYPEMEMBER, *PMQ2TYPEMEMBER; + + typedef BOOL (__cdecl *fMQData)(PCHAR szIndex, MQ2TYPEVAR &Ret); + + typedef struct _MQ2DataItem + { + CHAR Name[64]; + fMQData Function; + } MQ2DATAITEM, *PMQ2DATAITEM; + + LEGACY_API BOOL AddMQ2Type(class MQ2Type &Type); + LEGACY_API BOOL RemoveMQ2Type(class MQ2Type &Type); + + typedef struct _DATAVAR { + CHAR szName[MAX_STRING]; + MQ2TYPEVAR Var; + struct _DATAVAR *pNext; + struct _DATAVAR *pPrev; + struct _DATAVAR **ppHead; + } DATAVAR, *PDATAVAR; + + class MQ2Type + { + public: + inline MQ2Type(PCHAR NewName) + { + strncpy(TypeName,NewName,32); + TypeName[31]=0; + Official=AddMQ2Type(*this); + pInherits=0; + } + + inline void InitializeMembers(PMQ2TYPEMEMBER MemberArray) + { + for (unsigned long i = 0 ; MemberArray[i].ID ; i++) + { + AddMember(MemberArray[i].ID,MemberArray[i].Name); + } + } + + inline ~MQ2Type() + { + if (Official) + RemoveMQ2Type(*this); + Members.Cleanup(); + } + + virtual bool FromData(MQ2VARPTR &VarPtr, MQ2TYPEVAR &Source)=0; + virtual bool FromString(MQ2VARPTR &VarPtr, PCHAR Source)=0; + virtual void InitVariable(MQ2VARPTR &VarPtr) {VarPtr.Ptr=0;} + virtual void FreeVariable(MQ2VARPTR &VarPtr) {} + + virtual bool GetMember(MQ2VARPTR VarPtr, PCHAR Member, PCHAR Index, MQ2TYPEVAR &Dest)=0; + // virtual bool SetMember(PVOID Ptr, PCHAR Member, DWORD Index, MQ2TYPEVAR &Data)=0; + virtual bool ToString(MQ2VARPTR VarPtr, PCHAR Destination) + { + strcpy(Destination,TypeName); + return true; + } + + inline PCHAR GetName() {return &TypeName[0];} + + PCHAR GetMemberName(DWORD ID) + { + for (unsigned long N=0 ; N < Members.Size ; N++) + { + if (PMQ2TYPEMEMBER pMember = Members[N]) + { + if (pMember->ID==ID) + return &pMember->Name[0]; + } + } + return 0; + } + + BOOL GetMemberID(PCHAR Name, DWORD &Result) + { + unsigned long N=MemberMap[Name]; + if (N==0) + return false; + N--; + PMQ2TYPEMEMBER pMember = Members[N]; + Result=pMember->ID; + return true; + } + PMQ2TYPEMEMBER FindMember(PCHAR Name) + { + unsigned long N=MemberMap[Name]; + if (!N) + return 0; + N--; + return Members[N]; + } + BOOL InheritedMember(PCHAR Name) + { + if (!pInherits || !pInherits->FindMember(Name)) + return FALSE; + return TRUE; + } + void SetInheritance(MQ2Type *pNewInherit) + { + pInherits=pNewInherit; + } + + protected: + + inline BOOL AddMember(DWORD ID, PCHAR Name) + { + unsigned long N=MemberMap[Name]; + if (N>0) + return false; + N=Members.GetUnused(); + MemberMap[Name]=N+1; + PMQ2TYPEMEMBER pMember = new MQ2TYPEMEMBER; + pMember->Name=Name; + pMember->ID=ID; + Members[N]=pMember; + return true; + } + + inline BOOL RemoveMember(PCHAR Name) + { + unsigned long N=MemberMap[Name]; + if (N==0) + return false; + N--; + PMQ2TYPEMEMBER pMember = Members[N]; + delete pMember; + Members[N]=0; + } + + CHAR TypeName[32]; + BOOL Official; + CIndex Members; + map MemberMap; + MQ2Type *pInherits; + }; + + class CDataArray + { + public: + CDataArray() + { + pType=0; + nExtents=0; + pExtents=0; + pData=0; + TotalElements=0; + } + + CDataArray(MQ2Type *Type, PCHAR Index, PCHAR Default, BOOL ByData=FALSE) + { + nExtents=1; + + // count number of , 's + if (PCHAR pComma=strchr(Index,',')) + { + nExtents++; + while(pComma=strchr(&pComma[1],',')) + { + nExtents++; + } + } + + // allocate extents + + pExtents=(DWORD*)malloc(sizeof(DWORD)*nExtents); + + TotalElements=1; + + // read extents + PCHAR pStart=Index; + unsigned long N; + for (N = 0 ; N < nExtents ; N++) + { + PCHAR pComma=strchr(pStart,','); + if (pComma) + *pComma=0; + + pExtents[N]=atoi(pStart); + TotalElements*=pExtents[N]; + if (pComma) + { + *pComma=','; + pStart=&pComma[1]; + } + } + + pData = (MQ2VARPTR*) malloc(sizeof(MQ2VARPTR)*TotalElements); + + if (pType=Type) + for (N = 0 ; N < TotalElements ; N++) + { + pType->InitVariable(pData[N]); + if (ByData) + pType->FromData(pData[N],*(MQ2TYPEVAR *)Default); + else + pType->FromString(pData[N],Default); + } + + } + + void Delete() + { + if (pExtents) + free(pExtents); + if (pType && pData) + for (unsigned long N = 0 ; N < TotalElements ; N++) + { + pType->FreeVariable(pData[N]); + } + free(pData); + pType=0; + nExtents=0; + pExtents=0; + pData=0; + TotalElements=0; + } + + int GetElement(PCHAR Index) + { + DWORD Element=0; + if (nExtents==1) + { + if (strchr(Index,',')) + return -1; + Element=atoi(Index)-1; + if (Element>=TotalElements) + return -1; + return Element; + } + else + { + DWORD nGetExtents = 1; + + if (PCHAR pComma=strchr(Index,',')) + { + nGetExtents++; + while(pComma=strchr(&pComma[1],',')) + { + nGetExtents++; + } + } + if (nGetExtents!=nExtents) + return -1; + + // read extents + PCHAR pStart=Index; + unsigned long N; + for (N = 0 ; N < nExtents ; N++) + { + PCHAR pComma=strchr(pStart,','); + if (pComma) + *pComma=0; + + DWORD Temp=atoi(pStart)-1; + if (Temp>=pExtents[N]) + return -1; + for (unsigned long i = N+1 ; i < nExtents; i++) + Temp*=pExtents[i]; + Element+=Temp; + + if (pComma) + { + *pComma=','; + pStart=&pComma[1]; + } + } + if (Element>=TotalElements) + { + // bug in array logic + OutputDebugString("Bug in array logic\n"); + return -1; + } + return Element; + } + } + + BOOL GetElement(PCHAR Index, MQ2TYPEVAR &Dest) + { + DWORD Element=0; + if (nExtents==1) + { + if (strchr(Index,',')) + return FALSE; + Element=atoi(Index)-1; + if (Element>=TotalElements) + return FALSE; + Dest.Type=pType; + Dest.VarPtr=pData[Element]; + return TRUE; + } + else + { + DWORD nGetExtents = 1; + + if (PCHAR pComma=strchr(Index,',')) + { + nGetExtents++; + while(pComma=strchr(&pComma[1],',')) + { + nGetExtents++; + } + } + if (nGetExtents!=nExtents) + return FALSE; + + // read extents + PCHAR pStart=Index; + unsigned long N; + for (N = 0 ; N < nExtents ; N++) + { + PCHAR pComma=strchr(pStart,','); + if (pComma) + *pComma=0; + + DWORD Temp=atoi(pStart)-1; + if (Temp>=pExtents[N]) + return FALSE; + for (unsigned long i = N+1 ; i < nExtents; i++) + Temp*=pExtents[i]; + Element+=Temp; + + if (pComma) + { + *pComma=','; + pStart=&pComma[1]; + } + } + if (Element>=TotalElements) + { + // bug in array logic + OutputDebugString("Bug in array logic\n"); + return FALSE; + } + Dest.Type=pType; + Dest.VarPtr=pData[Element]; + return TRUE; + } + + } + + ~CDataArray() + { + if (pExtents) + free(pExtents); + if (pType && pData) + for (unsigned long N = 0 ; N < TotalElements ; N++) + { + pType->FreeVariable(pData[N]); + } + free(pData); + } + + MQ2Type *pType; + DWORD nExtents; + DWORD *pExtents; + MQ2VARPTR *pData; + DWORD TotalElements; + }; +#endif + + typedef struct _MQRANK + { + MQ2VARPTR VarPtr; + MQ2VARPTR Value; + } MQRANK, *PMQRANK; + + static int pMQRankFloatCompare(const void *A, const void *B) + { + if ((*(PMQRANK*)A)->Value.Float==(*(PMQRANK*)B)->Value.Float) + return 0; + if ((*(PMQRANK*)A)->Value.Float<(*(PMQRANK*)B)->Value.Float) + return -1; + return 1; + } + + static int MQRankFloatCompare(const void *A, const void *B) + { + if (((PMQRANK)A)->Value.Float==((PMQRANK)B)->Value.Float) + return 0; + if (((PMQRANK)A)->Value.Float<((PMQRANK)B)->Value.Float) + return -1; + return 1; + } + + static int MQRankFloatCompareReverse(const void *A, const void *B) + { + if (((PMQRANK)A)->Value.Float==((PMQRANK)B)->Value.Float) + return 0; + if (((PMQRANK)A)->Value.Float>((PMQRANK)B)->Value.Float) + return -1; + return 1; + } + + static int MQRankCompare(const void *A, const void *B) + { + if (((PMQRANK)A)->Value.DWord==((PMQRANK)B)->Value.DWord) + return 0; + if (((PMQRANK)A)->Value.DWord<((PMQRANK)B)->Value.DWord) + return -1; + return 1; + } + + static int MQRankCompareReverse(const void *A, const void *B) + { + if (((PMQRANK)A)->Value.DWord==((PMQRANK)B)->Value.DWord) + return 0; + if (((PMQRANK)A)->Value.DWord>((PMQRANK)B)->Value.DWord) + return -1; + return 1; + } + +#ifndef ISXEQ + typedef struct _MACROSTACK { + PMACROBLOCK Location; + struct _MACROSTACK *pNext; + CHAR Return[MAX_STRING]; + PDATAVAR Parameters; + PDATAVAR LocalVariables; + } MACROSTACK, *PMACROSTACK; + + typedef struct _EVENTQUEUE { + struct _EVENTQUEUE *pPrev; + struct _EVENTQUEUE *pNext; + DWORD Type; + PEVENTLIST pEventList; + PDATAVAR Parameters; + } EVENTQUEUE, *PEVENTQUEUE; +#endif + +}; +using namespace MQ2Internal; + diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2ItemDisplay.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2ItemDisplay.cpp new file mode 100644 index 0000000000..88afebb047 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2ItemDisplay.cpp @@ -0,0 +1,642 @@ +// MQ2ItemDisplay.cpp : Defines the entry point for the DLL application. +// + +// PLUGIN_API is only to be used for callbacks. All existing callbacks at this time +// are shown below. Remove the ones your plugin does not use. Always use Initialize +// and Shutdown for setup and cleanup, do NOT do it in DllMain. + + +#ifndef ISXEQ +#include "MQ2Main.h" +#else +#include "../ISXEQClient.h" +#include "ISXEQItemDisplay.h" +#endif + +// thanks, finally, SOE. we'll leave this here for a while and eventually remove it +#define DISABLE_TOOLTIP_TIMERS + +void Comment(PSPAWNINFO pChar, PCHAR szLine); + +extern "C" { + __declspec(dllexport) ITEMINFO g_Item; + CONTENTS g_Contents; +} + +// *************************************************************************** +// Function: ItemDisplayHook +// Description: Our Item display hook +// *************************************************************************** +class ItemDisplayHook +{ + typedef enum {None = 0, Clicky, Proc, Worn, Focus, Scroll} SEffectType; + + static bool bNoSpellTramp; + static SEffectType eEffectType; +public: + bool CXStrReplace (PCXSTR * Str, const char * cFind, const char * cReplace) + { + char cTemp[2048]; + DWORD dwSize = GetCXStr (*Str, cTemp, sizeof (cTemp)); + if (dwSize > 0 && dwSize < sizeof (cTemp) - 20) { + char * cPtr = strstr (cTemp, cFind); + if (cPtr != NULL) { + char * cDup = strdup (cPtr); + + strcpy (cPtr, cReplace); + strcpy (cPtr + strlen (cReplace), cDup + strlen (cFind)); + + free (cDup); + + SetCXStr (Str, cTemp); + return true; + } + } + + return false; + } + + const char * GetRaceThreeLetterCode (int iRace) + { + switch (iRace) + { + case 1: return ("HUM"); + case 2: return ("BAR"); + case 3: return ("ERU"); + case 4: return ("ELF"); + case 5: return ("HIE"); + case 6: return ("DEF"); + case 7: return ("HEF"); + case 8: return ("DWF"); + case 9: return ("TRL"); + case 10:return ("OGR"); + case 11:return ("HLF"); + case 12:return ("GNM"); + case 13:return ("IKS"); + case 14:return ("VAH"); + case 15:return ("FRG"); + case 16:return ("DRK"); + case 17:return ("SHD"); //shroud + } + + return ("UNKNOWN RACE"); + } + int GetDmgBonus (PCXSTR * Str) + { + char cTemp[2048]; + INT dmgbonuspos; + INT dmgbonus = 0; + INT badcharpos; + + GetCXStr(*Str, cTemp, sizeof (cTemp)); + + string ItemDisplay; + ItemDisplay = cTemp; + + char ActualDmgBonus[3]; + + dmgbonuspos = ItemDisplay.find("Dmg Bonus:"); + + if (dmgbonuspos != string::npos) { + dmgbonuspos = dmgbonuspos + 11; + ItemDisplay = ItemDisplay.substr(dmgbonuspos,3); + + badcharpos = ItemDisplay.find(" "); + + if (badcharpos != string::npos) { //found blank + ItemDisplay = ItemDisplay.substr(0,2); + }else{ + //badcharpos = tmpActualDmgBonus.find("<"); + badcharpos = ItemDisplay.find("<"); + if (badcharpos != string::npos) { //found < + ItemDisplay = ItemDisplay.substr(0,2); + } + } + + strcpy (ActualDmgBonus,ItemDisplay.c_str()); + dmgbonus = atoi(ActualDmgBonus); + } + + return dmgbonus; + } + + VOID SetSpell_Trampoline(int SpellID,bool HasSpellDescr); + VOID SetSpell_Detour(int SpellID,bool HasSpellDescr) + { + PEQSPELLINFOWINDOW This=(PEQSPELLINFOWINDOW)this; + PCHARINFO pCharInfo = NULL; + if (NULL == (pCharInfo = GetCharInfo())) return; + PSPELL pSpell = GetSpellByID(SpellID); + if (pSpell == NULL) { + return; + } + CHAR out[MAX_STRING] = {0}; + CHAR temp[MAX_STRING] = {0}; + if (!bNoSpellTramp) { + SetSpell_Trampoline(SpellID,HasSpellDescr); + strcpy(out,"
"); + } else { + char * cColour = "FF0000", * cName = "Blub"; + + switch (eEffectType) + { + case Clicky: + cColour = "00FF00"; + cName = "Clicky"; + break; + case Proc: + cColour = "FF00FF"; + cName = "Proc"; + break; + case Worn: + cColour = "FFFF00"; + cName = "Worn"; + break; + case Focus: + cColour = "9F9F00"; + cName = "Focus"; + break; + case Scroll: + cColour = "9F9F9F"; + cName = "Scroll"; + break; + } + + sprintf (out, "
Spell Info for %s effect: %s
", cColour, cName, pSpell->Name); + } + if (pLocalPlayer && pLocalPlayer->Data.GM) + { + sprintf(temp, "ID: %04d                            ", pSpell->ID); + strcat(out, temp); + } + DWORD Tics=GetSpellDuration(pSpell,pCharInfo->pSpawn); + if (Tics==0xFFFFFFFF) + strcat(out, "Duration: Permanent
" ); + else if (Tics==0xFFFFFFFE) + strcat(out, "Duration: Unknown
" ); + else if (Tics==0) { + // It's "instant", who cares? + strcat(out,"
"); + } + else { + sprintf(temp, "Duration: %1.1f minutes
",(float)((Tics*6.0f)/60.0f)); + strcat(out, temp); + } + + sprintf(temp, "RecoveryTime: %1.2f       RecastTime: %1.2f
", (float)(pSpell->FizzleTime/1000.0f), (float)(pSpell->RecastTime/1000.0f) ); + strcat(out,temp); + + if (pSpell->Range > 0.0f ) { + sprintf(temp, "Range: %1.0f", pSpell->Range ); + strcat(out,temp); + if ( pSpell->PushBack == 0.0f && pSpell->AERange == 0.0f) + strcat(out, "
"); + } + + if (pSpell->PushBack != 0.0f ) { + if (pSpell->Range > 0.0f ) + strcat(out, "                      " ); + sprintf(temp, "PushBack: %1.1f", pSpell->PushBack ); + strcat(out, temp); + if (pSpell->AERange == 0.0f || pSpell->Range > 0.0f ) + strcat(out, "
" ); + } + + if (pSpell->AERange > 0.0f ) { + if (pSpell->Range > 0.0f) + strcat(out, "                      " ); + else if (pSpell->PushBack > 0.0f ) + strcat(out, "                 " ); + sprintf(temp, "AERange: %1.0f
", pSpell->AERange ); + strcat(out, temp); + } + + if (pSpell->TargetType != 0x06 && pSpell->TargetType != 0x0e && pSpell->TargetType != 0x03 && pSpell->TargetType != 0x28 && pSpell->TargetType != 0x29 ) { + if (pSpell->SpellType == 0) { // Ziggy: Only show resist type for detrimental spells + switch(pSpell->Resist) + { + case 9: strcat(out, "Resist: Corruption" ); break; + case 7: strcat(out, "Resist: Prismatic[Avg]" ); break; // Ziggy - Added Reminder which.. + case 6: strcat(out, "Resist: Chromatic[Low]" ); break; // ..is what type of resist + case 5: strcat(out, "Resist: Disease" ); break; + case 4: strcat(out, "Resist: Poison" ); break; + case 3: strcat(out, "Resist: Cold/Ice" ); break; + case 2: strcat(out, "Resist: Fire" ); break; + case 1: strcat(out, "Resist: Magic" ); break; + case 0: strcat(out, "Resist: Unresistable"); break; + } + + if (pSpell->ResistAdj != 0 ) { + sprintf(temp, "   (Resist Adj.: %d)
", pSpell->ResistAdj ); + strcat(out,temp); + } else { + strcat(out,"
"); + } + } + } + + strcat(out, "
" ); + ShowSpellSlotInfo(pSpell,&out[strlen(out)]); + + //show usable classes routine by Koad// + + + bool bUseableClasses = false; + + if (pLocalPlayer && pLocalPlayer->Data.GM) + { + strcat(out, "
"); + for (int j = 0; j < 16; j++) { // Ziggy - output will word wrap properly now + if (pSpell->Level[j] > 0 && pSpell->Level[j] <= 70) { + if (bUseableClasses) strcat(out, ", "); + + sprintf(temp, "%s(%d)", GetClassDesc(j + 1), pSpell->Level[j]); + strcat(out, temp); + bUseableClasses = true; + } + } + if (bUseableClasses) strcat(out, "

"); + } + + if (pSpell->CastOnYou[0]) { + sprintf(temp, "Cast on you: %s
", pSpell->CastOnYou); + strcat(out,temp); + } + + if (pSpell->CastOnAnother[0]) { + sprintf(temp, "Cast on another: %s
", pSpell->CastOnAnother); + strcat(out,temp); + } + + if (pSpell->WearOff[0]) { + sprintf(temp, "Wears off: %s
", pSpell->WearOff); + strcat(out,temp); + } + + if (out[0]!=17) { + strcat(out,"
"); + AppendCXStr(&This->ItemInfo,&out[0]); + } + } + + VOID ItemSetSpell_Detour(int SpellID,bool HasSpellDescr) + { + PEQITEMWINDOW This=(PEQITEMWINDOW)this; + PCHARINFO pCharInfo = NULL; + if (NULL == (pCharInfo = GetCharInfo())) return; + PSPELL pSpell = GetSpellByID(SpellID); + if (pSpell == NULL) { + return; + } + + CHAR out[MAX_STRING] = {0}; + CHAR temp[MAX_STRING] = {0}; + if (!bNoSpellTramp) { + SetSpell_Trampoline(SpellID,HasSpellDescr); + strcpy(out,"
"); + } else { + char * cColour = "FF0000", * cName = "Blub"; + + switch (eEffectType) + { + case Clicky: + cColour = "00FF00"; + cName = "Clicky"; + break; + case Proc: + cColour = "FF00FF"; + cName = "Proc"; + break; + case Worn: + cColour = "FFFF00"; + cName = "Worn"; + break; + case Focus: + cColour = "9F9F00"; + cName = "Focus"; + break; + case Scroll: + cColour = "9F9F9F"; + cName = "Scroll"; + break; + } + + sprintf (out, "
Spell Info for %s effect: %s
", cColour, cName, pSpell->Name); + + if(This->ItemInfo && GetCXStr(This->ItemInfo, temp)) + { + if(strstr(temp, out)) + { + return; + } + } + } + if (pLocalPlayer && pLocalPlayer->Data.GM) + { + sprintf(temp, "ID: %04d                            ", pSpell->ID); + strcat(out, temp); + } + DWORD Tics=GetSpellDuration(pSpell,pCharInfo->pSpawn); + if (Tics==0xFFFFFFFF) + strcat(out, "Duration: Permanent
" ); + else if (Tics==0xFFFFFFFE) + strcat(out, "Duration: Unknown
" ); + else if (Tics==0) { + // It's "instant", who cares? + strcat(out,"
"); + } + else { + sprintf(temp, "Duration: %1.1f minutes
",(float)((Tics*6.0f)/60.0f)); + strcat(out, temp); + } + + sprintf(temp, "RecoveryTime: %1.2f       RecastTime: %1.2f
", (float)(pSpell->FizzleTime/1000.0f), (float)(pSpell->RecastTime/1000.0f) ); + strcat(out,temp); + + if (pSpell->Range > 0.0f ) { + sprintf(temp, "Range: %1.0f", pSpell->Range ); + strcat(out,temp); + if ( pSpell->PushBack == 0.0f && pSpell->AERange == 0.0f) + strcat(out, "
"); + } + + if (pSpell->PushBack != 0.0f ) { + if (pSpell->Range > 0.0f ) + strcat(out, "                      " ); + sprintf(temp, "PushBack: %1.1f", pSpell->PushBack ); + strcat(out, temp); + if (pSpell->AERange == 0.0f || pSpell->Range > 0.0f ) + strcat(out, "
" ); + } + + if (pSpell->AERange > 0.0f ) { + if (pSpell->Range > 0.0f) + strcat(out, "                      " ); + else if (pSpell->PushBack > 0.0f ) + strcat(out, "                 " ); + sprintf(temp, "AERange: %1.0f
", pSpell->AERange ); + strcat(out, temp); + } + + if (pSpell->TargetType != 0x06 && pSpell->TargetType != 0x0e && pSpell->TargetType != 0x03 && pSpell->TargetType != 0x28 && pSpell->TargetType != 0x29 ) { + if (pSpell->SpellType == 0) { // Ziggy: Only show resist type for detrimental spells + switch(pSpell->Resist) + { + case 9: strcat(out, "Resist: Corruption" ); break; + case 7: strcat(out, "Resist: Prismatic[Avg]" ); break; // Ziggy - Added Reminder which.. + case 6: strcat(out, "Resist: Chromatic[Low]" ); break; // ..is what type of resist + case 5: strcat(out, "Resist: Disease" ); break; + case 4: strcat(out, "Resist: Poison" ); break; + case 3: strcat(out, "Resist: Cold/Ice" ); break; + case 2: strcat(out, "Resist: Fire" ); break; + case 1: strcat(out, "Resist: Magic" ); break; + case 0: strcat(out, "Resist: Unresistable"); break; + } + + if (pSpell->ResistAdj != 0 ) { + sprintf(temp, "   (Resist Adj.: %d)
", pSpell->ResistAdj ); + strcat(out,temp); + } else { + strcat(out,"
"); + } + } + } + + strcat(out, "
" ); + ShowSpellSlotInfo(pSpell,&out[strlen(out)]); + + //show usable classes routine by Koad// + if (pLocalPlayer && pLocalPlayer->Data.GM) + { + bool bUseableClasses = false; + strcat(out, "
"); + for (int j = 0; j < 16; j++) { // Ziggy - output will word wrap properly now + if (pSpell->Level[j] > 0 && pSpell->Level[j] <= 70) { + if (bUseableClasses) strcat(out, ", "); + + sprintf(temp, "%s(%d)", GetClassDesc(j + 1), pSpell->Level[j]); + strcat(out, temp); + bUseableClasses = true; + } + } + if (bUseableClasses) strcat(out, "

"); + } + + if (pSpell->CastOnYou[0]) { + sprintf(temp, "Cast on you: %s
", pSpell->CastOnYou); + strcat(out,temp); + } + + if (pSpell->CastOnAnother[0]) { + sprintf(temp, "Cast on another: %s
", pSpell->CastOnAnother); + strcat(out,temp); + } + + if (pSpell->WearOff[0]) { + sprintf(temp, "Wears off: %s
", pSpell->WearOff); + strcat(out,temp); + } + + if (out[0]!=17) { + strcat(out,"
"); + //((CXStr)This->ItemInfo)+= + AppendCXStr(&This->ItemInfo,&out[0]); + } + } + + VOID UpdateStrings_Trampoline(); + VOID UpdateStrings_Detour() + { + PEQITEMWINDOW This=(PEQITEMWINDOW)this; + PCONTENTS item=(PCONTENTS)This->pItem; + volatile PITEMINFO Item=GetItemFromContents(item); + CHAR out[MAX_STRING] = {0}; + CHAR temp[MAX_STRING] = {0}; + CHAR temp2[MAX_STRING] = {0}; + PCHAR lore = NULL; + + UpdateStrings_Trampoline(); + + // keep a global copy of the last item displayed... + memcpy(&g_Item, Item, sizeof(ITEMINFO)); + + strcpy(out,"
"); + if ( Item->ItemNumber > 0 && pLocalPlayer && pLocalPlayer->Data.GM) { + sprintf(temp,"Item ID: %d
", Item->ItemNumber); + strcat(out, temp); + } + if ( ((EQ_Item*)item)->IsStackable() ) { + if ( Item->StackSize > 0 ) { + sprintf(temp,"Stackable Count: %d
", Item->StackSize); + strcat(out, temp); + } + } + if (Item->Cost>0) { + DWORD cp = Item->Cost; + DWORD sp = cp/10; cp=cp%10; + DWORD gp = sp/10; sp=sp%10; + DWORD pp = gp/10; gp=gp%10; + strcat(out,"Value:"); + if (pp>0) { + sprintf(temp," %dpp",pp); + strcat(out,temp); + } + if (gp>0) { + sprintf(temp," %dgp",gp); + strcat(out,temp); + } + if (sp>0) { + sprintf(temp," %dsp",sp); + strcat(out,temp); + } + if (cp>0) { + sprintf(temp," %dcp",cp); + strcat(out,temp); + } + strcat(out,"
"); + } + + if (Item->Clicky.TimerID!=0) { + int Secs = GetItemTimer(item); + if (!Secs) { + sprintf(temp,"Item Timer: Ready
"); + } else { + int Mins=(Secs/60)%60; + int Hrs=(Secs/3600); + Secs=Secs%60; + if (Hrs) + sprintf(temp,"Item Timer: %d:%02d:%02d
",Hrs,Mins,Secs); + else + sprintf(temp,"Item Timer: %d:%02d
",Mins,Secs); + } + strcat(out, temp); + } + + //Outlaw (AKA CheckinThingsOut) (02/24/2005) + if (Item->ItemType != 27) { //Arrows..they have dmg/dly but we don't want them + if ( Item->Delay > 0) { + if ( Item->Damage > 0) { + sprintf(temp,"Base DPS: %5.3f
", ((float)Item->Damage / (float)Item->Delay) * 10); + strcat(out, temp); + } + } + } + lore=Item->LoreName; + if (lore[0]=='*') lore++; + if (strcmp(lore,Item->Name)) { + sprintf(temp,"Item Lore: %s
",Item->LoreName); + strcat(out,temp); + } + PCHARINFO pChar = GetCharInfo(); // Ziggy - for item level highlights + // Will be 0 for no effect or -1 if other effects present + if (Item->Proc.SpellID && Item->Proc.SpellID!=-1) { + if (Item->Proc.RequiredLevel == 0 ) + sprintf(temp, "Procs at level 1 (Proc rate modifier: %d)
", Item->Proc.ProcRate); + else + sprintf(temp,"%sProcs at level %d%s (Proc rate modifier: %d)
", (Item->Proc.RequiredLevel > GetCharInfo2()->Level ? "" : ""), Item->Proc.RequiredLevel, (Item->Proc.RequiredLevel > GetCharInfo2()->Level ? "" : ""), Item->Proc.ProcRate); + strcat(out,temp); + } + /* No longer needed? + else if (Item->SpellId==998) { // 998 = haste + sprintf(temp,"%d%% Haste
",Item->Level+1); + strcat(out,temp); + } + */ + + // Just in case... + if (This->ItemInfo && (!strstr(This->ItemInfo->Text,"(Combat)")) && Item->Proc.ProcRate > 0 ) + { + sprintf(temp, "Proc rate Modifier: %d
", Item->Proc.ProcRate ); + strcat(out,temp); + } + + // Teh_Ish (02/08/2004) + if ( Item->Clicky.EffectType==4 || Item->Clicky.EffectType==1 || Item->Clicky.EffectType==5) { + if ( Item->Clicky.RequiredLevel == 0 ) + sprintf(temp, "Clickable at level 1
"); + else + sprintf(temp,"%sClickable at level %d%s
", (Item->Clicky.RequiredLevel > GetCharInfo2()->Level ? "" : ""), Item->Clicky.RequiredLevel, (Item->Clicky.RequiredLevel > GetCharInfo2()->Level ? "" : "")); + strcat(out,temp); + } + + // TheColonel (1/18/2004) + /* + if (Item->InstrumentType != 0){ + float instrumentmod = ((float)Item->InstrumentMod)/10.0f; + sprintf(temp,"Instrument mod: %3.1f to %s.
", instrumentmod, szItemTypes[Item->InstrumentType]); + strcat(out,temp); + } + /**/ + + if (Item->Type == ITEMTYPE_PACK) { + sprintf(temp,"Container Type: %s
",szCombineTypes[Item->Combine]); + strcat(out,temp); + } + + if (Item->ItemNumber > 0 && pLocalPlayer && pLocalPlayer->Data.GM) { + sprintf(temp, "%07d", Item->ItemNumber); + } + + if (out[0]!=17) { + strcat(out,"
"); + ((CStmlWnd*)This->DisplayWnd)->AppendSTML(&out[0]); + } + + // Ziggy - Items showing their spell details: + bNoSpellTramp=true; + if (Item->Clicky.SpellID > 0 && Item->Clicky.SpellID != -1) { + eEffectType = Clicky; + ItemSetSpell_Detour(Item->Clicky.SpellID, false); + } + + if (Item->Proc.SpellID > 0 && Item->Proc.SpellID != -1) { + eEffectType = Proc; + ItemSetSpell_Detour(Item->Proc.SpellID, false); + } + + if (Item->Worn.SpellID > 0 && Item->Worn.SpellID != -1) { + eEffectType = Worn; + ItemSetSpell_Detour(Item->Worn.SpellID, false); + } + + if (Item->Focus.SpellID > 0 && Item->Focus.SpellID != -1) { + eEffectType = Focus; + ItemSetSpell_Detour(Item->Focus.SpellID, false); + } + + if (Item->Scroll.SpellID > 0 && Item->Scroll.SpellID != -1) { + eEffectType = Scroll; + ItemSetSpell_Detour(Item->Scroll.SpellID, false); + } + bNoSpellTramp=false; + eEffectType = None; + } +}; + +ItemDisplayHook::SEffectType ItemDisplayHook::eEffectType = None; +bool ItemDisplayHook::bNoSpellTramp = false; + +DETOUR_TRAMPOLINE_EMPTY(VOID ItemDisplayHook::SetSpell_Trampoline(int SpellID,bool HasSpellDescr)); +DETOUR_TRAMPOLINE_EMPTY(VOID ItemDisplayHook::UpdateStrings_Trampoline()); + +#ifndef ISXEQ + +// Called once, when the plugin is to initialize +PLUGIN_API VOID InitializeMQ2ItemDisplay(VOID) +{ + memset(&g_Contents, 0, sizeof(g_Contents)); + g_Contents.Item1 = NULL; + g_Contents.Item2 = &g_Item; + g_Item.ItemNumber = 0; + + EzDetour(CItemDisplayWnd__SetSpell,&ItemDisplayHook::SetSpell_Detour,&ItemDisplayHook::SetSpell_Trampoline); + EzDetour(CItemDisplayWnd__UpdateStrings, &ItemDisplayHook::UpdateStrings_Detour, &ItemDisplayHook::UpdateStrings_Trampoline); +} + +// Called once, when the plugin is to shutdown +PLUGIN_API VOID ShutdownPlugin(VOID) +{ + RemoveDetour(CItemDisplayWnd__SetSpell); + RemoveDetour(CItemDisplayWnd__UpdateStrings); +} +#endif diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2KeyBinds.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2KeyBinds.cpp new file mode 100644 index 0000000000..9cadc32156 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2KeyBinds.cpp @@ -0,0 +1,624 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +#error /DCINTERFACE +#endif + +#define DBG_SPEW +#include "MQ2Main.h" +#include +#include +#include +using namespace std; + +void InjectMQ2Binds(COptionsWnd *pWnd); +void EjectMQ2Binds(COptionsWnd *pWnd); + +struct MQ2KeyBind +{ + char Name[32]; + KeyCombo Normal; + KeyCombo Alt; + fMQExecuteCmd Function; + BOOL State; +}; + +CIndex BindList(10); +map BindNameMap; + +inline MQ2KeyBind *KeyBindByName(char *Name) +{ + string Lwr=Name; + MakeLower(Lwr); + unsigned long N=BindNameMap[Lwr]; + if (!N) + return 0; + return BindList[--N]; +} + +inline void SetKeyBindNameMap(char *Name, unsigned long Number) +{ + string Lwr=Name; + MakeLower(Lwr); + BindNameMap[Lwr]=Number+1; +} + +inline void RemoveKeyBindNameMap(char *Name) +{ + string Lwr=Name; + MakeLower(Lwr); + BindNameMap[Lwr]=0; +} + +BOOL SetEQKeyBindByNumber(DWORD N, BOOL Alternate, KeyCombo &Combo) +{ + if (NAltKey[N] = Combo; + else + pKeypressHandler->NormalKey[N] = Combo; + + if(N < gnNormalEQMappableCommands) + pKeypressHandler->SaveKeymapping( N, Combo, Alternate ); + return TRUE; + } + return FALSE; +} + +inline BOOL SetEQKeyBind(PCHAR name, BOOL Alternate, KeyCombo &Combo ) +{ + return SetEQKeyBindByNumber(FindMappableCommand(name),Alternate,Combo); +} + +BOOL MQ2HandleKeyDown(class KeyCombo const &Combo) +{ + unsigned long N; + bool Ret=false; + for ( N = 0 ; N < nEQMappableCommands ; N++) + { + if (pKeypressHandler->CommandState[N]==0 && (pKeypressHandler->NormalKey[N]==Combo || + pKeypressHandler->AltKey[N]==Combo)) + { + ExecuteCmd(N,1,0); + pKeypressHandler->CommandState[N]=1; + Ret=true; + } + } + for ( N = 0 ; N < BindList.Size ; N++) + { + if (MQ2KeyBind *pBind=BindList[N]) + { + if (pBind->State==0 && (pBind->Normal==Combo || pBind->Alt==Combo)) + { + pBind->Function(pBind->Name,true); + pBind->State=1; + Ret=true; + } + } + } + return Ret; +} + +BOOL MQ2HandleKeyUp(class KeyCombo const &Combo) +{ + unsigned long N; + bool Ret=false; + for ( N = 0 ; N < nEQMappableCommands ; N++) + { + if (pKeypressHandler->CommandState[N] && (pKeypressHandler->NormalKey[N].Data[3]==Combo.Data[3] || + pKeypressHandler->AltKey[N].Data[3]==Combo.Data[3])) + { + ExecuteCmd(N,0,0); + pKeypressHandler->CommandState[N]=0; + Ret=true; + } + } + for ( N = 0 ; N < BindList.Size ; N++) + { + if (MQ2KeyBind *pBind=BindList[N]) + { + if (pBind->State==1 && (pBind->Normal.Data[3]==Combo.Data[3] || pBind->Alt.Data[3]==Combo.Data[3])) + { + pBind->Function(pBind->Name,false); + pBind->State=0; + Ret=true; + } + } + } + return Ret; +} + +class KeypressHandlerHook +{ +public: + void ClearCommandStateArray_Trampoline(void); + void ClearCommandStateArray_Hook(void) + { + unsigned long N; + for (N = 0 ; N < BindList.Size ; N++) + if (MQ2KeyBind *pBind=BindList[N]) + { + pBind->State=false; + } + ZeroMemory(&pKeypressHandler->CommandState[0],sizeof(pKeypressHandler->CommandState)); + } + + + bool HandleKeyDown_Trampoline(class KeyCombo const &); + bool HandleKeyUp_Trampoline(class KeyCombo const &); + + bool HandleKeyDown_Hook(class KeyCombo const &Combo) + { + if (!pWndMgr->HandleKeyboardMsg(Combo.Data[3],1)) + return true; + return (MQ2HandleKeyDown(Combo)!=0); + } + bool HandleKeyUp_Hook(class KeyCombo const &Combo) + { + bool Ret=false; + if (!pWndMgr->HandleKeyboardMsg(Combo.Data[3],0)) + Ret=true; + return (MQ2HandleKeyUp(Combo) || Ret); + } +}; + +DETOUR_TRAMPOLINE_EMPTY(void KeypressHandlerHook::ClearCommandStateArray_Trampoline(void)); +DETOUR_TRAMPOLINE_EMPTY(bool KeypressHandlerHook::HandleKeyDown_Trampoline(class KeyCombo const &)); +DETOUR_TRAMPOLINE_EMPTY(bool KeypressHandlerHook::HandleKeyUp_Trampoline(class KeyCombo const &)); + + +/* +class COptionsWndHook +{ +public: + void RefreshCurrentKeyboardAssignmentList_Trampoline(); + void RefreshCurrentKeyboardAssignmentList_Hook() + { + RefreshCurrentKeyboardAssignmentList_Trampoline(); + } + + void InitKeyboardAssignments_Trampoline(); + void InitKeyboardAssignments_Hook() + { + InitKeyboardAssignments_Trampoline(); + InjectMQ2Binds((COptionsWnd*)this); + } +}; +/**/ +VOID DoRangedBind(PCHAR Name,BOOL Down); + +void InitializeMQ2KeyBinds() +{ + /* + if (pOptionsWnd) + { + InjectMQ2Binds(pOptionsWnd); + } + /**/ + AddMQ2KeyBind("RANGED",DoRangedBind); + + EzDetour(KeypressHandler__ClearCommandStateArray,&KeypressHandlerHook::ClearCommandStateArray_Hook,&KeypressHandlerHook::ClearCommandStateArray_Trampoline); + EzDetour(KeypressHandler__HandleKeyDown,&KeypressHandlerHook::HandleKeyDown_Hook,&KeypressHandlerHook::HandleKeyDown_Trampoline); + EzDetour(KeypressHandler__HandleKeyUp,&KeypressHandlerHook::HandleKeyUp_Hook,&KeypressHandlerHook::HandleKeyUp_Trampoline); +} + +void ShutdownMQ2KeyBinds() +{ + BindList.Cleanup(); + RemoveDetour(KeypressHandler__ClearCommandStateArray); + RemoveDetour(KeypressHandler__HandleKeyDown); + RemoveDetour(KeypressHandler__HandleKeyUp); +} + +BOOL AddMQ2KeyBind(PCHAR name, fMQExecuteCmd Function) +{ + DebugSpew("AddMQ2KeyBind(%s)",name); + if (KeyBindByName(name)) + { + DebugSpew("AddMQ2KeyBind(%s) - Name already in use",name); + return false; + } + + MQ2KeyBind* pBind = new MQ2KeyBind; + pBind->State=false; + strncpy(pBind->Name,name,32); + pBind->Name[31]=0; + CHAR szBuffer[MAX_STRING]={0}; + CHAR szName[MAX_STRING]={0}; + + sprintf(szName,"%s_%s",pBind->Name,"Nrm"); + GetPrivateProfileString("Key Binds",szName,"clear",szBuffer,MAX_STRING,gszINIFilename); + ParseKeyCombo(szBuffer,pBind->Normal); + sprintf(szName,"%s_%s",pBind->Name,"Alt"); + GetPrivateProfileString("Key Binds",szName,"clear",szBuffer,MAX_STRING,gszINIFilename); + ParseKeyCombo(szBuffer,pBind->Alt); + + pBind->Function=Function; + + unsigned long N=BindList.GetUnused(); + BindList[N]=pBind; + SetKeyBindNameMap(name,N); + + return true; +} + +BOOL GetMQ2KeyBind(PCHAR name, BOOL Alt, KeyCombo &Combo) +{ + if (MQ2KeyBind *pBind=KeyBindByName(name)) + { + if (Alt) + Combo=pBind->Alt; + else + Combo=pBind->Normal; + return true; + } + return false; +} + +BOOL RemoveMQ2KeyBind(PCHAR name) +{ + DebugSpew("RemoveMQ2KeyBind(%s)",name); + string Lwr=name; + MakeLower(Lwr); + unsigned long N=BindNameMap[Lwr]; + if (!N) + return false; + --N; + if (MQ2KeyBind* pBind=BindList[N]) + { + BindNameMap[Lwr]=0; + BindList[N]=0; + delete pBind; + return true; + } + return false; +} + +BOOL PressMQ2KeyBind(PCHAR name, BOOL Hold) +{ + if (MQ2KeyBind *pBind=KeyBindByName(name)) + { + pBind->Function(pBind->Name,true); + if (!Hold) + pBind->Function(pBind->Name,false); + return true; + } + return false; +} + +BOOL SetMQ2KeyBind(PCHAR name, BOOL Alternate, KeyCombo &Combo) +{ + if (MQ2KeyBind *pBind=KeyBindByName(name)) + { + CHAR szName[MAX_STRING]={0}; + CHAR szBuffer[MAX_STRING]={0}; + if (!Alternate) + { + sprintf(szName,"%s_Nrm",pBind->Name); + pBind->Normal=Combo; + } + else + { + sprintf(szName,"%s_Alt",pBind->Name); + pBind->Alt=Combo; + } + WritePrivateProfileString("Key Binds",szName,DescribeKeyCombo(Combo,szBuffer),gszINIFilename); + return true; + } + return false; +} + +#ifndef ISXEQ +VOID MQ2KeyBindCommand(PSPAWNINFO pChar, PCHAR szLine) +{ + if (szLine[0]==0) + { + WriteChatColor("Usage: /bind >"); + return; + } + CHAR szBuffer[MAX_STRING]; + CHAR szArg1[MAX_STRING] = {0}; + GetArg(szArg1,szLine,1); + PCHAR szRest = GetNextArg(szLine); + PCHAR szArg=&szArg1[0]; + bool AltKey=false; + if (szArg[0]=='~') + { + AltKey=true; + szArg=&szArg1[1]; + } + unsigned long i; + if (!stricmp(szArg,"list")) + { + // list binds + CHAR szNormal[MAX_STRING]={0}; + CHAR szAlt[MAX_STRING]={0}; + WriteChatColor("MQ2 Binds"); + WriteChatColor("--------------"); + for (i = 0 ; i < BindList.Size ; i++) + { + if (MQ2KeyBind *pBind = BindList[i]) + { + sprintf(szArg1,"[\ay%s\ax] Nrm:\at%s\ax Alt:\at%s\ax",pBind->Name,DescribeKeyCombo(pBind->Normal,szNormal),DescribeKeyCombo(pBind->Alt,szAlt)); + WriteChatColor(szArg1); + } + } + WriteChatColor("--------------"); + WriteChatColor("End MQ2 Binds"); + return; + } + if (!stricmp(szArg,"eqlist")) + { + CHAR szNormal[MAX_STRING]={0}; + CHAR szAlt[MAX_STRING]={0}; + // list eq binds + WriteChatColor("EQ Binds"); + WriteChatColor("--------------"); + for (i = 0 ; i < nEQMappableCommands ; i++) + { + if((DWORD)szEQMappableCommands[i] == 0 || (DWORD)szEQMappableCommands[i] > (DWORD)__AC1_Data) + continue; + sprintf(szArg1,"[\ay%s\ax] Nrm:\at%s\ax Alt:\at%s\ax",szEQMappableCommands[i],DescribeKeyCombo(pKeypressHandler->NormalKey[i],szNormal),DescribeKeyCombo(pKeypressHandler->AltKey[i],szAlt)); + WriteChatColor(szArg1); + } + WriteChatColor("--------------"); + WriteChatColor("End EQ Binds"); + return; + } + + KeyCombo NewCombo; + if (!ParseKeyCombo(szRest,NewCombo)) + { + WriteChatColor("Invalid key combination"); + return; + } + + if (!stricmp(szArg,"clearcombo")) + { + KeyCombo ClearCombo; + // mq2 binds + for (i = 0; i < BindList.Size; i++) + { + MQ2KeyBind* pBind = BindList[i]; + if (pBind) + { + if (pBind->Alt == NewCombo && SetMQ2KeyBind(pBind->Name,true,ClearCombo)) + { + sprintf(szArg1,"Alternate %s cleared",pBind->Name); + WriteChatColor(szArg1); + } + if (pBind->Normal == NewCombo && SetMQ2KeyBind(pBind->Name,false,ClearCombo)) + { + sprintf(szArg1,"Normal %s cleared",pBind->Name); + WriteChatColor(szArg1); + } + } + } + + // eq binds + for (i = 0; i < nEQMappableCommands; i++) + { + if((DWORD)szEQMappableCommands[i] == 0 || (DWORD)szEQMappableCommands[i] > (DWORD)__AC1_Data) + continue; + if (pKeypressHandler->AltKey[i] == NewCombo && SetEQKeyBindByNumber(i,true,ClearCombo)) + { + sprintf(szArg1,"Alternate %s cleared",szEQMappableCommands[i] ); + WriteChatColor(szArg1); + } + if (pKeypressHandler->NormalKey[i] == NewCombo && SetEQKeyBindByNumber(i,false,ClearCombo)) + { + sprintf(szArg1,"Normal %s cleared", szEQMappableCommands[i]); + WriteChatColor(szArg1); + } + } + return; + } + + + + if (SetMQ2KeyBind(szArg,AltKey,NewCombo)) + { + MQ2KeyBind *pBind=KeyBindByName(szArg); + sprintf(szArg1,"%s %s now bound as %s",AltKey?"Alternate":"Normal",pBind->Name,DescribeKeyCombo(NewCombo,szBuffer)); + WriteChatColor(szArg1); + return; + } + + int N=FindMappableCommand(szArg); + if (N<0) + { + WriteChatColor("Unknown bind command name"); + return; + } + + if (SetEQKeyBindByNumber(N,AltKey,NewCombo)) + { + sprintf( szArg1,"%s %s now bound as %s", + (AltKey)?("Alternate"):("Normal"), + szEQMappableCommands[N], + DescribeKeyCombo((AltKey)?(pKeypressHandler->AltKey[N]):(pKeypressHandler->NormalKey[N]),szBuffer)); + } +} +#else +int CMD_MQ2Bind(int argc, char *argv[]) +{ + unsigned long i; + if (argc<2) + { + WriteChatf("Usage: %s >",argv[0]); + return 0; + } + if (!stricmp(argv[1],"list")) + { + // list binds + CHAR szNormal[MAX_STRING]={0}; + CHAR szAlt[MAX_STRING]={0}; + WriteChatColor("MQ2 Binds"); + WriteChatColor("--------------"); + foreach(MQ2KeyBind *pBind,i,BindList) + { + WriteChatf("[\ay%s\ax] Nrm:\at%s\ax Alt:\at%s\ax",pBind->Name,DescribeKeyCombo(pBind->Normal,szNormal),DescribeKeyCombo(pBind->Alt,szAlt)); + } + WriteChatColor("--------------"); + WriteChatColor("End MQ2 Binds"); + return 0; + } + if (!stricmp(argv[1],"eqlist")) + { + CHAR szNormal[MAX_STRING]={0}; + CHAR szAlt[MAX_STRING]={0}; + // list eq binds + WriteChatColor("EQ Binds"); + WriteChatColor("--------------"); + for (i = 0 ; i < nEQMappableCommands ; i++) + { + if((DWORD)szEQMappableCommands[i] == 0 || (DWORD)szEQMappableCommands[i] > (DWORD)__AC1_Data) + continue; + WriteChatf("[\ay%s\ax] Nrm:\at%s\ax Alt:\at%s\ax",szEQMappableCommands[i],DescribeKeyCombo(pKeypressHandler->NormalKey[i],szNormal),DescribeKeyCombo(pKeypressHandler->AltKey[i],szAlt)); + } + WriteChatColor("--------------"); + WriteChatColor("End EQ Binds"); + return 0; + } + + + KeyCombo NewCombo; + if (argc<3 || !ParseKeyCombo(argv[2],NewCombo)) + { + WriteChatColor("Invalid key combination"); + return 0; + } + + if (!stricmp(argv[1],"clearcombo")) + { + KeyCombo ClearCombo; + // mq2 binds + for (i = 0; i < BindList.Size; i++) + { + MQ2KeyBind* pBind = BindList[i]; + if (pBind) + { + if (pBind->Alt == NewCombo && SetMQ2KeyBind(pBind->Name,true,ClearCombo)) + { + WriteChatf("Alternate %s cleared",pBind->Name); + } + if (pBind->Normal == NewCombo && SetMQ2KeyBind(pBind->Name,false,ClearCombo)) + { + WriteChatf("Normal %s cleared",pBind->Name); + } + } + } + + // eq binds + for (i = 0; i < nEQMappableCommands; i++) + { + if((DWORD)szEQMappableCommands[i] == 0 || (DWORD)szEQMappableCommands[i] > (DWORD)__AC1_Data) + continue; + if (pKeypressHandler->AltKey[i] == NewCombo && SetEQKeyBindByNumber(i,true,ClearCombo)) + { + WriteChatf("Alternate %s cleared",szEQMappableCommands[i] ); + } + if (pKeypressHandler->NormalKey[i] == NewCombo && SetEQKeyBindByNumber(i,false,ClearCombo)) + { + WriteChatf("Normal %s cleared", szEQMappableCommands[i]); + } + } + return 0; + } + + + if (argv[1][0]=='~' && SetMQ2KeyBind(&argv[1][1],1,NewCombo)) + { + CHAR szBuffer[MAX_STRING]={0}; + MQ2KeyBind *pBind=KeyBindByName(&argv[1][1]); + WriteChatf("Alternate %s now bound as %s",pBind->Name,DescribeKeyCombo(NewCombo,szBuffer)); + } + + if (SetMQ2KeyBind(argv[1],0,NewCombo)) + { + CHAR szBuffer[MAX_STRING]={0}; + MQ2KeyBind *pBind=KeyBindByName(argv[1]); + WriteChatf("Normal %s now bound as %s",pBind->Name,DescribeKeyCombo(NewCombo,szBuffer)); + return 0; + } + + bool AltKey=argv[1][0]=='~'; + int N; + if (AltKey) + N=FindMappableCommand(&argv[1][1]); + else + N=FindMappableCommand(argv[1]); + if (N<0) + { + WriteChatColor("Unknown bind command name"); + return 0; + } + + if (SetEQKeyBindByNumber(N,AltKey,NewCombo)) + { + CHAR szBuffer[MAX_STRING]={0}; + WriteChatf("%s %s now bound as %s", + (AltKey)?("Alternate"):("Normal"), + szEQMappableCommands[N], + DescribeKeyCombo((AltKey)?(pKeypressHandler->AltKey[N]):(pKeypressHandler->NormalKey[N]),szBuffer)); + } + return 0; +} + +#endif + +VOID DoRangedBind(PCHAR Name,BOOL Down) +{ + if (Down && pTarget && gbRangedAttackReady) + { + pLocalPlayer->DoAttack(0x0B,0,pTarget); + gbRangedAttackReady=0; + } +} + +BOOL DumpBinds(PCHAR Filename) +{ + CHAR szFilename[MAX_STRING]={0}; + sprintf(szFilename,"%s\\Configs\\%s",gszINIPath,Filename); + if (!strchr(Filename,'.')) + strcat(szFilename,".cfg"); + FILE *file=fopen(szFilename,"wt"); + if (!file) + { + return false; + } + CHAR szBuffer[MAX_STRING]={0}; + unsigned long N; + for ( N = 0 ; N < nEQMappableCommands ; N++) + { + if((DWORD)szEQMappableCommands[N] == 0 || (DWORD)szEQMappableCommands[N] > (DWORD)__AC1_Data) + continue; + fprintf(file,"/bind %s %s\n",szEQMappableCommands[N],DescribeKeyCombo(pKeypressHandler->NormalKey[N],szBuffer)); + fprintf(file,"/bind ~%s %s\n",szEQMappableCommands[N],DescribeKeyCombo(pKeypressHandler->AltKey[N],szBuffer)); + } + for ( N = 0 ; N < BindList.Size ; N++) + { + if (MQ2KeyBind *pBind=BindList[N]) + { + fprintf(file,"/bind %s %s\n",pBind->Name,DescribeKeyCombo(pBind->Normal,szBuffer)); + fprintf(file,"/bind ~%s %s\n",pBind->Name,DescribeKeyCombo(pBind->Alt,szBuffer)); + } + } + fclose(file); + return true; +} + + diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2Labels.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2Labels.cpp new file mode 100644 index 0000000000..062a6f1a06 --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2Labels.cpp @@ -0,0 +1,138 @@ +// MQ2Labels.cpp : Defines the entry point for the DLL application. +// + +// MQ2 Custom Labels + + +#include "MQ2Main.h" +#include + +typedef string(*pEqTypesFunc)(); + +map eqTypesMap; + +// CSidlManager::CreateLabel 0x5F2470 + +// the tool tip is already copied out of the +// in class CControlTemplate. use this struct +// to mock up the class, so we don't have to +// worry about class instatiation and crap + +struct _CControl { + /*0x000*/ DWORD Fluff[0x24]; // if this changes update ISXEQLabels.cpp too + /*0x090*/ CXSTR * EQType; +}; + +// optimize off because the tramp looks blank to the compiler +// and it doesn't respect the fact the it will be a real routine +#pragma optimize ("g", off) + +class CSidlManagerHook { +public: + class CXWnd * CreateLabel_Trampoline(class CXWnd *, struct _CControl *); + class CXWnd * CreateLabel_Detour(class CXWnd *CWin, struct _CControl *CControl) + { + CLABELWND *p; + class CXWnd *tmp = CreateLabel_Trampoline(CWin, CControl); + p = (CLABELWND *)tmp; + if (CControl->EQType) { + *((DWORD *)&p->SidlPiece) = atoi(CControl->EQType->Text); + } else { + *((DWORD *)&p->SidlPiece) = 0; + } + + return tmp; + } +}; + +DETOUR_TRAMPOLINE_EMPTY(class CXWnd * CSidlManagerHook::CreateLabel_Trampoline(class CXWnd *, struct _CControl *)); + +#pragma optimize ("g", on) + +// CLabelHook::Draw_Detour + +class CLabelHook { +public: + VOID Draw_Trampoline(VOID); + VOID Draw_Detour(VOID) + { + PCLABELWND pThisLabel; + __asm {mov [pThisLabel], ecx}; + // (PCLABELWND)this; + Draw_Trampoline(); + CHAR Buffer[MAX_STRING] = {0}; + BOOL Found=FALSE; + DWORD index; + + std::string eqtypesString = ""; + + + if ((DWORD)pThisLabel->SidlPiece==9999) { + if (!pThisLabel->Wnd.XMLToolTip) { + strcpy(Buffer,"BadCustom"); + Found=TRUE; + } else { + //strcpy(Buffer,&pThisLabel->XMLToolTip->Text[0]); + STMLToPlainText(&pThisLabel->Wnd.XMLToolTip->Text[0],Buffer); + ParseMacroParameter(((PCHARINFO)pCharData)->pSpawn,Buffer); + if (!strcmp(Buffer,"NULL")) + Buffer[0]=0; + Found=TRUE; + } + } else if ((DWORD)pThisLabel->SidlPiece>=1000) { + for (auto eqtype : eqTypesMap) { + if (eqtype.first==(DWORD)pThisLabel->SidlPiece) { + + auto func = eqtype.second; + if (func) + { + eqtypesString = (*func)(); + Found = TRUE; + break; + } + } + } + } + if (Found) SetCXStr(&(pThisLabel->Wnd.WindowText),(PCHAR)eqtypesString.c_str()); + } +}; + +DETOUR_TRAMPOLINE_EMPTY(VOID CLabelHook::Draw_Trampoline(VOID)); + +BOOL StealNextGauge=FALSE; +DWORD NextGauge=0; + +std::string testDisplayFunction() +{ + return "Test"; +} + +// Called once, when the plugin is to initialize +PLUGIN_API VOID InitializeMQ2Labels(VOID) +{ + // DebugSpewAlways("Initializing MQ2Labels"); + eqTypesMap[1000] = testDisplayFunction; //and so forth + + // Add commands, macro parameters, hooks, etc. + //EasyClassDetour(CLabel__Draw,CLabelHook,Draw_Detour,VOID,(VOID),Draw_Trampoline); + EzDetour(CLabel__Draw,&CLabelHook::Draw_Detour,&CLabelHook::Draw_Trampoline); + EzDetour(CSidlManager__CreateLabel,&CSidlManagerHook::CreateLabel_Detour,&CSidlManagerHook::CreateLabel_Trampoline); + + + // currently in testing: + // EasyClassDetour(CGauge__Draw,CGaugeHook,Draw_Detour,VOID,(VOID),Draw_Trampoline); + // EasyDetour(__GetGaugeValueFromEQ,GetGaugeValueFromEQ_Hook,int,(int,class CXStr *,bool *),GetGaugeValueFromEQ_Trampoline); +} + +// Called once, when the plugin is to shutdown +PLUGIN_API VOID ShutdownLabelsPlugin(VOID) +{ + // DebugSpewAlways("Shutting down MQ2Labels"); + + // Remove commands, macro parameters, hooks, etc. + RemoveDetour(CSidlManager__CreateLabel); + RemoveDetour(CLabel__Draw); + //RemoveDetour(CGaugeWnd__Draw); + //RemoveDetour(__GetGaugeValueFromEQ); +} + diff --git a/client_files/native_autoloot/eq-core-dll/src/MQ2MacroCommands.cpp b/client_files/native_autoloot/eq-core-dll/src/MQ2MacroCommands.cpp new file mode 100644 index 0000000000..76ea2ca7be --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/MQ2MacroCommands.cpp @@ -0,0 +1,1253 @@ +/***************************************************************************** +MQ2Main.dll: MacroQuest2's extension DLL for EverQuest +Copyright (C) 2002-2003 Plazmic, 2003-2005 Lax + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as published by +the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +******************************************************************************/ + +#if !defined(CINTERFACE) +#error /DCINTERFACE +#endif +#ifndef ISXEQ + +#define DBG_SPEW + +#ifdef ISXEQ_LEGACY +#include "../ISXEQLegacy/ISXEQLegacy.h" +#else +#include "MQ2Main.h" +#endif + +/* VAR SYSTEM INDEPENDENT */ +// in-place cleanup of tabs, leading/trailing space +VOID CleanMacroLine(PCHAR szLine) +{ + if (!szLine || szLine[0]==0) + return; + PCHAR pChar=szLine; + while(pChar[0]) + { + if (pChar[0]=='\t' || pChar[0]==0x0a || pChar[0]==0x0d) + pChar[0]=' '; + ++pChar; + } + // find beginning and end + PCHAR pStart=szLine; + unsigned long Length=strlen(szLine); + PCHAR pEnd=&szLine[Length-1]; + + while(*pStart==' ') + ++pStart; + while(*pEnd==' ') + --pEnd; + if (!*pStart || !*pEnd) + { + szLine[0]=0; + return; + } + // keep only this part. + unsigned long NewLength=1+pEnd-pStart; + if (NewLength==Length) + return;//nothing to do + memmove(szLine,pStart,NewLength); + szLine[NewLength]=0; +} + +// *************************************************************************** +// Function: Include +// Description: Includes another macro file +// Usage: #include +// *************************************************************************** +DWORD Include(PCHAR szFile) +{ + CHAR szTemp[MAX_STRING] = {0}; + FILE *fMacro = fopen(szFile,"rt"); + DWORD LineNumber=0; + BOOL InBlockComment = FALSE; + PMACROBLOCK pAddedLine = NULL; + char *tmp; + if (!fMacro) { + FatalError("Couldn't open include file: %s",szFile); + return 0; + } + DebugSpewNoFile("Include - Including: %s",szFile); + while (!feof(fMacro)) { + + tmp = fgets(szTemp,MAX_STRING,fMacro); + + if (!tmp && feof(fMacro)) break; + + CleanMacroLine(szTemp); + + LineNumber++; + + if (!strncmp(szTemp,"|**",3)) { + InBlockComment=TRUE; + } + if (!InBlockComment) { + if (NULL == (pAddedLine=AddMacroLine(szTemp))) { + MacroError("Unable to add macro line."); + fclose(fMacro); + gszMacroName[0]=0; + gRunning = 0; + return 0; + } else if (1 != (DWORD)pAddedLine) { + pAddedLine->LineNumber = LineNumber; + strcpy(pAddedLine->SourceFile, GetFilenameFromFullPath(szFile)); + } + } else { + DebugSpewNoFile("Macro - BlockComment: %s",szTemp); + if (!strncmp(&szTemp[strlen(szTemp)-3],"**|",3)) { + InBlockComment=FALSE; + } + } + } + fclose(fMacro); + return 1; +} + +// *************************************************************************** +// Function: AddMacroLine +// Description: Add a line to the MacroBlock +// *************************************************************************** +PMACROBLOCK AddMacroLine(PCHAR szLine) +{ + PMACROBLOCK pBlock = NULL; + // replace all tabs with spaces + if ((szLine[0]==0) || (szLine[0]=='|')) return (PMACROBLOCK)1; + + PDEFINE pDef = pDefines; + if (szLine[0]!='#') while (pDef) { + while (strstr(szLine,pDef->szName)) { + CHAR szNew[MAX_STRING] = {0}; + strncpy(szNew,szLine,strstr(szLine,pDef->szName)-szLine); + strcat(szNew,pDef->szReplace); + strcat(szNew,strstr(szLine,pDef->szName)+strlen(pDef->szName)); + strcpy(szLine,szNew); + } + pDef = pDef->pNext; + } + if (szLine[0]=='#') { + if (!strnicmp(szLine,"#include ",9)) { + CHAR Filename[MAX_STRING] = {0}; + szLine+=8; + while (szLine[0]==' ') szLine++; + + if (!strstr(szLine,".")) strcat(szLine,".mac"); + sprintf(Filename,"%s\\%s",gszMacroPath, szLine); + + //DebugSpewNoFile("AddMacroLine - Including file: %s",Filename); + return (PMACROBLOCK)Include(Filename); + } else if (!strnicmp(szLine,"#turbo",6)) { + gTurbo = TRUE; + CHAR szArg[MAX_STRING] = {0}; + GetArg(szArg,szLine,2); + gMaxTurbo = atoi(szArg); + if (gMaxTurbo==0) + gMaxTurbo=20; + else if (gMaxTurbo>40) + { + MacroError("#turbo %d is too high, setting at 40 (maximum)",gMaxTurbo); + gMaxTurbo=40; + } + } else if (!strnicmp(szLine,"#define ",8)) { + CHAR szArg1[MAX_STRING] = {0}; + CHAR szArg2[MAX_STRING] = {0}; + PDEFINE pDef = (PDEFINE)malloc(sizeof(DEFINE)); + GetArg(szArg1,szLine,2); + GetArg(szArg2,szLine,3); + if ((szArg1[0]!=0) && (szArg2[0]!=0)) { + strcpy(pDef->szName,szArg1); + strcpy(pDef->szReplace,szArg2); + pDef->pNext = pDefines; + pDefines = pDef; + } else { + MacroError("Bad #define: %s",szLine); + } + } else if (!strnicmp(szLine,"#event ",7)) { + CHAR szArg1[MAX_STRING] = {0}; + CHAR szArg2[MAX_STRING] = {0}; + PEVENTLIST pEvent = (PEVENTLIST)malloc(sizeof(EVENTLIST)); + GetArg(szArg1,szLine,2); + GetArg(szArg2,szLine,3); + if ((szArg1[0]!=0) && (szArg2[0]!=0)) { + sprintf(pEvent->szName,"Sub Event_%s",szArg1); + strcpy(pEvent->szMatch,szArg2); +#ifdef USEBLECHEVENTS + pEvent->BlechID=pEventBlech->AddEvent(pEvent->szMatch,EventBlechCallback,pEvent); +#endif + pEvent->pEventFunc = NULL; + pEvent->pNext = pEventList; + pEventList = pEvent; + } else { + MacroError("Bad #event: %s",szLine); + } + } else if (!strnicmp(szLine,"#chat ",6)) { + szLine+=5; + while (szLine[0]==' ') szLine++; + if (!stricmp(szLine,"say")) gEventChat = gEventChat | CHAT_SAY; + if (!stricmp(szLine,"tell")) gEventChat = gEventChat | CHAT_TELL; + if (!stricmp(szLine,"ooc")) gEventChat = gEventChat | CHAT_OOC; + if (!stricmp(szLine,"shout")) gEventChat = gEventChat | CHAT_SHOUT; + if (!stricmp(szLine,"auc")) gEventChat = gEventChat | CHAT_AUC; + if (!stricmp(szLine,"guild")) gEventChat = gEventChat | CHAT_GUILD; + if (!stricmp(szLine,"group")) gEventChat = gEventChat | CHAT_GROUP; + if (!stricmp(szLine,"chat")) gEventChat = gEventChat | CHAT_CHAT; + } else if (szLine[1]=='!') { + // Like: #!/usr/local/bin/LegacyMQ2 + // ignore. + } else { + MacroError("Unknown # command: %s",szLine); + return FALSE; + } + } + + pBlock = (PMACROBLOCK)malloc(sizeof(MACROBLOCK)); + if (!pBlock) return NULL; + //DebugSpewNoFile("AddMacroLine - Adding: %s",szLine); + strcpy(pBlock->Line,szLine); + pBlock->LineNumber = -1; + pBlock->SourceFile[0]=0; + pBlock->pNext=NULL; + pBlock->pPrev=NULL; + + if ((!stricmp(szLine,"Sub Event_Chat")) || (!strnicmp(szLine,"Sub Event_Chat(",15))) { + gEventFunc[EVENT_CHAT] = pBlock; + } else if ((!stricmp(szLine,"Sub Event_Timer")) || (!strnicmp(szLine,"Sub Event_Timer(",16))) { + gEventFunc[EVENT_TIMER] = pBlock; + } else { + PEVENTLIST pEvent = pEventList; + while (pEvent) { + if (!stricmp(szLine,pEvent->szName)) { + pEvent->pEventFunc = pBlock; + } else { + CHAR szNameP[MAX_STRING] = {0}; + sprintf(szNameP,"%s(",pEvent->szName); + if (!strnicmp(szLine,szNameP,strlen(szNameP))) { + pEvent->pEventFunc = pBlock; + } + } + pEvent = pEvent->pNext; + } + } + if (!gMacroBlock) { + gMacroBlock=pBlock; + } else { + PMACROBLOCK pLoop = gMacroBlock; + while (pLoop->pNext) pLoop = pLoop->pNext; + pLoop->pNext = pBlock; + pBlock->pPrev = pLoop; + } + return pBlock; +} + + +// *************************************************************************** +// Function: Macro +// Description: Our '/macro' command +// Usage: /macro +// *************************************************************************** +VOID Macro(PSPAWNINFO pChar, PCHAR szLine) +{ + bRunNextCommand = TRUE; + CHAR szTemp[MAX_STRING] = {0}; + CHAR Filename[MAX_STRING] = {0}; + PCHAR Params = NULL; + PCHAR szNext = NULL; + BOOL InBlockComment = FALSE; + if (szLine[0] == 0) { + SyntaxError("Usage: /macro [param [param...]]"); + return; + } + if (gMacroBlock) + { + gReturn = false; + EndMacro(pChar,"");//"keep keys vars arrays timers"); + gReturn = true; + } + gMaxTurbo=20; + gTurbo=true; + GetArg(szTemp,szLine,1); + Params = GetNextArg(szLine); + + strcpy(gszMacroName,szTemp); +#ifdef ISXEQ_LEGACY + strcpy(Filename,szTemp); + FILE *fMacro = fopen(szTemp,"rt"); +#else + if (!strstr(szTemp,".")) strcat(szTemp,".mac"); + sprintf(Filename,"%s\\%s",gszMacroPath, szTemp); + + FILE *fMacro = fopen(Filename,"rt"); +#endif + if (!fMacro) { + FatalError("Couldn't open macro file: %s",Filename); + gszMacroName[0]=0; + gRunning = 0; + return; + } + gRunning = GetTickCount(); + gEventChat = 0; + strcpy(gszMacroName,szTemp); + DebugSpew("Macro - Loading macro: %s",Filename); + DWORD LineNumber = 0; + PMACROBLOCK pAddedLine = NULL; + while (!feof(fMacro)) { + fgets(szTemp,MAX_STRING,fMacro); + CleanMacroLine(szTemp); + LineNumber++; + if (!strncmp(szTemp,"|**",3)) { + InBlockComment=TRUE; + } + if (!InBlockComment) { + if (NULL == (pAddedLine=AddMacroLine(szTemp))) { + MacroError("Unable to add macro line."); + fclose(fMacro); + gszMacroName[0]=0; + gRunning = 0; + return; + } else if (1 != (DWORD)pAddedLine) { + pAddedLine->LineNumber = LineNumber; + strcpy(pAddedLine->SourceFile, GetFilenameFromFullPath(Filename)); + } + } else { + DebugSpew("Macro - BlockComment: %s",szTemp); + if (!strncmp(&szTemp[strlen(szTemp)-3],"**|",3)) { + InBlockComment=FALSE; + } + } + } + fclose(fMacro); + PDEFINE pDef; + while (pDefines) { + pDef = pDefines->pNext; + free(pDefines); + pDefines = pDef; + } + strcpy(szTemp, "Main"); + if (Params[0] !=0) { + strcat(szTemp, " "); + strcat(szTemp, Params); + } + DebugSpew("Macro - Starting macro with '/call %s'",szTemp); + Call(pChar, szTemp); + if ((gMacroBlock) && (gMacroBlock->pNext)) gMacroBlock = gMacroBlock->pNext; + if (gMacroBlock) gMacroBlock->MacroCmd = 1; + if ((!gMacroBlock) || (!gMacroStack)) { + gszMacroName[0]=0; + gRunning = 0; + } +#ifdef ISXEQ_LEGACY + else + { + char ShortName[128]; + ShortName[0]=0; + _splitpath(Filename,0,0,ShortName,0); + IS_ScriptEngineScriptBegins(pExtension,pISInterface,hScriptEngineService,&g_LegacyEngine,ShortName); + } +#endif +} + +// *************************************************************************** +// Function: Cleanup +// Description: Our '/cleanup' command +// Sends i, esc, esc, esc, esc, i +// Usage: /cleanup +// *************************************************************************** +VOID Cleanup(PSPAWNINFO pChar, PCHAR szLine) +{ + DebugSpewNoFile("Cleanup - Cleaning up screen"); + DWORD i; + KeyCombo Escape; + ParseKeyCombo("Esc",Escape); + if(ppContainerMgr && pContainerMgr) { + PEQ_CONTAINERWND_MANAGER ContainerMgr = (PEQ_CONTAINERWND_MANAGER)pContainerMgr; + DWORD concount=2; //Close inv + clear target + if (ContainerMgr->pWorldContents && ContainerMgr->pWorldContents->Open==1) concount++; + for (i=0;i<25;i++) { + if (ContainerMgr->pPCContainers[i] && ContainerMgr->pPCContainers[i]->Wnd.dShow==1) concount++; + } + for (i=0;idShow==0) + DoMappable(pChar,"inventory"); + } + } else { + DoMappable(pChar,"inventory"); + for (i=0;i<10;i++) + { + MQ2HandleKeyDown(Escape); + MQ2HandleKeyUp(Escape); + } + DoMappable(pChar,"inventory"); + } +} + +// *************************************************************************** +// Function: Delay +// Description: Our '/delay' command +// Usage: /delay

+ +You do not need perfect bug reports. Plain English is fine. Tell us what worked, what broke, what felt fun, and what felt confusing. +``` diff --git a/features/live-items/google-forms/live-items-public-test-form.gs b/features/live-items/google-forms/live-items-public-test-form.gs new file mode 100644 index 0000000000..b415034dfb --- /dev/null +++ b/features/live-items/google-forms/live-items-public-test-form.gs @@ -0,0 +1,422 @@ +/** + * Live Items Public Test Feedback form generator. + * + * How to use: + * 1. Go to https://script.google.com/ + * 2. Create a new project. + * 3. Paste this whole file into Code.gs. + * 4. Run createLiveItemsPublicTestFeedbackForm(). + * 5. Approve permissions. + * 6. Open the logged URLs for the edit form, public form, and response sheet. + */ + +const CREATE_RESPONSE_SHEET = true; + +const LIVE_ITEMS_FORM_SPEC = { + title: 'Live Items Public Test Feedback', + description: + 'Thanks for helping test Live Items. Please answer what you can. You do not need perfect notes. ' + + 'If something felt weird, confusing, too strong, too weak, or broken, tell us in plain English. ' + + 'Item links, screenshots, and mob names help if you have them.', + confirmationMessage: 'Thank you for testing Live Items. Your feedback helps shape the next pass.', + collectEmail: false, + allowResponseEdits: true, + showProgressBar: true, + shuffleQuestions: false, + responseSheetTitle: 'Live Items Public Test Feedback Responses', + sections: [ + { + title: 'Tester Info', + items: [ + { type: 'text', title: 'Tester name or Discord name', required: true }, + { type: 'text', title: 'Character name', required: true }, + { + type: 'text', + title: 'Class and level', + helpText: 'Example: Warrior level 12', + required: true, + }, + { type: 'date', title: 'Date tested' }, + ], + }, + { + title: 'Login And Patching', + items: [ + { + type: 'multipleChoice', + title: 'Were you able to patch your RoF2 client and log in?', + required: true, + choices: [ + 'Yes, patching and login worked', + 'I patched, but login had problems', + 'I could not patch', + 'I could not reach character select', + ], + }, + { + type: 'multipleChoice', + title: 'Were you able to enter tutorialb?', + required: true, + choices: ['Yes', 'No'], + }, + { + type: 'multipleChoice', + title: 'Did you see any missing file, XML, UI, or startup errors?', + required: true, + choices: ['No errors', 'Yes, I saw errors', 'Not sure'], + }, + { + type: 'paragraph', + title: 'If patching, login, or startup had problems, describe what happened.', + }, + ], + }, + { + title: 'Test NPCs', + items: [ + { + type: 'checkbox', + title: 'Which NPCs responded when hailed?', + required: true, + choices: ['Vedra Forgecall', 'Orin Augspinner', 'Mavren Instancewright', 'Talia Heirloomkeeper', 'Nalyx Augmentweaver', 'None of them'], + }, + { + type: 'multipleChoice', + title: 'Did the clickable dialogue text work?', + required: true, + choices: ['Yes', 'No', 'Some worked, some did not', 'I did not try clickable dialogue'], + }, + { type: 'paragraph', title: 'Was any NPC text confusing?' }, + ], + }, + { + title: 'Tester Helper Commands', + helpText: + 'These commands are optional, but they make bug reports much easier to trace. Hold an item on your cursor before using #helditemid.', + items: [ + { + type: 'checkbox', + title: 'Which helper commands did you try?', + choices: ['#helditemid / #itemid / #cursoritemid', '#heirloomdebug / #evolvingdebug', 'I did not try helper commands'], + }, + { + type: 'paragraph', + title: 'Paste any useful helper command output here.', + helpText: 'Item IDs, heirloom debug output, or anything that seemed wrong.', + }, + ], + }, + { + title: 'Random Loot From Tutorialb Mobs', + helpText: + 'Kill normal mobs in tutorialb and loot them like normal. The random Live Items loot should appear directly on corpses. It should not be a box or cache you have to open.', + items: [ + { + type: 'multipleChoice', + title: 'About how many normal mobs did you kill?', + required: true, + choices: ['1-4', '5-9', '10-19', '20+'], + }, + { + type: 'multipleChoice', + title: 'Did normal mobs have random Live Items loot directly on their corpses?', + required: true, + choices: ['Yes, every mob I checked had one', 'Most did, but not all', 'Only some did', 'None did', 'Not sure'], + }, + { + type: 'multipleChoice', + title: 'Did the loot look like normal corpse loot?', + required: true, + choices: ['Yes', 'No, it appeared as a box/cache', 'No, something else seemed wrong', 'Not sure'], + }, + { + type: 'multipleChoice', + title: 'Were you able to loot the random items normally?', + required: true, + choices: ['Yes', 'No', 'Some worked, some did not'], + }, + { + type: 'multipleChoice', + title: 'Did different mobs give different names or stat rolls?', + required: true, + choices: ['Yes, the items felt varied', 'A little, but they felt too similar', 'No, they looked mostly the same', 'Not sure'], + }, + { + type: 'multipleChoice', + title: 'Did random loot keep its stats after zoning, camping, or relogging?', + choices: ['Yes', 'No', 'I did not test this'], + }, + { + type: 'text', + title: 'What was the best random item you found?', + helpText: 'Item name/link if you have it.', + }, + { type: 'text', title: 'What was the strangest, worst, or most broken random item you found?' }, + { type: 'paragraph', title: 'Any notes about random loot?' }, + ], + }, + { + title: 'Item Forge Window', + helpText: 'Talk to Vedra Forgecall and choose open forge. Try making at least one item.', + items: [ + { + type: 'multipleChoice', + title: 'Did the Item Forge window open?', + required: true, + choices: ['Yes', 'No', 'It opened, but looked broken'], + }, + { + type: 'checkbox', + title: 'Which item types did you try creating?', + choices: ['Weapon', 'Armor', 'Jewelry', 'Charm', 'Shield', 'Augment'], + }, + { + type: 'multipleChoice', + title: 'Did the item you created match the name and stats you entered?', + choices: ['Yes', 'No', 'Some stats worked, some did not', 'I could not create an item'], + }, + { + type: 'multipleChoice', + title: 'Did the step buttons for stat changes work as expected?', + choices: ['Yes', 'No', 'Some worked, some did not', 'I did not try changing the step size'], + }, + { type: 'paragraph', title: 'Did any stat field not work or look wrong?' }, + { type: 'paragraph', title: 'Item Forge notes' }, + ], + }, + { + title: 'Augment NPC', + helpText: 'Talk to Orin Augspinner. Say start, add the upgrades you want, optionally name the augment, then say confirm. Use test shards if you need Blood Shards for testing.', + items: [ + { + type: 'multipleChoice', + title: 'Could you build a shardwork augment with the upgrades you wanted?', + required: true, + choices: ['Yes', 'No', 'I did not test augments'], + }, + { + type: 'multipleChoice', + title: 'Did Orin spend Blood Shards and give you a custom augment when you confirmed?', + required: true, + choices: ['Yes', 'No', 'I did not test augments'], + }, + { + type: 'multipleChoice', + title: 'Did the augment have the stats you purchased?', + choices: ['Yes', 'No', 'Not sure'], + }, + { + type: 'multipleChoice', + title: 'Could the augment be inserted into normal equipment slots?', + choices: ['Yes', 'No', 'I did not try inserting it', 'Not sure'], + }, + { + type: 'multipleChoice', + title: 'After inserting the augment, did the target item still look usable and keep its normal slots?', + choices: ['Yes', 'No', 'I did not try inserting it', 'Not sure'], + }, + { type: 'paragraph', title: 'If you tried inserting the augment into an item, what happened?' }, + { type: 'paragraph', title: 'Augment notes' }, + ], + }, + { + title: 'Instance Upgrade NPC', + helpText: + 'Talk to Mavren Instancewright. Hand him exactly one Live Items item with no coins and no extra items. He should return that same item as a +1 version with its supported positive stats increased by 10.', + items: [ + { + type: 'multipleChoice', + title: 'Did Mavren return your item as a +1 upgraded version?', + choices: ['Yes', 'No', 'I did not test this'], + }, + { + type: 'multipleChoice', + title: 'Did Mavren return only the upgraded item, without also giving back the original?', + choices: ['Yes, only the upgraded item came back', 'No, I also got the original back', 'No, something vanished or got stuck', 'I did not test this'], + }, + { + type: 'multipleChoice', + title: 'Did the upgraded item keep the correct name and stats after zoning, camping, or relogging?', + choices: ['Yes', 'No', 'I did not test persistence'], + }, + { type: 'paragraph', title: 'Instance upgrade notes' }, + ], + }, + { + title: 'Evolving Heirloom', + helpText: + 'Talk to Talia Heirloomkeeper and say heirloom. Keep the item equipped or in your inventory, then gain a level if you can. The heirloom should grow stronger when you level.', + items: [ + { + type: 'multipleChoice', + title: 'Did Talia give you a class-matched heirloom weapon?', + choices: ['Yes', 'No', 'I did not test this'], + }, + { + type: 'multipleChoice', + title: 'Did the heirloom grow stronger when you gained a level?', + choices: ['Yes', 'No', 'I could not gain a level during testing', 'I did not test this'], + }, + { + type: 'multipleChoice', + title: 'Did #heirloomdebug or #evolvingdebug find the heirloom while it was in inventory or equipped?', + choices: ['Yes', 'No', 'I did not try the debug command', 'Not sure'], + }, + { type: 'paragraph', title: 'Evolving heirloom notes' }, + ], + }, + { + title: 'Augment Fusion', + helpText: + 'Talk to Nalyx Augmentweaver. Say catalyst if you need an Augment Catalyst, then hand in exactly one Augment Catalyst plus one to three augment items, with no coins. Nalyx should return one fused augment with the supported stats combined.', + items: [ + { + type: 'multipleChoice', + title: 'Did Nalyx give you an Augment Catalyst when you asked for one?', + choices: ['Yes', 'No', 'I already had one', 'I did not test this'], + }, + { + type: 'multipleChoice', + title: 'Did Nalyx return one fused augment?', + choices: ['Yes', 'No', 'I did not test this'], + }, + { + type: 'multipleChoice', + title: 'Did the fused augment show the combined stats you expected?', + choices: ['Yes', 'No', 'Not sure', 'I did not test this'], + }, + { type: 'paragraph', title: 'Augment fusion notes' }, + ], + }, + { + title: 'Overall Feel', + helpText: 'These questions are just as useful as bug reports.', + items: [ + { type: 'paragraph', title: 'What felt fun?' }, + { type: 'paragraph', title: 'What felt annoying?' }, + { type: 'paragraph', title: 'What was confusing?' }, + { type: 'paragraph', title: 'Did any item seem way too strong or way too weak?' }, + { + type: 'multipleChoice', + title: 'Would you want this kind of loot while leveling normally?', + choices: ['Yes', 'Maybe, with changes', 'No', 'Not sure'], + }, + { + type: 'scale', + title: 'Overall, how excited are you about Live Items?', + lower: 1, + upper: 5, + lowLabel: 'Not excited', + highLabel: 'Very excited', + }, + ], + }, + { + title: 'Bugs Or Problems', + helpText: + 'If something broke, describe it in plain English. Example: I killed a kobold near the cave entrance. The corpse had no random item. I was a level 5 warrior.', + items: [ + { + type: 'multipleChoice', + title: 'Did you hit any bugs or broken behavior?', + required: true, + choices: ['No bugs noticed', 'Yes, one bug', 'Yes, multiple bugs', 'Not sure'], + }, + { + type: 'paragraph', + title: 'Bug report', + helpText: 'What were you doing? What did you expect? What actually happened?', + }, + { type: 'paragraph', title: 'Extra screenshots, item links, or notes' }, + ], + }, + ], +}; + +function createLiveItemsPublicTestFeedbackForm() { + const result = createGoogleFormFromSpec(LIVE_ITEMS_FORM_SPEC); + + Logger.log('Edit form: ' + result.editUrl); + Logger.log('Public form: ' + result.publishedUrl); + if (result.responseSheetUrl) { + Logger.log('Responses sheet: ' + result.responseSheetUrl); + } +} + +function createGoogleFormFromSpec(spec) { + const form = FormApp.create(spec.title); + form.setDescription(spec.description || ''); + form.setConfirmationMessage(spec.confirmationMessage || 'Thank you.'); + form.setCollectEmail(Boolean(spec.collectEmail)); + form.setAllowResponseEdits(Boolean(spec.allowResponseEdits)); + form.setProgressBar(Boolean(spec.showProgressBar)); + form.setShuffleQuestions(Boolean(spec.shuffleQuestions)); + + (spec.sections || []).forEach(function(section, index) { + if (index === 0) { + form.addSectionHeaderItem().setTitle(section.title).setHelpText(section.helpText || ''); + } else { + form.addPageBreakItem().setTitle(section.title).setHelpText(section.helpText || ''); + } + + (section.items || []).forEach(function(itemSpec) { + addItemToForm(form, itemSpec); + }); + }); + + let responseSheetUrl = ''; + if (CREATE_RESPONSE_SHEET) { + const sheet = SpreadsheetApp.create(spec.responseSheetTitle || spec.title + ' Responses'); + form.setDestination(FormApp.DestinationType.SPREADSHEET, sheet.getId()); + responseSheetUrl = sheet.getUrl(); + } + + return { + editUrl: form.getEditUrl(), + publishedUrl: form.getPublishedUrl(), + responseSheetUrl: responseSheetUrl, + }; +} + +function addItemToForm(form, itemSpec) { + let item; + + switch (itemSpec.type) { + case 'text': + item = form.addTextItem(); + break; + case 'paragraph': + item = form.addParagraphTextItem(); + break; + case 'date': + item = form.addDateItem(); + break; + case 'multipleChoice': + item = form.addMultipleChoiceItem(); + item.setChoiceValues(itemSpec.choices || []); + break; + case 'checkbox': + item = form.addCheckboxItem(); + item.setChoiceValues(itemSpec.choices || []); + break; + case 'scale': + item = form.addScaleItem(); + item.setBounds(itemSpec.lower || 1, itemSpec.upper || 5); + item.setLabels(itemSpec.lowLabel || '', itemSpec.highLabel || ''); + break; + default: + throw new Error('Unsupported form item type: ' + itemSpec.type); + } + + item.setTitle(itemSpec.title); + + if (itemSpec.helpText) { + item.setHelpText(itemSpec.helpText); + } + + if (itemSpec.required) { + item.setRequired(true); + } + + return item; +} diff --git a/features/live-items/patcher.yml b/features/live-items/patcher.yml new file mode 100644 index 0000000000..b8fc5b14db --- /dev/null +++ b/features/live-items/patcher.yml @@ -0,0 +1,14 @@ +version: 1 +id: live-items +label: Live Items +client: rof +files: + - source: client_files/native_autoloot/eq-core-dll/bin/dinput8.dll + destination: dinput8.dll + - source: client_files/native_autoloot/ui/EQUI_NativeItemForgeWnd.xml + destination: uifiles/default/EQUI_NativeItemForgeWnd.xml +generated: + eqhost: true + equiXml: true + equiIncludes: + - EQUI_NativeItemForgeWnd.xml diff --git a/features/live-items/quests/global/900900.lua b/features/live-items/quests/global/900900.lua new file mode 100644 index 0000000000..33ccc4b558 --- /dev/null +++ b/features/live-items/quests/global/900900.lua @@ -0,0 +1,273 @@ +local REQUIRED_COUNT = 5 +local COFFER_ITEM_ID = 900090 +local CLASS_LINKS_PER_LINE = 4 + +local fragments = { + { item_id = 900010, key = "scarred", name = "Scarred Dranik War Fragment" }, + { item_id = 900011, key = "causeway", name = "Noble Causeway Battle Fragment" }, + { item_id = 900012, key = "bloodfields", name = "Bloodfields War Fragment" }, + { item_id = 900013, key = "ruined", name = "Ruined Dranik Relic Fragment" }, + { item_id = 900014, key = "harbinger", name = "Harbinger Spire Relic Fragment" }, + { item_id = 900015, key = "wall", name = "Wall of Slaughter War Fragment" }, + { item_id = 900016, key = "riftseeker", name = "Riftseeker Sanctum Relic Fragment" }, +} + +local classes = { + { key = "warrior", name = "Warrior", class_id = 1, base_item_id = 900101 }, + { key = "cleric", name = "Cleric", class_id = 2, base_item_id = 900102 }, + { key = "paladin", name = "Paladin", class_id = 3, base_item_id = 900103 }, + { key = "ranger", name = "Ranger", class_id = 4, base_item_id = 900104 }, + { key = "shadowknight", name = "Shadow Knight", class_id = 5, base_item_id = 900105 }, + { key = "druid", name = "Druid", class_id = 6, base_item_id = 900106 }, + { key = "monk", name = "Monk", class_id = 7, base_item_id = 900107 }, + { key = "bard", name = "Bard", class_id = 8, base_item_id = 900108 }, + { key = "rogue", name = "Rogue", class_id = 9, base_item_id = 900109 }, + { key = "shaman", name = "Shaman", class_id = 10, base_item_id = 900110 }, + { key = "necromancer", name = "Necromancer", class_id = 11, base_item_id = 900111 }, + { key = "wizard", name = "Wizard", class_id = 12, base_item_id = 900112 }, + { key = "magician", name = "Magician", class_id = 13, base_item_id = 900113 }, + { key = "enchanter", name = "Enchanter", class_id = 14, base_item_id = 900114 }, + { key = "beastlord", name = "Beastlord", class_id = 15, base_item_id = 900115 }, + { key = "berserker", name = "Berserker", class_id = 16, base_item_id = 900116 }, +} + +local fragment_by_id = {} +for _, fragment in ipairs(fragments) do + fragment_by_id[fragment.item_id] = fragment +end + +local class_by_key = {} +for _, class in ipairs(classes) do + class_by_key[class.key] = class +end + +local function normalize(value) + return (value or ""):lower():gsub("[%s_%-]", "") +end + +local function bucket_name(key) + return "live_items_epic." .. key +end + +local function get_bucket(client, key) + return client:GetBucket(bucket_name(key)) +end + +local function set_bucket(client, key, value) + client:SetBucket(bucket_name(key), tostring(value)) +end + +local function selected_class(client) + return class_by_key[normalize(get_bucket(client, "class"))] +end + +local function reset_progress(client) + for _, fragment in ipairs(fragments) do + set_bucket(client, "fragment." .. fragment.key, 0) + end +end + +local function progress_for(client, fragment) + return tonumber(get_bucket(client, "fragment." .. fragment.key)) or 0 +end + +local function set_progress(client, fragment, count) + set_bucket(client, "fragment." .. fragment.key, math.max(0, math.min(REQUIRED_COUNT, count))) +end + +local function is_complete(client) + for _, fragment in ipairs(fragments) do + if progress_for(client, fragment) < REQUIRED_COUNT then + return false + end + end + + return true +end + +local function class_link_rows() + local rows = {} + local links = {} + + for index, class in ipairs(classes) do + table.insert(links, eq.say_link("choose " .. class.key, false, class.name)) + if #links == CLASS_LINKS_PER_LINE or index == #classes then + table.insert(rows, table.concat(links, ", ")) + links = {} + end + end + + return rows +end + +local function say_class_links(npc) + npc:Say("Choose your class epic:") + + for _, row in ipairs(class_link_rows()) do + npc:Say(row) + end +end + +local function show_progress(client) + local class = selected_class(client) + if class then + client:Message(15, "Requested epic: " .. class.name) + else + client:Message(15, "Requested epic: none selected") + end + + for _, fragment in ipairs(fragments) do + client:Message(15, string.format("%s: %d/%d", fragment.name, progress_for(client, fragment), REQUIRED_COUNT)) + end +end + +local function choose_class(e, key) + local class = class_by_key[normalize(key)] + if not class then + e.self:Say("I can shape epics for these disciplines.") + say_class_links(e.self) + return + end + + set_bucket(e.other, "class", class.key) + set_bucket(e.other, "class_name", class.name) + set_bucket(e.other, "base_item_id", class.base_item_id) + reset_progress(e.other) + e.self:Say(string.format("Then we forge for a %s. Bring me five of each war fragment and relic fragment.", class.name)) + show_progress(e.other) +end + +local function fragment_quantity(inst) + local charges = inst:GetCharges() + if charges and charges > 0 then + return charges + end + + return 1 +end + +local function trade_fragment_quantity(trade, fragment) + local quantity = 0 + for slot = 1, 4 do + local inst = trade["item" .. slot] + if inst and inst.valid and inst:GetID() == fragment.item_id then + quantity = quantity + fragment_quantity(inst) + end + end + + return quantity +end + +local function consume_fragment(e, fragment, quantity) + return e.self:CheckHandin(e.other, {}, { [tostring(fragment.item_id)] = quantity }, {}) +end + +local function reward_coffer(e, class) + local coffer = ItemInst(COFFER_ITEM_ID, 1) + coffer:SetCustomData("live_items_epic_class", class.key) + coffer:SetCustomData("live_items_epic_class_name", class.name) + coffer:SetCustomData("live_items_epic_base_item_id", tostring(class.base_item_id)) + coffer:SetDynamicItemData("name", class.name .. " Sealed Epic Coffer") + coffer:SetDynamicItemData("lore", "Open this coffer to roll a " .. class.name .. " Item Forge epic.") + coffer:RebuildDynamicItemData() + + e.other:PushItemOnCursor(coffer) + e.self:Say("The fragments answer the forge. Open the coffer when you are ready to roll your epic.") + + set_bucket(e.other, "class", "") + set_bucket(e.other, "class_name", "") + set_bucket(e.other, "base_item_id", 0) + reset_progress(e.other) +end + +local function reward_if_complete(e) + local class = selected_class(e.other) + if class and is_complete(e.other) then + reward_coffer(e, class) + return true + end + + return false +end + +function event_say(e) + local message = normalize(e.message) + + if message:find("^hail") then + if reward_if_complete(e) then + return + end + + e.self:Say("The Item Forge is awake. Choose the class epic you want, then bring me five of each fragment.") + say_class_links(e.self) + show_progress(e.other) + return + end + + local chosen_key = message:match("^choose(.+)$") + if chosen_key then + choose_class(e, chosen_key) + return + end + + if message == "progress" or message == "status" then + show_progress(e.other) + return + end + + if message == "reset" then + set_bucket(e.other, "class", "") + set_bucket(e.other, "class_name", "") + set_bucket(e.other, "base_item_id", 0) + reset_progress(e.other) + e.self:Say("Your Item Forge epic request has been reset.") + return + end +end + +function event_trade(e) + local item_lib = require("items") + local class = selected_class(e.other) + if not class then + e.self:Say("Choose the class epic first.") + say_class_links(e.self) + item_lib.return_items(e.self, e.other, e.trade) + return + end + + local accepted_any = false + local fragment_handed = false + + for _, fragment in ipairs(fragments) do + local quantity = trade_fragment_quantity(e.trade, fragment) + if quantity > 0 then + fragment_handed = true + + local current = progress_for(e.other, fragment) + local needed = math.max(0, REQUIRED_COUNT - current) + local accepted = math.min(needed, quantity) + + if accepted > 0 and consume_fragment(e, fragment, accepted) then + set_progress(e.other, fragment, current + accepted) + accepted_any = true + end + end + end + + item_lib.return_items(e.self, e.other, e.trade) + + if accepted_any then + show_progress(e.other) + if is_complete(e.other) then + reward_coffer(e, class) + else + e.self:Say("The forge remembers your progress. Bring the rest when you have them.") + end + elseif is_complete(e.other) then + reward_coffer(e, class) + elseif fragment_handed then + e.self:Say("I already have enough of those fragments for this request.") + else + e.self:Say("Those are not the fragments this forge needs.") + end +end diff --git a/features/live-items/quests/global/900901.lua b/features/live-items/quests/global/900901.lua new file mode 100644 index 0000000000..5549d993ad --- /dev/null +++ b/features/live-items/quests/global/900901.lua @@ -0,0 +1,45 @@ +local TEST_LOOT_CACHE_ID = 199091 + +local forge_payload = table.concat({ + "LIVEITEM|ui|open", + "types=weapon,armor,jewelry,charm,shield,augment", + "max_hp=500", + "max_mana=500", + "max_ac=100", + "max_damage=100", + "max_haste=50", + "stats=hp,mana,endur,ac,str,sta,dex,agi,int,wis,cha,mr,fr,cr,pr,dr,svcorruption,attack,accuracy,avoidance,regen,manaregen,enduranceregen,haste,damage,delay,shielding,spellshield,dotshielding,stunresist,strikethrough,damageshield,dsmitigation,healamt,spelldmg,clairvoyance,backstabdmg,heroic_str,heroic_sta,heroic_dex,heroic_agi,heroic_int,heroic_wis,heroic_cha,heroic_mr,heroic_fr,heroic_cr,heroic_pr,heroic_dr,heroic_svcorrup", +}, "|") + +function event_say(e) + if e.message:findi("hail") then + e.self:QuestSay( + e.other, + "Item Forge testing is ready. Use " .. + eq.say_link("open forge") .. + " to open the native forge, " .. + eq.say_link("random cache") .. + " to get a test loot cache, or " .. + eq.say_link("five caches") .. + " for a small batch." + ) + return + end + + if e.message:findi("open forge") or e.message:findi("forge") then + e.other:Message(10, forge_payload) + e.self:QuestSay(e.other, "The forge interface is open. Try every item type and stat field.") + return + end + + if e.message:findi("five caches") then + e.other:SummonItem(TEST_LOOT_CACHE_ID, 5) + e.self:QuestSay(e.other, "Five test caches are on your cursor. Open them to create per-instance random loot.") + return + end + + if e.message:findi("random cache") or e.message:findi("cache") then + e.other:SummonItem(TEST_LOOT_CACHE_ID, 1) + e.self:QuestSay(e.other, "A test cache is on your cursor. Open it to create a per-instance random item.") + end +end diff --git a/features/live-items/quests/global/900902.lua b/features/live-items/quests/global/900902.lua new file mode 100644 index 0000000000..1c5d6237a1 --- /dev/null +++ b/features/live-items/quests/global/900902.lua @@ -0,0 +1,429 @@ +local CURRENCY_ID = 90 +local CURRENCY_NAME = "Blood Shards" +local CURRENCY_ITEM_ID = 81436 +local TEMPLATE_ITEM_ID = 199207 +local DEFAULT_NAME = "Bloodbound Augment" +local ALL_EQUIPMENT_SLOTS = 8388607 +local ALL_AUGMENT_TYPES = 2147483647 + +local upgrade_order = { + "hp", "mana", "endur", "ac", + "str", "sta", "agi", "dex", "int", "wis", "cha", + "fr", "cr", "mr", "dr", "pr", + "allstats", "allresists", + "attack", "accuracy", "regen", "manaregen", "damageshield", "spelldmg", "healamt", "haste", +} + +local upgrades = { + hp = { name = "HP", cost = 5, amount = 10, fields = { "hp" } }, + mana = { name = "Mana", cost = 5, amount = 10, fields = { "mana" } }, + endur = { name = "Endurance", cost = 5, amount = 10, fields = { "endur" } }, + ac = { name = "AC", cost = 5, amount = 2, fields = { "ac" } }, + str = { name = "Strength", cost = 5, amount = 1, fields = { "astr" } }, + sta = { name = "Stamina", cost = 5, amount = 1, fields = { "asta" } }, + agi = { name = "Agility", cost = 5, amount = 1, fields = { "aagi" } }, + dex = { name = "Dexterity", cost = 5, amount = 1, fields = { "adex" } }, + int = { name = "Intelligence", cost = 5, amount = 1, fields = { "aint" } }, + wis = { name = "Wisdom", cost = 5, amount = 1, fields = { "awis" } }, + cha = { name = "Charisma", cost = 5, amount = 1, fields = { "acha" } }, + fr = { name = "Fire Resist", cost = 5, amount = 2, fields = { "fr" } }, + cr = { name = "Cold Resist", cost = 5, amount = 2, fields = { "cr" } }, + mr = { name = "Magic Resist", cost = 5, amount = 2, fields = { "mr" } }, + dr = { name = "Disease Resist", cost = 5, amount = 2, fields = { "dr" } }, + pr = { name = "Poison Resist", cost = 5, amount = 2, fields = { "pr" } }, + allstats = { name = "All Stats", cost = 20, amount = 1, fields = { "astr", "asta", "aagi", "adex", "aint", "awis", "acha" } }, + allresists = { name = "All Resists", cost = 15, amount = 2, fields = { "fr", "cr", "mr", "dr", "pr" } }, + attack = { name = "Attack", cost = 10, amount = 2, fields = { "attack" } }, + accuracy = { name = "Accuracy", cost = 10, amount = 2, fields = { "accuracy" } }, + regen = { name = "HP Regen", cost = 10, amount = 1, fields = { "regen" } }, + manaregen = { name = "Mana Regen", cost = 10, amount = 1, fields = { "manaregen" } }, + damageshield = { name = "Damage Shield", cost = 10, amount = 1, fields = { "damageshield" } }, + spelldmg = { name = "Spell Damage", cost = 10, amount = 1, fields = { "spelldmg" } }, + healamt = { name = "Heal Amount", cost = 10, amount = 1, fields = { "healamt" } }, + haste = { name = "Haste", cost = 25, amount = 1, fields = { "haste" } }, +} + +local field_labels = { + hp = "HP", mana = "Mana", endur = "Endurance", ac = "AC", + astr = "STR", asta = "STA", aagi = "AGI", adex = "DEX", aint = "INT", awis = "WIS", acha = "CHA", + fr = "FR", cr = "CR", mr = "MR", dr = "DR", pr = "PR", + attack = "Attack", accuracy = "Accuracy", regen = "HP Regen", manaregen = "Mana Regen", + damageshield = "Damage Shield", spelldmg = "Spell Damage", healamt = "Heal Amount", haste = "Haste", +} + +local field_order = { + "hp", "mana", "endur", "ac", + "astr", "asta", "aagi", "adex", "aint", "awis", "acha", + "fr", "cr", "mr", "dr", "pr", + "attack", "accuracy", "regen", "manaregen", "damageshield", "spelldmg", "healamt", "haste", +} + +local field_caps = { + hp = 1000, mana = 1000, endur = 1000, ac = 100, + astr = 127, asta = 127, aagi = 127, adex = 127, aint = 127, awis = 127, acha = 127, + fr = 127, cr = 127, mr = 127, dr = 127, pr = 127, + attack = 250, accuracy = 127, regen = 100, manaregen = 100, + damageshield = 100, spelldmg = 100, healamt = 100, haste = 100, +} + +local function normalize(value) + return (value or ""):lower():gsub("^%s+", ""):gsub("%s+$", ""):gsub("[%s_%-]", "") +end + +local function say_link(command, label) + return eq.say_link(command, false, label or command) +end + +local function bucket_name(client, key) + return "live_items_orin_shardwork." .. client:CharacterID() .. "." .. key +end + +local function get_bucket(client, key) + return client:GetBucket(bucket_name(client, key)) or "" +end + +local function set_bucket(client, key, value) + client:SetBucket(bucket_name(client, key), tostring(value or "")) +end + +local function get_count(client, key) + return tonumber(get_bucket(client, "upgrade." .. key)) or 0 +end + +local function set_count(client, key, count) + set_bucket(client, "upgrade." .. key, math.max(0, count or 0)) +end + +local function is_started(client) + return get_bucket(client, "started") == "1" +end + +local function get_build_name(client) + local name = get_bucket(client, "name") + if name == "" then + return DEFAULT_NAME + end + return name +end + +local function sanitize_name(name) + name = tostring(name or ""):gsub("[\r\n\t]", " "):gsub("%s+", " "):gsub("^%s+", ""):gsub("%s+$", "") + if name == "" then + return DEFAULT_NAME + end + return string.sub(name, 1, 50) +end + +local function reset_build(client) + set_bucket(client, "started", "") + set_bucket(client, "name", "") + for _, key in ipairs(upgrade_order) do + set_count(client, key, 0) + end +end + +local function start_build(client) + reset_build(client) + set_bucket(client, "started", "1") + set_bucket(client, "name", DEFAULT_NAME) +end + +local function build_totals(client) + local total_cost = 0 + local field_totals = {} + local lines = {} + + for _, key in ipairs(upgrade_order) do + local count = get_count(client, key) + local upgrade = upgrades[key] + if upgrade and count > 0 then + total_cost = total_cost + (upgrade.cost * count) + table.insert(lines, upgrade.name .. " x" .. count .. " = " .. (upgrade.cost * count) .. " " .. CURRENCY_NAME) + for _, field in ipairs(upgrade.fields) do + field_totals[field] = (field_totals[field] or 0) + (upgrade.amount * count) + end + end + end + + return total_cost, field_totals, lines +end + +local function summarize_fields(field_totals) + local parts = {} + for _, field in ipairs(field_order) do + if field_totals[field] and field_totals[field] > 0 then + table.insert(parts, field_labels[field] .. " +" .. field_totals[field]) + end + end + return table.concat(parts, ", ") +end + +local function get_upgrade_cap(upgrade) + local cap = nil + for _, field in ipairs(upgrade.fields) do + if field_caps[field] then + if cap == nil or field_caps[field] < cap then + cap = field_caps[field] + end + end + end + return cap +end + +local function find_limit_violations(field_totals) + local violations = {} + for _, field in ipairs(field_order) do + local value = field_totals[field] or 0 + local cap = field_caps[field] + if cap and value > cap then + table.insert(violations, field_labels[field] .. " " .. value .. "/" .. cap) + end + end + return violations +end + +local function can_add_upgrade(client, upgrade) + local _, field_totals = build_totals(client) + for _, field in ipairs(upgrade.fields) do + local cap = field_caps[field] + local projected = (field_totals[field] or 0) + upgrade.amount + if cap and projected > cap then + return false, field, cap, projected + end + end + return true +end + +local function show_greeting(e) + local balance = e.other:GetAlternateCurrencyValue(CURRENCY_ID) or 0 + e.self:QuestSay( + e.other, + "Good. You found the quiet heat of the forge. I can bind little truths into an augment if you bring me " .. + CURRENCY_NAME .. ". You have " .. balance .. " " .. CURRENCY_NAME .. ". Say " .. + say_link("start", "start") .. " to begin, " .. + say_link("show", "show") .. " to review your current work, or " .. + say_link("confirm", "finish it") .. " when it is ready." + ) +end + +local function show_upgrade_menu(e) + local links = {} + for _, key in ipairs(upgrade_order) do + local upgrade = upgrades[key] + local cap = get_upgrade_cap(upgrade) + local cap_text = cap and (", cap " .. cap) or "" + table.insert( + links, + say_link("add " .. key, upgrade.name) .. + " (" .. upgrade.cost .. " for +" .. upgrade.amount .. cap_text .. ")" + ) + end + e.other:Message(15, table.concat(links, ", ")) +end + +local function show_build(e) + if not is_started(e.other) then + e.self:QuestSay(e.other, "No shardwork is active. Say " .. say_link("start", "start") .. " to begin one.") + return + end + + local total_cost, field_totals, lines = build_totals(e.other) + local summary = summarize_fields(field_totals) + if summary == "" then + summary = "no upgrades yet" + end + + e.self:QuestSay(e.other, "Current shardwork: " .. get_build_name(e.other) .. ". Cost: " .. total_cost .. " " .. CURRENCY_NAME .. ".") + e.other:Message(15, "Stats: " .. summary) + if #lines > 0 then + e.other:Message(15, "Upgrades: " .. table.concat(lines, "; ")) + end + e.other:Message( + 15, + "Commands: " .. say_link("name Bloodbound Focus", "name ") .. ", " .. + say_link("confirm", "finish it") .. ", " .. + say_link("reset", "reset") .. ", " .. + say_link("test shards", "test shards") + ) + show_upgrade_menu(e) +end + +local function add_upgrade(e, raw_key) + if not is_started(e.other) then + start_build(e.other) + end + + local key = normalize(raw_key) + local upgrade = upgrades[key] + if not upgrade then + e.self:QuestSay(e.other, "I do not know that shardwork. Say " .. say_link("show", "show") .. " to see the list.") + return + end + + local allowed, field, cap, projected = can_add_upgrade(e.other, upgrade) + if not allowed then + e.self:QuestSay( + e.other, + upgrade.name .. " would push " .. field_labels[field] .. " to " .. projected .. + ", above the safe augment cap of " .. cap .. "." + ) + return + end + + set_count(e.other, key, get_count(e.other, key) + 1) + local total_cost = build_totals(e.other) + e.self:QuestSay( + e.other, + upgrade.name .. " added. Current cost is " .. total_cost .. " " .. CURRENCY_NAME .. "." + ) +end + +local function set_build_name(e, raw_name) + if not is_started(e.other) then + start_build(e.other) + end + + local name = sanitize_name(raw_name) + set_bucket(e.other, "name", name) + e.self:QuestSay(e.other, "The augment will be named '" .. name .. "'.") +end + +local function create_augment(client, field_totals, total_cost) + local name = get_build_name(client) + local summary = summarize_fields(field_totals) + local data = { + name = name, + lore = "A custom augment shaped from Blood Shards by Orin Augspinner.", + comment = "Live Items shardwork augment. Cost " .. total_cost .. " " .. CURRENCY_NAME .. ". " .. summary, + slots = ALL_EQUIPMENT_SLOTS, + augtype = ALL_AUGMENT_TYPES, + } + local modifiers = {} + + for field, value in pairs(field_totals) do + local cap = field_caps[field] + if cap and value > cap then + value = cap + end + modifiers[field] = value + end + + local augment = eq.create_live_item({ + item_id = TEMPLATE_ITEM_ID, + charges = 1, + data = data, + modifiers = modifiers, + custom_data = { + live_items_test_roll = "orin-shardwork-augment", + live_items_currency_id = CURRENCY_ID, + live_items_currency_spent = total_cost, + live_items_summary = summary, + }, + }) + + if not augment or not augment.valid then + error("Augment template " .. tostring(TEMPLATE_ITEM_ID) .. " was not found.") + end + + return augment, summary +end + +local function confirm_build(e) + if not is_started(e.other) then + e.self:QuestSay(e.other, "No shardwork is active. Say " .. say_link("start", "start") .. " to begin one.") + return + end + + local total_cost, field_totals = build_totals(e.other) + if total_cost <= 0 then + e.self:QuestSay(e.other, "Add at least one upgrade before finishing the augment.") + show_build(e) + return + end + + local violations = find_limit_violations(field_totals) + if #violations > 0 then + e.other:Message(13, "This shardwork exceeds safe augment caps: " .. table.concat(violations, "; ") .. ". Say reset and rebuild it.") + return + end + + local balance = e.other:GetAlternateCurrencyValue(CURRENCY_ID) or 0 + if balance < total_cost then + e.self:QuestSay(e.other, "You need " .. total_cost .. " " .. CURRENCY_NAME .. ", but you only have " .. balance .. ".") + return + end + + if not e.other:RemoveAlternateCurrencyValue(CURRENCY_ID, total_cost) then + e.self:QuestSay(e.other, "The shardwork would not take payment. Try again after checking your " .. CURRENCY_NAME .. ".") + return + end + + local ok, augment, summary = pcall(create_augment, e.other, field_totals, total_cost) + if not ok or not augment then + e.other:AddAlternateCurrencyValue(CURRENCY_ID, total_cost) + e.other:Message(13, "The augment weave failed and your " .. CURRENCY_NAME .. " were returned.") + if eq and eq.debug then + eq.debug("Live Items Orin shardwork error: " .. tostring(augment), 1) + end + return + end + + local reward_name = get_build_name(e.other) + e.other:RewardLiveItem(augment) + reset_build(e.other) + e.self:QuestSay(e.other, "Done. The Blood Shards are bound into " .. reward_name .. ": " .. summary .. ".") +end + +function event_say(e) + local raw_message = e.message or "" + local message = normalize(raw_message) + + if message == "hail" then + show_greeting(e) + return + end + + if message == "start" or message == "begin" or message == "startashardwork" then + start_build(e.other) + e.self:QuestSay(e.other, "The shardwork is started. Add upgrades, name it if you like, then finish it.") + show_build(e) + return + end + + if message == "show" or message == "status" or message == "showmyshardwork" then + show_build(e) + return + end + + if message == "reset" or message == "forget" or message == "forgetit" then + reset_build(e.other) + e.self:QuestSay(e.other, "The shardwork is cleared.") + return + end + + if message == "confirm" or message == "finish" or message == "finishit" then + confirm_build(e) + return + end + + if message == "testshards" or message == "shards" then + e.other:AddAlternateCurrencyValue(CURRENCY_ID, 250) + e.other:SummonItem(CURRENCY_ITEM_ID, 20) + e.self:QuestSay(e.other, "I added 250 " .. CURRENCY_NAME .. " for testing and gave you a few shard tokens.") + return + end + + local name = raw_message:match("^[Nn][Aa][Mm][Ee]%s+(.+)$") or raw_message:match("^%<(.+)%>$") + if name then + set_build_name(e, name) + return + end + + local add_key = raw_message:match("^[Aa][Dd][Dd]%s+([%a]+)$") + if add_key then + add_upgrade(e, add_key) + return + end + + e.self:QuestSay(e.other, "Say " .. say_link("show", "show") .. " to see your shardwork, or " .. say_link("start", "start") .. " to begin one.") +end diff --git a/features/live-items/quests/global/900904.lua b/features/live-items/quests/global/900904.lua new file mode 100644 index 0000000000..caaf8ab40d --- /dev/null +++ b/features/live-items/quests/global/900904.lua @@ -0,0 +1,130 @@ +local classes = { + [1] = { name = "Warrior", base_item_id = 54231, class_mask = 1, itemtype = 0, slots = 24576, damage = 24, delay = 24 }, + [2] = { name = "Cleric", base_item_id = 54232, class_mask = 2, itemtype = 3, slots = 24576, damage = 18, delay = 28 }, + [3] = { name = "Paladin", base_item_id = 50515, class_mask = 4, itemtype = 1, slots = 8192, damage = 34, delay = 36 }, + [4] = { name = "Ranger", base_item_id = 54231, class_mask = 8, itemtype = 0, slots = 24576, damage = 26, delay = 30 }, + [5] = { name = "Shadow Knight", base_item_id = 50515, class_mask = 16, itemtype = 1, slots = 8192, damage = 36, delay = 38 }, + [6] = { name = "Druid", base_item_id = 50513, class_mask = 32, itemtype = 4, slots = 8192, damage = 16, delay = 28 }, + [7] = { name = "Monk", base_item_id = 50513, class_mask = 64, itemtype = 4, slots = 8192, damage = 22, delay = 22 }, + [8] = { name = "Bard", base_item_id = 54231, class_mask = 128, itemtype = 0, slots = 24576, damage = 20, delay = 24 }, + [9] = { name = "Rogue", base_item_id = 54230, class_mask = 256, itemtype = 2, slots = 24576, damage = 23, delay = 21 }, + [10] = { name = "Shaman", base_item_id = 54232, class_mask = 512, itemtype = 3, slots = 24576, damage = 17, delay = 29 }, + [11] = { name = "Necromancer", base_item_id = 50513, class_mask = 1024, itemtype = 4, slots = 8192, damage = 14, delay = 30 }, + [12] = { name = "Wizard", base_item_id = 50513, class_mask = 2048, itemtype = 4, slots = 8192, damage = 14, delay = 30 }, + [13] = { name = "Magician", base_item_id = 50513, class_mask = 4096, itemtype = 4, slots = 8192, damage = 14, delay = 30 }, + [14] = { name = "Enchanter", base_item_id = 50513, class_mask = 8192, itemtype = 4, slots = 8192, damage = 14, delay = 30 }, + [15] = { name = "Beastlord", base_item_id = 67128, class_mask = 16384, itemtype = 3, slots = 8192, damage = 21, delay = 24 }, + [16] = { name = "Berserker", base_item_id = 50515, class_mask = 32768, itemtype = 1, slots = 8192, damage = 38, delay = 40 }, +} + +local initial_stats = { + hp = 50, + mana = 50, + endur = 50, + ac = 5, + str = 5, + sta = 5, + dex = 5, + agi = 5, + int = 5, + wis = 5, + cha = 5, + mr = 5, + fr = 5, + cr = 5, + pr = 5, + dr = 5, + corruption = 5, + attack = 5, + accuracy = 5, +} + +local function trim_item_name(name) + name = tostring(name or "Live Items Heirloom") + name = name:gsub("%s+", " "):gsub("^%s+", ""):gsub("%s+$", "") + return string.sub(name, 1, 64) +end + +local function class_definition(client) + return classes[client:GetClass()] or classes[1] +end + +local function create_heirloom(client) + local class = class_definition(client) + local player_name = client:GetCleanName() + local item_name = trim_item_name(player_name .. "'s " .. class.name .. " Heirloom") + + local data = { + name = item_name, + lore = "A Live Items heirloom that grows when its owner gains levels.", + comment = "Live Items evolving heirloom. Level-up quest hook mutates this item instance.", + classes = class.class_mask, + races = 65535, + itemtype = class.itemtype, + slots = class.slots, + hp = initial_stats.hp, + mana = initial_stats.mana, + endur = initial_stats.endur, + ac = initial_stats.ac, + damage = class.damage, + delay = class.delay, + } + + local modifiers = {} + for key, value in pairs(initial_stats) do + if key ~= "hp" and key ~= "mana" and key ~= "endur" and key ~= "ac" then + modifiers[key] = value + end + end + + return eq.create_live_item({ + item_id = class.base_item_id, + charges = 1, + data = data, + modifiers = modifiers, + custom_data = { + live_items_heirloom = "1", + live_items_heirloom_owner = player_name, + live_items_heirloom_class = class.name, + live_items_heirloom_level = tostring(client:GetLevel()), + live_items_instance_rank = "0", + live_items_original_name = item_name, + live_items_summary = "Heirloom starter: all core stats/resists +5, HP/Mana/End +50, AC +5.", + }, + }) +end + +function event_say_heirloom(e) + local ok, item = pcall(create_heirloom, e.other) + if not ok or not item or not item.valid then + e.self:Say("The heirloom pattern failed. The class templates may need to be seeded.") + if not ok and eq and eq.debug then + eq.debug("Live Items heirloom creation error: " .. tostring(item), 1) + end + return + end + + e.other:RewardLiveItem(item) + e.self:Say( + "Your evolving heirloom is on your cursor: " .. item:GetItemLink() .. + ". This is a Live Items test weapon for your class. Keep it equipped or in your inventory when you level up. " .. + "Instead of creating a new item ID, the level-up hook finds this exact item instance and rewrites its dynamic stats, so this same weapon grows with you." + ) +end + +function event_say(e) + local message = (e.message or ""):lower() + + if message:find("heirloom") then + event_say_heirloom(e) + return + end + + if message:find("hail") then + local heirloom_link = eq.say_link("heirloom", false, "heirloom") + e.self:Say( + "I can hand you a class-matched " .. heirloom_link .. + ". Keep it equipped or in your inventory. Each level-up will mutate that exact item instance and add +10 to its supported stats. Use #heirloomdebug if you want to confirm the marker before leveling." + ) + end +end diff --git a/features/live-items/quests/global/900905.lua b/features/live-items/quests/global/900905.lua new file mode 100644 index 0000000000..c9a631e606 --- /dev/null +++ b/features/live-items/quests/global/900905.lua @@ -0,0 +1,241 @@ +local CATALYST_ITEM_ID = 199211 +local MAX_TRADE_SLOTS = 4 +local MAX_SOURCE_AUGMENTS = MAX_TRADE_SLOTS - 1 +local MIN_SOURCE_AUGMENTS = 1 + +local stat_fields = { + { key = "ac", label = "AC", get = function(item) return item:AC() end }, + { key = "hp", label = "HP", get = function(item) return item:HP() end }, + { key = "mana", label = "Mana", get = function(item) return item:Mana() end }, + { key = "endur", label = "Endurance", get = function(item) return item:Endur() end }, + { key = "str", label = "STR", get = function(item) return item:AStr() end }, + { key = "sta", label = "STA", get = function(item) return item:ASta() end }, + { key = "dex", label = "DEX", get = function(item) return item:ADex() end }, + { key = "agi", label = "AGI", get = function(item) return item:AAgi() end }, + { key = "int", label = "INT", get = function(item) return item:AInt() end }, + { key = "wis", label = "WIS", get = function(item) return item:AWis() end }, + { key = "cha", label = "CHA", get = function(item) return item:ACha() end }, + { key = "mr", label = "MR", get = function(item) return item:MR() end }, + { key = "fr", label = "FR", get = function(item) return item:FR() end }, + { key = "cr", label = "CR", get = function(item) return item:CR() end }, + { key = "pr", label = "PR", get = function(item) return item:PR() end }, + { key = "dr", label = "DR", get = function(item) return item:DR() end }, + { key = "svcorruption", label = "Corruption", get = function(item) return item:SVCorruption() end }, + { key = "attack", label = "Attack", get = function(item) return item:Attack() end }, + { key = "accuracy", label = "Accuracy", get = function(item) return item:Accuracy() end }, + { key = "avoidance", label = "Avoidance", get = function(item) return item:Avoidance() end }, + { key = "regen", label = "HP Regen", get = function(item) return item:Regen() end }, + { key = "manaregen", label = "Mana Regen", get = function(item) return item:ManaRegen() end }, + { key = "enduranceregen", label = "End Regen", get = function(item) return item:EnduranceRegen() end }, + { key = "damageshield", label = "Damage Shield", get = function(item) return item:DamageShield() end }, + { key = "healamt", label = "Heal Amount", get = function(item) return item:HealAmt() end }, + { key = "spelldmg", label = "Spell Damage", get = function(item) return item:SpellDmg() end }, + { key = "clairvoyance", label = "Clairvoyance", get = function(item) return item:Clairvoyance() end }, + { key = "hstr", label = "Heroic STR", get = function(item) return item:HeroicStr() end }, + { key = "hsta", label = "Heroic STA", get = function(item) return item:HeroicSta() end }, + { key = "hdex", label = "Heroic DEX", get = function(item) return item:HeroicDex() end }, + { key = "hagi", label = "Heroic AGI", get = function(item) return item:HeroicAgi() end }, + { key = "hint", label = "Heroic INT", get = function(item) return item:HeroicInt() end }, + { key = "hwis", label = "Heroic WIS", get = function(item) return item:HeroicWis() end }, + { key = "hcha", label = "Heroic CHA", get = function(item) return item:HeroicCha() end }, + { key = "hmr", label = "Heroic MR", get = function(item) return item:HeroicMR() end }, + { key = "hfr", label = "Heroic FR", get = function(item) return item:HeroicFR() end }, + { key = "hcr", label = "Heroic CR", get = function(item) return item:HeroicCR() end }, + { key = "hdr", label = "Heroic DR", get = function(item) return item:HeroicDR() end }, + { key = "hpr", label = "Heroic PR", get = function(item) return item:HeroicPR() end }, + { key = "hsvcorruption", label = "Heroic Corruption", get = function(item) return item:HeroicSVCorrup() end }, +} + +local function as_number(value) + return tonumber(value) or 0 +end + +local function clean_name(name) + name = tostring(name or "Augment") + name = name:gsub("^Fused%s+", "") + name = name:gsub("%s+", " "):gsub("^%s+", ""):gsub("%s+$", "") + if name == "" then + return "Augment" + end + return name +end + +local function short_name(name) + return string.sub(name, 1, 63) +end + +local function trade_items(trade) + local items = {} + for slot = 1, MAX_TRADE_SLOTS do + local inst = trade["item" .. tostring(slot)] + if inst and inst.valid then + table.insert(items, inst) + end + end + return items +end + +local function summarize(parts) + if #parts <= 8 then + return table.concat(parts, ", ") + end + + local visible = {} + for index = 1, 8 do + table.insert(visible, parts[index]) + end + table.insert(visible, "and " .. tostring(#parts - 8) .. " more") + return table.concat(visible, ", ") +end + +local function split_trade_items(items) + local catalysts = {} + local sources = {} + + for _, inst in ipairs(items) do + if inst:GetID() == CATALYST_ITEM_ID then + table.insert(catalysts, inst) + else + table.insert(sources, inst) + end + end + + return catalysts, sources +end + +local function validate_augments(catalysts, sources) + if #catalysts ~= 1 then + return nil, "I need exactly one Augment Catalyst with the augments you want fused." + end + + if #sources < MIN_SOURCE_AUGMENTS or #sources > MAX_SOURCE_AUGMENTS then + return nil, "Hand me one Augment Catalyst and one to three augment items." + end + + local required = { [tostring(CATALYST_ITEM_ID)] = 1 } + local source_ids = {} + + for _, inst in ipairs(sources) do + local base_id = inst:GetID() + local item = inst:GetItem() + if not item or as_number(item:ID()) == 0 or as_number(item:AugType()) == 0 then + return nil, "Every non-catalyst hand-in must be an augment." + end + + required[tostring(base_id)] = (required[tostring(base_id)] or 0) + 1 + table.insert(source_ids, tostring(base_id)) + end + + return { + required = required, + source_ids = source_ids, + } +end + +local function fuse_augments(sources, source_ids) + local totals = {} + local changed = {} + + for _, field in ipairs(stat_fields) do + local total = 0 + for _, inst in ipairs(sources) do + local item = inst:GetItem() + total = total + as_number(field.get(item)) + end + totals[field.key] = total + end + + local output = sources[1]:Clone() + output:ClearDynamicItemData() + + for _, field in ipairs(stat_fields) do + local total = totals[field.key] + if total ~= 0 then + output:SetDynamicItemData(field.key, total) + table.insert(changed, field.label .. " " .. tostring(total)) + end + end + + if #changed == 0 then + return nil, "Those augments do not have any supported stats to fuse." + end + + local source_name = output:GetCustomData("live_items_aug_fusion_root_name") + if source_name == "" then + local item = sources[1]:GetItem() + source_name = item and clean_name(item:Name()) or "Augment" + end + + local name = short_name("Fused " .. clean_name(source_name)) + output:SetDynamicItemData("name", name) + output:SetCustomData("live_items_aug_fusion", "1") + output:SetCustomData("live_items_aug_fusion_root_name", source_name) + output:SetCustomData("live_items_aug_fusion_component_count", tostring(#sources)) + output:SetCustomData("live_items_aug_fusion_sources", table.concat(source_ids, ",")) + output:RebuildDynamicItemData() + + return { + item = output, + name = name, + changed = changed, + } +end + +function event_say(e) + if e.message:findi("catalyst") then + e.other:SummonItem(CATALYST_ITEM_ID, 1) + e.self:Say("An Augment Catalyst is on your cursor. Hand it back to me with one to three augment items and no coins when you are ready to test fusion.") + return + end + + if not e.message:findi("hail") then + return + end + + e.self:Say( + "Hand me one Augment Catalyst plus one to three augment items and no coins. " .. + "I will return one fused augment that carries the combined supported stats from the augment items. " .. + "Say " .. eq.say_link("catalyst") .. " if you need a catalyst for testing." + ) +end + +function event_trade(e) + local item_lib = require("items") + local items = trade_items(e.trade) + + if #items < 2 or #items > MAX_TRADE_SLOTS or e.trade.platinum > 0 or e.trade.gold > 0 or e.trade.silver > 0 or e.trade.copper > 0 then + e.self:Say("Hand me one Augment Catalyst plus one to three augment items and no coins.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + + local catalysts, sources = split_trade_items(items) + local validation, validation_error = validate_augments(catalysts, sources) + if not validation then + e.self:Say(validation_error) + item_lib.return_items(e.self, e.other, e.trade) + return + end + + local result, fuse_error = fuse_augments(sources, validation.source_ids) + if not result then + e.self:Say(fuse_error) + item_lib.return_items(e.self, e.other, e.trade) + return + end + + if not e.self:CheckHandin(e.other, {}, validation.required, {}) then + e.self:Say("The hand-in did not line up cleanly. Try handing me only the catalyst and augments you want fused.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + + if not e.other:PushItemOnCursor(result.item) then + e.self:Say("The fusion worked, but I could not place the fused augment on your cursor.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + + e.self:Say("Returned " .. result.item:GetItemLink() .. " with fused stats: " .. summarize(result.changed) .. ".") + item_lib.return_items(e.self, e.other, e.trade) +end diff --git a/features/live-items/quests/global/900906.lua b/features/live-items/quests/global/900906.lua new file mode 100644 index 0000000000..4f146eb816 --- /dev/null +++ b/features/live-items/quests/global/900906.lua @@ -0,0 +1,204 @@ +local UPGRADE_AMOUNT = 10 + +local stat_fields = { + { key = "hp", label = "HP", cap = 5000, get = function(item) return item:HP() end }, + { key = "mana", label = "Mana", cap = 5000, get = function(item) return item:Mana() end }, + { key = "endur", label = "Endurance", cap = 5000, get = function(item) return item:Endur() end }, + { key = "ac", label = "AC", cap = 1000, get = function(item) return item:AC() end }, + { key = "damage", label = "Damage", cap = 500, get = function(item) return item:Damage() end }, + { key = "str", label = "STR", cap = 500, get = function(item) return item:AStr() end }, + { key = "sta", label = "STA", cap = 500, get = function(item) return item:ASta() end }, + { key = "dex", label = "DEX", cap = 500, get = function(item) return item:ADex() end }, + { key = "agi", label = "AGI", cap = 500, get = function(item) return item:AAgi() end }, + { key = "int", label = "INT", cap = 500, get = function(item) return item:AInt() end }, + { key = "wis", label = "WIS", cap = 500, get = function(item) return item:AWis() end }, + { key = "cha", label = "CHA", cap = 500, get = function(item) return item:ACha() end }, + { key = "mr", label = "MR", cap = 500, get = function(item) return item:MR() end }, + { key = "fr", label = "FR", cap = 500, get = function(item) return item:FR() end }, + { key = "cr", label = "CR", cap = 500, get = function(item) return item:CR() end }, + { key = "pr", label = "PR", cap = 500, get = function(item) return item:PR() end }, + { key = "dr", label = "DR", cap = 500, get = function(item) return item:DR() end }, + { key = "corruption", label = "Corruption", cap = 500, get = function(item) return item:SVCorruption() end }, + { key = "hstr", label = "Heroic STR", cap = 500, get = function(item) return item:HeroicStr() end }, + { key = "hsta", label = "Heroic STA", cap = 500, get = function(item) return item:HeroicSta() end }, + { key = "hdex", label = "Heroic DEX", cap = 500, get = function(item) return item:HeroicDex() end }, + { key = "hagi", label = "Heroic AGI", cap = 500, get = function(item) return item:HeroicAgi() end }, + { key = "hint", label = "Heroic INT", cap = 500, get = function(item) return item:HeroicInt() end }, + { key = "hwis", label = "Heroic WIS", cap = 500, get = function(item) return item:HeroicWis() end }, + { key = "hcha", label = "Heroic CHA", cap = 500, get = function(item) return item:HeroicCha() end }, + { key = "hmr", label = "Heroic MR", cap = 500, get = function(item) return item:HeroicMR() end }, + { key = "hfr", label = "Heroic FR", cap = 500, get = function(item) return item:HeroicFR() end }, + { key = "hcr", label = "Heroic CR", cap = 500, get = function(item) return item:HeroicCR() end }, + { key = "hpr", label = "Heroic PR", cap = 500, get = function(item) return item:HeroicPR() end }, + { key = "hdr", label = "Heroic DR", cap = 500, get = function(item) return item:HeroicDR() end }, + { key = "hsvcorruption", label = "Heroic Corrup", cap = 500, get = function(item) return item:HeroicSVCorrup() end }, + { key = "attack", label = "Attack", cap = 500, get = function(item) return item:Attack() end }, + { key = "accuracy", label = "Accuracy", cap = 500, get = function(item) return item:Accuracy() end }, + { key = "avoidance", label = "Avoidance", cap = 500, get = function(item) return item:Avoidance() end }, + { key = "combateffects", label = "Combat Effects", cap = 500, get = function(item) return item:CombatEffects() end }, + { key = "shielding", label = "Shielding", cap = 500, get = function(item) return item:Shielding() end }, + { key = "spellshield", label = "Spell Shield", cap = 500, get = function(item) return item:SpellShield() end }, + { key = "dotshielding", label = "DoT Shield", cap = 500, get = function(item) return item:DotShielding() end }, + { key = "stunresist", label = "Stun Resist", cap = 500, get = function(item) return item:StunResist() end }, + { key = "strikethrough", label = "Strikethrough", cap = 500, get = function(item) return item:StrikeThrough() end }, + { key = "regen", label = "HP Regen", cap = 500, get = function(item) return item:Regen() end }, + { key = "manaregen", label = "Mana Regen", cap = 500, get = function(item) return item:ManaRegen() end }, + { key = "enduranceregen", label = "End Regen", cap = 500, get = function(item) return item:EnduranceRegen() end }, + { key = "damageshield", label = "Damage Shield", cap = 500, get = function(item) return item:DamageShield() end }, + { key = "dsmitigation", label = "DS Mitigation", cap = 500, get = function(item) return item:DSMitigation() end }, + { key = "healamt", label = "Heal Amount", cap = 500, get = function(item) return item:HealAmt() end }, + { key = "spelldmg", label = "Spell Damage", cap = 500, get = function(item) return item:SpellDmg() end }, + { key = "clairvoyance", label = "Clairvoyance", cap = 500, get = function(item) return item:Clairvoyance() end }, + { key = "backstabdmg", label = "Backstab Dmg", cap = 500, get = function(item) return item:BackstabDmg() end }, + { key = "haste", label = "Haste", cap = 100, get = function(item) return item:Haste() end }, +} + +local function number(value, default) + local converted = tonumber(value) + if converted == nil then + return default + end + return converted +end + +local function trim_item_name(name) + name = tostring(name or "Live Item") + name = name:gsub("%s+", " "):gsub("^%s+", ""):gsub("%s+$", "") + return string.sub(name, 1, 64) +end + +local function root_name(inst) + local stored = inst:GetCustomData("live_items_original_name") + if stored and stored ~= "" then + return stored + end + + local name = tostring(inst:GetName() or "Live Item") + name = name:gsub("%s%+%d+$", "") + inst:SetCustomData("live_items_original_name", name) + return name +end + +local function summarize(parts) + if #parts <= 8 then + return table.concat(parts, ", ") + end + + local visible = {} + for index = 1, 8 do + table.insert(visible, parts[index]) + end + + table.insert(visible, "and " .. tostring(#parts - 8) .. " more") + return table.concat(visible, ", ") +end + +local function upgrade_instance(inst, amount) + local item = inst:GetItem() + if not item or not item:valid() then + return nil, "The handed-in item could not be inspected." + end + + local rank = number(inst:GetCustomData("live_items_instance_rank"), 0) + 1 + local changed = {} + + for _, field in ipairs(stat_fields) do + local current = number(field.get(item), 0) + if current > 0 then + local next_value = math.min(field.cap, current + amount) + inst:DeleteDynamicItemModifier(field.key) + inst:SetDynamicItemData(field.key, next_value) + table.insert(changed, field.label .. " " .. tostring(current) .. "->" .. tostring(next_value)) + end + end + + if #changed == 0 then + for _, field in ipairs({ + { key = "hp", label = "HP", value = amount }, + { key = "mana", label = "Mana", value = amount }, + { key = "endur", label = "Endurance", value = amount }, + { key = "ac", label = "AC", value = amount }, + }) do + inst:DeleteDynamicItemModifier(field.key) + inst:SetDynamicItemData(field.key, field.value) + table.insert(changed, field.label .. " 0->" .. tostring(field.value)) + end + end + + local name = trim_item_name(root_name(inst) .. " +" .. tostring(rank)) + inst:SetDynamicItemData("name", name) + inst:SetDynamicItemData("comment", "Live Items instance upgrade rank " .. tostring(rank) .. ": " .. summarize(changed)) + inst:SetCustomData("live_items_instance_rank", tostring(rank)) + inst:SetCustomData("live_items_last_instance_upgrade", tostring(os.time())) + inst:RebuildDynamicItemData() + + return { + name = name, + rank = rank, + changed_count = #changed, + summary = summarize(changed), + } +end + +local function trade_items(trade) + local items = {} + for slot = 1, 4 do + local inst = trade["item" .. tostring(slot)] + if inst and inst.valid then + table.insert(items, inst) + end + end + return items +end + +function event_say(e) + if not e.message:findi("hail") then + return + end + + e.self:Say( + "Hand me exactly one item and I will return that same item instance as a +1 version. " .. + "Every supported positive stat it already has gains +" .. tostring(UPGRADE_AMOUNT) .. + ". If it has no supported stats yet, I seed HP, mana, endurance, and AC so the mutation is visible." + ) +end + +function event_trade(e) + local item_lib = require("items") + local items = trade_items(e.trade) + + if #items ~= 1 or e.trade.platinum > 0 or e.trade.gold > 0 or e.trade.silver > 0 or e.trade.copper > 0 then + e.self:Say("Hand me exactly one item and no coins. I need a clean handoff so I can mutate that exact instance.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + + local original = items[1] + local original_id = original:GetID() + local original_restore = original:Clone() + local upgraded = original:Clone() + local result, error_message = upgrade_instance(upgraded, UPGRADE_AMOUNT) + if not result then + e.self:Say(error_message) + item_lib.return_items(e.self, e.other, e.trade) + return + end + + if not e.self:CheckHandin(e.other, {}, { [tostring(original_id)] = 1 }, {}) then + e.self:Say("The hand-in did not line up cleanly. Hand me exactly one item and no coins.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + + if not e.other:PushItemOnCursor(upgraded) then + e.self:Say("The hand-in slipped out of the forge's grasp. I could not place the upgraded item on your cursor, so I returned the original item.") + e.other:PushItemOnCursor(original_restore) + return + end + + e.self:Say( + "Returned " .. upgraded:GetItemLink() .. " at +" .. tostring(result.rank) .. + ". Updated " .. tostring(result.changed_count) .. " fields: " .. result.summary .. "." + ) + item_lib.return_items(e.self, e.other, e.trade) +end diff --git a/features/live-items/quests/global/global_player.lua b/features/live-items/quests/global/global_player.lua new file mode 100644 index 0000000000..b409cdd649 --- /dev/null +++ b/features/live-items/quests/global/global_player.lua @@ -0,0 +1,335 @@ +local CURSOR_SLOT = 33 +local HEIRLOOM_GROWTH_PER_LEVEL = 10 +local DEBUG_HEIRLOOM_LEVEL_UP = true + +local commands = { + helditemid = true, + itemid = true, + cursoritemid = true, + heirloomdebug = true, + evolvingdebug = true, + liveitemdebug = true, +} + +local function is_handled_command(command) + return commands[string.lower(tostring(command or ""))] == true +end + +local function message(client, text) + client:Message(15, text) +end + +local function debug_message(client, text) + if DEBUG_HEIRLOOM_LEVEL_UP then + message(client, "[LiveItems Debug] " .. text) + end +end + +local function number(value, default) + local converted = tonumber(value) + if converted == nil then + return default + end + return converted +end + +local function trim_item_name(name) + name = tostring(name or "Live Items Heirloom") + name = name:gsub("%s+", " "):gsub("^%s+", ""):gsub("%s+$", "") + return string.sub(name, 1, 64) +end + +local stat_fields = { + { key = "hp", label = "HP", cap = 5000, get = function(item) return item:HP() end }, + { key = "mana", label = "Mana", cap = 5000, get = function(item) return item:Mana() end }, + { key = "endur", label = "Endurance", cap = 5000, get = function(item) return item:Endur() end }, + { key = "ac", label = "AC", cap = 1000, get = function(item) return item:AC() end }, + { key = "damage", label = "Damage", cap = 500, get = function(item) return item:Damage() end }, + { key = "str", label = "STR", cap = 500, get = function(item) return item:AStr() end }, + { key = "sta", label = "STA", cap = 500, get = function(item) return item:ASta() end }, + { key = "dex", label = "DEX", cap = 500, get = function(item) return item:ADex() end }, + { key = "agi", label = "AGI", cap = 500, get = function(item) return item:AAgi() end }, + { key = "int", label = "INT", cap = 500, get = function(item) return item:AInt() end }, + { key = "wis", label = "WIS", cap = 500, get = function(item) return item:AWis() end }, + { key = "cha", label = "CHA", cap = 500, get = function(item) return item:ACha() end }, + { key = "mr", label = "MR", cap = 500, get = function(item) return item:MR() end }, + { key = "fr", label = "FR", cap = 500, get = function(item) return item:FR() end }, + { key = "cr", label = "CR", cap = 500, get = function(item) return item:CR() end }, + { key = "pr", label = "PR", cap = 500, get = function(item) return item:PR() end }, + { key = "dr", label = "DR", cap = 500, get = function(item) return item:DR() end }, + { key = "corruption", label = "Corruption", cap = 500, get = function(item) return item:SVCorruption() end }, + { key = "hstr", label = "Heroic STR", cap = 500, get = function(item) return item:HeroicStr() end }, + { key = "hsta", label = "Heroic STA", cap = 500, get = function(item) return item:HeroicSta() end }, + { key = "hdex", label = "Heroic DEX", cap = 500, get = function(item) return item:HeroicDex() end }, + { key = "hagi", label = "Heroic AGI", cap = 500, get = function(item) return item:HeroicAgi() end }, + { key = "hint", label = "Heroic INT", cap = 500, get = function(item) return item:HeroicInt() end }, + { key = "hwis", label = "Heroic WIS", cap = 500, get = function(item) return item:HeroicWis() end }, + { key = "hcha", label = "Heroic CHA", cap = 500, get = function(item) return item:HeroicCha() end }, + { key = "hmr", label = "Heroic MR", cap = 500, get = function(item) return item:HeroicMR() end }, + { key = "hfr", label = "Heroic FR", cap = 500, get = function(item) return item:HeroicFR() end }, + { key = "hcr", label = "Heroic CR", cap = 500, get = function(item) return item:HeroicCR() end }, + { key = "hpr", label = "Heroic PR", cap = 500, get = function(item) return item:HeroicPR() end }, + { key = "hdr", label = "Heroic DR", cap = 500, get = function(item) return item:HeroicDR() end }, + { key = "hsvcorruption", label = "Heroic Corrup", cap = 500, get = function(item) return item:HeroicSVCorrup() end }, + { key = "attack", label = "Attack", cap = 500, get = function(item) return item:Attack() end }, + { key = "accuracy", label = "Accuracy", cap = 500, get = function(item) return item:Accuracy() end }, + { key = "avoidance", label = "Avoidance", cap = 500, get = function(item) return item:Avoidance() end }, + { key = "combateffects", label = "Combat Effects", cap = 500, get = function(item) return item:CombatEffects() end }, + { key = "shielding", label = "Shielding", cap = 500, get = function(item) return item:Shielding() end }, + { key = "spellshield", label = "Spell Shield", cap = 500, get = function(item) return item:SpellShield() end }, + { key = "dotshielding", label = "DoT Shield", cap = 500, get = function(item) return item:DotShielding() end }, + { key = "stunresist", label = "Stun Resist", cap = 500, get = function(item) return item:StunResist() end }, + { key = "strikethrough", label = "Strikethrough", cap = 500, get = function(item) return item:StrikeThrough() end }, + { key = "regen", label = "HP Regen", cap = 500, get = function(item) return item:Regen() end }, + { key = "manaregen", label = "Mana Regen", cap = 500, get = function(item) return item:ManaRegen() end }, + { key = "enduranceregen", label = "End Regen", cap = 500, get = function(item) return item:EnduranceRegen() end }, + { key = "damageshield", label = "Damage Shield", cap = 500, get = function(item) return item:DamageShield() end }, + { key = "dsmitigation", label = "DS Mitigation", cap = 500, get = function(item) return item:DSMitigation() end }, + { key = "healamt", label = "Heal Amount", cap = 500, get = function(item) return item:HealAmt() end }, + { key = "spelldmg", label = "Spell Damage", cap = 500, get = function(item) return item:SpellDmg() end }, + { key = "clairvoyance", label = "Clairvoyance", cap = 500, get = function(item) return item:Clairvoyance() end }, + { key = "backstabdmg", label = "Backstab Dmg", cap = 500, get = function(item) return item:BackstabDmg() end }, + { key = "haste", label = "Haste", cap = 100, get = function(item) return item:Haste() end }, +} + +local function root_name(inst) + local stored = inst:GetCustomData("live_items_original_name") + if stored and stored ~= "" then + return stored + end + + local name = tostring(inst:GetName() or "Live Items Heirloom") + name = name:gsub("%s%+%d+$", "") + inst:SetCustomData("live_items_original_name", name) + return name +end + +local function is_heirloom(inst) + if not inst or not inst.valid then + return false + end + + return inst:GetCustomData("live_items_heirloom") == "1" +end + +local function short_item_label(inst) + if not inst or not inst.valid then + return "empty" + end + + local link = inst:GetItemLink() + if link and link ~= "" then + return link + end + + return tostring(inst:GetName() or ("item " .. tostring(inst:GetID()))) +end + +local function scan_heirloom_slots(client, send_debug) + local inventory = client:GetInventory() + local result = { + scanned = 0, + occupied = 0, + found = {}, + cursor = nil, + } + + for _, slot_id in pairs(client:GetInventorySlots()) do + if slot_id < 2000 then + local inst = inventory:GetItem(slot_id) + + if slot_id == CURSOR_SLOT then + if inst and inst.valid then + result.cursor = inst + end + else + result.scanned = result.scanned + 1 + if inst and inst.valid then + result.occupied = result.occupied + 1 + if is_heirloom(inst) then + table.insert(result.found, { slot_id = slot_id, inst = inst }) + end + end + end + end + end + + if send_debug then + debug_message( + client, + "Heirloom scan: scanned " .. tostring(result.scanned) .. + " normal slots, occupied " .. tostring(result.occupied) .. + ", marked heirlooms found " .. tostring(#result.found) .. "." + ) + + for _, entry in ipairs(result.found) do + local inst = entry.inst + debug_message( + client, + "Found heirloom slot " .. tostring(entry.slot_id) .. + ": " .. short_item_label(inst) .. + ", rank " .. tostring(inst:GetCustomData("live_items_instance_rank") or "0") .. + ", owner " .. tostring(inst:GetCustomData("live_items_heirloom_owner") or "") + ) + end + + if result.cursor and result.cursor.valid then + debug_message( + client, + "Cursor holds " .. short_item_label(result.cursor) .. + " with heirloom flag '" .. tostring(result.cursor:GetCustomData("live_items_heirloom") or "") .. + "'. Cursor items are not auto-grown; put the heirloom in inventory or equipment before leveling." + ) + end + end + + return result +end + +local function summarize(parts) + if #parts <= 6 then + return table.concat(parts, ", ") + end + + local visible = {} + for index = 1, 6 do + table.insert(visible, parts[index]) + end + table.insert(visible, "and " .. tostring(#parts - 6) .. " more") + return table.concat(visible, ", ") +end + +local function grow_heirloom(inst, levels_gained) + local item = inst:GetItem() + if not item or not item:valid() then + return nil + end + + local amount = HEIRLOOM_GROWTH_PER_LEVEL * math.max(1, levels_gained) + local rank = number(inst:GetCustomData("live_items_instance_rank"), 0) + math.max(1, levels_gained) + local changed = {} + + for _, field in ipairs(stat_fields) do + local current = number(field.get(item), 0) + if current > 0 then + local next_value = math.min(field.cap, current + amount) + inst:DeleteDynamicItemModifier(field.key) + inst:SetDynamicItemData(field.key, next_value) + table.insert(changed, field.label .. " +" .. tostring(next_value - current)) + end + end + + if #changed == 0 then + return nil + end + + local name = trim_item_name(root_name(inst) .. " +" .. tostring(rank)) + inst:SetDynamicItemData("name", name) + inst:SetDynamicItemData("comment", "Live Items heirloom growth rank " .. tostring(rank) .. ": " .. summarize(changed)) + inst:SetCustomData("live_items_heirloom", "1") + inst:SetCustomData("live_items_instance_rank", tostring(rank)) + inst:SetCustomData("live_items_heirloom_level", tostring(number(inst:GetCustomData("live_items_heirloom_level"), 0) + math.max(1, levels_gained))) + inst:SetCustomData("live_items_last_heirloom_growth", tostring(os.time())) + inst:RebuildDynamicItemData() + + return { + name = name, + rank = rank, + changed_count = #changed, + summary = summarize(changed), + } +end + +function event_command(e) + if not is_handled_command(e.command) then + return 0 + end + + local command = string.lower(tostring(e.command or "")) + if command == "heirloomdebug" or command == "evolvingdebug" or command == "liveitemdebug" then + debug_message(e.self, "Manual heirloom debug command received.") + scan_heirloom_slots(e.self, true) + return 1 + end + + local inst = e.self:GetInventory():GetItem(CURSOR_SLOT) + if not inst or not inst.valid then + message(e.self, "Hold an item on your cursor, then use #helditemid.") + return 1 + end + + local item_id = inst:GetID() + if item_id == nil or item_id <= 0 then + message(e.self, "I could not read an item ID from the held cursor item.") + return 1 + end + + local name = inst:GetName() + local link = inst:GetItemLink() + local serial = inst:GetSerialNumber() + local parts = { + "Held item ID: " .. tostring(item_id), + } + + if name and name ~= "" then + table.insert(parts, "Name: " .. name) + end + + if link and link ~= "" then + table.insert(parts, "Link: " .. link) + end + + if serial and serial > 0 then + table.insert(parts, "Serial: " .. tostring(serial)) + end + + message(e.self, table.concat(parts, " | ")) + return 1 +end + +function event_level_up(e) + local client = e.self + local levels_gained = math.max(1, number(e.levels_gained, 1)) + local grown = 0 + local first_link = nil + local first_summary = nil + + debug_message(client, "event_level_up fired; levels_gained=" .. tostring(levels_gained) .. ".") + local scan = scan_heirloom_slots(client, true) + + for _, entry in ipairs(scan.found) do + local slot_id = entry.slot_id + local inst = entry.inst + debug_message(client, "Attempting heirloom growth in slot " .. tostring(slot_id) .. ": " .. short_item_label(inst)) + + local upgraded = inst:Clone() + local result = grow_heirloom(upgraded, levels_gained) + if result and client:PutItemInInventory(slot_id, upgraded) then + grown = grown + 1 + debug_message(client, "Slot " .. tostring(slot_id) .. " updated to rank " .. tostring(result.rank) .. ".") + if first_link == nil then + first_link = upgraded:GetItemLink() + first_summary = result.summary + end + elseif result then + debug_message(client, "Slot " .. tostring(slot_id) .. " growth failed while saving back to inventory.") + else + debug_message(client, "Slot " .. tostring(slot_id) .. " had no supported positive stats to grow.") + end + end + + if grown > 0 then + local level_text = levels_gained == 1 and "level" or "levels" + message( + client, + "Your Live Items heirloom grew for " .. tostring(levels_gained) .. " " .. level_text .. + ": " .. tostring(first_link or "heirloom") .. " (" .. tostring(first_summary or "stats increased") .. ")." + ) + + if grown > 1 then + message(client, tostring(grown) .. " heirloom items were updated.") + end + else + debug_message(client, "No heirloom items were updated on this level-up.") + end +end diff --git a/features/live-items/quests/global/items/199091.lua b/features/live-items/quests/global/items/199091.lua new file mode 100644 index 0000000000..df1b5c6cf6 --- /dev/null +++ b/features/live-items/quests/global/items/199091.lua @@ -0,0 +1,219 @@ +local CACHE_ITEM_ID = 199091 + +local templates = { + { id = 6002, type = "Weapon", name = "Staff", damage = true }, + { id = 6919, type = "Weapon", name = "Forlorn Bow", damage = true }, + { id = 7007, type = "Weapon", name = "Rusty Dagger", damage = true }, + { id = 10686, type = "Weapon", name = "Warhammer of Ethereal Energy", damage = true }, + { id = 14148, type = "Jewelry", name = "Ornate Ring" }, + { id = 59945, type = "Armor", name = "Kobold Leather Belt" }, + { id = 82924, type = "Armor", name = "Gloomiron Bracer" }, + { id = 82925, type = "Armor", name = "Gloomiron Gauntlets" }, + { id = 82926, type = "Armor", name = "Gloomiron Boots" }, + { id = 82927, type = "Armor", name = "Gloomiron Helm" }, + { id = 82931, type = "Armor", name = "Gloomchain Bracer" }, + { id = 82932, type = "Armor", name = "Gloomchain Gauntlets" }, + { id = 82933, type = "Armor", name = "Gloomchain Boots" }, + { id = 82934, type = "Armor", name = "Gloomchain Coif" }, + { id = 82952, type = "Weapon", name = "Gloomsteel Blade", damage = true }, + { id = 82953, type = "Weapon", name = "Gloomsteel Dagger", damage = true }, + { id = 82954, type = "Weapon", name = "Gloomsteel Hammer", damage = true }, + { id = 82955, type = "Weapon", name = "Gloomsteel Axe", damage = true }, + { id = 82956, type = "Weapon", name = "Gloomsteel Staff", damage = true }, +} + +local tiers = { + { name = "Magic", weight = 65, rolls = 6, min = 2, max = 8 }, + { name = "Rare", weight = 28, rolls = 8, min = 4, max = 12 }, + { name = "Legendary", weight = 7, rolls = 10, min = 7, max = 16 }, +} + +local stat_pool = { + { label = "STR", keys = { "str" } }, + { label = "STA", keys = { "sta" } }, + { label = "DEX", keys = { "dex" } }, + { label = "AGI", keys = { "agi" } }, + { label = "INT", keys = { "int" } }, + { label = "WIS", keys = { "wis" } }, + { label = "CHA", keys = { "cha" } }, + { label = "HP", data = "hp" }, + { label = "Mana", data = "mana" }, + { label = "Endurance", data = "endur" }, + { label = "AC", data = "ac" }, + { label = "Resist", keys = { "mr", "fr", "cr", "pr", "dr" } }, + { label = "Accuracy", keys = { "accuracy" } }, + { label = "Avoidance", keys = { "avoidance" } }, + { label = "Attack", keys = { "attack" } }, +} + +local suffixes = { + "of Embers", + "of Sparks", + "of the Rift", + "of the Noble Cause", + "of the Bloodfield", + "of the Sanctum", + "of Slaughter", +} + +local function roll_tier() + local total = 0 + for _, tier in ipairs(tiers) do + total = total + tier.weight + end + + local roll = math.random(total) + for _, tier in ipairs(tiers) do + if roll <= tier.weight then + return tier + end + roll = roll - tier.weight + end + + return tiers[1] +end + +local function add_roll(totals, stat, value) + totals[stat.label] = (totals[stat.label] or 0) + value + if stat.data then + totals[stat.data] = (totals[stat.data] or 0) + value + end + if stat.keys then + for _, key in ipairs(stat.keys) do + totals[key] = (totals[key] or 0) + value + end + end +end + +local function roll_stats(tier) + local totals = {} + local available = {} + + for _, stat in ipairs(stat_pool) do + table.insert(available, stat) + end + + for _ = 1, tier.rolls do + local source = available + if #source == 0 then + source = stat_pool + end + + local index = math.random(#source) + local stat = source[index] + add_roll(totals, stat, math.random(tier.min, tier.max)) + + if source == available then + table.remove(available, index) + end + end + + return totals +end + +local function summarize(stats) + local order = { "STR", "STA", "DEX", "AGI", "INT", "WIS", "CHA", "HP", "Mana", "Endurance", "AC", "Resist", "Accuracy", "Avoidance", "Attack" } + local parts = {} + for _, label in ipairs(order) do + if stats[label] and stats[label] > 0 then + table.insert(parts, label .. " +" .. stats[label]) + end + end + return table.concat(parts, ", ") +end + +local function create_random_item_from_template(template) + local tier = roll_tier() + local stats = roll_stats(tier) + local name = tier.name .. " " .. template.name .. " " .. suffixes[math.random(#suffixes)] + local summary = summarize(stats) + local data = { + name = name, + lore = "A unique tester roll created by the Live Items test cache.", + comment = "Live Items tester instance roll: " .. summary, + } + local modifiers = {} + + for key, value in pairs(stats) do + if key == "hp" or key == "mana" or key == "endur" or key == "ac" then + data[key] = value + elseif type(key) == "string" and key:lower() == key then + modifiers[key] = value + end + end + + if template.damage then + data.damage = math.random(8, 26) + data.delay = math.random(20, 34) + elseif template.augment then + data.ac = math.max(data.ac or 0, math.random(2, 8)) + else + data.damage = 0 + data.delay = 0 + end + + local item = eq.create_live_item({ + item_id = template.id, + charges = 1, + data = data, + modifiers = modifiers, + custom_data = { + live_items_test_roll = "tutorialb-cache", + live_items_tier = tier.name, + live_items_summary = summary, + }, + }) + + if not item or not item.valid then + error("Template item " .. tostring(template.id) .. " was not found.") + end + + return { + inst = item, + name = name, + tier = tier.name, + summary = summary, + } +end + +local function create_random_item(e) + local candidates = {} + for _, template in ipairs(templates) do + table.insert(candidates, template) + end + + local last_error = nil + while #candidates > 0 do + local index = math.random(#candidates) + local template = candidates[index] + table.remove(candidates, index) + + local ok, rolled = pcall(create_random_item_from_template, template) + if ok and rolled and rolled.inst and rolled.inst.valid then + return rolled + end + + last_error = rolled + end + + error("No Live Items cache templates were available. Last error: " .. tostring(last_error)) +end + +function event_item_click(e) + if e.self:GetID() ~= CACHE_ITEM_ID then + return + end + + local ok, rolled = pcall(create_random_item, e) + if not ok or not rolled then + e.owner:Message(13, "The cache fails to open. The Live Items test templates may need to be seeded.") + if eq and eq.debug then + eq.debug("Live Items test cache error: " .. tostring(rolled), 1) + end + return + end + + e.owner:DeleteItemInInventory(e.slot_id, 1, true) + e.owner:RewardLiveItem(rolled.inst) + e.owner:Message(15, "The cache rolls " .. rolled.name .. " (" .. rolled.tier .. "): " .. rolled.summary) +end diff --git a/features/live-items/quests/global/items/900090.lua b/features/live-items/quests/global/items/900090.lua new file mode 100644 index 0000000000..87dcf3d6f3 --- /dev/null +++ b/features/live-items/quests/global/items/900090.lua @@ -0,0 +1,207 @@ +local COFFER_ITEM_ID = 900090 +local RANDOM_ROLL_COUNT = 15 + +local classes = { + { key = "warrior", name = "Warrior", class_id = 1, base_item_id = 900101 }, + { key = "cleric", name = "Cleric", class_id = 2, base_item_id = 900102 }, + { key = "paladin", name = "Paladin", class_id = 3, base_item_id = 900103 }, + { key = "ranger", name = "Ranger", class_id = 4, base_item_id = 900104 }, + { key = "shadowknight", name = "Shadow Knight", class_id = 5, base_item_id = 900105 }, + { key = "druid", name = "Druid", class_id = 6, base_item_id = 900106 }, + { key = "monk", name = "Monk", class_id = 7, base_item_id = 900107 }, + { key = "bard", name = "Bard", class_id = 8, base_item_id = 900108 }, + { key = "rogue", name = "Rogue", class_id = 9, base_item_id = 900109 }, + { key = "shaman", name = "Shaman", class_id = 10, base_item_id = 900110 }, + { key = "necromancer", name = "Necromancer", class_id = 11, base_item_id = 900111 }, + { key = "wizard", name = "Wizard", class_id = 12, base_item_id = 900112 }, + { key = "magician", name = "Magician", class_id = 13, base_item_id = 900113 }, + { key = "enchanter", name = "Enchanter", class_id = 14, base_item_id = 900114 }, + { key = "beastlord", name = "Beastlord", class_id = 15, base_item_id = 900115 }, + { key = "berserker", name = "Berserker", class_id = 16, base_item_id = 900116 }, +} + +local class_by_key = {} +local class_by_id = {} +for _, class in ipairs(classes) do + class_by_key[class.key] = class + class_by_id[class.class_id] = class +end + +local static_stats = { + { key = "ac", label = "AC", value = 15 }, + { key = "hp", label = "HP", value = 100 }, + { key = "mana", label = "Mana", value = 100 }, +} + +local cleared_template_stats = { + "endur", + "haste", + "attack", + "accuracy", + "avoidance", +} + +local stat_pool = { + { label = "STR", keys = { "str" }, min = 5, max = 15 }, + { label = "DEX", keys = { "dex" }, min = 5, max = 15 }, + { label = "AGI", keys = { "agi" }, min = 5, max = 15 }, + { label = "INT", keys = { "int" }, min = 5, max = 15 }, + { label = "WIS", keys = { "wis" }, min = 5, max = 15 }, + { label = "CON", keys = { "sta" }, min = 5, max = 15 }, + { label = "CHA", keys = { "cha" }, min = 5, max = 15 }, + { label = "Resist", keys = { "mr", "fr", "cr", "pr", "dr" }, min = 5, max = 15 }, +} + +local suffixes = { + "the Ashwake", + "the Riftborn", + "the War-Sung", + "the Spirebound", + "the Sanctum Echo", + "the Harbinger", + "the Bloodfield", + "the Noble Cause", +} + +local function normalize(value) + return (value or ""):lower():gsub("[%s_%-]", "") +end + +local function selected_class(e) + local class_key = normalize(e.self:GetCustomData("live_items_epic_class")) + if class_by_key[class_key] then + return class_by_key[class_key] + end + + local class_name = normalize(e.self:GetCustomData("live_items_epic_class_name")) + if class_by_key[class_name] then + return class_by_key[class_name] + end + + return class_by_id[e.owner:GetClass()] +end + +local function add_roll(rolls, stat, value) + rolls[stat.label] = (rolls[stat.label] or 0) + value + for _, key in ipairs(stat.keys) do + rolls[key] = (rolls[key] or 0) + value + end +end + +local function roll_stats() + local totals = {} + local count = 0 + + for _, stat in ipairs(stat_pool) do + add_roll(totals, stat, math.random(stat.min, stat.max)) + count = count + 1 + end + + for _ = count + 1, RANDOM_ROLL_COUNT do + local stat = stat_pool[math.random(#stat_pool)] + add_roll(totals, stat, math.random(stat.min, stat.max)) + end + + local rolls = {} + for _, stat in ipairs(stat_pool) do + table.insert(rolls, { + keys = stat.keys, + label = stat.label, + value = totals[stat.label] or 0, + }) + end + + return rolls +end + +local function static_summary() + local parts = {} + for _, stat in ipairs(static_stats) do + table.insert(parts, string.format("%s +%d", stat.label, stat.value)) + end + + return table.concat(parts, ", ") +end + +local function roll_summary(rolls) + local parts = {} + for _, roll in ipairs(rolls) do + table.insert(parts, string.format("%s +%d", roll.label, roll.value)) + end + + return table.concat(parts, ", ") +end + +local function create_rolled_epic(e, class) + local suffix = suffixes[math.random(#suffixes)] + local rolls = roll_stats() + local summary = roll_summary(rolls) + local item_name = string.format("%s Epic of %s", class.name, suffix) + local data = { + name = item_name, + lore = "A unique live epic rolled for " .. e.owner:GetCleanName() .. ".", + comment = "Live Items epic instance: " .. static_summary() .. "; random rolls: " .. summary, + } + local modifiers = {} + + for _, stat in ipairs(static_stats) do + data[stat.key] = stat.value + end + + for _, key in ipairs(cleared_template_stats) do + data[key] = 0 + end + + for _, roll in ipairs(rolls) do + for _, key in ipairs(roll.keys) do + modifiers[key] = roll.value + end + end + + local epic = eq.create_live_item({ + item_id = class.base_item_id, + charges = 1, + data = data, + modifiers = modifiers, + custom_data = { + live_items_epic_class = class.key, + live_items_epic_rolls = summary, + live_items_epic_roll_mode = "instance", + }, + }) + + if not epic or not epic.valid then + error("Class epic template " .. tostring(class.base_item_id) .. " was not found.") + end + + return { + inst = epic, + item_name = item_name, + summary = summary, + } +end + +function event_item_click(e) + if e.self:GetID() ~= COFFER_ITEM_ID then + return + end + + local class = selected_class(e) + if not class then + e.owner:Message(13, "The coffer cannot determine which class epic to roll.") + return + end + + local ok, rolled = pcall(create_rolled_epic, e, class) + if not ok or rolled == nil then + e.owner:Message(13, "The coffer sputters. The Item Forge could not roll this epic.") + if eq and eq.debug then + eq.debug("Live Items epic coffer error: " .. tostring(rolled), 1) + end + return + end + + e.owner:DeleteItemInInventory(e.slot_id, 1, true) + e.owner:RewardLiveItem(rolled.inst) + e.owner:Message(15, "The coffer opens into " .. rolled.item_name .. ": " .. static_summary() .. "; " .. rolled.summary) +end diff --git a/features/live-items/quests/global/items/900091.lua b/features/live-items/quests/global/items/900091.lua new file mode 100644 index 0000000000..58325c7f9e --- /dev/null +++ b/features/live-items/quests/global/items/900091.lua @@ -0,0 +1,219 @@ +local CACHE_ITEM_ID = 900091 + +local templates = { + { id = 6002, type = "Weapon", name = "Staff", damage = true }, + { id = 6919, type = "Weapon", name = "Forlorn Bow", damage = true }, + { id = 7007, type = "Weapon", name = "Rusty Dagger", damage = true }, + { id = 10686, type = "Weapon", name = "Warhammer of Ethereal Energy", damage = true }, + { id = 14148, type = "Jewelry", name = "Ornate Ring" }, + { id = 59945, type = "Armor", name = "Kobold Leather Belt" }, + { id = 82924, type = "Armor", name = "Gloomiron Bracer" }, + { id = 82925, type = "Armor", name = "Gloomiron Gauntlets" }, + { id = 82926, type = "Armor", name = "Gloomiron Boots" }, + { id = 82927, type = "Armor", name = "Gloomiron Helm" }, + { id = 82931, type = "Armor", name = "Gloomchain Bracer" }, + { id = 82932, type = "Armor", name = "Gloomchain Gauntlets" }, + { id = 82933, type = "Armor", name = "Gloomchain Boots" }, + { id = 82934, type = "Armor", name = "Gloomchain Coif" }, + { id = 82952, type = "Weapon", name = "Gloomsteel Blade", damage = true }, + { id = 82953, type = "Weapon", name = "Gloomsteel Dagger", damage = true }, + { id = 82954, type = "Weapon", name = "Gloomsteel Hammer", damage = true }, + { id = 82955, type = "Weapon", name = "Gloomsteel Axe", damage = true }, + { id = 82956, type = "Weapon", name = "Gloomsteel Staff", damage = true }, +} + +local tiers = { + { name = "Magic", weight = 65, rolls = 6, min = 2, max = 8 }, + { name = "Rare", weight = 28, rolls = 8, min = 4, max = 12 }, + { name = "Legendary", weight = 7, rolls = 10, min = 7, max = 16 }, +} + +local stat_pool = { + { label = "STR", keys = { "str" } }, + { label = "STA", keys = { "sta" } }, + { label = "DEX", keys = { "dex" } }, + { label = "AGI", keys = { "agi" } }, + { label = "INT", keys = { "int" } }, + { label = "WIS", keys = { "wis" } }, + { label = "CHA", keys = { "cha" } }, + { label = "HP", data = "hp" }, + { label = "Mana", data = "mana" }, + { label = "Endurance", data = "endur" }, + { label = "AC", data = "ac" }, + { label = "Resist", keys = { "mr", "fr", "cr", "pr", "dr" } }, + { label = "Accuracy", keys = { "accuracy" } }, + { label = "Avoidance", keys = { "avoidance" } }, + { label = "Attack", keys = { "attack" } }, +} + +local suffixes = { + "of Embers", + "of Sparks", + "of the Rift", + "of the Noble Cause", + "of the Bloodfield", + "of the Sanctum", + "of Slaughter", +} + +local function roll_tier() + local total = 0 + for _, tier in ipairs(tiers) do + total = total + tier.weight + end + + local roll = math.random(total) + for _, tier in ipairs(tiers) do + if roll <= tier.weight then + return tier + end + roll = roll - tier.weight + end + + return tiers[1] +end + +local function add_roll(totals, stat, value) + totals[stat.label] = (totals[stat.label] or 0) + value + if stat.data then + totals[stat.data] = (totals[stat.data] or 0) + value + end + if stat.keys then + for _, key in ipairs(stat.keys) do + totals[key] = (totals[key] or 0) + value + end + end +end + +local function roll_stats(tier) + local totals = {} + local available = {} + + for _, stat in ipairs(stat_pool) do + table.insert(available, stat) + end + + for _ = 1, tier.rolls do + local source = available + if #source == 0 then + source = stat_pool + end + + local index = math.random(#source) + local stat = source[index] + add_roll(totals, stat, math.random(tier.min, tier.max)) + + if source == available then + table.remove(available, index) + end + end + + return totals +end + +local function summarize(stats) + local order = { "STR", "STA", "DEX", "AGI", "INT", "WIS", "CHA", "HP", "Mana", "Endurance", "AC", "Resist", "Accuracy", "Avoidance", "Attack" } + local parts = {} + for _, label in ipairs(order) do + if stats[label] and stats[label] > 0 then + table.insert(parts, label .. " +" .. stats[label]) + end + end + return table.concat(parts, ", ") +end + +local function create_random_item_from_template(template) + local tier = roll_tier() + local stats = roll_stats(tier) + local name = tier.name .. " " .. template.name .. " " .. suffixes[math.random(#suffixes)] + local summary = summarize(stats) + local data = { + name = name, + lore = "A unique tester roll created by the Live Items test cache.", + comment = "Live Items tester instance roll: " .. summary, + } + local modifiers = {} + + for key, value in pairs(stats) do + if key == "hp" or key == "mana" or key == "endur" or key == "ac" then + data[key] = value + elseif type(key) == "string" and key:lower() == key then + modifiers[key] = value + end + end + + if template.damage then + data.damage = math.random(8, 26) + data.delay = math.random(20, 34) + elseif template.augment then + data.ac = math.max(data.ac or 0, math.random(2, 8)) + else + data.damage = 0 + data.delay = 0 + end + + local item = eq.create_live_item({ + item_id = template.id, + charges = 1, + data = data, + modifiers = modifiers, + custom_data = { + live_items_test_roll = "tutorialb-cache", + live_items_tier = tier.name, + live_items_summary = summary, + }, + }) + + if not item or not item.valid then + error("Template item " .. tostring(template.id) .. " was not found.") + end + + return { + inst = item, + name = name, + tier = tier.name, + summary = summary, + } +end + +local function create_random_item(e) + local candidates = {} + for _, template in ipairs(templates) do + table.insert(candidates, template) + end + + local last_error = nil + while #candidates > 0 do + local index = math.random(#candidates) + local template = candidates[index] + table.remove(candidates, index) + + local ok, rolled = pcall(create_random_item_from_template, template) + if ok and rolled and rolled.inst and rolled.inst.valid then + return rolled + end + + last_error = rolled + end + + error("No Live Items cache templates were available. Last error: " .. tostring(last_error)) +end + +function event_item_click(e) + if e.self:GetID() ~= CACHE_ITEM_ID then + return + end + + local ok, rolled = pcall(create_random_item, e) + if not ok or not rolled then + e.owner:Message(13, "The cache fails to open. The Live Items test templates may need to be seeded.") + if eq and eq.debug then + eq.debug("Live Items test cache error: " .. tostring(rolled), 1) + end + return + end + + e.owner:DeleteItemInInventory(e.slot_id, 1, true) + e.owner:RewardLiveItem(rolled.inst) + e.owner:Message(15, "The cache rolls " .. rolled.name .. " (" .. rolled.tier .. "): " .. rolled.summary) +end diff --git a/features/live-items/quests/tutorialb/900905.lua b/features/live-items/quests/tutorialb/900905.lua new file mode 100644 index 0000000000..c9a631e606 --- /dev/null +++ b/features/live-items/quests/tutorialb/900905.lua @@ -0,0 +1,241 @@ +local CATALYST_ITEM_ID = 199211 +local MAX_TRADE_SLOTS = 4 +local MAX_SOURCE_AUGMENTS = MAX_TRADE_SLOTS - 1 +local MIN_SOURCE_AUGMENTS = 1 + +local stat_fields = { + { key = "ac", label = "AC", get = function(item) return item:AC() end }, + { key = "hp", label = "HP", get = function(item) return item:HP() end }, + { key = "mana", label = "Mana", get = function(item) return item:Mana() end }, + { key = "endur", label = "Endurance", get = function(item) return item:Endur() end }, + { key = "str", label = "STR", get = function(item) return item:AStr() end }, + { key = "sta", label = "STA", get = function(item) return item:ASta() end }, + { key = "dex", label = "DEX", get = function(item) return item:ADex() end }, + { key = "agi", label = "AGI", get = function(item) return item:AAgi() end }, + { key = "int", label = "INT", get = function(item) return item:AInt() end }, + { key = "wis", label = "WIS", get = function(item) return item:AWis() end }, + { key = "cha", label = "CHA", get = function(item) return item:ACha() end }, + { key = "mr", label = "MR", get = function(item) return item:MR() end }, + { key = "fr", label = "FR", get = function(item) return item:FR() end }, + { key = "cr", label = "CR", get = function(item) return item:CR() end }, + { key = "pr", label = "PR", get = function(item) return item:PR() end }, + { key = "dr", label = "DR", get = function(item) return item:DR() end }, + { key = "svcorruption", label = "Corruption", get = function(item) return item:SVCorruption() end }, + { key = "attack", label = "Attack", get = function(item) return item:Attack() end }, + { key = "accuracy", label = "Accuracy", get = function(item) return item:Accuracy() end }, + { key = "avoidance", label = "Avoidance", get = function(item) return item:Avoidance() end }, + { key = "regen", label = "HP Regen", get = function(item) return item:Regen() end }, + { key = "manaregen", label = "Mana Regen", get = function(item) return item:ManaRegen() end }, + { key = "enduranceregen", label = "End Regen", get = function(item) return item:EnduranceRegen() end }, + { key = "damageshield", label = "Damage Shield", get = function(item) return item:DamageShield() end }, + { key = "healamt", label = "Heal Amount", get = function(item) return item:HealAmt() end }, + { key = "spelldmg", label = "Spell Damage", get = function(item) return item:SpellDmg() end }, + { key = "clairvoyance", label = "Clairvoyance", get = function(item) return item:Clairvoyance() end }, + { key = "hstr", label = "Heroic STR", get = function(item) return item:HeroicStr() end }, + { key = "hsta", label = "Heroic STA", get = function(item) return item:HeroicSta() end }, + { key = "hdex", label = "Heroic DEX", get = function(item) return item:HeroicDex() end }, + { key = "hagi", label = "Heroic AGI", get = function(item) return item:HeroicAgi() end }, + { key = "hint", label = "Heroic INT", get = function(item) return item:HeroicInt() end }, + { key = "hwis", label = "Heroic WIS", get = function(item) return item:HeroicWis() end }, + { key = "hcha", label = "Heroic CHA", get = function(item) return item:HeroicCha() end }, + { key = "hmr", label = "Heroic MR", get = function(item) return item:HeroicMR() end }, + { key = "hfr", label = "Heroic FR", get = function(item) return item:HeroicFR() end }, + { key = "hcr", label = "Heroic CR", get = function(item) return item:HeroicCR() end }, + { key = "hdr", label = "Heroic DR", get = function(item) return item:HeroicDR() end }, + { key = "hpr", label = "Heroic PR", get = function(item) return item:HeroicPR() end }, + { key = "hsvcorruption", label = "Heroic Corruption", get = function(item) return item:HeroicSVCorrup() end }, +} + +local function as_number(value) + return tonumber(value) or 0 +end + +local function clean_name(name) + name = tostring(name or "Augment") + name = name:gsub("^Fused%s+", "") + name = name:gsub("%s+", " "):gsub("^%s+", ""):gsub("%s+$", "") + if name == "" then + return "Augment" + end + return name +end + +local function short_name(name) + return string.sub(name, 1, 63) +end + +local function trade_items(trade) + local items = {} + for slot = 1, MAX_TRADE_SLOTS do + local inst = trade["item" .. tostring(slot)] + if inst and inst.valid then + table.insert(items, inst) + end + end + return items +end + +local function summarize(parts) + if #parts <= 8 then + return table.concat(parts, ", ") + end + + local visible = {} + for index = 1, 8 do + table.insert(visible, parts[index]) + end + table.insert(visible, "and " .. tostring(#parts - 8) .. " more") + return table.concat(visible, ", ") +end + +local function split_trade_items(items) + local catalysts = {} + local sources = {} + + for _, inst in ipairs(items) do + if inst:GetID() == CATALYST_ITEM_ID then + table.insert(catalysts, inst) + else + table.insert(sources, inst) + end + end + + return catalysts, sources +end + +local function validate_augments(catalysts, sources) + if #catalysts ~= 1 then + return nil, "I need exactly one Augment Catalyst with the augments you want fused." + end + + if #sources < MIN_SOURCE_AUGMENTS or #sources > MAX_SOURCE_AUGMENTS then + return nil, "Hand me one Augment Catalyst and one to three augment items." + end + + local required = { [tostring(CATALYST_ITEM_ID)] = 1 } + local source_ids = {} + + for _, inst in ipairs(sources) do + local base_id = inst:GetID() + local item = inst:GetItem() + if not item or as_number(item:ID()) == 0 or as_number(item:AugType()) == 0 then + return nil, "Every non-catalyst hand-in must be an augment." + end + + required[tostring(base_id)] = (required[tostring(base_id)] or 0) + 1 + table.insert(source_ids, tostring(base_id)) + end + + return { + required = required, + source_ids = source_ids, + } +end + +local function fuse_augments(sources, source_ids) + local totals = {} + local changed = {} + + for _, field in ipairs(stat_fields) do + local total = 0 + for _, inst in ipairs(sources) do + local item = inst:GetItem() + total = total + as_number(field.get(item)) + end + totals[field.key] = total + end + + local output = sources[1]:Clone() + output:ClearDynamicItemData() + + for _, field in ipairs(stat_fields) do + local total = totals[field.key] + if total ~= 0 then + output:SetDynamicItemData(field.key, total) + table.insert(changed, field.label .. " " .. tostring(total)) + end + end + + if #changed == 0 then + return nil, "Those augments do not have any supported stats to fuse." + end + + local source_name = output:GetCustomData("live_items_aug_fusion_root_name") + if source_name == "" then + local item = sources[1]:GetItem() + source_name = item and clean_name(item:Name()) or "Augment" + end + + local name = short_name("Fused " .. clean_name(source_name)) + output:SetDynamicItemData("name", name) + output:SetCustomData("live_items_aug_fusion", "1") + output:SetCustomData("live_items_aug_fusion_root_name", source_name) + output:SetCustomData("live_items_aug_fusion_component_count", tostring(#sources)) + output:SetCustomData("live_items_aug_fusion_sources", table.concat(source_ids, ",")) + output:RebuildDynamicItemData() + + return { + item = output, + name = name, + changed = changed, + } +end + +function event_say(e) + if e.message:findi("catalyst") then + e.other:SummonItem(CATALYST_ITEM_ID, 1) + e.self:Say("An Augment Catalyst is on your cursor. Hand it back to me with one to three augment items and no coins when you are ready to test fusion.") + return + end + + if not e.message:findi("hail") then + return + end + + e.self:Say( + "Hand me one Augment Catalyst plus one to three augment items and no coins. " .. + "I will return one fused augment that carries the combined supported stats from the augment items. " .. + "Say " .. eq.say_link("catalyst") .. " if you need a catalyst for testing." + ) +end + +function event_trade(e) + local item_lib = require("items") + local items = trade_items(e.trade) + + if #items < 2 or #items > MAX_TRADE_SLOTS or e.trade.platinum > 0 or e.trade.gold > 0 or e.trade.silver > 0 or e.trade.copper > 0 then + e.self:Say("Hand me one Augment Catalyst plus one to three augment items and no coins.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + + local catalysts, sources = split_trade_items(items) + local validation, validation_error = validate_augments(catalysts, sources) + if not validation then + e.self:Say(validation_error) + item_lib.return_items(e.self, e.other, e.trade) + return + end + + local result, fuse_error = fuse_augments(sources, validation.source_ids) + if not result then + e.self:Say(fuse_error) + item_lib.return_items(e.self, e.other, e.trade) + return + end + + if not e.self:CheckHandin(e.other, {}, validation.required, {}) then + e.self:Say("The hand-in did not line up cleanly. Try handing me only the catalyst and augments you want fused.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + + if not e.other:PushItemOnCursor(result.item) then + e.self:Say("The fusion worked, but I could not place the fused augment on your cursor.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + + e.self:Say("Returned " .. result.item:GetItemLink() .. " with fused stats: " .. summarize(result.changed) .. ".") + item_lib.return_items(e.self, e.other, e.trade) +end diff --git a/features/live-items/quests/tutorialb/900906.lua b/features/live-items/quests/tutorialb/900906.lua new file mode 100644 index 0000000000..4f146eb816 --- /dev/null +++ b/features/live-items/quests/tutorialb/900906.lua @@ -0,0 +1,204 @@ +local UPGRADE_AMOUNT = 10 + +local stat_fields = { + { key = "hp", label = "HP", cap = 5000, get = function(item) return item:HP() end }, + { key = "mana", label = "Mana", cap = 5000, get = function(item) return item:Mana() end }, + { key = "endur", label = "Endurance", cap = 5000, get = function(item) return item:Endur() end }, + { key = "ac", label = "AC", cap = 1000, get = function(item) return item:AC() end }, + { key = "damage", label = "Damage", cap = 500, get = function(item) return item:Damage() end }, + { key = "str", label = "STR", cap = 500, get = function(item) return item:AStr() end }, + { key = "sta", label = "STA", cap = 500, get = function(item) return item:ASta() end }, + { key = "dex", label = "DEX", cap = 500, get = function(item) return item:ADex() end }, + { key = "agi", label = "AGI", cap = 500, get = function(item) return item:AAgi() end }, + { key = "int", label = "INT", cap = 500, get = function(item) return item:AInt() end }, + { key = "wis", label = "WIS", cap = 500, get = function(item) return item:AWis() end }, + { key = "cha", label = "CHA", cap = 500, get = function(item) return item:ACha() end }, + { key = "mr", label = "MR", cap = 500, get = function(item) return item:MR() end }, + { key = "fr", label = "FR", cap = 500, get = function(item) return item:FR() end }, + { key = "cr", label = "CR", cap = 500, get = function(item) return item:CR() end }, + { key = "pr", label = "PR", cap = 500, get = function(item) return item:PR() end }, + { key = "dr", label = "DR", cap = 500, get = function(item) return item:DR() end }, + { key = "corruption", label = "Corruption", cap = 500, get = function(item) return item:SVCorruption() end }, + { key = "hstr", label = "Heroic STR", cap = 500, get = function(item) return item:HeroicStr() end }, + { key = "hsta", label = "Heroic STA", cap = 500, get = function(item) return item:HeroicSta() end }, + { key = "hdex", label = "Heroic DEX", cap = 500, get = function(item) return item:HeroicDex() end }, + { key = "hagi", label = "Heroic AGI", cap = 500, get = function(item) return item:HeroicAgi() end }, + { key = "hint", label = "Heroic INT", cap = 500, get = function(item) return item:HeroicInt() end }, + { key = "hwis", label = "Heroic WIS", cap = 500, get = function(item) return item:HeroicWis() end }, + { key = "hcha", label = "Heroic CHA", cap = 500, get = function(item) return item:HeroicCha() end }, + { key = "hmr", label = "Heroic MR", cap = 500, get = function(item) return item:HeroicMR() end }, + { key = "hfr", label = "Heroic FR", cap = 500, get = function(item) return item:HeroicFR() end }, + { key = "hcr", label = "Heroic CR", cap = 500, get = function(item) return item:HeroicCR() end }, + { key = "hpr", label = "Heroic PR", cap = 500, get = function(item) return item:HeroicPR() end }, + { key = "hdr", label = "Heroic DR", cap = 500, get = function(item) return item:HeroicDR() end }, + { key = "hsvcorruption", label = "Heroic Corrup", cap = 500, get = function(item) return item:HeroicSVCorrup() end }, + { key = "attack", label = "Attack", cap = 500, get = function(item) return item:Attack() end }, + { key = "accuracy", label = "Accuracy", cap = 500, get = function(item) return item:Accuracy() end }, + { key = "avoidance", label = "Avoidance", cap = 500, get = function(item) return item:Avoidance() end }, + { key = "combateffects", label = "Combat Effects", cap = 500, get = function(item) return item:CombatEffects() end }, + { key = "shielding", label = "Shielding", cap = 500, get = function(item) return item:Shielding() end }, + { key = "spellshield", label = "Spell Shield", cap = 500, get = function(item) return item:SpellShield() end }, + { key = "dotshielding", label = "DoT Shield", cap = 500, get = function(item) return item:DotShielding() end }, + { key = "stunresist", label = "Stun Resist", cap = 500, get = function(item) return item:StunResist() end }, + { key = "strikethrough", label = "Strikethrough", cap = 500, get = function(item) return item:StrikeThrough() end }, + { key = "regen", label = "HP Regen", cap = 500, get = function(item) return item:Regen() end }, + { key = "manaregen", label = "Mana Regen", cap = 500, get = function(item) return item:ManaRegen() end }, + { key = "enduranceregen", label = "End Regen", cap = 500, get = function(item) return item:EnduranceRegen() end }, + { key = "damageshield", label = "Damage Shield", cap = 500, get = function(item) return item:DamageShield() end }, + { key = "dsmitigation", label = "DS Mitigation", cap = 500, get = function(item) return item:DSMitigation() end }, + { key = "healamt", label = "Heal Amount", cap = 500, get = function(item) return item:HealAmt() end }, + { key = "spelldmg", label = "Spell Damage", cap = 500, get = function(item) return item:SpellDmg() end }, + { key = "clairvoyance", label = "Clairvoyance", cap = 500, get = function(item) return item:Clairvoyance() end }, + { key = "backstabdmg", label = "Backstab Dmg", cap = 500, get = function(item) return item:BackstabDmg() end }, + { key = "haste", label = "Haste", cap = 100, get = function(item) return item:Haste() end }, +} + +local function number(value, default) + local converted = tonumber(value) + if converted == nil then + return default + end + return converted +end + +local function trim_item_name(name) + name = tostring(name or "Live Item") + name = name:gsub("%s+", " "):gsub("^%s+", ""):gsub("%s+$", "") + return string.sub(name, 1, 64) +end + +local function root_name(inst) + local stored = inst:GetCustomData("live_items_original_name") + if stored and stored ~= "" then + return stored + end + + local name = tostring(inst:GetName() or "Live Item") + name = name:gsub("%s%+%d+$", "") + inst:SetCustomData("live_items_original_name", name) + return name +end + +local function summarize(parts) + if #parts <= 8 then + return table.concat(parts, ", ") + end + + local visible = {} + for index = 1, 8 do + table.insert(visible, parts[index]) + end + + table.insert(visible, "and " .. tostring(#parts - 8) .. " more") + return table.concat(visible, ", ") +end + +local function upgrade_instance(inst, amount) + local item = inst:GetItem() + if not item or not item:valid() then + return nil, "The handed-in item could not be inspected." + end + + local rank = number(inst:GetCustomData("live_items_instance_rank"), 0) + 1 + local changed = {} + + for _, field in ipairs(stat_fields) do + local current = number(field.get(item), 0) + if current > 0 then + local next_value = math.min(field.cap, current + amount) + inst:DeleteDynamicItemModifier(field.key) + inst:SetDynamicItemData(field.key, next_value) + table.insert(changed, field.label .. " " .. tostring(current) .. "->" .. tostring(next_value)) + end + end + + if #changed == 0 then + for _, field in ipairs({ + { key = "hp", label = "HP", value = amount }, + { key = "mana", label = "Mana", value = amount }, + { key = "endur", label = "Endurance", value = amount }, + { key = "ac", label = "AC", value = amount }, + }) do + inst:DeleteDynamicItemModifier(field.key) + inst:SetDynamicItemData(field.key, field.value) + table.insert(changed, field.label .. " 0->" .. tostring(field.value)) + end + end + + local name = trim_item_name(root_name(inst) .. " +" .. tostring(rank)) + inst:SetDynamicItemData("name", name) + inst:SetDynamicItemData("comment", "Live Items instance upgrade rank " .. tostring(rank) .. ": " .. summarize(changed)) + inst:SetCustomData("live_items_instance_rank", tostring(rank)) + inst:SetCustomData("live_items_last_instance_upgrade", tostring(os.time())) + inst:RebuildDynamicItemData() + + return { + name = name, + rank = rank, + changed_count = #changed, + summary = summarize(changed), + } +end + +local function trade_items(trade) + local items = {} + for slot = 1, 4 do + local inst = trade["item" .. tostring(slot)] + if inst and inst.valid then + table.insert(items, inst) + end + end + return items +end + +function event_say(e) + if not e.message:findi("hail") then + return + end + + e.self:Say( + "Hand me exactly one item and I will return that same item instance as a +1 version. " .. + "Every supported positive stat it already has gains +" .. tostring(UPGRADE_AMOUNT) .. + ". If it has no supported stats yet, I seed HP, mana, endurance, and AC so the mutation is visible." + ) +end + +function event_trade(e) + local item_lib = require("items") + local items = trade_items(e.trade) + + if #items ~= 1 or e.trade.platinum > 0 or e.trade.gold > 0 or e.trade.silver > 0 or e.trade.copper > 0 then + e.self:Say("Hand me exactly one item and no coins. I need a clean handoff so I can mutate that exact instance.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + + local original = items[1] + local original_id = original:GetID() + local original_restore = original:Clone() + local upgraded = original:Clone() + local result, error_message = upgrade_instance(upgraded, UPGRADE_AMOUNT) + if not result then + e.self:Say(error_message) + item_lib.return_items(e.self, e.other, e.trade) + return + end + + if not e.self:CheckHandin(e.other, {}, { [tostring(original_id)] = 1 }, {}) then + e.self:Say("The hand-in did not line up cleanly. Hand me exactly one item and no coins.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + + if not e.other:PushItemOnCursor(upgraded) then + e.self:Say("The hand-in slipped out of the forge's grasp. I could not place the upgraded item on your cursor, so I returned the original item.") + e.other:PushItemOnCursor(original_restore) + return + end + + e.self:Say( + "Returned " .. upgraded:GetItemLink() .. " at +" .. tostring(result.rank) .. + ". Updated " .. tostring(result.changed_count) .. " fields: " .. result.summary .. "." + ) + item_lib.return_items(e.self, e.other, e.trade) +end diff --git a/features/live-items/quests/tutorialb/zone.lua b/features/live-items/quests/tutorialb/zone.lua new file mode 100644 index 0000000000..0b6be6ce26 --- /dev/null +++ b/features/live-items/quests/tutorialb/zone.lua @@ -0,0 +1,241 @@ +local skipped_npcs = { + [900901] = true, + [900902] = true, + [900903] = true, -- Reserved by the AI dialogue Sage Aurelian testbed NPC. + [900904] = true, + [900905] = true, + [900906] = true, +} + +local seed_marker = "live_items_tutorialb_spawn_loot_seeded" + +local templates = { + { id = 6002, type = "Weapon", name = "Staff", damage = true }, + { id = 6919, type = "Weapon", name = "Forlorn Bow", damage = true }, + { id = 7007, type = "Weapon", name = "Rusty Dagger", damage = true }, + { id = 10686, type = "Weapon", name = "Warhammer of Ethereal Energy", damage = true }, + { id = 14148, type = "Jewelry", name = "Ornate Ring" }, + { id = 59945, type = "Armor", name = "Kobold Leather Belt" }, + { id = 82924, type = "Armor", name = "Gloomiron Bracer" }, + { id = 82925, type = "Armor", name = "Gloomiron Gauntlets" }, + { id = 82926, type = "Armor", name = "Gloomiron Boots" }, + { id = 82927, type = "Armor", name = "Gloomiron Helm" }, + { id = 82931, type = "Armor", name = "Gloomchain Bracer" }, + { id = 82932, type = "Armor", name = "Gloomchain Gauntlets" }, + { id = 82933, type = "Armor", name = "Gloomchain Boots" }, + { id = 82934, type = "Armor", name = "Gloomchain Coif" }, + { id = 82952, type = "Weapon", name = "Gloomsteel Blade", damage = true }, + { id = 82953, type = "Weapon", name = "Gloomsteel Dagger", damage = true }, + { id = 82954, type = "Weapon", name = "Gloomsteel Hammer", damage = true }, + { id = 82955, type = "Weapon", name = "Gloomsteel Axe", damage = true }, + { id = 82956, type = "Weapon", name = "Gloomsteel Staff", damage = true }, +} + +local tiers = { + { name = "Magic", weight = 65, rolls = 6, min = 2, max = 8 }, + { name = "Rare", weight = 28, rolls = 8, min = 4, max = 12 }, + { name = "Legendary", weight = 7, rolls = 10, min = 7, max = 16 }, +} + +local stat_pool = { + { label = "STR", keys = { "str" } }, + { label = "STA", keys = { "sta" } }, + { label = "DEX", keys = { "dex" } }, + { label = "AGI", keys = { "agi" } }, + { label = "INT", keys = { "int" } }, + { label = "WIS", keys = { "wis" } }, + { label = "CHA", keys = { "cha" } }, + { label = "HP", data = "hp" }, + { label = "Mana", data = "mana" }, + { label = "Endurance", data = "endur" }, + { label = "AC", data = "ac" }, + { label = "Resist", keys = { "mr", "fr", "cr", "pr", "dr" } }, + { label = "Accuracy", keys = { "accuracy" } }, + { label = "Avoidance", keys = { "avoidance" } }, + { label = "Attack", keys = { "attack" } }, +} + +local suffixes = { + "of Embers", + "of Sparks", + "of the Rift", + "of the Noble Cause", + "of the Bloodfield", + "of the Sanctum", + "of Slaughter", +} + +local function roll_tier() + local total = 0 + for _, tier in ipairs(tiers) do + total = total + tier.weight + end + + local roll = math.random(total) + for _, tier in ipairs(tiers) do + if roll <= tier.weight then + return tier + end + roll = roll - tier.weight + end + + return tiers[1] +end + +local function add_roll(totals, stat, value) + totals[stat.label] = (totals[stat.label] or 0) + value + if stat.data then + totals[stat.data] = (totals[stat.data] or 0) + value + end + if stat.keys then + for _, key in ipairs(stat.keys) do + totals[key] = (totals[key] or 0) + value + end + end +end + +local function roll_stats(tier) + local totals = {} + local available = {} + + for _, stat in ipairs(stat_pool) do + table.insert(available, stat) + end + + for _ = 1, tier.rolls do + local source = available + if #source == 0 then + source = stat_pool + end + + local index = math.random(#source) + local stat = source[index] + add_roll(totals, stat, math.random(tier.min, tier.max)) + + if source == available then + table.remove(available, index) + end + end + + return totals +end + +local function summarize(stats) + local order = { "STR", "STA", "DEX", "AGI", "INT", "WIS", "CHA", "HP", "Mana", "Endurance", "AC", "Resist", "Accuracy", "Avoidance", "Attack" } + local parts = {} + for _, label in ipairs(order) do + if stats[label] and stats[label] > 0 then + table.insert(parts, label .. " +" .. stats[label]) + end + end + return table.concat(parts, ", ") +end + +local function create_random_item_from_template(template) + local tier = roll_tier() + local stats = roll_stats(tier) + local name = tier.name .. " " .. template.name .. " " .. suffixes[math.random(#suffixes)] + local summary = summarize(stats) + local data = { + name = name, + lore = "A unique tester roll carried by a tutorialb creature.", + comment = "Live Items tester spawn loot roll: " .. summary, + } + local modifiers = {} + + for key, value in pairs(stats) do + if key == "hp" or key == "mana" or key == "endur" or key == "ac" then + data[key] = value + elseif type(key) == "string" and key:lower() == key then + modifiers[key] = value + end + end + + if template.damage then + data.damage = math.random(8, 26) + data.delay = math.random(20, 34) + elseif template.augment then + data.ac = math.max(data.ac or 0, math.random(2, 8)) + else + data.damage = 0 + data.delay = 0 + end + + local item = eq.create_live_item({ + item_id = template.id, + charges = 1, + data = data, + modifiers = modifiers, + custom_data = { + live_items_test_roll = "tutorialb-spawn-loot", + live_items_tier = tier.name, + live_items_summary = summary, + }, + }) + + if not item or not item.valid then + error("Template item " .. tostring(template.id) .. " was not found.") + end + + return item +end + +local function create_random_item() + local candidates = {} + for _, template in ipairs(templates) do + table.insert(candidates, template) + end + + local last_error = nil + while #candidates > 0 do + local index = math.random(#candidates) + local template = candidates[index] + table.remove(candidates, index) + + local ok, item = pcall(create_random_item_from_template, template) + if ok and item and item.valid then + return item + end + + last_error = item + end + + error("No Live Items tutorialb spawn loot templates were available. Last error: " .. tostring(last_error)) +end + +local function seed_npc(npc) + if not npc or not npc.valid then + return + end + + if skipped_npcs[npc:GetNPCTypeID()] then + return + end + + if npc:EntityVariableExists(seed_marker) then + return + end + + local ok, item = pcall(create_random_item) + if ok and item and item.valid then + npc:AddLiveItem(item, false) + npc:SetEntityVariable(seed_marker, "1") + elseif eq and eq.debug then + eq.debug("Live Items tutorialb spawn loot error: " .. tostring(item), 1) + end +end + +local function seed_existing_npcs() + local list = eq.get_entity_list():GetNPCList() + for npc in list.entries do + seed_npc(npc) + end +end + +function event_spawn_zone(e) + seed_npc(e.other) +end + +function event_enter_zone(e) + seed_existing_npcs() +end diff --git a/features/live-items/sql/001_live_items_rules.sql b/features/live-items/sql/001_live_items_rules.sql index ea28cab1b4..d18b1289d0 100644 --- a/features/live-items/sql/001_live_items_rules.sql +++ b/features/live-items/sql/001_live_items_rules.sql @@ -4,8 +4,8 @@ INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Items:LiveItemLoading', 'true', 'Enable live DB item fallback'), -(1, 'Items:LiveItemMinID', '900000', 'First live item ID'), -(1, 'Items:LiveItemMaxID', '999999', 'Last live item ID'), +(1, 'Items:LiveItemMinID', '150000', 'First DB-backed live item ID'), +(1, 'Items:LiveItemMaxID', '199999', 'Last DB-backed live item ID; 950000-999998 is reserved for dynamic item client display IDs'), (1, 'Items:LiveItemPollIntervalSeconds', '1', 'Live item DB poll interval') ON DUPLICATE KEY UPDATE `rule_value` = VALUES(`rule_value`), diff --git a/features/live-items/sql/002_live_items_testbed_seed.sql b/features/live-items/sql/002_live_items_testbed_seed.sql new file mode 100644 index 0000000000..ad17367496 --- /dev/null +++ b/features/live-items/sql/002_live_items_testbed_seed.sql @@ -0,0 +1,60 @@ +-- Public testbed seed content for Live Items / Item Forge. +-- This tester round focuses on direct live loot, the forge NPC, and augment rewards. + +DELETE FROM spawn2 WHERE id = 900900 OR spawngroupID = 900900; +DELETE FROM spawnentry WHERE spawngroupID = 900900 OR npcID = 900900; +DELETE FROM spawngroup WHERE id = 900900; +DELETE FROM npc_types WHERE id = 900900; +DELETE FROM items WHERE id BETWEEN 900010 AND 900016; +DELETE FROM items WHERE id = 900090; +DELETE FROM items WHERE id BETWEEN 900101 AND 900116; + +REPLACE INTO alternate_currency (id, item_id) VALUES +(90, 81436); + +REPLACE INTO items ( + id, minstatus, Name, lore, comment, itemclass, itemtype, classes, races, + norent, nodrop, size, weight, magic, loregroup, maxcharges, price, sellrate, + questitemflag, updated, icon, stackable, stacksize, slots, damage, delay, + hp, mana, ac, augslot1type, augslot1visible, augslot2type, augslot2visible, + augtype, haste +) VALUES +(199091, 0, 'Live Items Test Loot Cache', 'Open this cache to roll a per-instance Item Forge test reward.', 'Seeded by Live Items testbed SQL', 0, 11, 65535, 65535, 255, 0, 1, 1, 1, 0, 0, 0, 1, 1, NOW(), 667, 1, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), +(199201, 0, 'Live Items Test Weapon Template', 'A base template for Live Items tester instance rolls.', 'Seeded by Live Items testbed SQL', 0, 0, 65535, 65535, 255, 0, 3, 8, 1, 0, -1, 0, 1, 1, NOW(), 519, 0, 0, 24576, 8, 24, 20, 20, 5, 7, 1, 7, 1, 0, 0), +(199202, 0, 'Live Items Test Armor Template', 'A base template for Live Items tester instance rolls.', 'Seeded by Live Items testbed SQL', 0, 10, 65535, 65535, 255, 0, 3, 8, 1, 0, -1, 0, 1, 1, NOW(), 538, 0, 0, 131072, 0, 0, 20, 20, 10, 7, 1, 7, 1, 0, 0), +(199203, 0, 'Live Items Test Jewelry Template', 'A base template for Live Items tester instance rolls.', 'Seeded by Live Items testbed SQL', 0, 29, 65535, 65535, 255, 0, 3, 8, 1, 0, -1, 0, 1, 1, NOW(), 674, 0, 0, 98304, 0, 0, 20, 20, 2, 7, 1, 7, 1, 0, 0), +(199204, 0, 'Live Items Test Charm Template', 'A base template for Live Items tester instance rolls.', 'Seeded by Live Items testbed SQL', 0, 52, 65535, 65535, 255, 0, 3, 8, 1, 0, -1, 0, 1, 1, NOW(), 1123, 0, 0, 1, 0, 0, 20, 20, 5, 7, 1, 7, 1, 0, 0), +(199205, 0, 'Live Items Test Shield Template', 'A base template for Live Items tester instance rolls.', 'Seeded by Live Items testbed SQL', 0, 8, 65535, 65535, 255, 0, 3, 8, 1, 0, -1, 0, 1, 1, NOW(), 535, 0, 0, 16384, 0, 0, 20, 20, 15, 7, 1, 7, 1, 0, 0), +(199206, 0, 'Live Items Test Augment Template', 'A base template for Live Items tester instance rolls.', 'Seeded by Live Items testbed SQL', 0, 54, 65535, 65535, 255, 0, 3, 8, 1, 0, -1, 0, 1, 1, NOW(), 646, 0, 0, 0, 0, 0, 10, 10, 3, 0, 0, 0, 0, 7, 0), +(199207, 0, 'Live Items Shardwork Augment Template', 'A base template for Orin shardwork augment rewards.', 'Seeded by Live Items testbed SQL', 0, 54, 65535, 65535, 255, 0, 3, 8, 1, 0, -1, 0, 1, 1, NOW(), 646, 0, 0, 8388607, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483647, 0); + +REPLACE INTO npc_types ( + id, name, lastname, level, race, `class`, bodytype, hp, gender, texture, + size, runspeed, findable, trackable, isquest, show_name, special_abilities, + skip_global_loot +) VALUES +-- 900903 is reserved for the AI dialogue Sage Aurelian testbed NPC. +(900901, 'Vedra_Forgecall', 'Live Items Forge Tester', 70, 1, 1, 1, 100000, 0, 0, 6.0, 1.25, 1, 1, 1, 1, '19,1', 1), +(900902, 'Orin_Augspinner', 'Live Items Augment Tester', 70, 1, 1, 1, 100000, 0, 0, 6.0, 1.25, 1, 1, 1, 1, '19,1', 1), +(900906, 'Mavren_Instancewright', 'Live Items Instance Mutator', 70, 1, 1, 1, 100000, 0, 0, 6.0, 1.25, 1, 1, 1, 1, '19,1', 1), +(900904, 'Talia_Heirloomkeeper', 'Live Items Evolving Tester', 70, 1, 1, 1, 100000, 0, 0, 6.0, 1.25, 1, 1, 1, 1, '19,1', 1); + +REPLACE INTO spawngroup (id, name, spawn_limit) VALUES +(900901, 'live_items_vedra_forgecall', 1), +(900902, 'live_items_orin_augspinner', 1), +(900906, 'live_items_mavren_instancewright', 1), +(900904, 'live_items_talia_heirloomkeeper', 1); + +REPLACE INTO spawnentry (spawngroupID, npcID, chance) VALUES +(900901, 900901, 100), +(900902, 900902, 100), +(900906, 900906, 100), +(900904, 900904, 100); + +REPLACE INTO spawn2 ( + id, spawngroupID, zone, version, x, y, z, heading, respawntime, variance +) VALUES +(900901, 900901, 'tutorialb', 0, -56.0, -80.0, 25.0, 128.0, 300, 0), +(900902, 900902, 'tutorialb', 0, -48.0, -80.0, 25.0, 128.0, 300, 0), +(900906, 900906, 'tutorialb', 0, -40.0, -80.0, 25.0, 128.0, 300, 0), +(900904, 900904, 'tutorialb', 0, -32.0, -80.0, 25.0, 128.0, 300, 0); diff --git a/features/live-items/sql/003_live_items_log_settings.sql b/features/live-items/sql/003_live_items_log_settings.sql new file mode 100644 index 0000000000..5f437aa842 --- /dev/null +++ b/features/live-items/sql/003_live_items_log_settings.sql @@ -0,0 +1,9 @@ +-- Live Items public testbed logging defaults. +-- CombatRecord defaults to GM say output in EQEmu, which is noisy for testers. + +UPDATE logsys_categories +SET log_to_console = 0, + log_to_file = 0, + log_to_gmsay = 0, + log_to_discord = 0 +WHERE log_category_description = 'CombatRecord'; diff --git a/features/live-items/sql/004_augment_fusion_testbed_seed.sql b/features/live-items/sql/004_augment_fusion_testbed_seed.sql new file mode 100644 index 0000000000..39828f46f5 --- /dev/null +++ b/features/live-items/sql/004_augment_fusion_testbed_seed.sql @@ -0,0 +1,52 @@ +-- Testbed seed content for the Live Items augment fusion prototype. +-- This is NPC fusion, not true nested augments. + +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) +VALUES +(1, 'Items:LiveItemLoading', 'true', 'Enable live DB item fallback'), +(1, 'Items:LiveItemMinID', '150000', 'First DB-backed live item ID'), +(1, 'Items:LiveItemMaxID', '199999', 'Last DB-backed live item ID; 950000-999998 is reserved for dynamic item client display IDs'), +(1, 'Items:LiveItemPollIntervalSeconds', '1', 'Live item DB poll interval') +ON DUPLICATE KEY UPDATE +`rule_value` = VALUES(`rule_value`), +`notes` = VALUES(`notes`); + +DELETE FROM spawn2 WHERE id = 900905 OR spawngroupID = 900905; +DELETE FROM spawnentry WHERE spawngroupID = 900905 OR npcID = 900905; +DELETE FROM spawngroup WHERE id = 900905; +DELETE FROM npc_types WHERE id = 900905; +DELETE FROM items WHERE id BETWEEN 199211 AND 199220; + +REPLACE INTO items ( + id, minstatus, Name, lore, comment, itemclass, itemtype, classes, races, + norent, nodrop, size, weight, magic, loregroup, maxcharges, price, sellrate, + questitemflag, updated, icon, stackable, stacksize, slots, + astr, asta, adex, aagi, aint, awis, acha, + hp, mana, endur, ac, mr, fr, cr, dr, pr, svcorruption, + attack, accuracy, avoidance, regen, manaregen, enduranceregen, + healamt, spelldmg, clairvoyance, + augslot1type, augslot1visible, augslot2type, augslot2visible, augtype, augrestrict +) VALUES +(199211, 0, 'Augment Catalyst', 'A catalytic shard used for augment fusion.', 'Seeded by Live Items augment fusion test SQL', 0, 54, 65535, 65535, 255, 0, 1, 1, 1, 0, -1, 0, 1, 1, NOW(), 646, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0), +(199212, 0, 'Fusion Test Tide Shard', 'A prototype augment shard.', 'Seeded by Live Items augment fusion test SQL', 0, 54, 65535, 65535, 255, 0, 1, 1, 1, 0, -1, 0, 1, 1, NOW(), 646, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 25, 0, 0, 0, 0, 5, 0, 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0), +(199213, 0, 'Fusion Test Stone Shard', 'A prototype augment shard.', 'Seeded by Live Items augment fusion test SQL', 0, 54, 65535, 65535, 255, 0, 1, 1, 1, 0, -1, 0, 1, 1, NOW(), 646, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 10, 0, 10, 5, 5, 0, 0, 5, 0, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 7, 0), +(199214, 0, 'Fusion Test Focus Shard', 'A prototype augment shard.', 'Seeded by Live Items augment fusion test SQL', 0, 54, 65535, 65535, 255, 0, 1, 1, 1, 0, -1, 0, 1, 1, NOW(), 646, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 10, 0, 0, 0, 0, 0, 0, 5, 0, 0, 3, 0, 1, 0, 0, 3, 3, 1, 0, 0, 0, 0, 7, 0), +(199220, 0, 'Fusion Test Socket Sash', 'A test item with visible type 7 augment slots.', 'Seeded by Live Items augment fusion test SQL', 0, 10, 65535, 65535, 255, 0, 3, 8, 1, 0, -1, 0, 1, 1, NOW(), 538, 0, 0, 131072, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 1, 7, 1, 0, 0); + +REPLACE INTO npc_types ( + id, name, lastname, level, race, `class`, bodytype, hp, gender, texture, + size, runspeed, findable, trackable, isquest, show_name, special_abilities, + skip_global_loot +) VALUES +(900905, 'Nalyx_Augmentweaver', 'Augment Fusion Prototype', 70, 1, 1, 1, 100000, 0, 0, 6.0, 1.25, 1, 1, 1, 1, '19,1', 1); + +REPLACE INTO spawngroup (id, name, spawn_limit) VALUES +(900905, 'live_items_nalyx_augmentweaver', 1); + +REPLACE INTO spawnentry (spawngroupID, npcID, chance) VALUES +(900905, 900905, 100); + +REPLACE INTO spawn2 ( + id, spawngroupID, zone, version, x, y, z, heading, respawntime, variance +) VALUES +(900905, 900905, 'tutorialb', 0, -24.0, -80.0, 25.0, 128.0, 300, 0); diff --git a/features/live-spells/MANIFEST.md b/features/live-spells/MANIFEST.md index 85c33ac849..4ad9b4d88c 100644 --- a/features/live-spells/MANIFEST.md +++ b/features/live-spells/MANIFEST.md @@ -7,6 +7,7 @@ This manifest lists the files and hook points that make up the standalone Live S - `zone/gm_commands/livespell.cpp` - `zone/live_spell_manager.h` - `docs/live-spells.md` +- `features/live-spells/patcher.yml` ## Existing Server Files To Patch @@ -34,8 +35,26 @@ Optional rules SQL lives in: | File | Purpose | | --- | --- | +| `client_files/native_autoloot/eq-core-dll/bin/dinput8.dll` | Feature-owned client DLL published to the EQ client root by `patcher.yml`. | | `client_files/native_autoloot/ui/EQUI_NativeSpellForgeWnd.xml` | Native SIDL window layout for Spell Forge input. | -| `client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h` | Not included in this proof branch. The current implementation is still shared runtime code and needs a `native-client-base` split. | + +`features/live-spells/patcher.yml` maps client-facing files from this repo into the target EverQuest client folder. It also enables generated `eqhost`, generated `EQUI.xml`, and includes `EQUI_NativeSpellForgeWnd.xml`. + +Do not add files directly to the local EQ client as the source of truth. The feature repo owns the external client payload; the EQ client folder is only a deployment target. + +In `patcher.yml`, `files[].source` is a path inside this repo and `files[].destination` is a path inside the EverQuest client root. Use `generated.eqhost: true` when the patcher should write `eqhost.txt`, `generated.equiXml: true` when native UI XML includes need to be injected, and `generated.equiIncludes` to list custom `EQUI_*.xml` windows explicitly. + +Missing files listed in `patcher.yml` are release blockers for real external syncs. Use `-AllowMissingClientFiles` only for partial local testing. + +Before regenerating the external patch feed, look up the workspace install id in `D:\Codex\Apps\EQEmu-feature-workspaces\installs.json`. It usually matches the feature id, but do not assume that blindly. Then run from the patcher host: + +```powershell +cd D:\Codex\Apps\EQEmu-feature-patcher\features\patcher\eqemupatcher\service +.\New-WorkspacePatcherDeployment.ps1 -Project -BaseUrl http://:8091/patcher/ +.\Test-WorkspacePatcherDeployment.ps1 -Project -BaseUrl http://:8091/patcher/ +``` + +The feed is published at `http://:8091/patcher//`. ## Commands @@ -54,3 +73,5 @@ Optional rules SQL lives in: - `LIVESPELL|upsert|...` The server owns spell generation, scroll creation, and validation. The native window is only an input surface. + +If Live Spells needs native client behavior, transport parsing, slash-command rewriting, or native EQ windows, that client DLL code belongs in this checkout. Do not source this feature's `dinput8.dll` from `EQEmu-native-client-runtime`. diff --git a/features/live-spells/README.md b/features/live-spells/README.md index 695029e51d..9fe691abdd 100644 --- a/features/live-spells/README.md +++ b/features/live-spells/README.md @@ -1,6 +1,6 @@ # Live Spells Feature Pack -Status: `draft`, `shared-runtime`, `proved-build` +Status: `draft`, `feature-dll`, `proved-build` This pack describes the Live Spells system: generated spell definitions, generated scroll items, server-side spell patching, and the native Spell Forge input window. @@ -26,14 +26,14 @@ This pack describes the Live Spells system: generated spell definitions, generat - EQEmu source rebuild. - Blank spell rows in the reserved generated spell range. - `rule_values` rows if the operator wants to override the generated scroll item live range. -- The native client DLL host if the operator wants the in-client Spell Forge window. +- This feature's native client DLL if the operator wants the in-client Spell Forge window. ## Install Outline 1. Apply the source files and hook patches listed in `MANIFEST.md`. 2. Optionally apply `sql/001_live_spell_runtime_rules.sql` to make generated scroll item live lookup explicit. 3. Rebuild `zone` and `world`. -4. Deploy `EQUI_NativeSpellForgeWnd.xml` and include it from the target client's `EQUI.xml`. +4. Add any client-facing files to `patcher.yml`, then regenerate the `live-spells` patch feed. 5. Use `#livespell dialog`, then craft a generated spell scroll. ## Smoke Test @@ -44,6 +44,22 @@ This pack describes the Live Spells system: generated spell definitions, generat 4. Scribe the scroll, memorize the generated spell, then cast it. 5. Restart a zone and confirm `#livespell ready` resyncs persisted generated spells. -## Current Shared-Runtime Caveat +## Client Patch Sync -This branch includes the native Spell Forge XML only. The C++ DLL implementation is still in the lab branch's shared native-client runtime header and should be split into `native-client-base` plus feature-specific native window code. +Client patch syncing is owned by `features/live-spells/patcher.yml`. The manifest maps files from this repo to their destination inside the EverQuest client folder, including this feature's `dinput8.dll` and `EQUI_NativeSpellForgeWnd.xml`. Do not add files directly to the local EQ client as the source of truth; the client folder is only a deployment target. + +In `patcher.yml`, `files[].source` is a path inside this repo and `files[].destination` is a path inside the EverQuest client root. Use `generated.eqhost: true` when the patcher should write `eqhost.txt`, `generated.equiXml: true` when native UI XML includes need to be injected, and `generated.equiIncludes` to list custom `EQUI_*.xml` windows explicitly. + +Before regenerating the external patch feed, look up the workspace install id in `D:\Codex\Apps\EQEmu-feature-workspaces\installs.json`. It usually matches the feature id, but do not assume that blindly. Then run from the patcher host: + +```powershell +cd D:\Codex\Apps\EQEmu-feature-patcher\features\patcher\eqemupatcher\service +.\New-WorkspacePatcherDeployment.ps1 -Project -BaseUrl http://:8091/patcher/ +.\Test-WorkspacePatcherDeployment.ps1 -Project -BaseUrl http://:8091/patcher/ +``` + +The feed is published at `http://:8091/patcher//`. Missing files listed in `patcher.yml` are release blockers for real external syncs; use `-AllowMissingClientFiles` only for partial local testing. + +## Native DLL Ownership + +Live Spells must not depend on `EQEmu-native-client-runtime` for a feature-specific `dinput8.dll`. Native client behavior, transport parsing, slash-command rewriting, and native EQ windows for this feature belong in this checkout and deploy only to `D:\EQClients\EQClient-Live-Spells`. diff --git a/features/live-spells/patcher.yml b/features/live-spells/patcher.yml new file mode 100644 index 0000000000..1eb1e65e1a --- /dev/null +++ b/features/live-spells/patcher.yml @@ -0,0 +1,14 @@ +version: 1 +id: live-spells +label: Live Spells +client: rof +files: + - source: client_files/native_autoloot/eq-core-dll/bin/dinput8.dll + destination: dinput8.dll + - source: client_files/native_autoloot/ui/EQUI_NativeSpellForgeWnd.xml + destination: uifiles/default/EQUI_NativeSpellForgeWnd.xml +generated: + eqhost: true + equiXml: true + equiIncludes: + - EQUI_NativeSpellForgeWnd.xml diff --git a/features/mq-interface/MANIFEST.md b/features/mq-interface/MANIFEST.md new file mode 100644 index 0000000000..3715c23332 --- /dev/null +++ b/features/mq-interface/MANIFEST.md @@ -0,0 +1,65 @@ +# Native Interface Manifest + +Feature id: `mq-interface` + +This manifest tracks the standalone source and client artifacts for the Native +Interface feature. + +## Test Target + +- Server: `D:\EQServers\EQServer-Mq-Interface` +- Client: `D:\EQClients\EQClient-Mq-Interface` +- Database: `eqemu_mq_interface` + +## Source Files + +- `common/item_power.h` +- `common/item_power.cpp` +- `zone/gm_commands/itemscore.cpp` +- `client_files/native_autoloot/eq-core-dll/eq-core-dll-visualstudio2022.sln` +- `client_files/native_autoloot/eq-core-dll/src/eq-core-dll-vs2022.vcxproj` +- `client_files/native_autoloot/eq-core-dll/src/dinput8.def` +- `client_files/native_autoloot/eq-core-dll/src/native_interface.cpp` + +## Built Client Artifact + +- `client_files/native_autoloot/eq-core-dll/bin/dinput8.dll` + +## Client Patcher Feed + +External/test-client sync is controlled by +`features/mq-interface/patcher.yml`. The patcher feed must include every +client-facing artifact required by testers. Missing files are release blockers +for external syncs; `-AllowMissingClientFiles` is only for partial local +testing. + +Do not use files copied directly into a local EQ client as the source of truth. +`source` paths in `patcher.yml` are repository paths, and `destination` paths +are relative to the EverQuest client root. `generated.eqhost`, +`generated.equiXml`, and `generated.equiIncludes` control generated +`eqhost.txt` and native UI include injection. + +When publishing the feed, pass the workspace install id from +`D:\Codex\Apps\EQEmu-feature-workspaces\installs.json` as `-Project`. It +usually matches the feature id, but do not assume that blindly. + +## Behavior + +- Live spawn labels on the native EQ map through a feature-owned map draw hook. +- Advanced native map filters for NPCs, players, corpses, normal labels, con + colors, include/hide text filters, target highlighting, and target line + drawing. +- `/nimap target ` native target selection by spawn label text or + spawn id. +- Additional native item inspection text, including item ids, stat/mask details, + aug slot data, and clicky/proc/worn/focus/scroll spell effect details. +- Gearscore item power scoring, item power database tables, `#itemscore` + operator tools, hidden `ITEMPOWER|set|...` transport, and native ItemDisplay + rendering. +- Additional native spell inspection text when the spell display window exposes + a valid spell id. + +## Schema and Server Runtime + +Custom database update version `1` creates `item_power`, +`item_power_override`, and `item_power_breakdown`. diff --git a/features/mq-interface/README.md b/features/mq-interface/README.md new file mode 100644 index 0000000000..367919da71 --- /dev/null +++ b/features/mq-interface/README.md @@ -0,0 +1,151 @@ +# Native Interface + +Standalone EQEmu feature branch for `mq-interface`. + +## Test Target + +- Server: `D:\EQServers\EQServer-Mq-Interface` +- Client: `D:\EQClients\EQClient-Mq-Interface` +- Database: `eqemu_mq_interface` + +## First Build Loop + +From `D:\Codex\Apps\EQEmu-feature-workspaces`: + +~~~powershell +.\verify-feature.ps1 mq-interface +.\install-server-runtime.ps1 mq-interface +.\install-client-files.ps1 mq-interface +.\run-db-updates.ps1 mq-interface +.\validate-install.ps1 mq-interface +~~~ + +`install-server-runtime.ps1` also refreshes Windows firewall allow rules for the copied server binaries. + +## Client Payload + +The merged Native Interface/Gearscore client payload is `dinput8.dll` only. Map, +ItemDisplay, spell display, and Gearscore text are rendered through native hooks +and inline ItemDisplay STML, not through a custom `EQUI_*.xml` window. + +## Client Patcher Sync + +External/test-client patch syncing is owned by +`features/mq-interface/patcher.yml`. When adding a client-facing artifact, +commit the file in this repo and add a `files` mapping from the repo path to the +destination path inside the EQ client folder. + +Do not treat files copied directly into the local EQ client as the source of +truth. The source of truth is the repo file plus its +`features/mq-interface/patcher.yml` mapping. + +Patcher fields: + +- `source`: path inside this repository. +- `destination`: path inside the EverQuest client root. +- `generated.eqhost`: writes `eqhost.txt`. +- `generated.equiXml`: injects native UI XML includes. +- `generated.equiIncludes`: explicit custom `EQUI_*.xml` windows. + +This feature currently patches: + +- `client_files/native_autoloot/eq-core-dll/bin/dinput8.dll` -> `dinput8.dll` + +The patcher config also generates `eqhost`. Missing files should block external +releases; `-AllowMissingClientFiles` is only for partial local testing. + +When regenerating the external feed, use the workspace install id from +`D:\Codex\Apps\EQEmu-feature-workspaces\installs.json` as `-Project`. It +usually matches the feature id, but do not assume that blindly. For this +checkout, `installs.json` currently lists `mq-interface`. + +Regenerate the external feed on the patcher host: + +~~~powershell +cd D:\Codex\Apps\EQEmu-feature-patcher\features\patcher\eqemupatcher\service +.\New-WorkspacePatcherDeployment.ps1 -Project -BaseUrl http://:8091/patcher/ +.\Test-WorkspacePatcherDeployment.ps1 -Project -BaseUrl http://:8091/patcher/ +~~~ + +Feed URL: `http://:8091/patcher//`. + +## Native Client DLL + +This feature builds its own `dinput8.dll` from: + +- `client_files/native_autoloot/eq-core-dll/eq-core-dll-visualstudio2022.sln` +- `client_files/native_autoloot/eq-core-dll/src/native_interface.cpp` + +Native client behavior: + +- Adds live spawn labels to the EQ map draw pass. NPCs are enabled by default; + players and corpses can be enabled in the client INI. +- Appends a `Native Interface` block to native item inspection windows with item + id, flags, masks, stat details, aug slots, and item spell effect details. +- Adds Gearscore item level/score/role details. This project owns the server + scorer, item power database tables, `#itemscore` command, hidden + `ITEMPOWER|set|...` transport, and native ItemDisplay rendering. +- Appends a `Native Interface` block to native spell inspection windows when the + spell info window exposes a valid spell id through the known client offset. + +Merged Gearscore server behavior: + +- `common/item_power.*` calculates item level, intrinsic score, and role scores. +- Custom DB update version `1` creates `item_power`, `item_power_override`, and + `item_power_breakdown`. +- Item packets emit hidden `ITEMPOWER|set|...` chat transport that the native + DLL consumes before rendering ItemDisplay text. +- `#itemscore init|show|recalc|explain|audit|override|clearoverride|view` + provides operator tools for scoring and inspection. + +Optional client config lives beside `eqgame.exe`: + +~~~ini +[Map] +Enabled=1 +ShowNPCs=1 +ShowPlayers=0 +ShowCorpses=0 +ChainEQLabels=1 +UseConColor=1 +ShowTarget=1 +TargetLine=1 +MaxLabels=0 +RefreshMs=1000 +NameFilter= +HideFilter= + +[Inspect] +Items=1 +Spells=1 +~~~ + +Diagnostics are written to `native_interface.log` in the client folder. + +Useful local commands: + +- `/nimap status` +- `/nativeinterfacemap status` +- `/nimap on` +- `/nimap off` +- `/nimap npcs on|off` +- `/nimap players on|off` +- `/nimap corpses on|off` +- `/nimap con on|off` +- `/nimap labels on|off` +- `/nimap filter |clear` +- `/nimap hide |clear` +- `/nimap target |clear` +- `/nimap targetline on|off` +- `/mapfilter NPC|PC|Corpse|Target|TargetLine|NormalLabels|NPCConColor on|off` +- `/ni status` +- `/nativeinterface status` + +`MaxLabels=0` means no display cap; the DLL still detects cycles in the +client's spawn linked list to avoid spinning forever on corrupt data. + +## Development Notes + +Reference code was pulled locally under `.reference/` for research only. The +implementation here is a feature-owned native DLL and should remain isolated to +`D:\EQClients\EQClient-Mq-Interface` during install/testing. diff --git a/features/mq-interface/patcher.yml b/features/mq-interface/patcher.yml new file mode 100644 index 0000000000..f2ed0c199b --- /dev/null +++ b/features/mq-interface/patcher.yml @@ -0,0 +1,9 @@ +version: 1 +id: mq-interface +label: Native Interface +client: rof +files: + - source: client_files/native_autoloot/eq-core-dll/bin/dinput8.dll + destination: dinput8.dll +generated: + eqhost: true diff --git a/features/multiclass/MANIFEST.md b/features/multiclass/MANIFEST.md new file mode 100644 index 0000000000..80a8a4f1c0 --- /dev/null +++ b/features/multiclass/MANIFEST.md @@ -0,0 +1,299 @@ +# Multiclass Manifest + +Feature id: `multiclass` + +This manifest lists the files and hook points that make up the standalone +Multiclass feature slice. + +## Added Server Files + +- `zone/multiclass_manager.cpp` +- `zone/multiclass_manager.h` +- `zone/gm_commands/multiclass.cpp` +- `zone/gm_commands/multiclass_ui.cpp` + +## Existing Server Files To Patch + +| File | Purpose | +| --- | --- | +| `common/database/database_update_manifest_custom.h` | Add the custom Multiclass schema migration. | +| `common/repositories/skill_caps_repository.h` | Add Multiclass client export support that emits highest-known skill caps for every player class. | +| `common/version.h` | Set `CUSTOM_BINARY_DATABASE_VERSION` for the custom migration. | +| `client_files/export/main.cpp` | Use the Multiclass-aware SkillCaps export for this standalone feature checkout. | +| `zone/CMakeLists.txt` | Build the Multiclass manager and command source. | +| `zone/aa.cpp` | Apply Multiclass shifted class masks to AA send/use checks and guard learned-AA packet writes against the fixed client profile array. | +| `zone/attack.cpp` | Apply Multiclass item usability to client weapon damage class validation and route class-specific combat skill bonuses through trio membership. | +| `zone/bonuses.cpp` | Apply Multiclass item usability to item bonus eligibility and apply locked-trio resonance passives during client bonus calculation. | +| `zone/client.cpp` | Apply Multiclass skill caps/training, class-derived innate abilities, tracking capability, max-skill handling, spell/disc auto-learn lists, native spellbook level refresh before bulk-scribe client packets, and secondary roster pets in generic spell-apply lists. | +| `zone/client_mods.cpp` | Apply Multiclass caster mana source and bard instrument logic. | +| `zone/client_packet.cpp` | Apply Multiclass bard item-click, rogue utility-skill actions, and item usability checks, seed eligible locked-trio skills on login/zone completion, send the caster-capable presentation class in the outbound player profile, and expand item preview/adventure merchant class-mask presentation. | +| `zone/client_process.cpp` | Apply Multiclass spell memorization, scroll scribing, skill trainer access, merchant class masks, bulk inventory item-packet class-mask presentation, and server-side Bard Melody pulses. | +| `zone/command.cpp` | Register `#multiclass`, `#multiclassui`, and `#mc`. | +| `zone/command.h` | Declare the command handlers. | +| `zone/effects.cpp` | Apply Multiclass spell level, scroll/tome, discipline, and spell modifier checks. | +| `zone/exp.cpp` | Seed newly eligible Multiclass class skills after level changes. | +| `zone/guild_mgr.cpp` | Apply Multiclass class masks to guild-bank usability display, including bulk list entries. | +| `zone/groups.cpp` | Include secondary Multiclass roster pets in group pet-affinity spell fanout and pet heal-count checks. | +| `zone/inventory.cpp` | Apply Multiclass item usability to direct equipment swaps and loot auto-equip, and expand per-client item-packet class masks for trio-usable items. | +| `zone/mob.cpp` | Apply Multiclass INT/WIS caster identity and keep Multiclass roster pets owner-valid even when they are not the stock active pet. | +| `zone/pets.cpp` | Allow eligible Multiclass profiles to keep up to three owned full pets without rotating `SetPet()`. | +| `zone/raids.cpp` | Include secondary Multiclass roster pets in raid-group pet-affinity spell fanout. | +| `zone/spell_effects.cpp` | Let eligible Multiclass pet trios pass the summon-spell one-pet guard until their roster limit is reached, and apply Multiclass trio masks to player-facing class cast restrictions. | +| `zone/special_attacks.cpp` | Apply Multiclass class membership to combat ability branches such as Backstab, Frenzy, Kick, Monk attacks, and Bard casting exceptions. | +| `zone/spells.cpp` | Apply Multiclass spell levels to fizzle and spell-group cache logic, item-click class restrictions, refresh native spellbook levels after scroll scribing, and include secondary roster pets in direct group-target pet-affinity casts. | +| `zone/worldserver.cpp` | Include secondary Multiclass roster pets in cross-zone and world-wide spell apply/fade pet paths. | +| `zone/zonedb.cpp` | Persist secondary Multiclass roster pets in reserved stock pet slots, save/load supplemental pet command state, and reload pets after the normal primary pet. | +| `zone/zonedb.h` | Expose the Multiclass secondary pet and pet-state reload hooks. | + +## Database Objects + +Custom migration version 1 creates the THJ-style fixed trio profile schema: + +- `custom_multiclass_profiles` +- `custom_multiclass_profile_audit` + +Custom migration version 2 upgrades the earlier first-slice active-class +scaffold, if present, into `custom_multiclass_profiles` and removes the old +active-track tables. + +Custom migration version 3 creates supplemental pet command-state storage: + +- `custom_multiclass_pet_state` + +Custom migration version 4 creates Bard Melody slot storage: + +- `custom_multiclass_bard_melody` + +Reference SQL lives in: + +- `features/multiclass/sql/001_multiclass_schema.sql` + +## Added Feature Docs + +- `features/multiclass/TRIO_RESONANCE.md` + +## Native Client Assets + +| File | Purpose | +| --- | --- | +| `client_files/native_autoloot/ui/EQUI_NativeMulticlassWnd.xml` | Native SIDL window shell for Multiclass, Multiclass Pets, Bard Melody, and Multiclass Discs, including resize anchors, the stock active-discipline gauge mirror, and hotkey controls for sizable native windows. | +| `client_files/native_autoloot/eq-core-dll/eq-core-dll-visualstudio2022.sln` | Feature-local native DLL solution used by the Multiclass build. | +| `client_files/native_autoloot/eq-core-dll/src/eq-core-dll-vs2022.vcxproj` | Feature-local native DLL project file. | +| `client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h` | Feature-local native runtime implementation for Multiclass windows, transport parsing, command rewrites, spellbook patching, server-authored vitals/class presentation, player mana-HUD and spell-gem presentation, pet UI, Bard Melody UI, discipline UI, discipline reuse countdown display, discipline hotkey creation, and session cleanup. | +| `client_files/native_autoloot/eq-core-dll/bin/dinput8.dll` | Built feature-local runtime DLL installed into the Multiclass client. | +| `features/multiclass/patcher.yml` | Project-owned external/test-client patcher feed declaration. Maps feature-owned client files into the EverQuest client folder and requests generated `eqhost`, generated `EQUI.xml`, and the native XML include. | +| Target client `uifiles/default/EQUI.xml` | Must include `EQUI_NativeMulticlassWnd.xml` so the EQ client loads the window definition. | + +Client patch syncing for external testers is owned by +`features/multiclass/patcher.yml`. Add any client-facing DLL, XML, config, +status, patch note, zone asset, or other test-client file there with a +repo-relative `source` and client-relative `destination`. Do not use the local +EQ client folder as the source of truth. For real external syncs, missing files +are release blockers; `-AllowMissingClientFiles` is only for partial local +testing. Patcher deployment `-Project` values come from +`D:\Codex\Apps\EQEmu-feature-workspaces\installs.json` install ids. + +## Admin / Native Bridge Commands + +- `#multiclass status` +- `#multiclass set ` +- `#multiclass diag` +- `#multiclass diag skills` +- `#multiclass diag spells` +- `#multiclass diag discs` +- `#multiclass diag aa` + - reports trio AA mask, visible AA definition count, learned profile entries, + first-rank purchase candidates, grant-only entries, and learned-AA packet + guard usage +- `#multiclass diag melody` +- `#multiclass diag bonuses` +- `#multiclass diag pets` +- `#multiclass diag items` +- `#multiclass native` +- `#multiclass help` +- `#multiclass reweave grant ` +- `#multiclass reweave ` +- `#multiclassui status` +- `#multiclassui refresh` +- `#multiclassui open` +- `#multiclassui choose ` +- `#mc status` +- `#mc refresh` +- `#mc open` +- `#mc choose ` +- `#mc pets` +- `#mc pet refresh` +- `#mc pet focus ` +- `#mc pet attack all` +- `#mc pet back all` +- `#mc pet follow all` +- `#mc pet guard all` +- `#mc pet health all` +- `#mc pet taunt` +- `#mc pet hold` +- `#mc pet spellhold` +- `#mc pet dismiss` +- `#mc melody open` +- `#mc melody refresh` +- `#mc melody set ` +- `#mc melody clear [slot]` +- `#mc disc open` +- `#mc disc refresh` +- `#mc disc use ` +- `#mc reweave ` + +`#multiclass` remains GMAdmin-only. `#multiclassui` and its shorter `#mc` alias +are Player-accessible so the native DLL can request snapshots and submit +server-authoritative trio choices. The native DLL also rewrites `/mc`, +`/multiclass`, and `/multiclassui` into `#mc` bridge calls, making `/mc` the +recognizable in-game reopen shortcut while keeping selection state on the +server. It also rewrites `/mcpets`, `/multiclasspets`, and `/petui` into the +standalone Multiclass pet console bridge. `/disc`, `/discs`, `/discipline`, +`/discwindow`, `/combatability`, `/combatabilities`, and `/mc disc` rewrite into +the native Multiclass discipline bridge so caster-root melee trios do not hit +the stock client class gate. +`#mc reweave ` is the first player-safe bridge for rare +one-slot reweaves. It consumes a granted reweave, requires a locked trio, and +is restricted to cities or bind-safe sanctuaries. Slot 1 remains tied to the +base character identity for now. + +## Native Transport + +- `MULTICLASS|profile|...` +- `MULTICLASS|vitals|...` +- `MULTICLASS|trio|...` +- `MULTICLASS|skills|summary=...|unlocked=...` +- `MULTICLASS|bonuses|summary=...` +- `MULTICLASS|selection|...` +- `MULTICLASS|spell_levels|begin` +- `MULTICLASS|spell_level|id=...|level=...|presentation=...` +- `MULTICLASS|spell_levels|end|count=...` +- `MULTICLASS|pet_roster|...` +- `MULTICLASS|pet|...` +- `MULTICLASS|melody|...` +- `MULTICLASS|melody_slot|...` +- `MULTICLASS|melody_song|...` +- `MULTICLASS|melody_songs|end|count=...` +- `MULTICLASS|disciplines|clear` +- `MULTICLASS|disciplines|summary|...` +- `MULTICLASS|discipline|...` with `timer` and `total` reuse fields +- `MULTICLASS|disciplines|end|count=...` +- `MULTICLASS|window|clear` +- `MULTICLASS|window|show` +- `MULTICLASS|pet_window|show` +- `MULTICLASS|melody_window|show` +- `MULTICLASS|discipline_window|show` + +The server owns all future validation and state mutation. The native window is +only a display/input surface. This branch owns the native runtime code for +these Multiclass behaviors instead of depending on the shared +`native-client-runtime` checkout. The runtime parses these transport lines, +opens `NativeMulticlassWnd` for trio identity/selection, opens the separate +`NativeMulticlassPetWnd` for pet roster controls, refreshes the displayed trio, +opens the separate `NativeMulticlassMelodyWnd` for Bard Melody controls, +opens the separate `NativeMulticlassDisciplineWnd` for learned discipline use, +reuse countdown display, active-effect gauge mirroring, and hotkey creation, +uses compact slot selectors for unlocked profiles, renders server-owned +role/resonance notes, skill-unlock summaries, and resonance-bonus summaries, +patches the client spellbook and spell-gem right-click menu required-level display for +off-presentation-class trio spells using both spell-id and normalized-name +lookup keys, consumes server-authored +vitals/classmask snapshots, patches local mana/class presentation data for +melee-base caster trios, keeps the stock Player Window mana gauge/labels visible +for mana-class presentations, retries showing the stock spell-gem window after +profile/vitals refreshes, destroys stale native windows during client UI +reset/logout, and sends locked-trio choices back through `#mc choose`. Pet buttons +send targeted roster commands through `#mc pet` and bridge +through stock EQEmu pet command handling where possible so normal pet response +text and command-state updates are preserved. The slim pet console shows pet +name, mode, HP/MP, and taunt/hold/no-cast flags; the stale target column was +removed because it only updates on explicit roster refresh. The pet console is +resizable and is released with the other Multiclass native windows during client +UI reset/logout. +It also rewrites `/mcmelody`, `/multiclassmelody`, `/melodyui`, and `/mc +melody` into the Bard Melody bridge. +It rewrites `/disc` and related discipline shortcuts into `#mc disc`. + +## Current Capability Hooks + +- Trio class slots and class masks live in `zone/multiclass_manager.*`. +- Locked trio names, resonance keys, level 10 through 60 passive tiers, and + rare one-slot reweave rules live in `zone/multiclass_manager.*`. +- Mana/caster identity uses selected caster slots while preserving the base + profile class as the client identity. +- Spell, discipline, scroll, tome, fizzle, skill, combat ability, item equip, + item-click, guild-bank, merchant, loot auto-equip, weapon damage, class cast + restrictions, and AA class + gates have first-pass Multiclass routing. Outgoing item packets, item previews, + adventure merchant lists, and the login bulk-inventory snapshot clone or + expand trio-usable item class masks to the character's trio, keeping global + item data unchanged while reducing client-side drag/drop and tooltip mismatch. + Native snapshots also send the best trio level for scribed off-class spells + so the client spellbook does not show level 255 for usable Necromancer, + Beastlord, or other non-presentation spells. The native runtime rewrites + spell-gem context menu labels from the same patch rows, keyed by spell id when + the context menu exposes it and by normalized spell name as fallback. Bulk + spell scribing now sends those native level rows before the client receives + the scribe packets so newly cached spell-gem context menus do not retain + level 255 until zoning. +- The feature-local client export utility emits `SkillCaps.txt` with the + highest known cap for each skill/level across all player classes, then relies + on the server capability layer for authoritative per-trio skill enforcement. +- Locked profiles auto-seed eligible non-tradeskill, non-specialization class + skills to `1` on trio lock, login/zone completion, level-up, and native + refresh once the character meets the best trio train level. This unlocks + off-base class tools without maxing skills or bypassing tradeskill/content + progression. +- Eligible pet-heavy Multiclass profiles can keep up to three active owned pets + in-zone. Summon spell effects now defer the stock one-pet denial when the + Multiclass roster still has capacity, then `zone/pets.cpp` registers the new + owned pet without rotating away the existing focused pet. `zone/mob.cpp` + treats those roster pets as owner-valid even when they are not the stock + `client->petid`, preventing older roster pets from being cleared as + ownerless. Secondary roster pets now save into reserved `character_pet_*` + slots `10..12`, preserving stock pet HP, mana, buffs, worn equipment, size, + petpower, and taunt state across zoning and logout/login. Supplemental pet + command metadata lives in `custom_multiclass_pet_state`. Group/raid + pet-affinity spell fanout, generic spell-apply lists, and cross-zone/world-wide + spell apply/fade pet paths include secondary roster pets wherever stock logic + already allows pets. The separate native pet console displays roster rows, + native focus, HP/mana, taunt, hold, and no-cast state, with + broadcast/focused command routing. +- Bard Melody uses `custom_multiclass_bard_melody`, `#mc melody`, and + `NativeMulticlassMelodyWnd` to pulse up to four selected scribed Bard songs + without consuming spell gems. Slot changes preserve the active pulse cadence + instead of refreshing the whole stack immediately. When Melody has active + slots, Bard songs cast from normal spell gems are on-demand casts and do not + start the stock auto-repeat loop. First pass blocks + charm/fear/mez/stun/root/lull songs from Melody until they are explicitly + validated. +- Caster-root melee trios use `#mc disc`, `/disc` rewrites, and + `NativeMulticlassDisciplineWnd` to list and activate learned disciplines + through server-authoritative Multiclass discipline checks when the stock + combat window refuses the presentation class. +- `/mc` open/refresh and trio lock resend the stock AA table with the trio AA + mask, giving the client another chance to display off-base class AA entries + without a camp cycle. +- Locked profiles receive server-side resonance bonuses every ten levels from + 10 through 60. Exact trio identities get named tracks and accent bonuses; + every other trio falls back to role-based tracks. Native snapshots send the + current/next tier summary through `MULTICLASS|bonuses|...`. +- Rare reweaves have initial server-side scaffolding. Admins can grant + reweaves, and players can spend one through the native bridge to change slot + 2 or 3 in a city or bind-safe sanctuary. + +## Living Design Notes + +- `docs/multiclass.md` records the current source-dive facts, fixed-trio + decisions, capability-layer direction, multiple-pet policy, implementation + slices, and open client proof points. +- `features/multiclass/VALIDATION.md` records the manual trio matrix and + per-trio proof checklist for the next test pass. +- `features/multiclass/TRIO_RESONANCE.md` records exact trio names, fallback + archetypes, and level 10 through 60 resonance tier names. + +## Test Target + +- Server: `D:\EQServers\EQServer-Multiclass` +- Client: `D:\EQClients\EQClient-Multiclass` +- Database: `eqemu_multiclass` diff --git a/features/multiclass/README.md b/features/multiclass/README.md new file mode 100644 index 0000000000..43888b1b94 --- /dev/null +++ b/features/multiclass/README.md @@ -0,0 +1,264 @@ +# Multiclass + +Standalone EQEmu feature branch for `multiclass`. + +## Current Slice + +This branch owns the server-side Multiclass feature boundary, the native window +XML, and the feature-local native DLL runtime code needed by Multiclass. The +current buildable slice stores one fixed trio profile per character, includes +GMAdmin-only test/profile diagnostics, exposes a player-safe native UI bridge, +and routes the first core capability gates through the Multiclass manager: +mana, caster identity, spells, disciplines, skills, item class masks, and AA +class masks. Direct equipment moves now validate wearable item class/race +against the trio mask, so a Beastlord / Magician / Necromancer can wear an item +that allows Magician or Necromancer even if Beastlord is absent, and weapon +damage/click-item checks now use the same trio eligibility. Spell/AA cast +restriction checks that are explicitly class-based now read the player's trio +mask, while NPCs and other non-player actors keep stock single-class handling. +`/mc` open/refresh resends the stock AA table with the trio AA mask so off-base +class AA entries can appear without camping after profile changes. +Combat ability +branches such as Backstab, Frenzy, Kick, Monk attacks, and Rogue utility actions +now read trio class membership instead of only the base class. Locked trios also +auto-seed eligible non-tradeskill, non-specialization class skills to `1` on +login/zone completion, level-up, trio lock, and native refresh once the +character meets the best trio train level, so off-base tools like Backstab, +Frenzy, Meditate, and instrument skills become usable without manual GM skill +patches. Item packets, previews, adventure merchant lists, and the login +bulk-inventory snapshot also clone or expand trio-usable item class masks to the +full trio so the stock client has a better chance to show and drag the item as +usable. + +Native UI is the intended first player flow. Multiple-pet ownership is +implemented as a server-owned roster for eligible pet-heavy trios. Pet summon +spell effects now allow eligible locked trios to keep summoning until the +Multiclass roster cap is reached, while non-Multiclass characters keep the stock +one-pet limit. Roster pets remain owner-valid even when they are not the stock +active pet pointer, so later summons do not orphan or replace earlier pets. +Secondary roster pets persist through zoning and logout/login using reserved +`character_pet_*` slots `10..12`; the stock current pet and suspended minion +slots remain unchanged. A small Multiclass pet-state table preserves command +state that does not live cleanly in stock pet rows, including focus, hold, +spell-hold, pet order, and guard point. Group and raid pet-affinity spell fanout now includes +secondary non-charmed roster pets wherever stock logic already allows pets. +Cross-zone and world-wide spell apply/fade helpers also include secondary +Multiclass roster pets when the stock server rule allows spells on pets. + +Bard trios now have an early server-authoritative Melody surface. The separate +native Melody window lists scribed Bard songs, lets the player assign up to +four slots, stores those slots in the database, and pulses selected songs from +the server without occupying the normal spell gems. Slot changes do not reset +the server pulse timer; the new mix takes effect on the next scheduled pulse. +When Melody has active slots, Bard songs cast from normal spell gems are +treated as on-demand casts instead of starting the stock auto-repeat loop. +Control songs such as charm, fear, mez, stun, root, and lull are intentionally +blocked from Melody in this first pass until they can be tested safely. + +Caster-root melee trios now have a native discipline bridge. `/disc`, `/discs`, +and `/mc disc` open `NativeMulticlassDisciplineWnd`; using a row submits through +`#mc disc use ` so Wizard-root Rogue/Berserker-style builds avoid the +stock client class rejection and still execute disciplines server-side through +the existing Multiclass capability checks. The window mirrors the stock active +discipline gauge, ticks selected reuse timers locally from server transport +metadata, and can create `/mc disc use ` hotkeys for learned discs. + +## Test Target + +- Server: `D:\EQServers\EQServer-Multiclass` +- Client: `D:\EQClients\EQClient-Multiclass` +- Database: `eqemu_multiclass` + +## Admin / Native Bridge Commands + +- `#multiclass status` +- `#multiclass set ` +- `#multiclass diag` +- `#multiclass diag skills` +- `#multiclass diag spells` +- `#multiclass diag discs` +- `#multiclass diag aa` reports trio AA mask, visible AA definition count, + learned profile entries, first-rank purchase candidates, grant-only entries, + and the learned-AA packet guard. +- `#multiclass diag melody` +- `#multiclass diag bonuses` +- `#multiclass diag pets` +- `#multiclass diag items` +- `#multiclass native` +- `#multiclass help` +- `#multiclass reweave grant ` +- `#multiclass reweave ` +- `#multiclassui status` +- `#multiclassui refresh` +- `#multiclassui open` +- `#multiclassui choose ` +- `#mc status` +- `#mc refresh` +- `#mc open` +- `#mc choose ` +- `#mc pets` +- `#mc pet refresh` +- `#mc pet focus ` +- `#mc pet attack all` +- `#mc pet back all` +- `#mc pet follow all` +- `#mc pet guard all` +- `#mc pet health all` +- `#mc pet taunt` +- `#mc pet hold` +- `#mc pet spellhold` +- `#mc pet dismiss` +- `#mc melody open` +- `#mc melody refresh` +- `#mc melody set ` +- `#mc melody clear [slot]` +- `#mc disc open` +- `#mc disc refresh` +- `#mc disc use ` +- `#mc reweave ` + +Players should not need a typed command loop. `#multiclassui` exists as the +explicit bridge name, while `#mc` is the shorter player-safe alias. The native +DLL rewrites `/mc`, `/multiclass`, and `/multiclassui` into `#mc` bridge calls +so `/mc` can reopen or refresh the window in a recognizable way. It also +rewrites `/mcpets`, `/multiclasspets`, and `/petui` into the standalone pet +console bridge, and `/mcmelody`, `/multiclassmelody`, `/melodyui`, or +`/mc melody` into the Bard Melody bridge. `/disc`, `/discs`, `/discipline`, +`/discwindow`, `/combatability`, and `/mc disc` now route to the native +Multiclass discipline bridge instead of the stock client class-gated command. + +For melee-base caster trios, the server now sends vitals/classmask snapshots and +the native DLL applies the server-approved presentation class and mana values to +local client presentation structures. It also keeps the stock Player Window mana +gauge visible when the presentation class is a mana class and repeatedly nudges +the stock spell-gem window visible after profile/vitals refreshes. The server +remains authoritative for actual mana values; this is a HUD presentation bridge +for characters created as pure melee. + +Locked trios now receive server-side resonance bonuses every ten levels from +10 through 60. The bonuses are applied during normal client bonus calculation +and are shown in the main native Multiclass window through +`MULTICLASS|bonuses|...`. Exact identities such as Grand Menagerie, Warbound +Arcanum, Spellblade Compact, Radiant Hymn, Velvet Conspiracy, Arcane Duelist +Pact, Verdant Synod, Aegis Covenant, Dirge of the Grave, and Wildcall Pact have +named tier tracks; other combinations fall back to role-based tracks. + +Rare reweaves now have server-side scaffolding. Admins can grant reweaves, and +the native bridge can spend one reweave to change slot 2 or 3 in a city or +bind-safe sanctuary. Slot 1 remains tied to the character's base identity until +a deeper client-presentation strategy is proven. + +## Database + +Custom migration version 1 creates the initial trio profile tables: + +- `custom_multiclass_profiles` +- `custom_multiclass_profile_audit` + +Custom migration version 2 upgrades the earlier active-track scaffold, if +present, into the trio profile schema. + +Custom migration version 3 creates `custom_multiclass_pet_state` for pet command +metadata that supplements stock `character_pet_*` persistence. + +Custom migration version 4 creates `custom_multiclass_bard_melody` for the +native Melody slot assignments. + +Reference SQL lives in `features/multiclass/sql/001_multiclass_schema.sql`. + +## Native Client Assets + +- `client_files/native_autoloot/ui/EQUI_NativeMulticlassWnd.xml` +- `client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h` +- `client_files/native_autoloot/eq-core-dll/bin/dinput8.dll` +- `features/multiclass/patcher.yml` + +The runtime client DLL is feature-owned here. Multiclass does not rely on the +shared `native-client-runtime` checkout for its DLL-side `NativeMulticlassWnd`, +`NativeMulticlassPetWnd`, `MULTICLASS|...` parser, slash-command rewrites, +spellbook level patching, or spell-gem context-menu label hook. + +The native runtime now parses `MULTICLASS|...` transport lines, opens +`NativeMulticlassWnd` on profile snapshots, displays the trio and presentation +class, lets an unlocked profile choose second and third classes with compact +slot selectors, renders server-owned trio role/resonance notes plus compact +skill-unlock and resonance-bonus summaries, and patches the local spellbook and spell-gem right-click +menu required-level display for scribed off-class trio spells using spell-id and +normalized-name lookup keys. It also consumes server-authored +`MULTICLASS|vitals|...` rows, keeps the stock Player Window mana gauge visible +for mana-class presentations, and retries showing the stock spell-gem window for +caster-capable trios. It hooks the client UI reset path, destroys Multiclass +runtime windows, and clears transient transport state when the client leaves the +in-game session so stale native windows do not remain over character select or +survive into the next login. Pet control is split into a separate +`NativeMulticlassPetWnd`, opened from the main window or `/mcpets`, with up to +three compact pet rows. The pet console stays intentionally slim: pet name, +mode, HP/MP, and taunt/hold/no-cast flags, with no stale target column. Its +refresh, pet focus, broadcast pet commands, and focused pet toggles submit +through the `#mc` bridge alias. Native pet buttons target the selected roster +row directly and bridge through stock EQEmu pet command handling where possible +so normal pet response text and pet-button state updates still happen. The pet +console is resizable and is released with the other Multiclass native windows +during client UI reset/logout. + +Bulk spell scribing stages the server spellbook update first, sends the native +Multiclass level patch rows, then sends the client scribe packets. This keeps +the stock spell-gem right-click menus from caching off-class spells as level 255 +until the player zones. + +`NativeMulticlassMelodyWnd` is a separate Bard-song surface. It consumes +`MULTICLASS|melody...` transport rows, lists four server-owned slots, displays +eligible scribed songs, and submits slot changes back through `#mc melody`. + +`NativeMulticlassDisciplineWnd` is a separate discipline surface. It consumes +`MULTICLASS|discipline...` transport rows, lists learned disciplines with level, +timer, total reuse duration, and readiness state, and submits use requests back +through `#mc disc`. Its child controls use SIDL `AutoStretch` anchors so the +inner list, stock active-effect gauge, footer, and buttons follow the sizable +window frame. + +The feature-local client export utility emits `SkillCaps.txt` with the highest +known skill cap for each skill/level across player classes, following the useful +THJ client-file pattern while keeping real per-trio skill enforcement and +class-skill behavior on the server. + +External/test-client patch syncing is driven by +`features/multiclass/patcher.yml`. Add any client-facing file there with a +repo-relative `source` and the destination path inside the EverQuest client +folder. Do not add files directly to the local EQ client as the source of truth. +The current feed includes the feature-owned `dinput8.dll`, native Multiclass +XML, generated `eqhost`, generated `EQUI.xml`, and the native XML include. +Missing files block real external syncs; `-AllowMissingClientFiles` is only for +partial local testing. Patcher deployment `-Project` values come from +`D:\Codex\Apps\EQEmu-feature-workspaces\installs.json` install ids; for this +checkout it is currently `multiclass`, but future projects should verify rather +than assuming the feature id. + +`features/multiclass/TRIO_RESONANCE.md` records the current exact trio names, +fallback archetypes, and level 10 through 60 bonus tiers. + +## Design Guardrails + +- Keep class swaps server-authoritative. +- Prefer one fixed trio. If class changes exist later, make them rare one-slot + reweaves earned through content. +- Current reweave scaffolding only changes slot 2 or 3 in cities or bind-safe + sanctuaries. It is intended for future native UI/token flow, not free swapping. +- Allow multiple pet builds; pet-heavy trios are part of the intended fantasy. +- Use the native Multiclass pet console as the primary pet control surface. + The stock pet window should remain compatibility-only, not the required way + to focus or command individual Multiclass pets. +- The current roster supports active in-zone pets. Saving/loading all three pet + states across zone/camp now uses reserved stock pet slots for the secondary + roster pets plus the Multiclass pet-state table for command metadata. Death + still follows stock active-pet clearing behavior. +- Keep Bard Melody in its own native window. The normal spell bar should stay + free for the player's other two classes. +- Store future native UI decisions and audit rows in database-backed tables + before enabling trio power. +- Do not implement command-only class hacks that bypass equipment, spell, skill, + or zone restrictions. +- Keep shared identity systems character-wide unless a later design explicitly + splits them. +- Current resonance passives are a first tunable power pass. Keep future + balance changes centralized in `MulticlassManager::ApplyTrioBonuses`. diff --git a/features/multiclass/TRIO_RESONANCE.md b/features/multiclass/TRIO_RESONANCE.md new file mode 100644 index 0000000000..b58a739ca8 --- /dev/null +++ b/features/multiclass/TRIO_RESONANCE.md @@ -0,0 +1,76 @@ +# Multiclass Trio Resonance + +This file tracks the first implemented pass of trio names and level-gated +resonance bonuses. The goal is not restraint; it is a THJ-style power fantasy +with enough structure that the server can tune it cleanly later. + +## Bonus Cadence + +Locked trios unlock one resonance tier every ten levels: + +| Level | Tier | +| --- | --- | +| 10 | Tier 1 | +| 20 | Tier 2 | +| 30 | Tier 3 | +| 40 | Tier 4 | +| 50 | Tier 5 | +| 60 | Tier 6 | + +Bonuses are passive and server-side. They are applied through +`MulticlassManager::ApplyTrioBonuses` during client bonus calculation and are +reported in the native Multiclass window through `MULTICLASS|bonuses|...`. + +## Exact Trio Identities + +| Classes | Name | Tier Names | +| --- | --- | --- | +| Magician / Necromancer / Beastlord | Grand Menagerie | Bonded Leashes, Pack Savagery, Triune Ward, Shared Command, Alpha Chorus, Grand Menagerie | +| Warrior / Wizard / Magician | Warbound Arcanum | Arcane Bulwark, Summoner's Guard, Battlecaster's Focus, Elemental Reprisal, War-Mage Tempo, Arcanum Ascendant | +| Wizard / Rogue / Berserker | Spellblade Compact | Hidden Edge, Volatile Footwork, Spellsteel Accuracy, Rupture Window, Executioner's Spark, Compact Fulfilled | +| Cleric / Paladin / Bard | Radiant Hymn | Aegis Verse, Merciful Cadence, Consecrated Guard, Bright Refrain, Unbroken Chorus, Radiant Hymn | +| Enchanter / Bard / Rogue | Velvet Conspiracy | Soft Step, Mesmeric Rhythm, Knife in the Song, Velvet Escape, Mindbreak Flourish, Perfect Conspiracy | +| Warrior / Rogue / Wizard | Arcane Duelist Pact | Arcane Guard, Opening Cut, Riposte Spark, Duelist's Read, Killing Tempo, Pact of the Last Word | +| Cleric / Druid / Shaman | Verdant Synod | Green Accord, Cleansing Root, Patient Waters, Triune Recovery, Living Bastion, Verdant Synod | +| Warrior / Cleric / Paladin | Aegis Covenant | Shield Oath, Interlocking Plate, Mercy Under Fire, Blessed Rampart, Last Stand Prayer, Aegis Covenant | +| Shadow Knight / Bard / Necromancer | Dirge of the Grave | Grave Note, Dread Cadence, Bone Chorus, Umbral Recovery, Funeral Engine, Dirge of the Grave | +| Ranger / Druid / Beastlord | Wildcall Pact | Trail Sense, Pack Step, Living Thorn, Primal Recovery, Wildfire Hunt, Wildcall Pact | + +## Fallback Identity Rules + +Exact trio identities are preferred. Other combinations fall into broad +archetypes so every locked trio still has meaningful flavor: + +| Archetype | Trigger | Tier Theme | +| --- | --- | --- | +| Menagerie Mastery | Two or more pet classes | Pet durability, pet attack, pet criticals, command strength | +| Chorus of Three | Bard present | Song range, song mod cap, instrument support, mobility | +| Covenant Prime | Tank plus healer | HP, AC, mitigation, healing stability | +| Striker's Revelation | Striker plus caster | Accuracy, spell damage, Backstab/Frenzy pressure | +| Concord Ascendant | Healer plus caster | Mana recovery, healing, casting stability | +| Triad Ascendant | Everything else | Shared reserves, core stats, broad class harmony | + +## Current Mechanical Bonus Families + +The first implementation keeps bonuses intentionally broad and tunable: + +- Core locked-trio bonuses: HP, AC, ATK, and class-resource reserves. +- Tank bonuses: HP, AC, shielding, and shield block. +- Healer bonuses: heal amount, heal rate, heal crit chance, and mana regen. +- INT caster bonuses: spell damage, spell crit chance, and mana. +- WIS caster bonuses: WIS, heal amount, and mana regen. +- Striker bonuses: ATK, accuracy, melee crit chance, Backstab/Frenzy damage. +- Pet bonuses: pet max HP, pet attack, pet crit, and pet mitigation. +- Bard bonuses: singing/instrument mods, song range, and song mod cap. + +Exact identities add a small extra accent on top of those families. For +example, Grand Menagerie adds stronger pet bonuses and enables pet group-target +support at tier 4, while Spellblade Compact adds more Backstab/Frenzy damage +and casting stability. + +## Tuning Notes + +This is a first power pass. If the bonuses overshoot after testing, tune the +numbers in `MulticlassManager::ApplyTrioBonuses` before cutting features. +Bard Melody balance should stay separate; a future global Bard song scalar can +be added if the eight-song playstyle proves too strong. diff --git a/features/multiclass/VALIDATION.md b/features/multiclass/VALIDATION.md new file mode 100644 index 0000000000..a13508124c --- /dev/null +++ b/features/multiclass/VALIDATION.md @@ -0,0 +1,117 @@ +# Multiclass Validation Matrix + +## Current Pass Status + +2026-05-26: the current manual validation matrix has been worked through in +game. The pass covered the first required trio set, native Multiclass windows, +multi-pet behavior, caster presentation, spell gems/book behavior, discipline +bridge behavior, and Bard Melody. + +Issues found during the pass and fixed in this branch: + +- Native discipline window resize/anchor bug hid the Use and Hotkey buttons. +- Bard Melody slot edits refreshed the whole song stack immediately. +- Bard songs cast from normal spell gems while Melody was active could stick in + the stock auto-repeat loop. Melody now owns sustained song looping, while + spell-gem Bard songs are on-demand casts when Melody has active slots. + +Next validation should expand this document instead of repeating only the first +matrix. Candidate areas: deeper AA edge cases, item/equipment edge cases, +zoning/death/reconnect pet persistence, Bard balance tuning, and any trio +specific resonance/passive work. + +## Second-Pass Slice Queue + +The current overnight build is intended to be tested manually in slices. Do not +start or restart the server/client from automation unless the current test +slice explicitly asks for it. + +| Slice | Area | Morning Validation Goal | +| --- | --- | --- | +| 1 | Startup/session cleanup | Log in, open `/mc`, `/mcpets`, `/mcmelody`, and `/disc`, then camp to character select and back without stale native windows or login crashes. | +| 2 | Caster presentation | Warrior-root caster trios should show mana, spellbook, and spell-gem bar after login without needing Alt+S or zoning. | +| 3 | Spell display | Scribe off-presentation spells and check spellbook, spell-gem right-click menus, merchant spell lists, and scroll previews for lingering level 255 labels. | +| 4 | Skills/class tools | Wizard / Rogue / Berserker and similar trios should seed Backstab, Frenzy, combat defenses, tracking/forage/pick tools where eligible, then skill up normally. | +| 5 | Disc bridge | Learn and use off-base disciplines through `NativeMulticlassDisciplineWnd`; verify active gauge, reuse timer, Use, and Hotkey behavior. | +| 6 | AA visibility | Open the stock AA window after `/mc refresh` and verify visible off-base AA entries, purchase, learned persistence, active use, timers, and passive effects. Record any apparent client cap. | +| 7 | Item gates | Equip, swap, click, augment, bandolier, trade/parcel/merchant/guild-bank, and preview items that match any trio class; confirm no-trio items still fail. | +| 8 | Multi-pet hardening | Summon 1/2/3 pets, command all/focused, zone, camp/relog, crash/reconnect if safe, die/revive, and confirm persistence/clearing without duplication. | +| 9 | Bard Melody | Run four Melody songs, cast extra Bard songs from normal gems, clear/swap slots, and confirm no instant refresh spam or stuck stock auto-repeat. | +| 10 | Trio resonance | Check level 10/20/30/40/50/60 tier summaries and stat changes for exact trios and fallback trios; tune if bonuses feel flat or excessive. | +| 11 | Reweave | Grant a reweave, attempt slot 1, attempt slot 2/3 outside a safe zone, spend one in a city/bind-safe zone, and verify profile, AA, skills, spells, pets, and native summary refresh. | + +## New Resonance Test Trios + +These exact identities have named level 10 through 60 tracks in the current +server pass: + +| Trio | Identity | Validation Angle | +| --- | --- | --- | +| Magician / Necromancer / Beastlord | Grand Menagerie | Pet durability, pet pressure, tier 4 pet group-target support. | +| Warrior / Wizard / Magician | Warbound Arcanum | Melee-root caster presentation, tank shell, summoned pressure. | +| Wizard / Rogue / Berserker | Spellblade Compact | Caster-root melee tools, Backstab/Frenzy, disc bridge, spell burst. | +| Cleric / Paladin / Bard | Radiant Hymn | Healing, mitigation, Bard Melody support, hybrid tools. | +| Enchanter / Bard / Rogue | Velvet Conspiracy | Control, Melody, Rogue tools, on-demand Bard spell behavior. | +| Warrior / Rogue / Wizard | Arcane Duelist Pact | Tank/striker/caster blend and melee-plus-spell pressure. | +| Cleric / Druid / Shaman | Verdant Synod | Pure recovery and mana/heal scaling. | +| Warrior / Cleric / Paladin | Aegis Covenant | Defensive stacking and survivability. | +| Shadow Knight / Bard / Necromancer | Dirge of the Grave | Shadow spell damage, pet pressure, Bard support. | +| Ranger / Druid / Beastlord | Wildcall Pact | Tracking/nature tools, pet bonuses, hybrid casting. | + +## First-Pass Checklist + +This was the first manual test checklist. Do not start or restart the +server/client from automation unless the current test slice explicitly asks for +it. + +## Required Trios + +| Trio | Focus | Current Expected Proof | +| --- | --- | --- | +| Warrior / Magician / Wizard | Melee base with caster UI | Mana HUD appears, spellbook/gems work, one pet works, class cast restrictions accept Magician/Wizard spells. | +| Magician / Necromancer / Beastlord | Pet-heavy caster trio | Three full pets summon, command, save through zone/camp/relog, and restore hold/taunt/focus/order state. | +| Wizard / Rogue / Berserker | Caster base with melee tools | Backstab/Frenzy skills seed, combat ability packets work if stock UI exposes them, class-restricted AA/disc effects accept Rogue/Berserker. | +| Cleric / Paladin / Bard | Priest/hybrid/Bard mix | Bard Melody window opens, four eligible songs can be assigned, safe songs pulse, Paladin timers/discs remain available. | +| Enchanter / Bard / Rogue | Control/Bard/Rogue mix | Melody blocks unsafe control songs, Rogue tools seed, spell gems remain free for non-song casting. | + +## Per-Trio Checks + +- Login: `/mc` opens the main window and shows the expected trio, presentation + class, skill summary, pet policy, and Melody button when Bard is present. +- Pets: `/mcpets` opens the separate pet console; Attack/Back/Follow/Guard and + Health broadcast, while Taunt/Hold/Spellhold/Cast/Dismiss apply to the focused + row. +- Pet persistence: with three pets up, zone, camp/relog, and crash/reconnect if + safe; confirm all pets restore without duplication and that focus/hold/order + state is retained. +- Spells: scribe, memorize, cast, fizzle, inspect spellbook levels, and inspect + spell-gem right-click labels for off-presentation classes. +- Discs/class tools: learn/use disciplines and combat abilities for off-base + classes; if stock buttons are missing, record the exact base/trio/client UI + combination for the native Class Tools fallback. +- Items: equip/use/click an item allowed by any trio class and confirm items + allowed by no trio class still fail. +- AA: display, purchase, activate, timer, passive bonus, and persistence for an + off-base AA where possible. +- Bard Melody: assign up to four scribed safe songs, verify pulses without + occupying spell gems, clear one slot, clear all slots, and confirm blocked + control songs show a clear reason. + +## Build/Install Flow + +```powershell +cd D:\Codex\Apps\EQEmu-feature-workspaces +.\verify-feature.ps1 multiclass +.\install-server-runtime.ps1 multiclass +.\install-client-files.ps1 multiclass +.\run-db-updates.ps1 multiclass +.\validate-install.ps1 multiclass +``` + +After a working build, checkpoint feature-owned source and runtime files: + +```powershell +git status --short +git add +git commit -m "Checkpoint Multiclass native client work" +``` diff --git a/features/multiclass/patcher.yml b/features/multiclass/patcher.yml new file mode 100644 index 0000000000..337b9db9e0 --- /dev/null +++ b/features/multiclass/patcher.yml @@ -0,0 +1,14 @@ +version: 1 +id: multiclass +label: Multiclass +client: rof +files: + - source: client_files/native_autoloot/eq-core-dll/bin/dinput8.dll + destination: dinput8.dll + - source: client_files/native_autoloot/ui/EQUI_NativeMulticlassWnd.xml + destination: uifiles/default/EQUI_NativeMulticlassWnd.xml +generated: + eqhost: true + equiXml: true + equiIncludes: + - EQUI_NativeMulticlassWnd.xml diff --git a/features/multiclass/sql/001_multiclass_schema.sql b/features/multiclass/sql/001_multiclass_schema.sql new file mode 100644 index 0000000000..6fe2d0db96 --- /dev/null +++ b/features/multiclass/sql/001_multiclass_schema.sql @@ -0,0 +1,60 @@ +CREATE TABLE `custom_multiclass_profiles` ( + `character_id` INT UNSIGNED NOT NULL, + `class_slot_1` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `class_slot_2` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `class_slot_3` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `trio_name` VARCHAR(96) NOT NULL DEFAULT '', + `resonance_key` VARCHAR(64) NOT NULL DEFAULT '', + `multiple_pets_enabled` TINYINT(1) NOT NULL DEFAULT 1, + `locked` TINYINT(1) NOT NULL DEFAULT 0, + `reweaves_available` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `created_at` INT UNSIGNED NOT NULL DEFAULT 0, + `updated_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`), + KEY `idx_slot_1` (`class_slot_1`), + KEY `idx_slot_2` (`class_slot_2`), + KEY `idx_slot_3` (`class_slot_3`), + KEY `idx_resonance` (`resonance_key`) +); + +CREATE TABLE `custom_multiclass_profile_audit` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + `character_id` INT UNSIGNED NOT NULL DEFAULT 0, + `class_slot` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `class_id` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `action` VARCHAR(64) NOT NULL DEFAULT '', + `detail` VARCHAR(255) NOT NULL DEFAULT '', + `created_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_character_created` (`character_id`, `created_at`), + KEY `idx_class` (`class_id`) +); + +CREATE TABLE `custom_multiclass_pet_state` ( + `character_id` INT UNSIGNED NOT NULL, + `pet_slot` TINYINT UNSIGNED NOT NULL, + `spell_id` INT UNSIGNED NOT NULL DEFAULT 0, + `pet_name` VARCHAR(64) NOT NULL DEFAULT '', + `pet_order` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `held` TINYINT(1) NOT NULL DEFAULT 0, + `gheld` TINYINT(1) NOT NULL DEFAULT 0, + `nocast` TINYINT(1) NOT NULL DEFAULT 0, + `focused` TINYINT(1) NOT NULL DEFAULT 0, + `pet_stop` TINYINT(1) NOT NULL DEFAULT 0, + `pet_regroup` TINYINT(1) NOT NULL DEFAULT 0, + `guard_x` FLOAT NOT NULL DEFAULT 0, + `guard_y` FLOAT NOT NULL DEFAULT 0, + `guard_z` FLOAT NOT NULL DEFAULT 0, + `guard_heading` FLOAT NOT NULL DEFAULT 0, + `updated_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`, `pet_slot`), + KEY `idx_character_spell` (`character_id`, `spell_id`) +); + +CREATE TABLE `custom_multiclass_bard_melody` ( + `character_id` INT UNSIGNED NOT NULL, + `slot_id` TINYINT UNSIGNED NOT NULL, + `spell_id` INT UNSIGNED NOT NULL DEFAULT 0, + `updated_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`, `slot_id`) +); diff --git a/features/tradeskills/MANIFEST.md b/features/tradeskills/MANIFEST.md new file mode 100644 index 0000000000..002efc7589 --- /dev/null +++ b/features/tradeskills/MANIFEST.md @@ -0,0 +1,19 @@ +# Tradeskills Manifest + +Feature id: `tradeskills` + +This manifest starts intentionally small. Add required source files, SQL files, +client UI files, and operator notes as the feature becomes real. + +## Test Target + +- Server: `D:\EQServers\EQServer-Tradeskills` +- Client: `D:\EQClients\EQClient-Tradeskills` +- Database: `eqemu_tradeskills` + +## Expected First Implementation Updates + +- Add feature-owned source files to `features.json` `requiredFiles` once they exist. +- Add SQL migration files under `features/tradeskills/sql` if the feature needs schema/rule data. +- Add command, packet, or manager entry points here as they become part of the portable feature. +- If the feature has native client behavior, add the feature-owned DLL project/source and build this checkout's own `dinput8.dll`. \ No newline at end of file diff --git a/features/tradeskills/README.md b/features/tradeskills/README.md new file mode 100644 index 0000000000..8fe6496698 --- /dev/null +++ b/features/tradeskills/README.md @@ -0,0 +1,31 @@ +# Tradeskills + +Standalone EQEmu feature branch for `tradeskills`. + +## Test Target + +- Server: `D:\EQServers\EQServer-Tradeskills` +- Client: `D:\EQClients\EQClient-Tradeskills` +- Database: `eqemu_tradeskills` + +## First Build Loop + +From `D:\Codex\Apps\EQEmu-feature-workspaces`: + +~~~powershell +.\verify-feature.ps1 tradeskills +.\install-server-runtime.ps1 tradeskills +.\install-client-files.ps1 tradeskills +.\run-db-updates.ps1 tradeskills +.\validate-install.ps1 tradeskills +~~~ + +`install-server-runtime.ps1` also refreshes Windows firewall allow rules for the copied server binaries. + +## Client UI + +Native XML `EQUI_NativeTradeskillsWnd.xml` is installed into the prepared client and included from `uifiles/default/EQUI.xml` by the workspace client install scripts. + +## Development Notes + +Replace this section with feature behavior, commands, SQL, client files, operator install notes, and known test cases as the feature takes shape. \ No newline at end of file diff --git a/features/tradeskills/patcher.yml b/features/tradeskills/patcher.yml new file mode 100644 index 0000000000..46a258a849 --- /dev/null +++ b/features/tradeskills/patcher.yml @@ -0,0 +1,14 @@ +version: 1 +id: tradeskills +label: Tradeskills +client: rof +files: + - source: client_files/native_autoloot/eq-core-dll/bin/dinput8.dll + destination: dinput8.dll + - source: client_files/native_autoloot/ui/EQUI_NativeTradeskillsWnd.xml + destination: uifiles/default/EQUI_NativeTradeskillsWnd.xml +generated: + eqhost: true + equiXml: true + equiIncludes: + - EQUI_NativeTradeskillsWnd.xml diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index cded034657..ab7464a0c4 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -54,12 +54,14 @@ set(zone_sources heal_rotation.cpp horse.cpp inventory.cpp + item_rarity_manager.cpp loot.cpp main.cpp map.cpp merc.cpp mob.cpp mob_ai.cpp + multiclass_manager.cpp mob_appearance.cpp mob_info.cpp mob_movement_manager.cpp @@ -155,6 +157,7 @@ set(zone_headers hate_list.h heal_rotation.h horse.h + item_rarity_manager.h lua_bit.h lua_bot.h lua_buff.h @@ -191,6 +194,7 @@ set(zone_headers masterentity.h merc.h mob.h + multiclass_manager.h mob_movement_manager.h npc.h npc_scale_manager.h @@ -459,6 +463,7 @@ set(gm_command_sources gm_commands/grid.cpp gm_commands/guild.cpp gm_commands/hp.cpp + gm_commands/hpfix.cpp gm_commands/illusion_block.cpp gm_commands/instance.cpp gm_commands/interrogateinv.cpp @@ -466,6 +471,8 @@ set(gm_command_sources gm_commands/invsnapshot.cpp gm_commands/ipban.cpp gm_commands/itemedit.cpp + gm_commands/itemrarity.cpp + gm_commands/itemscore.cpp gm_commands/kick.cpp gm_commands/kill.cpp gm_commands/killallnpcs.cpp @@ -481,6 +488,8 @@ set(gm_command_sources gm_commands/modifynpcstat.cpp gm_commands/movechar.cpp gm_commands/movement.cpp + gm_commands/multiclass.cpp + gm_commands/multiclass_ui.cpp gm_commands/myskills.cpp gm_commands/mysql.cpp gm_commands/mystats.cpp diff --git a/zone/client.cpp b/zone/client.cpp index ddd29c6da9..4360ee3733 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -9242,6 +9242,32 @@ void Client::SendHPUpdateMarquee(){ SendMarqueeMessage(Chat::Yellow, 510, 0, 3000, 3000, health_update_notification); } +void Client::SendNativeHpFixUpdate(bool force) +{ + if (!native_hpfix_ready_) { + return; + } + + const int64 current = GetHP(); + const int64 maximum = GetMaxHP(); + if (maximum <= 0) { + return; + } + + const double percent = (static_cast(current) * 100.0) / static_cast(maximum); + const auto payload = fmt::format( + "HPFIX|self|current={}|max={}|percent={:.2f}", + current, + maximum, + percent + ); + + Message(Chat::Yellow, payload.c_str()); + if (force) { + LogHPUpdate("Native HPFIX forced update for [{}]: {}", GetCleanName(), payload); + } +} + uint32 Client::GetMoney(uint8 type, uint8 subtype) { uint32 value = 0; diff --git a/zone/client.h b/zone/client.h index 5cbd2c4def..bb20ecc93f 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1858,6 +1858,9 @@ class Client : public Mob void ResetHPUpdateTimer() { hpupdate_timer.Start(); } void SendHPUpdateMarquee(); + bool IsNativeHpFixReady() const { return native_hpfix_ready_; } + void SetNativeHpFixReady(bool ready) { native_hpfix_ready_ = ready; } + void SendNativeHpFixUpdate(bool force = false); void CheckRegionTypeChanges(); @@ -1946,6 +1949,7 @@ class Client : public Mob private: ExternalHandinMoneyReturned m_external_handin_money_returned = {}; std::vector m_external_handin_items_returned = {}; + bool native_hpfix_ready_ = false; public: ExternalHandinMoneyReturned GetExternalHandinMoneyReturned() { return m_external_handin_money_returned; } std::vector GetExternalHandinItemsReturned() { return m_external_handin_items_returned; } diff --git a/zone/command.cpp b/zone/command.cpp index 6a76dfc77c..4dd26e0887 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -165,6 +165,7 @@ int command_init(void) command_add("help", "[Search Criteria] - List available commands and their description, specify partial command as argument to search", AccountStatus::Player, command_help) || command_add("hotfix", "[hotfix_name] - Reloads shared memory into a hotfix, equiv to load_shared_memory followed by apply_shared_memory", AccountStatus::GMImpossible, command_hotfix) || command_add("hp", "Refresh your HP bar from the server.", AccountStatus::Player, command_hp) || + command_add("hpfix", "[native|refresh|status|items|off] - Native high-HP display test tools.", AccountStatus::Player, command_hpfix) || command_add("illusionblock", "Controls whether or not illusion effects will land on you when cast by other players or bots", AccountStatus::Guide, command_illusion_block) || command_add("instance", "Modify Instances", AccountStatus::GMMgmt, command_instance) || command_add("interrogateinv", "use [help] argument for available options", AccountStatus::Player, command_interrogateinv) || @@ -173,6 +174,8 @@ int command_init(void) command_add("ipban", "[IP] - Ban IP", AccountStatus::GMMgmt, command_ipban) || command_add("itemedit", "[set|add|clear|proc] - Edit the item currently held on your cursor", AccountStatus::GMMgmt, command_itemedit) || command_add("itemforge", "[dialog|craft] - Open or use the player item forge", AccountStatus::Player, command_itemforge) || + command_add("itemrarity", "Set, link, view, and add colored-rarity test loot for items.", AccountStatus::GMMgmt, command_itemrarity) || + command_add("itemscore", "Score, audit, and explain item power levels", AccountStatus::GMMgmt, command_itemscore) || command_add("kick", "[Character Name] - Disconnect a player by name", AccountStatus::GMLeadAdmin, command_kick) || command_add("kill", "Kill your target", AccountStatus::GMAdmin, command_kill) || command_add("killallnpcs", "[npc_name] - Kills all npcs by search name, leave blank for all attackable NPC's", AccountStatus::GMMgmt, command_killallnpcs) || @@ -190,6 +193,9 @@ int command_init(void) command_add("modifynpcstat", "[Stat] [Value] - Modifies an NPC's stats temporarily.", AccountStatus::GMLeadAdmin, command_modifynpcstat) || command_add("movechar", "[Character ID|Character Name] [Zone ID|Zone Short Name] - Move an offline character to the specified zone", AccountStatus::Guide, command_movechar) || command_add("movement", "Various movement commands", AccountStatus::GMMgmt, command_movement) || + command_add("multiclass", "[status|set|diag|native|help] - Admin/native bridge for Multiclass trio profiles", AccountStatus::GMAdmin, command_multiclass) || + command_add("multiclassui", "[status|choose|pets|disc] - Native Multiclass UI bridge", AccountStatus::Player, command_multiclass_ui) || + command_add("mc", "[open|status|refresh|choose|pets|pet|disc] - Short native Multiclass UI bridge", AccountStatus::Player, command_multiclass_ui) || command_add("myskills", "Show details about your current skill levels", AccountStatus::Player, command_myskills) || command_add("mysql", "[Help|Query] [SQL Query] - Mysql CLI, see 'Help' for options.", AccountStatus::GMImpossible, command_mysql) || command_add("mystats", "Show details about you or your pet", AccountStatus::Guide, command_mystats) || diff --git a/zone/command.h b/zone/command.h index 6b74f44454..edb202882f 100644 --- a/zone/command.h +++ b/zone/command.h @@ -122,6 +122,7 @@ void command_guild(Client *c, const Seperator *sep); void command_help(Client *c, const Seperator *sep); void command_hotfix(Client *c, const Seperator *sep); void command_hp(Client *c, const Seperator *sep); +void command_hpfix(Client *c, const Seperator *sep); void command_illusion_block(Client* c, const Seperator* sep); void command_instance(Client *c, const Seperator *sep); void command_interrogateinv(Client *c, const Seperator *sep); @@ -130,6 +131,8 @@ void command_invsnapshot(Client *c, const Seperator *sep); void command_ipban(Client *c, const Seperator *sep); void command_itemedit(Client *c, const Seperator *sep); void command_itemforge(Client *c, const Seperator *sep); +void command_itemrarity(Client *c, const Seperator *sep); +void command_itemscore(Client *c, const Seperator *sep); void command_kick(Client *c, const Seperator *sep); void command_killallnpcs(Client *c, const Seperator *sep); void command_kill(Client *c, const Seperator *sep); @@ -147,6 +150,8 @@ void command_merchantshop(Client *c, const Seperator *sep); void command_modifynpcstat(Client *c, const Seperator *sep); void command_movechar(Client *c, const Seperator *sep); void command_movement(Client *c, const Seperator *sep); +void command_multiclass(Client *c, const Seperator *sep); +void command_multiclass_ui(Client *c, const Seperator *sep); void command_myskills(Client *c, const Seperator *sep); void command_mysql(Client *c, const Seperator *sep); void command_mystats(Client *c, const Seperator *sep); diff --git a/zone/gm_commands/hpfix.cpp b/zone/gm_commands/hpfix.cpp new file mode 100644 index 0000000000..b699b0c7aa --- /dev/null +++ b/zone/gm_commands/hpfix.cpp @@ -0,0 +1,121 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTIBILITY 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, see . +*/ +#include "zone/client.h" + +namespace { + constexpr uint32 HPFIX_CHARM_ITEM_ID = 990001; + constexpr uint32 HPFIX_CHEST_ITEM_ID = 990002; + constexpr uint32 HPFIX_WAIST_ITEM_ID = 990003; + + bool HpFixCanUseGmTools(Client* c) + { + return c && c->Admin() >= AccountStatus::GMMgmt; + } + + void HpFixSummonItem(Client* c, uint32 item_id) + { + const auto* item = database.GetItem(item_id); + if (!item) { + c->Message( + Chat::White, + fmt::format( + "HPFIX test item {} is missing. Apply features/hpfix/sql/001_hpfix_test_items.sql first.", + item_id + ).c_str() + ); + return; + } + + c->SummonItem(item_id); + c->Message(Chat::White, fmt::format("Summoned {}.", item->Name).c_str()); + } + + void HpFixShowUsage(Client* c) + { + c->Message(Chat::White, "HPFIX: native ready, refresh, status, window, off, items"); + c->Message(Chat::White, "The DLL sends '#hpfix native ready' automatically; players should not need to type this."); + } +} + +void command_hpfix(Client* c, const Seperator* sep) +{ + const uint16 arguments = sep->argnum; + + if ( + arguments >= 2 && + !strcasecmp(sep->arg[1], "native") && + !strcasecmp(sep->arg[2], "ready") + ) { + c->SetNativeHpFixReady(true); + c->SendNativeHpFixUpdate(true); + return; + } + + if (!arguments || !strcasecmp(sep->arg[1], "help")) { + HpFixShowUsage(c); + return; + } + + if (!strcasecmp(sep->arg[1], "refresh")) { + c->SetNativeHpFixReady(true); + c->SendNativeHpFixUpdate(true); + c->Message(Chat::White, "Native HPFIX payload refreshed."); + return; + } + + if (!strcasecmp(sep->arg[1], "status")) { + const std::string ready_status = c->IsNativeHpFixReady() ? "ready" : "not ready"; + c->Message( + Chat::White, + fmt::format( + "Native HPFIX is {}. Server HP: {} / {}.", + ready_status, + c->GetHP(), + c->GetMaxHP() + ).c_str() + ); + return; + } + + if (!strcasecmp(sep->arg[1], "window")) { + c->SetNativeHpFixReady(true); + c->Message(Chat::Yellow, "HPFIX|window|show"); + c->SendNativeHpFixUpdate(true); + return; + } + + if (!strcasecmp(sep->arg[1], "off")) { + c->SetNativeHpFixReady(false); + c->Message(Chat::White, "Native HPFIX disabled for this zone session."); + return; + } + + if (!strcasecmp(sep->arg[1], "items")) { + if (!HpFixCanUseGmTools(c)) { + c->Message(Chat::White, "Insufficient status to summon HPFIX test items."); + return; + } + + HpFixSummonItem(c, HPFIX_CHARM_ITEM_ID); + HpFixSummonItem(c, HPFIX_CHEST_ITEM_ID); + HpFixSummonItem(c, HPFIX_WAIST_ITEM_ID); + return; + } + + HpFixShowUsage(c); +} diff --git a/zone/gm_commands/itemrarity.cpp b/zone/gm_commands/itemrarity.cpp new file mode 100644 index 0000000000..9a3ebe8ad6 --- /dev/null +++ b/zone/gm_commands/itemrarity.cpp @@ -0,0 +1,278 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTIBILITY 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, see . +*/ +#include "common/item_instance.h" +#include "common/seperator.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/corpse.h" +#include "zone/item_rarity_manager.h" +#include "zone/npc.h" +#include "zone/zonedb.h" + +#include + +namespace { + void SendUsage(Client *c) + { + c->Message(Chat::White, "Usage: #itemrarity init - Create the item_rarity table if it is missing."); + c->Message(Chat::White, "Usage: #itemrarity legend - Show rarity color samples."); + c->Message(Chat::White, "Usage: #itemrarity set [Item ID] [common|uncommon|rare|legendary|unique] - Tag an item."); + c->Message(Chat::White, "Usage: #itemrarity clear [Item ID] - Remove an item's rarity tag."); + c->Message(Chat::White, "Usage: #itemrarity show [Item ID] - Show an item's rarity tag."); + c->Message(Chat::White, "Usage: #itemrarity link [Item ID] - Send a clickable rarity-colored item link."); + c->Message(Chat::White, "Usage: #itemrarity view [Item ID] - Open the normal item inspect window and send its rarity link."); + c->Message(Chat::White, "Usage: #itemrarity loot [Item ID] [Rarity] [Charges] - Add tagged test loot to your NPC or corpse target."); + } + + bool GetItemID(Client *c, const Seperator *sep, int argument, uint32 &item_id) + { + if (!sep->IsNumber(argument)) { + c->Message(Chat::White, "Item ID must be numeric."); + return false; + } + + item_id = Strings::ToUnsignedInt(sep->arg[argument]); + if (!database.GetItem(item_id)) { + c->Message( + Chat::White, + "%s", + fmt::format( + "Item ID {} does not exist.", + item_id + ).c_str() + ); + return false; + } + + return true; + } + + bool GetRarity(Client *c, const Seperator *sep, int argument, ItemRarity &rarity) + { + if (!ItemRarityManager::TryParseRarity(sep->arg[argument], rarity)) { + c->Message(Chat::White, "Rarity must be common, uncommon, rare, legendary, unique, or a value from 0 to 4."); + return false; + } + + return true; + } + + void SendLegend(Client *c) + { + const ItemRarity rarities[] = { + ItemRarity::Common, + ItemRarity::Uncommon, + ItemRarity::Rare, + ItemRarity::Legendary, + ItemRarity::Unique + }; + + for (const auto rarity : rarities) { + c->Message( + ItemRarityManager::RarityChatColor(rarity), + "%s", + fmt::format( + "{} ({})", + ItemRarityManager::RarityName(rarity), + ItemRarityManager::RarityColorHex(rarity) + ).c_str() + ); + } + } + + void SendItemView(Client *c, uint32 item_id) + { + auto *inst = database.CreateItem(item_id); + if (!inst) { + c->Message(Chat::White, "Unable to create item instance."); + return; + } + + c->SendItemPacket(0, inst, ItemPacketViewLink); + delete inst; + } +} + +void command_itemrarity(Client *c, const Seperator *sep) +{ + const auto arguments = sep->argnum; + if (!arguments || !strcasecmp(sep->arg[1], "help")) { + SendUsage(c); + return; + } + + const bool is_init = !strcasecmp(sep->arg[1], "init"); + const bool is_legend = !strcasecmp(sep->arg[1], "legend"); + const bool is_set = !strcasecmp(sep->arg[1], "set"); + const bool is_clear = !strcasecmp(sep->arg[1], "clear"); + const bool is_show = !strcasecmp(sep->arg[1], "show"); + const bool is_link = !strcasecmp(sep->arg[1], "link"); + const bool is_view = !strcasecmp(sep->arg[1], "view"); + const bool is_loot = !strcasecmp(sep->arg[1], "loot"); + + if (is_init) { + if (ItemRarityManager::EnsureSchema()) { + c->Message(Chat::Green, "Item rarity schema is ready."); + } + else { + c->Message(Chat::Red, "Failed to create item rarity schema. Check zone logs for database errors."); + } + + return; + } + + if (is_legend) { + SendLegend(c); + return; + } + + if (is_set) { + if (arguments < 3) { + c->Message(Chat::White, "Usage: #itemrarity set [Item ID] [common|uncommon|rare|legendary|unique]"); + return; + } + + uint32 item_id = 0; + if (!GetItemID(c, sep, 2, item_id)) { + return; + } + + ItemRarity rarity = ItemRarity::Common; + if (!GetRarity(c, sep, 3, rarity)) { + return; + } + + if (!ItemRarityManager::SetRarity(item_id, rarity)) { + c->Message(Chat::Red, "Failed to save item rarity."); + return; + } + + ItemRarityManager::SendNativeRarity(c, item_id, rarity); + c->Message( + ItemRarityManager::RarityChatColor(rarity), + "%s", + fmt::format( + "Tagged {}.", + ItemRarityManager::BuildDecoratedLink(item_id, rarity) + ).c_str() + ); + return; + } + + if (is_clear) { + if (arguments < 2) { + c->Message(Chat::White, "Usage: #itemrarity clear [Item ID]"); + return; + } + + uint32 item_id = 0; + if (!GetItemID(c, sep, 2, item_id)) { + return; + } + + if (!ItemRarityManager::ClearRarity(item_id)) { + c->Message(Chat::Red, "Failed to clear item rarity."); + return; + } + + ItemRarityManager::SendNativeRarityClear(c, item_id); + c->Message( + Chat::White, + "%s", + fmt::format( + "Cleared rarity tag for {}.", + ItemRarityManager::BuildItemLink(item_id) + ).c_str() + ); + return; + } + + if (is_show || is_link || is_view) { + if (arguments < 2) { + c->Message(Chat::White, "Usage: #itemrarity show|link|view [Item ID]"); + return; + } + + uint32 item_id = 0; + if (!GetItemID(c, sep, 2, item_id)) { + return; + } + + if (is_view) { + ItemRarity rarity = ItemRarity::Common; + if (ItemRarityManager::TryGetRarity(item_id, rarity)) { + ItemRarityManager::SendNativeRarity(c, item_id, rarity); + } + + SendItemView(c, item_id); + } + + ItemRarityManager::SendRarityItemLink(c, item_id); + return; + } + + if (is_loot) { + if (arguments < 3) { + c->Message(Chat::White, "Usage: #itemrarity loot [Item ID] [Rarity] [Charges]"); + return; + } + + if (!c->GetTarget() || (!c->GetTarget()->IsNPC() && !c->GetTarget()->IsCorpse())) { + c->Message(Chat::White, "Target an NPC or corpse before using #itemrarity loot."); + return; + } + + uint32 item_id = 0; + if (!GetItemID(c, sep, 2, item_id)) { + return; + } + + ItemRarity rarity = ItemRarity::Common; + if (!GetRarity(c, sep, 3, rarity)) { + return; + } + + const auto charges = sep->IsNumber(4) ? static_cast(Strings::ToUnsignedInt(sep->arg[4])) : static_cast(1); + if (!ItemRarityManager::SetRarity(item_id, rarity)) { + c->Message(Chat::Red, "Failed to save item rarity."); + return; + } + + auto target = c->GetTarget(); + if (target->IsNPC()) { + target->CastToNPC()->AddItem(item_id, charges, false); + } + else if (target->IsCorpse()) { + target->CastToCorpse()->AddItem(item_id, charges); + } + + ItemRarityManager::SendNativeRarity(c, item_id, rarity); + c->Message( + ItemRarityManager::RarityChatColor(rarity), + "%s", + fmt::format( + "Added {} to {}.", + ItemRarityManager::BuildDecoratedLink(item_id, rarity), + c->GetTargetDescription(target) + ).c_str() + ); + return; + } + + SendUsage(c); +} diff --git a/zone/gm_commands/itemscore.cpp b/zone/gm_commands/itemscore.cpp new file mode 100644 index 0000000000..de467b7ea0 --- /dev/null +++ b/zone/gm_commands/itemscore.cpp @@ -0,0 +1,418 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; 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, see . +*/ +#include "common/item_instance.h" +#include "common/item_power.h" +#include "common/seperator.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/zonedb.h" + +#include +#include +#include + +namespace { + constexpr uint32 kRecalcChunkSize = 1000; + + std::string GetArg(const Seperator *sep, uint16 index) + { + if (!sep || index > sep->GetMaxArgNum() || !sep->arg[index]) { + return {}; + } + + return sep->arg[index]; + } + + void SendItemScoreUsage(Client *c) + { + c->Message(Chat::White, "Usage: #itemscore init"); + c->Message(Chat::White, "Usage: #itemscore show "); + c->Message(Chat::White, "Usage: #itemscore recalc "); + c->Message(Chat::White, "Usage: #itemscore explain "); + c->Message(Chat::White, "Usage: #itemscore audit [limit]"); + c->Message(Chat::White, "Usage: #itemscore override level <1-127>"); + c->Message(Chat::White, "Usage: #itemscore override multiplier "); + c->Message(Chat::White, "Usage: #itemscore override bonus "); + c->Message(Chat::White, "Usage: #itemscore override notes "); + c->Message(Chat::White, "Usage: #itemscore clearoverride "); + c->Message(Chat::White, "Usage: #itemscore view "); + } + + const EQ::ItemData *GetItem(Client *c, const std::string &item_id_arg, uint32 &item_id) + { + if (item_id_arg.empty() || !Strings::IsNumber(item_id_arg)) { + c->Message(Chat::Yellow, "Specify a numeric item ID."); + return nullptr; + } + + item_id = Strings::ToUnsignedInt(item_id_arg); + const auto *item = database.GetItem(item_id); + if (!item) { + c->Message(Chat::Yellow, "Item [{}] was not found in shared item data.", item_id); + return nullptr; + } + + return item; + } + + void SendTransport(Client *c, const EQ::ItemData &item) + { + std::string transport; + if (EQ::ItemPower::TryBuildStoredTransportMessage(database, item, transport)) { + c->Message(Chat::White, "%s", transport.c_str()); + } + } + + void SendStoredScore(Client *c, const EQ::ItemData &item) + { + EQ::ItemPower::StoredScore stored_score; + if (!EQ::ItemPower::TryGetStoredScore(database, item.ID, stored_score)) { + c->Message(Chat::Yellow, "No stored item power score for [{}] {}.", item.ID, database.CreateItemLink(item.ID)); + return; + } + + const auto role = EQ::ItemPower::BestRoleFromScores(stored_score); + c->Message( + Chat::White, + "Item Power [{}] {}: level [{}], score [{}], role [{}], version [{}], source [{}], updated [{}]", + item.ID, + database.CreateItemLink(item.ID), + stored_score.item_level, + stored_score.item_score, + EQ::ItemPower::RoleName(role), + stored_score.score_version, + stored_score.source, + stored_score.updated_at + ); + c->Message( + Chat::White, + "Role scores: tank [{}], melee [{}], caster [{}], healer [{}], hybrid [{}]", + stored_score.tank_score, + stored_score.melee_score, + stored_score.caster_score, + stored_score.healer_score, + stored_score.hybrid_score + ); + SendTransport(c, item); + } + + bool RecalculateItem(Client *c, const EQ::ItemData &item, bool save_breakdown) + { + if (!EQ::ItemPower::EnsureSchema(database)) { + c->Message(Chat::Red, "Unable to initialize item_power schema."); + return false; + } + + auto score = EQ::ItemPower::Calculate(item, save_breakdown); + EQ::ItemPower::ApplyOverrides(database, score); + + std::string error_message; + if (!EQ::ItemPower::SaveScore(database, score, &error_message, save_breakdown)) { + c->Message(Chat::Red, "Failed to save score for item [{}]: {}", item.ID, error_message); + return false; + } + + c->Message( + Chat::White, + "Recalculated [{}] {}: level [{}], score [{}], role [{}], source [{}]", + item.ID, + database.CreateItemLink(item.ID), + score.item_level, + score.item_score, + EQ::ItemPower::RoleName(score.best_role), + score.source + ); + SendTransport(c, item); + return true; + } + + void ExplainItem(Client *c, const EQ::ItemData &item) + { + auto score = EQ::ItemPower::Calculate(item, true); + EQ::ItemPower::ApplyOverrides(database, score); + + c->Message( + Chat::White, + "Computed [{}] {}: level [{}], score [{}], role [{}], slot budget [{} {:.2f}], source [{}]", + item.ID, + database.CreateItemLink(item.ID), + score.item_level, + score.item_score, + EQ::ItemPower::RoleName(score.best_role), + score.slot_budget_name, + score.slot_budget, + score.source + ); + c->Message( + Chat::White, + "Role scores: tank [{}], melee [{}], caster [{}], healer [{}], hybrid [{}]", + score.tank_score, + score.melee_score, + score.caster_score, + score.healer_score, + score.hybrid_score + ); + + for (const auto &component : score.breakdown) { + c->Message(Chat::White, "Component [{}]: score [{}] {}", component.component, component.score, component.details); + } + + for (const auto &warning : score.warnings) { + c->Message(Chat::Yellow, "Warning: {}", warning); + } + } + + void RecalculateAll(Client *c) + { + if (!EQ::ItemPower::EnsureSchema(database)) { + c->Message(Chat::Red, "Unable to initialize item_power schema."); + return; + } + + uint32 item_cursor = 0; + uint32 scored = 0; + uint32 chunk_count = 0; + + database.TransactionBegin(); + while (const auto *item = database.IterateItems(&item_cursor)) { + auto score = EQ::ItemPower::Calculate(*item, false); + EQ::ItemPower::ApplyOverrides(database, score); + + std::string error_message; + if (!EQ::ItemPower::SaveScore(database, score, &error_message, false, false)) { + database.TransactionRollback(); + c->Message(Chat::Red, "Recalculation stopped at item [{}]: {}", item->ID, error_message); + return; + } + + ++scored; + ++chunk_count; + + if (chunk_count >= kRecalcChunkSize) { + const auto commit = database.TransactionCommit(); + if (!commit.Success()) { + c->Message(Chat::Red, "Failed to commit item power scores: {}", commit.ErrorMessage()); + return; + } + + chunk_count = 0; + database.TransactionBegin(); + } + } + + const auto commit = database.TransactionCommit(); + if (!commit.Success()) { + c->Message(Chat::Red, "Failed to commit item power scores: {}", commit.ErrorMessage()); + return; + } + + c->Message(Chat::White, "Recalculated item power scores for [{}] shared-memory items.", scored); + } + + void AuditScores(Client *c, uint32 limit) + { + if (!EQ::ItemPower::SchemaReady(database)) { + c->Message(Chat::Yellow, "item_power schema is not ready. Run #itemscore init or database updates first."); + return; + } + + auto missing = database.QueryDatabase( + "SELECT COUNT(*) FROM `items` i LEFT JOIN `item_power` p ON p.`item_id` = i.`id` WHERE p.`item_id` IS NULL" + ); + if (missing.Success() && missing.RowCount()) { + auto row = missing.begin(); + c->Message(Chat::White, "Items missing item_power rows: [{}]", row[0] ? row[0] : "0"); + } + + auto stale = database.QueryDatabase( + fmt::format( + "SELECT COUNT(*) FROM `item_power` WHERE `score_version` <> {}", + EQ::ItemPower::ScoreVersion + ) + ); + if (stale.Success() && stale.RowCount()) { + auto row = stale.begin(); + c->Message(Chat::White, "Stored rows with stale score versions: [{}]", row[0] ? row[0] : "0"); + } + + auto outliers = database.QueryDatabase( + fmt::format( + "SELECT i.`id`, i.`Name`, i.`reqlevel`, i.`reclevel`, p.`item_level`, p.`item_score`, " + "ABS(CAST(p.`item_level` AS SIGNED) - CAST(GREATEST(i.`reqlevel`, CEIL(i.`reclevel` * 0.85)) AS SIGNED)) AS level_delta " + "FROM `item_power` p INNER JOIN `items` i ON i.`id` = p.`item_id` " + "ORDER BY level_delta DESC, p.`item_score` DESC LIMIT {}", + std::clamp(limit, 1, 50) + ) + ); + + if (!outliers.Success()) { + c->Message(Chat::Red, "Unable to audit item power scores: {}", outliers.ErrorMessage()); + return; + } + + c->Message(Chat::White, "Largest item level deltas:"); + for (auto row : outliers) { + c->Message( + Chat::White, + "[{}] {} req [{}] rec [{}] ilvl [{}] score [{}] delta [{}]", + row[0] ? row[0] : "0", + row[1] ? row[1] : "", + row[2] ? row[2] : "0", + row[3] ? row[3] : "0", + row[4] ? row[4] : "0", + row[5] ? row[5] : "0", + row[6] ? row[6] : "0" + ); + } + } + + void OverrideScore(Client *c, const Seperator *sep) + { + uint32 item_id = 0; + const auto *item = GetItem(c, GetArg(sep, 2), item_id); + if (!item) { + return; + } + + const auto field = Strings::ToLower(GetArg(sep, 3)); + const auto value = GetArg(sep, 4); + if (field.empty() || value.empty()) { + SendItemScoreUsage(c); + return; + } + + bool updated = false; + if (field == "level") { + if (!Strings::IsNumber(value)) { + c->Message(Chat::Yellow, "Level override must be numeric."); + return; + } + + const auto item_level = static_cast(std::clamp(Strings::ToUnsignedInt(value), 1, 127)); + updated = EQ::ItemPower::SetLevelOverride(database, item_id, item_level); + } + else if (field == "multiplier") { + const auto multiplier = Strings::ToFloat(value, 0.0f); + if (multiplier <= 0.0f) { + c->Message(Chat::Yellow, "Score multiplier must be greater than zero."); + return; + } + + updated = EQ::ItemPower::SetMultiplierOverride(database, item_id, multiplier); + } + else if (field == "bonus") { + if (!Strings::IsNumber(value)) { + c->Message(Chat::Yellow, "Flat score bonus must be numeric."); + return; + } + + updated = EQ::ItemPower::SetFlatBonusOverride(database, item_id, Strings::ToInt(value)); + } + else if (field == "notes") { + std::string notes = sep->argplus[4] ? sep->argplus[4] : ""; + Strings::Trim(notes); + updated = EQ::ItemPower::SetOverrideNotes(database, item_id, notes); + } + else { + SendItemScoreUsage(c); + return; + } + + if (!updated) { + c->Message(Chat::Red, "Failed to update item power override for item [{}].", item_id); + return; + } + + c->Message(Chat::White, "Updated item power override for [{}] {}.", item_id, database.CreateItemLink(item_id)); + if (field != "notes") { + RecalculateItem(c, *item, true); + } + } +} + +void command_itemscore(Client *c, const Seperator *sep) +{ + const auto action = Strings::ToLower(GetArg(sep, 1)); + if (action.empty() || action == "help") { + SendItemScoreUsage(c); + return; + } + + if (action == "init") { + if (EQ::ItemPower::EnsureSchema(database)) { + c->Message(Chat::White, "item_power schema is ready."); + } + else { + c->Message(Chat::Red, "item_power schema initialization failed."); + } + return; + } + + if (action == "audit") { + const auto limit = GetArg(sep, 2).empty() ? 10 : Strings::ToUnsignedInt(GetArg(sep, 2), 10); + AuditScores(c, limit); + return; + } + + if (action == "recalc" && Strings::ToLower(GetArg(sep, 2)) == "all") { + RecalculateAll(c); + return; + } + + if (action == "override") { + OverrideScore(c, sep); + return; + } + + uint32 item_id = 0; + const auto *item = GetItem(c, GetArg(sep, 2), item_id); + if (!item) { + return; + } + + if (action == "show") { + SendStoredScore(c, *item); + } + else if (action == "recalc") { + RecalculateItem(c, *item, true); + } + else if (action == "explain") { + ExplainItem(c, *item); + } + else if (action == "clearoverride") { + if (!EQ::ItemPower::ClearOverride(database, item_id)) { + c->Message(Chat::Red, "Failed to clear item power override for item [{}].", item_id); + return; + } + + c->Message(Chat::White, "Cleared item power override for [{}] {}.", item_id, database.CreateItemLink(item_id)); + RecalculateItem(c, *item, true); + } + else if (action == "view") { + std::unique_ptr inst(database.CreateItem(item, 1)); + if (!inst) { + c->Message(Chat::Red, "Unable to create a view packet for item [{}].", item_id); + return; + } + + c->SendItemPacket(0, inst.get(), ItemPacketViewLink); + } + else { + SendItemScoreUsage(c); + } +} diff --git a/zone/gm_commands/list.cpp b/zone/gm_commands/list.cpp index 22607ec4ec..e7d5f6f403 100755 --- a/zone/gm_commands/list.cpp +++ b/zone/gm_commands/list.cpp @@ -17,6 +17,7 @@ */ #include "zone/client.h" #include "zone/command.h" +#include "zone/bot.h" #include "zone/corpse.h" #include "zone/doors.h" #include "zone/object.h" diff --git a/zone/gm_commands/multiclass.cpp b/zone/gm_commands/multiclass.cpp new file mode 100644 index 0000000000..06295939c2 --- /dev/null +++ b/zone/gm_commands/multiclass.cpp @@ -0,0 +1,15 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. +*/ +#include "zone/multiclass_manager.h" + +void command_multiclass(Client *c, const Seperator *sep) +{ + multiclass_manager.HandleCommand(c, sep); +} diff --git a/zone/gm_commands/multiclass_ui.cpp b/zone/gm_commands/multiclass_ui.cpp new file mode 100644 index 0000000000..ab290ae280 --- /dev/null +++ b/zone/gm_commands/multiclass_ui.cpp @@ -0,0 +1,16 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. +*/ +#include "zone/multiclass_manager.h" + +void command_multiclass_ui(Client *c, const Seperator *sep) +{ + multiclass_manager.HandleNativeCommand(c, sep); +} + diff --git a/zone/item_rarity_manager.cpp b/zone/item_rarity_manager.cpp new file mode 100644 index 0000000000..a46aedef2e --- /dev/null +++ b/zone/item_rarity_manager.cpp @@ -0,0 +1,407 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTIBILITY 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, see . +*/ +#include "item_rarity_manager.h" + +#include "common/eq_constants.h" +#include "common/item_data.h" +#include "common/item_instance.h" +#include "common/say_link.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/zonedb.h" + +#include + +namespace { + constexpr const char *kItemRarityTable = "item_rarity"; + + int schema_ready = -1; + + void SetSchemaReady(bool ready) + { + schema_ready = ready ? 1 : 0; + } + + ItemRarity ClampRarity(uint8 rarity) + { + if (rarity > static_cast(ItemRarity::Unique)) { + return ItemRarity::Common; + } + + return static_cast(rarity); + } + + std::string ItemName(uint32 item_id) + { + const auto *item = database.GetItem(item_id); + if (!item) { + return fmt::format("Item {}", item_id); + } + + return item->Name; + } + + std::string ItemName(const EQ::ItemInstance *inst) + { + if (!inst || !inst->GetItem()) { + return "Unknown Item"; + } + + return inst->GetItem()->Name; + } +} + +bool ItemRarityManager::EnsureSchema() +{ + const auto results = database.QueryDatabase( + "CREATE TABLE IF NOT EXISTS `item_rarity` (" + "`item_id` INT UNSIGNED NOT NULL," + "`rarity` TINYINT UNSIGNED NOT NULL DEFAULT 0," + "`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," + "PRIMARY KEY (`item_id`)," + "CONSTRAINT `item_rarity_rarity_chk` CHECK (`rarity` BETWEEN 0 AND 4)" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;" + ); + + SetSchemaReady(results.Success()); + return results.Success(); +} + +bool ItemRarityManager::SchemaReady() +{ + if (schema_ready != -1) { + return schema_ready == 1; + } + + const bool ready = database.DoesTableExist(kItemRarityTable); + SetSchemaReady(ready); + return ready; +} + +bool ItemRarityManager::TryParseRarity(const std::string &value, ItemRarity &rarity) +{ + const auto lowered = Strings::ToLower(value); + + if (Strings::IsNumber(lowered)) { + const auto parsed = Strings::ToUnsignedInt(lowered); + if (parsed <= static_cast(ItemRarity::Unique)) { + rarity = static_cast(parsed); + return true; + } + + return false; + } + + if (lowered == "common") { + rarity = ItemRarity::Common; + return true; + } + + if (lowered == "uncommon") { + rarity = ItemRarity::Uncommon; + return true; + } + + if (lowered == "rare") { + rarity = ItemRarity::Rare; + return true; + } + + if (lowered == "legendary") { + rarity = ItemRarity::Legendary; + return true; + } + + if (lowered == "unique") { + rarity = ItemRarity::Unique; + return true; + } + + return false; +} + +const char *ItemRarityManager::RarityName(ItemRarity rarity) +{ + switch (rarity) { + case ItemRarity::Common: + return "Common"; + case ItemRarity::Uncommon: + return "Uncommon"; + case ItemRarity::Rare: + return "Rare"; + case ItemRarity::Legendary: + return "Legendary"; + case ItemRarity::Unique: + return "Unique"; + } + + return "Common"; +} + +const char *ItemRarityManager::RarityColorHex(ItemRarity rarity) +{ + switch (rarity) { + case ItemRarity::Common: + return "#F0F0F0"; + case ItemRarity::Uncommon: + return "#66FF66"; + case ItemRarity::Rare: + return "#00FFFF"; + case ItemRarity::Legendary: + return "#FFD15C"; + case ItemRarity::Unique: + return "#C080FF"; + } + + return "#F0F0F0"; +} + +uint16 ItemRarityManager::RarityChatColor(ItemRarity rarity) +{ + switch (rarity) { + case ItemRarity::Common: + return Chat::White; + case ItemRarity::Uncommon: + return Chat::Green; + case ItemRarity::Rare: + return Chat::Cyan; + case ItemRarity::Legendary: + return Chat::Yellow; + case ItemRarity::Unique: + return Chat::Magenta; + } + + return Chat::White; +} + +bool ItemRarityManager::TryGetRarity(uint32 item_id, ItemRarity &rarity) +{ + if (!item_id || !SchemaReady()) { + return false; + } + + auto results = database.QueryDatabase( + fmt::format( + "SELECT `rarity` FROM `{}` WHERE `item_id` = {} LIMIT 1", + kItemRarityTable, + item_id + ) + ); + + if (!results.Success() || !results.RowCount()) { + return false; + } + + auto row = results.begin(); + if (!row[0]) { + return false; + } + + rarity = ClampRarity(static_cast(Strings::ToUnsignedInt(row[0]))); + return true; +} + +bool ItemRarityManager::SetRarity(uint32 item_id, ItemRarity rarity) +{ + if (!item_id || !database.GetItem(item_id)) { + return false; + } + + if (!SchemaReady() && !EnsureSchema()) { + return false; + } + + const auto results = database.QueryDatabase( + fmt::format( + "INSERT INTO `{}` (`item_id`, `rarity`, `updated_at`) VALUES ({}, {}, NOW()) " + "ON DUPLICATE KEY UPDATE `rarity` = VALUES(`rarity`), `updated_at` = NOW()", + kItemRarityTable, + item_id, + static_cast(rarity) + ) + ); + + return results.Success(); +} + +bool ItemRarityManager::ClearRarity(uint32 item_id) +{ + if (!item_id || !SchemaReady()) { + return false; + } + + const auto results = database.QueryDatabase( + fmt::format( + "DELETE FROM `{}` WHERE `item_id` = {}", + kItemRarityTable, + item_id + ) + ); + + return results.Success(); +} + +std::string ItemRarityManager::BuildItemLink(uint32 item_id) +{ + return BuildItemLink(item_id, nullptr); +} + +std::string ItemRarityManager::BuildItemLink(uint32 item_id, const char *link_text) +{ + const auto *item = database.GetItem(item_id); + if (!item) { + return fmt::format("Item {}", item_id); + } + + EQ::SayLinkEngine linker; + linker.SetLinkType(EQ::saylink::SayLinkItemData); + linker.SetItemData(item); + if (link_text && link_text[0]) { + linker.SetProxyText(link_text); + } + + return linker.GenerateLink(); +} + +std::string ItemRarityManager::BuildItemLink(const EQ::ItemInstance *inst) +{ + return BuildItemLink(inst, nullptr); +} + +std::string ItemRarityManager::BuildItemLink(const EQ::ItemInstance *inst, const char *link_text) +{ + if (!inst || !inst->GetItem()) { + return "Unknown Item"; + } + + EQ::SayLinkEngine linker; + linker.SetLinkType(EQ::saylink::SayLinkItemInst); + linker.SetItemInst(inst); + if (link_text && link_text[0]) { + linker.SetProxyText(link_text); + } + + return linker.GenerateLink(); +} + +std::string ItemRarityManager::BuildDecoratedLink(uint32 item_id, ItemRarity rarity) +{ + return fmt::format( + "[{}] {} {}", + RarityName(rarity), + ItemName(item_id), + BuildItemLink(item_id, "(inspect)") + ); +} + +std::string ItemRarityManager::BuildDecoratedLink(const EQ::ItemInstance *inst, ItemRarity rarity) +{ + return fmt::format( + "[{}] {} {}", + RarityName(rarity), + ItemName(inst), + BuildItemLink(inst, "(inspect)") + ); +} + +void ItemRarityManager::SendNativeRarity(Client *client, uint32 item_id, ItemRarity rarity) +{ + if (!client || !item_id) { + return; + } + + const auto *item = database.GetItem(item_id); + client->Message( + Chat::Black, + "%s", + fmt::format( + "ITEMRARITY|set|item_id={}|rarity={}|name={}", + item_id, + static_cast(rarity), + item ? item->Name : "" + ).c_str() + ); +} + +void ItemRarityManager::SendNativeRarityClear(Client *client, uint32 item_id) +{ + if (!client || !item_id) { + return; + } + + const auto *item = database.GetItem(item_id); + client->Message( + Chat::Black, + "%s", + fmt::format( + "ITEMRARITY|clear|item_id={}|name={}", + item_id, + item ? item->Name : "" + ).c_str() + ); +} + +void ItemRarityManager::SendRarityItemLink(Client *client, uint32 item_id) +{ + if (!client) { + return; + } + + ItemRarity rarity = ItemRarity::Common; + const bool has_rarity = TryGetRarity(item_id, rarity); + if (!has_rarity) { + client->Message( + Chat::White, + "%s", + fmt::format( + "{} has no explicit rarity tag. Default display is Common.", + BuildItemLink(item_id) + ).c_str() + ); + return; + } + + SendNativeRarity(client, item_id, rarity); + client->Message( + RarityChatColor(rarity), + "%s", + BuildDecoratedLink(item_id, rarity).c_str() + ); +} + +void ItemRarityManager::SendLootedItemMessage(Client *client, const EQ::ItemInstance *inst, const std::string &) +{ + if (!client || !inst || !inst->GetItem()) { + return; + } + + ItemRarity rarity = ItemRarity::Common; + if (!TryGetRarity(inst->GetItem()->ID, rarity)) { + return; + } + + SendNativeRarity(client, inst->GetItem()->ID, rarity); + client->Message( + RarityChatColor(rarity), + "%s", + fmt::format( + "Looted {}", + BuildDecoratedLink(inst, rarity) + ).c_str() + ); +} diff --git a/zone/item_rarity_manager.h b/zone/item_rarity_manager.h new file mode 100644 index 0000000000..9ab9f95e27 --- /dev/null +++ b/zone/item_rarity_manager.h @@ -0,0 +1,63 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTIBILITY 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, see . +*/ +#pragma once + +#include "common/types.h" + +#include + +class Client; + +namespace EQ { + class ItemInstance; +} + +enum class ItemRarity : uint8 { + Common = 0, + Uncommon = 1, + Rare = 2, + Legendary = 3, + Unique = 4 +}; + +class ItemRarityManager { +public: + static bool EnsureSchema(); + static bool SchemaReady(); + + static bool TryParseRarity(const std::string &value, ItemRarity &rarity); + static const char *RarityName(ItemRarity rarity); + static const char *RarityColorHex(ItemRarity rarity); + static uint16 RarityChatColor(ItemRarity rarity); + + static bool TryGetRarity(uint32 item_id, ItemRarity &rarity); + static bool SetRarity(uint32 item_id, ItemRarity rarity); + static bool ClearRarity(uint32 item_id); + + static std::string BuildItemLink(uint32 item_id); + static std::string BuildItemLink(uint32 item_id, const char *link_text); + static std::string BuildItemLink(const EQ::ItemInstance *inst); + static std::string BuildItemLink(const EQ::ItemInstance *inst, const char *link_text); + static std::string BuildDecoratedLink(uint32 item_id, ItemRarity rarity); + static std::string BuildDecoratedLink(const EQ::ItemInstance *inst, ItemRarity rarity); + + static void SendNativeRarity(Client *client, uint32 item_id, ItemRarity rarity); + static void SendNativeRarityClear(Client *client, uint32 item_id); + static void SendRarityItemLink(Client *client, uint32 item_id); + static void SendLootedItemMessage(Client *client, const EQ::ItemInstance *inst, const std::string &item_link); +}; diff --git a/zone/mob.cpp b/zone/mob.cpp index d55fa4ab78..8c2a755098 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1540,6 +1540,7 @@ void Mob::SendHPUpdate(bool force_update_all) b->spawn_id = GetID(); b->max_hp = CastToClient()->GetMaxHP() - itembonuses.HP; CastToClient()->QueuePacket(&p); + CastToClient()->SendNativeHpFixUpdate(force_update_all); ResetHPUpdateTimer(); diff --git a/zone/multiclass_manager.cpp b/zone/multiclass_manager.cpp new file mode 100644 index 0000000000..42f0ae8025 --- /dev/null +++ b/zone/multiclass_manager.cpp @@ -0,0 +1,3158 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. +*/ +#include "multiclass_manager.h" + +#include "common/classes.h" +#include "common/eq_packet_structs.h" +#include "common/item_data.h" +#include "common/item_instance.h" +#include "common/rulesys.h" +#include "common/seperator.h" +#include "common/skill_caps.h" +#include "common/spdat.h" +#include "common/strings.h" +#include "zone/client.h" +#include "zone/entity.h" +#include "zone/npc.h" +#include "zone/string_ids.h" +#include "zone/zone.h" +#include "zone/zonedb.h" + +#include "fmt/format.h" + +#include +#include +#include +#include +#include +#include +#include + +MulticlassManager multiclass_manager; + +namespace { + +uint32 ToUInt(const char *value) +{ + return value ? Strings::ToUnsignedInt(value) : 0; +} + +bool IsPetClass(uint8 class_id) +{ + return class_id == Class::Magician || class_id == Class::Necromancer || class_id == Class::Beastlord; +} + +bool IsTankClass(uint8 class_id) +{ + return class_id == Class::Warrior || class_id == Class::Paladin || class_id == Class::ShadowKnight; +} + +bool IsHealerClass(uint8 class_id) +{ + return class_id == Class::Cleric || class_id == Class::Druid || class_id == Class::Shaman; +} + +bool IsIntCasterClass(uint8 class_id) +{ + switch (class_id) { + case Class::ShadowKnight: + case Class::Bard: + case Class::Necromancer: + case Class::Wizard: + case Class::Magician: + case Class::Enchanter: + return true; + default: + return false; + } +} + +bool IsWisCasterClass(uint8 class_id) +{ + switch (class_id) { + case Class::Cleric: + case Class::Paladin: + case Class::Ranger: + case Class::Druid: + case Class::Shaman: + case Class::Beastlord: + return true; + default: + return false; + } +} + +bool IsBardClass(uint8 class_id) +{ + return class_id == Class::Bard; +} + +bool IsStrikerClass(uint8 class_id) +{ + return class_id == Class::Monk || class_id == Class::Rogue || class_id == Class::Berserker; +} + +bool ShouldAutoSeedSkill(EQ::skills::SkillType skill_id) +{ + if (skill_id < EQ::skills::Skill1HBlunt || skill_id > EQ::skills::HIGHEST_SKILL) { + return false; + } + + if (EQ::skills::IsTradeskill(skill_id) || EQ::skills::IsSpecializedSkill(skill_id)) { + return false; + } + + return true; +} + +bool IsBlockedMelodyControlSong(uint16 spell_id) +{ + return + IsCharmSpell(spell_id) || + IsFearSpell(spell_id) || + IsMesmerizeSpell(spell_id) || + IsStunSpell(spell_id) || + IsEffectInSpell(spell_id, SpellEffect::Root) || + IsEffectInSpell(spell_id, SpellEffect::Lull); +} + +Mob *ResolveMelodyTarget(Client *client, uint16 spell_id) +{ + if (!client || !IsValidSpell(spell_id)) { + return nullptr; + } + + if (IsBeneficialSpell(spell_id)) { + return client; + } + + auto *target = client->GetTarget(); + if (!target || target == client) { + return nullptr; + } + + if (!client->IsAttackAllowed(target)) { + return nullptr; + } + + return target; +} + +std::array ProfileSlots(const MulticlassManager::Profile &profile) +{ + return {profile.class_slot_1, profile.class_slot_2, profile.class_slot_3}; +} + +void AddUnique(std::vector &values, const std::string &value) +{ + if (std::find(values.begin(), values.end(), value) == values.end()) { + values.push_back(value); + } +} + +void AddRoleTags(std::vector &roles, uint8 class_id) +{ + if (IsTankClass(class_id)) { + AddUnique(roles, "Vanguard"); + } + + if (IsHealerClass(class_id)) { + AddUnique(roles, "Healer"); + } + + if (IsPetClass(class_id)) { + AddUnique(roles, "Pet"); + } + + if (IsIntCasterClass(class_id)) { + AddUnique(roles, "Arcane"); + } + + if (IsWisCasterClass(class_id)) { + AddUnique(roles, "Primal"); + } + + if (IsBardClass(class_id)) { + AddUnique(roles, "Bardic"); + } + + if (IsStrikerClass(class_id)) { + AddUnique(roles, "Striker"); + } +} + +std::string JoinValues(const std::vector &values, const std::string &delimiter) +{ + std::string joined; + for (const auto &value : values) { + if (!joined.empty()) { + joined += delimiter; + } + + joined += value; + } + + return joined; +} + +std::string PetOrderName(uint8 pet_order) +{ + switch (pet_order) { + case 0: + return "follow"; + case 1: + return "sit"; + case 2: + return "guard"; + case 3: + return "feign"; + default: + return "unknown"; + } +} + +std::string NormalizeLookupText(const std::string &value) +{ + std::string normalized; + normalized.reserve(value.size()); + for (const auto c : value) { + const auto value_char = static_cast(c); + if (std::isalnum(value_char)) { + normalized.push_back(static_cast(std::tolower(value_char))); + } + } + + return normalized; +} + +std::array SortedProfileSlots(const MulticlassManager::Profile &profile) +{ + auto slots = ProfileSlots(profile); + std::sort(slots.begin(), slots.end()); + return slots; +} + +std::string TrioKey(const MulticlassManager::Profile &profile) +{ + const auto slots = SortedProfileSlots(profile); + return fmt::format("{}-{}-{}", slots[0], slots[1], slots[2]); +} + +struct TrioTemplate { + const char *key; + const char *name; + const char *summary; + const char *bonus_path; +}; + +const TrioTemplate *FindExactTrioTemplate(const MulticlassManager::Profile &profile) +{ + static const std::array templates = {{ + {"11-13-15", "Grand Menagerie", "Three bonded pet lines fighting as one stable. Pet scaling and command strength are the core fantasy.", "Menagerie"}, + {"1-12-13", "Warbound Arcanum", "A battle shell with summoned pressure and arcane burst. Built to stand still and make the field burn.", "Arcanum"}, + {"9-12-16", "Spellblade Compact", "A caster-root melee killer with Rogue precision, Berserker violence, and Wizard finishers.", "Spellblade"}, + {"2-3-8", "Radiant Hymn", "A holy frontline chorus: plate, healing, and sustained Bard support in one identity.", "Hymn"}, + {"8-9-14", "Velvet Conspiracy", "Charm, song, and knives. This trio wins by controlling the room before the room notices.", "Conspiracy"}, + {"1-9-12", "Arcane Duelist Pact", "A duelist shell that mixes weapon pressure, Rogue openings, and Wizard punishment.", "Duelist"}, + {"2-6-10", "Verdant Synod", "Three healing traditions braided together for recovery, cures, and long-form survival.", "Synod"}, + {"1-2-3", "Aegis Covenant", "The pure defensive oath: Warrior durability, Cleric recovery, and Paladin protection.", "Aegis"}, + {"5-8-11", "Dirge of the Grave", "Shadow magic, undead pressure, and Bard cadence sharpened into a grim support engine.", "Dirge"}, + {"4-6-15", "Wildcall Pact", "Ranger, Druid, and Beastlord form a roaming primal kit with tracking, pet pressure, and nature magic.", "Wildcall"}, + }}; + + const auto key = TrioKey(profile); + for (const auto &entry : templates) { + if (key == entry.key) { + return &entry; + } + } + + return nullptr; +} + +uint8 UnlockedResonanceTiers(uint8 level) +{ + return std::min(6, level / 10); +} + +std::array BuildBonusTierNames(const MulticlassManager::Profile &profile) +{ + if (const auto *exact = FindExactTrioTemplate(profile)) { + const std::string path = exact->bonus_path; + if (path == "Menagerie") { + return {"Bonded Leashes", "Pack Savagery", "Triune Ward", "Shared Command", "Alpha Chorus", "Grand Menagerie"}; + } + if (path == "Arcanum") { + return {"Arcane Bulwark", "Summoner's Guard", "Battlecaster's Focus", "Elemental Reprisal", "War-Mage Tempo", "Arcanum Ascendant"}; + } + if (path == "Spellblade") { + return {"Hidden Edge", "Volatile Footwork", "Spellsteel Accuracy", "Rupture Window", "Executioner's Spark", "Compact Fulfilled"}; + } + if (path == "Hymn") { + return {"Aegis Verse", "Merciful Cadence", "Consecrated Guard", "Bright Refrain", "Unbroken Chorus", "Radiant Hymn"}; + } + if (path == "Conspiracy") { + return {"Soft Step", "Mesmeric Rhythm", "Knife in the Song", "Velvet Escape", "Mindbreak Flourish", "Perfect Conspiracy"}; + } + if (path == "Duelist") { + return {"Arcane Guard", "Opening Cut", "Riposte Spark", "Duelist's Read", "Killing Tempo", "Pact of the Last Word"}; + } + if (path == "Synod") { + return {"Green Accord", "Cleansing Root", "Patient Waters", "Triune Recovery", "Living Bastion", "Verdant Synod"}; + } + if (path == "Aegis") { + return {"Shield Oath", "Interlocking Plate", "Mercy Under Fire", "Blessed Rampart", "Last Stand Prayer", "Aegis Covenant"}; + } + if (path == "Dirge") { + return {"Grave Note", "Dread Cadence", "Bone Chorus", "Umbral Recovery", "Funeral Engine", "Dirge of the Grave"}; + } + if (path == "Wildcall") { + return {"Trail Sense", "Pack Step", "Living Thorn", "Primal Recovery", "Wildfire Hunt", "Wildcall Pact"}; + } + } + + uint8 pet_classes = 0; + bool has_tank = false; + bool has_healer = false; + bool has_bard = false; + bool has_striker = false; + bool has_int_caster = false; + bool has_wis_caster = false; + + for (const auto class_id : ProfileSlots(profile)) { + if (!IsPlayerClass(class_id)) { + continue; + } + + pet_classes += IsPetClass(class_id) ? 1 : 0; + has_tank = has_tank || IsTankClass(class_id); + has_healer = has_healer || IsHealerClass(class_id); + has_bard = has_bard || IsBardClass(class_id); + has_striker = has_striker || IsStrikerClass(class_id); + has_int_caster = has_int_caster || IsIntCasterClass(class_id); + has_wis_caster = has_wis_caster || IsWisCasterClass(class_id); + } + + if (pet_classes > 1) { + return {"Bonded Petcraft", "Shared Instinct", "Pack Ward", "Triple Command", "Alpha Pressure", "Menagerie Mastery"}; + } + if (has_bard) { + return {"Opening Verse", "Resonant Step", "Songguard", "Crescendo", "Echoing Tools", "Chorus of Three"}; + } + if (has_tank && has_healer) { + return {"Steady Oath", "Field Mending", "Guarded Recovery", "Line Holder", "Saving Hand", "Covenant Prime"}; + } + if (has_striker && (has_int_caster || has_wis_caster)) { + return {"Cutting Spark", "Quickened Hands", "Spellstep", "Exploit Weakness", "Lethal Focus", "Striker's Revelation"}; + } + if (has_healer && (has_int_caster || has_wis_caster)) { + return {"Twin Font", "Clear Mind", "Merciful Focus", "Harmonic Recovery", "Grace Under Fire", "Concord Ascendant"}; + } + + return {"Cross Training", "Shared Reserves", "Field Focus", "Class Harmony", "Trio Momentum", "Triad Ascendant"}; +} + +} + +void MulticlassManager::HandleCommand(Client *client, const Seperator *sep) +{ + if (!client || !sep) { + return; + } + + if (sep->argnum < 1) { + SendStatus(client); + return; + } + + if (!strcasecmp(sep->arg[1], "help")) { + SendHelp(client); + return; + } + + if (!strcasecmp(sep->arg[1], "status")) { + SendStatus(client); + return; + } + + if (!strcasecmp(sep->arg[1], "diag") || !strcasecmp(sep->arg[1], "diagnostics")) { + SendDiagnostics(client, sep->arg[2]); + return; + } + + if (!strcasecmp(sep->arg[1], "reweave")) { + Client *target_client = client; + if (client->GetTarget() && client->GetTarget()->IsClient()) { + target_client = client->GetTarget()->CastToClient(); + } + + if (!strcasecmp(sep->arg[2], "grant")) { + const auto grant_count = static_cast(std::min(255, Strings::ToUnsignedInt(sep->arg[3]))); + if (!grant_count || !EnsureProfile(target_client)) { + client->Message(Chat::White, "Usage: #multiclass reweave grant while targeting the character."); + return; + } + + auto profile = LoadProfile(target_client->CharacterID()); + profile.reweaves_available = std::min(255, profile.reweaves_available + grant_count); + if (SaveProfile(profile, "admin_reweave_grant")) { + client->Message( + Chat::White, + fmt::format( + "Granted {} reweave{} to {}. Available: {}.", + grant_count, + grant_count == 1 ? "" : "s", + target_client->GetCleanName(), + profile.reweaves_available + ).c_str() + ); + SendNativeSnapshot(target_client, "A reweave has been granted.", false, false); + } else { + client->Message(Chat::White, "Unable to grant Multiclass reweaves."); + } + return; + } + + std::string status; + const auto slot_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); + const auto class_id = ParseClassId(sep->arg[3]); + if (!ReweaveProfileSlot(target_client, slot_id, class_id, "admin_reweave", status)) { + client->Message(Chat::White, status.c_str()); + return; + } + + client->Message(Chat::White, status.c_str()); + RefreshAlternateAdvancementTable(target_client); + SendNativeSnapshot(target_client, status, false, false); + return; + } + + if (!strcasecmp(sep->arg[1], "set")) { + Client *target_client = client; + if (client->GetTarget() && client->GetTarget()->IsClient()) { + target_client = client->GetTarget()->CastToClient(); + } + + const auto class_slot_1 = ParseClassId(sep->arg[2]); + const auto class_slot_2 = ParseClassId(sep->arg[3]); + const auto class_slot_3 = ParseClassId(sep->arg[4]); + if (!class_slot_1 || !class_slot_2 || !class_slot_3) { + client->Message(Chat::White, "Usage: #multiclass set . Classes may be ids or names."); + return; + } + + if (SetProfile(target_client, class_slot_1, class_slot_2, class_slot_3, "admin")) { + client->Message( + Chat::White, + fmt::format( + "Multiclass trio set for {}: {} / {} / {}.", + target_client->GetCleanName(), + ClassName(class_slot_1, target_client->GetLevel()), + ClassName(class_slot_2, target_client->GetLevel()), + ClassName(class_slot_3, target_client->GetLevel()) + ).c_str() + ); + SendStatus(client); + RefreshAlternateAdvancementTable(target_client); + SendNativeSnapshot(target_client, "Trio updated. Spellbook levels refreshed.", false, false); + } else { + client->Message(Chat::White, "Unable to set Multiclass trio profile."); + } + return; + } + + if ( + !strcasecmp(sep->arg[1], "window") || + !strcasecmp(sep->arg[1], "ui") || + !strcasecmp(sep->arg[1], "native") + ) { + SendNativeSnapshot(client); + return; + } + + SendHelp(client); +} + +void MulticlassManager::HandleNativeCommand(Client *client, const Seperator *sep) +{ + if (!client || !sep) { + return; + } + + if ( + sep->argnum < 1 || + !strcasecmp(sep->arg[1], "status") || + !strcasecmp(sep->arg[1], "refresh") || + !strcasecmp(sep->arg[1], "open") || + !strcasecmp(sep->arg[1], "window") + ) { + RefreshAlternateAdvancementTable(client); + SendNativeSnapshot(client); + return; + } + + if (!strcasecmp(sep->arg[1], "pets") || !strcasecmp(sep->arg[1], "petwindow") || !strcasecmp(sep->arg[1], "petui")) { + SendNativeSnapshot(client, "Pet console refreshed.", false, true); + return; + } + + if (!strcasecmp(sep->arg[1], "melody") || !strcasecmp(sep->arg[1], "bardmelody") || !strcasecmp(sep->arg[1], "songui")) { + std::string status; + bool show_melody_window = false; + HandleNativeMelodyCommand(client, sep, status, show_melody_window); + SendNativeSnapshot(client, status, false, false); + SendNativeBardMelody(client, show_melody_window); + return; + } + + if ( + !strcasecmp(sep->arg[1], "disc") || + !strcasecmp(sep->arg[1], "discs") || + !strcasecmp(sep->arg[1], "discipline") || + !strcasecmp(sep->arg[1], "disciplines") || + !strcasecmp(sep->arg[1], "combat") || + !strcasecmp(sep->arg[1], "combatability") + ) { + std::string status; + bool show_discipline_window = false; + HandleNativeDisciplineCommand(client, sep, status, show_discipline_window); + SendNativeSnapshot(client, status, false, false); + SendNativeDisciplines(client, show_discipline_window, status); + return; + } + + if (!strcasecmp(sep->arg[1], "choose") || !strcasecmp(sep->arg[1], "lock")) { + const auto class_slot_2 = ParseClassId(sep->arg[2]); + const auto class_slot_3 = ParseClassId(sep->arg[3]); + std::string status; + if (!SetProfileFromNative(client, class_slot_2, class_slot_3, status)) { + SendNativeSnapshot(client, status); + return; + } + + RefreshAlternateAdvancementTable(client); + SendNativeSnapshot(client, "Trio locked. Camp once if the stock client needs to rebuild class windows."); + return; + } + + if (!strcasecmp(sep->arg[1], "reweave")) { + std::string status; + const auto slot_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); + const auto class_id = ParseClassId(sep->arg[3]); + if (!ReweaveProfileSlot(client, slot_id, class_id, "native_reweave", status)) { + SendNativeSnapshot(client, status); + return; + } + + RefreshAlternateAdvancementTable(client); + SendNativeSnapshot(client, status); + return; + } + + if (!strcasecmp(sep->arg[1], "help")) { + SendNativeSnapshot(client, "Choose two different added classes, then lock the trio."); + return; + } + + if (!strcasecmp(sep->arg[1], "pet") || !strcasecmp(sep->arg[1], "petcmd")) { + std::string status; + HandleNativePetCommand(client, sep, status); + SendNativeSnapshot(client, status, false, true); + return; + } + + SendNativeSnapshot(client, "Unsupported Multiclass UI request."); +} + +bool MulticlassManager::EnsureProfile(Client *client) +{ + if (!client || !client->CharacterID() || !IsPlayerClass(client->GetClass()) || !SchemaAvailable()) { + return false; + } + + const uint32 character_id = client->CharacterID(); + const uint8 class_id = client->GetClass(); + const auto class_name = Strings::Escape(ClassName(class_id, client->GetLevel())); + const auto trio_name = Strings::Escape(fmt::format("{} Triad", class_name)); + + auto results = database.QueryDatabase( + fmt::format( + "INSERT INTO `custom_multiclass_profiles` " + "(`character_id`, `class_slot_1`, `class_slot_2`, `class_slot_3`, `trio_name`, `resonance_key`, `multiple_pets_enabled`, `locked`, `reweaves_available`, `created_at`, `updated_at`) " + "VALUES ({}, {}, 0, 0, '{}', '', 1, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()) " + "ON DUPLICATE KEY UPDATE " + "`class_slot_1` = IF(`class_slot_1` = 0, VALUES(`class_slot_1`), `class_slot_1`), " + "`trio_name` = IF(`trio_name` = '', VALUES(`trio_name`), `trio_name`), " + "`updated_at` = VALUES(`updated_at`)", + character_id, + class_id, + trio_name + ) + ); + + if (results.Success()) { + profile_cache_.erase(character_id); + return true; + } + + return false; +} + +MulticlassManager::Profile MulticlassManager::LoadProfile(uint32 character_id) +{ + Profile profile; + if (!character_id) { + return profile; + } + + const auto cached_profile = profile_cache_.find(character_id); + if (cached_profile != profile_cache_.end()) { + return cached_profile->second; + } + + if (!SchemaAvailable()) { + return profile; + } + + auto results = database.QueryDatabase( + fmt::format( + "SELECT `character_id`, `class_slot_1`, `class_slot_2`, `class_slot_3`, `trio_name`, `resonance_key`, " + "`multiple_pets_enabled`, `locked`, `reweaves_available` " + "FROM `custom_multiclass_profiles` WHERE `character_id` = {} LIMIT 1", + character_id + ) + ); + + if (!results.Success() || !results.RowCount()) { + if (results.Success()) { + profile.character_id = character_id; + profile_cache_[character_id] = profile; + } + + return profile; + } + + auto row = results.begin(); + profile.character_id = ToUInt(row[0]); + profile.class_slot_1 = static_cast(ToUInt(row[1])); + profile.class_slot_2 = static_cast(ToUInt(row[2])); + profile.class_slot_3 = static_cast(ToUInt(row[3])); + profile.trio_name = row[4] ? row[4] : ""; + profile.resonance_key = row[5] ? row[5] : ""; + profile.multiple_pets_enabled = ToUInt(row[6]) != 0; + profile.locked = ToUInt(row[7]) != 0; + profile.reweaves_available = static_cast(ToUInt(row[8])); + + if (profile.trio_name.empty()) { + profile.trio_name = BuildTrioName(profile); + } + + profile_cache_[character_id] = profile; + return profile; +} + +bool MulticlassManager::SetProfile(Client *client, uint8 class_slot_1, uint8 class_slot_2, uint8 class_slot_3, const std::string &source) +{ + if ( + !client || + !client->CharacterID() || + !IsPlayerClass(class_slot_1) || + !IsPlayerClass(class_slot_2) || + !IsPlayerClass(class_slot_3) || + !SchemaAvailable() + ) { + return false; + } + + if (class_slot_1 == class_slot_2 || class_slot_1 == class_slot_3 || class_slot_2 == class_slot_3) { + return false; + } + + Profile profile; + profile.character_id = client->CharacterID(); + profile.class_slot_1 = class_slot_1; + profile.class_slot_2 = class_slot_2; + profile.class_slot_3 = class_slot_3; + profile.multiple_pets_enabled = true; + profile.locked = true; + profile.reweaves_available = 0; + profile.trio_name = BuildTrioName(profile); + profile.resonance_key = TrioKey(profile); + + if (!SaveProfile(profile, source)) { + return false; + } + + AuditProfile(profile, source); + SeedEligibleSkills(client, true); + return true; +} + +bool MulticlassManager::HasClass(uint32 character_id, uint8 class_id) +{ + if (!IsPlayerClass(class_id)) { + return false; + } + + const auto profile = LoadProfile(character_id); + return profile.class_slot_1 == class_id || profile.class_slot_2 == class_id || profile.class_slot_3 == class_id; +} + +bool MulticlassManager::HasClass(const Client *client, uint8 class_id) +{ + if (!client || !IsPlayerClass(class_id)) { + return false; + } + + const auto slots = GetClassSlots(client); + return slots[0] == class_id || slots[1] == class_id || slots[2] == class_id; +} + +bool MulticlassManager::HasMultiplePetProfile(uint32 character_id) +{ + const auto profile = LoadProfile(character_id); + if (!profile.multiple_pets_enabled) { + return false; + } + + const std::array slots = {profile.class_slot_1, profile.class_slot_2, profile.class_slot_3}; + uint8 pet_classes = 0; + for (const auto class_id : slots) { + if (IsPetClass(class_id)) { + pet_classes++; + } + } + + return pet_classes > 1; +} + +uint8 MulticlassManager::GetPetRosterLimit(const Client *client) +{ + if (!client || !client->CharacterID()) { + return 1; + } + + const auto profile = LoadProfile(client->CharacterID()); + if (!profile.multiple_pets_enabled || !profile.locked) { + return 1; + } + + uint8 pet_classes = 0; + for (const auto class_id : GetClassSlots(client)) { + pet_classes += IsPetClass(class_id) ? 1 : 0; + } + + if (!pet_classes) { + return 1; + } + + return std::min(3, pet_classes); +} + +std::vector MulticlassManager::GetPetRoster(const Client *client) +{ + std::vector pets; + if (!client) { + return pets; + } + + for (const auto &entry : entity_list.GetNPCList()) { + auto *npc = entry.second; + if ( + !npc || + npc->GetOwnerID() != client->GetID() || + !npc->IsPet() || + !npc->GetPetSpellID() + ) { + continue; + } + + pets.push_back(npc); + } + + std::sort( + pets.begin(), + pets.end(), + [](const Mob *left, const Mob *right) { + return left && right && left->GetID() < right->GetID(); + } + ); + + return pets; +} + +std::vector MulticlassManager::GetSecondaryPetRoster(Client *client) +{ + std::vector pets; + if (!client || GetPetRosterLimit(client) <= 1) { + return pets; + } + + auto *primary_pet = client->GetPet(); + for (auto *pet : GetPetRoster(client)) { + if (!pet || pet == primary_pet || pet->IsCharmed()) { + continue; + } + + pets.push_back(pet); + } + + return pets; +} + +bool MulticlassManager::IsPetRosterMember(const Client *client, Mob *pet) +{ + if ( + !client || + !pet || + !client->CharacterID() || + GetPetRosterLimit(client) <= 1 || + pet->GetOwnerID() != client->GetID() || + !pet->IsNPC() || + !pet->IsPet() + ) { + return false; + } + + auto *npc = pet->CastToNPC(); + return npc && npc->GetPetSpellID(); +} + +bool MulticlassManager::CanCreateAdditionalPet(Client *client) +{ + if (!client) { + return false; + } + + auto roster = GetPetRoster(client); + auto *current_pet = client->GetPet(); + if ( + current_pet && + std::find(roster.begin(), roster.end(), current_pet) == roster.end() + ) { + return false; + } + + return roster.size() < GetPetRosterLimit(client); +} + +bool MulticlassManager::RegisterPet(Client *client, Mob *pet) +{ + if (!client || !pet || !client->CharacterID()) { + return false; + } + + auto roster = GetPetRoster(client); + if (roster.empty()) { + roster.push_back(pet); + } + + auto focused_pet = GetFocusedPet(client); + if (!focused_pet || roster.size() <= 1) { + focused_pet_ids_[client->CharacterID()] = pet->GetID(); + focused_pet = pet; + } + + if (focused_pet && focused_pet->GetOwnerID() == client->GetID()) { + client->SetPetID(focused_pet->GetID()); + } else { + client->SetPetID(pet->GetID()); + } + + return true; +} + +MulticlassManager::ClassSlots MulticlassManager::GetClassSlots(const Client *client) +{ + ClassSlots slots = {0, 0, 0}; + if (!client || !IsPlayerClass(client->GetClass())) { + return slots; + } + + const auto profile = LoadProfile(client->CharacterID()); + slots[0] = IsPlayerClass(profile.class_slot_1) ? profile.class_slot_1 : client->GetClass(); + slots[1] = IsPlayerClass(profile.class_slot_2) ? profile.class_slot_2 : 0; + slots[2] = IsPlayerClass(profile.class_slot_3) ? profile.class_slot_3 : 0; + + return slots; +} + +uint32 MulticlassManager::GetClassMask(const Client *client) +{ + uint32 mask = 0; + for (const auto class_id : GetClassSlots(client)) { + if (IsPlayerClass(class_id)) { + mask |= GetPlayerClassBit(class_id); + } + } + + return mask; +} + +uint32 MulticlassManager::GetAAClassMask(const Client *client) +{ + uint32 mask = 0; + for (const auto class_id : GetClassSlots(client)) { + if (IsPlayerClass(class_id)) { + mask |= (1 << class_id); + } + } + + return mask; +} + +uint8 MulticlassManager::GetBestSpellLevel(const Client *client, uint16 spell_id) +{ + if (!client || !IsValidSpell(spell_id)) { + return 255; + } + + uint8 best_level = 255; + for (const auto class_id : GetClassSlots(client)) { + if (!IsPlayerClass(class_id)) { + continue; + } + + best_level = std::min(best_level, spells[spell_id].classes[class_id - 1]); + } + + return best_level; +} + +bool MulticlassManager::CanUseSpell(const Client *client, uint16 spell_id) +{ + const auto best_level = GetBestSpellLevel(client, spell_id); + return best_level != 255 && client && client->GetLevel() >= best_level; +} + +bool MulticlassManager::CanUseItem(const Client *client, const EQ::ItemInstance *inst) +{ + if (!client || !inst) { + return false; + } + + const auto *item = inst->GetItem(); + if (!item) { + return false; + } + + if (!(item->Races & GetPlayerRaceBit(client->GetBaseRace()))) { + return false; + } + + return (item->Classes & GetClassMask(client)) != 0; +} + +bool MulticlassManager::CanHaveSkill(const Client *client, EQ::skills::SkillType skill_id) +{ + return GetBestSkillCap(client, skill_id, RuleI(Character, MaxLevel)) > 0; +} + +uint16 MulticlassManager::GetBestSkillCap(const Client *client, EQ::skills::SkillType skill_id, uint8 level) +{ + if (!client) { + return 0; + } + + uint16 best_cap = 0; + for (const auto class_id : GetClassSlots(client)) { + if (!IsPlayerClass(class_id)) { + continue; + } + + const auto normalized_skill = NormalizeSkillForClass(client, class_id, skill_id); + best_cap = std::max(best_cap, static_cast(SkillCaps::Instance()->GetSkillCap(class_id, normalized_skill, level).cap)); + } + + return best_cap; +} + +uint8 MulticlassManager::GetBestSkillTrainLevel(const Client *client, EQ::skills::SkillType skill_id) +{ + if (!client) { + return 0; + } + + uint8 best_train_level = 0; + for (const auto class_id : GetClassSlots(client)) { + if (!IsPlayerClass(class_id)) { + continue; + } + + const auto normalized_skill = NormalizeSkillForClass(client, class_id, skill_id); + const auto train_level = SkillCaps::Instance()->GetSkillTrainLevel(class_id, normalized_skill, RuleI(Character, MaxLevel)); + if (train_level && (!best_train_level || train_level < best_train_level)) { + best_train_level = train_level; + } + } + + return best_train_level; +} + +uint16 MulticlassManager::SeedEligibleSkills(Client *client, bool notify) +{ + if (!client || !client->CharacterID() || !SchemaAvailable() || !EnsureProfile(client)) { + return 0; + } + + const auto profile = LoadProfile(client->CharacterID()); + if ( + !profile.locked || + !IsPlayerClass(profile.class_slot_1) || + !IsPlayerClass(profile.class_slot_2) || + !IsPlayerClass(profile.class_slot_3) + ) { + return 0; + } + + std::vector seeded_names; + for (const auto &skill_entry : EQ::skills::GetSkillTypeMap()) { + const auto skill_id = skill_entry.first; + if (!ShouldAutoSeedSkill(skill_id) || client->GetRawSkill(skill_id) > 0) { + continue; + } + + const auto train_level = GetBestSkillTrainLevel(client, skill_id); + if (!train_level || client->GetLevel() < train_level) { + continue; + } + + if (!GetBestSkillCap(client, skill_id, client->GetLevel())) { + continue; + } + + client->SetSkill(skill_id, 1); + seeded_names.emplace_back(skill_entry.second); + } + + if (notify && !seeded_names.empty()) { + std::vector preview; + const auto preview_count = std::min(seeded_names.size(), 6); + for (size_t i = 0; i < preview_count; ++i) { + preview.emplace_back(seeded_names[i]); + } + + const auto extra_count = seeded_names.size() - preview_count; + client->Message( + Chat::Skills, + fmt::format( + "Multiclass unlocked {} class skill{}: {}{}.", + seeded_names.size(), + seeded_names.size() == 1 ? "" : "s", + JoinValues(preview, ", "), + extra_count ? fmt::format(", and {} more", extra_count) : "" + ).c_str() + ); + } + + return static_cast(seeded_names.size()); +} + +void MulticlassManager::ApplyTrioBonuses(Client *client, StatBonuses *bonuses) +{ + if (!client || !bonuses || !client->CharacterID() || !SchemaAvailable()) { + return; + } + + const auto profile = LoadProfile(client->CharacterID()); + if ( + !profile.locked || + !IsPlayerClass(profile.class_slot_1) || + !IsPlayerClass(profile.class_slot_2) || + !IsPlayerClass(profile.class_slot_3) + ) { + return; + } + + const auto tiers = UnlockedResonanceTiers(client->GetLevel()); + if (!tiers) { + return; + } + + uint8 pet_classes = 0; + bool has_tank = false; + bool has_healer = false; + bool has_int_caster = false; + bool has_wis_caster = false; + bool has_bard = false; + bool has_striker = false; + + for (const auto class_id : ProfileSlots(profile)) { + if (!IsPlayerClass(class_id)) { + continue; + } + + pet_classes += IsPetClass(class_id) ? 1 : 0; + has_tank = has_tank || IsTankClass(class_id); + has_healer = has_healer || IsHealerClass(class_id); + has_int_caster = has_int_caster || IsIntCasterClass(class_id); + has_wis_caster = has_wis_caster || IsWisCasterClass(class_id); + has_bard = has_bard || IsBardClass(class_id); + has_striker = has_striker || IsStrikerClass(class_id); + } + + const int level = client->GetLevel(); + const int tier_value = tiers; + + bonuses->HP += level * tier_value * 2; + bonuses->ATK += tier_value * 3; + bonuses->AC += tier_value * 3; + + if (has_int_caster || has_wis_caster || has_bard) { + bonuses->Mana += level * tier_value * 2; + bonuses->ManaRegen += tier_value; + bonuses->ChannelChanceSpells += tier_value; + } + + if (has_tank || has_striker) { + bonuses->Endurance += level * tier_value * 2; + bonuses->EnduranceRegen += tier_value; + } + + if (has_tank) { + bonuses->HP += level * tier_value * 2; + bonuses->AC += tier_value * 6; + bonuses->MeleeMitigation += tier_value; + bonuses->ShieldBlock += tier_value; + } + + if (has_healer) { + bonuses->HealAmt += tier_value * 4; + bonuses->HealRate += tier_value; + bonuses->CriticalHealChance += tier_value; + bonuses->ManaRegen += tier_value; + } + + if (has_int_caster) { + bonuses->SpellDmg += tier_value * 4; + bonuses->CriticalSpellChance += tier_value; + bonuses->Mana += level * tier_value; + } + + if (has_wis_caster) { + bonuses->ManaRegen += tier_value; + bonuses->WIS += tier_value * 2; + bonuses->HealAmt += tier_value * 2; + } + + if (has_striker) { + bonuses->ATK += tier_value * 5; + bonuses->HitChance += tier_value * 10; + bonuses->CriticalHitChance[EQ::skills::HIGHEST_SKILL + 1] += tier_value; + bonuses->SkillDamageAmount[EQ::skills::SkillBackstab] += tier_value * 2; + bonuses->SkillDamageAmount[EQ::skills::SkillFrenzy] += tier_value * 2; + bonuses->SkillDamageAmount2[EQ::skills::SkillBackstab] += tier_value; + bonuses->SkillDamageAmount2[EQ::skills::SkillFrenzy] += tier_value; + } + + if (pet_classes) { + bonuses->PetMaxHP += pet_classes * tier_value * 2; + bonuses->PetCriticalHit += pet_classes * tier_value; + bonuses->Pet_Add_Atk += pet_classes * tier_value * 5; + bonuses->PetMeleeMitigation += pet_classes * tier_value * 2; + } + + if (has_bard) { + bonuses->singingMod += tier_value; + bonuses->brassMod += tier_value; + bonuses->percussionMod += tier_value; + bonuses->windMod += tier_value; + bonuses->stringedMod += tier_value; + bonuses->songModCap += tier_value; + bonuses->SongRange += tier_value * 5; + } + + if (const auto *exact = FindExactTrioTemplate(profile)) { + const std::string path = exact->bonus_path; + if (path == "Menagerie") { + bonuses->PetMaxHP += tier_value * 4; + bonuses->PetCriticalHit += tier_value * 2; + bonuses->Pet_Add_Atk += tier_value * 8; + if (tiers >= 4) { + bonuses->GivePetGroupTarget = true; + } + } else if (path == "Arcanum") { + bonuses->PercentMaxHPChange += tier_value * 50; + bonuses->SpellDmg += tier_value * 3; + bonuses->DamageShield += tier_value * 2; + } else if (path == "Spellblade") { + bonuses->SkillDamageAmount[EQ::skills::SkillBackstab] += tier_value * 3; + bonuses->SkillDamageAmount[EQ::skills::SkillFrenzy] += tier_value * 3; + bonuses->CriticalSpellChance += tier_value; + bonuses->ChannelChanceSpells += tier_value * 2; + } else if (path == "Hymn") { + bonuses->HealRate += tier_value; + bonuses->MeleeMitigation += tier_value; + bonuses->SongRange += tier_value * 5; + } else if (path == "Conspiracy") { + bonuses->AvoidMeleeChance += tier_value * 2; + bonuses->DodgeChance += tier_value; + bonuses->ChannelChanceSpells += tier_value * 2; + bonuses->SpellDmg += tier_value * 2; + } else if (path == "Duelist") { + bonuses->RiposteChance += tier_value; + bonuses->DodgeChance += tier_value; + bonuses->SpellDmg += tier_value * 2; + bonuses->HitChance += tier_value * 6; + } else if (path == "Synod") { + bonuses->HealRate += tier_value * 2; + bonuses->ManaRegen += tier_value * 2; + bonuses->CriticalHealChance += tier_value; + } else if (path == "Aegis") { + bonuses->AC += tier_value * 8; + bonuses->MeleeMitigation += tier_value * 2; + bonuses->HPRegen += tier_value; + } else if (path == "Dirge") { + bonuses->SpellDmg += tier_value * 3; + bonuses->Pet_Add_Atk += tier_value * 5; + bonuses->ManaRegen += tier_value; + } else if (path == "Wildcall") { + bonuses->PetCriticalHit += tier_value; + bonuses->HitChance += tier_value * 5; + bonuses->HPRegen += tier_value; + bonuses->ManaRegen += tier_value; + } + } +} + +std::string MulticlassManager::BuildTrioBonusSummary(Client *client) +{ + if (!client || !client->CharacterID() || !SchemaAvailable() || !EnsureProfile(client)) { + return "Resonance bonuses: profile unavailable."; + } + + const auto profile = LoadProfile(client->CharacterID()); + if (!profile.locked) { + return "Resonance bonuses unlock every 10 levels after the trio is locked."; + } + + const auto tiers = UnlockedResonanceTiers(client->GetLevel()); + const auto tier_names = BuildBonusTierNames(profile); + + std::vector active; + for (uint8 i = 0; i < tiers && i < tier_names.size(); ++i) { + active.emplace_back(fmt::format("L{} {}", (i + 1) * 10, tier_names[i])); + } + + if (active.empty()) { + return fmt::format("Resonance bonuses: 0/6 active. Next: L10 {}.", tier_names[0]); + } + + std::string summary = fmt::format("Resonance bonuses: {}/6 active: {}", tiers, JoinValues(active, ", ")); + if (tiers < tier_names.size()) { + summary += fmt::format(". Next: L{} {}", (tiers + 1) * 10, tier_names[tiers]); + } + + return summary + "."; +} + +bool MulticlassManager::IsIntCaster(const Client *client) +{ + for (const auto class_id : GetClassSlots(client)) { + if (IsIntCasterClass(class_id)) { + return true; + } + } + + return false; +} + +bool MulticlassManager::IsWisCaster(const Client *client) +{ + for (const auto class_id : GetClassSlots(client)) { + if (IsWisCasterClass(class_id)) { + return true; + } + } + + return false; +} + +bool MulticlassManager::IsBard(const Client *client) +{ + for (const auto class_id : GetClassSlots(client)) { + if (IsBardClass(class_id)) { + return true; + } + } + + return false; +} + +uint8 MulticlassManager::GetPrimaryIntCasterClass(const Client *client) +{ + for (const auto class_id : GetClassSlots(client)) { + if (IsIntCasterClass(class_id)) { + return class_id; + } + } + + return client ? client->GetClass() : Class::None; +} + +uint8 MulticlassManager::GetPrimaryWisCasterClass(const Client *client) +{ + for (const auto class_id : GetClassSlots(client)) { + if (IsWisCasterClass(class_id)) { + return class_id; + } + } + + return client ? client->GetClass() : Class::None; +} + +uint8 MulticlassManager::GetClientPresentationClass(const Client *client) +{ + if (!client || !IsPlayerClass(client->GetClass())) { + return Class::None; + } + + if (IsCasterClass(client->GetClass()) || IsSpellFighterClass(client->GetClass())) { + return client->GetClass(); + } + + for (const auto class_id : GetClassSlots(client)) { + if (IsCasterClass(class_id) || IsSpellFighterClass(class_id)) { + return class_id; + } + } + + return client->GetClass(); +} + +void MulticlassManager::SendNativeSpellLevelSnapshot(Client *client) +{ + if (!client) { + return; + } + + SendNativeSpellLevelPatch(client, GetClientPresentationClass(client)); +} + +void MulticlassManager::SendHelp(Client *client) +{ + client->Message(Chat::White, "Multiclass admin/native bridge commands:"); + client->Message(Chat::White, "#multiclass status - Show the target Multiclass trio profile."); + client->Message(Chat::White, "#multiclass set - Admin-set the target trio."); + client->Message(Chat::White, "#multiclass reweave grant - Admin-grant rare one-slot reweaves to the target."); + client->Message(Chat::White, "#multiclass reweave - Admin-test a one-slot reweave."); + client->Message(Chat::White, "#multiclass diag - Show capability masks and caster/skill diagnostics."); + client->Message(Chat::White, "#multiclass native - Send the native window snapshot contract."); + client->Message(Chat::White, "#mc pets - Open or refresh the standalone native pet console."); + client->Message(Chat::White, "#mc disc - Open or refresh the native Multiclass discipline bridge."); + client->Message(Chat::White, "Player flow should go through the native Multiclass UI, not typed commands."); +} + +void MulticlassManager::SendStatus(Client *client) +{ + if (!SchemaAvailable()) { + client->Message(Chat::White, "Multiclass tables are not installed. Run world database:updates for this feature."); + return; + } + + Client *target_client = client; + if (client->GetTarget() && client->GetTarget()->IsClient()) { + target_client = client->GetTarget()->CastToClient(); + } + + if (!EnsureProfile(target_client)) { + client->Message(Chat::White, "Multiclass profile is unavailable."); + return; + } + + const auto profile = LoadProfile(target_client->CharacterID()); + client->Message( + Chat::White, + fmt::format( + "Multiclass profile for {}: {} / {} / {} [{}]. Multiple pets: {}. Locked: {}. Reweaves: {}.", + target_client->GetCleanName(), + ClassName(profile.class_slot_1, target_client->GetLevel()), + ClassName(profile.class_slot_2, target_client->GetLevel()), + ClassName(profile.class_slot_3, target_client->GetLevel()), + profile.trio_name, + profile.multiple_pets_enabled ? "enabled" : "disabled", + profile.locked ? "yes" : "no", + profile.reweaves_available + ).c_str() + ); +} + +void MulticlassManager::SendDiagnostics(Client *client, const char *topic) +{ + if (!client) { + return; + } + + Client *target_client = client; + if (client->GetTarget() && client->GetTarget()->IsClient()) { + target_client = client->GetTarget()->CastToClient(); + } + + if (!EnsureProfile(target_client)) { + client->Message(Chat::White, "Multiclass profile is unavailable."); + return; + } + + const auto topic_value = topic ? Strings::ToLower(topic) : ""; + if (!topic_value.empty() && topic_value != "all") { + if (topic_value == "skills" || topic_value == "skill") { + uint16 eligible_count = 0; + uint16 active_count = 0; + uint16 seedable_count = 0; + std::vector missing_preview; + + for (const auto &skill_entry : EQ::skills::GetSkillTypeMap()) { + const auto skill_id = skill_entry.first; + if (!ShouldAutoSeedSkill(skill_id)) { + continue; + } + + const auto train_level = GetBestSkillTrainLevel(target_client, skill_id); + const auto cap = GetBestSkillCap(target_client, skill_id, target_client->GetLevel()); + if (!train_level || target_client->GetLevel() < train_level || !cap) { + continue; + } + + ++eligible_count; + if (target_client->GetRawSkill(skill_id) > 0) { + ++active_count; + } else { + ++seedable_count; + if (missing_preview.size() < 8) { + missing_preview.emplace_back(skill_entry.second); + } + } + } + + client->Message( + Chat::White, + fmt::format( + "Multiclass skill diagnostics for {}: {} active / {} eligible; {} ready to seed.", + target_client->GetCleanName(), + active_count, + eligible_count, + seedable_count + ).c_str() + ); + if (!missing_preview.empty()) { + client->Message(Chat::White, fmt::format("Ready preview: {}.", JoinValues(missing_preview, ", ")).c_str()); + } + return; + } + + if (topic_value == "spells" || topic_value == "spell") { + uint16 scribed_count = 0; + uint16 usable_count = 0; + uint16 off_presentation_count = 0; + const auto presentation_class = GetClientPresentationClass(target_client); + for (uint32 slot_id = 0; slot_id < EQ::spells::SPELLBOOK_SIZE; ++slot_id) { + const auto spell_id = target_client->GetPP().spell_book[slot_id]; + if (!IsValidSpell(spell_id)) { + continue; + } + + ++scribed_count; + const auto best_level = GetBestSpellLevel(target_client, spell_id); + if (best_level != 255 && target_client->GetLevel() >= best_level) { + ++usable_count; + if (IsPlayerClass(presentation_class) && spells[spell_id].classes[presentation_class - 1] == 255) { + ++off_presentation_count; + } + } + } + + client->Message( + Chat::White, + fmt::format( + "Multiclass spell diagnostics for {}: {} scribed, {} usable by trio, {} require native off-presentation display patches.", + target_client->GetCleanName(), + scribed_count, + usable_count, + off_presentation_count + ).c_str() + ); + return; + } + + if (topic_value == "discs" || topic_value == "disc" || topic_value == "disciplines") { + uint16 learned_count = 0; + uint16 usable_count = 0; + for (uint32 slot_id = 0; slot_id < MAX_PP_DISCIPLINES; ++slot_id) { + const auto spell_id = target_client->GetPP().disciplines.values[slot_id]; + if (!IsValidSpell(spell_id)) { + continue; + } + + ++learned_count; + if (CanUseSpell(target_client, spell_id)) { + ++usable_count; + } + } + + client->Message( + Chat::White, + fmt::format( + "Multiclass discipline diagnostics for {}: {} learned, {} usable by trio.", + target_client->GetCleanName(), + learned_count, + usable_count + ).c_str() + ); + return; + } + + if (topic_value == "aa" || topic_value == "aas") { + uint16 visible_count = 0; + uint16 learned_count = 0; + uint16 first_rank_purchase_count = 0; + uint16 grant_only_count = 0; + const auto aa_class_mask = GetAAClassMask(target_client); + for (const auto &aa_entry : zone->aa_abilities) { + auto *ability = aa_entry.second.get(); + if (!ability || !ability->first || !(ability->classes & aa_class_mask)) { + continue; + } + + if (!target_client->CanUseAlternateAdvancementRank(ability->first)) { + continue; + } + + ++visible_count; + if (ability->grant_only) { + ++grant_only_count; + } + + uint32 charges = 0; + if (target_client->GetAA(ability->first_rank_id, &charges)) { + ++learned_count; + } else if (target_client->CanPurchaseAlternateAdvancementRank(ability->first, false, true)) { + ++first_rank_purchase_count; + } + } + + client->Message( + Chat::White, + fmt::format( + "Multiclass AA diagnostics for {}: AA class mask {}, normal class mask {}.", + target_client->GetCleanName(), + aa_class_mask, + GetClassMask(target_client) + ).c_str() + ); + client->Message( + Chat::White, + fmt::format( + "AA window candidates: {} visible definitions, {} learned/profile entries, {} first ranks purchasable, {} grant-only.", + visible_count, + learned_count, + first_rank_purchase_count, + grant_only_count + ).c_str() + ); + client->Message( + Chat::White, + fmt::format( + "Learned AA packet guard: {} / {} profile entries used. Current first goal is visibility; full buyout needs separate cap testing.", + learned_count, + MAX_PP_AA_ARRAY + ).c_str() + ); + return; + } + + if (topic_value == "melody" || topic_value == "bard" || topic_value == "songs") { + client->Message(Chat::White, BuildBardMelodySummary(target_client).c_str()); + if (IsBard(target_client)) { + const auto slots = LoadBardMelody(target_client); + for (size_t i = 0; i < slots.size(); ++i) { + const auto spell_id = slots[i]; + client->Message( + Chat::White, + fmt::format( + "Melody slot {}: {}{}", + i + 1, + IsValidSpell(spell_id) ? spells[spell_id].name : "-", + IsValidSpell(spell_id) ? fmt::format(" ({})", spell_id) : "" + ).c_str() + ); + } + } + return; + } + + if (topic_value == "bonuses" || topic_value == "bonus" || topic_value == "resonance") { + client->Message(Chat::White, BuildTrioBonusSummary(target_client).c_str()); + const auto profile = LoadProfile(target_client->CharacterID()); + const auto metadata = BuildTrioMetadata(profile); + client->Message(Chat::White, fmt::format("Resonance identity: {}. Roles: {}.", metadata.resonance, metadata.roles).c_str()); + return; + } + + if (topic_value == "pets" || topic_value == "pet") { + const auto roster = GetPetRoster(target_client); + client->Message( + Chat::White, + fmt::format( + "Multiclass pet diagnostics for {}: {}/{} active roster pets. Focus: {}.", + target_client->GetCleanName(), + roster.size(), + GetPetRosterLimit(target_client), + GetFocusedPet(target_client) ? GetFocusedPet(target_client)->GetCleanName() : "-" + ).c_str() + ); + for (auto *pet : roster) { + if (!pet || !pet->IsNPC()) { + continue; + } + client->Message( + Chat::White, + fmt::format( + "Pet {} [{}]: order {}, hp {:.0f}, mana {:.0f}, taunt {}, hold {}, nocast {}.", + pet->GetCleanName(), + pet->GetID(), + PetOrderName(pet->GetPetOrder()), + pet->GetHPRatio(), + pet->GetManaRatio(), + pet->CastToNPC()->IsTaunting() ? "on" : "off", + (pet->IsHeld() || pet->IsGHeld()) ? "on" : "off", + pet->IsNoCast() ? "on" : "off" + ).c_str() + ); + } + return; + } + + if (topic_value == "items" || topic_value == "item") { + const auto class_mask = GetClassMask(target_client); + uint16 usable_equipped = 0; + uint16 blocked_equipped = 0; + for (int16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) { + const auto *inst = target_client->GetInv().GetItem(slot_id); + if (!inst) { + continue; + } + + if (CanUseItem(target_client, inst)) { + ++usable_equipped; + } else { + ++blocked_equipped; + } + } + + client->Message( + Chat::White, + fmt::format( + "Multiclass item diagnostics for {}: class mask {}, equipped usable {}, equipped blocked {}.", + target_client->GetCleanName(), + class_mask, + usable_equipped, + blocked_equipped + ).c_str() + ); + return; + } + + client->Message(Chat::White, "#multiclass diag topics: skills, spells, discs, aa, melody, bonuses, pets, items, all."); + return; + } + + const auto slots = GetClassSlots(target_client); + client->Message( + Chat::White, + fmt::format( + "Multiclass diagnostics for {}: slots [{} / {} / {}], class mask {}, AA mask {}.", + target_client->GetCleanName(), + ClassName(slots[0], target_client->GetLevel()), + ClassName(slots[1], target_client->GetLevel()), + ClassName(slots[2], target_client->GetLevel()), + GetClassMask(target_client), + GetAAClassMask(target_client) + ).c_str() + ); + client->Message( + Chat::White, + fmt::format( + "Client presentation class: {}. Base server class remains {}.", + ClassName(GetClientPresentationClass(target_client), target_client->GetLevel()), + ClassName(target_client->GetClass(), target_client->GetLevel()) + ).c_str() + ); + client->Message(Chat::White, BuildTrioBonusSummary(target_client).c_str()); + client->Message( + Chat::White, + fmt::format( + "Caster flags: INT={}, WIS={}, Bard={}. Skill samples: Meditate cap {}, Dual Wield cap {}, Defense cap {}.", + IsIntCaster(target_client) ? "yes" : "no", + IsWisCaster(target_client) ? "yes" : "no", + IsBard(target_client) ? "yes" : "no", + GetBestSkillCap(target_client, EQ::skills::SkillMeditate, target_client->GetLevel()), + GetBestSkillCap(target_client, EQ::skills::SkillDualWield, target_client->GetLevel()), + GetBestSkillCap(target_client, EQ::skills::SkillDefense, target_client->GetLevel()) + ).c_str() + ); +} + +void MulticlassManager::SendNativeSnapshot(Client *client, const std::string &status, bool show_window, bool show_pet_window) +{ + if (!SchemaAvailable()) { + client->Message(Chat::White, "Multiclass tables are not installed. Run world database:updates for this feature."); + return; + } + + if (!EnsureProfile(client)) { + client->Message(Chat::White, "Multiclass native snapshot is unavailable."); + return; + } + + const auto profile = LoadProfile(client->CharacterID()); + const auto presentation_class = GetClientPresentationClass(client); + const auto metadata = BuildTrioMetadata(profile); + const auto pet_roster = GetPetRoster(client); + auto *focused_pet = GetFocusedPet(client); + const auto focused_pet_id = focused_pet ? focused_pet->GetID() : 0; + const auto current_mana = std::max(0, client->GetMana()); + const auto max_mana = std::max(0, client->GetMaxMana()); + const auto current_endurance = std::max(0, client->GetEndurance()); + const auto max_endurance = std::max(0, client->GetMaxEndurance()); + const auto seeded_skills = SeedEligibleSkills(client, true); + std::string status_text = status.empty() ? + (profile.locked ? "Trio locked." : "Choose two added classes to lock your trio.") : + status; + if (seeded_skills > 0 && status.empty()) { + status_text = fmt::format("Unlocked {} Multiclass skill{}.", seeded_skills, seeded_skills == 1 ? "" : "s"); + } + + client->Message(Chat::White, "MULTICLASS|window|clear"); + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|profile|name={}|resonance={}|class1={}|class1_name={}|class2={}|class2_name={}|class3={}|class3_name={}|presentation={}|presentation_name={}|base={}|base_name={}|pets={}|locked={}|reweaves={}", + ProtocolValue(profile.trio_name), + ProtocolValue(profile.resonance_key.empty() ? TrioKey(profile) : profile.resonance_key), + profile.class_slot_1, + ProtocolValue(ClassName(profile.class_slot_1, client->GetLevel())), + profile.class_slot_2, + ProtocolValue(ClassName(profile.class_slot_2, client->GetLevel())), + profile.class_slot_3, + ProtocolValue(ClassName(profile.class_slot_3, client->GetLevel())), + presentation_class, + ProtocolValue(ClassName(presentation_class, client->GetLevel())), + client->GetClass(), + ProtocolValue(ClassName(client->GetClass(), client->GetLevel())), + profile.multiple_pets_enabled ? 1 : 0, + profile.locked ? 1 : 0, + profile.reweaves_available + ).c_str() + ); + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|vitals|mana={}|max_mana={}|endurance={}|max_endurance={}|class_mask={}|aa_mask={}|presentation={}|base={}", + current_mana, + max_mana, + current_endurance, + max_endurance, + GetClassMask(client), + GetAAClassMask(client), + presentation_class, + client->GetClass() + ).c_str() + ); + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|trio|roles={}|resonance={}|summary={}", + ProtocolValue(metadata.roles), + ProtocolValue(metadata.resonance), + ProtocolValue(metadata.summary) + ).c_str() + ); + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|skills|summary={}|unlocked={}", + ProtocolValue(BuildSkillSummary(client)), + seeded_skills + ).c_str() + ); + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|bonuses|summary={}", + ProtocolValue(BuildTrioBonusSummary(client)) + ).c_str() + ); + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|selection|can_choose={}|status={}", + profile.locked ? 0 : 1, + ProtocolValue(status_text) + ).c_str() + ); + SendNativeSpellLevelPatch(client, presentation_class); + SendNativeBardMelody(client, false); + SendNativeDisciplines(client, false); + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|pet_roster|mode=live|count={}|limit={}|focus={}|policy={}|control={}", + pet_roster.size(), + GetPetRosterLimit(client), + focused_pet_id, + ProtocolValue(metadata.pet_policy), + ProtocolValue(metadata.pet_control) + ).c_str() + ); + for (auto *pet : pet_roster) { + if (!pet || !pet->IsNPC()) { + continue; + } + + auto *pet_npc = pet->CastToNPC(); + auto *target = pet->GetTarget(); + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|pet|id={}|name={}|hp={:.0f}|mana={:.0f}|target={}|taunt={}|hold={}|spellhold={}|order={}|focused={}", + pet->GetID(), + ProtocolValue(pet->GetCleanName()), + pet->GetHPRatio(), + pet->GetManaRatio(), + ProtocolValue(target ? target->GetCleanName() : "-"), + pet_npc->IsTaunting() ? 1 : 0, + (pet->IsHeld() || pet->IsGHeld()) ? 1 : 0, + pet->IsNoCast() ? 1 : 0, + ProtocolValue(PetOrderName(pet->GetPetOrder())), + pet->GetID() == focused_pet_id ? 1 : 0 + ).c_str() + ); + } + if (show_window) { + client->Message(Chat::White, "MULTICLASS|window|show"); + } + + if (show_pet_window) { + client->Message(Chat::White, "MULTICLASS|pet_window|show"); + } +} + +void MulticlassManager::SendNativeSpellLevelPatch(Client *client, uint8 presentation_class) +{ + if (!client || !IsPlayerClass(presentation_class)) { + return; + } + + uint16 patched_count = 0; + client->Message(Chat::White, "MULTICLASS|spell_levels|begin"); + for (const auto spell_id_value : client->GetScribedSpells()) { + if (spell_id_value < 0 || spell_id_value > std::numeric_limits::max()) { + continue; + } + + const auto spell_id = static_cast(spell_id_value); + if (!IsValidSpell(spell_id)) { + continue; + } + + const auto best_level = GetBestSpellLevel(client, spell_id); + if (!best_level || best_level == 255) { + continue; + } + + if (spells[spell_id].classes[presentation_class - 1] == best_level) { + continue; + } + + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|spell_level|id={}|level={}|presentation={}", + spell_id, + best_level, + presentation_class + ).c_str() + ); + patched_count++; + } + + client->Message( + Chat::White, + fmt::format("MULTICLASS|spell_levels|end|count={}", patched_count).c_str() + ); +} + +bool MulticlassManager::SetProfileFromNative(Client *client, uint8 class_slot_2, uint8 class_slot_3, std::string &status) +{ + if (!client || !client->CharacterID()) { + status = "Character profile is unavailable."; + return false; + } + + if (!SchemaAvailable() || !EnsureProfile(client)) { + status = "Multiclass tables are unavailable."; + return false; + } + + auto profile = LoadProfile(client->CharacterID()); + if (profile.locked) { + status = "This trio is already locked."; + return false; + } + + const auto class_slot_1 = IsPlayerClass(profile.class_slot_1) ? profile.class_slot_1 : client->GetClass(); + if (!IsPlayerClass(class_slot_1) || !IsPlayerClass(class_slot_2) || !IsPlayerClass(class_slot_3)) { + status = "Choose two valid added classes."; + return false; + } + + if (class_slot_1 == class_slot_2 || class_slot_1 == class_slot_3 || class_slot_2 == class_slot_3) { + status = "Choose three different classes."; + return false; + } + + if (!SetProfile(client, class_slot_1, class_slot_2, class_slot_3, "native")) { + status = "Unable to lock the selected trio."; + return false; + } + + return true; +} + +bool MulticlassManager::ReweaveProfileSlot(Client *client, uint8 class_slot, uint8 class_id, const std::string &source, std::string &status) +{ + if (!client || !client->CharacterID()) { + status = "Character profile is unavailable."; + return false; + } + + if (!SchemaAvailable() || !EnsureProfile(client)) { + status = "Multiclass tables are unavailable."; + return false; + } + + if (!IsPlayerClass(class_id) || class_slot < 2 || class_slot > 3) { + status = "Reweave usage: choose slot 2 or 3 and a valid class. Slot 1 stays tied to the character's base identity for now."; + return false; + } + + auto profile = LoadProfile(client->CharacterID()); + if (!profile.locked) { + status = "Lock a trio before reweaving it."; + return false; + } + + if (!profile.reweaves_available && source != "admin_reweave") { + status = "No reweaves are available."; + return false; + } + + if (source != "admin_reweave" && (!zone || (!zone->IsCity() && !zone->CanBind()))) { + status = "Reweaves are only available in cities or bind-safe sanctuaries."; + return false; + } + + if ( + class_id == profile.class_slot_1 || + (class_slot != 2 && class_id == profile.class_slot_2) || + (class_slot != 3 && class_id == profile.class_slot_3) + ) { + status = "Choose a class that is not already in the trio."; + return false; + } + + const auto previous_class = class_slot == 2 ? profile.class_slot_2 : profile.class_slot_3; + if (class_slot == 2) { + profile.class_slot_2 = class_id; + } else { + profile.class_slot_3 = class_id; + } + + if (source != "admin_reweave" && profile.reweaves_available > 0) { + --profile.reweaves_available; + } + + profile.trio_name = BuildTrioName(profile); + profile.resonance_key = TrioKey(profile); + profile.multiple_pets_enabled = true; + + if (!SaveProfile(profile, source)) { + status = "Unable to save the reweave."; + return false; + } + + AuditProfile(profile, source); + SeedEligibleSkills(client, true); + client->CalcBonuses(); + + status = fmt::format( + "Rewove slot {} from {} to {}. Reweaves left: {}.", + class_slot, + ClassName(previous_class, client->GetLevel()), + ClassName(class_id, client->GetLevel()), + profile.reweaves_available + ); + return true; +} + +Mob *MulticlassManager::GetFocusedPet(Client *client) +{ + if (!client || !client->CharacterID()) { + return nullptr; + } + + const auto roster = GetPetRoster(client); + if (roster.empty()) { + focused_pet_ids_.erase(client->CharacterID()); + return nullptr; + } + + const auto focused_pet_id = focused_pet_ids_[client->CharacterID()]; + auto *focused_pet = entity_list.GetMob(focused_pet_id); + if (focused_pet && focused_pet->GetOwnerID() == client->GetID() && focused_pet->IsPet()) { + return focused_pet; + } + + focused_pet_ids_[client->CharacterID()] = roster.front()->GetID(); + client->SetPetID(roster.front()->GetID()); + return roster.front(); +} + +bool MulticlassManager::SetFocusedPet(Client *client, uint16 pet_id) +{ + if (!client || !client->CharacterID() || !pet_id) { + return false; + } + + for (auto *pet : GetPetRoster(client)) { + if (pet && pet->GetID() == pet_id) { + focused_pet_ids_[client->CharacterID()] = pet_id; + client->SetPetID(pet_id); + return true; + } + } + + return false; +} + +bool MulticlassManager::ApplyStockPetCommand(Client *client, Mob *pet, uint32 command, Mob *target, std::string &status) +{ + if (!client || !pet || !pet->IsNPC()) { + status = "Select an active Multiclass pet first."; + return false; + } + + const auto pet_id = pet->GetID(); + const auto original_pet_id = client->GetPetID(); + + client->SetPetID(pet_id); + + EQApplicationPacket app(OP_PetCommands, sizeof(PetCommand_Struct)); + auto *pet_command = reinterpret_cast(app.pBuffer); + pet_command->command = command; + pet_command->target = target ? target->GetID() : 0; + client->Handle_OP_PetCommands(&app); + + if (command == PET_GETLOST) { + focused_pet_ids_.erase(client->CharacterID()); + if (original_pet_id && original_pet_id != pet_id && entity_list.GetMob(original_pet_id)) { + client->SetPetID(original_pet_id); + } else { + client->SetPetID(0); + GetFocusedPet(client); + } + status = "Focused pet dismissed."; + return true; + } + + if (original_pet_id && original_pet_id != pet_id && entity_list.GetMob(original_pet_id)) { + client->SetPetID(original_pet_id); + } + + status = "Pet command sent."; + return true; +} + +bool MulticlassManager::ApplyPetAction(Client *client, Mob *pet, const std::string &action, std::string &status) +{ + if (!client || !pet || !pet->IsNPC()) { + status = "Select an active Multiclass pet first."; + return false; + } + + auto *pet_npc = pet->CastToNPC(); + const auto action_name = Strings::ToLower(action); + + if (action_name == "attack" || action_name == "qattack") { + auto *target = client->GetTarget(); + if (!target || target == client) { + status = "Target an enemy before sending pets to attack."; + return false; + } + + if (target->IsMezzed()) { + status = "Pets will not wake a mezzed target."; + return false; + } + + if (pet->IsFeared() || !pet->IsAttackAllowed(target)) { + status = "One or more pets cannot attack that target."; + return false; + } + + ApplyStockPetCommand(client, pet, action_name == "qattack" ? PET_QATTACK : PET_ATTACK, target, status); + status = fmt::format("Sent {} to attack {}.", pet->GetCleanName(), target->GetCleanName()); + return true; + } + + if (action_name == "back" || action_name == "backoff") { + ApplyStockPetCommand(client, pet, PET_BACKOFF, nullptr, status); + status = "Pet attack cleared."; + return true; + } + + if (action_name == "follow" || action_name == "guardme") { + ApplyStockPetCommand(client, pet, action_name == "guardme" ? PET_GUARDME : PET_FOLLOWME, nullptr, status); + status = "Pet follow mode set."; + return true; + } + + if (action_name == "guard" || action_name == "guardhere") { + ApplyStockPetCommand(client, pet, PET_GUARDHERE, nullptr, status); + status = "Pet guard spot set."; + return true; + } + + if (action_name == "taunt") { + ApplyStockPetCommand(client, pet, PET_TAUNT, nullptr, status); + status = pet_npc->IsTaunting() ? "Focused pet taunt enabled." : "Focused pet taunt disabled."; + return true; + } + + if (action_name == "hold") { + pet->SetHeld(!pet->IsHeld()); + if (pet->IsHeld()) { + pet->SetGHeld(false); + client->MessageString(Chat::PetResponse, PET_HOLD_SET_ON); + pet->SayString(client, Chat::PetResponse, PET_NOW_HOLDING); + } else { + client->MessageString(Chat::PetResponse, PET_HOLD_SET_OFF); + } + client->SetPetCommandState(PET_BUTTON_HOLD, pet->IsHeld() ? 1 : 0); + client->SetPetCommandState(PET_BUTTON_GHOLD, 0); + status = pet->IsHeld() ? "Focused pet hold enabled." : "Focused pet hold disabled."; + return true; + } + + if (action_name == "spellhold" || action_name == "nocast") { + pet->SetNoCast(!pet->IsNoCast()); + client->MessageString(Chat::PetResponse, pet->IsNoCast() ? PET_NOT_CASTING : PET_CASTING); + client->MessageString(Chat::PetResponse, pet->IsNoCast() ? PET_SPELLHOLD_SET_ON : PET_SPELLHOLD_SET_OFF); + client->SetPetCommandState(PET_BUTTON_SPELLHOLD, pet->IsNoCast() ? 1 : 0); + status = pet->IsNoCast() ? "Focused pet spell hold enabled." : "Focused pet spell hold disabled."; + return true; + } + + if (action_name == "sit") { + const bool should_sit = pet->GetPetOrder() != 1; + pet->SetPetOrder(should_sit ? 1 : 0); + pet->SetAppearance(should_sit ? eaSitting : eaStanding); + status = should_sit ? "Focused pet is sitting." : "Focused pet is standing."; + return true; + } + + if (action_name == "dismiss" || action_name == "getlost") { + return ApplyStockPetCommand(client, pet, PET_GETLOST, nullptr, status); + } + + if (action_name == "health") { + ApplyStockPetCommand(client, pet, PET_HEALTHREPORT, nullptr, status); + status = "Pet health reported."; + return true; + } + + status = "Unsupported pet action."; + return false; +} + +bool MulticlassManager::HandleNativePetCommand(Client *client, const Seperator *sep, std::string &status) +{ + if (!client || !sep) { + status = "Multiclass pet command is unavailable."; + return false; + } + + const auto roster = GetPetRoster(client); + if (roster.empty()) { + status = "No active Multiclass pets yet."; + return false; + } + + if (sep->argnum < 2 || !strcasecmp(sep->arg[2], "refresh")) { + status = "Pet roster refreshed."; + return true; + } + + const std::string action = sep->arg[2] ? sep->arg[2] : ""; + const auto action_name = Strings::ToLower(action); + if (action_name == "focus") { + const auto pet_id = static_cast(Strings::ToUnsignedInt(sep->arg[3])); + if (!SetFocusedPet(client, pet_id)) { + status = "Unable to focus that pet."; + return false; + } + + auto *pet = GetFocusedPet(client); + status = pet ? fmt::format("Focused {}.", pet->GetCleanName()) : "Pet focus updated."; + return true; + } + + std::vector targets; + const auto target_arg = sep->arg[3] ? Strings::ToLower(sep->arg[3]) : ""; + const bool all_pets = target_arg == "all" || + action_name == "attack" || + action_name == "qattack" || + action_name == "back" || + action_name == "backoff" || + action_name == "follow" || + action_name == "guard" || + action_name == "guardme" || + action_name == "health"; + + if (target_arg != "all" && Strings::IsNumber(target_arg)) { + const auto pet_id = static_cast(Strings::ToUnsignedInt(target_arg.c_str())); + for (auto *pet : roster) { + if (pet && pet->GetID() == pet_id) { + SetFocusedPet(client, pet_id); + targets.push_back(pet); + break; + } + } + } else if (all_pets) { + targets = roster; + } else { + auto *focused_pet = GetFocusedPet(client); + if (focused_pet) { + targets.push_back(focused_pet); + } + } + + if (targets.empty()) { + status = "Select an active Multiclass pet first."; + return false; + } + + uint8 applied = 0; + std::string last_status; + for (auto *pet : targets) { + if (ApplyPetAction(client, pet, action, last_status)) { + ++applied; + } + } + + if (applied > 1) { + status = fmt::format("Applied {} to {} pets.", action, applied); + } else if (applied == 1) { + status = last_status; + } else { + status = last_status.empty() ? "Pet command did not apply." : last_status; + } + + return applied > 0; +} + +bool MulticlassManager::HandleNativeMelodyCommand(Client *client, const Seperator *sep, std::string &status, bool &show_melody_window) +{ + show_melody_window = true; + if (!client || !sep) { + status = "Bard Melody is unavailable."; + return false; + } + + if (!IsBard(client)) { + status = "Bard Melody requires Bard in your trio."; + return false; + } + + if (!MelodySchemaAvailable()) { + status = "Bard Melody tables are unavailable."; + return false; + } + + const std::string action = sep->arg[2] ? Strings::ToLower(sep->arg[2]) : ""; + if (action.empty() || action == "open" || action == "refresh" || action == "status") { + status = BuildBardMelodySummary(client); + return true; + } + + auto slots = LoadBardMelody(client); + if (action == "clear") { + if (sep->argnum >= 3 && Strings::IsNumber(sep->arg[3])) { + const int slot_id = Strings::ToInt(sep->arg[3]); + if (!EQ::ValueWithin(slot_id, 1, static_cast(slots.size()))) { + status = "Choose a Bard Melody slot from 1 to 4."; + return false; + } + + slots[slot_id - 1] = 0; + SaveBardMelody(client, slots); + status = fmt::format("Cleared Bard Melody slot {}.", slot_id); + return true; + } + + slots = {}; + SaveBardMelody(client, slots); + status = "Cleared Bard Melody."; + return true; + } + + if (action == "set") { + const int slot_id = Strings::ToInt(sep->arg[3]); + const uint16 spell_id = static_cast(Strings::ToUnsignedInt(sep->arg[4])); + if (!EQ::ValueWithin(slot_id, 1, static_cast(slots.size()))) { + status = "Choose a Bard Melody slot from 1 to 4."; + return false; + } + + std::string reason; + if (!IsAllowedBardMelodySong(client, spell_id, &reason)) { + status = reason.empty() ? "That song cannot be used in Bard Melody." : reason; + return false; + } + + slots[slot_id - 1] = spell_id; + SaveBardMelody(client, slots); + status = fmt::format("Bard Melody slot {} set to {}.", slot_id, spells[spell_id].name); + return true; + } + + status = "Bard Melody supports open, refresh, set , and clear [slot]."; + return false; +} + +bool MulticlassManager::HandleNativeDisciplineCommand(Client *client, const Seperator *sep, std::string &status, bool &show_discipline_window) +{ + show_discipline_window = true; + if (!client || !sep) { + status = "Multiclass disciplines are unavailable."; + return false; + } + + const std::string action = sep->arg[2] ? Strings::ToLower(sep->arg[2]) : ""; + if (action.empty() || action == "open" || action == "refresh" || action == "status" || action == "list" || action == "window") { + status = BuildDisciplineSummary(client); + return true; + } + + const char *lookup_text = nullptr; + if (action == "use") { + lookup_text = sep->argplus[3]; + } else { + lookup_text = sep->argplus[2]; + } + + if (!lookup_text || !lookup_text[0]) { + status = "Select a learned discipline first."; + return false; + } + + std::string lookup = lookup_text; + Strings::Trim(lookup); + if (lookup.empty()) { + status = "Select a learned discipline first."; + return false; + } + + uint16 spell_id = 0; + const auto learned_disciplines = client->GetLearnedDisciplines(); + if (Strings::IsNumber(lookup)) { + const auto requested_id = static_cast(Strings::ToUnsignedInt(lookup)); + for (const auto learned_id : learned_disciplines) { + if (learned_id == requested_id && IsValidSpell(learned_id) && IsDiscipline(learned_id)) { + spell_id = requested_id; + break; + } + } + } else { + const auto wanted = NormalizeLookupText(lookup); + if (!wanted.empty()) { + for (const auto learned_id : learned_disciplines) { + if (!IsValidSpell(learned_id) || !IsDiscipline(learned_id)) { + continue; + } + + if (NormalizeLookupText(spells[learned_id].name) == wanted) { + spell_id = static_cast(learned_id); + break; + } + } + + if (!spell_id) { + for (const auto learned_id : learned_disciplines) { + if (!IsValidSpell(learned_id) || !IsDiscipline(learned_id)) { + continue; + } + + const auto normalized_name = NormalizeLookupText(spells[learned_id].name); + if (normalized_name.find(wanted) != std::string::npos) { + spell_id = static_cast(learned_id); + break; + } + } + } + } + } + + if (!IsValidSpell(spell_id) || !IsDiscipline(spell_id)) { + status = "That discipline is not learned on this character."; + return false; + } + + const auto target_id = client->GetTarget() ? client->GetTarget()->GetID() : client->GetID(); + if (!client->UseDiscipline(spell_id, target_id)) { + status = fmt::format("{} was not ready.", spells[spell_id].name); + return false; + } + + status = fmt::format("Used {}.", spells[spell_id].name); + return true; +} + +bool MulticlassManager::MelodySchemaAvailable() +{ + if (melody_schema_available_) { + return true; + } + + auto results = database.QueryDatabase("SHOW TABLES LIKE 'custom_multiclass_bard_melody'"); + melody_schema_available_ = results.Success() && results.RowCount() > 0; + return melody_schema_available_; +} + +MulticlassManager::BardMelodySlots MulticlassManager::LoadBardMelody(Client *client) +{ + BardMelodySlots slots = {}; + if (!client || !client->CharacterID() || !MelodySchemaAvailable()) { + return slots; + } + + const auto cached = bard_melody_cache_.find(client->CharacterID()); + if (cached != bard_melody_cache_.end()) { + return cached->second; + } + + auto results = database.QueryDatabase( + fmt::format( + "SELECT `slot_id`, `spell_id` FROM `custom_multiclass_bard_melody` " + "WHERE `character_id` = {} AND `slot_id` BETWEEN 1 AND 4", + client->CharacterID() + ) + ); + + if (results.Success()) { + for (auto row = results.begin(); row != results.end(); ++row) { + const int slot_id = Strings::ToInt(row[0]); + const uint16 spell_id = static_cast(Strings::ToUnsignedInt(row[1])); + if (EQ::ValueWithin(slot_id, 1, static_cast(slots.size()))) { + slots[slot_id - 1] = spell_id; + } + } + } + + bard_melody_cache_[client->CharacterID()] = slots; + return slots; +} + +bool MulticlassManager::SaveBardMelody(Client *client, const BardMelodySlots &slots) +{ + if (!client || !client->CharacterID() || !MelodySchemaAvailable()) { + return false; + } + + auto delete_results = database.QueryDatabase( + fmt::format( + "DELETE FROM `custom_multiclass_bard_melody` WHERE `character_id` = {}", + client->CharacterID() + ) + ); + + if (!delete_results.Success()) { + return false; + } + + std::vector values; + for (size_t i = 0; i < slots.size(); ++i) { + if (!slots[i]) { + continue; + } + + values.emplace_back( + fmt::format( + "({}, {}, {}, UNIX_TIMESTAMP())", + client->CharacterID(), + i + 1, + slots[i] + ) + ); + } + + if (!values.empty()) { + auto insert_results = database.QueryDatabase( + fmt::format( + "INSERT INTO `custom_multiclass_bard_melody` (`character_id`, `slot_id`, `spell_id`, `updated_at`) VALUES {}", + Strings::Join(values, ",") + ) + ); + + if (!insert_results.Success()) { + return false; + } + } + + bard_melody_cache_[client->CharacterID()] = slots; + return true; +} + +bool MulticlassManager::IsAllowedBardMelodySong(Client *client, uint16 spell_id, std::string *reason) +{ + if (!client || !IsBard(client)) { + if (reason) { + *reason = "Bard Melody requires Bard in your trio."; + } + return false; + } + + if (!IsValidSpell(spell_id) || !IsBardSong(spell_id)) { + if (reason) { + *reason = "Choose a scribed Bard song."; + } + return false; + } + + bool scribed = false; + for (const auto scribed_spell : client->GetScribedSpells()) { + if (scribed_spell == spell_id) { + scribed = true; + break; + } + } + + if (!scribed) { + if (reason) { + *reason = "That Bard song is not in your spellbook."; + } + return false; + } + + const auto best_level = GetBestSpellLevel(client, spell_id); + if (best_level == 255 || client->GetLevel() < best_level) { + if (reason) { + *reason = "Your trio cannot use that Bard song yet."; + } + return false; + } + + if (IsBlockedMelodyControlSong(spell_id)) { + if (reason) { + *reason = "Charm, fear, mez, stun, root, and lull songs are disabled for Bard Melody until separately validated."; + } + return false; + } + + return true; +} + +void MulticlassManager::RefreshAlternateAdvancementTable(Client *client) +{ + if (!client) { + return; + } + + client->SendClearPlayerAA(); + client->SendAlternateAdvancementTable(); + client->SendAlternateAdvancementPoints(); + client->SendAlternateAdvancementStats(); +} + +bool MulticlassManager::HasActiveBardMelody(Client *client) +{ + if (!client || !IsBard(client) || !MelodySchemaAvailable()) { + return false; + } + + const auto slots = LoadBardMelody(client); + for (const auto spell_id : slots) { + if (spell_id && IsAllowedBardMelodySong(client, spell_id, nullptr)) { + return true; + } + } + + return false; +} + +std::string MulticlassManager::BuildBardMelodySummary(Client *client) +{ + if (!client || !IsBard(client)) { + return "Bard Melody: Bard not in trio."; + } + + const auto slots = LoadBardMelody(client); + uint8 active = 0; + for (const auto spell_id : slots) { + if (IsValidSpell(spell_id)) { + active++; + } + } + + return fmt::format("Bard Melody: {}/4 song slots selected.", active); +} + +std::string MulticlassManager::BuildDisciplineSummary(Client *client) +{ + if (!client) { + return "Disciplines: unavailable."; + } + + uint16 learned_count = 0; + uint16 ready_count = 0; + for (const auto spell_id : client->GetLearnedDisciplines()) { + if (!IsValidSpell(spell_id) || !IsDiscipline(spell_id)) { + continue; + } + + ++learned_count; + const auto best_level = GetBestSpellLevel(client, static_cast(spell_id)); + const auto timer = client->GetDisciplineTimer(spells[spell_id].timer_id); + if (best_level != 255 && client->GetLevel() >= best_level && timer == 0) { + ++ready_count; + } + } + + if (!learned_count) { + return "Disciplines: none learned."; + } + + return fmt::format("Disciplines: {}/{} ready.", ready_count, learned_count); +} + +void MulticlassManager::SendNativeDisciplines(Client *client, bool show_discipline_window, const std::string &status) +{ + if (!client) { + return; + } + + struct DisciplineRow { + uint16 slot = 0; + uint16 spell_id = 0; + uint8 level = 255; + uint32 timer = 0; + uint32 timer_total = 0; + bool ready = false; + std::string state; + }; + + std::vector rows; + uint16 usable_count = 0; + uint16 ready_count = 0; + + for (uint32 slot_id = 0; slot_id < MAX_PP_DISCIPLINES; ++slot_id) { + const auto spell_id = client->GetPP().disciplines.values[slot_id]; + if (!IsValidSpell(spell_id) || !IsDiscipline(spell_id)) { + continue; + } + + DisciplineRow row; + row.slot = static_cast(slot_id + 1); + row.spell_id = static_cast(spell_id); + row.level = GetBestSpellLevel(client, row.spell_id); + row.timer = client->GetDisciplineTimer(spells[spell_id].timer_id); + row.timer_total = spells[spell_id].recast_time > 0 ? spells[spell_id].recast_time / 1000 : 0; + if (row.timer > 0) { + row.timer_total = std::max(row.timer_total, row.timer); + } + + const bool usable = row.level != 255 && client->GetLevel() >= row.level; + if (usable) { + ++usable_count; + } + + row.ready = usable && row.timer == 0; + if (row.ready) { + ++ready_count; + row.state = "Ready"; + } else if (row.level == 255) { + row.state = "Trio blocked"; + } else if (client->GetLevel() < row.level) { + row.state = fmt::format("Level {}", row.level); + } else if (row.timer > 0) { + row.state = "Reuse"; + } else { + row.state = "Blocked"; + } + + rows.emplace_back(row); + } + + const auto status_text = !status.empty() ? status : BuildDisciplineSummary(client); + client->Message(Chat::White, "MULTICLASS|disciplines|clear"); + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|disciplines|summary|status={}|count={}|usable={}|ready={}", + ProtocolValue(status_text), + rows.size(), + usable_count, + ready_count + ).c_str() + ); + + for (const auto &row : rows) { + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|discipline|slot={}|id={}|name={}|level={}|timer={}|total={}|ready={}|state={}", + row.slot, + row.spell_id, + ProtocolValue(spells[row.spell_id].name), + row.level == 255 ? 0 : row.level, + row.timer, + row.timer_total, + row.ready ? 1 : 0, + ProtocolValue(row.state) + ).c_str() + ); + } + + client->Message(Chat::White, fmt::format("MULTICLASS|disciplines|end|count={}", rows.size()).c_str()); + if (show_discipline_window) { + client->Message(Chat::White, "MULTICLASS|discipline_window|show"); + } +} + +void MulticlassManager::SendNativeBardMelody(Client *client, bool show_melody_window) +{ + if (!client) { + return; + } + + const bool has_bard = IsBard(client); + const auto slots = has_bard ? LoadBardMelody(client) : BardMelodySlots{}; + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|melody|has_bard={}|status={}", + has_bard ? 1 : 0, + ProtocolValue(BuildBardMelodySummary(client)) + ).c_str() + ); + + for (size_t i = 0; i < slots.size(); ++i) { + const auto spell_id = slots[i]; + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|melody_slot|slot={}|id={}|name={}|level={}|state={}", + i + 1, + spell_id, + ProtocolValue(IsValidSpell(spell_id) ? spells[spell_id].name : "-"), + IsValidSpell(spell_id) ? GetBestSpellLevel(client, spell_id) : 0, + IsValidSpell(spell_id) ? "selected" : "empty" + ).c_str() + ); + } + + uint16 candidate_count = 0; + if (has_bard) { + for (const auto scribed_spell : client->GetScribedSpells()) { + if (scribed_spell < 0 || scribed_spell > std::numeric_limits::max()) { + continue; + } + + const auto spell_id = static_cast(scribed_spell); + if (!IsValidSpell(spell_id) || !IsBardSong(spell_id)) { + continue; + } + + std::string reason; + const bool allowed = IsAllowedBardMelodySong(client, spell_id, &reason); + client->Message( + Chat::White, + fmt::format( + "MULTICLASS|melody_song|id={}|name={}|level={}|allowed={}|reason={}", + spell_id, + ProtocolValue(spells[spell_id].name), + GetBestSpellLevel(client, spell_id), + allowed ? 1 : 0, + ProtocolValue(reason) + ).c_str() + ); + candidate_count++; + } + } + + client->Message(Chat::White, fmt::format("MULTICLASS|melody_songs|end|count={}", candidate_count).c_str()); + if (show_melody_window) { + client->Message(Chat::White, "MULTICLASS|melody_window|show"); + } +} + +void MulticlassManager::ProcessBardMelody(Client *client) +{ + if (!client || client->IsDead() || !IsBard(client) || !MelodySchemaAvailable()) { + return; + } + + const auto now = static_cast(std::time(nullptr)); + auto &next_pulse = bard_melody_next_pulse_[client->CharacterID()]; + if (next_pulse && now < next_pulse) { + return; + } + + next_pulse = now + 6; + + const auto slots = LoadBardMelody(client); + for (const auto spell_id : slots) { + if (!spell_id || !IsAllowedBardMelodySong(client, spell_id, nullptr)) { + continue; + } + + auto *target = ResolveMelodyTarget(client, spell_id); + if (!target) { + continue; + } + + client->ApplyBardPulse(spell_id, target, EQ::spells::CastingSlot::Item); + } +} + +bool MulticlassManager::SchemaAvailable() +{ + if (schema_available_) { + return true; + } + + auto results = database.QueryDatabase("SHOW TABLES LIKE 'custom_multiclass_profiles'"); + schema_available_ = results.Success() && results.RowCount() > 0; + return schema_available_; +} + +bool MulticlassManager::SaveProfile(const Profile &profile, const std::string &source) +{ + if (!profile.character_id) { + return false; + } + + const auto trio_name = Strings::Escape(profile.trio_name); + const auto resonance_key = Strings::Escape(profile.resonance_key); + const auto source_value = Strings::Escape(source); + + auto results = database.QueryDatabase( + fmt::format( + "INSERT INTO `custom_multiclass_profiles` " + "(`character_id`, `class_slot_1`, `class_slot_2`, `class_slot_3`, `trio_name`, `resonance_key`, `multiple_pets_enabled`, `locked`, `reweaves_available`, `created_at`, `updated_at`) " + "VALUES ({}, {}, {}, {}, '{}', '{}', {}, {}, {}, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()) " + "ON DUPLICATE KEY UPDATE " + "`class_slot_1` = VALUES(`class_slot_1`), " + "`class_slot_2` = VALUES(`class_slot_2`), " + "`class_slot_3` = VALUES(`class_slot_3`), " + "`trio_name` = VALUES(`trio_name`), " + "`resonance_key` = VALUES(`resonance_key`), " + "`multiple_pets_enabled` = VALUES(`multiple_pets_enabled`), " + "`locked` = VALUES(`locked`), " + "`reweaves_available` = VALUES(`reweaves_available`), " + "`updated_at` = UNIX_TIMESTAMP()", + profile.character_id, + profile.class_slot_1, + profile.class_slot_2, + profile.class_slot_3, + trio_name, + resonance_key, + profile.multiple_pets_enabled ? 1 : 0, + profile.locked ? 1 : 0, + profile.reweaves_available + ) + ); + + if (!results.Success()) { + return false; + } + + profile_cache_[profile.character_id] = profile; + + auto audit_results = database.QueryDatabase( + fmt::format( + "INSERT INTO `custom_multiclass_profile_audit` " + "(`character_id`, `class_slot`, `class_id`, `action`, `detail`, `created_at`) " + "VALUES ({}, 0, 0, 'save', '{}', UNIX_TIMESTAMP())", + profile.character_id, + source_value + ) + ); + return audit_results.Success(); +} + +bool MulticlassManager::AuditProfile(const Profile &profile, const std::string &source) +{ + const auto detail = Strings::Escape(source); + auto results = database.QueryDatabase( + fmt::format( + "INSERT INTO `custom_multiclass_profile_audit` " + "(`character_id`, `class_slot`, `class_id`, `action`, `detail`, `created_at`) " + "VALUES " + "({}, 1, {}, 'set_slot', '{}', UNIX_TIMESTAMP()), " + "({}, 2, {}, 'set_slot', '{}', UNIX_TIMESTAMP()), " + "({}, 3, {}, 'set_slot', '{}', UNIX_TIMESTAMP())", + profile.character_id, + profile.class_slot_1, + detail, + profile.character_id, + profile.class_slot_2, + detail, + profile.character_id, + profile.class_slot_3, + detail + ) + ); + + return results.Success(); +} + +std::string MulticlassManager::ClassName(uint8 class_id, uint8 level) +{ + if (!IsPlayerClass(class_id)) { + return "Unchosen"; + } + + const char *class_name = GetClassIDName(class_id, level); + return class_name ? class_name : "Unknown"; +} + +std::string MulticlassManager::BuildTrioName(const Profile &profile) +{ + if (const auto *exact = FindExactTrioTemplate(profile)) { + return exact->name; + } + + const std::array slots = {profile.class_slot_1, profile.class_slot_2, profile.class_slot_3}; + uint8 chosen = 0; + uint8 pet_classes = 0; + bool has_tank = false; + bool has_healer = false; + + for (const auto class_id : slots) { + if (!IsPlayerClass(class_id)) { + continue; + } + + chosen++; + pet_classes += IsPetClass(class_id) ? 1 : 0; + has_tank = has_tank || IsTankClass(class_id); + has_healer = has_healer || IsHealerClass(class_id); + } + + if (!chosen) { + return "Unchosen Triad"; + } + + if (pet_classes >= 3) { + return "Grand Menagerie"; + } + + if (pet_classes == 2) { + return "Twin Menagerie"; + } + + if (has_tank && has_healer && chosen >= 3) { + return "Warbound Covenant"; + } + + return fmt::format("{} Triad", ClassName(profile.class_slot_1)); +} + +MulticlassManager::TrioMetadata MulticlassManager::BuildTrioMetadata(const Profile &profile) +{ + TrioMetadata metadata; + std::vector roles; + + uint8 chosen = 0; + uint8 pet_classes = 0; + bool has_tank = false; + bool has_healer = false; + bool has_int_caster = false; + bool has_bard = false; + bool has_striker = false; + + for (const auto class_id : ProfileSlots(profile)) { + if (!IsPlayerClass(class_id)) { + continue; + } + + ++chosen; + AddRoleTags(roles, class_id); + pet_classes += IsPetClass(class_id) ? 1 : 0; + has_tank = has_tank || IsTankClass(class_id); + has_healer = has_healer || IsHealerClass(class_id); + has_int_caster = has_int_caster || IsIntCasterClass(class_id); + has_bard = has_bard || IsBardClass(class_id); + has_striker = has_striker || IsStrikerClass(class_id); + } + + metadata.roles = roles.empty() ? "Unchosen" : JoinValues(roles, " / "); + + if (const auto *exact = FindExactTrioTemplate(profile)) { + metadata.resonance = exact->name; + metadata.summary = exact->summary; + } else if (pet_classes >= 3) { + metadata.resonance = "Grand Menagerie"; + } else if (pet_classes == 2) { + metadata.resonance = "Twin Menagerie"; + } else if (has_tank && pet_classes && has_int_caster) { + metadata.resonance = "Warbound Arcanum"; + } else if (has_tank && has_healer) { + metadata.resonance = "Warbound Covenant"; + } else if (has_healer && has_int_caster) { + metadata.resonance = "Concord of Mind and Spirit"; + } else if (has_bard) { + metadata.resonance = "Chorus of Three"; + } else if (has_striker && has_int_caster) { + metadata.resonance = "Spellblade Compact"; + } else if (!profile.trio_name.empty()) { + metadata.resonance = profile.trio_name; + } else { + metadata.resonance = BuildTrioName(profile); + } + + if (!profile.locked) { + metadata.summary = "Pick two added classes. The server locks the trio and applies capability routing after confirmation."; + } else if (!metadata.summary.empty()) { + // Exact trio templates provide their own summary. + } else if (pet_classes > 1) { + metadata.summary = fmt::format( + "Multi-pet trio. Summon up to {} owned pets in-zone, then use this window for focus and broadcast commands.", + std::min(3, pet_classes) + ); + } else if (has_tank && pet_classes && has_int_caster) { + metadata.summary = "Tough base with pet pressure and burst casting. Spellbook presentation is enabled for caster controls."; + } else if (has_tank && has_healer) { + metadata.summary = "Durable support trio with defensive skills, healing, and melee staying power."; + } else if (has_healer && has_int_caster) { + metadata.summary = "Hybrid caster support trio with healing, control, and offensive spell access."; + } else if (pet_classes == 1) { + metadata.summary = "Pet-capable trio. The native pet console controls the active owned pet and keeps stock pet controls as compatibility only."; + } else if (chosen) { + metadata.summary = "Fixed trio identity. Class gates route through the Multiclass capability layer."; + } else { + metadata.summary = "Choose your second and third classes to define this character's trio identity."; + } + + metadata.pet_policy = profile.multiple_pets_enabled ? "native-ui" : "single-pet"; + metadata.pet_control = profile.multiple_pets_enabled ? + "Attack/Back/Follow/Guard affect all pets; Taunt/Hold/Cast/Dismiss affect the focused pet." : + "Single-pet profile; native pet console still displays pet state."; + + return metadata; +} + +std::string MulticlassManager::BuildSkillSummary(Client *client) +{ + if (!client || !SchemaAvailable() || !EnsureProfile(client)) { + return "Skills: profile unavailable."; + } + + const auto profile = LoadProfile(client->CharacterID()); + if (!profile.locked) { + return "Skills: lock your trio to unlock off-class tools."; + } + + uint16 eligible_count = 0; + uint16 active_count = 0; + uint16 ready_unseeded_count = 0; + for (const auto &skill_entry : EQ::skills::GetSkillTypeMap()) { + const auto skill_id = skill_entry.first; + if (!ShouldAutoSeedSkill(skill_id)) { + continue; + } + + const auto train_level = GetBestSkillTrainLevel(client, skill_id); + if (!train_level || client->GetLevel() < train_level || !GetBestSkillCap(client, skill_id, client->GetLevel())) { + continue; + } + + ++eligible_count; + if (client->GetRawSkill(skill_id) > 0) { + ++active_count; + } else { + ++ready_unseeded_count; + } + } + + return fmt::format( + "Skills: {}/{} active{}; tradeskills and specializations stay content-based.", + active_count, + eligible_count, + ready_unseeded_count ? fmt::format(", {} ready to seed", ready_unseeded_count) : "" + ); +} + +uint8 MulticlassManager::ParseClassId(const char *value) +{ + if (!value || !value[0]) { + return Class::None; + } + + if (Strings::IsNumber(value)) { + const auto class_id = static_cast(Strings::ToUnsignedInt(value)); + return IsPlayerClass(class_id) ? class_id : Class::None; + } + + const auto wanted = Strings::ToLower(value); + for (uint8 class_id = Class::Warrior; class_id <= Class::Berserker; ++class_id) { + auto class_name = Strings::ToLower(GetClassIDName(class_id)); + class_name = Strings::Replace(class_name, " ", ""); + if ( + wanted == Strings::ToLower(GetClassIDName(class_id)) || + wanted == class_name || + wanted == Strings::ToLower(GetPlayerClassAbbreviation(class_id)) + ) { + return class_id; + } + } + + if (wanted == "sk" || wanted == "shadowknight") { + return Class::ShadowKnight; + } + + return Class::None; +} + +std::string MulticlassManager::ProtocolValue(std::string value) +{ + for (auto &c : value) { + if (c == '|' || c == '\r' || c == '\n' || c == '\t') { + c = ' '; + } + } + + return value; +} + +EQ::skills::SkillType MulticlassManager::NormalizeSkillForClass(const Client *client, uint8 class_id, EQ::skills::SkillType skill_id) +{ + if ( + client && + client->ClientVersion() < EQ::versions::ClientVersion::RoF2 && + class_id == Class::Berserker && + skill_id == EQ::skills::Skill1HPiercing + ) { + return EQ::skills::Skill2HPiercing; + } + + return skill_id; +} diff --git a/zone/multiclass_manager.h b/zone/multiclass_manager.h new file mode 100644 index 0000000000..a159300e41 --- /dev/null +++ b/zone/multiclass_manager.h @@ -0,0 +1,134 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. +*/ +#pragma once + +#include "common/skills.h" +#include "common/types.h" + +#include +#include +#include +#include + +class Client; +class Mob; +class Seperator; +struct StatBonuses; + +namespace EQ { + class ItemInstance; +} + +class MulticlassManager { +public: + using ClassSlots = std::array; + using BardMelodySlots = std::array; + + struct Profile { + uint32 character_id = 0; + uint8 class_slot_1 = 0; + uint8 class_slot_2 = 0; + uint8 class_slot_3 = 0; + std::string trio_name; + std::string resonance_key; + bool multiple_pets_enabled = true; + bool locked = false; + uint8 reweaves_available = 0; + }; + + void HandleCommand(Client *client, const Seperator *sep); + void HandleNativeCommand(Client *client, const Seperator *sep); + bool EnsureProfile(Client *client); + Profile LoadProfile(uint32 character_id); + bool SetProfile(Client *client, uint8 class_slot_1, uint8 class_slot_2, uint8 class_slot_3, const std::string &source); + bool HasClass(uint32 character_id, uint8 class_id); + bool HasClass(const Client *client, uint8 class_id); + bool HasMultiplePetProfile(uint32 character_id); + ClassSlots GetClassSlots(const Client *client); + uint32 GetClassMask(const Client *client); + uint32 GetAAClassMask(const Client *client); + uint8 GetBestSpellLevel(const Client *client, uint16 spell_id); + bool CanUseSpell(const Client *client, uint16 spell_id); + bool CanUseItem(const Client *client, const EQ::ItemInstance *inst); + bool CanHaveSkill(const Client *client, EQ::skills::SkillType skill_id); + uint16 GetBestSkillCap(const Client *client, EQ::skills::SkillType skill_id, uint8 level); + uint8 GetBestSkillTrainLevel(const Client *client, EQ::skills::SkillType skill_id); + uint16 SeedEligibleSkills(Client *client, bool notify = true); + void ApplyTrioBonuses(Client *client, StatBonuses *bonuses); + std::string BuildTrioBonusSummary(Client *client); + bool IsIntCaster(const Client *client); + bool IsWisCaster(const Client *client); + bool IsBard(const Client *client); + uint8 GetPrimaryIntCasterClass(const Client *client); + uint8 GetPrimaryWisCasterClass(const Client *client); + uint8 GetClientPresentationClass(const Client *client); + uint8 GetPetRosterLimit(const Client *client); + std::vector GetPetRoster(const Client *client); + std::vector GetSecondaryPetRoster(Client *client); + bool IsPetRosterMember(const Client *client, Mob *pet); + bool CanCreateAdditionalPet(Client *client); + bool RegisterPet(Client *client, Mob *pet); + bool SetFocusedPet(Client *client, uint16 pet_id); + bool HasActiveBardMelody(Client *client); + void ProcessBardMelody(Client *client); + void SendNativeSpellLevelSnapshot(Client *client); + +private: + void SendHelp(Client *client); + void SendStatus(Client *client); + void SendDiagnostics(Client *client, const char *topic = nullptr); + void SendNativeSnapshot(Client *client, const std::string &status = "", bool show_window = true, bool show_pet_window = false); + void SendNativeSpellLevelPatch(Client *client, uint8 presentation_class); + + struct TrioMetadata { + std::string roles; + std::string resonance; + std::string summary; + std::string pet_policy; + std::string pet_control; + }; + + bool SetProfileFromNative(Client *client, uint8 class_slot_2, uint8 class_slot_3, std::string &status); + bool ReweaveProfileSlot(Client *client, uint8 class_slot, uint8 class_id, const std::string &source, std::string &status); + bool HandleNativePetCommand(Client *client, const Seperator *sep, std::string &status); + bool HandleNativeMelodyCommand(Client *client, const Seperator *sep, std::string &status, bool &show_melody_window); + bool HandleNativeDisciplineCommand(Client *client, const Seperator *sep, std::string &status, bool &show_discipline_window); + bool ApplyStockPetCommand(Client *client, Mob *pet, uint32 command, Mob *target, std::string &status); + bool ApplyPetAction(Client *client, Mob *pet, const std::string &action, std::string &status); + Mob *GetFocusedPet(Client *client); + bool SchemaAvailable(); + bool MelodySchemaAvailable(); + BardMelodySlots LoadBardMelody(Client *client); + bool SaveBardMelody(Client *client, const BardMelodySlots &slots); + void SendNativeBardMelody(Client *client, bool show_melody_window = false); + void SendNativeDisciplines(Client *client, bool show_discipline_window = false, const std::string &status = ""); + void RefreshAlternateAdvancementTable(Client *client); + bool IsAllowedBardMelodySong(Client *client, uint16 spell_id, std::string *reason = nullptr); + std::string BuildBardMelodySummary(Client *client); + std::string BuildDisciplineSummary(Client *client); + bool SaveProfile(const Profile &profile, const std::string &source); + bool AuditProfile(const Profile &profile, const std::string &source); + std::string ClassName(uint8 class_id, uint8 level = 0); + std::string BuildTrioName(const Profile &profile); + TrioMetadata BuildTrioMetadata(const Profile &profile); + std::string BuildSkillSummary(Client *client); + uint8 ParseClassId(const char *value); + std::string ProtocolValue(std::string value); + EQ::skills::SkillType NormalizeSkillForClass(const Client *client, uint8 class_id, EQ::skills::SkillType skill_id); + + bool schema_available_ = false; + bool melody_schema_available_ = false; + std::unordered_map profile_cache_; + std::unordered_map focused_pet_ids_; + std::unordered_map bard_melody_cache_; + std::unordered_map bard_melody_next_pulse_; +}; + +extern MulticlassManager multiclass_manager; From 32c512addc324c0f15a62d6a2762def5184992ee Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Tue, 2 Jun 2026 00:17:45 -0700 Subject: [PATCH 132/194] Checkpoint all features native client work --- .../eq-core-dll/bin/dinput8.dll | Bin 1439744 -> 1554944 bytes .../eq-core-dll/src/core_autoloot_native.h | 5302 ++++++++++++++--- zone/client.h | 1 + zone/corpse.cpp | 13 + zone/inventory.cpp | 21 + 5 files changed, 4497 insertions(+), 840 deletions(-) diff --git a/client_files/native_autoloot/eq-core-dll/bin/dinput8.dll b/client_files/native_autoloot/eq-core-dll/bin/dinput8.dll index 2a803424eba5fa4917c065c7ecf55b4ca9b1c6cb..e855feec758fa6c5ed534d7d0b7e0a43fe291f8a 100644 GIT binary patch delta 619002 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≶hX5Nb&|+DI4Z2^ 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%0D&2Nh2Bk4xt8Vc+z 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 sL);>n+zML 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 {^%<0# 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%0A2oOo#)N&et{& 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
    kIs+8(22m0-+obFNa~V7ZIoA|uuDF@4w` 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 Pa)I)ci!=Iw&)ok5lUiVF diff --git a/client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h b/client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h index ffccf3ba23..6392c52cf6 100644 --- a/client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h +++ b/client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h @@ -1,11 +1,13 @@ #ifndef CORE_AUTOLOOT_NATIVE_H #define CORE_AUTOLOOT_NATIVE_H +#include #include #include #include #include #include +#include #include static void NativeAutoLootTrace(const char* format, ...) @@ -61,6 +63,15 @@ static void NativeSpellForgeShowWindow(const std::string& payload); static void NativeItemForgeShowWindow(const std::string& payload); static void NativeAchievementEnsureWindow(bool show); static bool NativeAchievementParseTransport(const char* message); +static void NativeUIShowcaseEnsureWindow(bool show); +static void NativeHpFixEnsureWindow(bool show); +static void NativeMulticlassEnsureWindow(bool show); +static void NativeMulticlassEnsurePetWindow(bool show); +static void NativeMulticlassEnsureMelodyWindow(bool show); +static void NativeMulticlassEnsureDisciplineWindow(bool show); +static bool NativeMulticlassParseTransport(const char* message); +static void NativeMulticlassInstallContextMenuHook(); +static void NativeMulticlassMaintainPresentationUI(); class NativeAutoLootWnd : public CCustomWnd { @@ -230,6 +241,7 @@ static bool gNativeAutoLootHooksInstalled = false; static bool gNativeAutoLootChatHookInstalled = false; static bool gNativeAutoLootCommandHookInstalled = false; static bool gNativeAutoLootPulseHookInstalled = false; +static bool gNativeAutoLootUiResetHookInstalled = false; static bool gNativeAutoLootRequestedInitialStatus = false; static bool gNativeAutoLootPulseHookEnabled = false; static bool gNativeAutoLootEnabled = false; @@ -239,6 +251,7 @@ static int gNativeAutoLootInGamePulses = 0; static int gNativeAutoLootKeepCount = 0; static int gNativeAutoLootIgnoreCount = 0; static bool gNativeLiveSpellSentReady = false; +static bool gNativeHpFixSentReady = false; static bool gNativeAutoLootPulseFaulted = false; static std::string gNativeAutoLootGroupMode = "solo"; static std::string gNativeAutoLootAssigned = "none"; @@ -388,6 +401,15 @@ static int NativeToInt(const std::string& value, int fallback = 0) return atoi(value.c_str()); } +static long long NativeToInt64(const std::string& value, long long fallback = 0) +{ + if (value.empty()) { + return fallback; + } + + return _strtoi64(value.c_str(), nullptr, 10); +} + static bool NativeToBool(const std::string& value) { return NativeToInt(value) != 0 || value == "true" || value == "on"; @@ -402,227 +424,2164 @@ static float NativeToFloat(const std::string& value, float fallback = 0.0f) return static_cast(atof(value.c_str())); } -template -static void NativeCopyText(char (&destination)[Size], const std::string& source) +struct NativeItemPowerInfo { - memset(destination, 0, Size); - strncpy_s(destination, source.c_str(), Size - 1); -} + int item_id = 0; + int item_level = 0; + int score = 0; + int version = 0; + std::string role; + std::string source; + std::string name; + DWORD last_seen = 0; +}; -static bool NativeIsKeepRule(const std::string& rule) +struct NativeItemRarityInfo { - return rule == "include" || rule == "keep" || rule == "always" || rule == "loot"; -} + int item_id = 0; + int rarity = 0; + std::string name; + DWORD last_seen = 0; +}; -static bool NativeIsNeverRule(const std::string& rule) -{ - return rule == "exclude" || rule == "ignore" || rule == "never" || rule == "skip"; -} +static std::unordered_map gNativeItemPowerById; +static std::unordered_map gNativeItemRarityById; -static const char* NativeShortRule(const std::string& rule) +static bool NativeItemPowerParseTransport(const char* message) { - if (NativeIsKeepRule(rule)) { - return "X"; + if (!message || !NativeStartsWith(message, "ITEMPOWER|")) { + return false; } - if (NativeIsNeverRule(rule)) { - return "X"; + const std::string payload(message); + const int item_id = NativeToInt(NativeGetPairValue(payload, "item_id")); + if (item_id <= 0) { + return true; } - return ""; + if (NativeStartsWith(message, "ITEMPOWER|clear|")) { + gNativeItemPowerById.erase(item_id); + NativeAutoLootTrace("ItemPower cleared item_id=%d", item_id); + return true; + } + + NativeItemPowerInfo info; + info.item_id = item_id; + info.item_level = NativeToInt(NativeGetPairValue(payload, "ilvl")); + info.score = NativeToInt(NativeGetPairValue(payload, "score")); + info.version = NativeToInt(NativeGetPairValue(payload, "version")); + info.role = NativeGetPairValue(payload, "role"); + info.source = NativeGetPairValue(payload, "source"); + info.name = NativeGetPairValue(payload, "name"); + info.last_seen = GetTickCount(); + + if (info.item_level > 0 || info.score > 0) { + gNativeItemPowerById[item_id] = info; + NativeAutoLootTrace( + "ItemPower cached item_id=%d ilvl=%d score=%d role=%s source=%s", + info.item_id, + info.item_level, + info.score, + info.role.c_str(), + info.source.c_str() + ); + } + + return true; } -static const char* NativeDisplayRule(const std::string& rule) +static bool NativeItemRarityParseTransport(const char* message) { - if (NativeIsNeverRule(rule)) { - return "Never"; + if (!message || !NativeStartsWith(message, "ITEMRARITY|")) { + return false; } - if (NativeIsKeepRule(rule)) { - return "Keep"; + const std::string payload(message); + const int item_id = NativeToInt(NativeGetPairValue(payload, "item_id")); + if (item_id <= 0) { + return true; } - return "-"; + if (NativeStartsWith(message, "ITEMRARITY|clear|")) { + gNativeItemRarityById.erase(item_id); + NativeAutoLootTrace("ItemRarity cleared item_id=%d", item_id); + return true; + } + + NativeItemRarityInfo info; + info.item_id = item_id; + info.rarity = NativeToInt(NativeGetPairValue(payload, "rarity")); + info.name = NativeGetPairValue(payload, "name"); + info.last_seen = GetTickCount(); + if (info.rarity >= 0 && info.rarity <= 4) { + gNativeItemRarityById[item_id] = info; + NativeAutoLootTrace("ItemRarity cached item_id=%d rarity=%d name=%s", item_id, info.rarity, info.name.c_str()); + } + + return true; } -struct NativeAchievementCategoryRow +template +static void NativeCopyText(char (&destination)[Size], const std::string& source) +{ + memset(destination, 0, Size); + strncpy_s(destination, source.c_str(), Size - 1); +} + +struct NativeMulticlassClassDef { int id = 0; - int parent_id = 0; - int total = 0; - int completed = 0; - int points = 0; - std::string name = "Category"; + const char* name = ""; }; -struct NativeAchievementRow +static const NativeMulticlassClassDef gNativeMulticlassClassDefs[] = { + {1, "Warrior"}, + {2, "Cleric"}, + {3, "Paladin"}, + {4, "Ranger"}, + {5, "Shadow Knight"}, + {6, "Druid"}, + {7, "Monk"}, + {8, "Bard"}, + {9, "Rogue"}, + {10, "Shaman"}, + {11, "Necromancer"}, + {12, "Wizard"}, + {13, "Magician"}, + {14, "Enchanter"}, + {15, "Beastlord"}, + {16, "Berserker"} +}; + +struct NativeMulticlassPetRow { int id = 0; - int category_id = 0; - int points = 0; - bool completed = false; - std::string name = "Achievement"; - std::string description; + int hp = 0; + int mana = 0; + bool taunt = false; + bool hold = false; + bool spellhold = false; + bool focused = false; + std::string name = "Pet"; + std::string order = "follow"; + std::string target = "-"; }; -struct NativeAchievementObjectiveRow +struct NativeMulticlassMelodySlot { - int id = 0; - int current = 0; - int required = 0; - bool completed = false; - std::string name = "Objective"; + int slot = 0; + int spell_id = 0; + int level = 0; + std::string name = "-"; + std::string state = "empty"; }; -class NativeAchievementWnd : public CCustomWnd +struct NativeMulticlassMelodySong { -public: - NativeAchievementWnd() : CCustomWnd((char*)"NativeAchievementWnd") - { - CloseOnESC = 1; - SetWndNotification(NativeAchievementWnd); + int spell_id = 0; + int level = 0; + bool allowed = false; + std::string name = "Song"; + std::string reason; +}; - SummaryLabel = GetChildItem("NAW_SummaryLabel"); - CategoryList = (CListWnd*)GetChildItem("NAW_CategoryList"); - AchievementList = (CListWnd*)GetChildItem("NAW_AchievementList"); - DetailTitleLabel = GetChildItem("NAW_DetailTitleLabel"); - DetailDescriptionLabel = GetChildItem("NAW_DetailDescriptionLabel"); - ObjectiveList = (CListWnd*)GetChildItem("NAW_ObjectiveList"); - StatusLabel = GetChildItem("NAW_StatusLabel"); - RefreshButton = (CButtonWnd*)GetChildItem("NAW_RefreshButton"); - CheckButton = (CButtonWnd*)GetChildItem("NAW_CheckButton"); +struct NativeMulticlassDisciplineRow +{ + int slot = 0; + int spell_id = 0; + int level = 0; + int timer = 0; + int timer_total = 0; + DWORD timer_received_ms = 0; + bool ready = false; + std::string name = "Discipline"; + std::string state = "Blocked"; +}; - Layout(); - SetStatus("Open with /achievement, /ach, #achievement, or #ach."); - RefreshRows(); - } +struct NativeMulticlassState +{ + bool has_profile = false; + bool locked = false; + bool can_choose = false; + bool multiple_pets = false; + int class1 = 0; + int class2 = 0; + int class3 = 0; + int presentation = 0; + int base = 0; + int reweaves = 0; + int selected_slot2 = 0; + int selected_slot3 = 0; + int roster_count = 0; + int roster_limit = 1; + int focus_id = 0; + int mana = 0; + int max_mana = 0; + int endurance = 0; + int max_endurance = 0; + int class_mask = 0; + int aa_mask = 0; + std::string profile_name = "Unchosen Trio"; + std::string resonance_key; + std::string class1_name = "Base"; + std::string class2_name = "Unchosen"; + std::string class3_name = "Unchosen"; + std::string presentation_name = "Unknown"; + std::string base_name = "Unknown"; + std::string roles = "-"; + std::string resonance = "Trio Notes"; + std::string summary = "Waiting for Multiclass profile."; + std::string skill_summary = "Skills: waiting for profile."; + std::string bonus_summary = "Resonance bonuses: waiting for profile."; + std::string selection_status = "Waiting for Multiclass profile..."; + std::string pet_policy = "single-pet"; + std::string pet_control = "Pet console pending."; + bool has_bard = false; + std::string melody_status = "Bard Melody: waiting for profile."; + std::string discipline_status = "Disciplines: waiting for profile."; +}; - int WndNotification(CXWnd* pWnd, unsigned int Message, void* unknown) - { - if (Message == XWM_CLOSE) { - pXWnd()->Show(0, 1); - return 1; +class NativeMulticlassWnd; +class NativeMulticlassPetWnd; +class NativeMulticlassMelodyWnd; +class NativeMulticlassDisciplineWnd; + +static NativeMulticlassWnd* gNativeMulticlassWnd = nullptr; +static NativeMulticlassPetWnd* gNativeMulticlassPetWnd = nullptr; +static NativeMulticlassMelodyWnd* gNativeMulticlassMelodyWnd = nullptr; +static NativeMulticlassDisciplineWnd* gNativeMulticlassDisciplineWnd = nullptr; +static NativeMulticlassState gNativeMulticlassState; +static std::vector gNativeMulticlassPets; +static std::vector gNativeMulticlassMelodySlots; +static std::vector gNativeMulticlassMelodySongs; +static std::vector gNativeMulticlassDisciplineRows; +static bool gNativeMulticlassSentStatus = false; +static bool gNativeMulticlassContextMenuHookInstalled = false; +static bool gNativeMulticlassContextMenuHookEnabled = true; +static bool gNativeMulticlassSpellLevelsLoading = false; +static int gNativeMulticlassSpellLevelPatchCount = 0; +static int gNativeMulticlassShowCasterUiPulses = 0; +static std::unordered_map gNativeMulticlassSpellLevelsById; +static std::unordered_map gNativeMulticlassSpellLevelsByName; + +static void NativeMulticlassRefreshWindows(); +static void NativeMulticlassNormalizeSelections(); +static bool NativeMulticlassRewriteSpellMenuText(const char* text, std::string& rewritten); + +static bool NativeMulticlassIsPlayerClass(int class_id) +{ + return class_id >= 1 && class_id <= 16; +} + +static const char* NativeMulticlassClassName(int class_id) +{ + for (const auto& class_def : gNativeMulticlassClassDefs) { + if (class_def.id == class_id) { + return class_def.name; } + } - if (Message == XWM_LCLICK) { - if (pWnd == (CXWnd*)RefreshButton) { - char command[128]; - sprintf_s(command, "/say #ach native refresh %d %d", SelectedCategoryID, SelectedAchievementID); - NativeAutoLootSendCommand(command); - SetStatus("Refreshing achievements..."); - return 1; - } + return "Unchosen"; +} - if (pWnd == (CXWnd*)CheckButton) { - char command[128]; - sprintf_s(command, "/say #ach native check %d %d", SelectedCategoryID, SelectedAchievementID); - NativeAutoLootSendCommand(command); - SetStatus("Checking automatic achievements..."); - return 1; - } +static DWORD NativeMulticlassToDword(int value) +{ + return value > 0 ? (DWORD)value : 0; +} - if (pWnd == (CXWnd*)CategoryList) { - NativeAchievementCategoryRow* category = GetSelectedCategory(); - if (category && category->id > 0 && category->id != SelectedCategoryID) { - char command[128]; - sprintf_s(command, "/say #ach native category %d", category->id); - NativeAutoLootSendCommand(command); - SetStatus("Loading achievement category..."); - } - return 1; - } +static bool NativeMulticlassPresentationUsesMana(int class_id) +{ + switch (class_id) { + case 2: // Cleric + case 3: // Paladin + case 4: // Ranger + case 5: // Shadow Knight + case 6: // Druid + case 8: // Bard + case 10: // Shaman + case 11: // Necromancer + case 12: // Wizard + case 13: // Magician + case 14: // Enchanter + case 15: // Beastlord + return true; + default: + return false; + } +} - if (pWnd == (CXWnd*)AchievementList) { - NativeAchievementRow* achievement = GetSelectedAchievement(); - if (achievement && achievement->id > 0 && achievement->id != SelectedAchievementID) { - char command[128]; - sprintf_s(command, "/say #ach native detail %d %d", achievement->id, SelectedCategoryID); - NativeAutoLootSendCommand(command); - SetStatus("Loading achievement detail..."); - } - return 1; - } - } +static void NativeMulticlassScheduleCasterUI() +{ + if ( + gNativeMulticlassState.has_profile && + NativeMulticlassPresentationUsesMana(gNativeMulticlassState.presentation) + ) { + gNativeMulticlassShowCasterUiPulses = 240; + } +} - return CSidlScreenWnd::WndNotification(pWnd, Message, unknown); +static void NativeMulticlassPatchPlayerData(EQPlayer* player) +{ + if (!player) { + return; } - void Layout() - { - // Achievement resize is handled by SIDL AutoStretch anchors. + if (NativeMulticlassIsPlayerClass(gNativeMulticlassState.presentation)) { + player->Data.Class = (BYTE)gNativeMulticlassState.presentation; } - void RefreshRows(); - void SetStatus(const char* text) - { - SetLabel(StatusLabel, text ? text : ""); + if (gNativeMulticlassState.max_mana > 0) { + player->Data.ManaCurrent = NativeMulticlassToDword(gNativeMulticlassState.mana); + player->Data.ManaMax = NativeMulticlassToDword(gNativeMulticlassState.max_mana); } -private: - NativeAchievementCategoryRow* GetSelectedCategory(); - NativeAchievementRow* GetSelectedAchievement(); - void RefreshCategoryList(); - void RefreshAchievementList(); - void RefreshObjectiveList(); - void SelectCategoryListRow(); - void SelectAchievementListRow(); - void SetLabel(CXWnd* label, const char* text) - { - if (label) { - CXStr value(text ? text : ""); - label->SetWindowTextA(value); - } + if (gNativeMulticlassState.max_endurance > 0) { + player->Data.EnduranceMax = NativeMulticlassToDword(gNativeMulticlassState.max_endurance); } +} - CXWnd* SummaryLabel = nullptr; - CListWnd* CategoryList = nullptr; - CListWnd* AchievementList = nullptr; - CXWnd* DetailTitleLabel = nullptr; - CXWnd* DetailDescriptionLabel = nullptr; - CListWnd* ObjectiveList = nullptr; - CXWnd* StatusLabel = nullptr; - CButtonWnd* RefreshButton = nullptr; - CButtonWnd* CheckButton = nullptr; - int SelectedCategoryID = 0; - int SelectedAchievementID = 0; -}; +static void NativeMulticlassPatchLocalVitals() +{ + if ( + !gNativeMulticlassState.has_profile || + !NativeMulticlassPresentationUsesMana(gNativeMulticlassState.presentation) || + !ppCharData || + !pCharData + ) { + return; + } -static NativeAchievementWnd* gNativeAchievementWnd = nullptr; -static std::vector gNativeAchievementCategories; -static std::vector gNativeAchievementRows; -static std::vector gNativeAchievementObjectives; -static int gNativeAchievementSelectedCategory = 0; -static int gNativeAchievementSelectedAchievement = 0; -static int gNativeAchievementCompleted = 0; -static int gNativeAchievementTotal = 0; -static int gNativeAchievementPoints = 0; -static int gNativeAchievementCategoryCount = 0; -static bool gNativeAchievementLoading = false; -static bool gNativeAchievementCategoriesDirty = true; -static bool gNativeAchievementRowsDirty = true; -static bool gNativeAchievementObjectivesDirty = true; -static std::string gNativeAchievementDetailTitle = "Select an achievement"; -static std::string gNativeAchievementDetailDescription = ""; + __try { + PCHARINFO2 char_info = GetCharInfo2(); + if (char_info) { + if (NativeMulticlassIsPlayerClass(gNativeMulticlassState.presentation)) { + char_info->Class = (DWORD)gNativeMulticlassState.presentation; + } + if (gNativeMulticlassState.max_mana > 0) { + char_info->Mana = NativeMulticlassToDword(gNativeMulticlassState.mana); + } + if (gNativeMulticlassState.max_endurance > 0) { + char_info->Endurance = NativeMulticlassToDword(gNativeMulticlassState.endurance); + } + } -class NativeSpellForgeWnd : public CCustomWnd -{ -public: - NativeSpellForgeWnd() : CCustomWnd((char*)"NativeSpellForgeWnd") - { - CloseOnESC = 1; - SetWndNotification(NativeSpellForgeWnd); + if (ppLocalPlayer) { + NativeMulticlassPatchPlayerData(pLocalPlayer); + } + if (ppCharSpawn && pCharSpawn && (!ppLocalPlayer || pCharSpawn != pLocalPlayer)) { + NativeMulticlassPatchPlayerData(pCharSpawn); + } + } + __except (EXCEPTION_EXECUTE_HANDLER) { + } +} - FormTab = (CButtonWnd*)GetChildItem("ASFW_FormTab"); - DeliveryTab = (CButtonWnd*)GetChildItem("ASFW_DeliveryTab"); - PowerTab = (CButtonWnd*)GetChildItem("ASFW_PowerTab"); - CastingTab = (CButtonWnd*)GetChildItem("ASFW_CastingTab"); - ReviewTab = (CButtonWnd*)GetChildItem("ASFW_ReviewTab"); +static void NativeMulticlassShowPlayerManaPiece(const char* child_name) +{ + if (!child_name || !pPlayerWnd) { + return; + } - FormPage = GetChildItem("ASFW_FormPage"); - DeliveryPage = GetChildItem("ASFW_DeliveryPage"); - PowerPage = GetChildItem("ASFW_PowerPage"); - CastingPage = GetChildItem("ASFW_CastingPage"); - ReviewPage = GetChildItem("ASFW_ReviewPage"); + CXWnd* child = nullptr; + __try { + child = pPlayerWnd->GetChildItem((char*)child_name); + } + __except (EXCEPTION_EXECUTE_HANDLER) { + child = nullptr; + } + + if (child) { + child->Show(1, 1); + } +} + +static void NativeMulticlassShowSpellGemWindow() +{ + if (!ppCastSpellWnd || !pCastSpellWnd) { + return; + } + + __try { + CXWnd* spell_window = (CXWnd*)pCastSpellWnd; + if (spell_window) { + spell_window->Show(1, 1); + } + } + __except (EXCEPTION_EXECUTE_HANDLER) { + } +} + +static void NativeMulticlassMaintainPresentationUI() +{ + if ( + !gNativeMulticlassState.has_profile || + !NativeMulticlassPresentationUsesMana(gNativeMulticlassState.presentation) || + !pPlayerWnd + ) { + return; + } + + NativeMulticlassPatchLocalVitals(); + NativeMulticlassShowPlayerManaPiece("Player_Mana"); + NativeMulticlassShowPlayerManaPiece("PlayerMana"); + NativeMulticlassShowPlayerManaPiece("Player_ManaLabel"); + NativeMulticlassShowPlayerManaPiece("ManaLabel"); + NativeMulticlassShowPlayerManaPiece("Player_ManaPercLabel"); + NativeMulticlassShowPlayerManaPiece("ManPercLabel"); + + if (gNativeMulticlassShowCasterUiPulses > 0) { + --gNativeMulticlassShowCasterUiPulses; + NativeMulticlassShowSpellGemWindow(); + } +} + +static std::string NativeMulticlassNormalizedName(const std::string& value) +{ + std::string normalized; + normalized.reserve(value.size()); + bool previous_space = false; + for (char c : value) { + const unsigned char ch = static_cast(c); + if (isspace(ch)) { + if (!normalized.empty() && !previous_space) { + normalized.push_back(' '); + } + previous_space = true; + continue; + } + + normalized.push_back(static_cast(tolower(ch))); + previous_space = false; + } + + while (!normalized.empty() && normalized[normalized.size() - 1] == ' ') { + normalized.resize(normalized.size() - 1); + } + + return normalized; +} + +static void NativeMulticlassSetLabel(CXWnd* label, const char* text) +{ + if (label) { + CXStr value(text ? text : ""); + label->SetWindowTextA(value); + } +} + +static void NativeMulticlassSetButtonText(CButtonWnd* button, const char* text) +{ + if (button) { + CXStr value(text ? text : ""); + ((CXWnd*)button)->SetWindowTextA(value); + } +} + +static void NativeMulticlassSetVisible(CXWnd* wnd, bool visible) +{ + if (wnd) { + wnd->Show(visible ? 1 : 0, 1); + } +} + +static bool NativeMulticlassClassAvailableForSlot(int class_id, int slot) +{ + if (!NativeMulticlassIsPlayerClass(class_id)) { + return false; + } + + if (class_id == gNativeMulticlassState.class1) { + return false; + } + + if (slot == 2 && class_id == gNativeMulticlassState.selected_slot3) { + return false; + } + + if (slot == 3 && class_id == gNativeMulticlassState.selected_slot2) { + return false; + } + + return true; +} + +static int NativeMulticlassNextClass(int current, int direction, int slot) +{ + if (direction == 0) { + direction = 1; + } + + int candidate = NativeMulticlassIsPlayerClass(current) ? current : 1; + for (int step = 0; step < 16; ++step) { + candidate += direction > 0 ? 1 : -1; + if (candidate > 16) { + candidate = 1; + } + else if (candidate < 1) { + candidate = 16; + } + + if (NativeMulticlassClassAvailableForSlot(candidate, slot)) { + return candidate; + } + } + + return current; +} + +static void NativeMulticlassNormalizeSelections() +{ + if (gNativeMulticlassState.locked) { + gNativeMulticlassState.selected_slot2 = gNativeMulticlassState.class2; + gNativeMulticlassState.selected_slot3 = gNativeMulticlassState.class3; + return; + } + + if (!NativeMulticlassClassAvailableForSlot(gNativeMulticlassState.selected_slot2, 2)) { + gNativeMulticlassState.selected_slot2 = NativeMulticlassNextClass(gNativeMulticlassState.class1, 1, 2); + } + + if (!NativeMulticlassClassAvailableForSlot(gNativeMulticlassState.selected_slot3, 3)) { + gNativeMulticlassState.selected_slot3 = NativeMulticlassNextClass(gNativeMulticlassState.selected_slot2, 1, 3); + } +} + +static NativeMulticlassPetRow* NativeMulticlassFindPet(int pet_id) +{ + if (pet_id <= 0) { + return nullptr; + } + + for (auto& pet : gNativeMulticlassPets) { + if (pet.id == pet_id) { + return &pet; + } + } + + return nullptr; +} + +static bool NativeMulticlassApplySpellLevelPatch(const std::string& payload) +{ + const int spell_id = NativeToInt(NativeGetPairValue(payload, "id")); + const int level = NativeToInt(NativeGetPairValue(payload, "level"), 255); + const int presentation = NativeToInt(NativeGetPairValue(payload, "presentation")); + + if (!pSpellMgr || spell_id <= 0 || spell_id >= TOTAL_SPELL_COUNT || level <= 0 || level > 254 || presentation < 1 || presentation > 16) { + NativeAutoLootTrace("multiclass rejected spell level patch: id=%d level=%d presentation=%d", spell_id, level, presentation); + return true; + } + + PSPELLMGR spell_mgr = (PSPELLMGR)pSpellMgr; + PSPELL spell = spell_mgr->Spells[spell_id]; + if (!spell) { + NativeAutoLootTrace("multiclass spell level patch missing spell: id=%d", spell_id); + return true; + } + + spell->Level[presentation - 1] = static_cast(level); + gNativeMulticlassSpellLevelsById[spell_id] = level; + + if (spell->Name[0]) { + gNativeMulticlassSpellLevelsByName[NativeMulticlassNormalizedName(spell->Name)] = level; + } + + ++gNativeMulticlassSpellLevelPatchCount; + return true; +} + +static bool NativeMulticlassRewriteSpellMenuText(const char* text, unsigned int menu_id, std::string& rewritten) +{ + if (!text || !text[0] || (gNativeMulticlassSpellLevelsByName.empty() && gNativeMulticlassSpellLevelsById.empty())) { + return false; + } + + const char* cursor = text; + while (*cursor == ' ' || *cursor == '\t') { + ++cursor; + } + + if (!isdigit(static_cast(*cursor))) { + return false; + } + + int displayed_level = 0; + while (isdigit(static_cast(*cursor))) { + displayed_level = (displayed_level * 10) + (*cursor - '0'); + ++cursor; + } + + if (cursor[0] != ' ' || cursor[1] != '-' || cursor[2] != ' ') { + return false; + } + + cursor += 3; + int approved_level = 0; + const auto found_by_id = gNativeMulticlassSpellLevelsById.find(static_cast(menu_id)); + if (found_by_id != gNativeMulticlassSpellLevelsById.end()) { + approved_level = found_by_id->second; + } + + if (!approved_level) { + const std::string spell_name = NativeMulticlassNormalizedName(cursor); + const auto found_by_name = gNativeMulticlassSpellLevelsByName.find(spell_name); + if (found_by_name != gNativeMulticlassSpellLevelsByName.end()) { + approved_level = found_by_name->second; + } + } + + if (approved_level <= 0 || approved_level == displayed_level) { + return false; + } + + char buffer[256]; + sprintf_s(buffer, "%d - %s", approved_level, cursor); + rewritten = buffer; + return true; +} + +class NativeMulticlassWnd : public CCustomWnd +{ +public: + NativeMulticlassWnd() : CCustomWnd((char*)"NativeMulticlassWnd") + { + CloseOnESC = 1; + SetWndNotification(NativeMulticlassWnd); + + StatusLabel = GetChildItem("MCW_StatusLabel"); + RefreshButton = (CButtonWnd*)GetChildItem("MCW_RefreshButton"); + TrioLabel = GetChildItem("MCW_TrioLabel"); + PresentationLabel = GetChildItem("MCW_PresentationLabel"); + Slot2Label = GetChildItem("MCW_Slot2Label"); + Slot2PrevButton = (CButtonWnd*)GetChildItem("MCW_Slot2PrevButton"); + Slot2ValueLabel = GetChildItem("MCW_Slot2ValueLabel"); + Slot2NextButton = (CButtonWnd*)GetChildItem("MCW_Slot2NextButton"); + Slot3Label = GetChildItem("MCW_Slot3Label"); + Slot3PrevButton = (CButtonWnd*)GetChildItem("MCW_Slot3PrevButton"); + Slot3ValueLabel = GetChildItem("MCW_Slot3ValueLabel"); + Slot3NextButton = (CButtonWnd*)GetChildItem("MCW_Slot3NextButton"); + MelodyButton = (CButtonWnd*)GetChildItem("MCW_MelodyButton"); + DiscsButton = (CButtonWnd*)GetChildItem("MCW_DiscsButton"); + PetsButton = (CButtonWnd*)GetChildItem("MCW_PetsButton"); + LockButton = (CButtonWnd*)GetChildItem("MCW_LockButton"); + InfoHeaderLabel = GetChildItem("MCW_InfoHeaderLabel"); + InfoLabel = GetChildItem("MCW_InfoLabel"); + + Layout(); + Refresh(); + } + + int WndNotification(CXWnd* pWnd, unsigned int Message, void* unknown) + { + if (Message == XWM_CLOSE) { + pXWnd()->Show(0, 1); + return 1; + } + + if (Message == XWM_LCLICK) { + if (pWnd == (CXWnd*)RefreshButton) { + NativeAutoLootSendCommand("/say #mc refresh"); + SetStatus("Refreshing Multiclass profile..."); + return 1; + } + + if (pWnd == (CXWnd*)PetsButton) { + NativeMulticlassEnsurePetWindow(true); + NativeAutoLootSendCommand("/say #mc pets"); + SetStatus("Opening pet console..."); + return 1; + } + + if (pWnd == (CXWnd*)MelodyButton) { + NativeMulticlassEnsureMelodyWindow(true); + NativeAutoLootSendCommand("/say #mc melody open"); + SetStatus("Opening Bard Melody..."); + return 1; + } + + if (pWnd == (CXWnd*)DiscsButton) { + NativeMulticlassEnsureDisciplineWindow(true); + NativeAutoLootSendCommand("/say #mc disc open"); + SetStatus("Opening discipline tools..."); + return 1; + } + + if (pWnd == (CXWnd*)Slot2PrevButton || pWnd == (CXWnd*)Slot2NextButton) { + if (!gNativeMulticlassState.locked && gNativeMulticlassState.can_choose) { + gNativeMulticlassState.selected_slot2 = NativeMulticlassNextClass(gNativeMulticlassState.selected_slot2, pWnd == (CXWnd*)Slot2NextButton ? 1 : -1, 2); + NativeMulticlassNormalizeSelections(); + Refresh(); + } + return 1; + } + + if (pWnd == (CXWnd*)Slot3PrevButton || pWnd == (CXWnd*)Slot3NextButton) { + if (!gNativeMulticlassState.locked && gNativeMulticlassState.can_choose) { + gNativeMulticlassState.selected_slot3 = NativeMulticlassNextClass(gNativeMulticlassState.selected_slot3, pWnd == (CXWnd*)Slot3NextButton ? 1 : -1, 3); + NativeMulticlassNormalizeSelections(); + Refresh(); + } + return 1; + } + + if (pWnd == (CXWnd*)LockButton) { + if (gNativeMulticlassState.locked) { + SetStatus("This trio is already locked."); + return 1; + } + + NativeMulticlassNormalizeSelections(); + if (!NativeMulticlassIsPlayerClass(gNativeMulticlassState.selected_slot2) || !NativeMulticlassIsPlayerClass(gNativeMulticlassState.selected_slot3)) { + SetStatus("Choose two added classes before locking."); + return 1; + } + + char command[128]; + sprintf_s(command, "/say #mc choose %d %d", gNativeMulticlassState.selected_slot2, gNativeMulticlassState.selected_slot3); + NativeAutoLootSendCommand(command); + SetStatus("Locking trio..."); + return 1; + } + } + + return CSidlScreenWnd::WndNotification(pWnd, Message, unknown); + } + + void Layout() + { + } + + void SetStatus(const char* text) + { + NativeMulticlassSetLabel(StatusLabel, text); + } + + void Refresh() + { + NativeMulticlassNormalizeSelections(); + + NativeMulticlassSetLabel(StatusLabel, gNativeMulticlassState.selection_status.c_str()); + + char trio[192]; + sprintf_s( + trio, + "%s / %s / %s [%s]", + gNativeMulticlassState.class1_name.c_str(), + gNativeMulticlassState.class2_name.c_str(), + gNativeMulticlassState.class3_name.c_str(), + gNativeMulticlassState.profile_name.c_str() + ); + NativeMulticlassSetLabel(TrioLabel, trio); + + char presentation[256]; + if (gNativeMulticlassState.max_mana > 0) { + sprintf_s( + presentation, + "Presentation: %s. Base: %s. Mana: %d/%d. Pets: %s. Reweaves: %d.", + gNativeMulticlassState.presentation_name.c_str(), + gNativeMulticlassState.base_name.c_str(), + gNativeMulticlassState.mana, + gNativeMulticlassState.max_mana, + gNativeMulticlassState.multiple_pets ? "enabled" : "disabled", + gNativeMulticlassState.reweaves + ); + } + else { + sprintf_s( + presentation, + "Presentation: %s. Base: %s. Pets: %s. Reweaves: %d.", + gNativeMulticlassState.presentation_name.c_str(), + gNativeMulticlassState.base_name.c_str(), + gNativeMulticlassState.multiple_pets ? "enabled" : "disabled", + gNativeMulticlassState.reweaves + ); + } + NativeMulticlassSetLabel(PresentationLabel, presentation); + + NativeMulticlassSetLabel(Slot2Label, "Second Class"); + NativeMulticlassSetLabel(Slot3Label, "Third Class"); + NativeMulticlassSetLabel(Slot2ValueLabel, NativeMulticlassClassName(gNativeMulticlassState.selected_slot2)); + NativeMulticlassSetLabel(Slot3ValueLabel, NativeMulticlassClassName(gNativeMulticlassState.selected_slot3)); + + const bool editable = !gNativeMulticlassState.locked && gNativeMulticlassState.can_choose; + NativeMulticlassSetVisible((CXWnd*)Slot2PrevButton, editable); + NativeMulticlassSetVisible((CXWnd*)Slot2NextButton, editable); + NativeMulticlassSetVisible((CXWnd*)Slot3PrevButton, editable); + NativeMulticlassSetVisible((CXWnd*)Slot3NextButton, editable); + NativeMulticlassSetVisible((CXWnd*)MelodyButton, gNativeMulticlassState.has_bard); + NativeMulticlassSetVisible((CXWnd*)DiscsButton, gNativeMulticlassState.locked); + NativeMulticlassSetButtonText(LockButton, gNativeMulticlassState.locked ? "Locked" : "Lock Trio"); + + char info_header[192]; + sprintf_s(info_header, "Trio Notes - %s", gNativeMulticlassState.resonance.c_str()); + NativeMulticlassSetLabel(InfoHeaderLabel, info_header); + + char info[768]; + sprintf_s( + info, + "%s Roles: %s. %s %s", + gNativeMulticlassState.summary.c_str(), + gNativeMulticlassState.roles.c_str(), + gNativeMulticlassState.skill_summary.c_str(), + gNativeMulticlassState.bonus_summary.c_str() + ); + NativeMulticlassSetLabel(InfoLabel, info); + } + +private: + CXWnd* StatusLabel = nullptr; + CButtonWnd* RefreshButton = nullptr; + CXWnd* TrioLabel = nullptr; + CXWnd* PresentationLabel = nullptr; + CXWnd* Slot2Label = nullptr; + CButtonWnd* Slot2PrevButton = nullptr; + CXWnd* Slot2ValueLabel = nullptr; + CButtonWnd* Slot2NextButton = nullptr; + CXWnd* Slot3Label = nullptr; + CButtonWnd* Slot3PrevButton = nullptr; + CXWnd* Slot3ValueLabel = nullptr; + CButtonWnd* Slot3NextButton = nullptr; + CButtonWnd* MelodyButton = nullptr; + CButtonWnd* DiscsButton = nullptr; + CButtonWnd* PetsButton = nullptr; + CButtonWnd* LockButton = nullptr; + CXWnd* InfoHeaderLabel = nullptr; + CXWnd* InfoLabel = nullptr; +}; + +class NativeMulticlassPetWnd : public CCustomWnd +{ +public: + NativeMulticlassPetWnd() : CCustomWnd((char*)"NativeMulticlassPetWnd") + { + CloseOnESC = 1; + SetWndNotification(NativeMulticlassPetWnd); + + StatusLabel = GetChildItem("MCPW_StatusLabel"); + RefreshButton = (CButtonWnd*)GetChildItem("MCPW_RefreshButton"); + PetList = (CListWnd*)GetChildItem("MCPW_PetList"); + AttackButton = (CButtonWnd*)GetChildItem("MCPW_PetAttackButton"); + BackButton = (CButtonWnd*)GetChildItem("MCPW_PetBackButton"); + FollowButton = (CButtonWnd*)GetChildItem("MCPW_PetFollowButton"); + GuardButton = (CButtonWnd*)GetChildItem("MCPW_PetGuardButton"); + HealthButton = (CButtonWnd*)GetChildItem("MCPW_PetHealthButton"); + TauntButton = (CButtonWnd*)GetChildItem("MCPW_PetTauntButton"); + SitButton = (CButtonWnd*)GetChildItem("MCPW_PetSitButton"); + HoldButton = (CButtonWnd*)GetChildItem("MCPW_PetHoldButton"); + SpellHoldButton = (CButtonWnd*)GetChildItem("MCPW_PetSpellHoldButton"); + DismissButton = (CButtonWnd*)GetChildItem("MCPW_PetDismissButton"); + + Layout(); + RefreshRows(); + } + + int WndNotification(CXWnd* pWnd, unsigned int Message, void* unknown) + { + if (Message == XWM_CLOSE) { + pXWnd()->Show(0, 1); + return 1; + } + + if (Message == XWM_LCLICK) { + if (pWnd == (CXWnd*)PetList) { + const int selected_pet_id = SelectedPetID(); + if (selected_pet_id > 0) { + char command[128]; + sprintf_s(command, "/say #mc pet focus %d", selected_pet_id); + NativeAutoLootSendCommand(command); + SetStatus("Focusing pet..."); + } + return 1; + } + + if (pWnd == (CXWnd*)RefreshButton) { + NativeAutoLootSendCommand("/say #mc pet refresh"); + SetStatus("Refreshing pet roster..."); + return 1; + } + + if (pWnd == (CXWnd*)AttackButton) { + SendAction("attack", true); + return 1; + } + + if (pWnd == (CXWnd*)BackButton) { + SendAction("back", true); + return 1; + } + + if (pWnd == (CXWnd*)FollowButton) { + SendAction("follow", true); + return 1; + } + + if (pWnd == (CXWnd*)GuardButton) { + SendAction("guard", true); + return 1; + } + + if (pWnd == (CXWnd*)HealthButton) { + SendAction("health", true); + return 1; + } + + if (pWnd == (CXWnd*)TauntButton) { + SendAction("taunt", false); + return 1; + } + + if (pWnd == (CXWnd*)SitButton) { + SendAction("sit", false); + return 1; + } + + if (pWnd == (CXWnd*)HoldButton) { + SendAction("hold", false); + return 1; + } + + if (pWnd == (CXWnd*)SpellHoldButton) { + SendAction("spellhold", false); + return 1; + } + + if (pWnd == (CXWnd*)DismissButton) { + SendAction("dismiss", false); + return 1; + } + } + + return CSidlScreenWnd::WndNotification(pWnd, Message, unknown); + } + + void Layout() + { + } + + void SetStatus(const char* text) + { + NativeMulticlassSetLabel(StatusLabel, text); + } + + void RefreshRows() + { + if (!PetList) { + return; + } + + PetList->DeleteAll(); + + if (SelectedPetIDValue <= 0) { + SelectedPetIDValue = gNativeMulticlassState.focus_id; + } + + if (!NativeMulticlassFindPet(SelectedPetIDValue) && !gNativeMulticlassPets.empty()) { + SelectedPetIDValue = gNativeMulticlassState.focus_id > 0 ? gNativeMulticlassState.focus_id : gNativeMulticlassPets.front().id; + } + + int selected_row = -1; + for (const auto& pet : gNativeMulticlassPets) { + char name[128]; + sprintf_s(name, "%s%s", pet.focused ? "* " : "", pet.name.c_str()); + CXStr name_text(name); + const COLORREF row_color = pet.id == SelectedPetIDValue ? 0xFFFF4040 : 0xFFFFFFFF; + const int row = PetList->AddString(name_text, row_color, (uint32_t)pet.id, nullptr, nullptr); + + char hp_mp[32]; + sprintf_s(hp_mp, "%d/%d", pet.hp, pet.mana); + char toggles[32]; + sprintf_s(toggles, "%c/%c/%c", pet.taunt ? 'Y' : '-', pet.hold ? 'Y' : '-', pet.spellhold ? 'Y' : '-'); + CXStr order(pet.order.c_str()); + CXStr hpmp(hp_mp); + CXStr toggle_text(toggles); + PetList->SetItemText(row, 1, &order); + PetList->SetItemText(row, 2, &hpmp); + PetList->SetItemText(row, 3, &toggle_text); + + if (pet.id == SelectedPetIDValue) { + selected_row = row; + } + } + + if (gNativeMulticlassPets.empty()) { + CXStr dash("-"); + const int row = PetList->AddString(dash, 0xFFB0B0B0, 0, nullptr, nullptr); + CXStr empty("No active roster."); + PetList->SetItemText(row, 1, &empty); + PetList->SetItemText(row, 2, &dash); + PetList->SetItemText(row, 3, &dash); + } + else if (selected_row >= 0) { + PetList->SetCurSel(selected_row); + } + + char status[160]; + const NativeMulticlassPetRow* focused = NativeMulticlassFindPet(gNativeMulticlassState.focus_id); + sprintf_s( + status, + "Pets %d/%d. Focus: %s.", + gNativeMulticlassState.roster_count, + gNativeMulticlassState.roster_limit, + focused ? focused->name.c_str() : "-" + ); + SetStatus(status); + } + +private: + int SelectedPetID() + { + if (!PetList) { + return SelectedPetIDValue; + } + + const int selected = PetList->GetCurSel(); + if (selected < 0) { + return SelectedPetIDValue; + } + + const int pet_id = (int)PetList->GetItemData(selected); + if (pet_id > 0) { + SelectedPetIDValue = pet_id; + } + + return SelectedPetIDValue; + } + + void SendAction(const char* action, bool all_pets) + { + if (!action || !action[0]) { + return; + } + + char command[160]; + if (all_pets) { + sprintf_s(command, "/say #mc pet %s all", action); + } + else { + const int pet_id = SelectedPetID(); + if (pet_id > 0) { + sprintf_s(command, "/say #mc pet %s %d", action, pet_id); + } + else { + sprintf_s(command, "/say #mc pet %s", action); + } + } + + NativeAutoLootSendCommand(command); + SetStatus("Sending pet command..."); + } + + CXWnd* StatusLabel = nullptr; + CButtonWnd* RefreshButton = nullptr; + CListWnd* PetList = nullptr; + CButtonWnd* AttackButton = nullptr; + CButtonWnd* BackButton = nullptr; + CButtonWnd* FollowButton = nullptr; + CButtonWnd* GuardButton = nullptr; + CButtonWnd* HealthButton = nullptr; + CButtonWnd* TauntButton = nullptr; + CButtonWnd* SitButton = nullptr; + CButtonWnd* HoldButton = nullptr; + CButtonWnd* SpellHoldButton = nullptr; + CButtonWnd* DismissButton = nullptr; + int SelectedPetIDValue = 0; +}; + +class NativeMulticlassMelodyWnd : public CCustomWnd +{ +public: + NativeMulticlassMelodyWnd() : CCustomWnd((char*)"NativeMulticlassMelodyWnd") + { + CloseOnESC = 1; + SetWndNotification(NativeMulticlassMelodyWnd); + + StatusLabel = GetChildItem("MCMW_StatusLabel"); + RefreshButton = (CButtonWnd*)GetChildItem("MCMW_RefreshButton"); + SlotList = (CListWnd*)GetChildItem("MCMW_SlotList"); + SongList = (CListWnd*)GetChildItem("MCMW_SongList"); + PrevButton = (CButtonWnd*)GetChildItem("MCMW_PrevButton"); + NextButton = (CButtonWnd*)GetChildItem("MCMW_NextButton"); + ClearSlotButton = (CButtonWnd*)GetChildItem("MCMW_ClearSlotButton"); + ClearAllButton = (CButtonWnd*)GetChildItem("MCMW_ClearAllButton"); + FooterLabel = GetChildItem("MCMW_FooterLabel"); + + Layout(); + RefreshRows(); + } + + int WndNotification(CXWnd* pWnd, unsigned int Message, void* unknown) + { + if (Message == XWM_CLOSE) { + pXWnd()->Show(0, 1); + return 1; + } + + if (Message == XWM_LCLICK) { + if (pWnd == (CXWnd*)RefreshButton) { + NativeAutoLootSendCommand("/say #mc melody refresh"); + SetStatus("Refreshing Bard Melody..."); + return 1; + } + + if (pWnd == (CXWnd*)SlotList) { + SelectedSlot(); + RefreshRows(); + return 1; + } + + if (pWnd == (CXWnd*)SongList) { + const int spell_id = SelectedSongID(); + const int slot = SelectedSlot(); + if (slot > 0 && spell_id > 0) { + SendSet(slot, spell_id); + } + return 1; + } + + if (pWnd == (CXWnd*)PrevButton) { + CycleSong(-1); + return 1; + } + + if (pWnd == (CXWnd*)NextButton) { + CycleSong(1); + return 1; + } + + if (pWnd == (CXWnd*)ClearSlotButton) { + const int slot = SelectedSlot(); + if (slot > 0) { + char command[128]; + sprintf_s(command, "/say #mc melody clear %d", slot); + NativeAutoLootSendCommand(command); + SetStatus("Clearing melody slot..."); + } + return 1; + } + + if (pWnd == (CXWnd*)ClearAllButton) { + NativeAutoLootSendCommand("/say #mc melody clear"); + SetStatus("Clearing Bard Melody..."); + return 1; + } + } + + return CSidlScreenWnd::WndNotification(pWnd, Message, unknown); + } + + void Layout() + { + } + + void SetStatus(const char* text) + { + NativeMulticlassSetLabel(StatusLabel, text); + } + + void RefreshRows() + { + if (!SlotList || !SongList) { + return; + } + + SlotList->DeleteAll(); + SongList->DeleteAll(); + + if (SelectedSlotValue < 1 || SelectedSlotValue > 4) { + SelectedSlotValue = 1; + } + + int selected_slot_row = -1; + for (int slot_id = 1; slot_id <= 4; ++slot_id) { + const NativeMulticlassMelodySlot* slot = FindSlot(slot_id); + char label[24]; + sprintf_s(label, "Slot %d", slot_id); + CXStr slot_text(label); + const COLORREF row_color = slot_id == SelectedSlotValue ? 0xFFFF4040 : 0xFFFFFFFF; + const int row = SlotList->AddString(slot_text, row_color, (uint32_t)slot_id, nullptr, nullptr); + + CXStr song(slot ? slot->name.c_str() : "-"); + char level[32]; + sprintf_s(level, "%d", slot ? slot->level : 0); + CXStr level_text(slot && slot->level > 0 ? level : "-"); + CXStr state(slot ? slot->state.c_str() : "empty"); + SlotList->SetItemText(row, 1, &song); + SlotList->SetItemText(row, 2, &level_text); + SlotList->SetItemText(row, 3, &state); + + if (slot_id == SelectedSlotValue) { + selected_slot_row = row; + } + } + + if (selected_slot_row >= 0) { + SlotList->SetCurSel(selected_slot_row); + } + + int selected_song_row = -1; + for (const auto& song : gNativeMulticlassMelodySongs) { + CXStr name(song.name.c_str()); + const COLORREF row_color = song.allowed ? 0xFFFFFFFF : 0xFF909090; + const int row = SongList->AddString(name, row_color, (uint32_t)song.spell_id, nullptr, nullptr); + + char level[32]; + sprintf_s(level, "%d", song.level); + CXStr level_text(level); + CXStr state(song.allowed ? "Ready" : "Blocked"); + CXStr reason(song.reason.empty() ? "-" : song.reason.c_str()); + SongList->SetItemText(row, 1, &level_text); + SongList->SetItemText(row, 2, &state); + SongList->SetItemText(row, 3, &reason); + + if (song.spell_id == SelectedSongIDValue) { + selected_song_row = row; + } + } + + if (gNativeMulticlassMelodySongs.empty()) { + CXStr dash("-"); + const int row = SongList->AddString(dash, 0xFFB0B0B0, 0, nullptr, nullptr); + CXStr empty(gNativeMulticlassState.has_bard ? "No scribed Bard songs." : "Bard not in trio."); + SongList->SetItemText(row, 1, &dash); + SongList->SetItemText(row, 2, &empty); + SongList->SetItemText(row, 3, &dash); + } + else if (selected_song_row >= 0) { + SongList->SetCurSel(selected_song_row); + } + + SetStatus(gNativeMulticlassState.melody_status.c_str()); + NativeMulticlassSetLabel(FooterLabel, "Select a slot, then choose a scribed Bard song. Spell gems stay free."); + } + +private: + const NativeMulticlassMelodySlot* FindSlot(int slot_id) const + { + for (const auto& slot : gNativeMulticlassMelodySlots) { + if (slot.slot == slot_id) { + return &slot; + } + } + + return nullptr; + } + + int SelectedSlot() + { + if (!SlotList) { + return SelectedSlotValue; + } + + const int selected = SlotList->GetCurSel(); + if (selected >= 0) { + const int slot_id = (int)SlotList->GetItemData(selected); + if (slot_id >= 1 && slot_id <= 4) { + SelectedSlotValue = slot_id; + } + } + + return SelectedSlotValue; + } + + int SelectedSongID() + { + if (!SongList) { + return SelectedSongIDValue; + } + + const int selected = SongList->GetCurSel(); + if (selected >= 0) { + const int spell_id = (int)SongList->GetItemData(selected); + if (spell_id > 0) { + SelectedSongIDValue = spell_id; + } + } + + return SelectedSongIDValue; + } + + void SendSet(int slot_id, int spell_id) + { + char command[160]; + sprintf_s(command, "/say #mc melody set %d %d", slot_id, spell_id); + NativeAutoLootSendCommand(command); + SetStatus("Setting melody slot..."); + } + + void CycleSong(int direction) + { + if (gNativeMulticlassMelodySongs.empty()) { + SetStatus("No Bard songs are available."); + return; + } + + std::vector allowed_indices; + for (size_t i = 0; i < gNativeMulticlassMelodySongs.size(); ++i) { + if (gNativeMulticlassMelodySongs[i].allowed) { + allowed_indices.push_back((int)i); + } + } + + if (allowed_indices.empty()) { + SetStatus("No Bard songs are ready for Melody."); + return; + } + + int current_allowed_index = -1; + for (size_t i = 0; i < allowed_indices.size(); ++i) { + if (gNativeMulticlassMelodySongs[allowed_indices[i]].spell_id == SelectedSongIDValue) { + current_allowed_index = (int)i; + break; + } + } + + if (current_allowed_index < 0) { + current_allowed_index = 0; + } + else { + current_allowed_index += direction; + if (current_allowed_index < 0) { + current_allowed_index = (int)allowed_indices.size() - 1; + } + if (current_allowed_index >= (int)allowed_indices.size()) { + current_allowed_index = 0; + } + } + + const auto& song = gNativeMulticlassMelodySongs[allowed_indices[current_allowed_index]]; + SelectedSongIDValue = song.spell_id; + SendSet(SelectedSlot(), song.spell_id); + RefreshRows(); + } + + CXWnd* StatusLabel = nullptr; + CButtonWnd* RefreshButton = nullptr; + CListWnd* SlotList = nullptr; + CListWnd* SongList = nullptr; + CButtonWnd* PrevButton = nullptr; + CButtonWnd* NextButton = nullptr; + CButtonWnd* ClearSlotButton = nullptr; + CButtonWnd* ClearAllButton = nullptr; + CXWnd* FooterLabel = nullptr; + int SelectedSlotValue = 1; + int SelectedSongIDValue = 0; +}; + +class NativeMulticlassDisciplineWnd : public CCustomWnd +{ +public: + NativeMulticlassDisciplineWnd() : CCustomWnd((char*)"NativeMulticlassDisciplineWnd") + { + CloseOnESC = 1; + SetWndNotification(NativeMulticlassDisciplineWnd); + + StatusLabel = GetChildItem("MCDW_StatusLabel"); + RefreshButton = (CButtonWnd*)GetChildItem("MCDW_RefreshButton"); + ActiveEffectLabel = GetChildItem("MCDW_ActiveEffectLabel"); + ActiveEffectGauge = (CGaugeWnd*)GetChildItem("MCDW_ActiveEffectGauge"); + ReuseLabel = GetChildItem("MCDW_ReuseLabel"); + DisciplineList = (CListWnd*)GetChildItem("MCDW_DisciplineList"); + UseButton = (CButtonWnd*)GetChildItem("MCDW_UseButton"); + HotkeyButton = (CButtonWnd*)GetChildItem("MCDW_HotkeyButton"); + FooterLabel = GetChildItem("MCDW_FooterLabel"); + + Layout(); + RefreshRows(); + } + + int WndNotification(CXWnd* pWnd, unsigned int Message, void* unknown) + { + if (Message == XWM_CLOSE) { + pXWnd()->Show(0, 1); + return 1; + } + + if (Message == XWM_LCLICK) { + if (pWnd == (CXWnd*)RefreshButton) { + NativeAutoLootSendCommand("/say #mc disc refresh"); + SetStatus("Refreshing disciplines..."); + return 1; + } + + if (pWnd == (CXWnd*)DisciplineList) { + SelectedSpellID(); + RefreshRows(); + return 1; + } + + if (pWnd == (CXWnd*)UseButton) { + SendUse(); + return 1; + } + + if (pWnd == (CXWnd*)HotkeyButton) { + CreateHotkey(); + return 1; + } + } + + return CSidlScreenWnd::WndNotification(pWnd, Message, unknown); + } + + void Layout() + { + // Resize is handled by SIDL AutoStretch anchors. Keep the method so + // every native Multiclass window has a pulse-time resize hook. + DWORD now = GetTickCount(); + if (now - LastTimerRefreshMs >= 1000) { + LastTimerRefreshMs = now; + if (HasActiveReuseTimer()) { + RefreshRows(); + } + else { + UpdateTimerLabels(); + } + } + } + + void SetStatus(const char* text) + { + NativeMulticlassSetLabel(StatusLabel, text); + } + + void RefreshRows() + { + if (!DisciplineList) { + return; + } + + DisciplineList->DeleteAll(); + + if (SelectedSpellIDValue > 0 && !FindDiscipline(SelectedSpellIDValue)) { + SelectedSpellIDValue = 0; + } + + if (SelectedSpellIDValue <= 0 && !gNativeMulticlassDisciplineRows.empty()) { + SelectedSpellIDValue = gNativeMulticlassDisciplineRows.front().spell_id; + } + + int selected_row = -1; + for (const auto& disc : gNativeMulticlassDisciplineRows) { + CXStr name(disc.name.c_str()); + COLORREF row_color = disc.ready ? 0xFFFFFFFF : 0xFFB0B0B0; + if (disc.spell_id == SelectedSpellIDValue) { + row_color = 0xFFFF4040; + } + + const int row = DisciplineList->AddString(name, row_color, (uint32_t)disc.spell_id, nullptr, nullptr); + + char level[32]; + sprintf_s(level, "%d", disc.level); + char timer[32]; + const int remaining_timer = CurrentTimerSeconds(disc); + const bool locally_ready = disc.ready || (disc.timer > 0 && remaining_timer <= 0); + if (remaining_timer > 0) { + const std::string formatted_timer = FormatTimer(remaining_timer); + strcpy_s(timer, sizeof(timer), formatted_timer.c_str()); + } + else { + sprintf_s(timer, "-"); + } + + CXStr level_text(level); + CXStr timer_text(timer); + const std::string state = locally_ready ? "Ready" : (remaining_timer > 0 ? "Reuse" : disc.state); + CXStr state_text(state.c_str()); + DisciplineList->SetItemText(row, 1, &level_text); + DisciplineList->SetItemText(row, 2, &timer_text); + DisciplineList->SetItemText(row, 3, &state_text); + + if (disc.spell_id == SelectedSpellIDValue) { + selected_row = row; + } + } + + if (gNativeMulticlassDisciplineRows.empty()) { + CXStr dash("-"); + const int row = DisciplineList->AddString(dash, 0xFFB0B0B0, 0, nullptr, nullptr); + CXStr empty("No learned disciplines."); + DisciplineList->SetItemText(row, 1, &dash); + DisciplineList->SetItemText(row, 2, &dash); + DisciplineList->SetItemText(row, 3, &empty); + } + else if (selected_row >= 0) { + DisciplineList->SetCurSel(selected_row); + } + + SetStatus(gNativeMulticlassState.discipline_status.c_str()); + UpdateTimerLabels(); + NativeMulticlassSetLabel(FooterLabel, "Use activates selected disc. Hotkey creates a /mc disc button."); + } + +private: + const NativeMulticlassDisciplineRow* FindDiscipline(int spell_id) const + { + for (const auto& disc : gNativeMulticlassDisciplineRows) { + if (disc.spell_id == spell_id) { + return &disc; + } + } + + return nullptr; + } + + int SelectedSpellID() + { + if (!DisciplineList) { + return SelectedSpellIDValue; + } + + const int selected = DisciplineList->GetCurSel(); + if (selected >= 0) { + const int spell_id = (int)DisciplineList->GetItemData(selected); + if (spell_id > 0) { + SelectedSpellIDValue = spell_id; + } + } + + return SelectedSpellIDValue; + } + + void SendUse() + { + const int spell_id = SelectedSpellID(); + if (spell_id <= 0) { + SetStatus("Select a discipline first."); + return; + } + + char command[128]; + sprintf_s(command, "/say #mc disc use %d", spell_id); + NativeAutoLootSendCommand(command); + SetStatus("Using discipline..."); + } + + void CreateHotkey() + { + const int spell_id = SelectedSpellID(); + const auto* disc = FindDiscipline(spell_id); + if (!disc) { + SetStatus("Select a discipline first."); + return; + } + + const std::string label = HotkeyLabel(disc->name, spell_id); + char command[256]; + sprintf_s(command, "/hotbutton %s /mc disc use %d", label.c_str(), spell_id); + NativeAutoLootSendCommand(command); + + char status[256]; + sprintf_s(status, "Created hotkey for %.180s.", disc->name.c_str()); + SetStatus(status); + } + + static int CurrentTimerSeconds(const NativeMulticlassDisciplineRow& disc) + { + if (disc.timer <= 0) { + return 0; + } + + const DWORD elapsed_ms = disc.timer_received_ms ? (GetTickCount() - disc.timer_received_ms) : 0; + const int elapsed_seconds = static_cast(elapsed_ms / 1000); + if (elapsed_seconds >= disc.timer) { + return 0; + } + + return disc.timer - elapsed_seconds; + } + + static std::string FormatTimer(int seconds) + { + if (seconds <= 0) { + return "-"; + } + + char buffer[32]; + if (seconds >= 3600) { + sprintf_s(buffer, "%d:%02d:%02d", seconds / 3600, (seconds / 60) % 60, seconds % 60); + } + else if (seconds >= 60) { + sprintf_s(buffer, "%d:%02d", seconds / 60, seconds % 60); + } + else { + sprintf_s(buffer, "%ds", seconds); + } + + return buffer; + } + + static std::string ReuseBar(int remaining, int total) + { + if (remaining <= 0 || total <= 0) { + return "Ready"; + } + + const int width = 12; + int filled = (remaining * width + total - 1) / total; + if (filled < 1) { + filled = 1; + } + if (filled > width) { + filled = width; + } + + std::string bar = "["; + for (int i = 0; i < width; ++i) { + bar.push_back(i < filled ? '#' : '-'); + } + bar.push_back(']'); + return bar; + } + + static std::string HotkeyLabel(const std::string& name, int spell_id) + { + std::string label; + label.reserve(16); + for (char c : name) { + if (label.size() >= 15) { + break; + } + + const unsigned char ch = static_cast(c); + if (isalnum(ch)) { + label.push_back(static_cast(c)); + } + else if ((isspace(ch) || c == '-' || c == '_') && !label.empty() && label.back() != '_') { + label.push_back('_'); + } + } + + while (!label.empty() && label.back() == '_') { + label.resize(label.size() - 1); + } + + if (label.empty()) { + char fallback[32]; + sprintf_s(fallback, "Disc%d", spell_id); + label = fallback; + } + + return label; + } + + bool HasActiveReuseTimer() const + { + for (const auto& disc : gNativeMulticlassDisciplineRows) { + if (CurrentTimerSeconds(disc) > 0) { + return true; + } + } + + return false; + } + + void UpdateTimerLabels() + { + NativeMulticlassSetLabel(ActiveEffectLabel, "Active:"); + const auto* disc = FindDiscipline(SelectedSpellIDValue); + if (!disc) { + NativeMulticlassSetLabel(ReuseLabel, "Reuse: -"); + return; + } + + const int remaining = CurrentTimerSeconds(*disc); + const int total = disc->timer_total > 0 ? disc->timer_total : disc->timer; + const std::string reuse = remaining > 0 ? + ("Reuse: " + ReuseBar(remaining, total) + " " + FormatTimer(remaining)) : + "Reuse: ready"; + NativeMulticlassSetLabel(ReuseLabel, reuse.c_str()); + } + + CXWnd* StatusLabel = nullptr; + CButtonWnd* RefreshButton = nullptr; + CXWnd* ActiveEffectLabel = nullptr; + CGaugeWnd* ActiveEffectGauge = nullptr; + CXWnd* ReuseLabel = nullptr; + CListWnd* DisciplineList = nullptr; + CButtonWnd* UseButton = nullptr; + CButtonWnd* HotkeyButton = nullptr; + CXWnd* FooterLabel = nullptr; + int SelectedSpellIDValue = 0; + DWORD LastTimerRefreshMs = 0; +}; + +static void NativeMulticlassRefreshWindows() +{ + if (gNativeMulticlassWnd) { + gNativeMulticlassWnd->Refresh(); + } + + if (gNativeMulticlassPetWnd) { + gNativeMulticlassPetWnd->RefreshRows(); + } + + if (gNativeMulticlassMelodyWnd) { + gNativeMulticlassMelodyWnd->RefreshRows(); + } + + if (gNativeMulticlassDisciplineWnd) { + gNativeMulticlassDisciplineWnd->RefreshRows(); + } +} + +static void NativeMulticlassEnsureWindow(bool show) +{ + if (!pSidlMgr || !pWndMgr) { + return; + } + + if (!gNativeMulticlassWnd) { + NativeAutoLootTrace("creating Multiclass window"); + NativeMulticlassWnd* created_window = nullptr; + __try { + created_window = new NativeMulticlassWnd(); + } __except(EXCEPTION_EXECUTE_HANDLER) { + NativeAutoLootTrace("Multiclass window construction faulted; check EQUI_NativeMulticlassWnd.xml"); + created_window = nullptr; + } + + if (!created_window) { + return; + } + + gNativeMulticlassWnd = created_window; + NativeAutoLootTrace("Multiclass window created"); + } + + gNativeMulticlassWnd->Refresh(); + if (show && gNativeMulticlassWnd) { + gNativeMulticlassWnd->pXWnd()->Show(1, 1); + } +} + +static void NativeMulticlassEnsurePetWindow(bool show) +{ + if (!pSidlMgr || !pWndMgr) { + return; + } + + if (!gNativeMulticlassPetWnd) { + NativeAutoLootTrace("creating Multiclass pet window"); + NativeMulticlassPetWnd* created_window = nullptr; + __try { + created_window = new NativeMulticlassPetWnd(); + } __except(EXCEPTION_EXECUTE_HANDLER) { + NativeAutoLootTrace("Multiclass pet window construction faulted; check EQUI_NativeMulticlassWnd.xml"); + created_window = nullptr; + } + + if (!created_window) { + return; + } + + gNativeMulticlassPetWnd = created_window; + NativeAutoLootTrace("Multiclass pet window created"); + } + + gNativeMulticlassPetWnd->RefreshRows(); + if (show && gNativeMulticlassPetWnd) { + gNativeMulticlassPetWnd->pXWnd()->Show(1, 1); + } +} + +static void NativeMulticlassEnsureMelodyWindow(bool show) +{ + if (!pSidlMgr || !pWndMgr) { + return; + } + + if (!gNativeMulticlassMelodyWnd) { + NativeAutoLootTrace("creating Multiclass melody window"); + NativeMulticlassMelodyWnd* created_window = nullptr; + __try { + created_window = new NativeMulticlassMelodyWnd(); + } __except(EXCEPTION_EXECUTE_HANDLER) { + NativeAutoLootTrace("Multiclass melody window construction faulted; check EQUI_NativeMulticlassWnd.xml"); + created_window = nullptr; + } + + if (!created_window) { + return; + } + + gNativeMulticlassMelodyWnd = created_window; + NativeAutoLootTrace("Multiclass melody window created"); + } + + gNativeMulticlassMelodyWnd->RefreshRows(); + if (show && gNativeMulticlassMelodyWnd) { + gNativeMulticlassMelodyWnd->pXWnd()->Show(1, 1); + } +} + +static void NativeMulticlassEnsureDisciplineWindow(bool show) +{ + if (!pSidlMgr || !pWndMgr) { + return; + } + + if (!gNativeMulticlassDisciplineWnd) { + NativeAutoLootTrace("creating Multiclass discipline window"); + NativeMulticlassDisciplineWnd* created_window = nullptr; + __try { + created_window = new NativeMulticlassDisciplineWnd(); + } __except(EXCEPTION_EXECUTE_HANDLER) { + NativeAutoLootTrace("Multiclass discipline window construction faulted; check EQUI_NativeMulticlassWnd.xml"); + created_window = nullptr; + } + + if (!created_window) { + return; + } + + gNativeMulticlassDisciplineWnd = created_window; + NativeAutoLootTrace("Multiclass discipline window created"); + } + + gNativeMulticlassDisciplineWnd->RefreshRows(); + if (show && gNativeMulticlassDisciplineWnd) { + gNativeMulticlassDisciplineWnd->pXWnd()->Show(1, 1); + } +} + +static void NativeMulticlassHideRuntimeWindows() +{ + __try { + if (gNativeMulticlassWnd) { + gNativeMulticlassWnd->pXWnd()->Show(0, 1); + } + if (gNativeMulticlassPetWnd) { + gNativeMulticlassPetWnd->pXWnd()->Show(0, 1); + } + if (gNativeMulticlassMelodyWnd) { + gNativeMulticlassMelodyWnd->pXWnd()->Show(0, 1); + } + if (gNativeMulticlassDisciplineWnd) { + gNativeMulticlassDisciplineWnd->pXWnd()->Show(0, 1); + } + } + __except (EXCEPTION_EXECUTE_HANDLER) { + } +} + +static void NativeMulticlassDestroyRuntimeWindows() +{ + if (gNativeMulticlassWnd) { + NativeMulticlassWnd* window = gNativeMulticlassWnd; + gNativeMulticlassWnd = nullptr; + __try { + window->pXWnd()->Show(0, 1); + delete window; + } + __except (EXCEPTION_EXECUTE_HANDLER) { + NativeAutoLootTrace("Multiclass window release faulted during UI reset"); + } + } + + if (gNativeMulticlassPetWnd) { + NativeMulticlassPetWnd* window = gNativeMulticlassPetWnd; + gNativeMulticlassPetWnd = nullptr; + __try { + window->pXWnd()->Show(0, 1); + delete window; + } + __except (EXCEPTION_EXECUTE_HANDLER) { + NativeAutoLootTrace("Multiclass pet window release faulted during UI reset"); + } + } + + if (gNativeMulticlassMelodyWnd) { + NativeMulticlassMelodyWnd* window = gNativeMulticlassMelodyWnd; + gNativeMulticlassMelodyWnd = nullptr; + __try { + window->pXWnd()->Show(0, 1); + delete window; + } + __except (EXCEPTION_EXECUTE_HANDLER) { + NativeAutoLootTrace("Multiclass melody window release faulted during UI reset"); + } + } + + if (gNativeMulticlassDisciplineWnd) { + NativeMulticlassDisciplineWnd* window = gNativeMulticlassDisciplineWnd; + gNativeMulticlassDisciplineWnd = nullptr; + __try { + window->pXWnd()->Show(0, 1); + delete window; + } + __except (EXCEPTION_EXECUTE_HANDLER) { + NativeAutoLootTrace("Multiclass discipline window release faulted during UI reset"); + } + } +} + +static void NativeMulticlassResetSessionState(bool hide_windows) +{ + if (hide_windows) { + NativeMulticlassHideRuntimeWindows(); + } + + gNativeMulticlassState = NativeMulticlassState(); + gNativeMulticlassPets.clear(); + gNativeMulticlassMelodySlots.clear(); + gNativeMulticlassMelodySongs.clear(); + gNativeMulticlassDisciplineRows.clear(); + gNativeMulticlassSpellLevelsById.clear(); + gNativeMulticlassSpellLevelsByName.clear(); + gNativeMulticlassSpellLevelPatchCount = 0; + gNativeMulticlassSpellLevelsLoading = false; + gNativeMulticlassShowCasterUiPulses = 0; +} + +class NativeMulticlassContextMenuHook +{ +public: + int Trampoline(const CXStr& text, unsigned int menu_id, bool checked, DWORD color, bool enabled); + int Detour(const CXStr& text, unsigned int menu_id, bool checked, DWORD color, bool enabled) + { + const char* raw_text = text.Ptr ? text.Ptr->Text : ""; + std::string rewritten; + if (NativeMulticlassRewriteSpellMenuText(raw_text, menu_id, rewritten)) { + CXStr value(rewritten.c_str()); + return Trampoline(value, menu_id, checked, color, enabled); + } + + return Trampoline(text, menu_id, checked, color, enabled); + } +}; + +DETOUR_TRAMPOLINE_EMPTY(int NativeMulticlassContextMenuHook::Trampoline(const CXStr& text, unsigned int menu_id, bool checked, DWORD color, bool enabled)); + +static DWORD NativeMulticlassContextMenuAddMenuItemAddress() +{ + return (((DWORD)0x0085B7B0 - 0x400000) + baseAddress); +} + +static void NativeMulticlassInstallContextMenuHook() +{ + if (!gNativeMulticlassContextMenuHookEnabled || gNativeMulticlassContextMenuHookInstalled) { + return; + } + + NativeAutoLootTrace("installing Multiclass context menu hook"); + EzDetour(NativeMulticlassContextMenuAddMenuItemAddress(), &NativeMulticlassContextMenuHook::Detour, &NativeMulticlassContextMenuHook::Trampoline); + gNativeMulticlassContextMenuHookInstalled = true; +} + +static bool NativeIsKeepRule(const std::string& rule) +{ + return rule == "include" || rule == "keep" || rule == "always" || rule == "loot"; +} + +static bool NativeIsNeverRule(const std::string& rule) +{ + return rule == "exclude" || rule == "ignore" || rule == "never" || rule == "skip"; +} + +static const char* NativeShortRule(const std::string& rule) +{ + if (NativeIsKeepRule(rule)) { + return "X"; + } + + if (NativeIsNeverRule(rule)) { + return "X"; + } + + return ""; +} + +static const char* NativeDisplayRule(const std::string& rule) +{ + if (NativeIsNeverRule(rule)) { + return "Never"; + } + + if (NativeIsKeepRule(rule)) { + return "Keep"; + } + + return "-"; +} + +struct NativeAchievementCategoryRow +{ + int id = 0; + int parent_id = 0; + int total = 0; + int completed = 0; + int points = 0; + std::string name = "Category"; +}; + +struct NativeAchievementRow +{ + int id = 0; + int category_id = 0; + int points = 0; + bool completed = false; + std::string name = "Achievement"; + std::string description; +}; + +struct NativeAchievementObjectiveRow +{ + int id = 0; + int current = 0; + int required = 0; + bool completed = false; + std::string name = "Objective"; +}; + +class NativeAchievementWnd : public CCustomWnd +{ +public: + NativeAchievementWnd() : CCustomWnd((char*)"NativeAchievementWnd") + { + CloseOnESC = 1; + SetWndNotification(NativeAchievementWnd); + + SummaryLabel = GetChildItem("NAW_SummaryLabel"); + CategoryList = (CListWnd*)GetChildItem("NAW_CategoryList"); + AchievementList = (CListWnd*)GetChildItem("NAW_AchievementList"); + DetailTitleLabel = GetChildItem("NAW_DetailTitleLabel"); + DetailDescriptionLabel = GetChildItem("NAW_DetailDescriptionLabel"); + ObjectiveList = (CListWnd*)GetChildItem("NAW_ObjectiveList"); + StatusLabel = GetChildItem("NAW_StatusLabel"); + RefreshButton = (CButtonWnd*)GetChildItem("NAW_RefreshButton"); + CheckButton = (CButtonWnd*)GetChildItem("NAW_CheckButton"); + + Layout(); + SetStatus("Open with /achievement, /ach, #achievement, or #ach."); + RefreshRows(); + } + + int WndNotification(CXWnd* pWnd, unsigned int Message, void* unknown) + { + if (Message == XWM_CLOSE) { + pXWnd()->Show(0, 1); + return 1; + } + + if (Message == XWM_LCLICK) { + if (pWnd == (CXWnd*)RefreshButton) { + char command[128]; + sprintf_s(command, "/say #ach native refresh %d %d", SelectedCategoryID, SelectedAchievementID); + NativeAutoLootSendCommand(command); + SetStatus("Refreshing achievements..."); + return 1; + } + + if (pWnd == (CXWnd*)CheckButton) { + char command[128]; + sprintf_s(command, "/say #ach native check %d %d", SelectedCategoryID, SelectedAchievementID); + NativeAutoLootSendCommand(command); + SetStatus("Checking automatic achievements..."); + return 1; + } + + if (pWnd == (CXWnd*)CategoryList) { + NativeAchievementCategoryRow* category = GetSelectedCategory(); + if (category && category->id > 0 && category->id != SelectedCategoryID) { + char command[128]; + sprintf_s(command, "/say #ach native category %d", category->id); + NativeAutoLootSendCommand(command); + SetStatus("Loading achievement category..."); + } + return 1; + } + + if (pWnd == (CXWnd*)AchievementList) { + NativeAchievementRow* achievement = GetSelectedAchievement(); + if (achievement && achievement->id > 0 && achievement->id != SelectedAchievementID) { + char command[128]; + sprintf_s(command, "/say #ach native detail %d %d", achievement->id, SelectedCategoryID); + NativeAutoLootSendCommand(command); + SetStatus("Loading achievement detail..."); + } + return 1; + } + } + + return CSidlScreenWnd::WndNotification(pWnd, Message, unknown); + } + + void Layout() + { + // Achievement resize is handled by SIDL AutoStretch anchors. + } + + void RefreshRows(); + void SetStatus(const char* text) + { + SetLabel(StatusLabel, text ? text : ""); + } + +private: + NativeAchievementCategoryRow* GetSelectedCategory(); + NativeAchievementRow* GetSelectedAchievement(); + void RefreshCategoryList(); + void RefreshAchievementList(); + void RefreshObjectiveList(); + void SelectCategoryListRow(); + void SelectAchievementListRow(); + void SetLabel(CXWnd* label, const char* text) + { + if (label) { + CXStr value(text ? text : ""); + label->SetWindowTextA(value); + } + } + + CXWnd* SummaryLabel = nullptr; + CListWnd* CategoryList = nullptr; + CListWnd* AchievementList = nullptr; + CXWnd* DetailTitleLabel = nullptr; + CXWnd* DetailDescriptionLabel = nullptr; + CListWnd* ObjectiveList = nullptr; + CXWnd* StatusLabel = nullptr; + CButtonWnd* RefreshButton = nullptr; + CButtonWnd* CheckButton = nullptr; + int SelectedCategoryID = 0; + int SelectedAchievementID = 0; +}; + +static NativeAchievementWnd* gNativeAchievementWnd = nullptr; +static std::vector gNativeAchievementCategories; +static std::vector gNativeAchievementRows; +static std::vector gNativeAchievementObjectives; +static int gNativeAchievementSelectedCategory = 0; +static int gNativeAchievementSelectedAchievement = 0; +static int gNativeAchievementCompleted = 0; +static int gNativeAchievementTotal = 0; +static int gNativeAchievementPoints = 0; +static int gNativeAchievementCategoryCount = 0; +static bool gNativeAchievementLoading = false; +static bool gNativeAchievementCategoriesDirty = true; +static bool gNativeAchievementRowsDirty = true; +static bool gNativeAchievementObjectivesDirty = true; +static std::string gNativeAchievementDetailTitle = "Select an achievement"; +static std::string gNativeAchievementDetailDescription = ""; + +class NativeSpellForgeWnd : public CCustomWnd +{ +public: + NativeSpellForgeWnd() : CCustomWnd((char*)"NativeSpellForgeWnd") + { + CloseOnESC = 1; + SetWndNotification(NativeSpellForgeWnd); + + FormTab = (CButtonWnd*)GetChildItem("ASFW_FormTab"); + DeliveryTab = (CButtonWnd*)GetChildItem("ASFW_DeliveryTab"); + PowerTab = (CButtonWnd*)GetChildItem("ASFW_PowerTab"); + CastingTab = (CButtonWnd*)GetChildItem("ASFW_CastingTab"); + ReviewTab = (CButtonWnd*)GetChildItem("ASFW_ReviewTab"); + + FormPage = GetChildItem("ASFW_FormPage"); + DeliveryPage = GetChildItem("ASFW_DeliveryPage"); + PowerPage = GetChildItem("ASFW_PowerPage"); + CastingPage = GetChildItem("ASFW_CastingPage"); + ReviewPage = GetChildItem("ASFW_ReviewPage"); NameEdit = (CEditWnd*)GetChildItem("ASFW_NameEdit"); FireButton = (CButtonWnd*)GetChildItem("ASFW_FireButton"); @@ -632,38 +2591,634 @@ class NativeSpellForgeWnd : public CCustomWnd DiseaseButton = (CButtonWnd*)GetChildItem("ASFW_DiseaseButton"); ElementHintLabel = GetChildItem("ASFW_ElementHintLabel"); - TargetButton = (CButtonWnd*)GetChildItem("ASFW_TargetButton"); - AEButton = (CButtonWnd*)GetChildItem("ASFW_AEButton"); - PBAEButton = (CButtonWnd*)GetChildItem("ASFW_PBAEButton"); - RangeMinusButton = (CButtonWnd*)GetChildItem("ASFW_RangeMinusButton"); - RangePlusButton = (CButtonWnd*)GetChildItem("ASFW_RangePlusButton"); - RangeValueLabel = GetChildItem("ASFW_RangeValueLabel"); - RadiusValueLabel = GetChildItem("ASFW_RadiusValueLabel"); - TargetHintLabel = GetChildItem("ASFW_TargetHintLabel"); + TargetButton = (CButtonWnd*)GetChildItem("ASFW_TargetButton"); + AEButton = (CButtonWnd*)GetChildItem("ASFW_AEButton"); + PBAEButton = (CButtonWnd*)GetChildItem("ASFW_PBAEButton"); + RangeMinusButton = (CButtonWnd*)GetChildItem("ASFW_RangeMinusButton"); + RangePlusButton = (CButtonWnd*)GetChildItem("ASFW_RangePlusButton"); + RangeValueLabel = GetChildItem("ASFW_RangeValueLabel"); + RadiusValueLabel = GetChildItem("ASFW_RadiusValueLabel"); + TargetHintLabel = GetChildItem("ASFW_TargetHintLabel"); + + DamageMinusButton = (CButtonWnd*)GetChildItem("ASFW_DamageMinusButton"); + DamagePlusButton = (CButtonWnd*)GetChildItem("ASFW_DamagePlusButton"); + DamageValueLabel = GetChildItem("ASFW_DamageValueLabel"); + ManaValueLabel = GetChildItem("ASFW_ManaValueLabel"); + PowerHintLabel = GetChildItem("ASFW_PowerHintLabel"); + + RecastMinusButton = (CButtonWnd*)GetChildItem("ASFW_RecastMinusButton"); + RecastPlusButton = (CButtonWnd*)GetChildItem("ASFW_RecastPlusButton"); + RecastValueLabel = GetChildItem("ASFW_RecastValueLabel"); + CastValueLabel = GetChildItem("ASFW_CastValueLabel"); + CastingHintLabel = GetChildItem("ASFW_CastingHintLabel"); + + ReviewNameLabel = GetChildItem("ASFW_ReviewNameLabel"); + ReviewFormLabel = GetChildItem("ASFW_ReviewFormLabel"); + ReviewDeliveryLabel = GetChildItem("ASFW_ReviewDeliveryLabel"); + ReviewPowerLabel = GetChildItem("ASFW_ReviewPowerLabel"); + ReviewCastingLabel = GetChildItem("ASFW_ReviewCastingLabel"); + CreateButton = (CButtonWnd*)GetChildItem("ASFW_CreateButton"); + StatusLabel = GetChildItem("ASFW_StatusLabel"); + + SetEditText(DefaultSpellName().c_str()); + ShowPage(PageForm); + SetStatus("Choose a spell form, then tune delivery and power."); + UpdateView(); + } + + int WndNotification(CXWnd* pWnd, unsigned int Message, void* unknown) + { + if (Message == XWM_CLOSE) { + pXWnd()->Show(0, 1); + return 1; + } + + if (Message == XWM_LCLICK) { + if (pWnd == (CXWnd*)FormTab) { + ShowPage(PageForm); + return 1; + } + + if (pWnd == (CXWnd*)DeliveryTab) { + ShowPage(PageDelivery); + return 1; + } + + if (pWnd == (CXWnd*)PowerTab) { + ShowPage(PagePower); + return 1; + } + + if (pWnd == (CXWnd*)CastingTab) { + ShowPage(PageCasting); + return 1; + } + + if (pWnd == (CXWnd*)ReviewTab) { + ShowPage(PageReview); + return 1; + } + + if (pWnd == (CXWnd*)FireButton) { + SelectElement(0); + return 1; + } + + if (pWnd == (CXWnd*)ColdButton) { + SelectElement(1); + return 1; + } + + if (pWnd == (CXWnd*)MagicButton) { + SelectElement(2); + return 1; + } + + if (pWnd == (CXWnd*)PoisonButton) { + SelectElement(3); + return 1; + } + + if (pWnd == (CXWnd*)DiseaseButton) { + SelectElement(4); + return 1; + } + + if (pWnd == (CXWnd*)TargetButton) { + TargetIndex = 0; + SetStatus("Delivery set to single target."); + UpdateView(); + return 1; + } + + if (pWnd == (CXWnd*)AEButton) { + TargetIndex = 1; + SetStatus("Delivery set to targeted AE."); + UpdateView(); + return 1; + } + + if (pWnd == (CXWnd*)PBAEButton) { + TargetIndex = 2; + SetStatus("Delivery set to point blank AE."); + UpdateView(); + return 1; + } + + if (pWnd == (CXWnd*)RangeMinusButton) { + Range = ClampInt(Range - 25, 25, 300); + UpdateView(); + return 1; + } + + if (pWnd == (CXWnd*)RangePlusButton) { + Range = ClampInt(Range + 25, 25, 300); + UpdateView(); + return 1; + } + + if (pWnd == (CXWnd*)DamageMinusButton) { + Damage = ClampInt(Damage - 25, 25, 500); + UpdateView(); + return 1; + } + + if (pWnd == (CXWnd*)DamagePlusButton) { + Damage = ClampInt(Damage + 25, 25, 500); + UpdateView(); + return 1; + } + + if (pWnd == (CXWnd*)RecastMinusButton) { + Recast = ClampInt(Recast - 1000, 1000, 30000); + UpdateView(); + return 1; + } + + if (pWnd == (CXWnd*)RecastPlusButton) { + Recast = ClampInt(Recast + 1000, 1000, 30000); + UpdateView(); + return 1; + } + + if (pWnd == (CXWnd*)CreateButton) { + CreateScroll(); + return 1; + } + } + + return CSidlScreenWnd::WndNotification(pWnd, Message, unknown); + } + + void Open(const std::string& payload) + { + (void)payload; + pXWnd()->Show(1, 1); + SetStatus("Spell Forge opened. Build a scroll, then scribe it normally."); + UpdateView(); + } + + void Layout() + { + } + +private: + enum ForgePage { + PageForm = 0, + PageDelivery = 1, + PagePower = 2, + PageCasting = 3, + PageReview = 4 + }; + + static int ClampInt(int value, int minimum, int maximum) + { + if (value < minimum) { + return minimum; + } + + if (value > maximum) { + return maximum; + } + + return value; + } + + void SetLabel(CXWnd* label, const char* text) + { + if (label) { + CXStr value(text ? text : ""); + label->SetWindowTextA(value); + } + } + + void SetButtonText(CButtonWnd* button, const char* text) + { + if (button) { + CXStr value(text ? text : ""); + ((CXWnd*)button)->SetWindowTextA(value); + } + } + + void SetVisible(CXWnd* wnd, bool visible) + { + if (wnd) { + wnd->Show(visible ? 1 : 0, 1); + } + } + + void SetStatus(const char* text) + { + SetLabel(StatusLabel, text); + } + + const char* ElementKey() const + { + switch (ElementIndex) { + case 1: + return "cold"; + case 2: + return "magic"; + case 3: + return "poison"; + case 4: + return "disease"; + default: + return "fire"; + } + } + + const char* ElementLabel() const + { + switch (ElementIndex) { + case 1: + return "Cold"; + case 2: + return "Magic"; + case 3: + return "Poison"; + case 4: + return "Disease"; + default: + return "Fire"; + } + } + + const char* ElementNoun() const + { + switch (ElementIndex) { + case 1: + return "Frost"; + case 2: + return "Arcane"; + case 3: + return "Venom"; + case 4: + return "Blight"; + default: + return "Ember"; + } + } + + const char* ElementHint() const + { + switch (ElementIndex) { + case 1: + return "Cold uses a chill resist profile and a blue spell icon."; + case 2: + return "Magic is a clean arcane damage pattern."; + case 3: + return "Poison uses the poison resist profile for green damage spells."; + case 4: + return "Disease uses the disease resist profile and a darker icon."; + default: + return "Fire uses the fire resist profile and the ember icon."; + } + } + + const char* TargetKey() const + { + if (TargetIndex == 1) { + return "ae"; + } + + if (TargetIndex == 2) { + return "pbae"; + } + + return "target"; + } + + const char* TargetLabel() const + { + if (TargetIndex == 1) { + return "Targeted AE"; + } + + if (TargetIndex == 2) { + return "Point Blank AE"; + } + + return "Single Target"; + } + + const char* TargetSuffix() const + { + if (TargetIndex == 1) { + return "Burst"; + } + + if (TargetIndex == 2) { + return "Bloom"; + } + + return "Lash"; + } + + int Radius() const + { + return TargetIndex == 0 ? 0 : 35; + } + + int ManaCost() const + { + return ClampInt(5 + (Damage / 5), 5, 5000); + } + + int CastTime() const + { + return ClampInt(1500 + (Damage / 20), 1500, 6000); + } + + std::string DefaultSpellName() const + { + return std::string(ElementNoun()) + " " + TargetSuffix(); + } + + void SetEditText(const char* text) + { + if (!NameEdit) { + return; + } + + char buffer[80] = { 0 }; + strcpy_s(buffer, text && text[0] ? text : DefaultSpellName().c_str()); + SetCXStr(&NameEdit->InputText, buffer); + CXStr value(buffer); + ((CXWnd*)NameEdit)->SetWindowTextA(value); + } + + std::string ReadName() const + { + char text[80] = { 0 }; + if (NameEdit && NameEdit->InputText) { + GetCXStr(NameEdit->InputText, text, sizeof(text)); + } + + std::string name(text); + if (name.empty()) { + name = DefaultSpellName(); + } + + return name; + } + + std::string EncodeName(const std::string& name) const + { + std::string encoded; + encoded.reserve(name.size()); + + for (char ch : name) { + const bool alpha = (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); + const bool digit = ch >= '0' && ch <= '9'; + if (alpha || digit) { + encoded.push_back(ch); + } + else if (ch == ' ' || ch == '_' || ch == '-') { + if (!encoded.empty() && encoded.back() != '_') { + encoded.push_back('_'); + } + } + + if (encoded.size() >= 40) { + break; + } + } + + while (!encoded.empty() && encoded.back() == '_') { + encoded.pop_back(); + } + + if (encoded.empty()) { + encoded = DefaultSpellName(); + for (char& ch : encoded) { + if (ch == ' ') { + ch = '_'; + } + } + } + + return encoded; + } + + void SelectElement(int index) + { + ElementIndex = ClampInt(index, 0, 4); + SetEditText(DefaultSpellName().c_str()); + SetStatus("Spell form changed."); + UpdateView(); + } + + void ShowPage(ForgePage page) + { + CurrentPage = page; + SetVisible(FormPage, CurrentPage == PageForm); + SetVisible(DeliveryPage, CurrentPage == PageDelivery); + SetVisible(PowerPage, CurrentPage == PagePower); + SetVisible(CastingPage, CurrentPage == PageCasting); + SetVisible(ReviewPage, CurrentPage == PageReview); + UpdateView(); + } + + void UpdateTabs() + { + SetButtonText(FormTab, CurrentPage == PageForm ? "> Form <" : "Form"); + SetButtonText(DeliveryTab, CurrentPage == PageDelivery ? "> Delivery <" : "Delivery"); + SetButtonText(PowerTab, CurrentPage == PagePower ? "> Power <" : "Power"); + SetButtonText(CastingTab, CurrentPage == PageCasting ? "> Casting <" : "Casting"); + SetButtonText(ReviewTab, CurrentPage == PageReview ? "> Review <" : "Review"); + } + + void UpdateView() + { + UpdateTabs(); + + SetButtonText(FireButton, ElementIndex == 0 ? "* Fire" : "Fire"); + SetButtonText(ColdButton, ElementIndex == 1 ? "* Cold" : "Cold"); + SetButtonText(MagicButton, ElementIndex == 2 ? "* Magic" : "Magic"); + SetButtonText(PoisonButton, ElementIndex == 3 ? "* Poison" : "Poison"); + SetButtonText(DiseaseButton, ElementIndex == 4 ? "* Disease" : "Disease"); + SetLabel(ElementHintLabel, ElementHint()); + + SetButtonText(TargetButton, TargetIndex == 0 ? "* Single Target" : "Single Target"); + SetButtonText(AEButton, TargetIndex == 1 ? "* Targeted AE" : "Targeted AE"); + SetButtonText(PBAEButton, TargetIndex == 2 ? "* Point Blank AE" : "Point Blank AE"); + + char text[192]; + sprintf_s(text, "%d", Range); + SetLabel(RangeValueLabel, text); + sprintf_s(text, "%d", Radius()); + SetLabel(RadiusValueLabel, text); + sprintf_s(text, "%s spells use range %d and radius %d.", TargetLabel(), Range, Radius()); + SetLabel(TargetHintLabel, text); + + sprintf_s(text, "%d", Damage); + SetLabel(DamageValueLabel, text); + sprintf_s(text, "%d", ManaCost()); + SetLabel(ManaValueLabel, text); + sprintf_s(text, "Higher damage raises mana and cast time. Current damage range is 25 to 500."); + SetLabel(PowerHintLabel, text); + + sprintf_s(text, "%.1f sec", Recast / 1000.0f); + SetLabel(RecastValueLabel, text); + sprintf_s(text, "%.1f sec", CastTime() / 1000.0f); + SetLabel(CastValueLabel, text); + sprintf_s(text, "Short recasts feel snappy; long recasts are safer for stronger spells."); + SetLabel(CastingHintLabel, text); + + const std::string name = ReadName(); + SetLabel(ReviewNameLabel, name.c_str()); + sprintf_s(text, "%s damage using %s resist.", ElementLabel(), ElementLabel()); + SetLabel(ReviewFormLabel, text); + sprintf_s(text, "%s, range %d, radius %d.", TargetLabel(), Range, Radius()); + SetLabel(ReviewDeliveryLabel, text); + sprintf_s(text, "%d damage for %d mana.", Damage, ManaCost()); + SetLabel(ReviewPowerLabel, text); + sprintf_s(text, "%.1f sec cast, %.1f sec recast.", CastTime() / 1000.0f, Recast / 1000.0f); + SetLabel(ReviewCastingLabel, text); + } + + void CreateScroll() + { + const std::string name = ReadName(); + const std::string encoded_name = EncodeName(name); + + char command[256]; + sprintf_s( + command, + "/say #livespell craft element=%s target=%s range=%d damage=%d recast=%d name=%s", + ElementKey(), + TargetKey(), + Range, + Damage, + Recast, + encoded_name.c_str() + ); + + NativeAutoLootSendCommand(command); + SetStatus("Creating scroll. Watch chat for the new item."); + } + + ForgePage CurrentPage = PageForm; + int ElementIndex = 1; + int TargetIndex = 0; + int Range = 200; + int Damage = 100; + int Recast = 3000; + + CButtonWnd* FormTab = nullptr; + CButtonWnd* DeliveryTab = nullptr; + CButtonWnd* PowerTab = nullptr; + CButtonWnd* CastingTab = nullptr; + CButtonWnd* ReviewTab = nullptr; + CXWnd* FormPage = nullptr; + CXWnd* DeliveryPage = nullptr; + CXWnd* PowerPage = nullptr; + CXWnd* CastingPage = nullptr; + CXWnd* ReviewPage = nullptr; + CEditWnd* NameEdit = nullptr; + CButtonWnd* FireButton = nullptr; + CButtonWnd* ColdButton = nullptr; + CButtonWnd* MagicButton = nullptr; + CButtonWnd* PoisonButton = nullptr; + CButtonWnd* DiseaseButton = nullptr; + CXWnd* ElementHintLabel = nullptr; + CButtonWnd* TargetButton = nullptr; + CButtonWnd* AEButton = nullptr; + CButtonWnd* PBAEButton = nullptr; + CButtonWnd* RangeMinusButton = nullptr; + CButtonWnd* RangePlusButton = nullptr; + CXWnd* RangeValueLabel = nullptr; + CXWnd* RadiusValueLabel = nullptr; + CXWnd* TargetHintLabel = nullptr; + CButtonWnd* DamageMinusButton = nullptr; + CButtonWnd* DamagePlusButton = nullptr; + CXWnd* DamageValueLabel = nullptr; + CXWnd* ManaValueLabel = nullptr; + CXWnd* PowerHintLabel = nullptr; + CButtonWnd* RecastMinusButton = nullptr; + CButtonWnd* RecastPlusButton = nullptr; + CXWnd* RecastValueLabel = nullptr; + CXWnd* CastValueLabel = nullptr; + CXWnd* CastingHintLabel = nullptr; + CXWnd* ReviewNameLabel = nullptr; + CXWnd* ReviewFormLabel = nullptr; + CXWnd* ReviewDeliveryLabel = nullptr; + CXWnd* ReviewPowerLabel = nullptr; + CXWnd* ReviewCastingLabel = nullptr; + CButtonWnd* CreateButton = nullptr; + CXWnd* StatusLabel = nullptr; +}; + +static NativeSpellForgeWnd* gNativeSpellForgeWnd = nullptr; + +static void NativeSpellForgeShowWindow(const std::string& payload) +{ + if (!gNativeSpellForgeWnd) { + NativeAutoLootTrace("creating spell forge window"); + gNativeSpellForgeWnd = new NativeSpellForgeWnd(); + } + + gNativeSpellForgeWnd->Open(payload); +} + +class NativeItemForgeWnd : public CCustomWnd +{ +public: + NativeItemForgeWnd() : CCustomWnd((char*)"NativeItemForgeWnd") + { + CloseOnESC = 1; + SetWndNotification(NativeItemForgeWnd); + + FormTab = (CButtonWnd*)GetChildItem("AIFW_FormTab"); + StatsTab = (CButtonWnd*)GetChildItem("AIFW_StatsTab"); + CombatTab = (CButtonWnd*)GetChildItem("AIFW_CombatTab"); + ReviewTab = (CButtonWnd*)GetChildItem("AIFW_ReviewTab"); + FormPage = GetChildItem("AIFW_FormPage"); + StatsPage = GetChildItem("AIFW_StatsPage"); + CombatPage = GetChildItem("AIFW_CombatPage"); + ReviewPage = GetChildItem("AIFW_ReviewPage"); - DamageMinusButton = (CButtonWnd*)GetChildItem("ASFW_DamageMinusButton"); - DamagePlusButton = (CButtonWnd*)GetChildItem("ASFW_DamagePlusButton"); - DamageValueLabel = GetChildItem("ASFW_DamageValueLabel"); - ManaValueLabel = GetChildItem("ASFW_ManaValueLabel"); - PowerHintLabel = GetChildItem("ASFW_PowerHintLabel"); + NameEdit = (CEditWnd*)GetChildItem("AIFW_NameEdit"); + WeaponButton = (CButtonWnd*)GetChildItem("AIFW_WeaponButton"); + ArmorButton = (CButtonWnd*)GetChildItem("AIFW_ArmorButton"); + JewelryButton = (CButtonWnd*)GetChildItem("AIFW_JewelryButton"); + CharmButton = (CButtonWnd*)GetChildItem("AIFW_CharmButton"); + ShieldButton = (CButtonWnd*)GetChildItem("AIFW_ShieldButton"); + TypeHintLabel = GetChildItem("AIFW_TypeHintLabel"); - RecastMinusButton = (CButtonWnd*)GetChildItem("ASFW_RecastMinusButton"); - RecastPlusButton = (CButtonWnd*)GetChildItem("ASFW_RecastPlusButton"); - RecastValueLabel = GetChildItem("ASFW_RecastValueLabel"); - CastValueLabel = GetChildItem("ASFW_CastValueLabel"); - CastingHintLabel = GetChildItem("ASFW_CastingHintLabel"); + HPMinusButton = (CButtonWnd*)GetChildItem("AIFW_HPMinusButton"); + HPPlusButton = (CButtonWnd*)GetChildItem("AIFW_HPPlusButton"); + HPValueLabel = GetChildItem("AIFW_HPValueLabel"); + ManaMinusButton = (CButtonWnd*)GetChildItem("AIFW_ManaMinusButton"); + ManaPlusButton = (CButtonWnd*)GetChildItem("AIFW_ManaPlusButton"); + ManaValueLabel = GetChildItem("AIFW_ManaValueLabel"); + ACMinusButton = (CButtonWnd*)GetChildItem("AIFW_ACMinusButton"); + ACPlusButton = (CButtonWnd*)GetChildItem("AIFW_ACPlusButton"); + ACValueLabel = GetChildItem("AIFW_ACValueLabel"); + StatsHintLabel = GetChildItem("AIFW_StatsHintLabel"); - ReviewNameLabel = GetChildItem("ASFW_ReviewNameLabel"); - ReviewFormLabel = GetChildItem("ASFW_ReviewFormLabel"); - ReviewDeliveryLabel = GetChildItem("ASFW_ReviewDeliveryLabel"); - ReviewPowerLabel = GetChildItem("ASFW_ReviewPowerLabel"); - ReviewCastingLabel = GetChildItem("ASFW_ReviewCastingLabel"); - CreateButton = (CButtonWnd*)GetChildItem("ASFW_CreateButton"); - StatusLabel = GetChildItem("ASFW_StatusLabel"); + DamageMinusButton = (CButtonWnd*)GetChildItem("AIFW_DamageMinusButton"); + DamagePlusButton = (CButtonWnd*)GetChildItem("AIFW_DamagePlusButton"); + DamageValueLabel = GetChildItem("AIFW_DamageValueLabel"); + DelayMinusButton = (CButtonWnd*)GetChildItem("AIFW_DelayMinusButton"); + DelayPlusButton = (CButtonWnd*)GetChildItem("AIFW_DelayPlusButton"); + DelayValueLabel = GetChildItem("AIFW_DelayValueLabel"); + HasteMinusButton = (CButtonWnd*)GetChildItem("AIFW_HasteMinusButton"); + HastePlusButton = (CButtonWnd*)GetChildItem("AIFW_HastePlusButton"); + HasteValueLabel = GetChildItem("AIFW_HasteValueLabel"); + CombatHintLabel = GetChildItem("AIFW_CombatHintLabel"); - SetEditText(DefaultSpellName().c_str()); + ReviewNameLabel = GetChildItem("AIFW_ReviewNameLabel"); + ReviewTypeLabel = GetChildItem("AIFW_ReviewTypeLabel"); + ReviewStatsLabel = GetChildItem("AIFW_ReviewStatsLabel"); + ReviewCombatLabel = GetChildItem("AIFW_ReviewCombatLabel"); + CreateButton = (CButtonWnd*)GetChildItem("AIFW_CreateButton"); + StatusLabel = GetChildItem("AIFW_StatusLabel"); + + SetEditText(DefaultItemName().c_str()); ShowPage(PageForm); - SetStatus("Choose a spell form, then tune delivery and power."); + SetStatus("Choose an item form, then tune stats and combat values."); UpdateView(); } @@ -680,110 +3235,120 @@ class NativeSpellForgeWnd : public CCustomWnd return 1; } - if (pWnd == (CXWnd*)DeliveryTab) { - ShowPage(PageDelivery); + if (pWnd == (CXWnd*)StatsTab) { + ShowPage(PageStats); return 1; } - if (pWnd == (CXWnd*)PowerTab) { - ShowPage(PagePower); + if (pWnd == (CXWnd*)CombatTab) { + ShowPage(PageCombat); return 1; } - if (pWnd == (CXWnd*)CastingTab) { - ShowPage(PageCasting); + if (pWnd == (CXWnd*)ReviewTab) { + ShowPage(PageReview); return 1; } - if (pWnd == (CXWnd*)ReviewTab) { - ShowPage(PageReview); + if (pWnd == (CXWnd*)WeaponButton) { + SelectType(0); return 1; } - if (pWnd == (CXWnd*)FireButton) { - SelectElement(0); + if (pWnd == (CXWnd*)ArmorButton) { + SelectType(1); return 1; } - if (pWnd == (CXWnd*)ColdButton) { - SelectElement(1); + if (pWnd == (CXWnd*)JewelryButton) { + SelectType(2); return 1; } - if (pWnd == (CXWnd*)MagicButton) { - SelectElement(2); + if (pWnd == (CXWnd*)CharmButton) { + SelectType(3); return 1; } - if (pWnd == (CXWnd*)PoisonButton) { - SelectElement(3); + if (pWnd == (CXWnd*)ShieldButton) { + SelectType(4); return 1; } - if (pWnd == (CXWnd*)DiseaseButton) { - SelectElement(4); + if (pWnd == (CXWnd*)HPMinusButton) { + HP = ClampInt(HP - 25, 0, 500); + UpdateView(); return 1; } - if (pWnd == (CXWnd*)TargetButton) { - TargetIndex = 0; - SetStatus("Delivery set to single target."); + if (pWnd == (CXWnd*)HPPlusButton) { + HP = ClampInt(HP + 25, 0, 500); UpdateView(); return 1; } - if (pWnd == (CXWnd*)AEButton) { - TargetIndex = 1; - SetStatus("Delivery set to targeted AE."); + if (pWnd == (CXWnd*)ManaMinusButton) { + Mana = ClampInt(Mana - 25, 0, 500); UpdateView(); return 1; } - if (pWnd == (CXWnd*)PBAEButton) { - TargetIndex = 2; - SetStatus("Delivery set to point blank AE."); + if (pWnd == (CXWnd*)ManaPlusButton) { + Mana = ClampInt(Mana + 25, 0, 500); UpdateView(); return 1; } - if (pWnd == (CXWnd*)RangeMinusButton) { - Range = ClampInt(Range - 25, 25, 300); + if (pWnd == (CXWnd*)ACMinusButton) { + AC = ClampInt(AC - 5, 0, 100); UpdateView(); return 1; } - if (pWnd == (CXWnd*)RangePlusButton) { - Range = ClampInt(Range + 25, 25, 300); + if (pWnd == (CXWnd*)ACPlusButton) { + AC = ClampInt(AC + 5, 0, 100); UpdateView(); return 1; } if (pWnd == (CXWnd*)DamageMinusButton) { - Damage = ClampInt(Damage - 25, 25, 500); + Damage = ClampInt(Damage - 2, 0, 100); UpdateView(); return 1; } if (pWnd == (CXWnd*)DamagePlusButton) { - Damage = ClampInt(Damage + 25, 25, 500); + Damage = ClampInt(Damage + 2, 0, 100); UpdateView(); return 1; } - if (pWnd == (CXWnd*)RecastMinusButton) { - Recast = ClampInt(Recast - 1000, 1000, 30000); + if (pWnd == (CXWnd*)DelayMinusButton) { + Delay = ClampInt(Delay - 2, 10, 60); UpdateView(); return 1; } - if (pWnd == (CXWnd*)RecastPlusButton) { - Recast = ClampInt(Recast + 1000, 1000, 30000); + if (pWnd == (CXWnd*)DelayPlusButton) { + Delay = ClampInt(Delay + 2, 10, 60); + UpdateView(); + return 1; + } + + if (pWnd == (CXWnd*)HasteMinusButton) { + Haste = ClampInt(Haste - 5, 0, 50); + UpdateView(); + return 1; + } + + if (pWnd == (CXWnd*)HastePlusButton) { + Haste = ClampInt(Haste + 5, 0, 50); UpdateView(); return 1; } if (pWnd == (CXWnd*)CreateButton) { - CreateScroll(); + CreateItem(); return 1; } } @@ -795,7 +3360,7 @@ class NativeSpellForgeWnd : public CCustomWnd { (void)payload; pXWnd()->Show(1, 1); - SetStatus("Spell Forge opened. Build a scroll, then scribe it normally."); + SetStatus("Item Forge opened. Create will summon the finished item."); UpdateView(); } @@ -804,12 +3369,11 @@ class NativeSpellForgeWnd : public CCustomWnd } private: - enum ForgePage { + enum ItemPage { PageForm = 0, - PageDelivery = 1, - PagePower = 2, - PageCasting = 3, - PageReview = 4 + PageStats = 1, + PageCombat = 2, + PageReview = 3 }; static int ClampInt(int value, int minimum, int maximum) @@ -853,127 +3417,78 @@ class NativeSpellForgeWnd : public CCustomWnd SetLabel(StatusLabel, text); } - const char* ElementKey() const - { - switch (ElementIndex) { - case 1: - return "cold"; - case 2: - return "magic"; - case 3: - return "poison"; - case 4: - return "disease"; - default: - return "fire"; - } - } - - const char* ElementLabel() const - { - switch (ElementIndex) { - case 1: - return "Cold"; - case 2: - return "Magic"; - case 3: - return "Poison"; - case 4: - return "Disease"; - default: - return "Fire"; - } - } - - const char* ElementNoun() const - { - switch (ElementIndex) { - case 1: - return "Frost"; - case 2: - return "Arcane"; - case 3: - return "Venom"; - case 4: - return "Blight"; - default: - return "Ember"; - } - } - - const char* ElementHint() const + const char* TypeKey() const { - switch (ElementIndex) { + switch (TypeIndex) { case 1: - return "Cold uses a chill resist profile and a blue spell icon."; + return "armor"; case 2: - return "Magic is a clean arcane damage pattern."; + return "jewelry"; case 3: - return "Poison uses the poison resist profile for green damage spells."; + return "charm"; case 4: - return "Disease uses the disease resist profile and a darker icon."; - default: - return "Fire uses the fire resist profile and the ember icon."; - } - } - - const char* TargetKey() const - { - if (TargetIndex == 1) { - return "ae"; - } - - if (TargetIndex == 2) { - return "pbae"; - } - - return "target"; - } - - const char* TargetLabel() const - { - if (TargetIndex == 1) { - return "Targeted AE"; - } - - if (TargetIndex == 2) { - return "Point Blank AE"; + return "shield"; + default: + return "weapon"; } - - return "Single Target"; } - const char* TargetSuffix() const + const char* TypeLabel() const { - if (TargetIndex == 1) { - return "Burst"; - } - - if (TargetIndex == 2) { - return "Bloom"; + switch (TypeIndex) { + case 1: + return "Armor"; + case 2: + return "Jewelry"; + case 3: + return "Charm"; + case 4: + return "Shield"; + default: + return "Weapon"; } - - return "Lash"; } - int Radius() const + const char* TypeSuffix() const { - return TargetIndex == 0 ? 0 : 35; + switch (TypeIndex) { + case 1: + return "Cuirass"; + case 2: + return "Ring"; + case 3: + return "Charm"; + case 4: + return "Shield"; + default: + return "Blade"; + } } - int ManaCost() const + const char* TypeHint() const { - return ClampInt(5 + (Damage / 5), 5, 5000); + switch (TypeIndex) { + case 1: + return "Armor becomes a chest piece and favors AC over weapon values."; + case 2: + return "Jewelry becomes a ring and carries clean HP, mana, and AC stats."; + case 3: + return "Charms equip in the charm slot and ignore combat weapon values."; + case 4: + return "Shields equip in secondary and turn AC into the main stat."; + default: + return "Weapons equip primary or secondary and use damage, delay, and haste."; + } } - int CastTime() const + bool UsesCombatValues() const { - return ClampInt(1500 + (Damage / 20), 1500, 6000); + return TypeIndex == 0; } - std::string DefaultSpellName() const + std::string DefaultItemName() const { - return std::string(ElementNoun()) + " " + TargetSuffix(); + return std::string("Forged ") + TypeSuffix(); } void SetEditText(const char* text) @@ -983,7 +3498,7 @@ class NativeSpellForgeWnd : public CCustomWnd } char buffer[80] = { 0 }; - strcpy_s(buffer, text && text[0] ? text : DefaultSpellName().c_str()); + strcpy_s(buffer, text && text[0] ? text : DefaultItemName().c_str()); SetCXStr(&NameEdit->InputText, buffer); CXStr value(buffer); ((CXWnd*)NameEdit)->SetWindowTextA(value); @@ -998,7 +3513,7 @@ class NativeSpellForgeWnd : public CCustomWnd std::string name(text); if (name.empty()) { - name = DefaultSpellName(); + name = DefaultItemName(); } return name; @@ -1031,7 +3546,7 @@ class NativeSpellForgeWnd : public CCustomWnd } if (encoded.empty()) { - encoded = DefaultSpellName(); + encoded = DefaultItemName(); for (char& ch : encoded) { if (ch == ' ') { ch = '_'; @@ -1042,21 +3557,20 @@ class NativeSpellForgeWnd : public CCustomWnd return encoded; } - void SelectElement(int index) + void SelectType(int index) { - ElementIndex = ClampInt(index, 0, 4); - SetEditText(DefaultSpellName().c_str()); - SetStatus("Spell form changed."); + TypeIndex = ClampInt(index, 0, 4); + SetEditText(DefaultItemName().c_str()); + SetStatus("Item form changed."); UpdateView(); } - void ShowPage(ForgePage page) + void ShowPage(ItemPage page) { CurrentPage = page; SetVisible(FormPage, CurrentPage == PageForm); - SetVisible(DeliveryPage, CurrentPage == PageDelivery); - SetVisible(PowerPage, CurrentPage == PagePower); - SetVisible(CastingPage, CurrentPage == PageCasting); + SetVisible(StatsPage, CurrentPage == PageStats); + SetVisible(CombatPage, CurrentPage == PageCombat); SetVisible(ReviewPage, CurrentPage == PageReview); UpdateView(); } @@ -1064,203 +3578,182 @@ class NativeSpellForgeWnd : public CCustomWnd void UpdateTabs() { SetButtonText(FormTab, CurrentPage == PageForm ? "> Form <" : "Form"); - SetButtonText(DeliveryTab, CurrentPage == PageDelivery ? "> Delivery <" : "Delivery"); - SetButtonText(PowerTab, CurrentPage == PagePower ? "> Power <" : "Power"); - SetButtonText(CastingTab, CurrentPage == PageCasting ? "> Casting <" : "Casting"); + SetButtonText(StatsTab, CurrentPage == PageStats ? "> Stats <" : "Stats"); + SetButtonText(CombatTab, CurrentPage == PageCombat ? "> Combat <" : "Combat"); SetButtonText(ReviewTab, CurrentPage == PageReview ? "> Review <" : "Review"); } void UpdateView() { UpdateTabs(); - - SetButtonText(FireButton, ElementIndex == 0 ? "* Fire" : "Fire"); - SetButtonText(ColdButton, ElementIndex == 1 ? "* Cold" : "Cold"); - SetButtonText(MagicButton, ElementIndex == 2 ? "* Magic" : "Magic"); - SetButtonText(PoisonButton, ElementIndex == 3 ? "* Poison" : "Poison"); - SetButtonText(DiseaseButton, ElementIndex == 4 ? "* Disease" : "Disease"); - SetLabel(ElementHintLabel, ElementHint()); - - SetButtonText(TargetButton, TargetIndex == 0 ? "* Single Target" : "Single Target"); - SetButtonText(AEButton, TargetIndex == 1 ? "* Targeted AE" : "Targeted AE"); - SetButtonText(PBAEButton, TargetIndex == 2 ? "* Point Blank AE" : "Point Blank AE"); + SetButtonText(WeaponButton, TypeIndex == 0 ? "* Weapon" : "Weapon"); + SetButtonText(ArmorButton, TypeIndex == 1 ? "* Armor" : "Armor"); + SetButtonText(JewelryButton, TypeIndex == 2 ? "* Jewelry" : "Jewelry"); + SetButtonText(CharmButton, TypeIndex == 3 ? "* Charm" : "Charm"); + SetButtonText(ShieldButton, TypeIndex == 4 ? "* Shield" : "Shield"); + SetLabel(TypeHintLabel, TypeHint()); char text[192]; - sprintf_s(text, "%d", Range); - SetLabel(RangeValueLabel, text); - sprintf_s(text, "%d", Radius()); - SetLabel(RadiusValueLabel, text); - sprintf_s(text, "%s spells use range %d and radius %d.", TargetLabel(), Range, Radius()); - SetLabel(TargetHintLabel, text); - - sprintf_s(text, "%d", Damage); - SetLabel(DamageValueLabel, text); - sprintf_s(text, "%d", ManaCost()); + sprintf_s(text, "%d", HP); + SetLabel(HPValueLabel, text); + sprintf_s(text, "%d", Mana); SetLabel(ManaValueLabel, text); - sprintf_s(text, "Higher damage raises mana and cast time. Current damage range is 25 to 500."); - SetLabel(PowerHintLabel, text); + sprintf_s(text, "%d", AC); + SetLabel(ACValueLabel, text); + sprintf_s(text, "Stat ranges: HP 0-500, Mana 0-500, AC 0-100."); + SetLabel(StatsHintLabel, text); - sprintf_s(text, "%.1f sec", Recast / 1000.0f); - SetLabel(RecastValueLabel, text); - sprintf_s(text, "%.1f sec", CastTime() / 1000.0f); - SetLabel(CastValueLabel, text); - sprintf_s(text, "Short recasts feel snappy; long recasts are safer for stronger spells."); - SetLabel(CastingHintLabel, text); + sprintf_s(text, "%d", UsesCombatValues() ? Damage : 0); + SetLabel(DamageValueLabel, text); + sprintf_s(text, "%d", UsesCombatValues() ? Delay : 0); + SetLabel(DelayValueLabel, text); + sprintf_s(text, "%d%%", UsesCombatValues() ? Haste : 0); + SetLabel(HasteValueLabel, text); + SetLabel(CombatHintLabel, UsesCombatValues() ? "Weapon values apply to blades. Other forms keep these at zero." : "This item form ignores weapon damage, delay, and haste."); const std::string name = ReadName(); SetLabel(ReviewNameLabel, name.c_str()); - sprintf_s(text, "%s damage using %s resist.", ElementLabel(), ElementLabel()); - SetLabel(ReviewFormLabel, text); - sprintf_s(text, "%s, range %d, radius %d.", TargetLabel(), Range, Radius()); - SetLabel(ReviewDeliveryLabel, text); - sprintf_s(text, "%d damage for %d mana.", Damage, ManaCost()); - SetLabel(ReviewPowerLabel, text); - sprintf_s(text, "%.1f sec cast, %.1f sec recast.", CastTime() / 1000.0f, Recast / 1000.0f); - SetLabel(ReviewCastingLabel, text); + sprintf_s(text, "%s item, summoned directly to your cursor.", TypeLabel()); + SetLabel(ReviewTypeLabel, text); + sprintf_s(text, "HP %d, Mana %d, AC %d.", HP, Mana, AC); + SetLabel(ReviewStatsLabel, text); + sprintf_s(text, "Damage %d, Delay %d, Haste %d%%.", UsesCombatValues() ? Damage : 0, UsesCombatValues() ? Delay : 0, UsesCombatValues() ? Haste : 0); + SetLabel(ReviewCombatLabel, text); } - void CreateScroll() + void CreateItem() { - const std::string name = ReadName(); - const std::string encoded_name = EncodeName(name); - + const std::string encoded_name = EncodeName(ReadName()); char command[256]; sprintf_s( command, - "/say #livespell craft element=%s target=%s range=%d damage=%d recast=%d name=%s", - ElementKey(), - TargetKey(), - Range, - Damage, - Recast, + "/say #itemforge craft type=%s hp=%d mana=%d ac=%d damage=%d delay=%d haste=%d name=%s", + TypeKey(), + HP, + Mana, + AC, + UsesCombatValues() ? Damage : 0, + UsesCombatValues() ? Delay : 24, + UsesCombatValues() ? Haste : 0, encoded_name.c_str() ); NativeAutoLootSendCommand(command); - SetStatus("Creating scroll. Watch chat for the new item."); + SetStatus("Creating item. Watch chat and your cursor."); } - ForgePage CurrentPage = PageForm; - int ElementIndex = 1; - int TargetIndex = 0; - int Range = 200; - int Damage = 100; - int Recast = 3000; + ItemPage CurrentPage = PageForm; + int TypeIndex = 0; + int HP = 50; + int Mana = 25; + int AC = 5; + int Damage = 8; + int Delay = 24; + int Haste = 0; CButtonWnd* FormTab = nullptr; - CButtonWnd* DeliveryTab = nullptr; - CButtonWnd* PowerTab = nullptr; - CButtonWnd* CastingTab = nullptr; + CButtonWnd* StatsTab = nullptr; + CButtonWnd* CombatTab = nullptr; CButtonWnd* ReviewTab = nullptr; CXWnd* FormPage = nullptr; - CXWnd* DeliveryPage = nullptr; - CXWnd* PowerPage = nullptr; - CXWnd* CastingPage = nullptr; + CXWnd* StatsPage = nullptr; + CXWnd* CombatPage = nullptr; CXWnd* ReviewPage = nullptr; CEditWnd* NameEdit = nullptr; - CButtonWnd* FireButton = nullptr; - CButtonWnd* ColdButton = nullptr; - CButtonWnd* MagicButton = nullptr; - CButtonWnd* PoisonButton = nullptr; - CButtonWnd* DiseaseButton = nullptr; - CXWnd* ElementHintLabel = nullptr; - CButtonWnd* TargetButton = nullptr; - CButtonWnd* AEButton = nullptr; - CButtonWnd* PBAEButton = nullptr; - CButtonWnd* RangeMinusButton = nullptr; - CButtonWnd* RangePlusButton = nullptr; - CXWnd* RangeValueLabel = nullptr; - CXWnd* RadiusValueLabel = nullptr; - CXWnd* TargetHintLabel = nullptr; + CButtonWnd* WeaponButton = nullptr; + CButtonWnd* ArmorButton = nullptr; + CButtonWnd* JewelryButton = nullptr; + CButtonWnd* CharmButton = nullptr; + CButtonWnd* ShieldButton = nullptr; + CXWnd* TypeHintLabel = nullptr; + CButtonWnd* HPMinusButton = nullptr; + CButtonWnd* HPPlusButton = nullptr; + CXWnd* HPValueLabel = nullptr; + CButtonWnd* ManaMinusButton = nullptr; + CButtonWnd* ManaPlusButton = nullptr; + CXWnd* ManaValueLabel = nullptr; + CButtonWnd* ACMinusButton = nullptr; + CButtonWnd* ACPlusButton = nullptr; + CXWnd* ACValueLabel = nullptr; + CXWnd* StatsHintLabel = nullptr; CButtonWnd* DamageMinusButton = nullptr; CButtonWnd* DamagePlusButton = nullptr; CXWnd* DamageValueLabel = nullptr; - CXWnd* ManaValueLabel = nullptr; - CXWnd* PowerHintLabel = nullptr; - CButtonWnd* RecastMinusButton = nullptr; - CButtonWnd* RecastPlusButton = nullptr; - CXWnd* RecastValueLabel = nullptr; - CXWnd* CastValueLabel = nullptr; - CXWnd* CastingHintLabel = nullptr; + CButtonWnd* DelayMinusButton = nullptr; + CButtonWnd* DelayPlusButton = nullptr; + CXWnd* DelayValueLabel = nullptr; + CButtonWnd* HasteMinusButton = nullptr; + CButtonWnd* HastePlusButton = nullptr; + CXWnd* HasteValueLabel = nullptr; + CXWnd* CombatHintLabel = nullptr; CXWnd* ReviewNameLabel = nullptr; - CXWnd* ReviewFormLabel = nullptr; - CXWnd* ReviewDeliveryLabel = nullptr; - CXWnd* ReviewPowerLabel = nullptr; - CXWnd* ReviewCastingLabel = nullptr; + CXWnd* ReviewTypeLabel = nullptr; + CXWnd* ReviewStatsLabel = nullptr; + CXWnd* ReviewCombatLabel = nullptr; CButtonWnd* CreateButton = nullptr; CXWnd* StatusLabel = nullptr; }; -static NativeSpellForgeWnd* gNativeSpellForgeWnd = nullptr; +static NativeItemForgeWnd* gNativeItemForgeWnd = nullptr; -static void NativeSpellForgeShowWindow(const std::string& payload) -{ - if (!gNativeSpellForgeWnd) { - NativeAutoLootTrace("creating spell forge window"); - gNativeSpellForgeWnd = new NativeSpellForgeWnd(); +static void NativeItemForgeShowWindow(const std::string& payload) +{ + if (!gNativeItemForgeWnd) { + NativeAutoLootTrace("creating item forge window"); + gNativeItemForgeWnd = new NativeItemForgeWnd(); } - gNativeSpellForgeWnd->Open(payload); + gNativeItemForgeWnd->Open(payload); } -class NativeItemForgeWnd : public CCustomWnd +class NativeUIShowcaseWnd : public CCustomWnd { public: - NativeItemForgeWnd() : CCustomWnd((char*)"NativeItemForgeWnd") + NativeUIShowcaseWnd() : CCustomWnd((char*)"NativeUIShowcaseWnd") { + NativeAutoLootTrace("UI showcase constructor body entered"); CloseOnESC = 1; - SetWndNotification(NativeItemForgeWnd); - - FormTab = (CButtonWnd*)GetChildItem("AIFW_FormTab"); - StatsTab = (CButtonWnd*)GetChildItem("AIFW_StatsTab"); - CombatTab = (CButtonWnd*)GetChildItem("AIFW_CombatTab"); - ReviewTab = (CButtonWnd*)GetChildItem("AIFW_ReviewTab"); - FormPage = GetChildItem("AIFW_FormPage"); - StatsPage = GetChildItem("AIFW_StatsPage"); - CombatPage = GetChildItem("AIFW_CombatPage"); - ReviewPage = GetChildItem("AIFW_ReviewPage"); - - NameEdit = (CEditWnd*)GetChildItem("AIFW_NameEdit"); - WeaponButton = (CButtonWnd*)GetChildItem("AIFW_WeaponButton"); - ArmorButton = (CButtonWnd*)GetChildItem("AIFW_ArmorButton"); - JewelryButton = (CButtonWnd*)GetChildItem("AIFW_JewelryButton"); - CharmButton = (CButtonWnd*)GetChildItem("AIFW_CharmButton"); - ShieldButton = (CButtonWnd*)GetChildItem("AIFW_ShieldButton"); - TypeHintLabel = GetChildItem("AIFW_TypeHintLabel"); - - HPMinusButton = (CButtonWnd*)GetChildItem("AIFW_HPMinusButton"); - HPPlusButton = (CButtonWnd*)GetChildItem("AIFW_HPPlusButton"); - HPValueLabel = GetChildItem("AIFW_HPValueLabel"); - ManaMinusButton = (CButtonWnd*)GetChildItem("AIFW_ManaMinusButton"); - ManaPlusButton = (CButtonWnd*)GetChildItem("AIFW_ManaPlusButton"); - ManaValueLabel = GetChildItem("AIFW_ManaValueLabel"); - ACMinusButton = (CButtonWnd*)GetChildItem("AIFW_ACMinusButton"); - ACPlusButton = (CButtonWnd*)GetChildItem("AIFW_ACPlusButton"); - ACValueLabel = GetChildItem("AIFW_ACValueLabel"); - StatsHintLabel = GetChildItem("AIFW_StatsHintLabel"); - - DamageMinusButton = (CButtonWnd*)GetChildItem("AIFW_DamageMinusButton"); - DamagePlusButton = (CButtonWnd*)GetChildItem("AIFW_DamagePlusButton"); - DamageValueLabel = GetChildItem("AIFW_DamageValueLabel"); - DelayMinusButton = (CButtonWnd*)GetChildItem("AIFW_DelayMinusButton"); - DelayPlusButton = (CButtonWnd*)GetChildItem("AIFW_DelayPlusButton"); - DelayValueLabel = GetChildItem("AIFW_DelayValueLabel"); - HasteMinusButton = (CButtonWnd*)GetChildItem("AIFW_HasteMinusButton"); - HastePlusButton = (CButtonWnd*)GetChildItem("AIFW_HastePlusButton"); - HasteValueLabel = GetChildItem("AIFW_HasteValueLabel"); - CombatHintLabel = GetChildItem("AIFW_CombatHintLabel"); - - ReviewNameLabel = GetChildItem("AIFW_ReviewNameLabel"); - ReviewTypeLabel = GetChildItem("AIFW_ReviewTypeLabel"); - ReviewStatsLabel = GetChildItem("AIFW_ReviewStatsLabel"); - ReviewCombatLabel = GetChildItem("AIFW_ReviewCombatLabel"); - CreateButton = (CButtonWnd*)GetChildItem("AIFW_CreateButton"); - StatusLabel = GetChildItem("AIFW_StatusLabel"); - - SetEditText(DefaultItemName().c_str()); - ShowPage(PageForm); - SetStatus("Choose an item form, then tune stats and combat values."); - UpdateView(); + SetWndNotification(NativeUIShowcaseWnd); + + InputsTab = (CButtonWnd*)GetChildItem("NUIS_InputsTab"); + DataTab = (CButtonWnd*)GetChildItem("NUIS_DataTab"); + TextTab = (CButtonWnd*)GetChildItem("NUIS_TextTab"); + InputsPage = GetChildItem("NUIS_InputsPage"); + DataPage = GetChildItem("NUIS_DataPage"); + TextPage = GetChildItem("NUIS_TextPage"); + + NameEdit = (CEditWnd*)GetChildItem("NUIS_NameEdit"); + ModeCombo = (CComboWnd*)GetChildItem("NUIS_ModeCombo"); + PreviewCheck = (CButtonWnd*)GetChildItem("NUIS_EnablePreviewCheck"); + AutoApplyCheck = (CButtonWnd*)GetChildItem("NUIS_AutoApplyCheck"); + GoldRadio = (CButtonWnd*)GetChildItem("NUIS_GoldRadio"); + GreenRadio = (CButtonWnd*)GetChildItem("NUIS_GreenRadio"); + RedRadio = (CButtonWnd*)GetChildItem("NUIS_RedRadio"); + DensitySlider = (CSliderWnd*)GetChildItem("NUIS_DensitySlider"); + DensityMinusButton = (CButtonWnd*)GetChildItem("NUIS_DensityMinusButton"); + DensityPlusButton = (CButtonWnd*)GetChildItem("NUIS_DensityPlusButton"); + DensityValueLabel = GetChildItem("NUIS_DensityValueLabel"); + ApplyButton = (CButtonWnd*)GetChildItem("NUIS_ApplyButton"); + ResetButton = (CButtonWnd*)GetChildItem("NUIS_ResetButton"); + InputPreviewLabel = GetChildItem("NUIS_InputPreviewLabel"); + + ControlList = (CListWnd*)GetChildItem("NUIS_ControlList"); + SelectFirstButton = (CButtonWnd*)GetChildItem("NUIS_SelectFirstButton"); + AddRowButton = (CButtonWnd*)GetChildItem("NUIS_AddRowButton"); + DataStatusLabel = GetChildItem("NUIS_DataStatusLabel"); + + StoryText = (CStmlWnd*)GetChildItem("NUIS_StoryText"); + STMLPlainButton = (CButtonWnd*)GetChildItem("NUIS_STMLPlainButton"); + STMLColorButton = (CButtonWnd*)GetChildItem("NUIS_STMLColorButton"); + STMLAppendButton = (CButtonWnd*)GetChildItem("NUIS_STMLAppendButton"); + StatusLabel = GetChildItem("NUIS_StatusLabel"); + NativeAutoLootTrace("UI showcase child controls resolved"); + + PopulateCombo(); + PopulateControlList(); + ResetDemo(); + ShowPage(PageInputs); + SetSTMLPlain(); } int WndNotification(CXWnd* pWnd, unsigned int Message, void* unknown) @@ -1270,481 +3763,825 @@ class NativeItemForgeWnd : public CCustomWnd return 1; } - if (Message == XWM_LCLICK) { - if (pWnd == (CXWnd*)FormTab) { - ShowPage(PageForm); - return 1; - } - - if (pWnd == (CXWnd*)StatsTab) { - ShowPage(PageStats); - return 1; + if (pWnd == (CXWnd*)DensitySlider && (Message == XWM_NEWVALUE || Message == XWM_LMOUSEUP || Message == XWM_LCLICK)) { + if (DensitySlider) { + Density = ClampInt(DensitySlider->GetValue(), 0, 10); + UpdateView(); + SetStatus("Slider changed."); } + return 1; + } - if (pWnd == (CXWnd*)CombatTab) { - ShowPage(PageCombat); - return 1; + if (pWnd == (CXWnd*)ModeCombo && (Message == XWM_NEWVALUE || Message == XWM_LCLICK)) { + if (ModeCombo) { + const int choice = ModeCombo->GetCurChoice(); + if (choice >= 0 && choice <= 3) { + ModeIndex = choice; + UpdateView(); + SetStatus("Dropdown selection changed."); + } } + return 1; + } - if (pWnd == (CXWnd*)ReviewTab) { - ShowPage(PageReview); + if (Message == XWM_LCLICK) { + if (pWnd == (CXWnd*)InputsTab) { + ShowPage(PageInputs); return 1; } - if (pWnd == (CXWnd*)WeaponButton) { - SelectType(0); + if (pWnd == (CXWnd*)DataTab) { + ShowPage(PageData); return 1; } - if (pWnd == (CXWnd*)ArmorButton) { - SelectType(1); + if (pWnd == (CXWnd*)TextTab) { + ShowPage(PageText); return 1; } - if (pWnd == (CXWnd*)JewelryButton) { - SelectType(2); + if (pWnd == (CXWnd*)PreviewCheck) { + PreviewEnabled = !PreviewEnabled; + UpdateView(); + SetStatus("Checkbox toggled."); return 1; } - if (pWnd == (CXWnd*)CharmButton) { - SelectType(3); + if (pWnd == (CXWnd*)AutoApplyCheck) { + AutoApply = !AutoApply; + UpdateView(); + SetStatus("Second checkbox toggled."); return 1; } - if (pWnd == (CXWnd*)ShieldButton) { - SelectType(4); + if (pWnd == (CXWnd*)GoldRadio) { + AccentIndex = 0; + UpdateView(); + SetStatus("Radio group set to gold."); return 1; } - if (pWnd == (CXWnd*)HPMinusButton) { - HP = ClampInt(HP - 25, 0, 500); + if (pWnd == (CXWnd*)GreenRadio) { + AccentIndex = 1; UpdateView(); + SetStatus("Radio group set to green."); return 1; } - if (pWnd == (CXWnd*)HPPlusButton) { - HP = ClampInt(HP + 25, 0, 500); + if (pWnd == (CXWnd*)RedRadio) { + AccentIndex = 2; UpdateView(); + SetStatus("Radio group set to red."); return 1; } - if (pWnd == (CXWnd*)ManaMinusButton) { - Mana = ClampInt(Mana - 25, 0, 500); + if (pWnd == (CXWnd*)DensityMinusButton) { + Density = ClampInt(Density - 1, 0, 10); UpdateView(); + SetStatus("Stepper decreased the slider value."); return 1; } - if (pWnd == (CXWnd*)ManaPlusButton) { - Mana = ClampInt(Mana + 25, 0, 500); + if (pWnd == (CXWnd*)DensityPlusButton) { + Density = ClampInt(Density + 1, 0, 10); UpdateView(); + SetStatus("Stepper increased the slider value."); return 1; } - if (pWnd == (CXWnd*)ACMinusButton) { - AC = ClampInt(AC - 5, 0, 100); + if (pWnd == (CXWnd*)ApplyButton) { UpdateView(); + SetStatus("Applied the current input state locally."); return 1; } - if (pWnd == (CXWnd*)ACPlusButton) { - AC = ClampInt(AC + 5, 0, 100); - UpdateView(); + if (pWnd == (CXWnd*)ResetButton) { + ResetDemo(); + SetStatus("Showcase controls reset."); return 1; } - if (pWnd == (CXWnd*)DamageMinusButton) { - Damage = ClampInt(Damage - 2, 0, 100); - UpdateView(); + if (pWnd == (CXWnd*)ControlList) { + UpdateSelectedListStatus(); return 1; } - if (pWnd == (CXWnd*)DamagePlusButton) { - Damage = ClampInt(Damage + 2, 0, 100); - UpdateView(); + if (pWnd == (CXWnd*)SelectFirstButton) { + if (ControlList) { + ControlList->SetCurSel(0); + } + UpdateSelectedListStatus(); return 1; } - if (pWnd == (CXWnd*)DelayMinusButton) { - Delay = ClampInt(Delay - 2, 10, 60); - UpdateView(); + if (pWnd == (CXWnd*)AddRowButton) { + AddSampleRow(); return 1; } - if (pWnd == (CXWnd*)DelayPlusButton) { - Delay = ClampInt(Delay + 2, 10, 60); - UpdateView(); + if (pWnd == (CXWnd*)STMLPlainButton) { + SetSTMLPlain(); + SetStatus("STML text reset to the plain sample."); return 1; } - if (pWnd == (CXWnd*)HasteMinusButton) { - Haste = ClampInt(Haste - 5, 0, 50); - UpdateView(); + if (pWnd == (CXWnd*)STMLColorButton) { + SetSTMLColor(); + SetStatus("STML text swapped to the color sample."); return 1; } - if (pWnd == (CXWnd*)HastePlusButton) { - Haste = ClampInt(Haste + 5, 0, 50); - UpdateView(); + if (pWnd == (CXWnd*)STMLAppendButton) { + AppendSTMLLine(); + SetStatus("Appended an STML log line."); return 1; } + } + + return CSidlScreenWnd::WndNotification(pWnd, Message, unknown); + } + + void Open() + { + pXWnd()->Show(1, 1); + SetStatus("Native UI Showcase opened. Try the tabs, dropdown, checks, list, slider, gauge, and STML pane."); + UpdateView(); + } + + void Layout() + { + } + + void ResetDemo() + { + ModeIndex = 1; + AccentIndex = 0; + Density = 5; + PreviewEnabled = true; + AutoApply = false; + SetEditText("Prototype Panel"); + UpdateView(); + } + + void SetStatus(const char* text) + { + SetLabel(StatusLabel, text); + } + +private: + enum ShowcasePage { + PageInputs = 0, + PageData = 1, + PageText = 2 + }; + + static int ClampInt(int value, int minimum, int maximum) + { + if (value < minimum) { + return minimum; + } + + if (value > maximum) { + return maximum; + } + + return value; + } + + void SetVisible(CXWnd* wnd, bool visible) + { + if (wnd) { + wnd->Show(visible ? 1 : 0, 1); + } + } + + void SetLabel(CXWnd* label, const char* text) + { + if (label) { + CXStr value(text ? text : ""); + label->SetWindowTextA(value); + } + } + + void SetButtonText(CButtonWnd* button, const char* text) + { + if (button) { + CXStr value(text ? text : ""); + ((CXWnd*)button)->SetWindowTextA(value); + } + } + + void SetButtonCheck(CButtonWnd* button, bool checked) + { + if (button) { + button->Checked = checked ? 1 : 0; + button->SetCheck(checked); + } + } + + void SetEditText(const char* text) + { + if (!NameEdit) { + return; + } + + char buffer[96] = { 0 }; + strcpy_s(buffer, text && text[0] ? text : "Prototype Panel"); + SetCXStr(&NameEdit->InputText, buffer); + CXStr value(buffer); + ((CXWnd*)NameEdit)->SetWindowTextA(value); + } + + std::string ReadName() const + { + char text[96] = { 0 }; + if (NameEdit && NameEdit->InputText) { + GetCXStr(NameEdit->InputText, text, sizeof(text)); + } + + if (!text[0]) { + return "Prototype Panel"; + } + + return text; + } + + const char* ModeLabel() const + { + switch (ModeIndex) { + case 0: + return "Compact"; + case 2: + return "Dense Operations"; + case 3: + return "Read Only"; + default: + return "Comfortable"; + } + } + + const char* AccentLabel() const + { + switch (AccentIndex) { + case 1: + return "Green"; + case 2: + return "Red"; + default: + return "Gold"; + } + } + + COLORREF AccentColor() const + { + switch (AccentIndex) { + case 1: + return 0xFF66FF66; + case 2: + return 0xFFFF8080; + default: + return 0xFFFFFF80; + } + } + + void PopulateCombo() + { + if (!ModeCombo) { + return; + } + + ModeCombo->DeleteAll(); + ModeCombo->InsertChoice((char*)"Compact"); + ModeCombo->InsertChoice((char*)"Comfortable"); + ModeCombo->InsertChoice((char*)"Dense Operations"); + ModeCombo->InsertChoice((char*)"Read Only"); + ModeCombo->SetChoice(ModeIndex); + } + + void AddListRow(const char* control, const char* pattern, const char* notes, COLORREF color, uint32_t data) + { + if (!ControlList) { + return; + } + + CXStr control_text(control); + const int row = ControlList->AddString(control_text, color, data, nullptr, nullptr); + CXStr pattern_text(pattern); + CXStr notes_text(notes); + ControlList->SetItemText(row, 1, &pattern_text); + ControlList->SetItemText(row, 2, ¬es_text); + ControlList->SetItemColor(row, 2, color); + } + + void PopulateControlList() + { + if (!ControlList) { + return; + } + + ControlList->DeleteAll(); + AddListRow("Button", "command", "click actions", 0xFFFFFFFF, 1); + AddListRow("Checkbox", "toggle", "local bool state", 0xFF66FF66, 2); + AddListRow("Radio", "choice set", "one active option", 0xFFFFFF80, 3); + AddListRow("Combobox", "dropdown", "single selection", 0xFF80C0FF, 4); + AddListRow("Slider", "numeric", "drag or stepper", 0xFFFFC080, 5); + AddListRow("Listbox", "table", "rows and columns", 0xFFFFFFFF, 6); + AddListRow("Gauge", "EQType", "bound client value", 0xFFFFFF80, 7); + AddListRow("STMLbox", "rich text", "colored help/logs", 0xFF66FF66, 8); + ControlList->SetCurSel(0); + UpdateSelectedListStatus(); + } + + void AddSampleRow() + { + ++SampleRows; + char control[64]; + sprintf_s(control, "Sample %d", SampleRows); + AddListRow(control, "runtime", "added from C++", AccentColor(), 100 + SampleRows); + if (ControlList) { + ControlList->SetCurSel(7 + SampleRows); + } + SetLabel(DataStatusLabel, "Added a runtime row with hidden item data and accent coloring."); + } - if (pWnd == (CXWnd*)CreateButton) { - CreateItem(); - return 1; - } + void UpdateSelectedListStatus() + { + if (!ControlList) { + return; } - return CSidlScreenWnd::WndNotification(pWnd, Message, unknown); + const int selected = ControlList->GetCurSel(); + if (selected < 0) { + SetLabel(DataStatusLabel, "Select a row to see listbox selection handling."); + return; + } + + const uint32_t data = ControlList->GetItemData(selected); + char text[160]; + sprintf_s(text, "Selected row %d with hidden data %u. List rows can carry text, colors, selection, and item data.", selected + 1, data); + SetLabel(DataStatusLabel, text); } - void Open(const std::string& payload) + void ShowPage(ShowcasePage page) { - (void)payload; - pXWnd()->Show(1, 1); - SetStatus("Item Forge opened. Create will summon the finished item."); - UpdateView(); + CurrentPage = page; + SetVisible(InputsPage, CurrentPage == PageInputs); + SetVisible(DataPage, CurrentPage == PageData); + SetVisible(TextPage, CurrentPage == PageText); + UpdateTabs(); } - void Layout() + void UpdateTabs() { + SetButtonText(InputsTab, CurrentPage == PageInputs ? "> Inputs <" : "Inputs"); + SetButtonText(DataTab, CurrentPage == PageData ? "> Data <" : "Data Views"); + SetButtonText(TextTab, CurrentPage == PageText ? "> Text <" : "Rich Text"); } -private: - enum ItemPage { - PageForm = 0, - PageStats = 1, - PageCombat = 2, - PageReview = 3 - }; - - static int ClampInt(int value, int minimum, int maximum) + void UpdateView() { - if (value < minimum) { - return minimum; + UpdateTabs(); + + if (ModeCombo) { + ModeCombo->SetChoice(ModeIndex); } - if (value > maximum) { - return maximum; + if (DensitySlider) { + DensitySlider->SetNumTicks(10); + DensitySlider->SetValue(Density); } - return value; - } + SetButtonCheck(PreviewCheck, PreviewEnabled); + SetButtonCheck(AutoApplyCheck, AutoApply); + SetButtonCheck(GoldRadio, AccentIndex == 0); + SetButtonCheck(GreenRadio, AccentIndex == 1); + SetButtonCheck(RedRadio, AccentIndex == 2); - void SetLabel(CXWnd* label, const char* text) - { - if (label) { - CXStr value(text ? text : ""); - label->SetWindowTextA(value); - } + SetButtonText(PreviewCheck, PreviewEnabled ? "Preview: On" : "Preview: Off"); + SetButtonText(AutoApplyCheck, AutoApply ? "Auto Apply: On" : "Auto Apply: Off"); + SetButtonText(GoldRadio, AccentIndex == 0 ? "* Gold" : "Gold"); + SetButtonText(GreenRadio, AccentIndex == 1 ? "* Green" : "Green"); + SetButtonText(RedRadio, AccentIndex == 2 ? "* Red" : "Red"); + + char value[32]; + sprintf_s(value, "%d", Density); + SetLabel(DensityValueLabel, value); + + char preview[384]; + sprintf_s( + preview, + "Name: %s\nMode: %s\nPreview: %s Auto Apply: %s Accent: %s Density: %d\nThis is a local-only playground for native EQ controls before we commit to a feature workflow.", + ReadName().c_str(), + ModeLabel(), + PreviewEnabled ? "on" : "off", + AutoApply ? "on" : "off", + AccentLabel(), + Density + ); + SetLabel(InputPreviewLabel, preview); } - void SetButtonText(CButtonWnd* button, const char* text) + void SetSTML(const char* text) { - if (button) { + if (StoryText) { CXStr value(text ? text : ""); - ((CXWnd*)button)->SetWindowTextA(value); + StoryText->SetSTMLText(value, false, nullptr); + StoryText->ForceParseNow(); } } - void SetVisible(CXWnd* wnd, bool visible) + void SetSTMLPlain() { - if (wnd) { - wnd->Show(visible ? 1 : 0, 1); - } + SetSTML( + "Native UI STML sample
    " + "
    " + "Use this for help panes, compact summaries, changelogs, walkthroughs, or output logs.
    " + "Buttons below swap the content or append a new line without recreating the window." + ); } - void SetStatus(const char* text) + void SetSTMLColor() { - SetLabel(StatusLabel, text); + SetSTML( + "Green: success or enabled state
    " + "Gold: warning, pending, or important metadata
    " + "Red: blocked or destructive action
    " + "
    " + "STML is a useful middle ground between plain labels and a full list view." + ); } - const char* TypeKey() const + void AppendSTMLLine() { - switch (TypeIndex) { - case 1: - return "armor"; - case 2: - return "jewelry"; - case 3: - return "charm"; - case 4: - return "shield"; - default: - return "weapon"; + if (!StoryText) { + return; } + + ++LogLine; + char line[128]; + sprintf_s(line, "
    Appended runtime line %d with density %d and %s accent.", LogLine, Density, AccentLabel()); + CXStr value(line); + StoryText->AppendSTML(value); + StoryText->ForceParseNow(); + } + + ShowcasePage CurrentPage = PageInputs; + int ModeIndex = 1; + int AccentIndex = 0; + int Density = 5; + int SampleRows = 0; + int LogLine = 0; + bool PreviewEnabled = true; + bool AutoApply = false; + + CButtonWnd* InputsTab = nullptr; + CButtonWnd* DataTab = nullptr; + CButtonWnd* TextTab = nullptr; + CXWnd* InputsPage = nullptr; + CXWnd* DataPage = nullptr; + CXWnd* TextPage = nullptr; + CEditWnd* NameEdit = nullptr; + CComboWnd* ModeCombo = nullptr; + CButtonWnd* PreviewCheck = nullptr; + CButtonWnd* AutoApplyCheck = nullptr; + CButtonWnd* GoldRadio = nullptr; + CButtonWnd* GreenRadio = nullptr; + CButtonWnd* RedRadio = nullptr; + CSliderWnd* DensitySlider = nullptr; + CButtonWnd* DensityMinusButton = nullptr; + CButtonWnd* DensityPlusButton = nullptr; + CXWnd* DensityValueLabel = nullptr; + CButtonWnd* ApplyButton = nullptr; + CButtonWnd* ResetButton = nullptr; + CXWnd* InputPreviewLabel = nullptr; + CListWnd* ControlList = nullptr; + CButtonWnd* SelectFirstButton = nullptr; + CButtonWnd* AddRowButton = nullptr; + CXWnd* DataStatusLabel = nullptr; + CStmlWnd* StoryText = nullptr; + CButtonWnd* STMLPlainButton = nullptr; + CButtonWnd* STMLColorButton = nullptr; + CButtonWnd* STMLAppendButton = nullptr; + CXWnd* StatusLabel = nullptr; +}; + +static NativeUIShowcaseWnd* gNativeUIShowcaseWnd = nullptr; + +static bool NativeUIShowcaseFileExists(const char* path) +{ + FILE* file = nullptr; + if (fopen_s(&file, path, "r") || !file) { + return false; } - const char* TypeLabel() const - { - switch (TypeIndex) { - case 1: - return "Armor"; - case 2: - return "Jewelry"; - case 3: - return "Charm"; - case 4: - return "Shield"; - default: - return "Weapon"; - } + fclose(file); + return true; +} + +static bool NativeUIShowcaseFileContains(const char* path, const char* needle) +{ + FILE* file = nullptr; + if (fopen_s(&file, path, "r") || !file) { + return false; } - const char* TypeSuffix() const - { - switch (TypeIndex) { - case 1: - return "Cuirass"; - case 2: - return "Ring"; - case 3: - return "Charm"; - case 4: - return "Shield"; - default: - return "Blade"; + char line[1024]; + while (fgets(line, sizeof(line), file)) { + if (strstr(line, needle)) { + fclose(file); + return true; } } - const char* TypeHint() const + fclose(file); + return false; +} + +struct NativeHpFixState +{ + bool has_payload = false; + long long current = 0; + long long maximum = 0; + float percent = 0.0f; +}; + +static NativeHpFixState gNativeHpFixState; + +static std::string NativeHpFixFormatInteger(long long value) +{ + char raw[64]; + sprintf_s(raw, "%lld", value); + + std::string text(raw); + const bool negative = !text.empty() && text[0] == '-'; + int insert_at = static_cast(text.size()) - 3; + const int first_digit = negative ? 1 : 0; + + while (insert_at > first_digit) { + text.insert(static_cast(insert_at), ","); + insert_at -= 3; + } + + return text; +} + +static void NativeHpFixSetLabel(CXWnd* label, const char* text) +{ + if (label) { + CXStr value(text ? text : ""); + label->SetWindowTextA(value); + } +} + +class NativeHpFixWnd : public CCustomWnd +{ +public: + NativeHpFixWnd() : CCustomWnd((char*)"NativeHpFixWnd") { - switch (TypeIndex) { - case 1: - return "Armor becomes a chest piece and favors AC over weapon values."; - case 2: - return "Jewelry becomes a ring and carries clean HP, mana, and AC stats."; - case 3: - return "Charms equip in the charm slot and ignore combat weapon values."; - case 4: - return "Shields equip in secondary and turn AC into the main stat."; - default: - return "Weapons equip primary or secondary and use damage, delay, and haste."; - } + CloseOnESC = 1; + SetWndNotification(NativeHpFixWnd); + + StatusLabel = GetChildItem("HPFIX_StatusLabel"); + CurrentLabel = GetChildItem("HPFIX_CurrentLabel"); + MaxLabel = GetChildItem("HPFIX_MaxLabel"); + PercentLabel = GetChildItem("HPFIX_PercentLabel"); + DetailLabel = GetChildItem("HPFIX_DetailLabel"); + + SetStatus("Waiting for native HPFIX payload..."); + Refresh(); } - bool UsesCombatValues() const + int WndNotification(CXWnd* pWnd, unsigned int Message, void* unknown) { - return TypeIndex == 0; + if (Message == XWM_CLOSE) { + pXWnd()->Show(0, 1); + return 1; + } + + return CSidlScreenWnd::WndNotification(pWnd, Message, unknown); } - std::string DefaultItemName() const + void Open() { - return std::string("Forged ") + TypeSuffix(); + pXWnd()->Show(1, 1); + Refresh(); } - void SetEditText(const char* text) + void Refresh() { - if (!NameEdit) { + if (!gNativeHpFixState.has_payload) { + NativeHpFixSetLabel(CurrentLabel, "Current: pending"); + NativeHpFixSetLabel(MaxLabel, "Maximum: pending"); + NativeHpFixSetLabel(PercentLabel, "Percent: pending"); + NativeHpFixSetLabel(DetailLabel, "The server will send authoritative self HP after the DLL handshake."); return; } - char buffer[80] = { 0 }; - strcpy_s(buffer, text && text[0] ? text : DefaultItemName().c_str()); - SetCXStr(&NameEdit->InputText, buffer); - CXStr value(buffer); - ((CXWnd*)NameEdit)->SetWindowTextA(value); + const std::string current = "Current: " + NativeHpFixFormatInteger(gNativeHpFixState.current); + const std::string maximum = "Maximum: " + NativeHpFixFormatInteger(gNativeHpFixState.maximum); + + char percent[64]; + sprintf_s(percent, "Percent: %.2f%%", gNativeHpFixState.percent); + + NativeHpFixSetLabel(CurrentLabel, current.c_str()); + NativeHpFixSetLabel(MaxLabel, maximum.c_str()); + NativeHpFixSetLabel(PercentLabel, percent); + NativeHpFixSetLabel(DetailLabel, "Overlay uses server-authoritative HP and leaves OP_HPUpdate unchanged."); } - std::string ReadName() const + void SetStatus(const char* text) { - char text[80] = { 0 }; - if (NameEdit && NameEdit->InputText) { - GetCXStr(NameEdit->InputText, text, sizeof(text)); - } + NativeHpFixSetLabel(StatusLabel, text); + } - std::string name(text); - if (name.empty()) { - name = DefaultItemName(); - } +private: + CXWnd* StatusLabel = nullptr; + CXWnd* CurrentLabel = nullptr; + CXWnd* MaxLabel = nullptr; + CXWnd* PercentLabel = nullptr; + CXWnd* DetailLabel = nullptr; +}; - return name; +static NativeHpFixWnd* gNativeHpFixWnd = nullptr; + +static bool NativeHpFixClientFilesReady() +{ + char xml_path[MAX_PATH]; + char equi_path[MAX_PATH]; + if (gszEQPath[0]) { + sprintf_s(xml_path, "%s\\uifiles\\default\\EQUI_NativeHpFixWnd.xml", gszEQPath); + sprintf_s(equi_path, "%s\\uifiles\\default\\EQUI.xml", gszEQPath); + } + else { + strcpy_s(xml_path, "uifiles\\default\\EQUI_NativeHpFixWnd.xml"); + strcpy_s(equi_path, "uifiles\\default\\EQUI.xml"); } - std::string EncodeName(const std::string& name) const - { - std::string encoded; - encoded.reserve(name.size()); + if (!NativeUIShowcaseFileExists(xml_path)) { + NativeAutoLootTrace("HPFIX XML missing: %s", xml_path); + return false; + } - for (char ch : name) { - const bool alpha = (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); - const bool digit = ch >= '0' && ch <= '9'; - if (alpha || digit) { - encoded.push_back(ch); - } - else if (ch == ' ' || ch == '_' || ch == '-') { - if (!encoded.empty() && encoded.back() != '_') { - encoded.push_back('_'); - } - } + if (!NativeUIShowcaseFileContains(equi_path, "EQUI_NativeHpFixWnd.xml")) { + NativeAutoLootTrace("HPFIX XML is not included by EQUI.xml: %s", equi_path); + return false; + } - if (encoded.size() >= 40) { - break; - } + return true; +} + +static void NativeHpFixEnsureWindow(bool show) +{ + if (!pSidlMgr || !pWndMgr) { + return; + } + + if (!gNativeHpFixWnd) { + if (!NativeHpFixClientFilesReady()) { + return; } - while (!encoded.empty() && encoded.back() == '_') { - encoded.pop_back(); + NativeAutoLootTrace("creating HPFIX window"); + NativeHpFixWnd* created_window = nullptr; + __try { + created_window = new NativeHpFixWnd(); + } __except(EXCEPTION_EXECUTE_HANDLER) { + NativeAutoLootTrace("HPFIX window construction faulted; check EQUI_NativeHpFixWnd.xml"); + created_window = nullptr; } - if (encoded.empty()) { - encoded = DefaultItemName(); - for (char& ch : encoded) { - if (ch == ' ') { - ch = '_'; - } - } + if (!created_window) { + return; } - return encoded; + gNativeHpFixWnd = created_window; + NativeAutoLootTrace("HPFIX window created"); } - void SelectType(int index) - { - TypeIndex = ClampInt(index, 0, 4); - SetEditText(DefaultItemName().c_str()); - SetStatus("Item form changed."); - UpdateView(); + if (show && gNativeHpFixWnd) { + gNativeHpFixWnd->Open(); } +} - void ShowPage(ItemPage page) - { - CurrentPage = page; - SetVisible(FormPage, CurrentPage == PageForm); - SetVisible(StatsPage, CurrentPage == PageStats); - SetVisible(CombatPage, CurrentPage == PageCombat); - SetVisible(ReviewPage, CurrentPage == PageReview); - UpdateView(); +static void NativeHpFixTryUpdatePlayerWindowLabel() +{ + if (!ppPlayerWnd || !pPlayerWnd || !gNativeHpFixState.has_payload) { + return; + } + + CXWnd* hp_label = nullptr; + __try { + hp_label = ((CXWnd*)pPlayerWnd)->GetChildItem("Player_HPLabel"); + } __except(EXCEPTION_EXECUTE_HANDLER) { + NativeAutoLootTrace("HPFIX could not query Player_HPLabel"); + hp_label = nullptr; } - void UpdateTabs() - { - SetButtonText(FormTab, CurrentPage == PageForm ? "> Form <" : "Form"); - SetButtonText(StatsTab, CurrentPage == PageStats ? "> Stats <" : "Stats"); - SetButtonText(CombatTab, CurrentPage == PageCombat ? "> Combat <" : "Combat"); - SetButtonText(ReviewTab, CurrentPage == PageReview ? "> Review <" : "Review"); + if (!hp_label) { + return; } - void UpdateView() - { - UpdateTabs(); - SetButtonText(WeaponButton, TypeIndex == 0 ? "* Weapon" : "Weapon"); - SetButtonText(ArmorButton, TypeIndex == 1 ? "* Armor" : "Armor"); - SetButtonText(JewelryButton, TypeIndex == 2 ? "* Jewelry" : "Jewelry"); - SetButtonText(CharmButton, TypeIndex == 3 ? "* Charm" : "Charm"); - SetButtonText(ShieldButton, TypeIndex == 4 ? "* Shield" : "Shield"); - SetLabel(TypeHintLabel, TypeHint()); + char text[128]; + sprintf_s( + text, + "%s / %s", + NativeHpFixFormatInteger(gNativeHpFixState.current).c_str(), + NativeHpFixFormatInteger(gNativeHpFixState.maximum).c_str() + ); + NativeHpFixSetLabel(hp_label, text); +} - char text[192]; - sprintf_s(text, "%d", HP); - SetLabel(HPValueLabel, text); - sprintf_s(text, "%d", Mana); - SetLabel(ManaValueLabel, text); - sprintf_s(text, "%d", AC); - SetLabel(ACValueLabel, text); - sprintf_s(text, "Stat ranges: HP 0-500, Mana 0-500, AC 0-100."); - SetLabel(StatsHintLabel, text); +static bool NativeHpFixApplyPayload(const std::string& payload) +{ + const long long current = NativeToInt64(NativeGetPairValue(payload, "current"), -1); + const long long maximum = NativeToInt64(NativeGetPairValue(payload, "max"), -1); + if (current < 0 || maximum <= 0) { + NativeAutoLootTrace("HPFIX ignored invalid payload: %s", payload.c_str()); + return true; + } - sprintf_s(text, "%d", UsesCombatValues() ? Damage : 0); - SetLabel(DamageValueLabel, text); - sprintf_s(text, "%d", UsesCombatValues() ? Delay : 0); - SetLabel(DelayValueLabel, text); - sprintf_s(text, "%d%%", UsesCombatValues() ? Haste : 0); - SetLabel(HasteValueLabel, text); - SetLabel(CombatHintLabel, UsesCombatValues() ? "Weapon values apply to blades. Other forms keep these at zero." : "This item form ignores weapon damage, delay, and haste."); + gNativeHpFixState.has_payload = true; + gNativeHpFixState.current = current; + gNativeHpFixState.maximum = maximum; + gNativeHpFixState.percent = NativeToFloat( + NativeGetPairValue(payload, "percent"), + maximum > 0 ? static_cast((static_cast(current) * 100.0) / static_cast(maximum)) : 0.0f + ); - const std::string name = ReadName(); - SetLabel(ReviewNameLabel, name.c_str()); - sprintf_s(text, "%s item, summoned directly to your cursor.", TypeLabel()); - SetLabel(ReviewTypeLabel, text); - sprintf_s(text, "HP %d, Mana %d, AC %d.", HP, Mana, AC); - SetLabel(ReviewStatsLabel, text); - sprintf_s(text, "Damage %d, Delay %d, Haste %d%%.", UsesCombatValues() ? Damage : 0, UsesCombatValues() ? Delay : 0, UsesCombatValues() ? Haste : 0); - SetLabel(ReviewCombatLabel, text); + NativeHpFixEnsureWindow(true); + if (gNativeHpFixWnd) { + gNativeHpFixWnd->SetStatus("Authoritative HP received."); + gNativeHpFixWnd->Refresh(); } - void CreateItem() - { - const std::string encoded_name = EncodeName(ReadName()); - char command[256]; - sprintf_s( - command, - "/say #itemforge craft type=%s hp=%d mana=%d ac=%d damage=%d delay=%d haste=%d name=%s", - TypeKey(), - HP, - Mana, - AC, - UsesCombatValues() ? Damage : 0, - UsesCombatValues() ? Delay : 24, - UsesCombatValues() ? Haste : 0, - encoded_name.c_str() - ); + NativeHpFixTryUpdatePlayerWindowLabel(); + NativeAutoLootTrace( + "HPFIX update current=%lld maximum=%lld percent=%.2f", + gNativeHpFixState.current, + gNativeHpFixState.maximum, + gNativeHpFixState.percent + ); + return true; +} - NativeAutoLootSendCommand(command); - SetStatus("Creating item. Watch chat and your cursor."); +static bool NativeUIShowcaseClientFilesReady() +{ + char xml_path[MAX_PATH]; + char equi_path[MAX_PATH]; + if (gszEQPath[0]) { + sprintf_s(xml_path, "%s\\uifiles\\default\\EQUI_NativeUIShowcaseWnd.xml", gszEQPath); + sprintf_s(equi_path, "%s\\uifiles\\default\\EQUI.xml", gszEQPath); + } + else { + strcpy_s(xml_path, "uifiles\\default\\EQUI_NativeUIShowcaseWnd.xml"); + strcpy_s(equi_path, "uifiles\\default\\EQUI.xml"); } - ItemPage CurrentPage = PageForm; - int TypeIndex = 0; - int HP = 50; - int Mana = 25; - int AC = 5; - int Damage = 8; - int Delay = 24; - int Haste = 0; + if (!NativeUIShowcaseFileExists(xml_path)) { + NativeAutoLootTrace("UI showcase XML missing: %s", xml_path); + return false; + } - CButtonWnd* FormTab = nullptr; - CButtonWnd* StatsTab = nullptr; - CButtonWnd* CombatTab = nullptr; - CButtonWnd* ReviewTab = nullptr; - CXWnd* FormPage = nullptr; - CXWnd* StatsPage = nullptr; - CXWnd* CombatPage = nullptr; - CXWnd* ReviewPage = nullptr; - CEditWnd* NameEdit = nullptr; - CButtonWnd* WeaponButton = nullptr; - CButtonWnd* ArmorButton = nullptr; - CButtonWnd* JewelryButton = nullptr; - CButtonWnd* CharmButton = nullptr; - CButtonWnd* ShieldButton = nullptr; - CXWnd* TypeHintLabel = nullptr; - CButtonWnd* HPMinusButton = nullptr; - CButtonWnd* HPPlusButton = nullptr; - CXWnd* HPValueLabel = nullptr; - CButtonWnd* ManaMinusButton = nullptr; - CButtonWnd* ManaPlusButton = nullptr; - CXWnd* ManaValueLabel = nullptr; - CButtonWnd* ACMinusButton = nullptr; - CButtonWnd* ACPlusButton = nullptr; - CXWnd* ACValueLabel = nullptr; - CXWnd* StatsHintLabel = nullptr; - CButtonWnd* DamageMinusButton = nullptr; - CButtonWnd* DamagePlusButton = nullptr; - CXWnd* DamageValueLabel = nullptr; - CButtonWnd* DelayMinusButton = nullptr; - CButtonWnd* DelayPlusButton = nullptr; - CXWnd* DelayValueLabel = nullptr; - CButtonWnd* HasteMinusButton = nullptr; - CButtonWnd* HastePlusButton = nullptr; - CXWnd* HasteValueLabel = nullptr; - CXWnd* CombatHintLabel = nullptr; - CXWnd* ReviewNameLabel = nullptr; - CXWnd* ReviewTypeLabel = nullptr; - CXWnd* ReviewStatsLabel = nullptr; - CXWnd* ReviewCombatLabel = nullptr; - CButtonWnd* CreateButton = nullptr; - CXWnd* StatusLabel = nullptr; -}; + if (!NativeUIShowcaseFileContains(equi_path, "EQUI_NativeUIShowcaseWnd.xml")) { + NativeAutoLootTrace("UI showcase XML is not included by EQUI.xml: %s", equi_path); + return false; + } -static NativeItemForgeWnd* gNativeItemForgeWnd = nullptr; + return true; +} -static void NativeItemForgeShowWindow(const std::string& payload) +static void NativeUIShowcaseEnsureWindow(bool show) { - if (!gNativeItemForgeWnd) { - NativeAutoLootTrace("creating item forge window"); - gNativeItemForgeWnd = new NativeItemForgeWnd(); + if (!pSidlMgr || !pWndMgr) { + return; } - gNativeItemForgeWnd->Open(payload); + if (!gNativeUIShowcaseWnd) { + if (!NativeUIShowcaseClientFilesReady()) { + NativeAutoLootTrace("UI showcase window not created because client files are incomplete"); + return; + } + + NativeAutoLootTrace("creating UI showcase window"); + NativeUIShowcaseWnd* created_window = nullptr; + __try { + created_window = new NativeUIShowcaseWnd(); + } __except(EXCEPTION_EXECUTE_HANDLER) { + NativeAutoLootTrace("UI showcase window construction faulted; check EQUI_NativeUIShowcaseWnd.xml"); + created_window = nullptr; + } + + if (!created_window) { + return; + } + + gNativeUIShowcaseWnd = created_window; + NativeAutoLootTrace("UI showcase window created"); + } + + if (show && gNativeUIShowcaseWnd) { + gNativeUIShowcaseWnd->Open(); + } } void NativeAchievementWnd::RefreshCategoryList() @@ -2289,25 +5126,250 @@ static bool NativeCommandMatch(const char* line, const char* command, const char return false; } - const size_t command_length = strlen(command); - if (strnicmp(line, command, command_length) != 0) { - return false; + const size_t command_length = strlen(command); + if (strnicmp(line, command, command_length) != 0) { + return false; + } + + const char next = line[command_length]; + if (next != 0 && next != ' ' && next != '\t') { + return false; + } + + if (arguments) { + const char* current = line + command_length; + while (*current == ' ' || *current == '\t') { + ++current; + } + *arguments = current; + } + + return true; +} + +static bool NativeUIShowcaseHandleCommand(const char* line) +{ + if (!line) { + return false; + } + + while (*line == ' ' || *line == '\t') { + ++line; + } + + const char* arguments = nullptr; + if ( + !NativeCommandMatch(line, "/nativeui", &arguments) && + !NativeCommandMatch(line, "/uishowcase", &arguments) && + !NativeCommandMatch(line, "/showcase", &arguments) + ) { + return false; + } + + if (arguments && NativeCommandMatch(arguments, "close", nullptr)) { + if (gNativeUIShowcaseWnd) { + gNativeUIShowcaseWnd->pXWnd()->Show(0, 1); + } + return true; + } + + NativeUIShowcaseEnsureWindow(true); + if (gNativeUIShowcaseWnd) { + if (arguments && NativeCommandMatch(arguments, "reset", nullptr)) { + gNativeUIShowcaseWnd->ResetDemo(); + gNativeUIShowcaseWnd->SetStatus("Showcase opened and reset."); + } + } + + return true; +} + +static bool NativeMulticlassRewriteCommand(const char* line, char* output, size_t output_size) +{ + if (!line || !output || !output_size) { + return false; + } + + while (*line == ' ' || *line == '\t') { + ++line; + } + + const char* arguments = nullptr; + if ( + NativeCommandMatch(line, "/mc", &arguments) || + NativeCommandMatch(line, "/multiclass", &arguments) || + NativeCommandMatch(line, "/multiclassui", &arguments) + ) { + if (!arguments || !arguments[0]) { + strcpy_s(output, output_size, "/say #mc open"); + return true; + } + + if ( + NativeCommandMatch(arguments, "open", nullptr) || + NativeCommandMatch(arguments, "window", nullptr) || + NativeCommandMatch(arguments, "ui", nullptr) || + NativeCommandMatch(arguments, "panel", nullptr) + ) { + strcpy_s(output, output_size, "/say #mc open"); + return true; + } + + if ( + NativeCommandMatch(arguments, "refresh", nullptr) || + NativeCommandMatch(arguments, "status", nullptr) + ) { + strcpy_s(output, output_size, "/say #mc refresh"); + return true; + } + + if ( + NativeCommandMatch(arguments, "pets", nullptr) || + NativeCommandMatch(arguments, "petui", nullptr) || + NativeCommandMatch(arguments, "petwindow", nullptr) + ) { + strcpy_s(output, output_size, "/say #mc pets"); + return true; + } + + const char* disc_arguments = nullptr; + if ( + NativeCommandMatch(arguments, "disc", &disc_arguments) || + NativeCommandMatch(arguments, "discs", &disc_arguments) || + NativeCommandMatch(arguments, "discipline", &disc_arguments) || + NativeCommandMatch(arguments, "disciplines", &disc_arguments) + ) { + if (!disc_arguments || !disc_arguments[0]) { + strcpy_s(output, output_size, "/say #mc disc open"); + } + else { + sprintf_s(output, output_size, "/say #mc disc %s", disc_arguments); + } + return true; + } + + const char* melody_arguments = nullptr; + if ( + NativeCommandMatch(arguments, "melody", &melody_arguments) || + NativeCommandMatch(arguments, "bardmelody", &melody_arguments) || + NativeCommandMatch(arguments, "songui", &melody_arguments) + ) { + if (!melody_arguments || !melody_arguments[0]) { + strcpy_s(output, output_size, "/say #mc melody open"); + } + else { + sprintf_s(output, output_size, "/say #mc melody %s", melody_arguments); + } + return true; + } + + sprintf_s(output, output_size, "/say #mc %s", arguments); + return true; + } + + if ( + NativeCommandMatch(line, "/mcpets", &arguments) || + NativeCommandMatch(line, "/multiclasspets", &arguments) || + NativeCommandMatch(line, "/petui", &arguments) + ) { + if (!arguments || !arguments[0]) { + strcpy_s(output, output_size, "/say #mc pets"); + return true; + } + + if ( + NativeCommandMatch(arguments, "open", nullptr) || + NativeCommandMatch(arguments, "window", nullptr) || + NativeCommandMatch(arguments, "ui", nullptr) || + NativeCommandMatch(arguments, "panel", nullptr) + ) { + strcpy_s(output, output_size, "/say #mc pets"); + return true; + } + + if ( + NativeCommandMatch(arguments, "refresh", nullptr) || + NativeCommandMatch(arguments, "status", nullptr) + ) { + strcpy_s(output, output_size, "/say #mc pet refresh"); + return true; + } + + sprintf_s(output, output_size, "/say #mc pet %s", arguments); + return true; + } + + if ( + NativeCommandMatch(line, "/disc", &arguments) || + NativeCommandMatch(line, "/discs", &arguments) || + NativeCommandMatch(line, "/discipline", &arguments) || + NativeCommandMatch(line, "/disciplines", &arguments) || + NativeCommandMatch(line, "/discwindow", &arguments) || + NativeCommandMatch(line, "/combatability", &arguments) || + NativeCommandMatch(line, "/combatabilities", &arguments) || + NativeCommandMatch(line, "/combatdisc", &arguments) + ) { + if (!arguments || !arguments[0]) { + strcpy_s(output, output_size, "/say #mc disc open"); + return true; + } + + if ( + NativeCommandMatch(arguments, "open", nullptr) || + NativeCommandMatch(arguments, "window", nullptr) || + NativeCommandMatch(arguments, "ui", nullptr) || + NativeCommandMatch(arguments, "panel", nullptr) || + NativeCommandMatch(arguments, "list", nullptr) + ) { + strcpy_s(output, output_size, "/say #mc disc open"); + return true; + } + + if ( + NativeCommandMatch(arguments, "refresh", nullptr) || + NativeCommandMatch(arguments, "status", nullptr) + ) { + strcpy_s(output, output_size, "/say #mc disc refresh"); + return true; + } + + sprintf_s(output, output_size, "/say #mc disc %s", arguments); + return true; } - const char next = line[command_length]; - if (next != 0 && next != ' ' && next != '\t') { - return false; - } + if ( + NativeCommandMatch(line, "/mcmelody", &arguments) || + NativeCommandMatch(line, "/multiclassmelody", &arguments) || + NativeCommandMatch(line, "/melodyui", &arguments) + ) { + if (!arguments || !arguments[0]) { + strcpy_s(output, output_size, "/say #mc melody open"); + return true; + } - if (arguments) { - const char* current = line + command_length; - while (*current == ' ' || *current == '\t') { - ++current; + if ( + NativeCommandMatch(arguments, "open", nullptr) || + NativeCommandMatch(arguments, "window", nullptr) || + NativeCommandMatch(arguments, "ui", nullptr) || + NativeCommandMatch(arguments, "panel", nullptr) + ) { + strcpy_s(output, output_size, "/say #mc melody open"); + return true; } - *arguments = current; + + if ( + NativeCommandMatch(arguments, "refresh", nullptr) || + NativeCommandMatch(arguments, "status", nullptr) + ) { + strcpy_s(output, output_size, "/say #mc melody refresh"); + return true; + } + + sprintf_s(output, output_size, "/say #mc melody %s", arguments); + return true; } - return true; + return false; } static bool NativeAchievementRewriteCommand(const char* line, char* output, size_t output_size) @@ -2356,7 +5418,20 @@ class NativeAutoLootCommandHook VOID Trampoline(EQPlayer* player, PCHAR line); VOID Detour(EQPlayer* player, PCHAR line) { + if (NativeUIShowcaseHandleCommand(line)) { + NativeAutoLootTrace("handled local UI showcase command: %s", line ? line : ""); + return; + } + char rewritten[256]; + + + if (NativeMulticlassRewriteCommand(line, rewritten, sizeof(rewritten))) { + NativeAutoLootTrace("rewrite command: %s -> %s", line ? line : "", rewritten); + Trampoline(player, rewritten); + return; + } + if (NativeAchievementRewriteCommand(line, rewritten, sizeof(rewritten))) { NativeAutoLootTrace("rewrite command: %s -> %s", line ? line : "", rewritten); Trampoline(player, rewritten); @@ -2471,6 +5546,351 @@ static bool NativeApplyLiveSpellPatch(const std::string& payload) return true; } +static bool NativeMulticlassParseTransport(const char* message) +{ + if (!message || !message[0] || !NativeStartsWith(message, "MULTICLASS|")) { + return false; + } + + if (NativeStartsWith(message, "MULTICLASS|window|clear")) { + gNativeMulticlassPets.clear(); + gNativeMulticlassMelodySlots.clear(); + gNativeMulticlassMelodySongs.clear(); + gNativeMulticlassDisciplineRows.clear(); + gNativeMulticlassState.selection_status = "Refreshing Multiclass profile..."; + gNativeMulticlassState.skill_summary = "Skills: refreshing..."; + gNativeMulticlassState.bonus_summary = "Resonance bonuses: refreshing..."; + gNativeMulticlassState.melody_status = "Bard Melody: refreshing..."; + gNativeMulticlassState.discipline_status = "Disciplines: refreshing..."; + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|profile|")) { + const std::string payload(message + strlen("MULTICLASS|profile|")); + gNativeMulticlassState.has_profile = true; + gNativeMulticlassState.profile_name = NativeGetPairValue(payload, "name"); + gNativeMulticlassState.resonance_key = NativeGetPairValue(payload, "resonance"); + gNativeMulticlassState.class1 = NativeToInt(NativeGetPairValue(payload, "class1")); + gNativeMulticlassState.class2 = NativeToInt(NativeGetPairValue(payload, "class2")); + gNativeMulticlassState.class3 = NativeToInt(NativeGetPairValue(payload, "class3")); + gNativeMulticlassState.presentation = NativeToInt(NativeGetPairValue(payload, "presentation")); + gNativeMulticlassState.base = NativeToInt(NativeGetPairValue(payload, "base")); + gNativeMulticlassState.multiple_pets = NativeToBool(NativeGetPairValue(payload, "pets")); + gNativeMulticlassState.locked = NativeToBool(NativeGetPairValue(payload, "locked")); + gNativeMulticlassState.reweaves = NativeToInt(NativeGetPairValue(payload, "reweaves")); + gNativeMulticlassState.class1_name = NativeGetPairValue(payload, "class1_name"); + gNativeMulticlassState.class2_name = NativeGetPairValue(payload, "class2_name"); + gNativeMulticlassState.class3_name = NativeGetPairValue(payload, "class3_name"); + gNativeMulticlassState.presentation_name = NativeGetPairValue(payload, "presentation_name"); + gNativeMulticlassState.base_name = NativeGetPairValue(payload, "base_name"); + + if (gNativeMulticlassState.profile_name.empty()) { + gNativeMulticlassState.profile_name = "Multiclass Trio"; + } + if (gNativeMulticlassState.class1_name.empty()) { + gNativeMulticlassState.class1_name = NativeMulticlassClassName(gNativeMulticlassState.class1); + } + if (gNativeMulticlassState.class2_name.empty()) { + gNativeMulticlassState.class2_name = NativeMulticlassClassName(gNativeMulticlassState.class2); + } + if (gNativeMulticlassState.class3_name.empty()) { + gNativeMulticlassState.class3_name = NativeMulticlassClassName(gNativeMulticlassState.class3); + } + if (gNativeMulticlassState.presentation_name.empty()) { + gNativeMulticlassState.presentation_name = NativeMulticlassClassName(gNativeMulticlassState.presentation); + } + if (gNativeMulticlassState.base_name.empty()) { + gNativeMulticlassState.base_name = NativeMulticlassClassName(gNativeMulticlassState.base); + } + + if (NativeMulticlassIsPlayerClass(gNativeMulticlassState.class2)) { + gNativeMulticlassState.selected_slot2 = gNativeMulticlassState.class2; + } + if (NativeMulticlassIsPlayerClass(gNativeMulticlassState.class3)) { + gNativeMulticlassState.selected_slot3 = gNativeMulticlassState.class3; + } + + NativeMulticlassNormalizeSelections(); + NativeMulticlassScheduleCasterUI(); + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|vitals|")) { + const std::string payload(message + strlen("MULTICLASS|vitals|")); + gNativeMulticlassState.mana = NativeToInt(NativeGetPairValue(payload, "mana")); + gNativeMulticlassState.max_mana = NativeToInt(NativeGetPairValue(payload, "max_mana")); + gNativeMulticlassState.endurance = NativeToInt(NativeGetPairValue(payload, "endurance")); + gNativeMulticlassState.max_endurance = NativeToInt(NativeGetPairValue(payload, "max_endurance")); + gNativeMulticlassState.class_mask = NativeToInt(NativeGetPairValue(payload, "class_mask")); + gNativeMulticlassState.aa_mask = NativeToInt(NativeGetPairValue(payload, "aa_mask")); + const int presentation = NativeToInt(NativeGetPairValue(payload, "presentation")); + const int base = NativeToInt(NativeGetPairValue(payload, "base")); + if (NativeMulticlassIsPlayerClass(presentation)) { + gNativeMulticlassState.presentation = presentation; + gNativeMulticlassState.presentation_name = NativeMulticlassClassName(presentation); + } + if (NativeMulticlassIsPlayerClass(base)) { + gNativeMulticlassState.base = base; + gNativeMulticlassState.base_name = NativeMulticlassClassName(base); + } + NativeMulticlassScheduleCasterUI(); + NativeMulticlassPatchLocalVitals(); + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|trio|")) { + const std::string payload(message + strlen("MULTICLASS|trio|")); + gNativeMulticlassState.roles = NativeGetPairValue(payload, "roles"); + gNativeMulticlassState.resonance = NativeGetPairValue(payload, "resonance"); + gNativeMulticlassState.summary = NativeGetPairValue(payload, "summary"); + if (gNativeMulticlassState.roles.empty()) { + gNativeMulticlassState.roles = "-"; + } + if (gNativeMulticlassState.resonance.empty()) { + gNativeMulticlassState.resonance = "Trio Notes"; + } + if (gNativeMulticlassState.summary.empty()) { + gNativeMulticlassState.summary = "Fixed trio identity."; + } + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|skills|")) { + const std::string payload(message + strlen("MULTICLASS|skills|")); + gNativeMulticlassState.skill_summary = NativeGetPairValue(payload, "summary"); + if (gNativeMulticlassState.skill_summary.empty()) { + gNativeMulticlassState.skill_summary = "Skills: waiting for profile."; + } + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|bonuses|")) { + const std::string payload(message + strlen("MULTICLASS|bonuses|")); + gNativeMulticlassState.bonus_summary = NativeGetPairValue(payload, "summary"); + if (gNativeMulticlassState.bonus_summary.empty()) { + gNativeMulticlassState.bonus_summary = "Resonance bonuses: waiting for profile."; + } + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|selection|")) { + const std::string payload(message + strlen("MULTICLASS|selection|")); + gNativeMulticlassState.can_choose = NativeToBool(NativeGetPairValue(payload, "can_choose")); + gNativeMulticlassState.selection_status = NativeGetPairValue(payload, "status"); + if (gNativeMulticlassState.selection_status.empty()) { + gNativeMulticlassState.selection_status = gNativeMulticlassState.locked ? "Trio locked." : "Choose two added classes."; + } + NativeMulticlassNormalizeSelections(); + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|spell_levels|begin")) { + gNativeMulticlassSpellLevelsLoading = true; + gNativeMulticlassSpellLevelPatchCount = 0; + gNativeMulticlassSpellLevelsById.clear(); + gNativeMulticlassSpellLevelsByName.clear(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|spell_level|")) { + return NativeMulticlassApplySpellLevelPatch(std::string(message + strlen("MULTICLASS|spell_level|"))); + } + + if (NativeStartsWith(message, "MULTICLASS|spell_levels|end")) { + const std::string payload(message + strlen("MULTICLASS|spell_levels|end")); + const int expected_count = NativeToInt(NativeGetPairValue(payload, "count"), gNativeMulticlassSpellLevelPatchCount); + gNativeMulticlassSpellLevelsLoading = false; + NativeAutoLootTrace("Multiclass spellbook levels patched: %d/%d", gNativeMulticlassSpellLevelPatchCount, expected_count); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|pet_roster|")) { + const std::string payload(message + strlen("MULTICLASS|pet_roster|")); + gNativeMulticlassPets.clear(); + gNativeMulticlassState.roster_count = NativeToInt(NativeGetPairValue(payload, "count")); + gNativeMulticlassState.roster_limit = NativeToInt(NativeGetPairValue(payload, "limit"), 1); + gNativeMulticlassState.focus_id = NativeToInt(NativeGetPairValue(payload, "focus")); + gNativeMulticlassState.pet_policy = NativeGetPairValue(payload, "policy"); + gNativeMulticlassState.pet_control = NativeGetPairValue(payload, "control"); + if (gNativeMulticlassState.pet_policy.empty()) { + gNativeMulticlassState.pet_policy = "single-pet"; + } + if (gNativeMulticlassState.pet_control.empty()) { + gNativeMulticlassState.pet_control = "Attack/Back/Follow/Guard affect all pets; toggles affect focus."; + } + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|pet|")) { + const std::string payload(message + strlen("MULTICLASS|pet|")); + NativeMulticlassPetRow row; + row.id = NativeToInt(NativeGetPairValue(payload, "id")); + row.name = NativeGetPairValue(payload, "name"); + row.hp = NativeToInt(NativeGetPairValue(payload, "hp")); + row.mana = NativeToInt(NativeGetPairValue(payload, "mana")); + row.target = NativeGetPairValue(payload, "target"); + row.taunt = NativeToBool(NativeGetPairValue(payload, "taunt")); + row.hold = NativeToBool(NativeGetPairValue(payload, "hold")); + row.spellhold = NativeToBool(NativeGetPairValue(payload, "spellhold")); + row.order = NativeGetPairValue(payload, "order"); + row.focused = NativeToBool(NativeGetPairValue(payload, "focused")); + if (row.name.empty()) { + row.name = "Pet"; + } + if (row.target.empty()) { + row.target = "-"; + } + if (row.order.empty()) { + row.order = "follow"; + } + if (row.focused) { + gNativeMulticlassState.focus_id = row.id; + } + if (row.id > 0) { + gNativeMulticlassPets.push_back(row); + } + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|melody|")) { + const std::string payload(message + strlen("MULTICLASS|melody|")); + gNativeMulticlassState.has_bard = NativeToBool(NativeGetPairValue(payload, "has_bard")); + gNativeMulticlassState.melody_status = NativeGetPairValue(payload, "status"); + if (gNativeMulticlassState.melody_status.empty()) { + gNativeMulticlassState.melody_status = gNativeMulticlassState.has_bard ? "Bard Melody: ready." : "Bard Melody: Bard not in trio."; + } + gNativeMulticlassMelodySlots.clear(); + gNativeMulticlassMelodySongs.clear(); + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|melody_slot|")) { + const std::string payload(message + strlen("MULTICLASS|melody_slot|")); + NativeMulticlassMelodySlot row; + row.slot = NativeToInt(NativeGetPairValue(payload, "slot")); + row.spell_id = NativeToInt(NativeGetPairValue(payload, "id")); + row.name = NativeGetPairValue(payload, "name"); + row.level = NativeToInt(NativeGetPairValue(payload, "level")); + row.state = NativeGetPairValue(payload, "state"); + if (row.name.empty()) { + row.name = "-"; + } + if (row.state.empty()) { + row.state = row.spell_id > 0 ? "selected" : "empty"; + } + if (row.slot >= 1 && row.slot <= 4) { + gNativeMulticlassMelodySlots.push_back(row); + } + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|melody_song|")) { + const std::string payload(message + strlen("MULTICLASS|melody_song|")); + NativeMulticlassMelodySong row; + row.spell_id = NativeToInt(NativeGetPairValue(payload, "id")); + row.name = NativeGetPairValue(payload, "name"); + row.level = NativeToInt(NativeGetPairValue(payload, "level")); + row.allowed = NativeToBool(NativeGetPairValue(payload, "allowed")); + row.reason = NativeGetPairValue(payload, "reason"); + if (row.name.empty()) { + row.name = "Song"; + } + if (row.spell_id > 0) { + gNativeMulticlassMelodySongs.push_back(row); + } + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|melody_songs|end")) { + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|disciplines|clear")) { + gNativeMulticlassDisciplineRows.clear(); + gNativeMulticlassState.discipline_status = "Disciplines: refreshing..."; + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|disciplines|summary|")) { + const std::string payload(message + strlen("MULTICLASS|disciplines|summary|")); + gNativeMulticlassState.discipline_status = NativeGetPairValue(payload, "status"); + if (gNativeMulticlassState.discipline_status.empty()) { + gNativeMulticlassState.discipline_status = "Disciplines: ready."; + } + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|discipline|")) { + const std::string payload(message + strlen("MULTICLASS|discipline|")); + NativeMulticlassDisciplineRow row; + row.slot = NativeToInt(NativeGetPairValue(payload, "slot")); + row.spell_id = NativeToInt(NativeGetPairValue(payload, "id")); + row.name = NativeGetPairValue(payload, "name"); + row.level = NativeToInt(NativeGetPairValue(payload, "level")); + row.timer = NativeToInt(NativeGetPairValue(payload, "timer")); + row.timer_total = NativeToInt(NativeGetPairValue(payload, "total")); + if (row.timer_total <= 0) { + row.timer_total = row.timer; + } + row.timer_received_ms = GetTickCount(); + row.ready = NativeToBool(NativeGetPairValue(payload, "ready")); + row.state = NativeGetPairValue(payload, "state"); + if (row.name.empty()) { + row.name = "Discipline"; + } + if (row.state.empty()) { + row.state = row.ready ? "Ready" : "Blocked"; + } + if (row.spell_id > 0) { + gNativeMulticlassDisciplineRows.push_back(row); + } + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|disciplines|end")) { + NativeMulticlassRefreshWindows(); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|window|show")) { + NativeMulticlassEnsureWindow(true); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|pet_window|show")) { + NativeMulticlassEnsurePetWindow(true); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|melody_window|show")) { + NativeMulticlassEnsureMelodyWindow(true); + return true; + } + + if (NativeStartsWith(message, "MULTICLASS|discipline_window|show")) { + NativeMulticlassEnsureDisciplineWindow(true); + return true; + } + + return true; +} + static bool NativeAchievementParseTransport(const char* message) { if (!message || !message[0] || !NativeStartsWith(message, "ACH|")) { @@ -2636,10 +6056,47 @@ static bool NativeAutoLootParseTransport(const char* message) return false; } + if (NativeStartsWith(message, "SHOWCASE|window|show")) { + NativeUIShowcaseEnsureWindow(true); + return true; + } + + if (NativeStartsWith(message, "SHOWCASE|")) { + return true; + } + if (NativeAchievementParseTransport(message)) { return true; } + if (NativeMulticlassParseTransport(message)) { + return true; + } + + if (NativeStartsWith(message, "HPFIX|self|")) { + return NativeHpFixApplyPayload(std::string(message + strlen("HPFIX|self|"))); + } + + if (NativeStartsWith(message, "HPFIX|window|show")) { + NativeHpFixEnsureWindow(true); + if (gNativeHpFixWnd) { + gNativeHpFixWnd->SetStatus("HPFIX window opened."); + } + return true; + } + + if (NativeStartsWith(message, "HPFIX|")) { + return true; + } + + if (NativeItemPowerParseTransport(message)) { + return true; + } + + if (NativeItemRarityParseTransport(message)) { + return true; + } + if (NativeStartsWith(message, "LIVESPELL|upsert|")) { return NativeApplyLiveSpellPatch(std::string(message + strlen("LIVESPELL|upsert|"))); } @@ -2806,7 +6263,7 @@ static bool NativeAutoLootParseTransport(const char* message) return true; } - if (strstr(message, "You say, '#autoloot") || strstr(message, "You say, '#lootfilter") || strstr(message, "You say, '#livespell") || strstr(message, "You say, '#itemforge") || strstr(message, "You say, '#ach")) { + if (strstr(message, "You say, '#autoloot") || strstr(message, "You say, '#lootfilter") || strstr(message, "You say, '#livespell") || strstr(message, "You say, '#itemforge") || strstr(message, "You say, '#ach") || strstr(message, "You say, '#mc") || strstr(message, "You say, '#multiclass") || strstr(message, "You say, '#nativeui") || strstr(message, "You say, '#showcase") || strstr(message, "You say, '#hpfix")) { return true; } @@ -2863,6 +6320,31 @@ static void NativeAutoLootResetSessionRequests() gNativeAutoLootInGamePulses = 0; gNativeAutoLootRequestedInitialStatus = false; gNativeLiveSpellSentReady = false; + gNativeHpFixSentReady = false; + gNativeHpFixState = NativeHpFixState(); + gNativeItemPowerById.clear(); + gNativeItemRarityById.clear(); + gNativeMulticlassSentStatus = false; + NativeMulticlassResetSessionState(true); +} + +static void NativeAutoLootResetClientUiSession(const char* reason) +{ + NativeAutoLootTrace("client UI reset: %s", reason ? reason : "unknown"); + if (gNativeHpFixWnd) { + delete gNativeHpFixWnd; + gNativeHpFixWnd = nullptr; + } + NativeMulticlassDestroyRuntimeWindows(); + gNativeAutoLootInGamePulses = 0; + gNativeAutoLootRequestedInitialStatus = false; + gNativeLiveSpellSentReady = false; + gNativeHpFixSentReady = false; + gNativeHpFixState = NativeHpFixState(); + gNativeItemPowerById.clear(); + gNativeItemRarityById.clear(); + gNativeMulticlassSentStatus = false; + NativeMulticlassResetSessionState(false); } static void NativeAutoLootMaybeSendInitialRequests() @@ -2882,16 +6364,27 @@ static void NativeAutoLootMaybeSendInitialRequests() gNativeLiveSpellSentReady = true; NativeAutoLootSendCommand("/say #livespell ready"); } + + if (!gNativeHpFixSentReady) { + gNativeHpFixSentReady = true; + NativeAutoLootSendCommand("/say #hpfix native ready"); + } + + if (!gNativeMulticlassSentStatus) { + gNativeMulticlassSentStatus = true; + NativeAutoLootSendCommand("/say #mc status"); + } } static void NativeAutoLootPulse() { - if (!pSidlMgr || !pWndMgr) { + const DWORD state = GetGameState(); + if (state != GAMESTATE_INGAME) { + NativeAutoLootResetSessionRequests(); return; } - const DWORD state = GetGameState(); - if (state != GAMESTATE_INGAME) { + if (!pSidlMgr || !pWndMgr) { NativeAutoLootResetSessionRequests(); return; } @@ -2935,6 +6428,32 @@ static void NativeAutoLootPulse() gNativeAchievementWnd->Layout(); } + if (gNativeUIShowcaseWnd) { + gNativeUIShowcaseWnd->Layout(); + } + + if (gNativeHpFixWnd) { + gNativeHpFixWnd->Refresh(); + } + + if (gNativeMulticlassWnd) { + gNativeMulticlassWnd->Layout(); + } + + if (gNativeMulticlassPetWnd) { + gNativeMulticlassPetWnd->Layout(); + } + + if (gNativeMulticlassMelodyWnd) { + gNativeMulticlassMelodyWnd->Layout(); + } + + if (gNativeMulticlassDisciplineWnd) { + gNativeMulticlassDisciplineWnd->Layout(); + } + + NativeMulticlassMaintainPresentationUI(); + if (!gNativeAutoLootRequestedInitialStatus) { gNativeAutoLootRequestedInitialStatus = true; NativeAutoLootSendCommand("/say #autoloot native status"); @@ -2944,6 +6463,16 @@ static void NativeAutoLootPulse() gNativeLiveSpellSentReady = true; NativeAutoLootSendCommand("/say #livespell ready"); } + + if (!gNativeHpFixSentReady) { + gNativeHpFixSentReady = true; + NativeAutoLootSendCommand("/say #hpfix native ready"); + } + + if (!gNativeMulticlassSentStatus) { + gNativeMulticlassSentStatus = true; + NativeAutoLootSendCommand("/say #mc status"); + } } BOOL NativeAutoLoot_ProcessGameEvents_Trampoline(VOID); @@ -2965,6 +6494,44 @@ BOOL NativeAutoLoot_ProcessGameEvents_Detour(VOID) } DETOUR_TRAMPOLINE_EMPTY(BOOL NativeAutoLoot_ProcessGameEvents_Trampoline(VOID)); +class NativeAutoLootUiResetHook +{ +public: + VOID CleanUI_Trampoline(VOID); + VOID CleanUI_Detour(VOID) + { + NativeAutoLootResetClientUiSession("clean game UI"); + CleanUI_Trampoline(); + } + + VOID ReloadUI_Trampoline(BOOL use_ini); + VOID ReloadUI_Detour(BOOL use_ini) + { + NativeAutoLootResetClientUiSession("reload UI"); + ReloadUI_Trampoline(use_ini); + } +}; + +DETOUR_TRAMPOLINE_EMPTY(VOID NativeAutoLootUiResetHook::CleanUI_Trampoline(VOID)); +DETOUR_TRAMPOLINE_EMPTY(VOID NativeAutoLootUiResetHook::ReloadUI_Trampoline(BOOL)); + +static void NativeAutoLootInstallUiResetHook() +{ + if (gNativeAutoLootUiResetHookInstalled) { + return; + } + + if (isMQInjectsEnabled) { + NativeAutoLootTrace("native UI reset hook skipped because MQ display hook is enabled"); + return; + } + + NativeAutoLootTrace("installing native UI reset hook"); + EzDetour(CDisplay__CleanGameUI, &NativeAutoLootUiResetHook::CleanUI_Detour, &NativeAutoLootUiResetHook::CleanUI_Trampoline); + EzDetour(CDisplay__ReloadUI, &NativeAutoLootUiResetHook::ReloadUI_Detour, &NativeAutoLootUiResetHook::ReloadUI_Trampoline); + gNativeAutoLootUiResetHookInstalled = true; +} + static void InitAutoLootNative() { if (gNativeAutoLootHooksInstalled) { @@ -2974,6 +6541,8 @@ static void InitAutoLootNative() gNativeAutoLootHooksInstalled = true; NativeAutoLootInstallChatHook(); NativeAutoLootInstallCommandHook(); + NativeMulticlassInstallContextMenuHook(); + NativeAutoLootInstallUiResetHook(); if (!gNativeAutoLootPulseHookEnabled) { NativeAutoLootTrace("native pulse hook disabled"); @@ -3014,6 +6583,36 @@ static void ShutdownAutoLootNative() gNativeAchievementWnd = nullptr; } + if (gNativeUIShowcaseWnd) { + delete gNativeUIShowcaseWnd; + gNativeUIShowcaseWnd = nullptr; + } + + if (gNativeHpFixWnd) { + delete gNativeHpFixWnd; + gNativeHpFixWnd = nullptr; + } + + if (gNativeMulticlassWnd) { + delete gNativeMulticlassWnd; + gNativeMulticlassWnd = nullptr; + } + + if (gNativeMulticlassPetWnd) { + delete gNativeMulticlassPetWnd; + gNativeMulticlassPetWnd = nullptr; + } + + if (gNativeMulticlassMelodyWnd) { + delete gNativeMulticlassMelodyWnd; + gNativeMulticlassMelodyWnd = nullptr; + } + + if (gNativeMulticlassDisciplineWnd) { + delete gNativeMulticlassDisciplineWnd; + gNativeMulticlassDisciplineWnd = nullptr; + } + if (gNativeAutoLootChatHookInstalled) { RemoveDetour(CEverQuest__dsp_chat); gNativeAutoLootChatHookInstalled = false; @@ -3024,6 +6623,17 @@ static void ShutdownAutoLootNative() gNativeAutoLootCommandHookInstalled = false; } + if (gNativeMulticlassContextMenuHookInstalled) { + RemoveDetour(NativeMulticlassContextMenuAddMenuItemAddress()); + gNativeMulticlassContextMenuHookInstalled = false; + } + + if (gNativeAutoLootUiResetHookInstalled) { + RemoveDetour(CDisplay__CleanGameUI); + RemoveDetour(CDisplay__ReloadUI); + gNativeAutoLootUiResetHookInstalled = false; + } + if (gNativeAutoLootPulseHookInstalled) { RemoveDetour((DWORD)ProcessGameEvents); gNativeAutoLootPulseHookInstalled = false; @@ -3032,8 +6642,20 @@ static void ShutdownAutoLootNative() gNativeAutoLootHooksInstalled = false; gNativeAutoLootRequestedInitialStatus = false; gNativeLiveSpellSentReady = false; + gNativeHpFixSentReady = false; + gNativeHpFixState = NativeHpFixState(); + gNativeItemPowerById.clear(); + gNativeItemRarityById.clear(); + gNativeMulticlassSentStatus = false; gNativeAutoLootPulseFaulted = false; gNativeAutoLootInGamePulses = 0; + gNativeMulticlassPets.clear(); + gNativeMulticlassMelodySlots.clear(); + gNativeMulticlassMelodySongs.clear(); + gNativeMulticlassSpellLevelsById.clear(); + gNativeMulticlassSpellLevelsByName.clear(); + gNativeMulticlassSpellLevelPatchCount = 0; + gNativeMulticlassSpellLevelsLoading = false; } #endif diff --git a/zone/client.h b/zone/client.h index bb20ecc93f..5903e3b544 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1159,6 +1159,7 @@ class Client : public Mob void SendItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPacketType packet_type); bool RefreshLiveItem(EQ::ItemInstance* inst); bool RefreshLiveItemTree(EQ::ItemInstance* inst); + void SendItemPowerTransport(const EQ::ItemInstance* inst); bool IsValidSlot(uint32 slot); bool IsBankSlot(uint32 slot); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 85495a5677..7a97dceeb6 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -30,6 +30,7 @@ #include "zone/dynamic_zone.h" #include "zone/entity.h" #include "zone/groups.h" +#include "zone/item_rarity_manager.h" #include "zone/mob.h" #include "zone/queryserv.h" #include "zone/quest_parser_collection.h" @@ -316,7 +317,13 @@ CorpseAutoLootResult Corpse::AutoLootItem(Client *c, uint16 lootslot, bool send_ linker.GenerateLink(); if (send_messages) { + ItemRarity rarity = ItemRarity::Common; + if (ItemRarityManager::TryGetRarity(inst->GetItem()->ID, rarity)) { + ItemRarityManager::SendNativeRarity(c, inst->GetItem()->ID, rarity); + } + c->MessageString(Chat::Loot, LOOTED_MESSAGE, linker.Link().c_str()); + ItemRarityManager::SendLootedItemMessage(c, inst, linker.Link()); Group *g = c->GetGroup(); if (g) { @@ -2028,7 +2035,13 @@ void Corpse::LootCorpseItem(Client *c, const EQApplicationPacket *app) linker.GenerateLink(); + ItemRarity rarity = ItemRarity::Common; + if (ItemRarityManager::TryGetRarity(inst->GetItem()->ID, rarity)) { + ItemRarityManager::SendNativeRarity(c, inst->GetItem()->ID, rarity); + } + c->MessageString(Chat::Loot, LOOTED_MESSAGE, linker.Link().c_str()); + ItemRarityManager::SendLootedItemMessage(c, inst, linker.Link()); if (!IsPlayerCorpse()) { Group *g = c->GetGroup(); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index c761de261b..e97c8e5865 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -20,6 +20,7 @@ #include "common/eqemu_logsys.h" #include "common/events/player_event_logs.h" #include "common/evolving_items.h" +#include "common/item_power.h" #include "common/repositories/character_corpse_items_repository.h" #include "common/strings.h" #include "zone/bot.h" @@ -1586,6 +1587,25 @@ bool Client::RefreshLiveItemTree(EQ::ItemInstance* inst) return refreshed; } +void Client::SendItemPowerTransport(const EQ::ItemInstance* inst) +{ + if (!inst || !inst->GetItem()) { + return; + } + + std::string item_power_transport; + if (EQ::ItemPower::TryBuildTransportMessage(database, *inst->GetItem(), item_power_transport, true)) { + Message(Chat::White, "%s", item_power_transport.c_str()); + } + + for (uint16 bag_slot = EQ::invbag::SLOT_BEGIN; bag_slot < EQ::invbag::SLOT_COUNT; ++bag_slot) { + const auto *bag_inst = inst->GetItem(static_cast(bag_slot)); + if (bag_inst) { + SendItemPowerTransport(bag_inst); + } + } +} + bool Client::IsValidSlot(uint32 slot) { if (slot <= EQ::invslot::POSSESSIONS_END && slot >= EQ::invslot::POSSESSIONS_BEGIN) { return ((((uint64)1 << slot) & GetInv().GetLookup()->PossessionsBitmask) != 0); @@ -3042,6 +3062,7 @@ void Client::SendItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPac } RefreshLiveItemTree(const_cast(inst)); + SendItemPowerTransport(inst); // Serialize item into |-delimited string (Titanium- uses '|' delimiter .. newer clients use pure data serialization) std::string packet = inst->Serialize(slot_id); From 6072e50975701484814f8977c5688baa04dadd3a Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Tue, 2 Jun 2026 00:33:30 -0700 Subject: [PATCH 133/194] Checkpoint all features native client work --- client_files/export/main.cpp | 4 +- .../database_update_manifest_custom.h | 132 ++++++ common/repositories/skill_caps_repository.h | 31 ++ common/version.h | 2 +- zone/aa.cpp | 18 +- zone/attack.cpp | 84 ++-- zone/bonuses.cpp | 6 +- zone/client.cpp | 118 ++++-- zone/client.h | 1 + zone/client_mods.cpp | 9 +- zone/client_packet.cpp | 58 ++- zone/client_process.cpp | 46 ++- zone/effects.cpp | 58 +-- zone/exp.cpp | 2 + zone/groups.cpp | 18 + zone/guild_mgr.cpp | 12 +- zone/inventory.cpp | 113 ++++- zone/mob.cpp | 24 ++ zone/pets.cpp | 13 +- zone/raids.cpp | 11 + zone/special_attacks.cpp | 72 ++-- zone/spell_effects.cpp | 216 ++++++++-- zone/spells.cpp | 93 ++++- zone/worldserver.cpp | 130 +++--- zone/zonedb.cpp | 391 ++++++++++++++++++ zone/zonedb.h | 2 + 26 files changed, 1365 insertions(+), 299 deletions(-) diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index 952ba9dd37..87f29ea56d 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -152,7 +152,7 @@ void ExportSkillCaps(SharedDatabase* db) return; } - const auto& lines = SkillCapsRepository::GetSkillCapFileLines(*db); + const auto& lines = SkillCapsRepository::GetMulticlassSkillCapFileLines(*db); const std::string& file_string = Strings::Implode("\n", lines); @@ -160,7 +160,7 @@ void ExportSkillCaps(SharedDatabase* db) file.close(); - LogInfo("Exported [{}] Skill Cap{}", lines.size(), lines.size() != 1 ? "s" : ""); + LogInfo("Exported [{}] Multiclass Skill Cap{}", lines.size(), lines.size() != 1 ? "s" : ""); } void ExportBaseData(SharedDatabase *db) diff --git a/common/database/database_update_manifest_custom.h b/common/database/database_update_manifest_custom.h index 807a147926..84f025b2fe 100644 --- a/common/database/database_update_manifest_custom.h +++ b/common/database/database_update_manifest_custom.h @@ -2046,6 +2046,138 @@ ON DUPLICATE KEY UPDATE R"()", .content_schema_update = false, }, + ManifestEntry{ + .version = 5, + .description = "2026_06_01_gearscore_item_power", + .check = "SHOW TABLES LIKE 'item_power'", + .condition = "empty", + .match = "", + .sql = R"( +CREATE TABLE IF NOT EXISTS `item_power` ( + `item_id` INT UNSIGNED NOT NULL, + `item_level` SMALLINT UNSIGNED NOT NULL, + `item_score` INT UNSIGNED NOT NULL, + `tank_score` INT UNSIGNED NOT NULL DEFAULT 0, + `melee_score` INT UNSIGNED NOT NULL DEFAULT 0, + `caster_score` INT UNSIGNED NOT NULL DEFAULT 0, + `healer_score` INT UNSIGNED NOT NULL DEFAULT 0, + `hybrid_score` INT UNSIGNED NOT NULL DEFAULT 0, + `score_version` SMALLINT UNSIGNED NOT NULL, + `source` ENUM('computed', 'manual', 'generated') NOT NULL DEFAULT 'computed', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`item_id`), + INDEX `idx_item_power_level` (`item_level`), + INDEX `idx_item_power_score_version` (`score_version`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `item_power_override` ( + `item_id` INT UNSIGNED NOT NULL PRIMARY KEY, + `item_level_override` SMALLINT UNSIGNED NULL, + `score_multiplier` FLOAT NULL, + `flat_score_bonus` INT NULL, + `notes` TEXT NULL, + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE IF NOT EXISTS `item_power_breakdown` ( + `item_id` INT UNSIGNED NOT NULL, + `score_version` SMALLINT UNSIGNED NOT NULL, + `component` VARCHAR(64) NOT NULL, + `score` INT NOT NULL, + `details` TEXT NULL, + PRIMARY KEY (`item_id`, `score_version`, `component`), + INDEX `idx_item_power_breakdown_version` (`score_version`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +)", + .content_schema_update = false, + }, + ManifestEntry{ + .version = 6, + .description = "2026_06_01_item_rarity", + .check = "SHOW TABLES LIKE 'item_rarity'", + .condition = "empty", + .match = "", + .sql = R"( +CREATE TABLE IF NOT EXISTS `item_rarity` ( + `item_id` INT UNSIGNED NOT NULL, + `rarity` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`item_id`), + CONSTRAINT `item_rarity_rarity_chk` CHECK (`rarity` BETWEEN 0 AND 4) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +)", + .content_schema_update = false, + }, + ManifestEntry{ + .version = 7, + .description = "2026_05_26_custom_multiclass_schema", + .check = "SHOW TABLES LIKE 'custom_multiclass_profiles'", + .condition = "empty", + .match = "", + .sql = R"( +CREATE TABLE IF NOT EXISTS `custom_multiclass_profiles` ( + `character_id` INT UNSIGNED NOT NULL, + `class_slot_1` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `class_slot_2` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `class_slot_3` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `trio_name` VARCHAR(96) NOT NULL DEFAULT '', + `resonance_key` VARCHAR(64) NOT NULL DEFAULT '', + `multiple_pets_enabled` TINYINT(1) NOT NULL DEFAULT 1, + `locked` TINYINT(1) NOT NULL DEFAULT 0, + `reweaves_available` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `created_at` INT UNSIGNED NOT NULL DEFAULT 0, + `updated_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`), + KEY `idx_slot_1` (`class_slot_1`), + KEY `idx_slot_2` (`class_slot_2`), + KEY `idx_slot_3` (`class_slot_3`), + KEY `idx_resonance` (`resonance_key`) +); + +CREATE TABLE IF NOT EXISTS `custom_multiclass_profile_audit` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + `character_id` INT UNSIGNED NOT NULL DEFAULT 0, + `class_slot` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `class_id` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `action` VARCHAR(64) NOT NULL DEFAULT '', + `detail` VARCHAR(255) NOT NULL DEFAULT '', + `created_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_character_created` (`character_id`, `created_at`), + KEY `idx_class` (`class_id`) +); + +CREATE TABLE IF NOT EXISTS `custom_multiclass_pet_state` ( + `character_id` INT UNSIGNED NOT NULL, + `pet_slot` TINYINT UNSIGNED NOT NULL, + `spell_id` INT UNSIGNED NOT NULL DEFAULT 0, + `pet_name` VARCHAR(64) NOT NULL DEFAULT '', + `pet_order` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `held` TINYINT(1) NOT NULL DEFAULT 0, + `gheld` TINYINT(1) NOT NULL DEFAULT 0, + `nocast` TINYINT(1) NOT NULL DEFAULT 0, + `focused` TINYINT(1) NOT NULL DEFAULT 0, + `pet_stop` TINYINT(1) NOT NULL DEFAULT 0, + `pet_regroup` TINYINT(1) NOT NULL DEFAULT 0, + `guard_x` FLOAT NOT NULL DEFAULT 0, + `guard_y` FLOAT NOT NULL DEFAULT 0, + `guard_z` FLOAT NOT NULL DEFAULT 0, + `guard_heading` FLOAT NOT NULL DEFAULT 0, + `updated_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`, `pet_slot`), + KEY `idx_character_spell` (`character_id`, `spell_id`) +); + +CREATE TABLE IF NOT EXISTS `custom_multiclass_bard_melody` ( + `character_id` INT UNSIGNED NOT NULL, + `slot_id` TINYINT UNSIGNED NOT NULL, + `spell_id` INT UNSIGNED NOT NULL DEFAULT 0, + `updated_at` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`character_id`, `slot_id`) +); +)", + .content_schema_update = false, + }, }; // see struct definitions for what each field does diff --git a/common/repositories/skill_caps_repository.h b/common/repositories/skill_caps_repository.h index 179103f7fb..269044f4d2 100644 --- a/common/repositories/skill_caps_repository.h +++ b/common/repositories/skill_caps_repository.h @@ -78,4 +78,35 @@ class SkillCapsRepository: public BaseSkillCapsRepository { return lines; } + + static std::vector GetMulticlassSkillCapFileLines(Database& db) + { + std::vector lines; + + auto results = db.QueryDatabase( + fmt::format( + "SELECT CONCAT_WS('^', class_ids.class_id, caps.skill_id, caps.level, caps.cap, 0) " + "FROM (" + "SELECT 1 AS class_id UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 " + "UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 " + "UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12 " + "UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL SELECT 16" + ") AS class_ids " + "JOIN (" + "SELECT skill_id, level, MAX(cap) AS cap " + "FROM {} " + "GROUP BY skill_id, level" + ") AS caps " + "WHERE caps.cap > 0 " + "ORDER BY class_ids.class_id, caps.skill_id, caps.level ASC", + TableName() + ) + ); + + for (auto row : results) { + lines.emplace_back(row[0]); + } + + return lines; + } }; diff --git a/common/version.h b/common/version.h index 5374845dd9..70a503241f 100644 --- a/common/version.h +++ b/common/version.h @@ -40,4 +40,4 @@ #define CURRENT_BINARY_DATABASE_VERSION 9328 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9055 -#define CUSTOM_BINARY_DATABASE_VERSION 4 +#define CUSTOM_BINARY_DATABASE_VERSION 7 diff --git a/zone/aa.cpp b/zone/aa.cpp index 984386d405..66cf20d87c 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -34,6 +34,7 @@ #include "zone/corpse.h" #include "zone/groups.h" #include "zone/mob.h" +#include "zone/multiclass_manager.h" #include "zone/queryserv.h" #include "zone/quest_parser_collection.h" #include "zone/raids.h" @@ -523,6 +524,10 @@ void Client::ResetAA() int slot_id = 0; for (auto& rank_value: aa_ranks) { + if (slot_id >= MAX_PP_AA_ARRAY) { + break; + } + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(rank_value.first, rank_value.second.first); auto ability = ability_rank.first; auto rank = ability_rank.second; @@ -923,7 +928,7 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { return; } - if(!(ability->classes & (1 << GetClass()))) { + if(!(ability->classes & multiclass_manager.GetAAClassMask(this))) { return; } @@ -946,7 +951,7 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { aai->spell = rank->spell; aai->spell_type = rank->spell_type; aai->spell_refresh = rank->recast_time; - aai->classes = ability->classes; + aai->classes = ability->classes | multiclass_manager.GetAAClassMask(this); aai->level_req = rank->level_req; aai->current_level = level; aai->max_level = ability->GetMaxLevel(this); @@ -998,6 +1003,10 @@ void Client::SendAlternateAdvancementPoints() { int i = 0; for(auto &aa : zone->aa_abilities) { + if (i >= MAX_PP_AA_ARRAY) { + break; + } + uint32 charges = 0; auto ranks = GetAA(aa.second->first_rank_id, &charges); if(ranks) { @@ -1334,7 +1343,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { } else { // Bards can cast instant cast AAs while they are casting or channeling item cast. - if (GetClass() == Class::Bard && IsCasting() && spells[rank->spell].cast_time == 0) { + if (multiclass_manager.IsBard(this) && IsCasting() && spells[rank->spell].cast_time == 0) { if (!DoCastingChecksOnCaster(rank->spell, EQ::spells::CastingSlot::AltAbility)) { return; } @@ -1570,7 +1579,8 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) return false; } - if (!(a->classes & (1 << GetClass()))) { + const auto class_mask = IsClient() ? multiclass_manager.GetAAClassMask(CastToClient()) : (1 << GetClass()); + if (!(a->classes & class_mask)) { return false; } diff --git a/zone/attack.cpp b/zone/attack.cpp index b6e6148ba5..37bb6000b5 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -29,6 +29,7 @@ #include "zone/fastmath.h" #include "zone/lua_parser.h" #include "zone/mob.h" +#include "zone/multiclass_manager.h" #include "zone/npc.h" #include "zone/queryserv.h" #include "zone/quest_parser_collection.h" @@ -43,6 +44,21 @@ extern FastMath g_Math; extern EntityList entity_list; extern Zone* zone; +namespace { +bool HasMulticlassCombatClass(Mob *mob, uint8 class_id) +{ + if (!mob) { + return false; + } + + if (mob->IsClient()) { + return multiclass_manager.HasClass(mob->CastToClient(), class_id); + } + + return mob->GetClass() == class_id; +} +} + //SYNC WITH: tune.cpp, mob.h TuneAttackAnimation EQ::skills::SkillType Mob::AttackAnimation(int Hand, const EQ::ItemInstance* weapon, EQ::skills::SkillType skillinuse) { @@ -590,7 +606,7 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit) } // dodge - if (CanThisClassDodge() && (InFront || GetClass() == Class::Monk)) { + if (CanThisClassDodge() && (InFront || HasMulticlassCombatClass(this, Class::Monk))) { if (IsClient()) CastToClient()->CheckIncreaseSkill(EQ::skills::SkillDodge, other, -10); // check auto discs ... I guess aa/items too :P @@ -1151,7 +1167,7 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemData *weapon_item) { return 0; } } - else if ((GetClass() == Class::Monk || GetClass() == Class::Beastlord) && GetLevel() >= 30) { + else if ((HasMulticlassCombatClass(this, Class::Monk) || HasMulticlassCombatClass(this, Class::Beastlord)) && GetLevel() >= 30) { dmg = GetHandToHandDamage(); } else { @@ -1238,7 +1254,11 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemInstance *weapon_item, in return 0; } - if (!weapon_item->IsClassEquipable(GetClass()) && + const bool class_equipable = IsClient() ? + multiclass_manager.CanUseItem(CastToClient(), weapon_item) : + weapon_item->IsClassEquipable(GetClass()); + + if (!class_equipable && ( !IsBot() || (IsBot() && !RuleB(Bots, AllowBotEquipAnyClassGear)) @@ -1578,7 +1598,7 @@ bool Mob::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool LogCombatDetail("Attacking [{}] with hand [{}] [{}]", other->GetName(), Hand, bRiposte ? "this is a riposte" : ""); if ( - (IsCasting() && GetClass() != Class::Bard && !IsFromSpell) + (IsCasting() && !HasMulticlassCombatClass(this, Class::Bard) && !IsFromSpell) || ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) || (GetHP() < 0) || (!IsAttackAllowed(other)) @@ -3967,34 +3987,32 @@ bool Client::CheckDoubleAttack() // with varying triple attack skill (1-3% error at least) bool Client::CheckTripleAttack() { - int chance; + int chance = 0; if (RuleB(Combat, ClassicTripleAttack)) { if ( - IsClient() && GetLevel() >= 60 && ( - GetClass() == Class::Warrior || - GetClass() == Class::Ranger || - GetClass() == Class::Monk || - GetClass() == Class::Berserker + multiclass_manager.HasClass(this, Class::Warrior) || + multiclass_manager.HasClass(this, Class::Ranger) || + multiclass_manager.HasClass(this, Class::Monk) || + multiclass_manager.HasClass(this, Class::Berserker) ) ) { - switch (GetClass()) { - case Class::Warrior: - chance = RuleI(Combat, ClassicTripleAttackChanceWarrior); - break; - case Class::Ranger: - chance = RuleI(Combat, ClassicTripleAttackChanceRanger); - break; - case Class::Monk: - chance = RuleI(Combat, ClassicTripleAttackChanceMonk); - break; - case Class::Berserker: - chance = RuleI(Combat, ClassicTripleAttackChanceBerserker); - break; - default: - break; + if (multiclass_manager.HasClass(this, Class::Warrior)) { + chance = std::max(chance, RuleI(Combat, ClassicTripleAttackChanceWarrior)); + } + + if (multiclass_manager.HasClass(this, Class::Ranger)) { + chance = std::max(chance, RuleI(Combat, ClassicTripleAttackChanceRanger)); + } + + if (multiclass_manager.HasClass(this, Class::Monk)) { + chance = std::max(chance, RuleI(Combat, ClassicTripleAttackChanceMonk)); + } + + if (multiclass_manager.HasClass(this, Class::Berserker)) { + chance = std::max(chance, RuleI(Combat, ClassicTripleAttackChanceBerserker)); } } } else { @@ -5444,11 +5462,11 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * // We either require an innate crit chance or some SPA 169 to crit bool innate_crit = false; int crit_chance = GetCriticalChanceBonus(hit.skill); - if ((GetClass() == Class::Warrior || GetClass() == Class::Berserker) && GetLevel() >= 12) { + if ((HasMulticlassCombatClass(this, Class::Warrior) || HasMulticlassCombatClass(this, Class::Berserker)) && GetLevel() >= 12) { innate_crit = true; - } else if (GetClass() == Class::Ranger && GetLevel() >= 12 && hit.skill == EQ::skills::SkillArchery) { + } else if (HasMulticlassCombatClass(this, Class::Ranger) && GetLevel() >= 12 && hit.skill == EQ::skills::SkillArchery) { innate_crit = true; - } else if (GetClass() == Class::Rogue && GetLevel() >= 12 && hit.skill == EQ::skills::SkillThrowing) { + } else if (HasMulticlassCombatClass(this, Class::Rogue) && GetLevel() >= 12 && hit.skill == EQ::skills::SkillThrowing) { innate_crit = true; } @@ -5474,7 +5492,7 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * dex_bonus += 45; // chances did not match live without a small boost // so if we have an innate crit we have a better chance, except for ber throwing - if (!innate_crit || (GetClass() == Class::Berserker && hit.skill == EQ::skills::SkillThrowing)) { + if (!innate_crit || (HasMulticlassCombatClass(this, Class::Berserker) && hit.skill == EQ::skills::SkillThrowing)) { dex_bonus = dex_bonus * 3 / 5; } @@ -5502,7 +5520,7 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * LogCombatDetail("Crit success roll [{}] dex chance [{}] og dmg [{}] crit_mod [{}] new dmg [{}]", roll, dex_bonus, og_damage, crit_mod, hit.damage_done); // step 3: check deadly strike - if (GetClass() == Class::Rogue && hit.skill == EQ::skills::SkillThrowing) { + if (HasMulticlassCombatClass(this, Class::Rogue) && hit.skill == EQ::skills::SkillThrowing) { if (BehindMob(defender, GetX(), GetY())) { int chance = GetLevel() * 12; if (zone->random.Int(1, 1000) < chance) { @@ -6372,7 +6390,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac // BER weren't parsing the halving if (hit.skill == EQ::skills::SkillArchery || - (hit.skill == EQ::skills::SkillThrowing && GetClass() != Class::Berserker)) + (hit.skill == EQ::skills::SkillThrowing && !HasMulticlassCombatClass(this, Class::Berserker))) hit.damage_done /= 2; if (hit.damage_done < 1) @@ -6385,7 +6403,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac if (headshot > 0) { hit.damage_done = headshot; } - else if (GetClass() == Class::Ranger && GetLevel() >= RuleI(Combat, ArcheryBonusLevelRequirement)) { // no double dmg on headshot + else if (HasMulticlassCombatClass(this, Class::Ranger) && GetLevel() >= RuleI(Combat, ArcheryBonusLevelRequirement)) { // no double dmg on headshot if ((defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) || !RuleB(Combat, ArcheryBonusRequiresStationary)) { hit.damage_done *= 2; MessageString(Chat::MeleeCrit, BOW_DOUBLE_DAMAGE); @@ -6415,7 +6433,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac } } } - else if (hit.skill == EQ::skills::SkillFrenzy && GetClass() == Class::Berserker && GetLevel() > 50) { + else if (hit.skill == EQ::skills::SkillFrenzy && HasMulticlassCombatClass(this, Class::Berserker) && GetLevel() > 50) { extra_mincap = 4 * GetLevel() / 5; } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 131bf0f27c..2023bd7997 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -24,6 +24,7 @@ #include "zone/entity.h" #include "zone/mob.h" #include "zone/bot.h" +#include "zone/multiclass_manager.h" #include "zone/quest_parser_collection.h" #include @@ -66,6 +67,7 @@ void Client::CalcBonuses() CalcEdibleBonuses(&itembonuses); CalcSpellBonuses(&spellbonuses); CalcAABonuses(&aabonuses); + multiclass_manager.ApplyTrioBonuses(this, &aabonuses); CalcSeeInvisibleLevel(); CalcInvisibleLevel(); @@ -260,7 +262,7 @@ void Mob::AddItemBonuses(const EQ::ItemInstance* inst, StatBonuses* b, bool is_a return; } - if (IsClient() && !is_tribute && !inst->IsEquipable(GetBaseRace(), GetClass())) { + if (IsClient() && !is_tribute && !multiclass_manager.CanUseItem(CastToClient(), inst)) { if (item->ItemType != EQ::item::ItemTypeFood && item->ItemType != EQ::item::ItemTypeDrink) { return; } @@ -520,7 +522,7 @@ void Mob::AdditiveWornBonuses(const EQ::ItemInstance* inst, StatBonuses* b, bool const auto* item = inst->GetItem(); - if (!inst->IsEquipable(GetBaseRace(), GetClass())) { + if (IsClient() ? !multiclass_manager.CanUseItem(CastToClient(), inst) : !inst->IsEquipable(GetBaseRace(), GetClass())) { return; } diff --git a/zone/client.cpp b/zone/client.cpp index 4360ee3733..aa7b93c0c0 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -53,6 +53,7 @@ #include "zone/guild_mgr.h" #include "zone/lua_parser.h" #include "zone/mob_movement_manager.h" +#include "zone/multiclass_manager.h" #include "zone/petitions.h" #include "zone/position.h" #include "zone/queryserv.h" @@ -3178,6 +3179,10 @@ bool Client::HasSkill(EQ::skills::SkillType skill_id) const bool Client::CanHaveSkill(EQ::skills::SkillType skill_id) const { + if (multiclass_manager.CanHaveSkill(this, skill_id)) { + return true; + } + if ( ClientVersion() < EQ::versions::ClientVersion::RoF2 && class_ == Class::Berserker && @@ -3191,6 +3196,13 @@ bool Client::CanHaveSkill(EQ::skills::SkillType skill_id) const uint16 Client::MaxSkill(EQ::skills::SkillType skill_id, uint8 class_id, uint8 level) const { + if (class_id == GetClass()) { + const auto multiclass_cap = multiclass_manager.GetBestSkillCap(this, skill_id, level); + if (multiclass_cap) { + return multiclass_cap; + } + } + if ( ClientVersion() < EQ::versions::ClientVersion::RoF2 && class_id == Class::Berserker && @@ -3204,6 +3216,13 @@ uint16 Client::MaxSkill(EQ::skills::SkillType skill_id, uint8 class_id, uint8 le uint8 Client::GetSkillTrainLevel(EQ::skills::SkillType skill_id, uint8 class_id) { + if (class_id == GetClass()) { + const auto multiclass_train_level = multiclass_manager.GetBestSkillTrainLevel(this, skill_id); + if (multiclass_train_level) { + return multiclass_train_level; + } + } + if ( ClientVersion() < EQ::versions::ClientVersion::RoF2 && class_id == Class::Berserker && @@ -9632,8 +9651,7 @@ void Client::InitInnates() // The client calls this in a few places. When you remove a vision buff and in SetHeights, which is called in // illusions, mounts, and a bunch of other cases. All of the calls to InitInnates are wrapped in restoring regen // besides the call initializing the first time - auto race = GetRace(); - auto class_ = GetClass(); + auto race = GetRace(); for (int i = 0; i < InnateSkillMax; ++i) { m_pp.InnateSkills[i] = InnateDisabled; @@ -9726,25 +9744,26 @@ void Client::InitInnates() break; } - switch (class_) { - case Class::Druid: - m_pp.InnateSkills[InnateHarmony] = InnateEnabled; - break; - case Class::Bard: - m_pp.InnateSkills[InnateReveal] = InnateEnabled; - break; - case Class::Rogue: - m_pp.InnateSkills[InnateSurprise] = InnateEnabled; - m_pp.InnateSkills[InnateReveal] = InnateEnabled; - break; - case Class::Ranger: - m_pp.InnateSkills[InnateAwareness] = InnateEnabled; - break; - case Class::Monk: - m_pp.InnateSkills[InnateSurprise] = InnateEnabled; - m_pp.InnateSkills[InnateAwareness] = InnateEnabled; - default: - break; + if (multiclass_manager.HasClass(this, Class::Druid)) { + m_pp.InnateSkills[InnateHarmony] = InnateEnabled; + } + + if (multiclass_manager.HasClass(this, Class::Bard)) { + m_pp.InnateSkills[InnateReveal] = InnateEnabled; + } + + if (multiclass_manager.HasClass(this, Class::Rogue)) { + m_pp.InnateSkills[InnateSurprise] = InnateEnabled; + m_pp.InnateSkills[InnateReveal] = InnateEnabled; + } + + if (multiclass_manager.HasClass(this, Class::Ranger)) { + m_pp.InnateSkills[InnateAwareness] = InnateEnabled; + } + + if (multiclass_manager.HasClass(this, Class::Monk)) { + m_pp.InnateSkills[InnateSurprise] = InnateEnabled; + m_pp.InnateSkills[InnateAwareness] = InnateEnabled; } } @@ -10809,11 +10828,16 @@ std::vector Client::GetLearnableDisciplines(uint8 min_level, uint8 max_leve continue; } - if (max_level && spells[spell_id].classes[m_pp.class_ - 1] > max_level) { + const auto multiclass_level = multiclass_manager.GetBestSpellLevel(this, spell_id); + if (multiclass_level == 255) { + continue; + } + + if (max_level && multiclass_level > max_level) { continue; } - if (min_level > 1 && spells[spell_id].classes[m_pp.class_ - 1] < min_level) { + if (min_level > 1 && multiclass_level < min_level) { continue; } @@ -10880,11 +10904,16 @@ std::vector Client::GetScribeableSpells(uint8 min_level, uint8 max_level) { continue; } - if (max_level && spells[spell_id].classes[m_pp.class_ - 1] > max_level) { + const auto multiclass_level = multiclass_manager.GetBestSpellLevel(this, spell_id); + if (multiclass_level == 255) { continue; } - if (min_level > 1 && spells[spell_id].classes[m_pp.class_ - 1] < min_level) { + if (max_level && multiclass_level > max_level) { + continue; + } + + if (min_level > 1 && multiclass_level < min_level) { continue; } @@ -10917,7 +10946,7 @@ std::vector Client::GetScribeableSpells(uint8 min_level, uint8 max_level) { if (g != spell_group_cache.end()) { for (const auto& s : g->second) { if ( - EQ::ValueWithin(spells[s].classes[m_pp.class_ - 1], min_level, max_level) && + EQ::ValueWithin(multiclass_manager.GetBestSpellLevel(this, s), min_level, max_level) && s == spell_id && scribeable ) { @@ -11664,6 +11693,7 @@ uint16 Client::ScribeSpells(uint8 min_level, uint8 max_level) { auto available_book_slot = GetNextAvailableSpellBookSlot(); std::vector spell_ids = GetScribeableSpells(min_level, max_level); + std::vector> client_updates; uint16 scribed_spells = 0; if (!spell_ids.empty()) { @@ -11684,8 +11714,10 @@ uint16 Client::ScribeSpells(uint8 min_level, uint8 max_level) continue; } - // defer saving per spell and bulk save at the end - ScribeSpell(spell_id, available_book_slot, true, true); + // Defer both DB writes and client book packets so Multiclass can + // patch off-class display levels before the client caches menus. + ScribeSpell(spell_id, available_book_slot, false, true); + client_updates.emplace_back(available_book_slot, spell_id); available_book_slot = GetNextAvailableSpellBookSlot(available_book_slot); scribed_spells++; } @@ -11699,6 +11731,11 @@ uint16 Client::ScribeSpells(uint8 min_level, uint8 max_level) ); Message(Chat::White, fmt::format("You have learned {}!", spell_message).c_str()); + multiclass_manager.SendNativeSpellLevelSnapshot(this); + for (const auto& [slot, spell_id] : client_updates) { + MemorizeSpell(slot, spell_id, memSpellScribing); + } + // bulk insert spells SaveSpells(); } @@ -11790,7 +11827,13 @@ uint16 Client::GetClassTrackingDistanceMultiplier(uint16 class_) { } bool Client::CanThisClassTrack() { - return (GetClassTrackingDistanceMultiplier(GetClass()) > 0) ? true : false; + for (const auto class_id : multiclass_manager.GetClassSlots(this)) { + if (GetClassTrackingDistanceMultiplier(class_id) > 0) { + return true; + } + } + + return false; } void Client::ReconnectUCS() @@ -12110,6 +12153,11 @@ std::vector Client::GetApplySpellList( if (allow_pets && m.member->HasPet()) { l.push_back(m.member->GetPet()); } + if (allow_pets) { + for (auto *pet : multiclass_manager.GetSecondaryPetRoster(m.member)) { + l.push_back(pet); + } + } if (allow_bots) { const auto& sbl = entity_list.GetBotListByCharacterID(m.member->CharacterID()); @@ -12132,6 +12180,11 @@ std::vector Client::GetApplySpellList( if (allow_pets && m->HasPet()) { l.push_back(m->GetPet()); } + if (allow_pets && m->IsClient()) { + for (auto *pet : multiclass_manager.GetSecondaryPetRoster(m->CastToClient())) { + l.push_back(pet); + } + } if (allow_bots) { const auto& sbl = entity_list.GetBotListByCharacterID(m->CastToClient()->CharacterID()); @@ -12148,6 +12201,11 @@ std::vector Client::GetApplySpellList( if (allow_pets && HasPet()) { l.push_back(GetPet()); } + if (allow_pets) { + for (auto *pet : multiclass_manager.GetSecondaryPetRoster(this)) { + l.push_back(pet); + } + } if (allow_bots) { const auto& sbl = entity_list.GetBotListByCharacterID(CharacterID()); @@ -12212,7 +12270,7 @@ void Client::MaxSkills() auto current_skill_value = ( EQ::skills::IsSpecializedSkill(s.first) ? MAX_SPECIALIZED_SKILL : - SkillCaps::Instance()->GetSkillCap(GetClass(), s.first, GetLevel()).cap + MaxSkill(s.first) ); if (GetSkill(s.first) < current_skill_value) { diff --git a/zone/client.h b/zone/client.h index 5903e3b544..072a4351dd 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1156,6 +1156,7 @@ class Client : public Mob void SendItemLink(const EQ::ItemInstance* inst, bool sendtoall=false); void SendLootItemInPacket(const EQ::ItemInstance* inst, int16 slot_id); + EQ::ItemInstance* CloneItemForMulticlassPresentation(const EQ::ItemInstance* inst); void SendItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPacketType packet_type); bool RefreshLiveItem(EQ::ItemInstance* inst); bool RefreshLiveItemTree(EQ::ItemInstance* inst); diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 63b5b1fe48..2207e26608 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -22,6 +22,7 @@ #include "common/spdat.h" #include "zone/bot.h" #include "zone/mob.h" +#include "zone/multiclass_manager.h" #include @@ -575,7 +576,7 @@ int64 Client::CalcBaseMana() ConvertedWisInt = (3 * over200 - 300) / 2 + over200; } - auto base_data = zone->GetBaseData(GetLevel(), GetClass()); + auto base_data = zone->GetBaseData(GetLevel(), multiclass_manager.GetPrimaryIntCasterClass(this)); if (base_data.level == GetLevel()) { max_m = base_data.mana + (ConvertedWisInt * base_data.mana_fac) + itembonuses.heroic_max_mana; } @@ -608,7 +609,7 @@ int64 Client::CalcBaseMana() ConvertedWisInt = (3 * over200 - 300) / 2 + over200; } - auto base_data = zone->GetBaseData(GetLevel(), GetClass()); + auto base_data = zone->GetBaseData(GetLevel(), multiclass_manager.GetPrimaryWisCasterClass(this)); if (base_data.level == GetLevel()) { max_m = base_data.mana + (ConvertedWisInt * base_data.mana_fac) + itembonuses.heroic_max_mana; } @@ -665,7 +666,7 @@ int64 Client::CalcManaRegen(bool bCombat) if (IsSitting() || CanMedOnHorse()) { // kind of weird to do it here w/e // client does some base medding regen for shrouds here - if (GetClass() != Class::Bard) { + if (!multiclass_manager.IsBard(this)) { auto skill = GetSkill(EQ::skills::SkillMeditate); if (skill > 0) { regen++; @@ -1443,7 +1444,7 @@ int32 Client::CalcATK() uint32 Mob::GetInstrumentMod(uint16 spell_id) { - if (GetClass() != Class::Bard || spells[spell_id].is_discipline || spell_id == SPELL_AMPLIFICATION) { + if ((IsClient() ? !multiclass_manager.IsBard(CastToClient()) : GetClass() != Class::Bard) || spells[spell_id].is_discipline || spell_id == SPELL_AMPLIFICATION) { //Other classes can get a base effects mod using SPA 413 if (HasBaseEffectFocus()) { return (10 + (GetFocusEffect(focusFcBaseEffects, spell_id) / 10));//TODO: change action->instrument mod to float to support < 10% focus values diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index c8627f0bd4..93285af118 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -46,6 +46,7 @@ #include "zone/guild_mgr.h" #include "zone/merc.h" #include "zone/mob_movement_manager.h" +#include "zone/multiclass_manager.h" #include "zone/petitions.h" #include "zone/queryserv.h" #include "zone/quest_parser_collection.h" @@ -69,6 +70,24 @@ extern WorldServer worldserver; extern EntityList entity_list; typedef void (Client::*ClientPacketProc)(const EQApplicationPacket *app); +static uint32 GetMulticlassItemClassPresentationMask(Client *client, const EQ::ItemData *item) +{ + if (!item) { + return 0; + } + + if (!client) { + return item->Classes; + } + + const auto class_mask = multiclass_manager.GetClassMask(client); + if ((item->Races & GetPlayerRaceBit(client->GetBaseRace())) && (item->Classes & class_mask)) { + return item->Classes | class_mask; + } + + return item->Classes; +} + //Use a map for connecting opcodes since it dosent get used a lot and is sparse std::map ConnectingOpcodes; //Use a static array for connected, for speed @@ -958,6 +977,8 @@ void Client::CompleteConnect() SetPetCommandState(PetButton::SpellHold, PetButtonState::Off); } + multiclass_manager.SeedEligibleSkills(this, true); + database.LoadAuras(this); // this ends up spawning them so probably safer to load this later (here) database.LoadCharacterDisciplines(this); @@ -1685,9 +1706,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) m_pp.spellSlotRefresh[i] = p_timers.GetRemainingTime(pTimerSpellStart + m_pp.mem_spells[i]) * 1000; /* Ability slot refresh send SK/PAL */ - if (m_pp.class_ == Class::ShadowKnight || m_pp.class_ == Class::Paladin) { + if (multiclass_manager.HasClass(this, Class::ShadowKnight) || multiclass_manager.HasClass(this, Class::Paladin)) { uint32 abilitynum = 0; - if (m_pp.class_ == Class::ShadowKnight) { abilitynum = pTimerHarmTouch; } + if (multiclass_manager.HasClass(this, Class::ShadowKnight)) { abilitynum = pTimerHarmTouch; } else { abilitynum = pTimerLayHands; } uint32 remaining = p_timers.GetRemainingTime(abilitynum); @@ -1716,7 +1737,12 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) /* The entityid field in the Player Profile is used by the Client in relation to Group Leadership AA */ m_pp.entityid = GetID(); - memcpy(outapp->pBuffer, &m_pp, outapp->size); + auto profile_for_client = m_pp; + const auto presentation_class = multiclass_manager.GetClientPresentationClass(this); + if (IsPlayerClass(presentation_class)) { + profile_for_client.class_ = presentation_class; + } + memcpy(outapp->pBuffer, &profile_for_client, outapp->size); outapp->priority = 6; FastQueuePacket(&outapp); @@ -1743,9 +1769,11 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) pet->SetTaunting(m_petinfo.taunting); } } + database.LoadMulticlassPetState(this, pet, PetInfoType::Current); } m_petinfo.SpellID = 0; } + database.LoadMulticlassPetInfo(this); } /* Moved here so it's after where we load the pet data. */ if (!aabonuses.ZoneSuspendMinion && !spellbonuses.ZoneSuspendMinion && !itembonuses.ZoneSuspendMinion) { @@ -2258,7 +2286,7 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app) ss << (item->Stackable ? 1 : 0) << "|"; ss << (item->LoreFlag ? 1 : 0) << "|"; ss << item->Races << "|"; - ss << item->Classes; + ss << GetMulticlassItemClassPresentationMask(this, item); count++; } } @@ -2612,7 +2640,7 @@ void Client::Handle_OP_AltCurrencyMerchantRequest(const EQApplicationPacket *app item_ss << "0|"; item_ss << "1|"; item_ss << item->Races << "|"; - item_ss << item->Classes; + item_ss << GetMulticlassItemClassPresentationMask(this, item); count++; } } @@ -3035,7 +3063,7 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app) bool IsPoison = (poison && poison->ItemType == EQ::item::ItemTypePoison); - if (IsPoison && GetClass() == Class::Rogue) { + if (IsPoison && multiclass_manager.HasClass(this, Class::Rogue)) { // Live always checks for skillup, even when poison is too high CheckIncreaseSkill(EQ::skills::SkillApplyPoison, nullptr, 10); @@ -8921,7 +8949,7 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app) hidden = true; tmHidden = Timer::GetCurrentTime(); } - if (GetClass() == Class::Rogue) { + if (multiclass_manager.HasClass(this, Class::Rogue)) { auto outapp = new EQApplicationPacket(OP_SimpleMessage, sizeof(SimpleMessage_Struct)); SimpleMessage_Struct *msg = (SimpleMessage_Struct *)outapp->pBuffer; msg->color = 0x010E; @@ -9288,7 +9316,7 @@ void Client::Handle_OP_ItemPreview(const EQApplicationPacket *app) outapp->WriteUInt32(item->Regen); outapp->WriteUInt32(item->ManaRegen); outapp->WriteSInt32(item->EnduranceRegen); - outapp->WriteUInt32(item->Classes); + outapp->WriteUInt32(GetMulticlassItemClassPresentationMask(this, item)); outapp->WriteUInt32(item->Races); outapp->WriteUInt32(item->Deity); outapp->WriteUInt32(item->SkillModValue); @@ -9399,7 +9427,8 @@ void Client::Handle_OP_ItemPreviewRequest(const EQApplicationPacket* app) if (item) { EQ::ItemInstance* inst = database.CreateItem(item); if (inst) { - std::string packet = inst->Serialize(-1); + auto *presentation_inst = CloneItemForMulticlassPresentation(inst); + std::string packet = (presentation_inst ? presentation_inst : inst)->Serialize(-1); auto outapp = new EQApplicationPacket(OP_ItemPreviewRequest, packet.length()); memcpy(outapp->pBuffer, packet.c_str(), packet.length()); @@ -9409,6 +9438,7 @@ void Client::Handle_OP_ItemPreviewRequest(const EQApplicationPacket* app) QueuePacket(outapp); safe_delete(outapp); + safe_delete(presentation_inst); safe_delete(inst); } } @@ -9494,7 +9524,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) Bards on live can click items while casting spell gems, it stops that song cast and replaces it with item click cast. Can not click while casting other items. */ - if (GetClass() == Class::Bard && IsCasting() && casting_spell_slot < CastingSlot::MaxGems) + if (multiclass_manager.IsBard(this) && IsCasting() && casting_spell_slot < CastingSlot::MaxGems) { is_casting_bard_song = true; } @@ -9653,7 +9683,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) if (!IsCastWhileInvisibleSpell(item->Click.Effect)) { CommonBreakInvisible(); // client can't do this for us :( } - if (GetClass() == Class::Bard){ + if (multiclass_manager.IsBard(this)){ DoBardCastingFromItemClick(is_casting_bard_song, item->CastTime, item->Click.Effect, target_id, CastingSlot::Item, slot_id, item->RecastType, item->RecastDelay); } else { @@ -9718,7 +9748,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) if (!IsCastWhileInvisibleSpell(augitem->Click.Effect)) { CommonBreakInvisible(); // client can't do this for us :( } - if (GetClass() == Class::Bard) { + if (multiclass_manager.IsBard(this)) { DoBardCastingFromItemClick(is_casting_bard_song, augitem->CastTime, augitem->Click.Effect, target_id, CastingSlot::Item, slot_id, augitem->RecastType, augitem->RecastDelay); } else { @@ -9738,7 +9768,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } else { - if (ClientVersion() >= EQ::versions::ClientVersion::SoD && !inst->IsEquipable(GetBaseRace(), GetClass())) + if (ClientVersion() >= EQ::versions::ClientVersion::SoD && !multiclass_manager.CanUseItem(this, inst)) { if (item->ItemType != EQ::item::ItemTypeFood && item->ItemType != EQ::item::ItemTypeDrink && item->ItemType != EQ::item::ItemTypeAlcohol) { @@ -14756,7 +14786,7 @@ void Client::Handle_OP_Sneak(const EQApplicationPacket *app) sa_out->parameter = sneaking; QueuePacket(outapp); safe_delete(outapp); - if (GetClass() == Class::Rogue) { + if (multiclass_manager.HasClass(this, Class::Rogue)) { outapp = new EQApplicationPacket(OP_SimpleMessage, 12); SimpleMessage_Struct *msg = (SimpleMessage_Struct *)outapp->pBuffer; msg->color = 0x010E; diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 03e3cdaf9b..00e6092d2c 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -35,6 +35,7 @@ #include "zone/guild_mgr.h" #include "zone/live_spell_manager.h" #include "zone/map.h" +#include "zone/multiclass_manager.h" #include "zone/petitions.h" #include "zone/queryserv.h" #include "zone/quest_parser_collection.h" @@ -45,6 +46,7 @@ #include "zone/zonedb.h" #include +#include extern QueryServ* QServ; extern Zone* zone; @@ -238,6 +240,7 @@ bool Client::Process() { } } } + multiclass_manager.ProcessBardMelody(this); if (GetMerc()) { UpdateMercTimer(); @@ -455,7 +458,7 @@ bool Client::Process() { } } - if (GetClass() == Class::Warrior || GetClass() == Class::Berserker) { + if (multiclass_manager.HasClass(this, Class::Warrior) || multiclass_manager.HasClass(this, Class::Berserker)) { if (!dead && !IsBerserk() && GetHPRatio() < RuleI(Combat, BerserkerFrenzyStart)) { entity_list.MessageCloseString(this, false, 200, 0, BERSERK_START, GetName()); berserk = true; @@ -777,6 +780,17 @@ void Client::BulkSendInventoryItems() EQ::OutBuffer ob; EQ::OutBuffer::pos_type last_pos = ob.tellp(); + std::vector multiclass_presentation_items; + + const auto serialize_inventory_item = [this, &multiclass_presentation_items, &ob](const EQ::ItemInstance* inst, int16 slot_id) { + auto *presentation_inst = CloneItemForMulticlassPresentation(inst); + const auto *serialized_inst = presentation_inst ? presentation_inst : inst; + serialized_inst->Serialize(ob, slot_id); + + if (presentation_inst) { + multiclass_presentation_items.push_back(presentation_inst); + } + }; // Possessions items for (int16 slot_id = EQ::invslot::POSSESSIONS_BEGIN; slot_id <= EQ::invslot::POSSESSIONS_END; slot_id++) { @@ -785,7 +799,7 @@ void Client::BulkSendInventoryItems() continue; } - inst->Serialize(ob, slot_id); + serialize_inventory_item(inst, slot_id); if (ob.tellp() == last_pos) { LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id); @@ -802,7 +816,7 @@ void Client::BulkSendInventoryItems() continue; } - inst->Serialize(ob, slot_id); + serialize_inventory_item(inst, slot_id); if (ob.tellp() == last_pos) { LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id); @@ -818,7 +832,7 @@ void Client::BulkSendInventoryItems() continue; } - inst->Serialize(ob, slot_id); + serialize_inventory_item(inst, slot_id); if (ob.tellp() == last_pos) { LogInventory("Serialization failed on item slot [{}] during BulkSendInventoryItems. Item skipped", slot_id); @@ -835,6 +849,10 @@ void Client::BulkSendInventoryItems() QueuePacket(outapp); safe_delete(outapp); + + for (auto *inst : multiclass_presentation_items) { + safe_delete(inst); + } } void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { @@ -885,7 +903,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { continue; } - if (!(ml.classes_required & (1 << (GetClass() - 1)))) { + if (!(ml.classes_required & multiclass_manager.GetClassMask(this))) { continue; } @@ -1169,17 +1187,15 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) return; } + const auto multiclass_spell_level = multiclass_manager.GetBestSpellLevel(this, m->spell_id); if ( m->scribing != memSpellForget && - ( - !IsPlayerClass(GetClass()) || - GetLevel() < spells[m->spell_id].classes[GetClass() - 1] - ) + (!IsPlayerClass(GetClass()) || multiclass_spell_level == 255 || GetLevel() < multiclass_spell_level) ) { MessageString( Chat::Red, SPELL_LEVEL_TO_LOW, - std::to_string(spells[m->spell_id].classes[GetClass() - 1]).c_str(), + std::to_string(multiclass_spell_level).c_str(), spells[m->spell_id].name ); return; @@ -1195,7 +1211,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) if ( item && RuleB(Character, RestrictSpellScribing) && - !item->IsEquipable(GetRace(), GetClass()) + !multiclass_manager.CanUseItem(this, inst) ) { MessageString(Chat::Red, CANNOT_USE_ITEM); break; @@ -1626,7 +1642,7 @@ void Client::OPGMTraining(const EQApplicationPacket *app) //you can only use your own trainer, client enforces this, but why trust it if (!RuleB(Character, AllowCrossClassTrainers)) { int trains_class = pTrainer->GetClass() - (Class::WarriorGM - Class::Warrior); - if (GetClass() != trains_class) { + if (!multiclass_manager.HasClass(this, trains_class)) { safe_delete(outapp); return; } @@ -1651,7 +1667,7 @@ void Client::OPGMTraining(const EQApplicationPacket *app) } } - if (ClientVersion() < EQ::versions::ClientVersion::RoF2 && GetClass() == Class::Berserker) { + if (ClientVersion() < EQ::versions::ClientVersion::RoF2 && multiclass_manager.HasClass(this, Class::Berserker)) { gmtrain->skills[EQ::skills::Skill1HPiercing] = gmtrain->skills[EQ::skills::Skill2HPiercing]; gmtrain->skills[EQ::skills::Skill2HPiercing] = 0; } @@ -1685,7 +1701,7 @@ void Client::OPGMEndTraining(const EQApplicationPacket *app) //you can only use your own trainer, client enforces this, but why trust it if (!RuleB(Character, AllowCrossClassTrainers)) { int trains_class = pTrainer->GetClass() - (Class::WarriorGM - Class::Warrior); - if (GetClass() != trains_class) + if (!multiclass_manager.HasClass(this, trains_class)) return; } @@ -1716,7 +1732,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app) //you can only use your own trainer, client enforces this, but why trust it if (!RuleB(Character, AllowCrossClassTrainers)) { int trains_class = pTrainer->GetClass() - (Class::WarriorGM - Class::Warrior); - if (GetClass() != trains_class) + if (!multiclass_manager.HasClass(this, trains_class)) return; } diff --git a/zone/effects.cpp b/zone/effects.cpp index 0d0b1ce348..9722476c87 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -22,11 +22,29 @@ #include "common/spdat.h" #include "zone/client.h" #include "zone/entity.h" +#include "zone/multiclass_manager.h" #include "zone/position.h" #include "zone/string_ids.h" #include "zone/worldserver.h" #include "zone/zonedb.h" +namespace { + +uint8 GetEffectiveSpellClassLevel(Mob *caster, uint16 spell_id) +{ + if (caster && caster->IsClient()) { + return multiclass_manager.GetBestSpellLevel(caster->CastToClient(), spell_id); + } + + if (!caster) { + return 255; + } + + return spells[spell_id].classes[(caster->GetClass() % 17) - 1]; +} + +} + float Mob::GetActSpellRange(uint16 spell_id, float range) { float extrange = 100; @@ -135,7 +153,7 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg) { value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value) * ratio / 100; - } else if (!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) { + } else if (!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && GetEffectiveSpellClassLevel(this, spell_id) >= GetLevel() - 5) { value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, base_value) * ratio / 100; } @@ -187,7 +205,7 @@ int64 Mob::GetActSpellDamage(uint16 spell_id, int64 value, Mob* target) { else if ( !spells[spell_id].no_heal_damage_item_mod && GetSpellDmg() && - spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5 + GetEffectiveSpellClassLevel(this, spell_id) >= GetLevel() - 5 ) { value -= GetExtraSpellAmt(spell_id, GetSpellDmg(), base_value); } @@ -291,7 +309,7 @@ int64 Mob::GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_ else if ( !spells[spell_id].no_heal_damage_item_mod && GetSpellDmg() && - spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5 + GetEffectiveSpellClassLevel(this, spell_id) >= GetLevel() - 5 ) { extra_dmg += GetExtraSpellAmt(spell_id, GetSpellDmg(), base_value)*ratio/100; } @@ -337,7 +355,7 @@ int64 Mob::GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_ else if ( !spells[spell_id].no_heal_damage_item_mod && GetSpellDmg() && - spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5 + GetEffectiveSpellClassLevel(this, spell_id) >= GetLevel() - 5 ) { extra_dmg += GetExtraSpellAmt(spell_id, GetSpellDmg(), base_value); } @@ -479,7 +497,7 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr else if ( !spells[spell_id].no_heal_damage_item_mod && GetHealAmt() && - spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5 + GetEffectiveSpellClassLevel(this, spell_id) >= GetLevel() - 5 ) { value += GetExtraSpellAmt(spell_id, GetHealAmt(), base_value); //Item Heal Amt Add before critical } @@ -533,7 +551,7 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr else if ( !spells[spell_id].no_heal_damage_item_mod && GetHealAmt() && - spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5 + GetEffectiveSpellClassLevel(this, spell_id) >= GetLevel() - 5 ) { extra_heal += GetExtraSpellAmt(spell_id, GetHealAmt(), base_value); } @@ -566,7 +584,7 @@ int32 Mob::GetActSpellCost(uint16 spell_id, int32 cost) cost *= 2; // Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell - if(itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) + if(itembonuses.Clairvoyance && GetEffectiveSpellClassLevel(this, spell_id) >= GetLevel() - 5) { int mana_back = itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; // Doesnt generate mana, so best case is a free spell @@ -672,18 +690,10 @@ bool Client::TrainDiscipline(uint32 itemid) { return false; } - const auto player_class = GetClass(); - if (player_class == Class::Wizard || player_class == Class::Enchanter || player_class == Class::Magician || player_class == Class::Necromancer) { - Message(Chat::Red, "Your class cannot learn from this tome."); - //summon them the item back... - SummonItem(itemid); - return false; - } - //make sure we can train this... //can we use the item? - const auto class_bit = static_cast(1 << (player_class - 1)); - if (!(item->Classes & class_bit)) { + const auto class_mask = multiclass_manager.GetClassMask(this); + if (!(item->Classes & class_mask)) { Message(Chat::Red, "Your class cannot learn from this tome."); //summon them the item back... SummonItem(itemid); @@ -698,7 +708,7 @@ bool Client::TrainDiscipline(uint32 itemid) { //can we use the spell? const auto& spell = spells[spell_id]; - const auto level_to_use = spell.classes[player_class - 1]; + const auto level_to_use = multiclass_manager.GetBestSpellLevel(this, spell_id); if (level_to_use == 255) { Message(Chat::Red, "Your class cannot learn from this tome."); //summon them the item back... @@ -758,9 +768,7 @@ bool Client::MemorizeSpellFromItem(uint32 item_id) { return false; } - const auto class_bit = static_cast(1 << (GetClass() - 1)); - - if (!(item->Classes & class_bit)) { + if (!(item->Classes & multiclass_manager.GetClassMask(this))) { Message(Chat::Red, "Your class cannot learn from this scroll."); SummonItem(item_id); return false; @@ -773,7 +781,7 @@ bool Client::MemorizeSpellFromItem(uint32 item_id) { } const auto& spell = spells[spell_id]; - const auto level_to_use = spell.classes[GetClass() - 1]; + const auto level_to_use = multiclass_manager.GetBestSpellLevel(this, spell_id); if (level_to_use == 255) { Message(Chat::Red, "Your class cannot learn from this scroll."); SummonItem(item_id); @@ -884,7 +892,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { //can we use the spell? const SPDat_Spell_Struct &spell = spells[spell_id]; - uint8 level_to_use = spell.classes[GetClass() - 1]; + uint8 level_to_use = multiclass_manager.GetBestSpellLevel(this, spell_id); if(level_to_use == 255) { Message(Chat::Red, "Your class cannot learn from this tome."); //should summon them a new one... @@ -947,7 +955,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { if (reduced_recast > 0) { instant_recast = false; - if (GetClass() == Class::Bard && IsCasting() && spells[spell_id].cast_time == 0) { + if (multiclass_manager.IsBard(this) && IsCasting() && spells[spell_id].cast_time == 0) { if (DoCastingChecksOnCaster(spell_id, EQ::spells::CastingSlot::Discipline)) { SpellFinished(spell_id, entity_list.GetMob(target), EQ::spells::CastingSlot::Discipline, 0, -1, spells[spell_id].resist_difficulty, false, -1, (uint32)DiscTimer, reduced_recast, false); } @@ -962,7 +970,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { } if (instant_recast) { - if (GetClass() == Class::Bard && IsCasting() && spells[spell_id].cast_time == 0) { + if (multiclass_manager.IsBard(this) && IsCasting() && spells[spell_id].cast_time == 0) { if (DoCastingChecksOnCaster(spell_id, EQ::spells::CastingSlot::Discipline)) { SpellFinished(spell_id, entity_list.GetMob(target), EQ::spells::CastingSlot::Discipline, 0, -1, spells[spell_id].resist_difficulty, false, -1, 0xFFFFFFFF, 0, false); } diff --git a/zone/exp.cpp b/zone/exp.cpp index a9013b9879..f0174a932d 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -26,6 +26,7 @@ #include "zone/groups.h" #include "zone/lua_parser.h" #include "zone/mob.h" +#include "zone/multiclass_manager.h" #include "zone/queryserv.h" #include "zone/quest_parser_collection.h" #include "zone/achievement_manager.h" @@ -968,6 +969,7 @@ void Client::SetLevel(uint8 set_level, bool command) LogInfo("Setting Level for [{}] to [{}]", GetName(), set_level); CalcBonuses(); + multiclass_manager.SeedEligibleSkills(this, true); if (!RuleB(Character, HealOnLevel)) { const auto max_hp = CalcMaxHP(); diff --git a/zone/groups.cpp b/zone/groups.cpp index e15ba4b858..bc32acfad7 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -24,6 +24,7 @@ #include "common/repositories/group_leaders_repository.h" #include "zone/dynamic_zone.h" #include "zone/masterentity.h" +#include "zone/multiclass_manager.h" #include "zone/queryserv.h" #include "zone/string_ids.h" #include "zone/worldserver.h" @@ -830,6 +831,11 @@ void Group::CastGroupSpell(Mob* caster, uint16 spell_id) { #ifdef GROUP_BUFF_PETS if(spells[spell_id].target_type != ST_GroupNoPets && caster->GetPet() && caster->HasPetAffinity() && !caster->GetPet()->IsCharmed()) caster->SpellOnTarget(spell_id, caster->GetPet()); + if (spells[spell_id].target_type != ST_GroupNoPets && caster->IsClient() && caster->HasPetAffinity()) { + for (auto *pet : multiclass_manager.GetSecondaryPetRoster(caster->CastToClient())) { + caster->SpellOnTarget(spell_id, pet); + } + } #endif } else if(members[z] != nullptr) @@ -841,6 +847,11 @@ void Group::CastGroupSpell(Mob* caster, uint16 spell_id) { #ifdef GROUP_BUFF_PETS if(spells[spell_id].target_type != ST_GroupNoPets && members[z]->GetPet() && members[z]->HasPetAffinity() && !members[z]->GetPet()->IsCharmed()) caster->SpellOnTarget(spell_id, members[z]->GetPet()); + if (spells[spell_id].target_type != ST_GroupNoPets && members[z]->IsClient() && members[z]->HasPetAffinity()) { + for (auto *pet : multiclass_manager.GetSecondaryPetRoster(members[z]->CastToClient())) { + caster->SpellOnTarget(spell_id, pet); + } + } #endif } else LogSpells("Group spell: [{}] is out of range [{}] at distance [{}] from [{}]", members[z]->GetName(), range, distance, caster->GetName()); @@ -2277,6 +2288,13 @@ int8 Group::GetNumberNeedingHealedInGroup(int8 hpr, bool include_pets) { if(members[i]->GetPet() && members[i]->GetPet()->GetHPRatio() <= hpr) { need_healed++; } + if (members[i]->IsClient()) { + for (auto *pet : multiclass_manager.GetSecondaryPetRoster(members[i]->CastToClient())) { + if (pet && pet->GetHPRatio() <= hpr) { + need_healed++; + } + } + } } } } diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index 4b4e3cbc3a..62ad9ce88c 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -18,11 +18,13 @@ #include "guild_mgr.h" #include "common/emu_versions.h" +#include "common/races.h" #include "common/repositories/guild_bank_repository.h" #include "common/repositories/guild_ranks_repository.h" #include "common/servertalk.h" #include "common/strings.h" #include "zone/client.h" +#include "zone/multiclass_manager.h" #include "zone/string_ids.h" #include "zone/worldserver.h" #include "zone/zonedb.h" @@ -759,7 +761,8 @@ void GuildBankManager::SendGuildBank(Client *c) outapp->WriteUInt32(1); outapp->WriteUInt8(0); } - outapp->WriteUInt8(item->IsEquipable(c->GetBaseRace(), c->GetBaseClass()) ? 1 : 0); + const bool useable = (item->Races & GetPlayerRaceBit(c->GetBaseRace())) && (item->Classes & multiclass_manager.GetClassMask(c)); + outapp->WriteUInt8(useable ? 1 : 0); outapp->WriteString(item->Name); } else { @@ -784,7 +787,8 @@ void GuildBankManager::SendGuildBank(Client *c) outapp->WriteUInt32(1); outapp->WriteUInt8(0); } - outapp->WriteUInt8(Item->IsEquipable(c->GetBaseRace(), c->GetBaseClass()) ? 1 : 0); + const bool useable = (Item->Races & GetPlayerRaceBit(c->GetBaseRace())) && (Item->Classes & multiclass_manager.GetClassMask(c)); + outapp->WriteUInt8(useable ? 1 : 0); outapp->WriteString(Item->Name); } else { @@ -871,7 +875,7 @@ void GuildBankManager::SendGuildBank(Client *c) continue; } - bool useable = item->IsEquipable(c->GetBaseRace(), c->GetBaseClass()); + bool useable = (item->Races & GetPlayerRaceBit(c->GetBaseRace())) && (item->Classes & multiclass_manager.GetClassMask(c)); auto outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankItemUpdate_Struct)); auto gbius = (GuildBankItemUpdate_Struct *) outapp->pBuffer; @@ -1716,7 +1720,7 @@ void GuildBankManager::SendGuildBankItemUpdate(uint32 guild_id, int32 slot_id, u gbius.icon_id = item_data ? item_data->Icon : 0; gbius.display = display; gbius.allow_merge = item_data ? item_data->Stackable : false; - gbius.is_useable = item_data ? item_data->IsEquipable(c->GetRace(), c->GetClass()) : false; + gbius.is_useable = item_data ? ((item_data->Races & GetPlayerRaceBit(c->GetRace())) && (item_data->Classes & multiclass_manager.GetClassMask(c))) : false; gbius.quantity = item.quantity; strn0cpy(gbius.item_name, item_data ? item_data->Name : "", sizeof(gbius.item_name)); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index e97c8e5865..4b87377f3c 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -24,6 +24,7 @@ #include "common/repositories/character_corpse_items_repository.h" #include "common/strings.h" #include "zone/bot.h" +#include "zone/multiclass_manager.h" #include "zone/queryserv.h" #include "zone/quest_parser_collection.h" #include "zone/worldserver.h" @@ -32,6 +33,68 @@ extern WorldServer worldserver; extern QueryServ *QServ; +namespace { +bool CheckMulticlassEquipPermission( + Client *client, + const EQ::ItemInstance *inst, + int16 equipment_slot, + EQ::InventoryProfile::SwapItemFailState &fail_state +) +{ + if (!inst || !EQ::ValueWithin(equipment_slot, EQ::invslot::EQUIPMENT_BEGIN, EQ::invslot::EQUIPMENT_END)) { + return true; + } + + if (!inst->IsSlotAllowed(equipment_slot)) { + fail_state = EQ::InventoryProfile::swapNotAllowed; + return false; + } + + if (!multiclass_manager.CanUseItem(client, inst)) { + fail_state = EQ::InventoryProfile::swapRaceClass; + return false; + } + + return true; +} + +bool ApplyMulticlassItemPresentation(Client *client, EQ::ItemInstance *inst, uint32 class_mask) +{ + if (!client || !inst || !class_mask) { + return false; + } + + bool changed = false; + auto *item = const_cast(inst->GetItem()); + if ( + item && + (item->Classes & class_mask) && + multiclass_manager.CanUseItem(client, inst) + ) { + const auto expanded_classes = item->Classes | class_mask; + if (expanded_classes != item->Classes) { + item->Classes = expanded_classes; + changed = true; + } + } + + for (int augment_index = EQ::invaug::SOCKET_BEGIN; augment_index <= EQ::invaug::SOCKET_END; ++augment_index) { + auto *augment = inst->GetAugment(augment_index); + if (augment) { + changed = ApplyMulticlassItemPresentation(client, augment, class_mask) || changed; + } + } + + for (auto &[slot_id, child] : *inst->GetContents()) { + if (child) { + changed = ApplyMulticlassItemPresentation(client, child, class_mask) || changed; + } + } + + return changed; +} +} + // @merth: this needs to be touched up uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { if (itemnum == 0) @@ -258,6 +321,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 augments[EQ::invaug::SOCKET_COUNT] = { aug1, aug2, aug3, aug4, aug5, aug6 }; uint32 classes = item->Classes; + const uint32 multiclass_class_mask = multiclass_manager.GetClassMask(this); uint32 races = item->Races; uint32 slots = item->Slots; bool enforce_wearable = RuleB(Inventory, EnforceAugmentWear); @@ -451,7 +515,8 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, if(enforce_usable) { // check for class usability - if(item->Classes && !(classes &= augtest->Classes)) { + classes &= augtest->Classes; + if(item->Classes && !(classes & multiclass_class_mask)) { Message( Chat::Red, fmt::format( @@ -1198,7 +1263,7 @@ bool Client::TryStacking(EQ::ItemInstance* item, uint8 type, bool try_worn, bool bool Client::AutoPutLootInInventory(EQ::ItemInstance& inst, bool try_worn, bool try_cursor, LootItem** bag_item_data) { // #1: Try to auto equip - if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel <= level && (!inst.GetItem()->Attuneable || inst.IsAttuned()) && inst.GetItem()->ItemType != EQ::item::ItemTypeAugmentation) { + if (try_worn && multiclass_manager.CanUseItem(this, &inst) && inst.GetItem()->ReqLevel <= level && (!inst.GetItem()->Attuneable || inst.IsAttuned()) && inst.GetItem()->ItemType != EQ::item::ItemTypeAugmentation) { for (int16 i = EQ::invslot::EQUIPMENT_BEGIN; i <= EQ::invslot::EQUIPMENT_END; i++) { if ((((uint64)1 << i) & GetInv().GetLookup()->PossessionsBitmask) == 0) continue; @@ -2131,6 +2196,22 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } else { // Not dealing with charges - just do direct swap + EQ::InventoryProfile::SwapItemFailState fail_state = EQ::InventoryProfile::swapInvalid; + if ( + !CheckMulticlassEquipPermission(this, src_inst, dst_slot_id, fail_state) || + !CheckMulticlassEquipPermission(this, dst_inst, src_slot_id, fail_state) + ) { + const char* fail_message = "The selected slot was invalid."; + if (fail_state == EQ::InventoryProfile::swapRaceClass || fail_state == EQ::InventoryProfile::swapDeity) { + 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."; + } + + Message(Chat::Red, "%s", fail_message); + return false; + } + if (src_inst && (dst_slot_id <= EQ::invslot::EQUIPMENT_END) && dst_slot_id >= EQ::invslot::EQUIPMENT_BEGIN) { if (src_inst->GetItem()->Attuneable) { src_inst->SetAttuned(true); @@ -2147,8 +2228,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { SetMaterial(dst_slot_id,src_inst->GetItem()->ID); } - EQ::InventoryProfile::SwapItemFailState fail_state = EQ::InventoryProfile::swapInvalid; - if (!m_inv.SwapItem(src_slot_id, dst_slot_id, fail_state, GetBaseRace(), GetBaseClass(), GetDeity(), GetLevel())) { + fail_state = EQ::InventoryProfile::swapInvalid; + if (!m_inv.SwapItem(src_slot_id, dst_slot_id, fail_state, GetBaseRace(), Class::None, GetDeity(), GetLevel())) { const char* fail_message = "The selected slot was invalid."; if (fail_state == EQ::InventoryProfile::swapRaceClass || fail_state == EQ::InventoryProfile::swapDeity) fail_message = "Your class, deity and/or race may not equip that item."; @@ -3021,6 +3102,26 @@ uint32 Client::GetEquipmentColor(uint8 material_slot) const return 0; } +EQ::ItemInstance* Client::CloneItemForMulticlassPresentation(const EQ::ItemInstance* inst) +{ + if (!inst) { + return nullptr; + } + + const auto multiclass_class_mask = multiclass_manager.GetClassMask(this); + const auto base_class_mask = GetPlayerClassBit(GetBaseClass()); + if (!multiclass_class_mask || !(multiclass_class_mask & ~base_class_mask)) { + return nullptr; + } + + auto *presentation_inst = inst->Clone(); + if (presentation_inst && !ApplyMulticlassItemPresentation(this, presentation_inst, multiclass_class_mask)) { + safe_delete(presentation_inst); + } + + return presentation_inst; +} + // Send an item packet (including all subitems of the item) void Client::SendItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPacketType packet_type) { @@ -3065,7 +3166,8 @@ void Client::SendItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPac SendItemPowerTransport(inst); // Serialize item into |-delimited string (Titanium- uses '|' delimiter .. newer clients use pure data serialization) - std::string packet = inst->Serialize(slot_id); + auto *presentation_inst = CloneItemForMulticlassPresentation(inst); + std::string packet = (presentation_inst ? presentation_inst : inst)->Serialize(slot_id); EmuOpcode opcode = OP_Unknown; EQApplicationPacket* outapp = nullptr; @@ -3082,6 +3184,7 @@ void Client::SendItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPac DumpPacket(outapp); #endif FastQueuePacket(&outapp); + safe_delete(presentation_inst); } static int16 BandolierSlotToWeaponSlot(int BandolierSlot) diff --git a/zone/mob.cpp b/zone/mob.cpp index 8c2a755098..faf087a0ef 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -27,6 +27,7 @@ #include "zone/bot.h" #include "zone/dialogue_window.h" #include "zone/mob_movement_manager.h" +#include "zone/multiclass_manager.h" #include "zone/quest_parser_collection.h" #include "zone/string_ids.h" #include "zone/water_map.h" @@ -1007,6 +1008,10 @@ int64 Mob::GetSpellHPBonuses() { bool Mob::IsIntelligenceCasterClass() const { + if (IsClient() && multiclass_manager.IsIntCaster(CastToClient())) { + return true; + } + switch (GetClass()) { case Class::ShadowKnight: case Class::Bard: @@ -1076,6 +1081,10 @@ bool Mob::IsWarriorClass() const bool Mob::IsWisdomCasterClass() const { + if (IsClient() && multiclass_manager.IsWisCaster(CastToClient())) { + return true; + } + switch (GetClass()) { case Class::Cleric: case Class::Paladin: @@ -4516,6 +4525,13 @@ Mob* Mob::GetOwnerOrSelf() return m; } + if ( + m->IsClient() && + multiclass_manager.IsPetRosterMember(m->CastToClient(), this) + ) { + return m; + } + if (IsNPC() && CastToNPC()->GetSwarmInfo()){ return CastToNPC()->GetSwarmInfo()->GetOwner(); } @@ -4531,6 +4547,14 @@ Mob* Mob::GetOwner() { return m; } + if ( + m && + m->IsClient() && + multiclass_manager.IsPetRosterMember(m->CastToClient(), this) + ) { + return m; + } + if(IsNPC() && CastToNPC()->GetSwarmInfo()){ return CastToNPC()->GetSwarmInfo()->GetOwner(); } diff --git a/zone/pets.cpp b/zone/pets.cpp index 029e69b33a..32bae06a58 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -26,6 +26,7 @@ #include "zone/client.h" #include "zone/entity.h" #include "zone/mob.h" +#include "zone/multiclass_manager.h" #include "zone/zonedb.h" #include @@ -81,9 +82,15 @@ void Mob::MakePet(uint16 spell_id, const char* pettype, const char *petname) { void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, const char *petname, float in_size) { // Sanity and early out checking first. - if(HasPet() || pettype == nullptr) + if(pettype == nullptr) return; + if (HasPet()) { + if (!IsClient() || !multiclass_manager.CanCreateAdditionalPet(CastToClient())) { + return; + } + } + int16 act_power = 0; // The actual pet power we'll use. if (petpower == -1) { if (IsClient()) { @@ -281,7 +288,9 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, npc->size = in_size; entity_list.AddNPC(npc, true, true); - SetPetID(npc->GetID()); + if (!IsClient() || !multiclass_manager.RegisterPet(CastToClient(), npc)) { + SetPetID(npc->GetID()); + } // We need to handle PetType 5 (petHatelist), add the current target to the hatelist of the pet if (record.petcontrol == PetType::TargetLock) diff --git a/zone/raids.cpp b/zone/raids.cpp index eb8acd73cb..17c5d03a08 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -27,6 +27,7 @@ #include "zone/entity.h" #include "zone/groups.h" #include "zone/mob.h" +#include "zone/multiclass_manager.h" #include "zone/queryserv.h" #include "zone/raids.h" #include "zone/string_ids.h" @@ -674,6 +675,11 @@ void Raid::CastGroupSpell(Mob* caster, uint16 spellid, uint32 gid) if (spells[spellid].target_type != ST_GroupNoPets && caster->GetPet() && caster->HasPetAffinity() && !caster->GetPet()->IsCharmed()) { caster->SpellOnTarget(spellid, caster->GetPet()); } + if (spells[spellid].target_type != ST_GroupNoPets && caster->IsClient() && caster->HasPetAffinity()) { + for (auto *pet : multiclass_manager.GetSecondaryPetRoster(caster->CastToClient())) { + caster->SpellOnTarget(spellid, pet); + } + } #endif } else if (m.member != nullptr && m.group_number == gid) { @@ -686,6 +692,11 @@ void Raid::CastGroupSpell(Mob* caster, uint16 spellid, uint32 gid) !m.member->GetPet()->IsCharmed()) { caster->SpellOnTarget(spellid, m.member->GetPet()); } + if (spells[spellid].target_type != ST_GroupNoPets && m.member->IsClient() && m.member->HasPetAffinity()) { + for (auto *pet : multiclass_manager.GetSecondaryPetRoster(m.member->CastToClient())) { + caster->SpellOnTarget(spellid, pet); + } + } #endif } else { diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 466ab7d589..f66c8edcac 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -23,6 +23,7 @@ #include "zone/client.h" #include "zone/entity.h" #include "zone/lua_parser.h" +#include "zone/multiclass_manager.h" #include "zone/npc.h" #include "zone/string_ids.h" @@ -328,9 +329,14 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) return; } + const bool has_bard_class = multiclass_manager.HasClass(this, Class::Bard); + const bool has_berserker_class = multiclass_manager.HasClass(this, Class::Berserker); + const bool has_monk_class = multiclass_manager.HasClass(this, Class::Monk); + const bool has_rogue_class = multiclass_manager.HasClass(this, Class::Rogue); + // make sure were actually able to use such an attack. (Bards can throw while casting. ~Kayen confirmed on live 1/22) if ( - (spellend_timer.Enabled() && GetClass() != Class::Bard) || + (spellend_timer.Enabled() && !has_bard_class) || IsFeared() || IsStunned() || IsMezzed() || @@ -461,7 +467,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) CheckIncreaseSkill(EQ::skills::SkillFrenzy, GetTarget(), 10); DoAnim(anim1HWeapon, 0, false); - if (GetClass() == Class::Berserker) { + if (has_berserker_class) { int chance = GetLevel() * 2 + GetSkill(EQ::skills::SkillFrenzy); if (zone->random.Roll0(450) < chance) { @@ -496,19 +502,17 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) return; } - const uint8 class_id = GetClass(); - // Warrior, Ranger, Monk, Beastlord, and Berserker can kick always const uint32 allowed_kick_classes = RuleI(Combat, ExtraAllowedKickClassesBitmask); + const uint32 class_mask = multiclass_manager.GetClassMask(this); + const uint32 innate_kick_classes = + GetPlayerClassBit(Class::Warrior) | + GetPlayerClassBit(Class::Ranger) | + GetPlayerClassBit(Class::Monk) | + GetPlayerClassBit(Class::Beastlord) | + GetPlayerClassBit(Class::Berserker); - const bool can_use_kick = ( - class_id == Class::Warrior || - class_id == Class::Ranger || - class_id == Class::Monk || - class_id == Class::Beastlord || - class_id == Class::Berserker || - allowed_kick_classes & GetPlayerClassBit(class_id) - ); + const bool can_use_kick = ((innate_kick_classes | allowed_kick_classes) & class_mask) != 0; bool found_skill = false; @@ -535,7 +539,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) } } - if (class_id == Class::Monk) { + if (has_monk_class) { reuse_time = MonkSpecialAttack(GetTarget(), ca_atk->m_skill) - 1 - skill_reduction; // Live AA - Technique of Master Wu @@ -600,7 +604,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) if ( ca_atk->m_atk == 100 && ca_atk->m_skill == EQ::skills::SkillBackstab && - class_id == Class::Rogue + has_rogue_class ) { reuse_time = BackstabReuseTime - 1 - skill_reduction; TryBackstab(GetTarget(), reuse_time); @@ -1593,7 +1597,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 } if(!IsAttackAllowed(other) || - (IsCasting() && GetClass() != Class::Bard) || + (IsCasting() && !(IsClient() && multiclass_manager.HasClass(CastToClient(), Class::Bard))) || IsSitting() || (DivineAura() && !GetGM()) || IsStunned() || @@ -2058,20 +2062,13 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) uint16 skill_to_use = -1; if (skill == -1){ - switch(GetClass()){ - case Class::Warrior: - case Class::Ranger: - case Class::Beastlord: - skill_to_use = EQ::skills::SkillKick; - break; - case Class::Berserker: + if (multiclass_manager.HasClass(this, Class::Berserker) && MaxSkill(EQ::skills::SkillFrenzy)) { skill_to_use = EQ::skills::SkillFrenzy; - break; - case Class::ShadowKnight: - case Class::Paladin: - skill_to_use = EQ::skills::SkillBash; - break; - case Class::Monk: + } + else if (multiclass_manager.HasClass(this, Class::Rogue) && MaxSkill(EQ::skills::SkillBackstab)) { + skill_to_use = EQ::skills::SkillBackstab; + } + else if (multiclass_manager.HasClass(this, Class::Monk)) { if(GetLevel() >= 30) { skill_to_use = EQ::skills::SkillFlyingKick; @@ -2096,10 +2093,19 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) { skill_to_use = EQ::skills::SkillKick; } - break; - case Class::Rogue: - skill_to_use = EQ::skills::SkillBackstab; - break; + } + else if ( + multiclass_manager.HasClass(this, Class::ShadowKnight) || + multiclass_manager.HasClass(this, Class::Paladin) + ) { + skill_to_use = EQ::skills::SkillBash; + } + else if ( + multiclass_manager.HasClass(this, Class::Warrior) || + multiclass_manager.HasClass(this, Class::Ranger) || + multiclass_manager.HasClass(this, Class::Beastlord) + ) { + skill_to_use = EQ::skills::SkillKick; } } @@ -2137,7 +2143,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) ReuseTime = (FrenzyReuseTime - 1) / HasteMod; // bards can do riposte frenzy for some reason - if (!IsRiposte && GetClass() == Class::Berserker) { + if (!IsRiposte && multiclass_manager.HasClass(this, Class::Berserker)) { int chance = GetLevel() * 2 + GetSkill(EQ::skills::SkillFrenzy); if (zone->random.Roll0(450) < chance) AtkRounds++; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 4930f11549..4d9ba9a0ad 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -27,6 +27,7 @@ #include "common/spdat.h" #include "zone/bot.h" #include "zone/lua_parser.h" +#include "zone/multiclass_manager.h" #include "zone/quest_parser_collection.h" #include "zone/string_ids.h" #include "zone/worldserver.h" @@ -38,6 +39,80 @@ extern Zone* zone; extern volatile bool is_zone_loaded; extern WorldServer worldserver; +namespace { + +bool MulticlassRestrictionHasClass(Mob *mob, uint8 class_id) +{ + if (!mob) { + return false; + } + + if (mob->IsClient()) { + return multiclass_manager.HasClass(mob->CastToClient(), class_id); + } + + return mob->GetClass() == class_id; +} + +bool MulticlassRestrictionHasAnyClass(Mob *mob, uint32 class_mask) +{ + if (!mob) { + return false; + } + + if (mob->IsClient()) { + return (multiclass_manager.GetClassMask(mob->CastToClient()) & class_mask) != 0; + } + + return (GetPlayerClassBit(mob->GetClass()) & class_mask) != 0; +} + +bool MulticlassRestrictionIsCasterClass(Mob *mob) +{ + if (!mob) { + return false; + } + + if (mob->IsClient()) { + auto *client = mob->CastToClient(); + return multiclass_manager.IsIntCaster(client) || multiclass_manager.IsWisCaster(client); + } + + return IsCasterClass(mob->GetClass()); +} + +bool MulticlassRestrictionIsNonSpellFighter(Mob *mob) +{ + const uint32 non_spell_fighter_mask = + GetPlayerClassBit(Class::Warrior) | + GetPlayerClassBit(Class::Monk) | + GetPlayerClassBit(Class::Bard) | + GetPlayerClassBit(Class::Rogue) | + GetPlayerClassBit(Class::Berserker); + + return MulticlassRestrictionHasAnyClass(mob, non_spell_fighter_mask); +} + +bool MulticlassRestrictionHasManaClass(Mob *mob) +{ + const uint32 mana_class_mask = + GetPlayerClassBit(Class::Cleric) | + GetPlayerClassBit(Class::Paladin) | + GetPlayerClassBit(Class::Ranger) | + GetPlayerClassBit(Class::ShadowKnight) | + GetPlayerClassBit(Class::Druid) | + GetPlayerClassBit(Class::Shaman) | + GetPlayerClassBit(Class::Necromancer) | + GetPlayerClassBit(Class::Wizard) | + GetPlayerClassBit(Class::Magician) | + GetPlayerClassBit(Class::Enchanter) | + GetPlayerClassBit(Class::Beastlord); + + return MulticlassRestrictionHasAnyClass(mob, mana_class_mask); +} + +} // namespace + // the spell can still fail here, if the buff can't stack // in this case false will be returned, true otherwise @@ -1288,7 +1363,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Summon %s: %s", (effect==SE_Familiar)?"Familiar":"Pet", spell.teleport_zone); #endif - if(GetPet()) + const bool can_create_multiclass_pet = IsClient() && multiclass_manager.CanCreateAdditionalPet(CastToClient()); + if(GetPet() && !can_create_multiclass_pet) { MessageString(Chat::Shout, ONLY_ONE_PET); } @@ -7733,108 +7809,158 @@ bool Mob::PassCastRestriction(int value) break; case IS_CLASS_MELEE_THAT_CAN_BASH_OR_KICK_EXCEPT_BARD: - if ((GetClass() != Class::Bard) && (GetClass() != Class::Rogue) && IsFighterClass(GetClass())) + if ( + MulticlassRestrictionHasAnyClass( + this, + GetPlayerClassBit(Class::Warrior) | + GetPlayerClassBit(Class::Paladin) | + GetPlayerClassBit(Class::Ranger) | + GetPlayerClassBit(Class::ShadowKnight) | + GetPlayerClassBit(Class::Monk) | + GetPlayerClassBit(Class::Beastlord) | + GetPlayerClassBit(Class::Berserker) + ) + ) return true; break; case IS_CLASS_PURE_MELEE: - if (GetClass() == Class::Rogue || GetClass() == Class::Warrior || GetClass() == Class::Berserker || GetClass() == Class::Monk) + if ( + MulticlassRestrictionHasAnyClass( + this, + GetPlayerClassBit(Class::Warrior) | + GetPlayerClassBit(Class::Monk) | + GetPlayerClassBit(Class::Rogue) | + GetPlayerClassBit(Class::Berserker) + ) + ) return true; break; case IS_CLASS_PURE_CASTER: - if (IsINTCasterClass(GetClass())) + if ( + MulticlassRestrictionHasAnyClass( + this, + GetPlayerClassBit(Class::Necromancer) | + GetPlayerClassBit(Class::Wizard) | + GetPlayerClassBit(Class::Magician) | + GetPlayerClassBit(Class::Enchanter) + ) + ) return true; break; case IS_CLASS_HYBRID_CLASS: - if (IsHybridClass(GetClass())) + if ( + MulticlassRestrictionHasAnyClass( + this, + GetPlayerClassBit(Class::Paladin) | + GetPlayerClassBit(Class::Ranger) | + GetPlayerClassBit(Class::ShadowKnight) | + GetPlayerClassBit(Class::Bard) | + GetPlayerClassBit(Class::Beastlord) + ) + ) return true; break; case IS_CLASS_WARRIOR: - if (GetClass() == Class::Warrior) + if (MulticlassRestrictionHasClass(this, Class::Warrior)) return true; break; case IS_CLASS_CLERIC: - if (GetClass() == Class::Cleric) + if (MulticlassRestrictionHasClass(this, Class::Cleric)) return true; break; case IS_CLASS_PALADIN: - if (GetClass() == Class::Paladin) + if (MulticlassRestrictionHasClass(this, Class::Paladin)) return true; break; case IS_CLASS_RANGER: - if (GetClass() == Class::Ranger) + if (MulticlassRestrictionHasClass(this, Class::Ranger)) return true; break; case IS_CLASS_SHADOWKNIGHT: - if (GetClass() == Class::ShadowKnight) + if (MulticlassRestrictionHasClass(this, Class::ShadowKnight)) return true; break; case IS_CLASS_DRUID: - if (GetClass() == Class::Druid) + if (MulticlassRestrictionHasClass(this, Class::Druid)) return true; break; case IS_CLASS_MONK: - if (GetClass() == Class::Monk) + if (MulticlassRestrictionHasClass(this, Class::Monk)) return true; break; case IS_CLASS_BARD2: case IS_CLASS_BARD: - if (GetClass() == Class::Bard) + if (MulticlassRestrictionHasClass(this, Class::Bard)) return true; break; case IS_CLASS_ROGUE: - if (GetClass() == Class::Rogue) + if (MulticlassRestrictionHasClass(this, Class::Rogue)) return true; break; case IS_CLASS_SHAMAN: - if (GetClass() == Class::Shaman) + if (MulticlassRestrictionHasClass(this, Class::Shaman)) return true; break; case IS_CLASS_NECRO: - if (GetClass() == Class::Necromancer) + if (MulticlassRestrictionHasClass(this, Class::Necromancer)) return true; break; case IS_CLASS_MAGE: - if (GetClass() == Class::Magician) + if (MulticlassRestrictionHasClass(this, Class::Magician)) return true; break; case IS_CLASS_ENCHANTER: - if (GetClass() == Class::Enchanter) + if (MulticlassRestrictionHasClass(this, Class::Enchanter)) return true; break; case IS_CLASS_BEASTLORD: - if (GetClass() == Class::Beastlord) + if (MulticlassRestrictionHasClass(this, Class::Beastlord)) return true; break; case IS_CLASS_BERSERKER: - if (GetClass() == Class::Berserker) + if (MulticlassRestrictionHasClass(this, Class::Berserker)) return true; break; case IS_CLASS_CLR_SHM_DRU: - if (IsWISCasterClass(GetClass())) + if ( + MulticlassRestrictionHasAnyClass( + this, + GetPlayerClassBit(Class::Cleric) | + GetPlayerClassBit(Class::Druid) | + GetPlayerClassBit(Class::Shaman) + ) + ) return true; break; case IS_CLASS_NOT_WAR_PAL_SK: - if ((GetClass() != Class::Warrior) && (GetClass() != Class::Paladin) && (GetClass() != Class::ShadowKnight)) + if ( + !MulticlassRestrictionHasAnyClass( + this, + GetPlayerClassBit(Class::Warrior) | + GetPlayerClassBit(Class::Paladin) | + GetPlayerClassBit(Class::ShadowKnight) + ) + ) return true; break; @@ -8121,12 +8247,25 @@ bool Mob::PassCastRestriction(int value) break; case IS_CLASS_KNIGHT_HYBRID_MELEE: - if (IsHybridClass(GetClass()) || IsNonSpellFighterClass(GetClass())) + if ( + MulticlassRestrictionHasAnyClass( + this, + GetPlayerClassBit(Class::Paladin) | + GetPlayerClassBit(Class::Ranger) | + GetPlayerClassBit(Class::ShadowKnight) | + GetPlayerClassBit(Class::Bard) | + GetPlayerClassBit(Class::Beastlord) | + GetPlayerClassBit(Class::Warrior) | + GetPlayerClassBit(Class::Monk) | + GetPlayerClassBit(Class::Rogue) | + GetPlayerClassBit(Class::Berserker) + ) + ) return true; break; case IS_CLASS_WARRIOR_CASTER_PRIEST: - if (IsCasterClass(GetClass()) || GetClass() == Class::Warrior) + if (MulticlassRestrictionIsCasterClass(this) || MulticlassRestrictionHasClass(this, Class::Warrior)) return true; break; @@ -8352,44 +8491,55 @@ bool Mob::PassCastRestriction(int value) case IS_CLASS_CASTER_PRIEST: - if (IsCasterClass(GetClass())) + if (MulticlassRestrictionIsCasterClass(this)) return true; break; case IS_END_OR_MANA_ABOVE_20_PCT: { - if (IsNonSpellFighterClass(GetClass()) && CastToClient()->GetEndurancePercent() >= 20) { + if (MulticlassRestrictionIsNonSpellFighter(this) && IsClient() && CastToClient()->GetEndurancePercent() >= 20) { return true; } - else if (!IsNonSpellFighterClass(GetClass()) && GetManaRatio() >= 20) { + else if ((!MulticlassRestrictionIsNonSpellFighter(this) || MulticlassRestrictionHasManaClass(this)) && GetManaRatio() >= 20) { return true; } break; } case IS_END_OR_MANA_BELOW_10_PCT: { - if (IsNonSpellFighterClass(GetClass()) && CastToClient()->GetEndurancePercent() <= 10) { + if (MulticlassRestrictionIsNonSpellFighter(this) && IsClient() && CastToClient()->GetEndurancePercent() <= 10) { return true; } - else if (!IsNonSpellFighterClass(GetClass()) && GetManaRatio() <= 10) { + else if ((!MulticlassRestrictionIsNonSpellFighter(this) || MulticlassRestrictionHasManaClass(this)) && GetManaRatio() <= 10) { return true; } - else if (IsHybridClass(GetClass()) && CastToClient()->GetEndurancePercent() <= 10) { + else if ( + MulticlassRestrictionHasAnyClass( + this, + GetPlayerClassBit(Class::Paladin) | + GetPlayerClassBit(Class::Ranger) | + GetPlayerClassBit(Class::ShadowKnight) | + GetPlayerClassBit(Class::Bard) | + GetPlayerClassBit(Class::Beastlord) + ) && + IsClient() && + CastToClient()->GetEndurancePercent() <= 10 + ) { return true; } break; } case IS_END_OR_MANA_BELOW_30_PCT: case IS_END_OR_MANA_BELOW_30_PCT2: { - if (IsNonSpellFighterClass(GetClass()) && CastToClient()->GetEndurancePercent() <= 30) { + if (MulticlassRestrictionIsNonSpellFighter(this) && IsClient() && CastToClient()->GetEndurancePercent() <= 30) { return true; } - else if (!IsNonSpellFighterClass(GetClass()) && GetManaRatio() <= 30) { + else if ((!MulticlassRestrictionIsNonSpellFighter(this) || MulticlassRestrictionHasManaClass(this)) && GetManaRatio() <= 30) { return true; } break; } case IS_NOT_CLASS_BARD: - if (GetClass() != Class::Bard) + if (!MulticlassRestrictionHasClass(this, Class::Bard)) return true; break; diff --git a/zone/spells.cpp b/zone/spells.cpp index 08ce49ec2d..ea399f135c 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -86,6 +86,7 @@ #include "zone/live_spell_manager.h" #include "zone/lua_parser.h" #include "zone/mob_movement_manager.h" +#include "zone/multiclass_manager.h" #include "zone/queryserv.h" #include "zone/quest_parser_collection.h" #include "zone/string_ids.h" @@ -103,6 +104,19 @@ extern QueryServ *QServ; using EQ::spells::CastingSlot; +namespace { + +bool IsEffectiveBard(Mob *mob) +{ + if (mob && mob->IsClient()) { + return multiclass_manager.IsBard(mob->CastToClient()); + } + + return mob && mob->GetClass() == Class::Bard; +} + +} + // this is run constantly for every mob void Mob::SpellProcess() { @@ -1060,8 +1074,9 @@ bool Client::CheckFizzle(uint16 spell_id) //Live AA - Spell Casting Expertise, Mastery of the Past no_fizzle_level = aabonuses.MasteryofPast + itembonuses.MasteryofPast + spellbonuses.MasteryofPast; + const auto multiclass_spell_level = multiclass_manager.GetBestSpellLevel(this, spell_id); - if (spells[spell_id].classes[GetClass()-1] < no_fizzle_level) { + if (multiclass_spell_level < no_fizzle_level) { return true; } @@ -1112,7 +1127,7 @@ bool Client::CheckFizzle(uint16 spell_id) } // BARDS ARE SPECIAL - they add both CHA and DEX mods to get casting rates similar to full casters without spec skill - if (GetClass() == Class::Bard) { + if (multiclass_manager.IsBard(this)) { prime_stat_reduction = (GetCHA() - 75 + GetDEX() - 75) / 10.0; } @@ -1141,12 +1156,12 @@ bool Client::CheckFizzle(uint16 spell_id) int par_skill; int act_skill; - par_skill = spells[spell_id].classes[GetClass()-1] * 5 - 10;//IIRC even if you are lagging behind the skill levels you don't fizzle much + par_skill = multiclass_spell_level * 5 - 10;//IIRC even if you are lagging behind the skill levels you don't fizzle much if (par_skill > 235) { par_skill = 235; } - par_skill += spells[spell_id].classes[GetClass()-1]; // maximum of 270 for level 65 spell + par_skill += multiclass_spell_level; // maximum of 270 for level 65 spell act_skill = GetSkill(spells[spell_id].skill); act_skill += GetLevel(); // maximum of whatever the client can cheat @@ -1181,7 +1196,7 @@ bool Client::CheckFizzle(uint16 spell_id) float diff = par_skill + static_cast(spells[spell_id].base_difficulty) - act_skill; // if you have high int/wis you fizzle less, you fizzle more if you are stupid - if (GetClass() == Class::Bard) { + if (multiclass_manager.IsBard(this)) { diff -= (GetCHA() - 110) / 20.0; } else if (IsIntelligenceCasterClass()) { diff -= (GetINT() - 125) / 20.0; @@ -1469,16 +1484,22 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo bool bard_song_mode = false; bool regain_conc = false; Mob *spell_target = entity_list.GetMob(target_id); + const bool multiclass_melody_owns_song_loop = + IsClient() && + slot < CastingSlot::MaxGems && + IsBardSong(spell_id) && + multiclass_manager.HasActiveBardMelody(CastToClient()); + // here we do different things if this is a bard casting a bard song from // a spell bar slot - if(GetClass() == Class::Bard) // bard's can move when casting any spell... + if(IsEffectiveBard(this)) // bard's can move when casting any spell... { if (IsBardSong(spell_id) && slot < CastingSlot::MaxGems) { if (spells[spell_id].buff_duration == 0xFFFF) { LogSpells("Bard song [{}] not applying bard logic because duration. dur=[{}], recast=[{}]", spell_id, spells[spell_id].buff_duration, spells[spell_id].recast_time); } else { - if (IsPulsingBardSong(spell_id)) { + if (IsPulsingBardSong(spell_id) && !multiclass_melody_owns_song_loop) { bardsong = spell_id; bardsong_slot = slot; @@ -1493,8 +1514,13 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo } bardsong_timer.Start(6000); } - LogSpells("Bard song [{}] started: slot [{}], target id [{}]", bardsong, (int)bardsong_slot, bardsong_target_id); - bard_song_mode = true; + if (multiclass_melody_owns_song_loop) { + LogSpells("Bard song [{}] cast as one-shot because Multiclass Melody owns sustained song looping", spell_id); + } + else { + LogSpells("Bard song [{}] started: slot [{}], target id [{}]", bardsong, (int)bardsong_slot, bardsong_target_id); + } + bard_song_mode = !multiclass_melody_owns_song_loop; } } } @@ -2671,7 +2697,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in Group *target_group = entity_list.GetGroupByMob(spell_target); if (target_group) { target_group->CastGroupSpell(this, spell_id); - if (target_group != GetGroup() && GetClass() != Class::Bard) { + if (target_group != GetGroup() && !IsEffectiveBard(this)) { SpellOnTarget(spell_id, this); } } @@ -2701,6 +2727,11 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in if (spells[spell_id].target_type != ST_GroupNoPets && GetPet() && HasPetAffinity() && !GetPet()->IsCharmed()) { SpellOnTarget(spell_id, GetPet()); } + if (spells[spell_id].target_type != ST_GroupNoPets && IsClient() && HasPetAffinity()) { + for (auto *pet : multiclass_manager.GetSecondaryPetRoster(CastToClient())) { + SpellOnTarget(spell_id, pet); + } + } #endif } @@ -2710,6 +2741,11 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in if (spells[spell_id].target_type != ST_GroupNoPets && spell_target->GetPet() && spell_target->HasPetAffinity() && !spell_target->GetPet()->IsCharmed()) { SpellOnTarget(spell_id, spell_target->GetPet()); } + if (spells[spell_id].target_type != ST_GroupNoPets && spell_target->IsClient() && spell_target->HasPetAffinity()) { + for (auto *pet : multiclass_manager.GetSecondaryPetRoster(spell_target->CastToClient())) { + SpellOnTarget(spell_id, pet); + } + } #endif } } @@ -2803,7 +2839,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in } } //handle bard AA and Discipline recast timers when singing - if (GetClass() == Class::Bard && spell_id != casting_spell_id && timer != 0xFFFFFFFF) { + if (IsEffectiveBard(this) && spell_id != casting_spell_id && timer != 0xFFFFFFFF) { CastToClient()->GetPTimers().Start(timer, timer_duration); LogSpells("Spell [{}]: Setting BARD custom reuse timer [{}] to [{}]", spell_id, casting_spell_timer, casting_spell_timer_duration); } @@ -3592,7 +3628,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid ); if (caster) { - if (caster->IsClient() && RuleB(Client, UseLiveBlockedMessage) && caster->GetClass() != Class::Bard) { + if (caster->IsClient() && RuleB(Client, UseLiveBlockedMessage) && !IsEffectiveBard(caster)) { caster->Message( Chat::Red, fmt::format( @@ -3604,7 +3640,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid ); } - if (caster->IsBot() && RuleB(Bots, BotsUseLiveBlockedMessage) && caster->GetClass() != Class::Bard) { + if (caster->IsBot() && RuleB(Bots, BotsUseLiveBlockedMessage) && !IsEffectiveBard(caster)) { caster->GetOwner()->Message( Chat::SpellFailure, fmt::format( @@ -6013,6 +6049,10 @@ void Client::ScribeSpell(uint16 spell_id, int slot, bool update_client, bool def } LogSpells("Spell [{}] scribed into spell book slot [{}]", spell_id, slot); + if (update_client && !defer_save) { + multiclass_manager.SendNativeSpellLevelSnapshot(this); + } + if (update_client) { MemorizeSpell(slot, spell_id, memSpellScribing); } @@ -6152,6 +6192,19 @@ uint32 Client::GetHighestScribedSpellinSpellGroup(uint32 spell_group) std::unordered_map> Client::LoadSpellGroupCache(uint8 min_level, uint8 max_level) { std::unordered_map> spell_group_cache; + std::vector class_conditions; + + for (const auto class_id : multiclass_manager.GetClassSlots(this)) { + if (!IsPlayerClass(class_id)) { + continue; + } + + class_conditions.emplace_back(fmt::format("classes{} BETWEEN {} AND {}", class_id, min_level, max_level)); + } + + if (class_conditions.empty()) { + return spell_group_cache; + } const auto query = fmt::format( "SELECT a.spellgroup, a.id, a.rank " @@ -6161,8 +6214,8 @@ std::unordered_map> Client::LoadSpellGroupCache(uint "FROM spells_new " "GROUP BY spellgroup) " "b ON a.spellgroup = b.spellgroup AND a.rank = b.rank " - "WHERE a.spellgroup IN (SELECT DISTINCT spellgroup FROM spells_new WHERE spellgroup != 0 and classes{} BETWEEN {} AND {}) ORDER BY `rank` DESC", - m_pp.class_, min_level, max_level + "WHERE a.spellgroup IN (SELECT DISTINCT spellgroup FROM spells_new WHERE spellgroup != 0 AND ({})) ORDER BY `rank` DESC", + Strings::Join(class_conditions, " OR ") ); auto results = content_db.QueryDatabase(query); @@ -6519,7 +6572,7 @@ bool Mob::UseBardSpellLogic(uint16 spell_id, int slot) ( IsValidSpell(spell_id) && slot != -1 && - GetClass() == Class::Bard && + IsEffectiveBard(this) && slot <= EQ::spells::SPELL_GEM_COUNT && IsBardSong(spell_id) ); @@ -6527,7 +6580,7 @@ bool Mob::UseBardSpellLogic(uint16 spell_id, int slot) int Mob::GetCasterLevel(uint16 spell_id) { int level = GetLevel(); - if (GetClass() == Class::Bard) { + if (IsEffectiveBard(this)) { // Bards receive effective casting level increases to resists/effect. They don't receive benefit from spells like intellectual superiority, however. level += itembonuses.effective_casting_level + aabonuses.effective_casting_level; } else { @@ -7411,9 +7464,9 @@ bool Mob::CheckItemRaceClassDietyRestrictionsOnCast(uint32 inventory_slot) { } //Added to prevent MQ2 exploitation of equipping normally-unequippable/clickable items with effects and clicking them for benefits. - EQ::ItemInstance *itm = CastToClient()->GetInv().GetItem(inventory_slot); - int bitmask = 1; - bitmask = bitmask << (CastToClient()->GetClass() - 1); + auto *client = CastToClient(); + EQ::ItemInstance *itm = client->GetInv().GetItem(inventory_slot); + const auto bitmask = multiclass_manager.GetClassMask(client); if (itm && itm->GetItem()->Classes != 65535) { if ((itm->GetItem()->Click.Type == EQ::item::ItemEffectEquipClick) && !(itm->GetItem()->Classes & bitmask)) { if (CastToClient()->ClientVersion() < EQ::versions::ClientVersion::SoF) { diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index a314936ca3..88f806c384 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -38,6 +38,7 @@ #include "zone/entity.h" #include "zone/guild_mgr.h" #include "zone/mob.h" +#include "zone/multiclass_manager.h" #include "zone/petitions.h" #include "zone/queryserv.h" #include "zone/quest_parser_collection.h" @@ -66,6 +67,39 @@ void Shutdown(); // QuestParserCollection *parse = 0; +namespace { +void ApplyOrFadePetSpell(Mob *owner, uint16 spell_id, bool fade) +{ + if (!owner) { + return; + } + + if (owner->HasPet()) { + if (fade) { + owner->GetPet()->BuffFadeBySpellID(spell_id); + } else { + owner->GetPet()->ApplySpellBuff(spell_id); + } + } + + if (!owner->IsClient()) { + return; + } + + for (auto *pet : multiclass_manager.GetSecondaryPetRoster(owner->CastToClient())) { + if (!pet) { + continue; + } + + if (fade) { + pet->BuffFadeBySpellID(spell_id); + } else { + pet->ApplySpellBuff(spell_id); + } + } +} +} + WorldServer::WorldServer() { cur_groupid = 0; @@ -2585,9 +2619,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) b->ApplySpellBuff(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (b->HasPet()) { - b->GetPet()->ApplySpellBuff(s->spell_id); - } + ApplyOrFadePetSpell(b, s->spell_id, false); } } } @@ -2599,9 +2631,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (c->HasPet()) { - c->GetPet()->ApplySpellBuff(s->spell_id); - } + ApplyOrFadePetSpell(c, s->spell_id, false); } break; @@ -2613,9 +2643,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) b->BuffFadeBySpellID(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (b->HasPet()) { - b->GetPet()->BuffFadeBySpellID(s->spell_id); - } + ApplyOrFadePetSpell(b, s->spell_id, true); } } } @@ -2627,9 +2655,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (c->HasPet()) { - c->GetPet()->BuffFadeBySpellID(s->spell_id); - } + ApplyOrFadePetSpell(c, s->spell_id, true); } break; @@ -2652,9 +2678,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) m->ApplySpellBuff(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (m->HasPet()) { - m->GetPet()->ApplySpellBuff(s->spell_id); - } + ApplyOrFadePetSpell(m, s->spell_id, false); } break; @@ -2662,9 +2686,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) m->BuffFadeBySpellID(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (m->HasPet()) { - m->GetPet()->BuffFadeBySpellID(s->spell_id); - } + ApplyOrFadePetSpell(m, s->spell_id, true); } break; @@ -2689,9 +2711,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) m.member->ApplySpellBuff(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (m.member->HasPet()) { - m.member->GetPet()->ApplySpellBuff(s->spell_id); - } + ApplyOrFadePetSpell(m.member, s->spell_id, false); } break; @@ -2699,9 +2719,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) m.member->BuffFadeBySpellID(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (m.member->HasPet()) { - m.member->GetPet()->BuffFadeBySpellID(s->spell_id); - } + ApplyOrFadePetSpell(m.member, s->spell_id, true); } break; @@ -2721,9 +2739,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) b->ApplySpellBuff(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (b->HasPet()) { - b->GetPet()->ApplySpellBuff(s->spell_id); - } + ApplyOrFadePetSpell(b, s->spell_id, false); } } } @@ -2735,9 +2751,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (c.second->HasPet()) { - c.second->GetPet()->ApplySpellBuff(s->spell_id); - } + ApplyOrFadePetSpell(c.second, s->spell_id, false); } break; @@ -2749,9 +2763,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) b->BuffFadeBySpellID(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (b->HasPet()) { - b->GetPet()->BuffFadeBySpellID(s->spell_id); - } + ApplyOrFadePetSpell(b, s->spell_id, true); } } } @@ -2763,9 +2775,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (c.second->HasPet()) { - c.second->GetPet()->BuffFadeBySpellID(s->spell_id); - } + ApplyOrFadePetSpell(c.second, s->spell_id, true); } break; @@ -2784,9 +2794,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) b->ApplySpellBuff(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (b->HasPet()) { - b->GetPet()->ApplySpellBuff(s->spell_id); - } + ApplyOrFadePetSpell(b, s->spell_id, false); } } } @@ -2798,9 +2806,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (c.second->HasPet()) { - c.second->GetPet()->ApplySpellBuff(s->spell_id); - } + ApplyOrFadePetSpell(c.second, s->spell_id, false); } break; @@ -2812,9 +2818,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) b->BuffFadeBySpellID(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (b->HasPet()) { - b->GetPet()->BuffFadeBySpellID(s->spell_id); - } + ApplyOrFadePetSpell(b, s->spell_id, true); } } } @@ -2826,9 +2830,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (c.second->HasPet()) { - c.second->GetPet()->BuffFadeBySpellID(s->spell_id); - } + ApplyOrFadePetSpell(c.second, s->spell_id, true); } break; @@ -2847,9 +2849,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) b->ApplySpellBuff(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (b->HasPet()) { - b->GetPet()->ApplySpellBuff(s->spell_id); - } + ApplyOrFadePetSpell(b, s->spell_id, false); } } } @@ -2861,9 +2861,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (c->HasPet()) { - c->GetPet()->ApplySpellBuff(s->spell_id); - } + ApplyOrFadePetSpell(c, s->spell_id, false); } break; @@ -2875,9 +2873,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) b->BuffFadeBySpellID(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (b->HasPet()) { - b->GetPet()->BuffFadeBySpellID(s->spell_id); - } + ApplyOrFadePetSpell(b, s->spell_id, true); } } } @@ -2889,9 +2885,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (c->HasPet()) { - c->GetPet()->BuffFadeBySpellID(s->spell_id); - } + ApplyOrFadePetSpell(c, s->spell_id, true); } break; @@ -3235,9 +3229,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) b->ApplySpellBuff(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (b->HasPet()) { - b->GetPet()->ApplySpellBuff(s->spell_id); - } + ApplyOrFadePetSpell(b, s->spell_id, false); } } } @@ -3249,9 +3241,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (c.second->HasPet()) { - c.second->GetPet()->ApplySpellBuff(s->spell_id); - } + ApplyOrFadePetSpell(c.second, s->spell_id, false); } } else if (s->update_type == WWSpellUpdateType_Remove) { c.second->BuffFadeBySpellID(s->spell_id); @@ -3261,9 +3251,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) b->BuffFadeBySpellID(s->spell_id); if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (b->HasPet()) { - b->GetPet()->BuffFadeBySpellID(s->spell_id); - } + ApplyOrFadePetSpell(b, s->spell_id, true); } } } @@ -3275,9 +3263,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } if (RuleB(Zone, AllowCrossZoneSpellsOnPets)) { - if (c.second->HasPet()) { - c.second->GetPet()->BuffFadeBySpellID(s->spell_id); - } + ApplyOrFadePetSpell(c.second, s->spell_id, true); } } } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 24414a2d02..529b50095d 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -67,17 +67,222 @@ #include "zone/corpse.h" #include "zone/groups.h" #include "zone/merc.h" +#include "zone/multiclass_manager.h" +#include "zone/npc.h" #include "zone/zone.h" #include "fmt/format.h" +#include #include #include +#include extern Zone* zone; ZoneDatabase database; ZoneDatabase content_db; +namespace { + +constexpr int MulticlassPetInfoSlotBegin = 10; +constexpr int MulticlassPetInfoSlotEnd = 12; + +void CapturePetInfo(NPC *pet, PetInfo &pet_info) +{ + memset(&pet_info, 0, sizeof(PetInfo)); + if (!pet || !pet->GetPetSpellID()) { + return; + } + + pet_info.SpellID = pet->GetPetSpellID(); + pet_info.HP = pet->GetHP(); + pet_info.Mana = pet->GetMana(); + pet->GetPetState(pet_info.Buffs, pet_info.Items, pet_info.Name); + pet_info.petpower = pet->GetPetPower(); + pet_info.size = pet->GetSize(); + pet_info.taunting = pet->IsTaunting(); +} + +void AppendPetInfoRows( + Client *client, + int pet_info_type, + const PetInfo &pet_state, + std::vector &pet_infos, + std::vector &pet_buffs, + std::vector &inventory +) +{ + if (!client || !client->CharacterID() || !pet_state.SpellID) { + return; + } + + auto pet_info = CharacterPetInfoRepository::NewEntity(); + pet_info.char_id = client->CharacterID(); + pet_info.pet = pet_info_type; + pet_info.petname = pet_state.Name; + pet_info.petpower = pet_state.petpower; + pet_info.spell_id = pet_state.SpellID; + pet_info.hp = pet_state.HP; + pet_info.mana = pet_state.Mana; + pet_info.size = pet_state.size; + pet_info.taunting = pet_state.taunting ? 1 : 0; + pet_infos.push_back(pet_info); + + const uint32 max_slots = ( + RuleI(Spells, MaxTotalSlotsPET) > PET_BUFF_COUNT ? + PET_BUFF_COUNT : + RuleI(Spells, MaxTotalSlotsPET) + ); + + for (int slot_id = 0; slot_id < max_slots; slot_id++) { + if (!IsValidSpell(pet_state.Buffs[slot_id].spellid)) { + continue; + } + + auto pet_buff = CharacterPetBuffsRepository::NewEntity(); + pet_buff.char_id = client->CharacterID(); + pet_buff.pet = pet_info_type; + pet_buff.slot = slot_id; + pet_buff.spell_id = pet_state.Buffs[slot_id].spellid; + pet_buff.caster_level = pet_state.Buffs[slot_id].level; + pet_buff.ticsremaining = pet_state.Buffs[slot_id].duration; + pet_buff.counters = pet_state.Buffs[slot_id].counters; + pet_buff.instrument_mod = pet_state.Buffs[slot_id].bard_modifier; + pet_buffs.push_back(pet_buff); + } + + for ( + int slot_id = EQ::invslot::EQUIPMENT_BEGIN; + slot_id <= EQ::invslot::EQUIPMENT_END; + slot_id++ + ) { + if (!pet_state.Items[slot_id]) { + continue; + } + + auto item = CharacterPetInventoryRepository::NewEntity(); + item.char_id = client->CharacterID(); + item.pet = pet_info_type; + item.slot = slot_id; + item.item_id = pet_state.Items[slot_id]; + inventory.push_back(item); + } +} + +bool MulticlassPetStateSchemaAvailable() +{ + auto results = database.QueryDatabase("SHOW TABLES LIKE 'custom_multiclass_pet_state'"); + return results.Success() && results.RowCount() > 0; +} + +std::string BuildMulticlassPetStateValue(Client *client, int pet_info_type, NPC *pet, uint16 focused_pet_id) +{ + if (!client || !client->CharacterID() || !pet || !pet->GetPetSpellID()) { + return ""; + } + + const auto guard_point = pet->GetGuardPoint(); + return fmt::format( + "({}, {}, {}, '{}', {}, {}, {}, {}, {}, {}, {}, {:.3f}, {:.3f}, {:.3f}, {:.3f}, UNIX_TIMESTAMP())", + client->CharacterID(), + pet_info_type, + pet->GetPetSpellID(), + Strings::Escape(pet->GetCleanName()), + pet->GetPetOrder(), + pet->IsHeld() ? 1 : 0, + pet->IsGHeld() ? 1 : 0, + pet->IsNoCast() ? 1 : 0, + pet->GetID() == focused_pet_id ? 1 : 0, + pet->IsPetStop() ? 1 : 0, + pet->IsPetRegroup() ? 1 : 0, + guard_point.x, + guard_point.y, + guard_point.z, + guard_point.w + ); +} + +void ApplyMulticlassPetStateRow(Client *client, NPC *pet, int pet_info_type) +{ + if (!client || !client->CharacterID() || !pet || !MulticlassPetStateSchemaAvailable()) { + return; + } + + auto results = database.QueryDatabase( + fmt::format( + "SELECT `pet_order`, `held`, `gheld`, `nocast`, `focused`, `pet_stop`, `pet_regroup`, " + "`guard_x`, `guard_y`, `guard_z`, `guard_heading` " + "FROM `custom_multiclass_pet_state` " + "WHERE `character_id` = {} AND `pet_slot` = {} LIMIT 1", + client->CharacterID(), + pet_info_type + ) + ); + + if (!results.Success() || results.RowCount() == 0) { + return; + } + + auto row = results.begin(); + const uint8 pet_order = Strings::ToUnsignedInt(row[0]); + const bool held = Strings::ToBool(row[1]); + const bool gheld = Strings::ToBool(row[2]); + const bool nocast = Strings::ToBool(row[3]); + const bool focused = Strings::ToBool(row[4]); + const bool pet_stop = Strings::ToBool(row[5]); + const bool pet_regroup = Strings::ToBool(row[6]); + const float guard_x = Strings::ToFloat(row[7]); + const float guard_y = Strings::ToFloat(row[8]); + const float guard_z = Strings::ToFloat(row[9]); + const float guard_heading = Strings::ToFloat(row[10]); + + pet->SetPetOrder(pet_order); + pet->SetHeld(held); + pet->SetGHeld(gheld); + pet->SetNoCast(nocast); + pet->SetPetStop(pet_stop); + pet->SetPetRegroup(pet_regroup); + + if (guard_heading != 0.0f) { + pet->SaveGuardSpot(glm::vec4(guard_x, guard_y, guard_z, guard_heading)); + } else if (pet_order != PetOrder::Guard) { + pet->SaveGuardSpot(true); + } + + if (focused) { + multiclass_manager.SetFocusedPet(client, pet->GetID()); + } +} + +std::unordered_set GetRosterPetIds(Client *client) +{ + std::unordered_set ids; + for (auto *pet : multiclass_manager.GetPetRoster(client)) { + if (pet) { + ids.insert(pet->GetID()); + } + } + + return ids; +} + +NPC *FindNewRosterPet(Client *client, const std::unordered_set &previous_ids) +{ + for (auto *pet : multiclass_manager.GetPetRoster(client)) { + if (!pet || !pet->IsNPC()) { + continue; + } + + if (previous_ids.find(pet->GetID()) == previous_ids.end()) { + return pet->CastToNPC(); + } + } + + return nullptr; +} + +} + ZoneDatabase::ZoneDatabase() : SharedDatabase() { @@ -3097,6 +3302,7 @@ void ZoneDatabase::SavePetInfo(Client *client) std::vector inventory; auto item = CharacterPetInventoryRepository::NewEntity(); + std::vector multiclass_pet_state_values; for (int pet_info_type = PetInfoType::Current; pet_info_type <= PetInfoType::Suspended; pet_info_type++) { p = client->GetPetInfo(pet_info_type); @@ -3185,6 +3391,49 @@ void ZoneDatabase::SavePetInfo(Client *client) } } + if (!client->IsDead() && multiclass_manager.GetPetRosterLimit(client) > 1) { + auto *current_pet = client->GetPet(); + const auto current_pet_id = current_pet ? current_pet->GetID() : 0; + if (current_pet && current_pet->IsNPC()) { + const auto value = BuildMulticlassPetStateValue(client, PetInfoType::Current, current_pet->CastToNPC(), current_pet_id); + if (!value.empty()) { + multiclass_pet_state_values.emplace_back(value); + } + } + + const uint8 roster_limit = multiclass_manager.GetPetRosterLimit(client); + const uint8 secondary_limit = current_pet_id ? (roster_limit - 1) : roster_limit; + uint8 saved_secondary_pets = 0; + int pet_info_type = MulticlassPetInfoSlotBegin; + + for (auto *roster_pet : multiclass_manager.GetPetRoster(client)) { + if ( + !roster_pet || + !roster_pet->IsNPC() || + roster_pet->GetID() == current_pet_id || + pet_info_type > MulticlassPetInfoSlotEnd || + saved_secondary_pets >= secondary_limit + ) { + continue; + } + + auto *pet_npc = roster_pet->CastToNPC(); + if (!pet_npc || !pet_npc->GetPetSpellID()) { + continue; + } + + PetInfo secondary_pet_info; + CapturePetInfo(pet_npc, secondary_pet_info); + AppendPetInfoRows(client, pet_info_type, secondary_pet_info, pet_infos, pet_buffs, inventory); + const auto value = BuildMulticlassPetStateValue(client, pet_info_type, pet_npc, current_pet_id); + if (!value.empty()) { + multiclass_pet_state_values.emplace_back(value); + } + pet_info_type++; + saved_secondary_pets++; + } + } + CharacterPetInfoRepository::DeleteWhere( database, fmt::format( @@ -3220,6 +3469,26 @@ void ZoneDatabase::SavePetInfo(Client *client) if (!inventory.empty()) { CharacterPetInventoryRepository::InsertMany(database, inventory); } + + if (MulticlassPetStateSchemaAvailable()) { + QueryDatabase( + fmt::format( + "DELETE FROM `custom_multiclass_pet_state` WHERE `character_id` = {}", + client->CharacterID() + ) + ); + + if (!multiclass_pet_state_values.empty()) { + QueryDatabase( + fmt::format( + "INSERT INTO `custom_multiclass_pet_state` " + "(`character_id`, `pet_slot`, `spell_id`, `pet_name`, `pet_order`, `held`, `gheld`, `nocast`, `focused`, `pet_stop`, `pet_regroup`, `guard_x`, `guard_y`, `guard_z`, `guard_heading`, `updated_at`) " + "VALUES {}", + Strings::Join(multiclass_pet_state_values, ",") + ) + ); + } + } } void ZoneDatabase::RemoveTempFactions(Client *client) { @@ -3359,6 +3628,128 @@ void ZoneDatabase::LoadPetInfo(Client *client) } } +void ZoneDatabase::LoadMulticlassPetInfo(Client *client) +{ + if (!client || !client->CharacterID() || multiclass_manager.GetPetRosterLimit(client) <= 1) { + return; + } + + auto pet_infos = CharacterPetInfoRepository::GetWhere( + database, + fmt::format( + "`char_id` = {} AND `pet` BETWEEN {} AND {}", + client->CharacterID(), + MulticlassPetInfoSlotBegin, + MulticlassPetInfoSlotEnd + ) + ); + + if (pet_infos.empty()) { + return; + } + + std::sort( + pet_infos.begin(), + pet_infos.end(), + [](const auto &left, const auto &right) { + return left.pet < right.pet; + } + ); + + auto pet_buffs = CharacterPetBuffsRepository::GetWhere( + database, + fmt::format( + "`char_id` = {} AND `pet` BETWEEN {} AND {}", + client->CharacterID(), + MulticlassPetInfoSlotBegin, + MulticlassPetInfoSlotEnd + ) + ); + + auto inventory = CharacterPetInventoryRepository::GetWhere( + database, + fmt::format( + "`char_id` = {} AND `pet` BETWEEN {} AND {}", + client->CharacterID(), + MulticlassPetInfoSlotBegin, + MulticlassPetInfoSlotEnd + ) + ); + + for (const auto &e : pet_infos) { + if (multiclass_manager.GetPetRoster(client).size() >= multiclass_manager.GetPetRosterLimit(client)) { + return; + } + + if (e.spell_id <= 1 || e.spell_id > SPDAT_RECORDS || !IsValidSpell(e.spell_id)) { + continue; + } + + PetInfo pet_state; + memset(&pet_state, 0, sizeof(PetInfo)); + strn0cpy(pet_state.Name, e.petname.c_str(), sizeof(pet_state.Name)); + pet_state.petpower = e.petpower; + pet_state.SpellID = e.spell_id; + pet_state.HP = e.hp; + pet_state.Mana = e.mana; + pet_state.size = e.size; + pet_state.taunting = e.taunting; + + const int max_buff_slots = std::min(RuleI(Spells, MaxTotalSlotsPET), PET_BUFF_COUNT); + for (const auto &buff : pet_buffs) { + if (buff.pet != e.pet || buff.slot < 0 || buff.slot >= max_buff_slots || !IsValidSpell(buff.spell_id)) { + continue; + } + + pet_state.Buffs[buff.slot].spellid = buff.spell_id; + pet_state.Buffs[buff.slot].level = buff.caster_level; + pet_state.Buffs[buff.slot].player_id = 0; + pet_state.Buffs[buff.slot].effect_type = BuffEffectType::Buff; + pet_state.Buffs[buff.slot].duration = buff.ticsremaining; + pet_state.Buffs[buff.slot].counters = buff.counters; + pet_state.Buffs[buff.slot].bard_modifier = buff.instrument_mod; + } + + for (const auto &item : inventory) { + if (item.pet != e.pet || !EQ::ValueWithin(item.slot, EQ::invslot::EQUIPMENT_BEGIN, EQ::invslot::EQUIPMENT_END)) { + continue; + } + + pet_state.Items[item.slot] = item.item_id; + } + + const auto previous_ids = GetRosterPetIds(client); + client->MakePoweredPet( + pet_state.SpellID, + spells[pet_state.SpellID].teleport_zone, + pet_state.petpower, + pet_state.Name, + pet_state.size + ); + + auto *pet = FindNewRosterPet(client, previous_ids); + if (!pet) { + continue; + } + + pet->SetPetState(pet_state.Buffs, pet_state.Items); + pet->CalcBonuses(); + pet->SetHP(pet_state.HP); + pet->SetMana(pet_state.Mana); + + if (client->ClientVersionBit() & EQ::versions::maskUFAndLater) { + pet->SetTaunting(pet_state.taunting); + } + + LoadMulticlassPetState(client, pet, e.pet); + } +} + +void ZoneDatabase::LoadMulticlassPetState(Client *client, NPC *pet, int pet_info_type) +{ + ApplyMulticlassPetStateRow(client, pet, pet_info_type); +} + bool ZoneDatabase::GetFactionData(FactionMods* fm, uint32 class_mod, uint32 race_mod, uint32 deity_mod, int32 faction_id) { if (faction_id <= 0 || faction_id > (int32) max_faction) return false; diff --git a/zone/zonedb.h b/zone/zonedb.h index c751a47370..ccfb276f38 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -436,6 +436,8 @@ class ZoneDatabase : public SharedDatabase { void SaveAuras(Client *c); void LoadAuras(Client *c); void LoadPetInfo(Client *c); + void LoadMulticlassPetInfo(Client *c); + void LoadMulticlassPetState(Client *c, NPC *pet, int pet_info_type); void SavePetInfo(Client *c); void RemoveTempFactions(Client *c); void UpdateItemRecast(uint32 char_id, uint32 recast_type, uint32 timestamp); From 374b2a8da140e021b1d57c0901450fe4835a6363 Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:59:02 -0700 Subject: [PATCH 134/194] Checkpoint all features AI NPC response bridge --- .gitignore | 7 + .../ui/EQUI_NativeAiNpcResponseWnd.xml | 30 - docs/ai-npc-response.md | 102 +- docs/features-all.md | 25 +- features/ai-npc-response/MANIFEST.md | 43 +- features/ai-npc-response/README.md | 73 +- features/ai-npc-response/ai-bridge/README.md | 133 ++ .../ai-npc-response/ai-bridge/app/__init__.py | 1 + .../ai-npc-response/ai-bridge/app/main.py | 1187 +++++++++++++++++ .../ai-bridge/config/lore.json | 70 + .../ai-bridge/config/npcs.json | 49 + .../ai-bridge/config/online_lore.json | 22 + .../ai-bridge/requirements.txt | 3 + .../ai-bridge/samples/eqemu_ai_npc_sample.pl | 80 ++ .../ai-bridge/scripts/Setup-AiBridge.ps1 | 45 + .../ai-bridge/scripts/Start-AiBridge.ps1 | 53 + .../ai-bridge/scripts/Start-OllamaLocal.ps1 | 36 + .../ai-bridge/scripts/Stop-AiBridge.ps1 | 24 + .../ai-bridge/scripts/Stop-OllamaLocal.ps1 | 17 + .../ai-bridge/scripts/Test-BridgeLatency.ps1 | 40 + .../ai-bridge/scripts/Test-Ollama.ps1 | 7 + features/ai-npc-response/patcher.yml | 18 +- .../quests/tutorialb/900903.pl | 157 +++ .../sql/001_sage_aurelian_tutorialb.sql | 182 +++ features/all-features/patcher.yml | 3 - 25 files changed, 2307 insertions(+), 100 deletions(-) delete mode 100644 client_files/native_autoloot/ui/EQUI_NativeAiNpcResponseWnd.xml create mode 100644 features/ai-npc-response/ai-bridge/README.md create mode 100644 features/ai-npc-response/ai-bridge/app/__init__.py create mode 100644 features/ai-npc-response/ai-bridge/app/main.py create mode 100644 features/ai-npc-response/ai-bridge/config/lore.json create mode 100644 features/ai-npc-response/ai-bridge/config/npcs.json create mode 100644 features/ai-npc-response/ai-bridge/config/online_lore.json create mode 100644 features/ai-npc-response/ai-bridge/requirements.txt create mode 100644 features/ai-npc-response/ai-bridge/samples/eqemu_ai_npc_sample.pl create mode 100644 features/ai-npc-response/ai-bridge/scripts/Setup-AiBridge.ps1 create mode 100644 features/ai-npc-response/ai-bridge/scripts/Start-AiBridge.ps1 create mode 100644 features/ai-npc-response/ai-bridge/scripts/Start-OllamaLocal.ps1 create mode 100644 features/ai-npc-response/ai-bridge/scripts/Stop-AiBridge.ps1 create mode 100644 features/ai-npc-response/ai-bridge/scripts/Stop-OllamaLocal.ps1 create mode 100644 features/ai-npc-response/ai-bridge/scripts/Test-BridgeLatency.ps1 create mode 100644 features/ai-npc-response/ai-bridge/scripts/Test-Ollama.ps1 create mode 100644 features/ai-npc-response/quests/tutorialb/900903.pl create mode 100644 features/ai-npc-response/sql/001_sage_aurelian_tutorialb.sql diff --git a/.gitignore b/.gitignore index 627d3c6306..961ea49348 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,10 @@ compile_flags.txt # CMake Files cmake-build-relwithdebinfo/* skill-caps.diff + +# Local code index and AI NPC bridge runtime artifacts +.codegraph/ +features/ai-npc-response/ai-bridge/.venv/ +features/ai-npc-response/ai-bridge/runtime/ +features/ai-npc-response/ai-bridge/ollama-models/ +features/ai-npc-response/ai-bridge/**/__pycache__/ diff --git a/client_files/native_autoloot/ui/EQUI_NativeAiNpcResponseWnd.xml b/client_files/native_autoloot/ui/EQUI_NativeAiNpcResponseWnd.xml deleted file mode 100644 index 8b4c367b58..0000000000 --- a/client_files/native_autoloot/ui/EQUI_NativeAiNpcResponseWnd.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - NativeAiNpcResponseWnd - false - 12090 - 460180 - AI NPC response - WDT_Def - true - true - true - true - false - false - AINPCRESPONSE_StatusLabel - - \ No newline at end of file diff --git a/docs/ai-npc-response.md b/docs/ai-npc-response.md index 37a5665f33..7d0de4d71f 100644 --- a/docs/ai-npc-response.md +++ b/docs/ai-npc-response.md @@ -1,29 +1,93 @@ # AI NPC response -Design and operator documentation for the standalone `ai-npc-response` feature. +Design and operator notes for the standalone `ai-npc-response` feature. -## Overview +## Architecture -Describe the feature behavior, player/admin workflows, commands, database changes, client files, and how another server operator can install it. +```text +EQEmu Perl quest -> localhost FastAPI bridge -> Ollama chat/generate API -> NPC speech +``` -## Local Verification +The bridge listens only on `127.0.0.1:18080` and calls Ollama on +`127.0.0.1:11434`. The public testbed should not expose either port. -- Build: `.\verify-feature.ps1 ai-npc-response` -- Install runtime: `.\install-server-runtime.ps1 ai-npc-response` -- Install client files: `.\install-client-files.ps1 ai-npc-response` -- Run DB updates: `.\run-db-updates.ps1 ai-npc-response` -- Validate install: `.\validate-install.ps1 ai-npc-response` +## Current Prototype -## External Client Sync +Sage Aurelian is a Tutorial B test NPC (`npc_types.id = 900903`) placed near +Orin Augspinner and Vedra Forgecall. His quest script starts an async bridge +job, says a short thinking line for deeper lore requests, and polls for the +answer on a timer. -- Client patch manifest: `features/ai-npc-response/patcher.yml` -- `-Project` is the workspace install id from `D:\Codex\Apps\EQEmu-feature-workspaces\installs.json`. It usually matches the feature id, but confirm it first. -- Patcher host commands: +The bridge supports: -~~~powershell -cd D:\Codex\Apps\EQEmu-feature-patcher\features\patcher\eqemupatcher\service -.\New-WorkspacePatcherDeployment.ps1 -Project -BaseUrl http://:8091/patcher/ -.\Test-WorkspacePatcherDeployment.ps1 -Project -BaseUrl http://:8091/patcher/ -~~~ +- `POST /eqemu/npc-chat` for phase 1 synchronous requests. +- `POST /eqemu/npc-chat/start` for async/polling requests. +- `GET /eqemu/npc-chat/result/{job_id}` for completed async results. +- `GET /health` for config/model/bind checks. -Missing files are release blockers for real external syncs. Use `-AllowMissingClientFiles` only for partial local testing. \ No newline at end of file +## Lore Guarding + +The current guardrails are deliberately light so the pipeline can be tested: + +- Compact NPC persona config in `ai-bridge/config/npcs.json`. +- Zone/global lore and exact-term fallbacks in `ai-bridge/config/lore.json`. +- Optional whitelisted MediaWiki sources in `ai-bridge/config/online_lore.json`. +- Output scrubbers for prompt leaks, OOC terms, and wiki infobox metadata. + +For known terms like Quarm, the bridge prefers local lore/fallbacks over +generated guesses. For online snippets that expose a clean fact sentence, it +returns a deterministic in-character summary instead of asking the tiny model +to improvise. + +## Testbed Install + +From a checkout on the testbed VM, copy the bridge folder to: + +```text +D:\EQEmu\Testbed\ai-bridge +``` + +Install/start: + +```powershell +cd D:\EQEmu\Testbed\ai-bridge +.\scripts\Setup-AiBridge.ps1 +.\scripts\Start-OllamaLocal.ps1 -Background +.\scripts\Test-Ollama.ps1 +.\scripts\Start-AiBridge.ps1 -Background +Invoke-RestMethod http://127.0.0.1:18080/health +``` + +Apply `features/ai-npc-response/sql/001_sage_aurelian_tutorialb.sql` to the +testbed DB, then copy `features/ai-npc-response/quests/tutorialb/900903.pl` to +`D:\EQEmu\Testbed\server\quests\tutorialb\900903.pl`. + +Reload the quest and repop Tutorial B in-game. No EQEmu service restart is +required for this prototype NPC/quest change. + +## Latency Test + +Use: + +```powershell +cd D:\EQEmu\Testbed\ai-bridge +.\scripts\Test-BridgeLatency.ps1 -Count 5 +``` + +Also test the async in-game path by asking Sage Aurelian: + +- `hail` +- `who is quarm` +- `who is firiona vie` +- `tell me about karnor's castle` +- `where is my computer` + +## Next Work + +- Move from online wiki lookup to curated reference files or a local lore + retrieval index. +- Add per-zone reference folders and per-NPC reference attachments. +- Protect real quest keywords before sending text to the model. +- Add per-player conversation memory with short TTLs. +- Compare `qwen2.5:0.5b`, `qwen2.5:3b`, and a 7B/8B model for response quality + versus latency. diff --git a/docs/features-all.md b/docs/features-all.md index b9b6b8cffa..61597d1850 100644 --- a/docs/features-all.md +++ b/docs/features-all.md @@ -28,8 +28,11 @@ The combined custom database manifest uses: - Custom version `2`: Achievement schema. - Custom version `3`: Achievement catalog seed. - Custom version `4`: Live hunter achievement seed. +- Custom version `5`: Gearscore item power schema. +- Custom version `6`: Item rarity schema. +- Custom version `7`: Multiclass schema. -`common/version.h` sets `CUSTOM_BINARY_DATABASE_VERSION` to `4`. +`common/version.h` sets `CUSTOM_BINARY_DATABASE_VERSION` to `7`. ## Native Client Assets @@ -48,11 +51,27 @@ client DLL. - `EQUI_NativeMulticlassWnd.xml` - `EQUI_NativeTradeskillsWnd.xml` - `EQUI_NativeHpFixWnd.xml` -- `EQUI_NativeAiNpcResponseWnd.xml` - `EQUI_NativeAugsInAugsWnd.xml` - `EQUI_NativeDynamicQuestsWnd.xml` -The runtime handles `AUTOLOOT|`, `LIVEITEM|`, `LIVESPELL|`, and `ACH|` transport lines. It is no longer only lab code, but it is still monolithic internally: most feature-specific client behavior lives in `client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h`. The next cleanup is splitting that into a reusable native-client base plus feature-specific native modules. +The runtime handles `AUTOLOOT|`, `LIVEITEM|`, `LIVESPELL|`, `ACH|`, `HPFIX|`, +`ITEMPOWER|`, and `ITEMRARITY|` transport lines. It is no longer only lab code, +but it is still monolithic internally: most feature-specific client behavior +lives in `client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h`. +The next cleanup is splitting that into a reusable native-client base plus +feature-specific native modules. + +## AI NPC Response + +The AI NPC Response prototype is included as a feature payload under +`features/ai-npc-response/`. It contains a localhost-only FastAPI/Ollama bridge, +a Tutorial B Perl quest for Sage Aurelian, and an idempotent SQL seed for NPC +and spawn id `900903`. + +This prototype currently has no client-facing files. Its standalone +`features/ai-npc-response/patcher.yml` is intentionally empty, so the +all-features client patcher does not publish an AI NPC native XML window until +that feature commits one as source of truth. The expanded all-features target stages additional feature payloads in this checkout first, then wires server/native behavior here. Standalone feature projects remain in diff --git a/features/ai-npc-response/MANIFEST.md b/features/ai-npc-response/MANIFEST.md index 6096e0ae6c..456c1e3620 100644 --- a/features/ai-npc-response/MANIFEST.md +++ b/features/ai-npc-response/MANIFEST.md @@ -2,20 +2,37 @@ Feature id: `ai-npc-response` -This manifest starts intentionally small. Add required source files, SQL files, -client UI files, and operator notes as the feature becomes real. +## Prototype Files -## Test Target +- `features/ai-npc-response/ai-bridge/app/main.py` +- `features/ai-npc-response/ai-bridge/app/__init__.py` +- `features/ai-npc-response/ai-bridge/config/npcs.json` +- `features/ai-npc-response/ai-bridge/config/lore.json` +- `features/ai-npc-response/ai-bridge/config/online_lore.json` +- `features/ai-npc-response/ai-bridge/requirements.txt` +- `features/ai-npc-response/ai-bridge/scripts/*.ps1` +- `features/ai-npc-response/ai-bridge/samples/eqemu_ai_npc_sample.pl` +- `features/ai-npc-response/quests/tutorialb/900903.pl` +- `features/ai-npc-response/sql/001_sage_aurelian_tutorialb.sql` +- `features/ai-npc-response/patcher.yml` -- Server: `D:\EQServers\EQServer-Ai-Npc-Response` -- Client: `D:\EQClients\EQClient-Ai-Npc-Response` -- Database: `eqemu_ai_npc_response` +## Runtime Targets -## Expected First Implementation Updates +- Testbed bridge: `D:\EQEmu\Testbed\ai-bridge` +- Testbed quest: `D:\EQEmu\Testbed\server\quests\tutorialb\900903.pl` +- Testbed DB seed: `npc_types`, `spawngroup`, `spawnentry`, and `spawn2` + rows for NPC/spawn id `900903`. -- Add feature-owned source files to `features.json` `requiredFiles` once they exist. -- Add SQL migration files under `features/ai-npc-response/sql` if the feature needs schema/rule data. -- Add command, packet, or manager entry points here as they become part of the portable feature. -- Add external/test-client files to `features/ai-npc-response/patcher.yml` so the workspace patcher feed can publish them. -- In `patcher.yml`, `source` is repo-relative and `destination` is relative to the EverQuest client root. -- If the feature has native client behavior, add the feature-owned DLL project/source and build this checkout's own `dinput8.dll`. \ No newline at end of file +## Client Files + +None for the current prototype. `patcher.yml` is intentionally empty until +native client UI or other client-facing files become part of the feature. + +## Next Implementation Areas + +- Replace the ad hoc online lore lookup with curated retrieval files and/or a + small indexed lore corpus. +- Add protected quest keyword handling before generative fallback. +- Add per-NPC/player memory scoped by zone. +- Add faction, deity, class, race, and quest-state context inputs. +- Package a testbed deployment script once the VM path conventions stabilize. diff --git a/features/ai-npc-response/README.md b/features/ai-npc-response/README.md index 41e384bce1..f37a502122 100644 --- a/features/ai-npc-response/README.md +++ b/features/ai-npc-response/README.md @@ -1,35 +1,66 @@ # AI NPC response -Standalone EQEmu feature branch for `ai-npc-response`. +Standalone source for the `ai-npc-response` EQEmu prototype. -## Test Target +The current prototype connects an EQEmu Perl quest NPC to a local-only FastAPI +bridge, which calls Ollama and returns short in-character speech. -- Server: `D:\EQServers\EQServer-Ai-Npc-Response` -- Client: `D:\EQClients\EQClient-Ai-Npc-Response` -- Database: `eqemu_ai_npc_response` +## Contents -## First Build Loop +- `ai-bridge/`: FastAPI bridge, config, startup scripts, and latency tests. +- `quests/tutorialb/900903.pl`: async/polling quest script for Sage Aurelian. +- `sql/001_sage_aurelian_tutorialb.sql`: idempotent seed for the Tutorial B + test NPC and spawn. +- `patcher.yml`: currently empty because this phase has no client-facing files. -From `D:\Codex\Apps\EQEmu-feature-workspaces`: +## Testbed Target -~~~powershell -.\verify-feature.ps1 ai-npc-response -.\install-server-runtime.ps1 ai-npc-response -.\install-client-files.ps1 ai-npc-response -.\run-db-updates.ps1 ai-npc-response -.\validate-install.ps1 ai-npc-response -~~~ +- Bridge install: `D:\EQEmu\Testbed\ai-bridge` +- EQEmu server: `D:\EQEmu\Testbed\server` +- Quest target: `D:\EQEmu\Testbed\server\quests\tutorialb\900903.pl` +- Bridge endpoint: `http://127.0.0.1:18080` +- Ollama endpoint: `http://127.0.0.1:11434` -`install-server-runtime.ps1` also refreshes Windows firewall allow rules for the copied server binaries. +Keep both Ollama and the bridge bound to localhost. Do not expose the bridge +publicly. -## Client UI +## Prototype NPC -Native XML `EQUI_NativeAiNpcResponseWnd.xml` is installed into the prepared client and included from `uifiles/default/EQUI.xml` by the workspace client install scripts. +- NPC type id: `900903` +- Name: `Sage_Aurelian` +- Zone: `tutorialb` +- Location: near Orin Augspinner and Vedra Forgecall -## Client Patcher Feed +The quest script uses `POST /eqemu/npc-chat/start` and polls +`GET /eqemu/npc-chat/result/{job_id}` so deeper lore lookups do not hold the +zone process for the full model/search latency. -External/test-client patch syncing is owned by `features/ai-npc-response/patcher.yml`. Do not add files directly to `D:\EQClients\EQClient-Ai-Npc-Response` as the source of truth. Add any client-facing XML, DLL, config, zone asset, patch note, status file, or other tester-facing file to this repo and list it there before publishing a patcher feed. +## Model Notes -## Development Notes +`scripts/Start-AiBridge.ps1` currently defaults the testbed to +`qwen2.5:0.5b` for very fast iteration. The bridge code default is +`qwen2.5:3b` if launched without that script, and the model can be overridden: -Replace this section with feature behavior, commands, SQL, client files, operator install notes, and known test cases as the feature takes shape. \ No newline at end of file +```powershell +.\scripts\Start-AiBridge.ps1 -Model qwen2.5:3b +``` + +The richer model is better for flavor; the smaller model is useful while +testing guardrails and latency. + +## Validation + +From the bridge install directory on the VM: + +```powershell +.\scripts\Setup-AiBridge.ps1 +.\scripts\Start-OllamaLocal.ps1 -Background +.\scripts\Test-Ollama.ps1 +.\scripts\Start-AiBridge.ps1 -Background +Invoke-RestMethod http://127.0.0.1:18080/health +.\scripts\Test-BridgeLatency.ps1 -Count 5 +``` + +For the EQEmu side, apply the SQL seed, copy the quest script into the +Tutorial B quest folder, then use in-game quest reload/repop tools. This does +not require an EQEmu service restart. diff --git a/features/ai-npc-response/ai-bridge/README.md b/features/ai-npc-response/ai-bridge/README.md new file mode 100644 index 0000000000..3e51440063 --- /dev/null +++ b/features/ai-npc-response/ai-bridge/README.md @@ -0,0 +1,133 @@ +# EQEmu AI NPC Bridge Prototype + +Local-only FastAPI bridge for EQEmu NPC dialogue on the public testbed VM. + +## Paths + +- Source root in this repo: `features\ai-npc-response\ai-bridge` +- Testbed bridge root: `D:\EQEmu\Testbed\ai-bridge` +- Testbed EQEmu server root: `D:\EQEmu\Testbed\server` +- Safe sample quest scripts: `D:\EQEmu\Testbed\ai-bridge\samples` + +The bridge binds to `127.0.0.1:18080` only. Do not expose this port publicly. + +## Model + +The testbed startup script defaults to `qwen2.5:0.5b` for fast iteration: + +```powershell +.\scripts\Start-AiBridge.ps1 +``` + +Override the model when testing richer responses: + +```powershell +.\scripts\Start-AiBridge.ps1 -Model qwen2.5:3b +``` + +For a 7B/8B follow-up, check RAM and response time first. + +## Setup + +Run from the bridge root on the VM: + +```powershell +cd D:\EQEmu\Testbed\ai-bridge +.\scripts\Setup-AiBridge.ps1 +``` + +Confirm Ollama is listening locally: + +```powershell +.\scripts\Start-OllamaLocal.ps1 -Background +.\scripts\Test-Ollama.ps1 +``` + +Pull a model if needed: + +```powershell +ollama pull qwen2.5:0.5b +ollama pull qwen2.5:3b +``` + +Start the bridge in the foreground: + +```powershell +.\scripts\Start-AiBridge.ps1 +``` + +Or start it in the background: + +```powershell +.\scripts\Start-AiBridge.ps1 -Background +``` + +## Endpoints + +- `GET /health` +- `POST /eqemu/npc-chat` +- `POST /eqemu/npc-chat/start` +- `GET /eqemu/npc-chat/result/{job_id}` + +`/eqemu/npc-chat/start` returns immediate hail/OOC/advice responses when it +can. Deeper lore requests return a job id and a short acknowledgment so the +quest script can poll instead of blocking the zone process. + +## Test + +Health check: + +```powershell +Invoke-RestMethod http://127.0.0.1:18080/health +``` + +Single synchronous request: + +```powershell +$payload = @{ + npc_id = 900903 + npc_name = 'Sage Aurelian' + zone_short_name = 'tutorialb' + player_name = 'Tester' + player_message = 'who is quarm' +} | ConvertTo-Json + +Invoke-RestMethod -Method Post -Uri http://127.0.0.1:18080/eqemu/npc-chat -ContentType 'application/json' -Body $payload +``` + +Latency sample: + +```powershell +.\scripts\Test-BridgeLatency.ps1 -Count 5 +``` + +## EQEmu Quest + +The deployed Tutorial B prototype quest is tracked at: + +```text +features\ai-npc-response\quests\tutorialb\900903.pl +``` + +On the testbed VM, it belongs at: + +```text +D:\EQEmu\Testbed\server\quests\tutorialb\900903.pl +``` + +The test NPC/spawn seed is: + +```text +features\ai-npc-response\sql\001_sage_aurelian_tutorialb.sql +``` + +Reload the quest and repop Tutorial B in-game after copying/applying the +tracked files. No EQEmu service restart is required for this prototype. + +## Next Improvements + +- Replace online wiki lookup with curated reference files or local retrieval. +- Add per-NPC memory scoped by player and zone. +- Add faction, race, class, deity, and quest-state prompt inputs. +- Add protected quest keyword handling before generative fallback. +- Run broader model comparisons once the guardrails are more stable. diff --git a/features/ai-npc-response/ai-bridge/app/__init__.py b/features/ai-npc-response/ai-bridge/app/__init__.py new file mode 100644 index 0000000000..f8b69517f9 --- /dev/null +++ b/features/ai-npc-response/ai-bridge/app/__init__.py @@ -0,0 +1 @@ +"""EQEmu local AI bridge prototype.""" diff --git a/features/ai-npc-response/ai-bridge/app/main.py b/features/ai-npc-response/ai-bridge/app/main.py new file mode 100644 index 0000000000..70a3b9e84a --- /dev/null +++ b/features/ai-npc-response/ai-bridge/app/main.py @@ -0,0 +1,1187 @@ +from __future__ import annotations + +import asyncio +import html +import json +import logging +import os +import re +import time +import uuid +from functools import lru_cache +from pathlib import Path +from typing import Any +from urllib.parse import quote, urlparse + +import httpx +from fastapi import FastAPI +from pydantic import BaseModel, Field + +BRIDGE_ROOT = Path(__file__).resolve().parents[1] +CONFIG_PATH = Path(os.getenv("EQEMU_NPC_CONFIG", BRIDGE_ROOT / "config" / "npcs.json")) +LORE_PATH = Path(os.getenv("EQEMU_LORE_CONFIG", BRIDGE_ROOT / "config" / "lore.json")) +ONLINE_LORE_PATH = Path(os.getenv("EQEMU_ONLINE_LORE_CONFIG", BRIDGE_ROOT / "config" / "online_lore.json")) +ONLINE_CACHE_PATH = Path(os.getenv("EQEMU_ONLINE_LORE_CACHE", BRIDGE_ROOT / "runtime" / "online-lore-cache.json")) + +OLLAMA_URL = os.getenv("OLLAMA_URL", "http://127.0.0.1:11434").rstrip("/") +OLLAMA_MODEL = os.getenv("OLLAMA_MODEL", "qwen2.5:3b") +OLLAMA_DEEP_MODEL = os.getenv("OLLAMA_DEEP_MODEL", OLLAMA_MODEL) +OLLAMA_KEEP_ALIVE = os.getenv("OLLAMA_KEEP_ALIVE", "10m") +OLLAMA_TIMEOUT_SECONDS = float(os.getenv("OLLAMA_TIMEOUT_SECONDS", "6.0")) +OLLAMA_DEEP_TIMEOUT_SECONDS = float(os.getenv("OLLAMA_DEEP_TIMEOUT_SECONDS", "8.0")) +OLLAMA_PREWARM_TIMEOUT_SECONDS = float(os.getenv("OLLAMA_PREWARM_TIMEOUT_SECONDS", "45.0")) +OLLAMA_NUM_PREDICT = int(os.getenv("OLLAMA_NUM_PREDICT", "36")) +OLLAMA_DEEP_NUM_PREDICT = int(os.getenv("OLLAMA_DEEP_NUM_PREDICT", "72")) +OLLAMA_TEMPERATURE = float(os.getenv("OLLAMA_TEMPERATURE", "0.25")) +EQEMU_MAX_RESPONSE_CHARS = int(os.getenv("EQEMU_MAX_RESPONSE_CHARS", "420")) +EQEMU_PREWARM = os.getenv("EQEMU_PREWARM", "1").lower() not in {"0", "false", "no"} +ONLINE_LORE_LOOKUP = os.getenv("ONLINE_LORE_LOOKUP", "1").lower() not in {"0", "false", "no"} +ONLINE_LORE_TIMEOUT_SECONDS = float(os.getenv("ONLINE_LORE_TIMEOUT_SECONDS", "7.0")) +ONLINE_LORE_CACHE_TTL_SECONDS = int(os.getenv("ONLINE_LORE_CACHE_TTL_SECONDS", "604800")) +CHAT_JOB_TTL_SECONDS = int(os.getenv("CHAT_JOB_TTL_SECONDS", "90")) +CHAT_JOB_POLL_AFTER_MS = int(os.getenv("CHAT_JOB_POLL_AFTER_MS", "1500")) + +DEFAULT_FALLBACK = "I need a moment to gather my thoughts. Speak with me again shortly." + +OOC_INPUT_TERMS = { + "ai", + "chatgpt", + "computer", + "database", + "discord", + "google", + "internet", + "language model", + "llm", + "prompt", + "server", + "website", +} + +OOC_OUTPUT_TERMS = { + "chatgpt", + "descriptions local", + "everquest npc", + "facts", + "google search", + "http", + "language model", + "known records", + "ollama", + "persona:", + "player's words", + "prompt", + "provided lore", + "respond now", + "style:", + "this world", + "tutorialb", +} + +UNKNOWN_LORE_STOPWORDS = { + "a", + "about", + "an", + "are", + "can", + "do", + "does", + "for", + "here", + "i", + "in", + "is", + "know", + "me", + "mine", + "mines", + "my", + "norrath", + "of", + "plane", + "should", + "tell", + "the", + "these", + "this", + "time", + "what", + "where", + "who", + "why", + "your", + "you", +} + +ADVICE_PATTERNS = ( + r"\bwhat should i do\b", + r"\bwhere should i go\b", + r"\bwhat now\b", + r"\bhelp\b", + r"\badvice\b", +) + +DEFAULT_HAIL_RESPONSE = ( + "Well met, traveler. I am Sage Aurelian. Bring me a name, place, plane, old battle, or rumor of Norrath, " + "and I will answer what fragments I know. Deeper tales may take me a moment to recall." +) + +logging.basicConfig( + level=os.getenv("LOG_LEVEL", "INFO").upper(), + format="%(asctime)s %(levelname)s %(name)s %(message)s", +) +log = logging.getLogger("eqemu-ai-bridge") + +app = FastAPI(title="EQEmu AI NPC Bridge", version="0.1.0") + +CHAT_JOBS: dict[str, dict[str, Any]] = {} +CHAT_JOBS_LOCK = asyncio.Lock() +ONLINE_CACHE_LOCK = asyncio.Lock() + + +class NpcChatRequest(BaseModel): + npc_id: int | str = Field(..., description="EQEmu NPC type/id or stable identifier.") + npc_name: str = Field(..., min_length=1, max_length=96) + zone_short_name: str = Field(..., min_length=1, max_length=64) + player_name: str = Field(..., min_length=1, max_length=64) + player_message: str = Field(..., min_length=1, max_length=500) + recent_context: list[str] | str | None = Field(default=None, max_length=1200) + max_tokens: int | None = Field(default=None, ge=16, le=160) + timeout_seconds: float | None = Field(default=None, ge=1.0, le=15.0) + + +class NpcChatResponse(BaseModel): + ok: bool + response: str + model: str + latency_ms: int + fallback: bool = False + reason: str | None = None + sources: list[str] = Field(default_factory=list) + + +class NpcChatStartResponse(BaseModel): + ok: bool + done: bool + status: str + job_id: str | None = None + response: str | None = None + ack_response: str | None = None + poll_after_ms: int = CHAT_JOB_POLL_AFTER_MS + reason: str | None = None + + +class NpcChatResultResponse(BaseModel): + ok: bool + done: bool + status: str + job_id: str + response: str | None = None + model: str = OLLAMA_MODEL + latency_ms: int = 0 + fallback: bool = False + reason: str | None = None + sources: list[str] = Field(default_factory=list) + + +def _normalize(value: Any) -> str: + return re.sub(r"[^a-z0-9]+", "", str(value).lower()) + + +def _flat_lower(value: Any) -> str: + return re.sub(r"\s+", " ", str(value).lower()).strip() + + +@lru_cache(maxsize=1) +def load_personas() -> dict[str, Any]: + if not CONFIG_PATH.exists(): + log.warning("Persona config not found: %s", CONFIG_PATH) + return {"defaults": {}, "npcs": {}} + + with CONFIG_PATH.open("r", encoding="utf-8") as handle: + data = json.load(handle) + + data.setdefault("defaults", {}) + data.setdefault("npcs", {}) + return data + + +@lru_cache(maxsize=1) +def load_lore() -> dict[str, Any]: + if not LORE_PATH.exists(): + log.warning("Lore config not found: %s", LORE_PATH) + return {"global": [], "zones": {}, "terms": []} + + with LORE_PATH.open("r", encoding="utf-8") as handle: + data = json.load(handle) + + data.setdefault("global", []) + data.setdefault("zones", {}) + data.setdefault("terms", []) + return data + + +@lru_cache(maxsize=1) +def load_online_lore_config() -> dict[str, Any]: + if not ONLINE_LORE_PATH.exists(): + return {"enabled": ONLINE_LORE_LOOKUP, "sources": []} + + with ONLINE_LORE_PATH.open("r", encoding="utf-8") as handle: + data = json.load(handle) + + data.setdefault("enabled", ONLINE_LORE_LOOKUP) + data.setdefault("sources", []) + return data + + +def load_online_cache() -> dict[str, Any]: + if not ONLINE_CACHE_PATH.exists(): + return {"entries": {}} + + try: + with ONLINE_CACHE_PATH.open("r", encoding="utf-8") as handle: + data = json.load(handle) + except Exception as exc: # noqa: BLE001 + log.warning("Online lore cache read failed: %s", exc) + return {"entries": {}} + + data.setdefault("entries", {}) + return data + + +def save_online_cache(cache: dict[str, Any]) -> None: + try: + ONLINE_CACHE_PATH.parent.mkdir(parents=True, exist_ok=True) + with ONLINE_CACHE_PATH.open("w", encoding="utf-8") as handle: + json.dump(cache, handle, indent=2) + except Exception as exc: # noqa: BLE001 + log.warning("Online lore cache write failed: %s", exc) + + +def find_persona(req: NpcChatRequest) -> dict[str, Any]: + data = load_personas() + defaults = data.get("defaults", {}) + npcs = data.get("npcs", {}) + npc_id = str(req.npc_id) + + if npc_id in npcs: + return {**defaults, **npcs[npc_id]} + + req_name = _normalize(req.npc_name) + req_zone = _normalize(req.zone_short_name) + for persona in npcs.values(): + match = persona.get("match", {}) + names = [_normalize(x) for x in match.get("npc_names", [])] + zones = [_normalize(x) for x in match.get("zone_short_names", [])] + if names and req_name not in names: + continue + if zones and req_zone not in zones: + continue + return {**defaults, **persona} + + return defaults + + +def compact_recent_context(value: list[str] | str | None) -> str: + if value is None: + return "None." + if isinstance(value, str): + text = value + else: + text = "\n".join(str(item) for item in value[-4:]) + text = re.sub(r"\s+", " ", text).strip() + return text[:600] if text else "None." + + +def ooc_input_detected(req: NpcChatRequest) -> bool: + text = _flat_lower(req.player_message) + return any(re.search(rf"\b{re.escape(term)}\b", text) for term in OOC_INPUT_TERMS) + + +def hail_detected(req: NpcChatRequest) -> bool: + text = _flat_lower(req.player_message) + npc_name = _flat_lower(req.npc_name) + cleaned = re.sub(r"[^a-z0-9' ]+", " ", text) + cleaned = re.sub(r"\s+", " ", cleaned).strip() + return cleaned in {"hail", "hello", "hi", "greetings"} or cleaned == f"hail {npc_name}" + + +def hail_response(req: NpcChatRequest, persona: dict[str, Any]) -> NpcChatResponse: + text = persona.get("hail_response") or DEFAULT_HAIL_RESPONSE + return NpcChatResponse( + ok=True, + response=clean_npc_speech(str(text)), + model=OLLAMA_MODEL, + latency_ms=0, + fallback=False, + reason="hail", + ) + + +def ooc_output_detected(text: str) -> bool: + lower = _flat_lower(text) + return any(term in lower for term in OOC_OUTPUT_TERMS) + + +def prompt_leak_detected(text: str) -> bool: + return bool( + re.search( + r"\b(Persona|Style|Record\s+\d+|Known records|Player's words|Respond now as|FACTS|NPC lore)\b\s*[:;,]", + text, + flags=re.IGNORECASE, + ) + ) + + +def matched_lore_entries(req: NpcChatRequest) -> list[dict[str, Any]]: + lore = load_lore() + message = _normalize(req.player_message) + matches: list[dict[str, Any]] = [] + for entry in lore.get("terms", []): + aliases = entry.get("aliases", []) + if any(_normalize(alias) and _normalize(alias) in message for alias in aliases): + matches.append(entry) + return matches + + +def relevant_lore(req: NpcChatRequest, persona: dict[str, Any]) -> str: + lore = load_lore() + snippets: list[str] = [] + matched_entries = matched_lore_entries(req) + + for entry in matched_entries: + snippets.append(f"{entry.get('id', 'lore')}: {entry.get('text', '')}") + + persona_lore = persona.get("lore") + if persona_lore: + snippets.append(f"NPC: {persona_lore}") + + zone_key = _normalize(req.zone_short_name) + zones = lore.get("zones", {}) + for key, entries in zones.items(): + if _normalize(key) == zone_key: + for entry in entries[:2]: + snippets.append(f"Zone: {entry.get('text', '')}") + break + + snippets.append("If these facts do not answer the question, say you know only rumors or fragments.") + + compact = [re.sub(r"\s+", " ", item).strip() for item in snippets if item.strip()] + return " ".join(compact[:5])[:900] or "No specific lore was found." + + +def lore_fallback_text(req: NpcChatRequest, persona: dict[str, Any]) -> str | None: + if ooc_input_detected(req): + return persona.get( + "ooc_fallback", + "That sounds like strange tinker's jargon. Ask me of Norrath's folk, places, or dangers, and I will answer what fragments I know.", + ) + + if zone_advice_question(req): + return persona.get( + "advice_fallback", + "Keep your wits in these mines. Watch the shadows, speak with nearby guides, and trust caution over tavern rumor.", + ) + + if unknown_lore_question(req): + return persona.get( + "unknown_lore_fallback", + "I know only fragments of that name. Best not dress rumor as truth without a stronger tale to hold it.", + ) + + for entry in matched_lore_entries(req): + fallback = entry.get("fallback_response") + if fallback: + return str(fallback) + + return None + + +def zone_advice_question(req: NpcChatRequest) -> bool: + lower = _flat_lower(req.player_message) + return any(re.search(pattern, lower) for pattern in ADVICE_PATTERNS) + + +def unknown_lore_question(req: NpcChatRequest) -> bool: + if matched_lore_entries(req) or ooc_input_detected(req): + return False + + lower = _flat_lower(req.player_message) + if not re.search(r"\b(who|what|where|tell me|do you know)\b", lower): + return False + + tokens = re.findall(r"[A-Za-z][A-Za-z']+", req.player_message) + meaningful = [token for token in tokens if token.lower() not in UNKNOWN_LORE_STOPWORDS] + if any(token[:1].isupper() for token in meaningful): + return True + + return bool(re.search(r"\b(king|queen|lord|lady|dragon|sorcerer|god|goddess|prince|princess)\b", lower)) + + +def extract_lore_query(req: NpcChatRequest) -> str: + text = req.player_message.strip() + text = re.sub(r"[?!.,;:]+$", "", text).strip() + patterns = ( + r"^(can you\s+)?(look up|search for|tell me about|tell me of|who is|who was|what is|what was|do you know about)\s+", + r"^(can you\s+)?(recall|remember)\s+", + ) + for pattern in patterns: + text = re.sub(pattern, "", text, flags=re.IGNORECASE).strip() + text = re.sub(r"\b(for me|in this zone|in the zone|nearby|around here)\b", "", text, flags=re.IGNORECASE) + text = re.sub(r"\s+", " ", text).strip(" '\"") + return text[:96] + + +def deep_lookup_question(req: NpcChatRequest) -> bool: + if ooc_input_detected(req) or zone_advice_question(req): + return False + + lower = _flat_lower(req.player_message) + if not re.search(r"\b(who is|who was|what is|what was|tell me about|tell me of|look up|search for|do you know about|recall|remember)\b", lower): + return False + + query = extract_lore_query(req) + return len(_normalize(query)) >= 3 + + +def source_allowed(api_url: str, source: dict[str, Any]) -> bool: + host = (urlparse(api_url).hostname or "").lower() + allowed_hosts = [str(item).lower() for item in source.get("allowed_hosts", [])] + return host in allowed_hosts + + +def html_to_text(value: str) -> str: + text = re.sub(r"(?is)<(script|style|table|figure|sup)[^>]*>.*?", " ", value) + text = re.sub(r"(?is)", "\n", text) + text = re.sub(r"(?is)

    ||", "\n", text) + text = re.sub(r"(?is)<[^>]+>", " ", text) + text = html.unescape(text) + text = re.sub(r"\[[^\]]{1,20}\]", " ", text) + text = re.sub(r"(?is)Related Quests .*? Lore ", "Lore ", text) + text = re.sub(r"\s+", " ", text) + return scrub_source_text(text) + + +def scrub_source_text(text: str) -> str: + text = re.sub(r"\s+", " ", text).strip() + text = re.sub( + r"(?i)^zone_name\s+.+?\s+zone_type\s+\S+\s+level_range\s+\S+\s+Continent\s+.+?\s+Expansion\s+.+?\s+instanced\s+(?:Yes|No)\s+key_required\s+(?:Yes|No)\s+", + "", + text, + ) + text = re.sub( + r"(?i)\b(zone_name|zone_type|level_range|continent|expansion|instanced|key_required|copy\s*/waypoint)\b\s+[^.]{0,40}", + " ", + text, + ) + text = re.sub(r"(?i)\b(Quests starting in|Quests involved with|Traveling To and From)\b.*$", "", text) + text = re.sub(r"(?i)\b(Help|LootDB|EQ2Map|EQ2LL|ZAM)\s+", " ", text) + text = re.sub(r"\s+", " ", text) + return text.strip(" .,:;") + + +def select_relevant_text(text: str, query: str, max_chars: int = 450) -> str: + query_tokens = {token.lower() for token in re.findall(r"[A-Za-z][A-Za-z']+", query) if len(token) > 2} + sentences = [item.strip() for item in re.split(r"(?<=[.!?])\s+", text) if len(item.strip()) > 30] + clean_sentences = [ + item + for item in sentences + if not re.search(r"\b(advertisement|sign in|edit source|navigation|category|community content|this article is a stub|you can help)\b", item, re.I) + ] + selected: list[str] = [] + for sentence in clean_sentences: + lower = sentence.lower() + if any(token in lower for token in query_tokens): + selected.append(sentence) + if len(" ".join(selected)) >= max_chars: + break + + if not selected: + selected = clean_sentences[:4] + + return scrub_source_text(" ".join(selected)[:max_chars]) + + +def page_url_for_source(source: dict[str, Any], title: str) -> str: + template = str(source.get("page_url_template", "")) + if not template: + return "" + return template.replace("{title}", quote(title.replace(" ", "_"), safe="_'")) + + +async def search_mediawiki_source(client: httpx.AsyncClient, source: dict[str, Any], query: str) -> list[dict[str, str]]: + api_url = str(source.get("api_url", "")) + if not api_url or not source_allowed(api_url, source): + return [] + + search_limit = int(source.get("search_limit", 2)) + search_params = { + "action": "query", + "list": "search", + "srsearch": query, + "format": "json", + "srlimit": search_limit, + } + search_response = await client.get(api_url, params=search_params) + search_response.raise_for_status() + search_data = search_response.json() + results = search_data.get("query", {}).get("search", []) + + snippets: list[dict[str, str]] = [] + for item in results[:search_limit]: + pageid = item.get("pageid") + title = str(item.get("title", "")).strip() + if not pageid or not title: + continue + + parse_params = { + "action": "parse", + "pageid": pageid, + "prop": "text", + "format": "json", + "formatversion": "2", + } + parse_response = await client.get(api_url, params=parse_params) + parse_response.raise_for_status() + parse_data = parse_response.json() + page_html = str(parse_data.get("parse", {}).get("text", "")) + text = select_relevant_text(html_to_text(page_html), query) + if not text: + raw_snippet = html_to_text(str(item.get("snippet", ""))) + text = raw_snippet[:500] + if not text: + continue + + snippets.append( + { + "source": str(source.get("name", "online lore")), + "title": title, + "url": page_url_for_source(source, title), + "text": text, + } + ) + + return snippets + + +async def online_lore_lookup(query: str) -> tuple[list[dict[str, str]], bool]: + config = load_online_lore_config() + if not ONLINE_LORE_LOOKUP or not config.get("enabled", True): + return [], False + + cache_key = _normalize(query) + now = int(time.time()) + async with ONLINE_CACHE_LOCK: + cache = load_online_cache() + cached = cache.get("entries", {}).get(cache_key) + if cached and now - int(cached.get("cached_at", 0)) < ONLINE_LORE_CACHE_TTL_SECONDS: + max_snippets = int(config.get("max_snippets", 3)) + cached_snippets = [] + for snippet in list(cached.get("snippets", []))[:max_snippets]: + trimmed = dict(snippet) + trimmed["text"] = scrub_source_text(str(trimmed.get("text", "")))[:500] + cached_snippets.append(trimmed) + return cached_snippets, True + + snippets: list[dict[str, str]] = [] + headers = {"User-Agent": "eqemu-ai-npc-lore-prototype/0.2"} + timeout = httpx.Timeout(ONLINE_LORE_TIMEOUT_SECONDS) + async with httpx.AsyncClient(timeout=timeout, headers=headers, follow_redirects=True) as client: + for source in config.get("sources", []): + if str(source.get("type", "mediawiki")) != "mediawiki": + continue + try: + snippets.extend(await search_mediawiki_source(client, source, query)) + except Exception as exc: # noqa: BLE001 + log.warning("Online lore source failed for %s: %s", source.get("name"), exc) + if len(snippets) >= int(config.get("max_snippets", 3)): + break + + snippets = snippets[: int(config.get("max_snippets", 3))] + async with ONLINE_CACHE_LOCK: + cache = load_online_cache() + cache.setdefault("entries", {})[cache_key] = { + "cached_at": now, + "query": query, + "snippets": snippets, + } + save_online_cache(cache) + + return snippets, False + + +def local_lore_snippets(req: NpcChatRequest) -> list[dict[str, str]]: + snippets: list[dict[str, str]] = [] + for entry in matched_lore_entries(req): + text = str(entry.get("text", "")).strip() + if text: + snippets.append({"source": "local lore", "title": str(entry.get("id", "lore")), "url": "", "text": text}) + return snippets + + +def build_messages(req: NpcChatRequest, persona: dict[str, Any], repair_text: str | None = None) -> list[dict[str, str]]: + persona_text = persona.get( + "persona", + "A grounded EverQuest NPC who answers briefly and stays in character.", + ) + speech_style = persona.get( + "speech_style", + "Direct, warm, and concise. One or two short sentences.", + ) + setting_warning = ( + "Out-of-setting words are confused tinkerer jargon; deflect briefly in-character." + if ooc_input_detected(req) + else "" + ) + + system = ( + f"You are {req.npc_name}, an EverQuest NPC in {req.zone_short_name}. " + "Speak as live NPC dialogue in 1-2 sentences, under 30 words. " + "Answer the player directly. Use only FACTS. If FACTS do not answer it, admit you know only fragments. " + "Never mention AI, prompts, HTTP, Google, websites, databases, servers, admin tools, computers, or the internet. " + f"{setting_warning}" + ) + + user = ( + f"Persona: {str(persona_text)[:240]}\n" + f"Style: {str(speech_style)[:120]}\n" + f"Player {req.player_name} says: {req.player_message}\n" + f"Context: {compact_recent_context(req.recent_context)}\n" + f"FACTS: {relevant_lore(req, persona)}\n" + ) + if repair_text: + user += ( + "\nYour previous draft contained out-of-setting language or unsupported lore. " + f"Rewrite this as in-character NPC speech using only the lore above: {repair_text}\n" + ) + user += f"Respond now as {req.npc_name}." + return [{"role": "system", "content": system}, {"role": "user", "content": user}] + + +def build_deep_messages( + req: NpcChatRequest, + persona: dict[str, Any], + query: str, + snippets: list[dict[str, str]], +) -> list[dict[str, str]]: + persona_text = persona.get( + "persona", + "A grounded EverQuest NPC who answers briefly and stays in character.", + ) + speech_style = persona.get("speech_style", "Brief, grounded, and useful.") + records: list[str] = [] + for index, snippet in enumerate(snippets[:4], start=1): + title = snippet.get("title", "record") + text = re.sub(r"\s+", " ", snippet.get("text", "")).strip()[:500] + records.append(f"Record {index}, {title}: {text}") + + system = ( + f"You are {req.npc_name}, an EverQuest NPC in {req.zone_short_name}. " + "You are answering after consulting old records. Speak in-character in 1-3 sentences, under 70 words. " + "Use only the records below. If they are thin or conflicting, be cautious and say only what seems certain. " + "Do not mention websites, searches, records, wikis, URLs, AI, prompts, HTTP, databases, servers, computers, or the internet." + ) + user = ( + f"Persona: {str(persona_text)[:260]}\n" + f"Style: {str(speech_style)[:140]}\n" + f"Player {req.player_name} asked about: {query}\n" + f"Player's words: {req.player_message}\n" + f"Known records:\n" + "\n".join(records) + f"\nRespond now as {req.npc_name}." + ) + return [{"role": "system", "content": system}, {"role": "user", "content": user}] + + +_CONTROL_CHARS = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]") + + +def clean_npc_speech(text: str, max_chars: int = EQEMU_MAX_RESPONSE_CHARS) -> str: + text = _CONTROL_CHARS.sub("", text) + text = text.replace("\r", " ").replace("\n", " ") + text = re.sub(r"\s+", " ", text).strip().strip('"') + + for prefix in ("NPC:", "Assistant:", "AI:", "Response:"): + if text.lower().startswith(prefix.lower()): + text = text[len(prefix) :].strip() + + if len(text) <= max_chars: + return text + + truncated = text[:max_chars].rstrip() + sentence_end = max(truncated.rfind("."), truncated.rfind("!"), truncated.rfind("?")) + if sentence_end >= 80: + return truncated[: sentence_end + 1] + return truncated.rstrip(",;: ") + "..." + + +def fallback_response(req: NpcChatRequest, persona: dict[str, Any], reason: str, latency_ms: int) -> NpcChatResponse: + text = persona.get("fallback") or DEFAULT_FALLBACK + return NpcChatResponse( + ok=False, + response=clean_npc_speech(text), + model=OLLAMA_MODEL, + latency_ms=latency_ms, + fallback=True, + reason=reason, + ) + + +def grounded_fallback_response( + req: NpcChatRequest, + persona: dict[str, Any], + reason: str, + latency_ms: int, +) -> NpcChatResponse: + text = lore_fallback_text(req, persona) + if not text: + return fallback_response(req, persona, reason, latency_ms) + + return NpcChatResponse( + ok=False, + response=clean_npc_speech(text), + model=OLLAMA_MODEL, + latency_ms=latency_ms, + fallback=True, + reason=reason, + ) + + +def grounded_output_failure(req: NpcChatRequest, text: str) -> str | None: + if prompt_leak_detected(text): + return "prompt_leak" + + if ooc_output_detected(text): + return "ooc_output" + + lower = _flat_lower(text) + for entry in matched_lore_entries(req): + for term in entry.get("forbidden_response_terms", []): + if str(term).lower() in lower: + return f"unsupported_lore_{entry.get('id', 'term')}" + required_terms = entry.get("required_response_terms", []) + if required_terms and not any(str(term).lower() in lower for term in required_terms): + return f"unsupported_lore_{entry.get('id', 'term')}" + + return None + + +async def call_ollama_messages( + messages: list[dict[str, str]], + *, + model: str, + timeout: float, + max_tokens: int, + temperature: float = OLLAMA_TEMPERATURE, +) -> str: + payload = { + "model": model, + "messages": messages, + "stream": False, + "keep_alive": OLLAMA_KEEP_ALIVE, + "options": { + "temperature": temperature, + "num_predict": max_tokens, + "num_ctx": 1024, + "top_p": 0.82, + "repeat_penalty": 1.12, + }, + } + + async with httpx.AsyncClient(timeout=timeout) as client: + response = await client.post(f"{OLLAMA_URL}/api/chat", json=payload) + response.raise_for_status() + data = response.json() + + message = data.get("message") or {} + return str(message.get("content") or data.get("response") or "").strip() + + +async def call_ollama(req: NpcChatRequest, persona: dict[str, Any], repair_text: str | None = None) -> str: + timeout = req.timeout_seconds or OLLAMA_TIMEOUT_SECONDS + max_tokens = req.max_tokens or OLLAMA_NUM_PREDICT + return await call_ollama_messages( + build_messages(req, persona, repair_text=repair_text), + model=OLLAMA_MODEL, + timeout=timeout, + max_tokens=max_tokens, + ) + + +def source_labels(snippets: list[dict[str, str]]) -> list[str]: + labels: list[str] = [] + for snippet in snippets: + title = snippet.get("title", "record") + source = snippet.get("source", "lore") + url = snippet.get("url", "") + labels.append(f"{source}: {title}" + (f" <{url}>" if url else "")) + return labels[:4] + + +def snippet_fact_sentence(query: str, snippets: list[dict[str, str]]) -> str | None: + query_name = re.escape(query.strip()) + patterns = [ + (rf"\b{query_name}\b\s+is\s+([^.!?;]{{8,180}})", "is"), + (rf"\b{query_name}\b\s+was\s+([^.!?;]{{8,180}})", "was"), + (rf"\b{query_name}\b,\s+([^.!?;]{{8,180}})", "comma"), + ] + for snippet in snippets: + text = scrub_source_text(str(snippet.get("text", ""))) + for pattern, mode in patterns: + match = re.search(pattern, text, flags=re.IGNORECASE) + if match: + title = str(snippet.get("title", "")).strip() + subject = title if title and _normalize(query) == _normalize(title) else query.strip() + predicate = match.group(1).strip(" .,:;") + predicate = re.sub(r"\b(Related Quests|Lore|Early Life)\b.*$", "", predicate).strip(" .,:;") + if predicate: + if mode == "comma": + return f"{subject}, {predicate}." + return f"{subject} is {predicate}." + + query_tokens = {token.lower() for token in re.findall(r"[A-Za-z][A-Za-z']+", query) if len(token) > 2} + for snippet in snippets: + sentences = [item.strip() for item in re.split(r"(?<=[.!?])\s+", scrub_source_text(str(snippet.get("text", ""))))] + for sentence in sentences: + lower = sentence.lower() + if any(token in lower for token in query_tokens) and not re.search(r"\b(stub|related quests|you can help)\b", lower): + return sentence[:220].strip(" .,:;") + "." + return None + + +def deep_fallback_response( + req: NpcChatRequest, + persona: dict[str, Any], + query: str, + snippets: list[dict[str, str]], + reason: str, + latency_ms: int, +) -> NpcChatResponse: + if matched_lore_entries(req): + response = grounded_fallback_response(req, persona, reason, latency_ms) + response.sources = source_labels(snippets) + return response + + fact = snippet_fact_sentence(query, snippets) + if fact: + text = f"The old tales say this much: {fact} Beyond that, the tale grows tangled." + else: + text = persona.get( + "unknown_lore_fallback", + "I find only scattered rumor on that name. Best not dress rumor as truth without a stronger tale to hold it.", + ) + + return NpcChatResponse( + ok=False, + response=clean_npc_speech(text), + model=OLLAMA_DEEP_MODEL, + latency_ms=latency_ms, + fallback=True, + reason=reason, + sources=source_labels(snippets), + ) + + +def deep_query_output_failure(query: str, text: str) -> str | None: + tokens = [token.lower() for token in re.findall(r"[A-Za-z][A-Za-z']+", query) if len(token) > 2] + if not tokens: + return None + + lower = _flat_lower(text) + if not any(token in lower for token in tokens): + return "unanswered_query" + + return None + + +async def deep_lore_chat(req: NpcChatRequest, persona: dict[str, Any]) -> NpcChatResponse: + started = time.perf_counter() + query = extract_lore_query(req) + snippets = local_lore_snippets(req) + online_snippets, cached = await online_lore_lookup(query) + snippets.extend(online_snippets) + + if not snippets: + latency_ms = int((time.perf_counter() - started) * 1000) + text = persona.get( + "unknown_lore_fallback", + "I find only scattered rumor on that name. Best not dress rumor as truth without a stronger tale to hold it.", + ) + return NpcChatResponse( + ok=False, + response=clean_npc_speech(text), + model=OLLAMA_DEEP_MODEL, + latency_ms=latency_ms, + fallback=True, + reason="no_lore_records", + ) + + latency_ms = int((time.perf_counter() - started) * 1000) + if matched_lore_entries(req): + response = grounded_fallback_response(req, persona, "local_lore", latency_ms) + response.sources = source_labels(snippets) + return response + + fact = snippet_fact_sentence(query, snippets) + if fact: + return NpcChatResponse( + ok=True, + response=clean_npc_speech(f"The old tales say this much: {fact} Beyond that, the tale grows tangled."), + model=OLLAMA_DEEP_MODEL, + latency_ms=latency_ms, + fallback=False, + reason="source_fact", + sources=source_labels(snippets), + ) + + try: + raw = await call_ollama_messages( + build_deep_messages(req, persona, query, snippets), + model=OLLAMA_DEEP_MODEL, + timeout=OLLAMA_DEEP_TIMEOUT_SECONDS, + max_tokens=req.max_tokens or OLLAMA_DEEP_NUM_PREDICT, + temperature=0.2, + ) + latency_ms = int((time.perf_counter() - started) * 1000) + cleaned = clean_npc_speech(raw) + if not cleaned: + return deep_fallback_response(req, persona, query, snippets, "empty_deep_model_response", latency_ms) + query_failure = deep_query_output_failure(query, cleaned) + if query_failure: + return deep_fallback_response(req, persona, query, snippets, query_failure, latency_ms) + failure_reason = grounded_output_failure(req, cleaned) + if failure_reason: + return deep_fallback_response(req, persona, query, snippets, failure_reason, latency_ms) + return NpcChatResponse( + ok=True, + response=cleaned, + model=OLLAMA_DEEP_MODEL, + latency_ms=latency_ms, + fallback=False, + reason="cached_lore" if cached else None, + sources=source_labels(snippets), + ) + except httpx.TimeoutException: + latency_ms = int((time.perf_counter() - started) * 1000) + return deep_fallback_response(req, persona, query, snippets, "deep_ollama_timeout", latency_ms) + except Exception as exc: # noqa: BLE001 + latency_ms = int((time.perf_counter() - started) * 1000) + log.warning("Deep lore chat failed: %s", exc) + return deep_fallback_response(req, persona, query, snippets, "deep_bridge_error", latency_ms) + + +async def cleanup_chat_jobs() -> None: + now = time.time() + async with CHAT_JOBS_LOCK: + expired = [ + job_id + for job_id, job in CHAT_JOBS.items() + if now - float(job.get("created_at", now)) > CHAT_JOB_TTL_SECONDS + ] + for job_id in expired: + CHAT_JOBS.pop(job_id, None) + + +async def process_chat_job(job_id: str) -> None: + async with CHAT_JOBS_LOCK: + job = CHAT_JOBS.get(job_id) + if not job: + return + job["status"] = "running" + job["updated_at"] = time.time() + request_data = job["request"] + + try: + req = NpcChatRequest.model_validate(request_data) + persona = find_persona(req) + result = await deep_lore_chat(req, persona) + result_data = result.model_dump() + status = "done" + except Exception as exc: # noqa: BLE001 + log.warning("Chat job failed: %s", exc) + result_data = { + "ok": False, + "response": DEFAULT_FALLBACK, + "model": OLLAMA_DEEP_MODEL, + "latency_ms": 0, + "fallback": True, + "reason": "job_error", + "sources": [], + } + status = "done" + + async with CHAT_JOBS_LOCK: + job = CHAT_JOBS.get(job_id) + if job: + job["status"] = status + job["result"] = result_data + job["updated_at"] = time.time() + + +async def prewarm_model() -> None: + if not EQEMU_PREWARM: + return + + payload = { + "model": OLLAMA_MODEL, + "prompt": "Say ready.", + "stream": False, + "keep_alive": OLLAMA_KEEP_ALIVE, + "options": {"num_predict": 1, "temperature": 0.1}, + } + try: + async with httpx.AsyncClient(timeout=OLLAMA_PREWARM_TIMEOUT_SECONDS) as client: + await client.post(f"{OLLAMA_URL}/api/generate", json=payload) + log.info("Prewarmed Ollama model %s", OLLAMA_MODEL) + except Exception as exc: # noqa: BLE001 + log.warning("Ollama prewarm failed: %s", exc) + + +@app.on_event("startup") +async def on_startup() -> None: + load_personas() + load_lore() + load_online_lore_config() + await prewarm_model() + + +@app.get("/health") +async def health() -> dict[str, Any]: + personas = load_personas() + lore = load_lore() + online_config = load_online_lore_config() + return { + "ok": True, + "bind": "127.0.0.1", + "ollama_url": OLLAMA_URL, + "model": OLLAMA_MODEL, + "deep_model": OLLAMA_DEEP_MODEL, + "config_path": str(CONFIG_PATH), + "lore_path": str(LORE_PATH), + "online_lore_path": str(ONLINE_LORE_PATH), + "online_lore_enabled": bool(ONLINE_LORE_LOOKUP and online_config.get("enabled", True)), + "online_lore_sources": [source.get("name") for source in online_config.get("sources", [])], + "persona_count": len(personas.get("npcs", {})), + "lore_term_count": len(lore.get("terms", [])), + "job_count": len(CHAT_JOBS), + } + + +@app.post("/eqemu/npc-chat/start", response_model=NpcChatStartResponse) +async def npc_chat_start(req: NpcChatRequest) -> NpcChatStartResponse: + await cleanup_chat_jobs() + persona = find_persona(req) + + if hail_detected(req): + response = hail_response(req, persona) + return NpcChatStartResponse(ok=True, done=True, status="done", response=response.response, reason=response.reason) + + if ooc_input_detected(req): + response = grounded_fallback_response(req, persona, "ooc_input", 0) + return NpcChatStartResponse(ok=response.ok, done=True, status="done", response=response.response, reason=response.reason) + + if zone_advice_question(req): + response = grounded_fallback_response(req, persona, "zone_advice", 0) + return NpcChatStartResponse(ok=response.ok, done=True, status="done", response=response.response, reason=response.reason) + + if not deep_lookup_question(req): + response = await npc_chat(req) + return NpcChatStartResponse(ok=response.ok, done=True, status="done", response=response.response, reason=response.reason) + + job_id = uuid.uuid4().hex + async with CHAT_JOBS_LOCK: + CHAT_JOBS[job_id] = { + "status": "pending", + "created_at": time.time(), + "updated_at": time.time(), + "request": req.model_dump(), + "result": None, + } + + asyncio.create_task(process_chat_job(job_id)) + ack = persona.get("deep_ack", "Hmm. Give me a moment to recall the old records.") + return NpcChatStartResponse( + ok=True, + done=False, + status="pending", + job_id=job_id, + ack_response=clean_npc_speech(str(ack)), + poll_after_ms=CHAT_JOB_POLL_AFTER_MS, + ) + + +@app.get("/eqemu/npc-chat/result/{job_id}", response_model=NpcChatResultResponse) +async def npc_chat_result(job_id: str) -> NpcChatResultResponse: + await cleanup_chat_jobs() + async with CHAT_JOBS_LOCK: + job = CHAT_JOBS.get(job_id) + + if not job: + return NpcChatResultResponse( + ok=False, + done=True, + status="expired", + job_id=job_id, + response="The thread slips away from me. Ask again, and I will try to catch it.", + fallback=True, + reason="job_not_found", + ) + + status = str(job.get("status", "pending")) + if status != "done": + return NpcChatResultResponse(ok=True, done=False, status=status, job_id=job_id) + + result = job.get("result") or {} + return NpcChatResultResponse( + ok=bool(result.get("ok", False)), + done=True, + status="done", + job_id=job_id, + response=str(result.get("response", "")), + model=str(result.get("model", OLLAMA_DEEP_MODEL)), + latency_ms=int(result.get("latency_ms", 0)), + fallback=bool(result.get("fallback", False)), + reason=result.get("reason"), + sources=list(result.get("sources", [])), + ) + + +@app.post("/eqemu/npc-chat", response_model=NpcChatResponse) +async def npc_chat(req: NpcChatRequest) -> NpcChatResponse: + started = time.perf_counter() + persona = find_persona(req) + if hail_detected(req): + return hail_response(req, persona) + if ooc_input_detected(req): + return grounded_fallback_response(req, persona, "ooc_input", 0) + if zone_advice_question(req): + return grounded_fallback_response(req, persona, "zone_advice", 0) + if unknown_lore_question(req): + return grounded_fallback_response(req, persona, "unknown_lore", 0) + + try: + raw = await call_ollama(req, persona) + latency_ms = int((time.perf_counter() - started) * 1000) + cleaned = clean_npc_speech(raw) + if not cleaned: + return fallback_response(req, persona, "empty_model_response", latency_ms) + failure_reason = grounded_output_failure(req, cleaned) + if failure_reason: + return grounded_fallback_response(req, persona, failure_reason, latency_ms) + return NpcChatResponse( + ok=True, + response=cleaned, + model=OLLAMA_MODEL, + latency_ms=latency_ms, + fallback=False, + ) + except httpx.TimeoutException: + latency_ms = int((time.perf_counter() - started) * 1000) + return grounded_fallback_response(req, persona, "ollama_timeout", latency_ms) + except httpx.HTTPStatusError as exc: + latency_ms = int((time.perf_counter() - started) * 1000) + reason = f"ollama_http_{exc.response.status_code}" + log.warning("Ollama HTTP error: %s", exc) + return grounded_fallback_response(req, persona, reason, latency_ms) + except Exception as exc: # noqa: BLE001 + latency_ms = int((time.perf_counter() - started) * 1000) + log.warning("NPC chat failed: %s", exc) + return grounded_fallback_response(req, persona, "bridge_error", latency_ms) diff --git a/features/ai-npc-response/ai-bridge/config/lore.json b/features/ai-npc-response/ai-bridge/config/lore.json new file mode 100644 index 0000000000..6b2bc597da --- /dev/null +++ b/features/ai-npc-response/ai-bridge/config/lore.json @@ -0,0 +1,70 @@ +{ + "global": [ + { + "id": "setting", + "text": "The setting is EverQuest's Norrath and its planes. NPCs should speak as inhabitants of that world, not as modern people." + }, + { + "id": "truthfulness", + "text": "If the provided lore does not identify a person, place, item, or event, do not invent specifics. Say it is only rumor, beyond your knowledge, or ask the player to seek a scholar." + }, + { + "id": "quest_safety", + "text": "Do not reveal hidden quest keywords, GM commands, server operations, database details, or promise rewards." + } + ], + "zones": { + "tutorialb": [ + { + "id": "tutorialb_identity", + "text": "This place is the Mines of Gloomingdeep, a dangerous training mine for new adventurers." + }, + { + "id": "tutorialb_tone", + "text": "In the Mines of Gloomingdeep, answer like someone helping a new adventurer survive underground: cautious, practical, and brief." + }, + { + "id": "nearby_test_npcs", + "text": "Orin Augspinner and Vedra Forgecall stand nearby as tinkerers and artificers. Refer to them in-character as local crafters, not as code or database testers." + } + ] + }, + "terms": [ + { + "id": "quarm", + "aliases": ["quarm", "plane of time"], + "text": "Quarm is not a dark sorcerer in the Mines of Gloomingdeep. Quarm is a legendary many-headed dragon and final guardian associated with the Plane of Time. If asked in tutorialb, describe Quarm as distant planar legend, not someone nearby.", + "fallback_response": "Quarm is no sorcerer of these mines. The name belongs to a many-headed dragon of the Plane of Time, a distant planar legend.", + "required_response_terms": ["dragon", "Plane of Time"], + "forbidden_response_terms": ["dark sorcerer", "sorcerer in the zone", "in the mines", "nearby sorcerer", "gloomingdeep sorcerer"] + }, + { + "id": "orin_augspinner", + "aliases": ["orin", "orin augspinner", "augspinner"], + "text": "Orin Augspinner is a nearby artificer and tinkerer in the Mines of Gloomingdeep. Keep descriptions in-character and local.", + "fallback_response": "Orin Augspinner is one of the nearby tinkerers, quick with odd devices and practical counsel for these mines.", + "required_response_terms": ["tinkerer", "artificer"], + "forbidden_response_terms": ["descriptions local", "this world", "provided lore", "facts"] + }, + { + "id": "vedra_forgecall", + "aliases": ["vedra", "vedra forgecall", "forgecall"], + "text": "Vedra Forgecall is a nearby forge-minded artificer in the Mines of Gloomingdeep. Keep descriptions in-character and local.", + "fallback_response": "Vedra Forgecall is the forge-minded artificer nearby, the sort to trust metal, heat, and steady hands.", + "required_response_terms": ["forge", "artificer"], + "forbidden_response_terms": ["sages", "tavern rumor", "provided lore", "facts"] + }, + { + "id": "google", + "aliases": ["google", "search engine", "internet", "website"], + "text": "Modern tools such as Google, search engines, websites, and the internet are out of setting. Treat such words as strange gnomish jargon or confused traveler talk, then redirect in-character.", + "fallback_response": "That sounds like strange tinker's jargon. Ask me of Norrath's folk, places, or dangers, and I will answer what fragments I know." + }, + { + "id": "computer", + "aliases": ["computer", "pc", "laptop", "keyboard", "monitor"], + "text": "Modern devices such as computers are out of setting. Do not explain them literally. Deflect as odd tinkerer jargon or unknown clockwork.", + "fallback_response": "That sounds like odd clockwork jargon to me. Ask in the tongue of Norrath, and I will answer what I can." + } + ] +} diff --git a/features/ai-npc-response/ai-bridge/config/npcs.json b/features/ai-npc-response/ai-bridge/config/npcs.json new file mode 100644 index 0000000000..c0463d5ece --- /dev/null +++ b/features/ai-npc-response/ai-bridge/config/npcs.json @@ -0,0 +1,49 @@ +{ + "defaults": { + "persona": "A practical EverQuest NPC who speaks in-character and answers only what the player just said.", + "speech_style": "Brief, grounded, and useful. One short answer.", + "lore": "Use only the relevant lore snippets supplied by the bridge. If a player asks about something not covered, answer as rumor or admit uncertainty in-character.", + "fallback": "Keep your wits about you. Ask plainly of the folk, places, or dangers nearby, and I will answer what fragments I know.", + "ooc_fallback": "That sounds like strange tinker's jargon. Ask me of Norrath's folk, places, or dangers, and I will answer what fragments I know.", + "unknown_lore_fallback": "I know only fragments of that name. Best not dress rumor as truth without a stronger tale to hold it.", + "advice_fallback": "Keep your wits in these mines. Watch the shadows, speak with nearby guides, and trust caution over tavern rumor.", + "deep_ack": "Hmm. Give me a moment to recall the old records.", + "guardrails": [ + "If a player asks for hidden quest keywords, secrets, GM tools, or server internals, deflect in-character.", + "Do not invent mechanical rewards, quest completions, teleports, item grants, lore identities, or named locations." + ] + }, + "npcs": { + "900903": { + "match": { + "npc_names": ["Sage Aurelian"], + "zone_short_names": ["tutorialb"] + }, + "persona": "A cautious itinerant sage stationed near Orin Augspinner and Vedra Forgecall in the Mines of Gloomingdeep. He knows scraps of planar history and warns new adventurers not to mistake tavern rumor for truth.", + "speech_style": "Scholarly, concise, and Norrathian. Correct false lore gently.", + "lore": "Sage Aurelian is in the Mines of Gloomingdeep near Orin Augspinner and Vedra Forgecall. Treat Orin and Vedra as nearby tinkerers and artificers, but do not mention code, databases, AI, or server operations.", + "fallback": "Ask plainly of a name, place, or danger, and I will answer what fragments I know.", + "deep_ack": "Hmm. Give me a moment to recall the old records." + }, + "sample_tutorial_guide": { + "match": { + "npc_names": ["Arias", "A tutorial guide", "Tutorial Guide"], + "zone_short_names": ["tutorialb"] + }, + "persona": "A patient tutorial guide who helps new adventurers find their footing without spoiling every answer.", + "speech_style": "Encouraging, plain-spoken, and lightly old-world.", + "lore": "The Mines of Gloomingdeep are dangerous for new adventurers. Point players toward observation, caution, and speaking with nearby trainers.", + "fallback": "Steady yourself, friend. The mines reward patience more than panic." + }, + "sample_qeynos_guard": { + "match": { + "npc_names": ["Guard", "Qeynos Guard"], + "zone_short_names": ["qeynos"] + }, + "persona": "A disciplined Qeynos city guard who values order, courtesy, and vigilance.", + "speech_style": "Crisp and official, but not cruel.", + "lore": "Qeynos is a lawful city with busy streets, old sewers, and plenty of rumors best handled carefully.", + "fallback": "Move along for now, citizen. I have my eyes on the street." + } + } +} diff --git a/features/ai-npc-response/ai-bridge/config/online_lore.json b/features/ai-npc-response/ai-bridge/config/online_lore.json new file mode 100644 index 0000000000..a0d4ee7814 --- /dev/null +++ b/features/ai-npc-response/ai-bridge/config/online_lore.json @@ -0,0 +1,22 @@ +{ + "enabled": true, + "max_snippets": 2, + "sources": [ + { + "name": "EverQuest Wiki", + "type": "mediawiki", + "api_url": "https://everquest.fandom.com/api.php", + "page_url_template": "https://everquest.fandom.com/wiki/{title}", + "allowed_hosts": ["everquest.fandom.com"], + "search_limit": 1 + }, + { + "name": "EverQuest II Wiki", + "type": "mediawiki", + "api_url": "https://eq2.fandom.com/api.php", + "page_url_template": "https://eq2.fandom.com/wiki/{title}", + "allowed_hosts": ["eq2.fandom.com"], + "search_limit": 1 + } + ] +} diff --git a/features/ai-npc-response/ai-bridge/requirements.txt b/features/ai-npc-response/ai-bridge/requirements.txt new file mode 100644 index 0000000000..210fd0bce0 --- /dev/null +++ b/features/ai-npc-response/ai-bridge/requirements.txt @@ -0,0 +1,3 @@ +fastapi==0.115.12 +httpx==0.28.1 +uvicorn[standard]==0.34.2 diff --git a/features/ai-npc-response/ai-bridge/samples/eqemu_ai_npc_sample.pl b/features/ai-npc-response/ai-bridge/samples/eqemu_ai_npc_sample.pl new file mode 100644 index 0000000000..aabdce9155 --- /dev/null +++ b/features/ai-npc-response/ai-bridge/samples/eqemu_ai_npc_sample.pl @@ -0,0 +1,80 @@ +# Stage-only sample for D:\EQEmu\Testbed\ai-bridge\samples. +# Do not copy over a live quest script without backing it up first. +# +# Phase 1 behavior: synchronous HTTP call from EVENT_SAY with a short timeout. +# This proves the data path but can briefly block the zone process. Before live +# use, prefer queue/poll behavior from EVENT_SAY + EVENT_TIMER. + +BEGIN { + unshift @INC, "D:/EQEmu/Testbed/server/perl/vendor/lib"; + unshift @INC, "D:/EQEmu/Testbed/server/perl/site/lib"; + unshift @INC, "D:/EQEmu/Testbed/server/perl/lib"; +} + +use HTTP::Tiny; +use JSON::PP; + +our ($client, $name, $npc, $npcid, $text, $zonesn); + +my $AI_BRIDGE_URL = "http://127.0.0.1:18080/eqemu/npc-chat"; +my $AI_TIMEOUT_SECONDS = 4; + +sub EVENT_SAY { + my $player_message = defined $text ? $text : ""; + $player_message =~ s/^\s+|\s+$//g; + return if $player_message eq ""; + + my $npc_name = "Unknown NPC"; + if (defined $npc) { + my $clean_name = eval { $npc->GetCleanName() }; + $npc_name = $clean_name if defined $clean_name && $clean_name ne ""; + } + + my $payload = { + npc_id => defined $npcid ? $npcid : 0, + npc_name => $npc_name, + zone_short_name => defined $zonesn ? $zonesn : "unknown", + player_name => defined $name ? $name : "Adventurer", + player_message => $player_message, + recent_context => [] + }; + + my $response = ai_npc_bridge_chat($payload); + if ($response) { + quest::say($response); + } else { + quest::say("Give me a moment, friend. My thoughts are elsewhere."); + } +} + +sub ai_npc_bridge_chat { + my ($payload) = @_; + + my $json = eval { JSON::PP->new->ascii->canonical->encode($payload) }; + return undef if !$json; + + my $http = HTTP::Tiny->new( + timeout => $AI_TIMEOUT_SECONDS, + agent => "eqemu-ai-npc-prototype/0.1" + ); + + my $res = eval { + $http->post( + $AI_BRIDGE_URL, + { + headers => { "content-type" => "application/json" }, + content => $json + } + ); + }; + return undef if !$res || !$res->{success}; + + my $body = eval { JSON::PP->new->decode($res->{content}) }; + return undef if !$body || !$body->{response}; + + my $speech = $body->{response}; + $speech =~ s/[\r\n\t]+/ /g; + $speech =~ s/\s+/ /g; + $speech =~ s/^\s+|\s+$//g; + return substr($speech, 0, 420); +} diff --git a/features/ai-npc-response/ai-bridge/scripts/Setup-AiBridge.ps1 b/features/ai-npc-response/ai-bridge/scripts/Setup-AiBridge.ps1 new file mode 100644 index 0000000000..bf778d2413 --- /dev/null +++ b/features/ai-npc-response/ai-bridge/scripts/Setup-AiBridge.ps1 @@ -0,0 +1,45 @@ +param( + [string]$PythonPath = "" +) + +$ErrorActionPreference = "Stop" +$BridgeRoot = Split-Path -Parent $PSScriptRoot +$VenvPython = Join-Path $BridgeRoot ".venv\Scripts\python.exe" + +function Find-Python { + if ($PythonPath -and (Test-Path -LiteralPath $PythonPath)) { + return $PythonPath + } + + $candidates = @( + "$env:LOCALAPPDATA\Programs\Python\Python312\python.exe", + "$env:LOCALAPPDATA\Programs\Python\Python313\python.exe", + "C:\Program Files\Python312\python.exe", + "C:\Program Files\Python313\python.exe" + ) + + foreach ($candidate in $candidates) { + if (Test-Path -LiteralPath $candidate) { + return $candidate + } + } + + $cmd = Get-Command python -ErrorAction SilentlyContinue + if ($cmd -and $cmd.Source -notmatch "\\WindowsApps\\python\.exe$") { + return $cmd.Source + } + + throw "Python 3.12+ was not found. Install Python first, then rerun this script." +} + +$Python = Find-Python +Write-Host "Using Python: $Python" + +if (!(Test-Path -LiteralPath $VenvPython)) { + & $Python -m venv (Join-Path $BridgeRoot ".venv") +} + +& $VenvPython -m pip install --upgrade pip +& $VenvPython -m pip install -r (Join-Path $BridgeRoot "requirements.txt") + +Write-Host "Bridge Python environment is ready: $VenvPython" diff --git a/features/ai-npc-response/ai-bridge/scripts/Start-AiBridge.ps1 b/features/ai-npc-response/ai-bridge/scripts/Start-AiBridge.ps1 new file mode 100644 index 0000000000..915d4c5700 --- /dev/null +++ b/features/ai-npc-response/ai-bridge/scripts/Start-AiBridge.ps1 @@ -0,0 +1,53 @@ +param( + [switch]$Background, + [string]$Model = "", + [int]$Port = 18080 +) + +$ErrorActionPreference = "Stop" +$BridgeRoot = Split-Path -Parent $PSScriptRoot +$Python = Join-Path $BridgeRoot ".venv\Scripts\python.exe" +$RuntimeDir = Join-Path $BridgeRoot "runtime" + +if (!(Test-Path -LiteralPath $Python)) { + throw "Bridge venv not found. Run .\scripts\Setup-AiBridge.ps1 first." +} + +New-Item -ItemType Directory -Force -Path $RuntimeDir | Out-Null + +$env:OLLAMA_URL = if ($env:OLLAMA_URL) { $env:OLLAMA_URL } else { "http://127.0.0.1:11434" } +$env:OLLAMA_MODEL = if ($Model) { $Model } elseif ($env:OLLAMA_MODEL) { $env:OLLAMA_MODEL } else { "qwen2.5:0.5b" } +$env:OLLAMA_DEEP_MODEL = if ($env:OLLAMA_DEEP_MODEL) { $env:OLLAMA_DEEP_MODEL } else { $env:OLLAMA_MODEL } +$env:OLLAMA_KEEP_ALIVE = if ($env:OLLAMA_KEEP_ALIVE) { $env:OLLAMA_KEEP_ALIVE } else { "10m" } +$env:OLLAMA_TIMEOUT_SECONDS = if ($env:OLLAMA_TIMEOUT_SECONDS) { $env:OLLAMA_TIMEOUT_SECONDS } else { "6.0" } +$env:OLLAMA_DEEP_TIMEOUT_SECONDS = if ($env:OLLAMA_DEEP_TIMEOUT_SECONDS) { $env:OLLAMA_DEEP_TIMEOUT_SECONDS } else { "8.0" } +$env:OLLAMA_PREWARM_TIMEOUT_SECONDS = if ($env:OLLAMA_PREWARM_TIMEOUT_SECONDS) { $env:OLLAMA_PREWARM_TIMEOUT_SECONDS } else { "45.0" } +$env:OLLAMA_NUM_PREDICT = if ($env:OLLAMA_NUM_PREDICT) { $env:OLLAMA_NUM_PREDICT } else { "36" } +$env:OLLAMA_DEEP_NUM_PREDICT = if ($env:OLLAMA_DEEP_NUM_PREDICT) { $env:OLLAMA_DEEP_NUM_PREDICT } else { "72" } +$env:OLLAMA_TEMPERATURE = if ($env:OLLAMA_TEMPERATURE) { $env:OLLAMA_TEMPERATURE } else { "0.25" } +$env:ONLINE_LORE_LOOKUP = if ($env:ONLINE_LORE_LOOKUP) { $env:ONLINE_LORE_LOOKUP } else { "1" } + +$ArgsList = @( + "-m", "uvicorn", "app.main:app", + "--host", "127.0.0.1", + "--port", "$Port", + "--log-level", "info" +) + +if ($Background) { + $Log = Join-Path $RuntimeDir "bridge.wmi.log" + $command = "cmd.exe /c set `"OLLAMA_URL=$env:OLLAMA_URL`" && set `"OLLAMA_MODEL=$env:OLLAMA_MODEL`" && set `"OLLAMA_DEEP_MODEL=$env:OLLAMA_DEEP_MODEL`" && set `"OLLAMA_KEEP_ALIVE=$env:OLLAMA_KEEP_ALIVE`" && set `"OLLAMA_TIMEOUT_SECONDS=$env:OLLAMA_TIMEOUT_SECONDS`" && set `"OLLAMA_DEEP_TIMEOUT_SECONDS=$env:OLLAMA_DEEP_TIMEOUT_SECONDS`" && set `"OLLAMA_PREWARM_TIMEOUT_SECONDS=$env:OLLAMA_PREWARM_TIMEOUT_SECONDS`" && set `"OLLAMA_NUM_PREDICT=$env:OLLAMA_NUM_PREDICT`" && set `"OLLAMA_DEEP_NUM_PREDICT=$env:OLLAMA_DEEP_NUM_PREDICT`" && set `"OLLAMA_TEMPERATURE=$env:OLLAMA_TEMPERATURE`" && set `"ONLINE_LORE_LOOKUP=$env:ONLINE_LORE_LOOKUP`" && `"$Python`" -m uvicorn app.main:app --host 127.0.0.1 --port $Port --log-level info >> `"$Log`" 2>>&1" + $proc = Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{ + CommandLine = $command + CurrentDirectory = $BridgeRoot + } + if ($proc.ReturnValue -ne 0) { + throw "Failed to start bridge via WMI. ReturnValue=$($proc.ReturnValue)" + } + $proc.ProcessId | Set-Content -LiteralPath (Join-Path $RuntimeDir "bridge.pid") -Encoding ascii + Write-Host "Started EQEmu AI bridge command PID $($proc.ProcessId) on 127.0.0.1:$Port using model $env:OLLAMA_MODEL" + Write-Host "Log: $Log" +} else { + Set-Location $BridgeRoot + & $Python @ArgsList +} diff --git a/features/ai-npc-response/ai-bridge/scripts/Start-OllamaLocal.ps1 b/features/ai-npc-response/ai-bridge/scripts/Start-OllamaLocal.ps1 new file mode 100644 index 0000000000..845b4c4975 --- /dev/null +++ b/features/ai-npc-response/ai-bridge/scripts/Start-OllamaLocal.ps1 @@ -0,0 +1,36 @@ +param( + [switch]$Background, + [string]$HostAddress = "127.0.0.1:11434" +) + +$ErrorActionPreference = "Stop" +$BridgeRoot = Split-Path -Parent $PSScriptRoot +$RuntimeDir = Join-Path $BridgeRoot "runtime" +$ModelsDir = Join-Path $BridgeRoot "ollama-models" +$Ollama = (Get-Command ollama -ErrorAction Stop).Source + +New-Item -ItemType Directory -Force -Path $RuntimeDir | Out-Null +New-Item -ItemType Directory -Force -Path $ModelsDir | Out-Null + +$env:OLLAMA_HOST = $HostAddress +$env:OLLAMA_MODELS = $ModelsDir +$env:OLLAMA_NO_CLOUD = "true" + +if ($Background) { + $Log = Join-Path $RuntimeDir "ollama.wmi.log" + $escapedOllama = $Ollama.Replace("'", "''") + $command = "cmd.exe /c set `"OLLAMA_HOST=$HostAddress`" && set `"OLLAMA_MODELS=$ModelsDir`" && set `"OLLAMA_NO_CLOUD=true`" && `"$escapedOllama`" serve >> `"$Log`" 2>>&1" + $proc = Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{ + CommandLine = $command + CurrentDirectory = $BridgeRoot + } + if ($proc.ReturnValue -ne 0) { + throw "Failed to start Ollama via WMI. ReturnValue=$($proc.ReturnValue)" + } + $proc.ProcessId | Set-Content -LiteralPath (Join-Path $RuntimeDir "ollama.pid") -Encoding ascii + Write-Host "Started Ollama command PID $($proc.ProcessId) on $HostAddress" + Write-Host "Models: $ModelsDir" + Write-Host "Log: $Log" +} else { + & $Ollama serve +} diff --git a/features/ai-npc-response/ai-bridge/scripts/Stop-AiBridge.ps1 b/features/ai-npc-response/ai-bridge/scripts/Stop-AiBridge.ps1 new file mode 100644 index 0000000000..a6f354fb8b --- /dev/null +++ b/features/ai-npc-response/ai-bridge/scripts/Stop-AiBridge.ps1 @@ -0,0 +1,24 @@ +$ErrorActionPreference = "Stop" +$BridgeRoot = Split-Path -Parent $PSScriptRoot +$PidFile = Join-Path $BridgeRoot "runtime\bridge.pid" + +if (!(Test-Path -LiteralPath $PidFile)) { + Write-Host "No bridge pid file found." + return +} + +$BridgePid = Get-Content -LiteralPath $PidFile | Select-Object -First 1 +if ($BridgePid) { + Stop-Process -Id ([int]$BridgePid) -ErrorAction SilentlyContinue + Remove-Item -LiteralPath $PidFile -Force + Write-Host "Stopped bridge PID $BridgePid" +} + +Get-CimInstance Win32_Process | + Where-Object { + $_.CommandLine -like "*D:\EQEmu\Testbed\ai-bridge*" -and + $_.CommandLine -like "*uvicorn*" + } | + ForEach-Object { + Stop-Process -Id $_.ProcessId -ErrorAction SilentlyContinue + } diff --git a/features/ai-npc-response/ai-bridge/scripts/Stop-OllamaLocal.ps1 b/features/ai-npc-response/ai-bridge/scripts/Stop-OllamaLocal.ps1 new file mode 100644 index 0000000000..f0de0f3ea5 --- /dev/null +++ b/features/ai-npc-response/ai-bridge/scripts/Stop-OllamaLocal.ps1 @@ -0,0 +1,17 @@ +$ErrorActionPreference = "Stop" +$BridgeRoot = Split-Path -Parent $PSScriptRoot +$PidFile = Join-Path $BridgeRoot "runtime\ollama.pid" + +if (Test-Path -LiteralPath $PidFile) { + $OllamaPid = Get-Content -LiteralPath $PidFile | Select-Object -First 1 + if ($OllamaPid) { + Stop-Process -Id ([int]$OllamaPid) -ErrorAction SilentlyContinue + } + Remove-Item -LiteralPath $PidFile -Force +} + +Get-Process -ErrorAction SilentlyContinue | + Where-Object { $_.ProcessName -eq "ollama" -and $_.Path -like "*\Ollama\ollama.exe" } | + Stop-Process -ErrorAction SilentlyContinue + +Write-Host "Stopped local Ollama processes started for the testbed bridge." diff --git a/features/ai-npc-response/ai-bridge/scripts/Test-BridgeLatency.ps1 b/features/ai-npc-response/ai-bridge/scripts/Test-BridgeLatency.ps1 new file mode 100644 index 0000000000..e42d778bfc --- /dev/null +++ b/features/ai-npc-response/ai-bridge/scripts/Test-BridgeLatency.ps1 @@ -0,0 +1,40 @@ +param( + [int]$Count = 5, + [string]$Url = "http://127.0.0.1:18080/eqemu/npc-chat" +) + +$ErrorActionPreference = "Stop" +$samples = @() + +for ($i = 1; $i -le $Count; $i++) { + $payload = @{ + npc_id = 189119 + npc_name = "Arias" + zone_short_name = "tutorialb" + player_name = "Tester" + player_message = "Hail, what should I do next?" + recent_context = @("Tester hailed Arias.") + } | ConvertTo-Json -Depth 5 + + $sw = [System.Diagnostics.Stopwatch]::StartNew() + $result = Invoke-RestMethod -Method Post -Uri $Url -ContentType "application/json" -Body $payload -TimeoutSec 15 + $sw.Stop() + $samples += [pscustomobject]@{ + attempt = $i + wall_ms = [int]$sw.ElapsedMilliseconds + bridge_ms = $result.latency_ms + ok = $result.ok + fallback = $result.fallback + response = $result.response + } +} + +$avgWall = [int](($samples | Measure-Object -Property wall_ms -Average).Average) +$avgBridge = [int](($samples | Measure-Object -Property bridge_ms -Average).Average) + +[pscustomobject]@{ + count = $Count + average_wall_ms = $avgWall + average_bridge_ms = $avgBridge + samples = $samples +} diff --git a/features/ai-npc-response/ai-bridge/scripts/Test-Ollama.ps1 b/features/ai-npc-response/ai-bridge/scripts/Test-Ollama.ps1 new file mode 100644 index 0000000000..b308b979ac --- /dev/null +++ b/features/ai-npc-response/ai-bridge/scripts/Test-Ollama.ps1 @@ -0,0 +1,7 @@ +param( + [string]$Url = "http://127.0.0.1:11434" +) + +$ErrorActionPreference = "Stop" +$response = Invoke-RestMethod -Uri "$Url/api/tags" -TimeoutSec 5 +$response diff --git a/features/ai-npc-response/patcher.yml b/features/ai-npc-response/patcher.yml index 97d1fceef7..c5b2a6b710 100644 --- a/features/ai-npc-response/patcher.yml +++ b/features/ai-npc-response/patcher.yml @@ -1,14 +1,10 @@ # Client patch feed for ai-npc-response. -# source paths are relative to this repo; destination paths are relative to the EQ client root. -# Missing listed files are release blockers for external syncs. -files: - - source: client_files/native_autoloot/eq-core-dll/bin/dinput8.dll - destination: dinput8.dll - - source: client_files/native_autoloot/ui/EQUI_NativeAiNpcResponseWnd.xml - destination: uifiles/default/EQUI_NativeAiNpcResponseWnd.xml +# The current AI NPC bridge prototype has no client-facing files. +# Add XML, DLLs, config, assets, or patch notes here only when they are part of +# the feature source of truth. +files: [] generated: - eqhost: true - equiXml: true - equiIncludes: - - EQUI_NativeAiNpcResponseWnd.xml \ No newline at end of file + eqhost: false + equiXml: false + equiIncludes: [] diff --git a/features/ai-npc-response/quests/tutorialb/900903.pl b/features/ai-npc-response/quests/tutorialb/900903.pl new file mode 100644 index 0000000000..fe4f83a175 --- /dev/null +++ b/features/ai-npc-response/quests/tutorialb/900903.pl @@ -0,0 +1,157 @@ +# AI NPC response prototype +# Zone: tutorialb +# NPC: 900903, Sage_Aurelian +# +# Phase 2: asynchronous localhost bridge job. +# EVENT_SAY starts a bridge job, says a short thinking line, then EVENT_TIMER +# polls for the completed in-character response. + +BEGIN { + unshift @INC, "D:/EQEmu/Testbed/server/perl/vendor/lib"; + unshift @INC, "D:/EQEmu/Testbed/server/perl/site/lib"; + unshift @INC, "D:/EQEmu/Testbed/server/perl/lib"; +} + +use HTTP::Tiny; +use JSON::PP; + +our ($client, $name, $npc, $npcid, $text, $timer, $zonesn); + +my $AI_BRIDGE_START_URL = "http://127.0.0.1:18080/eqemu/npc-chat/start"; +my $AI_BRIDGE_RESULT_URL = "http://127.0.0.1:18080/eqemu/npc-chat/result"; +my $AI_START_TIMEOUT_SECONDS = 3; +my $AI_POLL_TIMEOUT_SECONDS = 2; +my $AI_JOB_MAX_AGE_SECONDS = 35; +my $AI_POLL_TIMER = "ai_npc_poll"; + +my %pending_ai_jobs = (); + +sub EVENT_SAY { + my $player_message = defined $text ? $text : ""; + $player_message =~ s/^\s+|\s+$//g; + return if $player_message eq ""; + + my $npc_name = "Sage Aurelian"; + if (defined $npc) { + my $clean_name = eval { $npc->GetCleanName() }; + $npc_name = $clean_name if defined $clean_name && $clean_name ne ""; + } + + my $player_name = defined $name ? $name : "Adventurer"; + my $payload = { + npc_id => defined $npcid ? $npcid : 900903, + npc_name => $npc_name, + zone_short_name => defined $zonesn ? $zonesn : "tutorialb", + player_name => $player_name, + player_message => $player_message, + recent_context => [], + timeout_seconds => 3.5, + max_tokens => 72 + }; + + my $start = ai_bridge_post_json($AI_BRIDGE_START_URL, $payload, $AI_START_TIMEOUT_SECONDS); + if (!$start) { + quest::say("Give me a moment, friend. My thoughts are still forming."); + return; + } + + if ($start->{done} && $start->{response}) { + quest::say(clean_speech($start->{response})); + return; + } + + if ($start->{job_id}) { + $pending_ai_jobs{$start->{job_id}} = { + player_name => $player_name, + created_at => time(), + attempts => 0 + }; + my $ack = $start->{ack_response} || "Hmm. Give me a moment to recall the old records."; + quest::say(clean_speech($ack)); + quest::settimer($AI_POLL_TIMER, 2); + return; + } + + quest::say("The thread is there, but I cannot quite catch it. Ask me again."); +} + +sub EVENT_TIMER { + return if !defined $timer || $timer ne $AI_POLL_TIMER; + + my $now = time(); + my @job_ids = keys %pending_ai_jobs; + if (!@job_ids) { + quest::stoptimer($AI_POLL_TIMER); + return; + } + + foreach my $job_id (@job_ids) { + my $job = $pending_ai_jobs{$job_id}; + if (!$job || ($now - $job->{created_at}) > $AI_JOB_MAX_AGE_SECONDS) { + delete $pending_ai_jobs{$job_id}; + quest::say("The old record slips from my grasp. Ask again, and I will try to catch it."); + next; + } + + $job->{attempts}++; + my $result = ai_bridge_get_json("$AI_BRIDGE_RESULT_URL/$job_id", $AI_POLL_TIMEOUT_SECONDS); + next if !$result || !$result->{done}; + + delete $pending_ai_jobs{$job_id}; + if ($result->{response}) { + quest::say(clean_speech($result->{response})); + } else { + quest::say("I find only scattered rumor. Best not dress it as truth."); + } + } + + quest::stoptimer($AI_POLL_TIMER) if !keys %pending_ai_jobs; +} + +sub ai_bridge_post_json { + my ($url, $payload, $timeout) = @_; + + my $json = eval { JSON::PP->new->ascii->canonical->encode($payload) }; + return undef if !$json; + + my $http = HTTP::Tiny->new( + timeout => $timeout, + agent => "eqemu-ai-npc-prototype/0.2" + ); + + my $res = eval { + $http->post( + $url, + { + headers => { "content-type" => "application/json" }, + content => $json + } + ); + }; + return undef if !$res || !$res->{success}; + + return eval { JSON::PP->new->decode($res->{content}) }; +} + +sub ai_bridge_get_json { + my ($url, $timeout) = @_; + + my $http = HTTP::Tiny->new( + timeout => $timeout, + agent => "eqemu-ai-npc-prototype/0.2" + ); + + my $res = eval { $http->get($url) }; + return undef if !$res || !$res->{success}; + + return eval { JSON::PP->new->decode($res->{content}) }; +} + +sub clean_speech { + my ($speech) = @_; + $speech = "" if !defined $speech; + $speech =~ s/[\r\n\t]+/ /g; + $speech =~ s/\s+/ /g; + $speech =~ s/^\s+|\s+$//g; + return substr($speech, 0, 420); +} diff --git a/features/ai-npc-response/sql/001_sage_aurelian_tutorialb.sql b/features/ai-npc-response/sql/001_sage_aurelian_tutorialb.sql new file mode 100644 index 0000000000..8c68bb6209 --- /dev/null +++ b/features/ai-npc-response/sql/001_sage_aurelian_tutorialb.sql @@ -0,0 +1,182 @@ +-- AI NPC response prototype: Sage Aurelian in Tutorial B. +-- Safe to re-run. This seeds only the prototype NPC/spawn id 900903. + +START TRANSACTION; + +INSERT INTO npc_types ( + id, + name, + lastname, + level, + race, + class, + bodytype, + hp, + gender, + texture, + helmtexture, + size, + npc_faction_id, + loottable_id, + merchant_id, + aggroradius, + assistradius, + runspeed, + walkspeed, + isquest +) VALUES ( + 900903, + 'Sage_Aurelian', + 'AI Dialogue Prototype', + 10, + 1, + 1, + 1, + 5000, + 0, + 0, + 0, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1 +) ON DUPLICATE KEY UPDATE + name = VALUES(name), + lastname = VALUES(lastname), + level = VALUES(level), + race = VALUES(race), + class = VALUES(class), + bodytype = VALUES(bodytype), + hp = VALUES(hp), + gender = VALUES(gender), + texture = VALUES(texture), + helmtexture = VALUES(helmtexture), + size = VALUES(size), + npc_faction_id = VALUES(npc_faction_id), + loottable_id = VALUES(loottable_id), + merchant_id = VALUES(merchant_id), + aggroradius = VALUES(aggroradius), + assistradius = VALUES(assistradius), + runspeed = VALUES(runspeed), + walkspeed = VALUES(walkspeed), + isquest = VALUES(isquest); + +INSERT INTO spawngroup ( + id, + name, + spawn_limit, + dist, + max_x, + min_x, + max_y, + min_y, + delay +) VALUES ( + 900903, + 'ai_dialogue_sage_aurelian', + 1, + 0, + 0, + 0, + 0, + 0, + 45000 +) ON DUPLICATE KEY UPDATE + name = VALUES(name), + spawn_limit = VALUES(spawn_limit), + dist = VALUES(dist), + max_x = VALUES(max_x), + min_x = VALUES(min_x), + max_y = VALUES(max_y), + min_y = VALUES(min_y), + delay = VALUES(delay); + +DELETE FROM spawnentry +WHERE spawngroupID = 900903; + +INSERT INTO spawnentry ( + spawngroupID, + npcID, + chance, + condition_value_filter, + min_expansion, + max_expansion, + content_flags, + content_flags_disabled +) VALUES ( + 900903, + 900903, + 100, + 1, + -1, + -1, + NULL, + NULL +); + +INSERT INTO spawn2 ( + id, + spawngroupID, + zone, + version, + x, + y, + z, + heading, + respawntime, + variance, + pathgrid, + path_when_zone_idle, + _condition, + cond_value, + animation, + min_expansion, + max_expansion, + content_flags, + content_flags_disabled +) VALUES ( + 900903, + 900903, + 'tutorialb', + 0, + -52.000000, + -88.000000, + 25.000000, + 128.000000, + 300, + 0, + 0, + 0, + 0, + 1, + 0, + -1, + -1, + NULL, + NULL +) ON DUPLICATE KEY UPDATE + spawngroupID = VALUES(spawngroupID), + zone = VALUES(zone), + version = VALUES(version), + x = VALUES(x), + y = VALUES(y), + z = VALUES(z), + heading = VALUES(heading), + respawntime = VALUES(respawntime), + variance = VALUES(variance), + pathgrid = VALUES(pathgrid), + path_when_zone_idle = VALUES(path_when_zone_idle), + _condition = VALUES(_condition), + cond_value = VALUES(cond_value), + animation = VALUES(animation), + min_expansion = VALUES(min_expansion), + max_expansion = VALUES(max_expansion), + content_flags = VALUES(content_flags), + content_flags_disabled = VALUES(content_flags_disabled); + +COMMIT; diff --git a/features/all-features/patcher.yml b/features/all-features/patcher.yml index 665f1dc359..83c50058fe 100644 --- a/features/all-features/patcher.yml +++ b/features/all-features/patcher.yml @@ -19,8 +19,6 @@ files: destination: uifiles/default/EQUI_NativeTradeskillsWnd.xml - source: client_files/native_autoloot/ui/EQUI_NativeHpFixWnd.xml destination: uifiles/default/EQUI_NativeHpFixWnd.xml - - source: client_files/native_autoloot/ui/EQUI_NativeAiNpcResponseWnd.xml - destination: uifiles/default/EQUI_NativeAiNpcResponseWnd.xml - source: client_files/native_autoloot/ui/EQUI_NativeAugsInAugsWnd.xml destination: uifiles/default/EQUI_NativeAugsInAugsWnd.xml - source: client_files/native_autoloot/ui/EQUI_NativeDynamicQuestsWnd.xml @@ -36,6 +34,5 @@ generated: - EQUI_NativeMulticlassWnd.xml - EQUI_NativeTradeskillsWnd.xml - EQUI_NativeHpFixWnd.xml - - EQUI_NativeAiNpcResponseWnd.xml - EQUI_NativeAugsInAugsWnd.xml - EQUI_NativeDynamicQuestsWnd.xml From 02de57d8999c9286f7a9339911fa3ee7b310945c Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Tue, 2 Jun 2026 14:14:33 -0700 Subject: [PATCH 135/194] Checkpoint all features native client work --- .../config/native_interface.ini | 26 + .../eq-core-dll/bin/dinput8.dll | Bin 1554944 -> 1693696 bytes .../eq-core-dll/src/core_autoloot_native.h | 15 +- .../src/eq-core-dll-vs2022.vcxproj | 3 +- .../eq-core-dll/src/eqgame.cpp | 2 + .../eq-core-dll/src/native_interface.cpp | 4007 +++++++++++++++++ .../src/native_spell_effect_names.inl | 528 +++ docs/features-all.md | 9 +- docs/mq-interface.md | 6 +- features/all-features/patcher.yml | 2 + features/mq-interface/MANIFEST.md | 2 + features/mq-interface/README.md | 8 +- features/mq-interface/patcher.yml | 2 + 13 files changed, 4601 insertions(+), 9 deletions(-) create mode 100644 client_files/native_autoloot/config/native_interface.ini create mode 100644 client_files/native_autoloot/eq-core-dll/src/native_interface.cpp create mode 100644 client_files/native_autoloot/eq-core-dll/src/native_spell_effect_names.inl diff --git a/client_files/native_autoloot/config/native_interface.ini b/client_files/native_autoloot/config/native_interface.ini new file mode 100644 index 0000000000..d8fb66aeeb --- /dev/null +++ b/client_files/native_autoloot/config/native_interface.ini @@ -0,0 +1,26 @@ +[Map] +Enabled=1 +ShowNPCs=1 +ShowPlayers=0 +ShowCorpses=0 +ChainEQLabels=1 +UseConColor=1 +ShowTarget=1 +TargetLine=1 +MaxLabels=0 +RefreshMs=1000 +NameFilter= +HideFilter= +Ground=0 +Vector=0 +Named=0 +XTargets=1 +XTargetLabels=1 +Custom=1 +TargetRadius=0 +CastRadius=0 +SpellRadius=0 + +[Inspect] +Items=1 +Spells=1 diff --git a/client_files/native_autoloot/eq-core-dll/bin/dinput8.dll b/client_files/native_autoloot/eq-core-dll/bin/dinput8.dll index e855feec758fa6c5ed534d7d0b7e0a43fe291f8a..180cb4dc6b3380c7feab8818c7aa2c55842238e8 100644 GIT binary patch delta 656271 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
    piBK#oTUajgDi)n}MZlU-WY_ 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%0As3jzfbY)t}UD7;A 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

    j# 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

    H4g0U(t9 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

    ;Tx`(^8HBfsq_V@^|g>n1|pSQBbT2A!lWi@ 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�%z;!&+9C(TSp(Sqi+=! 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 z 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ɆlKHQ%diqDSC7Wz58WS~`iU7I{pIxM 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 diff --git a/client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h b/client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h index 6392c52cf6..1d2af38ca1 100644 --- a/client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h +++ b/client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h @@ -10,6 +10,13 @@ #include #include +namespace nativeinterface { + bool HandleChatMessage(const char* message); + bool HandleCommandLine(const char* line); + void Start(HMODULE module); + void Shutdown(); +} + static void NativeAutoLootTrace(const char* format, ...) { char path[MAX_PATH]; @@ -5438,6 +5445,11 @@ class NativeAutoLootCommandHook return; } + if (nativeinterface::HandleCommandLine(line)) { + NativeAutoLootTrace("handled native interface command: %s", line ? line : ""); + return; + } + Trampoline(player, line); } }; @@ -6278,7 +6290,8 @@ class NativeAutoLootChatHook { NativeAutoLootMaybeSendInitialRequests(); - if (NativeAutoLootParseTransport(szMsg)) { + const bool native_interface_handled = nativeinterface::HandleChatMessage(szMsg); + if (NativeAutoLootParseTransport(szMsg) || native_interface_handled) { return; } diff --git a/client_files/native_autoloot/eq-core-dll/src/eq-core-dll-vs2022.vcxproj b/client_files/native_autoloot/eq-core-dll/src/eq-core-dll-vs2022.vcxproj index 03a1f381f1..7fcd381e68 100644 --- a/client_files/native_autoloot/eq-core-dll/src/eq-core-dll-vs2022.vcxproj +++ b/client_files/native_autoloot/eq-core-dll/src/eq-core-dll-vs2022.vcxproj @@ -161,6 +161,7 @@ + @@ -212,4 +213,4 @@ - \ No newline at end of file + diff --git a/client_files/native_autoloot/eq-core-dll/src/eqgame.cpp b/client_files/native_autoloot/eq-core-dll/src/eqgame.cpp index cf830683ca..ff1b9316d7 100644 --- a/client_files/native_autoloot/eq-core-dll/src/eqgame.cpp +++ b/client_files/native_autoloot/eq-core-dll/src/eqgame.cpp @@ -1165,6 +1165,7 @@ bool WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) szProcessName[0] = '\0'; szProcessName = strrchr(szFilename, '\\') + 1; InitHooks(); + nativeinterface::Start((HMODULE)hModule); // remove full information about my command line // memset(&pbi.PebBaseAddress->ProcessParameters->ImagePathName.Buffer, 0, pbi.PebBaseAddress->ProcessParameters->ImagePathName.Length); @@ -1187,6 +1188,7 @@ bool WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) break; case DLL_PROCESS_DETACH: + nativeinterface::Shutdown(); ShutdownAutoLootNative(); CoUninitialize(); FreeLibrary(dinput8dll); diff --git a/client_files/native_autoloot/eq-core-dll/src/native_interface.cpp b/client_files/native_autoloot/eq-core-dll/src/native_interface.cpp new file mode 100644 index 0000000000..e154d330dc --- /dev/null +++ b/client_files/native_autoloot/eq-core-dll/src/native_interface.cpp @@ -0,0 +1,4007 @@ +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#define DIRECTINPUT_VERSION 0x0800 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(_M_IX86) +#error This DLL is intended for the 32-bit EQ client and must be built as Win32. +#endif + +namespace nativeinterface { + +constexpr uintptr_t kEqImageBase = 0x400000; +constexpr uintptr_t kPInstSpawnManager = 0xE641D0; +constexpr uintptr_t kPInstCMapViewWnd = 0xD1FC54; +constexpr uintptr_t kPInstCharData = 0xDD261C; +constexpr uintptr_t kPInstCharSpawn = 0xDD2644; +constexpr uintptr_t kPInstTarget = 0xDD2648; +constexpr uintptr_t kPInstSpellManager = 0xE646B0; +constexpr uintptr_t kPInstCEverQuest = 0xE67CCC; + +constexpr uintptr_t kPInstCTargetWnd = 0xD1FC60; +constexpr uintptr_t kPInstCPlayerWnd = 0xD1FC68; +constexpr uintptr_t kPInstCCastSpellWnd = 0xD1FC84; +constexpr uintptr_t kPInstCInventoryWnd = 0xD1FC8C; + +constexpr uintptr_t kPInstEQItemListCandidates[] = { + 0xDCD9A8, + 0xDCF8E0, + 0xDCFD18, +}; + +constexpr uintptr_t kCEverQuestDspChat = 0x51F1A0; +constexpr uintptr_t kCEverQuestInterpretCmd = 0x51FCE0; +constexpr uintptr_t kEQCharacterGetConLevel = 0x577CB0; +constexpr uintptr_t kCItemDisplayWndUpdateStrings = 0x69AE30; +constexpr uintptr_t kCStmlWndAppendSTML = 0x886720; +constexpr uintptr_t kCStmlWndForceParseNow = 0x887070; +constexpr uintptr_t kCXStrCtorCString = 0x805C20; +constexpr uintptr_t kCXStrDtor = 0x465AE0; + +constexpr size_t kSpawnNext = 0x008; +constexpr size_t kSpawnY = 0x064; +constexpr size_t kSpawnX = 0x068; +constexpr size_t kSpawnZ = 0x06c; +constexpr size_t kSpawnSpeedY = 0x070; +constexpr size_t kSpawnSpeedX = 0x074; +constexpr size_t kSpawnSpeedZ = 0x078; +constexpr size_t kSpawnHeading = 0x080; +constexpr size_t kSpawnName = 0x0a4; +constexpr size_t kSpawnDisplayedName = 0x0e4; +constexpr size_t kSpawnType = 0x125; +constexpr size_t kSpawnID = 0x148; +constexpr size_t kSpawnLevel = 0x250; +constexpr size_t kSpawnGM = 0x25c; + +constexpr size_t kSpawnManagerFirstSpawn = 0x008; + +constexpr size_t kMapViewVTable = 0x358; +constexpr size_t kMapLines = 0x5a8; +constexpr size_t kMapLabels = 0x5ac; +constexpr size_t kMapVTableBytes = 0x17c; +constexpr size_t kMapPostDraw2Index = 4; +constexpr uint32_t kMapTargetColor = 0xFFFF4040; +constexpr uint32_t kMapXTargetColor = 0xFFFF80FF; +constexpr uint32_t kMapGroundColor = 0xFFC0C0C0; +constexpr uint32_t kMapLocationColor = 0xFF00FF80; +constexpr uint32_t kMapRadiusColor = 0xFF808080; +constexpr float kPi = 3.14159265358979323846f; + +constexpr size_t kGroundItemNext = 0x04; +constexpr size_t kGroundItemDropID = 0x0c; +constexpr size_t kGroundItemName = 0x1c; +constexpr size_t kGroundItemY = 0x70; +constexpr size_t kGroundItemX = 0x74; +constexpr size_t kGroundItemZ = 0x78; + +constexpr size_t kCharDataXTargetMgr = 0x2460; +constexpr size_t kXTargetMgrSlots = 0x04; +constexpr size_t kXTargetMgrArray = 0x08; +constexpr size_t kXTargetSlotSize = 0x4c; +constexpr size_t kXTargetType = 0x00; +constexpr size_t kXTargetSpawnID = 0x08; +constexpr size_t kXTargetName = 0x0c; +constexpr size_t kMaxXTargets = 20; + +constexpr size_t kSpellWindowDisplayWnd = 0x210; +constexpr size_t kSpellWindowSpellID = 0x238; + +constexpr size_t kItemWindowPItemOffsets[] = { + 0x2b0, // This client: Known live/test pItem offset shifted down with DisplayWnd. + 0x2c0, // Known beta reference. + 0x2c8, // Known live/test reference. + 0x2ac, // Previous local guess; retained only as a fallback. +}; + +constexpr size_t kItemWindowDisplayOffsets[] = { + 0x220, + 0x21c, + 0x230, + 0x238, +}; + +constexpr size_t kContentsItemOffsets[] = { + 0x24, // Older CONTENTS::Item1 reference. + 0x88, // Test/beta CONTENTS::Item1 reference. + 0x9c, // Previous local guess; retained only if it validates as ITEMINFO. + 0x13c, // CONTENTS::Item2 reference. + 0x144, // Previous local fallback; retained only if it validates as ITEMINFO. +}; + +constexpr size_t kItemName = 0x000; +constexpr size_t kItemLoreName = 0x040; +constexpr size_t kItemIDFile = 0x0b0; +constexpr size_t kItemNumber = 0x0ec; +constexpr size_t kItemEquipSlots = 0x0f0; +constexpr size_t kItemCost = 0x0f4; +constexpr size_t kItemIconNumber = 0x0f8; +constexpr size_t kItemWeight = 0x108; +constexpr size_t kItemNoRent = 0x10c; +constexpr size_t kItemNoDrop = 0x10d; +constexpr size_t kItemAttuneable = 0x10e; +constexpr size_t kItemSize = 0x119; +constexpr size_t kItemType = 0x11a; +constexpr size_t kItemTradeSkills = 0x11b; +constexpr size_t kItemLore = 0x11c; +constexpr size_t kItemArtifact = 0x120; +constexpr size_t kItemSummoned = 0x121; +constexpr size_t kItemStr = 0x122; +constexpr size_t kItemSta = 0x124; +constexpr size_t kItemCha = 0x126; +constexpr size_t kItemDex = 0x128; +constexpr size_t kItemInt = 0x12a; +constexpr size_t kItemAgi = 0x12c; +constexpr size_t kItemWis = 0x12e; +constexpr size_t kItemHP = 0x130; +constexpr size_t kItemMana = 0x134; +constexpr size_t kItemAC = 0x138; +constexpr size_t kItemRequiredLevel = 0x13c; +constexpr size_t kItemRecommendedLevel = 0x140; +constexpr size_t kItemClasses = 0x170; +constexpr size_t kItemRaces = 0x174; +constexpr size_t kItemDeity = 0x178; +constexpr size_t kItemMagic = 0x180; +constexpr size_t kItemDelay = 0x182; +constexpr size_t kItemRange = 0x185; +constexpr size_t kItemDamage = 0x188; +constexpr size_t kItemAugSlot1 = 0x1ec; +constexpr size_t kItemAugSlot2 = 0x1f4; +constexpr size_t kItemAugSlot3 = 0x1fc; +constexpr size_t kItemAugSlot4 = 0x204; +constexpr size_t kItemAugSlot5 = 0x20c; +constexpr size_t kItemAugSlot6 = 0x214; +constexpr size_t kItemAugType = 0x21c; +constexpr size_t kItemAugRestrictions = 0x220; +constexpr size_t kItemClicky = 0x284; +constexpr size_t kItemProc = 0x2e8; +constexpr size_t kItemWorn = 0x34c; +constexpr size_t kItemFocus = 0x3b0; +constexpr size_t kItemScroll = 0x414; +constexpr size_t kItemCombatEffects = 0x4f0; +constexpr size_t kItemShielding = 0x4f4; +constexpr size_t kItemStunResist = 0x4f8; +constexpr size_t kItemDoTShielding = 0x4fc; +constexpr size_t kItemStrikeThrough = 0x500; +constexpr size_t kItemDmgBonusSkill = 0x504; +constexpr size_t kItemDmgBonusValue = 0x508; +constexpr size_t kItemSpellShield = 0x50c; +constexpr size_t kItemAvoidance = 0x510; +constexpr size_t kItemAccuracy = 0x514; +constexpr size_t kItemCastTime = 0x51c; +constexpr size_t kItemCombine = 0x520; +constexpr size_t kItemSlots = 0x521; +constexpr size_t kItemSizeCapacity = 0x522; +constexpr size_t kItemWeightReduction = 0x523; +constexpr size_t kItemEndurance = 0x550; +constexpr size_t kItemAttack = 0x554; +constexpr size_t kItemHPRegen = 0x558; +constexpr size_t kItemManaRegen = 0x55c; +constexpr size_t kItemEnduranceRegen = 0x560; +constexpr size_t kItemHaste = 0x564; +constexpr size_t kItemDamShield = 0x568; +constexpr size_t kItemStackSize = 0x580; +constexpr size_t kItemMaxPower = 0x588; +constexpr size_t kItemPurity = 0x58c; +constexpr size_t kItemQuestItem = 0x598; +constexpr size_t kItemClairvoyance = 0x5a0; + +constexpr size_t kItemSpellID = 0x00; +constexpr size_t kItemSpellRequiredLevel = 0x04; +constexpr size_t kItemSpellEffectType = 0x05; +constexpr size_t kItemSpellMaxCharges = 0x0c; +constexpr size_t kItemSpellCastTime = 0x10; +constexpr size_t kItemSpellTimerID = 0x14; +constexpr size_t kItemSpellRecastType = 0x18; +constexpr size_t kItemSpellProcRate = 0x1c; + +constexpr size_t kSpellManagerSpells = 0x2c180; +constexpr uint32_t kMaxSpellID = 0xAFC9; +constexpr size_t kSpellRange = 0x000; +constexpr size_t kSpellAERange = 0x004; +constexpr size_t kSpellCastTime = 0x010; +constexpr size_t kSpellRecastTime = 0x018; +constexpr size_t kSpellDurationType = 0x01c; +constexpr size_t kSpellDurationValue1 = 0x020; +constexpr size_t kSpellMana = 0x028; +constexpr size_t kSpellBase = 0x02c; +constexpr size_t kSpellBase2 = 0x05c; +constexpr size_t kSpellMax = 0x08c; +constexpr size_t kSpellCalc = 0x0ec; +constexpr size_t kSpellAttrib = 0x11c; +constexpr size_t kSpellDescriptionNumber = 0x154; +constexpr size_t kSpellResistAdj = 0x158; +constexpr size_t kSpellIcon = 0x168; +constexpr size_t kSpellID = 0x174; +constexpr size_t kSpellEnduranceCost = 0x194; +constexpr size_t kSpellCanMGB = 0x241; +constexpr size_t kSpellLevel = 0x247; +constexpr size_t kSpellSpellType = 0x26b; +constexpr size_t kSpellResist = 0x26d; +constexpr size_t kSpellTargetType = 0x26e; +constexpr size_t kSpellSkill = 0x270; +constexpr size_t kSpellName = 0x27a; +constexpr size_t kSpellTarget = 0x2ba; +constexpr size_t kSpellCastOnYou = 0x3ba; +constexpr size_t kSpellCastOnAnother = 0x41a; +constexpr size_t kSpellWearOff = 0x47a; +constexpr size_t kSpellEffectSlots = 12; +constexpr int kSpellEffectNone = 254; +constexpr int kSpellEffectStackingBlock = 148; +constexpr int kSpellEffectStackingOverwrite = 149; + +enum SpawnType : uint8_t { + kSpawnPlayer = 0, + kSpawnNPC = 1, + kSpawnCorpse = 2 +}; + +template +T NativeClamp(T value, T min_value, T max_value) { + return value < min_value ? min_value : (value > max_value ? max_value : value); +} + +struct Config { + bool map_enabled = true; + bool map_show_npcs = true; + bool map_show_players = false; + bool map_show_corpses = false; + bool map_chain_eq_labels = true; + bool map_use_con_color = true; + bool map_show_target = true; + bool map_target_line = true; + bool map_show_ground = false; + bool map_show_vectors = false; + bool map_named_only = false; + bool map_show_xtargets = true; + bool map_xtarget_labels = true; + float map_target_radius = 0.0f; + float map_cast_radius = 0.0f; + float map_spell_radius = 0.0f; + std::string map_highlight_filter; + uint32_t map_highlight_color = 0xFFFF00FF; + int map_highlight_size = 24; + int map_max_labels = 0; + int map_refresh_ms = 1000; + std::string map_name_filter; + std::string map_hide_filter; + bool xtar_enabled = true; + bool inspect_items = true; + bool inspect_spells = true; +}; + +#pragma pack(push, 1) +struct Point3 { + float x; + float y; + float z; +}; + +struct MapLabelNative { + uint32_t unknown0; + MapLabelNative* next; + MapLabelNative* prev; + Point3 location; + uint32_t color; + uint32_t size; + char* label; + uint32_t layer; + uint32_t width; + uint32_t height; + uint32_t unknown30; + uint32_t unknown34; +}; + +struct MapLineNative { + MapLineNative* next; + MapLineNative* prev; + Point3 start; + Point3 end; + uint32_t color; + uint32_t layer; +}; + +struct CXStr { + void* text; +}; + +struct CXSize { + DWORD a; + DWORD b; + DWORD c; + DWORD d; + DWORD e; + DWORD f; +}; +#pragma pack(pop) + +static_assert(sizeof(MapLabelNative) == 0x38, "MapLabelNative must match EQ MAPLABEL size"); +static_assert(sizeof(MapLineNative) == 0x28, "MapLineNative must match EQ MAPLINE size"); + +struct ManagedMapLabel { + MapLabelNative native{}; + std::string text; +}; + +struct MapLocation { + std::string label; + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; +}; + +struct XTargetInfo { + int slot = 0; + uint32_t type = 0; + uint32_t spawn_id = 0; + std::string name; + void* spawn = nullptr; + float distance = 0.0f; +}; + +struct ItemPowerInfo { + uint32_t item_id = 0; + uint32_t item_level = 0; + uint32_t score = 0; + uint32_t version = 0; + std::string role; + std::string source; + std::string name; + DWORD last_seen = 0; +}; + +struct InlineHook { + void* target = nullptr; + void* detour = nullptr; + BYTE original_bytes[16]{}; + size_t length = 0; + BYTE* gateway = nullptr; + bool installed = false; + + template + T original() const { + return reinterpret_cast(gateway); + } +}; + +using MapPostDraw2Proc = int(__thiscall*)(void*); +using ItemUpdateStringsProc = void(__thiscall*)(void*); +using InterpretCmdProc = void(__thiscall*)(void*, void*, char*); +using DspChatProc = void(__thiscall*)(void*, const char*, DWORD, bool, bool); +using GetConLevelProc = int(__thiscall*)(void*, void*); +using CXStrCtorCStringProc = CXStr*(__thiscall*)(CXStr*, const char*); +using CXStrDtorProc = void(__thiscall*)(CXStr*); +using CStmlWndAppendSTMLProc = CXSize*(__thiscall*)(void*, CXSize*, CXStr); +using CStmlWndForceParseNowProc = void(__thiscall*)(void*); + +HMODULE g_module = nullptr; +HMODULE g_real_dinput = nullptr; +HANDLE g_worker = nullptr; +volatile bool g_shutdown = false; +Config g_config; +InlineHook g_item_update_hook; +InlineHook g_command_hook; +InlineHook g_chat_hook; + +void* g_hooked_map_window = nullptr; +void** g_old_map_vtable = nullptr; +void** g_new_map_vtable = nullptr; +MapPostDraw2Proc g_old_map_post_draw2 = nullptr; +std::vector g_map_labels; +std::vector g_map_lines; +std::vector g_map_locations; +DWORD g_last_map_refresh = 0; +__declspec(thread) bool g_in_update_strings = false; +__declspec(thread) bool g_in_map_post_draw = false; +int g_map_draw_log_count = 0; +int g_item_update_log_count = 0; +int g_item_lookup_log_count = 0; +int g_item_append_log_count = 0; +int g_spell_append_log_count = 0; +int g_item_power_transport_log_count = 0; +int g_stml_append_log_count = 0; +CRITICAL_SECTION g_item_power_lock{}; +bool g_item_power_lock_ready = false; +std::unordered_map g_item_power_by_id; + +uintptr_t Rebase(uintptr_t address) { + auto base = reinterpret_cast(GetModuleHandleA(nullptr)); + return base + (address - kEqImageBase); +} + +std::string GetClientDirectory() { + char path[MAX_PATH]{}; + if (!GetModuleFileNameA(nullptr, path, MAX_PATH)) { + return "."; + } + + char* slash = strrchr(path, '\\'); + if (slash) { + *slash = '\0'; + } + + return path; +} + +std::string JoinClientPath(const char* file_name) { + std::string path = GetClientDirectory(); + if (!path.empty() && path.back() != '\\') { + path.push_back('\\'); + } + path += file_name; + return path; +} + +void Log(const char* fmt, ...) { + char line[2048]{}; + va_list args; + va_start(args, fmt); + _vsnprintf_s(line, sizeof(line), _TRUNCATE, fmt, args); + va_end(args); + + std::string path = JoinClientPath("native_interface.log"); + FILE* fp = nullptr; + if (fopen_s(&fp, path.c_str(), "a") == 0 && fp) { + SYSTEMTIME st{}; + GetLocalTime(&st); + fprintf(fp, "[%04u-%02u-%02u %02u:%02u:%02u] %s\n", + st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, line); + fclose(fp); + } +} + +bool IsReadableMemory(const void* ptr, size_t bytes) { + if (!ptr || bytes == 0) { + return false; + } + + MEMORY_BASIC_INFORMATION mbi{}; + if (!VirtualQuery(ptr, &mbi, sizeof(mbi))) { + return false; + } + + if (mbi.State != MEM_COMMIT || (mbi.Protect & (PAGE_NOACCESS | PAGE_GUARD))) { + return false; + } + + uintptr_t start = reinterpret_cast(ptr); + uintptr_t end = start + bytes; + uintptr_t region_end = reinterpret_cast(mbi.BaseAddress) + mbi.RegionSize; + return end <= region_end; +} + +template +bool SafeRead(const void* address, T& value) { + if (!IsReadableMemory(address, sizeof(T))) { + return false; + } + + __try { + value = *reinterpret_cast(address); + return true; + } __except (EXCEPTION_EXECUTE_HANDLER) { + return false; + } +} + +template +T ReadValue(const void* address, T fallback = T{}) { + T value{}; + if (SafeRead(address, value)) { + return value; + } + return fallback; +} + +void* ReadPtr(const void* address) { + void* value = nullptr; + SafeRead(address, value); + return value; +} + +void* ReadPtrOffset(const void* base, size_t offset) { + if (!base) { + return nullptr; + } + return ReadPtr(static_cast(base) + offset); +} + +void* ReadGlobalPtr(uintptr_t rebased_global_ptr) { + return ReadPtr(reinterpret_cast(Rebase(rebased_global_ptr))); +} + +bool WriteGlobalPtr(uintptr_t rebased_global_ptr, void* value) { + void** target = reinterpret_cast(Rebase(rebased_global_ptr)); + if (!IsReadableMemory(target, sizeof(void*))) { + return false; + } + + __try { + *target = value; + return true; + } __except (EXCEPTION_EXECUTE_HANDLER) { + return false; + } +} + +bool CopyFixedStringRaw(const char* address, size_t max_len, char* buffer, size_t buffer_len) { + if (!address || !buffer || buffer_len == 0 || max_len == 0) { + return false; + } + + buffer[0] = '\0'; + size_t limit = max_len; + if (limit > buffer_len - 1) { + limit = buffer_len - 1; + } + + __try { + for (size_t i = 0; i < limit; ++i) { + char c = *(address + i); + if (c == '\0') { + break; + } + buffer[i] = c; + } + } __except (EXCEPTION_EXECUTE_HANDLER) { + buffer[0] = '\0'; + return false; + } + + return true; +} + +std::string ReadFixedString(const void* address, size_t max_len) { + if (!address || max_len == 0 || !IsReadableMemory(address, 1)) { + return {}; + } + + char buffer[256]{}; + if (!CopyFixedStringRaw(static_cast(address), max_len, buffer, sizeof(buffer))) { + return {}; + } + + return std::string(buffer); +} + +void LoadConfig() { + std::string path = JoinClientPath("native_interface.ini"); + g_config.map_enabled = GetPrivateProfileIntA("Map", "Enabled", 1, path.c_str()) != 0; + g_config.map_show_npcs = GetPrivateProfileIntA("Map", "ShowNPCs", 1, path.c_str()) != 0; + g_config.map_show_players = GetPrivateProfileIntA("Map", "ShowPlayers", 0, path.c_str()) != 0; + g_config.map_show_corpses = GetPrivateProfileIntA("Map", "ShowCorpses", 0, path.c_str()) != 0; + g_config.map_chain_eq_labels = GetPrivateProfileIntA("Map", "ChainEQLabels", 1, path.c_str()) != 0; + g_config.map_use_con_color = GetPrivateProfileIntA("Map", "UseConColor", 1, path.c_str()) != 0; + g_config.map_show_target = GetPrivateProfileIntA("Map", "ShowTarget", 1, path.c_str()) != 0; + g_config.map_target_line = GetPrivateProfileIntA("Map", "TargetLine", 1, path.c_str()) != 0; + g_config.map_show_ground = GetPrivateProfileIntA("Map", "Ground", 0, path.c_str()) != 0; + g_config.map_show_vectors = GetPrivateProfileIntA("Map", "Vector", 0, path.c_str()) != 0; + g_config.map_named_only = GetPrivateProfileIntA("Map", "Named", 0, path.c_str()) != 0; + g_config.map_show_xtargets = GetPrivateProfileIntA("Map", "XTargets", 1, path.c_str()) != 0; + g_config.map_xtarget_labels = GetPrivateProfileIntA("Map", "XTargetLabels", 1, path.c_str()) != 0; + g_config.map_highlight_color = static_cast(GetPrivateProfileIntA("Map", "HighlightColor", 0x00FF00FF, path.c_str())) | 0xFF000000; + g_config.map_highlight_size = NativeClamp(static_cast(GetPrivateProfileIntA("Map", "HighlightSize", 24, path.c_str())), 4, 200); + int max_labels = static_cast(GetPrivateProfileIntA("Map", "MaxLabels", 0, path.c_str())); + g_config.map_max_labels = max_labels <= 0 ? 0 : NativeClamp(max_labels, 1, 2048); + int refresh_ms = static_cast(GetPrivateProfileIntA("Map", "RefreshMs", 1000, path.c_str())); + g_config.map_refresh_ms = NativeClamp(refresh_ms, 250, 5000); + char float_value[64]{}; + GetPrivateProfileStringA("Map", "TargetRadius", "0", float_value, sizeof(float_value), path.c_str()); + g_config.map_target_radius = std::max(0.0f, static_cast(atof(float_value))); + GetPrivateProfileStringA("Map", "CastRadius", "0", float_value, sizeof(float_value), path.c_str()); + g_config.map_cast_radius = std::max(0.0f, static_cast(atof(float_value))); + GetPrivateProfileStringA("Map", "SpellRadius", "0", float_value, sizeof(float_value), path.c_str()); + g_config.map_spell_radius = std::max(0.0f, static_cast(atof(float_value))); + char name_filter[256]{}; + GetPrivateProfileStringA("Map", "NameFilter", "", name_filter, sizeof(name_filter), path.c_str()); + g_config.map_name_filter = name_filter; + char hide_filter[256]{}; + GetPrivateProfileStringA("Map", "HideFilter", "", hide_filter, sizeof(hide_filter), path.c_str()); + g_config.map_hide_filter = hide_filter; + char highlight_filter[256]{}; + GetPrivateProfileStringA("Map", "HighlightFilter", "", highlight_filter, sizeof(highlight_filter), path.c_str()); + g_config.map_highlight_filter = highlight_filter; + g_config.xtar_enabled = GetPrivateProfileIntA("XTarget", "Enabled", 1, path.c_str()) != 0; + g_config.inspect_items = GetPrivateProfileIntA("Inspect", "Items", 1, path.c_str()) != 0; + g_config.inspect_spells = GetPrivateProfileIntA("Inspect", "Spells", 1, path.c_str()) != 0; +} + +void SaveConfigBool(const char* section, const char* key, bool value) { + std::string path = JoinClientPath("native_interface.ini"); + WritePrivateProfileStringA(section, key, value ? "1" : "0", path.c_str()); +} + +void SaveConfigString(const char* section, const char* key, const std::string& value) { + std::string path = JoinClientPath("native_interface.ini"); + WritePrivateProfileStringA(section, key, value.c_str(), path.c_str()); +} + +void SaveConfigInt(const char* section, const char* key, int value) { + char buffer[32]{}; + _snprintf_s(buffer, sizeof(buffer), _TRUNCATE, "%d", value); + std::string path = JoinClientPath("native_interface.ini"); + WritePrivateProfileStringA(section, key, buffer, path.c_str()); +} + +void SaveConfigFloat(const char* section, const char* key, float value) { + char buffer[32]{}; + _snprintf_s(buffer, sizeof(buffer), _TRUNCATE, "%.2f", value); + std::string path = JoinClientPath("native_interface.ini"); + WritePrivateProfileStringA(section, key, buffer, path.c_str()); +} + +void Chat(const char* fmt, ...) { + char line[1024]{}; + va_list args; + va_start(args, fmt); + _vsnprintf_s(line, sizeof(line), _TRUNCATE, fmt, args); + va_end(args); + + Log("%s", line); + + void* everquest = ReadGlobalPtr(kPInstCEverQuest); + if (!everquest) { + return; + } + + auto dsp_chat = reinterpret_cast(Rebase(kCEverQuestDspChat)); + dsp_chat(everquest, line, 15, false, true); +} + +bool CommandMatch(const char* line, const char* command, const char** arguments) { + if (!line || !command) { + return false; + } + + while (*line == ' ' || *line == '\t') { + ++line; + } + + size_t command_len = strlen(command); + if (_strnicmp(line, command, command_len) != 0) { + return false; + } + + char next = line[command_len]; + if (next != '\0' && next != ' ' && next != '\t') { + return false; + } + + if (arguments) { + const char* current = line + command_len; + while (*current == ' ' || *current == '\t') { + ++current; + } + *arguments = current; + } + + return true; +} + +std::string TrimCopy(const char* text) { + if (!text) { + return {}; + } + + while (*text == ' ' || *text == '\t') { + ++text; + } + + const char* end = text + strlen(text); + while (end > text && (end[-1] == ' ' || end[-1] == '\t' || end[-1] == '\r' || end[-1] == '\n')) { + --end; + } + + return std::string(text, end); +} + +std::string LowerCopy(std::string value) { + std::transform(value.begin(), value.end(), value.begin(), [](unsigned char c) { + return static_cast(std::tolower(c)); + }); + return value; +} + +bool StartsWith(const char* value, const char* prefix) { + return value && prefix && strncmp(value, prefix, strlen(prefix)) == 0; +} + +bool ContainsInsensitive(const std::string& value, const std::string& needle) { + if (needle.empty()) { + return true; + } + return LowerCopy(value).find(LowerCopy(needle)) != std::string::npos; +} + +bool ParseOnOff(const char* args, bool current_value, bool default_if_missing) { + if (!args || !args[0]) { + return default_if_missing; + } + + if (CommandMatch(args, "on", nullptr) || CommandMatch(args, "1", nullptr) || + CommandMatch(args, "true", nullptr)) { + return true; + } + + if (CommandMatch(args, "off", nullptr) || CommandMatch(args, "0", nullptr) || + CommandMatch(args, "false", nullptr)) { + return false; + } + + return current_value; +} + +std::vector SplitWords(const char* text) { + std::vector words; + if (!text) { + return words; + } + + while (*text) { + while (*text == ' ' || *text == '\t') { + ++text; + } + if (!*text) { + break; + } + + const char* start = text; + while (*text && *text != ' ' && *text != '\t') { + ++text; + } + words.emplace_back(start, text); + } + + return words; +} + +bool TryParseInt(const std::string& value, int& out) { + if (value.empty()) { + return false; + } + + char* end = nullptr; + long parsed = strtol(value.c_str(), &end, 10); + if (!end || *end != '\0') { + return false; + } + + out = static_cast(parsed); + return true; +} + +bool TryParseFloat(const std::string& value, float& out) { + if (value.empty()) { + return false; + } + + char* end = nullptr; + float parsed = strtof(value.c_str(), &end); + if (!end || *end != '\0') { + return false; + } + + out = parsed; + return true; +} + +bool TryParseColorToken(const std::string& value, uint32_t& out) { + if (value.empty()) { + return false; + } + + std::string token = value; + if (token[0] == '#') { + token.erase(token.begin()); + } else if (token.size() > 2 && token[0] == '0' && (token[1] == 'x' || token[1] == 'X')) { + token.erase(0, 2); + } + + if (token.empty() || token.size() > 8) { + return false; + } + + char* end = nullptr; + unsigned long parsed = strtoul(token.c_str(), &end, 16); + if (!end || *end != '\0') { + return false; + } + + uint32_t color = static_cast(parsed); + if (token.size() <= 6) { + color |= 0xFF000000; + } + out = color; + return true; +} + +bool ReadTransportUInt(const char* message, const char* key, uint32_t& value) { + const char* found = strstr(message, key); + if (!found) { + return false; + } + + found += strlen(key); + char* end = nullptr; + unsigned long parsed = strtoul(found, &end, 10); + if (end == found) { + return false; + } + + value = static_cast(parsed); + return true; +} + +std::string ReadTransportString(const char* message, const char* key) { + const char* found = strstr(message, key); + if (!found) { + return {}; + } + + found += strlen(key); + const char* end = strchr(found, '|'); + return end ? std::string(found, end) : std::string(found); +} + +bool ParseItemPowerTransport(const char* message) { + if (!StartsWith(message, "ITEMPOWER|")) { + return false; + } + + uint32_t item_id = 0; + if (!ReadTransportUInt(message, "item_id=", item_id) || item_id == 0) { + return true; + } + + if (StartsWith(message, "ITEMPOWER|clear|")) { + if (g_item_power_lock_ready) { + EnterCriticalSection(&g_item_power_lock); + g_item_power_by_id.erase(item_id); + LeaveCriticalSection(&g_item_power_lock); + } + return true; + } + + ItemPowerInfo info{}; + info.item_id = item_id; + info.last_seen = GetTickCount(); + ReadTransportUInt(message, "ilvl=", info.item_level); + ReadTransportUInt(message, "score=", info.score); + ReadTransportUInt(message, "version=", info.version); + info.role = ReadTransportString(message, "role="); + info.source = ReadTransportString(message, "source="); + info.name = ReadTransportString(message, "name="); + + if (info.item_level == 0 && info.score == 0) { + return true; + } + + if (g_item_power_lock_ready) { + EnterCriticalSection(&g_item_power_lock); + g_item_power_by_id[item_id] = info; + LeaveCriticalSection(&g_item_power_lock); + } + + if (g_item_power_transport_log_count < 16) { + ++g_item_power_transport_log_count; + Log("cached item power item=%u ilvl=%u score=%u role=%s version=%u source=%s name=%s", + info.item_id, + info.item_level, + info.score, + info.role.c_str(), + info.version, + info.source.c_str(), + info.name.c_str()); + } + + return true; +} + +bool LookupItemPower(uint32_t item_id, ItemPowerInfo& info) { + if (!item_id || !g_item_power_lock_ready) { + return false; + } + + EnterCriticalSection(&g_item_power_lock); + const auto iter = g_item_power_by_id.find(item_id); + if (iter == g_item_power_by_id.end()) { + LeaveCriticalSection(&g_item_power_lock); + return false; + } + + info = iter->second; + LeaveCriticalSection(&g_item_power_lock); + return true; +} + +size_t ItemPowerCacheSize() { + if (!g_item_power_lock_ready) { + return 0; + } + + EnterCriticalSection(&g_item_power_lock); + const size_t size = g_item_power_by_id.size(); + LeaveCriticalSection(&g_item_power_lock); + return size; +} + +bool WriteJump(BYTE* target, void* detour) { + DWORD old_protect = 0; + if (!VirtualProtect(target, 5, PAGE_EXECUTE_READWRITE, &old_protect)) { + return false; + } + + target[0] = 0xE9; + *reinterpret_cast(target + 1) = + static_cast(reinterpret_cast(detour) - target - 5); + + DWORD unused = 0; + VirtualProtect(target, 5, old_protect, &unused); + FlushInstructionCache(GetCurrentProcess(), target, 5); + return true; +} + +bool InstallInlineHook(InlineHook& hook, void* target, void* detour, size_t length) { + if (hook.installed) { + return true; + } + + if (!target || !detour || length < 5 || length > sizeof(hook.original_bytes)) { + return false; + } + + hook.gateway = static_cast(VirtualAlloc(nullptr, length + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)); + if (!hook.gateway) { + return false; + } + + hook.target = target; + hook.detour = detour; + hook.length = length; + memcpy(hook.original_bytes, target, length); + memcpy(hook.gateway, target, length); + WriteJump(hook.gateway + length, static_cast(target) + length); + + DWORD old_protect = 0; + if (!VirtualProtect(target, length, PAGE_EXECUTE_READWRITE, &old_protect)) { + VirtualFree(hook.gateway, 0, MEM_RELEASE); + hook.gateway = nullptr; + return false; + } + + memset(target, 0x90, length); + WriteJump(static_cast(target), detour); + + DWORD unused = 0; + VirtualProtect(target, length, old_protect, &unused); + FlushInstructionCache(GetCurrentProcess(), target, length); + + hook.installed = true; + return true; +} + +void RemoveInlineHook(InlineHook& hook) { + if (!hook.installed || !hook.target) { + return; + } + + DWORD old_protect = 0; + if (VirtualProtect(hook.target, hook.length, PAGE_EXECUTE_READWRITE, &old_protect)) { + memcpy(hook.target, hook.original_bytes, hook.length); + DWORD unused = 0; + VirtualProtect(hook.target, hook.length, old_protect, &unused); + FlushInstructionCache(GetCurrentProcess(), hook.target, hook.length); + } + + if (hook.gateway) { + VirtualFree(hook.gateway, 0, MEM_RELEASE); + } + + hook = InlineHook{}; +} + +void* GetSpell(uint32_t spell_id) { + if (spell_id == 0 || spell_id >= kMaxSpellID) { + return nullptr; + } + + void* spell_mgr = ReadGlobalPtr(kPInstSpellManager); + if (!spell_mgr) { + return nullptr; + } + + return ReadPtr(static_cast(spell_mgr) + kSpellManagerSpells + spell_id * sizeof(void*)); +} + +std::string GetSpellName(uint32_t spell_id) { + void* spell = GetSpell(spell_id); + if (!spell) { + char fallback[32]{}; + _snprintf_s(fallback, sizeof(fallback), _TRUNCATE, "Spell %u", spell_id); + return fallback; + } + return ReadFixedString(static_cast(spell) + kSpellName, 0x40); +} + +std::string EscapeStml(const std::string& text) { + std::string out; + out.reserve(text.size()); + for (char c : text) { + switch (c) { + case '&': + out += "&"; + break; + case '<': + out += "<"; + break; + case '>': + out += ">"; + break; + default: + out.push_back(c); + break; + } + } + return out; +} + +void AppendLine(std::string& out, const char* label, int value) { + if (value == 0) { + return; + } + + char line[128]{}; + _snprintf_s(line, sizeof(line), _TRUNCATE, "%s: %d
    ", label, value); + out += line; +} + +void AppendHexLine(std::string& out, const char* label, uint32_t value) { + if (value == 0) { + return; + } + + char line[128]{}; + _snprintf_s(line, sizeof(line), _TRUNCATE, "%s: 0x%X
    ", label, value); + out += line; +} + +void AppendFloatLine(std::string& out, const char* label, float value) { + if (value == 0.0f) { + return; + } + + char line[128]{}; + _snprintf_s(line, sizeof(line), _TRUNCATE, "%s: %.1f
    ", label, value); + out += line; +} + +void AppendFlags(std::string& out, void* item) { + std::vector flags; + if (ReadValue(static_cast(item) + kItemNoDrop) != 0) { + flags.emplace_back("No Drop"); + } + if (ReadValue(static_cast(item) + kItemNoRent) != 0) { + flags.emplace_back("No Rent"); + } + if (ReadValue(static_cast(item) + kItemAttuneable) != 0) { + flags.emplace_back("Attuneable"); + } + if (ReadValue(static_cast(item) + kItemMagic) != 0) { + flags.emplace_back("Magic"); + } + if (ReadValue(static_cast(item) + kItemLore) != 0) { + flags.emplace_back("Lore"); + } + if (ReadValue(static_cast(item) + kItemSummoned) != 0) { + flags.emplace_back("Summoned"); + } + if (ReadValue(static_cast(item) + kItemArtifact) != 0) { + flags.emplace_back("Artifact"); + } + if (ReadValue(static_cast(item) + kItemQuestItem) != 0) { + flags.emplace_back("Quest"); + } + if (ReadValue(static_cast(item) + kItemTradeSkills) != 0) { + flags.emplace_back("Tradeskill"); + } + + if (!flags.empty()) { + out += "Flags: "; + for (size_t i = 0; i < flags.size(); ++i) { + if (i) { + out += ", "; + } + out += flags[i]; + } + out += "
    "; + } +} + +void AppendMoneyLine(std::string& out, uint32_t copper) { + if (copper == 0) { + return; + } + + uint32_t cp = copper; + uint32_t sp = cp / 10; + cp %= 10; + uint32_t gp = sp / 10; + sp %= 10; + uint32_t pp = gp / 10; + gp %= 10; + + char line[128]{}; + _snprintf_s(line, sizeof(line), _TRUNCATE, "Value: %upp %ugp %usp %ucp
    ", pp, gp, sp, cp); + out += line; +} + +double PositiveScore(double value) { + return value > 0.0 ? value : 0.0; +} + +double SoftCapScore(double value, double cap) { + value = PositiveScore(value); + if (cap <= 0.0) { + return value; + } + + const double soft_cap = cap * 0.70; + if (value <= soft_cap) { + return value; + } + + return soft_cap + ((value - soft_cap) * 0.35); +} + +uint32_t RoundScoreValue(double value) { + if (value <= 0.0) { + return 0; + } + + return static_cast(std::lround(value)); +} + +double LocalSlotBudget(void* item) { + const int damage = ReadValue(static_cast(item) + kItemDamage); + const int delay = ReadValue(static_cast(item) + kItemDelay); + if (damage > 0 && delay > 0) { + return 1.25; + } + + const uint32_t slots = ReadValue(static_cast(item) + kItemEquipSlots); + struct SlotBudget { + uint8_t slot; + double budget; + }; + static const SlotBudget budgets[] = { + {0, 1.00}, {1, 0.60}, {2, 1.00}, {3, 0.75}, {4, 0.60}, + {5, 0.75}, {6, 0.95}, {7, 0.95}, {8, 0.90}, {9, 0.65}, + {10, 0.65}, {11, 0.75}, {12, 0.85}, {13, 1.25}, {14, 1.15}, + {15, 0.60}, {16, 0.60}, {17, 1.35}, {18, 1.20}, {19, 0.85}, + {20, 0.85}, {21, 1.00}, {22, 0.25} + }; + + double best = 1.0; + bool found = false; + for (const auto& budget : budgets) { + if ((slots & (1u << budget.slot)) && (!found || budget.budget > best)) { + best = budget.budget; + found = true; + } + } + return best; +} + +uint16_t LocalItemLevel(uint32_t score, double slot_budget, uint8_t req_level, uint8_t rec_level) { + const double budget = std::max(slot_budget, 0.25); + const double normalized_power = std::max(1.0, static_cast(score) / budget); + const auto computed_level = static_cast( + NativeClamp( + static_cast(std::lround(std::pow(normalized_power, 0.58))), + 1, + 127 + ) + ); + const auto rec_floor = static_cast(std::ceil(static_cast(rec_level) * 0.85)); + return std::max( + std::max(computed_level, static_cast(req_level)), + std::max(rec_floor, 1) + ); +} + +struct LocalRoleWeights { + double hp = 0.0; + double mana = 0.0; + double endurance = 0.0; + double ac = 0.0; + double str = 0.0; + double sta = 0.0; + double dex = 0.0; + double agi = 0.0; + double intel = 0.0; + double wis = 0.0; + double haste = 0.0; + double atk = 0.0; + double accuracy = 0.0; + double combat_effects = 0.0; + double strikethrough = 0.0; + double weapon = 0.0; + double regen = 0.0; + double mana_regen = 0.0; + double endurance_regen = 0.0; +}; + +LocalRoleWeights GetLocalRoleWeights(const std::string& role) { + LocalRoleWeights weights{}; + if (role == "tank") { + weights.hp = 1.30; + weights.ac = 1.50; + weights.sta = 1.25; + weights.agi = 1.15; + weights.weapon = 0.70; + weights.mana = 0.35; + } else if (role == "melee") { + weights.weapon = 1.60; + weights.str = 1.25; + weights.dex = 1.25; + weights.haste = 1.40; + weights.atk = 1.35; + weights.accuracy = 1.50; + weights.combat_effects = 1.30; + weights.strikethrough = 1.25; + weights.hp = 0.60; + weights.ac = 0.60; + weights.mana = 0.10; + } else if (role == "caster") { + weights.hp = 0.50; + weights.ac = 0.50; + weights.mana = 1.25; + weights.intel = 1.20; + weights.wis = 1.20; + weights.mana_regen = 1.25; + weights.weapon = 0.10; + weights.haste = 0.10; + } else if (role == "healer") { + weights.hp = 0.70; + weights.ac = 0.70; + weights.mana = 1.35; + weights.intel = 1.20; + weights.wis = 1.20; + weights.mana_regen = 1.35; + weights.weapon = 0.10; + weights.haste = 0.10; + } else { + weights.hp = 1.00; + weights.mana = 0.75; + weights.endurance = 0.90; + weights.ac = 1.00; + weights.str = 1.10; + weights.sta = 1.10; + weights.dex = 1.10; + weights.agi = 1.00; + weights.intel = 0.85; + weights.wis = 0.85; + weights.weapon = 1.00; + } + return weights; +} + +uint32_t LocalRoleScore(void* item, const std::string& role) { + const LocalRoleWeights weights = GetLocalRoleWeights(role); + double score = 0.0; + + score += PositiveScore(ReadValue(static_cast(item) + kItemHP)) * 0.10 * weights.hp; + score += PositiveScore(ReadValue(static_cast(item) + kItemMana)) * 0.08 * weights.mana; + score += PositiveScore(ReadValue(static_cast(item) + kItemEndurance)) * 0.08 * weights.endurance; + score += PositiveScore(ReadValue(static_cast(item) + kItemAC)) * 1.80 * weights.ac; + + score += PositiveScore(ReadValue(static_cast(item) + kItemStr)) * 0.35 * weights.str; + score += PositiveScore(ReadValue(static_cast(item) + kItemSta)) * 0.35 * weights.sta; + score += PositiveScore(ReadValue(static_cast(item) + kItemDex)) * 0.35 * weights.dex; + score += PositiveScore(ReadValue(static_cast(item) + kItemAgi)) * 0.35 * weights.agi; + score += PositiveScore(ReadValue(static_cast(item) + kItemInt)) * 0.35 * weights.intel; + score += PositiveScore(ReadValue(static_cast(item) + kItemWis)) * 0.35 * weights.wis; + + score += SoftCapScore(ReadValue(static_cast(item) + kItemHPRegen), 30.0) * 2.00 * weights.regen; + score += SoftCapScore(ReadValue(static_cast(item) + kItemManaRegen), 15.0) * 2.50 * weights.mana_regen; + score += SoftCapScore(ReadValue(static_cast(item) + kItemEnduranceRegen), 15.0) * 2.50 * weights.endurance_regen; + + score += SoftCapScore(ReadValue(static_cast(item) + kItemAttack), 250.0) * 0.25 * weights.atk; + score += SoftCapScore(ReadValue(static_cast(item) + kItemAccuracy), 150.0) * 0.90 * weights.accuracy; + score += SoftCapScore(ReadValue(static_cast(item) + kItemCombatEffects), 100.0) * 0.80 * weights.combat_effects; + score += SoftCapScore(ReadValue(static_cast(item) + kItemStrikeThrough), 35.0) * 2.50 * weights.strikethrough; + score += SoftCapScore(ReadValue(static_cast(item) + kItemHaste), 100.0) * 2.20 * weights.haste; + + const int damage = ReadValue(static_cast(item) + kItemDamage); + const int delay = ReadValue(static_cast(item) + kItemDelay); + if (damage > 0 && delay > 0) { + const double weapon_score = (static_cast(damage) * 10.0 / static_cast(delay)) * 12.0; + score += weapon_score * weights.weapon; + } + + return RoundScoreValue(score); +} + +bool CalculateLocalItemPower(void* item, uint32_t item_id, ItemPowerInfo& info) { + if (!item || !item_id) { + return false; + } + + struct RoleScore { + const char* role; + uint32_t score; + }; + + RoleScore scores[] = { + {"tank", LocalRoleScore(item, "tank")}, + {"melee", LocalRoleScore(item, "melee")}, + {"caster", LocalRoleScore(item, "caster")}, + {"healer", LocalRoleScore(item, "healer")}, + {"hybrid", LocalRoleScore(item, "hybrid")} + }; + + RoleScore best = scores[0]; + for (const auto& score : scores) { + if (score.score > best.score) { + best = score; + } + } + + if (best.score == 0) { + return false; + } + + info = ItemPowerInfo{}; + info.item_id = item_id; + info.score = best.score; + info.role = best.role; + info.source = "local"; + info.item_level = LocalItemLevel( + info.score, + LocalSlotBudget(item), + ReadValue(static_cast(item) + kItemRequiredLevel), + ReadValue(static_cast(item) + kItemRecommendedLevel) + ); + info.last_seen = GetTickCount(); + return true; +} + +std::string ItemPowerRoleDisplayName(const std::string& role) { + if (role == "tank") { + return "Tank"; + } + if (role == "melee") { + return "Melee DPS"; + } + if (role == "caster") { + return "Caster DPS"; + } + if (role == "healer") { + return "Healer"; + } + if (role == "hybrid") { + return "Hybrid"; + } + if (role == "none") { + return ""; + } + return role; +} + +bool AppendItemPowerLines(std::string& out, void* item, uint32_t item_id) { + ItemPowerInfo info{}; + if (!LookupItemPower(item_id, info) && !CalculateLocalItemPower(item, item_id, info)) { + return false; + } + + if (info.score == 0) { + return false; + } + + char line[256]{}; + _snprintf_s(line, sizeof(line), _TRUNCATE, "Item Level: %u
    ", info.item_level); + out += line; + + _snprintf_s(line, sizeof(line), _TRUNCATE, "Gearscore: %u
    ", info.score); + out += line; + + const std::string role = ItemPowerRoleDisplayName(info.role); + if (!role.empty()) { + out += "Best Role: "; + out += EscapeStml(role); + out += "
    "; + } + + return true; +} + +int64_t Abs64(int64_t value) { + return value < 0 ? -value : value; +} + +int64_t CalcSpellValue(int calc, int64_t base, int64_t max, int tick, int min_level, int level) { + if (calc == 0) { + return base; + } + + if (calc == 100) { + if (max > 0 && (base > max || level > min_level)) { + return max; + } + return base; + } + + int64_t change = 0; + switch (calc) { + case 101: change = level / 2; break; + case 102: change = level; break; + case 103: change = level * 2; break; + case 104: change = level * 3; break; + case 105: change = level * 4; break; + case 106: change = level * 5; break; + case 107: change = -1 * tick; break; + case 108: change = -2 * tick; break; + case 109: change = level / 4; break; + case 110: change = level / 6; break; + case 111: if (level > 16) change = (level - 16) * 6; break; + case 112: if (level > 24) change = (level - 24) * 8; break; + case 113: if (level > 34) change = (level - 34) * 10; break; + case 114: if (level > 44) change = (level - 44) * 15; break; + case 115: if (level > 15) change = (level - 15) * 7; break; + case 116: if (level > 24) change = (level - 24) * 10; break; + case 117: if (level > 34) change = (level - 34) * 13; break; + case 118: if (level > 44) change = (level - 44) * 20; break; + case 119: change = level / 8; break; + case 120: change = -5 * tick; break; + case 121: change = level / 3; break; + case 122: change = -12 * tick; break; + case 123: if (tick > 1) change = Abs64(max) - Abs64(base); break; + case 124: if (level > 50) change = level - 50; break; + case 125: if (level > 50) change = (level - 50) * 2; break; + case 126: if (level > 50) change = (level - 50) * 3; break; + case 127: if (level > 50) change = (level - 50) * 4; break; + case 128: if (level > 50) change = (level - 50) * 5; break; + case 129: if (level > 50) change = (level - 50) * 10; break; + case 130: if (level > 50) change = (level - 50) * 15; break; + case 131: if (level > 50) change = (level - 50) * 20; break; + case 132: if (level > 50) change = (level - 50) * 25; break; + case 139: if (level > 30) change = (level - 30) / 2; break; + case 140: if (level > 30) change = level - 30; break; + case 141: if (level > 30) change = 3 * (level - 30) / 2; break; + case 142: if (level > 30) change = 2 * (level - 30); break; + case 143: change = 3 * level / 4; break; + case 3000: return base; + default: + if (calc > 0 && calc < 1000) { + change = level * calc; + } else if (calc >= 1000 && calc < 2000) { + change = tick * (calc - 1000) * -1; + } else if (calc >= 2000) { + change = level * (calc - 2000); + } + break; + } + + int64_t value = Abs64(base) + change; + if (max != 0 && value > Abs64(max)) { + value = Abs64(max); + } + return base < 0 ? -value : value; +} + +const char* SpellEffectName(int attrib) { + static const char* kSpellEffectNames[] = { +#include "native_spell_effect_names.inl" + }; + + if (attrib >= 0 && attrib < static_cast(sizeof(kSpellEffectNames) / sizeof(kSpellEffectNames[0]))) { + return kSpellEffectNames[attrib]; + } + + switch (attrib) { + case 0: return "Current Hit Points"; + case 1: return "Armor Class"; + case 2: return "Attack"; + case 3: return "Movement Speed"; + case 4: return "STR"; + case 5: return "DEX"; + case 6: return "AGI"; + case 7: return "STA"; + case 8: return "INT"; + case 9: return "WIS"; + case 10: return "CHA"; + case 11: return "Attack Speed"; + case 12: return "Invisibility"; + case 13: return "See Invisible"; + case 14: return "Water Breathing"; + case 15: return "Current Mana"; + case 20: return "Blindness"; + case 21: return "Stun"; + case 22: return "Charm"; + case 23: return "Fear"; + case 27: return "Dispel Magic"; + case 28: return "Invisibility Vs Undead"; + case 29: return "Invisibility Vs Animals"; + case 30: return "NPC Aggro Radius"; + case 31: return "Mesmerize"; + case 32: return "Summon"; + case 33: return "Summon Pet"; + case 34: return "Confuse"; + case 35: return "Disease Counter"; + case 36: return "Poison Counter"; + case 37: return "Detect Hostile"; + case 38: return "Detect Magic"; + case 39: return "Stacking: No Twincast"; + case 40: return "Invulnerability"; + case 41: return "Banish"; + case 42: return "Shadow Step"; + case 43: return "Berserk"; + case 44: return "Lycanthropy"; + case 45: return "Vampirism"; + case 46: return "Fire Resist"; + case 47: return "Cold Resist"; + case 48: return "Poison Resist"; + case 49: return "Disease Resist"; + case 50: return "Magic Resist"; + case 51: return "Detect Traps"; + case 52: return "Detect Undead"; + case 53: return "Detect Summoned"; + case 54: return "Detect Animals"; + case 55: return "Absorb Damage"; + case 56: return "True North"; + case 57: return "Levitation"; + case 58: return "Illusion"; + case 59: return "Damage Shield"; + case 60: return "Transfer Item"; + case 61: return "Identify"; + case 62: return "Item ID"; + case 63: return "Memblur"; + case 64: return "Spin Stun"; + case 65: return "Infravision"; + case 66: return "Ultravision"; + case 67: return "Eye Of Zomm"; + case 68: return "Reclaim Energy"; + case 69: return "Max Hit Points"; + case 70: return "Corpse Bomb"; + case 71: return "Create Undead Pet"; + case 72: return "Preserve Corpse"; + case 73: return "Bind Sight"; + case 74: return "Feign Death"; + case 75: return "Ventriloquism"; + case 76: return "Sentinel"; + case 77: return "Locate Corpse"; + case 78: return "Spell Shield"; + case 79: return "Current Hit Points Once"; + case 80: return "Enchant Light"; + case 81: return "Resurrect"; + case 82: return "Summon Player"; + case 83: return "Teleport"; + case 84: return "Toss"; + case 85: return "Add Proc"; + case 86: return "Reaction Radius"; + case 87: return "Magnification"; + case 88: return "Evacuate"; + case 89: return "Player Size"; + case 90: return "Ignore Pet"; + case 91: return "Summon Corpse"; + case 92: return "Hate"; + case 93: return "Control Weather"; + case 94: return "Make Fragile"; + case 95: return "Sacrifice"; + case 96: return "Silence"; + case 97: return "Max Mana"; + case 98: return "Bard Haste"; + case 99: return "Root"; + case 100: return "Heal Over Time"; + case 101: return "Complete Heal"; + case 102: return "Pet Fearless"; + case 103: return "Summon Pet"; + case 104: return "Translocate"; + case 105: return "Anti Gate"; + case 106: return "Summon Warder"; + case 107: return "Alter NPC Level"; + case 108: return "Summon Familiar"; + case 109: return "Summon In Bag"; + case 110: return "Archery"; + case 111: return "All Resists"; + case 112: return "Casting Level"; + case 113: return "Summon Mount"; + case 114: return "Hate Multiplier"; + case 115: return "Food/Water"; + case 116: return "Curse Counter"; + case 117: return "Make Weapons Magical"; + case 118: return "Singing Skill"; + case 119: return "Melee Overhaste"; + case 120: return "Healing Effectiveness"; + case 121: return "Reverse Damage Shield"; + case 122: return "Reduce Skill"; + case 123: return "Immunity"; + case 124: return "Spell Damage"; + case 125: return "Healing"; + case 126: return "Spell Resist Rate"; + case 127: return "Spell Haste"; + case 128: return "Spell Duration"; + case 129: return "Spell Range"; + case 130: return "Spell/Bash Hate"; + case 131: return "Chance of Using Reagent"; + case 132: return "Spell Mana Cost"; + case 134: return "Limit: Max Level"; + case 135: return "Limit: Resist"; + case 136: return "Limit: Target"; + case 137: return "Limit: Effect"; + case 138: return "Limit: Spell Type"; + case 139: return "Limit: Spell"; + case 140: return "Limit: Min Duration"; + case 141: return "Limit: Instant"; + case 142: return "Limit: Min Level"; + case 143: return "Limit: Min Cast Time"; + case 144: return "Limit: Max Cast Time"; + case 145: return "NPC Warder Banish"; + case 146: return "Portal Locations"; + case 147: return "Hit Points Percent"; + case 148: return "Stacking: Block"; + case 149: return "Stacking: Overwrite"; + case 150: return "Death Save"; + case 151: return "Pocket Pet"; + case 152: return "Summon Pets"; + case 153: return "Balance Party Damage"; + case 154: return "Remove Detrimental"; + case 155: return "PoP Resurrect"; + case 156: return "Mirror"; + case 157: return "Spell Damage Shield"; + case 158: return "Reflect Spell"; + case 159: return "All Stats"; + case 160: return "Drunk"; + case 167: return "Increase Pet Power"; + case 168: return "Defensive"; + case 169: return "Chance to Critical Melee"; + case 170: return "Chance to Critical Cast"; + case 254: return "No Effect"; + default: return nullptr; + } +} + +bool SpellEffectUsesPercent(int attrib) { + switch (attrib) { + case 3: + case 11: + case 98: + case 124: + case 125: + case 126: + case 127: + case 128: + case 129: + case 130: + case 131: + case 132: + case 167: + case 168: + case 177: + case 195: + case 200: + case 232: + case 233: + case 258: + case 273: + case 274: + case 275: + case 279: + case 280: + case 294: + case 302: + case 320: + case 483: + return true; + default: + return false; + } +} + +int LowestSpellLevel(void* spell) { + int lowest_level = 255; + for (size_t i = 0; i < 16; ++i) { + int level = ReadValue(static_cast(spell) + kSpellLevel + i); + if (level > 0 && level < 255) { + lowest_level = std::min(lowest_level, level); + } + } + return lowest_level == 255 ? 1 : lowest_level; +} + +void AppendSpellClassLevels(std::string& out, void* spell) { + static const char* kClassNames[16] = { + "WAR", "CLR", "PAL", "RNG", "SHD", "DRU", "MNK", "BRD", + "ROG", "SHM", "NEC", "WIZ", "MAG", "ENC", "BST", "BER" + }; + + std::string classes; + for (size_t i = 0; i < 16; ++i) { + int level = ReadValue(static_cast(spell) + kSpellLevel + i); + if (level <= 0 || level >= 255) { + continue; + } + + char part[32]{}; + _snprintf_s(part, sizeof(part), _TRUNCATE, "%s%s(%d)", classes.empty() ? "" : ", ", kClassNames[i], level); + classes += part; + } + + if (!classes.empty()) { + out += classes + "
    "; + } +} + +std::string FormatSpellEffectLine(void* spell, size_t slot) { + int attrib = ReadValue(static_cast(spell) + kSpellAttrib + slot * sizeof(int32_t), kSpellEffectNone); + int base = ReadValue(static_cast(spell) + kSpellBase + slot * sizeof(int32_t)); + int base2 = ReadValue(static_cast(spell) + kSpellBase2 + slot * sizeof(int32_t)); + int max = ReadValue(static_cast(spell) + kSpellMax + slot * sizeof(int32_t)); + int calc = ReadValue(static_cast(spell) + kSpellCalc + slot * sizeof(int32_t)); + + if (attrib == kSpellEffectNone || attrib < 0 || attrib > 700) { + return {}; + } + + if (attrib == 10 && (base <= 1 || base > 255)) { + return {}; + } + + int adjusted_base = base; + int adjusted_max = max; + if (attrib == 11) { + adjusted_base -= 100; + adjusted_max -= 100; + } else if (attrib == 127 || attrib == 128 || attrib == 132) { + adjusted_max = base2; + } + + int min_level = LowestSpellLevel(spell); + int calc_base = attrib == kSpellEffectStackingBlock ? adjusted_max : adjusted_base; + int64_t value = CalcSpellValue(calc, calc_base, adjusted_max, 1, min_level, min_level); + bool percent = SpellEffectUsesPercent(attrib); + const char* name = SpellEffectName(attrib); + char display_name_fallback[32]{}; + const char* display_name = name; + if (!display_name) { + _snprintf_s(display_name_fallback, sizeof(display_name_fallback), _TRUNCATE, "SPA %d", attrib); + display_name = display_name_fallback; + } + + char line[256]{}; + const char* direction = value < 0 ? "Decrease" : "Increase"; + int64_t magnitude = Abs64(value); + + switch (attrib) { + case 0: + case 15: + case 35: + case 36: + case 46: + case 47: + case 48: + case 49: + case 50: + case 69: + case 78: + case 79: + case 92: + case 97: + case 99: + case 100: + case 124: + case 147: + _snprintf_s(line, sizeof(line), _TRUNCATE, "Slot %u: %s %s by %lld%s
    ", + static_cast(slot + 1), direction, display_name, magnitude, percent ? "%" : ""); + break; + case 1: + _snprintf_s(line, sizeof(line), _TRUNCATE, "Slot %u: %s %s by %lld
    ", + static_cast(slot + 1), direction, display_name, magnitude); + break; + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 127: + case 128: + case 129: + case 130: + case 131: + case 132: + case 167: + case 168: + _snprintf_s(line, sizeof(line), _TRUNCATE, "Slot %u: %s %s by %lld%s
    ", + static_cast(slot + 1), direction, display_name, magnitude, percent ? "%" : ""); + break; + case 12: + case 13: + case 14: + case 20: + case 22: + case 23: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + case 58: + case 60: + case 61: + case 62: + case 65: + case 66: + case 67: + case 68: + case 70: + case 71: + case 72: + case 73: + case 75: + case 76: + case 77: + case 80: + case 82: + case 91: + case 96: + _snprintf_s(line, sizeof(line), _TRUNCATE, "Slot %u: %s
    ", + static_cast(slot + 1), display_name); + break; + case 21: + case 64: + _snprintf_s(line, sizeof(line), _TRUNCATE, "Slot %u: Stun for %.1fs
    ", + static_cast(slot + 1), static_cast(magnitude) / 1000.0f); + break; + case 27: + case 85: + case 134: + case 135: + case 136: + case 137: + case 138: + case 139: + case 140: + case 141: + case 142: + case 143: + case 144: + _snprintf_s(line, sizeof(line), _TRUNCATE, "Slot %u: %s (%d, %d, %d)
    ", + static_cast(slot + 1), display_name, base, base2, max); + break; + case kSpellEffectStackingBlock: + case kSpellEffectStackingOverwrite: { + int effect_slot = attrib == kSpellEffectStackingBlock ? (base2 > 0 ? base2 : calc - 200) : calc - 200; + int comparison_max = attrib == kSpellEffectStackingOverwrite && max > 1000 ? max - 1000 : max; + const char* referenced = SpellEffectName(base); + char fallback[48]{}; + if (!referenced) { + _snprintf_s(fallback, sizeof(fallback), _TRUNCATE, "Effect %d", base); + referenced = fallback; + } + + if (effect_slot > 0 && comparison_max > 0) { + _snprintf_s(line, sizeof(line), _TRUNCATE, "Slot %u: %s %s spell if slot %d is effect '%s' and < %lld
    ", + static_cast(slot + 1), display_name, + attrib == kSpellEffectStackingBlock ? "new" : "existing", + effect_slot, referenced, magnitude); + } else if (effect_slot > 0) { + _snprintf_s(line, sizeof(line), _TRUNCATE, "Slot %u: %s %s spell if slot %d is effect '%s'
    ", + static_cast(slot + 1), display_name, + attrib == kSpellEffectStackingBlock ? "new" : "existing", + effect_slot, referenced); + } else { + _snprintf_s(line, sizeof(line), _TRUNCATE, "Slot %u: %s %s spell if effect '%s'
    ", + static_cast(slot + 1), display_name, + attrib == kSpellEffectStackingBlock ? "new" : "existing", + referenced); + } + break; + } + default: + _snprintf_s(line, sizeof(line), _TRUNCATE, "Slot %u: %s by %lld%s
    ", + static_cast(slot + 1), display_name, magnitude, percent ? "%" : ""); + break; + } + + return std::string(line); +} + +void AppendSpellCore(std::string& out, uint32_t spell_id, const char* title, bool verbose) { + if (spell_id == 0 || spell_id == 0xFFFFFFFF || spell_id >= kMaxSpellID) { + return; + } + + void* spell = GetSpell(spell_id); + std::string name = EscapeStml(GetSpellName(spell_id)); + + char line[256]{}; + if (strcmp(title, "Spell") == 0) { + _snprintf_s(line, sizeof(line), _TRUNCATE, "Spell: %s (#%u)
    ", name.c_str(), spell_id); + } else { + _snprintf_s(line, sizeof(line), _TRUNCATE, "Spell Info for %s effect: %s
    ", title, name.c_str()); + } + out += line; + + if (!spell || !verbose) { + return; + } + + _snprintf_s(line, sizeof(line), _TRUNCATE, "ID: %04u
    ", spell_id); + out += line; + + int cast_time = ReadValue(static_cast(spell) + kSpellCastTime); + int recast_time = ReadValue(static_cast(spell) + kSpellRecastTime); + if (cast_time > 0 || recast_time > 0) { + _snprintf_s(line, sizeof(line), _TRUNCATE, "CastTime: %.2fs   RecastTime: %.2fs
    ", + static_cast(cast_time) / 1000.0f, + static_cast(recast_time) / 1000.0f); + out += line; + } + + float range = ReadValue(static_cast(spell) + kSpellRange); + float ae_range = ReadValue(static_cast(spell) + kSpellAERange); + if (range > 0.0f || ae_range > 0.0f) { + if (range > 0.0f) { + _snprintf_s(line, sizeof(line), _TRUNCATE, "Range: %.0f", range); + out += line; + } + if (ae_range > 0.0f) { + _snprintf_s(line, sizeof(line), _TRUNCATE, "%sAERange: %.0f", range > 0.0f ? "   " : "", ae_range); + out += line; + } + out += "
    "; + } + + for (size_t i = 0; i < kSpellEffectSlots; ++i) { + out += FormatSpellEffectLine(spell, i); + } + + AppendSpellClassLevels(out, spell); + + std::string cast_on_you = EscapeStml(ReadFixedString(static_cast(spell) + kSpellCastOnYou, 0x60)); + std::string cast_on_another = EscapeStml(ReadFixedString(static_cast(spell) + kSpellCastOnAnother, 0x60)); + std::string wear_off = EscapeStml(ReadFixedString(static_cast(spell) + kSpellWearOff, 0x60)); + if (!cast_on_you.empty()) { + out += "Cast on you: " + cast_on_you + "
    "; + } + if (!cast_on_another.empty()) { + out += "Cast on another: " + cast_on_another + "
    "; + } + if (!wear_off.empty()) { + out += "Wears off: " + wear_off + "
    "; + } +} + +void AppendItemSpellLine(std::string& out, void* item, size_t offset, const char* label) { + uint32_t spell_id = ReadValue(static_cast(item) + offset + kItemSpellID); + if (spell_id == 0 || spell_id == 0xFFFFFFFF || spell_id >= kMaxSpellID) { + return; + } + + AppendSpellCore(out, spell_id, label, true); +} + +bool AppendSTML(void* stml_wnd, const std::string& text) { + if (!stml_wnd || text.empty()) { + return false; + } + + auto ctor = reinterpret_cast(Rebase(kCXStrCtorCString)); + auto append = reinterpret_cast(Rebase(kCStmlWndAppendSTML)); + auto parse_now = reinterpret_cast(Rebase(kCStmlWndForceParseNow)); + + CXStr value{}; + CXSize result{}; + __try { + ctor(&value, text.c_str()); + + // AppendSTML takes CXStr by value. EQ destroys that stack parameter + // before returning, so do not call the CXStr destructor here. + append(stml_wnd, &result, value); + parse_now(stml_wnd); + } __except (EXCEPTION_EXECUTE_HANDLER) { + Log("AppendSTML exception stml=%p bytes=%u", stml_wnd, static_cast(text.size())); + return false; + } + + if (g_stml_append_log_count < 12) { + ++g_stml_append_log_count; + Log("AppendSTML stml=%p bytes=%u", stml_wnd, static_cast(text.size())); + } + return true; +} + +bool LooksLikeItem(void* item) { + if (!item || !IsReadableMemory(item, 0x200)) { + return false; + } + + uint32_t item_id = ReadValue(static_cast(item) + kItemNumber); + if (item_id == 0 || item_id > 10000000) { + return false; + } + + return !ReadFixedString(static_cast(item) + kItemName, 0x40).empty(); +} + +struct ItemInspectContext { + void* contents = nullptr; + void* item = nullptr; + void* display_wnd = nullptr; + size_t p_item_offset = 0; + size_t contents_item_offset = 0; + size_t display_offset = 0; +}; + +bool FindItemInContents(void* contents, void** out_item, size_t* out_item_offset) { + if (out_item) { + *out_item = nullptr; + } + if (out_item_offset) { + *out_item_offset = 0; + } + if (!contents) { + return false; + } + + for (size_t offset : kContentsItemOffsets) { + void* item = ReadPtrOffset(contents, offset); + if (LooksLikeItem(item)) { + if (out_item) { + *out_item = item; + } + if (out_item_offset) { + *out_item_offset = offset; + } + return true; + } + } + + return false; +} + +void* GetItemFromContents(void* contents) { + void* item = nullptr; + size_t item_offset = 0; + if (FindItemInContents(contents, &item, &item_offset)) { + return item; + } + return nullptr; +} + +void* FindItemDisplayWnd(void* window, size_t* out_display_offset) { + if (out_display_offset) { + *out_display_offset = 0; + } + if (!window) { + return nullptr; + } + + for (size_t offset : kItemWindowDisplayOffsets) { + void* display_wnd = ReadPtrOffset(window, offset); + if (display_wnd && IsReadableMemory(display_wnd, sizeof(void*))) { + if (out_display_offset) { + *out_display_offset = offset; + } + return display_wnd; + } + } + + return nullptr; +} + +bool FindDisplayedItem(void* window, ItemInspectContext& context) { + context = ItemInspectContext{}; + if (!window) { + return false; + } + + for (size_t p_item_offset : kItemWindowPItemOffsets) { + void* contents = ReadPtrOffset(window, p_item_offset); + void* item = nullptr; + size_t contents_item_offset = 0; + if (!FindItemInContents(contents, &item, &contents_item_offset)) { + continue; + } + + size_t display_offset = 0; + void* display_wnd = FindItemDisplayWnd(window, &display_offset); + if (!display_wnd) { + continue; + } + + context.contents = contents; + context.item = item; + context.display_wnd = display_wnd; + context.p_item_offset = p_item_offset; + context.contents_item_offset = contents_item_offset; + context.display_offset = display_offset; + return true; + } + + return false; +} + +void LogItemLookupFailure(void* window) { + if (g_item_lookup_log_count >= 12) { + return; + } + + ++g_item_lookup_log_count; + Log("ItemInspect lookup failed window=%p pItem[2b0]=%p pItem[2c0]=%p pItem[2c8]=%p pItem[2ac]=%p display[220]=%p display[21c]=%p display[230]=%p display[238]=%p", + window, + ReadPtrOffset(window, 0x2b0), + ReadPtrOffset(window, 0x2c0), + ReadPtrOffset(window, 0x2c8), + ReadPtrOffset(window, 0x2ac), + ReadPtrOffset(window, 0x220), + ReadPtrOffset(window, 0x21c), + ReadPtrOffset(window, 0x230), + ReadPtrOffset(window, 0x238)); +} + +bool AppendItemInspect(void* window) { + if (!g_config.inspect_items || !window) { + return false; + } + + ItemInspectContext context{}; + if (!FindDisplayedItem(window, context)) { + LogItemLookupFailure(window); + return false; + } + + void* item = context.item; + void* display_wnd = context.display_wnd; + std::string out = "
    Native Interface
    "; + + uint32_t item_id = ReadValue(static_cast(item) + kItemNumber); + std::string name = EscapeStml(ReadFixedString(static_cast(item) + kItemName, 0x40)); + if (g_item_append_log_count < 12) { + ++g_item_append_log_count; + Log("ItemInspect append window=%p display=%p pItemOff=0x%X contents=%p itemOff=0x%X item=%p item_id=%u name=%s displayOff=0x%X", + window, + display_wnd, + static_cast(context.p_item_offset), + context.contents, + static_cast(context.contents_item_offset), + item, + item_id, + name.c_str(), + static_cast(context.display_offset)); + } + + char line[256]{}; + _snprintf_s(line, sizeof(line), _TRUNCATE, "Item ID: %u
    ", item_id); + out += line; + AppendItemPowerLines(out, item, item_id); + + std::string lore = EscapeStml(ReadFixedString(static_cast(item) + kItemLoreName, 0x70)); + if (!lore.empty() && lore != name && !(lore.size() > 1 && lore[0] == '*' && lore.substr(1) == name)) { + out += "Item Lore: " + lore + "
    "; + } + + AppendMoneyLine(out, ReadValue(static_cast(item) + kItemCost)); + + int stack_size = ReadValue(static_cast(item) + kItemStackSize); + if (stack_size > 1) { + AppendLine(out, "Stackable Count", stack_size); + } + + int damage = ReadValue(static_cast(item) + kItemDamage); + int delay = ReadValue(static_cast(item) + kItemDelay); + if (damage > 0 && delay > 0) { + float ratio = static_cast(delay) / static_cast(damage); + _snprintf_s(line, sizeof(line), _TRUNCATE, "Ratio: %.3f
    ", ratio); + out += line; + float efficiency = (static_cast(damage) * 2.0f / static_cast(delay)) * 50.0f; + _snprintf_s(line, sizeof(line), _TRUNCATE, "Efficiency: %.0f
    ", efficiency); + out += line; + } + + uint32_t proc_spell = ReadValue(static_cast(item) + kItemProc + kItemSpellID); + if (proc_spell > 0 && proc_spell != 0xFFFFFFFF && proc_spell < kMaxSpellID) { + int required_level = ReadValue(static_cast(item) + kItemProc + kItemSpellRequiredLevel); + int proc_rate = ReadValue(static_cast(item) + kItemProc + kItemSpellProcRate); + if (required_level <= 0) { + required_level = 1; + } + if (proc_rate != 0) { + _snprintf_s(line, sizeof(line), _TRUNCATE, "Procs at level %d (Proc rate modifier: %d)
    ", + required_level, proc_rate); + } else { + _snprintf_s(line, sizeof(line), _TRUNCATE, "Procs at level %d
    ", required_level); + } + out += line; + } + + uint32_t click_spell = ReadValue(static_cast(item) + kItemClicky + kItemSpellID); + if (click_spell > 0 && click_spell != 0xFFFFFFFF && click_spell < kMaxSpellID) { + int required_level = ReadValue(static_cast(item) + kItemClicky + kItemSpellRequiredLevel); + if (required_level <= 0) { + required_level = 1; + } + _snprintf_s(line, sizeof(line), _TRUNCATE, "Clickable at level %d
    ", required_level); + out += line; + } + + uint8_t slots = ReadValue(static_cast(item) + kItemSlots); + if (slots) { + AppendLine(out, "Container Slots", slots); + AppendLine(out, "Weight Reduction", ReadValue(static_cast(item) + kItemWeightReduction)); + } + + AppendItemSpellLine(out, item, kItemClicky, "Clicky"); + AppendItemSpellLine(out, item, kItemProc, "Proc"); + AppendItemSpellLine(out, item, kItemWorn, "Worn"); + AppendItemSpellLine(out, item, kItemFocus, "Focus"); + AppendItemSpellLine(out, item, kItemScroll, "Scroll"); + + out += "
    "; + AppendSTML(display_wnd, out); + return true; +} + +void AppendSpellInspect(void* window) { + if (!g_config.inspect_spells || !window) { + return; + } + + uint32_t spell_id = ReadValue(static_cast(window) + kSpellWindowSpellID); + if (spell_id == 0 || spell_id >= kMaxSpellID || !GetSpell(spell_id)) { + return; + } + + void* display_wnd = ReadPtrOffset(window, kSpellWindowDisplayWnd); + if (!display_wnd) { + return; + } + + if (g_spell_append_log_count < 12) { + ++g_spell_append_log_count; + Log("SpellInspect append window=%p display=%p spell_id=%u", window, display_wnd, spell_id); + } + + std::string out = "
    Native Interface
    "; + AppendSpellCore(out, spell_id, "Spell", true); + out += "
    "; + AppendSTML(display_wnd, out); +} + +void __fastcall ItemUpdateStringsDetour(void* self, void*) { + ItemUpdateStringsProc original = g_item_update_hook.original(); + if (!original) { + return; + } + + if (g_in_update_strings) { + original(self); + return; + } + + g_in_update_strings = true; + original(self); + if (g_item_update_log_count < 12) { + ++g_item_update_log_count; + Log("ItemDisplay UpdateStrings detour self=%p", self); + } + + if (!AppendItemInspect(self)) { + AppendSpellInspect(self); + } + g_in_update_strings = false; +} + +void __fastcall DspChatDetour(void* self, void*, const char* message, DWORD color, bool eq_log, bool do_percent_subst) { + if (ParseItemPowerTransport(message)) { + return; + } + + DspChatProc original = g_chat_hook.original(); + if (original) { + original(self, message, color, eq_log, do_percent_subst); + } +} + +std::string CleanSpawnName(std::string name) { + if (name.empty()) { + return name; + } + + std::replace(name.begin(), name.end(), '_', ' '); + while (!name.empty() && (name.back() == ' ' || name.back() == '\t')) { + name.pop_back(); + } + return name; +} + +bool ShouldShowSpawn(uint8_t type, uint8_t gm, bool is_target) { + if (is_target && g_config.map_show_target) { + return true; + } + + if (gm) { + return g_config.map_show_players || g_config.map_show_npcs; + } + + switch (type) { + case kSpawnNPC: + return g_config.map_show_npcs; + case kSpawnPlayer: + return g_config.map_show_players; + case kSpawnCorpse: + return g_config.map_show_corpses; + default: + return false; + } +} + +bool NamePassesFilters(const std::string& name, bool is_target) { + if (is_target && g_config.map_show_target) { + return true; + } + + if (!g_config.map_name_filter.empty() && !ContainsInsensitive(name, g_config.map_name_filter)) { + return false; + } + + if (!g_config.map_hide_filter.empty() && ContainsInsensitive(name, g_config.map_hide_filter)) { + return false; + } + + return true; +} + +bool TryParseUInt32(const std::string& value, uint32_t& out) { + if (value.empty()) { + return false; + } + + char* end = nullptr; + unsigned long parsed = strtoul(value.c_str(), &end, 10); + if (!end || *end != '\0') { + return false; + } + + out = static_cast(parsed); + return true; +} + +double SpawnDistanceSquared(void* local_spawn, void* spawn) { + if (!local_spawn || !spawn) { + return 0.0; + } + + double dx = static_cast(ReadValue(static_cast(spawn) + kSpawnX, 0.0f)) - + static_cast(ReadValue(static_cast(local_spawn) + kSpawnX, 0.0f)); + double dy = static_cast(ReadValue(static_cast(spawn) + kSpawnY, 0.0f)) - + static_cast(ReadValue(static_cast(local_spawn) + kSpawnY, 0.0f)); + double dz = static_cast(ReadValue(static_cast(spawn) + kSpawnZ, 0.0f)) - + static_cast(ReadValue(static_cast(local_spawn) + kSpawnZ, 0.0f)); + return dx * dx + dy * dy + dz * dz; +} + +float SpawnDistance(void* local_spawn, void* spawn) { + return static_cast(sqrt(SpawnDistanceSquared(local_spawn, spawn))); +} + +bool IsFiniteWorldCoord(float value) { + return std::isfinite(value) && value > -100000.0f && value < 100000.0f; +} + +std::string GetSpawnCleanName(void* spawn) { + if (!spawn) { + return {}; + } + + std::string name = CleanSpawnName(ReadFixedString(static_cast(spawn) + kSpawnDisplayedName, 0x40)); + if (name.empty()) { + name = CleanSpawnName(ReadFixedString(static_cast(spawn) + kSpawnName, 0x40)); + } + return name; +} + +void* FindSpawnByID(uint32_t spawn_id) { + if (spawn_id == 0) { + return nullptr; + } + + void* spawn_mgr = ReadGlobalPtr(kPInstSpawnManager); + void* spawn = ReadPtrOffset(spawn_mgr, kSpawnManagerFirstSpawn); + std::unordered_set visited; + while (spawn && visited.insert(spawn).second) { + void* next = ReadPtrOffset(spawn, kSpawnNext); + uint32_t current_id = ReadValue(static_cast(spawn) + kSpawnID, 0); + if (current_id == spawn_id) { + return spawn; + } + spawn = next; + } + + return nullptr; +} + +bool LooksLikeXTargetMgr(void* manager) { + if (!manager || !IsReadableMemory(manager, kXTargetMgrArray + sizeof(void*))) { + return false; + } + + uint32_t slots = ReadValue(static_cast(manager) + kXTargetMgrSlots, 0xFFFFFFFF); + if (slots > kMaxXTargets) { + return false; + } + + void* array = ReadPtrOffset(manager, kXTargetMgrArray); + if (slots == 0) { + return true; + } + + return array && IsReadableMemory(array, static_cast(slots) * kXTargetSlotSize); +} + +std::vector ReadXTargets() { + std::vector targets; + void* char_data = ReadGlobalPtr(kPInstCharData); + if (!char_data) { + return targets; + } + + void* manager = ReadPtrOffset(char_data, kCharDataXTargetMgr); + if (!LooksLikeXTargetMgr(manager)) { + void* inline_manager = static_cast(char_data) + kCharDataXTargetMgr; + manager = LooksLikeXTargetMgr(inline_manager) ? inline_manager : nullptr; + } + if (!manager) { + return targets; + } + + uint32_t slot_count = ReadValue(static_cast(manager) + kXTargetMgrSlots, 0); + slot_count = std::min(slot_count, kMaxXTargets); + void* array = ReadPtrOffset(manager, kXTargetMgrArray); + if (!array || !IsReadableMemory(array, static_cast(slot_count) * kXTargetSlotSize)) { + return targets; + } + + void* local_spawn = ReadGlobalPtr(kPInstCharSpawn); + targets.reserve(slot_count); + for (uint32_t i = 0; i < slot_count; ++i) { + BYTE* slot = static_cast(array) + static_cast(i) * kXTargetSlotSize; + uint32_t spawn_id = ReadValue(slot + kXTargetSpawnID, 0); + std::string name = CleanSpawnName(ReadFixedString(slot + kXTargetName, 0x40)); + if (spawn_id == 0 && name.empty()) { + continue; + } + + XTargetInfo info{}; + info.slot = static_cast(i + 1); + info.type = ReadValue(slot + kXTargetType, 0); + info.spawn_id = spawn_id; + info.name = name; + info.spawn = FindSpawnByID(spawn_id); + if (info.spawn && local_spawn) { + info.distance = SpawnDistance(local_spawn, info.spawn); + if (info.name.empty()) { + info.name = GetSpawnCleanName(info.spawn); + } + } + targets.push_back(std::move(info)); + } + + return targets; +} + +const XTargetInfo* FindXTargetForSpawn(const std::vector& targets, void* spawn, uint32_t spawn_id) { + if (!spawn && spawn_id == 0) { + return nullptr; + } + + for (const auto& target : targets) { + if ((spawn && target.spawn == spawn) || (spawn_id != 0 && target.spawn_id == spawn_id)) { + return ⌖ + } + } + return nullptr; +} + +bool LooksLikeGroundItem(void* item) { + if (!item || !IsReadableMemory(item, 0x80)) { + return false; + } + + std::string name = CleanSpawnName(ReadFixedString(static_cast(item) + kGroundItemName, 0x20)); + if (name.empty()) { + return false; + } + + float x = ReadValue(static_cast(item) + kGroundItemX, 0.0f); + float y = ReadValue(static_cast(item) + kGroundItemY, 0.0f); + float z = ReadValue(static_cast(item) + kGroundItemZ, 0.0f); + return IsFiniteWorldCoord(x) && IsFiniteWorldCoord(y) && IsFiniteWorldCoord(z); +} + +void* FindGroundItemList() { + for (uintptr_t candidate_address : kPInstEQItemListCandidates) { + void* head = ReadGlobalPtr(candidate_address); + if (LooksLikeGroundItem(head)) { + return head; + } + + void* nested_head = ReadPtr(head); + if (LooksLikeGroundItem(nested_head)) { + return nested_head; + } + } + + return nullptr; +} + +bool CanAddMapLabel() { + return g_config.map_max_labels <= 0 || static_cast(g_map_labels.size()) < g_config.map_max_labels; +} + +void AddMapLabelText(const std::string& text, float x, float y, float z, uint32_t color, uint32_t size = 3, uint32_t layer = 2) { + if (text.empty() || !CanAddMapLabel() || !IsFiniteWorldCoord(x) || !IsFiniteWorldCoord(y) || !IsFiniteWorldCoord(z)) { + return; + } + + ManagedMapLabel managed{}; + managed.text = text; + managed.native.location.x = -x; + managed.native.location.y = -y; + managed.native.location.z = z; + managed.native.color = color; + managed.native.size = size; + managed.native.layer = layer; + managed.native.width = 20; + managed.native.height = 14; + g_map_labels.push_back(std::move(managed)); +} + +void AddWorldMapLine(float start_x, float start_y, float start_z, float end_x, float end_y, float end_z, + uint32_t color, uint32_t layer = 2) { + if (!IsFiniteWorldCoord(start_x) || !IsFiniteWorldCoord(start_y) || !IsFiniteWorldCoord(start_z) || + !IsFiniteWorldCoord(end_x) || !IsFiniteWorldCoord(end_y) || !IsFiniteWorldCoord(end_z)) { + return; + } + + MapLineNative line{}; + line.start.x = -start_x; + line.start.y = -start_y; + line.start.z = start_z; + line.end.x = -end_x; + line.end.y = -end_y; + line.end.z = end_z; + line.color = color; + line.layer = layer; + g_map_lines.push_back(line); +} + +void AddMapCircle(float center_x, float center_y, float center_z, float radius, uint32_t color, uint32_t segments = 48) { + if (radius <= 0.0f || !IsFiniteWorldCoord(center_x) || !IsFiniteWorldCoord(center_y) || !IsFiniteWorldCoord(center_z)) { + return; + } + + segments = NativeClamp(segments, 12, 96); + for (uint32_t i = 0; i < segments; ++i) { + float a1 = (static_cast(i) / static_cast(segments)) * (2.0f * kPi); + float a2 = (static_cast(i + 1) / static_cast(segments)) * (2.0f * kPi); + AddWorldMapLine(center_x + cosf(a1) * radius, center_y + sinf(a1) * radius, center_z, + center_x + cosf(a2) * radius, center_y + sinf(a2) * radius, center_z, color, 2); + } +} + +void AddMapBoxMarker(float center_x, float center_y, float center_z, float radius, uint32_t color) { + if (radius <= 0.0f) { + return; + } + + AddWorldMapLine(center_x - radius, center_y - radius, center_z, center_x + radius, center_y - radius, center_z, color, 2); + AddWorldMapLine(center_x + radius, center_y - radius, center_z, center_x + radius, center_y + radius, center_z, color, 2); + AddWorldMapLine(center_x + radius, center_y + radius, center_z, center_x - radius, center_y + radius, center_z, color, 2); + AddWorldMapLine(center_x - radius, center_y + radius, center_z, center_x - radius, center_y - radius, center_z, color, 2); +} + +bool LooksNamedSpawn(uint8_t type, const std::string& name) { + if (type != kSpawnNPC || name.empty()) { + return false; + } + + std::string lowered = LowerCopy(name); + if (lowered.find("corpse") != std::string::npos) { + return false; + } + + return lowered.rfind("a ", 0) != 0 && lowered.rfind("an ", 0) != 0 && lowered.rfind("the ", 0) != 0; +} + +bool NameIsHighlighted(const std::string& name) { + return !g_config.map_highlight_filter.empty() && ContainsInsensitive(name, g_config.map_highlight_filter); +} + +void* FindSpawnByNameOrID(const std::string& query, std::string& found_name) { + found_name.clear(); + if (query.empty()) { + return nullptr; + } + + uint32_t query_id = 0; + bool match_id = TryParseUInt32(query, query_id); + void* spawn_mgr = ReadGlobalPtr(kPInstSpawnManager); + void* local_spawn = ReadGlobalPtr(kPInstCharSpawn); + void* spawn = ReadPtrOffset(spawn_mgr, kSpawnManagerFirstSpawn); + void* best_spawn = nullptr; + double best_distance = 1.0e30; + + std::unordered_set visited; + while (spawn && visited.insert(spawn).second) { + void* next = ReadPtrOffset(spawn, kSpawnNext); + if (spawn == local_spawn) { + spawn = next; + continue; + } + + std::string name = CleanSpawnName(ReadFixedString(static_cast(spawn) + kSpawnDisplayedName, 0x40)); + if (name.empty()) { + name = CleanSpawnName(ReadFixedString(static_cast(spawn) + kSpawnName, 0x40)); + } + + uint32_t spawn_id = ReadValue(static_cast(spawn) + kSpawnID, 0); + bool matches = (match_id && spawn_id == query_id) || (!name.empty() && ContainsInsensitive(name, query)); + if (matches) { + double distance = SpawnDistanceSquared(local_spawn, spawn); + if (!best_spawn || distance < best_distance) { + best_spawn = spawn; + best_distance = distance; + found_name = name; + } + } + + spawn = next; + } + + return best_spawn; +} + +uint32_t ConColorToARGB(int con_color) { + switch (con_color) { + case 0: + case 1: + return 0xFF505050; + case 2: + return 0xFF00FF00; + case 3: + return 0xFF00FFFF; + case 4: + return 0xFF0000FF; + case 5: + return 0xFFFFFFFF; + case 6: + return 0xFFFFFF00; + case 7: + default: + return 0xFFFF0000; + } +} + +int ApproximateConLevel(int player_level, int spawn_level) { + if (player_level <= 0 || spawn_level <= 0) { + return 5; + } + + int diff = spawn_level - player_level; + if (diff >= 3) { + return 7; + } + if (diff >= 1) { + return 6; + } + if (diff == 0) { + return 5; + } + if (diff >= -2) { + return 4; + } + if (diff >= -4) { + return 3; + } + if (diff >= -7) { + return 2; + } + return 1; +} + +uint32_t GetSpawnConColor(void* spawn, int spawn_level) { + void* char_data = ReadGlobalPtr(kPInstCharData); + if (char_data) { + auto get_con_level = reinterpret_cast(Rebase(kEQCharacterGetConLevel)); + __try { + int con_level = get_con_level(char_data, spawn); + if (con_level >= 0 && con_level <= 7) { + return ConColorToARGB(con_level); + } + } __except (EXCEPTION_EXECUTE_HANDLER) { + } + } + + void* local_spawn = ReadGlobalPtr(kPInstCharSpawn); + int player_level = ReadValue(static_cast(local_spawn) + kSpawnLevel, 0); + return ConColorToARGB(ApproximateConLevel(player_level, spawn_level)); +} + +uint32_t SpawnColor(void* spawn, uint8_t type, uint8_t gm, int spawn_level) { + if (g_config.map_use_con_color && spawn && (type == kSpawnNPC || type == kSpawnPlayer)) { + return GetSpawnConColor(spawn, spawn_level); + } + + if (gm) { + return 0xFFFF66FF; + } + + switch (type) { + case kSpawnNPC: + return 0xFF00E5FF; + case kSpawnPlayer: + return 0xFF66CCFF; + case kSpawnCorpse: + return 0xFFBBBBBB; + default: + return 0xFFFFFFFF; + } +} + +void UpdateMapLabels() { + g_map_labels.clear(); + g_map_lines.clear(); + + if (!g_config.map_enabled) { + return; + } + + void* spawn_mgr = ReadGlobalPtr(kPInstSpawnManager); + void* local_spawn = ReadGlobalPtr(kPInstCharSpawn); + void* target_spawn = ReadGlobalPtr(kPInstTarget); + void* spawn = ReadPtrOffset(spawn_mgr, kSpawnManagerFirstSpawn); + if (!spawn) { + return; + } + + std::vector xtargets = (g_config.xtar_enabled || g_config.map_show_xtargets) ? ReadXTargets() : std::vector{}; + g_map_labels.reserve(384); + g_map_lines.reserve(128); + std::unordered_set visited; + bool target_in_spawn_list = false; + while (spawn && visited.insert(spawn).second) { + + void* next = ReadPtrOffset(spawn, kSpawnNext); + if (spawn == local_spawn) { + spawn = next; + continue; + } + + uint8_t type = ReadValue(static_cast(spawn) + kSpawnType, 0xFF); + uint8_t gm = ReadValue(static_cast(spawn) + kSpawnGM, 0); + bool is_target = spawn == target_spawn; + if (is_target) { + target_in_spawn_list = true; + } + + uint32_t spawn_id = ReadValue(static_cast(spawn) + kSpawnID, 0); + const XTargetInfo* xtarget = FindXTargetForSpawn(xtargets, spawn, spawn_id); + bool is_xtarget = xtarget != nullptr; + if (!ShouldShowSpawn(type, gm, is_target) && !(g_config.map_show_xtargets && is_xtarget)) { + spawn = next; + continue; + } + + std::string name = GetSpawnCleanName(spawn); + if (name.empty()) { + spawn = next; + continue; + } + if (!NamePassesFilters(name, is_target)) { + spawn = next; + continue; + } + if (g_config.map_named_only && !is_target && !is_xtarget && !LooksNamedSpawn(type, name)) { + spawn = next; + continue; + } + + int level = ReadValue(static_cast(spawn) + kSpawnLevel, 0); + float x = ReadValue(static_cast(spawn) + kSpawnX, 0.0f); + float y = ReadValue(static_cast(spawn) + kSpawnY, 0.0f); + float z = ReadValue(static_cast(spawn) + kSpawnZ, 0.0f); + + uint32_t color = (is_target && g_config.map_show_target) ? kMapTargetColor : SpawnColor(spawn, type, gm, level); + uint32_t label_size = 3; + if (is_xtarget && !is_target) { + color = kMapXTargetColor; + } + if (NameIsHighlighted(name)) { + color = g_config.map_highlight_color; + label_size = static_cast(NativeClamp(g_config.map_highlight_size, 4, 200)); + AddMapBoxMarker(x, y, z, 12.0f, g_config.map_highlight_color); + } + + std::string label = name; + if (is_xtarget && g_config.map_xtarget_labels && xtarget) { + char suffix[64]{}; + if (xtarget->distance > 0.0f) { + _snprintf_s(suffix, sizeof(suffix), _TRUNCATE, " [XT%d %.0f]", xtarget->slot, xtarget->distance); + } else { + _snprintf_s(suffix, sizeof(suffix), _TRUNCATE, " [XT%d]", xtarget->slot); + } + label += suffix; + } + AddMapLabelText(label, x, y, z, color, label_size); + + if (g_config.map_show_vectors) { + float speed_x = ReadValue(static_cast(spawn) + kSpawnSpeedX, 0.0f); + float speed_y = ReadValue(static_cast(spawn) + kSpawnSpeedY, 0.0f); + float heading = ReadValue(static_cast(spawn) + kSpawnHeading, 0.0f); + float vector_x = speed_x; + float vector_y = speed_y; + if (fabsf(vector_x) < 0.01f && fabsf(vector_y) < 0.01f) { + float angle = heading * (2.0f * kPi / 512.0f); + vector_x = sinf(angle) * 12.0f; + vector_y = cosf(angle) * 12.0f; + } else { + vector_x *= 8.0f; + vector_y *= 8.0f; + } + AddWorldMapLine(x, y, z, x + vector_x, y + vector_y, z, color, 2); + } + + spawn = next; + } + + if (g_config.map_show_ground) { + void* ground = FindGroundItemList(); + std::unordered_set ground_visited; + unsigned ground_count = 0; + while (ground && ground_visited.insert(ground).second && ground_count < 512) { + void* next_ground = ReadPtrOffset(ground, kGroundItemNext); + if (!LooksLikeGroundItem(ground)) { + break; + } + + std::string name = CleanSpawnName(ReadFixedString(static_cast(ground) + kGroundItemName, 0x20)); + float x = ReadValue(static_cast(ground) + kGroundItemX, 0.0f); + float y = ReadValue(static_cast(ground) + kGroundItemY, 0.0f); + float z = ReadValue(static_cast(ground) + kGroundItemZ, 0.0f); + AddMapLabelText(std::string("G: ") + name, x, y, z, kMapGroundColor, 3); + AddMapBoxMarker(x, y, z, 4.0f, kMapGroundColor); + ++ground_count; + ground = next_ground; + } + } + + for (const auto& location : g_map_locations) { + AddMapLabelText(location.label, location.x, location.y, location.z, kMapLocationColor, 4); + AddMapBoxMarker(location.x, location.y, location.z, 8.0f, kMapLocationColor); + } + + for (size_t i = 0; i < g_map_labels.size(); ++i) { + g_map_labels[i].native.next = (i + 1 < g_map_labels.size()) ? &g_map_labels[i + 1].native : nullptr; + g_map_labels[i].native.prev = (i > 0) ? &g_map_labels[i - 1].native : nullptr; + g_map_labels[i].native.label = const_cast(g_map_labels[i].text.c_str()); + } + + if (target_in_spawn_list && local_spawn && target_spawn && local_spawn != target_spawn) { + float local_x = ReadValue(static_cast(local_spawn) + kSpawnX, 0.0f); + float local_y = ReadValue(static_cast(local_spawn) + kSpawnY, 0.0f); + float local_z = ReadValue(static_cast(local_spawn) + kSpawnZ, 0.0f); + float target_x = ReadValue(static_cast(target_spawn) + kSpawnX, 0.0f); + float target_y = ReadValue(static_cast(target_spawn) + kSpawnY, 0.0f); + float target_z = ReadValue(static_cast(target_spawn) + kSpawnZ, 0.0f); + + if (g_config.map_target_line) { + AddWorldMapLine(local_x, local_y, local_z, target_x, target_y, target_z, kMapTargetColor, 2); + } + if (g_config.map_target_radius > 0.0f) { + AddMapCircle(target_x, target_y, target_z, g_config.map_target_radius, kMapTargetColor); + } + } + + if (local_spawn) { + float local_x = ReadValue(static_cast(local_spawn) + kSpawnX, 0.0f); + float local_y = ReadValue(static_cast(local_spawn) + kSpawnY, 0.0f); + float local_z = ReadValue(static_cast(local_spawn) + kSpawnZ, 0.0f); + AddMapCircle(local_x, local_y, local_z, g_config.map_cast_radius, kMapRadiusColor); + AddMapCircle(local_x, local_y, local_z, g_config.map_spell_radius, 0xFF80C0FF); + } + + for (size_t i = 0; i < g_map_lines.size(); ++i) { + g_map_lines[i].next = (i + 1 < g_map_lines.size()) ? &g_map_lines[i + 1] : nullptr; + g_map_lines[i].prev = (i > 0) ? &g_map_lines[i - 1] : nullptr; + } +} + +void AttachMapLabels(void* map_window, MapLabelNative*& original_labels) { + original_labels = nullptr; + if (!map_window || g_map_labels.empty()) { + return; + } + + auto labels_ptr = reinterpret_cast(static_cast(map_window) + kMapLabels); + original_labels = ReadValue(labels_ptr, nullptr); + + MapLabelNative* head = &g_map_labels.front().native; + MapLabelNative* tail = &g_map_labels.back().native; + if (g_config.map_chain_eq_labels && original_labels) { + tail->next = original_labels; + } + + *labels_ptr = head; +} + +void DetachMapLabels(void* map_window, MapLabelNative* original_labels) { + if (!map_window || g_map_labels.empty()) { + return; + } + + auto labels_ptr = reinterpret_cast(static_cast(map_window) + kMapLabels); + MapLabelNative* tail = &g_map_labels.back().native; + if (g_config.map_chain_eq_labels && original_labels) { + tail->next = nullptr; + } + + *labels_ptr = original_labels; +} + +void AttachMapLines(void* map_window, MapLineNative*& original_lines) { + original_lines = nullptr; + if (!map_window || g_map_lines.empty()) { + return; + } + + auto lines_ptr = reinterpret_cast(static_cast(map_window) + kMapLines); + original_lines = ReadValue(lines_ptr, nullptr); + + MapLineNative* head = &g_map_lines.front(); + MapLineNative* tail = &g_map_lines.back(); + tail->next = original_lines; + *lines_ptr = head; +} + +void DetachMapLines(void* map_window, MapLineNative* original_lines) { + if (!map_window || g_map_lines.empty()) { + return; + } + + auto lines_ptr = reinterpret_cast(static_cast(map_window) + kMapLines); + MapLineNative* tail = &g_map_lines.back(); + tail->next = nullptr; + *lines_ptr = original_lines; +} + +int __fastcall MapPostDraw2Detour(void* self, void*) { + if (g_in_map_post_draw) { + return g_old_map_post_draw2 ? g_old_map_post_draw2(self) : 0; + } + + g_in_map_post_draw = true; + + DWORD now = GetTickCount(); + DWORD update_start = now; + if (now - g_last_map_refresh > static_cast(g_config.map_refresh_ms)) { + UpdateMapLabels(); + g_last_map_refresh = now; + } + DWORD update_elapsed = GetTickCount() - update_start; + + if (g_map_draw_log_count < 8) { + ++g_map_draw_log_count; + Log("Map draw pass labels=%u lines=%u update_ms=%lu parent=%p draw_self=%p", + static_cast(g_map_labels.size()), static_cast(g_map_lines.size()), + update_elapsed, g_hooked_map_window, self); + } + + MapLabelNative* original_labels = nullptr; + MapLineNative* original_lines = nullptr; + void* map_window = g_hooked_map_window ? g_hooked_map_window : ReadGlobalPtr(kPInstCMapViewWnd); + AttachMapLabels(map_window, original_labels); + AttachMapLines(map_window, original_lines); + + int result = 0; + if (g_old_map_post_draw2) { + result = g_old_map_post_draw2(self); + } + + DetachMapLines(map_window, original_lines); + DetachMapLabels(map_window, original_labels); + g_in_map_post_draw = false; + return result; +} + +void RestoreMapHook() { + if (!g_hooked_map_window || !g_new_map_vtable || !g_old_map_vtable) { + return; + } + + auto vtable_field = reinterpret_cast(static_cast(g_hooked_map_window) + kMapViewVTable); + void** current = ReadValue(vtable_field, nullptr); + if (current == g_new_map_vtable) { + DWORD old_protect = 0; + if (VirtualProtect(vtable_field, sizeof(void*), PAGE_EXECUTE_READWRITE, &old_protect)) { + *vtable_field = g_old_map_vtable; + DWORD unused = 0; + VirtualProtect(vtable_field, sizeof(void*), old_protect, &unused); + } + } + + VirtualFree(g_new_map_vtable, 0, MEM_RELEASE); + g_hooked_map_window = nullptr; + g_old_map_vtable = nullptr; + g_new_map_vtable = nullptr; + g_old_map_post_draw2 = nullptr; +} + +bool InstallMapHook() { + if (!g_config.map_enabled) { + return false; + } + + void* map_window = ReadGlobalPtr(kPInstCMapViewWnd); + if (!map_window) { + return false; + } + + if (map_window == g_hooked_map_window && g_new_map_vtable) { + return true; + } + + RestoreMapHook(); + + auto vtable_field = reinterpret_cast(static_cast(map_window) + kMapViewVTable); + void** old_vtable = ReadValue(vtable_field, nullptr); + if (!old_vtable || !IsReadableMemory(old_vtable, kMapVTableBytes)) { + return false; + } + + void** new_vtable = static_cast(VirtualAlloc(nullptr, kMapVTableBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); + if (!new_vtable) { + return false; + } + + memcpy(new_vtable, old_vtable, kMapVTableBytes); + g_old_map_post_draw2 = reinterpret_cast(new_vtable[kMapPostDraw2Index]); + if (new_vtable[kMapPostDraw2Index] == reinterpret_cast(&MapPostDraw2Detour)) { + VirtualFree(new_vtable, 0, MEM_RELEASE); + g_old_map_post_draw2 = nullptr; + return false; + } + new_vtable[kMapPostDraw2Index] = reinterpret_cast(&MapPostDraw2Detour); + + DWORD old_protect = 0; + if (!VirtualProtect(vtable_field, sizeof(void*), PAGE_EXECUTE_READWRITE, &old_protect)) { + VirtualFree(new_vtable, 0, MEM_RELEASE); + return false; + } + + *vtable_field = new_vtable; + DWORD unused = 0; + VirtualProtect(vtable_field, sizeof(void*), old_protect, &unused); + + g_hooked_map_window = map_window; + g_old_map_vtable = old_vtable; + g_new_map_vtable = new_vtable; + Log("Installed map PostDraw2 hook at map window %p", map_window); + return true; +} + +void InstallItemHook() { + void* target = reinterpret_cast(Rebase(kCItemDisplayWndUpdateStrings)); + if (InstallInlineHook(g_item_update_hook, target, reinterpret_cast(&ItemUpdateStringsDetour), 6)) { + Log("Installed item display UpdateStrings hook at %p", target); + } else { + Log("Failed to install item display UpdateStrings hook at %p", target); + } +} + +void InstallChatHook() { + void* target = reinterpret_cast(Rebase(kCEverQuestDspChat)); + if (InstallInlineHook(g_chat_hook, target, reinterpret_cast(&DspChatDetour), 6)) { + Log("Installed DspChat hook at %p", target); + } else { + Log("Failed to install DspChat hook at %p", target); + } +} + +void PrintMapStatus() { + void* map_window = ReadGlobalPtr(kPInstCMapViewWnd); + void* spawn_mgr = ReadGlobalPtr(kPInstSpawnManager); + void* first_spawn = ReadPtrOffset(spawn_mgr, kSpawnManagerFirstSpawn); + void* target_spawn = ReadGlobalPtr(kPInstTarget); + char max_labels[32]{}; + if (g_config.map_max_labels <= 0) { + strcpy_s(max_labels, "unlimited"); + } else { + _snprintf_s(max_labels, sizeof(max_labels), _TRUNCATE, "%d", g_config.map_max_labels); + } + Chat("NativeMap: %s, hook=%s, labels=%u, map=%p, hooked=%p, first_spawn=%p", + g_config.map_enabled ? "on" : "off", + g_new_map_vtable ? "installed" : "not installed", + static_cast(g_map_labels.size()), + map_window, + g_hooked_map_window, + first_spawn); + Chat("NativeMap filters: npcs=%d players=%d corpses=%d con_color=%d target=%d target_line=%d normal_labels=%d max=%s refresh_ms=%d", + g_config.map_show_npcs ? 1 : 0, + g_config.map_show_players ? 1 : 0, + g_config.map_show_corpses ? 1 : 0, + g_config.map_use_con_color ? 1 : 0, + g_config.map_show_target ? 1 : 0, + g_config.map_target_line ? 1 : 0, + g_config.map_chain_eq_labels ? 1 : 0, + max_labels, + g_config.map_refresh_ms); + Chat("NativeMap extra: ground=%d vector=%d named=%d xtargets=%d xtlabels=%d radii target=%.1f cast=%.1f spell=%.1f", + g_config.map_show_ground ? 1 : 0, + g_config.map_show_vectors ? 1 : 0, + g_config.map_named_only ? 1 : 0, + g_config.map_show_xtargets ? 1 : 0, + g_config.map_xtarget_labels ? 1 : 0, + g_config.map_target_radius, + g_config.map_cast_radius, + g_config.map_spell_radius); + Chat("NativeMap search: filter='%s' hide='%s' highlight='%s' current_target=%p lines=%u", + g_config.map_name_filter.empty() ? "" : g_config.map_name_filter.c_str(), + g_config.map_hide_filter.empty() ? "" : g_config.map_hide_filter.c_str(), + g_config.map_highlight_filter.empty() ? "" : g_config.map_highlight_filter.c_str(), + target_spawn, + static_cast(g_map_lines.size())); +} + +void RefreshMapOverlay() { + g_last_map_refresh = 0; + UpdateMapLabels(); +} + +void SetMapBool(bool& setting, const char* ini_key, bool enabled, bool refresh) { + setting = enabled; + SaveConfigBool("Map", ini_key, enabled); + if (refresh) { + RefreshMapOverlay(); + } +} + +void SetMapFloat(float& setting, const char* ini_key, float value) { + setting = std::max(0.0f, value); + SaveConfigFloat("Map", ini_key, setting); + RefreshMapOverlay(); +} + +bool HandleTextFilterCommand(const char* args, std::string& setting, const char* ini_key, const char* label) { + std::string value = TrimCopy(args); + if (value.empty()) { + Chat("NativeMap %s filter is '%s'.", label, setting.empty() ? "" : setting.c_str()); + return true; + } + + std::string lowered = LowerCopy(value); + if (lowered == "clear" || lowered == "off" || lowered == "none") { + setting.clear(); + SaveConfigString("Map", ini_key, setting); + RefreshMapOverlay(); + Chat("NativeMap %s filter cleared.", label); + return true; + } + + setting = value; + SaveConfigString("Map", ini_key, setting); + RefreshMapOverlay(); + Chat("NativeMap %s filter set to '%s'.", label, setting.c_str()); + return true; +} + +bool HandleTargetCommand(const char* args) { + std::string query = TrimCopy(args); + if (query.empty()) { + Chat("NativeMap target usage: /nimap target |clear"); + return true; + } + + std::string lowered = LowerCopy(query); + if (lowered == "clear" || lowered == "off") { + if (WriteGlobalPtr(kPInstTarget, nullptr)) { + RefreshMapOverlay(); + Chat("NativeMap target cleared."); + } else { + Chat("NativeMap target clear failed."); + } + return true; + } + + std::string found_name; + void* spawn = FindSpawnByNameOrID(query, found_name); + if (!spawn) { + Chat("NativeMap found no spawn matching '%s'.", query.c_str()); + return true; + } + + if (WriteGlobalPtr(kPInstTarget, spawn)) { + RefreshMapOverlay(); + Chat("NativeMap target selected: %s.", found_name.empty() ? query.c_str() : found_name.c_str()); + } else { + Chat("NativeMap target select failed."); + } + return true; +} + +bool HandleMapFilterCommand(const char* args) { + if (!args || !args[0] || CommandMatch(args, "status", nullptr)) { + RefreshMapOverlay(); + PrintMapStatus(); + return true; + } + + if (CommandMatch(args, "help", nullptr)) { + Chat("MapFilter: NPC|PC|Corpse|Target|TargetLine|NormalLabels|NPCConColor|Ground|Vector|Named|XTargets|XTargetLabels on/off"); + Chat("MapFilter: Custom , Hide , TargetRadius|CastRadius|SpellRadius "); + return true; + } + + const char* sub_args = nullptr; + if (CommandMatch(args, "NPC", &sub_args)) { + bool enabled = ParseOnOff(sub_args, g_config.map_show_npcs, !g_config.map_show_npcs); + SetMapBool(g_config.map_show_npcs, "ShowNPCs", enabled, true); + Chat("MapFilter NPC is now %s.", enabled ? "on" : "off"); + return true; + } + + if (CommandMatch(args, "PC", &sub_args) || CommandMatch(args, "Player", &sub_args) || + CommandMatch(args, "Players", &sub_args)) { + bool enabled = ParseOnOff(sub_args, g_config.map_show_players, !g_config.map_show_players); + SetMapBool(g_config.map_show_players, "ShowPlayers", enabled, true); + Chat("MapFilter PC is now %s.", enabled ? "on" : "off"); + return true; + } + + if (CommandMatch(args, "Corpse", &sub_args) || CommandMatch(args, "Corpses", &sub_args)) { + bool enabled = ParseOnOff(sub_args, g_config.map_show_corpses, !g_config.map_show_corpses); + SetMapBool(g_config.map_show_corpses, "ShowCorpses", enabled, true); + Chat("MapFilter Corpse is now %s.", enabled ? "on" : "off"); + return true; + } + + if (CommandMatch(args, "Target", &sub_args)) { + bool enabled = ParseOnOff(sub_args, g_config.map_show_target, !g_config.map_show_target); + SetMapBool(g_config.map_show_target, "ShowTarget", enabled, true); + Chat("MapFilter Target is now %s.", enabled ? "on" : "off"); + return true; + } + + if (CommandMatch(args, "TargetLine", &sub_args)) { + bool enabled = ParseOnOff(sub_args, g_config.map_target_line, !g_config.map_target_line); + SetMapBool(g_config.map_target_line, "TargetLine", enabled, true); + Chat("MapFilter TargetLine is now %s.", enabled ? "on" : "off"); + return true; + } + + if (CommandMatch(args, "NormalLabels", &sub_args) || CommandMatch(args, "Labels", &sub_args)) { + bool enabled = ParseOnOff(sub_args, g_config.map_chain_eq_labels, !g_config.map_chain_eq_labels); + SetMapBool(g_config.map_chain_eq_labels, "ChainEQLabels", enabled, true); + Chat("MapFilter NormalLabels is now %s.", enabled ? "on" : "off"); + return true; + } + + if (CommandMatch(args, "NPCConColor", &sub_args) || CommandMatch(args, "ConColor", &sub_args)) { + bool enabled = ParseOnOff(sub_args, g_config.map_use_con_color, !g_config.map_use_con_color); + SetMapBool(g_config.map_use_con_color, "UseConColor", enabled, true); + Chat("MapFilter NPCConColor is now %s.", enabled ? "on" : "off"); + return true; + } + + if (CommandMatch(args, "Ground", &sub_args) || CommandMatch(args, "GroundItems", &sub_args)) { + bool enabled = ParseOnOff(sub_args, g_config.map_show_ground, !g_config.map_show_ground); + SetMapBool(g_config.map_show_ground, "Ground", enabled, true); + Chat("MapFilter Ground is now %s.", enabled ? "on" : "off"); + return true; + } + + if (CommandMatch(args, "Vector", &sub_args) || CommandMatch(args, "Vectors", &sub_args)) { + bool enabled = ParseOnOff(sub_args, g_config.map_show_vectors, !g_config.map_show_vectors); + SetMapBool(g_config.map_show_vectors, "Vector", enabled, true); + Chat("MapFilter Vector is now %s.", enabled ? "on" : "off"); + return true; + } + + if (CommandMatch(args, "Named", &sub_args)) { + bool enabled = ParseOnOff(sub_args, g_config.map_named_only, !g_config.map_named_only); + SetMapBool(g_config.map_named_only, "Named", enabled, true); + Chat("MapFilter Named is now %s.", enabled ? "on" : "off"); + return true; + } + + if (CommandMatch(args, "XTargets", &sub_args) || CommandMatch(args, "XTarget", &sub_args)) { + bool enabled = ParseOnOff(sub_args, g_config.map_show_xtargets, !g_config.map_show_xtargets); + SetMapBool(g_config.map_show_xtargets, "XTargets", enabled, true); + Chat("MapFilter XTargets is now %s.", enabled ? "on" : "off"); + return true; + } + + if (CommandMatch(args, "XTargetLabels", &sub_args) || CommandMatch(args, "XTLabels", &sub_args)) { + bool enabled = ParseOnOff(sub_args, g_config.map_xtarget_labels, !g_config.map_xtarget_labels); + SetMapBool(g_config.map_xtarget_labels, "XTargetLabels", enabled, true); + Chat("MapFilter XTargetLabels is now %s.", enabled ? "on" : "off"); + return true; + } + + if (CommandMatch(args, "TargetRadius", &sub_args)) { + float value = 0.0f; + if (!TryParseFloat(TrimCopy(sub_args), value)) { + Chat("MapFilter TargetRadius is %.1f. Usage: /mapfilter TargetRadius ", g_config.map_target_radius); + return true; + } + SetMapFloat(g_config.map_target_radius, "TargetRadius", value); + Chat("MapFilter TargetRadius set to %.1f.", g_config.map_target_radius); + return true; + } + + if (CommandMatch(args, "CastRadius", &sub_args)) { + float value = 0.0f; + if (!TryParseFloat(TrimCopy(sub_args), value)) { + Chat("MapFilter CastRadius is %.1f. Usage: /mapfilter CastRadius ", g_config.map_cast_radius); + return true; + } + SetMapFloat(g_config.map_cast_radius, "CastRadius", value); + Chat("MapFilter CastRadius set to %.1f.", g_config.map_cast_radius); + return true; + } + + if (CommandMatch(args, "SpellRadius", &sub_args)) { + float value = 0.0f; + if (!TryParseFloat(TrimCopy(sub_args), value)) { + Chat("MapFilter SpellRadius is %.1f. Usage: /mapfilter SpellRadius ", g_config.map_spell_radius); + return true; + } + SetMapFloat(g_config.map_spell_radius, "SpellRadius", value); + Chat("MapFilter SpellRadius set to %.1f.", g_config.map_spell_radius); + return true; + } + + if (CommandMatch(args, "Custom", &sub_args) || CommandMatch(args, "Filter", &sub_args)) { + return HandleTextFilterCommand(sub_args, g_config.map_name_filter, "NameFilter", "name"); + } + + if (CommandMatch(args, "Hide", &sub_args)) { + return HandleTextFilterCommand(sub_args, g_config.map_hide_filter, "HideFilter", "hide"); + } + + Chat("MapFilter supported: NPC, PC, Corpse, Target, TargetLine, NormalLabels, NPCConColor, Ground, Vector, Named, XTargets, Custom, Hide."); + return true; +} + +bool HandleNativeMapCommand(const char* line) { + const char* args = nullptr; + if (CommandMatch(line, "/mapfilter", &args)) { + return HandleMapFilterCommand(args); + } + + if (!CommandMatch(line, "/nimap", &args) && + !CommandMatch(line, "/nativeinterfacemap", &args)) { + return false; + } + + if (!args || !args[0] || CommandMatch(args, "status", nullptr)) { + RefreshMapOverlay(); + PrintMapStatus(); + return true; + } + + if (CommandMatch(args, "help", nullptr)) { + Chat("NativeMap: on|off|status|reload|npcs|players|corpses|con|labels|showtarget|targetline|ground|vector|named|target"); + Chat("NativeMap commands: /nimap or /nativeinterfacemap."); + Chat("Map tools: /mapfilter help, /mapshow , /maphide , /highlight , /maploc add
    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

    #~&K*V$JS)hQiDJxKf5X+1r5aj%AP7e5;<%HdnM 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 z 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 Deh=cE delta 262942 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"IW_Class"); + if (class_label) { + CXStr value(class_text.c_str()); + class_label->SetWindowTextA(value); + } + } + __except (EXCEPTION_EXECUTE_HANDLER) { + } +} - if (gNativeMulticlassShowCasterUiPulses > 0) { - --gNativeMulticlassShowCasterUiPulses; - NativeMulticlassShowSpellGemWindow(); +static void NativeMulticlassMaintainPresentationUI() +{ + if (!gNativeMulticlassState.has_profile) { + return; + } + + NativeMulticlassPatchInventoryClassLabel(); + + if (NativeMulticlassPresentationUsesMana(gNativeMulticlassState.presentation) && pPlayerWnd) { + NativeMulticlassPatchLocalVitals(); + NativeMulticlassShowPlayerManaPiece("Player_Mana"); + NativeMulticlassShowPlayerManaPiece("PlayerMana"); + NativeMulticlassShowPlayerManaPiece("Player_ManaLabel"); + NativeMulticlassShowPlayerManaPiece("ManaLabel"); + NativeMulticlassShowPlayerManaPiece("Player_ManaPercLabel"); + NativeMulticlassShowPlayerManaPiece("ManPercLabel"); + + if (gNativeMulticlassShowCasterUiPulses > 0) { + --gNativeMulticlassShowCasterUiPulses; + NativeMulticlassShowSpellGemWindow(); + } } } From ca50d3eca08fcb867c9519642cce5b2d0d30ffbd Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Thu, 4 Jun 2026 22:23:27 -0700 Subject: [PATCH 142/194] Checkpoint all features feature gates --- common/ruletypes.h | 16 ++++ docs/features-all.md | 31 ++++++- .../quests/tutorialb/900903.pl | 6 ++ .../all-features/quests/global/900901.lua | 10 +++ .../all-features/quests/global/900902.lua | 10 +++ .../all-features/quests/global/900904.lua | 10 +++ .../all-features/quests/global/900905.lua | 16 ++++ .../all-features/quests/global/900906.lua | 16 ++++ .../quests/global/global_player.lua | 13 +++ .../quests/global/items/199091.lua | 10 +++ .../all-features/quests/tutorialb/900905.lua | 16 ++++ .../all-features/quests/tutorialb/900906.lua | 16 ++++ .../all-features/quests/tutorialb/zone.lua | 13 +++ zone/CMakeLists.txt | 1 + zone/achievement_manager.cpp | 21 +++-- zone/autoloot_manager.cpp | 86 +++++++++++++++++++ zone/client.cpp | 5 ++ zone/command.cpp | 1 + zone/command.h | 1 + zone/gm_commands/customfeatures.cpp | 36 ++++++++ zone/gm_commands/hpfix.cpp | 7 ++ zone/gm_commands/itemrarity.cpp | 6 ++ zone/gm_commands/itemscore.cpp | 6 ++ zone/gm_commands/liveitem.cpp | 15 ++++ zone/gm_commands/livespell.cpp | 30 +++++++ zone/inventory.cpp | 5 ++ zone/item_rarity_manager.cpp | 17 ++++ zone/multiclass_manager.cpp | 71 ++++++++++++--- 28 files changed, 473 insertions(+), 18 deletions(-) create mode 100644 zone/gm_commands/customfeatures.cpp diff --git a/common/ruletypes.h b/common/ruletypes.h index 5ad9fdb9de..30e2a84435 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -37,6 +37,22 @@ +RULE_CATEGORY(CustomFeatures) +RULE_BOOL(CustomFeatures, MulticlassEnabled, true, "Enables the custom Multiclass trio feature, including trio profiles, secondary class permissions, native UI sync, resonance bonuses, and multi-pet behavior.") +RULE_BOOL(CustomFeatures, AchievementsEnabled, true, "Enables the custom Achievements feature, including achievement progress processing, commands, and native achievement window sync.") +RULE_BOOL(CustomFeatures, AutoLootEnabled, true, "Enables the custom source-backed AutoLoot, LootFilter, AutoSell, Need/Greed, and native AutoLoot window behavior.") +RULE_BOOL(CustomFeatures, GearScoreEnabled, true, "Enables the custom item power/gearscore transport and #itemscore tools.") +RULE_BOOL(CustomFeatures, LiveItemsEnabled, true, "Enables the custom Live Items and Item Forge testing commands and native Item Forge behavior.") +RULE_BOOL(CustomFeatures, LiveSpellsEnabled, true, "Enables the custom Live Spells and Spell Forge commands, server spell patching, and native Spell Forge sync.") +RULE_BOOL(CustomFeatures, ItemRarityEnabled, true, "Enables the custom item rarity tools and native rarity transport.") +RULE_BOOL(CustomFeatures, HpFixEnabled, true, "Enables the native high-HP client display helper and #hpfix tools.") +RULE_BOOL(CustomFeatures, AiDialogueEnabled, true, "Enables the custom AI dialogue feature payload and related scripted NPC behavior.") +RULE_BOOL(CustomFeatures, TradeskillsEnabled, true, "Enables custom native tradeskill feature behavior when wired by the server and client payload.") +RULE_BOOL(CustomFeatures, AugsInAugsEnabled, true, "Enables custom Augs-in-Augs feature behavior when wired by the server and client payload.") +RULE_BOOL(CustomFeatures, DynamicQuestsEnabled, true, "Enables custom Dynamic Quests feature behavior when wired by the server and client payload.") +RULE_BOOL(CustomFeatures, MqInterfaceEnabled, true, "Enables bundled MQ-derived native client interface helpers such as map and item display when shipped in the all-features DLL.") +RULE_CATEGORY_END() + RULE_CATEGORY(Character) RULE_INT(Character, MaxLevel, 65, "Sets the highest level for players that can be reached through experience") RULE_BOOL(Character, PerCharacterQglobalMaxLevel, false, "Check for qglobal 'CharMaxLevel' character qglobal (Type 5, \"\"), if player tries to level beyond that point, it will not go beyond that level") diff --git a/docs/features-all.md b/docs/features-all.md index e50dc95d99..77ada1279b 100644 --- a/docs/features-all.md +++ b/docs/features-all.md @@ -1,6 +1,7 @@ # All Features Bundle -This branch combines the standalone feature branches on top of a clean EQEmu base: +This branch is the maintained source of truth for the combined custom EQEmu +distribution on top of a clean EQEmu base: - AutoLoot - Live Items / Item Forge @@ -18,7 +19,33 @@ This branch combines the standalone feature branches on top of a clean EQEmu bas ## Branch Shape -The bundle keeps the feature commits layered instead of using the dirty integration lab as source of truth. This gives operators one branch to grab when they want every system, while preserving the individual feature branches for piecemeal installs. +The all-features checkout now owns the maintained combined package. Standalone feature +projects are useful as historical references or extraction targets, but normal feature +fixes for the combined server should land here and be protected by runtime feature +gates instead of maintaining separate live implementations. + +Feature gates live in the `CustomFeatures` rule category: + +- `CustomFeatures:MulticlassEnabled` +- `CustomFeatures:AchievementsEnabled` +- `CustomFeatures:AutoLootEnabled` +- `CustomFeatures:GearScoreEnabled` +- `CustomFeatures:LiveItemsEnabled` +- `CustomFeatures:LiveSpellsEnabled` +- `CustomFeatures:ItemRarityEnabled` +- `CustomFeatures:HpFixEnabled` +- `CustomFeatures:AiDialogueEnabled` +- `CustomFeatures:TradeskillsEnabled` +- `CustomFeatures:AugsInAugsEnabled` +- `CustomFeatures:DynamicQuestsEnabled` +- `CustomFeatures:MqInterfaceEnabled` + +Use `#customfeatures` in-game as a GM admin to print the current all-features gate +state. When adding or changing feature behavior, gate it at server authority +boundaries: commands, passive event processors, native transport senders, quest entry +points, and item/spell mutation paths. The all-features client patcher may still ship +all XML and native DLL payloads together; disabled server rules should prevent the +feature from doing real work. ## Database diff --git a/features/ai-npc-response/quests/tutorialb/900903.pl b/features/ai-npc-response/quests/tutorialb/900903.pl index fe4f83a175..7fa1b98ac7 100644 --- a/features/ai-npc-response/quests/tutorialb/900903.pl +++ b/features/ai-npc-response/quests/tutorialb/900903.pl @@ -27,6 +27,12 @@ BEGIN my %pending_ai_jobs = (); sub EVENT_SAY { + my $enabled = quest::get_rule("CustomFeatures:AiDialogueEnabled"); + if (defined $enabled && $enabled =~ /^(0|false)$/i) { + quest::say("The old records are quiet right now. Try me again another time."); + return; + } + my $player_message = defined $text ? $text : ""; $player_message =~ s/^\s+|\s+$//g; return if $player_message eq ""; diff --git a/features/all-features/quests/global/900901.lua b/features/all-features/quests/global/900901.lua index 5549d993ad..99038cc357 100644 --- a/features/all-features/quests/global/900901.lua +++ b/features/all-features/quests/global/900901.lua @@ -1,5 +1,10 @@ local TEST_LOOT_CACHE_ID = 199091 +local function live_items_enabled() + local value = eq.get_rule("CustomFeatures:LiveItemsEnabled") + return value == nil or value == "" or value == "true" or value == "1" +end + local forge_payload = table.concat({ "LIVEITEM|ui|open", "types=weapon,armor,jewelry,charm,shield,augment", @@ -12,6 +17,11 @@ local forge_payload = table.concat({ }, "|") function event_say(e) + if not live_items_enabled() then + e.self:QuestSay(e.other, "The Item Forge is disabled right now.") + return + end + if e.message:findi("hail") then e.self:QuestSay( e.other, diff --git a/features/all-features/quests/global/900902.lua b/features/all-features/quests/global/900902.lua index 1c5d6237a1..fb92886003 100644 --- a/features/all-features/quests/global/900902.lua +++ b/features/all-features/quests/global/900902.lua @@ -6,6 +6,11 @@ local DEFAULT_NAME = "Bloodbound Augment" local ALL_EQUIPMENT_SLOTS = 8388607 local ALL_AUGMENT_TYPES = 2147483647 +local function live_items_enabled() + local value = eq.get_rule("CustomFeatures:LiveItemsEnabled") + return value == nil or value == "" or value == "true" or value == "1" +end + local upgrade_order = { "hp", "mana", "endur", "ac", "str", "sta", "agi", "dex", "int", "wis", "cha", @@ -375,6 +380,11 @@ local function confirm_build(e) end function event_say(e) + if not live_items_enabled() then + e.self:QuestSay(e.other, "Shardwork is disabled right now.") + return + end + local raw_message = e.message or "" local message = normalize(raw_message) diff --git a/features/all-features/quests/global/900904.lua b/features/all-features/quests/global/900904.lua index caaf8ab40d..f37b61a099 100644 --- a/features/all-features/quests/global/900904.lua +++ b/features/all-features/quests/global/900904.lua @@ -17,6 +17,11 @@ local classes = { [16] = { name = "Berserker", base_item_id = 50515, class_mask = 32768, itemtype = 1, slots = 8192, damage = 38, delay = 40 }, } +local function live_items_enabled() + local value = eq.get_rule("CustomFeatures:LiveItemsEnabled") + return value == nil or value == "" or value == "true" or value == "1" +end + local initial_stats = { hp = 50, mana = 50, @@ -113,6 +118,11 @@ function event_say_heirloom(e) end function event_say(e) + if not live_items_enabled() then + e.self:Say("Heirloom testing is disabled right now.") + return + end + local message = (e.message or ""):lower() if message:find("heirloom") then diff --git a/features/all-features/quests/global/900905.lua b/features/all-features/quests/global/900905.lua index c9a631e606..1e869b50d0 100644 --- a/features/all-features/quests/global/900905.lua +++ b/features/all-features/quests/global/900905.lua @@ -3,6 +3,11 @@ local MAX_TRADE_SLOTS = 4 local MAX_SOURCE_AUGMENTS = MAX_TRADE_SLOTS - 1 local MIN_SOURCE_AUGMENTS = 1 +local function live_items_enabled() + local value = eq.get_rule("CustomFeatures:LiveItemsEnabled") + return value == nil or value == "" or value == "true" or value == "1" +end + local stat_fields = { { key = "ac", label = "AC", get = function(item) return item:AC() end }, { key = "hp", label = "HP", get = function(item) return item:HP() end }, @@ -182,6 +187,11 @@ local function fuse_augments(sources, source_ids) end function event_say(e) + if not live_items_enabled() then + e.self:Say("Augment fusion is disabled right now.") + return + end + if e.message:findi("catalyst") then e.other:SummonItem(CATALYST_ITEM_ID, 1) e.self:Say("An Augment Catalyst is on your cursor. Hand it back to me with one to three augment items and no coins when you are ready to test fusion.") @@ -201,6 +211,12 @@ end function event_trade(e) local item_lib = require("items") + if not live_items_enabled() then + e.self:Say("Augment fusion is disabled right now.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + local items = trade_items(e.trade) if #items < 2 or #items > MAX_TRADE_SLOTS or e.trade.platinum > 0 or e.trade.gold > 0 or e.trade.silver > 0 or e.trade.copper > 0 then diff --git a/features/all-features/quests/global/900906.lua b/features/all-features/quests/global/900906.lua index 4f146eb816..d5abc4f8c6 100644 --- a/features/all-features/quests/global/900906.lua +++ b/features/all-features/quests/global/900906.lua @@ -1,5 +1,10 @@ local UPGRADE_AMOUNT = 10 +local function live_items_enabled() + local value = eq.get_rule("CustomFeatures:LiveItemsEnabled") + return value == nil or value == "" or value == "true" or value == "1" +end + local stat_fields = { { key = "hp", label = "HP", cap = 5000, get = function(item) return item:HP() end }, { key = "mana", label = "Mana", cap = 5000, get = function(item) return item:Mana() end }, @@ -152,6 +157,11 @@ local function trade_items(trade) end function event_say(e) + if not live_items_enabled() then + e.self:Say("Instance upgrades are disabled right now.") + return + end + if not e.message:findi("hail") then return end @@ -165,6 +175,12 @@ end function event_trade(e) local item_lib = require("items") + if not live_items_enabled() then + e.self:Say("Instance upgrades are disabled right now.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + local items = trade_items(e.trade) if #items ~= 1 or e.trade.platinum > 0 or e.trade.gold > 0 or e.trade.silver > 0 or e.trade.copper > 0 then diff --git a/features/all-features/quests/global/global_player.lua b/features/all-features/quests/global/global_player.lua index b409cdd649..f4ea9cfd3e 100644 --- a/features/all-features/quests/global/global_player.lua +++ b/features/all-features/quests/global/global_player.lua @@ -11,6 +11,11 @@ local commands = { liveitemdebug = true, } +local function live_items_enabled() + local value = eq.get_rule("CustomFeatures:LiveItemsEnabled") + return value == nil or value == "" or value == "true" or value == "1" +end + local function is_handled_command(command) return commands[string.lower(tostring(command or ""))] == true end @@ -245,6 +250,10 @@ function event_command(e) return 0 end + if not live_items_enabled() then + return 0 + end + local command = string.lower(tostring(e.command or "")) if command == "heirloomdebug" or command == "evolvingdebug" or command == "liveitemdebug" then debug_message(e.self, "Manual heirloom debug command received.") @@ -288,6 +297,10 @@ function event_command(e) end function event_level_up(e) + if not live_items_enabled() then + return + end + local client = e.self local levels_gained = math.max(1, number(e.levels_gained, 1)) local grown = 0 diff --git a/features/all-features/quests/global/items/199091.lua b/features/all-features/quests/global/items/199091.lua index df1b5c6cf6..87cae41378 100644 --- a/features/all-features/quests/global/items/199091.lua +++ b/features/all-features/quests/global/items/199091.lua @@ -1,5 +1,10 @@ local CACHE_ITEM_ID = 199091 +local function live_items_enabled() + local value = eq.get_rule("CustomFeatures:LiveItemsEnabled") + return value == nil or value == "" or value == "true" or value == "1" +end + local templates = { { id = 6002, type = "Weapon", name = "Staff", damage = true }, { id = 6919, type = "Weapon", name = "Forlorn Bow", damage = true }, @@ -200,6 +205,11 @@ local function create_random_item(e) end function event_item_click(e) + if not live_items_enabled() then + e.owner:Message(13, "Live Items test caches are disabled right now.") + return + end + if e.self:GetID() ~= CACHE_ITEM_ID then return end diff --git a/features/all-features/quests/tutorialb/900905.lua b/features/all-features/quests/tutorialb/900905.lua index c9a631e606..1e869b50d0 100644 --- a/features/all-features/quests/tutorialb/900905.lua +++ b/features/all-features/quests/tutorialb/900905.lua @@ -3,6 +3,11 @@ local MAX_TRADE_SLOTS = 4 local MAX_SOURCE_AUGMENTS = MAX_TRADE_SLOTS - 1 local MIN_SOURCE_AUGMENTS = 1 +local function live_items_enabled() + local value = eq.get_rule("CustomFeatures:LiveItemsEnabled") + return value == nil or value == "" or value == "true" or value == "1" +end + local stat_fields = { { key = "ac", label = "AC", get = function(item) return item:AC() end }, { key = "hp", label = "HP", get = function(item) return item:HP() end }, @@ -182,6 +187,11 @@ local function fuse_augments(sources, source_ids) end function event_say(e) + if not live_items_enabled() then + e.self:Say("Augment fusion is disabled right now.") + return + end + if e.message:findi("catalyst") then e.other:SummonItem(CATALYST_ITEM_ID, 1) e.self:Say("An Augment Catalyst is on your cursor. Hand it back to me with one to three augment items and no coins when you are ready to test fusion.") @@ -201,6 +211,12 @@ end function event_trade(e) local item_lib = require("items") + if not live_items_enabled() then + e.self:Say("Augment fusion is disabled right now.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + local items = trade_items(e.trade) if #items < 2 or #items > MAX_TRADE_SLOTS or e.trade.platinum > 0 or e.trade.gold > 0 or e.trade.silver > 0 or e.trade.copper > 0 then diff --git a/features/all-features/quests/tutorialb/900906.lua b/features/all-features/quests/tutorialb/900906.lua index 4f146eb816..d5abc4f8c6 100644 --- a/features/all-features/quests/tutorialb/900906.lua +++ b/features/all-features/quests/tutorialb/900906.lua @@ -1,5 +1,10 @@ local UPGRADE_AMOUNT = 10 +local function live_items_enabled() + local value = eq.get_rule("CustomFeatures:LiveItemsEnabled") + return value == nil or value == "" or value == "true" or value == "1" +end + local stat_fields = { { key = "hp", label = "HP", cap = 5000, get = function(item) return item:HP() end }, { key = "mana", label = "Mana", cap = 5000, get = function(item) return item:Mana() end }, @@ -152,6 +157,11 @@ local function trade_items(trade) end function event_say(e) + if not live_items_enabled() then + e.self:Say("Instance upgrades are disabled right now.") + return + end + if not e.message:findi("hail") then return end @@ -165,6 +175,12 @@ end function event_trade(e) local item_lib = require("items") + if not live_items_enabled() then + e.self:Say("Instance upgrades are disabled right now.") + item_lib.return_items(e.self, e.other, e.trade) + return + end + local items = trade_items(e.trade) if #items ~= 1 or e.trade.platinum > 0 or e.trade.gold > 0 or e.trade.silver > 0 or e.trade.copper > 0 then diff --git a/features/all-features/quests/tutorialb/zone.lua b/features/all-features/quests/tutorialb/zone.lua index 0b6be6ce26..ee3526e850 100644 --- a/features/all-features/quests/tutorialb/zone.lua +++ b/features/all-features/quests/tutorialb/zone.lua @@ -9,6 +9,11 @@ local skipped_npcs = { local seed_marker = "live_items_tutorialb_spawn_loot_seeded" +local function live_items_enabled() + local value = eq.get_rule("CustomFeatures:LiveItemsEnabled") + return value == nil or value == "" or value == "true" or value == "1" +end + local templates = { { id = 6002, type = "Weapon", name = "Staff", damage = true }, { id = 6919, type = "Weapon", name = "Forlorn Bow", damage = true }, @@ -233,9 +238,17 @@ local function seed_existing_npcs() end function event_spawn_zone(e) + if not live_items_enabled() then + return + end + seed_npc(e.other) end function event_enter_zone(e) + if not live_items_enabled() then + return + end + seed_existing_npcs() end diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index ab7464a0c4..0712e442c7 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -397,6 +397,7 @@ set(gm_command_sources gm_commands/corpse.cpp gm_commands/corpsefix.cpp gm_commands/countitem.cpp + gm_commands/customfeatures.cpp gm_commands/damage.cpp gm_commands/databuckets.cpp gm_commands/dbspawn2.cpp diff --git a/zone/achievement_manager.cpp b/zone/achievement_manager.cpp index e7f5bc9831..800b24d452 100644 --- a/zone/achievement_manager.cpp +++ b/zone/achievement_manager.cpp @@ -9,6 +9,7 @@ */ #include "achievement_manager.h" +#include "common/rulesys.h" #include "common/seperator.h" #include "common/skills.h" #include "common/strings.h" @@ -24,6 +25,11 @@ AchievementManager achievement_manager; namespace { + bool AchievementsEnabled() + { + return RuleB(CustomFeatures, AchievementsEnabled); + } + uint32 ToUInt(const char *value) { return value ? Strings::ToUnsignedInt(value) : 0; @@ -70,6 +76,11 @@ void AchievementManager::HandleCommand(Client *client, const Seperator *sep) return; } + if (!AchievementsEnabled()) { + client->Message(Chat::White, "Achievements are disabled on this server."); + return; + } + if (sep->argnum < 1) { SendNativeWindow(client); return; @@ -187,7 +198,7 @@ void AchievementManager::HandleCommand(Client *client, const Seperator *sep) void AchievementManager::ProcessLevel(Client *client) { - if (!client) { + if (!client || !AchievementsEnabled()) { return; } @@ -219,7 +230,7 @@ void AchievementManager::ProcessLevel(Client *client) void AchievementManager::ProcessZoneVisit(Client *client) { - if (!client || !zone) { + if (!client || !zone || !AchievementsEnabled()) { return; } @@ -236,7 +247,7 @@ void AchievementManager::ProcessZoneVisit(Client *client) void AchievementManager::ProcessTaskComplete(Client *client, uint32 task_id) { - if (!client || !task_id) { + if (!client || !task_id || !AchievementsEnabled()) { return; } @@ -253,7 +264,7 @@ void AchievementManager::ProcessTaskComplete(Client *client, uint32 task_id) void AchievementManager::ProcessSkill(Client *client, uint32 skill_id, uint32 value) { - if (!client) { + if (!client || !AchievementsEnabled()) { return; } @@ -270,7 +281,7 @@ void AchievementManager::ProcessSkill(Client *client, uint32 skill_id, uint32 va void AchievementManager::ProcessKill(Client *client, NPC *npc) { - if (!client || !npc || !zone) { + if (!client || !npc || !zone || !AchievementsEnabled()) { return; } diff --git a/zone/autoloot_manager.cpp b/zone/autoloot_manager.cpp index 01771fd282..be48289606 100644 --- a/zone/autoloot_manager.cpp +++ b/zone/autoloot_manager.cpp @@ -13,6 +13,7 @@ #include "common/emu_constants.h" #include "common/inventory_profile.h" #include "common/item_instance.h" +#include "common/rulesys.h" #include "common/say_link.h" #include "common/seperator.h" #include "common/strings.h" @@ -40,6 +41,24 @@ namespace { constexpr uint32 kNeedGreedSeconds = 45; constexpr uint32 kAutosellSessionSeconds = 60; + bool AutoLootEnabled() + { + return RuleB(CustomFeatures, AutoLootEnabled); + } + + bool RequireAutoLootEnabled(Client *client) + { + if (AutoLootEnabled()) { + return true; + } + + if (client) { + client->Message(Chat::White, "AutoLoot is disabled on this server."); + } + + return false; + } + bool IsValidFilterMode(const std::string &mode) { return Strings::EqualFold(mode, "both") || @@ -197,6 +216,13 @@ namespace { void AutoLootManager::Process() { + if (!AutoLootEnabled()) { + m_pending_votes.clear(); + m_autosell_sessions.clear(); + m_loot_entries.clear(); + return; + } + const time_t now = std::time(nullptr); if (now == m_last_process) { return; @@ -566,6 +592,10 @@ Client *AutoLootManager::DetermineRecipient(Client *resolved_client, Corpse *cor void AutoLootManager::ProcessCorpseDeath(Corpse *corpse, Mob *killer) { + if (!AutoLootEnabled()) { + return; + } + if (!corpse || !corpse->IsNPCCorpse()) { return; } @@ -580,6 +610,10 @@ void AutoLootManager::ProcessCorpseDeath(Corpse *corpse, Mob *killer) void AutoLootManager::ProcessNearby(Client *client, float radius) { + if (!RequireAutoLootEnabled(client)) { + return; + } + if (!client) { return; } @@ -615,6 +649,10 @@ void AutoLootManager::ProcessNearby(Client *client, float radius) void AutoLootManager::ProcessCorpse(Corpse *corpse, Client *resolved_client, bool nearby) { + if (!AutoLootEnabled()) { + return; + } + if (!corpse || !resolved_client || !corpse->IsNPCCorpse() || corpse->IsBeingLooted()) { return; } @@ -629,6 +667,10 @@ void AutoLootManager::ProcessCorpse(Corpse *corpse, Client *resolved_client, boo bool AutoLootManager::QueueCorpseEntries(Corpse *corpse, Client *resolved_client, bool nearby) { + if (!AutoLootEnabled()) { + return false; + } + if (!corpse || !resolved_client || !corpse->IsNPCCorpse() || corpse->IsBeingLooted()) { return false; } @@ -787,6 +829,10 @@ void AutoLootManager::PruneLootEntries() void AutoLootManager::SendNativeSnapshot(Client *client) { + if (!AutoLootEnabled()) { + return; + } + if (!client) { return; } @@ -827,12 +873,20 @@ void AutoLootManager::SendNativeSnapshot(Client *client) void AutoLootManager::SendNativeUpdate(Client *client) { + if (!AutoLootEnabled()) { + return; + } + SendNativeStatus(client); SendNativeSnapshot(client); } void AutoLootManager::RefreshQueuedRulesForClient(Client *client) { + if (!AutoLootEnabled()) { + return; + } + if (!client) { return; } @@ -858,6 +912,10 @@ void AutoLootManager::RefreshQueuedRulesForClient(Client *client) void AutoLootManager::SendNativeFilterUpdate(Client *client) { + if (!AutoLootEnabled()) { + return; + } + RefreshQueuedRulesForClient(client); SendNativeUpdate(client); SendNativeFilters(client, "both"); @@ -865,6 +923,10 @@ void AutoLootManager::SendNativeFilterUpdate(Client *client) void AutoLootManager::HandleLootAction(Client *client, const Seperator *sep) { + if (!RequireAutoLootEnabled(client)) { + return; + } + if (!client || !sep || sep->argnum < 3 || !sep->IsNumber(2)) { client->Message(Chat::White, "Usage: #autoloot action [Entry ID] [loot|leave|never|alwaysloot]"); return; @@ -939,6 +1001,10 @@ void AutoLootManager::HandleLootAction(Client *client, const Seperator *sep) void AutoLootManager::HandlePersonalLootCommand(Client *client, const Seperator *sep) { + if (!RequireAutoLootEnabled(client)) { + return; + } + if (!client || !sep || sep->argnum < 2) { client->Message(Chat::White, "Usage: #autoloot personal [lootall|leaveall]"); return; @@ -1516,6 +1582,10 @@ void AutoLootManager::CancelAutosell(Client *client) void AutoLootManager::HandleAutolootCommand(Client *client, const Seperator *sep) { + if (!RequireAutoLootEnabled(client)) { + return; + } + if (!client || !sep) { return; } @@ -1734,6 +1804,10 @@ void AutoLootManager::HandleAutolootCommand(Client *client, const Seperator *sep void AutoLootManager::HandleLootFilterCommand(Client *client, const Seperator *sep) { + if (!RequireAutoLootEnabled(client)) { + return; + } + if (!client || !sep) { return; } @@ -1873,6 +1947,10 @@ void AutoLootManager::HandleLootFilterCommand(Client *client, const Seperator *s void AutoLootManager::HandleAutosellCommand(Client *client, const Seperator *sep) { + if (!RequireAutoLootEnabled(client)) { + return; + } + if (!client || !sep) { return; } @@ -1951,6 +2029,10 @@ void AutoLootManager::HandleAutosellCommand(Client *client, const Seperator *sep void AutoLootManager::HandleNeedGreedCommand(Client *client, const Seperator *sep) { + if (!RequireAutoLootEnabled(client)) { + return; + } + if (!client || !sep || sep->argnum < 3 || strcasecmp(sep->arg[1], "vote") || !sep->IsNumber(2)) { client->Message(Chat::White, "Usage: #needgreed vote [Vote ID] [need|greed|pass]"); return; @@ -1961,6 +2043,10 @@ void AutoLootManager::HandleNeedGreedCommand(Client *client, const Seperator *se void AutoLootManager::ShowWindow(Client *client) { + if (!RequireAutoLootEnabled(client)) { + return; + } + if (!client) { return; } diff --git a/zone/client.cpp b/zone/client.cpp index aa7b93c0c0..2a0799ddae 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -9263,6 +9263,11 @@ void Client::SendHPUpdateMarquee(){ void Client::SendNativeHpFixUpdate(bool force) { + if (!RuleB(CustomFeatures, HpFixEnabled)) { + native_hpfix_ready_ = false; + return; + } + if (!native_hpfix_ready_) { return; } diff --git a/zone/command.cpp b/zone/command.cpp index 4dd26e0887..9a00b24d4e 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -146,6 +146,7 @@ int command_init(void) command_add("evolve", "Evolving Item manipulation commands. Use argument help for more info.", AccountStatus::Steward, command_evolvingitems) || command_add("faction", "[Find (criteria | all ) | Review (criteria | all) | Reset (id)] - Resets Player's Faction", AccountStatus::QuestTroupe, command_faction) || command_add("factionassociation", "[factionid] [amount] - triggers a faction hits via association", AccountStatus::GMLeadAdmin, command_faction_association) || + command_add("customfeatures", "- Show enabled/disabled custom all-features rule gates", AccountStatus::GMAdmin, command_customfeatures) || command_add("feature", "Change your or your target's feature's temporarily", AccountStatus::QuestTroupe, command_feature) || command_add("size", "Change your targets size (alias of #feature size)", AccountStatus::QuestTroupe, command_feature) || command_add("find", "Search command used to find various things", AccountStatus::Guide, command_find) || diff --git a/zone/command.h b/zone/command.h index edb202882f..f5e3bd996b 100644 --- a/zone/command.h +++ b/zone/command.h @@ -80,6 +80,7 @@ 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_countitem(Client *c, const Seperator *sep); +void command_customfeatures(Client *c, const Seperator *sep); void command_damage(Client *c, const Seperator *sep); void command_databuckets(Client *c, const Seperator *sep); void command_dbspawn2(Client *c, const Seperator *sep); diff --git a/zone/gm_commands/customfeatures.cpp b/zone/gm_commands/customfeatures.cpp new file mode 100644 index 0000000000..d4030a0f74 --- /dev/null +++ b/zone/gm_commands/customfeatures.cpp @@ -0,0 +1,36 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + 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; either version 3 of the License, or + (at your option) any later version. +*/ +#include "common/rulesys.h" +#include "zone/client.h" + +namespace { + void SendFeatureStatus(Client *c, const char *name, bool enabled) + { + c->Message(Chat::White, "{}: {}", name, enabled ? "enabled" : "disabled"); + } +} + +void command_customfeatures(Client *c, const Seperator *) +{ + c->Message(Chat::White, "All Features rule gates:"); + SendFeatureStatus(c, "Multiclass", RuleB(CustomFeatures, MulticlassEnabled)); + SendFeatureStatus(c, "Achievements", RuleB(CustomFeatures, AchievementsEnabled)); + SendFeatureStatus(c, "AutoLoot", RuleB(CustomFeatures, AutoLootEnabled)); + SendFeatureStatus(c, "GearScore", RuleB(CustomFeatures, GearScoreEnabled)); + SendFeatureStatus(c, "Live Items", RuleB(CustomFeatures, LiveItemsEnabled)); + SendFeatureStatus(c, "Live Spells", RuleB(CustomFeatures, LiveSpellsEnabled)); + SendFeatureStatus(c, "Item Rarity", RuleB(CustomFeatures, ItemRarityEnabled)); + SendFeatureStatus(c, "HPFIX", RuleB(CustomFeatures, HpFixEnabled)); + SendFeatureStatus(c, "AI Dialogue", RuleB(CustomFeatures, AiDialogueEnabled)); + SendFeatureStatus(c, "Tradeskills", RuleB(CustomFeatures, TradeskillsEnabled)); + SendFeatureStatus(c, "Augs-in-Augs", RuleB(CustomFeatures, AugsInAugsEnabled)); + SendFeatureStatus(c, "Dynamic Quests", RuleB(CustomFeatures, DynamicQuestsEnabled)); + SendFeatureStatus(c, "MQ Interface", RuleB(CustomFeatures, MqInterfaceEnabled)); +} diff --git a/zone/gm_commands/hpfix.cpp b/zone/gm_commands/hpfix.cpp index b699b0c7aa..f1dda51094 100644 --- a/zone/gm_commands/hpfix.cpp +++ b/zone/gm_commands/hpfix.cpp @@ -15,6 +15,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#include "common/rulesys.h" #include "zone/client.h" namespace { @@ -54,6 +55,12 @@ namespace { void command_hpfix(Client* c, const Seperator* sep) { + if (!RuleB(CustomFeatures, HpFixEnabled)) { + c->SetNativeHpFixReady(false); + c->Message(Chat::White, "HPFIX is disabled on this server."); + return; + } + const uint16 arguments = sep->argnum; if ( diff --git a/zone/gm_commands/itemrarity.cpp b/zone/gm_commands/itemrarity.cpp index 9a3ebe8ad6..8f3b031d8a 100644 --- a/zone/gm_commands/itemrarity.cpp +++ b/zone/gm_commands/itemrarity.cpp @@ -16,6 +16,7 @@ along with this program. If not, see . */ #include "common/item_instance.h" +#include "common/rulesys.h" #include "common/seperator.h" #include "common/strings.h" #include "zone/client.h" @@ -110,6 +111,11 @@ namespace { void command_itemrarity(Client *c, const Seperator *sep) { + if (!RuleB(CustomFeatures, ItemRarityEnabled)) { + c->Message(Chat::White, "Item Rarity is disabled on this server."); + return; + } + const auto arguments = sep->argnum; if (!arguments || !strcasecmp(sep->arg[1], "help")) { SendUsage(c); diff --git a/zone/gm_commands/itemscore.cpp b/zone/gm_commands/itemscore.cpp index de467b7ea0..8c2d2b8357 100644 --- a/zone/gm_commands/itemscore.cpp +++ b/zone/gm_commands/itemscore.cpp @@ -17,6 +17,7 @@ */ #include "common/item_instance.h" #include "common/item_power.h" +#include "common/rulesys.h" #include "common/seperator.h" #include "common/strings.h" #include "zone/client.h" @@ -347,6 +348,11 @@ namespace { void command_itemscore(Client *c, const Seperator *sep) { + if (!RuleB(CustomFeatures, GearScoreEnabled)) { + c->Message(Chat::White, "GearScore is disabled on this server."); + return; + } + const auto action = Strings::ToLower(GetArg(sep, 1)); if (action.empty() || action == "help") { SendItemScoreUsage(c); diff --git a/zone/gm_commands/liveitem.cpp b/zone/gm_commands/liveitem.cpp index f614da2c48..efe5330905 100644 --- a/zone/gm_commands/liveitem.cpp +++ b/zone/gm_commands/liveitem.cpp @@ -35,6 +35,11 @@ #include namespace { + bool LiveItemsEnabled() + { + return RuleB(CustomFeatures, LiveItemsEnabled); + } + void SendLiveItemUsage(Client *c) { c->Message( @@ -428,6 +433,11 @@ namespace { void command_itemforge(Client *c, const Seperator *sep) { + if (!LiveItemsEnabled()) { + c->Message(Chat::White, "Live Items are disabled on this server."); + return; + } + const auto arguments = sep->argnum; if (!arguments || !strcasecmp(sep->arg[1], "help")) { SendItemForgeUsage(c); @@ -481,6 +491,11 @@ void command_itemforge(Client *c, const Seperator *sep) void command_liveitem(Client *c, const Seperator *sep) { + if (!LiveItemsEnabled()) { + c->Message(Chat::White, "Live Items are disabled on this server."); + return; + } + const auto arguments = sep->argnum; if (!arguments || !strcasecmp(sep->arg[1], "help")) { SendLiveItemUsage(c); diff --git a/zone/gm_commands/livespell.cpp b/zone/gm_commands/livespell.cpp index d57956a44a..36e95044c3 100644 --- a/zone/gm_commands/livespell.cpp +++ b/zone/gm_commands/livespell.cpp @@ -41,6 +41,11 @@ namespace { constexpr const char *LiveSpellNextScrollBucket = "live_spell.next_scroll_item_id"; bool gLiveSpellServerLoaded = false; + bool LiveSpellsEnabled() + { + return RuleB(CustomFeatures, LiveSpellsEnabled); + } + struct LiveSpellElement { const char *key; const char *label; @@ -789,6 +794,10 @@ namespace { namespace LiveSpellManager { void EnsureServerLoaded() { + if (!LiveSpellsEnabled()) { + return; + } + if (gLiveSpellServerLoaded) { return; } @@ -799,6 +808,13 @@ namespace LiveSpellManager { void SendClientSync(Client *c) { + if (!LiveSpellsEnabled()) { + if (c) { + c->Message(Chat::White, "Live Spells are disabled on this server."); + } + return; + } + EnsureServerLoaded(); int sent = 0; @@ -820,6 +836,11 @@ namespace LiveSpellManager { const std::string &custom_name ) { + if (!LiveSpellsEnabled()) { + c->Message(Chat::White, "Live Spells are disabled on this server."); + return false; + } + EnsureServerLoaded(); auto definition = BuildLiveSpellDefinition(c, element, target, range, damage, recast_time, custom_name); @@ -864,12 +885,21 @@ namespace LiveSpellManager { bool IsLiveSpell(const uint16 spell_id) { + if (!LiveSpellsEnabled()) { + return false; + } + return IsPersistedLiveSpellID(spell_id); } } void command_livespell(Client *c, const Seperator *sep) { + if (!LiveSpellsEnabled()) { + c->Message(Chat::White, "Live Spells are disabled on this server."); + return; + } + const auto arguments = sep->argnum; if (!arguments || !strcasecmp(sep->arg[1], "help")) { SendLiveSpellUsage(c); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 4b87377f3c..22b7b0bd46 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -21,6 +21,7 @@ #include "common/events/player_event_logs.h" #include "common/evolving_items.h" #include "common/item_power.h" +#include "common/rulesys.h" #include "common/repositories/character_corpse_items_repository.h" #include "common/strings.h" #include "zone/bot.h" @@ -1654,6 +1655,10 @@ bool Client::RefreshLiveItemTree(EQ::ItemInstance* inst) void Client::SendItemPowerTransport(const EQ::ItemInstance* inst) { + if (!RuleB(CustomFeatures, GearScoreEnabled)) { + return; + } + if (!inst || !inst->GetItem()) { return; } diff --git a/zone/item_rarity_manager.cpp b/zone/item_rarity_manager.cpp index a46aedef2e..ed2419637c 100644 --- a/zone/item_rarity_manager.cpp +++ b/zone/item_rarity_manager.cpp @@ -20,6 +20,7 @@ #include "common/eq_constants.h" #include "common/item_data.h" #include "common/item_instance.h" +#include "common/rulesys.h" #include "common/say_link.h" #include "common/strings.h" #include "zone/client.h" @@ -321,6 +322,10 @@ std::string ItemRarityManager::BuildDecoratedLink(const EQ::ItemInstance *inst, void ItemRarityManager::SendNativeRarity(Client *client, uint32 item_id, ItemRarity rarity) { + if (!RuleB(CustomFeatures, ItemRarityEnabled)) { + return; + } + if (!client || !item_id) { return; } @@ -340,6 +345,10 @@ void ItemRarityManager::SendNativeRarity(Client *client, uint32 item_id, ItemRar void ItemRarityManager::SendNativeRarityClear(Client *client, uint32 item_id) { + if (!RuleB(CustomFeatures, ItemRarityEnabled)) { + return; + } + if (!client || !item_id) { return; } @@ -358,6 +367,10 @@ void ItemRarityManager::SendNativeRarityClear(Client *client, uint32 item_id) void ItemRarityManager::SendRarityItemLink(Client *client, uint32 item_id) { + if (!RuleB(CustomFeatures, ItemRarityEnabled)) { + return; + } + if (!client) { return; } @@ -386,6 +399,10 @@ void ItemRarityManager::SendRarityItemLink(Client *client, uint32 item_id) void ItemRarityManager::SendLootedItemMessage(Client *client, const EQ::ItemInstance *inst, const std::string &) { + if (!RuleB(CustomFeatures, ItemRarityEnabled)) { + return; + } + if (!client || !inst || !inst->GetItem()) { return; } diff --git a/zone/multiclass_manager.cpp b/zone/multiclass_manager.cpp index 23bf111393..eaf364da0b 100644 --- a/zone/multiclass_manager.cpp +++ b/zone/multiclass_manager.cpp @@ -39,6 +39,24 @@ MulticlassManager multiclass_manager; namespace { +bool MulticlassEnabled() +{ + return RuleB(CustomFeatures, MulticlassEnabled); +} + +bool RequireMulticlassEnabled(Client *client) +{ + if (MulticlassEnabled()) { + return true; + } + + if (client) { + client->Message(Chat::White, "Multiclass is disabled on this server."); + } + + return false; +} + uint32 ToUInt(const char *value) { return value ? Strings::ToUnsignedInt(value) : 0; @@ -397,6 +415,10 @@ void MulticlassManager::HandleCommand(Client *client, const Seperator *sep) return; } + if (!RequireMulticlassEnabled(client)) { + return; + } + if (sep->argnum < 1) { SendStatus(client); return; @@ -516,6 +538,10 @@ void MulticlassManager::HandleNativeCommand(Client *client, const Seperator *sep return; } + if (!RequireMulticlassEnabled(client)) { + return; + } + if ( sep->argnum < 1 || !strcasecmp(sep->arg[1], "status") || @@ -603,7 +629,7 @@ void MulticlassManager::HandleNativeCommand(Client *client, const Seperator *sep bool MulticlassManager::EnsureProfile(Client *client) { - if (!client || !client->CharacterID() || !IsPlayerClass(client->GetClass()) || !SchemaAvailable()) { + if (!MulticlassEnabled() || !client || !client->CharacterID() || !IsPlayerClass(client->GetClass()) || !SchemaAvailable()) { return false; } @@ -638,7 +664,7 @@ bool MulticlassManager::EnsureProfile(Client *client) MulticlassManager::Profile MulticlassManager::LoadProfile(uint32 character_id) { Profile profile; - if (!character_id) { + if (!MulticlassEnabled() || !character_id) { return profile; } @@ -691,6 +717,7 @@ MulticlassManager::Profile MulticlassManager::LoadProfile(uint32 character_id) bool MulticlassManager::SetProfile(Client *client, uint8 class_slot_1, uint8 class_slot_2, uint8 class_slot_3, const std::string &source) { if ( + !MulticlassEnabled() || !client || !client->CharacterID() || !IsPlayerClass(class_slot_1) || @@ -728,7 +755,7 @@ bool MulticlassManager::SetProfile(Client *client, uint8 class_slot_1, uint8 cla bool MulticlassManager::HasClass(uint32 character_id, uint8 class_id) { - if (!IsPlayerClass(class_id)) { + if (!MulticlassEnabled() || !IsPlayerClass(class_id)) { return false; } @@ -742,12 +769,20 @@ bool MulticlassManager::HasClass(const Client *client, uint8 class_id) return false; } + if (!MulticlassEnabled()) { + return client->GetClass() == class_id; + } + const auto slots = GetClassSlots(client); return slots[0] == class_id || slots[1] == class_id || slots[2] == class_id; } bool MulticlassManager::HasMultiplePetProfile(uint32 character_id) { + if (!MulticlassEnabled()) { + return false; + } + const auto profile = LoadProfile(character_id); if (!profile.multiple_pets_enabled) { return false; @@ -766,7 +801,7 @@ bool MulticlassManager::HasMultiplePetProfile(uint32 character_id) uint8 MulticlassManager::GetPetRosterLimit(const Client *client) { - if (!client || !client->CharacterID()) { + if (!MulticlassEnabled() || !client || !client->CharacterID()) { return 1; } @@ -822,7 +857,7 @@ std::vector MulticlassManager::GetPetRoster(const Client *client) std::vector MulticlassManager::GetSecondaryPetRoster(Client *client) { std::vector pets; - if (!client || GetPetRosterLimit(client) <= 1) { + if (!MulticlassEnabled() || !client || GetPetRosterLimit(client) <= 1) { return pets; } @@ -841,6 +876,7 @@ std::vector MulticlassManager::GetSecondaryPetRoster(Client *client) bool MulticlassManager::IsPetRosterMember(const Client *client, Mob *pet) { if ( + !MulticlassEnabled() || !client || !pet || !client->CharacterID() || @@ -858,7 +894,7 @@ bool MulticlassManager::IsPetRosterMember(const Client *client, Mob *pet) bool MulticlassManager::CanCreateAdditionalPet(Client *client) { - if (!client) { + if (!MulticlassEnabled() || !client) { return false; } @@ -876,7 +912,7 @@ bool MulticlassManager::CanCreateAdditionalPet(Client *client) bool MulticlassManager::RegisterPet(Client *client, Mob *pet) { - if (!client || !pet || !client->CharacterID()) { + if (!MulticlassEnabled() || !client || !pet || !client->CharacterID()) { return false; } @@ -907,6 +943,11 @@ MulticlassManager::ClassSlots MulticlassManager::GetClassSlots(const Client *cli return slots; } + if (!MulticlassEnabled()) { + slots[0] = client->GetClass(); + return slots; + } + const auto profile = LoadProfile(client->CharacterID()); slots[0] = IsPlayerClass(profile.class_slot_1) ? profile.class_slot_1 : client->GetClass(); slots[1] = IsPlayerClass(profile.class_slot_2) ? profile.class_slot_2 : 0; @@ -1029,7 +1070,7 @@ uint8 MulticlassManager::GetBestSkillTrainLevel(const Client *client, EQ::skills uint16 MulticlassManager::SeedEligibleSkills(Client *client, bool notify) { - if (!client || !client->CharacterID() || !SchemaAvailable() || !EnsureProfile(client)) { + if (!MulticlassEnabled() || !client || !client->CharacterID() || !SchemaAvailable() || !EnsureProfile(client)) { return 0; } @@ -1088,7 +1129,7 @@ uint16 MulticlassManager::SeedEligibleSkills(Client *client, bool notify) void MulticlassManager::ApplyTrioBonuses(Client *client, StatBonuses *bonuses) { - if (!client || !bonuses || !client->CharacterID() || !SchemaAvailable()) { + if (!MulticlassEnabled() || !client || !bonuses || !client->CharacterID() || !SchemaAvailable()) { return; } @@ -2458,6 +2499,10 @@ bool MulticlassManager::HandleNativeDisciplineCommand(Client *client, const Sepe bool MulticlassManager::MelodySchemaAvailable() { + if (!MulticlassEnabled()) { + return false; + } + if (melody_schema_available_) { return true; } @@ -2614,7 +2659,7 @@ void MulticlassManager::RefreshAlternateAdvancementTable(Client *client) bool MulticlassManager::HasActiveBardMelody(Client *client) { - if (!client || !IsBard(client) || !MelodySchemaAvailable()) { + if (!MulticlassEnabled() || !client || !IsBard(client) || !MelodySchemaAvailable()) { return false; } @@ -2836,7 +2881,7 @@ void MulticlassManager::SendNativeBardMelody(Client *client, bool show_melody_wi void MulticlassManager::ProcessBardMelody(Client *client) { - if (!client || client->IsDead() || !IsBard(client) || !MelodySchemaAvailable()) { + if (!MulticlassEnabled() || !client || client->IsDead() || !IsBard(client) || !MelodySchemaAvailable()) { return; } @@ -2865,6 +2910,10 @@ void MulticlassManager::ProcessBardMelody(Client *client) bool MulticlassManager::SchemaAvailable() { + if (!MulticlassEnabled()) { + return false; + } + if (schema_available_) { return true; } From 1ff723fd8aeafb44561c1c1167834af7e84fa2cd Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Thu, 4 Jun 2026 22:28:28 -0700 Subject: [PATCH 143/194] Checkpoint all features patcher eqhost guard --- docs/features-all.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/features-all.md b/docs/features-all.md index 77ada1279b..82759e851e 100644 --- a/docs/features-all.md +++ b/docs/features-all.md @@ -163,9 +163,21 @@ value is the workspace install id from feature id, but check the registry instead of assuming it. For this checkout, the current install id is `all-features`. +Do not let all-features patcher generation fall back to local login defaults. +External tester `eqhost.txt` must stay pointed at the public testbed login endpoint: + +```ini +[LoginServer] +Host=47.181.1.223:5999 +``` + +Do not change generated `eqhost.txt` behavior or the public login host unless the user +explicitly asks for an eqhost/login-host change. When manually regenerating this feed, +pass the public login host and port explicitly. + ```powershell cd D:\Codex\Apps\EQEmu-feature-patcher\features\patcher\eqemupatcher\service -.\New-WorkspacePatcherDeployment.ps1 -Project all-features -BaseUrl http://:8091/patcher/ +.\New-WorkspacePatcherDeployment.ps1 -Project all-features -BaseUrl http://47.181.1.223:8091/patcher/ -LoginHost 47.181.1.223 -LoginPort 5999 .\Test-WorkspacePatcherDeployment.ps1 -Project all-features -BaseUrl http://:8091/patcher/ ``` From 906ca3bb24c2768f86f67aa3109767e815edc7aa Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Thu, 4 Jun 2026 23:07:30 -0700 Subject: [PATCH 144/194] Checkpoint all features patcher build version --- .../eq-core-dll/bin/dinput8.dll | Bin 1694208 -> 1694720 bytes .../eq-core-dll/src/core_autoloot_native.h | 22 ++++++++++++------ features/all-features/patcher.yml | 2 ++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/client_files/native_autoloot/eq-core-dll/bin/dinput8.dll b/client_files/native_autoloot/eq-core-dll/bin/dinput8.dll index 86d6ee751b71a86062a5a428ae9ea2308044e99c..00bde75ed67264cf39d8c16b088a3782de41e9af 100644 GIT binary patch delta 183313 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 delta 182879 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®F= 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 F{|7A$mCOJD diff --git a/client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h b/client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h index 377be3abbf..f396409129 100644 --- a/client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h +++ b/client_files/native_autoloot/eq-core-dll/src/core_autoloot_native.h @@ -824,18 +824,26 @@ static std::string NativeMulticlassInventoryClassText() return ""; } - if (!gNativeMulticlassState.profile_name.empty() && gNativeMulticlassState.profile_name != "Unchosen Trio") { - return gNativeMulticlassState.profile_name; - } - if ( NativeMulticlassIsPlayerClass(gNativeMulticlassState.class1) && NativeMulticlassIsPlayerClass(gNativeMulticlassState.class2) && NativeMulticlassIsPlayerClass(gNativeMulticlassState.class3) ) { - return std::string(NativeMulticlassClassName(gNativeMulticlassState.class1)) + " / " + - NativeMulticlassClassName(gNativeMulticlassState.class2) + " / " + - NativeMulticlassClassName(gNativeMulticlassState.class3); + const std::string class1 = gNativeMulticlassState.class1_name.empty() ? + NativeMulticlassClassName(gNativeMulticlassState.class1) : + gNativeMulticlassState.class1_name; + const std::string class2 = gNativeMulticlassState.class2_name.empty() ? + NativeMulticlassClassName(gNativeMulticlassState.class2) : + gNativeMulticlassState.class2_name; + const std::string class3 = gNativeMulticlassState.class3_name.empty() ? + NativeMulticlassClassName(gNativeMulticlassState.class3) : + gNativeMulticlassState.class3_name; + + return class1 + "\n" + class2 + "\n" + class3; + } + + if (!gNativeMulticlassState.profile_name.empty() && gNativeMulticlassState.profile_name != "Unchosen Trio") { + return gNativeMulticlassState.profile_name; } return "Multiclass Trio"; diff --git a/features/all-features/patcher.yml b/features/all-features/patcher.yml index b56013074e..6a65e14760 100644 --- a/features/all-features/patcher.yml +++ b/features/all-features/patcher.yml @@ -1,6 +1,8 @@ version: 1 id: all-features label: All Features +patchVersion: 'Build 1' +autoIncrementPatchVersion: true client: rof files: - source: client_files/native_autoloot/eq-core-dll/bin/dinput8.dll From 7263f3596e92c462e8aacfa0442da4d20ac0b11b Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Thu, 4 Jun 2026 23:12:50 -0700 Subject: [PATCH 145/194] Checkpoint all features patcher build 2 --- features/all-features/patcher.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/all-features/patcher.yml b/features/all-features/patcher.yml index 6a65e14760..013f6518e0 100644 --- a/features/all-features/patcher.yml +++ b/features/all-features/patcher.yml @@ -1,7 +1,7 @@ version: 1 id: all-features label: All Features -patchVersion: 'Build 1' +patchVersion: 'Build 2' autoIncrementPatchVersion: true client: rof files: From 899539923dd0ed9ef0a00e6e33cded8b62b970c3 Mon Sep 17 00:00:00 2001 From: Barathos <169070864+Barathos@users.noreply.github.com> Date: Fri, 5 Jun 2026 00:09:08 -0700 Subject: [PATCH 146/194] Checkpoint all features achievements handoff --- .../eq-core-dll/bin/dinput8.dll | Bin 1694720 -> 1701376 bytes .../eq-core-dll/src/core_autoloot_native.h | 86 +++ .../ui/Achievement_TitleBorders.tga | Bin 0 -> 65580 bytes .../ui/Achievement_Titlebar.tga | Bin 0 -> 131116 bytes .../ui/Achievement_account_unlock_color.tga | Bin 0 -> 146 bytes .../ui/Achievement_achieved_color.tga | Bin 0 -> 4140 bytes .../ui/Achievement_hunter_collect_base.tga | Bin 0 -> 262188 bytes .../Achievement_hunter_collect_mouseover.tga | Bin 0 -> 262188 bytes .../Achievement_hunter_collect_selected.tga | Bin 0 -> 262188 bytes .../ui/Achievement_lock_color.tga | Bin 0 -> 4140 bytes .../ui/Achievement_subcat_base.tga | Bin 0 -> 262188 bytes .../ui/Achievement_subcat_base01.tga | Bin 0 -> 262188 bytes .../ui/Achievement_subcat_mouseover.tga | Bin 0 -> 262188 bytes .../ui/Achievement_subcat_mouseover01.tga | Bin 0 -> 262188 bytes .../ui/Achievement_subcat_selected.tga | Bin 0 -> 262188 bytes .../ui/Achievement_subcat_selected01.tga | Bin 0 -> 262188 bytes .../ui/Achievement_unlock_color.tga | Bin 0 -> 4140 bytes .../ui/EQUI_NativeAchievementWnd.xml | 296 +++++++-- features/all-features/patcher.yml | 32 +- zone/achievement_manager.cpp | 615 +++++++++++++++++- zone/achievement_manager.h | 21 + 21 files changed, 1008 insertions(+), 42 deletions(-) create mode 100644 client_files/native_autoloot/ui/Achievement_TitleBorders.tga create mode 100644 client_files/native_autoloot/ui/Achievement_Titlebar.tga create mode 100644 client_files/native_autoloot/ui/Achievement_account_unlock_color.tga create mode 100644 client_files/native_autoloot/ui/Achievement_achieved_color.tga create mode 100644 client_files/native_autoloot/ui/Achievement_hunter_collect_base.tga create mode 100644 client_files/native_autoloot/ui/Achievement_hunter_collect_mouseover.tga create mode 100644 client_files/native_autoloot/ui/Achievement_hunter_collect_selected.tga create mode 100644 client_files/native_autoloot/ui/Achievement_lock_color.tga create mode 100644 client_files/native_autoloot/ui/Achievement_subcat_base.tga create mode 100644 client_files/native_autoloot/ui/Achievement_subcat_base01.tga create mode 100644 client_files/native_autoloot/ui/Achievement_subcat_mouseover.tga create mode 100644 client_files/native_autoloot/ui/Achievement_subcat_mouseover01.tga create mode 100644 client_files/native_autoloot/ui/Achievement_subcat_selected.tga create mode 100644 client_files/native_autoloot/ui/Achievement_subcat_selected01.tga create mode 100644 client_files/native_autoloot/ui/Achievement_unlock_color.tga diff --git a/client_files/native_autoloot/eq-core-dll/bin/dinput8.dll b/client_files/native_autoloot/eq-core-dll/bin/dinput8.dll index 00bde75ed67264cf39d8c16b088a3782de41e9af..5ba5ef599f7f705599a1fb9c30fd76eb8c10f5f8 100644 GIT binary patch delta 547370 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

    eC$Tt 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 z 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 gNativeAchievementCategories; static std::vector gNativeAchievementRows; static std::vector gNativeAchievementObjectives; +static std::vector gNativeAchievementRewards; static int gNativeAchievementSelectedCategory = 0; static int gNativeAchievementSelectedAchievement = 0; static int gNativeAchievementCompleted = 0; @@ -2620,6 +2635,7 @@ static bool gNativeAchievementLoading = false; static bool gNativeAchievementCategoriesDirty = true; static bool gNativeAchievementRowsDirty = true; static bool gNativeAchievementObjectivesDirty = true; +static bool gNativeAchievementRewardsDirty = true; static std::string gNativeAchievementDetailTitle = "Select an achievement"; static std::string gNativeAchievementDetailDescription = ""; @@ -4766,6 +4782,40 @@ void NativeAchievementWnd::RefreshObjectiveList() gNativeAchievementObjectivesDirty = false; } +void NativeAchievementWnd::RefreshRewardList() +{ + if (!RewardList) { + return; + } + + RewardList->DeleteAll(); + if (gNativeAchievementRewards.empty()) { + CXStr dash("-"); + const int row = RewardList->AddString(dash, 0xFFB0B0B0, 0, nullptr, nullptr); + CXStr empty("No rewards listed."); + RewardList->SetItemText(row, 1, &empty); + gNativeAchievementRewardsDirty = false; + return; + } + + for (const NativeAchievementRewardRow& reward : gNativeAchievementRewards) { + CXStr state(reward.auto_claim ? "Auto" : "Claim"); + const int row = RewardList->AddString(state, reward.auto_claim ? 0xFF66FF66 : 0xFFFFFF80, (uint32_t)reward.definition_id, nullptr, nullptr); + + std::string reward_text = reward.name.empty() ? reward.type : reward.name; + if (!reward.tier.empty()) { + reward_text += " ["; + reward_text += reward.tier; + reward_text += "]"; + } + + CXStr name(reward_text.c_str()); + RewardList->SetItemText(row, 1, &name); + } + + gNativeAchievementRewardsDirty = false; +} + void NativeAchievementWnd::SelectCategoryListRow() { if (!CategoryList || SelectedCategoryID <= 0) { @@ -4829,6 +4879,10 @@ void NativeAchievementWnd::RefreshRows() if (gNativeAchievementObjectivesDirty) { RefreshObjectiveList(); } + + if (gNativeAchievementRewardsDirty) { + RefreshRewardList(); + } } NativeAchievementCategoryRow* NativeAchievementWnd::GetSelectedCategory() @@ -5967,11 +6021,13 @@ static bool NativeAchievementParseTransport(const char* message) gNativeAchievementCategories.clear(); gNativeAchievementRows.clear(); gNativeAchievementObjectives.clear(); + gNativeAchievementRewards.clear(); gNativeAchievementSelectedCategory = 0; gNativeAchievementSelectedAchievement = 0; gNativeAchievementCategoriesDirty = true; gNativeAchievementRowsDirty = true; gNativeAchievementObjectivesDirty = true; + gNativeAchievementRewardsDirty = true; gNativeAchievementDetailTitle = "Select an achievement"; gNativeAchievementDetailDescription.clear(); if (gNativeAchievementWnd) { @@ -5984,9 +6040,11 @@ static bool NativeAchievementParseTransport(const char* message) gNativeAchievementLoading = true; gNativeAchievementRows.clear(); gNativeAchievementObjectives.clear(); + gNativeAchievementRewards.clear(); gNativeAchievementSelectedAchievement = 0; gNativeAchievementRowsDirty = true; gNativeAchievementObjectivesDirty = true; + gNativeAchievementRewardsDirty = true; gNativeAchievementDetailTitle = "Select an achievement"; gNativeAchievementDetailDescription.clear(); if (gNativeAchievementWnd) { @@ -6005,6 +6063,12 @@ static bool NativeAchievementParseTransport(const char* message) return true; } + if (NativeStartsWith(message, "ACH|rewards|clear")) { + gNativeAchievementRewards.clear(); + gNativeAchievementRewardsDirty = true; + return true; + } + if (NativeStartsWith(message, "ACH|status|")) { const std::string payload(message + strlen("ACH|status|")); gNativeAchievementCompleted = NativeToInt(NativeGetPairValue(payload, "completed")); @@ -6078,6 +6142,8 @@ static bool NativeAchievementParseTransport(const char* message) gNativeAchievementDetailDescription = description; gNativeAchievementObjectives.clear(); gNativeAchievementObjectivesDirty = true; + gNativeAchievementRewards.clear(); + gNativeAchievementRewardsDirty = true; if (gNativeAchievementWnd && !gNativeAchievementLoading) { gNativeAchievementWnd->RefreshRows(); } @@ -6102,6 +6168,26 @@ static bool NativeAchievementParseTransport(const char* message) return true; } + if (NativeStartsWith(message, "ACH|reward|")) { + const std::string payload(message + strlen("ACH|reward|")); + NativeAchievementRewardRow row; + row.definition_id = static_cast(_strtoui64(NativeGetPairValue(payload, "definition").c_str(), nullptr, 10)); + row.type = NativeGetPairValue(payload, "type"); + row.reward_id = NativeToInt(NativeGetPairValue(payload, "id")); + row.amount = NativeToInt(NativeGetPairValue(payload, "amount")); + row.auto_claim = NativeToBool(NativeGetPairValue(payload, "auto")); + row.tier = NativeGetPairValue(payload, "tier"); + row.name = NativeGetPairValue(payload, "name"); + if (row.definition_id > 0 || !row.name.empty()) { + gNativeAchievementRewards.push_back(row); + gNativeAchievementRewardsDirty = true; + } + if (gNativeAchievementWnd && !gNativeAchievementLoading) { + gNativeAchievementWnd->RefreshRows(); + } + return true; + } + if (NativeStartsWith(message, "ACH|window|show")) { gNativeAchievementLoading = false; NativeAchievementEnsureWindow(true); diff --git a/client_files/native_autoloot/ui/Achievement_TitleBorders.tga b/client_files/native_autoloot/ui/Achievement_TitleBorders.tga new file mode 100644 index 0000000000000000000000000000000000000000..b0091a2f0544e9e27ae575c4d5a8a1ad7b9aa1ff GIT binary patch literal 65580 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 AuK)l5 literal 0 HcmV?d00001 diff --git a/client_files/native_autoloot/ui/Achievement_account_unlock_color.tga b/client_files/native_autoloot/ui/Achievement_account_unlock_color.tga new file mode 100644 index 0000000000000000000000000000000000000000..b1c65d35417a4bc961f2b01b1a79b2aeb0e79bdc GIT binary patch literal 146 YcmZQz;9`IQ1qKBM35NOn{QLun0lT~z;{X5v literal 0 HcmV?d00001 diff --git a/client_files/native_autoloot/ui/Achievement_achieved_color.tga b/client_files/native_autoloot/ui/Achievement_achieved_color.tga new file mode 100644 index 0000000000000000000000000000000000000000..b6b091390dbfe02df00718994329f10da4767b43 GIT binary patch literal 4140 zcmZQzU}As)1qLAG@D*bJKZ-}gU^ESkrh(BkFq#HN)4*sN7)=ACX<#%BjHZFnG%%V5 fM$^FXP6M#ffRLb2*D%juPk%q%2sck3S3L#*QY4w7 literal 0 HcmV?d00001 diff --git a/client_files/native_autoloot/ui/Achievement_hunter_collect_base.tga b/client_files/native_autoloot/ui/Achievement_hunter_collect_base.tga new file mode 100644 index 0000000000000000000000000000000000000000..4537de226c2da1e60ae64fabfdb68a08b81eded2 GIT binary patch literal 262188 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 literal 0 HcmV?d00001 diff --git a/client_files/native_autoloot/ui/Achievement_hunter_collect_mouseover.tga b/client_files/native_autoloot/ui/Achievement_hunter_collect_mouseover.tga new file mode 100644 index 0000000000000000000000000000000000000000..94d0c02295029b2c9b2d5082b0556c9ad2b3c4a5 GIT binary patch literal 262188 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 z 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 literal 0 HcmV?d00001 diff --git a/client_files/native_autoloot/ui/Achievement_subcat_base01.tga b/client_files/native_autoloot/ui/Achievement_subcat_base01.tga new file mode 100644 index 0000000000000000000000000000000000000000..780c316d7fbe0191dfb1b2e03009034c071f7fe8 GIT binary patch literal 262188 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�%r_WrpAe7@AXMwbF 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 Keaw0N_WuD#I445@ delta 543025 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